1 //========================================================================
5 // Copyright 1999-2003 Glyph & Cog, LLC
7 //========================================================================
11 #ifdef USE_GCC_PRAGMAS
12 #pragma implementation
25 #include "GlobalParams.h"
26 #include "CharCodeToUnicode.h"
27 #include "FontEncodingTables.h"
30 #include "CompactFontTables.h"
32 //------------------------------------------------------------------------
34 static inline char *nextLine(char *line, char *end) {
35 while (line < end && *line != '\n' && *line != '\r')
37 while (line < end && (*line == '\n' || *line == '\r'))
42 static char hexChars[17] = "0123456789ABCDEF";
44 //------------------------------------------------------------------------
46 //------------------------------------------------------------------------
48 FontFile::FontFile() {
51 FontFile::~FontFile() {
54 //------------------------------------------------------------------------
56 //------------------------------------------------------------------------
58 Type1FontFile::Type1FontFile(char *file, int len) {
59 char *line, *line1, *p, *p2;
66 encoding = (char **)gmalloc(256 * sizeof(char *));
67 for (i = 0; i < 256; ++i) {
70 haveEncoding = gFalse;
72 for (i = 1, line = file;
73 i <= 100 && line < file + len && !haveEncoding;
77 if (!strncmp(line, "/FontName", 9)) {
78 strncpy(buf, line, 255);
80 if ((p = strchr(buf+9, '/')) &&
81 (p = strtok(p+1, " \t\n\r"))) {
84 line = nextLine(line, file + len);
87 } else if (!strncmp(line, "/Encoding StandardEncoding def", 30)) {
88 for (j = 0; j < 256; ++j) {
89 if (standardEncoding[j]) {
90 encoding[j] = copyString(standardEncoding[j]);
94 } else if (!strncmp(line, "/Encoding 256 array", 19)) {
95 for (j = 0; j < 300; ++j) {
96 line1 = nextLine(line, file + len);
97 if ((n = line1 - line) > 255) {
100 strncpy(buf, line, n);
102 for (p = buf; *p == ' ' || *p == '\t'; ++p) ;
103 if (!strncmp(p, "dup", 3)) {
104 for (p += 3; *p == ' ' || *p == '\t'; ++p) ;
105 for (p2 = p; *p2 >= '0' && *p2 <= '9'; ++p2) ;
109 if ((code = atoi(p)) < 256) {
111 for (p = p2; *p == ' ' || *p == '\t'; ++p) ;
114 for (p2 = p; *p2 && *p2 != ' ' && *p2 != '\t'; ++p2) ;
116 encoding[code] = copyString(p);
121 if (strtok(buf, " \t") &&
122 (p = strtok(NULL, " \t\n\r")) && !strcmp(p, "def")) {
128 //~ check for getinterval/putinterval junk
129 haveEncoding = gTrue;
132 line = nextLine(line, file + len);
137 Type1FontFile::~Type1FontFile() {
143 for (i = 0; i < 256; ++i) {
149 //------------------------------------------------------------------------
151 //------------------------------------------------------------------------
153 struct Type1CTopDict {
162 double underlinePosition;
163 double underlineThickness;
166 double fontMatrix[6];
176 //----- CIDFont entries
184 struct Type1CPrivateDict {
187 double defaultWidthX;
188 GBool defaultWidthXFP;
189 double nominalWidthX;
190 GBool nominalWidthXFP;
193 Type1CFontFile::Type1CFontFile(char *fileA, int lenA) {
194 int nameIdxPos, namePos, nameLen;
196 file = (Guchar *)fileA;
202 // some tools embed Type 1C fonts with an extra whitespace char at
204 if (len > 0 && file[0] != '\x01') {
209 // make sure the header exists
214 // read name index (first font only)
215 nameIdxPos = file[2] & 0xff;
216 if ((namePos = getIndexValPos(nameIdxPos, 0, &nameLen)) < 0) {
219 name = new GString((char *)&file[namePos], nameLen);
221 topDictIdxPos = getIndexEnd(nameIdxPos);
222 stringIdxPos = getIndexEnd(topDictIdxPos);
223 gsubrIdxPos = getIndexEnd(stringIdxPos);
228 Type1CFontFile::~Type1CFontFile() {
233 for (i = 0; i < 256; ++i) {
240 char *Type1CFontFile::getName() {
241 return name->getCString();
244 char **Type1CFontFile::getEncoding() {
251 void Type1CFontFile::readEncoding() {
253 int idxPos, idxLen, pos;
255 int nCodes, nRanges, nLeft, nSups;
257 int charset, enc, charstrings;
265 encoding = (char **)gmalloc(256 * sizeof(char *));
266 for (i = 0; i < 256; ++i) {
270 // read top dict (first font only)
271 if ((idxPos = getIndexValPos(topDictIdxPos, 0, &idxLen)) < 0) {
274 charset = enc = charstrings = 0;
277 while (pos < idxPos + idxLen) {
278 if (file[pos] <= 27 || file[pos] == 31) {
281 if (pos >= idxPos + idxLen) {
284 key = (key << 8) | file[pos++];
286 if (key == 0x0f) { // charset
287 charset = (int)op[0];
288 } else if (key == 0x10) { // encoding
290 } else if (key == 0x11) { // charstrings
291 charstrings = (int)op[0];
295 x = getNum(&pos, &isFP);
302 // get number of glyphs from charstrings index
303 nGlyphs = getIndexLen(charstrings);
305 // read charset (GID -> name mapping)
306 glyphNames = readCharset(charset, nGlyphs);
308 // read encoding (GID -> code mapping)
310 for (i = 0; i < 256; ++i) {
311 if (standardEncoding[i]) {
312 encoding[i] = copyString(standardEncoding[i]);
315 } else if (enc == 1) {
316 for (i = 0; i < 256; ++i) {
317 if (expertEncoding[i]) {
318 encoding[i] = copyString(expertEncoding[i]);
323 if (pos < 0 || pos >= len) {
326 encFormat = file[pos++];
327 if ((encFormat & 0x7f) == 0) {
331 nCodes = 1 + file[pos++];
332 if (nCodes > nGlyphs) {
335 if (pos + nCodes - 1 > len) {
338 for (i = 1; i < nCodes; ++i) {
343 encoding[c] = copyString(getString(glyphNames[i], buf));
345 } else if ((encFormat & 0x7f) == 1) {
349 nRanges = file[pos++];
350 if (pos + 2 * nRanges > len) {
354 for (i = 0; i < nRanges; ++i) {
357 for (j = 0; j <= nLeft && nCodes < nGlyphs; ++j) {
362 encoding[c] = copyString(getString(glyphNames[nCodes], buf));
369 if (encFormat & 0x80) {
374 if (pos + nSups * 3 > len) {
377 for (i = 0; i < nSups; ++i) {
379 sid = getWord(pos, 2);
384 encoding[c] = copyString(getString(sid, buf));
390 if (charset < 0 || charset > 2) {
395 void Type1CFontFile::convertToType1(FontFileOutputFunc outputFuncA,
396 void *outputStreamA) {
398 Type1CPrivateDict privateDict;
399 char buf[512], eBuf[256];
400 int idxPos, idxLen, pos;
401 int nGlyphs, nCodes, nRanges, nLeft, nSups;
403 int encFormat, nCharStrings;
407 outputFunc = outputFuncA;
408 outputStream = outputStreamA;
410 // read top dict (first font only)
413 // write header and font dictionary, up to encoding
414 (*outputFunc)(outputStream, "%!FontType1-1.0: ", 17);
415 (*outputFunc)(outputStream, name->getCString(), name->getLength());
416 if (dict.version != 0) {
417 getString(dict.version, buf);
418 (*outputFunc)(outputStream, buf, strlen(buf));
420 (*outputFunc)(outputStream, "\n", 1);
421 // the dictionary needs room for 12 entries: the following 9, plus
422 // Private and CharStrings (in the eexec section) and FID (which is
423 // added by definefont)
424 (*outputFunc)(outputStream, "12 dict begin\n", 14);
425 (*outputFunc)(outputStream, "/FontInfo 10 dict dup begin\n", 28);
426 if (dict.version != 0) {
427 (*outputFunc)(outputStream, "/version (", 10);
428 (*outputFunc)(outputStream, buf, strlen(buf));
429 (*outputFunc)(outputStream, ") readonly def\n", 15);
431 if (dict.notice != 0) {
432 getString(dict.notice, buf);
433 (*outputFunc)(outputStream, "/Notice (", 9);
434 (*outputFunc)(outputStream, buf, strlen(buf));
435 (*outputFunc)(outputStream, ") readonly def\n", 15);
437 if (dict.copyright != 0) {
438 getString(dict.copyright, buf);
439 (*outputFunc)(outputStream, "/Copyright (", 12);
440 (*outputFunc)(outputStream, buf, strlen(buf));
441 (*outputFunc)(outputStream, ") readonly def\n", 15);
443 if (dict.fullName != 0) {
444 getString(dict.fullName, buf);
445 (*outputFunc)(outputStream, "/FullName (", 11);
446 (*outputFunc)(outputStream, buf, strlen(buf));
447 (*outputFunc)(outputStream, ") readonly def\n", 15);
449 if (dict.familyName != 0) {
450 getString(dict.familyName, buf);
451 (*outputFunc)(outputStream, "/FamilyName (", 13);
452 (*outputFunc)(outputStream, buf, strlen(buf));
453 (*outputFunc)(outputStream, ") readonly def\n", 15);
455 if (dict.weight != 0) {
456 getString(dict.weight, buf);
457 (*outputFunc)(outputStream, "/Weight (", 9);
458 (*outputFunc)(outputStream, buf, strlen(buf));
459 (*outputFunc)(outputStream, ") readonly def\n", 15);
461 if (dict.isFixedPitch) {
462 (*outputFunc)(outputStream, "/isFixedPitch true def\n", 23);
464 (*outputFunc)(outputStream, "/isFixedPitch false def\n", 24);
466 sprintf(buf, "/ItalicAngle %g def\n", dict.italicAngle);
467 (*outputFunc)(outputStream, buf, strlen(buf));
468 sprintf(buf, "/UnderlinePosition %g def\n", dict.underlinePosition);
469 (*outputFunc)(outputStream, buf, strlen(buf));
470 sprintf(buf, "/UnderlineThickness %g def\n", dict.underlineThickness);
471 (*outputFunc)(outputStream, buf, strlen(buf));
472 (*outputFunc)(outputStream, "end readonly def\n", 17);
473 (*outputFunc)(outputStream, "/FontName /", 11);
474 (*outputFunc)(outputStream, name->getCString(), name->getLength());
475 (*outputFunc)(outputStream, " def\n", 5);
476 sprintf(buf, "/PaintType %d def\n", dict.paintType);
477 (*outputFunc)(outputStream, buf, strlen(buf));
478 (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
479 sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] readonly def\n",
480 dict.fontMatrix[0], dict.fontMatrix[1], dict.fontMatrix[2],
481 dict.fontMatrix[3], dict.fontMatrix[4], dict.fontMatrix[5]);
482 (*outputFunc)(outputStream, buf, strlen(buf));
483 sprintf(buf, "/FontBBox [%g %g %g %g] readonly def\n",
484 dict.fontBBox[0], dict.fontBBox[1],
485 dict.fontBBox[2], dict.fontBBox[3]);
486 (*outputFunc)(outputStream, buf, strlen(buf));
487 sprintf(buf, "/StrokeWidth %g def\n", dict.strokeWidth);
488 (*outputFunc)(outputStream, buf, strlen(buf));
489 if (dict.uniqueID != 0) {
490 sprintf(buf, "/UniqueID %d def\n", dict.uniqueID);
491 (*outputFunc)(outputStream, buf, strlen(buf));
494 // get number of glyphs from charstrings index
495 nGlyphs = getIndexLen(dict.charStrings);
498 glyphNames = readCharset(dict.charset, nGlyphs);
500 // read encoding (glyph -> code mapping), write Type 1 encoding
501 (*outputFunc)(outputStream, "/Encoding ", 10);
502 if (dict.encoding == 0) {
503 (*outputFunc)(outputStream, "StandardEncoding def\n", 21);
505 (*outputFunc)(outputStream, "256 array\n", 10);
506 (*outputFunc)(outputStream,
507 "0 1 255 {1 index exch /.notdef put} for\n", 40);
508 if (dict.encoding == 1) {
509 for (i = 0; i < 256; ++i) {
510 if (expertEncoding[i]) {
511 sprintf(buf, "dup %d /%s put\n", i, expertEncoding[i]);
512 (*outputFunc)(outputStream, buf, strlen(buf));
517 if (pos < 0 || pos >= len) {
520 encFormat = file[pos++];
521 if ((encFormat & 0x7f) == 0) {
525 nCodes = 1 + file[pos++];
526 if (nCodes > nGlyphs) {
529 if (pos + nCodes - 1 > len) {
532 for (i = 1; i < nCodes; ++i) {
534 sprintf(buf, "dup %d /", c);
535 (*outputFunc)(outputStream, buf, strlen(buf));
536 getString(glyphNames[i], buf);
537 (*outputFunc)(outputStream, buf, strlen(buf));
538 (*outputFunc)(outputStream, " put\n", 5);
540 } else if ((encFormat & 0x7f) == 1) {
544 nRanges = file[pos++];
545 if (pos + 2 * nRanges > len) {
549 for (i = 0; i < nRanges; ++i) {
552 for (j = 0; j <= nLeft && nCodes < nGlyphs; ++j) {
553 sprintf(buf, "dup %d /", c);
554 (*outputFunc)(outputStream, buf, strlen(buf));
555 getString(glyphNames[nCodes], buf);
556 (*outputFunc)(outputStream, buf, strlen(buf));
557 (*outputFunc)(outputStream, " put\n", 5);
563 if (encFormat & 0x80) {
568 if (pos + nSups * 3 > len) {
571 for (i = 0; i < nSups; ++i) {
573 sid = getWord(pos, 2);
575 sprintf(buf, "dup %d /", c);
576 (*outputFunc)(outputStream, buf, strlen(buf));
578 (*outputFunc)(outputStream, buf, strlen(buf));
579 (*outputFunc)(outputStream, " put\n", 5);
584 (*outputFunc)(outputStream, "readonly def\n", 13);
586 (*outputFunc)(outputStream, "currentdict end\n", 16);
588 // start the binary section
589 (*outputFunc)(outputStream, "currentfile eexec\n", 18);
593 // get private dictionary
594 eexecWrite("\x83\xca\x73\xd5");
595 eexecWrite("dup /Private 32 dict dup begin\n");
596 eexecWrite("/RD {string currentfile exch readstring pop} executeonly def\n");
597 eexecWrite("/ND {noaccess def} executeonly def\n");
598 eexecWrite("/NP {noaccess put} executeonly def\n");
599 eexecWrite("/MinFeature {16 16} def\n");
600 eexecWrite("/password 5839 def\n");
601 readPrivateDict(&privateDict, dict.privateOffset, dict.privateSize);
602 eexecWrite(privateDict.dictData->getCString());
603 defaultWidthX = privateDict.defaultWidthX;
604 defaultWidthXFP = privateDict.defaultWidthXFP;
605 nominalWidthX = privateDict.nominalWidthX;
606 nominalWidthXFP = privateDict.nominalWidthXFP;
608 // set up subroutines
609 subrIdxPos = privateDict.subrsOffset;
610 i = getIndexLen(gsubrIdxPos);
611 gsubrBias = (i < 1240) ? 107 : (i < 33900) ? 1131 : 32768;
612 i = getIndexLen(subrIdxPos);
613 subrBias = (i < 1240) ? 107 : (i < 33900) ? 1131 : 32768;
616 nCharStrings = getIndexLen(dict.charStrings);
617 sprintf(eBuf, "2 index /CharStrings %d dict dup begin\n", nCharStrings);
619 for (i = 0; i < nCharStrings; ++i) {
620 if ((idxPos = getIndexValPos(dict.charStrings, i, &idxLen)) >= 0) {
621 eexecCvtGlyph(getString(glyphNames[i], buf), idxPos, idxLen);
626 eexecWrite("readonly put\n");
627 eexecWrite("noaccess put\n");
628 eexecWrite("dup /FontName get exch definefont pop\n");
629 eexecWrite("mark currentfile closefile\n");
633 (*outputFunc)(outputStream, "\n", 1);
635 for (i = 0; i < 8; ++i) {
636 (*outputFunc)(outputStream, "0000000000000000000000000000000000000000000000000000000000000000\n", 65);
638 (*outputFunc)(outputStream, "cleartomark\n", 12);
641 delete privateDict.dictData;
642 if (dict.charset > 2) {
647 void Type1CFontFile::convertToCIDType0(char *psName,
648 FontFileOutputFunc outputFuncA,
649 void *outputStreamA) {
651 Type1CPrivateDict *privateDicts;
652 GString *charStrings;
653 int *charStringOffsets;
657 int idxPos, idxLen, pos;
658 char buf[512], buf2[16];
659 int nGlyphs, nCIDs, gdBytes, nFDs;
660 int fdSelectFmt, nRanges, gid0, gid1, fd, offset;
666 outputFunc = outputFuncA;
667 outputStream = outputStreamA;
669 (*outputFunc)(outputStream, "/CIDInit /ProcSet findresource begin\n", 37);
671 // read top dict (first font only)
674 // read the FDArray dictionaries and Private dictionaries
675 if (dict.fdArrayOffset == 0) {
677 privateDicts = (Type1CPrivateDict *)
678 gmalloc(nFDs * sizeof(Type1CPrivateDict));
679 privateDicts[0].dictData = new GString();
680 privateDicts[0].subrsOffset = 0;
681 privateDicts[0].defaultWidthX = 0;
682 privateDicts[0].defaultWidthXFP = gFalse;
683 privateDicts[0].nominalWidthX = 0;
684 privateDicts[0].nominalWidthXFP = gFalse;
686 if ((nFDs = getIndexLen(dict.fdArrayOffset)) < 0) {
689 privateDicts = (Type1CPrivateDict *)
690 gmalloc(nFDs * sizeof(Type1CPrivateDict));
691 for (i = 0; i < nFDs; ++i) {
692 privateDicts[i].dictData = NULL;
694 for (i = 0; i < nFDs; ++i) {
695 privateDicts[i].dictData = NULL;
696 if ((idxPos = getIndexValPos(dict.fdArrayOffset, i, &idxLen)) < 0) {
701 while (pos < idxPos + idxLen) {
702 if (file[pos] <= 27 || file[pos] == 31) {
705 if (pos >= idxPos + idxLen) {
708 key = (key << 8) | file[pos++];
711 readPrivateDict(&privateDicts[i], (int)op[1], (int)op[0]);
715 x = getNum(&pos, &isFP);
722 if (!privateDicts[i].dictData) {
723 privateDicts[i].dictData = new GString();
724 privateDicts[i].subrsOffset = 0;
725 privateDicts[i].defaultWidthX = 0;
726 privateDicts[i].defaultWidthXFP = gFalse;
727 privateDicts[i].nominalWidthX = 0;
728 privateDicts[i].nominalWidthXFP = gFalse;
733 // get the glyph count
734 if ((nGlyphs = getIndexLen(dict.charStrings)) < 0) {
738 // read the FDSelect table
739 fdSelect = (Guchar *)gmalloc(nGlyphs);
740 if (dict.fdSelectOffset == 0) {
741 for (i = 0; i < nGlyphs; ++i) {
745 pos = dict.fdSelectOffset;
746 if (pos < 0 || pos >= len) {
749 fdSelectFmt = file[pos++];
750 if (fdSelectFmt == 0) {
751 if (pos + nGlyphs > len) {
754 memcpy(fdSelect, file + pos, nGlyphs);
755 } else if (fdSelectFmt == 3) {
759 nRanges = getWord(pos, 2);
761 gid0 = getWord(pos, 2);
763 if (pos + nRanges * 3 > len) {
766 for (i = 1; i <= nRanges; ++i) {
768 gid1 = getWord(pos, 2);
770 for (j = gid0; j < gid1; ++j) {
776 error(-1, "Unknown FDSelect table format in CID font");
777 for (i = 0; i < nGlyphs; ++i) {
783 // read the charset, compute the CID-to-GID mapping
784 charset = readCharset(dict.charset, nGlyphs);
786 for (i = 0; i < nGlyphs; ++i) {
787 if (charset[i] >= nCIDs) {
788 nCIDs = charset[i] + 1;
791 cidMap = (int *)gmalloc(nCIDs * sizeof(int));
792 for (i = 0; i < nCIDs; ++i) {
795 for (i = 0; i < nGlyphs; ++i) {
796 cidMap[charset[i]] = i;
799 // set up global subroutines
800 i = getIndexLen(gsubrIdxPos);
801 gsubrBias = (i < 1240) ? 107 : (i < 33900) ? 1131 : 32768;
803 // build the charstrings
804 charStrings = new GString();
805 charStringOffsets = (int *)gmalloc((nCIDs + 1) * sizeof(int));
806 for (i = 0; i < nCIDs; ++i) {
807 charStringOffsets[i] = charStrings->getLength();
808 if (cidMap[i] >= 0) {
809 if ((idxPos = getIndexValPos(dict.charStrings,
810 cidMap[i], &idxLen)) >= 0) {
811 j = fdSelect[cidMap[i]];
812 defaultWidthX = privateDicts[j].defaultWidthX;
813 defaultWidthXFP = privateDicts[j].defaultWidthXFP;
814 nominalWidthX = privateDicts[j].nominalWidthX;
815 nominalWidthXFP = privateDicts[j].nominalWidthXFP;
816 subrIdxPos = privateDicts[j].subrsOffset;
817 k = getIndexLen(subrIdxPos);
818 subrBias = (k < 1240) ? 107 : (k < 33900) ? 1131 : 32768;
819 cvtGlyph(idxPos, idxLen, gTrue);
820 charStrings->append(charBuf);
825 charStringOffsets[nCIDs] = charStrings->getLength();
827 // compute gdBytes = number of bytes needed for charstring offsets
828 // (offset size needs to account for the charstring offset table,
829 // with a worst case of five bytes per entry, plus the charstrings
831 i = (nCIDs + 1) * 5 + charStrings->getLength();
834 } else if (i < 0x10000) {
836 } else if (i < 0x1000000) {
842 // begin the font dictionary
843 (*outputFunc)(outputStream, "20 dict begin\n", 14);
844 (*outputFunc)(outputStream, "/CIDFontName /", 14);
845 (*outputFunc)(outputStream, psName, strlen(psName));
846 (*outputFunc)(outputStream, " def\n", 5);
847 (*outputFunc)(outputStream, "/CIDFontType 0 def\n", 19);
848 (*outputFunc)(outputStream, "/CIDSystemInfo 3 dict dup begin\n", 32);
849 if (dict.registry > 0 && dict.ordering > 0) {
850 getString(dict.registry, buf);
851 (*outputFunc)(outputStream, " /Registry (", 13);
852 (*outputFunc)(outputStream, buf, strlen(buf));
853 (*outputFunc)(outputStream, ") def\n", 6);
854 getString(dict.ordering, buf);
855 (*outputFunc)(outputStream, " /Ordering (", 13);
856 (*outputFunc)(outputStream, buf, strlen(buf));
857 (*outputFunc)(outputStream, ") def\n", 6);
859 (*outputFunc)(outputStream, " /Registry (Adobe) def\n", 24);
860 (*outputFunc)(outputStream, " /Ordering (Identity) def\n", 27);
862 sprintf(buf, " /Supplement %d def\n", dict.supplement);
863 (*outputFunc)(outputStream, buf, strlen(buf));
864 (*outputFunc)(outputStream, "end def\n", 8);
865 sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n",
866 dict.fontMatrix[0], dict.fontMatrix[1], dict.fontMatrix[2],
867 dict.fontMatrix[3], dict.fontMatrix[4], dict.fontMatrix[5]);
868 (*outputFunc)(outputStream, buf, strlen(buf));
869 sprintf(buf, "/FontBBox [%g %g %g %g] def\n",
870 dict.fontBBox[0], dict.fontBBox[1],
871 dict.fontBBox[2], dict.fontBBox[3]);
872 (*outputFunc)(outputStream, buf, strlen(buf));
873 (*outputFunc)(outputStream, "/FontInfo 1 dict dup begin\n", 27);
874 (*outputFunc)(outputStream, " /FSType 8 def\n", 16);
875 (*outputFunc)(outputStream, "end def\n", 8);
877 // CIDFont-specific entries
878 sprintf(buf, "/CIDCount %d def\n", nCIDs);
879 (*outputFunc)(outputStream, buf, strlen(buf));
880 (*outputFunc)(outputStream, "/FDBytes 1 def\n", 15);
881 sprintf(buf, "/GDBytes %d def\n", gdBytes);
882 (*outputFunc)(outputStream, buf, strlen(buf));
883 (*outputFunc)(outputStream, "/CIDMapOffset 0 def\n", 20);
884 if (dict.paintType != 0) {
885 sprintf(buf, "/PaintType %d def\n", dict.paintType);
886 (*outputFunc)(outputStream, buf, strlen(buf));
887 sprintf(buf, "/StrokeWidth %g def\n", dict.strokeWidth);
888 (*outputFunc)(outputStream, buf, strlen(buf));
892 sprintf(buf, "/FDArray %d array\n", nFDs);
893 (*outputFunc)(outputStream, buf, strlen(buf));
894 for (i = 0; i < nFDs; ++i) {
895 sprintf(buf, "dup %d 10 dict begin\n", i);
896 (*outputFunc)(outputStream, buf, strlen(buf));
897 (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
898 (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
899 sprintf(buf, "/PaintType %d def\n", dict.paintType);
900 (*outputFunc)(outputStream, buf, strlen(buf));
901 (*outputFunc)(outputStream, "/Private 32 dict begin\n", 23);
902 (*outputFunc)(outputStream, privateDicts[i].dictData->getCString(),
903 privateDicts[i].dictData->getLength());
904 (*outputFunc)(outputStream, "currentdict end def\n", 20);
905 (*outputFunc)(outputStream, "currentdict end put\n", 20);
907 (*outputFunc)(outputStream, "def\n", 4);
909 // start the binary section
910 offset = (nCIDs + 1) * (1 + gdBytes);
911 sprintf(buf, "(Hex) %d StartData\n",
912 offset + charStrings->getLength());
913 (*outputFunc)(outputStream, buf, strlen(buf));
915 // write the charstring offset (CIDMap) table
916 for (i = 0; i <= nCIDs; i += 6) {
917 for (j = 0; j < 6 && i+j <= nCIDs; ++j) {
918 if (i+j < nCIDs && cidMap[i+j] >= 0) {
919 buf[0] = (char)fdSelect[cidMap[i+j]];
923 n = offset + charStringOffsets[i+j];
924 for (k = gdBytes; k >= 1; --k) {
925 buf[k] = (char)(n & 0xff);
928 for (k = 0; k <= gdBytes; ++k) {
929 sprintf(buf2, "%02x", buf[k] & 0xff);
930 (*outputFunc)(outputStream, buf2, 2);
933 (*outputFunc)(outputStream, "\n", 1);
936 // write the charstring data
937 n = charStrings->getLength();
938 for (i = 0; i < n; i += 32) {
939 for (j = 0; j < 32 && i+j < n; ++j) {
940 sprintf(buf, "%02x", charStrings->getChar(i+j) & 0xff);
941 (*outputFunc)(outputStream, buf, strlen(buf));
944 (*outputFunc)(outputStream, ">", 1);
946 (*outputFunc)(outputStream, "\n", 1);
949 gfree(charStringOffsets);
956 for (i = 0; i < nFDs; ++i) {
957 if (privateDicts[i].dictData) {
958 delete privateDicts[i].dictData;
965 void Type1CFontFile::convertToType0(char *psName,
966 FontFileOutputFunc outputFuncA,
967 void *outputStreamA) {
969 Type1CPrivateDict *privateDicts;
973 int idxPos, idxLen, pos;
976 int nGlyphs, nCIDs, nFDs;
977 int fdSelectFmt, nRanges, gid0, gid1, fd;
983 outputFunc = outputFuncA;
984 outputStream = outputStreamA;
986 // read top dict (first font only)
989 // read the FDArray dictionaries and Private dictionaries
990 if (dict.fdArrayOffset == 0) {
992 privateDicts = (Type1CPrivateDict *)
993 gmalloc(nFDs * sizeof(Type1CPrivateDict));
994 privateDicts[0].dictData = new GString();
995 privateDicts[0].subrsOffset = 0;
996 privateDicts[0].defaultWidthX = 0;
997 privateDicts[0].defaultWidthXFP = gFalse;
998 privateDicts[0].nominalWidthX = 0;
999 privateDicts[0].nominalWidthXFP = gFalse;
1001 if ((nFDs = getIndexLen(dict.fdArrayOffset)) < 0) {
1004 privateDicts = (Type1CPrivateDict *)
1005 gmalloc(nFDs * sizeof(Type1CPrivateDict));
1006 for (i = 0; i < nFDs; ++i) {
1007 privateDicts[i].dictData = NULL;
1009 for (i = 0; i < nFDs; ++i) {
1010 privateDicts[i].dictData = NULL;
1011 if ((idxPos = getIndexValPos(dict.fdArrayOffset, i, &idxLen)) < 0) {
1016 while (pos < idxPos + idxLen) {
1017 if (file[pos] <= 27 || file[pos] == 31) {
1020 if (pos >= idxPos + idxLen) {
1023 key = (key << 8) | file[pos++];
1025 if (key == 0x0012) {
1026 readPrivateDict(&privateDicts[i], (int)op[1], (int)op[0]);
1030 x = getNum(&pos, &isFP);
1037 if (!privateDicts[i].dictData) {
1038 privateDicts[i].dictData = new GString();
1039 privateDicts[i].subrsOffset = 0;
1040 privateDicts[i].defaultWidthX = 0;
1041 privateDicts[i].defaultWidthXFP = gFalse;
1042 privateDicts[i].nominalWidthX = 0;
1043 privateDicts[i].nominalWidthXFP = gFalse;
1048 // get the glyph count
1049 if ((nGlyphs = getIndexLen(dict.charStrings)) < 0) {
1053 // read the FDSelect table
1054 fdSelect = (Guchar *)gmalloc(nGlyphs);
1055 if (dict.fdSelectOffset == 0) {
1056 for (i = 0; i < nGlyphs; ++i) {
1060 pos = dict.fdSelectOffset;
1061 if (pos < 0 || pos >= len) {
1064 fdSelectFmt = file[pos++];
1065 if (fdSelectFmt == 0) {
1066 if (pos + nGlyphs > len) {
1069 memcpy(fdSelect, file + pos, nGlyphs);
1070 } else if (fdSelectFmt == 3) {
1071 if (pos + 4 > len) {
1074 nRanges = getWord(pos, 2);
1076 gid0 = getWord(pos, 2);
1078 if (pos + nRanges * 3 > len) {
1081 for (i = 1; i <= nRanges; ++i) {
1083 gid1 = getWord(pos, 2);
1085 for (j = gid0; j < gid1; ++j) {
1091 error(-1, "Unknown FDSelect table format in CID font");
1092 for (i = 0; i < nGlyphs; ++i) {
1098 // read the charset, compute the CID-to-GID mapping
1099 charset = readCharset(dict.charset, nGlyphs);
1101 for (i = 0; i < nGlyphs; ++i) {
1102 if (charset[i] >= nCIDs) {
1103 nCIDs = charset[i] + 1;
1106 cidMap = (int *)gmalloc(nCIDs * sizeof(int));
1107 for (i = 0; i < nCIDs; ++i) {
1110 for (i = 0; i < nGlyphs; ++i) {
1111 cidMap[charset[i]] = i;
1114 // set up global subroutines
1115 i = getIndexLen(gsubrIdxPos);
1116 gsubrBias = (i < 1240) ? 107 : (i < 33900) ? 1131 : 32768;
1118 // write the descendant Type 1 fonts
1119 for (i = 0; i < nCIDs; i += 256) {
1121 //~ this assumes that all CIDs in this block have the same FD --
1122 //~ to handle multiple FDs correctly, need to somehow divide the
1125 for (j = 0; j < 256 && i+j < nCIDs; ++j) {
1126 if (cidMap[i+j] >= 0) {
1127 fd = fdSelect[cidMap[i+j]];
1132 // font dictionary (unencrypted section)
1133 (*outputFunc)(outputStream, "16 dict begin\n", 14);
1134 (*outputFunc)(outputStream, "/FontName /", 11);
1135 (*outputFunc)(outputStream, psName, strlen(psName));
1136 sprintf(buf, "_%02x def\n", i >> 8);
1137 (*outputFunc)(outputStream, buf, strlen(buf));
1138 (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
1139 sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n",
1140 dict.fontMatrix[0], dict.fontMatrix[1], dict.fontMatrix[2],
1141 dict.fontMatrix[3], dict.fontMatrix[4], dict.fontMatrix[5]);
1142 (*outputFunc)(outputStream, buf, strlen(buf));
1143 sprintf(buf, "/FontBBox [%g %g %g %g] def\n",
1144 dict.fontBBox[0], dict.fontBBox[1],
1145 dict.fontBBox[2], dict.fontBBox[3]);
1146 (*outputFunc)(outputStream, buf, strlen(buf));
1147 sprintf(buf, "/PaintType %d def\n", dict.paintType);
1148 (*outputFunc)(outputStream, buf, strlen(buf));
1149 if (dict.paintType != 0) {
1150 sprintf(buf, "/StrokeWidth %g def\n", dict.strokeWidth);
1151 (*outputFunc)(outputStream, buf, strlen(buf));
1153 (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
1154 for (j = 0; j < 256 && i+j < nCIDs; ++j) {
1155 sprintf(buf, "dup %d /c%02x put\n", j, j);
1156 (*outputFunc)(outputStream, buf, strlen(buf));
1159 sprintf(buf, "%d 1 255 { 1 index exch /.notdef put } for\n", j);
1160 (*outputFunc)(outputStream, buf, strlen(buf));
1162 (*outputFunc)(outputStream, "readonly def\n", 13);
1163 (*outputFunc)(outputStream, "currentdict end\n", 16);
1165 // start the binary section
1166 (*outputFunc)(outputStream, "currentfile eexec\n", 18);
1170 // start the private dictionary
1171 eexecWrite("\x83\xca\x73\xd5");
1172 eexecWrite("dup /Private 32 dict dup begin\n");
1173 eexecWrite("/RD {string currentfile exch readstring pop} executeonly def\n");
1174 eexecWrite("/ND {noaccess def} executeonly def\n");
1175 eexecWrite("/NP {noaccess put} executeonly def\n");
1176 eexecWrite("/MinFeature {16 16} def\n");
1177 eexecWrite("/password 5839 def\n");
1178 eexecWrite(privateDicts[fd].dictData->getCString());
1179 defaultWidthX = privateDicts[fd].defaultWidthX;
1180 defaultWidthXFP = privateDicts[fd].defaultWidthXFP;
1181 nominalWidthX = privateDicts[fd].nominalWidthX;
1182 nominalWidthXFP = privateDicts[fd].nominalWidthXFP;
1184 // set up the subroutines
1185 subrIdxPos = privateDicts[fd].subrsOffset;
1186 j = getIndexLen(subrIdxPos);
1187 subrBias = (j < 1240) ? 107 : (j < 33900) ? 1131 : 32768;
1189 // start the CharStrings
1190 sprintf(eBuf, "2 index /CharStrings 256 dict dup begin\n");
1193 // write the .notdef CharString
1194 if ((idxPos = getIndexValPos(dict.charStrings, 0, &idxLen)) >= 0) {
1195 eexecCvtGlyph(".notdef", idxPos, idxLen);
1198 // write the CharStrings
1199 for (j = 0; j < 256 && i+j < nCIDs; ++j) {
1200 if (cidMap[i+j] >= 0) {
1201 if ((idxPos = getIndexValPos(dict.charStrings,
1202 cidMap[i+j], &idxLen)) >= 0) {
1203 sprintf(buf, "c%02x", j);
1204 eexecCvtGlyph(buf, idxPos, idxLen);
1208 eexecWrite("end\n");
1209 eexecWrite("end\n");
1210 eexecWrite("readonly put\n");
1211 eexecWrite("noaccess put\n");
1212 eexecWrite("dup /FontName get exch definefont pop\n");
1213 eexecWrite("mark currentfile closefile\n");
1217 (*outputFunc)(outputStream, "\n", 1);
1219 for (j = 0; j < 8; ++j) {
1220 (*outputFunc)(outputStream, "0000000000000000000000000000000000000000000000000000000000000000\n", 65);
1222 (*outputFunc)(outputStream, "cleartomark\n", 12);
1225 // write the Type 0 parent font
1226 (*outputFunc)(outputStream, "16 dict begin\n", 14);
1227 (*outputFunc)(outputStream, "/FontName /", 11);
1228 (*outputFunc)(outputStream, psName, strlen(psName));
1229 (*outputFunc)(outputStream, " def\n", 5);
1230 (*outputFunc)(outputStream, "/FontType 0 def\n", 16);
1231 (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
1232 (*outputFunc)(outputStream, "/FMapType 2 def\n", 16);
1233 (*outputFunc)(outputStream, "/Encoding [\n", 12);
1234 for (i = 0; i < nCIDs; i += 256) {
1235 sprintf(buf, "%d\n", i >> 8);
1236 (*outputFunc)(outputStream, buf, strlen(buf));
1238 (*outputFunc)(outputStream, "] def\n", 6);
1239 (*outputFunc)(outputStream, "/FDepVector [\n", 14);
1240 for (i = 0; i < nCIDs; i += 256) {
1241 (*outputFunc)(outputStream, "/", 1);
1242 (*outputFunc)(outputStream, psName, strlen(psName));
1243 sprintf(buf, "_%02x findfont\n", i >> 8);
1244 (*outputFunc)(outputStream, buf, strlen(buf));
1246 (*outputFunc)(outputStream, "] def\n", 6);
1247 (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
1255 for (i = 0; i < nFDs; ++i) {
1256 if (privateDicts[i].dictData) {
1257 delete privateDicts[i].dictData;
1260 gfree(privateDicts);
1264 void Type1CFontFile::readTopDict(Type1CTopDict *dict) {
1265 int idxPos, idxLen, pos;
1273 dict->copyright = 0;
1275 dict->familyName = 0;
1277 dict->isFixedPitch = 0;
1278 dict->italicAngle = 0;
1279 dict->underlinePosition = -100;
1280 dict->underlineThickness = 50;
1281 dict->paintType = 0;
1282 dict->charstringType = 2;
1283 dict->fontMatrix[0] = 0.001;
1284 dict->fontMatrix[1] = 0;
1285 dict->fontMatrix[2] = 0;
1286 dict->fontMatrix[3] = 0.001;
1287 dict->fontMatrix[4] = 0;
1288 dict->fontMatrix[5] = 0;
1290 dict->fontBBox[0] = 0;
1291 dict->fontBBox[1] = 0;
1292 dict->fontBBox[2] = 0;
1293 dict->fontBBox[3] = 0;
1294 dict->strokeWidth = 0;
1297 dict->charStrings = 0;
1298 dict->privateSize = 0;
1299 dict->privateOffset = 0;
1302 dict->supplement = 0;
1303 dict->fdArrayOffset = 0;
1304 dict->fdSelectOffset = 0;
1305 if ((idxPos = getIndexValPos(topDictIdxPos, 0, &idxLen)) < 0) {
1310 while (pos < idxPos + idxLen) {
1311 if (file[pos] <= 27 || file[pos] == 31) {
1314 if (pos >= idxPos + idxLen) {
1317 key = (key << 8) | file[pos++];
1320 case 0x0000: dict->version = (int)op[0]; break;
1321 case 0x0001: dict->notice = (int)op[0]; break;
1322 case 0x0c00: dict->copyright = (int)op[0]; break;
1323 case 0x0002: dict->fullName = (int)op[0]; break;
1324 case 0x0003: dict->familyName = (int)op[0]; break;
1325 case 0x0004: dict->weight = (int)op[0]; break;
1326 case 0x0c01: dict->isFixedPitch = (int)op[0]; break;
1327 case 0x0c02: dict->italicAngle = op[0]; break;
1328 case 0x0c03: dict->underlinePosition = op[0]; break;
1329 case 0x0c04: dict->underlineThickness = op[0]; break;
1330 case 0x0c05: dict->paintType = (int)op[0]; break;
1331 case 0x0c06: dict->charstringType = (int)op[0]; break;
1332 case 0x0c07: dict->fontMatrix[0] = op[0];
1333 dict->fontMatrix[1] = op[1];
1334 dict->fontMatrix[2] = op[2];
1335 dict->fontMatrix[3] = op[3];
1336 dict->fontMatrix[4] = op[4];
1337 dict->fontMatrix[5] = op[5]; break;
1338 case 0x000d: dict->uniqueID = (int)op[0]; break;
1339 case 0x0005: dict->fontBBox[0] = op[0];
1340 dict->fontBBox[1] = op[1];
1341 dict->fontBBox[2] = op[2];
1342 dict->fontBBox[3] = op[3]; break;
1343 case 0x0c08: dict->strokeWidth = op[0]; break;
1344 case 0x000f: dict->charset = (int)op[0]; break;
1345 case 0x0010: dict->encoding = (int)op[0]; break;
1346 case 0x0011: dict->charStrings = (int)op[0]; break;
1347 case 0x0012: dict->privateSize = (int)op[0];
1348 dict->privateOffset = (int)op[1]; break;
1349 case 0x0c1e: dict->registry = (int)op[0];
1350 dict->ordering = (int)op[1];
1351 dict->supplement = (int)op[2]; break;
1352 case 0x0c24: dict->fdArrayOffset = (int)op[0]; break;
1353 case 0x0c25: dict->fdSelectOffset = (int)op[0]; break;
1357 x = getNum(&pos, &isFP);
1366 void Type1CFontFile::readPrivateDict(Type1CPrivateDict *privateDict,
1367 int offset, int size) {
1375 privateDict->dictData = new GString();
1376 privateDict->subrsOffset = 0;
1377 privateDict->defaultWidthX = 0;
1378 privateDict->defaultWidthXFP = gFalse;
1379 privateDict->nominalWidthX = 0;
1380 privateDict->nominalWidthXFP = gFalse;
1381 if (offset < 0 || offset + size > len) {
1386 while (pos < offset + size) {
1387 if (file[pos] <= 27 || file[pos] == 31) {
1390 if (pos >= offset + size) {
1393 key = (key << 8) | file[pos++];
1397 getDeltaInt(eBuf, "BlueValues", op, i);
1398 privateDict->dictData->append(eBuf);
1401 getDeltaInt(eBuf, "OtherBlues", op, i);
1402 privateDict->dictData->append(eBuf);
1405 getDeltaInt(eBuf, "FamilyBlues", op, i);
1406 privateDict->dictData->append(eBuf);
1409 getDeltaInt(eBuf, "FamilyOtherBlues", op, i);
1410 privateDict->dictData->append(eBuf);
1413 sprintf(eBuf, "/BlueScale %g def\n", op[0]);
1414 privateDict->dictData->append(eBuf);
1417 sprintf(eBuf, "/BlueShift %d def\n", (int)op[0]);
1418 privateDict->dictData->append(eBuf);
1421 sprintf(eBuf, "/BlueFuzz %d def\n", (int)op[0]);
1422 privateDict->dictData->append(eBuf);
1425 sprintf(eBuf, "/StdHW [%g] def\n", op[0]);
1426 privateDict->dictData->append(eBuf);
1429 sprintf(eBuf, "/StdVW [%g] def\n", op[0]);
1430 privateDict->dictData->append(eBuf);
1433 getDeltaReal(eBuf, "StemSnapH", op, i);
1434 privateDict->dictData->append(eBuf);
1437 getDeltaReal(eBuf, "StemSnapV", op, i);
1438 privateDict->dictData->append(eBuf);
1441 sprintf(eBuf, "/ForceBold %s def\n", op[0] ? "true" : "false");
1442 privateDict->dictData->append(eBuf);
1445 sprintf(eBuf, "/ForceBoldThreshold %g def\n", op[0]);
1446 privateDict->dictData->append(eBuf);
1449 sprintf(eBuf, "/LanguageGroup %d def\n", (int)op[0]);
1450 privateDict->dictData->append(eBuf);
1453 sprintf(eBuf, "/ExpansionFactor %g def\n", op[0]);
1454 privateDict->dictData->append(eBuf);
1457 error(-1, "Got Type 1C InitialRandomSeed");
1460 privateDict->subrsOffset = offset + (int)op[0];
1463 privateDict->defaultWidthX = op[0];
1464 privateDict->defaultWidthXFP = fp[0];
1467 privateDict->nominalWidthX = op[0];
1468 privateDict->nominalWidthXFP = fp[0];
1471 error(-1, "Unknown Type 1C private dict entry %04x", key);
1476 x = getNum(&pos, &isFP);
1485 Gushort *Type1CFontFile::readCharset(int charset, int nGlyphs) {
1486 Gushort *glyphNames;
1488 int charsetFormat, c;
1492 glyphNames = type1CISOAdobeCharset;
1493 } else if (charset == 1) {
1494 glyphNames = type1CExpertCharset;
1495 } else if (charset == 2) {
1496 glyphNames = type1CExpertSubsetCharset;
1498 glyphNames = (Gushort *)gmalloc(nGlyphs * sizeof(Gushort));
1499 for (i = 0; i < nGlyphs; ++i) {
1503 if (pos < 0 || pos >= len) {
1506 charsetFormat = file[pos++];
1507 if (charsetFormat == 0) {
1508 if (pos + (nGlyphs - 1) * 2 >= len) {
1511 for (i = 1; i < nGlyphs; ++i) {
1512 glyphNames[i] = getWord(pos, 2);
1515 } else if (charsetFormat == 1) {
1517 while (i < nGlyphs) {
1518 if (pos + 3 > len) {
1521 c = getWord(pos, 2);
1523 nLeft = file[pos++];
1524 for (j = 0; j <= nLeft && i < nGlyphs; ++j) {
1525 glyphNames[i++] = c++;
1528 } else if (charsetFormat == 2) {
1530 while (i < nGlyphs) {
1531 if (pos + 4 > len) {
1534 c = getWord(pos, 2);
1536 nLeft = getWord(pos, 2);
1538 for (j = 0; j <= nLeft && i < nGlyphs; ++j) {
1539 glyphNames[i++] = c++;
1548 void Type1CFontFile::eexecWrite(char *s) {
1552 for (p = (Guchar *)s; *p; ++p) {
1554 r1 = (x + r1) * 52845 + 22719;
1555 (*outputFunc)(outputStream, &hexChars[x >> 4], 1);
1556 (*outputFunc)(outputStream, &hexChars[x & 0x0f], 1);
1559 (*outputFunc)(outputStream, "\n", 1);
1565 void Type1CFontFile::eexecCvtGlyph(char *glyphName, int pos, int n) {
1568 cvtGlyph(pos, n, gTrue);
1569 sprintf(eBuf, "/%s %d RD ", glyphName, charBuf->getLength());
1571 eexecWriteCharstring((Guchar *)charBuf->getCString(), charBuf->getLength());
1572 eexecWrite(" ND\n");
1576 void Type1CFontFile::cvtGlyph(int pos, int n, GBool top) {
1578 int subrPos, subrLen;
1585 if (pos < 0 || pos + n > len) {
1590 charBuf = new GString();
1591 charBuf->append((char)73);
1592 charBuf->append((char)58);
1593 charBuf->append((char)147);
1594 charBuf->append((char)134);
1601 while (i < pos + n) {
1602 if (file[i] == 12) {
1603 if (i + 2 > pos + n) {
1606 switch (file[i+1]) {
1607 case 0: // dotsection (should be Type 1 only?)
1612 error(-1, "Wrong number of args (%d) to Type 2 hflex", nOps);
1614 eexecDumpNum(op[0], fp[0]);
1615 eexecDumpNum(0, gFalse);
1616 eexecDumpNum(op[1], fp[1]);
1617 eexecDumpNum(op[2], fp[2]);
1618 eexecDumpNum(op[3], fp[3]);
1619 eexecDumpNum(0, gFalse);
1621 eexecDumpNum(op[4], fp[4]);
1622 eexecDumpNum(0, gFalse);
1623 eexecDumpNum(op[5], fp[5]);
1624 eexecDumpNum(-op[2], fp[2]);
1625 eexecDumpNum(op[6], fp[6]);
1626 eexecDumpNum(0, gFalse);
1631 error(-1, "Wrong number of args (%d) to Type 2 flex", nOps);
1633 eexecDumpNum(op[0], fp[0]);
1634 eexecDumpNum(op[1], fp[1]);
1635 eexecDumpNum(op[2], fp[2]);
1636 eexecDumpNum(op[3], fp[3]);
1637 eexecDumpNum(op[4], fp[4]);
1638 eexecDumpNum(op[5], fp[5]);
1640 eexecDumpNum(op[6], fp[6]);
1641 eexecDumpNum(op[7], fp[7]);
1642 eexecDumpNum(op[8], fp[8]);
1643 eexecDumpNum(op[9], fp[9]);
1644 eexecDumpNum(op[10], fp[10]);
1645 eexecDumpNum(op[11], fp[11]);
1650 error(-1, "Wrong number of args (%d) to Type 2 hflex1", nOps);
1652 eexecDumpNum(op[0], fp[0]);
1653 eexecDumpNum(op[1], fp[1]);
1654 eexecDumpNum(op[2], fp[2]);
1655 eexecDumpNum(op[3], fp[3]);
1656 eexecDumpNum(op[4], fp[4]);
1657 eexecDumpNum(0, gFalse);
1659 eexecDumpNum(op[5], fp[5]);
1660 eexecDumpNum(0, gFalse);
1661 eexecDumpNum(op[6], fp[6]);
1662 eexecDumpNum(op[7], fp[7]);
1663 eexecDumpNum(op[8], fp[8]);
1664 eexecDumpNum(-(op[1] + op[3] + op[7]), fp[1] | fp[3] | fp[7]);
1669 error(-1, "Wrong number of args (%d) to Type 2 flex1", nOps);
1671 eexecDumpNum(op[0], fp[0]);
1672 eexecDumpNum(op[1], fp[1]);
1673 eexecDumpNum(op[2], fp[2]);
1674 eexecDumpNum(op[3], fp[3]);
1675 eexecDumpNum(op[4], fp[4]);
1676 eexecDumpNum(op[5], fp[5]);
1678 eexecDumpNum(op[6], fp[6]);
1679 eexecDumpNum(op[7], fp[7]);
1680 eexecDumpNum(op[8], fp[8]);
1681 eexecDumpNum(op[9], fp[9]);
1682 dx = op[0] + op[2] + op[4] + op[6] + op[8];
1683 dy = op[1] + op[3] + op[5] + op[7] + op[9];
1684 if (fabs(dx) > fabs(dy)) {
1685 eexecDumpNum(op[10], fp[10]);
1686 eexecDumpNum(-dy, fp[1] | fp[3] | fp[5] | fp[7] | fp[9]);
1688 eexecDumpNum(-dx, fp[0] | fp[2] | fp[4] | fp[6] | fp[8]);
1689 eexecDumpNum(op[10], fp[10]);
1715 error(-1, "Unimplemented Type 2 charstring op: 12.%d", file[i+1]);
1718 error(-1, "Illegal Type 2 charstring op: 12.%d", file[i+1]);
1723 } else if (file[i] == 19) { // hintmask
1726 cvtGlyphWidth(nOps & 1);
1731 error(-1, "Wrong number of args (%d) to Type 2 hintmask/vstemhm",
1736 i += 1 + ((nHints + 7) >> 3);
1738 } else if (file[i] == 20) { // cntrmask
1741 cvtGlyphWidth(nOps & 1);
1746 error(-1, "Wrong number of args (%d) to Type 2 cntrmask/vstemhm",
1751 i += 1 + ((nHints + 7) >> 3);
1753 } else if (file[i] == 28) {
1757 x = (file[i+1] << 8) + file[i+2];
1766 } else if (file[i] == 10) { // callsubr
1768 k = subrBias + (int)op[nOps - 1];
1770 if ((subrPos = getIndexValPos(subrIdxPos, k, &subrLen)) >= 0) {
1771 cvtGlyph(subrPos, subrLen, gFalse);
1774 error(-1, "Too few args to Type 2 callsubr");
1776 // don't clear the stack
1778 } else if (file[i] == 29) { // callgsubr
1780 k = gsubrBias + (int)op[nOps - 1];
1782 if ((subrPos = getIndexValPos(gsubrIdxPos, k, &subrLen)) >= 0) {
1783 cvtGlyph(subrPos, subrLen, gFalse);
1786 error(-1, "Too few args to Type 2 callgsubr");
1788 // don't clear the stack
1790 } else if (file[i] == 11) { // return
1791 // don't clear the stack
1793 } else if (file[i] <= 31) {
1797 cvtGlyphWidth(nOps == 2);
1801 error(-1, "Wrong number of args (%d) to Type 2 vmoveto", nOps);
1803 eexecDumpNum(op[0], fp[0]);
1807 if (nOps < 2 || nOps % 2 != 0) {
1808 error(-1, "Wrong number of args (%d) to Type 2 rlineto", nOps);
1810 for (k = 0; k < nOps; k += 2) {
1811 eexecDumpNum(op[k], fp[k]);
1812 eexecDumpNum(op[k+1], fp[k+1]);
1818 error(-1, "Wrong number of args (%d) to Type 2 hlineto", nOps);
1820 for (k = 0; k < nOps; ++k) {
1821 eexecDumpNum(op[k], fp[k]);
1822 eexecDumpOp1((k & 1) ? 7 : 6);
1827 error(-1, "Wrong number of args (%d) to Type 2 vlineto", nOps);
1829 for (k = 0; k < nOps; ++k) {
1830 eexecDumpNum(op[k], fp[k]);
1831 eexecDumpOp1((k & 1) ? 6 : 7);
1834 case 8: // rrcurveto
1835 if (nOps < 6 || nOps % 6 != 0) {
1836 error(-1, "Wrong number of args (%d) to Type 2 rrcurveto", nOps);
1838 for (k = 0; k < nOps; k += 6) {
1839 eexecDumpNum(op[k], fp[k]);
1840 eexecDumpNum(op[k+1], fp[k+1]);
1841 eexecDumpNum(op[k+2], fp[k+2]);
1842 eexecDumpNum(op[k+3], fp[k+3]);
1843 eexecDumpNum(op[k+4], fp[k+4]);
1844 eexecDumpNum(op[k+5], fp[k+5]);
1848 case 14: // endchar / seac
1850 cvtGlyphWidth(nOps == 1 || nOps == 5);
1855 eexecDumpNum(op[0], fp[0]);
1856 eexecDumpNum(op[1], fp[1]);
1857 eexecDumpNum(op[2], fp[2]);
1858 eexecDumpNum(op[3], fp[3]);
1860 } else if (nOps == 0) {
1863 error(-1, "Wrong number of args (%d) to Type 2 endchar", nOps);
1868 cvtGlyphWidth(nOps == 3);
1872 error(-1, "Wrong number of args (%d) to Type 2 rmoveto", nOps);
1874 eexecDumpNum(op[0], fp[0]);
1875 eexecDumpNum(op[1], fp[1]);
1880 cvtGlyphWidth(nOps == 2);
1884 error(-1, "Wrong number of args (%d) to Type 2 hmoveto", nOps);
1886 eexecDumpNum(op[0], fp[0]);
1889 case 24: // rcurveline
1890 if (nOps < 8 || (nOps - 2) % 6 != 0) {
1891 error(-1, "Wrong number of args (%d) to Type 2 rcurveline", nOps);
1893 for (k = 0; k < nOps - 2; k += 6) {
1894 eexecDumpNum(op[k], fp[k]);
1895 eexecDumpNum(op[k+1], fp[k+1]);
1896 eexecDumpNum(op[k+2], fp[k+2]);
1897 eexecDumpNum(op[k+3], fp[k+3]);
1898 eexecDumpNum(op[k+4], fp[k+4]);
1899 eexecDumpNum(op[k+5], fp[k+5]);
1902 eexecDumpNum(op[k], fp[k]);
1903 eexecDumpNum(op[k+1], fp[k]);
1906 case 25: // rlinecurve
1907 if (nOps < 8 || (nOps - 6) % 2 != 0) {
1908 error(-1, "Wrong number of args (%d) to Type 2 rlinecurve", nOps);
1910 for (k = 0; k < nOps - 6; k += 2) {
1911 eexecDumpNum(op[k], fp[k]);
1912 eexecDumpNum(op[k+1], fp[k]);
1915 eexecDumpNum(op[k], fp[k]);
1916 eexecDumpNum(op[k+1], fp[k+1]);
1917 eexecDumpNum(op[k+2], fp[k+2]);
1918 eexecDumpNum(op[k+3], fp[k+3]);
1919 eexecDumpNum(op[k+4], fp[k+4]);
1920 eexecDumpNum(op[k+5], fp[k+5]);
1923 case 26: // vvcurveto
1924 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
1925 error(-1, "Wrong number of args (%d) to Type 2 vvcurveto", nOps);
1927 if (nOps % 2 == 1) {
1928 eexecDumpNum(op[0], fp[0]);
1929 eexecDumpNum(op[1], fp[1]);
1930 eexecDumpNum(op[2], fp[2]);
1931 eexecDumpNum(op[3], fp[3]);
1932 eexecDumpNum(0, gFalse);
1933 eexecDumpNum(op[4], fp[4]);
1939 for (; k < nOps; k += 4) {
1940 eexecDumpNum(0, gFalse);
1941 eexecDumpNum(op[k], fp[k]);
1942 eexecDumpNum(op[k+1], fp[k+1]);
1943 eexecDumpNum(op[k+2], fp[k+2]);
1944 eexecDumpNum(0, gFalse);
1945 eexecDumpNum(op[k+3], fp[k+3]);
1949 case 27: // hhcurveto
1950 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
1951 error(-1, "Wrong number of args (%d) to Type 2 hhcurveto", nOps);
1953 if (nOps % 2 == 1) {
1954 eexecDumpNum(op[1], fp[1]);
1955 eexecDumpNum(op[0], fp[0]);
1956 eexecDumpNum(op[2], fp[2]);
1957 eexecDumpNum(op[3], fp[3]);
1958 eexecDumpNum(op[4], fp[4]);
1959 eexecDumpNum(0, gFalse);
1965 for (; k < nOps; k += 4) {
1966 eexecDumpNum(op[k], fp[k]);
1967 eexecDumpNum(0, gFalse);
1968 eexecDumpNum(op[k+1], fp[k+1]);
1969 eexecDumpNum(op[k+2], fp[k+2]);
1970 eexecDumpNum(op[k+3], fp[k+3]);
1971 eexecDumpNum(0, gFalse);
1975 case 30: // vhcurveto
1976 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
1977 error(-1, "Wrong number of args (%d) to Type 2 vhcurveto", nOps);
1979 for (k = 0; k < nOps && k != nOps-5; k += 4) {
1981 eexecDumpNum(op[k], fp[k]);
1982 eexecDumpNum(op[k+1], fp[k+1]);
1983 eexecDumpNum(op[k+2], fp[k+2]);
1984 eexecDumpNum(op[k+3], fp[k+3]);
1987 eexecDumpNum(op[k], fp[k]);
1988 eexecDumpNum(op[k+1], fp[k+1]);
1989 eexecDumpNum(op[k+2], fp[k+2]);
1990 eexecDumpNum(op[k+3], fp[k+3]);
1996 eexecDumpNum(0, gFalse);
1997 eexecDumpNum(op[k], fp[k]);
1998 eexecDumpNum(op[k+1], fp[k+1]);
1999 eexecDumpNum(op[k+2], fp[k+2]);
2000 eexecDumpNum(op[k+3], fp[k+3]);
2001 eexecDumpNum(op[k+4], fp[k+4]);
2003 eexecDumpNum(op[k], fp[k]);
2004 eexecDumpNum(0, gFalse);
2005 eexecDumpNum(op[k+1], fp[k+1]);
2006 eexecDumpNum(op[k+2], fp[k+2]);
2007 eexecDumpNum(op[k+4], fp[k+4]);
2008 eexecDumpNum(op[k+3], fp[k+3]);
2013 case 31: // hvcurveto
2014 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
2015 error(-1, "Wrong number of args (%d) to Type 2 hvcurveto", nOps);
2017 for (k = 0; k < nOps && k != nOps-5; k += 4) {
2019 eexecDumpNum(op[k], fp[k]);
2020 eexecDumpNum(op[k+1], fp[k+1]);
2021 eexecDumpNum(op[k+2], fp[k+2]);
2022 eexecDumpNum(op[k+3], fp[k+3]);
2025 eexecDumpNum(op[k], fp[k]);
2026 eexecDumpNum(op[k+1], fp[k+1]);
2027 eexecDumpNum(op[k+2], fp[k+2]);
2028 eexecDumpNum(op[k+3], fp[k+3]);
2034 eexecDumpNum(op[k], fp[k]);
2035 eexecDumpNum(0, gFalse);
2036 eexecDumpNum(op[k+1], fp[k+1]);
2037 eexecDumpNum(op[k+2], fp[k+2]);
2038 eexecDumpNum(op[k+4], fp[k+4]);
2039 eexecDumpNum(op[k+3], fp[k+3]);
2041 eexecDumpNum(0, gFalse);
2042 eexecDumpNum(op[k], fp[k]);
2043 eexecDumpNum(op[k+1], fp[k+1]);
2044 eexecDumpNum(op[k+2], fp[k+2]);
2045 eexecDumpNum(op[k+3], fp[k+3]);
2046 eexecDumpNum(op[k+4], fp[k+4]);
2053 cvtGlyphWidth(nOps & 1);
2057 error(-1, "Wrong number of args (%d) to Type 2 hstem", nOps);
2061 for (k = 0; k < nOps; k += 2) {
2063 d += op[k] + op[k+1];
2064 dFP |= fp[k] | fp[k+1];
2065 eexecDumpNum(d, dFP);
2066 eexecDumpNum(-op[k+1], fp[k+1]);
2070 eexecDumpNum(d, dFP);
2071 eexecDumpNum(op[k+1], fp[k+1]);
2081 cvtGlyphWidth(nOps & 1);
2085 error(-1, "Wrong number of args (%d) to Type 2 vstem", nOps);
2089 for (k = 0; k < nOps; k += 2) {
2091 d += op[k] + op[k+1];
2092 dFP |= fp[k] | fp[k+1];
2093 eexecDumpNum(d, dFP);
2094 eexecDumpNum(-op[k+1], fp[k+1]);
2098 eexecDumpNum(d, dFP);
2099 eexecDumpNum(op[k+1], fp[k+1]);
2107 case 15: // (obsolete)
2108 // this op is ignored, but we need the glyph width
2110 cvtGlyphWidth(nOps > 0);
2117 cvtGlyphWidth(nOps & 1);
2121 error(-1, "Wrong number of args (%d) to Type 2 hstemhm", nOps);
2128 cvtGlyphWidth(nOps & 1);
2132 error(-1, "Wrong number of args (%d) to Type 2 vstemhm", nOps);
2137 error(-1, "Unimplemented Type 2 charstring op: %d", file[i]);
2140 error(-1, "Illegal Type 2 charstring op: %d", file[i]);
2145 } else if (file[i] <= 246) {
2148 op[nOps++] = (int)file[i] - 139;
2151 } else if (file[i] <= 250) {
2157 op[nOps++] = (((int)file[i] - 247) << 8) + (int)file[i+1] + 108;
2160 } else if (file[i] <= 254) {
2166 op[nOps++] = -(((int)file[i] - 251) << 8) - (int)file[i+1] - 108;
2173 x = (file[i+1] << 24) | (file[i+2] << 16) | (file[i+3] << 8) | file[i+4];
2174 if (x & 0x80000000) {
2179 op[nOps++] = (double)x / 65536.0;
2185 // charstring encryption
2188 for (i = 0; i < charBuf->getLength(); ++i) {
2189 byte = charBuf->getChar(i) ^ (r2 >> 8);
2190 charBuf->setChar(i, byte);
2191 r2 = (byte + r2) * 52845 + 22719;
2196 void Type1CFontFile::cvtGlyphWidth(GBool useOp) {
2202 w = nominalWidthX + op[0];
2203 wFP = nominalWidthXFP | fp[0];
2204 for (i = 1; i < nOps; ++i) {
2211 wFP = defaultWidthXFP;
2213 eexecDumpNum(0, gFalse);
2214 eexecDumpNum(w, wFP);
2218 void Type1CFontFile::eexecDumpNum(double x, GBool fpA) {
2224 if (x >= -32768 && x < 32768) {
2225 y = (int)(x * 256.0);
2227 buf[1] = (Guchar)(y >> 24);
2228 buf[2] = (Guchar)(y >> 16);
2229 buf[3] = (Guchar)(y >> 8);
2240 error(-1, "Type 2 fixed point constant out of range");
2244 if (y >= -107 && y <= 107) {
2245 buf[0] = (Guchar)(y + 139);
2247 } else if (y > 107 && y <= 1131) {
2249 buf[0] = (Guchar)((y >> 8) + 247);
2250 buf[1] = (Guchar)(y & 0xff);
2252 } else if (y < -107 && y >= -1131) {
2254 buf[0] = (Guchar)((y >> 8) + 251);
2255 buf[1] = (Guchar)(y & 0xff);
2259 buf[1] = (Guchar)(y >> 24);
2260 buf[2] = (Guchar)(y >> 16);
2261 buf[3] = (Guchar)(y >> 8);
2266 charBuf->append((char *)buf, n);
2269 void Type1CFontFile::eexecDumpOp1(int opA) {
2270 charBuf->append((char)opA);
2273 void Type1CFontFile::eexecDumpOp2(int opA) {
2274 charBuf->append((char)12);
2275 charBuf->append((char)opA);
2278 void Type1CFontFile::eexecWriteCharstring(Guchar *s, int n) {
2283 for (i = 0; i < n; ++i) {
2284 x = s[i] ^ (r1 >> 8);
2285 r1 = (x + r1) * 52845 + 22719;
2286 (*outputFunc)(outputStream, &hexChars[x >> 4], 1);
2287 (*outputFunc)(outputStream, &hexChars[x & 0x0f], 1);
2290 (*outputFunc)(outputStream, "\n", 1);
2296 void Type1CFontFile::getDeltaInt(char *buf, char *key, double *opA,
2300 sprintf(buf, "/%s [", key);
2303 for (i = 0; i < n; ++i) {
2305 sprintf(buf, "%s%d", i > 0 ? " " : "", x);
2308 sprintf(buf, "] def\n");
2311 void Type1CFontFile::getDeltaReal(char *buf, char *key, double *opA,
2316 sprintf(buf, "/%s [", key);
2319 for (i = 0; i < n; ++i) {
2321 sprintf(buf, "%s%g", i > 0 ? " " : "", x);
2324 sprintf(buf, "] def\n");
2327 int Type1CFontFile::getIndexLen(int indexPos) {
2328 if (indexPos + 2 > len) {
2331 return (int)getWord(indexPos, 2);
2334 int Type1CFontFile::getIndexValPos(int indexPos, int i, int *valLen) {
2335 int n, offSize, idxStartPos;
2338 if (indexPos < 0 || indexPos + 3 > len) {
2341 n = (int)getWord(indexPos, 2);
2345 offSize = file[indexPos + 2];
2346 if (offSize < 1 || offSize > 4) {
2349 idxStartPos = indexPos + 3 + (n + 1) * offSize - 1;
2350 if (idxStartPos >= len) {
2353 pos0 = idxStartPos + getWord(indexPos + 3 + i * offSize, offSize);
2354 pos1 = idxStartPos + getWord(indexPos + 3 + (i + 1) * offSize, offSize);
2355 if (pos0 < 0 || pos0 >= len || pos1 < pos0 || pos1 > len) {
2358 *valLen = pos1 - pos0;
2362 int Type1CFontFile::getIndexEnd(int indexPos) {
2363 int n, offSize, idxStartPos;
2365 if (indexPos < 0 || indexPos + 3 > len) {
2368 n = (int)getWord(indexPos, 2);
2369 offSize = file[indexPos + 2];
2370 idxStartPos = indexPos + 3 + (n + 1) * offSize - 1;
2371 if (idxStartPos >= len) {
2374 return idxStartPos + getWord(indexPos + 3 + n * offSize, offSize);
2377 Guint Type1CFontFile::getWord(int pos, int size) {
2381 if (pos < 0 || pos + size > len) {
2385 for (i = 0; i < size; ++i) {
2386 x = (x << 8) + file[pos + i];
2391 double Type1CFontFile::getNum(int *pos, GBool *isFP) {
2392 static char nybChars[16] = "0123456789.ee -";
2393 int b0, b, nyb0, nyb1;
2406 } else if (b0 == 28) {
2407 if (*pos + 3 <= len) {
2408 x = (file[*pos + 1] << 8) + file[*pos + 2];
2411 } else if (b0 == 29) {
2412 if (*pos + 5 <= len) {
2413 x = (file[*pos + 1] << 24) + (file[*pos + 2] << 16) +
2414 (file[*pos + 3] << 8) + file[*pos + 4];
2417 } else if (b0 == 30) {
2430 buf[i++] = nybChars[nyb0];
2443 buf[i++] = nybChars[nyb1];
2453 char *theLocale = setlocale(LC_NUMERIC, "C");
2455 setlocale(LC_NUMERIC, theLocale);
2458 } else if (b0 == 31) {
2460 } else if (b0 < 247) {
2463 } else if (b0 < 251) {
2464 if (*pos + 2 <= len) {
2465 x = ((b0 - 247) << 8) + file[*pos + 1] + 108;
2469 if (*pos + 2 <= len) {
2470 x = -((b0 - 251) << 8) - file[*pos + 1] - 108;
2477 char *Type1CFontFile::getString(int sid, char *buf) {
2481 strcpy(buf, type1CStdStrings[sid]);
2484 idxPos = getIndexValPos(stringIdxPos, sid, &n);
2485 if (idxPos < 0 || n < 0 || n > 255 || idxPos + n > len) {
2488 strncpy(buf, (char *)&file[idxPos], n);
2495 //------------------------------------------------------------------------
2497 //------------------------------------------------------------------------
2503 // character code = number used as an element of a text string
2505 // character name = glyph name = name for a particular glyph within a
2508 // glyph index = position (within some internal table in the font)
2509 // where the instructions to draw a particular glyph are
2515 // Type 1 fonts contain:
2517 // Encoding: array of glyph names, maps char codes to glyph names
2519 // Encoding[charCode] = charName
2521 // CharStrings: dictionary of instructions, keyed by character names,
2522 // maps character name to glyph data
2524 // CharStrings[charName] = glyphData
2529 // TrueType fonts contain:
2531 // 'cmap' table: mapping from character code to glyph index; there may
2532 // be multiple cmaps in a TrueType font
2534 // cmap[charCode] = glyphIdx
2536 // 'post' table: mapping from glyph index to glyph name
2538 // post[glyphIdx] = glyphName
2543 // Type 42 fonts contain:
2545 // Encoding: array of glyph names, maps char codes to glyph names
2547 // Encoding[charCode] = charName
2549 // CharStrings: dictionary of glyph indexes, keyed by character names,
2550 // maps character name to glyph index
2552 // CharStrings[charName] = glyphIdx
2555 struct TTFontTableHdr {
2563 char *tag; // 4-byte tag
2564 GBool required; // required by the TrueType spec?
2575 // TrueType tables to be embedded in Type 42 fonts.
2576 // NB: the table names must be in alphabetical order here.
2577 #define nT42Tables 11
2578 static T42Table t42Tables[nT42Tables] = {
2591 #define t42HeadTable 3
2592 #define t42LocaTable 6
2593 #define t42GlyfTable 2
2595 // Glyph names in some arbitrary standard that Apple uses for their
2597 static char *macGlyphNames[258] = {
2858 struct TrueTypeLoca {
2864 TrueTypeFontFile::TrueTypeFontFile(char *fileA, int lenA) {
2865 int pos, pos2, i, idx, n, length;
2866 Guint size, startPos, endPos;
2875 // read table directory
2876 nTables = getUShort(4);
2877 tableHdrs = (TTFontTableHdr *)gmalloc(nTables * sizeof(TTFontTableHdr));
2879 for (i = 0; i < nTables; ++i) {
2880 tableHdrs[i].tag[0] = getByte(pos+0);
2881 tableHdrs[i].tag[1] = getByte(pos+1);
2882 tableHdrs[i].tag[2] = getByte(pos+2);
2883 tableHdrs[i].tag[3] = getByte(pos+3);
2884 tableHdrs[i].checksum = getULong(pos+4);
2885 tableHdrs[i].offset = getULong(pos+8);
2886 tableHdrs[i].length = getULong(pos+12);
2887 if (tableHdrs[i].offset + tableHdrs[i].length < tableHdrs[i].offset ||
2888 tableHdrs[i].offset + tableHdrs[i].length > (Guint)len) {
2889 tableHdrs[i].offset = (Guint)-1;
2894 // check for tables that are required by both the TrueType spec
2895 // and the Type 42 spec
2896 if (seekTable("head") < 0 ||
2897 seekTable("hhea") < 0 ||
2898 seekTable("loca") < 0 ||
2899 seekTable("maxp") < 0 ||
2900 seekTable("glyf") < 0 ||
2901 seekTable("hmtx") < 0) {
2902 error(-1, "TrueType font file is missing a required table");
2906 // some embedded TrueType fonts have an incorrect (too small) cmap
2908 idx = seekTableIdx("cmap");
2910 pos = tableHdrs[idx].offset;
2911 n = getUShort(pos + 2);
2912 size = (Guint)(4 + 8 * n);
2913 for (i = 0; i < n; ++i) {
2914 startPos = getULong(pos + 4 + 8*i + 4);
2915 length = getUShort(pos + startPos + 2);
2916 endPos = startPos + length;
2917 if (endPos > size) {
2921 if ((mungedCmapSize = size > tableHdrs[idx].length)) {
2922 #if 0 // don't bother printing this error message - it's too common
2923 error(-1, "Bad cmap table size in TrueType font");
2925 tableHdrs[idx].length = size;
2928 mungedCmapSize = gFalse;
2931 // read the 'head' table
2932 pos = seekTable("head");
2933 bbox[0] = getShort(pos + 36);
2934 bbox[1] = getShort(pos + 38);
2935 bbox[2] = getShort(pos + 40);
2936 bbox[3] = getShort(pos + 42);
2937 locaFmt = getShort(pos + 50);
2939 // read the 'maxp' table
2940 pos = seekTable("maxp");
2941 nGlyphs = getUShort(pos + 4);
2943 // read the 'cmap' table
2944 if ((pos = seekTable("cmap")) >= 0) {
2946 if ((nCmaps = getUShort(pos2)) > 0) {
2948 cmaps = (TTFontCmap *)gmalloc(nCmaps * sizeof(TTFontCmap));
2949 for (i = 0; i < nCmaps; ++i) {
2950 cmaps[i].platform = getUShort(pos2);
2951 cmaps[i].encoding = getUShort(pos2 + 2);
2952 cmaps[i].offset = pos + getULong(pos2 + 4);
2954 cmaps[i].fmt = getUShort(cmaps[i].offset);
2955 cmaps[i].len = getUShort(cmaps[i].offset + 2);
2961 TrueTypeFontFile::~TrueTypeFontFile() {
2965 for (i = 0; i < 256; ++i) {
2976 char *TrueTypeFontFile::getName() {
2980 char **TrueTypeFontFile::getEncoding() {
2984 encoding = (char **)gmalloc(256 * sizeof(char *));
2985 for (i = 0; i < 256; ++i) {
2992 int TrueTypeFontFile::getNumCmaps() {
2996 int TrueTypeFontFile::getCmapPlatform(int i) {
2997 return cmaps[i].platform;
3000 int TrueTypeFontFile::getCmapEncoding(int i) {
3001 return cmaps[i].encoding;
3004 int TrueTypeFontFile::findCmap(int platform, int enc) {
3007 for (i = 0; i < nCmaps; ++i) {
3008 if (cmaps[i].platform == platform && cmaps[i].encoding == enc) {
3015 Gushort TrueTypeFontFile::mapCodeToGID(int i, int c) {
3016 if (i < 0 || i >= nCmaps) {
3019 return (Gushort)getCmapEntry(cmaps[i].fmt, cmaps[i].offset, c);
3022 GHash *TrueTypeFontFile::getNameToGID() {
3026 int stringIdx, stringPos, pos, i, j, n;
3028 if ((pos = seekTable("post")) < 0) {
3032 fmt = getULong(pos);
3036 if (fmt == 0x00010000) {
3037 nameToGID = new GHash(gTrue);
3038 for (i = 0; i < 258; ++i) {
3039 nameToGID->add(new GString(macGlyphNames[i]), (void *)i);
3043 } else if (fmt == 0x00020000) {
3044 nameToGID = new GHash(gTrue);
3045 n = getUShort(pos + 32);
3050 stringPos = pos + 34 + 2*nGlyphs;
3051 for (i = 0; i < nGlyphs; ++i) {
3052 j = getUShort(pos + 34 + 2*i);
3054 nameToGID->remove(macGlyphNames[j]);
3055 nameToGID->add(new GString(macGlyphNames[j]), (void *)i);
3058 if (j != stringIdx) {
3059 for (stringIdx = 0, stringPos = pos + 34 + 2*nGlyphs;
3061 ++stringIdx, stringPos += 1 + getByte(stringPos)) ;
3063 n = getByte(stringPos);
3064 if (stringPos >= 0 && stringPos + 1 + n <= len) {
3065 s = new GString(file + stringPos + 1, n);
3066 nameToGID->remove(s);
3067 nameToGID->add(s, (void *)i);
3075 } else if (fmt == 0x000280000) {
3076 nameToGID = new GHash(gTrue);
3077 for (i = 0; i < nGlyphs; ++i) {
3078 j = getByte(pos + 32 + i);
3080 nameToGID->remove(macGlyphNames[j]);
3081 nameToGID->add(new GString(macGlyphNames[j]), (void *)i);
3089 void TrueTypeFontFile::convertToType42(char *name, char **encodingA,
3090 GBool pdfFontHasEncoding,
3092 FontFileOutputFunc outputFunc,
3093 void *outputStream) {
3097 sprintf(buf, "%%!PS-TrueTypeFont-%g\n", getFixed(0));
3098 (*outputFunc)(outputStream, buf, strlen(buf));
3100 // begin the font dictionary
3101 (*outputFunc)(outputStream, "10 dict begin\n", 14);
3102 (*outputFunc)(outputStream, "/FontName /", 11);
3103 (*outputFunc)(outputStream, name, strlen(name));
3104 (*outputFunc)(outputStream, " def\n", 5);
3105 (*outputFunc)(outputStream, "/FontType 42 def\n", 17);
3106 (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
3107 sprintf(buf, "/FontBBox [%d %d %d %d] def\n",
3108 bbox[0], bbox[1], bbox[2], bbox[3]);
3109 (*outputFunc)(outputStream, buf, strlen(buf));
3110 (*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
3112 // write the guts of the dictionary
3113 cvtEncoding(encodingA, pdfFontHasEncoding, outputFunc, outputStream);
3114 cvtCharStrings(encodingA, pdfFontHasEncoding, codeToGID,
3115 outputFunc, outputStream);
3116 cvtSfnts(outputFunc, outputStream, NULL);
3118 // end the dictionary and define the font
3119 (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
3122 void TrueTypeFontFile::convertToCIDType2(char *name, Gushort *cidMap,
3124 FontFileOutputFunc outputFunc,
3125 void *outputStream) {
3131 sprintf(buf, "%%!PS-TrueTypeFont-%g\n", getFixed(0));
3132 (*outputFunc)(outputStream, buf, strlen(buf));
3134 // begin the font dictionary
3135 (*outputFunc)(outputStream, "20 dict begin\n", 14);
3136 (*outputFunc)(outputStream, "/CIDFontName /", 14);
3137 (*outputFunc)(outputStream, name, strlen(name));
3138 (*outputFunc)(outputStream, " def\n", 5);
3139 (*outputFunc)(outputStream, "/CIDFontType 2 def\n", 19);
3140 (*outputFunc)(outputStream, "/FontType 42 def\n", 17);
3141 (*outputFunc)(outputStream, "/CIDSystemInfo 3 dict dup begin\n", 32);
3142 (*outputFunc)(outputStream, " /Registry (Adobe) def\n", 24);
3143 (*outputFunc)(outputStream, " /Ordering (Identity) def\n", 27);
3144 (*outputFunc)(outputStream, " /Supplement 0 def\n", 20);
3145 (*outputFunc)(outputStream, " end def\n", 10);
3146 (*outputFunc)(outputStream, "/GDBytes 2 def\n", 15);
3148 sprintf(buf, "/CIDCount %d def\n", nCIDs);
3149 (*outputFunc)(outputStream, buf, strlen(buf));
3150 if (nCIDs > 32767) {
3151 (*outputFunc)(outputStream, "/CIDMap [", 9);
3152 for (i = 0; i < nCIDs; i += 32768 - 16) {
3153 (*outputFunc)(outputStream, "<\n", 2);
3154 for (j = 0; j < 32768 - 16 && i+j < nCIDs; j += 16) {
3155 (*outputFunc)(outputStream, " ", 2);
3156 for (k = 0; k < 16 && i+j+k < nCIDs; ++k) {
3157 cid = cidMap[i+j+k];
3158 sprintf(buf, "%02x%02x", (cid >> 8) & 0xff, cid & 0xff);
3159 (*outputFunc)(outputStream, buf, strlen(buf));
3161 (*outputFunc)(outputStream, "\n", 1);
3163 (*outputFunc)(outputStream, " >", 3);
3165 (*outputFunc)(outputStream, "\n", 1);
3166 (*outputFunc)(outputStream, "] def\n", 6);
3168 (*outputFunc)(outputStream, "/CIDMap <\n", 10);
3169 for (i = 0; i < nCIDs; i += 16) {
3170 (*outputFunc)(outputStream, " ", 2);
3171 for (j = 0; j < 16 && i+j < nCIDs; ++j) {
3173 sprintf(buf, "%02x%02x", (cid >> 8) & 0xff, cid & 0xff);
3174 (*outputFunc)(outputStream, buf, strlen(buf));
3176 (*outputFunc)(outputStream, "\n", 1);
3178 (*outputFunc)(outputStream, "> def\n", 6);
3181 // direct mapping - just fill the string(s) with s[i]=i
3182 sprintf(buf, "/CIDCount %d def\n", nGlyphs);
3183 (*outputFunc)(outputStream, buf, strlen(buf));
3184 if (nGlyphs > 32767) {
3185 (*outputFunc)(outputStream, "/CIDMap [\n", 10);
3186 for (i = 0; i < nGlyphs; i += 32767) {
3187 j = nGlyphs - i < 32767 ? nGlyphs - i : 32767;
3188 sprintf(buf, " %d string 0 1 %d {\n", 2 * j, j - 1);
3189 (*outputFunc)(outputStream, buf, strlen(buf));
3190 sprintf(buf, " 2 copy dup 2 mul exch %d add -8 bitshift put\n", i);
3191 (*outputFunc)(outputStream, buf, strlen(buf));
3192 sprintf(buf, " 1 index exch dup 2 mul 1 add exch %d add"
3193 " 255 and put\n", i);
3194 (*outputFunc)(outputStream, buf, strlen(buf));
3195 (*outputFunc)(outputStream, " } for\n", 8);
3197 (*outputFunc)(outputStream, "] def\n", 6);
3199 sprintf(buf, "/CIDMap %d string\n", 2 * nGlyphs);
3200 (*outputFunc)(outputStream, buf, strlen(buf));
3201 sprintf(buf, " 0 1 %d {\n", nGlyphs - 1);
3202 (*outputFunc)(outputStream, buf, strlen(buf));
3203 (*outputFunc)(outputStream,
3204 " 2 copy dup 2 mul exch -8 bitshift put\n", 42);
3205 (*outputFunc)(outputStream,
3206 " 1 index exch dup 2 mul 1 add exch 255 and put\n", 50);
3207 (*outputFunc)(outputStream, " } for\n", 8);
3208 (*outputFunc)(outputStream, "def\n", 4);
3211 (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
3212 sprintf(buf, "/FontBBox [%d %d %d %d] def\n",
3213 bbox[0], bbox[1], bbox[2], bbox[3]);
3214 (*outputFunc)(outputStream, buf, strlen(buf));
3215 (*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
3216 (*outputFunc)(outputStream, "/Encoding [] readonly def\n", 26);
3217 (*outputFunc)(outputStream, "/CharStrings 1 dict dup begin\n", 30);
3218 (*outputFunc)(outputStream, " /.notdef 0 def\n", 17);
3219 (*outputFunc)(outputStream, " end readonly def\n", 19);
3221 // write the guts of the dictionary
3222 cvtSfnts(outputFunc, outputStream, NULL);
3224 // end the dictionary and define the font
3225 (*outputFunc)(outputStream,
3226 "CIDFontName currentdict end /CIDFont defineresource pop\n",
3230 void TrueTypeFontFile::convertToType0(char *name, Gushort *cidMap,
3232 FontFileOutputFunc outputFunc,
3233 void *outputStream) {
3238 // write the Type 42 sfnts array
3239 sfntsName = (new GString(name))->append("_sfnts");
3240 cvtSfnts(outputFunc, outputStream, sfntsName);
3243 // write the descendant Type 42 fonts
3244 n = cidMap ? nCIDs : nGlyphs;
3245 for (i = 0; i < n; i += 256) {
3246 (*outputFunc)(outputStream, "10 dict begin\n", 14);
3247 (*outputFunc)(outputStream, "/FontName /", 11);
3248 (*outputFunc)(outputStream, name, strlen(name));
3249 sprintf(buf, "_%02x def\n", i >> 8);
3250 (*outputFunc)(outputStream, buf, strlen(buf));
3251 (*outputFunc)(outputStream, "/FontType 42 def\n", 17);
3252 (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
3253 sprintf(buf, "/FontBBox [%d %d %d %d] def\n",
3254 bbox[0], bbox[1], bbox[2], bbox[3]);
3255 (*outputFunc)(outputStream, buf, strlen(buf));
3256 (*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
3257 (*outputFunc)(outputStream, "/sfnts ", 7);
3258 (*outputFunc)(outputStream, name, strlen(name));
3259 (*outputFunc)(outputStream, "_sfnts def\n", 11);
3260 (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
3261 for (j = 0; j < 256 && i+j < n; ++j) {
3262 sprintf(buf, "dup %d /c%02x put\n", j, j);
3263 (*outputFunc)(outputStream, buf, strlen(buf));
3265 (*outputFunc)(outputStream, "readonly def\n", 13);
3266 (*outputFunc)(outputStream, "/CharStrings 257 dict dup begin\n", 32);
3267 (*outputFunc)(outputStream, "/.notdef 0 def\n", 15);
3268 for (j = 0; j < 256 && i+j < n; ++j) {
3269 sprintf(buf, "/c%02x %d def\n", j, cidMap ? cidMap[i+j] : i+j);
3270 (*outputFunc)(outputStream, buf, strlen(buf));
3272 (*outputFunc)(outputStream, "end readonly def\n", 17);
3273 (*outputFunc)(outputStream,
3274 "FontName currentdict end definefont pop\n", 40);
3277 // write the Type 0 parent font
3278 (*outputFunc)(outputStream, "16 dict begin\n", 14);
3279 (*outputFunc)(outputStream, "/FontName /", 11);
3280 (*outputFunc)(outputStream, name, strlen(name));
3281 (*outputFunc)(outputStream, " def\n", 5);
3282 (*outputFunc)(outputStream, "/FontType 0 def\n", 16);
3283 (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
3284 (*outputFunc)(outputStream, "/FMapType 2 def\n", 16);
3285 (*outputFunc)(outputStream, "/Encoding [\n", 12);
3286 for (i = 0; i < n; i += 256) {
3287 sprintf(buf, "%d\n", i >> 8);
3288 (*outputFunc)(outputStream, buf, strlen(buf));
3290 (*outputFunc)(outputStream, "] def\n", 6);
3291 (*outputFunc)(outputStream, "/FDepVector [\n", 14);
3292 for (i = 0; i < n; i += 256) {
3293 (*outputFunc)(outputStream, "/", 1);
3294 (*outputFunc)(outputStream, name, strlen(name));
3295 sprintf(buf, "_%02x findfont\n", i >> 8);
3296 (*outputFunc)(outputStream, buf, strlen(buf));
3298 (*outputFunc)(outputStream, "] def\n", 6);
3299 (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
3302 int TrueTypeFontFile::getByte(int pos) {
3303 if (pos < 0 || pos >= len) {
3306 return file[pos] & 0xff;
3309 int TrueTypeFontFile::getChar(int pos) {
3312 if (pos < 0 || pos >= len) {
3315 x = file[pos] & 0xff;
3321 int TrueTypeFontFile::getUShort(int pos) {
3324 if (pos < 0 || pos+1 >= len) {
3327 x = file[pos] & 0xff;
3328 x = (x << 8) + (file[pos+1] & 0xff);
3332 int TrueTypeFontFile::getShort(int pos) {
3335 if (pos < 0 || pos+1 >= len) {
3338 x = file[pos] & 0xff;
3339 x = (x << 8) + (file[pos+1] & 0xff);
3345 Guint TrueTypeFontFile::getULong(int pos) {
3348 if (pos < 0 || pos+3 >= len) {
3351 x = file[pos] & 0xff;
3352 x = (x << 8) + (file[pos+1] & 0xff);
3353 x = (x << 8) + (file[pos+2] & 0xff);
3354 x = (x << 8) + (file[pos+3] & 0xff);
3358 double TrueTypeFontFile::getFixed(int pos) {
3362 y = getUShort(pos+2);
3363 return (double)x + (double)y / 65536;
3366 int TrueTypeFontFile::seekTable(char *tag) {
3369 for (i = 0; i < nTables; ++i) {
3370 if (!strncmp(tableHdrs[i].tag, tag, 4)) {
3371 return (int)tableHdrs[i].offset;
3377 int TrueTypeFontFile::seekTableIdx(char *tag) {
3380 for (i = 0; i < nTables; ++i) {
3381 if (!strncmp(tableHdrs[i].tag, tag, 4)) {
3382 if (tableHdrs[i].offset == (Guint)-1) {
3391 void TrueTypeFontFile::cvtEncoding(char **encodingA, GBool pdfFontHasEncoding,
3392 FontFileOutputFunc outputFunc,
3393 void *outputStream) {
3398 (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
3399 if (pdfFontHasEncoding) {
3400 for (i = 0; i < 256; ++i) {
3401 if (!(name = encodingA[i])) {
3404 sprintf(buf, "dup %d /", i);
3405 (*outputFunc)(outputStream, buf, strlen(buf));
3406 (*outputFunc)(outputStream, name, strlen(name));
3407 (*outputFunc)(outputStream, " put\n", 5);
3410 for (i = 0; i < 256; ++i) {
3411 sprintf(buf, "dup %d /c%02x put\n", i, i);
3412 (*outputFunc)(outputStream, buf, strlen(buf));
3415 (*outputFunc)(outputStream, "readonly def\n", 13);
3418 void TrueTypeFontFile::cvtCharStrings(char **encodingA,
3419 GBool pdfFontHasEncoding,
3421 FontFileOutputFunc outputFunc,
3422 void *outputStream) {
3424 char buf[64], buf2[16];
3427 // always define '.notdef'
3428 (*outputFunc)(outputStream, "/CharStrings 256 dict dup begin\n", 32);
3429 (*outputFunc)(outputStream, "/.notdef 0 def\n", 15);
3431 // if there's no 'cmap' table, punt
3436 // map char name to glyph index:
3437 // 1. use encoding to map name to char code
3438 // 2. use codeToGID to map char code to glyph index
3439 // N.B. We do this in reverse order because font subsets can have
3440 // weird encodings that use the same character name twice, and
3441 // the first definition is probably the one we want.
3442 k = 0; // make gcc happy
3443 for (i = 255; i >= 0; --i) {
3444 if (pdfFontHasEncoding) {
3445 name = encodingA[i];
3447 sprintf(buf2, "c%02x", i);
3450 if (name && strcmp(name, ".notdef")) {
3452 // note: Distiller (maybe Adobe's PS interpreter in general)
3453 // doesn't like TrueType fonts that have CharStrings entries
3454 // which point to nonexistent glyphs, hence the (k < nGlyphs)
3456 if (k > 0 && k < nGlyphs) {
3457 (*outputFunc)(outputStream, "/", 1);
3458 (*outputFunc)(outputStream, name, strlen(name));
3459 sprintf(buf, " %d def\n", k);
3460 (*outputFunc)(outputStream, buf, strlen(buf));
3466 (*outputFunc)(outputStream, "end readonly def\n", 17);
3469 int TrueTypeFontFile::getCmapEntry(int cmapFmt, int pos, int code) {
3470 int cmapLen, cmapFirst;
3471 int segCnt, segEnd, segStart, segDelta, segOffset;
3475 case 0: // byte encoding table (Apple standard)
3476 cmapLen = getUShort(pos + 2);
3477 if (code >= cmapLen) {
3480 return getByte(pos + 6 + code);
3482 case 4: // segment mapping to delta values (Microsoft standard)
3483 segCnt = getUShort(pos + 6) / 2;
3486 segEnd = getUShort(pos + 14 + 2*b);
3487 if (code > segEnd) {
3488 // malformed font -- the TrueType spec requires the last segEnd
3492 // invariant: seg[a].end < code <= seg[b].end
3495 segEnd = getUShort(pos + 14 + 2*m);
3496 if (segEnd < code) {
3502 segStart = getUShort(pos + 16 + 2*segCnt + 2*b);
3503 segDelta = getUShort(pos + 16 + 4*segCnt + 2*b);
3504 segOffset = getUShort(pos + 16 + 6*segCnt + 2*b);
3505 if (code < segStart) {
3508 if (segOffset == 0) {
3509 i = (code + segDelta) & 0xffff;
3511 i = getUShort(pos + 16 + 6*segCnt + 2*b +
3512 segOffset + 2 * (code - segStart));
3514 i = (i + segDelta) & 0xffff;
3519 case 6: // trimmed table mapping
3520 cmapFirst = getUShort(pos + 6);
3521 cmapLen = getUShort(pos + 8);
3522 if (code < cmapFirst || code >= cmapFirst + cmapLen) {
3525 return getUShort(pos + 10 + 2*(code - cmapFirst));
3528 // shouldn't happen - this is checked earlier
3534 static int cmpTrueTypeLocaIdx(const void *p1, const void *p2) {
3535 return ((TrueTypeLoca *)p1)->idx - ((TrueTypeLoca *)p2)->idx;
3538 static int cmpTrueTypeLocaPos(const void *p1, const void *p2) {
3539 if (((TrueTypeLoca *)p1)->pos == ((TrueTypeLoca *)p2)->pos) {
3540 return ((TrueTypeLoca *)p1)->idx - ((TrueTypeLoca *)p2)->idx;
3542 return ((TrueTypeLoca *)p1)->pos - ((TrueTypeLoca *)p2)->pos;
3546 void TrueTypeFontFile::cvtSfnts(FontFileOutputFunc outputFunc,
3547 void *outputStream, GString *name) {
3548 TTFontTableHdr newTableHdrs[nT42Tables];
3549 char tableDir[12 + nT42Tables*16];
3551 TrueTypeLoca *origLocaTable;
3555 int pos, glyfPos, length, glyphLength, pad;
3558 // construct the 'head' table, zero out the font checksum
3559 memcpy(headTable, file + seekTable("head"), 54);
3560 headTable[8] = headTable[9] = headTable[10] = headTable[11] = (char)0;
3562 // read the original 'loca' table and sort it into proper order --
3563 // some (non-compliant) fonts have out-of-order loca tables; in
3564 // order to correctly handle the case where (compliant) fonts have
3565 // empty entries in the middle of the table, cmpTrueTypeLocaPos uses
3566 // pos as its primary sort key, and idx as its secondary key
3567 // (ensuring that adjacent entries with the same pos value remain in
3569 origLocaTable = (TrueTypeLoca *)gmalloc((nGlyphs + 1) *
3570 sizeof(TrueTypeLoca));
3571 pos = seekTable("loca");
3572 for (i = 0; i <= nGlyphs; ++i) {
3573 origLocaTable[i].idx = i;
3575 origLocaTable[i].pos = getULong(pos + 4*i);
3577 origLocaTable[i].pos = 2 * getUShort(pos + 2*i);
3580 qsort(origLocaTable, nGlyphs + 1, sizeof(TrueTypeLoca), &cmpTrueTypeLocaPos);
3581 for (i = 0; i < nGlyphs; ++i) {
3582 origLocaTable[i].length = origLocaTable[i+1].pos - origLocaTable[i].pos;
3584 origLocaTable[nGlyphs].length = 0;
3585 qsort(origLocaTable, nGlyphs + 1, sizeof(TrueTypeLoca), &cmpTrueTypeLocaIdx);
3587 // construct the new 'loca' table, padding each glyph out to a
3588 // multiple of 4 bytes
3589 locaTable = (char *)gmalloc((nGlyphs + 1) * (locaFmt ? 4 : 2));
3591 for (i = 0; i <= nGlyphs; ++i) {
3593 locaTable[4*i ] = (char)(pos >> 24);
3594 locaTable[4*i+1] = (char)(pos >> 16);
3595 locaTable[4*i+2] = (char)(pos >> 8);
3596 locaTable[4*i+3] = (char) pos;
3598 locaTable[2*i ] = (char)(pos >> 9);
3599 locaTable[2*i+1] = (char)(pos >> 1);
3601 length = origLocaTable[i].length;
3603 length += 4 - (length & 3);
3608 // count the number of tables
3610 for (i = 0; i < nT42Tables; ++i) {
3611 if (t42Tables[i].required ||
3612 seekTable(t42Tables[i].tag) >= 0) {
3617 // construct the new table headers, including table checksums
3618 // (pad each table out to a multiple of 4 bytes)
3619 pos = 12 + nNewTables*16;
3621 for (i = 0; i < nT42Tables; ++i) {
3623 checksum = 0; // make gcc happy
3624 if (i == t42HeadTable) {
3626 checksum = computeTableChecksum(headTable, 54);
3627 } else if (i == t42LocaTable) {
3628 length = (nGlyphs + 1) * (locaFmt ? 4 : 2);
3629 checksum = computeTableChecksum(locaTable, length);
3630 } else if (i == t42GlyfTable) {
3633 glyfPos = seekTable("glyf");
3634 for (j = 0; j < nGlyphs; ++j) {
3635 glyphLength = origLocaTable[j].length;
3636 pad = (glyphLength & 3) ? 4 - (glyphLength & 3) : 0;
3637 length += glyphLength + pad;
3638 if (glyphLength >= 0 &&
3639 glyfPos + origLocaTable[j].pos + glyphLength <= len) {
3641 computeTableChecksum(file + glyfPos + origLocaTable[j].pos,
3646 if ((j = seekTableIdx(t42Tables[i].tag)) >= 0) {
3647 length = tableHdrs[j].length;
3648 checksum = computeTableChecksum(file + tableHdrs[j].offset, length);
3649 } else if (t42Tables[i].required) {
3650 error(-1, "Embedded TrueType font is missing a required table ('%s')",
3657 strncpy(newTableHdrs[k].tag, t42Tables[i].tag, 4);
3658 newTableHdrs[k].checksum = checksum;
3659 newTableHdrs[k].offset = pos;
3660 newTableHdrs[k].length = length;
3661 pad = (length & 3) ? 4 - (length & 3) : 0;
3662 pos += length + pad;
3667 // construct the table directory
3668 tableDir[0] = 0x00; // sfnt version
3672 tableDir[4] = 0; // numTables
3673 tableDir[5] = nNewTables;
3674 tableDir[6] = 0; // searchRange
3675 tableDir[7] = (char)128;
3676 tableDir[8] = 0; // entrySelector
3678 tableDir[10] = 0; // rangeShift
3679 tableDir[11] = (char)(16 * nNewTables - 128);
3681 for (i = 0; i < nNewTables; ++i) {
3682 tableDir[pos ] = newTableHdrs[i].tag[0];
3683 tableDir[pos+ 1] = newTableHdrs[i].tag[1];
3684 tableDir[pos+ 2] = newTableHdrs[i].tag[2];
3685 tableDir[pos+ 3] = newTableHdrs[i].tag[3];
3686 tableDir[pos+ 4] = (char)(newTableHdrs[i].checksum >> 24);
3687 tableDir[pos+ 5] = (char)(newTableHdrs[i].checksum >> 16);
3688 tableDir[pos+ 6] = (char)(newTableHdrs[i].checksum >> 8);
3689 tableDir[pos+ 7] = (char) newTableHdrs[i].checksum;
3690 tableDir[pos+ 8] = (char)(newTableHdrs[i].offset >> 24);
3691 tableDir[pos+ 9] = (char)(newTableHdrs[i].offset >> 16);
3692 tableDir[pos+10] = (char)(newTableHdrs[i].offset >> 8);
3693 tableDir[pos+11] = (char) newTableHdrs[i].offset;
3694 tableDir[pos+12] = (char)(newTableHdrs[i].length >> 24);
3695 tableDir[pos+13] = (char)(newTableHdrs[i].length >> 16);
3696 tableDir[pos+14] = (char)(newTableHdrs[i].length >> 8);
3697 tableDir[pos+15] = (char) newTableHdrs[i].length;
3701 // compute the font checksum and store it in the head table
3702 checksum = computeTableChecksum(tableDir, 12 + nNewTables*16);
3703 for (i = 0; i < nNewTables; ++i) {
3704 checksum += newTableHdrs[i].checksum;
3706 checksum = 0xb1b0afba - checksum; // because the TrueType spec says so
3707 headTable[ 8] = (char)(checksum >> 24);
3708 headTable[ 9] = (char)(checksum >> 16);
3709 headTable[10] = (char)(checksum >> 8);
3710 headTable[11] = (char) checksum;
3712 // start the sfnts array
3714 (*outputFunc)(outputStream, "/", 1);
3715 (*outputFunc)(outputStream, name->getCString(), name->getLength());
3716 (*outputFunc)(outputStream, " [\n", 3);
3718 (*outputFunc)(outputStream, "/sfnts [\n", 9);
3721 // write the table directory
3722 dumpString(tableDir, 12 + nNewTables*16, outputFunc, outputStream);
3725 for (i = 0; i < nNewTables; ++i) {
3726 if (i == t42HeadTable) {
3727 dumpString(headTable, 54, outputFunc, outputStream);
3728 } else if (i == t42LocaTable) {
3729 length = (nGlyphs + 1) * (locaFmt ? 4 : 2);
3730 dumpString(locaTable, length, outputFunc, outputStream);
3731 } else if (i == t42GlyfTable) {
3732 glyfPos = seekTable("glyf");
3733 for (j = 0; j < nGlyphs; ++j) {
3734 length = origLocaTable[j].length;
3736 glyfPos + origLocaTable[j].pos + length <= len) {
3737 dumpString(file + glyfPos + origLocaTable[j].pos, length,
3738 outputFunc, outputStream);
3742 // length == 0 means the table is missing and the error was
3743 // already reported during the construction of the table
3745 if ((length = newTableHdrs[i].length) > 0) {
3746 j = seekTable(t42Tables[i].tag);
3748 dumpString(file + seekTable(t42Tables[i].tag), length,
3749 outputFunc, outputStream);
3755 // end the sfnts array
3756 (*outputFunc)(outputStream, "] def\n", 6);
3758 gfree(origLocaTable);
3762 void TrueTypeFontFile::dumpString(char *s, int length,
3763 FontFileOutputFunc outputFunc,
3764 void *outputStream) {
3768 (*outputFunc)(outputStream, "<", 1);
3769 for (i = 0; i < length; i += 32) {
3770 for (j = 0; j < 32 && i+j < length; ++j) {
3771 sprintf(buf, "%02X", s[i+j] & 0xff);
3772 (*outputFunc)(outputStream, buf, strlen(buf));
3774 if (i % (65536 - 32) == 65536 - 64) {
3775 (*outputFunc)(outputStream, ">\n<", 3);
3776 } else if (i+32 < length) {
3777 (*outputFunc)(outputStream, "\n", 1);
3781 pad = 4 - (length & 3);
3782 for (i = 0; i < pad; ++i) {
3783 (*outputFunc)(outputStream, "00", 2);
3786 // add an extra zero byte because the Adobe Type 42 spec says so
3787 (*outputFunc)(outputStream, "00>\n", 4);
3790 Guint TrueTypeFontFile::computeTableChecksum(char *data, int length) {
3791 Guint checksum, word;
3795 for (i = 0; i+3 < length; i += 4) {
3796 word = ((data[i ] & 0xff) << 24) +
3797 ((data[i+1] & 0xff) << 16) +
3798 ((data[i+2] & 0xff) << 8) +
3805 switch (length & 3) {
3807 word |= (data[i+2] & 0xff) << 8;
3809 word |= (data[i+1] & 0xff) << 16;
3811 word |= (data[i ] & 0xff) << 24;
3819 void TrueTypeFontFile::writeTTF(FILE *out) {
3820 static char cmapTab[20] = {
3821 0, 0, // table version number
3822 0, 1, // number of encoding tables
3823 0, 1, // platform ID
3824 0, 0, // encoding ID
3825 0, 0, 0, 12, // offset of subtable
3826 0, 0, // subtable format
3827 0, 1, // subtable length
3828 0, 1, // subtable version
3829 0, // map char 0 -> glyph 0
3830 0 // pad to multiple of four bytes
3832 static char nameTab[8] = {
3834 0, 0, // number of name records
3835 0, 6, // offset to start of string storage
3836 0, 0 // pad to multiple of four bytes
3838 static char postTab[32] = {
3839 0, 1, 0, 0, // format
3840 0, 0, 0, 0, // italic angle
3841 0, 0, // underline position
3842 0, 0, // underline thickness
3843 0, 0, 0, 0, // fixed pitch
3844 0, 0, 0, 0, // min Type 42 memory
3845 0, 0, 0, 0, // max Type 42 memory
3846 0, 0, 0, 0, // min Type 1 memory
3847 0, 0, 0, 0 // max Type 1 memory
3849 GBool haveCmap, haveName, havePost;
3850 GBool dirCmap, dirName, dirPost;
3852 int nNewTables, nZeroLengthTables, nAllTables;
3853 TTFontTableHdr *newTableHdrs;
3855 TrueTypeLoca *origLocaTable;
3857 int length, glyfLength;
3858 Guint t, pos, pos2, pos3;
3861 // check for missing/broken tables
3862 haveCmap = seekTable("cmap") >= 0;
3863 haveName = seekTable("name") >= 0;
3864 havePost = seekTable("post") >= 0;
3865 unsortedLoca = gFalse;
3866 pos = seekTable("loca");
3868 for (i = 0; i <= nGlyphs; ++i) {
3870 pos3 = getULong(pos + 4*i);
3872 pos3 = 2 * getUShort(pos + 2*i);
3875 unsortedLoca = gTrue;
3880 nNewTables = (haveCmap ? 0 : 1) + (haveName ? 0 : 1) + (havePost ? 0 : 1);
3881 nZeroLengthTables = 0;
3882 for (i = 0; i < nTables; ++i) {
3883 if (tableHdrs[i].length == 0) {
3884 ++nZeroLengthTables;
3887 if (!nNewTables && !nZeroLengthTables && !mungedCmapSize && !unsortedLoca) {
3888 // nothing is broken - write the TTF file as is
3889 fwrite(file, 1, len, out);
3893 // if the glyph data isn't sorted (as listed in the 'loca' table),
3894 // construct a new 'loca' table
3896 origLocaTable = (TrueTypeLoca *)gmalloc((nGlyphs + 1) *
3897 sizeof(TrueTypeLoca));
3898 pos = seekTable("loca");
3899 for (i = 0; i <= nGlyphs; ++i) {
3900 origLocaTable[i].idx = i;
3902 origLocaTable[i].pos = getULong(pos + 4*i);
3904 origLocaTable[i].pos = 2 * getUShort(pos + 2*i);
3907 qsort(origLocaTable, nGlyphs + 1, sizeof(TrueTypeLoca),
3908 &cmpTrueTypeLocaPos);
3909 for (i = 0; i < nGlyphs; ++i) {
3910 origLocaTable[i].length = origLocaTable[i+1].pos - origLocaTable[i].pos;
3912 origLocaTable[nGlyphs].length = 0;
3913 qsort(origLocaTable, nGlyphs + 1, sizeof(TrueTypeLoca),
3914 &cmpTrueTypeLocaIdx);
3915 locaTable = (char *)gmalloc((nGlyphs + 1) * (locaFmt ? 4 : 2));
3917 for (i = 0; i <= nGlyphs; ++i) {
3919 locaTable[4*i ] = (char)(pos >> 24);
3920 locaTable[4*i+1] = (char)(pos >> 16);
3921 locaTable[4*i+2] = (char)(pos >> 8);
3922 locaTable[4*i+3] = (char) pos;
3924 locaTable[2*i ] = (char)(pos >> 9);
3925 locaTable[2*i+1] = (char)(pos >> 1);
3927 length = origLocaTable[i].length;
3929 length += 4 - (length & 3);
3935 origLocaTable = NULL; // make gcc happy
3936 locaTable = NULL; // make gcc happy
3937 glyfLength = 0; // make gcc happy
3940 // construct the new table directory
3941 nAllTables = nTables - nZeroLengthTables + nNewTables;
3942 newTableHdrs = (TTFontTableHdr *)gmalloc(nAllTables *
3943 sizeof(TTFontTableHdr));
3947 pos = 12 + nAllTables * 16;
3949 for (i = 0; i < nTables; ++i) {
3950 if (!dirCmap && strncmp(tableHdrs[i].tag, "cmap", 4) > 0) {
3951 memcpy(newTableHdrs[j].tag, "cmap", 4);
3952 newTableHdrs[j].checksum = 0; //~ should compute the checksum
3953 newTableHdrs[j].offset = pos;
3954 pos += newTableHdrs[j].length = sizeof(cmapTab);
3956 pos += 4 - (pos & 3);
3961 if (!dirName && strncmp(tableHdrs[i].tag, "name", 4) > 0) {
3962 memcpy(newTableHdrs[j].tag, "name", 4);
3963 newTableHdrs[j].checksum = 0; //~ should compute the checksum
3964 newTableHdrs[j].offset = pos;
3965 pos += newTableHdrs[j].length = sizeof(nameTab);
3967 pos += 4 - (pos & 3);
3972 if (!dirPost && strncmp(tableHdrs[i].tag, "post", 4) > 0) {
3973 memcpy(newTableHdrs[j].tag, "post", 4);
3974 newTableHdrs[j].checksum = 0; //~ should compute the checksum
3975 newTableHdrs[j].offset = pos;
3976 pos += newTableHdrs[j].length = sizeof(postTab);
3978 pos += 4 - (pos & 3);
3983 // throw away zero-length tables - they confuse FreeType
3984 if (tableHdrs[i].length > 0) {
3985 memcpy(newTableHdrs[j].tag, tableHdrs[i].tag, 4);
3986 newTableHdrs[j].checksum = tableHdrs[i].checksum;
3987 newTableHdrs[j].offset = pos;
3988 if (unsortedLoca && !strncmp(tableHdrs[i].tag, "loca", 4)) {
3989 newTableHdrs[j].length = (nGlyphs + 1) * (locaFmt ? 4 : 2);
3990 } else if (unsortedLoca && !strncmp(tableHdrs[i].tag, "glyf", 4)) {
3991 newTableHdrs[j].length = glyfLength;
3993 newTableHdrs[j].length = tableHdrs[i].length;
3995 pos += newTableHdrs[j].length;
3997 pos += 4 - (pos & 3);
4003 memcpy(newTableHdrs[j].tag, "cmap", 4);
4004 newTableHdrs[j].checksum = 0; //~ should compute the checksum
4005 newTableHdrs[j].offset = pos;
4006 pos += newTableHdrs[j].length = sizeof(cmapTab);
4008 pos += 4 - (pos & 3);
4013 memcpy(newTableHdrs[j].tag, "name", 4);
4014 newTableHdrs[j].checksum = 0; //~ should compute the checksum
4015 newTableHdrs[j].offset = pos;
4016 pos += newTableHdrs[j].length = sizeof(nameTab);
4018 pos += 4 - (pos & 3);
4023 memcpy(newTableHdrs[j].tag, "post", 4);
4024 newTableHdrs[j].checksum = 0; //~ should compute the checksum
4025 newTableHdrs[j].offset = pos;
4026 pos += newTableHdrs[j].length = sizeof(postTab);
4028 pos += 4 - (pos & 3);
4032 tableDir = (char *)gmalloc(12 + nAllTables * 16);
4033 tableDir[0] = 0x00; // sfnt version
4037 tableDir[4] = (char)((nAllTables >> 8) & 0xff); // numTables
4038 tableDir[5] = (char)(nAllTables & 0xff);
4039 for (i = -1, t = (Guint)nAllTables; t; ++i, t >>= 1) ;
4041 tableDir[6] = (char)((t >> 8) & 0xff); // searchRange
4042 tableDir[7] = (char)(t & 0xff);
4043 tableDir[8] = (char)((i >> 8) & 0xff); // entrySelector
4044 tableDir[9] = (char)(i & 0xff);
4045 t = nAllTables * 16 - t;
4046 tableDir[10] = (char)((t >> 8) & 0xff); // rangeShift
4047 tableDir[11] = (char)(t & 0xff);
4049 for (i = 0; i < nAllTables; ++i) {
4050 tableDir[pos ] = newTableHdrs[i].tag[0];
4051 tableDir[pos+ 1] = newTableHdrs[i].tag[1];
4052 tableDir[pos+ 2] = newTableHdrs[i].tag[2];
4053 tableDir[pos+ 3] = newTableHdrs[i].tag[3];
4054 tableDir[pos+ 4] = (char)(newTableHdrs[i].checksum >> 24);
4055 tableDir[pos+ 5] = (char)(newTableHdrs[i].checksum >> 16);
4056 tableDir[pos+ 6] = (char)(newTableHdrs[i].checksum >> 8);
4057 tableDir[pos+ 7] = (char) newTableHdrs[i].checksum;
4058 tableDir[pos+ 8] = (char)(newTableHdrs[i].offset >> 24);
4059 tableDir[pos+ 9] = (char)(newTableHdrs[i].offset >> 16);
4060 tableDir[pos+10] = (char)(newTableHdrs[i].offset >> 8);
4061 tableDir[pos+11] = (char) newTableHdrs[i].offset;
4062 tableDir[pos+12] = (char)(newTableHdrs[i].length >> 24);
4063 tableDir[pos+13] = (char)(newTableHdrs[i].length >> 16);
4064 tableDir[pos+14] = (char)(newTableHdrs[i].length >> 8);
4065 tableDir[pos+15] = (char) newTableHdrs[i].length;
4069 // write the table directory
4070 fwrite(tableDir, 1, 12 + 16 * nAllTables, out);
4073 for (i = 0; i < nAllTables; ++i) {
4074 if (!haveCmap && !strncmp(newTableHdrs[i].tag, "cmap", 4)) {
4075 fwrite(cmapTab, 1, newTableHdrs[i].length, out);
4076 } else if (!haveName && !strncmp(newTableHdrs[i].tag, "name", 4)) {
4077 fwrite(nameTab, 1, newTableHdrs[i].length, out);
4078 } else if (!havePost && !strncmp(newTableHdrs[i].tag, "post", 4)) {
4079 fwrite(postTab, 1, newTableHdrs[i].length, out);
4080 } else if (unsortedLoca && !strncmp(newTableHdrs[i].tag, "loca", 4)) {
4081 fwrite(locaTable, 1, newTableHdrs[i].length, out);
4082 } else if (unsortedLoca && !strncmp(newTableHdrs[i].tag, "glyf", 4)) {
4083 pos = seekTable("glyf");
4084 for (j = 0; j < nGlyphs; ++j) {
4085 length = origLocaTable[j].length;
4087 pos + origLocaTable[j].pos + length <= (Guint)len) {
4088 fwrite(file + pos + origLocaTable[j].pos, 1, length, out);
4089 if ((k = length & 3)) {
4090 for (; k < 4; ++k) {
4091 fputc((char)0, out);
4097 fwrite(file + seekTable(newTableHdrs[i].tag),
4098 1, newTableHdrs[i].length, out);
4100 if ((j = (newTableHdrs[i].length & 3))) {
4101 for (; j < 4; ++j) {
4102 fputc((char)0, out);
4108 gfree(newTableHdrs);
4110 gfree(origLocaTable);