📄 qfontsubset.cpp
字号:
// head table font.head.font_revision = 0x00010000; font.head.flags = (1 << 2) | (1 << 4); font.head.created = 0; // ### font.head.modified = 0; // ### font.head.xMin = SHRT_MAX; font.head.xMax = SHRT_MIN; font.head.yMin = SHRT_MAX; font.head.yMax = SHRT_MIN; font.head.macStyle = (fontEngine->fontDef.weight > QFont::Normal) ? 1 : 0; font.head.macStyle |= (fontEngine->fontDef.styleHint != QFont::StyleNormal) ? 1 : 0; // hhea table font.hhea.ascender = qRound(properties.ascent); font.hhea.descender = -qRound(properties.descent); font.hhea.lineGap = qRound(properties.leading); font.hhea.maxAdvanceWidth = TO_TTF(fontEngine->maxCharWidth()); font.hhea.minLeftSideBearing = TO_TTF(fontEngine->minLeftBearing()); font.hhea.minRightSideBearing = TO_TTF(fontEngine->minRightBearing()); font.hhea.xMaxExtent = SHRT_MIN; font.maxp.numGlyphs = 0; font.maxp.maxPoints = 0; font.maxp.maxContours = 0; font.maxp.maxCompositePoints = 0; font.maxp.maxCompositeContours = 0; font.maxp.maxComponentElements = 0; font.maxp.maxComponentDepth = 0; font.maxp.numGlyphs = nGlyphs(); uint sumAdvances = 0; for (int i = 0; i < nGlyphs(); ++i) { glyph_t g = glyph_indices.at(i); QPainterPath path; glyph_metrics_t metric; fontEngine->getUnscaledGlyph(g, &path, &metric); if (noEmbed) { path = QPainterPath(); if (g == 0) path.addRect(QRectF(0, 0, 1000, 1000)); } QTtfGlyph glyph = generateGlyph(i, path, metric.xoff.toReal(), metric.x.toReal(), properties.emSquare.toReal()); font.head.xMin = qMin(font.head.xMin, glyph.xMin); font.head.xMax = qMax(font.head.xMax, glyph.xMax); font.head.yMin = qMin(font.head.yMin, glyph.yMin); font.head.yMax = qMax(font.head.yMax, glyph.yMax); font.hhea.xMaxExtent = qMax(font.hhea.xMaxExtent, (qint16)(glyph.lsb + glyph.xMax - glyph.xMin)); font.maxp.maxPoints = qMax(font.maxp.maxPoints, glyph.numPoints); font.maxp.maxContours = qMax(font.maxp.maxContours, glyph.numContours); if (glyph.xMax > glyph.xMin) sumAdvances += glyph.xMax - glyph.xMin;// qDebug("adding glyph %d size=%d", glyph.index, glyph.data.size()); glyphs.append(glyph); widths[i] = glyph.advanceWidth; } QList<QTtfTable> tables = generateGlyphTables(font, glyphs); tables.append(generateHead(font.head)); tables.append(generateHhea(font.hhea)); tables.append(generateMaxp(font.maxp)); // name QTtfTable name_table; name_table.tag = MAKE_TAG('n', 'a', 'm', 'e'); if (!noEmbed) name_table.data = fontEngine->getSfntTable(name_table.tag); if (name_table.data.isEmpty()) { qttf_name_table name; if (noEmbed) name.copyright = QLatin1String("Fake font"); else name.copyright = QLatin1String(properties.copyright); name.family = fontEngine->fontDef.family; name.subfamily = QLatin1String("Regular"); // ###### name.postscript_name = QLatin1String(properties.postscriptName); name_table = generateName(name); } tables.append(name_table); if (!noEmbed) { QTtfTable os2; os2.tag = MAKE_TAG('O', 'S', '/', '2'); os2.data = fontEngine->getSfntTable(os2.tag); if (!os2.data.isEmpty()) tables.append(os2); } return bindFont(tables);}// ------------------ Type 1 generation ---------------------------// needs at least 6 bytes of space in tmpstatic const char *encodeNumber(int num, char *tmp){ const char *ret = tmp; if(num >= -107 && num <= 107) { QPdf::toHex((uchar)(num + 139), tmp); tmp += 2; } else if (num > 107 && num <= 1131) { num -= 108; QPdf::toHex((uchar)((num >> 8) + 247), tmp); tmp += 2; QPdf::toHex((uchar)(num & 0xff), tmp); tmp += 2; } else if(num < - 107 && num >= -1131) { num += 108; num = -num; QPdf::toHex((uchar)((num >> 8) + 251), tmp); tmp += 2; QPdf::toHex((uchar)(num & 0xff), tmp); tmp += 2; } else { *tmp++ = 'f'; *tmp++ = 'f'; QPdf::toHex((uchar)(num >> 24), tmp); tmp += 2; QPdf::toHex((uchar)(num >> 16), tmp); tmp += 2; QPdf::toHex((uchar)(num >> 8), tmp); tmp += 2; QPdf::toHex((uchar)(num >> 0), tmp); tmp += 2; } *tmp = 0;// qDebug("encodeNumber: %d -> '%s'", num, ret); return ret;}static QByteArray charString(const QPainterPath &path, qreal advance, qreal lsb, qreal ppem){ // the charstring commands we need const char *hsbw = "0D"; const char *closepath = "09"; const char *moveto[3] = { "16", "04", "15" }; const char *lineto[3] = { "06", "07", "05" }; const char *rcurveto = "08"; const char *endchar = "0E"; enum { horizontal = 1, vertical = 2 }; char tmp[16]; qreal factor = 1000./ppem; int lsb_i = qRound(lsb*factor); int advance_i = qRound(advance*factor);// qDebug("--- charstring"); // first of all add lsb and width to the charstring using the hsbw command QByteArray charstring; charstring += encodeNumber(lsb_i, tmp); charstring += encodeNumber(advance_i, tmp); charstring += hsbw; // add the path int xl = lsb_i; int yl = 0; bool openpath = false; for (int i = 0; i < path.elementCount(); ++i) { const QPainterPath::Element &elm = path.elementAt(i); int x = qRound(elm.x*factor); int y = -qRound(elm.y*factor); int dx = x - xl; int dy = y - yl; if (elm.type == QPainterPath::MoveToElement && openpath) {// qDebug("closepath %s", closepath); charstring += closepath; } if (elm.type == QPainterPath::MoveToElement || elm.type == QPainterPath::LineToElement) { int type = -1; if (dx || !dy) { charstring += encodeNumber(dx, tmp); type += horizontal;// qDebug("horizontal"); } if (dy) { charstring += encodeNumber(dy, tmp); type += vertical;// qDebug("vertical"); }// qDebug("moveto/lineto %s", (elm.type == QPainterPath::MoveToElement ? moveto[type] : lineto[type])); charstring += (elm.type == QPainterPath::MoveToElement ? moveto[type] : lineto[type]); openpath = true; xl = x; yl = y; } else { Q_ASSERT(elm.type == QPainterPath::CurveToElement); const QPainterPath::Element &elm2 = path.elementAt(++i); const QPainterPath::Element &elm3 = path.elementAt(++i); int x2 = qRound(elm2.x*factor); int y2 = -qRound(elm2.y*factor); int x3 = qRound(elm3.x*factor); int y3 = -qRound(elm3.y*factor); charstring += encodeNumber(dx, tmp); charstring += encodeNumber(dy, tmp); charstring += encodeNumber(x2 - x, tmp); charstring += encodeNumber(y2 - y, tmp); charstring += encodeNumber(x3 - x2, tmp); charstring += encodeNumber(y3 - y2, tmp); charstring += rcurveto; openpath = true; xl = x3; yl = y3;// qDebug("rcurveto"); } } if (openpath) charstring += closepath; charstring += endchar; if (charstring.length() > 240) { int pos = 240; while (pos < charstring.length()) { charstring.insert(pos, '\n'); pos += 241; } } return charstring;}#ifndef QT_NO_FREETYPEstatic const char *helvetica_styles[4] = { "Helvetica", "Helvetica-Bold", "Helvetica-Oblique", "Helvetica-BoldOblique"};static const char *times_styles[4] = { "Times-Regular", "Times-Bold", "Times-Italic", "Times-BoldItalic"};static const char *courier_styles[4] = { "Courier", "Courier-Bold", "Courier-Oblique", "Courier-BoldOblique"};#endifQByteArray QFontSubset::toType1() const{ QFontEngine::Properties properties = fontEngine->properties(); QVector<int> reverseMap = getReverseMap(); QByteArray font; QPdf::ByteStream s(&font); QByteArray id = QByteArray::number(object_id); QByteArray psname = properties.postscriptName; psname.replace(" ", ""); standard_font = false;#ifndef QT_NO_FREETYPE FT_Face face = ft_face(fontEngine); if (face && !FT_IS_SCALABLE(face)) { int style = 0; if (fontEngine->fontDef.style) style += 2; if (fontEngine->fontDef.weight >= QFont::Bold) style++; if (fontEngine->fontDef.family.contains(QLatin1String("Helvetica"))) { psname = helvetica_styles[style]; standard_font = true; } else if (fontEngine->fontDef.family.contains(QLatin1String("Times"))) { psname = times_styles[style]; standard_font = true; } else if (fontEngine->fontDef.family.contains(QLatin1String("Courier"))) { psname = courier_styles[style]; standard_font = true; } }#endif s << "/F" << id << "-Base\n"; if (standard_font) { s << "/" << psname << " findfont\n" "0 dict copy dup /NumGlyphs 0 put dup /CMap 256 array put def\n"; } else { s << "<<\n"; if(!psname.isEmpty()) s << "/FontName /" << psname << "\n"; s << "/FontInfo <</FsType " << (int)fontEngine->fsType << ">>\n" "/FontType 1\n" "/PaintType 0\n" "/FontMatrix [.001 0 0 .001 0 0]\n" "/FontBBox { 0 0 0 0 }\n" "/Private <<\n" "/password 5839\n" "/MinFeature {16 16}\n" "/BlueValues []\n" "/lenIV -1\n" ">>\n" "/CharStrings << >>\n" "/NumGlyphs 0\n" "/CMap 256 array\n" ">> def\n"; } s << type1AddedGlyphs(); downloaded_glyphs = glyph_indices.size(); return font;}QByteArray QFontSubset::type1AddedGlyphs() const{ if (downloaded_glyphs == glyph_indices.size()) return QByteArray(); QFontEngine::Properties properties = fontEngine->properties(); QVector<int> reverseMap = getReverseMap(); QByteArray glyphs; QPdf::ByteStream s(&glyphs); int nGlyphs = glyph_indices.size(); QByteArray id = QByteArray::number(object_id); s << "F" << id << "-Base [\n"; for (int i = downloaded_glyphs; i < nGlyphs; ++i) { glyph_t g = glyph_indices.at(i); QPainterPath path; glyph_metrics_t metric; fontEngine->getUnscaledGlyph(g, &path, &metric); QByteArray charstring = ::charString(path, metric.xoff.toReal(), metric.x.toReal(), properties.emSquare.toReal()); s << glyphName(i, reverseMap); if (!standard_font) s << "\n<" << charstring << ">\n"; } s << (standard_font ? "] T1AddMapping\n" : "] T1AddGlyphs\n"); return glyphs;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -