1 /* Copyright (C) 2000-2008 by George Williams */
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are met:
6 * Redistributions of source code must retain the above copyright notice, this
7 * list of conditions and the following disclaimer.
9 * Redistributions in binary form must reproduce the above copyright notice,
10 * this list of conditions and the following disclaimer in the documentation
11 * and/or other materials provided with the distribution.
13 * The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 #include <sys/types.h>
40 FontDict
*fd
, *mainfd
;
41 /* always in font data */
43 unsigned int inchars
:1;
44 unsigned int inprivate
:1;
45 unsigned int insubs
:1;
46 unsigned int inmetrics
: 1;
47 unsigned int inmetrics2
: 1;
49 unsigned int inencoding
: 1;
50 unsigned int simpleencoding
: 1;
51 unsigned int multiline
: 1;
52 unsigned int incidsysteminfo
: 1;
53 unsigned int inblendfi
:1;
54 unsigned int inblendprivate
:1;
55 unsigned int skipping_mbf
: 1;
56 unsigned int inblend
: 1;
57 unsigned int iscid
: 1;
58 unsigned int iscff
: 1;
59 unsigned int useshexstrings
: 1;
60 unsigned int doneencoding
: 1;
61 unsigned int ignore
: 1;
68 unsigned int alreadycomplained
: 1;
70 char *vbuf
, *vmax
, *vpt
;
74 static void copyenc(char *encoding
[256],char *std
[256]) {
76 for ( i
=0; i
<256; ++i
)
77 encoding
[i
] = copy(std
[i
]);
80 char *AdobeStandardEncoding
[] = {
100 /* 0013 */ ".notdef",
101 /* 0014 */ ".notdef",
102 /* 0015 */ ".notdef",
103 /* 0016 */ ".notdef",
104 /* 0017 */ ".notdef",
105 /* 0018 */ ".notdef",
106 /* 0019 */ ".notdef",
107 /* 001a */ ".notdef",
108 /* 001b */ ".notdef",
109 /* 001c */ ".notdef",
110 /* 001d */ ".notdef",
111 /* 001e */ ".notdef",
112 /* 001f */ ".notdef",
115 /* 0022 */ "quotedbl",
116 /* 0023 */ "numbersign",
118 /* 0025 */ "percent",
119 /* 0026 */ "ampersand",
120 /* 0027 */ "quoteright",
121 /* 0028 */ "parenleft",
122 /* 0029 */ "parenright",
123 /* 002a */ "asterisk",
140 /* 003b */ "semicolon",
143 /* 003e */ "greater",
144 /* 003f */ "question",
172 /* 005b */ "bracketleft",
173 /* 005c */ "backslash",
174 /* 005d */ "bracketright",
175 /* 005e */ "asciicircum",
176 /* 005f */ "underscore",
177 /* 0060 */ "quoteleft",
204 /* 007b */ "braceleft",
206 /* 007d */ "braceright",
207 /* 007e */ "asciitilde",
208 /* 007f */ ".notdef",
209 /* 0080 */ ".notdef",
210 /* 0081 */ ".notdef",
211 /* 0082 */ ".notdef",
212 /* 0083 */ ".notdef",
213 /* 0084 */ ".notdef",
214 /* 0085 */ ".notdef",
215 /* 0086 */ ".notdef",
216 /* 0087 */ ".notdef",
217 /* 0088 */ ".notdef",
218 /* 0089 */ ".notdef",
219 /* 008a */ ".notdef",
220 /* 008b */ ".notdef",
221 /* 008c */ ".notdef",
222 /* 008d */ ".notdef",
223 /* 008e */ ".notdef",
224 /* 008f */ ".notdef",
225 /* 0090 */ ".notdef",
226 /* 0091 */ ".notdef",
227 /* 0092 */ ".notdef",
228 /* 0093 */ ".notdef",
229 /* 0094 */ ".notdef",
230 /* 0095 */ ".notdef",
231 /* 0096 */ ".notdef",
232 /* 0097 */ ".notdef",
233 /* 0098 */ ".notdef",
234 /* 0099 */ ".notdef",
235 /* 009a */ ".notdef",
236 /* 009b */ ".notdef",
237 /* 009c */ ".notdef",
238 /* 009d */ ".notdef",
239 /* 009e */ ".notdef",
240 /* 009f */ ".notdef",
241 /* 00a0 */ ".notdef",
242 /* 00a1 */ "exclamdown",
244 /* 00a3 */ "sterling",
245 /* 00a4 */ "fraction",
248 /* 00a7 */ "section",
249 /* 00a8 */ "currency",
250 /* 00a9 */ "quotesingle",
251 /* 00aa */ "quotedblleft",
252 /* 00ab */ "guillemotleft",
253 /* 00ac */ "guilsinglleft",
254 /* 00ad */ "guilsinglright",
257 /* 00b0 */ ".notdef",
260 /* 00b3 */ "daggerdbl",
261 /* 00b4 */ "periodcentered",
262 /* 00b5 */ ".notdef",
263 /* 00b6 */ "paragraph",
265 /* 00b8 */ "quotesinglbase",
266 /* 00b9 */ "quotedblbase",
267 /* 00ba */ "quotedblright",
268 /* 00bb */ "guillemotright",
269 /* 00bc */ "ellipsis",
270 /* 00bd */ "perthousand",
271 /* 00be */ ".notdef",
272 /* 00bf */ "questiondown",
273 /* 00c0 */ ".notdef",
276 /* 00c3 */ "circumflex",
280 /* 00c7 */ "dotaccent",
281 /* 00c8 */ "dieresis",
282 /* 00c9 */ ".notdef",
284 /* 00cb */ "cedilla",
285 /* 00cc */ ".notdef",
286 /* 00cd */ "hungarumlaut",
290 /* 00d1 */ ".notdef",
291 /* 00d2 */ ".notdef",
292 /* 00d3 */ ".notdef",
293 /* 00d4 */ ".notdef",
294 /* 00d5 */ ".notdef",
295 /* 00d6 */ ".notdef",
296 /* 00d7 */ ".notdef",
297 /* 00d8 */ ".notdef",
298 /* 00d9 */ ".notdef",
299 /* 00da */ ".notdef",
300 /* 00db */ ".notdef",
301 /* 00dc */ ".notdef",
302 /* 00dd */ ".notdef",
303 /* 00de */ ".notdef",
304 /* 00df */ ".notdef",
305 /* 00e0 */ ".notdef",
307 /* 00e2 */ ".notdef",
308 /* 00e3 */ "ordfeminine",
309 /* 00e4 */ ".notdef",
310 /* 00e5 */ ".notdef",
311 /* 00e6 */ ".notdef",
312 /* 00e7 */ ".notdef",
316 /* 00eb */ "ordmasculine",
317 /* 00ec */ ".notdef",
318 /* 00ed */ ".notdef",
319 /* 00ee */ ".notdef",
320 /* 00ef */ ".notdef",
321 /* 00f0 */ ".notdef",
323 /* 00f2 */ ".notdef",
324 /* 00f3 */ ".notdef",
325 /* 00f4 */ ".notdef",
326 /* 00f5 */ "dotlessi",
327 /* 00f6 */ ".notdef",
328 /* 00f7 */ ".notdef",
332 /* 00fb */ "germandbls",
333 /* 00fc */ ".notdef",
334 /* 00fd */ ".notdef",
335 /* 00fe */ ".notdef",
338 static void setStdEnc(char *encoding
[256]) {
339 copyenc(encoding
,AdobeStandardEncoding
);
342 static void setLatin1Enc(char *encoding
[256]) {
343 static char *latin1enc
[] = {
344 /* 0000 */ ".notdef",
345 /* 0001 */ ".notdef",
346 /* 0002 */ ".notdef",
347 /* 0003 */ ".notdef",
348 /* 0004 */ ".notdef",
349 /* 0005 */ ".notdef",
350 /* 0006 */ ".notdef",
351 /* 0007 */ ".notdef",
352 /* 0008 */ ".notdef",
353 /* 0009 */ ".notdef",
354 /* 000a */ ".notdef",
355 /* 000b */ ".notdef",
356 /* 000c */ ".notdef",
357 /* 000d */ ".notdef",
358 /* 000e */ ".notdef",
359 /* 000f */ ".notdef",
360 /* 0010 */ ".notdef",
361 /* 0011 */ ".notdef",
362 /* 0012 */ ".notdef",
363 /* 0013 */ ".notdef",
364 /* 0014 */ ".notdef",
365 /* 0015 */ ".notdef",
366 /* 0016 */ ".notdef",
367 /* 0017 */ ".notdef",
368 /* 0018 */ ".notdef",
369 /* 0019 */ ".notdef",
370 /* 001a */ ".notdef",
371 /* 001b */ ".notdef",
372 /* 001c */ ".notdef",
373 /* 001d */ ".notdef",
374 /* 001e */ ".notdef",
375 /* 001f */ ".notdef",
378 /* 0022 */ "quotedbl",
379 /* 0023 */ "numbersign",
381 /* 0025 */ "percent",
382 /* 0026 */ "ampersand",
383 /* 0027 */ "quoteright",
384 /* 0028 */ "parenleft",
385 /* 0029 */ "parenright",
386 /* 002a */ "asterisk",
403 /* 003b */ "semicolon",
406 /* 003e */ "greater",
407 /* 003f */ "question",
435 /* 005b */ "bracketleft",
436 /* 005c */ "backslash",
437 /* 005d */ "bracketright",
438 /* 005e */ "asciicircum",
439 /* 005f */ "underscore",
467 /* 007b */ "braceleft",
469 /* 007d */ "braceright",
470 /* 007e */ "asciitilde",
471 /* 007f */ ".notdef",
472 /* 0080 */ ".notdef",
473 /* 0081 */ ".notdef",
474 /* 0082 */ ".notdef",
475 /* 0083 */ ".notdef",
476 /* 0084 */ ".notdef",
477 /* 0085 */ ".notdef",
478 /* 0086 */ ".notdef",
479 /* 0087 */ ".notdef",
480 /* 0088 */ ".notdef",
481 /* 0089 */ ".notdef",
482 /* 008a */ ".notdef",
483 /* 008b */ ".notdef",
484 /* 008c */ ".notdef",
485 /* 008d */ ".notdef",
486 /* 008e */ ".notdef",
487 /* 008f */ ".notdef",
488 /* 0090 */ "dotlessi", /* Um, Adobe's Latin1 has some extra chars */
490 /* 0092 */ "accute", /* This is a duplicate... */
491 /* 0093 */ "circumflex",
495 /* 0097 */ "dotaccent",
496 /* 0098 */ "dieresis",
497 /* 0099 */ ".notdef",
499 /* 009b */ "cedilla",
500 /* 009c */ ".notdef",
501 /* 009d */ "hungarumlaut",
505 /* 00a1 */ "exclamdown",
507 /* 00a3 */ "sterling",
508 /* 00a4 */ "currency",
510 /* 00a6 */ "brokenbar",
511 /* 00a7 */ "section",
512 /* 00a8 */ "dieresis",
513 /* 00a9 */ "copyright",
514 /* 00aa */ "ordfeminine",
515 /* 00ab */ "guillemotleft",
516 /* 00ac */ "logicalnot",
518 /* 00ae */ "registered",
521 /* 00b1 */ "plusminus",
522 /* 00b2 */ "twosuperior",
523 /* 00b3 */ "threesuperior",
526 /* 00b6 */ "paragraph",
527 /* 00b7 */ "periodcentered",
528 /* 00b8 */ "cedilla",
529 /* 00b9 */ "onesuperior",
530 /* 00ba */ "ordmasculine",
531 /* 00bb */ "guillemotright",
532 /* 00bc */ "onequarter",
533 /* 00bd */ "onehalf",
534 /* 00be */ "threequarters",
535 /* 00bf */ "questiondown",
538 /* 00c2 */ "Acircumflex",
540 /* 00c4 */ "Adieresis",
543 /* 00c7 */ "Ccedilla",
546 /* 00ca */ "Ecircumflex",
547 /* 00cb */ "Edieresis",
550 /* 00ce */ "Icircumflex",
551 /* 00cf */ "Idieresis",
556 /* 00d4 */ "Ocircumflex",
558 /* 00d6 */ "Odieresis",
559 /* 00d7 */ "multiply",
563 /* 00db */ "Ucircumflex",
564 /* 00dc */ "Udieresis",
567 /* 00df */ "germandbls",
570 /* 00e2 */ "acircumflex",
572 /* 00e4 */ "adieresis",
575 /* 00e7 */ "ccedilla",
578 /* 00ea */ "ecircumflex",
579 /* 00eb */ "edieresis",
582 /* 00ee */ "icircumflex",
583 /* 00ef */ "idieresis",
588 /* 00f4 */ "ocircumflex",
590 /* 00f6 */ "odieresis",
595 /* 00fb */ "ucircumflex",
596 /* 00fc */ "udieresis",
599 /* 00ff */ "ydieresis"
601 copyenc(encoding
,latin1enc
);
604 char *AdobeExpertEncoding
[] = {
605 /* 0000 */ ".notdef",
606 /* 0001 */ ".notdef",
607 /* 0002 */ ".notdef",
608 /* 0003 */ ".notdef",
609 /* 0004 */ ".notdef",
610 /* 0005 */ ".notdef",
611 /* 0006 */ ".notdef",
612 /* 0007 */ ".notdef",
613 /* 0008 */ ".notdef",
614 /* 0009 */ ".notdef",
615 /* 000a */ ".notdef",
616 /* 000b */ ".notdef",
617 /* 000c */ ".notdef",
618 /* 000d */ ".notdef",
619 /* 000e */ ".notdef",
620 /* 000f */ ".notdef",
621 /* 0010 */ ".notdef",
622 /* 0011 */ ".notdef",
623 /* 0012 */ ".notdef",
624 /* 0013 */ ".notdef",
625 /* 0014 */ ".notdef",
626 /* 0015 */ ".notdef",
627 /* 0016 */ ".notdef",
628 /* 0017 */ ".notdef",
629 /* 0018 */ ".notdef",
630 /* 0019 */ ".notdef",
631 /* 001a */ ".notdef",
632 /* 001b */ ".notdef",
633 /* 001c */ ".notdef",
634 /* 001d */ ".notdef",
635 /* 001e */ ".notdef",
636 /* 001f */ ".notdef",
638 /* 0021 */ "exclamsmall",
639 /* 0022 */ "Hungarumlautsmal",
640 /* 0023 */ ".notdef",
641 /* 0024 */ "dollaroldstyle",
642 /* 0025 */ "dollarsuperior",
643 /* 0026 */ "ampersandsmall",
644 /* 0027 */ "Acutesmall",
645 /* 0028 */ "parenleftsuperior",
646 /* 0029 */ "parenrightsuperior",
647 /* 002a */ "twodotenleader",
648 /* 002b */ "onedotenleader",
652 /* 002f */ "fraction",
653 /* 0030 */ "zerooldstyle",
654 /* 0031 */ "oneoldstyle",
655 /* 0032 */ "twooldstyle",
656 /* 0033 */ "threeoldstyle",
657 /* 0034 */ "fouroldstyle",
658 /* 0035 */ "fiveoldstyle",
659 /* 0036 */ "sixoldstyle",
660 /* 0037 */ "sevenoldstyle",
661 /* 0038 */ "eightoldstyle",
662 /* 0039 */ "nineoldstyle",
664 /* 003b */ "semicolon",
665 /* 003c */ "commasuperior",
666 /* 003d */ "threequartersemdash",
667 /* 003e */ "periodsuperior",
668 /* 003f */ "questionsmall",
669 /* 0040 */ ".notdef",
670 /* 0041 */ "asuperior",
671 /* 0042 */ "bsuperior",
672 /* 0043 */ "centsuperior",
673 /* 0044 */ "dsuperior",
674 /* 0045 */ "esuperior",
675 /* 0046 */ ".notdef",
676 /* 0047 */ ".notdef",
677 /* 0048 */ ".notdef",
678 /* 0049 */ "isuperior",
679 /* 004a */ ".notdef",
680 /* 004b */ ".notdef",
681 /* 004c */ "lsuperior",
682 /* 004d */ "msuperior",
683 /* 004e */ "nsuperior",
684 /* 004f */ "osuperior",
685 /* 0050 */ ".notdef",
686 /* 0051 */ ".notdef",
687 /* 0052 */ "rsuperior",
688 /* 0053 */ "ssuperior",
689 /* 0054 */ "tsuperior",
690 /* 0055 */ ".notdef",
696 /* 005b */ "parenleftinferior",
697 /* 005c */ ".notdef",
698 /* 005d */ "parenrightinferior",
699 /* 005e */ "Circumflexsmall",
700 /* 005f */ "hyphensuperior",
701 /* 0060 */ "Gravesmall",
728 /* 007b */ "colonmonetary",
729 /* 007c */ "onefitted",
731 /* 007e */ "Tildesmall",
732 /* 007f */ ".notdef",
733 /* 0080 */ ".notdef",
734 /* 0081 */ ".notdef",
735 /* 0082 */ ".notdef",
736 /* 0083 */ ".notdef",
737 /* 0084 */ ".notdef",
738 /* 0085 */ ".notdef",
739 /* 0086 */ ".notdef",
740 /* 0087 */ ".notdef",
741 /* 0088 */ ".notdef",
742 /* 0089 */ ".notdef",
743 /* 008a */ ".notdef",
744 /* 008b */ ".notdef",
745 /* 008c */ ".notdef",
746 /* 008d */ ".notdef",
747 /* 008e */ ".notdef",
748 /* 008f */ ".notdef",
749 /* 0090 */ ".notdef",
750 /* 0091 */ ".notdef",
751 /* 0092 */ ".notdef",
752 /* 0093 */ ".notdef",
753 /* 0094 */ ".notdef",
754 /* 0095 */ ".notdef",
755 /* 0096 */ ".notdef",
756 /* 0097 */ ".notdef",
757 /* 0098 */ ".notdef",
758 /* 0099 */ ".notdef",
759 /* 009a */ ".notdef",
760 /* 009b */ ".notdef",
761 /* 009c */ ".notdef",
762 /* 009d */ ".notdef",
763 /* 009e */ ".notdef",
764 /* 009f */ ".notdef",
765 /* 00a0 */ ".notdef",
766 /* 00a1 */ "exclamdownsmall",
767 /* 00a2 */ "centoldstyle",
768 /* 00a3 */ "Lslashsmall",
769 /* 00a4 */ ".notdef",
770 /* 00a5 */ ".notdef",
771 /* 00a6 */ "Scaronsmall",
772 /* 00a7 */ "Zcaronsmall",
773 /* 00a8 */ "Dieresissmall",
774 /* 00a9 */ "Brevesmall",
775 /* 00aa */ "Caronsmall",
776 /* 00ab */ ".notdef",
777 /* 00ac */ "Dotaccentsmall",
778 /* 00ad */ ".notdef",
779 /* 00ae */ ".notdef",
780 /* 00af */ "Macronsmall",
781 /* 00b0 */ ".notdef",
782 /* 00b1 */ ".notdef",
783 /* 00b2 */ "figuredash",
784 /* 00b3 */ "hypheninferior",
785 /* 00b4 */ ".notdef",
786 /* 00b5 */ ".notdef",
787 /* 00b6 */ "Ogoneksmall",
788 /* 00b7 */ "Ringsmall",
789 /* 00b8 */ "Cedillasmall",
790 /* 00b9 */ ".notdef",
791 /* 00ba */ ".notdef",
792 /* 00bb */ ".notdef",
793 /* 00bc */ "onequarter",
794 /* 00bd */ "onehalf",
795 /* 00be */ "threequarters",
796 /* 00bf */ "questiondownsmall",
797 /* 00c0 */ "oneeighth",
798 /* 00c1 */ "threeeighths",
799 /* 00c2 */ "fiveeighths",
800 /* 00c3 */ "seveneighths",
801 /* 00c4 */ "onethird",
802 /* 00c5 */ "twothirds",
803 /* 00c6 */ ".notdef",
804 /* 00c7 */ ".notdef",
805 /* 00c8 */ "zerosuperior",
806 /* 00c9 */ "onesuperior",
807 /* 00ca */ "twosuperior",
808 /* 00cb */ "threesuperior",
809 /* 00cc */ "foursuperior",
810 /* 00cd */ "fivesuperior",
811 /* 00ce */ "sixsuperior",
812 /* 00cf */ "sevensuperior",
813 /* 00d0 */ "eightsuperior",
814 /* 00d1 */ "ninesuperior",
815 /* 00d2 */ "zeroinferior",
816 /* 00d3 */ "oneinferior",
817 /* 00d4 */ "twoinferior",
818 /* 00d5 */ "threeinferior",
819 /* 00d6 */ "fourinferior",
820 /* 00d7 */ "fiveinferior",
821 /* 00d8 */ "sixinferior",
822 /* 00d9 */ "seveninferior",
823 /* 00da */ "eightinferior",
824 /* 00db */ "nineinferior",
825 /* 00dc */ "centinferior",
826 /* 00dd */ "dollarinferior",
827 /* 00de */ "periodinferior",
828 /* 00df */ "commainferior",
829 /* 00e0 */ "Agravesmall",
830 /* 00e1 */ "Aacutesmall",
831 /* 00e2 */ "Acircumflexsmall",
832 /* 00e3 */ "Atildesmall",
833 /* 00e4 */ "Adieresissmall",
834 /* 00e5 */ "Aringsmall",
835 /* 00e6 */ "AEsmall",
836 /* 00e7 */ "Ccedillasmall",
837 /* 00e8 */ "Egravesmall",
838 /* 00e9 */ "Eacutesmall",
839 /* 00ea */ "Ecircumflexsmall",
840 /* 00eb */ "Edieresissmall",
841 /* 00ec */ "Igravesmall",
842 /* 00ed */ "Iacutesmall",
843 /* 00ee */ "Icircumflexsmall",
844 /* 00ef */ "Idieresissmall",
845 /* 00f0 */ "Ethsmall",
846 /* 00f1 */ "Ntildesmall",
847 /* 00f2 */ "Ogravesmall",
848 /* 00f3 */ "Oacutesmall",
849 /* 00f4 */ "Ocircumflexsmall",
850 /* 00f5 */ "Otildesmall",
851 /* 00f6 */ "Odieresissmall",
852 /* 00f7 */ "OEsmall",
853 /* 00f8 */ "Oslashsmall",
854 /* 00f9 */ "Ugravesmall",
855 /* 00fa */ "Uacutesmall",
856 /* 00fb */ "Ucircumflexsmall",
857 /* 00fc */ "Udieresissmall",
858 /* 00fd */ "Yacutesmall",
859 /* 00fe */ "Thornsmall",
860 /* 00ff */ "Ydieresissmall"
863 static struct fontdict
*MakeEmptyFont(void) {
864 struct fontdict
*ret
;
866 ret
= gcalloc(1,sizeof(struct fontdict
));
867 ret
->fontinfo
= gcalloc(1,sizeof(struct fontinfo
));
868 ret
->chars
= gcalloc(1,sizeof(struct pschars
));
869 ret
->private = gcalloc(1,sizeof(struct private));
870 ret
->private->subrs
= gcalloc(1,sizeof(struct pschars
));
871 ret
->private->private = gcalloc(1,sizeof(struct psdict
));
872 ret
->private->leniv
= 4;
873 ret
->encoding_name
= &custom
;
874 ret
->fontinfo
->fstype
= -1;
878 static struct fontdict
*PSMakeEmptyFont(void) {
879 struct fontdict
*ret
;
881 ret
= gcalloc(1,sizeof(struct fontdict
));
882 ret
->fontinfo
= gcalloc(1,sizeof(struct fontinfo
));
883 ret
->chars
= gcalloc(1,sizeof(struct pschars
));
884 ret
->private = gcalloc(1,sizeof(struct private));
885 ret
->private->subrs
= gcalloc(1,sizeof(struct pschars
));
886 ret
->private->private = gcalloc(1,sizeof(struct psdict
));
887 ret
->private->leniv
= 4;
888 ret
->charprocs
= gcalloc(1,sizeof(struct charprocs
));
889 ret
->encoding_name
= &custom
;
890 ret
->fontinfo
->fstype
= -1;
894 static char *myfgets(char *str
, int len
, FILE *file
) {
898 for ( pt
= str
, end
= str
+len
-1; pt
<end
&& (ch
=getc(file
))!=EOF
&& ch
!='\r' && ch
!='\n';
902 else if ( ch
=='\r' ) {
904 if ((ch
=getc(file
))!='\n' )
915 static char *myfgetsNoNulls(char *str
, int len
, FILE *file
) {
919 for ( pt
= str
, end
= str
+len
-1; pt
<end
&& (ch
=getc(file
))!=EOF
&& ch
!='\r' && ch
!='\n'; ) {
925 else if ( ch
=='\r' ) {
927 if ((ch
=getc(file
))!='\n' )
938 static char *getstring(char *start
,FILE *in
) {
940 int parencnt
=0, len
=0;
944 while ( *start
!='\0' && *start
!='(' ) ++start
;
945 if ( *start
=='\0' ) {
946 if ( myfgetsNoNulls(buffer
,sizeof(buffer
),in
)==NULL
)
955 for ( end
= start
; *end
!='\0' && (*end
!=')' || parencnt
>0); ++end
) {
956 if ( *end
=='\\' && (end
[1]=='(' || end
[1]==')'))
958 else if ( *end
=='(' ) ++parencnt
;
959 else if ( *end
==')' ) --parencnt
;
963 ret
= galloc(end
-start
+1);
965 ret
= grealloc(ret
,len
+end
-start
);
966 strncpy(ret
+len
-1,start
,end
-start
);
972 if ( myfgetsNoNulls(buffer
,sizeof(buffer
),in
)==NULL
)
979 static char *gettoken(char *start
) {
982 while ( *start
!='\0' && *start
!='/' && *start
!='(' ) ++start
;
983 if ( *start
=='/' || *start
=='(' ) ++start
;
984 for ( end
= start
; *end
!='\0' && !isspace(*end
) && *end
!='[' && *end
!='/' && *end
!='{' && *end
!='(' && *end
!=')'; ++end
);
985 ret
= galloc(end
-start
+1);
987 strncpy(ret
,start
,end
-start
);
988 ret
[end
-start
] = '\0';
992 static int getbool(char *start
) {
994 while ( isspace(*start
) ) ++start
;
995 if ( *start
=='T' || *start
=='t' )
1001 static void fillintarray(int *array
,char *start
,int maxentries
) {
1005 while ( *start
!='\0' && *start
!='[' && *start
!='{' ) ++start
;
1006 if ( *start
=='[' || *start
=='{' ) ++start
;
1007 for ( i
=0; i
<maxentries
&& *start
!=']' && *start
!='}'; ++i
) {
1008 array
[i
] = (int) strtod(start
,&end
);
1012 while ( isspace(*start
) ) ++start
;
1016 static void fillrealarray(real
*array
,char *start
,int maxentries
) {
1020 while ( *start
!='\0' && *start
!='[' && *start
!='{' ) ++start
;
1021 if ( *start
=='[' || *start
=='{' ) ++start
;
1022 for ( i
=0; i
<maxentries
&& *start
!=']' && *start
!='}'; ++i
) {
1023 while ( isspace( *start
)) ++start
;
1024 if ( isdigit(*start
) || *start
=='-' || *start
=='.' )
1025 array
[i
] = strtod(start
,&end
);
1026 else if ( strncmp(start
,"div",3)==0 && i
>=2 ) {
1027 /* Some of Luc Devroye's fonts have a "div" in the FontMatrix */
1028 array
[i
-2] /= array
[i
-1];
1036 while ( isspace(*start
) ) ++start
;
1040 static void InitDict(struct psdict
*dict
,char *line
) {
1041 while ( *line
!='/' && *line
!='\0' ) ++line
;
1042 while ( !isspace(*line
) && *line
!='\0' ) ++line
;
1043 dict
->cnt
+= strtol(line
,NULL
,10);
1044 if ( dict
->next
>0 ) { int i
; /* Shouldn't happen, but did in a bad file */
1045 dict
->keys
= grealloc(dict
->keys
,dict
->cnt
*sizeof(char *));
1046 dict
->values
= grealloc(dict
->values
,dict
->cnt
*sizeof(char *));
1047 for ( i
=dict
->next
; i
<dict
->cnt
; ++i
) {
1048 dict
->keys
[i
] = NULL
; dict
->values
[i
] = NULL
;
1051 dict
->keys
= gcalloc(dict
->cnt
,sizeof(char *));
1052 dict
->values
= gcalloc(dict
->cnt
,sizeof(char *));
1056 static void InitChars(struct pschars
*chars
,char *line
) {
1057 while ( *line
!='/' && *line
!='\0' ) ++line
;
1058 while ( !isspace(*line
) && *line
!='\0' ) ++line
;
1059 chars
->cnt
= strtol(line
,NULL
,10);
1060 if ( chars
->cnt
>0 ) {
1061 chars
->keys
= gcalloc(chars
->cnt
,sizeof(char *));
1062 chars
->values
= gcalloc(chars
->cnt
,sizeof(char *));
1063 chars
->lens
= gcalloc(chars
->cnt
,sizeof(int));
1064 ff_progress_change_total(chars
->cnt
);
1068 static void InitCharProcs(struct charprocs
*cp
, char *line
) {
1069 while ( *line
!='/' && *line
!='\0' ) ++line
;
1070 while ( !isspace(*line
) && *line
!='\0' ) ++line
;
1071 cp
->cnt
= strtol(line
,NULL
,10);
1073 cp
->keys
= gcalloc(cp
->cnt
,sizeof(char *));
1074 cp
->values
= gcalloc(cp
->cnt
,sizeof(SplineChar
*));
1075 ff_progress_change_total(cp
->cnt
);
1079 static int mycmp(char *str
,char *within
, char *end
) {
1080 while ( within
<end
) {
1081 if ( *str
!=*within
)
1082 return( *str
-*within
);
1085 return( *str
=='\0'?0:1 );
1088 static void ContinueValue(struct fontparse
*fp
, struct psdict
*dict
, char *line
) {
1089 int incomment
= false;
1092 if ( !fp
->instring
&& fp
->depth
==0 &&
1093 (strncmp(line
,"def",3)==0 ||
1094 strncmp(line
,"|-",2)==0 || strncmp(line
,"ND",2)==0)) {
1096 while ( fp
->vpt
>fp
->vbuf
+1 && isspace(fp
->vpt
[-1]) )
1098 if ( fp
->vpt
>fp
->vbuf
+8 && strncmp(fp
->vpt
-8,"noaccess",8)==0 )
1100 else if ( fp
->vpt
>fp
->vbuf
+8 && strncmp(fp
->vpt
-8,"readonly",8)==0 )
1102 else if ( fp
->vpt
>fp
->vbuf
+4 && strncmp(fp
->vpt
-4,"bind",4)==0 )
1107 /* In some URW fonts (Nimbus Sans L, n019003l) we get a complex */
1108 /* expression rather than just an array. This is ok. The expression */
1109 /* converts itself into an array. We could just truncate to the */
1110 /* default array, but I don't see any reason to do so */
1111 if ( fp
->pending_parse
!=NULL
) {
1112 *fp
->pending_parse
= copyn(fp
->vbuf
,fp
->vpt
-fp
->vbuf
);
1113 fp
->pending_parse
= NULL
;
1115 dict
->values
[dict
->next
] = copyn(fp
->vbuf
,fp
->vpt
-fp
->vbuf
);
1119 fp
->multiline
= false;
1122 if ( fp
->vpt
>=fp
->vmax
) {
1123 int len
= fp
->vmax
-fp
->vbuf
+1000, off
=fp
->vpt
-fp
->vbuf
;
1124 fp
->vbuf
= grealloc(fp
->vbuf
,len
);
1125 fp
->vpt
= fp
->vbuf
+off
;
1126 fp
->vmax
= fp
->vbuf
+len
;
1128 if ( fp
->instring
) {
1129 if ( *line
==')' ) --fp
->instring
;
1130 } else if ( incomment
) {
1132 } else if ( *line
=='(' )
1134 else if ( *line
=='%' )
1136 else if ( *line
=='[' || *line
=='{' )
1138 else if ( *line
=='}' || *line
==']' )
1140 *fp
->vpt
++ = *line
++;
1144 static void AddValue(struct fontparse
*fp
, struct psdict
*dict
, char *line
, char *endtok
) {
1148 if ( dict
->next
>=dict
->cnt
) {
1150 dict
->keys
= grealloc(dict
->keys
,dict
->cnt
*sizeof(char *));
1151 dict
->values
= grealloc(dict
->values
,dict
->cnt
*sizeof(char *));
1153 dict
->keys
[dict
->next
] = copyn(line
+1,endtok
-(line
+1));
1155 pt
= line
+strlen(line
)-1;
1156 while ( isspace(*endtok
)) ++endtok
;
1157 while ( pt
>endtok
&& isspace(*pt
)) --pt
;
1159 if ( strncmp(pt
-3,"def",3)==0 )
1161 else if ( strncmp(pt
-2,"|-",2)==0 || strncmp(pt
-2,"ND",2)==0 )
1164 fp
->multiline
= true;
1165 ContinueValue(fp
,dict
,endtok
);
1169 while ( pt
-1>endtok
&& isspace(pt
[-1])) --pt
;
1170 if ( pt
-8>endtok
&& strncmp(pt
-8,"noaccess",8)==0 )
1172 else if ( pt
-8>endtok
&& strncmp(pt
-8,"readonly",8)==0 )
1174 else if ( pt
-4>endtok
&& strncmp(pt
-4,"bind",4)==0 )
1180 dict
->values
[dict
->next
] = copyn(endtok
,pt
-endtok
);
1183 *fp
->pending_parse
= copyn(endtok
,pt
-endtok
);
1184 fp
->pending_parse
= NULL
;
1188 static int hex(int ch1
, int ch2
) {
1189 if ( ch1
>='0' && ch1
<='9' )
1191 else if ( ch1
>='a' )
1195 if ( ch2
>='0' && ch2
<='9' )
1197 else if ( ch2
>='a' )
1201 return( (ch1
<<4)|ch2
);
1208 static void initcode(void) {
1212 static int decode(unsigned char cypher
) {
1213 unsigned char plain
= ( cypher
^ (r
>>8));
1214 r
= (cypher
+ r
) * c1
+ c2
;
1218 static void dumpzeros(FILE *out
, unsigned char *zeros
, int zcnt
) {
1219 while ( --zcnt
>= 0 )
1220 fputc(*zeros
++,out
);
1223 static void decodestr(unsigned char *str
, int len
) {
1224 unsigned short r
= 4330;
1225 unsigned char plain
, cypher
;
1229 plain
= ( cypher
^ (r
>>8));
1230 r
= (cypher
+ r
) * c1
+ c2
;
1235 static void findstring(struct fontparse
*fp
,struct pschars
*subrs
,int index
,char *nametok
,char *str
) {
1236 char buffer
[1024], *bpt
, *bs
, *end
= buffer
+sizeof(buffer
)-1;
1239 while ( isspace(*str
)) ++str
;
1243 while ( *str
!=')' && *str
!='\0' ) {
1247 if ( isdigit( *++str
)) {
1249 if ( isdigit( *str
)) {
1250 val
= (val
<<3) | (*str
++-'0');
1251 if ( isdigit( *str
))
1252 val
= (val
<<3) | (*str
++-'0');
1260 decodestr((unsigned char *) buffer
,bpt
-buffer
);
1261 bs
= buffer
+ fp
->fd
->private->leniv
;
1262 if ( bpt
<bs
) bs
=bpt
; /* garbage */
1263 subrs
->lens
[index
] = bpt
-bs
;
1264 subrs
->keys
[index
] = copy(nametok
);
1265 subrs
->values
[index
] = galloc(bpt
-bs
);
1266 memcpy(subrs
->values
[index
],bs
,bpt
-bs
);
1267 if ( index
>=subrs
->next
) subrs
->next
= index
+1;
1271 /* Type42 charstrings are actually numbers */
1272 static void findnumbers(struct fontparse
*fp
,struct pschars
*chars
,char *str
) {
1277 int index
= chars
->next
;
1280 while ( isspace(*str
)) ++str
;
1284 while ( isalnum(*str
) || *str
=='.' ) ++str
;
1286 index
= chars
->next
;
1289 val
= strtol(str
,&end
,10);
1290 chars
->lens
[index
] = 0;
1291 chars
->keys
[index
] = copy(namestrt
);
1292 chars
->values
[index
] = (void *) (intpt
) val
;
1293 chars
->next
= index
+1;
1295 while ( isspace(*str
)) ++str
;
1296 if ( str
[0]=='d' && str
[1]=='e' && str
[2]=='f' )
1301 static char *rmbinary(char *line
) {
1304 for ( pt
=line
; *pt
; ++pt
) {
1305 if (( *pt
<' ' || *pt
>=0x7f ) && *pt
!='\n' ) {
1306 if ( strlen(pt
)>5 ) {
1322 static void sfnts2tempfile(struct fontparse
*fp
,FILE *in
,char *line
) {
1324 int instring
= false, firstnibble
=true, sofar
=0, nibble
;
1325 int complained
= false;
1328 fp
->sfnts
= tmpfile();
1330 /* first finish off anything in the current line */
1331 while ( (pt
=strpbrk(line
,"<]" ))!=NULL
) {
1336 for ( ++pt
; *pt
&& *pt
!='>'; ++pt
) {
1341 else if ( *pt
>='a' && *pt
<='f' )
1342 nibble
= *pt
-'a'+10;
1343 else if ( *pt
>='A' && *pt
<='F' )
1344 nibble
= *pt
-'A'+10;
1346 if ( !complained
) {
1347 LogError( _("Invalid hex digit in sfnts array\n") );
1353 if ( firstnibble
) {
1355 firstnibble
= false;
1357 putc(sofar
|nibble
,fp
->sfnts
);
1363 if ( ftell(fp
->sfnts
)&1 ) { /* Strings must be contain an even number of bytes */
1364 /* But may be padded with a trailing NUL */
1365 fseek(fp
->sfnts
,-1,SEEK_CUR
);
1373 while ( (ch
=getc(in
))!=EOF
) {
1378 if ( !instring
&& ch
=='<' ) {
1382 } else if ( !instring
) {
1383 if ( !complained
) {
1384 LogError( _("Invalid character outside of string in sfnts array\n") );
1387 } else if ( instring
&& ch
=='>' ) {
1388 if ( ftell(fp
->sfnts
)&1 ) { /* Strings must be contain an even number of bytes */
1389 /* But may be padded with a trailing NUL */
1390 fseek(fp
->sfnts
,-1,SEEK_CUR
);
1396 else if ( ch
>='a' && ch
<='f' )
1398 else if ( ch
>='A' && ch
<='F' )
1401 if ( !complained
) {
1402 LogError( _("Invalid hex digit in sfnts array\n") );
1407 if ( firstnibble
) {
1409 firstnibble
= false;
1411 putc(sofar
|nibble
,fp
->sfnts
);
1418 while ( ch
!=EOF
&& ch
!='\n' && ch
!='\r' )
1423 static void ParseSimpleEncoding(struct fontparse
*fp
,char *line
) {
1426 while ( *line
!='\0' && *line
!=']' ) {
1427 while ( isspace(*line
)) ++line
;
1435 while ( isspace(*line
)) ++line
;
1436 for ( pt
=tok
; !isspace(*line
) && *line
!='\0' && *line
!='/' && *line
!=']'; ) {
1437 if ( pt
<tok
+sizeof(tok
)-2 )
1443 if ( fp
->simple_enc_pos
<256 )
1444 fp
->fd
->encoding
[fp
->simple_enc_pos
++] = copy(tok
);
1447 fp
->simpleencoding
= false;
1448 fp
->inencoding
= false;
1452 static void parseline(struct fontparse
*fp
,char *line
,FILE *in
) {
1453 char buffer
[200], *pt
, *endtok
;
1455 while ( *line
==' ' || *line
=='\t' ) ++line
;
1456 if ( line
[0]=='%' && !fp
->multiline
)
1459 if ( fp
->simpleencoding
) {
1460 ParseSimpleEncoding(fp
,line
);
1462 } else if (( fp
->inencoding
&& strncmp(line
,"dup",3)==0 ) ||
1463 ( strncmp(line
,"dup ",4)==0 && isdigit(line
[4]) &&
1464 strstr(line
+strlen(line
)-6," put")!=NULL
&& strchr(line
,'/')!=NULL
)) {
1465 /* Fontographer's type3 fonts claim to be standard, but then aren't */
1466 fp
->fd
->encoding_name
= &custom
;
1467 /* Metamorphasis has multiple entries on a line */
1468 while ( strncmp(line
,"dup",3)==0 ) {
1470 int pos
= strtol(line
+3,&end
,10);
1472 while ( isspace( *line
)) ++line
;
1473 if ( *line
=='/' ) ++line
;
1474 for ( pt
= buffer
; !isspace(*line
); *pt
++ = *line
++ );
1476 if ( pos
>=0 && pos
<256 ) {
1477 free(fp
->fd
->encoding
[pos
]);
1478 fp
->fd
->encoding
[pos
] = copy(buffer
);
1480 while ( isspace(*line
)) ++line
;
1481 if ( strncmp(line
,"put",3)==0 ) line
+=3;
1482 while ( isspace(*line
)) ++line
;
1485 } else if ( fp
->inencoding
&& strstr(line
,"for")!=NULL
&& strstr(line
,"/.notdef")!=NULL
) {
1486 /* the T1 spec I've got doesn't allow for this, but I've seen it anyway*/
1487 /* 0 1 255 {1 index exch /.notdef put} for */
1488 /* 0 1 31 { 1 index exch /.notdef put } bind for */
1490 for ( i
=0; i
<256; ++i
)
1491 if ( fp
->fd
->encoding
[i
]==NULL
)
1492 fp
->fd
->encoding
[i
] = copy(".notdef");
1494 } else if ( fp
->inencoding
&& strstr(line
,"Encoding")!=NULL
&& strstr(line
,"put")!=NULL
) {
1495 /* Saw a type 3 font with lines like "Encoding 1 /_a0 put" */
1498 while ( isspace(*line
)) ++line
;
1499 if ( strncmp(line
,"Encoding ",9)==0 ) {
1501 pos
= strtol(line
,&end
,10);
1503 while ( isspace(*line
)) ++line
;
1506 for ( pt
= buffer
; !isspace(*line
); *pt
++ = *line
++ );
1508 if ( pos
>=0 && pos
<256 )
1509 fp
->fd
->encoding
[pos
] = copy(buffer
);
1513 } else if ( fp
->insubs
) {
1514 struct pschars
*subrs
= fp
->fd
->private->subrs
;
1515 while ( isspace(*line
)) ++line
;
1516 if ( strncmp(line
,"dup ",4)==0 ) {
1519 for ( line
+= 4; *line
==' '; ++line
);
1520 i
= strtol(line
,&ept
,10);
1523 else if ( i
<subrs
->cnt
) {
1524 findstring(fp
,subrs
,i
,NULL
,ept
);
1525 } else if ( !fp
->alreadycomplained
) {
1526 LogError( _("Index too big (must be <%d) \"%s"), subrs
->cnt
, rmbinary(line
));
1527 fp
->alreadycomplained
= true;
1529 } else if ( strncmp(line
, "readonly put", 12)==0 || strncmp(line
, "ND", 2)==0 || strncmp(line
, "|-", 2)==0 ) {
1532 } else if ( *line
=='\n' || *line
=='\0' ) {
1533 /* Ignore blank lines */;
1534 } else if ( !fp
->alreadycomplained
) {
1535 LogError( _("Didn't understand \"%s"), rmbinary(line
) );
1536 fp
->alreadycomplained
= true;
1538 } else if ( fp
->inchars
) {
1539 struct pschars
*chars
= fp
->fd
->chars
;
1540 while ( isspace(*line
)) ++line
;
1541 if ( strncmp(line
,"end",3)==0 )
1542 fp
->ignore
= fp
->inchars
= false;
1543 else if ( *line
=='\n' || *line
=='\0' )
1545 else if ( *line
!='/' || !(isalpha(line
[1]) || line
[1]=='.')) {
1546 LogError( _("No name for CharStrings dictionary \"%s"), rmbinary(line
) );
1547 fp
->alreadycomplained
= true;
1548 } else if ( fp
->ignore
) {
1550 } else if ( chars
->next
>=chars
->cnt
)
1551 LogError( _("Too many entries in CharStrings dictionary \"%s"), rmbinary(line
) );
1552 else if ( fp
->fd
->fonttype
==42 || fp
->fd
->fonttype
==11 || fp
->fd
->cidfonttype
==2 )
1553 findnumbers(fp
,chars
,line
);
1555 int i
= chars
->next
;
1556 char *namestrt
= ++line
;
1557 while ( isalnum(*line
) || *line
=='.' ) ++line
;
1559 findstring(fp
,chars
,i
,namestrt
,line
+1);
1566 while ( isspace(*line
)) ++line
;
1569 for ( endtok
=line
+1; !isspace(*endtok
) && *endtok
!='(' && *endtok
!='/' &&
1570 *endtok
!='{' && *endtok
!='[' && *endtok
!='\0'; ++endtok
);
1572 if ( strstr(line
,"/shareddict")!=NULL
&& strstr(line
,"where")!=NULL
) {
1573 fp
->infi
= fp
->inbb
= fp
->inmetrics
= fp
->inmetrics2
= false;
1574 fp
->inprivate
= fp
->inblendprivate
= fp
->inblendfi
= false;
1575 fp
->skipping_mbf
= true;
1579 if ( mycmp("Encoding",line
+1,endtok
)==0 && !fp
->doneencoding
) {
1580 if ( strstr(endtok
,"StandardEncoding")!=NULL
) {
1581 fp
->fd
->encoding_name
= FindOrMakeEncoding("AdobeStandard");
1582 setStdEnc(fp
->fd
->encoding
);
1583 } else if ( strstr(endtok
,"ISOLatin1Encoding")!=NULL
) {
1584 fp
->fd
->encoding_name
= FindOrMakeEncoding("ISO8859-1");
1585 setLatin1Enc(fp
->fd
->encoding
);
1587 fp
->fd
->encoding_name
= &custom
;
1590 if ( fp
->fd
->encoding_name
==NULL
)
1591 fp
->fd
->encoding_name
= &custom
;
1592 fp
->infi
= fp
->inprivate
= fp
->inbb
= fp
->inmetrics
= fp
->inmetrics2
= false;
1593 fp
->doneencoding
= true;
1594 while ( *endtok
==' ' || *endtok
=='\t' ) ++endtok
;
1595 if ( *endtok
=='[' ) { /* It's a literal array */
1596 fp
->simpleencoding
= true;
1597 fp
->simple_enc_pos
= 0;
1598 ParseSimpleEncoding(fp
,endtok
+1);
1600 } else if ( mycmp("BoundingBoxes",line
+1,endtok
)==0 ) {
1601 fp
->infi
= fp
->inprivate
= fp
->inencoding
= fp
->inmetrics
= fp
->inmetrics2
= false;
1603 } else if ( mycmp("Metrics",line
+1,endtok
)==0 ) {
1604 fp
->infi
= fp
->inprivate
= fp
->inbb
= fp
->inencoding
= fp
->inmetrics2
= false;
1605 fp
->inmetrics
= true;
1606 fp
->fd
->metrics
= gcalloc(1,sizeof(struct psdict
));
1607 fp
->fd
->metrics
->cnt
= strtol(endtok
,NULL
,10);
1608 fp
->fd
->metrics
->keys
= galloc(fp
->fd
->metrics
->cnt
*sizeof(char *));
1609 fp
->fd
->metrics
->values
= galloc(fp
->fd
->metrics
->cnt
*sizeof(char *));
1610 } else if ( strstr(line
,"/Private")!=NULL
&& strstr(line
,"/Blend")!=NULL
) {
1611 fp
->infi
= fp
->inbb
= fp
->inmetrics
= fp
->inmetrics2
= false;
1612 fp
->inprivate
= fp
->inblendprivate
= fp
->inblendfi
= false;
1613 fp
->inblendprivate
= 1;
1614 fp
->fd
->blendprivate
= gcalloc(1,sizeof(struct psdict
));
1615 InitDict(fp
->fd
->blendprivate
,line
);
1617 } else if ( strstr(line
,"/FontInfo")!=NULL
&& strstr(line
,"/Blend")!=NULL
) {
1618 fp
->infi
= fp
->inbb
= fp
->inmetrics
= fp
->inmetrics2
= false;
1619 fp
->inprivate
= fp
->inblendprivate
= fp
->inblendfi
= false;
1621 fp
->fd
->blendfontinfo
= gcalloc(1,sizeof(struct psdict
));
1622 InitDict(fp
->fd
->blendfontinfo
,line
);
1624 } else if ( fp
->infi
) {
1625 if ( fp
->multiline
) {
1626 ContinueValue(fp
,NULL
,line
);
1629 if ( endtok
==NULL
&& (strncmp(line
,"end", 3)==0 || strncmp(line
,">>",2)==0)) {
1632 } else if ( endtok
==NULL
)
1634 if ( mycmp("version",line
+1,endtok
)==0 ) {
1635 free(fp
->fd
->fontinfo
->version
);
1636 fp
->fd
->fontinfo
->version
= getstring(endtok
,in
);
1637 } else if ( mycmp("Notice",line
+1,endtok
)==0 ) {
1638 if ( fp
->fd
->fontinfo
->notice
!=NULL
)
1639 free(fp
->fd
->fontinfo
->notice
);
1640 fp
->fd
->fontinfo
->notice
= getstring(endtok
,in
);
1641 } else if ( mycmp("Copyright",line
+1,endtok
)==0 ) { /* cff spec allows for copyright and notice */
1642 if ( fp
->fd
->fontinfo
->notice
!=NULL
)
1643 free(fp
->fd
->fontinfo
->notice
);
1644 fp
->fd
->fontinfo
->notice
= getstring(endtok
,in
);
1645 } else if ( mycmp("FullName",line
+1,endtok
)==0 ) {
1646 if ( fp
->fd
->fontinfo
->fullname
==NULL
)
1647 fp
->fd
->fontinfo
->fullname
= getstring(endtok
,in
);
1649 free(getstring(endtok
,in
));
1650 } else if ( mycmp("FamilyName",line
+1,endtok
)==0 ) {
1651 free( fp
->fd
->fontinfo
->familyname
);
1652 fp
->fd
->fontinfo
->familyname
= getstring(endtok
,in
);
1653 } else if ( mycmp("Weight",line
+1,endtok
)==0 ) {
1654 free( fp
->fd
->fontinfo
->weight
);
1655 fp
->fd
->fontinfo
->weight
= getstring(endtok
,in
);
1656 } else if ( mycmp("ItalicAngle",line
+1,endtok
)==0 )
1657 fp
->fd
->fontinfo
->italicangle
= strtod(endtok
,NULL
);
1658 else if ( mycmp("UnderlinePosition",line
+1,endtok
)==0 )
1659 fp
->fd
->fontinfo
->underlineposition
= strtod(endtok
,NULL
);
1660 else if ( mycmp("UnderlineThickness",line
+1,endtok
)==0 )
1661 fp
->fd
->fontinfo
->underlinethickness
= strtod(endtok
,NULL
);
1662 else if ( mycmp("isFixedPitch",line
+1,endtok
)==0 )
1663 fp
->fd
->fontinfo
->isfixedpitch
= getbool(endtok
);
1664 else if ( mycmp("em",line
+1,endtok
)==0 )
1665 fp
->fd
->fontinfo
->em
= strtol(endtok
,NULL
,10);
1666 else if ( mycmp("ascent",line
+1,endtok
)==0 )
1667 fp
->fd
->fontinfo
->ascent
= strtol(endtok
,NULL
,10);
1668 else if ( mycmp("descent",line
+1,endtok
)==0 )
1669 fp
->fd
->fontinfo
->descent
= strtol(endtok
,NULL
,10);
1670 else if ( mycmp("FSType",line
+1,endtok
)==0 )
1671 fp
->fd
->fontinfo
->fstype
= strtol(endtok
,NULL
,10);
1672 else if ( mycmp("BlendDesignPositions",line
+1,endtok
)==0 ) {
1673 fp
->pending_parse
= &fp
->fd
->fontinfo
->blenddesignpositions
;
1674 AddValue(fp
,NULL
,line
,endtok
);
1675 } else if ( mycmp("BlendDesignMap",line
+1,endtok
)==0 ) {
1676 fp
->pending_parse
= &fp
->fd
->fontinfo
->blenddesignmap
;
1677 AddValue(fp
,NULL
,line
,endtok
);
1678 } else if ( mycmp("BlendAxisTypes",line
+1,endtok
)==0 ) {
1679 fp
->pending_parse
= &fp
->fd
->fontinfo
->blendaxistypes
;
1680 AddValue(fp
,NULL
,line
,endtok
);
1681 } else if ( !fp
->alreadycomplained
) {
1682 LogError( _("Didn't understand \"%s"), rmbinary(line
) );
1683 fp
->alreadycomplained
= true;
1685 } else if ( fp
->inblend
) {
1686 if ( endtok
==NULL
) {
1687 if ( *line
!='/' && strstr(line
,"end")!=NULL
)
1688 fp
->inblend
= false;
1691 /* Ignore anything in the blend dict defn */
1692 } else if ( fp
->inblendprivate
|| fp
->inblendfi
) {
1693 struct psdict
*subdict
= fp
->inblendfi
? fp
->fd
->blendfontinfo
: fp
->fd
->blendprivate
;
1694 if ( fp
->multiline
) {
1695 ContinueValue(fp
,subdict
,line
);
1697 } else if ( endtok
==NULL
) {
1698 if ( *line
!='/' && strstr(line
,"end")!=NULL
) {
1699 fp
->inblendprivate
= fp
->inblendfi
= false;
1700 fp
->inprivate
= true;
1704 AddValue(fp
,subdict
,line
,endtok
);
1705 } else if ( fp
->inprivate
) {
1706 if ( strstr(line
,"/CharStrings")!=NULL
&& strstr(line
,"dict")!=NULL
) {
1707 if ( fp
->fd
->chars
->next
==0 ) {
1708 InitChars(fp
->fd
->chars
,line
);
1712 LogError( _("Ignoring duplicate /CharStrings entry\n") );
1717 } else if ( strstr(line
,"/Subrs")!=NULL
) {
1718 if ( fp
->fd
->private->subrs
->next
>0 ) {
1720 LogError( _("Ignoring duplicate /Subrs entry\n") );
1722 InitChars(fp
->fd
->private->subrs
,line
);
1728 } else if ( fp
->multiline
) {
1729 ContinueValue(fp
,fp
->fd
->private->private,line
);
1732 if ( endtok
==NULL
) {
1734 if ( *pt
!='/' ) while ( (pt
=strstr(pt
,"end"))!=NULL
) {
1735 if ( fp
->inchars
) fp
->inchars
= false;
1736 else fp
->inprivate
= false;
1741 if ( mycmp("ND",line
+1,endtok
)==0 || mycmp("|-",line
+1,endtok
)==0 ||
1742 mycmp("NP",line
+1,endtok
)==0 || mycmp("|",line
+1,endtok
)==0 ||
1743 mycmp("RD",line
+1,endtok
)==0 || mycmp("-|",line
+1,endtok
)==0 ||
1744 mycmp("password",line
+1,endtok
)==0 ||
1745 mycmp("MinFeature",line
+1,endtok
)==0 )
1746 /* These conveigh no information, but are required */;
1747 else if ( mycmp("UniqueID",line
+1,endtok
)==0 ) {
1748 if ( fp
->fd
->uniqueid
==0 )
1749 fp
->fd
->uniqueid
= strtol(endtok
,NULL
,10);
1751 if ( mycmp("lenIV",line
+1,endtok
)==0 )
1752 fp
->fd
->private->leniv
= strtol(endtok
,NULL
,10); /* We need this value */
1753 AddValue(fp
,fp
->fd
->private->private,line
,endtok
);
1755 } else if ( fp
->incidsysteminfo
) {
1756 if ( endtok
==NULL
&& strncmp(line
,"end", 3)==0 ) {
1757 fp
->incidsysteminfo
=0;
1759 } else if ( endtok
==NULL
)
1761 if ( mycmp("Registry",line
+1,endtok
)==0 ) {
1762 free( fp
->fd
->registry
);
1763 fp
->fd
->registry
= getstring(endtok
,in
);
1764 } else if ( mycmp("Ordering",line
+1,endtok
)==0 ) {
1765 free( fp
->fd
->ordering
);
1766 fp
->fd
->ordering
= getstring(endtok
,in
);
1767 } else if ( mycmp("Supplement",line
+1,endtok
)==0 ) /* cff spec allows for copyright and notice */
1768 fp
->fd
->supplement
= strtol(endtok
,NULL
,0);
1770 if ( strstr(line
,"/Private")!=NULL
&& (strstr(line
,"dict")!=NULL
|| strstr(line
,"<<")!=NULL
)) {
1771 fp
->infi
= fp
->inbb
= fp
->inmetrics
= fp
->inmetrics2
= false;
1772 fp
->inprivate
= fp
->inblendprivate
= fp
->inblendfi
= false;
1773 if ( strstr(line
,"/Blend")!=NULL
) {
1774 fp
->inblendprivate
= 1;
1775 fp
->fd
->blendprivate
= gcalloc(1,sizeof(struct psdict
));
1776 InitDict(fp
->fd
->blendprivate
,line
);
1779 InitDict(fp
->fd
->private->private,line
);
1782 } else if ( strstr(line
,"/FontInfo")!=NULL
&& (strstr(line
,"dict")!=NULL
|| strstr(line
,"<<")!=NULL
)) {
1783 fp
->inprivate
= fp
->inbb
= fp
->inmetrics
= fp
->inmetrics2
= false;
1784 fp
->infi
= fp
->inblendprivate
= fp
->inblendfi
= false;
1785 if ( strstr(line
,"/Blend")!=NULL
) {
1787 fp
->fd
->blendfontinfo
= gcalloc(1,sizeof(struct psdict
));
1788 InitDict(fp
->fd
->blendfontinfo
,line
);
1793 } else if ( strstr(line
,"/Blend")!=NULL
&& strstr(line
,"dict")!=NULL
) {
1794 fp
->inprivate
= fp
->inbb
= fp
->inmetrics
= fp
->inmetrics2
= false;
1795 fp
->infi
= fp
->inblendprivate
= fp
->inblendfi
= false;
1798 } else if ( strstr(line
,"/sfnts")!=NULL
&& strstr(line
,"[")!=NULL
) {
1799 sfnts2tempfile(fp
,in
,line
);
1801 } else if ( strstr(line
,"/CharStrings")!=NULL
&& strstr(line
,"dict")!=NULL
1802 && fp
->fd
->fonttype
!=3 ) {
1803 if ( fp
->fd
->chars
->next
==0 ) {
1804 InitChars(fp
->fd
->chars
,line
);
1808 LogError( _("Ignoring duplicate /CharStrings entry\n") );
1812 fp
->infi
= fp
->inprivate
= fp
->inbb
= fp
->inmetrics
= fp
->inmetrics2
= false;
1813 fp
->inblendprivate
= fp
->inblendfi
= false;
1815 } else if ( mycmp("/CharProcs",line
,endtok
)==0 ) {
1816 InitCharProcs(fp
->fd
->charprocs
,line
);
1817 fp
->infi
= fp
->inprivate
= fp
->inbb
= fp
->inmetrics
= fp
->inmetrics2
= false;
1820 } else if ( strstr(line
,"/CIDSystemInfo")!=NULL
) {
1821 fp
->incidsysteminfo
= 1;
1823 } else if ( fp
->inmetrics
) {
1825 AddValue(fp
,fp
->fd
->metrics
,line
,endtok
);
1827 } else if ( fp
->inbb
) {
1832 if ( fp
->multiline
) {
1833 ContinueValue(fp
,NULL
,line
);
1837 if ( endtok
==NULL
) {
1838 if ( fp
->skipping_mbf
)
1840 else if ( fp
->fdindex
!=-1 && strstr(line
,"end")!=NULL
) {
1841 if ( ++fp
->fdindex
>=fp
->mainfd
->fdcnt
)
1842 fp
->fd
= fp
->mainfd
;
1844 fp
->fd
= fp
->mainfd
->fds
[fp
->fdindex
];
1848 if ( mycmp("FontName",line
+1,endtok
)==0 ) {
1849 if ( fp
->fd
->fontname
==NULL
)
1850 fp
->fd
->fontname
= gettoken(endtok
);
1852 free(gettoken(endtok
)); /* skip it */
1853 } else if ( mycmp("PaintType",line
+1,endtok
)==0 )
1854 fp
->fd
->painttype
= strtol(endtok
,NULL
,10);
1855 else if ( mycmp("FontType",line
+1,endtok
)==0 )
1856 fp
->fd
->fonttype
= strtol(endtok
,NULL
,10);
1857 else if ( mycmp("FontMatrix",line
+1,endtok
)==0 ) {
1858 if ( fp
->fd
->fontmatrix
[0]==0 )
1859 fillrealarray(fp
->fd
->fontmatrix
,endtok
,6);
1862 fillrealarray(temp
,endtok
,6);
1864 } else if ( mycmp("LanguageLevel",line
+1,endtok
)==0 )
1865 fp
->fd
->languagelevel
= strtol(endtok
,NULL
,10);
1866 else if ( mycmp("WMode",line
+1,endtok
)==0 )
1867 fp
->fd
->wmode
= strtol(endtok
,NULL
,10);
1868 else if ( mycmp("FontBBox",line
+1,endtok
)==0 )
1869 fillrealarray(fp
->fd
->fontbb
,endtok
,4);
1870 else if ( mycmp("UniqueID",line
+1,endtok
)==0 ) {
1871 if ( fp
->fd
->uniqueid
==0 )
1872 fp
->fd
->uniqueid
= strtol(endtok
,NULL
,10);
1873 } else if ( mycmp("UniqueId",line
+1,endtok
)==0 ) {
1874 LogError(_("This font contains a \"UniqueId\" variable, but the correct name for it is\n\t\"UniqueID\" (postscript is case concious)\n") );
1875 if ( fp
->fd
->uniqueid
==0 )
1876 fp
->fd
->uniqueid
= strtol(endtok
,NULL
,10);
1877 } else if ( mycmp("XUID",line
+1,endtok
)==0 ) {
1878 if ( fp
->fd
->xuid
[0]==0 )
1879 fillintarray(fp
->fd
->xuid
,endtok
,20);
1880 } else if ( mycmp("StrokeWidth",line
+1,endtok
)==0 )
1881 fp
->fd
->strokewidth
= strtod(endtok
,NULL
);
1882 else if ( mycmp("WeightVector",line
+1,endtok
)==0 ) {
1883 if ( fp
->fd
->weightvector
==NULL
) {
1884 fp
->pending_parse
= &fp
->fd
->weightvector
;
1885 AddValue(fp
,NULL
,line
,endtok
);
1887 } else if ( mycmp("$Blend",line
+1,endtok
)==0 ) {
1888 fp
->pending_parse
= &fp
->fd
->blendfunc
;
1889 AddValue(fp
,NULL
,line
,endtok
);
1890 } else if ( strstr( line
,"/NormalizeDesignVector" )!=NULL
) {
1891 fp
->pending_parse
= &fp
->fd
->ndv
;
1892 AddValue(fp
,NULL
,line
,endtok
);
1893 } else if ( strstr( line
,"/ConvertDesignVector" )!=NULL
) {
1894 fp
->pending_parse
= &fp
->fd
->cdv
;
1895 AddValue(fp
,NULL
,line
,endtok
);
1896 } else if ( mycmp("BuildChar",line
+1,endtok
)==0 )
1898 else if ( mycmp("BuildGlyph",line
+1,endtok
)==0 )
1900 else if ( mycmp("CIDFontName",line
+1,endtok
)==0 ) {
1901 free( fp
->fd
->cidfontname
);
1902 fp
->fd
->cidfontname
= gettoken(endtok
);
1903 } else if ( mycmp("CIDFontVersion",line
+1,endtok
)==0 ) {
1904 fp
->fd
->cidversion
= strtod(endtok
,NULL
);
1906 if ( fp
->fd
->fontinfo
->version
==NULL
) {
1908 sprintf(temp
,"%f", fp
->fd
->cidversion
);
1909 fp
->fd
->fontinfo
->version
= copy(temp
);
1912 } else if ( mycmp("CIDFontType",line
+1,endtok
)==0 )
1913 fp
->fd
->cidfonttype
= strtol(endtok
,NULL
,10);
1914 else if ( mycmp("UIDBase",line
+1,endtok
)==0 )
1915 fp
->fd
->uniqueid
= strtol(endtok
,NULL
,10);
1916 else if ( mycmp("CIDMapOffset",line
+1,endtok
)==0 )
1917 fp
->fd
->mapoffset
= strtol(endtok
,NULL
,10);
1918 else if ( mycmp("FDBytes",line
+1,endtok
)==0 )
1919 fp
->fd
->fdbytes
= strtol(endtok
,NULL
,10);
1920 else if ( mycmp("GDBytes",line
+1,endtok
)==0 )
1921 fp
->fd
->gdbytes
= strtol(endtok
,NULL
,10);
1922 else if ( mycmp("CIDCount",line
+1,endtok
)==0 )
1923 fp
->fd
->cidcnt
= strtol(endtok
,NULL
,10);
1924 else if ( mycmp("FDArray",line
+1,endtok
)==0 ) { int i
;
1925 fp
->mainfd
= fp
->fd
;
1926 fp
->fd
->fdcnt
= strtol(endtok
,NULL
,10);
1927 fp
->fd
->fds
= gcalloc(fp
->fd
->fdcnt
,sizeof(struct fontdict
*));
1928 for ( i
=0; i
<fp
->fd
->fdcnt
; ++i
)
1929 fp
->fd
->fds
[i
] = MakeEmptyFont();
1931 fp
->fd
= fp
->fd
->fds
[0];
1932 } else if ( mycmp("FontSetInit",line
+1,endtok
)==0 ) {
1935 } else if ( mycmp("CIDInit",line
+1,endtok
)==0 ) {
1938 } else if ( fp
->skipping_mbf
) { /* Skip over the makeblendedfont defn in a multimaster font */
1940 } else if ( !fp
->alreadycomplained
) {
1941 LogError( _("Didn't understand \"%s"), rmbinary(line
) );
1942 fp
->alreadycomplained
= true;
1947 static void addinfo(struct fontparse
*fp
,char *line
,char *tok
,char *binstart
,int binlen
,FILE *in
) {
1950 decodestr((unsigned char *) binstart
,binlen
);
1951 binstart
+= fp
->fd
->private->leniv
;
1952 binlen
-= fp
->fd
->private->leniv
;
1954 LogError( _("Bad CharString. Does not include lenIV bytes.\n") );
1960 struct pschars
*chars
= /*fp->insubs ?*/ fp
->fd
->private->subrs
/*: fp->fd->private->othersubrs*/;
1961 while ( isspace(*line
)) ++line
;
1962 if ( strncmp(line
,"dup ",4)==0 ) {
1963 int i
= strtol(line
+4,NULL
,10);
1966 else if ( i
<chars
->cnt
) {
1967 if ( chars
->values
[i
]!=NULL
)
1968 LogError( _("Duplicate definition of subroutine %d\n"), i
);
1969 chars
->lens
[i
] = binlen
;
1970 chars
->values
[i
] = galloc(binlen
);
1971 memcpy(chars
->values
[i
],binstart
,binlen
);
1972 if ( i
>=chars
->next
) chars
->next
= i
+1;
1973 } else if ( !fp
->alreadycomplained
) {
1974 LogError( _("Index too big (must be <%d) \"%s"), chars
->cnt
, rmbinary(line
));
1975 fp
->alreadycomplained
= true;
1977 } else if ( !fp
->alreadycomplained
) {
1978 LogError( _("Didn't understand \"%s"), rmbinary(line
) );
1979 fp
->alreadycomplained
= true;
1981 } else if ( fp
->inchars
) {
1982 struct pschars
*chars
= fp
->fd
->chars
;
1984 LogError( _("No name for CharStrings dictionary \"%s"), rmbinary(line
) );
1985 else if ( fp
->ignore
)
1987 else if ( chars
->next
>=chars
->cnt
)
1988 LogError( _("Too many entries in CharStrings dictionary \"%s"), rmbinary(line
) );
1990 int i
= chars
->next
;
1991 chars
->lens
[i
] = binlen
;
1992 chars
->keys
[i
] = copy(tok
);
1993 chars
->values
[i
] = galloc(binlen
);
1994 memcpy(chars
->values
[i
],binstart
,binlen
);
1998 } else if ( !fp
->alreadycomplained
) {
1999 /* Special hacks for known badly formatted fonts */
2000 if ( strstr(line
,"/CharStrings")!=NULL
) {
2001 for ( pt
=line
; *pt
!='/'; ++pt
);
2002 pt
= strchr(pt
+1,'/');
2005 parseline(fp
,line
,in
);
2012 } else if ( strstr(line
,"/Subrs")!=NULL
) {
2013 pt
= strstr(line
,"dup");
2016 parseline(fp
,line
,in
);
2024 LogError( _("Shouldn't be in addinfo \"%s"), rmbinary(line
) );
2025 fp
->alreadycomplained
= true;
2029 /* In the book the token which starts a character description is always RD but*/
2030 /* it's just the name of a subroutine which is defined in the private diction*/
2031 /* and it could be anything. in one case it was "-|" (hyphen bar) so we can't*/
2032 /* just look for RD we must be a bit smarter and figure out what the token is*/
2033 /* (oh. I see now. it's allowed to be either one "RD" or "-|", but nothing else*/
2035 /* It's defined as {string currentfile exch readstring pop} so look for that */
2036 /* Except that in gsf files we've also got "/-!{string currentfile exch readhexstring pop} readonly def" */
2037 /* NOTE: readhexstring!!! */
2038 /* And in files generated by GNU fontutils */
2039 static int glorpline(struct fontparse
*fp
, FILE *temp
, char *rdtok
) {
2040 static char *buffer
=NULL
, *end
;
2041 char *pt
, *binstart
;
2044 int innum
, val
=0, inbinary
, cnt
=0, inr
, wasspace
, nownum
, nowr
, nowspace
, sptok
;
2045 char *rdline
= "{string currentfile exch readstring pop}", *rpt
;
2046 char *rdline2
= "{string currentfile exch readhexstring pop}";
2047 char *tokpt
= NULL
, *rdpt
;
2050 int wasminus
=false, isminus
, nibble
=0, firstnibble
=true, inhex
;
2051 int willbehex
= false;
2058 if ( buffer
==NULL
) {
2059 buffer
= galloc(3000);
2062 innum
= inr
= 0; wasspace
= 0; inbinary
= 0; rpt
= NULL
; rdpt
= NULL
;
2064 pt
= buffer
; binstart
=NULL
; binlen
= 0; intok
=0; sptok
=0; first
=1;
2066 while ( (ch
=getc(temp
))!=EOF
) {
2069 int len
= (end
-buffer
)+2000;
2070 buffer
= grealloc(buffer
,len
);
2072 pt
= buffer
+(pt
-old
);
2073 if ( binstart
!=NULL
)
2074 binstart
= buffer
+(binstart
-old
);
2077 isminus
= ch
=='-' && wasspace
;
2078 nownum
= nowspace
= nowr
= 0;
2079 if ( rpt
!=NULL
&& ch
!=*rpt
&& ch
=='h' && rpt
-rdline
>25 && rpt
-rdline
<30 &&
2080 rdline2
[rpt
-rdline
]=='h' ) {
2081 rpt
= rdline2
+ (rpt
-rdline
);
2087 } else if ( inhex
) {
2088 if ( ishexdigit(ch
)) {
2090 if ( isdigit(ch
)) h
= ch
-'0';
2091 else if ( ch
>='a' && ch
<='f' ) h
= ch
-'a'+10;
2093 if ( firstnibble
) {
2097 pt
[-1] = (nibble
<<4)|h
;
2099 inbinary
= inhex
= 0;
2101 firstnibble
= !firstnibble
;
2104 /* skip everything not hex */
2106 } else if ( ch
=='/' ) {
2109 } else if ( intok
&& !isspace(ch
) && ch
!='{' && ch
!='[' ) {
2111 } else if ( (intok
||sptok
) && (ch
=='{' || ch
=='[')) {
2115 } else if ( intok
) {
2119 } else if ( sptok
&& isspace(ch
)) {
2121 if ( ch
=='\n' || ch
=='\r' )
2123 } else if ( sptok
&& !isdigit(ch
))
2125 else if ( rpt
!=NULL
&& ch
==*rpt
) {
2126 if ( *++rpt
=='\0' ) {
2127 /* it matched the character definition string so this is the */
2128 /* token we want to search for */
2129 strcpy(rdtok
,temptok
);
2130 fp
->useshexstrings
= willbehex
;
2133 } else if ( rpt
!=NULL
&& ch
==' ' ) {
2134 /* Extra spaces are ok */
2135 } else if ( rpt
!=NULL
) {
2138 } else if ( isdigit(ch
)) {
2142 val
= 10*val
+ ch
-'0';
2145 } else if ( isspace(ch
)) {
2147 if ( ch
=='\n' || ch
=='\r' )
2149 } else if ( wasspace
&& ch
==*rdtok
) {
2151 fp
->useshexstrings
= willbehex
;
2153 } else if ( wasspace
&& ch
=='-' ) { /* fonts produced by type1fix seem to define both "RD" and "-|" which confused me. so just respond to either */
2155 fp
->useshexstrings
= false;
2157 } else if ( wasspace
&& ch
=='R' ) { /* fonts produced by type1fix seem to define both "RD" and "-|" which confused me. so just respond to either */
2159 fp
->useshexstrings
= false;
2161 } else if ( inr
&& ch
==*rdpt
) {
2162 if ( *++rdpt
=='\0' ) {
2165 if ( isspace(ch
) && val
!=0 ) {
2166 inhex
= fp
->useshexstrings
;
2167 inbinary
= !fp
->useshexstrings
;
2175 } else if ( wasminus
&& ch
=='!' ) {
2178 if ( isspace(ch
) && val
!=0 ) {
2186 innum
= nownum
; wasspace
= nowspace
; inr
= nowr
;
2191 if ( binstart
==NULL
) {
2192 parseline(fp
,buffer
,temp
);
2194 addinfo(fp
,buffer
,temptok
,binstart
,binlen
,temp
);
2199 static int nrandombytes
[4];
2200 #define EODMARKLEN 16
2202 #define bgetc(extra,in) (*(extra)=='\0' ? getc(in) : (unsigned char ) *(extra)++ )
2204 static void decrypteexec(FILE *in
,FILE *temp
, int hassectionheads
,char *extra
) {
2205 int ch1
, ch2
, ch3
, ch4
, binary
;
2207 unsigned char zeros
[EODMARKLEN
+6+1];
2208 int sect_len
=0x7fffffff;
2210 if ( extra
==(void *) 5 ) extra
= "";
2212 /* The PLRM defines white space to include form-feed and null. The t1_spec*/
2213 /* does not. The t1_spec wins here. Someone gave me a font which began */
2214 /* with a formfeed and that was part of the encrypted body */
2215 while ( (ch1
=bgetc(extra
,in
))!=EOF
&& (ch1
==' ' || ch1
=='\t' || ch1
=='\n' || ch1
=='\r'));
2216 if ( ch1
==0200 && hassectionheads
) {
2217 /* skip the 6 byte section header in pfb files that follows eexec */
2218 ch1
= bgetc(extra
,in
);
2219 sect_len
= bgetc(extra
,in
);
2220 sect_len
|= bgetc(extra
,in
)<<8;
2221 sect_len
|= bgetc(extra
,in
)<<16;
2222 sect_len
|= bgetc(extra
,in
)<<24;
2224 ch1
= bgetc(extra
,in
);
2226 ch2
= bgetc(extra
,in
); ch3
= bgetc(extra
,in
); ch4
= bgetc(extra
,in
);
2228 if ( ch1
<'0' || (ch1
>'9' && ch1
<'A') || ( ch1
>'F' && ch1
<'a') || (ch1
>'f') ||
2229 ch2
<'0' || (ch2
>'9' && ch2
<'A') || (ch2
>'F' && ch2
<'a') || (ch2
>'f') ||
2230 ch3
<'0' || (ch3
>'9' && ch3
<'A') || (ch3
>'F' && ch3
<'a') || (ch3
>'f') ||
2231 ch4
<'0' || (ch4
>'9' && ch4
<'A') || (ch4
>'F' && ch4
<'a') || (ch4
>'f') )
2233 if ( ch1
==EOF
|| ch2
==EOF
|| ch3
==EOF
|| ch4
==EOF
) {
2239 nrandombytes
[0] = decode(ch1
);
2240 nrandombytes
[1] = decode(ch2
);
2241 nrandombytes
[2] = decode(ch3
);
2242 nrandombytes
[3] = decode(ch4
);
2244 while (( ch1
=bgetc(extra
,in
))!=EOF
) {
2246 if ( hassectionheads
) {
2247 if ( sect_len
==0 && ch1
==0200 ) {
2248 ch1
= bgetc(extra
,in
);
2249 sect_len
= bgetc(extra
,in
);
2250 sect_len
|= bgetc(extra
,in
)<<8;
2251 sect_len
|= bgetc(extra
,in
)<<16;
2252 sect_len
|= bgetc(extra
,in
)<<24;
2257 dumpzeros(temp
,zeros
,zcnt
);
2259 putc(decode(ch1
),temp
);
2262 if ( ch1
=='0' ) ++zcnt
; else {dumpzeros(temp
,zeros
,zcnt
); zcnt
= 0; }
2263 if ( zcnt
>EODMARKLEN
)
2266 putc(decode(ch1
),temp
);
2268 zeros
[zcnt
-1] = decode(ch1
);
2272 nrandombytes
[0] = decode(hex(ch1
,ch2
));
2273 nrandombytes
[1] = decode(hex(ch3
,ch4
));
2274 ch1
= bgetc(extra
,in
); ch2
= bgetc(extra
,in
); ch3
= bgetc(extra
,in
); ch4
= bgetc(extra
,in
);
2275 nrandombytes
[2] = decode(hex(ch1
,ch2
));
2276 nrandombytes
[3] = decode(hex(ch3
,ch4
));
2278 while (( ch1
=bgetc(extra
,in
))!=EOF
) {
2279 while ( ch1
!=EOF
&& isspace(ch1
)) ch1
= bgetc(extra
,in
);
2280 while ( (ch2
=bgetc(extra
,in
))!=EOF
&& isspace(ch2
));
2281 if ( ch1
=='0' && ch2
=='0' ) ++zcnt
; else { dumpzeros(temp
,zeros
,zcnt
); zcnt
= 0;}
2282 if ( zcnt
>EODMARKLEN
)
2285 putc(decode(hex(ch1
,ch2
)),temp
);
2287 zeros
[zcnt
-1] = decode(hex(ch1
,ch2
));
2290 while (( ch1
=bgetc(extra
,in
))=='0' || isspace(ch1
) );
2291 if ( ch1
!=EOF
) ungetc(ch1
,in
);
2294 static void decryptagain(struct fontparse
*fp
,FILE *temp
,char *rdtok
) {
2295 while ( glorpline(fp
,temp
,rdtok
));
2298 static void parsetype3(struct fontparse
*fp
,FILE *in
) {
2299 PSFontInterpretPS(in
,fp
->fd
->charprocs
,fp
->fd
->encoding
);
2302 static unsigned char *readt1str(FILE *temp
,int offset
,int len
,int leniv
) {
2304 unsigned char *str
, *pt
;
2305 unsigned short r
= 4330;
2306 unsigned char plain
, cypher
;
2307 /* The CID spec doesn't mention this, but the type 1 strings are all */
2308 /* eexec encrupted (with the nested encryption). Remember leniv varies */
2309 /* from fd to fd (potentially) */
2310 /* I'm told (by Ian Kemmish) that leniv==-1 => no eexec encryption */
2312 fseek(temp
,offset
,SEEK_SET
);
2314 str
= pt
= galloc(len
+1);
2315 for ( i
=0 ; i
<len
; ++i
)
2318 for ( i
=0; i
<leniv
; ++i
) {
2319 cypher
= getc(temp
);
2320 plain
= ( cypher
^ (r
>>8));
2321 r
= (cypher
+ r
) * c1
+ c2
;
2323 str
= pt
= galloc(len
-leniv
+1);
2324 for (; i
<len
; ++i
) {
2325 cypher
= getc(temp
);
2326 plain
= ( cypher
^ (r
>>8));
2327 r
= (cypher
+ r
) * c1
+ c2
;
2335 static void figurecids(struct fontparse
*fp
,FILE *temp
) {
2336 struct fontdict
*fd
= fp
->mainfd
;
2339 int cidcnt
= fd
->cidcnt
;
2341 /* Some cid formats don't have any of these */
2343 fd
->cidstrs
= galloc(cidcnt
*sizeof(uint8
*));
2344 fd
->cidlens
= galloc(cidcnt
*sizeof(int16
));
2345 fd
->cidfds
= galloc((cidcnt
+1)*sizeof(int16
));
2346 offsets
= galloc((cidcnt
+1)*sizeof(int));
2347 ff_progress_change_total(cidcnt
);
2349 fseek(temp
,fd
->mapoffset
,SEEK_SET
);
2350 for ( i
=0; i
<=fd
->cidcnt
; ++i
) {
2351 for ( j
=val
=0; j
<fd
->fdbytes
; ++j
)
2352 val
= (val
<<8) + getc(temp
);
2353 if ( val
>= fd
->fdcnt
&& val
!=255 ) { /* 255 is a special mark */
2354 LogError( _("Invalid FD (%d) assigned to CID %d.\n"), val
, i
);
2357 fd
->cidfds
[i
] = val
;
2358 for ( j
=val
=0; j
<fd
->gdbytes
; ++j
)
2359 val
= (val
<<8) + getc(temp
);
2362 fd
->cidlens
[i
-1] = offsets
[i
]-offsets
[i
-1];
2363 if ( fd
->cidlens
[i
-1]<0 ) {
2364 LogError( _("Bad CID offset for CID %d\n"), i
-1 );
2365 fd
->cidlens
[i
-1] = 0;
2370 for ( i
=0; i
<fd
->cidcnt
; ++i
) {
2371 if ( fd
->cidlens
[i
]== 0 )
2372 fd
->cidstrs
[i
] = NULL
;
2374 fd
->cidstrs
[i
] = readt1str(temp
,offsets
[i
],fd
->cidlens
[i
],
2375 fd
->fds
[fd
->cidfds
[i
]]->private->leniv
);
2376 fd
->cidlens
[i
] -= fd
->fds
[fd
->cidfds
[i
]]->private->leniv
;
2382 for ( k
=0; k
<fd
->fdcnt
; ++k
) {
2383 struct private *private = fd
->fds
[k
]->private;
2384 char *ssubroff
= PSDictHasEntry(private->private,"SubrMapOffset");
2385 char *ssdbytes
= PSDictHasEntry(private->private,"SDBytes");
2386 char *ssubrcnt
= PSDictHasEntry(private->private,"SubrCount");
2387 int subroff
, sdbytes
, subrcnt
;
2389 if ( ssubroff
!=NULL
&& ssdbytes
!=NULL
&& ssubrcnt
!=NULL
&&
2390 (subroff
=strtol(ssubroff
,NULL
,10))>=0 &&
2391 (sdbytes
=strtol(ssdbytes
,NULL
,10))>0 &&
2392 (subrcnt
=strtol(ssubrcnt
,NULL
,10))>0 ) {
2393 private->subrs
->cnt
= subrcnt
;
2394 private->subrs
->values
= gcalloc(subrcnt
,sizeof(char *));
2395 private->subrs
->lens
= gcalloc(subrcnt
,sizeof(int));
2396 leniv
= private->leniv
;
2397 offsets
= galloc((subrcnt
+1)*sizeof(int));
2398 fseek(temp
,subroff
,SEEK_SET
);
2399 for ( i
=0; i
<=subrcnt
; ++i
) {
2400 for ( j
=val
=0; j
<sdbytes
; ++j
)
2401 val
= (val
<<8) + getc(temp
);
2404 private->subrs
->lens
[i
-1] = offsets
[i
]-offsets
[i
-1];
2406 for ( i
=0; i
<subrcnt
; ++i
) {
2407 private->subrs
->values
[i
] = readt1str(temp
,offsets
[i
],
2408 private->subrs
->lens
[i
],leniv
);
2410 private->subrs
->next
= i
;
2413 PSDictRemoveEntry(private->private,"SubrMapOffset");
2414 PSDictRemoveEntry(private->private,"SDBytes");
2415 PSDictRemoveEntry(private->private,"SubrCount");
2419 static void dodata( struct fontparse
*fp
, FILE *in
, FILE *temp
) {
2420 int binary
, cnt
, len
;
2423 char fontsetname
[256];
2425 while ( (ch
=getc(in
))!='(' && ch
!='/' && ch
!=EOF
);
2427 /* There appears to be no provision for a hex encoding here */
2428 /* Why can't they use the same format for routines with the same name? */
2430 for ( pt
=fontsetname
; (ch
=getc(in
))!=' ' && ch
!=EOF
; )
2431 if ( pt
<fontsetname
+sizeof(fontsetname
)-1 )
2435 if ( (ch
=getc(in
))=='B' || ch
=='b' ) binary
= true;
2436 else if ( ch
=='H' || ch
=='h' ) binary
= false;
2438 binary
= true; /* Who knows? */
2439 LogError( _("Failed to parse the StartData command properly\n") );
2441 fontsetname
[0] = '\0';
2442 while ( (ch
=getc(in
))!=')' && ch
!=EOF
);
2444 if ( fscanf( in
, "%d", &len
)!=1 || len
<=0 ) {
2446 LogError( _("Failed to parse the StartData command properly, bad count\n") );
2449 while ( isspace(ch
=getc(in
)) );
2451 for ( pt
="StartData "; *pt
; ++pt
)
2452 getc(in
); /* And if it didn't match, what could I do about it? */
2461 /* Hex data are allowed to contain whitespace */
2462 while ( isspace(ch
=getc(in
)) );
2463 while ( isspace(ch2
=getc(in
)) );
2468 if ( (ch
=getc(in
))!='>' ) ungetc(ch
,in
);
2472 figurecids(fp
,temp
);
2474 fp
->fd
->sf
= _CFFParse(temp
,len
,fontsetname
);
2475 fp
->fd
->wascff
= true;
2479 static void realdecrypt(struct fontparse
*fp
,FILE *in
, FILE *temp
) {
2481 int first
, hassectionheads
;
2483 int saw_blend
= false;
2487 first
= 1; hassectionheads
= 0;
2488 while ( myfgets(buffer
,sizeof(buffer
),in
)!=NULL
) {
2489 if ( strstr(buffer
, "Blend")!=NULL
)
2491 if ( first
&& buffer
[0]=='\200' ) {
2492 int len
= strlen( buffer
);
2493 hassectionheads
= 1;
2494 fp
->fd
->wasbinary
= true;
2495 /* if there were a newline in the section header (in the length word)*/
2496 /* we would stop at it, and not read the full header */
2497 if ( len
<6 ) /* eat the header */
2498 while ( len
<6 ) { getc(in
); ++len
; }
2499 else /* Otherwise parse anything else on the line */
2500 parseline(fp
,buffer
+6,in
);
2501 } else if ( strstr(buffer
,"CharProcs")!=NULL
&& strstr(buffer
,"begin")!=NULL
) {
2504 } else if ( fp
->fd
->fonttype
!=42 && strstr(buffer
,"CharStrings")!=NULL
&& strstr(buffer
,"begin")!=NULL
) {
2505 /* Fontographer uses CharStrings even though they aren't */
2508 } else if ( !fp
->iscid
) {
2510 parseline(fp
,buffer
,in
);
2511 /* But if it's a multi master font, don't do the special private hack */
2512 else if ( strstr(buffer
,"/CharStrings")!=NULL
&&
2513 strstr(buffer
,"begin")!=NULL
&&
2514 (fp
->fd
->fonttype
!=42 && fp
->fd
->cidfonttype
!=2)) {
2515 /* gsf files are not eexec encoded, but the charstrings are encoded*/
2516 InitChars(fp
->fd
->chars
,buffer
);
2518 decryptagain(fp
,in
,rdtok
);
2520 } else if ( strstr(buffer
,"/Subrs")!=NULL
&& strstr(buffer
,"array")!=NULL
) {
2521 /* Same case as above */
2522 InitChars(fp
->fd
->private->subrs
,buffer
);
2524 decryptagain(fp
,in
,rdtok
);
2526 } else if ( strstr(buffer
,"/Private")!=NULL
&& (strstr(buffer
,"dict")!=NULL
|| strstr(buffer
,"<<")!=NULL
)) {
2527 /* files produced by GNU fontutils have some of the same issues */
2530 decryptagain(fp
,in
,rdtok
);
2533 parseline(fp
,buffer
,in
);
2535 parseline(fp
,buffer
,in
);
2537 if ( strstr(buffer
,"%%BeginData: ")!=NULL
)
2539 if ( strstr(buffer
,"currentfile")!=NULL
&& strstr(buffer
, "eexec")!=NULL
) {
2540 fp
->skipping_mbf
= false;
2543 /* Hmm. These lines were put in to handle parsing type42 fonts, but */
2544 /* they break multimaster fonts, and they don't seem to be needed */
2545 /* for type42s any more either. So... Away with them */
2547 if ( strstr(buffer
,"definefont")!=NULL
)
2552 if ( strstr(buffer
,"%%BeginData: ")!=NULL
) {
2553 /* used by both CID fonts and CFF fonts (and chameleons, whatever they are) */
2555 } else if ( strstr(buffer
,"eexec")!=NULL
) {
2556 decrypteexec(in
,temp
,hassectionheads
,strstr(buffer
, "eexec")+5);
2558 decryptagain(fp
,temp
,rdtok
);
2559 while ( myfgets(buffer
,sizeof(buffer
),in
)!=NULL
) {
2560 if ( buffer
[0]!='\200' || !hassectionheads
)
2561 parseline(fp
,buffer
,in
);
2563 } else if (( fp
->fd
->fonttype
==42 || fp
->fd
->cidfonttype
==2 ) && fp
->sfnts
!=NULL
) {
2564 fp
->fd
->sf
= _SFReadTTF(fp
->sfnts
,0,0,"<Temp File>",fp
->fd
);
2569 FontDict
*_ReadPSFont(FILE *in
) {
2571 struct fontparse fp
;
2577 LogError( _("Cannot open a temporary file\n") );
2581 oldloc
= setlocale(LC_NUMERIC
,"C");
2582 memset(&fp
,'\0',sizeof(fp
));
2583 fp
.fd
= fp
.mainfd
= PSMakeEmptyFont();
2585 realdecrypt(&fp
,in
,temp
);
2587 setlocale(LC_NUMERIC
,oldloc
);
2591 if ( fstat(fileno(in
),&b
)!=-1 ) {
2592 fp
.fd
->modificationtime
= b
.st_mtime
;
2593 fp
.fd
->creationtime
= b
.st_mtime
;
2598 FontDict
*ReadPSFont(char *fontname
) {
2602 in
= fopen(fontname
,"rb");
2604 LogError( _("Cannot open %s\n"), fontname
);
2607 fd
= _ReadPSFont(in
);
2612 void PSCharsFree(struct pschars
*chrs
) {
2617 for ( i
=0; i
<chrs
->next
; ++i
) {
2618 if ( chrs
->keys
!=NULL
) free(chrs
->keys
[i
]);
2619 free(chrs
->values
[i
]);
2627 void PSDictFree(struct psdict
*dict
) {
2632 for ( i
=0; i
<dict
->next
; ++i
) {
2633 if ( dict
->keys
!=NULL
) free(dict
->keys
[i
]);
2634 free(dict
->values
[i
]);
2641 static void PrivateFree(struct private *prv
) {
2642 PSCharsFree(prv
->subrs
);
2644 PSDictFree(prv
->private);
2646 PSCharsFree(prv
->othersubrs
);
2647 free(prv
->minfeature
);
2655 static void FontInfoFree(struct fontinfo
*fi
) {
2656 free(fi
->familyname
);
2661 free(fi
->blenddesignpositions
);
2662 free(fi
->blenddesignmap
);
2663 free(fi
->blendaxistypes
);
2667 void PSFontFree(FontDict
*fd
) {
2670 if ( fd
->encoding
!=NULL
)
2671 for ( i
=0; i
<256; ++i
)
2672 free( fd
->encoding
[i
]);
2674 free(fd
->cidfontname
);
2677 FontInfoFree(fd
->fontinfo
);
2678 PSCharsFree(fd
->chars
);
2679 PrivateFree(fd
->private);
2680 if ( fd
->charprocs
!=NULL
) {
2681 for ( i
=0; i
<fd
->charprocs
->cnt
; ++i
)
2682 free(fd
->charprocs
->keys
[i
]);
2683 free(fd
->charprocs
->keys
);
2684 free(fd
->charprocs
->values
);
2685 free(fd
->charprocs
);
2687 if ( fd
->cidstrs
!=NULL
) {
2688 for ( i
=0; i
<fd
->cidcnt
; ++i
)
2689 free( fd
->cidstrs
[i
]);
2694 if ( fd
->fds
!=NULL
) {
2695 for ( i
=0; i
<fd
->fdcnt
; ++i
)
2696 PSFontFree(fd
->fds
[i
]);
2699 free(fd
->blendfunc
);
2700 free(fd
->weightvector
);
2704 PSDictFree(fd
->blendprivate
);
2705 PSDictFree(fd
->blendfontinfo
);
2710 char **_NamesReadPostscript(FILE *ps
) {
2712 char buffer
[2000], *pt
, *end
;
2715 while ( fgets(buffer
,sizeof(buffer
),ps
)!=NULL
) {
2716 if ( strstr(buffer
,"/FontName")!=NULL
||
2717 strstr(buffer
,"/CIDFontName")!=NULL
) {
2718 pt
= strstr(buffer
,"FontName");
2719 pt
+= strlen("FontName");
2720 while ( isspace(*pt
)) ++pt
;
2721 if ( *pt
=='/' ) ++pt
;
2722 for ( end
= pt
; *end
!='\0' && !isspace(*end
); ++end
);
2723 ret
= galloc(2*sizeof(char *));
2724 ret
[0] = copyn(pt
,end
-pt
);
2727 } else if ( strstr(buffer
,"currentfile")!=NULL
&& strstr(buffer
,"eexec")!=NULL
)
2729 else if ( strstr(buffer
,"%%BeginData")!=NULL
)
2737 char **NamesReadPostscript(char *filename
) {
2738 return( _NamesReadPostscript( fopen(filename
,"rb")));