SkDWrite.cpp revision 72cf4fcafa54cfa04c5ec7cb8eaa3acb144712dd
172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com/* 272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com * Copyright 2014 Google Inc. 372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com * 472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com * Use of this source code is governed by a BSD-style license that can be 572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com * found in the LICENSE file. 672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com */ 772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com 872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com#include "SkDWrite.h" 972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com#include "SkHRESULT.h" 1072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com#include "SkOnce.h" 1172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com#include "SkString.h" 1272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com 1372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com#include <dwrite.h> 1472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com 1572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.comstatic IDWriteFactory* gDWriteFactory = NULL; 1672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com 1772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.comstatic void create_dwrite_factory(IDWriteFactory** factory) { 1872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com typedef decltype(DWriteCreateFactory)* DWriteCreateFactoryProc; 1972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com DWriteCreateFactoryProc dWriteCreateFactoryProc = reinterpret_cast<DWriteCreateFactoryProc>( 2072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com GetProcAddress(LoadLibraryW(L"dwrite.dll"), "DWriteCreateFactory")); 2172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com 2272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com if (!dWriteCreateFactoryProc) { 2372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com HRESULT hr = HRESULT_FROM_WIN32(GetLastError()); 2472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com if (!IS_ERROR(hr)) { 2572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com hr = ERROR_PROC_NOT_FOUND; 2672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com } 2772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com HRVM(hr, "Could not get DWriteCreateFactory proc."); 2872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com } 2972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com 3072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com HRVM(dWriteCreateFactoryProc(DWRITE_FACTORY_TYPE_SHARED, 3172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com __uuidof(IDWriteFactory), 3272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com reinterpret_cast<IUnknown**>(factory)), 3372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com "Could not create DirectWrite factory."); 3472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com} 3572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com 3672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.comstatic void release_dwrite_factory() { 3772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com if (gDWriteFactory) { 3872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com gDWriteFactory->Release(); 3972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com } 4072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com} 4172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com 4272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.comIDWriteFactory* sk_get_dwrite_factory() { 4372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com SK_DECLARE_STATIC_ONCE(once); 4472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com SkOnce(&once, create_dwrite_factory, &gDWriteFactory, release_dwrite_factory); 4572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com 4672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com return gDWriteFactory; 4772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com} 4872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com 4972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com//////////////////////////////////////////////////////////////////////////////// 5072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com// String conversion 5172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com 5272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com/** Converts a utf8 string to a WCHAR string. */ 5372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.comHRESULT sk_cstring_to_wchar(const char* skname, SkSMallocWCHAR* name) { 5472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com int wlen = MultiByteToWideChar(CP_UTF8, 0, skname, -1, NULL, 0); 5572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com if (0 == wlen) { 5672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com HRM(HRESULT_FROM_WIN32(GetLastError()), 5772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com "Could not get length for wchar to utf-8 conversion."); 5872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com } 5972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com name->reset(wlen); 6072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com wlen = MultiByteToWideChar(CP_UTF8, 0, skname, -1, name->get(), wlen); 6172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com if (0 == wlen) { 6272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com HRM(HRESULT_FROM_WIN32(GetLastError()), "Could not convert wchar to utf-8."); 6372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com } 6472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com return S_OK; 6572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com} 6672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com 6772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com/** Converts a WCHAR string to a utf8 string. */ 6872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.comHRESULT sk_wchar_to_skstring(WCHAR* name, SkString* skname) { 6972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com int len = WideCharToMultiByte(CP_UTF8, 0, name, -1, NULL, 0, NULL, NULL); 7072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com if (0 == len) { 7172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com HRM(HRESULT_FROM_WIN32(GetLastError()), 7272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com "Could not get length for utf-8 to wchar conversion."); 7372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com } 7472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com skname->resize(len - 1); 7572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com 7672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com // TODO: remove after https://code.google.com/p/skia/issues/detail?id=1989 is fixed. 7772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com // If we resize to 0 then the skname points to gEmptyRec (the unique empty SkString::Rec). 7872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com // gEmptyRec is static const and on Windows this means the value is in a read only page. 7972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com // Writing to it in the following call to WideCharToMultiByte will cause an access violation. 8072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com if (1 == len) { 8172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com return S_OK; 8272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com } 8372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com 8472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com len = WideCharToMultiByte(CP_UTF8, 0, name, -1, skname->writable_str(), len, NULL, NULL); 8572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com if (0 == len) { 8672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com HRM(HRESULT_FROM_WIN32(GetLastError()), "Could not convert utf-8 to wchar."); 8772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com } 8872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com return S_OK; 8972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com} 9072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com 9172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com//////////////////////////////////////////////////////////////////////////////// 9272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com// Locale 9372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com 9472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.comvoid sk_get_locale_string(IDWriteLocalizedStrings* names, const WCHAR* preferedLocale, 9572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com SkString* skname) { 9672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com UINT32 nameIndex = 0; 9772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com if (preferedLocale) { 9872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com // Ignore any errors and continue with index 0 if there is a problem. 9972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com BOOL nameExists; 10072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com names->FindLocaleName(preferedLocale, &nameIndex, &nameExists); 10172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com if (!nameExists) { 10272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com nameIndex = 0; 10372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com } 10472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com } 10572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com 10672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com UINT32 nameLength; 10772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com HRVM(names->GetStringLength(nameIndex, &nameLength), "Could not get name length."); 10872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com nameLength += 1; 10972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com 11072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com SkSMallocWCHAR name(nameLength); 11172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com HRVM(names->GetString(nameIndex, name.get(), nameLength), "Could not get string."); 11272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com 11372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com HRV(sk_wchar_to_skstring(name.get(), skname)); 11472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com} 11572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com 11672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.comHRESULT SkGetGetUserDefaultLocaleNameProc(SkGetUserDefaultLocaleNameProc* proc) { 11772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com *proc = reinterpret_cast<SkGetUserDefaultLocaleNameProc>( 11872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com GetProcAddress(LoadLibraryW(L"Kernel32.dll"), "GetUserDefaultLocaleName") 11972cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com ); 12072cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com if (!*proc) { 12172cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com HRESULT hr = HRESULT_FROM_WIN32(GetLastError()); 12272cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com if (!IS_ERROR(hr)) { 12372cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com hr = ERROR_PROC_NOT_FOUND; 12472cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com } 12572cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com return hr; 12672cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com } 12772cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com return S_OK; 12872cf4fcafa54cfa04c5ec7cb8eaa3acb144712ddbungeman@google.com} 129