22 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
23 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
24 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
25 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
26 0x0020, 0x0021, 0x2200, 0x0023, 0x2203, 0x0025, 0x0026, 0x220b,
27 0x0028, 0x0029, 0x2217, 0x002b, 0x002c, 0x2212, 0x002e, 0x002f,
28 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
29 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
31 0x2245, 0x0391, 0x0392, 0x03a7, 0x0394, 0x0395, 0x03a6, 0x0393,
32 0x0397, 0x0399, 0x03d1, 0x039a, 0x039b, 0x039c, 0x039d, 0x039f,
33 0x03a0, 0x0398, 0x03a1, 0x03a3, 0x03a4, 0x03a5, 0x03c2, 0x03a9,
34 0x039e, 0x03a8, 0x0396, 0x005b, 0x2234, 0x005d, 0x22a5, 0x005f,
35 0xf8e5, 0x03b1, 0x03b2, 0x03c7, 0x03b4, 0x03b5, 0x03c6, 0x03b3,
36 0x03b7, 0x03b9, 0x03d5, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03bf,
37 0x03c0, 0x03b8, 0x03c1, 0x03c3, 0x03c4, 0x03c5, 0x03d6, 0x03c9,
38 0x03be, 0x03c8, 0x03b6, 0x007b, 0x007c, 0x007d, 0x223c, 0x007f,
40 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
41 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
42 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
43 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
44 0x20ac, 0x03d2, 0x2023, 0x2264, 0x2044, 0x221e, 0x0192, 0x2263,
45 0x2666, 0x2665, 0x2660, 0x2194, 0x2190, 0x2191, 0x2192, 0x2193,
46 0x00b0, 0x00b1, 0x2033, 0x2265, 0x00d7, 0x221d, 0x2202, 0x2022,
47 0x00f7, 0x2260, 0x2261, 0x2248, 0x2026, 0xf8e6, 0xf8e7, 0x21b5,
49 0x2135, 0x2111, 0x211c, 0x2118, 0x2297, 0x2295, 0x2205, 0x2229,
50 0x222a, 0x2283, 0x2287, 0x2284, 0x2282, 0x2286, 0x2208, 0x2209,
51 0x2220, 0x2207, 0xf6da, 0xf6d9, 0xf6db, 0x220f, 0x221a, 0x22c5,
52 0x00ac, 0x2227, 0x2228, 0x21d4, 0x21d0, 0x21d1, 0x21d2, 0x21d3,
53 0x25ca, 0x2329, 0xf8e8, 0xf8e9, 0xf8ea, 0x2211, 0xf8eb, 0xf8ec,
54 0xf8ed, 0xf8ee, 0xf8ef, 0xf8f0, 0xf8f1, 0xf8f2, 0xf8f3, 0xf8f4,
55 0x0000, 0x232a, 0x222b, 0x2320, 0xf8f5, 0x2321, 0xf8f6, 0xf8f7,
56 0xf8f8, 0xf8f9, 0xf8fa, 0xf8fb, 0xf8fc, 0xf8fd, 0xf8fe, 0x0000
159QByteArray QFontSubset::createToUnicodeMap()
const
161 QList<
int> reverseMap = getReverseMap();
164 QPdf::ByteStream ts(&touc);
165 ts <<
"/CIDInit /ProcSet findresource begin\n"
168 "/CIDSystemInfo << /Registry (Adobe) /Ordering (UCS) /Supplement 0 >> def\n"
169 "/CMapName /Adobe-Identity-UCS def\n"
171 "1 begincodespacerange\n"
173 "endcodespacerange\n";
176 QByteArray ranges =
"<0000> <0000> <0000>\n";
177 QPdf::ByteStream s(&ranges);
180 for (qsizetype g = 1; g < nGlyphs(); ) {
181 int uc0 = reverseMap.at(g);
187 qsizetype startLinear = 0;
189 while (g < nGlyphs()) {
190 int uc = reverseMap[g];
192 if (!uc || (g>>8) != (start >> 8))
198 if (startLinear > 0 && g - startLinear >= 10)
206 if (g - startLinear < 10)
208 qsizetype endnonlinear = startLinear ? startLinear : g;
210 if (endnonlinear > start) {
211 s <<
'<' << QPdf::toHex((ushort)start, buf) <<
"> <";
212 s << QPdf::toHex((ushort)(endnonlinear - 1), buf) <<
"> ";
213 if (endnonlinear == start + 1) {
214 s <<
'<' << QPdf::toHex((ushort)reverseMap[start], buf) <<
">\n";
217 for (qsizetype i = start; i < endnonlinear; ++i) {
218 s <<
'<' << QPdf::toHex((ushort)reverseMap[i], buf) <<
"> ";
222 checkRanges(ts, ranges, nranges);
225 while (startLinear < g) {
226 qsizetype len = g - startLinear;
227 qsizetype uc_start = reverseMap[startLinear];
228 qsizetype uc_end = uc_start + len - 1;
229 if ((uc_end >> 8) != (uc_start >> 8))
230 len = 256 - (uc_start & 0xff);
231 s <<
'<' << QPdf::toHex((ushort)startLinear, buf) <<
"> <";
232 s << QPdf::toHex((ushort)(startLinear + len - 1), buf) <<
"> ";
233 s <<
'<' << QPdf::toHex((ushort)reverseMap[startLinear], buf) <<
">\n";
234 checkRanges(ts, ranges, nranges);
240 ts << nranges <<
"beginbfrange\n"
241 << ranges <<
"endbfrange\n";
244 "CMapName currentdict /CMap defineresource pop\n"
668static void convertPath(
const QPainterPath &path, QList<TTF_POINT> *points, QList<
int> *endPoints, qreal ppem)
670 int numElements = path.elementCount();
671 for (
int i = 0; i < numElements - 1; ++i) {
672 const QPainterPath::Element &e = path.elementAt(i);
674 p.x = qRound(e.x * 2048. / ppem);
675 p.y = qRound(-e.y * 2048. / ppem);
679 case QPainterPath::MoveToElement:
682 int start = endPoints->size() ? endPoints->at(endPoints->size()-1) - 1 : 0;
683 int end = points->size() - 1;
684 if (points->at(end).x == points->at(start).x
685 && points->at(end).y == points->at(start).y)
687 endPoints->append(points->size() - 1);
690 case QPainterPath::LineToElement:
693 case QPainterPath::CurveToElement: {
696 list[3] = points->at(points->size() - 1);
698 const QPainterPath::Element &e2 = path.elementAt(++i);
699 list[1].x = qRound(e2.x * 2048. / ppem);
700 list[1].y = qRound(-e2.y * 2048. / ppem);
701 const QPainterPath::Element &e3 = path.elementAt(++i);
702 list[0].x = qRound(e3.x * 2048. / ppem);
703 list[0].y = qRound(-e3.y * 2048. / ppem);
707 bool try_reduce = points->size() > 1
708 && points->at(points->size() - 1).flags ==
OnCurve
709 && points->at(points->size() - 2).flags ==
OffCurve;
711 while (base >= list) {
712 const int split_limit = 3;
721 Q_ASSERT(base - list < 3*16 + 1);
723 int i1_x = base[1].x + ((base[1].x - base[0].x) >> 1);
724 int i1_y = base[1].y + ((base[1].y - base[0].y) >> 1);
725 int i2_x = base[2].x + ((base[2].x - base[3].x) >> 1);
726 int i2_y = base[2].y + ((base[2].y - base[3].y) >> 1);
728 if (qAbs(i1_x - i2_x) <= split_limit && qAbs(i1_y - i2_y) <= split_limit) {
731 np.x = (i1_x + i2_x) >> 1;
732 np.y = (i1_y + i2_y) >> 1;
735 int mx = (points->at(points->size() - 2).x + base[2].x) >> 1;
736 int my = (points->at(points->size() - 2).y + base[2].y) >> 1;
737 if (qAbs(mx - base[3].x) <= split_limit && qAbs(my - base[3].y) <= split_limit)
749 base[6].x = base[3].x;
752 base[1].x = a = ( base[0].x + c ) >> 1;
753 base[5].x = b = ( base[3].x + d ) >> 1;
755 base[2].x = a = ( a + c ) >> 1;
756 base[4].x = b = ( b + c ) >> 1;
757 base[3].x = ( a + b ) >> 1;
759 base[6].y = base[3].y;
762 base[1].y = a = ( base[0].y + c ) >> 1;
763 base[5].y = b = ( base[3].y + d ) >> 1;
765 base[2].y = a = ( a + c ) >> 1;
766 base[4].y = b = ( b + c ) >> 1;
767 base[3].y = ( a + b ) >> 1;
775 case QPainterPath::CurveToDataElement:
782 int start = endPoints->size() ? endPoints->at(endPoints->size()-1) + 1 : 0;
783 int end = points->size() - 1;
784 if (points->at(end).x == points->at(start).x
785 && points->at(end).y == points->at(start).y)
787 endPoints->append(points->size() - 1);
1109QByteArray QFontSubset::toTruetype()
const
1114 qreal ppem = fontEngine->fontDef.pixelSize;
1115#define TO_TTF(x) qRound(x * 2048.
/ ppem)
1117 QFontEngine::Properties properties = fontEngine->properties();
1120 widths.resize(nGlyphs());
1123 font.head.font_revision = 0x00010000;
1124 font.head.flags = (1 << 2) | (1 << 4);
1125 font.head.created = 0;
1126 font.head.modified = 0;
1127 font.head.xMin = SHRT_MAX;
1128 font.head.xMax = SHRT_MIN;
1129 font.head.yMin = SHRT_MAX;
1130 font.head.yMax = SHRT_MIN;
1131 font.head.macStyle = (fontEngine->fontDef.weight > QFont::Normal) ? 1 : 0;
1132 font.head.macStyle |= (fontEngine->fontDef.styleHint != QFont::StyleNormal) ? 1 : 0;
1135 font.hhea.ascender = qRound(properties.ascent);
1136 font.hhea.descender = -qRound(properties.descent);
1137 font.hhea.lineGap = qRound(properties.leading);
1138 font.hhea.maxAdvanceWidth =
TO_TTF(fontEngine->maxCharWidth());
1139 font.hhea.minLeftSideBearing =
TO_TTF(fontEngine->minLeftBearing());
1140 font.hhea.minRightSideBearing =
TO_TTF(fontEngine->minRightBearing());
1141 font.hhea.xMaxExtent = SHRT_MIN;
1143 font.maxp.numGlyphs = 0;
1144 font.maxp.maxPoints = 0;
1145 font.maxp.maxContours = 0;
1146 font.maxp.maxCompositePoints = 0;
1147 font.maxp.maxCompositeContours = 0;
1148 font.maxp.maxComponentElements = 0;
1149 font.maxp.maxComponentDepth = 0;
1150 const qsizetype numGlyphs = nGlyphs();
1151 font.maxp.numGlyphs = quint16(numGlyphs);
1152 QList<QTtfGlyph> glyphs;
1153 glyphs.reserve(numGlyphs);
1155 for (qsizetype i = 0; i < numGlyphs; ++i) {
1156 glyph_t g = glyph_indices.at(i);
1158 glyph_metrics_t metric;
1159 fontEngine->getUnscaledGlyph(g, &path, &metric);
1161 path = QPainterPath();
1163 path.addRect(QRectF(0, 0, 1000, 1000));
1165 QTtfGlyph glyph = generateGlyph(i, path, metric.xoff.toReal(), metric.x.toReal(), properties.emSquare.toReal());
1167 font.head.xMin = qMin(font.head.xMin, glyph.xMin);
1168 font.head.xMax = qMax(font.head.xMax, glyph.xMax);
1169 font.head.yMin = qMin(font.head.yMin, glyph.yMin);
1170 font.head.yMax = qMax(font.head.yMax, glyph.yMax);
1172 font.hhea.xMaxExtent = qMax(font.hhea.xMaxExtent, (qint16)(glyph.lsb + glyph.xMax - glyph.xMin));
1174 font.maxp.maxPoints = qMax(font.maxp.maxPoints, glyph.numPoints);
1175 font.maxp.maxContours = qMax(font.maxp.maxContours, glyph.numContours);
1178 glyphs.append(glyph);
1179 widths[i] = glyph.advanceWidth;
1183 QList<QTtfTable> tables = generateGlyphTables(font, glyphs);
1184 tables.append(generateHead(font.head));
1185 tables.append(generateHhea(font.hhea));
1186 tables.append(generateMaxp(font.maxp));
1189 name_table.tag = QFont::Tag(
"name").value();
1191 name_table.data = fontEngine->getSfntTable(name_table.tag);
1192 if (name_table.data.isEmpty()) {
1195 name.copyright =
"Fake font"_L1;
1197 name.copyright = QLatin1StringView(properties.copyright);
1198 name.family = fontEngine->fontDef.families.constFirst();
1199 name.subfamily =
"Regular"_L1;
1200 name.postscript_name = QLatin1StringView(properties.postscriptName);
1203 tables.append(name_table);
1207 os2.tag = QFont::Tag(
"OS/2").value();
1208 os2.data = fontEngine->getSfntTable(os2.tag);
1209 if (!os2.data.isEmpty())
1213 return bindFont(tables);