beta-0.89.2
[luatex.git] / source / libs / poppler / poppler-src / fofi / FoFiType1.cc
blob151f2d5f5bbb3c5d79f39e4792cf571b67088b18
1 //========================================================================
2 //
3 // FoFiType1.cc
4 //
5 // Copyright 1999-2003 Glyph & Cog, LLC
6 //
7 //========================================================================
9 //========================================================================
11 // Modified under the Poppler project - http://poppler.freedesktop.org
13 // All changes made under the Poppler project to this file are licensed
14 // under GPL version 2 or later
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 <jwilk@jwilk.net>
19 // Copyright (C) 2014 Carlos Garcia Campos <carlosgc@gnome.org>
21 // To see a description of the changes please see the Changelog file that
22 // came with your tarball or type make ChangeLog if you are building from git
24 //========================================================================
26 #include <config.h>
28 #ifdef USE_GCC_PRAGMAS
29 #pragma implementation
30 #endif
32 #include <stdlib.h>
33 #include <string.h>
34 #include "goo/gmem.h"
35 #include "goo/GooLikely.h"
36 #include "FoFiEncodings.h"
37 #include "FoFiType1.h"
38 #include "poppler/Error.h"
40 //------------------------------------------------------------------------
41 // FoFiType1
42 //------------------------------------------------------------------------
44 FoFiType1 *FoFiType1::make(char *fileA, int lenA) {
45 return new FoFiType1(fileA, lenA, gFalse);
48 FoFiType1 *FoFiType1::load(char *fileName) {
49 char *fileA;
50 int lenA;
52 if (!(fileA = FoFiBase::readFile(fileName, &lenA))) {
53 return NULL;
55 return new FoFiType1(fileA, lenA, gTrue);
58 FoFiType1::FoFiType1(char *fileA, int lenA, GBool freeFileDataA):
59 FoFiBase(fileA, lenA, freeFileDataA)
61 name = NULL;
62 encoding = NULL;
63 fontMatrix[0] = 0.001;
64 fontMatrix[1] = 0;
65 fontMatrix[2] = 0;
66 fontMatrix[3] = 0.001;
67 fontMatrix[4] = 0;
68 fontMatrix[5] = 0;
69 parsed = gFalse;
70 undoPFB();
73 FoFiType1::~FoFiType1() {
74 int i;
76 if (name) {
77 gfree(name);
79 if (encoding && encoding != fofiType1StandardEncoding) {
80 for (i = 0; i < 256; ++i) {
81 gfree(encoding[i]);
83 gfree(encoding);
87 char *FoFiType1::getName() {
88 if (!parsed) {
89 parse();
91 return name;
94 char **FoFiType1::getEncoding() {
95 if (!parsed) {
96 parse();
98 return encoding;
101 void FoFiType1::getFontMatrix(double *mat) {
102 int i;
104 if (!parsed) {
105 parse();
107 for (i = 0; i < 6; ++i) {
108 mat[i] = fontMatrix[i];
112 void FoFiType1::writeEncoded(const char **newEncoding,
113 FoFiOutputFunc outputFunc, void *outputStream) {
114 char buf[512];
115 char *line, *line2, *p;
116 int i;
118 // copy everything up to the encoding
119 for (line = (char *)file;
120 line && strncmp(line, "/Encoding", 9);
121 line = getNextLine(line)) ;
122 if (!line) {
123 // no encoding - just copy the whole font file
124 (*outputFunc)(outputStream, (char *)file, len);
125 return;
127 (*outputFunc)(outputStream, (char *)file, line - (char *)file);
129 // write the new encoding
130 (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
131 (*outputFunc)(outputStream,
132 "0 1 255 {1 index exch /.notdef put} for\n", 40);
133 for (i = 0; i < 256; ++i) {
134 if (newEncoding[i]) {
135 sprintf(buf, "dup %d /%s put\n", i, newEncoding[i]);
136 (*outputFunc)(outputStream, buf, strlen(buf));
139 (*outputFunc)(outputStream, "readonly def\n", 13);
141 // find the end of the encoding data
142 //~ this ought to parse PostScript tokens
143 if (!strncmp(line, "/Encoding StandardEncoding def", 30)) {
144 line = getNextLine(line);
145 } else {
146 // skip "/Encoding" + one whitespace char,
147 // then look for 'def' preceded by PostScript whitespace
148 p = line + 10;
149 line = NULL;
150 for (; p < (char *)file + len; ++p) {
151 if ((*p == ' ' || *p == '\t' || *p == '\x0a' ||
152 *p == '\x0d' || *p == '\x0c' || *p == '\0') &&
153 p + 4 <= (char *)file + len &&
154 !strncmp(p + 1, "def", 3)) {
155 line = p + 4;
156 break;
161 // some fonts have two /Encoding entries in their dictionary, so we
162 // check for a second one here
163 if (line) {
164 for (line2 = line, i = 0;
165 i < 20 && line2 && strncmp(line2, "/Encoding", 9);
166 line2 = getNextLine(line2), ++i) ;
167 if (i < 20 && line2) {
168 (*outputFunc)(outputStream, line, line2 - line);
169 if (!strncmp(line2, "/Encoding StandardEncoding def", 30)) {
170 line = getNextLine(line2);
171 } else {
172 // skip "/Encoding" + one whitespace char,
173 // then look for 'def' preceded by PostScript whitespace
174 p = line2 + 10;
175 line = NULL;
176 for (; p < (char *)file + len; ++p) {
177 if ((*p == ' ' || *p == '\t' || *p == '\x0a' ||
178 *p == '\x0d' || *p == '\x0c' || *p == '\0') &&
179 p + 4 <= (char *)file + len &&
180 !strncmp(p + 1, "def", 3)) {
181 line = p + 4;
182 break;
188 // copy everything after the encoding
189 if (line) {
190 (*outputFunc)(outputStream, line, ((char *)file + len) - line);
195 char *FoFiType1::getNextLine(char *line) {
196 while (line < (char *)file + len && *line != '\x0a' && *line != '\x0d') {
197 ++line;
199 if (line < (char *)file + len && *line == '\x0d') {
200 ++line;
202 if (line < (char *)file + len && *line == '\x0a') {
203 ++line;
205 if (line >= (char *)file + len) {
206 return NULL;
208 return line;
211 void FoFiType1::parse() {
212 char *line, *line1, *p, *p2;
213 char buf[256];
214 char c;
215 int n, code, base, i, j;
216 char *tokptr;
217 GBool gotMatrix;
219 gotMatrix = gFalse;
220 for (i = 1, line = (char *)file;
221 i <= 100 && line && (!name || !encoding);
222 ++i) {
224 // get font name
225 if (!name && !strncmp(line, "/FontName", 9)) {
226 strncpy(buf, line, 255);
227 buf[255] = '\0';
228 if ((p = strchr(buf+9, '/')) &&
229 (p = strtok_r(p+1, " \t\n\r", &tokptr))) {
230 name = copyString(p);
232 line = getNextLine(line);
234 // get encoding
235 } else if (!encoding &&
236 !strncmp(line, "/Encoding StandardEncoding def", 30)) {
237 encoding = (char **)fofiType1StandardEncoding;
238 } else if (!encoding &&
239 !strncmp(line, "/Encoding 256 array", 19)) {
240 encoding = (char **)gmallocn(256, sizeof(char *));
241 for (j = 0; j < 256; ++j) {
242 encoding[j] = NULL;
244 for (j = 0, line = getNextLine(line);
245 j < 300 && line && (line1 = getNextLine(line));
246 ++j, line = line1) {
247 if ((n = (int)(line1 - line)) > 255) {
248 error(errSyntaxWarning, -1, "FoFiType1::parse a line has more than 255 characters, we don't support this");
249 n = 255;
251 strncpy(buf, line, n);
252 buf[n] = '\0';
253 for (p = buf; *p == ' ' || *p == '\t'; ++p) ;
254 if (!strncmp(p, "dup", 3)) {
255 while (1) {
256 p += 3;
257 for (; *p == ' ' || *p == '\t'; ++p) ;
258 code = 0;
259 if (*p == '8' && p[1] == '#') {
260 base = 8;
261 p += 2;
262 } else if (*p >= '0' && *p <= '9') {
263 base = 10;
264 } else {
265 break;
267 for (; *p >= '0' && *p < '0' + base && code < INT_MAX / (base + (*p - '0')); ++p) {
268 code = code * base + (*p - '0');
270 for (; *p == ' ' || *p == '\t'; ++p) ;
271 if (*p != '/') {
272 break;
274 ++p;
275 for (p2 = p; *p2 && *p2 != ' ' && *p2 != '\t'; ++p2) ;
276 if (code >= 0 && code < 256) {
277 c = *p2;
278 *p2 = '\0';
279 encoding[code] = copyString(p);
280 *p2 = c;
282 for (p = p2; *p == ' ' || *p == '\t'; ++p) ;
283 if (strncmp(p, "put", 3)) {
284 break;
286 for (p += 3; *p == ' ' || *p == '\t'; ++p) ;
287 if (strncmp(p, "dup", 3)) {
288 break;
291 } else {
292 if (strtok_r(buf, " \t", &tokptr) &&
293 (p = strtok_r(NULL, " \t\n\r", &tokptr)) && !strcmp(p, "def")) {
294 break;
298 //~ check for getinterval/putinterval junk
300 } else if (!gotMatrix && !strncmp(line, "/FontMatrix", 11)) {
301 strncpy(buf, line + 11, 255);
302 buf[255] = '\0';
303 if ((p = strchr(buf, '['))) {
304 ++p;
305 if ((p2 = strchr(p, ']'))) {
306 *p2 = '\0';
307 for (j = 0; j < 6; ++j) {
308 if ((p = strtok(j == 0 ? p : (char *)NULL, " \t\n\r"))) {
309 fontMatrix[j] = atof(p);
310 } else {
311 break;
316 gotMatrix = gTrue;
318 } else {
319 line = getNextLine(line);
323 parsed = gTrue;
326 // Undo the PFB encoding, i.e., remove the PFB headers.
327 void FoFiType1::undoPFB() {
328 GBool ok;
329 Guchar *file2;
330 int pos1, pos2, type;
331 Guint segLen;
333 ok = gTrue;
334 if (getU8(0, &ok) != 0x80 || !ok) {
335 return;
337 file2 = (Guchar *)gmalloc(len);
338 pos1 = pos2 = 0;
339 while (getU8(pos1, &ok) == 0x80 && ok) {
340 type = getU8(pos1 + 1, &ok);
341 if (type < 1 || type > 2 || !ok) {
342 break;
344 segLen = getU32LE(pos1 + 2, &ok);
345 pos1 += 6;
346 if (!ok || !checkRegion(pos1, segLen)) {
347 break;
349 memcpy(file2 + pos2, file + pos1, segLen);
350 pos1 += segLen;
351 pos2 += segLen;
353 if (freeFileData) {
354 gfree(fileData);
356 file = fileData = file2;
357 freeFileData = gTrue;
358 len = pos2;