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

« back to all changes in this revision

Viewing changes to pdftopdf/P2PFont.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
 
 P2PFont.cc
27
 
 pdftopdf font manager
28
 
*/
29
 
 
30
 
#include <config.h>
31
 
#include <string.h>
32
 
#include <sys/types.h>
33
 
#include <unistd.h>
34
 
#include <fcntl.h>
35
 
#include "goo/gmem.h"
36
 
#include "P2PFont.h"
37
 
#include "GfxFont.h"
38
 
#include "P2PError.h"
39
 
#include "P2PXRef.h"
40
 
#include "BuiltinFontTables.h"
41
 
#include "P2PCMap.h"
42
 
#include "GlobalParams.h"
43
 
#include "PDFFTrueTypeFont.h"
44
 
#include "P2PDoc.h"
45
 
#include "CharCodeToUnicode.h"
46
 
#include "P2PCharCodeToUnicode.h"
47
 
 
48
 
/* Size of CID (bytes) */
49
 
#define CID_SIZE 2
50
 
#define CIDTOGID_SIZE (1 << (8*CID_SIZE))
51
 
 
52
 
int P2PFontFile::nFontFiles = 0;
53
 
int P2PFontFile::fontFileListSize = 0;
54
 
P2PFontFile **P2PFontFile::fontFileList = 0;
55
 
char P2PFontFile::nextTag[7] = "AAAAA@";
56
 
 
57
 
#define FONT_FILE_LIST_INC 256
58
 
 
59
 
 
60
 
P2PCIDToGID::P2PCIDToGID(P2PFontFile *fontFileA, GBool wmodeA)
61
 
{
62
 
  fontFile = fontFileA;
63
 
  wmode = wmodeA;
64
 
}
65
 
 
66
 
P2PCIDToGID::~P2PCIDToGID()
67
 
{
68
 
  /* must not delete fontFile */
69
 
}
70
 
 
71
 
void P2PCIDToGID::output(P2POutputStream *str, XRef *xref)
72
 
{
73
 
  P2PObj *lenObj = new P2PObj();
74
 
  int cp;
75
 
  int len;
76
 
 
77
 
  P2PXRef::put(lenObj);
78
 
  outputBegin(str);
79
 
  str->puts("<< /Length ");
80
 
  lenObj->outputRef(str);
81
 
  if (P2PDoc::options.fontCompress && str->canDeflate()) {
82
 
    str->puts(" /Filter /FlateDecode ");
83
 
  }
84
 
  str->puts(" >>\n"
85
 
        "stream\n");
86
 
  cp = str->getPosition(); /* start position */
87
 
  if (P2PDoc::options.fontCompress) str->startDeflate();
88
 
  fontFile->outputCIDToGID(wmode,str,xref);
89
 
  if (P2PDoc::options.fontCompress) str->endDeflate();
90
 
  len = str->getPosition() - cp; /* calculate length */
91
 
  str->puts("\nendstream\n");
92
 
  outputEnd(str);
93
 
 
94
 
  /* output length */
95
 
  lenObj->outputBegin(str);
96
 
  str->printf("%d\n",len);
97
 
  lenObj->outputEnd(str);
98
 
}
99
 
 
100
 
char *P2PFontFile::getNextTag()
101
 
{
102
 
  int i;
103
 
 
104
 
  for (i = 5;i >= 0;i--) {
105
 
    int c = nextTag[i];
106
 
 
107
 
    nextTag[i] = ++c;
108
 
    if (c <= 'Z') break;
109
 
    nextTag[i] = 'A';
110
 
  }
111
 
  return nextTag;
112
 
}
113
 
 
114
 
P2PFontFile *P2PFontFile::getFontFile(GooString *fileNameA,
115
 
  GfxFont *fontA, GfxFontType typeA, int faceIndexA)
116
 
{
117
 
  int i;
118
 
 
119
 
  for (i = 0;i < nFontFiles;i++) {
120
 
    if (fontFileList[i] != 0 && strcmp(fileNameA->getCString(),
121
 
         fontFileList[i]->getFileName()->getCString()) == 0
122
 
         && faceIndexA == fontFileList[i]->faceIndex) {
123
 
      return fontFileList[i];
124
 
    }
125
 
  }
126
 
  if (nFontFiles >= fontFileListSize) {
127
 
    int size = fontFileListSize + FONT_FILE_LIST_INC;
128
 
    P2PFontFile **list;
129
 
 
130
 
    list = new P2PFontFile *[size];
131
 
    for (i = 0;i < nFontFiles;i++) {
132
 
      list[i] = fontFileList[i];
133
 
    }
134
 
    for (;i < size;i++) {
135
 
      list[i] = 0;
136
 
    }
137
 
    delete fontFileList;
138
 
    fontFileList = list;
139
 
    fontFileListSize = size;
140
 
  }
141
 
  fontFileList[nFontFiles] = new P2PFontFile(fileNameA,fontA,typeA,faceIndexA);
142
 
  P2PXRef::put(fontFileList[nFontFiles]);
143
 
  return fontFileList[nFontFiles++];
144
 
}
145
 
 
146
 
P2PFontFile::P2PFontFile(GooString *fileNameA, GfxFont *fontA,
147
 
  GfxFontType typeA, int faceIndexA)
148
 
{
149
 
  fileName = new GooString(fileNameA);
150
 
  font = fontA;
151
 
  type = typeA;
152
 
  faceIndex = faceIndexA;
153
 
  CIDToGID = 0;
154
 
  CIDToGID_V = 0;
155
 
  maxRefCID = 0;
156
 
  fontName = 0;
157
 
  setSecondPhase(gTrue);
158
 
  if (type == fontCIDType2) {
159
 
    charRefTable = new unsigned char[CIDTOGID_SIZE/8];
160
 
    memset(charRefTable,0,CIDTOGID_SIZE/8);
161
 
  } else {
162
 
    charRefTable = 0;
163
 
  }
164
 
  if (type == fontCIDType2 || type == fontTrueType) {
165
 
    UGooString *fn;
166
 
 
167
 
    tfont.init(fileName->getCString(),faceIndex);
168
 
    tfont.setupCmap();
169
 
    fn = tfont.getFontName();
170
 
    if (fn != 0) {
171
 
      if (type == fontCIDType2 && !P2PDoc::options.fontEmbeddingWhole) {
172
 
        char *tag;
173
 
        Unicode *p;
174
 
        int len;
175
 
        int tagLen;
176
 
        int fnLen;
177
 
        int i,j;
178
 
        Unicode *u;
179
 
 
180
 
        tag = getNextTag();
181
 
        tagLen = strlen(tag);
182
 
        fnLen = fn->getLength();
183
 
        len = tagLen+1+fnLen;
184
 
        /* use gmalloc because UGooString uses it */
185
 
        p = static_cast<Unicode *>(gmalloc(len*sizeof(Unicode)));
186
 
        /* copy tag */
187
 
        for (i = 0;i < tagLen;i++) {
188
 
          p[i] = tag[i];
189
 
        }
190
 
        p[i++] = '+';
191
 
        /* copy font name */
192
 
        u = fn->unicode();
193
 
        for (j = 0;j < fnLen;j++) {
194
 
          p[i++] = u[j];
195
 
        }
196
 
        fontName = new UGooString(p,len);
197
 
      } else {
198
 
        fontName = new UGooString(*fn);
199
 
      }
200
 
    }
201
 
  }
202
 
}
203
 
 
204
 
