1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtGui module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qfontsubset_p.h"
44 #include <qpainterpath.h>
45 #include "private/qpdf_p.h"
46 #include "private/qfunctions_p.h"
49 #include "private/qfontengine_x11_p.h"
52 #ifndef QT_NO_FREETYPE
53 #if defined(Q_WS_X11) || defined(Q_WS_QWS)
54 # include "private/qfontengine_ft_p.h"
57 #include FT_FREETYPE_H
62 static const char * const agl =
63 ".notdef\0space\0exclam\0quotedbl\0numbersign\0dollar\0percent\0ampersand\0"
64 "quotesingle\0parenleft\0parenright\0asterisk\0plus\0comma\0hyphen\0period\0"
65 "slash\0zero\0one\0two\0three\0four\0five\0six\0seven\0eight\0nine\0colon\0"
66 "semicolon\0less\0equal\0greater\0question\0at\0A\0B\0C\0D\0E\0F\0G\0H\0I\0J\0"
67 "K\0L\0M\0N\0O\0P\0Q\0R\0S\0T\0U\0V\0W\0X\0Y\0Z\0bracketleft\0backslash\0"
68 "bracketright\0asciicircum\0underscore\0grave\0a\0b\0c\0d\0e\0f\0g\0h\0i\0j\0"
69 "k\0l\0m\0n\0o\0p\0q\0r\0s\0t\0u\0v\0w\0x\0y\0z\0braceleft\0bar\0braceright\0"
70 "asciitilde\0space\0exclamdown\0cent\0sterling\0currency\0yen\0brokenbar\0"
71 "section\0dieresis\0copyright\0ordfeminine\0guillemotleft\0logicalnot\0"
72 "hyphen\0registered\0macron\0degree\0plusminus\0twosuperior\0threesuperior\0"
73 "acute\0mu\0paragraph\0periodcentered\0cedilla\0onesuperior\0ordmasculine\0"
74 "guillemotright\0onequarter\0onehalf\0threequarters\0questiondown\0Agrave\0"
75 "Aacute\0Acircumflex\0Atilde\0Adieresis\0Aring\0AE\0Ccedilla\0Egrave\0Eacute\0"
76 "Ecircumflex\0Edieresis\0Igrave\0Iacute\0Icircumflex\0Idieresis\0Eth\0Ntilde\0"
77 "Ograve\0Oacute\0Ocircumflex\0Otilde\0Odieresis\0multiply\0Oslash\0Ugrave\0"
78 "Uacute\0Ucircumflex\0Udieresis\0Yacute\0Thorn\0germandbls\0agrave\0aacute\0"
79 "acircumflex\0atilde\0adieresis\0aring\0ae\0ccedilla\0egrave\0eacute\0"
80 "ecircumflex\0edieresis\0igrave\0iacute\0icircumflex\0idieresis\0eth\0ntilde\0"
81 "ograve\0oacute\0ocircumflex\0otilde\0odieresis\0divide\0oslash\0ugrave\0"
82 "uacute\0ucircumflex\0udieresis\0yacute\0thorn\0ydieresis\0Amacron\0amacron\0"
83 "Abreve\0abreve\0Aogonek\0aogonek\0Cacute\0cacute\0Ccircumflex\0ccircumflex\0"
84 "Cdotaccent\0cdotaccent\0Ccaron\0ccaron\0Dcaron\0dcaron\0Dcroat\0dcroat\0"
85 "Emacron\0emacron\0Ebreve\0ebreve\0Edotaccent\0edotaccent\0Eogonek\0eogonek\0"
86 "Ecaron\0ecaron\0Gcircumflex\0gcircumflex\0Gbreve\0gbreve\0Gdotaccent\0"
87 "gdotaccent\0Gcommaaccent\0gcommaaccent\0Hcircumflex\0hcircumflex\0Hbar\0"
88 "hbar\0Itilde\0itilde\0Imacron\0imacron\0Ibreve\0ibreve\0Iogonek\0iogonek\0"
89 "Idotaccent\0dotlessi\0IJ\0ij\0Jcircumflex\0jcircumflex\0Kcommaaccent\0"
90 "kcommaaccent\0kgreenlandic\0Lacute\0lacute\0Lcommaaccent\0lcommaaccent\0"
91 "Lcaron\0lcaron\0Ldot\0ldot\0Lslash\0lslash\0Nacute\0nacute\0Ncommaaccent\0"
92 "ncommaaccent\0Ncaron\0ncaron\0napostrophe\0Eng\0eng\0Omacron\0omacron\0"
93 "Obreve\0obreve\0Ohungarumlaut\0ohungarumlaut\0OE\0oe\0Racute\0racute\0"
94 "Rcommaaccent\0rcommaaccent\0Rcaron\0rcaron\0Sacute\0sacute\0Scircumflex\0"
95 "scircumflex\0Scedilla\0scedilla\0Scaron\0scaron\0Tcaron\0tcaron\0Tbar\0tbar\0"
96 "Utilde\0utilde\0Umacron\0umacron\0Ubreve\0ubreve\0Uring\0uring\0"
97 "Uhungarumlaut\0uhungarumlaut\0Uogonek\0uogonek\0Wcircumflex\0wcircumflex\0"
98 "Ycircumflex\0ycircumflex\0Ydieresis\0Zacute\0zacute\0Zdotaccent\0zdotaccent\0"
99 "Zcaron\0zcaron\0longs\0florin\0Ohorn\0ohorn\0Uhorn\0uhorn\0Gcaron\0gcaron\0"
100 "Aringacute\0aringacute\0AEacute\0aeacute\0Oslashacute\0oslashacute\0"
101 "Scommaaccent\0scommaaccent\0Tcommaaccent\0tcommaaccent\0afii57929\0"
102 "afii64937\0circumflex\0caron\0breve\0dotaccent\0ring\0ogonek\0tilde\0"
103 "hungarumlaut\0gravecomb\0acutecomb\0tildecomb\0hookabovecomb\0dotbelowcomb\0"
104 "tonos\0dieresistonos\0Alphatonos\0anoteleia\0Epsilontonos\0Etatonos\0"
105 "Iotatonos\0Omicrontonos\0Upsilontonos\0Omegatonos\0iotadieresistonos\0Alpha\0"
106 "Beta\0Gamma\0Delta\0Epsilon\0Zeta\0Eta\0Theta\0Iota\0Kappa\0Lambda\0Mu\0Nu\0"
107 "Xi\0Omicron\0Pi\0Rho\0Sigma\0Tau\0Upsilon\0Phi\0Chi\0Psi\0Omega\0"
108 "Iotadieresis\0Upsilondieresis\0alphatonos\0epsilontonos\0etatonos\0"
109 "iotatonos\0upsilondieresistonos\0alpha\0beta\0gamma\0delta\0epsilon\0zeta\0"
110 "eta\0theta\0iota\0kappa\0lambda\0mu\0nu\0xi\0omicron\0pi\0rho\0sigma1\0"
111 "sigma\0tau\0upsilon\0phi\0chi\0psi\0omega\0iotadieresis\0upsilondieresis\0"
114 static const struct { quint16 u; quint16 index; } unicode_to_aglindex[] = {
115 {0x0000, 0}, {0x0020, 8}, {0x0021, 14}, {0x0022, 21},
116 {0x0023, 30}, {0x0024, 41}, {0x0025, 48}, {0x0026, 56},
117 {0x0027, 66}, {0x0028, 78}, {0x0029, 88}, {0x002A, 99},
118 {0x002B, 108}, {0x002C, 113}, {0x002D, 119}, {0x002E, 126},
119 {0x002F, 133}, {0x0030, 139}, {0x0031, 144}, {0x0032, 148},
120 {0x0033, 152}, {0x0034, 158}, {0x0035, 163}, {0x0036, 168},
121 {0x0037, 172}, {0x0038, 178}, {0x0039, 184}, {0x003A, 189},
122 {0x003B, 195}, {0x003C, 205}, {0x003D, 210}, {0x003E, 216},
123 {0x003F, 224}, {0x0040, 233}, {0x0041, 236}, {0x0042, 238},
124 {0x0043, 240}, {0x0044, 242}, {0x0045, 244}, {0x0046, 246},
125 {0x0047, 248}, {0x0048, 250}, {0x0049, 252}, {0x004A, 254},
126 {0x004B, 256}, {0x004C, 258}, {0x004D, 260}, {0x004E, 262},
127 {0x004F, 264}, {0x0050, 266}, {0x0051, 268}, {0x0052, 270},
128 {0x0053, 272}, {0x0054, 274}, {0x0055, 276}, {0x0056, 278},
129 {0x0057, 280}, {0x0058, 282}, {0x0059, 284}, {0x005A, 286},
130 {0x005B, 288}, {0x005C, 300}, {0x005D, 310}, {0x005E, 323},
131 {0x005F, 335}, {0x0060, 346}, {0x0061, 352}, {0x0062, 354},
132 {0x0063, 356}, {0x0064, 358}, {0x0065, 360}, {0x0066, 362},
133 {0x0067, 364}, {0x0068, 366}, {0x0069, 368}, {0x006A, 370},
134 {0x006B, 372}, {0x006C, 374}, {0x006D, 376}, {0x006E, 378},
135 {0x006F, 380}, {0x0070, 382}, {0x0071, 384}, {0x0072, 386},
136 {0x0073, 388}, {0x0074, 390}, {0x0075, 392}, {0x0076, 394},
137 {0x0077, 396}, {0x0078, 398}, {0x0079, 400}, {0x007A, 402},
138 {0x007B, 404}, {0x007C, 414}, {0x007D, 418}, {0x007E, 429},
139 {0x00A0, 440}, {0x00A1, 446}, {0x00A2, 457}, {0x00A3, 462},
140 {0x00A4, 471}, {0x00A5, 480}, {0x00A6, 484}, {0x00A7, 494},
141 {0x00A8, 502}, {0x00A9, 511}, {0x00AA, 521}, {0x00AB, 533},
142 {0x00AC, 547}, {0x00AD, 558}, {0x00AE, 565}, {0x00AF, 576},
143 {0x00B0, 583}, {0x00B1, 590}, {0x00B2, 600}, {0x00B3, 612},
144 {0x00B4, 626}, {0x00B5, 632}, {0x00B6, 635}, {0x00B7, 645},
145 {0x00B8, 660}, {0x00B9, 668}, {0x00BA, 680}, {0x00BB, 693},
146 {0x00BC, 708}, {0x00BD, 719}, {0x00BE, 727}, {0x00BF, 741},
147 {0x00C0, 754}, {0x00C1, 761}, {0x00C2, 768}, {0x00C3, 780},
148 {0x00C4, 787}, {0x00C5, 797}, {0x00C6, 803}, {0x00C7, 806},
149 {0x00C8, 815}, {0x00C9, 822}, {0x00CA, 829}, {0x00CB, 841},
150 {0x00CC, 851}, {0x00CD, 858}, {0x00CE, 865}, {0x00CF, 877},
151 {0x00D0, 887}, {0x00D1, 891}, {0x00D2, 898}, {0x00D3, 905},
152 {0x00D4, 912}, {0x00D5, 924}, {0x00D6, 931}, {0x00D7, 941},
153 {0x00D8, 950}, {0x00D9, 957}, {0x00DA, 964}, {0x00DB, 971},
154 {0x00DC, 983}, {0x00DD, 993}, {0x00DE, 1000}, {0x00DF, 1006},
155 {0x00E0, 1017}, {0x00E1, 1024}, {0x00E2, 1031}, {0x00E3, 1043},
156 {0x00E4, 1050}, {0x00E5, 1060}, {0x00E6, 1066}, {0x00E7, 1069},
157 {0x00E8, 1078}, {0x00E9, 1085}, {0x00EA, 1092}, {0x00EB, 1104},
158 {0x00EC, 1114}, {0x00ED, 1121}, {0x00EE, 1128}, {0x00EF, 1140},
159 {0x00F0, 1150}, {0x00F1, 1154}, {0x00F2, 1161}, {0x00F3, 1168},
160 {0x00F4, 1175}, {0x00F5, 1187}, {0x00F6, 1194}, {0x00F7, 1204},
161 {0x00F8, 1211}, {0x00F9, 1218}, {0x00FA, 1225}, {0x00FB, 1232},
162 {0x00FC, 1244}, {0x00FD, 1254}, {0x00FE, 1261}, {0x00FF, 1267},
163 {0x0100, 1277}, {0x0101, 1285}, {0x0102, 1293}, {0x0103, 1300},
164 {0x0104, 1307}, {0x0105, 1315}, {0x0106, 1323}, {0x0107, 1330},
165 {0x0108, 1337}, {0x0109, 1349}, {0x010A, 1361}, {0x010B, 1372},
166 {0x010C, 1383}, {0x010D, 1390}, {0x010E, 1397}, {0x010F, 1404},
167 {0x0110, 1411}, {0x0111, 1418}, {0x0112, 1425}, {0x0113, 1433},
168 {0x0114, 1441}, {0x0115, 1448}, {0x0116, 1455}, {0x0117, 1466},
169 {0x0118, 1477}, {0x0119, 1485}, {0x011A, 1493}, {0x011B, 1500},
170 {0x011C, 1507}, {0x011D, 1519}, {0x011E, 1531}, {0x011F, 1538},
171 {0x0120, 1545}, {0x0121, 1556}, {0x0122, 1567}, {0x0123, 1580},
172 {0x0124, 1593}, {0x0125, 1605}, {0x0126, 1617}, {0x0127, 1622},
173 {0x0128, 1627}, {0x0129, 1634}, {0x012A, 1641}, {0x012B, 1649},
174 {0x012C, 1657}, {0x012D, 1664}, {0x012E, 1671}, {0x012F, 1679},
175 {0x0130, 1687}, {0x0131, 1698}, {0x0132, 1707}, {0x0133, 1710},
176 {0x0134, 1713}, {0x0135, 1725}, {0x0136, 1737}, {0x0137, 1750},
177 {0x0138, 1763}, {0x0139, 1776}, {0x013A, 1783}, {0x013B, 1790},
178 {0x013C, 1803}, {0x013D, 1816}, {0x013E, 1823}, {0x013F, 1830},
179 {0x0140, 1835}, {0x0141, 1840}, {0x0142, 1847}, {0x0143, 1854},
180 {0x0144, 1861}, {0x0145, 1868}, {0x0146, 1881}, {0x0147, 1894},
181 {0x0148, 1901}, {0x0149, 1908}, {0x014A, 1920}, {0x014B, 1924},
182 {0x014C, 1928}, {0x014D, 1936}, {0x014E, 1944}, {0x014F, 1951},
183 {0x0150, 1958}, {0x0151, 1972}, {0x0152, 1986}, {0x0153, 1989},
184 {0x0154, 1992}, {0x0155, 1999}, {0x0156, 2006}, {0x0157, 2019},
185 {0x0158, 2032}, {0x0159, 2039}, {0x015A, 2046}, {0x015B, 2053},
186 {0x015C, 2060}, {0x015D, 2072}, {0x015E, 2084}, {0x015F, 2093},
187 {0x0160, 2102}, {0x0161, 2109}, {0x0164, 2116}, {0x0165, 2123},
188 {0x0166, 2130}, {0x0167, 2135}, {0x0168, 2140}, {0x0169, 2147},
189 {0x016A, 2154}, {0x016B, 2162}, {0x016C, 2170}, {0x016D, 2177},
190 {0x016E, 2184}, {0x016F, 2190}, {0x0170, 2196}, {0x0171, 2210},
191 {0x0172, 2224}, {0x0173, 2232}, {0x0174, 2240}, {0x0175, 2252},
192 {0x0176, 2264}, {0x0177, 2276}, {0x0178, 2288}, {0x0179, 2298},
193 {0x017A, 2305}, {0x017B, 2312}, {0x017C, 2323}, {0x017D, 2334},
194 {0x017E, 2341}, {0x017F, 2348}, {0x0192, 2354}, {0x01A0, 2361},
195 {0x01A1, 2367}, {0x01AF, 2373}, {0x01B0, 2379}, {0x01E6, 2385},
196 {0x01E7, 2392}, {0x01FA, 2399}, {0x01FB, 2410}, {0x01FC, 2421},
197 {0x01FD, 2429}, {0x01FE, 2437}, {0x01FF, 2449}, {0x0218, 2461},
198 {0x0219, 2474}, {0x021A, 2487}, {0x021B, 2500}, {0x02BC, 2513},
199 {0x02BD, 2523}, {0x02C6, 2533}, {0x02C7, 2544}, {0x02D8, 2550},
200 {0x02D9, 2556}, {0x02DA, 2566}, {0x02DB, 2571}, {0x02DC, 2578},
201 {0x02DD, 2584}, {0x0300, 2597}, {0x0301, 2607}, {0x0303, 2617},
202 {0x0309, 2627}, {0x0323, 2641}, {0x0384, 2654}, {0x0385, 2660},
203 {0x0386, 2674}, {0x0387, 2685}, {0x0388, 2695}, {0x0389, 2708},
204 {0x038A, 2717}, {0x038C, 2727}, {0x038E, 2740}, {0x038F, 2753},
205 {0x0390, 2764}, {0x0391, 2782}, {0x0392, 2788}, {0x0393, 2793},
206 {0x0394, 2799}, {0x0395, 2805}, {0x0396, 2813}, {0x0397, 2818},
207 {0x0398, 2822}, {0x0399, 2828}, {0x039A, 2833}, {0x039B, 2839},
208 {0x039C, 2846}, {0x039D, 2849}, {0x039E, 2852}, {0x039F, 2855},
209 {0x03A0, 2863}, {0x03A1, 2866}, {0x03A3, 2870}, {0x03A4, 2876},
210 {0x03A5, 2880}, {0x03A6, 2888}, {0x03A7, 2892}, {0x03A8, 2896},
211 {0x03A9, 2900}, {0x03AA, 2906}, {0x03AB, 2919}, {0x03AC, 2935},
212 {0x03AD, 2946}, {0x03AE, 2959}, {0x03AF, 2968}, {0x03B0, 2978},
213 {0x03B1, 2999}, {0x03B2, 3005}, {0x03B3, 3010}, {0x03B4, 3016},
214 {0x03B5, 3022}, {0x03B6, 3030}, {0x03B7, 3035}, {0x03B8, 3039},
215 {0x03B9, 3045}, {0x03BA, 3050}, {0x03BB, 3056}, {0x03BC, 3063},
216 {0x03BD, 3066}, {0x03BE, 3069}, {0x03BF, 3072}, {0x03C0, 3080},
217 {0x03C1, 3083}, {0x03C2, 3087}, {0x03C3, 3094}, {0x03C4, 3100},
218 {0x03C5, 3104}, {0x03C6, 3112}, {0x03C7, 3116}, {0x03C8, 3120},
219 {0x03C9, 3124}, {0x03CA, 3130}, {0x03CB, 3143}, {0x03CC, 3159},
220 {0x03CD, 3172}, {0x03CE, 3185}, {0x03D1, 3196}, {0x03D2, 3203},
221 {0x03D5, 3212}, {0x03D6, 3217}, {0xFFFF, 3224}
224 // This map is used for symbol fonts to get the correct glyph names for the latin range
225 static const unsigned short symbol_map[0x100] = {
226 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
227 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
228 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
229 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
230 0x0020, 0x0021, 0x2200, 0x0023, 0x2203, 0x0025, 0x0026, 0x220b,
231 0x0028, 0x0029, 0x2217, 0x002b, 0x002c, 0x2212, 0x002e, 0x002f,
232 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
233 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
235 0x2245, 0x0391, 0x0392, 0x03a7, 0x0394, 0x0395, 0x03a6, 0x0393,
236 0x0397, 0x0399, 0x03d1, 0x039a, 0x039b, 0x039c, 0x039d, 0x039f,
237 0x03a0, 0x0398, 0x03a1, 0x03a3, 0x03a4, 0x03a5, 0x03c2, 0x03a9,
238 0x039e, 0x03a8, 0x0396, 0x005b, 0x2234, 0x005d, 0x22a5, 0x005f,
239 0xf8e5, 0x03b1, 0x03b2, 0x03c7, 0x03b4, 0x03b5, 0x03c6, 0x03b3,
240 0x03b7, 0x03b9, 0x03d5, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03bf,
241 0x03c0, 0x03b8, 0x03c1, 0x03c3, 0x03c4, 0x03c5, 0x03d6, 0x03c9,
242 0x03be, 0x03c8, 0x03b6, 0x007b, 0x007c, 0x007d, 0x223c, 0x007f,
244 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
245 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
246 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
247 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
248 0x20ac, 0x03d2, 0x2023, 0x2264, 0x2044, 0x221e, 0x0192, 0x2263,
249 0x2666, 0x2665, 0x2660, 0x2194, 0x2190, 0x2191, 0x2192, 0x2193,
250 0x00b0, 0x00b1, 0x2033, 0x2265, 0x00d7, 0x221d, 0x2202, 0x2022,
251 0x00f7, 0x2260, 0x2261, 0x2248, 0x2026, 0xf8e6, 0xf8e7, 0x21b5,
253 0x2135, 0x2111, 0x211c, 0x2118, 0x2297, 0x2295, 0x2205, 0x2229,
254 0x222a, 0x2283, 0x2287, 0x2284, 0x2282, 0x2286, 0x2208, 0x2209,
255 0x2220, 0x2207, 0xf6da, 0xf6d9, 0xf6db, 0x220f, 0x221a, 0x22c5,
256 0x00ac, 0x2227, 0x2228, 0x21d4, 0x21d0, 0x21d1, 0x21d2, 0x21d3,
257 0x25ca, 0x2329, 0xf8e8, 0xf8e9, 0xf8ea, 0x2211, 0xf8eb, 0xf8ec,
258 0xf8ed, 0xf8ee, 0xf8ef, 0xf8f0, 0xf8f1, 0xf8f2, 0xf8f3, 0xf8f4,
259 0x0000, 0x232a, 0x222b, 0x2320, 0xf8f5, 0x2321, 0xf8f6, 0xf8f7,
260 0xf8f8, 0xf8f9, 0xf8fa, 0xf8fb, 0xf8fc, 0xf8fd, 0xf8fe, 0x0000,
263 // ---------------------------- PS/PDF helper methods -----------------------------------
265 QByteArray QFontSubset::glyphName(unsigned short unicode, bool symbol)
267 if (symbol && unicode < 0x100)
268 // map from latin1 to symbol
269 unicode = symbol_map[unicode];
272 while(unicode_to_aglindex[l].u < unicode)
274 if (unicode_to_aglindex[l].u == unicode)
275 return agl + unicode_to_aglindex[l].index;
281 QPdf::toHex(unicode, buffer+3);
285 #ifndef QT_NO_FREETYPE
286 static FT_Face ft_face(const QFontEngine *engine)
289 #ifndef QT_NO_FONTCONFIG
290 if (engine->type() == QFontEngine::Freetype) {
291 const QFontEngineFT *ft = static_cast<const QFontEngineFT *>(engine);
292 return ft->non_locked_face();
295 if (engine->type() == QFontEngine::XLFD) {
296 const QFontEngineXLFD *xlfd = static_cast<const QFontEngineXLFD *>(engine);
297 return xlfd->non_locked_face();
301 if (engine->type() == QFontEngine::Freetype) {
302 const QFontEngineFT *ft = static_cast<const QFontEngineFT *>(engine);
303 return ft->non_locked_face();
310 QByteArray QFontSubset::glyphName(unsigned int glyph, const QVector<int> reverseMap) const
312 uint glyphIndex = glyph_indices[glyph];
318 QPdf::ByteStream s(&ba);
319 #ifndef QT_NO_FREETYPE
320 FT_Face face = ft_face(fontEngine);
324 if (face && FT_HAS_GLYPH_NAMES(face)) {
325 #if defined(Q_WS_X11)
326 if (fontEngine->type() == QFontEngine::XLFD)
327 glyphIndex = static_cast<QFontEngineXLFD *>(fontEngine)->glyphIndexToFreetypeGlyphIndex(glyphIndex);
329 FT_Get_Glyph_Name(face, glyphIndex, &name, 32);
330 if (name[0] == '.') // fix broken PS fonts returning .notdef for many glyphs
337 #if defined(Q_WS_X11)
338 if (fontEngine->type() == QFontEngine::XLFD) {
339 uint uc = static_cast<QFontEngineXLFD *>(fontEngine)->toUnicode(glyphIndex);
340 s << '/' << glyphName(uc, false /* ### */);
343 if (reverseMap[glyphIndex] && reverseMap[glyphIndex] < 0x10000) {
344 s << '/' << glyphName(reverseMap[glyphIndex], false);
346 s << "/gl" << (int)glyphIndex;
352 QByteArray QFontSubset::widthArray() const
354 Q_ASSERT(!widths.isEmpty());
356 QFontEngine::Properties properties = fontEngine->properties();
359 QPdf::ByteStream s(&width);
360 QFixed scale = QFixed(1000)/emSquare;
362 QFixed defWidth = widths[0];
363 //qDebug("defWidth=%d, scale=%f", defWidth.toInt(), scale.toReal());
364 for (int i = 0; i < nGlyphs(); ++i) {
365 if (defWidth != widths[i])
369 s << "/DW " << (defWidth*scale).toInt();
372 for (int g = 0; g < nGlyphs();) {
373 QFixed w = widths[g];
377 while (g < nGlyphs()) {
378 QFixed nw = widths[g];
383 if (startLinear > 0 && g - startLinear >= 10)
390 // qDebug("start=%x startLinear=%x g-1=%x",start,startLinear,g-1);
391 if (g - startLinear < 10)
393 int endnonlinear = startLinear ? startLinear : g;
394 // qDebug(" startLinear=%x endnonlinear=%x", startLinear,endnonlinear);
395 if (endnonlinear > start) {
397 for (int i = start; i < endnonlinear; ++i)
398 s << (widths[i]*scale).toInt();
402 s << startLinear << g - 1 << (widths[startLinear]*scale).toInt() << '\n';
409 static void checkRanges(QPdf::ByteStream &ts, QByteArray &ranges, int &nranges)
411 if (++nranges > 100) {
412 ts << nranges << "beginbfrange\n"
413 << ranges << "endbfrange\n";
414 ranges = QByteArray();
419 QVector<int> QFontSubset::getReverseMap() const
421 QVector<int> reverseMap;
422 reverseMap.resize(0x10000);
423 for (uint i = 0; i < 0x10000; ++i)
425 QGlyphLayoutArray<10> glyphs;
426 for (uint uc = 0; uc < 0x10000; ++uc) {
429 fontEngine->stringToCMap(&ch, 1, &glyphs, &nglyphs, QTextEngine::GlyphIndicesOnly);
430 int idx = glyph_indices.indexOf(glyphs.glyphs[0]);
431 if (idx >= 0 && !reverseMap.at(idx))
432 reverseMap[idx] = uc;
437 QByteArray QFontSubset::createToUnicodeMap() const
439 QVector<int> reverseMap = getReverseMap();
442 QPdf::ByteStream ts(&touc);
443 ts << "/CIDInit /ProcSet findresource begin\n"
446 "/CIDSystemInfo << /Registry (Adobe) /Ordering (UCS) /Supplement 0 >> def\n"
447 "/CMapName /Adobe-Identity-UCS def\n"
449 "1 begincodespacerange\n"
451 "endcodespacerange\n";
454 QByteArray ranges = "<0000> <0000> <0000>\n";
455 QPdf::ByteStream s(&ranges);
458 for (int g = 1; g < nGlyphs(); ) {
459 int uc0 = reverseMap.at(g);
467 while (g < nGlyphs()) {
468 int uc = reverseMap[g];
469 // cmaps can't have the high byte changing within one range, so we need to break on that as well
470 if (!uc || (g>>8) != (start >> 8))
476 if (startLinear > 0 && g - startLinear >= 10)
483 // qDebug("start=%x startLinear=%x g-1=%x",start,startLinear,g-1);
484 if (g - startLinear < 10)
486 int endnonlinear = startLinear ? startLinear : g;
487 // qDebug(" startLinear=%x endnonlinear=%x", startLinear,endnonlinear);
488 if (endnonlinear > start) {
489 s << '<' << QPdf::toHex((ushort)start, buf) << "> <";
490 s << QPdf::toHex((ushort)(endnonlinear - 1), buf) << "> ";
491 if (endnonlinear == start + 1) {
492 s << '<' << QPdf::toHex((ushort)reverseMap[start], buf) << ">\n";
495 for (int i = start; i < endnonlinear; ++i) {
496 s << '<' << QPdf::toHex((ushort)reverseMap[i], buf) << "> ";
500 checkRanges(ts, ranges, nranges);
503 while (startLinear < g) {
504 int len = g - startLinear;
505 int uc_start = reverseMap[startLinear];
506 int uc_end = uc_start + len - 1;
507 if ((uc_end >> 8) != (uc_start >> 8))
508 len = 256 - (uc_start & 0xff);
509 s << '<' << QPdf::toHex((ushort)startLinear, buf) << "> <";
510 s << QPdf::toHex((ushort)(startLinear + len - 1), buf) << "> ";
511 s << '<' << QPdf::toHex((ushort)reverseMap[startLinear], buf) << ">\n";
512 checkRanges(ts, ranges, nranges);
518 ts << nranges << "beginbfrange\n"
519 << ranges << "endbfrange\n";
522 "CMapName currentdict /CMap defineresource pop\n"
529 int QFontSubset::addGlyph(int index)
531 int idx = glyph_indices.indexOf(index);
533 idx = glyph_indices.size();
534 glyph_indices.append(index);
540 // ------------------------------ Truetype generation ----------------------------------------------
542 typedef qint16 F2DOT14;
544 typedef quint16 GlyphID;
545 typedef quint16 Offset;
550 QTtfStream(QByteArray &ba) : data((uchar *)ba.data()) { start = data; }
551 QTtfStream &operator <<(quint8 v) { *data = v; ++data; return *this; }
552 QTtfStream &operator <<(quint16 v) { qToBigEndian(v, data); data += sizeof(v); return *this; }
553 QTtfStream &operator <<(quint32 v) { qToBigEndian(v, data); data += sizeof(v); return *this; }
554 QTtfStream &operator <<(qint8 v) { *data = quint8(v); ++data; return *this; }
555 QTtfStream &operator <<(qint16 v) { qToBigEndian(v, data); data += sizeof(v); return *this; }
556 QTtfStream &operator <<(qint32 v) { qToBigEndian(v, data); data += sizeof(v); return *this; }
557 QTtfStream &operator <<(qint64 v) { qToBigEndian(v, data); data += sizeof(v); return *this; }
559 int offset() const { return data - start; }
560 void setOffset(int o) { data = start + o; }
561 void align4() { while (offset() & 3) { *data = '\0'; ++data; } }
571 Q_DECLARE_TYPEINFO(QTtfTable, Q_MOVABLE_TYPE);
574 struct qttf_head_table {
575 qint32 font_revision;
584 qint16 indexToLocFormat;
588 struct qttf_hhea_table {
592 quint16 maxAdvanceWidth;
593 qint16 minLeftSideBearing;
594 qint16 minRightSideBearing;
596 quint16 numberOfHMetrics;
600 struct qttf_maxp_table {
604 quint16 maxCompositePoints;
605 quint16 maxCompositeContours;
606 quint16 maxComponentElements;
607 quint16 maxComponentDepth;
610 struct qttf_name_table {
614 QString postscript_name;
618 static QTtfTable generateHead(const qttf_head_table &head);
619 static QTtfTable generateHhea(const qttf_hhea_table &hhea);
620 static QTtfTable generateMaxp(const qttf_maxp_table &maxp);
621 static QTtfTable generateName(const qttf_name_table &name);
623 struct qttf_font_tables
625 qttf_head_table head;
626 qttf_hhea_table hhea;
627 qttf_maxp_table maxp;
637 quint16 advanceWidth;
643 Q_DECLARE_TYPEINFO(QTtfGlyph, Q_MOVABLE_TYPE);
645 static QTtfGlyph generateGlyph(int index, const QPainterPath &path, qreal advance, qreal lsb, qreal ppem);
646 // generates glyf, loca and hmtx
647 static QList<QTtfTable> generateGlyphTables(qttf_font_tables &tables, const QList<QTtfGlyph> &_glyphs);
649 static QByteArray bindFont(const QList<QTtfTable>& _tables);
652 static quint32 checksum(const QByteArray &table)
656 const uchar *d = (uchar *)table.constData();
657 while (offset <= table.size()-3) {
658 sum += qFromBigEndian<quint32>(d + offset);
663 while (offset < table.size()) {
664 x |= ((quint32)d[offset]) << shift;
673 static QTtfTable generateHead(const qttf_head_table &head)
675 const int head_size = 54;
677 t.tag = MAKE_TAG('h', 'e', 'a', 'd');
678 t.data.resize(head_size);
680 QTtfStream s(t.data);
682 // qint32 Table version number 0x00010000 for version 1.0.
683 // qint32 fontRevision Set by font manufacturer.
684 s << qint32(0x00010000)
685 << head.font_revision
686 // quint32 checkSumAdjustment To compute: set it to 0, sum the entire font as quint32, then store 0xB1B0AFBA - sum.
688 // quint32 magicNumber Set to 0x5F0F3CF5.
689 << quint32(0x5F0F3CF5)
690 // quint16 flags Bit 0: Baseline for font at y=0;
691 // Bit 1: Left sidebearing point at x=0;
692 // Bit 2: Instructions may depend on point size;
693 // Bit 3: Force ppem to integer values for all internal scaler math; may use fractional ppem sizes if this bit is clear;
694 // Bit 4: Instructions may alter advance width (the advance widths might not scale linearly);
695 // Bits 5-10: These should be set according to Apple's specification . However, they are not implemented in OpenType.
696 // Bit 11: Font data is 'lossless,' as a result of having been compressed and decompressed with the Agfa MicroType Express engine.
697 // Bit 12: Font converted (produce compatible metrics)
698 // Bit 13: Font optimized for ClearType
699 // Bit 14: Reserved, set to 0
700 // Bit 15: Reserved, set to 0
703 // quint16 unitsPerEm Valid range is from 16 to 16384. This value should be a power of 2 for fonts that have TrueType outlines.
705 // qint64 created Number of seconds since 12:00 midnight, January 1, 1904. 64-bit integer
707 // qint64 modified Number of seconds since 12:00 midnight, January 1, 1904. 64-bit integer
709 // qint16 xMin For all glyph bounding boxes.
710 // qint16 yMin For all glyph bounding boxes.
711 // qint16 xMax For all glyph bounding boxes.
712 // qint16 yMax For all glyph bounding boxes.
717 // quint16 macStyle Bit 0: Bold (if set to 1);
718 // Bit 1: Italic (if set to 1)
719 // Bit 2: Underline (if set to 1)
720 // Bit 3: Outline (if set to 1)
721 // Bit 4: Shadow (if set to 1)
722 // Bit 5: Condensed (if set to 1)
723 // Bit 6: Extended (if set to 1)
724 // Bits 7-15: Reserved (set to 0).
726 // quint16 lowestRecPPEM Smallest readable size in pixels.
727 << quint16(6) // just a wild guess
728 // qint16 fontDirectionHint 0: Fully mixed directional glyphs;
730 // 1: Only strongly left to right;
731 // 2: Like 1 but also contains neutrals;
732 // -1: Only strongly right to left;
733 // -2: Like -1 but also contains neutrals. 1
734 // qint16 indexToLocFormat 0 for short offsets, 1 for long.
735 << head.indexToLocFormat
736 // qint16 glyphDataFormat 0 for current format.
739 Q_ASSERT(s.offset() == head_size);
744 static QTtfTable generateHhea(const qttf_hhea_table &hhea)
746 const int hhea_size = 36;
748 t.tag = MAKE_TAG('h', 'h', 'e', 'a');
749 t.data.resize(hhea_size);
751 QTtfStream s(t.data);
752 // qint32 Table version number 0x00010000 for version 1.0.
753 s << qint32(0x00010000)
754 // qint16 Ascender Typographic ascent. (Distance from baseline of highest ascender)
756 // qint16 Descender Typographic descent. (Distance from baseline of lowest descender)
758 // qint16 LineGap Typographic line gap.
759 // Negative LineGap values are treated as zero
760 // in Windows 3.1, System 6, and
763 // quint16 advanceWidthMax Maximum advance width value in 'hmtx' table.
764 << hhea.maxAdvanceWidth
765 // qint16 minLeftSideBearing Minimum left sidebearing value in 'hmtx' table.
766 << hhea.minLeftSideBearing
767 // qint16 minRightSideBearing Minimum right sidebearing value; calculated as Min(aw - lsb - (xMax - xMin)).
768 << hhea.minRightSideBearing
769 // qint16 xMaxExtent Max(lsb + (xMax - xMin)).
771 // qint16 caretSlopeRise Used to calculate the slope of the cursor (rise/run); 1 for vertical.
773 // qint16 caretSlopeRun 0 for vertical.
775 // qint16 caretOffset The amount by which a slanted highlight on a glyph needs to be shifted to produce the best appearance. Set to 0 for non-slanted fonts
777 // qint16 (reserved) set to 0
779 // qint16 (reserved) set to 0
781 // qint16 (reserved) set to 0
783 // qint16 (reserved) set to 0
785 // qint16 metricDataFormat 0 for current format.
787 // quint16 numberOfHMetrics Number of hMetric entries in 'hmtx' table
788 << hhea.numberOfHMetrics;
790 Q_ASSERT(s.offset() == hhea_size);
795 static QTtfTable generateMaxp(const qttf_maxp_table &maxp)
797 const int maxp_size = 32;
799 t.tag = MAKE_TAG('m', 'a', 'x', 'p');
800 t.data.resize(maxp_size);
802 QTtfStream s(t.data);
804 // qint32 Table version number 0x00010000 for version 1.0.
805 s << qint32(0x00010000)
806 // quint16 numGlyphs The number of glyphs in the font.
808 // quint16 maxPoints Maximum points in a non-composite glyph.
810 // quint16 maxContours Maximum contours in a non-composite glyph.
812 // quint16 maxCompositePoints Maximum points in a composite glyph.
813 << maxp.maxCompositePoints
814 // quint16 maxCompositeContours Maximum contours in a composite glyph.
815 << maxp.maxCompositeContours
816 // quint16 maxZones 1 if instructions do not use the twilight zone (Z0), or 2 if instructions do use Z0; should be set to 2 in most cases.
817 << quint16(1) // we do not embed instructions
818 // quint16 maxTwilightPoints Maximum points used in Z0.
820 // quint16 maxStorage Number of Storage Area locations.
822 // quint16 maxFunctionDefs Number of FDEFs.
824 // quint16 maxInstructionDefs Number of IDEFs.
826 // quint16 maxStackElements Maximum stack depth2.
828 // quint16 maxSizeOfInstructions Maximum byte count for glyph instructions.
830 // quint16 maxComponentElements Maximum number of components referenced at "top level" for any composite glyph.
831 << maxp.maxComponentElements
832 // quint16 maxComponentDepth Maximum levels of recursion; 1 for simple components.
833 << maxp.maxComponentDepth;
835 Q_ASSERT(s.offset() == maxp_size);
839 struct QTtfNameRecord {
844 static QTtfTable generateName(const QList<QTtfNameRecord> &name);
846 static QTtfTable generateName(const qttf_name_table &name)
848 QList<QTtfNameRecord> list;
851 rec.value = name.copyright;
854 rec.value = name.family;
857 rec.value = name.subfamily;
860 rec.value = name.family;
861 if (name.subfamily != QLatin1String("Regular"))
862 rec.value += QLatin1Char(' ') + name.subfamily;
865 rec.value = name.postscript_name;
868 return generateName(list);
871 // ####### should probably generate Macintosh/Roman name entries as well
872 static QTtfTable generateName(const QList<QTtfNameRecord> &name)
874 const int char_size = 2;
877 t.tag = MAKE_TAG('n', 'a', 'm', 'e');
879 const int name_size = 6 + 12*name.size();
881 for (int i = 0; i < name.size(); ++i) {
882 string_size += name.at(i).value.length()*char_size;
884 t.data.resize(name_size + string_size);
886 QTtfStream s(t.data);
887 // quint16 format Format selector (=0).
889 // quint16 count Number of name records.
890 << quint16(name.size())
891 // quint16 stringOffset Offset to start of string storage (from start of table).
892 << quint16(name_size);
893 // NameRecord nameRecord[count] The name records where count is the number of records.
897 for (int i = 0; i < name.size(); ++i) {
898 int len = name.at(i).value.length()*char_size;
899 // quint16 platformID Platform ID.
900 // quint16 encodingID Platform-specific encoding ID.
901 // quint16 languageID Language ID.
904 << quint16(0x0409) // en_US
905 // quint16 nameId Name ID.
907 // quint16 length String length (in bytes).
909 // quint16 offset String offset from start of storage area (in bytes).
913 for (int i = 0; i < name.size(); ++i) {
914 const QString &n = name.at(i).value;
915 const ushort *uc = n.utf16();
916 for (int i = 0; i < n.length(); ++i) {
928 XShortVector = (1 << 1),
929 YShortVector = (1 << 2),
932 XShortPositive = (1 << 4),
934 YShortPositive = (1 << 5)
941 Q_DECLARE_TYPEINFO(TTF_POINT, Q_PRIMITIVE_TYPE);
943 static void convertPath(const QPainterPath &path, QList<TTF_POINT> *points, QList<int> *endPoints, qreal ppem)
945 int numElements = path.elementCount();
946 for (int i = 0; i < numElements - 1; ++i) {
947 const QPainterPath::Element &e = path.elementAt(i);
949 p.x = qRound(e.x * 2048. / ppem);
950 p.y = qRound(-e.y * 2048. / ppem);
954 case QPainterPath::MoveToElement:
956 // see if start and end points of the last contour agree
957 int start = endPoints->size() ? endPoints->at(endPoints->size()-1) - 1 : 0;
958 int end = points->size() - 1;
959 if (points->at(end).x == points->at(start).x
960 && points->at(end).y == points->at(start).y)
962 endPoints->append(points->size() - 1);
965 case QPainterPath::LineToElement:
968 case QPainterPath::CurveToElement: {
969 // cubic bezier curve, we need to reduce to a list of quadratic curves
970 TTF_POINT list[3*16 + 4]; // we need max 16 subdivisions
971 list[3] = points->at(points->size() - 1);
973 const QPainterPath::Element &e2 = path.elementAt(++i);
974 list[1].x = qRound(e2.x * 2048. / ppem);
975 list[1].y = qRound(-e2.y * 2048. / ppem);
976 const QPainterPath::Element &e3 = path.elementAt(++i);
977 list[0].x = qRound(e3.x * 2048. / ppem);
978 list[0].y = qRound(-e3.y * 2048. / ppem);
980 TTF_POINT *base = list;
982 bool try_reduce = points->size() > 1
983 && points->at(points->size() - 1).flags == OnCurve
984 && points->at(points->size() - 2).flags == OffCurve;
985 // qDebug("generating beziers:");
986 while (base >= list) {
987 const int split_limit = 3;
989 // qDebug("iteration:");
990 // TTF_POINT *x = list;
991 // while (x <= base + 3) {
992 // qDebug() << " " << QPoint(x->x, x->y);
996 Q_ASSERT(base - list < 3*16 + 1);
997 // first see if we can easily reduce the cubic to a quadratic bezier curve
998 int i1_x = base[1].x + ((base[1].x - base[0].x) >> 1);
999 int i1_y = base[1].y + ((base[1].y - base[0].y) >> 1);
1000 int i2_x = base[2].x + ((base[2].x - base[3].x) >> 1);
1001 int i2_y = base[2].y + ((base[2].y - base[3].y) >> 1);
1002 // qDebug() << "checking: i1=" << QPoint(i1_x, i1_y) << " i2=" << QPoint(i2_x, i2_y);
1003 if (qAbs(i1_x - i2_x) <= split_limit && qAbs(i1_y - i2_y) <= split_limit) {
1004 // got a quadratic bezier curve
1006 np.x = (i1_x + i2_x) >> 1;
1007 np.y = (i1_y + i2_y) >> 1;
1009 // see if we can optimize out the last onCurve point
1010 int mx = (points->at(points->size() - 2).x + base[2].x) >> 1;
1011 int my = (points->at(points->size() - 2).y + base[2].y) >> 1;
1012 if (qAbs(mx - base[3].x) <= split_limit && qAbs(my = base[3].y) <= split_limit)
1016 np.flags = OffCurve;
1018 // qDebug() << " appending offcurve point " << QPoint(np.x, np.y);
1022 // qDebug() << " -> splitting";
1024 base[6].x = base[3].x;
1027 base[1].x = a = ( base[0].x + c ) >> 1;
1028 base[5].x = b = ( base[3].x + d ) >> 1;
1030 base[2].x = a = ( a + c ) >> 1;
1031 base[4].x = b = ( b + c ) >> 1;
1032 base[3].x = ( a + b ) >> 1;
1034 base[6].y = base[3].y;
1037 base[1].y = a = ( base[0].y + c ) >> 1;
1038 base[5].y = b = ( base[3].y + d ) >> 1;
1040 base[2].y = a = ( a + c ) >> 1;
1041 base[4].y = b = ( b + c ) >> 1;
1042 base[3].y = ( a + b ) >> 1;
1050 case QPainterPath::CurveToDataElement:
1054 // qDebug() << " appending oncurve point " << QPoint(p.x, p.y);
1057 int start = endPoints->size() ? endPoints->at(endPoints->size()-1) + 1 : 0;
1058 int end = points->size() - 1;
1059 if (points->at(end).x == points->at(start).x
1060 && points->at(end).y == points->at(start).y)
1062 endPoints->append(points->size() - 1);
1065 static void getBounds(const QList<TTF_POINT> &points, qint16 *xmin, qint16 *xmax, qint16 *ymin, qint16 *ymax)
1067 *xmin = points.at(0).x;
1069 *ymin = points.at(0).y;
1072 for (int i = 1; i < points.size(); ++i) {
1073 *xmin = qMin(*xmin, points.at(i).x);
1074 *xmax = qMax(*xmax, points.at(i).x);
1075 *ymin = qMin(*ymin, points.at(i).y);
1076 *ymax = qMax(*ymax, points.at(i).y);
1080 static int convertToRelative(QList<TTF_POINT> *points)
1082 // convert points to relative and setup flags
1083 // qDebug() << "relative points:";
1086 int point_array_size = 0;
1087 for (int i = 0; i < points->size(); ++i) {
1088 const int x = points->at(i).x;
1089 const int y = points->at(i).y;
1093 rel.flags = points->at(i).flags;
1094 Q_ASSERT(rel.flags < 2);
1097 } else if (rel.x > 0 && rel.x < 256) {
1098 rel.flags |= XShortVector|XShortPositive;
1100 } else if (rel.x < 0 && rel.x > -256) {
1101 rel.flags |= XShortVector;
1105 point_array_size += 2;
1109 } else if (rel.y > 0 && rel.y < 256) {
1110 rel.flags |= YShortVector|YShortPositive;
1112 } else if (rel.y < 0 && rel.y > -256) {
1113 rel.flags |= YShortVector;
1117 point_array_size += 2;
1120 // #define toString(x) ((rel.flags & x) ? #x : "")
1121 // qDebug() << " " << QPoint(rel.x, rel.y) << "flags="
1122 // << toString(OnCurve) << toString(XShortVector)
1123 // << (rel.flags & XShortVector ? toString(XShortPositive) : toString(XSame))
1124 // << toString(YShortVector)
1125 // << (rel.flags & YShortVector ? toString(YShortPositive) : toString(YSame));
1130 return point_array_size;
1133 static void getGlyphData(QTtfGlyph *glyph, const QList<TTF_POINT> &points, const QList<int> &endPoints, int point_array_size)
1135 const int max_size = 5*sizeof(qint16) // header
1136 + endPoints.size()*sizeof(quint16) // end points of contours
1137 + sizeof(quint16) // instruction length == 0
1138 + points.size()*(1) // flags
1139 + point_array_size; // coordinates
1141 glyph->data.resize(max_size);
1143 QTtfStream s(glyph->data);
1144 s << qint16(endPoints.size())
1145 << glyph->xMin << glyph->yMin << glyph->xMax << glyph->yMax;
1147 for (int i = 0; i < endPoints.size(); ++i)
1148 s << quint16(endPoints.at(i));
1149 s << quint16(0); // instruction length
1152 for (int i = 0; i < points.size(); ++i)
1153 s << quint8(points.at(i).flags);
1155 for (int i = 0; i < points.size(); ++i) {
1156 quint8 flags = points.at(i).flags;
1157 qint16 x = points.at(i).x;
1159 if (flags & XShortVector)
1161 else if (!(flags & XSame))
1164 for (int i = 0; i < points.size(); ++i) {
1165 quint8 flags = points.at(i).flags;
1166 qint16 y = points.at(i).y;
1168 if (flags & YShortVector)
1170 else if (!(flags & YSame))
1174 // qDebug() << "offset=" << s.offset() << "max_size=" << max_size << "point_array_size=" << point_array_size;
1175 Q_ASSERT(s.offset() == max_size);
1177 glyph->numContours = endPoints.size();
1178 glyph->numPoints = points.size();
1181 static QTtfGlyph generateGlyph(int index, const QPainterPath &path, qreal advance, qreal lsb, qreal ppem)
1183 QList<TTF_POINT> points;
1184 QList<int> endPoints;
1186 glyph.index = index;
1187 glyph.advanceWidth = qRound(advance * 2048. / ppem);
1188 glyph.lsb = qRound(lsb * 2048. / ppem);
1190 if (!path.elementCount()) {
1191 //qDebug("glyph %d is empty", index);
1193 glyph.xMin = glyph.xMax = glyph.yMin = glyph.yMax = 0;
1194 glyph.numContours = 0;
1195 glyph.numPoints = 0;
1199 convertPath(path, &points, &endPoints, ppem);
1201 // qDebug() << "number of contours=" << endPoints.size();
1202 // for (int i = 0; i < points.size(); ++i)
1203 // qDebug() << " point[" << i << "] = " << QPoint(points.at(i).x, points.at(i).y) << " flags=" << points.at(i).flags;
1204 // qDebug() << "endPoints:";
1205 // for (int i = 0; i < endPoints.size(); ++i)
1206 // qDebug() << endPoints.at(i);
1208 getBounds(points, &glyph.xMin, &glyph.xMax, &glyph.yMin, &glyph.yMax);
1209 int point_array_size = convertToRelative(&points);
1210 getGlyphData(&glyph, points, endPoints, point_array_size);
1214 Q_STATIC_GLOBAL_OPERATOR bool operator <(const QTtfGlyph &g1, const QTtfGlyph &g2)
1216 return g1.index < g2.index;
1219 static QList<QTtfTable> generateGlyphTables(qttf_font_tables &tables, const QList<QTtfGlyph> &_glyphs)
1221 const int max_size_small = 65536*2;
1222 QList<QTtfGlyph> glyphs = _glyphs;
1225 Q_ASSERT(tables.maxp.numGlyphs == glyphs.at(glyphs.size()-1).index + 1);
1226 int nGlyphs = tables.maxp.numGlyphs;
1229 for (int i = 0; i < glyphs.size(); ++i)
1230 glyf_size += (glyphs.at(i).data.size() + 3) & ~3;
1232 tables.head.indexToLocFormat = glyf_size < max_size_small ? 0 : 1;
1233 tables.hhea.numberOfHMetrics = nGlyphs;
1236 glyf.tag = MAKE_TAG('g', 'l', 'y', 'f');
1239 loca.tag = MAKE_TAG('l', 'o', 'c', 'a');
1240 loca.data.resize(glyf_size < max_size_small ? (nGlyphs+1)*sizeof(quint16) : (nGlyphs+1)*sizeof(quint32));
1241 QTtfStream ls(loca.data);
1244 hmtx.tag = MAKE_TAG('h', 'm', 't', 'x');
1245 hmtx.data.resize(nGlyphs*4);
1246 QTtfStream hs(hmtx.data);
1249 for (int i = 0; i < nGlyphs; ++i) {
1250 int gpos = glyf.data.size();
1251 quint16 advance = 0;
1254 if (glyphs[pos].index == i) {
1256 // qDebug("emitting glyph %d: size=%d", i, glyphs.at(i).data.size());
1257 glyf.data += glyphs.at(pos).data;
1258 while (glyf.data.size() & 1)
1259 glyf.data.append('\0');
1260 advance = glyphs.at(pos).advanceWidth;
1261 lsb = glyphs.at(pos).lsb;
1264 if (glyf_size < max_size_small) {
1265 // use short loca format
1266 ls << quint16(gpos>>1);
1268 // use long loca format
1269 ls << quint32(gpos);
1274 if (glyf_size < max_size_small) {
1275 // use short loca format
1276 ls << quint16(glyf.data.size()>>1);
1278 // use long loca format
1279 ls << quint32(glyf.data.size());
1282 Q_ASSERT(loca.data.size() == ls.offset());
1283 Q_ASSERT(hmtx.data.size() == hs.offset());
1285 QList<QTtfTable> list;
1292 Q_STATIC_GLOBAL_OPERATOR bool operator <(const QTtfTable &t1, const QTtfTable &t2)
1294 return t1.tag < t2.tag;
1297 static QByteArray bindFont(const QList<QTtfTable>& _tables)
1299 QList<QTtfTable> tables = _tables;
1304 const int header_size = sizeof(qint32) + 4*sizeof(quint16);
1305 const int directory_size = 4*sizeof(quint32)*tables.size();
1306 font.resize(header_size + directory_size);
1310 int n = tables.size() >> 1;
1317 quint32 head_offset = 0;
1321 // Type Name Description
1322 // qint32 sfnt version 0x00010000 for version 1.0.
1323 // quint16 numTables Number of tables.
1324 // quint16 searchRange (Maximum power of 2 <= numTables) x 16.
1325 // quint16 entrySelector Log2(maximum power of 2 <= numTables).
1326 // quint16 rangeShift NumTables x 16-searchRange.
1327 f << qint32(0x00010000)
1328 << quint16(tables.size())
1331 << quint16(16*(tables.size() - pow));
1334 // Type Name Description
1335 // quint32 tag 4 -byte identifier.
1336 // quint32 checkSum CheckSum for this table.
1337 // quint32 offset Offset from beginning of TrueType font file.
1338 // quint32 length Length of this table.
1339 quint32 table_offset = header_size + directory_size;
1340 for (int i = 0; i < tables.size(); ++i) {
1341 const QTtfTable &t = tables.at(i);
1342 const quint32 size = (t.data.size() + 3) & ~3;
1343 if (t.tag == MAKE_TAG('h', 'e', 'a', 'd'))
1344 head_offset = table_offset;
1349 table_offset += size;
1350 #define TAG(x) char(t.tag >> 24) << char((t.tag >> 16) & 0xff) << char((t.tag >> 8) & 0xff) << char(t.tag & 0xff)
1351 //qDebug() << "table " << TAG(t.tag) << "has size " << t.data.size() << "stream at " << f.offset();
1354 for (int i = 0; i < tables.size(); ++i) {
1355 const QByteArray &t = tables.at(i).data;
1358 while (s & 3) { font += '\0'; ++s; }
1362 qWarning("QFontSubset: Font misses 'head' table");
1363 return QByteArray();
1366 // calculate the fonts checksum and qToBigEndian into 'head's checksum_adjust
1367 quint32 checksum_adjust = 0xB1B0AFBA - checksum(font);
1368 qToBigEndian(checksum_adjust, (uchar *)font.data() + head_offset + 8);
1375 PDF requires the following tables:
1377 head, hhea, loca, maxp, cvt , prep, glyf, hmtx, fpgm
1379 This means we don't have to add a os/2, post or name table. cvt , prep and fpgm could be empty
1383 QByteArray QFontSubset::toTruetype() const
1385 qttf_font_tables font;
1386 memset(&font, 0, sizeof(qttf_font_tables));
1388 qreal ppem = fontEngine->fontDef.pixelSize;
1389 #define TO_TTF(x) qRound(x * 2048. / ppem)
1390 QList<QTtfGlyph> glyphs;
1392 QFontEngine::Properties properties = fontEngine->properties();
1393 // initialize some stuff needed in createWidthArray
1395 widths.resize(nGlyphs());
1398 font.head.font_revision = 0x00010000;
1399 font.head.flags = (1 << 2) | (1 << 4);
1400 font.head.created = 0; // ###
1401 font.head.modified = 0; // ###
1402 font.head.xMin = SHRT_MAX;
1403 font.head.xMax = SHRT_MIN;
1404 font.head.yMin = SHRT_MAX;
1405 font.head.yMax = SHRT_MIN;
1406 font.head.macStyle = (fontEngine->fontDef.weight > QFont::Normal) ? 1 : 0;
1407 font.head.macStyle |= (fontEngine->fontDef.styleHint != QFont::StyleNormal) ? 1 : 0;
1410 font.hhea.ascender = qRound(properties.ascent);
1411 font.hhea.descender = -qRound(properties.descent);
1412 font.hhea.lineGap = qRound(properties.leading);
1413 font.hhea.maxAdvanceWidth = TO_TTF(fontEngine->maxCharWidth());
1414 font.hhea.minLeftSideBearing = TO_TTF(fontEngine->minLeftBearing());
1415 font.hhea.minRightSideBearing = TO_TTF(fontEngine->minRightBearing());
1416 font.hhea.xMaxExtent = SHRT_MIN;
1418 font.maxp.numGlyphs = 0;
1419 font.maxp.maxPoints = 0;
1420 font.maxp.maxContours = 0;
1421 font.maxp.maxCompositePoints = 0;
1422 font.maxp.maxCompositeContours = 0;
1423 font.maxp.maxComponentElements = 0;
1424 font.maxp.maxComponentDepth = 0;
1425 font.maxp.numGlyphs = nGlyphs();
1429 uint sumAdvances = 0;
1430 for (int i = 0; i < nGlyphs(); ++i) {
1431 glyph_t g = glyph_indices.at(i);
1433 glyph_metrics_t metric;
1434 fontEngine->getUnscaledGlyph(g, &path, &metric);
1436 path = QPainterPath();
1438 path.addRect(QRectF(0, 0, 1000, 1000));
1440 QTtfGlyph glyph = generateGlyph(i, path, metric.xoff.toReal(), metric.x.toReal(), properties.emSquare.toReal());
1442 font.head.xMin = qMin(font.head.xMin, glyph.xMin);
1443 font.head.xMax = qMax(font.head.xMax, glyph.xMax);
1444 font.head.yMin = qMin(font.head.yMin, glyph.yMin);
1445 font.head.yMax = qMax(font.head.yMax, glyph.yMax);
1447 font.hhea.xMaxExtent = qMax(font.hhea.xMaxExtent, (qint16)(glyph.lsb + glyph.xMax - glyph.xMin));
1449 font.maxp.maxPoints = qMax(font.maxp.maxPoints, glyph.numPoints);
1450 font.maxp.maxContours = qMax(font.maxp.maxContours, glyph.numContours);
1452 if (glyph.xMax > glyph.xMin)
1453 sumAdvances += glyph.xMax - glyph.xMin;
1455 // qDebug("adding glyph %d size=%d", glyph.index, glyph.data.size());
1456 glyphs.append(glyph);
1457 widths[i] = glyph.advanceWidth;
1461 QList<QTtfTable> tables = generateGlyphTables(font, glyphs);
1462 tables.append(generateHead(font.head));
1463 tables.append(generateHhea(font.hhea));
1464 tables.append(generateMaxp(font.maxp));
1466 QTtfTable name_table;
1467 name_table.tag = MAKE_TAG('n', 'a', 'm', 'e');
1469 name_table.data = fontEngine->getSfntTable(name_table.tag);
1470 if (name_table.data.isEmpty()) {
1471 qttf_name_table name;
1473 name.copyright = QLatin1String("Fake font");
1475 name.copyright = QLatin1String(properties.copyright);
1476 name.family = fontEngine->fontDef.family;
1477 name.subfamily = QLatin1String("Regular"); // ######
1478 name.postscript_name = QLatin1String(properties.postscriptName);
1479 name_table = generateName(name);
1481 tables.append(name_table);
1485 os2.tag = MAKE_TAG('O', 'S', '/', '2');
1486 os2.data = fontEngine->getSfntTable(os2.tag);
1487 if (!os2.data.isEmpty())
1491 return bindFont(tables);