1 //========================================================================
5 // Copyright 1999-2002 Glyph & Cog, LLC
7 //========================================================================
10 #pragma implementation
22 #include "GlobalParams.h"
23 #include "CharCodeToUnicode.h"
24 #include "FontEncodingTables.h"
27 #include "CompactFontTables.h"
29 //------------------------------------------------------------------------
31 static inline char *nextLine(char *line, char *end) {
32 while (line < end && *line != '\n' && *line != '\r')
34 while (line < end && *line == '\n' || *line == '\r')
39 static char hexChars[17] = "0123456789ABCDEF";
41 //------------------------------------------------------------------------
43 //------------------------------------------------------------------------
45 FontFile::FontFile() {
48 FontFile::~FontFile() {
51 //------------------------------------------------------------------------
53 //------------------------------------------------------------------------
55 Type1FontFile::Type1FontFile(char *file, int len) {
56 char *line, *line1, *p, *p2;
63 encoding = (char **)gmalloc(256 * sizeof(char *));
64 for (i = 0; i < 256; ++i) {
67 haveEncoding = gFalse;
69 for (i = 1, line = file;
70 i <= 100 && line < file + len && !haveEncoding;
74 if (!strncmp(line, "/FontName", 9)) {
75 strncpy(buf, line, 255);
77 if ((p = strchr(buf+9, '/')) &&
78 (p = strtok(p+1, " \t\n\r"))) {
81 line = nextLine(line, file + len);
84 } else if (!strncmp(line, "/Encoding StandardEncoding def", 30)) {
85 for (j = 0; j < 256; ++j) {
86 if (standardEncoding[j]) {
87 encoding[j] = copyString(standardEncoding[j]);
91 } else if (!strncmp(line, "/Encoding 256 array", 19)) {
92 for (j = 0; j < 300; ++j) {
93 line1 = nextLine(line, file + len);
94 if ((n = line1 - line) > 255) {
97 strncpy(buf, line, n);
99 for (p = buf; *p == ' ' || *p == '\t'; ++p) ;
100 if (!strncmp(p, "dup", 3)) {
101 for (p += 3; *p == ' ' || *p == '\t'; ++p) ;
102 for (p2 = p; *p2 >= '0' && *p2 <= '9'; ++p2) ;
106 if ((code = atoi(p)) < 256) {
108 for (p = p2; *p == ' ' || *p == '\t'; ++p) ;
111 for (p2 = p; *p2 && *p2 != ' ' && *p2 != '\t'; ++p2) ;
113 encoding[code] = copyString(p);
118 if (strtok(buf, " \t") &&
119 (p = strtok(NULL, " \t\n\r")) && !strcmp(p, "def")) {
125 //~ check for getinterval/putinterval junk
126 haveEncoding = gTrue;
129 line = nextLine(line, file + len);
134 Type1FontFile::~Type1FontFile() {
140 for (i = 0; i < 256; ++i) {
146 //------------------------------------------------------------------------
148 //------------------------------------------------------------------------
150 struct Type1CTopDict {
159 double underlinePosition;
160 double underlineThickness;
163 double fontMatrix[6];
173 //----- CIDFont entries
181 struct Type1CPrivateDict {
184 double defaultWidthX;
185 GBool defaultWidthXFP;
186 double nominalWidthX;
187 GBool nominalWidthXFP;
190 Type1CFontFile::Type1CFontFile(char *fileA, int lenA) {
191 Guchar *nameIdxPtr, *idxPtr0, *idxPtr1;
198 // some tools embed Type 1C fonts with an extra whitespace char at
200 if (file[0] != '\x01') {
205 topOffSize = file[3] & 0xff;
207 // read name index (first font only)
208 nameIdxPtr = (Guchar *)file + (file[2] & 0xff);
209 idxPtr0 = getIndexValPtr(nameIdxPtr, 0);
210 idxPtr1 = getIndexValPtr(nameIdxPtr, 1);
211 name = new GString((char *)idxPtr0, idxPtr1 - idxPtr0);
213 topDictIdxPtr = getIndexEnd(nameIdxPtr);
214 stringIdxPtr = getIndexEnd(topDictIdxPtr);
215 gsubrIdxPtr = getIndexEnd(stringIdxPtr);
218 Type1CFontFile::~Type1CFontFile() {
223 for (i = 0; i < 256; ++i) {
230 char *Type1CFontFile::getName() {
231 return name->getCString();
234 char **Type1CFontFile::getEncoding() {
236 readNameAndEncoding();
241 void Type1CFontFile::readNameAndEncoding() {
243 Guchar *idxPtr0, *idxPtr1, *ptr;
245 int nCodes, nRanges, nLeft, nSups;
247 int charset, enc, charstrings;
255 encoding = (char **)gmalloc(256 * sizeof(char *));
256 for (i = 0; i < 256; ++i) {
260 // read top dict (first font only)
261 idxPtr0 = getIndexValPtr(topDictIdxPtr, 0);
262 idxPtr1 = getIndexValPtr(topDictIdxPtr, 1);
263 charset = enc = charstrings = 0;
266 while (ptr < idxPtr1) {
267 if (*ptr <= 27 || *ptr == 31) {
270 key = (key << 8) | *ptr++;
272 if (key == 0x0f) { // charset
273 charset = (int)op[0];
274 } else if (key == 0x10) { // encoding
276 } else if (key == 0x11) { // charstrings
277 charstrings = (int)op[0];
281 x = getNum(&ptr, &isFP);
288 // get number of glyphs from charstrings index
289 nGlyphs = getIndexLen((Guchar *)file + charstrings);
291 // read charset (GID -> name mapping)
292 glyphNames = readCharset(charset, nGlyphs);
294 // read encoding (GID -> code mapping)
296 for (i = 0; i < 256; ++i) {
297 if (standardEncoding[i]) {
298 encoding[i] = copyString(standardEncoding[i]);
301 } else if (enc == 1) {
302 for (i = 0; i < 256; ++i) {
303 if (expertEncoding[i]) {
304 encoding[i] = copyString(expertEncoding[i]);
308 ptr = (Guchar *)file + enc;
310 if ((encFormat & 0x7f) == 0) {
312 if (nCodes > nGlyphs) {
315 for (i = 1; i < nCodes; ++i) {
317 encoding[c] = copyString(getString(glyphNames[i], buf));
319 } else if ((encFormat & 0x7f) == 1) {
322 for (i = 0; i < nRanges; ++i) {
325 for (j = 0; j <= nLeft && nCodes < nGlyphs; ++j) {
326 encoding[c] = copyString(getString(glyphNames[nCodes], buf));
332 if (encFormat & 0x80) {
334 for (i = 0; i < nSups; ++i) {
336 sid = getWord(ptr, 2);
338 encoding[c] = copyString(getString(sid, buf));
348 void Type1CFontFile::convertToType1(FILE *outA) {
350 Type1CPrivateDict privateDict;
351 char buf[256], eBuf[256];
352 Guchar *idxPtr0, *idxPtr1, *subrsIdxPtr, *charStringsIdxPtr, *ptr;
353 int nGlyphs, nCodes, nRanges, nLeft, nSups;
355 int encFormat, nSubrs, nCharStrings;
361 // read top dict (first font only)
365 //~ ... global subrs are unimplemented
367 // write header and font dictionary, up to encoding
368 fprintf(out, "%%!FontType1-1.0: %s", name->getCString());
369 if (dict.version != 0) {
370 fprintf(out, "%s", getString(dict.version, buf));
373 fprintf(out, "11 dict begin\n");
374 fprintf(out, "/FontInfo 10 dict dup begin\n");
375 if (dict.version != 0) {
376 fprintf(out, "/version (%s) readonly def\n",
377 getString(dict.version, buf));
379 if (dict.notice != 0) {
380 fprintf(out, "/Notice (%s) readonly def\n",
381 getString(dict.notice, buf));
383 if (dict.copyright != 0) {
384 fprintf(out, "/Copyright (%s) readonly def\n",
385 getString(dict.copyright, buf));
387 if (dict.fullName != 0) {
388 fprintf(out, "/FullName (%s) readonly def\n",
389 getString(dict.fullName, buf));
391 if (dict.familyName != 0) {
392 fprintf(out, "/FamilyName (%s) readonly def\n",
393 getString(dict.familyName, buf));
395 if (dict.weight != 0) {
396 fprintf(out, "/Weight (%s) readonly def\n",
397 getString(dict.weight, buf));
399 fprintf(out, "/isFixedPitch %s def\n", dict.isFixedPitch ? "true" : "false");
400 fprintf(out, "/ItalicAngle %g def\n", dict.italicAngle);
401 fprintf(out, "/UnderlinePosition %g def\n", dict.underlinePosition);
402 fprintf(out, "/UnderlineThickness %g def\n", dict.underlineThickness);
403 fprintf(out, "end readonly def\n");
404 fprintf(out, "/FontName /%s def\n", name->getCString());
405 fprintf(out, "/PaintType %d def\n", dict.paintType);
406 fprintf(out, "/FontType 1 def\n");
407 fprintf(out, "/FontMatrix [%g %g %g %g %g %g] readonly def\n",
408 dict.fontMatrix[0], dict.fontMatrix[1], dict.fontMatrix[2],
409 dict.fontMatrix[3], dict.fontMatrix[4], dict.fontMatrix[5]);
410 fprintf(out, "/FontBBox [%g %g %g %g] readonly def\n",
411 dict.fontBBox[0], dict.fontBBox[1],
412 dict.fontBBox[2], dict.fontBBox[3]);
413 fprintf(out, "/StrokeWidth %g def\n", dict.strokeWidth);
414 if (dict.uniqueID != 0) {
415 fprintf(out, "/UniqueID %d def\n", dict.uniqueID);
418 // get number of glyphs from charstrings index
419 nGlyphs = getIndexLen((Guchar *)file + dict.charStrings);
422 glyphNames = readCharset(dict.charset, nGlyphs);
424 // read encoding (glyph -> code mapping), write Type 1 encoding
425 fprintf(out, "/Encoding ");
426 if (dict.encoding == 0) {
427 fprintf(out, "StandardEncoding def\n");
429 fprintf(out, "256 array\n");
430 fprintf(out, "0 1 255 {1 index exch /.notdef put} for\n");
431 if (dict.encoding == 1) {
432 for (i = 0; i < 256; ++i) {
433 if (expertEncoding[i]) {
434 fprintf(out, "dup %d /%s put\n", i, expertEncoding[i]);
438 ptr = (Guchar *)file + dict.encoding;
440 if ((encFormat & 0x7f) == 0) {
442 if (nCodes > nGlyphs) {
445 for (i = 1; i < nCodes; ++i) {
447 fprintf(out, "dup %d /%s put\n",
448 c, getString(glyphNames[i], buf));
450 } else if ((encFormat & 0x7f) == 1) {
453 for (i = 0; i < nRanges; ++i) {
456 for (j = 0; j <= nLeft && nCodes < nGlyphs; ++j) {
457 fprintf(out, "dup %d /%s put\n",
458 c, getString(glyphNames[nCodes], buf));
464 if (encFormat & 0x80) {
466 for (i = 0; i < nSups; ++i) {
468 sid = getWord(ptr, 2);
470 fprintf(out, "dup %d /%s put\n", c, getString(sid, buf));
474 fprintf(out, "readonly def\n");
476 fprintf(out, "currentdict end\n");
478 // start the binary section
479 fprintf(out, "currentfile eexec\n");
483 // get private dictionary
484 eexecWrite("\x83\xca\x73\xd5");
485 eexecWrite("dup /Private 32 dict dup begin\n");
486 eexecWrite("/RD {string currentfile exch readstring pop} executeonly def\n");
487 eexecWrite("/ND {noaccess def} executeonly def\n");
488 eexecWrite("/NP {noaccess put} executeonly def\n");
489 eexecWrite("/MinFeature {16 16} ND\n");
490 readPrivateDict(&privateDict, dict.privateOffset, dict.privateSize);
491 eexecWrite(privateDict.dictData->getCString());
492 defaultWidthX = privateDict.defaultWidthX;
493 defaultWidthXFP = privateDict.defaultWidthXFP;
494 nominalWidthX = privateDict.nominalWidthX;
495 nominalWidthXFP = privateDict.nominalWidthXFP;
498 if (privateDict.subrsOffset != 0) {
499 subrsIdxPtr = (Guchar *)file + dict.privateOffset +
500 privateDict.subrsOffset;
501 nSubrs = getIndexLen(subrsIdxPtr);
502 sprintf(eBuf, "/Subrs %d array\n", nSubrs);
504 idxPtr1 = getIndexValPtr(subrsIdxPtr, 0);
505 for (i = 0; i < nSubrs; ++i) {
507 idxPtr1 = getIndexValPtr(subrsIdxPtr, i+1);
508 n = idxPtr1 - idxPtr0;
509 #if 1 //~ Type 2 subrs are unimplemented
510 error(-1, "Unimplemented Type 2 subrs");
512 sprintf(eBuf, "dup %d %d RD ", i, n);
514 eexecCvtGlyph(idxPtr0, n);
522 charStringsIdxPtr = (Guchar *)file + dict.charStrings;
523 nCharStrings = getIndexLen(charStringsIdxPtr);
524 sprintf(eBuf, "2 index /CharStrings %d dict dup begin\n", nCharStrings);
526 idxPtr1 = getIndexValPtr(charStringsIdxPtr, 0);
527 for (i = 0; i < nCharStrings; ++i) {
529 idxPtr1 = getIndexValPtr(charStringsIdxPtr, i+1);
530 n = idxPtr1 - idxPtr0;
531 eexecCvtGlyph(getString(glyphNames[i], buf), idxPtr0, n);
535 eexecWrite("readonly put\n");
536 eexecWrite("noaccess put\n");
537 eexecWrite("dup /FontName get exch definefont pop\n");
538 eexecWrite("mark currentfile closefile\n");
544 for (i = 0; i < 8; ++i) {
545 fprintf(out, "0000000000000000000000000000000000000000000000000000000000000000\n");
547 fprintf(out, "cleartomark\n");
550 delete privateDict.dictData;
551 if (dict.charset > 2) {
556 void Type1CFontFile::convertToCIDType0(char *psName, FILE *outA) {
558 Type1CPrivateDict *privateDicts;
559 GString *charStrings;
560 int *charStringOffsets;
564 Guchar *charStringsIdxPtr, *fdArrayIdx, *idxPtr0, *idxPtr1, *ptr;
566 int nGlyphs, nCIDs, gdBytes, nFDs;
567 int fdSelectFmt, nRanges, gid0, gid1, fd, offset;
575 fprintf(out, "/CIDInit /ProcSet findresource begin\n");
577 // read top dict (first font only)
580 // read the FDArray dictionaries and Private dictionaries
581 if (dict.fdArrayOffset == 0) {
583 privateDicts = (Type1CPrivateDict *)
584 gmalloc(nFDs * sizeof(Type1CPrivateDict));
585 privateDicts[0].dictData = new GString();
586 privateDicts[0].subrsOffset = 0;
587 privateDicts[0].defaultWidthX = 0;
588 privateDicts[0].defaultWidthXFP = gFalse;
589 privateDicts[0].nominalWidthX = 0;
590 privateDicts[0].nominalWidthXFP = gFalse;
592 fdArrayIdx = (Guchar *)file + dict.fdArrayOffset;
593 nFDs = getIndexLen(fdArrayIdx);
594 privateDicts = (Type1CPrivateDict *)
595 gmalloc(nFDs * sizeof(Type1CPrivateDict));
596 idxPtr1 = getIndexValPtr(fdArrayIdx, 0);
597 for (i = 0; i < nFDs; ++i) {
598 privateDicts[i].dictData = NULL;
600 idxPtr1 = getIndexValPtr(fdArrayIdx, i + 1);
603 while (ptr < idxPtr1) {
604 if (*ptr <= 27 || *ptr == 31) {
607 key = (key << 8) | *ptr++;
610 readPrivateDict(&privateDicts[i], (int)op[1], (int)op[0]);
614 x = getNum(&ptr, &isFP);
621 if (!privateDicts[i].dictData) {
622 privateDicts[i].dictData = new GString();
623 privateDicts[i].subrsOffset = 0;
624 privateDicts[i].defaultWidthX = 0;
625 privateDicts[i].defaultWidthXFP = gFalse;
626 privateDicts[i].nominalWidthX = 0;
627 privateDicts[i].nominalWidthXFP = gFalse;
632 // get the glyph count
633 charStringsIdxPtr = (Guchar *)file + dict.charStrings;
634 nGlyphs = getIndexLen(charStringsIdxPtr);
636 // read the FDSelect table
637 fdSelect = (Guchar *)gmalloc(nGlyphs);
638 if (dict.fdSelectOffset == 0) {
639 for (i = 0; i < nGlyphs; ++i) {
643 ptr = (Guchar *)file + dict.fdSelectOffset;
644 fdSelectFmt = *ptr++;
645 if (fdSelectFmt == 0) {
646 memcpy(fdSelect, ptr, nGlyphs);
647 } else if (fdSelectFmt == 3) {
648 nRanges = getWord(ptr, 2);
650 gid0 = getWord(ptr, 2);
652 for (i = 1; i <= nRanges; ++i) {
654 gid1 = getWord(ptr, 2);
656 for (j = gid0; j < gid1; ++j) {
662 error(-1, "Unknown FDSelect table format in CID font");
663 for (i = 0; i < nGlyphs; ++i) {
669 // read the charset, compute the CID-to-GID mapping
670 charset = readCharset(dict.charset, nGlyphs);
672 for (i = 0; i < nGlyphs; ++i) {
673 if (charset[i] >= nCIDs) {
674 nCIDs = charset[i] + 1;
677 cidMap = (int *)gmalloc(nCIDs * sizeof(int));
678 for (i = 0; i < nCIDs; ++i) {
681 for (i = 0; i < nGlyphs; ++i) {
682 cidMap[charset[i]] = i;
685 // build the charstrings
686 charStrings = new GString();
687 charStringOffsets = (int *)gmalloc((nCIDs + 1) * sizeof(int));
688 for (i = 0; i < nCIDs; ++i) {
689 charStringOffsets[i] = charStrings->getLength();
690 if (cidMap[i] >= 0) {
691 idxPtr0 = getIndexValPtr(charStringsIdxPtr, cidMap[i]);
692 idxPtr1 = getIndexValPtr(charStringsIdxPtr, cidMap[i]+1);
693 n = idxPtr1 - idxPtr0;
694 j = fdSelect[cidMap[i]];
695 defaultWidthX = privateDicts[j].defaultWidthX;
696 defaultWidthXFP = privateDicts[j].defaultWidthXFP;
697 nominalWidthX = privateDicts[j].nominalWidthX;
698 nominalWidthXFP = privateDicts[j].nominalWidthXFP;
699 cvtGlyph(idxPtr0, n);
700 charStrings->append(charBuf);
704 charStringOffsets[nCIDs] = charStrings->getLength();
706 // compute gdBytes = number of bytes needed for charstring offsets
707 // (offset size needs to account for the charstring offset table,
708 // with a worst case of five bytes per entry, plus the charstrings
710 i = (nCIDs + 1) * 5 + charStrings->getLength();
713 } else if (i < 0x10000) {
715 } else if (i < 0x1000000) {
721 // begin the font dictionary
722 fprintf(out, "20 dict begin\n");
723 fprintf(out, "/CIDFontName /%s def\n", psName);
724 fprintf(out, "/CIDFontType 0 def\n");
725 fprintf(out, "/CIDSystemInfo 3 dict dup begin\n");
726 if (dict.registry > 0 && dict.ordering > 0) {
727 fprintf(out, " /Registry (%s) def\n", getString(dict.registry, buf));
728 fprintf(out, " /Ordering (%s) def\n", getString(dict.ordering, buf));
730 fprintf(out, " /Registry (Adobe) def\n");
731 fprintf(out, " /Ordering (Identity) def\n");
733 fprintf(out, " /Supplement %d def\n", dict.supplement);
734 fprintf(out, "end def\n");
735 fprintf(out, "/FontMatrix [%g %g %g %g %g %g] def\n",
736 dict.fontMatrix[0], dict.fontMatrix[1], dict.fontMatrix[2],
737 dict.fontMatrix[3], dict.fontMatrix[4], dict.fontMatrix[5]);
738 fprintf(out, "/FontBBox [%g %g %g %g] def\n",
739 dict.fontBBox[0], dict.fontBBox[1],
740 dict.fontBBox[2], dict.fontBBox[3]);
741 fprintf(out, "/FontInfo 1 dict dup begin\n");
742 fprintf(out, " /FSType 8 def\n");
743 fprintf(out, "end def\n");
745 // CIDFont-specific entries
746 fprintf(out, "/CIDCount %d def\n", nCIDs);
747 fprintf(out, "/FDBytes 1 def\n");
748 fprintf(out, "/GDBytes %d def\n", gdBytes);
749 fprintf(out, "/CIDMapOffset 0 def\n");
750 if (dict.paintType != 0) {
751 fprintf(out, "/PaintType %d def\n", dict.paintType);
752 fprintf(out, "/StrokeWidth %g def\n", dict.strokeWidth);
756 fprintf(out, "/FDArray %d array\n", nFDs);
757 for (i = 0; i < nFDs; ++i) {
758 fprintf(out, "dup %d 10 dict begin\n", i);
759 fprintf(out, "/FontType 1 def\n");
760 fprintf(out, "/FontMatrix [1 0 0 1 0 0] def\n");
761 fprintf(out, "/PaintType %d def\n", dict.paintType);
762 fprintf(out, "/Private 32 dict begin\n");
763 fwrite(privateDicts[i].dictData->getCString(), 1,
764 privateDicts[i].dictData->getLength(), out);
765 fprintf(out, "currentdict end def\n");
766 fprintf(out, "currentdict end put\n");
768 fprintf(out, "def\n");
770 //~ need to deal with subrs
772 // start the binary section
773 offset = (nCIDs + 1) * (1 + gdBytes);
774 fprintf(out, "(Hex) %d StartData\n",
775 offset + charStrings->getLength());
777 // write the charstring offset (CIDMap) table
778 for (i = 0; i <= nCIDs; i += 6) {
779 for (j = 0; j < 6 && i+j <= nCIDs; ++j) {
780 if (cidMap[i+j] >= 0) {
781 buf[0] = (char)fdSelect[cidMap[i+j]];
785 n = offset + charStringOffsets[i+j];
786 for (k = gdBytes; k >= 1; --k) {
787 buf[k] = (char)(n & 0xff);
790 for (k = 0; k <= gdBytes; ++k) {
791 fprintf(out, "%02x", buf[k] & 0xff);
797 // write the charstring data
798 n = charStrings->getLength();
799 for (i = 0; i < n; i += 32) {
800 for (j = 0; j < 32 && i+j < n; ++j) {
801 fprintf(out, "%02x", charStrings->getChar(i+j) & 0xff);
809 for (i = 0; i < nFDs; ++i) {
810 delete privateDicts[i].dictData;
815 gfree(charStringOffsets);
820 void Type1CFontFile::convertToType0(char *psName, FILE *outA) {
822 Type1CPrivateDict *privateDicts;
826 Guchar *charStringsIdxPtr, *fdArrayIdx, *idxPtr0, *idxPtr1, *ptr;
829 int nGlyphs, nCIDs, nFDs;
830 int fdSelectFmt, nRanges, gid0, gid1, fd;
838 // read top dict (first font only)
841 // read the FDArray dictionaries and Private dictionaries
842 if (dict.fdArrayOffset == 0) {
844 privateDicts = (Type1CPrivateDict *)
845 gmalloc(nFDs * sizeof(Type1CPrivateDict));
846 privateDicts[0].dictData = new GString();
847 privateDicts[0].subrsOffset = 0;
848 privateDicts[0].defaultWidthX = 0;
849 privateDicts[0].defaultWidthXFP = gFalse;
850 privateDicts[0].nominalWidthX = 0;
851 privateDicts[0].nominalWidthXFP = gFalse;
853 fdArrayIdx = (Guchar *)file + dict.fdArrayOffset;
854 nFDs = getIndexLen(fdArrayIdx);
855 privateDicts = (Type1CPrivateDict *)
856 gmalloc(nFDs * sizeof(Type1CPrivateDict));
857 idxPtr1 = getIndexValPtr(fdArrayIdx, 0);
858 for (i = 0; i < nFDs; ++i) {
859 privateDicts[i].dictData = NULL;
861 idxPtr1 = getIndexValPtr(fdArrayIdx, i + 1);
864 while (ptr < idxPtr1) {
865 if (*ptr <= 27 || *ptr == 31) {
868 key = (key << 8) | *ptr++;
871 readPrivateDict(&privateDicts[i], (int)op[1], (int)op[0]);
875 x = getNum(&ptr, &isFP);
882 if (!privateDicts[i].dictData) {
883 privateDicts[i].dictData = new GString();
884 privateDicts[i].subrsOffset = 0;
885 privateDicts[i].defaultWidthX = 0;
886 privateDicts[i].defaultWidthXFP = gFalse;
887 privateDicts[i].nominalWidthX = 0;
888 privateDicts[i].nominalWidthXFP = gFalse;
893 // get the glyph count
894 charStringsIdxPtr = (Guchar *)file + dict.charStrings;
895 nGlyphs = getIndexLen(charStringsIdxPtr);
897 // read the FDSelect table
898 fdSelect = (Guchar *)gmalloc(nGlyphs);
899 if (dict.fdSelectOffset == 0) {
900 for (i = 0; i < nGlyphs; ++i) {
904 ptr = (Guchar *)file + dict.fdSelectOffset;
905 fdSelectFmt = *ptr++;
906 if (fdSelectFmt == 0) {
907 memcpy(fdSelect, ptr, nGlyphs);
908 } else if (fdSelectFmt == 3) {
909 nRanges = getWord(ptr, 2);
911 gid0 = getWord(ptr, 2);
913 for (i = 1; i <= nRanges; ++i) {
915 gid1 = getWord(ptr, 2);
917 for (j = gid0; j < gid1; ++j) {
923 error(-1, "Unknown FDSelect table format in CID font");
924 for (i = 0; i < nGlyphs; ++i) {
930 // read the charset, compute the CID-to-GID mapping
931 charset = readCharset(dict.charset, nGlyphs);
933 for (i = 0; i < nGlyphs; ++i) {
934 if (charset[i] >= nCIDs) {
935 nCIDs = charset[i] + 1;
938 cidMap = (int *)gmalloc(nCIDs * sizeof(int));
939 for (i = 0; i < nCIDs; ++i) {
942 for (i = 0; i < nGlyphs; ++i) {
943 cidMap[charset[i]] = i;
946 // write the descendant Type 1 fonts
947 for (i = 0; i < nCIDs; i += 256) {
949 //~ this assumes that all CIDs in this block have the same FD --
950 //~ to handle multiple FDs correctly, need to somehow divide the
953 for (j = 0; j < 256 && i+j < nCIDs; ++j) {
954 if (cidMap[i+j] >= 0) {
955 fd = fdSelect[cidMap[i+j]];
960 // font dictionary (unencrypted section)
961 fprintf(out, "16 dict begin\n");
962 fprintf(out, "/FontName /%s_%02x def\n", psName, i >> 8);
963 fprintf(out, "/FontType 1 def\n");
964 fprintf(out, "/FontMatrix [%g %g %g %g %g %g] def\n",
965 dict.fontMatrix[0], dict.fontMatrix[1], dict.fontMatrix[2],
966 dict.fontMatrix[3], dict.fontMatrix[4], dict.fontMatrix[5]);
967 fprintf(out, "/FontBBox [%g %g %g %g] def\n",
968 dict.fontBBox[0], dict.fontBBox[1],
969 dict.fontBBox[2], dict.fontBBox[3]);
970 fprintf(out, "/PaintType %d def\n", dict.paintType);
971 if (dict.paintType != 0) {
972 fprintf(out, "/StrokeWidth %g def\n", dict.strokeWidth);
974 fprintf(out, "/Encoding 256 array\n");
975 for (j = 0; j < 256 && i+j < nCIDs; ++j) {
976 fprintf(out, "dup %d /c%02x put\n", j, j);
978 fprintf(out, "readonly def\n");
979 fprintf(out, "currentdict end\n");
981 // start the binary section
982 fprintf(out, "currentfile eexec\n");
986 // start the private dictionary
987 eexecWrite("\x83\xca\x73\xd5");
988 eexecWrite("dup /Private 32 dict dup begin\n");
989 eexecWrite("/RD {string currentfile exch readstring pop} executeonly def\n");
990 eexecWrite("/ND {noaccess def} executeonly def\n");
991 eexecWrite("/NP {noaccess put} executeonly def\n");
992 eexecWrite("/MinFeature {16 16} ND\n");
993 eexecWrite(privateDicts[fd].dictData->getCString());
994 defaultWidthX = privateDicts[fd].defaultWidthX;
995 defaultWidthXFP = privateDicts[fd].defaultWidthXFP;
996 nominalWidthX = privateDicts[fd].nominalWidthX;
997 nominalWidthXFP = privateDicts[fd].nominalWidthXFP;
999 // start the CharStrings
1000 sprintf(eBuf, "2 index /CharStrings 256 dict dup begin\n");
1003 // write the .notdef CharString
1004 idxPtr0 = getIndexValPtr(charStringsIdxPtr, 0);
1005 idxPtr1 = getIndexValPtr(charStringsIdxPtr, 1);
1006 n = idxPtr1 - idxPtr0;
1007 eexecCvtGlyph(".notdef", idxPtr0, n);
1009 // write the CharStrings
1010 for (j = 0; j < 256 && i+j < nCIDs; ++j) {
1011 if (cidMap[i+j] >= 0) {
1012 idxPtr0 = getIndexValPtr(charStringsIdxPtr, cidMap[i+j]);
1013 idxPtr1 = getIndexValPtr(charStringsIdxPtr, cidMap[i+j]+1);
1014 n = idxPtr1 - idxPtr0;
1015 sprintf(buf, "c%02x", j);
1016 eexecCvtGlyph(buf, idxPtr0, n);
1019 eexecWrite("end\n");
1020 eexecWrite("end\n");
1021 eexecWrite("readonly put\n");
1022 eexecWrite("noaccess put\n");
1023 eexecWrite("dup /FontName get exch definefont pop\n");
1024 eexecWrite("mark currentfile closefile\n");
1030 for (j = 0; j < 8; ++j) {
1031 fprintf(out, "0000000000000000000000000000000000000000000000000000000000000000\n");
1033 fprintf(out, "cleartomark\n");
1036 // write the Type 0 parent font
1037 fprintf(out, "16 dict begin\n");
1038 fprintf(out, "/FontName /%s def\n", psName);
1039 fprintf(out, "/FontType 0 def\n");
1040 fprintf(out, "/FontMatrix [1 0 0 1 0 0] def\n");
1041 fprintf(out, "/FMapType 2 def\n");
1042 fprintf(out, "/Encoding [\n");
1043 for (i = 0; i < nCIDs; i += 256) {
1044 fprintf(out, "%d\n", i >> 8);
1046 fprintf(out, "] def\n");
1047 fprintf(out, "/FDepVector [\n");
1048 for (i = 0; i < nCIDs; i += 256) {
1049 fprintf(out, "/%s_%02x findfont\n", psName, i >> 8);
1051 fprintf(out, "] def\n");
1052 fprintf(out, "FontName currentdict end definefont pop\n");
1055 for (i = 0; i < nFDs; ++i) {
1056 delete privateDicts[i].dictData;
1058 gfree(privateDicts);
1064 void Type1CFontFile::readTopDict(Type1CTopDict *dict) {
1065 Guchar *idxPtr0, *idxPtr1, *ptr;
1071 idxPtr0 = getIndexValPtr(topDictIdxPtr, 0);
1072 idxPtr1 = getIndexValPtr(topDictIdxPtr, 1);
1075 dict->copyright = 0;
1077 dict->familyName = 0;
1079 dict->isFixedPitch = 0;
1080 dict->italicAngle = 0;
1081 dict->underlinePosition = -100;
1082 dict->underlineThickness = 50;
1083 dict->paintType = 0;
1084 dict->charstringType = 2;
1085 dict->fontMatrix[0] = 0.001;
1086 dict->fontMatrix[1] = 0;
1087 dict->fontMatrix[2] = 0;
1088 dict->fontMatrix[3] = 0.001;
1089 dict->fontMatrix[4] = 0;
1090 dict->fontMatrix[5] = 0;
1092 dict->fontBBox[0] = 0;
1093 dict->fontBBox[1] = 0;
1094 dict->fontBBox[2] = 0;
1095 dict->fontBBox[3] = 0;
1096 dict->strokeWidth = 0;
1099 dict->charStrings = 0;
1100 dict->privateSize = 0;
1101 dict->privateOffset = 0;
1104 dict->supplement = 0;
1105 dict->fdArrayOffset = 0;
1106 dict->fdSelectOffset = 0;
1109 while (ptr < idxPtr1) {
1110 if (*ptr <= 27 || *ptr == 31) {
1113 key = (key << 8) | *ptr++;
1116 case 0x0000: dict->version = (int)op[0]; break;
1117 case 0x0001: dict->notice = (int)op[0]; break;
1118 case 0x0c00: dict->copyright = (int)op[0]; break;
1119 case 0x0002: dict->fullName = (int)op[0]; break;
1120 case 0x0003: dict->familyName = (int)op[0]; break;
1121 case 0x0004: dict->weight = (int)op[0]; break;
1122 case 0x0c01: dict->isFixedPitch = (int)op[0]; break;
1123 case 0x0c02: dict->italicAngle = op[0]; break;
1124 case 0x0c03: dict->underlinePosition = op[0]; break;
1125 case 0x0c04: dict->underlineThickness = op[0]; break;
1126 case 0x0c05: dict->paintType = (int)op[0]; break;
1127 case 0x0c06: dict->charstringType = (int)op[0]; break;
1128 case 0x0c07: dict->fontMatrix[0] = op[0];
1129 dict->fontMatrix[1] = op[1];
1130 dict->fontMatrix[2] = op[2];
1131 dict->fontMatrix[3] = op[3];
1132 dict->fontMatrix[4] = op[4];
1133 dict->fontMatrix[5] = op[5]; break;
1134 case 0x000d: dict->uniqueID = (int)op[0]; break;
1135 case 0x0005: dict->fontBBox[0] = op[0];
1136 dict->fontBBox[1] = op[1];
1137 dict->fontBBox[2] = op[2];
1138 dict->fontBBox[3] = op[3]; break;
1139 case 0x0c08: dict->strokeWidth = op[0]; break;
1140 case 0x000f: dict->charset = (int)op[0]; break;
1141 case 0x0010: dict->encoding = (int)op[0]; break;
1142 case 0x0011: dict->charStrings = (int)op[0]; break;
1143 case 0x0012: dict->privateSize = (int)op[0];
1144 dict->privateOffset = (int)op[1]; break;
1145 case 0x0c1e: dict->registry = (int)op[0];
1146 dict->ordering = (int)op[1];
1147 dict->supplement = (int)op[2]; break;
1148 case 0x0c24: dict->fdArrayOffset = (int)op[0]; break;
1149 case 0x0c25: dict->fdSelectOffset = (int)op[0]; break;
1153 x = getNum(&ptr, &isFP);
1162 void Type1CFontFile::readPrivateDict(Type1CPrivateDict *privateDict,
1163 int offset, int size) {
1164 Guchar *idxPtr0, *idxPtr1, *ptr;
1171 privateDict->dictData = new GString();
1172 privateDict->subrsOffset = 0;
1173 privateDict->defaultWidthX = 0;
1174 privateDict->defaultWidthXFP = gFalse;
1175 privateDict->nominalWidthX = 0;
1176 privateDict->nominalWidthXFP = gFalse;
1177 idxPtr0 = (Guchar *)file + offset;
1178 idxPtr1 = idxPtr0 + size;
1181 while (ptr < idxPtr1) {
1182 if (*ptr <= 27 || *ptr == 31) {
1185 key = (key << 8) | *ptr++;
1189 getDeltaInt(eBuf, "BlueValues", op, i);
1190 privateDict->dictData->append(eBuf);
1193 getDeltaInt(eBuf, "OtherBlues", op, i);
1194 privateDict->dictData->append(eBuf);
1197 getDeltaInt(eBuf, "FamilyBlues", op, i);
1198 privateDict->dictData->append(eBuf);
1201 getDeltaInt(eBuf, "FamilyOtherBlues", op, i);
1202 privateDict->dictData->append(eBuf);
1205 sprintf(eBuf, "/BlueScale %g def\n", op[0]);
1206 privateDict->dictData->append(eBuf);
1209 sprintf(eBuf, "/BlueShift %d def\n", (int)op[0]);
1210 privateDict->dictData->append(eBuf);
1213 sprintf(eBuf, "/BlueFuzz %d def\n", (int)op[0]);
1214 privateDict->dictData->append(eBuf);
1217 sprintf(eBuf, "/StdHW [%g] def\n", op[0]);
1218 privateDict->dictData->append(eBuf);
1221 sprintf(eBuf, "/StdVW [%g] def\n", op[0]);
1222 privateDict->dictData->append(eBuf);
1225 getDeltaReal(eBuf, "StemSnapH", op, i);
1226 privateDict->dictData->append(eBuf);
1229 getDeltaReal(eBuf, "StemSnapV", op, i);
1230 privateDict->dictData->append(eBuf);
1233 sprintf(eBuf, "/ForceBold %s def\n", op[0] ? "true" : "false");
1234 privateDict->dictData->append(eBuf);
1237 sprintf(eBuf, "/ForceBoldThreshold %g def\n", op[0]);
1238 privateDict->dictData->append(eBuf);
1241 sprintf(eBuf, "/LanguageGroup %d def\n", (int)op[0]);
1242 privateDict->dictData->append(eBuf);
1245 sprintf(eBuf, "/ExpansionFactor %g def\n", op[0]);
1246 privateDict->dictData->append(eBuf);
1249 error(-1, "Got Type 1C InitialRandomSeed");
1252 privateDict->subrsOffset = (int)op[0];
1255 privateDict->defaultWidthX = op[0];
1256 privateDict->defaultWidthXFP = fp[0];
1259 privateDict->nominalWidthX = op[0];
1260 privateDict->nominalWidthXFP = fp[0];
1263 error(-1, "Unknown Type 1C private dict entry %04x", key);
1268 x = getNum(&ptr, &isFP);
1277 Gushort *Type1CFontFile::readCharset(int charset, int nGlyphs) {
1278 Gushort *glyphNames;
1280 int charsetFormat, c;
1284 glyphNames = type1CISOAdobeCharset;
1285 } else if (charset == 1) {
1286 glyphNames = type1CExpertCharset;
1287 } else if (charset == 2) {
1288 glyphNames = type1CExpertSubsetCharset;
1290 glyphNames = (Gushort *)gmalloc(nGlyphs * sizeof(Gushort));
1292 ptr = (Guchar *)file + charset;
1293 charsetFormat = *ptr++;
1294 if (charsetFormat == 0) {
1295 for (i = 1; i < nGlyphs; ++i) {
1296 glyphNames[i] = getWord(ptr, 2);
1299 } else if (charsetFormat == 1) {
1301 while (i < nGlyphs) {
1302 c = getWord(ptr, 2);
1305 for (j = 0; j <= nLeft && i < nGlyphs; ++j) {
1306 glyphNames[i++] = c++;
1309 } else if (charsetFormat == 2) {
1311 while (i < nGlyphs) {
1312 c = getWord(ptr, 2);
1314 nLeft = getWord(ptr, 2);
1316 for (j = 0; j <= nLeft && i < nGlyphs; ++j) {
1317 glyphNames[i++] = c++;
1325 void Type1CFontFile::eexecWrite(char *s) {
1329 for (p = (Guchar *)s; *p; ++p) {
1331 r1 = (x + r1) * 52845 + 22719;
1332 fputc(hexChars[x >> 4], out);
1333 fputc(hexChars[x & 0x0f], out);
1342 void Type1CFontFile::eexecCvtGlyph(char *glyphName, Guchar *s, int n) {
1346 sprintf(eBuf, "/%s %d RD ", glyphName, charBuf->getLength());
1348 eexecWriteCharstring((Guchar *)charBuf->getCString(), charBuf->getLength());
1349 eexecWrite(" ND\n");
1353 void Type1CFontFile::cvtGlyph(Guchar *s, int n) {
1356 GBool first = gTrue;
1363 charBuf = new GString();
1364 charBuf->append((char)73);
1365 charBuf->append((char)58);
1366 charBuf->append((char)147);
1367 charBuf->append((char)134);
1375 case 0: // dotsection (should be Type 1 only?)
1380 error(-1, "Wrong number of args (%d) to Type 2 hflex", nOps);
1382 eexecDumpNum(op[0], fp[0]);
1383 eexecDumpNum(0, gFalse);
1384 eexecDumpNum(op[1], fp[1]);
1385 eexecDumpNum(op[2], fp[2]);
1386 eexecDumpNum(op[3], fp[3]);
1387 eexecDumpNum(0, gFalse);
1389 eexecDumpNum(op[4], fp[4]);
1390 eexecDumpNum(0, gFalse);
1391 eexecDumpNum(op[5], fp[5]);
1392 eexecDumpNum(-op[2], fp[2]);
1393 eexecDumpNum(op[6], fp[6]);
1394 eexecDumpNum(0, gFalse);
1399 error(-1, "Wrong number of args (%d) to Type 2 flex", nOps);
1401 eexecDumpNum(op[0], fp[0]);
1402 eexecDumpNum(op[1], fp[1]);
1403 eexecDumpNum(op[2], fp[2]);
1404 eexecDumpNum(op[3], fp[3]);
1405 eexecDumpNum(op[4], fp[4]);
1406 eexecDumpNum(op[5], fp[5]);
1408 eexecDumpNum(op[6], fp[6]);
1409 eexecDumpNum(op[7], fp[7]);
1410 eexecDumpNum(op[8], fp[8]);
1411 eexecDumpNum(op[9], fp[9]);
1412 eexecDumpNum(op[10], fp[10]);
1413 eexecDumpNum(op[11], fp[11]);
1418 error(-1, "Wrong number of args (%d) to Type 2 hflex1", nOps);
1420 eexecDumpNum(op[0], fp[0]);
1421 eexecDumpNum(op[1], fp[1]);
1422 eexecDumpNum(op[2], fp[2]);
1423 eexecDumpNum(op[3], fp[3]);
1424 eexecDumpNum(op[4], fp[4]);
1425 eexecDumpNum(0, gFalse);
1427 eexecDumpNum(op[5], fp[5]);
1428 eexecDumpNum(0, gFalse);
1429 eexecDumpNum(op[6], fp[6]);
1430 eexecDumpNum(op[7], fp[7]);
1431 eexecDumpNum(op[8], fp[8]);
1432 eexecDumpNum(-(op[1] + op[3] + op[7]), fp[1] | fp[3] | fp[7]);
1437 error(-1, "Wrong number of args (%d) to Type 2 flex1", nOps);
1439 eexecDumpNum(op[0], fp[0]);
1440 eexecDumpNum(op[1], fp[1]);
1441 eexecDumpNum(op[2], fp[2]);
1442 eexecDumpNum(op[3], fp[3]);
1443 eexecDumpNum(op[4], fp[4]);
1444 eexecDumpNum(op[5], fp[5]);
1446 eexecDumpNum(op[6], fp[6]);
1447 eexecDumpNum(op[7], fp[7]);
1448 eexecDumpNum(op[8], fp[8]);
1449 eexecDumpNum(op[9], fp[9]);
1450 dx = op[0] + op[2] + op[4] + op[6] + op[8];
1451 dy = op[1] + op[3] + op[5] + op[7] + op[9];
1452 if (fabs(dx) > fabs(dy)) {
1453 eexecDumpNum(op[10], fp[10]);
1454 eexecDumpNum(-dy, fp[1] | fp[3] | fp[5] | fp[7] | fp[9]);
1456 eexecDumpNum(-dx, fp[0] | fp[2] | fp[4] | fp[6] | fp[8]);
1457 eexecDumpNum(op[10], fp[10]);
1483 error(-1, "Unimplemented Type 2 charstring op: 12.%d", s[i+1]);
1486 error(-1, "Illegal Type 2 charstring op: 12.%d", s[i+1]);
1491 } else if (s[i] == 19) { // hintmask
1494 cvtGlyphWidth(nOps == 1);
1499 error(-1, "Wrong number of args (%d) to Type 2 hintmask/vstemhm",
1504 i += 1 + ((nHints + 7) >> 3);
1506 } else if (s[i] == 20) { // cntrmask
1509 cvtGlyphWidth(nOps == 1);
1514 error(-1, "Wrong number of args (%d) to Type 2 cntrmask/vstemhm",
1519 i += 1 + ((nHints + 7) >> 3);
1521 } else if (s[i] == 28) {
1522 x = (s[i+1] << 8) + s[i+2];
1531 } else if (s[i] <= 31) {
1535 cvtGlyphWidth(nOps == 2);
1539 error(-1, "Wrong number of args (%d) to Type 2 vmoveto", nOps);
1541 eexecDumpNum(op[0], fp[0]);
1545 if (nOps < 2 || nOps % 2 != 0) {
1546 error(-1, "Wrong number of args (%d) to Type 2 rlineto", nOps);
1548 for (k = 0; k < nOps; k += 2) {
1549 eexecDumpNum(op[k], fp[k]);
1550 eexecDumpNum(op[k+1], fp[k+1]);
1556 error(-1, "Wrong number of args (%d) to Type 2 hlineto", nOps);
1558 for (k = 0; k < nOps; ++k) {
1559 eexecDumpNum(op[k], fp[k]);
1560 eexecDumpOp1((k & 1) ? 7 : 6);
1565 error(-1, "Wrong number of args (%d) to Type 2 vlineto", nOps);
1567 for (k = 0; k < nOps; ++k) {
1568 eexecDumpNum(op[k], fp[k]);
1569 eexecDumpOp1((k & 1) ? 6 : 7);
1572 case 8: // rrcurveto
1573 if (nOps < 6 || nOps % 6 != 0) {
1574 error(-1, "Wrong number of args (%d) to Type 2 rrcurveto", nOps);
1576 for (k = 0; k < nOps; k += 6) {
1577 eexecDumpNum(op[k], fp[k]);
1578 eexecDumpNum(op[k+1], fp[k+1]);
1579 eexecDumpNum(op[k+2], fp[k+2]);
1580 eexecDumpNum(op[k+3], fp[k+3]);
1581 eexecDumpNum(op[k+4], fp[k+4]);
1582 eexecDumpNum(op[k+5], fp[k+5]);
1586 case 14: // endchar / seac
1588 cvtGlyphWidth(nOps == 1 || nOps == 5);
1593 eexecDumpNum(op[0], fp[0]);
1594 eexecDumpNum(op[1], fp[1]);
1595 eexecDumpNum(op[2], fp[2]);
1596 eexecDumpNum(op[3], fp[3]);
1598 } else if (nOps == 0) {
1601 error(-1, "Wrong number of args (%d) to Type 2 endchar", nOps);
1606 cvtGlyphWidth(nOps == 3);
1610 error(-1, "Wrong number of args (%d) to Type 2 rmoveto", nOps);
1612 eexecDumpNum(op[0], fp[0]);
1613 eexecDumpNum(op[1], fp[1]);
1618 cvtGlyphWidth(nOps == 2);
1622 error(-1, "Wrong number of args (%d) to Type 2 hmoveto", nOps);
1624 eexecDumpNum(op[0], fp[0]);
1627 case 24: // rcurveline
1628 if (nOps < 8 || (nOps - 2) % 6 != 0) {
1629 error(-1, "Wrong number of args (%d) to Type 2 rcurveline", nOps);
1631 for (k = 0; k < nOps - 2; k += 6) {
1632 eexecDumpNum(op[k], fp[k]);
1633 eexecDumpNum(op[k+1], fp[k+1]);
1634 eexecDumpNum(op[k+2], fp[k+2]);
1635 eexecDumpNum(op[k+3], fp[k+3]);
1636 eexecDumpNum(op[k+4], fp[k+4]);
1637 eexecDumpNum(op[k+5], fp[k+5]);
1640 eexecDumpNum(op[k], fp[k]);
1641 eexecDumpNum(op[k+1], fp[k]);
1644 case 25: // rlinecurve
1645 if (nOps < 8 || (nOps - 6) % 2 != 0) {
1646 error(-1, "Wrong number of args (%d) to Type 2 rlinecurve", nOps);
1648 for (k = 0; k < nOps - 6; k += 2) {
1649 eexecDumpNum(op[k], fp[k]);
1650 eexecDumpNum(op[k+1], fp[k]);
1653 eexecDumpNum(op[k], fp[k]);
1654 eexecDumpNum(op[k+1], fp[k+1]);
1655 eexecDumpNum(op[k+2], fp[k+2]);
1656 eexecDumpNum(op[k+3], fp[k+3]);
1657 eexecDumpNum(op[k+4], fp[k+4]);
1658 eexecDumpNum(op[k+5], fp[k+5]);
1661 case 26: // vvcurveto
1662 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
1663 error(-1, "Wrong number of args (%d) to Type 2 vvcurveto", nOps);
1665 if (nOps % 2 == 1) {
1666 eexecDumpNum(op[0], fp[0]);
1667 eexecDumpNum(op[1], fp[1]);
1668 eexecDumpNum(op[2], fp[2]);
1669 eexecDumpNum(op[3], fp[3]);
1670 eexecDumpNum(0, gFalse);
1671 eexecDumpNum(op[4], fp[4]);
1677 for (; k < nOps; k += 4) {
1678 eexecDumpNum(0, gFalse);
1679 eexecDumpNum(op[k], fp[k]);
1680 eexecDumpNum(op[k+1], fp[k+1]);
1681 eexecDumpNum(op[k+2], fp[k+2]);
1682 eexecDumpNum(0, gFalse);
1683 eexecDumpNum(op[k+3], fp[k+3]);
1687 case 27: // hhcurveto
1688 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
1689 error(-1, "Wrong number of args (%d) to Type 2 hhcurveto", nOps);
1691 if (nOps % 2 == 1) {
1692 eexecDumpNum(op[1], fp[1]);
1693 eexecDumpNum(op[0], fp[0]);
1694 eexecDumpNum(op[2], fp[2]);
1695 eexecDumpNum(op[3], fp[3]);
1696 eexecDumpNum(op[4], fp[4]);
1697 eexecDumpNum(0, gFalse);
1703 for (; k < nOps; k += 4) {
1704 eexecDumpNum(op[k], fp[k]);
1705 eexecDumpNum(0, gFalse);
1706 eexecDumpNum(op[k+1], fp[k+1]);
1707 eexecDumpNum(op[k+2], fp[k+2]);
1708 eexecDumpNum(op[k+3], fp[k+3]);
1709 eexecDumpNum(0, gFalse);
1713 case 30: // vhcurveto
1714 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
1715 error(-1, "Wrong number of args (%d) to Type 2 vhcurveto", nOps);
1717 for (k = 0; k < nOps && k != nOps-5; k += 4) {
1719 eexecDumpNum(op[k], fp[k]);
1720 eexecDumpNum(op[k+1], fp[k+1]);
1721 eexecDumpNum(op[k+2], fp[k+2]);
1722 eexecDumpNum(op[k+3], fp[k+3]);
1725 eexecDumpNum(op[k], fp[k]);
1726 eexecDumpNum(op[k+1], fp[k+1]);
1727 eexecDumpNum(op[k+2], fp[k+2]);
1728 eexecDumpNum(op[k+3], fp[k+3]);
1734 eexecDumpNum(0, gFalse);
1735 eexecDumpNum(op[k], fp[k]);
1736 eexecDumpNum(op[k+1], fp[k+1]);
1737 eexecDumpNum(op[k+2], fp[k+2]);
1738 eexecDumpNum(op[k+3], fp[k+3]);
1739 eexecDumpNum(op[k+4], fp[k+4]);
1741 eexecDumpNum(op[k], fp[k]);
1742 eexecDumpNum(0, gFalse);
1743 eexecDumpNum(op[k+1], fp[k+1]);
1744 eexecDumpNum(op[k+2], fp[k+2]);
1745 eexecDumpNum(op[k+4], fp[k+4]);
1746 eexecDumpNum(op[k+3], fp[k+3]);
1751 case 31: // hvcurveto
1752 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
1753 error(-1, "Wrong number of args (%d) to Type 2 hvcurveto", nOps);
1755 for (k = 0; k < nOps && k != nOps-5; k += 4) {
1757 eexecDumpNum(op[k], fp[k]);
1758 eexecDumpNum(op[k+1], fp[k+1]);
1759 eexecDumpNum(op[k+2], fp[k+2]);
1760 eexecDumpNum(op[k+3], fp[k+3]);
1763 eexecDumpNum(op[k], fp[k]);
1764 eexecDumpNum(op[k+1], fp[k+1]);
1765 eexecDumpNum(op[k+2], fp[k+2]);
1766 eexecDumpNum(op[k+3], fp[k+3]);
1772 eexecDumpNum(op[k], fp[k]);
1773 eexecDumpNum(0, gFalse);
1774 eexecDumpNum(op[k+1], fp[k+1]);
1775 eexecDumpNum(op[k+2], fp[k+2]);
1776 eexecDumpNum(op[k+4], fp[k+4]);
1777 eexecDumpNum(op[k+3], fp[k+3]);
1779 eexecDumpNum(0, gFalse);
1780 eexecDumpNum(op[k], fp[k]);
1781 eexecDumpNum(op[k+1], fp[k+1]);
1782 eexecDumpNum(op[k+2], fp[k+2]);
1783 eexecDumpNum(op[k+3], fp[k+3]);
1784 eexecDumpNum(op[k+4], fp[k+4]);
1791 cvtGlyphWidth(nOps & 1);
1795 error(-1, "Wrong number of args (%d) to Type 2 hstem", nOps);
1799 for (k = 0; k < nOps; k += 2) {
1801 d += op[k] + op[k+1];
1802 dFP |= fp[k] | fp[k+1];
1803 eexecDumpNum(d, dFP);
1804 eexecDumpNum(-op[k+1], fp[k+1]);
1808 eexecDumpNum(d, dFP);
1809 eexecDumpNum(op[k+1], fp[k+1]);
1819 cvtGlyphWidth(nOps & 1);
1823 error(-1, "Wrong number of args (%d) to Type 2 vstem", nOps);
1827 for (k = 0; k < nOps; k += 2) {
1829 d += op[k] + op[k+1];
1830 dFP |= fp[k] | fp[k+1];
1831 eexecDumpNum(d, dFP);
1832 eexecDumpNum(-op[k+1], fp[k+1]);
1836 eexecDumpNum(d, dFP);
1837 eexecDumpNum(op[k+1], fp[k+1]);
1848 cvtGlyphWidth(nOps & 1);
1852 error(-1, "Wrong number of args (%d) to Type 2 hstemhm", nOps);
1859 cvtGlyphWidth(nOps & 1);
1863 error(-1, "Wrong number of args (%d) to Type 2 vstemhm", nOps);
1867 case 10: // callsubr
1870 case 29: // callgsubr
1871 error(-1, "Unimplemented Type 2 charstring op: %d", s[i]);
1874 error(-1, "Illegal Type 2 charstring op: %d", s[i]);
1879 } else if (s[i] <= 246) {
1882 op[nOps++] = (int)s[i] - 139;
1885 } else if (s[i] <= 250) {
1888 op[nOps++] = (((int)s[i] - 247) << 8) + (int)s[i+1] + 108;
1891 } else if (s[i] <= 254) {
1894 op[nOps++] = -(((int)s[i] - 251) << 8) - (int)s[i+1] - 108;
1898 x = (s[i+1] << 24) | (s[i+2] << 16) | (s[i+3] << 8) | s[i+4];
1903 op[nOps++] = (double)x / 65536.0;
1909 // charstring encryption
1911 for (i = 0; i < charBuf->getLength(); ++i) {
1912 byte = charBuf->getChar(i) ^ (r2 >> 8);
1913 charBuf->setChar(i, byte);
1914 r2 = (byte + r2) * 52845 + 22719;
1918 void Type1CFontFile::cvtGlyphWidth(GBool useOp) {
1924 w = nominalWidthX + op[0];
1925 wFP = nominalWidthXFP | fp[0];
1926 for (i = 1; i < nOps; ++i) {
1933 wFP = defaultWidthXFP;
1935 eexecDumpNum(0, gFalse);
1936 eexecDumpNum(w, wFP);
1940 void Type1CFontFile::eexecDumpNum(double x, GBool fpA) {
1946 if (x >= -32768 && x < 32768) {
1947 y = (int)(x * 256.0);
1949 buf[1] = (Guchar)(y >> 24);
1950 buf[2] = (Guchar)(y >> 16);
1951 buf[3] = (Guchar)(y >> 8);
1962 error(-1, "Type 2 fixed point constant out of range");
1966 if (y >= -107 && y <= 107) {
1967 buf[0] = (Guchar)(y + 139);
1969 } else if (y > 107 && y <= 1131) {
1971 buf[0] = (Guchar)((y >> 8) + 247);
1972 buf[1] = (Guchar)(y & 0xff);
1974 } else if (y < -107 && y >= -1131) {
1976 buf[0] = (Guchar)((y >> 8) + 251);
1977 buf[1] = (Guchar)(y & 0xff);
1981 buf[1] = (Guchar)(y >> 24);
1982 buf[2] = (Guchar)(y >> 16);
1983 buf[3] = (Guchar)(y >> 8);
1988 charBuf->append((char *)buf, n);
1991 void Type1CFontFile::eexecDumpOp1(int opA) {
1992 charBuf->append((char)opA);
1995 void Type1CFontFile::eexecDumpOp2(int opA) {
1996 charBuf->append((char)12);
1997 charBuf->append((char)opA);
2000 void Type1CFontFile::eexecWriteCharstring(Guchar *s, int n) {
2005 for (i = 0; i < n; ++i) {
2006 x = s[i] ^ (r1 >> 8);
2007 r1 = (x + r1) * 52845 + 22719;
2008 fputc(hexChars[x >> 4], out);
2009 fputc(hexChars[x & 0x0f], out);
2018 void Type1CFontFile::getDeltaInt(char *buf, char *key, double *opA,
2022 sprintf(buf, "/%s [", key);
2025 for (i = 0; i < n; ++i) {
2027 sprintf(buf, "%s%d", i > 0 ? " " : "", x);
2030 sprintf(buf, "] def\n");
2033 void Type1CFontFile::getDeltaReal(char *buf, char *key, double *opA,
2038 sprintf(buf, "/%s [", key);
2041 for (i = 0; i < n; ++i) {
2043 sprintf(buf, "%s%g", i > 0 ? " " : "", x);
2046 sprintf(buf, "] def\n");
2049 int Type1CFontFile::getIndexLen(Guchar *indexPtr) {
2050 return (int)getWord(indexPtr, 2);
2053 Guchar *Type1CFontFile::getIndexValPtr(Guchar *indexPtr, int i) {
2055 Guchar *idxStartPtr;
2057 n = (int)getWord(indexPtr, 2);
2058 offSize = indexPtr[2];
2059 idxStartPtr = indexPtr + 3 + (n + 1) * offSize - 1;
2060 return idxStartPtr + getWord(indexPtr + 3 + i * offSize, offSize);
2063 Guchar *Type1CFontFile::getIndexEnd(Guchar *indexPtr) {
2065 Guchar *idxStartPtr;
2067 n = (int)getWord(indexPtr, 2);
2068 offSize = indexPtr[2];
2069 idxStartPtr = indexPtr + 3 + (n + 1) * offSize - 1;
2070 return idxStartPtr + getWord(indexPtr + 3 + n * offSize, offSize);
2073 Guint Type1CFontFile::getWord(Guchar *ptr, int size) {
2078 for (i = 0; i < size; ++i) {
2079 x = (x << 8) + *ptr++;
2084 double Type1CFontFile::getNum(Guchar **ptr, GBool *isFP) {
2085 static char nybChars[16] = "0123456789.ee -";
2086 int b0, b, nyb0, nyb1;
2096 } else if (b0 == 28) {
2097 x = ((*ptr)[1] << 8) + (*ptr)[2];
2099 } else if (b0 == 29) {
2100 x = ((*ptr)[1] << 24) + ((*ptr)[2] << 16) + ((*ptr)[3] << 8) + (*ptr)[4];
2102 } else if (b0 == 30) {
2112 buf[i++] = nybChars[nyb0];
2125 buf[i++] = nybChars[nyb1];
2135 char *theLocale = setlocale(LC_NUMERIC, "C");
2137 setlocale(LC_NUMERIC, theLocale);
2140 } else if (b0 == 31) {
2142 } else if (b0 < 247) {
2145 } else if (b0 < 251) {
2146 x = ((b0 - 247) << 8) + (*ptr)[1] + 108;
2149 x = -((b0 - 251) << 8) - (*ptr)[1] - 108;
2155 char *Type1CFontFile::getString(int sid, char *buf) {
2156 Guchar *idxPtr0, *idxPtr1;
2160 strcpy(buf, type1CStdStrings[sid]);
2163 idxPtr0 = getIndexValPtr(stringIdxPtr, sid);
2164 idxPtr1 = getIndexValPtr(stringIdxPtr, sid + 1);
2165 if ((n = idxPtr1 - idxPtr0) > 255) {
2168 strncpy(buf, (char *)idxPtr0, n);
2174 //------------------------------------------------------------------------
2176 //------------------------------------------------------------------------
2182 // character code = number used as an element of a text string
2184 // character name = glyph name = name for a particular glyph within a
2187 // glyph index = position (within some internal table in the font)
2188 // where the instructions to draw a particular glyph are
2194 // Type 1 fonts contain:
2196 // Encoding: array of glyph names, maps char codes to glyph names
2198 // Encoding[charCode] = charName
2200 // CharStrings: dictionary of instructions, keyed by character names,
2201 // maps character name to glyph data
2203 // CharStrings[charName] = glyphData
2208 // TrueType fonts contain:
2210 // 'cmap' table: mapping from character code to glyph index; there may
2211 // be multiple cmaps in a TrueType font
2213 // cmap[charCode] = glyphIdx
2215 // 'post' table: mapping from glyph index to glyph name
2217 // post[glyphIdx] = glyphName
2222 // Type 42 fonts contain:
2224 // Encoding: array of glyph names, maps char codes to glyph names
2226 // Encoding[charCode] = charName
2228 // CharStrings: dictionary of glyph indexes, keyed by character names,
2229 // maps character name to glyph index
2231 // CharStrings[charName] = glyphIdx
2234 struct TTFontTableHdr {
2242 char *tag; // 4-byte tag
2243 GBool required; // required by the TrueType spec?
2246 // TrueType tables to be embedded in Type 42 fonts.
2247 // NB: the table names must be in alphabetical order here.
2248 #define nT42Tables 11
2249 static T42Table t42Tables[nT42Tables] = {
2262 #define t42HeadTable 3
2263 #define t42LocaTable 6
2264 #define t42GlyfTable 2
2266 // Glyph names in some arbitrary standard that Apple uses for their
2268 static char *macGlyphNames[258] = {
2529 enum T42FontIndexMode {
2531 t42FontModeCharCode,
2532 t42FontModeCharCodeOffset,
2536 TrueTypeFontFile::TrueTypeFontFile(char *fileA, int lenA) {
2544 // read table directory
2545 nTables = getUShort(4);
2546 tableHdrs = (TTFontTableHdr *)gmalloc(nTables * sizeof(TTFontTableHdr));
2548 for (i = 0; i < nTables; ++i) {
2549 tableHdrs[i].tag[0] = getByte(pos+0);
2550 tableHdrs[i].tag[1] = getByte(pos+1);
2551 tableHdrs[i].tag[2] = getByte(pos+2);
2552 tableHdrs[i].tag[3] = getByte(pos+3);
2553 tableHdrs[i].checksum = getULong(pos+4);
2554 tableHdrs[i].offset = getULong(pos+8);
2555 tableHdrs[i].length = getULong(pos+12);
2559 // check for tables that are required by both the TrueType spec
2560 // and the Type 42 spec
2561 if (seekTable("head") < 0 ||
2562 seekTable("hhea") < 0 ||
2563 seekTable("loca") < 0 ||
2564 seekTable("maxp") < 0 ||
2565 seekTable("glyf") < 0 ||
2566 seekTable("hmtx") < 0) {
2567 error(-1, "TrueType font file is missing a required table");
2571 // read the 'head' table
2572 pos = seekTable("head");
2573 bbox[0] = getShort(pos + 36);
2574 bbox[1] = getShort(pos + 38);
2575 bbox[2] = getShort(pos + 40);
2576 bbox[3] = getShort(pos + 42);
2577 locaFmt = getShort(pos + 50);
2579 // read the 'maxp' table
2580 pos = seekTable("maxp");
2581 nGlyphs = getUShort(pos + 4);
2584 TrueTypeFontFile::~TrueTypeFontFile() {
2588 for (i = 0; i < 256; ++i) {
2596 char *TrueTypeFontFile::getName() {
2600 char **TrueTypeFontFile::getEncoding() {
2602 int nCmaps, cmapPlatform, cmapEncoding, cmapFmt;
2603 int cmapLen, cmapOffset, cmapFirst;
2604 int segCnt, segStart, segEnd, segDelta, segOffset;
2608 int stringIdx, stringPos, n;
2614 //----- construct the (char code) -> (glyph idx) mapping
2616 // map everything to the missing glyph
2617 for (i = 0; i < 256; ++i) {
2621 // look for the 'cmap' table
2622 if ((pos = seekTable("cmap")) >= 0) {
2623 nCmaps = getUShort(pos+2);
2625 // if the font has a Windows-symbol cmap, use it;
2626 // otherwise, use the first cmap in the table
2627 for (i = 0; i < nCmaps; ++i) {
2628 cmapPlatform = getUShort(pos + 4 + 8*i);
2629 cmapEncoding = getUShort(pos + 4 + 8*i + 2);
2630 if (cmapPlatform == 3 && cmapEncoding == 0) {
2636 cmapPlatform = getUShort(pos + 4);
2637 cmapEncoding = getUShort(pos + 4 + 2);
2639 pos += getULong(pos + 4 + 8*i + 4);
2642 cmapFmt = getUShort(pos);
2644 case 0: // byte encoding table (Apple standard)
2645 cmapLen = getUShort(pos + 2);
2646 for (i = 0; i < cmapLen && i < 256; ++i) {
2647 cmap[i] = getByte(pos + 6 + i);
2650 case 4: // segment mapping to delta values (Microsoft standard)
2651 if (cmapPlatform == 3 && cmapEncoding == 0) {
2652 // Windows-symbol uses char codes 0xf000 - 0xf0ff
2653 cmapOffset = 0xf000;
2657 segCnt = getUShort(pos + 6) / 2;
2658 for (i = 0; i < segCnt; ++i) {
2659 segEnd = getUShort(pos + 14 + 2*i);
2660 segStart = getUShort(pos + 16 + 2*segCnt + 2*i);
2661 segDelta = getUShort(pos + 16 + 4*segCnt + 2*i);
2662 segOffset = getUShort(pos + 16 + 6*segCnt + 2*i);
2663 if (segStart - cmapOffset <= 0xff &&
2664 segEnd - cmapOffset >= 0) {
2665 for (j = (segStart - cmapOffset >= 0) ? segStart : cmapOffset;
2666 j <= segEnd && j - cmapOffset <= 0xff;
2668 if (segOffset == 0) {
2669 k = (j + segDelta) & 0xffff;
2671 k = getUShort(pos + 16 + 6*segCnt + 2*i +
2672 segOffset + 2 * (j - segStart));
2674 k = (k + segDelta) & 0xffff;
2677 cmap[j - cmapOffset] = k;
2682 case 6: // trimmed table mapping
2683 cmapFirst = getUShort(pos + 6);
2684 cmapLen = getUShort(pos + 8);
2685 for (i = cmapFirst; i < 256 && i < cmapFirst + cmapLen; ++i) {
2686 cmap[i] = getUShort(pos + 10 + 2*i);
2690 error(-1, "Unimplemented cmap format (%d) in TrueType font file",
2696 //----- construct the (glyph idx) -> (glyph name) mapping
2697 //----- and compute the (char code) -> (glyph name) mapping
2699 encoding = (char **)gmalloc(256 * sizeof(char *));
2700 for (i = 0; i < 256; ++i) {
2704 if ((pos = seekTable("post")) >= 0) {
2705 fmt = getULong(pos);
2708 if (fmt == 0x00010000) {
2709 for (i = 0; i < 256; ++i) {
2710 j = (cmap[i] < 258) ? cmap[i] : 0;
2711 encoding[i] = copyString(macGlyphNames[j]);
2715 } else if (fmt == 0x00020000) {
2717 stringPos = pos + 34 + 2*nGlyphs;
2718 for (i = 0; i < 256; ++i) {
2719 if (cmap[i] < nGlyphs) {
2720 j = getUShort(pos + 34 + 2 * cmap[i]);
2722 encoding[i] = copyString(macGlyphNames[j]);
2725 if (j != stringIdx) {
2726 for (stringIdx = 0, stringPos = pos + 34 + 2*nGlyphs;
2728 ++stringIdx, stringPos += 1 + getByte(stringPos)) ;
2730 n = getByte(stringPos);
2731 s = new GString(file + stringPos + 1, n);
2732 encoding[i] = copyString(s->getCString());
2738 encoding[i] = copyString(macGlyphNames[0]);
2743 } else if (fmt == 0x000280000) {
2744 for (i = 0; i < 256; ++i) {
2745 if (cmap[i] < nGlyphs) {
2746 j = i + getChar(pos + 32 + cmap[i]);
2750 encoding[i] = copyString(macGlyphNames[j]);
2753 // Ugh, just assume the Apple glyph set
2755 for (i = 0; i < 256; ++i) {
2756 j = (cmap[i] < 258) ? cmap[i] : 0;
2757 encoding[i] = copyString(macGlyphNames[j]);
2761 // no "post" table: assume the Apple glyph set
2763 for (i = 0; i < 256; ++i) {
2764 j = (cmap[i] < 258) ? cmap[i] : 0;
2765 encoding[i] = copyString(macGlyphNames[j]);
2772 void TrueTypeFontFile::convertToType42(char *name, char **encodingA,
2773 CharCodeToUnicode *toUnicode,
2774 GBool pdfFontHasEncoding, FILE *out) {
2776 fprintf(out, "%%!PS-TrueTypeFont-%g\n", getFixed(0));
2778 // begin the font dictionary
2779 fprintf(out, "10 dict begin\n");
2780 fprintf(out, "/FontName /%s def\n", name);
2781 fprintf(out, "/FontType 42 def\n");
2782 fprintf(out, "/FontMatrix [1 0 0 1 0 0] def\n");
2783 fprintf(out, "/FontBBox [%d %d %d %d] def\n",
2784 bbox[0], bbox[1], bbox[2], bbox[3]);
2785 fprintf(out, "/PaintType 0 def\n");
2787 // write the guts of the dictionary
2788 cvtEncoding(encodingA, out);
2789 cvtCharStrings(encodingA, toUnicode, pdfFontHasEncoding, out);
2790 cvtSfnts(out, NULL);
2792 // end the dictionary and define the font
2793 fprintf(out, "FontName currentdict end definefont pop\n");
2796 void TrueTypeFontFile::convertToCIDType2(char *name, Gushort *cidMap,
2797 int nCIDs, FILE *out) {
2802 fprintf(out, "%%!PS-TrueTypeFont-%g\n", getFixed(0));
2804 // begin the font dictionary
2805 fprintf(out, "20 dict begin\n");
2806 fprintf(out, "/CIDFontName /%s def\n", name);
2807 fprintf(out, "/CIDFontType 2 def\n");
2808 fprintf(out, "/FontType 42 def\n");
2809 fprintf(out, "/CIDSystemInfo 3 dict dup begin\n");
2810 fprintf(out, " /Registry (Adobe) def\n");
2811 fprintf(out, " /Ordering (Identity) def\n");
2812 fprintf(out, " /Supplement 0 def\n");
2813 fprintf(out, " end def\n");
2814 fprintf(out, "/GDBytes 2 def\n");
2816 fprintf(out, "/CIDCount %d def\n", nCIDs);
2817 if (nCIDs > 32767) {
2818 fprintf(out, "/CIDMap [");
2819 for (i = 0; i < nCIDs; i += 32768 - 16) {
2820 fprintf(out, "<\n");
2821 for (j = 0; j < 32768 - 16 && i+j < nCIDs; j += 16) {
2823 for (k = 0; k < 16 && i+j+k < nCIDs; ++k) {
2824 cid = cidMap[i+j+k];
2825 fprintf(out, "%02x%02x", (cid >> 8) & 0xff, cid & 0xff);
2832 fprintf(out, "] def\n");
2834 fprintf(out, "/CIDMap <\n");
2835 for (i = 0; i < nCIDs; i += 16) {
2837 for (j = 0; j < 16 && i+j < nCIDs; ++j) {
2839 fprintf(out, "%02x%02x", (cid >> 8) & 0xff, cid & 0xff);
2843 fprintf(out, "> def\n");
2846 // direct mapping - just fill the string(s) with s[i]=i
2847 fprintf(out, "/CIDCount %d def\n", nGlyphs);
2848 if (nGlyphs > 32767) {
2849 fprintf(out, "/CIDMap [\n");
2850 for (i = 0; i < nGlyphs; i += 32767) {
2851 j = nGlyphs - i < 32767 ? nGlyphs - i : 32767;
2852 fprintf(out, " %d string 0 1 %d {\n", 2 * j, j - 1);
2853 fprintf(out, " 2 copy dup 2 mul exch %d add -8 bitshift put\n", i);
2854 fprintf(out, " 1 index exch dup 2 mul 1 add exch %d add"
2855 " 255 and put\n", i);
2856 fprintf(out, " } for\n");
2858 fprintf(out, "] def\n");
2860 fprintf(out, "/CIDMap %d string\n", 2 * nGlyphs);
2861 fprintf(out, " 0 1 %d {\n", nGlyphs - 1);
2862 fprintf(out, " 2 copy dup 2 mul exch -8 bitshift put\n");
2863 fprintf(out, " 1 index exch dup 2 mul 1 add exch 255 and put\n");
2864 fprintf(out, " } for\n");
2865 fprintf(out, "def\n");
2868 fprintf(out, "/FontMatrix [1 0 0 1 0 0] def\n");
2869 fprintf(out, "/FontBBox [%d %d %d %d] def\n",
2870 bbox[0], bbox[1], bbox[2], bbox[3]);
2871 fprintf(out, "/PaintType 0 def\n");
2872 fprintf(out, "/Encoding [] readonly def\n");
2873 fprintf(out, "/CharStrings 1 dict dup begin\n");
2874 fprintf(out, " /.notdef 0 def\n");
2875 fprintf(out, " end readonly def\n");
2877 // write the guts of the dictionary
2878 cvtSfnts(out, NULL);
2880 // end the dictionary and define the font
2881 fprintf(out, "CIDFontName currentdict end /CIDFont defineresource pop\n");
2884 void TrueTypeFontFile::convertToType0(char *name, Gushort *cidMap,
2885 int nCIDs, FILE *out) {
2889 // write the Type 42 sfnts array
2890 sfntsName = (new GString(name))->append("_sfnts");
2891 cvtSfnts(out, sfntsName);
2894 // write the descendant Type 42 fonts
2895 n = cidMap ? nCIDs : nGlyphs;
2896 for (i = 0; i < n; i += 256) {
2897 fprintf(out, "10 dict begin\n");
2898 fprintf(out, "/FontName /%s_%02x def\n", name, i >> 8);
2899 fprintf(out, "/FontType 42 def\n");
2900 fprintf(out, "/FontMatrix [1 0 0 1 0 0] def\n");
2901 fprintf(out, "/FontBBox [%d %d %d %d] def\n",
2902 bbox[0], bbox[1], bbox[2], bbox[3]);
2903 fprintf(out, "/PaintType 0 def\n");
2904 fprintf(out, "/sfnts %s_sfnts def\n", name);
2905 fprintf(out, "/Encoding 256 array\n");
2906 for (j = 0; j < 256 && i+j < n; ++j) {
2907 fprintf(out, "dup %d /c%02x put\n", j, j);
2909 fprintf(out, "readonly def\n");
2910 fprintf(out, "/CharStrings 257 dict dup begin\n");
2911 fprintf(out, "/.notdef 0 def\n");
2912 for (j = 0; j < 256 && i+j < n; ++j) {
2913 fprintf(out, "/c%02x %d def\n", j, cidMap ? cidMap[i+j] : i+j);
2915 fprintf(out, "end readonly def\n");
2916 fprintf(out, "FontName currentdict end definefont pop\n");
2919 // write the Type 0 parent font
2920 fprintf(out, "16 dict begin\n");
2921 fprintf(out, "/FontName /%s def\n", name);
2922 fprintf(out, "/FontType 0 def\n");
2923 fprintf(out, "/FontMatrix [1 0 0 1 0 0] def\n");
2924 fprintf(out, "/FMapType 2 def\n");
2925 fprintf(out, "/Encoding [\n");
2926 for (i = 0; i < n; i += 256) {
2927 fprintf(out, "%d\n", i >> 8);
2929 fprintf(out, "] def\n");
2930 fprintf(out, "/FDepVector [\n");
2931 for (i = 0; i < n; i += 256) {
2932 fprintf(out, "/%s_%02x findfont\n", name, i >> 8);
2934 fprintf(out, "] def\n");
2935 fprintf(out, "FontName currentdict end definefont pop\n");
2938 int TrueTypeFontFile::getByte(int pos) {
2939 if (pos < 0 || pos >= len) {
2942 return file[pos] & 0xff;
2945 int TrueTypeFontFile::getChar(int pos) {
2948 if (pos < 0 || pos >= len) {
2951 x = file[pos] & 0xff;
2957 int TrueTypeFontFile::getUShort(int pos) {
2960 if (pos < 0 || pos+1 >= len) {
2963 x = file[pos] & 0xff;
2964 x = (x << 8) + (file[pos+1] & 0xff);
2968 int TrueTypeFontFile::getShort(int pos) {
2971 if (pos < 0 || pos+1 >= len) {
2974 x = file[pos] & 0xff;
2975 x = (x << 8) + (file[pos+1] & 0xff);
2981 Guint TrueTypeFontFile::getULong(int pos) {
2984 if (pos < 0 || pos+3 >= len) {
2987 x = file[pos] & 0xff;
2988 x = (x << 8) + (file[pos+1] & 0xff);
2989 x = (x << 8) + (file[pos+2] & 0xff);
2990 x = (x << 8) + (file[pos+3] & 0xff);
2994 double TrueTypeFontFile::getFixed(int pos) {
2998 y = getUShort(pos+2);
2999 return (double)x + (double)y / 65536;
3002 int TrueTypeFontFile::seekTable(char *tag) {
3005 for (i = 0; i < nTables; ++i) {
3006 if (!strncmp(tableHdrs[i].tag, tag, 4)) {
3007 return tableHdrs[i].offset;
3013 int TrueTypeFontFile::seekTableIdx(char *tag) {
3016 for (i = 0; i < nTables; ++i) {
3017 if (!strncmp(tableHdrs[i].tag, tag, 4)) {
3024 void TrueTypeFontFile::cvtEncoding(char **encodingA, FILE *out) {
3028 fprintf(out, "/Encoding 256 array\n");
3029 for (i = 0; i < 256; ++i) {
3030 if (!(name = encodingA[i])) {
3033 fprintf(out, "dup %d /%s put\n", i, name);
3035 fprintf(out, "readonly def\n");
3038 void TrueTypeFontFile::cvtCharStrings(char **encodingA,
3039 CharCodeToUnicode *toUnicode,
3040 GBool pdfFontHasEncoding, FILE *out) {
3041 int unicodeCmap, macRomanCmap, msSymbolCmap;
3042 int nCmaps, cmapPlatform, cmapEncoding, cmapFmt, cmapOffset;
3043 T42FontIndexMode mode;
3048 // always define '.notdef'
3049 fprintf(out, "/CharStrings 256 dict dup begin\n");
3050 fprintf(out, "/.notdef 0 def\n");
3052 // if there's no 'cmap' table, punt
3053 if ((pos = seekTable("cmap")) < 0) {
3057 // To match up with the Adobe-defined behaviour, we choose a cmap
3059 // 1. If the PDF font has an encoding:
3060 // 1a. If the TrueType font has a Microsoft Unicode cmap, use it,
3061 // and use the Unicode indexes, not the char codes.
3062 // 1b. If the TrueType font has a Macintosh Roman cmap, use it,
3063 // and reverse map the char names through MacRomanEncoding to
3065 // 2. If the PDF font does not have an encoding:
3066 // 2a. If the TrueType font has a Macintosh Roman cmap, use it,
3067 // and use char codes directly.
3068 // 2b. If the TrueType font has a Microsoft Symbol cmap, use it,
3069 // and use (0xf000 + char code).
3070 // 3. If none of these rules apply, use the first cmap and hope for
3071 // the best (this shouldn't happen).
3072 nCmaps = getUShort(pos+2);
3073 unicodeCmap = macRomanCmap = msSymbolCmap = -1;
3075 for (i = 0; i < nCmaps; ++i) {
3076 cmapPlatform = getUShort(pos + 4 + 8*i);
3077 cmapEncoding = getUShort(pos + 4 + 8*i + 2);
3078 if (cmapPlatform == 3 && cmapEncoding == 1) {
3080 } else if (cmapPlatform == 1 && cmapEncoding == 0) {
3082 } else if (cmapPlatform == 3 && cmapEncoding == 0) {
3087 mode = t42FontModeCharCode;
3088 if (pdfFontHasEncoding) {
3089 if (unicodeCmap >= 0) {
3091 mode = t42FontModeUnicode;
3092 } else if (macRomanCmap >= 0) {
3094 mode = t42FontModeMacRoman;
3097 if (macRomanCmap >= 0) {
3099 mode = t42FontModeCharCode;
3100 } else if (msSymbolCmap >= 0) {
3102 mode = t42FontModeCharCodeOffset;
3103 cmapOffset = 0xf000;
3106 cmapPlatform = getUShort(pos + 4 + 8*i);
3107 cmapEncoding = getUShort(pos + 4 + 8*i + 2);
3108 pos += getULong(pos + 4 + 8*i + 4);
3109 cmapFmt = getUShort(pos);
3110 if (cmapFmt != 0 && cmapFmt != 4 && cmapFmt != 6) {
3111 error(-1, "Unimplemented cmap format (%d) in TrueType font file",
3116 // map char name to glyph index:
3117 // 1. use encoding to map name to char code
3118 // 2. use cmap to map char code to glyph index
3119 j = 0; // make gcc happy
3120 for (i = 0; i < 256; ++i) {
3121 name = encodingA[i];
3122 if (name && strcmp(name, ".notdef")) {
3124 case t42FontModeUnicode:
3125 toUnicode->mapToUnicode((CharCode)i, &u, 1);
3128 case t42FontModeCharCode:
3131 case t42FontModeCharCodeOffset:
3134 case t42FontModeMacRoman:
3135 j = globalParams->getMacRomanCharCode(name);
3138 // note: Distiller (maybe Adobe's PS interpreter in general)
3139 // doesn't like TrueType fonts that have CharStrings entries
3140 // which point to nonexistent glyphs, hence the (k < nGlyphs)
3142 if ((k = getCmapEntry(cmapFmt, pos, j)) > 0 &&
3144 fprintf(out, "/%s %d def\n", name, k);
3150 fprintf(out, "end readonly def\n");
3153 int TrueTypeFontFile::getCmapEntry(int cmapFmt, int pos, int code) {
3154 int cmapLen, cmapFirst;
3155 int segCnt, segEnd, segStart, segDelta, segOffset;
3159 case 0: // byte encoding table (Apple standard)
3160 cmapLen = getUShort(pos + 2);
3161 if (code >= cmapLen) {
3164 return getByte(pos + 6 + code);
3166 case 4: // segment mapping to delta values (Microsoft standard)
3167 segCnt = getUShort(pos + 6) / 2;
3170 segEnd = getUShort(pos + 14 + 2*b);
3171 if (code > segEnd) {
3172 // malformed font -- the TrueType spec requires the last segEnd
3176 // invariant: seg[a].end < code <= seg[b].end
3179 segEnd = getUShort(pos + 14 + 2*m);
3180 if (segEnd < code) {
3186 segStart = getUShort(pos + 16 + 2*segCnt + 2*b);
3187 segDelta = getUShort(pos + 16 + 4*segCnt + 2*b);
3188 segOffset = getUShort(pos + 16 + 6*segCnt + 2*b);
3189 if (segOffset == 0) {
3190 i = (code + segDelta) & 0xffff;
3192 i = getUShort(pos + 16 + 6*segCnt + 2*b +
3193 segOffset + 2 * (code - segStart));
3195 i = (i + segDelta) & 0xffff;
3200 case 6: // trimmed table mapping
3201 cmapFirst = getUShort(pos + 6);
3202 cmapLen = getUShort(pos + 8);
3203 if (code < cmapFirst || code >= cmapFirst + cmapLen) {
3206 return getUShort(pos + 10 + 2*(code - cmapFirst));
3209 // shouldn't happen - this is checked earlier
3215 void TrueTypeFontFile::cvtSfnts(FILE *out, GString *name) {
3216 TTFontTableHdr newTableHdrs[nT42Tables];
3217 char tableDir[12 + nT42Tables*16];
3223 int pos, glyfPos, length, glyphLength, pad;
3226 // construct the 'head' table, zero out the font checksum
3227 memcpy(headTable, file + seekTable("head"), 54);
3228 headTable[8] = headTable[9] = headTable[10] = headTable[11] = (char)0;
3230 // read the original 'loca' table and construct the new one
3231 // (pad each glyph out to a multiple of 4 bytes)
3232 origLocaTable = (int *)gmalloc((nGlyphs + 1) * sizeof(int));
3233 pos = seekTable("loca");
3234 for (i = 0; i <= nGlyphs; ++i) {
3236 origLocaTable[i] = getULong(pos + 4*i);
3238 origLocaTable[i] = 2 * getUShort(pos + 2*i);
3241 locaTable = (char *)gmalloc((nGlyphs + 1) * (locaFmt ? 4 : 2));
3243 locaTable[0] = locaTable[1] = locaTable[2] = locaTable[3] = 0;
3245 locaTable[0] = locaTable[1] = 0;
3248 for (i = 1; i <= nGlyphs; ++i) {
3249 length = origLocaTable[i] - origLocaTable[i-1];
3251 length += 4 - (length & 3);
3255 locaTable[4*i ] = (char)(pos >> 24);
3256 locaTable[4*i+1] = (char)(pos >> 16);
3257 locaTable[4*i+2] = (char)(pos >> 8);
3258 locaTable[4*i+3] = (char) pos;
3260 locaTable[2*i ] = (char)(pos >> 9);
3261 locaTable[2*i+1] = (char)(pos >> 1);
3265 // count the number of tables
3267 for (i = 0; i < nT42Tables; ++i) {
3268 if (t42Tables[i].required ||
3269 seekTable(t42Tables[i].tag) >= 0) {
3274 // construct the new table headers, including table checksums
3275 // (pad each table out to a multiple of 4 bytes)
3276 pos = 12 + nNewTables*16;
3278 for (i = 0; i < nT42Tables; ++i) {
3280 checksum = 0; // make gcc happy
3281 if (i == t42HeadTable) {
3283 checksum = computeTableChecksum(headTable, 54);
3284 } else if (i == t42LocaTable) {
3285 length = (nGlyphs + 1) * (locaFmt ? 4 : 2);
3286 checksum = computeTableChecksum(locaTable, length);
3287 } else if (i == t42GlyfTable) {
3290 glyfPos = seekTable("glyf");
3291 for (j = 0; j < nGlyphs; ++j) {
3292 glyphLength = origLocaTable[j+1] - origLocaTable[j];
3293 pad = (glyphLength & 3) ? 4 - (glyphLength & 3) : 0;
3294 length += glyphLength + pad;
3295 checksum += computeTableChecksum(file + glyfPos + origLocaTable[j],
3299 if ((j = seekTableIdx(t42Tables[i].tag)) >= 0) {
3300 length = tableHdrs[j].length;
3301 checksum = computeTableChecksum(file + tableHdrs[j].offset, length);
3302 } else if (t42Tables[i].required) {
3303 error(-1, "Embedded TrueType font is missing a required table ('%s')",
3310 strncpy(newTableHdrs[k].tag, t42Tables[i].tag, 4);
3311 newTableHdrs[k].checksum = checksum;
3312 newTableHdrs[k].offset = pos;
3313 newTableHdrs[k].length = length;
3314 pad = (length & 3) ? 4 - (length & 3) : 0;
3315 pos += length + pad;
3320 // construct the table directory
3321 tableDir[0] = 0x00; // sfnt version
3325 tableDir[4] = 0; // numTables
3326 tableDir[5] = nNewTables;
3327 tableDir[6] = 0; // searchRange
3328 tableDir[7] = (char)128;
3329 tableDir[8] = 0; // entrySelector
3331 tableDir[10] = 0; // rangeShift
3332 tableDir[11] = (char)(16 * nNewTables - 128);
3334 for (i = 0; i < nNewTables; ++i) {
3335 tableDir[pos ] = newTableHdrs[i].tag[0];
3336 tableDir[pos+ 1] = newTableHdrs[i].tag[1];
3337 tableDir[pos+ 2] = newTableHdrs[i].tag[2];
3338 tableDir[pos+ 3] = newTableHdrs[i].tag[3];
3339 tableDir[pos+ 4] = (char)(newTableHdrs[i].checksum >> 24);
3340 tableDir[pos+ 5] = (char)(newTableHdrs[i].checksum >> 16);
3341 tableDir[pos+ 6] = (char)(newTableHdrs[i].checksum >> 8);
3342 tableDir[pos+ 7] = (char) newTableHdrs[i].checksum;
3343 tableDir[pos+ 8] = (char)(newTableHdrs[i].offset >> 24);
3344 tableDir[pos+ 9] = (char)(newTableHdrs[i].offset >> 16);
3345 tableDir[pos+10] = (char)(newTableHdrs[i].offset >> 8);
3346 tableDir[pos+11] = (char) newTableHdrs[i].offset;
3347 tableDir[pos+12] = (char)(newTableHdrs[i].length >> 24);
3348 tableDir[pos+13] = (char)(newTableHdrs[i].length >> 16);
3349 tableDir[pos+14] = (char)(newTableHdrs[i].length >> 8);
3350 tableDir[pos+15] = (char) newTableHdrs[i].length;
3354 // compute the font checksum and store it in the head table
3355 checksum = computeTableChecksum(tableDir, 12 + nNewTables*16);
3356 for (i = 0; i < nNewTables; ++i) {
3357 checksum += newTableHdrs[i].checksum;
3359 checksum = 0xb1b0afba - checksum; // because the TrueType spec says so
3360 headTable[ 8] = (char)(checksum >> 24);
3361 headTable[ 9] = (char)(checksum >> 16);
3362 headTable[10] = (char)(checksum >> 8);
3363 headTable[11] = (char) checksum;
3365 // start the sfnts array
3367 fprintf(out, "/%s [\n", name->getCString());
3369 fprintf(out, "/sfnts [\n");
3372 // write the table directory
3373 dumpString(tableDir, 12 + nNewTables*16, out);
3376 for (i = 0; i < nNewTables; ++i) {
3377 if (i == t42HeadTable) {
3378 dumpString(headTable, 54, out);
3379 } else if (i == t42LocaTable) {
3380 length = (nGlyphs + 1) * (locaFmt ? 4 : 2);
3381 dumpString(locaTable, length, out);
3382 } else if (i == t42GlyfTable) {
3383 glyfPos = seekTable("glyf");
3384 for (j = 0; j < nGlyphs; ++j) {
3385 length = origLocaTable[j+1] - origLocaTable[j];
3387 dumpString(file + glyfPos + origLocaTable[j], length, out);
3391 // length == 0 means the table is missing and the error was
3392 // already reported during the construction of the table
3394 if ((length = newTableHdrs[i].length) > 0) {
3395 dumpString(file + seekTable(t42Tables[i].tag), length, out);
3400 // end the sfnts array
3401 fprintf(out, "] def\n");
3403 gfree(origLocaTable);
3407 void TrueTypeFontFile::dumpString(char *s, int length, FILE *out) {
3411 for (i = 0; i < length; i += 32) {
3412 for (j = 0; j < 32 && i+j < length; ++j) {
3413 fprintf(out, "%02X", s[i+j] & 0xff);
3415 if (i % (65536 - 32) == 65536 - 64) {
3416 fprintf(out, ">\n<");
3417 } else if (i+32 < length) {
3422 pad = 4 - (length & 3);
3423 for (i = 0; i < pad; ++i) {
3427 // add an extra zero byte because the Adobe Type 42 spec says so
3428 fprintf(out, "00>\n");
3431 Guint TrueTypeFontFile::computeTableChecksum(char *data, int length) {
3432 Guint checksum, word;
3436 for (i = 0; i+3 < length; i += 4) {
3437 word = ((data[i ] & 0xff) << 24) +
3438 ((data[i+1] & 0xff) << 16) +
3439 ((data[i+2] & 0xff) << 8) +
3446 switch (length & 3) {
3448 word |= (data[i+2] & 0xff) << 8;
3450 word |= (data[i+1] & 0xff) << 16;
3452 word |= (data[i ] & 0xff) << 24;
3460 void TrueTypeFontFile::writeTTF(FILE *out) {
3461 static char cmapTab[20] = {
3462 0, 0, // table version number
3463 0, 1, // number of encoding tables
3464 0, 1, // platform ID
3465 0, 0, // encoding ID
3466 0, 0, 0, 12, // offset of subtable
3467 0, 0, // subtable format
3468 0, 1, // subtable length
3469 0, 1, // subtable version
3470 0, // map char 0 -> glyph 0
3471 0 // pad to multiple of four bytes
3473 static char nameTab[8] = {
3475 0, 0, // number of name records
3476 0, 6, // offset to start of string storage
3477 0, 0 // pad to multiple of four bytes
3479 static char postTab[32] = {
3480 0, 1, 0, 0, // format
3481 0, 0, 0, 0, // italic angle
3482 0, 0, // underline position
3483 0, 0, // underline thickness
3484 0, 0, 0, 0, // fixed pitch
3485 0, 0, 0, 0, // min Type 42 memory
3486 0, 0, 0, 0, // max Type 42 memory
3487 0, 0, 0, 0, // min Type 1 memory
3488 0, 0, 0, 0 // max Type 1 memory
3490 GBool haveCmap, haveName, havePost;
3491 GBool dirCmap, dirName, dirPost;
3492 int nNewTables, nAllTables, pad;
3497 // check for missing tables
3498 haveCmap = seekTable("cmap") >= 0;
3499 haveName = seekTable("name") >= 0;
3500 havePost = seekTable("post") >= 0;
3501 nNewTables = (haveCmap ? 0 : 1) + (haveName ? 0 : 1) + (havePost ? 0 : 1);
3503 // none are missing - write the TTF file as is
3504 fwrite(file, 1, len, out);
3508 // construct the new table directory
3509 nAllTables = nTables + nNewTables;
3510 tableDir = (char *)gmalloc(12 + nAllTables * 16);
3511 memcpy(tableDir, file, 12 + nTables * 16);
3512 tableDir[4] = (char)((nAllTables >> 8) & 0xff);
3513 tableDir[5] = (char)(nAllTables & 0xff);
3514 for (i = -1, t = (Guint)nAllTables; t; ++i, t >>= 1) ;
3516 tableDir[6] = (char)((t >> 8) & 0xff);
3517 tableDir[7] = (char)(t & 0xff);
3518 tableDir[8] = (char)((i >> 8) & 0xff);
3519 tableDir[9] = (char)(i & 0xff);
3520 t = nAllTables * 16 - t;
3521 tableDir[10] = (char)((t >> 8) & 0xff);
3522 tableDir[11] = (char)(t & 0xff);
3527 pad = (len & 3) ? 4 - (len & 3) : 0;
3528 pos = len + pad + 16 * nNewTables;
3529 for (i = 0; i < nTables; ++i) {
3530 if (!dirCmap && strncmp(tableHdrs[i].tag, "cmap", 4) > 0) {
3531 tableDir[12 + 16*j ] = 'c';
3532 tableDir[12 + 16*j + 1] = 'm';
3533 tableDir[12 + 16*j + 2] = 'a';
3534 tableDir[12 + 16*j + 3] = 'p';
3535 tableDir[12 + 16*j + 4] = (char)0; //~ should compute the checksum
3536 tableDir[12 + 16*j + 5] = (char)0;
3537 tableDir[12 + 16*j + 6] = (char)0;
3538 tableDir[12 + 16*j + 7] = (char)0;
3539 tableDir[12 + 16*j + 8] = (char)((pos >> 24) & 0xff);
3540 tableDir[12 + 16*j + 9] = (char)((pos >> 16) & 0xff);
3541 tableDir[12 + 16*j + 10] = (char)((pos >> 8) & 0xff);
3542 tableDir[12 + 16*j + 11] = (char)( pos & 0xff);
3543 tableDir[12 + 16*j + 12] = (char)((sizeof(cmapTab) >> 24) & 0xff);
3544 tableDir[12 + 16*j + 13] = (char)((sizeof(cmapTab) >> 16) & 0xff);
3545 tableDir[12 + 16*j + 14] = (char)((sizeof(cmapTab) >> 8) & 0xff);
3546 tableDir[12 + 16*j + 15] = (char)( sizeof(cmapTab) & 0xff);
3547 pos += sizeof(cmapTab);
3551 if (!dirName && strncmp(tableHdrs[i].tag, "name", 4) > 0) {
3552 tableDir[12 + 16*j ] = 'n';
3553 tableDir[12 + 16*j + 1] = 'a';
3554 tableDir[12 + 16*j + 2] = 'm';
3555 tableDir[12 + 16*j + 3] = 'e';
3556 tableDir[12 + 16*j + 4] = (char)0; //~ should compute the checksum
3557 tableDir[12 + 16*j + 5] = (char)0;
3558 tableDir[12 + 16*j + 6] = (char)0;
3559 tableDir[12 + 16*j + 7] = (char)0;
3560 tableDir[12 + 16*j + 8] = (char)((pos >> 24) & 0xff);
3561 tableDir[12 + 16*j + 9] = (char)((pos >> 16) & 0xff);
3562 tableDir[12 + 16*j + 10] = (char)((pos >> 8) & 0xff);
3563 tableDir[12 + 16*j + 11] = (char)( pos & 0xff);
3564 tableDir[12 + 16*j + 12] = (char)((sizeof(nameTab) >> 24) & 0xff);
3565 tableDir[12 + 16*j + 13] = (char)((sizeof(nameTab) >> 16) & 0xff);
3566 tableDir[12 + 16*j + 14] = (char)((sizeof(nameTab) >> 8) & 0xff);
3567 tableDir[12 + 16*j + 15] = (char)( sizeof(nameTab) & 0xff);
3568 pos += sizeof(nameTab);
3572 if (!dirName && strncmp(tableHdrs[i].tag, "post", 4) > 0) {
3573 tableDir[12 + 16*j ] = 'p';
3574 tableDir[12 + 16*j + 1] = 'o';
3575 tableDir[12 + 16*j + 2] = 's';
3576 tableDir[12 + 16*j + 3] = 't';
3577 tableDir[12 + 16*j + 4] = (char)0; //~ should compute the checksum
3578 tableDir[12 + 16*j + 5] = (char)0;
3579 tableDir[12 + 16*j + 6] = (char)0;
3580 tableDir[12 + 16*j + 7] = (char)0;
3581 tableDir[12 + 16*j + 8] = (char)((pos >> 24) & 0xff);
3582 tableDir[12 + 16*j + 9] = (char)((pos >> 16) & 0xff);
3583 tableDir[12 + 16*j + 10] = (char)((pos >> 8) & 0xff);
3584 tableDir[12 + 16*j + 11] = (char)( pos & 0xff);
3585 tableDir[12 + 16*j + 12] = (char)((sizeof(postTab) >> 24) & 0xff);
3586 tableDir[12 + 16*j + 13] = (char)((sizeof(postTab) >> 16) & 0xff);
3587 tableDir[12 + 16*j + 14] = (char)((sizeof(postTab) >> 8) & 0xff);
3588 tableDir[12 + 16*j + 15] = (char)( sizeof(postTab) & 0xff);
3589 pos += sizeof(postTab);
3593 memcpy(&tableDir[12 + 16*j], file + 12 + 16*i, 16);
3594 t = tableHdrs[i].offset + nNewTables * 16;
3595 tableDir[12 + 16*j + 8] = (char)((t >> 24) & 0xff);
3596 tableDir[12 + 16*j + 9] = (char)((t >> 16) & 0xff);
3597 tableDir[12 + 16*j + 10] = (char)((t >> 8) & 0xff);
3598 tableDir[12 + 16*j + 11] = (char)( t & 0xff);
3602 tableDir[12 + 16*j ] = 'c';
3603 tableDir[12 + 16*j + 1] = 'm';
3604 tableDir[12 + 16*j + 2] = 'a';
3605 tableDir[12 + 16*j + 3] = 'p';
3606 tableDir[12 + 16*j + 4] = (char)0; //~ should compute the checksum
3607 tableDir[12 + 16*j + 5] = (char)0;
3608 tableDir[12 + 16*j + 6] = (char)0;
3609 tableDir[12 + 16*j + 7] = (char)0;
3610 tableDir[12 + 16*j + 8] = (char)((pos >> 24) & 0xff);
3611 tableDir[12 + 16*j + 9] = (char)((pos >> 16) & 0xff);
3612 tableDir[12 + 16*j + 10] = (char)((pos >> 8) & 0xff);
3613 tableDir[12 + 16*j + 11] = (char)( pos & 0xff);
3614 tableDir[12 + 16*j + 12] = (char)((sizeof(cmapTab) >> 24) & 0xff);
3615 tableDir[12 + 16*j + 13] = (char)((sizeof(cmapTab) >> 16) & 0xff);
3616 tableDir[12 + 16*j + 14] = (char)((sizeof(cmapTab) >> 8) & 0xff);
3617 tableDir[12 + 16*j + 15] = (char)( sizeof(cmapTab) & 0xff);
3618 pos += sizeof(cmapTab);
3623 tableDir[12 + 16*j ] = 'n';
3624 tableDir[12 + 16*j + 1] = 'a';
3625 tableDir[12 + 16*j + 2] = 'm';
3626 tableDir[12 + 16*j + 3] = 'e';
3627 tableDir[12 + 16*j + 4] = (char)0; //~ should compute the checksum
3628 tableDir[12 + 16*j + 5] = (char)0;
3629 tableDir[12 + 16*j + 6] = (char)0;
3630 tableDir[12 + 16*j + 7] = (char)0;
3631 tableDir[12 + 16*j + 8] = (char)((pos >> 24) & 0xff);
3632 tableDir[12 + 16*j + 9] = (char)((pos >> 16) & 0xff);
3633 tableDir[12 + 16*j + 10] = (char)((pos >> 8) & 0xff);
3634 tableDir[12 + 16*j + 11] = (char)( pos & 0xff);
3635 tableDir[12 + 16*j + 12] = (char)((sizeof(nameTab) >> 24) & 0xff);
3636 tableDir[12 + 16*j + 13] = (char)((sizeof(nameTab) >> 16) & 0xff);
3637 tableDir[12 + 16*j + 14] = (char)((sizeof(nameTab) >> 8) & 0xff);
3638 tableDir[12 + 16*j + 15] = (char)( sizeof(nameTab) & 0xff);
3639 pos += sizeof(nameTab);
3644 tableDir[12 + 16*j ] = 'p';
3645 tableDir[12 + 16*j + 1] = 'o';
3646 tableDir[12 + 16*j + 2] = 's';
3647 tableDir[12 + 16*j + 3] = 't';
3648 tableDir[12 + 16*j + 4] = (char)0; //~ should compute the checksum
3649 tableDir[12 + 16*j + 5] = (char)0;
3650 tableDir[12 + 16*j + 6] = (char)0;
3651 tableDir[12 + 16*j + 7] = (char)0;
3652 tableDir[12 + 16*j + 8] = (char)((pos >> 24) & 0xff);
3653 tableDir[12 + 16*j + 9] = (char)((pos >> 16) & 0xff);
3654 tableDir[12 + 16*j + 10] = (char)((pos >> 8) & 0xff);
3655 tableDir[12 + 16*j + 11] = (char)( pos & 0xff);
3656 tableDir[12 + 16*j + 12] = (char)((sizeof(postTab) >> 24) & 0xff);
3657 tableDir[12 + 16*j + 13] = (char)((sizeof(postTab) >> 16) & 0xff);
3658 tableDir[12 + 16*j + 14] = (char)((sizeof(postTab) >> 8) & 0xff);
3659 tableDir[12 + 16*j + 15] = (char)( sizeof(postTab) & 0xff);
3660 pos += sizeof(postTab);
3665 // write the table directory
3666 fwrite(tableDir, 1, 12 + 16 * nAllTables, out);
3668 // write the original tables
3669 fwrite(file + 12 + 16*nTables, 1, len - (12 + 16*nTables), out);
3671 // write the new tables
3672 for (i = 0; i < pad; ++i) {
3673 fputc((char)0, out);
3676 fwrite(cmapTab, 1, sizeof(cmapTab), out);
3679 fwrite(nameTab, 1, sizeof(nameTab), out);
3682 fwrite(postTab, 1, sizeof(postTab), out);