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 
release_dwrite_factory()17 static void release_dwrite_factory() {
18     if (gDWriteFactory) {
19         gDWriteFactory->Release();
20     }
21 }
22 
create_dwrite_factory(IDWriteFactory ** factory)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);
sk_get_dwrite_factory()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. */
sk_cstring_to_wchar(const char * skname,SkSMallocWCHAR * name)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. */
sk_wchar_to_skstring(WCHAR * name,int nameLen,SkString * skname)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 
sk_get_locale_string(IDWriteLocalizedStrings * names,const WCHAR * preferedLocale,SkString * skname)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 
SkGetGetUserDefaultLocaleNameProc(SkGetUserDefaultLocaleNameProc * proc)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