summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--TODO10
-rw-r--r--include/mupdf/content.h1
-rw-r--r--mupdf/build.c78
-rw-r--r--mupdf/interpret.c5
-rw-r--r--tree/debug.c14
-rw-r--r--tree/optimize.c132
-rw-r--r--tree/tree.c3
7 files changed, 177 insertions, 66 deletions
diff --git a/TODO b/TODO
index bbe23a8e..4c29ca87 100644
--- a/TODO
+++ b/TODO
@@ -15,11 +15,8 @@ shadings
- ... jeong ...
rendering
- - bbox culling (cache bbox in over node?)
- - merge gka optims
- - optimize inner rendering loops
+ - bbox culling per glyph
- optimize image load/decode/scale
- - special-case optims (1, 2 and 4)
- cpu-specific optims
parser
@@ -28,10 +25,9 @@ parser
- annotations and destinations (for links and outline)
fz_optimizetree()
- - remove rectangular clip nodes whose children fit
- remove white fills at beginning of page
- - remove overs with only one child
- concatenate chained transforms
+ - remove identity transforms
clean up
- make source ansi c89 / pedantic
@@ -43,5 +39,5 @@ clean up
cache
global cache for cmaps and fontfiles (emb+sys)
- render cache (link-nodes and scaled images)
+ render cache (link-nodes and scaled images and shades)
diff --git a/include/mupdf/content.h b/include/mupdf/content.h
index b6eefae9..65bd386e 100644
--- a/include/mupdf/content.h
+++ b/include/mupdf/content.h
@@ -97,6 +97,7 @@ fz_error *pdf_addfillshape(pdf_gstate *gs, fz_node *shape);
fz_error *pdf_addstrokeshape(pdf_gstate *gs, fz_node *shape);
fz_error *pdf_addclipmask(pdf_gstate *gs, fz_node *shape);
fz_error *pdf_addtransform(pdf_gstate *gs, fz_node *transform);
+fz_error *pdf_addshade(pdf_gstate *gs, fz_shade *shade);
fz_error *pdf_showpath(pdf_csi*, int close, int fill, int stroke, int evenodd);
fz_error *pdf_showtext(pdf_csi*, fz_obj *text);
fz_error *pdf_flushtext(pdf_csi*);
diff --git a/mupdf/build.c b/mupdf/build.c
index 541bf056..06c09f84 100644
--- a/mupdf/build.c
+++ b/mupdf/build.c
@@ -150,8 +150,6 @@ pdf_setshade(pdf_csi *csi, int what, fz_shade *shade)
if (error)
return error;
-printf("setshade!\n");
-
mat = what == PDF_MFILL ? &gs->fill : &gs->stroke;
mat->kind = PDF_MSHADE;
@@ -217,28 +215,6 @@ addcolorshape(pdf_gstate *gs, fz_node *shape, fz_colorspace *cs, float *v)
}
static fz_error *
-addshadeshape(pdf_gstate *gs, fz_node *shape, fz_shade *shade)
-{
- fz_error *error;
- fz_node *mask;
- fz_node *color;
-
-printf("addshade!\n");
-
- error = fz_newmasknode(&mask);
- if (error) return error;
-
- error = fz_newshadenode(&color, shade);
- if (error) return error;
-
- fz_insertnodelast(mask, shape);
- fz_insertnodelast(mask, color);
- fz_insertnodelast(gs->head, mask);
-
- return nil;
-}
-
-static fz_error *
addinvisibleshape(pdf_gstate *gs, fz_node *shape)
{
fz_error *error;
@@ -351,6 +327,60 @@ printf(" %d,%d to %d,%d\n", x0, y0, x1, y1);
}
fz_error *
+pdf_addshade(pdf_gstate *gs, fz_shade *shade)
+{
+ fz_error *error;
+ fz_node *node;
+ fz_node *xform;
+ fz_matrix ctm;
+ fz_matrix inv;
+
+ ctm = getmatrix(gs->head);
+ inv = fz_invertmatrix(ctm);
+
+ error = fz_newtransformnode(&xform, inv);
+ if (error) return error;
+
+ error = fz_newshadenode(&node, shade);
+ if (error) return error;
+
+ fz_insertnodelast(xform, node);
+ fz_insertnodelast(gs->head, xform);
+
+ return nil;
+}
+
+static fz_error *
+addshadeshape(pdf_gstate *gs, fz_node *shape, fz_shade *shade)
+{
+ fz_error *error;
+ fz_node *mask;
+ fz_node *color;
+ fz_node *xform;
+ fz_matrix ctm;
+ fz_matrix inv;
+
+ ctm = getmatrix(gs->head);
+ inv = fz_invertmatrix(ctm);
+
+ error = fz_newtransformnode(&xform, inv);
+ if (error) return error;
+
+ error = fz_newmasknode(&mask);
+ if (error) return error;
+
+ error = fz_newshadenode(&color, shade);
+ if (error) return error;
+
+ fz_insertnodelast(mask, shape);
+ fz_insertnodelast(xform, color);
+ fz_insertnodelast(mask, xform);
+ fz_insertnodelast(gs->head, mask);
+
+ return nil;
+}
+
+fz_error *
pdf_addfillshape(pdf_gstate *gs, fz_node *shape)
{
switch (gs->fill.kind)
diff --git a/mupdf/interpret.c b/mupdf/interpret.c
index 22ed7f20..0ec70667 100644
--- a/mupdf/interpret.c
+++ b/mupdf/interpret.c
@@ -760,7 +760,6 @@ fz_debugobj(rdb);
fz_obj *dict;
fz_obj *obj;
fz_shade *shd;
- fz_node *node;
dict = fz_dictgets(rdb, "Pattern");
if (!dict)
@@ -774,10 +773,8 @@ fz_debugobj(rdb);
if (!shd)
return fz_throw("syntaxerror: missing pattern resource");
- error = fz_newshadenode(&node, shd);
+ error = pdf_addshade(gstate, shd);
if (error) return error;
-
- fz_insertnodelast(gstate->head, node);
}
else if (!strcmp(buf, "d0"))
diff --git a/tree/debug.c b/tree/debug.c
index a61872c4..e468ef27 100644
--- a/tree/debug.c
+++ b/tree/debug.c
@@ -6,16 +6,6 @@ static void indent(int level)
putchar(' ');
}
-static void showbbox(void *node0)
-{
- fz_node *node = node0;
- fz_irect bbox;
- bbox = fz_roundrect(fz_boundnode(node, fz_identity()));
- printf("[%d %d %d %d]",
- bbox.min.x, bbox.min.y,
- bbox.max.x, bbox.max.y);
-}
-
static void lispnode(fz_node *node, int level);
static void lispmeta(fz_metanode *node, int level)
@@ -36,7 +26,7 @@ static void lispover(fz_overnode *node, int level)
{
fz_node *child;
indent(level);
- printf("(over "); showbbox(node); printf("\n");
+ printf("(over\n");
for (child = node->super.first; child; child = child->next)
lispnode(child, level + 1);
indent(level);
@@ -47,7 +37,7 @@ static void lispmask(fz_masknode *node, int level)
{
fz_node *child;
indent(level);
- printf("(mask "); showbbox(node); printf("\n");
+ printf("(mask\n");
for (child = node->super.first; child; child = child->next)
lispnode(child, level + 1);
indent(level);
diff --git a/tree/optimize.c b/tree/optimize.c
index 14d98232..6371ddec 100644
--- a/tree/optimize.c
+++ b/tree/optimize.c
@@ -7,21 +7,23 @@
static void cleanovers(fz_node *node)
{
fz_node *prev;
- fz_node *over;
+ fz_node *next;
+ fz_node *current;
fz_node *child;
prev = nil;
- for (over = node->first; over; over = prev->next)
+ for (current = node->first; current; current = next)
{
- cleanovers(over);
+ next = current->next;
- if (fz_isovernode(over))
+ cleanovers(current);
+
+ if (fz_isovernode(current))
{
- if (over->first == over->last)
+ if (current->first == current->last)
{
- printf(" remove unused over node\n");
- child = over->first;
- fz_removenode(over);
+ child = current->first;
+ fz_removenode(current);
if (child)
{
if (prev)
@@ -29,28 +31,120 @@ static void cleanovers(fz_node *node)
else
fz_insertnodefirst(node, child);
}
- over = nil;
+ current = nil;
}
}
- if (over)
- prev = over;
+ if (current)
+ prev = current;
}
}
-fz_error *
-fz_optimizetree(fz_tree *tree)
+/*
+ * Remove rectangular clip-masks whose contents fit...
+ */
+
+static int getrect(fz_pathnode *path, fz_rect *bboxp)
{
- printf("optimizing tree\n");
+ float x, y, w, h;
-//printf("before:\n");
-//fz_debugtree(tree);
+ /* move x y, line x+w y, line x+w y+h, line x y+h, close */
- cleanovers(tree->root);
+ if (path->len != 13)
+ return 0;
+
+ if (path->els[0].k != FZ_MOVETO) return 0;
+ x = path->els[1].v;
+ y = path->els[2].v;
+
+ if (path->els[3].k != FZ_LINETO) return 0;
+ w = path->els[4].v - x;
+ if (path->els[5].v != y) return 0;
+
+ if (path->els[6].k != FZ_LINETO) return 0;
+ if (path->els[7].v != x + w) return 0;
+ h = path->els[8].v - y;
+
+ if (path->els[9].k != FZ_LINETO) return 0;
+ if (path->els[10].v != x) return 0;
+ if (path->els[11].v != y + h) return 0;
+
+ if (path->els[12].k != FZ_CLOSEPATH) return 0;
+
+ bboxp->min.x = MIN(x, x + w);
+ bboxp->min.y = MIN(y, y + h);
+ bboxp->max.x = MAX(x, x + w);
+ bboxp->max.y = MAX(y, y + h);
+
+ return 1;
+}
+
+static int fitsinside(fz_node *node, fz_rect clip)
+{
+ fz_rect bbox;
+ bbox = fz_boundnode(node, fz_identity());
+ if (fz_isinfiniterect(bbox)) return 0;
+ if (fz_isemptyrect(bbox)) return 1;
+ if (bbox.min.x < clip.min.x) return 0;
+ if (bbox.max.x > clip.max.x) return 0;
+ if (bbox.min.y < clip.min.y) return 0;
+ if (bbox.max.y > clip.max.y) return 0;
+ return 1;
+}
+
+static void cleanmasks(fz_node *node)
+{
+ fz_node *prev;
+ fz_node *next;
+ fz_node *current;
+ fz_node *shape;
+ fz_node *color;
+ fz_rect bbox;
-//printf("after:\n");
-//fz_debugtree(tree);
+ prev = nil;
+ for (current = node->first; current; current = next)
+ {
+ next = current->next;
+
+ cleanmasks(current);
+
+ if (fz_ismasknode(current))
+ {
+ shape = current->first;
+ color = shape->next;
+
+ if (fz_ispathnode(shape))
+ {
+ if (getrect((fz_pathnode*)shape, &bbox))
+ {
+ if (fitsinside(color, bbox))
+ {
+ printf("removed useless mask\n");
+ fz_removenode(current);
+ if (prev)
+ fz_insertnodeafter(prev, color);
+ else
+ fz_insertnodefirst(node, color);
+ current = nil;
+ }
+ }
+ }
+ }
+ if (current)
+ prev = current;
+ }
+}
+
+/*
+ *
+ */
+
+fz_error *
+fz_optimizetree(fz_tree *tree)
+{
+ cleanovers(tree->root);
+ cleanmasks(tree->root);
return nil;
}
diff --git a/tree/tree.c b/tree/tree.c
index e59d0413..f667e39a 100644
--- a/tree/tree.c
+++ b/tree/tree.c
@@ -105,6 +105,9 @@ fz_removenode(fz_node *child)
if (parent->first == child)
{
parent->first = child->next;
+ if (parent->last == child)
+ parent->last = nil;
+ return;
}
prev = parent->first;