Upstream version 11.39.250.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / ports / SkRemotableFontMgr_win_dw.cpp
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(), &familyName);
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_OVERRIDE {
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.fWidth,
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.lfFaceName, _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_OVERRIDE
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, identity);
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         virtual ~FontFallbackRenderer() { }
294
295         // IDWriteTextRenderer methods
296         virtual HRESULT STDMETHODCALLTYPE DrawGlyphRun(
297             void* clientDrawingContext,
298             FLOAT baselineOriginX,
299             FLOAT baselineOriginY,
300             DWRITE_MEASURING_MODE measuringMode,
301             DWRITE_GLYPH_RUN const* glyphRun,
302             DWRITE_GLYPH_RUN_DESCRIPTION const* glyphRunDescription,
303             IUnknown* clientDrawingEffect) SK_OVERRIDE
304         {
305             SkTScopedComPtr<IDWriteFont> font;
306             HRM(fOuter->fFontCollection->GetFontFromFontFace(glyphRun->fontFace, &font),
307                 "Could not get font from font face.");
308
309             // It is possible that the font passed does not actually have the requested character,
310             // due to no font being found and getting the fallback font.
311             // Check that the font actually contains the requested character.
312             BOOL exists;
313             HRM(font->HasCharacter(fCharacter, &exists), "Could not find character.");
314
315             if (exists) {
316                 HR(fOuter->FontToIdentity(font.get(), &fIdentity));
317             }
318
319             return S_OK;
320         }
321
322         virtual HRESULT STDMETHODCALLTYPE DrawUnderline(
323             void* clientDrawingContext,
324             FLOAT baselineOriginX,
325             FLOAT baselineOriginY,
326             DWRITE_UNDERLINE const* underline,
327             IUnknown* clientDrawingEffect) SK_OVERRIDE
328         { return E_NOTIMPL; }
329
330         virtual HRESULT STDMETHODCALLTYPE DrawStrikethrough(
331             void* clientDrawingContext,
332             FLOAT baselineOriginX,
333             FLOAT baselineOriginY,
334             DWRITE_STRIKETHROUGH const* strikethrough,
335             IUnknown* clientDrawingEffect) SK_OVERRIDE
336         { return E_NOTIMPL; }
337
338         virtual HRESULT STDMETHODCALLTYPE DrawInlineObject(
339             void* clientDrawingContext,
340             FLOAT originX,
341             FLOAT originY,
342             IDWriteInlineObject* inlineObject,
343             BOOL isSideways,
344             BOOL isRightToLeft,
345             IUnknown* clientDrawingEffect) SK_OVERRIDE
346         { return E_NOTIMPL; }
347
348         // IDWritePixelSnapping methods
349         virtual HRESULT STDMETHODCALLTYPE IsPixelSnappingDisabled(
350             void* clientDrawingContext,
351             BOOL* isDisabled) SK_OVERRIDE
352         {
353             *isDisabled = FALSE;
354             return S_OK;
355         }
356
357         virtual HRESULT STDMETHODCALLTYPE GetCurrentTransform(
358             void* clientDrawingContext,
359             DWRITE_MATRIX* transform) SK_OVERRIDE
360         {
361             const DWRITE_MATRIX ident = {1.0, 0.0, 0.0, 1.0, 0.0, 0.0};
362             *transform = ident;
363             return S_OK;
364         }
365
366         virtual HRESULT STDMETHODCALLTYPE GetPixelsPerDip(
367             void* clientDrawingContext,
368             FLOAT* pixelsPerDip) SK_OVERRIDE
369         {
370             *pixelsPerDip = 1.0f;
371             return S_OK;
372         }
373
374         // IUnknown methods
375         virtual ULONG STDMETHODCALLTYPE AddRef() SK_OVERRIDE {
376             return InterlockedIncrement(&fRefCount);
377         }
378
379         virtual ULONG STDMETHODCALLTYPE Release() SK_OVERRIDE {
380             ULONG newCount = InterlockedDecrement(&fRefCount);
381             if (0 == newCount) {
382                 delete this;
383             }
384             return newCount;
385         }
386
387         virtual HRESULT STDMETHODCALLTYPE QueryInterface(
388             IID const& riid, void** ppvObject) SK_OVERRIDE
389         {
390             if (__uuidof(IUnknown) == riid ||
391                 __uuidof(IDWritePixelSnapping) == riid ||
392                 __uuidof(IDWriteTextRenderer) == riid)
393             {
394                 *ppvObject = this;
395                 this->AddRef();
396                 return S_OK;
397             }
398             *ppvObject = NULL;
399             return E_FAIL;
400         }
401
402         const SkFontIdentity FallbackIdentity() { return fIdentity; }
403
404     protected:
405         ULONG fRefCount;
406         SkAutoTUnref<const SkRemotableFontMgr_DirectWrite> fOuter;
407         UINT32 fCharacter;
408         SkFontIdentity fIdentity;
409     };
410
411 #ifdef SK_FM_NEW_MATCH_FAMILY_STYLE_CHARACTER
412     virtual SkFontIdentity matchNameStyleCharacter(const char familyName[],
413                                                    const SkFontStyle& pattern,
414                                                    const char* bcp47[], int bcp47Count,
415                                                    SkUnichar character) const SK_OVERRIDE
416     {
417 #else
418     virtual SkFontIdentity matchNameStyleCharacter(const char familyName[],
419                                                    const SkFontStyle& pattern,
420                                                    const char bcp47_val[],
421                                                    SkUnichar character) const SK_OVERRIDE
422     {
423         const char** bcp47 = &bcp47_val;
424         int bcp47Count = bcp47_val ? 1 : 0;
425 #endif
426         SkFontIdentity identity = { SkFontIdentity::kInvalidDataId };
427
428         IDWriteFactory* dwFactory = sk_get_dwrite_factory();
429         if (NULL == dwFactory) {
430             return identity;
431         }
432
433         // TODO: use IDWriteFactory2::GetSystemFontFallback when available.
434
435         const DWriteStyle dwStyle(pattern);
436
437         SkSMallocWCHAR dwFamilyName;
438         if (NULL == familyName) {
439             HR_GENERAL(getDefaultFontFamilyName(&dwFamilyName), NULL, identity);
440         } else {
441             HR_GENERAL(sk_cstring_to_wchar(familyName, &dwFamilyName), NULL, identity);
442         }
443
444         const SkSMallocWCHAR* dwBcp47;
445         SkSMallocWCHAR dwBcp47Local;
446         if (bcp47Count < 1) {
447             dwBcp47 = &fLocaleName;
448         } else {
449             //TODO: support fallback stack.
450             HR_GENERAL(sk_cstring_to_wchar(bcp47[bcp47Count-1], &dwBcp47Local), NULL, identity);
451             dwBcp47 = &dwBcp47Local;
452         }
453
454         SkTScopedComPtr<IDWriteTextFormat> fallbackFormat;
455         HR_GENERAL(dwFactory->CreateTextFormat(dwFamilyName,
456                                                fFontCollection.get(),
457                                                dwStyle.fWeight,
458                                                dwStyle.fSlant,
459                                                dwStyle.fWidth,
460                                                72.0f,
461                                                *dwBcp47,
462                                                &fallbackFormat),
463                    "Could not create text format.",
464                    identity);
465
466         WCHAR str[16];
467         UINT32 strLen = static_cast<UINT32>(
468             SkUTF16_FromUnichar(character, reinterpret_cast<uint16_t*>(str)));
469         SkTScopedComPtr<IDWriteTextLayout> fallbackLayout;
470         HR_GENERAL(dwFactory->CreateTextLayout(str, strLen, fallbackFormat.get(),
471                                                200.0f, 200.0f,
472                                                &fallbackLayout),
473                    "Could not create text layout.",
474                    identity);
475
476         SkTScopedComPtr<FontFallbackRenderer> fontFallbackRenderer(
477             new FontFallbackRenderer(this, character));
478
479         HR_GENERAL(fallbackLayout->Draw(NULL, fontFallbackRenderer.get(), 50.0f, 50.0f),
480                    "Could not draw layout with renderer.",
481                    identity);
482
483         return fontFallbackRenderer->FallbackIdentity();
484     }
485
486     virtual SkStreamAsset* getData(int dataId) const SK_OVERRIDE {
487         SkAutoMutexAcquire ama(fDataIdCacheMutex);
488         if (dataId >= fDataIdCache.count()) {
489             return NULL;
490         }
491         const DataId& id = fDataIdCache[dataId];
492
493         SkTScopedComPtr<IDWriteFontFileLoader> loader;
494         HRNM(id.fLoader->QueryInterface(&loader), "QuerryInterface IDWriteFontFileLoader failed");
495
496         SkTScopedComPtr<IDWriteFontFileStream> fontFileStream;
497         HRNM(loader->CreateStreamFromKey(id.fKey, id.fKeySize, &fontFileStream),
498              "Could not create font file stream.");
499
500         return SkNEW_ARGS(SkDWriteFontFileStream, (fontFileStream.get()));
501     }
502
503 private:
504     SkTScopedComPtr<IDWriteFontCollection> fFontCollection;
505     SkSMallocWCHAR fLocaleName;
506
507     typedef SkRemotableFontMgr INHERITED;
508 };
509
510 SkRemotableFontMgr* SkRemotableFontMgr_New_DirectWrite() {
511     IDWriteFactory* factory = sk_get_dwrite_factory();
512     if (NULL == factory) {
513         return NULL;
514     }
515
516     SkTScopedComPtr<IDWriteFontCollection> sysFontCollection;
517     HRNM(factory->GetSystemFontCollection(&sysFontCollection, FALSE),
518          "Could not get system font collection.");
519
520     WCHAR localeNameStorage[LOCALE_NAME_MAX_LENGTH];
521     WCHAR* localeName = NULL;
522     int localeNameLen = 0;
523
524     // Dynamically load GetUserDefaultLocaleName function, as it is not available on XP.
525     SkGetUserDefaultLocaleNameProc getUserDefaultLocaleNameProc = NULL;
526     HRESULT hr = SkGetGetUserDefaultLocaleNameProc(&getUserDefaultLocaleNameProc);
527     if (NULL == getUserDefaultLocaleNameProc) {
528         SK_TRACEHR(hr, "Could not get GetUserDefaultLocaleName.");
529     } else {
530         localeNameLen = getUserDefaultLocaleNameProc(localeNameStorage, LOCALE_NAME_MAX_LENGTH);
531         if (localeNameLen) {
532             localeName = localeNameStorage;
533         };
534     }
535
536     return SkNEW_ARGS(SkRemotableFontMgr_DirectWrite, (sysFontCollection.get(),
537                                                        localeName, localeNameLen));
538 }