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
109f62ea84SAndrew Rist *
119f62ea84SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0
129f62ea84SAndrew Rist *
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.
199f62ea84SAndrew Rist *
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
434f60319cSAkikazu 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",
85cdf0e10cSrcweir "caron", "endash", "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
161*25e830b3SArrigo Marchiori /** TOP DICT keywords (also covers PRIV DICT keywords)
162*25e830b3SArrigo Marchiori *
163*25e830b3SArrigo Marchiori * Refer to the CFF Specification, tables 9 and 23.
164*25e830b3SArrigo Marchiori *
165*25e830b3SArrigo Marchiori * This array is indexed by operand.
166*25e830b3SArrigo Marchiori *
167*25e830b3SArrigo Marchiori * The first character tells the type of operand ('s': SID, 'b': boolean etc.).
168*25e830b3SArrigo 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
182*25e830b3SArrigo Marchiori /** TOP DICT escapes (also covers PRIV DICT escapes)
183*25e830b3SArrigo Marchiori *
184*25e830b3SArrigo Marchiori * Refer to the CFF Specification, tables 9 and 23.
185*25e830b3SArrigo Marchiori *
186*25e830b3SArrigo Marchiori * These operators come after the escape operator (no. 12).
187*25e830b3SArrigo Marchiori *
188*25e830b3SArrigo Marchiori * This array is indexed by operand.
189*25e830b3SArrigo Marchiori *
190*25e830b3SArrigo Marchiori * The first character tells the type of operand ('s': SID, 'b': boolean etc.).
191*25e830b3SArrigo 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
309*25e830b3SArrigo Marchiori /** Data layout of a CFF FontSet
310*25e830b3SArrigo Marchiori *
311*25e830b3SArrigo Marchiori * Refer to the CFF specification, chapter 2
312*25e830b3SArrigo Marchiori */
313cdf0e10cSrcweir struct CffGlobal
314cdf0e10cSrcweir {
315cdf0e10cSrcweir explicit CffGlobal();
316cdf0e10cSrcweir
317*25e830b3SArrigo Marchiori // Offset of the Name INDEX inside the CFF data
318cdf0e10cSrcweir int mnNameIdxBase;
319*25e830b3SArrigo 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
379*25e830b3SArrigo Marchiori : private CffGlobal
380cdf0e10cSrcweir {
381cdf0e10cSrcweir public:
382*25e830b3SArrigo Marchiori // Refer to Type 2 charstring format appendix B, "Type 2 Charstring Implementation Limits"
383*25e830b3SArrigo Marchiori static const int NMAXSTACK = 48; // argument stack
384*25e830b3SArrigo Marchiori static const int NMAXHINTS = 2*96; // number of stem hints (H/V total)
385*25e830b3SArrigo Marchiori static const int NMAXTRANS = 32; // TransientArray elements
386cdf0e10cSrcweir public:
387cdf0e10cSrcweir explicit CffSubsetterContext( const U8* pBasePtr, int nBaseLen);
388cdf0e10cSrcweir virtual ~CffSubsetterContext( void);
389cdf0e10cSrcweir
390*25e830b3SArrigo 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
407*25e830b3SArrigo Marchiori // First byte of CFF font data
408cdf0e10cSrcweir const U8* mpBasePtr;
409*25e830b3SArrigo Marchiori // Last byte of CFF font data
410cdf0e10cSrcweir const U8* mpBaseEnd;
411cdf0e10cSrcweir
412*25e830b3SArrigo 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:
423*25e830b3SArrigo Marchiori /** Prepare to access an element inside a CFF/CID index table
424*25e830b3SArrigo Marchiori *
425*25e830b3SArrigo Marchiori * nIndexBase: offset of the INDEX structure inside the CFF font data.
426*25e830b3SArrigo Marchiori * nDataIndex: offset of the element inside the INDEX structure.
427*25e830b3SArrigo Marchiori *
428*25e830b3SArrigo Marchiori * Sets mpReadPtr to the beginning of the element and mpReadEnd to the end of the element.
429*25e830b3SArrigo Marchiori *
430*25e830b3SArrigo Marchiori * Returns the size of the element, or -1 if the data is not valid (e.g. indices are too big).
431*25e830b3SArrigo Marchiori */
432cdf0e10cSrcweir int seekIndexData( int nIndexBase, int nDataIndex);
433*25e830b3SArrigo Marchiori /** Seek to the end of an INDEX structure
434*25e830b3SArrigo Marchiori *
435*25e830b3SArrigo Marchiori * nIndexBase: offset of the INDEX structure inside the CFF font data.
436*25e830b3SArrigo Marchiori *
437*25e830b3SArrigo Marchiori * Sets mpReadPtr to the first byte after the indicated structure.
438*25e830b3SArrigo Marchiori */
439cdf0e10cSrcweir void seekIndexEnd( int nIndexBase);
440cdf0e10cSrcweir
441cdf0e10cSrcweir private:
442cdf0e10cSrcweir const char** mpCharStringOps;
443cdf0e10cSrcweir const char** mpCharStringEscs;
444cdf0e10cSrcweir
445*25e830b3SArrigo 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
455*25e830b3SArrigo Marchiori /** Decode an integer DICT Data Operand and push it.
456*25e830b3SArrigo Marchiori *
457*25e830b3SArrigo Marchiori * Refer to the CFF Specification, table 3.
458*25e830b3SArrigo Marchiori *
459*25e830b3SArrigo Marchiori * Advances mpReadPtr.
460*25e830b3SArrigo 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
499*25e830b3SArrigo Marchiori
500*25e830b3SArrigo Marchiori // Count of mnValStack elements
501cdf0e10cSrcweir int mnStackIdx;
502*25e830b3SArrigo Marchiori // Stack for holding CFF DICT operands
503cdf0e10cSrcweir ValType mnValStack[ NMAXSTACK+4];
504*25e830b3SArrigo 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);
525*25e830b3SArrigo 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
643*25e830b3SArrigo Marchiori /** Read DICT operator at mpReadPtr.
644*25e830b3SArrigo Marchiori *
645*25e830b3SArrigo Marchiori * Sets the attributes of CffSubsetterContext::mpCffLocal
646*25e830b3SArrigo Marchiori */
readDictOp(void)647cdf0e10cSrcweir void CffSubsetterContext::readDictOp( void)
648cdf0e10cSrcweir {
649cdf0e10cSrcweir ValType nVal = 0;
650*25e830b3SArrigo Marchiori int nInt = 0;
651cdf0e10cSrcweir const U8 c = *mpReadPtr;
652*25e830b3SArrigo 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];
657*25e830b3SArrigo 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)
664*25e830b3SArrigo 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;
756*25e830b3SArrigo Marchiori } else if( (c >= 32) || (c == 28) ) {
757cdf0e10cSrcweir // --mpReadPtr;
758cdf0e10cSrcweir read2push();
759*25e830b3SArrigo 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 );
770*25e830b3SArrigo 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;
787*25e830b3SArrigo 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;
1355*25e830b3SArrigo Marchiori seekIndexData( mnGlobalSubrBase, nSubrNumber);
1356cdf0e10cSrcweir } else {
1357cdf0e10cSrcweir nSubrNumber += mpCffLocal->mnLocalSubrBias;
1358*25e830b3SArrigo 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];
1703*25e830b3SArrigo Marchiori if (maCffLocal.size() < static_cast<size_t>(mnFDAryCount))
1704*25e830b3SArrigo 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);
1927b87d82ffSHerbert Dürr 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
1934b87d82ffSHerbert Dürr int mnEECryptR;
1935cdf0e10cSrcweir public:
1936cdf0e10cSrcweir char* mpPtr;
1937cdf0e10cSrcweir
1938cdf0e10cSrcweir char maSubsetName[256];
1939cdf0e10cSrcweir bool mbPfbSubset;
1940b87d82ffSHerbert Dürr 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)
2013b87d82ffSHerbert Dürr 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
210068c47c4eSmseidel 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
211368c47c4eSmseidel 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