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

« back to all changes in this revision

Viewing changes to tests/poppler/fofi/FoFiTrueType.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
// FoFiTrueType.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) 2006 Takashi Iwai <tiwai@suse.de>
 
17
// Copyright (C) 2007 Koji Otani <sho@bbr.jp>
 
18
// Copyright (C) 2007 Carlos Garcia Campos <carlosgc@gnome.org>
 
19
// Copyright (C) 2008, 2009 Albert Astals Cid <aacid@kde.org>
 
20
// Copyright (C) 2008 Tomas Are Haavet <tomasare@gmail.com>
 
21
//
 
22
// To see a description of the changes please see the Changelog file that
 
23
// came with your tarball or type make ChangeLog if you are building from git
 
24
//
 
25
//========================================================================
 
26
 
 
27
#include <config.h>
 
28
 
 
29
#ifdef USE_GCC_PRAGMAS
 
30
#pragma implementation
 
31
#endif
 
32
 
 
33
#include <stdlib.h>
 
34
#include <string.h>
 
35
#include "goo/gtypes.h"
 
36
#include "goo/gmem.h"
 
37
#include "goo/GooString.h"
 
38
#include "goo/GooHash.h"
 
39
#include "FoFiType1C.h"
 
40
#include "FoFiTrueType.h"
 
41
#include "poppler/Error.h"
 
42
 
 
43
//
 
44
// Terminology
 
45
// -----------
 
46
//
 
47
// character code = number used as an element of a text string
 
48
//
 
49
// character name = glyph name = name for a particular glyph within a
 
50
//                  font
 
51
//
 
52
// glyph index = GID = position (within some internal table in the font)
 
53
//               where the instructions to draw a particular glyph are
 
54
//               stored
 
55
//
 
56
// Type 1 fonts
 
57
// ------------
 
58
//
 
59
// Type 1 fonts contain:
 
60
//
 
61
// Encoding: array of glyph names, maps char codes to glyph names
 
62
//
 
63
//           Encoding[charCode] = charName
 
64
//
 
65
// CharStrings: dictionary of instructions, keyed by character names,
 
66
//              maps character name to glyph data
 
67
//
 
68
//              CharStrings[charName] = glyphData
 
69
//
 
70
// TrueType fonts
 
71
// --------------
 
72
//
 
73
// TrueType fonts contain:
 
74
//
 
75
// 'cmap' table: mapping from character code to glyph index; there may
 
76
//               be multiple cmaps in a TrueType font
 
77
//
 
78
//               cmap[charCode] = gid
 
79
//
 
80
// 'post' table: mapping from glyph index to glyph name
 
81
//
 
82
//               post[gid] = glyphName
 
83
//
 
84
// Type 42 fonts
 
85
// -------------
 
86
//
 
87
// Type 42 fonts contain:
 
88
//
 
89
// Encoding: array of glyph names, maps char codes to glyph names
 
90
//
 
91
//           Encoding[charCode] = charName
 
92
//
 
93
// CharStrings: dictionary of glyph indexes, keyed by character names,
 
94
//              maps character name to glyph index
 
95
//
 
96
//              CharStrings[charName] = gid
 
97
//
 
98
 
 
99
//------------------------------------------------------------------------
 
100
 
 
101
#define ttcfTag 0x74746366
 
102
 
 
103
//------------------------------------------------------------------------
 
104
 
 
105
struct TrueTypeTable {
 
106
  Guint tag;
 
107
  Guint checksum;
 
108
  int offset;
 
109
  int origOffset;
 
110
  int len;
 
111
};
 
112
 
 
113
struct TrueTypeCmap {
 
114
  int platform;
 
115
  int encoding;
 
116
  int offset;
 
117
  int len;
 
118
  int fmt;
 
119
};
 
120
 
 
121
struct TrueTypeLoca {
 
122
  int idx;
 
123
  int origOffset;
 
124
  int newOffset;
 
125
  int len;
 
126
};
 
127
 
 
128
#define cmapTag 0x636d6170
 
129
#define glyfTag 0x676c7966
 
130
#define headTag 0x68656164
 
131
#define hheaTag 0x68686561
 
132
#define hmtxTag 0x686d7478
 
133
#define locaTag 0x6c6f6361
 
134
#define nameTag 0x6e616d65
 
135
#define os2Tag  0x4f532f32
 
136
#define postTag 0x706f7374
 
137
#define vrt2Tag 0x76727432
 
138
#define vertTag 0x76657274
 
139
 
 
140
static int cmpTrueTypeLocaOffset(const void *p1, const void *p2) {
 
141
  TrueTypeLoca *loca1 = (TrueTypeLoca *)p1;
 
142
  TrueTypeLoca *loca2 = (TrueTypeLoca *)p2;
 
143
 
 
144
  if (loca1->origOffset == loca2->origOffset) {
 
145
    return loca1->idx - loca2->idx;
 
146
  }
 
147
  return loca1->origOffset - loca2->origOffset;
 
148
}
 
149
 
 
150
static int cmpTrueTypeLocaIdx(const void *p1, const void *p2) {
 
151
  TrueTypeLoca *loca1 = (TrueTypeLoca *)p1;
 
152
  TrueTypeLoca *loca2 = (TrueTypeLoca *)p2;
 
153
 
 
154
  return loca1->idx - loca2->idx;
 
155
}
 
156
 
 
157
static int cmpTrueTypeTableTag(const void *p1, const void *p2) {
 
158
  TrueTypeTable *tab1 = (TrueTypeTable *)p1;
 
159
  TrueTypeTable *tab2 = (TrueTypeTable *)p2;
 
160
 
 
161
  return (int)tab1->tag - (int)tab2->tag;
 
162
}
 
163
 
 
164
//------------------------------------------------------------------------
 
165
 
 
166
struct T42Table {
 
167
  char *tag;                    // 4-byte tag
 
168
  GBool required;               // required by the TrueType spec?
 
169
};
 
170
 
 
171
// TrueType tables to be embedded in Type 42 fonts.
 
172
// NB: the table names must be in alphabetical order here.
 
173
#define nT42Tables 11
 
174
static T42Table t42Tables[nT42Tables] = {
 
175
  { "cvt ", gTrue  },
 
176
  { "fpgm", gTrue  },
 
177
  { "glyf", gTrue  },
 
178
  { "head", gTrue  },
 
179
  { "hhea", gTrue  },
 
180
  { "hmtx", gTrue  },
 
181
  { "loca", gTrue  },
 
182
  { "maxp", gTrue  },
 
183
  { "prep", gTrue  },
 
184
  { "vhea", gFalse },
 
185
  { "vmtx", gFalse }
 
186
};
 
187
#define t42HeadTable  3
 
188
#define t42LocaTable  6
 
189
#define t42GlyfTable  2
 
190
#define t42VheaTable  9
 
191
#define t42VmtxTable 10
 
192
 
 
193
//------------------------------------------------------------------------
 
194
 
 
195
// Glyph names in some arbitrary standard order that Apple uses for
 
196
// their TrueType fonts.
 
197
static char *macGlyphNames[258] = {
 
198
  ".notdef",        "null",           "CR",             "space",
 
199
  "exclam",         "quotedbl",       "numbersign",     "dollar",
 
200
  "percent",        "ampersand",      "quotesingle",    "parenleft",
 
201
  "parenright",     "asterisk",       "plus",           "comma",
 
202
  "hyphen",         "period",         "slash",          "zero",
 
203
  "one",            "two",            "three",          "four",
 
204
  "five",           "six",            "seven",          "eight",
 
205
  "nine",           "colon",          "semicolon",      "less",
 
206
  "equal",          "greater",        "question",       "at",
 
207
  "A",              "B",              "C",              "D",
 
208
  "E",              "F",              "G",              "H",
 
209
  "I",              "J",              "K",              "L",
 
210
  "M",              "N",              "O",              "P",
 
211
  "Q",              "R",              "S",              "T",
 
212
  "U",              "V",              "W",              "X",
 
213
  "Y",              "Z",              "bracketleft",    "backslash",
 
214
  "bracketright",   "asciicircum",    "underscore",     "grave",
 
215
  "a",              "b",              "c",              "d",
 
216
  "e",              "f",              "g",              "h",
 
217
  "i",              "j",              "k",              "l",
 
218
  "m",              "n",              "o",              "p",
 
219
  "q",              "r",              "s",              "t",
 
220
  "u",              "v",              "w",              "x",
 
221
  "y",              "z",              "braceleft",      "bar",
 
222
  "braceright",     "asciitilde",     "Adieresis",      "Aring",
 
223
  "Ccedilla",       "Eacute",         "Ntilde",         "Odieresis",
 
224
  "Udieresis",      "aacute",         "agrave",         "acircumflex",
 
225
  "adieresis",      "atilde",         "aring",          "ccedilla",
 
226
  "eacute",         "egrave",         "ecircumflex",    "edieresis",
 
227
  "iacute",         "igrave",         "icircumflex",    "idieresis",
 
228
  "ntilde",         "oacute",         "ograve",         "ocircumflex",
 
229
  "odieresis",      "otilde",         "uacute",         "ugrave",
 
230
  "ucircumflex",    "udieresis",      "dagger",         "degree",
 
231
  "cent",           "sterling",       "section",        "bullet",
 
232
  "paragraph",      "germandbls",     "registered",     "copyright",
 
233
  "trademark",      "acute",          "dieresis",       "notequal",
 
234
  "AE",             "Oslash",         "infinity",       "plusminus",
 
235
  "lessequal",      "greaterequal",   "yen",            "mu1",
 
236
  "partialdiff",    "summation",      "product",        "pi",
 
237
  "integral",       "ordfeminine",    "ordmasculine",   "Ohm",
 
238
  "ae",             "oslash",         "questiondown",   "exclamdown",
 
239
  "logicalnot",     "radical",        "florin",         "approxequal",
 
240
  "increment",      "guillemotleft",  "guillemotright", "ellipsis",
 
241
  "nbspace",        "Agrave",         "Atilde",         "Otilde",
 
242
  "OE",             "oe",             "endash",         "emdash",
 
243
  "quotedblleft",   "quotedblright",  "quoteleft",      "quoteright",
 
244
  "divide",         "lozenge",        "ydieresis",      "Ydieresis",
 
245
  "fraction",       "currency",       "guilsinglleft",  "guilsinglright",
 
246
  "fi",             "fl",             "daggerdbl",      "periodcentered",
 
247
  "quotesinglbase", "quotedblbase",   "perthousand",    "Acircumflex",
 
248
  "Ecircumflex",    "Aacute",         "Edieresis",      "Egrave",
 
249
  "Iacute",         "Icircumflex",    "Idieresis",      "Igrave",
 
250
  "Oacute",         "Ocircumflex",    "applelogo",      "Ograve",
 
251
  "Uacute",         "Ucircumflex",    "Ugrave",         "dotlessi",
 
252
  "circumflex",     "tilde",          "overscore",      "breve",
 
253
  "dotaccent",      "ring",           "cedilla",        "hungarumlaut",
 
254
  "ogonek",         "caron",          "Lslash",         "lslash",
 
255
  "Scaron",         "scaron",         "Zcaron",         "zcaron",
 
256
  "brokenbar",      "Eth",            "eth",            "Yacute",
 
257
  "yacute",         "Thorn",          "thorn",          "minus",
 
258
  "multiply",       "onesuperior",    "twosuperior",    "threesuperior",
 
259
  "onehalf",        "onequarter",     "threequarters",  "franc",
 
260
  "Gbreve",         "gbreve",         "Idot",           "Scedilla",
 
261
  "scedilla",       "Cacute",         "cacute",         "Ccaron",
 
262
  "ccaron",         "dmacron"
 
263
};
 
264
 
 
265
//------------------------------------------------------------------------
 
266
// FoFiTrueType
 
267
//------------------------------------------------------------------------
 
268
 
 
269
FoFiTrueType *FoFiTrueType::make(char *fileA, int lenA, int faceIndexA) {
 
270
  FoFiTrueType *ff;
 
271
 
 
272
  ff = new FoFiTrueType(fileA, lenA, gFalse, faceIndexA);
 
273
  if (!ff->parsedOk) {
 
274
    delete ff;
 
275
    return NULL;
 
276
  }
 
277
  return ff;
 
278
}
 
279
 
 
280
FoFiTrueType *FoFiTrueType::load(char *fileName, int faceIndexA) {
 
281
  FoFiTrueType *ff;
 
282
  char *fileA;
 
283
  int lenA;
 
284
 
 
285
  if (!(fileA = FoFiBase::readFile(fileName, &lenA))) {
 
286
    return NULL;
 
287
  }
 
288
  ff = new FoFiTrueType(fileA, lenA, gTrue, faceIndexA);
 
289
  if (!ff->parsedOk) {
 
290
    delete ff;
 
291
    return NULL;
 
292
  }
 
293
  return ff;
 
294
}
 
295
 
 
296
FoFiTrueType::FoFiTrueType(char *fileA, int lenA, GBool freeFileDataA, int faceIndexA):
 
297
  FoFiBase(fileA, lenA, freeFileDataA)
 
298
{
 
299
  tables = NULL;
 
300
  nTables = 0;
 
301
  cmaps = NULL;
 
302
  nCmaps = 0;
 
303
  nameToGID = NULL;
 
304
  parsedOk = gFalse;
 
305
  faceIndex = faceIndexA;
 
306
  gsubFeatureTable = 0;
 
307
  gsubLookupList = 0;
 
308
 
 
309
  parse();
 
310
}
 
311
 
 
312
FoFiTrueType::~FoFiTrueType() {
 
313
  gfree(tables);
 
314
  gfree(cmaps);
 
315
  if (nameToGID) {
 
316
    delete nameToGID;
 
317
  }
 
318
}
 
319
 
 
320
int FoFiTrueType::getNumCmaps() {
 
321
  return nCmaps;
 
322
}
 
323
 
 
324
int FoFiTrueType::getCmapPlatform(int i) {
 
325
  return cmaps[i].platform;
 
326
}
 
327
 
 
328
int FoFiTrueType::getCmapEncoding(int i) {
 
329
  return cmaps[i].encoding;
 
330
}
 
331
 
 
332
int FoFiTrueType::findCmap(int platform, int encoding) {
 
333
  int i;
 
334
 
 
335
  for (i = 0; i < nCmaps; ++i) {
 
336
    if (cmaps[i].platform == platform && cmaps[i].encoding == encoding) {
 
337
      return i;
 
338
    }
 
339
  }
 
340
  return -1;
 
341
}
 
