/reportlab-2.5/src/rl_addons/renderPM/gt1/gt1-parset1.c
C | 3242 lines | 2767 code | 326 blank | 149 comment | 630 complexity | e4ecef74d647c9a9056d513636877363 MD5 | raw file
Possible License(s): BSD-3-Clause, GPL-2.0, LGPL-2.0
Large files files are truncated, but you can click here to view the full file
- #include <stdio.h>
- #include <string.h>
- #include <ctype.h>
- #include <math.h>
- #if defined(macintosh)
- # include <extras.h>
- # define strdup _strdup
- #endif
- #include "libart_lgpl/art_bpath.h"
- #include "gt1-misc.h"
- #include "gt1-region.h"
- #include "gt1-namecontext.h"
- #include "gt1-value.h"
- #include "gt1-dict.h"
- #include "gt1-parset1.h"
- #ifdef AFM
- # include "parseAFM.h"
- #endif
- /* a big-assed module to parse Adobe Type 1 fonts into meaningful
- info */
- #define noVERBOSE
- static int
- read_int32_lsb (const char *p)
- {
- const unsigned char *q = (unsigned char *)p;
- return q[0] + (q[1] << 8) + (q[2] << 16) + (q[3] << 24);
- }
- /* this is a pfb to pfa converter
- Reference: Adobe technical note 5040, "Supporting Downloadable PostScript
- Language Fonts", page 9 */
- static char *
- pfb_to_flat (const char *input, int input_size)
- {
- const unsigned char *in = (unsigned char *)input;
- char *flat;
- int flat_size, flat_size_max;
- int in_idx;
- int length;
- int i;
- const char hextab[16] = "0123456789abcdef";
- flat_size = 0;
- flat_size_max = 32768;
- flat = gt1_new (char, flat_size_max);
- for (in_idx = 0; in_idx < input_size;)
- {
- if (in[in_idx] != 128)
- {
- gt1_free (flat);
- return NULL;
- }
- switch (in[in_idx + 1])
- {
- case 1:
- length = read_int32_lsb (input + in_idx + 2);
- if (flat_size + length > flat_size_max)
- {
- do
- flat_size_max <<= 1;
- while (flat_size + length > flat_size_max);
- flat = gt1_renew (flat, char, flat_size_max);
- }
- in_idx += 6;
- memcpy (flat + flat_size, in + in_idx, length);
- flat_size += length;
- in_idx += length;
- break;
- case 2:
- length = read_int32_lsb (input + in_idx + 2);
- if (flat_size + length * 3 > flat_size_max)
- {
- do
- flat_size_max <<= 1;
- while (flat_size + length * 3 > flat_size_max);
- flat = gt1_renew (flat, char, flat_size_max);
- }
- in_idx += 6;
- for (i = 0; i < length; i++)
- {
- flat[flat_size++] = hextab[in[in_idx] >> 4];
- flat[flat_size++] = hextab[in[in_idx] & 15];
- in_idx++;
- if ((i & 31) == 31 || i == length - 1)
- flat[flat_size++] = '\n';
- }
- break;
- case 3:
- /* zero terminate the returned string */
- if (flat_size == flat_size_max)
- gt1_double (flat, char, flat_size_max);
- flat[flat_size] = 0;
- return flat;
- default:
- gt1_free (flat);
- return NULL;
- }
- }
- return flat;
- }
- struct _Gt1TokenContext {
- char *source;
- int index;
- int pos;
- };
- typedef enum {
- TOK_NUM,
- TOK_STR,
- TOK_NAME, /* initial / */
- TOK_IDENT,
- TOK_OPENBRACE,
- TOK_CLOSEBRACE,
- TOK_END
- } TokenType;
- /* we're phasing this out in favor of value.h's Gt1String */
- typedef struct _MyGt1String MyGt1String;
- struct _MyGt1String {
- char *start;
- char *fin;
- };
- static void
- tokenize_free (Gt1TokenContext *tc)
- {
- gt1_free (tc->source);
- gt1_free (tc);
- }
- static Gt1TokenContext *
- tokenize_new (const char *input)
- {
- Gt1TokenContext *tc;
- int length;
- tc = gt1_new (Gt1TokenContext, 1);
- length = strlen (input);
- tc->source = gt1_new (char, length + 1);
- memcpy (tc->source, input, length + 1);
- tc->index = 0;
- tc->pos = 0;
- return tc;
- }
- static Gt1TokenContext *
- tokenize_new_from_mystring (MyGt1String *input)
- {
- Gt1TokenContext *tc;
- int length;
- tc = gt1_new (Gt1TokenContext, 1);
- length = input->fin - input->start;
- tc->source = gt1_new (char, length + 1);
- memcpy (tc->source, input->start, length + 1);
- tc->index = 0;
- tc->pos = 0;
- return tc;
- }
- /* this returns a TokenType, and sets result to the token contents.
- Note: this strips delimiters, like the initial /, and the enclosing ().
- */
- static TokenType
- tokenize_get (Gt1TokenContext *tc, MyGt1String *result)
- {
- unsigned char *s = (unsigned char *)tc->source;
- int index = tc->index;
- int pos = tc->pos;
- unsigned char c;
- TokenType type;
- /* skip comments altogether (maybe later we want them, though) */
- while (c = s[index], isspace (c) || c == '%')
- {
- /* skip leading whitespace */
- while (isspace (s[index]))
- {
- if (s[index] == '\r' || s[index] == '\n')
- pos = 0;
- else
- pos++;
- index++;
- }
- if (s[index] == '%')
- {
- do
- /* skip past end-of-line */
- {
- while (c = s[index], c && c != '\r' && c != '\n')
- index++;
- if (s[index] != 0) index++;
- }
- while (s[index] == '%');
- }
- }
- /* skip leading whitespace */
- while (c = s[index], isspace (c))
- {
- if (c == '\r' || c == '\n')
- pos = 0;
- else
- pos++;
- index++;
- }
- /* ok, so now we're at the actual start of a token */
- result->start = (char*)s + index;
- c = s[index];
- if (c == 0)
- {
- result->fin = (char*)s + index;
- type = TOK_END;
- }
- /* note: GhostScript checks much more strenuously. Further, this
- predicate does not pass the valid number -.9 */
- else if (isdigit (c) || c == '.' || (c == '-' && isdigit (s[index + 1])))
- {
- /* numeric token */
- while (c = s[index], c && !isspace (c) && c != '{' && c != '/' &&
- c != '[' && c != ']' && c != '}')
- {
- index++;
- pos++;
- }
- result->fin = (char*)s + index;
- type = TOK_NUM;
- }
- else if (c == '/')
- {
- /* an atom, or whatever that's called */
- index++;
- result->start = (char*)s + index;
- while (c = s[index], c && !isspace (c) && c != '{' && c != '/' &&
- c != '[' && c != ']' && c != '}' && c != '(')
- {
- index++;
- pos++;
- }
- result->fin = (char*)s + index;
- type = TOK_NAME;
- }
- else if (c == '(')
- {
- int nest;
- int backslash;
- nest = 1;
- index++;
- backslash = 0;
- result->start = (char*)s + index;
- while (c = s[index], c && nest)
- {
- if (backslash)
- backslash = 0;
- else if (c == '(')
- nest++;
- else if (c == ')')
- nest--;
- else if (c == '\\')
- backslash = 1;
- index++;
- if (c == '\r' || c == '\n')
- pos = 0;
- else
- pos++;
- }
- /* we could have a c == 0 error case here */
- result->fin = (char*)s + index - 1;
- type = TOK_STR;
- }
- else if (c == '{')
- {
- index++;
- result->fin = (char*)s + index;
- type = TOK_OPENBRACE;
- }
- else if (c == '}')
- {
- index++;
- result->fin = (char*)s + index;
- type = TOK_CLOSEBRACE;
- }
- else if (c == '[' || c == ']')
- {
- index++;
- result->fin = (char*)s + index;
- type = TOK_IDENT;
- }
- else
- {
- /* treat everything else as an identifier */
- while (c = s[index], c && !isspace (c) && c != '{' && c != '/' &&
- c != '[' && c != ']' && c != '}' && c != '(')
- {
- index++;
- pos++;
- }
- result->fin = (char*)s + index;
- if (isspace(c))
- index++; /* skip single trailing whitespace char - this is
- useful for readstring */
- type = TOK_IDENT;
- }
- tc->index = index;
- tc->pos = pos;
- return type;
- }
- static int
- ascii_to_hex (unsigned char c)
- {
- if (c <= '9') return c - '0';
- else if (c >= 'a') return c + 10 - 'a';
- else return c + 10 - 'A';
- }
- /* return a hex byte, or -1 on error */
- /* we don't deal with comments here */
- static int
- tokenize_get_hex_byte (Gt1TokenContext *tc)
- {
- const unsigned char *s = (const unsigned char *)tc->source;
- int index = tc->index;
- int pos = tc->pos;
- int byte;
- /* skip leading whitespace */
- while (isspace (s[index]))
- {
- if (s[index] == '\r' || s[index] == '\n')
- pos = 0;
- else
- pos++;
- index++;
- }
- if (isxdigit (s[index]) && isxdigit (s[index + 1]))
- {
- byte = (ascii_to_hex (s[index]) << 4) | ascii_to_hex (s[index + 1]);
- index += 2;
- }
- else
- byte = -1;
- tc->index = index;
- tc->pos = pos;
- return byte;
- }
- /* careful, we're _not_ protected against buffer overruns here */
- /* todo: fix this, it's definitely a potential security violation.
- This almost certainly implies changing the Gt1TokenContext structure
- to incorporate a size field, and de-emphasizing the use of
- zero-termination */
- static void
- tokenize_get_raw (Gt1TokenContext *tc, char *buf, int buf_size)
- {
- memcpy (buf, tc->source + tc->index, buf_size);
- tc->index += buf_size;
- }
- #ifdef DEBUG
- static void
- print_token (TokenType type, MyGt1String *lexeme)
- {
- char *start, *fin;
- start = lexeme->start;
- fin = lexeme->fin;
- switch (type)
- {
- case TOK_NUM:
- printf ("number ");
- break;
- case TOK_IDENT:
- printf ("identifier ");
- break;
- case TOK_NAME:
- printf ("name ");
- break;
- case TOK_STR:
- printf ("string ");
- break;
- case TOK_OPENBRACE:
- printf ("open brace ");
- break;
- case TOK_CLOSEBRACE:
- printf ("close brace ");
- break;
- case TOK_END:
- printf ("end ");
- break;
- default:
- break;
- }
- while (start != fin)
- printf ("%c", *start++);
- printf ("\n");
- }
- static void
- test_token (const char *flat)
- {
- Gt1TokenContext *tc;
- TokenType type;
- MyGt1String lexeme;
- tc = tokenize_new (flat);
- while (1)
- {
- type = tokenize_get (tc, &lexeme);
- if (type == TOK_END) break;
- print_token (type, &lexeme);
- }
- }
- #endif
- /* basic PostScript language types */
- typedef struct _Gt1ProcStep {
- TokenType tok_type;
- MyGt1String lexeme;
- } Gt1ProcStep;
- struct _Gt1Proc {
- int n_steps;
- /* sooner or later, we'll want to replace proc steps with
- plain PostScript values. - probably sooner in fact, because that's
- the best way to implement nested procedures, which currently do
- not work. */
- Gt1Value steps[1];
- };
- /* low-level PostScript routines */
- /* note: resulting array is _uninitialized_ ! */
- static Gt1Array *
- array_new (Gt1Region *r, int size)
- {
- Gt1Array *array;
- array = (Gt1Array *)gt1_region_alloc (r, sizeof(Gt1Array) +
- (size - 1) * sizeof(Gt1Value));
- array->n_values = size;
- return array;
- }
- struct _Gt1PSContext {
- Gt1Region *r; /* the region all PS values are allocated into */
- Gt1TokenContext *tc; /* this is for readstring, eexec, etc. */
- Gt1NameContext *nc; /* the context for all names */
- Gt1Value *value_stack;
- int n_values, n_values_max;
- /* ghostscript also has an execution stack - what's that? */
- Gt1Dict **gt1_dict_stack;
- int n_dicts, n_dicts_max;
- /* a special dict that holds all the fonts */
- Gt1Dict *fonts;
- Gt1TokenContext **file_stack; /* invariant: top of file stack == tc */
- int n_files, n_files_max;
- int quit; /* maybe this should be a string, for error messages too */
- };
- /* a very basic PostScript interpreter */
- /* make sure that value stack has enough room for pushing n values. */
- static void
- ensure_stack (Gt1PSContext *psc, int n)
- {
- if (psc->n_values + n == psc->n_values_max)
- {
- psc->n_values_max <<= 1;
- psc->value_stack = gt1_renew (psc->value_stack, Gt1Value, psc->n_values_max);
- }
- }
- static double
- parse_num (MyGt1String *number)
- {
- double sign;
- double mantissa;
- double decimal;
- int exp_sign;
- int exp;
- int i, length;
- const unsigned char *start;
- start = (const unsigned char *)number->start;
- length = number->fin - number->start;
- i = 0;
- sign = 1;
- if (i < length && start[i] == '-')
- {
- sign = -1;
- i++;
- }
- else if (i < length && start[i] == '+')
- i++;
- mantissa = 0;
- while (i < length && isdigit (start[i]))
- {
- mantissa = (mantissa * 10) + start[i] - '0';
- i++;
- }
- if (i < length && start[i] == '.')
- {
- i++;
- decimal = 1;
- while (i < length && isdigit (start[i]))
- {
- decimal *= 0.1;
- mantissa += (start[i] - '0') * decimal;
- i++;
- }
- }
- if (i < length && (start[i] == 'e' || start[i] == 'E'))
- {
- i++;
- exp_sign = 1;
- if (i < length && start[i] == '-')
- {
- exp_sign = -1;
- i++;
- }
- else if (i < length && start[i] == '+')
- i++;
- exp = 0;
- while (i < length && isdigit (start[i]))
- {
- exp = (exp * 10) + start[i] - '0';
- i++;
- }
- mantissa *= pow (10, exp * exp_sign);
- }
- return sign * mantissa;
- }
- #ifdef DEBUG
- static void
- print_mystring (MyGt1String *str)
- {
- char *start, *fin;
- start = str->start;
- fin = str->fin;
- while (start != fin)
- printf ("%c", *start++);
- }
- #endif
- static void
- print_string (Gt1String *str)
- {
- char *start;
- int size;
- int i;
- start = str->start;
- size = str->size;
- for (i = 0; i < size; i++);
- printf ("%c", start[i]);
- }
- static void
- print_value (Gt1PSContext *psc, Gt1Value *val)
- {
- switch (val->type)
- {
- case GT1_VAL_NUM:
- printf ("%g", val->val.num_val);
- break;
- case GT1_VAL_BOOL:
- printf ("%s", val->val.bool_val ? "true" : "false");
- break;
- case GT1_VAL_STR:
- printf ("\"");
- print_string (&val->val.str_val);
- printf ("\"");
- break;
- case GT1_VAL_NAME:
- printf ("/%s", gt1_name_context_string (psc->nc, val->val.name_val));
- break;
- case GT1_VAL_UNQ_NAME:
- printf ("%s", gt1_name_context_string (psc->nc, val->val.name_val));
- break;
- case GT1_VAL_DICT:
- printf ("<dictionary %d/%d>",
- val->val.dict_val->n_entries,
- val->val.dict_val->n_entries_max);
- break;
- case GT1_VAL_ARRAY:
- printf ("<array>");
- break;
- case GT1_VAL_PROC:
- #if 1
- printf ("<proc>");
- #else
- printf ("{ ");
- { int i;
- for (i = 0; i < val->val.proc_val->n_values; i++)
- {
- print_value (psc, &val->val.proc_val->vals[i]);
- printf (" ");
- }
- printf ("}");
- }
- #endif
- break;
- case GT1_VAL_FILE:
- printf ("<file>");
- break;
- case GT1_VAL_INTERNAL:
- printf ("<internal function>");
- case GT1_VAL_MARK:
- printf ("<mark>");
- break;
- default:
- printf ("???%d", val->type);
- }
- }
- #ifdef DEBUG
- static void
- print_token_short (TokenType type, MyGt1String *lexeme)
- {
- char *start, *fin;
- start = lexeme->start;
- fin = lexeme->fin;
- switch (type)
- {
- case TOK_NUM:
- print_mystring (lexeme);
- break;
- case TOK_IDENT:
- print_mystring (lexeme);
- break;
- case TOK_NAME:
- printf ("/");
- print_mystring (lexeme);
- break;
- case TOK_STR:
- printf ("(");
- print_mystring (lexeme);
- printf (")");
- break;
- case TOK_OPENBRACE:
- printf ("{");
- break;
- case TOK_CLOSEBRACE:
- printf ("}");
- break;
- case TOK_END:
- printf ("end ");
- break;
- default:
- break;
- }
- }
- #endif
- static void
- print_value_deep (Gt1PSContext *psc, Gt1Value *val, int nest)
- {
- int i, j;
- for (i = 0; i < nest; i++)
- printf (" ");
- switch (val->type)
- {
- case GT1_VAL_NUM:
- printf ("%g", val->val.num_val);
- break;
- case GT1_VAL_BOOL:
- printf ("%s", val->val.bool_val ? "true" : "false");
- break;
- case GT1_VAL_STR:
- printf ("\"");
- print_string (&val->val.str_val);
- printf ("\"");
- break;
- case GT1_VAL_NAME:
- printf ("/%s", gt1_name_context_string (psc->nc, val->val.name_val));
- break;
- case GT1_VAL_UNQ_NAME:
- printf ("%s", gt1_name_context_string (psc->nc, val->val.name_val));
- break;
- case GT1_VAL_DICT:
- printf ("<dictionary %d/%d> [\n",
- val->val.dict_val->n_entries,
- val->val.dict_val->n_entries_max);
- for (i = 0; i < val->val.dict_val->n_entries; i++)
- {
- for (j = 0; j < nest; j++)
- printf (" ");
- printf ("key %d\n", val->val.dict_val->entries[i].key);
- print_value_deep (psc, &val->val.dict_val->entries[i].val, nest + 1);
- }
- for (j = 0; j < nest; j++)
- printf (" ");
- printf ("]");
- break;
- case GT1_VAL_ARRAY:
- printf ("[\n");
- for (i = 0; i < val->val.array_val->n_values; i++)
- {
- print_value_deep (psc, &val->val.array_val->vals[i], nest + 1);
- }
- for (j = 0; j < nest; j++)
- printf (" ");
- printf ("]");
- break;
- case GT1_VAL_PROC:
- printf ("{\n");
- for (i = 0; i < val->val.proc_val->n_values; i++)
- {
- print_value_deep (psc, &val->val.proc_val->vals[i], nest + 1);
- }
- for (j = 0; j < nest; j++)
- printf (" ");
- printf ("}");
- break;
- case GT1_VAL_FILE:
- printf ("<file>");
- break;
- case GT1_VAL_INTERNAL:
- printf ("<internal function>");
- case GT1_VAL_MARK:
- printf ("<mark>");
- break;
- default:
- printf ("???");
- }
- printf ("\n");
- }
- #ifdef DEBUG
- static void
- print_stack (Gt1PSContext *psc)
- {
- int i;
- for (i = 0; i < psc->n_values; i++)
- {
- print_value (psc, &psc->value_stack[i]);
- if (i != psc->n_values - 1)
- printf (" ");
- }
- printf ("\n");
- }
- #endif
- static void
- eval_ps_val (Gt1PSContext *psc, Gt1Value *val);
- static void
- eval_proc (Gt1PSContext *psc, Gt1Proc *proc)
- {
- int i;
- #ifdef VERBOSE
- printf ("begin proc evaluation\n");
- #endif
- for (i = 0; !psc->quit && i < proc->n_values; i++)
- eval_ps_val (psc, &proc->vals[i]);
- #ifdef VERBOSE
- printf ("end proc evaluation\n");
- #endif
- }
- static Gt1Value *
- gt1_dict_stack_lookup (Gt1PSContext *psc, Gt1NameId key)
- {
- int i;
- Gt1Value *val;
- for (i = psc->n_dicts - 1; i >= 0; i--)
- {
- val = gt1_dict_lookup (psc->gt1_dict_stack[i], key);
- if (val != NULL)
- return val;
- }
- return NULL;
- }
- /* return 1 on success, with result set to the top of the value stack */
- static int
- get_stack_number (Gt1PSContext *psc, double *result, int index)
- {
- if (psc->n_values < index)
- {
- printf ("stack underflow\n");
- psc->quit = 1;
- return 0;
- }
- if (psc->value_stack[psc->n_values - index].type != GT1_VAL_NUM)
- {
- printf ("type error - expecting number\n");
- psc->quit = 1;
- return 0;
- }
- *result = psc->value_stack[psc->n_values - index].val.num_val;
- return 1;
- }
- /* return 1 on success, with result set to the top of the value stack */
- static int
- get_stack_dict (Gt1PSContext *psc, Gt1Dict **result, int index)
- {
- if (psc->n_values < index)
- {
- printf ("stack underflow\n");
- psc->quit = 1;
- return 0;
- }
- if (psc->value_stack[psc->n_values - index].type != GT1_VAL_DICT)
- {
- printf ("type error - expecting dict\n");
- psc->quit = 1;
- return 0;
- }
- *result = psc->value_stack[psc->n_values - index].val.dict_val;
- return 1;
- }
- /* return 1 on success, with result set to the top of the value stack */
- static int
- get_stack_name (Gt1PSContext *psc, Gt1NameId *result, int index)
- {
- if (psc->n_values < index)
- {
- printf ("stack underflow\n");
- psc->quit = 1;
- return 0;
- }
- if (psc->value_stack[psc->n_values - index].type != GT1_VAL_NAME)
- {
- printf ("type error - expecting atom\n");
- psc->quit = 1;
- return 0;
- }
- *result = psc->value_stack[psc->n_values - index].val.name_val;
- return 1;
- }
- /* return 1 on success, with result set to the top of the value stack */
- static int
- get_stack_file (Gt1PSContext *psc, Gt1TokenContext **result, int index)
- {
- if (psc->n_values < index)
- {
- printf ("stack underflow\n");
- psc->quit = 1;
- return 0;
- }
- if (psc->value_stack[psc->n_values - index].type != GT1_VAL_FILE)
- {
- printf ("type error - expecting file\n");
- psc->quit = 1;
- return 0;
- }
- *result = psc->value_stack[psc->n_values - index].val.file_val;
- return 1;
- }
- /* return 1 on success, with result set to the top of the value stack */
- static int
- get_stack_string (Gt1PSContext *psc, Gt1String *result, int index)
- {
- if (psc->n_values < index)
- {
- printf ("stack underflow\n");
- psc->quit = 1;
- return 0;
- }
- if (psc->value_stack[psc->n_values - index].type != GT1_VAL_STR)
- {
- printf ("type error - expecting string\n");
- psc->quit = 1;
- return 0;
- }
- *result = psc->value_stack[psc->n_values - index].val.str_val;
- return 1;
- }
- /* return 1 on success, with result set to the top of the value stack */
- static int
- get_stack_array (Gt1PSContext *psc, Gt1Array **result, int index)
- {
- if (psc->n_values < index)
- {
- printf ("stack underflow\n");
- psc->quit = 1;
- return 0;
- }
- if (psc->value_stack[psc->n_values - index].type != GT1_VAL_ARRAY)
- {
- printf ("type error - expecting array\n");
- psc->quit = 1;
- return 0;
- }
- *result = psc->value_stack[psc->n_values - index].val.array_val;
- return 1;
- }
- /* return 1 on success, with result set to the top of the value stack */
- static int
- get_stack_bool (Gt1PSContext *psc, int *result, int index)
- {
- if (psc->n_values < index)
- {
- printf ("stack underflow\n");
- psc->quit = 1;
- return 0;
- }
- if (psc->value_stack[psc->n_values - index].type != GT1_VAL_BOOL)
- {
- printf ("type error - expecting bool\n");
- psc->quit = 1;
- return 0;
- }
- *result = psc->value_stack[psc->n_values - index].val.bool_val;
- return 1;
- }
- /* return 1 on success, with result set to the top of the value stack */
- static int
- get_stack_proc (Gt1PSContext *psc, Gt1Proc **result, int index)
- {
- if (psc->n_values < index)
- {
- printf ("stack underflow\n");
- psc->quit = 1;
- return 0;
- }
- if (psc->value_stack[psc->n_values - index].type != GT1_VAL_PROC)
- {
- printf ("type error - expecting proc\n");
- psc->quit = 1;
- return 0;
- }
- *result = psc->value_stack[psc->n_values - index].val.proc_val;
- return 1;
- }
- /* here begin the internal procedures */
- static void
- internal_dict (Gt1PSContext *psc)
- {
- Gt1Dict *dict;
- double d_size;
- if (get_stack_number (psc, &d_size, 1))
- {
- dict = gt1_dict_new (psc->r, (int)d_size);
- psc->value_stack[psc->n_values - 1].type = GT1_VAL_DICT;
- psc->value_stack[psc->n_values - 1].val.dict_val = dict;
- }
- }
- static void
- internal_begin (Gt1PSContext *psc)
- {
- Gt1Dict *dict;
- if (get_stack_dict (psc, &dict, 1))
- {
- if (psc->n_dicts == psc->n_dicts_max)
- gt1_double (psc->gt1_dict_stack, Gt1Dict *, psc->n_dicts_max);
- psc->gt1_dict_stack[psc->n_dicts++] = dict;
- psc->n_values--;
- }
- }
- static void
- internal_end (Gt1PSContext *psc)
- {
- /* note: this magic constant changes if we separate out the internal
- dict from the user one; in fact, GhostScript uses three. */
- if (psc->n_dicts == 1)
- {
- printf ("dict stack underflow\n");
- psc->quit = 1;
- }
- psc->n_dicts--;
- }
- static void
- internal_dup (Gt1PSContext *psc)
- {
- if (psc->n_values == 0)
- {
- printf ("stack underflow\n");
- psc->quit = 1;
- }
- else
- {
- ensure_stack (psc, 1);
- psc->value_stack[psc->n_values] =
- psc->value_stack[psc->n_values - 1];
- psc->n_values++;
- }
- }
- static void
- internal_pop (Gt1PSContext *psc)
- {
- if (psc->n_values == 0)
- {
- printf ("stack underflow\n");
- psc->quit = 1;
- }
- else
- psc->n_values--;
- }
- static void
- internal_exch (Gt1PSContext *psc)
- {
- Gt1Value tmp;
- int stack_size;
- stack_size = psc->n_values;
- if (stack_size < 2)
- {
- printf ("stack underflow\n");
- psc->quit = 1;
- }
- else
- {
- tmp = psc->value_stack[stack_size - 2];
- psc->value_stack[stack_size - 2] =
- psc->value_stack[stack_size - 1];
- psc->value_stack[stack_size - 1] = tmp;
- }
- }
- /* this doesn't do anything - we don't enforce readonly */
- static void
- internal_readonly (Gt1PSContext *psc)
- {
- if (psc->n_values == 0)
- {
- printf ("stack underflow\n");
- psc->quit = 1;
- }
- }
- /* this doesn't do anything - we don't enforce executeonly */
- static void
- internal_executeonly (Gt1PSContext *psc)
- {
- if (psc->n_values == 0)
- {
- printf ("stack underflow\n");
- psc->quit = 1;
- }
- }
- /* this doesn't do anything - we don't enforce noaccess */
- static void
- internal_noaccess (Gt1PSContext *psc)
- {
- if (psc->n_values == 0)
- {
- printf ("stack underflow\n");
- psc->quit = 1;
- }
- }
- static void
- internal_def (Gt1PSContext *psc)
- {
- Gt1NameId key;
- Gt1Dict *dict;
- if (get_stack_name (psc, &key, 2))
- {
- dict = psc->gt1_dict_stack[psc->n_dicts - 1];
- gt1_dict_def (psc->r, dict, key, &psc->value_stack[psc->n_values - 1]);
- psc->n_values -= 2;
- }
- }
- static void
- internal_false (Gt1PSContext *psc)
- {
- ensure_stack (psc, 1);
- psc->value_stack[psc->n_values].type = GT1_VAL_BOOL;
- psc->value_stack[psc->n_values].val.bool_val = gt1_false;
- psc->n_values++;
- }
- static void
- internal_true (Gt1PSContext *psc)
- {
- ensure_stack (psc, 1);
- psc->value_stack[psc->n_values].type = GT1_VAL_BOOL;
- psc->value_stack[psc->n_values].val.bool_val = gt1_true;
- psc->n_values++;
- }
- static void
- internal_StandardEncoding (Gt1PSContext *psc)
- {
- ensure_stack (psc, 1);
- /* todo: push actual encoding array */
- psc->value_stack[psc->n_values].type = GT1_VAL_NUM;
- psc->value_stack[psc->n_values].val.num_val = 42;
- psc->n_values++;
- }
- static void
- internalop_openbracket (Gt1PSContext *psc)
- {
- ensure_stack (psc, 1);
- psc->value_stack[psc->n_values].type = GT1_VAL_MARK;
- psc->n_values++;
- }
- static void
- internalop_closebracket (Gt1PSContext *psc)
- {
- int i;
- Gt1Array *array;
- int size, start_idx;
- for (i = psc->n_values - 1; i >= 0; i--)
- if (psc->value_stack[i].type == GT1_VAL_MARK)
- break;
- if (psc->value_stack[i].type != GT1_VAL_MARK)
- {
- printf ("unmatched mark\n");
- psc->quit = 1;
- }
- start_idx = i + 1;
- size = psc->n_values - start_idx;
- array = array_new (psc->r, size);
- for (i = 0; i < size; i++)
- array->vals[i] = psc->value_stack[start_idx + i];
- psc->n_values -= size;
- psc->value_stack[psc->n_values - 1].type = GT1_VAL_ARRAY;
- psc->value_stack[psc->n_values - 1].val.array_val = array;
- }
- static void
- internal_currentdict (Gt1PSContext *psc)
- {
- ensure_stack (psc, 1);
- psc->value_stack[psc->n_values].type = GT1_VAL_DICT;
- psc->value_stack[psc->n_values].val.dict_val =
- psc->gt1_dict_stack[psc->n_dicts - 1];
- psc->n_values++;
- }
- static void
- internal_currentfile (Gt1PSContext *psc)
- {
- /* todo: we want to move away from a tc pointer towards tags, to avoid
- potential security holes from misusing these data structures */
- ensure_stack (psc, 1);
- psc->value_stack[psc->n_values].type = GT1_VAL_FILE;
- psc->value_stack[psc->n_values].val.file_val = psc->tc;
- psc->n_values++;
- }
- #define EEXEC_C1 ((unsigned short)52845)
- #define EEXEC_C2 ((unsigned short)22719)
- /* return number of bytes in result */
- static int
- decrypt_eexec (char *plaintext, const char *ciphertext, int ciphertext_size)
- {
- int i;
- unsigned short r;
- unsigned char cipher;
- unsigned char plain;
- r = 55665; /* initial key */
- for (i = 0; i < ciphertext_size; i++)
- {
- cipher = ciphertext[i];
- plain = (cipher ^ (r>>8));
- r = (cipher + r) * EEXEC_C1 + EEXEC_C2;
- if (i >= 4)
- plaintext[i - 4] = plain;
- }
- return ciphertext_size - 4;
- }
- /* this one is great fun! */
- static void
- internal_eexec (Gt1PSContext *psc)
- {
- Gt1TokenContext *file_tc;
- char *ciphertext;
- int ciphertext_size, ciphertext_size_max;
- char *plaintext;
- int plaintext_size;
- int num_nulls;
- int byte;
- MyGt1String string;
- Gt1TokenContext *new_tc;
- if (get_stack_file (psc, &file_tc, 1))
- {
- psc->n_values--;
- /* first, suck the encrypted stream from the specified file */
- ciphertext_size = 0;
- ciphertext_size_max = 512;
- ciphertext = gt1_new (char, ciphertext_size_max);
- num_nulls = 0;
- while (num_nulls < 16)
- {
- if (ciphertext_size == ciphertext_size_max)
- gt1_double (ciphertext, char, ciphertext_size_max);
- byte = tokenize_get_hex_byte (file_tc);
- if (byte < 0)
- {
- printf ("eexec input appears to be truncated\n");
- psc->quit = 1;
- return;
- }
- if (byte == 0)
- num_nulls++;
- else
- num_nulls = 0;
- ciphertext[ciphertext_size++] = byte;
- }
- /* then, decrypt it */
- plaintext = gt1_new (char, ciphertext_size);
- plaintext_size = decrypt_eexec (plaintext, ciphertext, ciphertext_size);
- gt1_free (ciphertext);
- #if 1 && defined(VERBOSE)
- fwrite (plaintext, 1, plaintext_size, stdout);
- #endif
- /* finally, create a new Gt1TokenContext for the string, and switch
- to executing it. */
- string.start = plaintext;
- string.fin = plaintext + plaintext_size;
- new_tc = tokenize_new_from_mystring (&string);
- gt1_free (plaintext);
- if (psc->n_files_max == psc->n_files)
- {
- printf ("overflow of file stack\n");
- psc->quit = 1;
- return;
- }
- psc->file_stack[psc->n_files++] = new_tc;
- psc->tc = new_tc;
- /* alternatively, we could have recursively called the PostScript
- evaluation loop from here, but this seems to be just as good. */
- }
- }
- static void
- internal_array (Gt1PSContext *psc)
- {
- Gt1Array *array;
- double d_size;
- if (get_stack_number (psc, &d_size, 1))
- {
- array = array_new (psc->r, (int)d_size);
- psc->value_stack[psc->n_values - 1].type = GT1_VAL_ARRAY;
- psc->value_stack[psc->n_values - 1].val.array_val = array;
- }
- }
- static void
- internal_string (Gt1PSContext *psc)
- {
- Gt1String string;
- double d_size;
- int size;
- if (get_stack_number (psc, &d_size, 1))
- {
- size = (int)d_size;
- string.start = gt1_region_alloc (psc->r, size);
- string.size = size;
- memset (string.start, 0, size);
- psc->value_stack[psc->n_values - 1].type = GT1_VAL_STR;
- psc->value_stack[psc->n_values - 1].val.str_val = string;
- }
- }
- static void
- internal_readstring (Gt1PSContext *psc)
- {
- Gt1String string;
- Gt1TokenContext *file_tc;
- if (get_stack_string (psc, &string, 1) &&
- get_stack_file (psc, &file_tc, 2))
- {
- tokenize_get_raw (file_tc, string.start, string.size);
- psc->value_stack[psc->n_values - 2].type = GT1_VAL_STR;
- psc->value_stack[psc->n_values - 2].val.str_val = string;
- psc->value_stack[psc->n_values - 1].type = GT1_VAL_BOOL;
- psc->value_stack[psc->n_values - 1].val.bool_val = gt1_true;
- }
- }
- static void
- internal_put (Gt1PSContext *psc)
- {
- Gt1Array *array;
- double d_index;
- int index;
- Gt1Dict *dict;
- Gt1NameId key;
- if (psc->n_values >= 3 &&
- psc->value_stack[psc->n_values - 3].type == GT1_VAL_DICT &&
- get_stack_name (psc, &key, 2))
- {
- /* dict key val put -- */
- get_stack_dict (psc, &dict, 3);
- gt1_dict_def (psc->r, dict, key, &psc->value_stack[psc->n_values - 1]);
- psc->n_values -= 3;
- }
- else if (psc->n_values >= 3 &&
- psc->value_stack[psc->n_values - 3].type == GT1_VAL_PROC &&
- get_stack_number (psc, &d_index, 2))
- {
- array = psc->value_stack[psc->n_values - 3].val.proc_val;
- index = (int)d_index;
- if (index < 0 || index >= array->n_values)
- {
- printf ("range check\n");
- psc->quit = 1;
- return;
- }
- array->vals[index] = psc->value_stack[psc->n_values - 1];
- psc->n_values -= 3;
- }
- else if (psc->n_values >= 3 &&
- get_stack_array (psc, &array, 3) &&
- get_stack_number (psc, &d_index, 2))
- {
- /* array index val put -- */
- index = (int)d_index;
- if (index < 0 || index >= array->n_values)
- {
- printf ("range check\n");
- psc->quit = 1;
- return;
- }
- array->vals[index] = psc->value_stack[psc->n_values - 1];
- psc->n_values -= 3;
- }
- }
- static void
- internal_get (Gt1PSContext *psc)
- {
- Gt1Array *array;
- double d_index;
- int index;
- Gt1Dict *dict;
- Gt1NameId key;
- Gt1Value *val;
- if (psc->n_values >= 2 &&
- psc->value_stack[psc->n_values - 2].type == GT1_VAL_DICT &&
- get_stack_name (psc, &key, 1))
- {
- /* dict key get val */
- get_stack_dict (psc, &dict, 2);
- val = gt1_dict_lookup (dict, key);
- if (val == NULL)
- {
- printf ("key not found\n");
- psc->quit = 1;
- return;
- }
- #ifdef VERBOSE
- printf ("value: ");
- print_value (psc, val);
- printf ("\n");
- #endif
- psc->n_values -= 1;
- psc->value_stack[psc->n_values - 1] = *val;
- }
- else if (psc->n_values >= 2 &&
- psc->value_stack[psc->n_values - 2].type == GT1_VAL_PROC &&
- get_stack_number (psc, &d_index, 1))
- {
- /* array index get val */
- array = psc->value_stack[psc->n_values - 2].val.proc_val;
- index = (int)d_index;
- if (index < 0 || index >= array->n_values)
- {
- printf ("range check\n");
- psc->quit = 1;
- return;
- }
- psc->n_values -= 1;
- psc->value_stack[psc->n_values - 1] = array->vals[index];
- }
- else if (get_stack_array (psc, &array, 2) &&
- get_stack_number (psc, &d_index, 1))
- {
- /* array index get val */
- index = (int)d_index;
- if (index < 0 || index >= array->n_values)
- {
- printf ("range check\n");
- psc->quit = 1;
- return;
- }
- psc->n_values -= 1;
- psc->value_stack[psc->n_values - 1] = array->vals[index];
- }
- }
- static void
- internal_index (Gt1PSContext *psc)
- {
- double d_index;
- int index;
- if (get_stack_number (psc, &d_index, 1))
- {
- index = (int)d_index;
- if (index < 0 || index > psc->n_values - 2)
- {
- printf ("index range check\n");
- psc->quit = 1;
- return;
- }
- psc->value_stack[psc->n_values - 1] =
- psc->value_stack[psc->n_values - (index + 2)];
- }
- }
- static void
- internal_definefont (Gt1PSContext *psc)
- {
- Gt1NameId key;
- Gt1Dict *dict;
- if (psc->n_values < 2)
- {
- printf ("stack underflow\n");
- psc->quit = 1;
- }
- else if (get_stack_name (psc, &key, 2))
- {
- dict = psc->fonts;
- gt1_dict_def (psc->r, dict, key, &psc->value_stack[psc->n_values - 1]);
- #ifdef VERBOSE
- print_value_deep (psc, &psc->value_stack[psc->n_values - 1], 0);
- #endif
- psc->n_values -= 1;
- }
- }
- static void
- internal_mark (Gt1PSContext *psc)
- {
- ensure_stack (psc, 1);
- psc->value_stack[psc->n_values].type = GT1_VAL_MARK;
- psc->n_values++;
- }
- static void
- internal_closefile (Gt1PSContext *psc)
- {
- Gt1TokenContext *tc;
- if (get_stack_file (psc, &tc, 1))
- {
- if (psc->n_files == 1)
- {
- printf ("file stack underflow\n");
- psc->quit = 1;
- }
- else if (psc->file_stack[psc->n_files - 1] == tc)
- {
- /* pop the file stack */
- tokenize_free (psc->tc);
- psc->n_files--;
- psc->tc = psc->file_stack[psc->n_files - 1];
- psc->n_values--;
- }
- else
- {
- printf ("closefile: whoa, file cowboy!\n");
- psc->quit = 1;
- }
- }
- }
- static void
- internal_cleartomark (Gt1PSContext *psc)
- {
- int i;
- for (i = psc->n_values - 1; i >= 0; i--)
- if (psc->value_stack[i].type == GT1_VAL_MARK)
- break;
- if (psc->value_stack[i].type != GT1_VAL_MARK)
- {
- printf ("cleartomark: unmatched mark\n");
- psc->quit = 1;
- }
- psc->n_values = i;
- }
- static void
- internal_systemdict (Gt1PSContext *psc)
- {
- ensure_stack (psc, 1);
- psc->value_stack[psc->n_values].type = GT1_VAL_DICT;
- psc->value_stack[psc->n_values].val.dict_val =
- psc->gt1_dict_stack[0];
- psc->n_values++;
- }
- static void
- internal_userdict (Gt1PSContext *psc)
- {
- ensure_stack (psc, 1);
- psc->value_stack[psc->n_values].type = GT1_VAL_DICT;
- psc->value_stack[psc->n_values].val.dict_val =
- psc->gt1_dict_stack[2];
- psc->n_values++;
- }
- static void
- internal_known (Gt1PSContext *psc)
- {
- Gt1NameId key;
- Gt1Dict *dict;
- int known;
- if (psc->n_values >= 2 &&
- get_stack_dict (psc, &dict, 2) &&
- get_stack_name (psc, &key, 1))
- {
- known = (gt1_dict_lookup (dict, key) != 0);
- psc->n_values -= 1;
- psc->value_stack[psc->n_values - 1].type = GT1_VAL_BOOL;
- psc->value_stack[psc->n_values - 1].val.bool_val = known;
- }
- }
- static void
- internal_ifelse (Gt1PSContext *psc)
- {
- Gt1Proc *proc1, *proc2;
- int bool;
- if (psc->n_values >= 3 &&
- get_stack_bool (psc, &bool, 3) &&
- get_stack_proc (psc, &proc1, 2) &&
- get_stack_proc (psc, &proc2, 1))
- {
- psc->n_values -= 3;
- if (bool)
- eval_proc (psc, proc1);
- else
- eval_proc (psc, proc2);
- }
- }
- static void
- internal_if (Gt1PSContext *psc)
- {
- Gt1Proc *proc;
- int bool;
- if (psc->n_values >= 2 &&
- get_stack_bool (psc, &bool, 2) &&
- get_stack_proc (psc, &proc, 1))
- {
- psc->n_values -= 2;
- if (bool)
- eval_proc (psc, proc);
- }
- }
- static void
- internal_for (Gt1PSContext *psc)
- {
- double initial, increment, limit;
- Gt1Proc *proc;
- double val;
- if (psc->n_values >= 4 &&
- get_stack_number (psc, &initial, 4) &&
- get_stack_number (psc, &increment, 3) &&
- get_stack_number (psc, &limit, 2) &&
- get_stack_proc (psc, &proc, 1))
- {
- psc->n_values -= 4;
- for (val = initial; !psc->quit &&
- (increment > 0 ? (val <= limit) : (val >= limit));
- val += increment)
- {
- ensure_stack (psc, 1);
- psc->value_stack[psc->n_values].type = GT1_VAL_NUM;
- psc->value_stack[psc->n_values].val.num_val = val;
- psc->n_values++;
- eval_proc (psc, proc);
- }
- }
- }
- static void
- internal_not (Gt1PSContext *psc)
- {
- int bool;
- if (psc->n_values >= 1 &&
- get_stack_bool (psc, &bool, 1))
- {
- psc->value_stack[psc->n_values - 1].val.bool_val = !bool;
- }
- }
- static void
- internal_bind (Gt1PSContext *psc)
- {
- Gt1Proc *proc;
- if (psc->n_values >= 1 &&
- get_stack_proc (psc, &proc, 1))
- {
- /* todo: implement, when procs become normal values */
- }
- }
- static void
- internal_exec (Gt1PSContext *psc)
- {
- Gt1Proc *proc;
- if (psc->n_values >= 1 &&
- get_stack_proc (psc, &proc, 1))
- {
- psc->n_values -= 1;
- eval_proc (psc, proc);
- }
- }
- static void
- internal_count (Gt1PSContext *psc)
- {
- ensure_stack (psc, 1);
- psc->value_stack[psc->n_values].type = GT1_VAL_NUM;
- psc->value_stack[psc->n_values].val.num_val = psc->n_values;
- psc->n_values++;
- }
- static void
- internal_eq (Gt1PSContext *psc)
- {
- double a, b;
- Gt1NameId na, nb;
- if (psc->n_values < 2)
- {
- printf ("stack underflow\n");
- psc->quit = 1;
- return;
- }
- if (psc->value_stack[psc->n_values - 1].type == GT1_VAL_NAME &&
- get_stack_name (psc, &na, 2) &&
- get_stack_name (psc, &nb, 1))
- {
- psc->n_values -= 1;
- psc->value_stack[psc->n_values - 1].type = GT1_VAL_BOOL;
- psc->value_stack[psc->n_values - 1].val.bool_val = (na == nb);
- }
- else if (get_stack_number (psc, &a, 2) &&
- get_stack_number (psc, &b, 1))
- {
- psc->n_values -= 1;
- psc->value_stack[psc->n_values - 1].type = GT1_VAL_BOOL;
- psc->value_stack[psc->n_values - 1].val.bool_val = (a == b);
- }
- }
- static void
- internal_ne (Gt1PSContext *psc)
- {
- internal_eq (psc);
- if (!psc->quit)
- psc->value_stack[psc->n_values - 1].val.bool_val =
- !psc->value_stack[psc->n_values - 1].val.bool_val;
- }
- static void
- internal_type (Gt1PSContext *psc)
- {
- Gt1ValueType type;
- if (psc->n_values >= 1)
- {
- type = psc->value_stack[psc->n_values - 1].type;
- if (type == GT1_VAL_NUM)
- {
- psc->value_stack[psc->n_values - 1].type = GT1_VAL_NAME;
- psc->value_stack[psc->n_values - 1].val.name_val =
- gt1_name_context_intern (psc->nc, "integertype");
- }
- else
- {
- printf ("type not fully implemented");
- }
- }
- }
- static void
- internal_cvx (Gt1PSContext *psc)
- {
- Gt1Value *val;
- if (psc->n_values < 1)
- {
- printf ("stack underflow\n");
- psc->quit = 1;
- }
- else
- {
- val = &psc->value_stack[psc->n_values - 1];
- if (val->type == GT1_VAL_NAME)
- val->type = GT1_VAL_UNQ_NAME;
- else if (val->type == GT1_VAL_ARRAY)
- val->type = GT1_VAL_PROC;
- else
- {
- printf ("warning: cvx called on ");
- print_value (psc, val);
- printf ("\n");
- }
- }
- }
- static void
- internal_matrix (Gt1PSContext *psc)
- {
- Gt1Array *array;
- int i;
- array = array_new (psc->r, 6);
- for (i = 0; i < 6; i++)
- {
- array->vals[i].type = GT1_VAL_NUM;
- array->vals[i].val.num_val = (i == 0 || i == 3);
- }
- psc->value_stack[psc->n_values].type = GT1_VAL_ARRAY;
- psc->value_stack[psc->n_values].val.array_val = array;
- psc->n_values++;
- }
- static void
- internal_FontDirectory (Gt1PSContext *psc)
- {
- ensure_stack (psc, 1);
- psc->value_stack[psc->n_values].type = GT1_VAL_DICT;
- psc->value_stack[psc->n_values].val.dict_val = psc->fonts;
- psc->n_values++;
- }
- /* the table of internal procedures */
- typedef struct _InternalGt1ProcListing {
- char *name;
- void (*function) (Gt1PSContext *psc);
- } InternalGt1ProcListing;
- InternalGt1ProcListing internal_procs[] = {
- { "dict", internal_dict },
- { "begin", internal_begin },
- { "end", internal_end },
- { "dup", internal_dup },
- { "pop", internal_pop },
- { "exch", internal_exch },
- { "readonly", internal_readonly },
- { "executeonly", internal_executeonly },
- { "noaccess", internal_noaccess },
- { "def", internal_def },
- { "false", internal_false },
- { "true", internal_true },
- { "StandardEncoding", internal_StandardEncoding },
- { "[", internalop_openbracket },
- { "]", internalop_closebracket },
- { "currentdict", internal_currentdict },
- { "currentfile", internal_currentfile },
- { "eexec", internal_eexec },
- { "array", internal_array },
- { "string", internal_string },
- { "readstring", internal_readstring },
- { "put", internal_put },
- { "get", internal_get },
- { "index", internal_index },
- { "definefont", internal_definefont },
- { "mark", internal_mark },
- { "closefile", internal_closefile },
- { "cleartomark", internal_cleartomark },
- { "systemdict", internal_systemdict },
- { "userdict", internal_userdict },
- { "known", internal_known },
- { "ifelse", internal_ifelse },
- { "if", internal_if },
- { "for", internal_for },
- { "not", internal_not },
- { "bind", internal_bind },
- { "exec", internal_exec },
- { "count", internal_count },
- { "eq", internal_eq },
- { "ne", internal_ne },
- { "type", internal_type },
- { "cvx", internal_cvx },
- { "matrix", internal_matrix },
- { "FontDirectory", internal_FontDirectory }
- };
- /* here end the internal procedures */
- static Gt1PSContext *
- pscontext_new (Gt1TokenContext *tc)
- {
- Gt1PSContext *psc;
- Gt1Dict *systemdict;
- Gt1Dict *globaldict;
- Gt1Dict *userdict;
- int i;
- Gt1Value val;
- psc = gt1_new (Gt1PSContext, 1);
- psc->r = gt1_region_new ();
- psc->tc = tc;
- psc->nc = gt1_name_context_new ();
- psc->n_values = 0;
- psc->n_values_max = 16;
- psc->value_stack = gt1_new (Gt1Value, psc->n_values_max);
- psc->n_dicts_max = 16;
- psc->gt1_dict_stack = gt1_new (Gt1Dict *, psc->n_dicts_max);
- systemdict = gt1_dict_new (psc->r, sizeof(internal_procs) /
- sizeof(InternalGt1ProcListing));
- for (i = 0; i < sizeof(internal_procs) / sizeof(InternalGt1ProcListing); i++)
- {
- val.type = GT1_VAL_INTERNAL;
- val.val.internal_val = internal_procs[i].function;
- gt1_dict_def (psc->r, systemdict,
- gt1_name_context_intern (psc->nc,
- internal_procs[i].name),
- &val);
- }
- psc->gt1_dict_stack[0] = systemdict;
- globaldict = gt1_dict_new (psc->r, 16);
- psc->gt1_dict_stack[1] = globaldict;
- userdict = gt1_dict_new (psc->r, 16);
- psc->gt1_dict_stack[2] = userdict;
- psc->n_dicts = 3;
- psc->fonts = gt1_dict_new (psc->r, 1);
- psc->n_files_max = 16;
- psc->file_stack = gt1_new (Gt1TokenContext *, psc->n_files_max);
- psc->file_stack[0] = tc;
- psc->n_files = 1;
- psc->quit = 0;
- return psc;
- }
- static void
- pscontext_free (Gt1PSContext *psc)
- {
- /* Empty the value stack. */
- while (psc->n_values > 0) internal_pop (psc);
- gt1_free (psc->value_stack);
- gt1_free (psc->file_stack);
- gt1_free (psc->gt1_dict_stack);
- gt1_name_context_free (psc->nc);
- gt1_region_free (psc->r);
- gt1_free (psc);
- }
- static void
- eval_executable (Gt1PSContext *psc, Gt1Value *val)
- {
- switch (val->type)
- {
- case GT1_VAL_INTERNAL:
- val->val.internal_val (psc);
- break;
- case GT1_VAL_PROC:
- eval_proc (psc, val->val.proc_val);
- break;
- default:
- ensure_stack (psc, 1);
- psc->value_stack[psc->n_values] = *val;
- psc->n_values++;
- break;
- }
- }
- /* Scan a value from the psc's token context - usually one token, or
- a proc. Return the token type. */
- static TokenType
- parse_ps_token (Gt1PSContext *psc, Gt1Value *val)
- {
- MyGt1String lexeme;
- TokenType type;
- Gt1Proc *proc;
- int n_proc, n_proc_max;
- type = tokenize_get (psc->tc, &lexeme);
- switch (type)
- {
- case TOK_NUM:
- val->type = GT1_VAL_NUM;
- val->val.num_val = parse_num (&lexeme);
- break;
- case TOK_NAME:
- val->type = GT1_VAL_NAME;
- val->val.name_val =
- gt1_name_context_intern_size (psc->nc, lexeme.start,
- lexeme.fin - lexeme.start);
- break;
- case TOK_STR:
- val->type = GT1_VAL_STR;
- /* todo: processing of escape characters */
- val->val.str_val.start = lexeme.start;
- val->val.str_val.size = lexeme.fin - lexeme.start;
- break;
- case TOK_IDENT:
- val->type = GT1_VAL_UNQ_NAME;
- val->val.name_val =
- gt1_name_context_intern_size (psc->nc, lexeme.start,
- lexeme.fin - lexeme.start);
- break;
- case TOK_OPENBRACE:
- n_proc = 0;
- n_proc_max = 16;
- proc = (Gt1Proc *)gt1_region_alloc (psc->r, sizeof(Gt1Proc) +
- (n_proc_max - 1) *
- sizeof(Gt1Value));
- while (1)
- {
- if (n_proc == n_proc_max)
- {
- int old_size;
- old_size = sizeof(Gt1Proc) + (n_proc_max - 1) * sizeof(Gt1Value);
- n_proc_max <<= 1;
- proc = (Gt1Proc *)gt1_region_realloc (psc->r, proc,
- old_size,
- sizeof(Gt1Proc) +
- (n_proc_max - 1) *
- sizeof(Gt1Value));
- }
- if (parse_ps_token (psc, &proc->vals[n_proc]) == TOK_CLOSEBRACE ||
- psc->quit)
- break;
- n_proc++;
- }
- proc->n_values = n_proc;
- val->type = GT1_VAL_PROC;
- val->val.proc_val = proc;
- break;
- case TOK_CLOSEBRACE:
- case TOK_END:
- break;
- default:
- printf ("unimplemented token type\n");
- psc->quit = 1;
- break;
- }
- return type;
- }
- static void
- eval_ps_val (Gt1PSContext *psc, Gt1Value *val)
- {
- Gt1Value *new_val;
- #ifdef VERBOSE
- print_value (psc, val);
- printf ("\n");
- #endif
- switch (val->type)
- {
- case GT1_VAL_NUM:
- case GT1_VAL_BOOL:
- case GT1_VAL_STR:
- case GT1_VAL_NAME:
- case GT1_VAL_ARRAY:
- case GT1_VAL_PROC:
- case GT1_VAL_DICT:
- ensure_stack (psc, 1);
- psc->value_stack[psc->n_values] = *val;
- psc->n_values++;
- break;
- case GT1_VAL_UNQ_NAME:
- new_val = gt1_dict_stack_lookup (psc, val->val.name_val);
- if (new_val != NULL)
- eval_executable (psc, new_val);
- else
- {
- printf ("undefined identifier ");
- print_value (psc, val);
- putchar ('\n');
- psc->quit = 1;
- }
- break;
- case GT1_VAL_INTERNAL:
- val->val.internal_val (psc);
- break;
- default:
- printf ("value not handled\n");
- psc->quit = 1;
- break;
- }
- #ifdef VERBOSE
- if (!psc->quit)
- {
- printf (" ");
- print_stack (psc);
- }
- #endif
- }
- /* maybe we should return the dict; easier to handle */
- static Gt1PSContext *
- eval_ps (Gt1TokenContext *tc)
- {
- TokenType type;
- Gt1PSContext *psc;
- Gt1Value val;
- psc = pscontext_new (tc);
- do {
- type = parse_ps_token (psc, &val);
- if (type == TOK_END) break;
- if (type == TOK_CLOSEBRACE)
- {
- printf ("unexpected close brace\n");
- break;
- }
- eval_ps_val (psc, &val);
- } while (!psc->quit);
- return psc;
- }
- /* This routine _assumes_ that plaintext is passed in with enough
- space to hold the decrypted text */
- static void
- charstring_decrypt (Gt1String *plaintext, Gt1String *ciphertext)
- {
- int ciphertext_size;
- int i;
- unsigned short r;
- unsigned char cipher;
- unsigned char plain;
- ciphertext_size = ciphertext->size;
- if (plaintext->size < ciphertext_size - 4)
- {
- printf ("not enough space allocated for charstring decryption\n");
- return;
- }
- r = 4330; /* initial key */
- for (i = 0; i < ciphertext_size; i++)
- {
- cipher = ciphertext->start[i];
- plain = (cipher ^ (r>>8));
- r = (cipher + r) * EEXEC_C1 + EEXEC_C2;
- if (i >= 4)
- plaintext->start[i - 4] = plain;
- }
- plaintext->size = ciphertext->size - 4;
- }
- #ifdef VERBOSE
- static void
- print_glyph_code (Gt1String *glyph_code)
- {
- Gt1String plaintext;
- int i;
- int byte, byte1, byte2, byte3, byte4;
- plaintext.start = gt1_alloc (glyph_code->size);
- plaintext.size = glyph_code->size;
- charstring_decrypt (&plaintext, glyph_code);
- for (i = 0; i < plaintext.size; i++)
- {
- byte = ((unsigned char *)plaintext.start)[i];
- if (byte >= 32 && byte <= 246)
- printf (" %d", byte - 139);
- else if (byte >= 247 && byte <= 250)
- {
- byte1 = ((unsigned char *)plaintext.start)[++i];
- printf (" %d", ((byte - 247) << 8) + byte1 + 108);
- }
- else if (byte >= 251 && byte <= 254)
- {
- byte1 = ((unsigned char *)plaintext.start)[++i];
- printf (" %d", -((byte - 251) << 8) - byte1 - 108);
- }
- else if (byte == 255)
- {
- byte1 = ((unsigned char *)plaintext.start)[++i];
- byte2 = ((unsigned char *)plaintext.start)[++i];
- byte3 = ((unsigned char *)plaintext.start)[++i];
- byte4 = ((unsigned char *)plaintext.start)[++i];
- /* warning: this _must_ be a 32 bit int - alpha portability
- issue! */
- printf (" %d", (byte1 << 24) + (byte2 << 16) + (byte3 << 8) + byte4);
- }
- else if (byte == 12)
- {
- byte1 = ((unsigned char *)plaintext.start)[++i];
- if (byte1 == 6)
- printf (" seac");
- else if (byte1 == 7)
- printf (" sbw");
- else if (byte1 == 0)
- printf (" dotsection");
- else if (byte1 == 2)
- printf (" hstem3");
- else if (byte1 == 1)
- printf (" vstem3");
- else if (byte1 == 12)
- printf (" div");
- else if (byte1 == 16)
- printf (" callothersubr");
- else if (byte1 == 17)
- printf (" pop");
- else if (byte1 == 33)
- printf (" setcurrentpoint");
- else
- printf (" esc%d", byte1);
- }
- else if (byte == 14)
- printf (" endchar");
- else if (byte == 13)
- printf (" hsbw");
- else if (byte == 9)
- printf (" closepath");
- else if (byte == 6)
- printf (" hlineto");
- else if (byte == 22)
- printf (" hmoveto");
- else if (byte == 31)
- printf (" hvcurveto");
- else if (byte == 5)
- printf (" rlineto");
- else if (byte == 21)
- printf (" rmoveto");
- else if (byte == 8)
- printf (" rrcurveto");
- else if (byte == 30)
- printf (" vhcurveto");
- else if (byte == 7)
- printf (" vlineto");
- else if (byte == 4)
- printf (" vmoveto");
- else if (byte == 1)
- printf (" hstem");
- else if (byte == 3)
- printf (" vstem");
- else if (byte == 10)
- printf (" callsubr");
- else if (byte == 11)
- printf (" return");
- else
- printf (" com%d", byte);
- }
- printf ("\n");
- gt1_free (plaintext.start);
- }
- #endif
- /* Gt1Dict is the toplevel font dict. This allocates a new string for the
- plaintext and stores it in body. */
- static void
- get_subr_body (Gt1PSContext *psc, Gt1String *body, Gt1Dict *fontdict, int subr)
- {
- Gt1Value *private_val;
- Gt1Value *subrs_val;
- Gt1Array *subrs_array;
- Gt1String *ciphertext;
- private_val = gt1_dict_lookup (fontdict,
- gt1_name_context_intern (psc->nc, "Private"));
- if (private_val == NULL)
- {
- printf ("No Private array\n");
- return;
- }
- subrs_val = gt1_dict_lookup (private_val->val.dict_val,
- gt1_name_context_intern (psc->nc, "Subrs"));
- if (subrs_val == NULL)
- {
- printf ("No Subrs array\n");
- return;
- }
- subrs_array = subrs_val->val.array_val;
- /* more type & range checking */
- ciphertext = &subrs_array->vals[subr].val.str_val;
- body->start = gt1_alloc (ciphertext->size);
- body->size = ciphertext->size;
- charstring_decrypt (body, ciphertext);
- }
- typedef struct _BezState {
- ArtBpath *bezpath;
- int size_bezpath, size_bezpath_max;
- /* this is designed to do compression of a string of moveto's in a row. */
- int need_moveto;
- double x, y; /* current point */
- double x0, y0; /* beginning of subpath */
- } BezState;
- static BezState *
- bs_new (void)
- {
- BezState *bs;
- bs = gt1_new (BezState, 1);
- bs->size_bezpath = 0;
- bs->size_bezpath_max = 16;
- bs->bezpath = gt1_new (ArtBpath, bs->size_bezpath_max);
- bs->x = 0;
- bs->y = 0;
- bs->x0 = 0;
- bs->y0 = 0;
- bs->need_moveto = 1;
- return bs;
- }
- static void
- bs_moveto (BezState *bs, double x, double y)
- {
- bs->x = x;
- bs->y = y;
- bs->need_moveto = 1;
- }
- static void
- bs_rmoveto (BezState *bs, double dx, double dy)
- {
- bs->x += dx;
- bs->y += dy;
- bs->need_moveto = 1;
- }
- static void
- bs_do_moveto (BezState *bs)
- {
- ArtBpath *bezpath;
- int size_bezpath;
- if (bs->need_moveto)
- {
- bezpath = bs->bezpath;
- size_bezpath = bs->size_bezpath;
- if (size_bezpath == bs->size_bezpath_max)
- {
- gt1_double (bezpath, ArtBpath, bs->size_bezpath_max);
- bs->bezpath = bezpath;
- }
- bezpath[size_bezpath].code = ART_MOVETO;
- bezpath[size_bezpath].x1 = 0;
- bezpath[size_bezpath].y1 = 0;
- bezpath[size_bezpath].x2 = 0;
- bezpath[size_bezpath].y2 = 0;
- bezpath[size_bezpath].x3 = bs->x;
- bezpath[size_bezpath].y3 = bs->y;
- bs->size_bezpath++;
- bs->x0 = bs->x;
- bs->y0 = bs->y;
- bs->need_moveto = 0;
- }
- }
- static void
- bs_rlineto (BezState *bs, double dx, double dy)
- {
- ArtBpath *bezpath;
- int size_bezpath;
- bs_do_moveto (bs);
- bezpath = bs->bezpath;
- size_bezpath = bs->size_bezpath;
- if (size_bezpath == …
Large files files are truncated, but you can click here to view the full file