P2PCIDToGID *P2PFontFile::getCIDToGID(GBool wmode)
205
 
{
206
 
  P2PCIDToGID **p;
207
 
 
208
 
  if (wmode) {
209
 
    p = &CIDToGID_V;
210
 
  } else {
211
 
    p = &CIDToGID;
212
 
  }
213
 
  if (*p == 0) {
214
 
    *p = new P2PCIDToGID(this,wmode);
215
 
    P2PXRef::put(*p);
216
 
  }
217
 
  return *p;
218
 
}
219
 
 
220
 
P2PFontFile::~P2PFontFile()
221
 
{
222
 
  if (fileName != 0) {
223
 
    delete fileName;
224
 
  }
225
 
  if (charRefTable != 0) delete[] charRefTable;
226
 
  if (fontName != 0) delete fontName;
227
 
  /* font is deleted by P2PFontDict, you must not delete it here */
228
 
  /* must not delete CIDToGID */
229
 
}
230
 
 
231
 
GBool P2PFontFile::isIdentity()
232
 
{
233
 
  /* alway false now */
234
 
  return gFalse;
235
 
}
236
 
 
237
 
void P2PFontFile::outputCIDToGID(GBool wmode, P2POutputStream *str, XRef *xref)
238
 
{
239
 
#define N_UCS_CANDIDATES 2
240
 
  /* space characters */
241
 
  static unsigned long spaces[] = {
242
 
    0x2000,0x2001,0x2002,0x2003,0x2004,0x2005,0x2006,0x2007,
243
 
    0x2008,0x2009,0x200A,0x00A0,0x200B,0x2060,0x3000,0xFEFF,
244
 
    0
245
 
  };
246
 
  static const char *adobe_cns1_cmaps[] = {
247
 
    "UniCNS-UTF32-V",
248
 
    "UniCNS-UCS2-V",
249
 
    "UniCNS-UTF32-H",
250
 
    "UniCNS-UCS2-H",
251
 
    0
252
 
  };
253
 
  static const char *adobe_gb1_cmaps[] = {
254
 
    "UniGB-UTF32-V",
255
 
    "UniGB-UCS2-V",
256
 
    "UniGB-UTF32-H",
257
 
    "UniGB-UCS2-H",
258
 
    0
259
 
  };
260
 
  static const char *adobe_japan1_cmaps[] = {
261
 
    "UniJIS-UTF32-V",
262
 
    "UniJIS-UCS2-V",
263
 
    "UniJIS-UTF32-H",
264
 
    "UniJIS-UCS2-H",
265
 
    0
266
 
  };
267
 
  static const char *adobe_japan2_cmaps[] = {
268
 
    "UniHojo-UTF32-V",
269
 
    "UniHojo-UCS2-V",
270
 
    "UniHojo-UTF32-H",
271
 
    "UniHojo-UCS2-H",
272
 
    0
273
 
  };
274
 
  static const char *adobe_korea1_cmaps[] = {
275
 
    "UniKS-UTF32-V",
276
 
    "UniKS-UCS2-V",
277
 
    "UniKS-UTF32-H",
278
 
    "UniKS-UCS2-H",
279
 
    0
280
 
  };
281
 
  static struct CMapListEntry {
282
 
    const char *collection;
283
 
    const char *scriptTag;
284
 
    const char *toUnicodeMap;
285
 
    const char **CMaps;
286
 
  } CMapList[] = {
287
 
    {
288
 
      "Adobe-CNS1",
289
 
      "kana",
290
 
      "Adobe-CNS1-UCS2",
291
 
      adobe_cns1_cmaps,
292
 
    },
293
 
    {
294
 
      "Adobe-GB1",
295
 
      "kana",
296
 
      "Adobe-GB1-UCS2",
297
 
      adobe_gb1_cmaps,
298
 
    },
299
 
    {
300
 
      "Adobe-Japan1",
301
 
      "kana",
302
 
      "Adobe-Japan1-UCS2",
303
 
      adobe_japan1_cmaps,
304
 
    },
305
 
    {
306
 
      "Adobe-Japan2",
307
 
      "kana",
308
 
      "Adobe-Japan2-UCS2",
309
 
      adobe_japan2_cmaps,
310
 
    },
311
 
    {
312
 
      "Adobe-Korea1",
313
 
      "kana",
314
 
      "Adobe-Korea1-UCS2",
315
 
      adobe_korea1_cmaps,
316
 
    },
317
 
    {
318
 
      0
319
 
    }
320
 
  };
321
 
  unsigned int i;
322
 
  Unicode *humap = 0;
323
 
  Unicode *vumap = 0;
324
 
  Unicode *tumap = 0;
325
 
 
326
 
  if (charRefTable == 0 || maxRefCID == 0) {
327
 
    str->putchar(0);
328
 
    str->putchar(0);
329
 
    return;
330
 
  }
331
 
  tfont.setupGSUB(0); /* reset GSUB */
332
 
  if (font != 0) {
333
 
    const char **cmapName;
334
 
    P2PCMap *cMap;
335
 
    CMapListEntry *lp;
336
 
    CharCodeToUnicode *octu;
337
 
 
338
 
    GfxCIDFont *cidfont = static_cast<GfxCIDFont *>(font);
339
 
    for (lp = CMapList;lp->collection != 0;lp++) {
340
 
      if (strcmp(lp->collection,cidfont->getCollection()->getCString()) == 0) {
341
 
        break;
342
 
      }
343
 
    }
344
 
    tumap = new Unicode[maxRefCID+1];
345
 
    if (lp->collection != 0) {
346
 
      GooString tname(lp->toUnicodeMap);
347
 
      P2PCharCodeToUnicode *ctu;
348
 
      if ((ctu = P2PCharCodeToUnicode::parseCMapFromFile(&tname,16)) != 0) {
349
 
        CharCode cid;
350
 
        for (cid = 0;cid <= maxRefCID ;cid++) {
351
 
          int len;
352
 
          Unicode ucodes[4];
353
 
 
354
 
          len = ctu->mapToUnicode(cid,ucodes,4);
355
 
          if (len == 1) {
356
 
            tumap[cid] = ucodes[0];
357
 
          } else {
358
 
            /* if not single character, ignore it */
359
 
            tumap[cid] = 0;
360
 
          }
361
 
        }
362
 
        delete ctu;
363
 
      }
364
 
      vumap = new Unicode[maxRefCID+1];
365
 
      memset(vumap,0,sizeof(Unicode)*(maxRefCID+1));
366
 
      humap = new Unicode[(maxRefCID+1)*N_UCS_CANDIDATES];
367
 
      memset(humap,0,sizeof(Unicode)*(maxRefCID+1)*N_UCS_CANDIDATES);
368
 
      for (cmapName = lp->CMaps;*cmapName != 0;cmapName++) {
369
 
        GooString cname(*cmapName);
370
 
 
371
 
        if ((cMap = P2PCMap::parse(&cmapCache,cidfont->getCollection(),&cname))
372
 
             != 0) {
373
 
          if (cMap->getWMode()) {
374
 
            cMap->setReverseMap(vumap,maxRefCID+1,1);
375
 
          } else {
376
 
            cMap->setReverseMap(humap,maxRefCID+1,N_UCS_CANDIDATES);
377
 
          }
378
 
          cMap->decRefCnt();
379
 
        }
380
 
      }
381
 
      tfont.setupGSUB(lp->scriptTag);
382
 
    } else {
383
 
      p2pError(-1,const_cast<char *>("Unknown character collection %s\n"),
384
 
        cidfont->getCollection()->getCString());
385
 
      if ((octu = cidfont->getToUnicode()) != 0) {
386
 
        CharCode cid;
387
 
        for (cid = 0;cid <= maxRefCID ;cid++) {
388
 
#ifdef OLD_MAPTOUNICODE
389
 
          Unicode ucode;
390
 
 
391
 
          humap[cid*N_UCS_CANDIDATES] = ucode;
392
 
#else
393
 
          Unicode *ucode = NULL;
394
 
 
395
 
          humap[cid*N_UCS_CANDIDATES] = *ucode;
396
 
#endif
397
 
          for (i = 1;i < N_UCS_CANDIDATES;i++) {
398
 
            humap[cid*N_UCS_CANDIDATES+i] = 0;
399
 
          }
400
 
        }
401
 
        octu->decRefCnt();
402
 
      }
403
 
    }
404
 
  }
405
 
  for (i = 0;i <= maxRefCID;i++) {
406
 
    Unicode unicode;
407
 
    unsigned long gid;
408
 
    int j;
409
 
 
410
 
    if ((charRefTable[i/8] & (1 << (i & (8-1)))) == 0) {
411
 
      /* not referenced CID */
412
 
      gid = 0;
413
 
    } else {
414
 
      /* referenced CID */
415
 
      unicode = 0;
416
 
      gid = 0;
417
 
      if (humap != 0) {
418
 
        for (j = 0;j < N_UCS_CANDIDATES
419
 
          && gid == 0 && (unicode = humap[i*N_UCS_CANDIDATES+j]) != 0;j++) {
420
 
          gid = tfont.getGID(unicode,gFalse,
421
 
            P2PDoc::options.fontEmbeddingWhole ? 1 : 0);
422
 
        }
423
 
      }
424
 
      if (gid == 0 && vumap != 0) {
425
 
        unicode = vumap[i];
426
 
        if (unicode != 0) {
427
 
          gid = tfont.getGID(unicode,gTrue,
428
 
            P2PDoc::options.fontEmbeddingWhole ? 1 : 0);
429
 
          if (gid == 0 && tumap != 0) {
430
 
            if ((unicode = tumap[i]) != 0) {
431
 
              gid = tfont.getGID(unicode,gTrue,
432
 
                P2PDoc::options.fontEmbeddingWhole ? 1 : 0);
433
 
            }
434
 
          }
435
 
        }
436
 
      }
437
 
      if (gid == 0 && tumap != 0) {
438
 
        if ((unicode = tumap[i]) != 0) {
439
 
            gid = tfont.getGID(unicode,gFalse,
440
 
              P2PDoc::options.fontEmbeddingWhole ? 1 : 0);
441
 
        }
442
 
      }
443
 
      if (gid == 0) {
444
 
        /* special handling space characters */
445
 
        unsigned long *p;
446
 
 
447
 
        if (humap != 0) unicode = humap[i];
448
 
        if (unicode != 0) {
449
 
          /* check if code is space character , so map code to 0x0020 */
450
 
          for (p = spaces;*p != 0;p++) {
451
 
            if (*p == unicode) {
452
 
              unicode = 0x20;
453
 
              gid = tfont.getGID(unicode,wmode,
454
 
                        P2PDoc::options.fontEmbeddingWhole ? 1 : 0);
455
 
              break;
456
 
            }
457
 
          }
458
 
        }
459
 
      }
460
 
    }
461
 
    /* output GID 
462
 
       size is 16bits.
463
 
       should output big endian format.
464
 
   */
465
 
    str->putchar((gid >> 8) & 0xff);
466
 
    str->putchar(gid & 0xff);
467
 
  }
468
 
  if (humap != 0) delete[] humap;
469
 
  if (vumap != 0) delete[] vumap;
470
 
}
471
 
 
472
 
