~ubuntu-branches/debian/experimental/cups-filters/experimental

« back to all changes in this revision

Viewing changes to 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 = static_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(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(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
 
}