| 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;
|
| +}
|
|
|