2007-09-29 08:39:35 +00:00
|
|
|
#include <fitz.h>
|
|
|
|
#include <mupdf.h>
|
|
|
|
|
|
|
|
fz_error *
|
|
|
|
pdf_newcsi(pdf_csi **csip, int maskonly)
|
|
|
|
{
|
|
|
|
fz_error *error;
|
|
|
|
pdf_csi *csi;
|
|
|
|
fz_node *node;
|
|
|
|
|
|
|
|
csi = *csip = fz_malloc(sizeof(pdf_csi));
|
|
|
|
if (!csi)
|
|
|
|
return fz_outofmem;
|
|
|
|
|
|
|
|
pdf_initgstate(&csi->gstate[0]);
|
|
|
|
|
|
|
|
csi->gtop = 0;
|
|
|
|
csi->top = 0;
|
|
|
|
csi->array = nil;
|
|
|
|
csi->xbalance = 0;
|
|
|
|
|
|
|
|
error = fz_newpathnode(&csi->path);
|
|
|
|
if (error) {
|
|
|
|
fz_free(csi);
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
error = fz_newtree(&csi->tree);
|
|
|
|
if (error) {
|
|
|
|
fz_dropnode((fz_node*)csi->path);
|
|
|
|
fz_free(csi);
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
error = fz_newovernode(&node);
|
|
|
|
csi->tree->root = node;
|
|
|
|
csi->gstate[0].head = node;
|
|
|
|
|
|
|
|
if (maskonly)
|
|
|
|
{
|
|
|
|
csi->gstate[0].fill.kind = PDF_MNONE;
|
|
|
|
csi->gstate[0].stroke.kind = PDF_MNONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
csi->clip = 0;
|
|
|
|
|
|
|
|
csi->textclip = nil;
|
|
|
|
csi->textmode = 0;
|
|
|
|
csi->text = nil;
|
|
|
|
csi->tm = fz_identity();
|
|
|
|
csi->tlm = fz_identity();
|
|
|
|
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
clearstack(pdf_csi *csi)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < csi->top; i++)
|
|
|
|
fz_dropobj(csi->stack[i]);
|
|
|
|
csi->top = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static fz_error *
|
|
|
|
gsave(pdf_csi *csi)
|
|
|
|
{
|
|
|
|
if (csi->gtop == 31)
|
|
|
|
return fz_throw("gstate overflow in content stream");
|
|
|
|
|
|
|
|
memcpy(&csi->gstate[csi->gtop + 1], &csi->gstate[csi->gtop], sizeof(pdf_gstate));
|
|
|
|
|
|
|
|
csi->gtop ++;
|
|
|
|
|
|
|
|
if (csi->gstate[csi->gtop].fill.cs)
|
|
|
|
fz_keepcolorspace(csi->gstate[csi->gtop].fill.cs);
|
|
|
|
if (csi->gstate[csi->gtop].stroke.cs)
|
|
|
|
fz_keepcolorspace(csi->gstate[csi->gtop].stroke.cs);
|
|
|
|
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
|
|
|
static fz_error *
|
|
|
|
grestore(pdf_csi *csi)
|
|
|
|
{
|
|
|
|
if (csi->gtop == 0)
|
|
|
|
return fz_throw("gstate underflow in content stream");
|
|
|
|
|
|
|
|
if (csi->gstate[csi->gtop].fill.cs)
|
|
|
|
fz_dropcolorspace(csi->gstate[csi->gtop].fill.cs);
|
|
|
|
if (csi->gstate[csi->gtop].stroke.cs)
|
|
|
|
fz_dropcolorspace(csi->gstate[csi->gtop].stroke.cs);
|
|
|
|
|
|
|
|
csi->gtop --;
|
|
|
|
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
pdf_dropcsi(pdf_csi *csi)
|
|
|
|
{
|
|
|
|
while (csi->gtop)
|
|
|
|
grestore(csi);
|
|
|
|
|
|
|
|
if (csi->gstate[csi->gtop].fill.cs)
|
|
|
|
fz_dropcolorspace(csi->gstate[csi->gtop].fill.cs);
|
|
|
|
if (csi->gstate[csi->gtop].stroke.cs)
|
|
|
|
fz_dropcolorspace(csi->gstate[csi->gtop].stroke.cs);
|
|
|
|
|
|
|
|
if (csi->path) fz_dropnode((fz_node*)csi->path);
|
|
|
|
if (csi->clip) fz_dropnode((fz_node*)csi->clip);
|
|
|
|
if (csi->textclip) fz_dropnode((fz_node*)csi->textclip);
|
|
|
|
if (csi->text) fz_dropnode((fz_node*)csi->text);
|
|
|
|
if (csi->array) fz_dropobj(csi->array);
|
|
|
|
|
|
|
|
clearstack(csi);
|
|
|
|
|
|
|
|
fz_free(csi);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Do some magic to call the xobject subroutine.
|
|
|
|
* Push gstate, set transform, clip, run, pop gstate.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static fz_error *
|
|
|
|
runxobject(pdf_csi *csi, pdf_xref *xref, pdf_xobject *xobj)
|
|
|
|
{
|
|
|
|
fz_error *error;
|
|
|
|
fz_node *transform;
|
|
|
|
fz_stream *file;
|
|
|
|
|
|
|
|
/* gsave */
|
|
|
|
error = gsave(csi);
|
|
|
|
if (error)
|
|
|
|
return error;
|
|
|
|
|
|
|
|
/* push transform */
|
|
|
|
|
|
|
|
error = fz_newtransformnode(&transform, xobj->matrix);
|
|
|
|
if (error)
|
|
|
|
return error;
|
|
|
|
|
|
|
|
error = pdf_addtransform(csi->gstate + csi->gtop, transform);
|
|
|
|
if (error)
|
|
|
|
{
|
|
|
|
fz_dropnode(transform);
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* run contents */
|
|
|
|
|
|
|
|
xobj->contents->rp = xobj->contents->bp;
|
|
|
|
|
|
|
|
error = fz_openrbuffer(&file, xobj->contents);
|
|
|
|
if (error)
|
|
|
|
return error;
|
|
|
|
|
|
|
|
error = pdf_runcsi(csi, xref, xobj->resources, file);
|
|
|
|
|
|
|
|
fz_dropstream(file);
|
|
|
|
|
|
|
|
if (error)
|
|
|
|
return error;
|
|
|
|
|
|
|
|
/* grestore */
|
|
|
|
error = grestore(csi);
|
|
|
|
if (error)
|
|
|
|
return error;
|
|
|
|
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Decode inline image and insert into page.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static fz_error *
|
|
|
|
runinlineimage(pdf_csi *csi, pdf_xref *xref, fz_obj *rdb, fz_stream *file, fz_obj *dict)
|
|
|
|
{
|
|
|
|
fz_error *error;
|
|
|
|
pdf_image *img = NULL;
|
|
|
|
char buf[256];
|
|
|
|
int token;
|
|
|
|
int len;
|
|
|
|
|
|
|
|
error = pdf_loadinlineimage(&img, xref, rdb, dict, file);
|
|
|
|
if (error)
|
|
|
|
return error;
|
|
|
|
|
|
|
|
token = pdf_lex(file, buf, sizeof buf, &len);
|
|
|
|
if (token != PDF_TKEYWORD || strcmp("EI", buf))
|
|
|
|
fz_warn("syntaxerror: corrupt inline image");
|
|
|
|
|
|
|
|
error = pdf_showimage(csi, img);
|
|
|
|
fz_dropimage((fz_image*)img);
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set gstate params from an ExtGState dictionary.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static fz_error *
|
|
|
|
runextgstate(pdf_gstate *gstate, pdf_xref *xref, fz_obj *extgstate)
|
|
|
|
{
|
|
|
|
int i, k;
|
|
|
|
|
|
|
|
for (i = 0; i < fz_dictlen(extgstate); i++)
|
|
|
|
{
|
|
|
|
fz_obj *key = fz_dictgetkey(extgstate, i);
|
|
|
|
fz_obj *val = fz_dictgetval(extgstate, i);
|
|
|
|
char *s = fz_toname(key);
|
|
|
|
|
|
|
|
if (!strcmp(s, "Font"))
|
|
|
|
{
|
|
|
|
if (fz_isarray(val) && fz_arraylen(val) == 2)
|
|
|
|
{
|
|
|
|
gstate->font = pdf_finditem(xref->store, PDF_KFONT, fz_arrayget(val, 0));
|
|
|
|
if (!gstate->font)
|
|
|
|
return fz_throw("syntaxerror: missing font resource");
|
|
|
|
gstate->size = fz_toreal(fz_arrayget(val, 1));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return fz_throw("syntaxerror in ExtGState/Font");
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (!strcmp(s, "LW"))
|
|
|
|
gstate->linewidth = fz_toreal(val);
|
|
|
|
else if (!strcmp(s, "LC"))
|
|
|
|
gstate->linecap = fz_toint(val);
|
|
|
|
else if (!strcmp(s, "LJ"))
|
|
|
|
gstate->linejoin = fz_toint(val);
|
|
|
|
else if (!strcmp(s, "ML"))
|
|
|
|
gstate->miterlimit = fz_toreal(val);
|
2007-10-19 23:05:02 +00:00
|
|
|
|
2007-09-29 08:39:35 +00:00
|
|
|
else if (!strcmp(s, "D"))
|
|
|
|
{
|
|
|
|
if (fz_isarray(val) && fz_arraylen(val) == 2)
|
|
|
|
{
|
|
|
|
fz_obj *dashes = fz_arrayget(val, 0);
|
|
|
|
gstate->dashlen = MAX(fz_arraylen(dashes), 32);
|
|
|
|
for (k = 0; k < gstate->dashlen; k++)
|
|
|
|
gstate->dashlist[k] = fz_toreal(fz_arrayget(dashes, k));
|
|
|
|
gstate->dashphase = fz_toreal(fz_arrayget(val, 1));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return fz_throw("syntaxerror in ExtGState/D");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The meat of the interpreter...
|
|
|
|
*/
|
|
|
|
|
|
|
|
static fz_error *
|
|
|
|
runkeyword(pdf_csi *csi, pdf_xref *xref, fz_obj *rdb, char *buf)
|
|
|
|
{
|
|
|
|
pdf_gstate *gstate = csi->gstate + csi->gtop;
|
|
|
|
fz_error *error;
|
|
|
|
float a, b, c, d, e, f;
|
|
|
|
float x, y, w, h;
|
|
|
|
fz_matrix m;
|
|
|
|
float v[FZ_MAXCOLORS];
|
|
|
|
int what;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (strlen(buf) > 1)
|
|
|
|
{
|
|
|
|
if (!strcmp(buf, "BX"))
|
|
|
|
{
|
|
|
|
if (csi->top != 0)
|
|
|
|
goto syntaxerror;
|
|
|
|
csi->xbalance ++;
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (!strcmp(buf, "EX"))
|
|
|
|
{
|
|
|
|
if (csi->top != 0)
|
|
|
|
goto syntaxerror;
|
|
|
|
csi->xbalance --;
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (!strcmp(buf, "MP"))
|
|
|
|
{
|
|
|
|
if (csi->top != 1)
|
|
|
|
goto syntaxerror;
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (!strcmp(buf, "DP"))
|
|
|
|
{
|
|
|
|
if (csi->top != 2)
|
|
|
|
goto syntaxerror;
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (!strcmp(buf, "BMC"))
|
|
|
|
{
|
|
|
|
if (csi->top != 1)
|
|
|
|
goto syntaxerror;
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (!strcmp(buf, "BDC"))
|
|
|
|
{
|
|
|
|
if (csi->top != 2)
|
|
|
|
goto syntaxerror;
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (!strcmp(buf, "EMC"))
|
|
|
|
{
|
|
|
|
if (csi->top != 0)
|
|
|
|
goto syntaxerror;
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (!strcmp(buf, "cm"))
|
|
|
|
{
|
|
|
|
fz_matrix m;
|
|
|
|
fz_node *transform;
|
|
|
|
|
|
|
|
if (csi->top != 6)
|
|
|
|
goto syntaxerror;
|
|
|
|
|
|
|
|
m.a = fz_toreal(csi->stack[0]);
|
|
|
|
m.b = fz_toreal(csi->stack[1]);
|
|
|
|
m.c = fz_toreal(csi->stack[2]);
|
|
|
|
m.d = fz_toreal(csi->stack[3]);
|
|
|
|
m.e = fz_toreal(csi->stack[4]);
|
|
|
|
m.f = fz_toreal(csi->stack[5]);
|
|
|
|
|
|
|
|
error = fz_newtransformnode(&transform, m);
|
|
|
|
if (error) return error;
|
|
|
|
error = pdf_addtransform(gstate, transform);
|
|
|
|
if (error)
|
|
|
|
{
|
|
|
|
fz_dropnode(transform);
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (!strcmp(buf, "ri"))
|
|
|
|
{
|
|
|
|
if (csi->top != 1)
|
|
|
|
goto syntaxerror;
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (!strcmp(buf, "gs"))
|
|
|
|
{
|
|
|
|
fz_obj *dict;
|
|
|
|
fz_obj *obj;
|
|
|
|
|
|
|
|
if (csi->top != 1)
|
|
|
|
goto syntaxerror;
|
|
|
|
|
|
|
|
dict = fz_dictgets(rdb, "ExtGState");
|
|
|
|
if (!dict)
|
|
|
|
return fz_throw("syntaxerror: missing extgstate resource");
|
|
|
|
|
|
|
|
obj = fz_dictget(dict, csi->stack[0]);
|
|
|
|
if (!obj)
|
|
|
|
return fz_throw("syntaxerror: missing extgstate resource");
|
|
|
|
|
|
|
|
runextgstate(gstate, xref, obj);
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (!strcmp(buf, "re"))
|
|
|
|
{
|
|
|
|
if (csi->top != 4)
|
|
|
|
goto syntaxerror;
|
|
|
|
x = fz_toreal(csi->stack[0]);
|
|
|
|
y = fz_toreal(csi->stack[1]);
|
|
|
|
w = fz_toreal(csi->stack[2]);
|
|
|
|
h = fz_toreal(csi->stack[3]);
|
|
|
|
error = fz_moveto(csi->path, x, y);
|
|
|
|
if (error) return error;
|
|
|
|
error = fz_lineto(csi->path, x + w, y);
|
|
|
|
if (error) return error;
|
|
|
|
error = fz_lineto(csi->path, x + w, y + h);
|
|
|
|
if (error) return error;
|
|
|
|
error = fz_lineto(csi->path, x, y + h);
|
|
|
|
if (error) return error;
|
|
|
|
error = fz_closepath(csi->path);
|
|
|
|
if (error) return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (!strcmp(buf, "f*"))
|
|
|
|
{
|
|
|
|
if (csi->top != 0)
|
|
|
|
goto syntaxerror;
|
|
|
|
error = pdf_showpath(csi, 0, 1, 0, 1);
|
|
|
|
if (error) return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (!strcmp(buf, "B*"))
|
|
|
|
{
|
|
|
|
if (csi->top != 0)
|
|
|
|
goto syntaxerror;
|
|
|
|
error = pdf_showpath(csi, 0, 1, 1, 1);
|
|
|
|
if (error) return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (!strcmp(buf, "b*"))
|
|
|
|
{
|
|
|
|
if (csi->top != 0)
|
|
|
|
goto syntaxerror;
|
|
|
|
error = pdf_showpath(csi, 1, 1, 1, 1);
|
|
|
|
if (error) return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (!strcmp(buf, "W*"))
|
|
|
|
{
|
|
|
|
if (csi->top != 0)
|
|
|
|
goto syntaxerror;
|
|
|
|
csi->clip = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (!strcmp(buf, "cs"))
|
|
|
|
{
|
|
|
|
what = PDF_MFILL;
|
|
|
|
goto Lsetcolorspace;
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (!strcmp(buf, "CS"))
|
|
|
|
{
|
|
|
|
fz_colorspace *cs;
|
|
|
|
fz_obj *obj;
|
|
|
|
|
|
|
|
what = PDF_MSTROKE;
|
|
|
|
|
|
|
|
Lsetcolorspace:
|
|
|
|
if (csi->top != 1)
|
|
|
|
goto syntaxerror;
|
|
|
|
|
|
|
|
obj = csi->stack[0];
|
|
|
|
|
|
|
|
if (!strcmp(fz_toname(obj), "Pattern"))
|
|
|
|
{
|
|
|
|
error = pdf_setpattern(csi, what, nil, nil);
|
|
|
|
if (error) return error;
|
|
|
|
}
|
|
|
|
|
2007-10-19 23:05:02 +00:00
|
|
|
else
|
2007-09-29 08:39:35 +00:00
|
|
|
{
|
|
|
|
if (!strcmp(fz_toname(obj), "DeviceGray"))
|
|
|
|
cs = pdf_devicegray;
|
|
|
|
else if (!strcmp(fz_toname(obj), "DeviceRGB"))
|
|
|
|
cs = pdf_devicergb;
|
|
|
|
else if (!strcmp(fz_toname(obj), "DeviceCMYK"))
|
|
|
|
cs = pdf_devicecmyk;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fz_obj *dict = fz_dictgets(rdb, "ColorSpace");
|
|
|
|
if (!dict)
|
|
|
|
return fz_throw("syntaxerror: missing colorspace resource");
|
|
|
|
obj = fz_dictget(dict, obj);
|
|
|
|
if (!obj)
|
|
|
|
return fz_throw("syntaxerror: missing colorspace resource");
|
|
|
|
|
|
|
|
cs = pdf_finditem(xref->store, PDF_KCOLORSPACE, obj);
|
|
|
|
if (!cs)
|
|
|
|
return fz_throw("syntaxerror: missing colorspace resource");
|
|
|
|
}
|
|
|
|
|
|
|
|
error = pdf_setcolorspace(csi, what, cs);
|
|
|
|
if (error) return error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (!strcmp(buf, "sc") || !strcmp(buf, "scn"))
|
|
|
|
{
|
|
|
|
what = PDF_MFILL;
|
|
|
|
goto Lsetcolor;
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (!strcmp(buf, "SC") || !strcmp(buf, "SCN"))
|
|
|
|
{
|
|
|
|
pdf_material *mat;
|
|
|
|
pdf_pattern *pat;
|
|
|
|
fz_shade *shd;
|
|
|
|
fz_obj *dict;
|
|
|
|
fz_obj *obj;
|
|
|
|
|
|
|
|
what = PDF_MSTROKE;
|
|
|
|
|
|
|
|
Lsetcolor:
|
|
|
|
mat = what == PDF_MSTROKE ? &gstate->stroke : &gstate->fill;
|
|
|
|
|
|
|
|
if (fz_isname(csi->stack[csi->top - 1]))
|
|
|
|
mat->kind = PDF_MPATTERN;
|
|
|
|
|
|
|
|
switch (mat->kind)
|
|
|
|
{
|
|
|
|
case PDF_MNONE:
|
|
|
|
return fz_throw("syntaxerror: cannot set color in mask objects");
|
|
|
|
|
|
|
|
case PDF_MINDEXED:
|
|
|
|
if (csi->top != 1)
|
|
|
|
goto syntaxerror;
|
|
|
|
v[0] = fz_toreal(csi->stack[0]);
|
|
|
|
error = pdf_setcolor(csi, what, v);
|
|
|
|
if (error) return error;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PDF_MCOLOR:
|
|
|
|
case PDF_MLAB:
|
|
|
|
if (csi->top != mat->cs->n)
|
|
|
|
goto syntaxerror;
|
|
|
|
for (i = 0; i < csi->top; i++)
|
|
|
|
v[i] = fz_toreal(csi->stack[i]);
|
|
|
|
error = pdf_setcolor(csi, what, v);
|
|
|
|
if (error) return error;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PDF_MPATTERN:
|
|
|
|
for (i = 0; i < csi->top - 1; i++)
|
|
|
|
v[i] = fz_toreal(csi->stack[i]);
|
|
|
|
|
|
|
|
dict = fz_dictgets(rdb, "Pattern");
|
|
|
|
if (!dict)
|
|
|
|
return fz_throw("syntaxerror: missing pattern resource");
|
|
|
|
|
|
|
|
obj = fz_dictget(dict, csi->stack[csi->top - 1]);
|
|
|
|
if (!obj)
|
|
|
|
return fz_throw("syntaxerror: missing pattern resource");
|
|
|
|
|
|
|
|
pat = pdf_finditem(xref->store, PDF_KPATTERN, obj);
|
|
|
|
if (pat)
|
|
|
|
{
|
|
|
|
error = pdf_setpattern(csi, what, pat, csi->top == 1 ? nil : v);
|
|
|
|
if (error) return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
shd = pdf_finditem(xref->store, PDF_KSHADE, obj);
|
|
|
|
if (shd)
|
|
|
|
{
|
|
|
|
error = pdf_setshade(csi, what, shd);
|
|
|
|
if (error) return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!pat && !shd)
|
|
|
|
return fz_throw("syntaxerror: missing pattern resource");
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PDF_MSHADE:
|
|
|
|
return fz_throw("syntaxerror: cannot set color in shade objects");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (!strcmp(buf, "rg"))
|
|
|
|
{
|
|
|
|
if (csi->top != 3)
|
|
|
|
goto syntaxerror;
|
|
|
|
|
|
|
|
v[0] = fz_toreal(csi->stack[0]);
|
|
|
|
v[1] = fz_toreal(csi->stack[1]);
|
|
|
|
v[2] = fz_toreal(csi->stack[2]);
|
|
|
|
|
|
|
|
error = pdf_setcolorspace(csi, PDF_MFILL, pdf_devicergb);
|
|
|
|
if (error) return error;
|
|
|
|
error = pdf_setcolor(csi, PDF_MFILL, v);
|
|
|
|
if (error) return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (!strcmp(buf, "RG"))
|
|
|
|
{
|
|
|
|
if (csi->top != 3)
|
|
|
|
goto syntaxerror;
|
|
|
|
|
|
|
|
v[0] = fz_toreal(csi->stack[0]);
|
|
|
|
v[1] = fz_toreal(csi->stack[1]);
|
|
|
|
v[2] = fz_toreal(csi->stack[2]);
|
|
|
|
|
|
|
|
error = pdf_setcolorspace(csi, PDF_MSTROKE, pdf_devicergb);
|
|
|
|
if (error) return error;
|
|
|
|
error = pdf_setcolor(csi, PDF_MSTROKE, v);
|
|
|
|
if (error) return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (!strcmp(buf, "BT"))
|
|
|
|
{
|
|
|
|
if (csi->top != 0)
|
|
|
|
goto syntaxerror;
|
|
|
|
csi->tm = fz_identity();
|
|
|
|
csi->tlm = fz_identity();
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (!strcmp(buf, "ET"))
|
|
|
|
{
|
|
|
|
if (csi->top != 0)
|
|
|
|
goto syntaxerror;
|
|
|
|
|
|
|
|
error = pdf_flushtext(csi);
|
|
|
|
if (error)
|
|
|
|
return error;
|
|
|
|
|
|
|
|
if (csi->textclip)
|
|
|
|
{
|
|
|
|
error = pdf_addclipmask(gstate, csi->textclip);
|
|
|
|
if (error) return error;
|
|
|
|
csi->textclip = nil;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (!strcmp(buf, "Tc"))
|
|
|
|
{
|
|
|
|
if (csi->top != 1)
|
|
|
|
goto syntaxerror;
|
|
|
|
gstate->charspace = fz_toreal(csi->stack[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (!strcmp(buf, "Tw"))
|
|
|
|
{
|
|
|
|
if (csi->top != 1)
|
|
|
|
goto syntaxerror;
|
|
|
|
gstate->wordspace = fz_toreal(csi->stack[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (!strcmp(buf, "Tz"))
|
|
|
|
{
|
|
|
|
if (csi->top != 1)
|
|
|
|
goto syntaxerror;
|
|
|
|
|
|
|
|
error = pdf_flushtext(csi);
|
|
|
|
if (error) return error;
|
|
|
|
|
|
|
|
gstate->scale = fz_toreal(csi->stack[0]) / 100.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (!strcmp(buf, "TL"))
|
|
|
|
{
|
|
|
|
if (csi->top != 1)
|
|
|
|
goto syntaxerror;
|
|
|
|
gstate->leading = fz_toreal(csi->stack[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (!strcmp(buf, "Tf"))
|
|
|
|
{
|
|
|
|
fz_obj *dict;
|
|
|
|
fz_obj *obj;
|
|
|
|
|
|
|
|
if (csi->top != 2)
|
|
|
|
goto syntaxerror;
|
|
|
|
|
|
|
|
dict = fz_dictgets(rdb, "Font");
|
|
|
|
if (!dict)
|
|
|
|
return fz_throw("syntaxerror: missing font resource");
|
|
|
|
|
|
|
|
obj = fz_dictget(dict, csi->stack[0]);
|
|
|
|
if (!obj)
|
|
|
|
return fz_throw("syntaxerror: missing font resource");
|
|
|
|
|
|
|
|
gstate->font = pdf_finditem(xref->store, PDF_KFONT, obj);
|
|
|
|
if (!gstate->font)
|
|
|
|
return fz_throw("syntaxerror: missing font resource");
|
|
|
|
|
|
|
|
gstate->size = fz_toreal(csi->stack[1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (!strcmp(buf, "Tr"))
|
|
|
|
{
|
|
|
|
if (csi->top != 1)
|
|
|
|
goto syntaxerror;
|
|
|
|
gstate->render = fz_toint(csi->stack[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (!strcmp(buf, "Ts"))
|
|
|
|
{
|
|
|
|
if (csi->top != 1)
|
|
|
|
goto syntaxerror;
|
|
|
|
gstate->rise = fz_toreal(csi->stack[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (!strcmp(buf, "Td"))
|
|
|
|
{
|
|
|
|
if (csi->top != 2)
|
|
|
|
goto syntaxerror;
|
|
|
|
m = fz_translate(fz_toreal(csi->stack[0]), fz_toreal(csi->stack[1]));
|
|
|
|
csi->tlm = fz_concat(m, csi->tlm);
|
|
|
|
csi->tm = csi->tlm;
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (!strcmp(buf, "TD"))
|
|
|
|
{
|
|
|
|
if (csi->top != 2)
|
|
|
|
goto syntaxerror;
|
|
|
|
gstate->leading = -fz_toreal(csi->stack[1]);
|
|
|
|
m = fz_translate(fz_toreal(csi->stack[0]), fz_toreal(csi->stack[1]));
|
|
|
|
csi->tlm = fz_concat(m, csi->tlm);
|
|
|
|
csi->tm = csi->tlm;
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (!strcmp(buf, "Tm"))
|
|
|
|
{
|
|
|
|
if (csi->top != 6)
|
|
|
|
goto syntaxerror;
|
|
|
|
|
|
|
|
error = pdf_flushtext(csi);
|
|
|
|
if (error) return error;
|
|
|
|
|
|
|
|
csi->tm.a = fz_toreal(csi->stack[0]);
|
|
|
|
csi->tm.b = fz_toreal(csi->stack[1]);
|
|
|
|
csi->tm.c = fz_toreal(csi->stack[2]);
|
|
|
|
csi->tm.d = fz_toreal(csi->stack[3]);
|
|
|
|
csi->tm.e = fz_toreal(csi->stack[4]);
|
|
|
|
csi->tm.f = fz_toreal(csi->stack[5]);
|
|
|
|
csi->tlm = csi->tm;
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (!strcmp(buf, "T*"))
|
|
|
|
{
|
|
|
|
if (csi->top != 0)
|
|
|
|
goto syntaxerror;
|
|
|
|
m = fz_translate(0, -gstate->leading);
|
|
|
|
csi->tlm = fz_concat(m, csi->tlm);
|
|
|
|
csi->tm = csi->tlm;
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (!strcmp(buf, "Tj"))
|
|
|
|
{
|
|
|
|
if (csi->top != 1)
|
|
|
|
goto syntaxerror;
|
|
|
|
error = pdf_showtext(csi, csi->stack[0]);
|
|
|
|
if (error) return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (!strcmp(buf, "TJ"))
|
|
|
|
{
|
|
|
|
if (csi->top != 1)
|
|
|
|
goto syntaxerror;
|
|
|
|
error = pdf_showtext(csi, csi->stack[0]);
|
|
|
|
if (error) return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (!strcmp(buf, "Do"))
|
|
|
|
{
|
|
|
|
fz_obj *dict;
|
|
|
|
fz_obj *obj;
|
|
|
|
pdf_image *img;
|
|
|
|
pdf_xobject *xobj;
|
|
|
|
|
|
|
|
if (csi->top != 1)
|
|
|
|
goto syntaxerror;
|
|
|
|
|
|
|
|
dict = fz_dictgets(rdb, "XObject");
|
|
|
|
if (!dict)
|
|
|
|
{
|
|
|
|
fz_debugobj(rdb);
|
|
|
|
return fz_throw("syntaxerror: missing xobject resource");
|
|
|
|
}
|
|
|
|
|
|
|
|
obj = fz_dictget(dict, csi->stack[0]);
|
|
|
|
if (!obj)
|
|
|
|
return fz_throw("syntaxerror: missing xobject resource");
|
|
|
|
|
|
|
|
img = pdf_finditem(xref->store, PDF_KIMAGE, obj);
|
|
|
|
xobj = pdf_finditem(xref->store, PDF_KXOBJECT, obj);
|
|
|
|
|
|
|
|
if (!img && !xobj)
|
|
|
|
return fz_throw("syntaxerror: missing xobject resource");
|
|
|
|
|
|
|
|
if (img)
|
|
|
|
{
|
|
|
|
error = pdf_showimage(csi, img);
|
|
|
|
if (error)
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (xobj)
|
|
|
|
{
|
|
|
|
clearstack(csi);
|
|
|
|
error = runxobject(csi, xref, xobj);
|
|
|
|
if (error)
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (!strcmp(buf, "sh"))
|
|
|
|
{
|
|
|
|
fz_obj *dict;
|
|
|
|
fz_obj *obj;
|
|
|
|
fz_shade *shd;
|
|
|
|
|
|
|
|
if (csi->top != 1)
|
|
|
|
goto syntaxerror;
|
|
|
|
|
|
|
|
dict = fz_dictgets(rdb, "Shading");
|
|
|
|
if (!dict)
|
|
|
|
return fz_throw("syntaxerror: missing shading resource");
|
|
|
|
|
|
|
|
obj = fz_dictget(dict, csi->stack[csi->top - 1]);
|
|
|
|
if (!obj)
|
|
|
|
return fz_throw("syntaxerror: missing shading resource");
|
|
|
|
|
|
|
|
shd = pdf_finditem(xref->store, PDF_KSHADE, obj);
|
|
|
|
if (!shd)
|
|
|
|
return fz_throw("syntaxerror: missing shading resource");
|
|
|
|
|
|
|
|
error = pdf_addshade(gstate, shd);
|
|
|
|
if (error) return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (!strcmp(buf, "d0"))
|
|
|
|
{
|
|
|
|
fz_warn("unimplemented: d0 charprocs");
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (!strcmp(buf, "d1"))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
else
|
|
|
|
if (!csi->xbalance) goto syntaxerror;
|
|
|
|
}
|
|
|
|
|
|
|
|
else switch (buf[0])
|
|
|
|
{
|
|
|
|
|
|
|
|
case 'q':
|
|
|
|
if (csi->top != 0)
|
|
|
|
goto syntaxerror;
|
|
|
|
error = gsave(csi);
|
|
|
|
if (error)
|
|
|
|
return error;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'Q':
|
|
|
|
if (csi->top != 0)
|
|
|
|
goto syntaxerror;
|
|
|
|
error = grestore(csi);
|
|
|
|
if (error)
|
|
|
|
return error;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'w':
|
|
|
|
if (csi->top != 1)
|
|
|
|
goto syntaxerror;
|
|
|
|
gstate->linewidth = fz_toreal(csi->stack[0]);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'J':
|
|
|
|
if (csi->top != 1)
|
|
|
|
goto syntaxerror;
|
|
|
|
gstate->linecap = fz_toint(csi->stack[0]);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'j':
|
|
|
|
if (csi->top != 1)
|
|
|
|
goto syntaxerror;
|
|
|
|
gstate->linejoin = fz_toint(csi->stack[0]);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'M':
|
|
|
|
if (csi->top != 1)
|
|
|
|
goto syntaxerror;
|
|
|
|
gstate->miterlimit = fz_toreal(csi->stack[0]);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'd':
|
|
|
|
if (csi->top != 2)
|
|
|
|
goto syntaxerror;
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
fz_obj *array = csi->stack[0];
|
|
|
|
gstate->dashlen = fz_arraylen(array);
|
|
|
|
if (gstate->dashlen > 32)
|
|
|
|
return fz_throw("rangecheck: too large dash pattern");
|
|
|
|
for (i = 0; i < gstate->dashlen; i++)
|
|
|
|
gstate->dashlist[i] = fz_toreal(fz_arrayget(array, i));
|
|
|
|
gstate->dashphase = fz_toreal(csi->stack[1]);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'i':
|
|
|
|
if (csi->top != 1)
|
|
|
|
goto syntaxerror;
|
|
|
|
/* flatness */
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'm':
|
|
|
|
if (csi->top != 2)
|
|
|
|
goto syntaxerror;
|
|
|
|
a = fz_toreal(csi->stack[0]);
|
|
|
|
b = fz_toreal(csi->stack[1]);
|
|
|
|
return fz_moveto(csi->path, a, b);
|
|
|
|
|
|
|
|
case 'l':
|
|
|
|
if (csi->top != 2)
|
|
|
|
goto syntaxerror;
|
|
|
|
a = fz_toreal(csi->stack[0]);
|
|
|
|
b = fz_toreal(csi->stack[1]);
|
|
|
|
return fz_lineto(csi->path, a, b);
|
|
|
|
|
|
|
|
case 'c':
|
|
|
|
if (csi->top != 6)
|
|
|
|
goto syntaxerror;
|
|
|
|
a = fz_toreal(csi->stack[0]);
|
|
|
|
b = fz_toreal(csi->stack[1]);
|
|
|
|
c = fz_toreal(csi->stack[2]);
|
|
|
|
d = fz_toreal(csi->stack[3]);
|
|
|
|
e = fz_toreal(csi->stack[4]);
|
|
|
|
f = fz_toreal(csi->stack[5]);
|
|
|
|
return fz_curveto(csi->path, a, b, c, d, e, f);
|
|
|
|
|
|
|
|
case 'v':
|
|
|
|
if (csi->top != 4)
|
|
|
|
goto syntaxerror;
|
|
|
|
a = fz_toreal(csi->stack[0]);
|
|
|
|
b = fz_toreal(csi->stack[1]);
|
|
|
|
c = fz_toreal(csi->stack[2]);
|
|
|
|
d = fz_toreal(csi->stack[3]);
|
|
|
|
return fz_curvetov(csi->path, a, b, c, d);
|
|
|
|
|
|
|
|
case 'y':
|
|
|
|
if (csi->top != 4)
|
|
|
|
goto syntaxerror;
|
|
|
|
a = fz_toreal(csi->stack[0]);
|
|
|
|
b = fz_toreal(csi->stack[1]);
|
|
|
|
c = fz_toreal(csi->stack[2]);
|
|
|
|
d = fz_toreal(csi->stack[3]);
|
|
|
|
return fz_curvetoy(csi->path, a, b, c, d);
|
|
|
|
|
|
|
|
case 'h':
|
|
|
|
if (csi->top != 0)
|
|
|
|
goto syntaxerror;
|
|
|
|
return fz_closepath(csi->path);
|
|
|
|
|
|
|
|
case 'S':
|
|
|
|
if (csi->top != 0)
|
|
|
|
goto syntaxerror;
|
|
|
|
error = pdf_showpath(csi, 0, 0, 1, 0);
|
|
|
|
if (error) return error;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 's':
|
|
|
|
if (csi->top != 0)
|
|
|
|
goto syntaxerror;
|
|
|
|
error = pdf_showpath(csi, 1, 0, 1, 0);
|
|
|
|
if (error) return error;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'F':
|
|
|
|
case 'f':
|
|
|
|
if (csi->top != 0)
|
|
|
|
goto syntaxerror;
|
|
|
|
error = pdf_showpath(csi, 0, 1, 0, 0);
|
|
|
|
if (error) return error;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'B':
|
|
|
|
if (csi->top != 0)
|
|
|
|
goto syntaxerror;
|
|
|
|
error = pdf_showpath(csi, 0, 1, 1, 0);
|
|
|
|
if (error) return error;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'b':
|
|
|
|
if (csi->top != 0)
|
|
|
|
goto syntaxerror;
|
|
|
|
error = pdf_showpath(csi, 1, 1, 1, 0);
|
|
|
|
if (error) return error;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'n':
|
|
|
|
if (csi->top != 0)
|
|
|
|
goto syntaxerror;
|
|
|
|
error = pdf_showpath(csi, 0, 0, 0, 0);
|
|
|
|
if (error) return error;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'W':
|
|
|
|
if (csi->top != 0)
|
|
|
|
goto syntaxerror;
|
|
|
|
csi->clip = 1;
|
|
|
|
break;
|
|
|
|
|
2007-10-19 23:05:02 +00:00
|
|
|
case 'g':
|
2007-09-29 08:39:35 +00:00
|
|
|
if (csi->top != 1)
|
|
|
|
goto syntaxerror;
|
|
|
|
|
|
|
|
v[0] = fz_toreal(csi->stack[0]);
|
|
|
|
error = pdf_setcolorspace(csi, PDF_MFILL, pdf_devicegray);
|
|
|
|
if (error) return error;
|
|
|
|
error = pdf_setcolor(csi, PDF_MFILL, v);
|
|
|
|
if (error) return error;
|
|
|
|
break;
|
2007-10-19 23:05:02 +00:00
|
|
|
|
2007-09-29 08:39:35 +00:00
|
|
|
case 'G':
|
|
|
|
if (csi->top != 1)
|
|
|
|
goto syntaxerror;
|
|
|
|
|
|
|
|
v[0] = fz_toreal(csi->stack[0]);
|
|
|
|
error = pdf_setcolorspace(csi, PDF_MSTROKE, pdf_devicegray);
|
|
|
|
if (error) return error;
|
|
|
|
error = pdf_setcolor(csi, PDF_MSTROKE, v);
|
|
|
|
if (error) return error;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'k':
|
|
|
|
if (csi->top != 4)
|
|
|
|
goto syntaxerror;
|
|
|
|
|
|
|
|
v[0] = fz_toreal(csi->stack[0]);
|
|
|
|
v[1] = fz_toreal(csi->stack[1]);
|
|
|
|
v[2] = fz_toreal(csi->stack[2]);
|
|
|
|
v[3] = fz_toreal(csi->stack[3]);
|
|
|
|
|
|
|
|
error = pdf_setcolorspace(csi, PDF_MFILL, pdf_devicecmyk);
|
|
|
|
if (error) return error;
|
|
|
|
error = pdf_setcolor(csi, PDF_MFILL, v);
|
|
|
|
if (error) return error;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'K':
|
|
|
|
if (csi->top != 4)
|
|
|
|
goto syntaxerror;
|
|
|
|
|
|
|
|
v[0] = fz_toreal(csi->stack[0]);
|
|
|
|
v[1] = fz_toreal(csi->stack[1]);
|
|
|
|
v[2] = fz_toreal(csi->stack[2]);
|
|
|
|
v[3] = fz_toreal(csi->stack[3]);
|
|
|
|
|
|
|
|
error = pdf_setcolorspace(csi, PDF_MSTROKE, pdf_devicecmyk);
|
|
|
|
if (error) return error;
|
|
|
|
error = pdf_setcolor(csi, PDF_MSTROKE, v);
|
|
|
|
if (error) return error;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case '\'':
|
|
|
|
if (csi->top != 1)
|
|
|
|
goto syntaxerror;
|
|
|
|
|
|
|
|
m = fz_translate(0, -gstate->leading);
|
|
|
|
csi->tlm = fz_concat(m, csi->tlm);
|
|
|
|
csi->tm = csi->tlm;
|
|
|
|
|
|
|
|
error = pdf_showtext(csi, csi->stack[0]);
|
|
|
|
if (error) return error;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case '"':
|
|
|
|
if (csi->top != 3)
|
|
|
|
goto syntaxerror;
|
|
|
|
|
|
|
|
gstate->wordspace = fz_toreal(csi->stack[0]);
|
|
|
|
gstate->charspace = fz_toreal(csi->stack[1]);
|
|
|
|
|
|
|
|
m = fz_translate(0, -gstate->leading);
|
|
|
|
csi->tlm = fz_concat(m, csi->tlm);
|
|
|
|
csi->tm = csi->tlm;
|
|
|
|
|
|
|
|
error = pdf_showtext(csi, csi->stack[2]);
|
|
|
|
if (error) return error;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
if (!csi->xbalance) goto syntaxerror;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil;
|
|
|
|
|
|
|
|
syntaxerror:
|
|
|
|
return fz_throw("syntaxerror in content stream: '%s'", buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
fz_error *
|
|
|
|
pdf_runcsi(pdf_csi *csi, pdf_xref *xref, fz_obj *rdb, fz_stream *file)
|
|
|
|
{
|
|
|
|
fz_error *error;
|
|
|
|
char buf[65536];
|
|
|
|
int token, len;
|
|
|
|
fz_obj *obj;
|
|
|
|
|
|
|
|
while (1)
|
|
|
|
{
|
|
|
|
if (csi->top == 31)
|
|
|
|
return fz_throw("stack overflow in content stream");
|
|
|
|
|
|
|
|
token = pdf_lex(file, buf, sizeof buf, &len);
|
|
|
|
|
|
|
|
if (csi->array)
|
|
|
|
{
|
|
|
|
if (token == PDF_TCARRAY)
|
|
|
|
{
|
|
|
|
csi->stack[csi->top] = csi->array;
|
|
|
|
csi->array = nil;
|
|
|
|
csi->top ++;
|
|
|
|
}
|
|
|
|
else if (token == PDF_TINT || token == PDF_TREAL)
|
|
|
|
{
|
|
|
|
error = fz_newreal(&obj, atof(buf));
|
|
|
|
if (error) return error;
|
|
|
|
error = fz_arraypush(csi->array, obj);
|
|
|
|
fz_dropobj(obj);
|
|
|
|
if (error) return error;
|
|
|
|
}
|
|
|
|
else if (token == PDF_TSTRING)
|
|
|
|
{
|
|
|
|
error = fz_newstring(&obj, buf, len);
|
|
|
|
if (error) return error;
|
|
|
|
error = fz_arraypush(csi->array, obj);
|
|
|
|
fz_dropobj(obj);
|
|
|
|
if (error) return error;
|
|
|
|
}
|
|
|
|
else if (token == PDF_TEOF)
|
|
|
|
{
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
clearstack(csi);
|
|
|
|
return fz_throw("syntaxerror in content stream");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
else switch (token)
|
|
|
|
{
|
|
|
|
case PDF_TEOF:
|
|
|
|
return nil;
|
|
|
|
|
|
|
|
/* optimize text-object array parsing */
|
|
|
|
case PDF_TOARRAY:
|
|
|
|
error = fz_newarray(&csi->array, 8);
|
|
|
|
if (error) return error;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PDF_TODICT:
|
|
|
|
error = pdf_parsedict(&csi->stack[csi->top], file, buf, sizeof buf);
|
|
|
|
if (error) return error;
|
|
|
|
csi->top ++;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PDF_TNAME:
|
|
|
|
error = fz_newname(&csi->stack[csi->top], buf);
|
|
|
|
if (error) return error;
|
|
|
|
csi->top ++;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PDF_TINT:
|
|
|
|
error = fz_newint(&csi->stack[csi->top], atoi(buf));
|
|
|
|
if (error) return error;
|
|
|
|
csi->top ++;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PDF_TREAL:
|
|
|
|
error = fz_newreal(&csi->stack[csi->top], atof(buf));
|
|
|
|
if (error) return error;
|
|
|
|
csi->top ++;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PDF_TSTRING:
|
|
|
|
error = fz_newstring(&csi->stack[csi->top], buf, len);
|
|
|
|
if (error) return error;
|
|
|
|
csi->top ++;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PDF_TTRUE:
|
|
|
|
error = fz_newbool(&csi->stack[csi->top], 1);
|
|
|
|
if (error) return error;
|
|
|
|
csi->top ++;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PDF_TFALSE:
|
|
|
|
error = fz_newbool(&csi->stack[csi->top], 0);
|
|
|
|
if (error) return error;
|
|
|
|
csi->top ++;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PDF_TNULL:
|
|
|
|
error = fz_newnull(&csi->stack[csi->top]);
|
|
|
|
if (error) return error;
|
|
|
|
csi->top ++;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PDF_TKEYWORD:
|
|
|
|
if (!strcmp(buf, "BI"))
|
|
|
|
{
|
|
|
|
fz_obj *obj;
|
|
|
|
|
|
|
|
error = pdf_parsedict(&obj, file, buf, sizeof buf);
|
|
|
|
if (error)
|
|
|
|
return error;
|
|
|
|
|
|
|
|
/* read whitespace after ID keyword */
|
|
|
|
fz_readbyte(file);
|
|
|
|
|
|
|
|
error = runinlineimage(csi, xref, rdb, file, obj);
|
|
|
|
fz_dropobj(obj);
|
|
|
|
if (error)
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
error = runkeyword(csi, xref, rdb, buf);
|
|
|
|
if (error) return error;
|
|
|
|
clearstack(csi);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
clearstack(csi);
|
|
|
|
return fz_throw("syntaxerror in content stream");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|