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