reactos/rosapps/smartpdf/fitz/mupdf/pdf_interpret.c
Daniel Reimer a7fddf9c07 Delete all Trailing spaces in code.
svn path=/trunk/; revision=29689
2007-10-19 23:05:02 +00:00

1208 lines
24 KiB
C

#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);
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;
}
else
{
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;
case 'g':
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;
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");
}
}
}