FontFile.cpp
1//========================================================================
2//
3// FontFile.cpp
4//
5// Copyright 1999-2002 Glyph & Cog, LLC
6//
7//========================================================================
8
9#include <aconf.h>
10
11#ifdef USE_GCC_PRAGMAS
12#pragma implementation
13#endif
14
15#include <math.h>
16#include <stdlib.h>
17#include <stddef.h>
18#include <stdarg.h>
19#include <string.h>
20#include <ctype.h>
21#include "gmem.h"
22#include "Error.h"
23#include "GlobalParams.h"
24#include "CharCodeToUnicode.h"
25#include "FontEncodingTables.h"
26#include "FontFile.h"
27
28#include "CompactFontTables.h"
29
30//------------------------------------------------------------------------
31
32static inline const char *nextLine(const char *line, const char *end) {
33 while (line < end && *line != '\n' && *line != '\r')
34 ++line;
35 while (line < end && *line == '\n' || *line == '\r')
36 ++line;
37 return line;
38}
39
40static const char hexChars[17] = "0123456789ABCDEF";
41
42//------------------------------------------------------------------------
43// FontFile
44//------------------------------------------------------------------------
45
46FontFile::FontFile() {
47}
48
49FontFile::~FontFile() {
50}
51
52//------------------------------------------------------------------------
53// Type1FontFile
54//------------------------------------------------------------------------
55
56Type1FontFile::Type1FontFile(const char *file, int len) {
57 const char *line, *line1;
58 char *p, *p2;
59 GBool haveEncoding;
60 char buf[256];
61 char c;
62 int n, code, i, j;
63
64 name = NULL;
65 encoding = (char **)gmalloc(256 * sizeof(char *));
66 for (i = 0; i < 256; ++i) {
67 encoding[i] = NULL;
68 }
69 haveEncoding = gFalse;
70
71 for (i = 1, line = file;
72 i <= 100 && line < file + len && !haveEncoding;
73 ++i) {
74
75 // get font name
76 if (!strncmp(line, "/FontName", 9)) {
77 strncpy(buf, line, 255);
78 buf[255] = '\0';
79 if ((p = strchr(buf+9, '/')) &&
80 (p = strtok(p+1, " \t\n\r"))) {
81 name = copyString(p);
82 }
83 line = nextLine(line, file + len);
84
85 // get encoding
86 } else if (!strncmp(line, "/Encoding StandardEncoding def", 30)) {
87 for (j = 0; j < 256; ++j) {
88 if (standardEncoding[j]) {
89 encoding[j] = copyString(standardEncoding[j]);
90 }
91 }
92 haveEncoding = gTrue;
93 } else if (!strncmp(line, "/Encoding 256 array", 19)) {
94 for (j = 0; j < 300; ++j) {
95 line1 = nextLine(line, file + len);
96 if ((n = line1 - line) > 255) {
97 n = 255;
98 }
99 strncpy(buf, line, n);
100 buf[n] = '\0';
101 for (p = buf; *p == ' ' || *p == '\t'; ++p) ;
102 if (!strncmp(p, "dup", 3)) {
103 for (p += 3; *p == ' ' || *p == '\t'; ++p) ;
104 for (p2 = p; *p2 >= '0' && *p2 <= '9'; ++p2) ;
105 if (*p2) {
106 c = *p2;
107 *p2 = '\0';
108 if ((code = atoi(p)) < 256) {
109 *p2 = c;
110 for (p = p2; *p == ' ' || *p == '\t'; ++p) ;
111 if (*p == '/') {
112 ++p;
113 for (p2 = p; *p2 && *p2 != ' ' && *p2 != '\t'; ++p2) ;
114 *p2 = '\0';
115 encoding[code] = copyString(p);
116 }
117 }
118 }
119 } else {
120 if (strtok(buf, " \t") &&
121 (p = strtok(NULL, " \t\n\r")) && !strcmp(p, "def")) {
122 break;
123 }
124 }
125 line = line1;
126 }
127 //~ check for getinterval/putinterval junk
128 haveEncoding = gTrue;
129
130 } else {
131 line = nextLine(line, file + len);
132 }
133 }
134}
135
136Type1FontFile::~Type1FontFile() {
137 int i;
138
139 if (name) {
140 gfree(name);
141 }
142 for (i = 0; i < 256; ++i) {
143 gfree(encoding[i]);
144 }
145 gfree(encoding);
146}
147
148//------------------------------------------------------------------------
149// Type1CFontFile
150//------------------------------------------------------------------------
151
152struct Type1CTopDict {
153 int version;
154 int notice;
155 int copyright;
156 int fullName;
157 int familyName;
158 int weight;
159 int isFixedPitch;
160 double italicAngle;
161 double underlinePosition;
162 double underlineThickness;
163 int paintType;
164 int charstringType;
165 double fontMatrix[6];
166 int uniqueID;
167 double fontBBox[4];
168 double strokeWidth;
169 int charset;
170 int encoding;
171 int charStrings;
172 int privateSize;
173 int privateOffset;
174
175 //----- CIDFont entries
176 int registry;
177 int ordering;
178 int supplement;
179 int fdArrayOffset;
180 int fdSelectOffset;
181};
182
183struct Type1CPrivateDict {
184 GString *dictData;
185 int subrsOffset;
186 double defaultWidthX;
187 GBool defaultWidthXFP;
188 double nominalWidthX;
189 GBool nominalWidthXFP;
190};
191
192Type1CFontFile::Type1CFontFile(const char *fileA, int lenA) {
193 Guchar *nameIdxPtr, *idxPtr0, *idxPtr1;
194
195 file = fileA;
196 len = lenA;
197 name = NULL;
198 encoding = NULL;
199
200 // some tools embed Type 1C fonts with an extra whitespace char at
201 // the beginning
202 if (file[0] != '\x01') {
203 ++file;
204 }
205
206 // read header
207 topOffSize = file[3] & 0xff;
208
209 // read name index (first font only)
210 nameIdxPtr = (Guchar *)file + (file[2] & 0xff);
211 idxPtr0 = getIndexValPtr(nameIdxPtr, 0);
212 idxPtr1 = getIndexValPtr(nameIdxPtr, 1);
213 name = new GString((char *)idxPtr0, idxPtr1 - idxPtr0);
214
215 topDictIdxPtr = getIndexEnd(nameIdxPtr);
216 stringIdxPtr = getIndexEnd(topDictIdxPtr);
217 gsubrIdxPtr = getIndexEnd(stringIdxPtr);
218}
219
220Type1CFontFile::~Type1CFontFile() {
221 int i;
222
223 delete name;
224 if (encoding) {
225 for (i = 0; i < 256; ++i) {
226 gfree(encoding[i]);
227 }
228 gfree(encoding);
229 }
230}
231
232const char *Type1CFontFile::getName() {
233 return name->getCString();
234}
235
236char **Type1CFontFile::getEncoding() {
237 if (!encoding) {
238 readNameAndEncoding();
239 }
240 return encoding;
241}
242
243void Type1CFontFile::readNameAndEncoding() {
244 char buf[256];
245 Guchar *idxPtr0, *idxPtr1, *ptr;
246 int nGlyphs;
247 int nCodes, nRanges, nLeft, nSups;
248 Gushort *glyphNames;
249 int charset, enc, charstrings;
250 int encFormat;
251 int c, sid;
252 double x;
253 GBool isFP;
254 int key;
255 int i, j;
256
257 encoding = (char **)gmalloc(256 * sizeof(char *));
258 for (i = 0; i < 256; ++i) {
259 encoding[i] = NULL;
260 }
261
262 // read top dict (first font only)
263 idxPtr0 = getIndexValPtr(topDictIdxPtr, 0);
264 idxPtr1 = getIndexValPtr(topDictIdxPtr, 1);
265 charset = enc = charstrings = 0;
266 i = 0;
267 ptr = idxPtr0;
268 while (ptr < idxPtr1) {
269 if (*ptr <= 27 || *ptr == 31) {
270 key = *ptr++;
271 if (key == 0x0c) {
272 key = (key << 8) | *ptr++;
273 }
274 if (key == 0x0f) { // charset
275 charset = (int)op[0];
276 } else if (key == 0x10) { // encoding
277 enc = (int)op[0];
278 } else if (key == 0x11) { // charstrings
279 charstrings = (int)op[0];
280 }
281 i = 0;
282 } else {
283 x = getNum(&ptr, &isFP);
284 if (i < 48) {
285 op[i++] = x;
286 }
287 }
288 }
289
290 // get number of glyphs from charstrings index
291 nGlyphs = getIndexLen((Guchar *)file + charstrings);
292
293 // read charset (GID -> name mapping)
294 glyphNames = readCharset(charset, nGlyphs);
295
296 // read encoding (GID -> code mapping)
297 if (enc == 0) {
298 for (i = 0; i < 256; ++i) {
299 if (standardEncoding[i]) {
300 encoding[i] = copyString(standardEncoding[i]);
301 }
302 }
303 } else if (enc == 1) {
304 for (i = 0; i < 256; ++i) {
305 if (expertEncoding[i]) {
306 encoding[i] = copyString(expertEncoding[i]);
307 }
308 }
309 } else {
310 ptr = (Guchar *)file + enc;
311 encFormat = *ptr++;
312 if ((encFormat & 0x7f) == 0) {
313 nCodes = 1 + *ptr++;
314 if (nCodes > nGlyphs) {
315 nCodes = nGlyphs;
316 }
317 for (i = 1; i < nCodes; ++i) {
318 c = *ptr++;
319 encoding[c] = copyString(getString(glyphNames[i], buf));
320 }
321 } else if ((encFormat & 0x7f) == 1) {
322 nRanges = *ptr++;
323 nCodes = 1;
324 for (i = 0; i < nRanges; ++i) {
325 c = *ptr++;
326 nLeft = *ptr++;
327 for (j = 0; j <= nLeft && nCodes < nGlyphs; ++j) {
328 encoding[c] = copyString(getString(glyphNames[nCodes], buf));
329 ++nCodes;
330 ++c;
331 }
332 }
333 }
334 if (encFormat & 0x80) {
335 nSups = *ptr++;
336 for (i = 0; i < nSups; ++i) {
337 c = *ptr++;
338 sid = getWord(ptr, 2);
339 ptr += 2;
340 encoding[c] = copyString(getString(sid, buf));
341 }
342 }
343 }
344
345 if (charset > 2) {
346 gfree(glyphNames);
347 }
348}
349
350void Type1CFontFile::convertToType1(FontFileOutputFunc outputFuncA,
351 void *outputStreamA) {
352 Type1CTopDict dict;
353 Type1CPrivateDict privateDict;
354 char buf[512], eBuf[256];
355 Guchar *idxPtr0, *idxPtr1, *subrsIdxPtr, *charStringsIdxPtr, *ptr;
356 int nGlyphs, nCodes, nRanges, nLeft, nSups;
357 Gushort *glyphNames;
358 int encFormat, nSubrs, nCharStrings;
359 int c, sid;
360 int i, j, n;
361
362 outputFunc = outputFuncA;
363 outputStream = outputStreamA;
364
365 // read top dict (first font only)
366 readTopDict(&dict);
367
368 // get global subrs
369 //~ ... global subrs are unimplemented
370
371 // write header and font dictionary, up to encoding
372 (*outputFunc)(outputStream, "%!FontType1-1.0: ", 17);
373 (*outputFunc)(outputStream, name->getCString(), name->getLength());
374 if (dict.version != 0) {
375 getString(dict.version, buf);
376 (*outputFunc)(outputStream, buf, strlen(buf));
377 }
378 (*outputFunc)(outputStream, "\n", 1);
379 (*outputFunc)(outputStream, "11 dict begin\n", 14);
380 (*outputFunc)(outputStream, "/FontInfo 10 dict dup begin\n", 28);
381 if (dict.version != 0) {
382 (*outputFunc)(outputStream, "/version (", 10);
383 (*outputFunc)(outputStream, buf, strlen(buf));
384 (*outputFunc)(outputStream, ") readonly def\n", 15);
385 }
386 if (dict.notice != 0) {
387 getString(dict.notice, buf);
388 (*outputFunc)(outputStream, "/Notice (", 9);
389 (*outputFunc)(outputStream, buf, strlen(buf));
390 (*outputFunc)(outputStream, ") readonly def\n", 15);
391 }
392 if (dict.copyright != 0) {
393 getString(dict.copyright, buf);
394 (*outputFunc)(outputStream, "/Copyright (", 12);
395 (*outputFunc)(outputStream, buf, strlen(buf));
396 (*outputFunc)(outputStream, ") readonly def\n", 15);
397 }
398 if (dict.fullName != 0) {
399 getString(dict.fullName, buf);
400 (*outputFunc)(outputStream, "/FullName (", 11);
401 (*outputFunc)(outputStream, buf, strlen(buf));
402 (*outputFunc)(outputStream, ") readonly def\n", 15);
403 }
404 if (dict.familyName != 0) {
405 getString(dict.familyName, buf);
406 (*outputFunc)(outputStream, "/FamilyName (", 13);
407 (*outputFunc)(outputStream, buf, strlen(buf));
408 (*outputFunc)(outputStream, ") readonly def\n", 15);
409 }
410 if (dict.weight != 0) {
411 getString(dict.weight, buf);
412 (*outputFunc)(outputStream, "/Weight (", 9);
413 (*outputFunc)(outputStream, buf, strlen(buf));
414 (*outputFunc)(outputStream, ") readonly def\n", 15);
415 }
416 if (dict.isFixedPitch) {
417 (*outputFunc)(outputStream, "/isFixedPitch true def\n", 23);
418 } else {
419 (*outputFunc)(outputStream, "/isFixedPitch false def\n", 24);
420 }
421 sprintf(buf, "/ItalicAngle %g def\n", dict.italicAngle);
422 (*outputFunc)(outputStream, buf, strlen(buf));
423 sprintf(buf, "/UnderlinePosition %g def\n", dict.underlinePosition);
424 (*outputFunc)(outputStream, buf, strlen(buf));
425 sprintf(buf, "/UnderlineThickness %g def\n", dict.underlineThickness);
426 (*outputFunc)(outputStream, buf, strlen(buf));
427 (*outputFunc)(outputStream, "end readonly def\n", 17);
428 (*outputFunc)(outputStream, "/FontName /", 11);
429 (*outputFunc)(outputStream, name->getCString(), name->getLength());
430 (*outputFunc)(outputStream, " def\n", 5);
431 sprintf(buf, "/PaintType %d def\n", dict.paintType);
432 (*outputFunc)(outputStream, buf, strlen(buf));
433 (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
434 sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] readonly def\n",
435 dict.fontMatrix[0], dict.fontMatrix[1], dict.fontMatrix[2],
436 dict.fontMatrix[3], dict.fontMatrix[4], dict.fontMatrix[5]);
437 (*outputFunc)(outputStream, buf, strlen(buf));
438 sprintf(buf, "/FontBBox [%g %g %g %g] readonly def\n",
439 dict.fontBBox[0], dict.fontBBox[1],
440 dict.fontBBox[2], dict.fontBBox[3]);
441 (*outputFunc)(outputStream, buf, strlen(buf));
442 sprintf(buf, "/StrokeWidth %g def\n", dict.strokeWidth);
443 (*outputFunc)(outputStream, buf, strlen(buf));
444 if (dict.uniqueID != 0) {
445 sprintf(buf, "/UniqueID %d def\n", dict.uniqueID);
446 (*outputFunc)(outputStream, buf, strlen(buf));
447 }
448
449 // get number of glyphs from charstrings index
450 nGlyphs = getIndexLen((Guchar *)file + dict.charStrings);
451
452 // read charset
453 glyphNames = readCharset(dict.charset, nGlyphs);
454
455 // read encoding (glyph -> code mapping), write Type 1 encoding
456 (*outputFunc)(outputStream, "/Encoding ", 10);
457 if (dict.encoding == 0) {
458 (*outputFunc)(outputStream, "StandardEncoding def\n", 21);
459 } else {
460 (*outputFunc)(outputStream, "256 array\n", 10);
461 (*outputFunc)(outputStream,
462 "0 1 255 {1 index exch /.notdef put} for\n", 40);
463 if (dict.encoding == 1) {
464 for (i = 0; i < 256; ++i) {
465 if (expertEncoding[i]) {
466 sprintf(buf, "dup %d /%s put\n", i, expertEncoding[i]);
467 (*outputFunc)(outputStream, buf, strlen(buf));
468 }
469 }
470 } else {
471 ptr = (Guchar *)file + dict.encoding;
472 encFormat = *ptr++;
473 if ((encFormat & 0x7f) == 0) {
474 nCodes = 1 + *ptr++;
475 if (nCodes > nGlyphs) {
476 nCodes = nGlyphs;
477 }
478 for (i = 1; i < nCodes; ++i) {
479 c = *ptr++;
480 sprintf(buf, "dup %d /", c);
481 (*outputFunc)(outputStream, buf, strlen(buf));
482 getString(glyphNames[i], buf);
483 (*outputFunc)(outputStream, buf, strlen(buf));
484 (*outputFunc)(outputStream, " put\n", 5);
485 }
486 } else if ((encFormat & 0x7f) == 1) {
487 nRanges = *ptr++;
488 nCodes = 1;
489 for (i = 0; i < nRanges; ++i) {
490 c = *ptr++;
491 nLeft = *ptr++;
492 for (j = 0; j <= nLeft && nCodes < nGlyphs; ++j) {
493 sprintf(buf, "dup %d /", c);
494 (*outputFunc)(outputStream, buf, strlen(buf));
495 getString(glyphNames[nCodes], buf);
496 (*outputFunc)(outputStream, buf, strlen(buf));
497 (*outputFunc)(outputStream, " put\n", 5);
498 ++nCodes;
499 ++c;
500 }
501 }
502 }
503 if (encFormat & 0x80) {
504 nSups = *ptr++;
505 for (i = 0; i < nSups; ++i) {
506 c = *ptr++;
507 sid = getWord(ptr, 2);
508 ptr += 2;
509 sprintf(buf, "dup %d /", c);
510 (*outputFunc)(outputStream, buf, strlen(buf));
511 getString(sid, buf);
512 (*outputFunc)(outputStream, buf, strlen(buf));
513 (*outputFunc)(outputStream, " put\n", 5);
514 }
515 }
516 }
517 (*outputFunc)(outputStream, "readonly def\n", 13);
518 }
519 (*outputFunc)(outputStream, "currentdict end\n", 16);
520
521 // start the binary section
522 (*outputFunc)(outputStream, "currentfile eexec\n", 18);
523 r1 = 55665;
524 line = 0;
525
526 // get private dictionary
527 eexecWrite("\x83\xca\x73\xd5");
528 eexecWrite("dup /Private 32 dict dup begin\n");
529 eexecWrite("/RD {string currentfile exch readstring pop} executeonly def\n");
530 eexecWrite("/ND {noaccess def} executeonly def\n");
531 eexecWrite("/NP {noaccess put} executeonly def\n");
532 eexecWrite("/MinFeature {16 16} ND\n");
533 readPrivateDict(&privateDict, dict.privateOffset, dict.privateSize);
534 eexecWrite(privateDict.dictData->getCString());
535 defaultWidthX = privateDict.defaultWidthX;
536 defaultWidthXFP = privateDict.defaultWidthXFP;
537 nominalWidthX = privateDict.nominalWidthX;
538 nominalWidthXFP = privateDict.nominalWidthXFP;
539
540 // get subrs
541 if (privateDict.subrsOffset != 0) {
542 subrsIdxPtr = (Guchar *)file + dict.privateOffset +
543 privateDict.subrsOffset;
544 nSubrs = getIndexLen(subrsIdxPtr);
545 sprintf(eBuf, "/Subrs %d array\n", nSubrs);
546 eexecWrite(eBuf);
547 idxPtr1 = getIndexValPtr(subrsIdxPtr, 0);
548 for (i = 0; i < nSubrs; ++i) {
549 idxPtr0 = idxPtr1;
550 idxPtr1 = getIndexValPtr(subrsIdxPtr, i+1);
551 n = idxPtr1 - idxPtr0;
552#if 1 //~ Type 2 subrs are unimplemented
553 error(-1, "Unimplemented Type 2 subrs");
554#else
555 sprintf(eBuf, "dup %d %d RD ", i, n);
556 eexecWrite(eBuf);
557 eexecCvtGlyph(idxPtr0, n);
558 eexecWrite(" NP\n");
559#endif
560 }
561 eexecWrite("ND\n");
562 }
563
564 // get CharStrings
565 charStringsIdxPtr = (Guchar *)file + dict.charStrings;
566 nCharStrings = getIndexLen(charStringsIdxPtr);
567 sprintf(eBuf, "2 index /CharStrings %d dict dup begin\n", nCharStrings);
568 eexecWrite(eBuf);
569 idxPtr1 = getIndexValPtr(charStringsIdxPtr, 0);
570 for (i = 0; i < nCharStrings; ++i) {
571 idxPtr0 = idxPtr1;
572 idxPtr1 = getIndexValPtr(charStringsIdxPtr, i+1);
573 n = idxPtr1 - idxPtr0;
574 eexecCvtGlyph(getString(glyphNames[i], buf), idxPtr0, n);
575 }
576 eexecWrite("end\n");
577 eexecWrite("end\n");
578 eexecWrite("readonly put\n");
579 eexecWrite("noaccess put\n");
580 eexecWrite("dup /FontName get exch definefont pop\n");
581 eexecWrite("mark currentfile closefile\n");
582
583 // trailer
584 if (line > 0) {
585 (*outputFunc)(outputStream, "\n", 1);
586 }
587 for (i = 0; i < 8; ++i) {
588 (*outputFunc)(outputStream, "0000000000000000000000000000000000000000000000000000000000000000\n", 65);
589 }
590 (*outputFunc)(outputStream, "cleartomark\n", 12);
591
592 // clean up
593 delete privateDict.dictData;
594 if (dict.charset > 2) {
595 gfree(glyphNames);
596 }
597}
598
599void Type1CFontFile::convertToCIDType0(const char *psName,
600 FontFileOutputFunc outputFuncA,
601 void *outputStreamA) {
602 Type1CTopDict dict;
603 Type1CPrivateDict *privateDicts;
604 GString *charStrings;
605 int *charStringOffsets;
606 Gushort *charset;
607 int *cidMap;
608 Guchar *fdSelect;
609 Guchar *charStringsIdxPtr, *fdArrayIdx, *idxPtr0, *idxPtr1, *ptr;
610 char buf[512], buf2[16];
611 int nGlyphs, nCIDs, gdBytes, nFDs;
612 int fdSelectFmt, nRanges, gid0, gid1, fd, offset;
613 int key;
614 double x;
615 GBool isFP;
616 int i, j, k, n;
617
618 outputFunc = outputFuncA;
619 outputStream = outputStreamA;
620
621 (*outputFunc)(outputStream, "/CIDInit /ProcSet findresource begin\n", 37);
622
623 // read top dict (first font only)
624 readTopDict(&dict);
625
626 // read the FDArray dictionaries and Private dictionaries
627 if (dict.fdArrayOffset == 0) {
628 nFDs = 1;
629 privateDicts = (Type1CPrivateDict *)
630 gmalloc(nFDs * sizeof(Type1CPrivateDict));
631 privateDicts[0].dictData = new GString();
632 privateDicts[0].subrsOffset = 0;
633 privateDicts[0].defaultWidthX = 0;
634 privateDicts[0].defaultWidthXFP = gFalse;
635 privateDicts[0].nominalWidthX = 0;
636 privateDicts[0].nominalWidthXFP = gFalse;
637 } else {
638 fdArrayIdx = (Guchar *)file + dict.fdArrayOffset;
639 nFDs = getIndexLen(fdArrayIdx);
640 privateDicts = (Type1CPrivateDict *)
641 gmalloc(nFDs * sizeof(Type1CPrivateDict));
642 idxPtr1 = getIndexValPtr(fdArrayIdx, 0);
643 for (i = 0; i < nFDs; ++i) {
644 privateDicts[i].dictData = NULL;
645 idxPtr0 = idxPtr1;
646 idxPtr1 = getIndexValPtr(fdArrayIdx, i + 1);
647 ptr = idxPtr0;
648 j = 0;
649 while (ptr < idxPtr1) {
650 if (*ptr <= 27 || *ptr == 31) {
651 key = *ptr++;
652 if (key == 0x0c) {
653 key = (key << 8) | *ptr++;
654 }
655 if (key == 0x0012) {
656 readPrivateDict(&privateDicts[i], (int)op[1], (int)op[0]);
657 }
658 j = 0;
659 } else {
660 x = getNum(&ptr, &isFP);
661 if (j < 48) {
662 op[j] = x;
663 fp[j++] = isFP;
664 }
665 }
666 }
667 if (!privateDicts[i].dictData) {
668 privateDicts[i].dictData = new GString();
669 privateDicts[i].subrsOffset = 0;
670 privateDicts[i].defaultWidthX = 0;
671 privateDicts[i].defaultWidthXFP = gFalse;
672 privateDicts[i].nominalWidthX = 0;
673 privateDicts[i].nominalWidthXFP = gFalse;
674 }
675 }
676 }
677
678 // get the glyph count
679 charStringsIdxPtr = (Guchar *)file + dict.charStrings;
680 nGlyphs = getIndexLen(charStringsIdxPtr);
681
682 // read the FDSelect table
683 fdSelect = (Guchar *)gmalloc(nGlyphs);
684 if (dict.fdSelectOffset == 0) {
685 for (i = 0; i < nGlyphs; ++i) {
686 fdSelect[i] = 0;
687 }
688 } else {
689 ptr = (Guchar *)file + dict.fdSelectOffset;
690 fdSelectFmt = *ptr++;
691 if (fdSelectFmt == 0) {
692 memcpy(fdSelect, ptr, nGlyphs);
693 } else if (fdSelectFmt == 3) {
694 nRanges = getWord(ptr, 2);
695 ptr += 2;
696 gid0 = getWord(ptr, 2);
697 ptr += 2;
698 for (i = 1; i <= nRanges; ++i) {
699 fd = *ptr++;
700 gid1 = getWord(ptr, 2);
701 ptr += 2;
702 for (j = gid0; j < gid1; ++j) {
703 fdSelect[j] = fd;
704 }
705 gid0 = gid1;
706 }
707 } else {
708 error(-1, "Unknown FDSelect table format in CID font");
709 for (i = 0; i < nGlyphs; ++i) {
710 fdSelect[i] = 0;
711 }
712 }
713 }
714
715 // read the charset, compute the CID-to-GID mapping
716 charset = readCharset(dict.charset, nGlyphs);
717 nCIDs = 0;
718 for (i = 0; i < nGlyphs; ++i) {
719 if (charset[i] >= nCIDs) {
720 nCIDs = charset[i] + 1;
721 }
722 }
723 cidMap = (int *)gmalloc(nCIDs * sizeof(int));
724 for (i = 0; i < nCIDs; ++i) {
725 cidMap[i] = -1;
726 }
727 for (i = 0; i < nGlyphs; ++i) {
728 cidMap[charset[i]] = i;
729 }
730
731 // build the charstrings
732 charStrings = new GString();
733 charStringOffsets = (int *)gmalloc((nCIDs + 1) * sizeof(int));
734 for (i = 0; i < nCIDs; ++i) {
735 charStringOffsets[i] = charStrings->getLength();
736 if (cidMap[i] >= 0) {
737 idxPtr0 = getIndexValPtr(charStringsIdxPtr, cidMap[i]);
738 idxPtr1 = getIndexValPtr(charStringsIdxPtr, cidMap[i]+1);
739 n = idxPtr1 - idxPtr0;
740 j = fdSelect[cidMap[i]];
741 defaultWidthX = privateDicts[j].defaultWidthX;
742 defaultWidthXFP = privateDicts[j].defaultWidthXFP;
743 nominalWidthX = privateDicts[j].nominalWidthX;
744 nominalWidthXFP = privateDicts[j].nominalWidthXFP;
745 cvtGlyph(idxPtr0, n);
746 charStrings->append(charBuf);
747 delete charBuf;
748 }
749 }
750 charStringOffsets[nCIDs] = charStrings->getLength();
751
752 // compute gdBytes = number of bytes needed for charstring offsets
753 // (offset size needs to account for the charstring offset table,
754 // with a worst case of five bytes per entry, plus the charstrings
755 // themselves)
756 i = (nCIDs + 1) * 5 + charStrings->getLength();
757 if (i < 0x100) {
758 gdBytes = 1;
759 } else if (i < 0x10000) {
760 gdBytes = 2;
761 } else if (i < 0x1000000) {
762 gdBytes = 3;
763 } else {
764 gdBytes = 4;
765 }
766
767 // begin the font dictionary
768 (*outputFunc)(outputStream, "20 dict begin\n", 14);
769 (*outputFunc)(outputStream, "/CIDFontName /", 14);
770 (*outputFunc)(outputStream, psName, strlen(psName));
771 (*outputFunc)(outputStream, " def\n", 5);
772 (*outputFunc)(outputStream, "/CIDFontType 0 def\n", 19);
773 (*outputFunc)(outputStream, "/CIDSystemInfo 3 dict dup begin\n", 32);
774 if (dict.registry > 0 && dict.ordering > 0) {
775 getString(dict.registry, buf);
776 (*outputFunc)(outputStream, " /Registry (", 13);
777 (*outputFunc)(outputStream, buf, strlen(buf));
778 (*outputFunc)(outputStream, ") def\n", 6);
779 getString(dict.ordering, buf);
780 (*outputFunc)(outputStream, " /Ordering (", 13);
781 (*outputFunc)(outputStream, buf, strlen(buf));
782 (*outputFunc)(outputStream, ") def\n", 6);
783 } else {
784 (*outputFunc)(outputStream, " /Registry (Adobe) def\n", 24);
785 (*outputFunc)(outputStream, " /Ordering (Identity) def\n", 27);
786 }
787 sprintf(buf, " /Supplement %d def\n", dict.supplement);
788 (*outputFunc)(outputStream, buf, strlen(buf));
789 (*outputFunc)(outputStream, "end def\n", 8);
790 sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n",
791 dict.fontMatrix[0], dict.fontMatrix[1], dict.fontMatrix[2],
792 dict.fontMatrix[3], dict.fontMatrix[4], dict.fontMatrix[5]);
793 (*outputFunc)(outputStream, buf, strlen(buf));
794 sprintf(buf, "/FontBBox [%g %g %g %g] def\n",
795 dict.fontBBox[0], dict.fontBBox[1],
796 dict.fontBBox[2], dict.fontBBox[3]);
797 (*outputFunc)(outputStream, buf, strlen(buf));
798 (*outputFunc)(outputStream, "/FontInfo 1 dict dup begin\n", 27);
799 (*outputFunc)(outputStream, " /FSType 8 def\n", 16);
800 (*outputFunc)(outputStream, "end def\n", 8);
801
802 // CIDFont-specific entries
803 sprintf(buf, "/CIDCount %d def\n", nCIDs);
804 (*outputFunc)(outputStream, buf, strlen(buf));
805 (*outputFunc)(outputStream, "/FDBytes 1 def\n", 15);
806 sprintf(buf, "/GDBytes %d def\n", gdBytes);
807 (*outputFunc)(outputStream, buf, strlen(buf));
808 (*outputFunc)(outputStream, "/CIDMapOffset 0 def\n", 20);
809 if (dict.paintType != 0) {
810 sprintf(buf, "/PaintType %d def\n", dict.paintType);
811 (*outputFunc)(outputStream, buf, strlen(buf));
812 sprintf(buf, "/StrokeWidth %g def\n", dict.strokeWidth);
813 (*outputFunc)(outputStream, buf, strlen(buf));
814 }
815
816 // FDArray entry
817 sprintf(buf, "/FDArray %d array\n", nFDs);
818 (*outputFunc)(outputStream, buf, strlen(buf));
819 for (i = 0; i < nFDs; ++i) {
820 sprintf(buf, "dup %d 10 dict begin\n", i);
821 (*outputFunc)(outputStream, buf, strlen(buf));
822 (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
823 (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
824 sprintf(buf, "/PaintType %d def\n", dict.paintType);
825 (*outputFunc)(outputStream, buf, strlen(buf));
826 (*outputFunc)(outputStream, "/Private 32 dict begin\n", 23);
827 (*outputFunc)(outputStream, privateDicts[i].dictData->getCString(),
828 privateDicts[i].dictData->getLength());
829 (*outputFunc)(outputStream, "currentdict end def\n", 20);
830 (*outputFunc)(outputStream, "currentdict end put\n", 20);
831 }
832 (*outputFunc)(outputStream, "def\n", 4);
833
834 //~ need to deal with subrs
835
836 // start the binary section
837 offset = (nCIDs + 1) * (1 + gdBytes);
838 sprintf(buf, "(Hex) %d StartData\n",
839 offset + charStrings->getLength());
840 (*outputFunc)(outputStream, buf, strlen(buf));
841
842 // write the charstring offset (CIDMap) table
843 for (i = 0; i <= nCIDs; i += 6) {
844 for (j = 0; j < 6 && i+j <= nCIDs; ++j) {
845 if (i+j < nCIDs && cidMap[i+j] >= 0) {
846 buf[0] = (char)fdSelect[cidMap[i+j]];
847 } else {
848 buf[0] = (char)0;
849 }
850 n = offset + charStringOffsets[i+j];
851 for (k = gdBytes; k >= 1; --k) {
852 buf[k] = (char)(n & 0xff);
853 n >>= 8;
854 }
855 for (k = 0; k <= gdBytes; ++k) {
856 sprintf(buf2, "%02x", buf[k] & 0xff);
857 (*outputFunc)(outputStream, buf2, 2);
858 }
859 }
860 (*outputFunc)(outputStream, "\n", 1);
861 }
862
863 // write the charstring data
864 n = charStrings->getLength();
865 for (i = 0; i < n; i += 32) {
866 for (j = 0; j < 32 && i+j < n; ++j) {
867 sprintf(buf, "%02x", charStrings->getChar(i+j) & 0xff);
868 (*outputFunc)(outputStream, buf, strlen(buf));
869 }
870 if (i + 32 >= n) {
871 (*outputFunc)(outputStream, ">", 1);
872 }
873 (*outputFunc)(outputStream, "\n", 1);
874 }
875
876 for (i = 0; i < nFDs; ++i) {
877 delete privateDicts[i].dictData;
878 }
879 gfree(privateDicts);
880 gfree(cidMap);
881 gfree(charset);
882 gfree(charStringOffsets);
883 delete charStrings;
884 gfree(fdSelect);
885}
886
887void Type1CFontFile::convertToType0(const char *psName,
888 FontFileOutputFunc outputFuncA,
889 void *outputStreamA) {
890 Type1CTopDict dict;
891 Type1CPrivateDict *privateDicts;
892 Gushort *charset;
893 int *cidMap;
894 Guchar *fdSelect;
895 Guchar *charStringsIdxPtr, *fdArrayIdx, *idxPtr0, *idxPtr1, *ptr;
896 char buf[512];
897 char eBuf[256];
898 int nGlyphs, nCIDs, nFDs;
899 int fdSelectFmt, nRanges, gid0, gid1, fd;
900 int key;
901 double x;
902 GBool isFP;
903 int i, j, n;
904
905 outputFunc = outputFuncA;
906 outputStream = outputStreamA;
907
908 // read top dict (first font only)
909 readTopDict(&dict);
910
911 // read the FDArray dictionaries and Private dictionaries
912 if (dict.fdArrayOffset == 0) {
913 nFDs = 1;
914 privateDicts = (Type1CPrivateDict *)
915 gmalloc(nFDs * sizeof(Type1CPrivateDict));
916 privateDicts[0].dictData = new GString();
917 privateDicts[0].subrsOffset = 0;
918 privateDicts[0].defaultWidthX = 0;
919 privateDicts[0].defaultWidthXFP = gFalse;
920 privateDicts[0].nominalWidthX = 0;
921 privateDicts[0].nominalWidthXFP = gFalse;
922 } else {
923 fdArrayIdx = (Guchar *)file + dict.fdArrayOffset;
924 nFDs = getIndexLen(fdArrayIdx);
925 privateDicts = (Type1CPrivateDict *)
926 gmalloc(nFDs * sizeof(Type1CPrivateDict));
927 idxPtr1 = getIndexValPtr(fdArrayIdx, 0);
928 for (i = 0; i < nFDs; ++i) {
929 privateDicts[i].dictData = NULL;
930 idxPtr0 = idxPtr1;
931 idxPtr1 = getIndexValPtr(fdArrayIdx, i + 1);
932 ptr = idxPtr0;
933 j = 0;
934 while (ptr < idxPtr1) {
935 if (*ptr <= 27 || *ptr == 31) {
936 key = *ptr++;
937 if (key == 0x0c) {
938 key = (key << 8) | *ptr++;
939 }
940 if (key == 0x0012) {
941 readPrivateDict(&privateDicts[i], (int)op[1], (int)op[0]);
942 }
943 j = 0;
944 } else {
945 x = getNum(&ptr, &isFP);
946 if (j < 48) {
947 op[j] = x;
948 fp[j++] = isFP;
949 }
950 }
951 }
952 if (!privateDicts[i].dictData) {
953 privateDicts[i].dictData = new GString();
954 privateDicts[i].subrsOffset = 0;
955 privateDicts[i].defaultWidthX = 0;
956 privateDicts[i].defaultWidthXFP = gFalse;
957 privateDicts[i].nominalWidthX = 0;
958 privateDicts[i].nominalWidthXFP = gFalse;
959 }
960 }
961 }
962
963 // get the glyph count
964 charStringsIdxPtr = (Guchar *)file + dict.charStrings;
965 nGlyphs = getIndexLen(charStringsIdxPtr);
966
967 // read the FDSelect table
968 fdSelect = (Guchar *)gmalloc(nGlyphs);
969 if (dict.fdSelectOffset == 0) {
970 for (i = 0; i < nGlyphs; ++i) {
971 fdSelect[i] = 0;
972 }
973 } else {
974 ptr = (Guchar *)file + dict.fdSelectOffset;
975 fdSelectFmt = *ptr++;
976 if (fdSelectFmt == 0) {
977 memcpy(fdSelect, ptr, nGlyphs);
978 } else if (fdSelectFmt == 3) {
979 nRanges = getWord(ptr, 2);
980 ptr += 2;
981 gid0 = getWord(ptr, 2);
982 ptr += 2;
983 for (i = 1; i <= nRanges; ++i) {
984 fd = *ptr++;
985 gid1 = getWord(ptr, 2);
986 ptr += 2;
987 for (j = gid0; j < gid1; ++j) {
988 fdSelect[j] = fd;
989 }
990 gid0 = gid1;
991 }
992 } else {
993 error(-1, "Unknown FDSelect table format in CID font");
994 for (i = 0; i < nGlyphs; ++i) {
995 fdSelect[i] = 0;
996 }
997 }
998 }
999
1000 // read the charset, compute the CID-to-GID mapping
1001 charset = readCharset(dict.charset, nGlyphs);
1002 nCIDs = 0;
1003 for (i = 0; i < nGlyphs; ++i) {
1004 if (charset[i] >= nCIDs) {
1005 nCIDs = charset[i] + 1;
1006 }
1007 }
1008 cidMap = (int *)gmalloc(nCIDs * sizeof(int));
1009 for (i = 0; i < nCIDs; ++i) {
1010 cidMap[i] = -1;
1011 }
1012 for (i = 0; i < nGlyphs; ++i) {
1013 cidMap[charset[i]] = i;
1014 }
1015
1016 // write the descendant Type 1 fonts
1017 for (i = 0; i < nCIDs; i += 256) {
1018
1019 //~ this assumes that all CIDs in this block have the same FD --
1020 //~ to handle multiple FDs correctly, need to somehow divide the
1021 //~ font up by FD
1022 fd = 0;
1023 for (j = 0; j < 256 && i+j < nCIDs; ++j) {
1024 if (cidMap[i+j] >= 0) {
1025 fd = fdSelect[cidMap[i+j]];
1026 break;
1027 }
1028 }
1029
1030 // font dictionary (unencrypted section)
1031 (*outputFunc)(outputStream, "16 dict begin\n", 14);
1032 (*outputFunc)(outputStream, "/FontName /", 11);
1033 (*outputFunc)(outputStream, psName, strlen(psName));
1034 sprintf(buf, "_%02x def\n", i >> 8);
1035 (*outputFunc)(outputStream, buf, strlen(buf));
1036 (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
1037 sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n",
1038 dict.fontMatrix[0], dict.fontMatrix[1], dict.fontMatrix[2],
1039 dict.fontMatrix[3], dict.fontMatrix[4], dict.fontMatrix[5]);
1040 (*outputFunc)(outputStream, buf, strlen(buf));
1041 sprintf(buf, "/FontBBox [%g %g %g %g] def\n",
1042 dict.fontBBox[0], dict.fontBBox[1],
1043 dict.fontBBox[2], dict.fontBBox[3]);
1044 (*outputFunc)(outputStream, buf, strlen(buf));
1045 sprintf(buf, "/PaintType %d def\n", dict.paintType);
1046 (*outputFunc)(outputStream, buf, strlen(buf));
1047 if (dict.paintType != 0) {
1048 sprintf(buf, "/StrokeWidth %g def\n", dict.strokeWidth);
1049 (*outputFunc)(outputStream, buf, strlen(buf));
1050 }
1051 (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
1052 for (j = 0; j < 256 && i+j < nCIDs; ++j) {
1053 sprintf(buf, "dup %d /c%02x put\n", j, j);
1054 (*outputFunc)(outputStream, buf, strlen(buf));
1055 }
1056 (*outputFunc)(outputStream, "readonly def\n", 13);
1057 (*outputFunc)(outputStream, "currentdict end\n", 16);
1058
1059 // start the binary section
1060 (*outputFunc)(outputStream, "currentfile eexec\n", 18);
1061 r1 = 55665;
1062 line = 0;
1063
1064 // start the private dictionary
1065 eexecWrite("\x83\xca\x73\xd5");
1066 eexecWrite("dup /Private 32 dict dup begin\n");
1067 eexecWrite("/RD {string currentfile exch readstring pop} executeonly def\n");
1068 eexecWrite("/ND {noaccess def} executeonly def\n");
1069 eexecWrite("/NP {noaccess put} executeonly def\n");
1070 eexecWrite("/MinFeature {16 16} ND\n");
1071 eexecWrite(privateDicts[fd].dictData->getCString());
1072 defaultWidthX = privateDicts[fd].defaultWidthX;
1073 defaultWidthXFP = privateDicts[fd].defaultWidthXFP;
1074 nominalWidthX = privateDicts[fd].nominalWidthX;
1075 nominalWidthXFP = privateDicts[fd].nominalWidthXFP;
1076
1077 // start the CharStrings
1078 sprintf(eBuf, "2 index /CharStrings 256 dict dup begin\n");
1079 eexecWrite(eBuf);
1080
1081 // write the .notdef CharString
1082 idxPtr0 = getIndexValPtr(charStringsIdxPtr, 0);
1083 idxPtr1 = getIndexValPtr(charStringsIdxPtr, 1);
1084 n = idxPtr1 - idxPtr0;
1085 eexecCvtGlyph(".notdef", idxPtr0, n);
1086
1087 // write the CharStrings
1088 for (j = 0; j < 256 && i+j < nCIDs; ++j) {
1089 if (cidMap[i+j] >= 0) {
1090 idxPtr0 = getIndexValPtr(charStringsIdxPtr, cidMap[i+j]);
1091 idxPtr1 = getIndexValPtr(charStringsIdxPtr, cidMap[i+j]+1);
1092 n = idxPtr1 - idxPtr0;
1093 sprintf(buf, "c%02x", j);
1094 eexecCvtGlyph(buf, idxPtr0, n);
1095 }
1096 }
1097 eexecWrite("end\n");
1098 eexecWrite("end\n");
1099 eexecWrite("readonly put\n");
1100 eexecWrite("noaccess put\n");
1101 eexecWrite("dup /FontName get exch definefont pop\n");
1102 eexecWrite("mark currentfile closefile\n");
1103
1104 // trailer
1105 if (line > 0) {
1106 (*outputFunc)(outputStream, "\n", 1);
1107 }
1108 for (j = 0; j < 8; ++j) {
1109 (*outputFunc)(outputStream, "0000000000000000000000000000000000000000000000000000000000000000\n", 65);
1110 }
1111 (*outputFunc)(outputStream, "cleartomark\n", 12);
1112 }
1113
1114 // write the Type 0 parent font
1115 (*outputFunc)(outputStream, "16 dict begin\n", 14);
1116 (*outputFunc)(outputStream, "/FontName /", 11);
1117 (*outputFunc)(outputStream, psName, strlen(psName));
1118 (*outputFunc)(outputStream, " def\n", 5);
1119 (*outputFunc)(outputStream, "/FontType 0 def\n", 16);
1120 (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
1121 (*outputFunc)(outputStream, "/FMapType 2 def\n", 16);
1122 (*outputFunc)(outputStream, "/Encoding [\n", 12);
1123 for (i = 0; i < nCIDs; i += 256) {
1124 sprintf(buf, "%d\n", i >> 8);
1125 (*outputFunc)(outputStream, buf, strlen(buf));
1126 }
1127 (*outputFunc)(outputStream, "] def\n", 6);
1128 (*outputFunc)(outputStream, "/FDepVector [\n", 14);
1129 for (i = 0; i < nCIDs; i += 256) {
1130 (*outputFunc)(outputStream, "/", 1);
1131 (*outputFunc)(outputStream, psName, strlen(psName));
1132 sprintf(buf, "_%02x findfont\n", i >> 8);
1133 (*outputFunc)(outputStream, buf, strlen(buf));
1134 }
1135 (*outputFunc)(outputStream, "] def\n", 6);
1136 (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
1137
1138 // clean up
1139 for (i = 0; i < nFDs; ++i) {
1140 delete privateDicts[i].dictData;
1141 }
1142 gfree(privateDicts);
1143 gfree(cidMap);
1144 gfree(charset);
1145 gfree(fdSelect);
1146}
1147
1148void Type1CFontFile::readTopDict(Type1CTopDict *dict) {
1149 Guchar *idxPtr0, *idxPtr1, *ptr;
1150 double x;
1151 GBool isFP;
1152 int key;
1153 int i;
1154
1155 idxPtr0 = getIndexValPtr(topDictIdxPtr, 0);
1156 idxPtr1 = getIndexValPtr(topDictIdxPtr, 1);
1157 dict->version = 0;
1158 dict->notice = 0;
1159 dict->copyright = 0;
1160 dict->fullName = 0;
1161 dict->familyName = 0;
1162 dict->weight = 0;
1163 dict->isFixedPitch = 0;
1164 dict->italicAngle = 0;
1165 dict->underlinePosition = -100;
1166 dict->underlineThickness = 50;
1167 dict->paintType = 0;
1168 dict->charstringType = 2;
1169 dict->fontMatrix[0] = 0.001;
1170 dict->fontMatrix[1] = 0;
1171 dict->fontMatrix[2] = 0;
1172 dict->fontMatrix[3] = 0.001;
1173 dict->fontMatrix[4] = 0;
1174 dict->fontMatrix[5] = 0;
1175 dict->uniqueID = 0;
1176 dict->fontBBox[0] = 0;
1177 dict->fontBBox[1] = 0;
1178 dict->fontBBox[2] = 0;
1179 dict->fontBBox[3] = 0;
1180 dict->strokeWidth = 0;
1181 dict->charset = 0;
1182 dict->encoding = 0;
1183 dict->charStrings = 0;
1184 dict->privateSize = 0;
1185 dict->privateOffset = 0;
1186 dict->registry = 0;
1187 dict->ordering = 0;
1188 dict->supplement = 0;
1189 dict->fdArrayOffset = 0;
1190 dict->fdSelectOffset = 0;
1191 i = 0;
1192 ptr = idxPtr0;
1193 while (ptr < idxPtr1) {
1194 if (*ptr <= 27 || *ptr == 31) {
1195 key = *ptr++;
1196 if (key == 0x0c) {
1197 key = (key << 8) | *ptr++;
1198 }
1199 switch (key) {
1200 case 0x0000: dict->version = (int)op[0]; break;
1201 case 0x0001: dict->notice = (int)op[0]; break;
1202 case 0x0c00: dict->copyright = (int)op[0]; break;
1203 case 0x0002: dict->fullName = (int)op[0]; break;
1204 case 0x0003: dict->familyName = (int)op[0]; break;
1205 case 0x0004: dict->weight = (int)op[0]; break;
1206 case 0x0c01: dict->isFixedPitch = (int)op[0]; break;
1207 case 0x0c02: dict->italicAngle = op[0]; break;
1208 case 0x0c03: dict->underlinePosition = op[0]; break;
1209 case 0x0c04: dict->underlineThickness = op[0]; break;
1210 case 0x0c05: dict->paintType = (int)op[0]; break;
1211 case 0x0c06: dict->charstringType = (int)op[0]; break;
1212 case 0x0c07: dict->fontMatrix[0] = op[0];
1213 dict->fontMatrix[1] = op[1];
1214 dict->fontMatrix[2] = op[2];
1215 dict->fontMatrix[3] = op[3];
1216 dict->fontMatrix[4] = op[4];
1217 dict->fontMatrix[5] = op[5]; break;
1218 case 0x000d: dict->uniqueID = (int)op[0]; break;
1219 case 0x0005: dict->fontBBox[0] = op[0];
1220 dict->fontBBox[1] = op[1];
1221 dict->fontBBox[2] = op[2];
1222 dict->fontBBox[3] = op[3]; break;
1223 case 0x0c08: dict->strokeWidth = op[0]; break;
1224 case 0x000f: dict->charset = (int)op[0]; break;
1225 case 0x0010: dict->encoding = (int)op[0]; break;
1226 case 0x0011: dict->charStrings = (int)op[0]; break;
1227 case 0x0012: dict->privateSize = (int)op[0];
1228 dict->privateOffset = (int)op[1]; break;
1229 case 0x0c1e: dict->registry = (int)op[0];
1230 dict->ordering = (int)op[1];
1231 dict->supplement = (int)op[2]; break;
1232 case 0x0c24: dict->fdArrayOffset = (int)op[0]; break;
1233 case 0x0c25: dict->fdSelectOffset = (int)op[0]; break;
1234 }
1235 i = 0;
1236 } else {
1237 x = getNum(&ptr, &isFP);
1238 if (i < 48) {
1239 op[i] = x;
1240 fp[i++] = isFP;
1241 }
1242 }
1243 }
1244}
1245
1246void Type1CFontFile::readPrivateDict(Type1CPrivateDict *privateDict,
1247 int offset, int size) {
1248 Guchar *idxPtr0, *idxPtr1, *ptr;
1249 char eBuf[256];
1250 int key;
1251 double x;
1252 GBool isFP;
1253 int i;
1254
1255 privateDict->dictData = new GString();
1256 privateDict->subrsOffset = 0;
1257 privateDict->defaultWidthX = 0;
1258 privateDict->defaultWidthXFP = gFalse;
1259 privateDict->nominalWidthX = 0;
1260 privateDict->nominalWidthXFP = gFalse;
1261 idxPtr0 = (Guchar *)file + offset;
1262 idxPtr1 = idxPtr0 + size;
1263 ptr = idxPtr0;
1264 i = 0;
1265 while (ptr < idxPtr1) {
1266 if (*ptr <= 27 || *ptr == 31) {
1267 key = *ptr++;
1268 if (key == 0x0c) {
1269 key = (key << 8) | *ptr++;
1270 }
1271 switch (key) {
1272 case 0x0006:
1273 getDeltaInt(eBuf, "BlueValues", op, i);
1274 privateDict->dictData->append(eBuf);
1275 break;
1276 case 0x0007:
1277 getDeltaInt(eBuf, "OtherBlues", op, i);
1278 privateDict->dictData->append(eBuf);
1279 break;
1280 case 0x0008:
1281 getDeltaInt(eBuf, "FamilyBlues", op, i);
1282 privateDict->dictData->append(eBuf);
1283 break;
1284 case 0x0009:
1285 getDeltaInt(eBuf, "FamilyOtherBlues", op, i);
1286 privateDict->dictData->append(eBuf);
1287 break;
1288 case 0x0c09:
1289 sprintf(eBuf, "/BlueScale %g def\n", op[0]);
1290 privateDict->dictData->append(eBuf);
1291 break;
1292 case 0x0c0a:
1293 sprintf(eBuf, "/BlueShift %d def\n", (int)op[0]);
1294 privateDict->dictData->append(eBuf);
1295 break;
1296 case 0x0c0b:
1297 sprintf(eBuf, "/BlueFuzz %d def\n", (int)op[0]);
1298 privateDict->dictData->append(eBuf);
1299 break;
1300 case 0x000a:
1301 sprintf(eBuf, "/StdHW [%g] def\n", op[0]);
1302 privateDict->dictData->append(eBuf);
1303 break;
1304 case 0x000b:
1305 sprintf(eBuf, "/StdVW [%g] def\n", op[0]);
1306 privateDict->dictData->append(eBuf);
1307 break;
1308 case 0x0c0c:
1309 getDeltaReal(eBuf, "StemSnapH", op, i);
1310 privateDict->dictData->append(eBuf);
1311 break;
1312 case 0x0c0d:
1313 getDeltaReal(eBuf, "StemSnapV", op, i);
1314 privateDict->dictData->append(eBuf);
1315 break;
1316 case 0x0c0e:
1317 sprintf(eBuf, "/ForceBold %s def\n", op[0] ? "true" : "false");
1318 privateDict->dictData->append(eBuf);
1319 break;
1320 case 0x0c0f:
1321 sprintf(eBuf, "/ForceBoldThreshold %g def\n", op[0]);
1322 privateDict->dictData->append(eBuf);
1323 break;
1324 case 0x0c11:
1325 sprintf(eBuf, "/LanguageGroup %d def\n", (int)op[0]);
1326 privateDict->dictData->append(eBuf);
1327 break;
1328 case 0x0c12:
1329 sprintf(eBuf, "/ExpansionFactor %g def\n", op[0]);
1330 privateDict->dictData->append(eBuf);
1331 break;
1332 case 0x0c13:
1333 error(-1, "Got Type 1C InitialRandomSeed");
1334 break;
1335 case 0x0013:
1336 privateDict->subrsOffset = (int)op[0];
1337 break;
1338 case 0x0014:
1339 privateDict->defaultWidthX = op[0];
1340 privateDict->defaultWidthXFP = fp[0];
1341 break;
1342 case 0x0015:
1343 privateDict->nominalWidthX = op[0];
1344 privateDict->nominalWidthXFP = fp[0];
1345 break;
1346 default:
1347 error(-1, "Unknown Type 1C private dict entry %04x", key);
1348 break;
1349 }
1350 i = 0;
1351 } else {
1352 x = getNum(&ptr, &isFP);
1353 if (i < 48) {
1354 op[i] = x;
1355 fp[i++] = isFP;
1356 }
1357 }
1358 }
1359}
1360
1361Gushort *Type1CFontFile::readCharset(int charset, int nGlyphs) {
1362 Gushort *glyphNames;
1363 Guchar *ptr;
1364 int charsetFormat, c;
1365 int nLeft, i, j;
1366
1367 if (charset == 0) {
1368 glyphNames = type1CISOAdobeCharset;
1369 } else if (charset == 1) {
1370 glyphNames = type1CExpertCharset;
1371 } else if (charset == 2) {
1372 glyphNames = type1CExpertSubsetCharset;
1373 } else {
1374 glyphNames = (Gushort *)gmalloc(nGlyphs * sizeof(Gushort));
1375 glyphNames[0] = 0;
1376 ptr = (Guchar *)file + charset;
1377 charsetFormat = *ptr++;
1378 if (charsetFormat == 0) {
1379 for (i = 1; i < nGlyphs; ++i) {
1380 glyphNames[i] = getWord(ptr, 2);
1381 ptr += 2;
1382 }
1383 } else if (charsetFormat == 1) {
1384 i = 1;
1385 while (i < nGlyphs) {
1386 c = getWord(ptr, 2);
1387 ptr += 2;
1388 nLeft = *ptr++;
1389 for (j = 0; j <= nLeft && i < nGlyphs; ++j) {
1390 glyphNames[i++] = c++;
1391 }
1392 }
1393 } else if (charsetFormat == 2) {
1394 i = 1;
1395 while (i < nGlyphs) {
1396 c = getWord(ptr, 2);
1397 ptr += 2;
1398 nLeft = getWord(ptr, 2);
1399 ptr += 2;
1400 for (j = 0; j <= nLeft && i < nGlyphs; ++j) {
1401 glyphNames[i++] = c++;
1402 }
1403 }
1404 }
1405 }
1406 return glyphNames;
1407}
1408
1409void Type1CFontFile::eexecWrite(const char *s) {
1410 const Guchar *p;
1411 Guchar x;
1412
1413 for (p = (const Guchar *)s; *p; ++p) {
1414 x = *p ^ (r1 >> 8);
1415 r1 = (x + r1) * 52845 + 22719;
1416 (*outputFunc)(outputStream, &hexChars[x >> 4], 1);
1417 (*outputFunc)(outputStream, &hexChars[x & 0x0f], 1);
1418 line += 2;
1419 if (line == 64) {
1420 (*outputFunc)(outputStream, "\n", 1);
1421 line = 0;
1422 }
1423 }
1424}
1425
1426void Type1CFontFile::eexecCvtGlyph(const char *glyphName, const Guchar *s, int n) {
1427 char eBuf[256];
1428
1429 cvtGlyph(s, n);
1430 sprintf(eBuf, "/%s %d RD ", glyphName, charBuf->getLength());
1431 eexecWrite(eBuf);
1432 eexecWriteCharstring((Guchar *)charBuf->getCString(), charBuf->getLength());
1433 eexecWrite(" ND\n");
1434 delete charBuf;
1435}
1436
1437void Type1CFontFile::cvtGlyph(const Guchar *s, int n) {
1438 int nHints;
1439 int x;
1440 GBool first = gTrue;
1441 double d, dx, dy;
1442 GBool dFP;
1443 Gushort r2;
1444 Guchar byte;
1445 int i, k;
1446
1447 charBuf = new GString();
1448 charBuf->append((char)73);
1449 charBuf->append((char)58);
1450 charBuf->append((char)147);
1451 charBuf->append((char)134);
1452
1453 i = 0;
1454 nOps = 0;
1455 nHints = 0;
1456 while (i < n) {
1457 if (s[i] == 12) {
1458 switch (s[i+1]) {
1459 case 0: // dotsection (should be Type 1 only?)
1460 // ignored
1461 break;
1462 case 34: // hflex
1463 if (nOps != 7) {
1464 error(-1, "Wrong number of args (%d) to Type 2 hflex", nOps);
1465 }
1466 eexecDumpNum(op[0], fp[0]);
1467 eexecDumpNum(0, gFalse);
1468 eexecDumpNum(op[1], fp[1]);
1469 eexecDumpNum(op[2], fp[2]);
1470 eexecDumpNum(op[3], fp[3]);
1471 eexecDumpNum(0, gFalse);
1472 eexecDumpOp1(8);
1473 eexecDumpNum(op[4], fp[4]);
1474 eexecDumpNum(0, gFalse);
1475 eexecDumpNum(op[5], fp[5]);
1476 eexecDumpNum(-op[2], fp[2]);
1477 eexecDumpNum(op[6], fp[6]);
1478 eexecDumpNum(0, gFalse);
1479 eexecDumpOp1(8);
1480 break;
1481 case 35: // flex
1482 if (nOps != 13) {
1483 error(-1, "Wrong number of args (%d) to Type 2 flex", nOps);
1484 }
1485 eexecDumpNum(op[0], fp[0]);
1486 eexecDumpNum(op[1], fp[1]);
1487 eexecDumpNum(op[2], fp[2]);
1488 eexecDumpNum(op[3], fp[3]);
1489 eexecDumpNum(op[4], fp[4]);
1490 eexecDumpNum(op[5], fp[5]);
1491 eexecDumpOp1(8);
1492 eexecDumpNum(op[6], fp[6]);
1493 eexecDumpNum(op[7], fp[7]);
1494 eexecDumpNum(op[8], fp[8]);
1495 eexecDumpNum(op[9], fp[9]);
1496 eexecDumpNum(op[10], fp[10]);
1497 eexecDumpNum(op[11], fp[11]);
1498 eexecDumpOp1(8);
1499 break;
1500 case 36: // hflex1
1501 if (nOps != 9) {
1502 error(-1, "Wrong number of args (%d) to Type 2 hflex1", nOps);
1503 }
1504 eexecDumpNum(op[0], fp[0]);
1505 eexecDumpNum(op[1], fp[1]);
1506 eexecDumpNum(op[2], fp[2]);
1507 eexecDumpNum(op[3], fp[3]);
1508 eexecDumpNum(op[4], fp[4]);
1509 eexecDumpNum(0, gFalse);
1510 eexecDumpOp1(8);
1511 eexecDumpNum(op[5], fp[5]);
1512 eexecDumpNum(0, gFalse);
1513 eexecDumpNum(op[6], fp[6]);
1514 eexecDumpNum(op[7], fp[7]);
1515 eexecDumpNum(op[8], fp[8]);
1516 eexecDumpNum(-(op[1] + op[3] + op[7]), fp[1] | fp[3] | fp[7]);
1517 eexecDumpOp1(8);
1518 break;
1519 case 37: // flex1
1520 if (nOps != 11) {
1521 error(-1, "Wrong number of args (%d) to Type 2 flex1", nOps);
1522 }
1523 eexecDumpNum(op[0], fp[0]);
1524 eexecDumpNum(op[1], fp[1]);
1525 eexecDumpNum(op[2], fp[2]);
1526 eexecDumpNum(op[3], fp[3]);
1527 eexecDumpNum(op[4], fp[4]);
1528 eexecDumpNum(op[5], fp[5]);
1529 eexecDumpOp1(8);
1530 eexecDumpNum(op[6], fp[6]);
1531 eexecDumpNum(op[7], fp[7]);
1532 eexecDumpNum(op[8], fp[8]);
1533 eexecDumpNum(op[9], fp[9]);
1534 dx = op[0] + op[2] + op[4] + op[6] + op[8];
1535 dy = op[1] + op[3] + op[5] + op[7] + op[9];
1536 if (fabs(dx) > fabs(dy)) {
1537 eexecDumpNum(op[10], fp[10]);
1538 eexecDumpNum(-dy, fp[1] | fp[3] | fp[5] | fp[7] | fp[9]);
1539 } else {
1540 eexecDumpNum(-dx, fp[0] | fp[2] | fp[4] | fp[6] | fp[8]);
1541 eexecDumpNum(op[10], fp[10]);
1542 }
1543 eexecDumpOp1(8);
1544 break;
1545 case 3: // and
1546 case 4: // or
1547 case 5: // not
1548 case 8: // store
1549 case 9: // abs
1550 case 10: // add
1551 case 11: // sub
1552 case 12: // div
1553 case 13: // load
1554 case 14: // neg
1555 case 15: // eq
1556 case 18: // drop
1557 case 20: // put
1558 case 21: // get
1559 case 22: // ifelse
1560 case 23: // random
1561 case 24: // mul
1562 case 26: // sqrt
1563 case 27: // dup
1564 case 28: // exch
1565 case 29: // index
1566 case 30: // roll
1567 error(-1, "Unimplemented Type 2 charstring op: 12.%d", s[i+1]);
1568 break;
1569 default:
1570 error(-1, "Illegal Type 2 charstring op: 12.%d", s[i+1]);
1571 break;
1572 }
1573 i += 2;
1574 nOps = 0;
1575 } else if (s[i] == 19) { // hintmask
1576 // ignored
1577 if (first) {
1578 cvtGlyphWidth(nOps == 1);
1579 first = gFalse;
1580 }
1581 if (nOps > 0) {
1582 if (nOps & 1) {
1583 error(-1, "Wrong number of args (%d) to Type 2 hintmask/vstemhm",
1584 nOps);
1585 }
1586 nHints += nOps / 2;
1587 }
1588 i += 1 + ((nHints + 7) >> 3);
1589 nOps = 0;
1590 } else if (s[i] == 20) { // cntrmask
1591 // ignored
1592 if (first) {
1593 cvtGlyphWidth(nOps == 1);
1594 first = gFalse;
1595 }
1596 if (nOps > 0) {
1597 if (nOps & 1) {
1598 error(-1, "Wrong number of args (%d) to Type 2 cntrmask/vstemhm",
1599 nOps);
1600 }
1601 nHints += nOps / 2;
1602 }
1603 i += 1 + ((nHints + 7) >> 3);
1604 nOps = 0;
1605 } else if (s[i] == 28) {
1606 x = (s[i+1] << 8) + s[i+2];
1607 if (x & 0x8000) {
1608 x |= -1 << 15;
1609 }
1610 if (nOps < 48) {
1611 fp[nOps] = gFalse;
1612 op[nOps++] = x;
1613 }
1614 i += 3;
1615 } else if (s[i] <= 31) {
1616 switch (s[i]) {
1617 case 4: // vmoveto
1618 if (first) {
1619 cvtGlyphWidth(nOps == 2);
1620 first = gFalse;
1621 }
1622 if (nOps != 1) {
1623 error(-1, "Wrong number of args (%d) to Type 2 vmoveto", nOps);
1624 }
1625 eexecDumpNum(op[0], fp[0]);
1626 eexecDumpOp1(4);
1627 break;
1628 case 5: // rlineto
1629 if (nOps < 2 || nOps % 2 != 0) {
1630 error(-1, "Wrong number of args (%d) to Type 2 rlineto", nOps);
1631 }
1632 for (k = 0; k < nOps; k += 2) {
1633 eexecDumpNum(op[k], fp[k]);
1634 eexecDumpNum(op[k+1], fp[k+1]);
1635 eexecDumpOp1(5);
1636 }
1637 break;
1638 case 6: // hlineto
1639 if (nOps < 1) {
1640 error(-1, "Wrong number of args (%d) to Type 2 hlineto", nOps);
1641 }
1642 for (k = 0; k < nOps; ++k) {
1643 eexecDumpNum(op[k], fp[k]);
1644 eexecDumpOp1((k & 1) ? 7 : 6);
1645 }
1646 break;
1647 case 7: // vlineto
1648 if (nOps < 1) {
1649 error(-1, "Wrong number of args (%d) to Type 2 vlineto", nOps);
1650 }
1651 for (k = 0; k < nOps; ++k) {
1652 eexecDumpNum(op[k], fp[k]);
1653 eexecDumpOp1((k & 1) ? 6 : 7);
1654 }
1655 break;
1656 case 8: // rrcurveto
1657 if (nOps < 6 || nOps % 6 != 0) {
1658 error(-1, "Wrong number of args (%d) to Type 2 rrcurveto", nOps);
1659 }
1660 for (k = 0; k < nOps; k += 6) {
1661 eexecDumpNum(op[k], fp[k]);
1662 eexecDumpNum(op[k+1], fp[k+1]);
1663 eexecDumpNum(op[k+2], fp[k+2]);
1664 eexecDumpNum(op[k+3], fp[k+3]);
1665 eexecDumpNum(op[k+4], fp[k+4]);
1666 eexecDumpNum(op[k+5], fp[k+5]);
1667 eexecDumpOp1(8);
1668 }
1669 break;
1670 case 14: // endchar / seac
1671 if (first) {
1672 cvtGlyphWidth(nOps == 1 || nOps == 5);
1673 first = gFalse;
1674 }
1675 if (nOps == 4) {
1676 eexecDumpNum(0, 0);
1677 eexecDumpNum(op[0], fp[0]);
1678 eexecDumpNum(op[1], fp[1]);
1679 eexecDumpNum(op[2], fp[2]);
1680 eexecDumpNum(op[3], fp[3]);
1681 eexecDumpOp2(6);
1682 } else if (nOps == 0) {
1683 eexecDumpOp1(14);
1684 } else {
1685 error(-1, "Wrong number of args (%d) to Type 2 endchar", nOps);
1686 }
1687 break;
1688 case 21: // rmoveto
1689 if (first) {
1690 cvtGlyphWidth(nOps == 3);
1691 first = gFalse;
1692 }
1693 if (nOps != 2) {
1694 error(-1, "Wrong number of args (%d) to Type 2 rmoveto", nOps);
1695 }
1696 eexecDumpNum(op[0], fp[0]);
1697 eexecDumpNum(op[1], fp[1]);
1698 eexecDumpOp1(21);
1699 break;
1700 case 22: // hmoveto
1701 if (first) {
1702 cvtGlyphWidth(nOps == 2);
1703 first = gFalse;
1704 }
1705 if (nOps != 1) {
1706 error(-1, "Wrong number of args (%d) to Type 2 hmoveto", nOps);
1707 }
1708 eexecDumpNum(op[0], fp[0]);
1709 eexecDumpOp1(22);
1710 break;
1711 case 24: // rcurveline
1712 if (nOps < 8 || (nOps - 2) % 6 != 0) {
1713 error(-1, "Wrong number of args (%d) to Type 2 rcurveline", nOps);
1714 }
1715 for (k = 0; k < nOps - 2; k += 6) {
1716 eexecDumpNum(op[k], fp[k]);
1717 eexecDumpNum(op[k+1], fp[k+1]);
1718 eexecDumpNum(op[k+2], fp[k+2]);
1719 eexecDumpNum(op[k+3], fp[k+3]);
1720 eexecDumpNum(op[k+4], fp[k+4]);
1721 eexecDumpNum(op[k+5], fp[k+5]);
1722 eexecDumpOp1(8);
1723 }
1724 eexecDumpNum(op[k], fp[k]);
1725 eexecDumpNum(op[k+1], fp[k]);
1726 eexecDumpOp1(5);
1727 break;
1728 case 25: // rlinecurve
1729 if (nOps < 8 || (nOps - 6) % 2 != 0) {
1730 error(-1, "Wrong number of args (%d) to Type 2 rlinecurve", nOps);
1731 }
1732 for (k = 0; k < nOps - 6; k += 2) {
1733 eexecDumpNum(op[k], fp[k]);
1734 eexecDumpNum(op[k+1], fp[k]);
1735 eexecDumpOp1(5);
1736 }
1737 eexecDumpNum(op[k], fp[k]);
1738 eexecDumpNum(op[k+1], fp[k+1]);
1739 eexecDumpNum(op[k+2], fp[k+2]);
1740 eexecDumpNum(op[k+3], fp[k+3]);
1741 eexecDumpNum(op[k+4], fp[k+4]);
1742 eexecDumpNum(op[k+5], fp[k+5]);
1743 eexecDumpOp1(8);
1744 break;
1745 case 26: // vvcurveto
1746 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
1747 error(-1, "Wrong number of args (%d) to Type 2 vvcurveto", nOps);
1748 }
1749 if (nOps % 2 == 1) {
1750 eexecDumpNum(op[0], fp[0]);
1751 eexecDumpNum(op[1], fp[1]);
1752 eexecDumpNum(op[2], fp[2]);
1753 eexecDumpNum(op[3], fp[3]);
1754 eexecDumpNum(0, gFalse);
1755 eexecDumpNum(op[4], fp[4]);
1756 eexecDumpOp1(8);
1757 k = 5;
1758 } else {
1759 k = 0;
1760 }
1761 for (; k < nOps; k += 4) {
1762 eexecDumpNum(0, gFalse);
1763 eexecDumpNum(op[k], fp[k]);
1764 eexecDumpNum(op[k+1], fp[k+1]);
1765 eexecDumpNum(op[k+2], fp[k+2]);
1766 eexecDumpNum(0, gFalse);
1767 eexecDumpNum(op[k+3], fp[k+3]);
1768 eexecDumpOp1(8);
1769 }
1770 break;
1771 case 27: // hhcurveto
1772 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
1773 error(-1, "Wrong number of args (%d) to Type 2 hhcurveto", nOps);
1774 }
1775 if (nOps % 2 == 1) {
1776 eexecDumpNum(op[1], fp[1]);
1777 eexecDumpNum(op[0], fp[0]);
1778 eexecDumpNum(op[2], fp[2]);
1779 eexecDumpNum(op[3], fp[3]);
1780 eexecDumpNum(op[4], fp[4]);
1781 eexecDumpNum(0, gFalse);
1782 eexecDumpOp1(8);
1783 k = 5;
1784 } else {
1785 k = 0;
1786 }
1787 for (; k < nOps; k += 4) {
1788 eexecDumpNum(op[k], fp[k]);
1789 eexecDumpNum(0, gFalse);
1790 eexecDumpNum(op[k+1], fp[k+1]);
1791 eexecDumpNum(op[k+2], fp[k+2]);
1792 eexecDumpNum(op[k+3], fp[k+3]);
1793 eexecDumpNum(0, gFalse);
1794 eexecDumpOp1(8);
1795 }
1796 break;
1797 case 30: // vhcurveto
1798 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
1799 error(-1, "Wrong number of args (%d) to Type 2 vhcurveto", nOps);
1800 }
1801 for (k = 0; k < nOps && k != nOps-5; k += 4) {
1802 if (k % 8 == 0) {
1803 eexecDumpNum(op[k], fp[k]);
1804 eexecDumpNum(op[k+1], fp[k+1]);
1805 eexecDumpNum(op[k+2], fp[k+2]);
1806 eexecDumpNum(op[k+3], fp[k+3]);
1807 eexecDumpOp1(30);
1808 } else {
1809 eexecDumpNum(op[k], fp[k]);
1810 eexecDumpNum(op[k+1], fp[k+1]);
1811 eexecDumpNum(op[k+2], fp[k+2]);
1812 eexecDumpNum(op[k+3], fp[k+3]);
1813 eexecDumpOp1(31);
1814 }
1815 }
1816 if (k == nOps-5) {
1817 if (k % 8 == 0) {
1818 eexecDumpNum(0, gFalse);
1819 eexecDumpNum(op[k], fp[k]);
1820 eexecDumpNum(op[k+1], fp[k+1]);
1821 eexecDumpNum(op[k+2], fp[k+2]);
1822 eexecDumpNum(op[k+3], fp[k+3]);
1823 eexecDumpNum(op[k+4], fp[k+4]);
1824 } else {
1825 eexecDumpNum(op[k], fp[k]);
1826 eexecDumpNum(0, gFalse);
1827 eexecDumpNum(op[k+1], fp[k+1]);
1828 eexecDumpNum(op[k+2], fp[k+2]);
1829 eexecDumpNum(op[k+4], fp[k+4]);
1830 eexecDumpNum(op[k+3], fp[k+3]);
1831 }
1832 eexecDumpOp1(8);
1833 }
1834 break;
1835 case 31: // hvcurveto
1836 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
1837 error(-1, "Wrong number of args (%d) to Type 2 hvcurveto", nOps);
1838 }
1839 for (k = 0; k < nOps && k != nOps-5; k += 4) {
1840 if (k % 8 == 0) {
1841 eexecDumpNum(op[k], fp[k]);
1842 eexecDumpNum(op[k+1], fp[k+1]);
1843 eexecDumpNum(op[k+2], fp[k+2]);
1844 eexecDumpNum(op[k+3], fp[k+3]);
1845 eexecDumpOp1(31);
1846 } else {
1847 eexecDumpNum(op[k], fp[k]);
1848 eexecDumpNum(op[k+1], fp[k+1]);
1849 eexecDumpNum(op[k+2], fp[k+2]);
1850 eexecDumpNum(op[k+3], fp[k+3]);
1851 eexecDumpOp1(30);
1852 }
1853 }
1854 if (k == nOps-5) {
1855 if (k % 8 == 0) {
1856 eexecDumpNum(op[k], fp[k]);
1857 eexecDumpNum(0, gFalse);
1858 eexecDumpNum(op[k+1], fp[k+1]);
1859 eexecDumpNum(op[k+2], fp[k+2]);
1860 eexecDumpNum(op[k+4], fp[k+4]);
1861 eexecDumpNum(op[k+3], fp[k+3]);
1862 } else {
1863 eexecDumpNum(0, gFalse);
1864 eexecDumpNum(op[k], fp[k]);
1865 eexecDumpNum(op[k+1], fp[k+1]);
1866 eexecDumpNum(op[k+2], fp[k+2]);
1867 eexecDumpNum(op[k+3], fp[k+3]);
1868 eexecDumpNum(op[k+4], fp[k+4]);
1869 }
1870 eexecDumpOp1(8);
1871 }
1872 break;
1873 case 1: // hstem
1874 if (first) {
1875 cvtGlyphWidth(nOps & 1);
1876 first = gFalse;
1877 }
1878 if (nOps & 1) {
1879 error(-1, "Wrong number of args (%d) to Type 2 hstem", nOps);
1880 }
1881 d = 0;
1882 dFP = gFalse;
1883 for (k = 0; k < nOps; k += 2) {
1884 if (op[k+1] < 0) {
1885 d += op[k] + op[k+1];
1886 dFP |= fp[k] | fp[k+1];
1887 eexecDumpNum(d, dFP);
1888 eexecDumpNum(-op[k+1], fp[k+1]);
1889 } else {
1890 d += op[k];
1891 dFP |= fp[k];
1892 eexecDumpNum(d, dFP);
1893 eexecDumpNum(op[k+1], fp[k+1]);
1894 d += op[k+1];
1895 dFP |= fp[k+1];
1896 }
1897 eexecDumpOp1(1);
1898 }
1899 nHints += nOps / 2;
1900 break;
1901 case 3: // vstem
1902 if (first) {
1903 cvtGlyphWidth(nOps & 1);
1904 first = gFalse;
1905 }
1906 if (nOps & 1) {
1907 error(-1, "Wrong number of args (%d) to Type 2 vstem", nOps);
1908 }
1909 d = 0;
1910 dFP = gFalse;
1911 for (k = 0; k < nOps; k += 2) {
1912 if (op[k+1] < 0) {
1913 d += op[k] + op[k+1];
1914 dFP |= fp[k] | fp[k+1];
1915 eexecDumpNum(d, dFP);
1916 eexecDumpNum(-op[k+1], fp[k+1]);
1917 } else {
1918 d += op[k];
1919 dFP |= fp[k];
1920 eexecDumpNum(d, dFP);
1921 eexecDumpNum(op[k+1], fp[k+1]);
1922 d += op[k+1];
1923 dFP |= fp[k+1];
1924 }
1925 eexecDumpOp1(3);
1926 }
1927 nHints += nOps / 2;
1928 break;
1929 case 18: // hstemhm
1930 // ignored
1931 if (first) {
1932 cvtGlyphWidth(nOps & 1);
1933 first = gFalse;
1934 }
1935 if (nOps & 1) {
1936 error(-1, "Wrong number of args (%d) to Type 2 hstemhm", nOps);
1937 }
1938 nHints += nOps / 2;
1939 break;
1940 case 23: // vstemhm
1941 // ignored
1942 if (first) {
1943 cvtGlyphWidth(nOps & 1);
1944 first = gFalse;
1945 }
1946 if (nOps & 1) {
1947 error(-1, "Wrong number of args (%d) to Type 2 vstemhm", nOps);
1948 }
1949 nHints += nOps / 2;
1950 break;
1951 case 10: // callsubr
1952 case 11: // return
1953 case 16: // blend
1954 case 29: // callgsubr
1955 error(-1, "Unimplemented Type 2 charstring op: %d", s[i]);
1956 break;
1957 default:
1958 error(-1, "Illegal Type 2 charstring op: %d", s[i]);
1959 break;
1960 }
1961 ++i;
1962 nOps = 0;
1963 } else if (s[i] <= 246) {
1964 if (nOps < 48) {
1965 fp[nOps] = gFalse;
1966 op[nOps++] = (int)s[i] - 139;
1967 }
1968 ++i;
1969 } else if (s[i] <= 250) {
1970 if (nOps < 48) {
1971 fp[nOps] = gFalse;
1972 op[nOps++] = (((int)s[i] - 247) << 8) + (int)s[i+1] + 108;
1973 }
1974 i += 2;
1975 } else if (s[i] <= 254) {
1976 if (nOps < 48) {
1977 fp[nOps] = gFalse;
1978 op[nOps++] = -(((int)s[i] - 251) << 8) - (int)s[i+1] - 108;
1979 }
1980 i += 2;
1981 } else {
1982 x = (s[i+1] << 24) | (s[i+2] << 16) | (s[i+3] << 8) | s[i+4];
1983 if (x & 0x80000000)
1984 x |= -1 << 31;
1985 if (nOps < 48) {
1986 fp[nOps] = gTrue;
1987 op[nOps++] = (double)x / 65536.0;
1988 }
1989 i += 5;
1990 }
1991 }
1992
1993 // charstring encryption
1994 r2 = 4330;
1995 for (i = 0; i < charBuf->getLength(); ++i) {
1996 byte = charBuf->getChar(i) ^ (r2 >> 8);
1997 charBuf->setChar(i, byte);
1998 r2 = (byte + r2) * 52845 + 22719;
1999 }
2000}
2001
2002void Type1CFontFile::cvtGlyphWidth(GBool useOp) {
2003 double w;
2004 GBool wFP;
2005 int i;
2006
2007 if (useOp) {
2008 w = nominalWidthX + op[0];
2009 wFP = nominalWidthXFP | fp[0];
2010 for (i = 1; i < nOps; ++i) {
2011 op[i-1] = op[i];
2012 fp[i-1] = fp[i];
2013 }
2014 --nOps;
2015 } else {
2016 w = defaultWidthX;
2017 wFP = defaultWidthXFP;
2018 }
2019 eexecDumpNum(0, gFalse);
2020 eexecDumpNum(w, wFP);
2021 eexecDumpOp1(13);
2022}
2023
2024void Type1CFontFile::eexecDumpNum(double x, GBool fpA) {
2025 Guchar buf[12];
2026 int y, n;
2027
2028 n = 0;
2029 if (fpA) {
2030 if (x >= -32768 && x < 32768) {
2031 y = (int)(x * 256.0);
2032 buf[0] = 255;
2033 buf[1] = (Guchar)(y >> 24);
2034 buf[2] = (Guchar)(y >> 16);
2035 buf[3] = (Guchar)(y >> 8);
2036 buf[4] = (Guchar)y;
2037 buf[5] = 255;
2038 buf[6] = 0;
2039 buf[7] = 0;
2040 buf[8] = 1;
2041 buf[9] = 0;
2042 buf[10] = 12;
2043 buf[11] = 12;
2044 n = 12;
2045 } else {
2046 error(-1, "Type 2 fixed point constant out of range");
2047 }
2048 } else {
2049 y = (int)x;
2050 if (y >= -107 && y <= 107) {
2051 buf[0] = (Guchar)(y + 139);
2052 n = 1;
2053 } else if (y > 107 && y <= 1131) {
2054 y -= 108;
2055 buf[0] = (Guchar)((y >> 8) + 247);
2056 buf[1] = (Guchar)(y & 0xff);
2057 n = 2;
2058 } else if (y < -107 && y >= -1131) {
2059 y = -y - 108;
2060 buf[0] = (Guchar)((y >> 8) + 251);
2061 buf[1] = (Guchar)(y & 0xff);
2062 n = 2;
2063 } else {
2064 buf[0] = 255;
2065 buf[1] = (Guchar)(y >> 24);
2066 buf[2] = (Guchar)(y >> 16);
2067 buf[3] = (Guchar)(y >> 8);
2068 buf[4] = (Guchar)y;
2069 n = 5;
2070 }
2071 }
2072 charBuf->append((char *)buf, n);
2073}
2074
2075void Type1CFontFile::eexecDumpOp1(int opA) {
2076 charBuf->append((char)opA);
2077}
2078
2079void Type1CFontFile::eexecDumpOp2(int opA) {
2080 charBuf->append((char)12);
2081 charBuf->append((char)opA);
2082}
2083
2084void Type1CFontFile::eexecWriteCharstring(const Guchar *s, int n) {
2085 Guchar x;
2086 int i;
2087
2088 // eexec encryption
2089 for (i = 0; i < n; ++i) {
2090 x = s[i] ^ (r1 >> 8);
2091 r1 = (x + r1) * 52845 + 22719;
2092 (*outputFunc)(outputStream, &hexChars[x >> 4], 1);
2093 (*outputFunc)(outputStream, &hexChars[x & 0x0f], 1);
2094 line += 2;
2095 if (line == 64) {
2096 (*outputFunc)(outputStream, "\n", 1);
2097 line = 0;
2098 }
2099 }
2100}
2101
2102void Type1CFontFile::getDeltaInt(char *buf, const char *key, const double *opA,
2103 int n) {
2104 int x, i;
2105
2106 sprintf(buf, "/%s [", key);
2107 buf += strlen(buf);
2108 x = 0;
2109 for (i = 0; i < n; ++i) {
2110 x += (int)opA[i];
2111 sprintf(buf, "%s%d", i > 0 ? " " : "", x);
2112 buf += strlen(buf);
2113 }
2114 sprintf(buf, "] def\n");
2115}
2116
2117void Type1CFontFile::getDeltaReal(char *buf, const char *key, const double *opA,
2118 int n) {
2119 double x;
2120 int i;
2121
2122 sprintf(buf, "/%s [", key);
2123 buf += strlen(buf);
2124 x = 0;
2125 for (i = 0; i < n; ++i) {
2126 x += opA[i];
2127 sprintf(buf, "%s%g", i > 0 ? " " : "", x);
2128 buf += strlen(buf);
2129 }
2130 sprintf(buf, "] def\n");
2131}
2132
2133int Type1CFontFile::getIndexLen(Guchar *indexPtr) {
2134 return (int)getWord(indexPtr, 2);
2135}
2136
2137Guchar *Type1CFontFile::getIndexValPtr(Guchar *indexPtr, int i) {
2138 int n, offSize;
2139 Guchar *idxStartPtr;
2140
2141 n = (int)getWord(indexPtr, 2);
2142 offSize = indexPtr[2];
2143 idxStartPtr = indexPtr + 3 + (n + 1) * offSize - 1;
2144 return idxStartPtr + getWord(indexPtr + 3 + i * offSize, offSize);
2145}
2146
2147Guchar *Type1CFontFile::getIndexEnd(Guchar *indexPtr) {
2148 int n, offSize;
2149 Guchar *idxStartPtr;
2150
2151 n = (int)getWord(indexPtr, 2);
2152 offSize = indexPtr[2];
2153 idxStartPtr = indexPtr + 3 + (n + 1) * offSize - 1;
2154 return idxStartPtr + getWord(indexPtr + 3 + n * offSize, offSize);
2155}
2156
2157Guint Type1CFontFile::getWord(Guchar *ptr, int size) {
2158 Guint x;
2159 int i;
2160
2161 x = 0;
2162 for (i = 0; i < size; ++i) {
2163 x = (x << 8) + *ptr++;
2164 }
2165 return x;
2166}
2167
2168double Type1CFontFile::getNum(Guchar **ptr, GBool *isFP) {
2169 static char nybChars[16] = "0123456789.ee -";
2170 int b0, b, nyb0, nyb1;
2171 double x;
2172 char buf[65];
2173 int i;
2174
2175 x = 0;
2176 *isFP = gFalse;
2177 b0 = (*ptr)[0];
2178 if (b0 < 28) {
2179 x = 0;
2180 } else if (b0 == 28) {
2181 x = ((*ptr)[1] << 8) + (*ptr)[2];
2182 *ptr += 3;
2183 } else if (b0 == 29) {
2184 x = ((*ptr)[1] << 24) + ((*ptr)[2] << 16) + ((*ptr)[3] << 8) + (*ptr)[4];
2185 *ptr += 5;
2186 } else if (b0 == 30) {
2187 *ptr += 1;
2188 i = 0;
2189 do {
2190 b = *(*ptr)++;
2191 nyb0 = b >> 4;
2192 nyb1 = b & 0x0f;
2193 if (nyb0 == 0xf) {
2194 break;
2195 }
2196 buf[i++] = nybChars[nyb0];
2197 if (i == 64) {
2198 break;
2199 }
2200 if (nyb0 == 0xc) {
2201 buf[i++] = '-';
2202 }
2203 if (i == 64) {
2204 break;
2205 }
2206 if (nyb1 == 0xf) {
2207 break;
2208 }
2209 buf[i++] = nybChars[nyb1];
2210 if (i == 64) {
2211 break;
2212 }
2213 if (nyb1 == 0xc) {
2214 buf[i++] = '-';
2215 }
2216 } while (i < 64);
2217 buf[i] = '\0';
2218 x = atof(buf);
2219 *isFP = gTrue;
2220 } else if (b0 == 31) {
2221 x = 0;
2222 } else if (b0 < 247) {
2223 x = b0 - 139;
2224 *ptr += 1;
2225 } else if (b0 < 251) {
2226 x = ((b0 - 247) << 8) + (*ptr)[1] + 108;
2227 *ptr += 2;
2228 } else {
2229 x = -((b0 - 251) << 8) - (*ptr)[1] - 108;
2230 *ptr += 2;
2231 }
2232 return x;
2233}
2234
2235char *Type1CFontFile::getString(int sid, char *buf) {
2236 Guchar *idxPtr0, *idxPtr1;
2237 int n;
2238
2239 if (sid < 391) {
2240 strcpy(buf, type1CStdStrings[sid]);
2241 } else {
2242 sid -= 391;
2243 idxPtr0 = getIndexValPtr(stringIdxPtr, sid);
2244 idxPtr1 = getIndexValPtr(stringIdxPtr, sid + 1);
2245 if ((n = idxPtr1 - idxPtr0) > 255) {
2246 n = 255;
2247 }
2248 strncpy(buf, (char *)idxPtr0, n);
2249 buf[n] = '\0';
2250 }
2251 return buf;
2252}
2253
2254//------------------------------------------------------------------------
2255// TrueTypeFontFile
2256//------------------------------------------------------------------------
2257
2258//
2259// Terminology
2260// -----------
2261//
2262// character code = number used as an element of a text string
2263//
2264// character name = glyph name = name for a particular glyph within a
2265// font
2266//
2267// glyph index = position (within some internal table in the font)
2268// where the instructions to draw a particular glyph are
2269// stored
2270//
2271// Type 1 fonts
2272// ------------
2273//
2274// Type 1 fonts contain:
2275//
2276// Encoding: array of glyph names, maps char codes to glyph names
2277//
2278// Encoding[charCode] = charName
2279//
2280// CharStrings: dictionary of instructions, keyed by character names,
2281// maps character name to glyph data
2282//
2283// CharStrings[charName] = glyphData
2284//
2285// TrueType fonts
2286// --------------
2287//
2288// TrueType fonts contain:
2289//
2290// 'cmap' table: mapping from character code to glyph index; there may
2291// be multiple cmaps in a TrueType font
2292//
2293// cmap[charCode] = glyphIdx
2294//
2295// 'post' table: mapping from glyph index to glyph name
2296//
2297// post[glyphIdx] = glyphName
2298//
2299// Type 42 fonts
2300// -------------
2301//
2302// Type 42 fonts contain:
2303//
2304// Encoding: array of glyph names, maps char codes to glyph names
2305//
2306// Encoding[charCode] = charName
2307//
2308// CharStrings: dictionary of glyph indexes, keyed by character names,
2309// maps character name to glyph index
2310//
2311// CharStrings[charName] = glyphIdx
2312//
2313
2314struct TTFontTableHdr {
2315 char tag[4];
2316 Guint checksum;
2317 Guint offset;
2318 Guint length;
2319};
2320
2321struct T42Table {
2322 const char *tag; // 4-byte tag
2323 GBool required; // required by the TrueType spec?
2324};
2325
2326// TrueType tables to be embedded in Type 42 fonts.
2327// NB: the table names must be in alphabetical order here.
2328#define nT42Tables 11
2329static T42Table t42Tables[nT42Tables] = {
2330 { "cvt ", gTrue },
2331 { "fpgm", gTrue },
2332 { "glyf", gTrue },
2333 { "head", gTrue },
2334 { "hhea", gTrue },
2335 { "hmtx", gTrue },
2336 { "loca", gTrue },
2337 { "maxp", gTrue },
2338 { "prep", gTrue },
2339 { "vhea", gFalse },
2340 { "vmtx", gFalse }
2341};
2342#define t42HeadTable 3
2343#define t42LocaTable 6
2344#define t42GlyfTable 2
2345
2346// Glyph names in some arbitrary standard that Apple uses for their
2347// TrueType fonts.
2348static const char *macGlyphNames[258] = {
2349 ".notdef",
2350 "null",
2351 "CR",
2352 "space",
2353 "exclam",
2354 "quotedbl",
2355 "numbersign",
2356 "dollar",
2357 "percent",
2358 "ampersand",
2359 "quotesingle",
2360 "parenleft",
2361 "parenright",
2362 "asterisk",
2363 "plus",
2364 "comma",
2365 "hyphen",
2366 "period",
2367 "slash",
2368 "zero",
2369 "one",
2370 "two",
2371 "three",
2372 "four",
2373 "five",
2374 "six",
2375 "seven",
2376 "eight",
2377 "nine",
2378 "colon",
2379 "semicolon",
2380 "less",
2381 "equal",
2382 "greater",
2383 "question",
2384 "at",
2385 "A",
2386 "B",
2387 "C",
2388 "D",
2389 "E",
2390 "F",
2391 "G",
2392 "H",
2393 "I",
2394 "J",
2395 "K",
2396 "L",
2397 "M",
2398 "N",
2399 "O",
2400 "P",
2401 "Q",
2402 "R",
2403 "S",
2404 "T",
2405 "U",
2406 "V",
2407 "W",
2408 "X",
2409 "Y",
2410 "Z",
2411 "bracketleft",
2412 "backslash",
2413 "bracketright",
2414 "asciicircum",
2415 "underscore",
2416 "grave",
2417 "a",
2418 "b",
2419 "c",
2420 "d",
2421 "e",
2422 "f",
2423 "g",
2424 "h",
2425 "i",
2426 "j",
2427 "k",
2428 "l",
2429 "m",
2430 "n",
2431 "o",
2432 "p",
2433 "q",
2434 "r",
2435 "s",
2436 "t",
2437 "u",
2438 "v",
2439 "w",
2440 "x",
2441 "y",
2442 "z",
2443 "braceleft",
2444 "bar",
2445 "braceright",
2446 "asciitilde",
2447 "Adieresis",
2448 "Aring",
2449 "Ccedilla",
2450 "Eacute",
2451 "Ntilde",
2452 "Odieresis",
2453 "Udieresis",
2454 "aacute",
2455 "agrave",
2456 "acircumflex",
2457 "adieresis",
2458 "atilde",
2459 "aring",
2460 "ccedilla",
2461 "eacute",
2462 "egrave",
2463 "ecircumflex",
2464 "edieresis",
2465 "iacute",
2466 "igrave",
2467 "icircumflex",
2468 "idieresis",
2469 "ntilde",
2470 "oacute",
2471 "ograve",
2472 "ocircumflex",
2473 "odieresis",
2474 "otilde",
2475 "uacute",
2476 "ugrave",
2477 "ucircumflex",
2478 "udieresis",
2479 "dagger",
2480 "degree",
2481 "cent",
2482 "sterling",
2483 "section",
2484 "bullet",
2485 "paragraph",
2486 "germandbls",
2487 "registered",
2488 "copyright",
2489 "trademark",
2490 "acute",
2491 "dieresis",
2492 "notequal",
2493 "AE",
2494 "Oslash",
2495 "infinity",
2496 "plusminus",
2497 "lessequal",
2498 "greaterequal",
2499 "yen",
2500 "mu1",
2501 "partialdiff",
2502 "summation",
2503 "product",
2504 "pi",
2505 "integral",
2506 "ordfeminine",
2507 "ordmasculine",
2508 "Ohm",
2509 "ae",
2510 "oslash",
2511 "questiondown",
2512 "exclamdown",
2513 "logicalnot",
2514 "radical",
2515 "florin",
2516 "approxequal",
2517 "increment",
2518 "guillemotleft",
2519 "guillemotright",
2520 "ellipsis",
2521 "nbspace",
2522 "Agrave",
2523 "Atilde",
2524 "Otilde",
2525 "OE",
2526 "oe",
2527 "endash",
2528 "emdash",
2529 "quotedblleft",
2530 "quotedblright",
2531 "quoteleft",
2532 "quoteright",
2533 "divide",
2534 "lozenge",
2535 "ydieresis",
2536 "Ydieresis",
2537 "fraction",
2538 "currency",
2539 "guilsinglleft",
2540 "guilsinglright",
2541 "fi",
2542 "fl",
2543 "daggerdbl",
2544 "periodcentered",
2545 "quotesinglbase",
2546 "quotedblbase",
2547 "perthousand",
2548 "Acircumflex",
2549 "Ecircumflex",
2550 "Aacute",
2551 "Edieresis",
2552 "Egrave",
2553 "Iacute",
2554 "Icircumflex",
2555 "Idieresis",
2556 "Igrave",
2557 "Oacute",
2558 "Ocircumflex",
2559 "applelogo",
2560 "Ograve",
2561 "Uacute",
2562 "Ucircumflex",
2563 "Ugrave",
2564 "dotlessi",
2565 "circumflex",
2566 "tilde",
2567 "overscore",
2568 "breve",
2569 "dotaccent",
2570 "ring",
2571 "cedilla",
2572 "hungarumlaut",
2573 "ogonek",
2574 "caron",
2575 "Lslash",
2576 "lslash",
2577 "Scaron",
2578 "scaron",
2579 "Zcaron",
2580 "zcaron",
2581 "brokenbar",
2582 "Eth",
2583 "eth",
2584 "Yacute",
2585 "yacute",
2586 "Thorn",
2587 "thorn",
2588 "minus",
2589 "multiply",
2590 "onesuperior",
2591 "twosuperior",
2592 "threesuperior",
2593 "onehalf",
2594 "onequarter",
2595 "threequarters",
2596 "franc",
2597 "Gbreve",
2598 "gbreve",
2599 "Idot",
2600 "Scedilla",
2601 "scedilla",
2602 "Cacute",
2603 "cacute",
2604 "Ccaron",
2605 "ccaron",
2606 "dmacron"
2607};
2608
2609enum T42FontIndexMode {
2610 t42FontModeUnicode,
2611 t42FontModeCharCode,
2612 t42FontModeCharCodeOffset,
2613 t42FontModeMacRoman
2614};
2615
2616TrueTypeFontFile::TrueTypeFontFile(const char *fileA, int lenA) {
2617 int pos, i, idx, n, length;
2618 Guint size, startPos, endPos;
2619
2620 file = fileA;
2621 len = lenA;
2622
2623 encoding = NULL;
2624
2625 // read table directory
2626 nTables = getUShort(4);
2627 tableHdrs = (TTFontTableHdr *)gmalloc(nTables * sizeof(TTFontTableHdr));
2628 pos = 12;
2629 for (i = 0; i < nTables; ++i) {
2630 tableHdrs[i].tag[0] = getByte(pos+0);
2631 tableHdrs[i].tag[1] = getByte(pos+1);
2632 tableHdrs[i].tag[2] = getByte(pos+2);
2633 tableHdrs[i].tag[3] = getByte(pos+3);
2634 tableHdrs[i].checksum = getULong(pos+4);
2635 tableHdrs[i].offset = getULong(pos+8);
2636 tableHdrs[i].length = getULong(pos+12);
2637 pos += 16;
2638 }
2639
2640 // check for tables that are required by both the TrueType spec
2641 // and the Type 42 spec
2642 if (seekTable("head") < 0 ||
2643 seekTable("hhea") < 0 ||
2644 seekTable("loca") < 0 ||
2645 seekTable("maxp") < 0 ||
2646 seekTable("glyf") < 0 ||
2647 seekTable("hmtx") < 0) {
2648 error(-1, "TrueType font file is missing a required table");
2649 return;
2650 }
2651
2652 // some embedded TrueType fonts have an incorrect (too small) cmap
2653 // table size
2654 idx = seekTableIdx("cmap");
2655 if (idx >= 0) {
2656 pos = tableHdrs[idx].offset;
2657 n = getUShort(pos + 2);
2658 size = (Guint)(4 + 8 * n);
2659 for (i = 0; i < n; ++i) {
2660 startPos = getULong(pos + 4 + 8*i + 4);
2661 length = getUShort(pos + startPos + 2);
2662 endPos = startPos + length;
2663 if (endPos > size) {
2664 size = endPos;
2665 }
2666 }
2667 if ((mungedCmapSize = size > tableHdrs[idx].length)) {
2668#if 0 // don't bother printing this error message - it's too common
2669 error(-1, "Bad cmap table size in TrueType font");
2670#endif
2671 tableHdrs[idx].length = size;
2672 }
2673 } else {
2674 mungedCmapSize = gFalse;
2675 }
2676
2677 // read the 'head' table
2678 pos = seekTable("head");
2679 bbox[0] = getShort(pos + 36);
2680 bbox[1] = getShort(pos + 38);
2681 bbox[2] = getShort(pos + 40);
2682 bbox[3] = getShort(pos + 42);
2683 locaFmt = getShort(pos + 50);
2684
2685 // read the 'maxp' table
2686 pos = seekTable("maxp");
2687 nGlyphs = getUShort(pos + 4);
2688}
2689
2690TrueTypeFontFile::~TrueTypeFontFile() {
2691 int i;
2692
2693 if (encoding) {
2694 for (i = 0; i < 256; ++i) {
2695 gfree(encoding[i]);
2696 }
2697 gfree(encoding);
2698 }
2699 gfree(tableHdrs);
2700}
2701
2702const char *TrueTypeFontFile::getName() {
2703 return NULL;
2704}
2705
2706char **TrueTypeFontFile::getEncoding() {
2707 int cmap[256];
2708 int nCmaps, cmapPlatform, cmapEncoding, cmapFmt;
2709 int cmapLen, cmapOffset, cmapFirst;
2710 int segCnt, segStart, segEnd, segDelta, segOffset;
2711 int pos, i, j, k;
2712 Guint fmt;
2713 GString *s;
2714 int stringIdx, stringPos, n;
2715
2716 if (encoding) {
2717 return encoding;
2718 }
2719
2720 //----- construct the (char code) -> (glyph idx) mapping
2721
2722 // map everything to the missing glyph
2723 for (i = 0; i < 256; ++i) {
2724 cmap[i] = 0;
2725 }
2726
2727 // look for the 'cmap' table
2728 if ((pos = seekTable("cmap")) >= 0) {
2729 nCmaps = getUShort(pos+2);
2730
2731 // if the font has a Windows-symbol cmap, use it;
2732 // otherwise, use the first cmap in the table
2733 for (i = 0; i < nCmaps; ++i) {
2734 cmapPlatform = getUShort(pos + 4 + 8*i);
2735 cmapEncoding = getUShort(pos + 4 + 8*i + 2);
2736 if (cmapPlatform == 3 && cmapEncoding == 0) {
2737 break;
2738 }
2739 }
2740 if (i >= nCmaps) {
2741 i = 0;
2742 cmapPlatform = getUShort(pos + 4);
2743 cmapEncoding = getUShort(pos + 4 + 2);
2744 }
2745 pos += getULong(pos + 4 + 8*i + 4);
2746
2747 // read the cmap
2748 cmapFmt = getUShort(pos);
2749 switch (cmapFmt) {
2750 case 0: // byte encoding table (Apple standard)
2751 cmapLen = getUShort(pos + 2);
2752 for (i = 0; i < cmapLen && i < 256; ++i) {
2753 cmap[i] = getByte(pos + 6 + i);
2754 }
2755 break;
2756 case 4: // segment mapping to delta values (Microsoft standard)
2757 if (cmapPlatform == 3 && cmapEncoding == 0) {
2758 // Windows-symbol uses char codes 0xf000 - 0xf0ff
2759 cmapOffset = 0xf000;
2760 } else {
2761 cmapOffset = 0;
2762 }
2763 segCnt = getUShort(pos + 6) / 2;
2764 for (i = 0; i < segCnt; ++i) {
2765 segEnd = getUShort(pos + 14 + 2*i);
2766 segStart = getUShort(pos + 16 + 2*segCnt + 2*i);
2767 segDelta = getUShort(pos + 16 + 4*segCnt + 2*i);
2768 segOffset = getUShort(pos + 16 + 6*segCnt + 2*i);
2769 if (segStart - cmapOffset <= 0xff &&
2770 segEnd - cmapOffset >= 0) {
2771 for (j = (segStart - cmapOffset >= 0) ? segStart : cmapOffset;
2772 j <= segEnd && j - cmapOffset <= 0xff;
2773 ++j) {
2774 if (segOffset == 0) {
2775 k = (j + segDelta) & 0xffff;
2776 } else {
2777 k = getUShort(pos + 16 + 6*segCnt + 2*i +
2778 segOffset + 2 * (j - segStart));
2779 if (k != 0) {
2780 k = (k + segDelta) & 0xffff;
2781 }
2782 }
2783 cmap[j - cmapOffset] = k;
2784 }
2785 }
2786 }
2787 break;
2788 case 6: // trimmed table mapping
2789 cmapFirst = getUShort(pos + 6);
2790 cmapLen = getUShort(pos + 8);
2791 for (i = cmapFirst; i < 256 && i < cmapFirst + cmapLen; ++i) {
2792 cmap[i] = getUShort(pos + 10 + 2*i);
2793 }
2794 break;
2795 default:
2796 error(-1, "Unimplemented cmap format (%d) in TrueType font file",
2797 cmapFmt);
2798 break;
2799 }
2800 }
2801
2802 //----- construct the (glyph idx) -> (glyph name) mapping
2803 //----- and compute the (char code) -> (glyph name) mapping
2804
2805 encoding = (char **)gmalloc(256 * sizeof(char *));
2806 for (i = 0; i < 256; ++i) {
2807 encoding[i] = NULL;
2808 }
2809
2810 if ((pos = seekTable("post")) >= 0) {
2811 fmt = getULong(pos);
2812
2813 // Apple font
2814 if (fmt == 0x00010000) {
2815 for (i = 0; i < 256; ++i) {
2816 j = (cmap[i] < 258) ? cmap[i] : 0;
2817 encoding[i] = copyString(macGlyphNames[j]);
2818 }
2819
2820 // Microsoft font
2821 } else if (fmt == 0x00020000) {
2822 stringIdx = 0;
2823 stringPos = pos + 34 + 2*nGlyphs;
2824 for (i = 0; i < 256; ++i) {
2825 if (cmap[i] < nGlyphs) {
2826 j = getUShort(pos + 34 + 2 * cmap[i]);
2827 if (j < 258) {
2828 encoding[i] = copyString(macGlyphNames[j]);
2829 } else {
2830 j -= 258;
2831 if (j != stringIdx) {
2832 for (stringIdx = 0, stringPos = pos + 34 + 2*nGlyphs;
2833 stringIdx < j;
2834 ++stringIdx, stringPos += 1 + getByte(stringPos)) ;
2835 }
2836 n = getByte(stringPos);
2837 s = new GString(file + stringPos + 1, n);
2838 encoding[i] = copyString(s->getCString());
2839 delete s;
2840 ++stringIdx;
2841 stringPos += 1 + n;
2842 }
2843 } else {
2844 encoding[i] = copyString(macGlyphNames[0]);
2845 }
2846 }
2847
2848 // Apple subset
2849 } else if (fmt == 0x000280000) {
2850 for (i = 0; i < 256; ++i) {
2851 if (cmap[i] < nGlyphs) {
2852 j = i + getChar(pos + 32 + cmap[i]);
2853 } else {
2854 j = 0;
2855 }
2856 encoding[i] = copyString(macGlyphNames[j]);
2857 }
2858
2859 // Ugh, just assume the Apple glyph set
2860 } else {
2861 for (i = 0; i < 256; ++i) {
2862 j = (cmap[i] < 258) ? cmap[i] : 0;
2863 encoding[i] = copyString(macGlyphNames[j]);
2864 }
2865 }
2866
2867 // no "post" table: assume the Apple glyph set
2868 } else {
2869 for (i = 0; i < 256; ++i) {
2870 j = (cmap[i] < 258) ? cmap[i] : 0;
2871 encoding[i] = copyString(macGlyphNames[j]);
2872 }
2873 }
2874
2875 return encoding;
2876}
2877
2878void TrueTypeFontFile::convertToType42(const char *name, const char **encodingA,
2879 CharCodeToUnicode *toUnicode,
2880 GBool pdfFontHasEncoding,
2881 FontFileOutputFunc outputFunc,
2882 void *outputStream) {
2883 char buf[512];
2884
2885 // write the header
2886 sprintf(buf, "%%!PS-TrueTypeFont-%g\n", getFixed(0));
2887 (*outputFunc)(outputStream, buf, strlen(buf));
2888
2889 // begin the font dictionary
2890 (*outputFunc)(outputStream, "10 dict begin\n", 14);
2891 (*outputFunc)(outputStream, "/FontName /", 11);
2892 (*outputFunc)(outputStream, name, strlen(name));
2893 (*outputFunc)(outputStream, " def\n", 5);
2894 (*outputFunc)(outputStream, "/FontType 42 def\n", 17);
2895 (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
2896 sprintf(buf, "/FontBBox [%d %d %d %d] def\n",
2897 bbox[0], bbox[1], bbox[2], bbox[3]);
2898 (*outputFunc)(outputStream, buf, strlen(buf));
2899 (*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
2900
2901 // write the guts of the dictionary
2902 cvtEncoding(encodingA, pdfFontHasEncoding, outputFunc, outputStream);
2903 cvtCharStrings(encodingA, toUnicode, pdfFontHasEncoding,
2904 outputFunc, outputStream);
2905 cvtSfnts(outputFunc, outputStream, NULL);
2906
2907 // end the dictionary and define the font
2908 (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
2909}
2910
2911void TrueTypeFontFile::convertToCIDType2(const char *name, const Gushort *cidMap,
2912 int nCIDs,
2913 FontFileOutputFunc outputFunc,
2914 void *outputStream) {
2915 char buf[512];
2916 Gushort cid;
2917 int i, j, k;
2918
2919 // write the header
2920 sprintf(buf, "%%!PS-TrueTypeFont-%g\n", getFixed(0));
2921 (*outputFunc)(outputStream, buf, strlen(buf));
2922
2923 // begin the font dictionary
2924 (*outputFunc)(outputStream, "20 dict begin\n", 14);
2925 (*outputFunc)(outputStream, "/CIDFontName /", 14);
2926 (*outputFunc)(outputStream, name, strlen(name));
2927 (*outputFunc)(outputStream, " def\n", 5);
2928 (*outputFunc)(outputStream, "/CIDFontType 2 def\n", 19);
2929 (*outputFunc)(outputStream, "/FontType 42 def\n", 17);
2930 (*outputFunc)(outputStream, "/CIDSystemInfo 3 dict dup begin\n", 32);
2931 (*outputFunc)(outputStream, " /Registry (Adobe) def\n", 24);
2932 (*outputFunc)(outputStream, " /Ordering (Identity) def\n", 27);
2933 (*outputFunc)(outputStream, " /Supplement 0 def\n", 20);
2934 (*outputFunc)(outputStream, " end def\n", 10);
2935 (*outputFunc)(outputStream, "/GDBytes 2 def\n", 15);
2936 if (cidMap) {
2937 sprintf(buf, "/CIDCount %d def\n", nCIDs);
2938 (*outputFunc)(outputStream, buf, strlen(buf));
2939 if (nCIDs > 32767) {
2940 (*outputFunc)(outputStream, "/CIDMap [", 9);
2941 for (i = 0; i < nCIDs; i += 32768 - 16) {
2942 (*outputFunc)(outputStream, "<\n", 2);
2943 for (j = 0; j < 32768 - 16 && i+j < nCIDs; j += 16) {
2944 (*outputFunc)(outputStream, " ", 2);
2945 for (k = 0; k < 16 && i+j+k < nCIDs; ++k) {
2946 cid = cidMap[i+j+k];
2947 sprintf(buf, "%02x%02x", (cid >> 8) & 0xff, cid & 0xff);
2948 (*outputFunc)(outputStream, buf, strlen(buf));
2949 }
2950 (*outputFunc)(outputStream, "\n", 1);
2951 }
2952 (*outputFunc)(outputStream, " >", 3);
2953 }
2954 (*outputFunc)(outputStream, "\n", 1);
2955 (*outputFunc)(outputStream, "] def\n", 6);
2956 } else {
2957 (*outputFunc)(outputStream, "/CIDMap <\n", 10);
2958 for (i = 0; i < nCIDs; i += 16) {
2959 (*outputFunc)(outputStream, " ", 2);
2960 for (j = 0; j < 16 && i+j < nCIDs; ++j) {
2961 cid = cidMap[i+j];
2962 sprintf(buf, "%02x%02x", (cid >> 8) & 0xff, cid & 0xff);
2963 (*outputFunc)(outputStream, buf, strlen(buf));
2964 }
2965 (*outputFunc)(outputStream, "\n", 1);
2966 }
2967 (*outputFunc)(outputStream, "> def\n", 6);
2968 }
2969 } else {
2970 // direct mapping - just fill the string(s) with s[i]=i
2971 sprintf(buf, "/CIDCount %d def\n", nGlyphs);
2972 (*outputFunc)(outputStream, buf, strlen(buf));
2973 if (nGlyphs > 32767) {
2974 (*outputFunc)(outputStream, "/CIDMap [\n", 10);
2975 for (i = 0; i < nGlyphs; i += 32767) {
2976 j = nGlyphs - i < 32767 ? nGlyphs - i : 32767;
2977 sprintf(buf, " %d string 0 1 %d {\n", 2 * j, j - 1);
2978 (*outputFunc)(outputStream, buf, strlen(buf));
2979 sprintf(buf, " 2 copy dup 2 mul exch %d add -8 bitshift put\n", i);
2980 (*outputFunc)(outputStream, buf, strlen(buf));
2981 sprintf(buf, " 1 index exch dup 2 mul 1 add exch %d add"
2982 " 255 and put\n", i);
2983 (*outputFunc)(outputStream, buf, strlen(buf));
2984 (*outputFunc)(outputStream, " } for\n", 8);
2985 }
2986 (*outputFunc)(outputStream, "] def\n", 6);
2987 } else {
2988 sprintf(buf, "/CIDMap %d string\n", 2 * nGlyphs);
2989 (*outputFunc)(outputStream, buf, strlen(buf));
2990 sprintf(buf, " 0 1 %d {\n", nGlyphs - 1);
2991 (*outputFunc)(outputStream, buf, strlen(buf));
2992 (*outputFunc)(outputStream,
2993 " 2 copy dup 2 mul exch -8 bitshift put\n", 42);
2994 (*outputFunc)(outputStream,
2995 " 1 index exch dup 2 mul 1 add exch 255 and put\n", 50);
2996 (*outputFunc)(outputStream, " } for\n", 8);
2997 (*outputFunc)(outputStream, "def\n", 4);
2998 }
2999 }
3000 (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
3001 sprintf(buf, "/FontBBox [%d %d %d %d] def\n",
3002 bbox[0], bbox[1], bbox[2], bbox[3]);
3003 (*outputFunc)(outputStream, buf, strlen(buf));
3004 (*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
3005 (*outputFunc)(outputStream, "/Encoding [] readonly def\n", 26);
3006 (*outputFunc)(outputStream, "/CharStrings 1 dict dup begin\n", 30);
3007 (*outputFunc)(outputStream, " /.notdef 0 def\n", 17);
3008 (*outputFunc)(outputStream, " end readonly def\n", 19);
3009
3010 // write the guts of the dictionary
3011 cvtSfnts(outputFunc, outputStream, NULL);
3012
3013 // end the dictionary and define the font
3014 (*outputFunc)(outputStream,
3015 "CIDFontName currentdict end /CIDFont defineresource pop\n",
3016 56);
3017}
3018
3019void TrueTypeFontFile::convertToType0(const char *name, const Gushort *cidMap,
3020 int nCIDs,
3021 FontFileOutputFunc outputFunc,
3022 void *outputStream) {
3023 char buf[512];
3024 GString *sfntsName;
3025 int n, i, j;
3026
3027 // write the Type 42 sfnts array
3028 sfntsName = (new GString(name))->append("_sfnts");
3029 cvtSfnts(outputFunc, outputStream, sfntsName);
3030 delete sfntsName;
3031
3032 // write the descendant Type 42 fonts
3033 n = cidMap ? nCIDs : nGlyphs;
3034 for (i = 0; i < n; i += 256) {
3035 (*outputFunc)(outputStream, "10 dict begin\n", 14);
3036 (*outputFunc)(outputStream, "/FontName /", 11);
3037 (*outputFunc)(outputStream, name, strlen(name));
3038 sprintf(buf, "_%02x def\n", i >> 8);
3039 (*outputFunc)(outputStream, buf, strlen(buf));
3040 (*outputFunc)(outputStream, "/FontType 42 def\n", 17);
3041 (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
3042 sprintf(buf, "/FontBBox [%d %d %d %d] def\n",
3043 bbox[0], bbox[1], bbox[2], bbox[3]);
3044 (*outputFunc)(outputStream, buf, strlen(buf));
3045 (*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
3046 (*outputFunc)(outputStream, "/sfnts ", 7);
3047 (*outputFunc)(outputStream, name, strlen(name));
3048 (*outputFunc)(outputStream, "_sfnts def\n", 11);
3049 (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
3050 for (j = 0; j < 256 && i+j < n; ++j) {
3051 sprintf(buf, "dup %d /c%02x put\n", j, j);
3052 (*outputFunc)(outputStream, buf, strlen(buf));
3053 }
3054 (*outputFunc)(outputStream, "readonly def\n", 13);
3055 (*outputFunc)(outputStream, "/CharStrings 257 dict dup begin\n", 32);
3056 (*outputFunc)(outputStream, "/.notdef 0 def\n", 15);
3057 for (j = 0; j < 256 && i+j < n; ++j) {
3058 sprintf(buf, "/c%02x %d def\n", j, cidMap ? cidMap[i+j] : i+j);
3059 (*outputFunc)(outputStream, buf, strlen(buf));
3060 }
3061 (*outputFunc)(outputStream, "end readonly def\n", 17);
3062 (*outputFunc)(outputStream,
3063 "FontName currentdict end definefont pop\n", 40);
3064 }
3065
3066 // write the Type 0 parent font
3067 (*outputFunc)(outputStream, "16 dict begin\n", 14);
3068 (*outputFunc)(outputStream, "/FontName /", 11);
3069 (*outputFunc)(outputStream, name, strlen(name));
3070 (*outputFunc)(outputStream, " def\n", 5);
3071 (*outputFunc)(outputStream, "/FontType 0 def\n", 16);
3072 (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
3073 (*outputFunc)(outputStream, "/FMapType 2 def\n", 16);
3074 (*outputFunc)(outputStream, "/Encoding [\n", 12);
3075 for (i = 0; i < n; i += 256) {
3076 sprintf(buf, "%d\n", i >> 8);
3077 (*outputFunc)(outputStream, buf, strlen(buf));
3078 }
3079 (*outputFunc)(outputStream, "] def\n", 6);
3080 (*outputFunc)(outputStream, "/FDepVector [\n", 14);
3081 for (i = 0; i < n; i += 256) {
3082 (*outputFunc)(outputStream, "/", 1);
3083 (*outputFunc)(outputStream, name, strlen(name));
3084 sprintf(buf, "_%02x findfont\n", i >> 8);
3085 (*outputFunc)(outputStream, buf, strlen(buf));
3086 }
3087 (*outputFunc)(outputStream, "] def\n", 6);
3088 (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
3089}
3090
3091int TrueTypeFontFile::getByte(int pos) {
3092 if (pos < 0 || pos >= len) {
3093 return 0;
3094 }
3095 return file[pos] & 0xff;
3096}
3097
3098int TrueTypeFontFile::getChar(int pos) {
3099 int x;
3100
3101 if (pos < 0 || pos >= len) {
3102 return 0;
3103 }
3104 x = file[pos] & 0xff;
3105 if (x & 0x80)
3106 x |= 0xffffff00;
3107 return x;
3108}
3109
3110int TrueTypeFontFile::getUShort(int pos) {
3111 int x;
3112
3113 if (pos < 0 || pos+1 >= len) {
3114 return 0;
3115 }
3116 x = file[pos] & 0xff;
3117 x = (x << 8) + (file[pos+1] & 0xff);
3118 return x;
3119}
3120
3121int TrueTypeFontFile::getShort(int pos) {
3122 int x;
3123
3124 if (pos < 0 || pos+1 >= len) {
3125 return 0;
3126 }
3127 x = file[pos] & 0xff;
3128 x = (x << 8) + (file[pos+1] & 0xff);
3129 if (x & 0x8000)
3130 x |= 0xffff0000;
3131 return x;
3132}
3133
3134Guint TrueTypeFontFile::getULong(int pos) {
3135 int x;
3136
3137 if (pos < 0 || pos+3 >= len) {
3138 return 0;
3139 }
3140 x = file[pos] & 0xff;
3141 x = (x << 8) + (file[pos+1] & 0xff);
3142 x = (x << 8) + (file[pos+2] & 0xff);
3143 x = (x << 8) + (file[pos+3] & 0xff);
3144 return x;
3145}
3146
3147double TrueTypeFontFile::getFixed(int pos) {
3148 int x, y;
3149
3150 x = getShort(pos);
3151 y = getUShort(pos+2);
3152 return (double)x + (double)y / 65536;
3153}
3154
3155int TrueTypeFontFile::seekTable(const char *tag) {
3156 int i;
3157
3158 for (i = 0; i < nTables; ++i) {
3159 if (!strncmp(tableHdrs[i].tag, tag, 4)) {
3160 return tableHdrs[i].offset;
3161 }
3162 }
3163 return -1;
3164}
3165
3166int TrueTypeFontFile::seekTableIdx(const char *tag) {
3167 int i;
3168
3169 for (i = 0; i < nTables; ++i) {
3170 if (!strncmp(tableHdrs[i].tag, tag, 4)) {
3171 return i;
3172 }
3173 }
3174 return -1;
3175}
3176
3177void TrueTypeFontFile::cvtEncoding(const char **encodingA, GBool pdfFontHasEncoding,
3178 FontFileOutputFunc outputFunc,
3179 void *outputStream) {
3180 const char *name;
3181 char buf[64];
3182 int i;
3183
3184 (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
3185 if (pdfFontHasEncoding) {
3186 for (i = 0; i < 256; ++i) {
3187 if (!(name = encodingA[i])) {
3188 name = ".notdef";
3189 }
3190 sprintf(buf, "dup %d /", i);
3191 (*outputFunc)(outputStream, buf, strlen(buf));
3192 (*outputFunc)(outputStream, name, strlen(name));
3193 (*outputFunc)(outputStream, " put\n", 5);
3194 }
3195 } else {
3196 for (i = 0; i < 256; ++i) {
3197 sprintf(buf, "dup %d /c%02x put\n", i, i);
3198 (*outputFunc)(outputStream, buf, strlen(buf));
3199 }
3200 }
3201 (*outputFunc)(outputStream, "readonly def\n", 13);
3202}
3203
3204void TrueTypeFontFile::cvtCharStrings(const char **encodingA,
3205 CharCodeToUnicode *toUnicode,
3206 GBool pdfFontHasEncoding,
3207 FontFileOutputFunc outputFunc,
3208 void *outputStream) {
3209 int unicodeCmap, macRomanCmap, msSymbolCmap;
3210 int nCmaps, cmapPlatform, cmapEncoding, cmapFmt, cmapOffset;
3211 T42FontIndexMode mode;
3212 const char *name;
3213 char buf[64], buf2[16];
3214 Unicode u;
3215 int pos, i, j, k;
3216
3217 // always define '.notdef'
3218 (*outputFunc)(outputStream, "/CharStrings 256 dict dup begin\n", 32);
3219 (*outputFunc)(outputStream, "/.notdef 0 def\n", 15);
3220
3221 // if there's no 'cmap' table, punt
3222 if ((pos = seekTable("cmap")) < 0) {
3223 goto err;
3224 }
3225
3226 // To match up with the Adobe-defined behaviour, we choose a cmap
3227 // like this:
3228 // 1. If the PDF font has an encoding:
3229 // 1a. If the TrueType font has a Microsoft Unicode cmap, use it,
3230 // and use the Unicode indexes, not the char codes.
3231 // 1b. If the TrueType font has a Macintosh Roman cmap, use it,
3232 // and reverse map the char names through MacRomanEncoding to
3233 // get char codes.
3234 // 2. If the PDF font does not have an encoding:
3235 // 2a. If the TrueType font has a Macintosh Roman cmap, use it,
3236 // and use char codes directly.
3237 // 2b. If the TrueType font has a Microsoft Symbol cmap, use it,
3238 // and use (0xf000 + char code).
3239 // 3. If none of these rules apply, use the first cmap and hope for
3240 // the best (this shouldn't happen).
3241 nCmaps = getUShort(pos+2);
3242 unicodeCmap = macRomanCmap = msSymbolCmap = -1;
3243 cmapOffset = 0;
3244 for (i = 0; i < nCmaps; ++i) {
3245 cmapPlatform = getUShort(pos + 4 + 8*i);
3246 cmapEncoding = getUShort(pos + 4 + 8*i + 2);
3247 if (cmapPlatform == 3 && cmapEncoding == 1) {
3248 unicodeCmap = i;
3249 } else if (cmapPlatform == 1 && cmapEncoding == 0) {
3250 macRomanCmap = i;
3251 } else if (cmapPlatform == 3 && cmapEncoding == 0) {
3252 msSymbolCmap = i;
3253 }
3254 }
3255 i = 0;
3256 mode = t42FontModeCharCode;
3257 if (pdfFontHasEncoding) {
3258 if (unicodeCmap >= 0) {
3259 i = unicodeCmap;
3260 mode = t42FontModeUnicode;
3261 } else if (macRomanCmap >= 0) {
3262 i = macRomanCmap;
3263 mode = t42FontModeMacRoman;
3264 }
3265 } else {
3266 if (macRomanCmap >= 0) {
3267 i = macRomanCmap;
3268 mode = t42FontModeCharCode;
3269 } else if (msSymbolCmap >= 0) {
3270 i = msSymbolCmap;
3271 mode = t42FontModeCharCodeOffset;
3272 cmapOffset = 0xf000;
3273 }
3274 }
3275 cmapPlatform = getUShort(pos + 4 + 8*i);
3276 cmapEncoding = getUShort(pos + 4 + 8*i + 2);
3277 pos += getULong(pos + 4 + 8*i + 4);
3278 cmapFmt = getUShort(pos);
3279 if (cmapFmt != 0 && cmapFmt != 4 && cmapFmt != 6) {
3280 error(-1, "Unimplemented cmap format (%d) in TrueType font file",
3281 cmapFmt);
3282 goto err;
3283 }
3284
3285 // map char name to glyph index:
3286 // 1. use encoding to map name to char code
3287 // 2. use cmap to map char code to glyph index
3288 j = 0; // make gcc happy
3289 for (i = 0; i < 256; ++i) {
3290 if (pdfFontHasEncoding) {
3291 name = encodingA[i];
3292 } else {
3293 sprintf(buf2, "c%02x", i);
3294 name = buf2;
3295 }
3296 if (name && strcmp(name, ".notdef")) {
3297 switch (mode) {
3298 case t42FontModeUnicode:
3299 toUnicode->mapToUnicode((CharCode)i, &u, 1);
3300 j = (int)u;
3301 break;
3302 case t42FontModeCharCode:
3303 j = i;
3304 break;
3305 case t42FontModeCharCodeOffset:
3306 j = cmapOffset + i;
3307 break;
3308 case t42FontModeMacRoman:
3309 j = globalParams->getMacRomanCharCode(name);
3310 break;
3311 }
3312 // note: Distiller (maybe Adobe's PS interpreter in general)
3313 // doesn't like TrueType fonts that have CharStrings entries
3314 // which point to nonexistent glyphs, hence the (k < nGlyphs)
3315 // test
3316 if ((k = getCmapEntry(cmapFmt, pos, j)) > 0 &&
3317 k < nGlyphs) {
3318 (*outputFunc)(outputStream, "/", 1);
3319 (*outputFunc)(outputStream, name, strlen(name));
3320 sprintf(buf, " %d def\n", k);
3321 (*outputFunc)(outputStream, buf, strlen(buf));
3322 }
3323 }
3324 }
3325
3326 err:
3327 (*outputFunc)(outputStream, "end readonly def\n", 17);
3328}
3329
3330int TrueTypeFontFile::getCmapEntry(int cmapFmt, int pos, int code) {
3331 int cmapLen, cmapFirst;
3332 int segCnt, segEnd, segStart, segDelta, segOffset;
3333 int a, b, m, i;
3334
3335 switch (cmapFmt) {
3336 case 0: // byte encoding table (Apple standard)
3337 cmapLen = getUShort(pos + 2);
3338 if (code >= cmapLen) {
3339 return 0;
3340 }
3341 return getByte(pos + 6 + code);
3342
3343 case 4: // segment mapping to delta values (Microsoft standard)
3344 segCnt = getUShort(pos + 6) / 2;
3345 a = -1;
3346 b = segCnt - 1;
3347 segEnd = getUShort(pos + 14 + 2*b);
3348 if (code > segEnd) {
3349 // malformed font -- the TrueType spec requires the last segEnd
3350 // to be 0xffff
3351 return 0;
3352 }
3353 // invariant: seg[a].end < code <= seg[b].end
3354 while (b - a > 1) {
3355 m = (a + b) / 2;
3356 segEnd = getUShort(pos + 14 + 2*m);
3357 if (segEnd < code) {
3358 a = m;
3359 } else {
3360 b = m;
3361 }
3362 }
3363 segStart = getUShort(pos + 16 + 2*segCnt + 2*b);
3364 segDelta = getUShort(pos + 16 + 4*segCnt + 2*b);
3365 segOffset = getUShort(pos + 16 + 6*segCnt + 2*b);
3366 if (segOffset == 0) {
3367 i = (code + segDelta) & 0xffff;
3368 } else {
3369 i = getUShort(pos + 16 + 6*segCnt + 2*b +
3370 segOffset + 2 * (code - segStart));
3371 if (i != 0) {
3372 i = (i + segDelta) & 0xffff;
3373 }
3374 }
3375 return i;
3376
3377 case 6: // trimmed table mapping
3378 cmapFirst = getUShort(pos + 6);
3379 cmapLen = getUShort(pos + 8);
3380 if (code < cmapFirst || code >= cmapFirst + cmapLen) {
3381 return 0;
3382 }
3383 return getUShort(pos + 10 + 2*(code - cmapFirst));
3384
3385 default:
3386 // shouldn't happen - this is checked earlier
3387 break;
3388 }
3389 return 0;
3390}
3391
3392void TrueTypeFontFile::cvtSfnts(FontFileOutputFunc outputFunc,
3393 void *outputStream, GString *name) {
3394 TTFontTableHdr newTableHdrs[nT42Tables];
3395 char tableDir[12 + nT42Tables*16];
3396 char headTable[54];
3397 int *origLocaTable;
3398 char *locaTable;
3399 int nNewTables;
3400 Guint checksum;
3401 int pos, glyfPos, length, glyphLength, pad;
3402 int i, j, k;
3403
3404 // construct the 'head' table, zero out the font checksum
3405 memcpy(headTable, file + seekTable("head"), 54);
3406 headTable[8] = headTable[9] = headTable[10] = headTable[11] = (char)0;
3407
3408 // read the original 'loca' table and construct the new one
3409 // (pad each glyph out to a multiple of 4 bytes)
3410 origLocaTable = (int *)gmalloc((nGlyphs + 1) * sizeof(int));
3411 pos = seekTable("loca");
3412 for (i = 0; i <= nGlyphs; ++i) {
3413 if (locaFmt) {
3414 origLocaTable[i] = getULong(pos + 4*i);
3415 } else {
3416 origLocaTable[i] = 2 * getUShort(pos + 2*i);
3417 }
3418 }
3419 locaTable = (char *)gmalloc((nGlyphs + 1) * (locaFmt ? 4 : 2));
3420 if (locaFmt) {
3421 locaTable[0] = locaTable[1] = locaTable[2] = locaTable[3] = 0;
3422 } else {
3423 locaTable[0] = locaTable[1] = 0;
3424 }
3425 pos = 0;
3426 for (i = 1; i <= nGlyphs; ++i) {
3427 length = origLocaTable[i] - origLocaTable[i-1];
3428 if (length & 3) {
3429 length += 4 - (length & 3);
3430 }
3431 pos += length;
3432 if (locaFmt) {
3433 locaTable[4*i ] = (char)(pos >> 24);
3434 locaTable[4*i+1] = (char)(pos >> 16);
3435 locaTable[4*i+2] = (char)(pos >> 8);
3436 locaTable[4*i+3] = (char) pos;
3437 } else {
3438 locaTable[2*i ] = (char)(pos >> 9);
3439 locaTable[2*i+1] = (char)(pos >> 1);
3440 }
3441 }
3442
3443 // count the number of tables
3444 nNewTables = 0;
3445 for (i = 0; i < nT42Tables; ++i) {
3446 if (t42Tables[i].required ||
3447 seekTable(t42Tables[i].tag) >= 0) {
3448 ++nNewTables;
3449 }
3450 }
3451
3452 // construct the new table headers, including table checksums
3453 // (pad each table out to a multiple of 4 bytes)
3454 pos = 12 + nNewTables*16;
3455 k = 0;
3456 for (i = 0; i < nT42Tables; ++i) {
3457 length = -1;
3458 checksum = 0; // make gcc happy
3459 if (i == t42HeadTable) {
3460 length = 54;
3461 checksum = computeTableChecksum(headTable, 54);
3462 } else if (i == t42LocaTable) {
3463 length = (nGlyphs + 1) * (locaFmt ? 4 : 2);
3464 checksum = computeTableChecksum(locaTable, length);
3465 } else if (i == t42GlyfTable) {
3466 length = 0;
3467 checksum = 0;
3468 glyfPos = seekTable("glyf");
3469 for (j = 0; j < nGlyphs; ++j) {
3470 glyphLength = origLocaTable[j+1] - origLocaTable[j];
3471 pad = (glyphLength & 3) ? 4 - (glyphLength & 3) : 0;
3472 length += glyphLength + pad;
3473 checksum += computeTableChecksum(file + glyfPos + origLocaTable[j],
3474 glyphLength);
3475 }
3476 } else {
3477 if ((j = seekTableIdx(t42Tables[i].tag)) >= 0) {
3478 length = tableHdrs[j].length;
3479 checksum = computeTableChecksum(file + tableHdrs[j].offset, length);
3480 } else if (t42Tables[i].required) {
3481 error(-1, "Embedded TrueType font is missing a required table ('%s')",
3482 t42Tables[i].tag);
3483 length = 0;
3484 checksum = 0;
3485 }
3486 }
3487 if (length >= 0) {
3488 strncpy(newTableHdrs[k].tag, t42Tables[i].tag, 4);
3489 newTableHdrs[k].checksum = checksum;
3490 newTableHdrs[k].offset = pos;
3491 newTableHdrs[k].length = length;
3492 pad = (length & 3) ? 4 - (length & 3) : 0;
3493 pos += length + pad;
3494 ++k;
3495 }
3496 }
3497
3498 // construct the table directory
3499 tableDir[0] = 0x00; // sfnt version
3500 tableDir[1] = 0x01;
3501 tableDir[2] = 0x00;
3502 tableDir[3] = 0x00;
3503 tableDir[4] = 0; // numTables
3504 tableDir[5] = nNewTables;
3505 tableDir[6] = 0; // searchRange
3506 tableDir[7] = (char)128;
3507 tableDir[8] = 0; // entrySelector
3508 tableDir[9] = 3;
3509 tableDir[10] = 0; // rangeShift
3510 tableDir[11] = (char)(16 * nNewTables - 128);
3511 pos = 12;
3512 for (i = 0; i < nNewTables; ++i) {
3513 tableDir[pos ] = newTableHdrs[i].tag[0];
3514 tableDir[pos+ 1] = newTableHdrs[i].tag[1];
3515 tableDir[pos+ 2] = newTableHdrs[i].tag[2];
3516 tableDir[pos+ 3] = newTableHdrs[i].tag[3];
3517 tableDir[pos+ 4] = (char)(newTableHdrs[i].checksum >> 24);
3518 tableDir[pos+ 5] = (char)(newTableHdrs[i].checksum >> 16);
3519 tableDir[pos+ 6] = (char)(newTableHdrs[i].checksum >> 8);
3520 tableDir[pos+ 7] = (char) newTableHdrs[i].checksum;
3521 tableDir[pos+ 8] = (char)(newTableHdrs[i].offset >> 24);
3522 tableDir[pos+ 9] = (char)(newTableHdrs[i].offset >> 16);
3523 tableDir[pos+10] = (char)(newTableHdrs[i].offset >> 8);
3524 tableDir[pos+11] = (char) newTableHdrs[i].offset;
3525 tableDir[pos+12] = (char)(newTableHdrs[i].length >> 24);
3526 tableDir[pos+13] = (char)(newTableHdrs[i].length >> 16);
3527 tableDir[pos+14] = (char)(newTableHdrs[i].length >> 8);
3528 tableDir[pos+15] = (char) newTableHdrs[i].length;
3529 pos += 16;
3530 }
3531
3532 // compute the font checksum and store it in the head table
3533 checksum = computeTableChecksum(tableDir, 12 + nNewTables*16);
3534 for (i = 0; i < nNewTables; ++i) {
3535 checksum += newTableHdrs[i].checksum;
3536 }
3537 checksum = 0xb1b0afba - checksum; // because the TrueType spec says so
3538 headTable[ 8] = (char)(checksum >> 24);
3539 headTable[ 9] = (char)(checksum >> 16);
3540 headTable[10] = (char)(checksum >> 8);
3541 headTable[11] = (char) checksum;
3542
3543 // start the sfnts array
3544 if (name) {
3545 (*outputFunc)(outputStream, "/", 1);
3546 (*outputFunc)(outputStream, name->getCString(), name->getLength());
3547 (*outputFunc)(outputStream, " [\n", 3);
3548 } else {
3549 (*outputFunc)(outputStream, "/sfnts [\n", 9);
3550 }
3551
3552 // write the table directory
3553 dumpString(tableDir, 12 + nNewTables*16, outputFunc, outputStream);
3554
3555 // write the tables
3556 for (i = 0; i < nNewTables; ++i) {
3557 if (i == t42HeadTable) {
3558 dumpString(headTable, 54, outputFunc, outputStream);
3559 } else if (i == t42LocaTable) {
3560 length = (nGlyphs + 1) * (locaFmt ? 4 : 2);
3561 dumpString(locaTable, length, outputFunc, outputStream);
3562 } else if (i == t42GlyfTable) {
3563 glyfPos = seekTable("glyf");
3564 for (j = 0; j < nGlyphs; ++j) {
3565 length = origLocaTable[j+1] - origLocaTable[j];
3566 if (length > 0) {
3567 dumpString(file + glyfPos + origLocaTable[j], length,
3568 outputFunc, outputStream);
3569 }
3570 }
3571 } else {
3572 // length == 0 means the table is missing and the error was
3573 // already reported during the construction of the table
3574 // headers
3575 if ((length = newTableHdrs[i].length) > 0) {
3576 dumpString(file + seekTable(t42Tables[i].tag), length,
3577 outputFunc, outputStream);
3578 }
3579 }
3580 }
3581
3582 // end the sfnts array
3583 (*outputFunc)(outputStream, "] def\n", 6);
3584
3585 gfree(origLocaTable);
3586 gfree(locaTable);
3587}
3588
3589void TrueTypeFontFile::dumpString(const char *s, int length,
3590 FontFileOutputFunc outputFunc,
3591 void *outputStream) {
3592 char buf[64];
3593 int pad, i, j;
3594
3595 (*outputFunc)(outputStream, "<", 1);
3596 for (i = 0; i < length; i += 32) {
3597 for (j = 0; j < 32 && i+j < length; ++j) {
3598 sprintf(buf, "%02X", s[i+j] & 0xff);
3599 (*outputFunc)(outputStream, buf, strlen(buf));
3600 }
3601 if (i % (65536 - 32) == 65536 - 64) {
3602 (*outputFunc)(outputStream, ">\n<", 3);
3603 } else if (i+32 < length) {
3604 (*outputFunc)(outputStream, "\n", 1);
3605 }
3606 }
3607 if (length & 3) {
3608 pad = 4 - (length & 3);
3609 for (i = 0; i < pad; ++i) {
3610 (*outputFunc)(outputStream, "00", 2);
3611 }
3612 }
3613 // add an extra zero byte because the Adobe Type 42 spec says so
3614 (*outputFunc)(outputStream, "00>\n", 4);
3615}
3616
3617Guint TrueTypeFontFile::computeTableChecksum(const char *data, int length) {
3618 Guint checksum, word;
3619 int i;
3620
3621 checksum = 0;
3622 for (i = 0; i+3 < length; i += 4) {
3623 word = ((data[i ] & 0xff) << 24) +
3624 ((data[i+1] & 0xff) << 16) +
3625 ((data[i+2] & 0xff) << 8) +
3626 (data[i+3] & 0xff);
3627 checksum += word;
3628 }
3629 if (length & 3) {
3630 word = 0;
3631 i = length & ~3;
3632 switch (length & 3) {
3633 case 3:
3634 word |= (data[i+2] & 0xff) << 8;
3635 case 2:
3636 word |= (data[i+1] & 0xff) << 16;
3637 case 1:
3638 word |= (data[i ] & 0xff) << 24;
3639 break;
3640 }
3641 checksum += word;
3642 }
3643 return checksum;
3644}
3645
3646void TrueTypeFontFile::writeTTF(FILE *out) {
3647 static char cmapTab[20] = {
3648 0, 0, // table version number
3649 0, 1, // number of encoding tables
3650 0, 1, // platform ID
3651 0, 0, // encoding ID
3652 0, 0, 0, 12, // offset of subtable
3653 0, 0, // subtable format
3654 0, 1, // subtable length
3655 0, 1, // subtable version
3656 0, // map char 0 -> glyph 0
3657 0 // pad to multiple of four bytes
3658 };
3659 static char nameTab[8] = {
3660 0, 0, // format
3661 0, 0, // number of name records
3662 0, 6, // offset to start of string storage
3663 0, 0 // pad to multiple of four bytes
3664 };
3665 static char postTab[32] = {
3666 0, 1, 0, 0, // format
3667 0, 0, 0, 0, // italic angle
3668 0, 0, // underline position
3669 0, 0, // underline thickness
3670 0, 0, 0, 0, // fixed pitch
3671 0, 0, 0, 0, // min Type 42 memory
3672 0, 0, 0, 0, // max Type 42 memory
3673 0, 0, 0, 0, // min Type 1 memory
3674 0, 0, 0, 0 // max Type 1 memory
3675 };
3676 GBool haveCmap, haveName, havePost;
3677 GBool dirCmap, dirName, dirPost;
3678 int nNewTables, nAllTables, pad;
3679 char *tableDir;
3680 Guint t, pos;
3681 int i, j;
3682
3683 // check for missing tables
3684 haveCmap = seekTable("cmap") >= 0;
3685 haveName = seekTable("name") >= 0;
3686 havePost = seekTable("post") >= 0;
3687 nNewTables = (haveCmap ? 0 : 1) + (haveName ? 0 : 1) + (havePost ? 0 : 1);
3688 if (!nNewTables && !mungedCmapSize) {
3689 // none are missing - write the TTF file as is
3690 fwrite(file, 1, len, out);
3691 return;
3692 }
3693
3694 // construct the new table directory
3695 nAllTables = nTables + nNewTables;
3696 tableDir = (char *)gmalloc(12 + nAllTables * 16);
3697 memcpy(tableDir, file, 12 + nTables * 16);
3698 tableDir[4] = (char)((nAllTables >> 8) & 0xff);
3699 tableDir[5] = (char)(nAllTables & 0xff);
3700 for (i = -1, t = (Guint)nAllTables; t; ++i, t >>= 1) ;
3701 t = 1 << (4 + i);
3702 tableDir[6] = (char)((t >> 8) & 0xff);
3703 tableDir[7] = (char)(t & 0xff);
3704 tableDir[8] = (char)((i >> 8) & 0xff);
3705 tableDir[9] = (char)(i & 0xff);
3706 t = nAllTables * 16 - t;
3707 tableDir[10] = (char)((t >> 8) & 0xff);
3708 tableDir[11] = (char)(t & 0xff);
3709 dirCmap = haveCmap;
3710 dirName = haveName;
3711 dirPost = havePost;
3712 j = 0;
3713 pad = (len & 3) ? 4 - (len & 3) : 0;
3714 pos = len + pad + 16 * nNewTables;
3715 for (i = 0; i < nTables; ++i) {
3716 if (!dirCmap && strncmp(tableHdrs[i].tag, "cmap", 4) > 0) {
3717 tableDir[12 + 16*j ] = 'c';
3718 tableDir[12 + 16*j + 1] = 'm';
3719 tableDir[12 + 16*j + 2] = 'a';
3720 tableDir[12 + 16*j + 3] = 'p';
3721 tableDir[12 + 16*j + 4] = (char)0; //~ should compute the checksum
3722 tableDir[12 + 16*j + 5] = (char)0;
3723 tableDir[12 + 16*j + 6] = (char)0;
3724 tableDir[12 + 16*j + 7] = (char)0;
3725 tableDir[12 + 16*j + 8] = (char)((pos >> 24) & 0xff);
3726 tableDir[12 + 16*j + 9] = (char)((pos >> 16) & 0xff);
3727 tableDir[12 + 16*j + 10] = (char)((pos >> 8) & 0xff);
3728 tableDir[12 + 16*j + 11] = (char)( pos & 0xff);
3729 tableDir[12 + 16*j + 12] = (char)((sizeof(cmapTab) >> 24) & 0xff);
3730 tableDir[12 + 16*j + 13] = (char)((sizeof(cmapTab) >> 16) & 0xff);
3731 tableDir[12 + 16*j + 14] = (char)((sizeof(cmapTab) >> 8) & 0xff);
3732 tableDir[12 + 16*j + 15] = (char)( sizeof(cmapTab) & 0xff);
3733 pos += sizeof(cmapTab);
3734 ++j;
3735 dirCmap = gTrue;
3736 }
3737 if (!dirName && strncmp(tableHdrs[i].tag, "name", 4) > 0) {
3738 tableDir[12 + 16*j ] = 'n';
3739 tableDir[12 + 16*j + 1] = 'a';
3740 tableDir[12 + 16*j + 2] = 'm';
3741 tableDir[12 + 16*j + 3] = 'e';
3742 tableDir[12 + 16*j + 4] = (char)0; //~ should compute the checksum
3743 tableDir[12 + 16*j + 5] = (char)0;
3744 tableDir[12 + 16*j + 6] = (char)0;
3745 tableDir[12 + 16*j + 7] = (char)0;
3746 tableDir[12 + 16*j + 8] = (char)((pos >> 24) & 0xff);
3747 tableDir[12 + 16*j + 9] = (char)((pos >> 16) & 0xff);
3748 tableDir[12 + 16*j + 10] = (char)((pos >> 8) & 0xff);
3749 tableDir[12 + 16*j + 11] = (char)( pos & 0xff);
3750 tableDir[12 + 16*j + 12] = (char)((sizeof(nameTab) >> 24) & 0xff);
3751 tableDir[12 + 16*j + 13] = (char)((sizeof(nameTab) >> 16) & 0xff);
3752 tableDir[12 + 16*j + 14] = (char)((sizeof(nameTab) >> 8) & 0xff);
3753 tableDir[12 + 16*j + 15] = (char)( sizeof(nameTab) & 0xff);
3754 pos += sizeof(nameTab);
3755 ++j;
3756 dirName = gTrue;
3757 }
3758 if (!dirName && strncmp(tableHdrs[i].tag, "post", 4) > 0) {
3759 tableDir[12 + 16*j ] = 'p';
3760 tableDir[12 + 16*j + 1] = 'o';
3761 tableDir[12 + 16*j + 2] = 's';
3762 tableDir[12 + 16*j + 3] = 't';
3763 tableDir[12 + 16*j + 4] = (char)0; //~ should compute the checksum
3764 tableDir[12 + 16*j + 5] = (char)0;
3765 tableDir[12 + 16*j + 6] = (char)0;
3766 tableDir[12 + 16*j + 7] = (char)0;
3767 tableDir[12 + 16*j + 8] = (char)((pos >> 24) & 0xff);
3768 tableDir[12 + 16*j + 9] = (char)((pos >> 16) & 0xff);
3769 tableDir[12 + 16*j + 10] = (char)((pos >> 8) & 0xff);
3770 tableDir[12 + 16*j + 11] = (char)( pos & 0xff);
3771 tableDir[12 + 16*j + 12] = (char)((sizeof(postTab) >> 24) & 0xff);
3772 tableDir[12 + 16*j + 13] = (char)((sizeof(postTab) >> 16) & 0xff);
3773 tableDir[12 + 16*j + 14] = (char)((sizeof(postTab) >> 8) & 0xff);
3774 tableDir[12 + 16*j + 15] = (char)( sizeof(postTab) & 0xff);
3775 pos += sizeof(postTab);
3776 ++j;
3777 dirPost = gTrue;
3778 }
3779 tableDir[12 + 16*j ] = tableHdrs[i].tag[0];
3780 tableDir[12 + 16*j + 1] = tableHdrs[i].tag[1];
3781 tableDir[12 + 16*j + 2] = tableHdrs[i].tag[2];
3782 tableDir[12 + 16*j + 3] = tableHdrs[i].tag[3];
3783 tableDir[12 + 16*j + 4] = (char)((tableHdrs[i].checksum >> 24) & 0xff);
3784 tableDir[12 + 16*j + 5] = (char)((tableHdrs[i].checksum >> 16) & 0xff);
3785 tableDir[12 + 16*j + 6] = (char)((tableHdrs[i].checksum >> 8) & 0xff);
3786 tableDir[12 + 16*j + 7] = (char)( tableHdrs[i].checksum & 0xff);
3787 t = tableHdrs[i].offset + nNewTables * 16;
3788 tableDir[12 + 16*j + 8] = (char)((t >> 24) & 0xff);
3789 tableDir[12 + 16*j + 9] = (char)((t >> 16) & 0xff);
3790 tableDir[12 + 16*j + 10] = (char)((t >> 8) & 0xff);
3791 tableDir[12 + 16*j + 11] = (char)( t & 0xff);
3792 tableDir[12 + 16*j + 12] = (char)((tableHdrs[i].length >> 24) & 0xff);
3793 tableDir[12 + 16*j + 13] = (char)((tableHdrs[i].length >> 16) & 0xff);
3794 tableDir[12 + 16*j + 14] = (char)((tableHdrs[i].length >> 8) & 0xff);
3795 tableDir[12 + 16*j + 15] = (char)( tableHdrs[i].length & 0xff);
3796 ++j;
3797 }
3798 if (!dirCmap) {
3799 tableDir[12 + 16*j ] = 'c';
3800 tableDir[12 + 16*j + 1] = 'm';
3801 tableDir[12 + 16*j + 2] = 'a';
3802 tableDir[12 + 16*j + 3] = 'p';
3803 tableDir[12 + 16*j + 4] = (char)0; //~ should compute the checksum
3804 tableDir[12 + 16*j + 5] = (char)0;
3805 tableDir[12 + 16*j + 6] = (char)0;
3806 tableDir[12 + 16*j + 7] = (char)0;
3807 tableDir[12 + 16*j + 8] = (char)((pos >> 24) & 0xff);
3808 tableDir[12 + 16*j + 9] = (char)((pos >> 16) & 0xff);
3809 tableDir[12 + 16*j + 10] = (char)((pos >> 8) & 0xff);
3810 tableDir[12 + 16*j + 11] = (char)( pos & 0xff);
3811 tableDir[12 + 16*j + 12] = (char)((sizeof(cmapTab) >> 24) & 0xff);
3812 tableDir[12 + 16*j + 13] = (char)((sizeof(cmapTab) >> 16) & 0xff);
3813 tableDir[12 + 16*j + 14] = (char)((sizeof(cmapTab) >> 8) & 0xff);
3814 tableDir[12 + 16*j + 15] = (char)( sizeof(cmapTab) & 0xff);
3815 pos += sizeof(cmapTab);
3816 ++j;
3817 dirCmap = gTrue;
3818 }
3819 if (!dirName) {
3820 tableDir[12 + 16*j ] = 'n';
3821 tableDir[12 + 16*j + 1] = 'a';
3822 tableDir[12 + 16*j + 2] = 'm';
3823 tableDir[12 + 16*j + 3] = 'e';
3824 tableDir[12 + 16*j + 4] = (char)0; //~ should compute the checksum
3825 tableDir[12 + 16*j + 5] = (char)0;
3826 tableDir[12 + 16*j + 6] = (char)0;
3827 tableDir[12 + 16*j + 7] = (char)0;
3828 tableDir[12 + 16*j + 8] = (char)((pos >> 24) & 0xff);
3829 tableDir[12 + 16*j + 9] = (char)((pos >> 16) & 0xff);
3830 tableDir[12 + 16*j + 10] = (char)((pos >> 8) & 0xff);
3831 tableDir[12 + 16*j + 11] = (char)( pos & 0xff);
3832 tableDir[12 + 16*j + 12] = (char)((sizeof(nameTab) >> 24) & 0xff);
3833 tableDir[12 + 16*j + 13] = (char)((sizeof(nameTab) >> 16) & 0xff);
3834 tableDir[12 + 16*j + 14] = (char)((sizeof(nameTab) >> 8) & 0xff);
3835 tableDir[12 + 16*j + 15] = (char)( sizeof(nameTab) & 0xff);
3836 pos += sizeof(nameTab);
3837 ++j;
3838 dirName = gTrue;
3839 }
3840 if (!dirPost) {
3841 tableDir[12 + 16*j ] = 'p';
3842 tableDir[12 + 16*j + 1] = 'o';
3843 tableDir[12 + 16*j + 2] = 's';
3844 tableDir[12 + 16*j + 3] = 't';
3845 tableDir[12 + 16*j + 4] = (char)0; //~ should compute the checksum
3846 tableDir[12 + 16*j + 5] = (char)0;
3847 tableDir[12 + 16*j + 6] = (char)0;
3848 tableDir[12 + 16*j + 7] = (char)0;
3849 tableDir[12 + 16*j + 8] = (char)((pos >> 24) & 0xff);
3850 tableDir[12 + 16*j + 9] = (char)((pos >> 16) & 0xff);
3851 tableDir[12 + 16*j + 10] = (char)((pos >> 8) & 0xff);
3852 tableDir[12 + 16*j + 11] = (char)( pos & 0xff);
3853 tableDir[12 + 16*j + 12] = (char)((sizeof(postTab) >> 24) & 0xff);
3854 tableDir[12 + 16*j + 13] = (char)((sizeof(postTab) >> 16) & 0xff);
3855 tableDir[12 + 16*j + 14] = (char)((sizeof(postTab) >> 8) & 0xff);
3856 tableDir[12 + 16*j + 15] = (char)( sizeof(postTab) & 0xff);
3857 pos += sizeof(postTab);
3858 ++j;
3859 dirPost = gTrue;
3860 }
3861
3862 // write the table directory
3863 fwrite(tableDir, 1, 12 + 16 * nAllTables, out);
3864
3865 // write the original tables
3866 fwrite(file + 12 + 16*nTables, 1, len - (12 + 16*nTables), out);
3867
3868 // write the new tables
3869 for (i = 0; i < pad; ++i) {
3870 fputc((char)0, out);
3871 }
3872 if (!haveCmap) {
3873 fwrite(cmapTab, 1, sizeof(cmapTab), out);
3874 }
3875 if (!haveName) {
3876 fwrite(nameTab, 1, sizeof(nameTab), out);
3877 }
3878 if (!havePost) {
3879 fwrite(postTab, 1, sizeof(postTab), out);
3880 }
3881
3882 gfree(tableDir);
3883}