upgraded to xpdf-3.01pl1
[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     if (line) {
112       line = getNextLine(line);
113     }
114   }
115   if (line) {
116     (*outputFunc)(outputStream, line, ((char *)file + len) - line);
117   }
118 }
119
120 char *FoFiType1::getNextLine(char *line) {
121   while (line < (char *)file + len && *line != '\x0a' && *line != '\x0d') {
122     ++line;
123   }
124   if (line < (char *)file + len && *line == '\x0d') {
125     ++line;
126   }
127   if (line < (char *)file + len && *line == '\x0a') {
128     ++line;
129   }
130   if (line >= (char *)file + len) {
131     return NULL;
132   }
133   return line;
134 }
135
136 void FoFiType1::parse() {
137   char *line, *line1, *p, *p2;
138   char buf[256];
139   char c;
140   int n, code, i, j;
141
142   for (i = 1, line = (char *)file;
143        i <= 100 && line && (!name || !encoding);
144        ++i) {
145
146     // get font name
147     if (!name && !strncmp(line, "/FontName", 9)) {
148       strncpy(buf, line, 255);
149       buf[255] = '\0';
150       if ((p = strchr(buf+9, '/')) &&
151           (p = strtok(p+1, " \t\n\r"))) {
152         name = copyString(p);
153       }
154       line = getNextLine(line);
155
156     // get encoding
157     } else if (!encoding &&
158                !strncmp(line, "/Encoding StandardEncoding def", 30)) {
159       encoding = fofiType1StandardEncoding;
160     } else if (!encoding &&
161                !strncmp(line, "/Encoding 256 array", 19)) {
162       encoding = (char **)gmallocn(256, sizeof(char *));
163       for (j = 0; j < 256; ++j) {
164         encoding[j] = NULL;
165       }
166       for (j = 0, line = getNextLine(line);
167            j < 300 && line && (line1 = getNextLine(line));
168            ++j, line = line1) {
169         if ((n = line1 - line) > 255) {
170           n = 255;
171         }
172         strncpy(buf, line, n);
173         buf[n] = '\0';
174         for (p = buf; *p == ' ' || *p == '\t'; ++p) ;
175         if (!strncmp(p, "dup", 3)) {
176           for (p += 3; *p == ' ' || *p == '\t'; ++p) ;
177           for (p2 = p; *p2 >= '0' && *p2 <= '9'; ++p2) ;
178           if (*p2) {
179             c = *p2;
180             *p2 = '\0';
181             if ((code = atoi(p)) < 256) {
182               *p2 = c;
183               for (p = p2; *p == ' ' || *p == '\t'; ++p) ;
184               if (*p == '/') {
185                 ++p;
186                 for (p2 = p; *p2 && *p2 != ' ' && *p2 != '\t'; ++p2) ;
187                 *p2 = '\0';
188                 encoding[code] = copyString(p);
189               }
190             }
191           }
192         } else {
193           p = strtok(buf, " \t\n\r");
194           if (p)
195           {
196             if (!strcmp(p, "def")) break;
197             if (!strcmp(p, "readonly")) break;
198             // the spec does not says this but i'm mantaining old xpdf behaviour that accepts "foo def" as end of the encoding array
199             p = strtok(buf, " \t\n\r");
200             if (p && !strcmp(p, "def")) break;
201           }
202         }
203       }
204       //~ check for getinterval/putinterval junk
205
206     } else {
207       line = getNextLine(line);
208     }
209   }
210
211   parsed = gTrue;
212 }