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