| /* | |
| * Copyright 2014 Google Inc. | |
| * | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| */ | |
| #include "include/core/SkTypes.h" | |
| #if defined(SK_BUILD_FOR_WIN) | |
| #include "include/core/SkString.h" | |
| #include "include/private/base/SkOnce.h" | |
| #include "src/utils/win/SkDWrite.h" | |
| #include "src/utils/win/SkHRESULT.h" | |
| #include <dwrite.h> | |
| #if defined(__clang__) | |
| #pragma clang diagnostic push | |
| #pragma clang diagnostic ignored "-Wcast-function-type" | |
| #endif | |
| static IDWriteFactory* gDWriteFactory = nullptr; | |
| static void release_dwrite_factory() { | |
| if (gDWriteFactory) { | |
| gDWriteFactory->Release(); | |
| } | |
| } | |
| static void create_dwrite_factory(IDWriteFactory** factory) { | |
| using DWriteCreateFactoryProc = decltype(DWriteCreateFactory)*; | |
| DWriteCreateFactoryProc dWriteCreateFactoryProc; | |
| dWriteCreateFactoryProc = reinterpret_cast<DWriteCreateFactoryProc>(GetProcAddress( | |
| LoadLibraryExW(L"DWriteCore.dll", NULL, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS), | |
| "DWriteCoreCreateFactory")); | |
| if (!dWriteCreateFactoryProc) { | |
| dWriteCreateFactoryProc = reinterpret_cast<DWriteCreateFactoryProc>(GetProcAddress( | |
| LoadLibraryExW(L"dwrite.dll", NULL, LOAD_LIBRARY_SEARCH_DEFAULT_DIRS), | |
| "DWriteCreateFactory")); | |
| } | |
| if (!dWriteCreateFactoryProc) { | |
| HRESULT hr = HRESULT_FROM_WIN32(GetLastError()); | |
| if (!IS_ERROR(hr)) { | |
| hr = ERROR_PROC_NOT_FOUND; | |
| } | |
| HRVM(hr, "Could not get DWriteCreateFactory proc."); | |
| } | |
| HRVM(dWriteCreateFactoryProc(DWRITE_FACTORY_TYPE_SHARED, | |
| __uuidof(IDWriteFactory), | |
| reinterpret_cast<IUnknown**>(factory)), | |
| "Could not create DirectWrite factory."); | |
| atexit(release_dwrite_factory); | |
| } | |
| IDWriteFactory* sk_get_dwrite_factory() { | |
| static SkOnce once; | |
| once(create_dwrite_factory, &gDWriteFactory); | |
| return gDWriteFactory; | |
| } | |
| //////////////////////////////////////////////////////////////////////////////// | |
| // String conversion | |
| /** Converts a utf8 string to a WCHAR string. */ | |
| HRESULT sk_cstring_to_wchar(const char* skname, SkSMallocWCHAR* name) { | |
| int wlen = MultiByteToWideChar(CP_UTF8, 0, skname, -1, nullptr, 0); | |
| if (0 == wlen) { | |
| HRM(HRESULT_FROM_WIN32(GetLastError()), | |
| "Could not get length for wchar to utf-8 conversion."); | |
| } | |
| name->reset(wlen); | |
| wlen = MultiByteToWideChar(CP_UTF8, 0, skname, -1, name->get(), wlen); | |
| if (0 == wlen) { | |
| HRM(HRESULT_FROM_WIN32(GetLastError()), "Could not convert wchar to utf-8."); | |
| } | |
| return S_OK; | |
| } | |
| /** Converts a WCHAR string to a utf8 string. */ | |
| HRESULT sk_wchar_to_skstring(WCHAR* name, int nameLen, SkString* skname) { | |
| int len = WideCharToMultiByte(CP_UTF8, 0, name, nameLen, nullptr, 0, nullptr, nullptr); | |
| if (0 == len) { | |
| if (nameLen <= 0) { | |
| skname->reset(); | |
| return S_OK; | |
| } | |
| HRM(HRESULT_FROM_WIN32(GetLastError()), | |
| "Could not get length for utf-8 to wchar conversion."); | |
| } | |
| skname->resize(len); | |
| len = WideCharToMultiByte(CP_UTF8, 0, name, nameLen, skname->data(), len, nullptr, nullptr); | |
| if (0 == len) { | |
| HRM(HRESULT_FROM_WIN32(GetLastError()), "Could not convert utf-8 to wchar."); | |
| } | |
| return S_OK; | |
| } | |
| //////////////////////////////////////////////////////////////////////////////// | |
| // Locale | |
| HRESULT sk_get_locale_string(IDWriteLocalizedStrings* names, const WCHAR* preferedLocale, | |
| SkString* skname) { | |
| UINT32 nameIndex = 0; | |
| if (preferedLocale) { | |
| // Ignore any errors and continue with index 0 if there is a problem. | |
| BOOL nameExists = FALSE; | |
| (void)names->FindLocaleName(preferedLocale, &nameIndex, &nameExists); | |
| if (!nameExists) { | |
| nameIndex = 0; | |
| } | |
| } | |
| UINT32 nameLen; | |
| HRM(names->GetStringLength(nameIndex, &nameLen), "Could not get name length."); | |
| SkSMallocWCHAR name(nameLen + 1); | |
| HRM(names->GetString(nameIndex, name.get(), nameLen + 1), "Could not get string."); | |
| HR(sk_wchar_to_skstring(name.get(), nameLen, skname)); | |
| return S_OK; | |
| } | |
| HRESULT SkGetGetUserDefaultLocaleNameProc(SkGetUserDefaultLocaleNameProc* proc) { | |
| *proc = reinterpret_cast<SkGetUserDefaultLocaleNameProc>( | |
| GetProcAddress(LoadLibraryExW(L"Kernel32.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32), | |
| "GetUserDefaultLocaleName")); | |
| if (!*proc) { | |
| HRESULT hr = HRESULT_FROM_WIN32(GetLastError()); | |
| if (!IS_ERROR(hr)) { | |
| hr = ERROR_PROC_NOT_FOUND; | |
| } | |
| return hr; | |
| } | |
| return S_OK; | |
| } | |
| #if defined(__clang__) | |
| #pragma clang diagnostic pop | |
| #endif | |
| #endif//defined(SK_BUILD_FOR_WIN) |