diff options
-rw-r--r-- | fitz/dev_draw.c | 122 | ||||
-rw-r--r-- | fitz/dev_list.c | 28 | ||||
-rw-r--r-- | fitz/dev_null.c | 4 | ||||
-rw-r--r-- | fitz/dev_trace.c | 28 | ||||
-rw-r--r-- | fitz/fitz_res.h | 8 | ||||
-rw-r--r-- | fitz/res_path.c | 13 | ||||
-rw-r--r-- | fitz/res_text.c | 4 | ||||
-rw-r--r-- | mupdf/mupdf.h | 7 | ||||
-rw-r--r-- | mupdf/pdf_build.c | 104 | ||||
-rw-r--r-- | mupdf/pdf_interpret.c | 111 |
10 files changed, 308 insertions, 121 deletions
diff --git a/fitz/dev_draw.c b/fitz/dev_draw.c index 2a312714..5faece16 100644 --- a/fitz/dev_draw.c +++ b/fitz/dev_draw.c @@ -242,6 +242,55 @@ fz_drawclippath(void *user, fz_path *path, fz_matrix ctm) } static void +fz_drawclipstrokepath(void *user, fz_path *path, fz_matrix ctm) +{ + fz_drawdevice *dev = user; + float expansion = fz_matrixexpansion(ctm); + float flatness = 0.3 / expansion; + float linewidth = path->linewidth; + fz_bbox clip, bbox; + fz_pixmap *mask, *dest; + + if (dev->cliptop == MAXCLIP) + { + fz_warn("assert: too many clip masks on stack"); + return; + } + + clip.x0 = dev->dest->x; + clip.y0 = dev->dest->y; + clip.x1 = dev->dest->x + dev->dest->w; + clip.y1 = dev->dest->y + dev->dest->h; + + if (linewidth * expansion < 0.1) + linewidth = 1.0 / expansion; + + fz_resetgel(dev->gel, clip); + if (path->dashlen > 0) + fz_dashpath(dev->gel, path, ctm, flatness, linewidth); + else + fz_strokepath(dev->gel, path, ctm, flatness, linewidth); + fz_sortgel(dev->gel); + + bbox = fz_boundgel(dev->gel); + bbox = fz_intersectbbox(bbox, clip); + + mask = fz_newpixmapwithrect(nil, bbox); + dest = fz_newpixmapwithrect(dev->model, bbox); + + memset(mask->samples, 0, mask->w * mask->h * mask->n); + memset(dest->samples, 0, dest->w * dest->h * dest->n); + + if (!fz_isemptyrect(bbox)) + fz_scanconvert(dev->gel, dev->ael, path->evenodd, bbox, mask, nil, 1); + + dev->clipstack[dev->cliptop].mask = mask; + dev->clipstack[dev->cliptop].dest = dev->dest; + dev->dest = dest; + dev->cliptop++; +} + +static void drawglyph(unsigned char *argb, fz_pixmap *dst, fz_pixmap *src, int xorig, int yorig) { unsigned char *dp, *sp; @@ -342,18 +391,74 @@ static void fz_drawstroketext(void *user, fz_text *text, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha) { - fz_warn("/%s setfont", text->font->name); - fz_debugtext(text, 0); - fz_warn("charpath stroke"); + fz_warn("stroked text not implemented; filling instead"); + fz_drawfilltext(user, text, ctm, colorspace, color, alpha); } static void fz_drawcliptext(void *user, fz_text *text, fz_matrix ctm) { - fz_warn("gsave"); - fz_warn("/%s setfont", text->font->name); - fz_debugtext(text, 0); - fz_warn("charpath clip"); + fz_drawdevice *dev = user; + fz_bbox clip, bbox; + fz_pixmap *mask, *dest; + fz_matrix tm, trm; + fz_pixmap *glyph; + int i, x, y, gid; + + if (dev->cliptop == MAXCLIP) + { + fz_warn("assert: too many clip masks on stack"); + return; + } + + clip.x0 = dev->dest->x; + clip.y0 = dev->dest->y; + clip.x1 = dev->dest->x + dev->dest->w; + clip.y1 = dev->dest->y + dev->dest->h; + + bbox = fz_roundrect(fz_boundtext(text, ctm)); + bbox = fz_intersectbbox(bbox, clip); + + mask = fz_newpixmapwithrect(nil, bbox); + dest = fz_newpixmapwithrect(dev->model, bbox); + + memset(mask->samples, 0, mask->w * mask->h * mask->n); + memset(dest->samples, 0, dest->w * dest->h * dest->n); + + if (!fz_isemptyrect(bbox)) + { + tm = text->trm; + + for (i = 0; i < text->len; i++) + { + gid = text->els[i].gid; + tm.e = text->els[i].x; + tm.f = text->els[i].y; + trm = fz_concat(tm, ctm); + x = floor(trm.e); + y = floor(trm.f); + trm.e = QUANT(trm.e - floor(trm.e), HSUBPIX); + trm.f = QUANT(trm.f - floor(trm.f), VSUBPIX); + + glyph = fz_renderglyph(dev->cache, text->font, gid, trm); + if (glyph) + { + drawglyph(NULL, mask, glyph, x, y); + fz_droppixmap(glyph); + } + } + } + + dev->clipstack[dev->cliptop].mask = mask; + dev->clipstack[dev->cliptop].dest = dev->dest; + dev->dest = dest; + dev->cliptop++; +} + +static void +fz_drawclipstroketext(void *user, fz_text *text, fz_matrix ctm) +{ + fz_drawcliptext(user, text, ctm); } static void @@ -756,10 +861,12 @@ fz_newdrawdevice(fz_glyphcache *cache, fz_pixmap *dest) dev->fillpath = fz_drawfillpath; dev->strokepath = fz_drawstrokepath; dev->clippath = fz_drawclippath; + dev->clipstrokepath = fz_drawclipstrokepath; dev->filltext = fz_drawfilltext; dev->stroketext = fz_drawstroketext; dev->cliptext = fz_drawcliptext; + dev->clipstroketext = fz_drawclipstroketext; dev->ignoretext = fz_drawignoretext; dev->fillimagemask = fz_drawfillimagemask; @@ -771,4 +878,3 @@ fz_newdrawdevice(fz_glyphcache *cache, fz_pixmap *dest) return dev; } - diff --git a/fitz/dev_list.c b/fitz/dev_list.c index 33b2310f..38b333cd 100644 --- a/fitz/dev_list.c +++ b/fitz/dev_list.c @@ -49,11 +49,13 @@ fz_freedisplaynode(fz_displaynode *node) case FZ_CMDFILLPATH: case FZ_CMDSTROKEPATH: case FZ_CMDCLIPPATH: + case FZ_CMDCLIPSTROKEPATH: fz_freepath(node->item.path); break; case FZ_CMDFILLTEXT: case FZ_CMDSTROKETEXT: case FZ_CMDCLIPTEXT: + case FZ_CMDCLIPSTROKETEXT: case FZ_CMDIGNORETEXT: fz_freetext(node->item.text); break; @@ -103,6 +105,15 @@ fz_listclippath(void *user, fz_path *path, fz_matrix ctm) } static void +fz_listclipstrokepath(void *user, fz_path *path, fz_matrix ctm) +{ + fz_displaynode *node; + node = fz_newdisplaynode(FZ_CMDCLIPSTROKEPATH, ctm, nil, nil, 0.0); + node->item.path = fz_clonepath(path); + fz_appenddisplaynode(user, node); +} + +static void fz_listfilltext(void *user, fz_text *text, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha) { @@ -132,6 +143,15 @@ fz_listcliptext(void *user, fz_text *text, fz_matrix ctm) } static void +fz_listclipstroketext(void *user, fz_text *text, fz_matrix ctm) +{ + fz_displaynode *node; + node = fz_newdisplaynode(FZ_CMDCLIPSTROKETEXT, ctm, nil, nil, 0.0); + node->item.text = fz_clonetext(text); + fz_appenddisplaynode(user, node); +} + +static void fz_listignoretext(void *user, fz_text *text, fz_matrix ctm) { fz_displaynode *node; @@ -193,10 +213,12 @@ fz_newlistdevice(fz_displaylist *list) dev->fillpath = fz_listfillpath; dev->strokepath = fz_liststrokepath; dev->clippath = fz_listclippath; + dev->clipstrokepath = fz_listclipstrokepath; dev->filltext = fz_listfilltext; dev->stroketext = fz_liststroketext; dev->cliptext = fz_listcliptext; + dev->clipstroketext = fz_listclipstroketext; dev->ignoretext = fz_listignoretext; dev->fillshade = fz_listfillshade; @@ -250,6 +272,9 @@ fz_executedisplaylist(fz_displaylist *list, fz_device *dev, fz_matrix topctm) case FZ_CMDCLIPPATH: dev->clippath(dev->user, node->item.path, ctm); break; + case FZ_CMDCLIPSTROKEPATH: + dev->clipstrokepath(dev->user, node->item.path, ctm); + break; case FZ_CMDFILLTEXT: dev->filltext(dev->user, node->item.text, ctm, node->colorspace, node->color, node->alpha); @@ -261,6 +286,9 @@ fz_executedisplaylist(fz_displaylist *list, fz_device *dev, fz_matrix topctm) case FZ_CMDCLIPTEXT: dev->cliptext(dev->user, node->item.text, ctm); break; + case FZ_CMDCLIPSTROKETEXT: + dev->clipstroketext(dev->user, node->item.text, ctm); + break; case FZ_CMDIGNORETEXT: dev->ignoretext(dev->user, node->item.text, ctm); break; diff --git a/fitz/dev_null.c b/fitz/dev_null.c index 751166c5..5c57e15d 100644 --- a/fitz/dev_null.c +++ b/fitz/dev_null.c @@ -4,9 +4,11 @@ static void fz_nullfreeuser(void *user) {} static void fz_nullfillpath(void *user, fz_path *path, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha) {} static void fz_nullstrokepath(void *user, fz_path *path, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha) {} static void fz_nullclippath(void *user, fz_path *path, fz_matrix ctm) {} +static void fz_nullclipstrokepath(void *user, fz_path *path, fz_matrix ctm) {} static void fz_nullfilltext(void *user, fz_text *text, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha) {} static void fz_nullstroketext(void *user, fz_text *text, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha) {} static void fz_nullcliptext(void *user, fz_text *text, fz_matrix ctm) {} +static void fz_nullclipstroketext(void *user, fz_text *text, fz_matrix ctm) {} static void fz_nullignoretext(void *user, fz_text *text, fz_matrix ctm) {} static void fz_nullpopclip(void *user) {} static void fz_nullfillshade(void *user, fz_shade *shade, fz_matrix ctm) {} @@ -26,10 +28,12 @@ fz_newdevice(void *user) dev->fillpath = fz_nullfillpath; dev->strokepath = fz_nullstrokepath; dev->clippath = fz_nullclippath; + dev->clipstrokepath = fz_nullclipstrokepath; dev->filltext = fz_nullfilltext; dev->stroketext = fz_nullstroketext; dev->cliptext = fz_nullcliptext; + dev->clipstroketext = fz_nullclipstroketext; dev->ignoretext = fz_nullignoretext; dev->fillshade = fz_nullfillshade; diff --git a/fitz/dev_trace.c b/fitz/dev_trace.c index 2a477709..751b94bb 100644 --- a/fitz/dev_trace.c +++ b/fitz/dev_trace.c @@ -119,6 +119,21 @@ fz_traceclippath(void *user, fz_path *path, fz_matrix ctm) } static void +fz_traceclipstrokepath(void *user, fz_path *path, fz_matrix ctm) +{ + printf("<gsave>\n"); + printf("<clipstrokepath "); + if (path->evenodd) + printf("winding=\"eofill\" "); + else + printf("winding=\"nonzero\" "); + fz_tracematrix(ctm); + printf(">\n"); + fz_tracepath(path, 0); + printf("</clipstrokepath>\n"); +} + +static void fz_tracefilltext(void *user, fz_text *text, fz_matrix ctm, fz_colorspace *colorspace, float *color, float alpha) { @@ -154,6 +169,17 @@ fz_tracecliptext(void *user, fz_text *text, fz_matrix ctm) } static void +fz_traceclipstroketext(void *user, fz_text *text, fz_matrix ctm) +{ + printf("<gsave>\n"); + printf("<clipstroketext font=\"%s\" ", text->font->name); + fz_tracematrix(fz_concat(ctm, text->trm)); + printf(">\n"); + fz_debugtext(text, 0); + printf("</clipstroketext>\n"); +} + +static void fz_traceignoretext(void *user, fz_text *text, fz_matrix ctm) { printf("<ignoretext font=\"%s\" ", text->font->name); @@ -211,10 +237,12 @@ fz_device *fz_newtracedevice(void) dev->fillpath = fz_tracefillpath; dev->strokepath = fz_tracestrokepath; dev->clippath = fz_traceclippath; + dev->clipstrokepath = fz_traceclipstrokepath; dev->filltext = fz_tracefilltext; dev->stroketext = fz_tracestroketext; dev->cliptext = fz_tracecliptext; + dev->clipstroketext = fz_traceclipstroketext; dev->ignoretext = fz_traceignoretext; dev->fillshade = fz_tracefillshade; diff --git a/fitz/fitz_res.h b/fitz/fitz_res.h index ae74f58f..f91885b3 100644 --- a/fitz/fitz_res.h +++ b/fitz/fitz_res.h @@ -78,10 +78,12 @@ struct fz_device_s void (*fillpath)(void *, fz_path *, fz_matrix, fz_colorspace *, float *color, float alpha); void (*strokepath)(void *, fz_path *, fz_matrix, fz_colorspace *, float *color, float alpha); void (*clippath)(void *, fz_path *, fz_matrix); + void (*clipstrokepath)(void *, fz_path *, fz_matrix); void (*filltext)(void *, fz_text *, fz_matrix, fz_colorspace *, float *color, float alpha); void (*stroketext)(void *, fz_text *, fz_matrix, fz_colorspace *, float *color, float alpha); void (*cliptext)(void *, fz_text *, fz_matrix); + void (*clipstroketext)(void *, fz_text *, fz_matrix); void (*ignoretext)(void *, fz_text *, fz_matrix); void (*fillshade)(void *, fz_shade *shd, fz_matrix ctm); @@ -131,9 +133,11 @@ typedef enum fz_displaycommand_e FZ_CMDFILLPATH, FZ_CMDSTROKEPATH, FZ_CMDCLIPPATH, + FZ_CMDCLIPSTROKEPATH, FZ_CMDFILLTEXT, FZ_CMDSTROKETEXT, FZ_CMDCLIPTEXT, + FZ_CMDCLIPSTROKETEXT, FZ_CMDIGNORETEXT, FZ_CMDFILLSHADE, FZ_CMDFILLIMAGE, @@ -216,7 +220,6 @@ void fz_curveto(fz_path*, float, float, float, float, float, float); void fz_curvetov(fz_path*, float, float, float, float); void fz_curvetoy(fz_path*, float, float, float, float); void fz_closepath(fz_path*); -void fz_resetpath(fz_path *path); void fz_freepath(fz_path *path); fz_path *fz_clonepath(fz_path *old); @@ -256,10 +259,9 @@ struct fz_text_s fz_text * fz_newtext(fz_font *face); void fz_addtext(fz_text *text, int gid, int ucs, float x, float y); void fz_endtext(fz_text *text); -void fz_resettext(fz_text *text); void fz_freetext(fz_text *text); void fz_debugtext(fz_text*, int indent); - +fz_rect fz_boundtext(fz_text *text, fz_matrix ctm); fz_text *fz_clonetext(fz_text *old); /* diff --git a/fitz/res_path.c b/fitz/res_path.c index dcf026c0..2817c721 100644 --- a/fitz/res_path.c +++ b/fitz/res_path.c @@ -43,19 +43,6 @@ fz_freepath(fz_path *path) fz_free(path); } -void -fz_resetpath(fz_path *path) -{ - path->dashlen = 0; - path->dashphase = 0; - path->evenodd = 0; - path->linecap = 0; - path->linejoin = 0; - path->linewidth = 1.0; - path->miterlimit = 10.0; - path->len = 0; -} - static void growpath(fz_path *path, int n) { diff --git a/fitz/res_text.c b/fitz/res_text.c index 99fb37a5..cdb4c066 100644 --- a/fitz/res_text.c +++ b/fitz/res_text.c @@ -89,7 +89,7 @@ fz_boundtext(fz_text *text, fz_matrix ctm) } static void -growtext(fz_text *text, int n) +fz_growtext(fz_text *text, int n) { if (text->len + n < text->cap) return; @@ -101,7 +101,7 @@ growtext(fz_text *text, int n) void fz_addtext(fz_text *text, int gid, int ucs, float x, float y) { - growtext(text, 1); + fz_growtext(text, 1); text->els[text->len].ucs = ucs; text->els[text->len].gid = gid; text->els[text->len].x = x; diff --git a/mupdf/mupdf.h b/mupdf/mupdf.h index 9b3aee70..4ae17c2b 100644 --- a/mupdf/mupdf.h +++ b/mupdf/mupdf.h @@ -638,6 +638,7 @@ struct pdf_gstate_s struct pdf_csi_s { fz_device *dev; + pdf_xref *xref; fz_obj *stack[32]; int top; @@ -667,16 +668,16 @@ void pdf_setcolorspace(pdf_csi *csi, int what, fz_colorspace *cs); 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*, pdf_xref *xref, int close, int fill, int stroke, int evenodd); +void pdf_showpath(pdf_csi*, int close, int fill, int stroke, int evenodd); void pdf_showtext(pdf_csi*, fz_obj *text); void pdf_flushtext(pdf_csi*); -void pdf_showimage(pdf_csi*, pdf_xref *xref, pdf_image *img); +void pdf_showimage(pdf_csi*, pdf_image *img); void pdf_showshade(pdf_csi*, fz_shade *shd); /* interpret.c */ void pdf_gsave(pdf_csi *csi); void pdf_grestore(pdf_csi *csi); -fz_error pdf_runcsibuffer(pdf_csi *csi, pdf_xref *xref, fz_obj *rdb, fz_buffer *contents); +fz_error pdf_runcsibuffer(pdf_csi *csi, fz_obj *rdb, fz_buffer *contents); fz_error pdf_runcontentstream(fz_device *dev, fz_matrix ctm, pdf_xref *xref, fz_obj *resources, fz_buffer *contents); pdf_material * pdf_keepmaterial(pdf_material *mat); diff --git a/mupdf/pdf_build.c b/mupdf/pdf_build.c index 59b6c6af..ea589f64 100644 --- a/mupdf/pdf_build.c +++ b/mupdf/pdf_build.c @@ -183,7 +183,7 @@ pdf_setshade(pdf_csi *csi, int what, fz_shade *shade) } void -pdf_showpattern(pdf_csi *csi, pdf_pattern *pat, pdf_xref *xref, fz_rect bbox, int what) +pdf_showpattern(pdf_csi *csi, pdf_pattern *pat, fz_rect bbox, int what) { pdf_gstate *gstate; fz_matrix ptm, invptm; @@ -238,7 +238,7 @@ pdf_showpattern(pdf_csi *csi, pdf_pattern *pat, pdf_xref *xref, fz_rect bbox, in { gstate->ctm = fz_concat(fz_translate(x * pat->xstep, y * pat->ystep), ptm); csi->topctm = gstate->ctm; - error = pdf_runcsibuffer(csi, xref, pat->resources, pat->contents); + error = pdf_runcsibuffer(csi, pat->resources, pat->contents); if (error) fz_catch(error, "cannot render pattern tile"); while (oldtop < csi->gtop) @@ -259,7 +259,7 @@ pdf_showshade(pdf_csi *csi, fz_shade *shd) } void -pdf_showimage(pdf_csi *csi, pdf_xref *xref, pdf_image *image) +pdf_showimage(pdf_csi *csi, pdf_image *image) { pdf_gstate *gstate = csi->gstate + csi->gtop; fz_pixmap *tile = fz_newpixmap(image->cs, 0, 0, image->w, image->h); @@ -302,7 +302,7 @@ pdf_showimage(pdf_csi *csi, pdf_xref *xref, pdf_image *image) bbox.y1 = 1; bbox = fz_transformrect(gstate->ctm, bbox); csi->dev->clipimagemask(csi->dev->user, tile, gstate->ctm); - pdf_showpattern(csi, gstate->fill.pattern, xref, bbox, PDF_MFILL); + pdf_showpattern(csi, gstate->fill.pattern, bbox, PDF_MFILL); csi->dev->popclip(csi->dev->user); break; case PDF_MSHADE: @@ -324,29 +324,33 @@ pdf_showimage(pdf_csi *csi, pdf_xref *xref, pdf_image *image) } void -pdf_showpath(pdf_csi *csi, pdf_xref *xref, int doclose, int dofill, int dostroke, int evenodd) +pdf_showpath(pdf_csi *csi, int doclose, int dofill, int dostroke, int evenodd) { pdf_gstate *gstate = csi->gstate + csi->gtop; fz_rect bbox; + fz_path *path; int i; + path = csi->path; + csi->path = fz_newpath(); + if (doclose) - fz_closepath(csi->path); - - csi->path->evenodd = evenodd; - csi->path->linewidth = gstate->linewidth; - csi->path->linecap = gstate->linecap; - csi->path->linejoin = gstate->linejoin; - csi->path->miterlimit = gstate->miterlimit; - csi->path->dashlen = gstate->dashlen; - csi->path->dashphase = gstate->dashphase; - for (i = 0; i < csi->path->dashlen; i++) - csi->path->dashlist[i] = gstate->dashlist[i]; + fz_closepath(path); + + path->evenodd = evenodd; + path->linewidth = gstate->linewidth; + path->linecap = gstate->linecap; + path->linejoin = gstate->linejoin; + path->miterlimit = gstate->miterlimit; + path->dashlen = gstate->dashlen; + path->dashphase = gstate->dashphase; + for (i = 0; i < path->dashlen; i++) + path->dashlist[i] = gstate->dashlist[i]; if (csi->clip) { gstate->clipdepth++; - csi->dev->clippath(csi->dev->user, csi->path, gstate->ctm); + csi->dev->clippath(csi->dev->user, path, gstate->ctm); csi->clip = 0; } @@ -359,17 +363,17 @@ pdf_showpath(pdf_csi *csi, pdf_xref *xref, int doclose, int dofill, int dostroke case PDF_MCOLOR: case PDF_MINDEXED: case PDF_MLAB: - csi->dev->fillpath(csi->dev->user, csi->path, gstate->ctm, + csi->dev->fillpath(csi->dev->user, path, gstate->ctm, gstate->fill.cs, gstate->fill.v, gstate->fill.alpha); break; case PDF_MPATTERN: - bbox = fz_boundpath(csi->path, gstate->ctm, 0); - csi->dev->clippath(csi->dev->user, csi->path, gstate->ctm); - pdf_showpattern(csi, gstate->fill.pattern, xref, bbox, PDF_MFILL); + bbox = fz_boundpath(path, gstate->ctm, 0); + csi->dev->clippath(csi->dev->user, path, gstate->ctm); + pdf_showpattern(csi, gstate->fill.pattern, bbox, PDF_MFILL); csi->dev->popclip(csi->dev->user); break; case PDF_MSHADE: - csi->dev->clippath(csi->dev->user, csi->path, gstate->ctm); + csi->dev->clippath(csi->dev->user, path, gstate->ctm); csi->dev->fillshade(csi->dev->user, gstate->fill.shade, gstate->ctm); csi->dev->popclip(csi->dev->user); break; @@ -385,19 +389,24 @@ pdf_showpath(pdf_csi *csi, pdf_xref *xref, int doclose, int dofill, int dostroke case PDF_MCOLOR: case PDF_MINDEXED: case PDF_MLAB: - csi->dev->strokepath(csi->dev->user, csi->path, gstate->ctm, + csi->dev->strokepath(csi->dev->user, path, gstate->ctm, gstate->stroke.cs, gstate->stroke.v, gstate->stroke.alpha); break; case PDF_MPATTERN: - fz_warn("pattern strokes not supported yet"); + bbox = fz_boundpath(path, gstate->ctm, 1); + csi->dev->clipstrokepath(csi->dev->user, path, gstate->ctm); + pdf_showpattern(csi, gstate->stroke.pattern, bbox, PDF_MFILL); + csi->dev->popclip(csi->dev->user); break; case PDF_MSHADE: - fz_warn("shading strokes not supported yet"); + csi->dev->clipstrokepath(csi->dev->user, path, gstate->ctm); + csi->dev->fillshade(csi->dev->user, gstate->stroke.shade, gstate->ctm); + csi->dev->popclip(csi->dev->user); break; } } - fz_resetpath(csi->path); + fz_freepath(path); } /* @@ -408,13 +417,17 @@ void pdf_flushtext(pdf_csi *csi) { pdf_gstate *gstate = csi->gstate + csi->gtop; + fz_text *text; int dofill = 0; int dostroke = 0; int doclip = 0; int doinvisible = 0; + fz_rect bbox; if (!csi->text) return; + text = csi->text; + csi->text = nil; switch (csi->textmode) { @@ -449,13 +462,21 @@ pdf_flushtext(pdf_csi *csi) break; } + /* FIXME -- stroked text is not implemented yet */ + if (dostroke) + { + fz_warn("stroked text not supported yet; filling instead"); + dostroke = 0; + dofill = 1; + } + if (doinvisible) - csi->dev->ignoretext(csi->dev->user, csi->text, gstate->ctm); + csi->dev->ignoretext(csi->dev->user, text, gstate->ctm); if (doclip) { gstate->clipdepth++; - csi->dev->cliptext(csi->dev->user, csi->text, gstate->ctm); + csi->dev->cliptext(csi->dev->user, text, gstate->ctm); } if (dofill) @@ -467,41 +488,50 @@ pdf_flushtext(pdf_csi *csi) case PDF_MCOLOR: case PDF_MINDEXED: case PDF_MLAB: - csi->dev->filltext(csi->dev->user, csi->text, gstate->ctm, + csi->dev->filltext(csi->dev->user, text, gstate->ctm, gstate->fill.cs, gstate->fill.v, gstate->fill.alpha); break; case PDF_MPATTERN: - fz_warn("pattern filled text not supported yet"); + bbox = fz_boundtext(text, gstate->ctm); + csi->dev->cliptext(csi->dev->user, text, gstate->ctm); + pdf_showpattern(csi, gstate->fill.pattern, bbox, PDF_MFILL); + csi->dev->popclip(csi->dev->user); break; case PDF_MSHADE: - fz_warn("shading filled text not supported yet"); + csi->dev->cliptext(csi->dev->user, text, gstate->ctm); + csi->dev->fillshade(csi->dev->user, gstate->fill.shade, gstate->ctm); + csi->dev->popclip(csi->dev->user); break; } } if (dostroke) { - switch (gstate->fill.kind) + switch (gstate->stroke.kind) { case PDF_MNONE: break; case PDF_MCOLOR: case PDF_MINDEXED: case PDF_MLAB: - csi->dev->stroketext(csi->dev->user, csi->text, gstate->ctm, + csi->dev->stroketext(csi->dev->user, text, gstate->ctm, gstate->stroke.cs, gstate->stroke.v, gstate->stroke.alpha); break; case PDF_MPATTERN: - fz_warn("pattern stroked text not supported yet"); + bbox = fz_boundtext(text, gstate->ctm); + csi->dev->clipstroketext(csi->dev->user, text, gstate->ctm); + pdf_showpattern(csi, gstate->stroke.pattern, bbox, PDF_MFILL); + csi->dev->popclip(csi->dev->user); break; case PDF_MSHADE: - fz_warn("shading stroked text not supported yet"); + csi->dev->clipstroketext(csi->dev->user, text, gstate->ctm); + csi->dev->fillshade(csi->dev->user, gstate->stroke.shade, gstate->ctm); + csi->dev->popclip(csi->dev->user); break; } } - fz_freetext(csi->text); - csi->text = nil; + fz_freetext(text); } static void diff --git a/mupdf/pdf_interpret.c b/mupdf/pdf_interpret.c index f3b57fd4..719c2b07 100644 --- a/mupdf/pdf_interpret.c +++ b/mupdf/pdf_interpret.c @@ -2,38 +2,36 @@ #include "mupdf.h" static pdf_csi * -pdf_newcsi(fz_device *dev, fz_matrix ctm) +pdf_newcsi(fz_device *dev, pdf_xref *xref, fz_matrix ctm) { pdf_csi *csi; csi = fz_malloc(sizeof(pdf_csi)); + csi->dev = dev; + csi->xref = xref; - pdf_initgstate(&csi->gstate[0], ctm); - csi->gtop = 0; csi->top = 0; csi->xbalance = 0; csi->array = nil; csi->path = fz_newpath(); - csi->text = nil; - csi->clip = 0; csi->clipevenodd = 0; - csi->textmode = 0; csi->text = nil; - csi->tm = fz_identity(); csi->tlm = fz_identity(); + csi->tm = fz_identity(); + csi->textmode = 0; csi->topctm = ctm; - - csi->dev = dev; + pdf_initgstate(&csi->gstate[0], ctm); + csi->gtop = 0; return csi; } static void -clearstack(pdf_csi *csi) +pdf_clearstack(pdf_csi *csi) { int i; for (i = 0; i < csi->top; i++) @@ -123,16 +121,19 @@ pdf_freecsi(pdf_csi *csi) while (csi->gtop) pdf_grestore(csi); - pdf_dropmaterial(&csi->gstate[csi->gtop].fill); - pdf_dropmaterial(&csi->gstate[csi->gtop].stroke); - if (csi->gstate[csi->gtop].font) - pdf_dropfont(csi->gstate[csi->gtop].font); + pdf_dropmaterial(&csi->gstate[0].fill); + pdf_dropmaterial(&csi->gstate[0].stroke); + if (csi->gstate[0].font) + pdf_dropfont(csi->gstate[0].font); + + while (csi->gstate[0].clipdepth--) + csi->dev->popclip(csi->dev->user); if (csi->path) fz_freepath(csi->path); if (csi->text) fz_freetext(csi->text); if (csi->array) fz_dropobj(csi->array); - clearstack(csi); + pdf_clearstack(csi); fz_free(csi); } @@ -143,7 +144,7 @@ pdf_freecsi(pdf_csi *csi) */ static fz_error -pdf_runxobject(pdf_csi *csi, pdf_xref *xref, fz_obj *resources, pdf_xobject *xobj) +pdf_runxobject(pdf_csi *csi, fz_obj *resources, pdf_xobject *xobj) { fz_error error; pdf_gstate *gstate; @@ -184,7 +185,7 @@ pdf_runxobject(pdf_csi *csi, pdf_xref *xref, fz_obj *resources, pdf_xobject *xob fz_lineto(csi->path, xobj->bbox.x0, xobj->bbox.y1); fz_closepath(csi->path); csi->clip = 1; - pdf_showpath(csi, xref, 0, 0, 0, 0); + pdf_showpath(csi, 0, 0, 0, 0); /* run contents */ @@ -194,7 +195,7 @@ pdf_runxobject(pdf_csi *csi, pdf_xref *xref, fz_obj *resources, pdf_xobject *xob if (xobj->resources) resources = xobj->resources; - error = pdf_runcsibuffer(csi, xref, resources, xobj->contents); + error = pdf_runcsibuffer(csi, resources, xobj->contents); if (error) return fz_rethrow(error, "cannot interpret XObject stream"); @@ -213,7 +214,7 @@ pdf_runxobject(pdf_csi *csi, pdf_xref *xref, fz_obj *resources, pdf_xobject *xob */ static fz_error -pdf_runinlineimage(pdf_csi *csi, pdf_xref *xref, fz_obj *rdb, fz_stream *file, fz_obj *dict) +pdf_runinlineimage(pdf_csi *csi, fz_obj *rdb, fz_stream *file, fz_obj *dict) { fz_error error; pdf_image *img; @@ -221,7 +222,7 @@ pdf_runinlineimage(pdf_csi *csi, pdf_xref *xref, fz_obj *rdb, fz_stream *file, f pdf_token_e tok; int len; - error = pdf_loadinlineimage(&img, xref, rdb, dict, file); + error = pdf_loadinlineimage(&img, csi->xref, rdb, dict, file); if (error) return fz_rethrow(error, "cannot load inline image"); @@ -238,7 +239,7 @@ pdf_runinlineimage(pdf_csi *csi, pdf_xref *xref, fz_obj *rdb, fz_stream *file, f return fz_throw("syntax error after inline image"); } - pdf_showimage(csi, xref, img); + pdf_showimage(csi, img); pdf_dropimage(img); return fz_okay; @@ -398,7 +399,7 @@ pdf_runextgstate(pdf_gstate *gstate, pdf_xref *xref, fz_obj *rdb, fz_obj *extgst */ static fz_error -pdf_runkeyword(pdf_csi *csi, pdf_xref *xref, fz_obj *rdb, char *buf) +pdf_runkeyword(pdf_csi *csi, fz_obj *rdb, char *buf) { pdf_gstate *gstate = csi->gstate + csi->gtop; fz_error error; @@ -494,7 +495,7 @@ pdf_runkeyword(pdf_csi *csi, pdf_xref *xref, fz_obj *rdb, char *buf) if (!obj) return fz_throw("cannot find extgstate resource /%s", fz_toname(csi->stack[0])); - error = pdf_runextgstate(gstate, xref, rdb, obj); + error = pdf_runextgstate(gstate, csi->xref, rdb, obj); if (error) return fz_rethrow(error, "cannot set ExtGState"); } @@ -520,21 +521,21 @@ pdf_runkeyword(pdf_csi *csi, pdf_xref *xref, fz_obj *rdb, char *buf) { if (csi->top != 0) goto syntaxerror; - pdf_showpath(csi, xref, 0, 1, 0, 1); + pdf_showpath(csi, 0, 1, 0, 1); } else if (!strcmp(buf, "B*")) { if (csi->top != 0) goto syntaxerror; - pdf_showpath(csi, xref, 0, 1, 1, 1); + pdf_showpath(csi, 0, 1, 1, 1); } else if (!strcmp(buf, "b*")) { if (csi->top != 0) goto syntaxerror; - pdf_showpath(csi, xref, 1, 1, 1, 1); + pdf_showpath(csi, 1, 1, 1, 1); } else if (!strcmp(buf, "W*")) @@ -589,7 +590,7 @@ Lsetcolorspace: if (!obj) return fz_throw("cannot find colorspace resource /%s", fz_toname(csi->stack[0])); - error = pdf_loadcolorspace(&cs, xref, obj); + error = pdf_loadcolorspace(&cs, csi->xref, obj); if (error) return fz_rethrow(error, "cannot load colorspace"); } @@ -662,7 +663,7 @@ Lsetcolor: if (fz_toint(patterntype) == 1) { pdf_pattern *pat; - error = pdf_loadpattern(&pat, xref, obj); + error = pdf_loadpattern(&pat, csi->xref, obj); if (error) return fz_rethrow(error, "cannot load pattern"); pdf_setpattern(csi, what, pat, csi->top == 1 ? nil : v); @@ -672,7 +673,7 @@ Lsetcolor: else if (fz_toint(patterntype) == 2) { fz_shade *shd; - error = pdf_loadshade(&shd, xref, obj); + error = pdf_loadshade(&shd, csi->xref, obj); if (error) return fz_rethrow(error, "cannot load shade"); pdf_setshade(csi, what, shd); @@ -783,7 +784,7 @@ Lsetcolor: gstate->font = nil; } - error = pdf_loadfont(&gstate->font, xref, rdb, obj); + error = pdf_loadfont(&gstate->font, csi->xref, rdb, obj); if (error) return fz_rethrow(error, "cannot load font"); @@ -893,13 +894,11 @@ Lsetcolor: if (!subtype) return fz_throw("no XObject subtype specified"); - clearstack(csi); - if (!strcmp(fz_toname(subtype), "Form")) { pdf_xobject *xobj; - error = pdf_loadxobject(&xobj, xref, obj); + error = pdf_loadxobject(&xobj, csi->xref, obj); if (error) return fz_rethrow(error, "cannot load xobject"); @@ -907,7 +906,7 @@ Lsetcolor: if (!xobj->resources) xobj->resources = fz_keepobj(rdb); - error = pdf_runxobject(csi, xref, rdb, xobj); + error = pdf_runxobject(csi, rdb, xobj); if (error) return fz_rethrow(error, "cannot draw xobject"); @@ -917,10 +916,10 @@ Lsetcolor: else if (!strcmp(fz_toname(subtype), "Image")) { pdf_image *img; - error = pdf_loadimage(&img, xref, obj); + error = pdf_loadimage(&img, csi->xref, obj); if (error) return fz_rethrow(error, "cannot load image"); - pdf_showimage(csi, xref, img); + pdf_showimage(csi, img); pdf_dropimage(img); } @@ -947,7 +946,7 @@ Lsetcolor: if (!obj) return fz_throw("cannot find shade resource: %s", fz_toname(csi->stack[csi->top - 1])); - error = pdf_loadshade(&shd, xref, obj); + error = pdf_loadshade(&shd, csi->xref, obj); if (error) return fz_rethrow(error, "cannot load shade"); pdf_showshade(csi, shd); @@ -1089,38 +1088,38 @@ Lsetcolor: case 'S': if (csi->top != 0) goto syntaxerror; - pdf_showpath(csi, xref, 0, 0, 1, 0); + pdf_showpath(csi, 0, 0, 1, 0); break; case 's': if (csi->top != 0) goto syntaxerror; - pdf_showpath(csi, xref, 1, 0, 1, 0); + pdf_showpath(csi, 1, 0, 1, 0); break; case 'F': case 'f': if (csi->top != 0) goto syntaxerror; - pdf_showpath(csi, xref, 0, 1, 0, 0); + pdf_showpath(csi, 0, 1, 0, 0); break; case 'B': if (csi->top != 0) goto syntaxerror; - pdf_showpath(csi, xref, 0, 1, 1, 0); + pdf_showpath(csi, 0, 1, 1, 0); break; case 'b': if (csi->top != 0) goto syntaxerror; - pdf_showpath(csi, xref, 1, 1, 1, 0); + pdf_showpath(csi, 1, 1, 1, 0); break; case 'n': if (csi->top != 0) goto syntaxerror; - pdf_showpath(csi, xref, 0, 0, 0, csi->clipevenodd); + pdf_showpath(csi, 0, 0, 0, csi->clipevenodd); break; case 'W': @@ -1212,13 +1211,15 @@ syntaxerror: } static fz_error -pdf_runcsifile(pdf_csi *csi, pdf_xref *xref, fz_obj *rdb, fz_stream *file, char *buf, int buflen) +pdf_runcsifile(pdf_csi *csi, fz_obj *rdb, fz_stream *file, char *buf, int buflen) { fz_error error; pdf_token_e tok; int len; fz_obj *obj; + pdf_clearstack(csi); + while (1) { if (csi->top == 31) @@ -1254,7 +1255,7 @@ pdf_runcsifile(pdf_csi *csi, pdf_xref *xref, fz_obj *rdb, fz_stream *file, char } else { - clearstack(csi); + pdf_clearstack(csi); return fz_throw("syntaxerror in array"); } } @@ -1270,7 +1271,7 @@ pdf_runcsifile(pdf_csi *csi, pdf_xref *xref, fz_obj *rdb, fz_stream *file, char break; case PDF_TODICT: - error = pdf_parsedict(&csi->stack[csi->top], xref, file, buf, buflen); + error = pdf_parsedict(&csi->stack[csi->top], csi->xref, file, buf, buflen); if (error) return fz_rethrow(error, "cannot parse dictionary"); csi->top ++; @@ -1317,7 +1318,7 @@ pdf_runcsifile(pdf_csi *csi, pdf_xref *xref, fz_obj *rdb, fz_stream *file, char fz_obj *obj; int ch; - error = pdf_parsedict(&obj, xref, file, buf, buflen); + error = pdf_parsedict(&obj, csi->xref, file, buf, buflen); if (error) return fz_rethrow(error, "cannot parse inline image dictionary"); @@ -1330,36 +1331,36 @@ pdf_runcsifile(pdf_csi *csi, pdf_xref *xref, fz_obj *rdb, fz_stream *file, char if (error) return fz_rethrow(error, "cannot parse whitespace before inline image"); - error = pdf_runinlineimage(csi, xref, rdb, file, obj); + error = pdf_runinlineimage(csi, rdb, file, obj); fz_dropobj(obj); if (error) return fz_rethrow(error, "cannot parse inline image"); } else { - error = pdf_runkeyword(csi, xref, rdb, buf); + error = pdf_runkeyword(csi, rdb, buf); if (error) return fz_rethrow(error, "cannot run '%s'", buf); - clearstack(csi); + pdf_clearstack(csi); } break; default: - clearstack(csi); + pdf_clearstack(csi); return fz_throw("syntaxerror in content stream"); } } } fz_error -pdf_runcsibuffer(pdf_csi *csi, pdf_xref *xref, fz_obj *rdb, fz_buffer *contents) +pdf_runcsibuffer(pdf_csi *csi, fz_obj *rdb, fz_buffer *contents) { fz_stream *file; fz_error error; contents->rp = contents->bp; file = fz_openrbuffer(contents); - error = pdf_runcsifile(csi, xref, rdb, file, xref->scratch, sizeof xref->scratch); + error = pdf_runcsifile(csi, rdb, file, csi->xref->scratch, sizeof csi->xref->scratch); fz_dropstream(file); contents->rp = contents->bp; if (error) @@ -1371,8 +1372,8 @@ fz_error pdf_runcontentstream(fz_device *dev, fz_matrix ctm, pdf_xref *xref, fz_obj *resources, fz_buffer *contents) { - pdf_csi *csi = pdf_newcsi(dev, ctm); - fz_error error = pdf_runcsibuffer(csi, xref, resources, contents); + pdf_csi *csi = pdf_newcsi(dev, xref, ctm); + fz_error error = pdf_runcsibuffer(csi, resources, contents); pdf_freecsi(csi); if (error) return fz_rethrow(error, "cannot parse content stream"); |