summaryrefslogtreecommitdiff
path: root/mupdf/build.c
diff options
context:
space:
mode:
authorTor Andersson <tor@ghostscript.com>2004-11-05 07:57:47 +0100
committerTor Andersson <tor@ghostscript.com>2004-11-05 07:57:47 +0100
commit24ee8c1e74d613b1ec394c7380b39349f07d47d6 (patch)
tree07c964441d983c713c05090021ce6da1e1c132fe /mupdf/build.c
parentcbbee31601e34f1f513a4d046d52963baebf07fa (diff)
downloadmupdf-24ee8c1e74d613b1ec394c7380b39349f07d47d6.tar.xz
tiling patterns
Diffstat (limited to 'mupdf/build.c')
-rw-r--r--mupdf/build.c131
1 files changed, 131 insertions, 0 deletions
diff --git a/mupdf/build.c b/mupdf/build.c
index 6a8f4fdf..20bb0f5d 100644
--- a/mupdf/build.c
+++ b/mupdf/build.c
@@ -83,18 +83,27 @@ pdf_setcolor(pdf_csi *csi, int what, float *v)
switch (mat->kind)
{
+ case PDF_MPATTERN:
+ if (!strcmp(mat->cs->name, "Lab"))
+ goto Llab;
+ if (!strcmp(mat->cs->name, "Indexed"))
+ goto Lindexed;
+ /* fall through */
+
case PDF_MCOLOR:
for (i = 0; i < mat->cs->n; i++)
mat->v[i] = v[i];
break;
case PDF_MLAB:
+Llab:
mat->v[0] = v[0] / 100.0;
mat->v[1] = (v[1] + 100) / 200.0;
mat->v[2] = (v[2] + 100) / 200.0;
break;
case PDF_MINDEXED:
+Lindexed:
ind = mat->indexed;
i = CLAMP(v[0], 0, ind->high);
for (k = 0; k < ind->base->n; k++)
@@ -108,6 +117,27 @@ pdf_setcolor(pdf_csi *csi, int what, float *v)
return nil;
}
+fz_error *
+pdf_setpattern(pdf_csi *csi, int what, pdf_pattern *pat, float *v)
+{
+ pdf_gstate *gs = csi->gstate + csi->gtop;
+ fz_error *error;
+ pdf_material *mat;
+
+ error = pdf_flushtext(csi);
+ if (error)
+ return error;
+
+ mat = what == PDF_MFILL ? &gs->fill : &gs->stroke;
+
+ mat->kind = PDF_MPATTERN;
+ mat->pattern = pat;
+
+ if (v)
+ return pdf_setcolor(csi, what, v);
+
+ return nil;
+}
fz_error *
pdf_buildstrokepath(pdf_gstate *gs, fz_pathnode *path)
@@ -165,6 +195,96 @@ addcolorshape(pdf_gstate *gs, fz_node *shape, fz_colorspace *cs, float *v)
return nil;
}
+static fz_matrix getmatrix(fz_node *node)
+{
+ if (node->parent)
+ {
+ fz_matrix ptm = getmatrix(node->parent);
+ if (fz_istransformnode(node))
+ return fz_concat(((fz_transformnode*)node)->m, ptm);
+ return ptm;
+ }
+ if (fz_istransformnode(node))
+ return ((fz_transformnode*)node)->m;
+ return fz_identity();
+}
+
+static fz_error *
+addpatternshape(pdf_gstate *gs, fz_node *shape,
+ pdf_pattern *pat, fz_colorspace *cs, float *v)
+{
+ fz_error *error;
+ fz_node *xform;
+ fz_node *over;
+ fz_node *mask;
+ fz_node *link;
+ fz_matrix ctm;
+ fz_matrix inv;
+ fz_matrix ptm;
+ fz_rect bbox;
+ int x, y, x0, y0, x1, y1;
+
+ /* patterns are painted in user space */
+ ctm = getmatrix(gs->head);
+ inv = fz_invertmatrix(ctm);
+
+ error = fz_newmasknode(&mask);
+ if (error) return error;
+
+ ptm = fz_concat(pat->matrix, fz_invertmatrix(ctm));
+ error = fz_newtransformnode(&xform, ptm);
+ if (error) return error;
+
+ error = fz_newovernode(&over);
+ if (error) return error;
+
+ fz_insertnode(mask, shape);
+ fz_insertnode(mask, xform);
+ fz_insertnode(xform, over);
+
+ /* get bbox of shape in pattern space for stamping */
+ ptm = fz_concat(ctm, fz_invertmatrix(pat->matrix));
+ bbox = fz_boundnode(shape, ptm);
+
+ /* expand bbox by pattern bbox */
+ bbox.min.x += pat->bbox.min.x;
+ bbox.min.y += pat->bbox.min.y;
+ bbox.max.x += pat->bbox.max.x;
+ bbox.max.y += pat->bbox.max.y;
+
+printf("stamping pattern [%g %g] over [%g %g %g %g]\n",
+ pat->xstep, pat->ystep,
+ bbox.min.x, bbox.min.y,
+ bbox.max.x, bbox.max.y);
+
+ x0 = fz_floor(bbox.min.x / pat->xstep);
+ y0 = fz_floor(bbox.min.y / pat->ystep);
+ x1 = fz_ceil(bbox.max.x / pat->xstep);
+ y1 = fz_ceil(bbox.max.y / pat->ystep);
+
+printf(" %d,%d to %d,%d\n", x0, y0, x1, y1);
+
+ for (y = y0; y <= y1; y++)
+ {
+ for (x = x0; x <= x1; x++)
+ {
+ ptm = fz_translate(x * pat->xstep, y * pat->ystep);
+ error = fz_newtransformnode(&xform, ptm);
+ if (error) return error;
+ error = fz_newlinknode(&link, pat->tree);
+ if (error) return error;
+ fz_insertnode(xform, link);
+ fz_insertnode(over, xform);
+ }
+ }
+
+ if (pat->ismask)
+ return addcolorshape(gs, mask, cs, v);
+
+ fz_insertnode(gs->head, mask);
+ return nil;
+}
+
fz_error *
pdf_addfillshape(pdf_gstate *gs, fz_node *shape)
{
@@ -174,7 +294,11 @@ pdf_addfillshape(pdf_gstate *gs, fz_node *shape)
fz_insertnode(gs->head, shape);
return nil;
case PDF_MCOLOR:
+ case PDF_MLAB:
+ case PDF_MINDEXED:
return addcolorshape(gs, shape, gs->fill.cs, gs->fill.v);
+ case PDF_MPATTERN:
+ return addpatternshape(gs, shape, gs->fill.pattern, gs->fill.cs, gs->fill.v);
default:
return fz_throw("unimplemented material");
}
@@ -189,7 +313,11 @@ pdf_addstrokeshape(pdf_gstate *gs, fz_node *shape)
fz_insertnode(gs->head, shape);
return nil;
case PDF_MCOLOR:
+ case PDF_MLAB:
+ case PDF_MINDEXED:
return addcolorshape(gs, shape, gs->stroke.cs, gs->stroke.v);
+ case PDF_MPATTERN:
+ return addpatternshape(gs, shape, gs->stroke.pattern, gs->stroke.cs, gs->stroke.v);
default:
return fz_throw("unimplemented material");
}
@@ -397,6 +525,9 @@ pdf_flushtext(pdf_csi *csi)
pdf_gstate *gstate = csi->gstate + csi->gtop;
fz_error *error;
+if (gstate->render != 0)
+fz_warn("unimplemented text render mode: %d", gstate->render);
+
if (csi->text)
{
error = pdf_addfillshape(gstate, (fz_node*)csi->text);