diff options
author | Russ Cox <rsc@swtch.com> | 2009-08-10 20:01:56 -0700 |
---|---|---|
committer | Russ Cox <rsc@swtch.com> | 2009-08-10 20:01:56 -0700 |
commit | f2887b9de88173031f52492147ba68e5ca94f719 (patch) | |
tree | 82f181ac28ad0a9902823d20efb9e0d332216486 /src/cmd/page | |
parent | b3453e08b88b3973f427c5bf982670bb5a09d259 (diff) | |
download | plan9port-f2887b9de88173031f52492147ba68e5ca94f719.tar.gz plan9port-f2887b9de88173031f52492147ba68e5ca94f719.tar.bz2 plan9port-f2887b9de88173031f52492147ba68e5ca94f719.zip |
page: move cmd/page/cache.c to src/cmd/page/cache.c
not sure how the codebot screwed that up.
Diffstat (limited to 'src/cmd/page')
-rw-r--r-- | src/cmd/page/cache.c | 196 |
1 files changed, 196 insertions, 0 deletions
diff --git a/src/cmd/page/cache.c b/src/cmd/page/cache.c new file mode 100644 index 00000000..87c2c25a --- /dev/null +++ b/src/cmd/page/cache.c @@ -0,0 +1,196 @@ +#include <u.h> +#include <libc.h> +#include <draw.h> +#include <cursor.h> +#include <event.h> +#include <bio.h> +#include <plumb.h> +#include <ctype.h> +#include <keyboard.h> +#include <thread.h> +#include "page.h" + +typedef struct Cached Cached; +struct Cached +{ + Document *doc; + int page; + int angle; + Image *im; +}; + +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; i<nelem(cache); i++){ + c = &cache[i]; + if(c->im) + 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; + + if((page < 0 || page >= doc->npage) && !doc->fwdonly) + return nil; + +Again: + for(i=0; i<nelem(cache); i++){ + c = &cache[i]; + if(c->doc == doc && c->angle == angle && c->page == page){ + 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; + + 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; + +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; i<nelem(cache); i++) + fprint(2, " %d", cache[i].page); + fprint(2, "\n"); + } + if(chatty) fprint(2, "cache%s return %d %p\n", ra, old.page, old.im); + return old.im; +} + +static void +raproc(void *a) +{ + Cached *c; + + c = a; + lockdisplay(display); + _cachedpage(c->doc, 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; +} |