#include #include #include #include #include #include #include #include #include #include #include "page.h" typedef struct Cached Cached; struct Cached { Document *doc; int page; int angle; Image *im; int ppi; }; static Cached cache[5]; static int rabusy; static Image* questionmark(void) { static Image *im; if(im) return im; im = xallocimage(display, Rect(0,0,50,50), GREY1, 1, DBlack); if(im == nil) return nil; string(im, ZP, display->white, ZP, display->defaultfont, "?"); return im; } void cacheflush(void) { int i; Cached *c; for(i=0; iim) freeimage(c->im); c->im = nil; c->doc = nil; } } static Image* _cachedpage(Document *doc, int angle, int page, char *ra) { int i; Cached *c, old; Image *im, *tmp; int ppi = 100; PDFInfo *pdf; PSInfo *ps; if((page < 0 || page >= doc->npage) && !doc->fwdonly) return nil; if (doc->type == Tpdf){ pdf = (PDFInfo *) doc->extra; ppi = pdf->gs.ppi; } else{ if (doc->type == Tps){ ps = (PSInfo *) doc->extra; ppi = ps->gs.ppi; } } Again: for(i=0; idoc == doc && c->angle == angle && c->page == page && c->ppi == ppi){ if(chatty) fprint(2, "cache%s hit %d\n", ra, page); goto Found; } if(c->doc == nil) break; } if(i >= nelem(cache)) i = nelem(cache)-1; c = &cache[i]; if(c->im) freeimage(c->im); c->im = nil; c->doc = nil; c->page = -1; c->ppi = -1; if(chatty) fprint(2, "cache%s load %d\n", ra, page); im = doc->drawpage(doc, page); if(im == nil){ if(doc->fwdonly) /* end of file */ wexits(0); im = questionmark(); if(im == nil){ Flush: if(i > 0){ cacheflush(); goto Again; } fprint(2, "out of memory: %r\n"); wexits("memory"); } return im; } if(im->r.min.x != 0 || im->r.min.y != 0){ /* translate to 0,0 */ tmp = xallocimage(display, Rect(0, 0, Dx(im->r), Dy(im->r)), im->chan, 0, DNofill); if(tmp == nil){ freeimage(im); goto Flush; } drawop(tmp, tmp->r, im, nil, im->r.min, S); freeimage(im); im = tmp; } switch(angle){ case 90: im = rot90(im); break; case 180: rot180(im); break; case 270: im = rot270(im); break; } if(im == nil) goto Flush; c->doc = doc; c->page = page; c->angle = angle; c->im = im; c->ppi = ppi; Found: if(chatty) fprint(2, "cache%s mtf %d @%d:", ra, c->page, i); old = *c; memmove(cache+1, cache, (c-cache)*sizeof cache[0]); cache[0] = old; if(chatty){ for(i=0; idoc, c->angle, c->page, "-ra"); rabusy = 0; unlockdisplay(display); free(c); threadexits(0); } Image* cachedpage(Document *doc, int angle, int page) { static int lastpage = -1; Cached *c; Image *im; int ra; if(doc->npage < 1) return display->white; im = _cachedpage(doc, angle, page, ""); if(im == nil) return nil; /* readahead */ ra = -1; if(!rabusy){ if(page == lastpage+1) ra = page+1; else if(page == lastpage-1) ra = page-1; } lastpage = page; if(ra >= 0){ c = emalloc(sizeof(*c)); c->doc = doc; c->angle = angle; c->page = ra; c->im = nil; rabusy = 1; if(proccreate(raproc, c, mainstacksize) == -1) rabusy = 0; } return im; }