Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(305)

Side by Side Diff: src/ports/SkRemotableFontMgr_win_dw.cpp

Issue 206683002: A remotable font management interface and DirectWrite implementation. (Closed) Base URL: http://skia.googlecode.com/svn/trunk/
Patch Set: Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ports/SkFontHost_win_dw.cpp ('k') | src/utils/win/SkDWrite.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright 2014 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 "SkDataTable.h"
9 #include "SkDWrite.h"
10 #include "SkDWriteFontFileStream.h"
11 #include "SkHRESULT.h"
12 #include "SkRemotableFontMgr.h"
13 #include "SkStream.h"
14 #include "SkString.h"
15 #include "SkTArray.h"
16 #include "SkThread.h"
17 #include "SkTScopedComPtr.h"
18 #include "SkTypeface_win.h"
19 #include "SkTypes.h"
20 #include "SkUtils.h"
21
22 #include <dwrite.h>
23
24 struct DWriteStyle {
25 explicit DWriteStyle(const SkFontStyle& pattern) {
26 switch (pattern.slant()) {
27 case SkFontStyle::kUpright_Slant:
28 fSlant = DWRITE_FONT_STYLE_NORMAL;
29 break;
30 case SkFontStyle::kItalic_Slant:
31 fSlant = DWRITE_FONT_STYLE_ITALIC;
32 break;
33 default:
34 SkASSERT(false);
35 }
36
37 fWeight = (DWRITE_FONT_WEIGHT)pattern.weight();
38 fWidth = (DWRITE_FONT_STRETCH)pattern.width();
39 }
40 DWRITE_FONT_STYLE fSlant;
41 DWRITE_FONT_WEIGHT fWeight;
42 DWRITE_FONT_STRETCH fWidth;
43 };
44
45 class SK_API SkRemotableFontMgr_DirectWrite : public SkRemotableFontMgr {
46 private:
47 struct DataId {
48 IUnknown* fLoader; // In COM only IUnknown pointers may be safely used for identity.
49 void* fKey;
50 UINT32 fKeySize;
51
52 DataId() { }
53
54 // This is actually a move!!!
55 explicit DataId(DataId& that)
56 : fLoader(that.fLoader), fKey(that.fKey), fKeySize(that.fKeySize)
57 {
58 that.fLoader = NULL;
59 that.fKey = NULL;
60 SkDEBUGCODE(that.fKeySize = 0xFFFFFFFF;)
61 }
62
63 ~DataId() {
64 if (fLoader) {
65 fLoader->Release();
66 }
67 sk_free(fKey);
68 }
69 };
70
71 mutable SkTArray<DataId> fDataIdCache;
72 mutable SkMutex fDataIdCacheMutex;
73
74 int FindOrAdd(IDWriteFontFileLoader* fontFileLoader,
75 const void* refKey, UINT32 refKeySize) const
76 {
77 SkTScopedComPtr<IUnknown> fontFileLoaderId;
78 HR_GENERAL(fontFileLoader->QueryInterface(&fontFileLoaderId),
79 "Failed to re-convert to IDWriteFontFileLoader.",
80 SkFontIdentity::kInvalidDataId);
81
82 SkAutoMutexAcquire ama(fDataIdCacheMutex);
83 int count = fDataIdCache.count();
84 int i;
85 for (i = 0; i < count; ++i) {
86 const DataId& current = fDataIdCache[i];
87 if (fontFileLoaderId.get() == current.fLoader &&
88 refKeySize == current.fKeySize &&
89 0 == memcmp(refKey, current.fKey, refKeySize))
90 {
91 return i;
92 }
93 }
94 DataId& added = fDataIdCache.push_back();
95 added.fLoader = fontFileLoaderId.release(); // Ref is passed.
96 added.fKey = sk_malloc_throw(refKeySize);
97 memcpy(added.fKey, refKey, refKeySize);
98 added.fKeySize = refKeySize;
99
100 return i;
101 }
102
103 public:
104 SK_DECLARE_INST_COUNT(SkRemotableFontMgr_DirectWrite)
105
106 /** localeNameLength must include the null terminator. */
107 SkRemotableFontMgr_DirectWrite(IDWriteFontCollection* fontCollection,
108 WCHAR* localeName, int localeNameLength)
109 : fFontCollection(SkRefComPtr(fontCollection))
110 , fLocaleName(localeNameLength)
111 {
112 memcpy(fLocaleName.get(), localeName, localeNameLength * sizeof(WCHAR));
113 }
114
115 virtual SkDataTable* getFamilyNames() const SK_OVERRIDE {
116 int count = fFontCollection->GetFontFamilyCount();
117
118 SkDataTableBuilder names(1024);
119 for (int index = 0; index < count; ++index) {
120 SkTScopedComPtr<IDWriteFontFamily> fontFamily;
121 HRNM(fFontCollection->GetFontFamily(index, &fontFamily),
122 "Could not get requested family.");
123
124 SkTScopedComPtr<IDWriteLocalizedStrings> familyNames;
125 HRNM(fontFamily->GetFamilyNames(&familyNames), "Could not get family names.");
126
127 SkString familyName;
128 sk_get_locale_string(familyNames.get(), fLocaleName.get(), &familyNa me);
129
130 names.appendString(familyName);
131 }
132 return names.detachDataTable();
133 }
134
135 HRESULT FontToIdentity(IDWriteFont* font, SkFontIdentity* fontId) const {
136 SkTScopedComPtr<IDWriteFontFace> fontFace;
137 HRM(font->CreateFontFace(&fontFace), "Could not create font face.");
138
139 UINT32 numFiles;
140 HR(fontFace->GetFiles(&numFiles, NULL));
141 if (numFiles > 1) {
142 return E_FAIL;
143 }
144
145 // data id
146 SkTScopedComPtr<IDWriteFontFile> fontFile;
147 HR(fontFace->GetFiles(&numFiles, &fontFile));
148
149 SkTScopedComPtr<IDWriteFontFileLoader> fontFileLoader;
150 HR(fontFile->GetLoader(&fontFileLoader));
151
152 const void* refKey;
153 UINT32 refKeySize;
154 HR(fontFile->GetReferenceKey(&refKey, &refKeySize));
155
156 fontId->fDataId = FindOrAdd(fontFileLoader.get(), refKey, refKeySize);
157
158 // index
159 fontId->fTtcIndex = fontFace->GetIndex();
160
161 // style
162 SkFontStyle::Slant slant;
163 switch (font->GetStyle()) {
164 case DWRITE_FONT_STYLE_NORMAL:
165 slant = SkFontStyle::kUpright_Slant;
166 break;
167 case DWRITE_FONT_STYLE_OBLIQUE:
168 case DWRITE_FONT_STYLE_ITALIC:
169 slant = SkFontStyle::kItalic_Slant;
170 break;
171 default:
172 SkASSERT(false);
173 }
174
175 int weight = font->GetWeight();
176 int width = font->GetStretch();
177
178 fontId->fFontStyle = SkFontStyle(weight, width, slant);
179 return S_OK;
180 }
181
182 virtual SkRemotableFontIdentitySet* getIndex(int familyIndex) const SK_OVERR IDE {
183 SkTScopedComPtr<IDWriteFontFamily> fontFamily;
184 HRNM(fFontCollection->GetFontFamily(familyIndex, &fontFamily),
185 "Could not get requested family.");
186
187 int count = fontFamily->GetFontCount();
188 SkFontIdentity* fontIds;
189 SkAutoTUnref<SkRemotableFontIdentitySet> fontIdSet(
190 new SkRemotableFontIdentitySet(count, &fontIds));
191 for (int fontIndex = 0; fontIndex < count; ++fontIndex) {
192 SkTScopedComPtr<IDWriteFont> font;
193 HRNM(fontFamily->GetFont(fontIndex, &font), "Could not get font.");
194
195 HRN(FontToIdentity(font.get(), &fontIds[fontIndex]));
196 }
197 return fontIdSet.detach();
198 }
199
200 virtual SkFontIdentity matchIndexStyle(int familyIndex,
201 const SkFontStyle& pattern) const SK_ OVERRIDE
202 {
203 SkFontIdentity identity = { SkFontIdentity::kInvalidDataId };
204
205 SkTScopedComPtr<IDWriteFontFamily> fontFamily;
206 HR_GENERAL(fFontCollection->GetFontFamily(familyIndex, &fontFamily),
207 "Could not get requested family.",
208 identity);
209
210 const DWriteStyle dwStyle(pattern);
211 SkTScopedComPtr<IDWriteFont> font;
212 HR_GENERAL(fontFamily->GetFirstMatchingFont(dwStyle.fWeight, dwStyle.fWi dth,
213 dwStyle.fSlant, &font),
214 "Could not match font in family.",
215 identity);
216
217 HR_GENERAL(FontToIdentity(font.get(), &identity), NULL, identity);
218
219 return identity;
220 }
221
222 static HRESULT getDefaultFontFamilyName(SkSMallocWCHAR* name) {
223 NONCLIENTMETRICSW metrics;
224 metrics.cbSize = sizeof(metrics);
225 if (0 == SystemParametersInfoW(SPI_GETNONCLIENTMETRICS,
226 sizeof(metrics),
227 &metrics,
228 0)) {
229 return E_UNEXPECTED;
230 }
231
232 size_t len = wcsnlen_s(metrics.lfMessageFont.lfFaceName, LF_FACESIZE) + 1;
233 if (0 != wcsncpy_s(name->reset(len), len, metrics.lfMessageFont.lfFaceNa me, _TRUNCATE)) {
234 return E_UNEXPECTED;
235 }
236
237 return S_OK;
238 }
239
240 virtual SkRemotableFontIdentitySet* matchName(const char familyName[]) const SK_OVERRIDE {
241 SkSMallocWCHAR dwFamilyName;
242 if (NULL == familyName) {
243 HR_GENERAL(getDefaultFontFamilyName(&dwFamilyName),
244 NULL, SkRemotableFontIdentitySet::NewEmpty());
245 } else {
246 HR_GENERAL(sk_cstring_to_wchar(familyName, &dwFamilyName),
247 NULL, SkRemotableFontIdentitySet::NewEmpty());
248 }
249
250 UINT32 index;
251 BOOL exists;
252 HR_GENERAL(fFontCollection->FindFamilyName(dwFamilyName.get(), &index, & exists),
253 "Failed while finding family by name.",
254 SkRemotableFontIdentitySet::NewEmpty());
255 if (!exists) {
256 return SkRemotableFontIdentitySet::NewEmpty();
257 }
258
259 return this->getIndex(index);
260 }
261
262 virtual SkFontIdentity matchNameStyle(const char familyName[],
263 const SkFontStyle& style) const SK_OVE RRIDE
264 {
265 SkFontIdentity identity = { SkFontIdentity::kInvalidDataId };
266
267 SkSMallocWCHAR dwFamilyName;
268 if (NULL == familyName) {
269 HR_GENERAL(getDefaultFontFamilyName(&dwFamilyName), NULL, identity);
270 } else {
271 HR_GENERAL(sk_cstring_to_wchar(familyName, &dwFamilyName), NULL, ide ntity);
272 }
273
274 UINT32 index;
275 BOOL exists;
276 HR_GENERAL(fFontCollection->FindFamilyName(dwFamilyName.get(), &index, & exists),
277 "Failed while finding family by name.",
278 identity);
279 if (!exists) {
280 return identity;
281 }
282
283 return this->matchIndexStyle(index, style);
284 }
285
286 class FontFallbackRenderer : public IDWriteTextRenderer {
287 public:
288 FontFallbackRenderer(const SkRemotableFontMgr_DirectWrite* outer, UINT32 character)
289 : fRefCount(1), fOuter(SkSafeRef(outer)), fCharacter(character) {
290 fIdentity.fDataId = SkFontIdentity::kInvalidDataId;
291 }
292
293 // IDWriteTextRenderer methods
294 virtual HRESULT STDMETHODCALLTYPE DrawGlyphRun(
295 void* clientDrawingContext,
296 FLOAT baselineOriginX,
297 FLOAT baselineOriginY,
298 DWRITE_MEASURING_MODE measuringMode,
299 DWRITE_GLYPH_RUN const* glyphRun,
300 DWRITE_GLYPH_RUN_DESCRIPTION const* glyphRunDescription,
301 IUnknown* clientDrawingEffect) SK_OVERRIDE
302 {
303 SkTScopedComPtr<IDWriteFont> font;
304 HRM(fOuter->fFontCollection->GetFontFromFontFace(glyphRun->fontFace, &font),
305 "Could not get font from font face.");
306
307 // It is possible that the font passed does not actually have the re quested character,
308 // due to no font being found and getting the fallback font.
309 // Check that the font actually contains the requested character.
310 BOOL exists;
311 HRM(font->HasCharacter(fCharacter, &exists), "Could not find charact er.");
312
313 if (exists) {
314 HR(fOuter->FontToIdentity(font.get(), &fIdentity));
315 }
316
317 return S_OK;
318 }
319
320 virtual HRESULT STDMETHODCALLTYPE DrawUnderline(
321 void* clientDrawingContext,
322 FLOAT baselineOriginX,
323 FLOAT baselineOriginY,
324 DWRITE_UNDERLINE const* underline,
325 IUnknown* clientDrawingEffect) SK_OVERRIDE
326 { return E_NOTIMPL; }
327
328 virtual HRESULT STDMETHODCALLTYPE DrawStrikethrough(
329 void* clientDrawingContext,
330 FLOAT baselineOriginX,
331 FLOAT baselineOriginY,
332 DWRITE_STRIKETHROUGH const* strikethrough,
333 IUnknown* clientDrawingEffect) SK_OVERRIDE
334 { return E_NOTIMPL; }
335
336 virtual HRESULT STDMETHODCALLTYPE DrawInlineObject(
337 void* clientDrawingContext,
338 FLOAT originX,
339 FLOAT originY,
340 IDWriteInlineObject* inlineObject,
341 BOOL isSideways,
342 BOOL isRightToLeft,
343 IUnknown* clientDrawingEffect) SK_OVERRIDE
344 { return E_NOTIMPL; }
345
346 // IDWritePixelSnapping methods
347 virtual HRESULT STDMETHODCALLTYPE IsPixelSnappingDisabled(
348 void* clientDrawingContext,
349 BOOL* isDisabled) SK_OVERRIDE
350 {
351 *isDisabled = FALSE;
352 return S_OK;
353 }
354
355 virtual HRESULT STDMETHODCALLTYPE GetCurrentTransform(
356 void* clientDrawingContext,
357 DWRITE_MATRIX* transform) SK_OVERRIDE
358 {
359 const DWRITE_MATRIX ident = {1.0, 0.0, 0.0, 1.0, 0.0, 0.0};
360 *transform = ident;
361 return S_OK;
362 }
363
364 virtual HRESULT STDMETHODCALLTYPE GetPixelsPerDip(
365 void* clientDrawingContext,
366 FLOAT* pixelsPerDip) SK_OVERRIDE
367 {
368 *pixelsPerDip = 1.0f;
369 return S_OK;
370 }
371
372 // IUnknown methods
373 virtual ULONG STDMETHODCALLTYPE AddRef() SK_OVERRIDE {
374 return InterlockedIncrement(&fRefCount);
375 }
376
377 virtual ULONG STDMETHODCALLTYPE Release() SK_OVERRIDE {
378 ULONG newCount = InterlockedDecrement(&fRefCount);
379 if (0 == newCount) {
380 delete this;
381 }
382 return newCount;
383 }
384
385 virtual HRESULT STDMETHODCALLTYPE QueryInterface(
386 IID const& riid, void** ppvObject) SK_OVERRIDE
387 {
388 if (__uuidof(IUnknown) == riid ||
389 __uuidof(IDWritePixelSnapping) == riid ||
390 __uuidof(IDWriteTextRenderer) == riid)
391 {
392 *ppvObject = this;
393 this->AddRef();
394 return S_OK;
395 }
396 *ppvObject = NULL;
397 return E_FAIL;
398 }
399
400 const SkFontIdentity FallbackIdentity() { return fIdentity; }
401
402 protected:
403 ULONG fRefCount;
404 SkAutoTUnref<const SkRemotableFontMgr_DirectWrite> fOuter;
405 UINT32 fCharacter;
406 SkFontIdentity fIdentity;
407 };
408
409 virtual SkFontIdentity matchNameStyleCharacter(const char familyName[],
410 const SkFontStyle& pattern,
411 const char bpc47[],
412 SkUnichar character) const S K_OVERRIDE
413 {
414 SkFontIdentity identity = { SkFontIdentity::kInvalidDataId };
415
416 IDWriteFactory* dwFactory = sk_get_dwrite_factory();
417 if (NULL == dwFactory) {
418 return identity;
419 }
420
421 // TODO: use IDWriteFactory2::GetSystemFontFallback when available.
422
423 const DWriteStyle dwStyle(pattern);
424
425 SkSMallocWCHAR dwFamilyName;
426 if (NULL == familyName) {
427 HR_GENERAL(getDefaultFontFamilyName(&dwFamilyName), NULL, identity);
428 } else {
429 HR_GENERAL(sk_cstring_to_wchar(familyName, &dwFamilyName), NULL, ide ntity);
430 }
431
432 const SkSMallocWCHAR* dwBpc47;
433 SkSMallocWCHAR dwBpc47Local;
434 if (NULL == bpc47) {
435 dwBpc47 = &fLocaleName;
436 } else {
437 HR_GENERAL(sk_cstring_to_wchar(bpc47, &dwBpc47Local), NULL, identity );
438 dwBpc47 = &dwBpc47Local;
439 }
440
441 SkTScopedComPtr<IDWriteTextFormat> fallbackFormat;
442 HR_GENERAL(dwFactory->CreateTextFormat(dwFamilyName,
443 fFontCollection.get(),
444 dwStyle.fWeight,
445 dwStyle.fSlant,
446 dwStyle.fWidth,
447 72.0f,
448 *dwBpc47,
449 &fallbackFormat),
450 "Could not create text format.",
451 identity);
452
453 WCHAR str[16];
454 UINT32 strLen = SkUTF16_FromUnichar(character, reinterpret_cast<uint16_t *>(str));
455 SkTScopedComPtr<IDWriteTextLayout> fallbackLayout;
456 HR_GENERAL(dwFactory->CreateTextLayout(str, strLen, fallbackFormat.get() ,
457 200.0f, 200.0f,
458 &fallbackLayout),
459 "Could not create text layout.",
460 identity);
461
462 SkTScopedComPtr<FontFallbackRenderer> fontFallbackRenderer(
463 new FontFallbackRenderer(this, character));
464
465 HR_GENERAL(fallbackLayout->Draw(NULL, fontFallbackRenderer.get(), 50.0f, 50.0f),
466 "Could not draw layout with renderer.",
467 identity);
468
469 return fontFallbackRenderer->FallbackIdentity();
470 }
471
472 virtual SkStreamAsset* getData(int dataId) const SK_OVERRIDE {
473 SkAutoMutexAcquire ama(fDataIdCacheMutex);
474 if (dataId >= fDataIdCache.count()) {
475 return NULL;
476 }
477 const DataId& id = fDataIdCache[dataId];
478
479 SkTScopedComPtr<IDWriteFontFileLoader> loader;
480 HRNM(id.fLoader->QueryInterface(&loader), "QuerryInterface IDWriteFontFi leLoader failed");
481
482 SkTScopedComPtr<IDWriteFontFileStream> fontFileStream;
483 HRNM(loader->CreateStreamFromKey(id.fKey, id.fKeySize, &fontFileStream),
484 "Could not create font file stream.");
485
486 return SkNEW_ARGS(SkDWriteFontFileStream, (fontFileStream.get()));
487 }
488
489 private:
490 SkTScopedComPtr<IDWriteFontCollection> fFontCollection;
491 SkSMallocWCHAR fLocaleName;
492
493 typedef SkRemotableFontMgr INHERITED;
494 };
495
496 SkRemotableFontMgr* SkRemotableFontMgr_New_DirectWrite() {
497 IDWriteFactory* factory = sk_get_dwrite_factory();
498 if (NULL == factory) {
499 return NULL;
500 }
501
502 SkTScopedComPtr<IDWriteFontCollection> sysFontCollection;
503 HRNM(factory->GetSystemFontCollection(&sysFontCollection, FALSE),
504 "Could not get system font collection.");
505
506 WCHAR localeNameStorage[LOCALE_NAME_MAX_LENGTH];
507 WCHAR* localeName = NULL;
508 int localeNameLen = 0;
509
510 // Dynamically load GetUserDefaultLocaleName function, as it is not availabl e on XP.
511 SkGetUserDefaultLocaleNameProc getUserDefaultLocaleNameProc = NULL;
512 HRESULT hr = SkGetGetUserDefaultLocaleNameProc(&getUserDefaultLocaleNameProc );
513 if (NULL == getUserDefaultLocaleNameProc) {
514 SK_TRACEHR(hr, "Could not get GetUserDefaultLocaleName.");
515 } else {
516 localeNameLen = getUserDefaultLocaleNameProc(localeNameStorage, LOCALE_N AME_MAX_LENGTH);
517 if (localeNameLen) {
518 localeName = localeNameStorage;
519 };
520 }
521
522 return SkNEW_ARGS(SkRemotableFontMgr_DirectWrite, (sysFontCollection.get(),
523 localeName, localeNameLen ));
524 }
OLDNEW
« no previous file with comments | « src/ports/SkFontHost_win_dw.cpp ('k') | src/utils/win/SkDWrite.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698