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

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

poppler, jpeg, freetype lib updates

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