From fda7116fc12ea7e125ff8fc9851e3ca9280459b9 Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Mon, 4 Apr 2011 01:29:38 +0200 Subject: draw: Speed up display list execution by using a visibility test. --- apps/pdfapp.c | 4 ++-- apps/pdfdraw.c | 6 +++--- apps/xpsdraw.c | 6 +++--- fitz/dev_draw.c | 1 - fitz/dev_list.c | 45 ++++++++++++++++++++++++++++++++++++++++++++- fitz/fitz.h | 2 +- 6 files changed, 53 insertions(+), 11 deletions(-) diff --git a/apps/pdfapp.c b/apps/pdfapp.c index a9cb698a..8f5b3912 100644 --- a/apps/pdfapp.c +++ b/apps/pdfapp.c @@ -365,7 +365,7 @@ static void pdfapp_showpage(pdfapp_t *app, int loadpage, int drawpage, int repai /* Extract text */ app->page_text = fz_newtextspan(); tdev = fz_newtextdevice(app->page_text); - fz_executedisplaylist(app->page_list, tdev, fz_identity); + fz_executedisplaylist(app->page_list, tdev, fz_identity, fz_infinitebbox); fz_freedevice(tdev); } @@ -392,7 +392,7 @@ static void pdfapp_showpage(pdfapp_t *app, int loadpage, int drawpage, int repai app->image = fz_newpixmapwithrect(colorspace, bbox); fz_clearpixmapwithcolor(app->image, 255); idev = fz_newdrawdevice(app->cache, app->image); - fz_executedisplaylist(app->page_list, idev, ctm); + fz_executedisplaylist(app->page_list, idev, ctm, bbox); fz_freedevice(idev); } diff --git a/apps/pdfdraw.c b/apps/pdfdraw.c index 9c46a3a9..3de0a80c 100644 --- a/apps/pdfdraw.c +++ b/apps/pdfdraw.c @@ -120,7 +120,7 @@ static void drawpage(pdf_xref *xref, int pagenum) dev = fz_newtracedevice(); printf("\n", pagenum); if (list) - fz_executedisplaylist(list, dev, fz_identity); + fz_executedisplaylist(list, dev, fz_identity, fz_infinitebbox); else pdf_runpage(xref, page, dev, fz_identity); printf("\n"); @@ -132,7 +132,7 @@ static void drawpage(pdf_xref *xref, int pagenum) fz_textspan *text = fz_newtextspan(); dev = fz_newtextdevice(text); if (list) - fz_executedisplaylist(list, dev, fz_identity); + fz_executedisplaylist(list, dev, fz_identity, fz_infinitebbox); else pdf_runpage(xref, page, dev, fz_identity); fz_freedevice(dev); @@ -173,7 +173,7 @@ static void drawpage(pdf_xref *xref, int pagenum) dev = fz_newdrawdevice(glyphcache, pix); if (list) - fz_executedisplaylist(list, dev, ctm); + fz_executedisplaylist(list, dev, ctm, bbox); else pdf_runpage(xref, page, dev, ctm); fz_freedevice(dev); diff --git a/apps/xpsdraw.c b/apps/xpsdraw.c index a9050a1c..2e30de9a 100644 --- a/apps/xpsdraw.c +++ b/apps/xpsdraw.c @@ -115,7 +115,7 @@ static void drawpage(xps_context *ctx, int pagenum) dev = fz_newtracedevice(); printf("\n", pagenum); if (list) - fz_executedisplaylist(list, dev, fz_identity); + fz_executedisplaylist(list, dev, fz_identity, fz_infinitebbox); else xps_run_page(ctx, page, dev, fz_identity); printf("\n"); @@ -127,7 +127,7 @@ static void drawpage(xps_context *ctx, int pagenum) fz_textspan *text = fz_newtextspan(); dev = fz_newtextdevice(text); if (list) - fz_executedisplaylist(list, dev, fz_identity); + fz_executedisplaylist(list, dev, fz_identity, fz_infinitebbox); else xps_run_page(ctx, page, dev, fz_identity); fz_freedevice(dev); @@ -171,7 +171,7 @@ static void drawpage(xps_context *ctx, int pagenum) dev = fz_newdrawdevice(glyphcache, pix); if (list) - fz_executedisplaylist(list, dev, ctm); + fz_executedisplaylist(list, dev, ctm, bbox); else xps_run_page(ctx, page, dev, ctm); fz_freedevice(dev); diff --git a/fitz/dev_draw.c b/fitz/dev_draw.c index e9cb74fc..e0a12492 100644 --- a/fitz/dev_draw.c +++ b/fitz/dev_draw.c @@ -632,7 +632,6 @@ fz_drawfillimage(void *user, fz_pixmap *image, fz_matrix ctm, float alpha) } #endif - if (image->colorspace != model && after) { converted = fz_newpixmap(model, image->x, image->y, image->w, image->h); diff --git a/fitz/dev_list.c b/fitz/dev_list.c index 4dcd1470..d90f64c2 100644 --- a/fitz/dev_list.c +++ b/fitz/dev_list.c @@ -176,6 +176,9 @@ fz_listcliptext(void *user, fz_text *text, fz_matrix ctm, int accumulate) node->rect = fz_boundtext(text, ctm); node->item.text = fz_clonetext(text); node->flag = accumulate; + /* when accumulating, be conservative about culling */ + if (accumulate) + node->rect = fz_infiniterect; fz_appenddisplaynode(user, node); } @@ -342,13 +345,53 @@ fz_freedisplaylist(fz_displaylist *list) } void -fz_executedisplaylist(fz_displaylist *list, fz_device *dev, fz_matrix topctm) +fz_executedisplaylist(fz_displaylist *list, fz_device *dev, fz_matrix topctm, fz_bbox bounds) { fz_displaynode *node; fz_rect bbox; + int clipped = 0; + + if (!fz_isinfinitebbox(bounds)) + { + /* add some fuzz at the edges, as especially glyph rects + * are sometimes not actually completely bounding the glyph */ + bounds.x0 -= 20; bounds.y0 -= 20; + bounds.x1 += 20; bounds.y1 += 20; + } + for (node = list->first; node; node = node->next) { fz_matrix ctm = fz_concat(node->ctm, topctm); + + /* cull objects to draw using a quick visibility test */ + if (clipped || fz_isemptybbox(fz_intersectbbox(fz_roundrect(node->rect), bounds))) + { + switch (node->cmd) + { + case FZ_CMDCLIPPATH: + case FZ_CMDCLIPSTROKEPATH: + case FZ_CMDCLIPTEXT: + case FZ_CMDCLIPSTROKETEXT: + case FZ_CMDCLIPIMAGEMASK: + case FZ_CMDBEGINMASK: + case FZ_CMDBEGINGROUP: + clipped++; + continue; + case FZ_CMDPOPCLIP: + case FZ_CMDENDGROUP: + if (!clipped) + break; + clipped--; + continue; + case FZ_CMDENDMASK: + if (!clipped) + break; + continue; + default: + continue; + } + } + switch (node->cmd) { case FZ_CMDFILLPATH: diff --git a/fitz/fitz.h b/fitz/fitz.h index 216c7264..4a91c90d 100644 --- a/fitz/fitz.h +++ b/fitz/fitz.h @@ -1126,7 +1126,7 @@ struct fz_displaylist_s fz_displaylist *fz_newdisplaylist(void); void fz_freedisplaylist(fz_displaylist *list); fz_device *fz_newlistdevice(fz_displaylist *list); -void fz_executedisplaylist(fz_displaylist *list, fz_device *dev, fz_matrix ctm); +void fz_executedisplaylist(fz_displaylist *list, fz_device *dev, fz_matrix ctm, fz_bbox area); /* * Function pointers for plotting functions. -- cgit v1.2.3