void P2PFontFile::output(P2POutputStream *str, XRef *xref)
473
 
{
474
 
  int fd;
475
 
  char buf[BUFSIZ];
476
 
  int n;
477
 
  P2PObj *lenObj = new P2PObj();
478
 
  P2PObj *len1Obj = 0;
479
 
  int cp;
480
 
  int len,len1 = 0;
481
 
 
482
 
//  fprintf(stderr,"INFO:Embedding font file from file %s\n",
483
 
//   fileName->getCString());
484
 
  outputBegin(str);
485
 
  /* output stream dictionary */
486
 
  str->puts("<< ");
487
 
  switch (type) {
488
 
  case fontType1C:
489
 
    str->puts("/SubType /Type1C ");
490
 
    /* should output Length1, Length2, Length3 */
491
 
    break;
492
 
  case fontCIDType0C:
493
 
    str->puts("/SubType /CIDFontType0C ");
494
 
    /* should output Length1, Length2, Length3 */
495
 
    break;
496
 
  case fontTrueType:
497
 
  case fontCIDType2:
498
 
    len1Obj = new P2PObj();
499
 
    P2PXRef::put(len1Obj);
500
 
    str->puts("/Length1 ");
501
 
    len1Obj->outputRef(str);
502
 
    break;
503
 
  case fontType1:
504
 
  case fontCIDType0:
505
 
    /* should output Length1, Length2, Length3 */
506
 
    break;
507
 
  default:
508
 
    break;
509
 
  }
510
 
  P2PXRef::put(lenObj);
511
 
  str->puts("/Length ");
512
 
  lenObj->outputRef(str);
513
 
  if (P2PDoc::options.fontCompress && str->canDeflate()) {
514
 
    str->puts(" /Filter /FlateDecode ");
515
 
  }
516
 
  str->puts(" >>\n");
517
 
 
518
 
  /* output stream body */
519
 
  str->puts("stream\n");
520
 
  if (P2PDoc::options.fontCompress) str->startDeflate();
521
 
  cp = str->getPosition();
522
 
  switch (type) {
523
 
  case fontCIDType2:
524
 
    tfont.output(str);
525
 
    len1 = tfont.getLength();
526
 
    break;
527
 
  case fontType1:
528
 
  case fontCIDType0:
529
 
  case fontType1C:
530
 
  case fontCIDType0C:
531
 
  case fontTrueType:
532
 
  default:
533
 
    if ((fd = open(fileName->getCString(),O_RDONLY)) < 0) {
534
 
      p2pError(-1,const_cast<char *>("Cannot open FontFile:%s\n"),fileName->getCString());
535
 
      return;
536
 
    }
537
 
    while ((n = read(fd,buf,BUFSIZ)) > 0) {
538
 
      char *p = buf;
539
 
      int r;
540
 
 
541
 
      while (n > 0) {
542
 
        r = str->write(p,n);
543
 
        if (r <= 0) break;
544
 
        n -= r;
545
 
        p += r;
546
 
      }
547
 
    }
548
 
    close(fd);
549
 
    break;
550
 
  }
551
 
 
552
 
  if (P2PDoc::options.fontCompress) str->endDeflate();
553
 
  len = str->getPosition()-cp; /* calculate length */
554
 
  str->puts("\nendstream\n");
555
 
 
556
 
  outputEnd(str);
557
 
 
558
 
  /* output length */
559
 
  lenObj->outputBegin(str);
560
 
  str->printf("%d\n",len);
561
 
  lenObj->outputEnd(str);
562
 
 
563
 
  if (len1Obj != 0) {
564
 
    /* output length1 */
565
 
    len1Obj->outputBegin(str);
566
 
    str->printf("%d\n",len1);
567
 
    len1Obj->outputEnd(str);
568
 
  }
569
 
}
570
 
 
571
 
