1 //========================================================================
5 // Copyright 1999 Derek B. Noonburg
7 //========================================================================
10 #pragma implementation
22 #include "StdFontInfo.h"
23 #include "CompactFontInfo.h"
25 //------------------------------------------------------------------------
27 static Guint getWord(Guchar *ptr, int size);
28 static double getNum(Guchar **ptr, GBool *fp);
29 static char *getString(int sid, Guchar *stringIdxPtr,
30 Guchar *stringStartPtr, int stringOffSize,
33 //------------------------------------------------------------------------
35 static inline char *nextLine(char *line, char *end) {
36 while (line < end && *line != '\n' && *line != '\r')
38 while (line < end && *line == '\n' || *line == '\r')
43 static char hexChars[17] = "0123456789ABCDEF";
45 //------------------------------------------------------------------------
47 //------------------------------------------------------------------------
49 FontFile::FontFile() {
52 FontFile::~FontFile() {
55 //------------------------------------------------------------------------
57 //------------------------------------------------------------------------
59 Type1FontFile::Type1FontFile(char *file, int len) {
60 char *line, *line1, *p;
68 for (i = 1, line = file; i <= 100 && line < file + len && !encoding; ++i) {
71 if (!strncmp(line, "/FontName", 9)) {
72 strncpy(buf, line, 255);
74 if ((p = strchr(buf+9, '/')) &&
75 (p = strtok(p+1, " \t\n\r")))
77 line = nextLine(line, file + len);
80 } else if (!strncmp(line, "/Encoding StandardEncoding def", 30)) {
81 encoding = type1StdEncoding.copy();
82 } else if (!strncmp(line, "/Encoding 256 array", 19)) {
83 encoding = new FontEncoding();
84 for (i = 0; i < 300; ++i) {
85 line1 = nextLine(line, file + len);
86 if ((n = line1 - line) > 255)
88 strncpy(buf, line, n);
90 p = strtok(buf, " \t");
91 if (p && !strcmp(p, "dup")) {
92 if ((p = strtok(NULL, " \t"))) {
93 if ((code = atoi(p)) < 256) {
94 if ((p = strtok(NULL, " \t"))) {
96 encoding->addChar(code, copyString(p+1));
102 if ((p = strtok(NULL, " \t\n\r")) && !strcmp(p, "def")) {
108 //~ check for getinterval/putinterval junk
111 line = nextLine(line, file + len);
116 Type1FontFile::~Type1FontFile() {
119 if (encoding && freeEnc)
123 FontEncoding *Type1FontFile::getEncoding(GBool taken) {
129 //------------------------------------------------------------------------
131 //------------------------------------------------------------------------
133 Type1CFontFile::Type1CFontFile(char *file, int len) {
135 Guchar *topPtr, *idxStartPtr, *idxPtr0, *idxPtr1;
136 Guchar *stringIdxPtr, *stringStartPtr;
137 int topOffSize, idxOffSize, stringOffSize;
138 int nFonts, nStrings, nGlyphs;
139 int nCodes, nRanges, nLeft, nSups;
141 int charset, enc, charstrings;
142 int charsetFormat, encFormat;
155 topPtr = (Guchar *)file + (file[2] & 0xff);
156 topOffSize = file[3] & 0xff;
158 // read name index (first font only)
159 nFonts = getWord(topPtr, 2);
160 idxOffSize = topPtr[2];
162 idxStartPtr = topPtr + (nFonts + 1) * idxOffSize - 1;
163 idxPtr0 = idxStartPtr + getWord(topPtr, idxOffSize);
164 idxPtr1 = idxStartPtr + getWord(topPtr + idxOffSize, idxOffSize);
165 if ((n = idxPtr1 - idxPtr0) > 255)
167 strncpy(buf, (char *)idxPtr0, n);
169 name = copyString(buf);
170 topPtr = idxStartPtr + getWord(topPtr + nFonts * idxOffSize, idxOffSize);
172 // read top dict index (first font only)
173 nFonts = getWord(topPtr, 2);
174 idxOffSize = topPtr[2];
176 idxStartPtr = topPtr + (nFonts + 1) * idxOffSize - 1;
177 idxPtr0 = idxStartPtr + getWord(topPtr, idxOffSize);
178 idxPtr1 = idxStartPtr + getWord(topPtr + idxOffSize, idxOffSize);
183 while (idxPtr0 < idxPtr1) {
184 if (*idxPtr0 <= 27 || *idxPtr0 == 31) {
187 key = (key << 8) | *idxPtr0++;
188 if (key == 0x0f) { // charset
189 charset = (int)op[0];
190 } else if (key == 0x10) { // encoding
192 } else if (key == 0x11) { // charstrings
193 charstrings = (int)op[0];
197 x = getNum(&idxPtr0, &isFP);
202 topPtr = idxStartPtr + getWord(topPtr + nFonts * idxOffSize, idxOffSize);
205 nStrings = getWord(topPtr, 2);
206 stringOffSize = topPtr[2];
208 stringIdxPtr = topPtr;
209 stringStartPtr = topPtr + (nStrings + 1) * stringOffSize - 1;
210 topPtr = stringStartPtr + getWord(topPtr + nStrings * stringOffSize,
213 // get number of glyphs from charstrings index
214 topPtr = (Guchar *)file + charstrings;
215 nGlyphs = getWord(topPtr, 2);
219 glyphNames = type1CISOAdobeCharset;
220 } else if (charset == 1) {
221 glyphNames = type1CExpertCharset;
222 } else if (charset == 2) {
223 glyphNames = type1CExpertSubsetCharset;
225 glyphNames = (Gushort *)gmalloc(nGlyphs * sizeof(Gushort));
227 topPtr = (Guchar *)file + charset;
228 charsetFormat = *topPtr++;
229 if (charsetFormat == 0) {
230 for (i = 1; i < nGlyphs; ++i) {
231 glyphNames[i] = getWord(topPtr, 2);
234 } else if (charsetFormat == 1) {
236 while (i < nGlyphs) {
237 c = getWord(topPtr, 2);
240 for (j = 0; j <= nLeft; ++j)
241 glyphNames[i++] = c++;
243 } else if (charsetFormat == 2) {
245 while (i < nGlyphs) {
246 c = getWord(topPtr, 2);
248 nLeft = getWord(topPtr, 2);
250 for (j = 0; j <= nLeft; ++j)
251 glyphNames[i++] = c++;
256 // read encoding (glyph -> code mapping)
258 encoding = type1StdEncoding.copy();
259 } else if (enc == 1) {
260 encoding = type1ExpertEncoding.copy();
262 encoding = new FontEncoding();
263 topPtr = (Guchar *)file + enc;
264 encFormat = *topPtr++;
265 if ((encFormat & 0x7f) == 0) {
266 nCodes = 1 + *topPtr++;
267 if (nCodes > nGlyphs) {
270 for (i = 1; i < nCodes; ++i) {
272 getString(glyphNames[i], stringIdxPtr, stringStartPtr,
274 encoding->addChar(c, copyString(buf));
276 } else if ((encFormat & 0x7f) == 1) {
279 for (i = 0; i < nRanges; ++i) {
282 for (j = 0; j <= nLeft && nCodes < nGlyphs; ++j) {
283 getString(glyphNames[nCodes], stringIdxPtr, stringStartPtr,
285 encoding->addChar(c, copyString(buf));
291 if (encFormat & 0x80) {
293 for (i = 0; i < nSups; ++i) {
295 sid = getWord(topPtr, 2);
297 getString(sid, stringIdxPtr, stringStartPtr,
299 encoding->addChar(c, copyString(buf));
308 Type1CFontFile::~Type1CFontFile() {
311 if (encoding && freeEnc)
315 FontEncoding *Type1CFontFile::getEncoding(GBool taken) {
321 static Guint getWord(Guchar *ptr, int size) {
326 for (i = 0; i < size; ++i)
327 x = (x << 8) + *ptr++;
331 static double getNum(Guchar **ptr, GBool *fp) {
332 static char nybChars[16] = "0123456789.ee -";
333 int b0, b, nyb0, nyb1;
343 } else if (b0 == 28) {
344 x = ((*ptr)[1] << 8) + (*ptr)[2];
346 } else if (b0 == 29) {
347 x = ((*ptr)[1] << 24) + ((*ptr)[2] << 16) + ((*ptr)[3] << 8) + (*ptr)[4];
349 } else if (b0 == 30) {
358 buf[i++] = nybChars[nyb0];
367 buf[i++] = nybChars[nyb1];
376 } else if (b0 == 31) {
378 } else if (b0 < 247) {
381 } else if (b0 < 251) {
382 x = ((b0 - 247) << 8) + (*ptr)[1] + 108;
385 x = -((b0 - 251) << 8) - (*ptr)[1] - 108;
391 static char *getString(int sid, Guchar *stringIdxPtr,
392 Guchar *stringStartPtr, int stringOffSize,
394 Guchar *idxPtr0, *idxPtr1;
398 strcpy(buf, type1CStdStrings[sid]);
401 idxPtr0 = stringStartPtr + getWord(stringIdxPtr + sid * stringOffSize,
403 idxPtr1 = stringStartPtr + getWord(stringIdxPtr + (sid+1) * stringOffSize,
405 if ((len = idxPtr1 - idxPtr0) > 255)
407 strncpy(buf, (char *)idxPtr0, len);
413 //------------------------------------------------------------------------
414 // Type1CFontConverter
415 //------------------------------------------------------------------------
417 Type1CFontConverter::Type1CFontConverter(char *file, int len, FILE *out) {
425 Type1CFontConverter::~Type1CFontConverter() {
428 void Type1CFontConverter::convert() {
439 double underlinePosition;
440 double underlineThickness;
442 int charstringType; //~ ???
443 double fontMatrix[6];
446 double strokeWidth; //~ ???
453 char buf[256], eBuf[256];
454 Guchar *topPtr, *idxStartPtr, *idxPtr0, *idxPtr1;
455 Guchar *stringIdxPtr, *stringStartPtr;
456 int topOffSize, idxOffSize, stringOffSize;
457 int nFonts, nStrings, nGlyphs;
458 int nCodes, nRanges, nLeft, nSups;
460 int charsetFormat, encFormat;
461 int subrsOffset, nSubrs;
470 topPtr = (Guchar *)file + (file[2] & 0xff);
471 topOffSize = file[3] & 0xff;
473 // read name (first font only)
474 nFonts = getWord(topPtr, 2);
475 idxOffSize = topPtr[2];
477 idxStartPtr = topPtr + (nFonts + 1) * idxOffSize - 1;
478 idxPtr0 = idxStartPtr + getWord(topPtr, idxOffSize);
479 idxPtr1 = idxStartPtr + getWord(topPtr + idxOffSize, idxOffSize);
480 if ((n = idxPtr1 - idxPtr0) > 255)
482 strncpy(buf, (char *)idxPtr0, n);
484 fontName = copyString(buf);
485 topPtr = idxStartPtr + getWord(topPtr + nFonts * idxOffSize, idxOffSize);
487 // read top dict (first font only)
488 nFonts = getWord(topPtr, 2);
489 idxOffSize = topPtr[2];
491 idxStartPtr = topPtr + (nFonts + 1) * idxOffSize - 1;
492 idxPtr0 = idxStartPtr + getWord(topPtr, idxOffSize);
493 idxPtr1 = idxStartPtr + getWord(topPtr + idxOffSize, idxOffSize);
500 dict.isFixedPitch = 0;
501 dict.italicAngle = 0;
502 dict.underlinePosition = -100;
503 dict.underlineThickness = 50;
505 dict.charstringType = 2;
506 dict.fontMatrix[0] = 0.001;
507 dict.fontMatrix[1] = 0;
508 dict.fontMatrix[2] = 0;
509 dict.fontMatrix[3] = 0.001;
510 dict.fontMatrix[4] = 0;
511 dict.fontMatrix[5] = 0;
513 dict.fontBBox[0] = 0;
514 dict.fontBBox[1] = 0;
515 dict.fontBBox[2] = 0;
516 dict.fontBBox[3] = 0;
517 dict.strokeWidth = 0;
520 dict.charStrings = 0;
521 dict.privateSize = 0;
522 dict.privateOffset = 0;
524 while (idxPtr0 < idxPtr1) {
525 if (*idxPtr0 <= 27 || *idxPtr0 == 31) {
528 key = (key << 8) | *idxPtr0++;
530 case 0x0000: dict.version = (int)op[0]; break;
531 case 0x0001: dict.notice = (int)op[0]; break;
532 case 0x0c00: dict.copyright = (int)op[0]; break;
533 case 0x0002: dict.fullName = (int)op[0]; break;
534 case 0x0003: dict.familyName = (int)op[0]; break;
535 case 0x0004: dict.weight = (int)op[0]; break;
536 case 0x0c01: dict.isFixedPitch = (int)op[0]; break;
537 case 0x0c02: dict.italicAngle = op[0]; break;
538 case 0x0c03: dict.underlinePosition = op[0]; break;
539 case 0x0c04: dict.underlineThickness = op[0]; break;
540 case 0x0c05: dict.paintType = (int)op[0]; break;
541 case 0x0c06: dict.charstringType = (int)op[0]; break;
542 case 0x0c07: dict.fontMatrix[0] = op[0];
543 dict.fontMatrix[1] = op[1];
544 dict.fontMatrix[2] = op[2];
545 dict.fontMatrix[3] = op[3];
546 dict.fontMatrix[4] = op[4];
547 dict.fontMatrix[5] = op[5]; break;
548 case 0x000d: dict.uniqueID = (int)op[0]; break;
549 case 0x0005: dict.fontBBox[0] = op[0];
550 dict.fontBBox[1] = op[1];
551 dict.fontBBox[2] = op[2];
552 dict.fontBBox[3] = op[3]; break;
553 case 0x0c08: dict.strokeWidth = op[0]; break;
554 case 0x000f: dict.charset = (int)op[0]; break;
555 case 0x0010: dict.encoding = (int)op[0]; break;
556 case 0x0011: dict.charStrings = (int)op[0]; break;
557 case 0x0012: dict.privateSize = (int)op[0];
558 dict.privateOffset = (int)op[1]; break;
562 x = getNum(&idxPtr0, &isFP);
569 topPtr = idxStartPtr + getWord(topPtr + nFonts * idxOffSize, idxOffSize);
572 nStrings = getWord(topPtr, 2);
573 stringOffSize = topPtr[2];
575 stringIdxPtr = topPtr;
576 stringStartPtr = topPtr + (nStrings + 1) * stringOffSize - 1;
577 topPtr = stringStartPtr + getWord(topPtr + nStrings * stringOffSize,
585 nGSubrs = getWord(topPtr, 2);
586 gSubrOffSize = topPtr[2];
590 // write header and font dictionary, up to encoding
591 fprintf(out, "%%!FontType1-1.0: %s", fontName);
592 if (dict.version != 0) {
594 getString(dict.version, stringIdxPtr, stringStartPtr,
595 stringOffSize, buf));
598 fprintf(out, "11 dict begin\n");
599 fprintf(out, "/FontInfo 10 dict dup begin\n");
600 if (dict.version != 0) {
601 fprintf(out, "/version (%s) readonly def\n",
602 getString(dict.version, stringIdxPtr, stringStartPtr,
603 stringOffSize, buf));
605 if (dict.notice != 0) {
606 fprintf(out, "/Notice (%s) readonly def\n",
607 getString(dict.notice, stringIdxPtr, stringStartPtr,
608 stringOffSize, buf));
610 if (dict.copyright != 0) {
611 fprintf(out, "/Copyright (%s) readonly def\n",
612 getString(dict.copyright, stringIdxPtr, stringStartPtr,
613 stringOffSize, buf));
615 if (dict.fullName != 0) {
616 fprintf(out, "/FullName (%s) readonly def\n",
617 getString(dict.fullName, stringIdxPtr, stringStartPtr,
618 stringOffSize, buf));
620 if (dict.familyName != 0) {
621 fprintf(out, "/FamilyName (%s) readonly def\n",
622 getString(dict.familyName, stringIdxPtr, stringStartPtr,
623 stringOffSize, buf));
625 if (dict.weight != 0) {
626 fprintf(out, "/Weight (%s) readonly def\n",
627 getString(dict.weight, stringIdxPtr, stringStartPtr,
628 stringOffSize, buf));
630 fprintf(out, "/isFixedPitch %s def\n", dict.isFixedPitch ? "true" : "false");
631 fprintf(out, "/ItalicAngle %g def\n", dict.italicAngle);
632 fprintf(out, "/UnderlinePosition %g def\n", dict.underlinePosition);
633 fprintf(out, "/UnderlineThickness %g def\n", dict.underlineThickness);
634 fprintf(out, "end readonly def\n");
635 fprintf(out, "/FontName /%s def\n", fontName);
636 fprintf(out, "/PaintType %d def\n", dict.paintType);
637 fprintf(out, "/FontType 1 def\n");
638 fprintf(out, "/FontMatrix [%g %g %g %g %g %g] readonly def\n",
639 dict.fontMatrix[0], dict.fontMatrix[1], dict.fontMatrix[2],
640 dict.fontMatrix[3], dict.fontMatrix[4], dict.fontMatrix[5]);
641 fprintf(out, "/FontBBox [%g %g %g %g] readonly def\n",
642 dict.fontBBox[0], dict.fontBBox[1],
643 dict.fontBBox[2], dict.fontBBox[3]);
644 if (dict.uniqueID != 0) {
645 fprintf(out, "/UniqueID %d def\n", dict.uniqueID);
648 // get number of glyphs from charstrings index
649 topPtr = (Guchar *)file + dict.charStrings;
650 nGlyphs = getWord(topPtr, 2);
653 if (dict.charset == 0) {
654 glyphNames = type1CISOAdobeCharset;
655 } else if (dict.charset == 1) {
656 glyphNames = type1CExpertCharset;
657 } else if (dict.charset == 2) {
658 glyphNames = type1CExpertSubsetCharset;
660 glyphNames = (Gushort *)gmalloc(nGlyphs * sizeof(Gushort));
662 topPtr = (Guchar *)file + dict.charset;
663 charsetFormat = *topPtr++;
664 if (charsetFormat == 0) {
665 for (i = 1; i < nGlyphs; ++i) {
666 glyphNames[i] = getWord(topPtr, 2);
669 } else if (charsetFormat == 1) {
671 while (i < nGlyphs) {
672 c = getWord(topPtr, 2);
675 for (j = 0; j <= nLeft; ++j)
676 glyphNames[i++] = c++;
678 } else if (charsetFormat == 2) {
680 while (i < nGlyphs) {
681 c = getWord(topPtr, 2);
683 nLeft = getWord(topPtr, 2);
685 for (j = 0; j <= nLeft; ++j)
686 glyphNames[i++] = c++;
691 // read encoding (glyph -> code mapping), write Type 1 encoding
692 fprintf(out, "/Encoding ");
693 if (dict.encoding == 0) {
694 fprintf(out, "StandardEncoding def\n");
696 fprintf(out, "256 array\n");
697 fprintf(out, "0 1 255 {1 index exch /.notdef put} for\n");
698 if (dict.encoding == 1) {
699 for (i = 0; i < 256; ++i) {
700 if (type1ExpertEncodingNames[i])
701 fprintf(out, "dup %d /%s put\n", i, type1ExpertEncodingNames[i]);
704 topPtr = (Guchar *)file + dict.encoding;
705 encFormat = *topPtr++;
706 if ((encFormat & 0x7f) == 0) {
707 nCodes = 1 + *topPtr++;
708 if (nCodes > nGlyphs) {
711 for (i = 1; i < nCodes; ++i) {
713 fprintf(out, "dup %d /%s put\n", c,
714 getString(glyphNames[i], stringIdxPtr, stringStartPtr,
715 stringOffSize, buf));
717 } else if ((encFormat & 0x7f) == 1) {
720 for (i = 0; i < nRanges; ++i) {
723 for (j = 0; j <= nLeft && nCodes < nGlyphs; ++j) {
724 fprintf(out, "dup %d /%s put\n", c,
725 getString(glyphNames[nCodes], stringIdxPtr, stringStartPtr,
726 stringOffSize, buf));
732 if (encFormat & 0x80) {
734 for (i = 0; i < nSups; ++i) {
736 sid = getWord(topPtr, 2);
738 fprintf(out, "dup %d /%s put\n", c,
739 getString(sid, stringIdxPtr, stringStartPtr,
740 stringOffSize, buf));
744 fprintf(out, "readonly def\n");
746 fprintf(out, "currentdict end\n");
747 fprintf(out, "currentfile eexec\n");
749 // get private dictionary
750 eexecWrite("\x83\xca\x73\xd5");
751 eexecWrite("dup /Private 32 dict dup begin\n");
752 eexecWrite("/RD {string currentfile exch readstring pop} executeonly def\n");
753 eexecWrite("/ND {noaccess def} executeonly def\n");
754 eexecWrite("/NP {noaccess put} executeonly def\n");
755 eexecWrite("/MinFeature {16 16} ND\n");
756 eexecWrite("/password 5839 def\n");
760 topPtr = (Guchar *)file + dict.privateOffset;
762 idxPtr1 = idxPtr0 + dict.privateSize;
764 while (idxPtr0 < idxPtr1) {
765 if (*idxPtr0 <= 27 || *idxPtr0 == 31) {
768 key = (key << 8) | *idxPtr0++;
771 getDeltaInt(eBuf, "BlueValues", op, i);
775 getDeltaInt(eBuf, "OtherBlues", op, i);
779 getDeltaInt(eBuf, "FamilyBlues", op, i);
783 getDeltaInt(eBuf, "FamilyOtherBlues", op, i);
787 sprintf(eBuf, "/BlueScale %g def\n", op[0]);
791 sprintf(eBuf, "/BlueShift %d def\n", (int)op[0]);
795 sprintf(eBuf, "/BlueFuzz %d def\n", (int)op[0]);
799 sprintf(eBuf, "/StdHW [%g] def\n", op[0]);
803 sprintf(eBuf, "/StdVW [%g] def\n", op[0]);
807 getDeltaReal(eBuf, "StemSnapH", op, i);
811 getDeltaReal(eBuf, "StemSnapV", op, i);
815 sprintf(eBuf, "/ForceBold %s def\n", op[0] ? "true" : "false");
819 sprintf(eBuf, "/ForceBoldThreshold %g def\n", op[0]);
823 sprintf(eBuf, "/LanguageGroup %d def\n", (int)op[0]);
827 sprintf(eBuf, "/ExpansionFactor %g def\n", op[0]);
831 error(-1, "Got Type 1C InitialRandomSeed");
834 subrsOffset = (int)op[0];
837 defaultWidthX = op[0];
838 defaultWidthXFP = fp[0];
841 nominalWidthX = op[0];
842 nominalWidthXFP = fp[0];
845 error(-1, "Uknown Type 1C private dict entry %04x", key);
850 x = getNum(&idxPtr0, &isFP);
859 if (subrsOffset != 0) {
860 topPtr += subrsOffset;
861 nSubrs = getWord(topPtr, 2);
862 idxOffSize = topPtr[2];
864 sprintf(eBuf, "/Subrs %d array\n", nSubrs);
866 idxStartPtr = topPtr + (nSubrs + 1) * idxOffSize - 1;
867 idxPtr1 = idxStartPtr + getWord(topPtr, idxOffSize);
868 for (i = 0; i < nSubrs; ++i) {
870 idxPtr1 = idxStartPtr + getWord(topPtr + (i+1)*idxOffSize, idxOffSize);
871 n = idxPtr1 - idxPtr0;
873 error(-1, "Unimplemented Type 2 subrs");
875 sprintf(eBuf, "dup %d %d RD ", i, n);
877 cvtGlyph(idxPtr0, n);
885 topPtr = (Guchar *)file + dict.charStrings;
886 nCharStrings = getWord(topPtr, 2);
887 idxOffSize = topPtr[2];
889 sprintf(eBuf, "2 index /CharStrings %d dict dup begin\n", nCharStrings);
891 idxStartPtr = topPtr + (nCharStrings + 1) * idxOffSize - 1;
892 idxPtr1 = idxStartPtr + getWord(topPtr, idxOffSize);
893 for (i = 0; i < nCharStrings; ++i) {
895 idxPtr1 = idxStartPtr + getWord(topPtr + (i+1)*idxOffSize, idxOffSize);
896 n = idxPtr1 - idxPtr0;
897 cvtGlyph(getString(glyphNames[i], stringIdxPtr, stringStartPtr,
903 eexecWrite("readonly put\n");
904 eexecWrite("noaccess put\n");
905 eexecWrite("dup /FontName get exch definefont pop\n");
906 eexecWrite("mark currentfile closefile\n");
911 for (i = 0; i < 8; ++i) {
912 fprintf(out, "0000000000000000000000000000000000000000000000000000000000000000\n");
914 fprintf(out, "cleartomark\n");
917 if (dict.charset > 2)
922 void Type1CFontConverter::eexecWrite(char *s) {
926 for (p = (Guchar *)s; *p; ++p) {
928 r1 = (x + r1) * 52845 + 22719;
929 fputc(hexChars[x >> 4], out);
930 fputc(hexChars[x & 0x0f], out);
939 void Type1CFontConverter::cvtGlyph(char *name, Guchar *s, int n) {
948 charBuf = new GString();
949 charBuf->append((char)73);
950 charBuf->append((char)58);
951 charBuf->append((char)147);
952 charBuf->append((char)134);
960 case 0: // dotsection (should be Type 1 only?)
965 error(-1, "Wrong number of args (%d) to Type 2 hflex", nOps);
967 eexecDumpNum(op[0], fp[0]);
968 eexecDumpNum(0, gFalse);
969 eexecDumpNum(op[1], fp[1]);
970 eexecDumpNum(op[2], fp[2]);
971 eexecDumpNum(op[3], fp[3]);
972 eexecDumpNum(0, gFalse);
974 eexecDumpNum(op[4], fp[4]);
975 eexecDumpNum(0, gFalse);
976 eexecDumpNum(op[5], fp[5]);
977 eexecDumpNum(-op[2], fp[2]);
978 eexecDumpNum(op[6], fp[6]);
979 eexecDumpNum(0, gFalse);
984 error(-1, "Wrong number of args (%d) to Type 2 flex", nOps);
986 eexecDumpNum(op[0], fp[0]);
987 eexecDumpNum(op[1], fp[1]);
988 eexecDumpNum(op[2], fp[2]);
989 eexecDumpNum(op[3], fp[3]);
990 eexecDumpNum(op[4], fp[4]);
991 eexecDumpNum(op[5], fp[5]);
993 eexecDumpNum(op[6], fp[6]);
994 eexecDumpNum(op[7], fp[7]);
995 eexecDumpNum(op[8], fp[8]);
996 eexecDumpNum(op[9], fp[9]);
997 eexecDumpNum(op[10], fp[10]);
998 eexecDumpNum(op[11], fp[11]);
1003 error(-1, "Wrong number of args (%d) to Type 2 hflex1", nOps);
1005 eexecDumpNum(op[0], fp[0]);
1006 eexecDumpNum(op[1], fp[1]);
1007 eexecDumpNum(op[2], fp[2]);
1008 eexecDumpNum(op[3], fp[3]);
1009 eexecDumpNum(op[4], fp[4]);
1010 eexecDumpNum(0, gFalse);
1012 eexecDumpNum(op[5], fp[5]);
1013 eexecDumpNum(0, gFalse);
1014 eexecDumpNum(op[6], fp[6]);
1015 eexecDumpNum(op[7], fp[7]);
1016 eexecDumpNum(op[8], fp[8]);
1017 eexecDumpNum(-(op[1] + op[3] + op[7]), fp[1] | fp[3] | fp[7]);
1022 error(-1, "Wrong number of args (%d) to Type 2 flex1", nOps);
1024 eexecDumpNum(op[0], fp[0]);
1025 eexecDumpNum(op[1], fp[1]);
1026 eexecDumpNum(op[2], fp[2]);
1027 eexecDumpNum(op[3], fp[3]);
1028 eexecDumpNum(op[4], fp[4]);
1029 eexecDumpNum(op[5], fp[5]);
1031 eexecDumpNum(op[6], fp[6]);
1032 eexecDumpNum(op[7], fp[7]);
1033 eexecDumpNum(op[8], fp[8]);
1034 eexecDumpNum(op[9], fp[9]);
1035 dx = op[0] + op[2] + op[4] + op[6] + op[8];
1036 dy = op[1] + op[3] + op[5] + op[7] + op[9];
1037 if (fabs(dx) > fabs(dy)) {
1038 eexecDumpNum(op[10], fp[10]);
1039 eexecDumpNum(-dy, fp[1] | fp[3] | fp[5] | fp[7] | fp[9]);
1041 eexecDumpNum(-dx, fp[0] | fp[2] | fp[4] | fp[6] | fp[8]);
1042 eexecDumpNum(op[10], fp[10]);
1068 error(-1, "Unimplemented Type 2 charstring op: 12.%d", s[i+1]);
1071 error(-1, "Illegal Type 2 charstring op: 12.%d", s[i+1]);
1076 } else if (s[i] == 19) { // hintmask
1079 cvtGlyphWidth(nOps == 1);
1084 error(-1, "Wrong number of args (%d) to Type 2 hintmask/vstemhm",
1089 i += 1 + ((nHints + 7) >> 3);
1091 } else if (s[i] == 20) { // cntrmask
1094 cvtGlyphWidth(nOps == 1);
1099 error(-1, "Wrong number of args (%d) to Type 2 cntrmask/vstemhm",
1104 i += 1 + ((nHints + 7) >> 3);
1106 } else if (s[i] == 28) {
1107 x = (s[i+1] << 8) + s[i+2];
1115 } else if (s[i] <= 31) {
1119 cvtGlyphWidth(nOps == 2);
1123 error(-1, "Wrong number of args (%d) to Type 2 vmoveto", nOps);
1124 eexecDumpNum(op[0], fp[0]);
1128 if (nOps < 2 || nOps % 2 != 0)
1129 error(-1, "Wrong number of args (%d) to Type 2 rlineto", nOps);
1130 for (k = 0; k < nOps; k += 2) {
1131 eexecDumpNum(op[k], fp[k]);
1132 eexecDumpNum(op[k+1], fp[k+1]);
1138 error(-1, "Wrong number of args (%d) to Type 2 hlineto", nOps);
1139 for (k = 0; k < nOps; ++k) {
1140 eexecDumpNum(op[k], fp[k]);
1141 eexecDumpOp1((k & 1) ? 7 : 6);
1146 error(-1, "Wrong number of args (%d) to Type 2 vlineto", nOps);
1147 for (k = 0; k < nOps; ++k) {
1148 eexecDumpNum(op[k], fp[k]);
1149 eexecDumpOp1((k & 1) ? 6 : 7);
1152 case 8: // rrcurveto
1153 if (nOps < 6 || nOps % 6 != 0)
1154 error(-1, "Wrong number of args (%d) to Type 2 rrcurveto", nOps);
1155 for (k = 0; k < nOps; k += 6) {
1156 eexecDumpNum(op[k], fp[k]);
1157 eexecDumpNum(op[k+1], fp[k+1]);
1158 eexecDumpNum(op[k+2], fp[k+2]);
1159 eexecDumpNum(op[k+3], fp[k+3]);
1160 eexecDumpNum(op[k+4], fp[k+4]);
1161 eexecDumpNum(op[k+5], fp[k+5]);
1165 case 14: // endchar / seac
1167 cvtGlyphWidth(nOps == 1 || nOps == 5);
1172 eexecDumpNum(op[0], fp[0]);
1173 eexecDumpNum(op[1], fp[1]);
1174 eexecDumpNum(op[2], fp[2]);
1175 eexecDumpNum(op[3], fp[3]);
1177 } else if (nOps == 0) {
1180 error(-1, "Wrong number of args (%d) to Type 2 endchar", nOps);
1185 cvtGlyphWidth(nOps == 3);
1189 error(-1, "Wrong number of args (%d) to Type 2 rmoveto", nOps);
1190 eexecDumpNum(op[0], fp[0]);
1191 eexecDumpNum(op[1], fp[1]);
1196 cvtGlyphWidth(nOps == 2);
1200 error(-1, "Wrong number of args (%d) to Type 2 hmoveto", nOps);
1201 eexecDumpNum(op[0], fp[0]);
1204 case 24: // rcurveline
1205 if (nOps < 8 || (nOps - 2) % 6 != 0)
1206 error(-1, "Wrong number of args (%d) to Type 2 rcurveline", nOps);
1207 for (k = 0; k < nOps - 2; k += 6) {
1208 eexecDumpNum(op[k], fp[k]);
1209 eexecDumpNum(op[k+1], fp[k+1]);
1210 eexecDumpNum(op[k+2], fp[k+2]);
1211 eexecDumpNum(op[k+3], fp[k+3]);
1212 eexecDumpNum(op[k+4], fp[k+4]);
1213 eexecDumpNum(op[k+5], fp[k+5]);
1216 eexecDumpNum(op[k], fp[k]);
1217 eexecDumpNum(op[k+1], fp[k]);
1220 case 25: // rlinecurve
1221 if (nOps < 8 || (nOps - 6) % 2 != 0)
1222 error(-1, "Wrong number of args (%d) to Type 2 rlinecurve", nOps);
1223 for (k = 0; k < nOps - 6; k += 2) {
1224 eexecDumpNum(op[k], fp[k]);
1225 eexecDumpNum(op[k+1], fp[k]);
1228 eexecDumpNum(op[k], fp[k]);
1229 eexecDumpNum(op[k+1], fp[k+1]);
1230 eexecDumpNum(op[k+2], fp[k+2]);
1231 eexecDumpNum(op[k+3], fp[k+3]);
1232 eexecDumpNum(op[k+4], fp[k+4]);
1233 eexecDumpNum(op[k+5], fp[k+5]);
1236 case 26: // vvcurveto
1237 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0))
1238 error(-1, "Wrong number of args (%d) to Type 2 vvcurveto", nOps);
1239 if (nOps % 2 == 1) {
1240 eexecDumpNum(op[0], fp[0]);
1241 eexecDumpNum(op[1], fp[1]);
1242 eexecDumpNum(op[2], fp[2]);
1243 eexecDumpNum(op[3], fp[3]);
1244 eexecDumpNum(0, gFalse);
1245 eexecDumpNum(op[4], fp[4]);
1251 for (; k < nOps; k += 4) {
1252 eexecDumpNum(0, gFalse);
1253 eexecDumpNum(op[k], fp[k]);
1254 eexecDumpNum(op[k+1], fp[k+1]);
1255 eexecDumpNum(op[k+2], fp[k+2]);
1256 eexecDumpNum(0, gFalse);
1257 eexecDumpNum(op[k+3], fp[k+3]);
1261 case 27: // hhcurveto
1262 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0))
1263 error(-1, "Wrong number of args (%d) to Type 2 hhcurveto", nOps);
1264 if (nOps % 2 == 1) {
1265 eexecDumpNum(op[1], fp[1]);
1266 eexecDumpNum(op[0], fp[0]);
1267 eexecDumpNum(op[2], fp[2]);
1268 eexecDumpNum(op[3], fp[3]);
1269 eexecDumpNum(op[4], fp[4]);
1270 eexecDumpNum(0, gFalse);
1276 for (; k < nOps; k += 4) {
1277 eexecDumpNum(op[k], fp[k]);
1278 eexecDumpNum(0, gFalse);
1279 eexecDumpNum(op[k+1], fp[k+1]);
1280 eexecDumpNum(op[k+2], fp[k+2]);
1281 eexecDumpNum(op[k+3], fp[k+3]);
1282 eexecDumpNum(0, gFalse);
1286 case 30: // vhcurveto
1287 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0))
1288 error(-1, "Wrong number of args (%d) to Type 2 vhcurveto", nOps);
1289 for (k = 0; k < nOps && k != nOps-5; k += 4) {
1291 eexecDumpNum(op[k], fp[k]);
1292 eexecDumpNum(op[k+1], fp[k+1]);
1293 eexecDumpNum(op[k+2], fp[k+2]);
1294 eexecDumpNum(op[k+3], fp[k+3]);
1297 eexecDumpNum(op[k], fp[k]);
1298 eexecDumpNum(op[k+1], fp[k+1]);
1299 eexecDumpNum(op[k+2], fp[k+2]);
1300 eexecDumpNum(op[k+3], fp[k+3]);
1306 eexecDumpNum(0, gFalse);
1307 eexecDumpNum(op[k], fp[k]);
1308 eexecDumpNum(op[k+1], fp[k+1]);
1309 eexecDumpNum(op[k+2], fp[k+2]);
1310 eexecDumpNum(op[k+3], fp[k+3]);
1311 eexecDumpNum(op[k+4], fp[k+4]);
1313 eexecDumpNum(op[k], fp[k]);
1314 eexecDumpNum(0, gFalse);
1315 eexecDumpNum(op[k+1], fp[k+1]);
1316 eexecDumpNum(op[k+2], fp[k+2]);
1317 eexecDumpNum(op[k+4], fp[k+4]);
1318 eexecDumpNum(op[k+3], fp[k+3]);
1323 case 31: // hvcurveto
1324 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0))
1325 error(-1, "Wrong number of args (%d) to Type 2 hvcurveto", nOps);
1326 for (k = 0; k < nOps && k != nOps-5; k += 4) {
1328 eexecDumpNum(op[k], fp[k]);
1329 eexecDumpNum(op[k+1], fp[k+1]);
1330 eexecDumpNum(op[k+2], fp[k+2]);
1331 eexecDumpNum(op[k+3], fp[k+3]);
1334 eexecDumpNum(op[k], fp[k]);
1335 eexecDumpNum(op[k+1], fp[k+1]);
1336 eexecDumpNum(op[k+2], fp[k+2]);
1337 eexecDumpNum(op[k+3], fp[k+3]);
1343 eexecDumpNum(op[k], fp[k]);
1344 eexecDumpNum(0, gFalse);
1345 eexecDumpNum(op[k+1], fp[k+1]);
1346 eexecDumpNum(op[k+2], fp[k+2]);
1347 eexecDumpNum(op[k+4], fp[k+4]);
1348 eexecDumpNum(op[k+3], fp[k+3]);
1350 eexecDumpNum(0, gFalse);
1351 eexecDumpNum(op[k], fp[k]);
1352 eexecDumpNum(op[k+1], fp[k+1]);
1353 eexecDumpNum(op[k+2], fp[k+2]);
1354 eexecDumpNum(op[k+3], fp[k+3]);
1355 eexecDumpNum(op[k+4], fp[k+4]);
1362 cvtGlyphWidth(nOps & 1);
1366 error(-1, "Wrong number of args (%d) to Type 2 hstem", nOps);
1370 for (k = 0; k < nOps; k += 2) {
1372 d += op[k] + op[k+1];
1373 dFP |= fp[k] | fp[k+1];
1374 eexecDumpNum(d, dFP);
1375 eexecDumpNum(-op[k+1], fp[k+1]);
1379 eexecDumpNum(d, dFP);
1380 eexecDumpNum(op[k+1], fp[k+1]);
1390 cvtGlyphWidth(nOps & 1);
1394 error(-1, "Wrong number of args (%d) to Type 2 vstem", nOps);
1398 for (k = 0; k < nOps; k += 2) {
1400 d += op[k] + op[k+1];
1401 dFP |= fp[k] | fp[k+1];
1402 eexecDumpNum(d, dFP);
1403 eexecDumpNum(-op[k+1], fp[k+1]);
1407 eexecDumpNum(d, dFP);
1408 eexecDumpNum(op[k+1], fp[k+1]);
1419 cvtGlyphWidth(nOps & 1);
1423 error(-1, "Wrong number of args (%d) to Type 2 hstemhm", nOps);
1430 cvtGlyphWidth(nOps & 1);
1434 error(-1, "Wrong number of args (%d) to Type 2 vstemhm", nOps);
1438 case 10: // callsubr
1441 case 29: // callgsubr
1442 error(-1, "Unimplemented Type 2 charstring op: %d", s[i]);
1445 error(-1, "Illegal Type 2 charstring op: %d", s[i]);
1450 } else if (s[i] <= 246) {
1453 op[nOps++] = (int)s[i] - 139;
1456 } else if (s[i] <= 250) {
1459 op[nOps++] = (((int)s[i] - 247) << 8) + (int)s[i+1] + 108;
1462 } else if (s[i] <= 254) {
1465 op[nOps++] = -(((int)s[i] - 251) << 8) - (int)s[i+1] - 108;
1469 x = (s[i+1] << 24) | (s[i+2] << 16) | (s[i+3] << 8) | s[i+4];
1474 op[nOps++] = (double)x / 65536.0;
1480 sprintf(eBuf, "/%s %d RD ", name, charBuf->getLength());
1482 eexecWriteCharstring((Guchar *)charBuf->getCString(), charBuf->getLength());
1483 eexecWrite(" ND\n");
1487 void Type1CFontConverter::cvtGlyphWidth(GBool useOp) {
1493 w = nominalWidthX + op[0];
1494 wFP = nominalWidthXFP | fp[0];
1495 for (i = 1; i < nOps; ++i) {
1502 wFP = defaultWidthXFP;
1504 eexecDumpNum(0, gFalse);
1505 eexecDumpNum(w, wFP);
1509 void Type1CFontConverter::eexecDumpNum(double x, GBool fp) {
1515 if (x >= -32768 && x < 32768) {
1516 y = (int)(x * 256.0);
1518 buf[1] = (Guchar)(y >> 24);
1519 buf[2] = (Guchar)(y >> 16);
1520 buf[3] = (Guchar)(y >> 8);
1531 error(-1, "Type 2 fixed point constant out of range");
1535 if (y >= -107 && y <= 107) {
1536 buf[0] = (Guchar)(y + 139);
1538 } else if (y > 107 && y <= 1131) {
1540 buf[0] = (Guchar)((y >> 8) + 247);
1541 buf[1] = (Guchar)(y & 0xff);
1543 } else if (y < -107 && y >= -1131) {
1545 buf[0] = (Guchar)((y >> 8) + 251);
1546 buf[1] = (Guchar)(y & 0xff);
1550 buf[1] = (Guchar)(y >> 24);
1551 buf[2] = (Guchar)(y >> 16);
1552 buf[3] = (Guchar)(y >> 8);
1557 charBuf->append((char *)buf, n);
1560 void Type1CFontConverter::eexecDumpOp1(int op) {
1561 charBuf->append((char)op);
1564 void Type1CFontConverter::eexecDumpOp2(int op) {
1565 charBuf->append((char)12);
1566 charBuf->append((char)op);
1569 void Type1CFontConverter::eexecWriteCharstring(Guchar *s, int n) {
1576 for (i = 0; i < n; ++i) {
1577 // charstring encryption
1580 r2 = (x + r2) * 52845 + 22719;
1584 r1 = (x + r1) * 52845 + 22719;
1585 fputc(hexChars[x >> 4], out);
1586 fputc(hexChars[x & 0x0f], out);
1595 void Type1CFontConverter::getDeltaInt(char *buf, char *name, double *op,
1599 buf += sprintf(buf, "/%s [", name);
1601 for (i = 0; i < n; ++i) {
1603 buf += sprintf(buf, "%s%d", i > 0 ? " " : "", x);
1605 sprintf(buf, "] def\n");
1608 void Type1CFontConverter::getDeltaReal(char *buf, char *name, double *op,
1613 buf += sprintf(buf, "/%s [", name);
1615 for (i = 0; i < n; ++i) {
1617 buf += sprintf(buf, "%s%g", i > 0 ? " " : "", x);
1619 sprintf(buf, "] def\n");