Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / ports / SkTypeface_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 "SkDWriteFontFileStream.h"
9 #include "SkFontDescriptor.h"
10 #include "SkFontStream.h"
11 #include "SkOTTable_head.h"
12 #include "SkOTTable_hhea.h"
13 #include "SkOTTable_OS_2.h"
14 #include "SkOTTable_post.h"
15 #include "SkScalerContext.h"
16 #include "SkScalerContext_win_dw.h"
17 #include "SkTypeface_win_dw.h"
18 #include "SkTypes.h"
19 #include "SkUtils.h"
20
21 void DWriteFontTypeface::onGetFontDescriptor(SkFontDescriptor* desc,
22                                              bool* isLocalStream) const {
23     // Get the family name.
24     SkTScopedComPtr<IDWriteLocalizedStrings> dwFamilyNames;
25     HRV(fDWriteFontFamily->GetFamilyNames(&dwFamilyNames));
26
27     UINT32 dwFamilyNamesLength;
28     HRV(dwFamilyNames->GetStringLength(0, &dwFamilyNamesLength));
29
30     SkSMallocWCHAR dwFamilyNameChar(dwFamilyNamesLength+1);
31     HRV(dwFamilyNames->GetString(0, dwFamilyNameChar.get(), dwFamilyNamesLength+1));
32
33     SkString utf8FamilyName;
34     HRV(sk_wchar_to_skstring(dwFamilyNameChar.get(), &utf8FamilyName));
35
36     desc->setFamilyName(utf8FamilyName.c_str());
37     *isLocalStream = SkToBool(fDWriteFontFileLoader.get());
38 }
39
40 static SkUnichar next_utf8(const void** chars) {
41     return SkUTF8_NextUnichar((const char**)chars);
42 }
43
44 static SkUnichar next_utf16(const void** chars) {
45     return SkUTF16_NextUnichar((const uint16_t**)chars);
46 }
47
48 static SkUnichar next_utf32(const void** chars) {
49     const SkUnichar** uniChars = (const SkUnichar**)chars;
50     SkUnichar uni = **uniChars;
51     *uniChars += 1;
52     return uni;
53 }
54
55 typedef SkUnichar (*EncodingProc)(const void**);
56
57 static EncodingProc find_encoding_proc(SkTypeface::Encoding enc) {
58     static const EncodingProc gProcs[] = {
59         next_utf8, next_utf16, next_utf32
60     };
61     SkASSERT((size_t)enc < SK_ARRAY_COUNT(gProcs));
62     return gProcs[enc];
63 }
64
65 int DWriteFontTypeface::onCharsToGlyphs(const void* chars, Encoding encoding,
66                                         uint16_t glyphs[], int glyphCount) const
67 {
68     if (NULL == glyphs) {
69         EncodingProc next_ucs4_proc = find_encoding_proc(encoding);
70         for (int i = 0; i < glyphCount; ++i) {
71             const SkUnichar c = next_ucs4_proc(&chars);
72             BOOL exists;
73             fDWriteFont->HasCharacter(c, &exists);
74             if (!exists) {
75                 return i;
76             }
77         }
78         return glyphCount;
79     }
80
81     switch (encoding) {
82     case SkTypeface::kUTF8_Encoding:
83     case SkTypeface::kUTF16_Encoding: {
84         static const int scratchCount = 256;
85         UINT32 scratch[scratchCount];
86         EncodingProc next_ucs4_proc = find_encoding_proc(encoding);
87         for (int baseGlyph = 0; baseGlyph < glyphCount; baseGlyph += scratchCount) {
88             int glyphsLeft = glyphCount - baseGlyph;
89             int limit = SkTMin(glyphsLeft, scratchCount);
90             for (int i = 0; i < limit; ++i) {
91                 scratch[i] = next_ucs4_proc(&chars);
92             }
93             fDWriteFontFace->GetGlyphIndices(scratch, limit, &glyphs[baseGlyph]);
94         }
95         break;
96     }
97     case SkTypeface::kUTF32_Encoding: {
98         const UINT32* utf32 = reinterpret_cast<const UINT32*>(chars);
99         fDWriteFontFace->GetGlyphIndices(utf32, glyphCount, glyphs);
100         break;
101     }
102     default:
103         SK_CRASH();
104     }
105
106     for (int i = 0; i < glyphCount; ++i) {
107         if (0 == glyphs[i]) {
108             return i;
109         }
110     }
111     return glyphCount;
112 }
113
114 int DWriteFontTypeface::onCountGlyphs() const {
115     return fDWriteFontFace->GetGlyphCount();
116 }
117
118 int DWriteFontTypeface::onGetUPEM() const {
119     DWRITE_FONT_METRICS metrics;
120     fDWriteFontFace->GetMetrics(&metrics);
121     return metrics.designUnitsPerEm;
122 }
123
124 class LocalizedStrings_IDWriteLocalizedStrings : public SkTypeface::LocalizedStrings {
125 public:
126     /** Takes ownership of the IDWriteLocalizedStrings. */
127     explicit LocalizedStrings_IDWriteLocalizedStrings(IDWriteLocalizedStrings* strings)
128         : fIndex(0), fStrings(strings)
129     { }
130
131     virtual bool next(SkTypeface::LocalizedString* localizedString) SK_OVERRIDE {
132         if (fIndex >= fStrings->GetCount()) {
133             return false;
134         }
135
136         // String
137         UINT32 stringLength;
138         HRBM(fStrings->GetStringLength(fIndex, &stringLength), "Could not get string length.");
139         stringLength += 1;
140
141         SkSMallocWCHAR wString(stringLength);
142         HRBM(fStrings->GetString(fIndex, wString.get(), stringLength), "Could not get string.");
143
144         HRB(sk_wchar_to_skstring(wString.get(), &localizedString->fString));
145
146         // Locale
147         UINT32 localeLength;
148         HRBM(fStrings->GetLocaleNameLength(fIndex, &localeLength), "Could not get locale length.");
149         localeLength += 1;
150
151         SkSMallocWCHAR wLocale(localeLength);
152         HRBM(fStrings->GetLocaleName(fIndex, wLocale.get(), localeLength), "Could not get locale.");
153
154         HRB(sk_wchar_to_skstring(wLocale.get(), &localizedString->fLanguage));
155
156         ++fIndex;
157         return true;
158     }
159
160 private:
161     UINT32 fIndex;
162     SkTScopedComPtr<IDWriteLocalizedStrings> fStrings;
163 };
164
165 SkTypeface::LocalizedStrings* DWriteFontTypeface::onCreateFamilyNameIterator() const {
166     SkTScopedComPtr<IDWriteLocalizedStrings> familyNames;
167     HRNM(fDWriteFontFamily->GetFamilyNames(&familyNames), "Could not obtain family names.");
168
169     return new LocalizedStrings_IDWriteLocalizedStrings(familyNames.release());
170 }
171
172 int DWriteFontTypeface::onGetTableTags(SkFontTableTag tags[]) const {
173     DWRITE_FONT_FACE_TYPE type = fDWriteFontFace->GetType();
174     if (type != DWRITE_FONT_FACE_TYPE_CFF &&
175         type != DWRITE_FONT_FACE_TYPE_TRUETYPE &&
176         type != DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION)
177     {
178         return 0;
179     }
180
181     int ttcIndex;
182     SkAutoTUnref<SkStream> stream(this->openStream(&ttcIndex));
183     return stream.get() ? SkFontStream::GetTableTags(stream, ttcIndex, tags) : 0;
184 }
185
186 size_t DWriteFontTypeface::onGetTableData(SkFontTableTag tag, size_t offset,
187                                           size_t length, void* data) const
188 {
189     AutoDWriteTable table(fDWriteFontFace.get(), SkEndian_SwapBE32(tag));
190     if (!table.fExists) {
191         return 0;
192     }
193
194     if (offset > table.fSize) {
195         return 0;
196     }
197     size_t size = SkTMin(length, table.fSize - offset);
198     if (NULL != data) {
199         memcpy(data, table.fData + offset, size);
200     }
201
202     return size;
203 }
204
205 SkStream* DWriteFontTypeface::onOpenStream(int* ttcIndex) const {
206     *ttcIndex = fDWriteFontFace->GetIndex();
207
208     UINT32 numFiles;
209     HRNM(fDWriteFontFace->GetFiles(&numFiles, NULL),
210          "Could not get number of font files.");
211     if (numFiles != 1) {
212         return NULL;
213     }
214
215     SkTScopedComPtr<IDWriteFontFile> fontFile;
216     HRNM(fDWriteFontFace->GetFiles(&numFiles, &fontFile), "Could not get font files.");
217
218     const void* fontFileKey;
219     UINT32 fontFileKeySize;
220     HRNM(fontFile->GetReferenceKey(&fontFileKey, &fontFileKeySize),
221          "Could not get font file reference key.");
222
223     SkTScopedComPtr<IDWriteFontFileLoader> fontFileLoader;
224     HRNM(fontFile->GetLoader(&fontFileLoader), "Could not get font file loader.");
225
226     SkTScopedComPtr<IDWriteFontFileStream> fontFileStream;
227     HRNM(fontFileLoader->CreateStreamFromKey(fontFileKey, fontFileKeySize,
228                                              &fontFileStream),
229          "Could not create font file stream.");
230
231     return SkNEW_ARGS(SkDWriteFontFileStream, (fontFileStream.get()));
232 }
233
234 SkScalerContext* DWriteFontTypeface::onCreateScalerContext(const SkDescriptor* desc) const {
235     return SkNEW_ARGS(SkScalerContext_DW, (const_cast<DWriteFontTypeface*>(this), desc));
236 }
237
238 void DWriteFontTypeface::onFilterRec(SkScalerContext::Rec* rec) const {
239     if (rec->fFlags & SkScalerContext::kLCD_BGROrder_Flag ||
240         rec->fFlags & SkScalerContext::kLCD_Vertical_Flag)
241     {
242         rec->fMaskFormat = SkMask::kA8_Format;
243     }
244
245     unsigned flagsWeDontSupport = SkScalerContext::kVertical_Flag |
246                                   SkScalerContext::kDevKernText_Flag |
247                                   SkScalerContext::kForceAutohinting_Flag |
248                                   SkScalerContext::kEmbolden_Flag |
249                                   SkScalerContext::kLCD_BGROrder_Flag |
250                                   SkScalerContext::kLCD_Vertical_Flag;
251     rec->fFlags &= ~flagsWeDontSupport;
252
253     SkPaint::Hinting h = rec->getHinting();
254     // DirectWrite does not provide for hinting hints.
255     h = SkPaint::kSlight_Hinting;
256     rec->setHinting(h);
257
258 #if SK_FONT_HOST_USE_SYSTEM_SETTINGS
259     IDWriteFactory* factory = get_dwrite_factory();
260     if (factory != NULL) {
261         SkTScopedComPtr<IDWriteRenderingParams> defaultRenderingParams;
262         if (SUCCEEDED(factory->CreateRenderingParams(&defaultRenderingParams))) {
263             float gamma = defaultRenderingParams->GetGamma();
264             rec->setDeviceGamma(gamma);
265             rec->setPaintGamma(gamma);
266
267             rec->setContrast(defaultRenderingParams->GetEnhancedContrast());
268         }
269     }
270 #endif
271 }
272
273 ///////////////////////////////////////////////////////////////////////////////
274 //PDF Support
275
276 using namespace skia_advanced_typeface_metrics_utils;
277
278 // Construct Glyph to Unicode table.
279 // Unicode code points that require conjugate pairs in utf16 are not
280 // supported.
281 // TODO(arthurhsu): Add support for conjugate pairs. It looks like that may
282 // require parsing the TTF cmap table (platform 4, encoding 12) directly instead
283 // of calling GetFontUnicodeRange().
284 // TODO(bungeman): This never does what anyone wants.
285 // What is really wanted is the text to glyphs mapping
286 static void populate_glyph_to_unicode(IDWriteFontFace* fontFace,
287                                       const unsigned glyphCount,
288                                       SkTDArray<SkUnichar>* glyphToUnicode) {
289     HRESULT hr = S_OK;
290
291     //Do this like free type instead
292     UINT32 count = 0;
293     for (UINT32 c = 0; c < 0x10FFFF; ++c) {
294         UINT16 glyph;
295         hr = fontFace->GetGlyphIndices(&c, 1, &glyph);
296         if (glyph > 0) {
297             ++count;
298         }
299     }
300
301     SkAutoTArray<UINT32> chars(count);
302     count = 0;
303     for (UINT32 c = 0; c < 0x10FFFF; ++c) {
304         UINT16 glyph;
305         hr = fontFace->GetGlyphIndices(&c, 1, &glyph);
306         if (glyph > 0) {
307             chars[count] = c;
308             ++count;
309         }
310     }
311
312     SkAutoTArray<UINT16> glyph(count);
313     fontFace->GetGlyphIndices(chars.get(), count, glyph.get());
314
315     USHORT maxGlyph = 0;
316     for (USHORT j = 0; j < count; ++j) {
317         if (glyph[j] > maxGlyph) maxGlyph = glyph[j];
318     }
319
320     glyphToUnicode->setCount(maxGlyph+1);
321     for (USHORT j = 0; j < maxGlyph+1u; ++j) {
322         (*glyphToUnicode)[j] = 0;
323     }
324
325     //'invert'
326     for (USHORT j = 0; j < count; ++j) {
327         if (glyph[j] < glyphCount && (*glyphToUnicode)[glyph[j]] == 0) {
328             (*glyphToUnicode)[glyph[j]] = chars[j];
329         }
330     }
331 }
332
333 static bool getWidthAdvance(IDWriteFontFace* fontFace, int gId, int16_t* advance) {
334     SkASSERT(advance);
335
336     UINT16 glyphId = gId;
337     DWRITE_GLYPH_METRICS gm;
338     HRESULT hr = fontFace->GetDesignGlyphMetrics(&glyphId, 1, &gm);
339
340     if (FAILED(hr)) {
341         *advance = 0;
342         return false;
343     }
344
345     *advance = gm.advanceWidth;
346     return true;
347 }
348
349 SkAdvancedTypefaceMetrics* DWriteFontTypeface::onGetAdvancedTypefaceMetrics(
350         SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo,
351         const uint32_t* glyphIDs,
352         uint32_t glyphIDsCount) const {
353
354     SkAdvancedTypefaceMetrics* info = NULL;
355
356     HRESULT hr = S_OK;
357
358     const unsigned glyphCount = fDWriteFontFace->GetGlyphCount();
359
360     DWRITE_FONT_METRICS dwfm;
361     fDWriteFontFace->GetMetrics(&dwfm);
362
363     info = new SkAdvancedTypefaceMetrics;
364     info->fEmSize = dwfm.designUnitsPerEm;
365     info->fLastGlyphID = SkToU16(glyphCount - 1);
366     info->fStyle = 0;
367     info->fFlags = SkAdvancedTypefaceMetrics::kEmpty_FontFlag;
368
369     // SkAdvancedTypefaceMetrics::fFontName is in theory supposed to be
370     // the PostScript name of the font. However, due to the way it is currently
371     // used, it must actually be a family name.
372     SkTScopedComPtr<IDWriteLocalizedStrings> familyNames;
373     hr = fDWriteFontFamily->GetFamilyNames(&familyNames);
374
375     UINT32 familyNameLength;
376     hr = familyNames->GetStringLength(0, &familyNameLength);
377
378     UINT32 size = familyNameLength+1;
379     SkSMallocWCHAR wFamilyName(size);
380     hr = familyNames->GetString(0, wFamilyName.get(), size);
381
382     hr = sk_wchar_to_skstring(wFamilyName.get(), &info->fFontName);
383
384     if (perGlyphInfo & SkAdvancedTypefaceMetrics::kToUnicode_PerGlyphInfo) {
385         populate_glyph_to_unicode(fDWriteFontFace.get(), glyphCount, &(info->fGlyphToUnicode));
386     }
387
388     DWRITE_FONT_FACE_TYPE fontType = fDWriteFontFace->GetType();
389     if (fontType == DWRITE_FONT_FACE_TYPE_TRUETYPE ||
390         fontType == DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION) {
391         info->fType = SkAdvancedTypefaceMetrics::kTrueType_Font;
392     } else {
393         info->fType = SkAdvancedTypefaceMetrics::kOther_Font;
394         info->fItalicAngle = 0;
395         info->fAscent = dwfm.ascent;;
396         info->fDescent = dwfm.descent;
397         info->fStemV = 0;
398         info->fCapHeight = dwfm.capHeight;
399         info->fBBox = SkIRect::MakeEmpty();
400         return info;
401     }
402
403     AutoTDWriteTable<SkOTTableHead> headTable(fDWriteFontFace.get());
404     AutoTDWriteTable<SkOTTablePostScript> postTable(fDWriteFontFace.get());
405     AutoTDWriteTable<SkOTTableHorizontalHeader> hheaTable(fDWriteFontFace.get());
406     AutoTDWriteTable<SkOTTableOS2> os2Table(fDWriteFontFace.get());
407     if (!headTable.fExists || !postTable.fExists || !hheaTable.fExists || !os2Table.fExists) {
408         info->fItalicAngle = 0;
409         info->fAscent = dwfm.ascent;;
410         info->fDescent = dwfm.descent;
411         info->fStemV = 0;
412         info->fCapHeight = dwfm.capHeight;
413         info->fBBox = SkIRect::MakeEmpty();
414         return info;
415     }
416
417     //There exist CJK fonts which set the IsFixedPitch and Monospace bits,
418     //but have full width, latin half-width, and half-width kana.
419     bool fixedWidth = (postTable->isFixedPitch &&
420                       (1 == SkEndian_SwapBE16(hheaTable->numberOfHMetrics)));
421     //Monospace
422     if (fixedWidth) {
423         info->fStyle |= SkAdvancedTypefaceMetrics::kFixedPitch_Style;
424     }
425     //Italic
426     if (os2Table->version.v0.fsSelection.field.Italic) {
427         info->fStyle |= SkAdvancedTypefaceMetrics::kItalic_Style;
428     }
429     //Script
430     if (SkPanose::FamilyType::Script == os2Table->version.v0.panose.bFamilyType.value) {
431         info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style;
432     //Serif
433     } else if (SkPanose::FamilyType::TextAndDisplay == os2Table->version.v0.panose.bFamilyType.value &&
434                SkPanose::Data::TextAndDisplay::SerifStyle::Triangle <= os2Table->version.v0.panose.data.textAndDisplay.bSerifStyle.value &&
435                SkPanose::Data::TextAndDisplay::SerifStyle::NoFit != os2Table->version.v0.panose.data.textAndDisplay.bSerifStyle.value) {
436         info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style;
437     }
438
439     info->fItalicAngle = SkEndian_SwapBE32(postTable->italicAngle) >> 16;
440
441     info->fAscent = SkToS16(dwfm.ascent);
442     info->fDescent = SkToS16(dwfm.descent);
443     info->fCapHeight = SkToS16(dwfm.capHeight);
444
445     info->fBBox = SkIRect::MakeLTRB((int32_t)SkEndian_SwapBE16((uint16_t)headTable->xMin),
446                                     (int32_t)SkEndian_SwapBE16((uint16_t)headTable->yMax),
447                                     (int32_t)SkEndian_SwapBE16((uint16_t)headTable->xMax),
448                                     (int32_t)SkEndian_SwapBE16((uint16_t)headTable->yMin));
449
450     //TODO: is this even desired? It seems PDF only wants this value for Type1
451     //fonts, and we only get here for TrueType fonts.
452     info->fStemV = 0;
453     /*
454     // Figure out a good guess for StemV - Min width of i, I, !, 1.
455     // This probably isn't very good with an italic font.
456     int16_t min_width = SHRT_MAX;
457     info->fStemV = 0;
458     char stem_chars[] = {'i', 'I', '!', '1'};
459     for (size_t i = 0; i < SK_ARRAY_COUNT(stem_chars); i++) {
460         ABC abcWidths;
461         if (GetCharABCWidths(hdc, stem_chars[i], stem_chars[i], &abcWidths)) {
462             int16_t width = abcWidths.abcB;
463             if (width > 0 && width < min_width) {
464                 min_width = width;
465                 info->fStemV = min_width;
466             }
467         }
468     }
469     */
470
471     if (perGlyphInfo & SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo) {
472         if (fixedWidth) {
473             appendRange(&info->fGlyphWidths, 0);
474             int16_t advance;
475             getWidthAdvance(fDWriteFontFace.get(), 1, &advance);
476             info->fGlyphWidths->fAdvance.append(1, &advance);
477             finishRange(info->fGlyphWidths.get(), 0,
478                         SkAdvancedTypefaceMetrics::WidthRange::kDefault);
479         } else {
480             info->fGlyphWidths.reset(
481                 getAdvanceData(fDWriteFontFace.get(),
482                                glyphCount,
483                                glyphIDs,
484                                glyphIDsCount,
485                                getWidthAdvance));
486         }
487     }
488
489     return info;
490 }