342
 
 
343
Gushort FoFiTrueType::mapCodeToGID(int i, Guint c) {
 
344
  Gushort gid;
 
345
  Guint segCnt, segEnd, segStart, segDelta, segOffset;
 
346
  Guint cmapFirst, cmapLen;
 
347
  int pos, a, b, m;
 
348
  GBool ok;
 
349
 
 
350
  if (i < 0 || i >= nCmaps) {
 
351
    return 0;
 
352
  }
 
353
  ok = gTrue;
 
354
  pos = cmaps[i].offset;
 
355
  switch (cmaps[i].fmt) {
 
356
  case 0:
 
357
    if (c + 6 >= (Guint)cmaps[i].len) {
 
358
      return 0;
 
359
    }
 
360
    gid = getU8(cmaps[i].offset + 6 + c, &ok);
 
361
    break;
 
362
  case 4:
 
363
    segCnt = getU16BE(pos + 6, &ok) / 2;
 
364
    a = -1;
 
365
    b = segCnt - 1;
 
366
    segEnd = getU16BE(pos + 14 + 2*b, &ok);
 
367
    if (c > segEnd) {
 
368
      // malformed font -- the TrueType spec requires the last segEnd
 
369
      // to be 0xffff
 
370
      return 0;
 
371
    }
 
372
    // invariant: seg[a].end < code <= seg[b].end
 
373
    while (b - a > 1 && ok) {
 
374
      m = (a + b) / 2;
 
375
      segEnd = getU16BE(pos + 14 + 2*m, &ok);
 
376
      if (segEnd < c) {
 
377
        a = m;
 
378
      } else {
 
379
        b = m;
 
380
      }
 
381
    }
 
382
    segStart = getU16BE(pos + 16 + 2*segCnt + 2*b, &ok);
 
383
    segDelta = getU16BE(pos + 16 + 4*segCnt + 2*b, &ok);
 
384
    segOffset = getU16BE(pos + 16 + 6*segCnt + 2*b, &ok);
 
385
    if (c < segStart) {
 
386
      return 0;
 
387
    }
 
388
    if (segOffset == 0) {
 
389
      gid = (c + segDelta) & 0xffff;
 
390
    } else {
 
391
      gid = getU16BE(pos + 16 + 6*segCnt + 2*b +
 
392
                       segOffset + 2 * (c - segStart), &ok);
 
393
      if (gid != 0) {
 
394
        gid = (gid + segDelta) & 0xffff;
 
395
      }
 
396
    }
 
397
    break;
 
398
  case 6:
 
399
    cmapFirst = getU16BE(pos + 6, &ok);
 
400
    cmapLen = getU16BE(pos + 8, &ok);
 
401
    if (c < cmapFirst || c >= cmapFirst + cmapLen) {
 
402
      return 0;
 
403
    }
 
404
    gid = getU16BE(pos + 10 + 2 * (c - cmapFirst), &ok);
 
405
    break;
 
406
  case 12:
 
407
    segCnt = getU32BE(pos + 12, &ok);
 
408
    a = -1;
 
409
    b = segCnt - 1;
 
410
    segEnd = getU32BE(pos + 16 + 12*b+4, &ok);
 
411
    if (c > segEnd) {
 
412
      return 0;
 
413
    }
 
414
    // invariant: seg[a].end < code <= seg[b].end
 
415
    while (b - a > 1 && ok) {
 
416
      m = (a + b) / 2;
 
417
      segEnd = getU32BE(pos + 16 + 12*m+4, &ok);
 
418
      if (segEnd < c) {
 
419
        a = m;
 
420
      } else {
 
421
        b = m;
 
422
      }
 
423
    }
 
424
    segStart = getU32BE(pos + 16 + 12*b, &ok);
 
425
    segDelta = getU32BE(pos + 16 + 12*b+8, &ok);
 
426
    if (c < segStart) {
 
427
      return 0;
 
428
    }
 
429
    gid = segDelta + (c-segStart);
 
430
    break;
 
431
  default:
 
432
    return 0;
 
433
  }
 
434
  if (!ok) {
 
435
    return 0;
 
436
  }
 
437
  return gid;
 
438
}
 
439
 
 
440
int FoFiTrueType::mapNameToGID(char *name) {
 
441
  if (!nameToGID) {
 
442
    return 0;
 
443
  }
 
444
  return nameToGID->lookupInt(name);
 
445
}
 
446
 
 
447
Gushort *FoFiTrueType::getCIDToGIDMap(int *nCIDs) {
 
448
  FoFiType1C *ff;
 
449
  Gushort *map;
 
450
  int i;
 
451
 
 
452
  *nCIDs = 0;
 
453
  if (!openTypeCFF) {
 
454
    return NULL;
 
455
  }
 
456
  i = seekTable("CFF ");
 
457
  if (!checkRegion(tables[i].offset, tables[i].len)) {
 
458
    return NULL;
 
459
  }
 
460
  if (!(ff = FoFiType1C::make((char *)file + tables[i].offset,
 
461
                              tables[i].len))) {
 
462
    return NULL;
 
463
  }
 
464
  map = ff->getCIDToGIDMap(nCIDs);
 
465
  delete ff;
 
466
  return map;
 
467
}
 
468
 
 
469
int FoFiTrueType::getEmbeddingRights() {
 
470
  int i, fsType;
 
471
  GBool ok;
 
472
 
 
473
  if ((i = seekTable("OS/2")) < 0) {
 
474
    return 4;
 
475
  }
 
476
  ok = gTrue;
 
477
  fsType = getU16BE(tables[i].offset + 8, &ok);
 
478
  if (!ok) {
 
479
    return 4;
 
480
  }
 
481
  if (fsType & 0x0008) {
 
482
    return 2;
 
483
  }
 
484
  if (fsType & 0x0004) {
 
485
    return 1;
 
486
  }
 
487
  if (fsType & 0x0002) {
 
488
    return 0;
 
489
  }
 
490
  return 3;
 
491
}
 
