1 //========================================================================
5 // Copyright 1999-2003 Glyph & Cog, LLC
7 //========================================================================
11 #ifdef USE_GCC_PRAGMAS
12 #pragma implementation
24 #include "GlobalParams.h"
25 #include "CharCodeToUnicode.h"
26 #include "FontEncodingTables.h"
29 #include "CompactFontTables.h"
31 //------------------------------------------------------------------------
33 static inline char *nextLine(char *line, char *end) {
34 while (line < end && *line != '\n' && *line != '\r')
36 while (line < end && *line == '\n' || *line == '\r')
41 static char hexChars[17] = "0123456789ABCDEF";
43 //------------------------------------------------------------------------
45 //------------------------------------------------------------------------
47 FontFile::FontFile() {
50 FontFile::~FontFile() {
53 //------------------------------------------------------------------------
55 //------------------------------------------------------------------------
57 Type1FontFile::Type1FontFile(char *file, int len) {
58 char *line, *line1, *p, *p2;
65 encoding = (char **)gmalloc(256 * sizeof(char *));
66 for (i = 0; i < 256; ++i) {
69 haveEncoding = gFalse;
71 for (i = 1, line = file;
72 i <= 100 && line < file + len && !haveEncoding;
76 if (!strncmp(line, "/FontName", 9)) {
77 strncpy(buf, line, 255);
79 if ((p = strchr(buf+9, '/')) &&
80 (p = strtok(p+1, " \t\n\r"))) {
83 line = nextLine(line, file + len);
86 } else if (!strncmp(line, "/Encoding StandardEncoding def", 30)) {
87 for (j = 0; j < 256; ++j) {
88 if (standardEncoding[j]) {
89 encoding[j] = copyString(standardEncoding[j]);
93 } else if (!strncmp(line, "/Encoding 256 array", 19)) {
94 for (j = 0; j < 300; ++j) {
95 line1 = nextLine(line, file + len);
96 if ((n = line1 - line) > 255) {
99 strncpy(buf, line, n);
101 for (p = buf; *p == ' ' || *p == '\t'; ++p) ;
102 if (!strncmp(p, "dup", 3)) {
103 for (p += 3; *p == ' ' || *p == '\t'; ++p) ;
104 for (p2 = p; *p2 >= '0' && *p2 <= '9'; ++p2) ;
108 if ((code = atoi(p)) < 256) {
110 for (p = p2; *p == ' ' || *p == '\t'; ++p) ;
113 for (p2 = p; *p2 && *p2 != ' ' && *p2 != '\t'; ++p2) ;
115 encoding[code] = copyString(p);
120 if (strtok(buf, " \t") &&
121 (p = strtok(NULL, " \t\n\r")) && !strcmp(p, "def")) {
127 //~ check for getinterval/putinterval junk
128 haveEncoding = gTrue;
131 line = nextLine(line, file + len);
136 Type1FontFile::~Type1FontFile() {
142 for (i = 0; i < 256; ++i) {
148 //------------------------------------------------------------------------
150 //------------------------------------------------------------------------
152 struct Type1CTopDict {
161 double underlinePosition;
162 double underlineThickness;
165 double fontMatrix[6];
175 //----- CIDFont entries
183 struct Type1CPrivateDict {
186 double defaultWidthX;
187 GBool defaultWidthXFP;
188 double nominalWidthX;
189 GBool nominalWidthXFP;
192 Type1CFontFile::Type1CFontFile(char *fileA, int lenA) {
193 int nameIdxPos, namePos, nameLen;
195 file = (Guchar *)fileA;
201 // some tools embed Type 1C fonts with an extra whitespace char at
203 if (len > 0 && file[0] != '\x01') {
208 // make sure the header exists
213 // read name index (first font only)
214 nameIdxPos = file[2] & 0xff;
215 if ((namePos = getIndexValPos(nameIdxPos, 0, &nameLen)) < 0) {
218 name = new GString((char *)&file[namePos], nameLen);
220 topDictIdxPos = getIndexEnd(nameIdxPos);
221 stringIdxPos = getIndexEnd(topDictIdxPos);
222 gsubrIdxPos = getIndexEnd(stringIdxPos);
227 Type1CFontFile::~Type1CFontFile() {
232 for (i = 0; i < 256; ++i) {
239 char *Type1CFontFile::getName() {
240 return name->getCString();
243 char **Type1CFontFile::getEncoding() {
250 void Type1CFontFile::readEncoding() {
252 int idxPos, idxLen, pos;
254 int nCodes, nRanges, nLeft, nSups;
256 int charset, enc, charstrings;
264 encoding = (char **)gmalloc(256 * sizeof(char *));
265 for (i = 0; i < 256; ++i) {
269 // read top dict (first font only)
270 if ((idxPos = getIndexValPos(topDictIdxPos, 0, &idxLen)) < 0) {
273 charset = enc = charstrings = 0;
276 while (pos < idxPos + idxLen) {
277 if (file[pos] <= 27 || file[pos] == 31) {
280 if (pos >= idxPos + idxLen) {
283 key = (key << 8) | file[pos++];
285 if (key == 0x0f) { // charset
286 charset = (int)op[0];
287 } else if (key == 0x10) { // encoding
289 } else if (key == 0x11) { // charstrings
290 charstrings = (int)op[0];
294 x = getNum(&pos, &isFP);
301 // get number of glyphs from charstrings index
302 nGlyphs = getIndexLen(charstrings);
304 // read charset (GID -> name mapping)
305 glyphNames = readCharset(charset, nGlyphs);
307 // read encoding (GID -> code mapping)
309 for (i = 0; i < 256; ++i) {
310 if (standardEncoding[i]) {
311 encoding[i] = copyString(standardEncoding[i]);
314 } else if (enc == 1) {
315 for (i = 0; i < 256; ++i) {
316 if (expertEncoding[i]) {
317 encoding[i] = copyString(expertEncoding[i]);
322 if (pos < 0 || pos >= len) {
325 encFormat = file[pos++];
326 if ((encFormat & 0x7f) == 0) {
330 nCodes = 1 + file[pos++];
331 if (nCodes > nGlyphs) {
334 if (pos + nCodes - 1 > len) {
337 for (i = 1; i < nCodes; ++i) {
342 encoding[c] = copyString(getString(glyphNames[i], buf));
344 } else if ((encFormat & 0x7f) == 1) {
348 nRanges = file[pos++];
349 if (pos + 2 * nRanges > len) {
353 for (i = 0; i < nRanges; ++i) {
356 for (j = 0; j <= nLeft && nCodes < nGlyphs; ++j) {
360 encoding[c] = copyString(getString(glyphNames[nCodes], buf));
366 if (encFormat & 0x80) {
371 if (pos + nSups * 3 > len) {
374 for (i = 0; i < nSups; ++i) {
376 sid = getWord(pos, 2);
381 encoding[c] = copyString(getString(sid, buf));
387 if (charset < 0 || charset > 2) {
392 void Type1CFontFile::convertToType1(FontFileOutputFunc outputFuncA,
393 void *outputStreamA) {
395 Type1CPrivateDict privateDict;
396 char buf[512], eBuf[256];
397 int idxPos, idxLen, pos;
398 int nGlyphs, nCodes, nRanges, nLeft, nSups;
400 int encFormat, nCharStrings;
404 outputFunc = outputFuncA;
405 outputStream = outputStreamA;
407 // read top dict (first font only)
410 // write header and font dictionary, up to encoding
411 (*outputFunc)(outputStream, "%!FontType1-1.0: ", 17);
412 (*outputFunc)(outputStream, name->getCString(), name->getLength());
413 if (dict.version != 0) {
414 getString(dict.version, buf);
415 (*outputFunc)(outputStream, buf, strlen(buf));
417 (*outputFunc)(outputStream, "\n", 1);
418 (*outputFunc)(outputStream, "11 dict begin\n", 14);
419 (*outputFunc)(outputStream, "/FontInfo 10 dict dup begin\n", 28);
420 if (dict.version != 0) {
421 (*outputFunc)(outputStream, "/version (", 10);
422 (*outputFunc)(outputStream, buf, strlen(buf));
423 (*outputFunc)(outputStream, ") readonly def\n", 15);
425 if (dict.notice != 0) {
426 getString(dict.notice, buf);
427 (*outputFunc)(outputStream, "/Notice (", 9);
428 (*outputFunc)(outputStream, buf, strlen(buf));
429 (*outputFunc)(outputStream, ") readonly def\n", 15);
431 if (dict.copyright != 0) {
432 getString(dict.copyright, buf);
433 (*outputFunc)(outputStream, "/Copyright (", 12);
434 (*outputFunc)(outputStream, buf, strlen(buf));
435 (*outputFunc)(outputStream, ") readonly def\n", 15);
437 if (dict.fullName != 0) {
438 getString(dict.fullName, buf);
439 (*outputFunc)(outputStream, "/FullName (", 11);
440 (*outputFunc)(outputStream, buf, strlen(buf));
441 (*outputFunc)(outputStream, ") readonly def\n", 15);
443 if (dict.familyName != 0) {
444 getString(dict.familyName, buf);
445 (*outputFunc)(outputStream, "/FamilyName (", 13);
446 (*outputFunc)(outputStream, buf, strlen(buf));
447 (*outputFunc)(outputStream, ") readonly def\n", 15);
449 if (dict.weight != 0) {
450 getString(dict.weight, buf);
451 (*outputFunc)(outputStream, "/Weight (", 9);
452 (*outputFunc)(outputStream, buf, strlen(buf));
453 (*outputFunc)(outputStream, ") readonly def\n", 15);
455 if (dict.isFixedPitch) {
456 (*outputFunc)(outputStream, "/isFixedPitch true def\n", 23);
458 (*outputFunc)(outputStream, "/isFixedPitch false def\n", 24);
460 sprintf(buf, "/ItalicAngle %g def\n", dict.italicAngle);
461 (*outputFunc)(outputStream, buf, strlen(buf));
462 sprintf(buf, "/UnderlinePosition %g def\n", dict.underlinePosition);
463 (*outputFunc)(outputStream, buf, strlen(buf));
464 sprintf(buf, "/UnderlineThickness %g def\n", dict.underlineThickness);
465 (*outputFunc)(outputStream, buf, strlen(buf));
466 (*outputFunc)(outputStream, "end readonly def\n", 17);
467 (*outputFunc)(outputStream, "/FontName /", 11);
468 (*outputFunc)(outputStream, name->getCString(), name->getLength());
469 (*outputFunc)(outputStream, " def\n", 5);
470 sprintf(buf, "/PaintType %d def\n", dict.paintType);
471 (*outputFunc)(outputStream, buf, strlen(buf));
472 (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
473 sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] readonly def\n",
474 dict.fontMatrix[0], dict.fontMatrix[1], dict.fontMatrix[2],
475 dict.fontMatrix[3], dict.fontMatrix[4], dict.fontMatrix[5]);
476 (*outputFunc)(outputStream, buf, strlen(buf));
477 sprintf(buf, "/FontBBox [%g %g %g %g] readonly def\n",
478 dict.fontBBox[0], dict.fontBBox[1],
479 dict.fontBBox[2], dict.fontBBox[3]);
480 (*outputFunc)(outputStream, buf, strlen(buf));
481 sprintf(buf, "/StrokeWidth %g def\n", dict.strokeWidth);
482 (*outputFunc)(outputStream, buf, strlen(buf));
483 if (dict.uniqueID != 0) {
484 sprintf(buf, "/UniqueID %d def\n", dict.uniqueID);
485 (*outputFunc)(outputStream, buf, strlen(buf));
488 // get number of glyphs from charstrings index
489 nGlyphs = getIndexLen(dict.charStrings);
492 glyphNames = readCharset(dict.charset, nGlyphs);
494 // read encoding (glyph -> code mapping), write Type 1 encoding
495 (*outputFunc)(outputStream, "/Encoding ", 10);
496 if (dict.encoding == 0) {
497 (*outputFunc)(outputStream, "StandardEncoding def\n", 21);
499 (*outputFunc)(outputStream, "256 array\n", 10);
500 (*outputFunc)(outputStream,
501 "0 1 255 {1 index exch /.notdef put} for\n", 40);
502 if (dict.encoding == 1) {
503 for (i = 0; i < 256; ++i) {
504 if (expertEncoding[i]) {
505 sprintf(buf, "dup %d /%s put\n", i, expertEncoding[i]);
506 (*outputFunc)(outputStream, buf, strlen(buf));
511 if (pos < 0 || pos >= len) {
514 encFormat = file[pos++];
515 if ((encFormat & 0x7f) == 0) {
519 nCodes = 1 + file[pos++];
520 if (nCodes > nGlyphs) {
523 if (pos + nCodes - 1 > len) {
526 for (i = 1; i < nCodes; ++i) {
528 sprintf(buf, "dup %d /", c);
529 (*outputFunc)(outputStream, buf, strlen(buf));
530 getString(glyphNames[i], buf);
531 (*outputFunc)(outputStream, buf, strlen(buf));
532 (*outputFunc)(outputStream, " put\n", 5);
534 } else if ((encFormat & 0x7f) == 1) {
538 nRanges = file[pos++];
539 if (pos + 2 * nRanges > len) {
543 for (i = 0; i < nRanges; ++i) {
546 for (j = 0; j <= nLeft && nCodes < nGlyphs; ++j) {
547 sprintf(buf, "dup %d /", c);
548 (*outputFunc)(outputStream, buf, strlen(buf));
549 getString(glyphNames[nCodes], buf);
550 (*outputFunc)(outputStream, buf, strlen(buf));
551 (*outputFunc)(outputStream, " put\n", 5);
557 if (encFormat & 0x80) {
562 if (pos + nSups * 3 > len) {
565 for (i = 0; i < nSups; ++i) {
567 sid = getWord(pos, 2);
569 sprintf(buf, "dup %d /", c);
570 (*outputFunc)(outputStream, buf, strlen(buf));
572 (*outputFunc)(outputStream, buf, strlen(buf));
573 (*outputFunc)(outputStream, " put\n", 5);
578 (*outputFunc)(outputStream, "readonly def\n", 13);
580 (*outputFunc)(outputStream, "currentdict end\n", 16);
582 // start the binary section
583 (*outputFunc)(outputStream, "currentfile eexec\n", 18);
587 // get private dictionary
588 eexecWrite("\x83\xca\x73\xd5");
589 eexecWrite("dup /Private 32 dict dup begin\n");
590 eexecWrite("/RD {string currentfile exch readstring pop} executeonly def\n");
591 eexecWrite("/ND {noaccess def} executeonly def\n");
592 eexecWrite("/NP {noaccess put} executeonly def\n");
593 eexecWrite("/MinFeature {16 16} ND\n");
594 readPrivateDict(&privateDict, dict.privateOffset, dict.privateSize);
595 eexecWrite(privateDict.dictData->getCString());
596 defaultWidthX = privateDict.defaultWidthX;
597 defaultWidthXFP = privateDict.defaultWidthXFP;
598 nominalWidthX = privateDict.nominalWidthX;
599 nominalWidthXFP = privateDict.nominalWidthXFP;
601 // set up subroutines
602 subrIdxPos = dict.privateOffset + privateDict.subrsOffset;
603 i = getIndexLen(gsubrIdxPos);
604 gsubrBias = (i < 1240) ? 107 : (i < 33900) ? 1131 : 32768;
605 i = getIndexLen(subrIdxPos);
606 subrBias = (i < 1240) ? 107 : (i < 33900) ? 1131 : 32768;
609 nCharStrings = getIndexLen(dict.charStrings);
610 sprintf(eBuf, "2 index /CharStrings %d dict dup begin\n", nCharStrings);
612 for (i = 0; i < nCharStrings; ++i) {
613 if ((idxPos = getIndexValPos(dict.charStrings, i, &idxLen)) >= 0) {
614 eexecCvtGlyph(getString(glyphNames[i], buf), idxPos, idxLen);
619 eexecWrite("readonly put\n");
620 eexecWrite("noaccess put\n");
621 eexecWrite("dup /FontName get exch definefont pop\n");
622 eexecWrite("mark currentfile closefile\n");
626 (*outputFunc)(outputStream, "\n", 1);
628 for (i = 0; i < 8; ++i) {
629 (*outputFunc)(outputStream, "0000000000000000000000000000000000000000000000000000000000000000\n", 65);
631 (*outputFunc)(outputStream, "cleartomark\n", 12);
634 delete privateDict.dictData;
635 if (dict.charset > 2) {
640 void Type1CFontFile::convertToCIDType0(char *psName,
641 FontFileOutputFunc outputFuncA,
642 void *outputStreamA) {
644 Type1CPrivateDict *privateDicts;
645 GString *charStrings;
646 int *charStringOffsets;
650 int idxPos, idxLen, pos;
651 char buf[512], buf2[16];
652 int nGlyphs, nCIDs, gdBytes, nFDs;
653 int fdSelectFmt, nRanges, gid0, gid1, fd, offset;
659 outputFunc = outputFuncA;
660 outputStream = outputStreamA;
662 (*outputFunc)(outputStream, "/CIDInit /ProcSet findresource begin\n", 37);
664 // read top dict (first font only)
667 // read the FDArray dictionaries and Private dictionaries
668 if (dict.fdArrayOffset == 0) {
670 privateDicts = (Type1CPrivateDict *)
671 gmalloc(nFDs * sizeof(Type1CPrivateDict));
672 privateDicts[0].dictData = new GString();
673 privateDicts[0].subrsOffset = 0;
674 privateDicts[0].defaultWidthX = 0;
675 privateDicts[0].defaultWidthXFP = gFalse;
676 privateDicts[0].nominalWidthX = 0;
677 privateDicts[0].nominalWidthXFP = gFalse;
679 if ((nFDs = getIndexLen(dict.fdArrayOffset)) < 0) {
682 privateDicts = (Type1CPrivateDict *)
683 gmalloc(nFDs * sizeof(Type1CPrivateDict));
684 for (i = 0; i < nFDs; ++i) {
685 privateDicts[i].dictData = NULL;
687 for (i = 0; i < nFDs; ++i) {
688 privateDicts[i].dictData = NULL;
689 if ((idxPos = getIndexValPos(dict.fdArrayOffset, i, &idxLen)) < 0) {
694 while (pos < idxPos + idxLen) {
695 if (file[pos] <= 27 || file[pos] == 31) {
698 if (pos >= idxPos + idxLen) {
701 key = (key << 8) | file[pos++];
704 readPrivateDict(&privateDicts[i], (int)op[1], (int)op[0]);
708 x = getNum(&pos, &isFP);
715 if (!privateDicts[i].dictData) {
716 privateDicts[i].dictData = new GString();
717 privateDicts[i].subrsOffset = 0;
718 privateDicts[i].defaultWidthX = 0;
719 privateDicts[i].defaultWidthXFP = gFalse;
720 privateDicts[i].nominalWidthX = 0;
721 privateDicts[i].nominalWidthXFP = gFalse;
726 // get the glyph count
727 if ((nGlyphs = getIndexLen(dict.charStrings)) < 0) {
731 // read the FDSelect table
732 fdSelect = (Guchar *)gmalloc(nGlyphs);
733 if (dict.fdSelectOffset == 0) {
734 for (i = 0; i < nGlyphs; ++i) {
738 pos = dict.fdSelectOffset;
739 if (pos < 0 || pos >= len) {
742 fdSelectFmt = file[pos++];
743 if (fdSelectFmt == 0) {
744 if (pos + nGlyphs > len) {
747 memcpy(fdSelect, file + pos, nGlyphs);
748 } else if (fdSelectFmt == 3) {
752 nRanges = getWord(pos, 2);
754 gid0 = getWord(pos, 2);
756 if (pos + nRanges * 3 > len) {
759 for (i = 1; i <= nRanges; ++i) {
761 gid1 = getWord(pos, 2);
763 for (j = gid0; j < gid1; ++j) {
769 error(-1, "Unknown FDSelect table format in CID font");
770 for (i = 0; i < nGlyphs; ++i) {
776 // read the charset, compute the CID-to-GID mapping
777 charset = readCharset(dict.charset, nGlyphs);
779 for (i = 0; i < nGlyphs; ++i) {
780 if (charset[i] >= nCIDs) {
781 nCIDs = charset[i] + 1;
784 cidMap = (int *)gmalloc(nCIDs * sizeof(int));
785 for (i = 0; i < nCIDs; ++i) {
788 for (i = 0; i < nGlyphs; ++i) {
789 cidMap[charset[i]] = i;
792 // set up global subroutines
793 i = getIndexLen(gsubrIdxPos);
794 gsubrBias = (i < 1240) ? 107 : (i < 33900) ? 1131 : 32768;
796 // build the charstrings
797 charStrings = new GString();
798 charStringOffsets = (int *)gmalloc((nCIDs + 1) * sizeof(int));
799 for (i = 0; i < nCIDs; ++i) {
800 charStringOffsets[i] = charStrings->getLength();
801 if (cidMap[i] >= 0) {
802 if ((idxPos = getIndexValPos(dict.charStrings,
803 cidMap[i], &idxLen)) >= 0) {
804 j = fdSelect[cidMap[i]];
805 defaultWidthX = privateDicts[j].defaultWidthX;
806 defaultWidthXFP = privateDicts[j].defaultWidthXFP;
807 nominalWidthX = privateDicts[j].nominalWidthX;
808 nominalWidthXFP = privateDicts[j].nominalWidthXFP;
809 subrIdxPos = dict.privateOffset + privateDicts[j].subrsOffset;
810 k = getIndexLen(subrIdxPos);
811 subrBias = (k < 1240) ? 107 : (k < 33900) ? 1131 : 32768;
812 cvtGlyph(idxPos, idxLen, gTrue);
813 charStrings->append(charBuf);
818 charStringOffsets[nCIDs] = charStrings->getLength();
820 // compute gdBytes = number of bytes needed for charstring offsets
821 // (offset size needs to account for the charstring offset table,
822 // with a worst case of five bytes per entry, plus the charstrings
824 i = (nCIDs + 1) * 5 + charStrings->getLength();
827 } else if (i < 0x10000) {
829 } else if (i < 0x1000000) {
835 // begin the font dictionary
836 (*outputFunc)(outputStream, "20 dict begin\n", 14);
837 (*outputFunc)(outputStream, "/CIDFontName /", 14);
838 (*outputFunc)(outputStream, psName, strlen(psName));
839 (*outputFunc)(outputStream, " def\n", 5);
840 (*outputFunc)(outputStream, "/CIDFontType 0 def\n", 19);
841 (*outputFunc)(outputStream, "/CIDSystemInfo 3 dict dup begin\n", 32);
842 if (dict.registry > 0 && dict.ordering > 0) {
843 getString(dict.registry, buf);
844 (*outputFunc)(outputStream, " /Registry (", 13);
845 (*outputFunc)(outputStream, buf, strlen(buf));
846 (*outputFunc)(outputStream, ") def\n", 6);
847 getString(dict.ordering, buf);
848 (*outputFunc)(outputStream, " /Ordering (", 13);
849 (*outputFunc)(outputStream, buf, strlen(buf));
850 (*outputFunc)(outputStream, ") def\n", 6);
852 (*outputFunc)(outputStream, " /Registry (Adobe) def\n", 24);
853 (*outputFunc)(outputStream, " /Ordering (Identity) def\n", 27);
855 sprintf(buf, " /Supplement %d def\n", dict.supplement);
856 (*outputFunc)(outputStream, buf, strlen(buf));
857 (*outputFunc)(outputStream, "end def\n", 8);
858 sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n",
859 dict.fontMatrix[0], dict.fontMatrix[1], dict.fontMatrix[2],
860 dict.fontMatrix[3], dict.fontMatrix[4], dict.fontMatrix[5]);
861 (*outputFunc)(outputStream, buf, strlen(buf));
862 sprintf(buf, "/FontBBox [%g %g %g %g] def\n",
863 dict.fontBBox[0], dict.fontBBox[1],
864 dict.fontBBox[2], dict.fontBBox[3]);
865 (*outputFunc)(outputStream, buf, strlen(buf));
866 (*outputFunc)(outputStream, "/FontInfo 1 dict dup begin\n", 27);
867 (*outputFunc)(outputStream, " /FSType 8 def\n", 16);
868 (*outputFunc)(outputStream, "end def\n", 8);
870 // CIDFont-specific entries
871 sprintf(buf, "/CIDCount %d def\n", nCIDs);
872 (*outputFunc)(outputStream, buf, strlen(buf));
873 (*outputFunc)(outputStream, "/FDBytes 1 def\n", 15);
874 sprintf(buf, "/GDBytes %d def\n", gdBytes);
875 (*outputFunc)(outputStream, buf, strlen(buf));
876 (*outputFunc)(outputStream, "/CIDMapOffset 0 def\n", 20);
877 if (dict.paintType != 0) {
878 sprintf(buf, "/PaintType %d def\n", dict.paintType);
879 (*outputFunc)(outputStream, buf, strlen(buf));
880 sprintf(buf, "/StrokeWidth %g def\n", dict.strokeWidth);
881 (*outputFunc)(outputStream, buf, strlen(buf));
885 sprintf(buf, "/FDArray %d array\n", nFDs);
886 (*outputFunc)(outputStream, buf, strlen(buf));
887 for (i = 0; i < nFDs; ++i) {
888 sprintf(buf, "dup %d 10 dict begin\n", i);
889 (*outputFunc)(outputStream, buf, strlen(buf));
890 (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
891 (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
892 sprintf(buf, "/PaintType %d def\n", dict.paintType);
893 (*outputFunc)(outputStream, buf, strlen(buf));
894 (*outputFunc)(outputStream, "/Private 32 dict begin\n", 23);
895 (*outputFunc)(outputStream, privateDicts[i].dictData->getCString(),
896 privateDicts[i].dictData->getLength());
897 (*outputFunc)(outputStream, "currentdict end def\n", 20);
898 (*outputFunc)(outputStream, "currentdict end put\n", 20);
900 (*outputFunc)(outputStream, "def\n", 4);
902 // start the binary section
903 offset = (nCIDs + 1) * (1 + gdBytes);
904 sprintf(buf, "(Hex) %d StartData\n",
905 offset + charStrings->getLength());
906 (*outputFunc)(outputStream, buf, strlen(buf));
908 // write the charstring offset (CIDMap) table
909 for (i = 0; i <= nCIDs; i += 6) {
910 for (j = 0; j < 6 && i+j <= nCIDs; ++j) {
911 if (i+j < nCIDs && cidMap[i+j] >= 0) {
912 buf[0] = (char)fdSelect[cidMap[i+j]];
916 n = offset + charStringOffsets[i+j];
917 for (k = gdBytes; k >= 1; --k) {
918 buf[k] = (char)(n & 0xff);
921 for (k = 0; k <= gdBytes; ++k) {
922 sprintf(buf2, "%02x", buf[k] & 0xff);
923 (*outputFunc)(outputStream, buf2, 2);
926 (*outputFunc)(outputStream, "\n", 1);
929 // write the charstring data
930 n = charStrings->getLength();
931 for (i = 0; i < n; i += 32) {
932 for (j = 0; j < 32 && i+j < n; ++j) {
933 sprintf(buf, "%02x", charStrings->getChar(i+j) & 0xff);
934 (*outputFunc)(outputStream, buf, strlen(buf));
937 (*outputFunc)(outputStream, ">", 1);
939 (*outputFunc)(outputStream, "\n", 1);
942 gfree(charStringOffsets);
949 for (i = 0; i < nFDs; ++i) {
950 if (privateDicts[i].dictData) {
951 delete privateDicts[i].dictData;
958 void Type1CFontFile::convertToType0(char *psName,
959 FontFileOutputFunc outputFuncA,
960 void *outputStreamA) {
962 Type1CPrivateDict *privateDicts;
966 int idxPos, idxLen, pos;
969 int nGlyphs, nCIDs, nFDs;
970 int fdSelectFmt, nRanges, gid0, gid1, fd;
976 outputFunc = outputFuncA;
977 outputStream = outputStreamA;
979 // read top dict (first font only)
982 // read the FDArray dictionaries and Private dictionaries
983 if (dict.fdArrayOffset == 0) {
985 privateDicts = (Type1CPrivateDict *)
986 gmalloc(nFDs * sizeof(Type1CPrivateDict));
987 privateDicts[0].dictData = new GString();
988 privateDicts[0].subrsOffset = 0;
989 privateDicts[0].defaultWidthX = 0;
990 privateDicts[0].defaultWidthXFP = gFalse;
991 privateDicts[0].nominalWidthX = 0;
992 privateDicts[0].nominalWidthXFP = gFalse;
994 if ((nFDs = getIndexLen(dict.fdArrayOffset)) < 0) {
997 privateDicts = (Type1CPrivateDict *)
998 gmalloc(nFDs * sizeof(Type1CPrivateDict));
999 for (i = 0; i < nFDs; ++i) {
1000 privateDicts[i].dictData = NULL;
1002 for (i = 0; i < nFDs; ++i) {
1003 privateDicts[i].dictData = NULL;
1004 if ((idxPos = getIndexValPos(dict.fdArrayOffset, i, &idxLen)) < 0) {
1009 while (pos < idxPos + idxLen) {
1010 if (file[pos] <= 27 || file[pos] == 31) {
1013 if (pos >= idxPos + idxLen) {
1016 key = (key << 8) | file[pos++];
1018 if (key == 0x0012) {
1019 readPrivateDict(&privateDicts[i], (int)op[1], (int)op[0]);
1023 x = getNum(&pos, &isFP);
1030 if (!privateDicts[i].dictData) {
1031 privateDicts[i].dictData = new GString();
1032 privateDicts[i].subrsOffset = 0;
1033 privateDicts[i].defaultWidthX = 0;
1034 privateDicts[i].defaultWidthXFP = gFalse;
1035 privateDicts[i].nominalWidthX = 0;
1036 privateDicts[i].nominalWidthXFP = gFalse;
1041 // get the glyph count
1042 if ((nGlyphs = getIndexLen(dict.charStrings)) < 0) {
1046 // read the FDSelect table
1047 fdSelect = (Guchar *)gmalloc(nGlyphs);
1048 if (dict.fdSelectOffset == 0) {
1049 for (i = 0; i < nGlyphs; ++i) {
1053 pos = dict.fdSelectOffset;
1054 if (pos < 0 || pos >= len) {
1057 fdSelectFmt = file[pos++];
1058 if (fdSelectFmt == 0) {
1059 if (pos + nGlyphs > len) {
1062 memcpy(fdSelect, file + pos, nGlyphs);
1063 } else if (fdSelectFmt == 3) {
1064 if (pos + 4 > len) {
1067 nRanges = getWord(pos, 2);
1069 gid0 = getWord(pos, 2);
1071 if (pos + nRanges * 3 > len) {
1074 for (i = 1; i <= nRanges; ++i) {
1076 gid1 = getWord(pos, 2);
1078 for (j = gid0; j < gid1; ++j) {
1084 error(-1, "Unknown FDSelect table format in CID font");
1085 for (i = 0; i < nGlyphs; ++i) {
1091 // read the charset, compute the CID-to-GID mapping
1092 charset = readCharset(dict.charset, nGlyphs);
1094 for (i = 0; i < nGlyphs; ++i) {
1095 if (charset[i] >= nCIDs) {
1096 nCIDs = charset[i] + 1;
1099 cidMap = (int *)gmalloc(nCIDs * sizeof(int));
1100 for (i = 0; i < nCIDs; ++i) {
1103 for (i = 0; i < nGlyphs; ++i) {
1104 cidMap[charset[i]] = i;
1107 // set up global subroutines
1108 i = getIndexLen(gsubrIdxPos);
1109 gsubrBias = (i < 1240) ? 107 : (i < 33900) ? 1131 : 32768;
1111 // write the descendant Type 1 fonts
1112 for (i = 0; i < nCIDs; i += 256) {
1114 //~ this assumes that all CIDs in this block have the same FD --
1115 //~ to handle multiple FDs correctly, need to somehow divide the
1118 for (j = 0; j < 256 && i+j < nCIDs; ++j) {
1119 if (cidMap[i+j] >= 0) {
1120 fd = fdSelect[cidMap[i+j]];
1125 // font dictionary (unencrypted section)
1126 (*outputFunc)(outputStream, "16 dict begin\n", 14);
1127 (*outputFunc)(outputStream, "/FontName /", 11);
1128 (*outputFunc)(outputStream, psName, strlen(psName));
1129 sprintf(buf, "_%02x def\n", i >> 8);
1130 (*outputFunc)(outputStream, buf, strlen(buf));
1131 (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
1132 sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n",
1133 dict.fontMatrix[0], dict.fontMatrix[1], dict.fontMatrix[2],
1134 dict.fontMatrix[3], dict.fontMatrix[4], dict.fontMatrix[5]);
1135 (*outputFunc)(outputStream, buf, strlen(buf));
1136 sprintf(buf, "/FontBBox [%g %g %g %g] def\n",
1137 dict.fontBBox[0], dict.fontBBox[1],
1138 dict.fontBBox[2], dict.fontBBox[3]);
1139 (*outputFunc)(outputStream, buf, strlen(buf));
1140 sprintf(buf, "/PaintType %d def\n", dict.paintType);
1141 (*outputFunc)(outputStream, buf, strlen(buf));
1142 if (dict.paintType != 0) {
1143 sprintf(buf, "/StrokeWidth %g def\n", dict.strokeWidth);
1144 (*outputFunc)(outputStream, buf, strlen(buf));
1146 (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
1147 for (j = 0; j < 256 && i+j < nCIDs; ++j) {
1148 sprintf(buf, "dup %d /c%02x put\n", j, j);
1149 (*outputFunc)(outputStream, buf, strlen(buf));
1151 (*outputFunc)(outputStream, "readonly def\n", 13);
1152 (*outputFunc)(outputStream, "currentdict end\n", 16);
1154 // start the binary section
1155 (*outputFunc)(outputStream, "currentfile eexec\n", 18);
1159 // start the private dictionary
1160 eexecWrite("\x83\xca\x73\xd5");
1161 eexecWrite("dup /Private 32 dict dup begin\n");
1162 eexecWrite("/RD {string currentfile exch readstring pop} executeonly def\n");
1163 eexecWrite("/ND {noaccess def} executeonly def\n");
1164 eexecWrite("/NP {noaccess put} executeonly def\n");
1165 eexecWrite("/MinFeature {16 16} ND\n");
1166 eexecWrite(privateDicts[fd].dictData->getCString());
1167 defaultWidthX = privateDicts[fd].defaultWidthX;
1168 defaultWidthXFP = privateDicts[fd].defaultWidthXFP;
1169 nominalWidthX = privateDicts[fd].nominalWidthX;
1170 nominalWidthXFP = privateDicts[fd].nominalWidthXFP;
1172 // set up the subroutines
1173 subrIdxPos = dict.privateOffset + privateDicts[fd].subrsOffset;
1174 j = getIndexLen(subrIdxPos);
1175 subrBias = (j < 1240) ? 107 : (j < 33900) ? 1131 : 32768;
1177 // start the CharStrings
1178 sprintf(eBuf, "2 index /CharStrings 256 dict dup begin\n");
1181 // write the .notdef CharString
1182 if ((idxPos = getIndexValPos(dict.charStrings, 0, &idxLen)) >= 0) {
1183 eexecCvtGlyph(".notdef", idxPos, idxLen);
1186 // write the CharStrings
1187 for (j = 0; j < 256 && i+j < nCIDs; ++j) {
1188 if (cidMap[i+j] >= 0) {
1189 if ((idxPos = getIndexValPos(dict.charStrings,
1190 cidMap[i+j], &idxLen)) >= 0) {
1191 sprintf(buf, "c%02x", j);
1192 eexecCvtGlyph(buf, idxPos, idxLen);
1196 eexecWrite("end\n");
1197 eexecWrite("end\n");
1198 eexecWrite("readonly put\n");
1199 eexecWrite("noaccess put\n");
1200 eexecWrite("dup /FontName get exch definefont pop\n");
1201 eexecWrite("mark currentfile closefile\n");
1205 (*outputFunc)(outputStream, "\n", 1);
1207 for (j = 0; j < 8; ++j) {
1208 (*outputFunc)(outputStream, "0000000000000000000000000000000000000000000000000000000000000000\n", 65);
1210 (*outputFunc)(outputStream, "cleartomark\n", 12);
1213 // write the Type 0 parent font
1214 (*outputFunc)(outputStream, "16 dict begin\n", 14);
1215 (*outputFunc)(outputStream, "/FontName /", 11);
1216 (*outputFunc)(outputStream, psName, strlen(psName));
1217 (*outputFunc)(outputStream, " def\n", 5);
1218 (*outputFunc)(outputStream, "/FontType 0 def\n", 16);
1219 (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
1220 (*outputFunc)(outputStream, "/FMapType 2 def\n", 16);
1221 (*outputFunc)(outputStream, "/Encoding [\n", 12);
1222 for (i = 0; i < nCIDs; i += 256) {
1223 sprintf(buf, "%d\n", i >> 8);
1224 (*outputFunc)(outputStream, buf, strlen(buf));
1226 (*outputFunc)(outputStream, "] def\n", 6);
1227 (*outputFunc)(outputStream, "/FDepVector [\n", 14);
1228 for (i = 0; i < nCIDs; i += 256) {
1229 (*outputFunc)(outputStream, "/", 1);
1230 (*outputFunc)(outputStream, psName, strlen(psName));
1231 sprintf(buf, "_%02x findfont\n", i >> 8);
1232 (*outputFunc)(outputStream, buf, strlen(buf));
1234 (*outputFunc)(outputStream, "] def\n", 6);
1235 (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
1243 for (i = 0; i < nFDs; ++i) {
1244 if (privateDicts[i].dictData) {
1245 delete privateDicts[i].dictData;
1248 gfree(privateDicts);
1252 void Type1CFontFile::readTopDict(Type1CTopDict *dict) {
1253 int idxPos, idxLen, pos;
1261 dict->copyright = 0;
1263 dict->familyName = 0;
1265 dict->isFixedPitch = 0;
1266 dict->italicAngle = 0;
1267 dict->underlinePosition = -100;
1268 dict->underlineThickness = 50;
1269 dict->paintType = 0;
1270 dict->charstringType = 2;
1271 dict->fontMatrix[0] = 0.001;
1272 dict->fontMatrix[1] = 0;
1273 dict->fontMatrix[2] = 0;
1274 dict->fontMatrix[3] = 0.001;
1275 dict->fontMatrix[4] = 0;
1276 dict->fontMatrix[5] = 0;
1278 dict->fontBBox[0] = 0;
1279 dict->fontBBox[1] = 0;
1280 dict->fontBBox[2] = 0;
1281 dict->fontBBox[3] = 0;
1282 dict->strokeWidth = 0;
1285 dict->charStrings = 0;
1286 dict->privateSize = 0;
1287 dict->privateOffset = 0;
1290 dict->supplement = 0;
1291 dict->fdArrayOffset = 0;
1292 dict->fdSelectOffset = 0;
1293 if ((idxPos = getIndexValPos(topDictIdxPos, 0, &idxLen)) < 0) {
1298 while (pos < idxPos + idxLen) {
1299 if (file[pos] <= 27 || file[pos] == 31) {
1302 if (pos >= idxPos + idxLen) {
1305 key = (key << 8) | file[pos++];
1308 case 0x0000: dict->version = (int)op[0]; break;
1309 case 0x0001: dict->notice = (int)op[0]; break;
1310 case 0x0c00: dict->copyright = (int)op[0]; break;
1311 case 0x0002: dict->fullName = (int)op[0]; break;
1312 case 0x0003: dict->familyName = (int)op[0]; break;
1313 case 0x0004: dict->weight = (int)op[0]; break;
1314 case 0x0c01: dict->isFixedPitch = (int)op[0]; break;
1315 case 0x0c02: dict->italicAngle = op[0]; break;
1316 case 0x0c03: dict->underlinePosition = op[0]; break;
1317 case 0x0c04: dict->underlineThickness = op[0]; break;
1318 case 0x0c05: dict->paintType = (int)op[0]; break;
1319 case 0x0c06: dict->charstringType = (int)op[0]; break;
1320 case 0x0c07: dict->fontMatrix[0] = op[0];
1321 dict->fontMatrix[1] = op[1];
1322 dict->fontMatrix[2] = op[2];
1323 dict->fontMatrix[3] = op[3];
1324 dict->fontMatrix[4] = op[4];
1325 dict->fontMatrix[5] = op[5]; break;
1326 case 0x000d: dict->uniqueID = (int)op[0]; break;
1327 case 0x0005: dict->fontBBox[0] = op[0];
1328 dict->fontBBox[1] = op[1];
1329 dict->fontBBox[2] = op[2];
1330 dict->fontBBox[3] = op[3]; break;
1331 case 0x0c08: dict->strokeWidth = op[0]; break;
1332 case 0x000f: dict->charset = (int)op[0]; break;
1333 case 0x0010: dict->encoding = (int)op[0]; break;
1334 case 0x0011: dict->charStrings = (int)op[0]; break;
1335 case 0x0012: dict->privateSize = (int)op[0];
1336 dict->privateOffset = (int)op[1]; break;
1337 case 0x0c1e: dict->registry = (int)op[0];
1338 dict->ordering = (int)op[1];
1339 dict->supplement = (int)op[2]; break;
1340 case 0x0c24: dict->fdArrayOffset = (int)op[0]; break;
1341 case 0x0c25: dict->fdSelectOffset = (int)op[0]; break;
1345 x = getNum(&pos, &isFP);
1354 void Type1CFontFile::readPrivateDict(Type1CPrivateDict *privateDict,
1355 int offset, int size) {
1363 privateDict->dictData = new GString();
1364 privateDict->subrsOffset = 0;
1365 privateDict->defaultWidthX = 0;
1366 privateDict->defaultWidthXFP = gFalse;
1367 privateDict->nominalWidthX = 0;
1368 privateDict->nominalWidthXFP = gFalse;
1369 if (offset < 0 || offset + size > len) {
1374 while (pos < offset + size) {
1375 if (file[pos] <= 27 || file[pos] == 31) {
1378 if (pos >= offset + size) {
1381 key = (key << 8) | file[pos++];
1385 getDeltaInt(eBuf, "BlueValues", op, i);
1386 privateDict->dictData->append(eBuf);
1389 getDeltaInt(eBuf, "OtherBlues", op, i);
1390 privateDict->dictData->append(eBuf);
1393 getDeltaInt(eBuf, "FamilyBlues", op, i);
1394 privateDict->dictData->append(eBuf);
1397 getDeltaInt(eBuf, "FamilyOtherBlues", op, i);
1398 privateDict->dictData->append(eBuf);
1401 sprintf(eBuf, "/BlueScale %g def\n", op[0]);
1402 privateDict->dictData->append(eBuf);
1405 sprintf(eBuf, "/BlueShift %d def\n", (int)op[0]);
1406 privateDict->dictData->append(eBuf);
1409 sprintf(eBuf, "/BlueFuzz %d def\n", (int)op[0]);
1410 privateDict->dictData->append(eBuf);
1413 sprintf(eBuf, "/StdHW [%g] def\n", op[0]);
1414 privateDict->dictData->append(eBuf);
1417 sprintf(eBuf, "/StdVW [%g] def\n", op[0]);
1418 privateDict->dictData->append(eBuf);
1421 getDeltaReal(eBuf, "StemSnapH", op, i);
1422 privateDict->dictData->append(eBuf);
1425 getDeltaReal(eBuf, "StemSnapV", op, i);
1426 privateDict->dictData->append(eBuf);
1429 sprintf(eBuf, "/ForceBold %s def\n", op[0] ? "true" : "false");
1430 privateDict->dictData->append(eBuf);
1433 sprintf(eBuf, "/ForceBoldThreshold %g def\n", op[0]);
1434 privateDict->dictData->append(eBuf);
1437 sprintf(eBuf, "/LanguageGroup %d def\n", (int)op[0]);
1438 privateDict->dictData->append(eBuf);
1441 sprintf(eBuf, "/ExpansionFactor %g def\n", op[0]);
1442 privateDict->dictData->append(eBuf);
1445 error(-1, "Got Type 1C InitialRandomSeed");
1448 privateDict->subrsOffset = (int)op[0];
1451 privateDict->defaultWidthX = op[0];
1452 privateDict->defaultWidthXFP = fp[0];
1455 privateDict->nominalWidthX = op[0];
1456 privateDict->nominalWidthXFP = fp[0];
1459 error(-1, "Unknown Type 1C private dict entry %04x", key);
1464 x = getNum(&pos, &isFP);
1473 Gushort *Type1CFontFile::readCharset(int charset, int nGlyphs) {
1474 Gushort *glyphNames;
1476 int charsetFormat, c;
1480 glyphNames = type1CISOAdobeCharset;
1481 } else if (charset == 1) {
1482 glyphNames = type1CExpertCharset;
1483 } else if (charset == 2) {
1484 glyphNames = type1CExpertSubsetCharset;
1486 glyphNames = (Gushort *)gmalloc(nGlyphs * sizeof(Gushort));
1487 for (i = 0; i < nGlyphs; ++i) {
1491 if (pos < 0 || pos >= len) {
1494 charsetFormat = file[pos++];
1495 if (charsetFormat == 0) {
1496 if (pos + (nGlyphs - 1) * 2 >= len) {
1499 for (i = 1; i < nGlyphs; ++i) {
1500 glyphNames[i] = getWord(pos, 2);
1503 } else if (charsetFormat == 1) {
1505 while (i < nGlyphs) {
1506 if (pos + 3 > len) {
1509 c = getWord(pos, 2);
1511 nLeft = file[pos++];
1512 for (j = 0; j <= nLeft && i < nGlyphs; ++j) {
1513 glyphNames[i++] = c++;
1516 } else if (charsetFormat == 2) {
1518 while (i < nGlyphs) {
1519 if (pos + 4 > len) {
1522 c = getWord(pos, 2);
1524 nLeft = getWord(pos, 2);
1526 for (j = 0; j <= nLeft && i < nGlyphs; ++j) {
1527 glyphNames[i++] = c++;
1536 void Type1CFontFile::eexecWrite(char *s) {
1540 for (p = (Guchar *)s; *p; ++p) {
1542 r1 = (x + r1) * 52845 + 22719;
1543 (*outputFunc)(outputStream, &hexChars[x >> 4], 1);
1544 (*outputFunc)(outputStream, &hexChars[x & 0x0f], 1);
1547 (*outputFunc)(outputStream, "\n", 1);
1553 void Type1CFontFile::eexecCvtGlyph(char *glyphName, int pos, int n) {
1556 cvtGlyph(pos, n, gTrue);
1557 sprintf(eBuf, "/%s %d RD ", glyphName, charBuf->getLength());
1559 eexecWriteCharstring((Guchar *)charBuf->getCString(), charBuf->getLength());
1560 eexecWrite(" ND\n");
1564 void Type1CFontFile::cvtGlyph(int pos, int n, GBool top) {
1566 int subrPos, subrLen;
1573 if (pos < 0 || pos + n > len) {
1578 charBuf = new GString();
1579 charBuf->append((char)73);
1580 charBuf->append((char)58);
1581 charBuf->append((char)147);
1582 charBuf->append((char)134);
1589 while (i < pos + n) {
1590 if (file[i] == 12) {
1591 if (i + 2 > pos + n) {
1594 switch (file[i+1]) {
1595 case 0: // dotsection (should be Type 1 only?)
1600 error(-1, "Wrong number of args (%d) to Type 2 hflex", nOps);
1602 eexecDumpNum(op[0], fp[0]);
1603 eexecDumpNum(0, gFalse);
1604 eexecDumpNum(op[1], fp[1]);
1605 eexecDumpNum(op[2], fp[2]);
1606 eexecDumpNum(op[3], fp[3]);
1607 eexecDumpNum(0, gFalse);
1609 eexecDumpNum(op[4], fp[4]);
1610 eexecDumpNum(0, gFalse);
1611 eexecDumpNum(op[5], fp[5]);
1612 eexecDumpNum(-op[2], fp[2]);
1613 eexecDumpNum(op[6], fp[6]);
1614 eexecDumpNum(0, gFalse);
1619 error(-1, "Wrong number of args (%d) to Type 2 flex", nOps);
1621 eexecDumpNum(op[0], fp[0]);
1622 eexecDumpNum(op[1], fp[1]);
1623 eexecDumpNum(op[2], fp[2]);
1624 eexecDumpNum(op[3], fp[3]);
1625 eexecDumpNum(op[4], fp[4]);
1626 eexecDumpNum(op[5], fp[5]);
1628 eexecDumpNum(op[6], fp[6]);
1629 eexecDumpNum(op[7], fp[7]);
1630 eexecDumpNum(op[8], fp[8]);
1631 eexecDumpNum(op[9], fp[9]);
1632 eexecDumpNum(op[10], fp[10]);
1633 eexecDumpNum(op[11], fp[11]);
1638 error(-1, "Wrong number of args (%d) to Type 2 hflex1", nOps);
1640 eexecDumpNum(op[0], fp[0]);
1641 eexecDumpNum(op[1], fp[1]);
1642 eexecDumpNum(op[2], fp[2]);
1643 eexecDumpNum(op[3], fp[3]);
1644 eexecDumpNum(op[4], fp[4]);
1645 eexecDumpNum(0, gFalse);
1647 eexecDumpNum(op[5], fp[5]);
1648 eexecDumpNum(0, gFalse);
1649 eexecDumpNum(op[6], fp[6]);
1650 eexecDumpNum(op[7], fp[7]);
1651 eexecDumpNum(op[8], fp[8]);
1652 eexecDumpNum(-(op[1] + op[3] + op[7]), fp[1] | fp[3] | fp[7]);
1657 error(-1, "Wrong number of args (%d) to Type 2 flex1", nOps);
1659 eexecDumpNum(op[0], fp[0]);
1660 eexecDumpNum(op[1], fp[1]);
1661 eexecDumpNum(op[2], fp[2]);
1662 eexecDumpNum(op[3], fp[3]);
1663 eexecDumpNum(op[4], fp[4]);
1664 eexecDumpNum(op[5], fp[5]);
1666 eexecDumpNum(op[6], fp[6]);
1667 eexecDumpNum(op[7], fp[7]);
1668 eexecDumpNum(op[8], fp[8]);
1669 eexecDumpNum(op[9], fp[9]);
1670 dx = op[0] + op[2] + op[4] + op[6] + op[8];
1671 dy = op[1] + op[3] + op[5] + op[7] + op[9];
1672 if (fabs(dx) > fabs(dy)) {
1673 eexecDumpNum(op[10], fp[10]);
1674 eexecDumpNum(-dy, fp[1] | fp[3] | fp[5] | fp[7] | fp[9]);
1676 eexecDumpNum(-dx, fp[0] | fp[2] | fp[4] | fp[6] | fp[8]);
1677 eexecDumpNum(op[10], fp[10]);
1703 error(-1, "Unimplemented Type 2 charstring op: 12.%d", file[i+1]);
1706 error(-1, "Illegal Type 2 charstring op: 12.%d", file[i+1]);
1711 } else if (file[i] == 19) { // hintmask
1714 cvtGlyphWidth(nOps == 1);
1719 error(-1, "Wrong number of args (%d) to Type 2 hintmask/vstemhm",
1724 i += 1 + ((nHints + 7) >> 3);
1726 } else if (file[i] == 20) { // cntrmask
1729 cvtGlyphWidth(nOps == 1);
1734 error(-1, "Wrong number of args (%d) to Type 2 cntrmask/vstemhm",
1739 i += 1 + ((nHints + 7) >> 3);
1741 } else if (file[i] == 28) {
1745 x = (file[i+1] << 8) + file[i+2];
1754 } else if (file[i] == 10) { // callsubr
1756 k = subrBias + (int)op[nOps - 1];
1758 if ((subrPos = getIndexValPos(subrIdxPos, k, &subrLen)) >= 0) {
1759 cvtGlyph(subrPos, subrLen, gFalse);
1762 error(-1, "Too few args to Type 2 callsubr");
1764 // don't clear the stack
1766 } else if (file[i] == 29) { // callgsubr
1768 k = gsubrBias + (int)op[nOps - 1];
1770 if ((subrPos = getIndexValPos(gsubrIdxPos, k, &subrLen)) >= 0) {
1771 cvtGlyph(subrPos, subrLen, gFalse);
1774 error(-1, "Too few args to Type 2 callgsubr");
1776 // don't clear the stack
1778 } else if (file[i] == 11) { // return
1779 // don't clear the stack
1781 } else if (file[i] <= 31) {
1785 cvtGlyphWidth(nOps == 2);
1789 error(-1, "Wrong number of args (%d) to Type 2 vmoveto", nOps);
1791 eexecDumpNum(op[0], fp[0]);
1795 if (nOps < 2 || nOps % 2 != 0) {
1796 error(-1, "Wrong number of args (%d) to Type 2 rlineto", nOps);
1798 for (k = 0; k < nOps; k += 2) {
1799 eexecDumpNum(op[k], fp[k]);
1800 eexecDumpNum(op[k+1], fp[k+1]);
1806 error(-1, "Wrong number of args (%d) to Type 2 hlineto", nOps);
1808 for (k = 0; k < nOps; ++k) {
1809 eexecDumpNum(op[k], fp[k]);
1810 eexecDumpOp1((k & 1) ? 7 : 6);
1815 error(-1, "Wrong number of args (%d) to Type 2 vlineto", nOps);
1817 for (k = 0; k < nOps; ++k) {
1818 eexecDumpNum(op[k], fp[k]);
1819 eexecDumpOp1((k & 1) ? 6 : 7);
1822 case 8: // rrcurveto
1823 if (nOps < 6 || nOps % 6 != 0) {
1824 error(-1, "Wrong number of args (%d) to Type 2 rrcurveto", nOps);
1826 for (k = 0; k < nOps; k += 6) {
1827 eexecDumpNum(op[k], fp[k]);
1828 eexecDumpNum(op[k+1], fp[k+1]);
1829 eexecDumpNum(op[k+2], fp[k+2]);
1830 eexecDumpNum(op[k+3], fp[k+3]);
1831 eexecDumpNum(op[k+4], fp[k+4]);
1832 eexecDumpNum(op[k+5], fp[k+5]);
1836 case 14: // endchar / seac
1838 cvtGlyphWidth(nOps == 1 || nOps == 5);
1843 eexecDumpNum(op[0], fp[0]);
1844 eexecDumpNum(op[1], fp[1]);
1845 eexecDumpNum(op[2], fp[2]);
1846 eexecDumpNum(op[3], fp[3]);
1848 } else if (nOps == 0) {
1851 error(-1, "Wrong number of args (%d) to Type 2 endchar", nOps);
1856 cvtGlyphWidth(nOps == 3);
1860 error(-1, "Wrong number of args (%d) to Type 2 rmoveto", nOps);
1862 eexecDumpNum(op[0], fp[0]);
1863 eexecDumpNum(op[1], fp[1]);
1868 cvtGlyphWidth(nOps == 2);
1872 error(-1, "Wrong number of args (%d) to Type 2 hmoveto", nOps);
1874 eexecDumpNum(op[0], fp[0]);
1877 case 24: // rcurveline
1878 if (nOps < 8 || (nOps - 2) % 6 != 0) {
1879 error(-1, "Wrong number of args (%d) to Type 2 rcurveline", nOps);
1881 for (k = 0; k < nOps - 2; k += 6) {
1882 eexecDumpNum(op[k], fp[k]);
1883 eexecDumpNum(op[k+1], fp[k+1]);
1884 eexecDumpNum(op[k+2], fp[k+2]);
1885 eexecDumpNum(op[k+3], fp[k+3]);
1886 eexecDumpNum(op[k+4], fp[k+4]);
1887 eexecDumpNum(op[k+5], fp[k+5]);
1890 eexecDumpNum(op[k], fp[k]);
1891 eexecDumpNum(op[k+1], fp[k]);
1894 case 25: // rlinecurve
1895 if (nOps < 8 || (nOps - 6) % 2 != 0) {
1896 error(-1, "Wrong number of args (%d) to Type 2 rlinecurve", nOps);
1898 for (k = 0; k < nOps - 6; k += 2) {
1899 eexecDumpNum(op[k], fp[k]);
1900 eexecDumpNum(op[k+1], fp[k]);
1903 eexecDumpNum(op[k], fp[k]);
1904 eexecDumpNum(op[k+1], fp[k+1]);
1905 eexecDumpNum(op[k+2], fp[k+2]);
1906 eexecDumpNum(op[k+3], fp[k+3]);
1907 eexecDumpNum(op[k+4], fp[k+4]);
1908 eexecDumpNum(op[k+5], fp[k+5]);
1911 case 26: // vvcurveto
1912 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
1913 error(-1, "Wrong number of args (%d) to Type 2 vvcurveto", nOps);
1915 if (nOps % 2 == 1) {
1916 eexecDumpNum(op[0], fp[0]);
1917 eexecDumpNum(op[1], fp[1]);
1918 eexecDumpNum(op[2], fp[2]);
1919 eexecDumpNum(op[3], fp[3]);
1920 eexecDumpNum(0, gFalse);
1921 eexecDumpNum(op[4], fp[4]);
1927 for (; k < nOps; k += 4) {
1928 eexecDumpNum(0, gFalse);
1929 eexecDumpNum(op[k], fp[k]);
1930 eexecDumpNum(op[k+1], fp[k+1]);
1931 eexecDumpNum(op[k+2], fp[k+2]);
1932 eexecDumpNum(0, gFalse);
1933 eexecDumpNum(op[k+3], fp[k+3]);
1937 case 27: // hhcurveto
1938 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
1939 error(-1, "Wrong number of args (%d) to Type 2 hhcurveto", nOps);
1941 if (nOps % 2 == 1) {
1942 eexecDumpNum(op[1], fp[1]);
1943 eexecDumpNum(op[0], fp[0]);
1944 eexecDumpNum(op[2], fp[2]);
1945 eexecDumpNum(op[3], fp[3]);
1946 eexecDumpNum(op[4], fp[4]);
1947 eexecDumpNum(0, gFalse);
1953 for (; k < nOps; k += 4) {
1954 eexecDumpNum(op[k], fp[k]);
1955 eexecDumpNum(0, gFalse);
1956 eexecDumpNum(op[k+1], fp[k+1]);
1957 eexecDumpNum(op[k+2], fp[k+2]);
1958 eexecDumpNum(op[k+3], fp[k+3]);
1959 eexecDumpNum(0, gFalse);
1963 case 30: // vhcurveto
1964 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
1965 error(-1, "Wrong number of args (%d) to Type 2 vhcurveto", nOps);
1967 for (k = 0; k < nOps && k != nOps-5; k += 4) {
1969 eexecDumpNum(op[k], fp[k]);
1970 eexecDumpNum(op[k+1], fp[k+1]);
1971 eexecDumpNum(op[k+2], fp[k+2]);
1972 eexecDumpNum(op[k+3], fp[k+3]);
1975 eexecDumpNum(op[k], fp[k]);
1976 eexecDumpNum(op[k+1], fp[k+1]);
1977 eexecDumpNum(op[k+2], fp[k+2]);
1978 eexecDumpNum(op[k+3], fp[k+3]);
1984 eexecDumpNum(0, gFalse);
1985 eexecDumpNum(op[k], fp[k]);
1986 eexecDumpNum(op[k+1], fp[k+1]);
1987 eexecDumpNum(op[k+2], fp[k+2]);
1988 eexecDumpNum(op[k+3], fp[k+3]);
1989 eexecDumpNum(op[k+4], fp[k+4]);
1991 eexecDumpNum(op[k], fp[k]);
1992 eexecDumpNum(0, gFalse);
1993 eexecDumpNum(op[k+1], fp[k+1]);
1994 eexecDumpNum(op[k+2], fp[k+2]);
1995 eexecDumpNum(op[k+4], fp[k+4]);
1996 eexecDumpNum(op[k+3], fp[k+3]);
2001 case 31: // hvcurveto
2002 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
2003 error(-1, "Wrong number of args (%d) to Type 2 hvcurveto", nOps);
2005 for (k = 0; k < nOps && k != nOps-5; k += 4) {
2007 eexecDumpNum(op[k], fp[k]);
2008 eexecDumpNum(op[k+1], fp[k+1]);
2009 eexecDumpNum(op[k+2], fp[k+2]);
2010 eexecDumpNum(op[k+3], fp[k+3]);
2013 eexecDumpNum(op[k], fp[k]);
2014 eexecDumpNum(op[k+1], fp[k+1]);
2015 eexecDumpNum(op[k+2], fp[k+2]);
2016 eexecDumpNum(op[k+3], fp[k+3]);
2022 eexecDumpNum(op[k], fp[k]);
2023 eexecDumpNum(0, gFalse);
2024 eexecDumpNum(op[k+1], fp[k+1]);
2025 eexecDumpNum(op[k+2], fp[k+2]);
2026 eexecDumpNum(op[k+4], fp[k+4]);
2027 eexecDumpNum(op[k+3], fp[k+3]);
2029 eexecDumpNum(0, gFalse);
2030 eexecDumpNum(op[k], fp[k]);
2031 eexecDumpNum(op[k+1], fp[k+1]);
2032 eexecDumpNum(op[k+2], fp[k+2]);
2033 eexecDumpNum(op[k+3], fp[k+3]);
2034 eexecDumpNum(op[k+4], fp[k+4]);
2041 cvtGlyphWidth(nOps & 1);
2045 error(-1, "Wrong number of args (%d) to Type 2 hstem", nOps);
2049 for (k = 0; k < nOps; k += 2) {
2051 d += op[k] + op[k+1];
2052 dFP |= fp[k] | fp[k+1];
2053 eexecDumpNum(d, dFP);
2054 eexecDumpNum(-op[k+1], fp[k+1]);
2058 eexecDumpNum(d, dFP);
2059 eexecDumpNum(op[k+1], fp[k+1]);
2069 cvtGlyphWidth(nOps & 1);
2073 error(-1, "Wrong number of args (%d) to Type 2 vstem", nOps);
2077 for (k = 0; k < nOps; k += 2) {
2079 d += op[k] + op[k+1];
2080 dFP |= fp[k] | fp[k+1];
2081 eexecDumpNum(d, dFP);
2082 eexecDumpNum(-op[k+1], fp[k+1]);
2086 eexecDumpNum(d, dFP);
2087 eexecDumpNum(op[k+1], fp[k+1]);
2098 cvtGlyphWidth(nOps & 1);
2102 error(-1, "Wrong number of args (%d) to Type 2 hstemhm", nOps);
2109 cvtGlyphWidth(nOps & 1);
2113 error(-1, "Wrong number of args (%d) to Type 2 vstemhm", nOps);
2118 error(-1, "Unimplemented Type 2 charstring op: %d", file[i]);
2121 error(-1, "Illegal Type 2 charstring op: %d", file[i]);
2126 } else if (file[i] <= 246) {
2129 op[nOps++] = (int)file[i] - 139;
2132 } else if (file[i] <= 250) {
2138 op[nOps++] = (((int)file[i] - 247) << 8) + (int)file[i+1] + 108;
2141 } else if (file[i] <= 254) {
2147 op[nOps++] = -(((int)file[i] - 251) << 8) - (int)file[i+1] - 108;
2154 x = (file[i+1] << 24) | (file[i+2] << 16) | (file[i+3] << 8) | file[i+4];
2155 if (x & 0x80000000) {
2160 op[nOps++] = (double)x / 65536.0;
2166 // charstring encryption
2169 for (i = 0; i < charBuf->getLength(); ++i) {
2170 byte = charBuf->getChar(i) ^ (r2 >> 8);
2171 charBuf->setChar(i, byte);
2172 r2 = (byte + r2) * 52845 + 22719;
2177 void Type1CFontFile::cvtGlyphWidth(GBool useOp) {
2183 w = nominalWidthX + op[0];
2184 wFP = nominalWidthXFP | fp[0];
2185 for (i = 1; i < nOps; ++i) {
2192 wFP = defaultWidthXFP;
2194 eexecDumpNum(0, gFalse);
2195 eexecDumpNum(w, wFP);
2199 void Type1CFontFile::eexecDumpNum(double x, GBool fpA) {
2205 if (x >= -32768 && x < 32768) {
2206 y = (int)(x * 256.0);
2208 buf[1] = (Guchar)(y >> 24);
2209 buf[2] = (Guchar)(y >> 16);
2210 buf[3] = (Guchar)(y >> 8);
2221 error(-1, "Type 2 fixed point constant out of range");
2225 if (y >= -107 && y <= 107) {
2226 buf[0] = (Guchar)(y + 139);
2228 } else if (y > 107 && y <= 1131) {
2230 buf[0] = (Guchar)((y >> 8) + 247);
2231 buf[1] = (Guchar)(y & 0xff);
2233 } else if (y < -107 && y >= -1131) {
2235 buf[0] = (Guchar)((y >> 8) + 251);
2236 buf[1] = (Guchar)(y & 0xff);
2240 buf[1] = (Guchar)(y >> 24);
2241 buf[2] = (Guchar)(y >> 16);
2242 buf[3] = (Guchar)(y >> 8);
2247 charBuf->append((char *)buf, n);
2250 void Type1CFontFile::eexecDumpOp1(int opA) {
2251 charBuf->append((char)opA);
2254 void Type1CFontFile::eexecDumpOp2(int opA) {
2255 charBuf->append((char)12);
2256 charBuf->append((char)opA);
2259 void Type1CFontFile::eexecWriteCharstring(Guchar *s, int n) {
2264 for (i = 0; i < n; ++i) {
2265 x = s[i] ^ (r1 >> 8);
2266 r1 = (x + r1) * 52845 + 22719;
2267 (*outputFunc)(outputStream, &hexChars[x >> 4], 1);
2268 (*outputFunc)(outputStream, &hexChars[x & 0x0f], 1);
2271 (*outputFunc)(outputStream, "\n", 1);
2277 void Type1CFontFile::getDeltaInt(char *buf, char *key, double *opA,
2281 sprintf(buf, "/%s [", key);
2284 for (i = 0; i < n; ++i) {
2286 sprintf(buf, "%s%d", i > 0 ? " " : "", x);
2289 sprintf(buf, "] def\n");
2292 void Type1CFontFile::getDeltaReal(char *buf, char *key, double *opA,
2297 sprintf(buf, "/%s [", key);
2300 for (i = 0; i < n; ++i) {
2302 sprintf(buf, "%s%g", i > 0 ? " " : "", x);
2305 sprintf(buf, "] def\n");
2308 int Type1CFontFile::getIndexLen(int indexPos) {
2309 if (indexPos + 2 > len) {
2312 return (int)getWord(indexPos, 2);
2315 int Type1CFontFile::getIndexValPos(int indexPos, int i, int *valLen) {
2316 int n, offSize, idxStartPos;
2319 if (indexPos < 0 || indexPos + 3 > len) {
2322 n = (int)getWord(indexPos, 2);
2326 offSize = file[indexPos + 2];
2327 if (offSize < 1 || offSize > 4) {
2330 idxStartPos = indexPos + 3 + (n + 1) * offSize - 1;
2331 if (idxStartPos >= len) {
2334 pos0 = idxStartPos + getWord(indexPos + 3 + i * offSize, offSize);
2335 pos1 = idxStartPos + getWord(indexPos + 3 + (i + 1) * offSize, offSize);
2336 if (pos0 < 0 || pos0 >= len || pos1 < pos0 || pos1 > len) {
2339 *valLen = pos1 - pos0;
2343 int Type1CFontFile::getIndexEnd(int indexPos) {
2344 int n, offSize, idxStartPos;
2346 if (indexPos + 3 > len) {
2349 n = (int)getWord(indexPos, 2);
2350 offSize = file[indexPos + 2];
2351 idxStartPos = indexPos + 3 + (n + 1) * offSize - 1;
2352 if (idxStartPos >= len) {
2355 return idxStartPos + getWord(indexPos + 3 + n * offSize, offSize);
2358 Guint Type1CFontFile::getWord(int pos, int size) {
2362 if (pos < 0 || pos + size > len) {
2366 for (i = 0; i < size; ++i) {
2367 x = (x << 8) + file[pos + i];
2372 double Type1CFontFile::getNum(int *pos, GBool *isFP) {
2373 static char nybChars[16] = "0123456789.ee -";
2374 int b0, b, nyb0, nyb1;
2387 } else if (b0 == 28) {
2388 if (*pos + 3 <= len) {
2389 x = (file[*pos + 1] << 8) + file[*pos + 2];
2392 } else if (b0 == 29) {
2393 if (*pos + 5 <= len) {
2394 x = (file[*pos + 1] << 24) + (file[*pos + 2] << 16) +
2395 (file[*pos + 3] << 8) + file[*pos + 4];
2398 } else if (b0 == 30) {
2411 buf[i++] = nybChars[nyb0];
2424 buf[i++] = nybChars[nyb1];
2434 char *theLocale = setlocale(LC_NUMERIC, "C");
2436 setlocale(LC_NUMERIC, theLocale);
2439 } else if (b0 == 31) {
2441 } else if (b0 < 247) {
2444 } else if (b0 < 251) {
2445 if (*pos + 2 <= len) {
2446 x = ((b0 - 247) << 8) + file[*pos + 1] + 108;
2450 if (*pos + 2 <= len) {
2451 x = -((b0 - 251) << 8) - file[*pos + 1] - 108;
2458 char *Type1CFontFile::getString(int sid, char *buf) {
2462 strcpy(buf, type1CStdStrings[sid]);
2465 idxPos = getIndexValPos(stringIdxPos, sid, &n);
2466 if (idxPos < 0 || n < 0 || n > 255 || idxPos + n > len) {
2469 strncpy(buf, (char *)&file[idxPos], n);
2476 //------------------------------------------------------------------------
2478 //------------------------------------------------------------------------
2484 // character code = number used as an element of a text string
2486 // character name = glyph name = name for a particular glyph within a
2489 // glyph index = position (within some internal table in the font)
2490 // where the instructions to draw a particular glyph are
2496 // Type 1 fonts contain:
2498 // Encoding: array of glyph names, maps char codes to glyph names
2500 // Encoding[charCode] = charName
2502 // CharStrings: dictionary of instructions, keyed by character names,
2503 // maps character name to glyph data
2505 // CharStrings[charName] = glyphData
2510 // TrueType fonts contain:
2512 // 'cmap' table: mapping from character code to glyph index; there may
2513 // be multiple cmaps in a TrueType font
2515 // cmap[charCode] = glyphIdx
2517 // 'post' table: mapping from glyph index to glyph name
2519 // post[glyphIdx] = glyphName
2524 // Type 42 fonts contain:
2526 // Encoding: array of glyph names, maps char codes to glyph names
2528 // Encoding[charCode] = charName
2530 // CharStrings: dictionary of glyph indexes, keyed by character names,
2531 // maps character name to glyph index
2533 // CharStrings[charName] = glyphIdx
2536 struct TTFontTableHdr {
2544 char *tag; // 4-byte tag
2545 GBool required; // required by the TrueType spec?
2548 // TrueType tables to be embedded in Type 42 fonts.
2549 // NB: the table names must be in alphabetical order here.
2550 #define nT42Tables 11
2551 static T42Table t42Tables[nT42Tables] = {
2564 #define t42HeadTable 3
2565 #define t42LocaTable 6
2566 #define t42GlyfTable 2
2568 // Glyph names in some arbitrary standard that Apple uses for their
2570 static char *macGlyphNames[258] = {
2831 enum T42FontIndexMode {
2833 t42FontModeCharCode,
2834 t42FontModeCharCodeOffset,
2838 struct TrueTypeLoca {
2844 TrueTypeFontFile::TrueTypeFontFile(char *fileA, int lenA) {
2845 int pos, i, idx, n, length;
2846 Guint size, startPos, endPos;
2853 // read table directory
2854 nTables = getUShort(4);
2855 tableHdrs = (TTFontTableHdr *)gmalloc(nTables * sizeof(TTFontTableHdr));
2857 for (i = 0; i < nTables; ++i) {
2858 tableHdrs[i].tag[0] = getByte(pos+0);
2859 tableHdrs[i].tag[1] = getByte(pos+1);
2860 tableHdrs[i].tag[2] = getByte(pos+2);
2861 tableHdrs[i].tag[3] = getByte(pos+3);
2862 tableHdrs[i].checksum = getULong(pos+4);
2863 tableHdrs[i].offset = getULong(pos+8);
2864 tableHdrs[i].length = getULong(pos+12);
2865 if (tableHdrs[i].offset + tableHdrs[i].length < tableHdrs[i].offset ||
2866 tableHdrs[i].offset + tableHdrs[i].length > (Guint)len) {
2867 tableHdrs[i].offset = (Guint)-1;
2872 // check for tables that are required by both the TrueType spec
2873 // and the Type 42 spec
2874 if (seekTable("head") < 0 ||
2875 seekTable("hhea") < 0 ||
2876 seekTable("loca") < 0 ||
2877 seekTable("maxp") < 0 ||
2878 seekTable("glyf") < 0 ||
2879 seekTable("hmtx") < 0) {
2880 error(-1, "TrueType font file is missing a required table");
2884 // some embedded TrueType fonts have an incorrect (too small) cmap
2886 idx = seekTableIdx("cmap");
2888 pos = tableHdrs[idx].offset;
2889 n = getUShort(pos + 2);
2890 size = (Guint)(4 + 8 * n);
2891 for (i = 0; i < n; ++i) {
2892 startPos = getULong(pos + 4 + 8*i + 4);
2893 length = getUShort(pos + startPos + 2);
2894 endPos = startPos + length;
2895 if (endPos > size) {
2899 if ((mungedCmapSize = size > tableHdrs[idx].length)) {
2900 #if 0 // don't bother printing this error message - it's too common
2901 error(-1, "Bad cmap table size in TrueType font");
2903 tableHdrs[idx].length = size;
2906 mungedCmapSize = gFalse;
2909 // read the 'head' table
2910 pos = seekTable("head");
2911 bbox[0] = getShort(pos + 36);
2912 bbox[1] = getShort(pos + 38);
2913 bbox[2] = getShort(pos + 40);
2914 bbox[3] = getShort(pos + 42);
2915 locaFmt = getShort(pos + 50);
2917 // read the 'maxp' table
2918 pos = seekTable("maxp");
2919 nGlyphs = getUShort(pos + 4);
2922 TrueTypeFontFile::~TrueTypeFontFile() {
2926 for (i = 0; i < 256; ++i) {
2934 char *TrueTypeFontFile::getName() {
2938 char **TrueTypeFontFile::getEncoding() {
2940 int nCmaps, cmapPlatform, cmapEncoding, cmapFmt;
2944 int stringIdx, stringPos, n;
2950 //----- construct the (char code) -> (glyph idx) mapping
2952 // map everything to the missing glyph
2953 for (i = 0; i < 256; ++i) {
2957 // look for the 'cmap' table
2958 if ((pos = seekTable("cmap")) >= 0) {
2959 nCmaps = getUShort(pos+2);
2961 // if the font has a Windows-symbol cmap, use it;
2962 // otherwise, use the first cmap in the table
2963 cmapPlatform = 0; // make gcc happy
2964 cmapEncoding = 0; // make gcc happy
2965 for (i = 0; i < nCmaps; ++i) {
2966 cmapPlatform = getUShort(pos + 4 + 8*i);
2967 cmapEncoding = getUShort(pos + 4 + 8*i + 2);
2968 if (cmapPlatform == 3 && cmapEncoding == 0) {
2974 cmapPlatform = getUShort(pos + 4);
2975 cmapEncoding = getUShort(pos + 4 + 2);
2977 pos += getULong(pos + 4 + 8*i + 4);
2980 cmapFmt = getUShort(pos);
2981 for (i = 0; i < 256; ++i) {
2982 cmap[i] = getCmapEntry(cmapFmt, pos, i);
2984 // Windows-symbol sometimes uses char codes 0xf000 - 0xf0ff, so
2985 // we use these to override 0x0000 - 0x00ff
2986 if (cmapPlatform == 3 && cmapEncoding == 0) {
2987 for (i = 0; i < 256; ++i) {
2988 if ((j = getCmapEntry(cmapFmt, pos, 0xf000 + i)) != 0) {
2995 //----- construct the (glyph idx) -> (glyph name) mapping
2996 //----- and compute the (char code) -> (glyph name) mapping
2998 encoding = (char **)gmalloc(256 * sizeof(char *));
2999 for (i = 0; i < 256; ++i) {
3003 if ((pos = seekTable("post")) >= 0) {
3004 fmt = getULong(pos);
3007 if (fmt == 0x00010000) {
3008 for (i = 0; i < 256; ++i) {
3009 j = (cmap[i] < 258) ? cmap[i] : 0;
3010 encoding[i] = copyString(macGlyphNames[j]);
3014 } else if (fmt == 0x00020000) {
3016 stringPos = pos + 34 + 2*nGlyphs;
3017 for (i = 0; i < 256; ++i) {
3018 if (cmap[i] < nGlyphs) {
3019 j = getUShort(pos + 34 + 2 * cmap[i]);
3021 encoding[i] = copyString(macGlyphNames[j]);
3024 if (j != stringIdx) {
3025 for (stringIdx = 0, stringPos = pos + 34 + 2*nGlyphs;
3027 ++stringIdx, stringPos += 1 + getByte(stringPos)) ;
3029 n = getByte(stringPos);
3030 if (stringPos >= 0 && stringPos + 1 + n <= len) {
3031 s = new GString(file + stringPos + 1, n);
3032 encoding[i] = copyString(s->getCString());
3035 encoding[i] = copyString(macGlyphNames[0]);
3041 encoding[i] = copyString(macGlyphNames[0]);
3046 } else if (fmt == 0x000280000) {
3047 for (i = 0; i < 256; ++i) {
3048 if (cmap[i] < nGlyphs) {
3049 j = i + getChar(pos + 32 + cmap[i]);
3053 encoding[i] = copyString(macGlyphNames[j]);
3056 // Ugh, just assume the Apple glyph set
3058 for (i = 0; i < 256; ++i) {
3059 j = (cmap[i] < 258) ? cmap[i] : 0;
3060 encoding[i] = copyString(macGlyphNames[j]);
3064 // no "post" table: assume the Apple glyph set
3066 for (i = 0; i < 256; ++i) {
3067 j = (cmap[i] < 258) ? cmap[i] : 0;
3068 encoding[i] = copyString(macGlyphNames[j]);
3075 void TrueTypeFontFile::convertToType42(char *name, char **encodingA,
3076 CharCodeToUnicode *toUnicode,
3077 GBool pdfFontHasEncoding,
3078 GBool pdfFontIsSymbolic,
3079 FontFileOutputFunc outputFunc,
3080 void *outputStream) {
3084 sprintf(buf, "%%!PS-TrueTypeFont-%g\n", getFixed(0));
3085 (*outputFunc)(outputStream, buf, strlen(buf));
3087 // begin the font dictionary
3088 (*outputFunc)(outputStream, "10 dict begin\n", 14);
3089 (*outputFunc)(outputStream, "/FontName /", 11);
3090 (*outputFunc)(outputStream, name, strlen(name));
3091 (*outputFunc)(outputStream, " def\n", 5);
3092 (*outputFunc)(outputStream, "/FontType 42 def\n", 17);
3093 (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
3094 sprintf(buf, "/FontBBox [%d %d %d %d] def\n",
3095 bbox[0], bbox[1], bbox[2], bbox[3]);
3096 (*outputFunc)(outputStream, buf, strlen(buf));
3097 (*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
3099 // write the guts of the dictionary
3100 cvtEncoding(encodingA, pdfFontHasEncoding, outputFunc, outputStream);
3101 cvtCharStrings(encodingA, toUnicode, pdfFontHasEncoding, pdfFontIsSymbolic,
3102 outputFunc, outputStream);
3103 cvtSfnts(outputFunc, outputStream, NULL);
3105 // end the dictionary and define the font
3106 (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
3109 void TrueTypeFontFile::convertToCIDType2(char *name, Gushort *cidMap,
3111 FontFileOutputFunc outputFunc,
3112 void *outputStream) {
3118 sprintf(buf, "%%!PS-TrueTypeFont-%g\n", getFixed(0));
3119 (*outputFunc)(outputStream, buf, strlen(buf));
3121 // begin the font dictionary
3122 (*outputFunc)(outputStream, "20 dict begin\n", 14);
3123 (*outputFunc)(outputStream, "/CIDFontName /", 14);
3124 (*outputFunc)(outputStream, name, strlen(name));
3125 (*outputFunc)(outputStream, " def\n", 5);
3126 (*outputFunc)(outputStream, "/CIDFontType 2 def\n", 19);
3127 (*outputFunc)(outputStream, "/FontType 42 def\n", 17);
3128 (*outputFunc)(outputStream, "/CIDSystemInfo 3 dict dup begin\n", 32);
3129 (*outputFunc)(outputStream, " /Registry (Adobe) def\n", 24);
3130 (*outputFunc)(outputStream, " /Ordering (Identity) def\n", 27);
3131 (*outputFunc)(outputStream, " /Supplement 0 def\n", 20);
3132 (*outputFunc)(outputStream, " end def\n", 10);
3133 (*outputFunc)(outputStream, "/GDBytes 2 def\n", 15);
3135 sprintf(buf, "/CIDCount %d def\n", nCIDs);
3136 (*outputFunc)(outputStream, buf, strlen(buf));
3137 if (nCIDs > 32767) {
3138 (*outputFunc)(outputStream, "/CIDMap [", 9);
3139 for (i = 0; i < nCIDs; i += 32768 - 16) {
3140 (*outputFunc)(outputStream, "<\n", 2);
3141 for (j = 0; j < 32768 - 16 && i+j < nCIDs; j += 16) {
3142 (*outputFunc)(outputStream, " ", 2);
3143 for (k = 0; k < 16 && i+j+k < nCIDs; ++k) {
3144 cid = cidMap[i+j+k];
3145 sprintf(buf, "%02x%02x", (cid >> 8) & 0xff, cid & 0xff);
3146 (*outputFunc)(outputStream, buf, strlen(buf));
3148 (*outputFunc)(outputStream, "\n", 1);
3150 (*outputFunc)(outputStream, " >", 3);
3152 (*outputFunc)(outputStream, "\n", 1);
3153 (*outputFunc)(outputStream, "] def\n", 6);
3155 (*outputFunc)(outputStream, "/CIDMap <\n", 10);
3156 for (i = 0; i < nCIDs; i += 16) {
3157 (*outputFunc)(outputStream, " ", 2);
3158 for (j = 0; j < 16 && i+j < nCIDs; ++j) {
3160 sprintf(buf, "%02x%02x", (cid >> 8) & 0xff, cid & 0xff);
3161 (*outputFunc)(outputStream, buf, strlen(buf));
3163 (*outputFunc)(outputStream, "\n", 1);
3165 (*outputFunc)(outputStream, "> def\n", 6);
3168 // direct mapping - just fill the string(s) with s[i]=i
3169 sprintf(buf, "/CIDCount %d def\n", nGlyphs);
3170 (*outputFunc)(outputStream, buf, strlen(buf));
3171 if (nGlyphs > 32767) {
3172 (*outputFunc)(outputStream, "/CIDMap [\n", 10);
3173 for (i = 0; i < nGlyphs; i += 32767) {
3174 j = nGlyphs - i < 32767 ? nGlyphs - i : 32767;
3175 sprintf(buf, " %d string 0 1 %d {\n", 2 * j, j - 1);
3176 (*outputFunc)(outputStream, buf, strlen(buf));
3177 sprintf(buf, " 2 copy dup 2 mul exch %d add -8 bitshift put\n", i);
3178 (*outputFunc)(outputStream, buf, strlen(buf));
3179 sprintf(buf, " 1 index exch dup 2 mul 1 add exch %d add"
3180 " 255 and put\n", i);
3181 (*outputFunc)(outputStream, buf, strlen(buf));
3182 (*outputFunc)(outputStream, " } for\n", 8);
3184 (*outputFunc)(outputStream, "] def\n", 6);
3186 sprintf(buf, "/CIDMap %d string\n", 2 * nGlyphs);
3187 (*outputFunc)(outputStream, buf, strlen(buf));
3188 sprintf(buf, " 0 1 %d {\n", nGlyphs - 1);
3189 (*outputFunc)(outputStream, buf, strlen(buf));
3190 (*outputFunc)(outputStream,
3191 " 2 copy dup 2 mul exch -8 bitshift put\n", 42);
3192 (*outputFunc)(outputStream,
3193 " 1 index exch dup 2 mul 1 add exch 255 and put\n", 50);
3194 (*outputFunc)(outputStream, " } for\n", 8);
3195 (*outputFunc)(outputStream, "def\n", 4);
3198 (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
3199 sprintf(buf, "/FontBBox [%d %d %d %d] def\n",
3200 bbox[0], bbox[1], bbox[2], bbox[3]);
3201 (*outputFunc)(outputStream, buf, strlen(buf));
3202 (*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
3203 (*outputFunc)(outputStream, "/Encoding [] readonly def\n", 26);
3204 (*outputFunc)(outputStream, "/CharStrings 1 dict dup begin\n", 30);
3205 (*outputFunc)(outputStream, " /.notdef 0 def\n", 17);
3206 (*outputFunc)(outputStream, " end readonly def\n", 19);
3208 // write the guts of the dictionary
3209 cvtSfnts(outputFunc, outputStream, NULL);
3211 // end the dictionary and define the font
3212 (*outputFunc)(outputStream,
3213 "CIDFontName currentdict end /CIDFont defineresource pop\n",
3217 void TrueTypeFontFile::convertToType0(char *name, Gushort *cidMap,
3219 FontFileOutputFunc outputFunc,
3220 void *outputStream) {
3225 // write the Type 42 sfnts array
3226 sfntsName = (new GString(name))->append("_sfnts");
3227 cvtSfnts(outputFunc, outputStream, sfntsName);
3230 // write the descendant Type 42 fonts
3231 n = cidMap ? nCIDs : nGlyphs;
3232 for (i = 0; i < n; i += 256) {
3233 (*outputFunc)(outputStream, "10 dict begin\n", 14);
3234 (*outputFunc)(outputStream, "/FontName /", 11);
3235 (*outputFunc)(outputStream, name, strlen(name));
3236 sprintf(buf, "_%02x def\n", i >> 8);
3237 (*outputFunc)(outputStream, buf, strlen(buf));
3238 (*outputFunc)(outputStream, "/FontType 42 def\n", 17);
3239 (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
3240 sprintf(buf, "/FontBBox [%d %d %d %d] def\n",
3241 bbox[0], bbox[1], bbox[2], bbox[3]);
3242 (*outputFunc)(outputStream, buf, strlen(buf));
3243 (*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
3244 (*outputFunc)(outputStream, "/sfnts ", 7);
3245 (*outputFunc)(outputStream, name, strlen(name));
3246 (*outputFunc)(outputStream, "_sfnts def\n", 11);
3247 (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
3248 for (j = 0; j < 256 && i+j < n; ++j) {
3249 sprintf(buf, "dup %d /c%02x put\n", j, j);
3250 (*outputFunc)(outputStream, buf, strlen(buf));
3252 (*outputFunc)(outputStream, "readonly def\n", 13);
3253 (*outputFunc)(outputStream, "/CharStrings 257 dict dup begin\n", 32);
3254 (*outputFunc)(outputStream, "/.notdef 0 def\n", 15);
3255 for (j = 0; j < 256 && i+j < n; ++j) {
3256 sprintf(buf, "/c%02x %d def\n", j, cidMap ? cidMap[i+j] : i+j);
3257 (*outputFunc)(outputStream, buf, strlen(buf));
3259 (*outputFunc)(outputStream, "end readonly def\n", 17);
3260 (*outputFunc)(outputStream,
3261 "FontName currentdict end definefont pop\n", 40);
3264 // write the Type 0 parent font
3265 (*outputFunc)(outputStream, "16 dict begin\n", 14);
3266 (*outputFunc)(outputStream, "/FontName /", 11);
3267 (*outputFunc)(outputStream, name, strlen(name));
3268 (*outputFunc)(outputStream, " def\n", 5);
3269 (*outputFunc)(outputStream, "/FontType 0 def\n", 16);
3270 (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
3271 (*outputFunc)(outputStream, "/FMapType 2 def\n", 16);
3272 (*outputFunc)(outputStream, "/Encoding [\n", 12);
3273 for (i = 0; i < n; i += 256) {
3274 sprintf(buf, "%d\n", i >> 8);
3275 (*outputFunc)(outputStream, buf, strlen(buf));
3277 (*outputFunc)(outputStream, "] def\n", 6);
3278 (*outputFunc)(outputStream, "/FDepVector [\n", 14);
3279 for (i = 0; i < n; i += 256) {
3280 (*outputFunc)(outputStream, "/", 1);
3281 (*outputFunc)(outputStream, name, strlen(name));
3282 sprintf(buf, "_%02x findfont\n", i >> 8);
3283 (*outputFunc)(outputStream, buf, strlen(buf));
3285 (*outputFunc)(outputStream, "] def\n", 6);
3286 (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
3289 int TrueTypeFontFile::getByte(int pos) {
3290 if (pos < 0 || pos >= len) {
3293 return file[pos] & 0xff;
3296 int TrueTypeFontFile::getChar(int pos) {
3299 if (pos < 0 || pos >= len) {
3302 x = file[pos] & 0xff;
3308 int TrueTypeFontFile::getUShort(int pos) {
3311 if (pos < 0 || pos+1 >= len) {
3314 x = file[pos] & 0xff;
3315 x = (x << 8) + (file[pos+1] & 0xff);
3319 int TrueTypeFontFile::getShort(int pos) {
3322 if (pos < 0 || pos+1 >= len) {
3325 x = file[pos] & 0xff;
3326 x = (x << 8) + (file[pos+1] & 0xff);
3332 Guint TrueTypeFontFile::getULong(int pos) {
3335 if (pos < 0 || pos+3 >= len) {
3338 x = file[pos] & 0xff;
3339 x = (x << 8) + (file[pos+1] & 0xff);
3340 x = (x << 8) + (file[pos+2] & 0xff);
3341 x = (x << 8) + (file[pos+3] & 0xff);
3345 double TrueTypeFontFile::getFixed(int pos) {
3349 y = getUShort(pos+2);
3350 return (double)x + (double)y / 65536;
3353 int TrueTypeFontFile::seekTable(char *tag) {
3356 for (i = 0; i < nTables; ++i) {
3357 if (!strncmp(tableHdrs[i].tag, tag, 4)) {
3358 return (int)tableHdrs[i].offset;
3364 int TrueTypeFontFile::seekTableIdx(char *tag) {
3367 for (i = 0; i < nTables; ++i) {
3368 if (!strncmp(tableHdrs[i].tag, tag, 4)) {
3369 if (tableHdrs[i].offset == (Guint)-1) {
3378 void TrueTypeFontFile::cvtEncoding(char **encodingA, GBool pdfFontHasEncoding,
3379 FontFileOutputFunc outputFunc,
3380 void *outputStream) {
3385 (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
3386 if (pdfFontHasEncoding) {
3387 for (i = 0; i < 256; ++i) {
3388 if (!(name = encodingA[i])) {
3391 sprintf(buf, "dup %d /", i);
3392 (*outputFunc)(outputStream, buf, strlen(buf));
3393 (*outputFunc)(outputStream, name, strlen(name));
3394 (*outputFunc)(outputStream, " put\n", 5);
3397 for (i = 0; i < 256; ++i) {
3398 sprintf(buf, "dup %d /c%02x put\n", i, i);
3399 (*outputFunc)(outputStream, buf, strlen(buf));
3402 (*outputFunc)(outputStream, "readonly def\n", 13);
3405 void TrueTypeFontFile::cvtCharStrings(char **encodingA,
3406 CharCodeToUnicode *toUnicode,
3407 GBool pdfFontHasEncoding,
3408 GBool pdfFontIsSymbolic,
3409 FontFileOutputFunc outputFunc,
3410 void *outputStream) {
3411 int unicodeCmap, macRomanCmap, msSymbolCmap;
3412 int nCmaps, cmapPlatform, cmapEncoding, cmapFmt, cmapOffset;
3413 T42FontIndexMode mode;
3415 char buf[64], buf2[16];
3419 // always define '.notdef'
3420 (*outputFunc)(outputStream, "/CharStrings 256 dict dup begin\n", 32);
3421 (*outputFunc)(outputStream, "/.notdef 0 def\n", 15);
3423 // if there's no 'cmap' table, punt
3424 if ((pos = seekTable("cmap")) < 0) {
3428 // To match up with the Adobe-defined behaviour, we choose a cmap
3430 // 1. If the PDF font has an encoding:
3431 // 1a. If the TrueType font has a Microsoft Unicode cmap, use it,
3432 // and use the Unicode indexes, not the char codes.
3433 // 1b. If the PDF font is symbolic and the TrueType font has a
3434 // Microsoft Symbol cmap, use it, and use (0xf000 + char code).
3435 // 1c. If the TrueType font has a Macintosh Roman cmap, use it,
3436 // and reverse map the char names through MacRomanEncoding to
3438 // 2. If the PDF font does not have an encoding:
3439 // 2a. If the TrueType font has a Macintosh Roman cmap, use it,
3440 // and use char codes directly.
3441 // 2b. If the TrueType font has a Microsoft Symbol cmap, use it,
3442 // and use (0xf000 + char code).
3443 // 3. If none of these rules apply, use the first cmap and hope for
3444 // the best (this shouldn't happen).
3445 nCmaps = getUShort(pos+2);
3446 unicodeCmap = macRomanCmap = msSymbolCmap = -1;
3448 for (i = 0; i < nCmaps; ++i) {
3449 cmapPlatform = getUShort(pos + 4 + 8*i);
3450 cmapEncoding = getUShort(pos + 4 + 8*i + 2);
3451 if ((cmapPlatform == 3 && cmapEncoding == 1) || cmapPlatform == 0) {
3453 } else if (cmapPlatform == 1 && cmapEncoding == 0) {
3455 } else if (cmapPlatform == 3 && cmapEncoding == 0) {
3460 mode = t42FontModeCharCode;
3461 if (pdfFontHasEncoding) {
3462 if (unicodeCmap >= 0) {
3464 mode = t42FontModeUnicode;
3465 } else if (pdfFontIsSymbolic && msSymbolCmap >= 0) {
3467 mode = t42FontModeCharCodeOffset;
3468 cmapOffset = 0xf000;
3469 } else if (macRomanCmap >= 0) {
3471 mode = t42FontModeMacRoman;
3474 if (macRomanCmap >= 0) {
3476 mode = t42FontModeCharCode;
3477 } else if (msSymbolCmap >= 0) {
3479 mode = t42FontModeCharCodeOffset;
3480 cmapOffset = 0xf000;
3483 cmapPlatform = getUShort(pos + 4 + 8*i);
3484 cmapEncoding = getUShort(pos + 4 + 8*i + 2);
3485 pos += getULong(pos + 4 + 8*i + 4);
3486 cmapFmt = getUShort(pos);
3487 if (cmapFmt != 0 && cmapFmt != 4 && cmapFmt != 6) {
3488 error(-1, "Unimplemented cmap format (%d) in TrueType font file",
3493 // map char name to glyph index:
3494 // 1. use encoding to map name to char code
3495 // 2. use cmap to map char code to glyph index
3496 // N.B. We do this in reverse order because font subsets can have
3497 // weird encodings that use the same character name twice, and
3498 // the first definition is probably the one we want.
3499 k = 0; // make gcc happy
3500 for (i = 255; i >= 0; --i) {
3501 if (pdfFontHasEncoding) {
3502 name = encodingA[i];
3504 sprintf(buf2, "c%02x", i);
3507 if (name && strcmp(name, ".notdef")) {
3509 case t42FontModeUnicode:
3510 toUnicode->mapToUnicode((CharCode)i, &u, 1);
3511 k = getCmapEntry(cmapFmt, pos, (int)u);
3513 case t42FontModeCharCode:
3514 k = getCmapEntry(cmapFmt, pos, i);
3516 case t42FontModeCharCodeOffset:
3517 if ((k = getCmapEntry(cmapFmt, pos, cmapOffset + i)) == 0) {
3518 k = getCmapEntry(cmapFmt, pos, i);
3521 case t42FontModeMacRoman:
3522 j = globalParams->getMacRomanCharCode(name);
3523 k = getCmapEntry(cmapFmt, pos, j);
3526 // note: Distiller (maybe Adobe's PS interpreter in general)
3527 // doesn't like TrueType fonts that have CharStrings entries
3528 // which point to nonexistent glyphs, hence the (k < nGlyphs)
3530 if (k > 0 && k < nGlyphs) {
3531 (*outputFunc)(outputStream, "/", 1);
3532 (*outputFunc)(outputStream, name, strlen(name));
3533 sprintf(buf, " %d def\n", k);
3534 (*outputFunc)(outputStream, buf, strlen(buf));
3540 (*outputFunc)(outputStream, "end readonly def\n", 17);
3543 int TrueTypeFontFile::getCmapEntry(int cmapFmt, int pos, int code) {
3544 int cmapLen, cmapFirst;
3545 int segCnt, segEnd, segStart, segDelta, segOffset;
3549 case 0: // byte encoding table (Apple standard)
3550 cmapLen = getUShort(pos + 2);
3551 if (code >= cmapLen) {
3554 return getByte(pos + 6 + code);
3556 case 4: // segment mapping to delta values (Microsoft standard)
3557 segCnt = getUShort(pos + 6) / 2;
3560 segEnd = getUShort(pos + 14 + 2*b);
3561 if (code > segEnd) {
3562 // malformed font -- the TrueType spec requires the last segEnd
3566 // invariant: seg[a].end < code <= seg[b].end
3569 segEnd = getUShort(pos + 14 + 2*m);
3570 if (segEnd < code) {
3576 segStart = getUShort(pos + 16 + 2*segCnt + 2*b);
3577 segDelta = getUShort(pos + 16 + 4*segCnt + 2*b);
3578 segOffset = getUShort(pos + 16 + 6*segCnt + 2*b);
3579 if (code < segStart) {
3582 if (segOffset == 0) {
3583 i = (code + segDelta) & 0xffff;
3585 i = getUShort(pos + 16 + 6*segCnt + 2*b +
3586 segOffset + 2 * (code - segStart));
3588 i = (i + segDelta) & 0xffff;
3593 case 6: // trimmed table mapping
3594 cmapFirst = getUShort(pos + 6);
3595 cmapLen = getUShort(pos + 8);
3596 if (code < cmapFirst || code >= cmapFirst + cmapLen) {
3599 return getUShort(pos + 10 + 2*(code - cmapFirst));
3602 // shouldn't happen - this is checked earlier
3608 static int cmpTrueTypeLocaIdx(const void *p1, const void *p2) {
3609 return ((TrueTypeLoca *)p1)->idx - ((TrueTypeLoca *)p2)->idx;
3612 static int cmpTrueTypeLocaPos(const void *p1, const void *p2) {
3613 if (((TrueTypeLoca *)p1)->pos == ((TrueTypeLoca *)p2)->pos) {
3614 return ((TrueTypeLoca *)p1)->idx - ((TrueTypeLoca *)p2)->idx;
3616 return ((TrueTypeLoca *)p1)->pos - ((TrueTypeLoca *)p2)->pos;
3620 void TrueTypeFontFile::cvtSfnts(FontFileOutputFunc outputFunc,
3621 void *outputStream, GString *name) {
3622 TTFontTableHdr newTableHdrs[nT42Tables];
3623 char tableDir[12 + nT42Tables*16];
3625 TrueTypeLoca *origLocaTable;
3629 int pos, glyfPos, length, glyphLength, pad;
3632 // construct the 'head' table, zero out the font checksum
3633 memcpy(headTable, file + seekTable("head"), 54);
3634 headTable[8] = headTable[9] = headTable[10] = headTable[11] = (char)0;
3636 // read the original 'loca' table and sort it into proper order --
3637 // some (non-compliant) fonts have out-of-order loca tables; in
3638 // order to correctly handle the case where (compliant) fonts have
3639 // empty entries in the middle of the table, cmpTrueTypeLocaPos uses
3640 // pos as its primary sort key, and idx as its secondary key
3641 // (ensuring that adjacent entries with the same pos value remain in
3643 origLocaTable = (TrueTypeLoca *)gmalloc((nGlyphs + 1) *
3644 sizeof(TrueTypeLoca));
3645 pos = seekTable("loca");
3646 for (i = 0; i <= nGlyphs; ++i) {
3647 origLocaTable[i].idx = i;
3649 origLocaTable[i].pos = getULong(pos + 4*i);
3651 origLocaTable[i].pos = 2 * getUShort(pos + 2*i);
3654 qsort(origLocaTable, nGlyphs + 1, sizeof(TrueTypeLoca), &cmpTrueTypeLocaPos);
3655 for (i = 0; i < nGlyphs; ++i) {
3656 origLocaTable[i].length = origLocaTable[i+1].pos - origLocaTable[i].pos;
3658 origLocaTable[nGlyphs].length = 0;
3659 qsort(origLocaTable, nGlyphs + 1, sizeof(TrueTypeLoca), &cmpTrueTypeLocaIdx);
3661 // construct the new 'loca' table, padding each glyph out to a
3662 // multiple of 4 bytes
3663 locaTable = (char *)gmalloc((nGlyphs + 1) * (locaFmt ? 4 : 2));
3665 for (i = 0; i <= nGlyphs; ++i) {
3667 locaTable[4*i ] = (char)(pos >> 24);
3668 locaTable[4*i+1] = (char)(pos >> 16);
3669 locaTable[4*i+2] = (char)(pos >> 8);
3670 locaTable[4*i+3] = (char) pos;
3672 locaTable[2*i ] = (char)(pos >> 9);
3673 locaTable[2*i+1] = (char)(pos >> 1);
3675 length = origLocaTable[i].length;
3677 length += 4 - (length & 3);
3682 // count the number of tables
3684 for (i = 0; i < nT42Tables; ++i) {
3685 if (t42Tables[i].required ||
3686 seekTable(t42Tables[i].tag) >= 0) {
3691 // construct the new table headers, including table checksums
3692 // (pad each table out to a multiple of 4 bytes)
3693 pos = 12 + nNewTables*16;
3695 for (i = 0; i < nT42Tables; ++i) {
3697 checksum = 0; // make gcc happy
3698 if (i == t42HeadTable) {
3700 checksum = computeTableChecksum(headTable, 54);
3701 } else if (i == t42LocaTable) {
3702 length = (nGlyphs + 1) * (locaFmt ? 4 : 2);
3703 checksum = computeTableChecksum(locaTable, length);
3704 } else if (i == t42GlyfTable) {
3707 glyfPos = seekTable("glyf");
3708 for (j = 0; j < nGlyphs; ++j) {
3709 glyphLength = origLocaTable[j].length;
3710 pad = (glyphLength & 3) ? 4 - (glyphLength & 3) : 0;
3711 length += glyphLength + pad;
3712 if (glyphLength >= 0 &&
3713 glyfPos + origLocaTable[j].pos + glyphLength <= len) {
3715 computeTableChecksum(file + glyfPos + origLocaTable[j].pos,
3720 if ((j = seekTableIdx(t42Tables[i].tag)) >= 0) {
3721 length = tableHdrs[j].length;
3722 checksum = computeTableChecksum(file + tableHdrs[j].offset, length);
3723 } else if (t42Tables[i].required) {
3724 error(-1, "Embedded TrueType font is missing a required table ('%s')",
3731 strncpy(newTableHdrs[k].tag, t42Tables[i].tag, 4);
3732 newTableHdrs[k].checksum = checksum;
3733 newTableHdrs[k].offset = pos;
3734 newTableHdrs[k].length = length;
3735 pad = (length & 3) ? 4 - (length & 3) : 0;
3736 pos += length + pad;
3741 // construct the table directory
3742 tableDir[0] = 0x00; // sfnt version
3746 tableDir[4] = 0; // numTables
3747 tableDir[5] = nNewTables;
3748 tableDir[6] = 0; // searchRange
3749 tableDir[7] = (char)128;
3750 tableDir[8] = 0; // entrySelector
3752 tableDir[10] = 0; // rangeShift
3753 tableDir[11] = (char)(16 * nNewTables - 128);
3755 for (i = 0; i < nNewTables; ++i) {
3756 tableDir[pos ] = newTableHdrs[i].tag[0];
3757 tableDir[pos+ 1] = newTableHdrs[i].tag[1];
3758 tableDir[pos+ 2] = newTableHdrs[i].tag[2];
3759 tableDir[pos+ 3] = newTableHdrs[i].tag[3];
3760 tableDir[pos+ 4] = (char)(newTableHdrs[i].checksum >> 24);
3761 tableDir[pos+ 5] = (char)(newTableHdrs[i].checksum >> 16);
3762 tableDir[pos+ 6] = (char)(newTableHdrs[i].checksum >> 8);
3763 tableDir[pos+ 7] = (char) newTableHdrs[i].checksum;
3764 tableDir[pos+ 8] = (char)(newTableHdrs[i].offset >> 24);
3765 tableDir[pos+ 9] = (char)(newTableHdrs[i].offset >> 16);
3766 tableDir[pos+10] = (char)(newTableHdrs[i].offset >> 8);
3767 tableDir[pos+11] = (char) newTableHdrs[i].offset;
3768 tableDir[pos+12] = (char)(newTableHdrs[i].length >> 24);
3769 tableDir[pos+13] = (char)(newTableHdrs[i].length >> 16);
3770 tableDir[pos+14] = (char)(newTableHdrs[i].length >> 8);
3771 tableDir[pos+15] = (char) newTableHdrs[i].length;
3775 // compute the font checksum and store it in the head table
3776 checksum = computeTableChecksum(tableDir, 12 + nNewTables*16);
3777 for (i = 0; i < nNewTables; ++i) {
3778 checksum += newTableHdrs[i].checksum;
3780 checksum = 0xb1b0afba - checksum; // because the TrueType spec says so
3781 headTable[ 8] = (char)(checksum >> 24);
3782 headTable[ 9] = (char)(checksum >> 16);
3783 headTable[10] = (char)(checksum >> 8);
3784 headTable[11] = (char) checksum;
3786 // start the sfnts array
3788 (*outputFunc)(outputStream, "/", 1);
3789 (*outputFunc)(outputStream, name->getCString(), name->getLength());
3790 (*outputFunc)(outputStream, " [\n", 3);
3792 (*outputFunc)(outputStream, "/sfnts [\n", 9);
3795 // write the table directory
3796 dumpString(tableDir, 12 + nNewTables*16, outputFunc, outputStream);
3799 for (i = 0; i < nNewTables; ++i) {
3800 if (i == t42HeadTable) {
3801 dumpString(headTable, 54, outputFunc, outputStream);
3802 } else if (i == t42LocaTable) {
3803 length = (nGlyphs + 1) * (locaFmt ? 4 : 2);
3804 dumpString(locaTable, length, outputFunc, outputStream);
3805 } else if (i == t42GlyfTable) {
3806 glyfPos = seekTable("glyf");
3807 for (j = 0; j < nGlyphs; ++j) {
3808 length = origLocaTable[j].length;
3810 glyfPos + origLocaTable[j].pos + length <= len) {
3811 dumpString(file + glyfPos + origLocaTable[j].pos, length,
3812 outputFunc, outputStream);
3816 // length == 0 means the table is missing and the error was
3817 // already reported during the construction of the table
3819 if ((length = newTableHdrs[i].length) > 0) {
3820 j = seekTable(t42Tables[i].tag);
3822 dumpString(file + seekTable(t42Tables[i].tag), length,
3823 outputFunc, outputStream);
3829 // end the sfnts array
3830 (*outputFunc)(outputStream, "] def\n", 6);
3832 gfree(origLocaTable);
3836 void TrueTypeFontFile::dumpString(char *s, int length,
3837 FontFileOutputFunc outputFunc,
3838 void *outputStream) {
3842 (*outputFunc)(outputStream, "<", 1);
3843 for (i = 0; i < length; i += 32) {
3844 for (j = 0; j < 32 && i+j < length; ++j) {
3845 sprintf(buf, "%02X", s[i+j] & 0xff);
3846 (*outputFunc)(outputStream, buf, strlen(buf));
3848 if (i % (65536 - 32) == 65536 - 64) {
3849 (*outputFunc)(outputStream, ">\n<", 3);
3850 } else if (i+32 < length) {
3851 (*outputFunc)(outputStream, "\n", 1);
3855 pad = 4 - (length & 3);
3856 for (i = 0; i < pad; ++i) {
3857 (*outputFunc)(outputStream, "00", 2);
3860 // add an extra zero byte because the Adobe Type 42 spec says so
3861 (*outputFunc)(outputStream, "00>\n", 4);
3864 Guint TrueTypeFontFile::computeTableChecksum(char *data, int length) {
3865 Guint checksum, word;
3869 for (i = 0; i+3 < length; i += 4) {
3870 word = ((data[i ] & 0xff) << 24) +
3871 ((data[i+1] & 0xff) << 16) +
3872 ((data[i+2] & 0xff) << 8) +
3879 switch (length & 3) {
3881 word |= (data[i+2] & 0xff) << 8;
3883 word |= (data[i+1] & 0xff) << 16;
3885 word |= (data[i ] & 0xff) << 24;
3893 void TrueTypeFontFile::writeTTF(FILE *out) {
3894 static char cmapTab[20] = {
3895 0, 0, // table version number
3896 0, 1, // number of encoding tables
3897 0, 1, // platform ID
3898 0, 0, // encoding ID
3899 0, 0, 0, 12, // offset of subtable
3900 0, 0, // subtable format
3901 0, 1, // subtable length
3902 0, 1, // subtable version
3903 0, // map char 0 -> glyph 0
3904 0 // pad to multiple of four bytes
3906 static char nameTab[8] = {
3908 0, 0, // number of name records
3909 0, 6, // offset to start of string storage
3910 0, 0 // pad to multiple of four bytes
3912 static char postTab[32] = {
3913 0, 1, 0, 0, // format
3914 0, 0, 0, 0, // italic angle
3915 0, 0, // underline position
3916 0, 0, // underline thickness
3917 0, 0, 0, 0, // fixed pitch
3918 0, 0, 0, 0, // min Type 42 memory
3919 0, 0, 0, 0, // max Type 42 memory
3920 0, 0, 0, 0, // min Type 1 memory
3921 0, 0, 0, 0 // max Type 1 memory
3923 GBool haveCmap, haveName, havePost;
3924 GBool dirCmap, dirName, dirPost;
3926 int nNewTables, nZeroLengthTables, nAllTables;
3927 TTFontTableHdr *newTableHdrs;
3929 TrueTypeLoca *origLocaTable;
3931 int length, glyfLength;
3935 // check for missing/broken tables
3936 haveCmap = seekTable("cmap") >= 0;
3937 haveName = seekTable("name") >= 0;
3938 havePost = seekTable("post") >= 0;
3939 unsortedLoca = gFalse;
3941 for (i = 0; i <= nGlyphs; ++i) {
3943 pos2 = getULong(pos + 4*i);
3945 pos2 = 2 * getUShort(pos + 2*i);
3948 unsortedLoca = gTrue;
3953 nNewTables = (haveCmap ? 0 : 1) + (haveName ? 0 : 1) + (havePost ? 0 : 1);
3954 nZeroLengthTables = 0;
3955 for (i = 0; i < nTables; ++i) {
3956 if (tableHdrs[i].length == 0) {
3957 ++nZeroLengthTables;
3960 if (!nNewTables && !nZeroLengthTables && !mungedCmapSize && !unsortedLoca) {
3961 // nothing is broken - write the TTF file as is
3962 fwrite(file, 1, len, out);
3966 // if the glyph data isn't sorted (as listed in the 'loca' table),
3967 // construct a new 'loca' table
3969 origLocaTable = (TrueTypeLoca *)gmalloc((nGlyphs + 1) *
3970 sizeof(TrueTypeLoca));
3971 pos = seekTable("loca");
3972 for (i = 0; i <= nGlyphs; ++i) {
3973 origLocaTable[i].idx = i;
3975 origLocaTable[i].pos = getULong(pos + 4*i);
3977 origLocaTable[i].pos = 2 * getUShort(pos + 2*i);
3980 qsort(origLocaTable, nGlyphs + 1, sizeof(TrueTypeLoca),
3981 &cmpTrueTypeLocaPos);
3982 for (i = 0; i < nGlyphs; ++i) {
3983 origLocaTable[i].length = origLocaTable[i+1].pos - origLocaTable[i].pos;
3985 origLocaTable[nGlyphs].length = 0;
3986 qsort(origLocaTable, nGlyphs + 1, sizeof(TrueTypeLoca),
3987 &cmpTrueTypeLocaIdx);
3988 locaTable = (char *)gmalloc((nGlyphs + 1) * (locaFmt ? 4 : 2));
3990 for (i = 0; i <= nGlyphs; ++i) {
3992 locaTable[4*i ] = (char)(pos >> 24);
3993 locaTable[4*i+1] = (char)(pos >> 16);
3994 locaTable[4*i+2] = (char)(pos >> 8);
3995 locaTable[4*i+3] = (char) pos;
3997 locaTable[2*i ] = (char)(pos >> 9);
3998 locaTable[2*i+1] = (char)(pos >> 1);
4000 length = origLocaTable[i].length;
4002 length += 4 - (length & 3);
4008 origLocaTable = NULL; // make gcc happy
4009 locaTable = NULL; // make gcc happy
4010 glyfLength = 0; // make gcc happy
4013 // construct the new table directory
4014 nAllTables = nTables - nZeroLengthTables + nNewTables;
4015 newTableHdrs = (TTFontTableHdr *)gmalloc(nAllTables *
4016 sizeof(TTFontTableHdr));
4020 pos = 12 + nAllTables * 16;
4022 for (i = 0; i < nTables; ++i) {
4023 if (!dirCmap && strncmp(tableHdrs[i].tag, "cmap", 4) > 0) {
4024 memcpy(newTableHdrs[j].tag, "cmap", 4);
4025 newTableHdrs[j].checksum = 0; //~ should compute the checksum
4026 newTableHdrs[j].offset = pos;
4027 pos += newTableHdrs[j].length = sizeof(cmapTab);
4029 pos += 4 - (pos & 3);
4034 if (!dirName && strncmp(tableHdrs[i].tag, "name", 4) > 0) {
4035 memcpy(newTableHdrs[j].tag, "name", 4);
4036 newTableHdrs[j].checksum = 0; //~ should compute the checksum
4037 newTableHdrs[j].offset = pos;
4038 pos += newTableHdrs[j].length = sizeof(nameTab);
4040 pos += 4 - (pos & 3);
4045 if (!dirPost && strncmp(tableHdrs[i].tag, "post", 4) > 0) {
4046 memcpy(newTableHdrs[j].tag, "post", 4);
4047 newTableHdrs[j].checksum = 0; //~ should compute the checksum
4048 newTableHdrs[j].offset = pos;
4049 pos += newTableHdrs[j].length = sizeof(postTab);
4051 pos += 4 - (pos & 3);
4056 // throw away zero-length tables - they confuse FreeType
4057 if (tableHdrs[i].length > 0) {
4058 memcpy(newTableHdrs[j].tag, tableHdrs[i].tag, 4);
4059 newTableHdrs[j].checksum = tableHdrs[i].checksum;
4060 newTableHdrs[j].offset = pos;
4061 if (unsortedLoca && !strncmp(tableHdrs[i].tag, "loca", 4)) {
4062 newTableHdrs[j].length = (nGlyphs + 1) * (locaFmt ? 4 : 2);
4063 } else if (unsortedLoca && !strncmp(tableHdrs[i].tag, "glyf", 4)) {
4064 newTableHdrs[j].length = glyfLength;
4066 newTableHdrs[j].length = tableHdrs[i].length;
4068 pos += newTableHdrs[j].length;
4070 pos += 4 - (pos & 3);
4076 memcpy(newTableHdrs[j].tag, "cmap", 4);
4077 newTableHdrs[j].checksum = 0; //~ should compute the checksum
4078 newTableHdrs[j].offset = pos;
4079 pos += newTableHdrs[j].length = sizeof(cmapTab);
4081 pos += 4 - (pos & 3);
4086 memcpy(newTableHdrs[j].tag, "name", 4);
4087 newTableHdrs[j].checksum = 0; //~ should compute the checksum
4088 newTableHdrs[j].offset = pos;
4089 pos += newTableHdrs[j].length = sizeof(nameTab);
4091 pos += 4 - (pos & 3);
4096 memcpy(newTableHdrs[j].tag, "post", 4);
4097 newTableHdrs[j].checksum = 0; //~ should compute the checksum
4098 newTableHdrs[j].offset = pos;
4099 pos += newTableHdrs[j].length = sizeof(postTab);
4101 pos += 4 - (pos & 3);
4105 tableDir = (char *)gmalloc(12 + nAllTables * 16);
4106 tableDir[0] = 0x00; // sfnt version
4110 tableDir[4] = (char)((nAllTables >> 8) & 0xff); // numTables
4111 tableDir[5] = (char)(nAllTables & 0xff);
4112 for (i = -1, t = (Guint)nAllTables; t; ++i, t >>= 1) ;
4114 tableDir[6] = (char)((t >> 8) & 0xff); // searchRange
4115 tableDir[7] = (char)(t & 0xff);
4116 tableDir[8] = (char)((i >> 8) & 0xff); // entrySelector
4117 tableDir[9] = (char)(i & 0xff);
4118 t = nAllTables * 16 - t;
4119 tableDir[10] = (char)((t >> 8) & 0xff); // rangeShift
4120 tableDir[11] = (char)(t & 0xff);
4122 for (i = 0; i < nAllTables; ++i) {
4123 tableDir[pos ] = newTableHdrs[i].tag[0];
4124 tableDir[pos+ 1] = newTableHdrs[i].tag[1];
4125 tableDir[pos+ 2] = newTableHdrs[i].tag[2];
4126 tableDir[pos+ 3] = newTableHdrs[i].tag[3];
4127 tableDir[pos+ 4] = (char)(newTableHdrs[i].checksum >> 24);
4128 tableDir[pos+ 5] = (char)(newTableHdrs[i].checksum >> 16);
4129 tableDir[pos+ 6] = (char)(newTableHdrs[i].checksum >> 8);
4130 tableDir[pos+ 7] = (char) newTableHdrs[i].checksum;
4131 tableDir[pos+ 8] = (char)(newTableHdrs[i].offset >> 24);
4132 tableDir[pos+ 9] = (char)(newTableHdrs[i].offset >> 16);
4133 tableDir[pos+10] = (char)(newTableHdrs[i].offset >> 8);
4134 tableDir[pos+11] = (char) newTableHdrs[i].offset;
4135 tableDir[pos+12] = (char)(newTableHdrs[i].length >> 24);
4136 tableDir[pos+13] = (char)(newTableHdrs[i].length >> 16);
4137 tableDir[pos+14] = (char)(newTableHdrs[i].length >> 8);
4138 tableDir[pos+15] = (char) newTableHdrs[i].length;
4142 // write the table directory
4143 fwrite(tableDir, 1, 12 + 16 * nAllTables, out);
4146 for (i = 0; i < nAllTables; ++i) {
4147 if (!haveCmap && !strncmp(newTableHdrs[i].tag, "cmap", 4)) {
4148 fwrite(cmapTab, 1, newTableHdrs[i].length, out);
4149 } else if (!haveName && !strncmp(newTableHdrs[i].tag, "name", 4)) {
4150 fwrite(nameTab, 1, newTableHdrs[i].length, out);
4151 } else if (!havePost && !strncmp(newTableHdrs[i].tag, "post", 4)) {
4152 fwrite(postTab, 1, newTableHdrs[i].length, out);
4153 } else if (unsortedLoca && !strncmp(newTableHdrs[i].tag, "loca", 4)) {
4154 fwrite(locaTable, 1, newTableHdrs[i].length, out);
4155 } else if (unsortedLoca && !strncmp(newTableHdrs[i].tag, "glyf", 4)) {
4156 pos = seekTable("glyf");
4157 for (j = 0; j < nGlyphs; ++j) {
4158 length = origLocaTable[j].length;
4160 pos + origLocaTable[j].pos + length <= (Guint)len) {
4161 fwrite(file + pos + origLocaTable[j].pos, 1, length, out);
4162 if ((k = length & 3)) {
4163 for (; k < 4; ++k) {
4164 fputc((char)0, out);
4170 fwrite(file + seekTable(newTableHdrs[i].tag),
4171 1, newTableHdrs[i].length, out);
4173 if ((j = (newTableHdrs[i].length & 3))) {
4174 for (; j < 4; ++j) {
4175 fputc((char)0, out);
4181 gfree(newTableHdrs);
4183 gfree(origLocaTable);