P2PFontDescriptor::P2PFontDescriptor(Object *descriptorA,
572
 
  GfxFont *fontA, GooString *fileName, GfxFontType typeA,
573
 
  int faceIndexA, XRef *xref, int num, int gen) : P2PObject(num,gen)
574
 
{
575
 
  descriptorA->copy(&descriptor);
576
 
  fontFile = P2PFontFile::getFontFile(fileName,fontA,typeA,faceIndexA);
577
 
  type = typeA;
578
 
}
579
 
 
580
 
P2PFontDescriptor::~P2PFontDescriptor()
581
 
{
582
 
  /* fontFile is pointed by multiple FontDescriptor,
583
 
     so, don't delete it here.  it is deleted by P2PXRef::clean() */
584
 
 
585
 
  descriptor.free();
586
 
}
587
 
 
588
 
void P2PFontDescriptor::output(P2POutputStream *str, XRef *xref)
589
 
{
590
 
  P2PObject *objs[2];
591
 
  const char *keys[2];
592
 
  int objsIndex = 0;
593
 
  P2PObj fnobj;
594
 
 
595
 
  /* only indirect referenced */
596
 
  outputBegin(str);
597
 
  if (fontFile != 0) {
598
 
    UGooString *fn;
599
 
 
600
 
    switch (type) {
601
 
    case fontCIDType0:
602
 
    case fontType1:
603
 
    default:
604
 
      keys[objsIndex] = "FontFile";
605
 
      break;
606
 
    case fontCIDType2:
607
 
    case fontTrueType:
608
 
      keys[objsIndex] = "FontFile2";
609
 
      break;
610
 
    case fontType1C:
611
 
    case fontCIDType0C:
612
 
      keys[objsIndex] = "FontFile3";
613
 
      break;
614
 
    }
615
 
    objs[objsIndex++] = fontFile;
616
 
    fn = fontFile->getFontName();
617
 
    if (fn != 0) {
618
 
      char *p;
619
 
 
620
 
      p = fn->getCString();
621
 
      fnobj.getObj()->initName(p);
622
 
      keys[objsIndex] = "FontName";
623
 
      objs[objsIndex++] = &fnobj;
624
 
      delete[] p;
625
 
    }
626
 
  }
627
 
  P2POutput::outputDict(descriptor.getDict(),keys,objs,objsIndex,str,xref);
628
 
  str->putchar('\n');
629
 
  outputEnd(str);
630
 
}
631
 
 
632
 
P2PCIDFontDict::P2PCIDFontDict(Object *fontDictA, GfxFont *fontA,
633
 
  GfxFontType typeA, GfxFontType embeddedTypeA,
634
 
  P2PFontDescriptor *fontDescriptorA, int num, int gen) : P2PObject(num,gen)
635
 
{
636
 
  type = typeA;
637
 
  embeddedType = embeddedTypeA;
638
 
  fontDictA->copy(&fontDict);
639
 
  fontDescriptor = fontDescriptorA;
640
 
  font = fontA;
641
 
}
642
 
 
643
 
P2PCIDFontDict::~P2PCIDFontDict()
644
 
{
645
 
  fontDict.free();
646
 
  /* must not delete font, it is deleted by P2PFontDict::~P2PFonrDict(). */
647
 
}
648
 
 
649
 
void P2PCIDFontDict::output(P2POutputStream *str, XRef *xref)
650
 
{
651
 
  P2PObject *objs[3];
652
 
  const char *keys[3];
653
 
  int objsIndex = 0;
654
 
  P2PObj *subtypeObjp = 0;
655
 
  P2PObj fnobj;
656
 
 
657
 
  if (embeddedType != type) {
658
 
    /* change subtype */
659
 
 
660
 
    subtypeObjp = new P2PObj();
661
 
    switch (embeddedType) {
662
 
    case fontCIDType0:
663
 
      subtypeObjp->getObj()->initName(const_cast<char *>("CIDFontType0"));
664
 
      break;
665
 
    case fontCIDType2:
666
 
      subtypeObjp->getObj()->initName(const_cast<char *>("CIDFontType2"));
667
 
      break;
668
 
    case fontTrueType:
669
 
    case fontUnknownType:
670
 
    case fontType1:
671
 
    case fontType1C:
672
 
    case fontType3:
673
 
    case fontCIDType0C:
674
 
    default:
675
 
      p2pError(-1,const_cast<char *>("P2PCIDFontDict: Illegal embedded font type"));
676
 
      goto end_output;
677
 
      break;
678
 
    }
679
 
    keys[objsIndex] = "Subtype";
680
 
    objs[objsIndex++] = subtypeObjp;
681
 
  }
682
 
  if (embeddedType == fontCIDType2) {
683
 
    /* Add CIDToGIDMap */
684
 
    P2PObject *objp;
685
 
    P2PFontFile *fontFile;
686
 
 
687
 
    fontFile = fontDescriptor->getFontFile();
688
 
    if (fontFile != 0) {
689
 
      UGooString *fn;
690
 
 
691
 
      if (!(fontFile->isIdentity())) {
692
 
        keys[objsIndex] = "CIDToGIDMap";
693
 
        objp = fontFile->getCIDToGID(font->getWMode());
694
 
        objs[objsIndex++] = objp;
695
 
      }
696
 
      fn = fontFile->getFontName();
697
 
      if (fn != 0) {
698
 
        char *p = fn->getCString();
699
 
        fnobj.getObj()->initName(p);
700
 
        keys[objsIndex] = "BaseFont";
701
 
        objs[objsIndex++] = &fnobj;
702
 
        delete[] p;
703
 
      }
704
 
    }
705
 
  }
706
 
 
707
 
  outputBegin(str);
708
 
  P2POutput::outputDict(fontDict.getDict(),keys,objs,objsIndex,str,xref);
709
 
  str->putchar('\n');
710
 
  outputEnd(str);
711
 
end_output:
712
 
  if (subtypeObjp != 0) {
713
 
    delete subtypeObjp;
714
 
  }
715
 
}
716
 
 
717
 
