diff options
author | Tor Andersson <tor@ghostscript.com> | 2004-11-25 04:46:31 +0100 |
---|---|---|
committer | Tor Andersson <tor@ghostscript.com> | 2004-11-25 04:46:31 +0100 |
commit | 9c659d040a3890dc6a33aed485eba15364631bec (patch) | |
tree | 50916134c964184f16706f93d253aa1000ab889d /tree | |
parent | 4b2218b903da6de40e8a82b9e2a69157d415637c (diff) | |
download | mupdf-9c659d040a3890dc6a33aed485eba15364631bec.tar.xz |
optimize away useless clipmasks. undo ctm for shades.
Diffstat (limited to 'tree')
-rw-r--r-- | tree/debug.c | 14 | ||||
-rw-r--r-- | tree/optimize.c | 132 | ||||
-rw-r--r-- | tree/tree.c | 3 |
3 files changed, 118 insertions, 31 deletions
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; |