diff options
Diffstat (limited to 'pdf/pdf_fontps.c')
-rw-r--r-- | pdf/pdf_fontps.c | 1239 |
1 files changed, 1239 insertions, 0 deletions
diff --git a/pdf/pdf_fontps.c b/pdf/pdf_fontps.c new file mode 100644 index 00000000..7ee9d2f0 --- /dev/null +++ b/pdf/pdf_fontps.c @@ -0,0 +1,1239 @@ +/* Copyright (C) 2020-2021 Artifex Software, Inc. + All Rights Reserved. + + This software is provided AS-IS with no warranty, either express or + implied. + + This software is distributed under license and may not be copied, + modified or distributed except as expressly authorized under the terms + of the license contained in the file LICENSE in this distribution. + + Refer to licensing information at http://www.artifex.com or contact + Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato, + CA 94945, U.S.A., +1(415)492-9861, for further information. +*/ + +/* common code for Postscript-type font handling */ +#include "scanchar.h" +#include "sfilter.h" +#include "stream.h" +#include "strimpl.h" + +#include "pdf_int.h" +#include "pdf_types.h" +#include "pdf_array.h" +#include "pdf_dict.h" +#include "pdf_font.h" +#include "pdf_font_types.h" +#include "pdf_fontps.h" + +static const char *const notdefnamestr = ".notdef"; + +int +pdfi_pscript_stack_init(pdf_context *pdfi_ctx, pdf_ps_oper_list_t *ops, void *client_data, + pdf_ps_ctx_t *s) +{ + int i, size = PDF_PS_STACK_SIZE; + int initsizebytes = sizeof(pdf_ps_stack_object_t) * PDF_PS_STACK_SIZE; + s->pdfi_ctx = pdfi_ctx; + s->ops = ops; + s->client_data = client_data; + + s->stack = (pdf_ps_stack_object_t *)gs_alloc_bytes(pdfi_ctx->memory, initsizebytes, "pdfi_pscript_stack_init(stack)"); + if (s->stack == NULL) + return_error(gs_error_VMerror); + + s->cur = s->stack + 1; + s->toplim = s->cur + size; + + for (i = 0; i < PDF_PS_STACK_GUARDS; i++) + s->stack[i].type = PDF_PS_OBJ_STACK_BOTTOM; + + for (i = 0; i < PDF_PS_STACK_GUARDS; i++) + s->stack[size - 1 + i].type = PDF_PS_OBJ_STACK_TOP; + + for (i = 0; i < size - 1; i++) { + pdf_ps_make_null(&(s->cur[i])); + } + return 0; +} + +void +pdfi_pscript_stack_finit(pdf_ps_ctx_t *s) +{ + int stackdepth; + + if ((stackdepth = pdf_ps_stack_count(s)) > 0) { + pdf_ps_stack_pop(s, stackdepth); + } + gs_free_object(s->pdfi_ctx->memory, s->stack, "pdfi_pscript_stack_finit(stack)"); +} + +int +ps_pdf_null_oper_func(gs_memory_t *mem, pdf_ps_ctx_t *stack, byte *buf, byte *bufend) +{ + return 0; +} + +int +clear_stack_oper_func(gs_memory_t *mem, pdf_ps_ctx_t *s, byte *buf, byte *bufend) +{ + int depth = s->cur - &(s->stack[1]); + + return pdf_ps_stack_pop(s, depth); +} + +int +pdf_ps_pop_oper_func(gs_memory_t *mem, pdf_ps_ctx_t *s, byte *buf, byte *bufend) +{ + return pdf_ps_stack_pop(s, 1); +} + +int +pdf_ps_pop_and_pushmark_func(gs_memory_t *mem, pdf_ps_ctx_t *stack, byte *buf, byte *bufend) +{ + int code = pdf_ps_stack_pop(stack, 1); + + if (code >= 0) + code = pdf_ps_stack_push_mark(stack); + return code; +} + +static inline int +pdf_ps_is_whitespace(int c) +{ + return (c == 0x20) || (c == 0x9) || (c == 0xD) || (c == 0xA); +} + +static inline int +pdf_ps_end_object(int c) +{ + return pdf_ps_is_whitespace(c) || (c == '/') || (c == '[') || (c == ']') || c == '{' || c == '}' || (c == '(') || (c == '<'); +} + +static inline int +pdf_ps_end_number_object(int c) +{ + return (c != '.' && c != 'e' && c != '-' && (c < '0' || c > '9')); +} + +static inline bool +ishex(char c) +{ + if (c < 0x30) + return false; + + if (c > 0x39) { + if (c > 'F') { + if (c < 'a') + return false; + if (c > 'f') + return false; + return true; + } + else { + if (c < 'A') + return false; + return true; + } + } + else + return true; +} + +static inline int +decodehex(char c) +{ + int retval = 0; + + if (ishex(c)) { + if (c > 0x39) { + if (c > 'F') { + retval = c - 0x57; + } + else { + retval = c - 0x37; + } + } + else { + retval = c - 0x30; + } + } + return retval; +} + +int +pdfi_pscript_interpret(pdf_ps_ctx_t *cs, byte *pdfpsbuf, int64_t buflen) +{ + int code = 0; + byte *buflim = pdfpsbuf + buflen; + int arraydepth = 0; + int stackdepth; + + while (pdfpsbuf < buflim && code >= 0) { + switch (*pdfpsbuf++) { + case '%': /* Comment */ + { + while (pdfpsbuf < buflim && *pdfpsbuf != char_EOL && *pdfpsbuf != '\f' && + *pdfpsbuf != char_CR) + pdfpsbuf++; + + if (*pdfpsbuf == char_EOL) + pdfpsbuf++; + } + break; + case '/': /* name */ + { + byte *n = pdfpsbuf; + int len; + + while (pdfpsbuf < buflim && !pdf_ps_end_object((int)*pdfpsbuf)) + pdfpsbuf++; + len = pdfpsbuf - n; + code = pdf_ps_stack_push_name(cs, n, len); + } break; + case '(': /* string */ + { + byte *s = pdfpsbuf; + int len; + int depth = 1; + + while (pdfpsbuf < buflim && depth > 0) { + if (*pdfpsbuf == '(') { + depth++; + } + else if (*pdfpsbuf == ')') { + depth--; + } + pdfpsbuf++; + } + len = (pdfpsbuf - s) - 1; + code = pdf_ps_stack_push_string(cs, s, len); + } + break; + case '<': /* hex string */ + { + byte *s = pdfpsbuf; + byte *s2 = s; + int len, i; + byte hbuf[2]; + + if (pdfpsbuf < buflim && *pdfpsbuf == '<') { /* Dict opening "<<" - we don't care */ + pdfpsbuf++; + continue; + } + while (pdfpsbuf < buflim && *pdfpsbuf != '>') + pdfpsbuf++; + len = pdfpsbuf - s; + while (len % 2) + len--; + for (i = 0; i < len; i += 2) { + hbuf[0] = s[i]; + hbuf[1] = s[i + 1]; + *s2++ = (decodehex(hbuf[0]) << 4) | decodehex(hbuf[1]); + } + pdfpsbuf++; /* move past the trailing '>' */ + code = pdf_ps_stack_push_string(cs, s, len >> 1); + } + break; + case '>': /* For hex strings, this should be handled above */ + { + if (pdfpsbuf < buflim && *pdfpsbuf == '>') { /* Dict closing "<<" - we still don't care */ + pdfpsbuf++; + } + } + break; + case '[':; /* begin array */ + case '{':; /* begin executable array (mainly, FontBBox) */ + arraydepth++; + code = pdf_ps_stack_push_arr_mark(cs); + break; + case ']': /* end array */ + case '}': /* end executable array */ + { + pdf_ps_stack_object_t *arr = NULL; + int i, size = pdf_ps_stack_count_to_mark(cs, PDF_PS_OBJ_ARR_MARK); + + if (size > 0 && arraydepth > 0) { + arr = (pdf_ps_stack_object_t *) gs_alloc_bytes(cs->pdfi_ctx->memory, size * sizeof(pdf_ps_stack_object_t), "pdfi_pscript_interpret(pdf_ps_stack_object_t"); + if (arr == NULL) { + code = gs_note_error(gs_error_VMerror); + /* clean up the stack, including the mark object */ + (void)pdf_ps_stack_pop(cs, size + 1); + size = 0; + } + else { + for (i = 0; i < size; i++) { + memcpy(&(arr[(size - 1) - i]), cs->cur, sizeof(*cs->cur)); + if (pdf_ps_obj_has_type(cs->cur, PDF_PS_OBJ_ARRAY)) { + pdf_ps_make_null(cs->cur); + } + (void)pdf_ps_stack_pop(cs, 1); + } + /* And pop the array mark */ + (void)pdf_ps_stack_pop(cs, 1); + } + } + else { + /* And pop the array mark for an emtpy array */ + (void)pdf_ps_stack_pop(cs, 1); + } + code = pdf_ps_stack_push_array(cs, arr, size > 0 ? size : 0); + arraydepth--; + if (arraydepth < 0) + arraydepth = 0; + } + break; + case '.': + case '-': + case '+': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9':{ + bool is_float = false; + int len; + byte *n = --pdfpsbuf, *numbuf; + + while (pdfpsbuf < buflim && !pdf_ps_end_number_object((int)*pdfpsbuf)) { + if (*pdfpsbuf == '.' || *pdfpsbuf == 'e') + is_float = true; + pdfpsbuf++; + } + len = pdfpsbuf - n; + if (len == 1 && *n == '-') { + /* Not a number, might be an operator */ + pdfpsbuf = n + 1; + goto retry_as_oper; + } + numbuf = gs_alloc_bytes(cs->pdfi_ctx->memory, len + 1, "ps pdf number buffer"); + if (numbuf == NULL) { + code = gs_note_error(gs_error_VMerror); + } + else { + memcpy(numbuf, n, len); + numbuf[len] = '\0'; + if (is_float) { + float f = (float)atof((const char *)numbuf); + + code = pdf_ps_stack_push_float(cs, f); + } + else { + int i = atoi((const char *)numbuf); + + code = pdf_ps_stack_push_int(cs, i); + } + gs_free_object(cs->pdfi_ctx->memory, numbuf, "ps pdf number buffer"); + } + } break; + case ' ': + case '\f': + case '\t': + case char_CR: + case char_EOL: + case char_NULL: + break; + default: + retry_as_oper:{ + byte *n = --pdfpsbuf; + int len, i; + int (*opfunc)(gs_memory_t *mem, pdf_ps_ctx_t *stack, byte *buf, byte *bufend) = NULL; + pdf_ps_oper_list_t *ops = cs->ops; + + while (pdfpsbuf < buflim && !pdf_ps_end_object((int)*pdfpsbuf)) + pdfpsbuf++; + + if (arraydepth == 0) { + len = pdfpsbuf - n; + for (i = 0; ops[i].opname != NULL; i++) { + if (len == ops[i].opnamelen && !memcmp(n, ops[i].opname, len)) { + opfunc = ops[i].oper; + break; + } + } + + if (opfunc) { + code = (*opfunc) (cs->pdfi_ctx->memory, cs, pdfpsbuf, buflim); + if (code > 0) { + pdfpsbuf += code; + code = 0; + } + } + } + } + break; + } + } + if ((stackdepth = pdf_ps_stack_count(cs)) > 0) { + pdf_ps_stack_pop(cs, stackdepth); + } + return code; +} + +static int +ps_font_def_func(gs_memory_t *mem, pdf_ps_ctx_t *s, byte *buf, byte *bufend) +{ + int code = 0, code2 = 0; + ps_font_interp_private *priv = (ps_font_interp_private *) s->client_data; + + if ((code = pdf_ps_stack_count(s)) < 2) { + return pdf_ps_stack_pop(s, code); + } + + if (pdf_ps_obj_has_type(&s->cur[-1], PDF_PS_OBJ_NAME)) { + if (!memcmp(s->cur[-1].val.name, PDF_PS_OPER_NAME_AND_LEN("FontName"))) { + int fnlen = 0; + char *pname = NULL; + + if (pdf_ps_obj_has_type(&s->cur[0], PDF_PS_OBJ_NAME)) { + fnlen = s->cur[0].size > gs_font_name_max ? gs_font_name_max : s->cur[0].size; + pname = (char *)s->cur[0].val.name; + } + else if (pdf_ps_obj_has_type(&s->cur[0], PDF_PS_OBJ_STRING)) { + fnlen = s->cur[0].size > gs_font_name_max ? gs_font_name_max : s->cur[0].size; + pname = (char *)s->cur[0].val.string; + } + if (pname) { + memcpy(priv->gsu.gst1.key_name.chars, pname, fnlen); + priv->gsu.gst1.key_name.chars[fnlen] = '\0'; + priv->gsu.gst1.key_name.size = fnlen; + + memcpy(priv->gsu.gst1.font_name.chars, pname, fnlen); + priv->gsu.gst1.font_name.chars[fnlen] = '\0'; + priv->gsu.gst1.font_name.size = fnlen; + } + } + else if (!memcmp(s->cur[-1].val.name, PDF_PS_OPER_NAME_AND_LEN("PaintType"))) { + if (pdf_ps_obj_has_type(&s->cur[0], PDF_PS_OBJ_INTEGER)) { + priv->gsu.gst1.PaintType = s->cur[0].val.i; + } + } + else if (!memcmp(s->cur[-1].val.name, PDF_PS_OPER_NAME_AND_LEN("StrokeWidth"))) { + if (pdf_ps_obj_has_type(&s->cur[0], PDF_PS_OBJ_FLOAT)) { + priv->gsu.gst1.StrokeWidth = s->cur[0].val.f; + } + else if (pdf_ps_obj_has_type(&s->cur[0], PDF_PS_OBJ_INTEGER)) { + priv->gsu.gst1.StrokeWidth = (float)s->cur[0].val.i; + } + } + else if (!memcmp(s->cur[-1].val.name, PDF_PS_OPER_NAME_AND_LEN("WMode"))) { + if (pdf_ps_obj_has_type(&s->cur[0], PDF_PS_OBJ_INTEGER)) { + priv->gsu.gst1.WMode = s->cur[0].val.i; + } + } + else if (!memcmp(s->cur[-1].val.name, PDF_PS_OPER_NAME_AND_LEN("lenIV"))) { + if (pdf_ps_obj_has_type(&s->cur[0], PDF_PS_OBJ_INTEGER)) { + priv->gsu.gst1.data.lenIV = s->cur[0].val.i; + } + } + else if (!memcmp(s->cur[-1].val.name, PDF_PS_OPER_NAME_AND_LEN("UniqueID"))) { + /* Ignore UniqueID if we already have a XUID */ + if (priv->gsu.gst1.UID.id >= 0) { + if (pdf_ps_obj_has_type(&s->cur[0], PDF_PS_OBJ_INTEGER)) { + uid_set_UniqueID(&priv->gsu.gst1.UID, s->cur[0].val.i); + } + } + } + else if (!memcmp(s->cur[-1].val.name, PDF_PS_OPER_NAME_AND_LEN("XUID"))) { + if (pdf_ps_obj_has_type(&s->cur[0], PDF_PS_OBJ_ARRAY)) { + int i, size = s->cur[0].size; + long *xvals = (long *)gs_alloc_bytes(mem, size *sizeof(long), "ps_font_def_func(xuid vals)"); + + if (xvals != NULL) { + for (i = 0; i < size; i++) { + if (pdf_ps_obj_has_type(&s->cur[0].val.arr[i], PDF_PS_OBJ_INTEGER)) { + xvals[i] = s->cur[0].val.arr[i].val.i; + } + else { + gs_free_object(mem, xvals, "ps_font_def_func(xuid vals)"); + xvals = NULL; + break; + } + } + } + if (xvals != NULL) { + if (priv->gsu.gst1.UID.xvalues != NULL) + gs_free_object(mem, priv->gsu.gst1.UID.xvalues, "ps_font_def_func(old xuid vals)"); + uid_set_XUID(&priv->gsu.gst1.UID, xvals, size); + } + } + } + else if (!memcmp(s->cur[-1].val.name, PDF_PS_OPER_NAME_AND_LEN("FontBBox"))) { + if (pdf_ps_obj_has_type(&s->cur[0], PDF_PS_OBJ_ARRAY)) { + int i, j; + double bbox[4] = { 0, 0, 1000, 1000 }; + if (pdf_ps_obj_has_type(&s->cur[0].val.arr[0], PDF_PS_OBJ_ARRAY)) { /* This is (probably) a Blend/FontBBox entry */ + code = pdfi_array_alloc(s->pdfi_ctx, s->cur[0].size, &priv->u.t1.blendfontbbox); + if (code >= 0) { + pdfi_countup(priv->u.t1.blendfontbbox); + for (i = 0; i < s->cur[0].size; i++) { + pdf_ps_stack_object_t *arr = &s->cur[0].val.arr[i]; + pdf_array *parr; + pdf_num *n; + if (pdf_ps_obj_has_type(arr, PDF_PS_OBJ_ARRAY)) { + code = pdfi_array_alloc(s->pdfi_ctx, arr->size, &parr); + if (code < 0) + break; + pdfi_countup(parr); + + for (j = 0; j < arr->size; j++) { + if (pdf_ps_obj_has_type(&arr->val.arr[j], PDF_PS_OBJ_INTEGER)) { + code = pdfi_object_alloc(s->pdfi_ctx, PDF_INT, 0, (pdf_obj **)&n); + if (code >= 0) + n->value.i = arr->val.arr[j].val.i; + } + else if (pdf_ps_obj_has_type(&arr->val.arr[j], PDF_PS_OBJ_FLOAT)) { + code = pdfi_object_alloc(s->pdfi_ctx, PDF_REAL, 0, (pdf_obj **)&n); + if (code >= 0) + n->value.d = arr->val.arr[j].val.f; + } + else { + code = pdfi_object_alloc(s->pdfi_ctx, PDF_INT, 0, (pdf_obj **)&n); + if (code >= 0) + n->value.i = 0; + } + if (code < 0) + break; + pdfi_countup(n); + code = pdfi_array_put(s->pdfi_ctx, parr, j, (pdf_obj *)n); + pdfi_countdown(n); + if (code < 0) break; + } + } + if (code >= 0) + code = pdfi_array_put(s->pdfi_ctx, priv->u.t1.blendfontbbox, i, (pdf_obj *)parr); + pdfi_countdown(parr); + } + } + } + else if (s->cur[0].size >= 4) { + for (i = 0; i < 4; i++) { + if (pdf_ps_obj_has_type(&s->cur[0].val.arr[i], PDF_PS_OBJ_INTEGER)) { + bbox[i] = (double)s->cur[0].val.arr[i].val.i; + } + else if (pdf_ps_obj_has_type(&s->cur[0].val.arr[i], PDF_PS_OBJ_FLOAT)) { + bbox[i] = (double)s->cur[0].val.arr[i].val.f; + } + } + priv->gsu.gst1.FontBBox.p.x = bbox[0]; + priv->gsu.gst1.FontBBox.p.y = bbox[1]; + priv->gsu.gst1.FontBBox.q.x = bbox[2]; + priv->gsu.gst1.FontBBox.q.y = bbox[3]; + } + } + } + else if (!memcmp(s->cur[-1].val.name, PDF_PS_OPER_NAME_AND_LEN("FontType"))) { + if (pdf_ps_obj_has_type(&s->cur[0], PDF_PS_OBJ_INTEGER)) { + priv->gsu.gst1.FontType = s->cur[0].val.i; + priv->u.t1.pdfi_font_type = s->cur[0].val.i == 1 ? e_pdf_font_type1 : e_pdf_cidfont_type0; + } + else { + priv->gsu.gst1.FontType = 1; + priv->u.t1.pdfi_font_type = e_pdf_font_type1; + } + } + else if (!memcmp(s->cur[-1].val.name, PDF_PS_OPER_NAME_AND_LEN("FontMatrix"))) { + if (pdf_ps_obj_has_type(&s->cur[0], PDF_PS_OBJ_ARRAY) && s->cur[0].size >= 6) { + int i; + double fmat[6] = { 0.001, 0, 0, 0.001, 0, 0 }; + for (i = 0; i < 6; i++) { + if (pdf_ps_obj_has_type(&s->cur[0].val.arr[i], PDF_PS_OBJ_INTEGER)) { + fmat[i] = (double)s->cur[0].val.arr[i].val.i; + } + else if (pdf_ps_obj_has_type(&s->cur[0].val.arr[i], PDF_PS_OBJ_FLOAT)) { + fmat[i] = (double)s->cur[0].val.arr[i].val.f; + } + } + priv->gsu.gst1.FontMatrix.xx = fmat[0]; + priv->gsu.gst1.FontMatrix.xy = fmat[1]; + priv->gsu.gst1.FontMatrix.yx = fmat[2]; + priv->gsu.gst1.FontMatrix.yy = fmat[3]; + priv->gsu.gst1.FontMatrix.tx = fmat[4]; + priv->gsu.gst1.FontMatrix.ty = fmat[5]; + priv->gsu.gst1.orig_FontMatrix = priv->gsu.gst1.FontMatrix; + } + } + else if (!memcmp(s->cur[-1].val.name, PDF_PS_OPER_NAME_AND_LEN("BlueValues"))) { + if (pdf_ps_obj_has_type(&s->cur[0], PDF_PS_OBJ_ARRAY)) { + int i, size = s->cur[0].size < 14 ? s->cur[0].size : 14; + + for (i = 0; i < size; i++) { + if (pdf_ps_obj_has_type(&s->cur[0].val.arr[i], PDF_PS_OBJ_INTEGER)) { + priv->gsu.gst1.data.BlueValues.values[i] = + (float)s->cur[0].val.arr[i].val.i; + } + else if (pdf_ps_obj_has_type(&s->cur[0].val.arr[i], PDF_PS_OBJ_FLOAT)) { + priv->gsu.gst1.data.BlueValues.values[i] = s->cur[0].val.arr[i].val.f; + } + else { + if (i == 0) + priv->gsu.gst1.data.BlueValues.values[i] = 0; + else + priv->gsu.gst1.data.BlueValues.values[i] = priv->gsu.gst1.data.BlueValues.values[i - 1] + 1; + } + } + priv->gsu.gst1.data.BlueValues.count = size; + } + } + else if (!memcmp(s->cur[-1].val.name, PDF_PS_OPER_NAME_AND_LEN("BlueScale"))) { + if (pdf_ps_obj_has_type(&s->cur[0], PDF_PS_OBJ_INTEGER)) { + priv->gsu.gst1.data.BlueScale = (float)s->cur[0].val.i; + } + else if (pdf_ps_obj_has_type(&s->cur[0], PDF_PS_OBJ_FLOAT)) { + priv->gsu.gst1.data.BlueScale = (float)s->cur[0].val.f; + } + } + else if (!memcmp(s->cur[-1].val.name, PDF_PS_OPER_NAME_AND_LEN("StdHW"))) { + if (pdf_ps_obj_has_type(&s->cur[0], PDF_PS_OBJ_ARRAY)) { + if (pdf_ps_obj_has_type(&s->cur[0].val.arr[0], PDF_PS_OBJ_INTEGER)) { + priv->gsu.gst1.data.StdHW.values[0] = (float)s->cur[0].val.arr[0].val.i; + priv->gsu.gst1.data.StdHW.count = 1; + } + else if (pdf_ps_obj_has_type(&s->cur[0].val.arr[0], PDF_PS_OBJ_FLOAT)) { + priv->gsu.gst1.data.StdHW.values[0] = s->cur[0].val.arr[0].val.f; + priv->gsu.gst1.data.StdHW.count = 1; + } + } + } + else if (!memcmp(s->cur[-1].val.name, PDF_PS_OPER_NAME_AND_LEN("StdVW"))) { + if (pdf_ps_obj_has_type(&s->cur[0], PDF_PS_OBJ_ARRAY)) { + if (pdf_ps_obj_has_type(&s->cur[0].val.arr[0], PDF_PS_OBJ_INTEGER)) { + priv->gsu.gst1.data.StdVW.values[0] = (float)s->cur[0].val.arr[0].val.i; + priv->gsu.gst1.data.StdVW.count = 1; + } + else if (pdf_ps_obj_has_type(&s->cur[0].val.arr[0], PDF_PS_OBJ_FLOAT)) { + priv->gsu.gst1.data.StdVW.values[0] = s->cur[0].val.arr[0].val.f; + priv->gsu.gst1.data.StdVW.count = 1; + } + } + } + else if (!memcmp(s->cur[-1].val.name, PDF_PS_OPER_NAME_AND_LEN("StemSnapH"))) { + if (pdf_ps_obj_has_type(&s->cur[0], PDF_PS_OBJ_ARRAY)) { + int i, size = s->cur[0].size > 12 ? 12 : s->cur[0].size; + + for (i = 0; i < size; i++) { + if (pdf_ps_obj_has_type(&s->cur[0].val.arr[i], PDF_PS_OBJ_INTEGER)) { + priv->gsu.gst1.data.StemSnapH.values[i] = (float)s->cur[0].val.arr[i].val.i; + } + else if (pdf_ps_obj_has_type(&s->cur[0].val.arr[i], PDF_PS_OBJ_FLOAT)) { + priv->gsu.gst1.data.StemSnapH.values[i] = s->cur[0].val.arr[i].val.f; + } + } + priv->gsu.gst1.data.StemSnapH.count = size; + } + } + else if (!memcmp(s->cur[-1].val.name, PDF_PS_OPER_NAME_AND_LEN("StemSnapV"))) { + if (pdf_ps_obj_has_type(&s->cur[0], PDF_PS_OBJ_ARRAY)) { + int i, size = s->cur[0].size > 12 ? 12 : s->cur[0].size; + + for (i = 0; i < size; i++) { + if (pdf_ps_obj_has_type(&s->cur[0].val.arr[i], PDF_PS_OBJ_INTEGER)) { + priv->gsu.gst1.data.StemSnapV.values[i] = (float)s->cur[0].val.arr[i].val.i; + } + else if (pdf_ps_obj_has_type(&s->cur[0].val.arr[i], PDF_PS_OBJ_FLOAT)) { + priv->gsu.gst1.data.StemSnapV.values[i] = s->cur[0].val.arr[i].val.f; + } + } + priv->gsu.gst1.data.StemSnapH.count = size; + } + } + else if (!memcmp(s->cur[-1].val.name, PDF_PS_OPER_NAME_AND_LEN("Encoding"))) { + pdf_array *new_enc = NULL; + + if (pdf_ps_obj_has_type(&s->cur[0], PDF_PS_OBJ_NAME)) { + pdf_name *pname; + + code = pdfi_name_alloc(s->pdfi_ctx, (byte *) s->cur[0].val.name, s->cur[0].size, (pdf_obj **) &pname); + if (code >= 0) { + pdfi_countup(pname); + + code = pdfi_create_Encoding(s->pdfi_ctx, (pdf_obj *) pname, NULL, (pdf_obj **) &new_enc); + if (code >= 0) { + pdfi_countdown(priv->u.t1.Encoding); + priv->u.t1.Encoding = new_enc; + } + pdfi_countdown(pname); + } + } + else if (pdf_ps_obj_has_type(&s->cur[0], PDF_PS_OBJ_ARRAY)) { + int i; + + code = pdfi_array_alloc(s->pdfi_ctx, s->cur[0].size, &new_enc); + if (code >= 0) { + pdfi_countup(new_enc); + for (i = 0; i < s->cur[0].size; i++) { + pdf_name *n = NULL; + byte *nm = (byte *) s->cur[0].val.arr[i].val.name; + int nlen = s->cur[0].val.arr[i].size; + + code = pdfi_name_alloc(s->pdfi_ctx, (byte *) nm, nlen, (pdf_obj **) &n); + if (code < 0) + break; + pdfi_countup(n); + code = pdfi_array_put(s->pdfi_ctx, new_enc, (uint64_t) i, (pdf_obj *) n); + pdfi_countdown(n); + if (code < 0) + break; + } + if (code < 0) { + pdfi_countdown(new_enc); + } + else { + pdfi_countdown(priv->u.t1.Encoding); + priv->u.t1.Encoding = new_enc; + new_enc = NULL; + } + } + } + } + else if (!memcmp(s->cur[-1].val.name, PDF_PS_OPER_NAME_AND_LEN("BlendDesignPositions"))) { + if (pdf_ps_obj_has_type(&s->cur[0], PDF_PS_OBJ_ARRAY)) { + code = pdfi_array_alloc(s->pdfi_ctx, s->cur[0].size, &priv->u.t1.blenddesignpositions); + if (code >= 0) { + int i, j; + pdfi_countup(priv->u.t1.blenddesignpositions); + + for (i = 0; i < s->cur[0].size && code >= 0; i++) { + pdf_ps_stack_object_t *so = &s->cur[0].val.arr[i]; + + if (pdf_ps_obj_has_type(so, PDF_PS_OBJ_ARRAY)) { + pdf_array *sa; + code = pdfi_array_alloc(s->pdfi_ctx, so->size, &sa); + if (code >= 0) { + pdfi_countup(sa); + for (j = 0; j < so->size; j++) { + pdf_num *n; + if (pdf_ps_obj_has_type(&so->val.arr[j], PDF_PS_OBJ_INTEGER)) { + code = pdfi_object_alloc(s->pdfi_ctx, PDF_INT, 0, (pdf_obj **)&n); + if (code >= 0) + n->value.i = so->val.arr[j].val.i; + } + else if (pdf_ps_obj_has_type(&so->val.arr[j], PDF_PS_OBJ_FLOAT)) { + code = pdfi_object_alloc(s->pdfi_ctx, PDF_REAL, 0, (pdf_obj **)&n); + if (code >= 0) + n->value.d = so->val.arr[j].val.f; + } + else { + code = pdfi_object_alloc(s->pdfi_ctx, PDF_INT, 0, (pdf_obj **)&n); + if (code >= 0) + n->value.i = 0; + } + if (code < 0) + break; + pdfi_countup(n); + code = pdfi_array_put(s->pdfi_ctx, sa, j, (pdf_obj *)n); + pdfi_countdown(n); + if (code < 0) break; + } + } + if (code >= 0) { + pdfi_array_put(s->pdfi_ctx, priv->u.t1.blenddesignpositions, i, (pdf_obj *)sa); + } + pdfi_countdown(sa); + } + } + } + + } + } + else if (!memcmp(s->cur[-1].val.name, PDF_PS_OPER_NAME_AND_LEN("BlendAxisTypes"))) { + if (pdf_ps_obj_has_type(&s->cur[0], PDF_PS_OBJ_ARRAY)) { + int i; + code = pdfi_array_alloc(s->pdfi_ctx, s->cur[0].size, &priv->u.t1.blendaxistypes); + if (code >= 0) { + pdfi_countup(priv->u.t1.blendaxistypes); + for (i = 0; i < s->cur[0].size; i++) { + pdf_ps_stack_object_t *so = &s->cur[0].val.arr[i]; + pdf_name *n; + if (pdf_ps_obj_has_type(so, PDF_PS_OBJ_NAME)) { + code = pdfi_object_alloc(s->pdfi_ctx, PDF_NAME, so->size, (pdf_obj **)&n); + if (code >= 0) { + pdfi_countup(n); + memcpy(n->data, so->val.name, so->size); + n->length = so->size; + code = pdfi_array_put(s->pdfi_ctx, priv->u.t1.blendaxistypes, i, (pdf_obj *)n); + pdfi_countdown(n); + } + } + if (code < 0) + break; + } + } + } + } + else if (!memcmp(s->cur[-1].val.name, PDF_PS_OPER_NAME_AND_LEN("BlendDesignMap"))) { + if (pdf_ps_obj_has_type(&s->cur[0], PDF_PS_OBJ_ARRAY)) { + int i, j, k; + pdf_ps_stack_object_t *arr1 = &s->cur[0], *arr2, *arr3; + pdf_array *parr2, *parr3; + code = pdfi_array_alloc(s->pdfi_ctx, arr1->size, &priv->u.t1.blenddesignmap); + if (code >= 0) { + pdfi_countup(priv->u.t1.blenddesignmap); + for (i = 0; i < arr1->size && code >= 0; i++) { + if (pdf_ps_obj_has_type(&arr1->val.arr[i], PDF_PS_OBJ_ARRAY)) { + arr2 = &arr1->val.arr[i]; + code = pdfi_array_alloc(s->pdfi_ctx, arr2->size, &parr2); + if (code < 0) + break; + for (j = 0; j < arr2->size; j++) { + pdf_num *n; + + arr3 = &arr2->val.arr[j]; + code = pdfi_array_alloc(s->pdfi_ctx, arr3->size, &parr3); + if (code < 0) + break; + + for (k = 0; k < arr3->size; k++) { + if (pdf_ps_obj_has_type(&arr3->val.arr[k], PDF_PS_OBJ_INTEGER)) { + code = pdfi_object_alloc(s->pdfi_ctx, PDF_INT, 0, (pdf_obj **)&n); + if (code >= 0) + n->value.i = arr3->val.arr[k].val.i; + } + else if (pdf_ps_obj_has_type(&arr1->val.arr[i], PDF_PS_OBJ_FLOAT)) { + code = pdfi_object_alloc(s->pdfi_ctx, PDF_REAL, 0, (pdf_obj **)&n); + if (code >= 0) + n->value.d = arr3->val.arr[k].val.f; + } + else { + code = pdfi_object_alloc(s->pdfi_ctx, PDF_INT, 0, (pdf_obj **)&n); + if (code >= 0) + n->value.i = 0; + } + if (code < 0) + break; + pdfi_countup(n); + code = pdfi_array_put(s->pdfi_ctx, parr3, k, (pdf_obj *)n); + pdfi_countdown(n); + if (code < 0) + break; + } + if (code < 0) + break; + pdfi_countup(parr3); + code = pdfi_array_put(s->pdfi_ctx, parr2, j, (pdf_obj *)parr3); + pdfi_countdown(parr3); + } + if (code < 0) + break; + pdfi_countup(parr2); + code = pdfi_array_put(s->pdfi_ctx, priv->u.t1.blenddesignmap, i, (pdf_obj *)parr2); + pdfi_countdown(parr2); + } + } + } + } + } + else if (!memcmp(s->cur[-1].val.name, PDF_PS_OPER_NAME_AND_LEN("WeightVector"))) { + if (pdf_ps_obj_has_type(&s->cur[0], PDF_PS_OBJ_ARRAY)) { + int i; + for (i = 0; i < s->cur[0].size; i++) { + if (pdf_ps_obj_has_type(&s->cur[0].val.arr[i], PDF_PS_OBJ_INTEGER)) { + priv->gsu.gst1.data.WeightVector.values[i] = s->cur[0].val.arr[i].val.i; + } + else if (pdf_ps_obj_has_type(&s->cur[0].val.arr[i], PDF_PS_OBJ_FLOAT)) { + priv->gsu.gst1.data.WeightVector.values[i] = s->cur[0].val.arr[i].val.f; + } + else { + priv->gsu.gst1.data.WeightVector.values[i] = 0; + } + } + priv->gsu.gst1.data.WeightVector.count = s->cur[0].size; + } + } + } + + code2 = pdf_ps_stack_pop(s, 2); + if (code < 0) + return code; + else + return code2; +} + +static int +ps_font_true_func(gs_memory_t *mem, pdf_ps_ctx_t *s, byte *buf, byte *bufend) +{ + (void)mem; + return pdf_ps_stack_push_boolean(s, true); +} + +static int +ps_font_false_func(gs_memory_t *mem, pdf_ps_ctx_t *s, byte *buf, byte *bufend) +{ + (void)mem; + return pdf_ps_stack_push_boolean(s, false); +} + +static int +ps_font_dict_begin_func(gs_memory_t *mem, pdf_ps_ctx_t *s, byte *buf, byte *bufend) +{ + (void)mem; + return pdf_ps_stack_push_dict_mark(s); +} + +static int +ps_font_dict_end_func(gs_memory_t *mem, pdf_ps_ctx_t *s, byte *buf, byte *bufend) +{ + int dsize = pdf_ps_stack_count_to_mark(s, PDF_PS_OBJ_DICT_MARK); + + (void)mem; + if (dsize >= 0) + return pdf_ps_stack_pop(s, dsize + 1); /* Add one for the mark object */ + else + return 0; +} + +static stream * +push_eexec_filter(gs_memory_t *mem, byte *buf, byte *bufend) +{ + stream *fs, *ffs = NULL; + stream *sstrm; + stream_exD_state *st; + byte *strbuf; + + sstrm = file_alloc_stream(mem, "push_eexec_filter(buf stream)"); + if (sstrm == NULL) + return NULL; + + /* Because of streams <shrug!> we advance the buffer one byte */ + buf++; + sread_string(sstrm, buf, bufend - buf); + sstrm->close_at_eod = false; + + fs = s_alloc(mem, "push_eexec_filter(fs)"); + strbuf = gs_alloc_bytes(mem, 4096, "push_eexec_filter(buf)"); + st = gs_alloc_struct(mem, stream_exD_state, s_exD_template.stype, "push_eexec_filter(st)"); + if (fs == NULL || st == NULL || strbuf == NULL) { + sclose(sstrm); + gs_free_object(mem, sstrm, "push_eexec_filter(buf stream)"); + gs_free_object(mem, fs, "push_eexec_filter(fs)"); + gs_free_object(mem, st, "push_eexec_filter(st)"); + goto done; + } + memset(st, 0x00, sizeof(stream_exD_state)); + + s_std_init(fs, strbuf, 69, &s_filter_read_procs, s_mode_read); + st->memory = mem; + st->templat = &s_exD_template; + fs->state = (stream_state *) st; + fs->procs.process = s_exD_template.process; + fs->strm = sstrm; + (*s_exD_template.set_defaults) ((stream_state *) st); + st->cstate = 55665; + st->binary = -1; + st->lenIV = 4; + st->keep_spaces = true; + (*s_exD_template.init) ((stream_state *) st); + fs->close_at_eod = false; + ffs = fs; + done: + return ffs; +} + +static void +pop_eexec_filter(gs_memory_t *mem, stream *s) +{ + stream *src = s->strm; + byte *b = s->cbuf; + + sclose(s); + gs_free_object(mem, s, "pop_eexec_filter(s)"); + gs_free_object(mem, b, "pop_eexec_filter(b)"); + if (src) + sclose(src); + gs_free_object(mem, src, "pop_eexec_filter(strm)"); +} + +/* We decode the eexec data in place */ +static int +ps_font_eexec_func(gs_memory_t *mem, pdf_ps_ctx_t *s, byte *buf, byte *bufend) +{ + stream *strm; + int c; + + strm = push_eexec_filter(mem, buf, bufend); + while (1) { + c = sgetc(strm); + if (c < 0) + break; + *buf = (byte) c; + buf++; + } + pop_eexec_filter(mem, strm); + + return 0; +} + +/* Normally, for us, "array" is a NULL op. + *The exception is when the name /Subrs is two objects + *down from the top of the stack, then we can use this call + *to record how many subrs we expect, and allocate space for them + */ +static int +ps_font_array_func(gs_memory_t *mem, pdf_ps_ctx_t *s, byte *buf, byte *bufend) +{ + ps_font_interp_private *priv = (ps_font_interp_private *) s->client_data; + int code = 0; + + if (pdf_ps_stack_count(s) < 2) { + return pdf_ps_stack_pop(s, 1); + } + if (pdf_ps_obj_has_type(&s->cur[-1], PDF_PS_OBJ_NAME) && + pdf_ps_obj_has_type(&s->cur[0], PDF_PS_OBJ_INTEGER) && + !memcmp(s->cur[-1].val.name, PDF_PS_OPER_NAME_AND_LEN("Subrs"))) { + + if (s->cur[0].val.i > 0) { + if (priv->u.t1.Subrs != NULL) { + int i; + for (i = 0; i < priv->u.t1.NumSubrs; i++) { + gs_free_object(mem, priv->u.t1.Subrs[i].data, "ps_font_array_func(Subrs[i])"); + } + gs_free_object(mem, priv->u.t1.Subrs, "ps_font_array_func(Subrs)"); + } + + priv->u.t1.Subrs = (gs_string *) gs_alloc_bytes(mem, s->cur[0].val.i *sizeof(gs_string), "ps_font_array_func(Subrs)"); + if (priv->u.t1.Subrs == NULL) { + return_error(gs_error_VMerror); + } + memset(priv->u.t1.Subrs, 0x00, s->cur[0].val.i * sizeof(gs_string)); + } + priv->u.t1.NumSubrs = s->cur[0].val.i; + code = pdf_ps_stack_pop(s, 1); + } + else if (pdf_ps_obj_has_type(&s->cur[-1], PDF_PS_OBJ_NAME) && + pdf_ps_obj_has_type(&s->cur[0], PDF_PS_OBJ_INTEGER) && + !memcmp(s->cur[-1].val.name, PDF_PS_OPER_NAME_AND_LEN("Encoding"))) { + /* We're defining a custom encoding array */ + pdf_ps_stack_object_t *arr = NULL; + int size = s->cur[0].val.i; + + if (size > 0) { + arr = (pdf_ps_stack_object_t *) gs_alloc_bytes(mem, size *sizeof(pdf_ps_stack_object_t), "ps_font_array_func(encoding array)"); + if (arr != NULL) { + code = pdf_ps_stack_pop(s, 1); + if (code < 0) { + gs_free_object(mem, arr, "ps_font_array_func(encoding array)"); + } + else { + int i; + + for (i = 0; i < size; i++) { + pdf_ps_make_name(&arr[i], (byte *) notdefnamestr, strlen(notdefnamestr)); + } + code = pdf_ps_stack_push_array(s, arr, size); + } + } + else { + code = gs_note_error(gs_error_VMerror); + } + } + } + return code; +} + +/* Normally, for us, "dict" is a NULL op. + *The exception is when the name /CharStrings is two objects + *down from the top of the stack, then we can use this call + *to record how many charstrings we expect, and allocate space for them + */ +static int +ps_font_dict_func(gs_memory_t *mem, pdf_ps_ctx_t *s, byte *buf, byte *bufend) +{ + ps_font_interp_private *priv = (ps_font_interp_private *) s->client_data; + + if (pdf_ps_stack_count(s) < 2) { + return pdf_ps_stack_pop(s, 1); + } + if (pdf_ps_obj_has_type(&s->cur[-1], PDF_PS_OBJ_NAME) && + pdf_ps_obj_has_type(&s->cur[0], PDF_PS_OBJ_INTEGER) && + !memcmp(s->cur[-1].val.name, PDF_PS_OPER_NAME_AND_LEN("CharStrings"))) { + int code; + pdf_dict *d = NULL; + + if (priv->u.t1.CharStrings == NULL) { + code = pdfi_dict_alloc(s->pdfi_ctx, s->cur[0].val.i, &d); + if (code < 0) { + priv->u.t1.CharStrings = NULL; + (void)pdf_ps_stack_pop(s, 1); + return code; + } + + priv->u.t1.CharStrings = d; + pdfi_countup(priv->u.t1.CharStrings); + } + } + return pdf_ps_stack_pop(s, 1); +} + +static int +pdf_ps_pop2_oper_func(gs_memory_t *mem, pdf_ps_ctx_t *s, byte *buf, byte *bufend) +{ + return pdf_ps_stack_pop(s, 2); +} + +static int +pdf_ps_pop4_oper_func(gs_memory_t *mem, pdf_ps_ctx_t *s, byte *buf, byte *bufend) +{ + return pdf_ps_stack_pop(s, 4); +} + +static int +pdf_ps_standardencoding_oper_func(gs_memory_t *mem, pdf_ps_ctx_t *s, byte *buf, byte *bufend) +{ + return pdf_ps_stack_push_name(s, (byte *) "StandardEncoding", 16); +} + +/* { string currentfile exch readstring pop } */ +static int +pdf_ps_RD_oper_func(gs_memory_t *mem, pdf_ps_ctx_t *s, byte *buf, byte *bufend) +{ + ps_font_interp_private *priv = (ps_font_interp_private *) s->client_data; + int code; + int size = 0; + + if (pdf_ps_stack_count(s) >= 1) { + if (priv->u.t1.Subrs != NULL && priv->u.t1.CharStrings == NULL) { + if (pdf_ps_obj_has_type(&s->cur[0], PDF_PS_OBJ_INTEGER) && + pdf_ps_obj_has_type(&s->cur[-1], PDF_PS_OBJ_INTEGER)) { + int inx = s->cur[-1].val.i; + + size = s->cur[0].val.i; + buf++; + if (buf + size < bufend) { + priv->u.t1.Subrs[inx].data = + gs_alloc_bytes(mem, size, "pdf_ps_RD_oper_func(subr string)"); + if (priv->u.t1.Subrs[inx].data == NULL) { + (void)pdf_ps_stack_pop(s, 2); + return_error(gs_error_VMerror); + } + memcpy(priv->u.t1.Subrs[inx].data, buf, size); + priv->u.t1.Subrs[inx].size = size; + } + } + } + else if (priv->u.t1.CharStrings != NULL) { + if (pdf_ps_obj_has_type(&s->cur[0], PDF_PS_OBJ_INTEGER) && + pdf_ps_obj_has_type(&s->cur[-1], PDF_PS_OBJ_NAME)) { + pdf_string *str = NULL; + pdf_obj *key = NULL; + bool key_known; + + size = s->cur[0].val.i; + buf++; + code = pdfi_name_alloc(s->pdfi_ctx, (byte *) s->cur[-1].val.name, s->cur[-1].size, &key); + if (code < 0) { + (void)pdf_ps_stack_pop(s, 2); + return code; + } + pdfi_countup(key); + + if (buf + size < bufend) { + code = pdfi_dict_known_by_key(s->pdfi_ctx, priv->u.t1.CharStrings, (pdf_name *)key, &key_known); + if (code >=0 && key_known != true) { + code = pdfi_object_alloc(s->pdfi_ctx, PDF_STRING, size, (pdf_obj **) &str); + if (code < 0) { + pdfi_countdown(key); + (void)pdf_ps_stack_pop(s, 2); + return code; + } + pdfi_countup(str); + memcpy(str->data, buf, size); + + code = pdfi_dict_put_obj(s->pdfi_ctx, priv->u.t1.CharStrings, key, (pdf_obj *) str); + if (code < 0) { + pdfi_countdown(str); + pdfi_countdown(key); + (void)pdf_ps_stack_pop(s, 2); + return code; + } + } + } + pdfi_countdown(str); + pdfi_countdown(key); + } + } + code = pdf_ps_stack_pop(s, 2); + return code < 0 ? code : size + 1; + } + return 0; +} + +static int +pdf_ps_put_oper_func(gs_memory_t *mem, pdf_ps_ctx_t *s, byte *buf, byte *bufend) +{ + int code; + + if ((code = pdf_ps_stack_count(s)) < 4) { + return 0; + } + + if (pdf_ps_obj_has_type(&s->cur[-3], PDF_PS_OBJ_NAME) && + !memcmp(s->cur[-3].val.name, PDF_PS_OPER_NAME_AND_LEN("Encoding")) && + pdf_ps_obj_has_type(&s->cur[-2], PDF_PS_OBJ_ARRAY) && + pdf_ps_obj_has_type(&s->cur[-1], PDF_PS_OBJ_INTEGER) && + pdf_ps_obj_has_type(&s->cur[0], PDF_PS_OBJ_NAME)) { + if (s->cur[-1].val.i < s->cur[-2].size) { + pdf_ps_make_name(&s->cur[-2].val.arr[s->cur[-1].val.i], s->cur[0].val.name, s->cur[0].size); + } + } + + code = pdf_ps_stack_pop(s, 2); + return code; +} + +static pdf_ps_oper_list_t ps_font_oper_list[] = { + {PDF_PS_OPER_NAME_AND_LEN("RD"), pdf_ps_RD_oper_func}, + {PDF_PS_OPER_NAME_AND_LEN("-|"), pdf_ps_RD_oper_func}, + {PDF_PS_OPER_NAME_AND_LEN("|"), pdf_ps_put_oper_func}, + {PDF_PS_OPER_NAME_AND_LEN("findresource"), clear_stack_oper_func}, + {PDF_PS_OPER_NAME_AND_LEN("dict"), ps_font_dict_func}, + {PDF_PS_OPER_NAME_AND_LEN("begin"), ps_font_dict_begin_func}, + {PDF_PS_OPER_NAME_AND_LEN("end"), ps_font_dict_end_func}, + {PDF_PS_OPER_NAME_AND_LEN("pop"), ps_pdf_null_oper_func}, + {PDF_PS_OPER_NAME_AND_LEN("def"), ps_font_def_func}, + {PDF_PS_OPER_NAME_AND_LEN("dup"), ps_pdf_null_oper_func}, + {PDF_PS_OPER_NAME_AND_LEN("defineresource"), clear_stack_oper_func}, + {PDF_PS_OPER_NAME_AND_LEN("definefont"), clear_stack_oper_func}, + {PDF_PS_OPER_NAME_AND_LEN("readonly"), ps_pdf_null_oper_func}, + {PDF_PS_OPER_NAME_AND_LEN("true"), ps_font_true_func}, + {PDF_PS_OPER_NAME_AND_LEN("false"), ps_font_false_func}, + {PDF_PS_OPER_NAME_AND_LEN("eexec"), ps_font_eexec_func}, + {PDF_PS_OPER_NAME_AND_LEN("array"), ps_font_array_func}, + {PDF_PS_OPER_NAME_AND_LEN("known"), pdf_ps_pop_oper_func}, + {PDF_PS_OPER_NAME_AND_LEN("if"), pdf_ps_pop_oper_func}, + {PDF_PS_OPER_NAME_AND_LEN("ifelse"), pdf_ps_pop2_oper_func}, + {PDF_PS_OPER_NAME_AND_LEN("for"), pdf_ps_pop4_oper_func}, + {PDF_PS_OPER_NAME_AND_LEN("put"), pdf_ps_put_oper_func}, + {PDF_PS_OPER_NAME_AND_LEN("StandardEncoding"), pdf_ps_standardencoding_oper_func}, + {NULL, 0, NULL} +}; + +int +pdfi_read_ps_font(pdf_context *ctx, pdf_dict *font_dict, byte *fbuf, int fbuflen, ps_font_interp_private *ps_font_priv) +{ + int code = 0; + pdf_ps_ctx_t ps_font_ctx; + + code = pdfi_pscript_stack_init(ctx, ps_font_oper_list, ps_font_priv, &ps_font_ctx); + if (code < 0) + goto error_out; + + code = pdfi_pscript_interpret(&ps_font_ctx, fbuf, fbuflen); + pdfi_pscript_stack_finit(&ps_font_ctx); + /* We have several files that have a load of garbage data in the stream after the font is defined, + and that can end up in a stackoverflow error, even though we have a complete font. Override it + and let the Type 1 specific code decide for itself if it can use the font. + */ + if (code == gs_error_stackoverflow) + code = 0; + + return code; + error_out: + code = gs_error_invalidfont; + return code; +} |