1 //========================================================================
5 // Copyright 1999-2002 Glyph & Cog, LLC
7 //========================================================================
10 #pragma implementation
21 #include "GlobalParams.h"
22 #include "CharCodeToUnicode.h"
23 #include "FontEncodingTables.h"
26 #include "CompactFontTables.h"
28 //------------------------------------------------------------------------
30 static inline char *nextLine(char *line, char *end) {
31 while (line < end && *line != '\n' && *line != '\r')
33 while (line < end && *line == '\n' || *line == '\r')
38 static char hexChars[17] = "0123456789ABCDEF";
40 //------------------------------------------------------------------------
42 //------------------------------------------------------------------------
44 FontFile::FontFile() {
47 FontFile::~FontFile() {
50 //------------------------------------------------------------------------
52 //------------------------------------------------------------------------
54 Type1FontFile::Type1FontFile(char *file, int len) {
55 char *line, *line1, *p, *p2;
62 encoding = (char **)gmalloc(256 * sizeof(char *));
63 for (i = 0; i < 256; ++i) {
66 haveEncoding = gFalse;
68 for (i = 1, line = file;
69 i <= 100 && line < file + len && !haveEncoding;
73 if (!strncmp(line, "/FontName", 9)) {
74 strncpy(buf, line, 255);
76 if ((p = strchr(buf+9, '/')) &&
77 (p = strtok(p+1, " \t\n\r"))) {
80 line = nextLine(line, file + len);
83 } else if (!strncmp(line, "/Encoding StandardEncoding def", 30)) {
84 for (j = 0; j < 256; ++j) {
85 if (standardEncoding[j]) {
86 encoding[j] = copyString(standardEncoding[j]);
90 } else if (!strncmp(line, "/Encoding 256 array", 19)) {
91 for (j = 0; j < 300; ++j) {
92 line1 = nextLine(line, file + len);
93 if ((n = line1 - line) > 255) {
96 strncpy(buf, line, n);
98 for (p = buf; *p == ' ' || *p == '\t'; ++p) ;
99 if (!strncmp(p, "dup", 3)) {
100 for (p += 3; *p == ' ' || *p == '\t'; ++p) ;
101 for (p2 = p; *p2 >= '0' && *p2 <= '9'; ++p2) ;
105 if ((code = atoi(p)) < 256) {
107 for (p = p2; *p == ' ' || *p == '\t'; ++p) ;
110 for (p2 = p; *p2 && *p2 != ' ' && *p2 != '\t'; ++p2) ;
112 encoding[code] = copyString(p);
117 if (strtok(buf, " \t") &&
118 (p = strtok(NULL, " \t\n\r")) && !strcmp(p, "def")) {
124 //~ check for getinterval/putinterval junk
125 haveEncoding = gTrue;
128 line = nextLine(line, file + len);
133 Type1FontFile::~Type1FontFile() {
139 for (i = 0; i < 256; ++i) {
145 //------------------------------------------------------------------------
147 //------------------------------------------------------------------------
149 struct Type1CTopDict {
158 double underlinePosition;
159 double underlineThickness;
162 double fontMatrix[6];
172 //----- CIDFont entries
180 struct Type1CPrivateDict {
183 double defaultWidthX;
184 GBool defaultWidthXFP;
185 double nominalWidthX;
186 GBool nominalWidthXFP;
189 Type1CFontFile::Type1CFontFile(char *fileA, int lenA) {
190 Guchar *nameIdxPtr, *idxPtr0, *idxPtr1;
197 // some tools embed Type 1C fonts with an extra whitespace char at
199 if (file[0] != '\x01') {
204 topOffSize = file[3] & 0xff;
206 // read name index (first font only)
207 nameIdxPtr = (Guchar *)file + (file[2] & 0xff);
208 idxPtr0 = getIndexValPtr(nameIdxPtr, 0);
209 idxPtr1 = getIndexValPtr(nameIdxPtr, 1);
210 name = new GString((char *)idxPtr0, idxPtr1 - idxPtr0);
212 topDictIdxPtr = getIndexEnd(nameIdxPtr);
213 stringIdxPtr = getIndexEnd(topDictIdxPtr);
214 gsubrIdxPtr = getIndexEnd(stringIdxPtr);
217 Type1CFontFile::~Type1CFontFile() {
222 for (i = 0; i < 256; ++i) {
229 char *Type1CFontFile::getName() {
230 return name->getCString();
233 char **Type1CFontFile::getEncoding() {
235 readNameAndEncoding();
240 void Type1CFontFile::readNameAndEncoding() {
242 Guchar *idxPtr0, *idxPtr1, *ptr;
244 int nCodes, nRanges, nLeft, nSups;
246 int charset, enc, charstrings;
254 encoding = (char **)gmalloc(256 * sizeof(char *));
255 for (i = 0; i < 256; ++i) {
259 // read top dict (first font only)
260 idxPtr0 = getIndexValPtr(topDictIdxPtr, 0);
261 idxPtr1 = getIndexValPtr(topDictIdxPtr, 1);
262 charset = enc = charstrings = 0;
265 while (ptr < idxPtr1) {
266 if (*ptr <= 27 || *ptr == 31) {
269 key = (key << 8) | *ptr++;
271 if (key == 0x0f) { // charset
272 charset = (int)op[0];
273 } else if (key == 0x10) { // encoding
275 } else if (key == 0x11) { // charstrings
276 charstrings = (int)op[0];
280 x = getNum(&ptr, &isFP);
287 // get number of glyphs from charstrings index
288 nGlyphs = getIndexLen((Guchar *)file + charstrings);
290 // read charset (GID -> name mapping)
291 glyphNames = readCharset(charset, nGlyphs);
293 // read encoding (GID -> code mapping)
295 for (i = 0; i < 256; ++i) {
296 if (standardEncoding[i]) {
297 encoding[i] = copyString(standardEncoding[i]);
300 } else if (enc == 1) {
301 for (i = 0; i < 256; ++i) {
302 if (expertEncoding[i]) {
303 encoding[i] = copyString(expertEncoding[i]);
307 ptr = (Guchar *)file + enc;
309 if ((encFormat & 0x7f) == 0) {
311 if (nCodes > nGlyphs) {
314 for (i = 1; i < nCodes; ++i) {
316 encoding[c] = copyString(getString(glyphNames[i], buf));
318 } else if ((encFormat & 0x7f) == 1) {
321 for (i = 0; i < nRanges; ++i) {
324 for (j = 0; j <= nLeft && nCodes < nGlyphs; ++j) {
325 encoding[c] = copyString(getString(glyphNames[nCodes], buf));
331 if (encFormat & 0x80) {
333 for (i = 0; i < nSups; ++i) {
335 sid = getWord(ptr, 2);
337 encoding[c] = copyString(getString(sid, buf));
347 void Type1CFontFile::convertToType1(FILE *outA) {
349 Type1CPrivateDict privateDict;
350 char buf[256], eBuf[256];
351 Guchar *idxPtr0, *idxPtr1, *subrsIdxPtr, *charStringsIdxPtr, *ptr;
352 int nGlyphs, nCodes, nRanges, nLeft, nSups;
354 int encFormat, nSubrs, nCharStrings;
360 // read top dict (first font only)
364 //~ ... global subrs are unimplemented
366 // write header and font dictionary, up to encoding
367 fprintf(out, "%%!FontType1-1.0: %s", name->getCString());
368 if (dict.version != 0) {
369 fprintf(out, "%s", getString(dict.version, buf));
372 fprintf(out, "11 dict begin\n");
373 fprintf(out, "/FontInfo 10 dict dup begin\n");
374 if (dict.version != 0) {
375 fprintf(out, "/version (%s) readonly def\n",
376 getString(dict.version, buf));
378 if (dict.notice != 0) {
379 fprintf(out, "/Notice (%s) readonly def\n",
380 getString(dict.notice, buf));
382 if (dict.copyright != 0) {
383 fprintf(out, "/Copyright (%s) readonly def\n",
384 getString(dict.copyright, buf));
386 if (dict.fullName != 0) {
387 fprintf(out, "/FullName (%s) readonly def\n",
388 getString(dict.fullName, buf));
390 if (dict.familyName != 0) {
391 fprintf(out, "/FamilyName (%s) readonly def\n",
392 getString(dict.familyName, buf));
394 if (dict.weight != 0) {
395 fprintf(out, "/Weight (%s) readonly def\n",
396 getString(dict.weight, buf));
398 fprintf(out, "/isFixedPitch %s def\n", dict.isFixedPitch ? "true" : "false");
399 fprintf(out, "/ItalicAngle %g def\n", dict.italicAngle);
400 fprintf(out, "/UnderlinePosition %g def\n", dict.underlinePosition);
401 fprintf(out, "/UnderlineThickness %g def\n", dict.underlineThickness);
402 fprintf(out, "end readonly def\n");
403 fprintf(out, "/FontName /%s def\n", name->getCString());
404 fprintf(out, "/PaintType %d def\n", dict.paintType);
405 fprintf(out, "/FontType 1 def\n");
406 fprintf(out, "/FontMatrix [%g %g %g %g %g %g] readonly def\n",
407 dict.fontMatrix[0], dict.fontMatrix[1], dict.fontMatrix[2],
408 dict.fontMatrix[3], dict.fontMatrix[4], dict.fontMatrix[5]);
409 fprintf(out, "/FontBBox [%g %g %g %g] readonly def\n",
410 dict.fontBBox[0], dict.fontBBox[1],
411 dict.fontBBox[2], dict.fontBBox[3]);
412 fprintf(out, "/StrokeWidth %g def\n", dict.strokeWidth);
413 if (dict.uniqueID != 0) {
414 fprintf(out, "/UniqueID %d def\n", dict.uniqueID);
417 // get number of glyphs from charstrings index
418 nGlyphs = getIndexLen((Guchar *)file + dict.charStrings);
421 glyphNames = readCharset(dict.charset, nGlyphs);
423 // read encoding (glyph -> code mapping), write Type 1 encoding
424 fprintf(out, "/Encoding ");
425 if (dict.encoding == 0) {
426 fprintf(out, "StandardEncoding def\n");
428 fprintf(out, "256 array\n");
429 fprintf(out, "0 1 255 {1 index exch /.notdef put} for\n");
430 if (dict.encoding == 1) {
431 for (i = 0; i < 256; ++i) {
432 if (expertEncoding[i]) {
433 fprintf(out, "dup %d /%s put\n", i, expertEncoding[i]);
437 ptr = (Guchar *)file + dict.encoding;
439 if ((encFormat & 0x7f) == 0) {
441 if (nCodes > nGlyphs) {
444 for (i = 1; i < nCodes; ++i) {
446 fprintf(out, "dup %d /%s put\n",
447 c, getString(glyphNames[i], buf));
449 } else if ((encFormat & 0x7f) == 1) {
452 for (i = 0; i < nRanges; ++i) {
455 for (j = 0; j <= nLeft && nCodes < nGlyphs; ++j) {
456 fprintf(out, "dup %d /%s put\n",
457 c, getString(glyphNames[nCodes], buf));
463 if (encFormat & 0x80) {
465 for (i = 0; i < nSups; ++i) {
467 sid = getWord(ptr, 2);
469 fprintf(out, "dup %d /%s put\n", c, getString(sid, buf));
473 fprintf(out, "readonly def\n");
475 fprintf(out, "currentdict end\n");
477 // start the binary section
478 fprintf(out, "currentfile eexec\n");
482 // get private dictionary
483 eexecWrite("\x83\xca\x73\xd5");
484 eexecWrite("dup /Private 32 dict dup begin\n");
485 eexecWrite("/RD {string currentfile exch readstring pop} executeonly def\n");
486 eexecWrite("/ND {noaccess def} executeonly def\n");
487 eexecWrite("/NP {noaccess put} executeonly def\n");
488 eexecWrite("/MinFeature {16 16} ND\n");
489 readPrivateDict(&privateDict, dict.privateOffset, dict.privateSize);
490 eexecWrite(privateDict.dictData->getCString());
491 defaultWidthX = privateDict.defaultWidthX;
492 defaultWidthXFP = privateDict.defaultWidthXFP;
493 nominalWidthX = privateDict.nominalWidthX;
494 nominalWidthXFP = privateDict.nominalWidthXFP;
497 if (privateDict.subrsOffset != 0) {
498 subrsIdxPtr = (Guchar *)file + dict.privateOffset +
499 privateDict.subrsOffset;
500 nSubrs = getIndexLen(subrsIdxPtr);
501 sprintf(eBuf, "/Subrs %d array\n", nSubrs);
503 idxPtr1 = getIndexValPtr(subrsIdxPtr, 0);
504 for (i = 0; i < nSubrs; ++i) {
506 idxPtr1 = getIndexValPtr(subrsIdxPtr, i+1);
507 n = idxPtr1 - idxPtr0;
508 #if 1 //~ Type 2 subrs are unimplemented
509 error(-1, "Unimplemented Type 2 subrs");
511 sprintf(eBuf, "dup %d %d RD ", i, n);
513 eexecCvtGlyph(idxPtr0, n);
521 charStringsIdxPtr = (Guchar *)file + dict.charStrings;
522 nCharStrings = getIndexLen(charStringsIdxPtr);
523 sprintf(eBuf, "2 index /CharStrings %d dict dup begin\n", nCharStrings);
525 idxPtr1 = getIndexValPtr(charStringsIdxPtr, 0);
526 for (i = 0; i < nCharStrings; ++i) {
528 idxPtr1 = getIndexValPtr(charStringsIdxPtr, i+1);
529 n = idxPtr1 - idxPtr0;
530 eexecCvtGlyph(getString(glyphNames[i], buf), idxPtr0, n);
534 eexecWrite("readonly put\n");
535 eexecWrite("noaccess put\n");
536 eexecWrite("dup /FontName get exch definefont pop\n");
537 eexecWrite("mark currentfile closefile\n");
543 for (i = 0; i < 8; ++i) {
544 fprintf(out, "0000000000000000000000000000000000000000000000000000000000000000\n");
546 fprintf(out, "cleartomark\n");
549 delete privateDict.dictData;
550 if (dict.charset > 2) {
555 void Type1CFontFile::convertToCIDType0(char *psName, FILE *outA) {
557 Type1CPrivateDict *privateDicts;
558 GString *charStrings;
559 int *charStringOffsets;
563 Guchar *charStringsIdxPtr, *fdArrayIdx, *idxPtr0, *idxPtr1, *ptr;
565 int nGlyphs, nCIDs, gdBytes, nFDs;
566 int fdSelectFmt, nRanges, gid0, gid1, fd, offset;
574 fprintf(out, "/CIDInit /ProcSet findresource begin\n");
576 // read top dict (first font only)
579 // read the FDArray dictionaries and Private dictionaries
580 if (dict.fdArrayOffset == 0) {
582 privateDicts = (Type1CPrivateDict *)
583 gmalloc(nFDs * sizeof(Type1CPrivateDict));
584 privateDicts[0].dictData = new GString();
585 privateDicts[0].subrsOffset = 0;
586 privateDicts[0].defaultWidthX = 0;
587 privateDicts[0].defaultWidthXFP = gFalse;
588 privateDicts[0].nominalWidthX = 0;
589 privateDicts[0].nominalWidthXFP = gFalse;
591 fdArrayIdx = (Guchar *)file + dict.fdArrayOffset;
592 nFDs = getIndexLen(fdArrayIdx);
593 privateDicts = (Type1CPrivateDict *)
594 gmalloc(nFDs * sizeof(Type1CPrivateDict));
595 idxPtr1 = getIndexValPtr(fdArrayIdx, 0);
596 for (i = 0; i < nFDs; ++i) {
597 privateDicts[i].dictData = NULL;
599 idxPtr1 = getIndexValPtr(fdArrayIdx, i + 1);
602 while (ptr < idxPtr1) {
603 if (*ptr <= 27 || *ptr == 31) {
606 key = (key << 8) | *ptr++;
609 readPrivateDict(&privateDicts[i], (int)op[1], (int)op[0]);
613 x = getNum(&ptr, &isFP);
620 if (!privateDicts[i].dictData) {
621 privateDicts[i].dictData = new GString();
622 privateDicts[i].subrsOffset = 0;
623 privateDicts[i].defaultWidthX = 0;
624 privateDicts[i].defaultWidthXFP = gFalse;
625 privateDicts[i].nominalWidthX = 0;
626 privateDicts[i].nominalWidthXFP = gFalse;
631 // get the glyph count
632 charStringsIdxPtr = (Guchar *)file + dict.charStrings;
633 nGlyphs = getIndexLen(charStringsIdxPtr);
635 // read the FDSelect table
636 fdSelect = (Guchar *)gmalloc(nGlyphs);
637 if (dict.fdSelectOffset == 0) {
638 for (i = 0; i < nGlyphs; ++i) {
642 ptr = (Guchar *)file + dict.fdSelectOffset;
643 fdSelectFmt = *ptr++;
644 if (fdSelectFmt == 0) {
645 memcpy(fdSelect, ptr, nGlyphs);
646 } else if (fdSelectFmt == 3) {
647 nRanges = getWord(ptr, 2);
649 gid0 = getWord(ptr, 2);
651 for (i = 1; i <= nRanges; ++i) {
653 gid1 = getWord(ptr, 2);
655 for (j = gid0; j < gid1; ++j) {
661 error(-1, "Unknown FDSelect table format in CID font");
662 for (i = 0; i < nGlyphs; ++i) {
668 // read the charset, compute the CID-to-GID mapping
669 charset = readCharset(dict.charset, nGlyphs);
671 for (i = 0; i < nGlyphs; ++i) {
672 if (charset[i] >= nCIDs) {
673 nCIDs = charset[i] + 1;
676 cidMap = (int *)gmalloc(nCIDs * sizeof(int));
677 for (i = 0; i < nCIDs; ++i) {
680 for (i = 0; i < nGlyphs; ++i) {
681 cidMap[charset[i]] = i;
684 // build the charstrings
685 charStrings = new GString();
686 charStringOffsets = (int *)gmalloc((nCIDs + 1) * sizeof(int));
687 for (i = 0; i < nCIDs; ++i) {
688 charStringOffsets[i] = charStrings->getLength();
689 if (cidMap[i] >= 0) {
690 idxPtr0 = getIndexValPtr(charStringsIdxPtr, cidMap[i]);
691 idxPtr1 = getIndexValPtr(charStringsIdxPtr, cidMap[i]+1);
692 n = idxPtr1 - idxPtr0;
693 j = fdSelect[cidMap[i]];
694 defaultWidthX = privateDicts[j].defaultWidthX;
695 defaultWidthXFP = privateDicts[j].defaultWidthXFP;
696 nominalWidthX = privateDicts[j].nominalWidthX;
697 nominalWidthXFP = privateDicts[j].nominalWidthXFP;
698 cvtGlyph(idxPtr0, n);
699 charStrings->append(charBuf);
703 charStringOffsets[nCIDs] = charStrings->getLength();
705 // compute gdBytes = number of bytes needed for charstring offsets
706 // (offset size needs to account for the charstring offset table,
707 // with a worst case of five bytes per entry, plus the charstrings
709 i = (nCIDs + 1) * 5 + charStrings->getLength();
712 } else if (i < 0x10000) {
714 } else if (i < 0x1000000) {
720 // begin the font dictionary
721 fprintf(out, "20 dict begin\n");
722 fprintf(out, "/CIDFontName /%s def\n", psName);
723 fprintf(out, "/CIDFontType 0 def\n");
724 fprintf(out, "/CIDSystemInfo 3 dict dup begin\n");
725 if (dict.registry > 0 && dict.ordering > 0) {
726 fprintf(out, " /Registry (%s) def\n", getString(dict.registry, buf));
727 fprintf(out, " /Ordering (%s) def\n", getString(dict.ordering, buf));
729 fprintf(out, " /Registry (Adobe) def\n");
730 fprintf(out, " /Ordering (Identity) def\n");
732 fprintf(out, " /Supplement %d def\n", dict.supplement);
733 fprintf(out, "end def\n");
734 fprintf(out, "/FontMatrix [%g %g %g %g %g %g] def\n",
735 dict.fontMatrix[0], dict.fontMatrix[1], dict.fontMatrix[2],
736 dict.fontMatrix[3], dict.fontMatrix[4], dict.fontMatrix[5]);
737 fprintf(out, "/FontBBox [%g %g %g %g] def\n",
738 dict.fontBBox[0], dict.fontBBox[1],
739 dict.fontBBox[2], dict.fontBBox[3]);
740 fprintf(out, "/FontInfo 1 dict dup begin\n");
741 fprintf(out, " /FSType 8 def\n");
742 fprintf(out, "end def\n");
744 // CIDFont-specific entries
745 fprintf(out, "/CIDCount %d def\n", nCIDs);
746 fprintf(out, "/FDBytes 1 def\n");
747 fprintf(out, "/GDBytes %d def\n", gdBytes);
748 fprintf(out, "/CIDMapOffset 0 def\n");
749 if (dict.paintType != 0) {
750 fprintf(out, "/PaintType %d def\n", dict.paintType);
751 fprintf(out, "/StrokeWidth %g def\n", dict.strokeWidth);
755 fprintf(out, "/FDArray %d array\n", nFDs);
756 for (i = 0; i < nFDs; ++i) {
757 fprintf(out, "dup %d 10 dict begin\n", i);
758 fprintf(out, "/FontType 1 def\n");
759 fprintf(out, "/FontMatrix [1 0 0 1 0 0] def\n");
760 fprintf(out, "/PaintType %d def\n", dict.paintType);
761 fprintf(out, "/Private 32 dict begin\n");
762 fwrite(privateDicts[i].dictData->getCString(), 1,
763 privateDicts[i].dictData->getLength(), out);
764 fprintf(out, "currentdict end def\n");
765 fprintf(out, "currentdict end put\n");
767 fprintf(out, "def\n");
769 //~ need to deal with subrs
771 // start the binary section
772 offset = (nCIDs + 1) * (1 + gdBytes);
773 fprintf(out, "(Hex) %d StartData\n",
774 offset + charStrings->getLength());
776 // write the charstring offset (CIDMap) table
777 for (i = 0; i <= nCIDs; i += 6) {
778 for (j = 0; j < 6 && i+j <= nCIDs; ++j) {
779 if (cidMap[i+j] >= 0) {
780 buf[0] = (char)fdSelect[cidMap[i+j]];
784 n = offset + charStringOffsets[i+j];
785 for (k = gdBytes; k >= 1; --k) {
786 buf[k] = (char)(n & 0xff);
789 for (k = 0; k <= gdBytes; ++k) {
790 fprintf(out, "%02x", buf[k] & 0xff);
796 // write the charstring data
797 n = charStrings->getLength();
798 for (i = 0; i < n; i += 32) {
799 for (j = 0; j < 32 && i+j < n; ++j) {
800 fprintf(out, "%02x", charStrings->getChar(i+j) & 0xff);
808 for (i = 0; i < nFDs; ++i) {
809 delete privateDicts[i].dictData;
814 gfree(charStringOffsets);
819 void Type1CFontFile::convertToType0(char *psName, FILE *outA) {
821 Type1CPrivateDict *privateDicts;
825 Guchar *charStringsIdxPtr, *fdArrayIdx, *idxPtr0, *idxPtr1, *ptr;
828 int nGlyphs, nCIDs, nFDs;
829 int fdSelectFmt, nRanges, gid0, gid1, fd;
837 // read top dict (first font only)
840 // read the FDArray dictionaries and Private dictionaries
841 if (dict.fdArrayOffset == 0) {
843 privateDicts = (Type1CPrivateDict *)
844 gmalloc(nFDs * sizeof(Type1CPrivateDict));
845 privateDicts[0].dictData = new GString();
846 privateDicts[0].subrsOffset = 0;
847 privateDicts[0].defaultWidthX = 0;
848 privateDicts[0].defaultWidthXFP = gFalse;
849 privateDicts[0].nominalWidthX = 0;
850 privateDicts[0].nominalWidthXFP = gFalse;
852 fdArrayIdx = (Guchar *)file + dict.fdArrayOffset;
853 nFDs = getIndexLen(fdArrayIdx);
854 privateDicts = (Type1CPrivateDict *)
855 gmalloc(nFDs * sizeof(Type1CPrivateDict));
856 idxPtr1 = getIndexValPtr(fdArrayIdx, 0);
857 for (i = 0; i < nFDs; ++i) {
858 privateDicts[i].dictData = NULL;
860 idxPtr1 = getIndexValPtr(fdArrayIdx, i + 1);
863 while (ptr < idxPtr1) {
864 if (*ptr <= 27 || *ptr == 31) {
867 key = (key << 8) | *ptr++;
870 readPrivateDict(&privateDicts[i], (int)op[1], (int)op[0]);
874 x = getNum(&ptr, &isFP);
881 if (!privateDicts[i].dictData) {
882 privateDicts[i].dictData = new GString();
883 privateDicts[i].subrsOffset = 0;
884 privateDicts[i].defaultWidthX = 0;
885 privateDicts[i].defaultWidthXFP = gFalse;
886 privateDicts[i].nominalWidthX = 0;
887 privateDicts[i].nominalWidthXFP = gFalse;
892 // get the glyph count
893 charStringsIdxPtr = (Guchar *)file + dict.charStrings;
894 nGlyphs = getIndexLen(charStringsIdxPtr);
896 // read the FDSelect table
897 fdSelect = (Guchar *)gmalloc(nGlyphs);
898 if (dict.fdSelectOffset == 0) {
899 for (i = 0; i < nGlyphs; ++i) {
903 ptr = (Guchar *)file + dict.fdSelectOffset;
904 fdSelectFmt = *ptr++;
905 if (fdSelectFmt == 0) {
906 memcpy(fdSelect, ptr, nGlyphs);
907 } else if (fdSelectFmt == 3) {
908 nRanges = getWord(ptr, 2);
910 gid0 = getWord(ptr, 2);
912 for (i = 1; i <= nRanges; ++i) {
914 gid1 = getWord(ptr, 2);
916 for (j = gid0; j < gid1; ++j) {
922 error(-1, "Unknown FDSelect table format in CID font");
923 for (i = 0; i < nGlyphs; ++i) {
929 // read the charset, compute the CID-to-GID mapping
930 charset = readCharset(dict.charset, nGlyphs);
932 for (i = 0; i < nGlyphs; ++i) {
933 if (charset[i] >= nCIDs) {
934 nCIDs = charset[i] + 1;
937 cidMap = (int *)gmalloc(nCIDs * sizeof(int));
938 for (i = 0; i < nCIDs; ++i) {
941 for (i = 0; i < nGlyphs; ++i) {
942 cidMap[charset[i]] = i;
945 // write the descendant Type 1 fonts
946 for (i = 0; i < nCIDs; i += 256) {
948 //~ this assumes that all CIDs in this block have the same FD --
949 //~ to handle multiple FDs correctly, need to somehow divide the
952 for (j = 0; j < 256 && i+j < nCIDs; ++j) {
953 if (cidMap[i+j] >= 0) {
954 fd = fdSelect[cidMap[i+j]];
959 // font dictionary (unencrypted section)
960 fprintf(out, "16 dict begin\n");
961 fprintf(out, "/FontName /%s_%02x def\n", psName, i >> 8);
962 fprintf(out, "/FontType 1 def\n");
963 fprintf(out, "/FontMatrix [%g %g %g %g %g %g] def\n",
964 dict.fontMatrix[0], dict.fontMatrix[1], dict.fontMatrix[2],
965 dict.fontMatrix[3], dict.fontMatrix[4], dict.fontMatrix[5]);
966 fprintf(out, "/FontBBox [%g %g %g %g] def\n",
967 dict.fontBBox[0], dict.fontBBox[1],
968 dict.fontBBox[2], dict.fontBBox[3]);
969 fprintf(out, "/PaintType %d def\n", dict.paintType);
970 if (dict.paintType != 0) {
971 fprintf(out, "/StrokeWidth %g def\n", dict.strokeWidth);
973 fprintf(out, "/Encoding 256 array\n");
974 for (j = 0; j < 256 && i+j < nCIDs; ++j) {
975 fprintf(out, "dup %d /c%02x put\n", j, j);
977 fprintf(out, "readonly def\n");
978 fprintf(out, "currentdict end\n");
980 // start the binary section
981 fprintf(out, "currentfile eexec\n");
985 // start the private dictionary
986 eexecWrite("\x83\xca\x73\xd5");
987 eexecWrite("dup /Private 32 dict dup begin\n");
988 eexecWrite("/RD {string currentfile exch readstring pop} executeonly def\n");
989 eexecWrite("/ND {noaccess def} executeonly def\n");
990 eexecWrite("/NP {noaccess put} executeonly def\n");
991 eexecWrite("/MinFeature {16 16} ND\n");
992 eexecWrite(privateDicts[fd].dictData->getCString());
993 defaultWidthX = privateDicts[fd].defaultWidthX;
994 defaultWidthXFP = privateDicts[fd].defaultWidthXFP;
995 nominalWidthX = privateDicts[fd].nominalWidthX;
996 nominalWidthXFP = privateDicts[fd].nominalWidthXFP;
998 // start the CharStrings
999 sprintf(eBuf, "2 index /CharStrings 256 dict dup begin\n");
1002 // write the .notdef CharString
1003 idxPtr0 = getIndexValPtr(charStringsIdxPtr, 0);
1004 idxPtr1 = getIndexValPtr(charStringsIdxPtr, 1);
1005 n = idxPtr1 - idxPtr0;
1006 eexecCvtGlyph(".notdef", idxPtr0, n);
1008 // write the CharStrings
1009 for (j = 0; j < 256 && i+j < nCIDs; ++j) {
1010 if (cidMap[i+j] >= 0) {
1011 idxPtr0 = getIndexValPtr(charStringsIdxPtr, cidMap[i+j]);
1012 idxPtr1 = getIndexValPtr(charStringsIdxPtr, cidMap[i+j]+1);
1013 n = idxPtr1 - idxPtr0;
1014 sprintf(buf, "c%02x", j);
1015 eexecCvtGlyph(buf, idxPtr0, n);
1018 eexecWrite("end\n");
1019 eexecWrite("end\n");
1020 eexecWrite("readonly put\n");
1021 eexecWrite("noaccess put\n");
1022 eexecWrite("dup /FontName get exch definefont pop\n");
1023 eexecWrite("mark currentfile closefile\n");
1029 for (j = 0; j < 8; ++j) {
1030 fprintf(out, "0000000000000000000000000000000000000000000000000000000000000000\n");
1032 fprintf(out, "cleartomark\n");
1035 // write the Type 0 parent font
1036 fprintf(out, "16 dict begin\n");
1037 fprintf(out, "/FontName /%s def\n", psName);
1038 fprintf(out, "/FontType 0 def\n");
1039 fprintf(out, "/FontMatrix [1 0 0 1 0 0] def\n");
1040 fprintf(out, "/FMapType 2 def\n");
1041 fprintf(out, "/Encoding [\n");
1042 for (i = 0; i < nCIDs; i += 256) {
1043 fprintf(out, "%d\n", i >> 8);
1045 fprintf(out, "] def\n");
1046 fprintf(out, "/FDepVector [\n");
1047 for (i = 0; i < nCIDs; i += 256) {
1048 fprintf(out, "/%s_%02x findfont\n", psName, i >> 8);
1050 fprintf(out, "] def\n");
1051 fprintf(out, "FontName currentdict end definefont pop\n");
1054 for (i = 0; i < nFDs; ++i) {
1055 delete privateDicts[i].dictData;
1057 gfree(privateDicts);
1063 void Type1CFontFile::readTopDict(Type1CTopDict *dict) {
1064 Guchar *idxPtr0, *idxPtr1, *ptr;
1070 idxPtr0 = getIndexValPtr(topDictIdxPtr, 0);
1071 idxPtr1 = getIndexValPtr(topDictIdxPtr, 1);
1074 dict->copyright = 0;
1076 dict->familyName = 0;
1078 dict->isFixedPitch = 0;
1079 dict->italicAngle = 0;
1080 dict->underlinePosition = -100;
1081 dict->underlineThickness = 50;
1082 dict->paintType = 0;
1083 dict->charstringType = 2;
1084 dict->fontMatrix[0] = 0.001;
1085 dict->fontMatrix[1] = 0;
1086 dict->fontMatrix[2] = 0;
1087 dict->fontMatrix[3] = 0.001;
1088 dict->fontMatrix[4] = 0;
1089 dict->fontMatrix[5] = 0;
1091 dict->fontBBox[0] = 0;
1092 dict->fontBBox[1] = 0;
1093 dict->fontBBox[2] = 0;
1094 dict->fontBBox[3] = 0;
1095 dict->strokeWidth = 0;
1098 dict->charStrings = 0;
1099 dict->privateSize = 0;
1100 dict->privateOffset = 0;
1103 dict->supplement = 0;
1104 dict->fdArrayOffset = 0;
1105 dict->fdSelectOffset = 0;
1108 while (ptr < idxPtr1) {
1109 if (*ptr <= 27 || *ptr == 31) {
1112 key = (key << 8) | *ptr++;
1115 case 0x0000: dict->version = (int)op[0]; break;
1116 case 0x0001: dict->notice = (int)op[0]; break;
1117 case 0x0c00: dict->copyright = (int)op[0]; break;
1118 case 0x0002: dict->fullName = (int)op[0]; break;
1119 case 0x0003: dict->familyName = (int)op[0]; break;
1120 case 0x0004: dict->weight = (int)op[0]; break;
1121 case 0x0c01: dict->isFixedPitch = (int)op[0]; break;
1122 case 0x0c02: dict->italicAngle = op[0]; break;
1123 case 0x0c03: dict->underlinePosition = op[0]; break;
1124 case 0x0c04: dict->underlineThickness = op[0]; break;
1125 case 0x0c05: dict->paintType = (int)op[0]; break;
1126 case 0x0c06: dict->charstringType = (int)op[0]; break;
1127 case 0x0c07: dict->fontMatrix[0] = op[0];
1128 dict->fontMatrix[1] = op[1];
1129 dict->fontMatrix[2] = op[2];
1130 dict->fontMatrix[3] = op[3];
1131 dict->fontMatrix[4] = op[4];
1132 dict->fontMatrix[5] = op[5]; break;
1133 case 0x000d: dict->uniqueID = (int)op[0]; break;
1134 case 0x0005: dict->fontBBox[0] = op[0];
1135 dict->fontBBox[1] = op[1];
1136 dict->fontBBox[2] = op[2];
1137 dict->fontBBox[3] = op[3]; break;
1138 case 0x0c08: dict->strokeWidth = op[0]; break;
1139 case 0x000f: dict->charset = (int)op[0]; break;
1140 case 0x0010: dict->encoding = (int)op[0]; break;
1141 case 0x0011: dict->charStrings = (int)op[0]; break;
1142 case 0x0012: dict->privateSize = (int)op[0];
1143 dict->privateOffset = (int)op[1]; break;
1144 case 0x0c1e: dict->registry = (int)op[0];
1145 dict->ordering = (int)op[1];
1146 dict->supplement = (int)op[2]; break;
1147 case 0x0c24: dict->fdArrayOffset = (int)op[0]; break;
1148 case 0x0c25: dict->fdSelectOffset = (int)op[0]; break;
1152 x = getNum(&ptr, &isFP);
1161 void Type1CFontFile::readPrivateDict(Type1CPrivateDict *privateDict,
1162 int offset, int size) {
1163 Guchar *idxPtr0, *idxPtr1, *ptr;
1170 privateDict->dictData = new GString();
1171 privateDict->subrsOffset = 0;
1172 privateDict->defaultWidthX = 0;
1173 privateDict->defaultWidthXFP = gFalse;
1174 privateDict->nominalWidthX = 0;
1175 privateDict->nominalWidthXFP = gFalse;
1176 idxPtr0 = (Guchar *)file + offset;
1177 idxPtr1 = idxPtr0 + size;
1180 while (ptr < idxPtr1) {
1181 if (*ptr <= 27 || *ptr == 31) {
1184 key = (key << 8) | *ptr++;
1188 getDeltaInt(eBuf, "BlueValues", op, i);
1189 privateDict->dictData->append(eBuf);
1192 getDeltaInt(eBuf, "OtherBlues", op, i);
1193 privateDict->dictData->append(eBuf);
1196 getDeltaInt(eBuf, "FamilyBlues", op, i);
1197 privateDict->dictData->append(eBuf);
1200 getDeltaInt(eBuf, "FamilyOtherBlues", op, i);
1201 privateDict->dictData->append(eBuf);
1204 sprintf(eBuf, "/BlueScale %g def\n", op[0]);
1205 privateDict->dictData->append(eBuf);
1208 sprintf(eBuf, "/BlueShift %d def\n", (int)op[0]);
1209 privateDict->dictData->append(eBuf);
1212 sprintf(eBuf, "/BlueFuzz %d def\n", (int)op[0]);
1213 privateDict->dictData->append(eBuf);
1216 sprintf(eBuf, "/StdHW [%g] def\n", op[0]);
1217 privateDict->dictData->append(eBuf);
1220 sprintf(eBuf, "/StdVW [%g] def\n", op[0]);
1221 privateDict->dictData->append(eBuf);
1224 getDeltaReal(eBuf, "StemSnapH", op, i);
1225 privateDict->dictData->append(eBuf);
1228 getDeltaReal(eBuf, "StemSnapV", op, i);
1229 privateDict->dictData->append(eBuf);
1232 sprintf(eBuf, "/ForceBold %s def\n", op[0] ? "true" : "false");
1233 privateDict->dictData->append(eBuf);
1236 sprintf(eBuf, "/ForceBoldThreshold %g def\n", op[0]);
1237 privateDict->dictData->append(eBuf);
1240 sprintf(eBuf, "/LanguageGroup %d def\n", (int)op[0]);
1241 privateDict->dictData->append(eBuf);
1244 sprintf(eBuf, "/ExpansionFactor %g def\n", op[0]);
1245 privateDict->dictData->append(eBuf);
1248 error(-1, "Got Type 1C InitialRandomSeed");
1251 privateDict->subrsOffset = (int)op[0];
1254 privateDict->defaultWidthX = op[0];
1255 privateDict->defaultWidthXFP = fp[0];
1258 privateDict->nominalWidthX = op[0];
1259 privateDict->nominalWidthXFP = fp[0];
1262 error(-1, "Unknown Type 1C private dict entry %04x", key);
1267 x = getNum(&ptr, &isFP);
1276 Gushort *Type1CFontFile::readCharset(int charset, int nGlyphs) {
1277 Gushort *glyphNames;
1279 int charsetFormat, c;
1283 glyphNames = type1CISOAdobeCharset;
1284 } else if (charset == 1) {
1285 glyphNames = type1CExpertCharset;
1286 } else if (charset == 2) {
1287 glyphNames = type1CExpertSubsetCharset;
1289 glyphNames = (Gushort *)gmalloc(nGlyphs * sizeof(Gushort));
1291 ptr = (Guchar *)file + charset;
1292 charsetFormat = *ptr++;
1293 if (charsetFormat == 0) {
1294 for (i = 1; i < nGlyphs; ++i) {
1295 glyphNames[i] = getWord(ptr, 2);
1298 } else if (charsetFormat == 1) {
1300 while (i < nGlyphs) {
1301 c = getWord(ptr, 2);
1304 for (j = 0; j <= nLeft && i < nGlyphs; ++j) {
1305 glyphNames[i++] = c++;
1308 } else if (charsetFormat == 2) {
1310 while (i < nGlyphs) {
1311 c = getWord(ptr, 2);
1313 nLeft = getWord(ptr, 2);
1315 for (j = 0; j <= nLeft && i < nGlyphs; ++j) {
1316 glyphNames[i++] = c++;
1324 void Type1CFontFile::eexecWrite(char *s) {
1328 for (p = (Guchar *)s; *p; ++p) {
1330 r1 = (x + r1) * 52845 + 22719;
1331 fputc(hexChars[x >> 4], out);
1332 fputc(hexChars[x & 0x0f], out);
1341 void Type1CFontFile::eexecCvtGlyph(char *glyphName, Guchar *s, int n) {
1345 sprintf(eBuf, "/%s %d RD ", glyphName, charBuf->getLength());
1347 eexecWriteCharstring((Guchar *)charBuf->getCString(), charBuf->getLength());
1348 eexecWrite(" ND\n");
1352 void Type1CFontFile::cvtGlyph(Guchar *s, int n) {
1355 GBool first = gTrue;
1362 charBuf = new GString();
1363 charBuf->append((char)73);
1364 charBuf->append((char)58);
1365 charBuf->append((char)147);
1366 charBuf->append((char)134);
1374 case 0: // dotsection (should be Type 1 only?)
1379 error(-1, "Wrong number of args (%d) to Type 2 hflex", nOps);
1381 eexecDumpNum(op[0], fp[0]);
1382 eexecDumpNum(0, gFalse);
1383 eexecDumpNum(op[1], fp[1]);
1384 eexecDumpNum(op[2], fp[2]);
1385 eexecDumpNum(op[3], fp[3]);
1386 eexecDumpNum(0, gFalse);
1388 eexecDumpNum(op[4], fp[4]);
1389 eexecDumpNum(0, gFalse);
1390 eexecDumpNum(op[5], fp[5]);
1391 eexecDumpNum(-op[2], fp[2]);
1392 eexecDumpNum(op[6], fp[6]);
1393 eexecDumpNum(0, gFalse);
1398 error(-1, "Wrong number of args (%d) to Type 2 flex", nOps);
1400 eexecDumpNum(op[0], fp[0]);
1401 eexecDumpNum(op[1], fp[1]);
1402 eexecDumpNum(op[2], fp[2]);
1403 eexecDumpNum(op[3], fp[3]);
1404 eexecDumpNum(op[4], fp[4]);
1405 eexecDumpNum(op[5], fp[5]);
1407 eexecDumpNum(op[6], fp[6]);
1408 eexecDumpNum(op[7], fp[7]);
1409 eexecDumpNum(op[8], fp[8]);
1410 eexecDumpNum(op[9], fp[9]);
1411 eexecDumpNum(op[10], fp[10]);
1412 eexecDumpNum(op[11], fp[11]);
1417 error(-1, "Wrong number of args (%d) to Type 2 hflex1", nOps);
1419 eexecDumpNum(op[0], fp[0]);
1420 eexecDumpNum(op[1], fp[1]);
1421 eexecDumpNum(op[2], fp[2]);
1422 eexecDumpNum(op[3], fp[3]);
1423 eexecDumpNum(op[4], fp[4]);
1424 eexecDumpNum(0, gFalse);
1426 eexecDumpNum(op[5], fp[5]);
1427 eexecDumpNum(0, gFalse);
1428 eexecDumpNum(op[6], fp[6]);
1429 eexecDumpNum(op[7], fp[7]);
1430 eexecDumpNum(op[8], fp[8]);
1431 eexecDumpNum(-(op[1] + op[3] + op[7]), fp[1] | fp[3] | fp[7]);
1436 error(-1, "Wrong number of args (%d) to Type 2 flex1", nOps);
1438 eexecDumpNum(op[0], fp[0]);
1439 eexecDumpNum(op[1], fp[1]);
1440 eexecDumpNum(op[2], fp[2]);
1441 eexecDumpNum(op[3], fp[3]);
1442 eexecDumpNum(op[4], fp[4]);
1443 eexecDumpNum(op[5], fp[5]);
1445 eexecDumpNum(op[6], fp[6]);
1446 eexecDumpNum(op[7], fp[7]);
1447 eexecDumpNum(op[8], fp[8]);
1448 eexecDumpNum(op[9], fp[9]);
1449 dx = op[0] + op[2] + op[4] + op[6] + op[8];
1450 dy = op[1] + op[3] + op[5] + op[7] + op[9];
1451 if (fabs(dx) > fabs(dy)) {
1452 eexecDumpNum(op[10], fp[10]);
1453 eexecDumpNum(-dy, fp[1] | fp[3] | fp[5] | fp[7] | fp[9]);
1455 eexecDumpNum(-dx, fp[0] | fp[2] | fp[4] | fp[6] | fp[8]);
1456 eexecDumpNum(op[10], fp[10]);
1482 error(-1, "Unimplemented Type 2 charstring op: 12.%d", s[i+1]);
1485 error(-1, "Illegal Type 2 charstring op: 12.%d", s[i+1]);
1490 } else if (s[i] == 19) { // hintmask
1493 cvtGlyphWidth(nOps == 1);
1498 error(-1, "Wrong number of args (%d) to Type 2 hintmask/vstemhm",
1503 i += 1 + ((nHints + 7) >> 3);
1505 } else if (s[i] == 20) { // cntrmask
1508 cvtGlyphWidth(nOps == 1);
1513 error(-1, "Wrong number of args (%d) to Type 2 cntrmask/vstemhm",
1518 i += 1 + ((nHints + 7) >> 3);
1520 } else if (s[i] == 28) {
1521 x = (s[i+1] << 8) + s[i+2];
1530 } else if (s[i] <= 31) {
1534 cvtGlyphWidth(nOps == 2);
1538 error(-1, "Wrong number of args (%d) to Type 2 vmoveto", nOps);
1540 eexecDumpNum(op[0], fp[0]);
1544 if (nOps < 2 || nOps % 2 != 0) {
1545 error(-1, "Wrong number of args (%d) to Type 2 rlineto", nOps);
1547 for (k = 0; k < nOps; k += 2) {
1548 eexecDumpNum(op[k], fp[k]);
1549 eexecDumpNum(op[k+1], fp[k+1]);
1555 error(-1, "Wrong number of args (%d) to Type 2 hlineto", nOps);
1557 for (k = 0; k < nOps; ++k) {
1558 eexecDumpNum(op[k], fp[k]);
1559 eexecDumpOp1((k & 1) ? 7 : 6);
1564 error(-1, "Wrong number of args (%d) to Type 2 vlineto", nOps);
1566 for (k = 0; k < nOps; ++k) {
1567 eexecDumpNum(op[k], fp[k]);
1568 eexecDumpOp1((k & 1) ? 6 : 7);
1571 case 8: // rrcurveto
1572 if (nOps < 6 || nOps % 6 != 0) {
1573 error(-1, "Wrong number of args (%d) to Type 2 rrcurveto", nOps);
1575 for (k = 0; k < nOps; k += 6) {
1576 eexecDumpNum(op[k], fp[k]);
1577 eexecDumpNum(op[k+1], fp[k+1]);
1578 eexecDumpNum(op[k+2], fp[k+2]);
1579 eexecDumpNum(op[k+3], fp[k+3]);
1580 eexecDumpNum(op[k+4], fp[k+4]);
1581 eexecDumpNum(op[k+5], fp[k+5]);
1585 case 14: // endchar / seac
1587 cvtGlyphWidth(nOps == 1 || nOps == 5);
1592 eexecDumpNum(op[0], fp[0]);
1593 eexecDumpNum(op[1], fp[1]);
1594 eexecDumpNum(op[2], fp[2]);
1595 eexecDumpNum(op[3], fp[3]);
1597 } else if (nOps == 0) {
1600 error(-1, "Wrong number of args (%d) to Type 2 endchar", nOps);
1605 cvtGlyphWidth(nOps == 3);
1609 error(-1, "Wrong number of args (%d) to Type 2 rmoveto", nOps);
1611 eexecDumpNum(op[0], fp[0]);
1612 eexecDumpNum(op[1], fp[1]);
1617 cvtGlyphWidth(nOps == 2);
1621 error(-1, "Wrong number of args (%d) to Type 2 hmoveto", nOps);
1623 eexecDumpNum(op[0], fp[0]);
1626 case 24: // rcurveline
1627 if (nOps < 8 || (nOps - 2) % 6 != 0) {
1628 error(-1, "Wrong number of args (%d) to Type 2 rcurveline", nOps);
1630 for (k = 0; k < nOps - 2; k += 6) {
1631 eexecDumpNum(op[k], fp[k]);
1632 eexecDumpNum(op[k+1], fp[k+1]);
1633 eexecDumpNum(op[k+2], fp[k+2]);
1634 eexecDumpNum(op[k+3], fp[k+3]);
1635 eexecDumpNum(op[k+4], fp[k+4]);
1636 eexecDumpNum(op[k+5], fp[k+5]);
1639 eexecDumpNum(op[k], fp[k]);
1640 eexecDumpNum(op[k+1], fp[k]);
1643 case 25: // rlinecurve
1644 if (nOps < 8 || (nOps - 6) % 2 != 0) {
1645 error(-1, "Wrong number of args (%d) to Type 2 rlinecurve", nOps);
1647 for (k = 0; k < nOps - 6; k += 2) {
1648 eexecDumpNum(op[k], fp[k]);
1649 eexecDumpNum(op[k+1], fp[k]);
1652 eexecDumpNum(op[k], fp[k]);
1653 eexecDumpNum(op[k+1], fp[k+1]);
1654 eexecDumpNum(op[k+2], fp[k+2]);
1655 eexecDumpNum(op[k+3], fp[k+3]);
1656 eexecDumpNum(op[k+4], fp[k+4]);
1657 eexecDumpNum(op[k+5], fp[k+5]);
1660 case 26: // vvcurveto
1661 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
1662 error(-1, "Wrong number of args (%d) to Type 2 vvcurveto", nOps);
1664 if (nOps % 2 == 1) {
1665 eexecDumpNum(op[0], fp[0]);
1666 eexecDumpNum(op[1], fp[1]);
1667 eexecDumpNum(op[2], fp[2]);
1668 eexecDumpNum(op[3], fp[3]);
1669 eexecDumpNum(0, gFalse);
1670 eexecDumpNum(op[4], fp[4]);
1676 for (; k < nOps; k += 4) {
1677 eexecDumpNum(0, gFalse);
1678 eexecDumpNum(op[k], fp[k]);
1679 eexecDumpNum(op[k+1], fp[k+1]);
1680 eexecDumpNum(op[k+2], fp[k+2]);
1681 eexecDumpNum(0, gFalse);
1682 eexecDumpNum(op[k+3], fp[k+3]);
1686 case 27: // hhcurveto
1687 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
1688 error(-1, "Wrong number of args (%d) to Type 2 hhcurveto", nOps);
1690 if (nOps % 2 == 1) {
1691 eexecDumpNum(op[1], fp[1]);
1692 eexecDumpNum(op[0], fp[0]);
1693 eexecDumpNum(op[2], fp[2]);
1694 eexecDumpNum(op[3], fp[3]);
1695 eexecDumpNum(op[4], fp[4]);
1696 eexecDumpNum(0, gFalse);
1702 for (; k < nOps; k += 4) {
1703 eexecDumpNum(op[k], fp[k]);
1704 eexecDumpNum(0, gFalse);
1705 eexecDumpNum(op[k+1], fp[k+1]);
1706 eexecDumpNum(op[k+2], fp[k+2]);
1707 eexecDumpNum(op[k+3], fp[k+3]);
1708 eexecDumpNum(0, gFalse);
1712 case 30: // vhcurveto
1713 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
1714 error(-1, "Wrong number of args (%d) to Type 2 vhcurveto", nOps);
1716 for (k = 0; k < nOps && k != nOps-5; k += 4) {
1718 eexecDumpNum(op[k], fp[k]);
1719 eexecDumpNum(op[k+1], fp[k+1]);
1720 eexecDumpNum(op[k+2], fp[k+2]);
1721 eexecDumpNum(op[k+3], fp[k+3]);
1724 eexecDumpNum(op[k], fp[k]);
1725 eexecDumpNum(op[k+1], fp[k+1]);
1726 eexecDumpNum(op[k+2], fp[k+2]);
1727 eexecDumpNum(op[k+3], fp[k+3]);
1733 eexecDumpNum(0, gFalse);
1734 eexecDumpNum(op[k], fp[k]);
1735 eexecDumpNum(op[k+1], fp[k+1]);
1736 eexecDumpNum(op[k+2], fp[k+2]);
1737 eexecDumpNum(op[k+3], fp[k+3]);
1738 eexecDumpNum(op[k+4], fp[k+4]);
1740 eexecDumpNum(op[k], fp[k]);
1741 eexecDumpNum(0, gFalse);
1742 eexecDumpNum(op[k+1], fp[k+1]);
1743 eexecDumpNum(op[k+2], fp[k+2]);
1744 eexecDumpNum(op[k+4], fp[k+4]);
1745 eexecDumpNum(op[k+3], fp[k+3]);
1750 case 31: // hvcurveto
1751 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
1752 error(-1, "Wrong number of args (%d) to Type 2 hvcurveto", nOps);
1754 for (k = 0; k < nOps && k != nOps-5; k += 4) {
1756 eexecDumpNum(op[k], fp[k]);
1757 eexecDumpNum(op[k+1], fp[k+1]);
1758 eexecDumpNum(op[k+2], fp[k+2]);
1759 eexecDumpNum(op[k+3], fp[k+3]);
1762 eexecDumpNum(op[k], fp[k]);
1763 eexecDumpNum(op[k+1], fp[k+1]);
1764 eexecDumpNum(op[k+2], fp[k+2]);
1765 eexecDumpNum(op[k+3], fp[k+3]);
1771 eexecDumpNum(op[k], fp[k]);
1772 eexecDumpNum(0, gFalse);
1773 eexecDumpNum(op[k+1], fp[k+1]);
1774 eexecDumpNum(op[k+2], fp[k+2]);
1775 eexecDumpNum(op[k+4], fp[k+4]);
1776 eexecDumpNum(op[k+3], fp[k+3]);
1778 eexecDumpNum(0, gFalse);
1779 eexecDumpNum(op[k], fp[k]);
1780 eexecDumpNum(op[k+1], fp[k+1]);
1781 eexecDumpNum(op[k+2], fp[k+2]);
1782 eexecDumpNum(op[k+3], fp[k+3]);
1783 eexecDumpNum(op[k+4], fp[k+4]);
1790 cvtGlyphWidth(nOps & 1);
1794 error(-1, "Wrong number of args (%d) to Type 2 hstem", nOps);
1798 for (k = 0; k < nOps; k += 2) {
1800 d += op[k] + op[k+1];
1801 dFP |= fp[k] | fp[k+1];
1802 eexecDumpNum(d, dFP);
1803 eexecDumpNum(-op[k+1], fp[k+1]);
1807 eexecDumpNum(d, dFP);
1808 eexecDumpNum(op[k+1], fp[k+1]);
1818 cvtGlyphWidth(nOps & 1);
1822 error(-1, "Wrong number of args (%d) to Type 2 vstem", nOps);
1826 for (k = 0; k < nOps; k += 2) {
1828 d += op[k] + op[k+1];
1829 dFP |= fp[k] | fp[k+1];
1830 eexecDumpNum(d, dFP);
1831 eexecDumpNum(-op[k+1], fp[k+1]);
1835 eexecDumpNum(d, dFP);
1836 eexecDumpNum(op[k+1], fp[k+1]);
1847 cvtGlyphWidth(nOps & 1);
1851 error(-1, "Wrong number of args (%d) to Type 2 hstemhm", nOps);
1858 cvtGlyphWidth(nOps & 1);
1862 error(-1, "Wrong number of args (%d) to Type 2 vstemhm", nOps);
1866 case 10: // callsubr
1869 case 29: // callgsubr
1870 error(-1, "Unimplemented Type 2 charstring op: %d", s[i]);
1873 error(-1, "Illegal Type 2 charstring op: %d", s[i]);
1878 } else if (s[i] <= 246) {
1881 op[nOps++] = (int)s[i] - 139;
1884 } else if (s[i] <= 250) {
1887 op[nOps++] = (((int)s[i] - 247) << 8) + (int)s[i+1] + 108;
1890 } else if (s[i] <= 254) {
1893 op[nOps++] = -(((int)s[i] - 251) << 8) - (int)s[i+1] - 108;
1897 x = (s[i+1] << 24) | (s[i+2] << 16) | (s[i+3] << 8) | s[i+4];
1902 op[nOps++] = (double)x / 65536.0;
1908 // charstring encryption
1910 for (i = 0; i < charBuf->getLength(); ++i) {
1911 byte = charBuf->getChar(i) ^ (r2 >> 8);
1912 charBuf->setChar(i, byte);
1913 r2 = (byte + r2) * 52845 + 22719;
1917 void Type1CFontFile::cvtGlyphWidth(GBool useOp) {
1923 w = nominalWidthX + op[0];
1924 wFP = nominalWidthXFP | fp[0];
1925 for (i = 1; i < nOps; ++i) {
1932 wFP = defaultWidthXFP;
1934 eexecDumpNum(0, gFalse);
1935 eexecDumpNum(w, wFP);
1939 void Type1CFontFile::eexecDumpNum(double x, GBool fpA) {
1945 if (x >= -32768 && x < 32768) {
1946 y = (int)(x * 256.0);
1948 buf[1] = (Guchar)(y >> 24);
1949 buf[2] = (Guchar)(y >> 16);
1950 buf[3] = (Guchar)(y >> 8);
1961 error(-1, "Type 2 fixed point constant out of range");
1965 if (y >= -107 && y <= 107) {
1966 buf[0] = (Guchar)(y + 139);
1968 } else if (y > 107 && y <= 1131) {
1970 buf[0] = (Guchar)((y >> 8) + 247);
1971 buf[1] = (Guchar)(y & 0xff);
1973 } else if (y < -107 && y >= -1131) {
1975 buf[0] = (Guchar)((y >> 8) + 251);
1976 buf[1] = (Guchar)(y & 0xff);
1980 buf[1] = (Guchar)(y >> 24);
1981 buf[2] = (Guchar)(y >> 16);
1982 buf[3] = (Guchar)(y >> 8);
1987 charBuf->append((char *)buf, n);
1990 void Type1CFontFile::eexecDumpOp1(int opA) {
1991 charBuf->append((char)opA);
1994 void Type1CFontFile::eexecDumpOp2(int opA) {
1995 charBuf->append((char)12);
1996 charBuf->append((char)opA);
1999 void Type1CFontFile::eexecWriteCharstring(Guchar *s, int n) {
2004 for (i = 0; i < n; ++i) {
2005 x = s[i] ^ (r1 >> 8);
2006 r1 = (x + r1) * 52845 + 22719;
2007 fputc(hexChars[x >> 4], out);
2008 fputc(hexChars[x & 0x0f], out);
2017 void Type1CFontFile::getDeltaInt(char *buf, char *key, double *opA,
2021 sprintf(buf, "/%s [", key);
2024 for (i = 0; i < n; ++i) {
2026 sprintf(buf, "%s%d", i > 0 ? " " : "", x);
2029 sprintf(buf, "] def\n");
2032 void Type1CFontFile::getDeltaReal(char *buf, char *key, double *opA,
2037 sprintf(buf, "/%s [", key);
2040 for (i = 0; i < n; ++i) {
2042 sprintf(buf, "%s%g", i > 0 ? " " : "", x);
2045 sprintf(buf, "] def\n");
2048 int Type1CFontFile::getIndexLen(Guchar *indexPtr) {
2049 return (int)getWord(indexPtr, 2);
2052 Guchar *Type1CFontFile::getIndexValPtr(Guchar *indexPtr, int i) {
2054 Guchar *idxStartPtr;
2056 n = (int)getWord(indexPtr, 2);
2057 offSize = indexPtr[2];
2058 idxStartPtr = indexPtr + 3 + (n + 1) * offSize - 1;
2059 return idxStartPtr + getWord(indexPtr + 3 + i * offSize, offSize);
2062 Guchar *Type1CFontFile::getIndexEnd(Guchar *indexPtr) {
2064 Guchar *idxStartPtr;
2066 n = (int)getWord(indexPtr, 2);
2067 offSize = indexPtr[2];
2068 idxStartPtr = indexPtr + 3 + (n + 1) * offSize - 1;
2069 return idxStartPtr + getWord(indexPtr + 3 + n * offSize, offSize);
2072 Guint Type1CFontFile::getWord(Guchar *ptr, int size) {
2077 for (i = 0; i < size; ++i) {
2078 x = (x << 8) + *ptr++;
2083 double Type1CFontFile::getNum(Guchar **ptr, GBool *isFP) {
2084 static char nybChars[16] = "0123456789.ee -";
2085 int b0, b, nyb0, nyb1;
2095 } else if (b0 == 28) {
2096 x = ((*ptr)[1] << 8) + (*ptr)[2];
2098 } else if (b0 == 29) {
2099 x = ((*ptr)[1] << 24) + ((*ptr)[2] << 16) + ((*ptr)[3] << 8) + (*ptr)[4];
2101 } else if (b0 == 30) {
2111 buf[i++] = nybChars[nyb0];
2124 buf[i++] = nybChars[nyb1];
2135 } else if (b0 == 31) {
2137 } else if (b0 < 247) {
2140 } else if (b0 < 251) {
2141 x = ((b0 - 247) << 8) + (*ptr)[1] + 108;
2144 x = -((b0 - 251) << 8) - (*ptr)[1] - 108;
2150 char *Type1CFontFile::getString(int sid, char *buf) {
2151 Guchar *idxPtr0, *idxPtr1;
2155 strcpy(buf, type1CStdStrings[sid]);
2158 idxPtr0 = getIndexValPtr(stringIdxPtr, sid);
2159 idxPtr1 = getIndexValPtr(stringIdxPtr, sid + 1);
2160 if ((n = idxPtr1 - idxPtr0) > 255) {
2163 strncpy(buf, (char *)idxPtr0, n);
2169 //------------------------------------------------------------------------
2171 //------------------------------------------------------------------------
2177 // character code = number used as an element of a text string
2179 // character name = glyph name = name for a particular glyph within a
2182 // glyph index = position (within some internal table in the font)
2183 // where the instructions to draw a particular glyph are
2189 // Type 1 fonts contain:
2191 // Encoding: array of glyph names, maps char codes to glyph names
2193 // Encoding[charCode] = charName
2195 // CharStrings: dictionary of instructions, keyed by character names,
2196 // maps character name to glyph data
2198 // CharStrings[charName] = glyphData
2203 // TrueType fonts contain:
2205 // 'cmap' table: mapping from character code to glyph index; there may
2206 // be multiple cmaps in a TrueType font
2208 // cmap[charCode] = glyphIdx
2210 // 'post' table: mapping from glyph index to glyph name
2212 // post[glyphIdx] = glyphName
2217 // Type 42 fonts contain:
2219 // Encoding: array of glyph names, maps char codes to glyph names
2221 // Encoding[charCode] = charName
2223 // CharStrings: dictionary of glyph indexes, keyed by character names,
2224 // maps character name to glyph index
2226 // CharStrings[charName] = glyphIdx
2229 struct TTFontTableHdr {
2237 char *tag; // 4-byte tag
2238 GBool required; // required by the TrueType spec?
2241 // TrueType tables to be embedded in Type 42 fonts.
2242 // NB: the table names must be in alphabetical order here.
2243 #define nT42Tables 11
2244 static T42Table t42Tables[nT42Tables] = {
2257 #define t42HeadTable 3
2258 #define t42LocaTable 6
2259 #define t42GlyfTable 2
2261 // Glyph names in some arbitrary standard that Apple uses for their
2263 static char *macGlyphNames[258] = {
2524 enum T42FontIndexMode {
2526 t42FontModeCharCode,
2527 t42FontModeCharCodeOffset,
2531 TrueTypeFontFile::TrueTypeFontFile(char *fileA, int lenA) {
2539 // read table directory
2540 nTables = getUShort(4);
2541 tableHdrs = (TTFontTableHdr *)gmalloc(nTables * sizeof(TTFontTableHdr));
2543 for (i = 0; i < nTables; ++i) {
2544 tableHdrs[i].tag[0] = getByte(pos+0);
2545 tableHdrs[i].tag[1] = getByte(pos+1);
2546 tableHdrs[i].tag[2] = getByte(pos+2);
2547 tableHdrs[i].tag[3] = getByte(pos+3);
2548 tableHdrs[i].checksum = getULong(pos+4);
2549 tableHdrs[i].offset = getULong(pos+8);
2550 tableHdrs[i].length = getULong(pos+12);
2554 // check for tables that are required by both the TrueType spec
2555 // and the Type 42 spec
2556 if (seekTable("head") < 0 ||
2557 seekTable("hhea") < 0 ||
2558 seekTable("loca") < 0 ||
2559 seekTable("maxp") < 0 ||
2560 seekTable("glyf") < 0 ||
2561 seekTable("hmtx") < 0) {
2562 error(-1, "TrueType font file is missing a required table");
2566 // read the 'head' table
2567 pos = seekTable("head");
2568 bbox[0] = getShort(pos + 36);
2569 bbox[1] = getShort(pos + 38);
2570 bbox[2] = getShort(pos + 40);
2571 bbox[3] = getShort(pos + 42);
2572 locaFmt = getShort(pos + 50);
2574 // read the 'maxp' table
2575 pos = seekTable("maxp");
2576 nGlyphs = getUShort(pos + 4);
2579 TrueTypeFontFile::~TrueTypeFontFile() {
2583 for (i = 0; i < 256; ++i) {
2591 char *TrueTypeFontFile::getName() {
2595 char **TrueTypeFontFile::getEncoding() {
2597 int nCmaps, cmapPlatform, cmapEncoding, cmapFmt;
2598 int cmapLen, cmapOffset, cmapFirst;
2599 int segCnt, segStart, segEnd, segDelta, segOffset;
2603 int stringIdx, stringPos, n;
2609 //----- construct the (char code) -> (glyph idx) mapping
2611 // map everything to the missing glyph
2612 for (i = 0; i < 256; ++i) {
2616 // look for the 'cmap' table
2617 if ((pos = seekTable("cmap")) >= 0) {
2618 nCmaps = getUShort(pos+2);
2620 // if the font has a Windows-symbol cmap, use it;
2621 // otherwise, use the first cmap in the table
2622 for (i = 0; i < nCmaps; ++i) {
2623 cmapPlatform = getUShort(pos + 4 + 8*i);
2624 cmapEncoding = getUShort(pos + 4 + 8*i + 2);
2625 if (cmapPlatform == 3 && cmapEncoding == 0) {
2631 cmapPlatform = getUShort(pos + 4);
2632 cmapEncoding = getUShort(pos + 4 + 2);
2634 pos += getULong(pos + 4 + 8*i + 4);
2637 cmapFmt = getUShort(pos);
2639 case 0: // byte encoding table (Apple standard)
2640 cmapLen = getUShort(pos + 2);
2641 for (i = 0; i < cmapLen && i < 256; ++i) {
2642 cmap[i] = getByte(pos + 6 + i);
2645 case 4: // segment mapping to delta values (Microsoft standard)
2646 if (cmapPlatform == 3 && cmapEncoding == 0) {
2647 // Windows-symbol uses char codes 0xf000 - 0xf0ff
2648 cmapOffset = 0xf000;
2652 segCnt = getUShort(pos + 6) / 2;
2653 for (i = 0; i < segCnt; ++i) {
2654 segEnd = getUShort(pos + 14 + 2*i);
2655 segStart = getUShort(pos + 16 + 2*segCnt + 2*i);
2656 segDelta = getUShort(pos + 16 + 4*segCnt + 2*i);
2657 segOffset = getUShort(pos + 16 + 6*segCnt + 2*i);
2658 if (segStart - cmapOffset <= 0xff &&
2659 segEnd - cmapOffset >= 0) {
2660 for (j = (segStart - cmapOffset >= 0) ? segStart : cmapOffset;
2661 j <= segEnd && j - cmapOffset <= 0xff;
2663 if (segOffset == 0) {
2664 k = (j + segDelta) & 0xffff;
2666 k = getUShort(pos + 16 + 6*segCnt + 2*i +
2667 segOffset + 2 * (j - segStart));
2669 k = (k + segDelta) & 0xffff;
2672 cmap[j - cmapOffset] = k;
2677 case 6: // trimmed table mapping
2678 cmapFirst = getUShort(pos + 6);
2679 cmapLen = getUShort(pos + 8);
2680 for (i = cmapFirst; i < 256 && i < cmapFirst + cmapLen; ++i) {
2681 cmap[i] = getUShort(pos + 10 + 2*i);
2685 error(-1, "Unimplemented cmap format (%d) in TrueType font file",
2691 //----- construct the (glyph idx) -> (glyph name) mapping
2692 //----- and compute the (char code) -> (glyph name) mapping
2694 encoding = (char **)gmalloc(256 * sizeof(char *));
2695 for (i = 0; i < 256; ++i) {
2699 if ((pos = seekTable("post")) >= 0) {
2700 fmt = getULong(pos);
2703 if (fmt == 0x00010000) {
2704 for (i = 0; i < 256; ++i) {
2705 j = (cmap[i] < 258) ? cmap[i] : 0;
2706 encoding[i] = copyString(macGlyphNames[j]);
2710 } else if (fmt == 0x00020000) {
2712 stringPos = pos + 34 + 2*nGlyphs;
2713 for (i = 0; i < 256; ++i) {
2714 if (cmap[i] < nGlyphs) {
2715 j = getUShort(pos + 34 + 2 * cmap[i]);
2717 encoding[i] = copyString(macGlyphNames[j]);
2720 if (j != stringIdx) {
2721 for (stringIdx = 0, stringPos = pos + 34 + 2*nGlyphs;
2723 ++stringIdx, stringPos += 1 + getByte(stringPos)) ;
2725 n = getByte(stringPos);
2726 s = new GString(file + stringPos + 1, n);
2727 encoding[i] = copyString(s->getCString());
2733 encoding[i] = copyString(macGlyphNames[0]);
2738 } else if (fmt == 0x000280000) {
2739 for (i = 0; i < 256; ++i) {
2740 if (cmap[i] < nGlyphs) {
2741 j = i + getChar(pos + 32 + cmap[i]);
2745 encoding[i] = copyString(macGlyphNames[j]);
2748 // Ugh, just assume the Apple glyph set
2750 for (i = 0; i < 256; ++i) {
2751 j = (cmap[i] < 258) ? cmap[i] : 0;
2752 encoding[i] = copyString(macGlyphNames[j]);
2756 // no "post" table: assume the Apple glyph set
2758 for (i = 0; i < 256; ++i) {
2759 j = (cmap[i] < 258) ? cmap[i] : 0;
2760 encoding[i] = copyString(macGlyphNames[j]);
2767 void TrueTypeFontFile::convertToType42(char *name, char **encodingA,
2768 CharCodeToUnicode *toUnicode,
2769 GBool pdfFontHasEncoding, FILE *out) {
2771 fprintf(out, "%%!PS-TrueTypeFont-%g\n", getFixed(0));
2773 // begin the font dictionary
2774 fprintf(out, "10 dict begin\n");
2775 fprintf(out, "/FontName /%s def\n", name);
2776 fprintf(out, "/FontType 42 def\n");
2777 fprintf(out, "/FontMatrix [1 0 0 1 0 0] def\n");
2778 fprintf(out, "/FontBBox [%d %d %d %d] def\n",
2779 bbox[0], bbox[1], bbox[2], bbox[3]);
2780 fprintf(out, "/PaintType 0 def\n");
2782 // write the guts of the dictionary
2783 cvtEncoding(encodingA, out);
2784 cvtCharStrings(encodingA, toUnicode, pdfFontHasEncoding, out);
2785 cvtSfnts(out, NULL);
2787 // end the dictionary and define the font
2788 fprintf(out, "FontName currentdict end definefont pop\n");
2791 void TrueTypeFontFile::convertToCIDType2(char *name, Gushort *cidMap,
2792 int nCIDs, FILE *out) {
2797 fprintf(out, "%%!PS-TrueTypeFont-%g\n", getFixed(0));
2799 // begin the font dictionary
2800 fprintf(out, "20 dict begin\n");
2801 fprintf(out, "/CIDFontName /%s def\n", name);
2802 fprintf(out, "/CIDFontType 2 def\n");
2803 fprintf(out, "/FontType 42 def\n");
2804 fprintf(out, "/CIDSystemInfo 3 dict dup begin\n");
2805 fprintf(out, " /Registry (Adobe) def\n");
2806 fprintf(out, " /Ordering (Identity) def\n");
2807 fprintf(out, " /Supplement 0 def\n");
2808 fprintf(out, " end def\n");
2809 fprintf(out, "/GDBytes 2 def\n");
2811 fprintf(out, "/CIDCount %d def\n", nCIDs);
2812 if (nCIDs > 32767) {
2813 fprintf(out, "/CIDMap [");
2814 for (i = 0; i < nCIDs; i += 32768 - 16) {
2815 fprintf(out, "<\n");
2816 for (j = 0; j < 32768 - 16 && i+j < nCIDs; j += 16) {
2818 for (k = 0; k < 16 && i+j+k < nCIDs; ++k) {
2819 cid = cidMap[i+j+k];
2820 fprintf(out, "%02x%02x", (cid >> 8) & 0xff, cid & 0xff);
2827 fprintf(out, "] def\n");
2829 fprintf(out, "/CIDMap <\n");
2830 for (i = 0; i < nCIDs; i += 16) {
2832 for (j = 0; j < 16 && i+j < nCIDs; ++j) {
2834 fprintf(out, "%02x%02x", (cid >> 8) & 0xff, cid & 0xff);
2838 fprintf(out, "> def\n");
2841 // direct mapping - just fill the string(s) with s[i]=i
2842 fprintf(out, "/CIDCount %d def\n", nGlyphs);
2843 if (nGlyphs > 32767) {
2844 fprintf(out, "/CIDMap [\n");
2845 for (i = 0; i < nGlyphs; i += 32767) {
2846 j = nGlyphs - i < 32767 ? nGlyphs - i : 32767;
2847 fprintf(out, " %d string 0 1 %d {\n", 2 * j, j - 1);
2848 fprintf(out, " 2 copy dup 2 mul exch %d add -8 bitshift put\n", i);
2849 fprintf(out, " 1 index exch dup 2 mul 1 add exch %d add"
2850 " 255 and put\n", i);
2851 fprintf(out, " } for\n");
2853 fprintf(out, "] def\n");
2855 fprintf(out, "/CIDMap %d string\n", 2 * nGlyphs);
2856 fprintf(out, " 0 1 %d {\n", nGlyphs - 1);
2857 fprintf(out, " 2 copy dup 2 mul exch -8 bitshift put\n");
2858 fprintf(out, " 1 index exch dup 2 mul 1 add exch 255 and put\n");
2859 fprintf(out, " } for\n");
2860 fprintf(out, "def\n");
2863 fprintf(out, "/FontMatrix [1 0 0 1 0 0] def\n");
2864 fprintf(out, "/FontBBox [%d %d %d %d] def\n",
2865 bbox[0], bbox[1], bbox[2], bbox[3]);
2866 fprintf(out, "/PaintType 0 def\n");
2867 fprintf(out, "/Encoding [] readonly def\n");
2868 fprintf(out, "/CharStrings 1 dict dup begin\n");
2869 fprintf(out, " /.notdef 0 def\n");
2870 fprintf(out, " end readonly def\n");
2872 // write the guts of the dictionary
2873 cvtSfnts(out, NULL);
2875 // end the dictionary and define the font
2876 fprintf(out, "CIDFontName currentdict end /CIDFont defineresource pop\n");
2879 void TrueTypeFontFile::convertToType0(char *name, Gushort *cidMap,
2880 int nCIDs, FILE *out) {
2884 // write the Type 42 sfnts array
2885 sfntsName = (new GString(name))->append("_sfnts");
2886 cvtSfnts(out, sfntsName);
2889 // write the descendant Type 42 fonts
2890 n = cidMap ? nCIDs : nGlyphs;
2891 for (i = 0; i < n; i += 256) {
2892 fprintf(out, "10 dict begin\n");
2893 fprintf(out, "/FontName /%s_%02x def\n", name, i >> 8);
2894 fprintf(out, "/FontType 42 def\n");
2895 fprintf(out, "/FontMatrix [1 0 0 1 0 0] def\n");
2896 fprintf(out, "/FontBBox [%d %d %d %d] def\n",
2897 bbox[0], bbox[1], bbox[2], bbox[3]);
2898 fprintf(out, "/PaintType 0 def\n");
2899 fprintf(out, "/sfnts %s_sfnts def\n", name);
2900 fprintf(out, "/Encoding 256 array\n");
2901 for (j = 0; j < 256 && i+j < n; ++j) {
2902 fprintf(out, "dup %d /c%02x put\n", j, j);
2904 fprintf(out, "readonly def\n");
2905 fprintf(out, "/CharStrings 257 dict dup begin\n");
2906 fprintf(out, "/.notdef 0 def\n");
2907 for (j = 0; j < 256 && i+j < n; ++j) {
2908 fprintf(out, "/c%02x %d def\n", j, cidMap ? cidMap[i+j] : i+j);
2910 fprintf(out, "end readonly def\n");
2911 fprintf(out, "FontName currentdict end definefont pop\n");
2914 // write the Type 0 parent font
2915 fprintf(out, "16 dict begin\n");
2916 fprintf(out, "/FontName /%s def\n", name);
2917 fprintf(out, "/FontType 0 def\n");
2918 fprintf(out, "/FontMatrix [1 0 0 1 0 0] def\n");
2919 fprintf(out, "/FMapType 2 def\n");
2920 fprintf(out, "/Encoding [\n");
2921 for (i = 0; i < n; i += 256) {
2922 fprintf(out, "%d\n", i >> 8);
2924 fprintf(out, "] def\n");
2925 fprintf(out, "/FDepVector [\n");
2926 for (i = 0; i < n; i += 256) {
2927 fprintf(out, "/%s_%02x findfont\n", name, i >> 8);
2929 fprintf(out, "] def\n");
2930 fprintf(out, "FontName currentdict end definefont pop\n");
2933 int TrueTypeFontFile::getByte(int pos) {
2934 if (pos < 0 || pos >= len) {
2937 return file[pos] & 0xff;
2940 int TrueTypeFontFile::getChar(int pos) {
2943 if (pos < 0 || pos >= len) {
2946 x = file[pos] & 0xff;
2952 int TrueTypeFontFile::getUShort(int pos) {
2955 if (pos < 0 || pos+1 >= len) {
2958 x = file[pos] & 0xff;
2959 x = (x << 8) + (file[pos+1] & 0xff);
2963 int TrueTypeFontFile::getShort(int pos) {
2966 if (pos < 0 || pos+1 >= len) {
2969 x = file[pos] & 0xff;
2970 x = (x << 8) + (file[pos+1] & 0xff);
2976 Guint TrueTypeFontFile::getULong(int pos) {
2979 if (pos < 0 || pos+3 >= len) {
2982 x = file[pos] & 0xff;
2983 x = (x << 8) + (file[pos+1] & 0xff);
2984 x = (x << 8) + (file[pos+2] & 0xff);
2985 x = (x << 8) + (file[pos+3] & 0xff);
2989 double TrueTypeFontFile::getFixed(int pos) {
2993 y = getUShort(pos+2);
2994 return (double)x + (double)y / 65536;
2997 int TrueTypeFontFile::seekTable(char *tag) {
3000 for (i = 0; i < nTables; ++i) {
3001 if (!strncmp(tableHdrs[i].tag, tag, 4)) {
3002 return tableHdrs[i].offset;
3008 int TrueTypeFontFile::seekTableIdx(char *tag) {
3011 for (i = 0; i < nTables; ++i) {
3012 if (!strncmp(tableHdrs[i].tag, tag, 4)) {
3019 void TrueTypeFontFile::cvtEncoding(char **encodingA, FILE *out) {
3023 fprintf(out, "/Encoding 256 array\n");
3024 for (i = 0; i < 256; ++i) {
3025 if (!(name = encodingA[i])) {
3028 fprintf(out, "dup %d /%s put\n", i, name);
3030 fprintf(out, "readonly def\n");
3033 void TrueTypeFontFile::cvtCharStrings(char **encodingA,
3034 CharCodeToUnicode *toUnicode,
3035 GBool pdfFontHasEncoding, FILE *out) {
3036 int unicodeCmap, macRomanCmap, msSymbolCmap;
3037 int nCmaps, cmapPlatform, cmapEncoding, cmapFmt, cmapOffset;
3038 T42FontIndexMode mode;
3043 // always define '.notdef'
3044 fprintf(out, "/CharStrings 256 dict dup begin\n");
3045 fprintf(out, "/.notdef 0 def\n");
3047 // if there's no 'cmap' table, punt
3048 if ((pos = seekTable("cmap")) < 0) {
3052 // To match up with the Adobe-defined behaviour, we choose a cmap
3054 // 1. If the PDF font has an encoding:
3055 // 1a. If the TrueType font has a Microsoft Unicode cmap, use it,
3056 // and use the Unicode indexes, not the char codes.
3057 // 1b. If the TrueType font has a Macintosh Roman cmap, use it,
3058 // and reverse map the char names through MacRomanEncoding to
3060 // 2. If the PDF font does not have an encoding:
3061 // 2a. If the TrueType font has a Macintosh Roman cmap, use it,
3062 // and use char codes directly.
3063 // 2b. If the TrueType font has a Microsoft Symbol cmap, use it,
3064 // and use (0xf000 + char code).
3065 // 3. If none of these rules apply, use the first cmap and hope for
3066 // the best (this shouldn't happen).
3067 nCmaps = getUShort(pos+2);
3068 unicodeCmap = macRomanCmap = msSymbolCmap = -1;
3070 for (i = 0; i < nCmaps; ++i) {
3071 cmapPlatform = getUShort(pos + 4 + 8*i);
3072 cmapEncoding = getUShort(pos + 4 + 8*i + 2);
3073 if (cmapPlatform == 3 && cmapEncoding == 1) {
3075 } else if (cmapPlatform == 1 && cmapEncoding == 0) {
3077 } else if (cmapPlatform == 3 && cmapEncoding == 0) {
3082 mode = t42FontModeCharCode;
3083 if (pdfFontHasEncoding) {
3084 if (unicodeCmap >= 0) {
3086 mode = t42FontModeUnicode;
3087 } else if (macRomanCmap >= 0) {
3089 mode = t42FontModeMacRoman;
3092 if (macRomanCmap >= 0) {
3094 mode = t42FontModeCharCode;
3095 } else if (msSymbolCmap >= 0) {
3097 mode = t42FontModeCharCodeOffset;
3098 cmapOffset = 0xf000;
3101 cmapPlatform = getUShort(pos + 4 + 8*i);
3102 cmapEncoding = getUShort(pos + 4 + 8*i + 2);
3103 pos += getULong(pos + 4 + 8*i + 4);
3104 cmapFmt = getUShort(pos);
3105 if (cmapFmt != 0 && cmapFmt != 4 && cmapFmt != 6) {
3106 error(-1, "Unimplemented cmap format (%d) in TrueType font file",
3111 // map char name to glyph index:
3112 // 1. use encoding to map name to char code
3113 // 2. use cmap to map char code to glyph index
3114 j = 0; // make gcc happy
3115 for (i = 0; i < 256; ++i) {
3116 name = encodingA[i];
3117 if (name && strcmp(name, ".notdef")) {
3119 case t42FontModeUnicode:
3120 toUnicode->mapToUnicode((CharCode)i, &u, 1);
3123 case t42FontModeCharCode:
3126 case t42FontModeCharCodeOffset:
3129 case t42FontModeMacRoman:
3130 j = globalParams->getMacRomanCharCode(name);
3133 // note: Distiller (maybe Adobe's PS interpreter in general)
3134 // doesn't like TrueType fonts that have CharStrings entries
3135 // which point to nonexistent glyphs, hence the (k < nGlyphs)
3137 if ((k = getCmapEntry(cmapFmt, pos, j)) > 0 &&
3139 fprintf(out, "/%s %d def\n", name, k);
3145 fprintf(out, "end readonly def\n");
3148 int TrueTypeFontFile::getCmapEntry(int cmapFmt, int pos, int code) {
3149 int cmapLen, cmapFirst;
3150 int segCnt, segEnd, segStart, segDelta, segOffset;
3154 case 0: // byte encoding table (Apple standard)
3155 cmapLen = getUShort(pos + 2);
3156 if (code >= cmapLen) {
3159 return getByte(pos + 6 + code);
3161 case 4: // segment mapping to delta values (Microsoft standard)
3162 segCnt = getUShort(pos + 6) / 2;
3165 segEnd = getUShort(pos + 14 + 2*b);
3166 if (code > segEnd) {
3167 // malformed font -- the TrueType spec requires the last segEnd
3171 // invariant: seg[a].end < code <= seg[b].end
3174 segEnd = getUShort(pos + 14 + 2*m);
3175 if (segEnd < code) {
3181 segStart = getUShort(pos + 16 + 2*segCnt + 2*b);
3182 segDelta = getUShort(pos + 16 + 4*segCnt + 2*b);
3183 segOffset = getUShort(pos + 16 + 6*segCnt + 2*b);
3184 if (segOffset == 0) {
3185 i = (code + segDelta) & 0xffff;
3187 i = getUShort(pos + 16 + 6*segCnt + 2*b +
3188 segOffset + 2 * (code - segStart));
3190 i = (i + segDelta) & 0xffff;
3195 case 6: // trimmed table mapping
3196 cmapFirst = getUShort(pos + 6);
3197 cmapLen = getUShort(pos + 8);
3198 if (code < cmapFirst || code >= cmapFirst + cmapLen) {
3201 return getUShort(pos + 10 + 2*(code - cmapFirst));
3204 // shouldn't happen - this is checked earlier
3210 void TrueTypeFontFile::cvtSfnts(FILE *out, GString *name) {
3211 TTFontTableHdr newTableHdrs[nT42Tables];
3212 char tableDir[12 + nT42Tables*16];
3218 int pos, glyfPos, length, glyphLength, pad;
3221 // construct the 'head' table, zero out the font checksum
3222 memcpy(headTable, file + seekTable("head"), 54);
3223 headTable[8] = headTable[9] = headTable[10] = headTable[11] = (char)0;
3225 // read the original 'loca' table and construct the new one
3226 // (pad each glyph out to a multiple of 4 bytes)
3227 origLocaTable = (int *)gmalloc((nGlyphs + 1) * sizeof(int));
3228 pos = seekTable("loca");
3229 for (i = 0; i <= nGlyphs; ++i) {
3231 origLocaTable[i] = getULong(pos + 4*i);
3233 origLocaTable[i] = 2 * getUShort(pos + 2*i);
3236 locaTable = (char *)gmalloc((nGlyphs + 1) * (locaFmt ? 4 : 2));
3238 locaTable[0] = locaTable[1] = locaTable[2] = locaTable[3] = 0;
3240 locaTable[0] = locaTable[1] = 0;
3243 for (i = 1; i <= nGlyphs; ++i) {
3244 length = origLocaTable[i] - origLocaTable[i-1];
3246 length += 4 - (length & 3);
3250 locaTable[4*i ] = (char)(pos >> 24);
3251 locaTable[4*i+1] = (char)(pos >> 16);
3252 locaTable[4*i+2] = (char)(pos >> 8);
3253 locaTable[4*i+3] = (char) pos;
3255 locaTable[2*i ] = (char)(pos >> 9);
3256 locaTable[2*i+1] = (char)(pos >> 1);
3260 // count the number of tables
3262 for (i = 0; i < nT42Tables; ++i) {
3263 if (t42Tables[i].required ||
3264 seekTable(t42Tables[i].tag) >= 0) {
3269 // construct the new table headers, including table checksums
3270 // (pad each table out to a multiple of 4 bytes)
3271 pos = 12 + nNewTables*16;
3273 for (i = 0; i < nT42Tables; ++i) {
3275 checksum = 0; // make gcc happy
3276 if (i == t42HeadTable) {
3278 checksum = computeTableChecksum(headTable, 54);
3279 } else if (i == t42LocaTable) {
3280 length = (nGlyphs + 1) * (locaFmt ? 4 : 2);
3281 checksum = computeTableChecksum(locaTable, length);
3282 } else if (i == t42GlyfTable) {
3285 glyfPos = seekTable("glyf");
3286 for (j = 0; j < nGlyphs; ++j) {
3287 glyphLength = origLocaTable[j+1] - origLocaTable[j];
3288 pad = (glyphLength & 3) ? 4 - (glyphLength & 3) : 0;
3289 length += glyphLength + pad;
3290 checksum += computeTableChecksum(file + glyfPos + origLocaTable[j],
3294 if ((j = seekTableIdx(t42Tables[i].tag)) >= 0) {
3295 length = tableHdrs[j].length;
3296 checksum = computeTableChecksum(file + tableHdrs[j].offset, length);
3297 } else if (t42Tables[i].required) {
3298 error(-1, "Embedded TrueType font is missing a required table ('%s')",
3305 strncpy(newTableHdrs[k].tag, t42Tables[i].tag, 4);
3306 newTableHdrs[k].checksum = checksum;
3307 newTableHdrs[k].offset = pos;
3308 newTableHdrs[k].length = length;
3309 pad = (length & 3) ? 4 - (length & 3) : 0;
3310 pos += length + pad;
3315 // construct the table directory
3316 tableDir[0] = 0x00; // sfnt version
3320 tableDir[4] = 0; // numTables
3321 tableDir[5] = nNewTables;
3322 tableDir[6] = 0; // searchRange
3323 tableDir[7] = (char)128;
3324 tableDir[8] = 0; // entrySelector
3326 tableDir[10] = 0; // rangeShift
3327 tableDir[11] = (char)(16 * nNewTables - 128);
3329 for (i = 0; i < nNewTables; ++i) {
3330 tableDir[pos ] = newTableHdrs[i].tag[0];
3331 tableDir[pos+ 1] = newTableHdrs[i].tag[1];
3332 tableDir[pos+ 2] = newTableHdrs[i].tag[2];
3333 tableDir[pos+ 3] = newTableHdrs[i].tag[3];
3334 tableDir[pos+ 4] = (char)(newTableHdrs[i].checksum >> 24);
3335 tableDir[pos+ 5] = (char)(newTableHdrs[i].checksum >> 16);
3336 tableDir[pos+ 6] = (char)(newTableHdrs[i].checksum >> 8);
3337 tableDir[pos+ 7] = (char) newTableHdrs[i].checksum;
3338 tableDir[pos+ 8] = (char)(newTableHdrs[i].offset >> 24);
3339 tableDir[pos+ 9] = (char)(newTableHdrs[i].offset >> 16);
3340 tableDir[pos+10] = (char)(newTableHdrs[i].offset >> 8);
3341 tableDir[pos+11] = (char) newTableHdrs[i].offset;
3342 tableDir[pos+12] = (char)(newTableHdrs[i].length >> 24);
3343 tableDir[pos+13] = (char)(newTableHdrs[i].length >> 16);
3344 tableDir[pos+14] = (char)(newTableHdrs[i].length >> 8);
3345 tableDir[pos+15] = (char) newTableHdrs[i].length;
3349 // compute the font checksum and store it in the head table
3350 checksum = computeTableChecksum(tableDir, 12 + nNewTables*16);
3351 for (i = 0; i < nNewTables; ++i) {
3352 checksum += newTableHdrs[i].checksum;
3354 checksum = 0xb1b0afba - checksum; // because the TrueType spec says so
3355 headTable[ 8] = (char)(checksum >> 24);
3356 headTable[ 9] = (char)(checksum >> 16);
3357 headTable[10] = (char)(checksum >> 8);
3358 headTable[11] = (char) checksum;
3360 // start the sfnts array
3362 fprintf(out, "/%s [\n", name->getCString());
3364 fprintf(out, "/sfnts [\n");
3367 // write the table directory
3368 dumpString(tableDir, 12 + nNewTables*16, out);
3371 for (i = 0; i < nNewTables; ++i) {
3372 if (i == t42HeadTable) {
3373 dumpString(headTable, 54, out);
3374 } else if (i == t42LocaTable) {
3375 length = (nGlyphs + 1) * (locaFmt ? 4 : 2);
3376 dumpString(locaTable, length, out);
3377 } else if (i == t42GlyfTable) {
3378 glyfPos = seekTable("glyf");
3379 for (j = 0; j < nGlyphs; ++j) {
3380 length = origLocaTable[j+1] - origLocaTable[j];
3382 dumpString(file + glyfPos + origLocaTable[j], length, out);
3386 // length == 0 means the table is missing and the error was
3387 // already reported during the construction of the table
3389 if ((length = newTableHdrs[i].length) > 0) {
3390 dumpString(file + seekTable(t42Tables[i].tag), length, out);
3395 // end the sfnts array
3396 fprintf(out, "] def\n");
3398 gfree(origLocaTable);
3402 void TrueTypeFontFile::dumpString(char *s, int length, FILE *out) {
3406 for (i = 0; i < length; i += 32) {
3407 for (j = 0; j < 32 && i+j < length; ++j) {
3408 fprintf(out, "%02X", s[i+j] & 0xff);
3410 if (i % (65536 - 32) == 65536 - 64) {
3411 fprintf(out, ">\n<");
3412 } else if (i+32 < length) {
3417 pad = 4 - (length & 3);
3418 for (i = 0; i < pad; ++i) {
3422 // add an extra zero byte because the Adobe Type 42 spec says so
3423 fprintf(out, "00>\n");
3426 Guint TrueTypeFontFile::computeTableChecksum(char *data, int length) {
3427 Guint checksum, word;
3431 for (i = 0; i+3 < length; i += 4) {
3432 word = ((data[i ] & 0xff) << 24) +
3433 ((data[i+1] & 0xff) << 16) +
3434 ((data[i+2] & 0xff) << 8) +
3441 switch (length & 3) {
3443 word |= (data[i+2] & 0xff) << 8;
3445 word |= (data[i+1] & 0xff) << 16;
3447 word |= (data[i ] & 0xff) << 24;
3455 void TrueTypeFontFile::writeTTF(FILE *out) {
3456 static char cmapTab[20] = {
3457 0, 0, // table version number
3458 0, 1, // number of encoding tables
3459 0, 1, // platform ID
3460 0, 0, // encoding ID
3461 0, 0, 0, 12, // offset of subtable
3462 0, 0, // subtable format
3463 0, 1, // subtable length
3464 0, 1, // subtable version
3465 0, // map char 0 -> glyph 0
3466 0 // pad to multiple of four bytes
3468 static char nameTab[8] = {
3470 0, 0, // number of name records
3471 0, 6, // offset to start of string storage
3472 0, 0 // pad to multiple of four bytes
3474 static char postTab[32] = {
3475 0, 1, 0, 0, // format
3476 0, 0, 0, 0, // italic angle
3477 0, 0, // underline position
3478 0, 0, // underline thickness
3479 0, 0, 0, 0, // fixed pitch
3480 0, 0, 0, 0, // min Type 42 memory
3481 0, 0, 0, 0, // max Type 42 memory
3482 0, 0, 0, 0, // min Type 1 memory
3483 0, 0, 0, 0 // max Type 1 memory
3485 GBool haveCmap, haveName, havePost;
3486 GBool dirCmap, dirName, dirPost;
3487 int nNewTables, nAllTables, pad;
3492 // check for missing tables
3493 haveCmap = seekTable("cmap") >= 0;
3494 haveName = seekTable("name") >= 0;
3495 havePost = seekTable("post") >= 0;
3496 nNewTables = (haveCmap ? 0 : 1) + (haveName ? 0 : 1) + (havePost ? 0 : 1);
3498 // none are missing - write the TTF file as is
3499 fwrite(file, 1, len, out);
3503 // construct the new table directory
3504 nAllTables = nTables + nNewTables;
3505 tableDir = (char *)gmalloc(12 + nAllTables * 16);
3506 memcpy(tableDir, file, 12 + nTables * 16);
3507 tableDir[4] = (char)((nAllTables >> 8) & 0xff);
3508 tableDir[5] = (char)(nAllTables & 0xff);
3509 for (i = -1, t = (Guint)nAllTables; t; ++i, t >>= 1) ;
3511 tableDir[6] = (char)((t >> 8) & 0xff);
3512 tableDir[7] = (char)(t & 0xff);
3513 tableDir[8] = (char)((i >> 8) & 0xff);
3514 tableDir[9] = (char)(i & 0xff);
3515 t = nAllTables * 16 - t;
3516 tableDir[10] = (char)((t >> 8) & 0xff);
3517 tableDir[11] = (char)(t & 0xff);
3522 pad = (len & 3) ? 4 - (len & 3) : 0;
3523 pos = len + pad + 16 * nNewTables;
3524 for (i = 0; i < nTables; ++i) {
3525 if (!dirCmap && strncmp(tableHdrs[i].tag, "cmap", 4) > 0) {
3526 tableDir[12 + 16*j ] = 'c';
3527 tableDir[12 + 16*j + 1] = 'm';
3528 tableDir[12 + 16*j + 2] = 'a';
3529 tableDir[12 + 16*j + 3] = 'p';
3530 tableDir[12 + 16*j + 4] = (char)0; //~ should compute the checksum
3531 tableDir[12 + 16*j + 5] = (char)0;
3532 tableDir[12 + 16*j + 6] = (char)0;
3533 tableDir[12 + 16*j + 7] = (char)0;
3534 tableDir[12 + 16*j + 8] = (char)((pos >> 24) & 0xff);
3535 tableDir[12 + 16*j + 9] = (char)((pos >> 16) & 0xff);
3536 tableDir[12 + 16*j + 10] = (char)((pos >> 8) & 0xff);
3537 tableDir[12 + 16*j + 11] = (char)( pos & 0xff);
3538 tableDir[12 + 16*j + 12] = (char)((sizeof(cmapTab) >> 24) & 0xff);
3539 tableDir[12 + 16*j + 13] = (char)((sizeof(cmapTab) >> 16) & 0xff);
3540 tableDir[12 + 16*j + 14] = (char)((sizeof(cmapTab) >> 8) & 0xff);
3541 tableDir[12 + 16*j + 15] = (char)( sizeof(cmapTab) & 0xff);
3542 pos += sizeof(cmapTab);
3546 if (!dirName && strncmp(tableHdrs[i].tag, "name", 4) > 0) {
3547 tableDir[12 + 16*j ] = 'n';
3548 tableDir[12 + 16*j + 1] = 'a';
3549 tableDir[12 + 16*j + 2] = 'm';
3550 tableDir[12 + 16*j + 3] = 'e';
3551 tableDir[12 + 16*j + 4] = (char)0; //~ should compute the checksum
3552 tableDir[12 + 16*j + 5] = (char)0;
3553 tableDir[12 + 16*j + 6] = (char)0;
3554 tableDir[12 + 16*j + 7] = (char)0;
3555 tableDir[12 + 16*j + 8] = (char)((pos >> 24) & 0xff);
3556 tableDir[12 + 16*j + 9] = (char)((pos >> 16) & 0xff);
3557 tableDir[12 + 16*j + 10] = (char)((pos >> 8) & 0xff);
3558 tableDir[12 + 16*j + 11] = (char)( pos & 0xff);
3559 tableDir[12 + 16*j + 12] = (char)((sizeof(nameTab) >> 24) & 0xff);
3560 tableDir[12 + 16*j + 13] = (char)((sizeof(nameTab) >> 16) & 0xff);
3561 tableDir[12 + 16*j + 14] = (char)((sizeof(nameTab) >> 8) & 0xff);
3562 tableDir[12 + 16*j + 15] = (char)( sizeof(nameTab) & 0xff);
3563 pos += sizeof(nameTab);
3567 if (!dirName && strncmp(tableHdrs[i].tag, "post", 4) > 0) {
3568 tableDir[12 + 16*j ] = 'p';
3569 tableDir[12 + 16*j + 1] = 'o';
3570 tableDir[12 + 16*j + 2] = 's';
3571 tableDir[12 + 16*j + 3] = 't';
3572 tableDir[12 + 16*j + 4] = (char)0; //~ should compute the checksum
3573 tableDir[12 + 16*j + 5] = (char)0;
3574 tableDir[12 + 16*j + 6] = (char)0;
3575 tableDir[12 + 16*j + 7] = (char)0;
3576 tableDir[12 + 16*j + 8] = (char)((pos >> 24) & 0xff);
3577 tableDir[12 + 16*j + 9] = (char)((pos >> 16) & 0xff);
3578 tableDir[12 + 16*j + 10] = (char)((pos >> 8) & 0xff);
3579 tableDir[12 + 16*j + 11] = (char)( pos & 0xff);
3580 tableDir[12 + 16*j + 12] = (char)((sizeof(postTab) >> 24) & 0xff);
3581 tableDir[12 + 16*j + 13] = (char)((sizeof(postTab) >> 16) & 0xff);
3582 tableDir[12 + 16*j + 14] = (char)((sizeof(postTab) >> 8) & 0xff);
3583 tableDir[12 + 16*j + 15] = (char)( sizeof(postTab) & 0xff);
3584 pos += sizeof(postTab);
3588 memcpy(&tableDir[12 + 16*j], file + 12 + 16*i, 16);
3589 t = tableHdrs[i].offset + nNewTables * 16;
3590 tableDir[12 + 16*j + 8] = (char)((t >> 24) & 0xff);
3591 tableDir[12 + 16*j + 9] = (char)((t >> 16) & 0xff);
3592 tableDir[12 + 16*j + 10] = (char)((t >> 8) & 0xff);
3593 tableDir[12 + 16*j + 11] = (char)( t & 0xff);
3597 tableDir[12 + 16*j ] = 'c';
3598 tableDir[12 + 16*j + 1] = 'm';
3599 tableDir[12 + 16*j + 2] = 'a';
3600 tableDir[12 + 16*j + 3] = 'p';
3601 tableDir[12 + 16*j + 4] = (char)0; //~ should compute the checksum
3602 tableDir[12 + 16*j + 5] = (char)0;
3603 tableDir[12 + 16*j + 6] = (char)0;
3604 tableDir[12 + 16*j + 7] = (char)0;
3605 tableDir[12 + 16*j + 8] = (char)((pos >> 24) & 0xff);
3606 tableDir[12 + 16*j + 9] = (char)((pos >> 16) & 0xff);
3607 tableDir[12 + 16*j + 10] = (char)((pos >> 8) & 0xff);
3608 tableDir[12 + 16*j + 11] = (char)( pos & 0xff);
3609 tableDir[12 + 16*j + 12] = (char)((sizeof(cmapTab) >> 24) & 0xff);
3610 tableDir[12 + 16*j + 13] = (char)((sizeof(cmapTab) >> 16) & 0xff);
3611 tableDir[12 + 16*j + 14] = (char)((sizeof(cmapTab) >> 8) & 0xff);
3612 tableDir[12 + 16*j + 15] = (char)( sizeof(cmapTab) & 0xff);
3613 pos += sizeof(cmapTab);
3618 tableDir[12 + 16*j ] = 'n';
3619 tableDir[12 + 16*j + 1] = 'a';
3620 tableDir[12 + 16*j + 2] = 'm';
3621 tableDir[12 + 16*j + 3] = 'e';
3622 tableDir[12 + 16*j + 4] = (char)0; //~ should compute the checksum
3623 tableDir[12 + 16*j + 5] = (char)0;
3624 tableDir[12 + 16*j + 6] = (char)0;
3625 tableDir[12 + 16*j + 7] = (char)0;
3626 tableDir[12 + 16*j + 8] = (char)((pos >> 24) & 0xff);
3627 tableDir[12 + 16*j + 9] = (char)((pos >> 16) & 0xff);
3628 tableDir[12 + 16*j + 10] = (char)((pos >> 8) & 0xff);
3629 tableDir[12 + 16*j + 11] = (char)( pos & 0xff);
3630 tableDir[12 + 16*j + 12] = (char)((sizeof(nameTab) >> 24) & 0xff);
3631 tableDir[12 + 16*j + 13] = (char)((sizeof(nameTab) >> 16) & 0xff);
3632 tableDir[12 + 16*j + 14] = (char)((sizeof(nameTab) >> 8) & 0xff);
3633 tableDir[12 + 16*j + 15] = (char)( sizeof(nameTab) & 0xff);
3634 pos += sizeof(nameTab);
3639 tableDir[12 + 16*j ] = 'p';
3640 tableDir[12 + 16*j + 1] = 'o';
3641 tableDir[12 + 16*j + 2] = 's';
3642 tableDir[12 + 16*j + 3] = 't';
3643 tableDir[12 + 16*j + 4] = (char)0; //~ should compute the checksum
3644 tableDir[12 + 16*j + 5] = (char)0;
3645 tableDir[12 + 16*j + 6] = (char)0;
3646 tableDir[12 + 16*j + 7] = (char)0;
3647 tableDir[12 + 16*j + 8] = (char)((pos >> 24) & 0xff);
3648 tableDir[12 + 16*j + 9] = (char)((pos >> 16) & 0xff);
3649 tableDir[12 + 16*j + 10] = (char)((pos >> 8) & 0xff);
3650 tableDir[12 + 16*j + 11] = (char)( pos & 0xff);
3651 tableDir[12 + 16*j + 12] = (char)((sizeof(postTab) >> 24) & 0xff);
3652 tableDir[12 + 16*j + 13] = (char)((sizeof(postTab) >> 16) & 0xff);
3653 tableDir[12 + 16*j + 14] = (char)((sizeof(postTab) >> 8) & 0xff);
3654 tableDir[12 + 16*j + 15] = (char)( sizeof(postTab) & 0xff);
3655 pos += sizeof(postTab);
3660 // write the table directory
3661 fwrite(tableDir, 1, 12 + 16 * nAllTables, out);
3663 // write the original tables
3664 fwrite(file + 12 + 16*nTables, 1, len - (12 + 16*nTables), out);
3666 // write the new tables
3667 for (i = 0; i < pad; ++i) {
3668 fputc((char)0, out);
3671 fwrite(cmapTab, 1, sizeof(cmapTab), out);
3674 fwrite(nameTab, 1, sizeof(nameTab), out);
3677 fwrite(postTab, 1, sizeof(postTab), out);