| /* | |
| * 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 "SkDWrite.h" | |
| #include "SkHRESULT.h" | |
| #include "SkOnce.h" | |
| #include "SkString.h" | |
| #include <dwrite.h> | |
| static IDWriteFactory* gDWriteFactory = NULL; | |
| static void release_dwrite_factory() { | |
| if (gDWriteFactory) { | |
| gDWriteFactory->Release(); | |
| } | |
| } | |
| static void create_dwrite_factory(IDWriteFactory** factory) { | |
| typedef decltype(DWriteCreateFactory)* DWriteCreateFactoryProc; | |
| DWriteCreateFactoryProc dWriteCreateFactoryProc = reinterpret_cast<DWriteCreateFactoryProc>( | |
| GetProcAddress(LoadLibraryW(L"dwrite.dll"), "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() { | |
| SK_DECLARE_STATIC_ONCE(once); | |
| SkOnce(&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, NULL, 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, SkString* skname) { | |
| int len = WideCharToMultiByte(CP_UTF8, 0, name, -1, NULL, 0, NULL, NULL); | |
| if (0 == len) { | |
| HRM(HRESULT_FROM_WIN32(GetLastError()), | |
| "Could not get length for utf-8 to wchar conversion."); | |
| } | |
| skname->resize(len - 1); | |
| // TODO: remove after https://code.google.com/p/skia/issues/detail?id=1989 is fixed. | |
| // If we resize to 0 then the skname points to gEmptyRec (the unique empty SkString::Rec). | |
| // gEmptyRec is static const and on Windows this means the value is in a read only page. | |
| // Writing to it in the following call to WideCharToMultiByte will cause an access violation. | |
| if (1 == len) { | |
| return S_OK; | |
| } | |
| len = WideCharToMultiByte(CP_UTF8, 0, name, -1, skname->writable_str(), len, NULL, NULL); | |
| if (0 == len) { | |
| HRM(HRESULT_FROM_WIN32(GetLastError()), "Could not convert utf-8 to wchar."); | |
| } | |
| return S_OK; | |
| } | |
| //////////////////////////////////////////////////////////////////////////////// | |
| // Locale | |
| void 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; | |
| names->FindLocaleName(preferedLocale, &nameIndex, &nameExists); | |
| if (!nameExists) { | |
| nameIndex = 0; | |
| } | |
| } | |
| UINT32 nameLength; | |
| HRVM(names->GetStringLength(nameIndex, &nameLength), "Could not get name length."); | |
| nameLength += 1; | |
| SkSMallocWCHAR name(nameLength); | |
| HRVM(names->GetString(nameIndex, name.get(), nameLength), "Could not get string."); | |
| HRV(sk_wchar_to_skstring(name.get(), skname)); | |
| } | |
| HRESULT SkGetGetUserDefaultLocaleNameProc(SkGetUserDefaultLocaleNameProc* proc) { | |
| *proc = reinterpret_cast<SkGetUserDefaultLocaleNameProc>( | |
| GetProcAddress(LoadLibraryW(L"Kernel32.dll"), "GetUserDefaultLocaleName") | |
| ); | |
| if (!*proc) { | |
| HRESULT hr = HRESULT_FROM_WIN32(GetLastError()); | |
| if (!IS_ERROR(hr)) { | |
| hr = ERROR_PROC_NOT_FOUND; | |
| } | |
| return hr; | |
| } | |
| return S_OK; | |
| } |