1 //========================================================================
5 // Copyright 1999-2002 Glyph & Cog, LLC
7 //========================================================================
11 #ifdef USE_GCC_PRAGMAS
12 #pragma implementation
23 #include "GlobalParams.h"
24 #include "CharCodeToUnicode.h"
25 #include "FontEncodingTables.h"
28 #include "CompactFontTables.h"
30 //------------------------------------------------------------------------
32 static inline char *nextLine(char *line, char *end) {
33 while (line < end && *line != '\n' && *line != '\r')
35 while (line < end && *line == '\n' || *line == '\r')
40 static char hexChars[17] = "0123456789ABCDEF";
42 //------------------------------------------------------------------------
44 //------------------------------------------------------------------------
46 FontFile::FontFile() {
49 FontFile::~FontFile() {
52 //------------------------------------------------------------------------
54 //------------------------------------------------------------------------
56 Type1FontFile::Type1FontFile(char *file, int len) {
57 char *line, *line1, *p, *p2;
64 encoding = (char **)gmalloc(256 * sizeof(char *));
65 for (i = 0; i < 256; ++i) {
68 haveEncoding = gFalse;
70 for (i = 1, line = file;
71 i <= 100 && line < file + len && !haveEncoding;
75 if (!strncmp(line, "/FontName", 9)) {
76 strncpy(buf, line, 255);
78 if ((p = strchr(buf+9, '/')) &&
79 (p = strtok(p+1, " \t\n\r"))) {
82 line = nextLine(line, file + len);
85 } else if (!strncmp(line, "/Encoding StandardEncoding def", 30)) {
86 for (j = 0; j < 256; ++j) {
87 if (standardEncoding[j]) {
88 encoding[j] = copyString(standardEncoding[j]);
92 } else if (!strncmp(line, "/Encoding 256 array", 19)) {
93 for (j = 0; j < 300; ++j) {
94 line1 = nextLine(line, file + len);
95 if ((n = line1 - line) > 255) {
98 strncpy(buf, line, n);
100 for (p = buf; *p == ' ' || *p == '\t'; ++p) ;
101 if (!strncmp(p, "dup", 3)) {
102 for (p += 3; *p == ' ' || *p == '\t'; ++p) ;
103 for (p2 = p; *p2 >= '0' && *p2 <= '9'; ++p2) ;
107 if ((code = atoi(p)) < 256) {
109 for (p = p2; *p == ' ' || *p == '\t'; ++p) ;
112 for (p2 = p; *p2 && *p2 != ' ' && *p2 != '\t'; ++p2) ;
114 encoding[code] = copyString(p);
119 if (strtok(buf, " \t") &&
120 (p = strtok(NULL, " \t\n\r")) && !strcmp(p, "def")) {
126 //~ check for getinterval/putinterval junk
127 haveEncoding = gTrue;
130 line = nextLine(line, file + len);
135 Type1FontFile::~Type1FontFile() {
141 for (i = 0; i < 256; ++i) {
147 //------------------------------------------------------------------------
149 //------------------------------------------------------------------------
151 struct Type1CTopDict {
160 double underlinePosition;
161 double underlineThickness;
164 double fontMatrix[6];
174 //----- CIDFont entries
182 struct Type1CPrivateDict {
185 double defaultWidthX;
186 GBool defaultWidthXFP;
187 double nominalWidthX;
188 GBool nominalWidthXFP;
191 Type1CFontFile::Type1CFontFile(char *fileA, int lenA) {
192 Guchar *nameIdxPtr, *idxPtr0, *idxPtr1;
199 // some tools embed Type 1C fonts with an extra whitespace char at
201 if (file[0] != '\x01') {
206 topOffSize = file[3] & 0xff;
208 // read name index (first font only)
209 nameIdxPtr = (Guchar *)file + (file[2] & 0xff);
210 idxPtr0 = getIndexValPtr(nameIdxPtr, 0);
211 idxPtr1 = getIndexValPtr(nameIdxPtr, 1);
212 name = new GString((char *)idxPtr0, idxPtr1 - idxPtr0);
214 topDictIdxPtr = getIndexEnd(nameIdxPtr);
215 stringIdxPtr = getIndexEnd(topDictIdxPtr);
216 gsubrIdxPtr = getIndexEnd(stringIdxPtr);
219 Type1CFontFile::~Type1CFontFile() {
224 for (i = 0; i < 256; ++i) {
231 char *Type1CFontFile::getName() {
232 return name->getCString();
235 char **Type1CFontFile::getEncoding() {
237 readNameAndEncoding();
242 void Type1CFontFile::readNameAndEncoding() {
244 Guchar *idxPtr0, *idxPtr1, *ptr;
246 int nCodes, nRanges, nLeft, nSups;
248 int charset, enc, charstrings;
256 encoding = (char **)gmalloc(256 * sizeof(char *));
257 for (i = 0; i < 256; ++i) {
261 // read top dict (first font only)
262 idxPtr0 = getIndexValPtr(topDictIdxPtr, 0);
263 idxPtr1 = getIndexValPtr(topDictIdxPtr, 1);
264 charset = enc = charstrings = 0;
267 while (ptr < idxPtr1) {
268 if (*ptr <= 27 || *ptr == 31) {
271 key = (key << 8) | *ptr++;
273 if (key == 0x0f) { // charset
274 charset = (int)op[0];
275 } else if (key == 0x10) { // encoding
277 } else if (key == 0x11) { // charstrings
278 charstrings = (int)op[0];
282 x = getNum(&ptr, &isFP);
289 // get number of glyphs from charstrings index
290 nGlyphs = getIndexLen((Guchar *)file + charstrings);
292 // read charset (GID -> name mapping)
293 glyphNames = readCharset(charset, nGlyphs);
295 // read encoding (GID -> code mapping)
297 for (i = 0; i < 256; ++i) {
298 if (standardEncoding[i]) {
299 encoding[i] = copyString(standardEncoding[i]);
302 } else if (enc == 1) {
303 for (i = 0; i < 256; ++i) {
304 if (expertEncoding[i]) {
305 encoding[i] = copyString(expertEncoding[i]);
309 ptr = (Guchar *)file + enc;
311 if ((encFormat & 0x7f) == 0) {
313 if (nCodes > nGlyphs) {
316 for (i = 1; i < nCodes; ++i) {
318 encoding[c] = copyString(getString(glyphNames[i], buf));
320 } else if ((encFormat & 0x7f) == 1) {
323 for (i = 0; i < nRanges; ++i) {
326 for (j = 0; j <= nLeft && nCodes < nGlyphs; ++j) {
327 encoding[c] = copyString(getString(glyphNames[nCodes], buf));
333 if (encFormat & 0x80) {
335 for (i = 0; i < nSups; ++i) {
337 sid = getWord(ptr, 2);
339 encoding[c] = copyString(getString(sid, buf));
349 void Type1CFontFile::convertToType1(FontFileOutputFunc outputFuncA,
350 void *outputStreamA) {
352 Type1CPrivateDict privateDict;
353 char buf[512], eBuf[256];
354 Guchar *idxPtr0, *idxPtr1, *subrsIdxPtr, *charStringsIdxPtr, *ptr;
355 int nGlyphs, nCodes, nRanges, nLeft, nSups;
357 int encFormat, nSubrs, nCharStrings;
361 outputFunc = outputFuncA;
362 outputStream = outputStreamA;
364 // read top dict (first font only)
368 //~ ... global subrs are unimplemented
370 // write header and font dictionary, up to encoding
371 (*outputFunc)(outputStream, "%!FontType1-1.0: ", 17);
372 (*outputFunc)(outputStream, name->getCString(), name->getLength());
373 if (dict.version != 0) {
374 getString(dict.version, buf);
375 (*outputFunc)(outputStream, buf, strlen(buf));
377 (*outputFunc)(outputStream, "\n", 1);
378 (*outputFunc)(outputStream, "11 dict begin\n", 14);
379 (*outputFunc)(outputStream, "/FontInfo 10 dict dup begin\n", 28);
380 if (dict.version != 0) {
381 (*outputFunc)(outputStream, "/version (", 10);
382 (*outputFunc)(outputStream, buf, strlen(buf));
383 (*outputFunc)(outputStream, ") readonly def\n", 15);
385 if (dict.notice != 0) {
386 getString(dict.notice, buf);
387 (*outputFunc)(outputStream, "/Notice (", 9);
388 (*outputFunc)(outputStream, buf, strlen(buf));
389 (*outputFunc)(outputStream, ") readonly def\n", 15);
391 if (dict.copyright != 0) {
392 getString(dict.copyright, buf);
393 (*outputFunc)(outputStream, "/Copyright (", 12);
394 (*outputFunc)(outputStream, buf, strlen(buf));
395 (*outputFunc)(outputStream, ") readonly def\n", 15);
397 if (dict.fullName != 0) {
398 getString(dict.fullName, buf);
399 (*outputFunc)(outputStream, "/FullName (", 11);
400 (*outputFunc)(outputStream, buf, strlen(buf));
401 (*outputFunc)(outputStream, ") readonly def\n", 15);
403 if (dict.familyName != 0) {
404 getString(dict.familyName, buf);
405 (*outputFunc)(outputStream, "/FamilyName (", 13);
406 (*outputFunc)(outputStream, buf, strlen(buf));
407 (*outputFunc)(outputStream, ") readonly def\n", 15);
409 if (dict.weight != 0) {
410 getString(dict.weight, buf);
411 (*outputFunc)(outputStream, "/Weight (", 9);
412 (*outputFunc)(outputStream, buf, strlen(buf));
413 (*outputFunc)(outputStream, ") readonly def\n", 15);
415 if (dict.isFixedPitch) {
416 (*outputFunc)(outputStream, "/isFixedPitch true def\n", 23);
418 (*outputFunc)(outputStream, "/isFixedPitch false def\n", 24);
420 sprintf(buf, "/ItalicAngle %g def\n", dict.italicAngle);
421 (*outputFunc)(outputStream, buf, strlen(buf));
422 sprintf(buf, "/UnderlinePosition %g def\n", dict.underlinePosition);
423 (*outputFunc)(outputStream, buf, strlen(buf));
424 sprintf(buf, "/UnderlineThickness %g def\n", dict.underlineThickness);
425 (*outputFunc)(outputStream, buf, strlen(buf));
426 (*outputFunc)(outputStream, "end readonly def\n", 17);
427 (*outputFunc)(outputStream, "/FontName /", 11);
428 (*outputFunc)(outputStream, name->getCString(), name->getLength());
429 (*outputFunc)(outputStream, " def\n", 5);
430 sprintf(buf, "/PaintType %d def\n", dict.paintType);
431 (*outputFunc)(outputStream, buf, strlen(buf));
432 (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
433 sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] readonly def\n",
434 dict.fontMatrix[0], dict.fontMatrix[1], dict.fontMatrix[2],
435 dict.fontMatrix[3], dict.fontMatrix[4], dict.fontMatrix[5]);
436 (*outputFunc)(outputStream, buf, strlen(buf));
437 sprintf(buf, "/FontBBox [%g %g %g %g] readonly def\n",
438 dict.fontBBox[0], dict.fontBBox[1],
439 dict.fontBBox[2], dict.fontBBox[3]);
440 (*outputFunc)(outputStream, buf, strlen(buf));
441 sprintf(buf, "/StrokeWidth %g def\n", dict.strokeWidth);
442 (*outputFunc)(outputStream, buf, strlen(buf));
443 if (dict.uniqueID != 0) {
444 sprintf(buf, "/UniqueID %d def\n", dict.uniqueID);
445 (*outputFunc)(outputStream, buf, strlen(buf));
448 // get number of glyphs from charstrings index
449 nGlyphs = getIndexLen((Guchar *)file + dict.charStrings);
452 glyphNames = readCharset(dict.charset, nGlyphs);
454 // read encoding (glyph -> code mapping), write Type 1 encoding
455 (*outputFunc)(outputStream, "/Encoding ", 10);
456 if (dict.encoding == 0) {
457 (*outputFunc)(outputStream, "StandardEncoding def\n", 21);
459 (*outputFunc)(outputStream, "256 array\n", 10);
460 (*outputFunc)(outputStream,
461 "0 1 255 {1 index exch /.notdef put} for\n", 40);
462 if (dict.encoding == 1) {
463 for (i = 0; i < 256; ++i) {
464 if (expertEncoding[i]) {
465 sprintf(buf, "dup %d /%s put\n", i, expertEncoding[i]);
466 (*outputFunc)(outputStream, buf, strlen(buf));
470 ptr = (Guchar *)file + dict.encoding;
472 if ((encFormat & 0x7f) == 0) {
474 if (nCodes > nGlyphs) {
477 for (i = 1; i < nCodes; ++i) {
479 sprintf(buf, "dup %d /", c);
480 (*outputFunc)(outputStream, buf, strlen(buf));
481 getString(glyphNames[i], buf);
482 (*outputFunc)(outputStream, buf, strlen(buf));
483 (*outputFunc)(outputStream, " put\n", 5);
485 } else if ((encFormat & 0x7f) == 1) {
488 for (i = 0; i < nRanges; ++i) {
491 for (j = 0; j <= nLeft && nCodes < nGlyphs; ++j) {
492 sprintf(buf, "dup %d /", c);
493 (*outputFunc)(outputStream, buf, strlen(buf));
494 getString(glyphNames[nCodes], buf);
495 (*outputFunc)(outputStream, buf, strlen(buf));
496 (*outputFunc)(outputStream, " put\n", 5);
502 if (encFormat & 0x80) {
504 for (i = 0; i < nSups; ++i) {
506 sid = getWord(ptr, 2);
508 sprintf(buf, "dup %d /", c);
509 (*outputFunc)(outputStream, buf, strlen(buf));
511 (*outputFunc)(outputStream, buf, strlen(buf));
512 (*outputFunc)(outputStream, " put\n", 5);
516 (*outputFunc)(outputStream, "readonly def\n", 13);
518 (*outputFunc)(outputStream, "currentdict end\n", 16);
520 // start the binary section
521 (*outputFunc)(outputStream, "currentfile eexec\n", 18);
525 // get private dictionary
526 eexecWrite("\x83\xca\x73\xd5");
527 eexecWrite("dup /Private 32 dict dup begin\n");
528 eexecWrite("/RD {string currentfile exch readstring pop} executeonly def\n");
529 eexecWrite("/ND {noaccess def} executeonly def\n");
530 eexecWrite("/NP {noaccess put} executeonly def\n");
531 eexecWrite("/MinFeature {16 16} ND\n");
532 readPrivateDict(&privateDict, dict.privateOffset, dict.privateSize);
533 eexecWrite(privateDict.dictData->getCString());
534 defaultWidthX = privateDict.defaultWidthX;
535 defaultWidthXFP = privateDict.defaultWidthXFP;
536 nominalWidthX = privateDict.nominalWidthX;
537 nominalWidthXFP = privateDict.nominalWidthXFP;
540 if (privateDict.subrsOffset != 0) {
541 subrsIdxPtr = (Guchar *)file + dict.privateOffset +
542 privateDict.subrsOffset;
543 nSubrs = getIndexLen(subrsIdxPtr);
544 sprintf(eBuf, "/Subrs %d array\n", nSubrs);
546 idxPtr1 = getIndexValPtr(subrsIdxPtr, 0);
547 for (i = 0; i < nSubrs; ++i) {
549 idxPtr1 = getIndexValPtr(subrsIdxPtr, i+1);
550 n = idxPtr1 - idxPtr0;
551 #if 1 //~ Type 2 subrs are unimplemented
552 error(-1, "Unimplemented Type 2 subrs");
554 sprintf(eBuf, "dup %d %d RD ", i, n);
556 eexecCvtGlyph(idxPtr0, n);
564 charStringsIdxPtr = (Guchar *)file + dict.charStrings;
565 nCharStrings = getIndexLen(charStringsIdxPtr);
566 sprintf(eBuf, "2 index /CharStrings %d dict dup begin\n", nCharStrings);
568 idxPtr1 = getIndexValPtr(charStringsIdxPtr, 0);
569 for (i = 0; i < nCharStrings; ++i) {
571 idxPtr1 = getIndexValPtr(charStringsIdxPtr, i+1);
572 n = idxPtr1 - idxPtr0;
573 eexecCvtGlyph(getString(glyphNames[i], buf), idxPtr0, n);
577 eexecWrite("readonly put\n");
578 eexecWrite("noaccess put\n");
579 eexecWrite("dup /FontName get exch definefont pop\n");
580 eexecWrite("mark currentfile closefile\n");
584 (*outputFunc)(outputStream, "\n", 1);
586 for (i = 0; i < 8; ++i) {
587 (*outputFunc)(outputStream, "0000000000000000000000000000000000000000000000000000000000000000\n", 65);
589 (*outputFunc)(outputStream, "cleartomark\n", 12);
592 delete privateDict.dictData;
593 if (dict.charset > 2) {
598 void Type1CFontFile::convertToCIDType0(char *psName,
599 FontFileOutputFunc outputFuncA,
600 void *outputStreamA) {
602 Type1CPrivateDict *privateDicts;
603 GString *charStrings;
604 int *charStringOffsets;
608 Guchar *charStringsIdxPtr, *fdArrayIdx, *idxPtr0, *idxPtr1, *ptr;
609 char buf[512], buf2[16];
610 int nGlyphs, nCIDs, gdBytes, nFDs;
611 int fdSelectFmt, nRanges, gid0, gid1, fd, offset;
617 outputFunc = outputFuncA;
618 outputStream = outputStreamA;
620 (*outputFunc)(outputStream, "/CIDInit /ProcSet findresource begin\n", 37);
622 // read top dict (first font only)
625 // read the FDArray dictionaries and Private dictionaries
626 if (dict.fdArrayOffset == 0) {
628 privateDicts = (Type1CPrivateDict *)
629 gmalloc(nFDs * sizeof(Type1CPrivateDict));
630 privateDicts[0].dictData = new GString();
631 privateDicts[0].subrsOffset = 0;
632 privateDicts[0].defaultWidthX = 0;
633 privateDicts[0].defaultWidthXFP = gFalse;
634 privateDicts[0].nominalWidthX = 0;
635 privateDicts[0].nominalWidthXFP = gFalse;
637 fdArrayIdx = (Guchar *)file + dict.fdArrayOffset;
638 nFDs = getIndexLen(fdArrayIdx);
639 privateDicts = (Type1CPrivateDict *)
640 gmalloc(nFDs * sizeof(Type1CPrivateDict));
641 idxPtr1 = getIndexValPtr(fdArrayIdx, 0);
642 for (i = 0; i < nFDs; ++i) {
643 privateDicts[i].dictData = NULL;
645 idxPtr1 = getIndexValPtr(fdArrayIdx, i + 1);
648 while (ptr < idxPtr1) {
649 if (*ptr <= 27 || *ptr == 31) {
652 key = (key << 8) | *ptr++;
655 readPrivateDict(&privateDicts[i], (int)op[1], (int)op[0]);
659 x = getNum(&ptr, &isFP);
666 if (!privateDicts[i].dictData) {
667 privateDicts[i].dictData = new GString();
668 privateDicts[i].subrsOffset = 0;
669 privateDicts[i].defaultWidthX = 0;
670 privateDicts[i].defaultWidthXFP = gFalse;
671 privateDicts[i].nominalWidthX = 0;
672 privateDicts[i].nominalWidthXFP = gFalse;
677 // get the glyph count
678 charStringsIdxPtr = (Guchar *)file + dict.charStrings;
679 nGlyphs = getIndexLen(charStringsIdxPtr);
681 // read the FDSelect table
682 fdSelect = (Guchar *)gmalloc(nGlyphs);
683 if (dict.fdSelectOffset == 0) {
684 for (i = 0; i < nGlyphs; ++i) {
688 ptr = (Guchar *)file + dict.fdSelectOffset;
689 fdSelectFmt = *ptr++;
690 if (fdSelectFmt == 0) {
691 memcpy(fdSelect, ptr, nGlyphs);
692 } else if (fdSelectFmt == 3) {
693 nRanges = getWord(ptr, 2);
695 gid0 = getWord(ptr, 2);
697 for (i = 1; i <= nRanges; ++i) {
699 gid1 = getWord(ptr, 2);
701 for (j = gid0; j < gid1; ++j) {
707 error(-1, "Unknown FDSelect table format in CID font");
708 for (i = 0; i < nGlyphs; ++i) {
714 // read the charset, compute the CID-to-GID mapping
715 charset = readCharset(dict.charset, nGlyphs);
717 for (i = 0; i < nGlyphs; ++i) {
718 if (charset[i] >= nCIDs) {
719 nCIDs = charset[i] + 1;
722 cidMap = (int *)gmalloc(nCIDs * sizeof(int));
723 for (i = 0; i < nCIDs; ++i) {
726 for (i = 0; i < nGlyphs; ++i) {
727 cidMap[charset[i]] = i;
730 // build the charstrings
731 charStrings = new GString();
732 charStringOffsets = (int *)gmalloc((nCIDs + 1) * sizeof(int));
733 for (i = 0; i < nCIDs; ++i) {
734 charStringOffsets[i] = charStrings->getLength();
735 if (cidMap[i] >= 0) {
736 idxPtr0 = getIndexValPtr(charStringsIdxPtr, cidMap[i]);
737 idxPtr1 = getIndexValPtr(charStringsIdxPtr, cidMap[i]+1);
738 n = idxPtr1 - idxPtr0;
739 j = fdSelect[cidMap[i]];
740 defaultWidthX = privateDicts[j].defaultWidthX;
741 defaultWidthXFP = privateDicts[j].defaultWidthXFP;
742 nominalWidthX = privateDicts[j].nominalWidthX;
743 nominalWidthXFP = privateDicts[j].nominalWidthXFP;
744 cvtGlyph(idxPtr0, n);
745 charStrings->append(charBuf);
749 charStringOffsets[nCIDs] = charStrings->getLength();
751 // compute gdBytes = number of bytes needed for charstring offsets
752 // (offset size needs to account for the charstring offset table,
753 // with a worst case of five bytes per entry, plus the charstrings
755 i = (nCIDs + 1) * 5 + charStrings->getLength();
758 } else if (i < 0x10000) {
760 } else if (i < 0x1000000) {
766 // begin the font dictionary
767 (*outputFunc)(outputStream, "20 dict begin\n", 14);
768 (*outputFunc)(outputStream, "/CIDFontName /", 14);
769 (*outputFunc)(outputStream, psName, strlen(psName));
770 (*outputFunc)(outputStream, " def\n", 5);
771 (*outputFunc)(outputStream, "/CIDFontType 0 def\n", 19);
772 (*outputFunc)(outputStream, "/CIDSystemInfo 3 dict dup begin\n", 32);
773 if (dict.registry > 0 && dict.ordering > 0) {
774 getString(dict.registry, buf);
775 (*outputFunc)(outputStream, " /Registry (", 13);
776 (*outputFunc)(outputStream, buf, strlen(buf));
777 (*outputFunc)(outputStream, ") def\n", 6);
778 getString(dict.ordering, buf);
779 (*outputFunc)(outputStream, " /Ordering (", 13);
780 (*outputFunc)(outputStream, buf, strlen(buf));
781 (*outputFunc)(outputStream, ") def\n", 6);
783 (*outputFunc)(outputStream, " /Registry (Adobe) def\n", 24);
784 (*outputFunc)(outputStream, " /Ordering (Identity) def\n", 27);
786 sprintf(buf, " /Supplement %d def\n", dict.supplement);
787 (*outputFunc)(outputStream, buf, strlen(buf));
788 (*outputFunc)(outputStream, "end def\n", 8);
789 sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n",
790 dict.fontMatrix[0], dict.fontMatrix[1], dict.fontMatrix[2],
791 dict.fontMatrix[3], dict.fontMatrix[4], dict.fontMatrix[5]);
792 (*outputFunc)(outputStream, buf, strlen(buf));
793 sprintf(buf, "/FontBBox [%g %g %g %g] def\n",
794 dict.fontBBox[0], dict.fontBBox[1],
795 dict.fontBBox[2], dict.fontBBox[3]);
796 (*outputFunc)(outputStream, buf, strlen(buf));
797 (*outputFunc)(outputStream, "/FontInfo 1 dict dup begin\n", 27);
798 (*outputFunc)(outputStream, " /FSType 8 def\n", 16);
799 (*outputFunc)(outputStream, "end def\n", 8);
801 // CIDFont-specific entries
802 sprintf(buf, "/CIDCount %d def\n", nCIDs);
803 (*outputFunc)(outputStream, buf, strlen(buf));
804 (*outputFunc)(outputStream, "/FDBytes 1 def\n", 15);
805 sprintf(buf, "/GDBytes %d def\n", gdBytes);
806 (*outputFunc)(outputStream, buf, strlen(buf));
807 (*outputFunc)(outputStream, "/CIDMapOffset 0 def\n", 20);
808 if (dict.paintType != 0) {
809 sprintf(buf, "/PaintType %d def\n", dict.paintType);
810 (*outputFunc)(outputStream, buf, strlen(buf));
811 sprintf(buf, "/StrokeWidth %g def\n", dict.strokeWidth);
812 (*outputFunc)(outputStream, buf, strlen(buf));
816 sprintf(buf, "/FDArray %d array\n", nFDs);
817 (*outputFunc)(outputStream, buf, strlen(buf));
818 for (i = 0; i < nFDs; ++i) {
819 sprintf(buf, "dup %d 10 dict begin\n", i);
820 (*outputFunc)(outputStream, buf, strlen(buf));
821 (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
822 (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
823 sprintf(buf, "/PaintType %d def\n", dict.paintType);
824 (*outputFunc)(outputStream, buf, strlen(buf));
825 (*outputFunc)(outputStream, "/Private 32 dict begin\n", 23);
826 (*outputFunc)(outputStream, privateDicts[i].dictData->getCString(),
827 privateDicts[i].dictData->getLength());
828 (*outputFunc)(outputStream, "currentdict end def\n", 20);
829 (*outputFunc)(outputStream, "currentdict end put\n", 20);
831 (*outputFunc)(outputStream, "def\n", 4);
833 //~ need to deal with subrs
835 // start the binary section
836 offset = (nCIDs + 1) * (1 + gdBytes);
837 sprintf(buf, "(Hex) %d StartData\n",
838 offset + charStrings->getLength());
839 (*outputFunc)(outputStream, buf, strlen(buf));
841 // write the charstring offset (CIDMap) table
842 for (i = 0; i <= nCIDs; i += 6) {
843 for (j = 0; j < 6 && i+j <= nCIDs; ++j) {
844 if (i+j < nCIDs && cidMap[i+j] >= 0) {
845 buf[0] = (char)fdSelect[cidMap[i+j]];
849 n = offset + charStringOffsets[i+j];
850 for (k = gdBytes; k >= 1; --k) {
851 buf[k] = (char)(n & 0xff);
854 for (k = 0; k <= gdBytes; ++k) {
855 sprintf(buf2, "%02x", buf[k] & 0xff);
856 (*outputFunc)(outputStream, buf2, 2);
859 (*outputFunc)(outputStream, "\n", 1);
862 // write the charstring data
863 n = charStrings->getLength();
864 for (i = 0; i < n; i += 32) {
865 for (j = 0; j < 32 && i+j < n; ++j) {
866 sprintf(buf, "%02x", charStrings->getChar(i+j) & 0xff);
867 (*outputFunc)(outputStream, buf, strlen(buf));
870 (*outputFunc)(outputStream, ">", 1);
872 (*outputFunc)(outputStream, "\n", 1);
875 for (i = 0; i < nFDs; ++i) {
876 delete privateDicts[i].dictData;
881 gfree(charStringOffsets);
886 void Type1CFontFile::convertToType0(char *psName,
887 FontFileOutputFunc outputFuncA,
888 void *outputStreamA) {
890 Type1CPrivateDict *privateDicts;
894 Guchar *charStringsIdxPtr, *fdArrayIdx, *idxPtr0, *idxPtr1, *ptr;
897 int nGlyphs, nCIDs, nFDs;
898 int fdSelectFmt, nRanges, gid0, gid1, fd;
904 outputFunc = outputFuncA;
905 outputStream = outputStreamA;
907 // read top dict (first font only)
910 // read the FDArray dictionaries and Private dictionaries
911 if (dict.fdArrayOffset == 0) {
913 privateDicts = (Type1CPrivateDict *)
914 gmalloc(nFDs * sizeof(Type1CPrivateDict));
915 privateDicts[0].dictData = new GString();
916 privateDicts[0].subrsOffset = 0;
917 privateDicts[0].defaultWidthX = 0;
918 privateDicts[0].defaultWidthXFP = gFalse;
919 privateDicts[0].nominalWidthX = 0;
920 privateDicts[0].nominalWidthXFP = gFalse;
922 fdArrayIdx = (Guchar *)file + dict.fdArrayOffset;
923 nFDs = getIndexLen(fdArrayIdx);
924 privateDicts = (Type1CPrivateDict *)
925 gmalloc(nFDs * sizeof(Type1CPrivateDict));
926 idxPtr1 = getIndexValPtr(fdArrayIdx, 0);
927 for (i = 0; i < nFDs; ++i) {
928 privateDicts[i].dictData = NULL;
930 idxPtr1 = getIndexValPtr(fdArrayIdx, i + 1);
933 while (ptr < idxPtr1) {
934 if (*ptr <= 27 || *ptr == 31) {
937 key = (key << 8) | *ptr++;
940 readPrivateDict(&privateDicts[i], (int)op[1], (int)op[0]);
944 x = getNum(&ptr, &isFP);
951 if (!privateDicts[i].dictData) {
952 privateDicts[i].dictData = new GString();
953 privateDicts[i].subrsOffset = 0;
954 privateDicts[i].defaultWidthX = 0;
955 privateDicts[i].defaultWidthXFP = gFalse;
956 privateDicts[i].nominalWidthX = 0;
957 privateDicts[i].nominalWidthXFP = gFalse;
962 // get the glyph count
963 charStringsIdxPtr = (Guchar *)file + dict.charStrings;
964 nGlyphs = getIndexLen(charStringsIdxPtr);
966 // read the FDSelect table
967 fdSelect = (Guchar *)gmalloc(nGlyphs);
968 if (dict.fdSelectOffset == 0) {
969 for (i = 0; i < nGlyphs; ++i) {
973 ptr = (Guchar *)file + dict.fdSelectOffset;
974 fdSelectFmt = *ptr++;
975 if (fdSelectFmt == 0) {
976 memcpy(fdSelect, ptr, nGlyphs);
977 } else if (fdSelectFmt == 3) {
978 nRanges = getWord(ptr, 2);
980 gid0 = getWord(ptr, 2);
982 for (i = 1; i <= nRanges; ++i) {
984 gid1 = getWord(ptr, 2);
986 for (j = gid0; j < gid1; ++j) {
992 error(-1, "Unknown FDSelect table format in CID font");
993 for (i = 0; i < nGlyphs; ++i) {
999 // read the charset, compute the CID-to-GID mapping
1000 charset = readCharset(dict.charset, nGlyphs);
1002 for (i = 0; i < nGlyphs; ++i) {
1003 if (charset[i] >= nCIDs) {
1004 nCIDs = charset[i] + 1;
1007 cidMap = (int *)gmalloc(nCIDs * sizeof(int));
1008 for (i = 0; i < nCIDs; ++i) {
1011 for (i = 0; i < nGlyphs; ++i) {
1012 cidMap[charset[i]] = i;
1015 // write the descendant Type 1 fonts
1016 for (i = 0; i < nCIDs; i += 256) {
1018 //~ this assumes that all CIDs in this block have the same FD --
1019 //~ to handle multiple FDs correctly, need to somehow divide the
1022 for (j = 0; j < 256 && i+j < nCIDs; ++j) {
1023 if (cidMap[i+j] >= 0) {
1024 fd = fdSelect[cidMap[i+j]];
1029 // font dictionary (unencrypted section)
1030 (*outputFunc)(outputStream, "16 dict begin\n", 14);
1031 (*outputFunc)(outputStream, "/FontName /", 11);
1032 (*outputFunc)(outputStream, psName, strlen(psName));
1033 sprintf(buf, "_%02x def\n", i >> 8);
1034 (*outputFunc)(outputStream, buf, strlen(buf));
1035 (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
1036 sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n",
1037 dict.fontMatrix[0], dict.fontMatrix[1], dict.fontMatrix[2],
1038 dict.fontMatrix[3], dict.fontMatrix[4], dict.fontMatrix[5]);
1039 (*outputFunc)(outputStream, buf, strlen(buf));
1040 sprintf(buf, "/FontBBox [%g %g %g %g] def\n",
1041 dict.fontBBox[0], dict.fontBBox[1],
1042 dict.fontBBox[2], dict.fontBBox[3]);
1043 (*outputFunc)(outputStream, buf, strlen(buf));
1044 sprintf(buf, "/PaintType %d def\n", dict.paintType);
1045 (*outputFunc)(outputStream, buf, strlen(buf));
1046 if (dict.paintType != 0) {
1047 sprintf(buf, "/StrokeWidth %g def\n", dict.strokeWidth);
1048 (*outputFunc)(outputStream, buf, strlen(buf));
1050 (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
1051 for (j = 0; j < 256 && i+j < nCIDs; ++j) {
1052 sprintf(buf, "dup %d /c%02x put\n", j, j);
1053 (*outputFunc)(outputStream, buf, strlen(buf));
1055 (*outputFunc)(outputStream, "readonly def\n", 13);
1056 (*outputFunc)(outputStream, "currentdict end\n", 16);
1058 // start the binary section
1059 (*outputFunc)(outputStream, "currentfile eexec\n", 18);
1063 // start the private dictionary
1064 eexecWrite("\x83\xca\x73\xd5");
1065 eexecWrite("dup /Private 32 dict dup begin\n");
1066 eexecWrite("/RD {string currentfile exch readstring pop} executeonly def\n");
1067 eexecWrite("/ND {noaccess def} executeonly def\n");
1068 eexecWrite("/NP {noaccess put} executeonly def\n");
1069 eexecWrite("/MinFeature {16 16} ND\n");
1070 eexecWrite(privateDicts[fd].dictData->getCString());
1071 defaultWidthX = privateDicts[fd].defaultWidthX;
1072 defaultWidthXFP = privateDicts[fd].defaultWidthXFP;
1073 nominalWidthX = privateDicts[fd].nominalWidthX;
1074 nominalWidthXFP = privateDicts[fd].nominalWidthXFP;
1076 // start the CharStrings
1077 sprintf(eBuf, "2 index /CharStrings 256 dict dup begin\n");
1080 // write the .notdef CharString
1081 idxPtr0 = getIndexValPtr(charStringsIdxPtr, 0);
1082 idxPtr1 = getIndexValPtr(charStringsIdxPtr, 1);
1083 n = idxPtr1 - idxPtr0;
1084 eexecCvtGlyph(".notdef", idxPtr0, n);
1086 // write the CharStrings
1087 for (j = 0; j < 256 && i+j < nCIDs; ++j) {
1088 if (cidMap[i+j] >= 0) {
1089 idxPtr0 = getIndexValPtr(charStringsIdxPtr, cidMap[i+j]);
1090 idxPtr1 = getIndexValPtr(charStringsIdxPtr, cidMap[i+j]+1);
1091 n = idxPtr1 - idxPtr0;
1092 sprintf(buf, "c%02x", j);
1093 eexecCvtGlyph(buf, idxPtr0, n);
1096 eexecWrite("end\n");
1097 eexecWrite("end\n");
1098 eexecWrite("readonly put\n");
1099 eexecWrite("noaccess put\n");
1100 eexecWrite("dup /FontName get exch definefont pop\n");
1101 eexecWrite("mark currentfile closefile\n");
1105 (*outputFunc)(outputStream, "\n", 1);
1107 for (j = 0; j < 8; ++j) {
1108 (*outputFunc)(outputStream, "0000000000000000000000000000000000000000000000000000000000000000\n", 65);
1110 (*outputFunc)(outputStream, "cleartomark\n", 12);
1113 // write the Type 0 parent font
1114 (*outputFunc)(outputStream, "16 dict begin\n", 14);
1115 (*outputFunc)(outputStream, "/FontName /", 11);
1116 (*outputFunc)(outputStream, psName, strlen(psName));
1117 (*outputFunc)(outputStream, " def\n", 5);
1118 (*outputFunc)(outputStream, "/FontType 0 def\n", 16);
1119 (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
1120 (*outputFunc)(outputStream, "/FMapType 2 def\n", 16);
1121 (*outputFunc)(outputStream, "/Encoding [\n", 12);
1122 for (i = 0; i < nCIDs; i += 256) {
1123 sprintf(buf, "%d\n", i >> 8);
1124 (*outputFunc)(outputStream, buf, strlen(buf));
1126 (*outputFunc)(outputStream, "] def\n", 6);
1127 (*outputFunc)(outputStream, "/FDepVector [\n", 14);
1128 for (i = 0; i < nCIDs; i += 256) {
1129 (*outputFunc)(outputStream, "/", 1);
1130 (*outputFunc)(outputStream, psName, strlen(psName));
1131 sprintf(buf, "_%02x findfont\n", i >> 8);
1132 (*outputFunc)(outputStream, buf, strlen(buf));
1134 (*outputFunc)(outputStream, "] def\n", 6);
1135 (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
1138 for (i = 0; i < nFDs; ++i) {
1139 delete privateDicts[i].dictData;
1141 gfree(privateDicts);
1147 void Type1CFontFile::readTopDict(Type1CTopDict *dict) {
1148 Guchar *idxPtr0, *idxPtr1, *ptr;
1154 idxPtr0 = getIndexValPtr(topDictIdxPtr, 0);
1155 idxPtr1 = getIndexValPtr(topDictIdxPtr, 1);
1158 dict->copyright = 0;
1160 dict->familyName = 0;
1162 dict->isFixedPitch = 0;
1163 dict->italicAngle = 0;
1164 dict->underlinePosition = -100;
1165 dict->underlineThickness = 50;
1166 dict->paintType = 0;
1167 dict->charstringType = 2;
1168 dict->fontMatrix[0] = 0.001;
1169 dict->fontMatrix[1] = 0;
1170 dict->fontMatrix[2] = 0;
1171 dict->fontMatrix[3] = 0.001;
1172 dict->fontMatrix[4] = 0;
1173 dict->fontMatrix[5] = 0;
1175 dict->fontBBox[0] = 0;
1176 dict->fontBBox[1] = 0;
1177 dict->fontBBox[2] = 0;
1178 dict->fontBBox[3] = 0;
1179 dict->strokeWidth = 0;
1182 dict->charStrings = 0;
1183 dict->privateSize = 0;
1184 dict->privateOffset = 0;
1187 dict->supplement = 0;
1188 dict->fdArrayOffset = 0;
1189 dict->fdSelectOffset = 0;
1192 while (ptr < idxPtr1) {
1193 if (*ptr <= 27 || *ptr == 31) {
1196 key = (key << 8) | *ptr++;
1199 case 0x0000: dict->version = (int)op[0]; break;
1200 case 0x0001: dict->notice = (int)op[0]; break;
1201 case 0x0c00: dict->copyright = (int)op[0]; break;
1202 case 0x0002: dict->fullName = (int)op[0]; break;
1203 case 0x0003: dict->familyName = (int)op[0]; break;
1204 case 0x0004: dict->weight = (int)op[0]; break;
1205 case 0x0c01: dict->isFixedPitch = (int)op[0]; break;
1206 case 0x0c02: dict->italicAngle = op[0]; break;
1207 case 0x0c03: dict->underlinePosition = op[0]; break;
1208 case 0x0c04: dict->underlineThickness = op[0]; break;
1209 case 0x0c05: dict->paintType = (int)op[0]; break;
1210 case 0x0c06: dict->charstringType = (int)op[0]; break;
1211 case 0x0c07: dict->fontMatrix[0] = op[0];
1212 dict->fontMatrix[1] = op[1];
1213 dict->fontMatrix[2] = op[2];
1214 dict->fontMatrix[3] = op[3];
1215 dict->fontMatrix[4] = op[4];
1216 dict->fontMatrix[5] = op[5]; break;
1217 case 0x000d: dict->uniqueID = (int)op[0]; break;
1218 case 0x0005: dict->fontBBox[0] = op[0];
1219 dict->fontBBox[1] = op[1];
1220 dict->fontBBox[2] = op[2];
1221 dict->fontBBox[3] = op[3]; break;
1222 case 0x0c08: dict->strokeWidth = op[0]; break;
1223 case 0x000f: dict->charset = (int)op[0]; break;
1224 case 0x0010: dict->encoding = (int)op[0]; break;
1225 case 0x0011: dict->charStrings = (int)op[0]; break;
1226 case 0x0012: dict->privateSize = (int)op[0];
1227 dict->privateOffset = (int)op[1]; break;
1228 case 0x0c1e: dict->registry = (int)op[0];
1229 dict->ordering = (int)op[1];
1230 dict->supplement = (int)op[2]; break;
1231 case 0x0c24: dict->fdArrayOffset = (int)op[0]; break;
1232 case 0x0c25: dict->fdSelectOffset = (int)op[0]; break;
1236 x = getNum(&ptr, &isFP);
1245 void Type1CFontFile::readPrivateDict(Type1CPrivateDict *privateDict,
1246 int offset, int size) {
1247 Guchar *idxPtr0, *idxPtr1, *ptr;
1254 privateDict->dictData = new GString();
1255 privateDict->subrsOffset = 0;
1256 privateDict->defaultWidthX = 0;
1257 privateDict->defaultWidthXFP = gFalse;
1258 privateDict->nominalWidthX = 0;
1259 privateDict->nominalWidthXFP = gFalse;
1260 idxPtr0 = (Guchar *)file + offset;
1261 idxPtr1 = idxPtr0 + size;
1264 while (ptr < idxPtr1) {
1265 if (*ptr <= 27 || *ptr == 31) {
1268 key = (key << 8) | *ptr++;
1272 getDeltaInt(eBuf, "BlueValues", op, i);
1273 privateDict->dictData->append(eBuf);
1276 getDeltaInt(eBuf, "OtherBlues", op, i);
1277 privateDict->dictData->append(eBuf);
1280 getDeltaInt(eBuf, "FamilyBlues", op, i);
1281 privateDict->dictData->append(eBuf);
1284 getDeltaInt(eBuf, "FamilyOtherBlues", op, i);
1285 privateDict->dictData->append(eBuf);
1288 sprintf(eBuf, "/BlueScale %g def\n", op[0]);
1289 privateDict->dictData->append(eBuf);
1292 sprintf(eBuf, "/BlueShift %d def\n", (int)op[0]);
1293 privateDict->dictData->append(eBuf);
1296 sprintf(eBuf, "/BlueFuzz %d def\n", (int)op[0]);
1297 privateDict->dictData->append(eBuf);
1300 sprintf(eBuf, "/StdHW [%g] def\n", op[0]);
1301 privateDict->dictData->append(eBuf);
1304 sprintf(eBuf, "/StdVW [%g] def\n", op[0]);
1305 privateDict->dictData->append(eBuf);
1308 getDeltaReal(eBuf, "StemSnapH", op, i);
1309 privateDict->dictData->append(eBuf);
1312 getDeltaReal(eBuf, "StemSnapV", op, i);
1313 privateDict->dictData->append(eBuf);
1316 sprintf(eBuf, "/ForceBold %s def\n", op[0] ? "true" : "false");
1317 privateDict->dictData->append(eBuf);
1320 sprintf(eBuf, "/ForceBoldThreshold %g def\n", op[0]);
1321 privateDict->dictData->append(eBuf);
1324 sprintf(eBuf, "/LanguageGroup %d def\n", (int)op[0]);
1325 privateDict->dictData->append(eBuf);
1328 sprintf(eBuf, "/ExpansionFactor %g def\n", op[0]);
1329 privateDict->dictData->append(eBuf);
1332 error(-1, "Got Type 1C InitialRandomSeed");
1335 privateDict->subrsOffset = (int)op[0];
1338 privateDict->defaultWidthX = op[0];
1339 privateDict->defaultWidthXFP = fp[0];
1342 privateDict->nominalWidthX = op[0];
1343 privateDict->nominalWidthXFP = fp[0];
1346 error(-1, "Unknown Type 1C private dict entry %04x", key);
1351 x = getNum(&ptr, &isFP);
1360 Gushort *Type1CFontFile::readCharset(int charset, int nGlyphs) {
1361 Gushort *glyphNames;
1363 int charsetFormat, c;
1367 glyphNames = type1CISOAdobeCharset;
1368 } else if (charset == 1) {
1369 glyphNames = type1CExpertCharset;
1370 } else if (charset == 2) {
1371 glyphNames = type1CExpertSubsetCharset;
1373 glyphNames = (Gushort *)gmalloc(nGlyphs * sizeof(Gushort));
1375 ptr = (Guchar *)file + charset;
1376 charsetFormat = *ptr++;
1377 if (charsetFormat == 0) {
1378 for (i = 1; i < nGlyphs; ++i) {
1379 glyphNames[i] = getWord(ptr, 2);
1382 } else if (charsetFormat == 1) {
1384 while (i < nGlyphs) {
1385 c = getWord(ptr, 2);
1388 for (j = 0; j <= nLeft && i < nGlyphs; ++j) {
1389 glyphNames[i++] = c++;
1392 } else if (charsetFormat == 2) {
1394 while (i < nGlyphs) {
1395 c = getWord(ptr, 2);
1397 nLeft = getWord(ptr, 2);
1399 for (j = 0; j <= nLeft && i < nGlyphs; ++j) {
1400 glyphNames[i++] = c++;
1408 void Type1CFontFile::eexecWrite(char *s) {
1412 for (p = (Guchar *)s; *p; ++p) {
1414 r1 = (x + r1) * 52845 + 22719;
1415 (*outputFunc)(outputStream, &hexChars[x >> 4], 1);
1416 (*outputFunc)(outputStream, &hexChars[x & 0x0f], 1);
1419 (*outputFunc)(outputStream, "\n", 1);
1425 void Type1CFontFile::eexecCvtGlyph(char *glyphName, Guchar *s, int n) {
1429 sprintf(eBuf, "/%s %d RD ", glyphName, charBuf->getLength());
1431 eexecWriteCharstring((Guchar *)charBuf->getCString(), charBuf->getLength());
1432 eexecWrite(" ND\n");
1436 void Type1CFontFile::cvtGlyph(Guchar *s, int n) {
1439 GBool first = gTrue;
1446 charBuf = new GString();
1447 charBuf->append((char)73);
1448 charBuf->append((char)58);
1449 charBuf->append((char)147);
1450 charBuf->append((char)134);
1458 case 0: // dotsection (should be Type 1 only?)
1463 error(-1, "Wrong number of args (%d) to Type 2 hflex", nOps);
1465 eexecDumpNum(op[0], fp[0]);
1466 eexecDumpNum(0, gFalse);
1467 eexecDumpNum(op[1], fp[1]);
1468 eexecDumpNum(op[2], fp[2]);
1469 eexecDumpNum(op[3], fp[3]);
1470 eexecDumpNum(0, gFalse);
1472 eexecDumpNum(op[4], fp[4]);
1473 eexecDumpNum(0, gFalse);
1474 eexecDumpNum(op[5], fp[5]);
1475 eexecDumpNum(-op[2], fp[2]);
1476 eexecDumpNum(op[6], fp[6]);
1477 eexecDumpNum(0, gFalse);
1482 error(-1, "Wrong number of args (%d) to Type 2 flex", nOps);
1484 eexecDumpNum(op[0], fp[0]);
1485 eexecDumpNum(op[1], fp[1]);
1486 eexecDumpNum(op[2], fp[2]);
1487 eexecDumpNum(op[3], fp[3]);
1488 eexecDumpNum(op[4], fp[4]);
1489 eexecDumpNum(op[5], fp[5]);
1491 eexecDumpNum(op[6], fp[6]);
1492 eexecDumpNum(op[7], fp[7]);
1493 eexecDumpNum(op[8], fp[8]);
1494 eexecDumpNum(op[9], fp[9]);
1495 eexecDumpNum(op[10], fp[10]);
1496 eexecDumpNum(op[11], fp[11]);
1501 error(-1, "Wrong number of args (%d) to Type 2 hflex1", nOps);
1503 eexecDumpNum(op[0], fp[0]);
1504 eexecDumpNum(op[1], fp[1]);
1505 eexecDumpNum(op[2], fp[2]);
1506 eexecDumpNum(op[3], fp[3]);
1507 eexecDumpNum(op[4], fp[4]);
1508 eexecDumpNum(0, gFalse);
1510 eexecDumpNum(op[5], fp[5]);
1511 eexecDumpNum(0, gFalse);
1512 eexecDumpNum(op[6], fp[6]);
1513 eexecDumpNum(op[7], fp[7]);
1514 eexecDumpNum(op[8], fp[8]);
1515 eexecDumpNum(-(op[1] + op[3] + op[7]), fp[1] | fp[3] | fp[7]);
1520 error(-1, "Wrong number of args (%d) to Type 2 flex1", nOps);
1522 eexecDumpNum(op[0], fp[0]);
1523 eexecDumpNum(op[1], fp[1]);
1524 eexecDumpNum(op[2], fp[2]);
1525 eexecDumpNum(op[3], fp[3]);
1526 eexecDumpNum(op[4], fp[4]);
1527 eexecDumpNum(op[5], fp[5]);
1529 eexecDumpNum(op[6], fp[6]);
1530 eexecDumpNum(op[7], fp[7]);
1531 eexecDumpNum(op[8], fp[8]);
1532 eexecDumpNum(op[9], fp[9]);
1533 dx = op[0] + op[2] + op[4] + op[6] + op[8];
1534 dy = op[1] + op[3] + op[5] + op[7] + op[9];
1535 if (fabs(dx) > fabs(dy)) {
1536 eexecDumpNum(op[10], fp[10]);
1537 eexecDumpNum(-dy, fp[1] | fp[3] | fp[5] | fp[7] | fp[9]);
1539 eexecDumpNum(-dx, fp[0] | fp[2] | fp[4] | fp[6] | fp[8]);
1540 eexecDumpNum(op[10], fp[10]);
1566 error(-1, "Unimplemented Type 2 charstring op: 12.%d", s[i+1]);
1569 error(-1, "Illegal Type 2 charstring op: 12.%d", s[i+1]);
1574 } else if (s[i] == 19) { // hintmask
1577 cvtGlyphWidth(nOps == 1);
1582 error(-1, "Wrong number of args (%d) to Type 2 hintmask/vstemhm",
1587 i += 1 + ((nHints + 7) >> 3);
1589 } else if (s[i] == 20) { // cntrmask
1592 cvtGlyphWidth(nOps == 1);
1597 error(-1, "Wrong number of args (%d) to Type 2 cntrmask/vstemhm",
1602 i += 1 + ((nHints + 7) >> 3);
1604 } else if (s[i] == 28) {
1605 x = (s[i+1] << 8) + s[i+2];
1614 } else if (s[i] <= 31) {
1618 cvtGlyphWidth(nOps == 2);
1622 error(-1, "Wrong number of args (%d) to Type 2 vmoveto", nOps);
1624 eexecDumpNum(op[0], fp[0]);
1628 if (nOps < 2 || nOps % 2 != 0) {
1629 error(-1, "Wrong number of args (%d) to Type 2 rlineto", nOps);
1631 for (k = 0; k < nOps; k += 2) {
1632 eexecDumpNum(op[k], fp[k]);
1633 eexecDumpNum(op[k+1], fp[k+1]);
1639 error(-1, "Wrong number of args (%d) to Type 2 hlineto", nOps);
1641 for (k = 0; k < nOps; ++k) {
1642 eexecDumpNum(op[k], fp[k]);
1643 eexecDumpOp1((k & 1) ? 7 : 6);
1648 error(-1, "Wrong number of args (%d) to Type 2 vlineto", nOps);
1650 for (k = 0; k < nOps; ++k) {
1651 eexecDumpNum(op[k], fp[k]);
1652 eexecDumpOp1((k & 1) ? 6 : 7);
1655 case 8: // rrcurveto
1656 if (nOps < 6 || nOps % 6 != 0) {
1657 error(-1, "Wrong number of args (%d) to Type 2 rrcurveto", nOps);
1659 for (k = 0; k < nOps; k += 6) {
1660 eexecDumpNum(op[k], fp[k]);
1661 eexecDumpNum(op[k+1], fp[k+1]);
1662 eexecDumpNum(op[k+2], fp[k+2]);
1663 eexecDumpNum(op[k+3], fp[k+3]);
1664 eexecDumpNum(op[k+4], fp[k+4]);
1665 eexecDumpNum(op[k+5], fp[k+5]);
1669 case 14: // endchar / seac
1671 cvtGlyphWidth(nOps == 1 || nOps == 5);
1676 eexecDumpNum(op[0], fp[0]);
1677 eexecDumpNum(op[1], fp[1]);
1678 eexecDumpNum(op[2], fp[2]);
1679 eexecDumpNum(op[3], fp[3]);
1681 } else if (nOps == 0) {
1684 error(-1, "Wrong number of args (%d) to Type 2 endchar", nOps);
1689 cvtGlyphWidth(nOps == 3);
1693 error(-1, "Wrong number of args (%d) to Type 2 rmoveto", nOps);
1695 eexecDumpNum(op[0], fp[0]);
1696 eexecDumpNum(op[1], fp[1]);
1701 cvtGlyphWidth(nOps == 2);
1705 error(-1, "Wrong number of args (%d) to Type 2 hmoveto", nOps);
1707 eexecDumpNum(op[0], fp[0]);
1710 case 24: // rcurveline
1711 if (nOps < 8 || (nOps - 2) % 6 != 0) {
1712 error(-1, "Wrong number of args (%d) to Type 2 rcurveline", nOps);
1714 for (k = 0; k < nOps - 2; k += 6) {
1715 eexecDumpNum(op[k], fp[k]);
1716 eexecDumpNum(op[k+1], fp[k+1]);
1717 eexecDumpNum(op[k+2], fp[k+2]);
1718 eexecDumpNum(op[k+3], fp[k+3]);
1719 eexecDumpNum(op[k+4], fp[k+4]);
1720 eexecDumpNum(op[k+5], fp[k+5]);
1723 eexecDumpNum(op[k], fp[k]);
1724 eexecDumpNum(op[k+1], fp[k]);
1727 case 25: // rlinecurve
1728 if (nOps < 8 || (nOps - 6) % 2 != 0) {
1729 error(-1, "Wrong number of args (%d) to Type 2 rlinecurve", nOps);
1731 for (k = 0; k < nOps - 6; k += 2) {
1732 eexecDumpNum(op[k], fp[k]);
1733 eexecDumpNum(op[k+1], fp[k]);
1736 eexecDumpNum(op[k], fp[k]);
1737 eexecDumpNum(op[k+1], fp[k+1]);
1738 eexecDumpNum(op[k+2], fp[k+2]);
1739 eexecDumpNum(op[k+3], fp[k+3]);
1740 eexecDumpNum(op[k+4], fp[k+4]);
1741 eexecDumpNum(op[k+5], fp[k+5]);
1744 case 26: // vvcurveto
1745 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
1746 error(-1, "Wrong number of args (%d) to Type 2 vvcurveto", nOps);
1748 if (nOps % 2 == 1) {
1749 eexecDumpNum(op[0], fp[0]);
1750 eexecDumpNum(op[1], fp[1]);
1751 eexecDumpNum(op[2], fp[2]);
1752 eexecDumpNum(op[3], fp[3]);
1753 eexecDumpNum(0, gFalse);
1754 eexecDumpNum(op[4], fp[4]);
1760 for (; k < nOps; k += 4) {
1761 eexecDumpNum(0, gFalse);
1762 eexecDumpNum(op[k], fp[k]);
1763 eexecDumpNum(op[k+1], fp[k+1]);
1764 eexecDumpNum(op[k+2], fp[k+2]);
1765 eexecDumpNum(0, gFalse);
1766 eexecDumpNum(op[k+3], fp[k+3]);
1770 case 27: // hhcurveto
1771 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
1772 error(-1, "Wrong number of args (%d) to Type 2 hhcurveto", nOps);
1774 if (nOps % 2 == 1) {
1775 eexecDumpNum(op[1], fp[1]);
1776 eexecDumpNum(op[0], fp[0]);
1777 eexecDumpNum(op[2], fp[2]);
1778 eexecDumpNum(op[3], fp[3]);
1779 eexecDumpNum(op[4], fp[4]);
1780 eexecDumpNum(0, gFalse);
1786 for (; k < nOps; k += 4) {
1787 eexecDumpNum(op[k], fp[k]);
1788 eexecDumpNum(0, gFalse);
1789 eexecDumpNum(op[k+1], fp[k+1]);
1790 eexecDumpNum(op[k+2], fp[k+2]);
1791 eexecDumpNum(op[k+3], fp[k+3]);
1792 eexecDumpNum(0, gFalse);
1796 case 30: // vhcurveto
1797 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
1798 error(-1, "Wrong number of args (%d) to Type 2 vhcurveto", nOps);
1800 for (k = 0; k < nOps && k != nOps-5; k += 4) {
1802 eexecDumpNum(op[k], fp[k]);
1803 eexecDumpNum(op[k+1], fp[k+1]);
1804 eexecDumpNum(op[k+2], fp[k+2]);
1805 eexecDumpNum(op[k+3], fp[k+3]);
1808 eexecDumpNum(op[k], fp[k]);
1809 eexecDumpNum(op[k+1], fp[k+1]);
1810 eexecDumpNum(op[k+2], fp[k+2]);
1811 eexecDumpNum(op[k+3], fp[k+3]);
1817 eexecDumpNum(0, gFalse);
1818 eexecDumpNum(op[k], fp[k]);
1819 eexecDumpNum(op[k+1], fp[k+1]);
1820 eexecDumpNum(op[k+2], fp[k+2]);
1821 eexecDumpNum(op[k+3], fp[k+3]);
1822 eexecDumpNum(op[k+4], fp[k+4]);
1824 eexecDumpNum(op[k], fp[k]);
1825 eexecDumpNum(0, gFalse);
1826 eexecDumpNum(op[k+1], fp[k+1]);
1827 eexecDumpNum(op[k+2], fp[k+2]);
1828 eexecDumpNum(op[k+4], fp[k+4]);
1829 eexecDumpNum(op[k+3], fp[k+3]);
1834 case 31: // hvcurveto
1835 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
1836 error(-1, "Wrong number of args (%d) to Type 2 hvcurveto", nOps);
1838 for (k = 0; k < nOps && k != nOps-5; k += 4) {
1840 eexecDumpNum(op[k], fp[k]);
1841 eexecDumpNum(op[k+1], fp[k+1]);
1842 eexecDumpNum(op[k+2], fp[k+2]);
1843 eexecDumpNum(op[k+3], fp[k+3]);
1846 eexecDumpNum(op[k], fp[k]);
1847 eexecDumpNum(op[k+1], fp[k+1]);
1848 eexecDumpNum(op[k+2], fp[k+2]);
1849 eexecDumpNum(op[k+3], fp[k+3]);
1855 eexecDumpNum(op[k], fp[k]);
1856 eexecDumpNum(0, gFalse);
1857 eexecDumpNum(op[k+1], fp[k+1]);
1858 eexecDumpNum(op[k+2], fp[k+2]);
1859 eexecDumpNum(op[k+4], fp[k+4]);
1860 eexecDumpNum(op[k+3], fp[k+3]);
1862 eexecDumpNum(0, gFalse);
1863 eexecDumpNum(op[k], fp[k]);
1864 eexecDumpNum(op[k+1], fp[k+1]);
1865 eexecDumpNum(op[k+2], fp[k+2]);
1866 eexecDumpNum(op[k+3], fp[k+3]);
1867 eexecDumpNum(op[k+4], fp[k+4]);
1874 cvtGlyphWidth(nOps & 1);
1878 error(-1, "Wrong number of args (%d) to Type 2 hstem", nOps);
1882 for (k = 0; k < nOps; k += 2) {
1884 d += op[k] + op[k+1];
1885 dFP |= fp[k] | fp[k+1];
1886 eexecDumpNum(d, dFP);
1887 eexecDumpNum(-op[k+1], fp[k+1]);
1891 eexecDumpNum(d, dFP);
1892 eexecDumpNum(op[k+1], fp[k+1]);
1902 cvtGlyphWidth(nOps & 1);
1906 error(-1, "Wrong number of args (%d) to Type 2 vstem", nOps);
1910 for (k = 0; k < nOps; k += 2) {
1912 d += op[k] + op[k+1];
1913 dFP |= fp[k] | fp[k+1];
1914 eexecDumpNum(d, dFP);
1915 eexecDumpNum(-op[k+1], fp[k+1]);
1919 eexecDumpNum(d, dFP);
1920 eexecDumpNum(op[k+1], fp[k+1]);
1931 cvtGlyphWidth(nOps & 1);
1935 error(-1, "Wrong number of args (%d) to Type 2 hstemhm", nOps);
1942 cvtGlyphWidth(nOps & 1);
1946 error(-1, "Wrong number of args (%d) to Type 2 vstemhm", nOps);
1950 case 10: // callsubr
1953 case 29: // callgsubr
1954 error(-1, "Unimplemented Type 2 charstring op: %d", s[i]);
1957 error(-1, "Illegal Type 2 charstring op: %d", s[i]);
1962 } else if (s[i] <= 246) {
1965 op[nOps++] = (int)s[i] - 139;
1968 } else if (s[i] <= 250) {
1971 op[nOps++] = (((int)s[i] - 247) << 8) + (int)s[i+1] + 108;
1974 } else if (s[i] <= 254) {
1977 op[nOps++] = -(((int)s[i] - 251) << 8) - (int)s[i+1] - 108;
1981 x = (s[i+1] << 24) | (s[i+2] << 16) | (s[i+3] << 8) | s[i+4];
1986 op[nOps++] = (double)x / 65536.0;
1992 // charstring encryption
1994 for (i = 0; i < charBuf->getLength(); ++i) {
1995 byte = charBuf->getChar(i) ^ (r2 >> 8);
1996 charBuf->setChar(i, byte);
1997 r2 = (byte + r2) * 52845 + 22719;
2001 void Type1CFontFile::cvtGlyphWidth(GBool useOp) {
2007 w = nominalWidthX + op[0];
2008 wFP = nominalWidthXFP | fp[0];
2009 for (i = 1; i < nOps; ++i) {
2016 wFP = defaultWidthXFP;
2018 eexecDumpNum(0, gFalse);
2019 eexecDumpNum(w, wFP);
2023 void Type1CFontFile::eexecDumpNum(double x, GBool fpA) {
2029 if (x >= -32768 && x < 32768) {
2030 y = (int)(x * 256.0);
2032 buf[1] = (Guchar)(y >> 24);
2033 buf[2] = (Guchar)(y >> 16);
2034 buf[3] = (Guchar)(y >> 8);
2045 error(-1, "Type 2 fixed point constant out of range");
2049 if (y >= -107 && y <= 107) {
2050 buf[0] = (Guchar)(y + 139);
2052 } else if (y > 107 && y <= 1131) {
2054 buf[0] = (Guchar)((y >> 8) + 247);
2055 buf[1] = (Guchar)(y & 0xff);
2057 } else if (y < -107 && y >= -1131) {
2059 buf[0] = (Guchar)((y >> 8) + 251);
2060 buf[1] = (Guchar)(y & 0xff);
2064 buf[1] = (Guchar)(y >> 24);
2065 buf[2] = (Guchar)(y >> 16);
2066 buf[3] = (Guchar)(y >> 8);
2071 charBuf->append((char *)buf, n);
2074 void Type1CFontFile::eexecDumpOp1(int opA) {
2075 charBuf->append((char)opA);
2078 void Type1CFontFile::eexecDumpOp2(int opA) {
2079 charBuf->append((char)12);
2080 charBuf->append((char)opA);
2083 void Type1CFontFile::eexecWriteCharstring(Guchar *s, int n) {
2088 for (i = 0; i < n; ++i) {
2089 x = s[i] ^ (r1 >> 8);
2090 r1 = (x + r1) * 52845 + 22719;
2091 (*outputFunc)(outputStream, &hexChars[x >> 4], 1);
2092 (*outputFunc)(outputStream, &hexChars[x & 0x0f], 1);
2095 (*outputFunc)(outputStream, "\n", 1);
2101 void Type1CFontFile::getDeltaInt(char *buf, char *key, double *opA,
2105 sprintf(buf, "/%s [", key);
2108 for (i = 0; i < n; ++i) {
2110 sprintf(buf, "%s%d", i > 0 ? " " : "", x);
2113 sprintf(buf, "] def\n");
2116 void Type1CFontFile::getDeltaReal(char *buf, char *key, double *opA,
2121 sprintf(buf, "/%s [", key);
2124 for (i = 0; i < n; ++i) {
2126 sprintf(buf, "%s%g", i > 0 ? " " : "", x);
2129 sprintf(buf, "] def\n");
2132 int Type1CFontFile::getIndexLen(Guchar *indexPtr) {
2133 return (int)getWord(indexPtr, 2);
2136 Guchar *Type1CFontFile::getIndexValPtr(Guchar *indexPtr, int i) {
2138 Guchar *idxStartPtr;
2140 n = (int)getWord(indexPtr, 2);
2141 offSize = indexPtr[2];
2142 idxStartPtr = indexPtr + 3 + (n + 1) * offSize - 1;
2143 return idxStartPtr + getWord(indexPtr + 3 + i * offSize, offSize);
2146 Guchar *Type1CFontFile::getIndexEnd(Guchar *indexPtr) {
2148 Guchar *idxStartPtr;
2150 n = (int)getWord(indexPtr, 2);
2151 offSize = indexPtr[2];
2152 idxStartPtr = indexPtr + 3 + (n + 1) * offSize - 1;
2153 return idxStartPtr + getWord(indexPtr + 3 + n * offSize, offSize);
2156 Guint Type1CFontFile::getWord(Guchar *ptr, int size) {
2161 for (i = 0; i < size; ++i) {
2162 x = (x << 8) + *ptr++;
2167 double Type1CFontFile::getNum(Guchar **ptr, GBool *isFP) {
2168 static char nybChars[16] = "0123456789.ee -";
2169 int b0, b, nyb0, nyb1;
2179 } else if (b0 == 28) {
2180 x = ((*ptr)[1] << 8) + (*ptr)[2];
2182 } else if (b0 == 29) {
2183 x = ((*ptr)[1] << 24) + ((*ptr)[2] << 16) + ((*ptr)[3] << 8) + (*ptr)[4];
2185 } else if (b0 == 30) {
2195 buf[i++] = nybChars[nyb0];
2208 buf[i++] = nybChars[nyb1];
2219 } else if (b0 == 31) {
2221 } else if (b0 < 247) {
2224 } else if (b0 < 251) {
2225 x = ((b0 - 247) << 8) + (*ptr)[1] + 108;
2228 x = -((b0 - 251) << 8) - (*ptr)[1] - 108;
2234 char *Type1CFontFile::getString(int sid, char *buf) {
2235 Guchar *idxPtr0, *idxPtr1;
2239 strcpy(buf, type1CStdStrings[sid]);
2242 idxPtr0 = getIndexValPtr(stringIdxPtr, sid);
2243 idxPtr1 = getIndexValPtr(stringIdxPtr, sid + 1);
2244 if ((n = idxPtr1 - idxPtr0) > 255) {
2247 strncpy(buf, (char *)idxPtr0, n);
2253 //------------------------------------------------------------------------
2255 //------------------------------------------------------------------------
2261 // character code = number used as an element of a text string
2263 // character name = glyph name = name for a particular glyph within a
2266 // glyph index = position (within some internal table in the font)
2267 // where the instructions to draw a particular glyph are
2273 // Type 1 fonts contain:
2275 // Encoding: array of glyph names, maps char codes to glyph names
2277 // Encoding[charCode] = charName
2279 // CharStrings: dictionary of instructions, keyed by character names,
2280 // maps character name to glyph data
2282 // CharStrings[charName] = glyphData
2287 // TrueType fonts contain:
2289 // 'cmap' table: mapping from character code to glyph index; there may
2290 // be multiple cmaps in a TrueType font
2292 // cmap[charCode] = glyphIdx
2294 // 'post' table: mapping from glyph index to glyph name
2296 // post[glyphIdx] = glyphName
2301 // Type 42 fonts contain:
2303 // Encoding: array of glyph names, maps char codes to glyph names
2305 // Encoding[charCode] = charName
2307 // CharStrings: dictionary of glyph indexes, keyed by character names,
2308 // maps character name to glyph index
2310 // CharStrings[charName] = glyphIdx
2313 struct TTFontTableHdr {
2321 char *tag; // 4-byte tag
2322 GBool required; // required by the TrueType spec?
2325 // TrueType tables to be embedded in Type 42 fonts.
2326 // NB: the table names must be in alphabetical order here.
2327 #define nT42Tables 11
2328 static T42Table t42Tables[nT42Tables] = {
2341 #define t42HeadTable 3
2342 #define t42LocaTable 6
2343 #define t42GlyfTable 2
2345 // Glyph names in some arbitrary standard that Apple uses for their
2347 static char *macGlyphNames[258] = {
2608 enum T42FontIndexMode {
2610 t42FontModeCharCode,
2611 t42FontModeCharCodeOffset,
2615 TrueTypeFontFile::TrueTypeFontFile(char *fileA, int lenA) {
2616 int pos, i, idx, n, length;
2617 Guint size, startPos, endPos;
2624 // read table directory
2625 nTables = getUShort(4);
2626 tableHdrs = (TTFontTableHdr *)gmalloc(nTables * sizeof(TTFontTableHdr));
2628 for (i = 0; i < nTables; ++i) {
2629 tableHdrs[i].tag[0] = getByte(pos+0);
2630 tableHdrs[i].tag[1] = getByte(pos+1);
2631 tableHdrs[i].tag[2] = getByte(pos+2);
2632 tableHdrs[i].tag[3] = getByte(pos+3);
2633 tableHdrs[i].checksum = getULong(pos+4);
2634 tableHdrs[i].offset = getULong(pos+8);
2635 tableHdrs[i].length = getULong(pos+12);
2639 // check for tables that are required by both the TrueType spec
2640 // and the Type 42 spec
2641 if (seekTable("head") < 0 ||
2642 seekTable("hhea") < 0 ||
2643 seekTable("loca") < 0 ||
2644 seekTable("maxp") < 0 ||
2645 seekTable("glyf") < 0 ||
2646 seekTable("hmtx") < 0) {
2647 error(-1, "TrueType font file is missing a required table");
2651 // some embedded TrueType fonts have an incorrect (too small) cmap
2653 idx = seekTableIdx("cmap");
2655 pos = tableHdrs[idx].offset;
2656 n = getUShort(pos + 2);
2657 size = (Guint)(4 + 8 * n);
2658 for (i = 0; i < n; ++i) {
2659 startPos = getULong(pos + 4 + 8*i + 4);
2660 length = getUShort(pos + startPos + 2);
2661 endPos = startPos + length;
2662 if (endPos > size) {
2666 if ((mungedCmapSize = size > tableHdrs[idx].length)) {
2667 #if 0 // don't bother printing this error message - it's too common
2668 error(-1, "Bad cmap table size in TrueType font");
2670 tableHdrs[idx].length = size;
2673 mungedCmapSize = gFalse;
2676 // read the 'head' table
2677 pos = seekTable("head");
2678 bbox[0] = getShort(pos + 36);
2679 bbox[1] = getShort(pos + 38);
2680 bbox[2] = getShort(pos + 40);
2681 bbox[3] = getShort(pos + 42);
2682 locaFmt = getShort(pos + 50);
2684 // read the 'maxp' table
2685 pos = seekTable("maxp");
2686 nGlyphs = getUShort(pos + 4);
2689 TrueTypeFontFile::~TrueTypeFontFile() {
2693 for (i = 0; i < 256; ++i) {
2701 char *TrueTypeFontFile::getName() {
2705 char **TrueTypeFontFile::getEncoding() {
2707 int nCmaps, cmapPlatform, cmapEncoding, cmapFmt;
2708 int cmapLen, cmapOffset, cmapFirst;
2709 int segCnt, segStart, segEnd, segDelta, segOffset;
2713 int stringIdx, stringPos, n;
2719 //----- construct the (char code) -> (glyph idx) mapping
2721 // map everything to the missing glyph
2722 for (i = 0; i < 256; ++i) {
2726 // look for the 'cmap' table
2727 if ((pos = seekTable("cmap")) >= 0) {
2728 nCmaps = getUShort(pos+2);
2730 // if the font has a Windows-symbol cmap, use it;
2731 // otherwise, use the first cmap in the table
2732 for (i = 0; i < nCmaps; ++i) {
2733 cmapPlatform = getUShort(pos + 4 + 8*i);
2734 cmapEncoding = getUShort(pos + 4 + 8*i + 2);
2735 if (cmapPlatform == 3 && cmapEncoding == 0) {
2741 cmapPlatform = getUShort(pos + 4);
2742 cmapEncoding = getUShort(pos + 4 + 2);
2744 pos += getULong(pos + 4 + 8*i + 4);
2747 cmapFmt = getUShort(pos);
2749 case 0: // byte encoding table (Apple standard)
2750 cmapLen = getUShort(pos + 2);
2751 for (i = 0; i < cmapLen && i < 256; ++i) {
2752 cmap[i] = getByte(pos + 6 + i);
2755 case 4: // segment mapping to delta values (Microsoft standard)
2756 if (cmapPlatform == 3 && cmapEncoding == 0) {
2757 // Windows-symbol uses char codes 0xf000 - 0xf0ff
2758 cmapOffset = 0xf000;
2762 segCnt = getUShort(pos + 6) / 2;
2763 for (i = 0; i < segCnt; ++i) {
2764 segEnd = getUShort(pos + 14 + 2*i);
2765 segStart = getUShort(pos + 16 + 2*segCnt + 2*i);
2766 segDelta = getUShort(pos + 16 + 4*segCnt + 2*i);
2767 segOffset = getUShort(pos + 16 + 6*segCnt + 2*i);
2768 if (segStart - cmapOffset <= 0xff &&
2769 segEnd - cmapOffset >= 0) {
2770 for (j = (segStart - cmapOffset >= 0) ? segStart : cmapOffset;
2771 j <= segEnd && j - cmapOffset <= 0xff;
2773 if (segOffset == 0) {
2774 k = (j + segDelta) & 0xffff;
2776 k = getUShort(pos + 16 + 6*segCnt + 2*i +
2777 segOffset + 2 * (j - segStart));
2779 k = (k + segDelta) & 0xffff;
2782 cmap[j - cmapOffset] = k;
2787 case 6: // trimmed table mapping
2788 cmapFirst = getUShort(pos + 6);
2789 cmapLen = getUShort(pos + 8);
2790 for (i = cmapFirst; i < 256 && i < cmapFirst + cmapLen; ++i) {
2791 cmap[i] = getUShort(pos + 10 + 2*i);
2795 error(-1, "Unimplemented cmap format (%d) in TrueType font file",
2801 //----- construct the (glyph idx) -> (glyph name) mapping
2802 //----- and compute the (char code) -> (glyph name) mapping
2804 encoding = (char **)gmalloc(256 * sizeof(char *));
2805 for (i = 0; i < 256; ++i) {
2809 if ((pos = seekTable("post")) >= 0) {
2810 fmt = getULong(pos);
2813 if (fmt == 0x00010000) {
2814 for (i = 0; i < 256; ++i) {
2815 j = (cmap[i] < 258) ? cmap[i] : 0;
2816 encoding[i] = copyString(macGlyphNames[j]);
2820 } else if (fmt == 0x00020000) {
2822 stringPos = pos + 34 + 2*nGlyphs;
2823 for (i = 0; i < 256; ++i) {
2824 if (cmap[i] < nGlyphs) {
2825 j = getUShort(pos + 34 + 2 * cmap[i]);
2827 encoding[i] = copyString(macGlyphNames[j]);
2830 if (j != stringIdx) {
2831 for (stringIdx = 0, stringPos = pos + 34 + 2*nGlyphs;
2833 ++stringIdx, stringPos += 1 + getByte(stringPos)) ;
2835 n = getByte(stringPos);
2836 s = new GString(file + stringPos + 1, n);
2837 encoding[i] = copyString(s->getCString());
2843 encoding[i] = copyString(macGlyphNames[0]);
2848 } else if (fmt == 0x000280000) {
2849 for (i = 0; i < 256; ++i) {
2850 if (cmap[i] < nGlyphs) {
2851 j = i + getChar(pos + 32 + cmap[i]);
2855 encoding[i] = copyString(macGlyphNames[j]);
2858 // Ugh, just assume the Apple glyph set
2860 for (i = 0; i < 256; ++i) {
2861 j = (cmap[i] < 258) ? cmap[i] : 0;
2862 encoding[i] = copyString(macGlyphNames[j]);
2866 // no "post" table: assume the Apple glyph set
2868 for (i = 0; i < 256; ++i) {
2869 j = (cmap[i] < 258) ? cmap[i] : 0;
2870 encoding[i] = copyString(macGlyphNames[j]);
2877 void TrueTypeFontFile::convertToType42(char *name, char **encodingA,
2878 CharCodeToUnicode *toUnicode,
2879 GBool pdfFontHasEncoding,
2880 FontFileOutputFunc outputFunc,
2881 void *outputStream) {
2885 sprintf(buf, "%%!PS-TrueTypeFont-%g\n", getFixed(0));
2886 (*outputFunc)(outputStream, buf, strlen(buf));
2888 // begin the font dictionary
2889 (*outputFunc)(outputStream, "10 dict begin\n", 14);
2890 (*outputFunc)(outputStream, "/FontName /", 11);
2891 (*outputFunc)(outputStream, name, strlen(name));
2892 (*outputFunc)(outputStream, " def\n", 5);
2893 (*outputFunc)(outputStream, "/FontType 42 def\n", 17);
2894 (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
2895 sprintf(buf, "/FontBBox [%d %d %d %d] def\n",
2896 bbox[0], bbox[1], bbox[2], bbox[3]);
2897 (*outputFunc)(outputStream, buf, strlen(buf));
2898 (*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
2900 // write the guts of the dictionary
2901 cvtEncoding(encodingA, pdfFontHasEncoding, outputFunc, outputStream);
2902 cvtCharStrings(encodingA, toUnicode, pdfFontHasEncoding,
2903 outputFunc, outputStream);
2904 cvtSfnts(outputFunc, outputStream, NULL);
2906 // end the dictionary and define the font
2907 (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
2910 void TrueTypeFontFile::convertToCIDType2(char *name, Gushort *cidMap,
2912 FontFileOutputFunc outputFunc,
2913 void *outputStream) {
2919 sprintf(buf, "%%!PS-TrueTypeFont-%g\n", getFixed(0));
2920 (*outputFunc)(outputStream, buf, strlen(buf));
2922 // begin the font dictionary
2923 (*outputFunc)(outputStream, "20 dict begin\n", 14);
2924 (*outputFunc)(outputStream, "/CIDFontName /", 14);
2925 (*outputFunc)(outputStream, name, strlen(name));
2926 (*outputFunc)(outputStream, " def\n", 5);
2927 (*outputFunc)(outputStream, "/CIDFontType 2 def\n", 19);
2928 (*outputFunc)(outputStream, "/FontType 42 def\n", 17);
2929 (*outputFunc)(outputStream, "/CIDSystemInfo 3 dict dup begin\n", 32);
2930 (*outputFunc)(outputStream, " /Registry (Adobe) def\n", 24);
2931 (*outputFunc)(outputStream, " /Ordering (Identity) def\n", 27);
2932 (*outputFunc)(outputStream, " /Supplement 0 def\n", 20);
2933 (*outputFunc)(outputStream, " end def\n", 10);
2934 (*outputFunc)(outputStream, "/GDBytes 2 def\n", 15);
2936 sprintf(buf, "/CIDCount %d def\n", nCIDs);
2937 (*outputFunc)(outputStream, buf, strlen(buf));
2938 if (nCIDs > 32767) {
2939 (*outputFunc)(outputStream, "/CIDMap [", 9);
2940 for (i = 0; i < nCIDs; i += 32768 - 16) {
2941 (*outputFunc)(outputStream, "<\n", 2);
2942 for (j = 0; j < 32768 - 16 && i+j < nCIDs; j += 16) {
2943 (*outputFunc)(outputStream, " ", 2);
2944 for (k = 0; k < 16 && i+j+k < nCIDs; ++k) {
2945 cid = cidMap[i+j+k];
2946 sprintf(buf, "%02x%02x", (cid >> 8) & 0xff, cid & 0xff);
2947 (*outputFunc)(outputStream, buf, strlen(buf));
2949 (*outputFunc)(outputStream, "\n", 1);
2951 (*outputFunc)(outputStream, " >", 3);
2953 (*outputFunc)(outputStream, "\n", 1);
2954 (*outputFunc)(outputStream, "] def\n", 6);
2956 (*outputFunc)(outputStream, "/CIDMap <\n", 10);
2957 for (i = 0; i < nCIDs; i += 16) {
2958 (*outputFunc)(outputStream, " ", 2);
2959 for (j = 0; j < 16 && i+j < nCIDs; ++j) {
2961 sprintf(buf, "%02x%02x", (cid >> 8) & 0xff, cid & 0xff);
2962 (*outputFunc)(outputStream, buf, strlen(buf));
2964 (*outputFunc)(outputStream, "\n", 1);
2966 (*outputFunc)(outputStream, "> def\n", 6);
2969 // direct mapping - just fill the string(s) with s[i]=i
2970 sprintf(buf, "/CIDCount %d def\n", nGlyphs);
2971 (*outputFunc)(outputStream, buf, strlen(buf));
2972 if (nGlyphs > 32767) {
2973 (*outputFunc)(outputStream, "/CIDMap [\n", 10);
2974 for (i = 0; i < nGlyphs; i += 32767) {
2975 j = nGlyphs - i < 32767 ? nGlyphs - i : 32767;
2976 sprintf(buf, " %d string 0 1 %d {\n", 2 * j, j - 1);
2977 (*outputFunc)(outputStream, buf, strlen(buf));
2978 sprintf(buf, " 2 copy dup 2 mul exch %d add -8 bitshift put\n", i);
2979 (*outputFunc)(outputStream, buf, strlen(buf));
2980 sprintf(buf, " 1 index exch dup 2 mul 1 add exch %d add"
2981 " 255 and put\n", i);
2982 (*outputFunc)(outputStream, buf, strlen(buf));
2983 (*outputFunc)(outputStream, " } for\n", 8);
2985 (*outputFunc)(outputStream, "] def\n", 6);
2987 sprintf(buf, "/CIDMap %d string\n", 2 * nGlyphs);
2988 (*outputFunc)(outputStream, buf, strlen(buf));
2989 sprintf(buf, " 0 1 %d {\n", nGlyphs - 1);
2990 (*outputFunc)(outputStream, buf, strlen(buf));
2991 (*outputFunc)(outputStream,
2992 " 2 copy dup 2 mul exch -8 bitshift put\n", 42);
2993 (*outputFunc)(outputStream,
2994 " 1 index exch dup 2 mul 1 add exch 255 and put\n", 50);
2995 (*outputFunc)(outputStream, " } for\n", 8);
2996 (*outputFunc)(outputStream, "def\n", 4);
2999 (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
3000 sprintf(buf, "/FontBBox [%d %d %d %d] def\n",
3001 bbox[0], bbox[1], bbox[2], bbox[3]);
3002 (*outputFunc)(outputStream, buf, strlen(buf));
3003 (*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
3004 (*outputFunc)(outputStream, "/Encoding [] readonly def\n", 26);
3005 (*outputFunc)(outputStream, "/CharStrings 1 dict dup begin\n", 30);
3006 (*outputFunc)(outputStream, " /.notdef 0 def\n", 17);
3007 (*outputFunc)(outputStream, " end readonly def\n", 19);
3009 // write the guts of the dictionary
3010 cvtSfnts(outputFunc, outputStream, NULL);
3012 // end the dictionary and define the font
3013 (*outputFunc)(outputStream,
3014 "CIDFontName currentdict end /CIDFont defineresource pop\n",
3018 void TrueTypeFontFile::convertToType0(char *name, Gushort *cidMap,
3020 FontFileOutputFunc outputFunc,
3021 void *outputStream) {
3026 // write the Type 42 sfnts array
3027 sfntsName = (new GString(name))->append("_sfnts");
3028 cvtSfnts(outputFunc, outputStream, sfntsName);
3031 // write the descendant Type 42 fonts
3032 n = cidMap ? nCIDs : nGlyphs;
3033 for (i = 0; i < n; i += 256) {
3034 (*outputFunc)(outputStream, "10 dict begin\n", 14);
3035 (*outputFunc)(outputStream, "/FontName /", 11);
3036 (*outputFunc)(outputStream, name, strlen(name));
3037 sprintf(buf, "_%02x def\n", i >> 8);
3038 (*outputFunc)(outputStream, buf, strlen(buf));
3039 (*outputFunc)(outputStream, "/FontType 42 def\n", 17);
3040 (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
3041 sprintf(buf, "/FontBBox [%d %d %d %d] def\n",
3042 bbox[0], bbox[1], bbox[2], bbox[3]);
3043 (*outputFunc)(outputStream, buf, strlen(buf));
3044 (*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
3045 (*outputFunc)(outputStream, "/sfnts ", 7);
3046 (*outputFunc)(outputStream, name, strlen(name));
3047 (*outputFunc)(outputStream, "_sfnts def\n", 11);
3048 (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
3049 for (j = 0; j < 256 && i+j < n; ++j) {
3050 sprintf(buf, "dup %d /c%02x put\n", j, j);
3051 (*outputFunc)(outputStream, buf, strlen(buf));
3053 (*outputFunc)(outputStream, "readonly def\n", 13);
3054 (*outputFunc)(outputStream, "/CharStrings 257 dict dup begin\n", 32);
3055 (*outputFunc)(outputStream, "/.notdef 0 def\n", 15);
3056 for (j = 0; j < 256 && i+j < n; ++j) {
3057 sprintf(buf, "/c%02x %d def\n", j, cidMap ? cidMap[i+j] : i+j);
3058 (*outputFunc)(outputStream, buf, strlen(buf));
3060 (*outputFunc)(outputStream, "end readonly def\n", 17);
3061 (*outputFunc)(outputStream,
3062 "FontName currentdict end definefont pop\n", 40);
3065 // write the Type 0 parent font
3066 (*outputFunc)(outputStream, "16 dict begin\n", 14);
3067 (*outputFunc)(outputStream, "/FontName /", 11);
3068 (*outputFunc)(outputStream, name, strlen(name));
3069 (*outputFunc)(outputStream, " def\n", 5);
3070 (*outputFunc)(outputStream, "/FontType 0 def\n", 16);
3071 (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
3072 (*outputFunc)(outputStream, "/FMapType 2 def\n", 16);
3073 (*outputFunc)(outputStream, "/Encoding [\n", 12);
3074 for (i = 0; i < n; i += 256) {
3075 sprintf(buf, "%d\n", i >> 8);
3076 (*outputFunc)(outputStream, buf, strlen(buf));
3078 (*outputFunc)(outputStream, "] def\n", 6);
3079 (*outputFunc)(outputStream, "/FDepVector [\n", 14);
3080 for (i = 0; i < n; i += 256) {
3081 (*outputFunc)(outputStream, "/", 1);
3082 (*outputFunc)(outputStream, name, strlen(name));
3083 sprintf(buf, "_%02x findfont\n", i >> 8);
3084 (*outputFunc)(outputStream, buf, strlen(buf));
3086 (*outputFunc)(outputStream, "] def\n", 6);
3087 (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
3090 int TrueTypeFontFile::getByte(int pos) {
3091 if (pos < 0 || pos >= len) {
3094 return file[pos] & 0xff;
3097 int TrueTypeFontFile::getChar(int pos) {
3100 if (pos < 0 || pos >= len) {
3103 x = file[pos] & 0xff;
3109 int TrueTypeFontFile::getUShort(int pos) {
3112 if (pos < 0 || pos+1 >= len) {
3115 x = file[pos] & 0xff;
3116 x = (x << 8) + (file[pos+1] & 0xff);
3120 int TrueTypeFontFile::getShort(int pos) {
3123 if (pos < 0 || pos+1 >= len) {
3126 x = file[pos] & 0xff;
3127 x = (x << 8) + (file[pos+1] & 0xff);
3133 Guint TrueTypeFontFile::getULong(int pos) {
3136 if (pos < 0 || pos+3 >= len) {
3139 x = file[pos] & 0xff;
3140 x = (x << 8) + (file[pos+1] & 0xff);
3141 x = (x << 8) + (file[pos+2] & 0xff);
3142 x = (x << 8) + (file[pos+3] & 0xff);
3146 double TrueTypeFontFile::getFixed(int pos) {
3150 y = getUShort(pos+2);
3151 return (double)x + (double)y / 65536;
3154 int TrueTypeFontFile::seekTable(char *tag) {
3157 for (i = 0; i < nTables; ++i) {
3158 if (!strncmp(tableHdrs[i].tag, tag, 4)) {
3159 return tableHdrs[i].offset;
3165 int TrueTypeFontFile::seekTableIdx(char *tag) {
3168 for (i = 0; i < nTables; ++i) {
3169 if (!strncmp(tableHdrs[i].tag, tag, 4)) {
3176 void TrueTypeFontFile::cvtEncoding(char **encodingA, GBool pdfFontHasEncoding,
3177 FontFileOutputFunc outputFunc,
3178 void *outputStream) {
3183 (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
3184 if (pdfFontHasEncoding) {
3185 for (i = 0; i < 256; ++i) {
3186 if (!(name = encodingA[i])) {
3189 sprintf(buf, "dup %d /", i);
3190 (*outputFunc)(outputStream, buf, strlen(buf));
3191 (*outputFunc)(outputStream, name, strlen(name));
3192 (*outputFunc)(outputStream, " put\n", 5);
3195 for (i = 0; i < 256; ++i) {
3196 sprintf(buf, "dup %d /c%02x put\n", i, i);
3197 (*outputFunc)(outputStream, buf, strlen(buf));
3200 (*outputFunc)(outputStream, "readonly def\n", 13);
3203 void TrueTypeFontFile::cvtCharStrings(char **encodingA,
3204 CharCodeToUnicode *toUnicode,
3205 GBool pdfFontHasEncoding,
3206 FontFileOutputFunc outputFunc,
3207 void *outputStream) {
3208 int unicodeCmap, macRomanCmap, msSymbolCmap;
3209 int nCmaps, cmapPlatform, cmapEncoding, cmapFmt, cmapOffset;
3210 T42FontIndexMode mode;
3212 char buf[64], buf2[16];
3216 // always define '.notdef'
3217 (*outputFunc)(outputStream, "/CharStrings 256 dict dup begin\n", 32);
3218 (*outputFunc)(outputStream, "/.notdef 0 def\n", 15);
3220 // if there's no 'cmap' table, punt
3221 if ((pos = seekTable("cmap")) < 0) {
3225 // To match up with the Adobe-defined behaviour, we choose a cmap
3227 // 1. If the PDF font has an encoding:
3228 // 1a. If the TrueType font has a Microsoft Unicode cmap, use it,
3229 // and use the Unicode indexes, not the char codes.
3230 // 1b. If the TrueType font has a Macintosh Roman cmap, use it,
3231 // and reverse map the char names through MacRomanEncoding to
3233 // 2. If the PDF font does not have an encoding:
3234 // 2a. If the TrueType font has a Macintosh Roman cmap, use it,
3235 // and use char codes directly.
3236 // 2b. If the TrueType font has a Microsoft Symbol cmap, use it,
3237 // and use (0xf000 + char code).
3238 // 3. If none of these rules apply, use the first cmap and hope for
3239 // the best (this shouldn't happen).
3240 nCmaps = getUShort(pos+2);
3241 unicodeCmap = macRomanCmap = msSymbolCmap = -1;
3243 for (i = 0; i < nCmaps; ++i) {
3244 cmapPlatform = getUShort(pos + 4 + 8*i);
3245 cmapEncoding = getUShort(pos + 4 + 8*i + 2);
3246 if (cmapPlatform == 3 && cmapEncoding == 1) {
3248 } else if (cmapPlatform == 1 && cmapEncoding == 0) {
3250 } else if (cmapPlatform == 3 && cmapEncoding == 0) {
3255 mode = t42FontModeCharCode;
3256 if (pdfFontHasEncoding) {
3257 if (unicodeCmap >= 0) {
3259 mode = t42FontModeUnicode;
3260 } else if (macRomanCmap >= 0) {
3262 mode = t42FontModeMacRoman;
3265 if (macRomanCmap >= 0) {
3267 mode = t42FontModeCharCode;
3268 } else if (msSymbolCmap >= 0) {
3270 mode = t42FontModeCharCodeOffset;
3271 cmapOffset = 0xf000;
3274 cmapPlatform = getUShort(pos + 4 + 8*i);
3275 cmapEncoding = getUShort(pos + 4 + 8*i + 2);
3276 pos += getULong(pos + 4 + 8*i + 4);
3277 cmapFmt = getUShort(pos);
3278 if (cmapFmt != 0 && cmapFmt != 4 && cmapFmt != 6) {
3279 error(-1, "Unimplemented cmap format (%d) in TrueType font file",
3284 // map char name to glyph index:
3285 // 1. use encoding to map name to char code
3286 // 2. use cmap to map char code to glyph index
3287 j = 0; // make gcc happy
3288 for (i = 0; i < 256; ++i) {
3289 if (pdfFontHasEncoding) {
3290 name = encodingA[i];
3292 sprintf(buf2, "c%02x", i);
3295 if (name && strcmp(name, ".notdef")) {
3297 case t42FontModeUnicode:
3298 toUnicode->mapToUnicode((CharCode)i, &u, 1);
3301 case t42FontModeCharCode:
3304 case t42FontModeCharCodeOffset:
3307 case t42FontModeMacRoman:
3308 j = globalParams->getMacRomanCharCode(name);
3311 // note: Distiller (maybe Adobe's PS interpreter in general)
3312 // doesn't like TrueType fonts that have CharStrings entries
3313 // which point to nonexistent glyphs, hence the (k < nGlyphs)
3315 if ((k = getCmapEntry(cmapFmt, pos, j)) > 0 &&
3317 (*outputFunc)(outputStream, "/", 1);
3318 (*outputFunc)(outputStream, name, strlen(name));
3319 sprintf(buf, " %d def\n", k);
3320 (*outputFunc)(outputStream, buf, strlen(buf));
3326 (*outputFunc)(outputStream, "end readonly def\n", 17);
3329 int TrueTypeFontFile::getCmapEntry(int cmapFmt, int pos, int code) {
3330 int cmapLen, cmapFirst;
3331 int segCnt, segEnd, segStart, segDelta, segOffset;
3335 case 0: // byte encoding table (Apple standard)
3336 cmapLen = getUShort(pos + 2);
3337 if (code >= cmapLen) {
3340 return getByte(pos + 6 + code);
3342 case 4: // segment mapping to delta values (Microsoft standard)
3343 segCnt = getUShort(pos + 6) / 2;
3346 segEnd = getUShort(pos + 14 + 2*b);
3347 if (code > segEnd) {
3348 // malformed font -- the TrueType spec requires the last segEnd
3352 // invariant: seg[a].end < code <= seg[b].end
3355 segEnd = getUShort(pos + 14 + 2*m);
3356 if (segEnd < code) {
3362 segStart = getUShort(pos + 16 + 2*segCnt + 2*b);
3363 segDelta = getUShort(pos + 16 + 4*segCnt + 2*b);
3364 segOffset = getUShort(pos + 16 + 6*segCnt + 2*b);
3365 if (segOffset == 0) {
3366 i = (code + segDelta) & 0xffff;
3368 i = getUShort(pos + 16 + 6*segCnt + 2*b +
3369 segOffset + 2 * (code - segStart));
3371 i = (i + segDelta) & 0xffff;
3376 case 6: // trimmed table mapping
3377 cmapFirst = getUShort(pos + 6);
3378 cmapLen = getUShort(pos + 8);
3379 if (code < cmapFirst || code >= cmapFirst + cmapLen) {
3382 return getUShort(pos + 10 + 2*(code - cmapFirst));
3385 // shouldn't happen - this is checked earlier
3391 void TrueTypeFontFile::cvtSfnts(FontFileOutputFunc outputFunc,
3392 void *outputStream, GString *name) {
3393 TTFontTableHdr newTableHdrs[nT42Tables];
3394 char tableDir[12 + nT42Tables*16];
3400 int pos, glyfPos, length, glyphLength, pad;
3403 // construct the 'head' table, zero out the font checksum
3404 memcpy(headTable, file + seekTable("head"), 54);
3405 headTable[8] = headTable[9] = headTable[10] = headTable[11] = (char)0;
3407 // read the original 'loca' table and construct the new one
3408 // (pad each glyph out to a multiple of 4 bytes)
3409 origLocaTable = (int *)gmalloc((nGlyphs + 1) * sizeof(int));
3410 pos = seekTable("loca");
3411 for (i = 0; i <= nGlyphs; ++i) {
3413 origLocaTable[i] = getULong(pos + 4*i);
3415 origLocaTable[i] = 2 * getUShort(pos + 2*i);
3418 locaTable = (char *)gmalloc((nGlyphs + 1) * (locaFmt ? 4 : 2));
3420 locaTable[0] = locaTable[1] = locaTable[2] = locaTable[3] = 0;
3422 locaTable[0] = locaTable[1] = 0;
3425 for (i = 1; i <= nGlyphs; ++i) {
3426 length = origLocaTable[i] - origLocaTable[i-1];
3428 length += 4 - (length & 3);
3432 locaTable[4*i ] = (char)(pos >> 24);
3433 locaTable[4*i+1] = (char)(pos >> 16);
3434 locaTable[4*i+2] = (char)(pos >> 8);
3435 locaTable[4*i+3] = (char) pos;
3437 locaTable[2*i ] = (char)(pos >> 9);
3438 locaTable[2*i+1] = (char)(pos >> 1);
3442 // count the number of tables
3444 for (i = 0; i < nT42Tables; ++i) {
3445 if (t42Tables[i].required ||
3446 seekTable(t42Tables[i].tag) >= 0) {
3451 // construct the new table headers, including table checksums
3452 // (pad each table out to a multiple of 4 bytes)
3453 pos = 12 + nNewTables*16;
3455 for (i = 0; i < nT42Tables; ++i) {
3457 checksum = 0; // make gcc happy
3458 if (i == t42HeadTable) {
3460 checksum = computeTableChecksum(headTable, 54);
3461 } else if (i == t42LocaTable) {
3462 length = (nGlyphs + 1) * (locaFmt ? 4 : 2);
3463 checksum = computeTableChecksum(locaTable, length);
3464 } else if (i == t42GlyfTable) {
3467 glyfPos = seekTable("glyf");
3468 for (j = 0; j < nGlyphs; ++j) {
3469 glyphLength = origLocaTable[j+1] - origLocaTable[j];
3470 pad = (glyphLength & 3) ? 4 - (glyphLength & 3) : 0;
3471 length += glyphLength + pad;
3472 checksum += computeTableChecksum(file + glyfPos + origLocaTable[j],
3476 if ((j = seekTableIdx(t42Tables[i].tag)) >= 0) {
3477 length = tableHdrs[j].length;
3478 checksum = computeTableChecksum(file + tableHdrs[j].offset, length);
3479 } else if (t42Tables[i].required) {
3480 error(-1, "Embedded TrueType font is missing a required table ('%s')",
3487 strncpy(newTableHdrs[k].tag, t42Tables[i].tag, 4);
3488 newTableHdrs[k].checksum = checksum;
3489 newTableHdrs[k].offset = pos;
3490 newTableHdrs[k].length = length;
3491 pad = (length & 3) ? 4 - (length & 3) : 0;
3492 pos += length + pad;
3497 // construct the table directory
3498 tableDir[0] = 0x00; // sfnt version
3502 tableDir[4] = 0; // numTables
3503 tableDir[5] = nNewTables;
3504 tableDir[6] = 0; // searchRange
3505 tableDir[7] = (char)128;
3506 tableDir[8] = 0; // entrySelector
3508 tableDir[10] = 0; // rangeShift
3509 tableDir[11] = (char)(16 * nNewTables - 128);
3511 for (i = 0; i < nNewTables; ++i) {
3512 tableDir[pos ] = newTableHdrs[i].tag[0];
3513 tableDir[pos+ 1] = newTableHdrs[i].tag[1];
3514 tableDir[pos+ 2] = newTableHdrs[i].tag[2];
3515 tableDir[pos+ 3] = newTableHdrs[i].tag[3];
3516 tableDir[pos+ 4] = (char)(newTableHdrs[i].checksum >> 24);
3517 tableDir[pos+ 5] = (char)(newTableHdrs[i].checksum >> 16);
3518 tableDir[pos+ 6] = (char)(newTableHdrs[i].checksum >> 8);
3519 tableDir[pos+ 7] = (char) newTableHdrs[i].checksum;
3520 tableDir[pos+ 8] = (char)(newTableHdrs[i].offset >> 24);
3521 tableDir[pos+ 9] = (char)(newTableHdrs[i].offset >> 16);
3522 tableDir[pos+10] = (char)(newTableHdrs[i].offset >> 8);
3523 tableDir[pos+11] = (char) newTableHdrs[i].offset;
3524 tableDir[pos+12] = (char)(newTableHdrs[i].length >> 24);
3525 tableDir[pos+13] = (char)(newTableHdrs[i].length >> 16);
3526 tableDir[pos+14] = (char)(newTableHdrs[i].length >> 8);
3527 tableDir[pos+15] = (char) newTableHdrs[i].length;
3531 // compute the font checksum and store it in the head table
3532 checksum = computeTableChecksum(tableDir, 12 + nNewTables*16);
3533 for (i = 0; i < nNewTables; ++i) {
3534 checksum += newTableHdrs[i].checksum;
3536 checksum = 0xb1b0afba - checksum; // because the TrueType spec says so
3537 headTable[ 8] = (char)(checksum >> 24);
3538 headTable[ 9] = (char)(checksum >> 16);
3539 headTable[10] = (char)(checksum >> 8);
3540 headTable[11] = (char) checksum;
3542 // start the sfnts array
3544 (*outputFunc)(outputStream, "/", 1);
3545 (*outputFunc)(outputStream, name->getCString(), name->getLength());
3546 (*outputFunc)(outputStream, " [\n", 3);
3548 (*outputFunc)(outputStream, "/sfnts [\n", 9);
3551 // write the table directory
3552 dumpString(tableDir, 12 + nNewTables*16, outputFunc, outputStream);
3555 for (i = 0; i < nNewTables; ++i) {
3556 if (i == t42HeadTable) {
3557 dumpString(headTable, 54, outputFunc, outputStream);
3558 } else if (i == t42LocaTable) {
3559 length = (nGlyphs + 1) * (locaFmt ? 4 : 2);
3560 dumpString(locaTable, length, outputFunc, outputStream);
3561 } else if (i == t42GlyfTable) {
3562 glyfPos = seekTable("glyf");
3563 for (j = 0; j < nGlyphs; ++j) {
3564 length = origLocaTable[j+1] - origLocaTable[j];
3566 dumpString(file + glyfPos + origLocaTable[j], length,
3567 outputFunc, outputStream);
3571 // length == 0 means the table is missing and the error was
3572 // already reported during the construction of the table
3574 if ((length = newTableHdrs[i].length) > 0) {
3575 dumpString(file + seekTable(t42Tables[i].tag), length,
3576 outputFunc, outputStream);
3581 // end the sfnts array
3582 (*outputFunc)(outputStream, "] def\n", 6);
3584 gfree(origLocaTable);
3588 void TrueTypeFontFile::dumpString(char *s, int length,
3589 FontFileOutputFunc outputFunc,
3590 void *outputStream) {
3594 (*outputFunc)(outputStream, "<", 1);
3595 for (i = 0; i < length; i += 32) {
3596 for (j = 0; j < 32 && i+j < length; ++j) {
3597 sprintf(buf, "%02X", s[i+j] & 0xff);
3598 (*outputFunc)(outputStream, buf, strlen(buf));
3600 if (i % (65536 - 32) == 65536 - 64) {
3601 (*outputFunc)(outputStream, ">\n<", 3);
3602 } else if (i+32 < length) {
3603 (*outputFunc)(outputStream, "\n", 1);
3607 pad = 4 - (length & 3);
3608 for (i = 0; i < pad; ++i) {
3609 (*outputFunc)(outputStream, "00", 2);
3612 // add an extra zero byte because the Adobe Type 42 spec says so
3613 (*outputFunc)(outputStream, "00>\n", 4);
3616 Guint TrueTypeFontFile::computeTableChecksum(char *data, int length) {
3617 Guint checksum, word;
3621 for (i = 0; i+3 < length; i += 4) {
3622 word = ((data[i ] & 0xff) << 24) +
3623 ((data[i+1] & 0xff) << 16) +
3624 ((data[i+2] & 0xff) << 8) +
3631 switch (length & 3) {
3633 word |= (data[i+2] & 0xff) << 8;
3635 word |= (data[i+1] & 0xff) << 16;
3637 word |= (data[i ] & 0xff) << 24;
3645 void TrueTypeFontFile::writeTTF(FILE *out) {
3646 static char cmapTab[20] = {
3647 0, 0, // table version number
3648 0, 1, // number of encoding tables
3649 0, 1, // platform ID
3650 0, 0, // encoding ID
3651 0, 0, 0, 12, // offset of subtable
3652 0, 0, // subtable format
3653 0, 1, // subtable length
3654 0, 1, // subtable version
3655 0, // map char 0 -> glyph 0
3656 0 // pad to multiple of four bytes
3658 static char nameTab[8] = {
3660 0, 0, // number of name records
3661 0, 6, // offset to start of string storage
3662 0, 0 // pad to multiple of four bytes
3664 static char postTab[32] = {
3665 0, 1, 0, 0, // format
3666 0, 0, 0, 0, // italic angle
3667 0, 0, // underline position
3668 0, 0, // underline thickness
3669 0, 0, 0, 0, // fixed pitch
3670 0, 0, 0, 0, // min Type 42 memory
3671 0, 0, 0, 0, // max Type 42 memory
3672 0, 0, 0, 0, // min Type 1 memory
3673 0, 0, 0, 0 // max Type 1 memory
3675 GBool haveCmap, haveName, havePost;
3676 GBool dirCmap, dirName, dirPost;
3677 int nNewTables, nAllTables, pad;
3682 // check for missing tables
3683 haveCmap = seekTable("cmap") >= 0;
3684 haveName = seekTable("name") >= 0;
3685 havePost = seekTable("post") >= 0;
3686 nNewTables = (haveCmap ? 0 : 1) + (haveName ? 0 : 1) + (havePost ? 0 : 1);
3687 if (!nNewTables && !mungedCmapSize) {
3688 // none are missing - write the TTF file as is
3689 fwrite(file, 1, len, out);
3693 // construct the new table directory
3694 nAllTables = nTables + nNewTables;
3695 tableDir = (char *)gmalloc(12 + nAllTables * 16);
3696 memcpy(tableDir, file, 12 + nTables * 16);
3697 tableDir[4] = (char)((nAllTables >> 8) & 0xff);
3698 tableDir[5] = (char)(nAllTables & 0xff);
3699 for (i = -1, t = (Guint)nAllTables; t; ++i, t >>= 1) ;
3701 tableDir[6] = (char)((t >> 8) & 0xff);
3702 tableDir[7] = (char)(t & 0xff);
3703 tableDir[8] = (char)((i >> 8) & 0xff);
3704 tableDir[9] = (char)(i & 0xff);
3705 t = nAllTables * 16 - t;
3706 tableDir[10] = (char)((t >> 8) & 0xff);
3707 tableDir[11] = (char)(t & 0xff);
3712 pad = (len & 3) ? 4 - (len & 3) : 0;
3713 pos = len + pad + 16 * nNewTables;
3714 for (i = 0; i < nTables; ++i) {
3715 if (!dirCmap && strncmp(tableHdrs[i].tag, "cmap", 4) > 0) {
3716 tableDir[12 + 16*j ] = 'c';
3717 tableDir[12 + 16*j + 1] = 'm';
3718 tableDir[12 + 16*j + 2] = 'a';
3719 tableDir[12 + 16*j + 3] = 'p';
3720 tableDir[12 + 16*j + 4] = (char)0; //~ should compute the checksum
3721 tableDir[12 + 16*j + 5] = (char)0;
3722 tableDir[12 + 16*j + 6] = (char)0;
3723 tableDir[12 + 16*j + 7] = (char)0;
3724 tableDir[12 + 16*j + 8] = (char)((pos >> 24) & 0xff);
3725 tableDir[12 + 16*j + 9] = (char)((pos >> 16) & 0xff);
3726 tableDir[12 + 16*j + 10] = (char)((pos >> 8) & 0xff);
3727 tableDir[12 + 16*j + 11] = (char)( pos & 0xff);
3728 tableDir[12 + 16*j + 12] = (char)((sizeof(cmapTab) >> 24) & 0xff);
3729 tableDir[12 + 16*j + 13] = (char)((sizeof(cmapTab) >> 16) & 0xff);
3730 tableDir[12 + 16*j + 14] = (char)((sizeof(cmapTab) >> 8) & 0xff);
3731 tableDir[12 + 16*j + 15] = (char)( sizeof(cmapTab) & 0xff);
3732 pos += sizeof(cmapTab);
3736 if (!dirName && strncmp(tableHdrs[i].tag, "name", 4) > 0) {
3737 tableDir[12 + 16*j ] = 'n';
3738 tableDir[12 + 16*j + 1] = 'a';
3739 tableDir[12 + 16*j + 2] = 'm';
3740 tableDir[12 + 16*j + 3] = 'e';
3741 tableDir[12 + 16*j + 4] = (char)0; //~ should compute the checksum
3742 tableDir[12 + 16*j + 5] = (char)0;
3743 tableDir[12 + 16*j + 6] = (char)0;
3744 tableDir[12 + 16*j + 7] = (char)0;
3745 tableDir[12 + 16*j + 8] = (char)((pos >> 24) & 0xff);
3746 tableDir[12 + 16*j + 9] = (char)((pos >> 16) & 0xff);
3747 tableDir[12 + 16*j + 10] = (char)((pos >> 8) & 0xff);
3748 tableDir[12 + 16*j + 11] = (char)( pos & 0xff);
3749 tableDir[12 + 16*j + 12] = (char)((sizeof(nameTab) >> 24) & 0xff);
3750 tableDir[12 + 16*j + 13] = (char)((sizeof(nameTab) >> 16) & 0xff);
3751 tableDir[12 + 16*j + 14] = (char)((sizeof(nameTab) >> 8) & 0xff);
3752 tableDir[12 + 16*j + 15] = (char)( sizeof(nameTab) & 0xff);
3753 pos += sizeof(nameTab);
3757 if (!dirName && strncmp(tableHdrs[i].tag, "post", 4) > 0) {
3758 tableDir[12 + 16*j ] = 'p';
3759 tableDir[12 + 16*j + 1] = 'o';
3760 tableDir[12 + 16*j + 2] = 's';
3761 tableDir[12 + 16*j + 3] = 't';
3762 tableDir[12 + 16*j + 4] = (char)0; //~ should compute the checksum
3763 tableDir[12 + 16*j + 5] = (char)0;
3764 tableDir[12 + 16*j + 6] = (char)0;
3765 tableDir[12 + 16*j + 7] = (char)0;
3766 tableDir[12 + 16*j + 8] = (char)((pos >> 24) & 0xff);
3767 tableDir[12 + 16*j + 9] = (char)((pos >> 16) & 0xff);
3768 tableDir[12 + 16*j + 10] = (char)((pos >> 8) & 0xff);
3769 tableDir[12 + 16*j + 11] = (char)( pos & 0xff);
3770 tableDir[12 + 16*j + 12] = (char)((sizeof(postTab) >> 24) & 0xff);
3771 tableDir[12 + 16*j + 13] = (char)((sizeof(postTab) >> 16) & 0xff);
3772 tableDir[12 + 16*j + 14] = (char)((sizeof(postTab) >> 8) & 0xff);
3773 tableDir[12 + 16*j + 15] = (char)( sizeof(postTab) & 0xff);
3774 pos += sizeof(postTab);
3778 tableDir[12 + 16*j ] = tableHdrs[i].tag[0];
3779 tableDir[12 + 16*j + 1] = tableHdrs[i].tag[1];
3780 tableDir[12 + 16*j + 2] = tableHdrs[i].tag[2];
3781 tableDir[12 + 16*j + 3] = tableHdrs[i].tag[3];
3782 tableDir[12 + 16*j + 4] = (char)((tableHdrs[i].checksum >> 24) & 0xff);
3783 tableDir[12 + 16*j + 5] = (char)((tableHdrs[i].checksum >> 16) & 0xff);
3784 tableDir[12 + 16*j + 6] = (char)((tableHdrs[i].checksum >> 8) & 0xff);
3785 tableDir[12 + 16*j + 7] = (char)( tableHdrs[i].checksum & 0xff);
3786 t = tableHdrs[i].offset + nNewTables * 16;
3787 tableDir[12 + 16*j + 8] = (char)((t >> 24) & 0xff);
3788 tableDir[12 + 16*j + 9] = (char)((t >> 16) & 0xff);
3789 tableDir[12 + 16*j + 10] = (char)((t >> 8) & 0xff);
3790 tableDir[12 + 16*j + 11] = (char)( t & 0xff);
3791 tableDir[12 + 16*j + 12] = (char)((tableHdrs[i].length >> 24) & 0xff);
3792 tableDir[12 + 16*j + 13] = (char)((tableHdrs[i].length >> 16) & 0xff);
3793 tableDir[12 + 16*j + 14] = (char)((tableHdrs[i].length >> 8) & 0xff);
3794 tableDir[12 + 16*j + 15] = (char)( tableHdrs[i].length & 0xff);
3798 tableDir[12 + 16*j ] = 'c';
3799 tableDir[12 + 16*j + 1] = 'm';
3800 tableDir[12 + 16*j + 2] = 'a';
3801 tableDir[12 + 16*j + 3] = 'p';
3802 tableDir[12 + 16*j + 4] = (char)0; //~ should compute the checksum
3803 tableDir[12 + 16*j + 5] = (char)0;
3804 tableDir[12 + 16*j + 6] = (char)0;
3805 tableDir[12 + 16*j + 7] = (char)0;
3806 tableDir[12 + 16*j + 8] = (char)((pos >> 24) & 0xff);
3807 tableDir[12 + 16*j + 9] = (char)((pos >> 16) & 0xff);
3808 tableDir[12 + 16*j + 10] = (char)((pos >> 8) & 0xff);
3809 tableDir[12 + 16*j + 11] = (char)( pos & 0xff);
3810 tableDir[12 + 16*j + 12] = (char)((sizeof(cmapTab) >> 24) & 0xff);
3811 tableDir[12 + 16*j + 13] = (char)((sizeof(cmapTab) >> 16) & 0xff);
3812 tableDir[12 + 16*j + 14] = (char)((sizeof(cmapTab) >> 8) & 0xff);
3813 tableDir[12 + 16*j + 15] = (char)( sizeof(cmapTab) & 0xff);
3814 pos += sizeof(cmapTab);
3819 tableDir[12 + 16*j ] = 'n';
3820 tableDir[12 + 16*j + 1] = 'a';
3821 tableDir[12 + 16*j + 2] = 'm';
3822 tableDir[12 + 16*j + 3] = 'e';
3823 tableDir[12 + 16*j + 4] = (char)0; //~ should compute the checksum
3824 tableDir[12 + 16*j + 5] = (char)0;
3825 tableDir[12 + 16*j + 6] = (char)0;
3826 tableDir[12 + 16*j + 7] = (char)0;
3827 tableDir[12 + 16*j + 8] = (char)((pos >> 24) & 0xff);
3828 tableDir[12 + 16*j + 9] = (char)((pos >> 16) & 0xff);
3829 tableDir[12 + 16*j + 10] = (char)((pos >> 8) & 0xff);
3830 tableDir[12 + 16*j + 11] = (char)( pos & 0xff);
3831 tableDir[12 + 16*j + 12] = (char)((sizeof(nameTab) >> 24) & 0xff);
3832 tableDir[12 + 16*j + 13] = (char)((sizeof(nameTab) >> 16) & 0xff);
3833 tableDir[12 + 16*j + 14] = (char)((sizeof(nameTab) >> 8) & 0xff);
3834 tableDir[12 + 16*j + 15] = (char)( sizeof(nameTab) & 0xff);
3835 pos += sizeof(nameTab);
3840 tableDir[12 + 16*j ] = 'p';
3841 tableDir[12 + 16*j + 1] = 'o';
3842 tableDir[12 + 16*j + 2] = 's';
3843 tableDir[12 + 16*j + 3] = 't';
3844 tableDir[12 + 16*j + 4] = (char)0; //~ should compute the checksum
3845 tableDir[12 + 16*j + 5] = (char)0;
3846 tableDir[12 + 16*j + 6] = (char)0;
3847 tableDir[12 + 16*j + 7] = (char)0;
3848 tableDir[12 + 16*j + 8] = (char)((pos >> 24) & 0xff);
3849 tableDir[12 + 16*j + 9] = (char)((pos >> 16) & 0xff);
3850 tableDir[12 + 16*j + 10] = (char)((pos >> 8) & 0xff);
3851 tableDir[12 + 16*j + 11] = (char)( pos & 0xff);
3852 tableDir[12 + 16*j + 12] = (char)((sizeof(postTab) >> 24) & 0xff);
3853 tableDir[12 + 16*j + 13] = (char)((sizeof(postTab) >> 16) & 0xff);
3854 tableDir[12 + 16*j + 14] = (char)((sizeof(postTab) >> 8) & 0xff);
3855 tableDir[12 + 16*j + 15] = (char)( sizeof(postTab) & 0xff);
3856 pos += sizeof(postTab);
3861 // write the table directory
3862 fwrite(tableDir, 1, 12 + 16 * nAllTables, out);
3864 // write the original tables
3865 fwrite(file + 12 + 16*nTables, 1, len - (12 + 16*nTables), out);
3867 // write the new tables
3868 for (i = 0; i < pad; ++i) {
3869 fputc((char)0, out);
3872 fwrite(cmapTab, 1, sizeof(cmapTab), out);
3875 fwrite(nameTab, 1, sizeof(nameTab), out);
3878 fwrite(postTab, 1, sizeof(postTab), out);