123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187 |
- #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 "page.h"
- typedef struct Cached Cached;
- struct Cached
- {
- Document *doc;
- int page;
- int angle;
- Image *im;
- };
- static Cached cache[5];
- 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;
- static int lastpage = -1;
- 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;
- }
- Image*
- cachedpage(Document *doc, int angle, int page)
- {
- static int lastpage = -1;
- static int rabusy;
- 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){
- rabusy = 1;
- switch(rfork(RFPROC|RFMEM|RFNOWAIT)){
- case -1:
- rabusy = 0;
- break;
- case 0:
- lockdisplay(display);
- _cachedpage(doc, angle, ra, "-ra");
- rabusy = 0;
- unlockdisplay(display);
- _exits(nil);
- default:
- break;
- }
- }
- return im;
- }
|