~ubuntu-branches/ubuntu/vivid/emscripten/vivid

« back to all changes in this revision

Viewing changes to tests/poppler/fofi/FoFiType1C.cc

  • Committer: Package Import Robot
  • Author(s): Sylvestre Ledru
  • Date: 2013-05-02 13:11:51 UTC
  • Revision ID: package-import@ubuntu.com-20130502131151-q8dvteqr1ef2x7xz
Tags: upstream-1.4.1~20130504~adb56cb
ImportĀ upstreamĀ versionĀ 1.4.1~20130504~adb56cb

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//========================================================================
 
2
//
 
3
// FoFiType1C.cc
 
4
//
 
5
// Copyright 1999-2003 Glyph & Cog, LLC
 
6
//
 
7
//========================================================================
 
8
 
 
9
//========================================================================
 
10
//
 
11
// Modified under the Poppler project - http://poppler.freedesktop.org
 
12
//
 
13
// All changes made under the Poppler project to this file are licensed
 
14
// under GPL version 2 or later
 
15
//
 
16
// Copyright (C) 2009, 2010 Albert Astals Cid <aacid@kde.org>
 
17
//
 
18
// To see a description of the changes please see the Changelog file that
 
19
// came with your tarball or type make ChangeLog if you are building from git
 
20
//
 
21
//========================================================================
 
22
 
 
23
#include <config.h>
 
24
 
 
25
#ifdef USE_GCC_PRAGMAS
 
26
#pragma implementation
 
27
#endif
 
28
 
 
29
#include <stdlib.h>
 
30
#include <string.h>
 
31
#include <math.h>
 
32
#include "goo/gmem.h"
 
33
#include "goo/gstrtod.h"
 
34
#include "goo/GooString.h"
 
35
#include "FoFiEncodings.h"
 
36
#include "FoFiType1C.h"
 
37
 
 
38
//------------------------------------------------------------------------
 
39
 
 
40
static char hexChars[17] = "0123456789ABCDEF";
 
41
 
 
42
//------------------------------------------------------------------------
 
43
// FoFiType1C
 
44
//------------------------------------------------------------------------
 
45
 
 
46
FoFiType1C *FoFiType1C::make(char *fileA, int lenA) {
 
47
  FoFiType1C *ff;
 
48
 
 
49
  ff = new FoFiType1C(fileA, lenA, gFalse);
 
50
  if (!ff->parse()) {
 
51
    delete ff;
 
52
    return NULL;
 
53
  }
 
54
  return ff;
 
55
}
 
56
 
 
57
FoFiType1C *FoFiType1C::load(char *fileName) {
 
58
  FoFiType1C *ff;
 
59
  char *fileA;
 
60
  int lenA;
 
61
 
 
62
  if (!(fileA = FoFiBase::readFile(fileName, &lenA))) {
 
63
    return NULL;
 
64
  }
 
65
  ff = new FoFiType1C(fileA, lenA, gTrue);
 
66
  if (!ff->parse()) {
 
67
    delete ff;
 
68
    return NULL;
 
69
  }
 
70
  return ff;
 
71
}
 
72
 
 
73
FoFiType1C::FoFiType1C(char *fileA, int lenA, GBool freeFileDataA):
 
74
  FoFiBase(fileA, lenA, freeFileDataA)
 
75
{
 
76
  name = NULL;
 
77
  encoding = NULL;
 
78
  privateDicts = NULL;
 
79
  fdSelect = NULL;
 
80
  charset = NULL;
 
81
}
 
82
 
 
83
FoFiType1C::~FoFiType1C() {
 
84
  int i;
 
85
 
 
86
  if (name) {
 
87
    delete name;
 
88
  }
 
89
  if (encoding &&
 
90
      encoding != fofiType1StandardEncoding &&
 
91
      encoding != fofiType1ExpertEncoding) {
 
92
    for (i = 0; i < 256; ++i) {
 
93
      gfree(encoding[i]);
 
94
    }
 
95
    gfree(encoding);
 
96
  }
 
97
  if (privateDicts) {
 
98
    gfree(privateDicts);
 
99
  }
 
100
  if (fdSelect) {
 
101
    gfree(fdSelect);
 
102
  }
 
103
  if (charset &&
 
104
      charset != fofiType1CISOAdobeCharset &&
 
105
      charset != fofiType1CExpertCharset &&
 
106
      charset != fofiType1CExpertSubsetCharset) {
 
107
    gfree(charset);
 
108
  }
 
109
}
 
110
 
 
111
char *FoFiType1C::getName() {
 
112
  return name ? name->getCString() : (char *)NULL;
 
113
}
 
114
 
 
115
char **FoFiType1C::getEncoding() {
 
116
  return encoding;
 
117
}
 
118
 
 
119
Gushort *FoFiType1C::getCIDToGIDMap(int *nCIDs) {
 
120
  Gushort *map;
 
121
  int n, i;
 
122
 
 
123
  // a CID font's top dict has ROS as the first operator
 
124
  if (topDict.firstOp != 0x0c1e) {
 
125
    *nCIDs = 0;
 
126
    return NULL;
 
127
  }
 
128
 
 
129
  // in a CID font, the charset data is the GID-to-CID mapping, so all
 
130
  // we have to do is reverse it
 
131
  n = 0;
 
132
  for (i = 0; i < nGlyphs; ++i) {
 
133
    if (charset[i] > n) {
 
134
      n = charset[i];
 
135
    }
 
136
  }
 
137
  ++n;
 
138
  map = (Gushort *)gmallocn(n, sizeof(Gushort));
 
139
  memset(map, 0, n * sizeof(Gushort));
 
140
  for (i = 0; i < nGlyphs; ++i) {
 
141
    map[charset[i]] = i;
 
142
  }
 
143
  *nCIDs = n;
 
144
  return map;
 
145
}
 
