xref: /aoo41x/main/vcl/source/fontsubset/cff.cxx (revision 25e830b3)
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