Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
1 /*
2 * Copyright 2011 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
8 #include "SkTypes.h"
9 #undef GetGlyphIndices
11 #include "SkAdvancedTypefaceMetrics.h"
12 #include "SkColorFilter.h"
13 #include "SkDWriteFontFileStream.h"
14 #include "SkDWriteGeometrySink.h"
15 #include "SkDescriptor.h"
16 #include "SkEndian.h"
17 #include "SkFontDescriptor.h"
18 #include "SkFontHost.h"
19 #include "SkFontMgr.h"
20 #include "SkFontStream.h"
21 #include "SkGlyph.h"
22 #include "SkHRESULT.h"
23 #include "SkMaskGamma.h"
24 #include "SkOnce.h"
25 #include "SkOTTable_head.h"
26 #include "SkOTTable_hhea.h"
27 #include "SkOTTable_OS_2.h"
28 #include "SkOTTable_post.h"
29 #include "SkPath.h"
30 #include "SkStream.h"
31 #include "SkString.h"
32 #include "SkTScopedComPtr.h"
33 #include "SkThread.h"
34 #include "SkTypeface_win.h"
35 #include "SkTypefaceCache.h"
36 #include "SkUtils.h"
38 #include <dwrite.h>
40 static bool isLCD(const SkScalerContext::Rec& rec) {
41 return SkMask::kLCD16_Format == rec.fMaskFormat ||
42 SkMask::kLCD32_Format == rec.fMaskFormat;
43 }
45 /** Prefer to use this type to prevent template proliferation. */
46 typedef SkAutoSTMalloc<16, WCHAR> SkSMallocWCHAR;
48 /** Converts a utf8 string to a WCHAR string. */
49 static HRESULT cstring_to_wchar(const char* skname, SkSMallocWCHAR* name) {
50 int wlen = MultiByteToWideChar(CP_UTF8, 0, skname, -1, NULL, 0);
51 if (0 == wlen) {
52 HRM(HRESULT_FROM_WIN32(GetLastError()),
53 "Could not get length for wchar to utf-8 conversion.");
54 }
55 name->reset(wlen);
56 wlen = MultiByteToWideChar(CP_UTF8, 0, skname, -1, name->get(), wlen);
57 if (0 == wlen) {
58 HRM(HRESULT_FROM_WIN32(GetLastError()), "Could not convert wchar to utf-8.");
59 }
60 return S_OK;
61 }
63 /** Converts a WCHAR string to a utf8 string. */
64 static HRESULT wchar_to_skstring(WCHAR* name, SkString* skname) {
65 int len = WideCharToMultiByte(CP_UTF8, 0, name, -1, NULL, 0, NULL, NULL);
66 if (0 == len) {
67 HRM(HRESULT_FROM_WIN32(GetLastError()),
68 "Could not get length for utf-8 to wchar conversion.");
69 }
70 skname->resize(len - 1);
72 // TODO: remove after https://code.google.com/p/skia/issues/detail?id=1989 is fixed.
73 // If we resize to 0 then the skname points to gEmptyRec (the unique empty SkString::Rec).
74 // gEmptyRec is static const and on Windows this means the value is in a read only page.
75 // Writing to it in the following call to WideCharToMultiByte will cause an access violation.
76 if (1 == len) {
77 return S_OK;
78 }
80 len = WideCharToMultiByte(CP_UTF8, 0, name, -1, skname->writable_str(), len, NULL, NULL);
81 if (0 == len) {
82 HRM(HRESULT_FROM_WIN32(GetLastError()), "Could not convert utf-8 to wchar.");
83 }
84 return S_OK;
85 }
87 ///////////////////////////////////////////////////////////////////////////////
89 static void create_dwrite_factory(IDWriteFactory** factory) {
90 typedef decltype(DWriteCreateFactory)* DWriteCreateFactoryProc;
91 DWriteCreateFactoryProc dWriteCreateFactoryProc = reinterpret_cast<DWriteCreateFactoryProc>(
92 GetProcAddress(LoadLibraryW(L"dwrite.dll"), "DWriteCreateFactory"));
94 if (!dWriteCreateFactoryProc) {
95 HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
96 if (!IS_ERROR(hr)) {
97 hr = ERROR_PROC_NOT_FOUND;
98 }
99 HRVM(hr, "Could not get DWriteCreateFactory proc.");
100 }
102 HRVM(dWriteCreateFactoryProc(DWRITE_FACTORY_TYPE_SHARED,
103 __uuidof(IDWriteFactory),
104 reinterpret_cast<IUnknown**>(factory)),
105 "Could not create DirectWrite factory.");
106 }
108 static IDWriteFactory* get_dwrite_factory() {
109 static IDWriteFactory* gDWriteFactory = NULL;
110 SK_DECLARE_STATIC_ONCE(once);
111 SkOnce(&once, create_dwrite_factory, &gDWriteFactory);
113 return gDWriteFactory;
114 }
116 ///////////////////////////////////////////////////////////////////////////////
118 class StreamFontFileLoader;
120 class SkFontMgr_DirectWrite : public SkFontMgr {
121 public:
122 /** localeNameLength must include the null terminator. */
123 SkFontMgr_DirectWrite(IDWriteFontCollection* fontCollection,
124 WCHAR* localeName, int localeNameLength)
125 : fFontCollection(SkRefComPtr(fontCollection))
126 , fLocaleName(localeNameLength)
127 {
128 memcpy(fLocaleName.get(), localeName, localeNameLength * sizeof(WCHAR));
129 }
131 SkTypeface* createTypefaceFromDWriteFont(IDWriteFontFace* fontFace,
132 IDWriteFont* font,
133 IDWriteFontFamily* fontFamily,
134 StreamFontFileLoader* = NULL,
135 IDWriteFontCollectionLoader* = NULL) const;
137 protected:
138 virtual int onCountFamilies() const SK_OVERRIDE;
139 virtual void onGetFamilyName(int index, SkString* familyName) const SK_OVERRIDE;
140 virtual SkFontStyleSet* onCreateStyleSet(int index) const SK_OVERRIDE;
141 virtual SkFontStyleSet* onMatchFamily(const char familyName[]) const SK_OVERRIDE;
142 virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
143 const SkFontStyle& fontstyle) const SK_OVERRIDE;
144 virtual SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember,
145 const SkFontStyle& fontstyle) const SK_OVERRIDE;
146 virtual SkTypeface* onCreateFromStream(SkStream* stream, int ttcIndex) const SK_OVERRIDE;
147 virtual SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const SK_OVERRIDE;
148 virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const SK_OVERRIDE;
149 virtual SkTypeface* onLegacyCreateTypeface(const char familyName[],
150 unsigned styleBits) const SK_OVERRIDE;
152 private:
153 HRESULT getByFamilyName(const WCHAR familyName[], IDWriteFontFamily** fontFamily) const;
154 HRESULT getDefaultFontFamily(IDWriteFontFamily** fontFamily) const;
156 void Add(SkTypeface* face, SkTypeface::Style requestedStyle, bool strong) const {
157 SkAutoMutexAcquire ama(fTFCacheMutex);
158 fTFCache.add(face, requestedStyle, strong);
159 }
161 SkTypeface* FindByProcAndRef(SkTypefaceCache::FindProc proc, void* ctx) const {
162 SkAutoMutexAcquire ama(fTFCacheMutex);
163 SkTypeface* typeface = fTFCache.findByProcAndRef(proc, ctx);
164 return typeface;
165 }
167 SkTScopedComPtr<IDWriteFontCollection> fFontCollection;
168 SkSMallocWCHAR fLocaleName;
169 mutable SkMutex fTFCacheMutex;
170 mutable SkTypefaceCache fTFCache;
172 friend class SkFontStyleSet_DirectWrite;
173 };
175 class SkFontStyleSet_DirectWrite : public SkFontStyleSet {
176 public:
177 SkFontStyleSet_DirectWrite(const SkFontMgr_DirectWrite* fontMgr,
178 IDWriteFontFamily* fontFamily)
179 : fFontMgr(SkRef(fontMgr))
180 , fFontFamily(SkRefComPtr(fontFamily))
181 { }
183 virtual int count() SK_OVERRIDE;
184 virtual void getStyle(int index, SkFontStyle* fs, SkString* styleName) SK_OVERRIDE;
185 virtual SkTypeface* createTypeface(int index) SK_OVERRIDE;
186 virtual SkTypeface* matchStyle(const SkFontStyle& pattern) SK_OVERRIDE;
188 private:
189 SkAutoTUnref<const SkFontMgr_DirectWrite> fFontMgr;
190 SkTScopedComPtr<IDWriteFontFamily> fFontFamily;
191 };
193 ///////////////////////////////////////////////////////////////////////////////
195 class DWriteOffscreen {
196 public:
197 DWriteOffscreen() : fWidth(0), fHeight(0) {
198 }
200 void init(IDWriteFontFace* fontFace, const DWRITE_MATRIX& xform, FLOAT fontSize) {
201 fFontFace = fontFace;
202 fFontSize = fontSize;
203 fXform = xform;
204 }
206 const void* draw(const SkGlyph&, bool isBW);
208 private:
209 uint16_t fWidth;
210 uint16_t fHeight;
211 IDWriteFontFace* fFontFace;
212 FLOAT fFontSize;
213 DWRITE_MATRIX fXform;
214 SkTDArray<uint8_t> fBits;
215 };
217 const void* DWriteOffscreen::draw(const SkGlyph& glyph, bool isBW) {
218 IDWriteFactory* factory = get_dwrite_factory();
219 SkASSERT(factory != NULL);
221 if (fWidth < glyph.fWidth || fHeight < glyph.fHeight) {
222 fWidth = SkMax32(fWidth, glyph.fWidth);
223 fHeight = SkMax32(fHeight, glyph.fHeight);
225 if (isBW) {
226 fBits.setCount(fWidth * fHeight);
227 } else {
228 fBits.setCount(fWidth * fHeight * 3);
229 }
230 }
232 // erase
233 memset(fBits.begin(), 0, fBits.count());
235 fXform.dx = SkFixedToFloat(glyph.getSubXFixed());
236 fXform.dy = SkFixedToFloat(glyph.getSubYFixed());
238 FLOAT advance = 0.0f;
240 UINT16 index = glyph.getGlyphID();
242 DWRITE_GLYPH_OFFSET offset;
243 offset.advanceOffset = 0.0f;
244 offset.ascenderOffset = 0.0f;
246 DWRITE_GLYPH_RUN run;
247 run.glyphCount = 1;
248 run.glyphAdvances = &advance;
249 run.fontFace = fFontFace;
250 run.fontEmSize = fFontSize;
251 run.bidiLevel = 0;
252 run.glyphIndices = &index;
253 run.isSideways = FALSE;
254 run.glyphOffsets = &offset;
256 DWRITE_RENDERING_MODE renderingMode;
257 DWRITE_TEXTURE_TYPE textureType;
258 if (isBW) {
259 renderingMode = DWRITE_RENDERING_MODE_ALIASED;
260 textureType = DWRITE_TEXTURE_ALIASED_1x1;
261 } else {
262 renderingMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC;
263 textureType = DWRITE_TEXTURE_CLEARTYPE_3x1;
264 }
265 SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis;
266 HRNM(factory->CreateGlyphRunAnalysis(&run,
267 1.0f, // pixelsPerDip,
268 &fXform,
269 renderingMode,
270 DWRITE_MEASURING_MODE_NATURAL,
271 0.0f, // baselineOriginX,
272 0.0f, // baselineOriginY,
273 &glyphRunAnalysis),
274 "Could not create glyph run analysis.");
276 //NOTE: this assumes that the glyph has already been measured
277 //with an exact same glyph run analysis.
278 RECT bbox;
279 bbox.left = glyph.fLeft;
280 bbox.top = glyph.fTop;
281 bbox.right = glyph.fLeft + glyph.fWidth;
282 bbox.bottom = glyph.fTop + glyph.fHeight;
283 HRNM(glyphRunAnalysis->CreateAlphaTexture(textureType,
284 &bbox,
285 fBits.begin(),
286 fBits.count()),
287 "Could not draw mask.");
288 return fBits.begin();
289 }
291 ///////////////////////////////////////////////////////////////////////////////
293 class StreamFontFileLoader : public IDWriteFontFileLoader {
294 public:
295 // IUnknown methods
296 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject);
297 virtual ULONG STDMETHODCALLTYPE AddRef();
298 virtual ULONG STDMETHODCALLTYPE Release();
300 // IDWriteFontFileLoader methods
301 virtual HRESULT STDMETHODCALLTYPE CreateStreamFromKey(
302 void const* fontFileReferenceKey,
303 UINT32 fontFileReferenceKeySize,
304 IDWriteFontFileStream** fontFileStream);
306 static HRESULT Create(SkStream* stream, StreamFontFileLoader** streamFontFileLoader) {
307 *streamFontFileLoader = new StreamFontFileLoader(stream);
308 if (NULL == streamFontFileLoader) {
309 return E_OUTOFMEMORY;
310 }
311 return S_OK;
312 }
314 SkAutoTUnref<SkStream> fStream;
316 private:
317 StreamFontFileLoader(SkStream* stream) : fRefCount(1), fStream(SkRef(stream)) { }
319 ULONG fRefCount;
320 };
322 HRESULT StreamFontFileLoader::QueryInterface(REFIID iid, void** ppvObject) {
323 if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileLoader)) {
324 *ppvObject = this;
325 AddRef();
326 return S_OK;
327 } else {
328 *ppvObject = NULL;
329 return E_NOINTERFACE;
330 }
331 }
333 ULONG StreamFontFileLoader::AddRef() {
334 return InterlockedIncrement(&fRefCount);
335 }
337 ULONG StreamFontFileLoader::Release() {
338 ULONG newCount = InterlockedDecrement(&fRefCount);
339 if (0 == newCount) {
340 delete this;
341 }
342 return newCount;
343 }
345 HRESULT StreamFontFileLoader::CreateStreamFromKey(
346 void const* fontFileReferenceKey,
347 UINT32 fontFileReferenceKeySize,
348 IDWriteFontFileStream** fontFileStream)
349 {
350 SkTScopedComPtr<SkDWriteFontFileStreamWrapper> stream;
351 HR(SkDWriteFontFileStreamWrapper::Create(fStream, &stream));
352 *fontFileStream = stream.release();
353 return S_OK;
354 }
356 class StreamFontFileEnumerator : public IDWriteFontFileEnumerator {
357 public:
358 // IUnknown methods
359 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject);
360 virtual ULONG STDMETHODCALLTYPE AddRef();
361 virtual ULONG STDMETHODCALLTYPE Release();
363 // IDWriteFontFileEnumerator methods
364 virtual HRESULT STDMETHODCALLTYPE MoveNext(BOOL* hasCurrentFile);
365 virtual HRESULT STDMETHODCALLTYPE GetCurrentFontFile(IDWriteFontFile** fontFile);
367 static HRESULT Create(IDWriteFactory* factory, IDWriteFontFileLoader* fontFileLoader,
368 StreamFontFileEnumerator** streamFontFileEnumerator) {
369 *streamFontFileEnumerator = new StreamFontFileEnumerator(factory, fontFileLoader);
370 if (NULL == streamFontFileEnumerator) {
371 return E_OUTOFMEMORY;
372 }
373 return S_OK;
374 }
375 private:
376 StreamFontFileEnumerator(IDWriteFactory* factory, IDWriteFontFileLoader* fontFileLoader);
377 ULONG fRefCount;
379 SkTScopedComPtr<IDWriteFactory> fFactory;
380 SkTScopedComPtr<IDWriteFontFile> fCurrentFile;
381 SkTScopedComPtr<IDWriteFontFileLoader> fFontFileLoader;
382 bool fHasNext;
383 };
385 StreamFontFileEnumerator::StreamFontFileEnumerator(IDWriteFactory* factory,
386 IDWriteFontFileLoader* fontFileLoader)
387 : fRefCount(1)
388 , fFactory(SkRefComPtr(factory))
389 , fCurrentFile()
390 , fFontFileLoader(SkRefComPtr(fontFileLoader))
391 , fHasNext(true)
392 { }
394 HRESULT StreamFontFileEnumerator::QueryInterface(REFIID iid, void** ppvObject) {
395 if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileEnumerator)) {
396 *ppvObject = this;
397 AddRef();
398 return S_OK;
399 } else {
400 *ppvObject = NULL;
401 return E_NOINTERFACE;
402 }
403 }
405 ULONG StreamFontFileEnumerator::AddRef() {
406 return InterlockedIncrement(&fRefCount);
407 }
409 ULONG StreamFontFileEnumerator::Release() {
410 ULONG newCount = InterlockedDecrement(&fRefCount);
411 if (0 == newCount) {
412 delete this;
413 }
414 return newCount;
415 }
417 HRESULT StreamFontFileEnumerator::MoveNext(BOOL* hasCurrentFile) {
418 *hasCurrentFile = FALSE;
420 if (!fHasNext) {
421 return S_OK;
422 }
423 fHasNext = false;
425 UINT32 dummy = 0;
426 HR(fFactory->CreateCustomFontFileReference(
427 &dummy, //cannot be NULL
428 sizeof(dummy), //even if this is 0
429 fFontFileLoader.get(),
430 &fCurrentFile));
432 *hasCurrentFile = TRUE;
433 return S_OK;
434 }
436 HRESULT StreamFontFileEnumerator::GetCurrentFontFile(IDWriteFontFile** fontFile) {
437 if (fCurrentFile.get() == NULL) {
438 *fontFile = NULL;
439 return E_FAIL;
440 }
442 *fontFile = SkRefComPtr(fCurrentFile.get());
443 return S_OK;
444 }
446 class StreamFontCollectionLoader : public IDWriteFontCollectionLoader {
447 public:
448 // IUnknown methods
449 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject);
450 virtual ULONG STDMETHODCALLTYPE AddRef();
451 virtual ULONG STDMETHODCALLTYPE Release();
453 // IDWriteFontCollectionLoader methods
454 virtual HRESULT STDMETHODCALLTYPE CreateEnumeratorFromKey(
455 IDWriteFactory* factory,
456 void const* collectionKey,
457 UINT32 collectionKeySize,
458 IDWriteFontFileEnumerator** fontFileEnumerator);
460 static HRESULT Create(IDWriteFontFileLoader* fontFileLoader,
461 StreamFontCollectionLoader** streamFontCollectionLoader) {
462 *streamFontCollectionLoader = new StreamFontCollectionLoader(fontFileLoader);
463 if (NULL == streamFontCollectionLoader) {
464 return E_OUTOFMEMORY;
465 }
466 return S_OK;
467 }
468 private:
469 StreamFontCollectionLoader(IDWriteFontFileLoader* fontFileLoader)
470 : fRefCount(1)
471 , fFontFileLoader(SkRefComPtr(fontFileLoader))
472 { }
474 ULONG fRefCount;
475 SkTScopedComPtr<IDWriteFontFileLoader> fFontFileLoader;
476 };
478 HRESULT StreamFontCollectionLoader::QueryInterface(REFIID iid, void** ppvObject) {
479 if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontCollectionLoader)) {
480 *ppvObject = this;
481 AddRef();
482 return S_OK;
483 } else {
484 *ppvObject = NULL;
485 return E_NOINTERFACE;
486 }
487 }
489 ULONG StreamFontCollectionLoader::AddRef() {
490 return InterlockedIncrement(&fRefCount);
491 }
493 ULONG StreamFontCollectionLoader::Release() {
494 ULONG newCount = InterlockedDecrement(&fRefCount);
495 if (0 == newCount) {
496 delete this;
497 }
498 return newCount;
499 }
501 HRESULT StreamFontCollectionLoader::CreateEnumeratorFromKey(
502 IDWriteFactory* factory,
503 void const* collectionKey,
504 UINT32 collectionKeySize,
505 IDWriteFontFileEnumerator** fontFileEnumerator)
506 {
507 SkTScopedComPtr<StreamFontFileEnumerator> enumerator;
508 HR(StreamFontFileEnumerator::Create(factory, fFontFileLoader.get(), &enumerator));
509 *fontFileEnumerator = enumerator.release();
510 return S_OK;
511 }
513 ///////////////////////////////////////////////////////////////////////////////
515 static SkTypeface::Style get_style(IDWriteFont* font) {
516 int style = SkTypeface::kNormal;
517 DWRITE_FONT_WEIGHT weight = font->GetWeight();
518 if (DWRITE_FONT_WEIGHT_DEMI_BOLD <= weight) {
519 style |= SkTypeface::kBold;
520 }
521 DWRITE_FONT_STYLE angle = font->GetStyle();
522 if (DWRITE_FONT_STYLE_OBLIQUE == angle || DWRITE_FONT_STYLE_ITALIC == angle) {
523 style |= SkTypeface::kItalic;
524 }
525 return static_cast<SkTypeface::Style>(style);
526 }
528 class DWriteFontTypeface : public SkTypeface {
529 private:
530 DWriteFontTypeface(SkTypeface::Style style, SkFontID fontID,
531 IDWriteFontFace* fontFace,
532 IDWriteFont* font,
533 IDWriteFontFamily* fontFamily,
534 StreamFontFileLoader* fontFileLoader = NULL,
535 IDWriteFontCollectionLoader* fontCollectionLoader = NULL)
536 : SkTypeface(style, fontID, false)
537 , fDWriteFontCollectionLoader(SkSafeRefComPtr(fontCollectionLoader))
538 , fDWriteFontFileLoader(SkSafeRefComPtr(fontFileLoader))
539 , fDWriteFontFamily(SkRefComPtr(fontFamily))
540 , fDWriteFont(SkRefComPtr(font))
541 , fDWriteFontFace(SkRefComPtr(fontFace))
542 { }
544 public:
545 SkTScopedComPtr<IDWriteFontCollectionLoader> fDWriteFontCollectionLoader;
546 SkTScopedComPtr<StreamFontFileLoader> fDWriteFontFileLoader;
547 SkTScopedComPtr<IDWriteFontFamily> fDWriteFontFamily;
548 SkTScopedComPtr<IDWriteFont> fDWriteFont;
549 SkTScopedComPtr<IDWriteFontFace> fDWriteFontFace;
551 static DWriteFontTypeface* Create(IDWriteFontFace* fontFace,
552 IDWriteFont* font,
553 IDWriteFontFamily* fontFamily,
554 StreamFontFileLoader* fontFileLoader = NULL,
555 IDWriteFontCollectionLoader* fontCollectionLoader = NULL) {
556 SkTypeface::Style style = get_style(font);
557 SkFontID fontID = SkTypefaceCache::NewFontID();
558 return SkNEW_ARGS(DWriteFontTypeface, (style, fontID,
559 fontFace, font, fontFamily,
560 fontFileLoader, fontCollectionLoader));
561 }
563 ~DWriteFontTypeface() {
564 if (fDWriteFontCollectionLoader.get() == NULL) return;
566 IDWriteFactory* factory = get_dwrite_factory();
567 SkASSERT(factory != NULL);
568 HRV(factory->UnregisterFontCollectionLoader(fDWriteFontCollectionLoader.get()));
569 HRV(factory->UnregisterFontFileLoader(fDWriteFontFileLoader.get()));
570 }
572 protected:
573 virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE;
574 virtual SkScalerContext* onCreateScalerContext(const SkDescriptor*) const SK_OVERRIDE;
575 virtual void onFilterRec(SkScalerContextRec*) const SK_OVERRIDE;
576 virtual SkAdvancedTypefaceMetrics* onGetAdvancedTypefaceMetrics(
577 SkAdvancedTypefaceMetrics::PerGlyphInfo,
578 const uint32_t*, uint32_t) const SK_OVERRIDE;
579 virtual void onGetFontDescriptor(SkFontDescriptor*, bool*) const SK_OVERRIDE;
580 virtual int onCharsToGlyphs(const void* chars, Encoding encoding,
581 uint16_t glyphs[], int glyphCount) const SK_OVERRIDE;
582 virtual int onCountGlyphs() const SK_OVERRIDE;
583 virtual int onGetUPEM() const SK_OVERRIDE;
584 virtual SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const SK_OVERRIDE;
585 virtual int onGetTableTags(SkFontTableTag tags[]) const SK_OVERRIDE;
586 virtual size_t onGetTableData(SkFontTableTag, size_t offset,
587 size_t length, void* data) const SK_OVERRIDE;
588 };
590 class SkScalerContext_DW : public SkScalerContext {
591 public:
592 SkScalerContext_DW(DWriteFontTypeface*, const SkDescriptor* desc);
593 virtual ~SkScalerContext_DW();
595 protected:
596 virtual unsigned generateGlyphCount() SK_OVERRIDE;
597 virtual uint16_t generateCharToGlyph(SkUnichar uni) SK_OVERRIDE;
598 virtual void generateAdvance(SkGlyph* glyph) SK_OVERRIDE;
599 virtual void generateMetrics(SkGlyph* glyph) SK_OVERRIDE;
600 virtual void generateImage(const SkGlyph& glyph) SK_OVERRIDE;
601 virtual void generatePath(const SkGlyph& glyph, SkPath* path) SK_OVERRIDE;
602 virtual void generateFontMetrics(SkPaint::FontMetrics* mX,
603 SkPaint::FontMetrics* mY) SK_OVERRIDE;
605 private:
606 DWriteOffscreen fOffscreen;
607 DWRITE_MATRIX fXform;
608 SkAutoTUnref<DWriteFontTypeface> fTypeface;
609 int fGlyphCount;
610 };
612 static bool are_same(IUnknown* a, IUnknown* b) {
613 SkTScopedComPtr<IUnknown> iunkA;
614 if (FAILED(a->QueryInterface(&iunkA))) {
615 return false;
616 }
618 SkTScopedComPtr<IUnknown> iunkB;
619 if (FAILED(b->QueryInterface(&iunkB))) {
620 return false;
621 }
623 return iunkA.get() == iunkB.get();
624 }
625 static bool FindByDWriteFont(SkTypeface* face, SkTypeface::Style requestedStyle, void* ctx) {
626 //Check to see if the two fonts are identical.
627 DWriteFontTypeface* dwFace = reinterpret_cast<DWriteFontTypeface*>(face);
628 IDWriteFont* dwFont = reinterpret_cast<IDWriteFont*>(ctx);
629 if (are_same(dwFace->fDWriteFont.get(), dwFont)) {
630 return true;
631 }
633 //Check if the two fonts share the same loader and have the same key.
634 SkTScopedComPtr<IDWriteFontFace> dwFaceFontFace;
635 SkTScopedComPtr<IDWriteFontFace> dwFontFace;
636 HRB(dwFace->fDWriteFont->CreateFontFace(&dwFaceFontFace));
637 HRB(dwFont->CreateFontFace(&dwFontFace));
638 if (are_same(dwFaceFontFace.get(), dwFontFace.get())) {
639 return true;
640 }
642 UINT32 dwFaceNumFiles;
643 UINT32 dwNumFiles;
644 HRB(dwFaceFontFace->GetFiles(&dwFaceNumFiles, NULL));
645 HRB(dwFontFace->GetFiles(&dwNumFiles, NULL));
646 if (dwFaceNumFiles != dwNumFiles) {
647 return false;
648 }
650 SkTScopedComPtr<IDWriteFontFile> dwFaceFontFile;
651 SkTScopedComPtr<IDWriteFontFile> dwFontFile;
652 HRB(dwFaceFontFace->GetFiles(&dwFaceNumFiles, &dwFaceFontFile));
653 HRB(dwFontFace->GetFiles(&dwNumFiles, &dwFontFile));
655 //for (each file) { //we currently only admit fonts from one file.
656 SkTScopedComPtr<IDWriteFontFileLoader> dwFaceFontFileLoader;
657 SkTScopedComPtr<IDWriteFontFileLoader> dwFontFileLoader;
658 HRB(dwFaceFontFile->GetLoader(&dwFaceFontFileLoader));
659 HRB(dwFontFile->GetLoader(&dwFontFileLoader));
660 if (!are_same(dwFaceFontFileLoader.get(), dwFontFileLoader.get())) {
661 return false;
662 }
663 //}
665 const void* dwFaceFontRefKey;
666 UINT32 dwFaceFontRefKeySize;
667 const void* dwFontRefKey;
668 UINT32 dwFontRefKeySize;
669 HRB(dwFaceFontFile->GetReferenceKey(&dwFaceFontRefKey, &dwFaceFontRefKeySize));
670 HRB(dwFontFile->GetReferenceKey(&dwFontRefKey, &dwFontRefKeySize));
671 if (dwFaceFontRefKeySize != dwFontRefKeySize) {
672 return false;
673 }
674 if (0 != memcmp(dwFaceFontRefKey, dwFontRefKey, dwFontRefKeySize)) {
675 return false;
676 }
678 //TODO: better means than comparing name strings?
679 //NOTE: .tfc and fake bold/italic will end up here.
680 SkTScopedComPtr<IDWriteFontFamily> dwFaceFontFamily;
681 SkTScopedComPtr<IDWriteFontFamily> dwFontFamily;
682 HRB(dwFace->fDWriteFont->GetFontFamily(&dwFaceFontFamily));
683 HRB(dwFont->GetFontFamily(&dwFontFamily));
685 SkTScopedComPtr<IDWriteLocalizedStrings> dwFaceFontFamilyNames;
686 SkTScopedComPtr<IDWriteLocalizedStrings> dwFaceFontNames;
687 HRB(dwFaceFontFamily->GetFamilyNames(&dwFaceFontFamilyNames));
688 HRB(dwFace->fDWriteFont->GetFaceNames(&dwFaceFontNames));
690 SkTScopedComPtr<IDWriteLocalizedStrings> dwFontFamilyNames;
691 SkTScopedComPtr<IDWriteLocalizedStrings> dwFontNames;
692 HRB(dwFontFamily->GetFamilyNames(&dwFontFamilyNames));
693 HRB(dwFont->GetFaceNames(&dwFontNames));
695 UINT32 dwFaceFontFamilyNameLength;
696 UINT32 dwFaceFontNameLength;
697 HRB(dwFaceFontFamilyNames->GetStringLength(0, &dwFaceFontFamilyNameLength));
698 HRB(dwFaceFontNames->GetStringLength(0, &dwFaceFontNameLength));
700 UINT32 dwFontFamilyNameLength;
701 UINT32 dwFontNameLength;
702 HRB(dwFontFamilyNames->GetStringLength(0, &dwFontFamilyNameLength));
703 HRB(dwFontNames->GetStringLength(0, &dwFontNameLength));
705 if (dwFaceFontFamilyNameLength != dwFontFamilyNameLength ||
706 dwFaceFontNameLength != dwFontNameLength)
707 {
708 return false;
709 }
711 SkSMallocWCHAR dwFaceFontFamilyNameChar(dwFaceFontFamilyNameLength+1);
712 SkSMallocWCHAR dwFaceFontNameChar(dwFaceFontNameLength+1);
713 HRB(dwFaceFontFamilyNames->GetString(0, dwFaceFontFamilyNameChar.get(), dwFaceFontFamilyNameLength+1));
714 HRB(dwFaceFontNames->GetString(0, dwFaceFontNameChar.get(), dwFaceFontNameLength+1));
716 SkSMallocWCHAR dwFontFamilyNameChar(dwFontFamilyNameLength+1);
717 SkSMallocWCHAR dwFontNameChar(dwFontNameLength+1);
718 HRB(dwFontFamilyNames->GetString(0, dwFontFamilyNameChar.get(), dwFontFamilyNameLength+1));
719 HRB(dwFontNames->GetString(0, dwFontNameChar.get(), dwFontNameLength+1));
721 return wcscmp(dwFaceFontFamilyNameChar.get(), dwFontFamilyNameChar.get()) == 0 &&
722 wcscmp(dwFaceFontNameChar.get(), dwFontNameChar.get()) == 0;
723 }
725 SkScalerContext_DW::SkScalerContext_DW(DWriteFontTypeface* typeface,
726 const SkDescriptor* desc)
727 : SkScalerContext(typeface, desc)
728 , fTypeface(SkRef(typeface))
729 , fGlyphCount(-1) {
731 fXform.m11 = SkScalarToFloat(fRec.fPost2x2[0][0]);
732 fXform.m12 = SkScalarToFloat(fRec.fPost2x2[1][0]);
733 fXform.m21 = SkScalarToFloat(fRec.fPost2x2[0][1]);
734 fXform.m22 = SkScalarToFloat(fRec.fPost2x2[1][1]);
735 fXform.dx = 0;
736 fXform.dy = 0;
738 fOffscreen.init(fTypeface->fDWriteFontFace.get(), fXform, SkScalarToFloat(fRec.fTextSize));
739 }
741 SkScalerContext_DW::~SkScalerContext_DW() {
742 }
744 unsigned SkScalerContext_DW::generateGlyphCount() {
745 if (fGlyphCount < 0) {
746 fGlyphCount = fTypeface->fDWriteFontFace->GetGlyphCount();
747 }
748 return fGlyphCount;
749 }
751 uint16_t SkScalerContext_DW::generateCharToGlyph(SkUnichar uni) {
752 uint16_t index = 0;
753 fTypeface->fDWriteFontFace->GetGlyphIndices(reinterpret_cast<UINT32*>(&uni), 1, &index);
754 return index;
755 }
757 void SkScalerContext_DW::generateAdvance(SkGlyph* glyph) {
758 //Delta is the difference between the right/left side bearing metric
759 //and where the right/left side bearing ends up after hinting.
760 //DirectWrite does not provide this information.
761 glyph->fRsbDelta = 0;
762 glyph->fLsbDelta = 0;
764 glyph->fAdvanceX = 0;
765 glyph->fAdvanceY = 0;
767 uint16_t glyphId = glyph->getGlyphID();
768 DWRITE_GLYPH_METRICS gm;
769 HRVM(fTypeface->fDWriteFontFace->GetDesignGlyphMetrics(&glyphId, 1, &gm),
770 "Could not get design metrics.");
772 DWRITE_FONT_METRICS dwfm;
773 fTypeface->fDWriteFontFace->GetMetrics(&dwfm);
775 SkScalar advanceX = SkScalarMulDiv(fRec.fTextSize,
776 SkIntToScalar(gm.advanceWidth),
777 SkIntToScalar(dwfm.designUnitsPerEm));
779 if (!(fRec.fFlags & kSubpixelPositioning_Flag)) {
780 advanceX = SkScalarRoundToScalar(advanceX);
781 }
783 SkVector vecs[1] = { { advanceX, 0 } };
784 SkMatrix mat;
785 fRec.getMatrixFrom2x2(&mat);
786 mat.mapVectors(vecs, SK_ARRAY_COUNT(vecs));
788 glyph->fAdvanceX = SkScalarToFixed(vecs[0].fX);
789 glyph->fAdvanceY = SkScalarToFixed(vecs[0].fY);
790 }
792 void SkScalerContext_DW::generateMetrics(SkGlyph* glyph) {
793 glyph->fWidth = 0;
795 this->generateAdvance(glyph);
797 //Measure raster size.
798 fXform.dx = SkFixedToFloat(glyph->getSubXFixed());
799 fXform.dy = SkFixedToFloat(glyph->getSubYFixed());
801 FLOAT advance = 0;
803 UINT16 glyphId = glyph->getGlyphID();
805 DWRITE_GLYPH_OFFSET offset;
806 offset.advanceOffset = 0.0f;
807 offset.ascenderOffset = 0.0f;
809 DWRITE_GLYPH_RUN run;
810 run.glyphCount = 1;
811 run.glyphAdvances = &advance;
812 run.fontFace = fTypeface->fDWriteFontFace.get();
813 run.fontEmSize = SkScalarToFloat(fRec.fTextSize);
814 run.bidiLevel = 0;
815 run.glyphIndices = &glyphId;
816 run.isSideways = FALSE;
817 run.glyphOffsets = &offset;
819 IDWriteFactory* factory = get_dwrite_factory();
820 SkASSERT(factory != NULL);
822 const bool isBW = SkMask::kBW_Format == fRec.fMaskFormat;
823 DWRITE_RENDERING_MODE renderingMode;
824 DWRITE_TEXTURE_TYPE textureType;
825 if (isBW) {
826 renderingMode = DWRITE_RENDERING_MODE_ALIASED;
827 textureType = DWRITE_TEXTURE_ALIASED_1x1;
828 } else {
829 renderingMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC;
830 textureType = DWRITE_TEXTURE_CLEARTYPE_3x1;
831 }
833 SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis;
834 HRVM(factory->CreateGlyphRunAnalysis(&run,
835 1.0f, // pixelsPerDip,
836 &fXform,
837 renderingMode,
838 DWRITE_MEASURING_MODE_NATURAL,
839 0.0f, // baselineOriginX,
840 0.0f, // baselineOriginY,
841 &glyphRunAnalysis),
842 "Could not create glyph run analysis.");
844 RECT bbox;
845 HRVM(glyphRunAnalysis->GetAlphaTextureBounds(textureType, &bbox),
846 "Could not get texture bounds.");
848 glyph->fWidth = SkToU16(bbox.right - bbox.left);
849 glyph->fHeight = SkToU16(bbox.bottom - bbox.top);
850 glyph->fLeft = SkToS16(bbox.left);
851 glyph->fTop = SkToS16(bbox.top);
852 }
854 void SkScalerContext_DW::generateFontMetrics(SkPaint::FontMetrics* mx,
855 SkPaint::FontMetrics* my) {
856 if (!(mx || my))
857 return;
859 if (mx) {
860 sk_bzero(mx, sizeof(*mx));
861 }
862 if (my) {
863 sk_bzero(my, sizeof(*my));
864 }
866 DWRITE_FONT_METRICS dwfm;
867 fTypeface->fDWriteFontFace->GetMetrics(&dwfm);
869 SkScalar upem = SkIntToScalar(dwfm.designUnitsPerEm);
870 if (mx) {
871 mx->fTop = -fRec.fTextSize * SkIntToScalar(dwfm.ascent) / upem;
872 mx->fAscent = mx->fTop;
873 mx->fDescent = fRec.fTextSize * SkIntToScalar(dwfm.descent) / upem;
874 mx->fBottom = mx->fDescent;
875 mx->fLeading = fRec.fTextSize * SkIntToScalar(dwfm.lineGap) / upem;
876 mx->fXHeight = fRec.fTextSize * SkIntToScalar(dwfm.xHeight) / upem;
877 mx->fUnderlineThickness = fRec.fTextSize * SkIntToScalar(dwfm.underlinePosition) / upem;
878 mx->fUnderlinePosition = -(fRec.fTextSize * SkIntToScalar(dwfm.underlineThickness) / upem);
880 mx->fFlags |= SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag;
881 mx->fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag;
882 }
884 if (my) {
885 my->fTop = -fRec.fTextSize * SkIntToScalar(dwfm.ascent) / upem;
886 my->fAscent = my->fTop;
887 my->fDescent = fRec.fTextSize * SkIntToScalar(dwfm.descent) / upem;
888 my->fBottom = my->fDescent;
889 my->fLeading = fRec.fTextSize * SkIntToScalar(dwfm.lineGap) / upem;
890 my->fXHeight = fRec.fTextSize * SkIntToScalar(dwfm.xHeight) / upem;
891 my->fUnderlineThickness = fRec.fTextSize * SkIntToScalar(dwfm.underlinePosition) / upem;
892 my->fUnderlinePosition = -(fRec.fTextSize * SkIntToScalar(dwfm.underlineThickness) / upem);
894 my->fFlags |= SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag;
895 my->fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag;
896 }
897 }
899 ///////////////////////////////////////////////////////////////////////////////
901 #include "SkColorPriv.h"
903 static void bilevel_to_bw(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph) {
904 const int width = glyph.fWidth;
905 const size_t dstRB = (width + 7) >> 3;
906 uint8_t* SK_RESTRICT dst = static_cast<uint8_t*>(glyph.fImage);
908 int byteCount = width >> 3;
909 int bitCount = width & 7;
911 for (int y = 0; y < glyph.fHeight; ++y) {
912 if (byteCount > 0) {
913 for (int i = 0; i < byteCount; ++i) {
914 unsigned byte = 0;
915 byte |= src[0] & (1 << 7);
916 byte |= src[1] & (1 << 6);
917 byte |= src[2] & (1 << 5);
918 byte |= src[3] & (1 << 4);
919 byte |= src[4] & (1 << 3);
920 byte |= src[5] & (1 << 2);
921 byte |= src[6] & (1 << 1);
922 byte |= src[7] & (1 << 0);
923 dst[i] = byte;
924 src += 8;
925 }
926 }
927 if (bitCount > 0) {
928 unsigned byte = 0;
929 unsigned mask = 0x80;
930 for (int i = 0; i < bitCount; i++) {
931 byte |= (src[i]) & mask;
932 mask >>= 1;
933 }
934 dst[byteCount] = byte;
935 }
936 src += bitCount;
937 dst += dstRB;
938 }
939 }
941 template<bool APPLY_PREBLEND>
942 static void rgb_to_a8(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph, const uint8_t* table8) {
943 const size_t dstRB = glyph.rowBytes();
944 const U16CPU width = glyph.fWidth;
945 uint8_t* SK_RESTRICT dst = static_cast<uint8_t*>(glyph.fImage);
947 for (U16CPU y = 0; y < glyph.fHeight; y++) {
948 for (U16CPU i = 0; i < width; i++) {
949 U8CPU r = *(src++);
950 U8CPU g = *(src++);
951 U8CPU b = *(src++);
952 dst[i] = sk_apply_lut_if<APPLY_PREBLEND>((r + g + b) / 3, table8);
953 }
954 dst = (uint8_t*)((char*)dst + dstRB);
955 }
956 }
958 template<bool APPLY_PREBLEND>
959 static void rgb_to_lcd16(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph,
960 const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) {
961 const size_t dstRB = glyph.rowBytes();
962 const U16CPU width = glyph.fWidth;
963 uint16_t* SK_RESTRICT dst = static_cast<uint16_t*>(glyph.fImage);
965 for (U16CPU y = 0; y < glyph.fHeight; y++) {
966 for (U16CPU i = 0; i < width; i++) {
967 U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableR);
968 U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableG);
969 U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableB);
970 dst[i] = SkPack888ToRGB16(r, g, b);
971 }
972 dst = (uint16_t*)((char*)dst + dstRB);
973 }
974 }
976 template<bool APPLY_PREBLEND>
977 static void rgb_to_lcd32(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph,
978 const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) {
979 const size_t dstRB = glyph.rowBytes();
980 const U16CPU width = glyph.fWidth;
981 SkPMColor* SK_RESTRICT dst = static_cast<SkPMColor*>(glyph.fImage);
983 for (U16CPU y = 0; y < glyph.fHeight; y++) {
984 for (U16CPU i = 0; i < width; i++) {
985 U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableR);
986 U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableG);
987 U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableB);
988 dst[i] = SkPackARGB32(0xFF, r, g, b);
989 }
990 dst = (SkPMColor*)((char*)dst + dstRB);
991 }
992 }
994 void SkScalerContext_DW::generateImage(const SkGlyph& glyph) {
995 const bool isBW = SkMask::kBW_Format == fRec.fMaskFormat;
996 const bool isAA = !isLCD(fRec);
998 //Create the mask.
999 const void* bits = fOffscreen.draw(glyph, isBW);
1000 if (!bits) {
1001 sk_bzero(glyph.fImage, glyph.computeImageSize());
1002 return;
1003 }
1005 //Copy the mask into the glyph.
1006 const uint8_t* src = (const uint8_t*)bits;
1007 if (isBW) {
1008 bilevel_to_bw(src, glyph);
1009 } else if (isAA) {
1010 if (fPreBlend.isApplicable()) {
1011 rgb_to_a8<true>(src, glyph, fPreBlend.fG);
1012 } else {
1013 rgb_to_a8<false>(src, glyph, fPreBlend.fG);
1014 }
1015 } else if (SkMask::kLCD16_Format == glyph.fMaskFormat) {
1016 if (fPreBlend.isApplicable()) {
1017 rgb_to_lcd16<true>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
1018 } else {
1019 rgb_to_lcd16<false>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
1020 }
1021 } else {
1022 SkASSERT(SkMask::kLCD32_Format == glyph.fMaskFormat);
1023 if (fPreBlend.isApplicable()) {
1024 rgb_to_lcd32<true>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
1025 } else {
1026 rgb_to_lcd32<false>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
1027 }
1028 }
1029 }
1031 void SkScalerContext_DW::generatePath(const SkGlyph& glyph, SkPath* path) {
1032 SkASSERT(&glyph && path);
1034 path->reset();
1036 SkTScopedComPtr<IDWriteGeometrySink> geometryToPath;
1037 HRVM(SkDWriteGeometrySink::Create(path, &geometryToPath),
1038 "Could not create geometry to path converter.");
1039 uint16_t glyphId = glyph.getGlyphID();
1040 //TODO: convert to<->from DIUs? This would make a difference if hinting.
1041 //It may not be needed, it appears that DirectWrite only hints at em size.
1042 HRVM(fTypeface->fDWriteFontFace->GetGlyphRunOutline(SkScalarToFloat(fRec.fTextSize),
1043 &glyphId,
1044 NULL, //advances
1045 NULL, //offsets
1046 1, //num glyphs
1047 FALSE, //sideways
1048 FALSE, //rtl
1049 geometryToPath.get()),
1050 "Could not create glyph outline.");
1052 SkMatrix mat;
1053 fRec.getMatrixFrom2x2(&mat);
1054 path->transform(mat);
1055 }
1057 void DWriteFontTypeface::onGetFontDescriptor(SkFontDescriptor* desc,
1058 bool* isLocalStream) const {
1059 // Get the family name.
1060 SkTScopedComPtr<IDWriteLocalizedStrings> dwFamilyNames;
1061 HRV(fDWriteFontFamily->GetFamilyNames(&dwFamilyNames));
1063 UINT32 dwFamilyNamesLength;
1064 HRV(dwFamilyNames->GetStringLength(0, &dwFamilyNamesLength));
1066 SkSMallocWCHAR dwFamilyNameChar(dwFamilyNamesLength+1);
1067 HRV(dwFamilyNames->GetString(0, dwFamilyNameChar.get(), dwFamilyNamesLength+1));
1069 SkString utf8FamilyName;
1070 HRV(wchar_to_skstring(dwFamilyNameChar.get(), &utf8FamilyName));
1072 desc->setFamilyName(utf8FamilyName.c_str());
1073 *isLocalStream = SkToBool(fDWriteFontFileLoader.get());
1074 }
1076 static SkUnichar next_utf8(const void** chars) {
1077 return SkUTF8_NextUnichar((const char**)chars);
1078 }
1080 static SkUnichar next_utf16(const void** chars) {
1081 return SkUTF16_NextUnichar((const uint16_t**)chars);
1082 }
1084 static SkUnichar next_utf32(const void** chars) {
1085 const SkUnichar** uniChars = (const SkUnichar**)chars;
1086 SkUnichar uni = **uniChars;
1087 *uniChars += 1;
1088 return uni;
1089 }
1091 typedef SkUnichar (*EncodingProc)(const void**);
1093 static EncodingProc find_encoding_proc(SkTypeface::Encoding enc) {
1094 static const EncodingProc gProcs[] = {
1095 next_utf8, next_utf16, next_utf32
1096 };
1097 SkASSERT((size_t)enc < SK_ARRAY_COUNT(gProcs));
1098 return gProcs[enc];
1099 }
1101 int DWriteFontTypeface::onCharsToGlyphs(const void* chars, Encoding encoding,
1102 uint16_t glyphs[], int glyphCount) const
1103 {
1104 if (NULL == glyphs) {
1105 EncodingProc next_ucs4_proc = find_encoding_proc(encoding);
1106 for (int i = 0; i < glyphCount; ++i) {
1107 const SkUnichar c = next_ucs4_proc(&chars);
1108 BOOL exists;
1109 fDWriteFont->HasCharacter(c, &exists);
1110 if (!exists) {
1111 return i;
1112 }
1113 }
1114 return glyphCount;
1115 }
1117 switch (encoding) {
1118 case SkTypeface::kUTF8_Encoding:
1119 case SkTypeface::kUTF16_Encoding: {
1120 static const int scratchCount = 256;
1121 UINT32 scratch[scratchCount];
1122 EncodingProc next_ucs4_proc = find_encoding_proc(encoding);
1123 for (int baseGlyph = 0; baseGlyph < glyphCount; baseGlyph += scratchCount) {
1124 int glyphsLeft = glyphCount - baseGlyph;
1125 int limit = SkTMin(glyphsLeft, scratchCount);
1126 for (int i = 0; i < limit; ++i) {
1127 scratch[i] = next_ucs4_proc(&chars);
1128 }
1129 fDWriteFontFace->GetGlyphIndices(scratch, limit, &glyphs[baseGlyph]);
1130 }
1131 break;
1132 }
1133 case SkTypeface::kUTF32_Encoding: {
1134 const UINT32* utf32 = reinterpret_cast<const UINT32*>(chars);
1135 fDWriteFontFace->GetGlyphIndices(utf32, glyphCount, glyphs);
1136 break;
1137 }
1138 default:
1139 SK_CRASH();
1140 }
1142 for (int i = 0; i < glyphCount; ++i) {
1143 if (0 == glyphs[i]) {
1144 return i;
1145 }
1146 }
1147 return glyphCount;
1148 }
1150 int DWriteFontTypeface::onCountGlyphs() const {
1151 return fDWriteFontFace->GetGlyphCount();
1152 }
1154 int DWriteFontTypeface::onGetUPEM() const {
1155 DWRITE_FONT_METRICS metrics;
1156 fDWriteFontFace->GetMetrics(&metrics);
1157 return metrics.designUnitsPerEm;
1158 }
1160 class LocalizedStrings_IDWriteLocalizedStrings : public SkTypeface::LocalizedStrings {
1161 public:
1162 /** Takes ownership of the IDWriteLocalizedStrings. */
1163 explicit LocalizedStrings_IDWriteLocalizedStrings(IDWriteLocalizedStrings* strings)
1164 : fIndex(0), fStrings(strings)
1165 { }
1167 virtual bool next(SkTypeface::LocalizedString* localizedString) SK_OVERRIDE {
1168 if (fIndex >= fStrings->GetCount()) {
1169 return false;
1170 }
1172 // String
1173 UINT32 stringLength;
1174 HRBM(fStrings->GetStringLength(fIndex, &stringLength), "Could not get string length.");
1175 stringLength += 1;
1177 SkSMallocWCHAR wString(stringLength);
1178 HRBM(fStrings->GetString(fIndex, wString.get(), stringLength), "Could not get string.");
1180 HRB(wchar_to_skstring(wString.get(), &localizedString->fString));
1182 // Locale
1183 UINT32 localeLength;
1184 HRBM(fStrings->GetLocaleNameLength(fIndex, &localeLength), "Could not get locale length.");
1185 localeLength += 1;
1187 SkSMallocWCHAR wLocale(localeLength);
1188 HRBM(fStrings->GetLocaleName(fIndex, wLocale.get(), localeLength), "Could not get locale.");
1190 HRB(wchar_to_skstring(wLocale.get(), &localizedString->fLanguage));
1192 ++fIndex;
1193 return true;
1194 }
1196 private:
1197 UINT32 fIndex;
1198 SkTScopedComPtr<IDWriteLocalizedStrings> fStrings;
1199 };
1201 SkTypeface::LocalizedStrings* DWriteFontTypeface::onCreateFamilyNameIterator() const {
1202 SkTScopedComPtr<IDWriteLocalizedStrings> familyNames;
1203 HRNM(fDWriteFontFamily->GetFamilyNames(&familyNames), "Could not obtain family names.");
1205 return new LocalizedStrings_IDWriteLocalizedStrings(familyNames.release());
1206 }
1208 int DWriteFontTypeface::onGetTableTags(SkFontTableTag tags[]) const {
1209 DWRITE_FONT_FACE_TYPE type = fDWriteFontFace->GetType();
1210 if (type != DWRITE_FONT_FACE_TYPE_CFF &&
1211 type != DWRITE_FONT_FACE_TYPE_TRUETYPE &&
1212 type != DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION)
1213 {
1214 return 0;
1215 }
1217 int ttcIndex;
1218 SkAutoTUnref<SkStream> stream(this->openStream(&ttcIndex));
1219 return stream.get() ? SkFontStream::GetTableTags(stream, ttcIndex, tags) : 0;
1220 }
1222 class AutoDWriteTable {
1223 public:
1224 AutoDWriteTable(IDWriteFontFace* fontFace, UINT32 beTag) : fFontFace(fontFace), fExists(FALSE) {
1225 // Any errors are ignored, user must check fExists anyway.
1226 fontFace->TryGetFontTable(beTag,
1227 reinterpret_cast<const void **>(&fData), &fSize, &fLock, &fExists);
1228 }
1229 ~AutoDWriteTable() {
1230 if (fExists) {
1231 fFontFace->ReleaseFontTable(fLock);
1232 }
1233 }
1235 const uint8_t* fData;
1236 UINT32 fSize;
1237 BOOL fExists;
1238 private:
1239 // Borrowed reference, the user must ensure the fontFace stays alive.
1240 IDWriteFontFace* fFontFace;
1241 void* fLock;
1242 };
1244 size_t DWriteFontTypeface::onGetTableData(SkFontTableTag tag, size_t offset,
1245 size_t length, void* data) const
1246 {
1247 AutoDWriteTable table(fDWriteFontFace.get(), SkEndian_SwapBE32(tag));
1248 if (!table.fExists) {
1249 return 0;
1250 }
1252 if (offset > table.fSize) {
1253 return 0;
1254 }
1255 size_t size = SkTMin(length, table.fSize - offset);
1256 if (NULL != data) {
1257 memcpy(data, table.fData + offset, size);
1258 }
1260 return size;
1261 }
1263 template <typename T> class SkAutoIDWriteUnregister {
1264 public:
1265 SkAutoIDWriteUnregister(IDWriteFactory* factory, T* unregister)
1266 : fFactory(factory), fUnregister(unregister)
1267 { }
1269 ~SkAutoIDWriteUnregister() {
1270 if (fUnregister) {
1271 unregister(fFactory, fUnregister);
1272 }
1273 }
1275 T* detatch() {
1276 T* old = fUnregister;
1277 fUnregister = NULL;
1278 return old;
1279 }
1281 private:
1282 HRESULT unregister(IDWriteFactory* factory, IDWriteFontFileLoader* unregister) {
1283 return factory->UnregisterFontFileLoader(unregister);
1284 }
1286 HRESULT unregister(IDWriteFactory* factory, IDWriteFontCollectionLoader* unregister) {
1287 return factory->UnregisterFontCollectionLoader(unregister);
1288 }
1290 IDWriteFactory* fFactory;
1291 T* fUnregister;
1292 };
1294 static SkTypeface* create_from_stream(SkStream* stream, int ttcIndex) {
1295 IDWriteFactory* factory = get_dwrite_factory();
1296 if (NULL == factory) {
1297 return NULL;
1298 }
1300 SkTScopedComPtr<StreamFontFileLoader> fontFileLoader;
1301 HRN(StreamFontFileLoader::Create(stream, &fontFileLoader));
1302 HRN(factory->RegisterFontFileLoader(fontFileLoader.get()));
1303 SkAutoIDWriteUnregister<StreamFontFileLoader> autoUnregisterFontFileLoader(
1304 factory, fontFileLoader.get());
1306 SkTScopedComPtr<StreamFontCollectionLoader> fontCollectionLoader;
1307 HRN(StreamFontCollectionLoader::Create(fontFileLoader.get(), &fontCollectionLoader));
1308 HRN(factory->RegisterFontCollectionLoader(fontCollectionLoader.get()));
1309 SkAutoIDWriteUnregister<StreamFontCollectionLoader> autoUnregisterFontCollectionLoader(
1310 factory, fontCollectionLoader.get());
1312 SkTScopedComPtr<IDWriteFontCollection> fontCollection;
1313 HRN(factory->CreateCustomFontCollection(fontCollectionLoader.get(), NULL, 0, &fontCollection));
1315 // Find the first non-simulated font which has the given ttc index.
1316 UINT32 familyCount = fontCollection->GetFontFamilyCount();
1317 for (UINT32 familyIndex = 0; familyIndex < familyCount; ++familyIndex) {
1318 SkTScopedComPtr<IDWriteFontFamily> fontFamily;
1319 HRN(fontCollection->GetFontFamily(familyIndex, &fontFamily));
1321 UINT32 fontCount = fontFamily->GetFontCount();
1322 for (UINT32 fontIndex = 0; fontIndex < fontCount; ++fontIndex) {
1323 SkTScopedComPtr<IDWriteFont> font;
1324 HRN(fontFamily->GetFont(fontIndex, &font));
1325 if (font->GetSimulations() != DWRITE_FONT_SIMULATIONS_NONE) {
1326 continue;
1327 }
1329 SkTScopedComPtr<IDWriteFontFace> fontFace;
1330 HRN(font->CreateFontFace(&fontFace));
1332 UINT32 faceIndex = fontFace->GetIndex();
1333 if (faceIndex == ttcIndex) {
1334 return DWriteFontTypeface::Create(fontFace.get(), font.get(), fontFamily.get(),
1335 autoUnregisterFontFileLoader.detatch(),
1336 autoUnregisterFontCollectionLoader.detatch());
1337 }
1338 }
1339 }
1341 return NULL;
1342 }
1344 SkStream* DWriteFontTypeface::onOpenStream(int* ttcIndex) const {
1345 *ttcIndex = fDWriteFontFace->GetIndex();
1347 UINT32 numFiles;
1348 HRNM(fDWriteFontFace->GetFiles(&numFiles, NULL),
1349 "Could not get number of font files.");
1350 if (numFiles != 1) {
1351 return NULL;
1352 }
1354 SkTScopedComPtr<IDWriteFontFile> fontFile;
1355 HRNM(fDWriteFontFace->GetFiles(&numFiles, &fontFile), "Could not get font files.");
1357 const void* fontFileKey;
1358 UINT32 fontFileKeySize;
1359 HRNM(fontFile->GetReferenceKey(&fontFileKey, &fontFileKeySize),
1360 "Could not get font file reference key.");
1362 SkTScopedComPtr<IDWriteFontFileLoader> fontFileLoader;
1363 HRNM(fontFile->GetLoader(&fontFileLoader), "Could not get font file loader.");
1365 SkTScopedComPtr<IDWriteFontFileStream> fontFileStream;
1366 HRNM(fontFileLoader->CreateStreamFromKey(fontFileKey, fontFileKeySize,
1367 &fontFileStream),
1368 "Could not create font file stream.");
1370 return SkNEW_ARGS(SkDWriteFontFileStream, (fontFileStream.get()));
1371 }
1373 SkScalerContext* DWriteFontTypeface::onCreateScalerContext(const SkDescriptor* desc) const {
1374 return SkNEW_ARGS(SkScalerContext_DW, (const_cast<DWriteFontTypeface*>(this), desc));
1375 }
1377 void DWriteFontTypeface::onFilterRec(SkScalerContext::Rec* rec) const {
1378 if (rec->fFlags & SkScalerContext::kLCD_BGROrder_Flag ||
1379 rec->fFlags & SkScalerContext::kLCD_Vertical_Flag)
1380 {
1381 rec->fMaskFormat = SkMask::kA8_Format;
1382 }
1384 unsigned flagsWeDontSupport = SkScalerContext::kDevKernText_Flag |
1385 SkScalerContext::kForceAutohinting_Flag |
1386 SkScalerContext::kEmbeddedBitmapText_Flag |
1387 SkScalerContext::kEmbolden_Flag |
1388 SkScalerContext::kLCD_BGROrder_Flag |
1389 SkScalerContext::kLCD_Vertical_Flag;
1390 rec->fFlags &= ~flagsWeDontSupport;
1392 SkPaint::Hinting h = rec->getHinting();
1393 // DirectWrite does not provide for hinting hints.
1394 h = SkPaint::kSlight_Hinting;
1395 rec->setHinting(h);
1397 #if SK_FONT_HOST_USE_SYSTEM_SETTINGS
1398 IDWriteFactory* factory = get_dwrite_factory();
1399 if (factory != NULL) {
1400 SkTScopedComPtr<IDWriteRenderingParams> defaultRenderingParams;
1401 if (SUCCEEDED(factory->CreateRenderingParams(&defaultRenderingParams))) {
1402 float gamma = defaultRenderingParams->GetGamma();
1403 rec->setDeviceGamma(gamma);
1404 rec->setPaintGamma(gamma);
1406 rec->setContrast(defaultRenderingParams->GetEnhancedContrast());
1407 }
1408 }
1409 #endif
1410 }
1412 ///////////////////////////////////////////////////////////////////////////////
1413 //PDF Support
1415 using namespace skia_advanced_typeface_metrics_utils;
1417 // Construct Glyph to Unicode table.
1418 // Unicode code points that require conjugate pairs in utf16 are not
1419 // supported.
1420 // TODO(arthurhsu): Add support for conjugate pairs. It looks like that may
1421 // require parsing the TTF cmap table (platform 4, encoding 12) directly instead
1422 // of calling GetFontUnicodeRange().
1423 // TODO(bungeman): This never does what anyone wants.
1424 // What is really wanted is the text to glyphs mapping
1425 static void populate_glyph_to_unicode(IDWriteFontFace* fontFace,
1426 const unsigned glyphCount,
1427 SkTDArray<SkUnichar>* glyphToUnicode) {
1428 HRESULT hr = S_OK;
1430 //Do this like free type instead
1431 UINT32 count = 0;
1432 for (UINT32 c = 0; c < 0x10FFFF; ++c) {
1433 UINT16 glyph;
1434 hr = fontFace->GetGlyphIndices(&c, 1, &glyph);
1435 if (glyph > 0) {
1436 ++count;
1437 }
1438 }
1440 SkAutoTArray<UINT32> chars(count);
1441 count = 0;
1442 for (UINT32 c = 0; c < 0x10FFFF; ++c) {
1443 UINT16 glyph;
1444 hr = fontFace->GetGlyphIndices(&c, 1, &glyph);
1445 if (glyph > 0) {
1446 chars[count] = c;
1447 ++count;
1448 }
1449 }
1451 SkAutoTArray<UINT16> glyph(count);
1452 fontFace->GetGlyphIndices(chars.get(), count, glyph.get());
1454 USHORT maxGlyph = 0;
1455 for (USHORT j = 0; j < count; ++j) {
1456 if (glyph[j] > maxGlyph) maxGlyph = glyph[j];
1457 }
1459 glyphToUnicode->setCount(maxGlyph+1);
1460 for (USHORT j = 0; j < maxGlyph+1u; ++j) {
1461 (*glyphToUnicode)[j] = 0;
1462 }
1464 //'invert'
1465 for (USHORT j = 0; j < count; ++j) {
1466 if (glyph[j] < glyphCount && (*glyphToUnicode)[glyph[j]] == 0) {
1467 (*glyphToUnicode)[glyph[j]] = chars[j];
1468 }
1469 }
1470 }
1472 static bool getWidthAdvance(IDWriteFontFace* fontFace, int gId, int16_t* advance) {
1473 SkASSERT(advance);
1475 UINT16 glyphId = gId;
1476 DWRITE_GLYPH_METRICS gm;
1477 HRESULT hr = fontFace->GetDesignGlyphMetrics(&glyphId, 1, &gm);
1479 if (FAILED(hr)) {
1480 *advance = 0;
1481 return false;
1482 }
1484 *advance = gm.advanceWidth;
1485 return true;
1486 }
1488 template<typename T> class AutoTDWriteTable : public AutoDWriteTable {
1489 public:
1490 static const UINT32 tag = DWRITE_MAKE_OPENTYPE_TAG(T::TAG0, T::TAG1, T::TAG2, T::TAG3);
1491 AutoTDWriteTable(IDWriteFontFace* fontFace) : AutoDWriteTable(fontFace, tag) { }
1493 const T* operator->() const { return reinterpret_cast<const T*>(fData); }
1494 };
1496 SkAdvancedTypefaceMetrics* DWriteFontTypeface::onGetAdvancedTypefaceMetrics(
1497 SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo,
1498 const uint32_t* glyphIDs,
1499 uint32_t glyphIDsCount) const {
1501 SkAdvancedTypefaceMetrics* info = NULL;
1503 HRESULT hr = S_OK;
1505 const unsigned glyphCount = fDWriteFontFace->GetGlyphCount();
1507 DWRITE_FONT_METRICS dwfm;
1508 fDWriteFontFace->GetMetrics(&dwfm);
1510 info = new SkAdvancedTypefaceMetrics;
1511 info->fEmSize = dwfm.designUnitsPerEm;
1512 info->fMultiMaster = false;
1513 info->fLastGlyphID = SkToU16(glyphCount - 1);
1514 info->fStyle = 0;
1517 SkTScopedComPtr<IDWriteLocalizedStrings> familyNames;
1518 SkTScopedComPtr<IDWriteLocalizedStrings> faceNames;
1519 hr = fDWriteFontFamily->GetFamilyNames(&familyNames);
1520 hr = fDWriteFont->GetFaceNames(&faceNames);
1522 UINT32 familyNameLength;
1523 hr = familyNames->GetStringLength(0, &familyNameLength);
1525 UINT32 faceNameLength;
1526 hr = faceNames->GetStringLength(0, &faceNameLength);
1528 UINT32 size = familyNameLength+1+faceNameLength+1;
1529 SkSMallocWCHAR wFamilyName(size);
1530 hr = familyNames->GetString(0, wFamilyName.get(), size);
1531 wFamilyName[familyNameLength] = L' ';
1532 hr = faceNames->GetString(0, &wFamilyName[familyNameLength+1], size - faceNameLength + 1);
1534 hr = wchar_to_skstring(wFamilyName.get(), &info->fFontName);
1536 if (perGlyphInfo & SkAdvancedTypefaceMetrics::kToUnicode_PerGlyphInfo) {
1537 populate_glyph_to_unicode(fDWriteFontFace.get(), glyphCount, &(info->fGlyphToUnicode));
1538 }
1540 DWRITE_FONT_FACE_TYPE fontType = fDWriteFontFace->GetType();
1541 if (fontType == DWRITE_FONT_FACE_TYPE_TRUETYPE ||
1542 fontType == DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION) {
1543 info->fType = SkAdvancedTypefaceMetrics::kTrueType_Font;
1544 } else {
1545 info->fType = SkAdvancedTypefaceMetrics::kOther_Font;
1546 info->fItalicAngle = 0;
1547 info->fAscent = dwfm.ascent;;
1548 info->fDescent = dwfm.descent;
1549 info->fStemV = 0;
1550 info->fCapHeight = dwfm.capHeight;
1551 info->fBBox = SkIRect::MakeEmpty();
1552 return info;
1553 }
1555 AutoTDWriteTable<SkOTTableHead> headTable(fDWriteFontFace.get());
1556 AutoTDWriteTable<SkOTTablePostScript> postTable(fDWriteFontFace.get());
1557 AutoTDWriteTable<SkOTTableHorizontalHeader> hheaTable(fDWriteFontFace.get());
1558 AutoTDWriteTable<SkOTTableOS2> os2Table(fDWriteFontFace.get());
1559 if (!headTable.fExists || !postTable.fExists || !hheaTable.fExists || !os2Table.fExists) {
1560 info->fItalicAngle = 0;
1561 info->fAscent = dwfm.ascent;;
1562 info->fDescent = dwfm.descent;
1563 info->fStemV = 0;
1564 info->fCapHeight = dwfm.capHeight;
1565 info->fBBox = SkIRect::MakeEmpty();
1566 return info;
1567 }
1569 //There exist CJK fonts which set the IsFixedPitch and Monospace bits,
1570 //but have full width, latin half-width, and half-width kana.
1571 bool fixedWidth = (postTable->isFixedPitch &&
1572 (1 == SkEndian_SwapBE16(hheaTable->numberOfHMetrics)));
1573 //Monospace
1574 if (fixedWidth) {
1575 info->fStyle |= SkAdvancedTypefaceMetrics::kFixedPitch_Style;
1576 }
1577 //Italic
1578 if (os2Table->version.v0.fsSelection.field.Italic) {
1579 info->fStyle |= SkAdvancedTypefaceMetrics::kItalic_Style;
1580 }
1581 //Script
1582 if (SkPanose::FamilyType::Script == os2Table->version.v0.panose.bFamilyType.value) {
1583 info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style;
1584 //Serif
1585 } else if (SkPanose::FamilyType::TextAndDisplay == os2Table->version.v0.panose.bFamilyType.value &&
1586 SkPanose::Data::TextAndDisplay::SerifStyle::Triangle <= os2Table->version.v0.panose.data.textAndDisplay.bSerifStyle.value &&
1587 SkPanose::Data::TextAndDisplay::SerifStyle::NoFit != os2Table->version.v0.panose.data.textAndDisplay.bSerifStyle.value) {
1588 info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style;
1589 }
1591 info->fItalicAngle = SkEndian_SwapBE32(postTable->italicAngle) >> 16;
1593 info->fAscent = SkToS16(dwfm.ascent);
1594 info->fDescent = SkToS16(dwfm.descent);
1595 info->fCapHeight = SkToS16(dwfm.capHeight);
1597 info->fBBox = SkIRect::MakeLTRB((int32_t)SkEndian_SwapBE16((uint16_t)headTable->xMin),
1598 (int32_t)SkEndian_SwapBE16((uint16_t)headTable->yMax),
1599 (int32_t)SkEndian_SwapBE16((uint16_t)headTable->xMax),
1600 (int32_t)SkEndian_SwapBE16((uint16_t)headTable->yMin));
1602 //TODO: is this even desired? It seems PDF only wants this value for Type1
1603 //fonts, and we only get here for TrueType fonts.
1604 info->fStemV = 0;
1605 /*
1606 // Figure out a good guess for StemV - Min width of i, I, !, 1.
1607 // This probably isn't very good with an italic font.
1608 int16_t min_width = SHRT_MAX;
1609 info->fStemV = 0;
1610 char stem_chars[] = {'i', 'I', '!', '1'};
1611 for (size_t i = 0; i < SK_ARRAY_COUNT(stem_chars); i++) {
1612 ABC abcWidths;
1613 if (GetCharABCWidths(hdc, stem_chars[i], stem_chars[i], &abcWidths)) {
1614 int16_t width = abcWidths.abcB;
1615 if (width > 0 && width < min_width) {
1616 min_width = width;
1617 info->fStemV = min_width;
1618 }
1619 }
1620 }
1621 */
1623 // If Restricted, the font may not be embedded in a document.
1624 // If not Restricted, the font can be embedded.
1625 // If PreviewPrint, the embedding is read-only.
1626 if (os2Table->version.v0.fsType.field.Restricted) {
1627 info->fType = SkAdvancedTypefaceMetrics::kNotEmbeddable_Font;
1628 } else if (perGlyphInfo & SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo) {
1629 if (fixedWidth) {
1630 appendRange(&info->fGlyphWidths, 0);
1631 int16_t advance;
1632 getWidthAdvance(fDWriteFontFace.get(), 1, &advance);
1633 info->fGlyphWidths->fAdvance.append(1, &advance);
1634 finishRange(info->fGlyphWidths.get(), 0,
1635 SkAdvancedTypefaceMetrics::WidthRange::kDefault);
1636 } else {
1637 info->fGlyphWidths.reset(
1638 getAdvanceData(fDWriteFontFace.get(),
1639 glyphCount,
1640 glyphIDs,
1641 glyphIDsCount,
1642 getWidthAdvance));
1643 }
1644 }
1646 return info;
1647 }
1649 ///////////////////////////////////////////////////////////////////////////////
1651 static void get_locale_string(IDWriteLocalizedStrings* names, const WCHAR* preferedLocale,
1652 SkString* skname) {
1653 UINT32 nameIndex = 0;
1654 if (preferedLocale) {
1655 // Ignore any errors and continue with index 0 if there is a problem.
1656 BOOL nameExists;
1657 names->FindLocaleName(preferedLocale, &nameIndex, &nameExists);
1658 if (!nameExists) {
1659 nameIndex = 0;
1660 }
1661 }
1663 UINT32 nameLength;
1664 HRVM(names->GetStringLength(nameIndex, &nameLength), "Could not get name length.");
1665 nameLength += 1;
1667 SkSMallocWCHAR name(nameLength);
1668 HRVM(names->GetString(nameIndex, name.get(), nameLength), "Could not get string.");
1670 HRV(wchar_to_skstring(name.get(), skname));
1671 }
1673 SkTypeface* SkFontMgr_DirectWrite::createTypefaceFromDWriteFont(
1674 IDWriteFontFace* fontFace,
1675 IDWriteFont* font,
1676 IDWriteFontFamily* fontFamily,
1677 StreamFontFileLoader* fontFileLoader,
1678 IDWriteFontCollectionLoader* fontCollectionLoader) const {
1679 SkTypeface* face = FindByProcAndRef(FindByDWriteFont, font);
1680 if (NULL == face) {
1681 face = DWriteFontTypeface::Create(fontFace, font, fontFamily,
1682 fontFileLoader, fontCollectionLoader);
1683 if (face) {
1684 Add(face, get_style(font), fontCollectionLoader != NULL);
1685 }
1686 }
1687 return face;
1688 }
1690 int SkFontMgr_DirectWrite::onCountFamilies() const {
1691 return fFontCollection->GetFontFamilyCount();
1692 }
1694 void SkFontMgr_DirectWrite::onGetFamilyName(int index, SkString* familyName) const {
1695 SkTScopedComPtr<IDWriteFontFamily> fontFamily;
1696 HRVM(fFontCollection->GetFontFamily(index, &fontFamily), "Could not get requested family.");
1698 SkTScopedComPtr<IDWriteLocalizedStrings> familyNames;
1699 HRVM(fontFamily->GetFamilyNames(&familyNames), "Could not get family names.");
1701 get_locale_string(familyNames.get(), fLocaleName.get(), familyName);
1702 }
1704 SkFontStyleSet* SkFontMgr_DirectWrite::onCreateStyleSet(int index) const {
1705 SkTScopedComPtr<IDWriteFontFamily> fontFamily;
1706 HRNM(fFontCollection->GetFontFamily(index, &fontFamily), "Could not get requested family.");
1708 return SkNEW_ARGS(SkFontStyleSet_DirectWrite, (this, fontFamily.get()));
1709 }
1711 SkFontStyleSet* SkFontMgr_DirectWrite::onMatchFamily(const char familyName[]) const {
1712 SkSMallocWCHAR dwFamilyName;
1713 HRN(cstring_to_wchar(familyName, &dwFamilyName));
1715 UINT32 index;
1716 BOOL exists;
1717 HRNM(fFontCollection->FindFamilyName(dwFamilyName.get(), &index, &exists),
1718 "Failed while finding family by name.");
1719 if (!exists) {
1720 return NULL;
1721 }
1723 return this->onCreateStyleSet(index);
1724 }
1726 SkTypeface* SkFontMgr_DirectWrite::onMatchFamilyStyle(const char familyName[],
1727 const SkFontStyle& fontstyle) const {
1728 SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName));
1729 return sset->matchStyle(fontstyle);
1730 }
1732 SkTypeface* SkFontMgr_DirectWrite::onMatchFaceStyle(const SkTypeface* familyMember,
1733 const SkFontStyle& fontstyle) const {
1734 SkString familyName;
1735 SkFontStyleSet_DirectWrite sset(
1736 this, ((DWriteFontTypeface*)familyMember)->fDWriteFontFamily.get()
1737 );
1738 return sset.matchStyle(fontstyle);
1739 }
1741 SkTypeface* SkFontMgr_DirectWrite::onCreateFromStream(SkStream* stream, int ttcIndex) const {
1742 return create_from_stream(stream, ttcIndex);
1743 }
1745 SkTypeface* SkFontMgr_DirectWrite::onCreateFromData(SkData* data, int ttcIndex) const {
1746 SkAutoTUnref<SkStream> stream(SkNEW_ARGS(SkMemoryStream, (data)));
1747 return this->createFromStream(stream, ttcIndex);
1748 }
1750 SkTypeface* SkFontMgr_DirectWrite::onCreateFromFile(const char path[], int ttcIndex) const {
1751 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path));
1752 return this->createFromStream(stream, ttcIndex);
1753 }
1755 HRESULT SkFontMgr_DirectWrite::getByFamilyName(const WCHAR wideFamilyName[],
1756 IDWriteFontFamily** fontFamily) const {
1757 UINT32 index;
1758 BOOL exists;
1759 HR(fFontCollection->FindFamilyName(wideFamilyName, &index, &exists));
1761 if (exists) {
1762 HR(fFontCollection->GetFontFamily(index, fontFamily));
1763 return S_OK;
1764 }
1765 return S_FALSE;
1766 }
1768 HRESULT SkFontMgr_DirectWrite::getDefaultFontFamily(IDWriteFontFamily** fontFamily) const {
1769 NONCLIENTMETRICSW metrics;
1770 metrics.cbSize = sizeof(metrics);
1771 if (0 == SystemParametersInfoW(SPI_GETNONCLIENTMETRICS,
1772 sizeof(metrics),
1773 &metrics,
1774 0)) {
1775 return E_UNEXPECTED;
1776 }
1777 HRM(this->getByFamilyName(metrics.lfMessageFont.lfFaceName, fontFamily),
1778 "Could not create DWrite font family from LOGFONT.");
1780 return S_OK;
1781 }
1783 SkTypeface* SkFontMgr_DirectWrite::onLegacyCreateTypeface(const char familyName[],
1784 unsigned styleBits) const {
1785 SkTScopedComPtr<IDWriteFontFamily> fontFamily;
1786 if (familyName) {
1787 SkSMallocWCHAR wideFamilyName;
1788 if (SUCCEEDED(cstring_to_wchar(familyName, &wideFamilyName))) {
1789 this->getByFamilyName(wideFamilyName, &fontFamily);
1790 }
1791 }
1793 if (NULL == fontFamily.get()) {
1794 // No family with given name, try default.
1795 HRNM(this->getDefaultFontFamily(&fontFamily), "Could not get default font family.");
1796 }
1798 SkTScopedComPtr<IDWriteFont> font;
1799 DWRITE_FONT_WEIGHT weight = (styleBits & SkTypeface::kBold)
1800 ? DWRITE_FONT_WEIGHT_BOLD
1801 : DWRITE_FONT_WEIGHT_NORMAL;
1802 DWRITE_FONT_STRETCH stretch = DWRITE_FONT_STRETCH_NORMAL;
1803 DWRITE_FONT_STYLE italic = (styleBits & SkTypeface::kItalic)
1804 ? DWRITE_FONT_STYLE_ITALIC
1805 : DWRITE_FONT_STYLE_NORMAL;
1806 HRNM(fontFamily->GetFirstMatchingFont(weight, stretch, italic, &font),
1807 "Could not get matching font.");
1809 SkTScopedComPtr<IDWriteFontFace> fontFace;
1810 HRNM(font->CreateFontFace(&fontFace), "Could not create font face.");
1812 return this->createTypefaceFromDWriteFont(fontFace.get(), font.get(), fontFamily.get());
1813 }
1815 ///////////////////////////////////////////////////////////////////////////////
1817 int SkFontStyleSet_DirectWrite::count() {
1818 return fFontFamily->GetFontCount();
1819 }
1821 SkTypeface* SkFontStyleSet_DirectWrite::createTypeface(int index) {
1822 SkTScopedComPtr<IDWriteFont> font;
1823 HRNM(fFontFamily->GetFont(index, &font), "Could not get font.");
1825 SkTScopedComPtr<IDWriteFontFace> fontFace;
1826 HRNM(font->CreateFontFace(&fontFace), "Could not create font face.");
1828 return fFontMgr->createTypefaceFromDWriteFont(fontFace.get(), font.get(), fFontFamily.get());
1829 }
1831 void SkFontStyleSet_DirectWrite::getStyle(int index, SkFontStyle* fs, SkString* styleName) {
1832 SkTScopedComPtr<IDWriteFont> font;
1833 HRVM(fFontFamily->GetFont(index, &font), "Could not get font.");
1835 SkFontStyle::Slant slant;
1836 switch (font->GetStyle()) {
1837 case DWRITE_FONT_STYLE_NORMAL:
1838 slant = SkFontStyle::kUpright_Slant;
1839 break;
1840 case DWRITE_FONT_STYLE_OBLIQUE:
1841 case DWRITE_FONT_STYLE_ITALIC:
1842 slant = SkFontStyle::kItalic_Slant;
1843 break;
1844 default:
1845 SkASSERT(false);
1846 }
1848 int weight = font->GetWeight();
1849 int width = font->GetStretch();
1851 *fs = SkFontStyle(weight, width, slant);
1853 SkTScopedComPtr<IDWriteLocalizedStrings> faceNames;
1854 if (SUCCEEDED(font->GetFaceNames(&faceNames))) {
1855 get_locale_string(faceNames.get(), fFontMgr->fLocaleName.get(), styleName);
1856 }
1857 }
1859 SkTypeface* SkFontStyleSet_DirectWrite::matchStyle(const SkFontStyle& pattern) {
1860 DWRITE_FONT_STYLE slant;
1861 switch (pattern.slant()) {
1862 case SkFontStyle::kUpright_Slant:
1863 slant = DWRITE_FONT_STYLE_NORMAL;
1864 break;
1865 case SkFontStyle::kItalic_Slant:
1866 slant = DWRITE_FONT_STYLE_ITALIC;
1867 break;
1868 default:
1869 SkASSERT(false);
1870 }
1872 DWRITE_FONT_WEIGHT weight = (DWRITE_FONT_WEIGHT)pattern.weight();
1873 DWRITE_FONT_STRETCH width = (DWRITE_FONT_STRETCH)pattern.width();
1875 SkTScopedComPtr<IDWriteFont> font;
1876 // TODO: perhaps use GetMatchingFonts and get the least simulated?
1877 HRNM(fFontFamily->GetFirstMatchingFont(weight, width, slant, &font),
1878 "Could not match font in family.");
1880 SkTScopedComPtr<IDWriteFontFace> fontFace;
1881 HRNM(font->CreateFontFace(&fontFace), "Could not create font face.");
1883 return fFontMgr->createTypefaceFromDWriteFont(fontFace.get(), font.get(),
1884 fFontFamily.get());
1885 }
1887 ///////////////////////////////////////////////////////////////////////////////
1889 typedef decltype(GetUserDefaultLocaleName)* GetUserDefaultLocaleNameProc;
1890 static HRESULT GetGetUserDefaultLocaleNameProc(GetUserDefaultLocaleNameProc* proc) {
1891 *proc = reinterpret_cast<GetUserDefaultLocaleNameProc>(
1892 GetProcAddress(LoadLibraryW(L"Kernel32.dll"), "GetUserDefaultLocaleName")
1893 );
1894 if (!*proc) {
1895 HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
1896 if (!IS_ERROR(hr)) {
1897 hr = ERROR_PROC_NOT_FOUND;
1898 }
1899 return hr;
1900 }
1901 return S_OK;
1902 }
1904 SkFontMgr* SkFontMgr_New_DirectWrite() {
1905 IDWriteFactory* factory = get_dwrite_factory();
1906 if (NULL == factory) {
1907 return NULL;
1908 }
1910 SkTScopedComPtr<IDWriteFontCollection> sysFontCollection;
1911 HRNM(factory->GetSystemFontCollection(&sysFontCollection, FALSE),
1912 "Could not get system font collection.");
1914 WCHAR localeNameStorage[LOCALE_NAME_MAX_LENGTH];
1915 WCHAR* localeName = NULL;
1916 int localeNameLen = 0;
1918 // Dynamically load GetUserDefaultLocaleName function, as it is not available on XP.
1919 GetUserDefaultLocaleNameProc getUserDefaultLocaleNameProc = NULL;
1920 HRESULT hr = GetGetUserDefaultLocaleNameProc(&getUserDefaultLocaleNameProc);
1921 if (NULL == getUserDefaultLocaleNameProc) {
1922 SK_TRACEHR(hr, "Could not get GetUserDefaultLocaleName.");
1923 } else {
1924 localeNameLen = getUserDefaultLocaleNameProc(localeNameStorage, LOCALE_NAME_MAX_LENGTH);
1925 if (localeNameLen) {
1926 localeName = localeNameStorage;
1927 };
1928 }
1930 return SkNEW_ARGS(SkFontMgr_DirectWrite, (sysFontCollection.get(), localeName, localeNameLen));
1931 }