void runTest(skiatest::Reporter* reporter) { SkAdvancedTypefaceMetrics metrics; metrics.setGlyphWidths( fAdvancesLen, fSubset, fSubsetLen, std::function<bool(int, int16_t*)>([this](int gId, int16_t* advance) { if (gId >= 0 && gId < fAdvancesLen) { *advance = fAdvances[gId]; return true; } return false; })); SkString stringResult = stringify_advance_data(metrics.fGlyphWidths); if (!stringResult.equals(fExpected)) { ERRORF(reporter, "Expected: %s\n Result: %s\n", fExpected, stringResult.c_str()); } }
SkAdvancedTypefaceMetrics* DWriteFontTypeface::onGetAdvancedTypefaceMetrics( PerGlyphInfo perGlyphInfo, const uint32_t* glyphIDs, uint32_t glyphIDsCount) const { SkAdvancedTypefaceMetrics* info = nullptr; HRESULT hr = S_OK; const unsigned glyphCount = fDWriteFontFace->GetGlyphCount(); DWRITE_FONT_METRICS dwfm; fDWriteFontFace->GetMetrics(&dwfm); info = new SkAdvancedTypefaceMetrics; info->fEmSize = dwfm.designUnitsPerEm; info->fLastGlyphID = SkToU16(glyphCount - 1); // SkAdvancedTypefaceMetrics::fFontName is in theory supposed to be // the PostScript name of the font. However, due to the way it is currently // used, it must actually be a family name. SkTScopedComPtr<IDWriteLocalizedStrings> familyNames; hr = fDWriteFontFamily->GetFamilyNames(&familyNames); UINT32 familyNameLen; hr = familyNames->GetStringLength(0, &familyNameLen); SkSMallocWCHAR familyName(familyNameLen+1); hr = familyNames->GetString(0, familyName.get(), familyNameLen+1); hr = sk_wchar_to_skstring(familyName.get(), familyNameLen, &info->fFontName); if (perGlyphInfo & kToUnicode_PerGlyphInfo) { populate_glyph_to_unicode(fDWriteFontFace.get(), glyphCount, &(info->fGlyphToUnicode)); } DWRITE_FONT_FACE_TYPE fontType = fDWriteFontFace->GetType(); if (fontType == DWRITE_FONT_FACE_TYPE_TRUETYPE || fontType == DWRITE_FONT_FACE_TYPE_TRUETYPE_COLLECTION) { info->fType = SkAdvancedTypefaceMetrics::kTrueType_Font; } else { info->fAscent = dwfm.ascent; info->fDescent = dwfm.descent; info->fCapHeight = dwfm.capHeight; return info; } AutoTDWriteTable<SkOTTableHead> headTable(fDWriteFontFace.get()); AutoTDWriteTable<SkOTTablePostScript> postTable(fDWriteFontFace.get()); AutoTDWriteTable<SkOTTableHorizontalHeader> hheaTable(fDWriteFontFace.get()); AutoTDWriteTable<SkOTTableOS2> os2Table(fDWriteFontFace.get()); if (!headTable.fExists || !postTable.fExists || !hheaTable.fExists || !os2Table.fExists) { info->fAscent = dwfm.ascent; info->fDescent = dwfm.descent; info->fCapHeight = dwfm.capHeight; return info; } //There exist CJK fonts which set the IsFixedPitch and Monospace bits, //but have full width, latin half-width, and half-width kana. bool fixedWidth = (postTable->isFixedPitch && (1 == SkEndian_SwapBE16(hheaTable->numberOfHMetrics))); //Monospace if (fixedWidth) { info->fStyle |= SkAdvancedTypefaceMetrics::kFixedPitch_Style; } //Italic if (os2Table->version.v0.fsSelection.field.Italic) { info->fStyle |= SkAdvancedTypefaceMetrics::kItalic_Style; } //Script if (SkPanose::FamilyType::Script == os2Table->version.v0.panose.bFamilyType.value) { info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style; //Serif } else if (SkPanose::FamilyType::TextAndDisplay == os2Table->version.v0.panose.bFamilyType.value && SkPanose::Data::TextAndDisplay::SerifStyle::Triangle <= os2Table->version.v0.panose.data.textAndDisplay.bSerifStyle.value && SkPanose::Data::TextAndDisplay::SerifStyle::NoFit != os2Table->version.v0.panose.data.textAndDisplay.bSerifStyle.value) { info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style; } info->fItalicAngle = SkEndian_SwapBE32(postTable->italicAngle) >> 16; info->fAscent = SkToS16(dwfm.ascent); info->fDescent = SkToS16(dwfm.descent); info->fCapHeight = SkToS16(dwfm.capHeight); info->fBBox = SkIRect::MakeLTRB((int32_t)SkEndian_SwapBE16((uint16_t)headTable->xMin), (int32_t)SkEndian_SwapBE16((uint16_t)headTable->yMax), (int32_t)SkEndian_SwapBE16((uint16_t)headTable->xMax), (int32_t)SkEndian_SwapBE16((uint16_t)headTable->yMin)); //TODO: is this even desired? It seems PDF only wants this value for Type1 //fonts, and we only get here for TrueType fonts. info->fStemV = 0; /* // Figure out a good guess for StemV - Min width of i, I, !, 1. // This probably isn't very good with an italic font. int16_t min_width = SHRT_MAX; info->fStemV = 0; char stem_chars[] = {'i', 'I', '!', '1'}; for (size_t i = 0; i < SK_ARRAY_COUNT(stem_chars); i++) { ABC abcWidths; if (GetCharABCWidths(hdc, stem_chars[i], stem_chars[i], &abcWidths)) { int16_t width = abcWidths.abcB; if (width > 0 && width < min_width) { min_width = width; info->fStemV = min_width; } } } */ if (perGlyphInfo & kHAdvance_PerGlyphInfo) { if (fixedWidth) { SkAdvancedTypefaceMetrics::WidthRange range(0); int16_t advance; getWidthAdvance(fDWriteFontFace.get(), 1, &advance); range.fAdvance.append(1, &advance); SkAdvancedTypefaceMetrics::FinishRange( &range, 0, SkAdvancedTypefaceMetrics::WidthRange::kDefault); info->fGlyphWidths.emplace_back(std::move(range)); } else { IDWriteFontFace* borrowedFontFace = fDWriteFontFace.get(); info->setGlyphWidths( glyphCount, glyphIDs, glyphIDsCount, SkAdvancedTypefaceMetrics::GetAdvance([borrowedFontFace](int gId, int16_t* data) { return getWidthAdvance(borrowedFontFace, gId, data); }) ); } } return info; }