]> git.ipfire.org Git - thirdparty/cups.git/blame - pdftops/FoFiType1C.cxx
Merge changes from CUPS 1.4svn-r7199.
[thirdparty/cups.git] / pdftops / FoFiType1C.cxx
CommitLineData
ef416fc2 1//========================================================================
2//
3// FoFiType1C.cc
4//
5// Copyright 1999-2003 Glyph & Cog, LLC
6//
7//========================================================================
8
9#include <config.h>
10
11#ifdef USE_GCC_PRAGMAS
12#pragma implementation
13#endif
14
15#include <stdlib.h>
16#include <string.h>
17#include <math.h>
18#include "gmem.h"
19#include "GString.h"
20#include "FoFiEncodings.h"
21#include "FoFiType1C.h"
22
23//------------------------------------------------------------------------
24
25static char hexChars[17] = "0123456789ABCDEF";
26
27//------------------------------------------------------------------------
28// FoFiType1C
29//------------------------------------------------------------------------
30
31FoFiType1C *FoFiType1C::make(char *fileA, int lenA) {
32 FoFiType1C *ff;
33
34 ff = new FoFiType1C(fileA, lenA, gFalse);
35 if (!ff->parse()) {
36 delete ff;
37 return NULL;
38 }
39 return ff;
40}
41
42FoFiType1C *FoFiType1C::load(char *fileName) {
43 FoFiType1C *ff;
44 char *fileA;
45 int lenA;
46
47 if (!(fileA = FoFiBase::readFile(fileName, &lenA))) {
48 return NULL;
49 }
50 ff = new FoFiType1C(fileA, lenA, gTrue);
51 if (!ff->parse()) {
52 delete ff;
53 return NULL;
54 }
55 return ff;
56}
57
58FoFiType1C::FoFiType1C(char *fileA, int lenA, GBool freeFileDataA):
59 FoFiBase(fileA, lenA, freeFileDataA)
60{
61 name = NULL;
62 encoding = NULL;
63 privateDicts = NULL;
64 fdSelect = NULL;
65 charset = NULL;
66}
67
68FoFiType1C::~FoFiType1C() {
69 int i;
70
71 if (name) {
72 delete name;
73 }
74 if (encoding &&
75 encoding != fofiType1StandardEncoding &&
76 encoding != fofiType1ExpertEncoding) {
77 for (i = 0; i < 256; ++i) {
78 gfree(encoding[i]);
79 }
80 gfree(encoding);
81 }
82 if (privateDicts) {
83 gfree(privateDicts);
84 }
85 if (fdSelect) {
86 gfree(fdSelect);
87 }
88 if (charset &&
89 charset != fofiType1CISOAdobeCharset &&
90 charset != fofiType1CExpertCharset &&
91 charset != fofiType1CExpertSubsetCharset) {
92 gfree(charset);
93 }
94}
95
96char *FoFiType1C::getName() {
97 return name ? name->getCString() : (char *)NULL;
98}
99
100char **FoFiType1C::getEncoding() {
101 return encoding;
102}
103
104Gushort *FoFiType1C::getCIDToGIDMap(int *nCIDs) {
105 Gushort *map;
106 int n, i;
107
108 // a CID font's top dict has ROS as the first operator
109 if (topDict.firstOp != 0x0c1e) {
110 *nCIDs = 0;
111 return NULL;
112 }
113
114 // in a CID font, the charset data is the GID-to-CID mapping, so all
115 // we have to do is reverse it
116 n = 0;
117 for (i = 0; i < nGlyphs; ++i) {
118 if (charset[i] > n) {
119 n = charset[i];
120 }
121 }
122 ++n;
123 map = (Gushort *)gmallocn(n, sizeof(Gushort));
124 memset(map, 0, n * sizeof(Gushort));
125 for (i = 0; i < nGlyphs; ++i) {
126 map[charset[i]] = i;
127 }
128 *nCIDs = n;
129 return map;
130}
131
132void FoFiType1C::convertToType1(char **newEncoding, GBool ascii,
133 FoFiOutputFunc outputFunc,
134 void *outputStream) {
135 Type1CEexecBuf eb;
136 Type1CIndex subrIdx;
137 Type1CIndexVal val;
138 char buf[512];
139 char **enc;
140 GBool ok;
141 int i;
142
143 // write header and font dictionary, up to encoding
144 ok = gTrue;
145 (*outputFunc)(outputStream, "%!FontType1-1.0: ", 17);
146 (*outputFunc)(outputStream, name->getCString(), name->getLength());
147 if (topDict.versionSID != 0) {
148 getString(topDict.versionSID, buf, &ok);
149 (*outputFunc)(outputStream, buf, strlen(buf));
150 }
151 (*outputFunc)(outputStream, "\n", 1);
152 // the dictionary needs room for 12 entries: the following 9, plus
153 // Private and CharStrings (in the eexec section) and FID (which is
154 // added by definefont)
155 (*outputFunc)(outputStream, "12 dict begin\n", 14);
156 (*outputFunc)(outputStream, "/FontInfo 10 dict dup begin\n", 28);
157 if (topDict.versionSID != 0) {
158 (*outputFunc)(outputStream, "/version (", 10);
159 (*outputFunc)(outputStream, buf, strlen(buf));
160 (*outputFunc)(outputStream, ") readonly def\n", 15);
161 }
162 if (topDict.noticeSID != 0) {
163 getString(topDict.noticeSID, buf, &ok);
164 (*outputFunc)(outputStream, "/Notice (", 9);
165 (*outputFunc)(outputStream, buf, strlen(buf));
166 (*outputFunc)(outputStream, ") readonly def\n", 15);
167 }
168 if (topDict.copyrightSID != 0) {
169 getString(topDict.copyrightSID, buf, &ok);
170 (*outputFunc)(outputStream, "/Copyright (", 12);
171 (*outputFunc)(outputStream, buf, strlen(buf));
172 (*outputFunc)(outputStream, ") readonly def\n", 15);
173 }
174 if (topDict.fullNameSID != 0) {
175 getString(topDict.fullNameSID, buf, &ok);
176 (*outputFunc)(outputStream, "/FullName (", 11);
177 (*outputFunc)(outputStream, buf, strlen(buf));
178 (*outputFunc)(outputStream, ") readonly def\n", 15);
179 }
180 if (topDict.familyNameSID != 0) {
181 getString(topDict.familyNameSID, buf, &ok);
182 (*outputFunc)(outputStream, "/FamilyName (", 13);
183 (*outputFunc)(outputStream, buf, strlen(buf));
184 (*outputFunc)(outputStream, ") readonly def\n", 15);
185 }
186 if (topDict.weightSID != 0) {
187 getString(topDict.weightSID, buf, &ok);
188 (*outputFunc)(outputStream, "/Weight (", 9);
189 (*outputFunc)(outputStream, buf, strlen(buf));
190 (*outputFunc)(outputStream, ") readonly def\n", 15);
191 }
192 if (topDict.isFixedPitch) {
193 (*outputFunc)(outputStream, "/isFixedPitch true def\n", 23);
194 } else {
195 (*outputFunc)(outputStream, "/isFixedPitch false def\n", 24);
196 }
197 sprintf(buf, "/ItalicAngle %g def\n", topDict.italicAngle);
198 (*outputFunc)(outputStream, buf, strlen(buf));
199 sprintf(buf, "/UnderlinePosition %g def\n", topDict.underlinePosition);
200 (*outputFunc)(outputStream, buf, strlen(buf));
201 sprintf(buf, "/UnderlineThickness %g def\n", topDict.underlineThickness);
202 (*outputFunc)(outputStream, buf, strlen(buf));
203 (*outputFunc)(outputStream, "end readonly def\n", 17);
204 (*outputFunc)(outputStream, "/FontName /", 11);
205 (*outputFunc)(outputStream, name->getCString(), name->getLength());
206 (*outputFunc)(outputStream, " def\n", 5);
207 sprintf(buf, "/PaintType %d def\n", topDict.paintType);
208 (*outputFunc)(outputStream, buf, strlen(buf));
209 (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
210 sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] readonly def\n",
211 topDict.fontMatrix[0], topDict.fontMatrix[1], topDict.fontMatrix[2],
212 topDict.fontMatrix[3], topDict.fontMatrix[4], topDict.fontMatrix[5]);
213 (*outputFunc)(outputStream, buf, strlen(buf));
214 sprintf(buf, "/FontBBox [%g %g %g %g] readonly def\n",
215 topDict.fontBBox[0], topDict.fontBBox[1],
216 topDict.fontBBox[2], topDict.fontBBox[3]);
217 (*outputFunc)(outputStream, buf, strlen(buf));
218 sprintf(buf, "/StrokeWidth %g def\n", topDict.strokeWidth);
219 (*outputFunc)(outputStream, buf, strlen(buf));
220 if (topDict.uniqueID != 0) {
221 sprintf(buf, "/UniqueID %d def\n", topDict.uniqueID);
222 (*outputFunc)(outputStream, buf, strlen(buf));
223 }
224
225 // write the encoding
226 (*outputFunc)(outputStream, "/Encoding ", 10);
227 if (!newEncoding && encoding == fofiType1StandardEncoding) {
228 (*outputFunc)(outputStream, "StandardEncoding def\n", 21);
229 } else {
230 (*outputFunc)(outputStream, "256 array\n", 10);
231 (*outputFunc)(outputStream,
232 "0 1 255 {1 index exch /.notdef put} for\n", 40);
233 enc = newEncoding ? newEncoding : encoding;
234 for (i = 0; i < 256; ++i) {
235 if (enc[i]) {
236 sprintf(buf, "dup %d /%s put\n", i, enc[i]);
237 (*outputFunc)(outputStream, buf, strlen(buf));
238 }
239 }
240 (*outputFunc)(outputStream, "readonly def\n", 13);
241 }
242 (*outputFunc)(outputStream, "currentdict end\n", 16);
243
244 // start the binary section
245 (*outputFunc)(outputStream, "currentfile eexec\n", 18);
246 eb.outputFunc = outputFunc;
247 eb.outputStream = outputStream;
248 eb.ascii = ascii;
249 eb.r1 = 55665;
250 eb.line = 0;
251
252 // write the private dictionary
253 eexecWrite(&eb, "\x83\xca\x73\xd5");
254 eexecWrite(&eb, "dup /Private 32 dict dup begin\n");
255 eexecWrite(&eb, "/RD {string currentfile exch readstring pop}"
256 " executeonly def\n");
257 eexecWrite(&eb, "/ND {noaccess def} executeonly def\n");
258 eexecWrite(&eb, "/NP {noaccess put} executeonly def\n");
259 eexecWrite(&eb, "/MinFeature {16 16} def\n");
260 eexecWrite(&eb, "/password 5839 def\n");
261 if (privateDicts[0].nBlueValues) {
262 eexecWrite(&eb, "/BlueValues [");
263 for (i = 0; i < privateDicts[0].nBlueValues; ++i) {
264 sprintf(buf, "%s%d", i > 0 ? " " : "", privateDicts[0].blueValues[i]);
265 eexecWrite(&eb, buf);
266 }
267 eexecWrite(&eb, "] def\n");
268 }
269 if (privateDicts[0].nOtherBlues) {
270 eexecWrite(&eb, "/OtherBlues [");
271 for (i = 0; i < privateDicts[0].nOtherBlues; ++i) {
272 sprintf(buf, "%s%d", i > 0 ? " " : "", privateDicts[0].otherBlues[i]);
273 eexecWrite(&eb, buf);
274 }
275 eexecWrite(&eb, "] def\n");
276 }
277 if (privateDicts[0].nFamilyBlues) {
278 eexecWrite(&eb, "/FamilyBlues [");
279 for (i = 0; i < privateDicts[0].nFamilyBlues; ++i) {
280 sprintf(buf, "%s%d", i > 0 ? " " : "", privateDicts[0].familyBlues[i]);
281 eexecWrite(&eb, buf);
282 }
283 eexecWrite(&eb, "] def\n");
284 }
285 if (privateDicts[0].nFamilyOtherBlues) {
286 eexecWrite(&eb, "/FamilyOtherBlues [");
287 for (i = 0; i < privateDicts[0].nFamilyOtherBlues; ++i) {
288 sprintf(buf, "%s%d", i > 0 ? " " : "",
289 privateDicts[0].familyOtherBlues[i]);
290 eexecWrite(&eb, buf);
291 }
292 eexecWrite(&eb, "] def\n");
293 }
294 if (privateDicts[0].blueScale != 0.039625) {
295 sprintf(buf, "/BlueScale %g def\n", privateDicts[0].blueScale);
296 eexecWrite(&eb, buf);
297 }
298 if (privateDicts[0].blueShift != 7) {
299 sprintf(buf, "/BlueShift %d def\n", privateDicts[0].blueShift);
300 eexecWrite(&eb, buf);
301 }
302 if (privateDicts[0].blueFuzz != 1) {
303 sprintf(buf, "/BlueFuzz %d def\n", privateDicts[0].blueFuzz);
304 eexecWrite(&eb, buf);
305 }
306 if (privateDicts[0].hasStdHW) {
307 sprintf(buf, "/StdHW [%g] def\n", privateDicts[0].stdHW);
308 eexecWrite(&eb, buf);
309 }
310 if (privateDicts[0].hasStdVW) {
311 sprintf(buf, "/StdVW [%g] def\n", privateDicts[0].stdVW);
312 eexecWrite(&eb, buf);
313 }
314 if (privateDicts[0].nStemSnapH) {
315 eexecWrite(&eb, "/StemSnapH [");
316 for (i = 0; i < privateDicts[0].nStemSnapH; ++i) {
317 sprintf(buf, "%s%g", i > 0 ? " " : "", privateDicts[0].stemSnapH[i]);
318 eexecWrite(&eb, buf);
319 }
320 eexecWrite(&eb, "] def\n");
321 }
322 if (privateDicts[0].nStemSnapV) {
323 eexecWrite(&eb, "/StemSnapV [");
324 for (i = 0; i < privateDicts[0].nStemSnapV; ++i) {
325 sprintf(buf, "%s%g", i > 0 ? " " : "", privateDicts[0].stemSnapV[i]);
326 eexecWrite(&eb, buf);
327 }
328 eexecWrite(&eb, "] def\n");
329 }
330 if (privateDicts[0].hasForceBold) {
331 sprintf(buf, "/ForceBold %s def\n",
332 privateDicts[0].forceBold ? "true" : "false");
333 eexecWrite(&eb, buf);
334 }
335 if (privateDicts[0].forceBoldThreshold != 0) {
336 sprintf(buf, "/ForceBoldThreshold %g def\n",
337 privateDicts[0].forceBoldThreshold);
338 eexecWrite(&eb, buf);
339 }
340 if (privateDicts[0].languageGroup != 0) {
341 sprintf(buf, "/LanguageGroup %d def\n", privateDicts[0].languageGroup);
342 eexecWrite(&eb, buf);
343 }
344 if (privateDicts[0].expansionFactor != 0.06) {
345 sprintf(buf, "/ExpansionFactor %g def\n", privateDicts[0].expansionFactor);
346 eexecWrite(&eb, buf);
347 }
348
349 // set up subroutines
350 ok = gTrue;
351 getIndex(privateDicts[0].subrsOffset, &subrIdx, &ok);
352 if (!ok) {
353 subrIdx.pos = -1;
354 }
355
356 // write the CharStrings
357 sprintf(buf, "2 index /CharStrings %d dict dup begin\n", nGlyphs);
358 eexecWrite(&eb, buf);
359 for (i = 0; i < nGlyphs; ++i) {
360 ok = gTrue;
361 getIndexVal(&charStringsIdx, i, &val, &ok);
362 if (ok) {
363 getString(charset[i], buf, &ok);
364 if (ok) {
365 eexecCvtGlyph(&eb, buf, val.pos, val.len, &subrIdx, &privateDicts[0]);
366 }
367 }
368 }
369 eexecWrite(&eb, "end\n");
370 eexecWrite(&eb, "end\n");
371 eexecWrite(&eb, "readonly put\n");
372 eexecWrite(&eb, "noaccess put\n");
373 eexecWrite(&eb, "dup /FontName get exch definefont pop\n");
374 eexecWrite(&eb, "mark currentfile closefile\n");
375
376 // trailer
377 if (ascii && eb.line > 0) {
378 (*outputFunc)(outputStream, "\n", 1);
379 }
380 for (i = 0; i < 8; ++i) {
381 (*outputFunc)(outputStream, "0000000000000000000000000000000000000000000000000000000000000000\n", 65);
382 }
383 (*outputFunc)(outputStream, "cleartomark\n", 12);
384}
385
386void FoFiType1C::convertToCIDType0(char *psName,
387 FoFiOutputFunc outputFunc,
388 void *outputStream) {
389 int *cidMap;
390 GString *charStrings;
391 int *charStringOffsets;
392 Type1CIndex subrIdx;
393 Type1CIndexVal val;
394 int nCIDs, gdBytes;
395 char buf[512], buf2[512];
396 GBool ok;
397 int gid, offset, n, i, j, k;
398
399 // compute the CID count and build the CID-to-GID mapping
400 nCIDs = 0;
401 for (i = 0; i < nGlyphs; ++i) {
402 if (charset[i] >= nCIDs) {
403 nCIDs = charset[i] + 1;
404 }
405 }
406 cidMap = (int *)gmallocn(nCIDs, sizeof(int));
407 for (i = 0; i < nCIDs; ++i) {
408 cidMap[i] = -1;
409 }
410 for (i = 0; i < nGlyphs; ++i) {
411 cidMap[charset[i]] = i;
412 }
413
414 // build the charstrings
415 charStrings = new GString();
416 charStringOffsets = (int *)gmallocn(nCIDs + 1, sizeof(int));
417 for (i = 0; i < nCIDs; ++i) {
418 charStringOffsets[i] = charStrings->getLength();
419 if ((gid = cidMap[i]) >= 0) {
420 ok = gTrue;
421 getIndexVal(&charStringsIdx, gid, &val, &ok);
422 if (ok) {
423 getIndex(privateDicts[fdSelect[gid]].subrsOffset, &subrIdx, &ok);
424 if (!ok) {
425 subrIdx.pos = -1;
426 }
427 cvtGlyph(val.pos, val.len, charStrings,
428 &subrIdx, &privateDicts[fdSelect[gid]], gTrue);
429 }
430 }
431 }
432 charStringOffsets[nCIDs] = charStrings->getLength();
433
434 // compute gdBytes = number of bytes needed for charstring offsets
435 // (offset size needs to account for the charstring offset table,
436 // with a worst case of five bytes per entry, plus the charstrings
437 // themselves)
438 i = (nCIDs + 1) * 5 + charStrings->getLength();
439 if (i < 0x100) {
440 gdBytes = 1;
441 } else if (i < 0x10000) {
442 gdBytes = 2;
443 } else if (i < 0x1000000) {
444 gdBytes = 3;
445 } else {
446 gdBytes = 4;
447 }
448
449 // begin the font dictionary
450 (*outputFunc)(outputStream, "/CIDInit /ProcSet findresource begin\n", 37);
451 (*outputFunc)(outputStream, "20 dict begin\n", 14);
452 (*outputFunc)(outputStream, "/CIDFontName /", 14);
453 (*outputFunc)(outputStream, psName, strlen(psName));
454 (*outputFunc)(outputStream, " def\n", 5);
455 (*outputFunc)(outputStream, "/CIDFontType 0 def\n", 19);
456 (*outputFunc)(outputStream, "/CIDSystemInfo 3 dict dup begin\n", 32);
457 if (topDict.registrySID > 0 && topDict.orderingSID > 0) {
458 ok = gTrue;
459 getString(topDict.registrySID, buf, &ok);
460 if (ok) {
461 (*outputFunc)(outputStream, " /Registry (", 13);
462 (*outputFunc)(outputStream, buf, strlen(buf));
463 (*outputFunc)(outputStream, ") def\n", 6);
464 }
465 ok = gTrue;
466 getString(topDict.orderingSID, buf, &ok);
467 if (ok) {
468 (*outputFunc)(outputStream, " /Ordering (", 13);
469 (*outputFunc)(outputStream, buf, strlen(buf));
470 (*outputFunc)(outputStream, ") def\n", 6);
471 }
472 } else {
473 (*outputFunc)(outputStream, " /Registry (Adobe) def\n", 24);
474 (*outputFunc)(outputStream, " /Ordering (Identity) def\n", 27);
475 }
476 sprintf(buf, " /Supplement %d def\n", topDict.supplement);
477 (*outputFunc)(outputStream, buf, strlen(buf));
478 (*outputFunc)(outputStream, "end def\n", 8);
479 if (topDict.hasFontMatrix) {
480 sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n",
481 topDict.fontMatrix[0], topDict.fontMatrix[1],
482 topDict.fontMatrix[2], topDict.fontMatrix[3],
483 topDict.fontMatrix[4], topDict.fontMatrix[5]);
484 (*outputFunc)(outputStream, buf, strlen(buf));
485 } else if (privateDicts[0].hasFontMatrix) {
486 (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
487 } else {
488 (*outputFunc)(outputStream,
489 "/FontMatrix [0.001 0 0 0.001 0 0] def\n", 38);
490 }
491 sprintf(buf, "/FontBBox [%g %g %g %g] def\n",
492 topDict.fontBBox[0], topDict.fontBBox[1],
493 topDict.fontBBox[2], topDict.fontBBox[3]);
494 (*outputFunc)(outputStream, buf, strlen(buf));
495 (*outputFunc)(outputStream, "/FontInfo 1 dict dup begin\n", 27);
496 (*outputFunc)(outputStream, " /FSType 8 def\n", 16);
497 (*outputFunc)(outputStream, "end def\n", 8);
498
499 // CIDFont-specific entries
500 sprintf(buf, "/CIDCount %d def\n", nCIDs);
501 (*outputFunc)(outputStream, buf, strlen(buf));
502 (*outputFunc)(outputStream, "/FDBytes 1 def\n", 15);
503 sprintf(buf, "/GDBytes %d def\n", gdBytes);
504 (*outputFunc)(outputStream, buf, strlen(buf));
505 (*outputFunc)(outputStream, "/CIDMapOffset 0 def\n", 20);
506 if (topDict.paintType != 0) {
507 sprintf(buf, "/PaintType %d def\n", topDict.paintType);
508 (*outputFunc)(outputStream, buf, strlen(buf));
509 sprintf(buf, "/StrokeWidth %g def\n", topDict.strokeWidth);
510 (*outputFunc)(outputStream, buf, strlen(buf));
511 }
512
513 // FDArray entry
514 sprintf(buf, "/FDArray %d array\n", nFDs);
515 (*outputFunc)(outputStream, buf, strlen(buf));
516 for (i = 0; i < nFDs; ++i) {
517 sprintf(buf, "dup %d 10 dict begin\n", i);
518 (*outputFunc)(outputStream, buf, strlen(buf));
519 (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
520 if (privateDicts[i].hasFontMatrix) {
521 sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n",
522 privateDicts[i].fontMatrix[0],
523 privateDicts[i].fontMatrix[1],
524 privateDicts[i].fontMatrix[2],
525 privateDicts[i].fontMatrix[3],
526 privateDicts[i].fontMatrix[4],
527 privateDicts[i].fontMatrix[5]);
528 (*outputFunc)(outputStream, buf, strlen(buf));
529 } else {
530 (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
531 }
532 sprintf(buf, "/PaintType %d def\n", topDict.paintType);
533 (*outputFunc)(outputStream, buf, strlen(buf));
534 (*outputFunc)(outputStream, "/Private 32 dict begin\n", 23);
535 if (privateDicts[i].nBlueValues) {
536 (*outputFunc)(outputStream, "/BlueValues [", 13);
537 for (j = 0; j < privateDicts[i].nBlueValues; ++j) {
538 sprintf(buf, "%s%d", j > 0 ? " " : "", privateDicts[i].blueValues[j]);
539 (*outputFunc)(outputStream, buf, strlen(buf));
540 }
541 (*outputFunc)(outputStream, "] def\n", 6);
542 }
543 if (privateDicts[i].nOtherBlues) {
544 (*outputFunc)(outputStream, "/OtherBlues [", 13);
545 for (j = 0; j < privateDicts[i].nOtherBlues; ++j) {
546 sprintf(buf, "%s%d", j > 0 ? " " : "", privateDicts[i].otherBlues[j]);
547 (*outputFunc)(outputStream, buf, strlen(buf));
548 }
549 (*outputFunc)(outputStream, "] def\n", 6);
550 }
551 if (privateDicts[i].nFamilyBlues) {
552 (*outputFunc)(outputStream, "/FamilyBlues [", 14);
553 for (j = 0; j < privateDicts[i].nFamilyBlues; ++j) {
554 sprintf(buf, "%s%d", j > 0 ? " " : "", privateDicts[i].familyBlues[j]);
555 (*outputFunc)(outputStream, buf, strlen(buf));
556 }
557 (*outputFunc)(outputStream, "] def\n", 6);
558 }
559 if (privateDicts[i].nFamilyOtherBlues) {
560 (*outputFunc)(outputStream, "/FamilyOtherBlues [", 19);
561 for (j = 0; j < privateDicts[i].nFamilyOtherBlues; ++j) {
562 sprintf(buf, "%s%d", j > 0 ? " " : "",
563 privateDicts[i].familyOtherBlues[j]);
564 (*outputFunc)(outputStream, buf, strlen(buf));
565 }
566 (*outputFunc)(outputStream, "] def\n", 6);
567 }
568 if (privateDicts[i].blueScale != 0.039625) {
569 sprintf(buf, "/BlueScale %g def\n", privateDicts[i].blueScale);
570 (*outputFunc)(outputStream, buf, strlen(buf));
571 }
572 if (privateDicts[i].blueShift != 7) {
573 sprintf(buf, "/BlueShift %d def\n", privateDicts[i].blueShift);
574 (*outputFunc)(outputStream, buf, strlen(buf));
575 }
576 if (privateDicts[i].blueFuzz != 1) {
577 sprintf(buf, "/BlueFuzz %d def\n", privateDicts[i].blueFuzz);
578 (*outputFunc)(outputStream, buf, strlen(buf));
579 }
580 if (privateDicts[i].hasStdHW) {
581 sprintf(buf, "/StdHW [%g] def\n", privateDicts[i].stdHW);
582 (*outputFunc)(outputStream, buf, strlen(buf));
583 }
584 if (privateDicts[i].hasStdVW) {
585 sprintf(buf, "/StdVW [%g] def\n", privateDicts[i].stdVW);
586 (*outputFunc)(outputStream, buf, strlen(buf));
587 }
588 if (privateDicts[i].nStemSnapH) {
589 (*outputFunc)(outputStream, "/StemSnapH [", 12);
590 for (j = 0; j < privateDicts[i].nStemSnapH; ++j) {
591 sprintf(buf, "%s%g", j > 0 ? " " : "", privateDicts[i].stemSnapH[j]);
592 (*outputFunc)(outputStream, buf, strlen(buf));
593 }
594 (*outputFunc)(outputStream, "] def\n", 6);
595 }
596 if (privateDicts[i].nStemSnapV) {
597 (*outputFunc)(outputStream, "/StemSnapV [", 12);
598 for (j = 0; j < privateDicts[i].nStemSnapV; ++j) {
599 sprintf(buf, "%s%g", j > 0 ? " " : "", privateDicts[i].stemSnapV[j]);
600 (*outputFunc)(outputStream, buf, strlen(buf));
601 }
602 (*outputFunc)(outputStream, "] def\n", 6);
603 }
604 if (privateDicts[i].hasForceBold) {
605 sprintf(buf, "/ForceBold %s def\n",
606 privateDicts[i].forceBold ? "true" : "false");
607 (*outputFunc)(outputStream, buf, strlen(buf));
608 }
609 if (privateDicts[i].forceBoldThreshold != 0) {
610 sprintf(buf, "/ForceBoldThreshold %g def\n",
611 privateDicts[i].forceBoldThreshold);
612 (*outputFunc)(outputStream, buf, strlen(buf));
613 }
614 if (privateDicts[i].languageGroup != 0) {
615 sprintf(buf, "/LanguageGroup %d def\n", privateDicts[i].languageGroup);
616 (*outputFunc)(outputStream, buf, strlen(buf));
617 }
618 if (privateDicts[i].expansionFactor != 0.06) {
619 sprintf(buf, "/ExpansionFactor %g def\n",
620 privateDicts[i].expansionFactor);
621 (*outputFunc)(outputStream, buf, strlen(buf));
622 }
623 (*outputFunc)(outputStream, "currentdict end def\n", 20);
624 (*outputFunc)(outputStream, "currentdict end put\n", 20);
625 }
626 (*outputFunc)(outputStream, "def\n", 4);
627
628 // start the binary section
629 offset = (nCIDs + 1) * (1 + gdBytes);
630 sprintf(buf, "(Hex) %d StartData\n",
631 offset + charStrings->getLength());
632 (*outputFunc)(outputStream, buf, strlen(buf));
633
634 // write the charstring offset (CIDMap) table
635 for (i = 0; i <= nCIDs; i += 6) {
636 for (j = 0; j < 6 && i+j <= nCIDs; ++j) {
637 if (i+j < nCIDs && cidMap[i+j] >= 0) {
638 buf[0] = (char)fdSelect[cidMap[i+j]];
639 } else {
640 buf[0] = (char)0;
641 }
642 n = offset + charStringOffsets[i+j];
643 for (k = gdBytes; k >= 1; --k) {
644 buf[k] = (char)(n & 0xff);
645 n >>= 8;
646 }
647 for (k = 0; k <= gdBytes; ++k) {
648 sprintf(buf2, "%02x", buf[k] & 0xff);
649 (*outputFunc)(outputStream, buf2, 2);
650 }
651 }
652 (*outputFunc)(outputStream, "\n", 1);
653 }
654
655 // write the charstring data
656 n = charStrings->getLength();
657 for (i = 0; i < n; i += 32) {
658 for (j = 0; j < 32 && i+j < n; ++j) {
659 sprintf(buf, "%02x", charStrings->getChar(i+j) & 0xff);
660 (*outputFunc)(outputStream, buf, strlen(buf));
661 }
662 if (i + 32 >= n) {
663 (*outputFunc)(outputStream, ">", 1);
664 }
665 (*outputFunc)(outputStream, "\n", 1);
666 }
667
668 gfree(charStringOffsets);
669 delete charStrings;
670 gfree(cidMap);
671}
672
673void FoFiType1C::convertToType0(char *psName,
674 FoFiOutputFunc outputFunc,
675 void *outputStream) {
676 int *cidMap;
677 Type1CIndex subrIdx;
678 Type1CIndexVal val;
679 int nCIDs;
680 char buf[512];
681 Type1CEexecBuf eb;
682 GBool ok;
683 int fd, i, j, k;
684
685 // compute the CID count and build the CID-to-GID mapping
686 nCIDs = 0;
687 for (i = 0; i < nGlyphs; ++i) {
688 if (charset[i] >= nCIDs) {
689 nCIDs = charset[i] + 1;
690 }
691 }
692 cidMap = (int *)gmallocn(nCIDs, sizeof(int));
693 for (i = 0; i < nCIDs; ++i) {
694 cidMap[i] = -1;
695 }
696 for (i = 0; i < nGlyphs; ++i) {
697 cidMap[charset[i]] = i;
698 }
699
700 // write the descendant Type 1 fonts
701 for (i = 0; i < nCIDs; i += 256) {
702
703 //~ this assumes that all CIDs in this block have the same FD --
704 //~ to handle multiple FDs correctly, need to somehow divide the
705 //~ font up by FD
706 fd = 0;
707 for (j = 0; j < 256 && i+j < nCIDs; ++j) {
708 if (cidMap[i+j] >= 0) {
709 fd = fdSelect[cidMap[i+j]];
710 break;
711 }
712 }
713
714 // font dictionary (unencrypted section)
715 (*outputFunc)(outputStream, "16 dict begin\n", 14);
716 (*outputFunc)(outputStream, "/FontName /", 11);
717 (*outputFunc)(outputStream, psName, strlen(psName));
718 sprintf(buf, "_%02x def\n", i >> 8);
719 (*outputFunc)(outputStream, buf, strlen(buf));
720 (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
721 if (privateDicts[fd].hasFontMatrix) {
722 sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n",
723 privateDicts[fd].fontMatrix[0],
724 privateDicts[fd].fontMatrix[1],
725 privateDicts[fd].fontMatrix[2],
726 privateDicts[fd].fontMatrix[3],
727 privateDicts[fd].fontMatrix[4],
728 privateDicts[fd].fontMatrix[5]);
729 (*outputFunc)(outputStream, buf, strlen(buf));
730 } else if (topDict.hasFontMatrix) {
731 (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
732 } else {
733 (*outputFunc)(outputStream,
734 "/FontMatrix [0.001 0 0 0.001 0 0] def\n", 38);
735 }
736 sprintf(buf, "/FontBBox [%g %g %g %g] def\n",
737 topDict.fontBBox[0], topDict.fontBBox[1],
738 topDict.fontBBox[2], topDict.fontBBox[3]);
739 (*outputFunc)(outputStream, buf, strlen(buf));
740 sprintf(buf, "/PaintType %d def\n", topDict.paintType);
741 (*outputFunc)(outputStream, buf, strlen(buf));
742 if (topDict.paintType != 0) {
743 sprintf(buf, "/StrokeWidth %g def\n", topDict.strokeWidth);
744 (*outputFunc)(outputStream, buf, strlen(buf));
745 }
746 (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
747 for (j = 0; j < 256 && i+j < nCIDs; ++j) {
748 sprintf(buf, "dup %d /c%02x put\n", j, j);
749 (*outputFunc)(outputStream, buf, strlen(buf));
750 }
751 if (j < 256) {
752 sprintf(buf, "%d 1 255 { 1 index exch /.notdef put } for\n", j);
753 (*outputFunc)(outputStream, buf, strlen(buf));
754 }
755 (*outputFunc)(outputStream, "readonly def\n", 13);
756 (*outputFunc)(outputStream, "currentdict end\n", 16);
757
758 // start the binary section
759 (*outputFunc)(outputStream, "currentfile eexec\n", 18);
760 eb.outputFunc = outputFunc;
761 eb.outputStream = outputStream;
762 eb.ascii = gTrue;
763 eb.r1 = 55665;
764 eb.line = 0;
765
766 // start the private dictionary
767 eexecWrite(&eb, "\x83\xca\x73\xd5");
768 eexecWrite(&eb, "dup /Private 32 dict dup begin\n");
769 eexecWrite(&eb, "/RD {string currentfile exch readstring pop}"
770 " executeonly def\n");
771 eexecWrite(&eb, "/ND {noaccess def} executeonly def\n");
772 eexecWrite(&eb, "/NP {noaccess put} executeonly def\n");
773 eexecWrite(&eb, "/MinFeature {16 16} def\n");
774 eexecWrite(&eb, "/password 5839 def\n");
775 if (privateDicts[fd].nBlueValues) {
776 eexecWrite(&eb, "/BlueValues [");
777 for (k = 0; k < privateDicts[fd].nBlueValues; ++k) {
778 sprintf(buf, "%s%d", k > 0 ? " " : "", privateDicts[fd].blueValues[k]);
779 eexecWrite(&eb, buf);
780 }
781 eexecWrite(&eb, "] def\n");
782 }
783 if (privateDicts[fd].nOtherBlues) {
784 eexecWrite(&eb, "/OtherBlues [");
785 for (k = 0; k < privateDicts[fd].nOtherBlues; ++k) {
786 sprintf(buf, "%s%d", k > 0 ? " " : "", privateDicts[fd].otherBlues[k]);
787 eexecWrite(&eb, buf);
788 }
789 eexecWrite(&eb, "] def\n");
790 }
791 if (privateDicts[fd].nFamilyBlues) {
792 eexecWrite(&eb, "/FamilyBlues [");
793 for (k = 0; k < privateDicts[fd].nFamilyBlues; ++k) {
794 sprintf(buf, "%s%d", k > 0 ? " " : "",
795 privateDicts[fd].familyBlues[k]);
796 eexecWrite(&eb, buf);
797 }
798 eexecWrite(&eb, "] def\n");
799 }
800 if (privateDicts[fd].nFamilyOtherBlues) {
801 eexecWrite(&eb, "/FamilyOtherBlues [");
802 for (k = 0; k < privateDicts[fd].nFamilyOtherBlues; ++k) {
803 sprintf(buf, "%s%d", k > 0 ? " " : "",
804 privateDicts[fd].familyOtherBlues[k]);
805 eexecWrite(&eb, buf);
806 }
807 eexecWrite(&eb, "] def\n");
808 }
809 if (privateDicts[fd].blueScale != 0.039625) {
810 sprintf(buf, "/BlueScale %g def\n", privateDicts[fd].blueScale);
811 eexecWrite(&eb, buf);
812 }
813 if (privateDicts[fd].blueShift != 7) {
814 sprintf(buf, "/BlueShift %d def\n", privateDicts[fd].blueShift);
815 eexecWrite(&eb, buf);
816 }
817 if (privateDicts[fd].blueFuzz != 1) {
818 sprintf(buf, "/BlueFuzz %d def\n", privateDicts[fd].blueFuzz);
819 eexecWrite(&eb, buf);
820 }
821 if (privateDicts[fd].hasStdHW) {
822 sprintf(buf, "/StdHW [%g] def\n", privateDicts[fd].stdHW);
823 eexecWrite(&eb, buf);
824 }
825 if (privateDicts[fd].hasStdVW) {
826 sprintf(buf, "/StdVW [%g] def\n", privateDicts[fd].stdVW);
827 eexecWrite(&eb, buf);
828 }
829 if (privateDicts[fd].nStemSnapH) {
830 eexecWrite(&eb, "/StemSnapH [");
831 for (k = 0; k < privateDicts[fd].nStemSnapH; ++k) {
832 sprintf(buf, "%s%g", k > 0 ? " " : "", privateDicts[fd].stemSnapH[k]);
833 eexecWrite(&eb, buf);
834 }
835 eexecWrite(&eb, "] def\n");
836 }
837 if (privateDicts[fd].nStemSnapV) {
838 eexecWrite(&eb, "/StemSnapV [");
839 for (k = 0; k < privateDicts[fd].nStemSnapV; ++k) {
840 sprintf(buf, "%s%g", k > 0 ? " " : "", privateDicts[fd].stemSnapV[k]);
841 eexecWrite(&eb, buf);
842 }
843 eexecWrite(&eb, "] def\n");
844 }
845 if (privateDicts[fd].hasForceBold) {
846 sprintf(buf, "/ForceBold %s def\n",
847 privateDicts[fd].forceBold ? "true" : "false");
848 eexecWrite(&eb, buf);
849 }
850 if (privateDicts[fd].forceBoldThreshold != 0) {
851 sprintf(buf, "/ForceBoldThreshold %g def\n",
852 privateDicts[fd].forceBoldThreshold);
853 eexecWrite(&eb, buf);
854 }
855 if (privateDicts[fd].languageGroup != 0) {
856 sprintf(buf, "/LanguageGroup %d def\n", privateDicts[fd].languageGroup);
857 eexecWrite(&eb, buf);
858 }
859 if (privateDicts[fd].expansionFactor != 0.06) {
860 sprintf(buf, "/ExpansionFactor %g def\n",
861 privateDicts[fd].expansionFactor);
862 eexecWrite(&eb, buf);
863 }
864
865 // set up the subroutines
866 ok = gTrue;
867 getIndex(privateDicts[fd].subrsOffset, &subrIdx, &ok);
868 if (!ok) {
869 subrIdx.pos = -1;
870 }
871
872 // start the CharStrings
873 sprintf(buf, "2 index /CharStrings 256 dict dup begin\n");
874 eexecWrite(&eb, buf);
875
876 // write the .notdef CharString
877 ok = gTrue;
878 getIndexVal(&charStringsIdx, 0, &val, &ok);
879 if (ok) {
880 eexecCvtGlyph(&eb, ".notdef", val.pos, val.len,
881 &subrIdx, &privateDicts[fd]);
882 }
883
884 // write the CharStrings
885 for (j = 0; j < 256 && i+j < nCIDs; ++j) {
886 if (cidMap[i+j] >= 0) {
887 ok = gTrue;
888 getIndexVal(&charStringsIdx, cidMap[i+j], &val, &ok);
889 if (ok) {
890 sprintf(buf, "c%02x", j);
891 eexecCvtGlyph(&eb, buf, val.pos, val.len,
892 &subrIdx, &privateDicts[fd]);
893 }
894 }
895 }
896 eexecWrite(&eb, "end\n");
897 eexecWrite(&eb, "end\n");
898 eexecWrite(&eb, "readonly put\n");
899 eexecWrite(&eb, "noaccess put\n");
900 eexecWrite(&eb, "dup /FontName get exch definefont pop\n");
901 eexecWrite(&eb, "mark currentfile closefile\n");
902
903 // trailer
904 if (eb.line > 0) {
905 (*outputFunc)(outputStream, "\n", 1);
906 }
907 for (j = 0; j < 8; ++j) {
908 (*outputFunc)(outputStream, "0000000000000000000000000000000000000000000000000000000000000000\n", 65);
909 }
910 (*outputFunc)(outputStream, "cleartomark\n", 12);
911 }
912
913 // write the Type 0 parent font
914 (*outputFunc)(outputStream, "16 dict begin\n", 14);
915 (*outputFunc)(outputStream, "/FontName /", 11);
916 (*outputFunc)(outputStream, psName, strlen(psName));
917 (*outputFunc)(outputStream, " def\n", 5);
918 (*outputFunc)(outputStream, "/FontType 0 def\n", 16);
919 if (topDict.hasFontMatrix) {
920 sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n",
921 topDict.fontMatrix[0], topDict.fontMatrix[1],
922 topDict.fontMatrix[2], topDict.fontMatrix[3],
923 topDict.fontMatrix[4], topDict.fontMatrix[5]);
924 (*outputFunc)(outputStream, buf, strlen(buf));
925 } else {
926 (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
927 }
928 (*outputFunc)(outputStream, "/FMapType 2 def\n", 16);
929 (*outputFunc)(outputStream, "/Encoding [\n", 12);
930 for (i = 0; i < nCIDs; i += 256) {
931 sprintf(buf, "%d\n", i >> 8);
932 (*outputFunc)(outputStream, buf, strlen(buf));
933 }
934 (*outputFunc)(outputStream, "] def\n", 6);
935 (*outputFunc)(outputStream, "/FDepVector [\n", 14);
936 for (i = 0; i < nCIDs; i += 256) {
937 (*outputFunc)(outputStream, "/", 1);
938 (*outputFunc)(outputStream, psName, strlen(psName));
939 sprintf(buf, "_%02x findfont\n", i >> 8);
940 (*outputFunc)(outputStream, buf, strlen(buf));
941 }
942 (*outputFunc)(outputStream, "] def\n", 6);
943 (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
944
945 gfree(cidMap);
946}
947
948void FoFiType1C::eexecCvtGlyph(Type1CEexecBuf *eb, char *glyphName,
949 int offset, int nBytes,
950 Type1CIndex *subrIdx,
951 Type1CPrivateDict *pDict) {
952 char buf[512];
953 GString *charBuf;
954
955 // generate the charstring
956 charBuf = new GString();
957 cvtGlyph(offset, nBytes, charBuf, subrIdx, pDict, gTrue);
958
959 sprintf(buf, "/%s %d RD ", glyphName, charBuf->getLength());
960 eexecWrite(eb, buf);
961 eexecWriteCharstring(eb, (Guchar *)charBuf->getCString(),
962 charBuf->getLength());
963 eexecWrite(eb, " ND\n");
964
965 delete charBuf;
966}
967
968void FoFiType1C::cvtGlyph(int offset, int nBytes, GString *charBuf,
969 Type1CIndex *subrIdx, Type1CPrivateDict *pDict,
970 GBool top) {
971 Type1CIndexVal val;
972 GBool ok, dFP;
973 double d, dx, dy;
974 Gushort r2;
975 Guchar byte;
976 int pos, subrBias, start, i, k;
977
978 start = charBuf->getLength();
979 if (top) {
980 charBuf->append((char)73);
981 charBuf->append((char)58);
982 charBuf->append((char)147);
983 charBuf->append((char)134);
984 nOps = 0;
985 nHints = 0;
986 firstOp = gTrue;
987 openPath = gFalse;
988 }
989
990 pos = offset;
991 while (pos < offset + nBytes) {
992 ok = gTrue;
993 pos = getOp(pos, gTrue, &ok);
994 if (!ok) {
995 break;
996 }
997 if (!ops[nOps - 1].isNum) {
998 --nOps; // drop the operator
999 switch (ops[nOps].op) {
1000 case 0x0001: // hstem
1001 if (firstOp) {
1002 cvtGlyphWidth(nOps & 1, charBuf, pDict);
1003 firstOp = gFalse;
1004 }
1005 if (nOps & 1) {
1006 //~ error(-1, "Wrong number of args (%d) to Type 2 hstem", nOps);
1007 }
1008 d = 0;
1009 dFP = gFalse;
1010 for (k = 0; k < nOps; k += 2) {
1011 // convert Type 2 edge hints (-20 or -21) to Type 1 ghost hints
1012 if (ops[k+1].num < 0) {
1013 d += ops[k].num + ops[k+1].num;
1014 dFP |= ops[k].isFP | ops[k+1].isFP;
1015 cvtNum(d, dFP, charBuf);
1016 cvtNum(-ops[k+1].num, ops[k+1].isFP, charBuf);
1017 } else {
1018 d += ops[k].num;
1019 dFP |= ops[k].isFP;
1020 cvtNum(d, dFP, charBuf);
1021 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1022 d += ops[k+1].num;
1023 dFP |= ops[k+1].isFP;
1024 }
1025 charBuf->append((char)1);
1026 }
1027 nHints += nOps / 2;
1028 nOps = 0;
1029 break;
1030 case 0x0003: // vstem
1031 if (firstOp) {
1032 cvtGlyphWidth(nOps & 1, charBuf, pDict);
1033 firstOp = gFalse;
1034 }
1035 if (nOps & 1) {
1036 //~ error(-1, "Wrong number of args (%d) to Type 2 vstem", nOps);
1037 }
1038 d = 0;
1039 dFP = gFalse;
1040 for (k = 0; k < nOps; k += 2) {
1041 // convert Type 2 edge hints (-20 or -21) to Type 1 ghost hints
1042 if (ops[k+1].num < 0) {
1043 d += ops[k].num + ops[k+1].num;
1044 dFP |= ops[k].isFP | ops[k+1].isFP;
1045 cvtNum(d, dFP, charBuf);
1046 cvtNum(-ops[k+1].num, ops[k+1].isFP, charBuf);
1047 } else {
1048 d += ops[k].num;
1049 dFP |= ops[k].isFP;
1050 cvtNum(d, dFP, charBuf);
1051 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1052 d += ops[k+1].num;
1053 dFP |= ops[k+1].isFP;
1054 }
1055 charBuf->append((char)3);
1056 }
1057 nHints += nOps / 2;
1058 nOps = 0;
1059 break;
1060 case 0x0004: // vmoveto
1061 if (firstOp) {
1062 cvtGlyphWidth(nOps == 2, charBuf, pDict);
1063 firstOp = gFalse;
1064 }
1065 if (openPath) {
1066 charBuf->append((char)9);
1067 openPath = gFalse;
1068 }
1069 if (nOps != 1) {
1070 //~ error(-1, "Wrong number of args (%d) to Type 2 vmoveto", nOps);
1071 }
1072 cvtNum(ops[0].num, ops[0].isFP, charBuf);
1073 charBuf->append((char)4);
1074 nOps = 0;
1075 break;
1076 case 0x0005: // rlineto
1077 if (nOps < 2 || nOps % 2 != 0) {
1078 //~ error(-1, "Wrong number of args (%d) to Type 2 rlineto", nOps);
1079 }
1080 for (k = 0; k < nOps; k += 2) {
1081 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1082 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1083 charBuf->append((char)5);
1084 }
1085 nOps = 0;
1086 openPath = gTrue;
1087 break;
1088 case 0x0006: // hlineto
1089 if (nOps < 1) {
1090 //~ error(-1, "Wrong number of args (%d) to Type 2 hlineto", nOps);
1091 }
1092 for (k = 0; k < nOps; ++k) {
1093 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1094 charBuf->append((char)((k & 1) ? 7 : 6));
1095 }
1096 nOps = 0;
1097 openPath = gTrue;
1098 break;
1099 case 0x0007: // vlineto
1100 if (nOps < 1) {
1101 //~ error(-1, "Wrong number of args (%d) to Type 2 vlineto", nOps);
1102 }
1103 for (k = 0; k < nOps; ++k) {
1104 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1105 charBuf->append((char)((k & 1) ? 6 : 7));
1106 }
1107 nOps = 0;
1108 openPath = gTrue;
1109 break;
1110 case 0x0008: // rrcurveto
1111 if (nOps < 6 || nOps % 6 != 0) {
1112 //~ error(-1, "Wrong number of args (%d) to Type 2 rrcurveto", nOps);
1113 }
1114 for (k = 0; k < nOps; k += 6) {
1115 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1116 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1117 cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1118 cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1119 cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
1120 cvtNum(ops[k+5].num, ops[k+5].isFP, charBuf);
1121 charBuf->append((char)8);
1122 }
1123 nOps = 0;
1124 openPath = gTrue;
1125 break;
1126 case 0x000a: // callsubr
1127 if (nOps >= 1) {
1128 subrBias = (subrIdx->len < 1240)
1129 ? 107 : (subrIdx->len < 33900) ? 1131 : 32768;
1130 k = subrBias + (int)ops[nOps - 1].num;
1131 --nOps;
1132 ok = gTrue;
1133 getIndexVal(subrIdx, k, &val, &ok);
1134 if (ok) {
1135 cvtGlyph(val.pos, val.len, charBuf, subrIdx, pDict, gFalse);
1136 }
1137 } else {
1138 //~ error(-1, "Too few args to Type 2 callsubr");
1139 }
1140 // don't clear the stack
1141 break;
1142 case 0x000b: // return
1143 // don't clear the stack
1144 break;
1145 case 0x000e: // endchar / seac
1146 if (firstOp) {
1147 cvtGlyphWidth(nOps == 1 || nOps == 5, charBuf, pDict);
1148 firstOp = gFalse;
1149 }
1150 if (openPath) {
1151 charBuf->append((char)9);
1152 openPath = gFalse;
1153 }
1154 if (nOps == 4) {
1155 cvtNum(0, gFalse, charBuf);
1156 cvtNum(ops[0].num, ops[0].isFP, charBuf);
1157 cvtNum(ops[1].num, ops[1].isFP, charBuf);
1158 cvtNum(ops[2].num, ops[2].isFP, charBuf);
1159 cvtNum(ops[3].num, ops[3].isFP, charBuf);
1160 charBuf->append((char)12)->append((char)6);
1161 } else if (nOps == 0) {
1162 charBuf->append((char)14);
1163 } else {
1164 //~ error(-1, "Wrong number of args (%d) to Type 2 endchar", nOps);
1165 }
1166 nOps = 0;
1167 break;
1168 case 0x000f: // (obsolete)
1169 // this op is ignored, but we need the glyph width
1170 if (firstOp) {
1171 cvtGlyphWidth(nOps > 0, charBuf, pDict);
1172 firstOp = gFalse;
1173 }
1174 nOps = 0;
1175 break;
1176 case 0x0010: // blend
1177 //~ error(-1, "Unimplemented Type 2 charstring op: %d", file[i]);
1178 nOps = 0;
1179 break;
1180 case 0x0012: // hstemhm
1181 // ignored
1182 if (firstOp) {
1183 cvtGlyphWidth(nOps & 1, charBuf, pDict);
1184 firstOp = gFalse;
1185 }
1186 if (nOps & 1) {
1187 //~ error(-1, "Wrong number of args (%d) to Type 2 hstemhm", nOps);
1188 }
1189 nHints += nOps / 2;
1190 nOps = 0;
1191 break;
1192 case 0x0013: // hintmask
1193 // ignored
1194 if (firstOp) {
1195 cvtGlyphWidth(nOps & 1, charBuf, pDict);
1196 firstOp = gFalse;
1197 }
1198 if (nOps > 0) {
1199 if (nOps & 1) {
1200 //~ error(-1, "Wrong number of args (%d) to Type 2 hintmask/vstemhm",
1201 //~ nOps);
1202 }
1203 nHints += nOps / 2;
1204 }
1205 pos += (nHints + 7) >> 3;
1206 nOps = 0;
1207 break;
1208 case 0x0014: // cntrmask
1209 // ignored
1210 if (firstOp) {
1211 cvtGlyphWidth(nOps & 1, charBuf, pDict);
1212 firstOp = gFalse;
1213 }
1214 if (nOps > 0) {
1215 if (nOps & 1) {
1216 //~ error(-1, "Wrong number of args (%d) to Type 2 cntrmask/vstemhm",
1217 //~ nOps);
1218 }
1219 nHints += nOps / 2;
1220 }
1221 pos += (nHints + 7) >> 3;
1222 nOps = 0;
1223 break;
1224 case 0x0015: // rmoveto
1225 if (firstOp) {
1226 cvtGlyphWidth(nOps == 3, charBuf, pDict);
1227 firstOp = gFalse;
1228 }
1229 if (openPath) {
1230 charBuf->append((char)9);
1231 openPath = gFalse;
1232 }
1233 if (nOps != 2) {
1234 //~ error(-1, "Wrong number of args (%d) to Type 2 rmoveto", nOps);
1235 }
1236 cvtNum(ops[0].num, ops[0].isFP, charBuf);
1237 cvtNum(ops[1].num, ops[1].isFP, charBuf);
1238 charBuf->append((char)21);
1239 nOps = 0;
1240 break;
1241 case 0x0016: // hmoveto
1242 if (firstOp) {
1243 cvtGlyphWidth(nOps == 2, charBuf, pDict);
1244 firstOp = gFalse;
1245 }
1246 if (openPath) {
1247 charBuf->append((char)9);
1248 openPath = gFalse;
1249 }
1250 if (nOps != 1) {
1251 //~ error(-1, "Wrong number of args (%d) to Type 2 hmoveto", nOps);
1252 }
1253 cvtNum(ops[0].num, ops[0].isFP, charBuf);
1254 charBuf->append((char)22);
1255 nOps = 0;
1256 break;
1257 case 0x0017: // vstemhm
1258 // ignored
1259 if (firstOp) {
1260 cvtGlyphWidth(nOps & 1, charBuf, pDict);
1261 firstOp = gFalse;
1262 }
1263 if (nOps & 1) {
1264 //~ error(-1, "Wrong number of args (%d) to Type 2 vstemhm", nOps);
1265 }
1266 nHints += nOps / 2;
1267 nOps = 0;
1268 break;
1269 case 0x0018: // rcurveline
1270 if (nOps < 8 || (nOps - 2) % 6 != 0) {
1271 //~ error(-1, "Wrong number of args (%d) to Type 2 rcurveline", nOps);
1272 }
1273 for (k = 0; k < nOps - 2; k += 6) {
1274 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1275 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1276 cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1277 cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1278 cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
1279 cvtNum(ops[k+5].num, ops[k+5].isFP, charBuf);
1280 charBuf->append((char)8);
1281 }
1282 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1283 cvtNum(ops[k+1].num, ops[k].isFP, charBuf);
1284 charBuf->append((char)5);
1285 nOps = 0;
1286 openPath = gTrue;
1287 break;
1288 case 0x0019: // rlinecurve
1289 if (nOps < 8 || (nOps - 6) % 2 != 0) {
1290 //~ error(-1, "Wrong number of args (%d) to Type 2 rlinecurve", nOps);
1291 }
1292 for (k = 0; k < nOps - 6; k += 2) {
1293 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1294 cvtNum(ops[k+1].num, ops[k].isFP, charBuf);
1295 charBuf->append((char)5);
1296 }
1297 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1298 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1299 cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1300 cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1301 cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
1302 cvtNum(ops[k+5].num, ops[k+5].isFP, charBuf);
1303 charBuf->append((char)8);
1304 nOps = 0;
1305 openPath = gTrue;
1306 break;
1307 case 0x001a: // vvcurveto
1308 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
1309 //~ error(-1, "Wrong number of args (%d) to Type 2 vvcurveto", nOps);
1310 }
1311 if (nOps % 2 == 1) {
1312 cvtNum(ops[0].num, ops[0].isFP, charBuf);
1313 cvtNum(ops[1].num, ops[1].isFP, charBuf);
1314 cvtNum(ops[2].num, ops[2].isFP, charBuf);
1315 cvtNum(ops[3].num, ops[3].isFP, charBuf);
1316 cvtNum(0, gFalse, charBuf);
1317 cvtNum(ops[4].num, ops[4].isFP, charBuf);
1318 charBuf->append((char)8);
1319 k = 5;
1320 } else {
1321 k = 0;
1322 }
1323 for (; k < nOps; k += 4) {
1324 cvtNum(0, gFalse, charBuf);
1325 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1326 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1327 cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1328 cvtNum(0, gFalse, charBuf);
1329 cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1330 charBuf->append((char)8);
1331 }
1332 nOps = 0;
1333 openPath = gTrue;
1334 break;
1335 case 0x001b: // hhcurveto
1336 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
1337 //~ error(-1, "Wrong number of args (%d) to Type 2 hhcurveto", nOps);
1338 }
1339 if (nOps % 2 == 1) {
1340 cvtNum(ops[1].num, ops[1].isFP, charBuf);
1341 cvtNum(ops[0].num, ops[0].isFP, charBuf);
1342 cvtNum(ops[2].num, ops[2].isFP, charBuf);
1343 cvtNum(ops[3].num, ops[3].isFP, charBuf);
1344 cvtNum(ops[4].num, ops[4].isFP, charBuf);
1345 cvtNum(0, gFalse, charBuf);
1346 charBuf->append((char)8);
1347 k = 5;
1348 } else {
1349 k = 0;
1350 }
1351 for (; k < nOps; k += 4) {
1352 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1353 cvtNum(0, gFalse, charBuf);
1354 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1355 cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1356 cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1357 cvtNum(0, gFalse, charBuf);
1358 charBuf->append((char)8);
1359 }
1360 nOps = 0;
1361 openPath = gTrue;
1362 break;
1363 case 0x001d: // callgsubr
1364 if (nOps >= 1) {
1365 k = gsubrBias + (int)ops[nOps - 1].num;
1366 --nOps;
1367 ok = gTrue;
1368 getIndexVal(&gsubrIdx, k, &val, &ok);
1369 if (ok) {
1370 cvtGlyph(val.pos, val.len, charBuf, subrIdx, pDict, gFalse);
1371 }
1372 } else {
1373 //~ error(-1, "Too few args to Type 2 callgsubr");
1374 }
1375 // don't clear the stack
1376 break;
1377 case 0x001e: // vhcurveto
1378 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
1379 //~ error(-1, "Wrong number of args (%d) to Type 2 vhcurveto", nOps);
1380 }
1381 for (k = 0; k < nOps && k != nOps-5; k += 4) {
1382 if (k % 8 == 0) {
1383 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1384 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1385 cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1386 cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1387 charBuf->append((char)30);
1388 } else {
1389 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1390 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1391 cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1392 cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1393 charBuf->append((char)31);
1394 }
1395 }
1396 if (k == nOps-5) {
1397 if (k % 8 == 0) {
1398 cvtNum(0, gFalse, charBuf);
1399 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1400 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1401 cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1402 cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1403 cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
1404 } else {
1405 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1406 cvtNum(0, gFalse, charBuf);
1407 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1408 cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1409 cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
1410 cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1411 }
1412 charBuf->append((char)8);
1413 }
1414 nOps = 0;
1415 openPath = gTrue;
1416 break;
1417 case 0x001f: // hvcurveto
1418 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
1419 //~ error(-1, "Wrong number of args (%d) to Type 2 hvcurveto", nOps);
1420 }
1421 for (k = 0; k < nOps && k != nOps-5; k += 4) {
1422 if (k % 8 == 0) {
1423 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1424 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1425 cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1426 cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1427 charBuf->append((char)31);
1428 } else {
1429 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1430 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1431 cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1432 cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1433 charBuf->append((char)30);
1434 }
1435 }
1436 if (k == nOps-5) {
1437 if (k % 8 == 0) {
1438 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1439 cvtNum(0, gFalse, charBuf);
1440 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1441 cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1442 cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
1443 cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1444 } else {
1445 cvtNum(0, gFalse, charBuf);
1446 cvtNum(ops[k].num, ops[k].isFP, charBuf);
1447 cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1448 cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1449 cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1450 cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
1451 }
1452 charBuf->append((char)8);
1453 }
1454 nOps = 0;
1455 openPath = gTrue;
1456 break;
1457 case 0x0c00: // dotsection (should be Type 1 only?)
1458 // ignored
1459 nOps = 0;
1460 break;
1461 case 0x0c03: // and
1462 case 0x0c04: // or
1463 case 0x0c05: // not
1464 case 0x0c08: // store
1465 case 0x0c09: // abs
1466 case 0x0c0a: // add
1467 case 0x0c0b: // sub
1468 case 0x0c0c: // div
1469 case 0x0c0d: // load
1470 case 0x0c0e: // neg
1471 case 0x0c0f: // eq
1472 case 0x0c12: // drop
1473 case 0x0c14: // put
1474 case 0x0c15: // get
1475 case 0x0c16: // ifelse
1476 case 0x0c17: // random
1477 case 0x0c18: // mul
1478 case 0x0c1a: // sqrt
1479 case 0x0c1b: // dup
1480 case 0x0c1c: // exch
1481 case 0x0c1d: // index
1482 case 0x0c1e: // roll
1483 //~ error(-1, "Unimplemented Type 2 charstring op: 12.%d", file[i+1]);
1484 nOps = 0;
1485 break;
1486 case 0x0c22: // hflex
1487 if (nOps != 7) {
1488 //~ error(-1, "Wrong number of args (%d) to Type 2 hflex", nOps);
1489 }
1490 cvtNum(ops[0].num, ops[0].isFP, charBuf);
1491 cvtNum(0, gFalse, charBuf);
1492 cvtNum(ops[1].num, ops[1].isFP, charBuf);
1493 cvtNum(ops[2].num, ops[2].isFP, charBuf);
1494 cvtNum(ops[3].num, ops[3].isFP, charBuf);
1495 cvtNum(0, gFalse, charBuf);
1496 charBuf->append((char)8);
1497 cvtNum(ops[4].num, ops[4].isFP, charBuf);
1498 cvtNum(0, gFalse, charBuf);
1499 cvtNum(ops[5].num, ops[5].isFP, charBuf);
1500 cvtNum(-ops[2].num, ops[2].isFP, charBuf);
1501 cvtNum(ops[6].num, ops[6].isFP, charBuf);
1502 cvtNum(0, gFalse, charBuf);
1503 charBuf->append((char)8);
1504 nOps = 0;
1505 openPath = gTrue;
1506 break;
1507 case 0x0c23: // flex
1508 if (nOps != 13) {
1509 //~ error(-1, "Wrong number of args (%d) to Type 2 flex", nOps);
1510 }
1511 cvtNum(ops[0].num, ops[0].isFP, charBuf);
1512 cvtNum(ops[1].num, ops[1].isFP, charBuf);
1513 cvtNum(ops[2].num, ops[2].isFP, charBuf);
1514 cvtNum(ops[3].num, ops[3].isFP, charBuf);
1515 cvtNum(ops[4].num, ops[4].isFP, charBuf);
1516 cvtNum(ops[5].num, ops[5].isFP, charBuf);
1517 charBuf->append((char)8);
1518 cvtNum(ops[6].num, ops[6].isFP, charBuf);
1519 cvtNum(ops[7].num, ops[7].isFP, charBuf);
1520 cvtNum(ops[8].num, ops[8].isFP, charBuf);
1521 cvtNum(ops[9].num, ops[9].isFP, charBuf);
1522 cvtNum(ops[10].num, ops[10].isFP, charBuf);
1523 cvtNum(ops[11].num, ops[11].isFP, charBuf);
1524 charBuf->append((char)8);
1525 nOps = 0;
1526 openPath = gTrue;
1527 break;
1528 case 0x0c24: // hflex1
1529 if (nOps != 9) {
1530 //~ error(-1, "Wrong number of args (%d) to Type 2 hflex1", nOps);
1531 }
1532 cvtNum(ops[0].num, ops[0].isFP, charBuf);
1533 cvtNum(ops[1].num, ops[1].isFP, charBuf);
1534 cvtNum(ops[2].num, ops[2].isFP, charBuf);
1535 cvtNum(ops[3].num, ops[3].isFP, charBuf);
1536 cvtNum(ops[4].num, ops[4].isFP, charBuf);
1537 cvtNum(0, gFalse, charBuf);
1538 charBuf->append((char)8);
1539 cvtNum(ops[5].num, ops[5].isFP, charBuf);
1540 cvtNum(0, gFalse, charBuf);
1541 cvtNum(ops[6].num, ops[6].isFP, charBuf);
1542 cvtNum(ops[7].num, ops[7].isFP, charBuf);
1543 cvtNum(ops[8].num, ops[8].isFP, charBuf);
1544 cvtNum(-(ops[1].num + ops[3].num + ops[7].num),
1545 ops[1].isFP | ops[3].isFP | ops[7].isFP, charBuf);
1546 charBuf->append((char)8);
1547 nOps = 0;
1548 openPath = gTrue;
1549 break;
1550 case 0x0c25: // flex1
1551 if (nOps != 11) {
1552 //~ error(-1, "Wrong number of args (%d) to Type 2 flex1", nOps);
1553 }
1554 cvtNum(ops[0].num, ops[0].isFP, charBuf);
1555 cvtNum(ops[1].num, ops[1].isFP, charBuf);
1556 cvtNum(ops[2].num, ops[2].isFP, charBuf);
1557 cvtNum(ops[3].num, ops[3].isFP, charBuf);
1558 cvtNum(ops[4].num, ops[4].isFP, charBuf);
1559 cvtNum(ops[5].num, ops[5].isFP, charBuf);
1560 charBuf->append((char)8);
1561 cvtNum(ops[6].num, ops[6].isFP, charBuf);
1562 cvtNum(ops[7].num, ops[7].isFP, charBuf);
1563 cvtNum(ops[8].num, ops[8].isFP, charBuf);
1564 cvtNum(ops[9].num, ops[9].isFP, charBuf);
1565 dx = ops[0].num + ops[2].num + ops[4].num + ops[6].num + ops[8].num;
1566 dy = ops[1].num + ops[3].num + ops[5].num + ops[7].num + ops[9].num;
1567 if (fabs(dx) > fabs(dy)) {
1568 cvtNum(ops[10].num, ops[10].isFP, charBuf);
1569 cvtNum(-dy, ops[1].isFP | ops[3].isFP | ops[5].isFP |
1570 ops[7].isFP | ops[9].isFP, charBuf);
1571 } else {
1572 cvtNum(-dx, ops[0].isFP | ops[2].isFP | ops[4].isFP |
1573 ops[6].isFP | ops[8].isFP, charBuf);
1574 cvtNum(ops[10].num, ops[10].isFP, charBuf);
1575 }
1576 charBuf->append((char)8);
1577 nOps = 0;
1578 openPath = gTrue;
1579 break;
1580 default:
1581 //~ error(-1, "Illegal Type 2 charstring op: %04x",
1582 //~ ops[nOps].op);
1583 nOps = 0;
1584 break;
1585 }
1586 }
1587 }
1588
1589 // charstring encryption
1590 if (top) {
1591 r2 = 4330;
1592 for (i = start; i < charBuf->getLength(); ++i) {
1593 byte = charBuf->getChar(i) ^ (r2 >> 8);
1594 charBuf->setChar(i, byte);
1595 r2 = (byte + r2) * 52845 + 22719;
1596 }
1597 }
1598}
1599
1600void FoFiType1C::cvtGlyphWidth(GBool useOp, GString *charBuf,
1601 Type1CPrivateDict *pDict) {
1602 double w;
1603 GBool wFP;
1604 int i;
1605
1606 if (useOp) {
1607 w = pDict->nominalWidthX + ops[0].num;
1608 wFP = pDict->nominalWidthXFP | ops[0].isFP;
1609 for (i = 1; i < nOps; ++i) {
1610 ops[i-1] = ops[i];
1611 }
1612 --nOps;
1613 } else {
1614 w = pDict->defaultWidthX;
1615 wFP = pDict->defaultWidthXFP;
1616 }
1617 cvtNum(0, gFalse, charBuf);
1618 cvtNum(w, wFP, charBuf);
1619 charBuf->append((char)13);
1620}
1621
1622void FoFiType1C::cvtNum(double x, GBool isFP, GString *charBuf) {
1623 Guchar buf[12];
1624 int y, n;
1625
1626 n = 0;
1627 if (isFP) {
1628 if (x >= -32768 && x < 32768) {
1629 y = (int)(x * 256.0);
1630 buf[0] = 255;
1631 buf[1] = (Guchar)(y >> 24);
1632 buf[2] = (Guchar)(y >> 16);
1633 buf[3] = (Guchar)(y >> 8);
1634 buf[4] = (Guchar)y;
1635 buf[5] = 255;
1636 buf[6] = 0;
1637 buf[7] = 0;
1638 buf[8] = 1;
1639 buf[9] = 0;
1640 buf[10] = 12;
1641 buf[11] = 12;
1642 n = 12;
1643 } else {
1644 //~ error(-1, "Type 2 fixed point constant out of range");
1645 }
1646 } else {
1647 y = (int)x;
1648 if (y >= -107 && y <= 107) {
1649 buf[0] = (Guchar)(y + 139);
1650 n = 1;
1651 } else if (y > 107 && y <= 1131) {
1652 y -= 108;
1653 buf[0] = (Guchar)((y >> 8) + 247);
1654 buf[1] = (Guchar)(y & 0xff);
1655 n = 2;
1656 } else if (y < -107 && y >= -1131) {
1657 y = -y - 108;
1658 buf[0] = (Guchar)((y >> 8) + 251);
1659 buf[1] = (Guchar)(y & 0xff);
1660 n = 2;
1661 } else {
1662 buf[0] = 255;
1663 buf[1] = (Guchar)(y >> 24);
1664 buf[2] = (Guchar)(y >> 16);
1665 buf[3] = (Guchar)(y >> 8);
1666 buf[4] = (Guchar)y;
1667 n = 5;
1668 }
1669 }
1670 charBuf->append((char *)buf, n);
1671}
1672
1673void FoFiType1C::eexecWrite(Type1CEexecBuf *eb, char *s) {
1674 Guchar *p;
1675 Guchar x;
1676
1677 for (p = (Guchar *)s; *p; ++p) {
1678 x = *p ^ (eb->r1 >> 8);
1679 eb->r1 = (x + eb->r1) * 52845 + 22719;
1680 if (eb->ascii) {
1681 (*eb->outputFunc)(eb->outputStream, &hexChars[x >> 4], 1);
1682 (*eb->outputFunc)(eb->outputStream, &hexChars[x & 0x0f], 1);
1683 eb->line += 2;
1684 if (eb->line == 64) {
1685 (*eb->outputFunc)(eb->outputStream, "\n", 1);
1686 eb->line = 0;
1687 }
1688 } else {
1689 (*eb->outputFunc)(eb->outputStream, (char *)&x, 1);
1690 }
1691 }
1692}
1693
1694void FoFiType1C::eexecWriteCharstring(Type1CEexecBuf *eb,
1695 Guchar *s, int n) {
1696 Guchar x;
1697 int i;
1698
1699 // eexec encryption
1700 for (i = 0; i < n; ++i) {
1701 x = s[i] ^ (eb->r1 >> 8);
1702 eb->r1 = (x + eb->r1) * 52845 + 22719;
1703 if (eb->ascii) {
1704 (*eb->outputFunc)(eb->outputStream, &hexChars[x >> 4], 1);
1705 (*eb->outputFunc)(eb->outputStream, &hexChars[x & 0x0f], 1);
1706 eb->line += 2;
1707 if (eb->line == 64) {
1708 (*eb->outputFunc)(eb->outputStream, "\n", 1);
1709 eb->line = 0;
1710 }
1711 } else {
1712 (*eb->outputFunc)(eb->outputStream, (char *)&x, 1);
1713 }
1714 }
1715}
1716
1717GBool FoFiType1C::parse() {
1718 Type1CIndex fdIdx;
1719 Type1CIndexVal val;
1720 int i;
1721
1722 parsedOk = gTrue;
1723
1724 // some tools embed Type 1C fonts with an extra whitespace char at
1725 // the beginning
1726 if (len > 0 && file[0] != '\x01') {
1727 ++file;
1728 --len;
1729 }
1730
1731 // find the indexes
1732 getIndex(getU8(2, &parsedOk), &nameIdx, &parsedOk);
1733 getIndex(nameIdx.endPos, &topDictIdx, &parsedOk);
1734 getIndex(topDictIdx.endPos, &stringIdx, &parsedOk);
1735 getIndex(stringIdx.endPos, &gsubrIdx, &parsedOk);
1736 if (!parsedOk) {
1737 return gFalse;
1738 }
1739 gsubrBias = (gsubrIdx.len < 1240) ? 107
1740 : (gsubrIdx.len < 33900) ? 1131 : 32768;
1741
1742 // read the first font name
1743 getIndexVal(&nameIdx, 0, &val, &parsedOk);
1744 if (!parsedOk) {
1745 return gFalse;
1746 }
1747 name = new GString((char *)&file[val.pos], val.len);
1748
1749 // read the top dict for the first font
1750 readTopDict();
1751
1752 // for CID fonts: read the FDArray dicts and private dicts
1753 if (topDict.firstOp == 0x0c1e) {
1754 if (topDict.fdArrayOffset == 0) {
1755 nFDs = 1;
1756 privateDicts = (Type1CPrivateDict *)gmalloc(sizeof(Type1CPrivateDict));
1757 readPrivateDict(0, 0, &privateDicts[0]);
1758 } else {
1759 getIndex(topDict.fdArrayOffset, &fdIdx, &parsedOk);
1760 if (!parsedOk) {
1761 return gFalse;
1762 }
1763 nFDs = fdIdx.len;
1764 privateDicts = (Type1CPrivateDict *)
1765 gmallocn(nFDs, sizeof(Type1CPrivateDict));
1766 for (i = 0; i < nFDs; ++i) {
1767 getIndexVal(&fdIdx, i, &val, &parsedOk);
1768 if (!parsedOk) {
1769 return gFalse;
1770 }
1771 readFD(val.pos, val.len, &privateDicts[i]);
1772 }
1773 }
1774
1775 // for 8-bit fonts: read the private dict
1776 } else {
1777 privateDicts = (Type1CPrivateDict *)gmalloc(sizeof(Type1CPrivateDict));
1778 readPrivateDict(topDict.privateOffset, topDict.privateSize,
1779 &privateDicts[0]);
1780 }
1781
1782 // check for parse errors in the private dict(s)
1783 if (!parsedOk) {
1784 return gFalse;
1785 }
1786
1787 // get the charstrings index
1788 if (topDict.charStringsOffset <= 0) {
1789 parsedOk = gFalse;
1790 return gFalse;
1791 }
1792 getIndex(topDict.charStringsOffset, &charStringsIdx, &parsedOk);
1793 if (!parsedOk) {
1794 return gFalse;
1795 }
1796 nGlyphs = charStringsIdx.len;
1797
1798 // for CID fonts: read the FDSelect table
1799 if (topDict.firstOp == 0x0c1e) {
1800 readFDSelect();
1801 if (!parsedOk) {
1802 return gFalse;
1803 }
1804 }
1805
1806 // read the charset
1807 if (!readCharset()) {
1808 parsedOk = gFalse;
1809 return gFalse;
1810 }
1811
1812 // for 8-bit fonts: build the encoding
1813 if (topDict.firstOp != 0x0c14 && topDict.firstOp != 0x0c1e) {
1814 buildEncoding();
1815 if (!parsedOk) {
1816 return gFalse;
1817 }
1818 }
1819
1820 return parsedOk;
1821}
1822
1823void FoFiType1C::readTopDict() {
1824 Type1CIndexVal topDictPtr;
1825 int pos;
1826
1827 topDict.firstOp = -1;
1828 topDict.versionSID = 0;
1829 topDict.noticeSID = 0;
1830 topDict.copyrightSID = 0;
1831 topDict.fullNameSID = 0;
1832 topDict.familyNameSID = 0;
1833 topDict.weightSID = 0;
1834 topDict.isFixedPitch = 0;
1835 topDict.italicAngle = 0;
1836 topDict.underlinePosition = -100;
1837 topDict.underlineThickness = 50;
1838 topDict.paintType = 0;
1839 topDict.charstringType = 2;
1840 topDict.fontMatrix[0] = 0.001;
1841 topDict.fontMatrix[1] = 0;
1842 topDict.fontMatrix[2] = 0;
1843 topDict.fontMatrix[3] = 0.001;
1844 topDict.fontMatrix[4] = 0;
1845 topDict.fontMatrix[5] = 0;
1846 topDict.hasFontMatrix = gFalse;
1847 topDict.uniqueID = 0;
1848 topDict.fontBBox[0] = 0;
1849 topDict.fontBBox[1] = 0;
1850 topDict.fontBBox[2] = 0;
1851 topDict.fontBBox[3] = 0;
1852 topDict.strokeWidth = 0;
1853 topDict.charsetOffset = 0;
1854 topDict.encodingOffset = 0;
1855 topDict.charStringsOffset = 0;
1856 topDict.privateSize = 0;
1857 topDict.privateOffset = 0;
1858 topDict.registrySID = 0;
1859 topDict.orderingSID = 0;
1860 topDict.supplement = 0;
1861 topDict.fdArrayOffset = 0;
1862 topDict.fdSelectOffset = 0;
1863
1864 getIndexVal(&topDictIdx, 0, &topDictPtr, &parsedOk);
1865 pos = topDictPtr.pos;
1866 nOps = 0;
1867 while (pos < topDictPtr.pos + topDictPtr.len) {
1868 pos = getOp(pos, gFalse, &parsedOk);
1869 if (!parsedOk) {
1870 break;
1871 }
1872 if (!ops[nOps - 1].isNum) {
1873 --nOps; // drop the operator
1874 if (topDict.firstOp < 0) {
1875 topDict.firstOp = ops[nOps].op;
1876 }
1877 switch (ops[nOps].op) {
1878 case 0x0000: topDict.versionSID = (int)ops[0].num; break;
1879 case 0x0001: topDict.noticeSID = (int)ops[0].num; break;
1880 case 0x0c00: topDict.copyrightSID = (int)ops[0].num; break;
1881 case 0x0002: topDict.fullNameSID = (int)ops[0].num; break;
1882 case 0x0003: topDict.familyNameSID = (int)ops[0].num; break;
1883 case 0x0004: topDict.weightSID = (int)ops[0].num; break;
1884 case 0x0c01: topDict.isFixedPitch = (int)ops[0].num; break;
1885 case 0x0c02: topDict.italicAngle = ops[0].num; break;
1886 case 0x0c03: topDict.underlinePosition = ops[0].num; break;
1887 case 0x0c04: topDict.underlineThickness = ops[0].num; break;
1888 case 0x0c05: topDict.paintType = (int)ops[0].num; break;
1889 case 0x0c06: topDict.charstringType = (int)ops[0].num; break;
1890 case 0x0c07: topDict.fontMatrix[0] = ops[0].num;
1891 topDict.fontMatrix[1] = ops[1].num;
1892 topDict.fontMatrix[2] = ops[2].num;
1893 topDict.fontMatrix[3] = ops[3].num;
1894 topDict.fontMatrix[4] = ops[4].num;
1895 topDict.fontMatrix[5] = ops[5].num;
1896 topDict.hasFontMatrix = gTrue; break;
1897 case 0x000d: topDict.uniqueID = (int)ops[0].num; break;
1898 case 0x0005: topDict.fontBBox[0] = ops[0].num;
1899 topDict.fontBBox[1] = ops[1].num;
1900 topDict.fontBBox[2] = ops[2].num;
1901 topDict.fontBBox[3] = ops[3].num; break;
1902 case 0x0c08: topDict.strokeWidth = ops[0].num; break;
1903 case 0x000f: topDict.charsetOffset = (int)ops[0].num; break;
1904 case 0x0010: topDict.encodingOffset = (int)ops[0].num; break;
1905 case 0x0011: topDict.charStringsOffset = (int)ops[0].num; break;
1906 case 0x0012: topDict.privateSize = (int)ops[0].num;
1907 topDict.privateOffset = (int)ops[1].num; break;
1908 case 0x0c1e: topDict.registrySID = (int)ops[0].num;
1909 topDict.orderingSID = (int)ops[1].num;
1910 topDict.supplement = (int)ops[2].num; break;
1911 case 0x0c24: topDict.fdArrayOffset = (int)ops[0].num; break;
1912 case 0x0c25: topDict.fdSelectOffset = (int)ops[0].num; break;
1913 }
1914 nOps = 0;
1915 }
1916 }
1917}
1918
1919// Read a CID font dict (FD) - this pulls out the private dict
1920// pointer, and reads the private dict. It also pulls the FontMatrix
1921// (if any) out of the FD.
1922void FoFiType1C::readFD(int offset, int length, Type1CPrivateDict *pDict) {
1923 int pos, pSize, pOffset;
1924 double fontMatrix[6];
1925 GBool hasFontMatrix;
1926
1927 hasFontMatrix = gFalse;
1928 pSize = pOffset = 0;
1929 pos = offset;
1930 nOps = 0;
1931 while (pos < offset + length) {
1932 pos = getOp(pos, gFalse, &parsedOk);
1933 if (!parsedOk) {
1934 return;
1935 }
1936 if (!ops[nOps - 1].isNum) {
1937 if (ops[nOps - 1].op == 0x0012) {
1938 if (nOps < 3) {
1939 parsedOk = gFalse;
1940 return;
1941 }
1942 pSize = (int)ops[0].num;
1943 pOffset = (int)ops[1].num;
1944 break;
1945 } else if (ops[nOps - 1].op == 0x0c07) {
1946 fontMatrix[0] = ops[0].num;
1947 fontMatrix[1] = ops[1].num;
1948 fontMatrix[2] = ops[2].num;
1949 fontMatrix[3] = ops[3].num;
1950 fontMatrix[4] = ops[4].num;
1951 fontMatrix[5] = ops[5].num;
1952 hasFontMatrix = gTrue;
1953 }
1954 nOps = 0;
1955 }
1956 }
1957 readPrivateDict(pOffset, pSize, pDict);
1958 if (hasFontMatrix) {
1959 pDict->fontMatrix[0] = fontMatrix[0];
1960 pDict->fontMatrix[1] = fontMatrix[1];
1961 pDict->fontMatrix[2] = fontMatrix[2];
1962 pDict->fontMatrix[3] = fontMatrix[3];
1963 pDict->fontMatrix[4] = fontMatrix[4];
1964 pDict->fontMatrix[5] = fontMatrix[5];
1965 pDict->hasFontMatrix = gTrue;
1966 }
1967}
1968
1969void FoFiType1C::readPrivateDict(int offset, int length,
1970 Type1CPrivateDict *pDict) {
1971 int pos;
1972
1973 pDict->hasFontMatrix = gFalse;
1974 pDict->nBlueValues = 0;
1975 pDict->nOtherBlues = 0;
1976 pDict->nFamilyBlues = 0;
1977 pDict->nFamilyOtherBlues = 0;
1978 pDict->blueScale = 0.039625;
1979 pDict->blueShift = 7;
1980 pDict->blueFuzz = 1;
1981 pDict->hasStdHW = gFalse;
1982 pDict->hasStdVW = gFalse;
1983 pDict->nStemSnapH = 0;
1984 pDict->nStemSnapV = 0;
1985 pDict->hasForceBold = gFalse;
1986 pDict->forceBoldThreshold = 0;
1987 pDict->languageGroup = 0;
1988 pDict->expansionFactor = 0.06;
1989 pDict->initialRandomSeed = 0;
1990 pDict->subrsOffset = 0;
1991 pDict->defaultWidthX = 0;
1992 pDict->defaultWidthXFP = gFalse;
1993 pDict->nominalWidthX = 0;
1994 pDict->nominalWidthXFP = gFalse;
1995
1996 // no dictionary
1997 if (offset == 0 || length == 0) {
1998 return;
1999 }
2000
2001 pos = offset;
2002 nOps = 0;
2003 while (pos < offset + length) {
2004 pos = getOp(pos, gFalse, &parsedOk);
2005 if (!parsedOk) {
2006 break;
2007 }
2008 if (!ops[nOps - 1].isNum) {
2009 --nOps; // drop the operator
2010 switch (ops[nOps].op) {
2011 case 0x0006:
2012 pDict->nBlueValues = getDeltaIntArray(pDict->blueValues,
2013 type1CMaxBlueValues);
2014 break;
2015 case 0x0007:
2016 pDict->nOtherBlues = getDeltaIntArray(pDict->otherBlues,
2017 type1CMaxOtherBlues);
2018 break;
2019 case 0x0008:
2020 pDict->nFamilyBlues = getDeltaIntArray(pDict->familyBlues,
2021 type1CMaxBlueValues);
2022 break;
2023 case 0x0009:
2024 pDict->nFamilyOtherBlues = getDeltaIntArray(pDict->familyOtherBlues,
2025 type1CMaxOtherBlues);
2026 break;
2027 case 0x0c09:
2028 pDict->blueScale = ops[0].num;
2029 break;
2030 case 0x0c0a:
2031 pDict->blueShift = (int)ops[0].num;
2032 break;
2033 case 0x0c0b:
2034 pDict->blueFuzz = (int)ops[0].num;
2035 break;
2036 case 0x000a:
2037 pDict->stdHW = ops[0].num;
2038 pDict->hasStdHW = gTrue;
2039 break;
2040 case 0x000b:
2041 pDict->stdVW = ops[0].num;
2042 pDict->hasStdVW = gTrue;
2043 break;
2044 case 0x0c0c:
2045 pDict->nStemSnapH = getDeltaFPArray(pDict->stemSnapH,
2046 type1CMaxStemSnap);
2047 break;
2048 case 0x0c0d:
2049 pDict->nStemSnapV = getDeltaFPArray(pDict->stemSnapV,
2050 type1CMaxStemSnap);
2051 break;
2052 case 0x0c0e:
2053 pDict->forceBold = ops[0].num != 0;
2054 pDict->hasForceBold = gTrue;
2055 break;
2056 case 0x0c0f:
2057 pDict->forceBoldThreshold = ops[0].num;
2058 break;
2059 case 0x0c11:
2060 pDict->languageGroup = (int)ops[0].num;
2061 break;
2062 case 0x0c12:
2063 pDict->expansionFactor = ops[0].num;
2064 break;
2065 case 0x0c13:
2066 pDict->initialRandomSeed = (int)ops[0].num;
2067 break;
2068 case 0x0013:
2069 pDict->subrsOffset = offset + (int)ops[0].num;
2070 break;
2071 case 0x0014:
2072 pDict->defaultWidthX = ops[0].num;
2073 pDict->defaultWidthXFP = ops[0].isFP;
2074 break;
2075 case 0x0015:
2076 pDict->nominalWidthX = ops[0].num;
2077 pDict->nominalWidthXFP = ops[0].isFP;
2078 break;
2079 }
2080 nOps = 0;
2081 }
2082 }
2083}
2084
2085void FoFiType1C::readFDSelect() {
2086 int fdSelectFmt, pos, nRanges, gid0, gid1, fd, i, j;
2087
2088 fdSelect = (Guchar *)gmalloc(nGlyphs);
2089 if (topDict.fdSelectOffset == 0) {
2090 for (i = 0; i < nGlyphs; ++i) {
2091 fdSelect[i] = 0;
2092 }
2093 } else {
2094 pos = topDict.fdSelectOffset;
2095 fdSelectFmt = getU8(pos++, &parsedOk);
2096 if (!parsedOk) {
2097 return;
2098 }
2099 if (fdSelectFmt == 0) {
2100 if (!checkRegion(pos, nGlyphs)) {
2101 parsedOk = gFalse;
2102 return;
2103 }
2104 memcpy(fdSelect, file + pos, nGlyphs);
2105 } else if (fdSelectFmt == 3) {
2106 nRanges = getU16BE(pos, &parsedOk);
2107 pos += 2;
2108 gid0 = getU16BE(pos, &parsedOk);
2109 pos += 2;
2110 for (i = 1; i <= nRanges; ++i) {
2111 fd = getU8(pos++, &parsedOk);
2112 gid1 = getU16BE(pos, &parsedOk);
2113 if (!parsedOk) {
2114 return;
2115 }
2116 pos += 2;
2117 if (gid0 > gid1 || gid1 > nGlyphs) {
2118 //~ error(-1, "Bad FDSelect table in CID font");
2119 parsedOk = gFalse;
2120 return;
2121 }
2122 for (j = gid0; j < gid1; ++j) {
2123 fdSelect[j] = fd;
2124 }
2125 gid0 = gid1;
2126 }
2127 } else {
2128 //~ error(-1, "Unknown FDSelect table format in CID font");
2129 for (i = 0; i < nGlyphs; ++i) {
2130 fdSelect[i] = 0;
2131 }
2132 }
2133 }
2134}
2135
2136void FoFiType1C::buildEncoding() {
2137 char buf[256];
2138 int nCodes, nRanges, encFormat;
2139 int pos, c, sid, nLeft, nSups, i, j;
2140
2141 if (topDict.encodingOffset == 0) {
2142 encoding = fofiType1StandardEncoding;
2143
2144 } else if (topDict.encodingOffset == 1) {
2145 encoding = fofiType1ExpertEncoding;
2146
2147 } else {
2148 encoding = (char **)gmallocn(256, sizeof(char *));
2149 for (i = 0; i < 256; ++i) {
2150 encoding[i] = NULL;
2151 }
2152 pos = topDict.encodingOffset;
2153 encFormat = getU8(pos++, &parsedOk);
2154 if (!parsedOk) {
2155 return;
2156 }
2157 if ((encFormat & 0x7f) == 0) {
2158 nCodes = 1 + getU8(pos++, &parsedOk);
2159 if (!parsedOk) {
2160 return;
2161 }
2162 if (nCodes > nGlyphs) {
2163 nCodes = nGlyphs;
2164 }
2165 for (i = 1; i < nCodes; ++i) {
2166 c = getU8(pos++, &parsedOk);
2167 if (!parsedOk) {
2168 return;
2169 }
2170 if (encoding[c]) {
2171 gfree(encoding[c]);
2172 }
2173 encoding[c] = copyString(getString(charset[i], buf, &parsedOk));
2174 }
2175 } else if ((encFormat & 0x7f) == 1) {
2176 nRanges = getU8(pos++, &parsedOk);
2177 if (!parsedOk) {
2178 return;
2179 }
2180 nCodes = 1;
2181 for (i = 0; i < nRanges; ++i) {
2182 c = getU8(pos++, &parsedOk);
2183 nLeft = getU8(pos++, &parsedOk);
2184 if (!parsedOk) {
2185 return;
2186 }
2187 for (j = 0; j <= nLeft && nCodes < nGlyphs; ++j) {
2188 if (c < 256) {
2189 if (encoding[c]) {
2190 gfree(encoding[c]);
2191 }
2192 encoding[c] = copyString(getString(charset[nCodes], buf,
2193 &parsedOk));
2194 }
2195 ++nCodes;
2196 ++c;
2197 }
2198 }
2199 }
2200 if (encFormat & 0x80) {
2201 nSups = getU8(pos++, &parsedOk);
2202 if (!parsedOk) {
2203 return;
2204 }
2205 for (i = 0; i < nSups; ++i) {
2206 c = getU8(pos++, &parsedOk);;
2207 if (!parsedOk) {
2208 return;;
2209 }
2210 sid = getU16BE(pos, &parsedOk);
2211 pos += 2;
2212 if (!parsedOk) {
2213 return;
2214 }
2215 if (encoding[c]) {
2216 gfree(encoding[c]);
2217 }
2218 encoding[c] = copyString(getString(sid, buf, &parsedOk));
2219 }
2220 }
2221 }
2222}
2223
2224GBool FoFiType1C::readCharset() {
2225 int charsetFormat, c, pos;
2226 int nLeft, i, j;
2227
2228 if (topDict.charsetOffset == 0) {
2229 charset = fofiType1CISOAdobeCharset;
2230 } else if (topDict.charsetOffset == 1) {
2231 charset = fofiType1CExpertCharset;
2232 } else if (topDict.charsetOffset == 2) {
2233 charset = fofiType1CExpertSubsetCharset;
2234 } else {
2235 charset = (Gushort *)gmallocn(nGlyphs, sizeof(Gushort));
2236 for (i = 0; i < nGlyphs; ++i) {
2237 charset[i] = 0;
2238 }
2239 pos = topDict.charsetOffset;
2240 charsetFormat = getU8(pos++, &parsedOk);
2241 if (charsetFormat == 0) {
2242 for (i = 1; i < nGlyphs; ++i) {
2243 charset[i] = (Gushort)getU16BE(pos, &parsedOk);
2244 pos += 2;
2245 if (!parsedOk) {
2246 break;
2247 }
2248 }
2249 } else if (charsetFormat == 1) {
2250 i = 1;
2251 while (i < nGlyphs) {
2252 c = getU16BE(pos, &parsedOk);
2253 pos += 2;
2254 nLeft = getU8(pos++, &parsedOk);
2255 if (!parsedOk) {
2256 break;
2257 }
2258 for (j = 0; j <= nLeft && i < nGlyphs; ++j) {
2259 charset[i++] = (Gushort)c++;
2260 }
2261 }
2262 } else if (charsetFormat == 2) {
2263 i = 1;
2264 while (i < nGlyphs) {
2265 c = getU16BE(pos, &parsedOk);
2266 pos += 2;
2267 nLeft = getU16BE(pos, &parsedOk);
2268 pos += 2;
2269 if (!parsedOk) {
2270 break;
2271 }
2272 for (j = 0; j <= nLeft && i < nGlyphs; ++j) {
2273 charset[i++] = (Gushort)c++;
2274 }
2275 }
2276 }
2277 if (!parsedOk) {
2278 gfree(charset);
2279 charset = NULL;
2280 return gFalse;
2281 }
2282 }
2283 return gTrue;
2284}
2285
2286int FoFiType1C::getOp(int pos, GBool charstring, GBool *ok) {
2287 static char nybChars[16] = "0123456789.ee -";
2288 Type1COp op;
2289 char buf[65];
2290 int b0, b1, nyb0, nyb1, x, i;
2291
2292 b0 = getU8(pos++, ok);
2293 op.isNum = gTrue;
2294 op.isFP = gFalse;
2295
2296 if (b0 == 28) {
2297 x = getU8(pos++, ok);
2298 x = (x << 8) | getU8(pos++, ok);
2299 if (x & 0x8000) {
2300 x |= ~0xffff;
2301 }
2302 op.num = x;
2303
2304 } else if (!charstring && b0 == 29) {
2305 x = getU8(pos++, ok);
2306 x = (x << 8) | getU8(pos++, ok);
2307 x = (x << 8) | getU8(pos++, ok);
2308 x = (x << 8) | getU8(pos++, ok);
2309 if (x & 0x80000000) {
2310 x |= ~0xffffffff;
2311 }
2312 op.num = x;
2313
2314 } else if (!charstring && b0 == 30) {
2315 i = 0;
2316 do {
2317 b1 = getU8(pos++, ok);
2318 nyb0 = b1 >> 4;
2319 nyb1 = b1 & 0x0f;
2320 if (nyb0 == 0xf) {
2321 break;
2322 }
2323 buf[i++] = nybChars[nyb0];
2324 if (i == 64) {
2325 break;
2326 }
2327 if (nyb0 == 0xc) {
2328 buf[i++] = '-';
2329 }
2330 if (i == 64) {
2331 break;
2332 }
2333 if (nyb1 == 0xf) {
2334 break;
2335 }
2336 buf[i++] = nybChars[nyb1];
2337 if (i == 64) {
2338 break;
2339 }
2340 if (nyb1 == 0xc) {
2341 buf[i++] = '-';
2342 }
2343 } while (i < 64);
2344 buf[i] = '\0';
2345 op.num = atof(buf);
2346 op.isFP = gTrue;
2347
2348 } else if (b0 >= 32 && b0 <= 246) {
2349 op.num = b0 - 139;
2350
2351 } else if (b0 >= 247 && b0 <= 250) {
2352 op.num = ((b0 - 247) << 8) + getU8(pos++, ok) + 108;
2353
2354 } else if (b0 >= 251 && b0 <= 254) {
2355 op.num = -((b0 - 251) << 8) - getU8(pos++, ok) - 108;
2356
2357 } else if (charstring && b0 == 255) {
2358 x = getU8(pos++, ok);
2359 x = (x << 8) | getU8(pos++, ok);
2360 x = (x << 8) | getU8(pos++, ok);
2361 x = (x << 8) | getU8(pos++, ok);
2362 if (x & 0x80000000) {
2363 x |= ~0xffffffff;
2364 }
2365 op.num = (double)x / 65536.0;
2366 op.isFP = gTrue;
2367
2368 } else if (b0 == 12) {
2369 op.isNum = gFalse;
2370 op.op = 0x0c00 + getU8(pos++, ok);
2371
2372 } else {
2373 op.isNum = gFalse;
2374 op.op = b0;
2375 }
2376
2377 if (nOps < 49) {
2378 ops[nOps++] = op;
2379 }
2380
2381 return pos;
2382}
2383
2384// Convert the delta-encoded ops array to an array of ints.
2385int FoFiType1C::getDeltaIntArray(int *arr, int maxLen) {
2386 int x;
2387 int n, i;
2388
2389 if ((n = nOps) > maxLen) {
2390 n = maxLen;
2391 }
2392 x = 0;
2393 for (i = 0; i < n; ++i) {
2394 x += (int)ops[i].num;
2395 arr[i] = x;
2396 }
2397 return n;
2398}
2399
2400// Convert the delta-encoded ops array to an array of doubles.
2401int FoFiType1C::getDeltaFPArray(double *arr, int maxLen) {
2402 double x;
2403 int n, i;
2404
2405 if ((n = nOps) > maxLen) {
2406 n = maxLen;
2407 }
2408 x = 0;
2409 for (i = 0; i < n; ++i) {
2410 x += ops[i].num;
2411 arr[i] = x;
2412 }
2413 return n;
2414}
2415
2416void FoFiType1C::getIndex(int pos, Type1CIndex *idx, GBool *ok) {
2417 idx->pos = pos;
2418 idx->len = getU16BE(pos, ok);
2419 if (idx->len == 0) {
2420 // empty indexes are legal and contain just the length field
2421 idx->offSize = 0;
2422 idx->startPos = idx->endPos = pos + 2;
2423 } else {
2424 idx->offSize = getU8(pos + 2, ok);
2425 if (idx->offSize < 1 || idx->offSize > 4) {
2426 *ok = gFalse;
2427 }
2428 idx->startPos = pos + 3 + (idx->len + 1) * idx->offSize - 1;
2429 if (idx->startPos < 0 || idx->startPos >= len) {
2430 *ok = gFalse;
2431 }
2432 idx->endPos = idx->startPos + getUVarBE(pos + 3 + idx->len * idx->offSize,
2433 idx->offSize, ok);
2434 if (idx->endPos < idx->startPos || idx->endPos > len) {
2435 *ok = gFalse;
2436 }
2437 }
2438}
2439
2440void FoFiType1C::getIndexVal(Type1CIndex *idx, int i,
2441 Type1CIndexVal *val, GBool *ok) {
2442 int pos0, pos1;
2443
2444 if (i < 0 || i >= idx->len) {
2445 *ok = gFalse;
2446 return;
2447 }
2448 pos0 = idx->startPos + getUVarBE(idx->pos + 3 + i * idx->offSize,
2449 idx->offSize, ok);
2450 pos1 = idx->startPos + getUVarBE(idx->pos + 3 + (i + 1) * idx->offSize,
2451 idx->offSize, ok);
2452 if (pos0 < idx->startPos || pos0 > idx->endPos ||
2453 pos1 <= idx->startPos || pos1 > idx->endPos ||
2454 pos1 < pos0) {
2455 *ok = gFalse;
2456 }
2457 val->pos = pos0;
2458 val->len = pos1 - pos0;
2459}
2460
2461char *FoFiType1C::getString(int sid, char *buf, GBool *ok) {
2462 Type1CIndexVal val;
2463 int n;
2464
2465 if (sid < 391) {
2466 strcpy(buf, fofiType1CStdStrings[sid]);
2467 } else {
2468 sid -= 391;
2469 getIndexVal(&stringIdx, sid, &val, ok);
2470 if (*ok) {
2471 if ((n = val.len) > 255) {
2472 n = 255;
2473 }
2474 strncpy(buf, (char *)&file[val.pos], n);
2475 buf[n] = '\0';
2476 } else {
2477 buf[0] = '\0';
2478 }
2479 }
2480 return buf;
2481}