fe54a632406ca409b133c71026cd6f56d553ba8f
[swftools.git] / pdf2swf / xpdf / FoFiType1.cc
1 //========================================================================
2 //
3 // FoFiType1.cc
4 //
5 // Copyright 1999-2003 Glyph & Cog, LLC
6 //
7 //========================================================================
8
9 #include <aconf.h>
10
11 #ifdef USE_GCC_PRAGMAS
12 #pragma implementation
13 #endif
14
15 #include <stdlib.h>
16 #include <string.h>
17 #include "gmem.h"
18 #include "FoFiEncodings.h"
19 #include "FoFiType1.h"
20
21 //------------------------------------------------------------------------
22 // FoFiType1
23 //------------------------------------------------------------------------
24
25 FoFiType1 *FoFiType1::make(char *fileA, int lenA) {
26   return new FoFiType1(fileA, lenA, gFalse);
27 }
28
29 FoFiType1 *FoFiType1::load(char *fileName) {
30   char *fileA;
31   int lenA;
32
33   if (!(fileA = FoFiBase::readFile(fileName, &lenA))) {
34     return NULL;
35   }
36   return new FoFiType1(fileA, lenA, gTrue);
37 }
38
39 FoFiType1::FoFiType1(char *fileA, int lenA, GBool freeFileDataA):
40   FoFiBase(fileA, lenA, freeFileDataA)
41 {
42   name = NULL;
43   encoding = NULL;
44   parsed = gFalse;
45 }
46
47 FoFiType1::~FoFiType1() {
48   int i;
49
50   if (name) {
51     gfree(name);
52   }
53   if (encoding && encoding != fofiType1StandardEncoding) {
54     for (i = 0; i < 256; ++i) {
55       gfree(encoding[i]);
56     }
57     gfree(encoding);
58   }
59 }
60
61 char *FoFiType1::getName() {
62   if (!parsed) {
63     parse();
64   }
65   return name;
66 }
67
68 char **FoFiType1::getEncoding() {
69   if (!parsed) {
70     parse();
71   }
72   return encoding;
73 }
74
75 void FoFiType1::writeEncoded(char **newEncoding,
76                              FoFiOutputFunc outputFunc, void *outputStream) {
77   char buf[512];
78   char *line;
79   int i;
80
81   // copy everything up to the encoding
82   for (line = (char *)file;
83        line && strncmp(line, "/Encoding", 9);
84        line = getNextLine(line)) ;
85   if (!line) {
86     // no encoding - just copy the whole font file
87     (*outputFunc)(outputStream, (char *)file, len);
88     return;
89   }
90   (*outputFunc)(outputStream, (char *)file, line - (char *)file);
91
92   // write the new encoding
93   (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
94   (*outputFunc)(outputStream,
95                 "0 1 255 {1 index exch /.notdef put} for\n", 40);
96   for (i = 0; i < 256; ++i) {
97     if (newEncoding[i]) {
98       sprintf(buf, "dup %d /%s put\n", i, newEncoding[i]);
99       (*outputFunc)(outputStream, buf, strlen(buf));
100     }
101   }
102   (*outputFunc)(outputStream, "readonly def\n", 13);
103   
104   // copy everything after the encoding
105   if (!strncmp(line, "/Encoding StandardEncoding def", 30)) {
106     line = getNextLine(line);
107   } else {
108     for (line = getNextLine(line);
109          line && strncmp(line, "readonly def", 12);
110          line = getNextLine(line)) ;
111   }
112   if (line) {
113     (*outputFunc)(outputStream, line, ((char *)file + len) - line);
114   }
115 }
116
117 char *FoFiType1::getNextLine(char *line) {
118   while (line < (char *)file + len && *line != '\x0a' && *line != '\x0d') {
119     ++line;
120   }
121   if (line < (char *)file + len && *line == '\x0d') {
122     ++line;
123   }
124   if (line < (char *)file + len && *line == '\x0a') {
125     ++line;
126   }
127   if (line >= (char *)file + len) {
128     return NULL;
129   }
130   return line;
131 }
132
133 void FoFiType1::parse() {
134   char *line, *line1, *p, *p2;
135   char buf[256];
136   char c;
137   int n, code, i, j;
138
139   for (i = 1, line = (char *)file;
140        i <= 100 && line && (!name || !encoding);
141        ++i) {
142
143     // get font name
144     if (!name && !strncmp(line, "/FontName", 9)) {
145       strncpy(buf, line, 255);
146       buf[255] = '\0';
147       if ((p = strchr(buf+9, '/')) &&
148           (p = strtok(p+1, " \t\n\r"))) {
149         name = copyString(p);
150       }
151       line = getNextLine(line);
152
153     // get encoding
154     } else if (!encoding &&
155                !strncmp(line, "/Encoding StandardEncoding def", 30)) {
156       encoding = fofiType1StandardEncoding;
157     } else if (!encoding &&
158                !strncmp(line, "/Encoding 256 array", 19)) {
159       encoding = (char **)gmalloc(256 * sizeof(char *));
160       for (j = 0; j < 256; ++j) {
161         encoding[j] = NULL;
162       }
163       line = getNextLine(line);
164       for (j = 0; j < 300 && line; ++j) {
165         line1 = getNextLine(line);
166         if ((n = line1 - line) > 255) {
167           n = 255;
168         }
169         strncpy(buf, line, n);
170         buf[n] = '\0';
171         for (p = buf; *p == ' ' || *p == '\t'; ++p) ;
172         if (!strncmp(p, "dup", 3)) {
173           for (p += 3; *p == ' ' || *p == '\t'; ++p) ;
174           for (p2 = p; *p2 >= '0' && *p2 <= '9'; ++p2) ;
175           if (*p2) {
176             c = *p2;
177             *p2 = '\0';
178             if ((code = atoi(p)) < 256) {
179               *p2 = c;
180               for (p = p2; *p == ' ' || *p == '\t'; ++p) ;
181               if (*p == '/') {
182                 ++p;
183                 for (p2 = p; *p2 && *p2 != ' ' && *p2 != '\t'; ++p2) ;
184                 *p2 = '\0';
185                 encoding[code] = copyString(p);
186               }
187             }
188           }
189         } else {
190           if (strtok(buf, " \t") &&
191               (p = strtok(NULL, " \t\n\r")) && !strcmp(p, "def")) {
192             break;
193           }
194         }
195         line = line1;
196       }
197       //~ check for getinterval/putinterval junk
198
199     } else {
200       line = getNextLine(line);
201     }
202
203     ++i;
204   }
205
206   parsed = gTrue;
207 }