diff options
Diffstat (limited to 'chromium/third_party/skia/src/utils/win/SkDWrite.cpp')
-rw-r--r-- | chromium/third_party/skia/src/utils/win/SkDWrite.cpp | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/chromium/third_party/skia/src/utils/win/SkDWrite.cpp b/chromium/third_party/skia/src/utils/win/SkDWrite.cpp new file mode 100644 index 00000000000..87826b5194e --- /dev/null +++ b/chromium/third_party/skia/src/utils/win/SkDWrite.cpp @@ -0,0 +1,130 @@ +/* + * 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; +} |