Fix uses of qRound on non-floating-point types.
[profile/ivi/qtbase.git] / src / gui / text / qfontsubset.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the QtGui module of the Qt Toolkit.
8 **
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.
17 **
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.
21 **
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.
29 **
30 ** Other Usage
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.
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 #include <qdebug.h>
42 #include "qfontsubset_p.h"
43 #include <qendian.h>
44 #include <qpainterpath.h>
45 #include "private/qpdf_p.h"
46 #include "private/qfunctions_p.h"
47
48 #ifdef Q_WS_X11
49 #include "private/qfontengine_x11_p.h"
50 #endif
51
52 #ifndef QT_NO_FREETYPE
53 #if defined(Q_WS_X11) || defined(Q_WS_QWS)
54 #    include "private/qfontengine_ft_p.h"
55 #endif
56 #include <ft2build.h>
57 #include FT_FREETYPE_H
58 #endif
59
60 #ifndef QT_NO_PRINTER
61
62 QT_BEGIN_NAMESPACE
63
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"
114 ;
115
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}
224 };
225
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,
236
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,
245
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,
254
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,
263 };
264
265 // ---------------------------- PS/PDF helper methods -----------------------------------
266
267 QByteArray QFontSubset::glyphName(unsigned short unicode, bool symbol)
268 {
269     if (symbol && unicode < 0x100)
270         // map from latin1 to symbol
271         unicode = symbol_map[unicode];
272
273     int l = 0;
274     while(unicode_to_aglindex[l].u < unicode)
275         l++;
276     if (unicode_to_aglindex[l].u == unicode)
277         return agl + unicode_to_aglindex[l].index;
278
279     char buffer[8];
280     buffer[0] = 'u';
281     buffer[1] = 'n';
282     buffer[2] = 'i';
283     QPdf::toHex(unicode, buffer+3);
284     return buffer;
285 }
286
287 #ifndef QT_NO_FREETYPE
288 static FT_Face ft_face(const QFontEngine *engine)
289 {
290 #ifdef Q_WS_X11
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();
295     } else
296 #endif
297     if (engine->type() == QFontEngine::XLFD) {
298         const QFontEngineXLFD *xlfd = static_cast<const QFontEngineXLFD *>(engine);
299         return xlfd->non_locked_face();
300     }
301 #endif
302 #ifdef Q_WS_QWS
303     if (engine->type() == QFontEngine::Freetype) {
304         const QFontEngineFT *ft = static_cast<const QFontEngineFT *>(engine);
305         return ft->non_locked_face();
306     }
307 #endif
308     return 0;
309 }
310 #endif
311
312 QByteArray QFontSubset::glyphName(unsigned int glyph, const QVector<int> reverseMap) const
313 {
314     uint glyphIndex = glyph_indices[glyph];
315
316     if (glyphIndex == 0)
317         return "/.notdef";
318
319     QByteArray ba;
320     QPdf::ByteStream s(&ba);
321 #ifndef QT_NO_FREETYPE
322     FT_Face face = ft_face(fontEngine);
323
324     char name[32];
325     name[0] = 0;
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);
330 #endif
331         FT_Get_Glyph_Name(face, glyphIndex, &name, 32);
332         if (name[0] == '.') // fix broken PS fonts returning .notdef for many glyphs
333             name[0] = 0;
334     }
335     if (name[0]) {
336         s << '/' << name;
337     } else
338 #endif
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 /* ### */);
343     } else
344 #endif
345     if (reverseMap[glyphIndex] && reverseMap[glyphIndex] < 0x10000) {
346         s << '/' << glyphName(reverseMap[glyphIndex], false);
347     } else {
348         s << "/gl" << (int)glyphIndex;
349     }
350     return ba;
351 }
352
353
354 QByteArray QFontSubset::widthArray() const
355 {
356     Q_ASSERT(!widths.isEmpty());
357
358     QFontEngine::Properties properties = fontEngine->properties();
359
360     QByteArray width;
361     QPdf::ByteStream s(&width);
362     QFixed scale = QFixed(1000)/emSquare;
363
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])
368             defWidth = 0;
369     }
370     if (defWidth > 0) {
371         s << "/DW " << (defWidth*scale).toInt();
372     } else {
373         s << "/W [";
374         for (int g = 0; g < nGlyphs();) {
375             QFixed w = widths[g];
376             int start = g;
377             int startLinear = 0;
378             ++g;
379             while (g < nGlyphs()) {
380                 QFixed nw = widths[g];
381                 if (nw == w) {
382                 if (!startLinear)
383                     startLinear = g - 1;
384                 } else {
385                     if (startLinear > 0 && g - startLinear >= 10)
386                         break;
387                     startLinear = 0;
388                 }
389                 w = nw;
390                 ++g;
391             }
392             // qDebug("start=%x startLinear=%x g-1=%x",start,startLinear,g-1);
393             if (g - startLinear < 10)
394                 startLinear = 0;
395             int endnonlinear = startLinear ? startLinear : g;
396             // qDebug("    startLinear=%x endnonlinear=%x", startLinear,endnonlinear);
397             if (endnonlinear > start) {
398                 s << start << '[';
399                 for (int i = start; i < endnonlinear; ++i)
400                     s << (widths[i]*scale).toInt();
401                 s << "]\n";
402             }
403             if (startLinear)
404                 s << startLinear << g - 1 << (widths[startLinear]*scale).toInt() << '\n';
405         }
406         s << "]\n";
407     }
408     return width;
409 }
410
411 static void checkRanges(QPdf::ByteStream &ts, QByteArray &ranges, int &nranges)
412 {
413     if (++nranges > 100) {
414         ts << nranges << "beginbfrange\n"
415            << ranges << "endbfrange\n";
416         ranges = QByteArray();
417         nranges = 0;
418     }
419 }
420
421 QVector<int> QFontSubset::getReverseMap() const
422 {
423     QVector<int> reverseMap;
424     reverseMap.resize(0x10000);
425     for (uint i = 0; i < 0x10000; ++i)
426         reverseMap[i] = 0;
427     QGlyphLayoutArray<10> glyphs;
428     for (uint uc = 0; uc < 0x10000; ++uc) {
429         QChar ch(uc);
430         int nglyphs = 10;
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;
435     }
436     return reverseMap;
437 }
438
439 QByteArray QFontSubset::createToUnicodeMap() const
440 {
441     QVector<int> reverseMap = getReverseMap();
442
443     QByteArray touc;
444     QPdf::ByteStream ts(&touc);
445     ts << "/CIDInit /ProcSet findresource begin\n"
446         "12 dict begin\n"
447         "begincmap\n"
448         "/CIDSystemInfo << /Registry (Adobe) /Ordering (UCS) /Supplement 0 >> def\n"
449         "/CMapName /Adobe-Identity-UCS def\n"
450         "/CMapType 2 def\n"
451         "1 begincodespacerange\n"
452         "<0000> <FFFF>\n"
453         "endcodespacerange\n";
454
455     int nranges = 1;
456     QByteArray ranges = "<0000> <0000> <0000>\n";
457     QPdf::ByteStream s(&ranges);
458
459     char buf[5];
460     for (int g = 1; g < nGlyphs(); ) {
461         int uc0 = reverseMap.at(g);
462         if (!uc0) {
463             ++g;
464             continue;
465         }
466         int start = g;
467         int startLinear = 0;
468         ++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))
473                 break;
474             if (uc == uc0 + 1) {
475                 if (!startLinear)
476                     startLinear = g - 1;
477             } else {
478                 if (startLinear > 0 && g - startLinear >= 10)
479                     break;
480                 startLinear = 0;
481             }
482             uc0 = uc;
483             ++g;
484         }
485         // qDebug("start=%x startLinear=%x g-1=%x",start,startLinear,g-1);
486         if (g - startLinear < 10)
487             startLinear = 0;
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";
495             } else {
496                 s << '[';
497                 for (int i = start; i < endnonlinear; ++i) {
498                     s << '<' << QPdf::toHex((ushort)reverseMap[i], buf) << "> ";
499                 }
500                 s << "]\n";
501             }
502             checkRanges(ts, ranges, nranges);
503         }
504         if (startLinear) {
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);
515                 startLinear += len;
516             }
517         }
518     }
519     if (nranges) {
520         ts << nranges << "beginbfrange\n"
521            << ranges << "endbfrange\n";
522     }
523     ts << "endcmap\n"
524         "CMapName currentdict /CMap defineresource pop\n"
525         "end\n"
526         "end\n";
527
528     return touc;
529 }
530
531 int QFontSubset::addGlyph(int index)
532 {
533     int idx = glyph_indices.indexOf(index);
534     if (idx < 0) {
535         idx = glyph_indices.size();
536         glyph_indices.append(index);
537     }
538     return idx;
539 }
540
541
542 // ------------------------------ Truetype generation ----------------------------------------------
543
544 typedef qint16 F2DOT14;
545 typedef quint32 Tag;
546 typedef quint16 GlyphID;
547 typedef quint16 Offset;
548
549
550 class QTtfStream {
551 public:
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; }
560
561     int offset() const { return data - start; }
562     void setOffset(int o) { data = start + o; }
563     void align4() { while (offset() & 3) { *data = '\0'; ++data; } }
564 private:
565     uchar *data;
566     uchar *start;
567 };
568
569 struct QTtfTable {
570     Tag tag;
571     QByteArray data;
572 };
573 Q_DECLARE_TYPEINFO(QTtfTable, Q_MOVABLE_TYPE);
574
575
576 struct qttf_head_table {
577     qint32 font_revision;
578     quint16 flags;
579     qint64 created;
580     qint64 modified;
581     qint16 xMin;
582     qint16 yMin;
583     qint16 xMax;
584     qint16 yMax;
585     quint16 macStyle;
586     qint16 indexToLocFormat;
587 };
588
589
590 struct qttf_hhea_table {
591     qint16 ascender;
592     qint16 descender;
593     qint16 lineGap;
594     quint16 maxAdvanceWidth;
595     qint16 minLeftSideBearing;
596     qint16 minRightSideBearing;
597     qint16 xMaxExtent;
598     quint16 numberOfHMetrics;
599 };
600
601
602 struct qttf_maxp_table {
603     quint16 numGlyphs;
604     quint16 maxPoints;
605     quint16 maxContours;
606     quint16 maxCompositePoints;
607     quint16 maxCompositeContours;
608     quint16 maxComponentElements;
609     quint16 maxComponentDepth;
610 };
611
612 struct qttf_name_table {
613     QString copyright;
614     QString family;
615     QString subfamily;
616     QString postscript_name;
617 };
618
619
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);
624
625 struct qttf_font_tables
626 {
627     qttf_head_table head;
628     qttf_hhea_table hhea;
629     qttf_maxp_table maxp;
630 };
631
632
633 struct QTtfGlyph {
634     quint16 index;
635     qint16 xMin;
636     qint16 xMax;
637     qint16 yMin;
638     qint16 yMax;
639     quint16 advanceWidth;
640     qint16 lsb;
641     quint16 numContours;
642     quint16 numPoints;
643     QByteArray data;
644 };
645 Q_DECLARE_TYPEINFO(QTtfGlyph, Q_MOVABLE_TYPE);
646
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);
650
651 static QByteArray bindFont(const QList<QTtfTable>& _tables);
652
653
654 static quint32 checksum(const QByteArray &table)
655 {
656     quint32 sum = 0;
657     int offset = 0;
658     const uchar *d = (uchar *)table.constData();
659     while (offset <= table.size()-3) {
660         sum += qFromBigEndian<quint32>(d + offset);
661         offset += 4;
662     }
663     int shift = 24;
664     quint32 x = 0;
665     while (offset < table.size()) {
666         x |= ((quint32)d[offset]) << shift;
667         ++offset;
668         shift -= 8;
669     }
670     sum += x;
671
672     return sum;
673 }
674
675 static QTtfTable generateHead(const qttf_head_table &head)
676 {
677     const int head_size = 54;
678     QTtfTable t;
679     t.tag = MAKE_TAG('h', 'e', 'a', 'd');
680     t.data.resize(head_size);
681
682     QTtfStream s(t.data);
683
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.
689       << quint32(0)
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
703       << quint16(0)
704
705 // quint16  unitsPerEm  Valid range is from 16 to 16384. This value should be a power of 2 for fonts that have TrueType outlines.
706       << quint16(2048)
707 // qint64  created  Number of seconds since 12:00 midnight, January 1, 1904. 64-bit integer
708       << head.created
709 // qint64  modified  Number of seconds since 12:00 midnight, January 1, 1904. 64-bit integer
710       << head.modified
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.
715       << head.xMin
716       << head.yMin
717       << head.xMax
718       << head.yMax
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).
727       << head.macStyle
728 // quint16  lowestRecPPEM  Smallest readable size in pixels.
729       << quint16(6) // just a wild guess
730 // qint16  fontDirectionHint   0: Fully mixed directional glyphs;
731       << qint16(0)
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.
739       << qint16(0);
740
741     Q_ASSERT(s.offset() == head_size);
742     return t;
743 }
744
745
746 static QTtfTable generateHhea(const qttf_hhea_table &hhea)
747 {
748     const int hhea_size = 36;
749     QTtfTable t;
750     t.tag = MAKE_TAG('h', 'h', 'e', 'a');
751     t.data.resize(hhea_size);
752
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)
757       << hhea.ascender
758 // qint16  Descender  Typographic descent.  (Distance from baseline of lowest descender)
759       << hhea.descender
760 // qint16  LineGap  Typographic line gap.
761 // Negative LineGap values are treated as zero
762 // in Windows 3.1, System 6, and
763 // System 7.
764       << hhea.lineGap
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)).
772       << hhea.xMaxExtent
773 // qint16  caretSlopeRise  Used to calculate the slope of the cursor (rise/run); 1 for vertical.
774       << qint16(1)
775 // qint16  caretSlopeRun  0 for vertical.
776       << qint16(0)
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
778       << qint16(0)
779 // qint16  (reserved)  set to 0
780       << qint16(0)
781 // qint16  (reserved)  set to 0
782       << qint16(0)
783 // qint16  (reserved)  set to 0
784       << qint16(0)
785 // qint16  (reserved)  set to 0
786       << qint16(0)
787 // qint16  metricDataFormat  0 for current format.
788       << qint16(0)
789 // quint16  numberOfHMetrics  Number of hMetric entries in 'hmtx' table
790       << hhea.numberOfHMetrics;
791
792     Q_ASSERT(s.offset() == hhea_size);
793     return t;
794 }
795
796
797 static QTtfTable generateMaxp(const qttf_maxp_table &maxp)
798 {
799     const int maxp_size = 32;
800     QTtfTable t;
801     t.tag = MAKE_TAG('m', 'a', 'x', 'p');
802     t.data.resize(maxp_size);
803
804     QTtfStream s(t.data);
805
806 // qint32  Table version number  0x00010000 for version 1.0.
807     s << qint32(0x00010000)
808 // quint16  numGlyphs  The number of glyphs in the font.
809       << maxp.numGlyphs
810 // quint16  maxPoints  Maximum points in a non-composite glyph.
811       << maxp.maxPoints
812 // quint16  maxContours  Maximum contours in a non-composite glyph.
813       << maxp.maxContours
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.
821       << quint16(0)
822 // quint16  maxStorage  Number of Storage Area locations.
823       << quint16(0)
824 // quint16  maxFunctionDefs  Number of FDEFs.
825       << quint16(0)
826 // quint16  maxInstructionDefs  Number of IDEFs.
827       << quint16(0)
828 // quint16  maxStackElements  Maximum stack depth2.
829       << quint16(0)
830 // quint16  maxSizeOfInstructions  Maximum byte count for glyph instructions.
831       << quint16(0)
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;
836
837     Q_ASSERT(s.offset() == maxp_size);
838     return t;
839 }
840
841 struct QTtfNameRecord {
842     quint16 nameId;
843     QString value;
844 };
845
846 static QTtfTable generateName(const QList<QTtfNameRecord> &name);
847
848 static QTtfTable generateName(const qttf_name_table &name)
849 {
850     QList<QTtfNameRecord> list;
851     QTtfNameRecord rec;
852     rec.nameId = 0;
853     rec.value = name.copyright;
854     list.append(rec);
855     rec.nameId = 1;
856     rec.value = name.family;
857     list.append(rec);
858     rec.nameId = 2;
859     rec.value = name.subfamily;
860     list.append(rec);
861     rec.nameId = 4;
862     rec.value = name.family;
863     if (name.subfamily != QLatin1String("Regular"))
864         rec.value += QLatin1Char(' ') + name.subfamily;
865     list.append(rec);
866     rec.nameId = 6;
867     rec.value = name.postscript_name;
868     list.append(rec);
869
870     return generateName(list);
871 }
872
873 // ####### should probably generate Macintosh/Roman name entries as well
874 static QTtfTable generateName(const QList<QTtfNameRecord> &name)
875 {
876     const int char_size = 2;
877
878     QTtfTable t;
879     t.tag = MAKE_TAG('n', 'a', 'm', 'e');
880
881     const int name_size = 6 + 12*name.size();
882     int string_size = 0;
883     for (int i = 0; i < name.size(); ++i) {
884         string_size += name.at(i).value.length()*char_size;
885     }
886     t.data.resize(name_size + string_size);
887
888     QTtfStream s(t.data);
889 // quint16  format  Format selector (=0).
890     s << quint16(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.
896 // (Variable)
897
898     int off = 0;
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.
904         s << quint16(3)
905           << quint16(1)
906           << quint16(0x0409) // en_US
907 // quint16  nameId  Name ID.
908           << name.at(i).nameId
909 // quint16  length  String length (in bytes).
910           << quint16(len)
911 // quint16  offset  String offset from start of storage area (in bytes).
912           << quint16(off);
913         off += len;
914     }
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) {
919             s << quint16(*uc);
920             ++uc;
921         }
922     }
923     return t;
924 }
925
926
927 enum Flags {
928     OffCurve = 0,
929     OnCurve = (1 << 0),
930     XShortVector = (1 << 1),
931     YShortVector = (1 << 2),
932     Repeat = (1 << 3),
933     XSame = (1 << 4),
934     XShortPositive = (1 << 4),
935     YSame = (1 << 5),
936     YShortPositive = (1 << 5)
937 };
938 struct TTF_POINT {
939     qint16 x;
940     qint16 y;
941     quint8 flags;
942 };
943 Q_DECLARE_TYPEINFO(TTF_POINT, Q_PRIMITIVE_TYPE);
944
945 static void convertPath(const QPainterPath &path, QList<TTF_POINT> *points, QList<int> *endPoints, qreal ppem)
946 {
947     int numElements = path.elementCount();
948     for (int i = 0; i < numElements - 1; ++i) {
949         const QPainterPath::Element &e = path.elementAt(i);
950         TTF_POINT p;
951         p.x = qRound(e.x * 2048. / ppem);
952         p.y = qRound(-e.y * 2048. / ppem);
953         p.flags = 0;
954
955         switch(e.type) {
956         case QPainterPath::MoveToElement:
957             if (i != 0) {
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)
963                     points->takeLast();
964                 endPoints->append(points->size() - 1);
965             }
966             // fall through
967         case QPainterPath::LineToElement:
968             p.flags = OnCurve;
969             break;
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);
974             list[2] = p;
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);
981
982             TTF_POINT *base = list;
983
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;
990 //                 {
991 //                     qDebug("iteration:");
992 //                     TTF_POINT *x = list;
993 //                     while (x <= base + 3) {
994 //                         qDebug() << "    " << QPoint(x->x, x->y);
995 //                         ++x;
996 //                     }
997 //                 }
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
1007                     TTF_POINT np;
1008                     np.x = (i1_x + i2_x) >> 1;
1009                     np.y = (i1_y + i2_y) >> 1;
1010                     if (try_reduce) {
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)
1015                             points->takeLast();
1016                         try_reduce = false;
1017                     }
1018                     np.flags = OffCurve;
1019                     points->append(np);
1020 //                     qDebug() << "   appending offcurve point " << QPoint(np.x, np.y);
1021                     base -= 3;
1022                 } else {
1023                     // need to split
1024 //                     qDebug() << "  -> splitting";
1025                     qint16 a, b, c, d;
1026                     base[6].x = base[3].x;
1027                     c = base[1].x;
1028                     d = base[2].x;
1029                     base[1].x = a = ( base[0].x + c ) >> 1;
1030                     base[5].x = b = ( base[3].x + d ) >> 1;
1031                     c = ( c + 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;
1035
1036                     base[6].y = base[3].y;
1037                     c = base[1].y;
1038                     d = base[2].y;
1039                     base[1].y = a = ( base[0].y + c ) >> 1;
1040                     base[5].y = b = ( base[3].y + d ) >> 1;
1041                     c = ( c + 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;
1045                     base += 3;
1046                 }
1047             }
1048             p = list[0];
1049             p.flags = OnCurve;
1050             break;
1051         }
1052         case QPainterPath::CurveToDataElement:
1053             Q_ASSERT(false);
1054             break;
1055         }
1056 //         qDebug() << "   appending oncurve point " << QPoint(p.x, p.y);
1057         points->append(p);
1058     }
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)
1063         points->takeLast();
1064     endPoints->append(points->size() - 1);
1065 }
1066
1067 static void getBounds(const QList<TTF_POINT> &points, qint16 *xmin, qint16 *xmax, qint16 *ymin, qint16 *ymax)
1068 {
1069     *xmin = points.at(0).x;
1070     *xmax = *xmin;
1071     *ymin = points.at(0).y;
1072     *ymax = *ymin;
1073
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);
1079     }
1080 }
1081
1082 static int convertToRelative(QList<TTF_POINT> *points)
1083 {
1084     // convert points to relative and setup flags
1085 //     qDebug() << "relative points:";
1086     qint16 prev_x = 0;
1087     qint16 prev_y = 0;
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;
1092         TTF_POINT rel;
1093         rel.x = x - prev_x;
1094         rel.y = y - prev_y;
1095         rel.flags = points->at(i).flags;
1096         Q_ASSERT(rel.flags < 2);
1097         if (!rel.x) {
1098             rel.flags |= XSame;
1099         } else if (rel.x > 0 && rel.x < 256) {
1100             rel.flags |= XShortVector|XShortPositive;
1101             point_array_size++;
1102         } else if (rel.x < 0 && rel.x > -256) {
1103             rel.flags |= XShortVector;
1104             rel.x = -rel.x;
1105             point_array_size++;
1106         } else {
1107             point_array_size += 2;
1108         }
1109         if (!rel.y) {
1110             rel.flags |= YSame;
1111         } else if (rel.y > 0 && rel.y < 256) {
1112             rel.flags |= YShortVector|YShortPositive;
1113             point_array_size++;
1114         } else if (rel.y < 0 && rel.y > -256) {
1115             rel.flags |= YShortVector;
1116             rel.y = -rel.y;
1117             point_array_size++;
1118         } else {
1119             point_array_size += 2;
1120         }
1121         (*points)[i] = rel;
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));
1128
1129         prev_x = x;
1130         prev_y = y;
1131     }
1132     return point_array_size;
1133 }
1134
1135 static void getGlyphData(QTtfGlyph *glyph, const QList<TTF_POINT> &points, const QList<int> &endPoints, int point_array_size)
1136 {
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
1142
1143     glyph->data.resize(max_size);
1144
1145     QTtfStream s(glyph->data);
1146     s << qint16(endPoints.size())
1147       << glyph->xMin << glyph->yMin << glyph->xMax << glyph->yMax;
1148
1149     for (int i = 0; i < endPoints.size(); ++i)
1150         s << quint16(endPoints.at(i));
1151     s << quint16(0); // instruction length
1152
1153     // emit flags
1154     for (int i = 0; i < points.size(); ++i)
1155         s << quint8(points.at(i).flags);
1156     // emit points
1157     for (int i = 0; i < points.size(); ++i) {
1158         quint8 flags = points.at(i).flags;
1159         qint16 x = points.at(i).x;
1160
1161         if (flags & XShortVector)
1162             s << quint8(x);
1163         else if (!(flags & XSame))
1164             s << qint16(x);
1165     }
1166     for (int i = 0; i < points.size(); ++i) {
1167         quint8 flags = points.at(i).flags;
1168         qint16 y = points.at(i).y;
1169
1170         if (flags & YShortVector)
1171             s << quint8(y);
1172         else if (!(flags & YSame))
1173             s << qint16(y);
1174     }
1175
1176 //     qDebug() << "offset=" << s.offset() << "max_size=" << max_size << "point_array_size=" << point_array_size;
1177     Q_ASSERT(s.offset() == max_size);
1178
1179     glyph->numContours = endPoints.size();
1180     glyph->numPoints = points.size();
1181 }
1182
1183 static QTtfGlyph generateGlyph(int index, const QPainterPath &path, qreal advance, qreal lsb, qreal ppem)
1184 {
1185     QList<TTF_POINT> points;
1186     QList<int> endPoints;
1187     QTtfGlyph glyph;
1188     glyph.index = index;
1189     glyph.advanceWidth = qRound(advance * 2048. / ppem);
1190     glyph.lsb = qRound(lsb * 2048. / ppem);
1191
1192     if (!path.elementCount()) {
1193         //qDebug("glyph %d is empty", index);
1194         lsb = 0;
1195         glyph.xMin = glyph.xMax = glyph.yMin = glyph.yMax = 0;
1196         glyph.numContours = 0;
1197         glyph.numPoints = 0;
1198         return glyph;
1199     }
1200
1201     convertPath(path, &points, &endPoints, ppem);
1202
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);
1209
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);
1213     return glyph;
1214 }
1215
1216 Q_STATIC_GLOBAL_OPERATOR bool operator <(const QTtfGlyph &g1, const QTtfGlyph &g2)
1217 {
1218     return g1.index < g2.index;
1219 }
1220
1221 static QList<QTtfTable> generateGlyphTables(qttf_font_tables &tables, const QList<QTtfGlyph> &_glyphs)
1222 {
1223     const int max_size_small = 65536*2;
1224     QList<QTtfGlyph> glyphs = _glyphs;
1225     qSort(glyphs);
1226
1227     Q_ASSERT(tables.maxp.numGlyphs == glyphs.at(glyphs.size()-1).index + 1);
1228     int nGlyphs = tables.maxp.numGlyphs;
1229
1230     int glyf_size = 0;
1231     for (int i = 0; i < glyphs.size(); ++i)
1232         glyf_size += (glyphs.at(i).data.size() + 3) & ~3;
1233
1234     tables.head.indexToLocFormat = glyf_size < max_size_small ? 0 : 1;
1235     tables.hhea.numberOfHMetrics = nGlyphs;
1236
1237     QTtfTable glyf;
1238     glyf.tag = MAKE_TAG('g', 'l', 'y', 'f');
1239
1240     QTtfTable loca;
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);
1244
1245     QTtfTable hmtx;
1246     hmtx.tag = MAKE_TAG('h', 'm', 't', 'x');
1247     hmtx.data.resize(nGlyphs*4);
1248     QTtfStream hs(hmtx.data);
1249
1250     int pos = 0;
1251     for (int i = 0; i < nGlyphs; ++i) {
1252         int gpos = glyf.data.size();
1253         quint16 advance = 0;
1254         qint16 lsb = 0;
1255
1256         if (glyphs[pos].index == i) {
1257             // emit glyph
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;
1264             ++pos;
1265         }
1266         if (glyf_size < max_size_small) {
1267             // use short loca format
1268             ls << quint16(gpos>>1);
1269         } else {
1270             // use long loca format
1271             ls << quint32(gpos);
1272         }
1273         hs << advance
1274            << lsb;
1275     }
1276     if (glyf_size < max_size_small) {
1277         // use short loca format
1278         ls << quint16(glyf.data.size()>>1);
1279     } else {
1280         // use long loca format
1281         ls << quint32(glyf.data.size());
1282     }
1283
1284     Q_ASSERT(loca.data.size() == ls.offset());
1285     Q_ASSERT(hmtx.data.size() == hs.offset());
1286
1287     QList<QTtfTable> list;
1288     list.append(glyf);
1289     list.append(loca);
1290     list.append(hmtx);
1291     return list;
1292 }
1293
1294 Q_STATIC_GLOBAL_OPERATOR bool operator <(const QTtfTable &t1, const QTtfTable &t2)
1295 {
1296     return t1.tag < t2.tag;
1297 }
1298
1299 static QByteArray bindFont(const QList<QTtfTable>& _tables)
1300 {
1301     QList<QTtfTable> tables = _tables;
1302
1303     qSort(tables);
1304
1305     QByteArray font;
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);
1309
1310     int log2 = 0;
1311     int pow = 1;
1312     int n = tables.size() >> 1;
1313     while (n) {
1314         ++log2;
1315         pow <<= 1;
1316         n >>= 1;
1317     }
1318
1319     quint32 head_offset = 0;
1320     {
1321         QTtfStream f(font);
1322 // Offset Table
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())
1331           << quint16(16*pow)
1332           << quint16(log2)
1333           << quint16(16*(tables.size() - pow));
1334
1335 // Table Directory
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;
1347             f << t.tag
1348               << checksum(t.data)
1349               << table_offset
1350               << t.data.size();
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();
1354         }
1355     }
1356     for (int i = 0; i < tables.size(); ++i) {
1357         const QByteArray &t = tables.at(i).data;
1358         font += t;
1359         int s = t.size();
1360         while (s & 3) { font += '\0'; ++s; }
1361     }
1362
1363     if (!head_offset) {
1364         qWarning("QFontSubset: Font misses 'head' table");
1365         return QByteArray();
1366     }
1367
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);
1371
1372     return font;
1373 }
1374
1375
1376 /*
1377   PDF requires the following tables:
1378
1379   head, hhea, loca, maxp, cvt , prep, glyf, hmtx, fpgm
1380
1381   This means we don't have to add a os/2, post or name table. cvt , prep and fpgm could be empty
1382   if really required.
1383 */
1384
1385 QByteArray QFontSubset::toTruetype() const
1386 {
1387     qttf_font_tables font;
1388     memset(&font, 0, sizeof(qttf_font_tables));
1389
1390     qreal ppem = fontEngine->fontDef.pixelSize;
1391 #define TO_TTF(x) qRound(x * 2048. / ppem)
1392     QList<QTtfGlyph> glyphs;
1393
1394     QFontEngine::Properties properties = fontEngine->properties();
1395     // initialize some stuff needed in createWidthArray
1396     emSquare = 2048;
1397     widths.resize(nGlyphs());
1398
1399     // head table
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;
1410
1411     // hhea table
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;
1419
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();
1428
1429
1430
1431     uint sumAdvances = 0;
1432     for (int i = 0; i < nGlyphs(); ++i) {
1433         glyph_t g = glyph_indices.at(i);
1434         QPainterPath path;
1435         glyph_metrics_t metric;
1436         fontEngine->getUnscaledGlyph(g, &path, &metric);
1437         if (noEmbed) {
1438             path = QPainterPath();
1439             if (g == 0)
1440                 path.addRect(QRectF(0, 0, 1000, 1000));
1441         }
1442         QTtfGlyph glyph = generateGlyph(i, path, metric.xoff.toReal(), metric.x.toReal(), properties.emSquare.toReal());
1443
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);
1448
1449         font.hhea.xMaxExtent = qMax(font.hhea.xMaxExtent, (qint16)(glyph.lsb + glyph.xMax - glyph.xMin));
1450
1451         font.maxp.maxPoints = qMax(font.maxp.maxPoints, glyph.numPoints);
1452         font.maxp.maxContours = qMax(font.maxp.maxContours, glyph.numContours);
1453
1454         if (glyph.xMax > glyph.xMin)
1455             sumAdvances += glyph.xMax - glyph.xMin;
1456
1457 //         qDebug("adding glyph %d size=%d", glyph.index, glyph.data.size());
1458         glyphs.append(glyph);
1459         widths[i] = glyph.advanceWidth;
1460     }
1461
1462
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));
1467     // name
1468     QTtfTable name_table;
1469     name_table.tag = MAKE_TAG('n', 'a', 'm', 'e');
1470     if (!noEmbed)
1471         name_table.data = fontEngine->getSfntTable(name_table.tag);
1472     if (name_table.data.isEmpty()) {
1473         qttf_name_table name;
1474         if (noEmbed)
1475             name.copyright = QLatin1String("Fake font");
1476         else
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);
1482     }
1483     tables.append(name_table);
1484
1485     if (!noEmbed) {
1486         QTtfTable os2;
1487         os2.tag = MAKE_TAG('O', 'S', '/', '2');
1488         os2.data = fontEngine->getSfntTable(os2.tag);
1489         if (!os2.data.isEmpty())
1490             tables.append(os2);
1491     }
1492
1493     return bindFont(tables);
1494 }
1495
1496 // ------------------ Type 1 generation ---------------------------
1497
1498 // needs at least 6 bytes of space in tmp
1499 static const char *encodeNumber(int num, char *tmp)
1500 {
1501     const char *ret = tmp;
1502     if(num >= -107 && num <= 107) {
1503         QPdf::toHex((uchar)(num + 139), tmp);
1504         tmp += 2;
1505     } else if (num > 107 && num <= 1131) {
1506         num -= 108;
1507         QPdf::toHex((uchar)((num >> 8) + 247), tmp);
1508         tmp += 2;
1509         QPdf::toHex((uchar)(num & 0xff), tmp);
1510         tmp += 2;
1511     } else if(num < - 107 && num >= -1131) {
1512         num += 108;
1513         num = -num;
1514         QPdf::toHex((uchar)((num >> 8) + 251), tmp);
1515         tmp += 2;
1516         QPdf::toHex((uchar)(num & 0xff), tmp);
1517         tmp += 2;
1518     } else {
1519         *tmp++ = 'f';
1520         *tmp++ = 'f';
1521         QPdf::toHex((uchar)(num >> 24), tmp);
1522         tmp += 2;
1523         QPdf::toHex((uchar)(num >> 16), tmp);
1524         tmp += 2;
1525         QPdf::toHex((uchar)(num >> 8), tmp);
1526         tmp += 2;
1527         QPdf::toHex((uchar)(num >> 0), tmp);
1528         tmp += 2;
1529     }
1530     *tmp = 0;
1531 //     qDebug("encodeNumber: %d -> '%s'", num, ret);
1532     return ret;
1533 }
1534
1535 static QByteArray charString(const QPainterPath &path, qreal advance, qreal lsb, qreal ppem)
1536 {
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";
1544
1545     enum { horizontal = 1,  vertical = 2 };
1546
1547     char tmp[16];
1548
1549     qreal factor = 1000./ppem;
1550
1551     int lsb_i = qRound(lsb*factor);
1552     int advance_i = qRound(advance*factor);
1553 //     qDebug("--- charstring");
1554
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);
1559     charstring += hsbw;
1560
1561     // add the path
1562     int xl = lsb_i;
1563     int yl = 0;
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);
1569         int dx = x - xl;
1570         int dy = y - yl;
1571         if (elm.type == QPainterPath::MoveToElement && openpath) {
1572 //             qDebug("closepath %s", closepath);
1573             charstring += closepath;
1574         }
1575         if (elm.type == QPainterPath::MoveToElement ||
1576             elm.type == QPainterPath::LineToElement) {
1577             int type = -1;
1578             if (dx || !dy) {
1579                 charstring += encodeNumber(dx, tmp);
1580                 type += horizontal;
1581 //                 qDebug("horizontal");
1582             }
1583             if (dy) {
1584                 charstring += encodeNumber(dy, tmp);
1585                 type += vertical;
1586 //                 qDebug("vertical");
1587             }
1588 //             qDebug("moveto/lineto %s", (elm.type == QPainterPath::MoveToElement ? moveto[type] : lineto[type]));
1589             charstring += (elm.type == QPainterPath::MoveToElement ? moveto[type] : lineto[type]);
1590             openpath = true;
1591             xl = x;
1592             yl = y;
1593         } else {
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;
1608             openpath = true;
1609             xl = x3;
1610             yl = y3;
1611 //             qDebug("rcurveto");
1612         }
1613     }
1614     if (openpath)
1615         charstring += closepath;
1616     charstring += endchar;
1617     if (charstring.length() > 240) {
1618         int pos = 240;
1619         while (pos < charstring.length()) {
1620             charstring.insert(pos, '\n');
1621             pos += 241;
1622         }
1623     }
1624     return charstring;
1625 }
1626
1627 #ifndef QT_NO_FREETYPE
1628 static const char *helvetica_styles[4] = {
1629     "Helvetica",
1630     "Helvetica-Bold",
1631     "Helvetica-Oblique",
1632     "Helvetica-BoldOblique"
1633 };
1634 static const char *times_styles[4] = {
1635     "Times-Regular",
1636     "Times-Bold",
1637     "Times-Italic",
1638     "Times-BoldItalic"
1639 };
1640 static const char *courier_styles[4] = {
1641     "Courier",
1642     "Courier-Bold",
1643     "Courier-Oblique",
1644     "Courier-BoldOblique"
1645 };
1646 #endif
1647
1648 QByteArray QFontSubset::toType1() const
1649 {
1650     QFontEngine::Properties properties = fontEngine->properties();
1651     QVector<int> reverseMap = getReverseMap();
1652
1653     QByteArray font;
1654     QPdf::ByteStream s(&font);
1655
1656     QByteArray id = QByteArray::number(object_id);
1657     QByteArray psname = properties.postscriptName;
1658     psname.replace(' ', "");
1659
1660     standard_font = false;
1661
1662 #ifndef QT_NO_FREETYPE
1663     FT_Face face = ft_face(fontEngine);
1664     if (face && !FT_IS_SCALABLE(face)) {
1665         int style = 0;
1666         if (fontEngine->fontDef.style)
1667             style += 2;
1668         if (fontEngine->fontDef.weight >= QFont::Bold)
1669             style++;
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;
1679         }
1680     }
1681 #endif
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";
1686     } else {
1687         s << "<<\n";
1688         if(!psname.isEmpty())
1689             s << "/FontName /" << psname << '\n';
1690         s << "/FontInfo <</FsType " << (int)fontEngine->fsType << ">>\n"
1691             "/FontType 1\n"
1692             "/PaintType 0\n"
1693             "/FontMatrix [.001 0 0 .001 0 0]\n"
1694             "/FontBBox { 0 0 0 0 }\n"
1695             "/Private <<\n"
1696             "/password 5839\n"
1697             "/MinFeature {16 16}\n"
1698             "/BlueValues []\n"
1699             "/lenIV -1\n"
1700             ">>\n"
1701             "/CharStrings << >>\n"
1702             "/NumGlyphs 0\n"
1703             "/CMap 256 array\n"
1704             ">> def\n";
1705     }
1706     s << type1AddedGlyphs();
1707     downloaded_glyphs = glyph_indices.size();
1708
1709     return font;
1710 }
1711
1712 QByteArray QFontSubset::type1AddedGlyphs() const
1713 {
1714     if (downloaded_glyphs == glyph_indices.size())
1715         return QByteArray();
1716
1717     QFontEngine::Properties properties = fontEngine->properties();
1718     QVector<int> reverseMap = getReverseMap();
1719     QByteArray glyphs;
1720     QPdf::ByteStream s(&glyphs);
1721
1722     int nGlyphs = glyph_indices.size();
1723     QByteArray id = QByteArray::number(object_id);
1724
1725     s << 'F' << id << "-Base [\n";
1726     for (int i = downloaded_glyphs; i < nGlyphs; ++i) {
1727         glyph_t g = glyph_indices.at(i);
1728         QPainterPath path;
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);
1734         if (!standard_font)
1735           s << "\n<" << charstring << ">\n";
1736     }
1737     s << (standard_font ? "] T1AddMapping\n" : "] T1AddGlyphs\n");
1738     return glyphs;
1739 }
1740
1741 QT_END_NAMESPACE
1742
1743 #endif // QT_NO_PRINTER