diff options
-rw-r--r-- | TODO | 10 | ||||
-rw-r--r-- | include/mupdf/content.h | 1 | ||||
-rw-r--r-- | mupdf/build.c | 78 | ||||
-rw-r--r-- | mupdf/interpret.c | 5 | ||||
-rw-r--r-- | tree/debug.c | 14 | ||||
-rw-r--r-- | tree/optimize.c | 132 | ||||
-rw-r--r-- | tree/tree.c | 3 |
7 files changed, 177 insertions, 66 deletions
@@ -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; |