~ubuntu-branches/ubuntu/raring/cups-filters/raring-proposed

« back to all changes in this revision

Viewing changes to filter/pdftopdf/PDFFTrueTypeFont.cxx

  • Committer: Package Import Robot
  • Author(s): Till Kamppeter
  • Date: 2012-07-22 18:57:32 UTC
  • mfrom: (1.1.17)
  • Revision ID: package-import@ubuntu.com-20120722185732-26kkte5p1lth3rt5
Tags: 1.0.20-0bzr1
* New upstream release
   - pdftops: Added another workaround for Kyocera printers: Some
     models get very slow on images which request interpolation,
     so now we remove the image interpolation requests by additional
     PostScript code only inserted for Kyocera printers (LP: #1026974).
   - Made the Poppler-based filters pdftopdf and pdftoopvp build with
     both Poppler 0.18.x and 0.20.x (Upstream bug #1055).
   - Fixes according to Coverity scan results (Upstream bug #1054).
   - Switched build system to autotools. This especially fixes several
     build problems in Gentoo. Also build-tested with CUPS 1.6.0b1.
   - Fixes for compatibility with clang/gcc-4.7.
   - textonly: Filter did not work as a pipe with copies=1 (Upstream bug
     #1032).
   - texttopdf: Avoid trimming the results of FcFontSort(), as this may
     miss some reasonable candidates under certain circumstances. BTW,
     fix passing a non-pointer as a pointer to "result" (Closes: #670055).
   - Corrected documentation. The option for the maximum image rendering
     resolution in pdftops is "pdftops-max-image-resolution", not
     "pdftops-max-image-resolution-default".
* debian/patches/fcfontsort-no-trim.patch: Removed, fixed upstream.
* debian/rules: Updated options for ./configure and make for the new autotools
  build system.
* debian/watch: Switched to bz2 upstream packages.
* debian/rules, debian/copyright, debian/cups-filters.docs: Updated for
  renamed documentation files.
* debian/control, debian/libfontembed1.install,
  debian/libfontembed-dev.install: Added new binary packages for libfontembed.
* debian/copyright: Updated for recent file additions, and rearrangement of
  directories.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 
 
3
Copyright (c) 2006-2007, BBR Inc.  All rights reserved.
 
4
 
 
5
Permission is hereby granted, free of charge, to any person obtaining
 
6
a copy of this software and associated documentation files (the
 
7
"Software"), to deal in the Software without restriction, including
 
8
without limitation the rights to use, copy, modify, merge, publish,
 
9
distribute, sublicense, and/or sell copies of the Software, and to
 
10
permit persons to whom the Software is furnished to do so, subject to
 
11
the following conditions:
 
12
 
 
13
The above copyright notice and this permission notice shall be included
 
14
in all copies or substantial portions of the Software.
 
15
 
 
16
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 
17
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 
18
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 
19
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 
20
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 
21
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 
22
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
23
 
 
24
*/
 
25
/*
 
26
 PDFFTrueTypeFont.cc
 
27
 TrueType font manager
 
28
*/
 
29
 
 
30
#include <stdio.h>
 
31
#include <stdlib.h>
 
32
#include <sys/types.h>
 
33
#include <sys/stat.h>
 
34
#include <fcntl.h>
 
35
#include <unistd.h>
 
36
#include <sys/mman.h>
 
37
#include <string.h>
 
38
#include "PDFFTrueTypeFont.h"
 
39
#include "P2PError.h"
 
40
 
 
41
#define TAG(a1,a2,a3,a4) (((a1) & 0xff) << 24 | \
 
42
   ((a2) & 0xff) << 16 | ((a3) & 0xff) << 8| ((a4) & 0xff))
 
43
 
 
44
#define TAG_TTC  TAG('t','t','c','f') /* ttcf */
 
45
#define TAG_NAME TAG('n','a','m','e') /* name */
 
46
#define TAG_CMAP TAG('c','m','a','p') /* cmap */
 
47
#define TAG_GSUB TAG('G','S','U','B') /* GSUB */
 
48
#define TAG_KANA TAG('k','a','n','a') /* kana */
 
49
#define TAG_VERT TAG('v','e','r','t') /* vert */
 
50
#define TAG_VRT2 TAG('v','r','t','2') /* vrt2 */
 
51
#define TAG_GLYF TAG('g','l','y','f') /* glyf */
 
52
#define TAG_LOCA TAG('l','o','c','a') /* loca */
 
53
#define TAG_HEAD TAG('h','e','a','d') /* head */
 
54
#define TAG_HHEA TAG('h','h','e','a') /* hhea */
 
55
#define TAG_HMTX TAG('h','m','t','x') /* hmtx */
 
56
#define TAG_MAXP TAG('m','a','x','p') /* maxp */
 
57
#define TAG_CVT  TAG('c','v','t',' ') /* cvt */
 
58
#define TAG_PREP TAG('p','r','e','p') /* prep */
 
59
#define TAG_FPGM TAG('f','p','g','m') /* fpgm */
 
60
 
 
61
#define GIDMAP_TABLE_INC 1024
 
62
#define OFFSET_TABLE_LEN 12
 
63
 
 
64
#ifdef PDFTOPDF
 
65
#define GLYF_INC 4096
 
66
#define LOCA_INC 1024
 
67
#define HMTX_INC 1024
 
68
 
 
69
/* generating font specifications */
 
70
/* table directory entry index */
 
71
#define TDIR_HEAD 0
 
72
#define TDIR_HHEA 1
 
73
#define TDIR_LOCA 2
 
74
#define TDIR_MAXP 3
 
75
#define TDIR_CVT  4
 
76
#define TDIR_PREP 5
 
77
#define TDIR_GLYF 6
 
78
#define TDIR_HMTX 7
 
79
#define TDIR_FPGM 8
 
80
 
 
81
/* number of tables */
 
82
#define TDIR_LEN 9
 
83
 
 
84
/* (Maximum power of 2 <= numTables) x 16. */
 
85
#define SEARCH_RANGE (8*16)
 
86
/* Log2(maximum power of 2 <= numTables) */
 
87
#define ENTRY_SELECTOR 3
 
88
 
 
89
/* table sizes */
 
90
#define HEAD_TABLE_LEN (54 + 2) /* 2 for padding */
 
91
#define HHEA_TABLE_LEN 36
 
92
#define MAXP_TABLE_LEN 32
 
93
 
 
94
/* table directory entry size */
 
95
#define TABLE_DIR_ENTRY_LEN 16
 
96
 
 
97
/* length of longHorMetrics entry */
 
98
#define LONGHORMETRIC_LEN (sizeof(USHORT)+sizeof(SHORT))
 
99
 
 
100
/* composite glyph script flags */
 
101
#define CG_ARG_1_AND_2_ARE_WORDS (1 << 0)
 
102
#define CG_ARGS_ARE_XY_VALUES (1 << 1)
 
103
#define CG_ROUND_XY_TO_GRID (1 << 2)
 
104
#define CG_WE_HAVE_A_SCALE (1 << 3)
 
105
#define CG_RESERVED (1 << 4)
 
106
#define CG_MORE_COMPONENTS (1 << 5)
 
107
#define CG_WE_HAVE_AN_X_AND_Y_SCALE (1 << 6)
 
108
#define CG_WE_HAVE_A_TWO_BY_TWO (1 << 7)
 
109
#define CG_WE_HAVE_INSTRUCTIONS (1 << 8)
 
110
#define CG_USE_MY_METRICS (1 << 9)
 
111
#define CG_OVERLAP_COMPOUND (1 << 10)
 
112
#define CG_SCALED_COMPONENTS_OFFSET (1 << 11)
 
113
#define CG_UNSCALED_COMPONENT_OFFSET (1 << 12)
 
114
#endif
 
115
 
 
116
#ifdef PDFTOPDF
 
117
unsigned long PDFFTrueTypeFont::mapGID(unsigned long orgGID)
 
118
{
 
119
  unsigned long i;
 
120
 
 
121
  if (orgGID == 0) return 0;
 
122
  if (GIDMap == 0) {
 
123
    GIDMapSize = GIDMAP_TABLE_INC;
 
124
    GIDMap = new unsigned long [GIDMapSize];
 
125
    GIDMap[0] = 0; /* always map 0 to 0 */
 
126
  }
 
127
  /* check if gid is already registered */
 
128
  for (i = 1;i < maxGID;i++) {
 
129
    if (GIDMap[i] == orgGID) return i;
 
130
  }
 
131
  /* not found */
 
132
  /* then regsiter it */
 
133
  if (++maxGID >= GIDMapSize) {
 
134
    /* realloc GIDMap */
 
135
    unsigned long *p;
 
136
    unsigned int newSize;
 
137
 
 
138
    newSize = GIDMapSize + GIDMAP_TABLE_INC;
 
139
    p = new unsigned long [newSize];
 
140
    memcpy(p,GIDMap,GIDMapSize*sizeof(unsigned long));
 
141
    delete[] GIDMap;
 
142
    GIDMap = p;
 
143
    GIDMapSize = newSize;
 
144
  }
 
145
  GIDMap[maxGID] = orgGID;
 
146
//fprintf(stderr,"DEBUG:map GID %d to %d\n",orgGID,maxGID);
 
147
  return maxGID;
 
148
}
 
149
 
 
150
void PDFFTrueTypeFont::allocNewLGHTable()
 
151
{
 
152
  /* Long version loca */
 
153
  loca = new ULONG [maxGID+2];
 
154
  locaSize = maxGID+2;
 
155
 
 
156
  /* allocate glyf */
 
157
  glyfSize = GLYF_INC;
 
158
  cGlyfIndex = 0;
 
159
  glyf = new unsigned char [glyfSize];
 
160
 
 
161
  /* allocate hmtx */
 
162
  /* all long metric */
 
163
  hmtx = new LongHorMetric [maxGID+1];
 
164
  hmtxSize = maxGID+1;
 
165
}
 
166
 
 
167
void PDFFTrueTypeFont::reallocNewLHTable()
 
168
{
 
169
  if (locaSize < maxGID+2) {
 
170
    unsigned long newSize;
 
171
    ULONG *np;
 
172
 
 
173
    newSize = locaSize+LOCA_INC;
 
174
    np = new ULONG [newSize];
 
175
    memcpy(np,loca,locaSize*sizeof(ULONG));
 
176
    delete[] loca;
 
177
    loca = np;
 
178
    locaSize = newSize;
 
179
  }
 
180
  if (hmtxSize < maxGID+1) {
 
181
    unsigned long newSize;
 
182
    LongHorMetric *np;
 
183
 
 
184
    newSize = hmtxSize+HMTX_INC;
 
185
    np = new LongHorMetric [newSize];
 
186
    memcpy(np,hmtx,hmtxSize*sizeof(LongHorMetric));
 
187
    delete[] hmtx;
 
188
    hmtx = np;
 
189
    hmtxSize = newSize;
 
190
  }
 
191
}
 
192
 
 
193
int PDFFTrueTypeFont::readOrgTables()
 
194
{
 
195
  if (getTableDirEntry(TAG_HEAD,&(orgTDir[TDIR_HEAD])) < 0) {
 
196
    p2pError(-1,const_cast<char *>("head table not found in font file %s"),
 
197
       fileName);
 
198
    return -1;
 
199
  }
 
200
  setOffset(orgTDir[TDIR_HEAD].offset);
 
201
  if (head.read(this) < 0) {
 
202
    return -1;
 
203
  }
 
204
 
 
205
  if (getTableDirEntry(TAG_HHEA,&(orgTDir[TDIR_HHEA])) < 0) {
 
206
    p2pError(-1,const_cast<char *>("hhea table not found in font file %s"),
 
207
       fileName);
 
208
    return -1;
 
209
  }
 
210
  setOffset(orgTDir[TDIR_HHEA].offset);
 
211
  if (hhea.read(this) < 0) {
 
212
    return -1;
 
213
  }
 
214
 
 
215
  if (getTableDirEntry(TAG_MAXP,&(orgTDir[TDIR_MAXP])) < 0) {
 
216
    p2pError(-1,const_cast<char *>("maxp table not found in font file %s"),
 
217
      fileName);
 
218
    return -1;
 
219
  }
 
220
  setOffset(orgTDir[TDIR_MAXP].offset);
 
221
  if (maxp.read(this) < 0) {
 
222
    return -1;
 
223
  }
 
224
 
 
225
  if (getTableDirEntry(TAG_LOCA,&(orgTDir[TDIR_LOCA])) < 0) {
 
226
    p2pError(-1,const_cast<char *>("loca table not found in font file %s"),
 
227
      fileName);
 
228
    return -1;
 
229
  }
 
230
 
 
231
  if (getTableDirEntry(TAG_GLYF,&(orgTDir[TDIR_GLYF])) < 0) {
 
232
    p2pError(-1,const_cast<char *>("glyf table not found in font file %s"),
 
233
      fileName);
 
234
    return -1;
 
235
  }
 
236
 
 
237
  if (getTableDirEntry(TAG_HMTX,&(orgTDir[TDIR_HMTX])) < 0) {
 
238
    p2pError(-1,const_cast<char *>("hmtx table not found in font file %s"),
 
239
      fileName);
 
240
    return -1;
 
241
  }
 
242
 
 
243
  if (getTableDirEntry(TAG_CVT,&(orgTDir[TDIR_CVT])) < 0) {
 
244
    /* not found */
 
245
    orgTDir[TDIR_CVT].tag = 0; /* null */
 
246
  }
 
247
 
 
248
  if (getTableDirEntry(TAG_PREP,&(orgTDir[TDIR_PREP])) < 0) {
 
249
    /* not found */
 
250
    orgTDir[TDIR_PREP].tag = 0; /* null */
 
251
  }
 
252
 
 
253
  if (getTableDirEntry(TAG_FPGM,&(orgTDir[TDIR_FPGM])) < 0) {
 
254
    /* not found */
 
255
    orgTDir[TDIR_FPGM].tag = 0; /* null */
 
256
  }
 
257
  return 0;
 
258
}
 
259
 
 
260
void PDFFTrueTypeFont::outputWholeFile(P2POutputStream *str)
 
261
{
 
262
  int n = fileLength;
 
263
  int r;
 
264
  unsigned char *p = top;
 
265
 
 
266
  while (n > 0) {
 
267
    r = str->write(p,n);
 
268
    if (r <= 0) break;
 
269
    n -= r;
 
270
    p += r;
 
271
  }
 
272
  outputLength = fileLength;
 
273
}
 
274
 
 
275
/* creating loca ,glyf and hmtx */
 
276
void PDFFTrueTypeFont::createLGHTable()
 
277
{
 
278
  unsigned long i;
 
279
  USHORT defWidth;
 
280
 
 
281
  /* allocate new tables */
 
282
  allocNewLGHTable();
 
283
 
 
284
  locaEntrySize = head.indexToLocFormat == 0 ? 2 : 4;
 
285
 
 
286
  /* read the last longHorMetrics for default width */
 
287
  read(orgTDir[TDIR_HHEA].offset+(hhea.numberOfHMetrics-1)*(sizeof(USHORT)
 
288
    +sizeof(SHORT)),&defWidth);
 
289
 
 
290
  /* NOTE: maxGID may be changed in this loop. */
 
291
  for (i = 0;i <= maxGID;i++) {
 
292
    ULONG start, end;
 
293
    unsigned long len;
 
294
    SHORT numberOfContours;
 
295
    unsigned long longHorMetricsLen
 
296
      = hhea.numberOfHMetrics*(sizeof(USHORT)+sizeof(SHORT));
 
297
 
 
298
    /* glyf */
 
299
    setOffset(orgTDir[TDIR_LOCA].offset+GIDMap[i]*locaEntrySize);
 
300
    read(&start,locaEntrySize);
 
301
    read(&end,locaEntrySize);
 
302
    len = end-start;
 
303
    /* convert start to offset from the top of file */
 
304
    start += orgTDir[TDIR_GLYF].offset;
 
305
 
 
306
    /* copy glyf entry */
 
307
    if (cGlyfIndex+len >= glyfSize) {
 
308
      /* realloc glyf */
 
309
      unsigned char *p;
 
310
      unsigned long newSize
 
311
        = (cGlyfIndex+len+GLYF_INC-1)/GLYF_INC;
 
312
      newSize *= GLYF_INC;
 
313
 
 
314
      p = new unsigned char [newSize];
 
315
      memcpy(p,glyf,cGlyfIndex);
 
316
      delete[] glyf;
 
317
      glyf = p;
 
318
      glyfSize = newSize;
 
319
    }
 
320
    read(start,&numberOfContours);
 
321
    if (numberOfContours < 0) {
 
322
      /* composite glyph */
 
323
//fprintf(stderr,"DEBUG: GID=%d is composite glyph\n",GIDMap[i]);
 
324
      SHORT flags;
 
325
      /* closure for copy */
 
326
      class _CopyGlyf {
 
327
      public:
 
328
        unsigned char *dst;
 
329
        unsigned char *src;
 
330
 
 
331
        _CopyGlyf(unsigned char *dstA, unsigned char *srcA) {
 
332
          dst = dstA;
 
333
          src = srcA;
 
334
        }
 
335
        void copy(unsigned long n) {
 
336
          memcpy(dst,src,n);
 
337
          dst += n;
 
338
          src += n;
 
339
        }
 
340
        void copy(unsigned char *p, unsigned long n) {
 
341
          memcpy(dst,p,n);
 
342
          dst += n;
 
343
          src += n;
 
344
        }
 
345
      } copyGlyf(glyf+cGlyfIndex,top+start);
 
346
 
 
347
      int haveInstructions = 0;
 
348
 
 
349
      /* skip xMin,yMin,xMax,yMax */
 
350
      advance(sizeof(SHORT)*4);
 
351
 
 
352
      /* copy header */
 
353
      copyGlyf.copy(sizeof(SHORT)*5);
 
354
 
 
355
      do {
 
356
        unsigned long oldMax;
 
357
        SHORT mappedGID;
 
358
        SHORT glyphIndex;
 
359
 
 
360
        read(&flags);
 
361
        haveInstructions |= (flags & CG_WE_HAVE_INSTRUCTIONS) != 0;
 
362
        /* copy flags */
 
363
        copyGlyf.copy(sizeof(flags));
 
364
 
 
365
        read(&glyphIndex);
 
366
//fprintf(stderr,"DEBUG: composite ref GID=%d, maxGID=%d\n",glyphIndex,maxGID);
 
367
        oldMax = maxGID;
 
368
        mappedGID = mapGID(glyphIndex);
 
369
        mappedGID = toBE(mappedGID); /* convert Big endian */
 
370
        /* put mapped GID */
 
371
        copyGlyf.copy(reinterpret_cast<unsigned char *>(&mappedGID),
 
372
          sizeof(glyphIndex));
 
373
 
 
374
        if (maxGID != oldMax) {
 
375
          /* new GID has been added */
 
376
//fprintf(stderr,"DEBUG: composite GID added\n");
 
377
          reallocNewLHTable();
 
378
        }
 
379
 
 
380
        if (flags & CG_ARG_1_AND_2_ARE_WORDS) {
 
381
          /* copy argument1, argument2 */
 
382
          advance(sizeof(SHORT)*2);
 
383
          copyGlyf.copy(sizeof(SHORT)*2);
 
384
        } else {
 
385
          /* copy arg1and2 */
 
386
          advance(sizeof(USHORT));
 
387
          copyGlyf.copy(sizeof(USHORT));
 
388
        }
 
389
        if (flags & CG_WE_HAVE_A_SCALE) {
 
390
          /* copy scale */
 
391
          advance(sizeof(F2Dot14));
 
392
          copyGlyf.copy(sizeof(F2Dot14));
 
393
        } else if (flags & CG_WE_HAVE_AN_X_AND_Y_SCALE) {
 
394
          /* copy xscale, yscale */
 
395
          advance(sizeof(F2Dot14)*2);
 
396
          copyGlyf.copy(sizeof(F2Dot14)*2);
 
397
        } else if (flags & CG_WE_HAVE_A_TWO_BY_TWO) {
 
398
          /* copy xscale, scale01, scale10, yscale */
 
399
          advance(sizeof(F2Dot14)*4);
 
400
          copyGlyf.copy(sizeof(F2Dot14)*4);
 
401
        }
 
402
      } while (flags & CG_MORE_COMPONENTS);
 
403
      if (haveInstructions) {
 
404
        USHORT numInstr;
 
405
 
 
406
        read(&numInstr);
 
407
        /* copy instructions */
 
408
        advance(sizeof(USHORT)+numInstr);
 
409
        copyGlyf.copy(sizeof(USHORT)+numInstr);
 
410
      }
 
411
    } else {
 
412
      /* single glyph */
 
413
      memcpy(glyf+cGlyfIndex,top+start,len);
 
414
    }
 
415
    loca[i] = cGlyfIndex;
 
416
    cGlyfIndex += len;
 
417
 
 
418
    /* hmtx */
 
419
    if (GIDMap[i] < hhea.numberOfHMetrics) {
 
420
      /* long version */
 
421
      setOffset(orgTDir[TDIR_HMTX].offset+GIDMap[i]*(sizeof(USHORT)
 
422
        +sizeof(SHORT)));
 
423
      read(&(hmtx[i].advanceWidth));
 
424
      read(&(hmtx[i].lsb));
 
425
    } else {
 
426
      /* lsb only version */
 
427
      read(orgTDir[TDIR_HMTX].offset+longHorMetricsLen
 
428
        +(GIDMap[i]-hhea.numberOfHMetrics)*sizeof(SHORT),&(hmtx[i].lsb));
 
429
      hmtx[i].advanceWidth = defWidth;
 
430
    }
 
431
  }
 
432
  loca[i] = cGlyfIndex; /* last entry */
 
433
}
 
434
 
 
435
unsigned long PDFFTrueTypeFont::locaCheckSum()
 
436
{
 
437
  unsigned long sum = 0;
 
438
  unsigned long i;
 
439
 
 
440
  for (i = 0;i < maxGID+2;i++) {
 
441
    sum += loca[i];
 
442
  }
 
443
  return sum;
 
444
}
 
445
 
 
446
unsigned long PDFFTrueTypeFont::glyfCheckSum()
 
447
{
 
448
  unsigned long sum = 0;
 
449
  unsigned long n = (cGlyfIndex+3)/4;
 
450
  unsigned long i;
 
451
  ULONG *p = reinterpret_cast<ULONG *>(glyf);
 
452
 
 
453
  for (i = 0;i < n;i++) {
 
454
    sum += toBE(p[i]);
 
455
  }
 
456
  return sum;
 
457
}
 
458
 
 
459
unsigned long PDFFTrueTypeFont::hmtxCheckSum()
 
460
{
 
461
  unsigned long sum = 0;
 
462
  unsigned long i;
 
463
 
 
464
  for (i = 0;i < maxGID+1;i++) {
 
465
    sum += hmtx[i].checkSum();
 
466
  }
 
467
  return sum;
 
468
}
 
469
 
 
470
void PDFFTrueTypeFont::setupNewTableDirectory()
 
471
{
 
472
  unsigned long toffset = OFFSET_TABLE_LEN+TABLE_DIR_ENTRY_LEN*TDIR_LEN;
 
473
 
 
474
  tDir[TDIR_HEAD].tag = TAG_HEAD;
 
475
  tDir[TDIR_HEAD].checkSum = head.checkSum();
 
476
  tDir[TDIR_HEAD].offset = toffset;
 
477
  tDir[TDIR_HEAD].length = HEAD_TABLE_LEN;
 
478
  toffset += tDir[TDIR_HEAD].length;
 
479
 
 
480
  tDir[TDIR_HHEA].tag = TAG_HHEA;
 
481
  tDir[TDIR_HHEA].checkSum = hhea.checkSum();
 
482
  tDir[TDIR_HHEA].offset = toffset;
 
483
  tDir[TDIR_HHEA].length = HHEA_TABLE_LEN;
 
484
  toffset += tDir[TDIR_HHEA].length;
 
485
 
 
486
  tDir[TDIR_LOCA].tag = TAG_LOCA;
 
487
  tDir[TDIR_LOCA].checkSum = locaCheckSum();
 
488
  tDir[TDIR_LOCA].offset = toffset;
 
489
  tDir[TDIR_LOCA].length = (maxGID+2)*sizeof(ULONG);
 
490
  toffset += tDir[TDIR_LOCA].length;
 
491
 
 
492
  tDir[TDIR_MAXP].tag = TAG_MAXP;
 
493
  tDir[TDIR_MAXP].checkSum = maxp.checkSum();
 
494
  tDir[TDIR_MAXP].offset = toffset;
 
495
  tDir[TDIR_MAXP].length = MAXP_TABLE_LEN;
 
496
  toffset += tDir[TDIR_MAXP].length;
 
497
 
 
498
  /* copy cvt table, so checkSum and length are same as original */
 
499
  tDir[TDIR_CVT].tag = TAG_CVT;
 
500
  tDir[TDIR_CVT].offset = toffset;
 
501
  if (orgTDir[TDIR_CVT].tag == 0) {
 
502
    /* no cvt table in original font, output empty */
 
503
    tDir[TDIR_CVT].checkSum = TAG_CVT + toffset;
 
504
    tDir[TDIR_CVT].length = 0;
 
505
  } else {
 
506
    tDir[TDIR_CVT].checkSum = orgTDir[TDIR_CVT].checkSum;
 
507
    tDir[TDIR_CVT].length = orgTDir[TDIR_CVT].length;
 
508
  }
 
509
  toffset += tDir[TDIR_CVT].length;
 
510
 
 
511
  /* copy prep table, so checkSum and length are same as original */
 
512
  tDir[TDIR_PREP].tag = TAG_PREP;
 
513
  tDir[TDIR_PREP].offset = toffset;
 
514
  if (orgTDir[TDIR_PREP].tag == 0) {
 
515
    /* no prep table in original font, output empty */
 
516
    tDir[TDIR_PREP].checkSum = TAG_PREP + toffset;
 
517
    tDir[TDIR_PREP].length = 0;
 
518
  } else {
 
519
    tDir[TDIR_PREP].length = orgTDir[TDIR_PREP].length;
 
520
    tDir[TDIR_PREP].checkSum = orgTDir[TDIR_PREP].checkSum;
 
521
  }
 
522
  toffset += tDir[TDIR_PREP].length;
 
523
 
 
524
  tDir[TDIR_GLYF].tag = TAG_GLYF;
 
525
  tDir[TDIR_GLYF].checkSum = glyfCheckSum();
 
526
  tDir[TDIR_GLYF].offset = toffset;
 
527
  tDir[TDIR_GLYF].length = cGlyfIndex;
 
528
  toffset += tDir[TDIR_GLYF].length;
 
529
 
 
530
  tDir[TDIR_HMTX].tag = TAG_HMTX;
 
531
  tDir[TDIR_HMTX].checkSum = hmtxCheckSum();
 
532
  tDir[TDIR_HMTX].offset = toffset;
 
533
  tDir[TDIR_HMTX].length = (maxGID+1)*LONGHORMETRIC_LEN;
 
534
  toffset += tDir[TDIR_HMTX].length;
 
535
 
 
536
  /* copy fpgm table, so checkSum and length are same as original */
 
537
  tDir[TDIR_FPGM].tag = TAG_FPGM;
 
538
  tDir[TDIR_FPGM].offset = toffset;
 
539
  if (orgTDir[TDIR_FPGM].tag == 0) {
 
540
    /* no fpgm table in original font, output empty */
 
541
    tDir[TDIR_FPGM].checkSum = TAG_FPGM + toffset;
 
542
    tDir[TDIR_FPGM].length = 0;
 
543
  } else {
 
544
    tDir[TDIR_FPGM].length = orgTDir[TDIR_FPGM].length;
 
545
    tDir[TDIR_FPGM].checkSum = orgTDir[TDIR_FPGM].checkSum;
 
546
  }
 
547
  toffset += tDir[TDIR_FPGM].length;
 
548
}
 
549
 
 
550
void PDFFTrueTypeFont::outputOffsetTable(P2POutputStream *str)
 
551
{
 
552
  write(str,static_cast<Fixed>(0x0010000)); /* version 1.0 */
 
553
  write(str,static_cast<USHORT>(TDIR_LEN)); /* numTable */
 
554
  write(str,static_cast<USHORT>(SEARCH_RANGE)); /* searchRange */
 
555
  write(str,static_cast<USHORT>(ENTRY_SELECTOR)); /* entrySelector */
 
556
  write(str,static_cast<USHORT>(TDIR_LEN*16-SEARCH_RANGE)); /* rangeShift */
 
557
}
 
558
 
 
559
unsigned long PDFFTrueTypeFont::offsetTableCheckSum()
 
560
{
 
561
  unsigned long sum = 0;
 
562
 
 
563
  sum += 0x0010000; /* version 1.0 */
 
564
  sum += TDIR_LEN << 16; /* numTable */
 
565
  sum += SEARCH_RANGE & 0xffff; /* searchRange */
 
566
  sum += ENTRY_SELECTOR << 16; /* entrySelector */
 
567
  sum += (TDIR_LEN*16-SEARCH_RANGE) & 0xffff; /* rangeShift */
 
568
  return sum;
 
569
}
 
570
 
 
571
unsigned long PDFFTrueTypeFont::allCheckSum()
 
572
{
 
573
  unsigned long sum = 0;
 
574
  int i;
 
575
 
 
576
  sum += offsetTableCheckSum();
 
577
  sum += tableDirectoryCheckSum();
 
578
  for (i = 0;i < TDIR_LEN;i++) {
 
579
    sum += tDir[i].checkSum;
 
580
  }
 
581
  return sum;
 
582
}
 
583
 
 
584
unsigned long PDFFTrueTypeFont::tableDirectoryCheckSum()
 
585
{
 
586
  int i;
 
587
  unsigned long sum = 0;
 
588
 
 
589
  for (i = 0;i < TDIR_LEN;i++) {
 
590
    sum += tDir[i].calcCheckSum();
 
591
  }
 
592
  return sum;
 
593
}
 
594
 
 
595
void PDFFTrueTypeFont::outputOrgData(P2POutputStream *str,
 
596
  unsigned long offset, unsigned long len)
 
597
{
 
598
  str->write(top+offset,len);
 
599
}
 
600
 
 
601
void PDFFTrueTypeFont::outputCvt(P2POutputStream *str)
 
602
{
 
603
  /* copy original data */
 
604
  outputOrgData(str,orgTDir[TDIR_CVT].offset,tDir[TDIR_CVT].length);
 
605
}
 
606
 
 
607
void PDFFTrueTypeFont::outputPrep(P2POutputStream *str)
 
608
{
 
609
  /* copy original data */
 
610
  outputOrgData(str,orgTDir[TDIR_PREP].offset,tDir[TDIR_PREP].length);
 
611
}
 
612
 
 
613
void PDFFTrueTypeFont::outputFpgm(P2POutputStream *str)
 
614
{
 
615
  /* copy original data */
 
616
  outputOrgData(str,orgTDir[TDIR_FPGM].offset,tDir[TDIR_FPGM].length);
 
617
}
 
618
 
 
619
void PDFFTrueTypeFont::outputLoca(P2POutputStream *str)
 
620
{
 
621
  unsigned long i;
 
622
 
 
623
  for (i = 0;i < maxGID+2;i++) {
 
624
    write(str,loca[i]);
 
625
  }
 
626
}
 
627
 
 
628
void PDFFTrueTypeFont::outputGlyf(P2POutputStream *str)
 
629
{
 
630
  str->write(glyf,cGlyfIndex);
 
631
}
 
632
 
 
633
void PDFFTrueTypeFont::outputHmtx(P2POutputStream *str)
 
634
{
 
635
  unsigned long i;
 
636
 
 
637
  for (i = 0;i < maxGID+1;i++) {
 
638
    hmtx[i].output(this,str);
 
639
  }
 
640
}
 
641
 
 
642
void PDFFTrueTypeFont::outputTableDirectory(P2POutputStream *str)
 
643
{
 
644
  unsigned int i;
 
645
 
 
646
  for (i = 0;i < TDIR_LEN;i++) {
 
647
    tDir[i].output(this,str);
 
648
  }
 
649
}
 
650
 
 
651
void PDFFTrueTypeFont::output(P2POutputStream *str)
 
652
{
 
653
  if (GIDMap == 0) {
 
654
    /* output whole file */
 
655
    outputWholeFile(str);
 
656
    return;
 
657
  }
 
658
 
 
659
  /* read or setup original tables */
 
660
  if (readOrgTables() < 0) {
 
661
    /* error */
 
662
    return;
 
663
  }
 
664
 
 
665
  /* creating loca ,glyf and hmtx */
 
666
  createLGHTable();
 
667
 
 
668
  /* change rest table values */
 
669
  head.checkSumAdjustment = 0;
 
670
  hhea.numberOfHMetrics = maxGID+1; /* all metrics are long format */
 
671
  maxp.numGlyphs = maxGID+1;
 
672
  maxp.maxContours = maxGID+1;
 
673
  maxp.maxCompositeContours = maxGID+1;
 
674
 
 
675
  setupNewTableDirectory();
 
676
 
 
677
  /* calc Adjustment */
 
678
  head.checkSumAdjustment = 0xB1B0AFBA-allCheckSum();
 
679
 
 
680
  /* output font */
 
681
  outputOffsetTable(str);
 
682
  outputTableDirectory(str);
 
683
  outputHead(str);
 
684
  outputHhea(str);
 
685
  outputLoca(str);
 
686
  outputMaxp(str);
 
687
  outputCvt(str);
 
688
  outputPrep(str);
 
689
  outputGlyf(str);
 
690
  outputHmtx(str);
 
691
  outputFpgm(str);
 
692
 
 
693
  /* setup table directory */
 
694
  freeNewTables();
 
695
}
 
696
 
 
697
void PDFFTrueTypeFont::freeNewTables()
 
698
{
 
699
  if (glyf != 0) {
 
700
    delete[] glyf;
 
701
    glyf = 0;
 
702
  }
 
703
  if (hmtx != 0) {
 
704
    delete[] hmtx;
 
705
    hmtx = 0;
 
706
    hmtxSize = 0;
 
707
  }
 
708
  if (loca != 0) {
 
709
    delete[] loca;
 
710
    loca = 0;
 
711
    locaSize = 0;
 
712
  }
 
713
}
 
714
 
 
715
int PDFFTrueTypeFont::Head::read(PDFFTrueTypeFont *font)
 
716
{
 
717
  font->read(&version);
 
718
  if ((version & 0x10000) != 0x10000) {
 
719
    p2pError(-1,const_cast<char *>("Not supported head table version in file %s"),
 
720
       font->fileName);
 
721
    return -1;
 
722
  }
 
723
  font->read(&fontRevision);
 
724
  font->read(&checkSumAdjustment);
 
725
  font->read(&magicNumber);
 
726
  font->read(&flags);
 
727
  font->read(&unitsPerEm);
 
728
  font->read(&created);
 
729
  font->read(&modified);
 
730
  font->read(&xMin);
 
731
  font->read(&yMin);
 
732
  font->read(&xMax);
 
733
  font->read(&yMax);
 
734
  font->read(&macStyle);
 
735
  font->read(&lowestRecPPEM);
 
736
  font->read(&fontDirectionHint);
 
737
  font->read(&indexToLocFormat);
 
738
  font->read(&glyphDataFormat);
 
739
  return 0;
 
740
}
 
741
 
 
742
void PDFFTrueTypeFont::Head::output(PDFFTrueTypeFont *font, P2POutputStream *str)
 
743
{
 
744
  font->write(str,version);
 
745
  font->write(str,fontRevision);
 
746
  font->write(str,checkSumAdjustment);
 
747
  font->write(str,magicNumber);
 
748
  font->write(str,flags);
 
749
  font->write(str,unitsPerEm);
 
750
  font->write(str,created);
 
751
  font->write(str,modified);
 
752
  font->write(str,xMin);
 
753
  font->write(str,yMin);
 
754
  font->write(str,xMax);
 
755
  font->write(str,yMax);
 
756
  font->write(str,macStyle);
 
757
  font->write(str,lowestRecPPEM);
 
758
  font->write(str,fontDirectionHint);
 
759
  font->write(str,indexToLocFormat);
 
760
  font->write(str,glyphDataFormat);
 
761
  font->write(str,static_cast<USHORT>(0)); /* padding */
 
762
}
 
763
 
 
764
unsigned long PDFFTrueTypeFont::Head::checkSum()
 
765
{
 
766
  unsigned long sum = 0;
 
767
 
 
768
  sum += version;
 
769
  sum += fontRevision;
 
770
  sum += magicNumber;
 
771
  sum += flags << 16;
 
772
  sum += unitsPerEm & 0xffff;
 
773
  sum += (created >> 32) & 0xffffffff;
 
774
  sum += created & 0xffffffff;
 
775
  sum += (modified >> 32) & 0xffffffff;
 
776
  sum += modified & 0xffffffff;
 
777
  sum += xMin << 16;
 
778
  sum += yMin & 0xffff;
 
779
  sum += xMax << 16;
 
780
  sum += yMax & 0xffff;
 
781
  sum += macStyle << 16;
 
782
  sum += lowestRecPPEM & 0xffff;
 
783
  sum += fontDirectionHint << 16;
 
784
  sum += indexToLocFormat & 0xffff;
 
785
  sum += glyphDataFormat << 16;
 
786
 
 
787
  return sum;
 
788
}
 
789
 
 
790
int PDFFTrueTypeFont::Hhea::read(PDFFTrueTypeFont *font)
 
791
{
 
792
  font->read(&version);
 
793
  if ((version & 0x10000) != 0x10000) {
 
794
    p2pError(-1,const_cast<char *>("Not supported hhea table version in file %s"),
 
795
      font->fileName);
 
796
    return -1;
 
797
  }
 
798
  font->read(&Ascender);
 
799
  font->read(&Descender);
 
800
  font->read(&LineGap);
 
801
  font->read(&advanceWidthMax);
 
802
  font->read(&minLeftSideBearing);
 
803
  font->read(&minRightSideBearing);
 
804
  font->read(&xMacExtent);
 
805
  font->read(&caretSlopeRise);
 
806
  font->read(&caretSlopeRun);
 
807
  font->read(&caretOffset);
 
808
  /* skip reserved */
 
809
  font->skip<SHORT>();
 
810
  font->skip<SHORT>();
 
811
  font->skip<SHORT>();
 
812
  font->skip<SHORT>();
 
813
  font->read(&metricDataFormat);
 
814
  font->read(&numberOfHMetrics);
 
815
  return 0;
 
816
}
 
817
 
 
818
void PDFFTrueTypeFont::Hhea::output(PDFFTrueTypeFont *font, P2POutputStream *str)
 
819
{
 
820
  font->write(str,version);
 
821
  font->write(str,Ascender);
 
822
  font->write(str,Descender);
 
823
  font->write(str,LineGap);
 
824
  font->write(str,advanceWidthMax);
 
825
  font->write(str,minLeftSideBearing);
 
826
  font->write(str,minRightSideBearing);
 
827
  font->write(str,xMacExtent);
 
828
  font->write(str,caretSlopeRise);
 
829
  font->write(str,caretSlopeRun);
 
830
  font->write(str,caretOffset);
 
831
  /* output reserved */
 
832
  font->write(str,static_cast<SHORT>(0));
 
833
  font->write(str,static_cast<SHORT>(0));
 
834
  font->write(str,static_cast<SHORT>(0));
 
835
  font->write(str,static_cast<SHORT>(0));
 
836
  font->write(str,metricDataFormat);
 
837
  font->write(str,numberOfHMetrics);
 
838
}
 
839
 
 
840
unsigned long PDFFTrueTypeFont::Hhea::checkSum()
 
841
{
 
842
  unsigned long sum = 0;
 
843
 
 
844
  sum += version;
 
845
  sum += Ascender << 16;
 
846
  sum += Descender & 0xffff;
 
847
  sum += LineGap << 16;
 
848
  sum += advanceWidthMax & 0xffff;
 
849
  sum += minLeftSideBearing << 16;
 
850
  sum += minRightSideBearing & 0xffff;
 
851
  sum += xMacExtent << 16;
 
852
  sum += caretSlopeRise & 0xffff;
 
853
  sum += caretSlopeRun << 16;
 
854
  sum += caretOffset & 0xffff;
 
855
  sum += metricDataFormat << 16;
 
856
  sum += numberOfHMetrics & 0xffff;
 
857
  return sum;
 
858
}
 
859
 
 
860
int PDFFTrueTypeFont::Maxp::read(PDFFTrueTypeFont *font)
 
861
{
 
862
  font->read(&version);
 
863
  if ((version & 0x10000) != 0x10000) {
 
864
    p2pError(-1,const_cast<char *>("Not supported maxp table version in file %s"),
 
865
      font->fileName);
 
866
    return -1;
 
867
  }
 
868
  font->read(&numGlyphs);
 
869
  font->read(&maxPoints);
 
870
  font->read(&maxContours);
 
871
  font->read(&maxCompositePoints);
 
872
  font->read(&maxCompositeContours);
 
873
  font->read(&maxZones);
 
874
  font->read(&maxTwilightPoints);
 
875
  font->read(&maxStorage);
 
876
  font->read(&maxFunctionDefs);
 
877
  font->read(&maxInstructionDefs);
 
878
  font->read(&maxStackElements);
 
879
  font->read(&maxSizeOfInstructions);
 
880
  font->read(&maxComponentElements);
 
881
  font->read(&maxComponentDepth);
 
882
  return 0;
 
883
}
 
884
 
 
885
void PDFFTrueTypeFont::Maxp::output(PDFFTrueTypeFont *font, P2POutputStream *str)
 
886
{
 
887
  font->write(str,version);
 
888
  font->write(str,numGlyphs);
 
889
  font->write(str,maxPoints);
 
890
  font->write(str,maxContours);
 
891
  font->write(str,maxCompositePoints);
 
892
  font->write(str,maxCompositeContours);
 
893
  font->write(str,maxZones);
 
894
  font->write(str,maxTwilightPoints);
 
895
  font->write(str,maxStorage);
 
896
  font->write(str,maxFunctionDefs);
 
897
  font->write(str,maxInstructionDefs);
 
898
  font->write(str,maxStackElements);
 
899
  font->write(str,maxSizeOfInstructions);
 
900
  font->write(str,maxComponentElements);
 
901
  font->write(str,maxComponentDepth);
 
902
}
 
903
 
 
904
unsigned long PDFFTrueTypeFont::Maxp::checkSum()
 
905
{
 
906
  unsigned long sum = 0;
 
907
 
 
908
  sum += version;
 
909
  sum += numGlyphs << 16;
 
910
  sum += maxPoints & 0xffff;
 
911
  sum += maxContours << 16;
 
912
  sum += maxCompositePoints & 0xffff;
 
913
  sum += maxCompositeContours << 16;
 
914
  sum += maxZones & 0xffff;
 
915
  sum += maxTwilightPoints << 16;
 
916
  sum += maxStorage & 0xffff;
 
917
  sum += maxFunctionDefs << 16;
 
918
  sum += maxInstructionDefs & 0xffff;
 
919
  sum += maxStackElements << 16;
 
920
  sum += maxSizeOfInstructions & 0xffff;
 
921
  sum += maxComponentElements << 16;
 
922
  sum += maxComponentDepth & 0xffff;
 
923
  return sum;
 
924
}
 
925
 
 
926
void PDFFTrueTypeFont::TableDirectory::output(PDFFTrueTypeFont *font,
 
927
  P2POutputStream *str)
 
928
{
 
929
  font->write(str,tag);
 
930
  font->write(str,checkSum);
 
931
  font->write(str,offset);
 
932
  font->write(str,length);
 
933
}
 
934
 
 
935
unsigned long PDFFTrueTypeFont::TableDirectory::calcCheckSum()
 
936
{
 
937
  unsigned long sum = 0;
 
938
 
 
939
  sum += tag;
 
940
  sum += checkSum;
 
941
  sum += offset;
 
942
  sum += length;
 
943
  return sum;
 
944
}
 
945
#endif
 
946
 
 
947
int PDFFTrueTypeFont::setupCmap()
 
948
{
 
949
  ULONG cmapTable;
 
950
  USHORT numCMTables;
 
951
  unsigned int i;
 
952
  USHORT format = 0;
 
953
  unsigned int format4Offset = 0;
 
954
 
 
955
  if (cmap != 0) return 0; /* already setup */
 
956
  if (getTable(TAG_CMAP,&cmapTable) < 0) {
 
957
    p2pError(-1,const_cast<char *>("cmap table not found in font file %s"),
 
958
      fileName);
 
959
    return -1;
 
960
  }
 
961
  setOffset(cmapTable);
 
962
  skip<USHORT>(); // skip version
 
963
  read(&numCMTables);
 
964
 
 
965
  /* find unicode table */
 
966
  /* NOTICE: only support, Microsoft Unicode or platformID == 0 */
 
967
  for (i = 0;i < numCMTables;i++) {
 
968
    USHORT platformID, encodingID;
 
969
    ULONG subtable;
 
970
 
 
971
    read(&platformID);
 
972
    read(&encodingID);
 
973
    read(&subtable);
 
974
    if ((platformID == 3 /* Microsoft */ && encodingID == 1 /* Unicode */)
 
975
        || platformID == 0) {
 
976
      unsigned long old = getOffset(); /* save current offset */
 
977
 
 
978
      setOffset(subtable+cmapTable);
 
979
      read(&format);
 
980
      if (format == 4) {
 
981
        /* found , but continue searching for format 12 */
 
982
        format4Offset = getOffset();
 
983
      }
 
984
      setOffset(old); /* restore old offset */
 
985
    } else if ((platformID == 3 /* Microsoft */ && encodingID == 10 /* UCS-4 */)
 
986
        || platformID == 0) {
 
987
      unsigned long old = getOffset(); /* save current offset */
 
988
 
 
989
      setOffset(subtable+cmapTable);
 
990
      read(&format);
 
991
      if (format == 12) {
 
992
        /* found */
 
993
        break;
 
994
      }
 
995
      if (format == 4) {
 
996
        /* found , but continue searching for format 12 */
 
997
        format4Offset = getOffset();
 
998
      }
 
999
      setOffset(old); /* restore old offset */
 
1000
    }
 
1001
  }
 
1002
  if (i >= numCMTables && format4Offset == 0) {
 
1003
    /* not found */
 
1004
    p2pError(-1,const_cast<char *>("cmap table: Microsoft, Unicode, format 4 or 12 subtable not found in font file %s"),fileName);
 
1005
    return -1;
 
1006
  }
 
1007
  if (format == 12) {
 
1008
    cmap = new CmapFormat12();
 
1009
    cmap->read(this);
 
1010
  } else {
 
1011
    /* format 4 */
 
1012
    setOffset(format4Offset);
 
1013
    cmap = new CmapFormat4();
 
1014
    cmap->read(this);
 
1015
  }
 
1016
 
 
1017
  return 0;
 
1018
}
 
1019
 
 
1020
#ifdef PDFTOPDF
 
1021
unsigned long PDFFTrueTypeFont::getGID(unsigned long unicode, int wmode, int whole)
 
1022
#else
 
1023
unsigned long PDFFTrueTypeFont::getGID(unsigned long unicode, int wmode)
 
1024
#endif
 
1025
{
 
1026
  USHORT gid = 0;
 
1027
 
 
1028
  if (cmap == 0) return 0;
 
1029
 
 
1030
//fprintf(stderr,"DEBUG:getGID %d\n",code);
 
1031
  gid = cmap->getGID(this, unicode);
 
1032
 
 
1033
  if (wmode && gid != 0) {
 
1034
    gid = mapToVertGID(unicode,gid);
 
1035
  }
 
1036
 
 
1037
#ifdef PDFTOPDF
 
1038
  if (!whole) gid = mapGID(gid);
 
1039
#endif
 
1040
  return gid;
 
1041
}
 
1042
 
 
1043
unsigned long PDFFTrueTypeFont::CmapFormat4::getGID(PDFFTrueTypeFont *font,
 
1044
   unsigned long unicode)
 
1045
{
 
1046
  USHORT gid = 0;
 
1047
  int a = -1;
 
1048
  int b = segCount - 1;
 
1049
  int m;
 
1050
 
 
1051
  if (unicode > endCode[b]) {
 
1052
    /* segment not found */
 
1053
    /* illegal format */
 
1054
    return 0;
 
1055
  }
 
1056
  while (b - a > 1) {
 
1057
    m = (a+b)/2;
 
1058
    if (endCode[m] < unicode) {
 
1059
      a = m;
 
1060
    } else {
 
1061
      b = m;
 
1062
    }
 
1063
  }
 
1064
 
 
1065
  if (unicode >= startCode[b]) {
 
1066
    if (idRangeOffset[b] != 0) {
 
1067
      ULONG off = idRangeOffsetTop + b*2
 
1068
          + idRangeOffset[b]
 
1069
          + (unicode - startCode[b])*2;
 
1070
      font->read(off,&gid);
 
1071
      if (gid != 0) gid += idDelta[b];
 
1072
    } else {
 
1073
      gid = unicode + idDelta[b];
 
1074
    }
 
1075
  }
 
1076
  return gid;
 
1077
}
 
1078
 
 
1079
void PDFFTrueTypeFont::CmapFormat4::read(PDFFTrueTypeFont *font)
 
1080
{
 
1081
  unsigned int i;
 
1082
 
 
1083
  /* read subtable */
 
1084
  font->read(&length);
 
1085
  font->read(&language);
 
1086
  font->read(&segCountX2);
 
1087
  segCount = segCountX2/2;
 
1088
  font->read(&searchRange);
 
1089
  font->read(&entrySelector);
 
1090
  font->read(&rangeShift);
 
1091
  endCode = new USHORT[segCount];
 
1092
  for (i = 0;i < segCount;i++) {
 
1093
    font->read(&(endCode[i]));
 
1094
  }
 
1095
  font->skip<USHORT>(); // skip reservedPad 
 
1096
  startCode = new USHORT[segCount];
 
1097
  for (i = 0;i < segCount;i++) {
 
1098
    font->read(&(startCode[i]));
 
1099
  }
 
1100
  idDelta = new SHORT[segCount];
 
1101
  for (i = 0;i < segCount;i++) {
 
1102
    font->read(&(idDelta[i]));
 
1103
  }
 
1104
  idRangeOffsetTop = font->getOffset();
 
1105
  idRangeOffset = new USHORT[segCount];
 
1106
  for (i = 0;i < segCount;i++) {
 
1107
    font->read(&(idRangeOffset[i]));
 
1108
  }
 
1109
}
 
1110
 
 
1111
unsigned long PDFFTrueTypeFont::CmapFormat12::getGID(PDFFTrueTypeFont *font,
 
1112
   unsigned long unicode)
 
1113
{
 
1114
  unsigned long gid = 0;
 
1115
  int a = -1;
 
1116
  int b = nGroups - 1;
 
1117
  int m;
 
1118
 
 
1119
  if (unicode > endCharCode[b]) {
 
1120
    /* segment not found */
 
1121
    /* illegal format */
 
1122
    return 0;
 
1123
  }
 
1124
  while (b - a > 1) {
 
1125
    m = (a+b)/2;
 
1126
    if (endCharCode[m] < unicode) {
 
1127
      a = m;
 
1128
    } else {
 
1129
      b = m;
 
1130
    }
 
1131
  }
 
1132
 
 
1133
  if (unicode >= startCharCode[b]) {
 
1134
    gid = startGlyphID[b] + unicode - startCharCode[b];
 
1135
  }
 
1136
  return gid;
 
1137
}
 
1138
 
 
1139
void PDFFTrueTypeFont::CmapFormat12::read(PDFFTrueTypeFont *font)
 
1140
{
 
1141
  unsigned int i;
 
1142
 
 
1143
  /* read subtable */
 
1144
  font->skip<USHORT>(); // skip reservedPad 
 
1145
  font->read(&length);
 
1146
  font->read(&language);
 
1147
  font->read(&nGroups);
 
1148
 
 
1149
  startCharCode = new ULONG[nGroups];
 
1150
  endCharCode = new ULONG[nGroups];
 
1151
  startGlyphID = new ULONG[nGroups];
 
1152
  for (i = 0;i < nGroups;i++) {
 
1153
    font->read(&(startCharCode[i]));
 
1154
    font->read(&(endCharCode[i]));
 
1155
    font->read(&(startGlyphID[i]));
 
1156
  }
 
1157
}
 
1158
 
 
1159
int PDFFTrueTypeFont::setOffsetTable(unsigned int faceIndexA)
 
1160
{
 
1161
  char *ext;
 
1162
 
 
1163
  offsetTable = 0;
 
1164
  /* check if file is TTC */
 
1165
  if ((ext = strrchr(fileName,'.')) != 0 && strncasecmp(ext,".ttc",4) == 0) {
 
1166
    /* TTC file */
 
1167
    /* set offsetTable */
 
1168
    TAG TTCTag;
 
1169
    ULONG numFonts;
 
1170
 
 
1171
    setOffset(0);
 
1172
    read(&TTCTag);
 
1173
    if (TTCTag != TAG_TTC) {
 
1174
      p2pError(-1,const_cast<char *>("Illegal TTCTag:0x%08lx of TTC file:%s"),
 
1175
        TTCTag,fileName);
 
1176
      return -1;
 
1177
    }
 
1178
    skip<ULONG>(); /* skip version */
 
1179
    read(&numFonts);
 
1180
    if (numFonts <= faceIndexA) {
 
1181
      p2pError(-1,const_cast<char *>("Too large faceIndex:%d of TTC file:%s : faces=%ld"),
 
1182
        faceIndexA,fileName,numFonts);
 
1183
      return -1;
 
1184
    }
 
1185
    advance(sizeof(ULONG)*faceIndexA); /* skip to the element */
 
1186
    read(&offsetTable);
 
1187
  }
 
1188
  return 0;
 
1189
}
 
1190
 
 
1191
PDFFTrueTypeFont::PDFFTrueTypeFont()
 
1192
{
 
1193
#ifdef PDFTOPDF
 
1194
  outputLength = 0;
 
1195
  GIDMap = 0;
 
1196
  GIDMapSize = 0;
 
1197
  maxGID = 0;
 
1198
  glyf = 0;
 
1199
  glyfSize = 0;
 
1200
  cGlyfIndex = 0;
 
1201
  hmtx = 0;
 
1202
  hmtxSize = 0;
 
1203
  loca = 0;
 
1204
  locaSize = 0;
 
1205
  locaEntrySize = 0;
 
1206
  tDir = new TableDirectory [TDIR_LEN];
 
1207
  orgTDir = new TableDirectory [TDIR_LEN];
 
1208
#endif
 
1209
  cmap = 0;
 
1210
  top = 0;
 
1211
  offset = 0;
 
1212
  fileName = 0;
 
1213
  fileLength = 0;
 
1214
  fontFileFD = -1;
 
1215
  featureTable = 0;
 
1216
  lookupList = 0;
 
1217
  fontName = 0;
 
1218
  numTables = 0;
 
1219
  scriptTag = 0;
 
1220
}
 
1221
 
 
1222
UGooString *PDFFTrueTypeFont::getFontName()
 
1223
{
 
1224
  ULONG nameTable;
 
1225
  USHORT count;
 
1226
  USHORT stringOffset;
 
1227
  unsigned int i;
 
1228
 
 
1229
  if (fontName != 0) return fontName;
 
1230
  if (getTable(TAG_NAME,&nameTable) < 0) {
 
1231
    p2pError(-1,const_cast<char *>("name table not found in font file %s"),
 
1232
       fileName);
 
1233
    return 0;
 
1234
  }
 
1235
  setOffset(nameTable);
 
1236
  skip<USHORT>(); /* skip format */
 
1237
  read(&count);
 
1238
  read(&stringOffset);
 
1239
  for (i = 0;i < count;i++) {
 
1240
    USHORT nameID;
 
1241
    USHORT length;
 
1242
    USHORT so;
 
1243
    USHORT platformID;
 
1244
    USHORT encodingID;
 
1245
    USHORT languageID;
 
1246
 
 
1247
    //advance(sizeof(USHORT)*3); /* skip to nameID */
 
1248
    read(&platformID);
 
1249
    read(&encodingID);
 
1250
    read(&languageID);
 
1251
    read(&nameID);
 
1252
    read(&length);
 
1253
    read(&so);
 
1254
    if (nameID == 6) {
 
1255
      /* PostScript name */
 
1256
      if (platformID == 0 /* Unicode */ || platformID == 3 /* Microsoft */) {
 
1257
         /* Unicode */
 
1258
        Unicode *p = new Unicode[length/2];
 
1259
        unsigned int j;
 
1260
 
 
1261
        setOffset(nameTable+stringOffset+so);
 
1262
        for (j = 0;j < length/2;j++) {
 
1263
          USHORT u;
 
1264
          read(&u);
 
1265
          p[j] = u;
 
1266
        }
 
1267
        fontName = new UGooString(p,length/2);
 
1268
        return fontName;
 
1269
      } else {
 
1270
        unsigned int j;
 
1271
        Unicode *p = new Unicode[length];
 
1272
        unsigned char *q = top+nameTable+stringOffset+so;
 
1273
 
 
1274
        for (j = 0;j < length;j++) {
 
1275
          p[j] = q[j];
 
1276
        }
 
1277
        fontName = new UGooString(p,length);
 
1278
        return fontName;
 
1279
      }
 
1280
    }
 
1281
  }
 
1282
  return 0;
 
1283
}
 
1284
 
 
1285
int PDFFTrueTypeFont::init(const char *fileNameA, unsigned int faceIndexA)
 
1286
{
 
1287
  struct stat sbuf;
 
1288
  Fixed sfntVersion;
 
1289
 
 
1290
  offsetTable = 0;
 
1291
  fileName = new char [strlen(fileNameA)+1];
 
1292
  strcpy(fileName,fileNameA);
 
1293
  if ((fontFileFD = open(fileName,O_RDONLY)) < 0) {
 
1294
    p2pError(-1,const_cast<char *>("Can't open font file %s"),fileName);
 
1295
    return -1;
 
1296
  }
 
1297
  if (fstat(fontFileFD,&sbuf) < 0) {
 
1298
    p2pError(-1,const_cast<char *>("Can't get stat of font file %s"),fileName);
 
1299
    goto error_end;
 
1300
  }
 
1301
  fileLength = sbuf.st_size;
 
1302
  if ((top = reinterpret_cast<unsigned char *>(
 
1303
      mmap(0,fileLength,PROT_READ,MAP_PRIVATE,fontFileFD,0))) == 0) {
 
1304
    p2pError(-1,const_cast<char *>("mmap font file %s failed"),fileName);
 
1305
    goto error_end;
 
1306
  }
 
1307
  if (setOffsetTable(faceIndexA) < 0) goto error_end2;
 
1308
  setOffset(offsetTable);
 
1309
  read(&sfntVersion);
 
1310
  if (sfntVersion != 0x00010000) {
 
1311
    p2pError(-1,const_cast<char *>("Illegal sfnt version in font file %s"),
 
1312
      fileName);
 
1313
    goto error_end2;
 
1314
  }
 
1315
  read(&numTables);
 
1316
  return 0;
 
1317
 
 
1318
error_end2:
 
1319
  munmap((char *)top,fileLength);
 
1320
error_end:
 
1321
  close(fontFileFD);
 
1322
  fontFileFD = -1;
 
1323
  return -1;
 
1324
}
 
1325
 
 
1326
PDFFTrueTypeFont::~PDFFTrueTypeFont()
 
1327
{
 
1328
#ifdef PDFTOPDF
 
1329
  if (cmap != 0) delete cmap;
 
1330
  if (GIDMap != 0) delete[] GIDMap;
 
1331
  if (tDir != 0) delete[] tDir;
 
1332
  if (orgTDir != 0) delete[] orgTDir;
 
1333
  freeNewTables();
 
1334
#endif
 
1335
 
 
1336
  if (top != 0) {
 
1337
    munmap((char *)top,fileLength);
 
1338
  }
 
1339
  if (fontFileFD >= 0) close(fontFileFD);
 
1340
  if (fileName != 0) delete[] fileName;
 
1341
  if (fontName != 0) delete fontName;
 
1342
}
 
1343
 
 
1344
unsigned long PDFFTrueTypeFont::charToTag(const char *tagName)
 
1345
{
 
1346
  int n = strlen(tagName);
 
1347
  unsigned long tag = 0;
 
1348
  int i;
 
1349
 
 
1350
  if (n > 4) n = 4;
 
1351
  for (i = 0;i < n;i++) {
 
1352
    tag <<= 8;
 
1353
    tag |= tagName[i] & 0xff;
 
1354
  }
 
1355
  for (;i < 4;i++) {
 
1356
    tag <<= 8;
 
1357
    tag |= ' ';
 
1358
  }
 
1359
  return tag;
 
1360
}
 
1361
 
 
1362
/*
 
1363
  setup GSUB table data
 
1364
  Only supporting vertical text substitution.
 
1365
*/
 
1366
int PDFFTrueTypeFont::setupGSUB(const char *tagName)
 
1367
{
 
1368
  ULONG gsubTable;
 
1369
  unsigned int i;
 
1370
  USHORT scriptList, featureList;
 
1371
  USHORT scriptCount;
 
1372
  TAG tag;
 
1373
  USHORT scriptTable;
 
1374
  USHORT langSys;
 
1375
  USHORT featureCount;
 
1376
  USHORT featureIndex;
 
1377
  USHORT ftable = 0;
 
1378
  USHORT llist;
 
1379
  ULONG oldOffset;
 
1380
  ULONG ttag;
 
1381
 
 
1382
  if (tagName == 0) {
 
1383
    featureTable = 0;
 
1384
    return 0;
 
1385
  }
 
1386
  ttag = charToTag(tagName);
 
1387
  if (featureTable != 0 && ttag == scriptTag) {
 
1388
    /* already setup GSUB */
 
1389
    return 0;
 
1390
  }
 
1391
  scriptTag = ttag;
 
1392
  /* read GSUB Header */
 
1393
  if (getTable(TAG_GSUB,&gsubTable) < 0) {
 
1394
    return 0; /* GSUB table not found */
 
1395
  }
 
1396
  setOffset(gsubTable);
 
1397
  skip<Fixed>(); // skip version
 
1398
  read(&scriptList);
 
1399
  read(&featureList);
 
1400
  read(&llist);
 
1401
 
 
1402
  lookupList = llist+gsubTable; /* change to offset from top of file */
 
1403
  /* read script list table */
 
1404
  setOffset(gsubTable+scriptList);
 
1405
  read(&scriptCount);
 
1406
  /* find  script */
 
1407
  for (i = 0;i < scriptCount;i++) {
 
1408
    read(&tag);
 
1409
    read(&scriptTable);
 
1410
    if (tag == scriptTag) {
 
1411
      /* found */
 
1412
      break;
 
1413
    }
 
1414
  }
 
1415
  if (i >= scriptCount) {
 
1416
    /* not found */
 
1417
    return 0;
 
1418
  }
 
1419
 
 
1420
  /* read script table */
 
1421
  /* use default language system */
 
1422
  setOffset(gsubTable+scriptList+scriptTable);
 
1423
  read(&langSys); /* default language system */
 
1424
 
 
1425
  /* read LangSys table */
 
1426
  if (langSys == 0) {
 
1427
    /* no ldefault LangSys */
 
1428
    return 0;
 
1429
  }
 
1430
 
 
1431
  setOffset(gsubTable+scriptList+scriptTable+langSys);
 
1432
  skip<USHORT>(); /* skip LookupOrder */
 
1433
  read(&featureIndex); /* ReqFeatureIndex */
 
1434
  if (featureIndex != 0xffff) {
 
1435
    oldOffset = getOffset();
 
1436
    /* read feature record */
 
1437
    setOffset(gsubTable+featureList);
 
1438
 
 
1439
    read(&featureCount);
 
1440
    setOffset(gsubTable+featureList+sizeof(USHORT)+
 
1441
       featureIndex*(sizeof(TAG)+sizeof(USHORT)));
 
1442
    read(&tag);
 
1443
    if (tag == TAG_VRT2) {
 
1444
      /* vrt2 is preferred, overwrite vert */
 
1445
      read(&ftable);
 
1446
      /* convert to offset from file top */
 
1447
      featureTable = ftable+gsubTable+featureList;
 
1448
      return 0;
 
1449
    } else if (tag == TAG_VERT) {
 
1450
      read(&ftable);
 
1451
    }
 
1452
    setOffset(oldOffset); /* restore offset */
 
1453
  }
 
1454
  read(&featureCount);
 
1455
  /* find 'vrt2' or 'vert' feature */
 
1456
  for (i = 0;i < featureCount;i++) {
 
1457
    read(&featureIndex);
 
1458
    oldOffset = getOffset();
 
1459
    /* read feature record */
 
1460
    setOffset(gsubTable+featureList+sizeof(USHORT)+
 
1461
       featureIndex*(sizeof(TAG)+sizeof(USHORT)));
 
1462
    read(&tag);
 
1463
    if (tag == TAG_VRT2) {
 
1464
      /* vrt2 is preferred, overwrite vert */
 
1465
      read(&ftable);
 
1466
      break;
 
1467
    } else if (ftable == 0 && tag == TAG_VERT) {
 
1468
      read(&ftable);
 
1469
    }
 
1470
    setOffset(oldOffset); /* restore offset */
 
1471
  }
 
1472
  if (ftable == 0) {
 
1473
    /* vert nor vrt2 are not found */
 
1474
    return 0;
 
1475
  }
 
1476
  /* convert to offset from file top */
 
1477
  featureTable = ftable+gsubTable+featureList;
 
1478
  return 0;
 
1479
}
 
1480
 
 
1481
int PDFFTrueTypeFont::getTableDirEntry(TAG tableTag, TableDirectory *ent)
 
1482
{
 
1483
  unsigned int i;
 
1484
 
 
1485
 /* set to the top of Table Directory entiries */
 
1486
  setOffset(offsetTable+OFFSET_TABLE_LEN);
 
1487
  for (i = 0;i < numTables;i++) {
 
1488
    ULONG tag;
 
1489
 
 
1490
    read(&tag);
 
1491
    if (tag == tableTag) {
 
1492
      /* found */
 
1493
      ent->tag = tag;
 
1494
      read(&(ent->checkSum));
 
1495
      read(&(ent->offset));
 
1496
      read(&(ent->length));
 
1497
      return 0;
 
1498
    }
 
1499
    advance(sizeof(ULONG)*3); /* skip to next entry */
 
1500
  }
 
1501
  return -1; /* not found */
 
1502
}
 
1503
 
 
1504
int PDFFTrueTypeFont::getTable(TAG tableTag, ULONG *tableOffset,
 
1505
  ULONG *tableLength)
 
1506
{
 
1507
  TableDirectory ent;
 
1508
 
 
1509
  if (getTableDirEntry(tableTag,&ent) < 0) {
 
1510
    /* not found */
 
1511
    return -1;
 
1512
  }
 
1513
  if (tableOffset != 0) {
 
1514
    *tableOffset = ent.offset;
 
1515
  }
 
1516
  if (tableLength != 0) {
 
1517
    *tableLength = ent.length;
 
1518
  }
 
1519
  return 0;
 
1520
}
 
1521
 
 
1522
unsigned long PDFFTrueTypeFont::doMapToVertGID(unsigned long orgGID)
 
1523
{
 
1524
  USHORT lookupCount;
 
1525
  USHORT lookupListIndex;
 
1526
  ULONG i;
 
1527
  unsigned long gid = 0;
 
1528
 
 
1529
  setOffset(featureTable+sizeof(USHORT));
 
1530
  read(&lookupCount);
 
1531
  for (i = 0;i < lookupCount;i++) {
 
1532
    read(&lookupListIndex);
 
1533
    if ((gid = scanLookupList(lookupListIndex,orgGID)) != 0) {
 
1534
      break;
 
1535
    }
 
1536
  }
 
1537
  return gid;
 
1538
}
 
1539
 
 
1540
unsigned long PDFFTrueTypeFont::mapToVertGID(unsigned long code,
 
1541
  unsigned long orgGID)
 
1542
{
 
1543
  unsigned long mapped;
 
1544
  //unsigned long i;
 
1545
 
 
1546
  if (featureTable == 0) return orgGID;
 
1547
  if ((mapped = doMapToVertGID(orgGID)) != 0) {
 
1548
//fprintf(stderr,"DEBUG:GSUB map %d to %d\n",orgGID,mapped);
 
1549
    return mapped;
 
1550
  }
 
1551
  return orgGID;
 
1552
}
 
1553
 
 
1554
unsigned long PDFFTrueTypeFont::scanLookupList(USHORT listIndex,
 
1555
  unsigned long orgGID)
 
1556
{
 
1557
  USHORT lookupTable;
 
1558
  USHORT subTableCount;
 
1559
  USHORT subTable;
 
1560
  ULONG i;
 
1561
  unsigned long gid = 0;
 
1562
  ULONG oldOffset = getOffset();
 
1563
 
 
1564
  if (lookupList == 0) return 0; /* no lookup list */
 
1565
  setOffset(lookupList+sizeof(USHORT)+listIndex*sizeof(USHORT));
 
1566
  read(&lookupTable);
 
1567
  /* read lookup table */
 
1568
  setOffset(lookupList+lookupTable);
 
1569
  skip<USHORT>(); /* skip LookupType */
 
1570
  skip<USHORT>(); /* skip LookupFlag */
 
1571
  read(&subTableCount);
 
1572
  for (i = 0;i < subTableCount;i++) {
 
1573
    read(&subTable);
 
1574
    if ((gid = scanLookupSubTable(lookupList+lookupTable+subTable,orgGID))
 
1575
         != 0) break;
 
1576
  }
 
1577
  setOffset(oldOffset); /* restore offset */
 
1578
  return gid;
 
1579
}
 
1580
 
 
1581
unsigned long PDFFTrueTypeFont::scanLookupSubTable(ULONG subTable,
 
1582
  unsigned long orgGID)
 
1583
{
 
1584
  USHORT format;
 
1585
  USHORT coverage;
 
1586
  SHORT delta;
 
1587
  SHORT glyphCount;
 
1588
  GlyphID substitute;
 
1589
  unsigned long gid = 0;
 
1590
  int coverageIndex;
 
1591
  ULONG oldOffset = getOffset();
 
1592
 
 
1593
  setOffset(subTable);
 
1594
  read(&format);
 
1595
  read(&coverage);
 
1596
  if ((coverageIndex =
 
1597
     checkGIDInCoverage(subTable+coverage,orgGID)) >= 0) {
 
1598
    switch (format) {
 
1599
    case 1:
 
1600
      /* format 1 */
 
1601
      read(&delta);
 
1602
      gid = orgGID+delta;
 
1603
      break;
 
1604
    case 2:
 
1605
      /* format 2 */
 
1606
      read(&glyphCount);
 
1607
      if (glyphCount > coverageIndex) {
 
1608
        advance(coverageIndex*sizeof(GlyphID));
 
1609
        read(&substitute);
 
1610
        gid = substitute;
 
1611
      }
 
1612
      break;
 
1613
    default:
 
1614
      /* unknown format */
 
1615
      break;
 
1616
    }
 
1617
  }
 
1618
  setOffset(oldOffset); /* restore offset */
 
1619
  return gid;
 
1620
}
 
1621
 
 
1622
int PDFFTrueTypeFont::checkGIDInCoverage(ULONG coverage, unsigned long orgGID)
 
1623
{
 
1624
  int index = -1;
 
1625
  ULONG oldOffset = getOffset();
 
1626
  USHORT format;
 
1627
  USHORT count;
 
1628
  ULONG i;
 
1629
 
 
1630
  setOffset(coverage);
 
1631
  read(&format);
 
1632
  switch (format) {
 
1633
  case 1:
 
1634
    read(&count);
 
1635
    for (i = 0;i < count;i++) {
 
1636
      GlyphID gid;
 
1637
 
 
1638
      read(&gid);
 
1639
      if (gid == orgGID) {
 
1640
        /* found */
 
1641
        index = i;
 
1642
        break;
 
1643
      } else if (gid > orgGID) {
 
1644
        /* not found */
 
1645
        break;
 
1646
      }
 
1647
    }
 
1648
    break;
 
1649
  case 2:
 
1650
    read(&count);
 
1651
    for (i = 0;i < count;i++) {
 
1652
      GlyphID startGID, endGID;
 
1653
      USHORT startIndex;
 
1654
 
 
1655
      read(&startGID);
 
1656
      read(&endGID);
 
1657
      read(&startIndex);
 
1658
      if (startGID <= orgGID && orgGID <= endGID) {
 
1659
        /* found */
 
1660
        index = startIndex+orgGID-startGID;
 
1661
        break;
 
1662
      } else if (orgGID <= endGID) {
 
1663
        /* not found */
 
1664
        break;
 
1665
      }
 
1666
    }
 
1667
    break;
 
1668
  default:
 
1669
    break;
 
1670
  }
 
1671
  setOffset(oldOffset); /* restore offset */
 
1672
  return index;
 
1673
}