23#include "GlobalParams.h"
24#include "CharCodeToUnicode.h"
25#include "FontEncodingTables.h"
28#include "CompactFontTables.h"
32static inline const char *nextLine(
const char *line,
const char *end) {
33 while (line < end && *line !=
'\n' && *line !=
'\r')
35 while (line < end && *line ==
'\n' || *line ==
'\r')
40static const char hexChars[17] =
"0123456789ABCDEF";
49FontFile::~FontFile() {
56Type1FontFile::Type1FontFile(
const char *file,
int len) {
57 const char *line, *line1;
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")) {
128 haveEncoding = gTrue;
131 line = nextLine(line, file + len);
136Type1FontFile::~Type1FontFile() {
142 for (i = 0; i < 256; ++i) {
152struct Type1CTopDict {
161 double underlinePosition;
162 double underlineThickness;
165 double fontMatrix[6];
183struct Type1CPrivateDict {
186 double defaultWidthX;
187 GBool defaultWidthXFP;
188 double nominalWidthX;
189 GBool nominalWidthXFP;
192Type1CFontFile::Type1CFontFile(
const char *fileA,
int lenA) {
193 Guchar *nameIdxPtr, *idxPtr0, *idxPtr1;
202 if (file[0] !=
'\x01') {
207 topOffSize = file[3] & 0xff;
210 nameIdxPtr = (Guchar *)file + (file[2] & 0xff);
211 idxPtr0 = getIndexValPtr(nameIdxPtr, 0);
212 idxPtr1 = getIndexValPtr(nameIdxPtr, 1);
213 name =
new GString((
char *)idxPtr0, idxPtr1 - idxPtr0);
215 topDictIdxPtr = getIndexEnd(nameIdxPtr);
216 stringIdxPtr = getIndexEnd(topDictIdxPtr);
217 gsubrIdxPtr = getIndexEnd(stringIdxPtr);
220Type1CFontFile::~Type1CFontFile() {
225 for (i = 0; i < 256; ++i) {
232const char *Type1CFontFile::getName() {
233 return name->getCString();
236char **Type1CFontFile::getEncoding() {
238 readNameAndEncoding();
243void Type1CFontFile::readNameAndEncoding() {
245 Guchar *idxPtr0, *idxPtr1, *ptr;
247 int nCodes, nRanges, nLeft, nSups;
249 int charset, enc, charstrings;
257 encoding = (
char **)gmalloc(256 *
sizeof(
char *));
258 for (i = 0; i < 256; ++i) {
263 idxPtr0 = getIndexValPtr(topDictIdxPtr, 0);
264 idxPtr1 = getIndexValPtr(topDictIdxPtr, 1);
265 charset = enc = charstrings = 0;
268 while (ptr < idxPtr1) {
269 if (*ptr <= 27 || *ptr == 31) {
272 key = (key << 8) | *ptr++;
275 charset = (int)op[0];
276 }
else if (key == 0x10) {
278 }
else if (key == 0x11) {
279 charstrings = (int)op[0];
283 x = getNum(&ptr, &isFP);
291 nGlyphs = getIndexLen((Guchar *)file + charstrings);
294 glyphNames = readCharset(charset, nGlyphs);
298 for (i = 0; i < 256; ++i) {
299 if (standardEncoding[i]) {
300 encoding[i] = copyString(standardEncoding[i]);
303 }
else if (enc == 1) {
304 for (i = 0; i < 256; ++i) {
305 if (expertEncoding[i]) {
306 encoding[i] = copyString(expertEncoding[i]);
310 ptr = (Guchar *)file + enc;
312 if ((encFormat & 0x7f) == 0) {
314 if (nCodes > nGlyphs) {
317 for (i = 1; i < nCodes; ++i) {
319 encoding[c] = copyString(getString(glyphNames[i], buf));
321 }
else if ((encFormat & 0x7f) == 1) {
324 for (i = 0; i < nRanges; ++i) {
327 for (j = 0; j <= nLeft && nCodes < nGlyphs; ++j) {
328 encoding[c] = copyString(getString(glyphNames[nCodes], buf));
334 if (encFormat & 0x80) {
336 for (i = 0; i < nSups; ++i) {
338 sid = getWord(ptr, 2);
340 encoding[c] = copyString(getString(sid, buf));
350void Type1CFontFile::convertToType1(FontFileOutputFunc outputFuncA,
351 void *outputStreamA) {
353 Type1CPrivateDict privateDict;
354 char buf[512], eBuf[256];
355 Guchar *idxPtr0, *idxPtr1, *subrsIdxPtr, *charStringsIdxPtr, *ptr;
356 int nGlyphs, nCodes, nRanges, nLeft, nSups;
358 int encFormat, nSubrs, nCharStrings;
362 outputFunc = outputFuncA;
363 outputStream = outputStreamA;
372 (*outputFunc)(outputStream,
"%!FontType1-1.0: ", 17);
373 (*outputFunc)(outputStream, name->getCString(), name->getLength());
374 if (dict.version != 0) {
375 getString(dict.version, buf);
376 (*outputFunc)(outputStream, buf, strlen(buf));
378 (*outputFunc)(outputStream,
"\n", 1);
379 (*outputFunc)(outputStream,
"11 dict begin\n", 14);
380 (*outputFunc)(outputStream,
"/FontInfo 10 dict dup begin\n", 28);
381 if (dict.version != 0) {
382 (*outputFunc)(outputStream,
"/version (", 10);
383 (*outputFunc)(outputStream, buf, strlen(buf));
384 (*outputFunc)(outputStream,
") readonly def\n", 15);
386 if (dict.notice != 0) {
387 getString(dict.notice, buf);
388 (*outputFunc)(outputStream,
"/Notice (", 9);
389 (*outputFunc)(outputStream, buf, strlen(buf));
390 (*outputFunc)(outputStream,
") readonly def\n", 15);
392 if (dict.copyright != 0) {
393 getString(dict.copyright, buf);
394 (*outputFunc)(outputStream,
"/Copyright (", 12);
395 (*outputFunc)(outputStream, buf, strlen(buf));
396 (*outputFunc)(outputStream,
") readonly def\n", 15);
398 if (dict.fullName != 0) {
399 getString(dict.fullName, buf);
400 (*outputFunc)(outputStream,
"/FullName (", 11);
401 (*outputFunc)(outputStream, buf, strlen(buf));
402 (*outputFunc)(outputStream,
") readonly def\n", 15);
404 if (dict.familyName != 0) {
405 getString(dict.familyName, buf);
406 (*outputFunc)(outputStream,
"/FamilyName (", 13);
407 (*outputFunc)(outputStream, buf, strlen(buf));
408 (*outputFunc)(outputStream,
") readonly def\n", 15);
410 if (dict.weight != 0) {
411 getString(dict.weight, buf);
412 (*outputFunc)(outputStream,
"/Weight (", 9);
413 (*outputFunc)(outputStream, buf, strlen(buf));
414 (*outputFunc)(outputStream,
") readonly def\n", 15);
416 if (dict.isFixedPitch) {
417 (*outputFunc)(outputStream,
"/isFixedPitch true def\n", 23);
419 (*outputFunc)(outputStream,
"/isFixedPitch false def\n", 24);
421 sprintf(buf,
"/ItalicAngle %g def\n", dict.italicAngle);
422 (*outputFunc)(outputStream, buf, strlen(buf));
423 sprintf(buf,
"/UnderlinePosition %g def\n", dict.underlinePosition);
424 (*outputFunc)(outputStream, buf, strlen(buf));
425 sprintf(buf,
"/UnderlineThickness %g def\n", dict.underlineThickness);
426 (*outputFunc)(outputStream, buf, strlen(buf));
427 (*outputFunc)(outputStream,
"end readonly def\n", 17);
428 (*outputFunc)(outputStream,
"/FontName /", 11);
429 (*outputFunc)(outputStream, name->getCString(), name->getLength());
430 (*outputFunc)(outputStream,
" def\n", 5);
431 sprintf(buf,
"/PaintType %d def\n", dict.paintType);
432 (*outputFunc)(outputStream, buf, strlen(buf));
433 (*outputFunc)(outputStream,
"/FontType 1 def\n", 16);
434 sprintf(buf,
"/FontMatrix [%g %g %g %g %g %g] readonly def\n",
435 dict.fontMatrix[0], dict.fontMatrix[1], dict.fontMatrix[2],
436 dict.fontMatrix[3], dict.fontMatrix[4], dict.fontMatrix[5]);
437 (*outputFunc)(outputStream, buf, strlen(buf));
438 sprintf(buf,
"/FontBBox [%g %g %g %g] readonly def\n",
439 dict.fontBBox[0], dict.fontBBox[1],
440 dict.fontBBox[2], dict.fontBBox[3]);
441 (*outputFunc)(outputStream, buf, strlen(buf));
442 sprintf(buf,
"/StrokeWidth %g def\n", dict.strokeWidth);
443 (*outputFunc)(outputStream, buf, strlen(buf));
444 if (dict.uniqueID != 0) {
445 sprintf(buf,
"/UniqueID %d def\n", dict.uniqueID);
446 (*outputFunc)(outputStream, buf, strlen(buf));
450 nGlyphs = getIndexLen((Guchar *)file + dict.charStrings);
453 glyphNames = readCharset(dict.charset, nGlyphs);
456 (*outputFunc)(outputStream,
"/Encoding ", 10);
457 if (dict.encoding == 0) {
458 (*outputFunc)(outputStream,
"StandardEncoding def\n", 21);
460 (*outputFunc)(outputStream,
"256 array\n", 10);
461 (*outputFunc)(outputStream,
462 "0 1 255 {1 index exch /.notdef put} for\n", 40);
463 if (dict.encoding == 1) {
464 for (i = 0; i < 256; ++i) {
465 if (expertEncoding[i]) {
466 sprintf(buf,
"dup %d /%s put\n", i, expertEncoding[i]);
467 (*outputFunc)(outputStream, buf, strlen(buf));
471 ptr = (Guchar *)file + dict.encoding;
473 if ((encFormat & 0x7f) == 0) {
475 if (nCodes > nGlyphs) {
478 for (i = 1; i < nCodes; ++i) {
480 sprintf(buf,
"dup %d /", c);
481 (*outputFunc)(outputStream, buf, strlen(buf));
482 getString(glyphNames[i], buf);
483 (*outputFunc)(outputStream, buf, strlen(buf));
484 (*outputFunc)(outputStream,
" put\n", 5);
486 }
else if ((encFormat & 0x7f) == 1) {
489 for (i = 0; i < nRanges; ++i) {
492 for (j = 0; j <= nLeft && nCodes < nGlyphs; ++j) {
493 sprintf(buf,
"dup %d /", c);
494 (*outputFunc)(outputStream, buf, strlen(buf));
495 getString(glyphNames[nCodes], buf);
496 (*outputFunc)(outputStream, buf, strlen(buf));
497 (*outputFunc)(outputStream,
" put\n", 5);
503 if (encFormat & 0x80) {
505 for (i = 0; i < nSups; ++i) {
507 sid = getWord(ptr, 2);
509 sprintf(buf,
"dup %d /", c);
510 (*outputFunc)(outputStream, buf, strlen(buf));
512 (*outputFunc)(outputStream, buf, strlen(buf));
513 (*outputFunc)(outputStream,
" put\n", 5);
517 (*outputFunc)(outputStream,
"readonly def\n", 13);
519 (*outputFunc)(outputStream,
"currentdict end\n", 16);
522 (*outputFunc)(outputStream,
"currentfile eexec\n", 18);
527 eexecWrite(
"\x83\xca\x73\xd5");
528 eexecWrite(
"dup /Private 32 dict dup begin\n");
529 eexecWrite(
"/RD {string currentfile exch readstring pop} executeonly def\n");
530 eexecWrite(
"/ND {noaccess def} executeonly def\n");
531 eexecWrite(
"/NP {noaccess put} executeonly def\n");
532 eexecWrite(
"/MinFeature {16 16} ND\n");
533 readPrivateDict(&privateDict, dict.privateOffset, dict.privateSize);
534 eexecWrite(privateDict.dictData->getCString());
535 defaultWidthX = privateDict.defaultWidthX;
536 defaultWidthXFP = privateDict.defaultWidthXFP;
537 nominalWidthX = privateDict.nominalWidthX;
538 nominalWidthXFP = privateDict.nominalWidthXFP;
541 if (privateDict.subrsOffset != 0) {
542 subrsIdxPtr = (Guchar *)file + dict.privateOffset +
543 privateDict.subrsOffset;
544 nSubrs = getIndexLen(subrsIdxPtr);
545 sprintf(eBuf,
"/Subrs %d array\n", nSubrs);
547 idxPtr1 = getIndexValPtr(subrsIdxPtr, 0);
548 for (i = 0; i < nSubrs; ++i) {
550 idxPtr1 = getIndexValPtr(subrsIdxPtr, i+1);
551 n = idxPtr1 - idxPtr0;
553 error(-1,
"Unimplemented Type 2 subrs");
555 sprintf(eBuf,
"dup %d %d RD ", i, n);
557 eexecCvtGlyph(idxPtr0, n);
565 charStringsIdxPtr = (Guchar *)file + dict.charStrings;
566 nCharStrings = getIndexLen(charStringsIdxPtr);
567 sprintf(eBuf,
"2 index /CharStrings %d dict dup begin\n", nCharStrings);
569 idxPtr1 = getIndexValPtr(charStringsIdxPtr, 0);
570 for (i = 0; i < nCharStrings; ++i) {
572 idxPtr1 = getIndexValPtr(charStringsIdxPtr, i+1);
573 n = idxPtr1 - idxPtr0;
574 eexecCvtGlyph(getString(glyphNames[i], buf), idxPtr0, n);
578 eexecWrite(
"readonly put\n");
579 eexecWrite(
"noaccess put\n");
580 eexecWrite(
"dup /FontName get exch definefont pop\n");
581 eexecWrite(
"mark currentfile closefile\n");
585 (*outputFunc)(outputStream,
"\n", 1);
587 for (i = 0; i < 8; ++i) {
588 (*outputFunc)(outputStream,
"0000000000000000000000000000000000000000000000000000000000000000\n", 65);
590 (*outputFunc)(outputStream,
"cleartomark\n", 12);
593 delete privateDict.dictData;
594 if (dict.charset > 2) {
599void Type1CFontFile::convertToCIDType0(
const char *psName,
600 FontFileOutputFunc outputFuncA,
601 void *outputStreamA) {
603 Type1CPrivateDict *privateDicts;
604 GString *charStrings;
605 int *charStringOffsets;
609 Guchar *charStringsIdxPtr, *fdArrayIdx, *idxPtr0, *idxPtr1, *ptr;
610 char buf[512], buf2[16];
611 int nGlyphs, nCIDs, gdBytes, nFDs;
612 int fdSelectFmt, nRanges, gid0, gid1, fd, offset;
618 outputFunc = outputFuncA;
619 outputStream = outputStreamA;
621 (*outputFunc)(outputStream,
"/CIDInit /ProcSet findresource begin\n", 37);
627 if (dict.fdArrayOffset == 0) {
629 privateDicts = (Type1CPrivateDict *)
630 gmalloc(nFDs *
sizeof(Type1CPrivateDict));
631 privateDicts[0].dictData =
new GString();
632 privateDicts[0].subrsOffset = 0;
633 privateDicts[0].defaultWidthX = 0;
634 privateDicts[0].defaultWidthXFP = gFalse;
635 privateDicts[0].nominalWidthX = 0;
636 privateDicts[0].nominalWidthXFP = gFalse;
638 fdArrayIdx = (Guchar *)file + dict.fdArrayOffset;
639 nFDs = getIndexLen(fdArrayIdx);
640 privateDicts = (Type1CPrivateDict *)
641 gmalloc(nFDs *
sizeof(Type1CPrivateDict));
642 idxPtr1 = getIndexValPtr(fdArrayIdx, 0);
643 for (i = 0; i < nFDs; ++i) {
644 privateDicts[i].dictData = NULL;
646 idxPtr1 = getIndexValPtr(fdArrayIdx, i + 1);
649 while (ptr < idxPtr1) {
650 if (*ptr <= 27 || *ptr == 31) {
653 key = (key << 8) | *ptr++;
656 readPrivateDict(&privateDicts[i], (
int)op[1], (
int)op[0]);
660 x = getNum(&ptr, &isFP);
667 if (!privateDicts[i].dictData) {
668 privateDicts[i].dictData =
new GString();
669 privateDicts[i].subrsOffset = 0;
670 privateDicts[i].defaultWidthX = 0;
671 privateDicts[i].defaultWidthXFP = gFalse;
672 privateDicts[i].nominalWidthX = 0;
673 privateDicts[i].nominalWidthXFP = gFalse;
679 charStringsIdxPtr = (Guchar *)file + dict.charStrings;
680 nGlyphs = getIndexLen(charStringsIdxPtr);
683 fdSelect = (Guchar *)gmalloc(nGlyphs);
684 if (dict.fdSelectOffset == 0) {
685 for (i = 0; i < nGlyphs; ++i) {
689 ptr = (Guchar *)file + dict.fdSelectOffset;
690 fdSelectFmt = *ptr++;
691 if (fdSelectFmt == 0) {
692 memcpy(fdSelect, ptr, nGlyphs);
693 }
else if (fdSelectFmt == 3) {
694 nRanges = getWord(ptr, 2);
696 gid0 = getWord(ptr, 2);
698 for (i = 1; i <= nRanges; ++i) {
700 gid1 = getWord(ptr, 2);
702 for (j = gid0; j < gid1; ++j) {
708 error(-1,
"Unknown FDSelect table format in CID font");
709 for (i = 0; i < nGlyphs; ++i) {
716 charset = readCharset(dict.charset, nGlyphs);
718 for (i = 0; i < nGlyphs; ++i) {
719 if (charset[i] >= nCIDs) {
720 nCIDs = charset[i] + 1;
723 cidMap = (
int *)gmalloc(nCIDs *
sizeof(
int));
724 for (i = 0; i < nCIDs; ++i) {
727 for (i = 0; i < nGlyphs; ++i) {
728 cidMap[charset[i]] = i;
732 charStrings =
new GString();
733 charStringOffsets = (
int *)gmalloc((nCIDs + 1) *
sizeof(
int));
734 for (i = 0; i < nCIDs; ++i) {
735 charStringOffsets[i] = charStrings->getLength();
736 if (cidMap[i] >= 0) {
737 idxPtr0 = getIndexValPtr(charStringsIdxPtr, cidMap[i]);
738 idxPtr1 = getIndexValPtr(charStringsIdxPtr, cidMap[i]+1);
739 n = idxPtr1 - idxPtr0;
740 j = fdSelect[cidMap[i]];
741 defaultWidthX = privateDicts[j].defaultWidthX;
742 defaultWidthXFP = privateDicts[j].defaultWidthXFP;
743 nominalWidthX = privateDicts[j].nominalWidthX;
744 nominalWidthXFP = privateDicts[j].nominalWidthXFP;
745 cvtGlyph(idxPtr0, n);
746 charStrings->append(charBuf);
750 charStringOffsets[nCIDs] = charStrings->getLength();
756 i = (nCIDs + 1) * 5 + charStrings->getLength();
759 }
else if (i < 0x10000) {
761 }
else if (i < 0x1000000) {
768 (*outputFunc)(outputStream,
"20 dict begin\n", 14);
769 (*outputFunc)(outputStream,
"/CIDFontName /", 14);
770 (*outputFunc)(outputStream, psName, strlen(psName));
771 (*outputFunc)(outputStream,
" def\n", 5);
772 (*outputFunc)(outputStream,
"/CIDFontType 0 def\n", 19);
773 (*outputFunc)(outputStream,
"/CIDSystemInfo 3 dict dup begin\n", 32);
774 if (dict.registry > 0 && dict.ordering > 0) {
775 getString(dict.registry, buf);
776 (*outputFunc)(outputStream,
" /Registry (", 13);
777 (*outputFunc)(outputStream, buf, strlen(buf));
778 (*outputFunc)(outputStream,
") def\n", 6);
779 getString(dict.ordering, buf);
780 (*outputFunc)(outputStream,
" /Ordering (", 13);
781 (*outputFunc)(outputStream, buf, strlen(buf));
782 (*outputFunc)(outputStream,
") def\n", 6);
784 (*outputFunc)(outputStream,
" /Registry (Adobe) def\n", 24);
785 (*outputFunc)(outputStream,
" /Ordering (Identity) def\n", 27);
787 sprintf(buf,
" /Supplement %d def\n", dict.supplement);
788 (*outputFunc)(outputStream, buf, strlen(buf));
789 (*outputFunc)(outputStream,
"end def\n", 8);
790 sprintf(buf,
"/FontMatrix [%g %g %g %g %g %g] def\n",
791 dict.fontMatrix[0], dict.fontMatrix[1], dict.fontMatrix[2],
792 dict.fontMatrix[3], dict.fontMatrix[4], dict.fontMatrix[5]);
793 (*outputFunc)(outputStream, buf, strlen(buf));
794 sprintf(buf,
"/FontBBox [%g %g %g %g] def\n",
795 dict.fontBBox[0], dict.fontBBox[1],
796 dict.fontBBox[2], dict.fontBBox[3]);
797 (*outputFunc)(outputStream, buf, strlen(buf));
798 (*outputFunc)(outputStream,
"/FontInfo 1 dict dup begin\n", 27);
799 (*outputFunc)(outputStream,
" /FSType 8 def\n", 16);
800 (*outputFunc)(outputStream,
"end def\n", 8);
803 sprintf(buf,
"/CIDCount %d def\n", nCIDs);
804 (*outputFunc)(outputStream, buf, strlen(buf));
805 (*outputFunc)(outputStream,
"/FDBytes 1 def\n", 15);
806 sprintf(buf,
"/GDBytes %d def\n", gdBytes);
807 (*outputFunc)(outputStream, buf, strlen(buf));
808 (*outputFunc)(outputStream,
"/CIDMapOffset 0 def\n", 20);
809 if (dict.paintType != 0) {
810 sprintf(buf,
"/PaintType %d def\n", dict.paintType);
811 (*outputFunc)(outputStream, buf, strlen(buf));
812 sprintf(buf,
"/StrokeWidth %g def\n", dict.strokeWidth);
813 (*outputFunc)(outputStream, buf, strlen(buf));
817 sprintf(buf,
"/FDArray %d array\n", nFDs);
818 (*outputFunc)(outputStream, buf, strlen(buf));
819 for (i = 0; i < nFDs; ++i) {
820 sprintf(buf,
"dup %d 10 dict begin\n", i);
821 (*outputFunc)(outputStream, buf, strlen(buf));
822 (*outputFunc)(outputStream,
"/FontType 1 def\n", 16);
823 (*outputFunc)(outputStream,
"/FontMatrix [1 0 0 1 0 0] def\n", 30);
824 sprintf(buf,
"/PaintType %d def\n", dict.paintType);
825 (*outputFunc)(outputStream, buf, strlen(buf));
826 (*outputFunc)(outputStream,
"/Private 32 dict begin\n", 23);
827 (*outputFunc)(outputStream, privateDicts[i].dictData->getCString(),
828 privateDicts[i].dictData->getLength());
829 (*outputFunc)(outputStream,
"currentdict end def\n", 20);
830 (*outputFunc)(outputStream,
"currentdict end put\n", 20);
832 (*outputFunc)(outputStream,
"def\n", 4);
837 offset = (nCIDs + 1) * (1 + gdBytes);
838 sprintf(buf,
"(Hex) %d StartData\n",
839 offset + charStrings->getLength());
840 (*outputFunc)(outputStream, buf, strlen(buf));
843 for (i = 0; i <= nCIDs; i += 6) {
844 for (j = 0; j < 6 && i+j <= nCIDs; ++j) {
845 if (i+j < nCIDs && cidMap[i+j] >= 0) {
846 buf[0] = (char)fdSelect[cidMap[i+j]];
850 n = offset + charStringOffsets[i+j];
851 for (k = gdBytes; k >= 1; --k) {
852 buf[k] = (char)(n & 0xff);
855 for (k = 0; k <= gdBytes; ++k) {
856 sprintf(buf2,
"%02x", buf[k] & 0xff);
857 (*outputFunc)(outputStream, buf2, 2);
860 (*outputFunc)(outputStream,
"\n", 1);
864 n = charStrings->getLength();
865 for (i = 0; i < n; i += 32) {
866 for (j = 0; j < 32 && i+j < n; ++j) {
867 sprintf(buf,
"%02x", charStrings->getChar(i+j) & 0xff);
868 (*outputFunc)(outputStream, buf, strlen(buf));
871 (*outputFunc)(outputStream,
">", 1);
873 (*outputFunc)(outputStream,
"\n", 1);
876 for (i = 0; i < nFDs; ++i) {
877 delete privateDicts[i].dictData;
882 gfree(charStringOffsets);
887void Type1CFontFile::convertToType0(
const char *psName,
888 FontFileOutputFunc outputFuncA,
889 void *outputStreamA) {
891 Type1CPrivateDict *privateDicts;
895 Guchar *charStringsIdxPtr, *fdArrayIdx, *idxPtr0, *idxPtr1, *ptr;
898 int nGlyphs, nCIDs, nFDs;
899 int fdSelectFmt, nRanges, gid0, gid1, fd;
905 outputFunc = outputFuncA;
906 outputStream = outputStreamA;
912 if (dict.fdArrayOffset == 0) {
914 privateDicts = (Type1CPrivateDict *)
915 gmalloc(nFDs *
sizeof(Type1CPrivateDict));
916 privateDicts[0].dictData =
new GString();
917 privateDicts[0].subrsOffset = 0;
918 privateDicts[0].defaultWidthX = 0;
919 privateDicts[0].defaultWidthXFP = gFalse;
920 privateDicts[0].nominalWidthX = 0;
921 privateDicts[0].nominalWidthXFP = gFalse;
923 fdArrayIdx = (Guchar *)file + dict.fdArrayOffset;
924 nFDs = getIndexLen(fdArrayIdx);
925 privateDicts = (Type1CPrivateDict *)
926 gmalloc(nFDs *
sizeof(Type1CPrivateDict));
927 idxPtr1 = getIndexValPtr(fdArrayIdx, 0);
928 for (i = 0; i < nFDs; ++i) {
929 privateDicts[i].dictData = NULL;
931 idxPtr1 = getIndexValPtr(fdArrayIdx, i + 1);
934 while (ptr < idxPtr1) {
935 if (*ptr <= 27 || *ptr == 31) {
938 key = (key << 8) | *ptr++;
941 readPrivateDict(&privateDicts[i], (
int)op[1], (
int)op[0]);
945 x = getNum(&ptr, &isFP);
952 if (!privateDicts[i].dictData) {
953 privateDicts[i].dictData =
new GString();
954 privateDicts[i].subrsOffset = 0;
955 privateDicts[i].defaultWidthX = 0;
956 privateDicts[i].defaultWidthXFP = gFalse;
957 privateDicts[i].nominalWidthX = 0;
958 privateDicts[i].nominalWidthXFP = gFalse;
964 charStringsIdxPtr = (Guchar *)file + dict.charStrings;
965 nGlyphs = getIndexLen(charStringsIdxPtr);
968 fdSelect = (Guchar *)gmalloc(nGlyphs);
969 if (dict.fdSelectOffset == 0) {
970 for (i = 0; i < nGlyphs; ++i) {
974 ptr = (Guchar *)file + dict.fdSelectOffset;
975 fdSelectFmt = *ptr++;
976 if (fdSelectFmt == 0) {
977 memcpy(fdSelect, ptr, nGlyphs);
978 }
else if (fdSelectFmt == 3) {
979 nRanges = getWord(ptr, 2);
981 gid0 = getWord(ptr, 2);
983 for (i = 1; i <= nRanges; ++i) {
985 gid1 = getWord(ptr, 2);
987 for (j = gid0; j < gid1; ++j) {
993 error(-1,
"Unknown FDSelect table format in CID font");
994 for (i = 0; i < nGlyphs; ++i) {
1001 charset = readCharset(dict.charset, nGlyphs);
1003 for (i = 0; i < nGlyphs; ++i) {
1004 if (charset[i] >= nCIDs) {
1005 nCIDs = charset[i] + 1;
1008 cidMap = (
int *)gmalloc(nCIDs *
sizeof(
int));
1009 for (i = 0; i < nCIDs; ++i) {
1012 for (i = 0; i < nGlyphs; ++i) {
1013 cidMap[charset[i]] = i;
1017 for (i = 0; i < nCIDs; i += 256) {
1023 for (j = 0; j < 256 && i+j < nCIDs; ++j) {
1024 if (cidMap[i+j] >= 0) {
1025 fd = fdSelect[cidMap[i+j]];
1031 (*outputFunc)(outputStream,
"16 dict begin\n", 14);
1032 (*outputFunc)(outputStream,
"/FontName /", 11);
1033 (*outputFunc)(outputStream, psName, strlen(psName));
1034 sprintf(buf,
"_%02x def\n", i >> 8);
1035 (*outputFunc)(outputStream, buf, strlen(buf));
1036 (*outputFunc)(outputStream,
"/FontType 1 def\n", 16);
1037 sprintf(buf,
"/FontMatrix [%g %g %g %g %g %g] def\n",
1038 dict.fontMatrix[0], dict.fontMatrix[1], dict.fontMatrix[2],
1039 dict.fontMatrix[3], dict.fontMatrix[4], dict.fontMatrix[5]);
1040 (*outputFunc)(outputStream, buf, strlen(buf));
1041 sprintf(buf,
"/FontBBox [%g %g %g %g] def\n",
1042 dict.fontBBox[0], dict.fontBBox[1],
1043 dict.fontBBox[2], dict.fontBBox[3]);
1044 (*outputFunc)(outputStream, buf, strlen(buf));
1045 sprintf(buf,
"/PaintType %d def\n", dict.paintType);
1046 (*outputFunc)(outputStream, buf, strlen(buf));
1047 if (dict.paintType != 0) {
1048 sprintf(buf,
"/StrokeWidth %g def\n", dict.strokeWidth);
1049 (*outputFunc)(outputStream, buf, strlen(buf));
1051 (*outputFunc)(outputStream,
"/Encoding 256 array\n", 20);
1052 for (j = 0; j < 256 && i+j < nCIDs; ++j) {
1053 sprintf(buf,
"dup %d /c%02x put\n", j, j);
1054 (*outputFunc)(outputStream, buf, strlen(buf));
1056 (*outputFunc)(outputStream,
"readonly def\n", 13);
1057 (*outputFunc)(outputStream,
"currentdict end\n", 16);
1060 (*outputFunc)(outputStream,
"currentfile eexec\n", 18);
1065 eexecWrite(
"\x83\xca\x73\xd5");
1066 eexecWrite(
"dup /Private 32 dict dup begin\n");
1067 eexecWrite(
"/RD {string currentfile exch readstring pop} executeonly def\n");
1068 eexecWrite(
"/ND {noaccess def} executeonly def\n");
1069 eexecWrite(
"/NP {noaccess put} executeonly def\n");
1070 eexecWrite(
"/MinFeature {16 16} ND\n");
1071 eexecWrite(privateDicts[fd].dictData->getCString());
1072 defaultWidthX = privateDicts[fd].defaultWidthX;
1073 defaultWidthXFP = privateDicts[fd].defaultWidthXFP;
1074 nominalWidthX = privateDicts[fd].nominalWidthX;
1075 nominalWidthXFP = privateDicts[fd].nominalWidthXFP;
1078 sprintf(eBuf,
"2 index /CharStrings 256 dict dup begin\n");
1082 idxPtr0 = getIndexValPtr(charStringsIdxPtr, 0);
1083 idxPtr1 = getIndexValPtr(charStringsIdxPtr, 1);
1084 n = idxPtr1 - idxPtr0;
1085 eexecCvtGlyph(
".notdef", idxPtr0, n);
1088 for (j = 0; j < 256 && i+j < nCIDs; ++j) {
1089 if (cidMap[i+j] >= 0) {
1090 idxPtr0 = getIndexValPtr(charStringsIdxPtr, cidMap[i+j]);
1091 idxPtr1 = getIndexValPtr(charStringsIdxPtr, cidMap[i+j]+1);
1092 n = idxPtr1 - idxPtr0;
1093 sprintf(buf,
"c%02x", j);
1094 eexecCvtGlyph(buf, idxPtr0, n);
1097 eexecWrite(
"end\n");
1098 eexecWrite(
"end\n");
1099 eexecWrite(
"readonly put\n");
1100 eexecWrite(
"noaccess put\n");
1101 eexecWrite(
"dup /FontName get exch definefont pop\n");
1102 eexecWrite(
"mark currentfile closefile\n");
1106 (*outputFunc)(outputStream,
"\n", 1);
1108 for (j = 0; j < 8; ++j) {
1109 (*outputFunc)(outputStream,
"0000000000000000000000000000000000000000000000000000000000000000\n", 65);
1111 (*outputFunc)(outputStream,
"cleartomark\n", 12);
1115 (*outputFunc)(outputStream,
"16 dict begin\n", 14);
1116 (*outputFunc)(outputStream,
"/FontName /", 11);
1117 (*outputFunc)(outputStream, psName, strlen(psName));
1118 (*outputFunc)(outputStream,
" def\n", 5);
1119 (*outputFunc)(outputStream,
"/FontType 0 def\n", 16);
1120 (*outputFunc)(outputStream,
"/FontMatrix [1 0 0 1 0 0] def\n", 30);
1121 (*outputFunc)(outputStream,
"/FMapType 2 def\n", 16);
1122 (*outputFunc)(outputStream,
"/Encoding [\n", 12);
1123 for (i = 0; i < nCIDs; i += 256) {
1124 sprintf(buf,
"%d\n", i >> 8);
1125 (*outputFunc)(outputStream, buf, strlen(buf));
1127 (*outputFunc)(outputStream,
"] def\n", 6);
1128 (*outputFunc)(outputStream,
"/FDepVector [\n", 14);
1129 for (i = 0; i < nCIDs; i += 256) {
1130 (*outputFunc)(outputStream,
"/", 1);
1131 (*outputFunc)(outputStream, psName, strlen(psName));
1132 sprintf(buf,
"_%02x findfont\n", i >> 8);
1133 (*outputFunc)(outputStream, buf, strlen(buf));
1135 (*outputFunc)(outputStream,
"] def\n", 6);
1136 (*outputFunc)(outputStream,
"FontName currentdict end definefont pop\n", 40);
1139 for (i = 0; i < nFDs; ++i) {
1140 delete privateDicts[i].dictData;
1142 gfree(privateDicts);
1148void Type1CFontFile::readTopDict(Type1CTopDict *dict) {
1149 Guchar *idxPtr0, *idxPtr1, *ptr;
1155 idxPtr0 = getIndexValPtr(topDictIdxPtr, 0);
1156 idxPtr1 = getIndexValPtr(topDictIdxPtr, 1);
1159 dict->copyright = 0;
1161 dict->familyName = 0;
1163 dict->isFixedPitch = 0;
1164 dict->italicAngle = 0;
1165 dict->underlinePosition = -100;
1166 dict->underlineThickness = 50;
1167 dict->paintType = 0;
1168 dict->charstringType = 2;
1169 dict->fontMatrix[0] = 0.001;
1170 dict->fontMatrix[1] = 0;
1171 dict->fontMatrix[2] = 0;
1172 dict->fontMatrix[3] = 0.001;
1173 dict->fontMatrix[4] = 0;
1174 dict->fontMatrix[5] = 0;
1176 dict->fontBBox[0] = 0;
1177 dict->fontBBox[1] = 0;
1178 dict->fontBBox[2] = 0;
1179 dict->fontBBox[3] = 0;
1180 dict->strokeWidth = 0;
1183 dict->charStrings = 0;
1184 dict->privateSize = 0;
1185 dict->privateOffset = 0;
1188 dict->supplement = 0;
1189 dict->fdArrayOffset = 0;
1190 dict->fdSelectOffset = 0;
1193 while (ptr < idxPtr1) {
1194 if (*ptr <= 27 || *ptr == 31) {
1197 key = (key << 8) | *ptr++;
1200 case 0x0000: dict->version = (int)op[0];
break;
1201 case 0x0001: dict->notice = (int)op[0];
break;
1202 case 0x0c00: dict->copyright = (int)op[0];
break;
1203 case 0x0002: dict->fullName = (int)op[0];
break;
1204 case 0x0003: dict->familyName = (int)op[0];
break;
1205 case 0x0004: dict->weight = (int)op[0];
break;
1206 case 0x0c01: dict->isFixedPitch = (int)op[0];
break;
1207 case 0x0c02: dict->italicAngle = op[0];
break;
1208 case 0x0c03: dict->underlinePosition = op[0];
break;
1209 case 0x0c04: dict->underlineThickness = op[0];
break;
1210 case 0x0c05: dict->paintType = (int)op[0];
break;
1211 case 0x0c06: dict->charstringType = (int)op[0];
break;
1212 case 0x0c07: dict->fontMatrix[0] = op[0];
1213 dict->fontMatrix[1] = op[1];
1214 dict->fontMatrix[2] = op[2];
1215 dict->fontMatrix[3] = op[3];
1216 dict->fontMatrix[4] = op[4];
1217 dict->fontMatrix[5] = op[5];
break;
1218 case 0x000d: dict->uniqueID = (int)op[0];
break;
1219 case 0x0005: dict->fontBBox[0] = op[0];
1220 dict->fontBBox[1] = op[1];
1221 dict->fontBBox[2] = op[2];
1222 dict->fontBBox[3] = op[3];
break;
1223 case 0x0c08: dict->strokeWidth = op[0];
break;
1224 case 0x000f: dict->charset = (int)op[0];
break;
1225 case 0x0010: dict->encoding = (int)op[0];
break;
1226 case 0x0011: dict->charStrings = (int)op[0];
break;
1227 case 0x0012: dict->privateSize = (int)op[0];
1228 dict->privateOffset = (int)op[1];
break;
1229 case 0x0c1e: dict->registry = (int)op[0];
1230 dict->ordering = (int)op[1];
1231 dict->supplement = (int)op[2];
break;
1232 case 0x0c24: dict->fdArrayOffset = (int)op[0];
break;
1233 case 0x0c25: dict->fdSelectOffset = (int)op[0];
break;
1237 x = getNum(&ptr, &isFP);
1246void Type1CFontFile::readPrivateDict(Type1CPrivateDict *privateDict,
1247 int offset,
int size) {
1248 Guchar *idxPtr0, *idxPtr1, *ptr;
1255 privateDict->dictData =
new GString();
1256 privateDict->subrsOffset = 0;
1257 privateDict->defaultWidthX = 0;
1258 privateDict->defaultWidthXFP = gFalse;
1259 privateDict->nominalWidthX = 0;
1260 privateDict->nominalWidthXFP = gFalse;
1261 idxPtr0 = (Guchar *)file + offset;
1262 idxPtr1 = idxPtr0 + size;
1265 while (ptr < idxPtr1) {
1266 if (*ptr <= 27 || *ptr == 31) {
1269 key = (key << 8) | *ptr++;
1273 getDeltaInt(eBuf,
"BlueValues", op, i);
1274 privateDict->dictData->append(eBuf);
1277 getDeltaInt(eBuf,
"OtherBlues", op, i);
1278 privateDict->dictData->append(eBuf);
1281 getDeltaInt(eBuf,
"FamilyBlues", op, i);
1282 privateDict->dictData->append(eBuf);
1285 getDeltaInt(eBuf,
"FamilyOtherBlues", op, i);
1286 privateDict->dictData->append(eBuf);
1289 sprintf(eBuf,
"/BlueScale %g def\n", op[0]);
1290 privateDict->dictData->append(eBuf);
1293 sprintf(eBuf,
"/BlueShift %d def\n", (
int)op[0]);
1294 privateDict->dictData->append(eBuf);
1297 sprintf(eBuf,
"/BlueFuzz %d def\n", (
int)op[0]);
1298 privateDict->dictData->append(eBuf);
1301 sprintf(eBuf,
"/StdHW [%g] def\n", op[0]);
1302 privateDict->dictData->append(eBuf);
1305 sprintf(eBuf,
"/StdVW [%g] def\n", op[0]);
1306 privateDict->dictData->append(eBuf);
1309 getDeltaReal(eBuf,
"StemSnapH", op, i);
1310 privateDict->dictData->append(eBuf);
1313 getDeltaReal(eBuf,
"StemSnapV", op, i);
1314 privateDict->dictData->append(eBuf);
1317 sprintf(eBuf,
"/ForceBold %s def\n", op[0] ?
"true" :
"false");
1318 privateDict->dictData->append(eBuf);
1321 sprintf(eBuf,
"/ForceBoldThreshold %g def\n", op[0]);
1322 privateDict->dictData->append(eBuf);
1325 sprintf(eBuf,
"/LanguageGroup %d def\n", (
int)op[0]);
1326 privateDict->dictData->append(eBuf);
1329 sprintf(eBuf,
"/ExpansionFactor %g def\n", op[0]);
1330 privateDict->dictData->append(eBuf);
1333 error(-1,
"Got Type 1C InitialRandomSeed");
1336 privateDict->subrsOffset = (int)op[0];
1339 privateDict->defaultWidthX = op[0];
1340 privateDict->defaultWidthXFP = fp[0];
1343 privateDict->nominalWidthX = op[0];
1344 privateDict->nominalWidthXFP = fp[0];
1347 error(-1,
"Unknown Type 1C private dict entry %04x", key);
1352 x = getNum(&ptr, &isFP);
1361Gushort *Type1CFontFile::readCharset(
int charset,
int nGlyphs) {
1362 Gushort *glyphNames;
1364 int charsetFormat, c;
1368 glyphNames = type1CISOAdobeCharset;
1369 }
else if (charset == 1) {
1370 glyphNames = type1CExpertCharset;
1371 }
else if (charset == 2) {
1372 glyphNames = type1CExpertSubsetCharset;
1374 glyphNames = (Gushort *)gmalloc(nGlyphs *
sizeof(Gushort));
1376 ptr = (Guchar *)file + charset;
1377 charsetFormat = *ptr++;
1378 if (charsetFormat == 0) {
1379 for (i = 1; i < nGlyphs; ++i) {
1380 glyphNames[i] = getWord(ptr, 2);
1383 }
else if (charsetFormat == 1) {
1385 while (i < nGlyphs) {
1386 c = getWord(ptr, 2);
1389 for (j = 0; j <= nLeft && i < nGlyphs; ++j) {
1390 glyphNames[i++] = c++;
1393 }
else if (charsetFormat == 2) {
1395 while (i < nGlyphs) {
1396 c = getWord(ptr, 2);
1398 nLeft = getWord(ptr, 2);
1400 for (j = 0; j <= nLeft && i < nGlyphs; ++j) {
1401 glyphNames[i++] = c++;
1409void Type1CFontFile::eexecWrite(
const char *s) {
1413 for (p = (
const Guchar *)s; *p; ++p) {
1415 r1 = (x + r1) * 52845 + 22719;
1416 (*outputFunc)(outputStream, &hexChars[x >> 4], 1);
1417 (*outputFunc)(outputStream, &hexChars[x & 0x0f], 1);
1420 (*outputFunc)(outputStream,
"\n", 1);
1426void Type1CFontFile::eexecCvtGlyph(
const char *glyphName,
const Guchar *s,
int n) {
1430 sprintf(eBuf,
"/%s %d RD ", glyphName, charBuf->getLength());
1432 eexecWriteCharstring((Guchar *)charBuf->getCString(), charBuf->getLength());
1433 eexecWrite(
" ND\n");
1437void Type1CFontFile::cvtGlyph(
const Guchar *s,
int n) {
1440 GBool first = gTrue;
1447 charBuf =
new GString();
1448 charBuf->append((
char)73);
1449 charBuf->append((
char)58);
1450 charBuf->append((
char)147);
1451 charBuf->append((
char)134);
1464 error(-1,
"Wrong number of args (%d) to Type 2 hflex", nOps);
1466 eexecDumpNum(op[0], fp[0]);
1467 eexecDumpNum(0, gFalse);
1468 eexecDumpNum(op[1], fp[1]);
1469 eexecDumpNum(op[2], fp[2]);
1470 eexecDumpNum(op[3], fp[3]);
1471 eexecDumpNum(0, gFalse);
1473 eexecDumpNum(op[4], fp[4]);
1474 eexecDumpNum(0, gFalse);
1475 eexecDumpNum(op[5], fp[5]);
1476 eexecDumpNum(-op[2], fp[2]);
1477 eexecDumpNum(op[6], fp[6]);
1478 eexecDumpNum(0, gFalse);
1483 error(-1,
"Wrong number of args (%d) to Type 2 flex", nOps);
1485 eexecDumpNum(op[0], fp[0]);
1486 eexecDumpNum(op[1], fp[1]);
1487 eexecDumpNum(op[2], fp[2]);
1488 eexecDumpNum(op[3], fp[3]);
1489 eexecDumpNum(op[4], fp[4]);
1490 eexecDumpNum(op[5], fp[5]);
1492 eexecDumpNum(op[6], fp[6]);
1493 eexecDumpNum(op[7], fp[7]);
1494 eexecDumpNum(op[8], fp[8]);
1495 eexecDumpNum(op[9], fp[9]);
1496 eexecDumpNum(op[10], fp[10]);
1497 eexecDumpNum(op[11], fp[11]);
1502 error(-1,
"Wrong number of args (%d) to Type 2 hflex1", nOps);
1504 eexecDumpNum(op[0], fp[0]);
1505 eexecDumpNum(op[1], fp[1]);
1506 eexecDumpNum(op[2], fp[2]);
1507 eexecDumpNum(op[3], fp[3]);
1508 eexecDumpNum(op[4], fp[4]);
1509 eexecDumpNum(0, gFalse);
1511 eexecDumpNum(op[5], fp[5]);
1512 eexecDumpNum(0, gFalse);
1513 eexecDumpNum(op[6], fp[6]);
1514 eexecDumpNum(op[7], fp[7]);
1515 eexecDumpNum(op[8], fp[8]);
1516 eexecDumpNum(-(op[1] + op[3] + op[7]), fp[1] | fp[3] | fp[7]);
1521 error(-1,
"Wrong number of args (%d) to Type 2 flex1", nOps);
1523 eexecDumpNum(op[0], fp[0]);
1524 eexecDumpNum(op[1], fp[1]);
1525 eexecDumpNum(op[2], fp[2]);
1526 eexecDumpNum(op[3], fp[3]);
1527 eexecDumpNum(op[4], fp[4]);
1528 eexecDumpNum(op[5], fp[5]);
1530 eexecDumpNum(op[6], fp[6]);
1531 eexecDumpNum(op[7], fp[7]);
1532 eexecDumpNum(op[8], fp[8]);
1533 eexecDumpNum(op[9], fp[9]);
1534 dx = op[0] + op[2] + op[4] + op[6] + op[8];
1535 dy = op[1] + op[3] + op[5] + op[7] + op[9];
1536 if (fabs(dx) > fabs(dy)) {
1537 eexecDumpNum(op[10], fp[10]);
1538 eexecDumpNum(-dy, fp[1] | fp[3] | fp[5] | fp[7] | fp[9]);
1540 eexecDumpNum(-dx, fp[0] | fp[2] | fp[4] | fp[6] | fp[8]);
1541 eexecDumpNum(op[10], fp[10]);
1567 error(-1,
"Unimplemented Type 2 charstring op: 12.%d", s[i+1]);
1570 error(-1,
"Illegal Type 2 charstring op: 12.%d", s[i+1]);
1575 }
else if (s[i] == 19) {
1578 cvtGlyphWidth(nOps == 1);
1583 error(-1,
"Wrong number of args (%d) to Type 2 hintmask/vstemhm",
1588 i += 1 + ((nHints + 7) >> 3);
1590 }
else if (s[i] == 20) {
1593 cvtGlyphWidth(nOps == 1);
1598 error(-1,
"Wrong number of args (%d) to Type 2 cntrmask/vstemhm",
1603 i += 1 + ((nHints + 7) >> 3);
1605 }
else if (s[i] == 28) {
1606 x = (s[i+1] << 8) + s[i+2];
1615 }
else if (s[i] <= 31) {
1619 cvtGlyphWidth(nOps == 2);
1623 error(-1,
"Wrong number of args (%d) to Type 2 vmoveto", nOps);
1625 eexecDumpNum(op[0], fp[0]);
1629 if (nOps < 2 || nOps % 2 != 0) {
1630 error(-1,
"Wrong number of args (%d) to Type 2 rlineto", nOps);
1632 for (k = 0; k < nOps; k += 2) {
1633 eexecDumpNum(op[k], fp[k]);
1634 eexecDumpNum(op[k+1], fp[k+1]);
1640 error(-1,
"Wrong number of args (%d) to Type 2 hlineto", nOps);
1642 for (k = 0; k < nOps; ++k) {
1643 eexecDumpNum(op[k], fp[k]);
1644 eexecDumpOp1((k & 1) ? 7 : 6);
1649 error(-1,
"Wrong number of args (%d) to Type 2 vlineto", nOps);
1651 for (k = 0; k < nOps; ++k) {
1652 eexecDumpNum(op[k], fp[k]);
1653 eexecDumpOp1((k & 1) ? 6 : 7);
1657 if (nOps < 6 || nOps % 6 != 0) {
1658 error(-1,
"Wrong number of args (%d) to Type 2 rrcurveto", nOps);
1660 for (k = 0; k < nOps; k += 6) {
1661 eexecDumpNum(op[k], fp[k]);
1662 eexecDumpNum(op[k+1], fp[k+1]);
1663 eexecDumpNum(op[k+2], fp[k+2]);
1664 eexecDumpNum(op[k+3], fp[k+3]);
1665 eexecDumpNum(op[k+4], fp[k+4]);
1666 eexecDumpNum(op[k+5], fp[k+5]);
1672 cvtGlyphWidth(nOps == 1 || nOps == 5);
1677 eexecDumpNum(op[0], fp[0]);
1678 eexecDumpNum(op[1], fp[1]);
1679 eexecDumpNum(op[2], fp[2]);
1680 eexecDumpNum(op[3], fp[3]);
1682 }
else if (nOps == 0) {
1685 error(-1,
"Wrong number of args (%d) to Type 2 endchar", nOps);
1690 cvtGlyphWidth(nOps == 3);
1694 error(-1,
"Wrong number of args (%d) to Type 2 rmoveto", nOps);
1696 eexecDumpNum(op[0], fp[0]);
1697 eexecDumpNum(op[1], fp[1]);
1702 cvtGlyphWidth(nOps == 2);
1706 error(-1,
"Wrong number of args (%d) to Type 2 hmoveto", nOps);
1708 eexecDumpNum(op[0], fp[0]);
1712 if (nOps < 8 || (nOps - 2) % 6 != 0) {
1713 error(-1,
"Wrong number of args (%d) to Type 2 rcurveline", nOps);
1715 for (k = 0; k < nOps - 2; k += 6) {
1716 eexecDumpNum(op[k], fp[k]);
1717 eexecDumpNum(op[k+1], fp[k+1]);
1718 eexecDumpNum(op[k+2], fp[k+2]);
1719 eexecDumpNum(op[k+3], fp[k+3]);
1720 eexecDumpNum(op[k+4], fp[k+4]);
1721 eexecDumpNum(op[k+5], fp[k+5]);
1724 eexecDumpNum(op[k], fp[k]);
1725 eexecDumpNum(op[k+1], fp[k]);
1729 if (nOps < 8 || (nOps - 6) % 2 != 0) {
1730 error(-1,
"Wrong number of args (%d) to Type 2 rlinecurve", nOps);
1732 for (k = 0; k < nOps - 6; k += 2) {
1733 eexecDumpNum(op[k], fp[k]);
1734 eexecDumpNum(op[k+1], fp[k]);
1737 eexecDumpNum(op[k], fp[k]);
1738 eexecDumpNum(op[k+1], fp[k+1]);
1739 eexecDumpNum(op[k+2], fp[k+2]);
1740 eexecDumpNum(op[k+3], fp[k+3]);
1741 eexecDumpNum(op[k+4], fp[k+4]);
1742 eexecDumpNum(op[k+5], fp[k+5]);
1746 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
1747 error(-1,
"Wrong number of args (%d) to Type 2 vvcurveto", nOps);
1749 if (nOps % 2 == 1) {
1750 eexecDumpNum(op[0], fp[0]);
1751 eexecDumpNum(op[1], fp[1]);
1752 eexecDumpNum(op[2], fp[2]);
1753 eexecDumpNum(op[3], fp[3]);
1754 eexecDumpNum(0, gFalse);
1755 eexecDumpNum(op[4], fp[4]);
1761 for (; k < nOps; k += 4) {
1762 eexecDumpNum(0, gFalse);
1763 eexecDumpNum(op[k], fp[k]);
1764 eexecDumpNum(op[k+1], fp[k+1]);
1765 eexecDumpNum(op[k+2], fp[k+2]);
1766 eexecDumpNum(0, gFalse);
1767 eexecDumpNum(op[k+3], fp[k+3]);
1772 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
1773 error(-1,
"Wrong number of args (%d) to Type 2 hhcurveto", nOps);
1775 if (nOps % 2 == 1) {
1776 eexecDumpNum(op[1], fp[1]);
1777 eexecDumpNum(op[0], fp[0]);
1778 eexecDumpNum(op[2], fp[2]);
1779 eexecDumpNum(op[3], fp[3]);
1780 eexecDumpNum(op[4], fp[4]);
1781 eexecDumpNum(0, gFalse);
1787 for (; k < nOps; k += 4) {
1788 eexecDumpNum(op[k], fp[k]);
1789 eexecDumpNum(0, gFalse);
1790 eexecDumpNum(op[k+1], fp[k+1]);
1791 eexecDumpNum(op[k+2], fp[k+2]);
1792 eexecDumpNum(op[k+3], fp[k+3]);
1793 eexecDumpNum(0, gFalse);
1798 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
1799 error(-1,
"Wrong number of args (%d) to Type 2 vhcurveto", nOps);
1801 for (k = 0; k < nOps && k != nOps-5; k += 4) {
1803 eexecDumpNum(op[k], fp[k]);
1804 eexecDumpNum(op[k+1], fp[k+1]);
1805 eexecDumpNum(op[k+2], fp[k+2]);
1806 eexecDumpNum(op[k+3], fp[k+3]);
1809 eexecDumpNum(op[k], fp[k]);
1810 eexecDumpNum(op[k+1], fp[k+1]);
1811 eexecDumpNum(op[k+2], fp[k+2]);
1812 eexecDumpNum(op[k+3], fp[k+3]);
1818 eexecDumpNum(0, gFalse);
1819 eexecDumpNum(op[k], fp[k]);
1820 eexecDumpNum(op[k+1], fp[k+1]);
1821 eexecDumpNum(op[k+2], fp[k+2]);
1822 eexecDumpNum(op[k+3], fp[k+3]);
1823 eexecDumpNum(op[k+4], fp[k+4]);
1825 eexecDumpNum(op[k], fp[k]);
1826 eexecDumpNum(0, gFalse);
1827 eexecDumpNum(op[k+1], fp[k+1]);
1828 eexecDumpNum(op[k+2], fp[k+2]);
1829 eexecDumpNum(op[k+4], fp[k+4]);
1830 eexecDumpNum(op[k+3], fp[k+3]);
1836 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
1837 error(-1,
"Wrong number of args (%d) to Type 2 hvcurveto", nOps);
1839 for (k = 0; k < nOps && k != nOps-5; k += 4) {
1841 eexecDumpNum(op[k], fp[k]);
1842 eexecDumpNum(op[k+1], fp[k+1]);
1843 eexecDumpNum(op[k+2], fp[k+2]);
1844 eexecDumpNum(op[k+3], fp[k+3]);
1847 eexecDumpNum(op[k], fp[k]);
1848 eexecDumpNum(op[k+1], fp[k+1]);
1849 eexecDumpNum(op[k+2], fp[k+2]);
1850 eexecDumpNum(op[k+3], fp[k+3]);
1856 eexecDumpNum(op[k], fp[k]);
1857 eexecDumpNum(0, gFalse);
1858 eexecDumpNum(op[k+1], fp[k+1]);
1859 eexecDumpNum(op[k+2], fp[k+2]);
1860 eexecDumpNum(op[k+4], fp[k+4]);
1861 eexecDumpNum(op[k+3], fp[k+3]);
1863 eexecDumpNum(0, gFalse);
1864 eexecDumpNum(op[k], fp[k]);
1865 eexecDumpNum(op[k+1], fp[k+1]);
1866 eexecDumpNum(op[k+2], fp[k+2]);
1867 eexecDumpNum(op[k+3], fp[k+3]);
1868 eexecDumpNum(op[k+4], fp[k+4]);
1875 cvtGlyphWidth(nOps & 1);
1879 error(-1,
"Wrong number of args (%d) to Type 2 hstem", nOps);
1883 for (k = 0; k < nOps; k += 2) {
1885 d += op[k] + op[k+1];
1886 dFP |= fp[k] | fp[k+1];
1887 eexecDumpNum(d, dFP);
1888 eexecDumpNum(-op[k+1], fp[k+1]);
1892 eexecDumpNum(d, dFP);
1893 eexecDumpNum(op[k+1], fp[k+1]);
1903 cvtGlyphWidth(nOps & 1);
1907 error(-1,
"Wrong number of args (%d) to Type 2 vstem", nOps);
1911 for (k = 0; k < nOps; k += 2) {
1913 d += op[k] + op[k+1];
1914 dFP |= fp[k] | fp[k+1];
1915 eexecDumpNum(d, dFP);
1916 eexecDumpNum(-op[k+1], fp[k+1]);
1920 eexecDumpNum(d, dFP);
1921 eexecDumpNum(op[k+1], fp[k+1]);
1932 cvtGlyphWidth(nOps & 1);
1936 error(-1,
"Wrong number of args (%d) to Type 2 hstemhm", nOps);
1943 cvtGlyphWidth(nOps & 1);
1947 error(-1,
"Wrong number of args (%d) to Type 2 vstemhm", nOps);
1955 error(-1,
"Unimplemented Type 2 charstring op: %d", s[i]);
1958 error(-1,
"Illegal Type 2 charstring op: %d", s[i]);
1963 }
else if (s[i] <= 246) {
1966 op[nOps++] = (int)s[i] - 139;
1969 }
else if (s[i] <= 250) {
1972 op[nOps++] = (((int)s[i] - 247) << 8) + (
int)s[i+1] + 108;
1975 }
else if (s[i] <= 254) {
1978 op[nOps++] = -(((int)s[i] - 251) << 8) - (
int)s[i+1] - 108;
1982 x = (s[i+1] << 24) | (s[i+2] << 16) | (s[i+3] << 8) | s[i+4];
1987 op[nOps++] = (double)x / 65536.0;
1995 for (i = 0; i < charBuf->getLength(); ++i) {
1996 byte = charBuf->getChar(i) ^ (r2 >> 8);
1997 charBuf->setChar(i,
byte);
1998 r2 = (
byte + r2) * 52845 + 22719;
2002void Type1CFontFile::cvtGlyphWidth(GBool useOp) {
2008 w = nominalWidthX + op[0];
2009 wFP = nominalWidthXFP | fp[0];
2010 for (i = 1; i < nOps; ++i) {
2017 wFP = defaultWidthXFP;
2019 eexecDumpNum(0, gFalse);
2020 eexecDumpNum(w, wFP);
2024void Type1CFontFile::eexecDumpNum(
double x, GBool fpA) {
2030 if (x >= -32768 && x < 32768) {
2031 y = (int)(x * 256.0);
2033 buf[1] = (Guchar)(y >> 24);
2034 buf[2] = (Guchar)(y >> 16);
2035 buf[3] = (Guchar)(y >> 8);
2046 error(-1,
"Type 2 fixed point constant out of range");
2050 if (y >= -107 && y <= 107) {
2051 buf[0] = (Guchar)(y + 139);
2053 }
else if (y > 107 && y <= 1131) {
2055 buf[0] = (Guchar)((y >> 8) + 247);
2056 buf[1] = (Guchar)(y & 0xff);
2058 }
else if (y < -107 && y >= -1131) {
2060 buf[0] = (Guchar)((y >> 8) + 251);
2061 buf[1] = (Guchar)(y & 0xff);
2065 buf[1] = (Guchar)(y >> 24);
2066 buf[2] = (Guchar)(y >> 16);
2067 buf[3] = (Guchar)(y >> 8);
2072 charBuf->append((
char *)buf, n);
2075void Type1CFontFile::eexecDumpOp1(
int opA) {
2076 charBuf->append((
char)opA);
2079void Type1CFontFile::eexecDumpOp2(
int opA) {
2080 charBuf->append((
char)12);
2081 charBuf->append((
char)opA);
2084void Type1CFontFile::eexecWriteCharstring(
const Guchar *s,
int n) {
2089 for (i = 0; i < n; ++i) {
2090 x = s[i] ^ (r1 >> 8);
2091 r1 = (x + r1) * 52845 + 22719;
2092 (*outputFunc)(outputStream, &hexChars[x >> 4], 1);
2093 (*outputFunc)(outputStream, &hexChars[x & 0x0f], 1);
2096 (*outputFunc)(outputStream,
"\n", 1);
2102void Type1CFontFile::getDeltaInt(
char *buf,
const char *key,
const double *opA,
2106 sprintf(buf,
"/%s [", key);
2109 for (i = 0; i < n; ++i) {
2111 sprintf(buf,
"%s%d", i > 0 ?
" " :
"", x);
2114 sprintf(buf,
"] def\n");
2117void Type1CFontFile::getDeltaReal(
char *buf,
const char *key,
const double *opA,
2122 sprintf(buf,
"/%s [", key);
2125 for (i = 0; i < n; ++i) {
2127 sprintf(buf,
"%s%g", i > 0 ?
" " :
"", x);
2130 sprintf(buf,
"] def\n");
2133int Type1CFontFile::getIndexLen(Guchar *indexPtr) {
2134 return (
int)getWord(indexPtr, 2);
2137Guchar *Type1CFontFile::getIndexValPtr(Guchar *indexPtr,
int i) {
2139 Guchar *idxStartPtr;
2141 n = (int)getWord(indexPtr, 2);
2142 offSize = indexPtr[2];
2143 idxStartPtr = indexPtr + 3 + (n + 1) * offSize - 1;
2144 return idxStartPtr + getWord(indexPtr + 3 + i * offSize, offSize);
2147Guchar *Type1CFontFile::getIndexEnd(Guchar *indexPtr) {
2149 Guchar *idxStartPtr;
2151 n = (int)getWord(indexPtr, 2);
2152 offSize = indexPtr[2];
2153 idxStartPtr = indexPtr + 3 + (n + 1) * offSize - 1;
2154 return idxStartPtr + getWord(indexPtr + 3 + n * offSize, offSize);
2157Guint Type1CFontFile::getWord(Guchar *ptr,
int size) {
2162 for (i = 0; i < size; ++i) {
2163 x = (x << 8) + *ptr++;
2168double Type1CFontFile::getNum(Guchar **ptr, GBool *isFP) {
2169 static char nybChars[16] =
"0123456789.ee -";
2170 int b0, b, nyb0, nyb1;
2180 }
else if (b0 == 28) {
2181 x = ((*ptr)[1] << 8) + (*ptr)[2];
2183 }
else if (b0 == 29) {
2184 x = ((*ptr)[1] << 24) + ((*ptr)[2] << 16) + ((*ptr)[3] << 8) + (*ptr)[4];
2186 }
else if (b0 == 30) {
2196 buf[i++] = nybChars[nyb0];
2209 buf[i++] = nybChars[nyb1];
2220 }
else if (b0 == 31) {
2222 }
else if (b0 < 247) {
2225 }
else if (b0 < 251) {
2226 x = ((b0 - 247) << 8) + (*ptr)[1] + 108;
2229 x = -((b0 - 251) << 8) - (*ptr)[1] - 108;
2235char *Type1CFontFile::getString(
int sid,
char *buf) {
2236 Guchar *idxPtr0, *idxPtr1;
2240 strcpy(buf, type1CStdStrings[sid]);
2243 idxPtr0 = getIndexValPtr(stringIdxPtr, sid);
2244 idxPtr1 = getIndexValPtr(stringIdxPtr, sid + 1);
2245 if ((n = idxPtr1 - idxPtr0) > 255) {
2248 strncpy(buf, (
char *)idxPtr0, n);
2314struct TTFontTableHdr {
2328#define nT42Tables 11
2329static T42Table t42Tables[nT42Tables] = {
2342#define t42HeadTable 3
2343#define t42LocaTable 6
2344#define t42GlyfTable 2
2348static const char *macGlyphNames[258] = {
2609enum T42FontIndexMode {
2611 t42FontModeCharCode,
2612 t42FontModeCharCodeOffset,
2616TrueTypeFontFile::TrueTypeFontFile(
const char *fileA,
int lenA) {
2617 int pos, i, idx, n, length;
2618 Guint size, startPos, endPos;
2626 nTables = getUShort(4);
2627 tableHdrs = (TTFontTableHdr *)gmalloc(nTables *
sizeof(TTFontTableHdr));
2629 for (i = 0; i < nTables; ++i) {
2630 tableHdrs[i].tag[0] = getByte(pos+0);
2631 tableHdrs[i].tag[1] = getByte(pos+1);
2632 tableHdrs[i].tag[2] = getByte(pos+2);
2633 tableHdrs[i].tag[3] = getByte(pos+3);
2634 tableHdrs[i].checksum = getULong(pos+4);
2635 tableHdrs[i].offset = getULong(pos+8);
2636 tableHdrs[i].length = getULong(pos+12);
2642 if (seekTable(
"head") < 0 ||
2643 seekTable(
"hhea") < 0 ||
2644 seekTable(
"loca") < 0 ||
2645 seekTable(
"maxp") < 0 ||
2646 seekTable(
"glyf") < 0 ||
2647 seekTable(
"hmtx") < 0) {
2648 error(-1,
"TrueType font file is missing a required table");
2654 idx = seekTableIdx(
"cmap");
2656 pos = tableHdrs[idx].offset;
2657 n = getUShort(pos + 2);
2658 size = (Guint)(4 + 8 * n);
2659 for (i = 0; i < n; ++i) {
2660 startPos = getULong(pos + 4 + 8*i + 4);
2661 length = getUShort(pos + startPos + 2);
2662 endPos = startPos + length;
2663 if (endPos > size) {
2667 if ((mungedCmapSize = size > tableHdrs[idx].length)) {
2669 error(-1,
"Bad cmap table size in TrueType font");
2671 tableHdrs[idx].length = size;
2674 mungedCmapSize = gFalse;
2678 pos = seekTable(
"head");
2679 bbox[0] = getShort(pos + 36);
2680 bbox[1] = getShort(pos + 38);
2681 bbox[2] = getShort(pos + 40);
2682 bbox[3] = getShort(pos + 42);
2683 locaFmt = getShort(pos + 50);
2686 pos = seekTable(
"maxp");
2687 nGlyphs = getUShort(pos + 4);
2690TrueTypeFontFile::~TrueTypeFontFile() {
2694 for (i = 0; i < 256; ++i) {
2702const char *TrueTypeFontFile::getName() {
2706char **TrueTypeFontFile::getEncoding() {
2708 int nCmaps, cmapPlatform, cmapEncoding, cmapFmt;
2709 int cmapLen, cmapOffset, cmapFirst;
2710 int segCnt, segStart, segEnd, segDelta, segOffset;
2714 int stringIdx, stringPos, n;
2723 for (i = 0; i < 256; ++i) {
2728 if ((pos = seekTable(
"cmap")) >= 0) {
2729 nCmaps = getUShort(pos+2);
2733 for (i = 0; i < nCmaps; ++i) {
2734 cmapPlatform = getUShort(pos + 4 + 8*i);
2735 cmapEncoding = getUShort(pos + 4 + 8*i + 2);
2736 if (cmapPlatform == 3 && cmapEncoding == 0) {
2742 cmapPlatform = getUShort(pos + 4);
2743 cmapEncoding = getUShort(pos + 4 + 2);
2745 pos += getULong(pos + 4 + 8*i + 4);
2748 cmapFmt = getUShort(pos);
2751 cmapLen = getUShort(pos + 2);
2752 for (i = 0; i < cmapLen && i < 256; ++i) {
2753 cmap[i] = getByte(pos + 6 + i);
2757 if (cmapPlatform == 3 && cmapEncoding == 0) {
2759 cmapOffset = 0xf000;
2763 segCnt = getUShort(pos + 6) / 2;
2764 for (i = 0; i < segCnt; ++i) {
2765 segEnd = getUShort(pos + 14 + 2*i);
2766 segStart = getUShort(pos + 16 + 2*segCnt + 2*i);
2767 segDelta = getUShort(pos + 16 + 4*segCnt + 2*i);
2768 segOffset = getUShort(pos + 16 + 6*segCnt + 2*i);
2769 if (segStart - cmapOffset <= 0xff &&
2770 segEnd - cmapOffset >= 0) {
2771 for (j = (segStart - cmapOffset >= 0) ? segStart : cmapOffset;
2772 j <= segEnd && j - cmapOffset <= 0xff;
2774 if (segOffset == 0) {
2775 k = (j + segDelta) & 0xffff;
2777 k = getUShort(pos + 16 + 6*segCnt + 2*i +
2778 segOffset + 2 * (j - segStart));
2780 k = (k + segDelta) & 0xffff;
2783 cmap[j - cmapOffset] = k;
2789 cmapFirst = getUShort(pos + 6);
2790 cmapLen = getUShort(pos + 8);
2791 for (i = cmapFirst; i < 256 && i < cmapFirst + cmapLen; ++i) {
2792 cmap[i] = getUShort(pos + 10 + 2*i);
2796 error(-1,
"Unimplemented cmap format (%d) in TrueType font file",
2805 encoding = (
char **)gmalloc(256 *
sizeof(
char *));
2806 for (i = 0; i < 256; ++i) {
2810 if ((pos = seekTable(
"post")) >= 0) {
2811 fmt = getULong(pos);
2814 if (fmt == 0x00010000) {
2815 for (i = 0; i < 256; ++i) {
2816 j = (cmap[i] < 258) ? cmap[i] : 0;
2817 encoding[i] = copyString(macGlyphNames[j]);
2821 }
else if (fmt == 0x00020000) {
2823 stringPos = pos + 34 + 2*nGlyphs;
2824 for (i = 0; i < 256; ++i) {
2825 if (cmap[i] < nGlyphs) {
2826 j = getUShort(pos + 34 + 2 * cmap[i]);
2828 encoding[i] = copyString(macGlyphNames[j]);
2831 if (j != stringIdx) {
2832 for (stringIdx = 0, stringPos = pos + 34 + 2*nGlyphs;
2834 ++stringIdx, stringPos += 1 + getByte(stringPos)) ;
2836 n = getByte(stringPos);
2837 s =
new GString(file + stringPos + 1, n);
2838 encoding[i] = copyString(s->getCString());
2844 encoding[i] = copyString(macGlyphNames[0]);
2849 }
else if (fmt == 0x000280000) {
2850 for (i = 0; i < 256; ++i) {
2851 if (cmap[i] < nGlyphs) {
2852 j = i + getChar(pos + 32 + cmap[i]);
2856 encoding[i] = copyString(macGlyphNames[j]);
2861 for (i = 0; i < 256; ++i) {
2862 j = (cmap[i] < 258) ? cmap[i] : 0;
2863 encoding[i] = copyString(macGlyphNames[j]);
2869 for (i = 0; i < 256; ++i) {
2870 j = (cmap[i] < 258) ? cmap[i] : 0;
2871 encoding[i] = copyString(macGlyphNames[j]);
2878void TrueTypeFontFile::convertToType42(
const char *name,
const char **encodingA,
2879 CharCodeToUnicode *toUnicode,
2880 GBool pdfFontHasEncoding,
2881 FontFileOutputFunc outputFunc,
2882 void *outputStream) {
2886 sprintf(buf,
"%%!PS-TrueTypeFont-%g\n", getFixed(0));
2887 (*outputFunc)(outputStream, buf, strlen(buf));
2890 (*outputFunc)(outputStream,
"10 dict begin\n", 14);
2891 (*outputFunc)(outputStream,
"/FontName /", 11);
2892 (*outputFunc)(outputStream, name, strlen(name));
2893 (*outputFunc)(outputStream,
" def\n", 5);
2894 (*outputFunc)(outputStream,
"/FontType 42 def\n", 17);
2895 (*outputFunc)(outputStream,
"/FontMatrix [1 0 0 1 0 0] def\n", 30);
2896 sprintf(buf,
"/FontBBox [%d %d %d %d] def\n",
2897 bbox[0], bbox[1], bbox[2], bbox[3]);
2898 (*outputFunc)(outputStream, buf, strlen(buf));
2899 (*outputFunc)(outputStream,
"/PaintType 0 def\n", 17);
2902 cvtEncoding(encodingA, pdfFontHasEncoding, outputFunc, outputStream);
2903 cvtCharStrings(encodingA, toUnicode, pdfFontHasEncoding,
2904 outputFunc, outputStream);
2905 cvtSfnts(outputFunc, outputStream, NULL);
2908 (*outputFunc)(outputStream,
"FontName currentdict end definefont pop\n", 40);
2911void TrueTypeFontFile::convertToCIDType2(
const char *name,
const Gushort *cidMap,
2913 FontFileOutputFunc outputFunc,
2914 void *outputStream) {
2920 sprintf(buf,
"%%!PS-TrueTypeFont-%g\n", getFixed(0));
2921 (*outputFunc)(outputStream, buf, strlen(buf));
2924 (*outputFunc)(outputStream,
"20 dict begin\n", 14);
2925 (*outputFunc)(outputStream,
"/CIDFontName /", 14);
2926 (*outputFunc)(outputStream, name, strlen(name));
2927 (*outputFunc)(outputStream,
" def\n", 5);
2928 (*outputFunc)(outputStream,
"/CIDFontType 2 def\n", 19);
2929 (*outputFunc)(outputStream,
"/FontType 42 def\n", 17);
2930 (*outputFunc)(outputStream,
"/CIDSystemInfo 3 dict dup begin\n", 32);
2931 (*outputFunc)(outputStream,
" /Registry (Adobe) def\n", 24);
2932 (*outputFunc)(outputStream,
" /Ordering (Identity) def\n", 27);
2933 (*outputFunc)(outputStream,
" /Supplement 0 def\n", 20);
2934 (*outputFunc)(outputStream,
" end def\n", 10);
2935 (*outputFunc)(outputStream,
"/GDBytes 2 def\n", 15);
2937 sprintf(buf,
"/CIDCount %d def\n", nCIDs);
2938 (*outputFunc)(outputStream, buf, strlen(buf));
2939 if (nCIDs > 32767) {
2940 (*outputFunc)(outputStream,
"/CIDMap [", 9);
2941 for (i = 0; i < nCIDs; i += 32768 - 16) {
2942 (*outputFunc)(outputStream,
"<\n", 2);
2943 for (j = 0; j < 32768 - 16 && i+j < nCIDs; j += 16) {
2944 (*outputFunc)(outputStream,
" ", 2);
2945 for (k = 0; k < 16 && i+j+k < nCIDs; ++k) {
2946 cid = cidMap[i+j+k];
2947 sprintf(buf,
"%02x%02x", (cid >> 8) & 0xff, cid & 0xff);
2948 (*outputFunc)(outputStream, buf, strlen(buf));
2950 (*outputFunc)(outputStream,
"\n", 1);
2952 (*outputFunc)(outputStream,
" >", 3);
2954 (*outputFunc)(outputStream,
"\n", 1);
2955 (*outputFunc)(outputStream,
"] def\n", 6);
2957 (*outputFunc)(outputStream,
"/CIDMap <\n", 10);
2958 for (i = 0; i < nCIDs; i += 16) {
2959 (*outputFunc)(outputStream,
" ", 2);
2960 for (j = 0; j < 16 && i+j < nCIDs; ++j) {
2962 sprintf(buf,
"%02x%02x", (cid >> 8) & 0xff, cid & 0xff);
2963 (*outputFunc)(outputStream, buf, strlen(buf));
2965 (*outputFunc)(outputStream,
"\n", 1);
2967 (*outputFunc)(outputStream,
"> def\n", 6);
2971 sprintf(buf,
"/CIDCount %d def\n", nGlyphs);
2972 (*outputFunc)(outputStream, buf, strlen(buf));
2973 if (nGlyphs > 32767) {
2974 (*outputFunc)(outputStream,
"/CIDMap [\n", 10);
2975 for (i = 0; i < nGlyphs; i += 32767) {
2976 j = nGlyphs - i < 32767 ? nGlyphs - i : 32767;
2977 sprintf(buf,
" %d string 0 1 %d {\n", 2 * j, j - 1);
2978 (*outputFunc)(outputStream, buf, strlen(buf));
2979 sprintf(buf,
" 2 copy dup 2 mul exch %d add -8 bitshift put\n", i);
2980 (*outputFunc)(outputStream, buf, strlen(buf));
2981 sprintf(buf,
" 1 index exch dup 2 mul 1 add exch %d add"
2982 " 255 and put\n", i);
2983 (*outputFunc)(outputStream, buf, strlen(buf));
2984 (*outputFunc)(outputStream,
" } for\n", 8);
2986 (*outputFunc)(outputStream,
"] def\n", 6);
2988 sprintf(buf,
"/CIDMap %d string\n", 2 * nGlyphs);
2989 (*outputFunc)(outputStream, buf, strlen(buf));
2990 sprintf(buf,
" 0 1 %d {\n", nGlyphs - 1);
2991 (*outputFunc)(outputStream, buf, strlen(buf));
2992 (*outputFunc)(outputStream,
2993 " 2 copy dup 2 mul exch -8 bitshift put\n", 42);
2994 (*outputFunc)(outputStream,
2995 " 1 index exch dup 2 mul 1 add exch 255 and put\n", 50);
2996 (*outputFunc)(outputStream,
" } for\n", 8);
2997 (*outputFunc)(outputStream,
"def\n", 4);
3000 (*outputFunc)(outputStream,
"/FontMatrix [1 0 0 1 0 0] def\n", 30);
3001 sprintf(buf,
"/FontBBox [%d %d %d %d] def\n",
3002 bbox[0], bbox[1], bbox[2], bbox[3]);
3003 (*outputFunc)(outputStream, buf, strlen(buf));
3004 (*outputFunc)(outputStream,
"/PaintType 0 def\n", 17);
3005 (*outputFunc)(outputStream,
"/Encoding [] readonly def\n", 26);
3006 (*outputFunc)(outputStream,
"/CharStrings 1 dict dup begin\n", 30);
3007 (*outputFunc)(outputStream,
" /.notdef 0 def\n", 17);
3008 (*outputFunc)(outputStream,
" end readonly def\n", 19);
3011 cvtSfnts(outputFunc, outputStream, NULL);
3014 (*outputFunc)(outputStream,
3015 "CIDFontName currentdict end /CIDFont defineresource pop\n",
3019void TrueTypeFontFile::convertToType0(
const char *name,
const Gushort *cidMap,
3021 FontFileOutputFunc outputFunc,
3022 void *outputStream) {
3028 sfntsName = (
new GString(name))->append(
"_sfnts");
3029 cvtSfnts(outputFunc, outputStream, sfntsName);
3033 n = cidMap ? nCIDs : nGlyphs;
3034 for (i = 0; i < n; i += 256) {
3035 (*outputFunc)(outputStream,
"10 dict begin\n", 14);
3036 (*outputFunc)(outputStream,
"/FontName /", 11);
3037 (*outputFunc)(outputStream, name, strlen(name));
3038 sprintf(buf,
"_%02x def\n", i >> 8);
3039 (*outputFunc)(outputStream, buf, strlen(buf));
3040 (*outputFunc)(outputStream,
"/FontType 42 def\n", 17);
3041 (*outputFunc)(outputStream,
"/FontMatrix [1 0 0 1 0 0] def\n", 30);
3042 sprintf(buf,
"/FontBBox [%d %d %d %d] def\n",
3043 bbox[0], bbox[1], bbox[2], bbox[3]);
3044 (*outputFunc)(outputStream, buf, strlen(buf));
3045 (*outputFunc)(outputStream,
"/PaintType 0 def\n", 17);
3046 (*outputFunc)(outputStream,
"/sfnts ", 7);
3047 (*outputFunc)(outputStream, name, strlen(name));
3048 (*outputFunc)(outputStream,
"_sfnts def\n", 11);
3049 (*outputFunc)(outputStream,
"/Encoding 256 array\n", 20);
3050 for (j = 0; j < 256 && i+j < n; ++j) {
3051 sprintf(buf,
"dup %d /c%02x put\n", j, j);
3052 (*outputFunc)(outputStream, buf, strlen(buf));
3054 (*outputFunc)(outputStream,
"readonly def\n", 13);
3055 (*outputFunc)(outputStream,
"/CharStrings 257 dict dup begin\n", 32);
3056 (*outputFunc)(outputStream,
"/.notdef 0 def\n", 15);
3057 for (j = 0; j < 256 && i+j < n; ++j) {
3058 sprintf(buf,
"/c%02x %d def\n", j, cidMap ? cidMap[i+j] : i+j);
3059 (*outputFunc)(outputStream, buf, strlen(buf));
3061 (*outputFunc)(outputStream,
"end readonly def\n", 17);
3062 (*outputFunc)(outputStream,
3063 "FontName currentdict end definefont pop\n", 40);
3067 (*outputFunc)(outputStream,
"16 dict begin\n", 14);
3068 (*outputFunc)(outputStream,
"/FontName /", 11);
3069 (*outputFunc)(outputStream, name, strlen(name));
3070 (*outputFunc)(outputStream,
" def\n", 5);
3071 (*outputFunc)(outputStream,
"/FontType 0 def\n", 16);
3072 (*outputFunc)(outputStream,
"/FontMatrix [1 0 0 1 0 0] def\n", 30);
3073 (*outputFunc)(outputStream,
"/FMapType 2 def\n", 16);
3074 (*outputFunc)(outputStream,
"/Encoding [\n", 12);
3075 for (i = 0; i < n; i += 256) {
3076 sprintf(buf,
"%d\n", i >> 8);
3077 (*outputFunc)(outputStream, buf, strlen(buf));
3079 (*outputFunc)(outputStream,
"] def\n", 6);
3080 (*outputFunc)(outputStream,
"/FDepVector [\n", 14);
3081 for (i = 0; i < n; i += 256) {
3082 (*outputFunc)(outputStream,
"/", 1);
3083 (*outputFunc)(outputStream, name, strlen(name));
3084 sprintf(buf,
"_%02x findfont\n", i >> 8);
3085 (*outputFunc)(outputStream, buf, strlen(buf));
3087 (*outputFunc)(outputStream,
"] def\n", 6);
3088 (*outputFunc)(outputStream,
"FontName currentdict end definefont pop\n", 40);
3091int TrueTypeFontFile::getByte(
int pos) {
3092 if (pos < 0 || pos >= len) {
3095 return file[pos] & 0xff;
3098int TrueTypeFontFile::getChar(
int pos) {
3101 if (pos < 0 || pos >= len) {
3104 x = file[pos] & 0xff;
3110int TrueTypeFontFile::getUShort(
int pos) {
3113 if (pos < 0 || pos+1 >= len) {
3116 x = file[pos] & 0xff;
3117 x = (x << 8) + (file[pos+1] & 0xff);
3121int TrueTypeFontFile::getShort(
int pos) {
3124 if (pos < 0 || pos+1 >= len) {
3127 x = file[pos] & 0xff;
3128 x = (x << 8) + (file[pos+1] & 0xff);
3134Guint TrueTypeFontFile::getULong(
int pos) {
3137 if (pos < 0 || pos+3 >= len) {
3140 x = file[pos] & 0xff;
3141 x = (x << 8) + (file[pos+1] & 0xff);
3142 x = (x << 8) + (file[pos+2] & 0xff);
3143 x = (x << 8) + (file[pos+3] & 0xff);
3147double TrueTypeFontFile::getFixed(
int pos) {
3151 y = getUShort(pos+2);
3152 return (
double)x + (double)y / 65536;
3155int TrueTypeFontFile::seekTable(
const char *tag) {
3158 for (i = 0; i < nTables; ++i) {
3159 if (!strncmp(tableHdrs[i].tag, tag, 4)) {
3160 return tableHdrs[i].offset;
3166int TrueTypeFontFile::seekTableIdx(
const char *tag) {
3169 for (i = 0; i < nTables; ++i) {
3170 if (!strncmp(tableHdrs[i].tag, tag, 4)) {
3177void TrueTypeFontFile::cvtEncoding(
const char **encodingA, GBool pdfFontHasEncoding,
3178 FontFileOutputFunc outputFunc,
3179 void *outputStream) {
3184 (*outputFunc)(outputStream,
"/Encoding 256 array\n", 20);
3185 if (pdfFontHasEncoding) {
3186 for (i = 0; i < 256; ++i) {
3187 if (!(name = encodingA[i])) {
3190 sprintf(buf,
"dup %d /", i);
3191 (*outputFunc)(outputStream, buf, strlen(buf));
3192 (*outputFunc)(outputStream, name, strlen(name));
3193 (*outputFunc)(outputStream,
" put\n", 5);
3196 for (i = 0; i < 256; ++i) {
3197 sprintf(buf,
"dup %d /c%02x put\n", i, i);
3198 (*outputFunc)(outputStream, buf, strlen(buf));
3201 (*outputFunc)(outputStream,
"readonly def\n", 13);
3204void TrueTypeFontFile::cvtCharStrings(
const char **encodingA,
3205 CharCodeToUnicode *toUnicode,
3206 GBool pdfFontHasEncoding,
3207 FontFileOutputFunc outputFunc,
3208 void *outputStream) {
3209 int unicodeCmap, macRomanCmap, msSymbolCmap;
3210 int nCmaps, cmapPlatform, cmapEncoding, cmapFmt, cmapOffset;
3211 T42FontIndexMode mode;
3213 char buf[64], buf2[16];
3218 (*outputFunc)(outputStream,
"/CharStrings 256 dict dup begin\n", 32);
3219 (*outputFunc)(outputStream,
"/.notdef 0 def\n", 15);
3222 if ((pos = seekTable(
"cmap")) < 0) {
3241 nCmaps = getUShort(pos+2);
3242 unicodeCmap = macRomanCmap = msSymbolCmap = -1;
3244 for (i = 0; i < nCmaps; ++i) {
3245 cmapPlatform = getUShort(pos + 4 + 8*i);
3246 cmapEncoding = getUShort(pos + 4 + 8*i + 2);
3247 if (cmapPlatform == 3 && cmapEncoding == 1) {
3249 }
else if (cmapPlatform == 1 && cmapEncoding == 0) {
3251 }
else if (cmapPlatform == 3 && cmapEncoding == 0) {
3256 mode = t42FontModeCharCode;
3257 if (pdfFontHasEncoding) {
3258 if (unicodeCmap >= 0) {
3260 mode = t42FontModeUnicode;
3261 }
else if (macRomanCmap >= 0) {
3263 mode = t42FontModeMacRoman;
3266 if (macRomanCmap >= 0) {
3268 mode = t42FontModeCharCode;
3269 }
else if (msSymbolCmap >= 0) {
3271 mode = t42FontModeCharCodeOffset;
3272 cmapOffset = 0xf000;
3275 cmapPlatform = getUShort(pos + 4 + 8*i);
3276 cmapEncoding = getUShort(pos + 4 + 8*i + 2);
3277 pos += getULong(pos + 4 + 8*i + 4);
3278 cmapFmt = getUShort(pos);
3279 if (cmapFmt != 0 && cmapFmt != 4 && cmapFmt != 6) {
3280 error(-1,
"Unimplemented cmap format (%d) in TrueType font file",
3289 for (i = 0; i < 256; ++i) {
3290 if (pdfFontHasEncoding) {
3291 name = encodingA[i];
3293 sprintf(buf2,
"c%02x", i);
3296 if (name && strcmp(name,
".notdef")) {
3298 case t42FontModeUnicode:
3299 toUnicode->mapToUnicode((CharCode)i, &u, 1);
3302 case t42FontModeCharCode:
3305 case t42FontModeCharCodeOffset:
3308 case t42FontModeMacRoman:
3309 j = globalParams->getMacRomanCharCode(name);
3316 if ((k = getCmapEntry(cmapFmt, pos, j)) > 0 &&
3318 (*outputFunc)(outputStream,
"/", 1);
3319 (*outputFunc)(outputStream, name, strlen(name));
3320 sprintf(buf,
" %d def\n", k);
3321 (*outputFunc)(outputStream, buf, strlen(buf));
3327 (*outputFunc)(outputStream,
"end readonly def\n", 17);
3330int TrueTypeFontFile::getCmapEntry(
int cmapFmt,
int pos,
int code) {
3331 int cmapLen, cmapFirst;
3332 int segCnt, segEnd, segStart, segDelta, segOffset;
3337 cmapLen = getUShort(pos + 2);
3338 if (code >= cmapLen) {
3341 return getByte(pos + 6 + code);
3344 segCnt = getUShort(pos + 6) / 2;
3347 segEnd = getUShort(pos + 14 + 2*b);
3348 if (code > segEnd) {
3356 segEnd = getUShort(pos + 14 + 2*m);
3357 if (segEnd < code) {
3363 segStart = getUShort(pos + 16 + 2*segCnt + 2*b);
3364 segDelta = getUShort(pos + 16 + 4*segCnt + 2*b);
3365 segOffset = getUShort(pos + 16 + 6*segCnt + 2*b);
3366 if (segOffset == 0) {
3367 i = (code + segDelta) & 0xffff;
3369 i = getUShort(pos + 16 + 6*segCnt + 2*b +
3370 segOffset + 2 * (code - segStart));
3372 i = (i + segDelta) & 0xffff;
3378 cmapFirst = getUShort(pos + 6);
3379 cmapLen = getUShort(pos + 8);
3380 if (code < cmapFirst || code >= cmapFirst + cmapLen) {
3383 return getUShort(pos + 10 + 2*(code - cmapFirst));
3392void TrueTypeFontFile::cvtSfnts(FontFileOutputFunc outputFunc,
3393 void *outputStream, GString *name) {
3394 TTFontTableHdr newTableHdrs[nT42Tables];
3395 char tableDir[12 + nT42Tables*16];
3401 int pos, glyfPos, length, glyphLength, pad;
3405 memcpy(headTable, file + seekTable(
"head"), 54);
3406 headTable[8] = headTable[9] = headTable[10] = headTable[11] = (char)0;
3410 origLocaTable = (
int *)gmalloc((nGlyphs + 1) *
sizeof(
int));
3411 pos = seekTable(
"loca");
3412 for (i = 0; i <= nGlyphs; ++i) {
3414 origLocaTable[i] = getULong(pos + 4*i);
3416 origLocaTable[i] = 2 * getUShort(pos + 2*i);
3419 locaTable = (
char *)gmalloc((nGlyphs + 1) * (locaFmt ? 4 : 2));
3421 locaTable[0] = locaTable[1] = locaTable[2] = locaTable[3] = 0;
3423 locaTable[0] = locaTable[1] = 0;
3426 for (i = 1; i <= nGlyphs; ++i) {
3427 length = origLocaTable[i] - origLocaTable[i-1];
3429 length += 4 - (length & 3);
3433 locaTable[4*i ] = (char)(pos >> 24);
3434 locaTable[4*i+1] = (char)(pos >> 16);
3435 locaTable[4*i+2] = (char)(pos >> 8);
3436 locaTable[4*i+3] = (char) pos;
3438 locaTable[2*i ] = (char)(pos >> 9);
3439 locaTable[2*i+1] = (char)(pos >> 1);
3445 for (i = 0; i < nT42Tables; ++i) {
3446 if (t42Tables[i].required ||
3447 seekTable(t42Tables[i].tag) >= 0) {
3454 pos = 12 + nNewTables*16;
3456 for (i = 0; i < nT42Tables; ++i) {
3459 if (i == t42HeadTable) {
3461 checksum = computeTableChecksum(headTable, 54);
3462 }
else if (i == t42LocaTable) {
3463 length = (nGlyphs + 1) * (locaFmt ? 4 : 2);
3464 checksum = computeTableChecksum(locaTable, length);
3465 }
else if (i == t42GlyfTable) {
3468 glyfPos = seekTable(
"glyf");
3469 for (j = 0; j < nGlyphs; ++j) {
3470 glyphLength = origLocaTable[j+1] - origLocaTable[j];
3471 pad = (glyphLength & 3) ? 4 - (glyphLength & 3) : 0;
3472 length += glyphLength + pad;
3473 checksum += computeTableChecksum(file + glyfPos + origLocaTable[j],
3477 if ((j = seekTableIdx(t42Tables[i].tag)) >= 0) {
3478 length = tableHdrs[j].length;
3479 checksum = computeTableChecksum(file + tableHdrs[j].offset, length);
3480 }
else if (t42Tables[i].required) {
3481 error(-1,
"Embedded TrueType font is missing a required table ('%s')",
3488 strncpy(newTableHdrs[k].tag, t42Tables[i].tag, 4);
3489 newTableHdrs[k].checksum = checksum;
3490 newTableHdrs[k].offset = pos;
3491 newTableHdrs[k].length = length;
3492 pad = (length & 3) ? 4 - (length & 3) : 0;
3493 pos += length + pad;
3504 tableDir[5] = nNewTables;
3506 tableDir[7] = (char)128;
3510 tableDir[11] = (char)(16 * nNewTables - 128);
3512 for (i = 0; i < nNewTables; ++i) {
3513 tableDir[pos ] = newTableHdrs[i].tag[0];
3514 tableDir[pos+ 1] = newTableHdrs[i].tag[1];
3515 tableDir[pos+ 2] = newTableHdrs[i].tag[2];
3516 tableDir[pos+ 3] = newTableHdrs[i].tag[3];
3517 tableDir[pos+ 4] = (char)(newTableHdrs[i].checksum >> 24);
3518 tableDir[pos+ 5] = (char)(newTableHdrs[i].checksum >> 16);
3519 tableDir[pos+ 6] = (char)(newTableHdrs[i].checksum >> 8);
3520 tableDir[pos+ 7] = (char) newTableHdrs[i].checksum;
3521 tableDir[pos+ 8] = (char)(newTableHdrs[i].offset >> 24);
3522 tableDir[pos+ 9] = (char)(newTableHdrs[i].offset >> 16);
3523 tableDir[pos+10] = (char)(newTableHdrs[i].offset >> 8);
3524 tableDir[pos+11] = (char) newTableHdrs[i].offset;
3525 tableDir[pos+12] = (char)(newTableHdrs[i].length >> 24);
3526 tableDir[pos+13] = (char)(newTableHdrs[i].length >> 16);
3527 tableDir[pos+14] = (char)(newTableHdrs[i].length >> 8);
3528 tableDir[pos+15] = (char) newTableHdrs[i].length;
3533 checksum = computeTableChecksum(tableDir, 12 + nNewTables*16);
3534 for (i = 0; i < nNewTables; ++i) {
3535 checksum += newTableHdrs[i].checksum;
3537 checksum = 0xb1b0afba - checksum;
3538 headTable[ 8] = (char)(checksum >> 24);
3539 headTable[ 9] = (char)(checksum >> 16);
3540 headTable[10] = (char)(checksum >> 8);
3541 headTable[11] = (char) checksum;
3545 (*outputFunc)(outputStream,
"/", 1);
3546 (*outputFunc)(outputStream, name->getCString(), name->getLength());
3547 (*outputFunc)(outputStream,
" [\n", 3);
3549 (*outputFunc)(outputStream,
"/sfnts [\n", 9);
3553 dumpString(tableDir, 12 + nNewTables*16, outputFunc, outputStream);
3556 for (i = 0; i < nNewTables; ++i) {
3557 if (i == t42HeadTable) {
3558 dumpString(headTable, 54, outputFunc, outputStream);
3559 }
else if (i == t42LocaTable) {
3560 length = (nGlyphs + 1) * (locaFmt ? 4 : 2);
3561 dumpString(locaTable, length, outputFunc, outputStream);
3562 }
else if (i == t42GlyfTable) {
3563 glyfPos = seekTable(
"glyf");
3564 for (j = 0; j < nGlyphs; ++j) {
3565 length = origLocaTable[j+1] - origLocaTable[j];
3567 dumpString(file + glyfPos + origLocaTable[j], length,
3568 outputFunc, outputStream);
3575 if ((length = newTableHdrs[i].length) > 0) {
3576 dumpString(file + seekTable(t42Tables[i].tag), length,
3577 outputFunc, outputStream);
3583 (*outputFunc)(outputStream,
"] def\n", 6);
3585 gfree(origLocaTable);
3589void TrueTypeFontFile::dumpString(
const char *s,
int length,
3590 FontFileOutputFunc outputFunc,
3591 void *outputStream) {
3595 (*outputFunc)(outputStream,
"<", 1);
3596 for (i = 0; i < length; i += 32) {
3597 for (j = 0; j < 32 && i+j < length; ++j) {
3598 sprintf(buf,
"%02X", s[i+j] & 0xff);
3599 (*outputFunc)(outputStream, buf, strlen(buf));
3601 if (i % (65536 - 32) == 65536 - 64) {
3602 (*outputFunc)(outputStream,
">\n<", 3);
3603 }
else if (i+32 < length) {
3604 (*outputFunc)(outputStream,
"\n", 1);
3608 pad = 4 - (length & 3);
3609 for (i = 0; i < pad; ++i) {
3610 (*outputFunc)(outputStream,
"00", 2);
3614 (*outputFunc)(outputStream,
"00>\n", 4);
3617Guint TrueTypeFontFile::computeTableChecksum(
const char *data,
int length) {
3618 Guint checksum, word;
3622 for (i = 0; i+3 < length; i += 4) {
3623 word = ((data[i ] & 0xff) << 24) +
3624 ((data[i+1] & 0xff) << 16) +
3625 ((data[i+2] & 0xff) << 8) +
3632 switch (length & 3) {
3634 word |= (data[i+2] & 0xff) << 8;
3636 word |= (data[i+1] & 0xff) << 16;
3638 word |= (data[i ] & 0xff) << 24;
3646void TrueTypeFontFile::writeTTF(FILE *out) {
3647 static char cmapTab[20] = {
3659 static char nameTab[8] = {
3665 static char postTab[32] = {
3676 GBool haveCmap, haveName, havePost;
3677 GBool dirCmap, dirName, dirPost;
3678 int nNewTables, nAllTables, pad;
3684 haveCmap = seekTable(
"cmap") >= 0;
3685 haveName = seekTable(
"name") >= 0;
3686 havePost = seekTable(
"post") >= 0;
3687 nNewTables = (haveCmap ? 0 : 1) + (haveName ? 0 : 1) + (havePost ? 0 : 1);
3688 if (!nNewTables && !mungedCmapSize) {
3690 fwrite(file, 1, len, out);
3695 nAllTables = nTables + nNewTables;
3696 tableDir = (
char *)gmalloc(12 + nAllTables * 16);
3697 memcpy(tableDir, file, 12 + nTables * 16);
3698 tableDir[4] = (char)((nAllTables >> 8) & 0xff);
3699 tableDir[5] = (char)(nAllTables & 0xff);
3700 for (i = -1, t = (Guint)nAllTables; t; ++i, t >>= 1) ;
3702 tableDir[6] = (char)((t >> 8) & 0xff);
3703 tableDir[7] = (char)(t & 0xff);
3704 tableDir[8] = (char)((i >> 8) & 0xff);
3705 tableDir[9] = (char)(i & 0xff);
3706 t = nAllTables * 16 - t;
3707 tableDir[10] = (char)((t >> 8) & 0xff);
3708 tableDir[11] = (char)(t & 0xff);
3713 pad = (len & 3) ? 4 - (len & 3) : 0;
3714 pos = len + pad + 16 * nNewTables;
3715 for (i = 0; i < nTables; ++i) {
3716 if (!dirCmap && strncmp(tableHdrs[i].tag,
"cmap", 4) > 0) {
3717 tableDir[12 + 16*j ] =
'c';
3718 tableDir[12 + 16*j + 1] =
'm';
3719 tableDir[12 + 16*j + 2] =
'a';
3720 tableDir[12 + 16*j + 3] =
'p';
3721 tableDir[12 + 16*j + 4] = (char)0;
3722 tableDir[12 + 16*j + 5] = (char)0;
3723 tableDir[12 + 16*j + 6] = (char)0;
3724 tableDir[12 + 16*j + 7] = (char)0;
3725 tableDir[12 + 16*j + 8] = (char)((pos >> 24) & 0xff);
3726 tableDir[12 + 16*j + 9] = (char)((pos >> 16) & 0xff);
3727 tableDir[12 + 16*j + 10] = (char)((pos >> 8) & 0xff);
3728 tableDir[12 + 16*j + 11] = (char)( pos & 0xff);
3729 tableDir[12 + 16*j + 12] = (char)((
sizeof(cmapTab) >> 24) & 0xff);
3730 tableDir[12 + 16*j + 13] = (char)((
sizeof(cmapTab) >> 16) & 0xff);
3731 tableDir[12 + 16*j + 14] = (char)((
sizeof(cmapTab) >> 8) & 0xff);
3732 tableDir[12 + 16*j + 15] = (char)(
sizeof(cmapTab) & 0xff);
3733 pos +=
sizeof(cmapTab);
3737 if (!dirName && strncmp(tableHdrs[i].tag,
"name", 4) > 0) {
3738 tableDir[12 + 16*j ] =
'n';
3739 tableDir[12 + 16*j + 1] =
'a';
3740 tableDir[12 + 16*j + 2] =
'm';
3741 tableDir[12 + 16*j + 3] =
'e';
3742 tableDir[12 + 16*j + 4] = (char)0;
3743 tableDir[12 + 16*j + 5] = (char)0;
3744 tableDir[12 + 16*j + 6] = (char)0;
3745 tableDir[12 + 16*j + 7] = (char)0;
3746 tableDir[12 + 16*j + 8] = (char)((pos >> 24) & 0xff);
3747 tableDir[12 + 16*j + 9] = (char)((pos >> 16) & 0xff);
3748 tableDir[12 + 16*j + 10] = (char)((pos >> 8) & 0xff);
3749 tableDir[12 + 16*j + 11] = (char)( pos & 0xff);
3750 tableDir[12 + 16*j + 12] = (char)((
sizeof(nameTab) >> 24) & 0xff);
3751 tableDir[12 + 16*j + 13] = (char)((
sizeof(nameTab) >> 16) & 0xff);
3752 tableDir[12 + 16*j + 14] = (char)((
sizeof(nameTab) >> 8) & 0xff);
3753 tableDir[12 + 16*j + 15] = (char)(
sizeof(nameTab) & 0xff);
3754 pos +=
sizeof(nameTab);
3758 if (!dirName && strncmp(tableHdrs[i].tag,
"post", 4) > 0) {
3759 tableDir[12 + 16*j ] =
'p';
3760 tableDir[12 + 16*j + 1] =
'o';
3761 tableDir[12 + 16*j + 2] =
's';
3762 tableDir[12 + 16*j + 3] =
't';
3763 tableDir[12 + 16*j + 4] = (char)0;
3764 tableDir[12 + 16*j + 5] = (char)0;
3765 tableDir[12 + 16*j + 6] = (char)0;
3766 tableDir[12 + 16*j + 7] = (char)0;
3767 tableDir[12 + 16*j + 8] = (char)((pos >> 24) & 0xff);
3768 tableDir[12 + 16*j + 9] = (char)((pos >> 16) & 0xff);
3769 tableDir[12 + 16*j + 10] = (char)((pos >> 8) & 0xff);
3770 tableDir[12 + 16*j + 11] = (char)( pos & 0xff);
3771 tableDir[12 + 16*j + 12] = (char)((
sizeof(postTab) >> 24) & 0xff);
3772 tableDir[12 + 16*j + 13] = (char)((
sizeof(postTab) >> 16) & 0xff);
3773 tableDir[12 + 16*j + 14] = (char)((
sizeof(postTab) >> 8) & 0xff);
3774 tableDir[12 + 16*j + 15] = (char)(
sizeof(postTab) & 0xff);
3775 pos +=
sizeof(postTab);
3779 tableDir[12 + 16*j ] = tableHdrs[i].tag[0];
3780 tableDir[12 + 16*j + 1] = tableHdrs[i].tag[1];
3781 tableDir[12 + 16*j + 2] = tableHdrs[i].tag[2];
3782 tableDir[12 + 16*j + 3] = tableHdrs[i].tag[3];
3783 tableDir[12 + 16*j + 4] = (char)((tableHdrs[i].checksum >> 24) & 0xff);
3784 tableDir[12 + 16*j + 5] = (char)((tableHdrs[i].checksum >> 16) & 0xff);
3785 tableDir[12 + 16*j + 6] = (char)((tableHdrs[i].checksum >> 8) & 0xff);
3786 tableDir[12 + 16*j + 7] = (char)( tableHdrs[i].checksum & 0xff);
3787 t = tableHdrs[i].offset + nNewTables * 16;
3788 tableDir[12 + 16*j + 8] = (char)((t >> 24) & 0xff);
3789 tableDir[12 + 16*j + 9] = (char)((t >> 16) & 0xff);
3790 tableDir[12 + 16*j + 10] = (char)((t >> 8) & 0xff);
3791 tableDir[12 + 16*j + 11] = (char)( t & 0xff);
3792 tableDir[12 + 16*j + 12] = (char)((tableHdrs[i].length >> 24) & 0xff);
3793 tableDir[12 + 16*j + 13] = (char)((tableHdrs[i].length >> 16) & 0xff);
3794 tableDir[12 + 16*j + 14] = (char)((tableHdrs[i].length >> 8) & 0xff);
3795 tableDir[12 + 16*j + 15] = (char)( tableHdrs[i].length & 0xff);
3799 tableDir[12 + 16*j ] =
'c';
3800 tableDir[12 + 16*j + 1] =
'm';
3801 tableDir[12 + 16*j + 2] =
'a';
3802 tableDir[12 + 16*j + 3] =
'p';
3803 tableDir[12 + 16*j + 4] = (char)0;
3804 tableDir[12 + 16*j + 5] = (char)0;
3805 tableDir[12 + 16*j + 6] = (char)0;
3806 tableDir[12 + 16*j + 7] = (char)0;
3807 tableDir[12 + 16*j + 8] = (char)((pos >> 24) & 0xff);
3808 tableDir[12 + 16*j + 9] = (char)((pos >> 16) & 0xff);
3809 tableDir[12 + 16*j + 10] = (char)((pos >> 8) & 0xff);
3810 tableDir[12 + 16*j + 11] = (char)( pos & 0xff);
3811 tableDir[12 + 16*j + 12] = (char)((
sizeof(cmapTab) >> 24) & 0xff);
3812 tableDir[12 + 16*j + 13] = (char)((
sizeof(cmapTab) >> 16) & 0xff);
3813 tableDir[12 + 16*j + 14] = (char)((
sizeof(cmapTab) >> 8) & 0xff);
3814 tableDir[12 + 16*j + 15] = (char)(
sizeof(cmapTab) & 0xff);
3815 pos +=
sizeof(cmapTab);
3820 tableDir[12 + 16*j ] =
'n';
3821 tableDir[12 + 16*j + 1] =
'a';
3822 tableDir[12 + 16*j + 2] =
'm';
3823 tableDir[12 + 16*j + 3] =
'e';
3824 tableDir[12 + 16*j + 4] = (char)0;
3825 tableDir[12 + 16*j + 5] = (char)0;
3826 tableDir[12 + 16*j + 6] = (char)0;
3827 tableDir[12 + 16*j + 7] = (char)0;
3828 tableDir[12 + 16*j + 8] = (char)((pos >> 24) & 0xff);
3829 tableDir[12 + 16*j + 9] = (char)((pos >> 16) & 0xff);
3830 tableDir[12 + 16*j + 10] = (char)((pos >> 8) & 0xff);
3831 tableDir[12 + 16*j + 11] = (char)( pos & 0xff);
3832 tableDir[12 + 16*j + 12] = (char)((
sizeof(nameTab) >> 24) & 0xff);
3833 tableDir[12 + 16*j + 13] = (char)((
sizeof(nameTab) >> 16) & 0xff);
3834 tableDir[12 + 16*j + 14] = (char)((
sizeof(nameTab) >> 8) & 0xff);
3835 tableDir[12 + 16*j + 15] = (char)(
sizeof(nameTab) & 0xff);
3836 pos +=
sizeof(nameTab);
3841 tableDir[12 + 16*j ] =
'p';
3842 tableDir[12 + 16*j + 1] =
'o';
3843 tableDir[12 + 16*j + 2] =
's';
3844 tableDir[12 + 16*j + 3] =
't';
3845 tableDir[12 + 16*j + 4] = (char)0;
3846 tableDir[12 + 16*j + 5] = (char)0;
3847 tableDir[12 + 16*j + 6] = (char)0;
3848 tableDir[12 + 16*j + 7] = (char)0;
3849 tableDir[12 + 16*j + 8] = (char)((pos >> 24) & 0xff);
3850 tableDir[12 + 16*j + 9] = (char)((pos >> 16) & 0xff);
3851 tableDir[12 + 16*j + 10] = (char)((pos >> 8) & 0xff);
3852 tableDir[12 + 16*j + 11] = (char)( pos & 0xff);
3853 tableDir[12 + 16*j + 12] = (char)((
sizeof(postTab) >> 24) & 0xff);
3854 tableDir[12 + 16*j + 13] = (char)((
sizeof(postTab) >> 16) & 0xff);
3855 tableDir[12 + 16*j + 14] = (char)((
sizeof(postTab) >> 8) & 0xff);
3856 tableDir[12 + 16*j + 15] = (char)(
sizeof(postTab) & 0xff);
3857 pos +=
sizeof(postTab);
3863 fwrite(tableDir, 1, 12 + 16 * nAllTables, out);
3866 fwrite(file + 12 + 16*nTables, 1, len - (12 + 16*nTables), out);
3869 for (i = 0; i < pad; ++i) {
3870 fputc((
char)0, out);
3873 fwrite(cmapTab, 1,
sizeof(cmapTab), out);
3876 fwrite(nameTab, 1,
sizeof(nameTab), out);
3879 fwrite(postTab, 1,
sizeof(postTab), out);