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/optimize.c | |
parent | 4b2218b903da6de40e8a82b9e2a69157d415637c (diff) | |
download | mupdf-9c659d040a3890dc6a33aed485eba15364631bec.tar.xz |
optimize away useless clipmasks. undo ctm for shades.
Diffstat (limited to 'tree/optimize.c')
-rw-r--r-- | tree/optimize.c | 132 |
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; } |