summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fitz/dev_draw.c122
-rw-r--r--fitz/dev_list.c28
-rw-r--r--fitz/dev_null.c4
-rw-r--r--fitz/dev_trace.c28
-rw-r--r--fitz/fitz_res.h8
-rw-r--r--fitz/res_path.c13
-rw-r--r--fitz/res_text.c4
-rw-r--r--mupdf/mupdf.h7
-rw-r--r--mupdf/pdf_build.c104
-rw-r--r--mupdf/pdf_interpret.c111
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");