📄 qfontsubset.cpp
字号:
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("name"); if (!noEmbed) name_table.data = fontEngine->getSfntTable(name_table.tag); if (name_table.data.isEmpty()) { qttf_name_table name; if (noEmbed) name.copyright = "Fake font"; else name.copyright = properties.copyright; name.family = fontEngine->fontDef.family; name.subfamily = QLatin1String("Regular"); // ###### name.postscript_name = properties.postscriptName; name_table = generateName(name); } tables.append(name_table); if (!noEmbed) { QTtfTable os2; os2.tag = MAKE_TAG("OS/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); int nGlyphs = this->nGlyphs(); QByteArray id = QByteArray::number(object_id); QByteArray psname = properties.postscriptName; psname.replace(" ", ""); bool 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 if (!standard_font) { s << "/F" << id << "-Base <<\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"; 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); QByteArray charstring = ::charString(path, metric.xoff.toReal(), metric.x.toReal(), properties.emSquare.toReal()); s << glyphName(i, reverseMap) << "\n<" << charstring << ">\n"; } s << ">>\n" ">> def\n"; } int page = 0; while (nGlyphs > 0) { s << "/F" << id << "-" << page; if (standard_font) s << "/" << psname << " findfont\n"; else s << "F" << id << "-Base\n"; s << "0 dict copy dup /Encoding 256 array\n" "0 1 255 {1 index exch /.notdef put} for\n"; for (int i = 0; i < nGlyphs; ++i) s << "dup " << i << glyphName(i, reverseMap) << " put\n"; s << "put definefont pop\n"; ++page; nGlyphs -= 256; } s << "/F" << id << " <<\n" "/FontType 0\n" "/FMapType 2\n" "/FontMatrix[1 0 0 1 0 0]\n" "/Encoding ["; for (int i = 0; i < page; ++i) { if (page % 16 == 0) s << "\n"; s << i; } s << "]\n" "/FDepVector [\n"; for (int i = 0; i < page; ++i) { s << "/F" << id << "-" << i << " findfont\n"; } s << "]\n" ">> definefont pop\n"; return font;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -