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