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
64 static const char * const agl =
65 ".notdef\0space\0exclam\0quotedbl\0numbersign\0dollar\0percent\0ampersand\0"
66 "quotesingle\0parenleft\0parenright\0asterisk\0plus\0comma\0hyphen\0period\0"
67 "slash\0zero\0one\0two\0three\0four\0five\0six\0seven\0eight\0nine\0colon\0"
68 "semicolon\0less\0equal\0greater\0question\0at\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\0bracketleft\0backslash\0"
70 "bracketright\0asciicircum\0underscore\0grave\0a\0b\0c\0d\0e\0f\0g\0h\0i\0j\0"
71 "k\0l\0m\0n\0o\0p\0q\0r\0s\0t\0u\0v\0w\0x\0y\0z\0braceleft\0bar\0braceright\0"
72 "asciitilde\0space\0exclamdown\0cent\0sterling\0currency\0yen\0brokenbar\0"
73 "section\0dieresis\0copyright\0ordfeminine\0guillemotleft\0logicalnot\0"
74 "hyphen\0registered\0macron\0degree\0plusminus\0twosuperior\0threesuperior\0"
75 "acute\0mu\0paragraph\0periodcentered\0cedilla\0onesuperior\0ordmasculine\0"
76 "guillemotright\0onequarter\0onehalf\0threequarters\0questiondown\0Agrave\0"
77 "Aacute\0Acircumflex\0Atilde\0Adieresis\0Aring\0AE\0Ccedilla\0Egrave\0Eacute\0"
78 "Ecircumflex\0Edieresis\0Igrave\0Iacute\0Icircumflex\0Idieresis\0Eth\0Ntilde\0"
79 "Ograve\0Oacute\0Ocircumflex\0Otilde\0Odieresis\0multiply\0Oslash\0Ugrave\0"
80 "Uacute\0Ucircumflex\0Udieresis\0Yacute\0Thorn\0germandbls\0agrave\0aacute\0"
81 "acircumflex\0atilde\0adieresis\0aring\0ae\0ccedilla\0egrave\0eacute\0"
82 "ecircumflex\0edieresis\0igrave\0iacute\0icircumflex\0idieresis\0eth\0ntilde\0"
83 "ograve\0oacute\0ocircumflex\0otilde\0odieresis\0divide\0oslash\0ugrave\0"
84 "uacute\0ucircumflex\0udieresis\0yacute\0thorn\0ydieresis\0Amacron\0amacron\0"
85 "Abreve\0abreve\0Aogonek\0aogonek\0Cacute\0cacute\0Ccircumflex\0ccircumflex\0"
86 "Cdotaccent\0cdotaccent\0Ccaron\0ccaron\0Dcaron\0dcaron\0Dcroat\0dcroat\0"
87 "Emacron\0emacron\0Ebreve\0ebreve\0Edotaccent\0edotaccent\0Eogonek\0eogonek\0"
88 "Ecaron\0ecaron\0Gcircumflex\0gcircumflex\0Gbreve\0gbreve\0Gdotaccent\0"
89 "gdotaccent\0Gcommaaccent\0gcommaaccent\0Hcircumflex\0hcircumflex\0Hbar\0"
90 "hbar\0Itilde\0itilde\0Imacron\0imacron\0Ibreve\0ibreve\0Iogonek\0iogonek\0"
91 "Idotaccent\0dotlessi\0IJ\0ij\0Jcircumflex\0jcircumflex\0Kcommaaccent\0"
92 "kcommaaccent\0kgreenlandic\0Lacute\0lacute\0Lcommaaccent\0lcommaaccent\0"
93 "Lcaron\0lcaron\0Ldot\0ldot\0Lslash\0lslash\0Nacute\0nacute\0Ncommaaccent\0"
94 "ncommaaccent\0Ncaron\0ncaron\0napostrophe\0Eng\0eng\0Omacron\0omacron\0"
95 "Obreve\0obreve\0Ohungarumlaut\0ohungarumlaut\0OE\0oe\0Racute\0racute\0"
96 "Rcommaaccent\0rcommaaccent\0Rcaron\0rcaron\0Sacute\0sacute\0Scircumflex\0"
97 "scircumflex\0Scedilla\0scedilla\0Scaron\0scaron\0Tcaron\0tcaron\0Tbar\0tbar\0"
98 "Utilde\0utilde\0Umacron\0umacron\0Ubreve\0ubreve\0Uring\0uring\0"
99 "Uhungarumlaut\0uhungarumlaut\0Uogonek\0uogonek\0Wcircumflex\0wcircumflex\0"
100 "Ycircumflex\0ycircumflex\0Ydieresis\0Zacute\0zacute\0Zdotaccent\0zdotaccent\0"
101 "Zcaron\0zcaron\0longs\0florin\0Ohorn\0ohorn\0Uhorn\0uhorn\0Gcaron\0gcaron\0"
102 "Aringacute\0aringacute\0AEacute\0aeacute\0Oslashacute\0oslashacute\0"
103 "Scommaaccent\0scommaaccent\0Tcommaaccent\0tcommaaccent\0afii57929\0"
104 "afii64937\0circumflex\0caron\0breve\0dotaccent\0ring\0ogonek\0tilde\0"
105 "hungarumlaut\0gravecomb\0acutecomb\0tildecomb\0hookabovecomb\0dotbelowcomb\0"
106 "tonos\0dieresistonos\0Alphatonos\0anoteleia\0Epsilontonos\0Etatonos\0"
107 "Iotatonos\0Omicrontonos\0Upsilontonos\0Omegatonos\0iotadieresistonos\0Alpha\0"
108 "Beta\0Gamma\0Delta\0Epsilon\0Zeta\0Eta\0Theta\0Iota\0Kappa\0Lambda\0Mu\0Nu\0"
109 "Xi\0Omicron\0Pi\0Rho\0Sigma\0Tau\0Upsilon\0Phi\0Chi\0Psi\0Omega\0"
110 "Iotadieresis\0Upsilondieresis\0alphatonos\0epsilontonos\0etatonos\0"
111 "iotatonos\0upsilondieresistonos\0alpha\0beta\0gamma\0delta\0epsilon\0zeta\0"
112 "eta\0theta\0iota\0kappa\0lambda\0mu\0nu\0xi\0omicron\0pi\0rho\0sigma1\0"
113 "sigma\0tau\0upsilon\0phi\0chi\0psi\0omega\0iotadieresis\0upsilondieresis\0"
116 static const struct { quint16 u; quint16 index; } unicode_to_aglindex[] = {
117 {0x0000, 0}, {0x0020, 8}, {0x0021, 14}, {0x0022, 21},
118 {0x0023, 30}, {0x0024, 41}, {0x0025, 48}, {0x0026, 56},
119 {0x0027, 66}, {0x0028, 78}, {0x0029, 88}, {0x002A, 99},
120 {0x002B, 108}, {0x002C, 113}, {0x002D, 119}, {0x002E, 126},
121 {0x002F, 133}, {0x0030, 139}, {0x0031, 144}, {0x0032, 148},
122 {0x0033, 152}, {0x0034, 158}, {0x0035, 163}, {0x0036, 168},
123 {0x0037, 172}, {0x0038, 178}, {0x0039, 184}, {0x003A, 189},
124 {0x003B, 195}, {0x003C, 205}, {0x003D, 210}, {0x003E, 216},
125 {0x003F, 224}, {0x0040, 233}, {0x0041, 236}, {0x0042, 238},
126 {0x0043, 240}, {0x0044, 242}, {0x0045, 244}, {0x0046, 246},
127 {0x0047, 248}, {0x0048, 250}, {0x0049, 252}, {0x004A, 254},
128 {0x004B, 256}, {0x004C, 258}, {0x004D, 260}, {0x004E, 262},
129 {0x004F, 264}, {0x0050, 266}, {0x0051, 268}, {0x0052, 270},
130 {0x0053, 272}, {0x0054, 274}, {0x0055, 276}, {0x0056, 278},
131 {0x0057, 280}, {0x0058, 282}, {0x0059, 284}, {0x005A, 286},
132 {0x005B, 288}, {0x005C, 300}, {0x005D, 310}, {0x005E, 323},
133 {0x005F, 335}, {0x0060, 346}, {0x0061, 352}, {0x0062, 354},
134 {0x0063, 356}, {0x0064, 358}, {0x0065, 360}, {0x0066, 362},
135 {0x0067, 364}, {0x0068, 366}, {0x0069, 368}, {0x006A, 370},
136 {0x006B, 372}, {0x006C, 374}, {0x006D, 376}, {0x006E, 378},
137 {0x006F, 380}, {0x0070, 382}, {0x0071, 384}, {0x0072, 386},
138 {0x0073, 388}, {0x0074, 390}, {0x0075, 392}, {0x0076, 394},
139 {0x0077, 396}, {0x0078, 398}, {0x0079, 400}, {0x007A, 402},
140 {0x007B, 404}, {0x007C, 414}, {0x007D, 418}, {0x007E, 429},
141 {0x00A0, 440}, {0x00A1, 446}, {0x00A2, 457}, {0x00A3, 462},
142 {0x00A4, 471}, {0x00A5, 480}, {0x00A6, 484}, {0x00A7, 494},
143 {0x00A8, 502}, {0x00A9, 511}, {0x00AA, 521}, {0x00AB, 533},
144 {0x00AC, 547}, {0x00AD, 558}, {0x00AE, 565}, {0x00AF, 576},
145 {0x00B0, 583}, {0x00B1, 590}, {0x00B2, 600}, {0x00B3, 612},
146 {0x00B4, 626}, {0x00B5, 632}, {0x00B6, 635}, {0x00B7, 645},
147 {0x00B8, 660}, {0x00B9, 668}, {0x00BA, 680}, {0x00BB, 693},
148 {0x00BC, 708}, {0x00BD, 719}, {0x00BE, 727}, {0x00BF, 741},
149 {0x00C0, 754}, {0x00C1, 761}, {0x00C2, 768}, {0x00C3, 780},
150 {0x00C4, 787}, {0x00C5, 797}, {0x00C6, 803}, {0x00C7, 806},
151 {0x00C8, 815}, {0x00C9, 822}, {0x00CA, 829}, {0x00CB, 841},
152 {0x00CC, 851}, {0x00CD, 858}, {0x00CE, 865}, {0x00CF, 877},
153 {0x00D0, 887}, {0x00D1, 891}, {0x00D2, 898}, {0x00D3, 905},
154 {0x00D4, 912}, {0x00D5, 924}, {0x00D6, 931}, {0x00D7, 941},
155 {0x00D8, 950}, {0x00D9, 957}, {0x00DA, 964}, {0x00DB, 971},
156 {0x00DC, 983}, {0x00DD, 993}, {0x00DE, 1000}, {0x00DF, 1006},
157 {0x00E0, 1017}, {0x00E1, 1024}, {0x00E2, 1031}, {0x00E3, 1043},
158 {0x00E4, 1050}, {0x00E5, 1060}, {0x00E6, 1066}, {0x00E7, 1069},
159 {0x00E8, 1078}, {0x00E9, 1085}, {0x00EA, 1092}, {0x00EB, 1104},
160 {0x00EC, 1114}, {0x00ED, 1121}, {0x00EE, 1128}, {0x00EF, 1140},
161 {0x00F0, 1150}, {0x00F1, 1154}, {0x00F2, 1161}, {0x00F3, 1168},
162 {0x00F4, 1175}, {0x00F5, 1187}, {0x00F6, 1194}, {0x00F7, 1204},
163 {0x00F8, 1211}, {0x00F9, 1218}, {0x00FA, 1225}, {0x00FB, 1232},
164 {0x00FC, 1244}, {0x00FD, 1254}, {0x00FE, 1261}, {0x00FF, 1267},
165 {0x0100, 1277}, {0x0101, 1285}, {0x0102, 1293}, {0x0103, 1300},
166 {0x0104, 1307}, {0x0105, 1315}, {0x0106, 1323}, {0x0107, 1330},
167 {0x0108, 1337}, {0x0109, 1349}, {0x010A, 1361}, {0x010B, 1372},
168 {0x010C, 1383}, {0x010D, 1390}, {0x010E, 1397}, {0x010F, 1404},
169 {0x0110, 1411}, {0x0111, 1418}, {0x0112, 1425}, {0x0113, 1433},
170 {0x0114, 1441}, {0x0115, 1448}, {0x0116, 1455}, {0x0117, 1466},
171 {0x0118, 1477}, {0x0119, 1485}, {0x011A, 1493}, {0x011B, 1500},
172 {0x011C, 1507}, {0x011D, 1519}, {0x011E, 1531}, {0x011F, 1538},
173 {0x0120, 1545}, {0x0121, 1556}, {0x0122, 1567}, {0x0123, 1580},
174 {0x0124, 1593}, {0x0125, 1605}, {0x0126, 1617}, {0x0127, 1622},
175 {0x0128, 1627}, {0x0129, 1634}, {0x012A, 1641}, {0x012B, 1649},
176 {0x012C, 1657}, {0x012D, 1664}, {0x012E, 1671}, {0x012F, 1679},
177 {0x0130, 1687}, {0x0131, 1698}, {0x0132, 1707}, {0x0133, 1710},
178 {0x0134, 1713}, {0x0135, 1725}, {0x0136, 1737}, {0x0137, 1750},
179 {0x0138, 1763}, {0x0139, 1776}, {0x013A, 1783}, {0x013B, 1790},
180 {0x013C, 1803}, {0x013D, 1816}, {0x013E, 1823}, {0x013F, 1830},
181 {0x0140, 1835}, {0x0141, 1840}, {0x0142, 1847}, {0x0143, 1854},
182 {0x0144, 1861}, {0x0145, 1868}, {0x0146, 1881}, {0x0147, 1894},
183 {0x0148, 1901}, {0x0149, 1908}, {0x014A, 1920}, {0x014B, 1924},
184 {0x014C, 1928}, {0x014D, 1936}, {0x014E, 1944}, {0x014F, 1951},
185 {0x0150, 1958}, {0x0151, 1972}, {0x0152, 1986}, {0x0153, 1989},
186 {0x0154, 1992}, {0x0155, 1999}, {0x0156, 2006}, {0x0157, 2019},
187 {0x0158, 2032}, {0x0159, 2039}, {0x015A, 2046}, {0x015B, 2053},
188 {0x015C, 2060}, {0x015D, 2072}, {0x015E, 2084}, {0x015F, 2093},
189 {0x0160, 2102}, {0x0161, 2109}, {0x0164, 2116}, {0x0165, 2123},
190 {0x0166, 2130}, {0x0167, 2135}, {0x0168, 2140}, {0x0169, 2147},
191 {0x016A, 2154}, {0x016B, 2162}, {0x016C, 2170}, {0x016D, 2177},
192 {0x016E, 2184}, {0x016F, 2190}, {0x0170, 2196}, {0x0171, 2210},
193 {0x0172, 2224}, {0x0173, 2232}, {0x0174, 2240}, {0x0175, 2252},
194 {0x0176, 2264}, {0x0177, 2276}, {0x0178, 2288}, {0x0179, 2298},
195 {0x017A, 2305}, {0x017B, 2312}, {0x017C, 2323}, {0x017D, 2334},
196 {0x017E, 2341}, {0x017F, 2348}, {0x0192, 2354}, {0x01A0, 2361},
197 {0x01A1, 2367}, {0x01AF, 2373}, {0x01B0, 2379}, {0x01E6, 2385},
198 {0x01E7, 2392}, {0x01FA, 2399}, {0x01FB, 2410}, {0x01FC, 2421},
199 {0x01FD, 2429}, {0x01FE, 2437}, {0x01FF, 2449}, {0x0218, 2461},
200 {0x0219, 2474}, {0x021A, 2487}, {0x021B, 2500}, {0x02BC, 2513},
201 {0x02BD, 2523}, {0x02C6, 2533}, {0x02C7, 2544}, {0x02D8, 2550},
202 {0x02D9, 2556}, {0x02DA, 2566}, {0x02DB, 2571}, {0x02DC, 2578},
203 {0x02DD, 2584}, {0x0300, 2597}, {0x0301, 2607}, {0x0303, 2617},
204 {0x0309, 2627}, {0x0323, 2641}, {0x0384, 2654}, {0x0385, 2660},
205 {0x0386, 2674}, {0x0387, 2685}, {0x0388, 2695}, {0x0389, 2708},
206 {0x038A, 2717}, {0x038C, 2727}, {0x038E, 2740}, {0x038F, 2753},
207 {0x0390, 2764}, {0x0391, 2782}, {0x0392, 2788}, {0x0393, 2793},
208 {0x0394, 2799}, {0x0395, 2805}, {0x0396, 2813}, {0x0397, 2818},
209 {0x0398, 2822}, {0x0399, 2828}, {0x039A, 2833}, {0x039B, 2839},
210 {0x039C, 2846}, {0x039D, 2849}, {0x039E, 2852}, {0x039F, 2855},
211 {0x03A0, 2863}, {0x03A1, 2866}, {0x03A3, 2870}, {0x03A4, 2876},
212 {0x03A5, 2880}, {0x03A6, 2888}, {0x03A7, 2892}, {0x03A8, 2896},
213 {0x03A9, 2900}, {0x03AA, 2906}, {0x03AB, 2919}, {0x03AC, 2935},
214 {0x03AD, 2946}, {0x03AE, 2959}, {0x03AF, 2968}, {0x03B0, 2978},
215 {0x03B1, 2999}, {0x03B2, 3005}, {0x03B3, 3010}, {0x03B4, 3016},
216 {0x03B5, 3022}, {0x03B6, 3030}, {0x03B7, 3035}, {0x03B8, 3039},
217 {0x03B9, 3045}, {0x03BA, 3050}, {0x03BB, 3056}, {0x03BC, 3063},
218 {0x03BD, 3066}, {0x03BE, 3069}, {0x03BF, 3072}, {0x03C0, 3080},
219 {0x03C1, 3083}, {0x03C2, 3087}, {0x03C3, 3094}, {0x03C4, 3100},
220 {0x03C5, 3104}, {0x03C6, 3112}, {0x03C7, 3116}, {0x03C8, 3120},
221 {0x03C9, 3124}, {0x03CA, 3130}, {0x03CB, 3143}, {0x03CC, 3159},
222 {0x03CD, 3172}, {0x03CE, 3185}, {0x03D1, 3196}, {0x03D2, 3203},
223 {0x03D5, 3212}, {0x03D6, 3217}, {0xFFFF, 3224}
226 // This map is used for symbol fonts to get the correct glyph names for the latin range
227 static const unsigned short symbol_map[0x100] = {
228 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
229 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
230 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
231 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
232 0x0020, 0x0021, 0x2200, 0x0023, 0x2203, 0x0025, 0x0026, 0x220b,
233 0x0028, 0x0029, 0x2217, 0x002b, 0x002c, 0x2212, 0x002e, 0x002f,
234 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
235 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
237 0x2245, 0x0391, 0x0392, 0x03a7, 0x0394, 0x0395, 0x03a6, 0x0393,
238 0x0397, 0x0399, 0x03d1, 0x039a, 0x039b, 0x039c, 0x039d, 0x039f,
239 0x03a0, 0x0398, 0x03a1, 0x03a3, 0x03a4, 0x03a5, 0x03c2, 0x03a9,
240 0x039e, 0x03a8, 0x0396, 0x005b, 0x2234, 0x005d, 0x22a5, 0x005f,
241 0xf8e5, 0x03b1, 0x03b2, 0x03c7, 0x03b4, 0x03b5, 0x03c6, 0x03b3,
242 0x03b7, 0x03b9, 0x03d5, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03bf,
243 0x03c0, 0x03b8, 0x03c1, 0x03c3, 0x03c4, 0x03c5, 0x03d6, 0x03c9,
244 0x03be, 0x03c8, 0x03b6, 0x007b, 0x007c, 0x007d, 0x223c, 0x007f,
246 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
247 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
248 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
249 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
250 0x20ac, 0x03d2, 0x2023, 0x2264, 0x2044, 0x221e, 0x0192, 0x2263,
251 0x2666, 0x2665, 0x2660, 0x2194, 0x2190, 0x2191, 0x2192, 0x2193,
252 0x00b0, 0x00b1, 0x2033, 0x2265, 0x00d7, 0x221d, 0x2202, 0x2022,
253 0x00f7, 0x2260, 0x2261, 0x2248, 0x2026, 0xf8e6, 0xf8e7, 0x21b5,
255 0x2135, 0x2111, 0x211c, 0x2118, 0x2297, 0x2295, 0x2205, 0x2229,
256 0x222a, 0x2283, 0x2287, 0x2284, 0x2282, 0x2286, 0x2208, 0x2209,
257 0x2220, 0x2207, 0xf6da, 0xf6d9, 0xf6db, 0x220f, 0x221a, 0x22c5,
258 0x00ac, 0x2227, 0x2228, 0x21d4, 0x21d0, 0x21d1, 0x21d2, 0x21d3,
259 0x25ca, 0x2329, 0xf8e8, 0xf8e9, 0xf8ea, 0x2211, 0xf8eb, 0xf8ec,
260 0xf8ed, 0xf8ee, 0xf8ef, 0xf8f0, 0xf8f1, 0xf8f2, 0xf8f3, 0xf8f4,
261 0x0000, 0x232a, 0x222b, 0x2320, 0xf8f5, 0x2321, 0xf8f6, 0xf8f7,
262 0xf8f8, 0xf8f9, 0xf8fa, 0xf8fb, 0xf8fc, 0xf8fd, 0xf8fe, 0x0000,
265 // ---------------------------- PS/PDF helper methods -----------------------------------
267 QByteArray QFontSubset::glyphName(unsigned short unicode, bool symbol)
269 if (symbol && unicode < 0x100)
270 // map from latin1 to symbol
271 unicode = symbol_map[unicode];
274 while(unicode_to_aglindex[l].u < unicode)
276 if (unicode_to_aglindex[l].u == unicode)
277 return agl + unicode_to_aglindex[l].index;
283 QPdf::toHex(unicode, buffer+3);
287 #ifndef QT_NO_FREETYPE
288 static FT_Face ft_face(const QFontEngine *engine)
291 #ifndef QT_NO_FONTCONFIG
292 if (engine->type() == QFontEngine::Freetype) {
293 const QFontEngineFT *ft = static_cast<const QFontEngineFT *>(engine);
294 return ft->non_locked_face();
297 if (engine->type() == QFontEngine::XLFD) {
298 const QFontEngineXLFD *xlfd = static_cast<const QFontEngineXLFD *>(engine);
299 return xlfd->non_locked_face();
303 if (engine->type() == QFontEngine::Freetype) {
304 const QFontEngineFT *ft = static_cast<const QFontEngineFT *>(engine);
305 return ft->non_locked_face();
312 QByteArray QFontSubset::glyphName(unsigned int glyph, const QVector<int> reverseMap) const
314 uint glyphIndex = glyph_indices[glyph];
320 QPdf::ByteStream s(&ba);
321 #ifndef QT_NO_FREETYPE
322 FT_Face face = ft_face(fontEngine);
326 if (face && FT_HAS_GLYPH_NAMES(face)) {
327 #if defined(Q_WS_X11)
328 if (fontEngine->type() == QFontEngine::XLFD)
329 glyphIndex = static_cast<QFontEngineXLFD *>(fontEngine)->glyphIndexToFreetypeGlyphIndex(glyphIndex);
331 FT_Get_Glyph_Name(face, glyphIndex, &name, 32);
332 if (name[0] == '.') // fix broken PS fonts returning .notdef for many glyphs
339 #if defined(Q_WS_X11)
340 if (fontEngine->type() == QFontEngine::XLFD) {
341 uint uc = static_cast<QFontEngineXLFD *>(fontEngine)->toUnicode(glyphIndex);
342 s << '/' << glyphName(uc, false /* ### */);
345 if (reverseMap[glyphIndex] && reverseMap[glyphIndex] < 0x10000) {
346 s << '/' << glyphName(reverseMap[glyphIndex], false);
348 s << "/gl" << (int)glyphIndex;
354 QByteArray QFontSubset::widthArray() const
356 Q_ASSERT(!widths.isEmpty());
358 QFontEngine::Properties properties = fontEngine->properties();
361 QPdf::ByteStream s(&width);
362 QFixed scale = QFixed(1000)/emSquare;
364 QFixed defWidth = widths[0];
365 //qDebug("defWidth=%d, scale=%f", defWidth.toInt(), scale.toReal());
366 for (int i = 0; i < nGlyphs(); ++i) {
367 if (defWidth != widths[i])
371 s << "/DW " << (defWidth*scale).toInt();
374 for (int g = 0; g < nGlyphs();) {
375 QFixed w = widths[g];
379 while (g < nGlyphs()) {
380 QFixed nw = widths[g];
385 if (startLinear > 0 && g - startLinear >= 10)
392 // qDebug("start=%x startLinear=%x g-1=%x",start,startLinear,g-1);
393 if (g - startLinear < 10)
395 int endnonlinear = startLinear ? startLinear : g;
396 // qDebug(" startLinear=%x endnonlinear=%x", startLinear,endnonlinear);
397 if (endnonlinear > start) {
399 for (int i = start; i < endnonlinear; ++i)
400 s << (widths[i]*scale).toInt();
404 s << startLinear << g - 1 << (widths[startLinear]*scale).toInt() << '\n';
411 static void checkRanges(QPdf::ByteStream &ts, QByteArray &ranges, int &nranges)
413 if (++nranges > 100) {
414 ts << nranges << "beginbfrange\n"
415 << ranges << "endbfrange\n";
416 ranges = QByteArray();
421 QVector<int> QFontSubset::getReverseMap() const
423 QVector<int> reverseMap;
424 reverseMap.resize(0x10000);
425 for (uint i = 0; i < 0x10000; ++i)
427 QGlyphLayoutArray<10> glyphs;
428 for (uint uc = 0; uc < 0x10000; ++uc) {
431 fontEngine->stringToCMap(&ch, 1, &glyphs, &nglyphs, QTextEngine::GlyphIndicesOnly);
432 int idx = glyph_indices.indexOf(glyphs.glyphs[0]);
433 if (idx >= 0 && !reverseMap.at(idx))
434 reverseMap[idx] = uc;
439 QByteArray QFontSubset::createToUnicodeMap() const
441 QVector<int> reverseMap = getReverseMap();
444 QPdf::ByteStream ts(&touc);
445 ts << "/CIDInit /ProcSet findresource begin\n"
448 "/CIDSystemInfo << /Registry (Adobe) /Ordering (UCS) /Supplement 0 >> def\n"
449 "/CMapName /Adobe-Identity-UCS def\n"
451 "1 begincodespacerange\n"
453 "endcodespacerange\n";
456 QByteArray ranges = "<0000> <0000> <0000>\n";
457 QPdf::ByteStream s(&ranges);
460 for (int g = 1; g < nGlyphs(); ) {
461 int uc0 = reverseMap.at(g);
469 while (g < nGlyphs()) {
470 int uc = reverseMap[g];
471 // cmaps can't have the high byte changing within one range, so we need to break on that as well
472 if (!uc || (g>>8) != (start >> 8))
478 if (startLinear > 0 && g - startLinear >= 10)
485 // qDebug("start=%x startLinear=%x g-1=%x",start,startLinear,g-1);
486 if (g - startLinear < 10)
488 int endnonlinear = startLinear ? startLinear : g;
489 // qDebug(" startLinear=%x endnonlinear=%x", startLinear,endnonlinear);
490 if (endnonlinear > start) {
491 s << '<' << QPdf::toHex((ushort)start, buf) << "> <";
492 s << QPdf::toHex((ushort)(endnonlinear - 1), buf) << "> ";
493 if (endnonlinear == start + 1) {
494 s << '<' << QPdf::toHex((ushort)reverseMap[start], buf) << ">\n";
497 for (int i = start; i < endnonlinear; ++i) {
498 s << '<' << QPdf::toHex((ushort)reverseMap[i], buf) << "> ";
502 checkRanges(ts, ranges, nranges);
505 while (startLinear < g) {
506 int len = g - startLinear;
507 int uc_start = reverseMap[startLinear];
508 int uc_end = uc_start + len - 1;
509 if ((uc_end >> 8) != (uc_start >> 8))
510 len = 256 - (uc_start & 0xff);
511 s << '<' << QPdf::toHex((ushort)startLinear, buf) << "> <";
512 s << QPdf::toHex((ushort)(startLinear + len - 1), buf) << "> ";
513 s << '<' << QPdf::toHex((ushort)reverseMap[startLinear], buf) << ">\n";
514 checkRanges(ts, ranges, nranges);
520 ts << nranges << "beginbfrange\n"
521 << ranges << "endbfrange\n";
524 "CMapName currentdict /CMap defineresource pop\n"
531 int QFontSubset::addGlyph(int index)
533 int idx = glyph_indices.indexOf(index);
535 idx = glyph_indices.size();
536 glyph_indices.append(index);
542 // ------------------------------ Truetype generation ----------------------------------------------
544 typedef qint16 F2DOT14;
546 typedef quint16 GlyphID;
547 typedef quint16 Offset;
552 QTtfStream(QByteArray &ba) : data((uchar *)ba.data()) { start = data; }
553 QTtfStream &operator <<(quint8 v) { *data = v; ++data; return *this; }
554 QTtfStream &operator <<(quint16 v) { qToBigEndian(v, data); data += sizeof(v); return *this; }
555 QTtfStream &operator <<(quint32 v) { qToBigEndian(v, data); data += sizeof(v); return *this; }
556 QTtfStream &operator <<(qint8 v) { *data = quint8(v); ++data; return *this; }
557 QTtfStream &operator <<(qint16 v) { qToBigEndian(v, data); data += sizeof(v); return *this; }
558 QTtfStream &operator <<(qint32 v) { qToBigEndian(v, data); data += sizeof(v); return *this; }
559 QTtfStream &operator <<(qint64 v) { qToBigEndian(v, data); data += sizeof(v); return *this; }
561 int offset() const { return data - start; }
562 void setOffset(int o) { data = start + o; }
563 void align4() { while (offset() & 3) { *data = '\0'; ++data; } }
573 Q_DECLARE_TYPEINFO(QTtfTable, Q_MOVABLE_TYPE);
576 struct qttf_head_table {
577 qint32 font_revision;
586 qint16 indexToLocFormat;
590 struct qttf_hhea_table {
594 quint16 maxAdvanceWidth;
595 qint16 minLeftSideBearing;
596 qint16 minRightSideBearing;
598 quint16 numberOfHMetrics;
602 struct qttf_maxp_table {
606 quint16 maxCompositePoints;
607 quint16 maxCompositeContours;
608 quint16 maxComponentElements;
609 quint16 maxComponentDepth;
612 struct qttf_name_table {
616 QString postscript_name;
620 static QTtfTable generateHead(const qttf_head_table &head);
621 static QTtfTable generateHhea(const qttf_hhea_table &hhea);
622 static QTtfTable generateMaxp(const qttf_maxp_table &maxp);
623 static QTtfTable generateName(const qttf_name_table &name);
625 struct qttf_font_tables
627 qttf_head_table head;
628 qttf_hhea_table hhea;
629 qttf_maxp_table maxp;
639 quint16 advanceWidth;
645 Q_DECLARE_TYPEINFO(QTtfGlyph, Q_MOVABLE_TYPE);
647 static QTtfGlyph generateGlyph(int index, const QPainterPath &path, qreal advance, qreal lsb, qreal ppem);
648 // generates glyf, loca and hmtx
649 static QList<QTtfTable> generateGlyphTables(qttf_font_tables &tables, const QList<QTtfGlyph> &_glyphs);
651 static QByteArray bindFont(const QList<QTtfTable>& _tables);
654 static quint32 checksum(const QByteArray &table)
658 const uchar *d = (uchar *)table.constData();
659 while (offset <= table.size()-3) {
660 sum += qFromBigEndian<quint32>(d + offset);
665 while (offset < table.size()) {
666 x |= ((quint32)d[offset]) << shift;
675 static QTtfTable generateHead(const qttf_head_table &head)
677 const int head_size = 54;
679 t.tag = MAKE_TAG('h', 'e', 'a', 'd');
680 t.data.resize(head_size);
682 QTtfStream s(t.data);
684 // qint32 Table version number 0x00010000 for version 1.0.
685 // qint32 fontRevision Set by font manufacturer.
686 s << qint32(0x00010000)
687 << head.font_revision
688 // quint32 checkSumAdjustment To compute: set it to 0, sum the entire font as quint32, then store 0xB1B0AFBA - sum.
690 // quint32 magicNumber Set to 0x5F0F3CF5.
691 << quint32(0x5F0F3CF5)
692 // quint16 flags Bit 0: Baseline for font at y=0;
693 // Bit 1: Left sidebearing point at x=0;
694 // Bit 2: Instructions may depend on point size;
695 // Bit 3: Force ppem to integer values for all internal scaler math; may use fractional ppem sizes if this bit is clear;
696 // Bit 4: Instructions may alter advance width (the advance widths might not scale linearly);
697 // Bits 5-10: These should be set according to Apple's specification . However, they are not implemented in OpenType.
698 // Bit 11: Font data is 'lossless,' as a result of having been compressed and decompressed with the Agfa MicroType Express engine.
699 // Bit 12: Font converted (produce compatible metrics)
700 // Bit 13: Font optimized for ClearType
701 // Bit 14: Reserved, set to 0
702 // Bit 15: Reserved, set to 0
705 // quint16 unitsPerEm Valid range is from 16 to 16384. This value should be a power of 2 for fonts that have TrueType outlines.
707 // qint64 created Number of seconds since 12:00 midnight, January 1, 1904. 64-bit integer
709 // qint64 modified Number of seconds since 12:00 midnight, January 1, 1904. 64-bit integer
711 // qint16 xMin For all glyph bounding boxes.
712 // qint16 yMin For all glyph bounding boxes.
713 // qint16 xMax For all glyph bounding boxes.
714 // qint16 yMax For all glyph bounding boxes.
719 // quint16 macStyle Bit 0: Bold (if set to 1);
720 // Bit 1: Italic (if set to 1)
721 // Bit 2: Underline (if set to 1)
722 // Bit 3: Outline (if set to 1)
723 // Bit 4: Shadow (if set to 1)
724 // Bit 5: Condensed (if set to 1)
725 // Bit 6: Extended (if set to 1)
726 // Bits 7-15: Reserved (set to 0).
728 // quint16 lowestRecPPEM Smallest readable size in pixels.
729 << quint16(6) // just a wild guess
730 // qint16 fontDirectionHint 0: Fully mixed directional glyphs;
732 // 1: Only strongly left to right;
733 // 2: Like 1 but also contains neutrals;
734 // -1: Only strongly right to left;
735 // -2: Like -1 but also contains neutrals. 1
736 // qint16 indexToLocFormat 0 for short offsets, 1 for long.
737 << head.indexToLocFormat
738 // qint16 glyphDataFormat 0 for current format.
741 Q_ASSERT(s.offset() == head_size);
746 static QTtfTable generateHhea(const qttf_hhea_table &hhea)
748 const int hhea_size = 36;
750 t.tag = MAKE_TAG('h', 'h', 'e', 'a');
751 t.data.resize(hhea_size);
753 QTtfStream s(t.data);
754 // qint32 Table version number 0x00010000 for version 1.0.
755 s << qint32(0x00010000)
756 // qint16 Ascender Typographic ascent. (Distance from baseline of highest ascender)
758 // qint16 Descender Typographic descent. (Distance from baseline of lowest descender)
760 // qint16 LineGap Typographic line gap.
761 // Negative LineGap values are treated as zero
762 // in Windows 3.1, System 6, and
765 // quint16 advanceWidthMax Maximum advance width value in 'hmtx' table.
766 << hhea.maxAdvanceWidth
767 // qint16 minLeftSideBearing Minimum left sidebearing value in 'hmtx' table.
768 << hhea.minLeftSideBearing
769 // qint16 minRightSideBearing Minimum right sidebearing value; calculated as Min(aw - lsb - (xMax - xMin)).
770 << hhea.minRightSideBearing
771 // qint16 xMaxExtent Max(lsb + (xMax - xMin)).
773 // qint16 caretSlopeRise Used to calculate the slope of the cursor (rise/run); 1 for vertical.
775 // qint16 caretSlopeRun 0 for vertical.
777 // 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
779 // qint16 (reserved) set to 0
781 // qint16 (reserved) set to 0
783 // qint16 (reserved) set to 0
785 // qint16 (reserved) set to 0
787 // qint16 metricDataFormat 0 for current format.
789 // quint16 numberOfHMetrics Number of hMetric entries in 'hmtx' table
790 << hhea.numberOfHMetrics;
792 Q_ASSERT(s.offset() == hhea_size);
797 static QTtfTable generateMaxp(const qttf_maxp_table &maxp)
799 const int maxp_size = 32;
801 t.tag = MAKE_TAG('m', 'a', 'x', 'p');
802 t.data.resize(maxp_size);
804 QTtfStream s(t.data);
806 // qint32 Table version number 0x00010000 for version 1.0.
807 s << qint32(0x00010000)
808 // quint16 numGlyphs The number of glyphs in the font.
810 // quint16 maxPoints Maximum points in a non-composite glyph.
812 // quint16 maxContours Maximum contours in a non-composite glyph.
814 // quint16 maxCompositePoints Maximum points in a composite glyph.
815 << maxp.maxCompositePoints
816 // quint16 maxCompositeContours Maximum contours in a composite glyph.
817 << maxp.maxCompositeContours
818 // 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.
819 << quint16(1) // we do not embed instructions
820 // quint16 maxTwilightPoints Maximum points used in Z0.
822 // quint16 maxStorage Number of Storage Area locations.
824 // quint16 maxFunctionDefs Number of FDEFs.
826 // quint16 maxInstructionDefs Number of IDEFs.
828 // quint16 maxStackElements Maximum stack depth2.
830 // quint16 maxSizeOfInstructions Maximum byte count for glyph instructions.
832 // quint16 maxComponentElements Maximum number of components referenced at "top level" for any composite glyph.
833 << maxp.maxComponentElements
834 // quint16 maxComponentDepth Maximum levels of recursion; 1 for simple components.
835 << maxp.maxComponentDepth;
837 Q_ASSERT(s.offset() == maxp_size);
841 struct QTtfNameRecord {
846 static QTtfTable generateName(const QList<QTtfNameRecord> &name);
848 static QTtfTable generateName(const qttf_name_table &name)
850 QList<QTtfNameRecord> list;
853 rec.value = name.copyright;
856 rec.value = name.family;
859 rec.value = name.subfamily;
862 rec.value = name.family;
863 if (name.subfamily != QLatin1String("Regular"))
864 rec.value += QLatin1Char(' ') + name.subfamily;
867 rec.value = name.postscript_name;
870 return generateName(list);
873 // ####### should probably generate Macintosh/Roman name entries as well
874 static QTtfTable generateName(const QList<QTtfNameRecord> &name)
876 const int char_size = 2;
879 t.tag = MAKE_TAG('n', 'a', 'm', 'e');
881 const int name_size = 6 + 12*name.size();
883 for (int i = 0; i < name.size(); ++i) {
884 string_size += name.at(i).value.length()*char_size;
886 t.data.resize(name_size + string_size);
888 QTtfStream s(t.data);
889 // quint16 format Format selector (=0).
891 // quint16 count Number of name records.
892 << quint16(name.size())
893 // quint16 stringOffset Offset to start of string storage (from start of table).
894 << quint16(name_size);
895 // NameRecord nameRecord[count] The name records where count is the number of records.
899 for (int i = 0; i < name.size(); ++i) {
900 int len = name.at(i).value.length()*char_size;
901 // quint16 platformID Platform ID.
902 // quint16 encodingID Platform-specific encoding ID.
903 // quint16 languageID Language ID.
906 << quint16(0x0409) // en_US
907 // quint16 nameId Name ID.
909 // quint16 length String length (in bytes).
911 // quint16 offset String offset from start of storage area (in bytes).
915 for (int i = 0; i < name.size(); ++i) {
916 const QString &n = name.at(i).value;
917 const ushort *uc = n.utf16();
918 for (int i = 0; i < n.length(); ++i) {
930 XShortVector = (1 << 1),
931 YShortVector = (1 << 2),
934 XShortPositive = (1 << 4),
936 YShortPositive = (1 << 5)
943 Q_DECLARE_TYPEINFO(TTF_POINT, Q_PRIMITIVE_TYPE);
945 static void convertPath(const QPainterPath &path, QList<TTF_POINT> *points, QList<int> *endPoints, qreal ppem)
947 int numElements = path.elementCount();
948 for (int i = 0; i < numElements - 1; ++i) {
949 const QPainterPath::Element &e = path.elementAt(i);
951 p.x = qRound(e.x * 2048. / ppem);
952 p.y = qRound(-e.y * 2048. / ppem);
956 case QPainterPath::MoveToElement:
958 // see if start and end points of the last contour agree
959 int start = endPoints->size() ? endPoints->at(endPoints->size()-1) - 1 : 0;
960 int end = points->size() - 1;
961 if (points->at(end).x == points->at(start).x
962 && points->at(end).y == points->at(start).y)
964 endPoints->append(points->size() - 1);
967 case QPainterPath::LineToElement:
970 case QPainterPath::CurveToElement: {
971 // cubic bezier curve, we need to reduce to a list of quadratic curves
972 TTF_POINT list[3*16 + 4]; // we need max 16 subdivisions
973 list[3] = points->at(points->size() - 1);
975 const QPainterPath::Element &e2 = path.elementAt(++i);
976 list[1].x = qRound(e2.x * 2048. / ppem);
977 list[1].y = qRound(-e2.y * 2048. / ppem);
978 const QPainterPath::Element &e3 = path.elementAt(++i);
979 list[0].x = qRound(e3.x * 2048. / ppem);
980 list[0].y = qRound(-e3.y * 2048. / ppem);
982 TTF_POINT *base = list;
984 bool try_reduce = points->size() > 1
985 && points->at(points->size() - 1).flags == OnCurve
986 && points->at(points->size() - 2).flags == OffCurve;
987 // qDebug("generating beziers:");
988 while (base >= list) {
989 const int split_limit = 3;
991 // qDebug("iteration:");
992 // TTF_POINT *x = list;
993 // while (x <= base + 3) {
994 // qDebug() << " " << QPoint(x->x, x->y);
998 Q_ASSERT(base - list < 3*16 + 1);
999 // first see if we can easily reduce the cubic to a quadratic bezier curve
1000 int i1_x = base[1].x + ((base[1].x - base[0].x) >> 1);
1001 int i1_y = base[1].y + ((base[1].y - base[0].y) >> 1);
1002 int i2_x = base[2].x + ((base[2].x - base[3].x) >> 1);
1003 int i2_y = base[2].y + ((base[2].y - base[3].y) >> 1);
1004 // qDebug() << "checking: i1=" << QPoint(i1_x, i1_y) << " i2=" << QPoint(i2_x, i2_y);
1005 if (qAbs(i1_x - i2_x) <= split_limit && qAbs(i1_y - i2_y) <= split_limit) {
1006 // got a quadratic bezier curve
1008 np.x = (i1_x + i2_x) >> 1;
1009 np.y = (i1_y + i2_y) >> 1;
1011 // see if we can optimize out the last onCurve point
1012 int mx = (points->at(points->size() - 2).x + base[2].x) >> 1;
1013 int my = (points->at(points->size() - 2).y + base[2].y) >> 1;
1014 if (qAbs(mx - base[3].x) <= split_limit && qAbs(my = base[3].y) <= split_limit)
1018 np.flags = OffCurve;
1020 // qDebug() << " appending offcurve point " << QPoint(np.x, np.y);
1024 // qDebug() << " -> splitting";
1026 base[6].x = base[3].x;
1029 base[1].x = a = ( base[0].x + c ) >> 1;
1030 base[5].x = b = ( base[3].x + d ) >> 1;
1032 base[2].x = a = ( a + c ) >> 1;
1033 base[4].x = b = ( b + c ) >> 1;
1034 base[3].x = ( a + b ) >> 1;
1036 base[6].y = base[3].y;
1039 base[1].y = a = ( base[0].y + c ) >> 1;
1040 base[5].y = b = ( base[3].y + d ) >> 1;
1042 base[2].y = a = ( a + c ) >> 1;
1043 base[4].y = b = ( b + c ) >> 1;
1044 base[3].y = ( a + b ) >> 1;
1052 case QPainterPath::CurveToDataElement:
1056 // qDebug() << " appending oncurve point " << QPoint(p.x, p.y);
1059 int start = endPoints->size() ? endPoints->at(endPoints->size()-1) + 1 : 0;
1060 int end = points->size() - 1;
1061 if (points->at(end).x == points->at(start).x
1062 && points->at(end).y == points->at(start).y)
1064 endPoints->append(points->size() - 1);
1067 static void getBounds(const QList<TTF_POINT> &points, qint16 *xmin, qint16 *xmax, qint16 *ymin, qint16 *ymax)
1069 *xmin = points.at(0).x;
1071 *ymin = points.at(0).y;
1074 for (int i = 1; i < points.size(); ++i) {
1075 *xmin = qMin(*xmin, points.at(i).x);
1076 *xmax = qMax(*xmax, points.at(i).x);
1077 *ymin = qMin(*ymin, points.at(i).y);
1078 *ymax = qMax(*ymax, points.at(i).y);
1082 static int convertToRelative(QList<TTF_POINT> *points)
1084 // convert points to relative and setup flags
1085 // qDebug() << "relative points:";
1088 int point_array_size = 0;
1089 for (int i = 0; i < points->size(); ++i) {
1090 const int x = points->at(i).x;
1091 const int y = points->at(i).y;
1095 rel.flags = points->at(i).flags;
1096 Q_ASSERT(rel.flags < 2);
1099 } else if (rel.x > 0 && rel.x < 256) {
1100 rel.flags |= XShortVector|XShortPositive;
1102 } else if (rel.x < 0 && rel.x > -256) {
1103 rel.flags |= XShortVector;
1107 point_array_size += 2;
1111 } else if (rel.y > 0 && rel.y < 256) {
1112 rel.flags |= YShortVector|YShortPositive;
1114 } else if (rel.y < 0 && rel.y > -256) {
1115 rel.flags |= YShortVector;
1119 point_array_size += 2;
1122 // #define toString(x) ((rel.flags & x) ? #x : "")
1123 // qDebug() << " " << QPoint(rel.x, rel.y) << "flags="
1124 // << toString(OnCurve) << toString(XShortVector)
1125 // << (rel.flags & XShortVector ? toString(XShortPositive) : toString(XSame))
1126 // << toString(YShortVector)
1127 // << (rel.flags & YShortVector ? toString(YShortPositive) : toString(YSame));
1132 return point_array_size;
1135 static void getGlyphData(QTtfGlyph *glyph, const QList<TTF_POINT> &points, const QList<int> &endPoints, int point_array_size)
1137 const int max_size = 5*sizeof(qint16) // header
1138 + endPoints.size()*sizeof(quint16) // end points of contours
1139 + sizeof(quint16) // instruction length == 0
1140 + points.size()*(1) // flags
1141 + point_array_size; // coordinates
1143 glyph->data.resize(max_size);
1145 QTtfStream s(glyph->data);
1146 s << qint16(endPoints.size())
1147 << glyph->xMin << glyph->yMin << glyph->xMax << glyph->yMax;
1149 for (int i = 0; i < endPoints.size(); ++i)
1150 s << quint16(endPoints.at(i));
1151 s << quint16(0); // instruction length
1154 for (int i = 0; i < points.size(); ++i)
1155 s << quint8(points.at(i).flags);
1157 for (int i = 0; i < points.size(); ++i) {
1158 quint8 flags = points.at(i).flags;
1159 qint16 x = points.at(i).x;
1161 if (flags & XShortVector)
1163 else if (!(flags & XSame))
1166 for (int i = 0; i < points.size(); ++i) {
1167 quint8 flags = points.at(i).flags;
1168 qint16 y = points.at(i).y;
1170 if (flags & YShortVector)
1172 else if (!(flags & YSame))
1176 // qDebug() << "offset=" << s.offset() << "max_size=" << max_size << "point_array_size=" << point_array_size;
1177 Q_ASSERT(s.offset() == max_size);
1179 glyph->numContours = endPoints.size();
1180 glyph->numPoints = points.size();
1183 static QTtfGlyph generateGlyph(int index, const QPainterPath &path, qreal advance, qreal lsb, qreal ppem)
1185 QList<TTF_POINT> points;
1186 QList<int> endPoints;
1188 glyph.index = index;
1189 glyph.advanceWidth = qRound(advance * 2048. / ppem);
1190 glyph.lsb = qRound(lsb * 2048. / ppem);
1192 if (!path.elementCount()) {
1193 //qDebug("glyph %d is empty", index);
1195 glyph.xMin = glyph.xMax = glyph.yMin = glyph.yMax = 0;
1196 glyph.numContours = 0;
1197 glyph.numPoints = 0;
1201 convertPath(path, &points, &endPoints, ppem);
1203 // qDebug() << "number of contours=" << endPoints.size();
1204 // for (int i = 0; i < points.size(); ++i)
1205 // qDebug() << " point[" << i << "] = " << QPoint(points.at(i).x, points.at(i).y) << " flags=" << points.at(i).flags;
1206 // qDebug() << "endPoints:";
1207 // for (int i = 0; i < endPoints.size(); ++i)
1208 // qDebug() << endPoints.at(i);
1210 getBounds(points, &glyph.xMin, &glyph.xMax, &glyph.yMin, &glyph.yMax);
1211 int point_array_size = convertToRelative(&points);
1212 getGlyphData(&glyph, points, endPoints, point_array_size);
1216 Q_STATIC_GLOBAL_OPERATOR bool operator <(const QTtfGlyph &g1, const QTtfGlyph &g2)
1218 return g1.index < g2.index;
1221 static QList<QTtfTable> generateGlyphTables(qttf_font_tables &tables, const QList<QTtfGlyph> &_glyphs)
1223 const int max_size_small = 65536*2;
1224 QList<QTtfGlyph> glyphs = _glyphs;
1227 Q_ASSERT(tables.maxp.numGlyphs == glyphs.at(glyphs.size()-1).index + 1);
1228 int nGlyphs = tables.maxp.numGlyphs;
1231 for (int i = 0; i < glyphs.size(); ++i)
1232 glyf_size += (glyphs.at(i).data.size() + 3) & ~3;
1234 tables.head.indexToLocFormat = glyf_size < max_size_small ? 0 : 1;
1235 tables.hhea.numberOfHMetrics = nGlyphs;
1238 glyf.tag = MAKE_TAG('g', 'l', 'y', 'f');
1241 loca.tag = MAKE_TAG('l', 'o', 'c', 'a');
1242 loca.data.resize(glyf_size < max_size_small ? (nGlyphs+1)*sizeof(quint16) : (nGlyphs+1)*sizeof(quint32));
1243 QTtfStream ls(loca.data);
1246 hmtx.tag = MAKE_TAG('h', 'm', 't', 'x');
1247 hmtx.data.resize(nGlyphs*4);
1248 QTtfStream hs(hmtx.data);
1251 for (int i = 0; i < nGlyphs; ++i) {
1252 int gpos = glyf.data.size();
1253 quint16 advance = 0;
1256 if (glyphs[pos].index == i) {
1258 // qDebug("emitting glyph %d: size=%d", i, glyphs.at(i).data.size());
1259 glyf.data += glyphs.at(pos).data;
1260 while (glyf.data.size() & 1)
1261 glyf.data.append('\0');
1262 advance = glyphs.at(pos).advanceWidth;
1263 lsb = glyphs.at(pos).lsb;
1266 if (glyf_size < max_size_small) {
1267 // use short loca format
1268 ls << quint16(gpos>>1);
1270 // use long loca format
1271 ls << quint32(gpos);
1276 if (glyf_size < max_size_small) {
1277 // use short loca format
1278 ls << quint16(glyf.data.size()>>1);
1280 // use long loca format
1281 ls << quint32(glyf.data.size());
1284 Q_ASSERT(loca.data.size() == ls.offset());
1285 Q_ASSERT(hmtx.data.size() == hs.offset());
1287 QList<QTtfTable> list;
1294 Q_STATIC_GLOBAL_OPERATOR bool operator <(const QTtfTable &t1, const QTtfTable &t2)
1296 return t1.tag < t2.tag;
1299 static QByteArray bindFont(const QList<QTtfTable>& _tables)
1301 QList<QTtfTable> tables = _tables;
1306 const int header_size = sizeof(qint32) + 4*sizeof(quint16);
1307 const int directory_size = 4*sizeof(quint32)*tables.size();
1308 font.resize(header_size + directory_size);
1312 int n = tables.size() >> 1;
1319 quint32 head_offset = 0;
1323 // Type Name Description
1324 // qint32 sfnt version 0x00010000 for version 1.0.
1325 // quint16 numTables Number of tables.
1326 // quint16 searchRange (Maximum power of 2 <= numTables) x 16.
1327 // quint16 entrySelector Log2(maximum power of 2 <= numTables).
1328 // quint16 rangeShift NumTables x 16-searchRange.
1329 f << qint32(0x00010000)
1330 << quint16(tables.size())
1333 << quint16(16*(tables.size() - pow));
1336 // Type Name Description
1337 // quint32 tag 4 -byte identifier.
1338 // quint32 checkSum CheckSum for this table.
1339 // quint32 offset Offset from beginning of TrueType font file.
1340 // quint32 length Length of this table.
1341 quint32 table_offset = header_size + directory_size;
1342 for (int i = 0; i < tables.size(); ++i) {
1343 const QTtfTable &t = tables.at(i);
1344 const quint32 size = (t.data.size() + 3) & ~3;
1345 if (t.tag == MAKE_TAG('h', 'e', 'a', 'd'))
1346 head_offset = table_offset;
1351 table_offset += size;
1352 #define TAG(x) char(t.tag >> 24) << char((t.tag >> 16) & 0xff) << char((t.tag >> 8) & 0xff) << char(t.tag & 0xff)
1353 //qDebug() << "table " << TAG(t.tag) << "has size " << t.data.size() << "stream at " << f.offset();
1356 for (int i = 0; i < tables.size(); ++i) {
1357 const QByteArray &t = tables.at(i).data;
1360 while (s & 3) { font += '\0'; ++s; }
1364 qWarning("QFontSubset: Font misses 'head' table");
1365 return QByteArray();
1368 // calculate the fonts checksum and qToBigEndian into 'head's checksum_adjust
1369 quint32 checksum_adjust = 0xB1B0AFBA - checksum(font);
1370 qToBigEndian(checksum_adjust, (uchar *)font.data() + head_offset + 8);
1377 PDF requires the following tables:
1379 head, hhea, loca, maxp, cvt , prep, glyf, hmtx, fpgm
1381 This means we don't have to add a os/2, post or name table. cvt , prep and fpgm could be empty
1385 QByteArray QFontSubset::toTruetype() const
1387 qttf_font_tables font;
1388 memset(&font, 0, sizeof(qttf_font_tables));
1390 qreal ppem = fontEngine->fontDef.pixelSize;
1391 #define TO_TTF(x) qRound(x * 2048. / ppem)
1392 QList<QTtfGlyph> glyphs;
1394 QFontEngine::Properties properties = fontEngine->properties();
1395 // initialize some stuff needed in createWidthArray
1397 widths.resize(nGlyphs());
1400 font.head.font_revision = 0x00010000;
1401 font.head.flags = (1 << 2) | (1 << 4);
1402 font.head.created = 0; // ###
1403 font.head.modified = 0; // ###
1404 font.head.xMin = SHRT_MAX;
1405 font.head.xMax = SHRT_MIN;
1406 font.head.yMin = SHRT_MAX;
1407 font.head.yMax = SHRT_MIN;
1408 font.head.macStyle = (fontEngine->fontDef.weight > QFont::Normal) ? 1 : 0;
1409 font.head.macStyle |= (fontEngine->fontDef.styleHint != QFont::StyleNormal) ? 1 : 0;
1412 font.hhea.ascender = qRound(properties.ascent);
1413 font.hhea.descender = -qRound(properties.descent);
1414 font.hhea.lineGap = qRound(properties.leading);
1415 font.hhea.maxAdvanceWidth = TO_TTF(fontEngine->maxCharWidth());
1416 font.hhea.minLeftSideBearing = TO_TTF(fontEngine->minLeftBearing());
1417 font.hhea.minRightSideBearing = TO_TTF(fontEngine->minRightBearing());
1418 font.hhea.xMaxExtent = SHRT_MIN;
1420 font.maxp.numGlyphs = 0;
1421 font.maxp.maxPoints = 0;
1422 font.maxp.maxContours = 0;
1423 font.maxp.maxCompositePoints = 0;
1424 font.maxp.maxCompositeContours = 0;
1425 font.maxp.maxComponentElements = 0;
1426 font.maxp.maxComponentDepth = 0;
1427 font.maxp.numGlyphs = nGlyphs();
1431 uint sumAdvances = 0;
1432 for (int i = 0; i < nGlyphs(); ++i) {
1433 glyph_t g = glyph_indices.at(i);
1435 glyph_metrics_t metric;
1436 fontEngine->getUnscaledGlyph(g, &path, &metric);
1438 path = QPainterPath();
1440 path.addRect(QRectF(0, 0, 1000, 1000));
1442 QTtfGlyph glyph = generateGlyph(i, path, metric.xoff.toReal(), metric.x.toReal(), properties.emSquare.toReal());
1444 font.head.xMin = qMin(font.head.xMin, glyph.xMin);
1445 font.head.xMax = qMax(font.head.xMax, glyph.xMax);
1446 font.head.yMin = qMin(font.head.yMin, glyph.yMin);
1447 font.head.yMax = qMax(font.head.yMax, glyph.yMax);
1449 font.hhea.xMaxExtent = qMax(font.hhea.xMaxExtent, (qint16)(glyph.lsb + glyph.xMax - glyph.xMin));
1451 font.maxp.maxPoints = qMax(font.maxp.maxPoints, glyph.numPoints);
1452 font.maxp.maxContours = qMax(font.maxp.maxContours, glyph.numContours);
1454 if (glyph.xMax > glyph.xMin)
1455 sumAdvances += glyph.xMax - glyph.xMin;
1457 // qDebug("adding glyph %d size=%d", glyph.index, glyph.data.size());
1458 glyphs.append(glyph);
1459 widths[i] = glyph.advanceWidth;
1463 QList<QTtfTable> tables = generateGlyphTables(font, glyphs);
1464 tables.append(generateHead(font.head));
1465 tables.append(generateHhea(font.hhea));
1466 tables.append(generateMaxp(font.maxp));
1468 QTtfTable name_table;
1469 name_table.tag = MAKE_TAG('n', 'a', 'm', 'e');
1471 name_table.data = fontEngine->getSfntTable(name_table.tag);
1472 if (name_table.data.isEmpty()) {
1473 qttf_name_table name;
1475 name.copyright = QLatin1String("Fake font");
1477 name.copyright = QLatin1String(properties.copyright);
1478 name.family = fontEngine->fontDef.family;
1479 name.subfamily = QLatin1String("Regular"); // ######
1480 name.postscript_name = QLatin1String(properties.postscriptName);
1481 name_table = generateName(name);
1483 tables.append(name_table);
1487 os2.tag = MAKE_TAG('O', 'S', '/', '2');
1488 os2.data = fontEngine->getSfntTable(os2.tag);
1489 if (!os2.data.isEmpty())
1493 return bindFont(tables);
1496 // ------------------ Type 1 generation ---------------------------
1498 // needs at least 6 bytes of space in tmp
1499 static const char *encodeNumber(int num, char *tmp)
1501 const char *ret = tmp;
1502 if(num >= -107 && num <= 107) {
1503 QPdf::toHex((uchar)(num + 139), tmp);
1505 } else if (num > 107 && num <= 1131) {
1507 QPdf::toHex((uchar)((num >> 8) + 247), tmp);
1509 QPdf::toHex((uchar)(num & 0xff), tmp);
1511 } else if(num < - 107 && num >= -1131) {
1514 QPdf::toHex((uchar)((num >> 8) + 251), tmp);
1516 QPdf::toHex((uchar)(num & 0xff), tmp);
1521 QPdf::toHex((uchar)(num >> 24), tmp);
1523 QPdf::toHex((uchar)(num >> 16), tmp);
1525 QPdf::toHex((uchar)(num >> 8), tmp);
1527 QPdf::toHex((uchar)(num >> 0), tmp);
1531 // qDebug("encodeNumber: %d -> '%s'", num, ret);
1535 static QByteArray charString(const QPainterPath &path, qreal advance, qreal lsb, qreal ppem)
1537 // the charstring commands we need
1538 const char *hsbw = "0D";
1539 const char *closepath = "09";
1540 const char *moveto[3] = { "16", "04", "15" };
1541 const char *lineto[3] = { "06", "07", "05" };
1542 const char *rcurveto = "08";
1543 const char *endchar = "0E";
1545 enum { horizontal = 1, vertical = 2 };
1549 qreal factor = 1000./ppem;
1551 int lsb_i = qRound(lsb*factor);
1552 int advance_i = qRound(advance*factor);
1553 // qDebug("--- charstring");
1555 // first of all add lsb and width to the charstring using the hsbw command
1556 QByteArray charstring;
1557 charstring += encodeNumber(lsb_i, tmp);
1558 charstring += encodeNumber(advance_i, tmp);
1564 bool openpath = false;
1565 for (int i = 0; i < path.elementCount(); ++i) {
1566 const QPainterPath::Element &elm = path.elementAt(i);
1567 int x = qRound(elm.x*factor);
1568 int y = -qRound(elm.y*factor);
1571 if (elm.type == QPainterPath::MoveToElement && openpath) {
1572 // qDebug("closepath %s", closepath);
1573 charstring += closepath;
1575 if (elm.type == QPainterPath::MoveToElement ||
1576 elm.type == QPainterPath::LineToElement) {
1579 charstring += encodeNumber(dx, tmp);
1581 // qDebug("horizontal");
1584 charstring += encodeNumber(dy, tmp);
1586 // qDebug("vertical");
1588 // qDebug("moveto/lineto %s", (elm.type == QPainterPath::MoveToElement ? moveto[type] : lineto[type]));
1589 charstring += (elm.type == QPainterPath::MoveToElement ? moveto[type] : lineto[type]);
1594 Q_ASSERT(elm.type == QPainterPath::CurveToElement);
1595 const QPainterPath::Element &elm2 = path.elementAt(++i);
1596 const QPainterPath::Element &elm3 = path.elementAt(++i);
1597 int x2 = qRound(elm2.x*factor);
1598 int y2 = -qRound(elm2.y*factor);
1599 int x3 = qRound(elm3.x*factor);
1600 int y3 = -qRound(elm3.y*factor);
1601 charstring += encodeNumber(dx, tmp);
1602 charstring += encodeNumber(dy, tmp);
1603 charstring += encodeNumber(x2 - x, tmp);
1604 charstring += encodeNumber(y2 - y, tmp);
1605 charstring += encodeNumber(x3 - x2, tmp);
1606 charstring += encodeNumber(y3 - y2, tmp);
1607 charstring += rcurveto;
1611 // qDebug("rcurveto");
1615 charstring += closepath;
1616 charstring += endchar;
1617 if (charstring.length() > 240) {
1619 while (pos < charstring.length()) {
1620 charstring.insert(pos, '\n');
1627 #ifndef QT_NO_FREETYPE
1628 static const char *helvetica_styles[4] = {
1631 "Helvetica-Oblique",
1632 "Helvetica-BoldOblique"
1634 static const char *times_styles[4] = {
1640 static const char *courier_styles[4] = {
1644 "Courier-BoldOblique"
1648 QByteArray QFontSubset::toType1() const
1650 QFontEngine::Properties properties = fontEngine->properties();
1651 QVector<int> reverseMap = getReverseMap();
1654 QPdf::ByteStream s(&font);
1656 QByteArray id = QByteArray::number(object_id);
1657 QByteArray psname = properties.postscriptName;
1658 psname.replace(' ', "");
1660 standard_font = false;
1662 #ifndef QT_NO_FREETYPE
1663 FT_Face face = ft_face(fontEngine);
1664 if (face && !FT_IS_SCALABLE(face)) {
1666 if (fontEngine->fontDef.style)
1668 if (fontEngine->fontDef.weight >= QFont::Bold)
1670 if (fontEngine->fontDef.family.contains(QLatin1String("Helvetica"))) {
1671 psname = helvetica_styles[style];
1672 standard_font = true;
1673 } else if (fontEngine->fontDef.family.contains(QLatin1String("Times"))) {
1674 psname = times_styles[style];
1675 standard_font = true;
1676 } else if (fontEngine->fontDef.family.contains(QLatin1String("Courier"))) {
1677 psname = courier_styles[style];
1678 standard_font = true;
1682 s << "/F" << id << "-Base\n";
1683 if (standard_font) {
1684 s << '/' << psname << " findfont\n"
1685 "0 dict copy dup /NumGlyphs 0 put dup /CMap 256 array put def\n";
1688 if(!psname.isEmpty())
1689 s << "/FontName /" << psname << '\n';
1690 s << "/FontInfo <</FsType " << (int)fontEngine->fsType << ">>\n"
1693 "/FontMatrix [.001 0 0 .001 0 0]\n"
1694 "/FontBBox { 0 0 0 0 }\n"
1697 "/MinFeature {16 16}\n"
1701 "/CharStrings << >>\n"
1706 s << type1AddedGlyphs();
1707 downloaded_glyphs = glyph_indices.size();
1712 QByteArray QFontSubset::type1AddedGlyphs() const
1714 if (downloaded_glyphs == glyph_indices.size())
1715 return QByteArray();
1717 QFontEngine::Properties properties = fontEngine->properties();
1718 QVector<int> reverseMap = getReverseMap();
1720 QPdf::ByteStream s(&glyphs);
1722 int nGlyphs = glyph_indices.size();
1723 QByteArray id = QByteArray::number(object_id);
1725 s << 'F' << id << "-Base [\n";
1726 for (int i = downloaded_glyphs; i < nGlyphs; ++i) {
1727 glyph_t g = glyph_indices.at(i);
1729 glyph_metrics_t metric;
1730 fontEngine->getUnscaledGlyph(g, &path, &metric);
1731 QByteArray charstring = charString(path, metric.xoff.toReal(), metric.x.toReal(),
1732 properties.emSquare.toReal());
1733 s << glyphName(i, reverseMap);
1735 s << "\n<" << charstring << ">\n";
1737 s << (standard_font ? "] T1AddMapping\n" : "] T1AddGlyphs\n");
1743 #endif // QT_NO_PRINTER