blob: 1ab0b7e92bf5623069f397056bc8d6672657ce75 [file] [log] [blame]
bungeman@google.come8f05922012-08-16 16:13:40 +00001/*
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 */
7
8#include "SkTypes.h"
9#undef GetGlyphIndices
10
11#include "SkAdvancedTypefaceMetrics.h"
12#include "SkColorFilter.h"
13#include "SkDWriteFontFileStream.h"
14#include "SkDWriteGeometrySink.h"
15#include "SkDescriptor.h"
16#include "SkEndian.h"
bungeman@google.com94acfb52012-08-31 15:41:09 +000017#include "SkFontDescriptor.h"
bungeman@google.come8f05922012-08-16 16:13:40 +000018#include "SkFontHost.h"
bungeman@google.combfc6cc42013-08-21 15:20:43 +000019#include "SkFontMgr.h"
bungeman@google.comb10b51f2013-08-01 20:18:41 +000020#include "SkFontStream.h"
bungeman@google.come8f05922012-08-16 16:13:40 +000021#include "SkGlyph.h"
22#include "SkHRESULT.h"
23#include "SkMaskGamma.h"
24#include "SkOTTable_head.h"
25#include "SkOTTable_hhea.h"
26#include "SkOTTable_OS_2.h"
27#include "SkOTTable_post.h"
28#include "SkPath.h"
29#include "SkStream.h"
30#include "SkString.h"
31#include "SkTScopedComPtr.h"
32#include "SkThread.h"
33#include "SkTypeface_win.h"
34#include "SkTypefaceCache.h"
35#include "SkUtils.h"
36
37#include <dwrite.h>
38
39SK_DECLARE_STATIC_MUTEX(gFTMutex);
40
41static bool isLCD(const SkScalerContext::Rec& rec) {
42 return SkMask::kLCD16_Format == rec.fMaskFormat ||
43 SkMask::kLCD32_Format == rec.fMaskFormat;
44}
45
bungeman@google.com71033442013-05-01 14:21:20 +000046/** Prefer to use this type to prevent template proliferation. */
47typedef SkAutoSTMalloc<16, WCHAR> SkSMallocWCHAR;
48
49static 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}
62
63static HRESULT wchar_to_skstring(WCHAR* name, SkString* skname) {
64 int len = WideCharToMultiByte(CP_UTF8, 0, name, -1, NULL, 0, NULL, NULL);
65 if (0 == len) {
66 HRM(HRESULT_FROM_WIN32(GetLastError()),
67 "Could not get length for utf-8 to wchar conversion.");
68 }
69 skname->resize(len - 1);
70 len = WideCharToMultiByte(CP_UTF8, 0, name, -1, skname->writable_str(), len, NULL, NULL);
71 if (0 == len) {
72 HRM(HRESULT_FROM_WIN32(GetLastError()), "Could not convert utf-8 to wchar.");
73 }
74 return S_OK;
75}
76
bungeman@google.come8f05922012-08-16 16:13:40 +000077///////////////////////////////////////////////////////////////////////////////
78
bungeman@google.combfc6cc42013-08-21 15:20:43 +000079class StreamFontFileLoader;
80
81class SkFontMgr_DirectWrite : public SkFontMgr {
82public:
83 /** localeNameLength must include the null terminator. */
84 SkFontMgr_DirectWrite(IDWriteFontCollection* fontCollection,
85 WCHAR* localeName, int localeNameLength)
86 : fFontCollection(SkRefComPtr(fontCollection))
87 , fLocaleName(localeNameLength)
88 {
89 memcpy(fLocaleName.get(), localeName, localeNameLength * sizeof(WCHAR));
90 }
91
92 SkTypefaceCache* getTypefaceCache() { return &fTFCache; }
93
94 SkTypeface* createTypefaceFromDWriteFont(IDWriteFontFace* fontFace,
95 IDWriteFont* font,
96 IDWriteFontFamily* fontFamily,
97 StreamFontFileLoader* = NULL,
98 IDWriteFontCollectionLoader* = NULL);
99
100protected:
101 virtual int onCountFamilies() SK_OVERRIDE;
102 virtual void onGetFamilyName(int index, SkString* familyName) SK_OVERRIDE;
103 virtual SkFontStyleSet* onCreateStyleSet(int index) SK_OVERRIDE;
104 virtual SkFontStyleSet* onMatchFamily(const char familyName[]) SK_OVERRIDE;
105 virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
106 const SkFontStyle& fontstyle) SK_OVERRIDE;
107 virtual SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember,
108 const SkFontStyle& fontstyle) SK_OVERRIDE;
109 virtual SkTypeface* onCreateFromStream(SkStream* stream, int ttcIndex) SK_OVERRIDE;
110 virtual SkTypeface* onCreateFromData(SkData* data, int ttcIndex) SK_OVERRIDE;
111 virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) SK_OVERRIDE;
112 virtual SkTypeface* onLegacyCreateTypeface(const char familyName[],
113 unsigned styleBits) SK_OVERRIDE;
114
115private:
bungeman@google.com86dd7522013-10-04 17:00:35 +0000116 SkMutex fTFCacheMutex;
117 void Add(SkTypeface* face, SkTypeface::Style requestedStyle, bool strong) {
118 SkAutoMutexAcquire ama(fTFCacheMutex);
119 fTFCache.add(face, requestedStyle, strong);
120 }
121
122 SkTypeface* FindByProcAndRef(SkTypefaceCache::FindProc proc, void* ctx) {
123 SkAutoMutexAcquire ama(fTFCacheMutex);
124 SkTypeface* typeface = fTFCache.findByProcAndRef(proc, ctx);
125 return typeface;
126 }
127
bungeman@google.combfc6cc42013-08-21 15:20:43 +0000128 friend class SkFontStyleSet_DirectWrite;
129 SkTScopedComPtr<IDWriteFontCollection> fFontCollection;
130 SkSMallocWCHAR fLocaleName;
131 SkTypefaceCache fTFCache;
132};
133
134class SkFontStyleSet_DirectWrite : public SkFontStyleSet {
135public:
136 SkFontStyleSet_DirectWrite(SkFontMgr_DirectWrite* fontMgr, IDWriteFontFamily* fontFamily)
137 : fFontMgr(SkRef(fontMgr))
138 , fFontFamily(SkRefComPtr(fontFamily))
139 { }
140
141 virtual int count() SK_OVERRIDE;
142 virtual void getStyle(int index, SkFontStyle* fs, SkString* styleName) SK_OVERRIDE;
143 virtual SkTypeface* createTypeface(int index) SK_OVERRIDE;
144 virtual SkTypeface* matchStyle(const SkFontStyle& pattern) SK_OVERRIDE;
145
146private:
147 SkAutoTUnref<SkFontMgr_DirectWrite> fFontMgr;
148 SkTScopedComPtr<IDWriteFontFamily> fFontFamily;
149};
150
151///////////////////////////////////////////////////////////////////////////////
152
bungeman@google.come8f05922012-08-16 16:13:40 +0000153class DWriteOffscreen {
154public:
155 DWriteOffscreen() : fWidth(0), fHeight(0) {
156 }
157
158 void init(IDWriteFontFace* fontFace, const DWRITE_MATRIX& xform, FLOAT fontSize) {
159 fFontFace = fontFace;
160 fFontSize = fontSize;
161 fXform = xform;
162 }
163
164 const void* draw(const SkGlyph&, bool isBW);
165
166private:
167 uint16_t fWidth;
168 uint16_t fHeight;
169 IDWriteFontFace* fFontFace;
170 FLOAT fFontSize;
171 DWRITE_MATRIX fXform;
172 SkTDArray<uint8_t> fBits;
173};
174
bungeman@google.come8f05922012-08-16 16:13:40 +0000175static HRESULT get_dwrite_factory(IDWriteFactory** factory) {
176 static IDWriteFactory* gDWriteFactory = NULL;
177
178 if (gDWriteFactory != NULL) {
179 *factory = gDWriteFactory;
180 return S_OK;
181 }
182
bungeman@google.comaf9296e2013-08-21 14:53:59 +0000183 typedef decltype(DWriteCreateFactory)* DWriteCreateFactoryProc;
bungeman@google.come8f05922012-08-16 16:13:40 +0000184 DWriteCreateFactoryProc dWriteCreateFactoryProc =
185 reinterpret_cast<DWriteCreateFactoryProc>(
186 GetProcAddress(LoadLibraryW(L"dwrite.dll"), "DWriteCreateFactory")
187 )
188 ;
bungeman@google.come8f05922012-08-16 16:13:40 +0000189 if (!dWriteCreateFactoryProc) {
bungeman@google.com42a78292013-08-21 22:41:05 +0000190 HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
191 if (!IS_ERROR(hr)) {
192 hr = ERROR_PROC_NOT_FOUND;
193 }
194 return hr;
bungeman@google.come8f05922012-08-16 16:13:40 +0000195 }
196
197 HRM(dWriteCreateFactoryProc(DWRITE_FACTORY_TYPE_SHARED,
198 __uuidof(IDWriteFactory),
199 reinterpret_cast<IUnknown**>(&gDWriteFactory)),
200 "Could not create DirectWrite factory.");
rmistry@google.comd6176b02012-08-23 18:14:13 +0000201
bungeman@google.come8f05922012-08-16 16:13:40 +0000202 *factory = gDWriteFactory;
203 return S_OK;
204}
205
206const void* DWriteOffscreen::draw(const SkGlyph& glyph, bool isBW) {
207 IDWriteFactory* factory;
208 HRNM(get_dwrite_factory(&factory), "Could not get factory.");
209
210 if (fWidth < glyph.fWidth || fHeight < glyph.fHeight) {
211 fWidth = SkMax32(fWidth, glyph.fWidth);
212 fHeight = SkMax32(fHeight, glyph.fHeight);
213
214 if (isBW) {
215 fBits.setCount(fWidth * fHeight);
216 } else {
217 fBits.setCount(fWidth * fHeight * 3);
218 }
219 }
220
221 // erase
222 memset(fBits.begin(), 0, fBits.count());
223
224 fXform.dx = SkFixedToFloat(glyph.getSubXFixed());
225 fXform.dy = SkFixedToFloat(glyph.getSubYFixed());
226
227 FLOAT advance = 0.0f;
228
229 UINT16 index = glyph.getGlyphID();
230
231 DWRITE_GLYPH_OFFSET offset;
232 offset.advanceOffset = 0.0f;
233 offset.ascenderOffset = 0.0f;
234
235 DWRITE_GLYPH_RUN run;
236 run.glyphCount = 1;
237 run.glyphAdvances = &advance;
238 run.fontFace = fFontFace;
239 run.fontEmSize = fFontSize;
240 run.bidiLevel = 0;
241 run.glyphIndices = &index;
242 run.isSideways = FALSE;
243 run.glyphOffsets = &offset;
244
245 DWRITE_RENDERING_MODE renderingMode;
246 DWRITE_TEXTURE_TYPE textureType;
247 if (isBW) {
248 renderingMode = DWRITE_RENDERING_MODE_ALIASED;
249 textureType = DWRITE_TEXTURE_ALIASED_1x1;
250 } else {
251 renderingMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC;
252 textureType = DWRITE_TEXTURE_CLEARTYPE_3x1;
253 }
254 SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis;
255 HRNM(factory->CreateGlyphRunAnalysis(&run,
256 1.0f, // pixelsPerDip,
257 &fXform,
258 renderingMode,
259 DWRITE_MEASURING_MODE_NATURAL,
260 0.0f, // baselineOriginX,
261 0.0f, // baselineOriginY,
262 &glyphRunAnalysis),
263 "Could not create glyph run analysis.");
rmistry@google.comd6176b02012-08-23 18:14:13 +0000264
bungeman@google.come8f05922012-08-16 16:13:40 +0000265 //NOTE: this assumes that the glyph has already been measured
266 //with an exact same glyph run analysis.
267 RECT bbox;
268 bbox.left = glyph.fLeft;
269 bbox.top = glyph.fTop;
270 bbox.right = glyph.fLeft + glyph.fWidth;
271 bbox.bottom = glyph.fTop + glyph.fHeight;
272 HRNM(glyphRunAnalysis->CreateAlphaTexture(textureType,
273 &bbox,
274 fBits.begin(),
275 fBits.count()),
276 "Could not draw mask.");
277 return fBits.begin();
278}
279
280///////////////////////////////////////////////////////////////////////////////
281
bungeman@google.com94acfb52012-08-31 15:41:09 +0000282class StreamFontFileLoader : public IDWriteFontFileLoader {
283public:
284 // IUnknown methods
285 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject);
286 virtual ULONG STDMETHODCALLTYPE AddRef();
287 virtual ULONG STDMETHODCALLTYPE Release();
288
289 // IDWriteFontFileLoader methods
290 virtual HRESULT STDMETHODCALLTYPE CreateStreamFromKey(
291 void const* fontFileReferenceKey,
292 UINT32 fontFileReferenceKeySize,
293 IDWriteFontFileStream** fontFileStream);
294
295 static HRESULT Create(SkStream* stream, StreamFontFileLoader** streamFontFileLoader) {
296 *streamFontFileLoader = new StreamFontFileLoader(stream);
297 if (NULL == streamFontFileLoader) {
298 return E_OUTOFMEMORY;
299 }
300 return S_OK;
301 }
302
303 SkAutoTUnref<SkStream> fStream;
304
305private:
bungeman@google.com4bbc5242013-05-02 14:01:36 +0000306 StreamFontFileLoader(SkStream* stream) : fRefCount(1), fStream(SkRef(stream)) { }
bungeman@google.com94acfb52012-08-31 15:41:09 +0000307
308 ULONG fRefCount;
309};
310
311HRESULT StreamFontFileLoader::QueryInterface(REFIID iid, void** ppvObject) {
312 if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileLoader)) {
313 *ppvObject = this;
314 AddRef();
315 return S_OK;
316 } else {
317 *ppvObject = NULL;
318 return E_NOINTERFACE;
319 }
320}
321
322ULONG StreamFontFileLoader::AddRef() {
323 return InterlockedIncrement(&fRefCount);
324}
325
326ULONG StreamFontFileLoader::Release() {
327 ULONG newCount = InterlockedDecrement(&fRefCount);
328 if (0 == newCount) {
329 delete this;
330 }
331 return newCount;
332}
333
334HRESULT StreamFontFileLoader::CreateStreamFromKey(
335 void const* fontFileReferenceKey,
336 UINT32 fontFileReferenceKeySize,
337 IDWriteFontFileStream** fontFileStream)
338{
339 SkTScopedComPtr<SkDWriteFontFileStreamWrapper> stream;
340 HR(SkDWriteFontFileStreamWrapper::Create(fStream, &stream));
341 *fontFileStream = stream.release();
342 return S_OK;
343}
344
345class StreamFontFileEnumerator : public IDWriteFontFileEnumerator {
346public:
347 // IUnknown methods
348 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject);
349 virtual ULONG STDMETHODCALLTYPE AddRef();
350 virtual ULONG STDMETHODCALLTYPE Release();
351
352 // IDWriteFontFileEnumerator methods
353 virtual HRESULT STDMETHODCALLTYPE MoveNext(BOOL* hasCurrentFile);
354 virtual HRESULT STDMETHODCALLTYPE GetCurrentFontFile(IDWriteFontFile** fontFile);
355
356 static HRESULT Create(IDWriteFactory* factory, IDWriteFontFileLoader* fontFileLoader,
357 StreamFontFileEnumerator** streamFontFileEnumerator) {
358 *streamFontFileEnumerator = new StreamFontFileEnumerator(factory, fontFileLoader);
359 if (NULL == streamFontFileEnumerator) {
360 return E_OUTOFMEMORY;
361 }
362 return S_OK;
363 }
364private:
365 StreamFontFileEnumerator(IDWriteFactory* factory, IDWriteFontFileLoader* fontFileLoader);
366 ULONG fRefCount;
367
368 SkTScopedComPtr<IDWriteFactory> fFactory;
369 SkTScopedComPtr<IDWriteFontFile> fCurrentFile;
370 SkTScopedComPtr<IDWriteFontFileLoader> fFontFileLoader;
371 bool fHasNext;
372};
373
374StreamFontFileEnumerator::StreamFontFileEnumerator(IDWriteFactory* factory,
375 IDWriteFontFileLoader* fontFileLoader)
376 : fRefCount(1)
bungeman@google.com4bbc5242013-05-02 14:01:36 +0000377 , fFactory(SkRefComPtr(factory))
bungeman@google.com94acfb52012-08-31 15:41:09 +0000378 , fCurrentFile()
bungeman@google.com4bbc5242013-05-02 14:01:36 +0000379 , fFontFileLoader(SkRefComPtr(fontFileLoader))
bungeman@google.com94acfb52012-08-31 15:41:09 +0000380 , fHasNext(true)
bungeman@google.com4bbc5242013-05-02 14:01:36 +0000381{ }
bungeman@google.com94acfb52012-08-31 15:41:09 +0000382
383HRESULT StreamFontFileEnumerator::QueryInterface(REFIID iid, void** ppvObject) {
384 if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileEnumerator)) {
385 *ppvObject = this;
386 AddRef();
387 return S_OK;
388 } else {
389 *ppvObject = NULL;
390 return E_NOINTERFACE;
391 }
392}
393
394ULONG StreamFontFileEnumerator::AddRef() {
395 return InterlockedIncrement(&fRefCount);
396}
397
398ULONG StreamFontFileEnumerator::Release() {
399 ULONG newCount = InterlockedDecrement(&fRefCount);
400 if (0 == newCount) {
401 delete this;
402 }
403 return newCount;
404}
405
406HRESULT StreamFontFileEnumerator::MoveNext(BOOL* hasCurrentFile) {
407 *hasCurrentFile = FALSE;
408
409 if (!fHasNext) {
410 return S_OK;
411 }
412 fHasNext = false;
413
414 UINT32 dummy = 0;
415 HR(fFactory->CreateCustomFontFileReference(
416 &dummy, //cannot be NULL
417 sizeof(dummy), //even if this is 0
418 fFontFileLoader.get(),
419 &fCurrentFile));
420
421 *hasCurrentFile = TRUE;
422 return S_OK;
423}
424
425HRESULT StreamFontFileEnumerator::GetCurrentFontFile(IDWriteFontFile** fontFile) {
426 if (fCurrentFile.get() == NULL) {
427 *fontFile = NULL;
428 return E_FAIL;
429 }
430
bungeman@google.com4bbc5242013-05-02 14:01:36 +0000431 *fontFile = SkRefComPtr(fCurrentFile.get());
bungeman@google.com94acfb52012-08-31 15:41:09 +0000432 return S_OK;
433}
434
435class StreamFontCollectionLoader : public IDWriteFontCollectionLoader {
436public:
437 // IUnknown methods
438 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject);
439 virtual ULONG STDMETHODCALLTYPE AddRef();
440 virtual ULONG STDMETHODCALLTYPE Release();
441
442 // IDWriteFontCollectionLoader methods
443 virtual HRESULT STDMETHODCALLTYPE CreateEnumeratorFromKey(
444 IDWriteFactory* factory,
445 void const* collectionKey,
446 UINT32 collectionKeySize,
447 IDWriteFontFileEnumerator** fontFileEnumerator);
448
449 static HRESULT Create(IDWriteFontFileLoader* fontFileLoader,
450 StreamFontCollectionLoader** streamFontCollectionLoader) {
451 *streamFontCollectionLoader = new StreamFontCollectionLoader(fontFileLoader);
452 if (NULL == streamFontCollectionLoader) {
453 return E_OUTOFMEMORY;
454 }
455 return S_OK;
456 }
457private:
458 StreamFontCollectionLoader(IDWriteFontFileLoader* fontFileLoader)
459 : fRefCount(1)
bungeman@google.com4bbc5242013-05-02 14:01:36 +0000460 , fFontFileLoader(SkRefComPtr(fontFileLoader))
461 { }
bungeman@google.com94acfb52012-08-31 15:41:09 +0000462
463 ULONG fRefCount;
464 SkTScopedComPtr<IDWriteFontFileLoader> fFontFileLoader;
465};
466
467HRESULT StreamFontCollectionLoader::QueryInterface(REFIID iid, void** ppvObject) {
468 if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontCollectionLoader)) {
469 *ppvObject = this;
470 AddRef();
471 return S_OK;
472 } else {
473 *ppvObject = NULL;
474 return E_NOINTERFACE;
475 }
476}
477
478ULONG StreamFontCollectionLoader::AddRef() {
479 return InterlockedIncrement(&fRefCount);
480}
481
482ULONG StreamFontCollectionLoader::Release() {
483 ULONG newCount = InterlockedDecrement(&fRefCount);
484 if (0 == newCount) {
485 delete this;
486 }
487 return newCount;
488}
489
490HRESULT StreamFontCollectionLoader::CreateEnumeratorFromKey(
491 IDWriteFactory* factory,
492 void const* collectionKey,
493 UINT32 collectionKeySize,
494 IDWriteFontFileEnumerator** fontFileEnumerator)
495{
496 SkTScopedComPtr<StreamFontFileEnumerator> enumerator;
497 HR(StreamFontFileEnumerator::Create(factory, fFontFileLoader.get(), &enumerator));
498 *fontFileEnumerator = enumerator.release();
499 return S_OK;
500}
501
502///////////////////////////////////////////////////////////////////////////////
503
bungeman@google.come8f05922012-08-16 16:13:40 +0000504static SkTypeface::Style get_style(IDWriteFont* font) {
505 int style = SkTypeface::kNormal;
506 DWRITE_FONT_WEIGHT weight = font->GetWeight();
507 if (DWRITE_FONT_WEIGHT_DEMI_BOLD <= weight) {
508 style |= SkTypeface::kBold;
509 }
510 DWRITE_FONT_STYLE angle = font->GetStyle();
511 if (DWRITE_FONT_STYLE_OBLIQUE == angle || DWRITE_FONT_STYLE_ITALIC == angle) {
512 style |= SkTypeface::kItalic;
513 }
514 return static_cast<SkTypeface::Style>(style);
515}
516
517class DWriteFontTypeface : public SkTypeface {
518private:
519 DWriteFontTypeface(SkTypeface::Style style, SkFontID fontID,
520 IDWriteFontFace* fontFace,
521 IDWriteFont* font,
522 IDWriteFontFamily* fontFamily,
bungeman@google.com94acfb52012-08-31 15:41:09 +0000523 StreamFontFileLoader* fontFileLoader = NULL,
bungeman@google.come8f05922012-08-16 16:13:40 +0000524 IDWriteFontCollectionLoader* fontCollectionLoader = NULL)
525 : SkTypeface(style, fontID, false)
bungeman@google.com4bbc5242013-05-02 14:01:36 +0000526 , fDWriteFontCollectionLoader(SkSafeRefComPtr(fontCollectionLoader))
527 , fDWriteFontFileLoader(SkSafeRefComPtr(fontFileLoader))
528 , fDWriteFontFamily(SkRefComPtr(fontFamily))
529 , fDWriteFont(SkRefComPtr(font))
530 , fDWriteFontFace(SkRefComPtr(fontFace))
531 { }
bungeman@google.come8f05922012-08-16 16:13:40 +0000532
533public:
534 SkTScopedComPtr<IDWriteFontCollectionLoader> fDWriteFontCollectionLoader;
bungeman@google.com94acfb52012-08-31 15:41:09 +0000535 SkTScopedComPtr<StreamFontFileLoader> fDWriteFontFileLoader;
bungeman@google.come8f05922012-08-16 16:13:40 +0000536 SkTScopedComPtr<IDWriteFontFamily> fDWriteFontFamily;
537 SkTScopedComPtr<IDWriteFont> fDWriteFont;
538 SkTScopedComPtr<IDWriteFontFace> fDWriteFontFace;
539
540 static DWriteFontTypeface* Create(IDWriteFontFace* fontFace,
541 IDWriteFont* font,
542 IDWriteFontFamily* fontFamily,
bungeman@google.com94acfb52012-08-31 15:41:09 +0000543 StreamFontFileLoader* fontFileLoader = NULL,
bungeman@google.come8f05922012-08-16 16:13:40 +0000544 IDWriteFontCollectionLoader* fontCollectionLoader = NULL) {
545 SkTypeface::Style style = get_style(font);
546 SkFontID fontID = SkTypefaceCache::NewFontID();
bungeman@google.com94acfb52012-08-31 15:41:09 +0000547 return SkNEW_ARGS(DWriteFontTypeface, (style, fontID,
548 fontFace, font, fontFamily,
bungeman@google.come8f05922012-08-16 16:13:40 +0000549 fontFileLoader, fontCollectionLoader));
550 }
551
552 ~DWriteFontTypeface() {
553 if (fDWriteFontCollectionLoader.get() == NULL) return;
554
555 IDWriteFactory* factory;
556 HRVM(get_dwrite_factory(&factory), "Could not get factory.");
557 HRV(factory->UnregisterFontCollectionLoader(fDWriteFontCollectionLoader.get()));
558 HRV(factory->UnregisterFontFileLoader(fDWriteFontFileLoader.get()));
559 }
reed@google.com0da48612013-03-19 16:06:52 +0000560
561protected:
reed@google.com177dc6e2013-03-21 20:55:10 +0000562 virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE;
reed@google.com0da48612013-03-19 16:06:52 +0000563 virtual SkScalerContext* onCreateScalerContext(const SkDescriptor*) const SK_OVERRIDE;
564 virtual void onFilterRec(SkScalerContextRec*) const SK_OVERRIDE;
reed@google.com2689f612013-03-20 20:01:47 +0000565 virtual SkAdvancedTypefaceMetrics* onGetAdvancedTypefaceMetrics(
566 SkAdvancedTypefaceMetrics::PerGlyphInfo,
567 const uint32_t*, uint32_t) const SK_OVERRIDE;
reed@google.com5526ede2013-03-25 13:03:37 +0000568 virtual void onGetFontDescriptor(SkFontDescriptor*, bool*) const SK_OVERRIDE;
bungeman@google.com7bdd6142013-07-15 19:42:57 +0000569 virtual int onCountGlyphs() const SK_OVERRIDE;
570 virtual int onGetUPEM() const SK_OVERRIDE;
bungeman@google.com839702b2013-08-07 17:09:22 +0000571 virtual SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const SK_OVERRIDE;
bungeman@google.comb10b51f2013-08-01 20:18:41 +0000572 virtual int onGetTableTags(SkFontTableTag tags[]) const SK_OVERRIDE;
573 virtual size_t onGetTableData(SkFontTableTag, size_t offset,
574 size_t length, void* data) const SK_OVERRIDE;
reed@google.com30ddd612013-07-30 17:47:39 +0000575 virtual SkTypeface* onRefMatchingStyle(Style) const SK_OVERRIDE;
bungeman@google.come8f05922012-08-16 16:13:40 +0000576};
577
reed@google.com30ddd612013-07-30 17:47:39 +0000578class SkScalerContext_DW : public SkScalerContext {
bungeman@google.come8f05922012-08-16 16:13:40 +0000579public:
reed@google.com30ddd612013-07-30 17:47:39 +0000580 SkScalerContext_DW(DWriteFontTypeface*, const SkDescriptor* desc);
581 virtual ~SkScalerContext_DW();
bungeman@google.come8f05922012-08-16 16:13:40 +0000582
583protected:
584 virtual unsigned generateGlyphCount() SK_OVERRIDE;
585 virtual uint16_t generateCharToGlyph(SkUnichar uni) SK_OVERRIDE;
586 virtual void generateAdvance(SkGlyph* glyph) SK_OVERRIDE;
587 virtual void generateMetrics(SkGlyph* glyph) SK_OVERRIDE;
bungeman@google.coma76de722012-10-26 19:35:54 +0000588 virtual void generateImage(const SkGlyph& glyph) SK_OVERRIDE;
bungeman@google.come8f05922012-08-16 16:13:40 +0000589 virtual void generatePath(const SkGlyph& glyph, SkPath* path) SK_OVERRIDE;
590 virtual void generateFontMetrics(SkPaint::FontMetrics* mX,
591 SkPaint::FontMetrics* mY) SK_OVERRIDE;
592
593private:
594 DWriteOffscreen fOffscreen;
595 DWRITE_MATRIX fXform;
596 SkAutoTUnref<DWriteFontTypeface> fTypeface;
597 int fGlyphCount;
598};
599
600#define SK_DWRITE_DEFAULT_FONT_NAMED 1
601#define SK_DWRITE_DEFAULT_FONT_MESSAGE 2
602#define SK_DWRITE_DEFAULT_FONT_THEME 3
603#define SK_DWRITE_DEFAULT_FONT_SHELLDLG 4
604#define SK_DWRITE_DEFAULT_FONT_GDI 5
605#define SK_DWRITE_DEFAULT_FONT_STRATEGY SK_DWRITE_DEFAULT_FONT_MESSAGE
606
607static HRESULT get_default_font(IDWriteFont** font) {
608 IDWriteFactory* factory;
609 HRM(get_dwrite_factory(&factory), "Could not get factory.");
610
611#if SK_DWRITE_DEFAULT_FONT_STRATEGY == SK_DWRITE_DEFAULT_FONT_NAMED
612 SkTScopedComPtr<IDWriteFontCollection> sysFonts;
613 HRM(factory->GetSystemFontCollection(&sysFonts, false),
614 "Could not get system font collection.");
615
616 UINT32 index;
617 BOOL exists;
618 //hr = sysFonts->FindFamilyName(L"Georgia", &index, &exists);
619 HRM(sysFonts->FindFamilyName(L"Microsoft Sans Serif", &index, &exists),
620 "Could not access family names.");
621
622 if (!exists) {
623 SkDEBUGF(("The hard coded font family does not exist."));
624 return E_UNEXPECTED;
625 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000626
bungeman@google.come8f05922012-08-16 16:13:40 +0000627 SkTScopedComPtr<IDWriteFontFamily> fontFamily;
628 HRM(sysFonts->GetFontFamily(index, &fontFamily),
629 "Could not load the requested font family.");
630
631 HRM(fontFamily->GetFont(0, font), "Could not get first font from family.");
632
633#elif SK_DWRITE_DEFAULT_FONT_STRATEGY == SK_DWRITE_DEFAULT_FONT_MESSAGE
634 SkTScopedComPtr<IDWriteGdiInterop> gdi;
635 HRM(factory->GetGdiInterop(&gdi), "Could not get GDI interop.");
636
637 NONCLIENTMETRICSW metrics;
638 metrics.cbSize = sizeof(metrics);
639 if (0 == SystemParametersInfoW(SPI_GETNONCLIENTMETRICS,
640 sizeof(metrics),
641 &metrics,
642 0)) {
643 return E_UNEXPECTED;
644 }
645 HRM(gdi->CreateFontFromLOGFONT(&metrics.lfMessageFont, font),
646 "Could not create DWrite font from LOGFONT.");
647
648#elif SK_DWRITE_DEFAULT_FONT_STRATEGY == SK_DWRITE_DEFAULT_FONT_THEME
649 //Theme body font?
650
651#elif SK_DWRITE_DEFAULT_FONT_STRATEGY == SK_DWRITE_DEFAULT_FONT_SHELLDLG
652 //"MS Shell Dlg" or "MS Shell Dlg 2"?
653
654#elif SK_DWRITE_DEFAULT_FONT_STRATEGY == SK_DWRITE_DEFAULT_FONT_GDI
655 //Never works.
656 SkTScopedComPtr<IDWriteGdiInterop> gdi;
657 HRM(factory->GetGdiInterop(&gdi), "Could not get GDI interop.");
658
659 static LOGFONTW gDefaultFont = {};
660 gDefaultFont.lfFaceName
661 HRM(gdi->CreateFontFromLOGFONT(&gDefaultFont, font),
662 "Could not create DWrite font from LOGFONT.";
663#endif
664 return S_OK;
665}
666
667static bool are_same(IUnknown* a, IUnknown* b) {
668 SkTScopedComPtr<IUnknown> iunkA;
669 if (FAILED(a->QueryInterface(&iunkA))) {
670 return false;
671 }
672
673 SkTScopedComPtr<IUnknown> iunkB;
674 if (FAILED(b->QueryInterface(&iunkB))) {
675 return false;
676 }
677
678 return iunkA.get() == iunkB.get();
679}
680static bool FindByDWriteFont(SkTypeface* face, SkTypeface::Style requestedStyle, void* ctx) {
681 //Check to see if the two fonts are identical.
682 DWriteFontTypeface* dwFace = reinterpret_cast<DWriteFontTypeface*>(face);
683 IDWriteFont* dwFont = reinterpret_cast<IDWriteFont*>(ctx);
684 if (are_same(dwFace->fDWriteFont.get(), dwFont)) {
685 return true;
686 }
687
688 //Check if the two fonts share the same loader and have the same key.
689 SkTScopedComPtr<IDWriteFontFace> dwFaceFontFace;
690 SkTScopedComPtr<IDWriteFontFace> dwFontFace;
691 HRB(dwFace->fDWriteFont->CreateFontFace(&dwFaceFontFace));
692 HRB(dwFont->CreateFontFace(&dwFontFace));
693 if (are_same(dwFaceFontFace.get(), dwFontFace.get())) {
694 return true;
695 }
696
697 UINT32 dwFaceNumFiles;
698 UINT32 dwNumFiles;
699 HRB(dwFaceFontFace->GetFiles(&dwFaceNumFiles, NULL));
700 HRB(dwFontFace->GetFiles(&dwNumFiles, NULL));
701 if (dwFaceNumFiles != dwNumFiles) {
702 return false;
703 }
704
705 SkTScopedComPtr<IDWriteFontFile> dwFaceFontFile;
706 SkTScopedComPtr<IDWriteFontFile> dwFontFile;
707 HRB(dwFaceFontFace->GetFiles(&dwFaceNumFiles, &dwFaceFontFile));
708 HRB(dwFontFace->GetFiles(&dwNumFiles, &dwFontFile));
709
710 //for (each file) { //we currently only admit fonts from one file.
711 SkTScopedComPtr<IDWriteFontFileLoader> dwFaceFontFileLoader;
712 SkTScopedComPtr<IDWriteFontFileLoader> dwFontFileLoader;
713 HRB(dwFaceFontFile->GetLoader(&dwFaceFontFileLoader));
714 HRB(dwFontFile->GetLoader(&dwFontFileLoader));
715 if (!are_same(dwFaceFontFileLoader.get(), dwFontFileLoader.get())) {
716 return false;
717 }
718 //}
719
720 const void* dwFaceFontRefKey;
721 UINT32 dwFaceFontRefKeySize;
722 const void* dwFontRefKey;
723 UINT32 dwFontRefKeySize;
724 HRB(dwFaceFontFile->GetReferenceKey(&dwFaceFontRefKey, &dwFaceFontRefKeySize));
725 HRB(dwFontFile->GetReferenceKey(&dwFontRefKey, &dwFontRefKeySize));
726 if (dwFaceFontRefKeySize != dwFontRefKeySize) {
727 return false;
728 }
729 if (0 != memcmp(dwFaceFontRefKey, dwFontRefKey, dwFontRefKeySize)) {
730 return false;
731 }
732
733 //TODO: better means than comparing name strings?
734 //NOTE: .tfc and fake bold/italic will end up here.
735 SkTScopedComPtr<IDWriteFontFamily> dwFaceFontFamily;
736 SkTScopedComPtr<IDWriteFontFamily> dwFontFamily;
737 HRB(dwFace->fDWriteFont->GetFontFamily(&dwFaceFontFamily));
738 HRB(dwFont->GetFontFamily(&dwFontFamily));
739
740 SkTScopedComPtr<IDWriteLocalizedStrings> dwFaceFontFamilyNames;
741 SkTScopedComPtr<IDWriteLocalizedStrings> dwFaceFontNames;
742 HRB(dwFaceFontFamily->GetFamilyNames(&dwFaceFontFamilyNames));
743 HRB(dwFace->fDWriteFont->GetFaceNames(&dwFaceFontNames));
744
745 SkTScopedComPtr<IDWriteLocalizedStrings> dwFontFamilyNames;
746 SkTScopedComPtr<IDWriteLocalizedStrings> dwFontNames;
747 HRB(dwFontFamily->GetFamilyNames(&dwFontFamilyNames));
748 HRB(dwFont->GetFaceNames(&dwFontNames));
749
750 UINT32 dwFaceFontFamilyNameLength;
751 UINT32 dwFaceFontNameLength;
752 HRB(dwFaceFontFamilyNames->GetStringLength(0, &dwFaceFontFamilyNameLength));
753 HRB(dwFaceFontNames->GetStringLength(0, &dwFaceFontNameLength));
754
755 UINT32 dwFontFamilyNameLength;
756 UINT32 dwFontNameLength;
757 HRB(dwFontFamilyNames->GetStringLength(0, &dwFontFamilyNameLength));
758 HRB(dwFontNames->GetStringLength(0, &dwFontNameLength));
759
760 if (dwFaceFontFamilyNameLength != dwFontFamilyNameLength ||
761 dwFaceFontNameLength != dwFontNameLength)
762 {
763 return false;
764 }
765
bungeman@google.com71033442013-05-01 14:21:20 +0000766 SkSMallocWCHAR dwFaceFontFamilyNameChar(dwFaceFontFamilyNameLength+1);
767 SkSMallocWCHAR dwFaceFontNameChar(dwFaceFontNameLength+1);
768 HRB(dwFaceFontFamilyNames->GetString(0, dwFaceFontFamilyNameChar.get(), dwFaceFontFamilyNameLength+1));
769 HRB(dwFaceFontNames->GetString(0, dwFaceFontNameChar.get(), dwFaceFontNameLength+1));
bungeman@google.come8f05922012-08-16 16:13:40 +0000770
bungeman@google.com71033442013-05-01 14:21:20 +0000771 SkSMallocWCHAR dwFontFamilyNameChar(dwFontFamilyNameLength+1);
772 SkSMallocWCHAR dwFontNameChar(dwFontNameLength+1);
773 HRB(dwFontFamilyNames->GetString(0, dwFontFamilyNameChar.get(), dwFontFamilyNameLength+1));
774 HRB(dwFontNames->GetString(0, dwFontNameChar.get(), dwFontNameLength+1));
bungeman@google.come8f05922012-08-16 16:13:40 +0000775
bungeman@google.com71033442013-05-01 14:21:20 +0000776 return wcscmp(dwFaceFontFamilyNameChar.get(), dwFontFamilyNameChar.get()) == 0 &&
777 wcscmp(dwFaceFontNameChar.get(), dwFontNameChar.get()) == 0;
bungeman@google.come8f05922012-08-16 16:13:40 +0000778}
779
bungeman@google.come8f05922012-08-16 16:13:40 +0000780void SkDWriteFontFromTypeface(const SkTypeface* face, IDWriteFont** font) {
781 if (NULL == face) {
782 HRVM(get_default_font(font), "Could not get default font.");
783 } else {
bungeman@google.com4bbc5242013-05-02 14:01:36 +0000784 *font = SkRefComPtr(static_cast<const DWriteFontTypeface*>(face)->fDWriteFont.get());
bungeman@google.come8f05922012-08-16 16:13:40 +0000785 }
786}
bungeman@google.come8f05922012-08-16 16:13:40 +0000787
reed@google.com30ddd612013-07-30 17:47:39 +0000788SkScalerContext_DW::SkScalerContext_DW(DWriteFontTypeface* typeface,
reed@google.com0da48612013-03-19 16:06:52 +0000789 const SkDescriptor* desc)
790 : SkScalerContext(typeface, desc)
791 , fTypeface(SkRef(typeface))
bungeman@google.come8f05922012-08-16 16:13:40 +0000792 , fGlyphCount(-1) {
793 SkAutoMutexAcquire ac(gFTMutex);
794
795 fXform.m11 = SkScalarToFloat(fRec.fPost2x2[0][0]);
796 fXform.m12 = SkScalarToFloat(fRec.fPost2x2[1][0]);
797 fXform.m21 = SkScalarToFloat(fRec.fPost2x2[0][1]);
798 fXform.m22 = SkScalarToFloat(fRec.fPost2x2[1][1]);
799 fXform.dx = 0;
800 fXform.dy = 0;
801
bungeman@google.come8f05922012-08-16 16:13:40 +0000802 fOffscreen.init(fTypeface->fDWriteFontFace.get(), fXform, SkScalarToFloat(fRec.fTextSize));
803}
804
reed@google.com30ddd612013-07-30 17:47:39 +0000805SkScalerContext_DW::~SkScalerContext_DW() {
bungeman@google.come8f05922012-08-16 16:13:40 +0000806}
807
reed@google.com30ddd612013-07-30 17:47:39 +0000808unsigned SkScalerContext_DW::generateGlyphCount() {
bungeman@google.come8f05922012-08-16 16:13:40 +0000809 if (fGlyphCount < 0) {
810 fGlyphCount = fTypeface->fDWriteFontFace->GetGlyphCount();
811 }
812 return fGlyphCount;
813}
814
reed@google.com30ddd612013-07-30 17:47:39 +0000815uint16_t SkScalerContext_DW::generateCharToGlyph(SkUnichar uni) {
bungeman@google.come8f05922012-08-16 16:13:40 +0000816 uint16_t index = 0;
817 fTypeface->fDWriteFontFace->GetGlyphIndices(reinterpret_cast<UINT32*>(&uni), 1, &index);
818 return index;
819}
820
reed@google.com30ddd612013-07-30 17:47:39 +0000821void SkScalerContext_DW::generateAdvance(SkGlyph* glyph) {
bungeman@google.come8f05922012-08-16 16:13:40 +0000822 //Delta is the difference between the right/left side bearing metric
823 //and where the right/left side bearing ends up after hinting.
824 //DirectWrite does not provide this information.
825 glyph->fRsbDelta = 0;
826 glyph->fLsbDelta = 0;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000827
bungeman@google.come8f05922012-08-16 16:13:40 +0000828 glyph->fAdvanceX = 0;
829 glyph->fAdvanceY = 0;
830
831 uint16_t glyphId = glyph->getGlyphID();
832 DWRITE_GLYPH_METRICS gm;
833 HRVM(fTypeface->fDWriteFontFace->GetDesignGlyphMetrics(&glyphId, 1, &gm),
834 "Could not get design metrics.");
835
836 DWRITE_FONT_METRICS dwfm;
837 fTypeface->fDWriteFontFace->GetMetrics(&dwfm);
838
839 SkScalar advanceX = SkScalarMulDiv(fRec.fTextSize,
840 SkIntToScalar(gm.advanceWidth),
841 SkIntToScalar(dwfm.designUnitsPerEm));
rmistry@google.comd6176b02012-08-23 18:14:13 +0000842
bungeman@google.come8f05922012-08-16 16:13:40 +0000843 if (!(fRec.fFlags & kSubpixelPositioning_Flag)) {
844 advanceX = SkScalarRoundToScalar(advanceX);
845 }
846
847 SkVector vecs[1] = { { advanceX, 0 } };
848 SkMatrix mat;
bungeman@google.com091f51b2013-01-10 18:56:18 +0000849 fRec.getMatrixFrom2x2(&mat);
bungeman@google.come8f05922012-08-16 16:13:40 +0000850 mat.mapVectors(vecs, SK_ARRAY_COUNT(vecs));
851
852 glyph->fAdvanceX = SkScalarToFixed(vecs[0].fX);
853 glyph->fAdvanceY = SkScalarToFixed(vecs[0].fY);
854}
855
reed@google.com30ddd612013-07-30 17:47:39 +0000856void SkScalerContext_DW::generateMetrics(SkGlyph* glyph) {
bungeman@google.come8f05922012-08-16 16:13:40 +0000857 glyph->fWidth = 0;
858
859 this->generateAdvance(glyph);
860
861 //Measure raster size.
862 fXform.dx = SkFixedToFloat(glyph->getSubXFixed());
863 fXform.dy = SkFixedToFloat(glyph->getSubYFixed());
864
865 FLOAT advance = 0;
866
867 UINT16 glyphId = glyph->getGlyphID();
868
869 DWRITE_GLYPH_OFFSET offset;
870 offset.advanceOffset = 0.0f;
871 offset.ascenderOffset = 0.0f;
872
873 DWRITE_GLYPH_RUN run;
874 run.glyphCount = 1;
875 run.glyphAdvances = &advance;
876 run.fontFace = fTypeface->fDWriteFontFace.get();
877 run.fontEmSize = SkScalarToFloat(fRec.fTextSize);
878 run.bidiLevel = 0;
879 run.glyphIndices = &glyphId;
880 run.isSideways = FALSE;
881 run.glyphOffsets = &offset;
882
883 IDWriteFactory* factory;
884 HRVM(get_dwrite_factory(&factory), "Could not get factory.");
885
886 const bool isBW = SkMask::kBW_Format == fRec.fMaskFormat;
887 DWRITE_RENDERING_MODE renderingMode;
888 DWRITE_TEXTURE_TYPE textureType;
889 if (isBW) {
890 renderingMode = DWRITE_RENDERING_MODE_ALIASED;
891 textureType = DWRITE_TEXTURE_ALIASED_1x1;
892 } else {
893 renderingMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC;
894 textureType = DWRITE_TEXTURE_CLEARTYPE_3x1;
895 }
896
897 SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis;
898 HRVM(factory->CreateGlyphRunAnalysis(&run,
899 1.0f, // pixelsPerDip,
900 &fXform,
901 renderingMode,
902 DWRITE_MEASURING_MODE_NATURAL,
903 0.0f, // baselineOriginX,
904 0.0f, // baselineOriginY,
905 &glyphRunAnalysis),
906 "Could not create glyph run analysis.");
rmistry@google.comd6176b02012-08-23 18:14:13 +0000907
bungeman@google.come8f05922012-08-16 16:13:40 +0000908 RECT bbox;
909 HRVM(glyphRunAnalysis->GetAlphaTextureBounds(textureType, &bbox),
910 "Could not get texture bounds.");
911
912 glyph->fWidth = SkToU16(bbox.right - bbox.left);
913 glyph->fHeight = SkToU16(bbox.bottom - bbox.top);
914 glyph->fLeft = SkToS16(bbox.left);
915 glyph->fTop = SkToS16(bbox.top);
916}
917
reed@google.com30ddd612013-07-30 17:47:39 +0000918void SkScalerContext_DW::generateFontMetrics(SkPaint::FontMetrics* mx,
bungeman@google.come8f05922012-08-16 16:13:40 +0000919 SkPaint::FontMetrics* my) {
920 if (!(mx || my))
921 return;
922
bungeman@google.come1b9bad2013-08-27 21:51:37 +0000923 if (mx) {
924 sk_bzero(mx, sizeof(*mx));
925 }
926 if (my) {
927 sk_bzero(my, sizeof(*my));
928 }
929
bungeman@google.come8f05922012-08-16 16:13:40 +0000930 DWRITE_FONT_METRICS dwfm;
931 fTypeface->fDWriteFontFace->GetMetrics(&dwfm);
932
bungeman@google.come1b9bad2013-08-27 21:51:37 +0000933 SkScalar upem = SkIntToScalar(dwfm.designUnitsPerEm);
bungeman@google.come8f05922012-08-16 16:13:40 +0000934 if (mx) {
bungeman@google.com76875782013-08-28 03:16:02 +0000935 mx->fTop = -fRec.fTextSize * SkIntToScalar(dwfm.ascent) / upem;
936 mx->fAscent = mx->fTop;
937 mx->fDescent = fRec.fTextSize * SkIntToScalar(dwfm.descent) / upem;
938 mx->fBottom = mx->fDescent;
939 mx->fLeading = fRec.fTextSize * SkIntToScalar(dwfm.lineGap) / upem;
940 mx->fXHeight = fRec.fTextSize * SkIntToScalar(dwfm.xHeight) / upem;
bungeman@google.come8f05922012-08-16 16:13:40 +0000941 }
942
943 if (my) {
bungeman@google.come1b9bad2013-08-27 21:51:37 +0000944 my->fTop = -fRec.fTextSize * SkIntToScalar(dwfm.ascent) / upem;
bungeman@google.come8f05922012-08-16 16:13:40 +0000945 my->fAscent = my->fTop;
bungeman@google.come1b9bad2013-08-27 21:51:37 +0000946 my->fDescent = fRec.fTextSize * SkIntToScalar(dwfm.descent) / upem;
bungeman@google.come8f05922012-08-16 16:13:40 +0000947 my->fBottom = my->fDescent;
bungeman@google.come1b9bad2013-08-27 21:51:37 +0000948 my->fLeading = fRec.fTextSize * SkIntToScalar(dwfm.lineGap) / upem;
949 my->fXHeight = fRec.fTextSize * SkIntToScalar(dwfm.xHeight) / upem;
bungeman@google.come8f05922012-08-16 16:13:40 +0000950 }
951}
952
953///////////////////////////////////////////////////////////////////////////////
954
955#include "SkColorPriv.h"
956
957static void bilevel_to_bw(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph) {
958 const int width = glyph.fWidth;
959 const size_t dstRB = (width + 7) >> 3;
960 uint8_t* SK_RESTRICT dst = static_cast<uint8_t*>(glyph.fImage);
961
962 int byteCount = width >> 3;
963 int bitCount = width & 7;
964
965 for (int y = 0; y < glyph.fHeight; ++y) {
966 if (byteCount > 0) {
967 for (int i = 0; i < byteCount; ++i) {
968 unsigned byte = 0;
969 byte |= src[0] & (1 << 7);
970 byte |= src[1] & (1 << 6);
971 byte |= src[2] & (1 << 5);
972 byte |= src[3] & (1 << 4);
973 byte |= src[4] & (1 << 3);
974 byte |= src[5] & (1 << 2);
975 byte |= src[6] & (1 << 1);
976 byte |= src[7] & (1 << 0);
977 dst[i] = byte;
978 src += 8;
979 }
980 }
981 if (bitCount > 0) {
982 unsigned byte = 0;
983 unsigned mask = 0x80;
984 for (int i = 0; i < bitCount; i++) {
985 byte |= (src[i]) & mask;
986 mask >>= 1;
987 }
988 dst[byteCount] = byte;
989 }
990 src += bitCount;
991 dst += dstRB;
992 }
993}
994
995template<bool APPLY_PREBLEND>
996static void rgb_to_a8(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph, const uint8_t* table8) {
997 const size_t dstRB = glyph.rowBytes();
998 const U16CPU width = glyph.fWidth;
999 uint8_t* SK_RESTRICT dst = static_cast<uint8_t*>(glyph.fImage);
1000
1001 for (U16CPU y = 0; y < glyph.fHeight; y++) {
1002 for (U16CPU i = 0; i < width; i++) {
1003 U8CPU r = *(src++);
1004 U8CPU g = *(src++);
1005 U8CPU b = *(src++);
1006 dst[i] = sk_apply_lut_if<APPLY_PREBLEND>((r + g + b) / 3, table8);
1007 }
1008 dst = (uint8_t*)((char*)dst + dstRB);
1009 }
1010}
1011
1012template<bool APPLY_PREBLEND>
1013static void rgb_to_lcd16(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph,
1014 const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) {
1015 const size_t dstRB = glyph.rowBytes();
1016 const U16CPU width = glyph.fWidth;
1017 uint16_t* SK_RESTRICT dst = static_cast<uint16_t*>(glyph.fImage);
1018
1019 for (U16CPU y = 0; y < glyph.fHeight; y++) {
1020 for (U16CPU i = 0; i < width; i++) {
1021 U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableR);
1022 U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableG);
1023 U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableB);
1024 dst[i] = SkPack888ToRGB16(r, g, b);
1025 }
1026 dst = (uint16_t*)((char*)dst + dstRB);
1027 }
1028}
1029
1030template<bool APPLY_PREBLEND>
1031static void rgb_to_lcd32(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph,
1032 const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) {
1033 const size_t dstRB = glyph.rowBytes();
1034 const U16CPU width = glyph.fWidth;
1035 SkPMColor* SK_RESTRICT dst = static_cast<SkPMColor*>(glyph.fImage);
1036
1037 for (U16CPU y = 0; y < glyph.fHeight; y++) {
1038 for (U16CPU i = 0; i < width; i++) {
1039 U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableR);
1040 U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableG);
1041 U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableB);
1042 dst[i] = SkPackARGB32(0xFF, r, g, b);
1043 }
1044 dst = (SkPMColor*)((char*)dst + dstRB);
1045 }
1046}
1047
reed@google.com30ddd612013-07-30 17:47:39 +00001048void SkScalerContext_DW::generateImage(const SkGlyph& glyph) {
bungeman@google.come8f05922012-08-16 16:13:40 +00001049 SkAutoMutexAcquire ac(gFTMutex);
1050
bungeman@google.come8f05922012-08-16 16:13:40 +00001051 const bool isBW = SkMask::kBW_Format == fRec.fMaskFormat;
1052 const bool isAA = !isLCD(fRec);
1053
1054 //Create the mask.
1055 const void* bits = fOffscreen.draw(glyph, isBW);
1056 if (!bits) {
1057 sk_bzero(glyph.fImage, glyph.computeImageSize());
1058 return;
1059 }
1060
1061 //Copy the mask into the glyph.
bungeman@google.come8f05922012-08-16 16:13:40 +00001062 const uint8_t* src = (const uint8_t*)bits;
1063 if (isBW) {
1064 bilevel_to_bw(src, glyph);
1065 } else if (isAA) {
bungeman@google.coma76de722012-10-26 19:35:54 +00001066 if (fPreBlend.isApplicable()) {
1067 rgb_to_a8<true>(src, glyph, fPreBlend.fG);
bungeman@google.come8f05922012-08-16 16:13:40 +00001068 } else {
bungeman@google.coma76de722012-10-26 19:35:54 +00001069 rgb_to_a8<false>(src, glyph, fPreBlend.fG);
bungeman@google.come8f05922012-08-16 16:13:40 +00001070 }
1071 } else if (SkMask::kLCD16_Format == glyph.fMaskFormat) {
bungeman@google.coma76de722012-10-26 19:35:54 +00001072 if (fPreBlend.isApplicable()) {
1073 rgb_to_lcd16<true>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
bungeman@google.come8f05922012-08-16 16:13:40 +00001074 } else {
bungeman@google.coma76de722012-10-26 19:35:54 +00001075 rgb_to_lcd16<false>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
bungeman@google.come8f05922012-08-16 16:13:40 +00001076 }
1077 } else {
1078 SkASSERT(SkMask::kLCD32_Format == glyph.fMaskFormat);
bungeman@google.coma76de722012-10-26 19:35:54 +00001079 if (fPreBlend.isApplicable()) {
1080 rgb_to_lcd32<true>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
bungeman@google.come8f05922012-08-16 16:13:40 +00001081 } else {
bungeman@google.coma76de722012-10-26 19:35:54 +00001082 rgb_to_lcd32<false>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
bungeman@google.come8f05922012-08-16 16:13:40 +00001083 }
1084 }
1085}
1086
reed@google.com30ddd612013-07-30 17:47:39 +00001087void SkScalerContext_DW::generatePath(const SkGlyph& glyph, SkPath* path) {
bungeman@google.come8f05922012-08-16 16:13:40 +00001088 SkAutoMutexAcquire ac(gFTMutex);
1089
1090 SkASSERT(&glyph && path);
1091
1092 path->reset();
1093
1094 SkTScopedComPtr<IDWriteGeometrySink> geometryToPath;
1095 HRVM(SkDWriteGeometrySink::Create(path, &geometryToPath),
1096 "Could not create geometry to path converter.");
1097 uint16_t glyphId = glyph.getGlyphID();
1098 //TODO: convert to<->from DIUs? This would make a difference if hinting.
1099 //It may not be needed, it appears that DirectWrite only hints at em size.
1100 HRVM(fTypeface->fDWriteFontFace->GetGlyphRunOutline(SkScalarToFloat(fRec.fTextSize),
1101 &glyphId,
1102 NULL, //advances
1103 NULL, //offsets
1104 1, //num glyphs
1105 FALSE, //sideways
1106 FALSE, //rtl
1107 geometryToPath.get()),
1108 "Could not create glyph outline.");
bungeman@google.com091f51b2013-01-10 18:56:18 +00001109
1110 SkMatrix mat;
1111 fRec.getMatrixFrom2x2(&mat);
1112 path->transform(mat);
bungeman@google.come8f05922012-08-16 16:13:40 +00001113}
1114
reed@google.com5526ede2013-03-25 13:03:37 +00001115void DWriteFontTypeface::onGetFontDescriptor(SkFontDescriptor* desc,
1116 bool* isLocalStream) const {
bungeman@google.com94acfb52012-08-31 15:41:09 +00001117 // Get the family name.
1118 SkTScopedComPtr<IDWriteLocalizedStrings> dwFamilyNames;
reed@google.com5526ede2013-03-25 13:03:37 +00001119 HRV(fDWriteFontFamily->GetFamilyNames(&dwFamilyNames));
bungeman@google.com94acfb52012-08-31 15:41:09 +00001120
1121 UINT32 dwFamilyNamesLength;
1122 HRV(dwFamilyNames->GetStringLength(0, &dwFamilyNamesLength));
1123
bungeman@google.com71033442013-05-01 14:21:20 +00001124 SkSMallocWCHAR dwFamilyNameChar(dwFamilyNamesLength+1);
1125 HRV(dwFamilyNames->GetString(0, dwFamilyNameChar.get(), dwFamilyNamesLength+1));
bungeman@google.com94acfb52012-08-31 15:41:09 +00001126
bungeman@google.com71033442013-05-01 14:21:20 +00001127 SkString utf8FamilyName;
1128 HRV(wchar_to_skstring(dwFamilyNameChar.get(), &utf8FamilyName));
bungeman@google.com94acfb52012-08-31 15:41:09 +00001129
bungeman@google.com71033442013-05-01 14:21:20 +00001130 desc->setFamilyName(utf8FamilyName.c_str());
reed@google.com5526ede2013-03-25 13:03:37 +00001131 *isLocalStream = SkToBool(fDWriteFontFileLoader.get());
bungeman@google.come8f05922012-08-16 16:13:40 +00001132}
1133
bungeman@google.com7bdd6142013-07-15 19:42:57 +00001134int DWriteFontTypeface::onCountGlyphs() const {
1135 return fDWriteFontFace->GetGlyphCount();
1136}
1137
1138int DWriteFontTypeface::onGetUPEM() const {
1139 DWRITE_FONT_METRICS metrics;
1140 fDWriteFontFace->GetMetrics(&metrics);
1141 return metrics.designUnitsPerEm;
1142}
1143
bungeman@google.coma9802692013-08-07 02:45:25 +00001144class LocalizedStrings_IDWriteLocalizedStrings : public SkTypeface::LocalizedStrings {
1145public:
1146 /** Takes ownership of the IDWriteLocalizedStrings. */
1147 explicit LocalizedStrings_IDWriteLocalizedStrings(IDWriteLocalizedStrings* strings)
1148 : fIndex(0), fStrings(strings)
1149 { }
1150
1151 virtual bool next(SkTypeface::LocalizedString* localizedString) SK_OVERRIDE {
1152 if (fIndex >= fStrings->GetCount()) {
1153 return false;
1154 }
1155
1156 // String
1157 UINT32 stringLength;
1158 HRBM(fStrings->GetStringLength(fIndex, &stringLength), "Could not get string length.");
1159 stringLength += 1;
1160
1161 SkSMallocWCHAR wString(stringLength);
1162 HRBM(fStrings->GetString(fIndex, wString.get(), stringLength), "Could not get string.");
1163
1164 HRB(wchar_to_skstring(wString.get(), &localizedString->fString));
1165
1166 // Locale
1167 UINT32 localeLength;
1168 HRBM(fStrings->GetLocaleNameLength(fIndex, &localeLength), "Could not get locale length.");
1169 localeLength += 1;
1170
1171 SkSMallocWCHAR wLocale(localeLength);
1172 HRBM(fStrings->GetLocaleName(fIndex, wLocale.get(), localeLength), "Could not get locale.");
1173
1174 HRB(wchar_to_skstring(wLocale.get(), &localizedString->fLanguage));
1175
1176 ++fIndex;
1177 return true;
1178 }
1179
1180private:
1181 UINT32 fIndex;
1182 SkTScopedComPtr<IDWriteLocalizedStrings> fStrings;
1183};
1184
bungeman@google.com839702b2013-08-07 17:09:22 +00001185SkTypeface::LocalizedStrings* DWriteFontTypeface::onCreateFamilyNameIterator() const {
bungeman@google.coma9802692013-08-07 02:45:25 +00001186 SkTScopedComPtr<IDWriteLocalizedStrings> familyNames;
1187 HRNM(fDWriteFontFamily->GetFamilyNames(&familyNames), "Could not obtain family names.");
1188
1189 return new LocalizedStrings_IDWriteLocalizedStrings(familyNames.release());
1190}
1191
bungeman@google.comb10b51f2013-08-01 20:18:41 +00001192int DWriteFontTypeface::onGetTableTags(SkFontTableTag tags[]) const {
1193 DWRITE_FONT_FACE_TYPE type = fDWriteFontFace->GetType();
1194 if (type != DWRITE_FONT_FACE_TYPE_CFF &&
1195 type != DWRITE_FONT_FACE_TYPE_TRUETYPE &&
1196 type != DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION)
1197 {
1198 return 0;
1199 }
1200
1201 int ttcIndex;
1202 SkAutoTUnref<SkStream> stream(this->openStream(&ttcIndex));
1203 return stream.get() ? SkFontStream::GetTableTags(stream, ttcIndex, tags) : 0;
1204}
1205
1206class AutoDWriteTable {
1207public:
1208 AutoDWriteTable(IDWriteFontFace* fontFace, UINT32 beTag) : fFontFace(fontFace), fExists(FALSE) {
1209 // Any errors are ignored, user must check fExists anyway.
1210 fontFace->TryGetFontTable(beTag,
1211 reinterpret_cast<const void **>(&fData), &fSize, &fLock, &fExists);
1212 }
1213 ~AutoDWriteTable() {
1214 if (fExists) {
1215 fFontFace->ReleaseFontTable(fLock);
1216 }
1217 }
1218
1219 const uint8_t* fData;
1220 UINT32 fSize;
1221 BOOL fExists;
1222private:
1223 // Borrowed reference, the user must ensure the fontFace stays alive.
1224 IDWriteFontFace* fFontFace;
1225 void* fLock;
1226};
1227
1228size_t DWriteFontTypeface::onGetTableData(SkFontTableTag tag, size_t offset,
1229 size_t length, void* data) const
1230{
1231 AutoDWriteTable table(fDWriteFontFace.get(), SkEndian_SwapBE32(tag));
1232 if (!table.fExists) {
1233 return 0;
1234 }
1235
1236 if (offset > table.fSize) {
1237 return 0;
1238 }
1239 size_t size = SkTMin(length, table.fSize - offset);
1240 if (NULL != data) {
1241 memcpy(data, table.fData + offset, size);
1242 }
1243
1244 return size;
1245}
1246
bungeman@google.com4bbc5242013-05-02 14:01:36 +00001247template <typename T> class SkAutoIDWriteUnregister {
1248public:
1249 SkAutoIDWriteUnregister(IDWriteFactory* factory, T* unregister)
1250 : fFactory(factory), fUnregister(unregister)
1251 { }
1252
1253 ~SkAutoIDWriteUnregister() {
1254 if (fUnregister) {
1255 unregister(fFactory, fUnregister);
1256 }
1257 }
1258
1259 T* detatch() {
1260 T* old = fUnregister;
1261 fUnregister = NULL;
1262 return old;
1263 }
1264
1265private:
1266 HRESULT unregister(IDWriteFactory* factory, IDWriteFontFileLoader* unregister) {
1267 return factory->UnregisterFontFileLoader(unregister);
1268 }
1269
1270 HRESULT unregister(IDWriteFactory* factory, IDWriteFontCollectionLoader* unregister) {
1271 return factory->UnregisterFontCollectionLoader(unregister);
1272 }
1273
1274 IDWriteFactory* fFactory;
1275 T* fUnregister;
1276};
1277
1278static SkTypeface* create_from_stream(SkStream* stream, int ttcIndex) {
bungeman@google.come8f05922012-08-16 16:13:40 +00001279 IDWriteFactory* factory;
1280 HRN(get_dwrite_factory(&factory));
1281
1282 SkTScopedComPtr<StreamFontFileLoader> fontFileLoader;
1283 HRN(StreamFontFileLoader::Create(stream, &fontFileLoader));
1284 HRN(factory->RegisterFontFileLoader(fontFileLoader.get()));
bungeman@google.com4bbc5242013-05-02 14:01:36 +00001285 SkAutoIDWriteUnregister<StreamFontFileLoader> autoUnregisterFontFileLoader(
1286 factory, fontFileLoader.get());
bungeman@google.come8f05922012-08-16 16:13:40 +00001287
bungeman@google.com4bbc5242013-05-02 14:01:36 +00001288 SkTScopedComPtr<StreamFontCollectionLoader> fontCollectionLoader;
1289 HRN(StreamFontCollectionLoader::Create(fontFileLoader.get(), &fontCollectionLoader));
1290 HRN(factory->RegisterFontCollectionLoader(fontCollectionLoader.get()));
1291 SkAutoIDWriteUnregister<StreamFontCollectionLoader> autoUnregisterFontCollectionLoader(
1292 factory, fontCollectionLoader.get());
bungeman@google.come8f05922012-08-16 16:13:40 +00001293
bungeman@google.com4bbc5242013-05-02 14:01:36 +00001294 SkTScopedComPtr<IDWriteFontCollection> fontCollection;
1295 HRN(factory->CreateCustomFontCollection(fontCollectionLoader.get(), NULL, 0, &fontCollection));
bungeman@google.come8f05922012-08-16 16:13:40 +00001296
bungeman@google.com4bbc5242013-05-02 14:01:36 +00001297 // Find the first non-simulated font which has the given ttc index.
1298 UINT32 familyCount = fontCollection->GetFontFamilyCount();
1299 for (UINT32 familyIndex = 0; familyIndex < familyCount; ++familyIndex) {
1300 SkTScopedComPtr<IDWriteFontFamily> fontFamily;
1301 HRN(fontCollection->GetFontFamily(familyIndex, &fontFamily));
bungeman@google.come8f05922012-08-16 16:13:40 +00001302
bungeman@google.com4bbc5242013-05-02 14:01:36 +00001303 UINT32 fontCount = fontFamily->GetFontCount();
1304 for (UINT32 fontIndex = 0; fontIndex < fontCount; ++fontIndex) {
1305 SkTScopedComPtr<IDWriteFont> font;
1306 HRN(fontFamily->GetFont(fontIndex, &font));
1307 if (font->GetSimulations() != DWRITE_FONT_SIMULATIONS_NONE) {
1308 continue;
1309 }
bungeman@google.come8f05922012-08-16 16:13:40 +00001310
bungeman@google.com4bbc5242013-05-02 14:01:36 +00001311 SkTScopedComPtr<IDWriteFontFace> fontFace;
1312 HRN(font->CreateFontFace(&fontFace));
bungeman@google.come8f05922012-08-16 16:13:40 +00001313
bungeman@google.com4bbc5242013-05-02 14:01:36 +00001314 UINT32 faceIndex = fontFace->GetIndex();
1315 if (faceIndex == ttcIndex) {
bungeman@google.combfc6cc42013-08-21 15:20:43 +00001316 return DWriteFontTypeface::Create(fontFace.get(), font.get(), fontFamily.get(),
1317 autoUnregisterFontFileLoader.detatch(),
1318 autoUnregisterFontCollectionLoader.detatch());
bungeman@google.com4bbc5242013-05-02 14:01:36 +00001319 }
1320 }
1321 }
1322
1323 return NULL;
bungeman@google.come8f05922012-08-16 16:13:40 +00001324}
1325
reed@google.com177dc6e2013-03-21 20:55:10 +00001326SkStream* DWriteFontTypeface::onOpenStream(int* ttcIndex) const {
bungeman@google.com4bbc5242013-05-02 14:01:36 +00001327 *ttcIndex = fDWriteFontFace->GetIndex();
bungeman@google.come8f05922012-08-16 16:13:40 +00001328
1329 UINT32 numFiles;
reed@google.com177dc6e2013-03-21 20:55:10 +00001330 HRNM(fDWriteFontFace->GetFiles(&numFiles, NULL),
bungeman@google.come8f05922012-08-16 16:13:40 +00001331 "Could not get number of font files.");
1332 if (numFiles != 1) {
1333 return NULL;
1334 }
1335
1336 SkTScopedComPtr<IDWriteFontFile> fontFile;
reed@google.com177dc6e2013-03-21 20:55:10 +00001337 HRNM(fDWriteFontFace->GetFiles(&numFiles, &fontFile), "Could not get font files.");
bungeman@google.come8f05922012-08-16 16:13:40 +00001338
1339 const void* fontFileKey;
1340 UINT32 fontFileKeySize;
1341 HRNM(fontFile->GetReferenceKey(&fontFileKey, &fontFileKeySize),
1342 "Could not get font file reference key.");
1343
1344 SkTScopedComPtr<IDWriteFontFileLoader> fontFileLoader;
1345 HRNM(fontFile->GetLoader(&fontFileLoader), "Could not get font file loader.");
1346
1347 SkTScopedComPtr<IDWriteFontFileStream> fontFileStream;
1348 HRNM(fontFileLoader->CreateStreamFromKey(fontFileKey, fontFileKeySize,
1349 &fontFileStream),
1350 "Could not create font file stream.");
1351
1352 return SkNEW_ARGS(SkDWriteFontFileStream, (fontFileStream.get()));
1353}
1354
reed@google.com0da48612013-03-19 16:06:52 +00001355SkScalerContext* DWriteFontTypeface::onCreateScalerContext(const SkDescriptor* desc) const {
reed@google.com30ddd612013-07-30 17:47:39 +00001356 return SkNEW_ARGS(SkScalerContext_DW, (const_cast<DWriteFontTypeface*>(this), desc));
bungeman@google.come8f05922012-08-16 16:13:40 +00001357}
1358
1359static HRESULT get_by_family_name(const char familyName[], IDWriteFontFamily** fontFamily) {
1360 IDWriteFactory* factory;
1361 HR(get_dwrite_factory(&factory));
1362
1363 SkTScopedComPtr<IDWriteFontCollection> sysFontCollection;
1364 HR(factory->GetSystemFontCollection(&sysFontCollection, FALSE));
1365
bungeman@google.com71033442013-05-01 14:21:20 +00001366 SkSMallocWCHAR wideFamilyName;
1367 HR(cstring_to_wchar(familyName, &wideFamilyName));
bungeman@google.come8f05922012-08-16 16:13:40 +00001368
1369 UINT32 index;
1370 BOOL exists;
bungeman@google.com71033442013-05-01 14:21:20 +00001371 HR(sysFontCollection->FindFamilyName(wideFamilyName.get(), &index, &exists));
bungeman@google.come8f05922012-08-16 16:13:40 +00001372
1373 if (exists) {
1374 HR(sysFontCollection->GetFontFamily(index, fontFamily));
1375 return S_OK;
1376 }
1377 return S_FALSE;
1378}
1379
reed@google.com0da48612013-03-19 16:06:52 +00001380void DWriteFontTypeface::onFilterRec(SkScalerContext::Rec* rec) const {
commit-bot@chromium.orgc5fd4612013-05-06 22:23:08 +00001381 if (rec->fFlags & SkScalerContext::kLCD_BGROrder_Flag ||
1382 rec->fFlags & SkScalerContext::kLCD_Vertical_Flag)
1383 {
1384 rec->fMaskFormat = SkMask::kA8_Format;
1385 }
1386
bungeman@google.come8f05922012-08-16 16:13:40 +00001387 unsigned flagsWeDontSupport = SkScalerContext::kDevKernText_Flag |
1388 SkScalerContext::kAutohinting_Flag |
1389 SkScalerContext::kEmbeddedBitmapText_Flag |
1390 SkScalerContext::kEmbolden_Flag |
1391 SkScalerContext::kLCD_BGROrder_Flag |
1392 SkScalerContext::kLCD_Vertical_Flag;
1393 rec->fFlags &= ~flagsWeDontSupport;
1394
1395 SkPaint::Hinting h = rec->getHinting();
1396 // DirectWrite does not provide for hinting hints.
1397 h = SkPaint::kSlight_Hinting;
1398 rec->setHinting(h);
1399
1400#if SK_FONT_HOST_USE_SYSTEM_SETTINGS
1401 IDWriteFactory* factory;
1402 if (SUCCEEDED(get_dwrite_factory(&factory))) {
1403 SkTScopedComPtr<IDWriteRenderingParams> defaultRenderingParams;
1404 if (SUCCEEDED(factory->CreateRenderingParams(&defaultRenderingParams))) {
1405 float gamma = defaultRenderingParams->GetGamma();
1406 rec->setDeviceGamma(SkFloatToScalar(gamma));
1407 rec->setPaintGamma(SkFloatToScalar(gamma));
rmistry@google.comd6176b02012-08-23 18:14:13 +00001408
bungeman@google.come8f05922012-08-16 16:13:40 +00001409 rec->setContrast(SkFloatToScalar(defaultRenderingParams->GetEnhancedContrast()));
1410 }
1411 }
1412#endif
1413}
1414
1415///////////////////////////////////////////////////////////////////////////////
1416//PDF Support
1417
1418using namespace skia_advanced_typeface_metrics_utils;
1419
1420// Construct Glyph to Unicode table.
1421// Unicode code points that require conjugate pairs in utf16 are not
1422// supported.
1423// TODO(arthurhsu): Add support for conjugate pairs. It looks like that may
1424// require parsing the TTF cmap table (platform 4, encoding 12) directly instead
1425// of calling GetFontUnicodeRange().
1426// TODO(bungeman): This never does what anyone wants.
1427// What is really wanted is the text to glyphs mapping
1428static void populate_glyph_to_unicode(IDWriteFontFace* fontFace,
1429 const unsigned glyphCount,
1430 SkTDArray<SkUnichar>* glyphToUnicode) {
1431 HRESULT hr = S_OK;
1432
1433 //Do this like free type instead
1434 UINT32 count = 0;
1435 for (UINT32 c = 0; c < 0x10FFFF; ++c) {
1436 UINT16 glyph;
1437 hr = fontFace->GetGlyphIndices(&c, 1, &glyph);
1438 if (glyph > 0) {
1439 ++count;
1440 }
1441 }
1442
1443 SkAutoTArray<UINT32> chars(count);
1444 count = 0;
1445 for (UINT32 c = 0; c < 0x10FFFF; ++c) {
1446 UINT16 glyph;
1447 hr = fontFace->GetGlyphIndices(&c, 1, &glyph);
1448 if (glyph > 0) {
1449 chars[count] = c;
1450 ++count;
1451 }
1452 }
1453
1454 SkAutoTArray<UINT16> glyph(count);
1455 fontFace->GetGlyphIndices(chars.get(), count, glyph.get());
1456
1457 USHORT maxGlyph = 0;
1458 for (USHORT j = 0; j < count; ++j) {
1459 if (glyph[j] > maxGlyph) maxGlyph = glyph[j];
1460 }
1461
1462 glyphToUnicode->setCount(maxGlyph+1);
1463 for (size_t j = 0; j < maxGlyph+1u; ++j) {
1464 (*glyphToUnicode)[j] = 0;
1465 }
1466
1467 //'invert'
1468 for (USHORT j = 0; j < count; ++j) {
1469 if (glyph[j] < glyphCount && (*glyphToUnicode)[glyph[j]] == 0) {
1470 (*glyphToUnicode)[glyph[j]] = chars[j];
1471 }
1472 }
1473}
1474
1475static bool getWidthAdvance(IDWriteFontFace* fontFace, int gId, int16_t* advance) {
1476 SkASSERT(advance);
1477
1478 UINT16 glyphId = gId;
1479 DWRITE_GLYPH_METRICS gm;
1480 HRESULT hr = fontFace->GetDesignGlyphMetrics(&glyphId, 1, &gm);
1481
1482 if (FAILED(hr)) {
1483 *advance = 0;
1484 return false;
1485 }
1486
1487 *advance = gm.advanceWidth;
1488 return true;
1489}
1490
bungeman@google.comb10b51f2013-08-01 20:18:41 +00001491template<typename T> class AutoTDWriteTable : public AutoDWriteTable {
bungeman@google.come8f05922012-08-16 16:13:40 +00001492public:
bungeman@google.comb10b51f2013-08-01 20:18:41 +00001493 static const UINT32 tag = DWRITE_MAKE_OPENTYPE_TAG(T::TAG0, T::TAG1, T::TAG2, T::TAG3);
1494 AutoTDWriteTable(IDWriteFontFace* fontFace) : AutoDWriteTable(fontFace, tag) { }
bungeman@google.come8f05922012-08-16 16:13:40 +00001495
bungeman@google.comb10b51f2013-08-01 20:18:41 +00001496 const T* operator->() const { return reinterpret_cast<const T*>(fData); }
bungeman@google.come8f05922012-08-16 16:13:40 +00001497};
1498
reed@google.com2689f612013-03-20 20:01:47 +00001499SkAdvancedTypefaceMetrics* DWriteFontTypeface::onGetAdvancedTypefaceMetrics(
bungeman@google.come8f05922012-08-16 16:13:40 +00001500 SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo,
1501 const uint32_t* glyphIDs,
reed@google.com2689f612013-03-20 20:01:47 +00001502 uint32_t glyphIDsCount) const {
bungeman@google.come8f05922012-08-16 16:13:40 +00001503
1504 SkAdvancedTypefaceMetrics* info = NULL;
1505
1506 HRESULT hr = S_OK;
1507
reed@google.com2689f612013-03-20 20:01:47 +00001508 const unsigned glyphCount = fDWriteFontFace->GetGlyphCount();
bungeman@google.come8f05922012-08-16 16:13:40 +00001509
1510 DWRITE_FONT_METRICS dwfm;
reed@google.com2689f612013-03-20 20:01:47 +00001511 fDWriteFontFace->GetMetrics(&dwfm);
bungeman@google.come8f05922012-08-16 16:13:40 +00001512
1513 info = new SkAdvancedTypefaceMetrics;
1514 info->fEmSize = dwfm.designUnitsPerEm;
1515 info->fMultiMaster = false;
1516 info->fLastGlyphID = SkToU16(glyphCount - 1);
1517 info->fStyle = 0;
1518
1519
1520 SkTScopedComPtr<IDWriteLocalizedStrings> familyNames;
1521 SkTScopedComPtr<IDWriteLocalizedStrings> faceNames;
reed@google.com2689f612013-03-20 20:01:47 +00001522 hr = fDWriteFontFamily->GetFamilyNames(&familyNames);
1523 hr = fDWriteFont->GetFaceNames(&faceNames);
bungeman@google.come8f05922012-08-16 16:13:40 +00001524
1525 UINT32 familyNameLength;
1526 hr = familyNames->GetStringLength(0, &familyNameLength);
1527
1528 UINT32 faceNameLength;
1529 hr = faceNames->GetStringLength(0, &faceNameLength);
1530
bungeman@google.com71033442013-05-01 14:21:20 +00001531 UINT32 size = familyNameLength+1+faceNameLength+1;
1532 SkSMallocWCHAR wFamilyName(size);
1533 hr = familyNames->GetString(0, wFamilyName.get(), size);
bungeman@google.come8f05922012-08-16 16:13:40 +00001534 wFamilyName[familyNameLength] = L' ';
1535 hr = faceNames->GetString(0, &wFamilyName[familyNameLength+1], size - faceNameLength + 1);
1536
bungeman@google.com71033442013-05-01 14:21:20 +00001537 hr = wchar_to_skstring(wFamilyName.get(), &info->fFontName);
bungeman@google.come8f05922012-08-16 16:13:40 +00001538
1539 if (perGlyphInfo & SkAdvancedTypefaceMetrics::kToUnicode_PerGlyphInfo) {
reed@google.com2689f612013-03-20 20:01:47 +00001540 populate_glyph_to_unicode(fDWriteFontFace.get(), glyphCount, &(info->fGlyphToUnicode));
bungeman@google.come8f05922012-08-16 16:13:40 +00001541 }
1542
reed@google.com2689f612013-03-20 20:01:47 +00001543 DWRITE_FONT_FACE_TYPE fontType = fDWriteFontFace->GetType();
bungeman@google.come8f05922012-08-16 16:13:40 +00001544 if (fontType == DWRITE_FONT_FACE_TYPE_TRUETYPE ||
1545 fontType == DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION) {
1546 info->fType = SkAdvancedTypefaceMetrics::kTrueType_Font;
1547 } else {
1548 info->fType = SkAdvancedTypefaceMetrics::kOther_Font;
1549 info->fItalicAngle = 0;
1550 info->fAscent = dwfm.ascent;;
1551 info->fDescent = dwfm.descent;
1552 info->fStemV = 0;
1553 info->fCapHeight = dwfm.capHeight;
1554 info->fBBox = SkIRect::MakeEmpty();
1555 return info;
1556 }
1557
bungeman@google.comb10b51f2013-08-01 20:18:41 +00001558 AutoTDWriteTable<SkOTTableHead> headTable(fDWriteFontFace.get());
1559 AutoTDWriteTable<SkOTTablePostScript> postTable(fDWriteFontFace.get());
1560 AutoTDWriteTable<SkOTTableHorizontalHeader> hheaTable(fDWriteFontFace.get());
1561 AutoTDWriteTable<SkOTTableOS2> os2Table(fDWriteFontFace.get());
bungeman@google.come8f05922012-08-16 16:13:40 +00001562 if (!headTable.fExists || !postTable.fExists || !hheaTable.fExists || !os2Table.fExists) {
1563 info->fItalicAngle = 0;
1564 info->fAscent = dwfm.ascent;;
1565 info->fDescent = dwfm.descent;
1566 info->fStemV = 0;
1567 info->fCapHeight = dwfm.capHeight;
1568 info->fBBox = SkIRect::MakeEmpty();
1569 return info;
1570 }
1571
1572 //There exist CJK fonts which set the IsFixedPitch and Monospace bits,
1573 //but have full width, latin half-width, and half-width kana.
1574 bool fixedWidth = (postTable->isFixedPitch &&
1575 (1 == SkEndian_SwapBE16(hheaTable->numberOfHMetrics)));
1576 //Monospace
1577 if (fixedWidth) {
1578 info->fStyle |= SkAdvancedTypefaceMetrics::kFixedPitch_Style;
1579 }
1580 //Italic
1581 if (os2Table->version.v0.fsSelection.field.Italic) {
1582 info->fStyle |= SkAdvancedTypefaceMetrics::kItalic_Style;
1583 }
bungeman@google.come8f05922012-08-16 16:13:40 +00001584 //Script
1585 if (SkPanose::FamilyType::Script == os2Table->version.v0.panose.bFamilyType.value) {
1586 info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style;
1587 //Serif
1588 } else if (SkPanose::FamilyType::TextAndDisplay == os2Table->version.v0.panose.bFamilyType.value &&
1589 SkPanose::Data::TextAndDisplay::SerifStyle::Triangle <= os2Table->version.v0.panose.data.textAndDisplay.bSerifStyle.value &&
1590 SkPanose::Data::TextAndDisplay::SerifStyle::NoFit != os2Table->version.v0.panose.data.textAndDisplay.bSerifStyle.value) {
1591 info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style;
1592 }
1593
1594 info->fItalicAngle = SkEndian_SwapBE32(postTable->italicAngle) >> 16;
1595
1596 info->fAscent = SkToS16(dwfm.ascent);
1597 info->fDescent = SkToS16(dwfm.descent);
1598 info->fCapHeight = SkToS16(dwfm.capHeight);
1599
1600 info->fBBox = SkIRect::MakeLTRB((int32_t)SkEndian_SwapBE16((uint16_t)headTable->xMin),
1601 (int32_t)SkEndian_SwapBE16((uint16_t)headTable->yMax),
1602 (int32_t)SkEndian_SwapBE16((uint16_t)headTable->xMax),
1603 (int32_t)SkEndian_SwapBE16((uint16_t)headTable->yMin));
1604
1605 //TODO: is this even desired? It seems PDF only wants this value for Type1
1606 //fonts, and we only get here for TrueType fonts.
1607 info->fStemV = 0;
1608 /*
1609 // Figure out a good guess for StemV - Min width of i, I, !, 1.
1610 // This probably isn't very good with an italic font.
1611 int16_t min_width = SHRT_MAX;
1612 info->fStemV = 0;
1613 char stem_chars[] = {'i', 'I', '!', '1'};
1614 for (size_t i = 0; i < SK_ARRAY_COUNT(stem_chars); i++) {
1615 ABC abcWidths;
1616 if (GetCharABCWidths(hdc, stem_chars[i], stem_chars[i], &abcWidths)) {
1617 int16_t width = abcWidths.abcB;
1618 if (width > 0 && width < min_width) {
1619 min_width = width;
1620 info->fStemV = min_width;
1621 }
1622 }
1623 }
1624 */
rmistry@google.comd6176b02012-08-23 18:14:13 +00001625
bungeman@google.come8f05922012-08-16 16:13:40 +00001626 // If Restricted, the font may not be embedded in a document.
1627 // If not Restricted, the font can be embedded.
1628 // If PreviewPrint, the embedding is read-only.
1629 if (os2Table->version.v0.fsType.field.Restricted) {
1630 info->fType = SkAdvancedTypefaceMetrics::kNotEmbeddable_Font;
1631 } else if (perGlyphInfo & SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo) {
1632 if (fixedWidth) {
1633 appendRange(&info->fGlyphWidths, 0);
1634 int16_t advance;
reed@google.com2689f612013-03-20 20:01:47 +00001635 getWidthAdvance(fDWriteFontFace.get(), 1, &advance);
bungeman@google.come8f05922012-08-16 16:13:40 +00001636 info->fGlyphWidths->fAdvance.append(1, &advance);
1637 finishRange(info->fGlyphWidths.get(), 0,
1638 SkAdvancedTypefaceMetrics::WidthRange::kDefault);
1639 } else {
1640 info->fGlyphWidths.reset(
reed@google.com2689f612013-03-20 20:01:47 +00001641 getAdvanceData(fDWriteFontFace.get(),
bungeman@google.come8f05922012-08-16 16:13:40 +00001642 glyphCount,
1643 glyphIDs,
1644 glyphIDsCount,
1645 getWidthAdvance));
1646 }
1647 }
1648
1649 return info;
1650}
reed@google.com070da5e2013-03-27 20:01:49 +00001651
reed@google.com30ddd612013-07-30 17:47:39 +00001652static SkTypeface* create_typeface(const SkTypeface* familyFace,
1653 const char familyName[],
bungeman@google.combfc6cc42013-08-21 15:20:43 +00001654 unsigned style,
1655 SkFontMgr_DirectWrite* fontMgr) {
reed@google.com30ddd612013-07-30 17:47:39 +00001656 HRESULT hr;
1657 SkTScopedComPtr<IDWriteFontFamily> fontFamily;
1658 if (familyFace) {
1659 const DWriteFontTypeface* face = static_cast<const DWriteFontTypeface*>(familyFace);
1660 *(&fontFamily) = SkRefComPtr(face->fDWriteFontFamily.get());
1661
1662 } else if (familyName) {
1663 hr = get_by_family_name(familyName, &fontFamily);
1664 }
1665
1666 if (NULL == fontFamily.get()) {
1667 //No good family found, go with default.
1668 SkTScopedComPtr<IDWriteFont> font;
1669 hr = get_default_font(&font);
1670 hr = font->GetFontFamily(&fontFamily);
1671 }
1672
1673 SkTScopedComPtr<IDWriteFont> font;
1674 DWRITE_FONT_WEIGHT weight = (style & SkTypeface::kBold)
1675 ? DWRITE_FONT_WEIGHT_BOLD
1676 : DWRITE_FONT_WEIGHT_NORMAL;
1677 DWRITE_FONT_STRETCH stretch = DWRITE_FONT_STRETCH_UNDEFINED;
1678 DWRITE_FONT_STYLE italic = (style & SkTypeface::kItalic)
1679 ? DWRITE_FONT_STYLE_ITALIC
1680 : DWRITE_FONT_STYLE_NORMAL;
1681 hr = fontFamily->GetFirstMatchingFont(weight, stretch, italic, &font);
1682
1683 SkTScopedComPtr<IDWriteFontFace> fontFace;
1684 hr = font->CreateFontFace(&fontFace);
1685
bungeman@google.combfc6cc42013-08-21 15:20:43 +00001686 return fontMgr->createTypefaceFromDWriteFont(fontFace.get(), font.get(), fontFamily.get());
reed@google.com30ddd612013-07-30 17:47:39 +00001687}
1688
1689SkTypeface* DWriteFontTypeface::onRefMatchingStyle(Style style) const {
bungeman@google.combfc6cc42013-08-21 15:20:43 +00001690 SkFontMgr_DirectWrite* fontMgr = NULL;
1691 // todo: should each typeface have a ref to its fontmgr/cache?
1692 return create_typeface(this, NULL, style, fontMgr);
reed@google.com30ddd612013-07-30 17:47:39 +00001693}
1694
reed@google.com070da5e2013-03-27 20:01:49 +00001695///////////////////////////////////////////////////////////////////////////////
1696
bungeman@google.com71033442013-05-01 14:21:20 +00001697static void get_locale_string(IDWriteLocalizedStrings* names, const WCHAR* preferedLocale,
1698 SkString* skname) {
1699 UINT32 nameIndex = 0;
1700 if (preferedLocale) {
1701 // Ignore any errors and continue with index 0 if there is a problem.
1702 BOOL nameExists;
1703 names->FindLocaleName(preferedLocale, &nameIndex, &nameExists);
1704 if (!nameExists) {
1705 nameIndex = 0;
1706 }
1707 }
1708
1709 UINT32 nameLength;
1710 HRVM(names->GetStringLength(nameIndex, &nameLength), "Could not get name length.");
1711 nameLength += 1;
1712
1713 SkSMallocWCHAR name(nameLength);
1714 HRVM(names->GetString(nameIndex, name.get(), nameLength), "Could not get string.");
1715
1716 HRV(wchar_to_skstring(name.get(), skname));
1717}
1718
bungeman@google.combfc6cc42013-08-21 15:20:43 +00001719SkTypeface* SkFontMgr_DirectWrite::createTypefaceFromDWriteFont(
1720 IDWriteFontFace* fontFace,
1721 IDWriteFont* font,
1722 IDWriteFontFamily* fontFamily,
1723 StreamFontFileLoader* fontFileLoader,
1724 IDWriteFontCollectionLoader* fontCollectionLoader) {
bungeman@google.com86dd7522013-10-04 17:00:35 +00001725 SkTypeface* face = FindByProcAndRef(FindByDWriteFont, font);
bungeman@google.combfc6cc42013-08-21 15:20:43 +00001726 if (NULL == face) {
1727 face = DWriteFontTypeface::Create(fontFace, font, fontFamily,
1728 fontFileLoader, fontCollectionLoader);
1729 if (face) {
bungeman@google.com86dd7522013-10-04 17:00:35 +00001730 Add(face, get_style(font), fontCollectionLoader != NULL);
bungeman@google.com71033442013-05-01 14:21:20 +00001731 }
bungeman@google.combfc6cc42013-08-21 15:20:43 +00001732 }
1733 return face;
1734}
bungeman@google.com71033442013-05-01 14:21:20 +00001735
bungeman@google.combfc6cc42013-08-21 15:20:43 +00001736int SkFontMgr_DirectWrite::onCountFamilies() {
1737 return fFontCollection->GetFontFamilyCount();
1738}
bungeman@google.com71033442013-05-01 14:21:20 +00001739
bungeman@google.combfc6cc42013-08-21 15:20:43 +00001740void SkFontMgr_DirectWrite::onGetFamilyName(int index, SkString* familyName) {
1741 SkTScopedComPtr<IDWriteFontFamily> fontFamily;
1742 HRVM(fFontCollection->GetFontFamily(index, &fontFamily), "Could not get requested family.");
bungeman@google.com71033442013-05-01 14:21:20 +00001743
bungeman@google.combfc6cc42013-08-21 15:20:43 +00001744 SkTScopedComPtr<IDWriteLocalizedStrings> familyNames;
1745 HRVM(fontFamily->GetFamilyNames(&familyNames), "Could not get family names.");
bungeman@google.com71033442013-05-01 14:21:20 +00001746
bungeman@google.combfc6cc42013-08-21 15:20:43 +00001747 get_locale_string(familyNames.get(), fLocaleName.get(), familyName);
1748}
1749
1750SkFontStyleSet* SkFontMgr_DirectWrite::onCreateStyleSet(int index) {
1751 SkTScopedComPtr<IDWriteFontFamily> fontFamily;
1752 HRNM(fFontCollection->GetFontFamily(index, &fontFamily), "Could not get requested family.");
1753
1754 return SkNEW_ARGS(SkFontStyleSet_DirectWrite, (this, fontFamily.get()));
1755}
1756
1757SkFontStyleSet* SkFontMgr_DirectWrite::onMatchFamily(const char familyName[]) {
1758 SkSMallocWCHAR dwFamilyName;
1759 HRN(cstring_to_wchar(familyName, &dwFamilyName));
1760
1761 UINT32 index;
1762 BOOL exists;
1763 HRNM(fFontCollection->FindFamilyName(dwFamilyName.get(), &index, &exists),
1764 "Failed while finding family by name.");
1765 if (!exists) {
1766 return NULL;
bungeman@google.com71033442013-05-01 14:21:20 +00001767 }
1768
bungeman@google.combfc6cc42013-08-21 15:20:43 +00001769 return this->onCreateStyleSet(index);
1770}
bungeman@google.com71033442013-05-01 14:21:20 +00001771
bungeman@google.combfc6cc42013-08-21 15:20:43 +00001772SkTypeface* SkFontMgr_DirectWrite::onMatchFamilyStyle(const char familyName[],
1773 const SkFontStyle& fontstyle) {
1774 SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName));
1775 return sset->matchStyle(fontstyle);
1776}
bungeman@google.com71033442013-05-01 14:21:20 +00001777
bungeman@google.combfc6cc42013-08-21 15:20:43 +00001778SkTypeface* SkFontMgr_DirectWrite::onMatchFaceStyle(const SkTypeface* familyMember,
1779 const SkFontStyle& fontstyle) {
1780 SkString familyName;
1781 SkFontStyleSet_DirectWrite sset(
1782 this, ((DWriteFontTypeface*)familyMember)->fDWriteFontFamily.get()
1783 );
1784 return sset.matchStyle(fontstyle);
1785}
bungeman@google.com71033442013-05-01 14:21:20 +00001786
bungeman@google.combfc6cc42013-08-21 15:20:43 +00001787SkTypeface* SkFontMgr_DirectWrite::onCreateFromStream(SkStream* stream, int ttcIndex) {
1788 return create_from_stream(stream, ttcIndex);
1789}
bungeman@google.com71033442013-05-01 14:21:20 +00001790
bungeman@google.combfc6cc42013-08-21 15:20:43 +00001791SkTypeface* SkFontMgr_DirectWrite::onCreateFromData(SkData* data, int ttcIndex) {
1792 SkAutoTUnref<SkStream> stream(SkNEW_ARGS(SkMemoryStream, (data)));
1793 return this->createFromStream(stream, ttcIndex);
1794}
bungeman@google.com71033442013-05-01 14:21:20 +00001795
bungeman@google.combfc6cc42013-08-21 15:20:43 +00001796SkTypeface* SkFontMgr_DirectWrite::onCreateFromFile(const char path[], int ttcIndex) {
1797 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path));
1798 return this->createFromStream(stream, ttcIndex);
1799}
bungeman@google.com71033442013-05-01 14:21:20 +00001800
bungeman@google.combfc6cc42013-08-21 15:20:43 +00001801SkTypeface* SkFontMgr_DirectWrite::onLegacyCreateTypeface(const char familyName[],
1802 unsigned styleBits) {
1803 return create_typeface(NULL, familyName, styleBits, this);
1804}
bungeman@google.com71033442013-05-01 14:21:20 +00001805
bungeman@google.combfc6cc42013-08-21 15:20:43 +00001806///////////////////////////////////////////////////////////////////////////////
bungeman@google.com71033442013-05-01 14:21:20 +00001807
bungeman@google.combfc6cc42013-08-21 15:20:43 +00001808int SkFontStyleSet_DirectWrite::count() {
1809 return fFontFamily->GetFontCount();
1810}
bungeman@google.com71033442013-05-01 14:21:20 +00001811
bungeman@google.combfc6cc42013-08-21 15:20:43 +00001812SkTypeface* SkFontStyleSet_DirectWrite::createTypeface(int index) {
1813 SkTScopedComPtr<IDWriteFont> font;
1814 HRNM(fFontFamily->GetFont(index, &font), "Could not get font.");
reed@google.com30ddd612013-07-30 17:47:39 +00001815
bungeman@google.combfc6cc42013-08-21 15:20:43 +00001816 SkTScopedComPtr<IDWriteFontFace> fontFace;
1817 HRNM(font->CreateFontFace(&fontFace), "Could not create font face.");
1818
1819 return fFontMgr->createTypefaceFromDWriteFont(fontFace.get(), font.get(), fFontFamily.get());
1820}
bungeman@google.com71033442013-05-01 14:21:20 +00001821
1822void SkFontStyleSet_DirectWrite::getStyle(int index, SkFontStyle* fs, SkString* styleName) {
1823 SkTScopedComPtr<IDWriteFont> font;
1824 HRVM(fFontFamily->GetFont(index, &font), "Could not get font.");
1825
1826 SkFontStyle::Slant slant;
1827 switch (font->GetStyle()) {
1828 case DWRITE_FONT_STYLE_NORMAL:
1829 slant = SkFontStyle::kUpright_Slant;
1830 break;
1831 case DWRITE_FONT_STYLE_OBLIQUE:
1832 case DWRITE_FONT_STYLE_ITALIC:
1833 slant = SkFontStyle::kItalic_Slant;
1834 break;
1835 default:
1836 SkASSERT(false);
1837 }
1838
1839 int weight = font->GetWeight();
1840 int width = font->GetStretch();
1841
1842 *fs = SkFontStyle(weight, width, slant);
1843
1844 SkTScopedComPtr<IDWriteLocalizedStrings> faceNames;
1845 if (SUCCEEDED(font->GetFaceNames(&faceNames))) {
1846 get_locale_string(faceNames.get(), fFontMgr->fLocaleName.get(), styleName);
1847 }
1848}
1849
bungeman@google.combfc6cc42013-08-21 15:20:43 +00001850SkTypeface* SkFontStyleSet_DirectWrite::matchStyle(const SkFontStyle& pattern) {
1851 DWRITE_FONT_STYLE slant;
1852 switch (pattern.slant()) {
1853 case SkFontStyle::kUpright_Slant:
1854 slant = DWRITE_FONT_STYLE_NORMAL;
1855 break;
1856 case SkFontStyle::kItalic_Slant:
1857 slant = DWRITE_FONT_STYLE_ITALIC;
1858 break;
1859 default:
1860 SkASSERT(false);
1861 }
1862
1863 DWRITE_FONT_WEIGHT weight = (DWRITE_FONT_WEIGHT)pattern.weight();
1864 DWRITE_FONT_STRETCH width = (DWRITE_FONT_STRETCH)pattern.width();
1865
1866 SkTScopedComPtr<IDWriteFont> font;
1867 // TODO: perhaps use GetMatchingFonts and get the least simulated?
1868 HRNM(fFontFamily->GetFirstMatchingFont(weight, width, slant, &font),
1869 "Could not match font in family.");
1870
1871 SkTScopedComPtr<IDWriteFontFace> fontFace;
1872 HRNM(font->CreateFontFace(&fontFace), "Could not create font face.");
1873
1874 return fFontMgr->createTypefaceFromDWriteFont(fontFace.get(), font.get(),
1875 fFontFamily.get());
1876}
1877
reed@google.com30ddd612013-07-30 17:47:39 +00001878///////////////////////////////////////////////////////////////////////////////
1879
1880#ifndef SK_FONTHOST_USES_FONTMGR
1881
1882SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace,
1883 const char familyName[],
1884 SkTypeface::Style style) {
bungeman@google.combfc6cc42013-08-21 15:20:43 +00001885 return create_typeface(familyFace, familyName, style, NULL);
reed@google.com30ddd612013-07-30 17:47:39 +00001886}
1887
1888SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) {
1889 printf("SkFontHost::CreateTypefaceFromFile unimplemented");
1890 return NULL;
1891}
1892
1893SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) {
1894 return create_from_stream(stream, 0);
1895}
1896
1897#endif
1898
bungeman@google.comaf9296e2013-08-21 14:53:59 +00001899typedef decltype(GetUserDefaultLocaleName)* GetUserDefaultLocaleNameProc;
bungeman@google.com42a78292013-08-21 22:41:05 +00001900static HRESULT GetGetUserDefaultLocaleNameProc(GetUserDefaultLocaleNameProc* proc) {
1901 *proc = reinterpret_cast<GetUserDefaultLocaleNameProc>(
bungeman@google.comaf9296e2013-08-21 14:53:59 +00001902 GetProcAddress(LoadLibraryW(L"Kernel32.dll"), "GetUserDefaultLocaleName")
1903 );
bungeman@google.com42a78292013-08-21 22:41:05 +00001904 if (!*proc) {
1905 HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
1906 if (!IS_ERROR(hr)) {
1907 hr = ERROR_PROC_NOT_FOUND;
1908 }
1909 return hr;
1910 }
1911 return S_OK;
bungeman@google.comaf9296e2013-08-21 14:53:59 +00001912}
1913
bungeman@google.combfc6cc42013-08-21 15:20:43 +00001914SkFontMgr* SkFontMgr_New_DirectWrite() {
bungeman@google.com71033442013-05-01 14:21:20 +00001915 IDWriteFactory* factory;
1916 HRNM(get_dwrite_factory(&factory), "Could not get factory.");
1917
1918 SkTScopedComPtr<IDWriteFontCollection> sysFontCollection;
1919 HRNM(factory->GetSystemFontCollection(&sysFontCollection, FALSE),
1920 "Could not get system font collection.");
1921
1922 WCHAR localeNameStorage[LOCALE_NAME_MAX_LENGTH];
1923 WCHAR* localeName = NULL;
bungeman@google.comaf9296e2013-08-21 14:53:59 +00001924 int localeNameLen = 0;
1925
1926 // Dynamically load GetUserDefaultLocaleName function, as it is not available on XP.
bungeman@google.com42a78292013-08-21 22:41:05 +00001927 GetUserDefaultLocaleNameProc getUserDefaultLocaleNameProc = NULL;
1928 HRESULT hr = GetGetUserDefaultLocaleNameProc(&getUserDefaultLocaleNameProc);
bungeman@google.comaf9296e2013-08-21 14:53:59 +00001929 if (NULL == getUserDefaultLocaleNameProc) {
bungeman@google.com42a78292013-08-21 22:41:05 +00001930 SK_TRACEHR(hr, "Could not get GetUserDefaultLocaleName.");
bungeman@google.comaf9296e2013-08-21 14:53:59 +00001931 } else {
1932 localeNameLen = getUserDefaultLocaleNameProc(localeNameStorage, LOCALE_NAME_MAX_LENGTH);
1933 if (localeNameLen) {
1934 localeName = localeNameStorage;
1935 };
1936 }
bungeman@google.com71033442013-05-01 14:21:20 +00001937
1938 return SkNEW_ARGS(SkFontMgr_DirectWrite, (sysFontCollection.get(), localeName, localeNameLen));
reed@google.com070da5e2013-03-27 20:01:49 +00001939}