P2PDescendantFontsWrapper::P2PDescendantFontsWrapper(P2PObject *elementA)
718
 
{
719
 
  element = elementA;
720
 
}
721
 
 
722
 
P2PDescendantFontsWrapper::~P2PDescendantFontsWrapper()
723
 
{
724
 
  /* do nothing */
725
 
}
726
 
 
727
 
void P2PDescendantFontsWrapper::output(P2POutputStream *str, XRef *xref)
728
 
{
729
 
  str->puts("[ ");
730
 
  element->outputRef(str);
731
 
  str->puts(" ]");
732
 
}
733
 
 
734
 
void P2PFontDict::doReadFontDescriptor(Object *dictObj,
735
 
  GfxFontType type, const char *name, XRef *xref)
736
 
{
737
 
  Dict *dict = dictObj->getDict();
738
 
  Object obj;
739
 
  int num, gen;
740
 
  P2PObject *p;
741
 
  int faceIndex = 0;
742
 
 
743
 
  if (dict->lookupNF(const_cast<char *>("FontDescriptor"),&obj) == 0
744
 
       || obj.isNull()) {
745
 
    /* no FontDescriptor */
746
 
    p2pError(-1,const_cast<char *>("Font:%s has no FontDescriptor entry.\n"),name);
747
 
    return;
748
 
  }
749
 
  if (!obj.isRef()) {
750
 
    /* not indirect reference is error */
751
 
    p2pError(-1,const_cast<char *>("FontDescriptor entry of Font:%s is not indirect.\n"),name);
752
 
    goto end_read;
753
 
  }
754
 
  num = obj.getRefNum();
755
 
  gen = obj.getRefGen();
756
 
  if ((p = P2PObject::find(num,gen)) != 0) {
757
 
    /* already read */
758
 
    fontDescriptor = static_cast<P2PFontDescriptor *>(p);
759
 
    embeddedType = fontDescriptor->getType();
760
 
  } else {
761
 
    P2PFontFile *fp;
762
 
    UGooString *ugs;
763
 
#if POPPLER_VERSION_MAJOR > 0 || POPPLER_VERSION_MINOR >= 19
764
 
    GooString *fileName;
765
 
 
766
 
    SysFontType sftype;
767
 
    fileName = globalParams->findSystemFontFile(font,&sftype,
768
 
        &faceIndex, NULL);
769
 
    if (fileName == 0) {
770
 
      p2pError(-1, const_cast<char *>("Couldn't find a font for %s. Not embedded\n"),name);
771
 
      goto end_read;
772
 
    }
773
 
    switch (sftype) {
774
 
    case sysFontPFA:
775
 
    case sysFontPFB:
776
 
      p2pError(-1, const_cast<char *>("Found a Type1 font for font:%s. Embedding Type1 font not supported yet."),name);
777
 
      goto end_read;
778
 
      break;
779
 
    case sysFontTTF:
780
 
    case sysFontTTC:
781
 
      switch (type) {
782
 
      case fontCIDType2:
783
 
      case fontTrueType:
784
 
        break;
785
 
      case fontCIDType0C:
786
 
      case fontCIDType0:
787
 
        embeddedType = fontCIDType2;
788
 
        break;
789
 
      case fontType1:
790
 
      case fontType1C:
791
 
        embeddedType = fontTrueType;
792
 
        break;
793
 
      default:
794
 
        p2pError(-1, const_cast<char *>("Illegal type font\n"));
795
 
        goto end_read;
796
 
      }
797
 
      break;
798
 
    default:
799
 
      p2pError(-1, const_cast<char *>("found a unknown type font for %s. Not embedded\n"),name);
800
 
      goto end_read;
801
 
      break;
802
 
    }
803
 
#else
804
 
    GooString *fileName = font->getExtFontFile();
805
 
 
806
 
    if (fileName == 0) {
807
 
      DisplayFontParam *dfp = 0;
808
 
      /* look for substitute font */
809
 
 
810
 
      if (font->getName()) {
811
 
        dfp = globalParams->getDisplayFont(font);
812
 
        /* a caller must not delete dfp */
813
 
      }
814
 
      if (dfp == 0) {
815
 
        p2pError(-1, const_cast<char *>("Couldn't find a font for %s. Not embedded\n"),name);
816
 
        goto end_read;
817
 
      }
818
 
      switch (dfp->kind) {
819
 
      case displayFontT1:
820
 
        p2pError(-1, const_cast<char *>("Found a Type1 font for font:%s. Embedding Type1 font not supported yet."),name);
821
 
        goto end_read;
822
 
        break;
823
 
      case displayFontTT:
824
 
        switch (type) {
825
 
        case fontCIDType2:
826
 
        case fontTrueType:
827
 
          break;
828
 
        case fontCIDType0C:
829
 
        case fontCIDType0:
830
 
          embeddedType = fontCIDType2;
831
 
          break;
832
 
        case fontType1:
833
 
        case fontType1C:
834
 
          embeddedType = fontTrueType;
835
 
          break;
836
 
        default:
837
 
          p2pError(-1, const_cast<char *>("Illegal type font\n"));
838
 
          goto end_read;
839
 
        }
840
 
        fileName = dfp->tt.fileName;
841
 
        faceIndex = dfp->tt.faceIndex;
842
 
        break;
843
 
      default:
844
 
        p2pError(-1, const_cast<char *>("found a unknown type font for %s. Not embedded\n"),name);
845
 
        goto end_read;
846
 
        break;
847
 
      }
848
 
    }
849
 
#endif
850
 
    /* reset obj */
851
 
    obj.free();
852
 
 
853
 
    xref->fetch(num,gen,&obj);
854
 
    if (!obj.isDict()) {
855
 
        p2pError(-1, const_cast<char *>("Font Descriptor of Font:%s is not Dictionary. Not embedded\n"),name);
856
 
        goto end_read;
857
 
    }
858
 
//fprintf(stderr, "DEBUG: Embedding Font fileName=%s for %s\n",fileName->getCString(),name);
859
 
    fontDescriptor = new P2PFontDescriptor(&obj,font,fileName,
860
 
      embeddedType, faceIndex, xref,num,gen);
861
 
    P2PXRef::put(fontDescriptor);
862
 
    fp = fontDescriptor->getFontFile();
863
 
    ugs = 0;
864
 
    if (fp != 0) {
865
 
      ugs = fp->getFontName();
866
 
      if (ugs != 0) {
867
 
        char *cs = ugs->getCString();
868
 
 
869
 
        fprintf(stderr, "INFO: Embedded Font=%s, from fileName=%s for %s\n",
870
 
          cs,fileName->getCString(),name);
871
 
        delete[] cs;
872
 
      }
873
 
    }
874
 
    if (ugs == 0) {
875
 
      fprintf(stderr, "INFO: Embedded Font from fileName=%s for %s\n",
876
 
        fileName->getCString(),name);
877
 
    }
878
 
  }
879
 
end_read:
880
 
  obj.free();
881
 
}
882
 
 
883
 
void P2PFontDict::read8bitFontDescriptor(GfxFontType type, const char *name,
884
 
  XRef *xref)
