diff options
-rw-r--r-- | draw/meshdraw.c | 10 | ||||
-rw-r--r-- | fitz/dev_draw.c | 27 | ||||
-rw-r--r-- | fitz/dev_null.c | 2 | ||||
-rw-r--r-- | fitz/filt_faxd.c | 5 | ||||
-rw-r--r-- | fitz/fitz.h | 8 | ||||
-rw-r--r-- | fitz/res_shade.c | 12 | ||||
-rw-r--r-- | mupdf/mupdf.h | 14 | ||||
-rw-r--r-- | mupdf/pdf_build.c | 79 | ||||
-rw-r--r-- | mupdf/pdf_colorspace.c | 2 | ||||
-rw-r--r-- | mupdf/pdf_crypt.c | 8 | ||||
-rw-r--r-- | mupdf/pdf_interpret.c | 1709 | ||||
-rw-r--r-- | mupdf/pdf_shade.c | 26 | ||||
-rw-r--r-- | xps/xps_gradient.c | 4 |
13 files changed, 903 insertions, 1003 deletions
diff --git a/draw/meshdraw.c b/draw/meshdraw.c index 71c0bdb7..79437505 100644 --- a/draw/meshdraw.c +++ b/draw/meshdraw.c @@ -498,7 +498,7 @@ fz_paintmesh(fz_shade *shade, fz_matrix ctm, fz_pixmap *dest, fz_bbox bbox) if (shade->usefunction) ntris = shade->meshlen / 9; else - ntris = shade->meshlen / ((2 + shade->cs->n) * 3); + ntris = shade->meshlen / ((2 + shade->colorspace->n) * 3); while (ntris--) { @@ -513,10 +513,10 @@ fz_paintmesh(fz_shade *shade, fz_matrix ctm, fz_pixmap *dest, fz_bbox bbox) tri[k][2] = *mesh++ * 255; else { - fz_convertcolor(shade->cs, mesh, dest->colorspace, tri[k] + 2); + fz_convertcolor(shade->colorspace, mesh, dest->colorspace, tri[k] + 2); for (i = 0; i < dest->colorspace->n; i++) tri[k][i + 2] *= 255; - mesh += shade->cs->n; + mesh += shade->colorspace->n; } } fz_painttriangle(dest, tri[0], tri[1], tri[2], 2 + dest->colorspace->n, bbox); @@ -537,10 +537,10 @@ fz_paintshade(fz_shade *shade, fz_matrix ctm, fz_pixmap *dest, fz_bbox bbox) { for (i = 0; i < 256; i++) { - fz_convertcolor(shade->cs, shade->function[i], dest->colorspace, color); + fz_convertcolor(shade->colorspace, shade->function[i], dest->colorspace, color); for (k = 0; k < dest->colorspace->n; k++) clut[i][k] = color[k] * 255; - clut[i][k] = shade->function[i][shade->cs->n] * 255; + clut[i][k] = shade->function[i][shade->colorspace->n] * 255; } conv = fz_newpixmapwithrect(dest->colorspace, bbox); temp = fz_newpixmapwithrect(fz_devicegray, bbox); diff --git a/fitz/dev_draw.c b/fitz/dev_draw.c index 4d3c94f2..e9cb74fc 100644 --- a/fitz/dev_draw.c +++ b/fitz/dev_draw.c @@ -499,7 +499,7 @@ fz_drawfillshade(void *user, fz_shade *shade, fz_matrix ctm, float alpha) { unsigned char *s; int x, y, n, i; - fz_convertcolor(shade->cs, shade->background, model, colorfv); + fz_convertcolor(shade->colorspace, shade->background, model, colorfv); for (i = 0; i < model->n; i++) colorbv[i] = colorfv[i] * 255; colorbv[i] = 255; @@ -580,6 +580,7 @@ fz_drawfillimage(void *user, fz_pixmap *image, fz_matrix ctm, float alpha) fz_colorspace *model = dev->dest->colorspace; fz_pixmap *converted = nil; fz_pixmap *scaled = nil; + int after; int dx, dy; if (!model) @@ -591,7 +592,15 @@ fz_drawfillimage(void *user, fz_pixmap *image, fz_matrix ctm, float alpha) if (image->w == 0 || image->h == 0) return; - if (image->colorspace != model) + /* convert images with more components (cmyk->rgb) before scaling */ + /* convert images with fewer components (gray->rgb after scaling */ + /* convert images with expensive colorspace transforms after scaling */ + + after = 0; + if (image->colorspace == fz_devicegray) + after = 1; + + if (image->colorspace != model && !after) { converted = fz_newpixmap(model, image->x, image->y, image->w, image->h); fz_convertpixmap(image, converted); @@ -601,7 +610,7 @@ fz_drawfillimage(void *user, fz_pixmap *image, fz_matrix ctm, float alpha) #ifdef SMOOTHSCALE dx = sqrtf(ctm.a * ctm.a + ctm.b * ctm.b); dy = sqrtf(ctm.c * ctm.c + ctm.d * ctm.d); - if (dx < image->w || dy < image->h) + if (dx < image->w && dy < image->h) { scaled = fz_smoothtransformpixmap(image, &ctm, dev->dest->x, dev->dest->y, dx, dy); if (scaled == nil) @@ -623,6 +632,14 @@ fz_drawfillimage(void *user, fz_pixmap *image, fz_matrix ctm, float alpha) } #endif + + if (image->colorspace != model && after) + { + converted = fz_newpixmap(model, image->x, image->y, image->w, image->h); + fz_convertpixmap(image, converted); + image = converted; + } + fz_paintimage(dev->dest, dev->scissor, image, ctm, alpha * 255); if (scaled) @@ -649,7 +666,7 @@ fz_drawfillimagemask(void *user, fz_pixmap *image, fz_matrix ctm, #ifdef SMOOTHSCALE dx = sqrtf(ctm.a * ctm.a + ctm.b * ctm.b); dy = sqrtf(ctm.c * ctm.c + ctm.d * ctm.d); - if (dx < image->w || dy < image->h) + if (dx < image->w && dy < image->h) { scaled = fz_smoothtransformpixmap(image, &ctm, dev->dest->x, dev->dest->y, dx, dy); if (scaled == nil) @@ -720,7 +737,7 @@ fz_drawclipimagemask(void *user, fz_pixmap *image, fz_matrix ctm) #ifdef SMOOTHSCALE dx = sqrtf(ctm.a * ctm.a + ctm.b * ctm.b); dy = sqrtf(ctm.c * ctm.c + ctm.d * ctm.d); - if (dx < image->w || dy < image->h) + if (dx < image->w && dy < image->h) { scaled = fz_smoothtransformpixmap(image, &ctm, dev->dest->x, dev->dest->y, dx, dy); if (scaled == nil) diff --git a/fitz/dev_null.c b/fitz/dev_null.c index c48cc2aa..7c80b0ff 100644 --- a/fitz/dev_null.c +++ b/fitz/dev_null.c @@ -15,7 +15,7 @@ static void fz_nullfillshade(void *user, fz_shade *shade, fz_matrix ctm, float a static void fz_nullfillimage(void *user, fz_pixmap *image, fz_matrix ctm, float alpha) {} static void fz_nullfillimagemask(void *user, fz_pixmap *image, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha) {} static void fz_nullclipimagemask(void *user, fz_pixmap *image, fz_matrix ctm) {} -static void fz_nullbeginmask(void *user, fz_rect r, int luminosity, fz_colorspace *cs, float *bc) {} +static void fz_nullbeginmask(void *user, fz_rect r, int luminosity, fz_colorspace *colorspace, float *bc) {} static void fz_nullendmask(void *user) {} static void fz_nullbegingroup(void *user, fz_rect r, int isolated, int knockout, fz_blendmode blendmode, float alpha) {} static void fz_nullendgroup(void *user) {} diff --git a/fitz/filt_faxd.c b/fitz/filt_faxd.c index 5da826ae..714629e7 100644 --- a/fitz/filt_faxd.c +++ b/fitz/filt_faxd.c @@ -625,14 +625,15 @@ eol: if (fax->rp < fax->wp) return p - buf; - fax->rp = fax->dst; - fax->wp = fax->dst + fax->stride; tmp = fax->ref; fax->ref = fax->dst; fax->dst = tmp; memset(fax->dst, 0, fax->stride); + fax->rp = fax->dst; + fax->wp = fax->dst + fax->stride; + fax->stage = SNORMAL; fax->c = 0; fax->a = -1; diff --git a/fitz/fitz.h b/fitz/fitz.h index 39542c0d..d79e280e 100644 --- a/fitz/fitz.h +++ b/fitz/fitz.h @@ -720,8 +720,8 @@ struct fz_colorspace_s }; fz_colorspace *fz_newcolorspace(char *name, int n); -fz_colorspace *fz_keepcolorspace(fz_colorspace *cs); -void fz_dropcolorspace(fz_colorspace *cs); +fz_colorspace *fz_keepcolorspace(fz_colorspace *colorspace); +void fz_dropcolorspace(fz_colorspace *colorspace); void fz_convertcolor(fz_colorspace *srcs, float *srcv, fz_colorspace *dsts, float *dstv); void fz_convertpixmap(fz_pixmap *src, fz_pixmap *dst); @@ -894,7 +894,7 @@ struct fz_shade_s int refs; fz_rect bbox; /* can be fz_infiniterect */ - fz_colorspace *cs; + fz_colorspace *colorspace; fz_matrix matrix; /* matrix from pattern dict */ int usebackground; /* background color for fills but not 'sh' */ @@ -1019,7 +1019,7 @@ struct fz_device_s void (*popclip)(void *); - void (*beginmask)(void *, fz_rect, int luminosity, fz_colorspace *cs, float *bc); + void (*beginmask)(void *, fz_rect, int luminosity, fz_colorspace *, float *bc); void (*endmask)(void *); void (*begingroup)(void *, fz_rect, int isolated, int knockout, fz_blendmode blendmode, float alpha); void (*endgroup)(void *); diff --git a/fitz/res_shade.c b/fitz/res_shade.c index d6108236..e4afa14a 100644 --- a/fitz/res_shade.c +++ b/fitz/res_shade.c @@ -12,8 +12,8 @@ fz_dropshade(fz_shade *shade) { if (shade && --shade->refs == 0) { - if (shade->cs) - fz_dropcolorspace(shade->cs); + if (shade->colorspace) + fz_dropcolorspace(shade->colorspace); fz_free(shade->mesh); fz_free(shade); } @@ -28,7 +28,7 @@ fz_boundshade(fz_shade *shade, fz_matrix ctm) int i, ncomp, nvert; ctm = fz_concat(shade->matrix, ctm); - ncomp = shade->usefunction ? 3 : 2 + shade->cs->n; + ncomp = shade->usefunction ? 3 : 2 + shade->colorspace->n; nvert = shade->meshlen / ncomp; v = shade->mesh; @@ -82,7 +82,7 @@ fz_debugshade(fz_shade *shade) shade->bbox.x0, shade->bbox.y0, shade->bbox.x1, shade->bbox.y1); - printf("\tcolorspace %s\n", shade->cs->name); + printf("\tcolorspace %s\n", shade->colorspace->name); printf("\tmatrix [%g %g %g %g %g %g]\n", shade->matrix.a, shade->matrix.b, shade->matrix.c, @@ -91,7 +91,7 @@ fz_debugshade(fz_shade *shade) if (shade->usebackground) { printf("\tbackground ["); - for (i = 0; i < shade->cs->n; i++) + for (i = 0; i < shade->colorspace->n; i++) printf("%s%g", i == 0 ? "" : " ", shade->background[i]); printf("]\n"); } @@ -102,7 +102,7 @@ fz_debugshade(fz_shade *shade) n = 3; } else - n = 2 + shade->cs->n; + n = 2 + shade->colorspace->n; printf("\tvertices: %d\n", shade->meshlen); diff --git a/mupdf/mupdf.h b/mupdf/mupdf.h index a9a2a2ea..fe4cfee3 100644 --- a/mupdf/mupdf.h +++ b/mupdf/mupdf.h @@ -555,7 +555,7 @@ enum struct pdf_material_s { int kind; - fz_colorspace *cs; + fz_colorspace *colorspace; pdf_pattern *pattern; fz_shade *shade; float alpha; @@ -597,10 +597,16 @@ struct pdf_csi_s fz_device *dev; pdf_xref *xref; - fz_obj *stack[32]; + fz_obj *obj; + char name[256]; + unsigned char string[256]; + int stringlen; + float stack[32]; int top; + int xbalance; - fz_obj *array; + int intext; + int inarray; /* path object state */ fz_path *path; @@ -627,6 +633,8 @@ void pdf_setcolor(pdf_csi *csi, int what, float *v); void pdf_setpattern(pdf_csi *csi, int what, pdf_pattern *pat, float *v); void pdf_setshade(pdf_csi *csi, int what, fz_shade *shade); void pdf_showpath(pdf_csi*, int close, int fill, int stroke, int evenodd); +void pdf_showspace(pdf_csi *csi, float tadj); +void pdf_showstring(pdf_csi *csi, unsigned char *buf, int len); void pdf_showtext(pdf_csi*, fz_obj *text); void pdf_flushtext(pdf_csi*); void pdf_showimage(pdf_csi*, fz_pixmap *image); diff --git a/mupdf/pdf_build.c b/mupdf/pdf_build.c index 739ec976..4e19db92 100644 --- a/mupdf/pdf_build.c +++ b/mupdf/pdf_build.c @@ -16,14 +16,14 @@ pdf_initgstate(pdf_gstate *gs, fz_matrix ctm) memset(gs->strokestate.dashlist, 0, sizeof(gs->strokestate.dashlist)); gs->stroke.kind = PDF_MCOLOR; - gs->stroke.cs = fz_keepcolorspace(fz_devicegray); + gs->stroke.colorspace = fz_keepcolorspace(fz_devicegray); gs->stroke.v[0] = 0; gs->stroke.pattern = nil; gs->stroke.shade = nil; gs->stroke.alpha = 1; gs->fill.kind = PDF_MCOLOR; - gs->fill.cs = fz_keepcolorspace(fz_devicegray); + gs->fill.colorspace = fz_keepcolorspace(fz_devicegray); gs->fill.v[0] = 0; gs->fill.pattern = nil; gs->fill.shade = nil; @@ -45,7 +45,7 @@ pdf_initgstate(pdf_gstate *gs, fz_matrix ctm) } void -pdf_setcolorspace(pdf_csi *csi, int what, fz_colorspace *cs) +pdf_setcolorspace(pdf_csi *csi, int what, fz_colorspace *colorspace) { pdf_gstate *gs = csi->gstate + csi->gtop; pdf_material *mat; @@ -54,10 +54,10 @@ pdf_setcolorspace(pdf_csi *csi, int what, fz_colorspace *cs) mat = what == PDF_MFILL ? &gs->fill : &gs->stroke; - fz_dropcolorspace(mat->cs); + fz_dropcolorspace(mat->colorspace); mat->kind = PDF_MCOLOR; - mat->cs = fz_keepcolorspace(cs); + mat->colorspace = fz_keepcolorspace(colorspace); mat->v[0] = 0; mat->v[1] = 0; @@ -80,13 +80,13 @@ pdf_setcolor(pdf_csi *csi, int what, float *v) { case PDF_MPATTERN: case PDF_MCOLOR: - if (!strcmp(mat->cs->name, "Lab")) + if (!strcmp(mat->colorspace->name, "Lab")) { mat->v[0] = v[0] / 100; mat->v[1] = (v[1] + 100) / 200; mat->v[2] = (v[2] + 100) / 200; } - for (i = 0; i < mat->cs->n; i++) + for (i = 0; i < mat->colorspace->n; i++) mat->v[i] = v[i]; break; default: @@ -310,7 +310,7 @@ pdf_showimage(pdf_csi *csi, fz_pixmap *image) break; case PDF_MCOLOR: csi->dev->fillimagemask(csi->dev->user, image, gstate->ctm, - gstate->fill.cs, gstate->fill.v, gstate->fill.alpha); + gstate->fill.colorspace, gstate->fill.v, gstate->fill.alpha); break; case PDF_MPATTERN: if (gstate->fill.pattern) @@ -380,7 +380,7 @@ pdf_showpath(pdf_csi *csi, int doclose, int dofill, int dostroke, int evenodd) break; case PDF_MCOLOR: csi->dev->fillpath(csi->dev->user, path, evenodd, gstate->ctm, - gstate->fill.cs, gstate->fill.v, gstate->fill.alpha); + gstate->fill.colorspace, gstate->fill.v, gstate->fill.alpha); break; case PDF_MPATTERN: if (gstate->fill.pattern) @@ -409,7 +409,7 @@ pdf_showpath(pdf_csi *csi, int doclose, int dofill, int dostroke, int evenodd) break; case PDF_MCOLOR: csi->dev->strokepath(csi->dev->user, path, &gstate->strokestate, gstate->ctm, - gstate->stroke.cs, gstate->stroke.v, gstate->stroke.alpha); + gstate->stroke.colorspace, gstate->stroke.v, gstate->stroke.alpha); break; case PDF_MPATTERN: if (gstate->stroke.pattern) @@ -487,7 +487,7 @@ pdf_flushtext(pdf_csi *csi) break; case PDF_MCOLOR: csi->dev->filltext(csi->dev->user, text, gstate->ctm, - gstate->fill.cs, gstate->fill.v, gstate->fill.alpha); + gstate->fill.colorspace, gstate->fill.v, gstate->fill.alpha); break; case PDF_MPATTERN: if (gstate->fill.pattern) @@ -516,7 +516,7 @@ pdf_flushtext(pdf_csi *csi) break; case PDF_MCOLOR: csi->dev->stroketext(csi->dev->user, text, &gstate->strokestate, gstate->ctm, - gstate->stroke.cs, gstate->stroke.v, gstate->stroke.alpha); + gstate->stroke.colorspace, gstate->stroke.v, gstate->stroke.alpha); break; case PDF_MPATTERN: if (gstate->stroke.pattern) @@ -629,11 +629,18 @@ pdf_showglyph(pdf_csi *csi, int cid) } } -static void +void pdf_showspace(pdf_csi *csi, float tadj) { pdf_gstate *gstate = csi->gstate + csi->gtop; pdf_fontdesc *fontdesc = gstate->font; + + if (!fontdesc) + { + fz_warn("cannot draw text since font and size not set"); + return; + } + if (fontdesc->wmode == 0) csi->tm = fz_concat(fz_translate(tadj * gstate->scale, 0), csi->tm); else @@ -641,13 +648,11 @@ pdf_showspace(pdf_csi *csi, float tadj) } void -pdf_showtext(pdf_csi *csi, fz_obj *text) +pdf_showstring(pdf_csi *csi, unsigned char *buf, int len) { pdf_gstate *gstate = csi->gstate + csi->gtop; pdf_fontdesc *fontdesc = gstate->font; - unsigned char *buf; - unsigned char *end; - int i, len; + unsigned char *end = buf + len; int cpt, cid; if (!fontdesc) @@ -656,34 +661,38 @@ pdf_showtext(pdf_csi *csi, fz_obj *text) return; } + while (buf < end) + { + buf = pdf_decodecmap(fontdesc->encoding, buf, &cpt); + cid = pdf_lookupcmap(fontdesc->encoding, cpt); + if (cid >= 0) + pdf_showglyph(csi, cid); + else + fz_warn("cannot encode character with code point %#x", cpt); + if (cpt == 32) + pdf_showspace(csi, gstate->wordspace); + } +} + +void +pdf_showtext(pdf_csi *csi, fz_obj *text) +{ + pdf_gstate *gstate = csi->gstate + csi->gtop; + int i; + if (fz_isarray(text)) { for (i = 0; i < fz_arraylen(text); i++) { fz_obj *item = fz_arrayget(text, i); if (fz_isstring(item)) - pdf_showtext(csi, item); + pdf_showstring(csi, (unsigned char *)fz_tostrbuf(item), fz_tostrlen(item)); else pdf_showspace(csi, - fz_toreal(item) * gstate->size * 0.001f); } } - - if (fz_isstring(text)) + else if (fz_isstring(text)) { - buf = (unsigned char *)fz_tostrbuf(text); - len = fz_tostrlen(text); - end = buf + len; - - while (buf < end) - { - buf = pdf_decodecmap(fontdesc->encoding, buf, &cpt); - cid = pdf_lookupcmap(fontdesc->encoding, cpt); - if (cid >= 0) - pdf_showglyph(csi, cid); - else - fz_warn("cannot encode character with code point %#x", cpt); - if (cpt == 32) - pdf_showspace(csi, gstate->wordspace); - } + pdf_showstring(csi, (unsigned char *)fz_tostrbuf(text), fz_tostrlen(text)); } } diff --git a/mupdf/pdf_colorspace.c b/mupdf/pdf_colorspace.c index 765b3c68..6203e1bb 100644 --- a/mupdf/pdf_colorspace.c +++ b/mupdf/pdf_colorspace.c @@ -246,8 +246,10 @@ loadindexed(fz_colorspace **csp, pdf_xref *xref, fz_obj *array) idx = fz_malloc(sizeof(struct indexed)); idx->base = base; idx->high = fz_toint(highobj); + idx->high = CLAMP(idx->high, 0, 255); n = base->n * (idx->high + 1); idx->lookup = fz_malloc(n); + memset(idx->lookup, 0, n); cs = fz_newcolorspace("Indexed", 1); cs->toxyz = indexedtoxyz; diff --git a/mupdf/pdf_crypt.c b/mupdf/pdf_crypt.c index 25cb1d8d..6266e188 100644 --- a/mupdf/pdf_crypt.c +++ b/mupdf/pdf_crypt.c @@ -120,6 +120,10 @@ pdf_newcrypt(pdf_crypt **cryptp, fz_obj *dict, fz_obj *id) } } } + + /* in crypt revision 4, the crypt filter determines the key length */ + if (crypt->strf.method != PDF_CRYPT_NONE) + crypt->length = crypt->stmf.length; } } @@ -251,6 +255,10 @@ pdf_parsecryptfilter(pdf_cryptfilter *cf, fz_obj *dict, int defaultlength) if (fz_isint(obj)) cf->length = fz_toint(obj); + /* the length for crypt filters is supposed to be in bytes not bits */ + if (cf->length < 40) + cf->length = cf->length * 8; + if ((cf->length % 8) != 0) return fz_throw("invalid key length: %d", cf->length); diff --git a/mupdf/pdf_interpret.c b/mupdf/pdf_interpret.c index db5fcf93..6de24e74 100644 --- a/mupdf/pdf_interpret.c +++ b/mupdf/pdf_interpret.c @@ -11,8 +11,14 @@ pdf_newcsi(pdf_xref *xref, fz_device *dev, fz_matrix ctm) csi->dev = dev; csi->top = 0; + csi->obj = nil; + csi->name[0] = 0; + csi->stringlen = 0; + memset(csi->stack, 0, sizeof csi->stack); + csi->xbalance = 0; - csi->array = nil; + csi->intext = 0; + csi->inarray = 0; csi->path = fz_newpath(); csi->clip = 0; @@ -35,16 +41,24 @@ static void pdf_clearstack(pdf_csi *csi) { int i; + + if (csi->obj) + fz_dropobj(csi->obj); + csi->obj = nil; + + csi->name[0] = 0; + csi->stringlen = 0; for (i = 0; i < csi->top; i++) - fz_dropobj(csi->stack[i]); + csi->stack[i] = 0; + csi->top = 0; } pdf_material * pdf_keepmaterial(pdf_material *mat) { - if (mat->cs) - fz_keepcolorspace(mat->cs); + if (mat->colorspace) + fz_keepcolorspace(mat->colorspace); if (mat->pattern) pdf_keeppattern(mat->pattern); if (mat->shade) @@ -55,8 +69,8 @@ pdf_keepmaterial(pdf_material *mat) pdf_material * pdf_dropmaterial(pdf_material *mat) { - if (mat->cs) - fz_dropcolorspace(mat->cs); + if (mat->colorspace) + fz_dropcolorspace(mat->colorspace); if (mat->pattern) pdf_droppattern(mat->pattern); if (mat->shade) @@ -134,7 +148,6 @@ pdf_freecsi(pdf_csi *csi) if (csi->path) fz_freepath(csi->path); if (csi->text) fz_freetext(csi->text); - if (csi->array) fz_dropobj(csi->array); pdf_clearstack(csi); @@ -260,8 +273,9 @@ pdf_runinlineimage(pdf_csi *csi, fz_obj *rdb, fz_stream *file, fz_obj *dict) } static fz_error -pdf_runextgstate(pdf_csi *csi, pdf_gstate *gstate, fz_obj *rdb, fz_obj *extgstate) +pdf_runextgstate(pdf_csi *csi, fz_obj *rdb, fz_obj *extgstate) { + pdf_gstate *gstate = csi->gstate + csi->gtop; fz_colorspace *colorspace; int i, k; @@ -400,962 +414,843 @@ pdf_runextgstate(pdf_csi *csi, pdf_gstate *gstate, fz_obj *rdb, fz_obj *extgstat return fz_okay; } -/* TODO: split pdf_runkeyword into more manageable pieces */ +static void pdf_run_BDC(pdf_csi *csi) +{ +} -static fz_error -pdf_runkeyword(pdf_csi *csi, fz_obj *rdb, char *buf) +static fz_error pdf_run_BI(pdf_csi *csi, fz_obj *rdb, fz_stream *file) { - pdf_gstate *gstate = csi->gstate + csi->gtop; + int ch; 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; + char *buf = csi->xref->scratch; + int buflen = sizeof(csi->xref->scratch); + fz_obj *obj; + + error = pdf_parsedict(&obj, csi->xref, file, buf, buflen); + if (error) + return fz_rethrow(error, "cannot parse inline image dictionary"); + + /* read whitespace after ID keyword */ + ch = fz_readbyte(file); + if (ch == '\r') + if (fz_peekbyte(file) == '\n') + fz_readbyte(file); + + error = pdf_runinlineimage(csi, rdb, file, obj); + fz_dropobj(obj); + if (error) + return fz_rethrow(error, "cannot parse inline image"); + + return fz_okay; +} + +static void pdf_run_B(pdf_csi *csi) +{ + pdf_showpath(csi, 0, 1, 1, 0); +} + +static void pdf_run_BMC(pdf_csi *csi) +{ +} + +static void pdf_run_BT(pdf_csi *csi) +{ + csi->intext = 1; + csi->tm = fz_identity; + csi->tlm = fz_identity; +} + +static void pdf_run_BX(pdf_csi *csi) +{ + csi->xbalance ++; +} - switch (buf[0]) +static void pdf_run_Bstar(pdf_csi *csi) +{ + pdf_showpath(csi, 0, 1, 1, 1); +} + +static fz_error pdf_run_cs_imp(pdf_csi *csi, fz_obj *rdb, int what) +{ + fz_colorspace *colorspace; + fz_obj *obj, *dict; + fz_error error; + + if (!strcmp(csi->name, "Pattern")) + { + pdf_setpattern(csi, what, nil, nil); + } + else { - case 'B': - switch(buf[1]) + if (!strcmp(csi->name, "DeviceGray")) + colorspace = fz_keepcolorspace(fz_devicegray); + else if (!strcmp(csi->name, "DeviceRGB")) + colorspace = fz_keepcolorspace(fz_devicergb); + else if (!strcmp(csi->name, "DeviceCMYK")) + colorspace = fz_keepcolorspace(fz_devicecmyk); + else { - case 0: /* "B" */ - if (csi->top < 0) - goto syntaxerror; - pdf_showpath(csi, 0, 1, 1, 0); - break; - case 'D': /* "BDC" */ - if ((buf[2] != 'C') || (buf[3] != 0)) - goto defaultcase; - if (csi->top < 2) - goto syntaxerror; - break; - case 'M': /* "BMC" */ - if ((buf[2] != 'C') || (buf[3] != 0)) - goto defaultcase; - if (csi->top < 1) - goto syntaxerror; - break; - case 'T': /* "BT" */ - if (buf[2] != 0) - goto defaultcase; - if (csi->top < 0) - goto syntaxerror; - csi->tm = fz_identity; - csi->tlm = fz_identity; - break; - case 'X': /* "BX" */ - if (buf[2] != 0) - goto defaultcase; - if (csi->top < 0) - goto syntaxerror; - csi->xbalance ++; - break; - case '*': /* "B*" */ - if (buf[2] != 0) - goto defaultcase; - if (csi->top < 0) - goto syntaxerror; - pdf_showpath(csi, 0, 1, 1, 1); - break; - default: - goto defaultcase; + dict = fz_dictgets(rdb, "ColorSpace"); + if (!dict) + return fz_throw("cannot find ColorSpace dictionary"); + obj = fz_dictgets(dict, csi->name); + if (!obj) + return fz_throw("cannot find colorspace resource '%s'", csi->name); + error = pdf_loadcolorspace(&colorspace, csi->xref, obj); + if (error) + return fz_rethrow(error, "cannot load colorspace (%d 0 R)", fz_tonum(obj)); } - break; - case 'C': /* "CS" */ - if ((buf[1] == 'S') && (buf[2] == 0)) - { - fz_colorspace *cs; - fz_obj *obj; + pdf_setcolorspace(csi, what, colorspace); + + fz_dropcolorspace(colorspace); + } + return fz_okay; +} + +static void pdf_run_CS(pdf_csi *csi, fz_obj *rdb) +{ + fz_error error; + error = pdf_run_cs_imp(csi, rdb, PDF_MSTROKE); + if (error) + fz_catch(error, "cannot set colorspace"); +} - what = PDF_MSTROKE; +static void pdf_run_cs(pdf_csi *csi, fz_obj *rdb) +{ + fz_error error; + error = pdf_run_cs_imp(csi, rdb, PDF_MFILL); + if (error) + fz_catch(error, "cannot set colorspace"); +} -Lsetcolorspace: - if (csi->top < 1) - goto syntaxerror; +static void pdf_run_DP(pdf_csi *csi) +{ +} - obj = csi->stack[0]; +static fz_error pdf_run_Do(pdf_csi *csi, fz_obj *rdb) +{ + fz_obj *dict; + fz_obj *obj; + fz_obj *subtype; + fz_error error; - if (!fz_isname(obj)) - return fz_throw("malformed CS"); + dict = fz_dictgets(rdb, "XObject"); + if (!dict) + return fz_throw("cannot find XObject dictionary when looking for: '%s'", csi->name); - if (!strcmp(fz_toname(obj), "Pattern")) - { - pdf_setpattern(csi, what, nil, nil); - } + obj = fz_dictgets(dict, csi->name); + if (!obj) + return fz_throw("cannot find xobject resource: '%s'", csi->name); - else - { - if (!strcmp(fz_toname(obj), "DeviceGray")) - cs = fz_keepcolorspace(fz_devicegray); - else if (!strcmp(fz_toname(obj), "DeviceRGB")) - cs = fz_keepcolorspace(fz_devicergb); - else if (!strcmp(fz_toname(obj), "DeviceCMYK")) - cs = fz_keepcolorspace(fz_devicecmyk); - else - { - fz_obj *dict = fz_dictgets(rdb, "ColorSpace"); - if (!dict) - return fz_throw("cannot find ColorSpace dictionary"); - obj = fz_dictget(dict, obj); - if (!obj) - return fz_throw("cannot find colorspace resource /%s", fz_toname(csi->stack[0])); - - error = pdf_loadcolorspace(&cs, csi->xref, obj); - if (error) - return fz_rethrow(error, "cannot load colorspace (%d %d R)", fz_tonum(obj), fz_togen(obj)); - } + subtype = fz_dictgets(obj, "Subtype"); + if (!fz_isname(subtype)) + return fz_throw("no XObject subtype specified"); - pdf_setcolorspace(csi, what, cs); + if (!strcmp(fz_toname(subtype), "Form") && fz_dictgets(obj, "Subtype2")) + subtype = fz_dictgets(obj, "Subtype2"); - fz_dropcolorspace(cs); - } - } - else - goto defaultcase; - break; + if (!strcmp(fz_toname(subtype), "Form")) + { + pdf_xobject *xobj; - case 'D': - switch (buf[1]) - { - case 'P': /* "Dp" */ - if (buf[2] != 0) - goto defaultcase; - if (csi->top < 2) - goto syntaxerror; - break; - case 'o': /* "Do" */ + error = pdf_loadxobject(&xobj, csi->xref, obj); + if (error) + return fz_rethrow(error, "cannot load xobject (%d %d R)", fz_tonum(obj), fz_togen(obj)); + + /* Inherit parent resources, in case this one was empty XXX check where it's loaded */ + if (!xobj->resources) + xobj->resources = fz_keepobj(rdb); + + error = pdf_runxobject(csi, xobj->resources, xobj, fz_identity); + if (error) + return fz_rethrow(error, "cannot draw xobject (%d %d R)", fz_tonum(obj), fz_togen(obj)); + + pdf_dropxobject(xobj); + } + + else if (!strcmp(fz_toname(subtype), "Image")) + { + if ((csi->dev->hints & FZ_IGNOREIMAGE) == 0) { - fz_obj *dict; - fz_obj *obj; - fz_obj *subtype; + fz_pixmap *img; + error = pdf_loadimage(&img, csi->xref, obj); + if (error) + return fz_rethrow(error, "cannot load image (%d %d R)", fz_tonum(obj), fz_togen(obj)); + pdf_showimage(csi, img); + fz_droppixmap(img); + } + } - if (buf[2] != 0) - goto defaultcase; - if (csi->top < 1) - goto syntaxerror; + else if (!strcmp(fz_toname(subtype), "PS")) + { + fz_warn("ignoring XObject with subtype PS"); + } - dict = fz_dictgets(rdb, "XObject"); - if (!dict) - return fz_throw("cannot find XObject dictionary when looking for: '%s'", fz_toname(csi->stack[0])); + else + { + return fz_throw("unknown XObject subtype: '%s'", fz_toname(subtype)); + } - obj = fz_dictget(dict, csi->stack[0]); - if (!obj) - return fz_throw("cannot find xobject resource: '%s'", fz_toname(csi->stack[0])); + return fz_okay; +} - subtype = fz_dictgets(obj, "Subtype"); - if (!fz_isname(subtype)) - return fz_throw("no XObject subtype specified"); +static void pdf_run_EMC(pdf_csi *csi) +{ +} - if (!strcmp(fz_toname(subtype), "Form") && fz_dictgets(obj, "Subtype2")) - subtype = fz_dictgets(obj, "Subtype2"); +static void pdf_run_ET(pdf_csi *csi) +{ + pdf_flushtext(csi); + csi->accumulate = 1; + csi->intext = 0; +} - if (!strcmp(fz_toname(subtype), "Form")) - { - pdf_xobject *xobj; +static void pdf_run_EX(pdf_csi *csi) +{ + csi->xbalance --; +} - error = pdf_loadxobject(&xobj, csi->xref, obj); - if (error) - return fz_rethrow(error, "cannot load xobject (%d %d R)", fz_tonum(obj), fz_togen(obj)); +static void pdf_run_F(pdf_csi *csi) +{ + pdf_showpath(csi, 0, 1, 0, 0); +} - /* Inherit parent resources, in case this one was empty XXX check where it's loaded */ - if (!xobj->resources) - xobj->resources = fz_keepobj(rdb); +static void pdf_run_G(pdf_csi *csi) +{ + pdf_setcolorspace(csi, PDF_MSTROKE, fz_devicegray); + pdf_setcolor(csi, PDF_MSTROKE, csi->stack); +} - error = pdf_runxobject(csi, rdb, xobj, fz_identity); - if (error) - return fz_rethrow(error, "cannot draw xobject (%d %d R)", fz_tonum(obj), fz_togen(obj)); +static void pdf_run_J(pdf_csi *csi) +{ + pdf_gstate *gstate = csi->gstate + csi->gtop; + gstate->strokestate.linecap = csi->stack[0]; +} - pdf_dropxobject(xobj); - } +static void pdf_run_K(pdf_csi *csi) +{ + pdf_setcolorspace(csi, PDF_MSTROKE, fz_devicecmyk); + pdf_setcolor(csi, PDF_MSTROKE, csi->stack); +} - else if (!strcmp(fz_toname(subtype), "Image")) - { - if ((csi->dev->hints & FZ_IGNOREIMAGE) == 0) - { - fz_pixmap *img; - error = pdf_loadimage(&img, csi->xref, obj); - if (error) - return fz_rethrow(error, "cannot load image (%d %d R)", fz_tonum(obj), fz_togen(obj)); - pdf_showimage(csi, img); - fz_droppixmap(img); - } - } +static void pdf_run_M(pdf_csi *csi) +{ + pdf_gstate *gstate = csi->gstate + csi->gtop; + gstate->strokestate.miterlimit = csi->stack[0]; +} - else if (!strcmp(fz_toname(subtype), "PS")) - { - fz_warn("ignoring XObject with subtype PS"); - } +static void pdf_run_MP(pdf_csi *csi) +{ +} - else - { - return fz_throw("unknown XObject subtype: %s", fz_toname(subtype)); - } - break; - } - default: - goto defaultcase; - } - break; +static void pdf_run_Q(pdf_csi *csi) +{ + pdf_grestore(csi); +} - case 'E': - switch (buf[1]) - { - case 'X': /* "EX" */ - if (buf[2] != 0) - goto defaultcase; - if (csi->top < 0) - goto syntaxerror; - csi->xbalance --; - break; - case 'M': /* "EW" */ - if ((buf[2] != 'C') || (buf[3] != 0)) - goto defaultcase; - if (csi->top < 0) - goto syntaxerror; - break; - case 'T': /* "ET" */ - if (buf[2] != 0) - goto defaultcase; - if (csi->top < 0) - goto syntaxerror; - pdf_flushtext(csi); - csi->accumulate = 1; - break; - default: - goto defaultcase; - } - break; +static void pdf_run_RG(pdf_csi *csi) +{ + pdf_setcolorspace(csi, PDF_MSTROKE, fz_devicergb); + pdf_setcolor(csi, PDF_MSTROKE, csi->stack); +} - case 'F': /* "F" */ - if (buf[1] != 0) - goto defaultcase; - if (csi->top < 0) - goto syntaxerror; - pdf_showpath(csi, 0, 1, 0, 0); - break; +static void pdf_run_S(pdf_csi *csi) +{ + pdf_showpath(csi, 0, 0, 1, 0); +} - case 'G': /* "G" */ - if (buf[1] != 0) - goto defaultcase; - if (csi->top < 1) - goto syntaxerror; +static fz_error pdf_run_SC_imp(pdf_csi *csi, fz_obj *rdb, int what, pdf_material *mat) +{ + fz_error error; + fz_obj *patterntype; + fz_obj *dict; + fz_obj *obj; + int kind; - v[0] = fz_toreal(csi->stack[0]); - pdf_setcolorspace(csi, PDF_MSTROKE, fz_devicegray); - pdf_setcolor(csi, PDF_MSTROKE, v); - break; + kind = mat->kind; + if (csi->name[0]) + kind = PDF_MPATTERN; + + switch (kind) + { + case PDF_MNONE: + return fz_throw("cannot set color in mask objects"); - case 'J': /* "J" */ - if (buf[1] != 0) - goto defaultcase; - if (csi->top < 1) - goto syntaxerror; - gstate->strokestate.linecap = fz_toint(csi->stack[0]); + case PDF_MCOLOR: + pdf_setcolor(csi, what, csi->stack); break; - case 'K': /* "K" */ - if (buf[1] != 0) - goto defaultcase; - if (csi->top < 4) - goto syntaxerror; + case PDF_MPATTERN: + dict = fz_dictgets(rdb, "Pattern"); + if (!dict) + return fz_throw("cannot find Pattern dictionary"); - 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]); + obj = fz_dictgets(dict, csi->name); + if (!obj) + return fz_throw("cannot find pattern resource '%s'", csi->name); - pdf_setcolorspace(csi, PDF_MSTROKE, fz_devicecmyk); - pdf_setcolor(csi, PDF_MSTROKE, v); - break; + patterntype = fz_dictgets(obj, "PatternType"); - case 'M': - switch (buf[1]) + if (fz_toint(patterntype) == 1) { - case 0: /* "M" */ - if (csi->top < 1) - goto syntaxerror; - gstate->strokestate.miterlimit = fz_toreal(csi->stack[0]); - break; - case 'P': /* "Mp" */ - if (buf[2] != 0) - goto defaultcase; - if (csi->top < 1) - goto syntaxerror; - break; - default: - goto defaultcase; + pdf_pattern *pat; + error = pdf_loadpattern(&pat, csi->xref, obj); + if (error) + return fz_rethrow(error, "cannot load pattern (%d 0 R)", fz_tonum(obj)); + pdf_setpattern(csi, what, pat, csi->top > 0 ? csi->stack : nil); + pdf_droppattern(pat); + } + else if (fz_toint(patterntype) == 2) + { + fz_shade *shd; + error = pdf_loadshading(&shd, csi->xref, obj); + if (error) + return fz_rethrow(error, "cannot load shading (%d 0 R)", fz_tonum(obj)); + pdf_setshade(csi, what, shd); + fz_dropshade(shd); + } + else + { + return fz_throw("unknown pattern type: %d", fz_toint(patterntype)); } break; - case 'Q': /* "Q" */ - if (buf[1] != 0) - goto defaultcase; - if (csi->top < 0) - goto syntaxerror; - pdf_grestore(csi); - break; + case PDF_MSHADE: + return fz_throw("cannot set color in shade objects"); + } - case 'R': /* "RG" */ - if ((buf[1] != 'G') || (buf[2] != 0)) - goto defaultcase; - if (csi->top < 3) - goto syntaxerror; + return fz_okay; +} - v[0] = fz_toreal(csi->stack[0]); - v[1] = fz_toreal(csi->stack[1]); - v[2] = fz_toreal(csi->stack[2]); +static void pdf_run_SC(pdf_csi *csi, fz_obj *rdb) +{ + fz_error error; + pdf_gstate *gstate = csi->gstate + csi->gtop; + error = pdf_run_SC_imp(csi, rdb, PDF_MSTROKE, &gstate->stroke); + if (error) + fz_catch(error, "cannot set color and colorspace"); +} - pdf_setcolorspace(csi, PDF_MSTROKE, fz_devicergb); - pdf_setcolor(csi, PDF_MSTROKE, v); - break; +static void pdf_run_sc(pdf_csi *csi, fz_obj *rdb) +{ + fz_error error; + pdf_gstate *gstate = csi->gstate + csi->gtop; + error = pdf_run_SC_imp(csi, rdb, PDF_MFILL, &gstate->fill); + if (error) + fz_catch(error, "cannot set color and colorspace"); +} - case 'S': - switch (buf[1]) - { - case 0: /* "S" */ - if (csi->top < 0) - goto syntaxerror; - pdf_showpath(csi, 0, 0, 1, 0); - break; - case 'C': /* "SC" or "SCN" */ - { - pdf_material *mat; - fz_obj *patterntype; - fz_obj *dict; - fz_obj *obj; - int kind; +static void pdf_run_Tc(pdf_csi *csi) +{ + pdf_gstate *gstate = csi->gstate + csi->gtop; + gstate->charspace = csi->stack[0]; +} - if ((buf[2] != 0) && ((buf[2] != 'N') || (buf[3] != 0))) - goto defaultcase; +static void pdf_run_Tw(pdf_csi *csi) +{ + pdf_gstate *gstate = csi->gstate + csi->gtop; + gstate->wordspace = csi->stack[0]; +} - what = PDF_MSTROKE; +static void pdf_run_Tz(pdf_csi *csi) +{ + pdf_gstate *gstate = csi->gstate + csi->gtop; + float a = csi->stack[0] / 100; + pdf_flushtext(csi); + gstate->scale = a; +} -Lsetcolor: - mat = what == PDF_MSTROKE ? &gstate->stroke : &gstate->fill; +static void pdf_run_TL(pdf_csi *csi) +{ + pdf_gstate *gstate = csi->gstate + csi->gtop; + gstate->leading = csi->stack[0]; +} - kind = mat->kind; - if (fz_isname(csi->stack[csi->top - 1])) - kind = PDF_MPATTERN; +static fz_error pdf_run_Tf(pdf_csi *csi, fz_obj *rdb) +{ + pdf_gstate *gstate = csi->gstate + csi->gtop; + fz_error error; + fz_obj *dict; + fz_obj *obj; - switch (kind) - { - case PDF_MNONE: - return fz_throw("cannot set color in mask objects"); + gstate->size = csi->stack[0]; + if (gstate->font) + pdf_dropfont(gstate->font); + gstate->font = nil; - case PDF_MCOLOR: - if (csi->top < mat->cs->n) - goto syntaxerror; - for (i = 0; i < csi->top; i++) - v[i] = fz_toreal(csi->stack[i]); - pdf_setcolor(csi, what, v); - break; + dict = fz_dictgets(rdb, "Font"); + if (!dict) + return fz_throw("cannot find Font dictionary"); - case PDF_MPATTERN: - for (i = 0; i < csi->top - 1; i++) - v[i] = fz_toreal(csi->stack[i]); + obj = fz_dictgets(dict, csi->name); + if (!obj) + return fz_throw("cannot find font resource: '%s'", csi->name); - dict = fz_dictgets(rdb, "Pattern"); - if (!dict) - return fz_throw("cannot find Pattern dictionary"); + error = pdf_loadfont(&gstate->font, csi->xref, rdb, obj); + if (error) + return fz_rethrow(error, "cannot load font (%d 0 R)", fz_tonum(obj)); - obj = fz_dictget(dict, csi->stack[csi->top - 1]); - if (!obj) - return fz_throw("cannot find pattern resource /%s", - fz_toname(csi->stack[csi->top - 1])); + return fz_okay; +} - patterntype = fz_dictgets(obj, "PatternType"); +static void pdf_run_Tr(pdf_csi *csi) +{ + pdf_gstate *gstate = csi->gstate + csi->gtop; + gstate->render = csi->stack[0]; +} - if (fz_toint(patterntype) == 1) - { - pdf_pattern *pat; - error = pdf_loadpattern(&pat, csi->xref, obj); - if (error) - return fz_rethrow(error, "cannot load pattern (%d %d R)", fz_tonum(obj), fz_togen(obj)); - pdf_setpattern(csi, what, pat, csi->top == 1 ? nil : v); - pdf_droppattern(pat); - } +static void pdf_run_Ts(pdf_csi *csi) +{ + pdf_gstate *gstate = csi->gstate + csi->gtop; + gstate->rise = csi->stack[0]; +} - else if (fz_toint(patterntype) == 2) - { - fz_shade *shd; - error = pdf_loadshading(&shd, csi->xref, obj); - if (error) - return fz_rethrow(error, "cannot load shading (%d %d R)", fz_tonum(obj), fz_togen(obj)); - pdf_setshade(csi, what, shd); - fz_dropshade(shd); - } +static void pdf_run_Td(pdf_csi *csi) +{ + fz_matrix m = fz_translate(csi->stack[0], csi->stack[1]); + csi->tlm = fz_concat(m, csi->tlm); + csi->tm = csi->tlm; +} - else - { - return fz_throw("unknown pattern type: %d", fz_toint(patterntype)); - } +static void pdf_run_TD(pdf_csi *csi) +{ + pdf_gstate *gstate = csi->gstate + csi->gtop; + fz_matrix m; - break; + gstate->leading = -csi->stack[1]; + m = fz_translate(csi->stack[0], csi->stack[1]); + csi->tlm = fz_concat(m, csi->tlm); + csi->tm = csi->tlm; +} - case PDF_MSHADE: - return fz_throw("cannot set color in shade objects"); - } - break; - } - default: - goto defaultcase; - } - break; +static void pdf_run_Tm(pdf_csi *csi) +{ + pdf_flushtext(csi); + csi->tm.a = csi->stack[0]; + csi->tm.b = csi->stack[1]; + csi->tm.c = csi->stack[2]; + csi->tm.d = csi->stack[3]; + csi->tm.e = csi->stack[4]; + csi->tm.f = csi->stack[5]; + csi->tlm = csi->tm; +} - case 'T': - switch (buf[1]) - { - case 'c': /* "Tc" */ - if (buf[2] != 0) - goto defaultcase; - if (csi->top < 1) - goto syntaxerror; - gstate->charspace = fz_toreal(csi->stack[0]); - break; - case 'w': /* "Tw" */ - if (buf[2] != 0) - goto defaultcase; - if (csi->top < 1) - goto syntaxerror; - gstate->wordspace = fz_toreal(csi->stack[0]); - break; - case 'z': /* "Tz" */ - if (buf[2] != 0) - goto defaultcase; - if (csi->top < 1) - goto syntaxerror; - a = fz_toreal(csi->stack[0]) / 100; - pdf_flushtext(csi); - gstate->scale = a; - break; - case 'L': /* "TL" */ - if (buf[2] != 0) - goto defaultcase; - if (csi->top < 1) - goto syntaxerror; - gstate->leading = fz_toreal(csi->stack[0]); - break; - case 'f': /* "Tf" */ - { - fz_obj *dict; - fz_obj *obj; +static void pdf_run_Tstar(pdf_csi *csi) +{ + pdf_gstate *gstate = csi->gstate + csi->gtop; + fz_matrix m = fz_translate(0, -gstate->leading); + csi->tlm = fz_concat(m, csi->tlm); + csi->tm = csi->tlm; +} + +static void pdf_run_Tj(pdf_csi *csi) +{ + if (csi->stringlen) + pdf_showstring(csi, csi->string, csi->stringlen); + else + pdf_showtext(csi, csi->obj); +} - if (buf[2] != 0) - goto defaultcase; - if (csi->top < 2) - goto syntaxerror; +static void pdf_run_TJ(pdf_csi *csi) +{ + if (csi->stringlen) + pdf_showstring(csi, csi->string, csi->stringlen); + else + pdf_showtext(csi, csi->obj); +} - dict = fz_dictgets(rdb, "Font"); - if (!dict) - return fz_throw("cannot find Font dictionary"); +static void pdf_run_W(pdf_csi *csi) +{ + csi->clip = 1; + csi->clipevenodd = 0; +} - obj = fz_dictget(dict, csi->stack[0]); - if (!obj) - return fz_throw("cannot find font resource: %s", fz_toname(csi->stack[0])); +static void pdf_run_Wstar(pdf_csi *csi) +{ + csi->clip = 1; + csi->clipevenodd = 1; +} - if (gstate->font) - { - pdf_dropfont(gstate->font); - gstate->font = nil; - } +static void pdf_run_b(pdf_csi *csi) +{ + pdf_showpath(csi, 1, 1, 1, 0); +} - error = pdf_loadfont(&gstate->font, csi->xref, rdb, obj); - if (error) - return fz_rethrow(error, "cannot load font (%d %d R)", fz_tonum(obj), fz_togen(obj)); +static void pdf_run_bstar(pdf_csi *csi) +{ + pdf_showpath(csi, 1, 1, 1, 1); +} - gstate->size = fz_toreal(csi->stack[1]); +static void pdf_run_c(pdf_csi *csi) +{ + float a, b, c, d, e, f; + a = csi->stack[0]; + b = csi->stack[1]; + c = csi->stack[2]; + d = csi->stack[3]; + e = csi->stack[4]; + f = csi->stack[5]; + fz_curveto(csi->path, a, b, c, d, e, f); +} - break; - } - case 'r': /* "Tr" */ - if (buf[2] != 0) - goto defaultcase; - if (csi->top < 1) - goto syntaxerror; - gstate->render = fz_toint(csi->stack[0]); - break; - case 's': /* "Ts" */ - if (buf[2] != 0) - goto defaultcase; - if (csi->top < 1) - goto syntaxerror; - gstate->rise = fz_toreal(csi->stack[0]); - break; - case 'd': /* "Td" */ - if (buf[2] != 0) - goto defaultcase; - 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; - break; - case 'D': /* "TD" */ - if (buf[2] != 0) - goto defaultcase; - 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; - break; - case 'm': /* "Tm" */ - if (buf[2] != 0) - goto defaultcase; - 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]); - - pdf_flushtext(csi); - - csi->tm = m; - csi->tlm = csi->tm; - break; - case '*': /* "T*" */ - if (buf[2] != 0) - goto defaultcase; - if (csi->top < 0) - goto syntaxerror; - m = fz_translate(0, -gstate->leading); - csi->tlm = fz_concat(m, csi->tlm); - csi->tm = csi->tlm; - break; - case 'j': /* "Tj" */ - if (buf[2] != 0) - goto defaultcase; - if (csi->top < 1) - goto syntaxerror; - pdf_showtext(csi, csi->stack[0]); - break; - case 'J': /* "TJ" */ - if (buf[2] != 0) - goto defaultcase; - if (csi->top < 1) - goto syntaxerror; - pdf_showtext(csi, csi->stack[0]); - break; - default: - goto defaultcase; - } - break; +static void pdf_run_cm(pdf_csi *csi) +{ + pdf_gstate *gstate = csi->gstate + csi->gtop; + fz_matrix m; - case 'W': - switch (buf[1]) - { - case 0: /* "W" */ - if (csi->top < 0) - goto syntaxerror; - csi->clip = 1; - csi->clipevenodd = 0; - break; - case '*': /* "W*" */ - if (buf[2] != 0) - goto defaultcase; - if (csi->top < 0) - goto syntaxerror; - csi->clip = 1; - csi->clipevenodd = 1; - break; - default: - goto defaultcase; - } - break; + m.a = csi->stack[0]; + m.b = csi->stack[1]; + m.c = csi->stack[2]; + m.d = csi->stack[3]; + m.e = csi->stack[4]; + m.f = csi->stack[5]; - case 'b': - switch (buf[1]) - { - case 0: /* "b" */ - if (csi->top < 0) - goto syntaxerror; - pdf_showpath(csi, 1, 1, 1, 0); - break; - case '*': /* "b*" */ - if (buf[2] != 0) - goto defaultcase; - if (csi->top < 0) - goto syntaxerror; - pdf_showpath(csi, 1, 1, 1, 1); - break; - default: - goto defaultcase; - } - break; + gstate->ctm = fz_concat(m, gstate->ctm); +} - case 'c': - switch (buf[1]) - { - case 0: /* "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]); - fz_curveto(csi->path, a, b, c, d, e, f); - break; - case 'm': /* "cm" */ - { - if (buf[2] != 0) - goto defaultcase; - 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]); - - gstate->ctm = fz_concat(m, gstate->ctm); - break; - } - case 's': /* "cs" */ - if (buf[2] != 0) - goto defaultcase; - what = PDF_MFILL; - goto Lsetcolorspace; - default: - goto defaultcase; - } - break; +static void pdf_run_d(pdf_csi *csi) +{ + pdf_gstate *gstate = csi->gstate + csi->gtop; + fz_obj *array; + int i; - case 'd': - switch (buf[1]) - { - case 0: /* "d" */ - { - fz_obj *array; - if (csi->top < 2) - goto syntaxerror; - array = csi->stack[0]; - gstate->strokestate.dashlen = fz_arraylen(array); - if (gstate->strokestate.dashlen > 32) - return fz_throw("assert: dash pattern too big"); - for (i = 0; i < gstate->strokestate.dashlen; i++) - gstate->strokestate.dashlist[i] = fz_toreal(fz_arrayget(array, i)); - gstate->strokestate.dashphase = fz_toreal(csi->stack[1]); - break; - } - case '0': /* "d0" */ - case '1': /* "d1" */ - if (buf[2] != 0) - goto defaultcase; - /* we don't care about setcharwidth and setcachedevice */ - break; - default: - goto defaultcase; - } - break; + array = csi->obj; + gstate->strokestate.dashlen = MIN(fz_arraylen(array), nelem(gstate->strokestate.dashlist)); + for (i = 0; i < gstate->strokestate.dashlen; i++) + gstate->strokestate.dashlist[i] = fz_toreal(fz_arrayget(array, i)); + gstate->strokestate.dashphase = csi->stack[0]; +} - case 'f': - switch (buf[1]) - { - case 0: /* "f" */ - if (csi->top < 0) - goto syntaxerror; - pdf_showpath(csi, 0, 1, 0, 0); - break; - case '*': /* "f*" */ - if (buf[2] != 0) - goto defaultcase; - if (csi->top < 0) - goto syntaxerror; - pdf_showpath(csi, 0, 1, 0, 1); - break; - default: - goto defaultcase; - } - break; +static void pdf_run_d0(pdf_csi *csi) +{ +} - case 'g': - switch (buf[1]) - { - case 0: /* "g" */ - if (csi->top < 1) - goto syntaxerror; +static void pdf_run_d1(pdf_csi *csi) +{ +} - v[0] = fz_toreal(csi->stack[0]); - pdf_setcolorspace(csi, PDF_MFILL, fz_devicegray); - pdf_setcolor(csi, PDF_MFILL, v); - break; - case 's': /* "gs" */ - { - fz_obj *dict; - fz_obj *obj; +static void pdf_run_f(pdf_csi *csi) +{ + pdf_showpath(csi, 0, 1, 0, 0); +} - if (buf[2] != 0) - goto defaultcase; - if (csi->top < 1) - goto syntaxerror; +static void pdf_run_fstar(pdf_csi *csi) +{ + pdf_showpath(csi, 0, 1, 0, 1); +} - dict = fz_dictgets(rdb, "ExtGState"); - if (!dict) - return fz_throw("cannot find ExtGState dictionary"); +static void pdf_run_g(pdf_csi *csi) +{ + pdf_setcolorspace(csi, PDF_MFILL, fz_devicegray); + pdf_setcolor(csi, PDF_MFILL, csi->stack); +} - obj = fz_dictget(dict, csi->stack[0]); - if (!obj) - return fz_throw("cannot find extgstate resource /%s", fz_toname(csi->stack[0])); +static fz_error pdf_run_gs(pdf_csi *csi, fz_obj *rdb) +{ + fz_error error; + fz_obj *dict; + fz_obj *obj; - error = pdf_runextgstate(csi, gstate, rdb, obj); - if (error) - return fz_rethrow(error, "cannot set ExtGState (%d %d R)", fz_tonum(obj), fz_togen(obj)); - break; - } - default: - goto defaultcase; - } - break; + dict = fz_dictgets(rdb, "ExtGState"); + if (!dict) + return fz_throw("cannot find ExtGState dictionary"); - case 'h': /* "h" */ - if (buf[1] != 0) - goto defaultcase; - if (csi->top < 0) - goto syntaxerror; - fz_closepath(csi->path); - break; + obj = fz_dictgets(dict, csi->name); + if (!obj) + return fz_throw("cannot find extgstate resource '%s'", csi->name); - case 'i': /* "i" */ - if (buf[1] != 0) - goto defaultcase; - if (csi->top < 1) - goto syntaxerror; - /* flatness */ - break; + error = pdf_runextgstate(csi, rdb, obj); + if (error) + return fz_rethrow(error, "cannot set ExtGState (%d 0 R)", fz_tonum(obj)); + return fz_okay; +} - case 'j': /* "j" */ - if (buf[1] != 0) - goto defaultcase; - if (csi->top < 1) - goto syntaxerror; - gstate->strokestate.linejoin = fz_toint(csi->stack[0]); - break; +static void pdf_run_h(pdf_csi *csi) +{ + fz_closepath(csi->path); +} - case 'k': /* "k" */ - if (buf[1] != 0) - goto defaultcase; - if (csi->top < 4) - goto syntaxerror; +static void pdf_run_i(pdf_csi *csi) +{ +} - 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]); +static void pdf_run_j(pdf_csi *csi) +{ + pdf_gstate *gstate = csi->gstate + csi->gtop; + gstate->strokestate.linejoin = csi->stack[0]; +} - pdf_setcolorspace(csi, PDF_MFILL, fz_devicecmyk); - pdf_setcolor(csi, PDF_MFILL, v); - break; +static void pdf_run_k(pdf_csi *csi) +{ + pdf_setcolorspace(csi, PDF_MFILL, fz_devicecmyk); + pdf_setcolor(csi, PDF_MFILL, csi->stack); +} - case 'l': /* "l" */ - if (buf[1] != 0) - goto defaultcase; - if (csi->top < 2) - goto syntaxerror; - a = fz_toreal(csi->stack[0]); - b = fz_toreal(csi->stack[1]); - fz_lineto(csi->path, a, b); - break; +static void pdf_run_l(pdf_csi *csi) +{ + float a, b; + a = csi->stack[0]; + b = csi->stack[1]; + fz_lineto(csi->path, a, b); +} - case 'm': /* "m" */ - if (buf[1] != 0) - goto defaultcase; - if (csi->top < 2) - goto syntaxerror; - a = fz_toreal(csi->stack[0]); - b = fz_toreal(csi->stack[1]); - fz_moveto(csi->path, a, b); - break; +static void pdf_run_m(pdf_csi *csi) +{ + float a, b; + a = csi->stack[0]; + b = csi->stack[1]; + fz_moveto(csi->path, a, b); +} - case 'n': /* "n" */ - if (buf[1] != 0) - goto defaultcase; - if (csi->top < 0) - goto syntaxerror; - pdf_showpath(csi, 0, 0, 0, csi->clipevenodd); - break; +static void pdf_run_n(pdf_csi *csi) +{ + pdf_showpath(csi, 0, 0, 0, csi->clipevenodd); +} - case 'q': /* "q" */ - if (buf[1] != 0) - goto defaultcase; - if (csi->top < 0) - goto syntaxerror; - pdf_gsave(csi); - break; +static void pdf_run_q(pdf_csi *csi) +{ + pdf_gsave(csi); +} - case 'r': - switch (buf[1]) - { - case 'i': /* "ri" */ - if (buf[2] != 0) - goto defaultcase; - if (csi->top < 1) - goto syntaxerror; - break; - case 'e': /* "re" */ - if (buf[2] != 0) - goto defaultcase; - 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]); - - fz_moveto(csi->path, x, y); - fz_lineto(csi->path, x + w, y); - fz_lineto(csi->path, x + w, y + h); - fz_lineto(csi->path, x, y + h); - fz_closepath(csi->path); - break; - case 'g': /* "rg" */ - if (buf[2] != 0) - goto defaultcase; - 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]); - - pdf_setcolorspace(csi, PDF_MFILL, fz_devicergb); - pdf_setcolor(csi, PDF_MFILL, v); - break; - default: - goto defaultcase; - } - break; +static void pdf_run_re(pdf_csi *csi) +{ + float x, y, w, h; - case 's': - switch (buf[1]) - { - case 0: /* "s" */ - if (csi->top < 0) - goto syntaxerror; - pdf_showpath(csi, 1, 0, 1, 0); - break; - case 'c': /* "sc" or "scn" */ - if ((buf[2] != 0) && ((buf[2] != 'n') || (buf[3] != 0))) - goto defaultcase; - what = PDF_MFILL; - goto Lsetcolor; - case 'h': /* "sh" */ - { - fz_obj *dict; - fz_obj *obj; - fz_shade *shd; + x = csi->stack[0]; + y = csi->stack[1]; + w = csi->stack[2]; + h = csi->stack[3]; - if (buf[2] != 0) - goto defaultcase; - if (csi->top < 1) - goto syntaxerror; + fz_moveto(csi->path, x, y); + fz_lineto(csi->path, x + w, y); + fz_lineto(csi->path, x + w, y + h); + fz_lineto(csi->path, x, y + h); + fz_closepath(csi->path); +} - dict = fz_dictgets(rdb, "Shading"); - if (!dict) - return fz_throw("cannot find shading dictionary"); +static void pdf_run_rg(pdf_csi *csi) +{ + pdf_setcolorspace(csi, PDF_MFILL, fz_devicergb); + pdf_setcolor(csi, PDF_MFILL, csi->stack); +} - obj = fz_dictget(dict, csi->stack[csi->top - 1]); - if (!obj) - return fz_throw("cannot find shading resource: %s", fz_toname(csi->stack[csi->top - 1])); +static void pdf_run_ri(pdf_csi *csi) +{ +} - if ((csi->dev->hints & FZ_IGNORESHADE) == 0) - { - error = pdf_loadshading(&shd, csi->xref, obj); - if (error) - return fz_rethrow(error, "cannot load shading (%d %d R)", fz_tonum(obj), fz_togen(obj)); - pdf_showshade(csi, shd); - fz_dropshade(shd); - } - break; - } - default: - goto defaultcase; - } - break; +static void pdf_run_s(pdf_csi *csi) +{ + pdf_showpath(csi, 1, 0, 1, 0); +} - case 'v': /* "v" */ - if (buf[1] != 0) - goto defaultcase; - 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]); - fz_curvetov(csi->path, a, b, c, d); - break; +static fz_error pdf_run_sh(pdf_csi *csi, fz_obj *rdb) +{ + fz_obj *dict; + fz_obj *obj; + fz_shade *shd; + fz_error error; - case 'w': /* "w" */ - if (buf[1] != 0) - goto defaultcase; - if (csi->top < 1) - goto syntaxerror; - gstate->strokestate.linewidth = fz_toreal(csi->stack[0]); - break; + dict = fz_dictgets(rdb, "Shading"); + if (!dict) + return fz_throw("cannot find shading dictionary"); - case 'y': /* "y" */ - if (buf[1] != 0) - goto defaultcase; - 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]); - fz_curvetoy(csi->path, a, b, c, d); - break; + obj = fz_dictgets(dict, csi->name); + if (!obj) + return fz_throw("cannot find shading resource: '%s'", csi->name); - case '\'': /* "'" */ - if (buf[1] != 0) - goto defaultcase; - if (csi->top < 1) - goto syntaxerror; + if ((csi->dev->hints & FZ_IGNORESHADE) == 0) + { + error = pdf_loadshading(&shd, csi->xref, obj); + if (error) + return fz_rethrow(error, "cannot load shading (%d %d R)", fz_tonum(obj), fz_togen(obj)); + pdf_showshade(csi, shd); + fz_dropshade(shd); + } + return fz_okay; +} - m = fz_translate(0, -gstate->leading); - csi->tlm = fz_concat(m, csi->tlm); - csi->tm = csi->tlm; +static void pdf_run_v(pdf_csi *csi) +{ + float a, b, c, d; + a = csi->stack[0]; + b = csi->stack[1]; + c = csi->stack[2]; + d = csi->stack[3]; + fz_curvetov(csi->path, a, b, c, d); +} - pdf_showtext(csi, csi->stack[0]); - break; +static void pdf_run_w(pdf_csi *csi) +{ + pdf_gstate *gstate = csi->gstate + csi->gtop; + gstate->strokestate.linewidth = csi->stack[0]; +} - case '"': /* """ */ - if (buf[1] != 0) - goto defaultcase; - if (csi->top < 3) - goto syntaxerror; +static void pdf_run_y(pdf_csi *csi) +{ + float a, b, c, d; + a = csi->stack[0]; + b = csi->stack[1]; + c = csi->stack[2]; + d = csi->stack[3]; + fz_curvetoy(csi->path, a, b, c, d); +} - gstate->wordspace = fz_toreal(csi->stack[0]); - gstate->charspace = fz_toreal(csi->stack[1]); +static void pdf_run_squote(pdf_csi *csi) +{ + fz_matrix m; + pdf_gstate *gstate = csi->gstate + csi->gtop; + + m = fz_translate(0, -gstate->leading); + csi->tlm = fz_concat(m, csi->tlm); + csi->tm = csi->tlm; + + if (csi->stringlen) + pdf_showstring(csi, csi->string, csi->stringlen); + else + pdf_showtext(csi, csi->obj); +} + +static void pdf_run_dquote(pdf_csi *csi) +{ + fz_matrix m; + pdf_gstate *gstate = csi->gstate + csi->gtop; + + gstate->wordspace = csi->stack[0]; + gstate->charspace = csi->stack[1]; + + m = fz_translate(0, -gstate->leading); + csi->tlm = fz_concat(m, csi->tlm); + csi->tm = csi->tlm; - m = fz_translate(0, -gstate->leading); - csi->tlm = fz_concat(m, csi->tlm); - csi->tm = csi->tlm; + if (csi->stringlen) + pdf_showstring(csi, csi->string, csi->stringlen); + else + pdf_showtext(csi, csi->obj); +} + +#define A(a) (a) +#define B(a,b) (a | b << 8) +#define C(a,b,c) (a | b << 8 | c << 16) - pdf_showtext(csi, csi->stack[2]); +static fz_error +pdf_runkeyword(pdf_csi *csi, fz_obj *rdb, fz_stream *file, char *buf) +{ + fz_error error; + int key; + + key = buf[0]; + if (buf[1]) + { + key |= buf[1] << 8; + if (buf[2]) + { + key |= buf[2] << 16; + if (buf[3]) + key = 0; + } + } + + switch (key) + { + case A('"'): pdf_run_dquote(csi); break; + case A('\''): pdf_run_squote(csi); break; + case A('B'): pdf_run_B(csi); break; + case B('B','*'): pdf_run_Bstar(csi); break; + case C('B','D','C'): pdf_run_BDC(csi); break; + case B('B','I'): + error = pdf_run_BI(csi, rdb, file); + if (error) + return fz_rethrow(error, "cannot draw inline image"); + break; + case C('B','M','C'): pdf_run_BMC(csi); break; + case B('B','T'): pdf_run_BT(csi); break; + case B('B','X'): pdf_run_BX(csi); break; + case B('C','S'): pdf_run_CS(csi, rdb); break; + case B('D','P'): pdf_run_DP(csi); break; + case B('D','o'): + error = pdf_run_Do(csi, rdb); + if (error) + fz_catch(error, "cannot draw xobject/image"); + break; + case C('E','M','C'): pdf_run_EMC(csi); break; + case B('E','T'): pdf_run_ET(csi); break; + case B('E','X'): pdf_run_EX(csi); break; + case A('F'): pdf_run_F(csi); break; + case A('G'): pdf_run_G(csi); break; + case A('J'): pdf_run_J(csi); break; + case A('K'): pdf_run_K(csi); break; + case A('M'): pdf_run_M(csi); break; + case B('M','P'): pdf_run_MP(csi); break; + case A('Q'): pdf_run_Q(csi); break; + case B('R','G'): pdf_run_RG(csi); break; + case A('S'): pdf_run_S(csi); break; + case B('S','C'): pdf_run_SC(csi, rdb); break; + case C('S','C','N'): pdf_run_SC(csi, rdb); break; + case B('T','*'): pdf_run_Tstar(csi); break; + case B('T','D'): pdf_run_TD(csi); break; + case B('T','J'): pdf_run_TJ(csi); break; + case B('T','L'): pdf_run_TL(csi); break; + case B('T','c'): pdf_run_Tc(csi); break; + case B('T','d'): pdf_run_Td(csi); break; + case B('T','f'): + error = pdf_run_Tf(csi, rdb); + if (error) + fz_catch(error, "cannot set font"); + break; + case B('T','j'): pdf_run_Tj(csi); break; + case B('T','m'): pdf_run_Tm(csi); break; + case B('T','r'): pdf_run_Tr(csi); break; + case B('T','s'): pdf_run_Ts(csi); break; + case B('T','w'): pdf_run_Tw(csi); break; + case B('T','z'): pdf_run_Tz(csi); break; + case A('W'): pdf_run_W(csi); break; + case B('W','*'): pdf_run_Wstar(csi); break; + case A('b'): pdf_run_b(csi); break; + case B('b','*'): pdf_run_bstar(csi); break; + case A('c'): pdf_run_c(csi); break; + case B('c','m'): pdf_run_cm(csi); break; + case B('c','s'): pdf_run_cs(csi, rdb); break; + case A('d'): pdf_run_d(csi); break; + case B('d','0'): pdf_run_d0(csi); break; + case B('d','1'): pdf_run_d1(csi); break; + case A('f'): pdf_run_f(csi); break; + case B('f','*'): pdf_run_fstar(csi); break; + case A('g'): pdf_run_g(csi); break; + case B('g','s'): + error = pdf_run_gs(csi, rdb); + if (error) + fz_catch(error, "cannot set graphics state"); + break; + case A('h'): pdf_run_h(csi); break; + case A('i'): pdf_run_i(csi); break; + case A('j'): pdf_run_j(csi); break; + case A('k'): pdf_run_k(csi); break; + case A('l'): pdf_run_l(csi); break; + case A('m'): pdf_run_m(csi); break; + case A('n'): pdf_run_n(csi); break; + case A('q'): pdf_run_q(csi); break; + case B('r','e'): pdf_run_re(csi); break; + case B('r','g'): pdf_run_rg(csi); break; + case B('r','i'): pdf_run_ri(csi); break; + case A('s'): pdf_run_s(csi); break; + case B('s','c'): pdf_run_sc(csi, rdb); break; + case C('s','c','n'): pdf_run_sc(csi, rdb); break; + case B('s','h'): + error = pdf_run_sh(csi, rdb); + if (error) + fz_catch(error, "cannot draw shading"); break; + case A('v'): pdf_run_v(csi); break; + case A('w'): pdf_run_w(csi); break; + case A('y'): pdf_run_y(csi); break; default: -defaultcase: - /* don't fail on unknown keywords if braced by BX/EX */ if (!csi->xbalance) - fz_warn("unknown keyword: %s", buf); + fz_warn("unknown keyword: '%s'", buf); break; } return fz_okay; - -syntaxerror: - return fz_throw("syntax error near '%s' with %d items on the stack", buf, csi->top); } static fz_error @@ -1364,7 +1259,6 @@ pdf_runcsifile(pdf_csi *csi, fz_obj *rdb, fz_stream *file, char *buf, int buflen fz_error error; int tok; int len; - fz_obj *obj; pdf_clearstack(csi); @@ -1377,45 +1271,32 @@ pdf_runcsifile(pdf_csi *csi, fz_obj *rdb, fz_stream *file, char *buf, int buflen if (error) return fz_rethrow(error, "lexical error in content stream"); - if (csi->array) + if (csi->inarray) { if (tok == PDF_TCARRAY) { - csi->stack[csi->top] = csi->array; - csi->array = nil; - csi->top ++; + csi->inarray = 0; } else if (tok == PDF_TINT || tok == PDF_TREAL) { - obj = fz_newreal(atof(buf)); - fz_arraypush(csi->array, obj); - fz_dropobj(obj); + pdf_gstate *gstate = csi->gstate + csi->gtop; + pdf_showspace(csi, -atof(buf) * gstate->size * 0.001f); } else if (tok == PDF_TSTRING) { - obj = fz_newstring(buf, len); - fz_arraypush(csi->array, obj); - fz_dropobj(obj); + pdf_showstring(csi, (unsigned char *)buf, len); } else if (tok == PDF_TKEYWORD) { - /* some producers try to put Tw and Tc commands in the TJ array */ - fz_warn("ignoring keyword '%s' inside array", buf); if (!strcmp(buf, "Tw") || !strcmp(buf, "Tc")) - { - if (fz_arraylen(csi->array) > 0) - fz_arraydrop(csi->array); - } + fz_warn("ignoring keyword '%s' inside array", buf); + else + return fz_throw("syntax error in array"); } else if (tok == PDF_TEOF) - { return fz_okay; - } else - { - pdf_clearstack(csi); - return fz_throw("syntaxerror in array"); - } + return fz_throw("syntax error in array"); } else switch (tok) @@ -1424,85 +1305,60 @@ pdf_runcsifile(pdf_csi *csi, fz_obj *rdb, fz_stream *file, char *buf, int buflen case PDF_TEOF: return fz_okay; - /* optimize text-object array parsing */ case PDF_TOARRAY: - csi->array = fz_newarray(8); + if (!csi->intext) + { + error = pdf_parsearray(&csi->obj, csi->xref, file, buf, buflen); + if (error) + return fz_rethrow(error, "cannot parse array"); + } + else + { + csi->inarray = 1; + } break; case PDF_TODICT: - error = pdf_parsedict(&csi->stack[csi->top], csi->xref, file, buf, buflen); + error = pdf_parsedict(&csi->obj, csi->xref, file, buf, buflen); if (error) return fz_rethrow(error, "cannot parse dictionary"); - csi->top ++; break; case PDF_TNAME: - csi->stack[csi->top] = fz_newname(buf); - csi->top ++; + fz_strlcpy(csi->name, buf, sizeof(csi->name)); break; case PDF_TINT: - csi->stack[csi->top] = fz_newint(atoi(buf)); + csi->stack[csi->top] = atoi(buf); csi->top ++; break; case PDF_TREAL: - csi->stack[csi->top] = fz_newreal(atof(buf)); + csi->stack[csi->top] = atof(buf); csi->top ++; break; case PDF_TSTRING: - csi->stack[csi->top] = fz_newstring(buf, len); - csi->top ++; - break; - - case PDF_TTRUE: - csi->stack[csi->top] = fz_newbool(1); - csi->top ++; - break; - - case PDF_TFALSE: - csi->stack[csi->top] = fz_newbool(0); - csi->top ++; - break; - - case PDF_TNULL: - csi->stack[csi->top] = fz_newnull(); - csi->top ++; - break; - - case PDF_TKEYWORD: - if (!strcmp(buf, "BI")) + if (len <= sizeof(csi->string)) { - int ch; - - error = pdf_parsedict(&obj, csi->xref, file, buf, buflen); - if (error) - return fz_rethrow(error, "cannot parse inline image dictionary"); - - /* read whitespace after ID keyword */ - ch = fz_readbyte(file); - if (ch == '\r') - if (fz_peekbyte(file) == '\n') - fz_readbyte(file); - - error = pdf_runinlineimage(csi, rdb, file, obj); - fz_dropobj(obj); - if (error) - return fz_rethrow(error, "cannot parse inline image"); + memcpy(csi->string, buf, len); + csi->stringlen = len; } else { - error = pdf_runkeyword(csi, rdb, buf); - if (error) - fz_catch(error, "cannot run keyword '%s'", buf); - pdf_clearstack(csi); + csi->obj = fz_newstring(buf, len); } break; - default: + case PDF_TKEYWORD: + error = pdf_runkeyword(csi, rdb, file, buf); + if (error) + return fz_rethrow(error, "cannot run keyword"); pdf_clearstack(csi); - return fz_throw("syntaxerror in content stream"); + break; + + default: + return fz_throw("syntax error in content stream"); } } } @@ -1539,9 +1395,6 @@ pdf_runpage(pdf_xref *xref, pdf_page *page, fz_device *dev, fz_matrix ctm) if (error) return fz_rethrow(error, "cannot parse page content stream"); - if (page->transparency) - dev->endgroup(dev->user); - for (annot = page->annots; annot; annot = annot->next) { flags = fz_toint(fz_dictgets(annot->obj, "F")); @@ -1561,12 +1414,14 @@ pdf_runpage(pdf_xref *xref, pdf_page *page, fz_device *dev, fz_matrix ctm) return fz_rethrow(error, "cannot parse annotation appearance stream"); } + if (page->transparency) + dev->endgroup(dev->user); + return fz_okay; } fz_error -pdf_runglyph(pdf_xref *xref, fz_obj *resources, fz_buffer *contents, - fz_device *dev, fz_matrix ctm) +pdf_runglyph(pdf_xref *xref, fz_obj *resources, fz_buffer *contents, fz_device *dev, fz_matrix ctm) { pdf_csi *csi = pdf_newcsi(xref, dev, ctm); fz_error error = pdf_runcsibuffer(csi, resources, contents); diff --git a/mupdf/pdf_shade.c b/mupdf/pdf_shade.c index 9c4d8d09..1b301724 100644 --- a/mupdf/pdf_shade.c +++ b/mupdf/pdf_shade.c @@ -30,7 +30,7 @@ pdf_growmesh(fz_shade *shade, int amount) static void pdf_addvertex(fz_shade *shade, struct vertex *v) { - int ncomp = shade->usefunction ? 1 : shade->cs->n; + int ncomp = shade->usefunction ? 1 : shade->colorspace->n; int i; pdf_growmesh(shade, 2 + ncomp); shade->mesh[shade->meshlen++] = v->x; @@ -331,8 +331,8 @@ pdf_samplecompositeshadefunction(fz_shade *shade, pdf_function *func, float t0, for (i = 0; i < 256; i++) { t = t0 + (i / 255.0f) * (t1 - t0); - pdf_evalfunction(func, &t, 1, shade->function[i], shade->cs->n); - shade->function[i][shade->cs->n] = 1; + pdf_evalfunction(func, &t, 1, shade->function[i], shade->colorspace->n); + shade->function[i][shade->colorspace->n] = 1; } } @@ -415,7 +415,7 @@ pdf_loadfunctionbasedshading(fz_shade *shade, pdf_xref *xref, fz_obj *dict, pdf_ fv[0] = v[i].x; fv[1] = v[i].y; - pdf_evalfunction(func, fv, 2, v[i].c, shade->cs->n); + pdf_evalfunction(func, fv, 2, v[i].c, shade->colorspace->n); pt.x = v[i].x; pt.y = v[i].y; @@ -627,7 +627,7 @@ pdf_loadtype4shade(fz_shade *shade, pdf_xref *xref, fz_obj *dict, pdf_sampleshadefunction(shade, funcs, func, p.c0[0], p.c1[0]); } else - ncomp = shade->cs->n; + ncomp = shade->colorspace->n; while (!fz_iseofbits(stream)) { @@ -693,7 +693,7 @@ pdf_loadtype5shade(fz_shade *shade, pdf_xref *xref, fz_obj *dict, pdf_sampleshadefunction(shade, funcs, func, p.c0[0], p.c1[0]); } else - ncomp = shade->cs->n; + ncomp = shade->colorspace->n; ref = fz_calloc(p.vprow, sizeof(struct vertex)); buf = fz_calloc(p.vprow, sizeof(struct vertex)); @@ -745,7 +745,7 @@ pdf_loadtype6shade(fz_shade *shade, pdf_xref *xref, fz_obj *dict, pdf_sampleshadefunction(shade, funcs, func, p.c0[0], p.c1[0]); } else - ncomp = shade->cs->n; + ncomp = shade->colorspace->n; hasprevpatch = 0; @@ -865,7 +865,7 @@ pdf_loadtype7shade(fz_shade *shade, pdf_xref *xref, fz_obj *dict, pdf_sampleshadefunction(shade, funcs, func, p.c0[0], p.c1[0]); } else - ncomp = shade->cs->n; + ncomp = shade->colorspace->n; hasprevpatch = 0; @@ -994,7 +994,7 @@ pdf_loadshadingdict(fz_shade **shadep, pdf_xref *xref, fz_obj *dict, fz_matrix t shade->meshcap = 0; shade->mesh = nil; - shade->cs = nil; + shade->colorspace = nil; funcs = 0; @@ -1007,20 +1007,20 @@ pdf_loadshadingdict(fz_shade **shadep, pdf_xref *xref, fz_obj *dict, fz_matrix t fz_dropshade(shade); return fz_throw("shading colorspace is missing"); } - error = pdf_loadcolorspace(&shade->cs, xref, obj); + error = pdf_loadcolorspace(&shade->colorspace, xref, obj); if (error) { fz_dropshade(shade); return fz_rethrow(error, "cannot load colorspace (%d %d R)", fz_tonum(obj), fz_togen(obj)); } - pdf_logshade("colorspace %s\n", shade->cs->name); + pdf_logshade("colorspace %s\n", shade->colorspace->name); obj = fz_dictgets(dict, "Background"); if (obj) { pdf_logshade("background\n"); shade->usebackground = 1; - for (i = 0; i < shade->cs->n; i++) + for (i = 0; i < shade->colorspace->n; i++) shade->background[i] = fz_toreal(fz_arrayget(obj, i)); } @@ -1045,7 +1045,7 @@ pdf_loadshadingdict(fz_shade **shadep, pdf_xref *xref, fz_obj *dict, fz_matrix t else if (fz_isarray(obj)) { funcs = fz_arraylen(obj); - if (funcs != 1 && funcs != shade->cs->n) + if (funcs != 1 && funcs != shade->colorspace->n) { error = fz_throw("incorrect number of shading functions"); goto cleanup; diff --git a/xps/xps_gradient.c b/xps/xps_gradient.c index 3342112c..b23098bd 100644 --- a/xps/xps_gradient.c +++ b/xps/xps_gradient.c @@ -214,7 +214,7 @@ xps_draw_one_radial_gradient(xps_context *ctx, fz_matrix ctm, /* TODO: this (and the stuff in pdf_shade) should move to res_shade.c */ shade = fz_malloc(sizeof(fz_shade)); shade->refs = 1; - shade->cs = fz_devicergb; + shade->colorspace = fz_devicergb; shade->bbox = fz_infiniterect; shade->matrix = fz_identity; shade->usebackground = 0; @@ -255,7 +255,7 @@ xps_draw_one_linear_gradient(xps_context *ctx, fz_matrix ctm, /* TODO: this (and the stuff in pdf_shade) should move to res_shade.c */ shade = fz_malloc(sizeof(fz_shade)); shade->refs = 1; - shade->cs = fz_devicergb; + shade->colorspace = fz_devicergb; shade->bbox = fz_infiniterect; shade->matrix = fz_identity; shade->usebackground = 0; |