146
 
 
147
void FoFiType1C::convertToType1(char *psName, char **newEncoding, GBool ascii,
 
148
                                FoFiOutputFunc outputFunc,
 
149
                                void *outputStream) {
 
150
  int psNameLen;
 
151
  Type1CEexecBuf eb;
 
152
  Type1CIndex subrIdx;
 
153
  Type1CIndexVal val;
 
154
  GooString *buf;
 
155
  char buf2[256];
 
156
  char **enc;
 
157
  GBool ok;
 
158
  int i;
 
159
 
 
160
  if (psName) {
 
161
    psNameLen = strlen(psName);
 
162
  } else {
 
163
    psName = name->getCString();
 
164
    psNameLen = name->getLength();
 
165
  }
 
166
 
 
167
  // write header and font dictionary, up to encoding
 
168
  ok = gTrue;
 
169
  (*outputFunc)(outputStream, "%!FontType1-1.0: ", 17);
 
170
  (*outputFunc)(outputStream, psName, psNameLen);
 
171
  if (topDict.versionSID != 0) {
 
172
    getString(topDict.versionSID, buf2, &ok);
 
173
    (*outputFunc)(outputStream, buf2, strlen(buf2));
 
174
  }
 
175
  (*outputFunc)(outputStream, "\n", 1);
 
176
  // the dictionary needs room for 12 entries: the following 9, plus
 
177
  // Private and CharStrings (in the eexec section) and FID (which is
 
178
  // added by definefont)
 
179
  (*outputFunc)(outputStream, "12 dict begin\n", 14);
 
180
  (*outputFunc)(outputStream, "/FontInfo 10 dict dup begin\n", 28);
 
181
  if (topDict.versionSID != 0) {
 
182
    (*outputFunc)(outputStream, "/version (", 10);
 
183
    (*outputFunc)(outputStream, buf2, strlen(buf2));
 
184
    (*outputFunc)(outputStream, ") readonly def\n", 15);
 
185
  }
 
186
  if (topDict.noticeSID != 0) {
 
187
    getString(topDict.noticeSID, buf2, &ok);
 
188
    (*outputFunc)(outputStream, "/Notice (", 9);
 
189
    (*outputFunc)(outputStream, buf2, strlen(buf2));
 
190
    (*outputFunc)(outputStream, ") readonly def\n", 15);
 
191
  }
 
192
  if (topDict.copyrightSID != 0) {
 
193
    getString(topDict.copyrightSID, buf2, &ok);
 
194
    (*outputFunc)(outputStream, "/Copyright (", 12);
 
195
    (*outputFunc)(outputStream, buf2, strlen(buf2));
 
196
    (*outputFunc)(outputStream, ") readonly def\n", 15);
 
197
  }
 
198
  if (topDict.fullNameSID != 0) {
 
199
    getString(topDict.fullNameSID, buf2, &ok);
 
200
    (*outputFunc)(outputStream, "/FullName (", 11);
 
201
    (*outputFunc)(outputStream, buf2, strlen(buf2));
 
202
    (*outputFunc)(outputStream, ") readonly def\n", 15);
 
203
  }
 
204
  if (topDict.familyNameSID != 0) {
 
205
    getString(topDict.familyNameSID, buf2, &ok);
 
206
    (*outputFunc)(outputStream, "/FamilyName (", 13);
 
207
    (*outputFunc)(outputStream, buf2, strlen(buf2));
 
208
    (*outputFunc)(outputStream, ") readonly def\n", 15);
 
209
  }
 
210
  if (topDict.weightSID != 0) {
 
211
    getString(topDict.weightSID, buf2, &ok);
 
212
    (*outputFunc)(outputStream, "/Weight (", 9);
 
213
    (*outputFunc)(outputStream, buf2, strlen(buf2));
 
214
    (*outputFunc)(outputStream, ") readonly def\n", 15);
 
215
  }
 
216
  if (topDict.isFixedPitch) {
 
217
    (*outputFunc)(outputStream, "/isFixedPitch true def\n", 23);
 
218
  } else {
 
219
    (*outputFunc)(outputStream, "/isFixedPitch false def\n", 24);
 
220
  }
 
221
  buf = GooString::format("/ItalicAngle {0:.4g} def\n", topDict.italicAngle);
 
222
  (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
223
  delete buf;
 
224
  buf = GooString::format("/UnderlinePosition {0:.4g} def\n",
 
225
                        topDict.underlinePosition);
 
226
  (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
227
  delete buf;
 
228
  buf = GooString::format("/UnderlineThickness {0:.4g} def\n",
 
229
                        topDict.underlineThickness);
 
230
  (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
231
  delete buf;
 
232
  (*outputFunc)(outputStream, "end readonly def\n", 17);
 
233
  (*outputFunc)(outputStream, "/FontName /", 11);
 
234
  (*outputFunc)(outputStream, psName, psNameLen);
 
235
  (*outputFunc)(outputStream, " def\n", 5);
 
236
  buf = GooString::format("/PaintType {0:d} def\n", topDict.paintType);
 
237
  (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
238
  delete buf;
 
239
  (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
 
240
  buf = GooString::format("/FontMatrix [{0:.8g} {1:.8g} {2:.8g} {3:.8g} {4:.8g} {5:.8g}] readonly def\n",
 
241
                        topDict.fontMatrix[0], topDict.fontMatrix[1],
 
242
                        topDict.fontMatrix[2], topDict.fontMatrix[3],
 
243
                        topDict.fontMatrix[4], topDict.fontMatrix[5]);
 
244
  (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
245
  delete buf;
 
246
  buf = GooString::format("/FontBBox [{0:.4g} {1:.4g} {2:.4g} {3:.4g}] readonly def\n",
 
247
                        topDict.fontBBox[0], topDict.fontBBox[1],
 
248
                        topDict.fontBBox[2], topDict.fontBBox[3]);
 
249
  (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
250
  delete buf;
 
251
  buf = GooString::format("/StrokeWidth {0:.4g} def\n", topDict.strokeWidth);
 
252
  (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
253
  delete buf;
 
254
  if (topDict.uniqueID != 0) {
 
255
    buf = GooString::format("/UniqueID {0:d} def\n", topDict.uniqueID);
 
256
    (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
257
    delete buf;
 
258
  }
 
259
 
 
260
  // write the encoding
 
261
  (*outputFunc)(outputStream, "/Encoding ", 10);
 
262
  if (!newEncoding && encoding == fofiType1StandardEncoding) {
 
263
    (*outputFunc)(outputStream, "StandardEncoding def\n", 21);
 
264
  } else {
 
265
    (*outputFunc)(outputStream, "256 array\n", 10);
 
266
    (*outputFunc)(outputStream,
 
267
                  "0 1 255 {1 index exch /.notdef put} for\n", 40);
 
268
    enc = newEncoding ? newEncoding : encoding;
 
269
    for (i = 0; i < 256; ++i) {
 
270
      if (enc[i]) {
 
271
        buf = GooString::format("dup {0:d} /{1:s} put\n", i, enc[i]);
 
272
        (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
273
        delete buf;
 
274
      }
 
275
    }
 
276
    (*outputFunc)(outputStream, "readonly def\n", 13);
 
277
  }
 
278
  (*outputFunc)(outputStream, "currentdict end\n", 16);
 
279
 
 
280
  // start the binary section
 
281
  (*outputFunc)(outputStream, "currentfile eexec\n", 18);
 
282
  eb.outputFunc = outputFunc;
 
283
  eb.outputStream = outputStream;
 
284
  eb.ascii = ascii;
 
285
  eb.r1 = 55665;
 
286
  eb.line = 0;
 
287
 
 
288
  // write the private dictionary
 
289
  eexecWrite(&eb, "\x83\xca\x73\xd5");
 
290
  eexecWrite(&eb, "dup /Private 32 dict dup begin\n");
 
291
  eexecWrite(&eb, "/RD {string currentfile exch readstring pop}"
 
292
             " executeonly def\n");
 
293
  eexecWrite(&eb, "/ND {noaccess def} executeonly def\n");
 
294
  eexecWrite(&eb, "/NP {noaccess put} executeonly def\n");
 
295
  eexecWrite(&eb, "/MinFeature {16 16} def\n");
 
296
  eexecWrite(&eb, "/password 5839 def\n");
 
297
  if (privateDicts[0].nBlueValues) {
 
298
    eexecWrite(&eb, "/BlueValues [");
 
299
    for (i = 0; i < privateDicts[0].nBlueValues; ++i) {
 
300
      buf = GooString::format("{0:s}{1:d}",
 
301
                            i > 0 ? " " : "", privateDicts[0].blueValues[i]);
 
302
      eexecWrite(&eb, buf->getCString());
 
303
      delete buf;
 
304
    }
 
305
    eexecWrite(&eb, "] def\n");
 
306
  }
 
307
  if (privateDicts[0].nOtherBlues) {
 
308
    eexecWrite(&eb, "/OtherBlues [");
 
309
    for (i = 0; i < privateDicts[0].nOtherBlues; ++i) {
 
310
      buf = GooString::format("{0:s}{1:d}",
 
311
                            i > 0 ? " " : "", privateDicts[0].otherBlues[i]);
 
312
      eexecWrite(&eb, buf->getCString());
 
313
      delete buf;
 
314
    }
 
315
    eexecWrite(&eb, "] def\n");
 
316
  }
 
317
  if (privateDicts[0].nFamilyBlues) {
 
318
    eexecWrite(&eb, "/FamilyBlues [");
 
319
    for (i = 0; i < privateDicts[0].nFamilyBlues; ++i) {
 
320
      buf = GooString::format("{0:s}{1:d}",
 
321
                            i > 0 ? " " : "", privateDicts[0].familyBlues[i]);
 
322
      eexecWrite(&eb, buf->getCString());
 
323
      delete buf;
 
324
    }
 
325
    eexecWrite(&eb, "] def\n");
 
326
  }
 
327
  if (privateDicts[0].nFamilyOtherBlues) {
 
328
    eexecWrite(&eb, "/FamilyOtherBlues [");
 
329
    for (i = 0; i < privateDicts[0].nFamilyOtherBlues; ++i) {
 
330
      buf = GooString::format("{0:s}{1:d}", i > 0 ? " " : "",
 
331
                            privateDicts[0].familyOtherBlues[i]);
 
332
      eexecWrite(&eb, buf->getCString());
 
333
      delete buf;
 
334
    }
 
335
    eexecWrite(&eb, "] def\n");
 
336
  }
 
337
  if (privateDicts[0].blueScale != 0.039625) {
 
338
    buf = GooString::format("/BlueScale {0:.4g} def\n",
 
339
                          privateDicts[0].blueScale);
 
340
    eexecWrite(&eb, buf->getCString());
 
341
    delete buf;
 
342
  }
 
343
  if (privateDicts[0].blueShift != 7) {
 
344
    buf = GooString::format("/BlueShift {0:d} def\n", privateDicts[0].blueShift);
 
345
    eexecWrite(&eb, buf->getCString());
 
346
    delete buf;
 
347
  }
 
348
  if (privateDicts[0].blueFuzz != 1) {
 
349
    buf = GooString::format("/BlueFuzz {0:d} def\n", privateDicts[0].blueFuzz);
 
350
    eexecWrite(&eb, buf->getCString());
 
351
    delete buf;
 
352
  }
 
353
  if (privateDicts[0].hasStdHW) {
 
354
    buf = GooString::format("/StdHW [{0:.4g}] def\n", privateDicts[0].stdHW);
 
355
    eexecWrite(&eb, buf->getCString());
 
356
    delete buf;
 
357
  }
 
358
  if (privateDicts[0].hasStdVW) {
 
359
    buf = GooString::format("/StdVW [{0:.4g}] def\n", privateDicts[0].stdVW);
 
360
    eexecWrite(&eb, buf->getCString());
 
361
    delete buf;
 
362
  }
 
363
  if (privateDicts[0].nStemSnapH) {
 
364
    eexecWrite(&eb, "/StemSnapH [");
 
365
    for (i = 0; i < privateDicts[0].nStemSnapH; ++i) {
 
366
      buf = GooString::format("{0:s}{1:.4g}",
 
367
                            i > 0 ? " " : "", privateDicts[0].stemSnapH[i]);
 
368
      eexecWrite(&eb, buf->getCString());
 
369
      delete buf;
 
370
    }
 
371
    eexecWrite(&eb, "] def\n");
 
372
  }
 
373
  if (privateDicts[0].nStemSnapV) {
 
374
    eexecWrite(&eb, "/StemSnapV [");
 
375
    for (i = 0; i < privateDicts[0].nStemSnapV; ++i) {
 
376
      buf = GooString::format("{0:s}{1:.4g}",
 
377
                            i > 0 ? " " : "", privateDicts[0].stemSnapV[i]);
 
378
      eexecWrite(&eb, buf->getCString());
 
379
      delete buf;
 
380
    }
 
381
    eexecWrite(&eb, "] def\n");
 
382
  }
 
383
  if (privateDicts[0].hasForceBold) {
 
384
    buf = GooString::format("/ForceBold {0:s} def\n",
 
385
                          privateDicts[0].forceBold ? "true" : "false");
 
386
    eexecWrite(&eb, buf->getCString());
 
387
    delete buf;
 
388
  }
 
389
  if (privateDicts[0].forceBoldThreshold != 0) {
 
390
    buf = GooString::format("/ForceBoldThreshold {0:.4g} def\n",
 
391
                          privateDicts[0].forceBoldThreshold);
 
392
    eexecWrite(&eb, buf->getCString());
 
393
    delete buf;
 
394
  }
 
395
  if (privateDicts[0].languageGroup != 0) {
 
396
    buf = GooString::format("/LanguageGroup {0:d} def\n",
 
397
                          privateDicts[0].languageGroup);
 
398
    eexecWrite(&eb, buf->getCString());
 
399
    delete buf;
 
400
  }
 
401
  if (privateDicts[0].expansionFactor != 0.06) {
 
402
    buf = GooString::format("/ExpansionFactor {0:.4g} def\n",
 
403
                          privateDicts[0].expansionFactor);
 
404
    eexecWrite(&eb, buf->getCString());
 
405
    delete buf;
 
406
  }
 
407
 
 
408
  // set up subroutines
 
409
  ok = gTrue;
 
410
  getIndex(privateDicts[0].subrsOffset, &subrIdx, &ok);
 
411
  if (!ok) {
 
412
    subrIdx.pos = -1;
 
413
  }
 
414
 
 
415
  // write the CharStrings
 
416
  buf = GooString::format("2 index /CharStrings {0:d} dict dup begin\n",
 
417
                        nGlyphs);
 
418
  eexecWrite(&eb, buf->getCString());
 
419
  delete buf;
 
420
  for (i = 0; i < nGlyphs; ++i) {
 
421
    ok = gTrue;
 
422
    getIndexVal(&charStringsIdx, i, &val, &ok);
 
423
    if (ok) {
 
424
      getString(charset[i], buf2, &ok);
 
425
      if (ok) {
 
426
        eexecCvtGlyph(&eb, buf2, val.pos, val.len, &subrIdx, &privateDicts[0]);
 
427
      }
 
428
    }
 
429
  }
 
430
  eexecWrite(&eb, "end\n");
 
431
  eexecWrite(&eb, "end\n");
 
432
  eexecWrite(&eb, "readonly put\n");
 
433
  eexecWrite(&eb, "noaccess put\n");
 
434
  eexecWrite(&eb, "dup /FontName get exch definefont pop\n");
 
435
  eexecWrite(&eb, "mark currentfile closefile\n");
 
436
 
 
437
  // trailer
 
438
  if (ascii && eb.line > 0) {
 
439
    (*outputFunc)(outputStream, "\n", 1);
 
440
  }
 
441
  for (i = 0; i < 8; ++i) {
 
442
    (*outputFunc)(outputStream, "0000000000000000000000000000000000000000000000000000000000000000\n", 65);
 
443
  }
 
444
  (*outputFunc)(outputStream, "cleartomark\n", 12);
 
445
}
 
446
 
 
447
void FoFiType1C::convertToCIDType0(char *psName,
 
448
                                   FoFiOutputFunc outputFunc,
 
449
                                   void *outputStream) {
 
450
  int *cidMap;
 
451
  GooString *charStrings;
 
452
  int *charStringOffsets;
 
453
  Type1CIndex subrIdx;
 
454
  Type1CIndexVal val;
 
455
  int nCIDs, gdBytes;
 
456
  GooString *buf;
 
457
  char buf2[256];
 
458
  GBool ok;
 
459
  int gid, offset, n, i, j, k;
 
460
 
 
461
  // compute the CID count and build the CID-to-GID mapping
 
462
  nCIDs = 0;
 
463
  for (i = 0; i < nGlyphs; ++i) {
 
464
    if (charset[i] >= nCIDs) {
 
465
      nCIDs = charset[i] + 1;
 
466
    }
 
467
  }
 
468
  cidMap = (int *)gmallocn(nCIDs, sizeof(int));
 
469
  for (i = 0; i < nCIDs; ++i) {
 
470
    cidMap[i] = -1;
 
471
  }
 
472
  for (i = 0; i < nGlyphs; ++i) {
 
473
    cidMap[charset[i]] = i;
 
474
  }
 
475
 
 
476
  // build the charstrings
 
477
  charStrings = new GooString();
 
478
  charStringOffsets = (int *)gmallocn(nCIDs + 1, sizeof(int));
 
479
  for (i = 0; i < nCIDs; ++i) {
 
480
    charStringOffsets[i] = charStrings->getLength();
 
481
    if ((gid = cidMap[i]) >= 0) {
 
482
      ok = gTrue;
 
483
      getIndexVal(&charStringsIdx, gid, &val, &ok);
 
484
      if (ok) {
 
485
        getIndex(privateDicts[fdSelect[gid]].subrsOffset, &subrIdx, &ok);
 
486
        if (!ok) {
 
487
          subrIdx.pos = -1;
 
488
        }
 
489
        cvtGlyph(val.pos, val.len, charStrings,
 
490
                 &subrIdx, &privateDicts[fdSelect[gid]], gTrue);
 
491
      }
 
492
    }
 
493
  }
 
494
  charStringOffsets[nCIDs] = charStrings->getLength();
 
495
 
 
496
  // compute gdBytes = number of bytes needed for charstring offsets
 
497
  // (offset size needs to account for the charstring offset table,
 
498
  // with a worst case of five bytes per entry, plus the charstrings
 
499
  // themselves)
 
500
  i = (nCIDs + 1) * 5 + charStrings->getLength();
 
501
  if (i < 0x100) {
 
502
    gdBytes = 1;
 
503
  } else if (i < 0x10000) {
 
504
    gdBytes = 2;
 
505
  } else if (i < 0x1000000) {
 
506
    gdBytes = 3;
 
507
  } else {
 
508
    gdBytes = 4;
 
509
  }
 
510
 
 
511
  // begin the font dictionary
 
512
  (*outputFunc)(outputStream, "/CIDInit /ProcSet findresource begin\n", 37);
 
513
  (*outputFunc)(outputStream, "20 dict begin\n", 14);
 
514
  (*outputFunc)(outputStream, "/CIDFontName /", 14);
 
515
  (*outputFunc)(outputStream, psName, strlen(psName));
 
516
  (*outputFunc)(outputStream, " def\n", 5);
 
517
  (*outputFunc)(outputStream, "/CIDFontType 0 def\n", 19);
 
518
  (*outputFunc)(outputStream, "/CIDSystemInfo 3 dict dup begin\n", 32);
 
519
  if (topDict.registrySID > 0 && topDict.orderingSID > 0) {
 
520
    ok = gTrue;
 
521
    getString(topDict.registrySID, buf2, &ok);
 
522
    if (ok) {
 
523
      (*outputFunc)(outputStream, "  /Registry (", 13);
 
524
      (*outputFunc)(outputStream, buf2, strlen(buf2));
 
525
      (*outputFunc)(outputStream, ") def\n", 6);
 
526
    }
 
527
    ok = gTrue;
 
528
    getString(topDict.orderingSID, buf2, &ok);
 
529
    if (ok) {
 
530
      (*outputFunc)(outputStream, "  /Ordering (", 13);
 
531
      (*outputFunc)(outputStream, buf2, strlen(buf2));
 
532
      (*outputFunc)(outputStream, ") def\n", 6);
 
533
    }
 
534
  } else {
 
535
    (*outputFunc)(outputStream, "  /Registry (Adobe) def\n", 24);
 
536
    (*outputFunc)(outputStream, "  /Ordering (Identity) def\n", 27);
 
537
  }
 
538
  buf = GooString::format("  /Supplement {0:d} def\n", topDict.supplement);
 
539
  (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
540
  delete buf;
 
541
  (*outputFunc)(outputStream, "end def\n", 8);
 
542
  if (topDict.hasFontMatrix) {
 
543
    buf = GooString::format("/FontMatrix [{0:.8g} {1:.8g} {2:.8g} {3:.8g} {4:.8g} {5:.8g}] def\n",
 
544
                          topDict.fontMatrix[0], topDict.fontMatrix[1],
 
545
                          topDict.fontMatrix[2], topDict.fontMatrix[3],
 
546
                          topDict.fontMatrix[4], topDict.fontMatrix[5]);
 
547
    (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
548
    delete buf;
 
549
  } else if (privateDicts[0].hasFontMatrix) {
 
550
    (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
 
551
  } else {
 
552
    (*outputFunc)(outputStream,
 
553
                  "/FontMatrix [0.001 0 0 0.001 0 0] def\n", 38);
 
554
  }
 
555
  buf = GooString::format("/FontBBox [{0:.4g} {1:.4g} {2:.4g} {3:.4g}] def\n",
 
556
                        topDict.fontBBox[0], topDict.fontBBox[1],
 
557
                        topDict.fontBBox[2], topDict.fontBBox[3]);
 
558
  (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
559
  delete buf;
 
560
  (*outputFunc)(outputStream, "/FontInfo 1 dict dup begin\n", 27);
 
561
  (*outputFunc)(outputStream, "  /FSType 8 def\n", 16);
 
562
  (*outputFunc)(outputStream, "end def\n", 8);
 
563
 
 
564
  // CIDFont-specific entries
 
565
  buf = GooString::format("/CIDCount {0:d} def\n", nCIDs);
 
566
  (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
567
  delete buf;
 
568
  (*outputFunc)(outputStream, "/FDBytes 1 def\n", 15);
 
569
  buf = GooString::format("/GDBytes {0:d} def\n", gdBytes);
 
570
  (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
571
  delete buf;
 
572
  (*outputFunc)(outputStream, "/CIDMapOffset 0 def\n", 20);
 
573
  if (topDict.paintType != 0) {
 
574
    buf = GooString::format("/PaintType {0:d} def\n", topDict.paintType);
 
575
    (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
576
    delete buf;
 
577
    buf = GooString::format("/StrokeWidth {0:.4g} def\n", topDict.strokeWidth);
 
578
    (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
579
    delete buf;
 
580
  }
 
581
 
 
582
  // FDArray entry
 
583
  buf = GooString::format("/FDArray {0:d} array\n", nFDs);
 
584
  (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
585
  delete buf;
 
586
  for (i = 0; i < nFDs; ++i) {
 
587
    buf = GooString::format("dup {0:d} 10 dict begin\n", i);
 
588
    (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
589
    delete buf;
 
590
    (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
 
591
    if (privateDicts[i].hasFontMatrix) {
 
592
      buf = GooString::format("/FontMatrix [{0:.8g} {1:.8g} {2:.8g} {3:.8g} {4:.8g} {5:.8g}] def\n",
 
593
                            privateDicts[i].fontMatrix[0],
 
594
                            privateDicts[i].fontMatrix[1],
 
595
                            privateDicts[i].fontMatrix[2],
 
596
                            privateDicts[i].fontMatrix[3],
 
597
                            privateDicts[i].fontMatrix[4],
 
598
                            privateDicts[i].fontMatrix[5]);
 
599
      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
600
      delete buf;
 
601
    } else {
 
602
      (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
 
603
    }
 
604
    buf = GooString::format("/PaintType {0:d} def\n", topDict.paintType);
 
605
    (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
606
    delete buf;
 
607
    (*outputFunc)(outputStream, "/Private 32 dict begin\n", 23);
 
608
    if (privateDicts[i].nBlueValues) {
 
609
      (*outputFunc)(outputStream, "/BlueValues [", 13);
 
610
      for (j = 0; j < privateDicts[i].nBlueValues; ++j) {
 
611
        buf = GooString::format("{0:s}{1:d}",
 
612
                              j > 0 ? " " : "", privateDicts[i].blueValues[j]);
 
613
        (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
614
        delete buf;
 
615
      }
 
616
      (*outputFunc)(outputStream, "] def\n", 6);
 
617
    }
 
618
    if (privateDicts[i].nOtherBlues) {
 
619
      (*outputFunc)(outputStream, "/OtherBlues [", 13);
 
620
      for (j = 0; j < privateDicts[i].nOtherBlues; ++j) {
 
621
        buf = GooString::format("{0:s}{1:d}",
 
622
                              j > 0 ? " " : "", privateDicts[i].otherBlues[j]);
 
623
        (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
624
        delete buf;
 
625
      }
 
626
      (*outputFunc)(outputStream, "] def\n", 6);
 
627
    }
 
628
    if (privateDicts[i].nFamilyBlues) {
 
629
      (*outputFunc)(outputStream, "/FamilyBlues [", 14);
 
630
      for (j = 0; j < privateDicts[i].nFamilyBlues; ++j) {
 
631
        buf = GooString::format("{0:s}{1:d}",
 
632
                              j > 0 ? " " : "",
 
633
                              privateDicts[i].familyBlues[j]);
 
634
        (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
635
        delete buf;
 
636
      }
 
637
      (*outputFunc)(outputStream, "] def\n", 6);
 
638
    }
 
639
    if (privateDicts[i].nFamilyOtherBlues) {
 
640
      (*outputFunc)(outputStream, "/FamilyOtherBlues [", 19);
 
641
      for (j = 0; j < privateDicts[i].nFamilyOtherBlues; ++j) {
 
642
        buf = GooString::format("{0:s}{1:d}", j > 0 ? " " : "",
 
643
                              privateDicts[i].familyOtherBlues[j]);
 
644
        (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
645
        delete buf;
 
646
      }
 
647
      (*outputFunc)(outputStream, "] def\n", 6);
 
648
    }
 
649
    if (privateDicts[i].blueScale != 0.039625) {
 
650
      buf = GooString::format("/BlueScale {0:.4g} def\n",
 
651
                            privateDicts[i].blueScale);
 
652
      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
653
      delete buf;
 
654
    }
 
655
    if (privateDicts[i].blueShift != 7) {
 
656
      buf = GooString::format("/BlueShift {0:d} def\n",
 
657
                            privateDicts[i].blueShift);
 
658
      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
659
      delete buf;
 
660
    }
 
661
    if (privateDicts[i].blueFuzz != 1) {
 
662
      buf = GooString::format("/BlueFuzz {0:d} def\n", privateDicts[i].blueFuzz);
 
663
      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
664
      delete buf;
 
665
    }
 
666
    if (privateDicts[i].hasStdHW) {
 
667
      buf = GooString::format("/StdHW [{0:.4g}] def\n", privateDicts[i].stdHW);
 
668
      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
669
      delete buf;
 
670
    }
 
671
    if (privateDicts[i].hasStdVW) {
 
672
      buf = GooString::format("/StdVW [{0:.4g}] def\n", privateDicts[i].stdVW);
 
673
      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
674
      delete buf;
 
675
    }
 
676
    if (privateDicts[i].nStemSnapH) {
 
677
      (*outputFunc)(outputStream, "/StemSnapH [", 12);
 
678
      for (j = 0; j < privateDicts[i].nStemSnapH; ++j) {
 
679
        buf = GooString::format("{0:s}{1:.4g}",
 
680
                              j > 0 ? " " : "", privateDicts[i].stemSnapH[j]);
 
681
        (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
682
        delete buf;
 
683
      }
 
684
      (*outputFunc)(outputStream, "] def\n", 6);
 
685
    }
 
686
    if (privateDicts[i].nStemSnapV) {
 
687
      (*outputFunc)(outputStream, "/StemSnapV [", 12);
 
688
      for (j = 0; j < privateDicts[i].nStemSnapV; ++j) {
 
689
        buf = GooString::format("{0:s}{1:.4g}",
 
690
                              j > 0 ? " " : "", privateDicts[i].stemSnapV[j]);
 
691
        (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
692
        delete buf;
 
693
      }
 
694
      (*outputFunc)(outputStream, "] def\n", 6);
 
695
    }
 
696
    if (privateDicts[i].hasForceBold) {
 
697
      buf = GooString::format("/ForceBold {0:s} def\n",
 
698
                            privateDicts[i].forceBold ? "true" : "false");
 
699
      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
700
      delete buf;
 
701
    }
 
702
    if (privateDicts[i].forceBoldThreshold != 0) {
 
703
      buf = GooString::format("/ForceBoldThreshold {0:.4g} def\n",
 
704
                            privateDicts[i].forceBoldThreshold);
 
705
      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
706
      delete buf;
 
707
    }
 
708
    if (privateDicts[i].languageGroup != 0) {
 
709
      buf = GooString::format("/LanguageGroup {0:d} def\n",
 
710
                            privateDicts[i].languageGroup);
 
711
      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
712
      delete buf;
 
713
    }
 
714
    if (privateDicts[i].expansionFactor != 0.06) {
 
715
      buf = GooString::format("/ExpansionFactor {0:.4g} def\n",
 
716
                            privateDicts[i].expansionFactor);
 
717
      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
718
      delete buf;
 
719
    }
 
720
    (*outputFunc)(outputStream, "currentdict end def\n", 20);
 
721
    (*outputFunc)(outputStream, "currentdict end put\n", 20);
 
722
  }
 
723
  (*outputFunc)(outputStream, "def\n", 4);
 
724
 
 
725
  // start the binary section
 
726
  offset = (nCIDs + 1) * (1 + gdBytes);
 
727
  buf = GooString::format("(Hex) {0:d} StartData\n",
 
728
                        offset + charStrings->getLength());
 
729
  (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
730
  delete buf;
 
731
 
 
732
  // write the charstring offset (CIDMap) table
 
733
  for (i = 0; i <= nCIDs; i += 6) {
 
734
    for (j = 0; j < 6 && i+j <= nCIDs; ++j) {
 
735
      if (i+j < nCIDs && cidMap[i+j] >= 0) {
 
736
        buf2[0] = (char)fdSelect[cidMap[i+j]];
 
737
      } else {
 
738
        buf2[0] = (char)0;
 
739
      }
 
740
      n = offset + charStringOffsets[i+j];
 
741
      for (k = gdBytes; k >= 1; --k) {
 
742
        buf2[k] = (char)(n & 0xff);
 
743
        n >>= 8;
 
744
      }
 
745
      for (k = 0; k <= gdBytes; ++k) {
 
746
        buf = GooString::format("{0:02x}", buf2[k] & 0xff);
 
747
        (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
748
        delete buf;
 
749
      }
 
750
    }
 
751
    (*outputFunc)(outputStream, "\n", 1);
 
752
  }
 
753
 
 
754
  // write the charstring data
 
755
  n = charStrings->getLength();
 
756
  for (i = 0; i < n; i += 32) {
 
757
    for (j = 0; j < 32 && i+j < n; ++j) {
 
758
      buf = GooString::format("{0:02x}", charStrings->getChar(i+j) & 0xff);
 
759
      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
760
      delete buf;
 
761
    }
 
762
    if (i + 32 >= n) {
 
763
      (*outputFunc)(outputStream, ">", 1);
 
764
    }
 
765
    (*outputFunc)(outputStream, "\n", 1);
 
766
  }
 
767
 
 
768
  gfree(charStringOffsets);
 
769
  delete charStrings;
 
770
  gfree(cidMap);
 
771
}
 
772
 
 
773
void FoFiType1C::convertToType0(char *psName,
 
774
                                FoFiOutputFunc outputFunc,
 
775
                                void *outputStream) {
 
776
  int *cidMap;
 
777
  Type1CIndex subrIdx;
 
778
  Type1CIndexVal val;
 
779
  int nCIDs;
 
780
  GooString *buf;
 
781
  Type1CEexecBuf eb;
 
782
  GBool ok;
 
783
  int fd, i, j, k;
 
784
 
 
785
  // compute the CID count and build the CID-to-GID mapping
 
786
  nCIDs = 0;
 
787
  for (i = 0; i < nGlyphs; ++i) {
 
788
    if (charset[i] >= nCIDs) {
 
789
      nCIDs = charset[i] + 1;
 
790
    }
 
791
  }
 
792
  cidMap = (int *)gmallocn(nCIDs, sizeof(int));
 
793
  for (i = 0; i < nCIDs; ++i) {
 
794
    cidMap[i] = -1;
 
795
  }
 
796
  for (i = 0; i < nGlyphs; ++i) {
 
797
    cidMap[charset[i]] = i;
 
798
  }
 
799
 
 
800
  // write the descendant Type 1 fonts
 
801
  for (i = 0; i < nCIDs; i += 256) {
 
802
 
 
803
    //~ this assumes that all CIDs in this block have the same FD --
 
804
    //~ to handle multiple FDs correctly, need to somehow divide the
 
805
    //~ font up by FD; as a kludge we ignore CID 0, which is .notdef
 
806
    fd = 0;
 
807
    if (fdSelect != NULL) {
 
808
      for (j = i==0 ? 1 : 0; j < 256 && i+j < nCIDs; ++j) {
 
809
        if (cidMap[i+j] >= 0) {
 
810
          fd = fdSelect[cidMap[i+j]];
 
811
          break;
 
812
        }
 
813
      }
 
814
    }
 
815
 
 
816
    // font dictionary (unencrypted section)
 
817
    (*outputFunc)(outputStream, "16 dict begin\n", 14);
 
818
    (*outputFunc)(outputStream, "/FontName /", 11);
 
819
    (*outputFunc)(outputStream, psName, strlen(psName));
 
820
    buf = GooString::format("_{0:02x} def\n", i >> 8);
 
821
    (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
822
    delete buf;
 
823
    (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
 
824
    if (privateDicts[fd].hasFontMatrix) {
 
825
      buf = GooString::format("/FontMatrix [{0:.8g} {1:.8g} {2:.8g} {3:.8g} {4:.8g} {5:.8g}] def\n",
 
826
                            privateDicts[fd].fontMatrix[0],
 
827
                            privateDicts[fd].fontMatrix[1],
 
828
                            privateDicts[fd].fontMatrix[2],
 
829
                            privateDicts[fd].fontMatrix[3],
 
830
                            privateDicts[fd].fontMatrix[4],
 
831
                            privateDicts[fd].fontMatrix[5]);
 
832
      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
833
      delete buf;
 
834
    } else if (topDict.hasFontMatrix) {
 
835
      (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
 
836
    } else {
 
837
      (*outputFunc)(outputStream,
 
838
                    "/FontMatrix [0.001 0 0 0.001 0 0] def\n", 38);
 
839
    }
 
840
    buf = GooString::format("/FontBBox [{0:.4g} {1:.4g} {2:.4g} {3:.4g}] def\n",
 
841
                          topDict.fontBBox[0], topDict.fontBBox[1],
 
842
                          topDict.fontBBox[2], topDict.fontBBox[3]);
 
843
    (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
844
    delete buf;
 
845
    buf = GooString::format("/PaintType {0:d} def\n", topDict.paintType);
 
846
    (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
847
    delete buf;
 
848
    if (topDict.paintType != 0) {
 
849
      buf = GooString::format("/StrokeWidth {0:.4g} def\n", topDict.strokeWidth);
 
850
      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
851
      delete buf;
 
852
    }
 
853
    (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
 
854
    for (j = 0; j < 256 && i+j < nCIDs; ++j) {
 
855
      buf = GooString::format("dup {0:d} /c{1:02x} put\n", j, j);
 
856
      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
857
      delete buf;
 
858
    }
 
859
    if (j < 256) {
 
860
      buf = GooString::format("{0:d} 1 255 {{ 1 index exch /.notdef put }} for\n",
 
861
                            j);
 
862
      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
863
      delete buf;
 
864
    }
 
865
    (*outputFunc)(outputStream, "readonly def\n", 13);
 
866
    (*outputFunc)(outputStream, "currentdict end\n", 16);
 
867
 
 
868
    // start the binary section
 
869
    (*outputFunc)(outputStream, "currentfile eexec\n", 18);
 
870
    eb.outputFunc = outputFunc;
 
871
    eb.outputStream = outputStream;
 
872
    eb.ascii = gTrue;
 
873
    eb.r1 = 55665;
 
874
    eb.line = 0;
 
875
 
 
876
    // start the private dictionary
 
877
    eexecWrite(&eb, "\x83\xca\x73\xd5");
 
878
    eexecWrite(&eb, "dup /Private 32 dict dup begin\n");
 
879
    eexecWrite(&eb, "/RD {string currentfile exch readstring pop}"
 
880
               " executeonly def\n");
 
881
    eexecWrite(&eb, "/ND {noaccess def} executeonly def\n");
 
882
    eexecWrite(&eb, "/NP {noaccess put} executeonly def\n");
 
883
    eexecWrite(&eb, "/MinFeature {16 16} def\n");
 
884
    eexecWrite(&eb, "/password 5839 def\n");
 
885
    if (privateDicts[fd].nBlueValues) {
 
886
      eexecWrite(&eb, "/BlueValues [");
 
887
      for (k = 0; k < privateDicts[fd].nBlueValues; ++k) {
 
888
        buf = GooString::format("{0:s}{1:d}",
 
889
                              k > 0 ? " " : "",
 
890
                              privateDicts[fd].blueValues[k]);
 
891
        eexecWrite(&eb, buf->getCString());
 
892
        delete buf;
 
893
      }
 
894
      eexecWrite(&eb, "] def\n");
 
895
    }
 
896
    if (privateDicts[fd].nOtherBlues) {
 
897
      eexecWrite(&eb, "/OtherBlues [");
 
898
      for (k = 0; k < privateDicts[fd].nOtherBlues; ++k) {
 
899
        buf = GooString::format("{0:s}{1:d}",
 
900
                              k > 0 ? " " : "",
 
901
                              privateDicts[fd].otherBlues[k]);
 
902
        eexecWrite(&eb, buf->getCString());
 
903
        delete buf;
 
904
      }
 
905
      eexecWrite(&eb, "] def\n");
 
906
    }
 
907
    if (privateDicts[fd].nFamilyBlues) {
 
908
      eexecWrite(&eb, "/FamilyBlues [");
 
909
      for (k = 0; k < privateDicts[fd].nFamilyBlues; ++k) {
 
910
        buf = GooString::format("{0:s}{1:d}", k > 0 ? " " : "",
 
911
                              privateDicts[fd].familyBlues[k]);
 
912
        eexecWrite(&eb, buf->getCString());
 
913
        delete buf;
 
914
      }
 
915
      eexecWrite(&eb, "] def\n");
 
916
    }
 
917
    if (privateDicts[fd].nFamilyOtherBlues) {
 
918
      eexecWrite(&eb, "/FamilyOtherBlues [");
 
919
      for (k = 0; k < privateDicts[fd].nFamilyOtherBlues; ++k) {
 
920
        buf = GooString::format("{0:s}{1:d}", k > 0 ? " " : "",
 
921
                              privateDicts[fd].familyOtherBlues[k]);
 
922
        eexecWrite(&eb, buf->getCString());
 
923
        delete buf;
 
924
      }
 
925
      eexecWrite(&eb, "] def\n");
 
926
    }
 
927
    if (privateDicts[fd].blueScale != 0.039625) {
 
928
      buf = GooString::format("/BlueScale {0:.4g} def\n",
 
929
                            privateDicts[fd].blueScale);
 
930
      eexecWrite(&eb, buf->getCString());
 
931
      delete buf;
 
932
    }
 
933
    if (privateDicts[fd].blueShift != 7) {
 
934
      buf = GooString::format("/BlueShift {0:d} def\n",
 
935
                            privateDicts[fd].blueShift);
 
936
      eexecWrite(&eb, buf->getCString());
 
937
      delete buf;
 
938
    }
 
939
    if (privateDicts[fd].blueFuzz != 1) {
 
940
      buf = GooString::format("/BlueFuzz {0:d} def\n",
 
941
                            privateDicts[fd].blueFuzz);
 
942
      eexecWrite(&eb, buf->getCString());
 
943
      delete buf;
 
944
    }
 
945
    if (privateDicts[fd].hasStdHW) {
 
946
      buf = GooString::format("/StdHW [{0:.4g}] def\n", privateDicts[fd].stdHW);
 
947
      eexecWrite(&eb, buf->getCString());
 
948
      delete buf;
 
949
    }
 
950
    if (privateDicts[fd].hasStdVW) {
 
951
      buf = GooString::format("/StdVW [{0:.4g}] def\n", privateDicts[fd].stdVW);
 
952
      eexecWrite(&eb, buf->getCString());
 
953
      delete buf;
 
954
    }
 
955
    if (privateDicts[fd].nStemSnapH) {
 
956
      eexecWrite(&eb, "/StemSnapH [");
 
957
      for (k = 0; k < privateDicts[fd].nStemSnapH; ++k) {
 
958
        buf = GooString::format("{0:s}{1:.4g}",
 
959
                              k > 0 ? " " : "", privateDicts[fd].stemSnapH[k]);
 
960
        eexecWrite(&eb, buf->getCString());
 
961
        delete buf;
 
962
      }
 
963
      eexecWrite(&eb, "] def\n");
 
964
    }
 
965
    if (privateDicts[fd].nStemSnapV) {
 
966
      eexecWrite(&eb, "/StemSnapV [");
 
967
      for (k = 0; k < privateDicts[fd].nStemSnapV; ++k) {
 
968
        buf = GooString::format("{0:s}{1:.4g}",
 
969
                              k > 0 ? " " : "", privateDicts[fd].stemSnapV[k]);
 
970
        eexecWrite(&eb, buf->getCString());
 
971
        delete buf;
 
972
      }
 
973
      eexecWrite(&eb, "] def\n");
 
974
    }
 
975
    if (privateDicts[fd].hasForceBold) {
 
976
      buf = GooString::format("/ForceBold {0:s} def\n",
 
977
                            privateDicts[fd].forceBold ? "true" : "false");
 
978
      eexecWrite(&eb, buf->getCString());
 
979
      delete buf;
 
980
    }
 
981
    if (privateDicts[fd].forceBoldThreshold != 0) {
 
982
      buf = GooString::format("/ForceBoldThreshold {0:.4g} def\n",
 
983
                            privateDicts[fd].forceBoldThreshold);
 
984
      eexecWrite(&eb, buf->getCString());
 
985
      delete buf;
 
986
    }
 
987
    if (privateDicts[fd].languageGroup != 0) {
 
988
      buf = GooString::format("/LanguageGroup {0:d} def\n",
 
989
                            privateDicts[fd].languageGroup);
 
990
      eexecWrite(&eb, buf->getCString());
 
991
      delete buf;
 
992
    }
 
993
    if (privateDicts[fd].expansionFactor != 0.06) {
 
994
      buf = GooString::format("/ExpansionFactor {0:.4g} def\n",
 
995
                            privateDicts[fd].expansionFactor);
 
996
      eexecWrite(&eb, buf->getCString());
 
997
      delete buf;
 
998
    }
 
999
 
 
1000
    // set up the subroutines
 
1001
    ok = gTrue;
 
1002
    getIndex(privateDicts[fd].subrsOffset, &subrIdx, &ok);
 
1003
    if (!ok) {
 
1004
      subrIdx.pos = -1;
 
1005
    }
 
1006
 
 
1007
    // start the CharStrings
 
1008
    eexecWrite(&eb, "2 index /CharStrings 256 dict dup begin\n");
 
1009
 
 
1010
    // write the .notdef CharString
 
1011
    ok = gTrue;
 
1012
    getIndexVal(&charStringsIdx, 0, &val, &ok);
 
1013
    if (ok) {
 
1014
      eexecCvtGlyph(&eb, ".notdef", val.pos, val.len,
 
1015
                    &subrIdx, &privateDicts[fd]);
 
1016
    }
 
1017
 
 
1018
    // write the CharStrings
 
1019
    for (j = 0; j < 256 && i+j < nCIDs; ++j) {
 
1020
      if (cidMap[i+j] >= 0) {
 
1021
        ok = gTrue;
 
1022
        getIndexVal(&charStringsIdx, cidMap[i+j], &val, &ok);
 
1023
        if (ok) {
 
1024
          buf = GooString::format("c{0:02x}", j);
 
1025
          eexecCvtGlyph(&eb, buf->getCString(), val.pos, val.len,
 
1026
                        &subrIdx, &privateDicts[fd]);
 
1027
          delete buf;
 
1028
        }
 
1029
      }
 
1030
    }
 
1031
    eexecWrite(&eb, "end\n");
 
1032
    eexecWrite(&eb, "end\n");
 
1033
    eexecWrite(&eb, "readonly put\n");
 
1034
    eexecWrite(&eb, "noaccess put\n");
 
1035
    eexecWrite(&eb, "dup /FontName get exch definefont pop\n");
 
1036
    eexecWrite(&eb, "mark currentfile closefile\n");
 
1037
 
 
1038
    // trailer
 
1039
    if (eb.line > 0) {
 
1040
      (*outputFunc)(outputStream, "\n", 1);
 
1041
    }
 
1042
    for (j = 0; j < 8; ++j) {
 
1043
      (*outputFunc)(outputStream, "0000000000000000000000000000000000000000000000000000000000000000\n", 65);
 
1044
    }
 
1045
    (*outputFunc)(outputStream, "cleartomark\n", 12);
 
1046
  }
 
1047
 
 
1048
  // write the Type 0 parent font
 
1049
  (*outputFunc)(outputStream, "16 dict begin\n", 14);
 
1050
  (*outputFunc)(outputStream, "/FontName /", 11);
 
1051
  (*outputFunc)(outputStream, psName, strlen(psName));
 
1052
  (*outputFunc)(outputStream, " def\n", 5);
 
1053
  (*outputFunc)(outputStream, "/FontType 0 def\n", 16);
 
1054
  if (topDict.hasFontMatrix) {
 
1055
    buf = GooString::format("/FontMatrix [{0:.8g} {1:.8g} {2:.8g} {3:.8g} {4:.8g} {5:.8g}] def\n",
 
1056
                          topDict.fontMatrix[0], topDict.fontMatrix[1],
 
1057
                          topDict.fontMatrix[2], topDict.fontMatrix[3],
 
1058
                          topDict.fontMatrix[4], topDict.fontMatrix[5]);
 
1059
    (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
1060
    delete buf;
 
1061
  } else {
 
1062
    (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
 
1063
  }
 
1064
  (*outputFunc)(outputStream, "/FMapType 2 def\n", 16);
 
1065
  (*outputFunc)(outputStream, "/Encoding [\n", 12);
 
1066
  for (i = 0; i < nCIDs; i += 256) {
 
1067
    buf = GooString::format("{0:d}\n", i >> 8);
 
1068
    (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
1069
    delete buf;
 
1070
  }
 
1071
  (*outputFunc)(outputStream, "] def\n", 6);
 
1072
  (*outputFunc)(outputStream, "/FDepVector [\n", 14);
 
1073
  for (i = 0; i < nCIDs; i += 256) {
 
1074
    (*outputFunc)(outputStream, "/", 1);
 
1075
    (*outputFunc)(outputStream, psName, strlen(psName));
 
1076
    buf = GooString::format("_{0:02x} findfont\n", i >> 8);
 
1077
    (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
1078
    delete buf;
 
1079
  }
 
1080
  (*outputFunc)(outputStream, "] def\n", 6);
 
1081
  (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
 
1082
 
 
1083
  gfree(cidMap);
 
1084
}
 
1085
 
 
1086
void FoFiType1C::eexecCvtGlyph(Type1CEexecBuf *eb, char *glyphName,
 
1087
                               int offset, int nBytes,
 
1088
                               Type1CIndex *subrIdx,
 
1089
                               Type1CPrivateDict *pDict) {
 
1090
  GooString *buf;
 
1091
  GooString *charBuf;
 
1092
 
 
1093
  // generate the charstring
 
1094
  charBuf = new GooString();
 
1095
  cvtGlyph(offset, nBytes, charBuf, subrIdx, pDict, gTrue);
 
1096
 
 
1097
  buf = GooString::format("/{0:s} {1:d} RD ", glyphName, charBuf->getLength());
 
1098
  eexecWrite(eb, buf->getCString());
 
1099
  delete buf;
 
1100
  eexecWriteCharstring(eb, (Guchar *)charBuf->getCString(),
 
1101
                       charBuf->getLength());
 
1102
  eexecWrite(eb, " ND\n");
 
1103
 
 
1104
  delete charBuf;
 
1105
}
 
1106
 
 
1107
void FoFiType1C::cvtGlyph(int offset, int nBytes, GooString *charBuf,
 
1108
                          Type1CIndex *subrIdx, Type1CPrivateDict *pDict,
 
1109
                          GBool top) {
 
1110
  Type1CIndexVal val;
 
1111
  GBool ok, dFP;
 
1112
  double d, dx, dy;
 
1113
  Gushort r2;
 
1114
  Guchar byte;
 
1115
  int pos, subrBias, start, i, k;
 
1116
 
 
1117
  start = charBuf->getLength();
 
1118
  if (top) {
 
1119
    charBuf->append((char)73);
 
1120
    charBuf->append((char)58);
 
1121
    charBuf->append((char)147);
 
1122
    charBuf->append((char)134);
 
1123
    nOps = 0;
 
1124
    nHints = 0;
 
1125
    firstOp = gTrue;
 
1126
    openPath = gFalse;
 
1127
  }
 
1128
 
 
1129
  pos = offset;
 
1130
  while (pos < offset + nBytes) {
 
1131
    ok = gTrue;
 
1132
    pos = getOp(pos, gTrue, &ok);
 
1133
    if (!ok) {
 
1134
      break;
 
1135
    }
 
1136
    if (!ops[nOps - 1].isNum) {
 
1137
      --nOps; // drop the operator
 
1138
      switch (ops[nOps].op) {
 
1139
      case 0x0001:              // hstem
 
1140
        if (firstOp) {
 
1141
          cvtGlyphWidth(nOps & 1, charBuf, pDict);
 
1142
          firstOp = gFalse;
 
1143
        }
 
1144
        if (nOps & 1) {
 
1145
          //~ error(-1, "Wrong number of args (%d) to Type 2 hstem", nOps);
 
1146
        }
 
1147
        d = 0;
 
1148
        dFP = gFalse;
 
1149
        for (k = 0; k < nOps; k += 2) {
 
1150
          // convert Type 2 edge hints (-20 or -21) to Type 1 ghost hints
 
1151
          if (ops[k+1].num < 0) {
 
1152
            d += ops[k].num + ops[k+1].num;
 
1153
            dFP |= ops[k].isFP | ops[k+1].isFP;
 
1154
            cvtNum(d, dFP, charBuf);
 
1155
            cvtNum(-ops[k+1].num, ops[k+1].isFP, charBuf);
 
1156
          } else {
 
1157
            d += ops[k].num;
 
1158
            dFP |= ops[k].isFP;
 
1159
            cvtNum(d, dFP, charBuf);
 
1160
            cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
 
1161
            d += ops[k+1].num;
 
1162
            dFP |= ops[k+1].isFP;
 
1163
          }
 
1164
          charBuf->append((char)1);
 
1165
        }
 
1166
        nHints += nOps / 2;
 
1167
        nOps = 0;
 
1168
        break;
 
1169
      case 0x0003:              // vstem
 
1170
        if (firstOp) {
 
1171
          cvtGlyphWidth(nOps & 1, charBuf, pDict);
 
1172
          firstOp = gFalse;
 
1173
        }
 
1174
        if (nOps & 1) {
 
1175
          //~ error(-1, "Wrong number of args (%d) to Type 2 vstem", nOps);
 
1176
        }
 
1177
        d = 0;
 
1178
        dFP = gFalse;
 
1179
        for (k = 0; k < nOps; k += 2) {
 
1180
          // convert Type 2 edge hints (-20 or -21) to Type 1 ghost hints
 
1181
          if (ops[k+1].num < 0) {
 
1182
            d += ops[k].num + ops[k+1].num;
 
1183
            dFP |= ops[k].isFP | ops[k+1].isFP;
 
1184
            cvtNum(d, dFP, charBuf);
 
1185
            cvtNum(-ops[k+1].num, ops[k+1].isFP, charBuf);
 
1186
          } else {
 
1187
            d += ops[k].num;
 
1188
            dFP |= ops[k].isFP;
 
1189
            cvtNum(d, dFP, charBuf);
 
1190
            cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
 
1191
            d += ops[k+1].num;
 
1192
            dFP |= ops[k+1].isFP;
 
1193
          }
 
1194
          charBuf->append((char)3);
 
1195
        }
 
1196
        nHints += nOps / 2;
 
1197
        nOps = 0;
 
1198
        break;
 
1199
      case 0x0004:              // vmoveto
 
1200
        if (firstOp) {
 
1201
          cvtGlyphWidth(nOps == 2, charBuf, pDict);
 
1202
          firstOp = gFalse;
 
1203
        }
 
1204
        if (openPath) {
 
1205
          charBuf->append((char)9);
 
1206
          openPath = gFalse;
 
1207
        }
 
1208
        if (nOps != 1) {
 
1209
          //~ error(-1, "Wrong number of args (%d) to Type 2 vmoveto", nOps);
 
1210
        }
 
1211
        cvtNum(ops[0].num, ops[0].isFP, charBuf);
 
1212
        charBuf->append((char)4);
 
1213
        nOps = 0;
 
1214
        break;
 
1215
      case 0x0005:              // rlineto
 
1216
        if (nOps < 2 || nOps % 2 != 0) {
 
1217
          //~ error(-1, "Wrong number of args (%d) to Type 2 rlineto", nOps);
 
1218
        }
 
1219
        for (k = 0; k < nOps; k += 2) {
 
1220
          cvtNum(ops[k].num, ops[k].isFP, charBuf);
 
1221
          cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
 
1222
          charBuf->append((char)5);
 
1223
        }
 
1224
        nOps = 0;
 
1225
        openPath = gTrue;
 
1226
        break;
 
1227
      case 0x0006:              // hlineto
 
1228
        if (nOps < 1) {
 
1229
          //~ error(-1, "Wrong number of args (%d) to Type 2 hlineto", nOps);
 
1230
        }
 
1231
        for (k = 0; k < nOps; ++k) {
 
1232
          cvtNum(ops[k].num, ops[k].isFP, charBuf);
 
1233
          charBuf->append((char)((k & 1) ? 7 : 6));
 
1234
        }
 
1235
        nOps = 0;
 
1236
        openPath = gTrue;
 
1237
        break;
 
1238
      case 0x0007:              // vlineto
 
1239
        if (nOps < 1) {
 
1240
          //~ error(-1, "Wrong number of args (%d) to Type 2 vlineto", nOps);
 
1241
        }
 
1242
        for (k = 0; k < nOps; ++k) {
 
1243
          cvtNum(ops[k].num, ops[k].isFP, charBuf);
 
1244
          charBuf->append((char)((k & 1) ? 6 : 7));
 
1245
        }
 
1246
        nOps = 0;
 
1247
        openPath = gTrue;
 
1248
        break;
 
1249
      case 0x0008:              // rrcurveto
 
1250
        if (nOps < 6 || nOps % 6 != 0) {
 
1251
          //~ error(-1, "Wrong number of args (%d) to Type 2 rrcurveto", nOps);
 
1252
        }
 
1253
        for (k = 0; k < nOps; k += 6) {
 
1254
          cvtNum(ops[k].num, ops[k].isFP, charBuf);
 
1255
          cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
 
1256
          cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
 
1257
          cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
 
1258
          cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
 
1259
          cvtNum(ops[k+5].num, ops[k+5].isFP, charBuf);
 
1260
          charBuf->append((char)8);
 
1261
        }
 
1262
        nOps = 0;
 
1263
        openPath = gTrue;
 
1264
        break;
 
1265
      case 0x000a:              // callsubr
 
1266
        if (nOps >= 1) {
 
1267
          subrBias = (subrIdx->len < 1240)
 
1268
                       ? 107 : (subrIdx->len < 33900) ? 1131 : 32768;
 
1269
          k = subrBias + (int)ops[nOps - 1].num;
 
1270
          --nOps;
 
1271
          ok = gTrue;
 
1272
          getIndexVal(subrIdx, k, &val, &ok);
 
1273
          if (ok) {
 
1274
            cvtGlyph(val.pos, val.len, charBuf, subrIdx, pDict, gFalse);
 
1275
          }
 
1276
        } else {
 
1277
          //~ error(-1, "Too few args to Type 2 callsubr");
 
1278
        }
 
1279
        // don't clear the stack
 
1280
        break;
 
1281
      case 0x000b:              // return
 
1282
        // don't clear the stack
 
1283
        break;
 
1284
      case 0x000e:              // endchar / seac
 
1285
        if (firstOp) {
 
1286
          cvtGlyphWidth(nOps == 1 || nOps == 5, charBuf, pDict);
 
1287
          firstOp = gFalse;
 
1288
        }
 
1289
        if (openPath) {
 
1290
          charBuf->append((char)9);
 
1291
          openPath = gFalse;
 
1292
        }
 
1293
        if (nOps == 4) {
 
1294
          cvtNum(0, gFalse, charBuf);
 
1295
          cvtNum(ops[0].num, ops[0].isFP, charBuf);
 
1296
          cvtNum(ops[1].num, ops[1].isFP, charBuf);
 
1297
          cvtNum(ops[2].num, ops[2].isFP, charBuf);
 
1298
          cvtNum(ops[3].num, ops[3].isFP, charBuf);
 
1299
          charBuf->append((char)12)->append((char)6);
 
1300
        } else if (nOps == 0) {
 
1301
          charBuf->append((char)14);
 
1302
        } else {
 
1303
          //~ error(-1, "Wrong number of args (%d) to Type 2 endchar", nOps);
 
1304
        }
 
1305
        nOps = 0;
 
1306
        break;
 
1307
      case 0x000f:              // (obsolete)
 
1308
        // this op is ignored, but we need the glyph width
 
1309
        if (firstOp) {
 
1310
          cvtGlyphWidth(nOps > 0, charBuf, pDict);
 
1311
          firstOp = gFalse;
 
1312
        }
 
1313
        nOps = 0;
 
1314
        break;
 
1315
      case 0x0010:              // blend
 
1316
        //~ error(-1, "Unimplemented Type 2 charstring op: %d", file[i]);
 
1317
        nOps = 0;
 
1318
        break;
 
1319
      case 0x0012:              // hstemhm
 
1320
        // ignored
 
1321
        if (firstOp) {
 
1322
          cvtGlyphWidth(nOps & 1, charBuf, pDict);
 
1323
          firstOp = gFalse;
 
1324
        }
 
1325
        if (nOps & 1) {
 
1326
          //~ error(-1, "Wrong number of args (%d) to Type 2 hstemhm", nOps);
 
1327
        }
 
1328
        nHints += nOps / 2;
 
1329
        nOps = 0;
 
1330
        break;
 
1331
      case 0x0013:              // hintmask
 
1332
        // ignored
 
1333
        if (firstOp) {
 
1334
          cvtGlyphWidth(nOps & 1, charBuf, pDict);
 
1335
          firstOp = gFalse;
 
1336
        }
 
1337
        if (nOps > 0) {
 
1338
          if (nOps & 1) {
 
1339
            //~ error(-1, "Wrong number of args (%d) to Type 2 hintmask/vstemhm",
 
1340
            //~       nOps);
 
1341
          }
 
1342
          nHints += nOps / 2;
 
1343
        }
 
1344
        pos += (nHints + 7) >> 3;
 
1345
        nOps = 0;
 
1346
        break;
 
1347
      case 0x0014:              // cntrmask
 
1348
        // ignored
 
1349
        if (firstOp) {
 
1350
          cvtGlyphWidth(nOps & 1, charBuf, pDict);
 
1351
          firstOp = gFalse;
 
1352
        }
 
1353
        if (nOps > 0) {
 
1354
          if (nOps & 1) {
 
1355
            //~ error(-1, "Wrong number of args (%d) to Type 2 cntrmask/vstemhm",
 
1356
            //~       nOps);
 
1357
          }
 
1358
          nHints += nOps / 2;
 
1359
        }
 
1360
        pos += (nHints + 7) >> 3;
 
1361
        nOps = 0;
 
1362
        break;
 
1363
      case 0x0015:              // rmoveto
 
1364
        if (firstOp) {
 
1365
          cvtGlyphWidth(nOps == 3, charBuf, pDict);
 
1366
          firstOp = gFalse;
 
1367
        }
 
1368
        if (openPath) {
 
1369
          charBuf->append((char)9);
 
1370
          openPath = gFalse;
 
1371
        }
 
1372
        if (nOps != 2) {
 
1373
          //~ error(-1, "Wrong number of args (%d) to Type 2 rmoveto", nOps);
 
1374
        }
 
1375
        cvtNum(ops[0].num, ops[0].isFP, charBuf);
 
1376
        cvtNum(ops[1].num, ops[1].isFP, charBuf);
 
1377
        charBuf->append((char)21);
 
1378
        nOps = 0;
 
1379
        break;
 
1380
      case 0x0016:              // hmoveto
 
1381
        if (firstOp) {
 
1382
          cvtGlyphWidth(nOps == 2, charBuf, pDict);
 
1383
          firstOp = gFalse;
 
1384
        }
 
1385
        if (openPath) {
 
1386
          charBuf->append((char)9);
 
1387
          openPath = gFalse;
 
1388
        }
 
1389
        if (nOps != 1) {
 
1390
          //~ error(-1, "Wrong number of args (%d) to Type 2 hmoveto", nOps);
 
1391
        }
 
1392
        cvtNum(ops[0].num, ops[0].isFP, charBuf);
 
1393
        charBuf->append((char)22);
 
1394
        nOps = 0;
 
1395
        break;
 
1396
      case 0x0017:              // vstemhm
 
1397
        // ignored
 
1398
        if (firstOp) {
 
1399
          cvtGlyphWidth(nOps & 1, charBuf, pDict);
 
1400
          firstOp = gFalse;
 
1401
        }
 
1402
        if (nOps & 1) {
 
1403
          //~ error(-1, "Wrong number of args (%d) to Type 2 vstemhm", nOps);
 
1404
        }
 
1405
        nHints += nOps / 2;
 
1406
        nOps = 0;
 
1407
        break;
 
1408
      case 0x0018:              // rcurveline
 
1409
        if (nOps < 8 || (nOps - 2) % 6 != 0) {
 
1410
          //~ error(-1, "Wrong number of args (%d) to Type 2 rcurveline", nOps);
 
1411
        }
 
1412
        for (k = 0; k < nOps - 2; k += 6) {
 
1413
          cvtNum(ops[k].num, ops[k].isFP, charBuf);
 
1414
          cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
 
1415
          cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
 
1416
          cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
 
1417
          cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
 
1418
          cvtNum(ops[k+5].num, ops[k+5].isFP, charBuf);
 
1419
          charBuf->append((char)8);
 
1420
        }
 
1421
        cvtNum(ops[k].num, ops[k].isFP, charBuf);
 
1422
        cvtNum(ops[k+1].num, ops[k].isFP, charBuf);
 
1423
        charBuf->append((char)5);
 
1424
        nOps = 0;
 
1425
        openPath = gTrue;
 
1426
        break;
 
1427
      case 0x0019:              // rlinecurve
 
1428
        if (nOps < 8 || (nOps - 6) % 2 != 0) {
 
1429
          //~ error(-1, "Wrong number of args (%d) to Type 2 rlinecurve", nOps);
 
1430
        }
 
1431
        for (k = 0; k < nOps - 6; k += 2) {
 
1432
          cvtNum(ops[k].num, ops[k].isFP, charBuf);
 
1433
          cvtNum(ops[k+1].num, ops[k].isFP, charBuf);
 
1434
          charBuf->append((char)5);
 
1435
        }
 
1436
        cvtNum(ops[k].num, ops[k].isFP, charBuf);
 
1437
        cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
 
1438
        cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
 
1439
        cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
 
1440
        cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
 
1441
        cvtNum(ops[k+5].num, ops[k+5].isFP, charBuf);
 
1442
        charBuf->append((char)8);
 
1443
        nOps = 0;
 
1444
        openPath = gTrue;
 
1445
        break;
 
1446
      case 0x001a:              // vvcurveto
 
1447
        if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
 
1448
          //~ error(-1, "Wrong number of args (%d) to Type 2 vvcurveto", nOps);
 
1449
        }
 
1450
        if (nOps % 2 == 1) {
 
1451
          cvtNum(ops[0].num, ops[0].isFP, charBuf);
 
1452
          cvtNum(ops[1].num, ops[1].isFP, charBuf);
 
1453
          cvtNum(ops[2].num, ops[2].isFP, charBuf);
 
1454
          cvtNum(ops[3].num, ops[3].isFP, charBuf);
 
1455
          cvtNum(0, gFalse, charBuf);
 
1456
          cvtNum(ops[4].num, ops[4].isFP, charBuf);
 
1457
          charBuf->append((char)8);
 
1458
          k = 5;
 
1459
        } else {
 
1460
          k = 0;
 
1461
        }
 
1462
        for (; k < nOps; k += 4) {
 
1463
          cvtNum(0, gFalse, charBuf);
 
1464
          cvtNum(ops[k].num, ops[k].isFP, charBuf);
 
1465
          cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
 
1466
          cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
 
1467
          cvtNum(0, gFalse, charBuf);
 
1468
          cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
 
1469
          charBuf->append((char)8);
 
1470
        }
 
1471
        nOps = 0;
 
1472
        openPath = gTrue;
 
1473
        break;
 
1474
      case 0x001b:              // hhcurveto
 
1475
        if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
 
1476
          //~ error(-1, "Wrong number of args (%d) to Type 2 hhcurveto", nOps);
 
1477
        }
 
1478
        if (nOps % 2 == 1) {
 
1479
          cvtNum(ops[1].num, ops[1].isFP, charBuf);
 
1480
          cvtNum(ops[0].num, ops[0].isFP, charBuf);
 
1481
          cvtNum(ops[2].num, ops[2].isFP, charBuf);
 
1482
          cvtNum(ops[3].num, ops[3].isFP, charBuf);
 
1483
          cvtNum(ops[4].num, ops[4].isFP, charBuf);
 
1484
          cvtNum(0, gFalse, charBuf);
 
1485
          charBuf->append((char)8);
 
1486
          k = 5;
 
1487
        } else {
 
1488
          k = 0;
 
1489
        }
 
1490
        for (; k < nOps; k += 4) {
 
1491
          cvtNum(ops[k].num, ops[k].isFP, charBuf);
 
1492
          cvtNum(0, gFalse, charBuf);
 
1493
          cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
 
1494
          cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
 
1495
          cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
 
1496
          cvtNum(0, gFalse, charBuf);
 
1497
          charBuf->append((char)8);
 
1498
        }
 
1499
        nOps = 0;
 
1500
        openPath = gTrue;
 
1501
        break;
 
1502
      case 0x001d:              // callgsubr
 
1503
        if (nOps >= 1) {
 
1504
          k = gsubrBias + (int)ops[nOps - 1].num;
 
1505
          --nOps;
 
1506
          ok = gTrue;
 
1507
          getIndexVal(&gsubrIdx, k, &val, &ok);
 
1508
          if (ok) {
 
1509
            cvtGlyph(val.pos, val.len, charBuf, subrIdx, pDict, gFalse);
 
1510
          }
 
1511
        } else {
 
1512
          //~ error(-1, "Too few args to Type 2 callgsubr");
 
1513
        }
 
1514
        // don't clear the stack
 
1515
        break;
 
1516
      case 0x001e:              // vhcurveto
 
1517
        if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
 
1518
          //~ error(-1, "Wrong number of args (%d) to Type 2 vhcurveto", nOps);
 
1519
        }
 
1520
        for (k = 0; k < nOps && k != nOps-5; k += 4) {
 
1521
          if (k % 8 == 0) {
 
1522
            cvtNum(ops[k].num, ops[k].isFP, charBuf);
 
1523
            cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
 
1524
            cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
 
1525
            cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
 
1526
            charBuf->append((char)30);
 
1527
          } else {
 
1528
            cvtNum(ops[k].num, ops[k].isFP, charBuf);
 
1529
            cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
 
1530
            cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
 
1531
            cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
 
1532
            charBuf->append((char)31);
 
1533
          }
 
1534
        }
 
1535
        if (k == nOps-5) {
 
1536
          if (k % 8 == 0) {
 
1537
            cvtNum(0, gFalse, charBuf);
 
1538
            cvtNum(ops[k].num, ops[k].isFP, charBuf);
 
1539
            cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
 
1540
            cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
 
1541
            cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
 
1542
            cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
 
1543
          } else {
 
1544
            cvtNum(ops[k].num, ops[k].isFP, charBuf);
 
1545
            cvtNum(0, gFalse, charBuf);
 
1546
            cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
 
1547
            cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
 
1548
            cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
 
1549
            cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
 
1550
          }
 
1551
          charBuf->append((char)8);
 
1552
        }
 
1553
        nOps = 0;
 
1554
        openPath = gTrue;
 
1555
        break;
 
1556
      case 0x001f:              // hvcurveto
 
1557
        if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
 
1558
          //~ error(-1, "Wrong number of args (%d) to Type 2 hvcurveto", nOps);
 
1559
        }
 
1560
        for (k = 0; k < nOps && k != nOps-5; k += 4) {
 
1561
          if (k % 8 == 0) {
 
1562
            cvtNum(ops[k].num, ops[k].isFP, charBuf);
 
1563
            cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
 
1564
            cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
 
1565
            cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
 
1566
            charBuf->append((char)31);
 
1567
          } else {
 
1568
            cvtNum(ops[k].num, ops[k].isFP, charBuf);
 
1569
            cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
 
1570
            cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
 
1571
            cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
 
1572
            charBuf->append((char)30);
 
1573
          }
 
1574
        }
 
1575
        if (k == nOps-5) {
 
1576
          if (k % 8 == 0) {
 
1577
            cvtNum(ops[k].num, ops[k].isFP, charBuf);
 
1578
            cvtNum(0, gFalse, charBuf);
 
1579
            cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
 
1580
            cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
 
1581
            cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
 
1582
            cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
 
1583
          } else {
 
1584
            cvtNum(0, gFalse, charBuf);
 
1585
            cvtNum(ops[k].num, ops[k].isFP, charBuf);
 
1586
            cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
 
1587
            cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
 
1588
            cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
 
1589
            cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
 
1590
          }
 
1591
          charBuf->append((char)8);
 
1592
        }
 
1593
        nOps = 0;
 
1594
        openPath = gTrue;
 
1595
        break;
 
1596
      case 0x0c00:              // dotsection (should be Type 1 only?)
 
1597
        // ignored
 
1598
        nOps = 0;
 
1599
        break;
 
1600
      case 0x0c03:              // and
 
1601
      case 0x0c04:              // or
 
1602
      case 0x0c05:              // not
 
1603
      case 0x0c08:              // store
 
1604
      case 0x0c09:              // abs
 
1605
      case 0x0c0a:              // add
 
1606
      case 0x0c0b:              // sub
 
1607
      case 0x0c0c:              // div
 
1608
      case 0x0c0d:              // load
 
1609
      case 0x0c0e:              // neg
 
1610
      case 0x0c0f:              // eq
 
1611
      case 0x0c12:              // drop
 
1612
      case 0x0c14:              // put
 
1613
      case 0x0c15:              // get
 
1614
      case 0x0c16:              // ifelse
 
1615
      case 0x0c17:              // random
 
1616
      case 0x0c18:              // mul
 
1617
      case 0x0c1a:              // sqrt
 
1618
      case 0x0c1b:              // dup
 
1619
      case 0x0c1c:              // exch
 
1620
      case 0x0c1d:              // index
 
1621
      case 0x0c1e:              // roll
 
1622
        //~ error(-1, "Unimplemented Type 2 charstring op: 12.%d", file[i+1]);
 
1623
        nOps = 0;
 
1624
        break;
 
1625
      case 0x0c22:              // hflex
 
1626
        if (nOps != 7) {
 
1627
          //~ error(-1, "Wrong number of args (%d) to Type 2 hflex", nOps);
 
1628
        }
 
1629
        cvtNum(ops[0].num, ops[0].isFP, charBuf);
 
1630
        cvtNum(0, gFalse, charBuf);
 
1631
        cvtNum(ops[1].num, ops[1].isFP, charBuf);
 
1632
        cvtNum(ops[2].num, ops[2].isFP, charBuf);
 
1633
        cvtNum(ops[3].num, ops[3].isFP, charBuf);
 
1634
        cvtNum(0, gFalse, charBuf);
 
1635
        charBuf->append((char)8);
 
1636
        cvtNum(ops[4].num, ops[4].isFP, charBuf);
 
1637
        cvtNum(0, gFalse, charBuf);
 
1638
        cvtNum(ops[5].num, ops[5].isFP, charBuf);
 
1639
        cvtNum(-ops[2].num, ops[2].isFP, charBuf);
 
1640
        cvtNum(ops[6].num, ops[6].isFP, charBuf);
 
1641
        cvtNum(0, gFalse, charBuf);
 
1642
        charBuf->append((char)8);
 
1643
        nOps = 0;
 
1644
        openPath = gTrue;
 
1645
        break;
 
1646
      case 0x0c23:              // flex
 
1647
        if (nOps != 13) {
 
1648
          //~ error(-1, "Wrong number of args (%d) to Type 2 flex", nOps);
 
1649
        }
 
1650
        cvtNum(ops[0].num, ops[0].isFP, charBuf);
 
1651
        cvtNum(ops[1].num, ops[1].isFP, charBuf);
 
1652
        cvtNum(ops[2].num, ops[2].isFP, charBuf);
 
1653
        cvtNum(ops[3].num, ops[3].isFP, charBuf);
 
1654
        cvtNum(ops[4].num, ops[4].isFP, charBuf);
 
1655
        cvtNum(ops[5].num, ops[5].isFP, charBuf);
 
1656
        charBuf->append((char)8);
 
1657
        cvtNum(ops[6].num, ops[6].isFP, charBuf);
 
1658
        cvtNum(ops[7].num, ops[7].isFP, charBuf);
 
1659
        cvtNum(ops[8].num, ops[8].isFP, charBuf);
 
1660
        cvtNum(ops[9].num, ops[9].isFP, charBuf);
 
1661
        cvtNum(ops[10].num, ops[10].isFP, charBuf);
 
1662
        cvtNum(ops[11].num, ops[11].isFP, charBuf);
 
1663
        charBuf->append((char)8);
 
1664
        nOps = 0;
 
1665
        openPath = gTrue;
 
1666
        break;
 
1667
      case 0x0c24:              // hflex1
 
1668
        if (nOps != 9) {
 
1669
          //~ error(-1, "Wrong number of args (%d) to Type 2 hflex1", nOps);
 
1670
        }
 
1671
        cvtNum(ops[0].num, ops[0].isFP, charBuf);
 
1672
        cvtNum(ops[1].num, ops[1].isFP, charBuf);
 
1673
        cvtNum(ops[2].num, ops[2].isFP, charBuf);
 
1674
        cvtNum(ops[3].num, ops[3].isFP, charBuf);
 
1675
        cvtNum(ops[4].num, ops[4].isFP, charBuf);
 
1676
        cvtNum(0, gFalse, charBuf);
 
1677
        charBuf->append((char)8);
 
1678
        cvtNum(ops[5].num, ops[5].isFP, charBuf);
 
1679
        cvtNum(0, gFalse, charBuf);
 
1680
        cvtNum(ops[6].num, ops[6].isFP, charBuf);
 
1681
        cvtNum(ops[7].num, ops[7].isFP, charBuf);
 
1682
        cvtNum(ops[8].num, ops[8].isFP, charBuf);
 
1683
        cvtNum(-(ops[1].num + ops[3].num + ops[7].num),
 
1684
               ops[1].isFP | ops[3].isFP | ops[7].isFP, charBuf);
 
1685
        charBuf->append((char)8);
 
1686
        nOps = 0;
 
1687
        openPath = gTrue;
 
1688
        break;
 
1689
      case 0x0c25:              // flex1
 
1690
        if (nOps != 11) {
 
1691
          //~ error(-1, "Wrong number of args (%d) to Type 2 flex1", nOps);
 
1692
        }
 
1693
        cvtNum(ops[0].num, ops[0].isFP, charBuf);
 
1694
        cvtNum(ops[1].num, ops[1].isFP, charBuf);
 
1695
        cvtNum(ops[2].num, ops[2].isFP, charBuf);
 
1696
        cvtNum(ops[3].num, ops[3].isFP, charBuf);
 
1697
        cvtNum(ops[4].num, ops[4].isFP, charBuf);
 
1698
        cvtNum(ops[5].num, ops[5].isFP, charBuf);
 
1699
        charBuf->append((char)8);
 
1700
        cvtNum(ops[6].num, ops[6].isFP, charBuf);
 
1701
        cvtNum(ops[7].num, ops[7].isFP, charBuf);
 
1702
        cvtNum(ops[8].num, ops[8].isFP, charBuf);
 
1703
        cvtNum(ops[9].num, ops[9].isFP, charBuf);
 
1704
        dx = ops[0].num + ops[2].num + ops[4].num + ops[6].num + ops[8].num;
 
1705
        dy = ops[1].num + ops[3].num + ops[5].num + ops[7].num + ops[9].num;
 
1706
        if (fabs(dx) > fabs(dy)) {
 
1707
          cvtNum(ops[10].num, ops[10].isFP, charBuf);
 
1708
          cvtNum(-dy, ops[1].isFP | ops[3].isFP | ops[5].isFP |
 
1709
                      ops[7].isFP | ops[9].isFP, charBuf);
 
1710
        } else {
 
1711
          cvtNum(-dx, ops[0].isFP | ops[2].isFP | ops[4].isFP |
 
1712
                      ops[6].isFP | ops[8].isFP, charBuf);
 
1713
          cvtNum(ops[10].num, ops[10].isFP, charBuf);
 
1714
        }
 
1715
        charBuf->append((char)8);
 
1716
        nOps = 0;
 
1717
        openPath = gTrue;
 
1718
        break;
 
1719
      default:
 
1720
        //~ error(-1, "Illegal Type 2 charstring op: %04x",
 
1721
        //~       ops[nOps].op);
 
1722
        nOps = 0;
 
1723
        break;
 
1724
      }
 
1725
    }
 
1726
  }
 
1727
 
 
1728
  // charstring encryption
 
1729
  if (top) {
 
1730
    r2 = 4330;
 
1731
    for (i = start; i < charBuf->getLength(); ++i) {
 
1732
      byte = charBuf->getChar(i) ^ (r2 >> 8);
 
1733
      charBuf->setChar(i, byte);
 
1734
      r2 = (byte + r2) * 52845 + 22719;
 
1735
    }
 
1736
  }
 
1737
}
 
1738
 
 
1739
void FoFiType1C::cvtGlyphWidth(GBool useOp, GooString *charBuf,
 
1740
                               Type1CPrivateDict *pDict) {
 
1741
  double w;
 
1742
  GBool wFP;
 
1743
  int i;
 
1744
 
 
1745
  if (useOp) {
 
1746
    w = pDict->nominalWidthX + ops[0].num;
 
1747
    wFP = pDict->nominalWidthXFP | ops[0].isFP;
 
1748
    for (i = 1; i < nOps; ++i) {
 
1749
      ops[i-1] = ops[i];
 
1750
    }
 
1751
    --nOps;
 
1752
  } else {
 
1753
    w = pDict->defaultWidthX;
 
1754
    wFP = pDict->defaultWidthXFP;
 
1755
  }
 
1756
  cvtNum(0, gFalse, charBuf);
 
1757
  cvtNum(w, wFP, charBuf);
 
1758
  charBuf->append((char)13);
 
1759
}
 
1760
 
 
1761
void FoFiType1C::cvtNum(double x, GBool isFP, GooString *charBuf) {
 
1762
  Guchar buf[12];
 
1763
  int y, n;
 
1764
 
 
1765
  n = 0;
 
1766
  if (isFP) {
 
1767
    if (x >= -32768 && x < 32768) {
 
1768
      y = (int)(x * 256.0);
 
1769
      buf[0] = 255;
 
1770
      buf[1] = (Guchar)(y >> 24);
 
1771
      buf[2] = (Guchar)(y >> 16);
 
1772
      buf[3] = (Guchar)(y >> 8);
 
1773
      buf[4] = (Guchar)y;
 
1774
      buf[5] = 255;
 
1775
      buf[6] = 0;
 
1776
      buf[7] = 0;
 
1777
      buf[8] = 1;
 
1778
      buf[9] = 0;
 
1779
      buf[10] = 12;
 
1780
      buf[11] = 12;
 
1781
      n = 12;
 
1782
    } else {
 
1783
      //~ error(-1, "Type 2 fixed point constant out of range");
 
1784
    }
 
1785
  } else {
 
1786
    y = (int)x;
 
1787
    if (y >= -107 && y <= 107) {
 
1788
      buf[0] = (Guchar)(y + 139);
 
1789
      n = 1;
 
1790
    } else if (y > 107 && y <= 1131) {
 
1791
      y -= 108;
 
1792
      buf[0] = (Guchar)((y >> 8) + 247);
 
1793
      buf[1] = (Guchar)(y & 0xff);
 
1794
      n = 2;
 
1795
    } else if (y < -107 && y >= -1131) {
 
1796
      y = -y - 108;
 
1797
      buf[0] = (Guchar)((y >> 8) + 251);
 
1798
      buf[1] = (Guchar)(y & 0xff);
 
1799
      n = 2;
 
1800
    } else {
 
1801
      buf[0] = 255;
 
1802
      buf[1] = (Guchar)(y >> 24);
 
1803
      buf[2] = (Guchar)(y >> 16);
 
1804
      buf[3] = (Guchar)(y >> 8);
 
1805
      buf[4] = (Guchar)y;
 
1806
      n = 5;
 
1807
    }
 
1808
  }
 
1809
  charBuf->append((char *)buf, n);
 
1810
}
 
1811
 
 
1812
void FoFiType1C::eexecWrite(Type1CEexecBuf *eb, char *s) {
 
1813
  Guchar *p;
 
1814
  Guchar x;
 
1815
 
 
1816
  for (p = (Guchar *)s; *p; ++p) {
 
1817
    x = *p ^ (eb->r1 >> 8);
 
1818
    eb->r1 = (x + eb->r1) * 52845 + 22719;
 
1819
    if (eb->ascii) {
 
1820
      (*eb->outputFunc)(eb->outputStream, &hexChars[x >> 4], 1);
 
1821
      (*eb->outputFunc)(eb->outputStream, &hexChars[x & 0x0f], 1);
 
1822
      eb->line += 2;
 
1823
      if (eb->line == 64) {
 
1824
        (*eb->outputFunc)(eb->outputStream, "\n", 1);
 
1825
        eb->line = 0;
 
1826
      }
 
1827
    } else {
 
1828
      (*eb->outputFunc)(eb->outputStream, (char *)&x, 1);
 
1829
    }
 
1830
  }
 
1831
}
 
1832
 
 
1833
void FoFiType1C::eexecWriteCharstring(Type1CEexecBuf *eb,
 
1834
                                      Guchar *s, int n) {
 
1835
  Guchar x;
 
1836
  int i;
 
1837
 
 
1838
  // eexec encryption
 
1839
  for (i = 0; i < n; ++i) {
 
1840
    x = s[i] ^ (eb->r1 >> 8);
 
1841
    eb->r1 = (x + eb->r1) * 52845 + 22719;
 
1842
    if (eb->ascii) {
 
1843
      (*eb->outputFunc)(eb->outputStream, &hexChars[x >> 4], 1);
 
1844
      (*eb->outputFunc)(eb->outputStream, &hexChars[x & 0x0f], 1);
 
1845
      eb->line += 2;
 
1846
      if (eb->line == 64) {
 
1847
        (*eb->outputFunc)(eb->outputStream, "\n", 1);
 
1848
        eb->line = 0;
 
1849
      }
 
1850
    } else {
 
1851
      (*eb->outputFunc)(eb->outputStream, (char *)&x, 1);
 
1852
    }
 
1853
  }
 
1854
}
 
1855
 
 
1856
GBool FoFiType1C::parse() {
 
1857
  Type1CIndex fdIdx;
 
1858
  Type1CIndexVal val;
 
1859
  int i;
 
1860
 
 
1861
  parsedOk = gTrue;
 
1862
 
 
1863
  // some tools embed Type 1C fonts with an extra whitespace char at
 
1864
  // the beginning
 
1865
  if (len > 0 && file[0] != '\x01') {
 
1866
    ++file;
 
1867
    --len;
 
1868
  }
 
1869
 
 
1870
  // find the indexes
 
1871
  getIndex(getU8(2, &parsedOk), &nameIdx, &parsedOk);
 
1872
  getIndex(nameIdx.endPos, &topDictIdx, &parsedOk);
 
1873
  getIndex(topDictIdx.endPos, &stringIdx, &parsedOk);
 
1874
  getIndex(stringIdx.endPos, &gsubrIdx, &parsedOk);
 
1875
  if (!parsedOk) {
 
1876
    return gFalse;
 
1877
  }
 
1878
  gsubrBias = (gsubrIdx.len < 1240) ? 107
 
1879
                                    : (gsubrIdx.len < 33900) ? 1131 : 32768;
 
1880
 
 
1881
  // read the first font name
 
1882
  getIndexVal(&nameIdx, 0, &val, &parsedOk);
 
1883
  if (!parsedOk) {
 
1884
    return gFalse;
 
1885
  }
 
1886
  name = new GooString((char *)&file[val.pos], val.len);
 
1887
 
 
1888
  // read the top dict for the first font
 
1889
  readTopDict();
 
1890
 
 
1891
  // for CID fonts: read the FDArray dicts and private dicts
 
1892
  if (topDict.firstOp == 0x0c1e) {
 
1893
    if (topDict.fdArrayOffset == 0) {
 
1894
      nFDs = 1;
 
1895
      privateDicts = (Type1CPrivateDict *)gmalloc(sizeof(Type1CPrivateDict));
 
1896
      readPrivateDict(0, 0, &privateDicts[0]);
 
1897
    } else {
 
1898
      getIndex(topDict.fdArrayOffset, &fdIdx, &parsedOk);
 
1899
      if (!parsedOk) {
 
1900
        return gFalse;
 
1901
      }
 
1902
      nFDs = fdIdx.len;
 
1903
      privateDicts = (Type1CPrivateDict *)
 
1904
                         gmallocn(nFDs, sizeof(Type1CPrivateDict));
 
1905
      for (i = 0; i < nFDs; ++i) {
 
1906
        getIndexVal(&fdIdx, i, &val, &parsedOk);
 
1907
        if (!parsedOk) {
 
1908
          return gFalse;
 
1909
        }
 
1910
        readFD(val.pos, val.len, &privateDicts[i]);
 
1911
      }
 
1912
    }
 
1913
 
 
1914
  // for 8-bit fonts: read the private dict
 
1915
  } else {
 
1916
    privateDicts = (Type1CPrivateDict *)gmalloc(sizeof(Type1CPrivateDict));
 
1917
    readPrivateDict(topDict.privateOffset, topDict.privateSize,
 
1918
                    &privateDicts[0]);
 
1919
  }
 
1920
 
 
1921
  // check for parse errors in the private dict(s)
 
1922
  if (!parsedOk) {
 
1923
    return gFalse;
 
1924
  }
 
1925
 
 
1926
  // get the charstrings index
 
1927
  if (topDict.charStringsOffset <= 0) {
 
1928
    parsedOk = gFalse;
 
1929
    return gFalse;
 
1930
  }
 
1931
  getIndex(topDict.charStringsOffset, &charStringsIdx, &parsedOk);
 
1932
  if (!parsedOk) {
 
1933
    return gFalse;
 
1934
  }
 
1935
  nGlyphs = charStringsIdx.len;
 
1936
 
 
1937
  // for CID fonts: read the FDSelect table
 
1938
  if (topDict.firstOp == 0x0c1e) {
 
1939
    readFDSelect();
 
1940
    if (!parsedOk) {
 
1941
      return gFalse;
 
1942
    }
 
1943
  }
 
1944
 
 
1945
  // read the charset
 
1946
  if (!readCharset()) {
 
1947
    parsedOk = gFalse;
 
1948
    return gFalse;
 
1949
  }
 
1950
 
 
1951
  // for 8-bit fonts: build the encoding
 
1952
  if (topDict.firstOp != 0x0c14 && topDict.firstOp != 0x0c1e) {
 
1953
    buildEncoding();
 
1954
    if (!parsedOk) {
 
1955
      return gFalse;
 
1956
    }
 
1957
  }
 
1958
 
 
1959
  return parsedOk;
 
1960
}
 
1961
 
 
1962
void FoFiType1C::readTopDict() {
 
1963
  Type1CIndexVal topDictPtr;
 
1964
  int pos;
 
1965
 
 
1966
  topDict.firstOp = -1;
 
1967
  topDict.versionSID = 0;
 
1968
  topDict.noticeSID = 0;
 
1969
  topDict.copyrightSID = 0;
 
1970
  topDict.fullNameSID = 0;
 
1971
  topDict.familyNameSID = 0;
 
1972
  topDict.weightSID = 0;
 
1973
  topDict.isFixedPitch = 0;
 
1974
  topDict.italicAngle = 0;
 
1975
  topDict.underlinePosition = -100;
 
1976
  topDict.underlineThickness = 50;
 
1977
  topDict.paintType = 0;
 
1978
  topDict.charstringType = 2;
 
1979
  topDict.fontMatrix[0] = 0.001;
 
1980
  topDict.fontMatrix[1] = 0;
 
1981
  topDict.fontMatrix[2] = 0;
 
1982
  topDict.fontMatrix[3] = 0.001;
 
1983
  topDict.fontMatrix[4] = 0;
 
1984
  topDict.fontMatrix[5] = 0;
 
1985
  topDict.hasFontMatrix = gFalse;
 
1986
  topDict.uniqueID = 0;
 
1987
  topDict.fontBBox[0] = 0;
 
1988
  topDict.fontBBox[1] = 0;
 
1989
  topDict.fontBBox[2] = 0;
 
1990
  topDict.fontBBox[3] = 0;
 
1991
  topDict.strokeWidth = 0;
 
1992
  topDict.charsetOffset = 0;
 
1993
  topDict.encodingOffset = 0;
 
1994
  topDict.charStringsOffset = 0;
 
1995
  topDict.privateSize = 0;
 
1996
  topDict.privateOffset = 0;
 
1997
  topDict.registrySID = 0;
 
1998
  topDict.orderingSID = 0;
 
1999
  topDict.supplement = 0;
 
2000
  topDict.fdArrayOffset = 0;
 
2001
  topDict.fdSelectOffset = 0;
 
2002
 
 
2003
  getIndexVal(&topDictIdx, 0, &topDictPtr, &parsedOk);
 
2004
  pos = topDictPtr.pos;
 
2005
  nOps = 0;
 
2006
  while (pos < topDictPtr.pos + topDictPtr.len) {
 
2007
    pos = getOp(pos, gFalse, &parsedOk);
 
2008
    if (!parsedOk) {
 
2009
      break;
 
2010
    }
 
2011
    if (!ops[nOps - 1].isNum) {
 
2012
      --nOps; // drop the operator
 
2013
      if (topDict.firstOp < 0) {
 
2014
        topDict.firstOp = ops[nOps].op;
 
2015
      }
 
2016
      switch (ops[nOps].op) {
 
2017
      case 0x0000: topDict.versionSID = (int)ops[0].num; break;
 
2018
      case 0x0001: topDict.noticeSID = (int)ops[0].num; break;
 
2019
      case 0x0c00: topDict.copyrightSID = (int)ops[0].num; break;
 
2020
      case 0x0002: topDict.fullNameSID = (int)ops[0].num; break;
 
2021
      case 0x0003: topDict.familyNameSID = (int)ops[0].num; break;
 
2022
      case 0x0004: topDict.weightSID = (int)ops[0].num; break;
 
2023
      case 0x0c01: topDict.isFixedPitch = (int)ops[0].num; break;
 
2024
      case 0x0c02: topDict.italicAngle = ops[0].num; break;
 
2025
      case 0x0c03: topDict.underlinePosition = ops[0].num; break;
 
2026
      case 0x0c04: topDict.underlineThickness = ops[0].num; break;
 
2027
      case 0x0c05: topDict.paintType = (int)ops[0].num; break;
 
2028
      case 0x0c06: topDict.charstringType = (int)ops[0].num; break;
 
2029
      case 0x0c07: topDict.fontMatrix[0] = ops[0].num;
 
2030
                   topDict.fontMatrix[1] = ops[1].num;
 
2031
                   topDict.fontMatrix[2] = ops[2].num;
 
2032
                   topDict.fontMatrix[3] = ops[3].num;
 
2033
                   topDict.fontMatrix[4] = ops[4].num;
 
2034
                   topDict.fontMatrix[5] = ops[5].num;
 
2035
                   topDict.hasFontMatrix = gTrue; break;
 
2036
      case 0x000d: topDict.uniqueID = (int)ops[0].num; break;
 
2037
      case 0x0005: topDict.fontBBox[0] = ops[0].num;
 
2038
                   topDict.fontBBox[1] = ops[1].num;
 
2039
                   topDict.fontBBox[2] = ops[2].num;
 
2040
                   topDict.fontBBox[3] = ops[3].num; break;
 
2041
      case 0x0c08: topDict.strokeWidth = ops[0].num; break;
 
2042
      case 0x000f: topDict.charsetOffset = (int)ops[0].num; break;
 
2043
      case 0x0010: topDict.encodingOffset = (int)ops[0].num; break;
 
2044
      case 0x0011: topDict.charStringsOffset = (int)ops[0].num; break;
 
2045
      case 0x0012: topDict.privateSize = (int)ops[0].num;
 
2046
                   topDict.privateOffset = (int)ops[1].num; break;
 
2047
      case 0x0c1e: topDict.registrySID = (int)ops[0].num;
 
2048
                   topDict.orderingSID = (int)ops[1].num;
 
2049
                   topDict.supplement = (int)ops[2].num; break;
 
2050
      case 0x0c24: topDict.fdArrayOffset = (int)ops[0].num; break;
 
2051
      case 0x0c25: topDict.fdSelectOffset = (int)ops[0].num; break;
 
2052
      }
 
2053
      nOps = 0;
 
2054
    }
 
2055
  }
 
2056
}
 
2057
 
 
2058
// Read a CID font dict (FD) - this pulls out the private dict
 
2059
// pointer, and reads the private dict.  It also pulls the FontMatrix
 
2060
// (if any) out of the FD.
 
2061
void FoFiType1C::readFD(int offset, int length, Type1CPrivateDict *pDict) {
 
2062
  int pos, pSize, pOffset;
 
2063
  double fontMatrix[6] = {0};
 
2064
  GBool hasFontMatrix;
 
2065
 
 
2066
  hasFontMatrix = gFalse;
 
2067
  pSize = pOffset = 0;
 
2068
  pos = offset;
 
2069
  nOps = 0;
 
2070
  while (pos < offset + length) {
 
2071
    pos = getOp(pos, gFalse, &parsedOk);
 
2072
    if (!parsedOk) {
 
2073
      return;
 
2074
    }
 
2075
    if (!ops[nOps - 1].isNum) {
 
2076
      if (ops[nOps - 1].op == 0x0012) {
 
2077
        if (nOps < 3) {
 
2078
          parsedOk = gFalse;
 
2079
          return;
 
2080
        }
 
2081
        pSize = (int)ops[0].num;
 
2082
        pOffset = (int)ops[1].num;
 
2083
        break;
 
2084
      } else if (ops[nOps - 1].op == 0x0c07) {
 
2085
        fontMatrix[0] = ops[0].num;
 
2086
        fontMatrix[1] = ops[1].num;
 
2087
        fontMatrix[2] = ops[2].num;
 
2088
        fontMatrix[3] = ops[3].num;
 
2089
        fontMatrix[4] = ops[4].num;
 
2090
        fontMatrix[5] = ops[5].num;
 
2091
        hasFontMatrix = gTrue;
 
2092
      }
 
2093
      nOps = 0;
 
2094
    }
 
2095
  }
 
2096
  readPrivateDict(pOffset, pSize, pDict);
 
2097
  if (hasFontMatrix) {
 
2098
    pDict->fontMatrix[0] = fontMatrix[0];
 
2099
    pDict->fontMatrix[1] = fontMatrix[1];
 
2100
    pDict->fontMatrix[2] = fontMatrix[2];
 
2101
    pDict->fontMatrix[3] = fontMatrix[3];
 
2102
    pDict->fontMatrix[4] = fontMatrix[4];
 
2103
    pDict->fontMatrix[5] = fontMatrix[5];
 
2104
    pDict->hasFontMatrix = gTrue;
 
2105
  }
 
2106
}
 
2107
 
 
2108
void FoFiType1C::readPrivateDict(int offset, int length,
 
2109
                                 Type1CPrivateDict *pDict) {
 
2110
  int pos;
 
2111
 
 
2112
  pDict->hasFontMatrix = gFalse;
 
2113
  pDict->nBlueValues = 0;
 
2114
  pDict->nOtherBlues = 0;
 
2115
  pDict->nFamilyBlues = 0;
 
2116
  pDict->nFamilyOtherBlues = 0;
 
2117
  pDict->blueScale = 0.039625;
 
2118
  pDict->blueShift = 7;
 
2119
  pDict->blueFuzz = 1;
 
2120
  pDict->hasStdHW = gFalse;
 
2121
  pDict->hasStdVW = gFalse;
 
2122
  pDict->nStemSnapH = 0;
 
2123
  pDict->nStemSnapV = 0;
 
2124
  pDict->hasForceBold = gFalse;
 
2125
  pDict->forceBoldThreshold = 0;
 
2126
  pDict->languageGroup = 0;
 
2127
  pDict->expansionFactor = 0.06;
 
2128
  pDict->initialRandomSeed = 0;
 
2129
  pDict->subrsOffset = 0;
 
2130
  pDict->defaultWidthX = 0;
 
2131
  pDict->defaultWidthXFP = gFalse;
 
2132
  pDict->nominalWidthX = 0;
 
2133
  pDict->nominalWidthXFP = gFalse;
 
2134
 
 
2135
  // no dictionary
 
2136
  if (offset == 0 || length == 0) {
 
2137
    return;
 
2138
  }
 
2139
 
 
2140
  pos = offset;
 
2141
  nOps = 0;
 
2142
  while (pos < offset + length) {
 
2143
    pos = getOp(pos, gFalse, &parsedOk);
 
2144
    if (!parsedOk) {
 
2145
      break;
 
2146
    }
 
2147
    if (!ops[nOps - 1].isNum) {
 
2148
      --nOps; // drop the operator
 
2149
      switch (ops[nOps].op) {
 
2150
      case 0x0006:
 
2151
        pDict->nBlueValues = getDeltaIntArray(pDict->blueValues,
 
2152
                                              type1CMaxBlueValues);
 
2153
        break;
 
2154
      case 0x0007:
 
2155
        pDict->nOtherBlues = getDeltaIntArray(pDict->otherBlues,
 
2156
                                              type1CMaxOtherBlues);
 
2157
        break;
 
2158
      case 0x0008:
 
2159
        pDict->nFamilyBlues = getDeltaIntArray(pDict->familyBlues,
 
2160
                                               type1CMaxBlueValues);
 
2161
        break;
 
2162
      case 0x0009:
 
2163
        pDict->nFamilyOtherBlues = getDeltaIntArray(pDict->familyOtherBlues,
 
2164
                                                    type1CMaxOtherBlues);
 
2165
        break;
 
2166
      case 0x0c09:
 
2167
        pDict->blueScale = ops[0].num;
 
2168
        break;
 
2169
      case 0x0c0a:
 
2170
        pDict->blueShift = (int)ops[0].num;
 
2171
        break;
 
2172
      case 0x0c0b:
 
2173
        pDict->blueFuzz = (int)ops[0].num;
 
2174
        break;
 
2175
      case 0x000a:
 
2176
        pDict->stdHW = ops[0].num;
 
2177
        pDict->hasStdHW = gTrue;
 
2178
        break;
 
2179
      case 0x000b:
 
2180
        pDict->stdVW = ops[0].num;
 
2181
        pDict->hasStdVW = gTrue;
 
2182
        break;
 
2183
      case 0x0c0c:
 
2184
        pDict->nStemSnapH = getDeltaFPArray(pDict->stemSnapH,
 
2185
                                            type1CMaxStemSnap);
 
2186
        break;
 
2187
      case 0x0c0d:
 
2188
        pDict->nStemSnapV = getDeltaFPArray(pDict->stemSnapV,
 
2189
                                            type1CMaxStemSnap);
 
2190
        break;
 
2191
      case 0x0c0e:
 
2192
        pDict->forceBold = ops[0].num != 0;
 
2193
        pDict->hasForceBold = gTrue;
 
2194
        break;
 
2195
      case 0x0c0f:
 
2196
        pDict->forceBoldThreshold = ops[0].num;
 
2197
        break;
 
2198
      case 0x0c11:
 
2199
        pDict->languageGroup = (int)ops[0].num;
 
2200
        break;
 
2201
      case 0x0c12:
 
2202
        pDict->expansionFactor = ops[0].num;
 
2203
        break;
 
2204
      case 0x0c13:
 
2205
        pDict->initialRandomSeed = (int)ops[0].num;
 
2206
        break;
 
2207
      case 0x0013:
 
2208
        pDict->subrsOffset = offset + (int)ops[0].num;
 
2209
        break;
 
2210
      case 0x0014:
 
2211
        pDict->defaultWidthX = ops[0].num;
 
2212
        pDict->defaultWidthXFP = ops[0].isFP;
 
2213
        break;
 
2214
      case 0x0015:
 
2215
        pDict->nominalWidthX = ops[0].num;
 
2216
        pDict->nominalWidthXFP = ops[0].isFP;
 
2217
        break;
 
2218
      }
 
2219
      nOps = 0;
 
2220
    }
 
2221
  }
 
2222
}
 
2223
 
 
2224
void FoFiType1C::readFDSelect() {
 
2225
  int fdSelectFmt, pos, nRanges, gid0, gid1, fd, i, j;
 
2226
 
 
2227
  fdSelect = (Guchar *)gmalloc(nGlyphs);
 
2228
  if (topDict.fdSelectOffset == 0) {
 
2229
    for (i = 0; i < nGlyphs; ++i) {
 
2230
      fdSelect[i] = 0;
 
2231
    }
 
2232
  } else {
 
2233
    pos = topDict.fdSelectOffset;
 
2234
    fdSelectFmt = getU8(pos++, &parsedOk);
 
2235
    if (!parsedOk) {
 
2236
      return;
 
2237
    }
 
2238
    if (fdSelectFmt == 0) {
 
2239
      if (!checkRegion(pos, nGlyphs)) {
 
2240
        parsedOk = gFalse;
 
2241
        return;
 
2242
      }
 
2243
      memcpy(fdSelect, file + pos, nGlyphs);
 
2244
    } else if (fdSelectFmt == 3) {
 
2245
      nRanges = getU16BE(pos, &parsedOk);
 
2246
      pos += 2;
 
2247
      gid0 = getU16BE(pos, &parsedOk);
 
2248
      pos += 2;
 
2249
      for (i = 1; i <= nRanges; ++i) {
 
2250
        fd = getU8(pos++, &parsedOk);
 
2251
        gid1 = getU16BE(pos, &parsedOk);
 
2252
        if (!parsedOk) {
 
2253
          return;
 
2254
        }
 
2255
        pos += 2;
 
2256
        if (gid0 > gid1 || gid1 > nGlyphs) {
 
2257
          //~ error(-1, "Bad FDSelect table in CID font");
 
2258
          parsedOk = gFalse;
 
2259
          return;
 
2260
        }
 
2261
        for (j = gid0; j < gid1; ++j) {
 
2262
          fdSelect[j] = fd;
 
2263
        }
 
2264
        gid0 = gid1;
 
2265
      }
 
2266
    } else {
 
2267
      //~ error(-1, "Unknown FDSelect table format in CID font");
 
2268
      for (i = 0; i < nGlyphs; ++i) {
 
2269
        fdSelect[i] = 0;
 
2270
      }
 
2271
    }
 
2272
  }
 
2273
}
 
2274
 
 
2275
void FoFiType1C::buildEncoding() {
 
2276
  char buf[256];
 
2277
  int nCodes, nRanges, encFormat;
 
2278
  int pos, c, sid, nLeft, nSups, i, j;
 
2279
 
 
2280
  if (topDict.encodingOffset == 0) {
 
2281
    encoding = fofiType1StandardEncoding;
 
2282
 
 
2283
  } else if (topDict.encodingOffset == 1) {
 
2284
    encoding = fofiType1ExpertEncoding;
 
2285
 
 
2286
  } else {
 
2287
    encoding = (char **)gmallocn(256, sizeof(char *));
 
2288
    for (i = 0; i < 256; ++i) {
 
2289
      encoding[i] = NULL;
 
2290
    }
 
2291
    pos = topDict.encodingOffset;
 
2292
    encFormat = getU8(pos++, &parsedOk);
 
2293
    if (!parsedOk) {
 
2294
      return;
 
2295
    }
 
2296
    if ((encFormat & 0x7f) == 0) {
 
2297
      nCodes = 1 + getU8(pos++, &parsedOk);
 
2298
      if (!parsedOk) {
 
2299
        return;
 
2300
      }
 
2301
      if (nCodes > nGlyphs) {
 
2302
        nCodes = nGlyphs;
 
2303
      }
 
2304
      for (i = 1; i < nCodes; ++i) {
 
2305
        c = getU8(pos++, &parsedOk);
 
2306
        if (!parsedOk) {
 
2307
          return;
 
2308
        }
 
2309
        if (encoding[c]) {
 
2310
          gfree(encoding[c]);
 
2311
        }
 
2312
        encoding[c] = copyString(getString(charset[i], buf, &parsedOk));
 
2313
      }
 
2314
    } else if ((encFormat & 0x7f) == 1) {
 
2315
      nRanges = getU8(pos++, &parsedOk);
 
2316
      if (!parsedOk) {
 
2317
        return;
 
2318
      }
 
2319
      nCodes = 1;
 
2320
      for (i = 0; i < nRanges; ++i) {
 
2321
        c = getU8(pos++, &parsedOk);
 
2322
        nLeft = getU8(pos++, &parsedOk);
 
2323
        if (!parsedOk) {
 
2324
          return;
 
2325
        }
 
2326
        for (j = 0; j <= nLeft && nCodes < nGlyphs; ++j) {
 
2327
          if (c < 256) {
 
2328
            if (encoding[c]) {
 
2329
              gfree(encoding[c]);
 
2330
            }
 
2331
            encoding[c] = copyString(getString(charset[nCodes], buf,
 
2332
                                               &parsedOk));
 
2333
          }
 
2334
          ++nCodes;
 
2335
          ++c;
 
2336
        }
 
2337
      }
 
2338
    }
 
2339
    if (encFormat & 0x80) {
 
2340
      nSups = getU8(pos++, &parsedOk);
 
2341
      if (!parsedOk) {
 
2342
        return;
 
2343
      }
 
2344
      for (i = 0; i < nSups; ++i) {
 
2345
        c = getU8(pos++, &parsedOk);;
 
2346
        if (!parsedOk) {
 
2347
          return;;
 
2348
        }
 
2349
        sid = getU16BE(pos, &parsedOk);
 
2350
        pos += 2;
 
2351
        if (!parsedOk) {
 
2352
          return;
 
2353
        }
 
2354
        if (encoding[c]) {
 
2355
          gfree(encoding[c]);
 
2356
        }
 
2357
        encoding[c] = copyString(getString(sid, buf, &parsedOk));
 
2358
      }
 
2359
    }
 
2360
  }
 
2361
}
 
2362
 
 
2363
GBool FoFiType1C::readCharset() {
 
2364
  int charsetFormat, c, pos;
 
2365
  int nLeft, i, j;
 
2366
 
 
2367
  if (topDict.charsetOffset == 0) {
 
2368
    charset = fofiType1CISOAdobeCharset;
 
2369
  } else if (topDict.charsetOffset == 1) {
 
2370
    charset = fofiType1CExpertCharset;
 
2371
  } else if (topDict.charsetOffset == 2) {
 
2372
    charset = fofiType1CExpertSubsetCharset;
 
2373
  } else {
 
2374
    charset = (Gushort *)gmallocn(nGlyphs, sizeof(Gushort));
 
2375
    for (i = 0; i < nGlyphs; ++i) {
 
2376
      charset[i] = 0;
 
2377
    }
 
2378
    pos = topDict.charsetOffset;
 
2379
    charsetFormat = getU8(pos++, &parsedOk);
 
2380
    if (charsetFormat == 0) {
 
2381
      for (i = 1; i < nGlyphs; ++i) {
 
2382
        charset[i] = (Gushort)getU16BE(pos, &parsedOk);
 
2383
        pos += 2;
 
2384
        if (!parsedOk) {
 
2385
          break;
 
2386
        }
 
2387
      }
 
2388
    } else if (charsetFormat == 1) {
 
2389
      i = 1;
 
2390
      while (i < nGlyphs) {
 
2391
        c = getU16BE(pos, &parsedOk);
 
2392
        pos += 2;
 
2393
        nLeft = getU8(pos++, &parsedOk);
 
2394
        if (!parsedOk) {
 
2395
          break;
 
2396
        }
 
2397
        for (j = 0; j <= nLeft && i < nGlyphs; ++j) {
 
2398
          charset[i++] = (Gushort)c++;
 
2399
        }
 
2400
      }
 
2401
    } else if (charsetFormat == 2) {
 
2402
      i = 1;
 
2403
      while (i < nGlyphs) {
 
2404
        c = getU16BE(pos, &parsedOk);
 
2405
        pos += 2;
 
2406
        nLeft = getU16BE(pos, &parsedOk);
 
2407
        pos += 2;
 
2408
        if (!parsedOk) {
 
2409
          break;
 
2410
        }
 
2411
        for (j = 0; j <= nLeft && i < nGlyphs; ++j) {
 
2412
          charset[i++] = (Gushort)c++;
 
2413
        }
 
2414
      }
 
2415
    }
 
2416
    if (!parsedOk) {
 
2417
      gfree(charset);
 
2418
      charset = NULL;
 
2419
      return gFalse;
 
2420
    }
 
2421
  }
 
2422
  return gTrue;
 
2423
}
 
2424
 
 
2425
int FoFiType1C::getOp(int pos, GBool charstring, GBool *ok) {
 
2426
  static char nybChars[16] = "0123456789.ee -";
 
2427
  Type1COp op;
 
2428
  char buf[65];
 
2429
  int b0, b1, nyb0, nyb1, x, i;
 
2430
 
 
2431
  b0 = getU8(pos++, ok);
 
2432
  op.isNum = gTrue;
 
2433
  op.isFP = gFalse;
 
2434
 
 
2435
  if (b0 == 28) {
 
2436
    x = getU8(pos++, ok);
 
2437
    x = (x << 8) | getU8(pos++, ok);
 
2438
    if (x & 0x8000) {
 
2439
      x |= ~0xffff;
 
2440
    }
 
2441
    op.num = x;
 
2442
 
 
2443
  } else if (!charstring && b0 == 29) {
 
2444
    x = getU8(pos++, ok);
 
2445
    x = (x << 8) | getU8(pos++, ok);
 
2446
    x = (x << 8) | getU8(pos++, ok);
 
2447
    x = (x << 8) | getU8(pos++, ok);
 
2448
    if (x & 0x80000000) {
 
2449
      x |= ~0xffffffff;
 
2450
    }
 
2451
    op.num = x;
 
2452
 
 
2453
  } else if (!charstring && b0 == 30) {
 
2454
    i = 0;
 
2455
    do {
 
2456
      b1 = getU8(pos++, ok);
 
2457
      nyb0 = b1 >> 4;
 
2458
      nyb1 = b1 & 0x0f;
 
2459
      if (nyb0 == 0xf) {
 
2460
        break;
 
2461
      }
 
2462
      buf[i++] = nybChars[nyb0];
 
2463
      if (i == 64) {
 
2464
        break;
 
2465
      }
 
2466
      if (nyb0 == 0xc) {
 
2467
        buf[i++] = '-';
 
2468
      }
 
2469
      if (i == 64) {
 
2470
        break;
 
2471
      }
 
2472
      if (nyb1 == 0xf) {
 
2473
        break;
 
2474
      }
 
2475
      buf[i++] = nybChars[nyb1];
 
2476
      if (i == 64) {
 
2477
        break;
 
2478
      }
 
2479
      if (nyb1 == 0xc) {
 
2480
        buf[i++] = '-';
 
2481
      }
 
2482
    } while (i < 64);
 
2483
    buf[i] = '\0';
 
2484
    op.num = gatof(buf);
 
2485
    op.isFP = gTrue;
 
2486
 
 
2487
  } else if (b0 >= 32 && b0 <= 246) {
 
2488
    op.num = b0 - 139;
 
2489
 
 
2490
  } else if (b0 >= 247 && b0 <= 250) {
 
2491
    op.num = ((b0 - 247) << 8) + getU8(pos++, ok) + 108;
 
2492
 
 
2493
  } else if (b0 >= 251 && b0 <= 254) {
 
2494
    op.num = -((b0 - 251) << 8) - getU8(pos++, ok) - 108;
 
2495
 
 
2496
  } else if (charstring && b0 == 255) {
 
2497
    x = getU8(pos++, ok);
 
2498
    x = (x << 8) | getU8(pos++, ok);
 
2499
    x = (x << 8) | getU8(pos++, ok);
 
2500
    x = (x << 8) | getU8(pos++, ok);
 
2501
    if (x & 0x80000000) {
 
2502
      x |= ~0xffffffff;
 
2503
    }
 
2504
    op.num = (double)x / 65536.0;
 
2505
    op.isFP = gTrue;
 
2506
 
 
2507
  } else if (b0 == 12) {
 
2508
    op.isNum = gFalse;
 
2509
    op.op = 0x0c00 + getU8(pos++, ok);
 
2510
 
 
2511
  } else {
 
2512
    op.isNum = gFalse;
 
2513
    op.op = b0;
 
2514
  }
 
2515
 
 
2516
  if (nOps < 49) {
 
2517
    ops[nOps++] = op;
 
2518
  }
 
2519
 
 
2520
  return pos;
 
2521
}
 
2522
 
 
2523
// Convert the delta-encoded ops array to an array of ints.
 
2524
int FoFiType1C::getDeltaIntArray(int *arr, int maxLen) {
 
2525
  int x;
 
2526
  int n, i;
 
2527
 
 
2528
  if ((n = nOps) > maxLen) {
 
2529
    n = maxLen;
 
2530
  }
 
2531
  x = 0;
 
2532
  for (i = 0; i < n; ++i) {
 
2533
    x += (int)ops[i].num;
 
2534
    arr[i] = x;
 
2535
  }
 
2536
  return n;
 
2537
}
 
2538
 
 
2539
// Convert the delta-encoded ops array to an array of doubles.
 
2540
int FoFiType1C::getDeltaFPArray(double *arr, int maxLen) {
 
2541
  double x;
 
2542
  int n, i;
 
2543
 
 
2544
  if ((n = nOps) > maxLen) {
 
2545
    n = maxLen;
 
2546
  }
 
2547
  x = 0;
 
2548
  for (i = 0; i < n; ++i) {
 
2549
    x += ops[i].num;
 
2550
    arr[i] = x;
 
2551
  }
 
2552
  return n;
 
2553
}
 
2554
 
 
2555
void FoFiType1C::getIndex(int pos, Type1CIndex *idx, GBool *ok) {
 
2556
  idx->pos = pos;
 
2557
  idx->len = getU16BE(pos, ok);
 
2558
  if (idx->len == 0) {
 
2559
    // empty indexes are legal and contain just the length field
 
2560
    idx->offSize = 0;
 
2561
    idx->startPos = idx->endPos = pos + 2;
 
2562
  } else {
 
2563
    idx->offSize = getU8(pos + 2, ok);
 
2564
    if (idx->offSize < 1 || idx->offSize > 4) {
 
2565
      *ok = gFalse;
 
2566
    }
 
2567
    idx->startPos = pos + 3 + (idx->len + 1) * idx->offSize - 1;
 
2568
    if (idx->startPos < 0 || idx->startPos >= len) {
 
2569
      *ok = gFalse;
 
2570
    }
 
2571
    idx->endPos = idx->startPos + getUVarBE(pos + 3 + idx->len * idx->offSize,
 
2572
                                            idx->offSize, ok);
 
2573
    if (idx->endPos < idx->startPos || idx->endPos > len) {
 
2574
      *ok = gFalse;
 
2575
    }
 
2576
  }
 
2577
}
 
2578
 
 
2579
void FoFiType1C::getIndexVal(Type1CIndex *idx, int i,
 
2580
                             Type1CIndexVal *val, GBool *ok) {
 
2581
  int pos0, pos1;
 
2582
 
 
2583
  if (i < 0 || i >= idx->len) {
 
2584
    *ok = gFalse;
 
2585
    return;
 
2586
  }
 
2587
  pos0 = idx->startPos + getUVarBE(idx->pos + 3 + i * idx->offSize,
 
2588
                                   idx->offSize, ok);
 
2589
  pos1 = idx->startPos + getUVarBE(idx->pos + 3 + (i + 1) * idx->offSize,
 
2590
                                   idx->offSize, ok);
 
2591
  if (pos0 < idx->startPos || pos0 > idx->endPos ||
 
2592
      pos1 <= idx->startPos || pos1 > idx->endPos ||
 
2593
      pos1 < pos0) {
 
2594
    *ok = gFalse;
 
2595
  }
 
2596
  val->pos = pos0;
 
2597
  val->len = pos1 - pos0;
 
2598
}
 
2599
 
 
2600
char *FoFiType1C::getString(int sid, char *buf, GBool *ok) {
 
2601
  Type1CIndexVal val;
 
2602
  int n;
 
2603
 
 
2604
  if (sid < 391) {
 
2605
    strcpy(buf, fofiType1CStdStrings[sid]);
 
2606
  } else {
 
2607
    sid -= 391;
 
2608
    getIndexVal(&stringIdx, sid, &val, ok);
 
2609
    if (*ok) {
 
2610
      if ((n = val.len) > 255) {
 
2611
        n = 255;
 
2612
      }
 
2613
      strncpy(buf, (char *)&file[val.pos], n);
 
2614
      buf[n] = '\0';
 
2615
    } else {
 
2616
      buf[0] = '\0';
 
2617
    }
 
2618
  }
 
2619
  return buf;
 
2620
}