summaryrefslogtreecommitdiff
path: root/tree/optimize.c
diff options
context:
space:
mode:
authorTor Andersson <tor@ghostscript.com>2004-11-25 04:46:31 +0100
committerTor Andersson <tor@ghostscript.com>2004-11-25 04:46:31 +0100
commit9c659d040a3890dc6a33aed485eba15364631bec (patch)
tree50916134c964184f16706f93d253aa1000ab889d /tree/optimize.c
parent4b2218b903da6de40e8a82b9e2a69157d415637c (diff)
downloadmupdf-9c659d040a3890dc6a33aed485eba15364631bec.tar.xz
optimize away useless clipmasks. undo ctm for shades.
Diffstat (limited to 'tree/optimize.c')
-rw-r--r--tree/optimize.c132
1 files changed, 113 insertions, 19 deletions
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;
}