xref: /trunk/main/vcl/source/fontsubset/cff.cxx (revision 245cfa3273a796efe837af30e8f9170e3ad3ab98)
19f62ea84SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
39f62ea84SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
49f62ea84SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
59f62ea84SAndrew Rist  * distributed with this work for additional information
69f62ea84SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
79f62ea84SAndrew Rist  * to you under the Apache License, Version 2.0 (the
89f62ea84SAndrew Rist  * "License"); you may not use this file except in compliance
99f62ea84SAndrew Rist  * with the License.  You may obtain a copy of the License at
10cdf0e10cSrcweir  *
119f62ea84SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir  *
139f62ea84SAndrew Rist  * Unless required by applicable law or agreed to in writing,
149f62ea84SAndrew Rist  * software distributed under the License is distributed on an
159f62ea84SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
169f62ea84SAndrew Rist  * KIND, either express or implied.  See the License for the
179f62ea84SAndrew Rist  * specific language governing permissions and limitations
189f62ea84SAndrew Rist  * under the License.
19cdf0e10cSrcweir  *
209f62ea84SAndrew Rist  *************************************************************/
219f62ea84SAndrew Rist 
229f62ea84SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_vcl.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include <cstdio>
28cdf0e10cSrcweir #include <cstring>
29cdf0e10cSrcweir #include <assert.h>
30cdf0e10cSrcweir 
31248a599fSHerbert Dürr #include "fontsubset.hxx"
32cdf0e10cSrcweir 
33cdf0e10cSrcweir #include <vcl/strhelper.hxx>
34cdf0e10cSrcweir 
35cdf0e10cSrcweir //#define IGNORE_HINTS
36cdf0e10cSrcweir 
37cdf0e10cSrcweir typedef unsigned char U8;
38cdf0e10cSrcweir typedef unsigned short U16;
39cdf0e10cSrcweir typedef long long S64;
40cdf0e10cSrcweir 
41cdf0e10cSrcweir typedef sal_Int32 GlyphWidth;
42cdf0e10cSrcweir 
4365eb26c1SAkikazu Yoshikawa typedef double RealType;
44cdf0e10cSrcweir typedef RealType ValType;
45cdf0e10cSrcweir #include <vector>
46cdf0e10cSrcweir typedef std::vector<ValType> ValVector;
47cdf0e10cSrcweir 
48cdf0e10cSrcweir // ====================================================================
49cdf0e10cSrcweir 
50cdf0e10cSrcweir static const char* pStringIds[] = {
51cdf0e10cSrcweir /*0*/   ".notdef",      "space",            "exclam",           "quotedbl",
52cdf0e10cSrcweir     "numbersign",       "dollar",           "percent",          "ampersand",
53cdf0e10cSrcweir     "quoteright",       "parenleft",        "parenright",       "asterisk",
54cdf0e10cSrcweir     "plus",             "comma",            "hyphen",           "period",
55cdf0e10cSrcweir /*16*/  "slash",        "zero",             "one",              "two",
56cdf0e10cSrcweir     "three",            "four",             "five",             "six",
57cdf0e10cSrcweir     "seven",            "eight",            "nine",             "colon",
58cdf0e10cSrcweir     "semicolon",        "less",             "equal",            "greater",
59cdf0e10cSrcweir /*32*/  "question",     "at",               "A",                "B",
60cdf0e10cSrcweir     "C",                "D",                "E",                "F",
61cdf0e10cSrcweir     "G",                "H",                "I",                "J",
62cdf0e10cSrcweir     "K",                "L",                "M",                "N",
63cdf0e10cSrcweir /*48*/  "O",            "P",                "Q",                "R",
64cdf0e10cSrcweir     "S",                "T",                "U",                "V",
65cdf0e10cSrcweir     "W",                "X",                "Y",                "Z",
66cdf0e10cSrcweir     "bracketleft",      "backslash",        "bracketright",     "asciicircum",
67cdf0e10cSrcweir /*64*/  "underscore",   "quoteleft",        "a",                "b",
68cdf0e10cSrcweir     "c",                "d",                "e",                "f",
69cdf0e10cSrcweir     "g",                "h",                "i",                "j",
70cdf0e10cSrcweir     "k",                "l",                "m",                "n",
71cdf0e10cSrcweir /*80*/  "o",            "p",                "q",                "r",
72cdf0e10cSrcweir     "s",                "t",                "u",                "v",
73cdf0e10cSrcweir     "w",                "x",                "y",                "z",
74cdf0e10cSrcweir     "braceleft",        "bar",              "braceright",       "asciitilde",
75cdf0e10cSrcweir /*96*/  "exclamdown",   "cent",             "sterlin",          "fraction",
76cdf0e10cSrcweir     "yen",              "florin",           "section",          "currency",
77cdf0e10cSrcweir     "quotesingle",      "quotedblleft",     "guillemotleft",    "guilsinglleft",
78cdf0e10cSrcweir     "guilsinglright",   "fi",               "fl",               "endash",
79cdf0e10cSrcweir /*112*/ "dagger",       "daggerdbl",        "periodcentered",   "paragraph",
80cdf0e10cSrcweir     "bullet",           "quotesinglbase",   "quotedblbase",     "quotedblright",
81cdf0e10cSrcweir     "guillemotright",   "ellipsis",         "perthousand",      "questiondown",
82cdf0e10cSrcweir     "grave",            "acute",            "circumflex",       "tilde",
83cdf0e10cSrcweir /*128*/ "macron",       "breve",            "dotaccent",        "dieresis",
84cdf0e10cSrcweir     "ring",             "cedilla",          "hungarumlaut",     "ogonek",
85*245cfa32Smseidel     "caron",            "emdash",           "AE",               "ordfeminine",
86cdf0e10cSrcweir     "Lslash",           "Oslash",           "OE",               "ordmasculine",
87cdf0e10cSrcweir /*144*/ "ae",           "dotlessi",         "lslash",           "oslash",
88cdf0e10cSrcweir     "oe",               "germandbls",       "onesuperior",      "logicalnot",
89cdf0e10cSrcweir     "mu",               "trademark",        "Eth",              "onehalf",
90cdf0e10cSrcweir     "plusminus",        "Thorn",            "onequarter",       "divide",
91cdf0e10cSrcweir /*160*/ "brokenbar",    "degree",           "thorn",            "threequarters",
92cdf0e10cSrcweir     "twosuperior",      "registered",       "minus",            "eth",
93cdf0e10cSrcweir     "multiply",         "threesuperior",    "copyright",        "Aacute",
94cdf0e10cSrcweir     "Acircumflex",      "Adieresis",        "Agrave",           "Aring",
95cdf0e10cSrcweir /*176*/ "Atilde",       "Ccedilla",         "Eacute",           "Ecircumflex",
96cdf0e10cSrcweir     "Edieresis",        "Egrave",           "Iacute",           "Icircumflex",
97cdf0e10cSrcweir     "Idieresis",        "Igrave",           "Ntilde",           "Oacute",
98cdf0e10cSrcweir     "Ocircumflex",      "Odieresis",        "Ograve",           "Otilde",
99cdf0e10cSrcweir /*192*/ "Scaron",       "Uacute",           "Ucircumflex",      "Udieresis",
100cdf0e10cSrcweir     "Ugrave",           "Yacute",           "Ydieresis",        "Zcaron",
101cdf0e10cSrcweir     "aacute",           "acircumflex",      "adieresis",        "agrave",
102cdf0e10cSrcweir     "aring",            "atilde",           "ccedilla",         "eacute",
103cdf0e10cSrcweir /*208*/ "ecircumflex",  "edieresis",        "egrave",           "iacute",
104cdf0e10cSrcweir     "icircumflex",      "idieresis",        "igrave",           "ntilde",
105cdf0e10cSrcweir     "oacute",           "ocircumflex",      "odieresis",        "ograve",
106cdf0e10cSrcweir     "otilde",           "scaron",           "uacute",           "ucircumflex",
107cdf0e10cSrcweir /*224*/ "udieresis",    "ugrave",           "yacute",           "ydieresis",
108cdf0e10cSrcweir     "zcaron",           "exclamsmall",      "Hungarumlautsmall","dollaroldstyle",
109cdf0e10cSrcweir     "dollarsuperior",   "ampersandsmall",   "Acutesmall",       "parenleftsuperior",
110cdf0e10cSrcweir     "parenrightsuperior","twodotenleader",  "onedotenleader",   "zerooldstyle",
111cdf0e10cSrcweir /*240*/ "oneoldstyle",  "twooldstyle",      "threeoldstyle",    "fouroldstyle",
112cdf0e10cSrcweir     "fiveoldstyle",     "sixoldstyle",      "sevenoldstyle",    "eightoldstyle",
113cdf0e10cSrcweir     "nineoldstile",     "commasuperior",    "threequartersemdash","periodsuperior",
114cdf0e10cSrcweir     "questionsmall",    "asuperior",        "bsuperior",        "centsuperior",
115cdf0e10cSrcweir /*256*/ "dsuperior",    "esuperior",        "isuperior",        "lsuperior",
116cdf0e10cSrcweir     "msuperior",        "nsuperior",        "osuperior",        "rsuperior",
117cdf0e10cSrcweir     "ssuperior",        "tsuperior",        "ff",               "ffi",
118cdf0e10cSrcweir     "ffl",              "parenleftinferior","parenrightinferior","Circumflexsmall",
119cdf0e10cSrcweir /*272*/ "hyphensuperior","Gravesmall",      "Asmall",           "Bsmall",
120cdf0e10cSrcweir     "Csmall",           "Dsmall",           "Esmall",           "Fsmall",
121cdf0e10cSrcweir     "Gsmall",           "Hsmall",           "Ismall",           "Jsmall",
122cdf0e10cSrcweir     "Ksmall",           "Lsmall",           "Msmall",           "Nsmall",
123cdf0e10cSrcweir /*288*/ "Osmall",       "Psmall",           "Qsmall",           "Rsmall",
124cdf0e10cSrcweir     "Ssmall",           "Tsmall",           "Usmall",           "Vsmall",
125cdf0e10cSrcweir     "Wsmall",           "Xsmall",           "Ysmall",           "Zsmall",
126cdf0e10cSrcweir     "colonmonetary",    "onefitted",        "rupia",            "Tildesmall",
127cdf0e10cSrcweir /*304*/ "exclamdownsmall","centoldstyle",   "Lslashsmall",      "Scaronsmall",
128cdf0e10cSrcweir     "Zcaronsmall",      "Dieresissmall",    "Brevesmall",       "Caronsmall",
129cdf0e10cSrcweir     "Dotaccentsmall",   "Macronsmall",      "figuredash",       "hypheninferior",
130cdf0e10cSrcweir     "Ogoneksmall",      "Ringsmall",        "Cedillasmall",     "questiondownsmall",
131cdf0e10cSrcweir /*320*/ "oneeight",     "threeeights",      "fiveeights",       "seveneights",
132cdf0e10cSrcweir     "onethird",         "twothirds",        "zerosuperior",     "foursuperior",
133cdf0e10cSrcweir     "fivesuperior",     "sixsuperior",      "sevensuperior",    "eightsuperior",
134cdf0e10cSrcweir     "ninesuperior",     "zeroinferior",     "oneinferior",      "twoinferior",
135cdf0e10cSrcweir /*336*/ "threeinferior","fourinferior",     "fiveinferior",     "sixinferior",
136cdf0e10cSrcweir     "seveninferior",    "eightinferior",    "nineinferior",     "centinferior",
137cdf0e10cSrcweir     "dollarinferior",   "periodinferior",   "commainferior",    "Agravesmall",
138cdf0e10cSrcweir     "Aacutesmall",      "Acircumflexsmall", "Atildesmall",      "Adieresissmall",
139cdf0e10cSrcweir /*352*/ "Aringsmall",   "AEsmall",          "Ccedillasmall",    "Egravesmall",
140cdf0e10cSrcweir     "Eacutesmall",      "Ecircumflexsmall", "Edieresissmall",   "Igravesmall",
141cdf0e10cSrcweir     "Iacutesmall",      "Icircumflexsmall", "Idieresissmall",   "Ethsmall",
142cdf0e10cSrcweir     "Ntildesmall",      "Ogravesmall",      "Oacutesmall",      "Ocircumflexsmall",
143cdf0e10cSrcweir /*368*/ "Otildesmall",  "Odieressissmall",  "OEsmall",          "Oslashsmall",
144cdf0e10cSrcweir     "Ugravesmall",      "Uacutesmall",      "Ucircumflexsmall", "Udieresissmall",
145cdf0e10cSrcweir     "Yacutesmall",      "Thornsmall",       "Ydieresissmall",   "001.000",
146cdf0e10cSrcweir     "001.001",          "001.002",          "001.003",          "Black",
147cdf0e10cSrcweir /*384*/ "Bold",         "Book",             "Light",            "Medium",
148cdf0e10cSrcweir     "Regular",          "Roman",            "Semibold"
149cdf0e10cSrcweir };
150cdf0e10cSrcweir 
151cdf0e10cSrcweir // --------------------------------------------------------------------
152cdf0e10cSrcweir 
153cdf0e10cSrcweir #if 0 // TODO: use them
154cdf0e10cSrcweir static const char* pStdEncNames[] = {
155cdf0e10cSrcweir     "ISOAdobe", "Expert",   "ExpertSubSet"
156cdf0e10cSrcweir };
157cdf0e10cSrcweir #endif
158cdf0e10cSrcweir 
159cdf0e10cSrcweir // --------------------------------------------------------------------
160cdf0e10cSrcweir 
16128337f97SArrigo Marchiori /** TOP DICT keywords (also covers PRIV DICT keywords)
16228337f97SArrigo Marchiori  *
16328337f97SArrigo Marchiori  * Refer to the CFF Specification, tables 9 and 23.
16428337f97SArrigo Marchiori  *
16528337f97SArrigo Marchiori  * This array is indexed by operand.
16628337f97SArrigo Marchiori  *
16728337f97SArrigo Marchiori  * The first character tells the type of operand ('s': SID, 'b': boolean etc.).
16828337f97SArrigo Marchiori  */
169cdf0e10cSrcweir static const char* pDictOps[] = {
170cdf0e10cSrcweir     "sVersion",         "sNotice",              "sFullName",        "sFamilyName",
171cdf0e10cSrcweir     "sWeight",          "aFontBBox",            "dBlueValues",      "dOtherBlues",
172cdf0e10cSrcweir     "dFamilyBlues",     "dFamilyOtherBlues",    "nStdHW",           "nStdVW",
173cdf0e10cSrcweir     "xESC",             "nUniqueID",            "aXUID",            "nCharset",
174cdf0e10cSrcweir     "nEncoding",        "nCharStrings",         "PPrivate",         "nSubrs",
175cdf0e10cSrcweir     "nDefaultWidthX",   "nNominalWidthX",       NULL,               NULL,
176cdf0e10cSrcweir     NULL,               NULL,                   NULL,               NULL,
177cdf0e10cSrcweir     "shortint",         "longint",              "BCD",              NULL
178cdf0e10cSrcweir };
179cdf0e10cSrcweir 
180cdf0e10cSrcweir // --------------------------------------------------------------------
181cdf0e10cSrcweir 
18228337f97SArrigo Marchiori /** TOP DICT escapes (also covers PRIV DICT escapes)
18328337f97SArrigo Marchiori  *
18428337f97SArrigo Marchiori  * Refer to the CFF Specification, tables 9 and 23.
18528337f97SArrigo Marchiori  *
18628337f97SArrigo Marchiori  * These operators come after the escape operator (no. 12).
18728337f97SArrigo Marchiori  *
18828337f97SArrigo Marchiori  * This array is indexed by operand.
18928337f97SArrigo Marchiori  *
19028337f97SArrigo Marchiori  * The first character tells the type of operand ('s': SID, 'b': boolean etc.).
19128337f97SArrigo Marchiori  */
192cdf0e10cSrcweir static const char* pDictEscs[] = {
193cdf0e10cSrcweir     "sCopyright",           "bIsFixedPitch",    "nItalicAngle",     "nUnderlinePosition",
194cdf0e10cSrcweir     "nUnderlineThickness",  "nPaintType",       "tCharstringType",  "aFontMatrix",
195cdf0e10cSrcweir     "nStrokeWidth",         "nBlueScale",       "nBlueShift",       "nBlueFuzz",
196cdf0e10cSrcweir     "dStemSnapH",           "dStemSnapV",       "bForceBold",       NULL,
197cdf0e10cSrcweir     NULL,                   "nLanguageGroup",   "nExpansionFactor", "nInitialRandomSeed",
198cdf0e10cSrcweir     "nSyntheticBase",       "sPostScript",      "sBaseFontName",    "dBaseFontBlend",
199cdf0e10cSrcweir     NULL,                   NULL,               NULL,               NULL,
200cdf0e10cSrcweir     NULL,                   NULL,               "rROS",             "nCIDFontVersion",
201cdf0e10cSrcweir     "nCIDFontRevision",     "nCIDFontType",     "nCIDCount",        "nUIDBase",
202cdf0e10cSrcweir     "nFDArray",             "nFDSelect",        "sFontName"
203cdf0e10cSrcweir };
204cdf0e10cSrcweir 
205cdf0e10cSrcweir // --------------------------------------------------------------------
206cdf0e10cSrcweir 
207cdf0e10cSrcweir static const char* pType1Ops[] = {
208cdf0e10cSrcweir     NULL,               "2hstem",           NULL,               "2vstem",
209cdf0e10cSrcweir     "1vmoveto",         "Arlineto",         "1hlineto",         "1vlineto",
210cdf0e10cSrcweir     "Crrcurveto",       "0closepath",       "Lcallsubr",        "0return",
211cdf0e10cSrcweir     "xT1ESC",           "2hsbw",            "0endchar",         NULL,
212cdf0e10cSrcweir     NULL,               NULL,               NULL,               NULL,
213cdf0e10cSrcweir     NULL,               "2rmoveto",         "1hmoveto",         NULL,
214cdf0e10cSrcweir     NULL,               NULL,               NULL,               NULL,
215cdf0e10cSrcweir     NULL,               NULL,               "4vhcurveto",       "4hvcurveto"
216cdf0e10cSrcweir };
217cdf0e10cSrcweir 
218cdf0e10cSrcweir // --------------------------------------------------------------------
219cdf0e10cSrcweir 
220cdf0e10cSrcweir static const char* pT1EscOps[] = {
221cdf0e10cSrcweir     "0dotsection",      "6vstem3",          "6hstem3",          NULL,
222cdf0e10cSrcweir     NULL,               NULL,               "5seac",            "4sbw",
223cdf0e10cSrcweir     NULL,               "1abs",             "2add",             "2sub",
224cdf0e10cSrcweir     "2div",             NULL,               NULL,               NULL,
225cdf0e10cSrcweir     "Gcallothersubr",   "1pop",             NULL,               NULL,
226cdf0e10cSrcweir     NULL,               NULL,               NULL,               NULL,
227cdf0e10cSrcweir     NULL,               NULL,               NULL,               NULL,
228cdf0e10cSrcweir     NULL,               NULL,               NULL,               NULL,
229cdf0e10cSrcweir     NULL,               "2setcurrentpoint"
230cdf0e10cSrcweir };
231cdf0e10cSrcweir 
232cdf0e10cSrcweir // --------------------------------------------------------------------
233cdf0e10cSrcweir 
234cdf0e10cSrcweir struct TYPE1OP
235cdf0e10cSrcweir {
236cdf0e10cSrcweir     enum OPS
237cdf0e10cSrcweir     {
238cdf0e10cSrcweir         HSTEM=1,        VSTEM=3,        VMOVETO=4,      RLINETO=5,
239cdf0e10cSrcweir         HLINETO=6,      VLINETO=7,      RCURVETO=8,     CLOSEPATH=9,
240cdf0e10cSrcweir         CALLSUBR=10,    RETURN=11,      T1ESC=12,       HSBW=13,
241cdf0e10cSrcweir         ENDCHAR=14,     RMOVETO=21,     HMOVETO=22,     VHCURVETO=30,
242cdf0e10cSrcweir         HVCURVETO=31
243cdf0e10cSrcweir     };
244cdf0e10cSrcweir 
245cdf0e10cSrcweir     enum ESCS
246cdf0e10cSrcweir     {
247cdf0e10cSrcweir         DOTSECTION=0,   VSTEM3=1,           HSTEM3=2,   SEAC=6,
248cdf0e10cSrcweir         SBW=7,          ABS=9,              ADD=10,     SUB=11,
249cdf0e10cSrcweir         DIV=12,         CALLOTHERSUBR=16,   POP=17,     SETCURRENTPOINT=33
250cdf0e10cSrcweir     };
251cdf0e10cSrcweir };
252cdf0e10cSrcweir 
253cdf0e10cSrcweir // --------------------------------------------------------------------
254cdf0e10cSrcweir 
255cdf0e10cSrcweir static const char* pType2Ops[] = {
256cdf0e10cSrcweir     NULL,           "hhstem",       NULL,           "vvstem",
257cdf0e10cSrcweir     "mvmoveto",     "Arlineto",     "Ehlineto",     "Evlineto",
258cdf0e10cSrcweir     "Crrcurveto",   NULL,           "Lcallsubr",    "Xreturn",
259cdf0e10cSrcweir     "xT2ESC",       NULL,           "eendchar",     NULL,
260cdf0e10cSrcweir     NULL,           NULL,           "Hhstemhm",     "Khintmask",
261cdf0e10cSrcweir     "Kcntrmask",    "Mrmoveto",     "mhmoveto",     "Vvstemhm",
262cdf0e10cSrcweir     ".rcurveline",  ".rlinecurve",  ".vvcurveto",   ".hhcurveto",
263cdf0e10cSrcweir     ".shortint",    "Gcallgsubr",   ".vhcurveto",   ".hvcurveto"
264cdf0e10cSrcweir };
265cdf0e10cSrcweir 
266cdf0e10cSrcweir // --------------------------------------------------------------------
267cdf0e10cSrcweir 
268cdf0e10cSrcweir static const char* pT2EscOps[] = {
269cdf0e10cSrcweir     NULL,       NULL,       NULL,       "2and",
270cdf0e10cSrcweir     "2or",      "1not",     NULL,       NULL,
271cdf0e10cSrcweir     NULL,       "1abs",     "2add",     "2sub",
272cdf0e10cSrcweir     "2div",     NULL,       "1neg",     "2eq",
273cdf0e10cSrcweir     NULL,       NULL,       "1drop",    NULL,
274cdf0e10cSrcweir     "1put",     "1get",     "4ifelse",  "0random",
275cdf0e10cSrcweir     "2mul",     NULL,       "1sqrt",    "1dup",
276cdf0e10cSrcweir     "2exch",    "Iindex",   "Rroll",    NULL,
277cdf0e10cSrcweir     NULL,       NULL,       "7hflex",   "Fflex",
278cdf0e10cSrcweir     "9hflex1",  "fflex1"
279cdf0e10cSrcweir };
280cdf0e10cSrcweir 
281cdf0e10cSrcweir // --------------------------------------------------------------------
282cdf0e10cSrcweir 
283cdf0e10cSrcweir struct TYPE2OP
284cdf0e10cSrcweir {
285cdf0e10cSrcweir     enum OPS
286cdf0e10cSrcweir     {
287cdf0e10cSrcweir         HSTEM=1,        VSTEM=3,        VMOVETO=4,      RLINETO=5,
288cdf0e10cSrcweir         HLINETO=6,      VLINETO=7,      RCURVETO=8,     CALLSUBR=10,
289cdf0e10cSrcweir         RETURN=11,      T2ESC=12,       ENDCHAR=14,     HSTEMHM=18,
290cdf0e10cSrcweir         HINTMASK=19,    CNTRMASK=20,    RMOVETO=21,     HMOVETO=22,
291cdf0e10cSrcweir         VSTEMHM=23,     RCURVELINE=24,  RLINECURVE=25,  VVCURVETO=26,
292cdf0e10cSrcweir         HHCURVETO=27,   SHORTINT=28,    CALLGSUBR=29,   VHCURVETO=30,
293cdf0e10cSrcweir         HVCURVETO=31
294cdf0e10cSrcweir     };
295cdf0e10cSrcweir 
296cdf0e10cSrcweir     enum ESCS
297cdf0e10cSrcweir     {
298cdf0e10cSrcweir         AND=3,      OR=4,       NOT=5,      ABS=9,
299cdf0e10cSrcweir         ADD=10,     SUB=11,     DIV=12,     NEG=14,
300cdf0e10cSrcweir         EQ=15,      DROP=18,    PUT=20,     GET=21,
301cdf0e10cSrcweir         IFELSE=22,  RANDOM=23,  MUL=24,     SQRT=26,
302cdf0e10cSrcweir         DUP=27,     EXCH=28,    INDEX=29,   ROLL=30,
303cdf0e10cSrcweir         HFLEX=34,   FLEX=35,    HFLEX1=36,  FLEX1=37
304cdf0e10cSrcweir     };
305cdf0e10cSrcweir };
306cdf0e10cSrcweir 
307cdf0e10cSrcweir // ====================================================================
308cdf0e10cSrcweir 
30928337f97SArrigo Marchiori /** Data layout of a CFF FontSet
31028337f97SArrigo Marchiori  *
31128337f97SArrigo Marchiori  * Refer to the CFF specification, chapter 2
31228337f97SArrigo Marchiori  */
313cdf0e10cSrcweir struct CffGlobal
314cdf0e10cSrcweir {
315cdf0e10cSrcweir     explicit CffGlobal();
316cdf0e10cSrcweir 
31728337f97SArrigo Marchiori     // Offset of the Name INDEX inside the CFF data
318cdf0e10cSrcweir     int     mnNameIdxBase;
31928337f97SArrigo Marchiori     // Number of objects stored in the Name INDEX
320cdf0e10cSrcweir     int     mnNameIdxCount;
321cdf0e10cSrcweir     int     mnStringIdxBase;
322cdf0e10cSrcweir     int     mnStringIdxCount;
323cdf0e10cSrcweir     bool    mbCIDFont;
324cdf0e10cSrcweir     int     mnCharStrBase;
325cdf0e10cSrcweir     int     mnCharStrCount;
326cdf0e10cSrcweir     int     mnEncodingBase;
327cdf0e10cSrcweir     int     mnCharsetBase;
328cdf0e10cSrcweir     int     mnGlobalSubrBase;
329cdf0e10cSrcweir     int     mnGlobalSubrCount;
330cdf0e10cSrcweir     int     mnGlobalSubrBias;
331cdf0e10cSrcweir     int     mnFDSelectBase;
332cdf0e10cSrcweir     int     mnFontDictBase;
333cdf0e10cSrcweir     int     mnFDAryCount;
334cdf0e10cSrcweir 
335cdf0e10cSrcweir     ValVector   maFontBBox;
336cdf0e10cSrcweir     ValVector   maFontMatrix;
337cdf0e10cSrcweir 
338cdf0e10cSrcweir     int     mnFontNameSID;
339cdf0e10cSrcweir     int     mnFullNameSID;
340cdf0e10cSrcweir     int     mnFamilyNameSID;
341cdf0e10cSrcweir };
342cdf0e10cSrcweir 
343cdf0e10cSrcweir // ====================================================================
344cdf0e10cSrcweir 
345cdf0e10cSrcweir struct CffLocal
346cdf0e10cSrcweir {
347cdf0e10cSrcweir     explicit CffLocal();
348cdf0e10cSrcweir 
349cdf0e10cSrcweir     int     mnPrivDictBase;
350cdf0e10cSrcweir     int     mnPrivDictSize;
351cdf0e10cSrcweir     int     mnLocalSubrOffs;
352cdf0e10cSrcweir     int     mnLocalSubrBase;
353cdf0e10cSrcweir     int     mnLocalSubrCount;
354cdf0e10cSrcweir     int     mnLocalSubrBias;
355cdf0e10cSrcweir 
356cdf0e10cSrcweir     ValType maNominalWidth;
357cdf0e10cSrcweir     ValType maDefaultWidth;
358cdf0e10cSrcweir 
359cdf0e10cSrcweir     // ATM hinting related values
360cdf0e10cSrcweir     ValType     maStemStdHW;
361cdf0e10cSrcweir     ValType     maStemStdVW;
362cdf0e10cSrcweir     ValVector   maStemSnapH;
363cdf0e10cSrcweir     ValVector   maStemSnapV;
364cdf0e10cSrcweir     ValVector   maBlueValues;
365cdf0e10cSrcweir     ValVector   maOtherBlues;
366cdf0e10cSrcweir     ValVector   maFamilyBlues;
367cdf0e10cSrcweir     ValVector   maFamilyOtherBlues;
368cdf0e10cSrcweir     RealType    mfBlueScale;
369cdf0e10cSrcweir     RealType    mfBlueShift;
370cdf0e10cSrcweir     RealType    mfBlueFuzz;
371cdf0e10cSrcweir     RealType    mfExpFactor;
372cdf0e10cSrcweir     int         mnLangGroup;
373cdf0e10cSrcweir     bool        mbForceBold;
374cdf0e10cSrcweir };
375cdf0e10cSrcweir 
376cdf0e10cSrcweir // ====================================================================
377cdf0e10cSrcweir 
378cdf0e10cSrcweir class CffSubsetterContext
37928337f97SArrigo Marchiori :   private CffGlobal
380cdf0e10cSrcweir {
381cdf0e10cSrcweir public:
38228337f97SArrigo Marchiori     // Refer to Type 2 charstring format appendix B, "Type 2 Charstring Implementation Limits"
38328337f97SArrigo Marchiori     static const int NMAXSTACK = 48;    // argument stack
38428337f97SArrigo Marchiori     static const int NMAXHINTS = 2*96;  // number of stem hints (H/V total)
38528337f97SArrigo Marchiori     static const int NMAXTRANS = 32;    // TransientArray elements
386cdf0e10cSrcweir public:
387cdf0e10cSrcweir     explicit CffSubsetterContext( const U8* pBasePtr, int nBaseLen);
388cdf0e10cSrcweir     virtual ~CffSubsetterContext( void);
389cdf0e10cSrcweir 
39028337f97SArrigo Marchiori     // Begin parsing the CFF data
391cdf0e10cSrcweir     void    initialCffRead( void);
392cdf0e10cSrcweir     bool    emitAsType1( class Type1Emitter&,
393248a599fSHerbert Dürr                 const sal_GlyphId* pGlyphIds, const U8* pEncoding,
394cdf0e10cSrcweir                 GlyphWidth* pGlyphWidths, int nGlyphCount, FontSubsetInfo& );
395cdf0e10cSrcweir 
396cdf0e10cSrcweir     // used by charstring converter
397cdf0e10cSrcweir     void    setCharStringType( int);
fakeLocalSubrCount(int nLocalSubrs)398cdf0e10cSrcweir     void    fakeLocalSubrCount( int nLocalSubrs ) { maCffLocal[0].mnLocalSubrCount=nLocalSubrs;}
399cdf0e10cSrcweir protected:
400cdf0e10cSrcweir     int     convert2Type1Ops( CffLocal*, const U8* pType2Ops, int nType2Len, U8* pType1Ops);
401cdf0e10cSrcweir private:
402cdf0e10cSrcweir     void    convertOneTypeOp( void);
403cdf0e10cSrcweir     void    convertOneTypeEsc( void);
404cdf0e10cSrcweir     void    callType2Subr( bool bGlobal, int nSubrNumber);
getReadOfs(void) const405cdf0e10cSrcweir     long    getReadOfs( void) const { return (long)(mpReadPtr - mpBasePtr);}
406cdf0e10cSrcweir 
40728337f97SArrigo Marchiori     // First byte of CFF font data
408cdf0e10cSrcweir     const U8* mpBasePtr;
40928337f97SArrigo Marchiori     // Last byte of CFF font data
410cdf0e10cSrcweir     const U8* mpBaseEnd;
411cdf0e10cSrcweir 
41228337f97SArrigo Marchiori     // Moving cursors inside CFF font data
413cdf0e10cSrcweir     const U8* mpReadPtr;
414cdf0e10cSrcweir     const U8* mpReadEnd;
415cdf0e10cSrcweir 
416cdf0e10cSrcweir     U8*     mpWritePtr;
417cdf0e10cSrcweir     bool    mbSawError;
418cdf0e10cSrcweir     bool    mbNeedClose;
419cdf0e10cSrcweir     bool    mbIgnoreHints;
420cdf0e10cSrcweir     long    mnCntrMask;
421cdf0e10cSrcweir 
422cdf0e10cSrcweir private:
42328337f97SArrigo Marchiori     /** Prepare to access an element inside a CFF/CID index table
42428337f97SArrigo Marchiori      *
42528337f97SArrigo Marchiori      * nIndexBase: offset of the INDEX structure inside the CFF font data.
42628337f97SArrigo Marchiori      * nDataIndex: offset of the element inside the INDEX structure.
42728337f97SArrigo Marchiori      *
42828337f97SArrigo Marchiori      * Sets mpReadPtr to the beginning of the element and mpReadEnd to the end of the element.
42928337f97SArrigo Marchiori      *
43028337f97SArrigo Marchiori      * Returns the size of the element, or -1 if the data is not valid (e.g. indices are too big).
43128337f97SArrigo Marchiori      */
432cdf0e10cSrcweir     int     seekIndexData( int nIndexBase, int nDataIndex);
43328337f97SArrigo Marchiori     /** Seek to the end of an INDEX structure
43428337f97SArrigo Marchiori      *
43528337f97SArrigo Marchiori      * nIndexBase: offset of the INDEX structure inside the CFF font data.
43628337f97SArrigo Marchiori      *
43728337f97SArrigo Marchiori      * Sets mpReadPtr to the first byte after the indicated structure.
43828337f97SArrigo Marchiori      */
439cdf0e10cSrcweir     void    seekIndexEnd( int nIndexBase);
440cdf0e10cSrcweir 
441cdf0e10cSrcweir private:
442cdf0e10cSrcweir     const char**    mpCharStringOps;
443cdf0e10cSrcweir     const char**    mpCharStringEscs;
444cdf0e10cSrcweir 
44528337f97SArrigo Marchiori     std::vector<CffLocal>   maCffLocal;
446cdf0e10cSrcweir     CffLocal*   mpCffLocal;
447cdf0e10cSrcweir 
448cdf0e10cSrcweir     void        readDictOp( void);
449cdf0e10cSrcweir     RealType    readRealVal( void);
450cdf0e10cSrcweir     const char* getString( int nStringID);
451cdf0e10cSrcweir     int         getFDSelect( int nGlyphIndex) const;
452cdf0e10cSrcweir     int         getGlyphSID( int nGlyphIndex) const;
453cdf0e10cSrcweir     const char* getGlyphName( int nGlyphIndex);
454cdf0e10cSrcweir 
45528337f97SArrigo Marchiori     /** Decode an integer DICT Data Operand and push it.
45628337f97SArrigo Marchiori      *
45728337f97SArrigo Marchiori      * Refer to the CFF Specification, table 3.
45828337f97SArrigo Marchiori      *
45928337f97SArrigo Marchiori      * Advances mpReadPtr.
46028337f97SArrigo Marchiori      */
461cdf0e10cSrcweir     void    read2push( void);
462cdf0e10cSrcweir     void    pop2write( void);
463cdf0e10cSrcweir     void    writeType1Val( ValType);
464cdf0e10cSrcweir     void    writeTypeOp( int nTypeOp);
465cdf0e10cSrcweir     void    writeTypeEsc( int nTypeOp);
466cdf0e10cSrcweir     void    writeCurveTo( int nStackPos, int nIX1, int nIY1, int nIX2, int nIY2, int nIX3, int nIY3);
467cdf0e10cSrcweir     void    pop2MultiWrite( int nArgsPerTypo, int nTypeOp, int nTypeXor=0);
468cdf0e10cSrcweir     void    popAll2Write( int nTypeOp);
469cdf0e10cSrcweir 
470cdf0e10cSrcweir public: // TODO: is public really needed?
471cdf0e10cSrcweir     // accessing the value stack
472cdf0e10cSrcweir     // TODO: add more checks
push(ValType nVal)473cdf0e10cSrcweir     void    push( ValType nVal) { mnValStack[ mnStackIdx++] = nVal;}
popVal(void)474cdf0e10cSrcweir     ValType popVal( void) { return ((mnStackIdx>0) ? mnValStack[ --mnStackIdx] : 0);}
peekVal(void) const475cdf0e10cSrcweir     ValType peekVal( void) const { return ((mnStackIdx>0) ? mnValStack[ mnStackIdx-1] : 0);}
getVal(int nIndex) const476cdf0e10cSrcweir     ValType getVal( int nIndex) const { return mnValStack[ nIndex];}
477cdf0e10cSrcweir     int     popInt( void);
478cdf0e10cSrcweir     int     peekInt( void) const;
479cdf0e10cSrcweir     int     getInt( int nIndex) const;
size(void) const480cdf0e10cSrcweir     int     size( void) const { return mnStackIdx;}
empty(void) const481cdf0e10cSrcweir     bool    empty( void) const { return !mnStackIdx;}
clear(void)482cdf0e10cSrcweir     void    clear( void) { mnStackIdx = 0;}
483cdf0e10cSrcweir 
484cdf0e10cSrcweir     // accessing the charstring hints
485cdf0e10cSrcweir     void    addHints( bool bVerticalHints);
getHorzHintCount(void) const486cdf0e10cSrcweir     int     getHorzHintCount( void) const { return (mnHorzHintSize/2);}
getVertHintCount(void) const487cdf0e10cSrcweir     int     getVertHintCount( void) const { return (mnHintSize-mnHorzHintSize)/2;}
488cdf0e10cSrcweir     void    getHintPair( int nIndex, ValType* nMin, ValType* nEnd) const;
489cdf0e10cSrcweir 
490cdf0e10cSrcweir     // accessing other charstring specifics
hasCharWidth(void) const491cdf0e10cSrcweir     bool    hasCharWidth( void) const { return (maCharWidth > 0);}
getCharWidth(void) const492cdf0e10cSrcweir     ValType getCharWidth( void) const { return maCharWidth;}
setNominalWidth(ValType aWidth)493cdf0e10cSrcweir     void    setNominalWidth( ValType aWidth) { mpCffLocal->maNominalWidth = aWidth;}
setDefaultWidth(ValType aWidth)494cdf0e10cSrcweir     void    setDefaultWidth( ValType aWidth) { mpCffLocal->maDefaultWidth = aWidth;}
495cdf0e10cSrcweir     void    updateWidth( bool bUseFirstVal);
496cdf0e10cSrcweir 
497cdf0e10cSrcweir private:
498cdf0e10cSrcweir     // typeop exceution context
49928337f97SArrigo Marchiori 
50028337f97SArrigo Marchiori     // Count of mnValStack elements
501cdf0e10cSrcweir     int mnStackIdx;
50228337f97SArrigo Marchiori     // Stack for holding CFF DICT operands
503cdf0e10cSrcweir     ValType mnValStack[ NMAXSTACK+4];
50428337f97SArrigo Marchiori     // Transient array for Type 2 storage operators (PUT, GET)
505cdf0e10cSrcweir     ValType mnTransVals[ NMAXTRANS];
506cdf0e10cSrcweir 
507cdf0e10cSrcweir     int mnHintSize;
508cdf0e10cSrcweir     int mnHorzHintSize;
509cdf0e10cSrcweir     ValType mnHintStack[ NMAXHINTS];
510cdf0e10cSrcweir 
511cdf0e10cSrcweir     ValType maCharWidth;
512cdf0e10cSrcweir };
513cdf0e10cSrcweir 
514cdf0e10cSrcweir // --------------------------------------------------------------------
515cdf0e10cSrcweir 
CffSubsetterContext(const U8 * pBasePtr,int nBaseLen)516cdf0e10cSrcweir CffSubsetterContext::CffSubsetterContext( const U8* pBasePtr, int nBaseLen)
517cdf0e10cSrcweir :   mpBasePtr( pBasePtr)
518cdf0e10cSrcweir ,   mpBaseEnd( pBasePtr+nBaseLen)
519cdf0e10cSrcweir ,   mnStackIdx(0)
520cdf0e10cSrcweir ,   mnHintSize(0)
521cdf0e10cSrcweir ,   mnHorzHintSize(0)
522cdf0e10cSrcweir ,   maCharWidth(-1)
523cdf0e10cSrcweir {
524cdf0e10cSrcweir //  setCharStringType( 1);
52528337f97SArrigo Marchiori     maCffLocal.resize(1);
526cdf0e10cSrcweir     mpCffLocal = &maCffLocal[0];
527cdf0e10cSrcweir }
528cdf0e10cSrcweir 
529cdf0e10cSrcweir // --------------------------------------------------------------------
530cdf0e10cSrcweir 
~CffSubsetterContext(void)531cdf0e10cSrcweir CffSubsetterContext::~CffSubsetterContext( void)
532cdf0e10cSrcweir {
533cdf0e10cSrcweir }
534cdf0e10cSrcweir 
535cdf0e10cSrcweir // --------------------------------------------------------------------
536cdf0e10cSrcweir 
popInt(void)537cdf0e10cSrcweir inline int CffSubsetterContext::popInt( void)
538cdf0e10cSrcweir {
539cdf0e10cSrcweir     const ValType aVal = popVal();
540cdf0e10cSrcweir     const int nInt = static_cast<int>(aVal);
541cdf0e10cSrcweir     assert( nInt == aVal);
542cdf0e10cSrcweir     return nInt;
543cdf0e10cSrcweir }
544cdf0e10cSrcweir 
545cdf0e10cSrcweir // --------------------------------------------------------------------
546cdf0e10cSrcweir 
peekInt(void) const547cdf0e10cSrcweir inline int CffSubsetterContext::peekInt( void) const
548cdf0e10cSrcweir {
549cdf0e10cSrcweir     const ValType aVal = peekVal();
550cdf0e10cSrcweir     const int nInt = static_cast<int>(aVal);
551cdf0e10cSrcweir     assert( nInt == aVal);
552cdf0e10cSrcweir     return nInt;
553cdf0e10cSrcweir }
554cdf0e10cSrcweir 
555cdf0e10cSrcweir // --------------------------------------------------------------------
556cdf0e10cSrcweir 
getInt(int nIndex) const557cdf0e10cSrcweir inline int CffSubsetterContext::getInt( int nIndex) const
558cdf0e10cSrcweir {
559cdf0e10cSrcweir     const ValType aVal = getVal( nIndex);
560cdf0e10cSrcweir     const int nInt = static_cast<int>(aVal);
561cdf0e10cSrcweir     assert( nInt == aVal);
562cdf0e10cSrcweir     return nInt;
563cdf0e10cSrcweir }
564cdf0e10cSrcweir 
565cdf0e10cSrcweir // --------------------------------------------------------------------
566cdf0e10cSrcweir 
updateWidth(bool bUseFirstVal)567cdf0e10cSrcweir inline void CffSubsetterContext::updateWidth( bool bUseFirstVal)
568cdf0e10cSrcweir {
569cdf0e10cSrcweir #if 1 // TODO: is this still needed?
570cdf0e10cSrcweir     // the first value is not a hint but the charwidth
571cdf0e10cSrcweir     if( hasCharWidth())
572cdf0e10cSrcweir         return;
573cdf0e10cSrcweir #endif
574cdf0e10cSrcweir     if( bUseFirstVal) {
575cdf0e10cSrcweir         maCharWidth = mpCffLocal->maNominalWidth + mnValStack[0];
576cdf0e10cSrcweir         // remove bottom stack entry
577cdf0e10cSrcweir         --mnStackIdx;
578cdf0e10cSrcweir         for( int i = 0; i < mnStackIdx; ++i)
579cdf0e10cSrcweir             mnValStack[ i] = mnValStack[ i+1];
580cdf0e10cSrcweir     } else {
581cdf0e10cSrcweir         maCharWidth = mpCffLocal->maDefaultWidth;
582cdf0e10cSrcweir     }
583cdf0e10cSrcweir }
584cdf0e10cSrcweir 
585cdf0e10cSrcweir // --------------------------------------------------------------------
586cdf0e10cSrcweir 
addHints(bool bVerticalHints)587cdf0e10cSrcweir void CffSubsetterContext::addHints( bool bVerticalHints)
588cdf0e10cSrcweir {
589cdf0e10cSrcweir     // the first charstring value may a charwidth instead of a charwidth
590cdf0e10cSrcweir     updateWidth( (mnStackIdx & 1) != 0);
591cdf0e10cSrcweir     // return early (e.g. no implicit hints for hintmask)
592cdf0e10cSrcweir     if( !mnStackIdx)
593cdf0e10cSrcweir         return;
594cdf0e10cSrcweir 
595cdf0e10cSrcweir     // copy the remaining values to the hint arrays
596cdf0e10cSrcweir     // assert( (mnStackIdx & 1) == 0); // depends on called subrs
597cdf0e10cSrcweir     if( mnStackIdx & 1) --mnStackIdx;//#######
598cdf0e10cSrcweir     // TODO: if( !bSubr) assert( mnStackIdx >= 2);
599cdf0e10cSrcweir 
600cdf0e10cSrcweir     assert( (mnHintSize + mnStackIdx) <= 2*NMAXHINTS);
601cdf0e10cSrcweir 
602cdf0e10cSrcweir #ifdef IGNORE_HINTS
603cdf0e10cSrcweir     mnHintSize += mnStackIdx;
604cdf0e10cSrcweir #else
605cdf0e10cSrcweir     ValType nHintOfs = 0;
606cdf0e10cSrcweir     for( int i = 0; i < mnStackIdx; ++i) {
607cdf0e10cSrcweir         nHintOfs += mnValStack[ i ];
608cdf0e10cSrcweir         mnHintStack[ mnHintSize++] = nHintOfs;
609cdf0e10cSrcweir     }
610cdf0e10cSrcweir #endif // IGNORE_HINTS
611cdf0e10cSrcweir     if( !bVerticalHints)
612cdf0e10cSrcweir         mnHorzHintSize = mnHintSize;
613cdf0e10cSrcweir 
614cdf0e10cSrcweir     // clear all values from the stack
615cdf0e10cSrcweir     mnStackIdx = 0;
616cdf0e10cSrcweir }
617cdf0e10cSrcweir 
618cdf0e10cSrcweir // --------------------------------------------------------------------
619cdf0e10cSrcweir 
getHintPair(int nIndex,ValType * pMin,ValType * pEnd) const620cdf0e10cSrcweir void CffSubsetterContext::getHintPair( int nIndex, ValType* pMin, ValType* pEnd) const
621cdf0e10cSrcweir {
622cdf0e10cSrcweir     nIndex *= 2;
623cdf0e10cSrcweir     assert( nIndex < mnHintSize);
624cdf0e10cSrcweir     assert( nIndex >= 0);
625cdf0e10cSrcweir     const ValType* pHint = &mnHintStack[ nIndex ];
626cdf0e10cSrcweir     *pMin = pHint[0];
627cdf0e10cSrcweir     *pEnd = pHint[1];
628cdf0e10cSrcweir }
629cdf0e10cSrcweir 
630cdf0e10cSrcweir // --------------------------------------------------------------------
631cdf0e10cSrcweir 
setCharStringType(int nVal)632cdf0e10cSrcweir void CffSubsetterContext::setCharStringType( int nVal)
633cdf0e10cSrcweir {
634cdf0e10cSrcweir     switch( nVal) {
635cdf0e10cSrcweir         case 1: mpCharStringOps=pType1Ops; mpCharStringEscs=pT1EscOps; break;
636cdf0e10cSrcweir         case 2: mpCharStringOps=pType2Ops; mpCharStringEscs=pT2EscOps; break;
637cdf0e10cSrcweir         default: fprintf( stderr, "Unknown CharstringType=%d\n",nVal); break;
638cdf0e10cSrcweir     }
639cdf0e10cSrcweir }
640cdf0e10cSrcweir 
641cdf0e10cSrcweir // --------------------------------------------------------------------
642cdf0e10cSrcweir 
64328337f97SArrigo Marchiori /** Read DICT operator at mpReadPtr.
64428337f97SArrigo Marchiori  *
64528337f97SArrigo Marchiori  * Sets the attributes of CffSubsetterContext::mpCffLocal
64628337f97SArrigo Marchiori  */
readDictOp(void)647cdf0e10cSrcweir void CffSubsetterContext::readDictOp( void)
648cdf0e10cSrcweir {
649cdf0e10cSrcweir     ValType nVal = 0;
650cdf0e10cSrcweir     int nInt = 0;
651cdf0e10cSrcweir     const U8 c = *mpReadPtr;
65228337f97SArrigo Marchiori     if( c <= 21 ) { // we are looking at an operator
653cdf0e10cSrcweir         int nOpId = *(mpReadPtr++);
654cdf0e10cSrcweir         const char* pCmdName;
655cdf0e10cSrcweir         if( nOpId != 12)
656cdf0e10cSrcweir             pCmdName = pDictOps[ nOpId];
65728337f97SArrigo Marchiori         else { // escape: the operator is indicated in the following byte
658cdf0e10cSrcweir             const U8 nExtId = *(mpReadPtr++);
659cdf0e10cSrcweir             pCmdName = pDictEscs[ nExtId];
660cdf0e10cSrcweir             nOpId = 900 + nExtId;
661cdf0e10cSrcweir         }
662cdf0e10cSrcweir 
663cdf0e10cSrcweir         //TODO: if( nStackIdx > 0)
66428337f97SArrigo Marchiori         // The first byte of pCmdName indicates the type of operand
665cdf0e10cSrcweir         switch( *pCmdName) {
666cdf0e10cSrcweir         default: fprintf( stderr, "unsupported DictOp.type=\'%c\'\n", *pCmdName); break;
667cdf0e10cSrcweir         case 'b':   // bool
668cdf0e10cSrcweir             nInt = popInt();
669cdf0e10cSrcweir             switch( nOpId) {
670cdf0e10cSrcweir             case 915: mpCffLocal->mbForceBold = nInt; break;    // "ForceBold"
671cdf0e10cSrcweir             default: break; // TODO: handle more boolean dictops?
672cdf0e10cSrcweir             }
673cdf0e10cSrcweir             break;
674cdf0e10cSrcweir         case 'n':   // dict-op number
675cdf0e10cSrcweir             nVal = popVal();
676cdf0e10cSrcweir             nInt = static_cast<int>(nVal);
677cdf0e10cSrcweir             switch( nOpId) {
678cdf0e10cSrcweir             case  10: mpCffLocal->maStemStdHW = nVal; break;    // "StdHW"
679cdf0e10cSrcweir             case  11: mpCffLocal->maStemStdVW = nVal; break;    // "StdVW"
680cdf0e10cSrcweir             case  15: mnCharsetBase = nInt; break;              // "charset"
681cdf0e10cSrcweir             case  16: mnEncodingBase = nInt; break;             // "nEncoding"
682cdf0e10cSrcweir             case  17: mnCharStrBase = nInt; break;              // "nCharStrings"
683cdf0e10cSrcweir             case  19: mpCffLocal->mnLocalSubrOffs = nInt; break;// "nSubrs"
684cdf0e10cSrcweir             case  20: setDefaultWidth( nVal ); break;           // "defaultWidthX"
685cdf0e10cSrcweir             case  21: setNominalWidth( nVal ); break;           // "nominalWidthX"
686cdf0e10cSrcweir             case 909: mpCffLocal->mfBlueScale = nVal; break;    // "BlueScale"
687cdf0e10cSrcweir             case 910: mpCffLocal->mfBlueShift = nVal; break;    // "BlueShift"
688cdf0e10cSrcweir             case 911: mpCffLocal->mfBlueFuzz = nVal; break;     // "BlueFuzz"
689cdf0e10cSrcweir             case 912: mpCffLocal->mfExpFactor = nVal; break;    // "ExpansionFactor"
690cdf0e10cSrcweir             case 917: mpCffLocal->mnLangGroup = nInt; break;    // "LanguageGroup"
691cdf0e10cSrcweir             case 936: mnFontDictBase = nInt; break;             // "nFDArray"
692cdf0e10cSrcweir             case 937: mnFDSelectBase = nInt; break;             // "nFDSelect"
693cdf0e10cSrcweir             default: break; // TODO: handle more numeric dictops?
694cdf0e10cSrcweir             }
695cdf0e10cSrcweir             break;
696cdf0e10cSrcweir         case 'a': { // array
697cdf0e10cSrcweir             switch( nOpId) {
698cdf0e10cSrcweir             case   5: maFontBBox.clear(); break;     // "FontBBox"
699cdf0e10cSrcweir             case 907: maFontMatrix.clear(); break; // "FontMatrix"
700cdf0e10cSrcweir             default: break; // TODO: reset other arrays?
701cdf0e10cSrcweir             }
702cdf0e10cSrcweir             for( int i = 0; i < size(); ++i ) {
703cdf0e10cSrcweir                 nVal = getVal(i);
704cdf0e10cSrcweir                 switch( nOpId) {
705cdf0e10cSrcweir                 case   5: maFontBBox.push_back( nVal); break;     // "FontBBox"
706cdf0e10cSrcweir                 case 907: maFontMatrix.push_back( nVal); break; // "FontMatrix"
707cdf0e10cSrcweir                 default: break; // TODO: handle more array dictops?
708cdf0e10cSrcweir                 }
709cdf0e10cSrcweir             }
710cdf0e10cSrcweir             clear();
711cdf0e10cSrcweir             } break;
712cdf0e10cSrcweir         case 'd': { // delta array
713cdf0e10cSrcweir             nVal = 0;
714cdf0e10cSrcweir             for( int i = 0; i < size(); ++i ) {
715cdf0e10cSrcweir                 nVal += getVal(i);
716cdf0e10cSrcweir                 switch( nOpId) {
717cdf0e10cSrcweir                 case   6: mpCffLocal->maBlueValues.push_back( nVal); break;     // "BlueValues"
718cdf0e10cSrcweir                 case   7: mpCffLocal->maOtherBlues.push_back( nVal); break;     // "OtherBlues"
719cdf0e10cSrcweir                 case   8: mpCffLocal->maFamilyBlues.push_back( nVal); break;    // "FamilyBlues"
720cdf0e10cSrcweir                 case   9: mpCffLocal->maFamilyOtherBlues.push_back( nVal); break;// "FamilyOtherBlues"
721cdf0e10cSrcweir                 case 912: mpCffLocal->maStemSnapH.push_back( nVal); break;      // "StemSnapH"
722cdf0e10cSrcweir                 case 913: mpCffLocal->maStemSnapV.push_back( nVal); break;      // "StemSnapV"
723cdf0e10cSrcweir                 default: break; // TODO: handle more delta-array dictops?
724cdf0e10cSrcweir                 }
725cdf0e10cSrcweir             }
726cdf0e10cSrcweir             clear();
727cdf0e10cSrcweir             } break;
728cdf0e10cSrcweir         case 's':   // stringid (SID)
729cdf0e10cSrcweir             nInt = popInt();
730cdf0e10cSrcweir             switch( nOpId ) {
731cdf0e10cSrcweir             case   2: mnFullNameSID = nInt; break;      // "FullName"
732cdf0e10cSrcweir             case   3: mnFamilyNameSID = nInt; break;    // "FamilyName"
733cdf0e10cSrcweir             case 938: mnFontNameSID = nInt; break;      // "FontName"
734cdf0e10cSrcweir             default: break; // TODO: handle more string dictops?
735cdf0e10cSrcweir             }
736cdf0e10cSrcweir             break;
737cdf0e10cSrcweir         case 'P':   // private dict
738cdf0e10cSrcweir             mpCffLocal->mnPrivDictBase = popInt();
739cdf0e10cSrcweir             mpCffLocal->mnPrivDictSize = popInt();
740cdf0e10cSrcweir             break;
741cdf0e10cSrcweir         case 'r': { // ROS operands
742cdf0e10cSrcweir             int nSid1 = popInt();
743cdf0e10cSrcweir             int nSid2 = popInt();
744cdf0e10cSrcweir             (void)nSid1; // TODO: use
745cdf0e10cSrcweir             (void)nSid2; // TODO: use
746cdf0e10cSrcweir             nVal = popVal();
747cdf0e10cSrcweir             mbCIDFont = true;
748cdf0e10cSrcweir             } break;
749cdf0e10cSrcweir         case 't':   // CharstringType
750cdf0e10cSrcweir             nInt = popInt();
751cdf0e10cSrcweir             setCharStringType( nInt );
752cdf0e10cSrcweir             break;
753cdf0e10cSrcweir         }
754cdf0e10cSrcweir 
755cdf0e10cSrcweir         return;
75628337f97SArrigo Marchiori     } else if( (c >= 32) || (c == 28) ) {
757cdf0e10cSrcweir //      --mpReadPtr;
758cdf0e10cSrcweir         read2push();
75928337f97SArrigo Marchiori     } else if( c == 29 ) { // we are looking at a 32-bit operand
760cdf0e10cSrcweir         ++mpReadPtr;            // skip 29
761cdf0e10cSrcweir         int nS32 = mpReadPtr[0] << 24;
762cdf0e10cSrcweir         nS32 += mpReadPtr[1] << 16;
763cdf0e10cSrcweir         nS32 += mpReadPtr[2] << 8;
764cdf0e10cSrcweir         nS32 += mpReadPtr[3] << 0;
765cdf0e10cSrcweir         if( (sizeof(nS32) != 4) && (nS32 & (1<<31)))
766cdf0e10cSrcweir             nS32 |= (~0U) << 31;    // assuming 2s complement
767cdf0e10cSrcweir         mpReadPtr += 4;
768cdf0e10cSrcweir         nVal = static_cast<ValType>(nS32);
769cdf0e10cSrcweir         push( nVal );
77028337f97SArrigo Marchiori     } else if( c == 30) { // we are looking at a real number operand
771cdf0e10cSrcweir         ++mpReadPtr; // skip 30
772cdf0e10cSrcweir         const RealType fReal = readRealVal();
773cdf0e10cSrcweir         // push value onto stack
774cdf0e10cSrcweir         nVal = fReal;
775cdf0e10cSrcweir         push( nVal);
776cdf0e10cSrcweir     }
777cdf0e10cSrcweir }
778cdf0e10cSrcweir 
779cdf0e10cSrcweir // --------------------------------------------------------------------
780cdf0e10cSrcweir 
read2push()781cdf0e10cSrcweir void CffSubsetterContext::read2push()
782cdf0e10cSrcweir {
783cdf0e10cSrcweir     ValType aVal = 0;
784cdf0e10cSrcweir 
785cdf0e10cSrcweir     const U8*& p = mpReadPtr;
786cdf0e10cSrcweir     const U8 c = *p;
78728337f97SArrigo Marchiori     if( c == 28 ) {         // -32767..+32767
788cdf0e10cSrcweir         short nS16 = (p[1] << 8) + p[2];
789cdf0e10cSrcweir         if( (sizeof(nS16) != 2) && (nS16 & (1<<15)))
790cdf0e10cSrcweir             nS16 |= (~0U) << 15;    // assuming 2s complement
791cdf0e10cSrcweir         aVal = nS16;
792cdf0e10cSrcweir         p += 3;
793cdf0e10cSrcweir     } else if( c <= 246 ) {     // -107..+107
794cdf0e10cSrcweir         aVal = static_cast<ValType>(p[0] - 139);
795cdf0e10cSrcweir         p += 1;
796cdf0e10cSrcweir     } else if( c <= 250 ) {     // +108..+1131
797cdf0e10cSrcweir         aVal = static_cast<ValType>(((p[0] << 8) + p[1]) - 63124);
798cdf0e10cSrcweir         p += 2;
799cdf0e10cSrcweir     } else if( c <= 254 ) {     // -108..-1131
800cdf0e10cSrcweir         aVal = static_cast<ValType>(64148 - ((p[0] << 8) + p[1]));
801cdf0e10cSrcweir         p += 2;
802cdf0e10cSrcweir     } else /*if( c == 255)*/ {  // Fixed16.16
803cdf0e10cSrcweir         int nS32 = (p[1] << 24) + (p[2] << 16) + (p[3] << 8) + p[4];
804cdf0e10cSrcweir         if( (sizeof(nS32) != 2) && (nS32 & (1<<31)))
805cdf0e10cSrcweir             nS32 |= (~0U) << 31;    // assuming 2s complement
806cdf0e10cSrcweir         aVal = static_cast<ValType>(nS32 * (1.0 / 0x10000));
807cdf0e10cSrcweir         p += 5;
808cdf0e10cSrcweir     }
809cdf0e10cSrcweir 
810cdf0e10cSrcweir     push( aVal);
811cdf0e10cSrcweir }
812cdf0e10cSrcweir 
813cdf0e10cSrcweir // --------------------------------------------------------------------
814cdf0e10cSrcweir 
writeType1Val(ValType aVal)815cdf0e10cSrcweir void CffSubsetterContext::writeType1Val( ValType aVal)
816cdf0e10cSrcweir {
817cdf0e10cSrcweir     U8* pOut = mpWritePtr;
818cdf0e10cSrcweir 
819cdf0e10cSrcweir     int nInt = static_cast<int>(aVal);
820cdf0e10cSrcweir     static const int nOutCharstrType = 1;
821cdf0e10cSrcweir     if( (nInt != aVal) && (nOutCharstrType == 2)) {
822cdf0e10cSrcweir         // numtype==255 means int32 for Type1, but 16.16 for Type2 charstrings!!!
823cdf0e10cSrcweir         *(pOut++) = 255;                            // Fixed 16.16
824cdf0e10cSrcweir         *(pOut++) = static_cast<U8>(nInt >> 8);
825cdf0e10cSrcweir         *(pOut++) = static_cast<U8>(nInt);
826cdf0e10cSrcweir         nInt = static_cast<int>(aVal * 0x10000) & 0xFFFF;
827cdf0e10cSrcweir         *(pOut++) = static_cast<U8>(nInt >> 8);
828cdf0e10cSrcweir         *(pOut++) = static_cast<U8>(nInt);
829cdf0e10cSrcweir     } else if( (nInt >= -107) && (nInt <= +107)) {
830cdf0e10cSrcweir         *(pOut++) = static_cast<U8>(nInt + 139);    // -107..+107
831cdf0e10cSrcweir     } else if( (nInt >= -1131) && (nInt <= +1131)) {
832cdf0e10cSrcweir         if( nInt >= 0)
833cdf0e10cSrcweir             nInt += 63124;                          // +108..+1131
834cdf0e10cSrcweir         else
835cdf0e10cSrcweir             nInt = 64148 - nInt;                    // -108..-1131
836cdf0e10cSrcweir         *(pOut++) = static_cast<U8>(nInt >> 8);
837cdf0e10cSrcweir         *(pOut++) = static_cast<U8>(nInt);
838cdf0e10cSrcweir     } else if( nOutCharstrType == 1) {
839cdf0e10cSrcweir         // numtype==255 means int32 for Type1, but 16.16 for Type2 charstrings!!!
840cdf0e10cSrcweir         *(pOut++) = 255;
841cdf0e10cSrcweir         *(pOut++) = static_cast<U8>(nInt >> 24);
842cdf0e10cSrcweir         *(pOut++) = static_cast<U8>(nInt >> 16);
843cdf0e10cSrcweir         *(pOut++) = static_cast<U8>(nInt >> 8);
844cdf0e10cSrcweir         *(pOut++) = static_cast<U8>(nInt);
845cdf0e10cSrcweir     }
846cdf0e10cSrcweir 
847cdf0e10cSrcweir     mpWritePtr = pOut;
848cdf0e10cSrcweir }
849cdf0e10cSrcweir 
850cdf0e10cSrcweir // --------------------------------------------------------------------
851cdf0e10cSrcweir 
pop2write(void)852cdf0e10cSrcweir inline void CffSubsetterContext::pop2write( void)
853cdf0e10cSrcweir {
854cdf0e10cSrcweir     const ValType aVal = popVal();
855cdf0e10cSrcweir     writeType1Val( aVal);
856cdf0e10cSrcweir }
857cdf0e10cSrcweir 
858cdf0e10cSrcweir // --------------------------------------------------------------------
859cdf0e10cSrcweir 
writeTypeOp(int nTypeOp)860cdf0e10cSrcweir inline void CffSubsetterContext::writeTypeOp( int nTypeOp)
861cdf0e10cSrcweir {
862cdf0e10cSrcweir     *(mpWritePtr++) = static_cast<U8>(nTypeOp);
863cdf0e10cSrcweir }
864cdf0e10cSrcweir 
865cdf0e10cSrcweir // --------------------------------------------------------------------
866cdf0e10cSrcweir 
writeTypeEsc(int nTypeEsc)867cdf0e10cSrcweir inline void CffSubsetterContext::writeTypeEsc( int nTypeEsc)
868cdf0e10cSrcweir {
869cdf0e10cSrcweir     *(mpWritePtr++) = TYPE1OP::T1ESC;
870cdf0e10cSrcweir     *(mpWritePtr++) = static_cast<U8>(nTypeEsc);
871cdf0e10cSrcweir }
872cdf0e10cSrcweir 
873cdf0e10cSrcweir // --------------------------------------------------------------------
874cdf0e10cSrcweir 
pop2MultiWrite(int nArgsPerTypo,int nTypeOp,int nTypeXor)875cdf0e10cSrcweir void CffSubsetterContext::pop2MultiWrite( int nArgsPerTypo, int nTypeOp, int nTypeXor)
876cdf0e10cSrcweir {
877cdf0e10cSrcweir     for( int i = 0; i < mnStackIdx;) {
878cdf0e10cSrcweir         for( int j = 0; j < nArgsPerTypo; ++j) {
879cdf0e10cSrcweir             const ValType aVal = mnValStack[i+j];
880cdf0e10cSrcweir             writeType1Val( aVal);
881cdf0e10cSrcweir         }
882cdf0e10cSrcweir         i += nArgsPerTypo;
883cdf0e10cSrcweir         writeTypeOp( nTypeOp);
884cdf0e10cSrcweir         nTypeOp ^= nTypeXor;    // for toggling vlineto/hlineto
885cdf0e10cSrcweir     }
886cdf0e10cSrcweir     clear();
887cdf0e10cSrcweir }
888cdf0e10cSrcweir 
889cdf0e10cSrcweir // --------------------------------------------------------------------
890cdf0e10cSrcweir 
popAll2Write(int nTypeOp)891cdf0e10cSrcweir void CffSubsetterContext::popAll2Write( int nTypeOp)
892cdf0e10cSrcweir {
893cdf0e10cSrcweir     // pop in reverse order, then write
894cdf0e10cSrcweir     for( int i = 0; i < mnStackIdx; ++i) {
895cdf0e10cSrcweir         const ValType aVal = mnValStack[i];
896cdf0e10cSrcweir         writeType1Val( aVal);
897cdf0e10cSrcweir     }
898cdf0e10cSrcweir     clear();
899cdf0e10cSrcweir     writeTypeOp( nTypeOp);
900cdf0e10cSrcweir }
901cdf0e10cSrcweir 
902cdf0e10cSrcweir // --------------------------------------------------------------------
903cdf0e10cSrcweir 
writeCurveTo(int nStackPos,int nIX1,int nIY1,int nIX2,int nIY2,int nIX3,int nIY3)904cdf0e10cSrcweir void CffSubsetterContext::writeCurveTo( int nStackPos,
905cdf0e10cSrcweir     int nIX1, int nIY1, int nIX2, int nIY2, int nIX3, int nIY3)
906cdf0e10cSrcweir {
907cdf0e10cSrcweir     // get the values from the stack
908cdf0e10cSrcweir     const ValType nDX1 = nIX1 ? mnValStack[ nStackPos+nIX1 ] : 0;
909cdf0e10cSrcweir     const ValType nDY1 = nIY1 ? mnValStack[ nStackPos+nIY1 ] : 0;
910cdf0e10cSrcweir     const ValType nDX2 = nIX2 ? mnValStack[ nStackPos+nIX2 ] : 0;
911cdf0e10cSrcweir     const ValType nDY2 = nIY2 ? mnValStack[ nStackPos+nIY2 ] : 0;
912cdf0e10cSrcweir     const ValType nDX3 = nIX3 ? mnValStack[ nStackPos+nIX3 ] : 0;
913cdf0e10cSrcweir     const ValType nDY3 = nIY3 ? mnValStack[ nStackPos+nIY3 ] : 0;
914cdf0e10cSrcweir 
915cdf0e10cSrcweir     // emit the curveto operator and operands
916cdf0e10cSrcweir     // TODO: determine the most efficient curveto operator
917cdf0e10cSrcweir     // TODO: depending on type1op or type2op target
918cdf0e10cSrcweir     writeType1Val( nDX1 );
919cdf0e10cSrcweir     writeType1Val( nDY1 );
920cdf0e10cSrcweir     writeType1Val( nDX2 );
921cdf0e10cSrcweir     writeType1Val( nDY2 );
922cdf0e10cSrcweir     writeType1Val( nDX3 );
923cdf0e10cSrcweir     writeType1Val( nDY3 );
924cdf0e10cSrcweir     writeTypeOp( TYPE1OP::RCURVETO );
925cdf0e10cSrcweir }
926cdf0e10cSrcweir 
927cdf0e10cSrcweir // --------------------------------------------------------------------
928cdf0e10cSrcweir 
convertOneTypeOp(void)929cdf0e10cSrcweir void CffSubsetterContext::convertOneTypeOp( void)
930cdf0e10cSrcweir {
931cdf0e10cSrcweir     const int nType2Op = *(mpReadPtr++);
932cdf0e10cSrcweir 
933cdf0e10cSrcweir     int i, nInt; // prevent WAE for declarations inside switch cases
934cdf0e10cSrcweir     // convert each T2op
935cdf0e10cSrcweir     switch( nType2Op) {
936cdf0e10cSrcweir     case TYPE2OP::T2ESC:
937cdf0e10cSrcweir         convertOneTypeEsc();
938cdf0e10cSrcweir         break;
939cdf0e10cSrcweir     case TYPE2OP::HSTEM:
940cdf0e10cSrcweir     case TYPE2OP::VSTEM:
941cdf0e10cSrcweir         addHints( nType2Op == TYPE2OP::VSTEM );
942cdf0e10cSrcweir #ifndef IGNORE_HINTS
943cdf0e10cSrcweir         for( i = 0; i < mnHintSize; i+=2 ) {
944cdf0e10cSrcweir             writeType1Val( mnHintStack[i]);
945cdf0e10cSrcweir             writeType1Val( mnHintStack[i+1] - mnHintStack[i]);
946cdf0e10cSrcweir             writeTypeOp( nType2Op );
947cdf0e10cSrcweir         }
948cdf0e10cSrcweir #endif // IGNORE_HINTS
949cdf0e10cSrcweir         break;
950cdf0e10cSrcweir     case TYPE2OP::HSTEMHM:
951cdf0e10cSrcweir     case TYPE2OP::VSTEMHM:
952cdf0e10cSrcweir         addHints( nType2Op == TYPE2OP::VSTEMHM);
953cdf0e10cSrcweir         break;
954cdf0e10cSrcweir     case TYPE2OP::CNTRMASK:
955cdf0e10cSrcweir         // TODO: replace cntrmask with vstem3/hstem3
956cdf0e10cSrcweir         addHints( true);
957cdf0e10cSrcweir #ifdef IGNORE_HINTS
958cdf0e10cSrcweir         mpReadPtr += (mnHintSize + 15) / 16;
959cdf0e10cSrcweir         mbIgnoreHints = true;
960cdf0e10cSrcweir #else
961cdf0e10cSrcweir         {
962cdf0e10cSrcweir         U8 nMaskBit = 0;
963cdf0e10cSrcweir         U8 nMaskByte = 0;
964cdf0e10cSrcweir         for( i = 0; i < mnHintSize; i+=2, nMaskBit>>=1) {
965cdf0e10cSrcweir             if( !nMaskBit) {
966cdf0e10cSrcweir                 nMaskByte = *(mpReadPtr++);
967cdf0e10cSrcweir                 nMaskBit = 0x80;
968cdf0e10cSrcweir             }
969cdf0e10cSrcweir             if( !(nMaskByte & nMaskBit))
970cdf0e10cSrcweir                 continue;
971cdf0e10cSrcweir             if( i >= 8*(int)sizeof(mnCntrMask))
972cdf0e10cSrcweir                 mbIgnoreHints = true;
973cdf0e10cSrcweir             if( mbIgnoreHints)
974cdf0e10cSrcweir                 continue;
975cdf0e10cSrcweir             mnCntrMask |= (1U << i);
976cdf0e10cSrcweir         }
977cdf0e10cSrcweir         }
978cdf0e10cSrcweir #endif
979cdf0e10cSrcweir         break;
980cdf0e10cSrcweir     case TYPE2OP::HINTMASK:
981cdf0e10cSrcweir         addHints( true);
982cdf0e10cSrcweir #ifdef IGNORE_HINTS
983cdf0e10cSrcweir         mpReadPtr += (mnHintSize + 15) / 16;
984cdf0e10cSrcweir #else
985cdf0e10cSrcweir         {
986cdf0e10cSrcweir         long nHintMask = 0;
987cdf0e10cSrcweir         int nCntrBits[2] = {0,0};
988cdf0e10cSrcweir         U8 nMaskBit = 0;
989cdf0e10cSrcweir         U8 nMaskByte = 0;
990cdf0e10cSrcweir         for( i = 0; i < mnHintSize; i+=2, nMaskBit>>=1) {
991cdf0e10cSrcweir             if( !nMaskBit) {
992cdf0e10cSrcweir                 nMaskByte = *(mpReadPtr++);
993cdf0e10cSrcweir                 nMaskBit = 0x80;
994cdf0e10cSrcweir             }
995cdf0e10cSrcweir             if( !(nMaskByte & nMaskBit))
996cdf0e10cSrcweir                 continue;
997cdf0e10cSrcweir             if( i >= 8*(int)sizeof(nHintMask))
998cdf0e10cSrcweir                 mbIgnoreHints = true;
999cdf0e10cSrcweir             if( mbIgnoreHints)
1000cdf0e10cSrcweir                 continue;
1001cdf0e10cSrcweir             nHintMask |= (1U << i);
1002cdf0e10cSrcweir             nCntrBits[ i < mnHorzHintSize] += (mnCntrMask >> i) & 1;
1003cdf0e10cSrcweir         }
1004cdf0e10cSrcweir 
1005cdf0e10cSrcweir         mbIgnoreHints |= (nCntrBits[0] && (nCntrBits[0] != 3));
1006cdf0e10cSrcweir         mbIgnoreHints |= (nCntrBits[1] && (nCntrBits[1] != 3));
1007cdf0e10cSrcweir         if( mbIgnoreHints)
1008cdf0e10cSrcweir             break;
1009cdf0e10cSrcweir 
1010cdf0e10cSrcweir         for( i = 0; i < mnHintSize; i+=2) {
1011cdf0e10cSrcweir             if( !(nHintMask & (1U << i)))
1012cdf0e10cSrcweir                 continue;
1013cdf0e10cSrcweir             writeType1Val( mnHintStack[i]);
1014cdf0e10cSrcweir             writeType1Val( mnHintStack[i+1] - mnHintStack[i]);
1015cdf0e10cSrcweir             const bool bHorz = (i < mnHorzHintSize);
1016cdf0e10cSrcweir             if( !nCntrBits[ bHorz])
1017cdf0e10cSrcweir                 writeTypeOp( bHorz ? TYPE1OP::HSTEM : TYPE1OP::VSTEM);
1018cdf0e10cSrcweir             else if( !--nCntrBits[ bHorz])
1019cdf0e10cSrcweir                 writeTypeEsc( bHorz ? TYPE1OP::HSTEM3 : TYPE1OP::VSTEM3);
1020cdf0e10cSrcweir         }
1021cdf0e10cSrcweir         }
1022cdf0e10cSrcweir #endif
1023cdf0e10cSrcweir         break;
1024cdf0e10cSrcweir     case TYPE2OP::CALLSUBR:
1025cdf0e10cSrcweir     case TYPE2OP::CALLGSUBR:
1026cdf0e10cSrcweir         {
1027cdf0e10cSrcweir         nInt = popInt();
1028cdf0e10cSrcweir         const bool bGlobal = (nType2Op == TYPE2OP::CALLGSUBR);
1029cdf0e10cSrcweir         callType2Subr( bGlobal, nInt);
1030cdf0e10cSrcweir         }
1031cdf0e10cSrcweir         break;
1032cdf0e10cSrcweir     case TYPE2OP::RETURN:
1033cdf0e10cSrcweir         // TODO: check that we are in a subroutine
1034cdf0e10cSrcweir         return;
1035cdf0e10cSrcweir     case TYPE2OP::VMOVETO:
1036cdf0e10cSrcweir     case TYPE2OP::HMOVETO:
1037cdf0e10cSrcweir         if( mbNeedClose)
1038cdf0e10cSrcweir             writeTypeOp( TYPE1OP::CLOSEPATH);
1039cdf0e10cSrcweir         else
1040cdf0e10cSrcweir             updateWidth( size() > 1);
1041cdf0e10cSrcweir         mbNeedClose = true;
1042cdf0e10cSrcweir         pop2MultiWrite( 1, nType2Op);
1043cdf0e10cSrcweir         break;
1044cdf0e10cSrcweir     case TYPE2OP::VLINETO:
1045cdf0e10cSrcweir     case TYPE2OP::HLINETO:
1046cdf0e10cSrcweir         pop2MultiWrite( 1, nType2Op,
1047cdf0e10cSrcweir             TYPE1OP::VLINETO ^ TYPE1OP::HLINETO);
1048cdf0e10cSrcweir         break;
1049cdf0e10cSrcweir     case TYPE2OP::RMOVETO:
1050cdf0e10cSrcweir         // TODO: convert rmoveto to vlineto/hlineto if possible
1051cdf0e10cSrcweir         if( mbNeedClose)
1052cdf0e10cSrcweir             writeTypeOp( TYPE1OP::CLOSEPATH);
1053cdf0e10cSrcweir         else
1054cdf0e10cSrcweir             updateWidth( size() > 2);
1055cdf0e10cSrcweir         mbNeedClose = true;
1056cdf0e10cSrcweir         pop2MultiWrite( 2, nType2Op);
1057cdf0e10cSrcweir         break;
1058cdf0e10cSrcweir     case TYPE2OP::RLINETO:
1059cdf0e10cSrcweir         // TODO: convert rlineto to vlineto/hlineto if possible
1060cdf0e10cSrcweir         pop2MultiWrite( 2, nType2Op);
1061cdf0e10cSrcweir         break;
1062cdf0e10cSrcweir     case TYPE2OP::RCURVETO:
1063cdf0e10cSrcweir         // TODO: convert rcurveto to vh/hv/hh/vv-curveto if possible
1064cdf0e10cSrcweir         pop2MultiWrite( 6, nType2Op);
1065cdf0e10cSrcweir         break;
1066cdf0e10cSrcweir     case TYPE2OP::RCURVELINE:
1067cdf0e10cSrcweir         i = 0;
1068cdf0e10cSrcweir         while( (i += 6) <= mnStackIdx)
1069cdf0e10cSrcweir             writeCurveTo( i, -6, -5, -4, -3, -2, -1 );
1070cdf0e10cSrcweir         i -= 6;
1071cdf0e10cSrcweir         while( (i += 2) <= mnStackIdx) {
1072cdf0e10cSrcweir             writeType1Val( mnValStack[i-2]);
1073cdf0e10cSrcweir             writeType1Val( mnValStack[i-1]);
1074cdf0e10cSrcweir             writeTypeOp( TYPE2OP::RLINETO);
1075cdf0e10cSrcweir         }
1076cdf0e10cSrcweir         clear();
1077cdf0e10cSrcweir         break;
1078cdf0e10cSrcweir     case TYPE2OP::RLINECURVE:
1079cdf0e10cSrcweir         i = 0;
1080cdf0e10cSrcweir         while( (i += 2) <= mnStackIdx-6) {
1081cdf0e10cSrcweir             writeType1Val( mnValStack[i-2]);
1082cdf0e10cSrcweir             writeType1Val( mnValStack[i-1]);
1083cdf0e10cSrcweir             writeTypeOp( TYPE2OP::RLINETO);
1084cdf0e10cSrcweir         }
1085cdf0e10cSrcweir         i -= 2;
1086cdf0e10cSrcweir         while( (i += 6) <= mnStackIdx)
1087cdf0e10cSrcweir             writeCurveTo( i, -6, -5, -4, -3, -2, -1 );
1088cdf0e10cSrcweir         clear();
1089cdf0e10cSrcweir         break;
1090cdf0e10cSrcweir     case TYPE2OP::VHCURVETO:
1091cdf0e10cSrcweir     case TYPE2OP::HVCURVETO:
1092cdf0e10cSrcweir         {
1093cdf0e10cSrcweir         bool bVert = (nType2Op == TYPE2OP::VHCURVETO);
1094cdf0e10cSrcweir         i = 0;
1095cdf0e10cSrcweir         nInt = 0;
1096cdf0e10cSrcweir         if( mnStackIdx & 1 )
1097cdf0e10cSrcweir             nInt = static_cast<int>(mnValStack[ --mnStackIdx ]);
1098cdf0e10cSrcweir         while( (i += 4) <= mnStackIdx) {
1099cdf0e10cSrcweir             // TODO: use writeCurveTo()
1100cdf0e10cSrcweir             if( bVert ) writeType1Val( 0 );
1101cdf0e10cSrcweir             writeType1Val( mnValStack[i-4] );
1102cdf0e10cSrcweir             if( !bVert ) writeType1Val( 0);
1103cdf0e10cSrcweir             writeType1Val( mnValStack[i-3] );
1104cdf0e10cSrcweir             writeType1Val( mnValStack[i-2] );
1105cdf0e10cSrcweir             if( !bVert ) writeType1Val( static_cast<ValType>((i==mnStackIdx) ? nInt : 0) );
1106cdf0e10cSrcweir             writeType1Val( mnValStack[i-1] );
1107cdf0e10cSrcweir             if( bVert ) writeType1Val( static_cast<ValType>((i==mnStackIdx) ? nInt : 0) );
1108cdf0e10cSrcweir             bVert = !bVert;
1109cdf0e10cSrcweir             writeTypeOp( TYPE2OP::RCURVETO);
1110cdf0e10cSrcweir         }
1111cdf0e10cSrcweir         }
1112cdf0e10cSrcweir         clear();
1113cdf0e10cSrcweir         break;
1114cdf0e10cSrcweir     case TYPE2OP::HHCURVETO:
1115cdf0e10cSrcweir         i = (mnStackIdx & 1);
1116cdf0e10cSrcweir         while( (i += 4) <= mnStackIdx) {
1117cdf0e10cSrcweir             if( i != 5)
1118cdf0e10cSrcweir                 writeCurveTo( i, -4,  0, -3, -2, -1, 0);
1119cdf0e10cSrcweir             else
1120cdf0e10cSrcweir                 writeCurveTo( i, -4, -5, -3, -2, -1, 0);
1121cdf0e10cSrcweir         }
1122cdf0e10cSrcweir         clear();
1123cdf0e10cSrcweir         break;
1124cdf0e10cSrcweir     case TYPE2OP::VVCURVETO:
1125cdf0e10cSrcweir         i = (mnStackIdx & 1);
1126cdf0e10cSrcweir         while( (i += 4) <= mnStackIdx) {
1127cdf0e10cSrcweir             if( i != 5)
1128cdf0e10cSrcweir                 writeCurveTo( i,  0, -4, -3, -2, 0, -1);
1129cdf0e10cSrcweir             else
1130cdf0e10cSrcweir                 writeCurveTo( i, -5, -4, -3, -2, 0, -1);
1131cdf0e10cSrcweir         }
1132cdf0e10cSrcweir         clear();
1133cdf0e10cSrcweir         break;
1134cdf0e10cSrcweir     case TYPE2OP::ENDCHAR:
1135cdf0e10cSrcweir         if( mbNeedClose)
1136cdf0e10cSrcweir             writeTypeOp( TYPE1OP::CLOSEPATH);
1137cdf0e10cSrcweir         else
1138cdf0e10cSrcweir             updateWidth( size() >= 1);
1139cdf0e10cSrcweir         // mbNeedClose = true;
1140cdf0e10cSrcweir         writeTypeOp( TYPE1OP::ENDCHAR);
1141cdf0e10cSrcweir         break;
1142cdf0e10cSrcweir     default:
1143cdf0e10cSrcweir         if( ((nType2Op >= 32) && (nType2Op <= 255)) || (nType2Op == 28)) {
1144cdf0e10cSrcweir             --mpReadPtr;
1145cdf0e10cSrcweir             read2push();
1146cdf0e10cSrcweir         } else {
1147cdf0e10cSrcweir             popAll2Write( nType2Op);
1148cdf0e10cSrcweir             assert( false); // TODO?
1149cdf0e10cSrcweir         }
1150cdf0e10cSrcweir         break;
1151cdf0e10cSrcweir     }
1152cdf0e10cSrcweir }
1153cdf0e10cSrcweir 
1154cdf0e10cSrcweir // --------------------------------------------------------------------
1155cdf0e10cSrcweir 
convertOneTypeEsc(void)1156cdf0e10cSrcweir void CffSubsetterContext::convertOneTypeEsc( void)
1157cdf0e10cSrcweir {
1158cdf0e10cSrcweir     const int nType2Esc = *(mpReadPtr++);
1159cdf0e10cSrcweir     ValType* pTop = &mnValStack[ mnStackIdx-1];
1160cdf0e10cSrcweir     // convert each T2op
1161cdf0e10cSrcweir     switch( nType2Esc) {
1162cdf0e10cSrcweir     case TYPE2OP::AND:
1163cdf0e10cSrcweir         assert( mnStackIdx >= 2 );
1164cdf0e10cSrcweir         pTop[0] = static_cast<ValType>(static_cast<int>(pTop[0]) & static_cast<int>(pTop[-1]));
1165cdf0e10cSrcweir         --mnStackIdx;
1166cdf0e10cSrcweir         break;
1167cdf0e10cSrcweir     case TYPE2OP::OR:
1168cdf0e10cSrcweir         assert( mnStackIdx >= 2 );
1169cdf0e10cSrcweir         pTop[0] = static_cast<ValType>(static_cast<int>(pTop[0]) | static_cast<int>(pTop[-1]));
1170cdf0e10cSrcweir         --mnStackIdx;
1171cdf0e10cSrcweir         break;
1172cdf0e10cSrcweir     case TYPE2OP::NOT:
1173cdf0e10cSrcweir         assert( mnStackIdx >= 1 );
1174cdf0e10cSrcweir         pTop[0] = (pTop[0] == 0);
1175cdf0e10cSrcweir         break;
1176cdf0e10cSrcweir     case TYPE2OP::ABS:
1177cdf0e10cSrcweir         assert( mnStackIdx >= 1 );
1178cdf0e10cSrcweir         if( pTop[0] >= 0)
1179cdf0e10cSrcweir             break;
1180cdf0e10cSrcweir         // fall through
1181cdf0e10cSrcweir     case TYPE2OP::NEG:
1182cdf0e10cSrcweir         assert( mnStackIdx >= 1 );
1183cdf0e10cSrcweir         pTop[0] = -pTop[0];
1184cdf0e10cSrcweir         break;
1185cdf0e10cSrcweir     case TYPE2OP::ADD:
1186cdf0e10cSrcweir         assert( mnStackIdx >= 2 );
1187cdf0e10cSrcweir         pTop[0] += pTop[-1];
1188cdf0e10cSrcweir         --mnStackIdx;
1189cdf0e10cSrcweir         break;
1190cdf0e10cSrcweir     case TYPE2OP::SUB:
1191cdf0e10cSrcweir         assert( mnStackIdx >= 2 );
1192cdf0e10cSrcweir         pTop[0] -= pTop[-1];
1193cdf0e10cSrcweir         --mnStackIdx;
1194cdf0e10cSrcweir         break;
1195cdf0e10cSrcweir     case TYPE2OP::MUL:
1196cdf0e10cSrcweir         assert( mnStackIdx >= 2 );
1197cdf0e10cSrcweir         if( pTop[-1])
1198cdf0e10cSrcweir             pTop[0] *= pTop[-1];
1199cdf0e10cSrcweir         --mnStackIdx;
1200cdf0e10cSrcweir         break;
1201cdf0e10cSrcweir     case TYPE2OP::DIV:
1202cdf0e10cSrcweir         assert( mnStackIdx >= 2 );
1203cdf0e10cSrcweir         if( pTop[-1])
1204cdf0e10cSrcweir             pTop[0] /= pTop[-1];
1205cdf0e10cSrcweir         --mnStackIdx;
1206cdf0e10cSrcweir         break;
1207cdf0e10cSrcweir     case TYPE2OP::EQ:
1208cdf0e10cSrcweir         assert( mnStackIdx >= 2 );
1209cdf0e10cSrcweir         pTop[0] = (pTop[0] == pTop[-1]);
1210cdf0e10cSrcweir         --mnStackIdx;
1211cdf0e10cSrcweir         break;
1212cdf0e10cSrcweir     case TYPE2OP::DROP:
1213cdf0e10cSrcweir         assert( mnStackIdx >= 1 );
1214cdf0e10cSrcweir         --mnStackIdx;
1215cdf0e10cSrcweir         break;
1216cdf0e10cSrcweir     case TYPE2OP::PUT: {
1217cdf0e10cSrcweir         assert( mnStackIdx >= 2 );
1218cdf0e10cSrcweir         const int nIdx = static_cast<int>(pTop[0]);
1219cdf0e10cSrcweir         assert( nIdx >= 0 );
1220cdf0e10cSrcweir         assert( nIdx < NMAXTRANS );
1221cdf0e10cSrcweir         mnTransVals[ nIdx] = pTop[-1];
1222cdf0e10cSrcweir         mnStackIdx -= 2;
1223cdf0e10cSrcweir         break;
1224cdf0e10cSrcweir         }
1225cdf0e10cSrcweir     case TYPE2OP::GET: {
1226cdf0e10cSrcweir         assert( mnStackIdx >= 1 );
1227cdf0e10cSrcweir         const int nIdx = static_cast<int>(pTop[0]);
1228cdf0e10cSrcweir         assert( nIdx >= 0 );
1229cdf0e10cSrcweir         assert( nIdx < NMAXTRANS );
1230cdf0e10cSrcweir         pTop[0] = mnTransVals[ nIdx ];
1231cdf0e10cSrcweir         break;
1232cdf0e10cSrcweir         }
1233cdf0e10cSrcweir     case TYPE2OP::IFELSE: {
1234cdf0e10cSrcweir         assert( mnStackIdx >= 4 );
1235cdf0e10cSrcweir         if( pTop[-1] > pTop[0] )
1236cdf0e10cSrcweir             pTop[-3] = pTop[-2];
1237cdf0e10cSrcweir         mnStackIdx -= 3;
1238cdf0e10cSrcweir         break;
1239cdf0e10cSrcweir         }
1240cdf0e10cSrcweir     case TYPE2OP::RANDOM:
1241cdf0e10cSrcweir         pTop[+1] = 1234; // TODO
1242cdf0e10cSrcweir         ++mnStackIdx;
1243cdf0e10cSrcweir         break;
1244cdf0e10cSrcweir     case TYPE2OP::SQRT:
1245cdf0e10cSrcweir         // TODO: implement
1246cdf0e10cSrcweir         break;
1247cdf0e10cSrcweir     case TYPE2OP::DUP:
1248cdf0e10cSrcweir         assert( mnStackIdx >= 1 );
1249cdf0e10cSrcweir         pTop[+1] = pTop[0];
1250cdf0e10cSrcweir         ++mnStackIdx;
1251cdf0e10cSrcweir         break;
1252cdf0e10cSrcweir     case TYPE2OP::EXCH: {
1253cdf0e10cSrcweir         assert( mnStackIdx >= 2 );
1254cdf0e10cSrcweir         const ValType nVal = pTop[0];
1255cdf0e10cSrcweir         pTop[0] = pTop[-1];
1256cdf0e10cSrcweir         pTop[-1] = nVal;
1257cdf0e10cSrcweir         break;
1258cdf0e10cSrcweir         }
1259cdf0e10cSrcweir     case TYPE2OP::INDEX: {
1260cdf0e10cSrcweir         assert( mnStackIdx >= 1 );
1261cdf0e10cSrcweir         const int nVal = static_cast<int>(pTop[0]);
1262cdf0e10cSrcweir         assert( nVal >= 0 );
1263cdf0e10cSrcweir         assert( nVal < mnStackIdx-1 );
1264cdf0e10cSrcweir         pTop[0] = pTop[-1-nVal];
1265cdf0e10cSrcweir         break;
1266cdf0e10cSrcweir         }
1267cdf0e10cSrcweir     case TYPE2OP::ROLL: {
1268cdf0e10cSrcweir         assert( mnStackIdx >= 1 );
1269cdf0e10cSrcweir         const int nNum = static_cast<int>(pTop[0]);
1270cdf0e10cSrcweir         assert( nNum >= 0);
1271cdf0e10cSrcweir         assert( nNum < mnStackIdx-2 );
1272cdf0e10cSrcweir         (void)nNum; // TODO: implement
1273cdf0e10cSrcweir         const int nOfs = static_cast<int>(pTop[-1]);
1274cdf0e10cSrcweir         mnStackIdx -= 2;
1275cdf0e10cSrcweir         (void)nOfs;// TODO: implement
1276cdf0e10cSrcweir         break;
1277cdf0e10cSrcweir         }
1278cdf0e10cSrcweir     case TYPE2OP::HFLEX1: {
1279cdf0e10cSrcweir             assert( mnStackIdx == 9);
1280cdf0e10cSrcweir #if 0 // emulate hflex1 as straight line
1281cdf0e10cSrcweir             const ValType* pX = &mnValStack[ mnStackIdx];
1282cdf0e10cSrcweir             const ValType fDX = pX[-9] + pX[-7] + pX[-5] + pX[-4] + pX[-3] + pX[-1];
1283cdf0e10cSrcweir             writeType1Val( fDX);
1284cdf0e10cSrcweir             writeTypeOp( TYPE1OP::HLINETO);
1285cdf0e10cSrcweir #else // emulate hflex1 as two curves
1286cdf0e10cSrcweir             writeCurveTo( mnStackIdx, -9, -8, -7, -6, -5,  0);
1287cdf0e10cSrcweir             writeCurveTo( mnStackIdx, -4,  0, -3, -2, -1,  0);
1288cdf0e10cSrcweir         // TODO: emulate hflex1 using othersubr call
1289cdf0e10cSrcweir #endif
1290cdf0e10cSrcweir             mnStackIdx -= 9;
1291cdf0e10cSrcweir         }
1292cdf0e10cSrcweir         break;
1293cdf0e10cSrcweir     case TYPE2OP::HFLEX: {
1294cdf0e10cSrcweir             assert( mnStackIdx == 7);
1295cdf0e10cSrcweir             ValType* pX = &mnValStack[ mnStackIdx];
1296cdf0e10cSrcweir #if 0 // emulate hflex as straight line
1297cdf0e10cSrcweir             const ValType fDX = pX[-7] + pX[-6] + pX[-4] + pX[-3] + pX[-2] + pX[-1];
1298cdf0e10cSrcweir             writeType1Val( fDX);
1299cdf0e10cSrcweir             writeTypeOp( TYPE1OP::HLINETO);
1300cdf0e10cSrcweir #else // emulate hflex as two curves
1301cdf0e10cSrcweir             pX[+1] = -pX[-5]; // temp: +dy5==-dy2
1302cdf0e10cSrcweir             writeCurveTo( mnStackIdx, -7,  0, -6, -5, -4,  0);
1303cdf0e10cSrcweir             writeCurveTo( mnStackIdx, -3,  0, -2, +1, -1,  0);
1304cdf0e10cSrcweir         // TODO: emulate hflex using othersubr call
1305cdf0e10cSrcweir #endif
1306cdf0e10cSrcweir             mnStackIdx -= 7;
1307cdf0e10cSrcweir         }
1308cdf0e10cSrcweir         break;
1309cdf0e10cSrcweir     case TYPE2OP::FLEX: {
1310cdf0e10cSrcweir             assert( mnStackIdx == 13 );
1311cdf0e10cSrcweir             writeCurveTo( mnStackIdx, -13, -12, -11, -10, -9, -8 );
1312cdf0e10cSrcweir             writeCurveTo( mnStackIdx,  -7,  -6,  -5,  -4, -3, -2 );
1313cdf0e10cSrcweir             const ValType nFlexDepth =  mnValStack[ mnStackIdx-1 ];
1314cdf0e10cSrcweir             (void)nFlexDepth; // ignoring nFlexDepth
1315cdf0e10cSrcweir             mnStackIdx -= 13;
1316cdf0e10cSrcweir         }
1317cdf0e10cSrcweir         break;
1318cdf0e10cSrcweir     case TYPE2OP::FLEX1: {
1319cdf0e10cSrcweir             assert( mnStackIdx == 11 );
1320cdf0e10cSrcweir             // write the first part of the flex1-hinted curve
1321cdf0e10cSrcweir             writeCurveTo( mnStackIdx, -11, -10, -9, -8, -7, -6 );
1322cdf0e10cSrcweir 
1323cdf0e10cSrcweir             // determine if nD6 is horizontal or vertical
1324cdf0e10cSrcweir             const int i = mnStackIdx;
1325cdf0e10cSrcweir             ValType nDeltaX = mnValStack[i-11] + mnValStack[i-9] + mnValStack[i-7] + mnValStack[i-5] + mnValStack[i-3];
1326cdf0e10cSrcweir             if( nDeltaX < 0 ) nDeltaX = -nDeltaX;
1327cdf0e10cSrcweir             ValType nDeltaY = mnValStack[i-10] + mnValStack[i-8] + mnValStack[i-6] + mnValStack[i-4] + mnValStack[i-2];
1328cdf0e10cSrcweir             if( nDeltaY < 0 ) nDeltaY = -nDeltaY;
1329cdf0e10cSrcweir             const bool bVertD6 = (nDeltaY > nDeltaX);
1330cdf0e10cSrcweir 
1331cdf0e10cSrcweir             // write the second part of the flex1-hinted curve
1332cdf0e10cSrcweir             if( !bVertD6 )
1333cdf0e10cSrcweir                 writeCurveTo( mnStackIdx, -5, -4, -3, -2, -1, 0);
1334cdf0e10cSrcweir             else
1335cdf0e10cSrcweir                 writeCurveTo( mnStackIdx, -5, -4, -3, -2, 0, -1);
1336cdf0e10cSrcweir             mnStackIdx -= 11;
1337cdf0e10cSrcweir         }
1338cdf0e10cSrcweir         break;
1339cdf0e10cSrcweir     default:
1340cdf0e10cSrcweir         fprintf( stderr,"unhandled type2esc %d\n", nType2Esc);
1341cdf0e10cSrcweir         assert( false);
1342cdf0e10cSrcweir         break;
1343cdf0e10cSrcweir     }
1344cdf0e10cSrcweir }
1345cdf0e10cSrcweir 
1346cdf0e10cSrcweir // --------------------------------------------------------------------
1347cdf0e10cSrcweir 
callType2Subr(bool bGlobal,int nSubrNumber)1348cdf0e10cSrcweir void CffSubsetterContext::callType2Subr( bool bGlobal, int nSubrNumber)
1349cdf0e10cSrcweir {
1350cdf0e10cSrcweir     const U8* const pOldReadPtr = mpReadPtr;
1351cdf0e10cSrcweir     const U8* const pOldReadEnd = mpReadEnd;
1352cdf0e10cSrcweir 
1353cdf0e10cSrcweir     if( bGlobal ) {
1354cdf0e10cSrcweir         nSubrNumber += mnGlobalSubrBias;
135528337f97SArrigo Marchiori         seekIndexData( mnGlobalSubrBase, nSubrNumber);
1356cdf0e10cSrcweir     } else {
1357cdf0e10cSrcweir         nSubrNumber += mpCffLocal->mnLocalSubrBias;
135828337f97SArrigo Marchiori         seekIndexData( mpCffLocal->mnLocalSubrBase, nSubrNumber);
1359cdf0e10cSrcweir     }
1360cdf0e10cSrcweir 
1361cdf0e10cSrcweir     while( mpReadPtr < mpReadEnd)
1362cdf0e10cSrcweir         convertOneTypeOp();
1363cdf0e10cSrcweir 
1364cdf0e10cSrcweir     mpReadPtr = pOldReadPtr;
1365cdf0e10cSrcweir     mpReadEnd = pOldReadEnd;
1366cdf0e10cSrcweir }
1367cdf0e10cSrcweir 
1368cdf0e10cSrcweir // --------------------------------------------------------------------
1369cdf0e10cSrcweir 
1370cdf0e10cSrcweir static const int MAX_T1OPS_SIZE = 81920; // TODO: use dynamic value
1371cdf0e10cSrcweir 
convert2Type1Ops(CffLocal * pCffLocal,const U8 * const pT2Ops,int nT2Len,U8 * const pT1Ops)1372cdf0e10cSrcweir int CffSubsetterContext::convert2Type1Ops( CffLocal* pCffLocal, const U8* const pT2Ops, int nT2Len, U8* const pT1Ops)
1373cdf0e10cSrcweir {
1374cdf0e10cSrcweir     mpCffLocal = pCffLocal;
1375cdf0e10cSrcweir 
1376cdf0e10cSrcweir     // prepare the charstring conversion
1377cdf0e10cSrcweir     mpWritePtr = pT1Ops;
1378cdf0e10cSrcweir #if 1   // TODO: update caller
1379cdf0e10cSrcweir     U8 aType1Ops[ MAX_T1OPS_SIZE];
1380cdf0e10cSrcweir     if( !pT1Ops)
1381cdf0e10cSrcweir         mpWritePtr = aType1Ops;
1382cdf0e10cSrcweir     *const_cast<U8**>(&pT1Ops) = mpWritePtr;
1383cdf0e10cSrcweir #else
1384cdf0e10cSrcweir     assert( pT1Ops);
1385cdf0e10cSrcweir #endif
1386cdf0e10cSrcweir 
1387cdf0e10cSrcweir     // prepend random seed for T1crypt
1388cdf0e10cSrcweir     *(mpWritePtr++) = 0x48;
1389cdf0e10cSrcweir     *(mpWritePtr++) = 0x44;
1390cdf0e10cSrcweir     *(mpWritePtr++) = 0x55;
1391cdf0e10cSrcweir     *(mpWritePtr++) = ' ';
1392cdf0e10cSrcweir #if 1 // convert the Type2 charstring to Type1
1393cdf0e10cSrcweir     mpReadPtr = pT2Ops;
1394cdf0e10cSrcweir     mpReadEnd = pT2Ops + nT2Len;
1395cdf0e10cSrcweir     // prepend "hsbw" or "sbw"
1396cdf0e10cSrcweir     // TODO: only emit hsbw when charwidth is known
1397cdf0e10cSrcweir     // TODO: remove charwidth from T2 stack
1398cdf0e10cSrcweir     writeType1Val( 0); // TODO: aSubsetterContext.getLeftSideBearing();
1399cdf0e10cSrcweir     writeType1Val( 1000/*###getCharWidth()###*/);
1400cdf0e10cSrcweir     writeTypeOp( TYPE1OP::HSBW);
1401cdf0e10cSrcweir mbSawError = false;
1402cdf0e10cSrcweir mbNeedClose = false;
1403cdf0e10cSrcweir mbIgnoreHints = false;
1404cdf0e10cSrcweir mnHintSize=mnHorzHintSize=mnStackIdx=0; maCharWidth=-1;//#######
1405cdf0e10cSrcweir mnCntrMask = 0;
1406cdf0e10cSrcweir     while( mpReadPtr < mpReadEnd)
1407cdf0e10cSrcweir         convertOneTypeOp();
1408cdf0e10cSrcweir //  if( bActivePath)
1409cdf0e10cSrcweir //      writeTypeOp( TYPE1OP::CLOSEPATH);
1410cdf0e10cSrcweir //  if( bSubRoutine)
1411cdf0e10cSrcweir //      writeTypeOp( TYPE1OP::RETURN);
1412cdf0e10cSrcweir if( mbSawError) {
1413cdf0e10cSrcweir     mpWritePtr = pT1Ops+4;
1414cdf0e10cSrcweir     // create an "idiotproof" charstring
1415cdf0e10cSrcweir     writeType1Val( 0);
1416cdf0e10cSrcweir     writeType1Val( 800);
1417cdf0e10cSrcweir     writeTypeOp( TYPE1OP::HSBW);
1418cdf0e10cSrcweir     writeType1Val( 50);
1419cdf0e10cSrcweir     writeTypeOp( TYPE1OP::HMOVETO);
1420cdf0e10cSrcweir     writeType1Val( 650);
1421cdf0e10cSrcweir     writeType1Val( 100);
1422cdf0e10cSrcweir     writeTypeOp( TYPE1OP::RLINETO);
1423cdf0e10cSrcweir     writeType1Val( -350);
1424cdf0e10cSrcweir     writeType1Val( 700);
1425cdf0e10cSrcweir     writeTypeOp( TYPE1OP::RLINETO);
1426cdf0e10cSrcweir #if 0
1427cdf0e10cSrcweir     writeType1Val( -300);
1428cdf0e10cSrcweir     writeType1Val( -800);
1429cdf0e10cSrcweir     writeTypeOp( TYPE1OP::RLINETO);
1430cdf0e10cSrcweir #else
1431cdf0e10cSrcweir     writeTypeOp( TYPE1OP::CLOSEPATH);
1432cdf0e10cSrcweir #endif
1433cdf0e10cSrcweir     writeTypeOp( TYPE1OP::ENDCHAR);
1434cdf0e10cSrcweir }
1435cdf0e10cSrcweir #else // useful for manually encoding charstrings
1436cdf0e10cSrcweir     mpWritePtr = pT1Ops;
1437cdf0e10cSrcweir     mpWritePtr += sprintf( (char*)mpWritePtr, "OOo_\x8b\x8c\x0c\x10\x0b");
1438cdf0e10cSrcweir #endif
1439cdf0e10cSrcweir     const int nType1Len = mpWritePtr - pT1Ops;
1440cdf0e10cSrcweir 
1441cdf0e10cSrcweir     // encrypt the Type1 charstring
1442cdf0e10cSrcweir     int nRDCryptR = 4330; // TODO: mnRDCryptSeed;
1443cdf0e10cSrcweir     for( U8* p = pT1Ops; p < mpWritePtr; ++p) {
1444cdf0e10cSrcweir         *p ^= (nRDCryptR >> 8);
1445cdf0e10cSrcweir         nRDCryptR = (*(U8*)p + nRDCryptR) * 52845 + 22719;
1446cdf0e10cSrcweir     }
1447cdf0e10cSrcweir 
1448cdf0e10cSrcweir     return nType1Len;
1449cdf0e10cSrcweir }
1450cdf0e10cSrcweir 
1451cdf0e10cSrcweir // --------------------------------------------------------------------
1452cdf0e10cSrcweir 
readRealVal()1453cdf0e10cSrcweir RealType CffSubsetterContext::readRealVal()
1454cdf0e10cSrcweir {
1455cdf0e10cSrcweir     // TODO: more thorough number validity test
1456cdf0e10cSrcweir     bool bComma = false;
1457cdf0e10cSrcweir     int nExpVal = 0;
1458cdf0e10cSrcweir     int nExpSign = 0;
1459cdf0e10cSrcweir     S64 nNumber = 0;
1460cdf0e10cSrcweir     RealType fReal = +1.0;
1461cdf0e10cSrcweir     for(;;){
1462cdf0e10cSrcweir         const U8 c = *(mpReadPtr++); // read nibbles
1463cdf0e10cSrcweir         // parse high nibble
1464cdf0e10cSrcweir         const U8 nH = c >> 4U;
1465cdf0e10cSrcweir         if( nH <= 9) {
1466cdf0e10cSrcweir             nNumber = nNumber * 10 + nH;
1467cdf0e10cSrcweir             --nExpVal;
1468cdf0e10cSrcweir         } else if( nH == 10) {  // comma
1469cdf0e10cSrcweir             nExpVal = 0;
1470cdf0e10cSrcweir             bComma = true;
1471cdf0e10cSrcweir         } else if( nH == 11) {  // +exp
1472cdf0e10cSrcweir             fReal *= nNumber;
1473cdf0e10cSrcweir             nExpSign = +1;
1474cdf0e10cSrcweir             nNumber = 0;
1475cdf0e10cSrcweir         } else if( nH == 12) {  // -exp
1476cdf0e10cSrcweir             fReal *= nNumber;
1477cdf0e10cSrcweir             nExpSign = -1;
1478cdf0e10cSrcweir             nNumber = 0;
1479cdf0e10cSrcweir         } else if( nH == 13) {  // reserved
1480cdf0e10cSrcweir             // TODO: ignore or error?
1481cdf0e10cSrcweir         } else if( nH == 14)    // minus
1482cdf0e10cSrcweir             fReal = -fReal;
1483cdf0e10cSrcweir         else if( nH == 15)  // end
1484cdf0e10cSrcweir             break;
1485cdf0e10cSrcweir         // parse low nibble
1486cdf0e10cSrcweir         const U8 nL = c & 0x0F;
1487cdf0e10cSrcweir         if( nL <= 9) {
1488cdf0e10cSrcweir             nNumber = nNumber * 10 + nL;
1489cdf0e10cSrcweir             --nExpVal;
1490cdf0e10cSrcweir         } else if( nL == 10) {  // comma
1491cdf0e10cSrcweir             nExpVal = 0;
1492cdf0e10cSrcweir             bComma = true;
1493cdf0e10cSrcweir         } else if( nL == 11) {  // +exp
1494cdf0e10cSrcweir             fReal *= nNumber;
1495cdf0e10cSrcweir             nNumber = 0;
1496cdf0e10cSrcweir             nExpSign = +1;
1497cdf0e10cSrcweir         } else if( nL == 12) {  // -exp
1498cdf0e10cSrcweir             fReal *= nNumber;
1499cdf0e10cSrcweir             nNumber = 0;
1500cdf0e10cSrcweir             nExpSign = -1;
1501cdf0e10cSrcweir         } else if( nL == 13) {  // reserved
1502cdf0e10cSrcweir             // TODO: ignore or error?
1503cdf0e10cSrcweir         } else if( nL == 14)    // minus
1504cdf0e10cSrcweir             fReal = -fReal;
1505cdf0e10cSrcweir         else if( nL == 15)  // end
1506cdf0e10cSrcweir             break;
1507cdf0e10cSrcweir     }
1508cdf0e10cSrcweir 
1509cdf0e10cSrcweir     // merge exponents
1510cdf0e10cSrcweir     if( !bComma)
1511cdf0e10cSrcweir         nExpVal = 0;
1512cdf0e10cSrcweir     if( !nExpSign) { fReal *= nNumber;}
1513cdf0e10cSrcweir     else if( nExpSign > 0) { nExpVal += static_cast<int>(nNumber);}
1514cdf0e10cSrcweir     else if( nExpSign < 0) { nExpVal -= static_cast<int>(nNumber);}
1515cdf0e10cSrcweir 
1516cdf0e10cSrcweir     // apply exponents
1517cdf0e10cSrcweir     if( !nExpVal) { /*nothing to apply*/}
1518cdf0e10cSrcweir     else if( nExpVal > 0) { while( --nExpVal >= 0) fReal *= 10.0;}
1519cdf0e10cSrcweir     else if( nExpVal < 0) { while( ++nExpVal <= 0) fReal /= 10.0;}
1520cdf0e10cSrcweir     return fReal;
1521cdf0e10cSrcweir }
1522cdf0e10cSrcweir 
1523cdf0e10cSrcweir // --------------------------------------------------------------------
1524cdf0e10cSrcweir 
seekIndexData(int nIndexBase,int nDataIndex)1525cdf0e10cSrcweir int CffSubsetterContext::seekIndexData( int nIndexBase, int nDataIndex)
1526cdf0e10cSrcweir {
1527cdf0e10cSrcweir     assert( (nIndexBase > 0) && (mpBasePtr + nIndexBase + 3 <= mpBaseEnd));
1528cdf0e10cSrcweir     if( nDataIndex < 0)
1529cdf0e10cSrcweir         return -1;
1530cdf0e10cSrcweir     mpReadPtr = mpBasePtr + nIndexBase;
1531cdf0e10cSrcweir     const int nDataCount = (mpReadPtr[0]<<8) + mpReadPtr[1];
1532cdf0e10cSrcweir     if( nDataIndex >= nDataCount)
1533cdf0e10cSrcweir         return -1;
1534cdf0e10cSrcweir     const int nDataOfsSz = mpReadPtr[2];
1535cdf0e10cSrcweir     mpReadPtr += 3 + (nDataOfsSz * nDataIndex);
1536cdf0e10cSrcweir     int nOfs1 = 0;
1537cdf0e10cSrcweir     switch( nDataOfsSz) {
1538cdf0e10cSrcweir         default: fprintf( stderr, "\tINVALID nDataOfsSz=%d\n\n", nDataOfsSz); return -1;
1539cdf0e10cSrcweir         case 1: nOfs1 = mpReadPtr[0]; break;
1540cdf0e10cSrcweir         case 2: nOfs1 = (mpReadPtr[0]<<8) + mpReadPtr[1]; break;
1541cdf0e10cSrcweir         case 3: nOfs1 = (mpReadPtr[0]<<16) + (mpReadPtr[1]<<8) + mpReadPtr[2]; break;
1542cdf0e10cSrcweir         case 4: nOfs1 = (mpReadPtr[0]<<24) + (mpReadPtr[1]<<16) + (mpReadPtr[2]<<8) + mpReadPtr[3]; break;
1543cdf0e10cSrcweir     }
1544cdf0e10cSrcweir     mpReadPtr += nDataOfsSz;
1545cdf0e10cSrcweir 
1546cdf0e10cSrcweir     int nOfs2 = 0;
1547cdf0e10cSrcweir     switch( nDataOfsSz) {
1548cdf0e10cSrcweir         case 1: nOfs2 = mpReadPtr[0]; break;
1549cdf0e10cSrcweir         case 2: nOfs2 = (mpReadPtr[0]<<8) + mpReadPtr[1]; break;
1550cdf0e10cSrcweir         case 3: nOfs2 = (mpReadPtr[0]<<16) + (mpReadPtr[1]<<8) + mpReadPtr[2]; break;
1551cdf0e10cSrcweir         case 4: nOfs2 = (mpReadPtr[0]<<24) + (mpReadPtr[1]<<16) + (mpReadPtr[2]<<8) + mpReadPtr[3]; break;
1552cdf0e10cSrcweir     }
1553cdf0e10cSrcweir 
1554cdf0e10cSrcweir     mpReadPtr = mpBasePtr + (nIndexBase + 2) + nDataOfsSz * (nDataCount + 1) + nOfs1;
1555cdf0e10cSrcweir     mpReadEnd = mpReadPtr + (nOfs2 - nOfs1);
1556cdf0e10cSrcweir     assert( nOfs1 >= 0);
1557cdf0e10cSrcweir     assert( nOfs2 >= nOfs1);
1558cdf0e10cSrcweir     assert( mpReadPtr <= mpBaseEnd);
1559cdf0e10cSrcweir     assert( mpReadEnd <= mpBaseEnd);
1560cdf0e10cSrcweir     return (nOfs2 - nOfs1);
1561cdf0e10cSrcweir }
1562cdf0e10cSrcweir 
1563cdf0e10cSrcweir // --------------------------------------------------------------------
1564cdf0e10cSrcweir 
seekIndexEnd(int nIndexBase)1565cdf0e10cSrcweir void CffSubsetterContext::seekIndexEnd( int nIndexBase)
1566cdf0e10cSrcweir {
1567cdf0e10cSrcweir     assert( (nIndexBase > 0) && (mpBasePtr + nIndexBase + 3 <= mpBaseEnd));
1568cdf0e10cSrcweir     mpReadPtr = mpBasePtr + nIndexBase;
1569cdf0e10cSrcweir     const int nDataCount = (mpReadPtr[0]<<8) + mpReadPtr[1];
1570cdf0e10cSrcweir     const int nDataOfsSz = mpReadPtr[2];
1571cdf0e10cSrcweir     mpReadPtr += 3 + nDataOfsSz * nDataCount;
1572cdf0e10cSrcweir     assert( mpReadPtr <= mpBaseEnd);
1573cdf0e10cSrcweir     int nEndOfs = 0;
1574cdf0e10cSrcweir     switch( nDataOfsSz) {
1575cdf0e10cSrcweir         default: fprintf( stderr, "\tINVALID nDataOfsSz=%d\n\n", nDataOfsSz); return;
1576cdf0e10cSrcweir         case 1: nEndOfs = mpReadPtr[0]; break;
1577cdf0e10cSrcweir         case 2: nEndOfs = (mpReadPtr[0]<<8) + mpReadPtr[1]; break;
1578cdf0e10cSrcweir         case 3: nEndOfs = (mpReadPtr[0]<<16) + (mpReadPtr[1]<<8) + mpReadPtr[2];break;
1579cdf0e10cSrcweir         case 4: nEndOfs = (mpReadPtr[0]<<24) + (mpReadPtr[1]<<16) + (mpReadPtr[2]<<8) + mpReadPtr[3]; break;
1580cdf0e10cSrcweir     }
1581cdf0e10cSrcweir     mpReadPtr += nDataOfsSz;
1582cdf0e10cSrcweir     mpReadPtr += nEndOfs - 1;
1583cdf0e10cSrcweir     mpReadEnd = mpBaseEnd;
1584cdf0e10cSrcweir     assert( nEndOfs >= 0);
1585cdf0e10cSrcweir     assert( mpReadEnd <= mpBaseEnd);
1586cdf0e10cSrcweir }
1587cdf0e10cSrcweir 
1588cdf0e10cSrcweir // ====================================================================
1589cdf0e10cSrcweir 
1590cdf0e10cSrcweir // initialize FONTDICT specific values
CffLocal(void)1591cdf0e10cSrcweir CffLocal::CffLocal( void)
1592cdf0e10cSrcweir :   mnPrivDictBase( 0)
1593cdf0e10cSrcweir ,   mnPrivDictSize( 0)
1594cdf0e10cSrcweir ,   mnLocalSubrOffs( 0)
1595cdf0e10cSrcweir ,   mnLocalSubrBase( 0)
1596cdf0e10cSrcweir ,   mnLocalSubrCount( 0)
1597cdf0e10cSrcweir ,   mnLocalSubrBias( 0)
1598cdf0e10cSrcweir ,   maNominalWidth( 0)
1599cdf0e10cSrcweir ,   maDefaultWidth( 0)
1600cdf0e10cSrcweir ,   maStemStdHW( 0)
1601cdf0e10cSrcweir ,   maStemStdVW( 0)
1602cdf0e10cSrcweir ,   mfBlueScale( 0.0)
1603cdf0e10cSrcweir ,   mfBlueShift( 0.0)
1604cdf0e10cSrcweir ,   mfBlueFuzz( 0.0)
1605cdf0e10cSrcweir ,   mfExpFactor( 0.0)
1606cdf0e10cSrcweir ,   mnLangGroup( 0)
1607cdf0e10cSrcweir ,   mbForceBold( false)
1608cdf0e10cSrcweir {
1609cdf0e10cSrcweir     maStemSnapH.clear();
1610cdf0e10cSrcweir     maStemSnapV.clear();
1611cdf0e10cSrcweir     maBlueValues.clear();
1612cdf0e10cSrcweir     maOtherBlues.clear();
1613cdf0e10cSrcweir     maFamilyBlues.clear();
1614cdf0e10cSrcweir     maFamilyOtherBlues.clear();
1615cdf0e10cSrcweir }
1616cdf0e10cSrcweir 
1617cdf0e10cSrcweir // --------------------------------------------------------------------
1618cdf0e10cSrcweir 
CffGlobal(void)1619cdf0e10cSrcweir CffGlobal::CffGlobal( void)
1620cdf0e10cSrcweir :   mnNameIdxBase( 0)
1621cdf0e10cSrcweir ,   mnNameIdxCount( 0)
1622cdf0e10cSrcweir ,   mnStringIdxBase( 0)
1623cdf0e10cSrcweir ,   mnStringIdxCount( 0)
1624cdf0e10cSrcweir ,   mbCIDFont( false)
1625cdf0e10cSrcweir ,   mnCharStrBase( 0)
1626cdf0e10cSrcweir ,   mnCharStrCount( 0)
1627cdf0e10cSrcweir ,   mnEncodingBase( 0)
1628cdf0e10cSrcweir ,   mnCharsetBase( 0)
1629cdf0e10cSrcweir ,   mnGlobalSubrBase( 0)
1630cdf0e10cSrcweir ,   mnGlobalSubrCount( 0)
1631cdf0e10cSrcweir ,   mnGlobalSubrBias( 0)
1632cdf0e10cSrcweir ,   mnFDSelectBase( 0)
1633cdf0e10cSrcweir ,   mnFontDictBase( 0)
1634cdf0e10cSrcweir ,   mnFDAryCount( 1)
1635cdf0e10cSrcweir ,   mnFontNameSID( 0)
1636cdf0e10cSrcweir ,   mnFullNameSID( 0)
1637cdf0e10cSrcweir ,   mnFamilyNameSID( 0)
1638cdf0e10cSrcweir {
1639cdf0e10cSrcweir     maFontBBox.clear();
1640cdf0e10cSrcweir     // TODO; maFontMatrix.clear();
1641cdf0e10cSrcweir }
1642cdf0e10cSrcweir 
1643cdf0e10cSrcweir // --------------------------------------------------------------------
1644cdf0e10cSrcweir 
initialCffRead(void)1645cdf0e10cSrcweir void CffSubsetterContext::initialCffRead( void)
1646cdf0e10cSrcweir {
1647cdf0e10cSrcweir     // get the CFFHeader
1648cdf0e10cSrcweir     mpReadPtr = mpBasePtr;
1649cdf0e10cSrcweir     const U8 nVerMajor = *(mpReadPtr++);
1650cdf0e10cSrcweir     const U8 nVerMinor = *(mpReadPtr++);
1651cdf0e10cSrcweir     const U8 nHeaderSize = *(mpReadPtr++);
1652cdf0e10cSrcweir     const U8 nOffsetSize = *(mpReadPtr++);
1653cdf0e10cSrcweir     // TODO: is the version number useful for anything else?
1654cdf0e10cSrcweir     assert( (nVerMajor == 1) && (nVerMinor == 0));
1655cdf0e10cSrcweir     (void)(nVerMajor + nVerMinor + nOffsetSize); // avoid compiler warnings
1656cdf0e10cSrcweir 
1657cdf0e10cSrcweir     // prepare access to the NameIndex
1658cdf0e10cSrcweir     mnNameIdxBase = nHeaderSize;
1659cdf0e10cSrcweir     mpReadPtr = mpBasePtr + nHeaderSize;
1660cdf0e10cSrcweir     mnNameIdxCount = (mpReadPtr[0]<<8) + mpReadPtr[1];
1661cdf0e10cSrcweir     seekIndexEnd( mnNameIdxBase);
1662cdf0e10cSrcweir 
1663cdf0e10cSrcweir     // get the TopDict index
1664cdf0e10cSrcweir     const long nTopDictBase = getReadOfs();
1665cdf0e10cSrcweir     const int nTopDictCount = (mpReadPtr[0]<<8) + mpReadPtr[1];
1666cdf0e10cSrcweir     if( nTopDictCount) {
1667cdf0e10cSrcweir         for( int i = 0; i < nTopDictCount; ++i) {
1668cdf0e10cSrcweir             seekIndexData( nTopDictBase, i);
1669cdf0e10cSrcweir             while( mpReadPtr < mpReadEnd)
1670cdf0e10cSrcweir                 readDictOp();
1671cdf0e10cSrcweir             assert( mpReadPtr == mpReadEnd);
1672cdf0e10cSrcweir         }
1673cdf0e10cSrcweir     }
1674cdf0e10cSrcweir 
1675cdf0e10cSrcweir     // prepare access to the String index
1676cdf0e10cSrcweir     mnStringIdxBase =  getReadOfs();
1677cdf0e10cSrcweir     mnStringIdxCount = (mpReadPtr[0]<<8) + mpReadPtr[1];
1678cdf0e10cSrcweir     seekIndexEnd( mnStringIdxBase);
1679cdf0e10cSrcweir 
1680cdf0e10cSrcweir     // prepare access to the GlobalSubr index
1681cdf0e10cSrcweir     mnGlobalSubrBase =  getReadOfs();
1682cdf0e10cSrcweir     mnGlobalSubrCount = (mpReadPtr[0]<<8) + mpReadPtr[1];
1683cdf0e10cSrcweir     mnGlobalSubrBias = (mnGlobalSubrCount<1240)?107:(mnGlobalSubrCount<33900)?1131:32768;
1684cdf0e10cSrcweir     // skip past the last GlobalSubr entry
1685cdf0e10cSrcweir //  seekIndexEnd( mnGlobalSubrBase);
1686cdf0e10cSrcweir 
1687cdf0e10cSrcweir     // get/skip the Encodings (we got mnEncodingBase from TOPDICT)
1688cdf0e10cSrcweir //  seekEncodingsEnd( mnEncodingBase);
1689cdf0e10cSrcweir     // get/skip the Charsets (we got mnCharsetBase from TOPDICT)
1690cdf0e10cSrcweir //  seekCharsetsEnd( mnCharStrBase);
1691cdf0e10cSrcweir     // get/skip FDSelect (CID only) data
1692cdf0e10cSrcweir 
1693cdf0e10cSrcweir     // prepare access to the CharStrings index (we got the base from TOPDICT)
1694cdf0e10cSrcweir     mpReadPtr = mpBasePtr + mnCharStrBase;
1695cdf0e10cSrcweir     mnCharStrCount = (mpReadPtr[0]<<8) + mpReadPtr[1];
1696cdf0e10cSrcweir //  seekIndexEnd( mnCharStrBase);
1697cdf0e10cSrcweir 
1698cdf0e10cSrcweir     // read the FDArray index (CID only)
1699cdf0e10cSrcweir     if( mbCIDFont) {
1700cdf0e10cSrcweir //      assert( mnFontDictBase == tellRel());
1701cdf0e10cSrcweir         mpReadPtr = mpBasePtr + mnFontDictBase;
1702cdf0e10cSrcweir         mnFDAryCount = (mpReadPtr[0]<<8) + mpReadPtr[1];
170328337f97SArrigo Marchiori         if (maCffLocal.size() < static_cast<size_t>(mnFDAryCount))
170428337f97SArrigo Marchiori             maCffLocal.resize(mnFDAryCount);
1705cdf0e10cSrcweir 
1706cdf0e10cSrcweir         // read FDArray details to get access to the PRIVDICTs
1707cdf0e10cSrcweir         for( int i = 0; i < mnFDAryCount; ++i) {
1708cdf0e10cSrcweir             mpCffLocal = &maCffLocal[i];
1709cdf0e10cSrcweir             seekIndexData( mnFontDictBase, i);
1710cdf0e10cSrcweir             while( mpReadPtr < mpReadEnd)
1711cdf0e10cSrcweir                 readDictOp();
1712cdf0e10cSrcweir             assert( mpReadPtr == mpReadEnd);
1713cdf0e10cSrcweir         }
1714cdf0e10cSrcweir     }
1715cdf0e10cSrcweir 
1716cdf0e10cSrcweir     for( int i = 0; i < mnFDAryCount; ++i) {
1717cdf0e10cSrcweir         mpCffLocal = &maCffLocal[i];
1718cdf0e10cSrcweir 
1719cdf0e10cSrcweir         // get the PrivateDict index
1720cdf0e10cSrcweir         // (we got mnPrivDictSize and mnPrivDictBase from TOPDICT or FDArray)
1721cdf0e10cSrcweir         if( mpCffLocal->mnPrivDictSize != 0) {
1722cdf0e10cSrcweir             assert( mpCffLocal->mnPrivDictSize > 0);
1723cdf0e10cSrcweir             // get the PrivDict data
1724cdf0e10cSrcweir             mpReadPtr = mpBasePtr + mpCffLocal->mnPrivDictBase;
1725cdf0e10cSrcweir             mpReadEnd = mpReadPtr + mpCffLocal->mnPrivDictSize;
1726cdf0e10cSrcweir             assert( mpReadEnd <= mpBaseEnd);
1727cdf0e10cSrcweir             // read PrivDict details
1728cdf0e10cSrcweir             while( mpReadPtr < mpReadEnd)
1729cdf0e10cSrcweir                 readDictOp();
1730cdf0e10cSrcweir         }
1731cdf0e10cSrcweir 
1732cdf0e10cSrcweir         // prepare access to the LocalSubrs (we got mnLocalSubrOffs from PRIVDICT)
1733cdf0e10cSrcweir         if( mpCffLocal->mnLocalSubrOffs) {
1734cdf0e10cSrcweir             // read LocalSubrs summary
1735cdf0e10cSrcweir             mpCffLocal->mnLocalSubrBase = mpCffLocal->mnPrivDictBase + mpCffLocal->mnLocalSubrOffs;
1736cdf0e10cSrcweir             mpReadPtr = mpBasePtr + mpCffLocal->mnLocalSubrBase;
1737cdf0e10cSrcweir             const int nSubrCount = (mpReadPtr[0] << 8) + mpReadPtr[1];
1738cdf0e10cSrcweir             mpCffLocal->mnLocalSubrCount = nSubrCount;
1739cdf0e10cSrcweir             mpCffLocal->mnLocalSubrBias = (nSubrCount<1240)?107:(nSubrCount<33900)?1131:32768;
1740cdf0e10cSrcweir //          seekIndexEnd( mpCffLocal->mnLocalSubrBase);
1741cdf0e10cSrcweir         }
1742cdf0e10cSrcweir     }
1743cdf0e10cSrcweir 
1744cdf0e10cSrcweir     // ignore the Notices info
1745cdf0e10cSrcweir }
1746cdf0e10cSrcweir 
1747cdf0e10cSrcweir // --------------------------------------------------------------------
1748cdf0e10cSrcweir 
1749cdf0e10cSrcweir // get a cstring from a StringID
getString(int nStringID)1750cdf0e10cSrcweir const char* CffSubsetterContext::getString( int nStringID)
1751cdf0e10cSrcweir {
1752cdf0e10cSrcweir     // get a standard string if possible
1753cdf0e10cSrcweir     const static int nStdStrings = sizeof(pStringIds)/sizeof(*pStringIds);
1754cdf0e10cSrcweir     if( (nStringID >= 0) && (nStringID < nStdStrings))
1755cdf0e10cSrcweir         return pStringIds[ nStringID];
1756cdf0e10cSrcweir 
1757cdf0e10cSrcweir     // else get the string from the StringIndex table
1758cdf0e10cSrcweir     const U8* pReadPtr = mpReadPtr;
1759cdf0e10cSrcweir     const U8* pReadEnd = mpReadEnd;
1760cdf0e10cSrcweir     nStringID -= nStdStrings;
1761cdf0e10cSrcweir     int nLen = seekIndexData( mnStringIdxBase, nStringID);
1762cdf0e10cSrcweir     // assert( nLen >= 0);
1763cdf0e10cSrcweir     // TODO: just return the undecorated name
1764cdf0e10cSrcweir     // TODO: get rid of static char buffer
1765cdf0e10cSrcweir     static char aNameBuf[ 2560];
1766cdf0e10cSrcweir     if( nLen < 0) {
1767cdf0e10cSrcweir         sprintf( aNameBuf, "name[%d].notfound!", nStringID);
1768cdf0e10cSrcweir     } else {
1769cdf0e10cSrcweir         const int nMaxLen = sizeof(aNameBuf) - 1;
1770cdf0e10cSrcweir         if( nLen >= nMaxLen)
1771cdf0e10cSrcweir             nLen = nMaxLen;
1772cdf0e10cSrcweir         for( int i = 0; i < nLen; ++i)
1773cdf0e10cSrcweir             aNameBuf[i] = *(mpReadPtr++);
1774cdf0e10cSrcweir         aNameBuf[ nLen] = '\0';
1775cdf0e10cSrcweir     }
1776cdf0e10cSrcweir     mpReadPtr = pReadPtr;
1777cdf0e10cSrcweir     mpReadEnd = pReadEnd;
1778cdf0e10cSrcweir     return aNameBuf;
1779cdf0e10cSrcweir }
1780cdf0e10cSrcweir 
1781cdf0e10cSrcweir // --------------------------------------------------------------------
1782cdf0e10cSrcweir 
1783cdf0e10cSrcweir // access a CID's FDSelect table
getFDSelect(int nGlyphIndex) const1784cdf0e10cSrcweir int CffSubsetterContext::getFDSelect( int nGlyphIndex) const
1785cdf0e10cSrcweir {
1786cdf0e10cSrcweir     assert( nGlyphIndex >= 0);
1787cdf0e10cSrcweir     assert( nGlyphIndex < mnCharStrCount);
1788cdf0e10cSrcweir     if( !mbCIDFont)
1789cdf0e10cSrcweir         return 0;
1790cdf0e10cSrcweir 
1791cdf0e10cSrcweir     const U8* pReadPtr = mpBasePtr + mnFDSelectBase;
1792cdf0e10cSrcweir     const U8 nFDSelFormat = *(pReadPtr++);
1793cdf0e10cSrcweir     switch( nFDSelFormat) {
1794cdf0e10cSrcweir         case 0: { // FDSELECT format 0
1795cdf0e10cSrcweir                 pReadPtr += nGlyphIndex;
1796cdf0e10cSrcweir                 const U8 nFDIdx = *(pReadPtr++);
1797cdf0e10cSrcweir                 return nFDIdx;
1798cdf0e10cSrcweir             } //break;
1799cdf0e10cSrcweir         case 3: { // FDSELECT format 3
1800cdf0e10cSrcweir                 const U16 nRangeCount = (pReadPtr[0]<<8) + pReadPtr[1];
1801cdf0e10cSrcweir                 assert( nRangeCount > 0);
1802cdf0e10cSrcweir                 assert( nRangeCount <= mnCharStrCount);
1803cdf0e10cSrcweir                 U16 nPrev = (pReadPtr[2]<<8) + pReadPtr[3];
1804cdf0e10cSrcweir                 assert( nPrev == 0);
1805cdf0e10cSrcweir                 pReadPtr += 4;
1806cdf0e10cSrcweir                 // TODO? binary search
1807cdf0e10cSrcweir                 for( int i = 0; i < nRangeCount; ++i) {
1808cdf0e10cSrcweir                     const U8 nFDIdx = pReadPtr[0];
1809cdf0e10cSrcweir                     const U16 nNext = (pReadPtr[1]<<8) + pReadPtr[2];
1810cdf0e10cSrcweir                     assert( nPrev < nNext);
1811cdf0e10cSrcweir                     if( nGlyphIndex < nNext)
1812cdf0e10cSrcweir                         return nFDIdx;
1813cdf0e10cSrcweir                     pReadPtr += 3;
1814cdf0e10cSrcweir                     nPrev = nNext;
1815cdf0e10cSrcweir                 }
1816cdf0e10cSrcweir             } break;
1817cdf0e10cSrcweir         default:    // invalid FDselect format
1818cdf0e10cSrcweir             fprintf( stderr, "invalid CFF.FdselType=%d\n", nFDSelFormat);
1819cdf0e10cSrcweir             break;
1820cdf0e10cSrcweir     }
1821cdf0e10cSrcweir 
1822cdf0e10cSrcweir     assert( false);
1823cdf0e10cSrcweir     return -1;
1824cdf0e10cSrcweir }
1825cdf0e10cSrcweir 
1826cdf0e10cSrcweir // --------------------------------------------------------------------
1827cdf0e10cSrcweir 
getGlyphSID(int nGlyphIndex) const1828cdf0e10cSrcweir int CffSubsetterContext::getGlyphSID( int nGlyphIndex) const
1829cdf0e10cSrcweir {
1830cdf0e10cSrcweir     if( nGlyphIndex == 0)
1831cdf0e10cSrcweir         return 0;       // ".notdef"
1832cdf0e10cSrcweir     assert( nGlyphIndex >= 0);
1833cdf0e10cSrcweir     assert( nGlyphIndex < mnCharStrCount);
1834cdf0e10cSrcweir     if( (nGlyphIndex < 0) || (nGlyphIndex >= mnCharStrCount))
1835cdf0e10cSrcweir         return -1;
1836cdf0e10cSrcweir 
1837cdf0e10cSrcweir     // get the SID/CID from the Charset table
1838cdf0e10cSrcweir      const U8* pReadPtr = mpBasePtr + mnCharsetBase;
1839cdf0e10cSrcweir     const U8 nCSetFormat = *(pReadPtr++);
1840cdf0e10cSrcweir     int nGlyphsToSkip = nGlyphIndex - 1;
1841cdf0e10cSrcweir     switch( nCSetFormat) {
1842cdf0e10cSrcweir         case 0: // charset format 0
1843cdf0e10cSrcweir             pReadPtr += 2 * nGlyphsToSkip;
1844cdf0e10cSrcweir             nGlyphsToSkip = 0;
1845cdf0e10cSrcweir             break;
1846cdf0e10cSrcweir         case 1: // charset format 1
1847cdf0e10cSrcweir             while( nGlyphsToSkip >= 0) {
1848cdf0e10cSrcweir                 const int nLeft = pReadPtr[2];
1849cdf0e10cSrcweir                 if( nGlyphsToSkip <= nLeft)
1850cdf0e10cSrcweir                     break;
1851cdf0e10cSrcweir                 nGlyphsToSkip -= nLeft + 1;
1852cdf0e10cSrcweir                 pReadPtr += 3;
1853cdf0e10cSrcweir             }
1854cdf0e10cSrcweir             break;
1855cdf0e10cSrcweir         case 2: // charset format 2
1856cdf0e10cSrcweir             while( nGlyphsToSkip >= 0) {
1857cdf0e10cSrcweir                 const int nLeft = (pReadPtr[2]<<8) + pReadPtr[3];
1858cdf0e10cSrcweir                 if( nGlyphsToSkip <= nLeft)
1859cdf0e10cSrcweir                     break;
1860cdf0e10cSrcweir                 nGlyphsToSkip -= nLeft + 1;
1861cdf0e10cSrcweir                 pReadPtr += 4;
1862cdf0e10cSrcweir             }
1863cdf0e10cSrcweir             break;
1864cdf0e10cSrcweir         default:
1865cdf0e10cSrcweir             fprintf( stderr, "ILLEGAL CFF-Charset format %d\n", nCSetFormat);
1866cdf0e10cSrcweir             return -2;
1867cdf0e10cSrcweir     }
1868cdf0e10cSrcweir 
1869cdf0e10cSrcweir     int nSID = (pReadPtr[0]<<8) + pReadPtr[1];
1870cdf0e10cSrcweir     nSID += nGlyphsToSkip;
1871cdf0e10cSrcweir     // NOTE: for CID-fonts the resulting SID is interpreted as CID
1872cdf0e10cSrcweir     return nSID;
1873cdf0e10cSrcweir }
1874cdf0e10cSrcweir 
1875cdf0e10cSrcweir // --------------------------------------------------------------------
1876cdf0e10cSrcweir 
1877cdf0e10cSrcweir // NOTE: the result becomes invalid with the next call to this method
getGlyphName(int nGlyphIndex)1878cdf0e10cSrcweir const char* CffSubsetterContext::getGlyphName( int nGlyphIndex)
1879cdf0e10cSrcweir {
1880cdf0e10cSrcweir     // the first glyph is always the .notdef glyph
1881cdf0e10cSrcweir     const char* pGlyphName = ".notdef";
1882cdf0e10cSrcweir     if( nGlyphIndex == 0)
1883cdf0e10cSrcweir         return pGlyphName;
1884cdf0e10cSrcweir 
1885cdf0e10cSrcweir     // prepare a result buffer
1886cdf0e10cSrcweir     // TODO: get rid of static buffer
1887cdf0e10cSrcweir     static char aDefaultGlyphName[64];
1888cdf0e10cSrcweir     pGlyphName = aDefaultGlyphName;
1889cdf0e10cSrcweir 
1890cdf0e10cSrcweir     // get the glyph specific name
1891cdf0e10cSrcweir     const int nSID = getGlyphSID( nGlyphIndex);
1892cdf0e10cSrcweir     if( nSID < 0)           // default glyph name
1893cdf0e10cSrcweir         sprintf( aDefaultGlyphName, "gly%03d", nGlyphIndex);
1894cdf0e10cSrcweir     else if( mbCIDFont)     // default glyph name in CIDs
1895cdf0e10cSrcweir          sprintf( aDefaultGlyphName, "cid%03d", nSID);
1896cdf0e10cSrcweir     else {                  // glyph name from string table
1897cdf0e10cSrcweir         const char* pSidName = getString( nSID);
1898cdf0e10cSrcweir         // check validity of glyph name
1899cdf0e10cSrcweir         if( pSidName) {
1900cdf0e10cSrcweir             const char* p = pSidName;
1901cdf0e10cSrcweir             while( (*p >= '0') && (*p <= 'z')) ++p;
1902cdf0e10cSrcweir             if( (p >= pSidName+1) && (*p == '\0'))
1903cdf0e10cSrcweir                 pGlyphName = pSidName;
1904cdf0e10cSrcweir         }
1905cdf0e10cSrcweir         // if needed invent a fallback name
1906cdf0e10cSrcweir         if( pGlyphName != pSidName)
1907cdf0e10cSrcweir             sprintf( aDefaultGlyphName, "bad%03d", nSID);
1908cdf0e10cSrcweir     }
1909cdf0e10cSrcweir 
1910cdf0e10cSrcweir      return pGlyphName;
1911cdf0e10cSrcweir }
1912cdf0e10cSrcweir 
1913cdf0e10cSrcweir // --------------------------------------------------------------------
1914cdf0e10cSrcweir 
1915cdf0e10cSrcweir class Type1Emitter
1916cdf0e10cSrcweir {
1917cdf0e10cSrcweir public:
1918cdf0e10cSrcweir     explicit    Type1Emitter( const char* pOutFileName, bool bPfbSubset = true);
1919cdf0e10cSrcweir     explicit    Type1Emitter( FILE* pOutFile, bool bPfbSubset = true);
1920cdf0e10cSrcweir     /*virtual*/ ~Type1Emitter( void);
1921cdf0e10cSrcweir     void        setSubsetName( const char* );
1922cdf0e10cSrcweir 
1923cdf0e10cSrcweir     void        emitRawData( const char* pData, int nLength) const;
1924cdf0e10cSrcweir     void        emitAllRaw( void);
1925cdf0e10cSrcweir     void        emitAllHex( void);
1926cdf0e10cSrcweir     void        emitAllCrypted( void);
1927cdf0e10cSrcweir     int     tellPos( void) const;
1928cdf0e10cSrcweir     void        updateLen( int nTellPos, int nLength);
1929cdf0e10cSrcweir     void        emitValVector( const char* pLineHead, const char* pLineTail, const ValVector&);
1930cdf0e10cSrcweir private:
1931cdf0e10cSrcweir     FILE*       mpFileOut;
1932cdf0e10cSrcweir     bool        mbCloseOutfile;
1933cdf0e10cSrcweir     char        maBuffer[MAX_T1OPS_SIZE];   // TODO: dynamic allocation
1934cdf0e10cSrcweir     int     mnEECryptR;
1935cdf0e10cSrcweir public:
1936cdf0e10cSrcweir     char*       mpPtr;
1937cdf0e10cSrcweir 
1938cdf0e10cSrcweir     char        maSubsetName[256];
1939cdf0e10cSrcweir     bool        mbPfbSubset;
1940cdf0e10cSrcweir     int     mnHexLineCol;
1941cdf0e10cSrcweir };
1942cdf0e10cSrcweir 
1943cdf0e10cSrcweir // --------------------------------------------------------------------
1944cdf0e10cSrcweir 
Type1Emitter(const char * pPfbFileName,bool bPfbSubset)1945cdf0e10cSrcweir Type1Emitter::Type1Emitter( const char* pPfbFileName, bool bPfbSubset)
1946cdf0e10cSrcweir :   mpFileOut( NULL)
1947cdf0e10cSrcweir ,   mbCloseOutfile( true)
1948cdf0e10cSrcweir ,   mnEECryptR( 55665)  // default eexec seed, TODO: mnEECryptSeed
1949cdf0e10cSrcweir ,   mpPtr( maBuffer)
1950cdf0e10cSrcweir ,   mbPfbSubset( bPfbSubset)
1951cdf0e10cSrcweir ,   mnHexLineCol( 0)
1952cdf0e10cSrcweir {
1953cdf0e10cSrcweir     mpFileOut = fopen( pPfbFileName, "wb");
1954cdf0e10cSrcweir     maSubsetName[0] = '\0';
1955cdf0e10cSrcweir }
1956cdf0e10cSrcweir 
1957cdf0e10cSrcweir // --------------------------------------------------------------------
1958cdf0e10cSrcweir 
Type1Emitter(FILE * pOutFile,bool bPfbSubset)1959cdf0e10cSrcweir Type1Emitter::Type1Emitter( FILE* pOutFile, bool bPfbSubset)
1960cdf0e10cSrcweir :   mpFileOut( pOutFile)
1961cdf0e10cSrcweir ,   mbCloseOutfile( false)
1962cdf0e10cSrcweir ,   mnEECryptR( 55665)  // default eexec seed, TODO: mnEECryptSeed
1963cdf0e10cSrcweir ,   mpPtr( maBuffer)
1964cdf0e10cSrcweir ,   mbPfbSubset( bPfbSubset)
1965cdf0e10cSrcweir ,   mnHexLineCol( 0)
1966cdf0e10cSrcweir {
1967cdf0e10cSrcweir     maSubsetName[0] = '\0';
1968cdf0e10cSrcweir }
1969cdf0e10cSrcweir 
1970cdf0e10cSrcweir // --------------------------------------------------------------------
1971cdf0e10cSrcweir 
~Type1Emitter(void)1972cdf0e10cSrcweir Type1Emitter::~Type1Emitter( void)
1973cdf0e10cSrcweir {
1974cdf0e10cSrcweir     if( !mpFileOut)
1975cdf0e10cSrcweir         return;
1976cdf0e10cSrcweir     if( mbCloseOutfile )
1977cdf0e10cSrcweir         fclose( mpFileOut);
1978cdf0e10cSrcweir     mpFileOut = NULL;
1979cdf0e10cSrcweir }
1980cdf0e10cSrcweir 
1981cdf0e10cSrcweir // --------------------------------------------------------------------
1982cdf0e10cSrcweir 
setSubsetName(const char * pSubsetName)1983cdf0e10cSrcweir void Type1Emitter::setSubsetName( const char* pSubsetName)
1984cdf0e10cSrcweir {
1985cdf0e10cSrcweir     maSubsetName[0] = '\0';
1986cdf0e10cSrcweir     if( pSubsetName)
1987cdf0e10cSrcweir         strncpy( maSubsetName, pSubsetName, sizeof(maSubsetName));
1988cdf0e10cSrcweir     maSubsetName[sizeof(maSubsetName)-1] = '\0';
1989cdf0e10cSrcweir }
1990cdf0e10cSrcweir 
1991cdf0e10cSrcweir // --------------------------------------------------------------------
1992cdf0e10cSrcweir 
tellPos(void) const1993cdf0e10cSrcweir int Type1Emitter::tellPos( void) const
1994cdf0e10cSrcweir {
1995cdf0e10cSrcweir     int nTellPos = ftell( mpFileOut);
1996cdf0e10cSrcweir     return nTellPos;
1997cdf0e10cSrcweir }
1998cdf0e10cSrcweir 
1999cdf0e10cSrcweir // --------------------------------------------------------------------
2000cdf0e10cSrcweir 
updateLen(int nTellPos,int nLength)2001cdf0e10cSrcweir void Type1Emitter::updateLen( int nTellPos, int nLength)
2002cdf0e10cSrcweir {
2003cdf0e10cSrcweir     // update PFB segment header length
2004cdf0e10cSrcweir     U8 cData[4];
2005cdf0e10cSrcweir     cData[0] = static_cast<U8>(nLength >>  0);
2006cdf0e10cSrcweir     cData[1] = static_cast<U8>(nLength >>  8);
2007cdf0e10cSrcweir     cData[2] = static_cast<U8>(nLength >> 16);
2008cdf0e10cSrcweir     cData[3] = static_cast<U8>(nLength >> 24);
2009b87d82ffSHerbert Dürr     const long nCurrPos = ftell( mpFileOut);
2010cdf0e10cSrcweir     fseek( mpFileOut, nTellPos, SEEK_SET);
2011cdf0e10cSrcweir     fwrite( cData, 1, sizeof(cData), mpFileOut);
2012b87d82ffSHerbert Dürr     if( nCurrPos >= 0)
2013cdf0e10cSrcweir         fseek( mpFileOut, nCurrPos, SEEK_SET);
2014cdf0e10cSrcweir }
2015cdf0e10cSrcweir 
2016cdf0e10cSrcweir // --------------------------------------------------------------------
2017cdf0e10cSrcweir 
emitRawData(const char * pData,int nLength) const2018cdf0e10cSrcweir inline void Type1Emitter::emitRawData( const char* pData, int nLength) const
2019cdf0e10cSrcweir {
2020cdf0e10cSrcweir     fwrite( pData, 1, nLength, mpFileOut);
2021cdf0e10cSrcweir }
2022cdf0e10cSrcweir 
2023cdf0e10cSrcweir // --------------------------------------------------------------------
2024cdf0e10cSrcweir 
emitAllRaw(void)2025cdf0e10cSrcweir inline void Type1Emitter::emitAllRaw( void)
2026cdf0e10cSrcweir {
2027cdf0e10cSrcweir     // writeout raw data
2028cdf0e10cSrcweir     assert( (mpPtr - maBuffer) < (int)sizeof(maBuffer));
2029cdf0e10cSrcweir     emitRawData( maBuffer, mpPtr - maBuffer);
2030cdf0e10cSrcweir     // reset the raw buffer
2031cdf0e10cSrcweir     mpPtr = maBuffer;
2032cdf0e10cSrcweir }
2033cdf0e10cSrcweir 
2034cdf0e10cSrcweir // --------------------------------------------------------------------
2035cdf0e10cSrcweir 
emitAllHex(void)2036cdf0e10cSrcweir inline void Type1Emitter::emitAllHex( void)
2037cdf0e10cSrcweir {
2038cdf0e10cSrcweir     assert( (mpPtr - maBuffer) < (int)sizeof(maBuffer));
2039cdf0e10cSrcweir     for( const char* p = maBuffer; p < mpPtr;) {
2040cdf0e10cSrcweir         // convert binary chunk to hex
2041cdf0e10cSrcweir         char aHexBuf[0x4000];
2042cdf0e10cSrcweir         char* pOut = aHexBuf;
2043cdf0e10cSrcweir         while( (p < mpPtr) && (pOut < aHexBuf+sizeof(aHexBuf)-4)) {
2044cdf0e10cSrcweir             // convert each byte to hex
2045cdf0e10cSrcweir             char cNibble = (*p >> 4) & 0x0F;
2046cdf0e10cSrcweir             cNibble += (cNibble < 10) ? '0' : 'A'-10;
2047cdf0e10cSrcweir             *(pOut++) = cNibble;
2048cdf0e10cSrcweir             cNibble = *(p++) & 0x0F;
2049cdf0e10cSrcweir             cNibble += (cNibble < 10) ? '0' : 'A'-10;
2050cdf0e10cSrcweir             *(pOut++) = cNibble;
2051cdf0e10cSrcweir             // limit the line length
2052cdf0e10cSrcweir             if( (++mnHexLineCol & 0x3F) == 0)
2053cdf0e10cSrcweir                 *(pOut++) = '\n';
2054cdf0e10cSrcweir         }
2055cdf0e10cSrcweir         // writeout hex-converted chunk
2056cdf0e10cSrcweir         emitRawData( aHexBuf, pOut-aHexBuf);
2057cdf0e10cSrcweir     }
2058cdf0e10cSrcweir     // reset the raw buffer
2059cdf0e10cSrcweir     mpPtr = maBuffer;
2060cdf0e10cSrcweir }
2061cdf0e10cSrcweir 
2062cdf0e10cSrcweir // --------------------------------------------------------------------
2063cdf0e10cSrcweir 
emitAllCrypted(void)2064cdf0e10cSrcweir void Type1Emitter::emitAllCrypted( void)
2065cdf0e10cSrcweir {
2066cdf0e10cSrcweir     // apply t1crypt
2067cdf0e10cSrcweir     for( char* p = maBuffer; p < mpPtr; ++p) {
2068cdf0e10cSrcweir         *p ^= (mnEECryptR >> 8);
2069cdf0e10cSrcweir         mnEECryptR = (*(U8*)p + mnEECryptR) * 52845 + 22719;
2070cdf0e10cSrcweir     }
2071cdf0e10cSrcweir 
2072cdf0e10cSrcweir     // emit the t1crypt result
2073cdf0e10cSrcweir     if( mbPfbSubset)
2074cdf0e10cSrcweir         emitAllRaw();
2075cdf0e10cSrcweir     else
2076cdf0e10cSrcweir         emitAllHex();
2077cdf0e10cSrcweir }
2078cdf0e10cSrcweir 
2079cdf0e10cSrcweir // --------------------------------------------------------------------
2080cdf0e10cSrcweir 
2081cdf0e10cSrcweir // #i110387# quick-and-dirty double->ascii conversion
2082cdf0e10cSrcweir // needed because sprintf/ecvt/etc. alone are too localized (LC_NUMERIC)
2083cdf0e10cSrcweir // also strip off trailing zeros in fraction while we are at it
dbl2str(char * pOut,double fVal,int nPrecision=6)2084cdf0e10cSrcweir inline int dbl2str( char* pOut, double fVal, int nPrecision=6)
2085cdf0e10cSrcweir {
2086cdf0e10cSrcweir     const int nLen = psp::getValueOfDouble( pOut, fVal, nPrecision);
2087cdf0e10cSrcweir     return nLen;
2088cdf0e10cSrcweir }
2089cdf0e10cSrcweir 
2090cdf0e10cSrcweir // --------------------------------------------------------------------
2091cdf0e10cSrcweir 
emitValVector(const char * pLineHead,const char * pLineTail,const ValVector & rVector)2092cdf0e10cSrcweir void Type1Emitter::emitValVector( const char* pLineHead, const char* pLineTail,
2093cdf0e10cSrcweir     const ValVector& rVector)
2094cdf0e10cSrcweir {
2095cdf0e10cSrcweir     // ignore empty vectors
2096cdf0e10cSrcweir     if( rVector.empty())
2097cdf0e10cSrcweir         return;
2098cdf0e10cSrcweir 
2099cdf0e10cSrcweir     // emit the line head
2100851abcd9Struckman     mpPtr += sprintf( mpPtr, "%s", pLineHead);
2101cdf0e10cSrcweir     // emit the vector values
2102cdf0e10cSrcweir     ValVector::value_type aVal = 0;
2103cdf0e10cSrcweir     for( ValVector::const_iterator it = rVector.begin();;) {
2104cdf0e10cSrcweir         aVal = *it;
2105cdf0e10cSrcweir         if( ++it == rVector.end() )
2106cdf0e10cSrcweir             break;
2107cdf0e10cSrcweir         mpPtr += dbl2str( mpPtr, aVal);
2108cdf0e10cSrcweir         *(mpPtr++) = ' ';
2109cdf0e10cSrcweir     }
2110cdf0e10cSrcweir     // emit the last value
2111cdf0e10cSrcweir     mpPtr += dbl2str( mpPtr, aVal);
2112cdf0e10cSrcweir     // emit the line tail
2113851abcd9Struckman     mpPtr += sprintf( mpPtr, "%s", pLineTail);
2114cdf0e10cSrcweir }
2115cdf0e10cSrcweir 
2116cdf0e10cSrcweir // --------------------------------------------------------------------
2117cdf0e10cSrcweir 
emitAsType1(Type1Emitter & rEmitter,const sal_GlyphId * pReqGlyphIds,const U8 * pReqEncoding,GlyphWidth * pGlyphWidths,int nGlyphCount,FontSubsetInfo & rFSInfo)2118cdf0e10cSrcweir bool CffSubsetterContext::emitAsType1( Type1Emitter& rEmitter,
2119248a599fSHerbert Dürr     const sal_GlyphId* pReqGlyphIds, const U8* pReqEncoding,
2120cdf0e10cSrcweir     GlyphWidth* pGlyphWidths, int nGlyphCount, FontSubsetInfo& rFSInfo)
2121cdf0e10cSrcweir {
2122cdf0e10cSrcweir     // prepare some fontdirectory details
2123cdf0e10cSrcweir     static const int nUniqueIdBase = 4100000; // using private-interchange UniqueIds
2124cdf0e10cSrcweir     static int nUniqueId = nUniqueIdBase;
2125cdf0e10cSrcweir     ++nUniqueId;
2126cdf0e10cSrcweir 
2127cdf0e10cSrcweir     char* pFontName = rEmitter.maSubsetName;
2128cdf0e10cSrcweir     if( !*pFontName ) {
2129cdf0e10cSrcweir         if( mnFontNameSID) {
2130cdf0e10cSrcweir             // get the fontname directly if available
2131cdf0e10cSrcweir             strncpy( pFontName, getString( mnFontNameSID), sizeof(rEmitter.maSubsetName));
2132cdf0e10cSrcweir         } else if( mnFullNameSID) {
2133cdf0e10cSrcweir             // approximate fontname as fullname-whitespace
2134cdf0e10cSrcweir             const char* pI = getString( mnFullNameSID);
2135cdf0e10cSrcweir             char* pO = pFontName;
2136cdf0e10cSrcweir             const char* pLimit = pFontName + sizeof(rEmitter.maSubsetName) - 1;
2137cdf0e10cSrcweir             while( pO < pLimit) {
2138cdf0e10cSrcweir                 const char c = *(pI++);
2139cdf0e10cSrcweir                 if( c != ' ')
2140cdf0e10cSrcweir                     *(pO++) = c;
2141cdf0e10cSrcweir                 if( !c)
2142cdf0e10cSrcweir                     break;
2143cdf0e10cSrcweir             }
2144cdf0e10cSrcweir             *pO = '\0';
2145cdf0e10cSrcweir         } else {
2146cdf0e10cSrcweir             // fallback name of last resort
2147cdf0e10cSrcweir             strncpy( pFontName, "DummyName", sizeof(rEmitter.maSubsetName));
2148cdf0e10cSrcweir         }
2149cdf0e10cSrcweir     }
2150cdf0e10cSrcweir     const char* pFullName = pFontName;
2151cdf0e10cSrcweir     const char* pFamilyName = pFontName;
2152cdf0e10cSrcweir 
2153cdf0e10cSrcweir     char*& pOut = rEmitter.mpPtr; // convenience reference, TODO: cleanup
2154cdf0e10cSrcweir 
2155cdf0e10cSrcweir     // create a PFB+Type1 header
2156cdf0e10cSrcweir     if( rEmitter.mbPfbSubset ) {
2157cdf0e10cSrcweir         static const char aPfbHeader[] = "\x80\x01\x00\x00\x00\x00";
2158cdf0e10cSrcweir         rEmitter.emitRawData( aPfbHeader, sizeof(aPfbHeader)-1);
2159cdf0e10cSrcweir     }
2160cdf0e10cSrcweir 
2161cdf0e10cSrcweir     pOut += sprintf( pOut, "%%!FontType1-1.0: %s 001.003\n", rEmitter.maSubsetName);
2162cdf0e10cSrcweir     // emit TOPDICT
2163cdf0e10cSrcweir #if 0 // improve PS Type1 caching?
2164cdf0e10cSrcweir     nOfs += sprintf( &aT1Str[nOfs],
2165cdf0e10cSrcweir         "FontDirectory/%s known{/%s findfont dup/UniqueID known{dup\n"
2166cdf0e10cSrcweir         "/UniqueID get %d eq exch/FontType get 1 eq and}{pop false}ifelse\n"
2167cdf0e10cSrcweir         "{save true}{false}ifelse}\n{false}ifelse\n",
2168cdf0e10cSrcweir             pFamilyName, pFamilyName, nUniqueId);
2169cdf0e10cSrcweir #endif
2170cdf0e10cSrcweir     pOut += sprintf( pOut,
2171cdf0e10cSrcweir         "11 dict begin\n"   // TODO: dynamic entry count for TOPDICT
2172cdf0e10cSrcweir         "/FontType 1 def\n"
2173cdf0e10cSrcweir         "/PaintType 0 def\n");
2174cdf0e10cSrcweir     pOut += sprintf( pOut, "/FontName /%s def\n", rEmitter.maSubsetName);
2175cdf0e10cSrcweir     pOut += sprintf( pOut, "/UniqueID %d def\n", nUniqueId);
2176cdf0e10cSrcweir     // emit FontMatrix
2177cdf0e10cSrcweir     if( maFontMatrix.size() == 6)
2178cdf0e10cSrcweir         rEmitter.emitValVector( "/FontMatrix [", "]readonly def\n", maFontMatrix);
2179cdf0e10cSrcweir     else // emit default FontMatrix if needed
2180cdf0e10cSrcweir         pOut += sprintf( pOut, "/FontMatrix [0.001 0 0 0.001 0 0]readonly def\n");
2181cdf0e10cSrcweir     // emit FontBBox
2182cdf0e10cSrcweir     if( maFontBBox.size() == 4)
2183cdf0e10cSrcweir         rEmitter.emitValVector( "/FontBBox {", "}readonly def\n", maFontBBox);
2184cdf0e10cSrcweir     else // emit default FontBBox if needed
2185cdf0e10cSrcweir         pOut += sprintf( pOut, "/FontBBox {0 0 999 999}readonly def\n");
2186cdf0e10cSrcweir     // emit FONTINFO into TOPDICT
2187cdf0e10cSrcweir     pOut += sprintf( pOut,
2188cdf0e10cSrcweir         "/FontInfo 2 dict dup begin\n"  // TODO: check fontinfo entry count
2189cdf0e10cSrcweir         " /FullName (%s) readonly def\n"
2190cdf0e10cSrcweir         " /FamilyName (%s) readonly def\n"
2191cdf0e10cSrcweir         "end readonly def\n",
2192cdf0e10cSrcweir             pFullName, pFamilyName);
2193cdf0e10cSrcweir #if 0   // TODO: use an standard Type1 encoding if possible
2194cdf0e10cSrcweir     pOut += sprintf( pOut,
2195cdf0e10cSrcweir         "/Encoding StandardEncoding def\n");
2196cdf0e10cSrcweir #else
2197cdf0e10cSrcweir     pOut += sprintf( pOut,
2198cdf0e10cSrcweir         "/Encoding 256 array\n"
2199cdf0e10cSrcweir         "0 1 255 {1 index exch /.notdef put} for\n");
2200cdf0e10cSrcweir     for( int i = 1; (i < nGlyphCount) && (i < 256); ++i) {
2201248a599fSHerbert Dürr         const char* pGlyphName = getGlyphName( pReqGlyphIds[i]);
2202cdf0e10cSrcweir         pOut += sprintf( pOut, "dup %d /%s put\n", pReqEncoding[i], pGlyphName);
2203cdf0e10cSrcweir     }
2204cdf0e10cSrcweir     pOut += sprintf( pOut, "readonly def\n");
2205cdf0e10cSrcweir #endif
2206cdf0e10cSrcweir     pOut += sprintf( pOut,
2207cdf0e10cSrcweir         // TODO: more topdict entries
2208cdf0e10cSrcweir         "currentdict end\n"
2209cdf0e10cSrcweir         "currentfile eexec\n");
2210cdf0e10cSrcweir 
2211cdf0e10cSrcweir     // emit PFB header
2212cdf0e10cSrcweir     rEmitter.emitAllRaw();
2213cdf0e10cSrcweir     if( rEmitter.mbPfbSubset) {
2214cdf0e10cSrcweir         // update PFB header segment
2215cdf0e10cSrcweir         const int nPfbHeaderLen = rEmitter.tellPos() - 6;
2216cdf0e10cSrcweir         rEmitter.updateLen( 2, nPfbHeaderLen);
2217cdf0e10cSrcweir 
2218cdf0e10cSrcweir         // prepare start of eexec segment
2219cdf0e10cSrcweir         rEmitter.emitRawData( "\x80\x02\x00\x00\x00\x00", 6);   // segment start
2220cdf0e10cSrcweir     }
2221cdf0e10cSrcweir     const int nEExecSegTell = rEmitter.tellPos();
2222cdf0e10cSrcweir 
2223cdf0e10cSrcweir     // which always starts with a privdict
2224cdf0e10cSrcweir     // count the privdict entries
2225cdf0e10cSrcweir     int nPrivEntryCount = 9;
2226cdf0e10cSrcweir #if !defined(IGNORE_HINTS)
2227cdf0e10cSrcweir     // emit blue hints only if non-default values
2228cdf0e10cSrcweir     nPrivEntryCount += !mpCffLocal->maOtherBlues.empty();
2229cdf0e10cSrcweir     nPrivEntryCount += !mpCffLocal->maFamilyBlues.empty();
2230cdf0e10cSrcweir     nPrivEntryCount += !mpCffLocal->maFamilyOtherBlues.empty();
2231cdf0e10cSrcweir     nPrivEntryCount += (mpCffLocal->mfBlueScale != 0.0);
2232cdf0e10cSrcweir     nPrivEntryCount += (mpCffLocal->mfBlueShift != 0.0);
2233cdf0e10cSrcweir     nPrivEntryCount += (mpCffLocal->mfBlueFuzz != 0.0);
2234cdf0e10cSrcweir     // emit stem hints only if non-default values
2235cdf0e10cSrcweir     nPrivEntryCount += (mpCffLocal->maStemStdHW != 0);
2236cdf0e10cSrcweir     nPrivEntryCount += (mpCffLocal->maStemStdVW != 0);
2237cdf0e10cSrcweir     nPrivEntryCount += !mpCffLocal->maStemSnapH.empty();
2238cdf0e10cSrcweir     nPrivEntryCount += !mpCffLocal->maStemSnapV.empty();
2239cdf0e10cSrcweir     // emit other hints only if non-default values
2240cdf0e10cSrcweir     nPrivEntryCount += (mpCffLocal->mfExpFactor != 0.0);
2241cdf0e10cSrcweir     nPrivEntryCount += (mpCffLocal->mnLangGroup != 0);
2242cdf0e10cSrcweir     nPrivEntryCount += (mpCffLocal->mnLangGroup == 1);
2243cdf0e10cSrcweir     nPrivEntryCount += (mpCffLocal->mbForceBold != false);
2244cdf0e10cSrcweir #endif // IGNORE_HINTS
2245cdf0e10cSrcweir     // emit the privdict header
2246cdf0e10cSrcweir     pOut += sprintf( pOut,
2247cdf0e10cSrcweir         "\110\104\125 "
2248cdf0e10cSrcweir         "dup\n/Private %d dict dup begin\n"
2249cdf0e10cSrcweir         "/RD{string currentfile exch readstring pop}executeonly def\n"
2250cdf0e10cSrcweir         "/ND{noaccess def}executeonly def\n"
2251cdf0e10cSrcweir         "/NP{noaccess put}executeonly def\n"
2252cdf0e10cSrcweir         "/MinFeature{16 16}ND\n"
2253cdf0e10cSrcweir         "/password 5839 def\n",     // TODO: mnRDCryptSeed?
2254cdf0e10cSrcweir             nPrivEntryCount);
2255cdf0e10cSrcweir 
2256cdf0e10cSrcweir #if defined(IGNORE_HINTS)
2257cdf0e10cSrcweir     pOut += sprintf( pOut, "/BlueValues []ND\n");   // BlueValues are mandatory
2258cdf0e10cSrcweir #else
2259cdf0e10cSrcweir     // emit blue hint related privdict entries
2260cdf0e10cSrcweir     if( !mpCffLocal->maBlueValues.empty())
2261cdf0e10cSrcweir         rEmitter.emitValVector( "/BlueValues [", "]ND\n", mpCffLocal->maBlueValues);
2262cdf0e10cSrcweir     else
2263cdf0e10cSrcweir         pOut += sprintf( pOut, "/BlueValues []ND\n"); // default to empty BlueValues
2264cdf0e10cSrcweir     rEmitter.emitValVector( "/OtherBlues [", "]ND\n", mpCffLocal->maOtherBlues);
2265cdf0e10cSrcweir     rEmitter.emitValVector( "/FamilyBlues [", "]ND\n", mpCffLocal->maFamilyBlues);
2266cdf0e10cSrcweir     rEmitter.emitValVector( "/FamilyOtherBlues [", "]ND\n", mpCffLocal->maFamilyOtherBlues);
2267cdf0e10cSrcweir 
2268cdf0e10cSrcweir     if( mpCffLocal->mfBlueScale) {
2269cdf0e10cSrcweir         pOut += sprintf( pOut, "/BlueScale ");
2270cdf0e10cSrcweir         pOut += dbl2str( pOut, mpCffLocal->mfBlueScale, 6);
2271cdf0e10cSrcweir         pOut += sprintf( pOut, " def\n");
2272cdf0e10cSrcweir     }
2273cdf0e10cSrcweir     if( mpCffLocal->mfBlueShift) {  // default BlueShift==7
2274cdf0e10cSrcweir         pOut += sprintf( pOut, "/BlueShift ");
2275cdf0e10cSrcweir         pOut += dbl2str( pOut, mpCffLocal->mfBlueShift);
2276cdf0e10cSrcweir         pOut += sprintf( pOut, " def\n");
2277cdf0e10cSrcweir     }
2278cdf0e10cSrcweir     if( mpCffLocal->mfBlueFuzz) {       // default BlueFuzz==1
2279cdf0e10cSrcweir         pOut += sprintf( pOut, "/BlueFuzz ");
2280cdf0e10cSrcweir         pOut += dbl2str( pOut, mpCffLocal->mfBlueFuzz);
2281cdf0e10cSrcweir         pOut += sprintf( pOut, " def\n");
2282cdf0e10cSrcweir     }
2283cdf0e10cSrcweir 
2284cdf0e10cSrcweir     // emit stem hint related privdict entries
2285cdf0e10cSrcweir     if( mpCffLocal->maStemStdHW) {
2286cdf0e10cSrcweir         pOut += sprintf( pOut, "/StdHW [");
2287cdf0e10cSrcweir         pOut += dbl2str( pOut, mpCffLocal->maStemStdHW);
2288cdf0e10cSrcweir         pOut += sprintf( pOut, "] def\n");
2289cdf0e10cSrcweir     }
2290cdf0e10cSrcweir     if( mpCffLocal->maStemStdVW) {
2291cdf0e10cSrcweir         pOut += sprintf( pOut, "/StdVW [");
2292cdf0e10cSrcweir         pOut += dbl2str( pOut, mpCffLocal->maStemStdVW);
2293cdf0e10cSrcweir         pOut += sprintf( pOut, "] def\n");
2294cdf0e10cSrcweir     }
2295cdf0e10cSrcweir     rEmitter.emitValVector( "/StemSnapH [", "]ND\n", mpCffLocal->maStemSnapH);
2296cdf0e10cSrcweir     rEmitter.emitValVector( "/StemSnapV [", "]ND\n", mpCffLocal->maStemSnapV);
2297cdf0e10cSrcweir 
2298cdf0e10cSrcweir     // emit other hints
2299cdf0e10cSrcweir     if( mpCffLocal->mbForceBold)
2300cdf0e10cSrcweir         pOut += sprintf( pOut, "/ForceBold true def\n");
2301cdf0e10cSrcweir     if( mpCffLocal->mnLangGroup != 0)
2302cdf0e10cSrcweir         pOut += sprintf( pOut, "/LanguageGroup %d def\n", mpCffLocal->mnLangGroup);
2303cdf0e10cSrcweir     if( mpCffLocal->mnLangGroup == 1) // compatibility with ancient printers
2304cdf0e10cSrcweir         pOut += sprintf( pOut, "/RndStemUp false def\n");
2305cdf0e10cSrcweir     if( mpCffLocal->mfExpFactor) {
2306cdf0e10cSrcweir         pOut += sprintf( pOut, "/ExpansionFactor ");
2307cdf0e10cSrcweir         pOut += dbl2str( pOut, mpCffLocal->mfExpFactor);
2308cdf0e10cSrcweir         pOut += sprintf( pOut, " def\n");
2309cdf0e10cSrcweir     }
2310cdf0e10cSrcweir #endif // IGNORE_HINTS
2311cdf0e10cSrcweir 
2312cdf0e10cSrcweir     // emit remaining privdict entries
2313cdf0e10cSrcweir     pOut += sprintf( pOut, "/UniqueID %d def\n", nUniqueId);
2314cdf0e10cSrcweir     // TODO?: more privdict entries?
2315cdf0e10cSrcweir 
2316cdf0e10cSrcweir     static const char aOtherSubrs[] =
2317cdf0e10cSrcweir         "/OtherSubrs\n"
2318cdf0e10cSrcweir         "% Dummy code for faking flex hints\n"
2319cdf0e10cSrcweir         "[ {} {} {} {systemdict /internaldict known not {pop 3}\n"
2320cdf0e10cSrcweir         "{1183615869 systemdict /internaldict get exec\n"
2321cdf0e10cSrcweir         "dup /startlock known\n"
2322cdf0e10cSrcweir         "{/startlock get exec}\n"
2323cdf0e10cSrcweir         "{dup /strtlck known\n"
2324cdf0e10cSrcweir         "{/strtlck get exec}\n"
2325cdf0e10cSrcweir         "{pop 3}\nifelse}\nifelse}\nifelse\n} executeonly\n"
2326cdf0e10cSrcweir         "] ND\n";
2327cdf0e10cSrcweir     memcpy( pOut, aOtherSubrs, sizeof(aOtherSubrs)-1);
2328cdf0e10cSrcweir     pOut += sizeof(aOtherSubrs)-1;
2329cdf0e10cSrcweir 
2330cdf0e10cSrcweir     // emit used GlobalSubr charstrings
2331cdf0e10cSrcweir     // these are the just the default subrs
2332cdf0e10cSrcweir     // TODO: do we need them as the flex hints are resolved differently?
2333cdf0e10cSrcweir     static const char aSubrs[] =
2334cdf0e10cSrcweir         "/Subrs 5 array\n"
2335cdf0e10cSrcweir         "dup 0 15 RD \x5F\x3D\x6B\xAC\x3C\xBD\x74\x3D\x3E\x17\xA0\x86\x58\x08\x85 NP\n"
2336cdf0e10cSrcweir         "dup 1 9 RD \x5F\x3D\x6B\xD8\xA6\xB5\x68\xB6\xA2 NP\n"
2337cdf0e10cSrcweir         "dup 2 9 RD \x5F\x3D\x6B\xAC\x39\x46\xB9\x43\xF9 NP\n"
2338cdf0e10cSrcweir         "dup 3 5 RD \x5F\x3D\x6B\xAC\xB9 NP\n"
2339cdf0e10cSrcweir         "dup 4 12 RD \x5F\x3D\x6B\xAC\x3E\x5D\x48\x54\x62\x76\x39\x03 NP\n"
2340cdf0e10cSrcweir         "ND\n";
2341cdf0e10cSrcweir     memcpy( pOut, aSubrs, sizeof(aSubrs)-1);
2342cdf0e10cSrcweir     pOut += sizeof(aSubrs)-1;
2343cdf0e10cSrcweir 
2344cdf0e10cSrcweir     // TODO: emit more GlobalSubr charstrings?
2345cdf0e10cSrcweir     // TODO: emit used LocalSubr charstrings?
2346cdf0e10cSrcweir 
2347cdf0e10cSrcweir     // emit the CharStrings for the requested glyphs
2348cdf0e10cSrcweir     pOut += sprintf( pOut,
2349cdf0e10cSrcweir         "2 index /CharStrings %d dict dup begin\n", nGlyphCount);
2350cdf0e10cSrcweir     rEmitter.emitAllCrypted();
2351cdf0e10cSrcweir     for( int i = 0; i < nGlyphCount; ++i) {
2352248a599fSHerbert Dürr         const int nCffGlyphId = pReqGlyphIds[i];
2353248a599fSHerbert Dürr         assert( (nCffGlyphId >= 0) && (nCffGlyphId < mnCharStrCount));
2354cdf0e10cSrcweir         // get privdict context matching to the glyph
2355248a599fSHerbert Dürr         const int nFDSelect = getFDSelect( nCffGlyphId);
235615336cfdSHerbert Dürr         if( nFDSelect < 0)
235715336cfdSHerbert Dürr             continue;
2358cdf0e10cSrcweir         mpCffLocal = &maCffLocal[ nFDSelect];
2359cdf0e10cSrcweir         // convert the Type2op charstring to its Type1op counterpart
2360248a599fSHerbert Dürr         const int nT2Len = seekIndexData( mnCharStrBase, nCffGlyphId);
2361cdf0e10cSrcweir         assert( nT2Len > 0);
2362cdf0e10cSrcweir         U8 aType1Ops[ MAX_T1OPS_SIZE]; // TODO: dynamic allocation
2363cdf0e10cSrcweir         const int nT1Len = convert2Type1Ops( mpCffLocal, mpReadPtr, nT2Len, aType1Ops);
2364cdf0e10cSrcweir         // get the glyph name
2365248a599fSHerbert Dürr         const char* pGlyphName = getGlyphName( nCffGlyphId);
2366cdf0e10cSrcweir         // emit the encrypted Type1op charstring
2367cdf0e10cSrcweir         pOut += sprintf( pOut, "/%s %d RD ", pGlyphName, nT1Len);
2368cdf0e10cSrcweir         memcpy( pOut, aType1Ops, nT1Len);
2369cdf0e10cSrcweir         pOut += nT1Len;
2370cdf0e10cSrcweir         pOut += sprintf( pOut, " ND\n");
2371cdf0e10cSrcweir         rEmitter.emitAllCrypted();
2372cdf0e10cSrcweir         // provide individual glyphwidths if requested
2373cdf0e10cSrcweir         if( pGlyphWidths ) {
2374cdf0e10cSrcweir             ValType aCharWidth = getCharWidth();
2375cdf0e10cSrcweir             if( maFontMatrix.size() >= 4)
2376cdf0e10cSrcweir                 aCharWidth *= 1000.0F * maFontMatrix[0];
2377cdf0e10cSrcweir             pGlyphWidths[i] = static_cast<GlyphWidth>(aCharWidth);
2378cdf0e10cSrcweir         }
2379cdf0e10cSrcweir     }
2380cdf0e10cSrcweir     pOut += sprintf( pOut, "end end\nreadonly put\nput\n");
2381cdf0e10cSrcweir     pOut += sprintf( pOut, "dup/FontName get exch definefont pop\n");
2382cdf0e10cSrcweir     pOut += sprintf( pOut, "mark currentfile closefile\n");
2383cdf0e10cSrcweir     rEmitter.emitAllCrypted();
2384cdf0e10cSrcweir 
2385cdf0e10cSrcweir     // mark stop of eexec encryption
2386cdf0e10cSrcweir     if( rEmitter.mbPfbSubset) {
2387cdf0e10cSrcweir         const int nEExecLen = rEmitter.tellPos() - nEExecSegTell;
2388cdf0e10cSrcweir         rEmitter.updateLen( nEExecSegTell-4, nEExecLen);
2389cdf0e10cSrcweir     }
2390cdf0e10cSrcweir 
2391cdf0e10cSrcweir     // create PFB footer
2392cdf0e10cSrcweir     static const char aPfxFooter[] = "\x80\x01\x14\x02\x00\x00\n" // TODO: check segment len
2393cdf0e10cSrcweir         "0000000000000000000000000000000000000000000000000000000000000000\n"
2394cdf0e10cSrcweir         "0000000000000000000000000000000000000000000000000000000000000000\n"
2395cdf0e10cSrcweir         "0000000000000000000000000000000000000000000000000000000000000000\n"
2396cdf0e10cSrcweir         "0000000000000000000000000000000000000000000000000000000000000000\n"
2397cdf0e10cSrcweir         "0000000000000000000000000000000000000000000000000000000000000000\n"
2398cdf0e10cSrcweir         "0000000000000000000000000000000000000000000000000000000000000000\n"
2399cdf0e10cSrcweir         "0000000000000000000000000000000000000000000000000000000000000000\n"
2400cdf0e10cSrcweir         "0000000000000000000000000000000000000000000000000000000000000000\n"
2401cdf0e10cSrcweir         "cleartomark\n"
2402cdf0e10cSrcweir         "\x80\x03";
2403cdf0e10cSrcweir     if( rEmitter.mbPfbSubset)
2404cdf0e10cSrcweir         rEmitter.emitRawData( aPfxFooter, sizeof(aPfxFooter)-1);
2405cdf0e10cSrcweir     else
2406cdf0e10cSrcweir         rEmitter.emitRawData( aPfxFooter+6, sizeof(aPfxFooter)-9);
2407cdf0e10cSrcweir 
2408cdf0e10cSrcweir     // provide details to the subset requesters, TODO: move into own method?
2409cdf0e10cSrcweir     // note: Top and Bottom are flipped between Type1 and VCL
2410cdf0e10cSrcweir     // note: the rest of VCL expects the details below to be scaled like for an emUnits==1000 font
2411cdf0e10cSrcweir     ValType fXFactor = 1.0;
2412cdf0e10cSrcweir     ValType fYFactor = 1.0;
2413cdf0e10cSrcweir     if( maFontMatrix.size() >= 4) {
2414cdf0e10cSrcweir         fXFactor = 1000.0F * maFontMatrix[0];
2415cdf0e10cSrcweir         fYFactor = 1000.0F * maFontMatrix[3];
2416cdf0e10cSrcweir     }
2417cdf0e10cSrcweir     rFSInfo.m_aFontBBox = Rectangle( Point( static_cast<long>(maFontBBox[0] * fXFactor),
2418cdf0e10cSrcweir                                         static_cast<long>(maFontBBox[1] * fYFactor) ),
2419cdf0e10cSrcweir                                     Point( static_cast<long>(maFontBBox[2] * fXFactor),
2420cdf0e10cSrcweir                                         static_cast<long>(maFontBBox[3] * fYFactor) ) );
2421cdf0e10cSrcweir     // PDF-Spec says the values below mean the ink bounds!
2422cdf0e10cSrcweir     // TODO: use better approximations for these ink bounds
2423cdf0e10cSrcweir     rFSInfo.m_nAscent  = +rFSInfo.m_aFontBBox.Bottom(); // for capital letters
2424cdf0e10cSrcweir     rFSInfo.m_nDescent = -rFSInfo.m_aFontBBox.Top();    // for all letters
2425cdf0e10cSrcweir     rFSInfo.m_nCapHeight = rFSInfo.m_nAscent;           // for top-flat capital letters
2426cdf0e10cSrcweir 
2427cdf0e10cSrcweir     rFSInfo.m_nFontType = rEmitter.mbPfbSubset ? FontSubsetInfo::TYPE1_PFB : FontSubsetInfo::TYPE1_PFA;
2428cdf0e10cSrcweir     rFSInfo.m_aPSName   = String( rEmitter.maSubsetName, RTL_TEXTENCODING_UTF8 );
2429cdf0e10cSrcweir 
2430cdf0e10cSrcweir     return true;
2431cdf0e10cSrcweir }
2432cdf0e10cSrcweir 
2433cdf0e10cSrcweir // ====================================================================
2434cdf0e10cSrcweir 
CreateFontSubsetFromCff(GlyphWidth * pOutGlyphWidths)2435cdf0e10cSrcweir bool FontSubsetInfo::CreateFontSubsetFromCff( GlyphWidth* pOutGlyphWidths )
2436cdf0e10cSrcweir {
2437cdf0e10cSrcweir     CffSubsetterContext aCff( mpInFontBytes, mnInByteLength);
2438cdf0e10cSrcweir     aCff.initialCffRead();
2439cdf0e10cSrcweir 
2440cdf0e10cSrcweir     // emit Type1 subset from the CFF input
2441cdf0e10cSrcweir     // TODO: also support CFF->CFF subsetting (when PDF-export and PS-printing need it)
2442cdf0e10cSrcweir     const bool bPfbSubset = (0 != (mnReqFontTypeMask & FontSubsetInfo::TYPE1_PFB));
2443cdf0e10cSrcweir     Type1Emitter aType1Emitter( mpOutFile, bPfbSubset);
2444cdf0e10cSrcweir     aType1Emitter.setSubsetName( mpReqFontName);
2445cdf0e10cSrcweir     bool bRC = aCff.emitAsType1( aType1Emitter,
2446cdf0e10cSrcweir         mpReqGlyphIds, mpReqEncodedIds,
2447cdf0e10cSrcweir         pOutGlyphWidths, mnReqGlyphCount, *this);
2448cdf0e10cSrcweir     return bRC;
2449cdf0e10cSrcweir }
2450cdf0e10cSrcweir 
2451cdf0e10cSrcweir // ====================================================================
2452cdf0e10cSrcweir 
2453*245cfa32Smseidel /* vim: set noet sw=4 ts=4: */
2454