Qt 4.8
qfontsubset.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
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 
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)
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 
355 {
356  Q_ASSERT(!widths.isEmpty());
357 
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 
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 
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 
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:
567 };
568 
569 struct QTtfTable {
572 };
574 
575 
587 };
588 
589 
599 };
600 
601 
610 };
611 
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);
624 
626 {
630 };
631 
632 
633 struct QTtfGlyph {
644 };
646 
647 static QTtfGlyph generateGlyph(int index, const QPainterPath &path, qreal advance, qreal lsb, qreal ppem);
648 // generates glyf, loca and hmtx
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 
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 
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 
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 
844 };
845 
847 
849 {
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
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 {
942 };
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) {
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
968  p.flags = OnCurve;
969  break;
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  }
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 
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) {
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) {
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 
1217 {
1218  return g1.index < g2.index;
1219 }
1220 
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 
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 
1386 {
1387  qttf_font_tables font;
1388  memset(&font, 0, sizeof(qttf_font_tables));
1389 
1391 #define TO_TTF(x) qRound(x * 2048. / ppem)
1392  QList<QTtfGlyph> glyphs;
1393 
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;
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);
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()) {
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 ||
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 {
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 
1649 {
1651  QVector<int> reverseMap = getReverseMap();
1652 
1653  QByteArray font;
1654  QPdf::ByteStream s(&font);
1655 
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;
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();
1708 
1709  return font;
1710 }
1711 
1713 {
1715  return QByteArray();
1716 
1718  QVector<int> reverseMap = getReverseMap();
1719  QByteArray glyphs;
1720  QPdf::ByteStream s(&glyphs);
1721 
1722  int nGlyphs = glyph_indices.size();
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 
1742 
1743 #endif // QT_NO_PRINTER
ElementType type
the type of element
Definition: qpainterpath.h:81
qint16 xMin
Tag
Definition: qtranslator.cpp:86
QBool contains(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition: qstring.h:904
quint16 numPoints
double d
Definition: qnumeric_p.h:62
qttf_head_table head
The QPainterPath::Element class specifies the position and type of a subpath.
Definition: qpainterpath.h:77
virtual qreal minRightBearing() const
static void convertPath(const QPainterPath &path, QList< TTF_POINT > *points, QList< int > *endPoints, qreal ppem)
static FT_Face ft_face(const QFontEngine *engine)
static ShiftResult shift(const QBezier *orig, QBezier *shifted, qreal offset, qreal threshold)
Definition: qbezier.cpp:289
QByteArray createToUnicodeMap() const
int type
Definition: qmetatype.cpp:239
static const unsigned short symbol_map[0x100]
double qreal
Definition: qglobal.h:1193
void align4()
unsigned char c[8]
Definition: qnumeric_p.h:62
Q_DECL_CONSTEXPR const T & qMin(const T &a, const T &b)
Definition: qglobal.h:1215
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
int qint32
Definition: qglobal.h:937
char * data()
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:429
static const struct @277 unicode_to_aglindex[]
The QPainterPath class provides a container for painting operations, enabling graphical shapes to be ...
Definition: qpainterpath.h:67
QByteArray & append(char c)
Appends the character ch to this byte array.
HB_Glyph * glyphs
QVector< QFixed > widths
Definition: qfontsubset_p.h:92
QList< int > glyph_indices
Definition: qfontsubset_p.h:87
int addGlyph(int index)
QByteArray toTruetype() const
static const char * encodeNumber(int num, char *tmp)
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
static QByteArray charString(const QPainterPath &path, qreal advance, qreal lsb, qreal ppem)
int length() const
Returns the number of characters in this string.
Definition: qstring.h:696
QString postscript_name
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
quint16 u
long ASN1_INTEGER_get ASN1_INTEGER * a
quint16 numContours
qttf_hhea_table hhea
unsigned char quint8
Definition: qglobal.h:934
quint32 qFromBigEndian< quint32 >(const uchar *src)
Definition: qendian.h:239
QByteArray type1AddedGlyphs() const
qint16 yMax
QByteArray widthArray() const
qreal y
the y coordinate of the element&#39;s position.
Definition: qpainterpath.h:80
QFontEngine * fontEngine
Definition: qfontsubset_p.h:86
The QString class provides a Unicode character string.
Definition: qstring.h:83
uchar * data
uchar * start
Q_DECL_CONSTEXPR T qAbs(const T &t)
Definition: qglobal.h:1201
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
static QTtfTable generateMaxp(const qttf_maxp_table &maxp)
virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const =0
QByteArray glyphName(unsigned int glyph, const QVector< int > reverseMap) const
int downloaded_glyphs
Definition: qfontsubset_p.h:88
QTtfStream(QByteArray &ba)
static const uint base
Definition: qurl.cpp:268
virtual Type type() const =0
The QChar class provides a 16-bit Unicode character.
Definition: qchar.h:72
quint16 maxComponentDepth
const QPainterPath::Element & elementAt(int i) const
Returns the element at the given index in the painter path.
Definition: qpainterpath.h:402
qint16 xMax
Q_DECL_CONSTEXPR const T & qMax(const T &a, const T &b)
Definition: qglobal.h:1217
static void getBounds(const QList< TTF_POINT > &points, qint16 *xmin, qint16 *xmax, qint16 *ymin, qint16 *ymax)
static quint32 checksum(const QByteArray &table)
void resize(int size)
Sets the size of the vector to size.
Definition: qvector.h:342
qint16 yMin
#define MAKE_TAG(ch1, ch2, ch3, ch4)
virtual qreal maxCharWidth() const =0
for(int ii=mo->methodOffset();ii< mo->methodCount();++ii)
signed char qint8
Definition: qglobal.h:933
unsigned char uchar
Definition: qglobal.h:994
void append(const T &t)
Inserts value at the end of the list.
Definition: qlist.h:507
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
quint16 numberOfHMetrics
The QRectF class defines a rectangle in the plane using floating point precision. ...
Definition: qrect.h:511
QFixed emSquare
Definition: qfontsubset_p.h:91
struct FT_FaceRec_ * FT_Face
Definition: qfont.h:50
quint8 flags
QByteArray data
static QTtfTable generateName(const qttf_name_table &name)
static QTtfTable generateHhea(const qttf_hhea_table &hhea)
const char * name
#define Q_STATIC_GLOBAL_OPERATOR
Definition: qfunctions_p.h:71
const T & at(int i) const
Returns the item at index position i in the list.
Definition: qlist.h:468
short qint16
Definition: qglobal.h:935
static const char * courier_styles[4]
static int toInt(const QByteArray &str)
Definition: generator.cpp:167
T qToBigEndian(T source)
Definition: qendian.h:337
static QTtfTable generateHead(const qttf_head_table &head)
void setOffset(int o)
unsigned short quint16
Definition: qglobal.h:936
Q_CORE_EXPORT void qWarning(const char *,...)
static const char * data(const QByteArray &arr)
unsigned int uint
Definition: qglobal.h:996
The QLatin1String class provides a thin wrapper around an US-ASCII/Latin-1 encoded string literal...
Definition: qstring.h:654
void addRect(const QRectF &rect)
Adds the given rectangle to this path as a closed subpath.
qint16 minRightSideBearing
uint weight
Definition: qfont_p.h:95
__int64 qint64
Definition: qglobal.h:942
QByteArray toType1() const
virtual qreal minLeftBearing() const
#define TO_TTF(x)
static int convertToRelative(QList< TTF_POINT > *points)
virtual void getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics)
void qSort(RandomAccessIterator start, RandomAccessIterator end)
Definition: qalgorithms.h:177
quint16 maxAdvanceWidth
quint16 maxCompositePoints
qreal pixelSize
Definition: qfont_p.h:90
const T & at(int i) const
Returns the item at index position i in the vector.
Definition: qvector.h:350
const char * toHex(ushort u, char *buffer)
Definition: qpdf.cpp:862
qint16 F2DOT14
bool standard_font
Definition: qfontsubset_p.h:89
static QString toUnicode(QTextCodec *tc, const char *str)
Definition: qsql_mysql.cpp:95
int length() const
Same as size().
Definition: qbytearray.h:356
qint16 minLeftSideBearing
const char * constData() const
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:433
static const char * helvetica_styles[4]
quint16 GlyphID
int indexOf(const T &t, int from=0) const
Returns the index position of the first occurrence of value in the list, searching forward from index...
Definition: qlist.h:847
virtual Properties properties() const
Q_DECLARE_TYPEINFO(QTtfTable, Q_MOVABLE_TYPE)
quint16 index
static QByteArray bindFont(const QList< QTtfTable > &_tables)
unsigned short ushort
Definition: qglobal.h:995
QByteArray data
uint style
Definition: qfont_p.h:97
FT_Face non_locked_face() const
int nGlyphs() const
Definition: qfontsubset_p.h:90
void resize(int size)
Sets the size of the byte array to size bytes.
unsigned int quint32
Definition: qglobal.h:938
static void checkRanges(QPdf::ByteStream &ts, QByteArray &ranges, int &nranges)
int size() const
Returns the number of items in the list.
Definition: qlist.h:137
quint16 maxComponentElements
static QTtfGlyph generateGlyph(int index, const QPainterPath &path, qreal advance, qreal lsb, qreal ppem)
quint32 Tag
QFactoryLoader * l
qreal toReal() const
Definition: qfixed_p.h:77
int size() const
Returns the number of bytes in this byte array.
Definition: qbytearray.h:402
static const QCssKnownValue properties[NumProperties - 1]
Definition: qcssparser.cpp:67
qreal x
the x coordinate of the element&#39;s position.
Definition: qpainterpath.h:79
quint16 index
QDataStream & operator<<(QDataStream &s, const QAxBase &c)
Definition: qaxbase.h:203
T takeLast()
Removes the last item in the list and returns it.
Definition: qlist.h:492
static void getGlyphData(QTtfGlyph *glyph, const QList< TTF_POINT > &points, const QList< int > &endPoints, int point_array_size)
QByteArray & replace(int index, int len, const char *s)
This is an overloaded member function, provided for convenience. It differs from the above function o...
bool isEmpty() const
Returns true if the byte array has size 0; otherwise returns false.
Definition: qbytearray.h:421
bool isEmpty() const
Returns true if the vector has size 0; otherwise returns false.
Definition: qvector.h:139
int elementCount() const
Returns the number of path elements in the painter path.
Definition: qpainterpath.h:397
qttf_maxp_table maxp
qint16 lsb
qint16 indexToLocFormat
FT_Face non_locked_face() const
QFontDef fontDef
QString family
Definition: qfont_p.h:82
quint16 maxCompositeContours
static const KeyPair *const end
QVector< int > getReverseMap() const
Flags
uint styleHint
Definition: qfont_p.h:93
int offset() const
static const char * times_styles[4]
static QByteArray number(int, int base=10)
Returns a byte array containing the string equivalent of the number n to base base (10 by default)...
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:55
quint16 Offset
quint16 advanceWidth
static const char *const agl
Definition: qfontsubset.cpp:64
unsigned int glyph_t
const int object_id
Definition: qfontsubset_p.h:84
Q_DECL_CONSTEXPR int qRound(qreal d)
Definition: qglobal.h:1203
static QList< QTtfTable > generateGlyphTables(qttf_font_tables &tables, const QList< QTtfGlyph > &_glyphs)
Q_STATIC_GLOBAL_OPERATOR bool operator<(const QTtfGlyph &g1, const QTtfGlyph &g2)
The QList class is a template class that provides lists.
Definition: qdatastream.h:62
const ushort * utf16() const
Returns the QString as a &#39;\0\&#39;-terminated array of unsigned shorts.
Definition: qstring.cpp:5290
QByteArray & insert(int i, char c)
Inserts character ch at index position i in the byte array.
QByteArray getSfntTable(uint) const