1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/ports/SkFontHost_win_dw.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1931 @@ 1.4 +/* 1.5 + * Copyright 2011 Google Inc. 1.6 + * 1.7 + * Use of this source code is governed by a BSD-style license that can be 1.8 + * found in the LICENSE file. 1.9 + */ 1.10 + 1.11 +#include "SkTypes.h" 1.12 +#undef GetGlyphIndices 1.13 + 1.14 +#include "SkAdvancedTypefaceMetrics.h" 1.15 +#include "SkColorFilter.h" 1.16 +#include "SkDWriteFontFileStream.h" 1.17 +#include "SkDWriteGeometrySink.h" 1.18 +#include "SkDescriptor.h" 1.19 +#include "SkEndian.h" 1.20 +#include "SkFontDescriptor.h" 1.21 +#include "SkFontHost.h" 1.22 +#include "SkFontMgr.h" 1.23 +#include "SkFontStream.h" 1.24 +#include "SkGlyph.h" 1.25 +#include "SkHRESULT.h" 1.26 +#include "SkMaskGamma.h" 1.27 +#include "SkOnce.h" 1.28 +#include "SkOTTable_head.h" 1.29 +#include "SkOTTable_hhea.h" 1.30 +#include "SkOTTable_OS_2.h" 1.31 +#include "SkOTTable_post.h" 1.32 +#include "SkPath.h" 1.33 +#include "SkStream.h" 1.34 +#include "SkString.h" 1.35 +#include "SkTScopedComPtr.h" 1.36 +#include "SkThread.h" 1.37 +#include "SkTypeface_win.h" 1.38 +#include "SkTypefaceCache.h" 1.39 +#include "SkUtils.h" 1.40 + 1.41 +#include <dwrite.h> 1.42 + 1.43 +static bool isLCD(const SkScalerContext::Rec& rec) { 1.44 + return SkMask::kLCD16_Format == rec.fMaskFormat || 1.45 + SkMask::kLCD32_Format == rec.fMaskFormat; 1.46 +} 1.47 + 1.48 +/** Prefer to use this type to prevent template proliferation. */ 1.49 +typedef SkAutoSTMalloc<16, WCHAR> SkSMallocWCHAR; 1.50 + 1.51 +/** Converts a utf8 string to a WCHAR string. */ 1.52 +static HRESULT cstring_to_wchar(const char* skname, SkSMallocWCHAR* name) { 1.53 + int wlen = MultiByteToWideChar(CP_UTF8, 0, skname, -1, NULL, 0); 1.54 + if (0 == wlen) { 1.55 + HRM(HRESULT_FROM_WIN32(GetLastError()), 1.56 + "Could not get length for wchar to utf-8 conversion."); 1.57 + } 1.58 + name->reset(wlen); 1.59 + wlen = MultiByteToWideChar(CP_UTF8, 0, skname, -1, name->get(), wlen); 1.60 + if (0 == wlen) { 1.61 + HRM(HRESULT_FROM_WIN32(GetLastError()), "Could not convert wchar to utf-8."); 1.62 + } 1.63 + return S_OK; 1.64 +} 1.65 + 1.66 +/** Converts a WCHAR string to a utf8 string. */ 1.67 +static HRESULT wchar_to_skstring(WCHAR* name, SkString* skname) { 1.68 + int len = WideCharToMultiByte(CP_UTF8, 0, name, -1, NULL, 0, NULL, NULL); 1.69 + if (0 == len) { 1.70 + HRM(HRESULT_FROM_WIN32(GetLastError()), 1.71 + "Could not get length for utf-8 to wchar conversion."); 1.72 + } 1.73 + skname->resize(len - 1); 1.74 + 1.75 + // TODO: remove after https://code.google.com/p/skia/issues/detail?id=1989 is fixed. 1.76 + // If we resize to 0 then the skname points to gEmptyRec (the unique empty SkString::Rec). 1.77 + // gEmptyRec is static const and on Windows this means the value is in a read only page. 1.78 + // Writing to it in the following call to WideCharToMultiByte will cause an access violation. 1.79 + if (1 == len) { 1.80 + return S_OK; 1.81 + } 1.82 + 1.83 + len = WideCharToMultiByte(CP_UTF8, 0, name, -1, skname->writable_str(), len, NULL, NULL); 1.84 + if (0 == len) { 1.85 + HRM(HRESULT_FROM_WIN32(GetLastError()), "Could not convert utf-8 to wchar."); 1.86 + } 1.87 + return S_OK; 1.88 +} 1.89 + 1.90 +/////////////////////////////////////////////////////////////////////////////// 1.91 + 1.92 +static void create_dwrite_factory(IDWriteFactory** factory) { 1.93 + typedef decltype(DWriteCreateFactory)* DWriteCreateFactoryProc; 1.94 + DWriteCreateFactoryProc dWriteCreateFactoryProc = reinterpret_cast<DWriteCreateFactoryProc>( 1.95 + GetProcAddress(LoadLibraryW(L"dwrite.dll"), "DWriteCreateFactory")); 1.96 + 1.97 + if (!dWriteCreateFactoryProc) { 1.98 + HRESULT hr = HRESULT_FROM_WIN32(GetLastError()); 1.99 + if (!IS_ERROR(hr)) { 1.100 + hr = ERROR_PROC_NOT_FOUND; 1.101 + } 1.102 + HRVM(hr, "Could not get DWriteCreateFactory proc."); 1.103 + } 1.104 + 1.105 + HRVM(dWriteCreateFactoryProc(DWRITE_FACTORY_TYPE_SHARED, 1.106 + __uuidof(IDWriteFactory), 1.107 + reinterpret_cast<IUnknown**>(factory)), 1.108 + "Could not create DirectWrite factory."); 1.109 +} 1.110 + 1.111 +static IDWriteFactory* get_dwrite_factory() { 1.112 + static IDWriteFactory* gDWriteFactory = NULL; 1.113 + SK_DECLARE_STATIC_ONCE(once); 1.114 + SkOnce(&once, create_dwrite_factory, &gDWriteFactory); 1.115 + 1.116 + return gDWriteFactory; 1.117 +} 1.118 + 1.119 +/////////////////////////////////////////////////////////////////////////////// 1.120 + 1.121 +class StreamFontFileLoader; 1.122 + 1.123 +class SkFontMgr_DirectWrite : public SkFontMgr { 1.124 +public: 1.125 + /** localeNameLength must include the null terminator. */ 1.126 + SkFontMgr_DirectWrite(IDWriteFontCollection* fontCollection, 1.127 + WCHAR* localeName, int localeNameLength) 1.128 + : fFontCollection(SkRefComPtr(fontCollection)) 1.129 + , fLocaleName(localeNameLength) 1.130 + { 1.131 + memcpy(fLocaleName.get(), localeName, localeNameLength * sizeof(WCHAR)); 1.132 + } 1.133 + 1.134 + SkTypeface* createTypefaceFromDWriteFont(IDWriteFontFace* fontFace, 1.135 + IDWriteFont* font, 1.136 + IDWriteFontFamily* fontFamily, 1.137 + StreamFontFileLoader* = NULL, 1.138 + IDWriteFontCollectionLoader* = NULL) const; 1.139 + 1.140 +protected: 1.141 + virtual int onCountFamilies() const SK_OVERRIDE; 1.142 + virtual void onGetFamilyName(int index, SkString* familyName) const SK_OVERRIDE; 1.143 + virtual SkFontStyleSet* onCreateStyleSet(int index) const SK_OVERRIDE; 1.144 + virtual SkFontStyleSet* onMatchFamily(const char familyName[]) const SK_OVERRIDE; 1.145 + virtual SkTypeface* onMatchFamilyStyle(const char familyName[], 1.146 + const SkFontStyle& fontstyle) const SK_OVERRIDE; 1.147 + virtual SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember, 1.148 + const SkFontStyle& fontstyle) const SK_OVERRIDE; 1.149 + virtual SkTypeface* onCreateFromStream(SkStream* stream, int ttcIndex) const SK_OVERRIDE; 1.150 + virtual SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const SK_OVERRIDE; 1.151 + virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const SK_OVERRIDE; 1.152 + virtual SkTypeface* onLegacyCreateTypeface(const char familyName[], 1.153 + unsigned styleBits) const SK_OVERRIDE; 1.154 + 1.155 +private: 1.156 + HRESULT getByFamilyName(const WCHAR familyName[], IDWriteFontFamily** fontFamily) const; 1.157 + HRESULT getDefaultFontFamily(IDWriteFontFamily** fontFamily) const; 1.158 + 1.159 + void Add(SkTypeface* face, SkTypeface::Style requestedStyle, bool strong) const { 1.160 + SkAutoMutexAcquire ama(fTFCacheMutex); 1.161 + fTFCache.add(face, requestedStyle, strong); 1.162 + } 1.163 + 1.164 + SkTypeface* FindByProcAndRef(SkTypefaceCache::FindProc proc, void* ctx) const { 1.165 + SkAutoMutexAcquire ama(fTFCacheMutex); 1.166 + SkTypeface* typeface = fTFCache.findByProcAndRef(proc, ctx); 1.167 + return typeface; 1.168 + } 1.169 + 1.170 + SkTScopedComPtr<IDWriteFontCollection> fFontCollection; 1.171 + SkSMallocWCHAR fLocaleName; 1.172 + mutable SkMutex fTFCacheMutex; 1.173 + mutable SkTypefaceCache fTFCache; 1.174 + 1.175 + friend class SkFontStyleSet_DirectWrite; 1.176 +}; 1.177 + 1.178 +class SkFontStyleSet_DirectWrite : public SkFontStyleSet { 1.179 +public: 1.180 + SkFontStyleSet_DirectWrite(const SkFontMgr_DirectWrite* fontMgr, 1.181 + IDWriteFontFamily* fontFamily) 1.182 + : fFontMgr(SkRef(fontMgr)) 1.183 + , fFontFamily(SkRefComPtr(fontFamily)) 1.184 + { } 1.185 + 1.186 + virtual int count() SK_OVERRIDE; 1.187 + virtual void getStyle(int index, SkFontStyle* fs, SkString* styleName) SK_OVERRIDE; 1.188 + virtual SkTypeface* createTypeface(int index) SK_OVERRIDE; 1.189 + virtual SkTypeface* matchStyle(const SkFontStyle& pattern) SK_OVERRIDE; 1.190 + 1.191 +private: 1.192 + SkAutoTUnref<const SkFontMgr_DirectWrite> fFontMgr; 1.193 + SkTScopedComPtr<IDWriteFontFamily> fFontFamily; 1.194 +}; 1.195 + 1.196 +/////////////////////////////////////////////////////////////////////////////// 1.197 + 1.198 +class DWriteOffscreen { 1.199 +public: 1.200 + DWriteOffscreen() : fWidth(0), fHeight(0) { 1.201 + } 1.202 + 1.203 + void init(IDWriteFontFace* fontFace, const DWRITE_MATRIX& xform, FLOAT fontSize) { 1.204 + fFontFace = fontFace; 1.205 + fFontSize = fontSize; 1.206 + fXform = xform; 1.207 + } 1.208 + 1.209 + const void* draw(const SkGlyph&, bool isBW); 1.210 + 1.211 +private: 1.212 + uint16_t fWidth; 1.213 + uint16_t fHeight; 1.214 + IDWriteFontFace* fFontFace; 1.215 + FLOAT fFontSize; 1.216 + DWRITE_MATRIX fXform; 1.217 + SkTDArray<uint8_t> fBits; 1.218 +}; 1.219 + 1.220 +const void* DWriteOffscreen::draw(const SkGlyph& glyph, bool isBW) { 1.221 + IDWriteFactory* factory = get_dwrite_factory(); 1.222 + SkASSERT(factory != NULL); 1.223 + 1.224 + if (fWidth < glyph.fWidth || fHeight < glyph.fHeight) { 1.225 + fWidth = SkMax32(fWidth, glyph.fWidth); 1.226 + fHeight = SkMax32(fHeight, glyph.fHeight); 1.227 + 1.228 + if (isBW) { 1.229 + fBits.setCount(fWidth * fHeight); 1.230 + } else { 1.231 + fBits.setCount(fWidth * fHeight * 3); 1.232 + } 1.233 + } 1.234 + 1.235 + // erase 1.236 + memset(fBits.begin(), 0, fBits.count()); 1.237 + 1.238 + fXform.dx = SkFixedToFloat(glyph.getSubXFixed()); 1.239 + fXform.dy = SkFixedToFloat(glyph.getSubYFixed()); 1.240 + 1.241 + FLOAT advance = 0.0f; 1.242 + 1.243 + UINT16 index = glyph.getGlyphID(); 1.244 + 1.245 + DWRITE_GLYPH_OFFSET offset; 1.246 + offset.advanceOffset = 0.0f; 1.247 + offset.ascenderOffset = 0.0f; 1.248 + 1.249 + DWRITE_GLYPH_RUN run; 1.250 + run.glyphCount = 1; 1.251 + run.glyphAdvances = &advance; 1.252 + run.fontFace = fFontFace; 1.253 + run.fontEmSize = fFontSize; 1.254 + run.bidiLevel = 0; 1.255 + run.glyphIndices = &index; 1.256 + run.isSideways = FALSE; 1.257 + run.glyphOffsets = &offset; 1.258 + 1.259 + DWRITE_RENDERING_MODE renderingMode; 1.260 + DWRITE_TEXTURE_TYPE textureType; 1.261 + if (isBW) { 1.262 + renderingMode = DWRITE_RENDERING_MODE_ALIASED; 1.263 + textureType = DWRITE_TEXTURE_ALIASED_1x1; 1.264 + } else { 1.265 + renderingMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC; 1.266 + textureType = DWRITE_TEXTURE_CLEARTYPE_3x1; 1.267 + } 1.268 + SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis; 1.269 + HRNM(factory->CreateGlyphRunAnalysis(&run, 1.270 + 1.0f, // pixelsPerDip, 1.271 + &fXform, 1.272 + renderingMode, 1.273 + DWRITE_MEASURING_MODE_NATURAL, 1.274 + 0.0f, // baselineOriginX, 1.275 + 0.0f, // baselineOriginY, 1.276 + &glyphRunAnalysis), 1.277 + "Could not create glyph run analysis."); 1.278 + 1.279 + //NOTE: this assumes that the glyph has already been measured 1.280 + //with an exact same glyph run analysis. 1.281 + RECT bbox; 1.282 + bbox.left = glyph.fLeft; 1.283 + bbox.top = glyph.fTop; 1.284 + bbox.right = glyph.fLeft + glyph.fWidth; 1.285 + bbox.bottom = glyph.fTop + glyph.fHeight; 1.286 + HRNM(glyphRunAnalysis->CreateAlphaTexture(textureType, 1.287 + &bbox, 1.288 + fBits.begin(), 1.289 + fBits.count()), 1.290 + "Could not draw mask."); 1.291 + return fBits.begin(); 1.292 +} 1.293 + 1.294 +/////////////////////////////////////////////////////////////////////////////// 1.295 + 1.296 +class StreamFontFileLoader : public IDWriteFontFileLoader { 1.297 +public: 1.298 + // IUnknown methods 1.299 + virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject); 1.300 + virtual ULONG STDMETHODCALLTYPE AddRef(); 1.301 + virtual ULONG STDMETHODCALLTYPE Release(); 1.302 + 1.303 + // IDWriteFontFileLoader methods 1.304 + virtual HRESULT STDMETHODCALLTYPE CreateStreamFromKey( 1.305 + void const* fontFileReferenceKey, 1.306 + UINT32 fontFileReferenceKeySize, 1.307 + IDWriteFontFileStream** fontFileStream); 1.308 + 1.309 + static HRESULT Create(SkStream* stream, StreamFontFileLoader** streamFontFileLoader) { 1.310 + *streamFontFileLoader = new StreamFontFileLoader(stream); 1.311 + if (NULL == streamFontFileLoader) { 1.312 + return E_OUTOFMEMORY; 1.313 + } 1.314 + return S_OK; 1.315 + } 1.316 + 1.317 + SkAutoTUnref<SkStream> fStream; 1.318 + 1.319 +private: 1.320 + StreamFontFileLoader(SkStream* stream) : fRefCount(1), fStream(SkRef(stream)) { } 1.321 + 1.322 + ULONG fRefCount; 1.323 +}; 1.324 + 1.325 +HRESULT StreamFontFileLoader::QueryInterface(REFIID iid, void** ppvObject) { 1.326 + if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileLoader)) { 1.327 + *ppvObject = this; 1.328 + AddRef(); 1.329 + return S_OK; 1.330 + } else { 1.331 + *ppvObject = NULL; 1.332 + return E_NOINTERFACE; 1.333 + } 1.334 +} 1.335 + 1.336 +ULONG StreamFontFileLoader::AddRef() { 1.337 + return InterlockedIncrement(&fRefCount); 1.338 +} 1.339 + 1.340 +ULONG StreamFontFileLoader::Release() { 1.341 + ULONG newCount = InterlockedDecrement(&fRefCount); 1.342 + if (0 == newCount) { 1.343 + delete this; 1.344 + } 1.345 + return newCount; 1.346 +} 1.347 + 1.348 +HRESULT StreamFontFileLoader::CreateStreamFromKey( 1.349 + void const* fontFileReferenceKey, 1.350 + UINT32 fontFileReferenceKeySize, 1.351 + IDWriteFontFileStream** fontFileStream) 1.352 +{ 1.353 + SkTScopedComPtr<SkDWriteFontFileStreamWrapper> stream; 1.354 + HR(SkDWriteFontFileStreamWrapper::Create(fStream, &stream)); 1.355 + *fontFileStream = stream.release(); 1.356 + return S_OK; 1.357 +} 1.358 + 1.359 +class StreamFontFileEnumerator : public IDWriteFontFileEnumerator { 1.360 +public: 1.361 + // IUnknown methods 1.362 + virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject); 1.363 + virtual ULONG STDMETHODCALLTYPE AddRef(); 1.364 + virtual ULONG STDMETHODCALLTYPE Release(); 1.365 + 1.366 + // IDWriteFontFileEnumerator methods 1.367 + virtual HRESULT STDMETHODCALLTYPE MoveNext(BOOL* hasCurrentFile); 1.368 + virtual HRESULT STDMETHODCALLTYPE GetCurrentFontFile(IDWriteFontFile** fontFile); 1.369 + 1.370 + static HRESULT Create(IDWriteFactory* factory, IDWriteFontFileLoader* fontFileLoader, 1.371 + StreamFontFileEnumerator** streamFontFileEnumerator) { 1.372 + *streamFontFileEnumerator = new StreamFontFileEnumerator(factory, fontFileLoader); 1.373 + if (NULL == streamFontFileEnumerator) { 1.374 + return E_OUTOFMEMORY; 1.375 + } 1.376 + return S_OK; 1.377 + } 1.378 +private: 1.379 + StreamFontFileEnumerator(IDWriteFactory* factory, IDWriteFontFileLoader* fontFileLoader); 1.380 + ULONG fRefCount; 1.381 + 1.382 + SkTScopedComPtr<IDWriteFactory> fFactory; 1.383 + SkTScopedComPtr<IDWriteFontFile> fCurrentFile; 1.384 + SkTScopedComPtr<IDWriteFontFileLoader> fFontFileLoader; 1.385 + bool fHasNext; 1.386 +}; 1.387 + 1.388 +StreamFontFileEnumerator::StreamFontFileEnumerator(IDWriteFactory* factory, 1.389 + IDWriteFontFileLoader* fontFileLoader) 1.390 + : fRefCount(1) 1.391 + , fFactory(SkRefComPtr(factory)) 1.392 + , fCurrentFile() 1.393 + , fFontFileLoader(SkRefComPtr(fontFileLoader)) 1.394 + , fHasNext(true) 1.395 +{ } 1.396 + 1.397 +HRESULT StreamFontFileEnumerator::QueryInterface(REFIID iid, void** ppvObject) { 1.398 + if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileEnumerator)) { 1.399 + *ppvObject = this; 1.400 + AddRef(); 1.401 + return S_OK; 1.402 + } else { 1.403 + *ppvObject = NULL; 1.404 + return E_NOINTERFACE; 1.405 + } 1.406 +} 1.407 + 1.408 +ULONG StreamFontFileEnumerator::AddRef() { 1.409 + return InterlockedIncrement(&fRefCount); 1.410 +} 1.411 + 1.412 +ULONG StreamFontFileEnumerator::Release() { 1.413 + ULONG newCount = InterlockedDecrement(&fRefCount); 1.414 + if (0 == newCount) { 1.415 + delete this; 1.416 + } 1.417 + return newCount; 1.418 +} 1.419 + 1.420 +HRESULT StreamFontFileEnumerator::MoveNext(BOOL* hasCurrentFile) { 1.421 + *hasCurrentFile = FALSE; 1.422 + 1.423 + if (!fHasNext) { 1.424 + return S_OK; 1.425 + } 1.426 + fHasNext = false; 1.427 + 1.428 + UINT32 dummy = 0; 1.429 + HR(fFactory->CreateCustomFontFileReference( 1.430 + &dummy, //cannot be NULL 1.431 + sizeof(dummy), //even if this is 0 1.432 + fFontFileLoader.get(), 1.433 + &fCurrentFile)); 1.434 + 1.435 + *hasCurrentFile = TRUE; 1.436 + return S_OK; 1.437 +} 1.438 + 1.439 +HRESULT StreamFontFileEnumerator::GetCurrentFontFile(IDWriteFontFile** fontFile) { 1.440 + if (fCurrentFile.get() == NULL) { 1.441 + *fontFile = NULL; 1.442 + return E_FAIL; 1.443 + } 1.444 + 1.445 + *fontFile = SkRefComPtr(fCurrentFile.get()); 1.446 + return S_OK; 1.447 +} 1.448 + 1.449 +class StreamFontCollectionLoader : public IDWriteFontCollectionLoader { 1.450 +public: 1.451 + // IUnknown methods 1.452 + virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject); 1.453 + virtual ULONG STDMETHODCALLTYPE AddRef(); 1.454 + virtual ULONG STDMETHODCALLTYPE Release(); 1.455 + 1.456 + // IDWriteFontCollectionLoader methods 1.457 + virtual HRESULT STDMETHODCALLTYPE CreateEnumeratorFromKey( 1.458 + IDWriteFactory* factory, 1.459 + void const* collectionKey, 1.460 + UINT32 collectionKeySize, 1.461 + IDWriteFontFileEnumerator** fontFileEnumerator); 1.462 + 1.463 + static HRESULT Create(IDWriteFontFileLoader* fontFileLoader, 1.464 + StreamFontCollectionLoader** streamFontCollectionLoader) { 1.465 + *streamFontCollectionLoader = new StreamFontCollectionLoader(fontFileLoader); 1.466 + if (NULL == streamFontCollectionLoader) { 1.467 + return E_OUTOFMEMORY; 1.468 + } 1.469 + return S_OK; 1.470 + } 1.471 +private: 1.472 + StreamFontCollectionLoader(IDWriteFontFileLoader* fontFileLoader) 1.473 + : fRefCount(1) 1.474 + , fFontFileLoader(SkRefComPtr(fontFileLoader)) 1.475 + { } 1.476 + 1.477 + ULONG fRefCount; 1.478 + SkTScopedComPtr<IDWriteFontFileLoader> fFontFileLoader; 1.479 +}; 1.480 + 1.481 +HRESULT StreamFontCollectionLoader::QueryInterface(REFIID iid, void** ppvObject) { 1.482 + if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontCollectionLoader)) { 1.483 + *ppvObject = this; 1.484 + AddRef(); 1.485 + return S_OK; 1.486 + } else { 1.487 + *ppvObject = NULL; 1.488 + return E_NOINTERFACE; 1.489 + } 1.490 +} 1.491 + 1.492 +ULONG StreamFontCollectionLoader::AddRef() { 1.493 + return InterlockedIncrement(&fRefCount); 1.494 +} 1.495 + 1.496 +ULONG StreamFontCollectionLoader::Release() { 1.497 + ULONG newCount = InterlockedDecrement(&fRefCount); 1.498 + if (0 == newCount) { 1.499 + delete this; 1.500 + } 1.501 + return newCount; 1.502 +} 1.503 + 1.504 +HRESULT StreamFontCollectionLoader::CreateEnumeratorFromKey( 1.505 + IDWriteFactory* factory, 1.506 + void const* collectionKey, 1.507 + UINT32 collectionKeySize, 1.508 + IDWriteFontFileEnumerator** fontFileEnumerator) 1.509 +{ 1.510 + SkTScopedComPtr<StreamFontFileEnumerator> enumerator; 1.511 + HR(StreamFontFileEnumerator::Create(factory, fFontFileLoader.get(), &enumerator)); 1.512 + *fontFileEnumerator = enumerator.release(); 1.513 + return S_OK; 1.514 +} 1.515 + 1.516 +/////////////////////////////////////////////////////////////////////////////// 1.517 + 1.518 +static SkTypeface::Style get_style(IDWriteFont* font) { 1.519 + int style = SkTypeface::kNormal; 1.520 + DWRITE_FONT_WEIGHT weight = font->GetWeight(); 1.521 + if (DWRITE_FONT_WEIGHT_DEMI_BOLD <= weight) { 1.522 + style |= SkTypeface::kBold; 1.523 + } 1.524 + DWRITE_FONT_STYLE angle = font->GetStyle(); 1.525 + if (DWRITE_FONT_STYLE_OBLIQUE == angle || DWRITE_FONT_STYLE_ITALIC == angle) { 1.526 + style |= SkTypeface::kItalic; 1.527 + } 1.528 + return static_cast<SkTypeface::Style>(style); 1.529 +} 1.530 + 1.531 +class DWriteFontTypeface : public SkTypeface { 1.532 +private: 1.533 + DWriteFontTypeface(SkTypeface::Style style, SkFontID fontID, 1.534 + IDWriteFontFace* fontFace, 1.535 + IDWriteFont* font, 1.536 + IDWriteFontFamily* fontFamily, 1.537 + StreamFontFileLoader* fontFileLoader = NULL, 1.538 + IDWriteFontCollectionLoader* fontCollectionLoader = NULL) 1.539 + : SkTypeface(style, fontID, false) 1.540 + , fDWriteFontCollectionLoader(SkSafeRefComPtr(fontCollectionLoader)) 1.541 + , fDWriteFontFileLoader(SkSafeRefComPtr(fontFileLoader)) 1.542 + , fDWriteFontFamily(SkRefComPtr(fontFamily)) 1.543 + , fDWriteFont(SkRefComPtr(font)) 1.544 + , fDWriteFontFace(SkRefComPtr(fontFace)) 1.545 + { } 1.546 + 1.547 +public: 1.548 + SkTScopedComPtr<IDWriteFontCollectionLoader> fDWriteFontCollectionLoader; 1.549 + SkTScopedComPtr<StreamFontFileLoader> fDWriteFontFileLoader; 1.550 + SkTScopedComPtr<IDWriteFontFamily> fDWriteFontFamily; 1.551 + SkTScopedComPtr<IDWriteFont> fDWriteFont; 1.552 + SkTScopedComPtr<IDWriteFontFace> fDWriteFontFace; 1.553 + 1.554 + static DWriteFontTypeface* Create(IDWriteFontFace* fontFace, 1.555 + IDWriteFont* font, 1.556 + IDWriteFontFamily* fontFamily, 1.557 + StreamFontFileLoader* fontFileLoader = NULL, 1.558 + IDWriteFontCollectionLoader* fontCollectionLoader = NULL) { 1.559 + SkTypeface::Style style = get_style(font); 1.560 + SkFontID fontID = SkTypefaceCache::NewFontID(); 1.561 + return SkNEW_ARGS(DWriteFontTypeface, (style, fontID, 1.562 + fontFace, font, fontFamily, 1.563 + fontFileLoader, fontCollectionLoader)); 1.564 + } 1.565 + 1.566 + ~DWriteFontTypeface() { 1.567 + if (fDWriteFontCollectionLoader.get() == NULL) return; 1.568 + 1.569 + IDWriteFactory* factory = get_dwrite_factory(); 1.570 + SkASSERT(factory != NULL); 1.571 + HRV(factory->UnregisterFontCollectionLoader(fDWriteFontCollectionLoader.get())); 1.572 + HRV(factory->UnregisterFontFileLoader(fDWriteFontFileLoader.get())); 1.573 + } 1.574 + 1.575 +protected: 1.576 + virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE; 1.577 + virtual SkScalerContext* onCreateScalerContext(const SkDescriptor*) const SK_OVERRIDE; 1.578 + virtual void onFilterRec(SkScalerContextRec*) const SK_OVERRIDE; 1.579 + virtual SkAdvancedTypefaceMetrics* onGetAdvancedTypefaceMetrics( 1.580 + SkAdvancedTypefaceMetrics::PerGlyphInfo, 1.581 + const uint32_t*, uint32_t) const SK_OVERRIDE; 1.582 + virtual void onGetFontDescriptor(SkFontDescriptor*, bool*) const SK_OVERRIDE; 1.583 + virtual int onCharsToGlyphs(const void* chars, Encoding encoding, 1.584 + uint16_t glyphs[], int glyphCount) const SK_OVERRIDE; 1.585 + virtual int onCountGlyphs() const SK_OVERRIDE; 1.586 + virtual int onGetUPEM() const SK_OVERRIDE; 1.587 + virtual SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const SK_OVERRIDE; 1.588 + virtual int onGetTableTags(SkFontTableTag tags[]) const SK_OVERRIDE; 1.589 + virtual size_t onGetTableData(SkFontTableTag, size_t offset, 1.590 + size_t length, void* data) const SK_OVERRIDE; 1.591 +}; 1.592 + 1.593 +class SkScalerContext_DW : public SkScalerContext { 1.594 +public: 1.595 + SkScalerContext_DW(DWriteFontTypeface*, const SkDescriptor* desc); 1.596 + virtual ~SkScalerContext_DW(); 1.597 + 1.598 +protected: 1.599 + virtual unsigned generateGlyphCount() SK_OVERRIDE; 1.600 + virtual uint16_t generateCharToGlyph(SkUnichar uni) SK_OVERRIDE; 1.601 + virtual void generateAdvance(SkGlyph* glyph) SK_OVERRIDE; 1.602 + virtual void generateMetrics(SkGlyph* glyph) SK_OVERRIDE; 1.603 + virtual void generateImage(const SkGlyph& glyph) SK_OVERRIDE; 1.604 + virtual void generatePath(const SkGlyph& glyph, SkPath* path) SK_OVERRIDE; 1.605 + virtual void generateFontMetrics(SkPaint::FontMetrics* mX, 1.606 + SkPaint::FontMetrics* mY) SK_OVERRIDE; 1.607 + 1.608 +private: 1.609 + DWriteOffscreen fOffscreen; 1.610 + DWRITE_MATRIX fXform; 1.611 + SkAutoTUnref<DWriteFontTypeface> fTypeface; 1.612 + int fGlyphCount; 1.613 +}; 1.614 + 1.615 +static bool are_same(IUnknown* a, IUnknown* b) { 1.616 + SkTScopedComPtr<IUnknown> iunkA; 1.617 + if (FAILED(a->QueryInterface(&iunkA))) { 1.618 + return false; 1.619 + } 1.620 + 1.621 + SkTScopedComPtr<IUnknown> iunkB; 1.622 + if (FAILED(b->QueryInterface(&iunkB))) { 1.623 + return false; 1.624 + } 1.625 + 1.626 + return iunkA.get() == iunkB.get(); 1.627 +} 1.628 +static bool FindByDWriteFont(SkTypeface* face, SkTypeface::Style requestedStyle, void* ctx) { 1.629 + //Check to see if the two fonts are identical. 1.630 + DWriteFontTypeface* dwFace = reinterpret_cast<DWriteFontTypeface*>(face); 1.631 + IDWriteFont* dwFont = reinterpret_cast<IDWriteFont*>(ctx); 1.632 + if (are_same(dwFace->fDWriteFont.get(), dwFont)) { 1.633 + return true; 1.634 + } 1.635 + 1.636 + //Check if the two fonts share the same loader and have the same key. 1.637 + SkTScopedComPtr<IDWriteFontFace> dwFaceFontFace; 1.638 + SkTScopedComPtr<IDWriteFontFace> dwFontFace; 1.639 + HRB(dwFace->fDWriteFont->CreateFontFace(&dwFaceFontFace)); 1.640 + HRB(dwFont->CreateFontFace(&dwFontFace)); 1.641 + if (are_same(dwFaceFontFace.get(), dwFontFace.get())) { 1.642 + return true; 1.643 + } 1.644 + 1.645 + UINT32 dwFaceNumFiles; 1.646 + UINT32 dwNumFiles; 1.647 + HRB(dwFaceFontFace->GetFiles(&dwFaceNumFiles, NULL)); 1.648 + HRB(dwFontFace->GetFiles(&dwNumFiles, NULL)); 1.649 + if (dwFaceNumFiles != dwNumFiles) { 1.650 + return false; 1.651 + } 1.652 + 1.653 + SkTScopedComPtr<IDWriteFontFile> dwFaceFontFile; 1.654 + SkTScopedComPtr<IDWriteFontFile> dwFontFile; 1.655 + HRB(dwFaceFontFace->GetFiles(&dwFaceNumFiles, &dwFaceFontFile)); 1.656 + HRB(dwFontFace->GetFiles(&dwNumFiles, &dwFontFile)); 1.657 + 1.658 + //for (each file) { //we currently only admit fonts from one file. 1.659 + SkTScopedComPtr<IDWriteFontFileLoader> dwFaceFontFileLoader; 1.660 + SkTScopedComPtr<IDWriteFontFileLoader> dwFontFileLoader; 1.661 + HRB(dwFaceFontFile->GetLoader(&dwFaceFontFileLoader)); 1.662 + HRB(dwFontFile->GetLoader(&dwFontFileLoader)); 1.663 + if (!are_same(dwFaceFontFileLoader.get(), dwFontFileLoader.get())) { 1.664 + return false; 1.665 + } 1.666 + //} 1.667 + 1.668 + const void* dwFaceFontRefKey; 1.669 + UINT32 dwFaceFontRefKeySize; 1.670 + const void* dwFontRefKey; 1.671 + UINT32 dwFontRefKeySize; 1.672 + HRB(dwFaceFontFile->GetReferenceKey(&dwFaceFontRefKey, &dwFaceFontRefKeySize)); 1.673 + HRB(dwFontFile->GetReferenceKey(&dwFontRefKey, &dwFontRefKeySize)); 1.674 + if (dwFaceFontRefKeySize != dwFontRefKeySize) { 1.675 + return false; 1.676 + } 1.677 + if (0 != memcmp(dwFaceFontRefKey, dwFontRefKey, dwFontRefKeySize)) { 1.678 + return false; 1.679 + } 1.680 + 1.681 + //TODO: better means than comparing name strings? 1.682 + //NOTE: .tfc and fake bold/italic will end up here. 1.683 + SkTScopedComPtr<IDWriteFontFamily> dwFaceFontFamily; 1.684 + SkTScopedComPtr<IDWriteFontFamily> dwFontFamily; 1.685 + HRB(dwFace->fDWriteFont->GetFontFamily(&dwFaceFontFamily)); 1.686 + HRB(dwFont->GetFontFamily(&dwFontFamily)); 1.687 + 1.688 + SkTScopedComPtr<IDWriteLocalizedStrings> dwFaceFontFamilyNames; 1.689 + SkTScopedComPtr<IDWriteLocalizedStrings> dwFaceFontNames; 1.690 + HRB(dwFaceFontFamily->GetFamilyNames(&dwFaceFontFamilyNames)); 1.691 + HRB(dwFace->fDWriteFont->GetFaceNames(&dwFaceFontNames)); 1.692 + 1.693 + SkTScopedComPtr<IDWriteLocalizedStrings> dwFontFamilyNames; 1.694 + SkTScopedComPtr<IDWriteLocalizedStrings> dwFontNames; 1.695 + HRB(dwFontFamily->GetFamilyNames(&dwFontFamilyNames)); 1.696 + HRB(dwFont->GetFaceNames(&dwFontNames)); 1.697 + 1.698 + UINT32 dwFaceFontFamilyNameLength; 1.699 + UINT32 dwFaceFontNameLength; 1.700 + HRB(dwFaceFontFamilyNames->GetStringLength(0, &dwFaceFontFamilyNameLength)); 1.701 + HRB(dwFaceFontNames->GetStringLength(0, &dwFaceFontNameLength)); 1.702 + 1.703 + UINT32 dwFontFamilyNameLength; 1.704 + UINT32 dwFontNameLength; 1.705 + HRB(dwFontFamilyNames->GetStringLength(0, &dwFontFamilyNameLength)); 1.706 + HRB(dwFontNames->GetStringLength(0, &dwFontNameLength)); 1.707 + 1.708 + if (dwFaceFontFamilyNameLength != dwFontFamilyNameLength || 1.709 + dwFaceFontNameLength != dwFontNameLength) 1.710 + { 1.711 + return false; 1.712 + } 1.713 + 1.714 + SkSMallocWCHAR dwFaceFontFamilyNameChar(dwFaceFontFamilyNameLength+1); 1.715 + SkSMallocWCHAR dwFaceFontNameChar(dwFaceFontNameLength+1); 1.716 + HRB(dwFaceFontFamilyNames->GetString(0, dwFaceFontFamilyNameChar.get(), dwFaceFontFamilyNameLength+1)); 1.717 + HRB(dwFaceFontNames->GetString(0, dwFaceFontNameChar.get(), dwFaceFontNameLength+1)); 1.718 + 1.719 + SkSMallocWCHAR dwFontFamilyNameChar(dwFontFamilyNameLength+1); 1.720 + SkSMallocWCHAR dwFontNameChar(dwFontNameLength+1); 1.721 + HRB(dwFontFamilyNames->GetString(0, dwFontFamilyNameChar.get(), dwFontFamilyNameLength+1)); 1.722 + HRB(dwFontNames->GetString(0, dwFontNameChar.get(), dwFontNameLength+1)); 1.723 + 1.724 + return wcscmp(dwFaceFontFamilyNameChar.get(), dwFontFamilyNameChar.get()) == 0 && 1.725 + wcscmp(dwFaceFontNameChar.get(), dwFontNameChar.get()) == 0; 1.726 +} 1.727 + 1.728 +SkScalerContext_DW::SkScalerContext_DW(DWriteFontTypeface* typeface, 1.729 + const SkDescriptor* desc) 1.730 + : SkScalerContext(typeface, desc) 1.731 + , fTypeface(SkRef(typeface)) 1.732 + , fGlyphCount(-1) { 1.733 + 1.734 + fXform.m11 = SkScalarToFloat(fRec.fPost2x2[0][0]); 1.735 + fXform.m12 = SkScalarToFloat(fRec.fPost2x2[1][0]); 1.736 + fXform.m21 = SkScalarToFloat(fRec.fPost2x2[0][1]); 1.737 + fXform.m22 = SkScalarToFloat(fRec.fPost2x2[1][1]); 1.738 + fXform.dx = 0; 1.739 + fXform.dy = 0; 1.740 + 1.741 + fOffscreen.init(fTypeface->fDWriteFontFace.get(), fXform, SkScalarToFloat(fRec.fTextSize)); 1.742 +} 1.743 + 1.744 +SkScalerContext_DW::~SkScalerContext_DW() { 1.745 +} 1.746 + 1.747 +unsigned SkScalerContext_DW::generateGlyphCount() { 1.748 + if (fGlyphCount < 0) { 1.749 + fGlyphCount = fTypeface->fDWriteFontFace->GetGlyphCount(); 1.750 + } 1.751 + return fGlyphCount; 1.752 +} 1.753 + 1.754 +uint16_t SkScalerContext_DW::generateCharToGlyph(SkUnichar uni) { 1.755 + uint16_t index = 0; 1.756 + fTypeface->fDWriteFontFace->GetGlyphIndices(reinterpret_cast<UINT32*>(&uni), 1, &index); 1.757 + return index; 1.758 +} 1.759 + 1.760 +void SkScalerContext_DW::generateAdvance(SkGlyph* glyph) { 1.761 + //Delta is the difference between the right/left side bearing metric 1.762 + //and where the right/left side bearing ends up after hinting. 1.763 + //DirectWrite does not provide this information. 1.764 + glyph->fRsbDelta = 0; 1.765 + glyph->fLsbDelta = 0; 1.766 + 1.767 + glyph->fAdvanceX = 0; 1.768 + glyph->fAdvanceY = 0; 1.769 + 1.770 + uint16_t glyphId = glyph->getGlyphID(); 1.771 + DWRITE_GLYPH_METRICS gm; 1.772 + HRVM(fTypeface->fDWriteFontFace->GetDesignGlyphMetrics(&glyphId, 1, &gm), 1.773 + "Could not get design metrics."); 1.774 + 1.775 + DWRITE_FONT_METRICS dwfm; 1.776 + fTypeface->fDWriteFontFace->GetMetrics(&dwfm); 1.777 + 1.778 + SkScalar advanceX = SkScalarMulDiv(fRec.fTextSize, 1.779 + SkIntToScalar(gm.advanceWidth), 1.780 + SkIntToScalar(dwfm.designUnitsPerEm)); 1.781 + 1.782 + if (!(fRec.fFlags & kSubpixelPositioning_Flag)) { 1.783 + advanceX = SkScalarRoundToScalar(advanceX); 1.784 + } 1.785 + 1.786 + SkVector vecs[1] = { { advanceX, 0 } }; 1.787 + SkMatrix mat; 1.788 + fRec.getMatrixFrom2x2(&mat); 1.789 + mat.mapVectors(vecs, SK_ARRAY_COUNT(vecs)); 1.790 + 1.791 + glyph->fAdvanceX = SkScalarToFixed(vecs[0].fX); 1.792 + glyph->fAdvanceY = SkScalarToFixed(vecs[0].fY); 1.793 +} 1.794 + 1.795 +void SkScalerContext_DW::generateMetrics(SkGlyph* glyph) { 1.796 + glyph->fWidth = 0; 1.797 + 1.798 + this->generateAdvance(glyph); 1.799 + 1.800 + //Measure raster size. 1.801 + fXform.dx = SkFixedToFloat(glyph->getSubXFixed()); 1.802 + fXform.dy = SkFixedToFloat(glyph->getSubYFixed()); 1.803 + 1.804 + FLOAT advance = 0; 1.805 + 1.806 + UINT16 glyphId = glyph->getGlyphID(); 1.807 + 1.808 + DWRITE_GLYPH_OFFSET offset; 1.809 + offset.advanceOffset = 0.0f; 1.810 + offset.ascenderOffset = 0.0f; 1.811 + 1.812 + DWRITE_GLYPH_RUN run; 1.813 + run.glyphCount = 1; 1.814 + run.glyphAdvances = &advance; 1.815 + run.fontFace = fTypeface->fDWriteFontFace.get(); 1.816 + run.fontEmSize = SkScalarToFloat(fRec.fTextSize); 1.817 + run.bidiLevel = 0; 1.818 + run.glyphIndices = &glyphId; 1.819 + run.isSideways = FALSE; 1.820 + run.glyphOffsets = &offset; 1.821 + 1.822 + IDWriteFactory* factory = get_dwrite_factory(); 1.823 + SkASSERT(factory != NULL); 1.824 + 1.825 + const bool isBW = SkMask::kBW_Format == fRec.fMaskFormat; 1.826 + DWRITE_RENDERING_MODE renderingMode; 1.827 + DWRITE_TEXTURE_TYPE textureType; 1.828 + if (isBW) { 1.829 + renderingMode = DWRITE_RENDERING_MODE_ALIASED; 1.830 + textureType = DWRITE_TEXTURE_ALIASED_1x1; 1.831 + } else { 1.832 + renderingMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC; 1.833 + textureType = DWRITE_TEXTURE_CLEARTYPE_3x1; 1.834 + } 1.835 + 1.836 + SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis; 1.837 + HRVM(factory->CreateGlyphRunAnalysis(&run, 1.838 + 1.0f, // pixelsPerDip, 1.839 + &fXform, 1.840 + renderingMode, 1.841 + DWRITE_MEASURING_MODE_NATURAL, 1.842 + 0.0f, // baselineOriginX, 1.843 + 0.0f, // baselineOriginY, 1.844 + &glyphRunAnalysis), 1.845 + "Could not create glyph run analysis."); 1.846 + 1.847 + RECT bbox; 1.848 + HRVM(glyphRunAnalysis->GetAlphaTextureBounds(textureType, &bbox), 1.849 + "Could not get texture bounds."); 1.850 + 1.851 + glyph->fWidth = SkToU16(bbox.right - bbox.left); 1.852 + glyph->fHeight = SkToU16(bbox.bottom - bbox.top); 1.853 + glyph->fLeft = SkToS16(bbox.left); 1.854 + glyph->fTop = SkToS16(bbox.top); 1.855 +} 1.856 + 1.857 +void SkScalerContext_DW::generateFontMetrics(SkPaint::FontMetrics* mx, 1.858 + SkPaint::FontMetrics* my) { 1.859 + if (!(mx || my)) 1.860 + return; 1.861 + 1.862 + if (mx) { 1.863 + sk_bzero(mx, sizeof(*mx)); 1.864 + } 1.865 + if (my) { 1.866 + sk_bzero(my, sizeof(*my)); 1.867 + } 1.868 + 1.869 + DWRITE_FONT_METRICS dwfm; 1.870 + fTypeface->fDWriteFontFace->GetMetrics(&dwfm); 1.871 + 1.872 + SkScalar upem = SkIntToScalar(dwfm.designUnitsPerEm); 1.873 + if (mx) { 1.874 + mx->fTop = -fRec.fTextSize * SkIntToScalar(dwfm.ascent) / upem; 1.875 + mx->fAscent = mx->fTop; 1.876 + mx->fDescent = fRec.fTextSize * SkIntToScalar(dwfm.descent) / upem; 1.877 + mx->fBottom = mx->fDescent; 1.878 + mx->fLeading = fRec.fTextSize * SkIntToScalar(dwfm.lineGap) / upem; 1.879 + mx->fXHeight = fRec.fTextSize * SkIntToScalar(dwfm.xHeight) / upem; 1.880 + mx->fUnderlineThickness = fRec.fTextSize * SkIntToScalar(dwfm.underlinePosition) / upem; 1.881 + mx->fUnderlinePosition = -(fRec.fTextSize * SkIntToScalar(dwfm.underlineThickness) / upem); 1.882 + 1.883 + mx->fFlags |= SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag; 1.884 + mx->fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag; 1.885 + } 1.886 + 1.887 + if (my) { 1.888 + my->fTop = -fRec.fTextSize * SkIntToScalar(dwfm.ascent) / upem; 1.889 + my->fAscent = my->fTop; 1.890 + my->fDescent = fRec.fTextSize * SkIntToScalar(dwfm.descent) / upem; 1.891 + my->fBottom = my->fDescent; 1.892 + my->fLeading = fRec.fTextSize * SkIntToScalar(dwfm.lineGap) / upem; 1.893 + my->fXHeight = fRec.fTextSize * SkIntToScalar(dwfm.xHeight) / upem; 1.894 + my->fUnderlineThickness = fRec.fTextSize * SkIntToScalar(dwfm.underlinePosition) / upem; 1.895 + my->fUnderlinePosition = -(fRec.fTextSize * SkIntToScalar(dwfm.underlineThickness) / upem); 1.896 + 1.897 + my->fFlags |= SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag; 1.898 + my->fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag; 1.899 + } 1.900 +} 1.901 + 1.902 +/////////////////////////////////////////////////////////////////////////////// 1.903 + 1.904 +#include "SkColorPriv.h" 1.905 + 1.906 +static void bilevel_to_bw(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph) { 1.907 + const int width = glyph.fWidth; 1.908 + const size_t dstRB = (width + 7) >> 3; 1.909 + uint8_t* SK_RESTRICT dst = static_cast<uint8_t*>(glyph.fImage); 1.910 + 1.911 + int byteCount = width >> 3; 1.912 + int bitCount = width & 7; 1.913 + 1.914 + for (int y = 0; y < glyph.fHeight; ++y) { 1.915 + if (byteCount > 0) { 1.916 + for (int i = 0; i < byteCount; ++i) { 1.917 + unsigned byte = 0; 1.918 + byte |= src[0] & (1 << 7); 1.919 + byte |= src[1] & (1 << 6); 1.920 + byte |= src[2] & (1 << 5); 1.921 + byte |= src[3] & (1 << 4); 1.922 + byte |= src[4] & (1 << 3); 1.923 + byte |= src[5] & (1 << 2); 1.924 + byte |= src[6] & (1 << 1); 1.925 + byte |= src[7] & (1 << 0); 1.926 + dst[i] = byte; 1.927 + src += 8; 1.928 + } 1.929 + } 1.930 + if (bitCount > 0) { 1.931 + unsigned byte = 0; 1.932 + unsigned mask = 0x80; 1.933 + for (int i = 0; i < bitCount; i++) { 1.934 + byte |= (src[i]) & mask; 1.935 + mask >>= 1; 1.936 + } 1.937 + dst[byteCount] = byte; 1.938 + } 1.939 + src += bitCount; 1.940 + dst += dstRB; 1.941 + } 1.942 +} 1.943 + 1.944 +template<bool APPLY_PREBLEND> 1.945 +static void rgb_to_a8(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph, const uint8_t* table8) { 1.946 + const size_t dstRB = glyph.rowBytes(); 1.947 + const U16CPU width = glyph.fWidth; 1.948 + uint8_t* SK_RESTRICT dst = static_cast<uint8_t*>(glyph.fImage); 1.949 + 1.950 + for (U16CPU y = 0; y < glyph.fHeight; y++) { 1.951 + for (U16CPU i = 0; i < width; i++) { 1.952 + U8CPU r = *(src++); 1.953 + U8CPU g = *(src++); 1.954 + U8CPU b = *(src++); 1.955 + dst[i] = sk_apply_lut_if<APPLY_PREBLEND>((r + g + b) / 3, table8); 1.956 + } 1.957 + dst = (uint8_t*)((char*)dst + dstRB); 1.958 + } 1.959 +} 1.960 + 1.961 +template<bool APPLY_PREBLEND> 1.962 +static void rgb_to_lcd16(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph, 1.963 + const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) { 1.964 + const size_t dstRB = glyph.rowBytes(); 1.965 + const U16CPU width = glyph.fWidth; 1.966 + uint16_t* SK_RESTRICT dst = static_cast<uint16_t*>(glyph.fImage); 1.967 + 1.968 + for (U16CPU y = 0; y < glyph.fHeight; y++) { 1.969 + for (U16CPU i = 0; i < width; i++) { 1.970 + U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableR); 1.971 + U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableG); 1.972 + U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableB); 1.973 + dst[i] = SkPack888ToRGB16(r, g, b); 1.974 + } 1.975 + dst = (uint16_t*)((char*)dst + dstRB); 1.976 + } 1.977 +} 1.978 + 1.979 +template<bool APPLY_PREBLEND> 1.980 +static void rgb_to_lcd32(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph, 1.981 + const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) { 1.982 + const size_t dstRB = glyph.rowBytes(); 1.983 + const U16CPU width = glyph.fWidth; 1.984 + SkPMColor* SK_RESTRICT dst = static_cast<SkPMColor*>(glyph.fImage); 1.985 + 1.986 + for (U16CPU y = 0; y < glyph.fHeight; y++) { 1.987 + for (U16CPU i = 0; i < width; i++) { 1.988 + U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableR); 1.989 + U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableG); 1.990 + U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableB); 1.991 + dst[i] = SkPackARGB32(0xFF, r, g, b); 1.992 + } 1.993 + dst = (SkPMColor*)((char*)dst + dstRB); 1.994 + } 1.995 +} 1.996 + 1.997 +void SkScalerContext_DW::generateImage(const SkGlyph& glyph) { 1.998 + const bool isBW = SkMask::kBW_Format == fRec.fMaskFormat; 1.999 + const bool isAA = !isLCD(fRec); 1.1000 + 1.1001 + //Create the mask. 1.1002 + const void* bits = fOffscreen.draw(glyph, isBW); 1.1003 + if (!bits) { 1.1004 + sk_bzero(glyph.fImage, glyph.computeImageSize()); 1.1005 + return; 1.1006 + } 1.1007 + 1.1008 + //Copy the mask into the glyph. 1.1009 + const uint8_t* src = (const uint8_t*)bits; 1.1010 + if (isBW) { 1.1011 + bilevel_to_bw(src, glyph); 1.1012 + } else if (isAA) { 1.1013 + if (fPreBlend.isApplicable()) { 1.1014 + rgb_to_a8<true>(src, glyph, fPreBlend.fG); 1.1015 + } else { 1.1016 + rgb_to_a8<false>(src, glyph, fPreBlend.fG); 1.1017 + } 1.1018 + } else if (SkMask::kLCD16_Format == glyph.fMaskFormat) { 1.1019 + if (fPreBlend.isApplicable()) { 1.1020 + rgb_to_lcd16<true>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); 1.1021 + } else { 1.1022 + rgb_to_lcd16<false>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); 1.1023 + } 1.1024 + } else { 1.1025 + SkASSERT(SkMask::kLCD32_Format == glyph.fMaskFormat); 1.1026 + if (fPreBlend.isApplicable()) { 1.1027 + rgb_to_lcd32<true>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); 1.1028 + } else { 1.1029 + rgb_to_lcd32<false>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); 1.1030 + } 1.1031 + } 1.1032 +} 1.1033 + 1.1034 +void SkScalerContext_DW::generatePath(const SkGlyph& glyph, SkPath* path) { 1.1035 + SkASSERT(&glyph && path); 1.1036 + 1.1037 + path->reset(); 1.1038 + 1.1039 + SkTScopedComPtr<IDWriteGeometrySink> geometryToPath; 1.1040 + HRVM(SkDWriteGeometrySink::Create(path, &geometryToPath), 1.1041 + "Could not create geometry to path converter."); 1.1042 + uint16_t glyphId = glyph.getGlyphID(); 1.1043 + //TODO: convert to<->from DIUs? This would make a difference if hinting. 1.1044 + //It may not be needed, it appears that DirectWrite only hints at em size. 1.1045 + HRVM(fTypeface->fDWriteFontFace->GetGlyphRunOutline(SkScalarToFloat(fRec.fTextSize), 1.1046 + &glyphId, 1.1047 + NULL, //advances 1.1048 + NULL, //offsets 1.1049 + 1, //num glyphs 1.1050 + FALSE, //sideways 1.1051 + FALSE, //rtl 1.1052 + geometryToPath.get()), 1.1053 + "Could not create glyph outline."); 1.1054 + 1.1055 + SkMatrix mat; 1.1056 + fRec.getMatrixFrom2x2(&mat); 1.1057 + path->transform(mat); 1.1058 +} 1.1059 + 1.1060 +void DWriteFontTypeface::onGetFontDescriptor(SkFontDescriptor* desc, 1.1061 + bool* isLocalStream) const { 1.1062 + // Get the family name. 1.1063 + SkTScopedComPtr<IDWriteLocalizedStrings> dwFamilyNames; 1.1064 + HRV(fDWriteFontFamily->GetFamilyNames(&dwFamilyNames)); 1.1065 + 1.1066 + UINT32 dwFamilyNamesLength; 1.1067 + HRV(dwFamilyNames->GetStringLength(0, &dwFamilyNamesLength)); 1.1068 + 1.1069 + SkSMallocWCHAR dwFamilyNameChar(dwFamilyNamesLength+1); 1.1070 + HRV(dwFamilyNames->GetString(0, dwFamilyNameChar.get(), dwFamilyNamesLength+1)); 1.1071 + 1.1072 + SkString utf8FamilyName; 1.1073 + HRV(wchar_to_skstring(dwFamilyNameChar.get(), &utf8FamilyName)); 1.1074 + 1.1075 + desc->setFamilyName(utf8FamilyName.c_str()); 1.1076 + *isLocalStream = SkToBool(fDWriteFontFileLoader.get()); 1.1077 +} 1.1078 + 1.1079 +static SkUnichar next_utf8(const void** chars) { 1.1080 + return SkUTF8_NextUnichar((const char**)chars); 1.1081 +} 1.1082 + 1.1083 +static SkUnichar next_utf16(const void** chars) { 1.1084 + return SkUTF16_NextUnichar((const uint16_t**)chars); 1.1085 +} 1.1086 + 1.1087 +static SkUnichar next_utf32(const void** chars) { 1.1088 + const SkUnichar** uniChars = (const SkUnichar**)chars; 1.1089 + SkUnichar uni = **uniChars; 1.1090 + *uniChars += 1; 1.1091 + return uni; 1.1092 +} 1.1093 + 1.1094 +typedef SkUnichar (*EncodingProc)(const void**); 1.1095 + 1.1096 +static EncodingProc find_encoding_proc(SkTypeface::Encoding enc) { 1.1097 + static const EncodingProc gProcs[] = { 1.1098 + next_utf8, next_utf16, next_utf32 1.1099 + }; 1.1100 + SkASSERT((size_t)enc < SK_ARRAY_COUNT(gProcs)); 1.1101 + return gProcs[enc]; 1.1102 +} 1.1103 + 1.1104 +int DWriteFontTypeface::onCharsToGlyphs(const void* chars, Encoding encoding, 1.1105 + uint16_t glyphs[], int glyphCount) const 1.1106 +{ 1.1107 + if (NULL == glyphs) { 1.1108 + EncodingProc next_ucs4_proc = find_encoding_proc(encoding); 1.1109 + for (int i = 0; i < glyphCount; ++i) { 1.1110 + const SkUnichar c = next_ucs4_proc(&chars); 1.1111 + BOOL exists; 1.1112 + fDWriteFont->HasCharacter(c, &exists); 1.1113 + if (!exists) { 1.1114 + return i; 1.1115 + } 1.1116 + } 1.1117 + return glyphCount; 1.1118 + } 1.1119 + 1.1120 + switch (encoding) { 1.1121 + case SkTypeface::kUTF8_Encoding: 1.1122 + case SkTypeface::kUTF16_Encoding: { 1.1123 + static const int scratchCount = 256; 1.1124 + UINT32 scratch[scratchCount]; 1.1125 + EncodingProc next_ucs4_proc = find_encoding_proc(encoding); 1.1126 + for (int baseGlyph = 0; baseGlyph < glyphCount; baseGlyph += scratchCount) { 1.1127 + int glyphsLeft = glyphCount - baseGlyph; 1.1128 + int limit = SkTMin(glyphsLeft, scratchCount); 1.1129 + for (int i = 0; i < limit; ++i) { 1.1130 + scratch[i] = next_ucs4_proc(&chars); 1.1131 + } 1.1132 + fDWriteFontFace->GetGlyphIndices(scratch, limit, &glyphs[baseGlyph]); 1.1133 + } 1.1134 + break; 1.1135 + } 1.1136 + case SkTypeface::kUTF32_Encoding: { 1.1137 + const UINT32* utf32 = reinterpret_cast<const UINT32*>(chars); 1.1138 + fDWriteFontFace->GetGlyphIndices(utf32, glyphCount, glyphs); 1.1139 + break; 1.1140 + } 1.1141 + default: 1.1142 + SK_CRASH(); 1.1143 + } 1.1144 + 1.1145 + for (int i = 0; i < glyphCount; ++i) { 1.1146 + if (0 == glyphs[i]) { 1.1147 + return i; 1.1148 + } 1.1149 + } 1.1150 + return glyphCount; 1.1151 +} 1.1152 + 1.1153 +int DWriteFontTypeface::onCountGlyphs() const { 1.1154 + return fDWriteFontFace->GetGlyphCount(); 1.1155 +} 1.1156 + 1.1157 +int DWriteFontTypeface::onGetUPEM() const { 1.1158 + DWRITE_FONT_METRICS metrics; 1.1159 + fDWriteFontFace->GetMetrics(&metrics); 1.1160 + return metrics.designUnitsPerEm; 1.1161 +} 1.1162 + 1.1163 +class LocalizedStrings_IDWriteLocalizedStrings : public SkTypeface::LocalizedStrings { 1.1164 +public: 1.1165 + /** Takes ownership of the IDWriteLocalizedStrings. */ 1.1166 + explicit LocalizedStrings_IDWriteLocalizedStrings(IDWriteLocalizedStrings* strings) 1.1167 + : fIndex(0), fStrings(strings) 1.1168 + { } 1.1169 + 1.1170 + virtual bool next(SkTypeface::LocalizedString* localizedString) SK_OVERRIDE { 1.1171 + if (fIndex >= fStrings->GetCount()) { 1.1172 + return false; 1.1173 + } 1.1174 + 1.1175 + // String 1.1176 + UINT32 stringLength; 1.1177 + HRBM(fStrings->GetStringLength(fIndex, &stringLength), "Could not get string length."); 1.1178 + stringLength += 1; 1.1179 + 1.1180 + SkSMallocWCHAR wString(stringLength); 1.1181 + HRBM(fStrings->GetString(fIndex, wString.get(), stringLength), "Could not get string."); 1.1182 + 1.1183 + HRB(wchar_to_skstring(wString.get(), &localizedString->fString)); 1.1184 + 1.1185 + // Locale 1.1186 + UINT32 localeLength; 1.1187 + HRBM(fStrings->GetLocaleNameLength(fIndex, &localeLength), "Could not get locale length."); 1.1188 + localeLength += 1; 1.1189 + 1.1190 + SkSMallocWCHAR wLocale(localeLength); 1.1191 + HRBM(fStrings->GetLocaleName(fIndex, wLocale.get(), localeLength), "Could not get locale."); 1.1192 + 1.1193 + HRB(wchar_to_skstring(wLocale.get(), &localizedString->fLanguage)); 1.1194 + 1.1195 + ++fIndex; 1.1196 + return true; 1.1197 + } 1.1198 + 1.1199 +private: 1.1200 + UINT32 fIndex; 1.1201 + SkTScopedComPtr<IDWriteLocalizedStrings> fStrings; 1.1202 +}; 1.1203 + 1.1204 +SkTypeface::LocalizedStrings* DWriteFontTypeface::onCreateFamilyNameIterator() const { 1.1205 + SkTScopedComPtr<IDWriteLocalizedStrings> familyNames; 1.1206 + HRNM(fDWriteFontFamily->GetFamilyNames(&familyNames), "Could not obtain family names."); 1.1207 + 1.1208 + return new LocalizedStrings_IDWriteLocalizedStrings(familyNames.release()); 1.1209 +} 1.1210 + 1.1211 +int DWriteFontTypeface::onGetTableTags(SkFontTableTag tags[]) const { 1.1212 + DWRITE_FONT_FACE_TYPE type = fDWriteFontFace->GetType(); 1.1213 + if (type != DWRITE_FONT_FACE_TYPE_CFF && 1.1214 + type != DWRITE_FONT_FACE_TYPE_TRUETYPE && 1.1215 + type != DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION) 1.1216 + { 1.1217 + return 0; 1.1218 + } 1.1219 + 1.1220 + int ttcIndex; 1.1221 + SkAutoTUnref<SkStream> stream(this->openStream(&ttcIndex)); 1.1222 + return stream.get() ? SkFontStream::GetTableTags(stream, ttcIndex, tags) : 0; 1.1223 +} 1.1224 + 1.1225 +class AutoDWriteTable { 1.1226 +public: 1.1227 + AutoDWriteTable(IDWriteFontFace* fontFace, UINT32 beTag) : fFontFace(fontFace), fExists(FALSE) { 1.1228 + // Any errors are ignored, user must check fExists anyway. 1.1229 + fontFace->TryGetFontTable(beTag, 1.1230 + reinterpret_cast<const void **>(&fData), &fSize, &fLock, &fExists); 1.1231 + } 1.1232 + ~AutoDWriteTable() { 1.1233 + if (fExists) { 1.1234 + fFontFace->ReleaseFontTable(fLock); 1.1235 + } 1.1236 + } 1.1237 + 1.1238 + const uint8_t* fData; 1.1239 + UINT32 fSize; 1.1240 + BOOL fExists; 1.1241 +private: 1.1242 + // Borrowed reference, the user must ensure the fontFace stays alive. 1.1243 + IDWriteFontFace* fFontFace; 1.1244 + void* fLock; 1.1245 +}; 1.1246 + 1.1247 +size_t DWriteFontTypeface::onGetTableData(SkFontTableTag tag, size_t offset, 1.1248 + size_t length, void* data) const 1.1249 +{ 1.1250 + AutoDWriteTable table(fDWriteFontFace.get(), SkEndian_SwapBE32(tag)); 1.1251 + if (!table.fExists) { 1.1252 + return 0; 1.1253 + } 1.1254 + 1.1255 + if (offset > table.fSize) { 1.1256 + return 0; 1.1257 + } 1.1258 + size_t size = SkTMin(length, table.fSize - offset); 1.1259 + if (NULL != data) { 1.1260 + memcpy(data, table.fData + offset, size); 1.1261 + } 1.1262 + 1.1263 + return size; 1.1264 +} 1.1265 + 1.1266 +template <typename T> class SkAutoIDWriteUnregister { 1.1267 +public: 1.1268 + SkAutoIDWriteUnregister(IDWriteFactory* factory, T* unregister) 1.1269 + : fFactory(factory), fUnregister(unregister) 1.1270 + { } 1.1271 + 1.1272 + ~SkAutoIDWriteUnregister() { 1.1273 + if (fUnregister) { 1.1274 + unregister(fFactory, fUnregister); 1.1275 + } 1.1276 + } 1.1277 + 1.1278 + T* detatch() { 1.1279 + T* old = fUnregister; 1.1280 + fUnregister = NULL; 1.1281 + return old; 1.1282 + } 1.1283 + 1.1284 +private: 1.1285 + HRESULT unregister(IDWriteFactory* factory, IDWriteFontFileLoader* unregister) { 1.1286 + return factory->UnregisterFontFileLoader(unregister); 1.1287 + } 1.1288 + 1.1289 + HRESULT unregister(IDWriteFactory* factory, IDWriteFontCollectionLoader* unregister) { 1.1290 + return factory->UnregisterFontCollectionLoader(unregister); 1.1291 + } 1.1292 + 1.1293 + IDWriteFactory* fFactory; 1.1294 + T* fUnregister; 1.1295 +}; 1.1296 + 1.1297 +static SkTypeface* create_from_stream(SkStream* stream, int ttcIndex) { 1.1298 + IDWriteFactory* factory = get_dwrite_factory(); 1.1299 + if (NULL == factory) { 1.1300 + return NULL; 1.1301 + } 1.1302 + 1.1303 + SkTScopedComPtr<StreamFontFileLoader> fontFileLoader; 1.1304 + HRN(StreamFontFileLoader::Create(stream, &fontFileLoader)); 1.1305 + HRN(factory->RegisterFontFileLoader(fontFileLoader.get())); 1.1306 + SkAutoIDWriteUnregister<StreamFontFileLoader> autoUnregisterFontFileLoader( 1.1307 + factory, fontFileLoader.get()); 1.1308 + 1.1309 + SkTScopedComPtr<StreamFontCollectionLoader> fontCollectionLoader; 1.1310 + HRN(StreamFontCollectionLoader::Create(fontFileLoader.get(), &fontCollectionLoader)); 1.1311 + HRN(factory->RegisterFontCollectionLoader(fontCollectionLoader.get())); 1.1312 + SkAutoIDWriteUnregister<StreamFontCollectionLoader> autoUnregisterFontCollectionLoader( 1.1313 + factory, fontCollectionLoader.get()); 1.1314 + 1.1315 + SkTScopedComPtr<IDWriteFontCollection> fontCollection; 1.1316 + HRN(factory->CreateCustomFontCollection(fontCollectionLoader.get(), NULL, 0, &fontCollection)); 1.1317 + 1.1318 + // Find the first non-simulated font which has the given ttc index. 1.1319 + UINT32 familyCount = fontCollection->GetFontFamilyCount(); 1.1320 + for (UINT32 familyIndex = 0; familyIndex < familyCount; ++familyIndex) { 1.1321 + SkTScopedComPtr<IDWriteFontFamily> fontFamily; 1.1322 + HRN(fontCollection->GetFontFamily(familyIndex, &fontFamily)); 1.1323 + 1.1324 + UINT32 fontCount = fontFamily->GetFontCount(); 1.1325 + for (UINT32 fontIndex = 0; fontIndex < fontCount; ++fontIndex) { 1.1326 + SkTScopedComPtr<IDWriteFont> font; 1.1327 + HRN(fontFamily->GetFont(fontIndex, &font)); 1.1328 + if (font->GetSimulations() != DWRITE_FONT_SIMULATIONS_NONE) { 1.1329 + continue; 1.1330 + } 1.1331 + 1.1332 + SkTScopedComPtr<IDWriteFontFace> fontFace; 1.1333 + HRN(font->CreateFontFace(&fontFace)); 1.1334 + 1.1335 + UINT32 faceIndex = fontFace->GetIndex(); 1.1336 + if (faceIndex == ttcIndex) { 1.1337 + return DWriteFontTypeface::Create(fontFace.get(), font.get(), fontFamily.get(), 1.1338 + autoUnregisterFontFileLoader.detatch(), 1.1339 + autoUnregisterFontCollectionLoader.detatch()); 1.1340 + } 1.1341 + } 1.1342 + } 1.1343 + 1.1344 + return NULL; 1.1345 +} 1.1346 + 1.1347 +SkStream* DWriteFontTypeface::onOpenStream(int* ttcIndex) const { 1.1348 + *ttcIndex = fDWriteFontFace->GetIndex(); 1.1349 + 1.1350 + UINT32 numFiles; 1.1351 + HRNM(fDWriteFontFace->GetFiles(&numFiles, NULL), 1.1352 + "Could not get number of font files."); 1.1353 + if (numFiles != 1) { 1.1354 + return NULL; 1.1355 + } 1.1356 + 1.1357 + SkTScopedComPtr<IDWriteFontFile> fontFile; 1.1358 + HRNM(fDWriteFontFace->GetFiles(&numFiles, &fontFile), "Could not get font files."); 1.1359 + 1.1360 + const void* fontFileKey; 1.1361 + UINT32 fontFileKeySize; 1.1362 + HRNM(fontFile->GetReferenceKey(&fontFileKey, &fontFileKeySize), 1.1363 + "Could not get font file reference key."); 1.1364 + 1.1365 + SkTScopedComPtr<IDWriteFontFileLoader> fontFileLoader; 1.1366 + HRNM(fontFile->GetLoader(&fontFileLoader), "Could not get font file loader."); 1.1367 + 1.1368 + SkTScopedComPtr<IDWriteFontFileStream> fontFileStream; 1.1369 + HRNM(fontFileLoader->CreateStreamFromKey(fontFileKey, fontFileKeySize, 1.1370 + &fontFileStream), 1.1371 + "Could not create font file stream."); 1.1372 + 1.1373 + return SkNEW_ARGS(SkDWriteFontFileStream, (fontFileStream.get())); 1.1374 +} 1.1375 + 1.1376 +SkScalerContext* DWriteFontTypeface::onCreateScalerContext(const SkDescriptor* desc) const { 1.1377 + return SkNEW_ARGS(SkScalerContext_DW, (const_cast<DWriteFontTypeface*>(this), desc)); 1.1378 +} 1.1379 + 1.1380 +void DWriteFontTypeface::onFilterRec(SkScalerContext::Rec* rec) const { 1.1381 + if (rec->fFlags & SkScalerContext::kLCD_BGROrder_Flag || 1.1382 + rec->fFlags & SkScalerContext::kLCD_Vertical_Flag) 1.1383 + { 1.1384 + rec->fMaskFormat = SkMask::kA8_Format; 1.1385 + } 1.1386 + 1.1387 + unsigned flagsWeDontSupport = SkScalerContext::kDevKernText_Flag | 1.1388 + SkScalerContext::kForceAutohinting_Flag | 1.1389 + SkScalerContext::kEmbeddedBitmapText_Flag | 1.1390 + SkScalerContext::kEmbolden_Flag | 1.1391 + SkScalerContext::kLCD_BGROrder_Flag | 1.1392 + SkScalerContext::kLCD_Vertical_Flag; 1.1393 + rec->fFlags &= ~flagsWeDontSupport; 1.1394 + 1.1395 + SkPaint::Hinting h = rec->getHinting(); 1.1396 + // DirectWrite does not provide for hinting hints. 1.1397 + h = SkPaint::kSlight_Hinting; 1.1398 + rec->setHinting(h); 1.1399 + 1.1400 +#if SK_FONT_HOST_USE_SYSTEM_SETTINGS 1.1401 + IDWriteFactory* factory = get_dwrite_factory(); 1.1402 + if (factory != NULL) { 1.1403 + SkTScopedComPtr<IDWriteRenderingParams> defaultRenderingParams; 1.1404 + if (SUCCEEDED(factory->CreateRenderingParams(&defaultRenderingParams))) { 1.1405 + float gamma = defaultRenderingParams->GetGamma(); 1.1406 + rec->setDeviceGamma(gamma); 1.1407 + rec->setPaintGamma(gamma); 1.1408 + 1.1409 + rec->setContrast(defaultRenderingParams->GetEnhancedContrast()); 1.1410 + } 1.1411 + } 1.1412 +#endif 1.1413 +} 1.1414 + 1.1415 +/////////////////////////////////////////////////////////////////////////////// 1.1416 +//PDF Support 1.1417 + 1.1418 +using namespace skia_advanced_typeface_metrics_utils; 1.1419 + 1.1420 +// Construct Glyph to Unicode table. 1.1421 +// Unicode code points that require conjugate pairs in utf16 are not 1.1422 +// supported. 1.1423 +// TODO(arthurhsu): Add support for conjugate pairs. It looks like that may 1.1424 +// require parsing the TTF cmap table (platform 4, encoding 12) directly instead 1.1425 +// of calling GetFontUnicodeRange(). 1.1426 +// TODO(bungeman): This never does what anyone wants. 1.1427 +// What is really wanted is the text to glyphs mapping 1.1428 +static void populate_glyph_to_unicode(IDWriteFontFace* fontFace, 1.1429 + const unsigned glyphCount, 1.1430 + SkTDArray<SkUnichar>* glyphToUnicode) { 1.1431 + HRESULT hr = S_OK; 1.1432 + 1.1433 + //Do this like free type instead 1.1434 + UINT32 count = 0; 1.1435 + for (UINT32 c = 0; c < 0x10FFFF; ++c) { 1.1436 + UINT16 glyph; 1.1437 + hr = fontFace->GetGlyphIndices(&c, 1, &glyph); 1.1438 + if (glyph > 0) { 1.1439 + ++count; 1.1440 + } 1.1441 + } 1.1442 + 1.1443 + SkAutoTArray<UINT32> chars(count); 1.1444 + count = 0; 1.1445 + for (UINT32 c = 0; c < 0x10FFFF; ++c) { 1.1446 + UINT16 glyph; 1.1447 + hr = fontFace->GetGlyphIndices(&c, 1, &glyph); 1.1448 + if (glyph > 0) { 1.1449 + chars[count] = c; 1.1450 + ++count; 1.1451 + } 1.1452 + } 1.1453 + 1.1454 + SkAutoTArray<UINT16> glyph(count); 1.1455 + fontFace->GetGlyphIndices(chars.get(), count, glyph.get()); 1.1456 + 1.1457 + USHORT maxGlyph = 0; 1.1458 + for (USHORT j = 0; j < count; ++j) { 1.1459 + if (glyph[j] > maxGlyph) maxGlyph = glyph[j]; 1.1460 + } 1.1461 + 1.1462 + glyphToUnicode->setCount(maxGlyph+1); 1.1463 + for (USHORT j = 0; j < maxGlyph+1u; ++j) { 1.1464 + (*glyphToUnicode)[j] = 0; 1.1465 + } 1.1466 + 1.1467 + //'invert' 1.1468 + for (USHORT j = 0; j < count; ++j) { 1.1469 + if (glyph[j] < glyphCount && (*glyphToUnicode)[glyph[j]] == 0) { 1.1470 + (*glyphToUnicode)[glyph[j]] = chars[j]; 1.1471 + } 1.1472 + } 1.1473 +} 1.1474 + 1.1475 +static bool getWidthAdvance(IDWriteFontFace* fontFace, int gId, int16_t* advance) { 1.1476 + SkASSERT(advance); 1.1477 + 1.1478 + UINT16 glyphId = gId; 1.1479 + DWRITE_GLYPH_METRICS gm; 1.1480 + HRESULT hr = fontFace->GetDesignGlyphMetrics(&glyphId, 1, &gm); 1.1481 + 1.1482 + if (FAILED(hr)) { 1.1483 + *advance = 0; 1.1484 + return false; 1.1485 + } 1.1486 + 1.1487 + *advance = gm.advanceWidth; 1.1488 + return true; 1.1489 +} 1.1490 + 1.1491 +template<typename T> class AutoTDWriteTable : public AutoDWriteTable { 1.1492 +public: 1.1493 + static const UINT32 tag = DWRITE_MAKE_OPENTYPE_TAG(T::TAG0, T::TAG1, T::TAG2, T::TAG3); 1.1494 + AutoTDWriteTable(IDWriteFontFace* fontFace) : AutoDWriteTable(fontFace, tag) { } 1.1495 + 1.1496 + const T* operator->() const { return reinterpret_cast<const T*>(fData); } 1.1497 +}; 1.1498 + 1.1499 +SkAdvancedTypefaceMetrics* DWriteFontTypeface::onGetAdvancedTypefaceMetrics( 1.1500 + SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo, 1.1501 + const uint32_t* glyphIDs, 1.1502 + uint32_t glyphIDsCount) const { 1.1503 + 1.1504 + SkAdvancedTypefaceMetrics* info = NULL; 1.1505 + 1.1506 + HRESULT hr = S_OK; 1.1507 + 1.1508 + const unsigned glyphCount = fDWriteFontFace->GetGlyphCount(); 1.1509 + 1.1510 + DWRITE_FONT_METRICS dwfm; 1.1511 + fDWriteFontFace->GetMetrics(&dwfm); 1.1512 + 1.1513 + info = new SkAdvancedTypefaceMetrics; 1.1514 + info->fEmSize = dwfm.designUnitsPerEm; 1.1515 + info->fMultiMaster = false; 1.1516 + info->fLastGlyphID = SkToU16(glyphCount - 1); 1.1517 + info->fStyle = 0; 1.1518 + 1.1519 + 1.1520 + SkTScopedComPtr<IDWriteLocalizedStrings> familyNames; 1.1521 + SkTScopedComPtr<IDWriteLocalizedStrings> faceNames; 1.1522 + hr = fDWriteFontFamily->GetFamilyNames(&familyNames); 1.1523 + hr = fDWriteFont->GetFaceNames(&faceNames); 1.1524 + 1.1525 + UINT32 familyNameLength; 1.1526 + hr = familyNames->GetStringLength(0, &familyNameLength); 1.1527 + 1.1528 + UINT32 faceNameLength; 1.1529 + hr = faceNames->GetStringLength(0, &faceNameLength); 1.1530 + 1.1531 + UINT32 size = familyNameLength+1+faceNameLength+1; 1.1532 + SkSMallocWCHAR wFamilyName(size); 1.1533 + hr = familyNames->GetString(0, wFamilyName.get(), size); 1.1534 + wFamilyName[familyNameLength] = L' '; 1.1535 + hr = faceNames->GetString(0, &wFamilyName[familyNameLength+1], size - faceNameLength + 1); 1.1536 + 1.1537 + hr = wchar_to_skstring(wFamilyName.get(), &info->fFontName); 1.1538 + 1.1539 + if (perGlyphInfo & SkAdvancedTypefaceMetrics::kToUnicode_PerGlyphInfo) { 1.1540 + populate_glyph_to_unicode(fDWriteFontFace.get(), glyphCount, &(info->fGlyphToUnicode)); 1.1541 + } 1.1542 + 1.1543 + DWRITE_FONT_FACE_TYPE fontType = fDWriteFontFace->GetType(); 1.1544 + if (fontType == DWRITE_FONT_FACE_TYPE_TRUETYPE || 1.1545 + fontType == DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION) { 1.1546 + info->fType = SkAdvancedTypefaceMetrics::kTrueType_Font; 1.1547 + } else { 1.1548 + info->fType = SkAdvancedTypefaceMetrics::kOther_Font; 1.1549 + info->fItalicAngle = 0; 1.1550 + info->fAscent = dwfm.ascent;; 1.1551 + info->fDescent = dwfm.descent; 1.1552 + info->fStemV = 0; 1.1553 + info->fCapHeight = dwfm.capHeight; 1.1554 + info->fBBox = SkIRect::MakeEmpty(); 1.1555 + return info; 1.1556 + } 1.1557 + 1.1558 + AutoTDWriteTable<SkOTTableHead> headTable(fDWriteFontFace.get()); 1.1559 + AutoTDWriteTable<SkOTTablePostScript> postTable(fDWriteFontFace.get()); 1.1560 + AutoTDWriteTable<SkOTTableHorizontalHeader> hheaTable(fDWriteFontFace.get()); 1.1561 + AutoTDWriteTable<SkOTTableOS2> os2Table(fDWriteFontFace.get()); 1.1562 + if (!headTable.fExists || !postTable.fExists || !hheaTable.fExists || !os2Table.fExists) { 1.1563 + info->fItalicAngle = 0; 1.1564 + info->fAscent = dwfm.ascent;; 1.1565 + info->fDescent = dwfm.descent; 1.1566 + info->fStemV = 0; 1.1567 + info->fCapHeight = dwfm.capHeight; 1.1568 + info->fBBox = SkIRect::MakeEmpty(); 1.1569 + return info; 1.1570 + } 1.1571 + 1.1572 + //There exist CJK fonts which set the IsFixedPitch and Monospace bits, 1.1573 + //but have full width, latin half-width, and half-width kana. 1.1574 + bool fixedWidth = (postTable->isFixedPitch && 1.1575 + (1 == SkEndian_SwapBE16(hheaTable->numberOfHMetrics))); 1.1576 + //Monospace 1.1577 + if (fixedWidth) { 1.1578 + info->fStyle |= SkAdvancedTypefaceMetrics::kFixedPitch_Style; 1.1579 + } 1.1580 + //Italic 1.1581 + if (os2Table->version.v0.fsSelection.field.Italic) { 1.1582 + info->fStyle |= SkAdvancedTypefaceMetrics::kItalic_Style; 1.1583 + } 1.1584 + //Script 1.1585 + if (SkPanose::FamilyType::Script == os2Table->version.v0.panose.bFamilyType.value) { 1.1586 + info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style; 1.1587 + //Serif 1.1588 + } else if (SkPanose::FamilyType::TextAndDisplay == os2Table->version.v0.panose.bFamilyType.value && 1.1589 + SkPanose::Data::TextAndDisplay::SerifStyle::Triangle <= os2Table->version.v0.panose.data.textAndDisplay.bSerifStyle.value && 1.1590 + SkPanose::Data::TextAndDisplay::SerifStyle::NoFit != os2Table->version.v0.panose.data.textAndDisplay.bSerifStyle.value) { 1.1591 + info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style; 1.1592 + } 1.1593 + 1.1594 + info->fItalicAngle = SkEndian_SwapBE32(postTable->italicAngle) >> 16; 1.1595 + 1.1596 + info->fAscent = SkToS16(dwfm.ascent); 1.1597 + info->fDescent = SkToS16(dwfm.descent); 1.1598 + info->fCapHeight = SkToS16(dwfm.capHeight); 1.1599 + 1.1600 + info->fBBox = SkIRect::MakeLTRB((int32_t)SkEndian_SwapBE16((uint16_t)headTable->xMin), 1.1601 + (int32_t)SkEndian_SwapBE16((uint16_t)headTable->yMax), 1.1602 + (int32_t)SkEndian_SwapBE16((uint16_t)headTable->xMax), 1.1603 + (int32_t)SkEndian_SwapBE16((uint16_t)headTable->yMin)); 1.1604 + 1.1605 + //TODO: is this even desired? It seems PDF only wants this value for Type1 1.1606 + //fonts, and we only get here for TrueType fonts. 1.1607 + info->fStemV = 0; 1.1608 + /* 1.1609 + // Figure out a good guess for StemV - Min width of i, I, !, 1. 1.1610 + // This probably isn't very good with an italic font. 1.1611 + int16_t min_width = SHRT_MAX; 1.1612 + info->fStemV = 0; 1.1613 + char stem_chars[] = {'i', 'I', '!', '1'}; 1.1614 + for (size_t i = 0; i < SK_ARRAY_COUNT(stem_chars); i++) { 1.1615 + ABC abcWidths; 1.1616 + if (GetCharABCWidths(hdc, stem_chars[i], stem_chars[i], &abcWidths)) { 1.1617 + int16_t width = abcWidths.abcB; 1.1618 + if (width > 0 && width < min_width) { 1.1619 + min_width = width; 1.1620 + info->fStemV = min_width; 1.1621 + } 1.1622 + } 1.1623 + } 1.1624 + */ 1.1625 + 1.1626 + // If Restricted, the font may not be embedded in a document. 1.1627 + // If not Restricted, the font can be embedded. 1.1628 + // If PreviewPrint, the embedding is read-only. 1.1629 + if (os2Table->version.v0.fsType.field.Restricted) { 1.1630 + info->fType = SkAdvancedTypefaceMetrics::kNotEmbeddable_Font; 1.1631 + } else if (perGlyphInfo & SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo) { 1.1632 + if (fixedWidth) { 1.1633 + appendRange(&info->fGlyphWidths, 0); 1.1634 + int16_t advance; 1.1635 + getWidthAdvance(fDWriteFontFace.get(), 1, &advance); 1.1636 + info->fGlyphWidths->fAdvance.append(1, &advance); 1.1637 + finishRange(info->fGlyphWidths.get(), 0, 1.1638 + SkAdvancedTypefaceMetrics::WidthRange::kDefault); 1.1639 + } else { 1.1640 + info->fGlyphWidths.reset( 1.1641 + getAdvanceData(fDWriteFontFace.get(), 1.1642 + glyphCount, 1.1643 + glyphIDs, 1.1644 + glyphIDsCount, 1.1645 + getWidthAdvance)); 1.1646 + } 1.1647 + } 1.1648 + 1.1649 + return info; 1.1650 +} 1.1651 + 1.1652 +/////////////////////////////////////////////////////////////////////////////// 1.1653 + 1.1654 +static void get_locale_string(IDWriteLocalizedStrings* names, const WCHAR* preferedLocale, 1.1655 + SkString* skname) { 1.1656 + UINT32 nameIndex = 0; 1.1657 + if (preferedLocale) { 1.1658 + // Ignore any errors and continue with index 0 if there is a problem. 1.1659 + BOOL nameExists; 1.1660 + names->FindLocaleName(preferedLocale, &nameIndex, &nameExists); 1.1661 + if (!nameExists) { 1.1662 + nameIndex = 0; 1.1663 + } 1.1664 + } 1.1665 + 1.1666 + UINT32 nameLength; 1.1667 + HRVM(names->GetStringLength(nameIndex, &nameLength), "Could not get name length."); 1.1668 + nameLength += 1; 1.1669 + 1.1670 + SkSMallocWCHAR name(nameLength); 1.1671 + HRVM(names->GetString(nameIndex, name.get(), nameLength), "Could not get string."); 1.1672 + 1.1673 + HRV(wchar_to_skstring(name.get(), skname)); 1.1674 +} 1.1675 + 1.1676 +SkTypeface* SkFontMgr_DirectWrite::createTypefaceFromDWriteFont( 1.1677 + IDWriteFontFace* fontFace, 1.1678 + IDWriteFont* font, 1.1679 + IDWriteFontFamily* fontFamily, 1.1680 + StreamFontFileLoader* fontFileLoader, 1.1681 + IDWriteFontCollectionLoader* fontCollectionLoader) const { 1.1682 + SkTypeface* face = FindByProcAndRef(FindByDWriteFont, font); 1.1683 + if (NULL == face) { 1.1684 + face = DWriteFontTypeface::Create(fontFace, font, fontFamily, 1.1685 + fontFileLoader, fontCollectionLoader); 1.1686 + if (face) { 1.1687 + Add(face, get_style(font), fontCollectionLoader != NULL); 1.1688 + } 1.1689 + } 1.1690 + return face; 1.1691 +} 1.1692 + 1.1693 +int SkFontMgr_DirectWrite::onCountFamilies() const { 1.1694 + return fFontCollection->GetFontFamilyCount(); 1.1695 +} 1.1696 + 1.1697 +void SkFontMgr_DirectWrite::onGetFamilyName(int index, SkString* familyName) const { 1.1698 + SkTScopedComPtr<IDWriteFontFamily> fontFamily; 1.1699 + HRVM(fFontCollection->GetFontFamily(index, &fontFamily), "Could not get requested family."); 1.1700 + 1.1701 + SkTScopedComPtr<IDWriteLocalizedStrings> familyNames; 1.1702 + HRVM(fontFamily->GetFamilyNames(&familyNames), "Could not get family names."); 1.1703 + 1.1704 + get_locale_string(familyNames.get(), fLocaleName.get(), familyName); 1.1705 +} 1.1706 + 1.1707 +SkFontStyleSet* SkFontMgr_DirectWrite::onCreateStyleSet(int index) const { 1.1708 + SkTScopedComPtr<IDWriteFontFamily> fontFamily; 1.1709 + HRNM(fFontCollection->GetFontFamily(index, &fontFamily), "Could not get requested family."); 1.1710 + 1.1711 + return SkNEW_ARGS(SkFontStyleSet_DirectWrite, (this, fontFamily.get())); 1.1712 +} 1.1713 + 1.1714 +SkFontStyleSet* SkFontMgr_DirectWrite::onMatchFamily(const char familyName[]) const { 1.1715 + SkSMallocWCHAR dwFamilyName; 1.1716 + HRN(cstring_to_wchar(familyName, &dwFamilyName)); 1.1717 + 1.1718 + UINT32 index; 1.1719 + BOOL exists; 1.1720 + HRNM(fFontCollection->FindFamilyName(dwFamilyName.get(), &index, &exists), 1.1721 + "Failed while finding family by name."); 1.1722 + if (!exists) { 1.1723 + return NULL; 1.1724 + } 1.1725 + 1.1726 + return this->onCreateStyleSet(index); 1.1727 +} 1.1728 + 1.1729 +SkTypeface* SkFontMgr_DirectWrite::onMatchFamilyStyle(const char familyName[], 1.1730 + const SkFontStyle& fontstyle) const { 1.1731 + SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName)); 1.1732 + return sset->matchStyle(fontstyle); 1.1733 +} 1.1734 + 1.1735 +SkTypeface* SkFontMgr_DirectWrite::onMatchFaceStyle(const SkTypeface* familyMember, 1.1736 + const SkFontStyle& fontstyle) const { 1.1737 + SkString familyName; 1.1738 + SkFontStyleSet_DirectWrite sset( 1.1739 + this, ((DWriteFontTypeface*)familyMember)->fDWriteFontFamily.get() 1.1740 + ); 1.1741 + return sset.matchStyle(fontstyle); 1.1742 +} 1.1743 + 1.1744 +SkTypeface* SkFontMgr_DirectWrite::onCreateFromStream(SkStream* stream, int ttcIndex) const { 1.1745 + return create_from_stream(stream, ttcIndex); 1.1746 +} 1.1747 + 1.1748 +SkTypeface* SkFontMgr_DirectWrite::onCreateFromData(SkData* data, int ttcIndex) const { 1.1749 + SkAutoTUnref<SkStream> stream(SkNEW_ARGS(SkMemoryStream, (data))); 1.1750 + return this->createFromStream(stream, ttcIndex); 1.1751 +} 1.1752 + 1.1753 +SkTypeface* SkFontMgr_DirectWrite::onCreateFromFile(const char path[], int ttcIndex) const { 1.1754 + SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path)); 1.1755 + return this->createFromStream(stream, ttcIndex); 1.1756 +} 1.1757 + 1.1758 +HRESULT SkFontMgr_DirectWrite::getByFamilyName(const WCHAR wideFamilyName[], 1.1759 + IDWriteFontFamily** fontFamily) const { 1.1760 + UINT32 index; 1.1761 + BOOL exists; 1.1762 + HR(fFontCollection->FindFamilyName(wideFamilyName, &index, &exists)); 1.1763 + 1.1764 + if (exists) { 1.1765 + HR(fFontCollection->GetFontFamily(index, fontFamily)); 1.1766 + return S_OK; 1.1767 + } 1.1768 + return S_FALSE; 1.1769 +} 1.1770 + 1.1771 +HRESULT SkFontMgr_DirectWrite::getDefaultFontFamily(IDWriteFontFamily** fontFamily) const { 1.1772 + NONCLIENTMETRICSW metrics; 1.1773 + metrics.cbSize = sizeof(metrics); 1.1774 + if (0 == SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, 1.1775 + sizeof(metrics), 1.1776 + &metrics, 1.1777 + 0)) { 1.1778 + return E_UNEXPECTED; 1.1779 + } 1.1780 + HRM(this->getByFamilyName(metrics.lfMessageFont.lfFaceName, fontFamily), 1.1781 + "Could not create DWrite font family from LOGFONT."); 1.1782 + 1.1783 + return S_OK; 1.1784 +} 1.1785 + 1.1786 +SkTypeface* SkFontMgr_DirectWrite::onLegacyCreateTypeface(const char familyName[], 1.1787 + unsigned styleBits) const { 1.1788 + SkTScopedComPtr<IDWriteFontFamily> fontFamily; 1.1789 + if (familyName) { 1.1790 + SkSMallocWCHAR wideFamilyName; 1.1791 + if (SUCCEEDED(cstring_to_wchar(familyName, &wideFamilyName))) { 1.1792 + this->getByFamilyName(wideFamilyName, &fontFamily); 1.1793 + } 1.1794 + } 1.1795 + 1.1796 + if (NULL == fontFamily.get()) { 1.1797 + // No family with given name, try default. 1.1798 + HRNM(this->getDefaultFontFamily(&fontFamily), "Could not get default font family."); 1.1799 + } 1.1800 + 1.1801 + SkTScopedComPtr<IDWriteFont> font; 1.1802 + DWRITE_FONT_WEIGHT weight = (styleBits & SkTypeface::kBold) 1.1803 + ? DWRITE_FONT_WEIGHT_BOLD 1.1804 + : DWRITE_FONT_WEIGHT_NORMAL; 1.1805 + DWRITE_FONT_STRETCH stretch = DWRITE_FONT_STRETCH_NORMAL; 1.1806 + DWRITE_FONT_STYLE italic = (styleBits & SkTypeface::kItalic) 1.1807 + ? DWRITE_FONT_STYLE_ITALIC 1.1808 + : DWRITE_FONT_STYLE_NORMAL; 1.1809 + HRNM(fontFamily->GetFirstMatchingFont(weight, stretch, italic, &font), 1.1810 + "Could not get matching font."); 1.1811 + 1.1812 + SkTScopedComPtr<IDWriteFontFace> fontFace; 1.1813 + HRNM(font->CreateFontFace(&fontFace), "Could not create font face."); 1.1814 + 1.1815 + return this->createTypefaceFromDWriteFont(fontFace.get(), font.get(), fontFamily.get()); 1.1816 +} 1.1817 + 1.1818 +/////////////////////////////////////////////////////////////////////////////// 1.1819 + 1.1820 +int SkFontStyleSet_DirectWrite::count() { 1.1821 + return fFontFamily->GetFontCount(); 1.1822 +} 1.1823 + 1.1824 +SkTypeface* SkFontStyleSet_DirectWrite::createTypeface(int index) { 1.1825 + SkTScopedComPtr<IDWriteFont> font; 1.1826 + HRNM(fFontFamily->GetFont(index, &font), "Could not get font."); 1.1827 + 1.1828 + SkTScopedComPtr<IDWriteFontFace> fontFace; 1.1829 + HRNM(font->CreateFontFace(&fontFace), "Could not create font face."); 1.1830 + 1.1831 + return fFontMgr->createTypefaceFromDWriteFont(fontFace.get(), font.get(), fFontFamily.get()); 1.1832 +} 1.1833 + 1.1834 +void SkFontStyleSet_DirectWrite::getStyle(int index, SkFontStyle* fs, SkString* styleName) { 1.1835 + SkTScopedComPtr<IDWriteFont> font; 1.1836 + HRVM(fFontFamily->GetFont(index, &font), "Could not get font."); 1.1837 + 1.1838 + SkFontStyle::Slant slant; 1.1839 + switch (font->GetStyle()) { 1.1840 + case DWRITE_FONT_STYLE_NORMAL: 1.1841 + slant = SkFontStyle::kUpright_Slant; 1.1842 + break; 1.1843 + case DWRITE_FONT_STYLE_OBLIQUE: 1.1844 + case DWRITE_FONT_STYLE_ITALIC: 1.1845 + slant = SkFontStyle::kItalic_Slant; 1.1846 + break; 1.1847 + default: 1.1848 + SkASSERT(false); 1.1849 + } 1.1850 + 1.1851 + int weight = font->GetWeight(); 1.1852 + int width = font->GetStretch(); 1.1853 + 1.1854 + *fs = SkFontStyle(weight, width, slant); 1.1855 + 1.1856 + SkTScopedComPtr<IDWriteLocalizedStrings> faceNames; 1.1857 + if (SUCCEEDED(font->GetFaceNames(&faceNames))) { 1.1858 + get_locale_string(faceNames.get(), fFontMgr->fLocaleName.get(), styleName); 1.1859 + } 1.1860 +} 1.1861 + 1.1862 +SkTypeface* SkFontStyleSet_DirectWrite::matchStyle(const SkFontStyle& pattern) { 1.1863 + DWRITE_FONT_STYLE slant; 1.1864 + switch (pattern.slant()) { 1.1865 + case SkFontStyle::kUpright_Slant: 1.1866 + slant = DWRITE_FONT_STYLE_NORMAL; 1.1867 + break; 1.1868 + case SkFontStyle::kItalic_Slant: 1.1869 + slant = DWRITE_FONT_STYLE_ITALIC; 1.1870 + break; 1.1871 + default: 1.1872 + SkASSERT(false); 1.1873 + } 1.1874 + 1.1875 + DWRITE_FONT_WEIGHT weight = (DWRITE_FONT_WEIGHT)pattern.weight(); 1.1876 + DWRITE_FONT_STRETCH width = (DWRITE_FONT_STRETCH)pattern.width(); 1.1877 + 1.1878 + SkTScopedComPtr<IDWriteFont> font; 1.1879 + // TODO: perhaps use GetMatchingFonts and get the least simulated? 1.1880 + HRNM(fFontFamily->GetFirstMatchingFont(weight, width, slant, &font), 1.1881 + "Could not match font in family."); 1.1882 + 1.1883 + SkTScopedComPtr<IDWriteFontFace> fontFace; 1.1884 + HRNM(font->CreateFontFace(&fontFace), "Could not create font face."); 1.1885 + 1.1886 + return fFontMgr->createTypefaceFromDWriteFont(fontFace.get(), font.get(), 1.1887 + fFontFamily.get()); 1.1888 +} 1.1889 + 1.1890 +/////////////////////////////////////////////////////////////////////////////// 1.1891 + 1.1892 +typedef decltype(GetUserDefaultLocaleName)* GetUserDefaultLocaleNameProc; 1.1893 +static HRESULT GetGetUserDefaultLocaleNameProc(GetUserDefaultLocaleNameProc* proc) { 1.1894 + *proc = reinterpret_cast<GetUserDefaultLocaleNameProc>( 1.1895 + GetProcAddress(LoadLibraryW(L"Kernel32.dll"), "GetUserDefaultLocaleName") 1.1896 + ); 1.1897 + if (!*proc) { 1.1898 + HRESULT hr = HRESULT_FROM_WIN32(GetLastError()); 1.1899 + if (!IS_ERROR(hr)) { 1.1900 + hr = ERROR_PROC_NOT_FOUND; 1.1901 + } 1.1902 + return hr; 1.1903 + } 1.1904 + return S_OK; 1.1905 +} 1.1906 + 1.1907 +SkFontMgr* SkFontMgr_New_DirectWrite() { 1.1908 + IDWriteFactory* factory = get_dwrite_factory(); 1.1909 + if (NULL == factory) { 1.1910 + return NULL; 1.1911 + } 1.1912 + 1.1913 + SkTScopedComPtr<IDWriteFontCollection> sysFontCollection; 1.1914 + HRNM(factory->GetSystemFontCollection(&sysFontCollection, FALSE), 1.1915 + "Could not get system font collection."); 1.1916 + 1.1917 + WCHAR localeNameStorage[LOCALE_NAME_MAX_LENGTH]; 1.1918 + WCHAR* localeName = NULL; 1.1919 + int localeNameLen = 0; 1.1920 + 1.1921 + // Dynamically load GetUserDefaultLocaleName function, as it is not available on XP. 1.1922 + GetUserDefaultLocaleNameProc getUserDefaultLocaleNameProc = NULL; 1.1923 + HRESULT hr = GetGetUserDefaultLocaleNameProc(&getUserDefaultLocaleNameProc); 1.1924 + if (NULL == getUserDefaultLocaleNameProc) { 1.1925 + SK_TRACEHR(hr, "Could not get GetUserDefaultLocaleName."); 1.1926 + } else { 1.1927 + localeNameLen = getUserDefaultLocaleNameProc(localeNameStorage, LOCALE_NAME_MAX_LENGTH); 1.1928 + if (localeNameLen) { 1.1929 + localeName = localeNameStorage; 1.1930 + }; 1.1931 + } 1.1932 + 1.1933 + return SkNEW_ARGS(SkFontMgr_DirectWrite, (sysFontCollection.get(), localeName, localeNameLen)); 1.1934 +}