885
 
{
886
 
  doReadFontDescriptor(&fontDict,type,name,xref);
887
 
}
888
 
 
889
 
void P2PFontDict::readCIDFontDescriptor(GfxFontType type, const char *name,
890
 
  XRef *xref)
891
 
{
892
 
  Object obj;
893
 
  Object descendant;
894
 
  Dict *dict = fontDict.getDict();
895
 
  int num = -1, gen = -1;
896
 
 
897
 
  if (dict->lookup(const_cast<char *>("DescendantFonts"),&obj) == 0
898
 
       || obj.isNull()) {
899
 
    /* no DescendantFonts */
900
 
    p2pError(-1,const_cast<char *>("Font:%s has no DescendantFonts entry.\n"),name);
901
 
    return;
902
 
  }
903
 
  if (!obj.isArray() || obj.arrayGetNF(0,&descendant) == 0) {
904
 
    /* illegal DescendantFonts */
905
 
    p2pError(-1,const_cast<char *>("Font:%s has illegal DescendantFonts entry.\n"),name);
906
 
    goto end_read;
907
 
  }
908
 
  if (descendant.isRef()) {
909
 
    num = descendant.getRefNum();
910
 
    gen = descendant.getRefGen();
911
 
 
912
 
    cidFontDict = static_cast<P2PCIDFontDict *>(
913
 
      P2PObject::find(num,gen));
914
 
    if (cidFontDict == 0) {
915
 
      /* reset obj */
916
 
      descendant.free();
917
 
      xref->fetch(num,gen,&descendant);
918
 
    }
919
 
  }
920
 
  if (cidFontDict == 0) {
921
 
    if (!descendant.isDict()) {
922
 
      p2pError(-1,const_cast<char *>("Font:%s has illegal DescendantFonts entry.\n"),name);
923
 
      goto end_read1;
924
 
    }
925
 
    doReadFontDescriptor(&descendant,type,name,xref);
926
 
    cidFontDict = new P2PCIDFontDict(&descendant,font,type,
927
 
      embeddedType,fontDescriptor,num,gen);
928
 
    if (num > 0) P2PXRef::put(cidFontDict);
929
 
  }
930
 
end_read1:
931
 
  descendant.free();
932
 
end_read:
933
 
  obj.free();
934
 
}
935
 
 
936
 
UGooString *P2PFontDict::getEmbeddingFontName()
937
 
{
938
 
  P2PFontDescriptor *desc = fontDescriptor;
939
 
 
940
 
  if (cidFontDict != 0) {
941
 
    desc = cidFontDict->getFontDescriptor();
942
 
  }
943
 
  if (desc != 0) {
944
 
    P2PFontFile *file = desc->getFontFile();
945
 
    if (file != 0) return file->getFontName();
946
 
  }
947
 
  return 0;
948
 
}
949
 
 
950
 
void P2PFontDict::output(P2POutputStream *str, XRef *xref)
951
 
{
952
 
  int num, gen;
953
 
  P2PObject *objs[2];
954
 
  const char *keys[2];
955
 
  int nobjs = 0;
956
 
  UGooString *fn;
957
 
  P2PObj fnobj;
958
 
 
959
 
  fn = getEmbeddingFontName();
960
 
  if (fn != 0) {
961
 
    keys[nobjs] = "BaseFont";
962
 
    char *p = fn->getCString();
963
 
    fnobj.getObj()->initName(p);
964
 
    objs[nobjs] = &fnobj;
965
 
    nobjs++;
966
 
    delete[] p;
967
 
  }
968
 
  /* output indirect referenced dictionary only */
969
 
  outputBegin(str);
970
 
  if (cidFontDict != 0) {
971
 
    cidFontDict->getNum(&num,&gen);
972
 
    if (num < 0) {
973
 
      /* not indirect referenced, change it indirect referenced */
974
 
      P2PDescendantFontsWrapper *wrap
975
 
         = new P2PDescendantFontsWrapper(cidFontDict);
976
 
      keys[nobjs] = "DescendantFonts";
977
 
      objs[nobjs] = wrap;
978
 
      nobjs++;
979
 
 
980
 
      P2POutput::outputDict(fontDict.getDict(),keys,objs,nobjs,str,xref);
981
 
      delete wrap;
982
 
      P2PXRef::put(cidFontDict);
983
 
    } else {
984
 
      P2POutput::outputDict(fontDict.getDict(),keys,objs,nobjs,str,xref);
985
 
    }
986
 
  } else {
987
 
    if (embeddedType != font->getType()) {
988
 
      /* change subtype */
989
 
      P2PObj obj;
990
 
      keys[nobjs] = "Subtype";
991
 
      objs[nobjs] = &obj;
992
 
      nobjs++;
993
 
 
994
 
      switch (embeddedType) {
995
 
      case fontTrueType:
996
 
        obj.getObj()->initName(const_cast<char *>("TrueType"));
997
 
        P2POutput::outputDict(fontDict.getDict(),keys,objs,nobjs,str,xref);
998
 
        break;
999
 
      case fontType1:
1000
 
        obj.getObj()->initName(const_cast<char *>("Type1"));
1001
 
        P2POutput::outputDict(fontDict.getDict(),keys,objs,nobjs,str,xref);
1002
 
        break;
1003
 
      case fontCIDType2:
1004
 
      case fontCIDType0:
1005
 
      case fontCIDType0C:
1006
 
        /* change is not needed */
1007
 
        P2POutput::outputDict(fontDict.getDict(),keys,objs,nobjs,str,xref);
1008
 
        break;
1009
 
      case fontType1C:
1010
 
      case fontUnknownType:
1011
 
      case fontType3:
1012
 
      default:
1013
 
        p2pError(-1,const_cast<char *>("P2PFontDict: Illegal embedded font type"));
1014
 
        return;
1015
 
        break;
1016
 
      }
1017
 
    } else {
1018
 
      P2POutput::outputDict(fontDict.getDict(),keys,objs,nobjs,str,xref);
1019
 
    }
1020
 
  }
1021
 
  str->putchar('\n');
1022
 
  outputEnd(str);
1023
 
}
1024
 
 
1025
 
P2PFontDict::P2PFontDict(Object *fontDictA, XRef *xref, int num, int gen)
1026
 
  : P2PObject(num,gen)
1027
 
