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