blob: 33fc322836eacbd56a8f3cbed510b025d4bcc2aa [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"
19#include "SkGlyph.h"
20#include "SkHRESULT.h"
21#include "SkMaskGamma.h"
22#include "SkOTTable_head.h"
23#include "SkOTTable_hhea.h"
24#include "SkOTTable_OS_2.h"
25#include "SkOTTable_post.h"
26#include "SkPath.h"
27#include "SkStream.h"
28#include "SkString.h"
29#include "SkTScopedComPtr.h"
30#include "SkThread.h"
31#include "SkTypeface_win.h"
32#include "SkTypefaceCache.h"
33#include "SkUtils.h"
34
35#include <dwrite.h>
36
37SK_DECLARE_STATIC_MUTEX(gFTMutex);
38
39static bool isLCD(const SkScalerContext::Rec& rec) {
40 return SkMask::kLCD16_Format == rec.fMaskFormat ||
41 SkMask::kLCD32_Format == rec.fMaskFormat;
42}
43
bungeman@google.com71033442013-05-01 14:21:20 +000044/** Prefer to use this type to prevent template proliferation. */
45typedef SkAutoSTMalloc<16, WCHAR> SkSMallocWCHAR;
46
47static HRESULT cstring_to_wchar(const char* skname, SkSMallocWCHAR* name) {
48 int wlen = MultiByteToWideChar(CP_UTF8, 0, skname, -1, NULL, 0);
49 if (0 == wlen) {
50 HRM(HRESULT_FROM_WIN32(GetLastError()),
51 "Could not get length for wchar to utf-8 conversion.");
52 }
53 name->reset(wlen);
54 wlen = MultiByteToWideChar(CP_UTF8, 0, skname, -1, name->get(), wlen);
55 if (0 == wlen) {
56 HRM(HRESULT_FROM_WIN32(GetLastError()), "Could not convert wchar to utf-8.");
57 }
58 return S_OK;
59}
60
61static HRESULT wchar_to_skstring(WCHAR* name, SkString* skname) {
62 int len = WideCharToMultiByte(CP_UTF8, 0, name, -1, NULL, 0, NULL, NULL);
63 if (0 == len) {
64 HRM(HRESULT_FROM_WIN32(GetLastError()),
65 "Could not get length for utf-8 to wchar conversion.");
66 }
67 skname->resize(len - 1);
68 len = WideCharToMultiByte(CP_UTF8, 0, name, -1, skname->writable_str(), len, NULL, NULL);
69 if (0 == len) {
70 HRM(HRESULT_FROM_WIN32(GetLastError()), "Could not convert utf-8 to wchar.");
71 }
72 return S_OK;
73}
74
bungeman@google.come8f05922012-08-16 16:13:40 +000075///////////////////////////////////////////////////////////////////////////////
76
77class DWriteOffscreen {
78public:
79 DWriteOffscreen() : fWidth(0), fHeight(0) {
80 }
81
82 void init(IDWriteFontFace* fontFace, const DWRITE_MATRIX& xform, FLOAT fontSize) {
83 fFontFace = fontFace;
84 fFontSize = fontSize;
85 fXform = xform;
86 }
87
88 const void* draw(const SkGlyph&, bool isBW);
89
90private:
91 uint16_t fWidth;
92 uint16_t fHeight;
93 IDWriteFontFace* fFontFace;
94 FLOAT fFontSize;
95 DWRITE_MATRIX fXform;
96 SkTDArray<uint8_t> fBits;
97};
98
99typedef HRESULT (WINAPI *DWriteCreateFactoryProc)(
100 __in DWRITE_FACTORY_TYPE factoryType,
101 __in REFIID iid,
102 __out IUnknown **factory
103);
104
105static HRESULT get_dwrite_factory(IDWriteFactory** factory) {
106 static IDWriteFactory* gDWriteFactory = NULL;
107
108 if (gDWriteFactory != NULL) {
109 *factory = gDWriteFactory;
110 return S_OK;
111 }
112
113 DWriteCreateFactoryProc dWriteCreateFactoryProc =
114 reinterpret_cast<DWriteCreateFactoryProc>(
115 GetProcAddress(LoadLibraryW(L"dwrite.dll"), "DWriteCreateFactory")
116 )
117 ;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000118
bungeman@google.come8f05922012-08-16 16:13:40 +0000119 if (!dWriteCreateFactoryProc) {
120 return E_UNEXPECTED;
121 }
122
123 HRM(dWriteCreateFactoryProc(DWRITE_FACTORY_TYPE_SHARED,
124 __uuidof(IDWriteFactory),
125 reinterpret_cast<IUnknown**>(&gDWriteFactory)),
126 "Could not create DirectWrite factory.");
rmistry@google.comd6176b02012-08-23 18:14:13 +0000127
bungeman@google.come8f05922012-08-16 16:13:40 +0000128 *factory = gDWriteFactory;
129 return S_OK;
130}
131
132const void* DWriteOffscreen::draw(const SkGlyph& glyph, bool isBW) {
133 IDWriteFactory* factory;
134 HRNM(get_dwrite_factory(&factory), "Could not get factory.");
135
136 if (fWidth < glyph.fWidth || fHeight < glyph.fHeight) {
137 fWidth = SkMax32(fWidth, glyph.fWidth);
138 fHeight = SkMax32(fHeight, glyph.fHeight);
139
140 if (isBW) {
141 fBits.setCount(fWidth * fHeight);
142 } else {
143 fBits.setCount(fWidth * fHeight * 3);
144 }
145 }
146
147 // erase
148 memset(fBits.begin(), 0, fBits.count());
149
150 fXform.dx = SkFixedToFloat(glyph.getSubXFixed());
151 fXform.dy = SkFixedToFloat(glyph.getSubYFixed());
152
153 FLOAT advance = 0.0f;
154
155 UINT16 index = glyph.getGlyphID();
156
157 DWRITE_GLYPH_OFFSET offset;
158 offset.advanceOffset = 0.0f;
159 offset.ascenderOffset = 0.0f;
160
161 DWRITE_GLYPH_RUN run;
162 run.glyphCount = 1;
163 run.glyphAdvances = &advance;
164 run.fontFace = fFontFace;
165 run.fontEmSize = fFontSize;
166 run.bidiLevel = 0;
167 run.glyphIndices = &index;
168 run.isSideways = FALSE;
169 run.glyphOffsets = &offset;
170
171 DWRITE_RENDERING_MODE renderingMode;
172 DWRITE_TEXTURE_TYPE textureType;
173 if (isBW) {
174 renderingMode = DWRITE_RENDERING_MODE_ALIASED;
175 textureType = DWRITE_TEXTURE_ALIASED_1x1;
176 } else {
177 renderingMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC;
178 textureType = DWRITE_TEXTURE_CLEARTYPE_3x1;
179 }
180 SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis;
181 HRNM(factory->CreateGlyphRunAnalysis(&run,
182 1.0f, // pixelsPerDip,
183 &fXform,
184 renderingMode,
185 DWRITE_MEASURING_MODE_NATURAL,
186 0.0f, // baselineOriginX,
187 0.0f, // baselineOriginY,
188 &glyphRunAnalysis),
189 "Could not create glyph run analysis.");
rmistry@google.comd6176b02012-08-23 18:14:13 +0000190
bungeman@google.come8f05922012-08-16 16:13:40 +0000191 //NOTE: this assumes that the glyph has already been measured
192 //with an exact same glyph run analysis.
193 RECT bbox;
194 bbox.left = glyph.fLeft;
195 bbox.top = glyph.fTop;
196 bbox.right = glyph.fLeft + glyph.fWidth;
197 bbox.bottom = glyph.fTop + glyph.fHeight;
198 HRNM(glyphRunAnalysis->CreateAlphaTexture(textureType,
199 &bbox,
200 fBits.begin(),
201 fBits.count()),
202 "Could not draw mask.");
203 return fBits.begin();
204}
205
206///////////////////////////////////////////////////////////////////////////////
207
bungeman@google.com94acfb52012-08-31 15:41:09 +0000208class StreamFontFileLoader : public IDWriteFontFileLoader {
209public:
210 // IUnknown methods
211 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject);
212 virtual ULONG STDMETHODCALLTYPE AddRef();
213 virtual ULONG STDMETHODCALLTYPE Release();
214
215 // IDWriteFontFileLoader methods
216 virtual HRESULT STDMETHODCALLTYPE CreateStreamFromKey(
217 void const* fontFileReferenceKey,
218 UINT32 fontFileReferenceKeySize,
219 IDWriteFontFileStream** fontFileStream);
220
221 static HRESULT Create(SkStream* stream, StreamFontFileLoader** streamFontFileLoader) {
222 *streamFontFileLoader = new StreamFontFileLoader(stream);
223 if (NULL == streamFontFileLoader) {
224 return E_OUTOFMEMORY;
225 }
226 return S_OK;
227 }
228
229 SkAutoTUnref<SkStream> fStream;
230
231private:
232 StreamFontFileLoader(SkStream* stream) : fRefCount(1), fStream(stream) {
233 stream->ref();
234 }
235
236 ULONG fRefCount;
237};
238
239HRESULT StreamFontFileLoader::QueryInterface(REFIID iid, void** ppvObject) {
240 if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileLoader)) {
241 *ppvObject = this;
242 AddRef();
243 return S_OK;
244 } else {
245 *ppvObject = NULL;
246 return E_NOINTERFACE;
247 }
248}
249
250ULONG StreamFontFileLoader::AddRef() {
251 return InterlockedIncrement(&fRefCount);
252}
253
254ULONG StreamFontFileLoader::Release() {
255 ULONG newCount = InterlockedDecrement(&fRefCount);
256 if (0 == newCount) {
257 delete this;
258 }
259 return newCount;
260}
261
262HRESULT StreamFontFileLoader::CreateStreamFromKey(
263 void const* fontFileReferenceKey,
264 UINT32 fontFileReferenceKeySize,
265 IDWriteFontFileStream** fontFileStream)
266{
267 SkTScopedComPtr<SkDWriteFontFileStreamWrapper> stream;
268 HR(SkDWriteFontFileStreamWrapper::Create(fStream, &stream));
269 *fontFileStream = stream.release();
270 return S_OK;
271}
272
273class StreamFontFileEnumerator : public IDWriteFontFileEnumerator {
274public:
275 // IUnknown methods
276 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject);
277 virtual ULONG STDMETHODCALLTYPE AddRef();
278 virtual ULONG STDMETHODCALLTYPE Release();
279
280 // IDWriteFontFileEnumerator methods
281 virtual HRESULT STDMETHODCALLTYPE MoveNext(BOOL* hasCurrentFile);
282 virtual HRESULT STDMETHODCALLTYPE GetCurrentFontFile(IDWriteFontFile** fontFile);
283
284 static HRESULT Create(IDWriteFactory* factory, IDWriteFontFileLoader* fontFileLoader,
285 StreamFontFileEnumerator** streamFontFileEnumerator) {
286 *streamFontFileEnumerator = new StreamFontFileEnumerator(factory, fontFileLoader);
287 if (NULL == streamFontFileEnumerator) {
288 return E_OUTOFMEMORY;
289 }
290 return S_OK;
291 }
292private:
293 StreamFontFileEnumerator(IDWriteFactory* factory, IDWriteFontFileLoader* fontFileLoader);
294 ULONG fRefCount;
295
296 SkTScopedComPtr<IDWriteFactory> fFactory;
297 SkTScopedComPtr<IDWriteFontFile> fCurrentFile;
298 SkTScopedComPtr<IDWriteFontFileLoader> fFontFileLoader;
299 bool fHasNext;
300};
301
302StreamFontFileEnumerator::StreamFontFileEnumerator(IDWriteFactory* factory,
303 IDWriteFontFileLoader* fontFileLoader)
304 : fRefCount(1)
305 , fFactory(factory)
306 , fCurrentFile()
307 , fFontFileLoader(fontFileLoader)
308 , fHasNext(true)
309{
310 factory->AddRef();
311 fontFileLoader->AddRef();
312}
313
314HRESULT StreamFontFileEnumerator::QueryInterface(REFIID iid, void** ppvObject) {
315 if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileEnumerator)) {
316 *ppvObject = this;
317 AddRef();
318 return S_OK;
319 } else {
320 *ppvObject = NULL;
321 return E_NOINTERFACE;
322 }
323}
324
325ULONG StreamFontFileEnumerator::AddRef() {
326 return InterlockedIncrement(&fRefCount);
327}
328
329ULONG StreamFontFileEnumerator::Release() {
330 ULONG newCount = InterlockedDecrement(&fRefCount);
331 if (0 == newCount) {
332 delete this;
333 }
334 return newCount;
335}
336
337HRESULT StreamFontFileEnumerator::MoveNext(BOOL* hasCurrentFile) {
338 *hasCurrentFile = FALSE;
339
340 if (!fHasNext) {
341 return S_OK;
342 }
343 fHasNext = false;
344
345 UINT32 dummy = 0;
346 HR(fFactory->CreateCustomFontFileReference(
347 &dummy, //cannot be NULL
348 sizeof(dummy), //even if this is 0
349 fFontFileLoader.get(),
350 &fCurrentFile));
351
352 *hasCurrentFile = TRUE;
353 return S_OK;
354}
355
356HRESULT StreamFontFileEnumerator::GetCurrentFontFile(IDWriteFontFile** fontFile) {
357 if (fCurrentFile.get() == NULL) {
358 *fontFile = NULL;
359 return E_FAIL;
360 }
361
362 fCurrentFile.get()->AddRef();
363 *fontFile = fCurrentFile.get();
364 return S_OK;
365}
366
367class StreamFontCollectionLoader : public IDWriteFontCollectionLoader {
368public:
369 // IUnknown methods
370 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject);
371 virtual ULONG STDMETHODCALLTYPE AddRef();
372 virtual ULONG STDMETHODCALLTYPE Release();
373
374 // IDWriteFontCollectionLoader methods
375 virtual HRESULT STDMETHODCALLTYPE CreateEnumeratorFromKey(
376 IDWriteFactory* factory,
377 void const* collectionKey,
378 UINT32 collectionKeySize,
379 IDWriteFontFileEnumerator** fontFileEnumerator);
380
381 static HRESULT Create(IDWriteFontFileLoader* fontFileLoader,
382 StreamFontCollectionLoader** streamFontCollectionLoader) {
383 *streamFontCollectionLoader = new StreamFontCollectionLoader(fontFileLoader);
384 if (NULL == streamFontCollectionLoader) {
385 return E_OUTOFMEMORY;
386 }
387 return S_OK;
388 }
389private:
390 StreamFontCollectionLoader(IDWriteFontFileLoader* fontFileLoader)
391 : fRefCount(1)
392 , fFontFileLoader(fontFileLoader)
393 {
394 fontFileLoader->AddRef();
395 }
396
397 ULONG fRefCount;
398 SkTScopedComPtr<IDWriteFontFileLoader> fFontFileLoader;
399};
400
401HRESULT StreamFontCollectionLoader::QueryInterface(REFIID iid, void** ppvObject) {
402 if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontCollectionLoader)) {
403 *ppvObject = this;
404 AddRef();
405 return S_OK;
406 } else {
407 *ppvObject = NULL;
408 return E_NOINTERFACE;
409 }
410}
411
412ULONG StreamFontCollectionLoader::AddRef() {
413 return InterlockedIncrement(&fRefCount);
414}
415
416ULONG StreamFontCollectionLoader::Release() {
417 ULONG newCount = InterlockedDecrement(&fRefCount);
418 if (0 == newCount) {
419 delete this;
420 }
421 return newCount;
422}
423
424HRESULT StreamFontCollectionLoader::CreateEnumeratorFromKey(
425 IDWriteFactory* factory,
426 void const* collectionKey,
427 UINT32 collectionKeySize,
428 IDWriteFontFileEnumerator** fontFileEnumerator)
429{
430 SkTScopedComPtr<StreamFontFileEnumerator> enumerator;
431 HR(StreamFontFileEnumerator::Create(factory, fFontFileLoader.get(), &enumerator));
432 *fontFileEnumerator = enumerator.release();
433 return S_OK;
434}
435
436///////////////////////////////////////////////////////////////////////////////
437
bungeman@google.come8f05922012-08-16 16:13:40 +0000438static SkTypeface::Style get_style(IDWriteFont* font) {
439 int style = SkTypeface::kNormal;
440 DWRITE_FONT_WEIGHT weight = font->GetWeight();
441 if (DWRITE_FONT_WEIGHT_DEMI_BOLD <= weight) {
442 style |= SkTypeface::kBold;
443 }
444 DWRITE_FONT_STYLE angle = font->GetStyle();
445 if (DWRITE_FONT_STYLE_OBLIQUE == angle || DWRITE_FONT_STYLE_ITALIC == angle) {
446 style |= SkTypeface::kItalic;
447 }
448 return static_cast<SkTypeface::Style>(style);
449}
450
451class DWriteFontTypeface : public SkTypeface {
452private:
453 DWriteFontTypeface(SkTypeface::Style style, SkFontID fontID,
454 IDWriteFontFace* fontFace,
455 IDWriteFont* font,
456 IDWriteFontFamily* fontFamily,
bungeman@google.com94acfb52012-08-31 15:41:09 +0000457 StreamFontFileLoader* fontFileLoader = NULL,
bungeman@google.come8f05922012-08-16 16:13:40 +0000458 IDWriteFontCollectionLoader* fontCollectionLoader = NULL)
459 : SkTypeface(style, fontID, false)
460 , fDWriteFontCollectionLoader(fontCollectionLoader)
461 , fDWriteFontFileLoader(fontFileLoader)
462 , fDWriteFontFamily(fontFamily)
463 , fDWriteFont(font)
464 , fDWriteFontFace(fontFace) {
465
466 if (fontCollectionLoader != NULL) {
467 fontCollectionLoader->AddRef();
468 }
469 if (fontFileLoader != NULL) {
470 fontFileLoader->AddRef();
471 }
472 fontFamily->AddRef();
473 font->AddRef();
474 fontFace->AddRef();
475 }
476
477public:
478 SkTScopedComPtr<IDWriteFontCollectionLoader> fDWriteFontCollectionLoader;
bungeman@google.com94acfb52012-08-31 15:41:09 +0000479 SkTScopedComPtr<StreamFontFileLoader> fDWriteFontFileLoader;
bungeman@google.come8f05922012-08-16 16:13:40 +0000480 SkTScopedComPtr<IDWriteFontFamily> fDWriteFontFamily;
481 SkTScopedComPtr<IDWriteFont> fDWriteFont;
482 SkTScopedComPtr<IDWriteFontFace> fDWriteFontFace;
483
484 static DWriteFontTypeface* Create(IDWriteFontFace* fontFace,
485 IDWriteFont* font,
486 IDWriteFontFamily* fontFamily,
bungeman@google.com94acfb52012-08-31 15:41:09 +0000487 StreamFontFileLoader* fontFileLoader = NULL,
bungeman@google.come8f05922012-08-16 16:13:40 +0000488 IDWriteFontCollectionLoader* fontCollectionLoader = NULL) {
489 SkTypeface::Style style = get_style(font);
490 SkFontID fontID = SkTypefaceCache::NewFontID();
bungeman@google.com94acfb52012-08-31 15:41:09 +0000491 return SkNEW_ARGS(DWriteFontTypeface, (style, fontID,
492 fontFace, font, fontFamily,
bungeman@google.come8f05922012-08-16 16:13:40 +0000493 fontFileLoader, fontCollectionLoader));
494 }
495
496 ~DWriteFontTypeface() {
497 if (fDWriteFontCollectionLoader.get() == NULL) return;
498
499 IDWriteFactory* factory;
500 HRVM(get_dwrite_factory(&factory), "Could not get factory.");
501 HRV(factory->UnregisterFontCollectionLoader(fDWriteFontCollectionLoader.get()));
502 HRV(factory->UnregisterFontFileLoader(fDWriteFontFileLoader.get()));
503 }
reed@google.com0da48612013-03-19 16:06:52 +0000504
505protected:
reed@google.com177dc6e2013-03-21 20:55:10 +0000506 virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE;
reed@google.com0da48612013-03-19 16:06:52 +0000507 virtual SkScalerContext* onCreateScalerContext(const SkDescriptor*) const SK_OVERRIDE;
508 virtual void onFilterRec(SkScalerContextRec*) const SK_OVERRIDE;
reed@google.com2689f612013-03-20 20:01:47 +0000509 virtual SkAdvancedTypefaceMetrics* onGetAdvancedTypefaceMetrics(
510 SkAdvancedTypefaceMetrics::PerGlyphInfo,
511 const uint32_t*, uint32_t) const SK_OVERRIDE;
reed@google.com5526ede2013-03-25 13:03:37 +0000512 virtual void onGetFontDescriptor(SkFontDescriptor*, bool*) const SK_OVERRIDE;
bungeman@google.come8f05922012-08-16 16:13:40 +0000513};
514
515class SkScalerContext_Windows : public SkScalerContext {
516public:
reed@google.com0da48612013-03-19 16:06:52 +0000517 SkScalerContext_Windows(DWriteFontTypeface*, const SkDescriptor* desc);
bungeman@google.come8f05922012-08-16 16:13:40 +0000518 virtual ~SkScalerContext_Windows();
519
520protected:
521 virtual unsigned generateGlyphCount() SK_OVERRIDE;
522 virtual uint16_t generateCharToGlyph(SkUnichar uni) SK_OVERRIDE;
523 virtual void generateAdvance(SkGlyph* glyph) SK_OVERRIDE;
524 virtual void generateMetrics(SkGlyph* glyph) SK_OVERRIDE;
bungeman@google.coma76de722012-10-26 19:35:54 +0000525 virtual void generateImage(const SkGlyph& glyph) SK_OVERRIDE;
bungeman@google.come8f05922012-08-16 16:13:40 +0000526 virtual void generatePath(const SkGlyph& glyph, SkPath* path) SK_OVERRIDE;
527 virtual void generateFontMetrics(SkPaint::FontMetrics* mX,
528 SkPaint::FontMetrics* mY) SK_OVERRIDE;
529
530private:
531 DWriteOffscreen fOffscreen;
532 DWRITE_MATRIX fXform;
533 SkAutoTUnref<DWriteFontTypeface> fTypeface;
534 int fGlyphCount;
535};
536
537#define SK_DWRITE_DEFAULT_FONT_NAMED 1
538#define SK_DWRITE_DEFAULT_FONT_MESSAGE 2
539#define SK_DWRITE_DEFAULT_FONT_THEME 3
540#define SK_DWRITE_DEFAULT_FONT_SHELLDLG 4
541#define SK_DWRITE_DEFAULT_FONT_GDI 5
542#define SK_DWRITE_DEFAULT_FONT_STRATEGY SK_DWRITE_DEFAULT_FONT_MESSAGE
543
544static HRESULT get_default_font(IDWriteFont** font) {
545 IDWriteFactory* factory;
546 HRM(get_dwrite_factory(&factory), "Could not get factory.");
547
548#if SK_DWRITE_DEFAULT_FONT_STRATEGY == SK_DWRITE_DEFAULT_FONT_NAMED
549 SkTScopedComPtr<IDWriteFontCollection> sysFonts;
550 HRM(factory->GetSystemFontCollection(&sysFonts, false),
551 "Could not get system font collection.");
552
553 UINT32 index;
554 BOOL exists;
555 //hr = sysFonts->FindFamilyName(L"Georgia", &index, &exists);
556 HRM(sysFonts->FindFamilyName(L"Microsoft Sans Serif", &index, &exists),
557 "Could not access family names.");
558
559 if (!exists) {
560 SkDEBUGF(("The hard coded font family does not exist."));
561 return E_UNEXPECTED;
562 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000563
bungeman@google.come8f05922012-08-16 16:13:40 +0000564 SkTScopedComPtr<IDWriteFontFamily> fontFamily;
565 HRM(sysFonts->GetFontFamily(index, &fontFamily),
566 "Could not load the requested font family.");
567
568 HRM(fontFamily->GetFont(0, font), "Could not get first font from family.");
569
570#elif SK_DWRITE_DEFAULT_FONT_STRATEGY == SK_DWRITE_DEFAULT_FONT_MESSAGE
571 SkTScopedComPtr<IDWriteGdiInterop> gdi;
572 HRM(factory->GetGdiInterop(&gdi), "Could not get GDI interop.");
573
574 NONCLIENTMETRICSW metrics;
575 metrics.cbSize = sizeof(metrics);
576 if (0 == SystemParametersInfoW(SPI_GETNONCLIENTMETRICS,
577 sizeof(metrics),
578 &metrics,
579 0)) {
580 return E_UNEXPECTED;
581 }
582 HRM(gdi->CreateFontFromLOGFONT(&metrics.lfMessageFont, font),
583 "Could not create DWrite font from LOGFONT.");
584
585#elif SK_DWRITE_DEFAULT_FONT_STRATEGY == SK_DWRITE_DEFAULT_FONT_THEME
586 //Theme body font?
587
588#elif SK_DWRITE_DEFAULT_FONT_STRATEGY == SK_DWRITE_DEFAULT_FONT_SHELLDLG
589 //"MS Shell Dlg" or "MS Shell Dlg 2"?
590
591#elif SK_DWRITE_DEFAULT_FONT_STRATEGY == SK_DWRITE_DEFAULT_FONT_GDI
592 //Never works.
593 SkTScopedComPtr<IDWriteGdiInterop> gdi;
594 HRM(factory->GetGdiInterop(&gdi), "Could not get GDI interop.");
595
596 static LOGFONTW gDefaultFont = {};
597 gDefaultFont.lfFaceName
598 HRM(gdi->CreateFontFromLOGFONT(&gDefaultFont, font),
599 "Could not create DWrite font from LOGFONT.";
600#endif
601 return S_OK;
602}
603
604static bool are_same(IUnknown* a, IUnknown* b) {
605 SkTScopedComPtr<IUnknown> iunkA;
606 if (FAILED(a->QueryInterface(&iunkA))) {
607 return false;
608 }
609
610 SkTScopedComPtr<IUnknown> iunkB;
611 if (FAILED(b->QueryInterface(&iunkB))) {
612 return false;
613 }
614
615 return iunkA.get() == iunkB.get();
616}
617static bool FindByDWriteFont(SkTypeface* face, SkTypeface::Style requestedStyle, void* ctx) {
618 //Check to see if the two fonts are identical.
619 DWriteFontTypeface* dwFace = reinterpret_cast<DWriteFontTypeface*>(face);
620 IDWriteFont* dwFont = reinterpret_cast<IDWriteFont*>(ctx);
621 if (are_same(dwFace->fDWriteFont.get(), dwFont)) {
622 return true;
623 }
624
625 //Check if the two fonts share the same loader and have the same key.
626 SkTScopedComPtr<IDWriteFontFace> dwFaceFontFace;
627 SkTScopedComPtr<IDWriteFontFace> dwFontFace;
628 HRB(dwFace->fDWriteFont->CreateFontFace(&dwFaceFontFace));
629 HRB(dwFont->CreateFontFace(&dwFontFace));
630 if (are_same(dwFaceFontFace.get(), dwFontFace.get())) {
631 return true;
632 }
633
634 UINT32 dwFaceNumFiles;
635 UINT32 dwNumFiles;
636 HRB(dwFaceFontFace->GetFiles(&dwFaceNumFiles, NULL));
637 HRB(dwFontFace->GetFiles(&dwNumFiles, NULL));
638 if (dwFaceNumFiles != dwNumFiles) {
639 return false;
640 }
641
642 SkTScopedComPtr<IDWriteFontFile> dwFaceFontFile;
643 SkTScopedComPtr<IDWriteFontFile> dwFontFile;
644 HRB(dwFaceFontFace->GetFiles(&dwFaceNumFiles, &dwFaceFontFile));
645 HRB(dwFontFace->GetFiles(&dwNumFiles, &dwFontFile));
646
647 //for (each file) { //we currently only admit fonts from one file.
648 SkTScopedComPtr<IDWriteFontFileLoader> dwFaceFontFileLoader;
649 SkTScopedComPtr<IDWriteFontFileLoader> dwFontFileLoader;
650 HRB(dwFaceFontFile->GetLoader(&dwFaceFontFileLoader));
651 HRB(dwFontFile->GetLoader(&dwFontFileLoader));
652 if (!are_same(dwFaceFontFileLoader.get(), dwFontFileLoader.get())) {
653 return false;
654 }
655 //}
656
657 const void* dwFaceFontRefKey;
658 UINT32 dwFaceFontRefKeySize;
659 const void* dwFontRefKey;
660 UINT32 dwFontRefKeySize;
661 HRB(dwFaceFontFile->GetReferenceKey(&dwFaceFontRefKey, &dwFaceFontRefKeySize));
662 HRB(dwFontFile->GetReferenceKey(&dwFontRefKey, &dwFontRefKeySize));
663 if (dwFaceFontRefKeySize != dwFontRefKeySize) {
664 return false;
665 }
666 if (0 != memcmp(dwFaceFontRefKey, dwFontRefKey, dwFontRefKeySize)) {
667 return false;
668 }
669
670 //TODO: better means than comparing name strings?
671 //NOTE: .tfc and fake bold/italic will end up here.
672 SkTScopedComPtr<IDWriteFontFamily> dwFaceFontFamily;
673 SkTScopedComPtr<IDWriteFontFamily> dwFontFamily;
674 HRB(dwFace->fDWriteFont->GetFontFamily(&dwFaceFontFamily));
675 HRB(dwFont->GetFontFamily(&dwFontFamily));
676
677 SkTScopedComPtr<IDWriteLocalizedStrings> dwFaceFontFamilyNames;
678 SkTScopedComPtr<IDWriteLocalizedStrings> dwFaceFontNames;
679 HRB(dwFaceFontFamily->GetFamilyNames(&dwFaceFontFamilyNames));
680 HRB(dwFace->fDWriteFont->GetFaceNames(&dwFaceFontNames));
681
682 SkTScopedComPtr<IDWriteLocalizedStrings> dwFontFamilyNames;
683 SkTScopedComPtr<IDWriteLocalizedStrings> dwFontNames;
684 HRB(dwFontFamily->GetFamilyNames(&dwFontFamilyNames));
685 HRB(dwFont->GetFaceNames(&dwFontNames));
686
687 UINT32 dwFaceFontFamilyNameLength;
688 UINT32 dwFaceFontNameLength;
689 HRB(dwFaceFontFamilyNames->GetStringLength(0, &dwFaceFontFamilyNameLength));
690 HRB(dwFaceFontNames->GetStringLength(0, &dwFaceFontNameLength));
691
692 UINT32 dwFontFamilyNameLength;
693 UINT32 dwFontNameLength;
694 HRB(dwFontFamilyNames->GetStringLength(0, &dwFontFamilyNameLength));
695 HRB(dwFontNames->GetStringLength(0, &dwFontNameLength));
696
697 if (dwFaceFontFamilyNameLength != dwFontFamilyNameLength ||
698 dwFaceFontNameLength != dwFontNameLength)
699 {
700 return false;
701 }
702
bungeman@google.com71033442013-05-01 14:21:20 +0000703 SkSMallocWCHAR dwFaceFontFamilyNameChar(dwFaceFontFamilyNameLength+1);
704 SkSMallocWCHAR dwFaceFontNameChar(dwFaceFontNameLength+1);
705 HRB(dwFaceFontFamilyNames->GetString(0, dwFaceFontFamilyNameChar.get(), dwFaceFontFamilyNameLength+1));
706 HRB(dwFaceFontNames->GetString(0, dwFaceFontNameChar.get(), dwFaceFontNameLength+1));
bungeman@google.come8f05922012-08-16 16:13:40 +0000707
bungeman@google.com71033442013-05-01 14:21:20 +0000708 SkSMallocWCHAR dwFontFamilyNameChar(dwFontFamilyNameLength+1);
709 SkSMallocWCHAR dwFontNameChar(dwFontNameLength+1);
710 HRB(dwFontFamilyNames->GetString(0, dwFontFamilyNameChar.get(), dwFontFamilyNameLength+1));
711 HRB(dwFontNames->GetString(0, dwFontNameChar.get(), dwFontNameLength+1));
bungeman@google.come8f05922012-08-16 16:13:40 +0000712
bungeman@google.com71033442013-05-01 14:21:20 +0000713 return wcscmp(dwFaceFontFamilyNameChar.get(), dwFontFamilyNameChar.get()) == 0 &&
714 wcscmp(dwFaceFontNameChar.get(), dwFontNameChar.get()) == 0;
bungeman@google.come8f05922012-08-16 16:13:40 +0000715}
716
717SkTypeface* SkCreateTypefaceFromDWriteFont(IDWriteFontFace* fontFace,
718 IDWriteFont* font,
719 IDWriteFontFamily* fontFamily,
bungeman@google.com94acfb52012-08-31 15:41:09 +0000720 StreamFontFileLoader* fontFileLoader = NULL,
bungeman@google.come8f05922012-08-16 16:13:40 +0000721 IDWriteFontCollectionLoader* fontCollectionLoader = NULL) {
722 SkTypeface* face = SkTypefaceCache::FindByProcAndRef(FindByDWriteFont, font);
bungeman@google.com0729b622012-09-17 14:25:42 +0000723 if (NULL == face) {
bungeman@google.come8f05922012-08-16 16:13:40 +0000724 face = DWriteFontTypeface::Create(fontFace, font, fontFamily,
725 fontFileLoader, fontCollectionLoader);
726 SkTypefaceCache::Add(face, get_style(font), fontCollectionLoader != NULL);
727 }
728 return face;
729}
730
731void SkDWriteFontFromTypeface(const SkTypeface* face, IDWriteFont** font) {
732 if (NULL == face) {
733 HRVM(get_default_font(font), "Could not get default font.");
734 } else {
735 *font = static_cast<const DWriteFontTypeface*>(face)->fDWriteFont.get();
736 (*font)->AddRef();
737 }
738}
739static DWriteFontTypeface* GetDWriteFontByID(SkFontID fontID) {
740 return static_cast<DWriteFontTypeface*>(SkTypefaceCache::FindByID(fontID));
741}
742
reed@google.com0da48612013-03-19 16:06:52 +0000743SkScalerContext_Windows::SkScalerContext_Windows(DWriteFontTypeface* typeface,
744 const SkDescriptor* desc)
745 : SkScalerContext(typeface, desc)
746 , fTypeface(SkRef(typeface))
bungeman@google.come8f05922012-08-16 16:13:40 +0000747 , fGlyphCount(-1) {
748 SkAutoMutexAcquire ac(gFTMutex);
749
750 fXform.m11 = SkScalarToFloat(fRec.fPost2x2[0][0]);
751 fXform.m12 = SkScalarToFloat(fRec.fPost2x2[1][0]);
752 fXform.m21 = SkScalarToFloat(fRec.fPost2x2[0][1]);
753 fXform.m22 = SkScalarToFloat(fRec.fPost2x2[1][1]);
754 fXform.dx = 0;
755 fXform.dy = 0;
756
bungeman@google.come8f05922012-08-16 16:13:40 +0000757 fOffscreen.init(fTypeface->fDWriteFontFace.get(), fXform, SkScalarToFloat(fRec.fTextSize));
758}
759
760SkScalerContext_Windows::~SkScalerContext_Windows() {
761}
762
763unsigned SkScalerContext_Windows::generateGlyphCount() {
764 if (fGlyphCount < 0) {
765 fGlyphCount = fTypeface->fDWriteFontFace->GetGlyphCount();
766 }
767 return fGlyphCount;
768}
769
770uint16_t SkScalerContext_Windows::generateCharToGlyph(SkUnichar uni) {
771 uint16_t index = 0;
772 fTypeface->fDWriteFontFace->GetGlyphIndices(reinterpret_cast<UINT32*>(&uni), 1, &index);
773 return index;
774}
775
776void SkScalerContext_Windows::generateAdvance(SkGlyph* glyph) {
777 //Delta is the difference between the right/left side bearing metric
778 //and where the right/left side bearing ends up after hinting.
779 //DirectWrite does not provide this information.
780 glyph->fRsbDelta = 0;
781 glyph->fLsbDelta = 0;
rmistry@google.comd6176b02012-08-23 18:14:13 +0000782
bungeman@google.come8f05922012-08-16 16:13:40 +0000783 glyph->fAdvanceX = 0;
784 glyph->fAdvanceY = 0;
785
786 uint16_t glyphId = glyph->getGlyphID();
787 DWRITE_GLYPH_METRICS gm;
788 HRVM(fTypeface->fDWriteFontFace->GetDesignGlyphMetrics(&glyphId, 1, &gm),
789 "Could not get design metrics.");
790
791 DWRITE_FONT_METRICS dwfm;
792 fTypeface->fDWriteFontFace->GetMetrics(&dwfm);
793
794 SkScalar advanceX = SkScalarMulDiv(fRec.fTextSize,
795 SkIntToScalar(gm.advanceWidth),
796 SkIntToScalar(dwfm.designUnitsPerEm));
rmistry@google.comd6176b02012-08-23 18:14:13 +0000797
bungeman@google.come8f05922012-08-16 16:13:40 +0000798 if (!(fRec.fFlags & kSubpixelPositioning_Flag)) {
799 advanceX = SkScalarRoundToScalar(advanceX);
800 }
801
802 SkVector vecs[1] = { { advanceX, 0 } };
803 SkMatrix mat;
bungeman@google.com091f51b2013-01-10 18:56:18 +0000804 fRec.getMatrixFrom2x2(&mat);
bungeman@google.come8f05922012-08-16 16:13:40 +0000805 mat.mapVectors(vecs, SK_ARRAY_COUNT(vecs));
806
807 glyph->fAdvanceX = SkScalarToFixed(vecs[0].fX);
808 glyph->fAdvanceY = SkScalarToFixed(vecs[0].fY);
809}
810
811void SkScalerContext_Windows::generateMetrics(SkGlyph* glyph) {
812 glyph->fWidth = 0;
813
814 this->generateAdvance(glyph);
815
816 //Measure raster size.
817 fXform.dx = SkFixedToFloat(glyph->getSubXFixed());
818 fXform.dy = SkFixedToFloat(glyph->getSubYFixed());
819
820 FLOAT advance = 0;
821
822 UINT16 glyphId = glyph->getGlyphID();
823
824 DWRITE_GLYPH_OFFSET offset;
825 offset.advanceOffset = 0.0f;
826 offset.ascenderOffset = 0.0f;
827
828 DWRITE_GLYPH_RUN run;
829 run.glyphCount = 1;
830 run.glyphAdvances = &advance;
831 run.fontFace = fTypeface->fDWriteFontFace.get();
832 run.fontEmSize = SkScalarToFloat(fRec.fTextSize);
833 run.bidiLevel = 0;
834 run.glyphIndices = &glyphId;
835 run.isSideways = FALSE;
836 run.glyphOffsets = &offset;
837
838 IDWriteFactory* factory;
839 HRVM(get_dwrite_factory(&factory), "Could not get factory.");
840
841 const bool isBW = SkMask::kBW_Format == fRec.fMaskFormat;
842 DWRITE_RENDERING_MODE renderingMode;
843 DWRITE_TEXTURE_TYPE textureType;
844 if (isBW) {
845 renderingMode = DWRITE_RENDERING_MODE_ALIASED;
846 textureType = DWRITE_TEXTURE_ALIASED_1x1;
847 } else {
848 renderingMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC;
849 textureType = DWRITE_TEXTURE_CLEARTYPE_3x1;
850 }
851
852 SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis;
853 HRVM(factory->CreateGlyphRunAnalysis(&run,
854 1.0f, // pixelsPerDip,
855 &fXform,
856 renderingMode,
857 DWRITE_MEASURING_MODE_NATURAL,
858 0.0f, // baselineOriginX,
859 0.0f, // baselineOriginY,
860 &glyphRunAnalysis),
861 "Could not create glyph run analysis.");
rmistry@google.comd6176b02012-08-23 18:14:13 +0000862
bungeman@google.come8f05922012-08-16 16:13:40 +0000863 RECT bbox;
864 HRVM(glyphRunAnalysis->GetAlphaTextureBounds(textureType, &bbox),
865 "Could not get texture bounds.");
866
867 glyph->fWidth = SkToU16(bbox.right - bbox.left);
868 glyph->fHeight = SkToU16(bbox.bottom - bbox.top);
869 glyph->fLeft = SkToS16(bbox.left);
870 glyph->fTop = SkToS16(bbox.top);
871}
872
873void SkScalerContext_Windows::generateFontMetrics(SkPaint::FontMetrics* mx,
874 SkPaint::FontMetrics* my) {
875 if (!(mx || my))
876 return;
877
878 DWRITE_FONT_METRICS dwfm;
879 fTypeface->fDWriteFontFace->GetMetrics(&dwfm);
880
881 if (mx) {
882 mx->fTop = SkScalarMulDiv(-fRec.fTextSize,
883 SkIntToScalar(dwfm.ascent),
884 SkIntToScalar(dwfm.designUnitsPerEm));
885 mx->fAscent = mx->fTop;
886 mx->fDescent = SkScalarMulDiv(fRec.fTextSize,
887 SkIntToScalar(dwfm.descent),
888 SkIntToScalar(dwfm.designUnitsPerEm));
889 mx->fBottom = mx->fDescent;
890 //TODO, can be less than zero
891 mx->fLeading = SkScalarMulDiv(fRec.fTextSize,
892 SkIntToScalar(dwfm.lineGap),
893 SkIntToScalar(dwfm.designUnitsPerEm));
894 }
895
896 if (my) {
897 my->fTop = SkScalarMulDiv(-fRec.fTextSize,
898 SkIntToScalar(dwfm.ascent),
899 SkIntToScalar(dwfm.designUnitsPerEm));
900 my->fAscent = my->fTop;
901 my->fDescent = SkScalarMulDiv(fRec.fTextSize,
902 SkIntToScalar(dwfm.descent),
903 SkIntToScalar(dwfm.designUnitsPerEm));
904 my->fBottom = my->fDescent;
905 //TODO, can be less than zero
906 my->fLeading = SkScalarMulDiv(fRec.fTextSize,
907 SkIntToScalar(dwfm.lineGap),
908 SkIntToScalar(dwfm.designUnitsPerEm));
909 }
910}
911
912///////////////////////////////////////////////////////////////////////////////
913
914#include "SkColorPriv.h"
915
916static void bilevel_to_bw(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph) {
917 const int width = glyph.fWidth;
918 const size_t dstRB = (width + 7) >> 3;
919 uint8_t* SK_RESTRICT dst = static_cast<uint8_t*>(glyph.fImage);
920
921 int byteCount = width >> 3;
922 int bitCount = width & 7;
923
924 for (int y = 0; y < glyph.fHeight; ++y) {
925 if (byteCount > 0) {
926 for (int i = 0; i < byteCount; ++i) {
927 unsigned byte = 0;
928 byte |= src[0] & (1 << 7);
929 byte |= src[1] & (1 << 6);
930 byte |= src[2] & (1 << 5);
931 byte |= src[3] & (1 << 4);
932 byte |= src[4] & (1 << 3);
933 byte |= src[5] & (1 << 2);
934 byte |= src[6] & (1 << 1);
935 byte |= src[7] & (1 << 0);
936 dst[i] = byte;
937 src += 8;
938 }
939 }
940 if (bitCount > 0) {
941 unsigned byte = 0;
942 unsigned mask = 0x80;
943 for (int i = 0; i < bitCount; i++) {
944 byte |= (src[i]) & mask;
945 mask >>= 1;
946 }
947 dst[byteCount] = byte;
948 }
949 src += bitCount;
950 dst += dstRB;
951 }
952}
953
954template<bool APPLY_PREBLEND>
955static void rgb_to_a8(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph, const uint8_t* table8) {
956 const size_t dstRB = glyph.rowBytes();
957 const U16CPU width = glyph.fWidth;
958 uint8_t* SK_RESTRICT dst = static_cast<uint8_t*>(glyph.fImage);
959
960 for (U16CPU y = 0; y < glyph.fHeight; y++) {
961 for (U16CPU i = 0; i < width; i++) {
962 U8CPU r = *(src++);
963 U8CPU g = *(src++);
964 U8CPU b = *(src++);
965 dst[i] = sk_apply_lut_if<APPLY_PREBLEND>((r + g + b) / 3, table8);
966 }
967 dst = (uint8_t*)((char*)dst + dstRB);
968 }
969}
970
971template<bool APPLY_PREBLEND>
972static void rgb_to_lcd16(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph,
973 const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) {
974 const size_t dstRB = glyph.rowBytes();
975 const U16CPU width = glyph.fWidth;
976 uint16_t* SK_RESTRICT dst = static_cast<uint16_t*>(glyph.fImage);
977
978 for (U16CPU y = 0; y < glyph.fHeight; y++) {
979 for (U16CPU i = 0; i < width; i++) {
980 U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableR);
981 U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableG);
982 U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableB);
983 dst[i] = SkPack888ToRGB16(r, g, b);
984 }
985 dst = (uint16_t*)((char*)dst + dstRB);
986 }
987}
988
989template<bool APPLY_PREBLEND>
990static void rgb_to_lcd32(const uint8_t* SK_RESTRICT src, const SkGlyph& glyph,
991 const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) {
992 const size_t dstRB = glyph.rowBytes();
993 const U16CPU width = glyph.fWidth;
994 SkPMColor* SK_RESTRICT dst = static_cast<SkPMColor*>(glyph.fImage);
995
996 for (U16CPU y = 0; y < glyph.fHeight; y++) {
997 for (U16CPU i = 0; i < width; i++) {
998 U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableR);
999 U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableG);
1000 U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>(*(src++), tableB);
1001 dst[i] = SkPackARGB32(0xFF, r, g, b);
1002 }
1003 dst = (SkPMColor*)((char*)dst + dstRB);
1004 }
1005}
1006
bungeman@google.coma76de722012-10-26 19:35:54 +00001007void SkScalerContext_Windows::generateImage(const SkGlyph& glyph) {
bungeman@google.come8f05922012-08-16 16:13:40 +00001008 SkAutoMutexAcquire ac(gFTMutex);
1009
bungeman@google.come8f05922012-08-16 16:13:40 +00001010 const bool isBW = SkMask::kBW_Format == fRec.fMaskFormat;
1011 const bool isAA = !isLCD(fRec);
1012
1013 //Create the mask.
1014 const void* bits = fOffscreen.draw(glyph, isBW);
1015 if (!bits) {
1016 sk_bzero(glyph.fImage, glyph.computeImageSize());
1017 return;
1018 }
1019
1020 //Copy the mask into the glyph.
bungeman@google.come8f05922012-08-16 16:13:40 +00001021 const uint8_t* src = (const uint8_t*)bits;
1022 if (isBW) {
1023 bilevel_to_bw(src, glyph);
1024 } else if (isAA) {
bungeman@google.coma76de722012-10-26 19:35:54 +00001025 if (fPreBlend.isApplicable()) {
1026 rgb_to_a8<true>(src, glyph, fPreBlend.fG);
bungeman@google.come8f05922012-08-16 16:13:40 +00001027 } else {
bungeman@google.coma76de722012-10-26 19:35:54 +00001028 rgb_to_a8<false>(src, glyph, fPreBlend.fG);
bungeman@google.come8f05922012-08-16 16:13:40 +00001029 }
1030 } else if (SkMask::kLCD16_Format == glyph.fMaskFormat) {
bungeman@google.coma76de722012-10-26 19:35:54 +00001031 if (fPreBlend.isApplicable()) {
1032 rgb_to_lcd16<true>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
bungeman@google.come8f05922012-08-16 16:13:40 +00001033 } else {
bungeman@google.coma76de722012-10-26 19:35:54 +00001034 rgb_to_lcd16<false>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
bungeman@google.come8f05922012-08-16 16:13:40 +00001035 }
1036 } else {
1037 SkASSERT(SkMask::kLCD32_Format == glyph.fMaskFormat);
bungeman@google.coma76de722012-10-26 19:35:54 +00001038 if (fPreBlend.isApplicable()) {
1039 rgb_to_lcd32<true>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
bungeman@google.come8f05922012-08-16 16:13:40 +00001040 } else {
bungeman@google.coma76de722012-10-26 19:35:54 +00001041 rgb_to_lcd32<false>(src, glyph, fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
bungeman@google.come8f05922012-08-16 16:13:40 +00001042 }
1043 }
1044}
1045
1046void SkScalerContext_Windows::generatePath(const SkGlyph& glyph, SkPath* path) {
1047 SkAutoMutexAcquire ac(gFTMutex);
1048
1049 SkASSERT(&glyph && path);
1050
1051 path->reset();
1052
1053 SkTScopedComPtr<IDWriteGeometrySink> geometryToPath;
1054 HRVM(SkDWriteGeometrySink::Create(path, &geometryToPath),
1055 "Could not create geometry to path converter.");
1056 uint16_t glyphId = glyph.getGlyphID();
1057 //TODO: convert to<->from DIUs? This would make a difference if hinting.
1058 //It may not be needed, it appears that DirectWrite only hints at em size.
1059 HRVM(fTypeface->fDWriteFontFace->GetGlyphRunOutline(SkScalarToFloat(fRec.fTextSize),
1060 &glyphId,
1061 NULL, //advances
1062 NULL, //offsets
1063 1, //num glyphs
1064 FALSE, //sideways
1065 FALSE, //rtl
1066 geometryToPath.get()),
1067 "Could not create glyph outline.");
bungeman@google.com091f51b2013-01-10 18:56:18 +00001068
1069 SkMatrix mat;
1070 fRec.getMatrixFrom2x2(&mat);
1071 path->transform(mat);
bungeman@google.come8f05922012-08-16 16:13:40 +00001072}
1073
reed@google.com5526ede2013-03-25 13:03:37 +00001074void DWriteFontTypeface::onGetFontDescriptor(SkFontDescriptor* desc,
1075 bool* isLocalStream) const {
bungeman@google.com94acfb52012-08-31 15:41:09 +00001076 // Get the family name.
1077 SkTScopedComPtr<IDWriteLocalizedStrings> dwFamilyNames;
reed@google.com5526ede2013-03-25 13:03:37 +00001078 HRV(fDWriteFontFamily->GetFamilyNames(&dwFamilyNames));
bungeman@google.com94acfb52012-08-31 15:41:09 +00001079
1080 UINT32 dwFamilyNamesLength;
1081 HRV(dwFamilyNames->GetStringLength(0, &dwFamilyNamesLength));
1082
bungeman@google.com71033442013-05-01 14:21:20 +00001083 SkSMallocWCHAR dwFamilyNameChar(dwFamilyNamesLength+1);
1084 HRV(dwFamilyNames->GetString(0, dwFamilyNameChar.get(), dwFamilyNamesLength+1));
bungeman@google.com94acfb52012-08-31 15:41:09 +00001085
bungeman@google.com71033442013-05-01 14:21:20 +00001086 SkString utf8FamilyName;
1087 HRV(wchar_to_skstring(dwFamilyNameChar.get(), &utf8FamilyName));
bungeman@google.com94acfb52012-08-31 15:41:09 +00001088
bungeman@google.com71033442013-05-01 14:21:20 +00001089 desc->setFamilyName(utf8FamilyName.c_str());
reed@google.com5526ede2013-03-25 13:03:37 +00001090 *isLocalStream = SkToBool(fDWriteFontFileLoader.get());
bungeman@google.come8f05922012-08-16 16:13:40 +00001091}
1092
bungeman@google.com71033442013-05-01 14:21:20 +00001093static SkTypeface* create_from_stream(SkStream* stream) {
bungeman@google.come8f05922012-08-16 16:13:40 +00001094 IDWriteFactory* factory;
1095 HRN(get_dwrite_factory(&factory));
1096
1097 SkTScopedComPtr<StreamFontFileLoader> fontFileLoader;
1098 HRN(StreamFontFileLoader::Create(stream, &fontFileLoader));
1099 HRN(factory->RegisterFontFileLoader(fontFileLoader.get()));
1100
1101 SkTScopedComPtr<StreamFontCollectionLoader> streamFontCollectionLoader;
1102 HRN(StreamFontCollectionLoader::Create(fontFileLoader.get(), &streamFontCollectionLoader));
1103 HRN(factory->RegisterFontCollectionLoader(streamFontCollectionLoader.get()));
1104
1105 SkTScopedComPtr<IDWriteFontCollection> streamFontCollection;
1106 HRN(factory->CreateCustomFontCollection(streamFontCollectionLoader.get(), NULL, 0,
1107 &streamFontCollection));
1108
1109 SkTScopedComPtr<IDWriteFontFamily> fontFamily;
1110 HRN(streamFontCollection->GetFontFamily(0, &fontFamily));
1111
1112 SkTScopedComPtr<IDWriteFont> font;
1113 HRN(fontFamily->GetFont(0, &font));
1114
1115 SkTScopedComPtr<IDWriteFontFace> fontFace;
1116 HRN(font->CreateFontFace(&fontFace));
1117
1118 return SkCreateTypefaceFromDWriteFont(fontFace.get(), font.get(), fontFamily.get(),
1119 fontFileLoader.get(), streamFontCollectionLoader.get());
1120}
1121
bungeman@google.com71033442013-05-01 14:21:20 +00001122SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) {
1123 return create_from_stream(stream);
1124}
1125
reed@google.com177dc6e2013-03-21 20:55:10 +00001126SkStream* DWriteFontTypeface::onOpenStream(int* ttcIndex) const {
1127 *ttcIndex = 0;
bungeman@google.come8f05922012-08-16 16:13:40 +00001128
1129 UINT32 numFiles;
reed@google.com177dc6e2013-03-21 20:55:10 +00001130 HRNM(fDWriteFontFace->GetFiles(&numFiles, NULL),
bungeman@google.come8f05922012-08-16 16:13:40 +00001131 "Could not get number of font files.");
1132 if (numFiles != 1) {
1133 return NULL;
1134 }
1135
1136 SkTScopedComPtr<IDWriteFontFile> fontFile;
reed@google.com177dc6e2013-03-21 20:55:10 +00001137 HRNM(fDWriteFontFace->GetFiles(&numFiles, &fontFile), "Could not get font files.");
bungeman@google.come8f05922012-08-16 16:13:40 +00001138
1139 const void* fontFileKey;
1140 UINT32 fontFileKeySize;
1141 HRNM(fontFile->GetReferenceKey(&fontFileKey, &fontFileKeySize),
1142 "Could not get font file reference key.");
1143
1144 SkTScopedComPtr<IDWriteFontFileLoader> fontFileLoader;
1145 HRNM(fontFile->GetLoader(&fontFileLoader), "Could not get font file loader.");
1146
1147 SkTScopedComPtr<IDWriteFontFileStream> fontFileStream;
1148 HRNM(fontFileLoader->CreateStreamFromKey(fontFileKey, fontFileKeySize,
1149 &fontFileStream),
1150 "Could not create font file stream.");
1151
1152 return SkNEW_ARGS(SkDWriteFontFileStream, (fontFileStream.get()));
1153}
1154
reed@google.com0da48612013-03-19 16:06:52 +00001155SkScalerContext* DWriteFontTypeface::onCreateScalerContext(const SkDescriptor* desc) const {
1156 return SkNEW_ARGS(SkScalerContext_Windows, (const_cast<DWriteFontTypeface*>(this), desc));
bungeman@google.come8f05922012-08-16 16:13:40 +00001157}
1158
1159static HRESULT get_by_family_name(const char familyName[], IDWriteFontFamily** fontFamily) {
1160 IDWriteFactory* factory;
1161 HR(get_dwrite_factory(&factory));
1162
1163 SkTScopedComPtr<IDWriteFontCollection> sysFontCollection;
1164 HR(factory->GetSystemFontCollection(&sysFontCollection, FALSE));
1165
bungeman@google.com71033442013-05-01 14:21:20 +00001166 SkSMallocWCHAR wideFamilyName;
1167 HR(cstring_to_wchar(familyName, &wideFamilyName));
bungeman@google.come8f05922012-08-16 16:13:40 +00001168
1169 UINT32 index;
1170 BOOL exists;
bungeman@google.com71033442013-05-01 14:21:20 +00001171 HR(sysFontCollection->FindFamilyName(wideFamilyName.get(), &index, &exists));
bungeman@google.come8f05922012-08-16 16:13:40 +00001172
1173 if (exists) {
1174 HR(sysFontCollection->GetFontFamily(index, fontFamily));
1175 return S_OK;
1176 }
1177 return S_FALSE;
1178}
1179
1180/** Return the closest matching typeface given either an existing family
1181 (specified by a typeface in that family) or by a familyName, and a
1182 requested style.
1183 1) If familyFace is null, use familyName.
1184 2) If familyName is null, use familyFace.
1185 3) If both are null, return the default font that best matches style
1186 This MUST not return NULL.
1187 */
1188SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace,
1189 const char familyName[],
1190 SkTypeface::Style style) {
1191 HRESULT hr;
1192 SkTScopedComPtr<IDWriteFontFamily> fontFamily;
1193 SkTScopedComPtr<IDWriteFontCollectionLoader> fontCollectionLoader;
1194 SkTScopedComPtr<IDWriteFontFileLoader> fontFileLoader;
1195 if (familyFace) {
1196 const DWriteFontTypeface* face = static_cast<const DWriteFontTypeface*>(familyFace);
1197 face->fDWriteFontFamily.get()->AddRef();
1198 *(&fontFamily) = face->fDWriteFontFamily.get();
1199
1200 if (face->fDWriteFontCollectionLoader.get() != NULL) {
1201 face->fDWriteFontCollectionLoader.get()->AddRef();
1202 *(&fontCollectionLoader) = face->fDWriteFontCollectionLoader.get();
1203
1204 face->fDWriteFontFileLoader.get()->AddRef();
1205 *(&fontFileLoader) = face->fDWriteFontFileLoader.get();
1206 }
1207
1208 } else if (familyName) {
1209 hr = get_by_family_name(familyName, &fontFamily);
1210 }
1211
1212 if (NULL == fontFamily.get()) {
1213 //No good family found, go with default.
1214 SkTScopedComPtr<IDWriteFont> font;
1215 hr = get_default_font(&font);
1216 hr = font->GetFontFamily(&fontFamily);
1217 }
1218
1219 SkTScopedComPtr<IDWriteFont> font;
1220 DWRITE_FONT_WEIGHT weight = (style & SkTypeface::kBold)
1221 ? DWRITE_FONT_WEIGHT_BOLD
1222 : DWRITE_FONT_WEIGHT_NORMAL;
1223 DWRITE_FONT_STRETCH stretch = DWRITE_FONT_STRETCH_UNDEFINED;
1224 DWRITE_FONT_STYLE italic = (style & SkTypeface::kItalic)
1225 ? DWRITE_FONT_STYLE_ITALIC
1226 : DWRITE_FONT_STYLE_NORMAL;
1227 hr = fontFamily->GetFirstMatchingFont(weight, stretch, italic, &font);
1228
1229 SkTScopedComPtr<IDWriteFontFace> fontFace;
1230 hr = font->CreateFontFace(&fontFace);
1231
bungeman@google.com94acfb52012-08-31 15:41:09 +00001232 return SkCreateTypefaceFromDWriteFont(fontFace.get(), font.get(), fontFamily.get());
bungeman@google.come8f05922012-08-16 16:13:40 +00001233}
1234
1235SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) {
1236 printf("SkFontHost::CreateTypefaceFromFile unimplemented");
1237 return NULL;
1238}
1239
reed@google.com0da48612013-03-19 16:06:52 +00001240void DWriteFontTypeface::onFilterRec(SkScalerContext::Rec* rec) const {
bungeman@google.come8f05922012-08-16 16:13:40 +00001241 unsigned flagsWeDontSupport = SkScalerContext::kDevKernText_Flag |
1242 SkScalerContext::kAutohinting_Flag |
1243 SkScalerContext::kEmbeddedBitmapText_Flag |
1244 SkScalerContext::kEmbolden_Flag |
1245 SkScalerContext::kLCD_BGROrder_Flag |
1246 SkScalerContext::kLCD_Vertical_Flag;
1247 rec->fFlags &= ~flagsWeDontSupport;
1248
1249 SkPaint::Hinting h = rec->getHinting();
1250 // DirectWrite does not provide for hinting hints.
1251 h = SkPaint::kSlight_Hinting;
1252 rec->setHinting(h);
1253
1254#if SK_FONT_HOST_USE_SYSTEM_SETTINGS
1255 IDWriteFactory* factory;
1256 if (SUCCEEDED(get_dwrite_factory(&factory))) {
1257 SkTScopedComPtr<IDWriteRenderingParams> defaultRenderingParams;
1258 if (SUCCEEDED(factory->CreateRenderingParams(&defaultRenderingParams))) {
1259 float gamma = defaultRenderingParams->GetGamma();
1260 rec->setDeviceGamma(SkFloatToScalar(gamma));
1261 rec->setPaintGamma(SkFloatToScalar(gamma));
rmistry@google.comd6176b02012-08-23 18:14:13 +00001262
bungeman@google.come8f05922012-08-16 16:13:40 +00001263 rec->setContrast(SkFloatToScalar(defaultRenderingParams->GetEnhancedContrast()));
1264 }
1265 }
1266#endif
1267}
1268
1269///////////////////////////////////////////////////////////////////////////////
1270//PDF Support
1271
1272using namespace skia_advanced_typeface_metrics_utils;
1273
1274// Construct Glyph to Unicode table.
1275// Unicode code points that require conjugate pairs in utf16 are not
1276// supported.
1277// TODO(arthurhsu): Add support for conjugate pairs. It looks like that may
1278// require parsing the TTF cmap table (platform 4, encoding 12) directly instead
1279// of calling GetFontUnicodeRange().
1280// TODO(bungeman): This never does what anyone wants.
1281// What is really wanted is the text to glyphs mapping
1282static void populate_glyph_to_unicode(IDWriteFontFace* fontFace,
1283 const unsigned glyphCount,
1284 SkTDArray<SkUnichar>* glyphToUnicode) {
1285 HRESULT hr = S_OK;
1286
1287 //Do this like free type instead
1288 UINT32 count = 0;
1289 for (UINT32 c = 0; c < 0x10FFFF; ++c) {
1290 UINT16 glyph;
1291 hr = fontFace->GetGlyphIndices(&c, 1, &glyph);
1292 if (glyph > 0) {
1293 ++count;
1294 }
1295 }
1296
1297 SkAutoTArray<UINT32> chars(count);
1298 count = 0;
1299 for (UINT32 c = 0; c < 0x10FFFF; ++c) {
1300 UINT16 glyph;
1301 hr = fontFace->GetGlyphIndices(&c, 1, &glyph);
1302 if (glyph > 0) {
1303 chars[count] = c;
1304 ++count;
1305 }
1306 }
1307
1308 SkAutoTArray<UINT16> glyph(count);
1309 fontFace->GetGlyphIndices(chars.get(), count, glyph.get());
1310
1311 USHORT maxGlyph = 0;
1312 for (USHORT j = 0; j < count; ++j) {
1313 if (glyph[j] > maxGlyph) maxGlyph = glyph[j];
1314 }
1315
1316 glyphToUnicode->setCount(maxGlyph+1);
1317 for (size_t j = 0; j < maxGlyph+1u; ++j) {
1318 (*glyphToUnicode)[j] = 0;
1319 }
1320
1321 //'invert'
1322 for (USHORT j = 0; j < count; ++j) {
1323 if (glyph[j] < glyphCount && (*glyphToUnicode)[glyph[j]] == 0) {
1324 (*glyphToUnicode)[glyph[j]] = chars[j];
1325 }
1326 }
1327}
1328
1329static bool getWidthAdvance(IDWriteFontFace* fontFace, int gId, int16_t* advance) {
1330 SkASSERT(advance);
1331
1332 UINT16 glyphId = gId;
1333 DWRITE_GLYPH_METRICS gm;
1334 HRESULT hr = fontFace->GetDesignGlyphMetrics(&glyphId, 1, &gm);
1335
1336 if (FAILED(hr)) {
1337 *advance = 0;
1338 return false;
1339 }
1340
1341 *advance = gm.advanceWidth;
1342 return true;
1343}
1344
1345template<typename T>
1346class AutoDWriteTable {
1347public:
1348 AutoDWriteTable(IDWriteFontFace* fontFace)
1349 : fFontFace(fontFace)
1350 , fExists(FALSE) {
1351
1352 //fontFace->AddRef();
1353 const UINT32 tag = DWRITE_MAKE_OPENTYPE_TAG(T::TAG0,
1354 T::TAG1,
1355 T::TAG2,
1356 T::TAG3);
reed@google.com177dc6e2013-03-21 20:55:10 +00001357 // TODO: need to check for failure
1358 /*HRESULT hr =*/ fontFace->TryGetFontTable(tag,
bungeman@google.come8f05922012-08-16 16:13:40 +00001359 reinterpret_cast<const void **>(&fData), &fSize, &fLock, &fExists);
1360 }
1361 ~AutoDWriteTable() {
1362 if (fExists) {
1363 fFontFace->ReleaseFontTable(fLock);
1364 }
1365 }
1366 const T* operator->() const { return fData; }
1367
1368 const T* fData;
1369 UINT32 fSize;
1370 BOOL fExists;
1371private:
1372 //SkTScopedComPtr<IDWriteFontFace> fFontFace;
1373 IDWriteFontFace* fFontFace;
1374 void* fLock;
1375};
1376
reed@google.com2689f612013-03-20 20:01:47 +00001377SkAdvancedTypefaceMetrics* DWriteFontTypeface::onGetAdvancedTypefaceMetrics(
bungeman@google.come8f05922012-08-16 16:13:40 +00001378 SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo,
1379 const uint32_t* glyphIDs,
reed@google.com2689f612013-03-20 20:01:47 +00001380 uint32_t glyphIDsCount) const {
bungeman@google.come8f05922012-08-16 16:13:40 +00001381
1382 SkAdvancedTypefaceMetrics* info = NULL;
1383
1384 HRESULT hr = S_OK;
1385
reed@google.com2689f612013-03-20 20:01:47 +00001386 const unsigned glyphCount = fDWriteFontFace->GetGlyphCount();
bungeman@google.come8f05922012-08-16 16:13:40 +00001387
1388 DWRITE_FONT_METRICS dwfm;
reed@google.com2689f612013-03-20 20:01:47 +00001389 fDWriteFontFace->GetMetrics(&dwfm);
bungeman@google.come8f05922012-08-16 16:13:40 +00001390
1391 info = new SkAdvancedTypefaceMetrics;
1392 info->fEmSize = dwfm.designUnitsPerEm;
1393 info->fMultiMaster = false;
1394 info->fLastGlyphID = SkToU16(glyphCount - 1);
1395 info->fStyle = 0;
1396
1397
1398 SkTScopedComPtr<IDWriteLocalizedStrings> familyNames;
1399 SkTScopedComPtr<IDWriteLocalizedStrings> faceNames;
reed@google.com2689f612013-03-20 20:01:47 +00001400 hr = fDWriteFontFamily->GetFamilyNames(&familyNames);
1401 hr = fDWriteFont->GetFaceNames(&faceNames);
bungeman@google.come8f05922012-08-16 16:13:40 +00001402
1403 UINT32 familyNameLength;
1404 hr = familyNames->GetStringLength(0, &familyNameLength);
1405
1406 UINT32 faceNameLength;
1407 hr = faceNames->GetStringLength(0, &faceNameLength);
1408
bungeman@google.com71033442013-05-01 14:21:20 +00001409 UINT32 size = familyNameLength+1+faceNameLength+1;
1410 SkSMallocWCHAR wFamilyName(size);
1411 hr = familyNames->GetString(0, wFamilyName.get(), size);
bungeman@google.come8f05922012-08-16 16:13:40 +00001412 wFamilyName[familyNameLength] = L' ';
1413 hr = faceNames->GetString(0, &wFamilyName[familyNameLength+1], size - faceNameLength + 1);
1414
bungeman@google.com71033442013-05-01 14:21:20 +00001415 hr = wchar_to_skstring(wFamilyName.get(), &info->fFontName);
bungeman@google.come8f05922012-08-16 16:13:40 +00001416
1417 if (perGlyphInfo & SkAdvancedTypefaceMetrics::kToUnicode_PerGlyphInfo) {
reed@google.com2689f612013-03-20 20:01:47 +00001418 populate_glyph_to_unicode(fDWriteFontFace.get(), glyphCount, &(info->fGlyphToUnicode));
bungeman@google.come8f05922012-08-16 16:13:40 +00001419 }
1420
reed@google.com2689f612013-03-20 20:01:47 +00001421 DWRITE_FONT_FACE_TYPE fontType = fDWriteFontFace->GetType();
bungeman@google.come8f05922012-08-16 16:13:40 +00001422 if (fontType == DWRITE_FONT_FACE_TYPE_TRUETYPE ||
1423 fontType == DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION) {
1424 info->fType = SkAdvancedTypefaceMetrics::kTrueType_Font;
1425 } else {
1426 info->fType = SkAdvancedTypefaceMetrics::kOther_Font;
1427 info->fItalicAngle = 0;
1428 info->fAscent = dwfm.ascent;;
1429 info->fDescent = dwfm.descent;
1430 info->fStemV = 0;
1431 info->fCapHeight = dwfm.capHeight;
1432 info->fBBox = SkIRect::MakeEmpty();
1433 return info;
1434 }
1435
reed@google.com2689f612013-03-20 20:01:47 +00001436 AutoDWriteTable<SkOTTableHead> headTable(fDWriteFontFace.get());
1437 AutoDWriteTable<SkOTTablePostScript> postTable(fDWriteFontFace.get());
1438 AutoDWriteTable<SkOTTableHorizontalHeader> hheaTable(fDWriteFontFace.get());
1439 AutoDWriteTable<SkOTTableOS2> os2Table(fDWriteFontFace.get());
bungeman@google.come8f05922012-08-16 16:13:40 +00001440 if (!headTable.fExists || !postTable.fExists || !hheaTable.fExists || !os2Table.fExists) {
1441 info->fItalicAngle = 0;
1442 info->fAscent = dwfm.ascent;;
1443 info->fDescent = dwfm.descent;
1444 info->fStemV = 0;
1445 info->fCapHeight = dwfm.capHeight;
1446 info->fBBox = SkIRect::MakeEmpty();
1447 return info;
1448 }
1449
1450 //There exist CJK fonts which set the IsFixedPitch and Monospace bits,
1451 //but have full width, latin half-width, and half-width kana.
1452 bool fixedWidth = (postTable->isFixedPitch &&
1453 (1 == SkEndian_SwapBE16(hheaTable->numberOfHMetrics)));
1454 //Monospace
1455 if (fixedWidth) {
1456 info->fStyle |= SkAdvancedTypefaceMetrics::kFixedPitch_Style;
1457 }
1458 //Italic
1459 if (os2Table->version.v0.fsSelection.field.Italic) {
1460 info->fStyle |= SkAdvancedTypefaceMetrics::kItalic_Style;
1461 }
bungeman@google.come8f05922012-08-16 16:13:40 +00001462 //Script
1463 if (SkPanose::FamilyType::Script == os2Table->version.v0.panose.bFamilyType.value) {
1464 info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style;
1465 //Serif
1466 } else if (SkPanose::FamilyType::TextAndDisplay == os2Table->version.v0.panose.bFamilyType.value &&
1467 SkPanose::Data::TextAndDisplay::SerifStyle::Triangle <= os2Table->version.v0.panose.data.textAndDisplay.bSerifStyle.value &&
1468 SkPanose::Data::TextAndDisplay::SerifStyle::NoFit != os2Table->version.v0.panose.data.textAndDisplay.bSerifStyle.value) {
1469 info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style;
1470 }
1471
1472 info->fItalicAngle = SkEndian_SwapBE32(postTable->italicAngle) >> 16;
1473
1474 info->fAscent = SkToS16(dwfm.ascent);
1475 info->fDescent = SkToS16(dwfm.descent);
1476 info->fCapHeight = SkToS16(dwfm.capHeight);
1477
1478 info->fBBox = SkIRect::MakeLTRB((int32_t)SkEndian_SwapBE16((uint16_t)headTable->xMin),
1479 (int32_t)SkEndian_SwapBE16((uint16_t)headTable->yMax),
1480 (int32_t)SkEndian_SwapBE16((uint16_t)headTable->xMax),
1481 (int32_t)SkEndian_SwapBE16((uint16_t)headTable->yMin));
1482
1483 //TODO: is this even desired? It seems PDF only wants this value for Type1
1484 //fonts, and we only get here for TrueType fonts.
1485 info->fStemV = 0;
1486 /*
1487 // Figure out a good guess for StemV - Min width of i, I, !, 1.
1488 // This probably isn't very good with an italic font.
1489 int16_t min_width = SHRT_MAX;
1490 info->fStemV = 0;
1491 char stem_chars[] = {'i', 'I', '!', '1'};
1492 for (size_t i = 0; i < SK_ARRAY_COUNT(stem_chars); i++) {
1493 ABC abcWidths;
1494 if (GetCharABCWidths(hdc, stem_chars[i], stem_chars[i], &abcWidths)) {
1495 int16_t width = abcWidths.abcB;
1496 if (width > 0 && width < min_width) {
1497 min_width = width;
1498 info->fStemV = min_width;
1499 }
1500 }
1501 }
1502 */
rmistry@google.comd6176b02012-08-23 18:14:13 +00001503
bungeman@google.come8f05922012-08-16 16:13:40 +00001504 // If Restricted, the font may not be embedded in a document.
1505 // If not Restricted, the font can be embedded.
1506 // If PreviewPrint, the embedding is read-only.
1507 if (os2Table->version.v0.fsType.field.Restricted) {
1508 info->fType = SkAdvancedTypefaceMetrics::kNotEmbeddable_Font;
1509 } else if (perGlyphInfo & SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo) {
1510 if (fixedWidth) {
1511 appendRange(&info->fGlyphWidths, 0);
1512 int16_t advance;
reed@google.com2689f612013-03-20 20:01:47 +00001513 getWidthAdvance(fDWriteFontFace.get(), 1, &advance);
bungeman@google.come8f05922012-08-16 16:13:40 +00001514 info->fGlyphWidths->fAdvance.append(1, &advance);
1515 finishRange(info->fGlyphWidths.get(), 0,
1516 SkAdvancedTypefaceMetrics::WidthRange::kDefault);
1517 } else {
1518 info->fGlyphWidths.reset(
reed@google.com2689f612013-03-20 20:01:47 +00001519 getAdvanceData(fDWriteFontFace.get(),
bungeman@google.come8f05922012-08-16 16:13:40 +00001520 glyphCount,
1521 glyphIDs,
1522 glyphIDsCount,
1523 getWidthAdvance));
1524 }
1525 }
1526
1527 return info;
1528}
reed@google.com070da5e2013-03-27 20:01:49 +00001529
1530///////////////////////////////////////////////////////////////////////////////
1531
1532#include "SkFontMgr.h"
1533
bungeman@google.com71033442013-05-01 14:21:20 +00001534static void get_locale_string(IDWriteLocalizedStrings* names, const WCHAR* preferedLocale,
1535 SkString* skname) {
1536 UINT32 nameIndex = 0;
1537 if (preferedLocale) {
1538 // Ignore any errors and continue with index 0 if there is a problem.
1539 BOOL nameExists;
1540 names->FindLocaleName(preferedLocale, &nameIndex, &nameExists);
1541 if (!nameExists) {
1542 nameIndex = 0;
1543 }
1544 }
1545
1546 UINT32 nameLength;
1547 HRVM(names->GetStringLength(nameIndex, &nameLength), "Could not get name length.");
1548 nameLength += 1;
1549
1550 SkSMallocWCHAR name(nameLength);
1551 HRVM(names->GetString(nameIndex, name.get(), nameLength), "Could not get string.");
1552
1553 HRV(wchar_to_skstring(name.get(), skname));
1554}
1555
1556class SkFontMgr_DirectWrite;
1557
1558class SkFontStyleSet_DirectWrite : public SkFontStyleSet {
1559public:
1560 SkFontStyleSet_DirectWrite(const SkFontMgr_DirectWrite* fontMgr, IDWriteFontFamily* fontFamily)
1561 : fFontMgr(SkRef(fontMgr))
1562 , fFontFamily(SkRefComPtr(fontFamily))
1563 { }
1564
1565 virtual int count() SK_OVERRIDE {
1566 return fFontFamily->GetFontCount();
1567 }
1568
1569 virtual void getStyle(int index, SkFontStyle* fs, SkString* styleName);
1570
1571 virtual SkTypeface* createTypeface(int index) SK_OVERRIDE {
1572 SkTScopedComPtr<IDWriteFont> font;
1573 HRNM(fFontFamily->GetFont(index, &font), "Could not get font.");
1574
1575 SkTScopedComPtr<IDWriteFontFace> fontFace;
1576 HRNM(font->CreateFontFace(&fontFace), "Could not create font face.");
1577
1578 return SkCreateTypefaceFromDWriteFont(fontFace.get(), font.get(), fFontFamily.get());
1579 }
1580
1581 virtual SkTypeface* matchStyle(const SkFontStyle& pattern) SK_OVERRIDE {
1582 DWRITE_FONT_STYLE slant;
1583 switch (pattern.slant()) {
1584 case SkFontStyle::kUpright_Slant:
1585 slant = DWRITE_FONT_STYLE_NORMAL;
1586 break;
1587 case SkFontStyle::kItalic_Slant:
1588 slant = DWRITE_FONT_STYLE_ITALIC;
1589 break;
1590 default:
1591 SkASSERT(false);
1592 }
1593
1594 DWRITE_FONT_WEIGHT weight = (DWRITE_FONT_WEIGHT)pattern.weight();
1595 DWRITE_FONT_STRETCH width = (DWRITE_FONT_STRETCH)pattern.width();
1596
1597 SkTScopedComPtr<IDWriteFont> font;
1598 HRNM(fFontFamily->GetFirstMatchingFont(weight, width, slant, &font),
1599 "Could not match font in family.");
1600
1601 SkTScopedComPtr<IDWriteFontFace> fontFace;
1602 HRNM(font->CreateFontFace(&fontFace), "Could not create font face.");
1603
1604 return SkCreateTypefaceFromDWriteFont(fontFace.get(), font.get(), fFontFamily.get());
1605 }
1606
1607private:
1608 SkAutoTUnref<const SkFontMgr_DirectWrite> fFontMgr;
1609 SkTScopedComPtr<IDWriteFontFamily> fFontFamily;
1610};
1611
1612class SkFontMgr_DirectWrite : public SkFontMgr {
1613public:
1614 /** localeNameLength must include the null terminator. */
1615 SkFontMgr_DirectWrite(IDWriteFontCollection* fontCollection,
1616 WCHAR* localeName, int localeNameLength)
1617 : fFontCollection(SkRefComPtr(fontCollection))
1618 , fLocaleName(localeNameLength)
1619 {
1620 memcpy(fLocaleName.get(), localeName, localeNameLength * sizeof(WCHAR));
1621 }
1622
1623private:
1624 friend class SkFontStyleSet_DirectWrite;
1625 SkTScopedComPtr<IDWriteFontCollection> fFontCollection;
1626 SkSMallocWCHAR fLocaleName;
1627
1628protected:
1629 virtual int onCountFamilies() SK_OVERRIDE {
1630 return fFontCollection->GetFontFamilyCount();
1631 }
1632 virtual void onGetFamilyName(int index, SkString* familyName) SK_OVERRIDE {
1633 SkTScopedComPtr<IDWriteFontFamily> fontFamily;
1634 HRVM(fFontCollection->GetFontFamily(index, &fontFamily), "Could not get requested family.");
1635
1636 SkTScopedComPtr<IDWriteLocalizedStrings> familyNames;
1637 HRVM(fontFamily->GetFamilyNames(&familyNames), "Could not get family names.");
1638
1639 get_locale_string(familyNames.get(), fLocaleName.get(), familyName);
1640 }
1641 virtual SkFontStyleSet* onCreateStyleSet(int index) SK_OVERRIDE {
1642 SkTScopedComPtr<IDWriteFontFamily> fontFamily;
1643 HRNM(fFontCollection->GetFontFamily(index, &fontFamily), "Could not get requested family.");
1644
1645 return SkNEW_ARGS(SkFontStyleSet_DirectWrite, (this, fontFamily.get()));
1646 }
1647 virtual SkFontStyleSet* onMatchFamily(const char familyName[]) SK_OVERRIDE {
1648 SkSMallocWCHAR dwFamilyName;
1649 HRN(cstring_to_wchar(familyName, &dwFamilyName));
1650
1651 UINT32 index;
1652 BOOL exists;
1653 HRNM(fFontCollection->FindFamilyName(dwFamilyName.get(), &index, &exists),
1654 "Failed while finding family by name.");
1655 if (!exists) {
1656 return NULL;
1657 }
1658
1659 return this->onCreateStyleSet(index);
1660 }
1661
1662 virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
1663 const SkFontStyle& fontstyle) SK_OVERRIDE {
1664 SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName));
1665 return sset->matchStyle(fontstyle);
1666 }
1667 virtual SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember,
1668 const SkFontStyle& fontstyle) SK_OVERRIDE {
1669 SkString familyName;
1670 SkFontStyleSet_DirectWrite sset(
1671 this, ((DWriteFontTypeface*)familyMember)->fDWriteFontFamily.get()
1672 );
1673 return sset.matchStyle(fontstyle);
1674 }
1675 virtual SkTypeface* onCreateFromStream(SkStream* stream, int ttcIndex) SK_OVERRIDE {
1676 return create_from_stream(stream);
1677 }
1678 virtual SkTypeface* onCreateFromData(SkData* data, int ttcIndex) SK_OVERRIDE {
1679 SkAutoTUnref<SkStream> stream(SkNEW_ARGS(SkMemoryStream, (data)));
1680 return this->createFromStream(stream, ttcIndex);
1681 }
1682 virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) SK_OVERRIDE {
1683 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path));
1684 return this->createFromStream(stream, ttcIndex);
1685 }
1686};
1687
1688void SkFontStyleSet_DirectWrite::getStyle(int index, SkFontStyle* fs, SkString* styleName) {
1689 SkTScopedComPtr<IDWriteFont> font;
1690 HRVM(fFontFamily->GetFont(index, &font), "Could not get font.");
1691
1692 SkFontStyle::Slant slant;
1693 switch (font->GetStyle()) {
1694 case DWRITE_FONT_STYLE_NORMAL:
1695 slant = SkFontStyle::kUpright_Slant;
1696 break;
1697 case DWRITE_FONT_STYLE_OBLIQUE:
1698 case DWRITE_FONT_STYLE_ITALIC:
1699 slant = SkFontStyle::kItalic_Slant;
1700 break;
1701 default:
1702 SkASSERT(false);
1703 }
1704
1705 int weight = font->GetWeight();
1706 int width = font->GetStretch();
1707
1708 *fs = SkFontStyle(weight, width, slant);
1709
1710 SkTScopedComPtr<IDWriteLocalizedStrings> faceNames;
1711 if (SUCCEEDED(font->GetFaceNames(&faceNames))) {
1712 get_locale_string(faceNames.get(), fFontMgr->fLocaleName.get(), styleName);
1713 }
1714}
1715
reed@google.com070da5e2013-03-27 20:01:49 +00001716SkFontMgr* SkFontMgr::Factory() {
bungeman@google.com71033442013-05-01 14:21:20 +00001717 IDWriteFactory* factory;
1718 HRNM(get_dwrite_factory(&factory), "Could not get factory.");
1719
1720 SkTScopedComPtr<IDWriteFontCollection> sysFontCollection;
1721 HRNM(factory->GetSystemFontCollection(&sysFontCollection, FALSE),
1722 "Could not get system font collection.");
1723
1724 WCHAR localeNameStorage[LOCALE_NAME_MAX_LENGTH];
1725 WCHAR* localeName = NULL;
1726 int localeNameLen = GetUserDefaultLocaleName(localeNameStorage, LOCALE_NAME_MAX_LENGTH);
1727 if (localeNameLen) {
1728 localeName = localeNameStorage;
1729 };
1730
1731 return SkNEW_ARGS(SkFontMgr_DirectWrite, (sysFontCollection.get(), localeName, localeNameLen));
reed@google.com070da5e2013-03-27 20:01:49 +00001732}