Index: src/utils/win/SkDWrite.cpp |
=================================================================== |
--- src/utils/win/SkDWrite.cpp (revision 0) |
+++ src/utils/win/SkDWrite.cpp (working copy) |
@@ -0,0 +1,128 @@ |
+/* |
+ * 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 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."); |
+} |
+ |
+static void release_dwrite_factory() { |
+ if (gDWriteFactory) { |
+ gDWriteFactory->Release(); |
+ } |
+} |
+ |
+IDWriteFactory* sk_get_dwrite_factory() { |
+ SK_DECLARE_STATIC_ONCE(once); |
+ SkOnce(&once, create_dwrite_factory, &gDWriteFactory, release_dwrite_factory); |
+ |
+ 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; |
+} |