diff options
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/luafontloader/fontforge/fontforge/parsepfa.c')
-rw-r--r-- | Build/source/texk/web2c/luatexdir/luafontloader/fontforge/fontforge/parsepfa.c | 2740 |
1 files changed, 2740 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/luatexdir/luafontloader/fontforge/fontforge/parsepfa.c b/Build/source/texk/web2c/luatexdir/luafontloader/fontforge/fontforge/parsepfa.c new file mode 100644 index 00000000000..0c4108fa99e --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/luafontloader/fontforge/fontforge/parsepfa.c @@ -0,0 +1,2740 @@ +/* Copyright (C) 2000-2008 by George Williams */ +/* + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + + * The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "pfaedit.h" +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ustring.h> +#include <utype.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include "psfont.h" +#include <locale.h> + +struct fontparse { + FontDict *fd, *mainfd; + /* always in font data */ + unsigned int infi:1; + unsigned int inchars:1; + unsigned int inprivate:1; + unsigned int insubs:1; + unsigned int inmetrics: 1; + unsigned int inmetrics2: 1; + unsigned int inbb: 1; + unsigned int inencoding: 1; + unsigned int simpleencoding: 1; + unsigned int multiline: 1; + unsigned int incidsysteminfo: 1; + unsigned int inblendfi:1; + unsigned int inblendprivate:1; + unsigned int skipping_mbf: 1; + unsigned int inblend: 1; + unsigned int iscid: 1; + unsigned int iscff: 1; + unsigned int useshexstrings: 1; + unsigned int doneencoding: 1; + unsigned int ignore: 1; + int simple_enc_pos; + int instring; + int fdindex; + char **pending_parse; + FILE *sfnts; + + unsigned int alreadycomplained: 1; + + char *vbuf, *vmax, *vpt; + int depth; +}; + +static void copyenc(char *encoding[256],char *std[256]) { + int i; + for ( i=0; i<256; ++i ) + encoding[i] = copy(std[i]); +} + +char *AdobeStandardEncoding[] = { +/* 0000 */ ".notdef", +/* 0001 */ ".notdef", +/* 0002 */ ".notdef", +/* 0003 */ ".notdef", +/* 0004 */ ".notdef", +/* 0005 */ ".notdef", +/* 0006 */ ".notdef", +/* 0007 */ ".notdef", +/* 0008 */ ".notdef", +/* 0009 */ ".notdef", +/* 000a */ ".notdef", +/* 000b */ ".notdef", +/* 000c */ ".notdef", +/* 000d */ ".notdef", +/* 000e */ ".notdef", +/* 000f */ ".notdef", +/* 0010 */ ".notdef", +/* 0011 */ ".notdef", +/* 0012 */ ".notdef", +/* 0013 */ ".notdef", +/* 0014 */ ".notdef", +/* 0015 */ ".notdef", +/* 0016 */ ".notdef", +/* 0017 */ ".notdef", +/* 0018 */ ".notdef", +/* 0019 */ ".notdef", +/* 001a */ ".notdef", +/* 001b */ ".notdef", +/* 001c */ ".notdef", +/* 001d */ ".notdef", +/* 001e */ ".notdef", +/* 001f */ ".notdef", +/* 0020 */ "space", +/* 0021 */ "exclam", +/* 0022 */ "quotedbl", +/* 0023 */ "numbersign", +/* 0024 */ "dollar", +/* 0025 */ "percent", +/* 0026 */ "ampersand", +/* 0027 */ "quoteright", +/* 0028 */ "parenleft", +/* 0029 */ "parenright", +/* 002a */ "asterisk", +/* 002b */ "plus", +/* 002c */ "comma", +/* 002d */ "hyphen", +/* 002e */ "period", +/* 002f */ "slash", +/* 0030 */ "zero", +/* 0031 */ "one", +/* 0032 */ "two", +/* 0033 */ "three", +/* 0034 */ "four", +/* 0035 */ "five", +/* 0036 */ "six", +/* 0037 */ "seven", +/* 0038 */ "eight", +/* 0039 */ "nine", +/* 003a */ "colon", +/* 003b */ "semicolon", +/* 003c */ "less", +/* 003d */ "equal", +/* 003e */ "greater", +/* 003f */ "question", +/* 0040 */ "at", +/* 0041 */ "A", +/* 0042 */ "B", +/* 0043 */ "C", +/* 0044 */ "D", +/* 0045 */ "E", +/* 0046 */ "F", +/* 0047 */ "G", +/* 0048 */ "H", +/* 0049 */ "I", +/* 004a */ "J", +/* 004b */ "K", +/* 004c */ "L", +/* 004d */ "M", +/* 004e */ "N", +/* 004f */ "O", +/* 0050 */ "P", +/* 0051 */ "Q", +/* 0052 */ "R", +/* 0053 */ "S", +/* 0054 */ "T", +/* 0055 */ "U", +/* 0056 */ "V", +/* 0057 */ "W", +/* 0058 */ "X", +/* 0059 */ "Y", +/* 005a */ "Z", +/* 005b */ "bracketleft", +/* 005c */ "backslash", +/* 005d */ "bracketright", +/* 005e */ "asciicircum", +/* 005f */ "underscore", +/* 0060 */ "quoteleft", +/* 0061 */ "a", +/* 0062 */ "b", +/* 0063 */ "c", +/* 0064 */ "d", +/* 0065 */ "e", +/* 0066 */ "f", +/* 0067 */ "g", +/* 0068 */ "h", +/* 0069 */ "i", +/* 006a */ "j", +/* 006b */ "k", +/* 006c */ "l", +/* 006d */ "m", +/* 006e */ "n", +/* 006f */ "o", +/* 0070 */ "p", +/* 0071 */ "q", +/* 0072 */ "r", +/* 0073 */ "s", +/* 0074 */ "t", +/* 0075 */ "u", +/* 0076 */ "v", +/* 0077 */ "w", +/* 0078 */ "x", +/* 0079 */ "y", +/* 007a */ "z", +/* 007b */ "braceleft", +/* 007c */ "bar", +/* 007d */ "braceright", +/* 007e */ "asciitilde", +/* 007f */ ".notdef", +/* 0080 */ ".notdef", +/* 0081 */ ".notdef", +/* 0082 */ ".notdef", +/* 0083 */ ".notdef", +/* 0084 */ ".notdef", +/* 0085 */ ".notdef", +/* 0086 */ ".notdef", +/* 0087 */ ".notdef", +/* 0088 */ ".notdef", +/* 0089 */ ".notdef", +/* 008a */ ".notdef", +/* 008b */ ".notdef", +/* 008c */ ".notdef", +/* 008d */ ".notdef", +/* 008e */ ".notdef", +/* 008f */ ".notdef", +/* 0090 */ ".notdef", +/* 0091 */ ".notdef", +/* 0092 */ ".notdef", +/* 0093 */ ".notdef", +/* 0094 */ ".notdef", +/* 0095 */ ".notdef", +/* 0096 */ ".notdef", +/* 0097 */ ".notdef", +/* 0098 */ ".notdef", +/* 0099 */ ".notdef", +/* 009a */ ".notdef", +/* 009b */ ".notdef", +/* 009c */ ".notdef", +/* 009d */ ".notdef", +/* 009e */ ".notdef", +/* 009f */ ".notdef", +/* 00a0 */ ".notdef", +/* 00a1 */ "exclamdown", +/* 00a2 */ "cent", +/* 00a3 */ "sterling", +/* 00a4 */ "fraction", +/* 00a5 */ "yen", +/* 00a6 */ "florin", +/* 00a7 */ "section", +/* 00a8 */ "currency", +/* 00a9 */ "quotesingle", +/* 00aa */ "quotedblleft", +/* 00ab */ "guillemotleft", +/* 00ac */ "guilsinglleft", +/* 00ad */ "guilsinglright", +/* 00ae */ "fi", +/* 00af */ "fl", +/* 00b0 */ ".notdef", +/* 00b1 */ "endash", +/* 00b2 */ "dagger", +/* 00b3 */ "daggerdbl", +/* 00b4 */ "periodcentered", +/* 00b5 */ ".notdef", +/* 00b6 */ "paragraph", +/* 00b7 */ "bullet", +/* 00b8 */ "quotesinglbase", +/* 00b9 */ "quotedblbase", +/* 00ba */ "quotedblright", +/* 00bb */ "guillemotright", +/* 00bc */ "ellipsis", +/* 00bd */ "perthousand", +/* 00be */ ".notdef", +/* 00bf */ "questiondown", +/* 00c0 */ ".notdef", +/* 00c1 */ "grave", +/* 00c2 */ "acute", +/* 00c3 */ "circumflex", +/* 00c4 */ "tilde", +/* 00c5 */ "macron", +/* 00c6 */ "breve", +/* 00c7 */ "dotaccent", +/* 00c8 */ "dieresis", +/* 00c9 */ ".notdef", +/* 00ca */ "ring", +/* 00cb */ "cedilla", +/* 00cc */ ".notdef", +/* 00cd */ "hungarumlaut", +/* 00ce */ "ogonek", +/* 00cf */ "caron", +/* 00d0 */ "emdash", +/* 00d1 */ ".notdef", +/* 00d2 */ ".notdef", +/* 00d3 */ ".notdef", +/* 00d4 */ ".notdef", +/* 00d5 */ ".notdef", +/* 00d6 */ ".notdef", +/* 00d7 */ ".notdef", +/* 00d8 */ ".notdef", +/* 00d9 */ ".notdef", +/* 00da */ ".notdef", +/* 00db */ ".notdef", +/* 00dc */ ".notdef", +/* 00dd */ ".notdef", +/* 00de */ ".notdef", +/* 00df */ ".notdef", +/* 00e0 */ ".notdef", +/* 00e1 */ "AE", +/* 00e2 */ ".notdef", +/* 00e3 */ "ordfeminine", +/* 00e4 */ ".notdef", +/* 00e5 */ ".notdef", +/* 00e6 */ ".notdef", +/* 00e7 */ ".notdef", +/* 00e8 */ "Lslash", +/* 00e9 */ "Oslash", +/* 00ea */ "OE", +/* 00eb */ "ordmasculine", +/* 00ec */ ".notdef", +/* 00ed */ ".notdef", +/* 00ee */ ".notdef", +/* 00ef */ ".notdef", +/* 00f0 */ ".notdef", +/* 00f1 */ "ae", +/* 00f2 */ ".notdef", +/* 00f3 */ ".notdef", +/* 00f4 */ ".notdef", +/* 00f5 */ "dotlessi", +/* 00f6 */ ".notdef", +/* 00f7 */ ".notdef", +/* 00f8 */ "lslash", +/* 00f9 */ "oslash", +/* 00fa */ "oe", +/* 00fb */ "germandbls", +/* 00fc */ ".notdef", +/* 00fd */ ".notdef", +/* 00fe */ ".notdef", +/* 00ff */ ".notdef" +}; +static void setStdEnc(char *encoding[256]) { + copyenc(encoding,AdobeStandardEncoding); +} + +static void setLatin1Enc(char *encoding[256]) { + static char *latin1enc[] = { +/* 0000 */ ".notdef", +/* 0001 */ ".notdef", +/* 0002 */ ".notdef", +/* 0003 */ ".notdef", +/* 0004 */ ".notdef", +/* 0005 */ ".notdef", +/* 0006 */ ".notdef", +/* 0007 */ ".notdef", +/* 0008 */ ".notdef", +/* 0009 */ ".notdef", +/* 000a */ ".notdef", +/* 000b */ ".notdef", +/* 000c */ ".notdef", +/* 000d */ ".notdef", +/* 000e */ ".notdef", +/* 000f */ ".notdef", +/* 0010 */ ".notdef", +/* 0011 */ ".notdef", +/* 0012 */ ".notdef", +/* 0013 */ ".notdef", +/* 0014 */ ".notdef", +/* 0015 */ ".notdef", +/* 0016 */ ".notdef", +/* 0017 */ ".notdef", +/* 0018 */ ".notdef", +/* 0019 */ ".notdef", +/* 001a */ ".notdef", +/* 001b */ ".notdef", +/* 001c */ ".notdef", +/* 001d */ ".notdef", +/* 001e */ ".notdef", +/* 001f */ ".notdef", +/* 0020 */ "space", +/* 0021 */ "exclam", +/* 0022 */ "quotedbl", +/* 0023 */ "numbersign", +/* 0024 */ "dollar", +/* 0025 */ "percent", +/* 0026 */ "ampersand", +/* 0027 */ "quoteright", +/* 0028 */ "parenleft", +/* 0029 */ "parenright", +/* 002a */ "asterisk", +/* 002b */ "plus", +/* 002c */ "comma", +/* 002d */ "hyphen", +/* 002e */ "period", +/* 002f */ "slash", +/* 0030 */ "zero", +/* 0031 */ "one", +/* 0032 */ "two", +/* 0033 */ "three", +/* 0034 */ "four", +/* 0035 */ "five", +/* 0036 */ "six", +/* 0037 */ "seven", +/* 0038 */ "eight", +/* 0039 */ "nine", +/* 003a */ "colon", +/* 003b */ "semicolon", +/* 003c */ "less", +/* 003d */ "equal", +/* 003e */ "greater", +/* 003f */ "question", +/* 0040 */ "at", +/* 0041 */ "A", +/* 0042 */ "B", +/* 0043 */ "C", +/* 0044 */ "D", +/* 0045 */ "E", +/* 0046 */ "F", +/* 0047 */ "G", +/* 0048 */ "H", +/* 0049 */ "I", +/* 004a */ "J", +/* 004b */ "K", +/* 004c */ "L", +/* 004d */ "M", +/* 004e */ "N", +/* 004f */ "O", +/* 0050 */ "P", +/* 0051 */ "Q", +/* 0052 */ "R", +/* 0053 */ "S", +/* 0054 */ "T", +/* 0055 */ "U", +/* 0056 */ "V", +/* 0057 */ "W", +/* 0058 */ "X", +/* 0059 */ "Y", +/* 005a */ "Z", +/* 005b */ "bracketleft", +/* 005c */ "backslash", +/* 005d */ "bracketright", +/* 005e */ "asciicircum", +/* 005f */ "underscore", +/* 0060 */ "grave", +/* 0061 */ "a", +/* 0062 */ "b", +/* 0063 */ "c", +/* 0064 */ "d", +/* 0065 */ "e", +/* 0066 */ "f", +/* 0067 */ "g", +/* 0068 */ "h", +/* 0069 */ "i", +/* 006a */ "j", +/* 006b */ "k", +/* 006c */ "l", +/* 006d */ "m", +/* 006e */ "n", +/* 006f */ "o", +/* 0070 */ "p", +/* 0071 */ "q", +/* 0072 */ "r", +/* 0073 */ "s", +/* 0074 */ "t", +/* 0075 */ "u", +/* 0076 */ "v", +/* 0077 */ "w", +/* 0078 */ "x", +/* 0079 */ "y", +/* 007a */ "z", +/* 007b */ "braceleft", +/* 007c */ "bar", +/* 007d */ "braceright", +/* 007e */ "asciitilde", +/* 007f */ ".notdef", +/* 0080 */ ".notdef", +/* 0081 */ ".notdef", +/* 0082 */ ".notdef", +/* 0083 */ ".notdef", +/* 0084 */ ".notdef", +/* 0085 */ ".notdef", +/* 0086 */ ".notdef", +/* 0087 */ ".notdef", +/* 0088 */ ".notdef", +/* 0089 */ ".notdef", +/* 008a */ ".notdef", +/* 008b */ ".notdef", +/* 008c */ ".notdef", +/* 008d */ ".notdef", +/* 008e */ ".notdef", +/* 008f */ ".notdef", +/* 0090 */ "dotlessi", /* Um, Adobe's Latin1 has some extra chars */ +/* 0091 */ "grave", +/* 0092 */ "accute", /* This is a duplicate... */ +/* 0093 */ "circumflex", +/* 0094 */ "tilde", +/* 0095 */ "macron", +/* 0096 */ "breve", +/* 0097 */ "dotaccent", +/* 0098 */ "dieresis", +/* 0099 */ ".notdef", +/* 009a */ "ring", +/* 009b */ "cedilla", +/* 009c */ ".notdef", +/* 009d */ "hungarumlaut", +/* 009e */ "ogonek", +/* 009f */ "caron", +/* 00a0 */ "space", +/* 00a1 */ "exclamdown", +/* 00a2 */ "cent", +/* 00a3 */ "sterling", +/* 00a4 */ "currency", +/* 00a5 */ "yen", +/* 00a6 */ "brokenbar", +/* 00a7 */ "section", +/* 00a8 */ "dieresis", +/* 00a9 */ "copyright", +/* 00aa */ "ordfeminine", +/* 00ab */ "guillemotleft", +/* 00ac */ "logicalnot", +/* 00ad */ "hyphen", +/* 00ae */ "registered", +/* 00af */ "macron", +/* 00b0 */ "degree", +/* 00b1 */ "plusminus", +/* 00b2 */ "twosuperior", +/* 00b3 */ "threesuperior", +/* 00b4 */ "acute", +/* 00b5 */ "mu", +/* 00b6 */ "paragraph", +/* 00b7 */ "periodcentered", +/* 00b8 */ "cedilla", +/* 00b9 */ "onesuperior", +/* 00ba */ "ordmasculine", +/* 00bb */ "guillemotright", +/* 00bc */ "onequarter", +/* 00bd */ "onehalf", +/* 00be */ "threequarters", +/* 00bf */ "questiondown", +/* 00c0 */ "Agrave", +/* 00c1 */ "Aacute", +/* 00c2 */ "Acircumflex", +/* 00c3 */ "Atilde", +/* 00c4 */ "Adieresis", +/* 00c5 */ "Aring", +/* 00c6 */ "AE", +/* 00c7 */ "Ccedilla", +/* 00c8 */ "Egrave", +/* 00c9 */ "Eacute", +/* 00ca */ "Ecircumflex", +/* 00cb */ "Edieresis", +/* 00cc */ "Igrave", +/* 00cd */ "Iacute", +/* 00ce */ "Icircumflex", +/* 00cf */ "Idieresis", +/* 00d0 */ "Eth", +/* 00d1 */ "Ntilde", +/* 00d2 */ "Ograve", +/* 00d3 */ "Oacute", +/* 00d4 */ "Ocircumflex", +/* 00d5 */ "Otilde", +/* 00d6 */ "Odieresis", +/* 00d7 */ "multiply", +/* 00d8 */ "Oslash", +/* 00d9 */ "Ugrave", +/* 00da */ "Uacute", +/* 00db */ "Ucircumflex", +/* 00dc */ "Udieresis", +/* 00dd */ "Yacute", +/* 00de */ "Thorn", +/* 00df */ "germandbls", +/* 00e0 */ "agrave", +/* 00e1 */ "aacute", +/* 00e2 */ "acircumflex", +/* 00e3 */ "atilde", +/* 00e4 */ "adieresis", +/* 00e5 */ "aring", +/* 00e6 */ "ae", +/* 00e7 */ "ccedilla", +/* 00e8 */ "egrave", +/* 00e9 */ "eacute", +/* 00ea */ "ecircumflex", +/* 00eb */ "edieresis", +/* 00ec */ "igrave", +/* 00ed */ "iacute", +/* 00ee */ "icircumflex", +/* 00ef */ "idieresis", +/* 00f0 */ "eth", +/* 00f1 */ "ntilde", +/* 00f2 */ "ograve", +/* 00f3 */ "oacute", +/* 00f4 */ "ocircumflex", +/* 00f5 */ "otilde", +/* 00f6 */ "odieresis", +/* 00f7 */ "divide", +/* 00f8 */ "oslash", +/* 00f9 */ "ugrave", +/* 00fa */ "uacute", +/* 00fb */ "ucircumflex", +/* 00fc */ "udieresis", +/* 00fd */ "yacute", +/* 00fe */ "thorn", +/* 00ff */ "ydieresis" + }; + copyenc(encoding,latin1enc); +} + +char *AdobeExpertEncoding[] = { +/* 0000 */ ".notdef", +/* 0001 */ ".notdef", +/* 0002 */ ".notdef", +/* 0003 */ ".notdef", +/* 0004 */ ".notdef", +/* 0005 */ ".notdef", +/* 0006 */ ".notdef", +/* 0007 */ ".notdef", +/* 0008 */ ".notdef", +/* 0009 */ ".notdef", +/* 000a */ ".notdef", +/* 000b */ ".notdef", +/* 000c */ ".notdef", +/* 000d */ ".notdef", +/* 000e */ ".notdef", +/* 000f */ ".notdef", +/* 0010 */ ".notdef", +/* 0011 */ ".notdef", +/* 0012 */ ".notdef", +/* 0013 */ ".notdef", +/* 0014 */ ".notdef", +/* 0015 */ ".notdef", +/* 0016 */ ".notdef", +/* 0017 */ ".notdef", +/* 0018 */ ".notdef", +/* 0019 */ ".notdef", +/* 001a */ ".notdef", +/* 001b */ ".notdef", +/* 001c */ ".notdef", +/* 001d */ ".notdef", +/* 001e */ ".notdef", +/* 001f */ ".notdef", +/* 0020 */ "space", +/* 0021 */ "exclamsmall", +/* 0022 */ "Hungarumlautsmal", +/* 0023 */ ".notdef", +/* 0024 */ "dollaroldstyle", +/* 0025 */ "dollarsuperior", +/* 0026 */ "ampersandsmall", +/* 0027 */ "Acutesmall", +/* 0028 */ "parenleftsuperior", +/* 0029 */ "parenrightsuperior", +/* 002a */ "twodotenleader", +/* 002b */ "onedotenleader", +/* 002c */ "comma", +/* 002d */ "hyphen", +/* 002e */ "period", +/* 002f */ "fraction", +/* 0030 */ "zerooldstyle", +/* 0031 */ "oneoldstyle", +/* 0032 */ "twooldstyle", +/* 0033 */ "threeoldstyle", +/* 0034 */ "fouroldstyle", +/* 0035 */ "fiveoldstyle", +/* 0036 */ "sixoldstyle", +/* 0037 */ "sevenoldstyle", +/* 0038 */ "eightoldstyle", +/* 0039 */ "nineoldstyle", +/* 003a */ "colon", +/* 003b */ "semicolon", +/* 003c */ "commasuperior", +/* 003d */ "threequartersemdash", +/* 003e */ "periodsuperior", +/* 003f */ "questionsmall", +/* 0040 */ ".notdef", +/* 0041 */ "asuperior", +/* 0042 */ "bsuperior", +/* 0043 */ "centsuperior", +/* 0044 */ "dsuperior", +/* 0045 */ "esuperior", +/* 0046 */ ".notdef", +/* 0047 */ ".notdef", +/* 0048 */ ".notdef", +/* 0049 */ "isuperior", +/* 004a */ ".notdef", +/* 004b */ ".notdef", +/* 004c */ "lsuperior", +/* 004d */ "msuperior", +/* 004e */ "nsuperior", +/* 004f */ "osuperior", +/* 0050 */ ".notdef", +/* 0051 */ ".notdef", +/* 0052 */ "rsuperior", +/* 0053 */ "ssuperior", +/* 0054 */ "tsuperior", +/* 0055 */ ".notdef", +/* 0056 */ "ff", +/* 0057 */ "fi", +/* 0058 */ "fl", +/* 0059 */ "ffi", +/* 005a */ "ffl", +/* 005b */ "parenleftinferior", +/* 005c */ ".notdef", +/* 005d */ "parenrightinferior", +/* 005e */ "Circumflexsmall", +/* 005f */ "hyphensuperior", +/* 0060 */ "Gravesmall", +/* 0061 */ "Asmall", +/* 0062 */ "Bsmall", +/* 0063 */ "Csmall", +/* 0064 */ "Dsmall", +/* 0065 */ "Esmall", +/* 0066 */ "Fsmall", +/* 0067 */ "Gsmall", +/* 0068 */ "Hsmall", +/* 0069 */ "Ismall", +/* 006a */ "Jsmall", +/* 006b */ "Ksmall", +/* 006c */ "Lsmall", +/* 006d */ "Msmall", +/* 006e */ "Nsmall", +/* 006f */ "Osmall", +/* 0070 */ "Psmall", +/* 0071 */ "Qsmall", +/* 0072 */ "Rsmall", +/* 0073 */ "Ssmall", +/* 0074 */ "Tsmall", +/* 0075 */ "Usmall", +/* 0076 */ "Vsmall", +/* 0077 */ "Wsmall", +/* 0078 */ "Xsmall", +/* 0079 */ "Ysmall", +/* 007a */ "Zsmall", +/* 007b */ "colonmonetary", +/* 007c */ "onefitted", +/* 007d */ "rupiah", +/* 007e */ "Tildesmall", +/* 007f */ ".notdef", +/* 0080 */ ".notdef", +/* 0081 */ ".notdef", +/* 0082 */ ".notdef", +/* 0083 */ ".notdef", +/* 0084 */ ".notdef", +/* 0085 */ ".notdef", +/* 0086 */ ".notdef", +/* 0087 */ ".notdef", +/* 0088 */ ".notdef", +/* 0089 */ ".notdef", +/* 008a */ ".notdef", +/* 008b */ ".notdef", +/* 008c */ ".notdef", +/* 008d */ ".notdef", +/* 008e */ ".notdef", +/* 008f */ ".notdef", +/* 0090 */ ".notdef", +/* 0091 */ ".notdef", +/* 0092 */ ".notdef", +/* 0093 */ ".notdef", +/* 0094 */ ".notdef", +/* 0095 */ ".notdef", +/* 0096 */ ".notdef", +/* 0097 */ ".notdef", +/* 0098 */ ".notdef", +/* 0099 */ ".notdef", +/* 009a */ ".notdef", +/* 009b */ ".notdef", +/* 009c */ ".notdef", +/* 009d */ ".notdef", +/* 009e */ ".notdef", +/* 009f */ ".notdef", +/* 00a0 */ ".notdef", +/* 00a1 */ "exclamdownsmall", +/* 00a2 */ "centoldstyle", +/* 00a3 */ "Lslashsmall", +/* 00a4 */ ".notdef", +/* 00a5 */ ".notdef", +/* 00a6 */ "Scaronsmall", +/* 00a7 */ "Zcaronsmall", +/* 00a8 */ "Dieresissmall", +/* 00a9 */ "Brevesmall", +/* 00aa */ "Caronsmall", +/* 00ab */ ".notdef", +/* 00ac */ "Dotaccentsmall", +/* 00ad */ ".notdef", +/* 00ae */ ".notdef", +/* 00af */ "Macronsmall", +/* 00b0 */ ".notdef", +/* 00b1 */ ".notdef", +/* 00b2 */ "figuredash", +/* 00b3 */ "hypheninferior", +/* 00b4 */ ".notdef", +/* 00b5 */ ".notdef", +/* 00b6 */ "Ogoneksmall", +/* 00b7 */ "Ringsmall", +/* 00b8 */ "Cedillasmall", +/* 00b9 */ ".notdef", +/* 00ba */ ".notdef", +/* 00bb */ ".notdef", +/* 00bc */ "onequarter", +/* 00bd */ "onehalf", +/* 00be */ "threequarters", +/* 00bf */ "questiondownsmall", +/* 00c0 */ "oneeighth", +/* 00c1 */ "threeeighths", +/* 00c2 */ "fiveeighths", +/* 00c3 */ "seveneighths", +/* 00c4 */ "onethird", +/* 00c5 */ "twothirds", +/* 00c6 */ ".notdef", +/* 00c7 */ ".notdef", +/* 00c8 */ "zerosuperior", +/* 00c9 */ "onesuperior", +/* 00ca */ "twosuperior", +/* 00cb */ "threesuperior", +/* 00cc */ "foursuperior", +/* 00cd */ "fivesuperior", +/* 00ce */ "sixsuperior", +/* 00cf */ "sevensuperior", +/* 00d0 */ "eightsuperior", +/* 00d1 */ "ninesuperior", +/* 00d2 */ "zeroinferior", +/* 00d3 */ "oneinferior", +/* 00d4 */ "twoinferior", +/* 00d5 */ "threeinferior", +/* 00d6 */ "fourinferior", +/* 00d7 */ "fiveinferior", +/* 00d8 */ "sixinferior", +/* 00d9 */ "seveninferior", +/* 00da */ "eightinferior", +/* 00db */ "nineinferior", +/* 00dc */ "centinferior", +/* 00dd */ "dollarinferior", +/* 00de */ "periodinferior", +/* 00df */ "commainferior", +/* 00e0 */ "Agravesmall", +/* 00e1 */ "Aacutesmall", +/* 00e2 */ "Acircumflexsmall", +/* 00e3 */ "Atildesmall", +/* 00e4 */ "Adieresissmall", +/* 00e5 */ "Aringsmall", +/* 00e6 */ "AEsmall", +/* 00e7 */ "Ccedillasmall", +/* 00e8 */ "Egravesmall", +/* 00e9 */ "Eacutesmall", +/* 00ea */ "Ecircumflexsmall", +/* 00eb */ "Edieresissmall", +/* 00ec */ "Igravesmall", +/* 00ed */ "Iacutesmall", +/* 00ee */ "Icircumflexsmall", +/* 00ef */ "Idieresissmall", +/* 00f0 */ "Ethsmall", +/* 00f1 */ "Ntildesmall", +/* 00f2 */ "Ogravesmall", +/* 00f3 */ "Oacutesmall", +/* 00f4 */ "Ocircumflexsmall", +/* 00f5 */ "Otildesmall", +/* 00f6 */ "Odieresissmall", +/* 00f7 */ "OEsmall", +/* 00f8 */ "Oslashsmall", +/* 00f9 */ "Ugravesmall", +/* 00fa */ "Uacutesmall", +/* 00fb */ "Ucircumflexsmall", +/* 00fc */ "Udieresissmall", +/* 00fd */ "Yacutesmall", +/* 00fe */ "Thornsmall", +/* 00ff */ "Ydieresissmall" +}; + +static struct fontdict *MakeEmptyFont(void) { + struct fontdict *ret; + + ret = gcalloc(1,sizeof(struct fontdict)); + ret->fontinfo = gcalloc(1,sizeof(struct fontinfo)); + ret->chars = gcalloc(1,sizeof(struct pschars)); + ret->private = gcalloc(1,sizeof(struct private)); + ret->private->subrs = gcalloc(1,sizeof(struct pschars)); + ret->private->private = gcalloc(1,sizeof(struct psdict)); + ret->private->leniv = 4; + ret->encoding_name = &custom; + ret->fontinfo->fstype = -1; +return( ret ); +} + +static struct fontdict *PSMakeEmptyFont(void) { + struct fontdict *ret; + + ret = gcalloc(1,sizeof(struct fontdict)); + ret->fontinfo = gcalloc(1,sizeof(struct fontinfo)); + ret->chars = gcalloc(1,sizeof(struct pschars)); + ret->private = gcalloc(1,sizeof(struct private)); + ret->private->subrs = gcalloc(1,sizeof(struct pschars)); + ret->private->private = gcalloc(1,sizeof(struct psdict)); + ret->private->leniv = 4; + ret->charprocs = gcalloc(1,sizeof(struct charprocs)); + ret->encoding_name = &custom; + ret->fontinfo->fstype = -1; +return( ret ); +} + +static char *myfgets(char *str, int len, FILE *file) { + char *pt, *end; + int ch=0; + + for ( pt = str, end = str+len-1; pt<end && (ch=getc(file))!=EOF && ch!='\r' && ch!='\n'; + *pt++ = ch ); + if ( ch=='\n' ) + *pt++ = '\n'; + else if ( ch=='\r' ) { + *pt++ = '\r'; + if ((ch=getc(file))!='\n' ) + ungetc(ch,file); + else + *pt++ = '\n'; + } + if ( pt==str ) +return( NULL ); + *pt = '\0'; +return( str ); +} + +static char *myfgetsNoNulls(char *str, int len, FILE *file) { + char *pt, *end; + int ch=0; + + for ( pt = str, end = str+len-1; pt<end && (ch=getc(file))!=EOF && ch!='\r' && ch!='\n'; ) { + if ( ch!='\0' ) + *pt++ = ch; + } + if ( ch=='\n' ) + *pt++ = '\n'; + else if ( ch=='\r' ) { + *pt++ = '\r'; + if ((ch=getc(file))!='\n' ) + ungetc(ch,file); + else + *pt++ = '\n'; + } + if ( pt==str ) +return( NULL ); + *pt = '\0'; +return( str ); +} + +static char *getstring(char *start,FILE *in) { + char *end, *ret; + int parencnt=0, len=0; + char buffer[512]; + + forever { + while ( *start!='\0' && *start!='(' ) ++start; + if ( *start=='\0' ) { + if ( myfgetsNoNulls(buffer,sizeof(buffer),in)==NULL ) +return( copy("")); + start = buffer; + } else + break; + } + ++start; + ret = NULL; len = 1; + forever { + for ( end = start; *end!='\0' && (*end!=')' || parencnt>0); ++end ) { + if ( *end=='\\' && (end[1]=='(' || end[1]==')')) + ++end; + else if ( *end=='(' ) ++parencnt; + else if ( *end==')' ) --parencnt; + } + if ( end>start ) { + if ( ret==NULL ) + ret = galloc(end-start+1); + else + ret = grealloc(ret,len+end-start); + strncpy(ret+len-1,start,end-start); + len += end-start; + ret[len-1] = '\0'; + } + if ( *end!='\0' ) + break; + if ( myfgetsNoNulls(buffer,sizeof(buffer),in)==NULL ) +return( ret ); + start = buffer; + } +return( ret ); +} + +static char *gettoken(char *start) { + char *end, *ret; + + while ( *start!='\0' && *start!='/' && *start!='(' ) ++start; + if ( *start=='/' || *start=='(' ) ++start; + for ( end = start; *end!='\0' && !isspace(*end) && *end!='[' && *end!='/' && *end!='{' && *end!='(' && *end!=')'; ++end ); + ret = galloc(end-start+1); + if ( end>start ) + strncpy(ret,start,end-start); + ret[end-start] = '\0'; +return( ret ); +} + +static int getbool(char *start) { + + while ( isspace(*start) ) ++start; + if ( *start=='T' || *start=='t' ) +return( 1 ); + +return( 0 ); +} + +static void fillintarray(int *array,char *start,int maxentries) { + int i; + char *end; + + while ( *start!='\0' && *start!='[' && *start!='{' ) ++start; + if ( *start=='[' || *start=='{' ) ++start; + for ( i=0; i<maxentries && *start!=']' && *start!='}'; ++i ) { + array[i] = (int) strtod(start,&end); + if ( start==end ) +return; + start = end; + while ( isspace(*start) ) ++start; + } +} + +static void fillrealarray(real *array,char *start,int maxentries) { + int i; + char *end; + + while ( *start!='\0' && *start!='[' && *start!='{' ) ++start; + if ( *start=='[' || *start=='{' ) ++start; + for ( i=0; i<maxentries && *start!=']' && *start!='}'; ++i ) { + while ( isspace( *start )) ++start; + if ( isdigit(*start) || *start=='-' || *start=='.' ) + array[i] = strtod(start,&end); + else if ( strncmp(start,"div",3)==0 && i>=2 ) { + /* Some of Luc Devroye's fonts have a "div" in the FontMatrix */ + array[i-2] /= array[i-1]; + i -= 2; + end = start+3; + } else +return; + if ( start==end ) +return; + start = end; + while ( isspace(*start) ) ++start; + } +} + +static void InitDict(struct psdict *dict,char *line) { + while ( *line!='/' && *line!='\0' ) ++line; + while ( !isspace(*line) && *line!='\0' ) ++line; + dict->cnt += strtol(line,NULL,10); + if ( dict->next>0 ) { int i; /* Shouldn't happen, but did in a bad file */ + dict->keys = grealloc(dict->keys,dict->cnt*sizeof(char *)); + dict->values = grealloc(dict->values,dict->cnt*sizeof(char *)); + for ( i=dict->next; i<dict->cnt; ++i ) { + dict->keys[i] = NULL; dict->values[i] = NULL; + } + } else { + dict->keys = gcalloc(dict->cnt,sizeof(char *)); + dict->values = gcalloc(dict->cnt,sizeof(char *)); + } +} + +static void InitChars(struct pschars *chars,char *line) { + while ( *line!='/' && *line!='\0' ) ++line; + while ( !isspace(*line) && *line!='\0' ) ++line; + chars->cnt = strtol(line,NULL,10); + if ( chars->cnt>0 ) { + chars->keys = gcalloc(chars->cnt,sizeof(char *)); + chars->values = gcalloc(chars->cnt,sizeof(char *)); + chars->lens = gcalloc(chars->cnt,sizeof(int)); + ff_progress_change_total(chars->cnt); + } +} + +static void InitCharProcs(struct charprocs *cp, char *line) { + while ( *line!='/' && *line!='\0' ) ++line; + while ( !isspace(*line) && *line!='\0' ) ++line; + cp->cnt = strtol(line,NULL,10); + if ( cp->cnt>0 ) { + cp->keys = gcalloc(cp->cnt,sizeof(char *)); + cp->values = gcalloc(cp->cnt,sizeof(SplineChar *)); + ff_progress_change_total(cp->cnt); + } +} + +static int mycmp(char *str,char *within, char *end ) { + while ( within<end ) { + if ( *str!=*within ) +return( *str-*within ); + ++str; ++within; + } +return( *str=='\0'?0:1 ); +} + +static void ContinueValue(struct fontparse *fp, struct psdict *dict, char *line) { + int incomment = false; + + while ( *line ) { + if ( !fp->instring && fp->depth==0 && + (strncmp(line,"def",3)==0 || + strncmp(line,"|-",2)==0 || strncmp(line,"ND",2)==0)) { + while ( 1 ) { + while ( fp->vpt>fp->vbuf+1 && isspace(fp->vpt[-1]) ) + --fp->vpt; + if ( fp->vpt>fp->vbuf+8 && strncmp(fp->vpt-8,"noaccess",8)==0 ) + fp->vpt -= 8; + else if ( fp->vpt>fp->vbuf+8 && strncmp(fp->vpt-8,"readonly",8)==0 ) + fp->vpt -= 8; + else if ( fp->vpt>fp->vbuf+4 && strncmp(fp->vpt-4,"bind",4)==0 ) + fp->vpt -= 4; + else + break; + } + /* In some URW fonts (Nimbus Sans L, n019003l) we get a complex */ + /* expression rather than just an array. This is ok. The expression */ + /* converts itself into an array. We could just truncate to the */ + /* default array, but I don't see any reason to do so */ + if ( fp->pending_parse!=NULL ) { + *fp->pending_parse = copyn(fp->vbuf,fp->vpt-fp->vbuf); + fp->pending_parse = NULL; + } else { + dict->values[dict->next] = copyn(fp->vbuf,fp->vpt-fp->vbuf); + ++dict->next; + } + fp->vpt = fp->vbuf; + fp->multiline = false; +return; + } + if ( fp->vpt>=fp->vmax ) { + int len = fp->vmax-fp->vbuf+1000, off=fp->vpt-fp->vbuf; + fp->vbuf = grealloc(fp->vbuf,len); + fp->vpt = fp->vbuf+off; + fp->vmax = fp->vbuf+len; + } + if ( fp->instring ) { + if ( *line==')' ) --fp->instring; + } else if ( incomment ) { + /* Do Nothing */; + } else if ( *line=='(' ) + ++fp->instring; + else if ( *line=='%' ) + incomment = true; + else if ( *line=='[' || *line=='{' ) + ++fp->depth; + else if ( *line=='}' || *line==']' ) + --fp->depth; + *fp->vpt++ = *line++; + } +} + +static void AddValue(struct fontparse *fp, struct psdict *dict, char *line, char *endtok) { + char *pt; + + if ( dict!=NULL ) { + if ( dict->next>=dict->cnt ) { + dict->cnt += 10; + dict->keys = grealloc(dict->keys,dict->cnt*sizeof(char *)); + dict->values = grealloc(dict->values,dict->cnt*sizeof(char *)); + } + dict->keys[dict->next] = copyn(line+1,endtok-(line+1)); + } + pt = line+strlen(line)-1; + while ( isspace(*endtok)) ++endtok; + while ( pt>endtok && isspace(*pt)) --pt; + ++pt; + if ( strncmp(pt-3,"def",3)==0 ) + pt -= 3; + else if ( strncmp(pt-2,"|-",2)==0 || strncmp(pt-2,"ND",2)==0 ) + pt -= 2; + else { + fp->multiline = true; + ContinueValue(fp,dict,endtok); +return; + } + forever { + while ( pt-1>endtok && isspace(pt[-1])) --pt; + if ( pt-8>endtok && strncmp(pt-8,"noaccess",8)==0 ) + pt -= 8; + else if ( pt-8>endtok && strncmp(pt-8,"readonly",8)==0 ) + pt -= 8; + else if ( pt-4>endtok && strncmp(pt-4,"bind",4)==0 ) + pt -= 4; + else + break; + } + if ( dict!=NULL ) { + dict->values[dict->next] = copyn(endtok,pt-endtok); + ++dict->next; + } else { + *fp->pending_parse = copyn(endtok,pt-endtok); + fp->pending_parse = NULL; + } +} + +static int hex(int ch1, int ch2) { + if ( ch1>='0' && ch1<='9' ) + ch1 -= '0'; + else if ( ch1>='a' ) + ch1 -= 'a'-10; + else + ch1 -= 'A'-10; + if ( ch2>='0' && ch2<='9' ) + ch2 -= '0'; + else if ( ch2>='a' ) + ch2 -= 'a'-10; + else + ch2 -= 'A'-10; +return( (ch1<<4)|ch2 ); +} + +unsigned short r; +#define c1 52845 +#define c2 22719 + +static void initcode(void) { + r = 55665; +} + +static int decode(unsigned char cypher) { + unsigned char plain = ( cypher ^ (r>>8)); + r = (cypher + r) * c1 + c2; +return( plain ); +} + +static void dumpzeros(FILE *out, unsigned char *zeros, int zcnt) { + while ( --zcnt >= 0 ) + fputc(*zeros++,out); +} + +static void decodestr(unsigned char *str, int len) { + unsigned short r = 4330; + unsigned char plain, cypher; + + while ( len-->0 ) { + cypher = *str; + plain = ( cypher ^ (r>>8)); + r = (cypher + r) * c1 + c2; + *str++ = plain; + } +} + +static void findstring(struct fontparse *fp,struct pschars *subrs,int index,char *nametok,char *str) { + char buffer[1024], *bpt, *bs, *end = buffer+sizeof(buffer)-1; + int val; + + while ( isspace(*str)) ++str; + if ( *str=='(' ) { + ++str; + bpt = buffer; + while ( *str!=')' && *str!='\0' ) { + if ( *str!='\\' ) + val = *str++; + else { + if ( isdigit( *++str )) { + val = *str++-'0'; + if ( isdigit( *str )) { + val = (val<<3) | (*str++-'0'); + if ( isdigit( *str )) + val = (val<<3) | (*str++-'0'); + } + } else + val = *str++; + } + if ( bpt<end ) + *bpt++ = val; + } + decodestr((unsigned char *) buffer,bpt-buffer); + bs = buffer + fp->fd->private->leniv; + if ( bpt<bs ) bs=bpt; /* garbage */ + subrs->lens[index] = bpt-bs; + subrs->keys[index] = copy(nametok); + subrs->values[index] = galloc(bpt-bs); + memcpy(subrs->values[index],bs,bpt-bs); + if ( index>=subrs->next ) subrs->next = index+1; + } +} + +/* Type42 charstrings are actually numbers */ +static void findnumbers(struct fontparse *fp,struct pschars *chars,char *str) { + int val; + char *end; + (void)fp; + forever { + int index = chars->next; + char *namestrt; + + while ( isspace(*str)) ++str; + if ( *str!='/' ) + break; + namestrt = ++str; + while ( isalnum(*str) || *str=='.' ) ++str; + *str = '\0'; + index = chars->next; + + ++str; + val = strtol(str,&end,10); + chars->lens[index] = 0; + chars->keys[index] = copy(namestrt); + chars->values[index] = (void *) (intpt) val; + chars->next = index+1; + str = end; + while ( isspace(*str)) ++str; + if ( str[0]=='d' && str[1]=='e' && str[2]=='f' ) + str += 3; + } +} + +static char *rmbinary(char *line) { + char *pt; + + for ( pt=line; *pt; ++pt ) { + if (( *pt<' ' || *pt>=0x7f ) && *pt!='\n' ) { + if ( strlen(pt)>5 ) { + pt[0] = '.'; + pt[1] = '.'; + pt[2] = '.'; + pt[3] = '\n'; + pt[4] = '\0'; + } else { + pt[0] = '\n'; + pt[1] = '\0'; + } + break; + } + } +return( line ); +} + +static void sfnts2tempfile(struct fontparse *fp,FILE *in,char *line) { + char *pt; + int instring = false, firstnibble=true, sofar=0, nibble; + int complained = false; + int ch=0; + + fp->sfnts = tmpfile(); + + /* first finish off anything in the current line */ + while ( (pt=strpbrk(line,"<]" ))!=NULL ) { + if ( *pt==']' ) + goto skip_to_eol; + + instring = true; + for ( ++pt; *pt && *pt!='>'; ++pt ) { + if ( isspace(*pt)) + continue; + if ( isdigit(*pt)) + nibble = *pt-'0'; + else if ( *pt>='a' && *pt<='f' ) + nibble = *pt-'a'+10; + else if ( *pt>='A' && *pt<='F' ) + nibble = *pt-'A'+10; + else { + if ( !complained ) { + LogError( _("Invalid hex digit in sfnts array\n") ); + complained = true; + } + ++pt; + continue; + } + if ( firstnibble ) { + sofar = nibble<<4; + firstnibble = false; + } else { + putc(sofar|nibble,fp->sfnts); + sofar = 0; + firstnibble = true; + } + } + if ( *pt=='>' ) { + if ( ftell(fp->sfnts)&1 ) { /* Strings must be contain an even number of bytes */ + /* But may be padded with a trailing NUL */ + fseek(fp->sfnts,-1,SEEK_CUR); + } + ++pt; + instring = false; + } + line = pt; + } + + while ( (ch=getc(in))!=EOF ) { + if ( ch==']' ) + goto skip_to_eol; + if ( isspace(ch)) + continue; + if ( !instring && ch=='<' ) { + instring = true; + firstnibble = true; + sofar = 0; + } else if ( !instring ) { + if ( !complained ) { + LogError( _("Invalid character outside of string in sfnts array\n") ); + complained = true; + } + } else if ( instring && ch=='>' ) { + if ( ftell(fp->sfnts)&1 ) { /* Strings must be contain an even number of bytes */ + /* But may be padded with a trailing NUL */ + fseek(fp->sfnts,-1,SEEK_CUR); + } + instring = false; + } else { + if ( isdigit(ch)) + nibble = ch-'0'; + else if ( ch>='a' && ch<='f' ) + nibble = ch-'a'+10; + else if ( ch>='A' && ch<='F' ) + nibble = ch-'A'+10; + else { + if ( !complained ) { + LogError( _("Invalid hex digit in sfnts array\n") ); + complained = true; + } + continue; + } + if ( firstnibble ) { + sofar = nibble<<4; + firstnibble = false; + } else { + putc(sofar|nibble,fp->sfnts); + sofar = 0; + firstnibble = true; + } + } + } + skip_to_eol: + while ( ch!=EOF && ch!='\n' && ch!='\r' ) + ch = getc(in); + rewind(fp->sfnts); +} + +static void ParseSimpleEncoding(struct fontparse *fp,char *line) { + char tok[200], *pt; + + while ( *line!='\0' && *line!=']' ) { + while ( isspace(*line)) ++line; + if ( *line==']' ) + break; + if ( *line!='/' ) { + ++line; + continue; + } + ++line; + while ( isspace(*line)) ++line; + for ( pt=tok; !isspace(*line) && *line!='\0' && *line!='/' && *line!=']'; ) { + if ( pt<tok+sizeof(tok)-2 ) + *pt++ = *line++; + else + ++line; + } + *pt = '\0'; + if ( fp->simple_enc_pos<256 ) + fp->fd->encoding[fp->simple_enc_pos++] = copy(tok); + } + if ( *line==']' ) { + fp->simpleencoding = false; + fp->inencoding = false; + } +} + +static void parseline(struct fontparse *fp,char *line,FILE *in) { + char buffer[200], *pt, *endtok; + + while ( *line==' ' || *line=='\t' ) ++line; + if ( line[0]=='%' && !fp->multiline ) +return; + + if ( fp->simpleencoding ) { + ParseSimpleEncoding(fp,line); +return; + } else if (( fp->inencoding && strncmp(line,"dup",3)==0 ) || + ( strncmp(line,"dup ",4)==0 && isdigit(line[4]) && + strstr(line+strlen(line)-6," put")!=NULL && strchr(line,'/')!=NULL )) { + /* Fontographer's type3 fonts claim to be standard, but then aren't */ + fp->fd->encoding_name = &custom; + /* Metamorphasis has multiple entries on a line */ + while ( strncmp(line,"dup",3)==0 ) { + char *end; + int pos = strtol(line+3,&end,10); + line = end; + while ( isspace( *line )) ++line; + if ( *line=='/' ) ++line; + for ( pt = buffer; !isspace(*line); *pt++ = *line++ ); + *pt = '\0'; + if ( pos>=0 && pos<256 ) { + free(fp->fd->encoding[pos]); + fp->fd->encoding[pos] = copy(buffer); + } + while ( isspace(*line)) ++line; + if ( strncmp(line,"put",3)==0 ) line+=3; + while ( isspace(*line)) ++line; + } +return; + } else if ( fp->inencoding && strstr(line,"for")!=NULL && strstr(line,"/.notdef")!=NULL ) { + /* the T1 spec I've got doesn't allow for this, but I've seen it anyway*/ + /* 0 1 255 {1 index exch /.notdef put} for */ + /* 0 1 31 { 1 index exch /.notdef put } bind for */ + int i; + for ( i=0; i<256; ++i ) + if ( fp->fd->encoding[i]==NULL ) + fp->fd->encoding[i] = copy(".notdef"); +return; + } else if ( fp->inencoding && strstr(line,"Encoding")!=NULL && strstr(line,"put")!=NULL ) { + /* Saw a type 3 font with lines like "Encoding 1 /_a0 put" */ + char *end; + int pos; + while ( isspace(*line)) ++line; + if ( strncmp(line,"Encoding ",9)==0 ) { + line+=9; + pos = strtol(line,&end,10); + line = end; + while ( isspace(*line)) ++line; + if ( *line=='/' ) { + ++line; + for ( pt = buffer; !isspace(*line); *pt++ = *line++ ); + *pt = '\0'; + if ( pos>=0 && pos<256 ) + fp->fd->encoding[pos] = copy(buffer); + } + } +return; + } else if ( fp->insubs ) { + struct pschars *subrs = fp->fd->private->subrs; + while ( isspace(*line)) ++line; + if ( strncmp(line,"dup ",4)==0 ) { + int i; + char *ept; + for ( line += 4; *line==' '; ++line ); + i = strtol(line,&ept,10); + if ( fp->ignore ) + /* Do Nothing */; + else if ( i<subrs->cnt ) { + findstring(fp,subrs,i,NULL,ept); + } else if ( !fp->alreadycomplained ) { + LogError( _("Index too big (must be <%d) \"%s"), subrs->cnt, rmbinary(line)); + fp->alreadycomplained = true; + } + } else if ( strncmp(line, "readonly put", 12)==0 || strncmp(line, "ND", 2)==0 || strncmp(line, "|-", 2)==0 ) { + fp->insubs = false; + fp->ignore = false; + } else if ( *line=='\n' || *line=='\0' ) { + /* Ignore blank lines */; + } else if ( !fp->alreadycomplained ) { + LogError( _("Didn't understand \"%s"), rmbinary(line) ); + fp->alreadycomplained = true; + } + } else if ( fp->inchars ) { + struct pschars *chars = fp->fd->chars; + while ( isspace(*line)) ++line; + if ( strncmp(line,"end",3)==0 ) + fp->ignore = fp->inchars = false; + else if ( *line=='\n' || *line=='\0' ) + /* Ignore it */; + else if ( *line!='/' || !(isalpha(line[1]) || line[1]=='.')) { + LogError( _("No name for CharStrings dictionary \"%s"), rmbinary(line) ); + fp->alreadycomplained = true; + } else if ( fp->ignore ) { + /* Do Nothing */; + } else if ( chars->next>=chars->cnt ) + LogError( _("Too many entries in CharStrings dictionary \"%s"), rmbinary(line) ); + else if ( fp->fd->fonttype==42 || fp->fd->fonttype==11 || fp->fd->cidfonttype==2 ) + findnumbers(fp,chars,line); + else { + int i = chars->next; + char *namestrt = ++line; + while ( isalnum(*line) || *line=='.' ) ++line; + *line = '\0'; + findstring(fp,chars,i,namestrt,line+1); + ff_progress_next(); + } +return; + } + fp->inencoding = 0; + + while ( isspace(*line)) ++line; + endtok = NULL; + if ( *line=='/' ) + for ( endtok=line+1; !isspace(*endtok) && *endtok!='(' && *endtok!='/' && + *endtok!='{' && *endtok!='[' && *endtok!='\0'; ++endtok ); + + if ( strstr(line,"/shareddict")!=NULL && strstr(line,"where")!=NULL ) { + fp->infi = fp->inbb = fp->inmetrics = fp->inmetrics2 = false; + fp->inprivate = fp->inblendprivate = fp->inblendfi = false; + fp->skipping_mbf = true; +return; + } + + if ( mycmp("Encoding",line+1,endtok)==0 && !fp->doneencoding ) { + if ( strstr(endtok,"StandardEncoding")!=NULL ) { + fp->fd->encoding_name = FindOrMakeEncoding("AdobeStandard"); + setStdEnc(fp->fd->encoding); + } else if ( strstr(endtok,"ISOLatin1Encoding")!=NULL ) { + fp->fd->encoding_name = FindOrMakeEncoding("ISO8859-1"); + setLatin1Enc(fp->fd->encoding); + } else { + fp->fd->encoding_name = &custom; + fp->inencoding = 1; + } + if ( fp->fd->encoding_name==NULL ) + fp->fd->encoding_name = &custom; + fp->infi = fp->inprivate = fp->inbb = fp->inmetrics = fp->inmetrics2 = false; + fp->doneencoding = true; + while ( *endtok==' ' || *endtok=='\t' ) ++endtok; + if ( *endtok=='[' ) { /* It's a literal array */ + fp->simpleencoding = true; + fp->simple_enc_pos = 0; + ParseSimpleEncoding(fp,endtok+1); + } + } else if ( mycmp("BoundingBoxes",line+1,endtok)==0 ) { + fp->infi = fp->inprivate = fp->inencoding = fp->inmetrics = fp->inmetrics2 = false; + fp->inbb = true; + } else if ( mycmp("Metrics",line+1,endtok)==0 ) { + fp->infi = fp->inprivate = fp->inbb = fp->inencoding = fp->inmetrics2 = false; + fp->inmetrics = true; + fp->fd->metrics = gcalloc(1,sizeof(struct psdict)); + fp->fd->metrics->cnt = strtol(endtok,NULL,10); + fp->fd->metrics->keys = galloc(fp->fd->metrics->cnt*sizeof(char *)); + fp->fd->metrics->values = galloc(fp->fd->metrics->cnt*sizeof(char *)); + } else if ( strstr(line,"/Private")!=NULL && strstr(line,"/Blend")!=NULL ) { + fp->infi = fp->inbb = fp->inmetrics = fp->inmetrics2 = false; + fp->inprivate = fp->inblendprivate = fp->inblendfi = false; + fp->inblendprivate = 1; + fp->fd->blendprivate = gcalloc(1,sizeof(struct psdict)); + InitDict(fp->fd->blendprivate,line); +return; + } else if ( strstr(line,"/FontInfo")!=NULL && strstr(line,"/Blend")!=NULL ) { + fp->infi = fp->inbb = fp->inmetrics = fp->inmetrics2 = false; + fp->inprivate = fp->inblendprivate = fp->inblendfi = false; + fp->inblendfi = 1; + fp->fd->blendfontinfo = gcalloc(1,sizeof(struct psdict)); + InitDict(fp->fd->blendfontinfo,line); +return; + } else if ( fp->infi ) { + if ( fp->multiline ) { + ContinueValue(fp,NULL,line); +return; + } + if ( endtok==NULL && (strncmp(line,"end", 3)==0 || strncmp(line,">>",2)==0)) { + fp->infi=0; +return; + } else if ( endtok==NULL ) +return; + if ( mycmp("version",line+1,endtok)==0 ) { + free(fp->fd->fontinfo->version); + fp->fd->fontinfo->version = getstring(endtok,in); + } else if ( mycmp("Notice",line+1,endtok)==0 ) { + if ( fp->fd->fontinfo->notice!=NULL ) + free(fp->fd->fontinfo->notice); + fp->fd->fontinfo->notice = getstring(endtok,in); + } else if ( mycmp("Copyright",line+1,endtok)==0 ) { /* cff spec allows for copyright and notice */ + if ( fp->fd->fontinfo->notice!=NULL ) + free(fp->fd->fontinfo->notice); + fp->fd->fontinfo->notice = getstring(endtok,in); + } else if ( mycmp("FullName",line+1,endtok)==0 ) { + if ( fp->fd->fontinfo->fullname==NULL ) + fp->fd->fontinfo->fullname = getstring(endtok,in); + else + free(getstring(endtok,in)); + } else if ( mycmp("FamilyName",line+1,endtok)==0 ) { + free( fp->fd->fontinfo->familyname ); + fp->fd->fontinfo->familyname = getstring(endtok,in); + } else if ( mycmp("Weight",line+1,endtok)==0 ) { + free( fp->fd->fontinfo->weight ); + fp->fd->fontinfo->weight = getstring(endtok,in); + } else if ( mycmp("ItalicAngle",line+1,endtok)==0 ) + fp->fd->fontinfo->italicangle = strtod(endtok,NULL); + else if ( mycmp("UnderlinePosition",line+1,endtok)==0 ) + fp->fd->fontinfo->underlineposition = strtod(endtok,NULL); + else if ( mycmp("UnderlineThickness",line+1,endtok)==0 ) + fp->fd->fontinfo->underlinethickness = strtod(endtok,NULL); + else if ( mycmp("isFixedPitch",line+1,endtok)==0 ) + fp->fd->fontinfo->isfixedpitch = getbool(endtok); + else if ( mycmp("em",line+1,endtok)==0 ) + fp->fd->fontinfo->em = strtol(endtok,NULL,10); + else if ( mycmp("ascent",line+1,endtok)==0 ) + fp->fd->fontinfo->ascent = strtol(endtok,NULL,10); + else if ( mycmp("descent",line+1,endtok)==0 ) + fp->fd->fontinfo->descent = strtol(endtok,NULL,10); + else if ( mycmp("FSType",line+1,endtok)==0 ) + fp->fd->fontinfo->fstype = strtol(endtok,NULL,10); + else if ( mycmp("BlendDesignPositions",line+1,endtok)==0 ) { + fp->pending_parse = &fp->fd->fontinfo->blenddesignpositions; + AddValue(fp,NULL,line,endtok); + } else if ( mycmp("BlendDesignMap",line+1,endtok)==0 ) { + fp->pending_parse = &fp->fd->fontinfo->blenddesignmap; + AddValue(fp,NULL,line,endtok); + } else if ( mycmp("BlendAxisTypes",line+1,endtok)==0 ) { + fp->pending_parse = &fp->fd->fontinfo->blendaxistypes; + AddValue(fp,NULL,line,endtok); + } else if ( !fp->alreadycomplained ) { + LogError( _("Didn't understand \"%s"), rmbinary(line) ); + fp->alreadycomplained = true; + } + } else if ( fp->inblend ) { + if ( endtok==NULL ) { + if ( *line!='/' && strstr(line,"end")!=NULL ) + fp->inblend = false; +return; + } + /* Ignore anything in the blend dict defn */ + } else if ( fp->inblendprivate || fp->inblendfi ) { + struct psdict *subdict = fp->inblendfi ? fp->fd->blendfontinfo : fp->fd->blendprivate; + if ( fp->multiline ) { + ContinueValue(fp,subdict,line); +return; + } else if ( endtok==NULL ) { + if ( *line!='/' && strstr(line,"end")!=NULL ) { + fp->inblendprivate = fp->inblendfi = false; + fp->inprivate = true; + } +return; + } else + AddValue(fp,subdict,line,endtok); + } else if ( fp->inprivate ) { + if ( strstr(line,"/CharStrings")!=NULL && strstr(line,"dict")!=NULL ) { + if ( fp->fd->chars->next==0 ) { + InitChars(fp->fd->chars,line); + fp->ignore = false; + } else { + fp->ignore = true; + LogError( _("Ignoring duplicate /CharStrings entry\n") ); + } + fp->inchars = 1; + fp->insubs = 0; +return; + } else if ( strstr(line,"/Subrs")!=NULL ) { + if ( fp->fd->private->subrs->next>0 ) { + fp->ignore = true; + LogError( _("Ignoring duplicate /Subrs entry\n") ); + } else { + InitChars(fp->fd->private->subrs,line); + fp->ignore = false; + } + fp->insubs = 1; + fp->inchars = 0; +return; + } else if ( fp->multiline ) { + ContinueValue(fp,fp->fd->private->private,line); +return; + } + if ( endtok==NULL ) { + char *pt = line; + if ( *pt!='/' ) while ( (pt=strstr(pt,"end"))!=NULL ) { + if ( fp->inchars ) fp->inchars = false; + else fp->inprivate = false; + pt += 3; + } +return; + } + if ( mycmp("ND",line+1,endtok)==0 || mycmp("|-",line+1,endtok)==0 || + mycmp("NP",line+1,endtok)==0 || mycmp("|",line+1,endtok)==0 || + mycmp("RD",line+1,endtok)==0 || mycmp("-|",line+1,endtok)==0 || + mycmp("password",line+1,endtok)==0 || + mycmp("MinFeature",line+1,endtok)==0 ) + /* These conveigh no information, but are required */; + else if ( mycmp("UniqueID",line+1,endtok)==0 ) { + if ( fp->fd->uniqueid==0 ) + fp->fd->uniqueid = strtol(endtok,NULL,10); + } else { + if ( mycmp("lenIV",line+1,endtok)==0 ) + fp->fd->private->leniv = strtol(endtok,NULL,10); /* We need this value */ + AddValue(fp,fp->fd->private->private,line,endtok); + } + } else if ( fp->incidsysteminfo ) { + if ( endtok==NULL && strncmp(line,"end", 3)==0 ) { + fp->incidsysteminfo=0; +return; + } else if ( endtok==NULL ) +return; + if ( mycmp("Registry",line+1,endtok)==0 ) { + free( fp->fd->registry ); + fp->fd->registry = getstring(endtok,in); + } else if ( mycmp("Ordering",line+1,endtok)==0 ) { + free( fp->fd->ordering ); + fp->fd->ordering = getstring(endtok,in); + } else if ( mycmp("Supplement",line+1,endtok)==0 ) /* cff spec allows for copyright and notice */ + fp->fd->supplement = strtol(endtok,NULL,0); + } else { + if ( strstr(line,"/Private")!=NULL && (strstr(line,"dict")!=NULL || strstr(line,"<<")!=NULL )) { + fp->infi = fp->inbb = fp->inmetrics = fp->inmetrics2 = false; + fp->inprivate = fp->inblendprivate = fp->inblendfi = false; + if ( strstr(line,"/Blend")!=NULL ) { + fp->inblendprivate = 1; + fp->fd->blendprivate = gcalloc(1,sizeof(struct psdict)); + InitDict(fp->fd->blendprivate,line); + } else { + fp->inprivate = 1; + InitDict(fp->fd->private->private,line); + } +return; + } else if ( strstr(line,"/FontInfo")!=NULL && (strstr(line,"dict")!=NULL || strstr(line,"<<")!=NULL)) { + fp->inprivate = fp->inbb = fp->inmetrics = fp->inmetrics2 = false; + fp->infi = fp->inblendprivate = fp->inblendfi = false; + if ( strstr(line,"/Blend")!=NULL ) { + fp->inblendfi = 1; + fp->fd->blendfontinfo = gcalloc(1,sizeof(struct psdict)); + InitDict(fp->fd->blendfontinfo,line); + } else { + fp->infi = 1; + } +return; + } else if ( strstr(line,"/Blend")!=NULL && strstr(line,"dict")!=NULL ) { + fp->inprivate = fp->inbb = fp->inmetrics = fp->inmetrics2 = false; + fp->infi = fp->inblendprivate = fp->inblendfi = false; + fp->inblend = true; +return; + } else if ( strstr(line,"/sfnts")!=NULL && strstr(line,"[")!=NULL ) { + sfnts2tempfile(fp,in,line); +return; + } else if ( strstr(line,"/CharStrings")!=NULL && strstr(line,"dict")!=NULL + && fp->fd->fonttype!=3 ) { + if ( fp->fd->chars->next==0 ) { + InitChars(fp->fd->chars,line); + fp->ignore = false; + } else { + fp->ignore = true; + LogError( _("Ignoring duplicate /CharStrings entry\n") ); + } + fp->inchars = 1; + fp->insubs = 0; + fp->infi = fp->inprivate = fp->inbb = fp->inmetrics = fp->inmetrics2 = false; + fp->inblendprivate = fp->inblendfi = false; +return; + } else if ( mycmp("/CharProcs",line,endtok)==0 ) { + InitCharProcs(fp->fd->charprocs,line); + fp->infi = fp->inprivate = fp->inbb = fp->inmetrics = fp->inmetrics2 = false; + fp->insubs = 0; +return; + } else if ( strstr(line,"/CIDSystemInfo")!=NULL ) { + fp->incidsysteminfo = 1; +return; + } else if ( fp->inmetrics ) { + if ( endtok!=NULL ) + AddValue(fp,fp->fd->metrics,line,endtok); +return; + } else if ( fp->inbb ) { + /* Ignore it */; +return; + } + + if ( fp->multiline ) { + ContinueValue(fp,NULL,line); +return; + } + + if ( endtok==NULL ) { + if ( fp->skipping_mbf ) + ; + else if ( fp->fdindex!=-1 && strstr(line,"end")!=NULL ) { + if ( ++fp->fdindex>=fp->mainfd->fdcnt ) + fp->fd = fp->mainfd; + else + fp->fd = fp->mainfd->fds[fp->fdindex]; + } +return; + } + if ( mycmp("FontName",line+1,endtok)==0 ) { + if ( fp->fd->fontname==NULL ) + fp->fd->fontname = gettoken(endtok); + else + free(gettoken(endtok)); /* skip it */ + } else if ( mycmp("PaintType",line+1,endtok)==0 ) + fp->fd->painttype = strtol(endtok,NULL,10); + else if ( mycmp("FontType",line+1,endtok)==0 ) + fp->fd->fonttype = strtol(endtok,NULL,10); + else if ( mycmp("FontMatrix",line+1,endtok)==0 ) { + if ( fp->fd->fontmatrix[0]==0 ) + fillrealarray(fp->fd->fontmatrix,endtok,6); + else { + real temp[6]; + fillrealarray(temp,endtok,6); + } + } else if ( mycmp("LanguageLevel",line+1,endtok)==0 ) + fp->fd->languagelevel = strtol(endtok,NULL,10); + else if ( mycmp("WMode",line+1,endtok)==0 ) + fp->fd->wmode = strtol(endtok,NULL,10); + else if ( mycmp("FontBBox",line+1,endtok)==0 ) + fillrealarray(fp->fd->fontbb,endtok,4); + else if ( mycmp("UniqueID",line+1,endtok)==0 ) { + if ( fp->fd->uniqueid==0 ) + fp->fd->uniqueid = strtol(endtok,NULL,10); + } else if ( mycmp("UniqueId",line+1,endtok)==0 ) { + LogError(_("This font contains a \"UniqueId\" variable, but the correct name for it is\n\t\"UniqueID\" (postscript is case concious)\n") ); + if ( fp->fd->uniqueid==0 ) + fp->fd->uniqueid = strtol(endtok,NULL,10); + } else if ( mycmp("XUID",line+1,endtok)==0 ) { + if ( fp->fd->xuid[0]==0 ) + fillintarray(fp->fd->xuid,endtok,20); + } else if ( mycmp("StrokeWidth",line+1,endtok)==0 ) + fp->fd->strokewidth = strtod(endtok,NULL); + else if ( mycmp("WeightVector",line+1,endtok)==0 ) { + if ( fp->fd->weightvector==NULL ) { + fp->pending_parse = &fp->fd->weightvector; + AddValue(fp,NULL,line,endtok); + } + } else if ( mycmp("$Blend",line+1,endtok)==0 ) { + fp->pending_parse = &fp->fd->blendfunc; + AddValue(fp,NULL,line,endtok); + } else if ( strstr( line,"/NormalizeDesignVector" )!=NULL ) { + fp->pending_parse = &fp->fd->ndv; + AddValue(fp,NULL,line,endtok); + } else if ( strstr( line,"/ConvertDesignVector" )!=NULL ) { + fp->pending_parse = &fp->fd->cdv; + AddValue(fp,NULL,line,endtok); + } else if ( mycmp("BuildChar",line+1,endtok)==0 ) + /* Do Nothing */; + else if ( mycmp("BuildGlyph",line+1,endtok)==0 ) + /* Do Nothing */; + else if ( mycmp("CIDFontName",line+1,endtok)==0 ) { + free( fp->fd->cidfontname ); + fp->fd->cidfontname = gettoken(endtok); + } else if ( mycmp("CIDFontVersion",line+1,endtok)==0 ) { + fp->fd->cidversion = strtod(endtok,NULL); +#if 0 + if ( fp->fd->fontinfo->version==NULL ) { + char temp[40]; + sprintf(temp,"%f", fp->fd->cidversion); + fp->fd->fontinfo->version = copy(temp); + } +#endif + } else if ( mycmp("CIDFontType",line+1,endtok)==0 ) + fp->fd->cidfonttype = strtol(endtok,NULL,10); + else if ( mycmp("UIDBase",line+1,endtok)==0 ) + fp->fd->uniqueid = strtol(endtok,NULL,10); + else if ( mycmp("CIDMapOffset",line+1,endtok)==0 ) + fp->fd->mapoffset = strtol(endtok,NULL,10); + else if ( mycmp("FDBytes",line+1,endtok)==0 ) + fp->fd->fdbytes = strtol(endtok,NULL,10); + else if ( mycmp("GDBytes",line+1,endtok)==0 ) + fp->fd->gdbytes = strtol(endtok,NULL,10); + else if ( mycmp("CIDCount",line+1,endtok)==0 ) + fp->fd->cidcnt = strtol(endtok,NULL,10); + else if ( mycmp("FDArray",line+1,endtok)==0 ) { int i; + fp->mainfd = fp->fd; + fp->fd->fdcnt = strtol(endtok,NULL,10); + fp->fd->fds = gcalloc(fp->fd->fdcnt,sizeof(struct fontdict *)); + for ( i=0; i<fp->fd->fdcnt; ++i ) + fp->fd->fds[i] = MakeEmptyFont(); + fp->fdindex = 0; + fp->fd = fp->fd->fds[0]; + } else if ( mycmp("FontSetInit",line+1,endtok)==0 ) { + fp->iscff = true; + fp->iscid = false; + } else if ( mycmp("CIDInit",line+1,endtok)==0 ) { + fp->iscid = true; + fp->iscff = false; + } else if ( fp->skipping_mbf ) { /* Skip over the makeblendedfont defn in a multimaster font */ + /* Do Nothing */ + } else if ( !fp->alreadycomplained ) { + LogError( _("Didn't understand \"%s"), rmbinary(line) ); + fp->alreadycomplained = true; + } + } +} + +static void addinfo(struct fontparse *fp,char *line,char *tok,char *binstart,int binlen,FILE *in) { + char *pt; + + decodestr((unsigned char *) binstart,binlen); + binstart += fp->fd->private->leniv; + binlen -= fp->fd->private->leniv; + if ( binlen<0 ) { + LogError( _("Bad CharString. Does not include lenIV bytes.\n") ); +return; + } + + retry: + if ( fp->insubs ) { + struct pschars *chars = /*fp->insubs ?*/ fp->fd->private->subrs /*: fp->fd->private->othersubrs*/; + while ( isspace(*line)) ++line; + if ( strncmp(line,"dup ",4)==0 ) { + int i = strtol(line+4,NULL,10); + if ( fp->ignore ) + /* Do Nothing */; + else if ( i<chars->cnt ) { + if ( chars->values[i]!=NULL ) + LogError( _("Duplicate definition of subroutine %d\n"), i ); + chars->lens[i] = binlen; + chars->values[i] = galloc(binlen); + memcpy(chars->values[i],binstart,binlen); + if ( i>=chars->next ) chars->next = i+1; + } else if ( !fp->alreadycomplained ) { + LogError( _("Index too big (must be <%d) \"%s"), chars->cnt, rmbinary(line)); + fp->alreadycomplained = true; + } + } else if ( !fp->alreadycomplained ) { + LogError( _("Didn't understand \"%s"), rmbinary(line) ); + fp->alreadycomplained = true; + } + } else if ( fp->inchars ) { + struct pschars *chars = fp->fd->chars; + if ( *tok=='\0' ) + LogError( _("No name for CharStrings dictionary \"%s"), rmbinary(line) ); + else if ( fp->ignore ) + /* Do Nothing */; + else if ( chars->next>=chars->cnt ) + LogError( _("Too many entries in CharStrings dictionary \"%s"), rmbinary(line) ); + else { + int i = chars->next; + chars->lens[i] = binlen; + chars->keys[i] = copy(tok); + chars->values[i] = galloc(binlen); + memcpy(chars->values[i],binstart,binlen); + ++chars->next; + ff_progress_next(); + } + } else if ( !fp->alreadycomplained ) { + /* Special hacks for known badly formatted fonts */ + if ( strstr(line,"/CharStrings")!=NULL ) { + for ( pt=line; *pt!='/'; ++pt ); + pt = strchr(pt+1,'/'); + if ( pt!=NULL ) + *pt = '\0'; + parseline(fp,line,in); + if ( pt!=NULL ) { + *pt = '/'; + line = pt; + goto retry; + } +return; + } else if ( strstr(line,"/Subrs")!=NULL ) { + pt = strstr(line,"dup"); + if ( pt!=NULL ) + *pt = '\0'; + parseline(fp,line,in); + if ( pt!=NULL ) { + *pt = 'd'; + line = pt; + goto retry; + } +return; + } + LogError( _("Shouldn't be in addinfo \"%s"), rmbinary(line) ); + fp->alreadycomplained = true; + } +} + +/* In the book the token which starts a character description is always RD but*/ +/* it's just the name of a subroutine which is defined in the private diction*/ +/* and it could be anything. in one case it was "-|" (hyphen bar) so we can't*/ +/* just look for RD we must be a bit smarter and figure out what the token is*/ +/* (oh. I see now. it's allowed to be either one "RD" or "-|", but nothing else*/ +/* right) */ +/* It's defined as {string currentfile exch readstring pop} so look for that */ +/* Except that in gsf files we've also got "/-!{string currentfile exch readhexstring pop} readonly def" */ +/* NOTE: readhexstring!!! */ +/* And in files generated by GNU fontutils */ +static int glorpline(struct fontparse *fp, FILE *temp, char *rdtok) { + static char *buffer=NULL, *end; + char *pt, *binstart; + int binlen; + int ch; + int innum, val=0, inbinary, cnt=0, inr, wasspace, nownum, nowr, nowspace, sptok; + char *rdline = "{string currentfile exch readstring pop}", *rpt; + char *rdline2 = "{string currentfile exch readhexstring pop}"; + char *tokpt = NULL, *rdpt; + char temptok[255]; + int intok, first; + int wasminus=false, isminus, nibble=0, firstnibble=true, inhex; + int willbehex = false; + + ch = getc(temp); + if ( ch==EOF ) +return( 0 ); + ungetc(ch,temp); + + if ( buffer==NULL ) { + buffer = galloc(3000); + end = buffer+3000; + } + innum = inr = 0; wasspace = 0; inbinary = 0; rpt = NULL; rdpt = NULL; + inhex = 0; + pt = buffer; binstart=NULL; binlen = 0; intok=0; sptok=0; first=1; + temptok[0] = '\0'; + while ( (ch=getc(temp))!=EOF ) { + if ( pt>=end ) { + char *old = buffer; + int len = (end-buffer)+2000; + buffer = grealloc(buffer,len); + end = buffer+len; + pt = buffer+(pt-old); + if ( binstart!=NULL ) + binstart = buffer+(binstart-old); + } + *pt++ = ch; + isminus = ch=='-' && wasspace; + nownum = nowspace = nowr = 0; + if ( rpt!=NULL && ch!=*rpt && ch=='h' && rpt-rdline>25 && rpt-rdline<30 && + rdline2[rpt-rdline]=='h' ) { + rpt = rdline2 + (rpt-rdline); + willbehex = true; + } + if ( inbinary ) { + if ( --cnt==0 ) + inbinary = 0; + } else if ( inhex ) { + if ( ishexdigit(ch)) { + int h; + if ( isdigit(ch)) h = ch-'0'; + else if ( ch>='a' && ch<='f' ) h = ch-'a'+10; + else h = ch-'A'+10; + if ( firstnibble ) { + nibble = h; + --pt; + } else { + pt[-1] = (nibble<<4)|h; + if ( --cnt==0 ) + inbinary = inhex = 0; + } + firstnibble = !firstnibble; + } else { + --pt; + /* skip everything not hex */ + } + } else if ( ch=='/' ) { + intok = 1; + tokpt = temptok; + } else if ( intok && !isspace(ch) && ch!='{' && ch!='[' ) { + *tokpt++ = ch; + } else if ( (intok||sptok) && (ch=='{' || ch=='[')) { + *tokpt = '\0'; + rpt = rdline+1; + intok = sptok = 0; + } else if ( intok ) { + *tokpt = '\0'; + intok = 0; + sptok = 1; + } else if ( sptok && isspace(ch)) { + nowspace = 1; + if ( ch=='\n' || ch=='\r' ) + break; + } else if ( sptok && !isdigit(ch)) + sptok = 0; + else if ( rpt!=NULL && ch==*rpt ) { + if ( *++rpt=='\0' ) { + /* it matched the character definition string so this is the */ + /* token we want to search for */ + strcpy(rdtok,temptok); + fp->useshexstrings = willbehex; + rpt = NULL; + } + } else if ( rpt!=NULL && ch==' ' ) { + /* Extra spaces are ok */ + } else if ( rpt!=NULL ) { + rpt = NULL; + willbehex = false; + } else if ( isdigit(ch)) { + sptok = 0; + nownum = 1; + if ( innum ) + val = 10*val + ch-'0'; + else + val = ch-'0'; + } else if ( isspace(ch)) { + nowspace = 1; + if ( ch=='\n' || ch=='\r' ) + break; + } else if ( wasspace && ch==*rdtok ) { + nowr = 1; + fp->useshexstrings = willbehex; + rdpt = rdtok+1; + } else if ( wasspace && ch=='-' ) { /* fonts produced by type1fix seem to define both "RD" and "-|" which confused me. so just respond to either */ + nowr = 1; + fp->useshexstrings = false; + rdpt = "|"; + } else if ( wasspace && ch=='R' ) { /* fonts produced by type1fix seem to define both "RD" and "-|" which confused me. so just respond to either */ + nowr = 1; + fp->useshexstrings = false; + rdpt = "D"; + } else if ( inr && ch==*rdpt ) { + if ( *++rdpt =='\0' ) { + ch = getc(temp); + *pt++ = ch; + if ( isspace(ch) && val!=0 ) { + inhex = fp->useshexstrings; + inbinary = !fp->useshexstrings; + firstnibble = true; + cnt = val; + binstart = pt; + binlen = val; + } + } else + nowr = 1; + } else if ( wasminus && ch=='!' ) { + ch = getc(temp); + *pt++ = ch; + if ( isspace(ch) && val!=0 ) { + inhex = 1; + cnt = val; + binstart = pt; + binlen = val; + firstnibble = true; + } + } + innum = nownum; wasspace = nowspace; inr = nowr; + wasminus = isminus; + first = 0; + } + *pt = '\0'; + if ( binstart==NULL ) { + parseline(fp,buffer,temp); + } else { + addinfo(fp,buffer,temptok,binstart,binlen,temp); + } +return( 1 ); +} + +static int nrandombytes[4]; +#define EODMARKLEN 16 + +#define bgetc(extra,in) (*(extra)=='\0' ? getc(in) : (unsigned char ) *(extra)++ ) + +static void decrypteexec(FILE *in,FILE *temp, int hassectionheads,char *extra) { + int ch1, ch2, ch3, ch4, binary; + int zcnt; + unsigned char zeros[EODMARKLEN+6+1]; + int sect_len=0x7fffffff; + + if ( extra==(void *) 5 ) extra = ""; + + /* The PLRM defines white space to include form-feed and null. The t1_spec*/ + /* does not. The t1_spec wins here. Someone gave me a font which began */ + /* with a formfeed and that was part of the encrypted body */ + while ( (ch1=bgetc(extra,in))!=EOF && (ch1==' ' || ch1=='\t' || ch1=='\n' || ch1=='\r')); + if ( ch1==0200 && hassectionheads ) { + /* skip the 6 byte section header in pfb files that follows eexec */ + ch1 = bgetc(extra,in); + sect_len = bgetc(extra,in); + sect_len |= bgetc(extra,in)<<8; + sect_len |= bgetc(extra,in)<<16; + sect_len |= bgetc(extra,in)<<24; + sect_len -= 3; + ch1 = bgetc(extra,in); + } + ch2 = bgetc(extra,in); ch3 = bgetc(extra,in); ch4 = bgetc(extra,in); + binary = 0; + if ( ch1<'0' || (ch1>'9' && ch1<'A') || ( ch1>'F' && ch1<'a') || (ch1>'f') || + ch2<'0' || (ch2>'9' && ch2<'A') || (ch2>'F' && ch2<'a') || (ch2>'f') || + ch3<'0' || (ch3>'9' && ch3<'A') || (ch3>'F' && ch3<'a') || (ch3>'f') || + ch4<'0' || (ch4>'9' && ch4<'A') || (ch4>'F' && ch4<'a') || (ch4>'f') ) + binary = 1; + if ( ch1==EOF || ch2==EOF || ch3==EOF || ch4==EOF ) { +return; + } + + initcode(); + if ( binary ) { + nrandombytes[0] = decode(ch1); + nrandombytes[1] = decode(ch2); + nrandombytes[2] = decode(ch3); + nrandombytes[3] = decode(ch4); + zcnt = 0; + while (( ch1=bgetc(extra,in))!=EOF ) { + --sect_len; + if ( hassectionheads ) { + if ( sect_len==0 && ch1==0200 ) { + ch1 = bgetc(extra,in); + sect_len = bgetc(extra,in); + sect_len |= bgetc(extra,in)<<8; + sect_len |= bgetc(extra,in)<<16; + sect_len |= bgetc(extra,in)<<24; + sect_len += 1; + if ( ch1=='\1' ) + break; + } else { + dumpzeros(temp,zeros,zcnt); + zcnt = 0; + putc(decode(ch1),temp); + } + } else { + if ( ch1=='0' ) ++zcnt; else {dumpzeros(temp,zeros,zcnt); zcnt = 0; } + if ( zcnt>EODMARKLEN ) + break; + if ( zcnt==0 ) + putc(decode(ch1),temp); + else + zeros[zcnt-1] = decode(ch1); + } + } + } else { + nrandombytes[0] = decode(hex(ch1,ch2)); + nrandombytes[1] = decode(hex(ch3,ch4)); + ch1 = bgetc(extra,in); ch2 = bgetc(extra,in); ch3 = bgetc(extra,in); ch4 = bgetc(extra,in); + nrandombytes[2] = decode(hex(ch1,ch2)); + nrandombytes[3] = decode(hex(ch3,ch4)); + zcnt = 0; + while (( ch1=bgetc(extra,in))!=EOF ) { + while ( ch1!=EOF && isspace(ch1)) ch1 = bgetc(extra,in); + while ( (ch2=bgetc(extra,in))!=EOF && isspace(ch2)); + if ( ch1=='0' && ch2=='0' ) ++zcnt; else { dumpzeros(temp,zeros,zcnt); zcnt = 0;} + if ( zcnt>EODMARKLEN ) + break; + if ( zcnt==0 ) + putc(decode(hex(ch1,ch2)),temp); + else + zeros[zcnt-1] = decode(hex(ch1,ch2)); + } + } + while (( ch1=bgetc(extra,in))=='0' || isspace(ch1) ); + if ( ch1!=EOF ) ungetc(ch1,in); +} + +static void decryptagain(struct fontparse *fp,FILE *temp,char *rdtok) { + while ( glorpline(fp,temp,rdtok)); +} + +static void parsetype3(struct fontparse *fp,FILE *in) { + PSFontInterpretPS(in,fp->fd->charprocs,fp->fd->encoding ); +} + +static unsigned char *readt1str(FILE *temp,int offset,int len,int leniv) { + int i; + unsigned char *str, *pt; + unsigned short r = 4330; + unsigned char plain, cypher; + /* The CID spec doesn't mention this, but the type 1 strings are all */ + /* eexec encrupted (with the nested encryption). Remember leniv varies */ + /* from fd to fd (potentially) */ + /* I'm told (by Ian Kemmish) that leniv==-1 => no eexec encryption */ + + fseek(temp,offset,SEEK_SET); + if ( leniv<0 ) { + str = pt = galloc(len+1); + for ( i=0 ; i<len; ++i ) + *pt++ = getc(temp); + } else { + for ( i=0; i<leniv; ++i ) { + cypher = getc(temp); + plain = ( cypher ^ (r>>8)); + r = (cypher + r) * c1 + c2; + } + str = pt = galloc(len-leniv+1); + for (; i<len; ++i ) { + cypher = getc(temp); + plain = ( cypher ^ (r>>8)); + r = (cypher + r) * c1 + c2; + *pt++ = plain; + } + } + *pt = '\0'; +return( str ); +} + +static void figurecids(struct fontparse *fp,FILE *temp) { + struct fontdict *fd = fp->mainfd; + int i,j,k,val; + int *offsets; + int cidcnt = fd->cidcnt; + int leniv; + /* Some cid formats don't have any of these */ + + fd->cidstrs = galloc(cidcnt*sizeof(uint8 *)); + fd->cidlens = galloc(cidcnt*sizeof(int16)); + fd->cidfds = galloc((cidcnt+1)*sizeof(int16)); + offsets = galloc((cidcnt+1)*sizeof(int)); + ff_progress_change_total(cidcnt); + + fseek(temp,fd->mapoffset,SEEK_SET); + for ( i=0; i<=fd->cidcnt; ++i ) { + for ( j=val=0; j<fd->fdbytes; ++j ) + val = (val<<8) + getc(temp); + if ( val >= fd->fdcnt && val!=255 ) { /* 255 is a special mark */ + LogError( _("Invalid FD (%d) assigned to CID %d.\n"), val, i ); + val = 0; + } + fd->cidfds[i] = val; + for ( j=val=0; j<fd->gdbytes; ++j ) + val = (val<<8) + getc(temp); + offsets[i] = val; + if ( i!=0 ) { + fd->cidlens[i-1] = offsets[i]-offsets[i-1]; + if ( fd->cidlens[i-1]<0 ) { + LogError( _("Bad CID offset for CID %d\n"), i-1 ); + fd->cidlens[i-1] = 0; + } + } + } + + for ( i=0; i<fd->cidcnt; ++i ) { + if ( fd->cidlens[i]== 0 ) + fd->cidstrs[i] = NULL; + else { + fd->cidstrs[i] = readt1str(temp,offsets[i],fd->cidlens[i], + fd->fds[fd->cidfds[i]]->private->leniv); + fd->cidlens[i] -= fd->fds[fd->cidfds[i]]->private->leniv; + } + ff_progress_next(); + } + free(offsets); + + for ( k=0; k<fd->fdcnt; ++k ) { + struct private *private = fd->fds[k]->private; + char *ssubroff = PSDictHasEntry(private->private,"SubrMapOffset"); + char *ssdbytes = PSDictHasEntry(private->private,"SDBytes"); + char *ssubrcnt = PSDictHasEntry(private->private,"SubrCount"); + int subroff, sdbytes, subrcnt; + + if ( ssubroff!=NULL && ssdbytes!=NULL && ssubrcnt!=NULL && + (subroff=strtol(ssubroff,NULL,10))>=0 && + (sdbytes=strtol(ssdbytes,NULL,10))>0 && + (subrcnt=strtol(ssubrcnt,NULL,10))>0 ) { + private->subrs->cnt = subrcnt; + private->subrs->values = gcalloc(subrcnt,sizeof(char *)); + private->subrs->lens = gcalloc(subrcnt,sizeof(int)); + leniv = private->leniv; + offsets = galloc((subrcnt+1)*sizeof(int)); + fseek(temp,subroff,SEEK_SET); + for ( i=0; i<=subrcnt; ++i ) { + for ( j=val=0; j<sdbytes; ++j ) + val = (val<<8) + getc(temp); + offsets[i] = val; + if ( i!=0 ) + private->subrs->lens[i-1] = offsets[i]-offsets[i-1]; + } + for ( i=0; i<subrcnt; ++i ) { + private->subrs->values[i] = readt1str(temp,offsets[i], + private->subrs->lens[i],leniv); + } + private->subrs->next = i; + free(offsets); + } + PSDictRemoveEntry(private->private,"SubrMapOffset"); + PSDictRemoveEntry(private->private,"SDBytes"); + PSDictRemoveEntry(private->private,"SubrCount"); + } +} + +static void dodata( struct fontparse *fp, FILE *in, FILE *temp) { + int binary, cnt, len; + int ch, ch2; + char *pt; + char fontsetname[256]; + + while ( (ch=getc(in))!='(' && ch!='/' && ch!=EOF ); + if ( ch=='/' ) { + /* There appears to be no provision for a hex encoding here */ + /* Why can't they use the same format for routines with the same name? */ + binary = true; + for ( pt=fontsetname; (ch=getc(in))!=' ' && ch!=EOF; ) + if ( pt<fontsetname+sizeof(fontsetname)-1 ) + *pt++= ch; + *pt = '\0'; + } else { + if ( (ch=getc(in))=='B' || ch=='b' ) binary = true; + else if ( ch=='H' || ch=='h' ) binary = false; + else { + binary = true; /* Who knows? */ + LogError( _("Failed to parse the StartData command properly\n") ); + } + fontsetname[0] = '\0'; + while ( (ch=getc(in))!=')' && ch!=EOF ); + } + if ( fscanf( in, "%d", &len )!=1 || len<=0 ) { + len = 0; + LogError( _("Failed to parse the StartData command properly, bad count\n") ); + } + cnt = len; + while ( isspace(ch=getc(in)) ); + ungetc(ch,in); + for ( pt="StartData "; *pt; ++pt ) + getc(in); /* And if it didn't match, what could I do about it? */ + if ( binary ) { + while ( cnt>0 ) { + ch = getc(in); + putc(ch,temp); + --cnt; + } + } else { + while ( cnt>0 ) { + /* Hex data are allowed to contain whitespace */ + while ( isspace(ch=getc(in)) ); + while ( isspace(ch2=getc(in)) ); + ch = hex(ch,ch2); + putc(ch,temp); + --cnt; + } + if ( (ch=getc(in))!='>' ) ungetc(ch,in); + } + rewind(temp); + if ( fp->iscid ) + figurecids(fp,temp); + else { + fp->fd->sf = _CFFParse(temp,len,fontsetname); + fp->fd->wascff = true; + } +} + +static void realdecrypt(struct fontparse *fp,FILE *in, FILE *temp) { + char buffer[256]; + int first, hassectionheads; + char rdtok[20]; + int saw_blend = false; + + strcpy(rdtok,"RD"); + + first = 1; hassectionheads = 0; + while ( myfgets(buffer,sizeof(buffer),in)!=NULL ) { + if ( strstr(buffer, "Blend")!=NULL ) + saw_blend = true; + if ( first && buffer[0]=='\200' ) { + int len = strlen( buffer ); + hassectionheads = 1; + fp->fd->wasbinary = true; + /* if there were a newline in the section header (in the length word)*/ + /* we would stop at it, and not read the full header */ + if ( len<6 ) /* eat the header */ + while ( len<6 ) { getc(in); ++len; } + else /* Otherwise parse anything else on the line */ + parseline(fp,buffer+6,in); + } else if ( strstr(buffer,"CharProcs")!=NULL && strstr(buffer,"begin")!=NULL ) { + parsetype3(fp,in); +return; + } else if ( fp->fd->fonttype!=42 && strstr(buffer,"CharStrings")!=NULL && strstr(buffer,"begin")!=NULL ) { + /* Fontographer uses CharStrings even though they aren't */ + parsetype3(fp,in); +return; + } else if ( !fp->iscid ) { + if ( saw_blend ) + parseline(fp,buffer,in); + /* But if it's a multi master font, don't do the special private hack */ + else if ( strstr(buffer,"/CharStrings")!=NULL && + strstr(buffer,"begin")!=NULL && + (fp->fd->fonttype!=42 && fp->fd->cidfonttype!=2)) { + /* gsf files are not eexec encoded, but the charstrings are encoded*/ + InitChars(fp->fd->chars,buffer); + fp->inchars = 1; + decryptagain(fp,in,rdtok); +return; + } else if ( strstr(buffer,"/Subrs")!=NULL && strstr(buffer,"array")!=NULL ) { + /* Same case as above */ + InitChars(fp->fd->private->subrs,buffer); + fp->insubs = 1; + decryptagain(fp,in,rdtok); +return; + } else if ( strstr(buffer,"/Private")!=NULL && (strstr(buffer,"dict")!=NULL || strstr(buffer,"<<")!=NULL )) { + /* files produced by GNU fontutils have some of the same issues */ + fp->inprivate = 1; + fp->infi = false; + decryptagain(fp,in,rdtok); +return; + } else + parseline(fp,buffer,in); + } else + parseline(fp,buffer,in); + first = 0; + if ( strstr(buffer,"%%BeginData: ")!=NULL ) + break; + if ( strstr(buffer,"currentfile")!=NULL && strstr(buffer, "eexec")!=NULL ) { + fp->skipping_mbf = false; + break; + } + /* Hmm. These lines were put in to handle parsing type42 fonts, but */ + /* they break multimaster fonts, and they don't seem to be needed */ + /* for type42s any more either. So... Away with them */ +#if 0 + if ( strstr(buffer,"definefont")!=NULL ) + break; +#endif + } + + if ( strstr(buffer,"%%BeginData: ")!=NULL ) { + /* used by both CID fonts and CFF fonts (and chameleons, whatever they are) */ + dodata(fp,in,temp); + } else if ( strstr(buffer,"eexec")!=NULL ) { + decrypteexec(in,temp,hassectionheads,strstr(buffer, "eexec")+5); + rewind(temp); + decryptagain(fp,temp,rdtok); + while ( myfgets(buffer,sizeof(buffer),in)!=NULL ) { + if ( buffer[0]!='\200' || !hassectionheads ) + parseline(fp,buffer,in); + } + } else if (( fp->fd->fonttype==42 || fp->fd->cidfonttype==2 ) && fp->sfnts!=NULL ) { + fp->fd->sf = _SFReadTTF(fp->sfnts,0,0,"<Temp File>",fp->fd); + fclose(fp->sfnts); + } +} + +FontDict *_ReadPSFont(FILE *in) { + FILE *temp; + struct fontparse fp; + char *oldloc; + struct stat b; + + temp = tmpfile(); + if ( temp==NULL ) { + LogError( _("Cannot open a temporary file\n") ); + fclose(in); +return(NULL); + } + + oldloc = setlocale(LC_NUMERIC,"C"); + memset(&fp,'\0',sizeof(fp)); + fp.fd = fp.mainfd = PSMakeEmptyFont(); + fp.fdindex = -1; + realdecrypt(&fp,in,temp); + free(fp.vbuf); + setlocale(LC_NUMERIC,oldloc); + + fclose(temp); + + if ( fstat(fileno(in),&b)!=-1 ) { + fp.fd->modificationtime = b.st_mtime; + fp.fd->creationtime = b.st_mtime; + } +return( fp.fd ); +} + +FontDict *ReadPSFont(char *fontname) { + FILE *in; + FontDict *fd; + + in = fopen(fontname,"rb"); + if ( in==NULL ) { + LogError( _("Cannot open %s\n"), fontname ); +return(NULL); + } + fd = _ReadPSFont(in); + fclose(in); +return( fd ); +} + +void PSCharsFree(struct pschars *chrs) { + int i; + + if ( chrs==NULL ) +return; + for ( i=0; i<chrs->next; ++i ) { + if ( chrs->keys!=NULL ) free(chrs->keys[i]); + free(chrs->values[i]); + } + free(chrs->lens); + free(chrs->keys); + free(chrs->values); + free(chrs); +} + +void PSDictFree(struct psdict *dict) { + int i; + + if ( dict==NULL ) +return; + for ( i=0; i<dict->next; ++i ) { + if ( dict->keys!=NULL ) free(dict->keys[i]); + free(dict->values[i]); + } + free(dict->keys); + free(dict->values); + free(dict); +} + +static void PrivateFree(struct private *prv) { + PSCharsFree(prv->subrs); +#if 1 + PSDictFree(prv->private); +#else + PSCharsFree(prv->othersubrs); + free(prv->minfeature); + free(prv->nd); + free(prv->np); + free(prv->rd); +#endif + free(prv); +} + +static void FontInfoFree(struct fontinfo *fi) { + free(fi->familyname); + free(fi->fullname); + free(fi->notice); + free(fi->weight); + free(fi->version); + free(fi->blenddesignpositions); + free(fi->blenddesignmap); + free(fi->blendaxistypes); + free(fi); +} + +void PSFontFree(FontDict *fd) { + int i; + + if ( fd->encoding!=NULL ) + for ( i=0; i<256; ++i ) + free( fd->encoding[i]); + free(fd->fontname); + free(fd->cidfontname); + free(fd->registry); + free(fd->ordering); + FontInfoFree(fd->fontinfo); + PSCharsFree(fd->chars); + PrivateFree(fd->private); + if ( fd->charprocs!=NULL ) { + for ( i=0; i<fd->charprocs->cnt; ++i ) + free(fd->charprocs->keys[i]); + free(fd->charprocs->keys); + free(fd->charprocs->values); + free(fd->charprocs); + } + if ( fd->cidstrs!=NULL ) { + for ( i=0; i<fd->cidcnt; ++i ) + free( fd->cidstrs[i]); + free(fd->cidstrs); + } + free(fd->cidlens); + free(fd->cidfds); + if ( fd->fds!=NULL ) { + for ( i=0; i<fd->fdcnt; ++i ) + PSFontFree(fd->fds[i]); + free(fd->fds); + } + free(fd->blendfunc); + free(fd->weightvector); + free(fd->cdv); + free(fd->ndv); + + PSDictFree(fd->blendprivate); + PSDictFree(fd->blendfontinfo); + + free(fd); +} + +char **_NamesReadPostscript(FILE *ps) { + char **ret = NULL; + char buffer[2000], *pt, *end; + + if ( ps!=NULL ) { + while ( fgets(buffer,sizeof(buffer),ps)!=NULL ) { + if ( strstr(buffer,"/FontName")!=NULL || + strstr(buffer,"/CIDFontName")!=NULL ) { + pt = strstr(buffer,"FontName"); + pt += strlen("FontName"); + while ( isspace(*pt)) ++pt; + if ( *pt=='/' ) ++pt; + for ( end = pt; *end!='\0' && !isspace(*end); ++end ); + ret = galloc(2*sizeof(char *)); + ret[0] = copyn(pt,end-pt); + ret[1] = NULL; + break; + } else if ( strstr(buffer,"currentfile")!=NULL && strstr(buffer,"eexec")!=NULL ) + break; + else if ( strstr(buffer,"%%BeginData")!=NULL ) + break; + } + fclose(ps); + } +return( ret ); +} + +char **NamesReadPostscript(char *filename) { +return( _NamesReadPostscript( fopen(filename,"rb"))); +} |