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

Last change on this file since 461 was 461, checked in by Silvan Scherrer, 11 years ago

poppler update to 0.14.2

File size: 7.6 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 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 "FoFiEncodings.h"
35#include "FoFiType1.h"
36#include "poppler/Error.h"
37
38//------------------------------------------------------------------------
39// FoFiType1
40//------------------------------------------------------------------------
41
42FoFiType1 *FoFiType1::make(char *fileA, int lenA) {
43  return new FoFiType1(fileA, lenA, gFalse);
44}
45
46FoFiType1 *FoFiType1::load(char *fileName) {
47  char *fileA;
48  int lenA;
49
50  if (!(fileA = FoFiBase::readFile(fileName, &lenA))) {
51    return NULL;
52  }
53  return new FoFiType1(fileA, lenA, gTrue);
54}
55
56FoFiType1::FoFiType1(char *fileA, int lenA, GBool freeFileDataA):
57  FoFiBase(fileA, lenA, freeFileDataA)
58{
59  name = NULL;
60  encoding = NULL;
61  parsed = gFalse;
62}
63
64FoFiType1::~FoFiType1() {
65  int i;
66
67  if (name) {
68    gfree(name);
69  }
70  if (encoding && encoding != fofiType1StandardEncoding) {
71    for (i = 0; i < 256; ++i) {
72      gfree(encoding[i]);
73    }
74    gfree(encoding);
75  }
76}
77
78char *FoFiType1::getName() {
79  if (!parsed) {
80    parse();
81  }
82  return name;
83}
84
85char **FoFiType1::getEncoding() {
86  if (!parsed) {
87    parse();
88  }
89  return encoding;
90}
91
92void FoFiType1::writeEncoded(char **newEncoding,
93                             FoFiOutputFunc outputFunc, void *outputStream) {
94  char buf[512];
95  char *line, *line2, *p;
96  int i;
97
98  // copy everything up to the encoding
99  for (line = (char *)file;
100       line && strncmp(line, "/Encoding", 9);
101       line = getNextLine(line)) ;
102  if (!line) {
103    // no encoding - just copy the whole font file
104    (*outputFunc)(outputStream, (char *)file, len);
105    return;
106  }
107  (*outputFunc)(outputStream, (char *)file, line - (char *)file);
108
109  // write the new encoding
110  (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
111  (*outputFunc)(outputStream,
112                "0 1 255 {1 index exch /.notdef put} for\n", 40);
113  for (i = 0; i < 256; ++i) {
114    if (newEncoding[i]) {
115      sprintf(buf, "dup %d /%s put\n", i, newEncoding[i]);
116      (*outputFunc)(outputStream, buf, strlen(buf));
117    }
118  }
119  (*outputFunc)(outputStream, "readonly def\n", 13);
120 
121  // find the end of the encoding data
122  //~ this ought to parse PostScript tokens
123  if (!strncmp(line, "/Encoding StandardEncoding def", 30)) {
124    line = getNextLine(line);
125  } else {
126    // skip "/Encoding" + one whitespace char,
127    // then look for 'def' preceded by PostScript whitespace
128    p = line + 10;
129    line = NULL;
130    for (; p < (char *)file + len; ++p) {
131      if ((*p == ' ' || *p == '\t' || *p == '\x0a' ||
132           *p == '\x0d' || *p == '\x0c' || *p == '\0') &&
133          p + 4 <= (char *)file + len &&
134          !strncmp(p + 1, "def", 3)) {
135        line = p + 4;
136        break;
137      }
138    }
139  }
140
141  // some fonts have two /Encoding entries in their dictionary, so we
142  // check for a second one here
143  if (line) {
144    for (line2 = line, i = 0;
145         i < 20 && line2 && strncmp(line2, "/Encoding", 9);
146         line2 = getNextLine(line2), ++i) ;
147    if (i < 20 && line2) {
148      (*outputFunc)(outputStream, line, line2 - line);
149      if (!strncmp(line2, "/Encoding StandardEncoding def", 30)) {
150        line = getNextLine(line2);
151      } else {
152        // skip "/Encoding" + one whitespace char,
153        // then look for 'def' preceded by PostScript whitespace
154        p = line2 + 10;
155        line = NULL;
156        for (; p < (char *)file + len; ++p) {
157          if ((*p == ' ' || *p == '\t' || *p == '\x0a' ||
158               *p == '\x0d' || *p == '\x0c' || *p == '\0') &&
159              p + 4 <= (char *)file + len &&
160              !strncmp(p + 1, "def", 3)) {
161            line = p + 4;
162            break;
163          }
164        }
165      }
166    }
167
168    // copy everything after the encoding
169    if (line) {
170      (*outputFunc)(outputStream, line, ((char *)file + len) - line);
171    }
172  }
173}
174
175char *FoFiType1::getNextLine(char *line) {
176  while (line < (char *)file + len && *line != '\x0a' && *line != '\x0d') {
177    ++line;
178  }
179  if (line < (char *)file + len && *line == '\x0d') {
180    ++line;
181  }
182  if (line < (char *)file + len && *line == '\x0a') {
183    ++line;
184  }
185  if (line >= (char *)file + len) {
186    return NULL;
187  }
188  return line;
189}
190
191void FoFiType1::parse() {
192  char *line, *line1, *p, *p2;
193  char buf[256];
194  char c;
195  int n, code, i, j;
196  char *tokptr;
197
198  for (i = 1, line = (char *)file;
199       i <= 100 && line && (!name || !encoding);
200       ++i) {
201
202    // get font name
203    if (!name && !strncmp(line, "/FontName", 9)) {
204      strncpy(buf, line, 255);
205      buf[255] = '\0';
206      if ((p = strchr(buf+9, '/')) &&
207          (p = strtok_r(p+1, " \t\n\r", &tokptr))) {
208        name = copyString(p);
209      }
210      line = getNextLine(line);
211
212    // get encoding
213    } else if (!encoding &&
214               !strncmp(line, "/Encoding StandardEncoding def", 30)) {
215      encoding = fofiType1StandardEncoding;
216    } else if (!encoding &&
217               !strncmp(line, "/Encoding 256 array", 19)) {
218      encoding = (char **)gmallocn(256, sizeof(char *));
219      for (j = 0; j < 256; ++j) {
220        encoding[j] = NULL;
221      }
222      for (j = 0, line = getNextLine(line);
223           j < 300 && line && (line1 = getNextLine(line));
224           ++j, line = line1) {
225        if ((n = line1 - line) > 255) {
226          error(-1, "FoFiType1::parse a line has more than 255 characters, we don't support this");
227          n = 255;
228        }
229        strncpy(buf, line, n);
230        buf[n] = '\0';
231        for (p = buf; *p == ' ' || *p == '\t'; ++p) ;
232        if (!strncmp(p, "dup", 3)) {
233          for (p += 3; *p == ' ' || *p == '\t'; ++p) ;
234          for (p2 = p; *p2 >= '0' && *p2 <= '9'; ++p2) ;
235          if (*p2) {
236            c = *p2; // store it so we can recover it after atoi
237            *p2 = '\0'; // terminate p so atoi works
238            code = atoi(p);
239            *p2 = c;
240            if (code == 8 && *p2 == '#') {
241              code = 0;
242              for (++p2; *p2 >= '0' && *p2 <= '7'; ++p2) {
243                code = code * 8 + (*p2 - '0');
244              }
245            }
246            if (code < 256) {
247              for (p = p2; *p == ' ' || *p == '\t'; ++p) ;
248              if (*p == '/') {
249                ++p;
250                for (p2 = p; *p2 && *p2 != ' ' && *p2 != '\t'; ++p2) ;
251                c = *p2; // store it so we can recover it after copyString
252                *p2 = '\0'; // terminate p so copyString works
253                encoding[code] = copyString(p);
254                *p2 = c;
255                p = p2;
256                for (; *p == ' ' || *p == '\t'; ++p); // eat spaces between string and put
257                if (!strncmp(p, "put", 3)) {
258                  // eat put and spaces and newlines after put
259                  for (p += 3; *p == ' ' || *p == '\t' || *p == '\n' || *p == '\r'; ++p);
260                  if (*p)
261                  {
262                    // there is still something after the definition
263                    // there might be another definition in this line
264                    // so move line1 to the end of our parsing
265                    // so we start in the potential next definition in the next loop
266                    line1 = &line[p - buf];
267                  }
268                } else {
269                  error(-1, "FoFiType1::parse no put after dup");
270                }
271              }
272            }
273          }
274        } else {
275          if (strtok_r(buf, " \t", &tokptr) &&
276              (p = strtok_r(NULL, " \t\n\r", &tokptr)) && !strcmp(p, "def")) {
277            break;
278          }
279        }
280      }
281      //~ check for getinterval/putinterval junk
282
283    } else {
284      line = getNextLine(line);
285    }
286  }
287
288  parsed = gTrue;
289}
Note: See TracBrowser for help on using the repository browser.