in tools/fonts/TestSVGTypeface.cpp [444:774]
void TestSVGTypeface::exportTtxCommon(SkWStream* out,
const char* type,
const TArray<GlyfInfo>* glyfInfo) const {
int totalGlyphs = fGlyphCount;
out->writeText(" <GlyphOrder>\n");
for (int i = 0; i < fGlyphCount; ++i) {
out->writeText(" <GlyphID name=\"glyf");
out->writeHexAsText(i, 4);
out->writeText("\"/>\n");
}
if (glyfInfo) {
for (int i = 0; i < fGlyphCount; ++i) {
for (int j = 0; j < (*glyfInfo)[i].fLayers.size(); ++j) {
out->writeText(" <GlyphID name=\"glyf");
out->writeHexAsText(i, 4);
out->writeText("l");
out->writeHexAsText(j, 4);
out->writeText("\"/>\n");
++totalGlyphs;
}
}
}
out->writeText(" </GlyphOrder>\n");
out->writeText(" <head>\n");
out->writeText(" <tableVersion value=\"1.0\"/>\n");
out->writeText(" <fontRevision value=\"1.0\"/>\n");
out->writeText(" <checkSumAdjustment value=\"0xa9c3274\"/>\n");
out->writeText(" <magicNumber value=\"0x5f0f3cf5\"/>\n");
out->writeText(" <flags value=\"00000000 00011011\"/>\n");
out->writeText(" <unitsPerEm value=\"");
out->writeDecAsText(fUpem);
out->writeText("\"/>\n");
out->writeText(" <created value=\"Thu Feb 15 12:55:49 2018\"/>\n");
out->writeText(" <modified value=\"Thu Feb 15 12:55:49 2018\"/>\n");
// TODO: not recalculated for bitmap fonts?
out->writeText(" <xMin value=\"");
out->writeScalarAsText(fFontMetrics.fXMin);
out->writeText("\"/>\n");
out->writeText(" <yMin value=\"");
out->writeScalarAsText(-fFontMetrics.fBottom);
out->writeText("\"/>\n");
out->writeText(" <xMax value=\"");
out->writeScalarAsText(fFontMetrics.fXMax);
out->writeText("\"/>\n");
out->writeText(" <yMax value=\"");
out->writeScalarAsText(-fFontMetrics.fTop);
out->writeText("\"/>\n");
char macStyle[16] = {
'0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'};
if (this->fontStyle().weight() >= SkFontStyle::Bold().weight()) {
macStyle[0xF - 0x0] = '1'; // Bold
}
switch (this->fontStyle().slant()) {
case SkFontStyle::kUpright_Slant: break;
case SkFontStyle::kItalic_Slant:
macStyle[0xF - 0x1] = '1'; // Italic
break;
case SkFontStyle::kOblique_Slant:
macStyle[0xF - 0x1] = '1'; // Italic
break;
default: SK_ABORT("Unknown slant.");
}
if (this->fontStyle().width() <= SkFontStyle::kCondensed_Width) {
macStyle[0xF - 0x5] = '1'; // Condensed
} else if (this->fontStyle().width() >= SkFontStyle::kExpanded_Width) {
macStyle[0xF - 0x6] = '1'; // Extended
}
out->writeText(" <macStyle value=\"");
out->write(macStyle, 8);
out->writeText(" ");
out->write(macStyle + 8, 8);
out->writeText("\"/>\n");
out->writeText(" <lowestRecPPEM value=\"8\"/>\n");
out->writeText(" <fontDirectionHint value=\"2\"/>\n");
out->writeText(" <indexToLocFormat value=\"0\"/>\n");
out->writeText(" <glyphDataFormat value=\"0\"/>\n");
out->writeText(" </head>\n");
out->writeText(" <hhea>\n");
out->writeText(" <tableVersion value=\"0x00010000\"/>\n");
out->writeText(" <ascent value=\"");
out->writeDecAsText(-fFontMetrics.fAscent);
out->writeText("\"/>\n");
out->writeText(" <descent value=\"");
out->writeDecAsText(-fFontMetrics.fDescent);
out->writeText("\"/>\n");
out->writeText(" <lineGap value=\"");
out->writeDecAsText(fFontMetrics.fLeading);
out->writeText("\"/>\n");
out->writeText(" <advanceWidthMax value=\"0\"/>\n");
out->writeText(" <minLeftSideBearing value=\"0\"/>\n");
out->writeText(" <minRightSideBearing value=\"0\"/>\n");
out->writeText(" <xMaxExtent value=\"");
out->writeScalarAsText(fFontMetrics.fXMax - fFontMetrics.fXMin);
out->writeText("\"/>\n");
out->writeText(" <caretSlopeRise value=\"1\"/>\n");
out->writeText(" <caretSlopeRun value=\"0\"/>\n");
out->writeText(" <caretOffset value=\"0\"/>\n");
out->writeText(" <reserved0 value=\"0\"/>\n");
out->writeText(" <reserved1 value=\"0\"/>\n");
out->writeText(" <reserved2 value=\"0\"/>\n");
out->writeText(" <reserved3 value=\"0\"/>\n");
out->writeText(" <metricDataFormat value=\"0\"/>\n");
out->writeText(" <numberOfHMetrics value=\"0\"/>\n");
out->writeText(" </hhea>\n");
// Some of this table is going to be re-calculated, but we have to write it out anyway.
out->writeText(" <maxp>\n");
out->writeText(" <tableVersion value=\"0x10000\"/>\n");
out->writeText(" <numGlyphs value=\"");
out->writeDecAsText(totalGlyphs);
out->writeText("\"/>\n");
out->writeText(" <maxPoints value=\"4\"/>\n");
out->writeText(" <maxContours value=\"1\"/>\n");
out->writeText(" <maxCompositePoints value=\"0\"/>\n");
out->writeText(" <maxCompositeContours value=\"0\"/>\n");
out->writeText(" <maxZones value=\"1\"/>\n");
out->writeText(" <maxTwilightPoints value=\"0\"/>\n");
out->writeText(" <maxStorage value=\"0\"/>\n");
out->writeText(" <maxFunctionDefs value=\"10\"/>\n");
out->writeText(" <maxInstructionDefs value=\"0\"/>\n");
out->writeText(" <maxStackElements value=\"512\"/>\n");
out->writeText(" <maxSizeOfInstructions value=\"24\"/>\n");
out->writeText(" <maxComponentElements value=\"0\"/>\n");
out->writeText(" <maxComponentDepth value=\"0\"/>\n");
out->writeText(" </maxp>\n");
out->writeText(" <OS_2>\n");
out->writeText(" <version value=\"4\"/>\n");
out->writeText(" <xAvgCharWidth value=\"");
out->writeScalarAsText(fFontMetrics.fAvgCharWidth);
out->writeText("\"/>\n");
out->writeText(" <usWeightClass value=\"");
out->writeDecAsText(this->fontStyle().weight());
out->writeText("\"/>\n");
out->writeText(" <usWidthClass value=\"");
out->writeDecAsText(this->fontStyle().width());
out->writeText("\"/>\n");
out->writeText(" <fsType value=\"00000000 00000000\"/>\n");
out->writeText(" <ySubscriptXSize value=\"665\"/>\n");
out->writeText(" <ySubscriptYSize value=\"716\"/>\n");
out->writeText(" <ySubscriptXOffset value=\"0\"/>\n");
out->writeText(" <ySubscriptYOffset value=\"143\"/>\n");
out->writeText(" <ySuperscriptXSize value=\"665\"/>\n");
out->writeText(" <ySuperscriptYSize value=\"716\"/>\n");
out->writeText(" <ySuperscriptXOffset value=\"0\"/>\n");
out->writeText(" <ySuperscriptYOffset value=\"491\"/>\n");
out->writeText(" <yStrikeoutSize value=\"");
out->writeScalarAsText(fFontMetrics.fStrikeoutThickness);
out->writeText("\"/>\n");
out->writeText(" <yStrikeoutPosition value=\"");
out->writeScalarAsText(-fFontMetrics.fStrikeoutPosition);
out->writeText("\"/>\n");
out->writeText(" <sFamilyClass value=\"0\"/>\n");
out->writeText(" <panose>\n");
out->writeText(" <bFamilyType value=\"0\"/>\n");
out->writeText(" <bSerifStyle value=\"0\"/>\n");
out->writeText(" <bWeight value=\"0\"/>\n");
out->writeText(" <bProportion value=\"0\"/>\n");
out->writeText(" <bContrast value=\"0\"/>\n");
out->writeText(" <bStrokeVariation value=\"0\"/>\n");
out->writeText(" <bArmStyle value=\"0\"/>\n");
out->writeText(" <bLetterForm value=\"0\"/>\n");
out->writeText(" <bMidline value=\"0\"/>\n");
out->writeText(" <bXHeight value=\"0\"/>\n");
out->writeText(" </panose>\n");
out->writeText(" <ulUnicodeRange1 value=\"00000000 00000000 00000000 00000001\"/>\n");
out->writeText(" <ulUnicodeRange2 value=\"00010000 00000000 00000000 00000000\"/>\n");
out->writeText(" <ulUnicodeRange3 value=\"00000000 00000000 00000000 00000000\"/>\n");
out->writeText(" <ulUnicodeRange4 value=\"00000000 00000000 00000000 00000000\"/>\n");
out->writeText(" <achVendID value=\"Skia\"/>\n");
char fsSelection[16] = {
'0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'};
fsSelection[0xF - 0x7] = '1'; // Use typo metrics
if (this->fontStyle().weight() >= SkFontStyle::Bold().weight()) {
fsSelection[0xF - 0x5] = '1'; // Bold
}
switch (this->fontStyle().slant()) {
case SkFontStyle::kUpright_Slant:
if (this->fontStyle().weight() < SkFontStyle::Bold().weight()) {
fsSelection[0xF - 0x6] = '1'; // Not bold or italic, is regular
}
break;
case SkFontStyle::kItalic_Slant:
fsSelection[0xF - 0x0] = '1'; // Italic
break;
case SkFontStyle::kOblique_Slant:
fsSelection[0xF - 0x0] = '1'; // Italic
fsSelection[0xF - 0x9] = '1'; // Oblique
break;
default: SK_ABORT("Unknown slant.");
}
out->writeText(" <fsSelection value=\"");
out->write(fsSelection, 8);
out->writeText(" ");
out->write(fsSelection + 8, 8);
out->writeText("\"/>\n");
out->writeText(" <usFirstCharIndex value=\"0\"/>\n");
out->writeText(" <usLastCharIndex value=\"0\"/>\n");
out->writeText(" <sTypoAscender value=\"");
out->writeScalarAsText(-fFontMetrics.fAscent);
out->writeText("\"/>\n");
out->writeText(" <sTypoDescender value=\"");
out->writeScalarAsText(-fFontMetrics.fDescent);
out->writeText("\"/>\n");
out->writeText(" <sTypoLineGap value=\"");
out->writeScalarAsText(fFontMetrics.fLeading);
out->writeText("\"/>\n");
out->writeText(" <usWinAscent value=\"");
out->writeScalarAsText(-fFontMetrics.fAscent);
out->writeText("\"/>\n");
out->writeText(" <usWinDescent value=\"");
out->writeScalarAsText(fFontMetrics.fDescent);
out->writeText("\"/>\n");
out->writeText(" <ulCodePageRange1 value=\"00000000 00000000 00000000 00000000\"/>\n");
out->writeText(" <ulCodePageRange2 value=\"00000000 00000000 00000000 00000000\"/>\n");
out->writeText(" <sxHeight value=\"");
out->writeScalarAsText(fFontMetrics.fXHeight);
out->writeText("\"/>\n");
out->writeText(" <sCapHeight value=\"");
out->writeScalarAsText(fFontMetrics.fCapHeight);
out->writeText("\"/>\n");
out->writeText(" <usDefaultChar value=\"0\"/>\n");
out->writeText(" <usBreakChar value=\"32\"/>\n");
out->writeText(" <usMaxContext value=\"0\"/>\n");
out->writeText(" </OS_2>\n");
out->writeText(" <hmtx>\n");
for (int i = 0; i < fGlyphCount; ++i) {
out->writeText(" <mtx name=\"glyf");
out->writeHexAsText(i, 4);
out->writeText("\" width=\"");
out->writeDecAsText(fGlyphs[i].fAdvance);
out->writeText("\" lsb=\"");
int lsb = fGlyphs[i].fOrigin.fX;
if (glyfInfo) {
lsb += (*glyfInfo)[i].fBounds.fLeft;
}
out->writeDecAsText(lsb);
out->writeText("\"/>\n");
}
if (glyfInfo) {
for (int i = 0; i < fGlyphCount; ++i) {
for (int j = 0; j < (*glyfInfo)[i].fLayers.size(); ++j) {
out->writeText(" <mtx name=\"glyf");
out->writeHexAsText(i, 4);
out->writeText("l");
out->writeHexAsText(j, 4);
out->writeText("\" width=\"");
out->writeDecAsText(fGlyphs[i].fAdvance);
out->writeText("\" lsb=\"");
int32_t lsb = fGlyphs[i].fOrigin.fX + (*glyfInfo)[i].fLayers[j].fBounds.fLeft;
out->writeDecAsText(lsb);
out->writeText("\"/>\n");
}
}
}
out->writeText(" </hmtx>\n");
bool hasNonBMP = false;
out->writeText(" <cmap>\n");
out->writeText(" <tableVersion version=\"0\"/>\n");
out->writeText(" <cmap_format_4 platformID=\"3\" platEncID=\"1\" language=\"0\">\n");
fCMap.foreach ([&out, &hasNonBMP](const SkUnichar& c, const SkGlyphID& g) {
if (0xFFFF < c) {
hasNonBMP = true;
return;
}
out->writeText(" <map code=\"0x");
out->writeHexAsText(c, 4);
out->writeText("\" name=\"glyf");
out->writeHexAsText(g, 4);
out->writeText("\"/>\n");
});
out->writeText(" </cmap_format_4>\n");
if (hasNonBMP) {
out->writeText(
" <cmap_format_12 platformID=\"3\" platEncID=\"10\" format=\"12\" "
"reserved=\"0\" length=\"1\" language=\"0\" nGroups=\"0\">\n");
fCMap.foreach ([&out](const SkUnichar& c, const SkGlyphID& g) {
out->writeText(" <map code=\"0x");
out->writeHexAsText(c, 6);
out->writeText("\" name=\"glyf");
out->writeHexAsText(g, 4);
out->writeText("\"/>\n");
});
out->writeText(" </cmap_format_12>\n");
}
out->writeText(" </cmap>\n");
out->writeText(" <name>\n");
out->writeText(
" <namerecord nameID=\"1\" platformID=\"3\" platEncID=\"1\" langID=\"0x409\">\n");
out->writeText(" ");
out->writeText(fName.c_str());
out->writeText(" ");
out->writeText(type);
out->writeText("\n");
out->writeText(" </namerecord>\n");
out->writeText(
" <namerecord nameID=\"2\" platformID=\"3\" platEncID=\"1\" langID=\"0x409\">\n");
out->writeText(" Regular\n");
out->writeText(" </namerecord>\n");
out->writeText(
" <namerecord nameID=\"6\" platformID=\"3\" platEncID=\"1\" langID=\"0x409\">\n");
out->writeText(" ");
out->writeText(fName.c_str());
out->writeText("_");
out->writeText(type);
out->writeText("\n");
out->writeText(" </namerecord>\n");
out->writeText(" </name>\n");
out->writeText(" <post>\n");
out->writeText(" <formatType value=\"3.0\"/>\n");
out->writeText(" <italicAngle value=\"0.0\"/>\n");
out->writeText(" <underlinePosition value=\"");
out->writeScalarAsText(fFontMetrics.fUnderlinePosition);
out->writeText("\"/>\n");
out->writeText(" <underlineThickness value=\"");
out->writeScalarAsText(fFontMetrics.fUnderlineThickness);
out->writeText("\"/>\n");
out->writeText(" <isFixedPitch value=\"0\"/>\n");
out->writeText(" <minMemType42 value=\"0\"/>\n");
out->writeText(" <maxMemType42 value=\"0\"/>\n");
out->writeText(" <minMemType1 value=\"0\"/>\n");
out->writeText(" <maxMemType1 value=\"0\"/>\n");
out->writeText(" </post>\n");
}