1 /* 2 * Copyright 2014 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 #include "SkTypes.h" 8 #if defined(SK_BUILD_FOR_WIN) 9 10 #include "SkDWrite.h" 11 #include "SkHRESULT.h" 12 #include "SkOnce.h" 13 #include "SkString.h" 14 15 #include <dwrite.h> 16 17 static IDWriteFactory* gDWriteFactory = nullptr; 18 19 static void release_dwrite_factory() { 20 if (gDWriteFactory) { 21 gDWriteFactory->Release(); 22 } 23 } 24 25 static void create_dwrite_factory(IDWriteFactory** factory) { 26 typedef decltype(DWriteCreateFactory)* DWriteCreateFactoryProc; 27 DWriteCreateFactoryProc dWriteCreateFactoryProc = reinterpret_cast<DWriteCreateFactoryProc>( 28 GetProcAddress(LoadLibraryW(L"dwrite.dll"), "DWriteCreateFactory")); 29 30 if (!dWriteCreateFactoryProc) { 31 HRESULT hr = HRESULT_FROM_WIN32(GetLastError()); 32 if (!IS_ERROR(hr)) { 33 hr = ERROR_PROC_NOT_FOUND; 34 } 35 HRVM(hr, "Could not get DWriteCreateFactory proc."); 36 } 37 38 HRVM(dWriteCreateFactoryProc(DWRITE_FACTORY_TYPE_SHARED, 39 __uuidof(IDWriteFactory), 40 reinterpret_cast<IUnknown**>(factory)), 41 "Could not create DirectWrite factory."); 42 atexit(release_dwrite_factory); 43 } 44 45 46 IDWriteFactory* sk_get_dwrite_factory() { 47 static SkOnce once; 48 once(create_dwrite_factory, &gDWriteFactory); 49 return gDWriteFactory; 50 } 51 52 //////////////////////////////////////////////////////////////////////////////// 53 // String conversion 54 55 /** Converts a utf8 string to a WCHAR string. */ 56 HRESULT sk_cstring_to_wchar(const char* skname, SkSMallocWCHAR* name) { 57 int wlen = MultiByteToWideChar(CP_UTF8, 0, skname, -1, nullptr, 0); 58 if (0 == wlen) { 59 HRM(HRESULT_FROM_WIN32(GetLastError()), 60 "Could not get length for wchar to utf-8 conversion."); 61 } 62 name->reset(wlen); 63 wlen = MultiByteToWideChar(CP_UTF8, 0, skname, -1, name->get(), wlen); 64 if (0 == wlen) { 65 HRM(HRESULT_FROM_WIN32(GetLastError()), "Could not convert wchar to utf-8."); 66 } 67 return S_OK; 68 } 69 70 /** Converts a WCHAR string to a utf8 string. */ 71 HRESULT sk_wchar_to_skstring(WCHAR* name, int nameLen, SkString* skname) { 72 int len = WideCharToMultiByte(CP_UTF8, 0, name, nameLen, nullptr, 0, nullptr, nullptr); 73 if (0 == len) { 74 if (nameLen <= 0) { 75 skname->reset(); 76 return S_OK; 77 } 78 HRM(HRESULT_FROM_WIN32(GetLastError()), 79 "Could not get length for utf-8 to wchar conversion."); 80 } 81 skname->resize(len); 82 83 len = WideCharToMultiByte(CP_UTF8, 0, name, nameLen, skname->writable_str(), len, nullptr, nullptr); 84 if (0 == len) { 85 HRM(HRESULT_FROM_WIN32(GetLastError()), "Could not convert utf-8 to wchar."); 86 } 87 return S_OK; 88 } 89 90 //////////////////////////////////////////////////////////////////////////////// 91 // Locale 92 93 HRESULT sk_get_locale_string(IDWriteLocalizedStrings* names, const WCHAR* preferedLocale, 94 SkString* skname) { 95 UINT32 nameIndex = 0; 96 if (preferedLocale) { 97 // Ignore any errors and continue with index 0 if there is a problem. 98 BOOL nameExists = FALSE; 99 (void)names->FindLocaleName(preferedLocale, &nameIndex, &nameExists); 100 if (!nameExists) { 101 nameIndex = 0; 102 } 103 } 104 105 UINT32 nameLen; 106 HRM(names->GetStringLength(nameIndex, &nameLen), "Could not get name length."); 107 108 SkSMallocWCHAR name(nameLen + 1); 109 HRM(names->GetString(nameIndex, name.get(), nameLen + 1), "Could not get string."); 110 111 HR(sk_wchar_to_skstring(name.get(), nameLen, skname)); 112 return S_OK; 113 } 114 115 HRESULT SkGetGetUserDefaultLocaleNameProc(SkGetUserDefaultLocaleNameProc* proc) { 116 *proc = reinterpret_cast<SkGetUserDefaultLocaleNameProc>( 117 GetProcAddress(LoadLibraryW(L"Kernel32.dll"), "GetUserDefaultLocaleName") 118 ); 119 if (!*proc) { 120 HRESULT hr = HRESULT_FROM_WIN32(GetLastError()); 121 if (!IS_ERROR(hr)) { 122 hr = ERROR_PROC_NOT_FOUND; 123 } 124 return hr; 125 } 126 return S_OK; 127 } 128 129 #endif//defined(SK_BUILD_FOR_WIN) 130