src/gui/text/qfontsubset.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 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 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    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 optimised 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 optimise 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