OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkTypes.h" | 8 #include "SkTypes.h" |
9 #undef GetGlyphIndices | 9 #undef GetGlyphIndices |
10 | 10 |
11 #include "SkAdvancedTypefaceMetrics.h" | |
12 #include "SkColorFilter.h" | |
13 #include "SkDWrite.h" | 11 #include "SkDWrite.h" |
14 #include "SkDWriteFontFileStream.h" | |
15 #include "SkDWriteGeometrySink.h" | 12 #include "SkDWriteGeometrySink.h" |
16 #include "SkDescriptor.h" | |
17 #include "SkEndian.h" | 13 #include "SkEndian.h" |
18 #include "SkFontDescriptor.h" | |
19 #include "SkFontHost.h" | |
20 #include "SkFontMgr.h" | |
21 #include "SkFontStream.h" | |
22 #include "SkGlyph.h" | 14 #include "SkGlyph.h" |
23 #include "SkHRESULT.h" | 15 #include "SkHRESULT.h" |
24 #include "SkMaskGamma.h" | 16 #include "SkMaskGamma.h" |
25 #include "SkMatrix22.h" | 17 #include "SkMatrix22.h" |
26 #include "SkOnce.h" | |
27 #include "SkOTTable_EBLC.h" | 18 #include "SkOTTable_EBLC.h" |
28 #include "SkOTTable_EBSC.h" | 19 #include "SkOTTable_EBSC.h" |
29 #include "SkOTTable_head.h" | |
30 #include "SkOTTable_hhea.h" | |
31 #include "SkOTTable_OS_2.h" | |
32 #include "SkOTTable_post.h" | |
33 #include "SkPath.h" | 20 #include "SkPath.h" |
34 #include "SkStream.h" | 21 #include "SkScalerContext.h" |
35 #include "SkString.h" | 22 #include "SkScalerContext_win_dw.h" |
36 #include "SkTScopedComPtr.h" | 23 #include "SkTScopedComPtr.h" |
37 #include "SkThread.h" | 24 #include "SkTypeface_win_dw.h" |
38 #include "SkTypeface_win.h" | |
39 #include "SkTypefaceCache.h" | |
40 #include "SkUtils.h" | |
41 | 25 |
42 #include <dwrite.h> | 26 #include <dwrite.h> |
43 | 27 |
44 static bool isLCD(const SkScalerContext::Rec& rec) { | 28 static bool isLCD(const SkScalerContext::Rec& rec) { |
45 return SkMask::kLCD16_Format == rec.fMaskFormat || | 29 return SkMask::kLCD16_Format == rec.fMaskFormat || |
46 SkMask::kLCD32_Format == rec.fMaskFormat; | 30 SkMask::kLCD32_Format == rec.fMaskFormat; |
47 } | 31 } |
48 | 32 |
49 /////////////////////////////////////////////////////////////////////////////// | |
50 | |
51 class StreamFontFileLoader; | |
52 | |
53 class SkFontMgr_DirectWrite : public SkFontMgr { | |
54 public: | |
55 /** localeNameLength must include the null terminator. */ | |
56 SkFontMgr_DirectWrite(IDWriteFactory* factory, IDWriteFontCollection* fontCo
llection, | |
57 WCHAR* localeName, int localeNameLength) | |
58 : fFactory(SkRefComPtr(factory)) | |
59 , fFontCollection(SkRefComPtr(fontCollection)) | |
60 , fLocaleName(localeNameLength) | |
61 { | |
62 memcpy(fLocaleName.get(), localeName, localeNameLength * sizeof(WCHAR)); | |
63 } | |
64 | |
65 /** Creates a typeface using a typeface cache. */ | |
66 SkTypeface* createTypefaceFromDWriteFont(IDWriteFontFace* fontFace, | |
67 IDWriteFont* font, | |
68 IDWriteFontFamily* fontFamily) cons
t; | |
69 | |
70 protected: | |
71 virtual int onCountFamilies() const SK_OVERRIDE; | |
72 virtual void onGetFamilyName(int index, SkString* familyName) const SK_OVERR
IDE; | |
73 virtual SkFontStyleSet* onCreateStyleSet(int index) const SK_OVERRIDE; | |
74 virtual SkFontStyleSet* onMatchFamily(const char familyName[]) const SK_OVER
RIDE; | |
75 virtual SkTypeface* onMatchFamilyStyle(const char familyName[], | |
76 const SkFontStyle& fontstyle) const S
K_OVERRIDE; | |
77 virtual SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember, | |
78 const SkFontStyle& fontstyle) const SK_
OVERRIDE; | |
79 virtual SkTypeface* onCreateFromStream(SkStream* stream, int ttcIndex) const
SK_OVERRIDE; | |
80 virtual SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const SK_OV
ERRIDE; | |
81 virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const
SK_OVERRIDE; | |
82 virtual SkTypeface* onLegacyCreateTypeface(const char familyName[], | |
83 unsigned styleBits) const SK_OVER
RIDE; | |
84 | |
85 private: | |
86 HRESULT getByFamilyName(const WCHAR familyName[], IDWriteFontFamily** fontFa
mily) const; | |
87 HRESULT getDefaultFontFamily(IDWriteFontFamily** fontFamily) const; | |
88 | |
89 void Add(SkTypeface* face, SkTypeface::Style requestedStyle, bool strong) co
nst { | |
90 SkAutoMutexAcquire ama(fTFCacheMutex); | |
91 fTFCache.add(face, requestedStyle, strong); | |
92 } | |
93 | |
94 SkTypeface* FindByProcAndRef(SkTypefaceCache::FindProc proc, void* ctx) cons
t { | |
95 SkAutoMutexAcquire ama(fTFCacheMutex); | |
96 SkTypeface* typeface = fTFCache.findByProcAndRef(proc, ctx); | |
97 return typeface; | |
98 } | |
99 | |
100 SkTScopedComPtr<IDWriteFactory> fFactory; | |
101 SkTScopedComPtr<IDWriteFontCollection> fFontCollection; | |
102 SkSMallocWCHAR fLocaleName; | |
103 mutable SkMutex fTFCacheMutex; | |
104 mutable SkTypefaceCache fTFCache; | |
105 | |
106 friend class SkFontStyleSet_DirectWrite; | |
107 }; | |
108 | |
109 class SkFontStyleSet_DirectWrite : public SkFontStyleSet { | |
110 public: | |
111 SkFontStyleSet_DirectWrite(const SkFontMgr_DirectWrite* fontMgr, | |
112 IDWriteFontFamily* fontFamily) | |
113 : fFontMgr(SkRef(fontMgr)) | |
114 , fFontFamily(SkRefComPtr(fontFamily)) | |
115 { } | |
116 | |
117 virtual int count() SK_OVERRIDE; | |
118 virtual void getStyle(int index, SkFontStyle* fs, SkString* styleName) SK_OV
ERRIDE; | |
119 virtual SkTypeface* createTypeface(int index) SK_OVERRIDE; | |
120 virtual SkTypeface* matchStyle(const SkFontStyle& pattern) SK_OVERRIDE; | |
121 | |
122 private: | |
123 SkAutoTUnref<const SkFontMgr_DirectWrite> fFontMgr; | |
124 SkTScopedComPtr<IDWriteFontFamily> fFontFamily; | |
125 }; | |
126 | |
127 /////////////////////////////////////////////////////////////////////////////// | |
128 | |
129 class StreamFontFileLoader : public IDWriteFontFileLoader { | |
130 public: | |
131 // IUnknown methods | |
132 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObjec
t); | |
133 virtual ULONG STDMETHODCALLTYPE AddRef(); | |
134 virtual ULONG STDMETHODCALLTYPE Release(); | |
135 | |
136 // IDWriteFontFileLoader methods | |
137 virtual HRESULT STDMETHODCALLTYPE CreateStreamFromKey( | |
138 void const* fontFileReferenceKey, | |
139 UINT32 fontFileReferenceKeySize, | |
140 IDWriteFontFileStream** fontFileStream); | |
141 | |
142 static HRESULT Create(SkStream* stream, StreamFontFileLoader** streamFontFil
eLoader) { | |
143 *streamFontFileLoader = new StreamFontFileLoader(stream); | |
144 if (NULL == streamFontFileLoader) { | |
145 return E_OUTOFMEMORY; | |
146 } | |
147 return S_OK; | |
148 } | |
149 | |
150 SkAutoTUnref<SkStream> fStream; | |
151 | |
152 private: | |
153 StreamFontFileLoader(SkStream* stream) : fRefCount(1), fStream(SkRef(stream)
) { } | |
154 | |
155 ULONG fRefCount; | |
156 }; | |
157 | |
158 HRESULT StreamFontFileLoader::QueryInterface(REFIID iid, void** ppvObject) { | |
159 if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileLoader)) { | |
160 *ppvObject = this; | |
161 AddRef(); | |
162 return S_OK; | |
163 } else { | |
164 *ppvObject = NULL; | |
165 return E_NOINTERFACE; | |
166 } | |
167 } | |
168 | |
169 ULONG StreamFontFileLoader::AddRef() { | |
170 return InterlockedIncrement(&fRefCount); | |
171 } | |
172 | |
173 ULONG StreamFontFileLoader::Release() { | |
174 ULONG newCount = InterlockedDecrement(&fRefCount); | |
175 if (0 == newCount) { | |
176 delete this; | |
177 } | |
178 return newCount; | |
179 } | |
180 | |
181 HRESULT StreamFontFileLoader::CreateStreamFromKey( | |
182 void const* fontFileReferenceKey, | |
183 UINT32 fontFileReferenceKeySize, | |
184 IDWriteFontFileStream** fontFileStream) | |
185 { | |
186 SkTScopedComPtr<SkDWriteFontFileStreamWrapper> stream; | |
187 HR(SkDWriteFontFileStreamWrapper::Create(fStream, &stream)); | |
188 *fontFileStream = stream.release(); | |
189 return S_OK; | |
190 } | |
191 | |
192 class StreamFontFileEnumerator : public IDWriteFontFileEnumerator { | |
193 public: | |
194 // IUnknown methods | |
195 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObjec
t); | |
196 virtual ULONG STDMETHODCALLTYPE AddRef(); | |
197 virtual ULONG STDMETHODCALLTYPE Release(); | |
198 | |
199 // IDWriteFontFileEnumerator methods | |
200 virtual HRESULT STDMETHODCALLTYPE MoveNext(BOOL* hasCurrentFile); | |
201 virtual HRESULT STDMETHODCALLTYPE GetCurrentFontFile(IDWriteFontFile** fontF
ile); | |
202 | |
203 static HRESULT Create(IDWriteFactory* factory, IDWriteFontFileLoader* fontFi
leLoader, | |
204 StreamFontFileEnumerator** streamFontFileEnumerator) { | |
205 *streamFontFileEnumerator = new StreamFontFileEnumerator(factory, fontFi
leLoader); | |
206 if (NULL == streamFontFileEnumerator) { | |
207 return E_OUTOFMEMORY; | |
208 } | |
209 return S_OK; | |
210 } | |
211 private: | |
212 StreamFontFileEnumerator(IDWriteFactory* factory, IDWriteFontFileLoader* fon
tFileLoader); | |
213 ULONG fRefCount; | |
214 | |
215 SkTScopedComPtr<IDWriteFactory> fFactory; | |
216 SkTScopedComPtr<IDWriteFontFile> fCurrentFile; | |
217 SkTScopedComPtr<IDWriteFontFileLoader> fFontFileLoader; | |
218 bool fHasNext; | |
219 }; | |
220 | |
221 StreamFontFileEnumerator::StreamFontFileEnumerator(IDWriteFactory* factory, | |
222 IDWriteFontFileLoader* fontFi
leLoader) | |
223 : fRefCount(1) | |
224 , fFactory(SkRefComPtr(factory)) | |
225 , fCurrentFile() | |
226 , fFontFileLoader(SkRefComPtr(fontFileLoader)) | |
227 , fHasNext(true) | |
228 { } | |
229 | |
230 HRESULT StreamFontFileEnumerator::QueryInterface(REFIID iid, void** ppvObject) { | |
231 if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontFileEnumerator)) { | |
232 *ppvObject = this; | |
233 AddRef(); | |
234 return S_OK; | |
235 } else { | |
236 *ppvObject = NULL; | |
237 return E_NOINTERFACE; | |
238 } | |
239 } | |
240 | |
241 ULONG StreamFontFileEnumerator::AddRef() { | |
242 return InterlockedIncrement(&fRefCount); | |
243 } | |
244 | |
245 ULONG StreamFontFileEnumerator::Release() { | |
246 ULONG newCount = InterlockedDecrement(&fRefCount); | |
247 if (0 == newCount) { | |
248 delete this; | |
249 } | |
250 return newCount; | |
251 } | |
252 | |
253 HRESULT StreamFontFileEnumerator::MoveNext(BOOL* hasCurrentFile) { | |
254 *hasCurrentFile = FALSE; | |
255 | |
256 if (!fHasNext) { | |
257 return S_OK; | |
258 } | |
259 fHasNext = false; | |
260 | |
261 UINT32 dummy = 0; | |
262 HR(fFactory->CreateCustomFontFileReference( | |
263 &dummy, //cannot be NULL | |
264 sizeof(dummy), //even if this is 0 | |
265 fFontFileLoader.get(), | |
266 &fCurrentFile)); | |
267 | |
268 *hasCurrentFile = TRUE; | |
269 return S_OK; | |
270 } | |
271 | |
272 HRESULT StreamFontFileEnumerator::GetCurrentFontFile(IDWriteFontFile** fontFile)
{ | |
273 if (fCurrentFile.get() == NULL) { | |
274 *fontFile = NULL; | |
275 return E_FAIL; | |
276 } | |
277 | |
278 *fontFile = SkRefComPtr(fCurrentFile.get()); | |
279 return S_OK; | |
280 } | |
281 | |
282 class StreamFontCollectionLoader : public IDWriteFontCollectionLoader { | |
283 public: | |
284 // IUnknown methods | |
285 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObjec
t); | |
286 virtual ULONG STDMETHODCALLTYPE AddRef(); | |
287 virtual ULONG STDMETHODCALLTYPE Release(); | |
288 | |
289 // IDWriteFontCollectionLoader methods | |
290 virtual HRESULT STDMETHODCALLTYPE CreateEnumeratorFromKey( | |
291 IDWriteFactory* factory, | |
292 void const* collectionKey, | |
293 UINT32 collectionKeySize, | |
294 IDWriteFontFileEnumerator** fontFileEnumerator); | |
295 | |
296 static HRESULT Create(IDWriteFontFileLoader* fontFileLoader, | |
297 StreamFontCollectionLoader** streamFontCollectionLoade
r) { | |
298 *streamFontCollectionLoader = new StreamFontCollectionLoader(fontFileLoa
der); | |
299 if (NULL == streamFontCollectionLoader) { | |
300 return E_OUTOFMEMORY; | |
301 } | |
302 return S_OK; | |
303 } | |
304 private: | |
305 StreamFontCollectionLoader(IDWriteFontFileLoader* fontFileLoader) | |
306 : fRefCount(1) | |
307 , fFontFileLoader(SkRefComPtr(fontFileLoader)) | |
308 { } | |
309 | |
310 ULONG fRefCount; | |
311 SkTScopedComPtr<IDWriteFontFileLoader> fFontFileLoader; | |
312 }; | |
313 | |
314 HRESULT StreamFontCollectionLoader::QueryInterface(REFIID iid, void** ppvObject)
{ | |
315 if (iid == IID_IUnknown || iid == __uuidof(IDWriteFontCollectionLoader)) { | |
316 *ppvObject = this; | |
317 AddRef(); | |
318 return S_OK; | |
319 } else { | |
320 *ppvObject = NULL; | |
321 return E_NOINTERFACE; | |
322 } | |
323 } | |
324 | |
325 ULONG StreamFontCollectionLoader::AddRef() { | |
326 return InterlockedIncrement(&fRefCount); | |
327 } | |
328 | |
329 ULONG StreamFontCollectionLoader::Release() { | |
330 ULONG newCount = InterlockedDecrement(&fRefCount); | |
331 if (0 == newCount) { | |
332 delete this; | |
333 } | |
334 return newCount; | |
335 } | |
336 | |
337 HRESULT StreamFontCollectionLoader::CreateEnumeratorFromKey( | |
338 IDWriteFactory* factory, | |
339 void const* collectionKey, | |
340 UINT32 collectionKeySize, | |
341 IDWriteFontFileEnumerator** fontFileEnumerator) | |
342 { | |
343 SkTScopedComPtr<StreamFontFileEnumerator> enumerator; | |
344 HR(StreamFontFileEnumerator::Create(factory, fFontFileLoader.get(), &enumera
tor)); | |
345 *fontFileEnumerator = enumerator.release(); | |
346 return S_OK; | |
347 } | |
348 | |
349 /////////////////////////////////////////////////////////////////////////////// | |
350 | |
351 static SkTypeface::Style get_style(IDWriteFont* font) { | |
352 int style = SkTypeface::kNormal; | |
353 DWRITE_FONT_WEIGHT weight = font->GetWeight(); | |
354 if (DWRITE_FONT_WEIGHT_DEMI_BOLD <= weight) { | |
355 style |= SkTypeface::kBold; | |
356 } | |
357 DWRITE_FONT_STYLE angle = font->GetStyle(); | |
358 if (DWRITE_FONT_STYLE_OBLIQUE == angle || DWRITE_FONT_STYLE_ITALIC == angle)
{ | |
359 style |= SkTypeface::kItalic; | |
360 } | |
361 return static_cast<SkTypeface::Style>(style); | |
362 } | |
363 | |
364 class DWriteFontTypeface : public SkTypeface { | |
365 private: | |
366 DWriteFontTypeface(SkTypeface::Style style, SkFontID fontID, | |
367 IDWriteFactory* factory, | |
368 IDWriteFontFace* fontFace, | |
369 IDWriteFont* font, | |
370 IDWriteFontFamily* fontFamily, | |
371 StreamFontFileLoader* fontFileLoader = NULL, | |
372 IDWriteFontCollectionLoader* fontCollectionLoader = NULL) | |
373 : SkTypeface(style, fontID, false) | |
374 , fFactory(SkRefComPtr(factory)) | |
375 , fDWriteFontCollectionLoader(SkSafeRefComPtr(fontCollectionLoader)) | |
376 , fDWriteFontFileLoader(SkSafeRefComPtr(fontFileLoader)) | |
377 , fDWriteFontFamily(SkRefComPtr(fontFamily)) | |
378 , fDWriteFont(SkRefComPtr(font)) | |
379 , fDWriteFontFace(SkRefComPtr(fontFace)) | |
380 { } | |
381 | |
382 public: | |
383 SkTScopedComPtr<IDWriteFactory> fFactory; | |
384 SkTScopedComPtr<IDWriteFontCollectionLoader> fDWriteFontCollectionLoader; | |
385 SkTScopedComPtr<StreamFontFileLoader> fDWriteFontFileLoader; | |
386 SkTScopedComPtr<IDWriteFontFamily> fDWriteFontFamily; | |
387 SkTScopedComPtr<IDWriteFont> fDWriteFont; | |
388 SkTScopedComPtr<IDWriteFontFace> fDWriteFontFace; | |
389 | |
390 static DWriteFontTypeface* Create(IDWriteFactory* factory, | |
391 IDWriteFontFace* fontFace, | |
392 IDWriteFont* font, | |
393 IDWriteFontFamily* fontFamily, | |
394 StreamFontFileLoader* fontFileLoader = NUL
L, | |
395 IDWriteFontCollectionLoader* fontCollectio
nLoader = NULL) { | |
396 SkTypeface::Style style = get_style(font); | |
397 SkFontID fontID = SkTypefaceCache::NewFontID(); | |
398 return SkNEW_ARGS(DWriteFontTypeface, (style, fontID, | |
399 factory, fontFace, font, fontFami
ly, | |
400 fontFileLoader, fontCollectionLoa
der)); | |
401 } | |
402 | |
403 protected: | |
404 virtual void weak_dispose() const SK_OVERRIDE { | |
405 if (fDWriteFontCollectionLoader.get()) { | |
406 HRV(fFactory->UnregisterFontCollectionLoader(fDWriteFontCollectionLo
ader.get())); | |
407 } | |
408 if (fDWriteFontFileLoader.get()) { | |
409 HRV(fFactory->UnregisterFontFileLoader(fDWriteFontFileLoader.get()))
; | |
410 } | |
411 | |
412 //SkTypefaceCache::Remove(this); | |
413 INHERITED::weak_dispose(); | |
414 } | |
415 | |
416 virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE; | |
417 virtual SkScalerContext* onCreateScalerContext(const SkDescriptor*) const SK
_OVERRIDE; | |
418 virtual void onFilterRec(SkScalerContextRec*) const SK_OVERRIDE; | |
419 virtual SkAdvancedTypefaceMetrics* onGetAdvancedTypefaceMetrics( | |
420 SkAdvancedTypefaceMetrics::PerGlyphInfo, | |
421 const uint32_t*, uint32_t) const SK_OVERRIDE; | |
422 virtual void onGetFontDescriptor(SkFontDescriptor*, bool*) const SK_OVERRIDE
; | |
423 virtual int onCharsToGlyphs(const void* chars, Encoding encoding, | |
424 uint16_t glyphs[], int glyphCount) const SK_OVER
RIDE; | |
425 virtual int onCountGlyphs() const SK_OVERRIDE; | |
426 virtual int onGetUPEM() const SK_OVERRIDE; | |
427 virtual SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const SK_
OVERRIDE; | |
428 virtual int onGetTableTags(SkFontTableTag tags[]) const SK_OVERRIDE; | |
429 virtual size_t onGetTableData(SkFontTableTag, size_t offset, | |
430 size_t length, void* data) const SK_OVERRIDE; | |
431 | |
432 private: | |
433 typedef SkTypeface INHERITED; | |
434 }; | |
435 | |
436 class SkScalerContext_DW : public SkScalerContext { | |
437 public: | |
438 SkScalerContext_DW(DWriteFontTypeface*, const SkDescriptor* desc); | |
439 virtual ~SkScalerContext_DW(); | |
440 | |
441 protected: | |
442 virtual unsigned generateGlyphCount() SK_OVERRIDE; | |
443 virtual uint16_t generateCharToGlyph(SkUnichar uni) SK_OVERRIDE; | |
444 virtual void generateAdvance(SkGlyph* glyph) SK_OVERRIDE; | |
445 virtual void generateMetrics(SkGlyph* glyph) SK_OVERRIDE; | |
446 virtual void generateImage(const SkGlyph& glyph) SK_OVERRIDE; | |
447 virtual void generatePath(const SkGlyph& glyph, SkPath* path) SK_OVERRIDE; | |
448 virtual void generateFontMetrics(SkPaint::FontMetrics* mX, | |
449 SkPaint::FontMetrics* mY) SK_OVERRIDE; | |
450 | |
451 private: | |
452 const void* drawDWMask(const SkGlyph& glyph); | |
453 | |
454 SkTDArray<uint8_t> fBits; | |
455 /** The total matrix without the text height scale. */ | |
456 SkMatrix fSkXform; | |
457 /** The total matrix without the text height scale. */ | |
458 DWRITE_MATRIX fXform; | |
459 /** The non-rotational part of total matrix without the text height scale. | |
460 * This is used to find the magnitude of gdi compatible advances. | |
461 */ | |
462 DWRITE_MATRIX fGsA; | |
463 /** The inverse of the rotational part of the total matrix. | |
464 * This is used to find the direction of gdi compatible advances. | |
465 */ | |
466 SkMatrix fG_inv; | |
467 /** The text size to render with. */ | |
468 SkScalar fTextSizeRender; | |
469 /** The text size to measure with. */ | |
470 SkScalar fTextSizeMeasure; | |
471 SkAutoTUnref<DWriteFontTypeface> fTypeface; | |
472 int fGlyphCount; | |
473 DWRITE_RENDERING_MODE fRenderingMode; | |
474 DWRITE_TEXTURE_TYPE fTextureType; | |
475 DWRITE_MEASURING_MODE fMeasuringMode; | |
476 }; | |
477 | |
478 static bool are_same(IUnknown* a, IUnknown* b) { | |
479 SkTScopedComPtr<IUnknown> iunkA; | |
480 if (FAILED(a->QueryInterface(&iunkA))) { | |
481 return false; | |
482 } | |
483 | |
484 SkTScopedComPtr<IUnknown> iunkB; | |
485 if (FAILED(b->QueryInterface(&iunkB))) { | |
486 return false; | |
487 } | |
488 | |
489 return iunkA.get() == iunkB.get(); | |
490 } | |
491 static bool FindByDWriteFont(SkTypeface* face, SkTypeface::Style requestedStyle,
void* ctx) { | |
492 //Check to see if the two fonts are identical. | |
493 DWriteFontTypeface* dwFace = reinterpret_cast<DWriteFontTypeface*>(face); | |
494 IDWriteFont* dwFont = reinterpret_cast<IDWriteFont*>(ctx); | |
495 if (are_same(dwFace->fDWriteFont.get(), dwFont)) { | |
496 return true; | |
497 } | |
498 | |
499 //Check if the two fonts share the same loader and have the same key. | |
500 SkTScopedComPtr<IDWriteFontFace> dwFaceFontFace; | |
501 SkTScopedComPtr<IDWriteFontFace> dwFontFace; | |
502 HRB(dwFace->fDWriteFont->CreateFontFace(&dwFaceFontFace)); | |
503 HRB(dwFont->CreateFontFace(&dwFontFace)); | |
504 if (are_same(dwFaceFontFace.get(), dwFontFace.get())) { | |
505 return true; | |
506 } | |
507 | |
508 UINT32 dwFaceNumFiles; | |
509 UINT32 dwNumFiles; | |
510 HRB(dwFaceFontFace->GetFiles(&dwFaceNumFiles, NULL)); | |
511 HRB(dwFontFace->GetFiles(&dwNumFiles, NULL)); | |
512 if (dwFaceNumFiles != dwNumFiles) { | |
513 return false; | |
514 } | |
515 | |
516 SkTScopedComPtr<IDWriteFontFile> dwFaceFontFile; | |
517 SkTScopedComPtr<IDWriteFontFile> dwFontFile; | |
518 HRB(dwFaceFontFace->GetFiles(&dwFaceNumFiles, &dwFaceFontFile)); | |
519 HRB(dwFontFace->GetFiles(&dwNumFiles, &dwFontFile)); | |
520 | |
521 //for (each file) { //we currently only admit fonts from one file. | |
522 SkTScopedComPtr<IDWriteFontFileLoader> dwFaceFontFileLoader; | |
523 SkTScopedComPtr<IDWriteFontFileLoader> dwFontFileLoader; | |
524 HRB(dwFaceFontFile->GetLoader(&dwFaceFontFileLoader)); | |
525 HRB(dwFontFile->GetLoader(&dwFontFileLoader)); | |
526 if (!are_same(dwFaceFontFileLoader.get(), dwFontFileLoader.get())) { | |
527 return false; | |
528 } | |
529 //} | |
530 | |
531 const void* dwFaceFontRefKey; | |
532 UINT32 dwFaceFontRefKeySize; | |
533 const void* dwFontRefKey; | |
534 UINT32 dwFontRefKeySize; | |
535 HRB(dwFaceFontFile->GetReferenceKey(&dwFaceFontRefKey, &dwFaceFontRefKeySize
)); | |
536 HRB(dwFontFile->GetReferenceKey(&dwFontRefKey, &dwFontRefKeySize)); | |
537 if (dwFaceFontRefKeySize != dwFontRefKeySize) { | |
538 return false; | |
539 } | |
540 if (0 != memcmp(dwFaceFontRefKey, dwFontRefKey, dwFontRefKeySize)) { | |
541 return false; | |
542 } | |
543 | |
544 //TODO: better means than comparing name strings? | |
545 //NOTE: .tfc and fake bold/italic will end up here. | |
546 SkTScopedComPtr<IDWriteFontFamily> dwFaceFontFamily; | |
547 SkTScopedComPtr<IDWriteFontFamily> dwFontFamily; | |
548 HRB(dwFace->fDWriteFont->GetFontFamily(&dwFaceFontFamily)); | |
549 HRB(dwFont->GetFontFamily(&dwFontFamily)); | |
550 | |
551 SkTScopedComPtr<IDWriteLocalizedStrings> dwFaceFontFamilyNames; | |
552 SkTScopedComPtr<IDWriteLocalizedStrings> dwFaceFontNames; | |
553 HRB(dwFaceFontFamily->GetFamilyNames(&dwFaceFontFamilyNames)); | |
554 HRB(dwFace->fDWriteFont->GetFaceNames(&dwFaceFontNames)); | |
555 | |
556 SkTScopedComPtr<IDWriteLocalizedStrings> dwFontFamilyNames; | |
557 SkTScopedComPtr<IDWriteLocalizedStrings> dwFontNames; | |
558 HRB(dwFontFamily->GetFamilyNames(&dwFontFamilyNames)); | |
559 HRB(dwFont->GetFaceNames(&dwFontNames)); | |
560 | |
561 UINT32 dwFaceFontFamilyNameLength; | |
562 UINT32 dwFaceFontNameLength; | |
563 HRB(dwFaceFontFamilyNames->GetStringLength(0, &dwFaceFontFamilyNameLength)); | |
564 HRB(dwFaceFontNames->GetStringLength(0, &dwFaceFontNameLength)); | |
565 | |
566 UINT32 dwFontFamilyNameLength; | |
567 UINT32 dwFontNameLength; | |
568 HRB(dwFontFamilyNames->GetStringLength(0, &dwFontFamilyNameLength)); | |
569 HRB(dwFontNames->GetStringLength(0, &dwFontNameLength)); | |
570 | |
571 if (dwFaceFontFamilyNameLength != dwFontFamilyNameLength || | |
572 dwFaceFontNameLength != dwFontNameLength) | |
573 { | |
574 return false; | |
575 } | |
576 | |
577 SkSMallocWCHAR dwFaceFontFamilyNameChar(dwFaceFontFamilyNameLength+1); | |
578 SkSMallocWCHAR dwFaceFontNameChar(dwFaceFontNameLength+1); | |
579 HRB(dwFaceFontFamilyNames->GetString(0, dwFaceFontFamilyNameChar.get(), dwFa
ceFontFamilyNameLength+1)); | |
580 HRB(dwFaceFontNames->GetString(0, dwFaceFontNameChar.get(), dwFaceFontNameLe
ngth+1)); | |
581 | |
582 SkSMallocWCHAR dwFontFamilyNameChar(dwFontFamilyNameLength+1); | |
583 SkSMallocWCHAR dwFontNameChar(dwFontNameLength+1); | |
584 HRB(dwFontFamilyNames->GetString(0, dwFontFamilyNameChar.get(), dwFontFamily
NameLength+1)); | |
585 HRB(dwFontNames->GetString(0, dwFontNameChar.get(), dwFontNameLength+1)); | |
586 | |
587 return wcscmp(dwFaceFontFamilyNameChar.get(), dwFontFamilyNameChar.get()) ==
0 && | |
588 wcscmp(dwFaceFontNameChar.get(), dwFontNameChar.get()) == 0; | |
589 } | |
590 | |
591 class AutoDWriteTable { | |
592 public: | |
593 AutoDWriteTable(IDWriteFontFace* fontFace, UINT32 beTag) : fFontFace(fontFac
e), fExists(FALSE) { | |
594 // Any errors are ignored, user must check fExists anyway. | |
595 fontFace->TryGetFontTable(beTag, | |
596 reinterpret_cast<const void **>(&fData), &fSize, &fLock, &fExists); | |
597 } | |
598 ~AutoDWriteTable() { | |
599 if (fExists) { | |
600 fFontFace->ReleaseFontTable(fLock); | |
601 } | |
602 } | |
603 | |
604 const uint8_t* fData; | |
605 UINT32 fSize; | |
606 BOOL fExists; | |
607 private: | |
608 // Borrowed reference, the user must ensure the fontFace stays alive. | |
609 IDWriteFontFace* fFontFace; | |
610 void* fLock; | |
611 }; | |
612 template<typename T> class AutoTDWriteTable : public AutoDWriteTable { | |
613 public: | |
614 static const UINT32 tag = DWRITE_MAKE_OPENTYPE_TAG(T::TAG0, T::TAG1, T::TAG2
, T::TAG3); | |
615 AutoTDWriteTable(IDWriteFontFace* fontFace) : AutoDWriteTable(fontFace, tag)
{ } | |
616 | |
617 const T* get() const { return reinterpret_cast<const T*>(fData); } | |
618 const T* operator->() const { return reinterpret_cast<const T*>(fData); } | |
619 }; | |
620 | |
621 static bool hasBitmapStrike(DWriteFontTypeface* typeface, int size) { | 33 static bool hasBitmapStrike(DWriteFontTypeface* typeface, int size) { |
622 { | 34 { |
623 AutoTDWriteTable<SkOTTableEmbeddedBitmapLocation> eblc(typeface->fDWrite
FontFace.get()); | 35 AutoTDWriteTable<SkOTTableEmbeddedBitmapLocation> eblc(typeface->fDWrite
FontFace.get()); |
624 if (!eblc.fExists) { | 36 if (!eblc.fExists) { |
625 return false; | 37 return false; |
626 } | 38 } |
627 if (eblc.fSize < sizeof(SkOTTableEmbeddedBitmapLocation)) { | 39 if (eblc.fSize < sizeof(SkOTTableEmbeddedBitmapLocation)) { |
628 return false; | 40 return false; |
629 } | 41 } |
630 if (eblc->version != SkOTTableEmbeddedBitmapLocation::version_initial) { | 42 if (eblc->version != SkOTTableEmbeddedBitmapLocation::version_initial) { |
(...skipping 571 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1202 NULL, //advances | 614 NULL, //advances |
1203 NULL, //offsets | 615 NULL, //offsets |
1204 1, //num glyphs | 616 1, //num glyphs |
1205 FALSE, //sideways | 617 FALSE, //sideways |
1206 FALSE, //rtl | 618 FALSE, //rtl |
1207 geometryToPath.get()), | 619 geometryToPath.get()), |
1208 "Could not create glyph outline."); | 620 "Could not create glyph outline."); |
1209 | 621 |
1210 path->transform(fSkXform); | 622 path->transform(fSkXform); |
1211 } | 623 } |
1212 | |
1213 void DWriteFontTypeface::onGetFontDescriptor(SkFontDescriptor* desc, | |
1214 bool* isLocalStream) const { | |
1215 // Get the family name. | |
1216 SkTScopedComPtr<IDWriteLocalizedStrings> dwFamilyNames; | |
1217 HRV(fDWriteFontFamily->GetFamilyNames(&dwFamilyNames)); | |
1218 | |
1219 UINT32 dwFamilyNamesLength; | |
1220 HRV(dwFamilyNames->GetStringLength(0, &dwFamilyNamesLength)); | |
1221 | |
1222 SkSMallocWCHAR dwFamilyNameChar(dwFamilyNamesLength+1); | |
1223 HRV(dwFamilyNames->GetString(0, dwFamilyNameChar.get(), dwFamilyNamesLength+
1)); | |
1224 | |
1225 SkString utf8FamilyName; | |
1226 HRV(sk_wchar_to_skstring(dwFamilyNameChar.get(), &utf8FamilyName)); | |
1227 | |
1228 desc->setFamilyName(utf8FamilyName.c_str()); | |
1229 *isLocalStream = SkToBool(fDWriteFontFileLoader.get()); | |
1230 } | |
1231 | |
1232 static SkUnichar next_utf8(const void** chars) { | |
1233 return SkUTF8_NextUnichar((const char**)chars); | |
1234 } | |
1235 | |
1236 static SkUnichar next_utf16(const void** chars) { | |
1237 return SkUTF16_NextUnichar((const uint16_t**)chars); | |
1238 } | |
1239 | |
1240 static SkUnichar next_utf32(const void** chars) { | |
1241 const SkUnichar** uniChars = (const SkUnichar**)chars; | |
1242 SkUnichar uni = **uniChars; | |
1243 *uniChars += 1; | |
1244 return uni; | |
1245 } | |
1246 | |
1247 typedef SkUnichar (*EncodingProc)(const void**); | |
1248 | |
1249 static EncodingProc find_encoding_proc(SkTypeface::Encoding enc) { | |
1250 static const EncodingProc gProcs[] = { | |
1251 next_utf8, next_utf16, next_utf32 | |
1252 }; | |
1253 SkASSERT((size_t)enc < SK_ARRAY_COUNT(gProcs)); | |
1254 return gProcs[enc]; | |
1255 } | |
1256 | |
1257 int DWriteFontTypeface::onCharsToGlyphs(const void* chars, Encoding encoding, | |
1258 uint16_t glyphs[], int glyphCount) const | |
1259 { | |
1260 if (NULL == glyphs) { | |
1261 EncodingProc next_ucs4_proc = find_encoding_proc(encoding); | |
1262 for (int i = 0; i < glyphCount; ++i) { | |
1263 const SkUnichar c = next_ucs4_proc(&chars); | |
1264 BOOL exists; | |
1265 fDWriteFont->HasCharacter(c, &exists); | |
1266 if (!exists) { | |
1267 return i; | |
1268 } | |
1269 } | |
1270 return glyphCount; | |
1271 } | |
1272 | |
1273 switch (encoding) { | |
1274 case SkTypeface::kUTF8_Encoding: | |
1275 case SkTypeface::kUTF16_Encoding: { | |
1276 static const int scratchCount = 256; | |
1277 UINT32 scratch[scratchCount]; | |
1278 EncodingProc next_ucs4_proc = find_encoding_proc(encoding); | |
1279 for (int baseGlyph = 0; baseGlyph < glyphCount; baseGlyph += scratchCoun
t) { | |
1280 int glyphsLeft = glyphCount - baseGlyph; | |
1281 int limit = SkTMin(glyphsLeft, scratchCount); | |
1282 for (int i = 0; i < limit; ++i) { | |
1283 scratch[i] = next_ucs4_proc(&chars); | |
1284 } | |
1285 fDWriteFontFace->GetGlyphIndices(scratch, limit, &glyphs[baseGlyph])
; | |
1286 } | |
1287 break; | |
1288 } | |
1289 case SkTypeface::kUTF32_Encoding: { | |
1290 const UINT32* utf32 = reinterpret_cast<const UINT32*>(chars); | |
1291 fDWriteFontFace->GetGlyphIndices(utf32, glyphCount, glyphs); | |
1292 break; | |
1293 } | |
1294 default: | |
1295 SK_CRASH(); | |
1296 } | |
1297 | |
1298 for (int i = 0; i < glyphCount; ++i) { | |
1299 if (0 == glyphs[i]) { | |
1300 return i; | |
1301 } | |
1302 } | |
1303 return glyphCount; | |
1304 } | |
1305 | |
1306 int DWriteFontTypeface::onCountGlyphs() const { | |
1307 return fDWriteFontFace->GetGlyphCount(); | |
1308 } | |
1309 | |
1310 int DWriteFontTypeface::onGetUPEM() const { | |
1311 DWRITE_FONT_METRICS metrics; | |
1312 fDWriteFontFace->GetMetrics(&metrics); | |
1313 return metrics.designUnitsPerEm; | |
1314 } | |
1315 | |
1316 class LocalizedStrings_IDWriteLocalizedStrings : public SkTypeface::LocalizedStr
ings { | |
1317 public: | |
1318 /** Takes ownership of the IDWriteLocalizedStrings. */ | |
1319 explicit LocalizedStrings_IDWriteLocalizedStrings(IDWriteLocalizedStrings* s
trings) | |
1320 : fIndex(0), fStrings(strings) | |
1321 { } | |
1322 | |
1323 virtual bool next(SkTypeface::LocalizedString* localizedString) SK_OVERRIDE
{ | |
1324 if (fIndex >= fStrings->GetCount()) { | |
1325 return false; | |
1326 } | |
1327 | |
1328 // String | |
1329 UINT32 stringLength; | |
1330 HRBM(fStrings->GetStringLength(fIndex, &stringLength), "Could not get st
ring length."); | |
1331 stringLength += 1; | |
1332 | |
1333 SkSMallocWCHAR wString(stringLength); | |
1334 HRBM(fStrings->GetString(fIndex, wString.get(), stringLength), "Could no
t get string."); | |
1335 | |
1336 HRB(sk_wchar_to_skstring(wString.get(), &localizedString->fString)); | |
1337 | |
1338 // Locale | |
1339 UINT32 localeLength; | |
1340 HRBM(fStrings->GetLocaleNameLength(fIndex, &localeLength), "Could not ge
t locale length."); | |
1341 localeLength += 1; | |
1342 | |
1343 SkSMallocWCHAR wLocale(localeLength); | |
1344 HRBM(fStrings->GetLocaleName(fIndex, wLocale.get(), localeLength), "Coul
d not get locale."); | |
1345 | |
1346 HRB(sk_wchar_to_skstring(wLocale.get(), &localizedString->fLanguage)); | |
1347 | |
1348 ++fIndex; | |
1349 return true; | |
1350 } | |
1351 | |
1352 private: | |
1353 UINT32 fIndex; | |
1354 SkTScopedComPtr<IDWriteLocalizedStrings> fStrings; | |
1355 }; | |
1356 | |
1357 SkTypeface::LocalizedStrings* DWriteFontTypeface::onCreateFamilyNameIterator() c
onst { | |
1358 SkTScopedComPtr<IDWriteLocalizedStrings> familyNames; | |
1359 HRNM(fDWriteFontFamily->GetFamilyNames(&familyNames), "Could not obtain fami
ly names."); | |
1360 | |
1361 return new LocalizedStrings_IDWriteLocalizedStrings(familyNames.release()); | |
1362 } | |
1363 | |
1364 int DWriteFontTypeface::onGetTableTags(SkFontTableTag tags[]) const { | |
1365 DWRITE_FONT_FACE_TYPE type = fDWriteFontFace->GetType(); | |
1366 if (type != DWRITE_FONT_FACE_TYPE_CFF && | |
1367 type != DWRITE_FONT_FACE_TYPE_TRUETYPE && | |
1368 type != DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION) | |
1369 { | |
1370 return 0; | |
1371 } | |
1372 | |
1373 int ttcIndex; | |
1374 SkAutoTUnref<SkStream> stream(this->openStream(&ttcIndex)); | |
1375 return stream.get() ? SkFontStream::GetTableTags(stream, ttcIndex, tags) : 0
; | |
1376 } | |
1377 | |
1378 size_t DWriteFontTypeface::onGetTableData(SkFontTableTag tag, size_t offset, | |
1379 size_t length, void* data) const | |
1380 { | |
1381 AutoDWriteTable table(fDWriteFontFace.get(), SkEndian_SwapBE32(tag)); | |
1382 if (!table.fExists) { | |
1383 return 0; | |
1384 } | |
1385 | |
1386 if (offset > table.fSize) { | |
1387 return 0; | |
1388 } | |
1389 size_t size = SkTMin(length, table.fSize - offset); | |
1390 if (NULL != data) { | |
1391 memcpy(data, table.fData + offset, size); | |
1392 } | |
1393 | |
1394 return size; | |
1395 } | |
1396 | |
1397 template <typename T> class SkAutoIDWriteUnregister { | |
1398 public: | |
1399 SkAutoIDWriteUnregister(IDWriteFactory* factory, T* unregister) | |
1400 : fFactory(factory), fUnregister(unregister) | |
1401 { } | |
1402 | |
1403 ~SkAutoIDWriteUnregister() { | |
1404 if (fUnregister) { | |
1405 unregister(fFactory, fUnregister); | |
1406 } | |
1407 } | |
1408 | |
1409 T* detatch() { | |
1410 T* old = fUnregister; | |
1411 fUnregister = NULL; | |
1412 return old; | |
1413 } | |
1414 | |
1415 private: | |
1416 HRESULT unregister(IDWriteFactory* factory, IDWriteFontFileLoader* unregiste
r) { | |
1417 return factory->UnregisterFontFileLoader(unregister); | |
1418 } | |
1419 | |
1420 HRESULT unregister(IDWriteFactory* factory, IDWriteFontCollectionLoader* unr
egister) { | |
1421 return factory->UnregisterFontCollectionLoader(unregister); | |
1422 } | |
1423 | |
1424 IDWriteFactory* fFactory; | |
1425 T* fUnregister; | |
1426 }; | |
1427 | |
1428 SkStream* DWriteFontTypeface::onOpenStream(int* ttcIndex) const { | |
1429 *ttcIndex = fDWriteFontFace->GetIndex(); | |
1430 | |
1431 UINT32 numFiles; | |
1432 HRNM(fDWriteFontFace->GetFiles(&numFiles, NULL), | |
1433 "Could not get number of font files."); | |
1434 if (numFiles != 1) { | |
1435 return NULL; | |
1436 } | |
1437 | |
1438 SkTScopedComPtr<IDWriteFontFile> fontFile; | |
1439 HRNM(fDWriteFontFace->GetFiles(&numFiles, &fontFile), "Could not get font fi
les."); | |
1440 | |
1441 const void* fontFileKey; | |
1442 UINT32 fontFileKeySize; | |
1443 HRNM(fontFile->GetReferenceKey(&fontFileKey, &fontFileKeySize), | |
1444 "Could not get font file reference key."); | |
1445 | |
1446 SkTScopedComPtr<IDWriteFontFileLoader> fontFileLoader; | |
1447 HRNM(fontFile->GetLoader(&fontFileLoader), "Could not get font file loader."
); | |
1448 | |
1449 SkTScopedComPtr<IDWriteFontFileStream> fontFileStream; | |
1450 HRNM(fontFileLoader->CreateStreamFromKey(fontFileKey, fontFileKeySize, | |
1451 &fontFileStream), | |
1452 "Could not create font file stream."); | |
1453 | |
1454 return SkNEW_ARGS(SkDWriteFontFileStream, (fontFileStream.get())); | |
1455 } | |
1456 | |
1457 SkScalerContext* DWriteFontTypeface::onCreateScalerContext(const SkDescriptor* d
esc) const { | |
1458 return SkNEW_ARGS(SkScalerContext_DW, (const_cast<DWriteFontTypeface*>(this)
, desc)); | |
1459 } | |
1460 | |
1461 void DWriteFontTypeface::onFilterRec(SkScalerContext::Rec* rec) const { | |
1462 if (rec->fFlags & SkScalerContext::kLCD_BGROrder_Flag || | |
1463 rec->fFlags & SkScalerContext::kLCD_Vertical_Flag) | |
1464 { | |
1465 rec->fMaskFormat = SkMask::kA8_Format; | |
1466 } | |
1467 | |
1468 unsigned flagsWeDontSupport = SkScalerContext::kDevKernText_Flag | | |
1469 SkScalerContext::kForceAutohinting_Flag | | |
1470 SkScalerContext::kEmbolden_Flag | | |
1471 SkScalerContext::kLCD_BGROrder_Flag | | |
1472 SkScalerContext::kLCD_Vertical_Flag; | |
1473 rec->fFlags &= ~flagsWeDontSupport; | |
1474 | |
1475 SkPaint::Hinting h = rec->getHinting(); | |
1476 // DirectWrite does not provide for hinting hints. | |
1477 h = SkPaint::kSlight_Hinting; | |
1478 rec->setHinting(h); | |
1479 | |
1480 #if SK_FONT_HOST_USE_SYSTEM_SETTINGS | |
1481 IDWriteFactory* factory = get_dwrite_factory(); | |
1482 if (factory != NULL) { | |
1483 SkTScopedComPtr<IDWriteRenderingParams> defaultRenderingParams; | |
1484 if (SUCCEEDED(factory->CreateRenderingParams(&defaultRenderingParams)))
{ | |
1485 float gamma = defaultRenderingParams->GetGamma(); | |
1486 rec->setDeviceGamma(gamma); | |
1487 rec->setPaintGamma(gamma); | |
1488 | |
1489 rec->setContrast(defaultRenderingParams->GetEnhancedContrast()); | |
1490 } | |
1491 } | |
1492 #endif | |
1493 } | |
1494 | |
1495 /////////////////////////////////////////////////////////////////////////////// | |
1496 //PDF Support | |
1497 | |
1498 using namespace skia_advanced_typeface_metrics_utils; | |
1499 | |
1500 // Construct Glyph to Unicode table. | |
1501 // Unicode code points that require conjugate pairs in utf16 are not | |
1502 // supported. | |
1503 // TODO(arthurhsu): Add support for conjugate pairs. It looks like that may | |
1504 // require parsing the TTF cmap table (platform 4, encoding 12) directly instead | |
1505 // of calling GetFontUnicodeRange(). | |
1506 // TODO(bungeman): This never does what anyone wants. | |
1507 // What is really wanted is the text to glyphs mapping | |
1508 static void populate_glyph_to_unicode(IDWriteFontFace* fontFace, | |
1509 const unsigned glyphCount, | |
1510 SkTDArray<SkUnichar>* glyphToUnicode) { | |
1511 HRESULT hr = S_OK; | |
1512 | |
1513 //Do this like free type instead | |
1514 UINT32 count = 0; | |
1515 for (UINT32 c = 0; c < 0x10FFFF; ++c) { | |
1516 UINT16 glyph; | |
1517 hr = fontFace->GetGlyphIndices(&c, 1, &glyph); | |
1518 if (glyph > 0) { | |
1519 ++count; | |
1520 } | |
1521 } | |
1522 | |
1523 SkAutoTArray<UINT32> chars(count); | |
1524 count = 0; | |
1525 for (UINT32 c = 0; c < 0x10FFFF; ++c) { | |
1526 UINT16 glyph; | |
1527 hr = fontFace->GetGlyphIndices(&c, 1, &glyph); | |
1528 if (glyph > 0) { | |
1529 chars[count] = c; | |
1530 ++count; | |
1531 } | |
1532 } | |
1533 | |
1534 SkAutoTArray<UINT16> glyph(count); | |
1535 fontFace->GetGlyphIndices(chars.get(), count, glyph.get()); | |
1536 | |
1537 USHORT maxGlyph = 0; | |
1538 for (USHORT j = 0; j < count; ++j) { | |
1539 if (glyph[j] > maxGlyph) maxGlyph = glyph[j]; | |
1540 } | |
1541 | |
1542 glyphToUnicode->setCount(maxGlyph+1); | |
1543 for (USHORT j = 0; j < maxGlyph+1u; ++j) { | |
1544 (*glyphToUnicode)[j] = 0; | |
1545 } | |
1546 | |
1547 //'invert' | |
1548 for (USHORT j = 0; j < count; ++j) { | |
1549 if (glyph[j] < glyphCount && (*glyphToUnicode)[glyph[j]] == 0) { | |
1550 (*glyphToUnicode)[glyph[j]] = chars[j]; | |
1551 } | |
1552 } | |
1553 } | |
1554 | |
1555 static bool getWidthAdvance(IDWriteFontFace* fontFace, int gId, int16_t* advance
) { | |
1556 SkASSERT(advance); | |
1557 | |
1558 UINT16 glyphId = gId; | |
1559 DWRITE_GLYPH_METRICS gm; | |
1560 HRESULT hr = fontFace->GetDesignGlyphMetrics(&glyphId, 1, &gm); | |
1561 | |
1562 if (FAILED(hr)) { | |
1563 *advance = 0; | |
1564 return false; | |
1565 } | |
1566 | |
1567 *advance = gm.advanceWidth; | |
1568 return true; | |
1569 } | |
1570 | |
1571 SkAdvancedTypefaceMetrics* DWriteFontTypeface::onGetAdvancedTypefaceMetrics( | |
1572 SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo, | |
1573 const uint32_t* glyphIDs, | |
1574 uint32_t glyphIDsCount) const { | |
1575 | |
1576 SkAdvancedTypefaceMetrics* info = NULL; | |
1577 | |
1578 HRESULT hr = S_OK; | |
1579 | |
1580 const unsigned glyphCount = fDWriteFontFace->GetGlyphCount(); | |
1581 | |
1582 DWRITE_FONT_METRICS dwfm; | |
1583 fDWriteFontFace->GetMetrics(&dwfm); | |
1584 | |
1585 info = new SkAdvancedTypefaceMetrics; | |
1586 info->fEmSize = dwfm.designUnitsPerEm; | |
1587 info->fMultiMaster = false; | |
1588 info->fLastGlyphID = SkToU16(glyphCount - 1); | |
1589 info->fStyle = 0; | |
1590 | |
1591 | |
1592 SkTScopedComPtr<IDWriteLocalizedStrings> familyNames; | |
1593 SkTScopedComPtr<IDWriteLocalizedStrings> faceNames; | |
1594 hr = fDWriteFontFamily->GetFamilyNames(&familyNames); | |
1595 hr = fDWriteFont->GetFaceNames(&faceNames); | |
1596 | |
1597 UINT32 familyNameLength; | |
1598 hr = familyNames->GetStringLength(0, &familyNameLength); | |
1599 | |
1600 UINT32 faceNameLength; | |
1601 hr = faceNames->GetStringLength(0, &faceNameLength); | |
1602 | |
1603 UINT32 size = familyNameLength+1+faceNameLength+1; | |
1604 SkSMallocWCHAR wFamilyName(size); | |
1605 hr = familyNames->GetString(0, wFamilyName.get(), size); | |
1606 wFamilyName[familyNameLength] = L' '; | |
1607 hr = faceNames->GetString(0, &wFamilyName[familyNameLength+1], size - faceNa
meLength + 1); | |
1608 | |
1609 hr = sk_wchar_to_skstring(wFamilyName.get(), &info->fFontName); | |
1610 | |
1611 if (perGlyphInfo & SkAdvancedTypefaceMetrics::kToUnicode_PerGlyphInfo) { | |
1612 populate_glyph_to_unicode(fDWriteFontFace.get(), glyphCount, &(info->fGl
yphToUnicode)); | |
1613 } | |
1614 | |
1615 DWRITE_FONT_FACE_TYPE fontType = fDWriteFontFace->GetType(); | |
1616 if (fontType == DWRITE_FONT_FACE_TYPE_TRUETYPE || | |
1617 fontType == DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION) { | |
1618 info->fType = SkAdvancedTypefaceMetrics::kTrueType_Font; | |
1619 } else { | |
1620 info->fType = SkAdvancedTypefaceMetrics::kOther_Font; | |
1621 info->fItalicAngle = 0; | |
1622 info->fAscent = dwfm.ascent;; | |
1623 info->fDescent = dwfm.descent; | |
1624 info->fStemV = 0; | |
1625 info->fCapHeight = dwfm.capHeight; | |
1626 info->fBBox = SkIRect::MakeEmpty(); | |
1627 return info; | |
1628 } | |
1629 | |
1630 AutoTDWriteTable<SkOTTableHead> headTable(fDWriteFontFace.get()); | |
1631 AutoTDWriteTable<SkOTTablePostScript> postTable(fDWriteFontFace.get()); | |
1632 AutoTDWriteTable<SkOTTableHorizontalHeader> hheaTable(fDWriteFontFace.get())
; | |
1633 AutoTDWriteTable<SkOTTableOS2> os2Table(fDWriteFontFace.get()); | |
1634 if (!headTable.fExists || !postTable.fExists || !hheaTable.fExists || !os2Ta
ble.fExists) { | |
1635 info->fItalicAngle = 0; | |
1636 info->fAscent = dwfm.ascent;; | |
1637 info->fDescent = dwfm.descent; | |
1638 info->fStemV = 0; | |
1639 info->fCapHeight = dwfm.capHeight; | |
1640 info->fBBox = SkIRect::MakeEmpty(); | |
1641 return info; | |
1642 } | |
1643 | |
1644 //There exist CJK fonts which set the IsFixedPitch and Monospace bits, | |
1645 //but have full width, latin half-width, and half-width kana. | |
1646 bool fixedWidth = (postTable->isFixedPitch && | |
1647 (1 == SkEndian_SwapBE16(hheaTable->numberOfHMetrics))); | |
1648 //Monospace | |
1649 if (fixedWidth) { | |
1650 info->fStyle |= SkAdvancedTypefaceMetrics::kFixedPitch_Style; | |
1651 } | |
1652 //Italic | |
1653 if (os2Table->version.v0.fsSelection.field.Italic) { | |
1654 info->fStyle |= SkAdvancedTypefaceMetrics::kItalic_Style; | |
1655 } | |
1656 //Script | |
1657 if (SkPanose::FamilyType::Script == os2Table->version.v0.panose.bFamilyType.
value) { | |
1658 info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style; | |
1659 //Serif | |
1660 } else if (SkPanose::FamilyType::TextAndDisplay == os2Table->version.v0.pano
se.bFamilyType.value && | |
1661 SkPanose::Data::TextAndDisplay::SerifStyle::Triangle <= os2Table-
>version.v0.panose.data.textAndDisplay.bSerifStyle.value && | |
1662 SkPanose::Data::TextAndDisplay::SerifStyle::NoFit != os2Table->ve
rsion.v0.panose.data.textAndDisplay.bSerifStyle.value) { | |
1663 info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style; | |
1664 } | |
1665 | |
1666 info->fItalicAngle = SkEndian_SwapBE32(postTable->italicAngle) >> 16; | |
1667 | |
1668 info->fAscent = SkToS16(dwfm.ascent); | |
1669 info->fDescent = SkToS16(dwfm.descent); | |
1670 info->fCapHeight = SkToS16(dwfm.capHeight); | |
1671 | |
1672 info->fBBox = SkIRect::MakeLTRB((int32_t)SkEndian_SwapBE16((uint16_t)headTab
le->xMin), | |
1673 (int32_t)SkEndian_SwapBE16((uint16_t)headTab
le->yMax), | |
1674 (int32_t)SkEndian_SwapBE16((uint16_t)headTab
le->xMax), | |
1675 (int32_t)SkEndian_SwapBE16((uint16_t)headTab
le->yMin)); | |
1676 | |
1677 //TODO: is this even desired? It seems PDF only wants this value for Type1 | |
1678 //fonts, and we only get here for TrueType fonts. | |
1679 info->fStemV = 0; | |
1680 /* | |
1681 // Figure out a good guess for StemV - Min width of i, I, !, 1. | |
1682 // This probably isn't very good with an italic font. | |
1683 int16_t min_width = SHRT_MAX; | |
1684 info->fStemV = 0; | |
1685 char stem_chars[] = {'i', 'I', '!', '1'}; | |
1686 for (size_t i = 0; i < SK_ARRAY_COUNT(stem_chars); i++) { | |
1687 ABC abcWidths; | |
1688 if (GetCharABCWidths(hdc, stem_chars[i], stem_chars[i], &abcWidths)) { | |
1689 int16_t width = abcWidths.abcB; | |
1690 if (width > 0 && width < min_width) { | |
1691 min_width = width; | |
1692 info->fStemV = min_width; | |
1693 } | |
1694 } | |
1695 } | |
1696 */ | |
1697 | |
1698 // If Restricted, the font may not be embedded in a document. | |
1699 // If not Restricted, the font can be embedded. | |
1700 // If PreviewPrint, the embedding is read-only. | |
1701 if (os2Table->version.v0.fsType.field.Restricted) { | |
1702 info->fType = SkAdvancedTypefaceMetrics::kNotEmbeddable_Font; | |
1703 } else if (perGlyphInfo & SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo)
{ | |
1704 if (fixedWidth) { | |
1705 appendRange(&info->fGlyphWidths, 0); | |
1706 int16_t advance; | |
1707 getWidthAdvance(fDWriteFontFace.get(), 1, &advance); | |
1708 info->fGlyphWidths->fAdvance.append(1, &advance); | |
1709 finishRange(info->fGlyphWidths.get(), 0, | |
1710 SkAdvancedTypefaceMetrics::WidthRange::kDefault); | |
1711 } else { | |
1712 info->fGlyphWidths.reset( | |
1713 getAdvanceData(fDWriteFontFace.get(), | |
1714 glyphCount, | |
1715 glyphIDs, | |
1716 glyphIDsCount, | |
1717 getWidthAdvance)); | |
1718 } | |
1719 } | |
1720 | |
1721 return info; | |
1722 } | |
1723 | |
1724 /////////////////////////////////////////////////////////////////////////////// | |
1725 | |
1726 SkTypeface* SkFontMgr_DirectWrite::createTypefaceFromDWriteFont( | |
1727 IDWriteFontFace* fontFace, | |
1728 IDWriteFont* font, | |
1729 IDWriteFontFamily* fontFamily) const { | |
1730 SkTypeface* face = FindByProcAndRef(FindByDWriteFont, font); | |
1731 if (NULL == face) { | |
1732 face = DWriteFontTypeface::Create(fFactory.get(), fontFace, font, fontFa
mily); | |
1733 if (face) { | |
1734 Add(face, get_style(font), true); | |
1735 } | |
1736 } | |
1737 return face; | |
1738 } | |
1739 | |
1740 int SkFontMgr_DirectWrite::onCountFamilies() const { | |
1741 return fFontCollection->GetFontFamilyCount(); | |
1742 } | |
1743 | |
1744 void SkFontMgr_DirectWrite::onGetFamilyName(int index, SkString* familyName) con
st { | |
1745 SkTScopedComPtr<IDWriteFontFamily> fontFamily; | |
1746 HRVM(fFontCollection->GetFontFamily(index, &fontFamily), "Could not get requ
ested family."); | |
1747 | |
1748 SkTScopedComPtr<IDWriteLocalizedStrings> familyNames; | |
1749 HRVM(fontFamily->GetFamilyNames(&familyNames), "Could not get family names."
); | |
1750 | |
1751 sk_get_locale_string(familyNames.get(), fLocaleName.get(), familyName); | |
1752 } | |
1753 | |
1754 SkFontStyleSet* SkFontMgr_DirectWrite::onCreateStyleSet(int index) const { | |
1755 SkTScopedComPtr<IDWriteFontFamily> fontFamily; | |
1756 HRNM(fFontCollection->GetFontFamily(index, &fontFamily), "Could not get requ
ested family."); | |
1757 | |
1758 return SkNEW_ARGS(SkFontStyleSet_DirectWrite, (this, fontFamily.get())); | |
1759 } | |
1760 | |
1761 SkFontStyleSet* SkFontMgr_DirectWrite::onMatchFamily(const char familyName[]) co
nst { | |
1762 SkSMallocWCHAR dwFamilyName; | |
1763 HRN(sk_cstring_to_wchar(familyName, &dwFamilyName)); | |
1764 | |
1765 UINT32 index; | |
1766 BOOL exists; | |
1767 HRNM(fFontCollection->FindFamilyName(dwFamilyName.get(), &index, &exists), | |
1768 "Failed while finding family by name."); | |
1769 if (!exists) { | |
1770 return NULL; | |
1771 } | |
1772 | |
1773 return this->onCreateStyleSet(index); | |
1774 } | |
1775 | |
1776 SkTypeface* SkFontMgr_DirectWrite::onMatchFamilyStyle(const char familyName[], | |
1777 const SkFontStyle& fontsty
le) const { | |
1778 SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName)); | |
1779 return sset->matchStyle(fontstyle); | |
1780 } | |
1781 | |
1782 SkTypeface* SkFontMgr_DirectWrite::onMatchFaceStyle(const SkTypeface* familyMemb
er, | |
1783 const SkFontStyle& fontstyle
) const { | |
1784 SkString familyName; | |
1785 SkFontStyleSet_DirectWrite sset( | |
1786 this, ((DWriteFontTypeface*)familyMember)->fDWriteFontFamily.get() | |
1787 ); | |
1788 return sset.matchStyle(fontstyle); | |
1789 } | |
1790 | |
1791 SkTypeface* SkFontMgr_DirectWrite::onCreateFromStream(SkStream* stream, int ttcI
ndex) const { | |
1792 SkTScopedComPtr<StreamFontFileLoader> fontFileLoader; | |
1793 HRN(StreamFontFileLoader::Create(stream, &fontFileLoader)); | |
1794 HRN(fFactory->RegisterFontFileLoader(fontFileLoader.get())); | |
1795 SkAutoIDWriteUnregister<StreamFontFileLoader> autoUnregisterFontFileLoader( | |
1796 fFactory.get(), fontFileLoader.get()); | |
1797 | |
1798 SkTScopedComPtr<StreamFontCollectionLoader> fontCollectionLoader; | |
1799 HRN(StreamFontCollectionLoader::Create(fontFileLoader.get(), &fontCollection
Loader)); | |
1800 HRN(fFactory->RegisterFontCollectionLoader(fontCollectionLoader.get())); | |
1801 SkAutoIDWriteUnregister<StreamFontCollectionLoader> autoUnregisterFontCollec
tionLoader( | |
1802 fFactory.get(), fontCollectionLoader.get()); | |
1803 | |
1804 SkTScopedComPtr<IDWriteFontCollection> fontCollection; | |
1805 HRN(fFactory->CreateCustomFontCollection(fontCollectionLoader.get(), NULL, 0
, &fontCollection)); | |
1806 | |
1807 // Find the first non-simulated font which has the given ttc index. | |
1808 UINT32 familyCount = fontCollection->GetFontFamilyCount(); | |
1809 for (UINT32 familyIndex = 0; familyIndex < familyCount; ++familyIndex) { | |
1810 SkTScopedComPtr<IDWriteFontFamily> fontFamily; | |
1811 HRN(fontCollection->GetFontFamily(familyIndex, &fontFamily)); | |
1812 | |
1813 UINT32 fontCount = fontFamily->GetFontCount(); | |
1814 for (UINT32 fontIndex = 0; fontIndex < fontCount; ++fontIndex) { | |
1815 SkTScopedComPtr<IDWriteFont> font; | |
1816 HRN(fontFamily->GetFont(fontIndex, &font)); | |
1817 if (font->GetSimulations() != DWRITE_FONT_SIMULATIONS_NONE) { | |
1818 continue; | |
1819 } | |
1820 | |
1821 SkTScopedComPtr<IDWriteFontFace> fontFace; | |
1822 HRN(font->CreateFontFace(&fontFace)); | |
1823 | |
1824 UINT32 faceIndex = fontFace->GetIndex(); | |
1825 if (faceIndex == ttcIndex) { | |
1826 return DWriteFontTypeface::Create(fFactory.get(), | |
1827 fontFace.get(), font.get(), fo
ntFamily.get(), | |
1828 autoUnregisterFontFileLoader.d
etatch(), | |
1829 autoUnregisterFontCollectionLo
ader.detatch()); | |
1830 } | |
1831 } | |
1832 } | |
1833 | |
1834 return NULL; | |
1835 } | |
1836 | |
1837 SkTypeface* SkFontMgr_DirectWrite::onCreateFromData(SkData* data, int ttcIndex)
const { | |
1838 SkAutoTUnref<SkStream> stream(SkNEW_ARGS(SkMemoryStream, (data))); | |
1839 return this->createFromStream(stream, ttcIndex); | |
1840 } | |
1841 | |
1842 SkTypeface* SkFontMgr_DirectWrite::onCreateFromFile(const char path[], int ttcIn
dex) const { | |
1843 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path)); | |
1844 return this->createFromStream(stream, ttcIndex); | |
1845 } | |
1846 | |
1847 HRESULT SkFontMgr_DirectWrite::getByFamilyName(const WCHAR wideFamilyName[], | |
1848 IDWriteFontFamily** fontFamily) c
onst { | |
1849 UINT32 index; | |
1850 BOOL exists; | |
1851 HR(fFontCollection->FindFamilyName(wideFamilyName, &index, &exists)); | |
1852 | |
1853 if (exists) { | |
1854 HR(fFontCollection->GetFontFamily(index, fontFamily)); | |
1855 } | |
1856 return S_OK; | |
1857 } | |
1858 | |
1859 HRESULT SkFontMgr_DirectWrite::getDefaultFontFamily(IDWriteFontFamily** fontFami
ly) const { | |
1860 NONCLIENTMETRICSW metrics; | |
1861 metrics.cbSize = sizeof(metrics); | |
1862 if (0 == SystemParametersInfoW(SPI_GETNONCLIENTMETRICS, | |
1863 sizeof(metrics), | |
1864 &metrics, | |
1865 0)) { | |
1866 return E_UNEXPECTED; | |
1867 } | |
1868 HRM(this->getByFamilyName(metrics.lfMessageFont.lfFaceName, fontFamily), | |
1869 "Could not create DWrite font family from LOGFONT."); | |
1870 return S_OK; | |
1871 } | |
1872 | |
1873 SkTypeface* SkFontMgr_DirectWrite::onLegacyCreateTypeface(const char familyName[
], | |
1874 unsigned styleBits) co
nst { | |
1875 SkTScopedComPtr<IDWriteFontFamily> fontFamily; | |
1876 if (familyName) { | |
1877 SkSMallocWCHAR wideFamilyName; | |
1878 if (SUCCEEDED(sk_cstring_to_wchar(familyName, &wideFamilyName))) { | |
1879 this->getByFamilyName(wideFamilyName, &fontFamily); | |
1880 } | |
1881 } | |
1882 | |
1883 if (NULL == fontFamily.get()) { | |
1884 // No family with given name, try default. | |
1885 HRNM(this->getDefaultFontFamily(&fontFamily), "Could not get default fon
t family."); | |
1886 } | |
1887 | |
1888 if (NULL == fontFamily.get()) { | |
1889 // Could not obtain the default font. | |
1890 HRNM(fFontCollection->GetFontFamily(0, &fontFamily), | |
1891 "Could not get default-default font family."); | |
1892 } | |
1893 | |
1894 SkTScopedComPtr<IDWriteFont> font; | |
1895 DWRITE_FONT_WEIGHT weight = (styleBits & SkTypeface::kBold) | |
1896 ? DWRITE_FONT_WEIGHT_BOLD | |
1897 : DWRITE_FONT_WEIGHT_NORMAL; | |
1898 DWRITE_FONT_STRETCH stretch = DWRITE_FONT_STRETCH_NORMAL; | |
1899 DWRITE_FONT_STYLE italic = (styleBits & SkTypeface::kItalic) | |
1900 ? DWRITE_FONT_STYLE_ITALIC | |
1901 : DWRITE_FONT_STYLE_NORMAL; | |
1902 HRNM(fontFamily->GetFirstMatchingFont(weight, stretch, italic, &font), | |
1903 "Could not get matching font."); | |
1904 | |
1905 SkTScopedComPtr<IDWriteFontFace> fontFace; | |
1906 HRNM(font->CreateFontFace(&fontFace), "Could not create font face."); | |
1907 | |
1908 return this->createTypefaceFromDWriteFont(fontFace.get(), font.get(), fontFa
mily.get()); | |
1909 } | |
1910 | |
1911 /////////////////////////////////////////////////////////////////////////////// | |
1912 | |
1913 int SkFontStyleSet_DirectWrite::count() { | |
1914 return fFontFamily->GetFontCount(); | |
1915 } | |
1916 | |
1917 SkTypeface* SkFontStyleSet_DirectWrite::createTypeface(int index) { | |
1918 SkTScopedComPtr<IDWriteFont> font; | |
1919 HRNM(fFontFamily->GetFont(index, &font), "Could not get font."); | |
1920 | |
1921 SkTScopedComPtr<IDWriteFontFace> fontFace; | |
1922 HRNM(font->CreateFontFace(&fontFace), "Could not create font face."); | |
1923 | |
1924 return fFontMgr->createTypefaceFromDWriteFont(fontFace.get(), font.get(), fF
ontFamily.get()); | |
1925 } | |
1926 | |
1927 void SkFontStyleSet_DirectWrite::getStyle(int index, SkFontStyle* fs, SkString*
styleName) { | |
1928 SkTScopedComPtr<IDWriteFont> font; | |
1929 HRVM(fFontFamily->GetFont(index, &font), "Could not get font."); | |
1930 | |
1931 if (fs) { | |
1932 SkFontStyle::Slant slant; | |
1933 switch (font->GetStyle()) { | |
1934 case DWRITE_FONT_STYLE_NORMAL: | |
1935 slant = SkFontStyle::kUpright_Slant; | |
1936 break; | |
1937 case DWRITE_FONT_STYLE_OBLIQUE: | |
1938 case DWRITE_FONT_STYLE_ITALIC: | |
1939 slant = SkFontStyle::kItalic_Slant; | |
1940 break; | |
1941 default: | |
1942 SkASSERT(false); | |
1943 } | |
1944 | |
1945 int weight = font->GetWeight(); | |
1946 int width = font->GetStretch(); | |
1947 | |
1948 *fs = SkFontStyle(weight, width, slant); | |
1949 } | |
1950 | |
1951 if (styleName) { | |
1952 SkTScopedComPtr<IDWriteLocalizedStrings> faceNames; | |
1953 if (SUCCEEDED(font->GetFaceNames(&faceNames))) { | |
1954 sk_get_locale_string(faceNames.get(), fFontMgr->fLocaleName.get(), s
tyleName); | |
1955 } | |
1956 } | |
1957 } | |
1958 | |
1959 SkTypeface* SkFontStyleSet_DirectWrite::matchStyle(const SkFontStyle& pattern) { | |
1960 DWRITE_FONT_STYLE slant; | |
1961 switch (pattern.slant()) { | |
1962 case SkFontStyle::kUpright_Slant: | |
1963 slant = DWRITE_FONT_STYLE_NORMAL; | |
1964 break; | |
1965 case SkFontStyle::kItalic_Slant: | |
1966 slant = DWRITE_FONT_STYLE_ITALIC; | |
1967 break; | |
1968 default: | |
1969 SkASSERT(false); | |
1970 } | |
1971 | |
1972 DWRITE_FONT_WEIGHT weight = (DWRITE_FONT_WEIGHT)pattern.weight(); | |
1973 DWRITE_FONT_STRETCH width = (DWRITE_FONT_STRETCH)pattern.width(); | |
1974 | |
1975 SkTScopedComPtr<IDWriteFont> font; | |
1976 // TODO: perhaps use GetMatchingFonts and get the least simulated? | |
1977 HRNM(fFontFamily->GetFirstMatchingFont(weight, width, slant, &font), | |
1978 "Could not match font in family."); | |
1979 | |
1980 SkTScopedComPtr<IDWriteFontFace> fontFace; | |
1981 HRNM(font->CreateFontFace(&fontFace), "Could not create font face."); | |
1982 | |
1983 return fFontMgr->createTypefaceFromDWriteFont(fontFace.get(), font.get(), | |
1984 fFontFamily.get()); | |
1985 } | |
1986 | |
1987 /////////////////////////////////////////////////////////////////////////////// | |
1988 | |
1989 SkFontMgr* SkFontMgr_New_DirectWrite(IDWriteFactory* factory) { | |
1990 if (NULL == factory) { | |
1991 factory = sk_get_dwrite_factory(); | |
1992 if (NULL == factory) { | |
1993 return NULL; | |
1994 } | |
1995 } | |
1996 | |
1997 SkTScopedComPtr<IDWriteFontCollection> sysFontCollection; | |
1998 HRNM(factory->GetSystemFontCollection(&sysFontCollection, FALSE), | |
1999 "Could not get system font collection."); | |
2000 | |
2001 WCHAR localeNameStorage[LOCALE_NAME_MAX_LENGTH]; | |
2002 WCHAR* localeName = NULL; | |
2003 int localeNameLen = 0; | |
2004 | |
2005 // Dynamically load GetUserDefaultLocaleName function, as it is not availabl
e on XP. | |
2006 SkGetUserDefaultLocaleNameProc getUserDefaultLocaleNameProc = NULL; | |
2007 HRESULT hr = SkGetGetUserDefaultLocaleNameProc(&getUserDefaultLocaleNameProc
); | |
2008 if (NULL == getUserDefaultLocaleNameProc) { | |
2009 SK_TRACEHR(hr, "Could not get GetUserDefaultLocaleName."); | |
2010 } else { | |
2011 localeNameLen = getUserDefaultLocaleNameProc(localeNameStorage, LOCALE_N
AME_MAX_LENGTH); | |
2012 if (localeNameLen) { | |
2013 localeName = localeNameStorage; | |
2014 }; | |
2015 } | |
2016 | |
2017 return SkNEW_ARGS(SkFontMgr_DirectWrite, (factory, sysFontCollection.get(), | |
2018 localeName, localeNameLen)); | |
2019 } | |
2020 | |
2021 #include "SkFontMgr_indirect.h" | |
2022 SkFontMgr* SkFontMgr_New_DirectWriteRenderer(SkRemotableFontMgr* proxy) { | |
2023 SkAutoTUnref<SkFontMgr> impl(SkFontMgr_New_DirectWrite()); | |
2024 if (impl.get() == NULL) { | |
2025 return NULL; | |
2026 } | |
2027 return SkNEW_ARGS(SkFontMgr_Indirect, (impl.get(), proxy)); | |
2028 } | |
OLD | NEW |