{
1028
 
  Ref embID;
1029
 
  Ref id;
1030
 
  Dict *dict;
1031
 
  Object name;
1032
 
  GfxFontType type;
1033
 
 
1034
 
  font = 0;
1035
 
  fontDescriptor = 0;
1036
 
  cidFontDict = 0;
1037
 
  if (fontDictA == 0 || !fontDictA->isDict()) return;
1038
 
  fontDictA->copy(&fontDict);
1039
 
 
1040
 
  dict = fontDict.getDict();
1041
 
  dict->lookup(const_cast<char *>("BaseFont"),&name);
1042
 
  if (!name.isName()) {
1043
 
    p2pError(-1,const_cast<char *>("FontDictionary has not name type BaseFont entry\n"));
1044
 
    goto end_setup;
1045
 
  }
1046
 
  /* font id and tag are not used */
1047
 
  if ((font = GfxFont::makeFont(xref,const_cast<char *>(""),
1048
 
          id,fontDict.getDict())) == 0) {
1049
 
    p2pError(-1,const_cast<char *>("Can't get font %s. Not embedded\n"),
1050
 
      name.getName());
1051
 
    goto end_setup;
1052
 
  }
1053
 
  embeddedType = type = font->getType();
1054
 
  if (!font->getEmbeddedFontID(&embID)) {
1055
 
    /* not embedded */
1056
 
    int i;
1057
 
    const char *namep = name.getName();
1058
 
 
1059
 
//fprintf(stderr,"DEBUG:%s is not embedded\n",name.getName());
1060
 
 
1061
 
    /* check builtin fonts */
1062
 
    for (i = 0;i < nBuiltinFonts;i++) {
1063
 
      if (strcmp(namep, builtinFonts[i].name) == 0) {
1064
 
        /* built in font */
1065
 
        /* don't embed built in font */
1066
 
        fprintf(stderr,"INFO:%s is builtin font. not embedded.\n",namep);
1067
 
        goto end_setup;
1068
 
      }
1069
 
    }
1070
 
 
1071
 
    if (!P2PDoc::options.fontEmbeddingPreLoad) {
1072
 
      /* check pre-loaded fonts */
1073
 
      for (i = 0;i < P2PDoc::options.numPreFonts;i++) {
1074
 
        if (strcmp(namep, P2PDoc::options.preFonts[i]) == 0) {
1075
 
          /* pre-loaded font */
1076
 
          /* don't embed pre-loaded font */
1077
 
          fprintf(stderr,"INFO:%s is pre-loaded font. not embedded.\n",namep);
1078
 
          goto end_setup;
1079
 
        }
1080
 
      }
1081
 
    }
1082
 
 
1083
 
    switch (type) {
1084
 
    case fontType3:
1085
 
      /* Type3 font is always embedded */
1086
 
      /* do nothing */
1087
 
      break;
1088
 
    case fontTrueType:
1089
 
    case fontUnknownType:
1090
 
    case fontType1:
1091
 
    case fontType1C:
1092
 
#ifdef FONTTYPE_ENUM2
1093
 
    case fontType1COT:
1094
 
    case fontTrueTypeOT:
1095
 
#endif
1096
 
      /* 8bit font */
1097
 
      read8bitFontDescriptor(type,name.getName(),xref);
1098
 
      break;
1099
 
    case fontCIDType0:
1100
 
    case fontCIDType0C:
1101
 
    case fontCIDType2:
1102
 
#ifdef FONTTYPE_ENUM2
1103
 
    case fontCIDType0COT:
1104
 
    case fontCIDType2OT:
1105
 
#endif
1106
 
      /* CID font */
1107
 
      readCIDFontDescriptor(type,name.getName(),xref);
1108
 
      break;
1109
 
    }
1110
 
  } else {
1111
 
    /* embedded */
1112
 
  }
1113
 
end_setup:
1114
 
  name.free();
1115
 
}
1116
 
 
1117
 
P2PFontDict::~P2PFontDict()
1118
 
{
1119
 
  if (font != 0) {
1120
 
    font->decRefCnt();
1121
 
  }
1122
 
  /* fontDescriptor is pointed by multiple FontDict,
1123
 
     so, don't delete it here.  it is deleted by P2PXRef::clean() */
1124
 
  /* cidFontDict is pointed by multiple FontDict,
1125
 
     so, don't delete it here.  it is deleted by P2PXRef::clean() */
1126
 
 
1127
 
  fontDict.free();
1128
 
}
1129
 
 
1130
 
void P2PFontDict::showText(GooString *s)
1131
 
{
1132
 
  char *p;
1133
 
  int len;
1134
 
  int n;
1135
 
#ifdef OLD_MAPTOUNICODE
1136
 
  Unicode u[8];
1137
 
#else
1138
 
  Unicode *u = NULL;
1139
 
#endif
1140
 
  CharCode code;
1141
 
  int uLen;
1142
 
  double dx,dy,originX,originY;
1143
 
  P2PFontFile *fontFile;
1144
 
 
1145
 
  if (font == 0 || fontDescriptor == 0) return;
1146
 
  if ((fontFile = fontDescriptor->getFontFile()) == 0) return;
1147
 
  p = s->getCString();
1148
 
  len = s->getLength();
1149
 
  while (len > 0) {
1150
 
#ifdef OLD_MAPTOUNICODE
1151
 
    n = font->getNextChar(p,len,&code,u,(sizeof(u)/sizeof(Unicode)),&uLen,
1152
 
         &dx,&dy,&originX,&originY);
1153
 
#else
1154
 
    n = font->getNextChar(p,len,&code,&u,&uLen,
1155
 
         &dx,&dy,&originX,&originY);
1156
 
#endif
1157
 
    code &= (CIDTOGID_SIZE-1); /* mask */
1158
 
    fontFile->refChar(code);
1159
 
    p += n;
1160
 
    len -= n;
1161
 
  }
1162
 
}
1163
 
 
1164
 
P2PFontResource::P2PFontResource()
1165
 
{
1166
 
  keys = 0;
1167
 
  fontDicts = 0;
1168
 
  nDicts = 0;
1169
 
  nExtGState = 0;
1170
 
  extGStateKeys = 0;
1171
 
  extGStateFonts = 0;
1172
 
}
1173
 
 
1174
 
P2PFontResource::~P2PFontResource()
1175
 
{
1176
 
  int i;
1177
 
 
1178
 
  if (keys != 0) {
1179
 
    for (i = 0;i < nDicts;i++) {
1180
 
      delete keys[i];
1181
 
    }
1182
 
    delete[] keys;
1183
 
  }
1184
 
  if (fontDicts != 0) {
1185
 
    for (i = 0;i < nDicts;i++) {
1186
 
      if (fontDicts[i] != 0) {
1187
 
        int num, gen;
1188
 
 
1189
 
        fontDicts[i]->getNum(&num,&gen);
1190
 
        if (num < 0) {
1191
 
          /* Not indirect referenced FontDict */
1192
 
          /* output it as normal dictionary */
1193
 
          /* so, not needed any more */
1194
 
          delete fontDicts[i];
1195
 
        }
1196
 
        /* indirect referenced FontDict is registered in P2PXRef */
1197
 
        /* So, should not delete it. */
1198
 
      }
1199
 
    }
1200
 
    delete[] fontDicts;
1201
 
  }
1202
 
  if (extGStateKeys != 0) {
1203
 
    for (i = 0;i < nExtGState;i++) {
1204
 
      delete extGStateKeys[i];
1205
 
    }
1206
 
    delete[] extGStateKeys;
1207
 
  }
1208
 
  if (extGStateFonts != 0) {
1209
 
    /* indirect referenced FontDict is registered in P2PXRef */
1210
 
    /* So, should not delete it. */
1211
 
    delete[] extGStateFonts;
1212
 
  }
1213
 
}
1214
 
 
1215
 
void P2PFontResource::setup(P2PResources *resources, XRef *xref)
1216
 
