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