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