{
1217
 
  doSetup(resources->getFontResource(),xref);
1218
 
  doSetupExtGState(resources->getExtGState(),xref);
1219
 
}
1220
 
 
1221
 
void P2PFontResource::setup(Dict *resources, XRef *xref)
1222
 
{
1223
 
  Object obj;
1224
 
 
1225
 
  if (resources == 0) return;
1226
 
  resources->lookup(const_cast<char *>("Font"),&obj);
1227
 
  if (obj.isDict()) {
1228
 
    doSetup(obj.getDict(),xref);
1229
 
  }
1230
 
  obj.free();
1231
 
  resources->lookup(const_cast<char *>("ExtGState"),&obj);
1232
 
  if (obj.isDict()) {
1233
 
    doSetupExtGState(obj.getDict(),xref);
1234
 
  }
1235
 
  obj.free();
1236
 
}
1237
 
 
1238
 
void P2PFontResource::doSetup(Dict *fontResource, XRef *xref)
1239
 
{
1240
 
  int i;
1241
 
  P2PFontDict *p = 0;
1242
 
 
1243
 
  if (fontResource == 0) return;
1244
 
  nDicts = fontResource->getLength();
1245
 
  keys = new UGooString *[nDicts];
1246
 
  fontDicts = new P2PFontDict *[nDicts];
1247
 
  for (i = 0;i < nDicts;i++) {
1248
 
    Object obj;
1249
 
#ifdef HAVE_UGOOSTRING_H
1250
 
    UGooString *key = fontResource->getKey(i);
1251
 
#else
1252
 
    UGooString *key = new UGooString(fontResource->getKey(i));
1253
 
#endif
1254
 
 
1255
 
    fontResource->getValNF(i,&obj);
1256
 
    if (obj.isRef()) {
1257
 
      int num = obj.getRefNum();
1258
 
      int gen = obj.getRefGen();
1259
 
      if ((p = static_cast<P2PFontDict *>(P2PObject::find(num,gen))) == 0) {
1260
 
        Object fobj;
1261
 
 
1262
 
        xref->fetch(num,gen,&fobj);
1263
 
        if (fobj.isDict()) {
1264
 
          p = new P2PFontDict(&fobj,xref,num,gen);
1265
 
          /* register this in P2PXRef to output later */
1266
 
          P2PXRef::put(p);
1267
 
        }
1268
 
        fobj.free();
1269
 
      }
1270
 
    }
1271
 
    if (p != 0) {
1272
 
      keys[i] = new UGooString(*key);
1273
 
      fontDicts[i] = p;
1274
 
    } else if (obj.isDict()) {
1275
 
      keys[i] = new UGooString(*key);
1276
 
      fontDicts[i] = new P2PFontDict(&obj,xref);
1277
 
      P2PXRef::put(fontDicts[i]);
1278
 
    } else {
1279
 
      keys[i] = 0;
1280
 
      fontDicts[i] = 0;
1281
 
    }
1282
 
    obj.free();
1283
 
  }
1284
 
}
1285
 
 
1286
 
void P2PFontResource::doSetupExtGState(Dict *extGState, XRef *xref)
1287
 
{
1288
 
  int i;
1289
 
  P2PFontDict *p = 0;
1290
 
 
1291
 
  if (extGState == 0) return;
1292
 
  nExtGState = extGState->getLength();
1293
 
  extGStateKeys = new UGooString *[nExtGState];
1294
 
  extGStateFonts = new P2PFontDict *[nExtGState];
1295
 
  for (i = 0;i < nExtGState;i++) {
1296
 
    Object gstateObj;
1297
 
#ifdef HAVE_UGOOSTRING_H
1298
 
    UGooString *key = extGState->getKey(i);
1299
 
#else
1300
 
    char *key = extGState->getKey(i);
1301
 
#endif
1302
 
 
1303
 
    extGStateKeys[i] = 0;
1304
 
    extGStateFonts[i] = 0;
1305
 
    extGState->getVal(i,&gstateObj);
1306
 
    if (gstateObj.isDict()) {
1307
 
      Object fontArrayObj;
1308
 
      Dict *gstate = gstateObj.getDict();
1309
 
 
1310
 
      if (gstate->lookup(const_cast<char *>("Font"),&fontArrayObj) != 0) {
1311
 
        if (fontArrayObj.isArray() && fontArrayObj.arrayGetLength() > 0) {
1312
 
          Object fontRefObj;
1313
 
 
1314
 
          if (fontArrayObj.arrayGetNF(0,&fontRefObj) && fontRefObj.isRef()) {
1315
 
            int num = fontRefObj.getRefNum();
1316
 
            int gen = fontRefObj.getRefGen();
1317
 
 
1318
 
            if ((p = static_cast<P2PFontDict *>(P2PObject::find(num,gen)))
1319
 
                 == 0) {
1320
 
              Object fontObj;
1321
 
              xref->fetch(num,gen,&fontObj);
1322
 
              if (fontObj.isDict()) {
1323
 
                p = new P2PFontDict(&fontObj,xref,num,gen);
1324
 
                /* register this in P2PXRef to output later */
1325
 
                P2PXRef::put(p);
1326
 
              }
1327
 
              fontObj.free();
1328
 
            }
1329
 
          }
1330
 
          fontRefObj.free();
1331
 
        }
1332
 
#ifdef HAVE_UGOOSTRING_H
1333
 
        extGStateKeys[i] = new UGooString(*key);
1334
 
#else
1335
 
        extGStateKeys[i] = new UGooString(key);
1336
 
#endif
1337
 
        extGStateFonts[i] = p;
1338
 
      }
1339
 
      fontArrayObj.free();
1340
 
    }
1341
 
    gstateObj.free();
1342
 
  }
1343
 
}
1344
 
 
1345
 
void P2PFontResource::output(P2POutputStream *str, XRef *xref)
1346
 
{
1347
 
  int i;
1348
 
 
1349
 
  str->puts("<< ");
1350
 
  for (i = 0;i < nDicts;i++) {
1351
 
    P2POutput::outputName(keys[i]->getCString(),str);
1352
 
    str->putchar(' ');
1353
 
    fontDicts[i]->outputRef(str);
1354
 
    str->putchar('\n');
1355
 
  }
1356
 
  str->puts(" >>");
1357
 
}
1358
 
 
1359
 
P2PFontDict *P2PFontResource::lookup(const UGooString &key)
1360
 
{
1361
 
  int i;
1362
 
 
1363
 
  for (i = 0;i < nDicts;i++) {
1364
 
    if (key.cmp(keys[i]) == 0) {
1365
 
      return fontDicts[i];
1366
 
    }
1367
 
  }
1368
 
  return 0;
1369
 
}
1370
 
 
1371
 
P2PFontDict *P2PFontResource::lookupExtGState(const UGooString &key)
1372
 
{
1373
 
  int i;
1374
 
 
1375
 
  for (i = 0;i < nExtGState;i++) {
1376
 
    if (extGStateKeys != 0 && key.cmp(extGStateKeys[i]) == 0) {
1377
 
      return extGStateFonts[i];
1378
 
    }
1379
 
  }
1380
 
  return 0;
1381
 
}