492
 
 
493
void FoFiTrueType::convertToType42(char *psName, char **encoding,
 
494
                                   Gushort *codeToGID,
 
495
                                   FoFiOutputFunc outputFunc,
 
496
                                   void *outputStream) {
 
497
  GooString *buf;
 
498
  GBool ok;
 
499
 
 
500
  if (openTypeCFF) {
 
501
    return;
 
502
  }
 
503
 
 
504
  // write the header
 
505
  ok = gTrue;
 
506
  buf = GooString::format("%!PS-TrueTypeFont-{0:2g}\n",
 
507
                        (double)getS32BE(0, &ok) / 65536.0);
 
508
  (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
509
  delete buf;
 
510
 
 
511
  // begin the font dictionary
 
512
  (*outputFunc)(outputStream, "10 dict begin\n", 14);
 
513
  (*outputFunc)(outputStream, "/FontName /", 11);
 
514
  (*outputFunc)(outputStream, psName, strlen(psName));
 
515
  (*outputFunc)(outputStream, " def\n", 5);
 
516
  (*outputFunc)(outputStream, "/FontType 42 def\n", 17);
 
517
  (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
 
518
  buf = GooString::format("/FontBBox [{0:d} {1:d} {2:d} {3:d}] def\n",
 
519
                        bbox[0], bbox[1], bbox[2], bbox[3]);
 
520
  (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
521
  delete buf;
 
522
  (*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
 
523
 
 
524
  // write the guts of the dictionary
 
525
  cvtEncoding(encoding, outputFunc, outputStream);
 
526
  cvtCharStrings(encoding, codeToGID, outputFunc, outputStream);
 
527
  cvtSfnts(outputFunc, outputStream, NULL, gFalse);
 
528
 
 
529
  // end the dictionary and define the font
 
530
  (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
 
531
}
 
532
 
 
533
void FoFiTrueType::convertToType1(char *psName, char **newEncoding,
 
534
                                  GBool ascii, FoFiOutputFunc outputFunc,
 
535
                                  void *outputStream) {
 
536
  FoFiType1C *ff;
 
537
  int i;
 
538
 
 
539
  if (!openTypeCFF) {
 
540
    return;
 
541
  }
 
542
  i = seekTable("CFF ");
 
543
  if (!checkRegion(tables[i].offset, tables[i].len)) {
 
544
    return;
 
545
  }
 
546
  if (!(ff = FoFiType1C::make((char *)file + tables[i].offset,
 
547
                              tables[i].len))) {
 
548
    return;
 
549
  }
 
550
  ff->convertToType1(psName, newEncoding, ascii, outputFunc, outputStream);
 
551
  delete ff;
 
552
}
 
553
 
 
554
void FoFiTrueType::convertToCIDType2(char *psName,
 
555
                                     Gushort *cidMap, int nCIDs,
 
556
                                     GBool needVerticalMetrics,
 
557
                                     FoFiOutputFunc outputFunc,
 
558
                                     void *outputStream) {
 
559
  GooString *buf;
 
560
  Gushort cid;
 
561
  GBool ok;
 
562
  int i, j, k;
 
563
 
 
564
  if (openTypeCFF) {
 
565
    return;
 
566
  }
 
567
 
 
568
  // write the header
 
569
  ok = gTrue;
 
570
  buf = GooString::format("%!PS-TrueTypeFont-{0:2g}\n",
 
571
                        (double)getS32BE(0, &ok) / 65536.0);
 
572
  (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
573
  delete buf;
 
574
 
 
575
  // begin the font dictionary
 
576
  (*outputFunc)(outputStream, "20 dict begin\n", 14);
 
577
  (*outputFunc)(outputStream, "/CIDFontName /", 14);
 
578
  (*outputFunc)(outputStream, psName, strlen(psName));
 
579
  (*outputFunc)(outputStream, " def\n", 5);
 
580
  (*outputFunc)(outputStream, "/CIDFontType 2 def\n", 19);
 
581
  (*outputFunc)(outputStream, "/FontType 42 def\n", 17);
 
582
  (*outputFunc)(outputStream, "/CIDSystemInfo 3 dict dup begin\n", 32);
 
583
  (*outputFunc)(outputStream, "  /Registry (Adobe) def\n", 24);
 
584
  (*outputFunc)(outputStream, "  /Ordering (Identity) def\n", 27);
 
585
  (*outputFunc)(outputStream, "  /Supplement 0 def\n", 20);
 
586
  (*outputFunc)(outputStream, "  end def\n", 10);
 
587
  (*outputFunc)(outputStream, "/GDBytes 2 def\n", 15);
 
588
  if (cidMap) {
 
589
    buf = GooString::format("/CIDCount {0:d} def\n", nCIDs);
 
590
    (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
591
    delete buf;
 
592
    if (nCIDs > 32767) {
 
593
      (*outputFunc)(outputStream, "/CIDMap [", 9);
 
594
      for (i = 0; i < nCIDs; i += 32768 - 16) {
 
595
        (*outputFunc)(outputStream, "<\n", 2);
 
596
        for (j = 0; j < 32768 - 16 && i+j < nCIDs; j += 16) {
 
597
          (*outputFunc)(outputStream, "  ", 2);
 
598
          for (k = 0; k < 16 && i+j+k < nCIDs; ++k) {
 
599
            cid = cidMap[i+j+k];
 
600
            buf = GooString::format("{0:02x}{1:02x}",
 
601
                                  (cid >> 8) & 0xff, cid & 0xff);
 
602
            (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
603
            delete buf;
 
604
          }
 
605
          (*outputFunc)(outputStream, "\n", 1);
 
606
        }
 
607
        (*outputFunc)(outputStream, "  >", 3);
 
608
      }
 
609
      (*outputFunc)(outputStream, "\n", 1);
 
610
      (*outputFunc)(outputStream, "] def\n", 6);
 
611
    } else {
 
612
      (*outputFunc)(outputStream, "/CIDMap <\n", 10);
 
613
      for (i = 0; i < nCIDs; i += 16) {
 
614
        (*outputFunc)(outputStream, "  ", 2);
 
615
        for (j = 0; j < 16 && i+j < nCIDs; ++j) {
 
616
          cid = cidMap[i+j];
 
617
          buf = GooString::format("{0:02x}{1:02x}",
 
618
                                (cid >> 8) & 0xff, cid & 0xff);
 
619
          (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
620
          delete buf;
 
621
        }
 
622
        (*outputFunc)(outputStream, "\n", 1);
 
623
      }
 
624
      (*outputFunc)(outputStream, "> def\n", 6);
 
625
    }
 
626
  } else {
 
627
    // direct mapping - just fill the string(s) with s[i]=i
 
628
    buf = GooString::format("/CIDCount {0:d} def\n", nGlyphs);
 
629
    (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
630
    delete buf;
 
631
    if (nGlyphs > 32767) {
 
632
      (*outputFunc)(outputStream, "/CIDMap [\n", 10);
 
633
      for (i = 0; i < nGlyphs; i += 32767) {
 
634
        j = nGlyphs - i < 32767 ? nGlyphs - i : 32767;
 
635
        buf = GooString::format("  {0:d} string 0 1 {1:d} {{\n", 2 * j, j - 1);
 
636
        (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
637
        delete buf;
 
638
        buf = GooString::format("    2 copy dup 2 mul exch {0:d} add -8 bitshift put\n",
 
639
                              i);
 
640
        (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
641
        delete buf;
 
642
        buf = GooString::format("    1 index exch dup 2 mul 1 add exch {0:d} add"
 
643
                              " 255 and put\n", i);
 
644
        (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
645
        delete buf;
 
646
        (*outputFunc)(outputStream, "  } for\n", 8);
 
647
      }
 
648
      (*outputFunc)(outputStream, "] def\n", 6);
 
649
    } else {
 
650
      buf = GooString::format("/CIDMap {0:d} string\n", 2 * nGlyphs);
 
651
      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
652
      delete buf;
 
653
      buf = GooString::format("  0 1 {0:d} {{\n", nGlyphs - 1);
 
654
      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
655
      delete buf;
 
656
      (*outputFunc)(outputStream,
 
657
                    "    2 copy dup 2 mul exch -8 bitshift put\n", 42);
 
658
      (*outputFunc)(outputStream,
 
659
                    "    1 index exch dup 2 mul 1 add exch 255 and put\n", 50);
 
660
      (*outputFunc)(outputStream, "  } for\n", 8);
 
661
      (*outputFunc)(outputStream, "def\n", 4);
 
662
    }
 
663
  }
 
664
  (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
 
665
  buf = GooString::format("/FontBBox [{0:d} {1:d} {2:d} {3:d}] def\n",
 
666
                        bbox[0], bbox[1], bbox[2], bbox[3]);
 
667
  (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
668
  delete buf;
 
669
  (*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
 
670
  (*outputFunc)(outputStream, "/Encoding [] readonly def\n", 26);
 
671
  (*outputFunc)(outputStream, "/CharStrings 1 dict dup begin\n", 30);
 
672
  (*outputFunc)(outputStream, "  /.notdef 0 def\n", 17);
 
673
  (*outputFunc)(outputStream, "  end readonly def\n", 19);
 
674
 
 
675
  // write the guts of the dictionary
 
676
  cvtSfnts(outputFunc, outputStream, NULL, needVerticalMetrics);
 
677
 
 
678
  // end the dictionary and define the font
 
679
  (*outputFunc)(outputStream,
 
680
                "CIDFontName currentdict end /CIDFont defineresource pop\n",
 
681
                56);
 
682
}
 
683
 
 
684
void FoFiTrueType::convertToCIDType0(char *psName,
 
685
                                     FoFiOutputFunc outputFunc,
 
686
                                     void *outputStream) {
 
687
  FoFiType1C *ff;
 
688
  int i;
 
689
 
 
690
  if (!openTypeCFF) {
 
691
    return;
 
692
  }
 
693
  i = seekTable("CFF ");
 
694
  if (!checkRegion(tables[i].offset, tables[i].len)) {
 
695
    return;
 
696
  }
 
697
  if (!(ff = FoFiType1C::make((char *)file + tables[i].offset,
 
698
                              tables[i].len))) {
 
699
    return;
 
700
  }
 
701
  ff->convertToCIDType0(psName, outputFunc, outputStream);
 
702
  delete ff;
 
703
}
 
704
 
 
705
void FoFiTrueType::convertToType0(char *psName, Gushort *cidMap, int nCIDs,
 
706
                                  GBool needVerticalMetrics,
 
707
                                  FoFiOutputFunc outputFunc,
 
708
                                  void *outputStream) {
 
709
  GooString *buf;
 
710
  GooString *sfntsName;
 
711
  int n, i, j;
 
712
 
 
713
  if (openTypeCFF) {
 
714
    return;
 
715
  }
 
716
 
 
717
  // write the Type 42 sfnts array
 
718
  sfntsName = (new GooString(psName))->append("_sfnts");
 
719
  cvtSfnts(outputFunc, outputStream, sfntsName, needVerticalMetrics);
 
720
  delete sfntsName;
 
721
 
 
722
  // write the descendant Type 42 fonts
 
723
  n = cidMap ? nCIDs : nGlyphs;
 
724
  for (i = 0; i < n; i += 256) {
 
725
    (*outputFunc)(outputStream, "10 dict begin\n", 14);
 
726
    (*outputFunc)(outputStream, "/FontName /", 11);
 
727
    (*outputFunc)(outputStream, psName, strlen(psName));
 
728
    buf = GooString::format("_{0:02x} def\n", i >> 8);
 
729
    (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
730
    delete buf;
 
731
    (*outputFunc)(outputStream, "/FontType 42 def\n", 17);
 
732
    (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
 
733
    buf = GooString::format("/FontBBox [{0:d} {1:d} {2:d} {3:d}] def\n",
 
734
                          bbox[0], bbox[1], bbox[2], bbox[3]);
 
735
    (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
736
    delete buf;
 
737
    (*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
 
738
    (*outputFunc)(outputStream, "/sfnts ", 7);
 
739
    (*outputFunc)(outputStream, psName, strlen(psName));
 
740
    (*outputFunc)(outputStream, "_sfnts def\n", 11);
 
741
    (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
 
742
    for (j = 0; j < 256 && i+j < n; ++j) {
 
743
      buf = GooString::format("dup {0:d} /c{1:02x} put\n", j, j);
 
744
      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
745
      delete buf;
 
746
    }
 
747
    (*outputFunc)(outputStream, "readonly def\n", 13);
 
748
    (*outputFunc)(outputStream, "/CharStrings 257 dict dup begin\n", 32);
 
749
    (*outputFunc)(outputStream, "/.notdef 0 def\n", 15);
 
750
    for (j = 0; j < 256 && i+j < n; ++j) {
 
751
      buf = GooString::format("/c{0:02x} {1:d} def\n",
 
752
                            j, cidMap ? cidMap[i+j] : i+j);
 
753
      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
754
      delete buf;
 
755
    }
 
756
    (*outputFunc)(outputStream, "end readonly def\n", 17);
 
757
    (*outputFunc)(outputStream,
 
758
                  "FontName currentdict end definefont pop\n", 40);
 
759
  }
 
760
 
 
761
  // write the Type 0 parent font
 
762
  (*outputFunc)(outputStream, "16 dict begin\n", 14);
 
763
  (*outputFunc)(outputStream, "/FontName /", 11);
 
764
  (*outputFunc)(outputStream, psName, strlen(psName));
 
765
  (*outputFunc)(outputStream, " def\n", 5);
 
766
  (*outputFunc)(outputStream, "/FontType 0 def\n", 16);
 
767
  (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
 
768
  (*outputFunc)(outputStream, "/FMapType 2 def\n", 16);
 
769
  (*outputFunc)(outputStream, "/Encoding [\n", 12);
 
770
  for (i = 0; i < n; i += 256) {
 
771
    buf = GooString::format("{0:d}\n", i >> 8);
 
772
    (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
773
    delete buf;
 
774
  }
 
775
  (*outputFunc)(outputStream, "] def\n", 6);
 
776
  (*outputFunc)(outputStream, "/FDepVector [\n", 14);
 
777
  for (i = 0; i < n; i += 256) {
 
778
    (*outputFunc)(outputStream, "/", 1);
 
779
    (*outputFunc)(outputStream, psName, strlen(psName));
 
780
    buf = GooString::format("_{0:02x} findfont\n", i >> 8);
 
781
    (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
782
    delete buf;
 
783
  }
 
784
  (*outputFunc)(outputStream, "] def\n", 6);
 
785
  (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
 
786
}
 
787
 
 
788
void FoFiTrueType::convertToType0(char *psName,
 
789
                                  FoFiOutputFunc outputFunc,
 
790
                                  void *outputStream) {
 
791
  FoFiType1C *ff;
 
792
  int i;
 
793
 
 
794
  if (!openTypeCFF) {
 
795
    return;
 
796
  }
 
797
  i = seekTable("CFF ");
 
798
  if (!checkRegion(tables[i].offset, tables[i].len)) {
 
799
    return;
 
800
  }
 
801
  if (!(ff = FoFiType1C::make((char *)file + tables[i].offset,
 
802
                              tables[i].len))) {
 
803
    return;
 
804
  }
 
805
  ff->convertToType0(psName, outputFunc, outputStream);
 
806
  delete ff;
 
807
}
 
808
 
 
809
void FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc,
 
810
                            void *outputStream, char *name,
 
811
                            Gushort *codeToGID) {
 
812
  // this substitute cmap table maps char codes 0000-ffff directly to
 
813
  // glyphs 0000-ffff
 
814
  static char cmapTab[36] = {
 
815
    0, 0,                       // table version number
 
816
    0, 1,                       // number of encoding tables
 
817
    0, 1,                       // platform ID
 
818
    0, 0,                       // encoding ID
 
819
    0, 0, 0, 12,                // offset of subtable
 
820
    0, 4,                       // subtable format
 
821
    0, 24,                      // subtable length
 
822
    0, 0,                       // subtable version
 
823
    0, 2,                       // segment count * 2
 
824
    0, 2,                       // 2 * 2 ^ floor(log2(segCount))
 
825
    0, 0,                       // floor(log2(segCount))
 
826
    0, 0,                       // 2*segCount - 2*2^floor(log2(segCount))
 
827
    (char)0xff, (char)0xff,     // endCount[0]
 
828
    0, 0,                       // reserved
 
829
    0, 0,                       // startCount[0]
 
830
    0, 0,                       // idDelta[0]
 
831
    0, 0                        // pad to a mulitple of four bytes
 
832
  };
 
833
  static char nameTab[8] = {
 
834
    0, 0,                       // format
 
835
    0, 0,                       // number of name records
 
836
    0, 6,                       // offset to start of string storage
 
837
    0, 0                        // pad to multiple of four bytes
 
838
  };
 
839
  static char postTab[32] = {
 
840
    0, 1, 0, 0,                 // format
 
841
    0, 0, 0, 0,                 // italic angle
 
842
    0, 0,                       // underline position
 
843
    0, 0,                       // underline thickness
 
844
    0, 0, 0, 0,                 // fixed pitch
 
845
    0, 0, 0, 0,                 // min Type 42 memory
 
846
    0, 0, 0, 0,                 // max Type 42 memory
 
847
    0, 0, 0, 0,                 // min Type 1 memory
 
848
    0, 0, 0, 0                  // max Type 1 memory
 
849
  };
 
850
  static char os2Tab[86] = {
 
851
    0, 1,                       // version
 
852
    0, 1,                       // xAvgCharWidth
 
853
    0, 0,                       // usWeightClass
 
854
    0, 0,                       // usWidthClass
 
855
    0, 0,                       // fsType
 
856
    0, 0,                       // ySubscriptXSize
 
857
    0, 0,                       // ySubscriptYSize
 
858
    0, 0,                       // ySubscriptXOffset
 
859
    0, 0,                       // ySubscriptYOffset
 
860
    0, 0,                       // ySuperscriptXSize
 
861
    0, 0,                       // ySuperscriptYSize
 
862
    0, 0,                       // ySuperscriptXOffset
 
863
    0, 0,                       // ySuperscriptYOffset
 
864
    0, 0,                       // yStrikeoutSize
 
865
    0, 0,                       // yStrikeoutPosition
 
866
    0, 0,                       // sFamilyClass
 
867
    0, 0, 0, 0, 0,              // panose
 
868
    0, 0, 0, 0, 0,
 
869
    0, 0, 0, 0,                 // ulUnicodeRange1
 
870
    0, 0, 0, 0,                 // ulUnicodeRange2
 
871
    0, 0, 0, 0,                 // ulUnicodeRange3
 
872
    0, 0, 0, 0,                 // ulUnicodeRange4
 
873
    0, 0, 0, 0,                 // achVendID
 
874
    0, 0,                       // fsSelection
 
875
    0, 0,                       // usFirstCharIndex
 
876
    0, 0,                       // usLastCharIndex
 
877
    0, 0,                       // sTypoAscender
 
878
    0, 0,                       // sTypoDescender
 
879
    0, 0,                       // sTypoLineGap
 
880
    0, 0,                       // usWinAscent
 
881
    0, 0,                       // usWinDescent
 
882
    0, 0, 0, 0,                 // ulCodePageRange1
 
883
    0, 0, 0, 0                  // ulCodePageRange2
 
884
  };
 
885
  GBool missingCmap, missingName, missingPost, missingOS2;
 
886
  GBool unsortedLoca, badCmapLen, abbrevHMTX;
 
887
  int nZeroLengthTables;
 
888
  int nHMetrics, advWidth, lsb;
 
889
  TrueTypeLoca *locaTable;
 
890
  TrueTypeTable *newTables;
 
891
  char *newNameTab, *newCmapTab, *newHHEATab, *newHMTXTab;
 
892
  int nNewTables, cmapIdx, cmapLen, glyfLen, newNameLen, newCmapLen, next;
 
893
  int newHHEALen, newHMTXLen;
 
894
  Guint locaChecksum, glyfChecksum, fileChecksum;
 
895
  char *tableDir;
 
896
  char locaBuf[4], checksumBuf[4];
 
897
  GBool ok;
 
898
  Guint t;
 
899
  int pos, i, j, k, n;
 
900
 
 
901
  if (openTypeCFF) {
 
902
    return;
 
903
  }
 
904
 
 
905
  if (tables == NULL) {
 
906
    return;
 
907
  }
 
908
 
 
909
  // check for missing tables
 
910
  // (Note: if the OS/2 table is missing, the Microsoft PCL5 driver
 
911
  // will embed a PCL TrueType font with the pitch field set to zero,
 
912
  // which apparently causes divide-by-zero errors.  As far as I can
 
913
  // tell, the only important field in the OS/2 table is
 
914
  // xAvgCharWidth.)
 
915
  missingCmap = (cmapIdx = seekTable("cmap")) < 0;
 
916
  missingName = seekTable("name") < 0;
 
917
  missingPost = seekTable("post") < 0;
 
918
  missingOS2 = seekTable("OS/2") < 0;
 
919
 
 
920
  // read the loca table, check to see if it's sorted
 
921
  locaTable = (TrueTypeLoca *)gmallocn(nGlyphs + 1, sizeof(TrueTypeLoca));
 
922
  unsortedLoca = gFalse;
 
923
  i = seekTable("loca");
 
924
  pos = tables[i].offset;
 
925
  ok = gTrue;
 
926
  for (i = 0; i <= nGlyphs; ++i) {
 
927
    if (locaFmt) {
 
928
      locaTable[i].origOffset = (int)getU32BE(pos + i*4, &ok);
 
929
    } else {
 
930
      locaTable[i].origOffset = 2 * getU16BE(pos + i*2, &ok);
 
931
    }
 
932
    if (i > 0 && locaTable[i].origOffset < locaTable[i-1].origOffset) {
 
933
      unsortedLoca = gTrue;
 
934
    }
 
935
    // glyph descriptions must be at least 12 bytes long (nContours,
 
936
    // xMin, yMin, xMax, yMax, instructionLength - two bytes each);
 
937
    // invalid glyph descriptions (even if they're never used) make
 
938
    // Windows choke, so we work around that problem here (ideally,
 
939
    // this would parse the glyph descriptions in the glyf table and
 
940
    // remove any that were invalid, but this quick test is a decent
 
941
    // start)
 
942
    if (i > 0 &&
 
943
        locaTable[i].origOffset - locaTable[i-1].origOffset > 0 &&
 
944
        locaTable[i].origOffset - locaTable[i-1].origOffset < 12) {
 
945
      locaTable[i-1].origOffset = locaTable[i].origOffset;
 
946
      unsortedLoca = gTrue;
 
947
    }
 
948
    locaTable[i].idx = i;
 
949
  }
 
950
 
 
951
  // check for zero-length tables
 
952
  nZeroLengthTables = 0;
 
953
  for (i = 0; i < nTables; ++i) {
 
954
    if (tables[i].len == 0) {
 
955
      ++nZeroLengthTables;
 
956
    }
 
957
  }
 
958
 
 
959
  // check for an incorrect cmap table length
 
960
  badCmapLen = gFalse;
 
961
  cmapLen = 0; // make gcc happy
 
962
  if (!missingCmap) {
 
963
    if (nCmaps > 0) {
 
964
      cmapLen = cmaps[0].offset + cmaps[0].len;
 
965
      for (i = 1; i < nCmaps; ++i) {
 
966
        if (cmaps[i].offset + cmaps[i].len > cmapLen) {
 
967
          cmapLen = cmaps[i].offset + cmaps[i].len;
 
968
        }
 
969
      }
 
970
    }
 
971
    cmapLen -= tables[cmapIdx].offset;
 
972
    if (cmapLen > tables[cmapIdx].len) {
 
973
      badCmapLen = gTrue;
 
974
    }
 
975
  }
 
976
 
 
977
  // check for an abbreviated hmtx table (this is completely legal,
 
978
  // but confuses the Microsoft PCL5 printer driver, which generates
 
979
  // embedded fonts with the pitch field set to zero)
 
980
  i = seekTable("hhea");
 
981
  nHMetrics = getU16BE(tables[i].offset + 34, &ok);
 
982
  abbrevHMTX = nHMetrics < nGlyphs;
 
983
 
 
984
  // if nothing is broken, just write the TTF file as is
 
985
  if (!missingCmap && !missingName && !missingPost && !missingOS2 &&
 
986
      !unsortedLoca && !badCmapLen && !abbrevHMTX && nZeroLengthTables == 0 &&
 
987
      !name && !codeToGID) {
 
988
    (*outputFunc)(outputStream, (char *)file, len);
 
989
    goto done1;
 
990
  }
 
991
 
 
992
  // sort the 'loca' table: some (non-compliant) fonts have
 
993
  // out-of-order loca tables; in order to correctly handle the case
 
994
  // where (compliant) fonts have empty entries in the middle of the
 
995
  // table, cmpTrueTypeLocaOffset uses offset as its primary sort key,
 
996
  // and idx as its secondary key (ensuring that adjacent entries with
 
997
  // the same pos value remain in the same order)
 
998
  glyfLen = 0; // make gcc happy
 
999
  if (unsortedLoca) {
 
1000
    qsort(locaTable, nGlyphs + 1, sizeof(TrueTypeLoca),
 
1001
          &cmpTrueTypeLocaOffset);
 
1002
    for (i = 0; i < nGlyphs; ++i) {
 
1003
      locaTable[i].len = locaTable[i+1].origOffset - locaTable[i].origOffset;
 
1004
    }
 
1005
    locaTable[nGlyphs].len = 0;
 
1006
    qsort(locaTable, nGlyphs + 1, sizeof(TrueTypeLoca),
 
1007
          &cmpTrueTypeLocaIdx);
 
1008
    pos = 0;
 
1009
    for (i = 0; i <= nGlyphs; ++i) {
 
1010
      locaTable[i].newOffset = pos;
 
1011
      pos += locaTable[i].len;
 
1012
      if (pos & 3) {
 
1013
        pos += 4 - (pos & 3);
 
1014
      }
 
1015
    }
 
1016
    glyfLen = pos;
 
1017
  }
 
1018
 
 
1019
  // compute checksums for the loca and glyf tables
 
1020
  locaChecksum = glyfChecksum = 0;
 
1021
  if (unsortedLoca) {
 
1022
    if (locaFmt) {
 
1023
      for (j = 0; j <= nGlyphs; ++j) {
 
1024
        locaChecksum += locaTable[j].newOffset;
 
1025
      }
 
1026
    } else {
 
1027
      for (j = 0; j <= nGlyphs; j += 2) {
 
1028
        locaChecksum += locaTable[j].newOffset << 16;
 
1029
        if (j + 1 <= nGlyphs) {
 
1030
          locaChecksum += locaTable[j+1].newOffset;
 
1031
        }
 
1032
      }
 
1033
    }
 
1034
    pos = tables[seekTable("glyf")].offset;
 
1035
    for (j = 0; j < nGlyphs; ++j) {
 
1036
      n = locaTable[j].len;
 
1037
      if (n > 0) {
 
1038
        k = locaTable[j].origOffset;
 
1039
        if (checkRegion(pos + k, n)) {
 
1040
          glyfChecksum += computeTableChecksum(file + pos + k, n);
 
1041
        }
 
1042
      }
 
1043
    }
 
1044
  }
 
1045
 
 
1046
  // construct the new name table
 
1047
  if (name) {
 
1048
    n = strlen(name);
 
1049
    newNameLen = (6 + 4*12 + 2 * (3*n + 7) + 3) & ~3;
 
1050
    newNameTab = (char *)gmalloc(newNameLen);
 
1051
    memset(newNameTab, 0, newNameLen);
 
1052
    newNameTab[0] = 0;          // format selector
 
1053
    newNameTab[1] = 0;
 
1054
    newNameTab[2] = 0;          // number of name records
 
1055
    newNameTab[3] = 4;
 
1056
    newNameTab[4] = 0;          // offset to start of string storage
 
1057
    newNameTab[5] = 6 + 4*12;
 
1058
    next = 0;
 
1059
    for (i = 0; i < 4; ++i) {
 
1060
      newNameTab[6 + i*12 + 0] = 0;     // platform ID = Microsoft
 
1061
      newNameTab[6 + i*12 + 1] = 3;
 
1062
      newNameTab[6 + i*12 + 2] = 0;     // encoding ID = Unicode
 
1063
      newNameTab[6 + i*12 + 3] = 1;
 
1064
      newNameTab[6 + i*12 + 4] = 0x04;  // language ID = American English
 
1065
      newNameTab[6 + i*12 + 5] = 0x09;
 
1066
      newNameTab[6 + i*12 + 6] = 0;     // name ID
 
1067
      newNameTab[6 + i*12 + 7] = i + 1;
 
1068
      newNameTab[6 + i*12 + 8] = i+1 == 2 ? 0 : ((2*n) >> 8); // string length
 
1069
      newNameTab[6 + i*12 + 9] = i+1 == 2 ? 14 : ((2*n) & 0xff);
 
1070
      newNameTab[6 + i*12 + 10] = next >> 8;                // string offset
 
1071
      newNameTab[6 + i*12 + 11] = next & 0xff;
 
1072
      if (i+1 == 2) {
 
1073
        memcpy(newNameTab + 6 + 4*12 + next, "\0R\0e\0g\0u\0l\0a\0r", 14);
 
1074
        next += 14;
 
1075
      } else {
 
1076
        for (j = 0; j < n; ++j) {
 
1077
          newNameTab[6 + 4*12 + next + 2*j] = 0;
 
1078
          newNameTab[6 + 4*12 + next + 2*j + 1] = name[j];
 
1079
        }
 
1080
        next += 2*n;
 
1081
      }
 
1082
    }
 
1083
  } else {
 
1084
    newNameLen = 0;
 
1085
    newNameTab = NULL;
 
1086
  }
 
1087
 
 
1088
  // construct the new cmap table
 
1089
  if (codeToGID) {
 
1090
    newCmapLen = 44 + 256 * 2;
 
1091
    newCmapTab = (char *)gmalloc(newCmapLen);
 
1092
    newCmapTab[0] = 0;          // table version number = 0
 
1093
    newCmapTab[1] = 0;
 
1094
    newCmapTab[2] = 0;          // number of encoding tables = 1
 
1095
    newCmapTab[3] = 1;
 
1096
    newCmapTab[4] = 0;          // platform ID = Microsoft
 
1097
    newCmapTab[5] = 3;
 
1098
    newCmapTab[6] = 0;          // encoding ID = Unicode
 
1099
    newCmapTab[7] = 1;
 
1100
    newCmapTab[8] = 0;          // offset of subtable
 
1101
    newCmapTab[9] = 0;
 
1102
    newCmapTab[10] = 0;
 
1103
    newCmapTab[11] = 12;
 
1104
    newCmapTab[12] = 0;         // subtable format = 4
 
1105
    newCmapTab[13] = 4;
 
1106
    newCmapTab[14] = 0x02;      // subtable length
 
1107
    newCmapTab[15] = 0x20;
 
1108
    newCmapTab[16] = 0;         // subtable version = 0
 
1109
    newCmapTab[17] = 0;
 
1110
    newCmapTab[18] = 0;         // segment count * 2
 
1111
    newCmapTab[19] = 4;
 
1112
    newCmapTab[20] = 0;         // 2 * 2 ^ floor(log2(segCount))
 
1113
    newCmapTab[21] = 4;
 
1114
    newCmapTab[22] = 0;         // floor(log2(segCount))
 
1115
    newCmapTab[23] = 1;
 
1116
    newCmapTab[24] = 0;         // 2*segCount - 2*2^floor(log2(segCount))
 
1117
    newCmapTab[25] = 0;
 
1118
    newCmapTab[26] = 0x00;      // endCount[0]
 
1119
    newCmapTab[27] = (char)0xff;
 
1120
    newCmapTab[28] = (char)0xff; // endCount[1]
 
1121
    newCmapTab[29] = (char)0xff;
 
1122
    newCmapTab[30] = 0;         // reserved
 
1123
    newCmapTab[31] = 0;
 
1124
    newCmapTab[32] = 0x00;      // startCount[0]
 
1125
    newCmapTab[33] = 0x00;
 
1126
    newCmapTab[34] = (char)0xff; // startCount[1]
 
1127
    newCmapTab[35] = (char)0xff;
 
1128
    newCmapTab[36] = 0;         // idDelta[0]
 
1129
    newCmapTab[37] = 0;
 
1130
    newCmapTab[38] = 0;         // idDelta[1]
 
1131
    newCmapTab[39] = 1;
 
1132
    newCmapTab[40] = 0;         // idRangeOffset[0]
 
1133
    newCmapTab[41] = 4;
 
1134
    newCmapTab[42] = 0;         // idRangeOffset[1]
 
1135
    newCmapTab[43] = 0;
 
1136
    for (i = 0; i < 256; ++i) {
 
1137
      newCmapTab[44 + 2*i] = codeToGID[i] >> 8;
 
1138
      newCmapTab[44 + 2*i + 1] = codeToGID[i] & 0xff;
 
1139
    }
 
1140
  } else {
 
1141
    newCmapLen = 0;
 
1142
    newCmapTab = NULL;
 
1143
  }
 
1144
 
 
1145
  // generate the new hmtx table and the updated hhea table
 
1146
  if (abbrevHMTX) {
 
1147
    i = seekTable("hhea");
 
1148
    pos = tables[i].offset;
 
1149
    newHHEALen = 36;
 
1150
    newHHEATab = (char *)gmalloc(newHHEALen);
 
1151
    for (i = 0; i < newHHEALen; ++i) {
 
1152
      newHHEATab[i] = getU8(pos++, &ok);
 
1153
    }
 
1154
    newHHEATab[34] = nGlyphs >> 8;
 
1155
    newHHEATab[35] = nGlyphs & 0xff;
 
1156
    i = seekTable("hmtx");
 
1157
    pos = tables[i].offset;
 
1158
    newHMTXLen = 4 * nGlyphs;
 
1159
    newHMTXTab = (char *)gmalloc(newHMTXLen);
 
1160
    advWidth = 0;
 
1161
    for (i = 0; i < nHMetrics; ++i) {
 
1162
      advWidth = getU16BE(pos, &ok);
 
1163
      lsb = getU16BE(pos + 2, &ok);
 
1164
      pos += 4;
 
1165
      newHMTXTab[4*i    ] = advWidth >> 8;
 
1166
      newHMTXTab[4*i + 1] = advWidth & 0xff;
 
1167
      newHMTXTab[4*i + 2] = lsb >> 8;
 
1168
      newHMTXTab[4*i + 3] = lsb & 0xff;
 
1169
    }
 
1170
    for (; i < nGlyphs; ++i) {
 
1171
      lsb = getU16BE(pos, &ok);
 
1172
      pos += 2;
 
1173
      newHMTXTab[4*i    ] = advWidth >> 8;
 
1174
      newHMTXTab[4*i + 1] = advWidth & 0xff;
 
1175
      newHMTXTab[4*i + 2] = lsb >> 8;
 
1176
      newHMTXTab[4*i + 3] = lsb & 0xff;
 
1177
    }
 
1178
  } else {
 
1179
    newHHEATab = newHMTXTab = NULL;
 
1180
    newHHEALen = newHMTXLen = 0; // make gcc happy
 
1181
  }
 
1182
 
 
1183
  // construct the new table directory:
 
1184
  // - keep all original tables with non-zero length
 
1185
  // - fix the cmap table's length, if necessary
 
1186
  // - add missing tables
 
1187
  // - sort the table by tag
 
1188
  // - compute new table positions, including 4-byte alignment
 
1189
  // - (re)compute table checksums
 
1190
  nNewTables = nTables - nZeroLengthTables +
 
1191
               (missingCmap ? 1 : 0) + (missingName ? 1 : 0) +
 
1192
               (missingPost ? 1 : 0) + (missingOS2 ? 1 : 0);
 
1193
  newTables = (TrueTypeTable *)gmallocn(nNewTables, sizeof(TrueTypeTable));
 
1194
  j = 0;
 
1195
  for (i = 0; i < nTables; ++i) {
 
1196
    if (tables[i].len > 0) {
 
1197
      newTables[j] = tables[i];
 
1198
      newTables[j].origOffset = tables[i].offset;
 
1199
      if (checkRegion(tables[i].offset, newTables[i].len)) {
 
1200
        newTables[j].checksum =
 
1201
            computeTableChecksum(file + tables[i].offset, tables[i].len);
 
1202
        if (tables[i].tag == headTag) {
 
1203
          // don't include the file checksum
 
1204
          newTables[j].checksum -= getU32BE(tables[i].offset + 8, &ok);
 
1205
        }
 
1206
      }
 
1207
      if (newTables[j].tag == cmapTag && codeToGID) {
 
1208
        newTables[j].len = newCmapLen;
 
1209
        newTables[j].checksum = computeTableChecksum((Guchar *)newCmapTab,
 
1210
                                                     newCmapLen);
 
1211
      } else if (newTables[j].tag == cmapTag && badCmapLen) {
 
1212
        newTables[j].len = cmapLen;
 
1213
      } else if (newTables[j].tag == locaTag && unsortedLoca) {
 
1214
        newTables[j].len = (nGlyphs + 1) * (locaFmt ? 4 : 2);
 
1215
        newTables[j].checksum = locaChecksum;
 
1216
      } else if (newTables[j].tag == glyfTag && unsortedLoca) {
 
1217
        newTables[j].len = glyfLen;
 
1218
        newTables[j].checksum = glyfChecksum;
 
1219
      } else if (newTables[j].tag == nameTag && name) {
 
1220
        newTables[j].len = newNameLen;
 
1221
        newTables[j].checksum = computeTableChecksum((Guchar *)newNameTab,
 
1222
                                                     newNameLen);
 
1223
      } else if (newTables[j].tag == hheaTag && abbrevHMTX) {
 
1224
        newTables[j].len = newHHEALen;
 
1225
        newTables[j].checksum = computeTableChecksum((Guchar *)newHHEATab,
 
1226
                                                     newHHEALen);
 
1227
      } else if (newTables[j].tag == hmtxTag && abbrevHMTX) {
 
1228
        newTables[j].len = newHMTXLen;
 
1229
        newTables[j].checksum = computeTableChecksum((Guchar *)newHMTXTab,
 
1230
                                                     newHMTXLen);
 
1231
      }
 
1232
      ++j;
 
1233
    }
 
1234
  }
 
1235
  if (missingCmap) {
 
1236
    newTables[j].tag = cmapTag;
 
1237
    if (codeToGID) {
 
1238
      newTables[j].checksum = computeTableChecksum((Guchar *)newCmapTab,
 
1239
                                                   newCmapLen);
 
1240
      newTables[j].len = newCmapLen;
 
1241
    } else {
 
1242
      newTables[j].checksum = computeTableChecksum((Guchar *)cmapTab,
 
1243
                                                   sizeof(cmapTab));
 
1244
      newTables[j].len = sizeof(cmapTab);
 
1245
    }
 
1246
    ++j;
 
1247
  }
 
1248
  if (missingName) {
 
1249
    newTables[j].tag = nameTag;
 
1250
    if (name) {
 
1251
      newTables[j].checksum = computeTableChecksum((Guchar *)newNameTab,
 
1252
                                                   newNameLen);
 
1253
      newTables[j].len = newNameLen;
 
1254
    } else {
 
1255
      newTables[j].checksum = computeTableChecksum((Guchar *)nameTab,
 
1256
                                                   sizeof(nameTab));
 
1257
      newTables[j].len = sizeof(nameTab);
 
1258
    }
 
1259
    ++j;
 
1260
  }
 
1261
  if (missingPost) {
 
1262
    newTables[j].tag = postTag;
 
1263
    newTables[j].checksum = computeTableChecksum((Guchar *)postTab,
 
1264
                                                 sizeof(postTab));
 
1265
    newTables[j].len = sizeof(postTab);
 
1266
    ++j;
 
1267
  }
 
1268
  if (missingOS2) {
 
1269
    newTables[j].tag = os2Tag;
 
1270
    newTables[j].checksum = computeTableChecksum((Guchar *)os2Tab,
 
1271
                                                 sizeof(os2Tab));
 
1272
    newTables[j].len = sizeof(os2Tab);
 
1273
    ++j;
 
1274
  }
 
1275
  qsort(newTables, nNewTables, sizeof(TrueTypeTable),
 
1276
        &cmpTrueTypeTableTag);
 
1277
  pos = 12 + nNewTables * 16;
 
1278
  for (i = 0; i < nNewTables; ++i) {
 
1279
    newTables[i].offset = pos;
 
1280
    pos += newTables[i].len;
 
1281
    if (pos & 3) {
 
1282
      pos += 4 - (pos & 3);
 
1283
    }
 
1284
  }
 
1285
 
 
1286
  // write the table directory
 
1287
  tableDir = (char *)gmalloc(12 + nNewTables * 16);
 
1288
  tableDir[0] = 0x00;                                   // sfnt version
 
1289
  tableDir[1] = 0x01;
 
1290
  tableDir[2] = 0x00;
 
1291
  tableDir[3] = 0x00;
 
1292
  tableDir[4] = (char)((nNewTables >> 8) & 0xff);       // numTables
 
1293
  tableDir[5] = (char)(nNewTables & 0xff);
 
1294
  for (i = -1, t = (Guint)nNewTables; t; ++i, t >>= 1) ;
 
1295
  t = 1 << (4 + i);
 
1296
  tableDir[6] = (char)((t >> 8) & 0xff);                // searchRange
 
1297
  tableDir[7] = (char)(t & 0xff);
 
1298
  tableDir[8] = (char)((i >> 8) & 0xff);                // entrySelector
 
1299
  tableDir[9] = (char)(i & 0xff);
 
1300
  t = nNewTables * 16 - t;
 
1301
  tableDir[10] = (char)((t >> 8) & 0xff);               // rangeShift
 
1302
  tableDir[11] = (char)(t & 0xff);
 
1303
  pos = 12;
 
1304
  for (i = 0; i < nNewTables; ++i) {
 
1305
    tableDir[pos   ] = (char)(newTables[i].tag >> 24);
 
1306
    tableDir[pos+ 1] = (char)(newTables[i].tag >> 16);
 
1307
    tableDir[pos+ 2] = (char)(newTables[i].tag >>  8);
 
1308
    tableDir[pos+ 3] = (char) newTables[i].tag;
 
1309
    tableDir[pos+ 4] = (char)(newTables[i].checksum >> 24);
 
1310
    tableDir[pos+ 5] = (char)(newTables[i].checksum >> 16);
 
1311
    tableDir[pos+ 6] = (char)(newTables[i].checksum >>  8);
 
1312
    tableDir[pos+ 7] = (char) newTables[i].checksum;
 
1313
    tableDir[pos+ 8] = (char)(newTables[i].offset >> 24);
 
1314
    tableDir[pos+ 9] = (char)(newTables[i].offset >> 16);
 
1315
    tableDir[pos+10] = (char)(newTables[i].offset >>  8);
 
1316
    tableDir[pos+11] = (char) newTables[i].offset;
 
1317
    tableDir[pos+12] = (char)(newTables[i].len >> 24);
 
1318
    tableDir[pos+13] = (char)(newTables[i].len >> 16);
 
1319
    tableDir[pos+14] = (char)(newTables[i].len >>  8);
 
1320
    tableDir[pos+15] = (char) newTables[i].len;
 
1321
    pos += 16;
 
1322
  }
 
1323
  (*outputFunc)(outputStream, tableDir, 12 + nNewTables * 16);
 
1324
 
 
1325
  // compute the file checksum
 
1326
  fileChecksum = computeTableChecksum((Guchar *)tableDir,
 
1327
                                      12 + nNewTables * 16);
 
1328
  for (i = 0; i < nNewTables; ++i) {
 
1329
    fileChecksum += newTables[i].checksum;
 
1330
  }
 
1331
  fileChecksum = 0xb1b0afba - fileChecksum;
 
1332
 
 
1333
  // write the tables
 
1334
  for (i = 0; i < nNewTables; ++i) {
 
1335
    if (newTables[i].tag == headTag) {
 
1336
      if (checkRegion(newTables[i].origOffset, newTables[i].len)) {
 
1337
        (*outputFunc)(outputStream, (char *)file + newTables[i].origOffset, 8);
 
1338
        checksumBuf[0] = fileChecksum >> 24;
 
1339
        checksumBuf[1] = fileChecksum >> 16;
 
1340
        checksumBuf[2] = fileChecksum >> 8;
 
1341
        checksumBuf[3] = fileChecksum;
 
1342
        (*outputFunc)(outputStream, checksumBuf, 4);
 
1343
        (*outputFunc)(outputStream,
 
1344
                      (char *)file + newTables[i].origOffset + 12,
 
1345
                      newTables[i].len - 12);
 
1346
      } else {
 
1347
        for (j = 0; j < newTables[i].len; ++j) {
 
1348
          (*outputFunc)(outputStream, "\0", 1);
 
1349
        }
 
1350
      }
 
1351
    } else if (newTables[i].tag == cmapTag && codeToGID) {
 
1352
      (*outputFunc)(outputStream, newCmapTab, newTables[i].len);
 
1353
    } else if (newTables[i].tag == cmapTag && missingCmap) {
 
1354
      (*outputFunc)(outputStream, cmapTab, newTables[i].len);
 
1355
    } else if (newTables[i].tag == nameTag && name) {
 
1356
      (*outputFunc)(outputStream, newNameTab, newTables[i].len);
 
1357
    } else if (newTables[i].tag == nameTag && missingName) {
 
1358
      (*outputFunc)(outputStream, nameTab, newTables[i].len);
 
1359
    } else if (newTables[i].tag == postTag && missingPost) {
 
1360
      (*outputFunc)(outputStream, postTab, newTables[i].len);
 
1361
    } else if (newTables[i].tag == os2Tag && missingOS2) {
 
1362
      (*outputFunc)(outputStream, os2Tab, newTables[i].len);
 
1363
    } else if (newTables[i].tag == hheaTag && abbrevHMTX) {
 
1364
      (*outputFunc)(outputStream, newHHEATab, newTables[i].len);
 
1365
    } else if (newTables[i].tag == hmtxTag && abbrevHMTX) {
 
1366
      (*outputFunc)(outputStream, newHMTXTab, newTables[i].len);
 
1367
    } else if (newTables[i].tag == locaTag && unsortedLoca) {
 
1368
      for (j = 0; j <= nGlyphs; ++j) {
 
1369
        if (locaFmt) {
 
1370
          locaBuf[0] = (char)(locaTable[j].newOffset >> 24);
 
1371
          locaBuf[1] = (char)(locaTable[j].newOffset >> 16);
 
1372
          locaBuf[2] = (char)(locaTable[j].newOffset >>  8);
 
1373
          locaBuf[3] = (char) locaTable[j].newOffset;
 
1374
          (*outputFunc)(outputStream, locaBuf, 4);
 
1375
        } else {
 
1376
          locaBuf[0] = (char)(locaTable[j].newOffset >> 9);
 
1377
          locaBuf[1] = (char)(locaTable[j].newOffset >> 1);
 
1378
          (*outputFunc)(outputStream, locaBuf, 2);
 
1379
        }
 
1380
      }
 
1381
    } else if (newTables[i].tag == glyfTag && unsortedLoca) {
 
1382
      pos = tables[seekTable("glyf")].offset;
 
1383
      for (j = 0; j < nGlyphs; ++j) {
 
1384
        n = locaTable[j].len;
 
1385
        if (n > 0) {
 
1386
          k = locaTable[j].origOffset;
 
1387
          if (checkRegion(pos + k, n)) {
 
1388
            (*outputFunc)(outputStream, (char *)file + pos + k, n);
 
1389
          } else {
 
1390
            for (k = 0; k < n; ++k) {
 
1391
              (*outputFunc)(outputStream, "\0", 1);
 
1392
            }
 
1393
          }
 
1394
          if ((k = locaTable[j].len & 3)) {
 
1395
            (*outputFunc)(outputStream, "\0\0\0\0", 4 - k);
 
1396
          }
 
1397
        }
 
1398
      }
 
1399
    } else {
 
1400
      if (checkRegion(newTables[i].origOffset, newTables[i].len)) {
 
1401
        (*outputFunc)(outputStream, (char *)file + newTables[i].origOffset,
 
1402
                      newTables[i].len);
 
1403
      } else {
 
1404
        for (j = 0; j < newTables[i].len; ++j) {
 
1405
          (*outputFunc)(outputStream, "\0", 1);
 
1406
        }
 
1407
      }
 
1408
    }
 
1409
    if (newTables[i].len & 3) {
 
1410
      (*outputFunc)(outputStream, "\0\0\0", 4 - (newTables[i].len & 3));
 
1411
    }
 
1412
  }
 
1413
 
 
1414
  gfree(newHMTXTab);
 
1415
  gfree(newHHEATab);
 
1416
  gfree(newCmapTab);
 
1417
  gfree(newNameTab);
 
1418
  gfree(tableDir);
 
1419
  gfree(newTables);
 
1420
 done1:
 
1421
  gfree(locaTable);
 
1422
}
 
1423
 
 
1424
void FoFiTrueType::cvtEncoding(char **encoding,
 
1425
                               FoFiOutputFunc outputFunc,
 
1426
                               void *outputStream) {
 
1427
  char *name;
 
1428
  GooString *buf;
 
1429
  int i;
 
1430
 
 
1431
  (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
 
1432
  if (encoding) {
 
1433
    for (i = 0; i < 256; ++i) {
 
1434
      if (!(name = encoding[i])) {
 
1435
        name = ".notdef";
 
1436
      }
 
1437
      buf = GooString::format("dup {0:d} /", i);
 
1438
      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
1439
      delete buf;
 
1440
      (*outputFunc)(outputStream, name, strlen(name));
 
1441
      (*outputFunc)(outputStream, " put\n", 5);
 
1442
    }
 
1443
  } else {
 
1444
    for (i = 0; i < 256; ++i) {
 
1445
      buf = GooString::format("dup {0:d} /c{1:02x} put\n", i, i);
 
1446
      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
1447
      delete buf;
 
1448
    }
 
1449
  }
 
1450
  (*outputFunc)(outputStream, "readonly def\n", 13);
 
1451
}
 
1452
 
 
1453
void FoFiTrueType::cvtCharStrings(char **encoding,
 
1454
                                  Gushort *codeToGID,
 
1455
                                  FoFiOutputFunc outputFunc,
 
1456
                                  void *outputStream) {
 
1457
  char *name;
 
1458
  GooString *buf;
 
1459
  char buf2[16];
 
1460
  int i, k;
 
1461
 
 
1462
  // always define '.notdef'
 
1463
  (*outputFunc)(outputStream, "/CharStrings 256 dict dup begin\n", 32);
 
1464
  (*outputFunc)(outputStream, "/.notdef 0 def\n", 15);
 
1465
 
 
1466
  // if there's no 'cmap' table, punt
 
1467
  if (nCmaps == 0) {
 
1468
    goto err;
 
1469
  }
 
1470
 
 
1471
  // map char name to glyph index:
 
1472
  // 1. use encoding to map name to char code
 
1473
  // 2. use codeToGID to map char code to glyph index
 
1474
  // N.B. We do this in reverse order because font subsets can have
 
1475
  //      weird encodings that use the same character name twice, and
 
1476
  //      the first definition is probably the one we want.
 
1477
  k = 0; // make gcc happy
 
1478
  for (i = 255; i >= 0; --i) {
 
1479
    if (encoding) {
 
1480
      name = encoding[i];
 
1481
    } else {
 
1482
      sprintf(buf2, "c%02x", i);
 
1483
      name = buf2;
 
1484
    }
 
1485
    if (name && strcmp(name, ".notdef")) {
 
1486
      k = codeToGID[i];
 
1487
      // note: Distiller (maybe Adobe's PS interpreter in general)
 
1488
      // doesn't like TrueType fonts that have CharStrings entries
 
1489
      // which point to nonexistent glyphs, hence the (k < nGlyphs)
 
1490
      // test
 
1491
      if (k > 0 && k < nGlyphs) {
 
1492
        (*outputFunc)(outputStream, "/", 1);
 
1493
        (*outputFunc)(outputStream, name, strlen(name));
 
1494
        buf = GooString::format(" {0:d} def\n", k);
 
1495
        (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
1496
        delete buf;
 
1497
      }
 
1498
    }
 
1499
  }
 
1500
 
 
1501
 err:
 
1502
  (*outputFunc)(outputStream, "end readonly def\n", 17);
 
1503
}
 
1504
 
 
1505
void FoFiTrueType::cvtSfnts(FoFiOutputFunc outputFunc,
 
1506
                            void *outputStream, GooString *name,
 
1507
                            GBool needVerticalMetrics) {
 
1508
  Guchar headData[54];
 
1509
  TrueTypeLoca *locaTable;
 
1510
  Guchar *locaData;
 
1511
  TrueTypeTable newTables[nT42Tables];
 
1512
  Guchar tableDir[12 + nT42Tables*16];
 
1513
  GBool ok;
 
1514
  Guint checksum;
 
1515
  int nNewTables;
 
1516
  int length, pos, glyfPos, i, j, k;
 
1517
  Guchar vheaTab[36] = {
 
1518
    0, 1, 0, 0,                 // table version number
 
1519
    0, 0,                       // ascent
 
1520
    0, 0,                       // descent
 
1521
    0, 0,                       // reserved
 
1522
    0, 0,                       // max advance height
 
1523
    0, 0,                       // min top side bearing
 
1524
    0, 0,                       // min bottom side bearing
 
1525
    0, 0,                       // y max extent
 
1526
    0, 0,                       // caret slope rise
 
1527
    0, 1,                       // caret slope run
 
1528
    0, 0,                       // caret offset
 
1529
    0, 0,                       // reserved
 
1530
    0, 0,                       // reserved
 
1531
    0, 0,                       // reserved
 
1532
    0, 0,                       // reserved
 
1533
    0, 0,                       // metric data format
 
1534
    0, 1                        // number of advance heights in vmtx table
 
1535
  };
 
1536
  Guchar *vmtxTab;
 
1537
  GBool needVhea, needVmtx;
 
1538
  int advance;
 
1539
 
 
1540
  // construct the 'head' table, zero out the font checksum
 
1541
  i = seekTable("head");
 
1542
  if (i < 0 || i >= nTables) {
 
1543
    return;
 
1544
  }
 
1545
  pos = tables[i].offset;
 
1546
  if (!checkRegion(pos, 54)) {
 
1547
    return;
 
1548
  }
 
1549
  memcpy(headData, file + pos, 54);
 
1550
  headData[8] = headData[9] = headData[10] = headData[11] = (Guchar)0;
 
1551
 
 
1552
  // read the original 'loca' table, pad entries out to 4 bytes, and
 
1553
  // sort it into proper order -- some (non-compliant) fonts have
 
1554
  // out-of-order loca tables; in order to correctly handle the case
 
1555
  // where (compliant) fonts have empty entries in the middle of the
 
1556
  // table, cmpTrueTypeLocaPos uses offset as its primary sort key,
 
1557
  // and idx as its secondary key (ensuring that adjacent entries with
 
1558
  // the same pos value remain in the same order)
 
1559
  locaTable = (TrueTypeLoca *)gmallocn(nGlyphs + 1, sizeof(TrueTypeLoca));
 
1560
  i = seekTable("loca");
 
1561
  pos = tables[i].offset;
 
1562
  ok = gTrue;
 
1563
  for (i = 0; i <= nGlyphs; ++i) {
 
1564
    locaTable[i].idx = i;
 
1565
    if (locaFmt) {
 
1566
      locaTable[i].origOffset = (int)getU32BE(pos + i*4, &ok);
 
1567
    } else {
 
1568
      locaTable[i].origOffset = 2 * getU16BE(pos + i*2, &ok);
 
1569
    }
 
1570
  }
 
1571
  qsort(locaTable, nGlyphs + 1, sizeof(TrueTypeLoca),
 
1572
        &cmpTrueTypeLocaOffset);
 
1573
  for (i = 0; i < nGlyphs; ++i) {
 
1574
    locaTable[i].len = locaTable[i+1].origOffset - locaTable[i].origOffset;
 
1575
  }
 
1576
  locaTable[nGlyphs].len = 0;
 
1577
  qsort(locaTable, nGlyphs + 1, sizeof(TrueTypeLoca),
 
1578
        &cmpTrueTypeLocaIdx);
 
1579
  pos = 0;
 
1580
  for (i = 0; i <= nGlyphs; ++i) {
 
1581
    locaTable[i].newOffset = pos;
 
1582
    pos += locaTable[i].len;
 
1583
    if (pos & 3) {
 
1584
      pos += 4 - (pos & 3);
 
1585
    }
 
1586
  }
 
1587
 
 
1588
  // construct the new 'loca' table
 
1589
  locaData = (Guchar *)gmallocn(nGlyphs + 1, (locaFmt ? 4 : 2));
 
1590
  for (i = 0; i <= nGlyphs; ++i) {
 
1591
    pos = locaTable[i].newOffset;
 
1592
    if (locaFmt) {
 
1593
      locaData[4*i  ] = (Guchar)(pos >> 24);
 
1594
      locaData[4*i+1] = (Guchar)(pos >> 16);
 
1595
      locaData[4*i+2] = (Guchar)(pos >>  8);
 
1596
      locaData[4*i+3] = (Guchar) pos;
 
1597
    } else {
 
1598
      locaData[2*i  ] = (Guchar)(pos >> 9);
 
1599
      locaData[2*i+1] = (Guchar)(pos >> 1);
 
1600
    }
 
1601
  }
 
1602
 
 
1603
  // count the number of tables
 
1604
  nNewTables = 0;
 
1605
  for (i = 0; i < nT42Tables; ++i) {
 
1606
    if (t42Tables[i].required ||
 
1607
        seekTable(t42Tables[i].tag) >= 0) {
 
1608
      ++nNewTables;
 
1609
    }
 
1610
  }
 
1611
  vmtxTab = NULL; // make gcc happy
 
1612
  advance = 0; // make gcc happy
 
1613
  if (needVerticalMetrics) {
 
1614
    needVhea = seekTable("vhea") < 0;
 
1615
    needVmtx = seekTable("vmtx") < 0;
 
1616
    if (needVhea || needVmtx) {
 
1617
      i = seekTable("head");
 
1618
      advance = getU16BE(tables[i].offset + 18, &ok); // units per em
 
1619
      if (needVhea) {
 
1620
        ++nNewTables;
 
1621
      }
 
1622
      if (needVmtx) {
 
1623
        ++nNewTables;
 
1624
      }
 
1625
    }
 
1626
  }
 
1627
 
 
1628
  // construct the new table headers, including table checksums
 
1629
  // (pad each table out to a multiple of 4 bytes)
 
1630
  pos = 12 + nNewTables*16;
 
1631
  k = 0;
 
1632
  for (i = 0; i < nT42Tables; ++i) {
 
1633
    length = -1;
 
1634
    checksum = 0; // make gcc happy
 
1635
    if (i == t42HeadTable) {
 
1636
      length = 54;
 
1637
      checksum = computeTableChecksum(headData, 54);
 
1638
    } else if (i == t42LocaTable) {
 
1639
      length = (nGlyphs + 1) * (locaFmt ? 4 : 2);
 
1640
      checksum = computeTableChecksum(locaData, length);
 
1641
    } else if (i == t42GlyfTable) {
 
1642
      length = 0;
 
1643
      checksum = 0;
 
1644
      glyfPos = tables[seekTable("glyf")].offset;
 
1645
      for (j = 0; j < nGlyphs; ++j) {
 
1646
        length += locaTable[j].len;
 
1647
        if (length & 3) {
 
1648
          length += 4 - (length & 3);
 
1649
        }
 
1650
        if (checkRegion(glyfPos + locaTable[j].origOffset, locaTable[j].len)) {
 
1651
          checksum +=
 
1652
              computeTableChecksum(file + glyfPos + locaTable[j].origOffset,
 
1653
                                   locaTable[j].len);
 
1654
        }
 
1655
      }
 
1656
    } else {
 
1657
      if ((j = seekTable(t42Tables[i].tag)) >= 0) {
 
1658
        length = tables[j].len;
 
1659
        if (checkRegion(tables[j].offset, length)) {
 
1660
          checksum = computeTableChecksum(file + tables[j].offset, length);
 
1661
        }
 
1662
      } else if (needVerticalMetrics && i == t42VheaTable) {
 
1663
        vheaTab[10] = advance / 256;    // max advance height
 
1664
        vheaTab[11] = advance % 256;
 
1665
        length = sizeof(vheaTab);
 
1666
        checksum = computeTableChecksum(vheaTab, length);
 
1667
      } else if (needVerticalMetrics && i == t42VmtxTable) {
 
1668
        length = 4 + (nGlyphs - 1) * 4;
 
1669
        vmtxTab = (Guchar *)gmalloc(length);
 
1670
        vmtxTab[0] = advance / 256;
 
1671
        vmtxTab[1] = advance % 256;
 
1672
        for (j = 2; j < length; j += 2) {
 
1673
          vmtxTab[j] = 0;
 
1674
          vmtxTab[j+1] = 0;
 
1675
        }
 
1676
        checksum = computeTableChecksum(vmtxTab, length);
 
1677
      } else if (t42Tables[i].required) {
 
1678
        //~ error(-1, "Embedded TrueType font is missing a required table ('%s')",
 
1679
        //~       t42Tables[i].tag);
 
1680
        length = 0;
 
1681
        checksum = 0;
 
1682
      }
 
1683
    }
 
1684
    if (length >= 0) {
 
1685
      newTables[k].tag = ((t42Tables[i].tag[0] & 0xff) << 24) |
 
1686
                         ((t42Tables[i].tag[1] & 0xff) << 16) |
 
1687
                         ((t42Tables[i].tag[2] & 0xff) <<  8) |
 
1688
                          (t42Tables[i].tag[3] & 0xff);
 
1689
      newTables[k].checksum = checksum;
 
1690
      newTables[k].offset = pos;
 
1691
      newTables[k].len = length;
 
1692
      pos += length;
 
1693
      if (pos & 3) {
 
1694
        pos += 4 - (length & 3);
 
1695
      }
 
1696
      ++k;
 
1697
    }
 
1698
  }
 
1699
 
 
1700
  // construct the table directory
 
1701
  tableDir[0] = 0x00;           // sfnt version
 
1702
  tableDir[1] = 0x01;
 
1703
  tableDir[2] = 0x00;
 
1704
  tableDir[3] = 0x00;
 
1705
  tableDir[4] = 0;              // numTables
 
1706
  tableDir[5] = nNewTables;
 
1707
  tableDir[6] = 0;              // searchRange
 
1708
  tableDir[7] = (Guchar)128;
 
1709
  tableDir[8] = 0;              // entrySelector
 
1710
  tableDir[9] = 3;
 
1711
  tableDir[10] = 0;             // rangeShift
 
1712
  tableDir[11] = (Guchar)(16 * nNewTables - 128);
 
1713
  pos = 12;
 
1714
  for (i = 0; i < nNewTables; ++i) {
 
1715
    tableDir[pos   ] = (Guchar)(newTables[i].tag >> 24);
 
1716
    tableDir[pos+ 1] = (Guchar)(newTables[i].tag >> 16);
 
1717
    tableDir[pos+ 2] = (Guchar)(newTables[i].tag >>  8);
 
1718
    tableDir[pos+ 3] = (Guchar) newTables[i].tag;
 
1719
    tableDir[pos+ 4] = (Guchar)(newTables[i].checksum >> 24);
 
1720
    tableDir[pos+ 5] = (Guchar)(newTables[i].checksum >> 16);
 
1721
    tableDir[pos+ 6] = (Guchar)(newTables[i].checksum >>  8);
 
1722
    tableDir[pos+ 7] = (Guchar) newTables[i].checksum;
 
1723
    tableDir[pos+ 8] = (Guchar)(newTables[i].offset >> 24);
 
1724
    tableDir[pos+ 9] = (Guchar)(newTables[i].offset >> 16);
 
1725
    tableDir[pos+10] = (Guchar)(newTables[i].offset >>  8);
 
1726
    tableDir[pos+11] = (Guchar) newTables[i].offset;
 
1727
    tableDir[pos+12] = (Guchar)(newTables[i].len >> 24);
 
1728
    tableDir[pos+13] = (Guchar)(newTables[i].len >> 16);
 
1729
    tableDir[pos+14] = (Guchar)(newTables[i].len >>  8);
 
1730
    tableDir[pos+15] = (Guchar) newTables[i].len;
 
1731
    pos += 16;
 
1732
  }
 
1733
 
 
1734
  // compute the font checksum and store it in the head table
 
1735
  checksum = computeTableChecksum(tableDir, 12 + nNewTables*16);
 
1736
  for (i = 0; i < nNewTables; ++i) {
 
1737
    checksum += newTables[i].checksum;
 
1738
  }
 
1739
  checksum = 0xb1b0afba - checksum; // because the TrueType spec says so
 
1740
  headData[ 8] = (Guchar)(checksum >> 24);
 
1741
  headData[ 9] = (Guchar)(checksum >> 16);
 
1742
  headData[10] = (Guchar)(checksum >>  8);
 
1743
  headData[11] = (Guchar) checksum;
 
1744
 
 
1745
  // start the sfnts array
 
1746
  if (name) {
 
1747
    (*outputFunc)(outputStream, "/", 1);
 
1748
    (*outputFunc)(outputStream, name->getCString(), name->getLength());
 
1749
    (*outputFunc)(outputStream, " [\n", 3);
 
1750
  } else {
 
1751
    (*outputFunc)(outputStream, "/sfnts [\n", 9);
 
1752
  }
 
1753
 
 
1754
  // write the table directory
 
1755
  dumpString(tableDir, 12 + nNewTables*16, outputFunc, outputStream);
 
1756
 
 
1757
  // write the tables
 
1758
  for (i = 0; i < nNewTables; ++i) {
 
1759
    if (i == t42HeadTable) {
 
1760
      dumpString(headData, 54, outputFunc, outputStream);
 
1761
    } else if (i == t42LocaTable) {
 
1762
      length = (nGlyphs + 1) * (locaFmt ? 4 : 2);
 
1763
      dumpString(locaData, length, outputFunc, outputStream);
 
1764
    } else if (i == t42GlyfTable) {
 
1765
      glyfPos = tables[seekTable("glyf")].offset;
 
1766
      for (j = 0; j < nGlyphs; ++j) {
 
1767
        if (locaTable[j].len > 0 &&
 
1768
            checkRegion(glyfPos + locaTable[j].origOffset, locaTable[j].len)) {
 
1769
          dumpString(file + glyfPos + locaTable[j].origOffset,
 
1770
                     locaTable[j].len, outputFunc, outputStream);
 
1771
        }
 
1772
      }
 
1773
    } else {
 
1774
      // length == 0 means the table is missing and the error was
 
1775
      // already reported during the construction of the table
 
1776
      // headers
 
1777
      if ((length = newTables[i].len) > 0) {
 
1778
        if ((j = seekTable(t42Tables[i].tag)) >= 0 &&
 
1779
            checkRegion(tables[j].offset, tables[j].len)) {
 
1780
          dumpString(file + tables[j].offset, tables[j].len,
 
1781
                     outputFunc, outputStream);
 
1782
        } else if (needVerticalMetrics && i == t42VheaTable) {
 
1783
          dumpString(vheaTab, length, outputFunc, outputStream);
 
1784
        } else if (needVerticalMetrics && i == t42VmtxTable) {
 
1785
          dumpString(vmtxTab, length, outputFunc, outputStream);
 
1786
          gfree(vmtxTab);
 
1787
        }
 
1788
      }
 
1789
    }
 
1790
  }
 
1791
 
 
1792
  // end the sfnts array
 
1793
  (*outputFunc)(outputStream, "] def\n", 6);
 
1794
 
 
1795
  gfree(locaData);
 
1796
  gfree(locaTable);
 
1797
}
 
1798
 
 
1799
void FoFiTrueType::dumpString(Guchar *s, int length,
 
1800
                              FoFiOutputFunc outputFunc,
 
1801
                              void *outputStream) {
 
1802
  GooString *buf;
 
1803
  int pad, i, j;
 
1804
 
 
1805
  (*outputFunc)(outputStream, "<", 1);
 
1806
  for (i = 0; i < length; i += 32) {
 
1807
    for (j = 0; j < 32 && i+j < length; ++j) {
 
1808
      buf = GooString::format("{0:02x}", s[i+j] & 0xff);
 
1809
      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
 
1810
      delete buf;
 
1811
    }
 
1812
    if (i % (65536 - 32) == 65536 - 64) {
 
1813
      (*outputFunc)(outputStream, ">\n<", 3);
 
1814
    } else if (i+32 < length) {
 
1815
      (*outputFunc)(outputStream, "\n", 1);
 
1816
    }
 
1817
  }
 
1818
  if (length & 3) {
 
1819
    pad = 4 - (length & 3);
 
1820
    for (i = 0; i < pad; ++i) {
 
1821
      (*outputFunc)(outputStream, "00", 2);
 
1822
    }
 
1823
  }
 
1824
  // add an extra zero byte because the Adobe Type 42 spec says so
 
1825
  (*outputFunc)(outputStream, "00>\n", 4);
 
1826
}
 
1827
 
 
1828
Guint FoFiTrueType::computeTableChecksum(Guchar *data, int length) {
 
1829
  Guint checksum, word;
 
1830
  int i;
 
1831
 
 
1832
  checksum = 0;
 
1833
  for (i = 0; i+3 < length; i += 4) {
 
1834
    word = ((data[i  ] & 0xff) << 24) +
 
1835
           ((data[i+1] & 0xff) << 16) +
 
1836
           ((data[i+2] & 0xff) <<  8) +
 
1837
            (data[i+3] & 0xff);
 
1838
    checksum += word;
 
1839
  }
 
1840
  if (length & 3) {
 
1841
    word = 0;
 
1842
    i = length & ~3;
 
1843
    switch (length & 3) {
 
1844
    case 3:
 
1845
      word |= (data[i+2] & 0xff) <<  8;
 
1846
    case 2:
 
1847
      word |= (data[i+1] & 0xff) << 16;
 
1848
    case 1:
 
1849
      word |= (data[i  ] & 0xff) << 24;
 
1850
      break;
 
1851
    }
 
1852
    checksum += word;
 
1853
  }
 
1854
  return checksum;
 
1855
}
 
1856
 
 
1857
void FoFiTrueType::parse() {
 
1858
  Guint topTag;
 
1859
  int pos, ver, i, j;
 
1860
 
 
1861
  parsedOk = gTrue;
 
1862
 
 
1863
  // look for a collection (TTC)
 
1864
  topTag = getU32BE(0, &parsedOk);
 
1865
  if (!parsedOk) {
 
1866
    return;
 
1867
  }
 
1868
  if (topTag == ttcfTag) {
 
1869
    /* TTC font */
 
1870
    int dircount;
 
1871
 
 
1872
    dircount = getU32BE(8, &parsedOk);
 
1873
    if (!parsedOk)
 
1874
      return;
 
1875
    if (! dircount) {
 
1876
      parsedOk = gFalse;
 
1877
      return;
 
1878
    }
 
1879
 
 
1880
    if (faceIndex >= dircount)
 
1881
      faceIndex = 0;
 
1882
    pos = getU32BE(12 + faceIndex * 4, &parsedOk);
 
1883
    if (! parsedOk)
 
1884
      return;
 
1885
  } else {
 
1886
    pos = 0;
 
1887
  }
 
1888
 
 
1889
  // check the sfnt version
 
1890
  ver = getU32BE(pos, &parsedOk);
 
1891
  if (!parsedOk) {
 
1892
    return;
 
1893
  }
 
1894
  openTypeCFF = ver == 0x4f54544f; // 'OTTO'
 
1895
 
 
1896
  // read the table directory
 
1897
  nTables = getU16BE(pos + 4, &parsedOk);
 
1898
  if (!parsedOk) {
 
1899
    return;
 
1900
  }
 
1901
  tables = (TrueTypeTable *)gmallocn(nTables, sizeof(TrueTypeTable));
 
1902
  pos += 12;
 
1903
  int wrongTables = 0;
 
1904
  for (i = 0; i < nTables; ++i) {
 
1905
    tables[i].tag = getU32BE(pos, &parsedOk);
 
1906
    tables[i].checksum = getU32BE(pos + 4, &parsedOk);
 
1907
    tables[i].offset = (int)getU32BE(pos + 8, &parsedOk);
 
1908
    tables[i].len = (int)getU32BE(pos + 12, &parsedOk);
 
1909
    if (tables[i].offset + tables[i].len < tables[i].offset ||
 
1910
        tables[i].offset + tables[i].len > len) {
 
1911
      i--;
 
1912
      wrongTables++;
 
1913
      error(-1, "Found a bad table definition on true type definition, trying to continue...");
 
1914
    }
 
1915
    pos += 16;
 
1916
  }
 
1917
  nTables -= wrongTables;
 
1918
  tables = (TrueTypeTable *)greallocn_checkoverflow(tables, nTables, sizeof(TrueTypeTable));
 
1919
  if (!parsedOk || tables == NULL) {
 
1920
    return;
 
1921
  }
 
1922
 
 
1923
  // check for tables that are required by both the TrueType spec and
 
1924
  // the Type 42 spec
 
1925
  if (seekTable("head") < 0 ||
 
1926
      seekTable("hhea") < 0 ||
 
1927
      seekTable("maxp") < 0 ||
 
1928
      seekTable("hmtx") < 0 ||
 
1929
      (!openTypeCFF && seekTable("loca") < 0) ||
 
1930
      (!openTypeCFF && seekTable("glyf") < 0) ||
 
1931
      (openTypeCFF && seekTable("CFF ") < 0)) {
 
1932
    parsedOk = gFalse;
 
1933
    return;
 
1934
  }
 
1935
 
 
1936
  // read the cmaps
 
1937
  if ((i = seekTable("cmap")) >= 0) {
 
1938
    pos = tables[i].offset + 2;
 
1939
    nCmaps = getU16BE(pos, &parsedOk);
 
1940
    pos += 2;
 
1941
    if (!parsedOk) {
 
1942
      return;
 
1943
    }
 
1944
    cmaps = (TrueTypeCmap *)gmallocn(nCmaps, sizeof(TrueTypeCmap));
 
1945
    for (j = 0; j < nCmaps; ++j) {
 
1946
      cmaps[j].platform = getU16BE(pos, &parsedOk);
 
1947
      cmaps[j].encoding = getU16BE(pos + 2, &parsedOk);
 
1948
      cmaps[j].offset = tables[i].offset + getU32BE(pos + 4, &parsedOk);
 
1949
      pos += 8;
 
1950
      cmaps[j].fmt = getU16BE(cmaps[j].offset, &parsedOk);
 
1951
      cmaps[j].len = getU16BE(cmaps[j].offset + 2, &parsedOk);
 
1952
    }
 
1953
    if (!parsedOk) {
 
1954
      return;
 
1955
    }
 
1956
  } else {
 
1957
    nCmaps = 0;
 
1958
  }
 
1959
 
 
1960
  // get the number of glyphs from the maxp table
 
1961
  i = seekTable("maxp");
 
1962
  nGlyphs = getU16BE(tables[i].offset + 4, &parsedOk);
 
1963
  if (!parsedOk) {
 
1964
    return;
 
1965
  }
 
1966
 
 
1967
  // get the bbox and loca table format from the head table
 
1968
  i = seekTable("head");
 
1969
  bbox[0] = getS16BE(tables[i].offset + 36, &parsedOk);
 
1970
  bbox[1] = getS16BE(tables[i].offset + 38, &parsedOk);
 
1971
  bbox[2] = getS16BE(tables[i].offset + 40, &parsedOk);
 
1972
  bbox[3] = getS16BE(tables[i].offset + 42, &parsedOk);
 
1973
  locaFmt = getS16BE(tables[i].offset + 50, &parsedOk);
 
1974
  if (!parsedOk) {
 
1975
    return;
 
1976
  }
 
1977
 
 
1978
  // make sure the loca table is sane (correct length and entries are
 
1979
  // in bounds)
 
1980
  if (!openTypeCFF) {
 
1981
    i = seekTable("loca");
 
1982
    if (tables[i].len < 0) {
 
1983
      parsedOk = gFalse;
 
1984
      return;
 
1985
    }
 
1986
    if (tables[i].len < (nGlyphs + 1) * (locaFmt ? 4 : 2)) {
 
1987
      nGlyphs = tables[i].len / (locaFmt ? 4 : 2) - 1;
 
1988
    }
 
1989
    for (j = 0; j <= nGlyphs; ++j) {
 
1990
      if (locaFmt) {
 
1991
        pos = (int)getU32BE(tables[i].offset + j*4, &parsedOk);
 
1992
      } else {
 
1993
        pos = getU16BE(tables[i].offset + j*2, &parsedOk);
 
1994
      }
 
1995
      if (pos < 0 || pos > len) {
 
1996
        parsedOk = gFalse;
 
1997
      }
 
1998
    }
 
1999
    if (!parsedOk) {
 
2000
      return;
 
2001
    }
 
2002
  }
 
2003
 
 
2004
  // read the post table
 
2005
  readPostTable();
 
2006
}
 
2007
 
 
2008
void FoFiTrueType::readPostTable() {
 
2009
  GooString *name;
 
2010
  int tablePos, postFmt, stringIdx, stringPos;
 
2011
  GBool ok;
 
2012
  int i, j, n, m;
 
2013
 
 
2014
  ok = gTrue;
 
2015
  if ((i = seekTable("post")) < 0) {
 
2016
    return;
 
2017
  }
 
2018
  tablePos = tables[i].offset;
 
2019
  postFmt = getU32BE(tablePos, &ok);
 
2020
  if (!ok) {
 
2021
    goto err;
 
2022
  }
 
2023
  if (postFmt == 0x00010000) {
 
2024
    nameToGID = new GooHash(gTrue);
 
2025
    for (i = 0; i < 258; ++i) {
 
2026
      nameToGID->add(new GooString(macGlyphNames[i]), i);
 
2027
    }
 
2028
  } else if (postFmt == 0x00020000) {
 
2029
    nameToGID = new GooHash(gTrue);
 
2030
    n = getU16BE(tablePos + 32, &ok);
 
2031
    if (!ok) {
 
2032
      goto err;
 
2033
    }
 
2034
    if (n > nGlyphs) {
 
2035
      n = nGlyphs;
 
2036
    }
 
2037
    stringIdx = 0;
 
2038
    stringPos = tablePos + 34 + 2*n;
 
2039
    for (i = 0; i < n; ++i) {
 
2040
      j = getU16BE(tablePos + 34 + 2*i, &ok);
 
2041
      if (j < 258) {
 
2042
        nameToGID->removeInt(macGlyphNames[j]);
 
2043
        nameToGID->add(new GooString(macGlyphNames[j]), i);
 
2044
      } else {
 
2045
        j -= 258;
 
2046
        if (j != stringIdx) {
 
2047
          for (stringIdx = 0, stringPos = tablePos + 34 + 2*n;
 
2048
               stringIdx < j;
 
2049
               ++stringIdx, stringPos += 1 + getU8(stringPos, &ok)) ;
 
2050
          if (!ok) {
 
2051
            goto err;
 
2052
          }
 
2053
        }
 
2054
        m = getU8(stringPos, &ok);
 
2055
        if (!ok || !checkRegion(stringPos + 1, m)) {
 
2056
          goto err;
 
2057
        }
 
2058
        name = new GooString((char *)&file[stringPos + 1], m);
 
2059
        nameToGID->removeInt(name);
 
2060
        nameToGID->add(name, i);
 
2061
        ++stringIdx;
 
2062
        stringPos += 1 + m;
 
2063
      }
 
2064
    }
 
2065
  } else if (postFmt == 0x00028000) {
 
2066
    nameToGID = new GooHash(gTrue);
 
2067
    for (i = 0; i < nGlyphs; ++i) {
 
2068
      j = getU8(tablePos + 32 + i, &ok);
 
2069
      if (!ok) {
 
2070
        goto err;
 
2071
      }
 
2072
      if (j < 258) {
 
2073
        nameToGID->removeInt(macGlyphNames[j]);
 
2074
        nameToGID->add(new GooString(macGlyphNames[j]), i);
 
2075
      }
 
2076
    }
 
2077
  }
 
2078
 
 
2079
  return;
 
2080
 
 
2081
 err:
 
2082
  if (nameToGID) {
 
2083
    delete nameToGID;
 
2084
    nameToGID = NULL;
 
2085
  }
 
2086
}
 
2087
 
 
2088
int FoFiTrueType::seekTable(char *tag) {
 
2089
  Guint tagI;
 
2090
  int i;
 
2091
 
 
2092
  tagI = ((tag[0] & 0xff) << 24) |
 
2093
         ((tag[1] & 0xff) << 16) |
 
2094
         ((tag[2] & 0xff) << 8) |
 
2095
          (tag[3] & 0xff);
 
2096
  for (i = 0; i < nTables; ++i) {
 
2097
    if (tables[i].tag == tagI) {
 
2098
      return i;
 
2099
    }
 
2100
  }
 
2101
  return -1;
 
2102
}
 
2103
 
 
2104
Guint FoFiTrueType::charToTag(const char *tagName)
 
2105
{
 
2106
  int n = strlen(tagName);
 
2107
  Guint tag = 0;
 
2108
  int i;
 
2109
 
 
2110
  if (n > 4) n = 4;
 
2111
  for (i = 0;i < n;i++) {
 
2112
    tag <<= 8;
 
2113
    tag |= tagName[i] & 0xff;
 
2114
  }
 
2115
  for (;i < 4;i++) {
 
2116
    tag <<= 8;
 
2117
    tag |= ' ';
 
2118
  }
 
2119
  return tag;
 
2120
}
 
2121
 
 
2122
/*
 
2123
  setup GSUB table data
 
2124
  Only supporting vertical text substitution.
 
2125
*/
 
2126
int FoFiTrueType::setupGSUB(const char *tagName)
 
2127
{
 
2128
  Guint gsubTable;
 
2129
  unsigned int i;
 
2130
  Guint scriptList, featureList;
 
2131
  Guint scriptCount;
 
2132
  Guint tag;
 
2133
  Guint scriptTable = 0;
 
2134
  Guint langSys;
 
2135
  Guint featureCount;
 
2136
  Guint featureIndex;
 
2137
  Guint ftable = 0;
 
2138
  Guint llist;
 
2139
  Guint scriptTag;
 
2140
  int x;
 
2141
  Guint pos;
 
2142
 
 
2143
  if (tagName == 0) {
 
2144
    gsubFeatureTable = 0;
 
2145
    return 0;
 
2146
  }
 
2147
  scriptTag = charToTag(tagName);
 
2148
  /* read GSUB Header */
 
2149
  if ((x = seekTable("GSUB")) < 0) {
 
2150
    return 0; /* GSUB table not found */
 
2151
  }
 
2152
  gsubTable = tables[x].offset;
 
2153
  pos = gsubTable+4;
 
2154
  scriptList = getU16BE(pos,&parsedOk);
 
2155
  pos += 2;
 
2156
  featureList = getU16BE(pos,&parsedOk);
 
2157
  pos += 2;
 
2158
  llist = getU16BE(pos,&parsedOk);
 
2159
 
 
2160
  gsubLookupList = llist+gsubTable; /* change to offset from top of file */
 
2161
  /* read script list table */
 
2162
  pos = gsubTable+scriptList;
 
2163
  scriptCount = getU16BE(pos,&parsedOk);
 
2164
  pos += 2;
 
2165
  /* find  script */
 
2166
  for (i = 0;i < scriptCount;i++) {
 
2167
    tag = getU32BE(pos,&parsedOk);
 
2168
    pos += 4;
 
2169
    scriptTable = getU16BE(pos,&parsedOk);
 
2170
    pos += 2;
 
2171
    if (tag == scriptTag) {
 
2172
      /* found */
 
2173
      break;
 
2174
    }
 
2175
  }
 
2176
  if (i >= scriptCount) {
 
2177
    /* not found */
 
2178
    return 0;
 
2179
  }
 
2180
 
 
2181
  /* read script table */
 
2182
  /* use default language system */
 
2183
  pos = gsubTable+scriptList+scriptTable;
 
2184
  langSys = getU16BE(pos,&parsedOk);/* default language system */
 
2185
 
 
2186
  /* read LangSys table */
 
2187
  if (langSys == 0) {
 
2188
    /* no ldefault LangSys */
 
2189
    return 0;
 
2190
  }
 
2191
 
 
2192
  pos = gsubTable+scriptList+scriptTable+langSys+2;
 
2193
  featureIndex = getU16BE(pos,&parsedOk); /* ReqFeatureIndex */
 
2194
  pos += 2;
 
2195
 
 
2196
  if (featureIndex != 0xffff) {
 
2197
    Guint tpos;
 
2198
    /* read feature record */
 
2199
    tpos = gsubTable+featureList;
 
2200
    featureCount = getU16BE(tpos,&parsedOk);
 
2201
    tpos = gsubTable+featureList+2+featureIndex*(4+2);
 
2202
    tag = getU32BE(tpos,&parsedOk);
 
2203
    tpos += 4;
 
2204
    if (tag == vrt2Tag) {
 
2205
      /* vrt2 is preferred, overwrite vert */
 
2206
      ftable = getU16BE(tpos,&parsedOk);
 
2207
      /* convert to offset from file top */
 
2208
      gsubFeatureTable = ftable+gsubTable+featureList;
 
2209
      return 0;
 
2210
    } else if (tag == vertTag) {
 
2211
      ftable = getU16BE(tpos,&parsedOk);
 
2212
    }
 
2213
  }
 
2214
  featureCount = getU16BE(pos,&parsedOk);
 
2215
  pos += 2;
 
2216
  /* find 'vrt2' or 'vert' feature */
 
2217
  for (i = 0;i < featureCount;i++) {
 
2218
    Guint oldPos;
 
2219
 
 
2220
    featureIndex = getU16BE(pos,&parsedOk);
 
2221
    pos += 2;
 
2222
    oldPos = pos; /* save position */
 
2223
    /* read feature record */
 
2224
    pos = gsubTable+featureList+2+featureIndex*(4+2);
 
2225
    tag = getU32BE(pos,&parsedOk);
 
2226
    pos += 4;
 
2227
    if (tag == vrt2Tag) {
 
2228
      /* vrt2 is preferred, overwrite vert */
 
2229
      ftable = getU16BE(pos,&parsedOk);
 
2230
      break;
 
2231
    } else if (ftable == 0 && tag == vertTag) {
 
2232
      ftable = getU16BE(pos,&parsedOk);
 
2233
    }
 
2234
    pos = oldPos; /* restore old position */
 
2235
  }
 
2236
  if (ftable == 0) {
 
2237
    /* vert nor vrt2 are not found */
 
2238
    return 0;
 
2239
  }
 
2240
  /* convert to offset from file top */
 
2241
  gsubFeatureTable = ftable+gsubTable+featureList;
 
2242
  return 0;
 
2243
}
 
2244
 
 
2245
Guint FoFiTrueType::doMapToVertGID(Guint orgGID)
 
2246
{
 
2247
  Guint lookupCount;
 
2248
  Guint lookupListIndex;
 
2249
  Guint i;
 
2250
  Guint gid = 0;
 
2251
  Guint pos;
 
2252
 
 
2253
  pos = gsubFeatureTable+2;
 
2254
  lookupCount = getU16BE(pos,&parsedOk);
 
2255
  pos += 2;
 
2256
  for (i = 0;i < lookupCount;i++) {
 
2257
    lookupListIndex = getU16BE(pos,&parsedOk);
 
2258
    pos += 2;
 
2259
    if ((gid = scanLookupList(lookupListIndex,orgGID)) != 0) {
 
2260
      break;
 
2261
    }
 
2262
  }
 
2263
  return gid;
 
2264
}
 
2265
 
 
2266
Guint FoFiTrueType::mapToVertGID(Guint orgGID)
 
2267
{
 
2268
  Guint mapped;
 
2269
 
 
2270
  if (gsubFeatureTable == 0) return orgGID;
 
2271
  if ((mapped = doMapToVertGID(orgGID)) != 0) {
 
2272
    return mapped;
 
2273
  }
 
2274
  return orgGID;
 
2275
}
 
2276
 
 
2277
Guint FoFiTrueType::scanLookupList(Guint listIndex, Guint orgGID)
 
2278
{
 
2279
  Guint lookupTable;
 
2280
  Guint subTableCount;
 
2281
  Guint subTable;
 
2282
  Guint i;
 
2283
  Guint gid = 0;
 
2284
  Guint pos;
 
2285
 
 
2286
  if (gsubLookupList == 0) return 0; /* no lookup list */
 
2287
  pos = gsubLookupList+2+listIndex*2;
 
2288
  lookupTable = getU16BE(pos,&parsedOk);
 
2289
  /* read lookup table */
 
2290
  pos = gsubLookupList+lookupTable+4;
 
2291
  subTableCount = getU16BE(pos,&parsedOk);
 
2292
  pos += 2;;
 
2293
  for (i = 0;i < subTableCount;i++) {
 
2294
    subTable = getU16BE(pos,&parsedOk);
 
2295
    pos += 2;
 
2296
    if ((gid = scanLookupSubTable(gsubLookupList+lookupTable+subTable,orgGID))
 
2297
         != 0) break;
 
2298
  }
 
2299
  return gid;
 
2300
}
 
2301
 
 
2302
Guint FoFiTrueType::scanLookupSubTable(Guint subTable, Guint orgGID)
 
2303
{
 
2304
  Guint format;
 
2305
  Guint coverage;
 
2306
  int delta;
 
2307
  int glyphCount;
 
2308
  Guint substitute;
 
2309
  Guint gid = 0;
 
2310
  int coverageIndex;
 
2311
  int pos;
 
2312
 
 
2313
  pos = subTable;
 
2314
  format = getU16BE(pos,&parsedOk);
 
2315
  pos += 2;
 
2316
  coverage = getU16BE(pos,&parsedOk);
 
2317
  pos += 2;
 
2318
  if ((coverageIndex =
 
2319
     checkGIDInCoverage(subTable+coverage,orgGID)) >= 0) {
 
2320
    switch (format) {
 
2321
    case 1:
 
2322
      /* format 1 */
 
2323
      delta = getS16BE(pos,&parsedOk);
 
2324
      pos += 2;
 
2325
      gid = orgGID+delta;
 
2326
      break;
 
2327
    case 2:
 
2328
      /* format 2 */
 
2329
      glyphCount = getS16BE(pos,&parsedOk);
 
2330
      pos += 2;
 
2331
      if (glyphCount > coverageIndex) {
 
2332
        pos += coverageIndex*2;
 
2333
        substitute = getU16BE(pos,&parsedOk);
 
2334
        gid = substitute;
 
2335
      }
 
2336
      break;
 
2337
    default:
 
2338
      /* unknown format */
 
2339
      break;
 
2340
    }
 
2341
  }
 
2342
  return gid;
 
2343
}
 
2344
 
 
2345
int FoFiTrueType::checkGIDInCoverage(Guint coverage, Guint orgGID)
 
2346
{
 
2347
  int index = -1;
 
2348
  Guint format;
 
2349
  Guint count;
 
2350
  Guint i;
 
2351
  Guint pos;
 
2352
 
 
2353
  pos = coverage;
 
2354
  format = getU16BE(pos,&parsedOk);
 
2355
  pos += 2;
 
2356
  switch (format) {
 
2357
  case 1:
 
2358
    count = getU16BE(pos,&parsedOk);
 
2359
    pos += 2;
 
2360
    for (i = 0;i < count;i++) {
 
2361
      Guint gid;
 
2362
 
 
2363
      gid = getU16BE(pos,&parsedOk);
 
2364
      pos += 2;
 
2365
      if (gid == orgGID) {
 
2366
        /* found */
 
2367
        index = i;
 
2368
        break;
 
2369
      } else if (gid > orgGID) {
 
2370
        /* not found */
 
2371
        break;
 
2372
      }
 
2373
    }
 
2374
    break;
 
2375
  case 2:
 
2376
    count = getU16BE(pos,&parsedOk);
 
2377
    pos += 2;
 
2378
    for (i = 0;i < count;i++) {
 
2379
      Guint startGID, endGID;
 
2380
      Guint startIndex;
 
2381
 
 
2382
      startGID = getU16BE(pos,&parsedOk);
 
2383
      pos += 2;
 
2384
      endGID = getU16BE(pos,&parsedOk);
 
2385
      pos += 2;
 
2386
      startIndex = getU16BE(pos,&parsedOk);
 
2387
      pos += 2;
 
2388
      if (startGID <= orgGID && orgGID <= endGID) {
 
2389
        /* found */
 
2390
        index = startIndex+orgGID-startGID;
 
2391
        break;
 
2392
      } else if (orgGID <= endGID) {
 
2393
        /* not found */
 
2394
        break;
 
2395
      }
 
2396
    }
 
2397
    break;
 
2398
  default:
 
2399
    break;
 
2400
  }
 
2401
  return index;
 
2402
}
 
2403