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

Last change on this file since 257 was 257, checked in by Eugene Romanenko, 13 years ago

PDF plugin: Poppler library updated to version 0.10.0

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