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 #include "src/utils/win/SkDWriteNTDDI_VERSION.h"
8
9 #include "include/core/SkTypes.h"
10 #if defined(SK_BUILD_FOR_WIN)
11
12 // SkTypes will include Windows.h, which will pull in all of the GDI defines.
13 // GDI #defines GetGlyphIndices to GetGlyphIndicesA or GetGlyphIndicesW, but
14 // IDWriteFontFace has a method called GetGlyphIndices. Since this file does
15 // not use GDI, undefing GetGlyphIndices makes things less confusing.
16 #undef GetGlyphIndices
17
18 #include "include/core/SkData.h"
19 #include "include/private/SkTo.h"
20 #include "src/core/SkFontDescriptor.h"
21 #include "src/core/SkFontStream.h"
22 #include "src/core/SkScalerContext.h"
23 #include "src/core/SkUtils.h"
24 #include "src/ports/SkScalerContext_win_dw.h"
25 #include "src/ports/SkTypeface_win_dw.h"
26 #include "src/sfnt/SkOTTable_OS_2.h"
27 #include "src/sfnt/SkOTTable_fvar.h"
28 #include "src/sfnt/SkOTTable_head.h"
29 #include "src/sfnt/SkOTTable_hhea.h"
30 #include "src/sfnt/SkOTTable_post.h"
31 #include "src/sfnt/SkOTUtils.h"
32 #include "src/utils/win/SkDWrite.h"
33 #include "src/utils/win/SkDWriteFontFileStream.h"
34
onGetFamilyName(SkString * familyName) const35 void DWriteFontTypeface::onGetFamilyName(SkString* familyName) const {
36 SkTScopedComPtr<IDWriteLocalizedStrings> familyNames;
37 HRV(fDWriteFontFamily->GetFamilyNames(&familyNames));
38
39 sk_get_locale_string(familyNames.get(), nullptr/*fMgr->fLocaleName.get()*/, familyName);
40 }
41
onGetFontDescriptor(SkFontDescriptor * desc,bool * isLocalStream) const42 void DWriteFontTypeface::onGetFontDescriptor(SkFontDescriptor* desc,
43 bool* isLocalStream) const {
44 // Get the family name.
45 SkTScopedComPtr<IDWriteLocalizedStrings> familyNames;
46 HRV(fDWriteFontFamily->GetFamilyNames(&familyNames));
47
48 SkString utf8FamilyName;
49 sk_get_locale_string(familyNames.get(), nullptr/*fMgr->fLocaleName.get()*/, &utf8FamilyName);
50
51 desc->setFamilyName(utf8FamilyName.c_str());
52 desc->setStyle(this->fontStyle());
53 *isLocalStream = SkToBool(fDWriteFontFileLoader.get());
54 }
55
onCharsToGlyphs(const SkUnichar uni[],int count,SkGlyphID glyphs[]) const56 void DWriteFontTypeface::onCharsToGlyphs(const SkUnichar uni[], int count,
57 SkGlyphID glyphs[]) const {
58 fDWriteFontFace->GetGlyphIndices((const UINT32*)uni, count, glyphs);
59 }
60
onCountGlyphs() const61 int DWriteFontTypeface::onCountGlyphs() const {
62 return fDWriteFontFace->GetGlyphCount();
63 }
64
getPostScriptGlyphNames(SkString *) const65 void DWriteFontTypeface::getPostScriptGlyphNames(SkString*) const {}
66
onGetUPEM() const67 int DWriteFontTypeface::onGetUPEM() const {
68 DWRITE_FONT_METRICS metrics;
69 fDWriteFontFace->GetMetrics(&metrics);
70 return metrics.designUnitsPerEm;
71 }
72
73 class LocalizedStrings_IDWriteLocalizedStrings : public SkTypeface::LocalizedStrings {
74 public:
75 /** Takes ownership of the IDWriteLocalizedStrings. */
LocalizedStrings_IDWriteLocalizedStrings(IDWriteLocalizedStrings * strings)76 explicit LocalizedStrings_IDWriteLocalizedStrings(IDWriteLocalizedStrings* strings)
77 : fIndex(0), fStrings(strings)
78 { }
79
next(SkTypeface::LocalizedString * localizedString)80 bool next(SkTypeface::LocalizedString* localizedString) override {
81 if (fIndex >= fStrings->GetCount()) {
82 return false;
83 }
84
85 // String
86 UINT32 stringLen;
87 HRBM(fStrings->GetStringLength(fIndex, &stringLen), "Could not get string length.");
88
89 SkSMallocWCHAR wString(stringLen+1);
90 HRBM(fStrings->GetString(fIndex, wString.get(), stringLen+1), "Could not get string.");
91
92 HRB(sk_wchar_to_skstring(wString.get(), stringLen, &localizedString->fString));
93
94 // Locale
95 UINT32 localeLen;
96 HRBM(fStrings->GetLocaleNameLength(fIndex, &localeLen), "Could not get locale length.");
97
98 SkSMallocWCHAR wLocale(localeLen+1);
99 HRBM(fStrings->GetLocaleName(fIndex, wLocale.get(), localeLen+1), "Could not get locale.");
100
101 HRB(sk_wchar_to_skstring(wLocale.get(), localeLen, &localizedString->fLanguage));
102
103 ++fIndex;
104 return true;
105 }
106
107 private:
108 UINT32 fIndex;
109 SkTScopedComPtr<IDWriteLocalizedStrings> fStrings;
110 };
111
onCreateFamilyNameIterator() const112 SkTypeface::LocalizedStrings* DWriteFontTypeface::onCreateFamilyNameIterator() const {
113 sk_sp<SkTypeface::LocalizedStrings> nameIter =
114 SkOTUtils::LocalizedStrings_NameTable::MakeForFamilyNames(*this);
115 if (!nameIter) {
116 SkTScopedComPtr<IDWriteLocalizedStrings> familyNames;
117 HRNM(fDWriteFontFamily->GetFamilyNames(&familyNames), "Could not obtain family names.");
118 nameIter = sk_make_sp<LocalizedStrings_IDWriteLocalizedStrings>(familyNames.release());
119 }
120 return nameIter.release();
121 }
122
onGetVariationDesignPosition(SkFontArguments::VariationPosition::Coordinate coordinates[],int coordinateCount) const123 int DWriteFontTypeface::onGetVariationDesignPosition(
124 SkFontArguments::VariationPosition::Coordinate coordinates[], int coordinateCount) const
125 {
126
127 #if defined(NTDDI_WIN10_RS3) && NTDDI_VERSION >= NTDDI_WIN10_RS3
128
129 SkTScopedComPtr<IDWriteFontFace5> fontFace5;
130 if (FAILED(fDWriteFontFace->QueryInterface(&fontFace5))) {
131 return -1;
132 }
133
134 // Return 0 if the font is not variable font.
135 if (!fontFace5->HasVariations()) {
136 return 0;
137 }
138
139 UINT32 fontAxisCount = fontFace5->GetFontAxisValueCount();
140 SkTScopedComPtr<IDWriteFontResource> fontResource;
141 HR_GENERAL(fontFace5->GetFontResource(&fontResource), nullptr, -1);
142 UINT32 variableAxisCount = 0;
143 for (UINT32 i = 0; i < fontAxisCount; ++i) {
144 if (fontResource->GetFontAxisAttributes(i) & DWRITE_FONT_AXIS_ATTRIBUTES_VARIABLE) {
145 ++variableAxisCount;
146 }
147 }
148
149 if (!coordinates || coordinateCount < 0 || (unsigned)coordinateCount < variableAxisCount) {
150 return SkTo<int>(variableAxisCount);
151 }
152
153 SkAutoSTMalloc<8, DWRITE_FONT_AXIS_VALUE> fontAxisValue(fontAxisCount);
154 HR_GENERAL(fontFace5->GetFontAxisValues(fontAxisValue.get(), fontAxisCount), nullptr, -1);
155 UINT32 coordIndex = 0;
156 for (UINT32 axisIndex = 0; axisIndex < fontAxisCount; ++axisIndex) {
157 if (fontResource->GetFontAxisAttributes(axisIndex) & DWRITE_FONT_AXIS_ATTRIBUTES_VARIABLE) {
158 coordinates[coordIndex].axis = SkEndian_SwapBE32(fontAxisValue[axisIndex].axisTag);
159 coordinates[coordIndex].value = fontAxisValue[axisIndex].value;
160 ++coordIndex;
161 }
162 }
163
164 SkASSERT(coordIndex == variableAxisCount);
165 return SkTo<int>(variableAxisCount);
166
167 #endif
168
169 return -1;
170 }
171
onGetVariationDesignParameters(SkFontParameters::Variation::Axis parameters[],int parameterCount) const172 int DWriteFontTypeface::onGetVariationDesignParameters(
173 SkFontParameters::Variation::Axis parameters[], int parameterCount) const
174 {
175
176 #if defined(NTDDI_WIN10_RS3) && NTDDI_VERSION >= NTDDI_WIN10_RS3
177
178 SkTScopedComPtr<IDWriteFontFace5> fontFace5;
179 if (FAILED(fDWriteFontFace->QueryInterface(&fontFace5))) {
180 return -1;
181 }
182
183 // Return 0 if the font is not variable font.
184 if (!fontFace5->HasVariations()) {
185 return 0;
186 }
187
188 UINT32 fontAxisCount = fontFace5->GetFontAxisValueCount();
189 SkTScopedComPtr<IDWriteFontResource> fontResource;
190 HR_GENERAL(fontFace5->GetFontResource(&fontResource), nullptr, -1);
191 int variableAxisCount = 0;
192 for (UINT32 i = 0; i < fontAxisCount; ++i) {
193 if (fontResource->GetFontAxisAttributes(i) & DWRITE_FONT_AXIS_ATTRIBUTES_VARIABLE) {
194 variableAxisCount++;
195 }
196 }
197
198 if (!parameters || parameterCount < variableAxisCount) {
199 return variableAxisCount;
200 }
201
202 SkAutoSTMalloc<8, DWRITE_FONT_AXIS_RANGE> fontAxisRange(fontAxisCount);
203 HR_GENERAL(fontResource->GetFontAxisRanges(fontAxisRange.get(), fontAxisCount), nullptr, -1);
204 SkAutoSTMalloc<8, DWRITE_FONT_AXIS_VALUE> fontAxisDefaultValue(fontAxisCount);
205 HR_GENERAL(fontResource->GetDefaultFontAxisValues(fontAxisDefaultValue.get(), fontAxisCount),
206 nullptr, -1);
207 UINT32 coordIndex = 0;
208
209 for (UINT32 axisIndex = 0; axisIndex < fontAxisCount; ++axisIndex) {
210 if (fontResource->GetFontAxisAttributes(axisIndex) & DWRITE_FONT_AXIS_ATTRIBUTES_VARIABLE) {
211 parameters[coordIndex].tag = SkEndian_SwapBE32(fontAxisDefaultValue[axisIndex].axisTag);
212 parameters[coordIndex].min = fontAxisRange[axisIndex].minValue;
213 parameters[coordIndex].def = fontAxisDefaultValue[axisIndex].value;
214 parameters[coordIndex].max = fontAxisRange[axisIndex].maxValue;
215 parameters[coordIndex].setHidden(fontResource->GetFontAxisAttributes(axisIndex) &
216 DWRITE_FONT_AXIS_ATTRIBUTES_HIDDEN);
217 }
218 }
219
220 return variableAxisCount;
221
222 #endif
223
224 return -1;
225 }
226
onGetTableTags(SkFontTableTag tags[]) const227 int DWriteFontTypeface::onGetTableTags(SkFontTableTag tags[]) const {
228 DWRITE_FONT_FACE_TYPE type = fDWriteFontFace->GetType();
229 if (type != DWRITE_FONT_FACE_TYPE_CFF &&
230 type != DWRITE_FONT_FACE_TYPE_TRUETYPE &&
231 type != DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION)
232 {
233 return 0;
234 }
235
236 int ttcIndex;
237 std::unique_ptr<SkStreamAsset> stream = this->openStream(&ttcIndex);
238 return stream.get() ? SkFontStream::GetTableTags(stream.get(), ttcIndex, tags) : 0;
239 }
240
onGetTableData(SkFontTableTag tag,size_t offset,size_t length,void * data) const241 size_t DWriteFontTypeface::onGetTableData(SkFontTableTag tag, size_t offset,
242 size_t length, void* data) const
243 {
244 AutoDWriteTable table(fDWriteFontFace.get(), SkEndian_SwapBE32(tag));
245 if (!table.fExists) {
246 return 0;
247 }
248
249 if (offset > table.fSize) {
250 return 0;
251 }
252 size_t size = SkTMin(length, table.fSize - offset);
253 if (data) {
254 memcpy(data, table.fData + offset, size);
255 }
256
257 return size;
258 }
259
onCopyTableData(SkFontTableTag tag) const260 sk_sp<SkData> DWriteFontTypeface::onCopyTableData(SkFontTableTag tag) const {
261 const uint8_t* data;
262 UINT32 size;
263 void* lock;
264 BOOL exists;
265 fDWriteFontFace->TryGetFontTable(SkEndian_SwapBE32(tag),
266 reinterpret_cast<const void **>(&data), &size, &lock, &exists);
267 if (!exists) {
268 return nullptr;
269 }
270 struct Context {
271 Context(void* lock, IDWriteFontFace* face) : fLock(lock), fFontFace(SkRefComPtr(face)) {}
272 ~Context() { fFontFace->ReleaseFontTable(fLock); }
273 void* fLock;
274 SkTScopedComPtr<IDWriteFontFace> fFontFace;
275 };
276 return SkData::MakeWithProc(data, size,
277 [](const void*, void* ctx) { delete (Context*)ctx; },
278 new Context(lock, fDWriteFontFace.get()));
279 }
280
onMakeClone(const SkFontArguments & args) const281 sk_sp<SkTypeface> DWriteFontTypeface::onMakeClone(const SkFontArguments& args) const {
282 // Skip if the current face index does not match the ttcIndex
283 if (fDWriteFontFace->GetIndex() != SkTo<UINT32>(args.getCollectionIndex())) {
284 return sk_ref_sp(this);
285 }
286
287 #if defined(NTDDI_WIN10_RS3) && NTDDI_VERSION >= NTDDI_WIN10_RS3
288
289 SkTScopedComPtr<IDWriteFontFace5> fontFace5;
290
291 if (SUCCEEDED(fDWriteFontFace->QueryInterface(&fontFace5)) && fontFace5->HasVariations()) {
292 UINT32 fontAxisCount = fontFace5->GetFontAxisValueCount();
293 UINT32 argsCoordCount = args.getVariationDesignPosition().coordinateCount;
294 SkAutoSTMalloc<8, DWRITE_FONT_AXIS_VALUE> fontAxisValue(fontAxisCount);
295 HRN(fontFace5->GetFontAxisValues(fontAxisValue.get(), fontAxisCount));
296
297 for (UINT32 fontIndex = 0; fontIndex < fontAxisCount; ++fontIndex) {
298 for (UINT32 argsIndex = 0; argsIndex < argsCoordCount; ++argsIndex) {
299 if (SkEndian_SwapBE32(fontAxisValue[fontIndex].axisTag) ==
300 args.getVariationDesignPosition().coordinates[argsIndex].axis) {
301 fontAxisValue[fontIndex].value =
302 args.getVariationDesignPosition().coordinates[argsIndex].value;
303 }
304 }
305 }
306 SkTScopedComPtr<IDWriteFontResource> fontResource;
307 HRN(fontFace5->GetFontResource(&fontResource));
308 SkTScopedComPtr<IDWriteFontFace5> newFontFace5;
309 HRN(fontResource->CreateFontFace(fDWriteFont->GetSimulations(),
310 fontAxisValue.get(),
311 fontAxisCount,
312 &newFontFace5));
313
314 SkTScopedComPtr<IDWriteFontFace> newFontFace;
315 HRN(newFontFace5->QueryInterface(&newFontFace));
316 return DWriteFontTypeface::Make(fFactory.get(),
317 newFontFace.get(),
318 fDWriteFont.get(),
319 fDWriteFontFamily.get(),
320 fDWriteFontFileLoader.get(),
321 fDWriteFontCollectionLoader.get());
322 }
323
324 #endif
325
326 return sk_ref_sp(this);
327 }
328
onOpenStream(int * ttcIndex) const329 std::unique_ptr<SkStreamAsset> DWriteFontTypeface::onOpenStream(int* ttcIndex) const {
330 *ttcIndex = fDWriteFontFace->GetIndex();
331
332 UINT32 numFiles;
333 HRNM(fDWriteFontFace->GetFiles(&numFiles, nullptr),
334 "Could not get number of font files.");
335 if (numFiles != 1) {
336 return nullptr;
337 }
338
339 SkTScopedComPtr<IDWriteFontFile> fontFile;
340 HRNM(fDWriteFontFace->GetFiles(&numFiles, &fontFile), "Could not get font files.");
341
342 const void* fontFileKey;
343 UINT32 fontFileKeySize;
344 HRNM(fontFile->GetReferenceKey(&fontFileKey, &fontFileKeySize),
345 "Could not get font file reference key.");
346
347 SkTScopedComPtr<IDWriteFontFileLoader> fontFileLoader;
348 HRNM(fontFile->GetLoader(&fontFileLoader), "Could not get font file loader.");
349
350 SkTScopedComPtr<IDWriteFontFileStream> fontFileStream;
351 HRNM(fontFileLoader->CreateStreamFromKey(fontFileKey, fontFileKeySize,
352 &fontFileStream),
353 "Could not create font file stream.");
354
355 return std::unique_ptr<SkStreamAsset>(new SkDWriteFontFileStream(fontFileStream.get()));
356 }
357
onCreateScalerContext(const SkScalerContextEffects & effects,const SkDescriptor * desc) const358 SkScalerContext* DWriteFontTypeface::onCreateScalerContext(const SkScalerContextEffects& effects,
359 const SkDescriptor* desc) const {
360 return new SkScalerContext_DW(sk_ref_sp(const_cast<DWriteFontTypeface*>(this)), effects, desc);
361 }
362
onFilterRec(SkScalerContextRec * rec) const363 void DWriteFontTypeface::onFilterRec(SkScalerContextRec* rec) const {
364 if (rec->fFlags & SkScalerContext::kLCD_Vertical_Flag) {
365 rec->fMaskFormat = SkMask::kA8_Format;
366 rec->fFlags |= SkScalerContext::kGenA8FromLCD_Flag;
367 }
368
369 unsigned flagsWeDontSupport = SkScalerContext::kForceAutohinting_Flag |
370 SkScalerContext::kEmbolden_Flag |
371 SkScalerContext::kLCD_Vertical_Flag;
372 rec->fFlags &= ~flagsWeDontSupport;
373
374 SkFontHinting h = rec->getHinting();
375 // DirectWrite2 allows for hinting to be turned off. Force everything else to normal.
376 if (h != SkFontHinting::kNone || !fFactory2 || !fDWriteFontFace2) {
377 h = SkFontHinting::kNormal;
378 }
379 rec->setHinting(h);
380
381 #if defined(SK_FONT_HOST_USE_SYSTEM_SETTINGS)
382 IDWriteFactory* factory = sk_get_dwrite_factory();
383 if (factory != nullptr) {
384 SkTScopedComPtr<IDWriteRenderingParams> defaultRenderingParams;
385 if (SUCCEEDED(factory->CreateRenderingParams(&defaultRenderingParams))) {
386 float gamma = defaultRenderingParams->GetGamma();
387 rec->setDeviceGamma(gamma);
388 rec->setPaintGamma(gamma);
389
390 rec->setContrast(defaultRenderingParams->GetEnhancedContrast());
391 }
392 }
393 #elif defined(MOZ_SKIA)
394 rec->setContrast(fContrast);
395
396 rec->setDeviceGamma(fGamma);
397 rec->setPaintGamma(fGamma);
398 #endif
399 }
400
401 ///////////////////////////////////////////////////////////////////////////////
402 //PDF Support
403
getGlyphToUnicodeMap(SkUnichar * glyphToUnicode) const404 void DWriteFontTypeface::getGlyphToUnicodeMap(SkUnichar* glyphToUnicode) const {
405 unsigned glyphCount = fDWriteFontFace->GetGlyphCount();
406 sk_bzero(glyphToUnicode, sizeof(SkUnichar) * glyphCount);
407 IDWriteFontFace* fontFace = fDWriteFontFace.get();
408 int maxGlyph = -1;
409 unsigned remainingGlyphCount = glyphCount;
410 for (UINT32 c = 0; c < 0x10FFFF && remainingGlyphCount != 0; ++c) {
411 UINT16 glyph = 0;
412 HRVM(fontFace->GetGlyphIndices(&c, 1, &glyph), "Failed to get glyph index.");
413 // Intermittent DW bug on Windows 10. See crbug.com/470146.
414 if (glyph >= glyphCount) {
415 return;
416 }
417 if (0 < glyph && glyphToUnicode[glyph] == 0) {
418 maxGlyph = SkTMax(static_cast<int>(glyph), maxGlyph);
419 glyphToUnicode[glyph] = c; // Always use lowest-index unichar.
420 --remainingGlyphCount;
421 }
422 }
423 }
424
onGetAdvancedMetrics() const425 std::unique_ptr<SkAdvancedTypefaceMetrics> DWriteFontTypeface::onGetAdvancedMetrics() const {
426
427 std::unique_ptr<SkAdvancedTypefaceMetrics> info(nullptr);
428
429 DWRITE_FONT_METRICS dwfm;
430 fDWriteFontFace->GetMetrics(&dwfm);
431
432 info.reset(new SkAdvancedTypefaceMetrics);
433
434 info->fAscent = SkToS16(dwfm.ascent);
435 info->fDescent = SkToS16(dwfm.descent);
436 info->fCapHeight = SkToS16(dwfm.capHeight);
437
438 {
439 SkTScopedComPtr<IDWriteLocalizedStrings> postScriptNames;
440 BOOL exists = FALSE;
441 if (FAILED(fDWriteFont->GetInformationalStrings(
442 DWRITE_INFORMATIONAL_STRING_POSTSCRIPT_NAME,
443 &postScriptNames,
444 &exists)) ||
445 !exists ||
446 FAILED(sk_get_locale_string(postScriptNames.get(), nullptr, &info->fPostScriptName)))
447 {
448 SkDEBUGF("Unable to get postscript name for typeface %p\n", this);
449 }
450 }
451
452 // SkAdvancedTypefaceMetrics::fFontName must actually be a family name.
453 SkTScopedComPtr<IDWriteLocalizedStrings> familyNames;
454 if (FAILED(fDWriteFontFamily->GetFamilyNames(&familyNames)) ||
455 FAILED(sk_get_locale_string(familyNames.get(), nullptr, &info->fFontName)))
456 {
457 SkDEBUGF("Unable to get family name for typeface 0x%p\n", this);
458 }
459 if (info->fPostScriptName.isEmpty()) {
460 info->fPostScriptName = info->fFontName;
461 }
462
463 DWRITE_FONT_FACE_TYPE fontType = fDWriteFontFace->GetType();
464 if (fontType != DWRITE_FONT_FACE_TYPE_TRUETYPE &&
465 fontType != DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION)
466 {
467 return info;
468 }
469
470 // Simulated fonts aren't really TrueType fonts.
471 if (fDWriteFontFace->GetSimulations() == DWRITE_FONT_SIMULATIONS_NONE) {
472 info->fType = SkAdvancedTypefaceMetrics::kTrueType_Font;
473 }
474
475 AutoTDWriteTable<SkOTTableHead> headTable(fDWriteFontFace.get());
476 AutoTDWriteTable<SkOTTablePostScript> postTable(fDWriteFontFace.get());
477 AutoTDWriteTable<SkOTTableHorizontalHeader> hheaTable(fDWriteFontFace.get());
478 AutoTDWriteTable<SkOTTableOS2> os2Table(fDWriteFontFace.get());
479 if (!headTable.fExists || !postTable.fExists || !hheaTable.fExists || !os2Table.fExists) {
480 return info;
481 }
482
483 SkOTUtils::SetAdvancedTypefaceFlags(os2Table->version.v4.fsType, info.get());
484
485 // There are versions of DirectWrite which support named instances for system variation fonts,
486 // but no means to indicate that such a typeface is a variation.
487 AutoTDWriteTable<SkOTTableFontVariations> fvarTable(fDWriteFontFace.get());
488 if (fvarTable.fExists) {
489 info->fFlags |= SkAdvancedTypefaceMetrics::kMultiMaster_FontFlag;
490 }
491
492 //There exist CJK fonts which set the IsFixedPitch and Monospace bits,
493 //but have full width, latin half-width, and half-width kana.
494 bool fixedWidth = (postTable->isFixedPitch &&
495 (1 == SkEndian_SwapBE16(hheaTable->numberOfHMetrics)));
496 //Monospace
497 if (fixedWidth) {
498 info->fStyle |= SkAdvancedTypefaceMetrics::kFixedPitch_Style;
499 }
500 //Italic
501 if (os2Table->version.v0.fsSelection.field.Italic) {
502 info->fStyle |= SkAdvancedTypefaceMetrics::kItalic_Style;
503 }
504 //Serif
505 using SerifStyle = SkPanose::Data::TextAndDisplay::SerifStyle;
506 SerifStyle serifStyle = os2Table->version.v0.panose.data.textAndDisplay.bSerifStyle;
507 if (SkPanose::FamilyType::TextAndDisplay == os2Table->version.v0.panose.bFamilyType) {
508 if (SerifStyle::Cove == serifStyle ||
509 SerifStyle::ObtuseCove == serifStyle ||
510 SerifStyle::SquareCove == serifStyle ||
511 SerifStyle::ObtuseSquareCove == serifStyle ||
512 SerifStyle::Square == serifStyle ||
513 SerifStyle::Thin == serifStyle ||
514 SerifStyle::Bone == serifStyle ||
515 SerifStyle::Exaggerated == serifStyle ||
516 SerifStyle::Triangle == serifStyle)
517 {
518 info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style;
519 }
520 //Script
521 } else if (SkPanose::FamilyType::Script == os2Table->version.v0.panose.bFamilyType) {
522 info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style;
523 }
524
525 info->fItalicAngle = SkEndian_SwapBE32(postTable->italicAngle) >> 16;
526
527 info->fBBox = SkIRect::MakeLTRB((int32_t)SkEndian_SwapBE16((uint16_t)headTable->xMin),
528 (int32_t)SkEndian_SwapBE16((uint16_t)headTable->yMax),
529 (int32_t)SkEndian_SwapBE16((uint16_t)headTable->xMax),
530 (int32_t)SkEndian_SwapBE16((uint16_t)headTable->yMin));
531 return info;
532 }
533 #endif//defined(SK_BUILD_FOR_WIN)
534