summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--draw/porterduff.c30
-rw-r--r--fitz/dev_draw.c82
-rw-r--r--fitz/dev_list.c55
-rw-r--r--fitz/dev_null.c5
-rw-r--r--fitz/dev_trace.c20
-rw-r--r--fitz/fitz.h6
-rw-r--r--mupdf/pdf_build.c56
-rw-r--r--xps/xps_tile.c13
8 files changed, 246 insertions, 21 deletions
diff --git a/draw/porterduff.c b/draw/porterduff.c
index b8130ab6..69df467a 100644
--- a/draw/porterduff.c
+++ b/draw/porterduff.c
@@ -347,6 +347,36 @@ fz_paintspan(byte * restrict dp, byte * restrict sp, int n, int w, int alpha)
*/
void
+fz_paintpixmapbbox(fz_pixmap *dst, fz_pixmap *src, int alpha, fz_bbox bbox)
+{
+ unsigned char *sp, *dp;
+ int x, y, w, h, n;
+
+ assert(dst->n == src->n);
+
+ bbox = fz_intersectbbox(bbox, fz_boundpixmap(dst));
+ bbox = fz_intersectbbox(bbox, fz_boundpixmap(src));
+
+ x = bbox.x0;
+ y = bbox.y0;
+ w = bbox.x1 - bbox.x0;
+ h = bbox.y1 - bbox.y0;
+ if ((w | h) == 0)
+ return;
+
+ n = src->n;
+ sp = src->samples + ((y - src->y) * src->w + (x - src->x)) * src->n;
+ dp = dst->samples + ((y - dst->y) * dst->w + (x - dst->x)) * dst->n;
+
+ while (h--)
+ {
+ fz_paintspan(dp, sp, n, w, alpha);
+ sp += src->w * n;
+ dp += dst->w * n;
+ }
+}
+
+void
fz_paintpixmap(fz_pixmap *dst, fz_pixmap *src, int alpha)
{
unsigned char *sp, *dp;
diff --git a/fitz/dev_draw.c b/fitz/dev_draw.c
index e0a12492..fb8c4c72 100644
--- a/fitz/dev_draw.c
+++ b/fitz/dev_draw.c
@@ -27,6 +27,9 @@ struct fz_drawdevice_s
fz_blendmode blendmode;
int luminosity;
float alpha;
+ fz_matrix ctm;
+ float xstep, ystep;
+ fz_rect area;
} stack[STACKSIZE];
};
@@ -928,6 +931,82 @@ fz_drawendgroup(void *user)
}
static void
+fz_drawbegintile(void *user, fz_rect area, fz_rect view, float xstep, float ystep, fz_matrix ctm)
+{
+ fz_drawdevice *dev = user;
+ fz_colorspace *model = dev->dest->colorspace;
+ fz_pixmap *dest;
+ fz_bbox bbox;
+
+ /* area, view, xstep, ystep are in pattern space */
+ /* ctm maps from pattern space to device space */
+
+ if (dev->top == STACKSIZE)
+ {
+ fz_warn("assert: too many buffers on stack");
+ return;
+ }
+
+ bbox = fz_roundrect(fz_transformrect(ctm, view));
+ dest = fz_newpixmapwithrect(model, bbox);
+ fz_clearpixmap(dest);
+
+ dev->stack[dev->top].scissor = dev->scissor;
+ dev->stack[dev->top].dest = dev->dest;
+ dev->stack[dev->top].xstep = xstep;
+ dev->stack[dev->top].ystep = ystep;
+ dev->stack[dev->top].area = area;
+ dev->stack[dev->top].ctm = ctm;
+ dev->top++;
+
+ dev->scissor = bbox;
+ dev->dest = dest;
+}
+
+static void
+fz_drawendtile(void *user)
+{
+ fz_drawdevice *dev = user;
+ fz_pixmap *tile = dev->dest;
+ float xstep, ystep;
+ fz_matrix ctm, ttm;
+ fz_rect area;
+ int x0, y0, x1, y1, x, y;
+
+ if (dev->top > 0)
+ {
+ dev->top--;
+ xstep = dev->stack[dev->top].xstep;
+ ystep = dev->stack[dev->top].ystep;
+ area = dev->stack[dev->top].area;
+ ctm = dev->stack[dev->top].ctm;
+ dev->scissor = dev->stack[dev->top].scissor;
+ dev->dest = dev->stack[dev->top].dest;
+
+ x0 = floorf(area.x0 / xstep);
+ y0 = floorf(area.y0 / ystep);
+ x1 = ceilf(area.x1 / xstep);
+ y1 = ceilf(area.y1 / ystep);
+
+ ctm.e = tile->x;
+ ctm.f = tile->y;
+
+ for (y = y0; y < y1; y++)
+ {
+ for (x = x0; x < x1; x++)
+ {
+ ttm = fz_concat(fz_translate(x * xstep, y * ystep), ctm);
+ tile->x = roundf(ttm.e);
+ tile->y = roundf(ttm.f);
+ fz_paintpixmapbbox(dev->dest, tile, 255, dev->scissor);
+ }
+ }
+
+ fz_droppixmap(tile);
+ }
+}
+
+static void
fz_drawfreeuser(void *user)
{
fz_drawdevice *dev = user;
@@ -979,5 +1058,8 @@ fz_newdrawdevice(fz_glyphcache *cache, fz_pixmap *dest)
dev->begingroup = fz_drawbegingroup;
dev->endgroup = fz_drawendgroup;
+ dev->begintile = fz_drawbegintile;
+ dev->endtile = fz_drawendtile;
+
return dev;
}
diff --git a/fitz/dev_list.c b/fitz/dev_list.c
index bfa4ddf1..2bba6ed3 100644
--- a/fitz/dev_list.c
+++ b/fitz/dev_list.c
@@ -90,6 +90,8 @@ fz_freedisplaynode(fz_displaynode *node)
case FZ_CMDENDMASK:
case FZ_CMDBEGINGROUP:
case FZ_CMDENDGROUP:
+ case FZ_CMDBEGINTILE:
+ case FZ_CMDENDTILE:
break;
}
if (node->stroke)
@@ -291,6 +293,29 @@ fz_listendgroup(void *user)
fz_appenddisplaynode(user, node);
}
+static void
+fz_listbegintile(void *user, fz_rect area, fz_rect view, float xstep, float ystep, fz_matrix ctm)
+{
+ fz_displaynode *node;
+ node = fz_newdisplaynode(FZ_CMDBEGINTILE, ctm, nil, nil, 0);
+ node->rect = area;
+ node->color[0] = xstep;
+ node->color[1] = ystep;
+ node->color[2] = view.x0;
+ node->color[3] = view.y0;
+ node->color[4] = view.x1;
+ node->color[5] = view.y1;
+ fz_appenddisplaynode(user, node);
+}
+
+static void
+fz_listendtile(void *user)
+{
+ fz_displaynode *node;
+ node = fz_newdisplaynode(FZ_CMDENDTILE, fz_identity, nil, nil, 0);
+ fz_appenddisplaynode(user, node);
+}
+
fz_device *
fz_newlistdevice(fz_displaylist *list)
{
@@ -319,6 +344,9 @@ fz_newlistdevice(fz_displaylist *list)
dev->begingroup = fz_listbegingroup;
dev->endgroup = fz_listendgroup;
+ dev->begintile = fz_listbegintile;
+ dev->endtile = fz_listendtile;
+
return dev;
}
@@ -350,6 +378,7 @@ fz_executedisplaylist(fz_displaylist *list, fz_device *dev, fz_matrix topctm, fz
fz_displaynode *node;
fz_rect bbox;
int clipped = 0;
+ int tiled = 0;
if (!fz_isinfinitebbox(bounds))
{
@@ -364,11 +393,21 @@ fz_executedisplaylist(fz_displaylist *list, fz_device *dev, fz_matrix topctm, fz
fz_matrix ctm = fz_concat(node->ctm, topctm);
fz_rect rect = fz_transformrect(topctm, node->rect);
+ /* never skip tiles */
+ if (tiled)
+ goto visible;
+
/* cull objects to draw using a quick visibility test */
if (clipped || fz_isemptybbox(fz_intersectbbox(fz_roundrect(rect), bounds)))
{
switch (node->cmd)
{
+ case FZ_CMDBEGINTILE:
+ tiled++;
+ goto visible;
+ case FZ_CMDENDTILE:
+ tiled--;
+ goto visible;
case FZ_CMDCLIPPATH:
case FZ_CMDCLIPSTROKEPATH:
case FZ_CMDCLIPTEXT:
@@ -381,18 +420,19 @@ fz_executedisplaylist(fz_displaylist *list, fz_device *dev, fz_matrix topctm, fz
case FZ_CMDPOPCLIP:
case FZ_CMDENDGROUP:
if (!clipped)
- break;
+ goto visible;
clipped--;
continue;
case FZ_CMDENDMASK:
if (!clipped)
- break;
+ goto visible;
continue;
default:
continue;
}
}
+visible:
switch (node->cmd)
{
case FZ_CMDFILLPATH:
@@ -458,6 +498,17 @@ fz_executedisplaylist(fz_displaylist *list, fz_device *dev, fz_matrix topctm, fz
case FZ_CMDENDGROUP:
dev->endgroup(dev->user);
break;
+ case FZ_CMDBEGINTILE:
+ bbox.x0 = node->color[2];
+ bbox.y0 = node->color[3];
+ bbox.x1 = node->color[4];
+ bbox.y1 = node->color[5];
+ dev->begintile(dev->user, node->rect, bbox,
+ node->color[0], node->color[1], ctm);
+ break;
+ case FZ_CMDENDTILE:
+ dev->endtile(dev->user);
+ break;
}
}
}
diff --git a/fitz/dev_null.c b/fitz/dev_null.c
index 7c80b0ff..2d20a966 100644
--- a/fitz/dev_null.c
+++ b/fitz/dev_null.c
@@ -19,6 +19,8 @@ static void fz_nullbeginmask(void *user, fz_rect r, int luminosity, fz_colorspac
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) {}
+static void fz_nullbegintile(void *user, fz_rect area, fz_rect view, float xstep, float ystep, fz_matrix ctm) {}
+static void fz_nullendtile(void *user) {}
fz_device *
fz_newdevice(void *user)
@@ -54,6 +56,9 @@ fz_newdevice(void *user)
dev->begingroup = fz_nullbegingroup;
dev->endgroup = fz_nullendgroup;
+ dev->begintile = fz_nullbegintile;
+ dev->endtile = fz_nullendtile;
+
return dev;
}
diff --git a/fitz/dev_trace.c b/fitz/dev_trace.c
index 50ba02f3..f8a94b43 100644
--- a/fitz/dev_trace.c
+++ b/fitz/dev_trace.c
@@ -253,6 +253,23 @@ fz_traceendgroup(void *user)
printf("</group>\n");
}
+static void
+fz_tracebegintile(void *user, fz_rect area, fz_rect view, float xstep, float ystep, fz_matrix ctm)
+{
+ printf("<tile ");
+ printf("area=\"%g %g %g %g\" ", area.x0, area.y0, area.x1, area.y1);
+ printf("view=\"%g %g %g %g\" ", view.x0, view.y0, view.x1, view.y1);
+ printf("xstep=\"%g\" ystep=\"%g\" ", xstep, ystep);
+ fz_tracematrix(ctm);
+ printf(">\n");
+}
+
+static void
+fz_traceendtile(void *user)
+{
+ printf("</tile>\n");
+}
+
fz_device *fz_newtracedevice(void)
{
fz_device *dev = fz_newdevice(nil);
@@ -280,5 +297,8 @@ fz_device *fz_newtracedevice(void)
dev->begingroup = fz_tracebegingroup;
dev->endgroup = fz_traceendgroup;
+ dev->begintile = fz_tracebegintile;
+ dev->endtile = fz_traceendtile;
+
return dev;
}
diff --git a/fitz/fitz.h b/fitz/fitz.h
index 4a91c90d..9af91a3f 100644
--- a/fitz/fitz.h
+++ b/fitz/fitz.h
@@ -1026,6 +1026,9 @@ struct fz_device_s
void (*endmask)(void *);
void (*begingroup)(void *, fz_rect, int isolated, int knockout, fz_blendmode blendmode, float alpha);
void (*endgroup)(void *);
+
+ void (*begintile)(void *, fz_rect area, fz_rect view, float xstep, float ystep, fz_matrix ctm);
+ void (*endtile)(void *);
};
fz_device *fz_newdevice(void *user);
@@ -1095,6 +1098,8 @@ typedef enum fz_displaycommand_e
FZ_CMDENDMASK,
FZ_CMDBEGINGROUP,
FZ_CMDENDGROUP,
+ FZ_CMDBEGINTILE,
+ FZ_CMDENDTILE
} fz_displaycommand;
struct fz_displaynode_s
@@ -1194,6 +1199,7 @@ void fz_paintimagecolor(fz_pixmap *dst, fz_bbox scissor, fz_pixmap *img, fz_matr
void fz_paintpixmap(fz_pixmap *dst, fz_pixmap *src, int alpha);
void fz_paintpixmapmask(fz_pixmap *dst, fz_pixmap *src, fz_pixmap *msk);
+void fz_paintpixmapbbox(fz_pixmap *dst, fz_pixmap *src, int alpha, fz_bbox bbox);
void fz_blendpixmap(fz_pixmap *dst, fz_pixmap *src, int alpha, fz_blendmode blendmode);
diff --git a/mupdf/pdf_build.c b/mupdf/pdf_build.c
index 4e19db92..616f1c86 100644
--- a/mupdf/pdf_build.c
+++ b/mupdf/pdf_build.c
@@ -1,6 +1,8 @@
#include "fitz.h"
#include "mupdf.h"
+#define TILE
+
void
pdf_initgstate(pdf_gstate *gs, fz_matrix ctm)
{
@@ -150,13 +152,13 @@ pdf_setshade(pdf_csi *csi, int what, fz_shade *shade)
}
static void
-pdf_showpattern(pdf_csi *csi, pdf_pattern *pat, fz_rect bbox, int what)
+pdf_showpattern(pdf_csi *csi, pdf_pattern *pat, fz_rect area, int what)
{
pdf_gstate *gstate;
fz_matrix ptm, invptm;
fz_matrix oldtopctm;
fz_error error;
- int x, y, x0, y0, x1, y1;
+ int x0, y0, x1, y1;
int oldtop;
pdf_gsave(csi);
@@ -197,33 +199,51 @@ pdf_showpattern(pdf_csi *csi, pdf_pattern *pat, fz_rect bbox, int what)
/* patterns are painted using the ctm in effect at the beginning of the content stream */
/* get bbox of shape in pattern space for stamping */
- bbox = fz_transformrect(invptm, bbox);
- x0 = floorf(bbox.x0 / pat->xstep);
- y0 = floorf(bbox.y0 / pat->ystep);
- x1 = ceilf(bbox.x1 / pat->xstep);
- y1 = ceilf(bbox.y1 / pat->ystep);
+ area = fz_transformrect(invptm, area);
+ x0 = floorf(area.x0 / pat->xstep);
+ y0 = floorf(area.y0 / pat->ystep);
+ x1 = ceilf(area.x1 / pat->xstep);
+ y1 = ceilf(area.y1 / pat->ystep);
oldtopctm = csi->topctm;
oldtop = csi->gtop;
- for (y = y0; y < y1; y++)
+#ifdef TILE
+ if ((x1 - x0) * (y1 - y0) > 0)
+ {
+ csi->dev->begintile(csi->dev->user, area, pat->bbox, pat->xstep, pat->ystep, ptm);
+ gstate->ctm = ptm;
+ csi->topctm = gstate->ctm;
+ error = pdf_runcsibuffer(csi, pat->resources, pat->contents);
+ if (error)
+ fz_catch(error, "cannot render pattern tile");
+ while (oldtop < csi->gtop)
+ pdf_grestore(csi);
+ csi->dev->endtile(csi->dev->user);
+ }
+#else
{
- for (x = x0; x < x1; x++)
+ int x, y;
+ for (y = y0; y < y1; y++)
{
- gstate->ctm = fz_concat(fz_translate(x * pat->xstep, y * pat->ystep), ptm);
- csi->topctm = gstate->ctm;
- error = pdf_runcsibuffer(csi, pat->resources, pat->contents);
- while (oldtop < csi->gtop)
- pdf_grestore(csi);
- if (error)
+ for (x = x0; x < x1; x++)
{
- fz_catch(error, "cannot render pattern tile");
- goto cleanup;
+ gstate->ctm = fz_concat(fz_translate(x * pat->xstep, y * pat->ystep), ptm);
+ csi->topctm = gstate->ctm;
+ error = pdf_runcsibuffer(csi, pat->resources, pat->contents);
+ while (oldtop < csi->gtop)
+ pdf_grestore(csi);
+ if (error)
+ {
+ fz_catch(error, "cannot render pattern tile");
+ goto cleanup;
+ }
}
}
}
-
cleanup:
+#endif
+
csi->topctm = oldtopctm;
pdf_grestore(csi);
diff --git a/xps/xps_tile.c b/xps/xps_tile.c
index 2ddc190e..0f9c6c89 100644
--- a/xps/xps_tile.c
+++ b/xps/xps_tile.c
@@ -1,6 +1,8 @@
#include "fitz.h"
#include "muxps.h"
+#define TILE
+
/*
* Parse a tiling brush (visual and image brushes at this time) common
* properties. Use the callback to draw the individual tiles.
@@ -171,8 +173,16 @@ xps_parse_tiling_brush(xps_context *ctx, fz_matrix ctm, fz_rect area,
int y0 = floorf(bbox.y0 / ystep);
int x1 = ceilf(bbox.x1 / xstep);
int y1 = ceilf(bbox.y1 / ystep);
+#ifdef TILE
+ int ntile = (x1 - x0) * (y1 - y0);
+ if (ntile > 1)
+ ctx->dev->begintile(ctx->dev->user, bbox, viewbox, xstep, ystep, ctm);
+ if (ntile > 0)
+ xps_paint_tiling_brush(ctx, ctm, viewbox, tile_mode, &c);
+ if (ntile > 1)
+ ctx->dev->endtile(ctx->dev->user);
+#else
int x, y;
-
for (y = y0; y < y1; y++)
{
for (x = x0; x < x1; x++)
@@ -181,6 +191,7 @@ xps_parse_tiling_brush(xps_context *ctx, fz_matrix ctm, fz_rect area,
xps_paint_tiling_brush(ctx, ttm, viewbox, tile_mode, &c);
}
}
+#endif
}
else
{