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, *p2;
69 for (i = 1, line = file; i <= 100 && line < file + len && !encoding; ++i) {
72 if (!strncmp(line, "/FontName", 9)) {
73 strncpy(buf, line, 255);
75 if ((p = strchr(buf+9, '/')) &&
76 (p = strtok(p+1, " \t\n\r")))
78 line = nextLine(line, file + len);
81 } else if (!strncmp(line, "/Encoding StandardEncoding def", 30)) {
82 encoding = type1StdEncoding.copy();
83 } else if (!strncmp(line, "/Encoding 256 array", 19)) {
84 encoding = new FontEncoding();
85 for (i = 0; i < 300; ++i) {
86 line1 = nextLine(line, file + len);
87 if ((n = line1 - line) > 255)
89 strncpy(buf, line, n);
91 for (p = buf; *p == ' ' || *p == '\t'; ++p) ;
92 if (!strncmp(p, "dup", 3)) {
93 for (p += 3; *p == ' ' || *p == '\t'; ++p) ;
94 for (p2 = p; *p2 >= '0' && *p2 <= '9'; ++p2) ;
98 if ((code = atoi(p)) < 256) {
100 for (p = p2; *p == ' ' || *p == '\t'; ++p) ;
103 for (p2 = p; *p2 && *p2 != ' ' && *p2 != '\t'; ++p2) ;
105 encoding->addChar(code, copyString(p));
110 if (strtok(buf, " \t") &&
111 (p = strtok(NULL, " \t\n\r")) && !strcmp(p, "def")) {
117 //~ check for getinterval/putinterval junk
120 line = nextLine(line, file + len);
125 Type1FontFile::~Type1FontFile() {
128 if (encoding && freeEnc)
132 FontEncoding *Type1FontFile::getEncoding(GBool taken) {
138 //------------------------------------------------------------------------
140 //------------------------------------------------------------------------
142 Type1CFontFile::Type1CFontFile(char *file, int len) {
144 Guchar *topPtr, *idxStartPtr, *idxPtr0, *idxPtr1;
145 Guchar *stringIdxPtr, *stringStartPtr;
146 int topOffSize, idxOffSize, stringOffSize;
147 int nFonts, nStrings, nGlyphs;
148 int nCodes, nRanges, nLeft, nSups;
150 int charset, enc, charstrings;
151 int charsetFormat, encFormat;
164 topPtr = (Guchar *)file + (file[2] & 0xff);
165 topOffSize = file[3] & 0xff;
167 // read name index (first font only)
168 nFonts = getWord(topPtr, 2);
169 idxOffSize = topPtr[2];
171 idxStartPtr = topPtr + (nFonts + 1) * idxOffSize - 1;
172 idxPtr0 = idxStartPtr + getWord(topPtr, idxOffSize);
173 idxPtr1 = idxStartPtr + getWord(topPtr + idxOffSize, idxOffSize);
174 if ((n = idxPtr1 - idxPtr0) > 255)
176 strncpy(buf, (char *)idxPtr0, n);
178 name = copyString(buf);
179 topPtr = idxStartPtr + getWord(topPtr + nFonts * idxOffSize, idxOffSize);
181 // read top dict index (first font only)
182 nFonts = getWord(topPtr, 2);
183 idxOffSize = topPtr[2];
185 idxStartPtr = topPtr + (nFonts + 1) * idxOffSize - 1;
186 idxPtr0 = idxStartPtr + getWord(topPtr, idxOffSize);
187 idxPtr1 = idxStartPtr + getWord(topPtr + idxOffSize, idxOffSize);
192 while (idxPtr0 < idxPtr1) {
193 if (*idxPtr0 <= 27 || *idxPtr0 == 31) {
196 key = (key << 8) | *idxPtr0++;
197 if (key == 0x0f) { // charset
198 charset = (int)op[0];
199 } else if (key == 0x10) { // encoding
201 } else if (key == 0x11) { // charstrings
202 charstrings = (int)op[0];
206 x = getNum(&idxPtr0, &isFP);
211 topPtr = idxStartPtr + getWord(topPtr + nFonts * idxOffSize, idxOffSize);
214 nStrings = getWord(topPtr, 2);
215 stringOffSize = topPtr[2];
217 stringIdxPtr = topPtr;
218 stringStartPtr = topPtr + (nStrings + 1) * stringOffSize - 1;
219 topPtr = stringStartPtr + getWord(topPtr + nStrings * stringOffSize,
222 // get number of glyphs from charstrings index
223 topPtr = (Guchar *)file + charstrings;
224 nGlyphs = getWord(topPtr, 2);
228 glyphNames = type1CISOAdobeCharset;
229 } else if (charset == 1) {
230 glyphNames = type1CExpertCharset;
231 } else if (charset == 2) {
232 glyphNames = type1CExpertSubsetCharset;
234 glyphNames = (Gushort *)gmalloc(nGlyphs * sizeof(Gushort));
236 topPtr = (Guchar *)file + charset;
237 charsetFormat = *topPtr++;
238 if (charsetFormat == 0) {
239 for (i = 1; i < nGlyphs; ++i) {
240 glyphNames[i] = getWord(topPtr, 2);
243 } else if (charsetFormat == 1) {
245 while (i < nGlyphs) {
246 c = getWord(topPtr, 2);
249 for (j = 0; j <= nLeft; ++j)
250 glyphNames[i++] = c++;
252 } else if (charsetFormat == 2) {
254 while (i < nGlyphs) {
255 c = getWord(topPtr, 2);
257 nLeft = getWord(topPtr, 2);
259 for (j = 0; j <= nLeft; ++j)
260 glyphNames[i++] = c++;
265 // read encoding (glyph -> code mapping)
267 encoding = type1StdEncoding.copy();
268 } else if (enc == 1) {
269 encoding = type1ExpertEncoding.copy();
271 encoding = new FontEncoding();
272 topPtr = (Guchar *)file + enc;
273 encFormat = *topPtr++;
274 if ((encFormat & 0x7f) == 0) {
275 nCodes = 1 + *topPtr++;
276 if (nCodes > nGlyphs) {
279 for (i = 1; i < nCodes; ++i) {
281 getString(glyphNames[i], stringIdxPtr, stringStartPtr,
283 encoding->addChar(c, copyString(buf));
285 } else if ((encFormat & 0x7f) == 1) {
288 for (i = 0; i < nRanges; ++i) {
291 for (j = 0; j <= nLeft && nCodes < nGlyphs; ++j) {
292 getString(glyphNames[nCodes], stringIdxPtr, stringStartPtr,
294 encoding->addChar(c, copyString(buf));
300 if (encFormat & 0x80) {
302 for (i = 0; i < nSups; ++i) {
304 sid = getWord(topPtr, 2);
306 getString(sid, stringIdxPtr, stringStartPtr,
308 encoding->addChar(c, copyString(buf));
317 Type1CFontFile::~Type1CFontFile() {
320 if (encoding && freeEnc)
324 FontEncoding *Type1CFontFile::getEncoding(GBool taken) {
330 static Guint getWord(Guchar *ptr, int size) {
335 for (i = 0; i < size; ++i)
336 x = (x << 8) + *ptr++;
340 static double getNum(Guchar **ptr, GBool *fp) {
341 static char nybChars[16] = "0123456789.ee -";
342 int b0, b, nyb0, nyb1;
352 } else if (b0 == 28) {
353 x = ((*ptr)[1] << 8) + (*ptr)[2];
355 } else if (b0 == 29) {
356 x = ((*ptr)[1] << 24) + ((*ptr)[2] << 16) + ((*ptr)[3] << 8) + (*ptr)[4];
358 } else if (b0 == 30) {
367 buf[i++] = nybChars[nyb0];
376 buf[i++] = nybChars[nyb1];
385 } else if (b0 == 31) {
387 } else if (b0 < 247) {
390 } else if (b0 < 251) {
391 x = ((b0 - 247) << 8) + (*ptr)[1] + 108;
394 x = -((b0 - 251) << 8) - (*ptr)[1] - 108;
400 static char *getString(int sid, Guchar *stringIdxPtr,
401 Guchar *stringStartPtr, int stringOffSize,
403 Guchar *idxPtr0, *idxPtr1;
407 strcpy(buf, type1CStdStrings[sid]);
410 idxPtr0 = stringStartPtr + getWord(stringIdxPtr + sid * stringOffSize,
412 idxPtr1 = stringStartPtr + getWord(stringIdxPtr + (sid+1) * stringOffSize,
414 if ((len = idxPtr1 - idxPtr0) > 255)
416 strncpy(buf, (char *)idxPtr0, len);
422 //------------------------------------------------------------------------
423 // Type1CFontConverter
424 //------------------------------------------------------------------------
426 Type1CFontConverter::Type1CFontConverter(char *file, int len, FILE *out) {
434 Type1CFontConverter::~Type1CFontConverter() {
437 void Type1CFontConverter::convert() {
448 double underlinePosition;
449 double underlineThickness;
451 int charstringType; //~ ???
452 double fontMatrix[6];
455 double strokeWidth; //~ ???
462 char buf[256], eBuf[256];
463 Guchar *topPtr, *idxStartPtr, *idxPtr0, *idxPtr1;
464 Guchar *stringIdxPtr, *stringStartPtr;
465 int topOffSize, idxOffSize, stringOffSize;
466 int nFonts, nStrings, nGlyphs;
467 int nCodes, nRanges, nLeft, nSups;
469 int charsetFormat, encFormat;
470 int subrsOffset, nSubrs;
479 topPtr = (Guchar *)file + (file[2] & 0xff);
480 topOffSize = file[3] & 0xff;
482 // read name (first font only)
483 nFonts = getWord(topPtr, 2);
484 idxOffSize = topPtr[2];
486 idxStartPtr = topPtr + (nFonts + 1) * idxOffSize - 1;
487 idxPtr0 = idxStartPtr + getWord(topPtr, idxOffSize);
488 idxPtr1 = idxStartPtr + getWord(topPtr + idxOffSize, idxOffSize);
489 if ((n = idxPtr1 - idxPtr0) > 255)
491 strncpy(buf, (char *)idxPtr0, n);
493 fontName = copyString(buf);
494 topPtr = idxStartPtr + getWord(topPtr + nFonts * idxOffSize, idxOffSize);
496 // read top dict (first font only)
497 nFonts = getWord(topPtr, 2);
498 idxOffSize = topPtr[2];
500 idxStartPtr = topPtr + (nFonts + 1) * idxOffSize - 1;
501 idxPtr0 = idxStartPtr + getWord(topPtr, idxOffSize);
502 idxPtr1 = idxStartPtr + getWord(topPtr + idxOffSize, idxOffSize);
509 dict.isFixedPitch = 0;
510 dict.italicAngle = 0;
511 dict.underlinePosition = -100;
512 dict.underlineThickness = 50;
514 dict.charstringType = 2;
515 dict.fontMatrix[0] = 0.001;
516 dict.fontMatrix[1] = 0;
517 dict.fontMatrix[2] = 0;
518 dict.fontMatrix[3] = 0.001;
519 dict.fontMatrix[4] = 0;
520 dict.fontMatrix[5] = 0;
522 dict.fontBBox[0] = 0;
523 dict.fontBBox[1] = 0;
524 dict.fontBBox[2] = 0;
525 dict.fontBBox[3] = 0;
526 dict.strokeWidth = 0;
529 dict.charStrings = 0;
530 dict.privateSize = 0;
531 dict.privateOffset = 0;
533 while (idxPtr0 < idxPtr1) {
534 if (*idxPtr0 <= 27 || *idxPtr0 == 31) {
537 key = (key << 8) | *idxPtr0++;
539 case 0x0000: dict.version = (int)op[0]; break;
540 case 0x0001: dict.notice = (int)op[0]; break;
541 case 0x0c00: dict.copyright = (int)op[0]; break;
542 case 0x0002: dict.fullName = (int)op[0]; break;
543 case 0x0003: dict.familyName = (int)op[0]; break;
544 case 0x0004: dict.weight = (int)op[0]; break;
545 case 0x0c01: dict.isFixedPitch = (int)op[0]; break;
546 case 0x0c02: dict.italicAngle = op[0]; break;
547 case 0x0c03: dict.underlinePosition = op[0]; break;
548 case 0x0c04: dict.underlineThickness = op[0]; break;
549 case 0x0c05: dict.paintType = (int)op[0]; break;
550 case 0x0c06: dict.charstringType = (int)op[0]; break;
551 case 0x0c07: dict.fontMatrix[0] = op[0];
552 dict.fontMatrix[1] = op[1];
553 dict.fontMatrix[2] = op[2];
554 dict.fontMatrix[3] = op[3];
555 dict.fontMatrix[4] = op[4];
556 dict.fontMatrix[5] = op[5]; break;
557 case 0x000d: dict.uniqueID = (int)op[0]; break;
558 case 0x0005: dict.fontBBox[0] = op[0];
559 dict.fontBBox[1] = op[1];
560 dict.fontBBox[2] = op[2];
561 dict.fontBBox[3] = op[3]; break;
562 case 0x0c08: dict.strokeWidth = op[0]; break;
563 case 0x000f: dict.charset = (int)op[0]; break;
564 case 0x0010: dict.encoding = (int)op[0]; break;
565 case 0x0011: dict.charStrings = (int)op[0]; break;
566 case 0x0012: dict.privateSize = (int)op[0];
567 dict.privateOffset = (int)op[1]; break;
571 x = getNum(&idxPtr0, &isFP);
578 topPtr = idxStartPtr + getWord(topPtr + nFonts * idxOffSize, idxOffSize);
581 nStrings = getWord(topPtr, 2);
582 stringOffSize = topPtr[2];
584 stringIdxPtr = topPtr;
585 stringStartPtr = topPtr + (nStrings + 1) * stringOffSize - 1;
586 topPtr = stringStartPtr + getWord(topPtr + nStrings * stringOffSize,
594 nGSubrs = getWord(topPtr, 2);
595 gSubrOffSize = topPtr[2];
599 // write header and font dictionary, up to encoding
600 fprintf(out, "%%!FontType1-1.0: %s", fontName);
601 if (dict.version != 0) {
603 getString(dict.version, stringIdxPtr, stringStartPtr,
604 stringOffSize, buf));
607 fprintf(out, "11 dict begin\n");
608 fprintf(out, "/FontInfo 10 dict dup begin\n");
609 if (dict.version != 0) {
610 fprintf(out, "/version (%s) readonly def\n",
611 getString(dict.version, stringIdxPtr, stringStartPtr,
612 stringOffSize, buf));
614 if (dict.notice != 0) {
615 fprintf(out, "/Notice (%s) readonly def\n",
616 getString(dict.notice, stringIdxPtr, stringStartPtr,
617 stringOffSize, buf));
619 if (dict.copyright != 0) {
620 fprintf(out, "/Copyright (%s) readonly def\n",
621 getString(dict.copyright, stringIdxPtr, stringStartPtr,
622 stringOffSize, buf));
624 if (dict.fullName != 0) {
625 fprintf(out, "/FullName (%s) readonly def\n",
626 getString(dict.fullName, stringIdxPtr, stringStartPtr,
627 stringOffSize, buf));
629 if (dict.familyName != 0) {
630 fprintf(out, "/FamilyName (%s) readonly def\n",
631 getString(dict.familyName, stringIdxPtr, stringStartPtr,
632 stringOffSize, buf));
634 if (dict.weight != 0) {
635 fprintf(out, "/Weight (%s) readonly def\n",
636 getString(dict.weight, stringIdxPtr, stringStartPtr,
637 stringOffSize, buf));
639 fprintf(out, "/isFixedPitch %s def\n", dict.isFixedPitch ? "true" : "false");
640 fprintf(out, "/ItalicAngle %g def\n", dict.italicAngle);
641 fprintf(out, "/UnderlinePosition %g def\n", dict.underlinePosition);
642 fprintf(out, "/UnderlineThickness %g def\n", dict.underlineThickness);
643 fprintf(out, "end readonly def\n");
644 fprintf(out, "/FontName /%s def\n", fontName);
645 fprintf(out, "/PaintType %d def\n", dict.paintType);
646 fprintf(out, "/FontType 1 def\n");
647 fprintf(out, "/FontMatrix [%g %g %g %g %g %g] readonly def\n",
648 dict.fontMatrix[0], dict.fontMatrix[1], dict.fontMatrix[2],
649 dict.fontMatrix[3], dict.fontMatrix[4], dict.fontMatrix[5]);
650 fprintf(out, "/FontBBox [%g %g %g %g] readonly def\n",
651 dict.fontBBox[0], dict.fontBBox[1],
652 dict.fontBBox[2], dict.fontBBox[3]);
653 if (dict.uniqueID != 0) {
654 fprintf(out, "/UniqueID %d def\n", dict.uniqueID);
657 // get number of glyphs from charstrings index
658 topPtr = (Guchar *)file + dict.charStrings;
659 nGlyphs = getWord(topPtr, 2);
662 if (dict.charset == 0) {
663 glyphNames = type1CISOAdobeCharset;
664 } else if (dict.charset == 1) {
665 glyphNames = type1CExpertCharset;
666 } else if (dict.charset == 2) {
667 glyphNames = type1CExpertSubsetCharset;
669 glyphNames = (Gushort *)gmalloc(nGlyphs * sizeof(Gushort));
671 topPtr = (Guchar *)file + dict.charset;
672 charsetFormat = *topPtr++;
673 if (charsetFormat == 0) {
674 for (i = 1; i < nGlyphs; ++i) {
675 glyphNames[i] = getWord(topPtr, 2);
678 } else if (charsetFormat == 1) {
680 while (i < nGlyphs) {
681 c = getWord(topPtr, 2);
684 for (j = 0; j <= nLeft; ++j)
685 glyphNames[i++] = c++;
687 } else if (charsetFormat == 2) {
689 while (i < nGlyphs) {
690 c = getWord(topPtr, 2);
692 nLeft = getWord(topPtr, 2);
694 for (j = 0; j <= nLeft; ++j)
695 glyphNames[i++] = c++;
700 // read encoding (glyph -> code mapping), write Type 1 encoding
701 fprintf(out, "/Encoding ");
702 if (dict.encoding == 0) {
703 fprintf(out, "StandardEncoding def\n");
705 fprintf(out, "256 array\n");
706 fprintf(out, "0 1 255 {1 index exch /.notdef put} for\n");
707 if (dict.encoding == 1) {
708 for (i = 0; i < 256; ++i) {
709 if (type1ExpertEncodingNames[i])
710 fprintf(out, "dup %d /%s put\n", i, type1ExpertEncodingNames[i]);
713 topPtr = (Guchar *)file + dict.encoding;
714 encFormat = *topPtr++;
715 if ((encFormat & 0x7f) == 0) {
716 nCodes = 1 + *topPtr++;
717 if (nCodes > nGlyphs) {
720 for (i = 1; i < nCodes; ++i) {
722 fprintf(out, "dup %d /%s put\n", c,
723 getString(glyphNames[i], stringIdxPtr, stringStartPtr,
724 stringOffSize, buf));
726 } else if ((encFormat & 0x7f) == 1) {
729 for (i = 0; i < nRanges; ++i) {
732 for (j = 0; j <= nLeft && nCodes < nGlyphs; ++j) {
733 fprintf(out, "dup %d /%s put\n", c,
734 getString(glyphNames[nCodes], stringIdxPtr, stringStartPtr,
735 stringOffSize, buf));
741 if (encFormat & 0x80) {
743 for (i = 0; i < nSups; ++i) {
745 sid = getWord(topPtr, 2);
747 fprintf(out, "dup %d /%s put\n", c,
748 getString(sid, stringIdxPtr, stringStartPtr,
749 stringOffSize, buf));
753 fprintf(out, "readonly def\n");
755 fprintf(out, "currentdict end\n");
756 fprintf(out, "currentfile eexec\n");
758 // get private dictionary
759 eexecWrite("\x83\xca\x73\xd5");
760 eexecWrite("dup /Private 32 dict dup begin\n");
761 eexecWrite("/RD {string currentfile exch readstring pop} executeonly def\n");
762 eexecWrite("/ND {noaccess def} executeonly def\n");
763 eexecWrite("/NP {noaccess put} executeonly def\n");
764 eexecWrite("/MinFeature {16 16} ND\n");
765 eexecWrite("/password 5839 def\n");
769 topPtr = (Guchar *)file + dict.privateOffset;
771 idxPtr1 = idxPtr0 + dict.privateSize;
773 while (idxPtr0 < idxPtr1) {
774 if (*idxPtr0 <= 27 || *idxPtr0 == 31) {
777 key = (key << 8) | *idxPtr0++;
780 getDeltaInt(eBuf, "BlueValues", op, i);
784 getDeltaInt(eBuf, "OtherBlues", op, i);
788 getDeltaInt(eBuf, "FamilyBlues", op, i);
792 getDeltaInt(eBuf, "FamilyOtherBlues", op, i);
796 sprintf(eBuf, "/BlueScale %g def\n", op[0]);
800 sprintf(eBuf, "/BlueShift %d def\n", (int)op[0]);
804 sprintf(eBuf, "/BlueFuzz %d def\n", (int)op[0]);
808 sprintf(eBuf, "/StdHW [%g] def\n", op[0]);
812 sprintf(eBuf, "/StdVW [%g] def\n", op[0]);
816 getDeltaReal(eBuf, "StemSnapH", op, i);
820 getDeltaReal(eBuf, "StemSnapV", op, i);
824 sprintf(eBuf, "/ForceBold %s def\n", op[0] ? "true" : "false");
828 sprintf(eBuf, "/ForceBoldThreshold %g def\n", op[0]);
832 sprintf(eBuf, "/LanguageGroup %d def\n", (int)op[0]);
836 sprintf(eBuf, "/ExpansionFactor %g def\n", op[0]);
840 error(-1, "Got Type 1C InitialRandomSeed");
843 subrsOffset = (int)op[0];
846 defaultWidthX = op[0];
847 defaultWidthXFP = fp[0];
850 nominalWidthX = op[0];
851 nominalWidthXFP = fp[0];
854 error(-1, "Uknown Type 1C private dict entry %04x", key);
859 x = getNum(&idxPtr0, &isFP);
868 if (subrsOffset != 0) {
869 topPtr += subrsOffset;
870 nSubrs = getWord(topPtr, 2);
871 idxOffSize = topPtr[2];
873 sprintf(eBuf, "/Subrs %d array\n", nSubrs);
875 idxStartPtr = topPtr + (nSubrs + 1) * idxOffSize - 1;
876 idxPtr1 = idxStartPtr + getWord(topPtr, idxOffSize);
877 for (i = 0; i < nSubrs; ++i) {
879 idxPtr1 = idxStartPtr + getWord(topPtr + (i+1)*idxOffSize, idxOffSize);
880 n = idxPtr1 - idxPtr0;
882 error(-1, "Unimplemented Type 2 subrs");
884 sprintf(eBuf, "dup %d %d RD ", i, n);
886 cvtGlyph(idxPtr0, n);
894 topPtr = (Guchar *)file + dict.charStrings;
895 nCharStrings = getWord(topPtr, 2);
896 idxOffSize = topPtr[2];
898 sprintf(eBuf, "2 index /CharStrings %d dict dup begin\n", nCharStrings);
900 idxStartPtr = topPtr + (nCharStrings + 1) * idxOffSize - 1;
901 idxPtr1 = idxStartPtr + getWord(topPtr, idxOffSize);
902 for (i = 0; i < nCharStrings; ++i) {
904 idxPtr1 = idxStartPtr + getWord(topPtr + (i+1)*idxOffSize, idxOffSize);
905 n = idxPtr1 - idxPtr0;
906 cvtGlyph(getString(glyphNames[i], stringIdxPtr, stringStartPtr,
912 eexecWrite("readonly put\n");
913 eexecWrite("noaccess put\n");
914 eexecWrite("dup /FontName get exch definefont pop\n");
915 eexecWrite("mark currentfile closefile\n");
920 for (i = 0; i < 8; ++i) {
921 fprintf(out, "0000000000000000000000000000000000000000000000000000000000000000\n");
923 fprintf(out, "cleartomark\n");
926 if (dict.charset > 2)
931 void Type1CFontConverter::eexecWrite(char *s) {
935 for (p = (Guchar *)s; *p; ++p) {
937 r1 = (x + r1) * 52845 + 22719;
938 fputc(hexChars[x >> 4], out);
939 fputc(hexChars[x & 0x0f], out);
948 void Type1CFontConverter::cvtGlyph(char *name, Guchar *s, int n) {
957 charBuf = new GString();
958 charBuf->append((char)73);
959 charBuf->append((char)58);
960 charBuf->append((char)147);
961 charBuf->append((char)134);
969 case 0: // dotsection (should be Type 1 only?)
974 error(-1, "Wrong number of args (%d) to Type 2 hflex", nOps);
976 eexecDumpNum(op[0], fp[0]);
977 eexecDumpNum(0, gFalse);
978 eexecDumpNum(op[1], fp[1]);
979 eexecDumpNum(op[2], fp[2]);
980 eexecDumpNum(op[3], fp[3]);
981 eexecDumpNum(0, gFalse);
983 eexecDumpNum(op[4], fp[4]);
984 eexecDumpNum(0, gFalse);
985 eexecDumpNum(op[5], fp[5]);
986 eexecDumpNum(-op[2], fp[2]);
987 eexecDumpNum(op[6], fp[6]);
988 eexecDumpNum(0, gFalse);
993 error(-1, "Wrong number of args (%d) to Type 2 flex", nOps);
995 eexecDumpNum(op[0], fp[0]);
996 eexecDumpNum(op[1], fp[1]);
997 eexecDumpNum(op[2], fp[2]);
998 eexecDumpNum(op[3], fp[3]);
999 eexecDumpNum(op[4], fp[4]);
1000 eexecDumpNum(op[5], fp[5]);
1002 eexecDumpNum(op[6], fp[6]);
1003 eexecDumpNum(op[7], fp[7]);
1004 eexecDumpNum(op[8], fp[8]);
1005 eexecDumpNum(op[9], fp[9]);
1006 eexecDumpNum(op[10], fp[10]);
1007 eexecDumpNum(op[11], fp[11]);
1012 error(-1, "Wrong number of args (%d) to Type 2 hflex1", nOps);
1014 eexecDumpNum(op[0], fp[0]);
1015 eexecDumpNum(op[1], fp[1]);
1016 eexecDumpNum(op[2], fp[2]);
1017 eexecDumpNum(op[3], fp[3]);
1018 eexecDumpNum(op[4], fp[4]);
1019 eexecDumpNum(0, gFalse);
1021 eexecDumpNum(op[5], fp[5]);
1022 eexecDumpNum(0, gFalse);
1023 eexecDumpNum(op[6], fp[6]);
1024 eexecDumpNum(op[7], fp[7]);
1025 eexecDumpNum(op[8], fp[8]);
1026 eexecDumpNum(-(op[1] + op[3] + op[7]), fp[1] | fp[3] | fp[7]);
1031 error(-1, "Wrong number of args (%d) to Type 2 flex1", nOps);
1033 eexecDumpNum(op[0], fp[0]);
1034 eexecDumpNum(op[1], fp[1]);
1035 eexecDumpNum(op[2], fp[2]);
1036 eexecDumpNum(op[3], fp[3]);
1037 eexecDumpNum(op[4], fp[4]);
1038 eexecDumpNum(op[5], fp[5]);
1040 eexecDumpNum(op[6], fp[6]);
1041 eexecDumpNum(op[7], fp[7]);
1042 eexecDumpNum(op[8], fp[8]);
1043 eexecDumpNum(op[9], fp[9]);
1044 dx = op[0] + op[2] + op[4] + op[6] + op[8];
1045 dy = op[1] + op[3] + op[5] + op[7] + op[9];
1046 if (fabs(dx) > fabs(dy)) {
1047 eexecDumpNum(op[10], fp[10]);
1048 eexecDumpNum(-dy, fp[1] | fp[3] | fp[5] | fp[7] | fp[9]);
1050 eexecDumpNum(-dx, fp[0] | fp[2] | fp[4] | fp[6] | fp[8]);
1051 eexecDumpNum(op[10], fp[10]);
1077 error(-1, "Unimplemented Type 2 charstring op: 12.%d", s[i+1]);
1080 error(-1, "Illegal Type 2 charstring op: 12.%d", s[i+1]);
1085 } else if (s[i] == 19) { // hintmask
1088 cvtGlyphWidth(nOps == 1);
1093 error(-1, "Wrong number of args (%d) to Type 2 hintmask/vstemhm",
1098 i += 1 + ((nHints + 7) >> 3);
1100 } else if (s[i] == 20) { // cntrmask
1103 cvtGlyphWidth(nOps == 1);
1108 error(-1, "Wrong number of args (%d) to Type 2 cntrmask/vstemhm",
1113 i += 1 + ((nHints + 7) >> 3);
1115 } else if (s[i] == 28) {
1116 x = (s[i+1] << 8) + s[i+2];
1124 } else if (s[i] <= 31) {
1128 cvtGlyphWidth(nOps == 2);
1132 error(-1, "Wrong number of args (%d) to Type 2 vmoveto", nOps);
1133 eexecDumpNum(op[0], fp[0]);
1137 if (nOps < 2 || nOps % 2 != 0)
1138 error(-1, "Wrong number of args (%d) to Type 2 rlineto", nOps);
1139 for (k = 0; k < nOps; k += 2) {
1140 eexecDumpNum(op[k], fp[k]);
1141 eexecDumpNum(op[k+1], fp[k+1]);
1147 error(-1, "Wrong number of args (%d) to Type 2 hlineto", nOps);
1148 for (k = 0; k < nOps; ++k) {
1149 eexecDumpNum(op[k], fp[k]);
1150 eexecDumpOp1((k & 1) ? 7 : 6);
1155 error(-1, "Wrong number of args (%d) to Type 2 vlineto", nOps);
1156 for (k = 0; k < nOps; ++k) {
1157 eexecDumpNum(op[k], fp[k]);
1158 eexecDumpOp1((k & 1) ? 6 : 7);
1161 case 8: // rrcurveto
1162 if (nOps < 6 || nOps % 6 != 0)
1163 error(-1, "Wrong number of args (%d) to Type 2 rrcurveto", nOps);
1164 for (k = 0; k < nOps; k += 6) {
1165 eexecDumpNum(op[k], fp[k]);
1166 eexecDumpNum(op[k+1], fp[k+1]);
1167 eexecDumpNum(op[k+2], fp[k+2]);
1168 eexecDumpNum(op[k+3], fp[k+3]);
1169 eexecDumpNum(op[k+4], fp[k+4]);
1170 eexecDumpNum(op[k+5], fp[k+5]);
1174 case 14: // endchar / seac
1176 cvtGlyphWidth(nOps == 1 || nOps == 5);
1181 eexecDumpNum(op[0], fp[0]);
1182 eexecDumpNum(op[1], fp[1]);
1183 eexecDumpNum(op[2], fp[2]);
1184 eexecDumpNum(op[3], fp[3]);
1186 } else if (nOps == 0) {
1189 error(-1, "Wrong number of args (%d) to Type 2 endchar", nOps);
1194 cvtGlyphWidth(nOps == 3);
1198 error(-1, "Wrong number of args (%d) to Type 2 rmoveto", nOps);
1199 eexecDumpNum(op[0], fp[0]);
1200 eexecDumpNum(op[1], fp[1]);
1205 cvtGlyphWidth(nOps == 2);
1209 error(-1, "Wrong number of args (%d) to Type 2 hmoveto", nOps);
1210 eexecDumpNum(op[0], fp[0]);
1213 case 24: // rcurveline
1214 if (nOps < 8 || (nOps - 2) % 6 != 0)
1215 error(-1, "Wrong number of args (%d) to Type 2 rcurveline", nOps);
1216 for (k = 0; k < nOps - 2; k += 6) {
1217 eexecDumpNum(op[k], fp[k]);
1218 eexecDumpNum(op[k+1], fp[k+1]);
1219 eexecDumpNum(op[k+2], fp[k+2]);
1220 eexecDumpNum(op[k+3], fp[k+3]);
1221 eexecDumpNum(op[k+4], fp[k+4]);
1222 eexecDumpNum(op[k+5], fp[k+5]);
1225 eexecDumpNum(op[k], fp[k]);
1226 eexecDumpNum(op[k+1], fp[k]);
1229 case 25: // rlinecurve
1230 if (nOps < 8 || (nOps - 6) % 2 != 0)
1231 error(-1, "Wrong number of args (%d) to Type 2 rlinecurve", nOps);
1232 for (k = 0; k < nOps - 6; k += 2) {
1233 eexecDumpNum(op[k], fp[k]);
1234 eexecDumpNum(op[k+1], fp[k]);
1237 eexecDumpNum(op[k], fp[k]);
1238 eexecDumpNum(op[k+1], fp[k+1]);
1239 eexecDumpNum(op[k+2], fp[k+2]);
1240 eexecDumpNum(op[k+3], fp[k+3]);
1241 eexecDumpNum(op[k+4], fp[k+4]);
1242 eexecDumpNum(op[k+5], fp[k+5]);
1245 case 26: // vvcurveto
1246 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0))
1247 error(-1, "Wrong number of args (%d) to Type 2 vvcurveto", nOps);
1248 if (nOps % 2 == 1) {
1249 eexecDumpNum(op[0], fp[0]);
1250 eexecDumpNum(op[1], fp[1]);
1251 eexecDumpNum(op[2], fp[2]);
1252 eexecDumpNum(op[3], fp[3]);
1253 eexecDumpNum(0, gFalse);
1254 eexecDumpNum(op[4], fp[4]);
1260 for (; k < nOps; k += 4) {
1261 eexecDumpNum(0, gFalse);
1262 eexecDumpNum(op[k], fp[k]);
1263 eexecDumpNum(op[k+1], fp[k+1]);
1264 eexecDumpNum(op[k+2], fp[k+2]);
1265 eexecDumpNum(0, gFalse);
1266 eexecDumpNum(op[k+3], fp[k+3]);
1270 case 27: // hhcurveto
1271 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0))
1272 error(-1, "Wrong number of args (%d) to Type 2 hhcurveto", nOps);
1273 if (nOps % 2 == 1) {
1274 eexecDumpNum(op[1], fp[1]);
1275 eexecDumpNum(op[0], fp[0]);
1276 eexecDumpNum(op[2], fp[2]);
1277 eexecDumpNum(op[3], fp[3]);
1278 eexecDumpNum(op[4], fp[4]);
1279 eexecDumpNum(0, gFalse);
1285 for (; k < nOps; k += 4) {
1286 eexecDumpNum(op[k], fp[k]);
1287 eexecDumpNum(0, gFalse);
1288 eexecDumpNum(op[k+1], fp[k+1]);
1289 eexecDumpNum(op[k+2], fp[k+2]);
1290 eexecDumpNum(op[k+3], fp[k+3]);
1291 eexecDumpNum(0, gFalse);
1295 case 30: // vhcurveto
1296 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0))
1297 error(-1, "Wrong number of args (%d) to Type 2 vhcurveto", nOps);
1298 for (k = 0; k < nOps && k != nOps-5; k += 4) {
1300 eexecDumpNum(op[k], fp[k]);
1301 eexecDumpNum(op[k+1], fp[k+1]);
1302 eexecDumpNum(op[k+2], fp[k+2]);
1303 eexecDumpNum(op[k+3], fp[k+3]);
1306 eexecDumpNum(op[k], fp[k]);
1307 eexecDumpNum(op[k+1], fp[k+1]);
1308 eexecDumpNum(op[k+2], fp[k+2]);
1309 eexecDumpNum(op[k+3], fp[k+3]);
1315 eexecDumpNum(0, gFalse);
1316 eexecDumpNum(op[k], fp[k]);
1317 eexecDumpNum(op[k+1], fp[k+1]);
1318 eexecDumpNum(op[k+2], fp[k+2]);
1319 eexecDumpNum(op[k+3], fp[k+3]);
1320 eexecDumpNum(op[k+4], fp[k+4]);
1322 eexecDumpNum(op[k], fp[k]);
1323 eexecDumpNum(0, gFalse);
1324 eexecDumpNum(op[k+1], fp[k+1]);
1325 eexecDumpNum(op[k+2], fp[k+2]);
1326 eexecDumpNum(op[k+4], fp[k+4]);
1327 eexecDumpNum(op[k+3], fp[k+3]);
1332 case 31: // hvcurveto
1333 if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0))
1334 error(-1, "Wrong number of args (%d) to Type 2 hvcurveto", nOps);
1335 for (k = 0; k < nOps && k != nOps-5; k += 4) {
1337 eexecDumpNum(op[k], fp[k]);
1338 eexecDumpNum(op[k+1], fp[k+1]);
1339 eexecDumpNum(op[k+2], fp[k+2]);
1340 eexecDumpNum(op[k+3], fp[k+3]);
1343 eexecDumpNum(op[k], fp[k]);
1344 eexecDumpNum(op[k+1], fp[k+1]);
1345 eexecDumpNum(op[k+2], fp[k+2]);
1346 eexecDumpNum(op[k+3], fp[k+3]);
1352 eexecDumpNum(op[k], fp[k]);
1353 eexecDumpNum(0, gFalse);
1354 eexecDumpNum(op[k+1], fp[k+1]);
1355 eexecDumpNum(op[k+2], fp[k+2]);
1356 eexecDumpNum(op[k+4], fp[k+4]);
1357 eexecDumpNum(op[k+3], fp[k+3]);
1359 eexecDumpNum(0, gFalse);
1360 eexecDumpNum(op[k], fp[k]);
1361 eexecDumpNum(op[k+1], fp[k+1]);
1362 eexecDumpNum(op[k+2], fp[k+2]);
1363 eexecDumpNum(op[k+3], fp[k+3]);
1364 eexecDumpNum(op[k+4], fp[k+4]);
1371 cvtGlyphWidth(nOps & 1);
1375 error(-1, "Wrong number of args (%d) to Type 2 hstem", nOps);
1379 for (k = 0; k < nOps; k += 2) {
1381 d += op[k] + op[k+1];
1382 dFP |= fp[k] | fp[k+1];
1383 eexecDumpNum(d, dFP);
1384 eexecDumpNum(-op[k+1], fp[k+1]);
1388 eexecDumpNum(d, dFP);
1389 eexecDumpNum(op[k+1], fp[k+1]);
1399 cvtGlyphWidth(nOps & 1);
1403 error(-1, "Wrong number of args (%d) to Type 2 vstem", nOps);
1407 for (k = 0; k < nOps; k += 2) {
1409 d += op[k] + op[k+1];
1410 dFP |= fp[k] | fp[k+1];
1411 eexecDumpNum(d, dFP);
1412 eexecDumpNum(-op[k+1], fp[k+1]);
1416 eexecDumpNum(d, dFP);
1417 eexecDumpNum(op[k+1], fp[k+1]);
1428 cvtGlyphWidth(nOps & 1);
1432 error(-1, "Wrong number of args (%d) to Type 2 hstemhm", nOps);
1439 cvtGlyphWidth(nOps & 1);
1443 error(-1, "Wrong number of args (%d) to Type 2 vstemhm", nOps);
1447 case 10: // callsubr
1450 case 29: // callgsubr
1451 error(-1, "Unimplemented Type 2 charstring op: %d", s[i]);
1454 error(-1, "Illegal Type 2 charstring op: %d", s[i]);
1459 } else if (s[i] <= 246) {
1462 op[nOps++] = (int)s[i] - 139;
1465 } else if (s[i] <= 250) {
1468 op[nOps++] = (((int)s[i] - 247) << 8) + (int)s[i+1] + 108;
1471 } else if (s[i] <= 254) {
1474 op[nOps++] = -(((int)s[i] - 251) << 8) - (int)s[i+1] - 108;
1478 x = (s[i+1] << 24) | (s[i+2] << 16) | (s[i+3] << 8) | s[i+4];
1483 op[nOps++] = (double)x / 65536.0;
1489 sprintf(eBuf, "/%s %d RD ", name, charBuf->getLength());
1491 eexecWriteCharstring((Guchar *)charBuf->getCString(), charBuf->getLength());
1492 eexecWrite(" ND\n");
1496 void Type1CFontConverter::cvtGlyphWidth(GBool useOp) {
1502 w = nominalWidthX + op[0];
1503 wFP = nominalWidthXFP | fp[0];
1504 for (i = 1; i < nOps; ++i) {
1511 wFP = defaultWidthXFP;
1513 eexecDumpNum(0, gFalse);
1514 eexecDumpNum(w, wFP);
1518 void Type1CFontConverter::eexecDumpNum(double x, GBool fp) {
1524 if (x >= -32768 && x < 32768) {
1525 y = (int)(x * 256.0);
1527 buf[1] = (Guchar)(y >> 24);
1528 buf[2] = (Guchar)(y >> 16);
1529 buf[3] = (Guchar)(y >> 8);
1540 error(-1, "Type 2 fixed point constant out of range");
1544 if (y >= -107 && y <= 107) {
1545 buf[0] = (Guchar)(y + 139);
1547 } else if (y > 107 && y <= 1131) {
1549 buf[0] = (Guchar)((y >> 8) + 247);
1550 buf[1] = (Guchar)(y & 0xff);
1552 } else if (y < -107 && y >= -1131) {
1554 buf[0] = (Guchar)((y >> 8) + 251);
1555 buf[1] = (Guchar)(y & 0xff);
1559 buf[1] = (Guchar)(y >> 24);
1560 buf[2] = (Guchar)(y >> 16);
1561 buf[3] = (Guchar)(y >> 8);
1566 charBuf->append((char *)buf, n);
1569 void Type1CFontConverter::eexecDumpOp1(int op) {
1570 charBuf->append((char)op);
1573 void Type1CFontConverter::eexecDumpOp2(int op) {
1574 charBuf->append((char)12);
1575 charBuf->append((char)op);
1578 void Type1CFontConverter::eexecWriteCharstring(Guchar *s, int n) {
1585 for (i = 0; i < n; ++i) {
1586 // charstring encryption
1589 r2 = (x + r2) * 52845 + 22719;
1593 r1 = (x + r1) * 52845 + 22719;
1594 fputc(hexChars[x >> 4], out);
1595 fputc(hexChars[x & 0x0f], out);
1604 void Type1CFontConverter::getDeltaInt(char *buf, char *name, double *op,
1608 sprintf(buf, "/%s [", name);
1611 for (i = 0; i < n; ++i) {
1613 sprintf(buf, "%s%d", i > 0 ? " " : "", x);
1616 sprintf(buf, "] def\n");
1619 void Type1CFontConverter::getDeltaReal(char *buf, char *name, double *op,
1624 sprintf(buf, "/%s [", name);
1627 for (i = 0; i < n; ++i) {
1629 sprintf(buf, "%s%g", i > 0 ? " " : "", x);
1632 sprintf(buf, "] def\n");