Line | Source Code | Coverage |
---|
1 | | - |
2 | | - |
3 | | - |
4 | | - |
5 | | - |
6 | static const unsigned short symbol_map[0x100] = { | - |
7 | 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, | - |
8 | 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f, | - |
9 | 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, | - |
10 | 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f, | - |
11 | 0x0020, 0x0021, 0x2200, 0x0023, 0x2203, 0x0025, 0x0026, 0x220b, | - |
12 | 0x0028, 0x0029, 0x2217, 0x002b, 0x002c, 0x2212, 0x002e, 0x002f, | - |
13 | 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, | - |
14 | 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f, | - |
15 | | - |
16 | 0x2245, 0x0391, 0x0392, 0x03a7, 0x0394, 0x0395, 0x03a6, 0x0393, | - |
17 | 0x0397, 0x0399, 0x03d1, 0x039a, 0x039b, 0x039c, 0x039d, 0x039f, | - |
18 | 0x03a0, 0x0398, 0x03a1, 0x03a3, 0x03a4, 0x03a5, 0x03c2, 0x03a9, | - |
19 | 0x039e, 0x03a8, 0x0396, 0x005b, 0x2234, 0x005d, 0x22a5, 0x005f, | - |
20 | 0xf8e5, 0x03b1, 0x03b2, 0x03c7, 0x03b4, 0x03b5, 0x03c6, 0x03b3, | - |
21 | 0x03b7, 0x03b9, 0x03d5, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03bf, | - |
22 | 0x03c0, 0x03b8, 0x03c1, 0x03c3, 0x03c4, 0x03c5, 0x03d6, 0x03c9, | - |
23 | 0x03be, 0x03c8, 0x03b6, 0x007b, 0x007c, 0x007d, 0x223c, 0x007f, | - |
24 | | - |
25 | 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087, | - |
26 | 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f, | - |
27 | 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097, | - |
28 | 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f, | - |
29 | 0x20ac, 0x03d2, 0x2023, 0x2264, 0x2044, 0x221e, 0x0192, 0x2263, | - |
30 | 0x2666, 0x2665, 0x2660, 0x2194, 0x2190, 0x2191, 0x2192, 0x2193, | - |
31 | 0x00b0, 0x00b1, 0x2033, 0x2265, 0x00d7, 0x221d, 0x2202, 0x2022, | - |
32 | 0x00f7, 0x2260, 0x2261, 0x2248, 0x2026, 0xf8e6, 0xf8e7, 0x21b5, | - |
33 | | - |
34 | 0x2135, 0x2111, 0x211c, 0x2118, 0x2297, 0x2295, 0x2205, 0x2229, | - |
35 | 0x222a, 0x2283, 0x2287, 0x2284, 0x2282, 0x2286, 0x2208, 0x2209, | - |
36 | 0x2220, 0x2207, 0xf6da, 0xf6d9, 0xf6db, 0x220f, 0x221a, 0x22c5, | - |
37 | 0x00ac, 0x2227, 0x2228, 0x21d4, 0x21d0, 0x21d1, 0x21d2, 0x21d3, | - |
38 | 0x25ca, 0x2329, 0xf8e8, 0xf8e9, 0xf8ea, 0x2211, 0xf8eb, 0xf8ec, | - |
39 | 0xf8ed, 0xf8ee, 0xf8ef, 0xf8f0, 0xf8f1, 0xf8f2, 0xf8f3, 0xf8f4, | - |
40 | 0x0000, 0x232a, 0x222b, 0x2320, 0xf8f5, 0x2321, 0xf8f6, 0xf8f7, | - |
41 | 0xf8f8, 0xf8f9, 0xf8fa, 0xf8fb, 0xf8fc, 0xf8fd, 0xf8fe, 0x0000 | - |
42 | }; | - |
43 | | - |
44 | | - |
45 | | - |
46 | QByteArray QFontSubset::glyphName(unsigned short unicode, bool symbol) | - |
47 | { | - |
48 | if (symbol && unicode < 0x100) never evaluated: unicode < 0x100 | 0 |
49 | | - |
50 | unicode = symbol_map[unicode]; never executed: unicode = symbol_map[unicode]; | 0 |
51 | | - |
52 | const AGLEntry *r = qBinaryFind(unicode_to_agl_map, unicode_to_agl_map + unicode_to_agl_map_size, unicode); | - |
53 | if (r != unicode_to_agl_map + unicode_to_agl_map_size) never evaluated: r != unicode_to_agl_map + unicode_to_agl_map_size | 0 |
54 | return glyph_names + r->index; never executed: return glyph_names + r->index; | 0 |
55 | | - |
56 | char buffer[8]; | - |
57 | buffer[0] = 'u'; | - |
58 | buffer[1] = 'n'; | - |
59 | buffer[2] = 'i'; | - |
60 | QPdf::toHex(unicode, buffer+3); | - |
61 | return buffer; never executed: return buffer; | 0 |
62 | } | - |
63 | | - |
64 | QByteArray QFontSubset::glyphName(unsigned int glyph, const QVector<int> &reverseMap) const | - |
65 | { | - |
66 | uint glyphIndex = glyph_indices[glyph]; | - |
67 | | - |
68 | if (glyphIndex == 0) never evaluated: glyphIndex == 0 | 0 |
69 | return "/.notdef"; never executed: return "/.notdef"; | 0 |
70 | | - |
71 | QByteArray ba; | - |
72 | QPdf::ByteStream s(&ba); | - |
73 | if (reverseMap[glyphIndex] && reverseMap[glyphIndex] < 0x10000) { never evaluated: reverseMap[glyphIndex] never evaluated: reverseMap[glyphIndex] < 0x10000 | 0 |
74 | s << '/' << glyphName(reverseMap[glyphIndex], false); | - |
75 | } else { | 0 |
76 | s << "/gl" << (int)glyphIndex; | - |
77 | } | 0 |
78 | return ba; never executed: return ba; | 0 |
79 | } | - |
80 | | - |
81 | | - |
82 | QByteArray QFontSubset::widthArray() const | - |
83 | { | - |
84 | qt_noop(); | - |
85 | | - |
86 | QFontEngine::Properties properties = fontEngine->properties(); | - |
87 | | - |
88 | QByteArray width; | - |
89 | QPdf::ByteStream s(&width); | - |
90 | QFixed scale = QFixed(1000)/emSquare; | - |
91 | | - |
92 | QFixed defWidth = widths[0]; | - |
93 | | - |
94 | for (int i = 0; i < nGlyphs(); ++i) { never evaluated: i < nGlyphs() | 0 |
95 | if (defWidth != widths[i]) never evaluated: defWidth != widths[i] | 0 |
96 | defWidth = 0; never executed: defWidth = 0; | 0 |
97 | } | 0 |
98 | if (defWidth > 0) { never evaluated: defWidth > 0 | 0 |
99 | s << "/DW " << (defWidth*scale).toInt(); | - |
100 | } else { | 0 |
101 | s << "/W ["; | - |
102 | for (int g = 0; g < nGlyphs();) { never evaluated: g < nGlyphs() | 0 |
103 | QFixed w = widths[g]; | - |
104 | int start = g; | - |
105 | int startLinear = 0; | - |
106 | ++g; | - |
107 | while (g < nGlyphs()) { never evaluated: g < nGlyphs() | 0 |
108 | QFixed nw = widths[g]; | - |
109 | if (nw == w) { | 0 |
110 | if (!startLinear) never evaluated: !startLinear | 0 |
111 | startLinear = g - 1; never executed: startLinear = g - 1; | 0 |
112 | } else { | 0 |
113 | if (startLinear > 0 && g - startLinear >= 10) never evaluated: startLinear > 0 never evaluated: g - startLinear >= 10 | 0 |
114 | break; | 0 |
115 | startLinear = 0; | - |
116 | } | 0 |
117 | w = nw; | - |
118 | ++g; | - |
119 | } | 0 |
120 | | - |
121 | if (g - startLinear < 10) never evaluated: g - startLinear < 10 | 0 |
122 | startLinear = 0; never executed: startLinear = 0; | 0 |
123 | int endnonlinear = startLinear ? startLinear : g; never evaluated: startLinear | 0 |
124 | | - |
125 | if (endnonlinear > start) { never evaluated: endnonlinear > start | 0 |
126 | s << start << '['; | - |
127 | for (int i = start; i < endnonlinear; ++i) never evaluated: i < endnonlinear | 0 |
128 | s << (widths[i]*scale).toInt(); never executed: s << (widths[i]*scale).toInt(); | 0 |
129 | s << "]\n"; | - |
130 | } | 0 |
131 | if (startLinear) never evaluated: startLinear | 0 |
132 | s << startLinear << g - 1 << (widths[startLinear]*scale).toInt() << '\n'; never executed: s << startLinear << g - 1 << (widths[startLinear]*scale).toInt() << '\n'; | 0 |
133 | } | 0 |
134 | s << "]\n"; | - |
135 | } | 0 |
136 | return width; never executed: return width; | 0 |
137 | } | - |
138 | | - |
139 | static void checkRanges(QPdf::ByteStream &ts, QByteArray &ranges, int &nranges) | - |
140 | { | - |
141 | if (++nranges > 100) { never evaluated: ++nranges > 100 | 0 |
142 | ts << nranges << "beginbfrange\n" | - |
143 | << ranges << "endbfrange\n"; | - |
144 | ranges = QByteArray(); | - |
145 | nranges = 0; | - |
146 | } | 0 |
147 | } | 0 |
148 | | - |
149 | QVector<int> QFontSubset::getReverseMap() const | - |
150 | { | - |
151 | QVector<int> reverseMap(0x10000, 0); | - |
152 | QGlyphLayoutArray<10> glyphs; | - |
153 | for (uint uc = 0; uc < 0x10000; ++uc) { never evaluated: uc < 0x10000 | 0 |
154 | QChar ch(uc); | - |
155 | int nglyphs = 10; | - |
156 | fontEngine->stringToCMap(&ch, 1, &glyphs, &nglyphs, QFontEngine::GlyphIndicesOnly); | - |
157 | int idx = glyph_indices.indexOf(glyphs.glyphs[0]); | - |
158 | if (idx >= 0 && !reverseMap.at(idx)) never evaluated: idx >= 0 never evaluated: !reverseMap.at(idx) | 0 |
159 | reverseMap[idx] = uc; never executed: reverseMap[idx] = uc; | 0 |
160 | } | 0 |
161 | return reverseMap; never executed: return reverseMap; | 0 |
162 | } | - |
163 | | - |
164 | QByteArray QFontSubset::createToUnicodeMap() const | - |
165 | { | - |
166 | QVector<int> reverseMap = getReverseMap(); | - |
167 | | - |
168 | QByteArray touc; | - |
169 | QPdf::ByteStream ts(&touc); | - |
170 | ts << "/CIDInit /ProcSet findresource begin\n" | - |
171 | "12 dict begin\n" | - |
172 | "begincmap\n" | - |
173 | "/CIDSystemInfo << /Registry (Adobe) /Ordering (UCS) /Supplement 0 >> def\n" | - |
174 | "/CMapName /Adobe-Identity-UCS def\n" | - |
175 | "/CMapType 2 def\n" | - |
176 | "1 begincodespacerange\n" | - |
177 | "<0000> <FFFF>\n" | - |
178 | "endcodespacerange\n"; | - |
179 | | - |
180 | int nranges = 1; | - |
181 | QByteArray ranges = "<0000> <0000> <0000>\n"; | - |
182 | QPdf::ByteStream s(&ranges); | - |
183 | | - |
184 | char buf[5]; | - |
185 | for (int g = 1; g < nGlyphs(); ) { never evaluated: g < nGlyphs() | 0 |
186 | int uc0 = reverseMap.at(g); | - |
187 | if (!uc0) { | 0 |
188 | ++g; | - |
189 | continue; never executed: continue; | 0 |
190 | } | - |
191 | int start = g; | - |
192 | int startLinear = 0; | - |
193 | ++g; | - |
194 | while (g < nGlyphs()) { never evaluated: g < nGlyphs() | 0 |
195 | int uc = reverseMap[g]; | - |
196 | | - |
197 | if (!uc || (g>>8) != (start >> 8)) never evaluated: (g>>8) != (start >> 8) | 0 |
198 | break; | 0 |
199 | if (uc == uc0 + 1) { never evaluated: uc == uc0 + 1 | 0 |
200 | if (!startLinear) never evaluated: !startLinear | 0 |
201 | startLinear = g - 1; never executed: startLinear = g - 1; | 0 |
202 | } else { | 0 |
203 | if (startLinear > 0 && g - startLinear >= 10) never evaluated: startLinear > 0 never evaluated: g - startLinear >= 10 | 0 |
204 | break; | 0 |
205 | startLinear = 0; | - |
206 | } | 0 |
207 | uc0 = uc; | - |
208 | ++g; | - |
209 | } | 0 |
210 | | - |
211 | if (g - startLinear < 10) never evaluated: g - startLinear < 10 | 0 |
212 | startLinear = 0; never executed: startLinear = 0; | 0 |
213 | int endnonlinear = startLinear ? startLinear : g; never evaluated: startLinear | 0 |
214 | | - |
215 | if (endnonlinear > start) { never evaluated: endnonlinear > start | 0 |
216 | s << '<' << QPdf::toHex((ushort)start, buf) << "> <"; | - |
217 | s << QPdf::toHex((ushort)(endnonlinear - 1), buf) << "> "; | - |
218 | if (endnonlinear == start + 1) { never evaluated: endnonlinear == start + 1 | 0 |
219 | s << '<' << QPdf::toHex((ushort)reverseMap[start], buf) << ">\n"; | - |
220 | } else { | 0 |
221 | s << '['; | - |
222 | for (int i = start; i < endnonlinear; ++i) { never evaluated: i < endnonlinear | 0 |
223 | s << '<' << QPdf::toHex((ushort)reverseMap[i], buf) << "> "; | - |
224 | } | 0 |
225 | s << "]\n"; | - |
226 | } | 0 |
227 | checkRanges(ts, ranges, nranges); | - |
228 | } | 0 |
229 | if (startLinear) { never evaluated: startLinear | 0 |
230 | while (startLinear < g) { never evaluated: startLinear < g | 0 |
231 | int len = g - startLinear; | - |
232 | int uc_start = reverseMap[startLinear]; | - |
233 | int uc_end = uc_start + len - 1; | - |
234 | if ((uc_end >> 8) != (uc_start >> 8)) never evaluated: (uc_end >> 8) != (uc_start >> 8) | 0 |
235 | len = 256 - (uc_start & 0xff); never executed: len = 256 - (uc_start & 0xff); | 0 |
236 | s << '<' << QPdf::toHex((ushort)startLinear, buf) << "> <"; | - |
237 | s << QPdf::toHex((ushort)(startLinear + len - 1), buf) << "> "; | - |
238 | s << '<' << QPdf::toHex((ushort)reverseMap[startLinear], buf) << ">\n"; | - |
239 | checkRanges(ts, ranges, nranges); | - |
240 | startLinear += len; | - |
241 | } | 0 |
242 | } | 0 |
243 | } | 0 |
244 | if (nranges) { | 0 |
245 | ts << nranges << "beginbfrange\n" | - |
246 | << ranges << "endbfrange\n"; | - |
247 | } | 0 |
248 | ts << "endcmap\n" | - |
249 | "CMapName currentdict /CMap defineresource pop\n" | - |
250 | "end\n" | - |
251 | "end\n"; | - |
252 | | - |
253 | return touc; never executed: return touc; | 0 |
254 | } | - |
255 | | - |
256 | int QFontSubset::addGlyph(int index) | - |
257 | { | - |
258 | int idx = glyph_indices.indexOf(index); | - |
259 | if (idx < 0) { | 0 |
260 | idx = glyph_indices.size(); | - |
261 | glyph_indices.append(index); | - |
262 | } | 0 |
263 | return idx; never executed: return idx; | 0 |
264 | } | - |
265 | | - |
266 | | - |
267 | | - |
268 | | - |
269 | typedef qint16 F2DOT14; | - |
270 | typedef quint32 Tag; | - |
271 | typedef quint16 GlyphID; | - |
272 | typedef quint16 Offset; | - |
273 | | - |
274 | | - |
275 | class QTtfStream { | - |
276 | public: | - |
277 | QTtfStream(QByteArray &ba) : data((uchar *)ba.data()) { start = data; } | 0 |
278 | QTtfStream &operator <<(quint8 v) { *data = v; ++data; return *this; } never executed: return *this; | 0 |
279 | QTtfStream &operator <<(quint16 v) { qToBigEndian(v, data); data += sizeof(v); return *this; } never executed: return *this; | 0 |
280 | QTtfStream &operator <<(quint32 v) { qToBigEndian(v, data); data += sizeof(v); return *this; } never executed: return *this; | 0 |
281 | QTtfStream &operator <<(qint8 v) { *data = quint8(v); ++data; return *this; } never executed: return *this; | 0 |
282 | QTtfStream &operator <<(qint16 v) { qToBigEndian(v, data); data += sizeof(v); return *this; } never executed: return *this; | 0 |
283 | QTtfStream &operator <<(qint32 v) { qToBigEndian(v, data); data += sizeof(v); return *this; } never executed: return *this; | 0 |
284 | QTtfStream &operator <<(qint64 v) { qToBigEndian(v, data); data += sizeof(v); return *this; } never executed: return *this; | 0 |
285 | | - |
286 | int offset() const { return data - start; } never executed: return data - start; | 0 |
287 | void setOffset(int o) { data = start + o; } | 0 |
288 | void align4() { while (offset() & 3) { *data = '\0'; ++data; } } never evaluated: offset() & 3 | 0 |
289 | private: | - |
290 | uchar *data; | - |
291 | uchar *start; | - |
292 | }; | - |
293 | | - |
294 | struct QTtfTable { | - |
295 | Tag tag; | - |
296 | QByteArray data; | - |
297 | }; | - |
298 | template<> class QTypeInfo<QTtfTable > { public: enum { isComplex = (((Q_MOVABLE_TYPE) & Q_PRIMITIVE_TYPE) == 0), isStatic = (((Q_MOVABLE_TYPE) & (Q_MOVABLE_TYPE | Q_PRIMITIVE_TYPE)) == 0), isLarge = (sizeof(QTtfTable)>sizeof(void*)), isPointer = false, isDummy = (((Q_MOVABLE_TYPE) & Q_DUMMY_TYPE) != 0), sizeOf = sizeof(QTtfTable) }; static inline const char *name() { return "QTtfTable"; } }; | - |
299 | | - |
300 | | - |
301 | struct qttf_head_table { | - |
302 | qint32 font_revision; | - |
303 | quint16 flags; | - |
304 | qint64 created; | - |
305 | qint64 modified; | - |
306 | qint16 xMin; | - |
307 | qint16 yMin; | - |
308 | qint16 xMax; | - |
309 | qint16 yMax; | - |
310 | quint16 macStyle; | - |
311 | qint16 indexToLocFormat; | - |
312 | }; | - |
313 | | - |
314 | | - |
315 | struct qttf_hhea_table { | - |
316 | qint16 ascender; | - |
317 | qint16 descender; | - |
318 | qint16 lineGap; | - |
319 | quint16 maxAdvanceWidth; | - |
320 | qint16 minLeftSideBearing; | - |
321 | qint16 minRightSideBearing; | - |
322 | qint16 xMaxExtent; | - |
323 | quint16 numberOfHMetrics; | - |
324 | }; | - |
325 | | - |
326 | | - |
327 | struct qttf_maxp_table { | - |
328 | quint16 numGlyphs; | - |
329 | quint16 maxPoints; | - |
330 | quint16 maxContours; | - |
331 | quint16 maxCompositePoints; | - |
332 | quint16 maxCompositeContours; | - |
333 | quint16 maxComponentElements; | - |
334 | quint16 maxComponentDepth; | - |
335 | }; | - |
336 | | - |
337 | struct qttf_name_table { | - |
338 | QString copyright; | - |
339 | QString family; | - |
340 | QString subfamily; | - |
341 | QString postscript_name; | - |
342 | }; | - |
343 | | - |
344 | | - |
345 | static QTtfTable generateHead(const qttf_head_table &head); | - |
346 | static QTtfTable generateHhea(const qttf_hhea_table &hhea); | - |
347 | static QTtfTable generateMaxp(const qttf_maxp_table &maxp); | - |
348 | static QTtfTable generateName(const qttf_name_table &name); | - |
349 | | - |
350 | struct qttf_font_tables | - |
351 | { | - |
352 | qttf_head_table head; | - |
353 | qttf_hhea_table hhea; | - |
354 | qttf_maxp_table maxp; | - |
355 | }; | - |
356 | | - |
357 | | - |
358 | struct QTtfGlyph { | - |
359 | quint16 index; | - |
360 | qint16 xMin; | - |
361 | qint16 xMax; | - |
362 | qint16 yMin; | - |
363 | qint16 yMax; | - |
364 | quint16 advanceWidth; | - |
365 | qint16 lsb; | - |
366 | quint16 numContours; | - |
367 | quint16 numPoints; | - |
368 | QByteArray data; | - |
369 | }; | - |
370 | template<> class QTypeInfo<QTtfGlyph > { public: enum { isComplex = (((Q_MOVABLE_TYPE) & Q_PRIMITIVE_TYPE) == 0), isStatic = (((Q_MOVABLE_TYPE) & (Q_MOVABLE_TYPE | Q_PRIMITIVE_TYPE)) == 0), isLarge = (sizeof(QTtfGlyph)>sizeof(void*)), isPointer = false, isDummy = (((Q_MOVABLE_TYPE) & Q_DUMMY_TYPE) != 0), sizeOf = sizeof(QTtfGlyph) }; static inline const char *name() { return "QTtfGlyph"; } }; | - |
371 | | - |
372 | static QTtfGlyph generateGlyph(int index, const QPainterPath &path, qreal advance, qreal lsb, qreal ppem); | - |
373 | | - |
374 | static QList<QTtfTable> generateGlyphTables(qttf_font_tables &tables, const QList<QTtfGlyph> &_glyphs); | - |
375 | | - |
376 | static QByteArray bindFont(const QList<QTtfTable>& _tables); | - |
377 | | - |
378 | | - |
379 | static quint32 checksum(const QByteArray &table) | - |
380 | { | - |
381 | quint32 sum = 0; | - |
382 | int offset = 0; | - |
383 | const uchar *d = (uchar *)table.constData(); | - |
384 | while (offset <= table.size()-3) { never evaluated: offset <= table.size()-3 | 0 |
385 | sum += qFromBigEndian<quint32>(d + offset); | - |
386 | offset += 4; | - |
387 | } | 0 |
388 | int shift = 24; | - |
389 | quint32 x = 0; | - |
390 | while (offset < table.size()) { never evaluated: offset < table.size() | 0 |
391 | x |= ((quint32)d[offset]) << shift; | - |
392 | ++offset; | - |
393 | shift -= 8; | - |
394 | } | 0 |
395 | sum += x; | - |
396 | | - |
397 | return sum; never executed: return sum; | 0 |
398 | } | - |
399 | | - |
400 | static QTtfTable generateHead(const qttf_head_table &head) | - |
401 | { | - |
402 | const int head_size = 54; | - |
403 | QTtfTable t; | - |
404 | t.tag = ( (((quint32)('h')) << 24) | (((quint32)('e')) << 16) | (((quint32)('a')) << 8) | ((quint32)('d')) ); | - |
405 | t.data.resize(head_size); | - |
406 | | - |
407 | QTtfStream s(t.data); | - |
408 | | - |
409 | | - |
410 | | - |
411 | s << qint32(0x00010000) | - |
412 | << head.font_revision | - |
413 | | - |
414 | << quint32(0) | - |
415 | | - |
416 | << quint32(0x5F0F3CF5) | - |
417 | << quint16(0) | - |
418 | | - |
419 | | - |
420 | << quint16(2048) | - |
421 | | - |
422 | << head.created | - |
423 | | - |
424 | << head.modified | - |
425 | | - |
426 | | - |
427 | | - |
428 | | - |
429 | << head.xMin | - |
430 | << head.yMin | - |
431 | << head.xMax | - |
432 | << head.yMax | - |
433 | << head.macStyle | - |
434 | | - |
435 | << quint16(6) | - |
436 | | - |
437 | << qint16(0) | - |
438 | | - |
439 | | - |
440 | | - |
441 | | - |
442 | | - |
443 | << head.indexToLocFormat | - |
444 | | - |
445 | << qint16(0); | - |
446 | | - |
447 | qt_noop(); | - |
448 | return t; never executed: return t; | 0 |
449 | } | - |
450 | | - |
451 | | - |
452 | static QTtfTable generateHhea(const qttf_hhea_table &hhea) | - |
453 | { | - |
454 | const int hhea_size = 36; | - |
455 | QTtfTable t; | - |
456 | t.tag = ( (((quint32)('h')) << 24) | (((quint32)('h')) << 16) | (((quint32)('e')) << 8) | ((quint32)('a')) ); | - |
457 | t.data.resize(hhea_size); | - |
458 | | - |
459 | QTtfStream s(t.data); | - |
460 | | - |
461 | s << qint32(0x00010000) | - |
462 | | - |
463 | << hhea.ascender | - |
464 | | - |
465 | << hhea.descender | - |
466 | | - |
467 | | - |
468 | | - |
469 | | - |
470 | << hhea.lineGap | - |
471 | | - |
472 | << hhea.maxAdvanceWidth | - |
473 | | - |
474 | << hhea.minLeftSideBearing | - |
475 | | - |
476 | << hhea.minRightSideBearing | - |
477 | | - |
478 | << hhea.xMaxExtent | - |
479 | | - |
480 | << qint16(1) | - |
481 | | - |
482 | << qint16(0) | - |
483 | | - |
484 | << qint16(0) | - |
485 | | - |
486 | << qint16(0) | - |
487 | | - |
488 | << qint16(0) | - |
489 | | - |
490 | << qint16(0) | - |
491 | | - |
492 | << qint16(0) | - |
493 | | - |
494 | << qint16(0) | - |
495 | | - |
496 | << hhea.numberOfHMetrics; | - |
497 | | - |
498 | qt_noop(); | - |
499 | return t; never executed: return t; | 0 |
500 | } | - |
501 | | - |
502 | | - |
503 | static QTtfTable generateMaxp(const qttf_maxp_table &maxp) | - |
504 | { | - |
505 | const int maxp_size = 32; | - |
506 | QTtfTable t; | - |
507 | t.tag = ( (((quint32)('m')) << 24) | (((quint32)('a')) << 16) | (((quint32)('x')) << 8) | ((quint32)('p')) ); | - |
508 | t.data.resize(maxp_size); | - |
509 | | - |
510 | QTtfStream s(t.data); | - |
511 | | - |
512 | | - |
513 | s << qint32(0x00010000) | - |
514 | | - |
515 | << maxp.numGlyphs | - |
516 | | - |
517 | << maxp.maxPoints | - |
518 | | - |
519 | << maxp.maxContours | - |
520 | | - |
521 | << maxp.maxCompositePoints | - |
522 | | - |
523 | << maxp.maxCompositeContours | - |
524 | | - |
525 | << quint16(1) | - |
526 | | - |
527 | << quint16(0) | - |
528 | | - |
529 | << quint16(0) | - |
530 | | - |
531 | << quint16(0) | - |
532 | | - |
533 | << quint16(0) | - |
534 | | - |
535 | << quint16(0) | - |
536 | | - |
537 | << quint16(0) | - |
538 | | - |
539 | << maxp.maxComponentElements | - |
540 | | - |
541 | << maxp.maxComponentDepth; | - |
542 | | - |
543 | qt_noop(); | - |
544 | return t; never executed: return t; | 0 |
545 | } | - |
546 | | - |
547 | struct QTtfNameRecord { | - |
548 | quint16 nameId; | - |
549 | QString value; | - |
550 | }; | - |
551 | | - |
552 | static QTtfTable generateName(const QList<QTtfNameRecord> &name); | - |
553 | | - |
554 | static QTtfTable generateName(const qttf_name_table &name) | - |
555 | { | - |
556 | QList<QTtfNameRecord> list; | - |
557 | QTtfNameRecord rec; | - |
558 | rec.nameId = 0; | - |
559 | rec.value = name.copyright; | - |
560 | list.append(rec); | - |
561 | rec.nameId = 1; | - |
562 | rec.value = name.family; | - |
563 | list.append(rec); | - |
564 | rec.nameId = 2; | - |
565 | rec.value = name.subfamily; | - |
566 | list.append(rec); | - |
567 | rec.nameId = 4; | - |
568 | rec.value = name.family; | - |
569 | if (name.subfamily != QLatin1String("Regular")) never evaluated: name.subfamily != QLatin1String("Regular") | 0 |
570 | rec.value += QLatin1Char(' ') + name.subfamily; never executed: rec.value += QLatin1Char(' ') + name.subfamily; | 0 |
571 | list.append(rec); | - |
572 | rec.nameId = 6; | - |
573 | rec.value = name.postscript_name; | - |
574 | list.append(rec); | - |
575 | | - |
576 | return generateName(list); never executed: return generateName(list); | 0 |
577 | } | - |
578 | | - |
579 | | - |
580 | static QTtfTable generateName(const QList<QTtfNameRecord> &name) | - |
581 | { | - |
582 | const int char_size = 2; | - |
583 | | - |
584 | QTtfTable t; | - |
585 | t.tag = ( (((quint32)('n')) << 24) | (((quint32)('a')) << 16) | (((quint32)('m')) << 8) | ((quint32)('e')) ); | - |
586 | | - |
587 | const int name_size = 6 + 12*name.size(); | - |
588 | int string_size = 0; | - |
589 | for (int i = 0; i < name.size(); ++i) { never evaluated: i < name.size() | 0 |
590 | string_size += name.at(i).value.length()*char_size; | - |
591 | } | 0 |
592 | t.data.resize(name_size + string_size); | - |
593 | | - |
594 | QTtfStream s(t.data); | - |
595 | | - |
596 | s << quint16(0) | - |
597 | | - |
598 | << quint16(name.size()) | - |
599 | | - |
600 | << quint16(name_size); | - |
601 | | - |
602 | | - |
603 | | - |
604 | int off = 0; | - |
605 | for (int i = 0; i < name.size(); ++i) { never evaluated: i < name.size() | 0 |
606 | int len = name.at(i).value.length()*char_size; | - |
607 | | - |
608 | | - |
609 | | - |
610 | s << quint16(3) | - |
611 | << quint16(1) | - |
612 | << quint16(0x0409) | - |
613 | | - |
614 | << name.at(i).nameId | - |
615 | | - |
616 | << quint16(len) | - |
617 | | - |
618 | << quint16(off); | - |
619 | off += len; | - |
620 | } | 0 |
621 | for (int i = 0; i < name.size(); ++i) { never evaluated: i < name.size() | 0 |
622 | const QString &n = name.at(i).value; | - |
623 | const ushort *uc = n.utf16(); | - |
624 | for (int i = 0; i < n.length(); ++i) { never evaluated: i < n.length() | 0 |
625 | s << quint16(*uc); | - |
626 | ++uc; | - |
627 | } | 0 |
628 | } | 0 |
629 | return t; never executed: return t; | 0 |
630 | } | - |
631 | | - |
632 | | - |
633 | enum Flags { | - |
634 | OffCurve = 0, | - |
635 | OnCurve = (1 << 0), | - |
636 | XShortVector = (1 << 1), | - |
637 | YShortVector = (1 << 2), | - |
638 | Repeat = (1 << 3), | - |
639 | XSame = (1 << 4), | - |
640 | XShortPositive = (1 << 4), | - |
641 | YSame = (1 << 5), | - |
642 | YShortPositive = (1 << 5) | - |
643 | }; | - |
644 | struct TTF_POINT { | - |
645 | qint16 x; | - |
646 | qint16 y; | - |
647 | quint8 flags; | - |
648 | }; | - |
649 | template<> class QTypeInfo<TTF_POINT > { public: enum { isComplex = (((Q_PRIMITIVE_TYPE) & Q_PRIMITIVE_TYPE) == 0), isStatic = (((Q_PRIMITIVE_TYPE) & (Q_MOVABLE_TYPE | Q_PRIMITIVE_TYPE)) == 0), isLarge = (sizeof(TTF_POINT)>sizeof(void*)), isPointer = false, isDummy = (((Q_PRIMITIVE_TYPE) & Q_DUMMY_TYPE) != 0), sizeOf = sizeof(TTF_POINT) }; static inline const char *name() { return "TTF_POINT"; } }; | - |
650 | | - |
651 | static void convertPath(const QPainterPath &path, QList<TTF_POINT> *points, QList<int> *endPoints, qreal ppem) | - |
652 | { | - |
653 | int numElements = path.elementCount(); | - |
654 | for (int i = 0; i < numElements - 1; ++i) { never evaluated: i < numElements - 1 | 0 |
655 | const QPainterPath::Element &e = path.elementAt(i); | - |
656 | TTF_POINT p; | - |
657 | p.x = qRound(e.x * 2048. / ppem); | - |
658 | p.y = qRound(-e.y * 2048. / ppem); | - |
659 | p.flags = 0; | - |
660 | | - |
661 | switch(e.type) { | - |
662 | case QPainterPath::MoveToElement: | - |
663 | if (i != 0) { | 0 |
664 | | - |
665 | int start = endPoints->size() ? endPoints->at(endPoints->size()-1) - 1 : 0; never evaluated: endPoints->size() | 0 |
666 | int end = points->size() - 1; | - |
667 | if (points->at(end).x == points->at(start).x never evaluated: points->at(end).x == points->at(start).x | 0 |
668 | && points->at(end).y == points->at(start).y) never evaluated: points->at(end).y == points->at(start).y | 0 |
669 | points->takeLast(); never executed: points->takeLast(); | 0 |
670 | endPoints->append(points->size() - 1); | - |
671 | } | 0 |
672 | | - |
673 | case QPainterPath::LineToElement: code before this statement never executed: case QPainterPath::LineToElement: | 0 |
674 | p.flags = OnCurve; | - |
675 | break; | 0 |
676 | case QPainterPath::CurveToElement: { | - |
677 | | - |
678 | TTF_POINT list[3*16 + 4]; | - |
679 | list[3] = points->at(points->size() - 1); | - |
680 | list[2] = p; | - |
681 | const QPainterPath::Element &e2 = path.elementAt(++i); | - |
682 | list[1].x = qRound(e2.x * 2048. / ppem); | - |
683 | list[1].y = qRound(-e2.y * 2048. / ppem); | - |
684 | const QPainterPath::Element &e3 = path.elementAt(++i); | - |
685 | list[0].x = qRound(e3.x * 2048. / ppem); | - |
686 | list[0].y = qRound(-e3.y * 2048. / ppem); | - |
687 | | - |
688 | TTF_POINT *base = list; | - |
689 | | - |
690 | bool try_reduce = points->size() > 1 never evaluated: points->size() > 1 | 0 |
691 | && points->at(points->size() - 1).flags == OnCurve never evaluated: points->at(points->size() - 1).flags == OnCurve | 0 |
692 | && points->at(points->size() - 2).flags == OffCurve; never evaluated: points->at(points->size() - 2).flags == OffCurve | 0 |
693 | | - |
694 | while (base >= list) { never evaluated: base >= list | 0 |
695 | const int split_limit = 3; | - |
696 | qt_noop(); | - |
697 | | - |
698 | int i1_x = base[1].x + ((base[1].x - base[0].x) >> 1); | - |
699 | int i1_y = base[1].y + ((base[1].y - base[0].y) >> 1); | - |
700 | int i2_x = base[2].x + ((base[2].x - base[3].x) >> 1); | - |
701 | int i2_y = base[2].y + ((base[2].y - base[3].y) >> 1); | - |
702 | | - |
703 | if (qAbs(i1_x - i2_x) <= split_limit && qAbs(i1_y - i2_y) <= split_limit) { never evaluated: qAbs(i1_x - i2_x) <= split_limit never evaluated: qAbs(i1_y - i2_y) <= split_limit | 0 |
704 | | - |
705 | TTF_POINT np; | - |
706 | np.x = (i1_x + i2_x) >> 1; | - |
707 | np.y = (i1_y + i2_y) >> 1; | - |
708 | if (try_reduce) { never evaluated: try_reduce | 0 |
709 | | - |
710 | int mx = (points->at(points->size() - 2).x + base[2].x) >> 1; | - |
711 | int my = (points->at(points->size() - 2).y + base[2].y) >> 1; | - |
712 | if (qAbs(mx - base[3].x) <= split_limit && qAbs(my = base[3].y) <= split_limit) never evaluated: qAbs(mx - base[3].x) <= split_limit never evaluated: qAbs(my = base[3].y) <= split_limit | 0 |
713 | points->takeLast(); never executed: points->takeLast(); | 0 |
714 | try_reduce = false; | - |
715 | } | 0 |
716 | np.flags = OffCurve; | - |
717 | points->append(np); | - |
718 | | - |
719 | base -= 3; | - |
720 | } else { | 0 |
721 | | - |
722 | | - |
723 | qint16 a, b, c, d; | - |
724 | base[6].x = base[3].x; | - |
725 | c = base[1].x; | - |
726 | d = base[2].x; | - |
727 | base[1].x = a = ( base[0].x + c ) >> 1; | - |
728 | base[5].x = b = ( base[3].x + d ) >> 1; | - |
729 | c = ( c + d ) >> 1; | - |
730 | base[2].x = a = ( a + c ) >> 1; | - |
731 | base[4].x = b = ( b + c ) >> 1; | - |
732 | base[3].x = ( a + b ) >> 1; | - |
733 | | - |
734 | base[6].y = base[3].y; | - |
735 | c = base[1].y; | - |
736 | d = base[2].y; | - |
737 | base[1].y = a = ( base[0].y + c ) >> 1; | - |
738 | base[5].y = b = ( base[3].y + d ) >> 1; | - |
739 | c = ( c + d ) >> 1; | - |
740 | base[2].y = a = ( a + c ) >> 1; | - |
741 | base[4].y = b = ( b + c ) >> 1; | - |
742 | base[3].y = ( a + b ) >> 1; | - |
743 | base += 3; | - |
744 | } | 0 |
745 | } | - |
746 | p = list[0]; | - |
747 | p.flags = OnCurve; | - |
748 | break; | 0 |
749 | } | - |
750 | case QPainterPath::CurveToDataElement: | - |
751 | qt_noop(); | - |
752 | break; | 0 |
753 | } | - |
754 | | - |
755 | points->append(p); | - |
756 | } | 0 |
757 | int start = endPoints->size() ? endPoints->at(endPoints->size()-1) + 1 : 0; never evaluated: endPoints->size() | 0 |
758 | int end = points->size() - 1; | - |
759 | if (points->at(end).x == points->at(start).x never evaluated: points->at(end).x == points->at(start).x | 0 |
760 | && points->at(end).y == points->at(start).y) never evaluated: points->at(end).y == points->at(start).y | 0 |
761 | points->takeLast(); never executed: points->takeLast(); | 0 |
762 | endPoints->append(points->size() - 1); | - |
763 | } | 0 |
764 | | - |
765 | static void getBounds(const QList<TTF_POINT> &points, qint16 *xmin, qint16 *xmax, qint16 *ymin, qint16 *ymax) | - |
766 | { | - |
767 | *xmin = points.at(0).x; | - |
768 | *xmax = *xmin; | - |
769 | *ymin = points.at(0).y; | - |
770 | *ymax = *ymin; | - |
771 | | - |
772 | for (int i = 1; i < points.size(); ++i) { never evaluated: i < points.size() | 0 |
773 | *xmin = qMin(*xmin, points.at(i).x); | - |
774 | *xmax = qMax(*xmax, points.at(i).x); | - |
775 | *ymin = qMin(*ymin, points.at(i).y); | - |
776 | *ymax = qMax(*ymax, points.at(i).y); | - |
777 | } | 0 |
778 | } | 0 |
779 | | - |
780 | static int convertToRelative(QList<TTF_POINT> *points) | - |
781 | { | - |
782 | | - |
783 | | - |
784 | qint16 prev_x = 0; | - |
785 | qint16 prev_y = 0; | - |
786 | int point_array_size = 0; | - |
787 | for (int i = 0; i < points->size(); ++i) { never evaluated: i < points->size() | 0 |
788 | const int x = points->at(i).x; | - |
789 | const int y = points->at(i).y; | - |
790 | TTF_POINT rel; | - |
791 | rel.x = x - prev_x; | - |
792 | rel.y = y - prev_y; | - |
793 | rel.flags = points->at(i).flags; | - |
794 | qt_noop(); | - |
795 | if (!rel.x) { | 0 |
796 | rel.flags |= XSame; | - |
797 | } else if (rel.x > 0 && rel.x < 256) { never evaluated: rel.x > 0 never evaluated: rel.x < 256 | 0 |
798 | rel.flags |= XShortVector|XShortPositive; | - |
799 | point_array_size++; | - |
800 | } else if (rel.x < 0 && rel.x > -256) { never evaluated: rel.x < 0 never evaluated: rel.x > -256 | 0 |
801 | rel.flags |= XShortVector; | - |
802 | rel.x = -rel.x; | - |
803 | point_array_size++; | - |
804 | } else { | 0 |
805 | point_array_size += 2; | - |
806 | } | 0 |
807 | if (!rel.y) { | 0 |
808 | rel.flags |= YSame; | - |
809 | } else if (rel.y > 0 && rel.y < 256) { never evaluated: rel.y > 0 never evaluated: rel.y < 256 | 0 |
810 | rel.flags |= YShortVector|YShortPositive; | - |
811 | point_array_size++; | - |
812 | } else if (rel.y < 0 && rel.y > -256) { never evaluated: rel.y < 0 never evaluated: rel.y > -256 | 0 |
813 | rel.flags |= YShortVector; | - |
814 | rel.y = -rel.y; | - |
815 | point_array_size++; | - |
816 | } else { | 0 |
817 | point_array_size += 2; | - |
818 | } | 0 |
819 | (*points)[i] = rel; | - |
820 | | - |
821 | | - |
822 | | - |
823 | | - |
824 | | - |
825 | | - |
826 | | - |
827 | prev_x = x; | - |
828 | prev_y = y; | - |
829 | } | 0 |
830 | return point_array_size; never executed: return point_array_size; | 0 |
831 | } | - |
832 | | - |
833 | static void getGlyphData(QTtfGlyph *glyph, const QList<TTF_POINT> &points, const QList<int> &endPoints, int point_array_size) | - |
834 | { | - |
835 | const int max_size = 5*sizeof(qint16) | - |
836 | + endPoints.size()*sizeof(quint16) | - |
837 | + sizeof(quint16) | - |
838 | + points.size()*(1) | - |
839 | + point_array_size; | - |
840 | | - |
841 | glyph->data.resize(max_size); | - |
842 | | - |
843 | QTtfStream s(glyph->data); | - |
844 | s << qint16(endPoints.size()) | - |
845 | << glyph->xMin << glyph->yMin << glyph->xMax << glyph->yMax; | - |
846 | | - |
847 | for (int i = 0; i < endPoints.size(); ++i) never evaluated: i < endPoints.size() | 0 |
848 | s << quint16(endPoints.at(i)); never executed: s << quint16(endPoints.at(i)); | 0 |
849 | s << quint16(0); | - |
850 | | - |
851 | | - |
852 | for (int i = 0; i < points.size(); ++i) never evaluated: i < points.size() | 0 |
853 | s << quint8(points.at(i).flags); never executed: s << quint8(points.at(i).flags); | 0 |
854 | | - |
855 | for (int i = 0; i < points.size(); ++i) { never evaluated: i < points.size() | 0 |
856 | quint8 flags = points.at(i).flags; | - |
857 | qint16 x = points.at(i).x; | - |
858 | | - |
859 | if (flags & XShortVector) never evaluated: flags & XShortVector | 0 |
860 | s << quint8(x); never executed: s << quint8(x); | 0 |
861 | else if (!(flags & XSame)) never evaluated: !(flags & XSame) | 0 |
862 | s << qint16(x); never executed: s << qint16(x); | 0 |
863 | } | - |
864 | for (int i = 0; i < points.size(); ++i) { never evaluated: i < points.size() | 0 |
865 | quint8 flags = points.at(i).flags; | - |
866 | qint16 y = points.at(i).y; | - |
867 | | - |
868 | if (flags & YShortVector) never evaluated: flags & YShortVector | 0 |
869 | s << quint8(y); never executed: s << quint8(y); | 0 |
870 | else if (!(flags & YSame)) never evaluated: !(flags & YSame) | 0 |
871 | s << qint16(y); never executed: s << qint16(y); | 0 |
872 | } | - |
873 | | - |
874 | | - |
875 | qt_noop(); | - |
876 | | - |
877 | glyph->numContours = endPoints.size(); | - |
878 | glyph->numPoints = points.size(); | - |
879 | } | 0 |
880 | | - |
881 | static QTtfGlyph generateGlyph(int index, const QPainterPath &path, qreal advance, qreal lsb, qreal ppem) | - |
882 | { | - |
883 | QList<TTF_POINT> points; | - |
884 | QList<int> endPoints; | - |
885 | QTtfGlyph glyph; | - |
886 | glyph.index = index; | - |
887 | glyph.advanceWidth = qRound(advance * 2048. / ppem); | - |
888 | glyph.lsb = qRound(lsb * 2048. / ppem); | - |
889 | | - |
890 | if (!path.elementCount()) { never evaluated: !path.elementCount() | 0 |
891 | | - |
892 | lsb = 0; | - |
893 | glyph.xMin = glyph.xMax = glyph.yMin = glyph.yMax = 0; | - |
894 | glyph.numContours = 0; | - |
895 | glyph.numPoints = 0; | - |
896 | return glyph; never executed: return glyph; | 0 |
897 | } | - |
898 | | - |
899 | convertPath(path, &points, &endPoints, ppem); | - |
900 | getBounds(points, &glyph.xMin, &glyph.xMax, &glyph.yMin, &glyph.yMax); | - |
901 | int point_array_size = convertToRelative(&points); | - |
902 | getGlyphData(&glyph, points, endPoints, point_array_size); | - |
903 | return glyph; never executed: return glyph; | 0 |
904 | } | - |
905 | | - |
906 | static bool operator <(const QTtfGlyph &g1, const QTtfGlyph &g2) | - |
907 | { | - |
908 | return g1.index < g2.index; never executed: return g1.index < g2.index; | 0 |
909 | } | - |
910 | | - |
911 | static QList<QTtfTable> generateGlyphTables(qttf_font_tables &tables, const QList<QTtfGlyph> &_glyphs) | - |
912 | { | - |
913 | const int max_size_small = 65536*2; | - |
914 | QList<QTtfGlyph> glyphs = _glyphs; | - |
915 | qSort(glyphs); | - |
916 | | - |
917 | qt_noop(); | - |
918 | int nGlyphs = tables.maxp.numGlyphs; | - |
919 | | - |
920 | int glyf_size = 0; | - |
921 | for (int i = 0; i < glyphs.size(); ++i) never evaluated: i < glyphs.size() | 0 |
922 | glyf_size += (glyphs.at(i).data.size() + 3) & ~3; never executed: glyf_size += (glyphs.at(i).data.size() + 3) & ~3; | 0 |
923 | | - |
924 | tables.head.indexToLocFormat = glyf_size < max_size_small ? 0 : 1; never evaluated: glyf_size < max_size_small | 0 |
925 | tables.hhea.numberOfHMetrics = nGlyphs; | - |
926 | | - |
927 | QTtfTable glyf; | - |
928 | glyf.tag = ( (((quint32)('g')) << 24) | (((quint32)('l')) << 16) | (((quint32)('y')) << 8) | ((quint32)('f')) ); | - |
929 | | - |
930 | QTtfTable loca; | - |
931 | loca.tag = ( (((quint32)('l')) << 24) | (((quint32)('o')) << 16) | (((quint32)('c')) << 8) | ((quint32)('a')) ); | - |
932 | loca.data.resize(glyf_size < max_size_small ? (nGlyphs+1)*sizeof(quint16) : (nGlyphs+1)*sizeof(quint32)); | - |
933 | QTtfStream ls(loca.data); | - |
934 | | - |
935 | QTtfTable hmtx; | - |
936 | hmtx.tag = ( (((quint32)('h')) << 24) | (((quint32)('m')) << 16) | (((quint32)('t')) << 8) | ((quint32)('x')) ); | - |
937 | hmtx.data.resize(nGlyphs*4); | - |
938 | QTtfStream hs(hmtx.data); | - |
939 | | - |
940 | int pos = 0; | - |
941 | for (int i = 0; i < nGlyphs; ++i) { never evaluated: i < nGlyphs | 0 |
942 | int gpos = glyf.data.size(); | - |
943 | quint16 advance = 0; | - |
944 | qint16 lsb = 0; | - |
945 | | - |
946 | if (glyphs[pos].index == i) { never evaluated: glyphs[pos].index == i | 0 |
947 | | - |
948 | | - |
949 | glyf.data += glyphs.at(pos).data; | - |
950 | while (glyf.data.size() & 1) never evaluated: glyf.data.size() & 1 | 0 |
951 | glyf.data.append('\0'); never executed: glyf.data.append('\0'); | 0 |
952 | advance = glyphs.at(pos).advanceWidth; | - |
953 | lsb = glyphs.at(pos).lsb; | - |
954 | ++pos; | - |
955 | } | 0 |
956 | if (glyf_size < max_size_small) { never evaluated: glyf_size < max_size_small | 0 |
957 | | - |
958 | ls << quint16(gpos>>1); | - |
959 | } else { | 0 |
960 | | - |
961 | ls << quint32(gpos); | - |
962 | } | 0 |
963 | hs << advance | - |
964 | << lsb; | - |
965 | } | 0 |
966 | if (glyf_size < max_size_small) { never evaluated: glyf_size < max_size_small | 0 |
967 | | - |
968 | ls << quint16(glyf.data.size()>>1); | - |
969 | } else { | 0 |
970 | | - |
971 | ls << quint32(glyf.data.size()); | - |
972 | } | 0 |
973 | | - |
974 | qt_noop(); | - |
975 | qt_noop(); | - |
976 | | - |
977 | QList<QTtfTable> list; | - |
978 | list.append(glyf); | - |
979 | list.append(loca); | - |
980 | list.append(hmtx); | - |
981 | return list; never executed: return list; | 0 |
982 | } | - |
983 | | - |
984 | static bool operator <(const QTtfTable &t1, const QTtfTable &t2) | - |
985 | { | - |
986 | return t1.tag < t2.tag; never executed: return t1.tag < t2.tag; | 0 |
987 | } | - |
988 | | - |
989 | static QByteArray bindFont(const QList<QTtfTable>& _tables) | - |
990 | { | - |
991 | QList<QTtfTable> tables = _tables; | - |
992 | | - |
993 | qSort(tables); | - |
994 | | - |
995 | QByteArray font; | - |
996 | const int header_size = sizeof(qint32) + 4*sizeof(quint16); | - |
997 | const int directory_size = 4*sizeof(quint32)*tables.size(); | - |
998 | font.resize(header_size + directory_size); | - |
999 | | - |
1000 | int log2 = 0; | - |
1001 | int pow = 1; | - |
1002 | int n = tables.size() >> 1; | - |
1003 | while (n) { | 0 |
1004 | ++log2; | - |
1005 | pow <<= 1; | - |
1006 | n >>= 1; | - |
1007 | } | 0 |
1008 | | - |
1009 | quint32 head_offset = 0; | - |
1010 | { | - |
1011 | QTtfStream f(font); | - |
1012 | | - |
1013 | | - |
1014 | | - |
1015 | | - |
1016 | | - |
1017 | | - |
1018 | | - |
1019 | f << qint32(0x00010000) | - |
1020 | << quint16(tables.size()) | - |
1021 | << quint16(16*pow) | - |
1022 | << quint16(log2) | - |
1023 | << quint16(16*(tables.size() - pow)); | - |
1024 | | - |
1025 | | - |
1026 | | - |
1027 | | - |
1028 | | - |
1029 | | - |
1030 | | - |
1031 | quint32 table_offset = header_size + directory_size; | - |
1032 | for (int i = 0; i < tables.size(); ++i) { never evaluated: i < tables.size() | 0 |
1033 | const QTtfTable &t = tables.at(i); | - |
1034 | const quint32 size = (t.data.size() + 3) & ~3; | - |
1035 | if (t.tag == ( (((quint32)('h')) << 24) | (((quint32)('e')) << 16) | (((quint32)('a')) << 8) | ((quint32)('d')) )) never evaluated: t.tag == ( (((quint32)('h')) << 24) | (((quint32)('e')) << 16) | (((quint32)('a')) << 8) | ((quint32)('d')) ) | 0 |
1036 | head_offset = table_offset; never executed: head_offset = table_offset; | 0 |
1037 | f << t.tag | - |
1038 | << checksum(t.data) | - |
1039 | << table_offset | - |
1040 | << t.data.size(); | - |
1041 | table_offset += size; | - |
1042 | | - |
1043 | | - |
1044 | } | 0 |
1045 | } | - |
1046 | for (int i = 0; i < tables.size(); ++i) { never evaluated: i < tables.size() | 0 |
1047 | const QByteArray &t = tables.at(i).data; | - |
1048 | font += t; | - |
1049 | int s = t.size(); | - |
1050 | while (s & 3) { font += '\0'; ++s; } | 0 |
1051 | } | 0 |
1052 | | - |
1053 | if (!head_offset) { never evaluated: !head_offset | 0 |
1054 | QMessageLogger("text/qfontsubset.cpp", 1137, __PRETTY_FUNCTION__).warning("QFontSubset: Font misses 'head' table"); | - |
1055 | return QByteArray(); never executed: return QByteArray(); | 0 |
1056 | } | - |
1057 | | - |
1058 | | - |
1059 | quint32 checksum_adjust = 0xB1B0AFBA - checksum(font); | - |
1060 | qToBigEndian(checksum_adjust, (uchar *)font.data() + head_offset + 8); | - |
1061 | | - |
1062 | return font; never executed: return font; | 0 |
1063 | } | - |
1064 | QByteArray QFontSubset::toTruetype() const | - |
1065 | { | - |
1066 | qttf_font_tables font; | - |
1067 | memset(&font, 0, sizeof(qttf_font_tables)); | - |
1068 | | - |
1069 | qreal ppem = fontEngine->fontDef.pixelSize; | - |
1070 | | - |
1071 | QList<QTtfGlyph> glyphs; | - |
1072 | | - |
1073 | QFontEngine::Properties properties = fontEngine->properties(); | - |
1074 | | - |
1075 | emSquare = 2048; | - |
1076 | widths.resize(nGlyphs()); | - |
1077 | | - |
1078 | | - |
1079 | font.head.font_revision = 0x00010000; | - |
1080 | font.head.flags = (1 << 2) | (1 << 4); | - |
1081 | font.head.created = 0; | - |
1082 | font.head.modified = 0; | - |
1083 | font.head.xMin = 32767; | - |
1084 | font.head.xMax = (-32767 - 1); | - |
1085 | font.head.yMin = 32767; | - |
1086 | font.head.yMax = (-32767 - 1); | - |
1087 | font.head.macStyle = (fontEngine->fontDef.weight > QFont::Normal) ? 1 : 0; never evaluated: (fontEngine->fontDef.weight > QFont::Normal) | 0 |
1088 | font.head.macStyle |= (fontEngine->fontDef.styleHint != QFont::StyleNormal) ? 1 : 0; never evaluated: (fontEngine->fontDef.styleHint != QFont::StyleNormal) | 0 |
1089 | | - |
1090 | | - |
1091 | font.hhea.ascender = qRound(properties.ascent); | - |
1092 | font.hhea.descender = -qRound(properties.descent); | - |
1093 | font.hhea.lineGap = qRound(properties.leading); | - |
1094 | font.hhea.maxAdvanceWidth = qRound(fontEngine->maxCharWidth() * 2048. / ppem); | - |
1095 | font.hhea.minLeftSideBearing = qRound(fontEngine->minLeftBearing() * 2048. / ppem); | - |
1096 | font.hhea.minRightSideBearing = qRound(fontEngine->minRightBearing() * 2048. / ppem); | - |
1097 | font.hhea.xMaxExtent = (-32767 - 1); | - |
1098 | | - |
1099 | font.maxp.numGlyphs = 0; | - |
1100 | font.maxp.maxPoints = 0; | - |
1101 | font.maxp.maxContours = 0; | - |
1102 | font.maxp.maxCompositePoints = 0; | - |
1103 | font.maxp.maxCompositeContours = 0; | - |
1104 | font.maxp.maxComponentElements = 0; | - |
1105 | font.maxp.maxComponentDepth = 0; | - |
1106 | font.maxp.numGlyphs = nGlyphs(); | - |
1107 | | - |
1108 | | - |
1109 | | - |
1110 | uint sumAdvances = 0; | - |
1111 | for (int i = 0; i < nGlyphs(); ++i) { never evaluated: i < nGlyphs() | 0 |
1112 | glyph_t g = glyph_indices.at(i); | - |
1113 | QPainterPath path; | - |
1114 | glyph_metrics_t metric; | - |
1115 | fontEngine->getUnscaledGlyph(g, &path, &metric); | - |
1116 | if (noEmbed) { | 0 |
1117 | path = QPainterPath(); | - |
1118 | if (g == 0) | 0 |
1119 | path.addRect(QRectF(0, 0, 1000, 1000)); never executed: path.addRect(QRectF(0, 0, 1000, 1000)); | 0 |
1120 | } | 0 |
1121 | QTtfGlyph glyph = generateGlyph(i, path, metric.xoff.toReal(), metric.x.toReal(), properties.emSquare.toReal()); | - |
1122 | | - |
1123 | font.head.xMin = qMin(font.head.xMin, glyph.xMin); | - |
1124 | font.head.xMax = qMax(font.head.xMax, glyph.xMax); | - |
1125 | font.head.yMin = qMin(font.head.yMin, glyph.yMin); | - |
1126 | font.head.yMax = qMax(font.head.yMax, glyph.yMax); | - |
1127 | | - |
1128 | font.hhea.xMaxExtent = qMax(font.hhea.xMaxExtent, (qint16)(glyph.lsb + glyph.xMax - glyph.xMin)); | - |
1129 | | - |
1130 | font.maxp.maxPoints = qMax(font.maxp.maxPoints, glyph.numPoints); | - |
1131 | font.maxp.maxContours = qMax(font.maxp.maxContours, glyph.numContours); | - |
1132 | | - |
1133 | if (glyph.xMax > glyph.xMin) never evaluated: glyph.xMax > glyph.xMin | 0 |
1134 | sumAdvances += glyph.xMax - glyph.xMin; never executed: sumAdvances += glyph.xMax - glyph.xMin; | 0 |
1135 | | - |
1136 | | - |
1137 | glyphs.append(glyph); | - |
1138 | widths[i] = glyph.advanceWidth; | - |
1139 | } | 0 |
1140 | | - |
1141 | | - |
1142 | QList<QTtfTable> tables = generateGlyphTables(font, glyphs); | - |
1143 | tables.append(generateHead(font.head)); | - |
1144 | tables.append(generateHhea(font.hhea)); | - |
1145 | tables.append(generateMaxp(font.maxp)); | - |
1146 | | - |
1147 | QTtfTable name_table; | - |
1148 | name_table.tag = ( (((quint32)('n')) << 24) | (((quint32)('a')) << 16) | (((quint32)('m')) << 8) | ((quint32)('e')) ); | - |
1149 | if (!noEmbed) never evaluated: !noEmbed | 0 |
1150 | name_table.data = fontEngine->getSfntTable(name_table.tag); never executed: name_table.data = fontEngine->getSfntTable(name_table.tag); | 0 |
1151 | if (name_table.data.isEmpty()) { never evaluated: name_table.data.isEmpty() | 0 |
1152 | qttf_name_table name; | - |
1153 | if (noEmbed) | 0 |
1154 | name.copyright = QLatin1String("Fake font"); never executed: name.copyright = QLatin1String("Fake font"); | 0 |
1155 | else | - |
1156 | name.copyright = QLatin1String(properties.copyright); never executed: name.copyright = QLatin1String(properties.copyright); | 0 |
1157 | name.family = fontEngine->fontDef.family; | - |
1158 | name.subfamily = QLatin1String("Regular"); | - |
1159 | name.postscript_name = QLatin1String(properties.postscriptName); | - |
1160 | name_table = generateName(name); | - |
1161 | } | 0 |
1162 | tables.append(name_table); | - |
1163 | | - |
1164 | if (!noEmbed) { never evaluated: !noEmbed | 0 |
1165 | QTtfTable os2; | - |
1166 | os2.tag = ( (((quint32)('O')) << 24) | (((quint32)('S')) << 16) | (((quint32)('/')) << 8) | ((quint32)('2')) ); | - |
1167 | os2.data = fontEngine->getSfntTable(os2.tag); | - |
1168 | if (!os2.data.isEmpty()) never evaluated: !os2.data.isEmpty() | 0 |
1169 | tables.append(os2); never executed: tables.append(os2); | 0 |
1170 | } | 0 |
1171 | | - |
1172 | return bindFont(tables); never executed: return bindFont(tables); | 0 |
1173 | } | - |
1174 | | - |
1175 | | - |
1176 | | - |
| | |