URI:
       tcache.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tcache.c (3719B)
       ---
            1 #include <u.h>
            2 #include <libc.h>
            3 #include <draw.h>
            4 #include <cursor.h>
            5 #include <event.h>
            6 #include <bio.h>
            7 #include <plumb.h>
            8 #include <ctype.h>
            9 #include <keyboard.h>
           10 #include <thread.h>
           11 #include "page.h"
           12 
           13 typedef struct Cached Cached;
           14 struct Cached
           15 {
           16         Document *doc;
           17         int page;
           18         int angle;
           19         Image *im;
           20         int ppi;
           21 };
           22 
           23 static Cached cache[5];
           24 static int rabusy;
           25 
           26 static Image*
           27 questionmark(void)
           28 {
           29         static Image *im;
           30 
           31         if(im)
           32                 return im;
           33         im = xallocimage(display, Rect(0,0,50,50), GREY1, 1, DBlack);
           34         if(im == nil)
           35                 return nil;
           36         string(im, ZP, display->white, ZP, display->defaultfont, "?");
           37         return im;
           38 }
           39 
           40 void
           41 cacheflush(void)
           42 {
           43         int i;
           44         Cached *c;
           45 
           46         for(i=0; i<nelem(cache); i++){
           47                 c = &cache[i];
           48                 if(c->im)
           49                         freeimage(c->im);
           50                 c->im = nil;
           51                 c->doc = nil;
           52         }
           53 }
           54 
           55 static Image*
           56 _cachedpage(Document *doc, int angle, int page, char *ra)
           57 {
           58         int i;
           59         Cached *c, old;
           60         Image *im, *tmp;
           61         int ppi = 100;
           62         PDFInfo *pdf;
           63         PSInfo *ps;
           64 
           65         if((page < 0 || page >= doc->npage) && !doc->fwdonly)
           66                 return nil;
           67 
           68         if (doc->type == Tpdf){
           69                 pdf = (PDFInfo *) doc->extra;
           70                 ppi = pdf->gs.ppi;
           71         }
           72         else{
           73                 if (doc->type == Tps){
           74                         ps = (PSInfo *) doc->extra;
           75                         ppi = ps->gs.ppi;
           76                 }
           77         }
           78 
           79 Again:
           80         for(i=0; i<nelem(cache); i++){
           81                 c = &cache[i];
           82                 if(c->doc == doc && c->angle == angle && c->page == page && c->ppi == ppi){
           83                         if(chatty) fprint(2, "cache%s hit %d\n", ra, page);
           84                         goto Found;
           85                 }
           86                 if(c->doc == nil)
           87                         break;
           88         }
           89 
           90         if(i >= nelem(cache))
           91                 i = nelem(cache)-1;
           92         c = &cache[i];
           93         if(c->im)
           94                 freeimage(c->im);
           95         c->im = nil;
           96         c->doc = nil;
           97         c->page = -1;
           98         c->ppi = -1;
           99 
          100         if(chatty) fprint(2, "cache%s load %d\n", ra, page);
          101         im = doc->drawpage(doc, page);
          102         if(im == nil){
          103                 if(doc->fwdonly)        /* end of file */
          104                         wexits(0);
          105                 im = questionmark();
          106                 if(im == nil){
          107                 Flush:
          108                         if(i > 0){
          109                                 cacheflush();
          110                                 goto Again;
          111                         }
          112                         fprint(2, "out of memory: %r\n");
          113                         wexits("memory");
          114                 }
          115                 return im;
          116         }
          117 
          118         if(im->r.min.x != 0 || im->r.min.y != 0){
          119                 /* translate to 0,0 */
          120                 tmp = xallocimage(display, Rect(0, 0, Dx(im->r), Dy(im->r)), im->chan, 0, DNofill);
          121                 if(tmp == nil){
          122                         freeimage(im);
          123                         goto Flush;
          124                 }
          125                 drawop(tmp, tmp->r, im, nil, im->r.min, S);
          126                 freeimage(im);
          127                 im = tmp;
          128         }
          129 
          130         switch(angle){
          131         case 90:
          132                 im = rot90(im);
          133                 break;
          134         case 180:
          135                 rot180(im);
          136                 break;
          137         case 270:
          138                 im = rot270(im);
          139                 break;
          140         }
          141         if(im == nil)
          142                 goto Flush;
          143 
          144         c->doc = doc;
          145         c->page = page;
          146         c->angle = angle;
          147         c->im = im;
          148         c->ppi = ppi;
          149 
          150 Found:
          151         if(chatty) fprint(2, "cache%s mtf %d @%d:", ra, c->page, i);
          152         old = *c;
          153         memmove(cache+1, cache, (c-cache)*sizeof cache[0]);
          154         cache[0] = old;
          155         if(chatty){
          156                 for(i=0; i<nelem(cache); i++)
          157                         fprint(2, " %d", cache[i].page);
          158                 fprint(2, "\n");
          159         }
          160         if(chatty) fprint(2, "cache%s return %d %p\n", ra, old.page, old.im);
          161         return old.im;
          162 }
          163 
          164 static void
          165 raproc(void *a)
          166 {
          167         Cached *c;
          168 
          169         c = a;
          170         lockdisplay(display);
          171         /*
          172          * If there is only one page in a fwdonly file, we may reach EOF
          173          * while doing readahead and page will exit without showing anything.
          174          */
          175         if(!c->doc->fwdonly)
          176                 _cachedpage(c->doc, c->angle, c->page, "-ra");
          177         rabusy = 0;
          178         unlockdisplay(display);
          179         free(c);
          180         threadexits(0);
          181 }
          182 
          183 Image*
          184 cachedpage(Document *doc, int angle, int page)
          185 {
          186         static int lastpage = -1;
          187         Cached *c;
          188         Image *im;
          189         int ra;
          190 
          191         if(doc->npage < 1)
          192                 return display->white;
          193 
          194         im = _cachedpage(doc, angle, page, "");
          195         if(im == nil)
          196                 return nil;
          197 
          198         /* readahead */
          199         ra = -1;
          200         if(!rabusy){
          201                 if(page == lastpage+1)
          202                         ra = page+1;
          203                 else if(page == lastpage-1)
          204                         ra = page-1;
          205         }
          206         lastpage = page;
          207         if(ra >= 0){
          208                 c = emalloc(sizeof(*c));
          209                 c->doc = doc;
          210                 c->angle = angle;
          211                 c->page = ra;
          212                 c->im = nil;
          213                 rabusy = 1;
          214                 if(proccreate(raproc, c, mainstacksize) == -1)
          215                         rabusy = 0;
          216         }
          217         return im;
          218 }