source: trunk/poppler/mypoppler/fofi/FoFiType1.cc @ 515

Last change on this file since 515 was 515, checked in by Silvan Scherrer, 9 years ago

updated poppler to 0.20.3

File size: 8.7 KB
Line 
1//========================================================================
2//
3// FoFiType1.cc
4//
5// Copyright 1999-2003 Glyph & Cog, LLC
6//
7//========================================================================
8
9//========================================================================
10//
11// Modified under the Poppler project - http://poppler.freedesktop.org
12//
13// All changes made under the Poppler project to this file are licensed
14// under GPL version 2 or later
15//
16// Copyright (C) 2005, 2008, 2010 Albert Astals Cid <aacid@kde.org>
17// Copyright (C) 2005 Kristian HÞgsberg <krh@redhat.com>
18// Copyright (C) 2010 Jakub Wilk <ubanus@users.sf.net>
19//
20// To see a description of the changes please see the Changelog file that
21// came with your tarball or type make ChangeLog if you are building from git
22//
23//========================================================================
24
25#include <config.h>
26
27#ifdef USE_GCC_PRAGMAS
28#pragma implementation
29#endif
30
31#include <stdlib.h>
32#include <string.h>
33#include "goo/gmem.h"
34#include "goo/GooLikely.h"
35#include "FoFiEncodings.h"
36#include "FoFiType1.h"
37#include "poppler/Error.h"
38
39//------------------------------------------------------------------------
40// FoFiType1
41//------------------------------------------------------------------------
42
43FoFiType1 *FoFiType1::make(char *fileA, int lenA) {
44  return new FoFiType1(fileA, lenA, gFalse);
45}
46
47FoFiType1 *FoFiType1::load(char *fileName) {
48  char *fileA;
49  int lenA;
50
51  if (!(fileA = FoFiBase::readFile(fileName, &lenA))) {
52    return NULL;
53  }
54  return new FoFiType1(fileA, lenA, gTrue);
55}
56
57FoFiType1::FoFiType1(char *fileA, int lenA, GBool freeFileDataA):
58  FoFiBase(fileA, lenA, freeFileDataA)
59{
60  name = NULL;
61  encoding = NULL;
62  fontMatrix[0] = 0.001;
63  fontMatrix[1] = 0;
64  fontMatrix[2] = 0;
65  fontMatrix[3] = 0.001;
66  fontMatrix[4] = 0;
67  fontMatrix[5] = 0;
68  parsed = gFalse;
69  undoPFB();
70}
71
72FoFiType1::~FoFiType1() {
73  int i;
74
75  if (name) {
76    gfree(name);
77  }
78  if (encoding && encoding != fofiType1StandardEncoding) {
79    for (i = 0; i < 256; ++i) {
80      gfree(encoding[i]);
81    }
82    gfree(encoding);
83  }
84}
85
86char *FoFiType1::getName() {
87  if (!parsed) {
88    parse();
89  }
90  return name;
91}
92
93char **FoFiType1::getEncoding() {
94  if (!parsed) {
95    parse();
96  }
97  return encoding;
98}
99
100void FoFiType1::getFontMatrix(double *mat) {
101  int i;
102
103  if (!parsed) {
104    parse();
105  }
106  for (i = 0; i < 6; ++i) {
107    mat[i] = fontMatrix[i];
108  }
109}
110
111void FoFiType1::writeEncoded(const char **newEncoding,
112                             FoFiOutputFunc outputFunc, void *outputStream) {
113  char buf[512];
114  char *line, *line2, *p;
115  int i;
116
117  // copy everything up to the encoding
118  for (line = (char *)file;
119       line && strncmp(line, "/Encoding", 9);
120       line = getNextLine(line)) ;
121  if (!line) {
122    // no encoding - just copy the whole font file
123    (*outputFunc)(outputStream, (char *)file, len);
124    return;
125  }
126  (*outputFunc)(outputStream, (char *)file, line - (char *)file);
127
128  // write the new encoding
129  (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
130  (*outputFunc)(outputStream,
131                "0 1 255 {1 index exch /.notdef put} for\n", 40);
132  for (i = 0; i < 256; ++i) {
133    if (newEncoding[i]) {
134      sprintf(buf, "dup %d /%s put\n", i, newEncoding[i]);
135      (*outputFunc)(outputStream, buf, strlen(buf));
136    }
137  }
138  (*outputFunc)(outputStream, "readonly def\n", 13);
139 
140  // find the end of the encoding data
141  //~ this ought to parse PostScript tokens
142  if (!strncmp(line, "/Encoding StandardEncoding def", 30)) {
143    line = getNextLine(line);
144  } else {
145    // skip "/Encoding" + one whitespace char,
146    // then look for 'def' preceded by PostScript whitespace
147    p = line + 10;
148    line = NULL;
149    for (; p < (char *)file + len; ++p) {
150      if ((*p == ' ' || *p == '\t' || *p == '\x0a' ||
151           *p == '\x0d' || *p == '\x0c' || *p == '\0') &&
152          p + 4 <= (char *)file + len &&
153          !strncmp(p + 1, "def", 3)) {
154        line = p + 4;
155        break;
156      }
157    }
158  }
159
160  // some fonts have two /Encoding entries in their dictionary, so we
161  // check for a second one here
162  if (line) {
163    for (line2 = line, i = 0;
164         i < 20 && line2 && strncmp(line2, "/Encoding", 9);
165         line2 = getNextLine(line2), ++i) ;
166    if (i < 20 && line2) {
167      (*outputFunc)(outputStream, line, line2 - line);
168      if (!strncmp(line2, "/Encoding StandardEncoding def", 30)) {
169        line = getNextLine(line2);
170      } else {
171        // skip "/Encoding" + one whitespace char,
172        // then look for 'def' preceded by PostScript whitespace
173        p = line2 + 10;
174        line = NULL;
175        for (; p < (char *)file + len; ++p) {
176          if ((*p == ' ' || *p == '\t' || *p == '\x0a' ||
177               *p == '\x0d' || *p == '\x0c' || *p == '\0') &&
178              p + 4 <= (char *)file + len &&
179              !strncmp(p + 1, "def", 3)) {
180            line = p + 4;
181            break;
182          }
183        }
184      }
185    }
186
187    // copy everything after the encoding
188    if (line) {
189      (*outputFunc)(outputStream, line, ((char *)file + len) - line);
190    }
191  }
192}
193
194char *FoFiType1::getNextLine(char *line) {
195  while (line < (char *)file + len && *line != '\x0a' && *line != '\x0d') {
196    ++line;
197  }
198  if (line < (char *)file + len && *line == '\x0d') {
199    ++line;
200  }
201  if (line < (char *)file + len && *line == '\x0a') {
202    ++line;
203  }
204  if (line >= (char *)file + len) {
205    return NULL;
206  }
207  return line;
208}
209
210void FoFiType1::parse() {
211  char *line, *line1, *p, *p2;
212  char buf[256];
213  char c;
214  int n, code, base, i, j;
215  char *tokptr;
216  GBool gotMatrix;
217
218  gotMatrix = gFalse;
219  for (i = 1, line = (char *)file;
220       i <= 100 && line && (!name || !encoding);
221       ++i) {
222
223    // get font name
224    if (!name && !strncmp(line, "/FontName", 9)) {
225      strncpy(buf, line, 255);
226      buf[255] = '\0';
227      if ((p = strchr(buf+9, '/')) &&
228          (p = strtok_r(p+1, " \t\n\r", &tokptr))) {
229        name = copyString(p);
230      }
231      line = getNextLine(line);
232
233    // get encoding
234    } else if (!encoding &&
235               !strncmp(line, "/Encoding StandardEncoding def", 30)) {
236      encoding = (char **)fofiType1StandardEncoding;
237    } else if (!encoding &&
238               !strncmp(line, "/Encoding 256 array", 19)) {
239      encoding = (char **)gmallocn(256, sizeof(char *));
240      for (j = 0; j < 256; ++j) {
241        encoding[j] = NULL;
242      }
243      for (j = 0, line = getNextLine(line);
244           j < 300 && line && (line1 = getNextLine(line));
245           ++j, line = line1) {
246        if ((n = (int)(line1 - line)) > 255) {
247          error(errSyntaxWarning, -1, "FoFiType1::parse a line has more than 255 characters, we don't support this");
248          n = 255;
249        }
250        strncpy(buf, line, n);
251        buf[n] = '\0';
252        for (p = buf; *p == ' ' || *p == '\t'; ++p) ;
253        if (!strncmp(p, "dup", 3)) {
254          while (1) {
255            p += 3;
256            for (; *p == ' ' || *p == '\t'; ++p) ;
257            code = 0;
258            if (*p == '8' && p[1] == '#') {
259              base = 8;
260              p += 2;
261            } else if (*p >= '0' && *p <= '9') {
262              base = 10;
263            } else {
264              break;
265            }
266            for (; *p >= '0' && *p < '0' + base; ++p) {
267              code = code * base + (*p - '0');
268            }
269            for (; *p == ' ' || *p == '\t'; ++p) ;
270            if (*p != '/') {
271              break;
272            }
273            ++p;
274            for (p2 = p; *p2 && *p2 != ' ' && *p2 != '\t'; ++p2) ;
275            if (code >= 0 && code < 256) {
276              c = *p2;
277              *p2 = '\0';
278              encoding[code] = copyString(p);
279              *p2 = c;
280            }
281            for (p = p2; *p == ' ' || *p == '\t'; ++p) ;
282            if (strncmp(p, "put", 3)) {
283              break;
284            }
285            for (p += 3; *p == ' ' || *p == '\t'; ++p) ;
286            if (strncmp(p, "dup", 3)) {
287              break;
288            }
289          }
290        } else {
291          if (strtok_r(buf, " \t", &tokptr) &&
292              (p = strtok_r(NULL, " \t\n\r", &tokptr)) && !strcmp(p, "def")) {
293            break;
294          }
295        }
296      }
297      //~ check for getinterval/putinterval junk
298
299    } else if (!gotMatrix && !strncmp(line, "/FontMatrix", 11)) {
300      strncpy(buf, line + 11, 255);
301      buf[255] = '\0';
302      if ((p = strchr(buf, '['))) {
303        ++p;
304        if ((p2 = strchr(p, ']'))) {
305          *p2 = '\0';
306          for (j = 0; j < 6; ++j) {
307            if ((p = strtok(j == 0 ? p : (char *)NULL, " \t\n\r"))) {
308              fontMatrix[j] = atof(p);
309            } else {
310              break;
311            }
312          }
313        }
314      }
315      gotMatrix = gTrue;
316
317    } else {
318      line = getNextLine(line);
319    }
320  }
321
322  parsed = gTrue;
323}
324
325// Undo the PFB encoding, i.e., remove the PFB headers.
326void FoFiType1::undoPFB() {
327  GBool ok;
328  Guchar *file2;
329  int pos1, pos2, type;
330  Guint segLen;
331
332  ok = gTrue;
333  if (getU8(0, &ok) != 0x80 || !ok) {
334    return;
335  }
336  file2 = (Guchar *)gmalloc(len);
337  pos1 = pos2 = 0;
338  while (getU8(pos1, &ok) == 0x80 && ok) {
339    type = getU8(pos1 + 1, &ok);
340    if (type < 1 || type > 2 || !ok) {
341      break;
342    }
343    segLen = getU32LE(pos1 + 2, &ok);
344    pos1 += 6;
345    if (!ok || !checkRegion(pos1, segLen)) {
346      break;
347    }
348    memcpy(file2 + pos2, file + pos1, segLen);
349    pos1 += segLen;
350    pos2 += segLen;
351  }
352  if (freeFileData) {
353    gfree(fileData);
354  }
355  file = fileData = file2;
356  freeFileData = gTrue;
357  len = pos2;
358}
Note: See TracBrowser for help on using the repository browser.