mirror of
https://github.com/9fans/plan9port.git
synced 2025-01-12 11:10:07 +00:00
parent
3c6ab1854e
commit
b3453e08b8
5 changed files with 212 additions and 56 deletions
196
cmd/page/cache.c
Normal file
196
cmd/page/cache.c
Normal file
|
@ -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;
|
||||||
|
}
|
|
@ -4,6 +4,7 @@ TARG=page
|
||||||
|
|
||||||
HFILES=page.h
|
HFILES=page.h
|
||||||
OFILES=\
|
OFILES=\
|
||||||
|
cache.$O\
|
||||||
filter.$O\
|
filter.$O\
|
||||||
gfx.$O\
|
gfx.$O\
|
||||||
gs.$O\
|
gs.$O\
|
||||||
|
|
|
@ -228,6 +228,8 @@ threadmain(int argc, char **argv)
|
||||||
fprint(2, "page: initdraw failed: %r\n");
|
fprint(2, "page: initdraw failed: %r\n");
|
||||||
wexits("initdraw");
|
wexits("initdraw");
|
||||||
}
|
}
|
||||||
|
display->locking = 1;
|
||||||
|
|
||||||
truecolor = screen->depth > 8;
|
truecolor = screen->depth > 8;
|
||||||
viewer(doc);
|
viewer(doc);
|
||||||
wexits(0);
|
wexits(0);
|
||||||
|
|
|
@ -96,6 +96,8 @@ void wexits(char*);
|
||||||
Image* xallocimage(Display*, Rectangle, ulong, int, ulong);
|
Image* xallocimage(Display*, Rectangle, ulong, int, ulong);
|
||||||
int bell(void*, char*);
|
int bell(void*, char*);
|
||||||
Image* convert(Graphic *g);
|
Image* convert(Graphic *g);
|
||||||
|
Image* cachedpage(Document*, int, int);
|
||||||
|
void cacheflush(void);
|
||||||
|
|
||||||
extern int stdinfd;
|
extern int stdinfd;
|
||||||
extern int truecolor;
|
extern int truecolor;
|
||||||
|
|
|
@ -115,55 +115,17 @@ menugen(int n)
|
||||||
void
|
void
|
||||||
showpage(int page, Menu *m)
|
showpage(int page, Menu *m)
|
||||||
{
|
{
|
||||||
Image *tmp;
|
|
||||||
|
|
||||||
if(doc->fwdonly)
|
if(doc->fwdonly)
|
||||||
m->lasthit = 0; /* this page */
|
m->lasthit = 0; /* this page */
|
||||||
else
|
else
|
||||||
m->lasthit = reverse ? doc->npage-1-page : page;
|
m->lasthit = reverse ? doc->npage-1-page : page;
|
||||||
|
|
||||||
setcursor(mc, &reading);
|
setcursor(mc, &reading);
|
||||||
freeimage(im);
|
im = cachedpage(doc, angle, page);
|
||||||
if((page < 0 || page >= doc->npage) && !doc->fwdonly){
|
if(im == nil)
|
||||||
im = nil;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
im = doc->drawpage(doc, page);
|
|
||||||
if(im == nil) {
|
|
||||||
if(doc->fwdonly) /* this is how we know we're out of pages */
|
|
||||||
wexits(0);
|
wexits(0);
|
||||||
|
if(resizing)
|
||||||
im = xallocimage(display, Rect(0,0,50,50), GREY1, 1, DBlack);
|
|
||||||
if(im == nil) {
|
|
||||||
fprint(2, "out of memory: %r\n");
|
|
||||||
wexits("memory");
|
|
||||||
}
|
|
||||||
string(im, ZP, display->white, ZP, display->defaultfont, "?");
|
|
||||||
}else if(resizing){
|
|
||||||
resize(Dx(im->r), Dy(im->r));
|
resize(Dx(im->r), Dy(im->r));
|
||||||
}
|
|
||||||
if(im->r.min.x > 0 || im->r.min.y > 0) {
|
|
||||||
tmp = xallocimage(display, Rect(0, 0, Dx(im->r), Dy(im->r)), im->chan, 0, DNofill);
|
|
||||||
if(tmp == nil) {
|
|
||||||
fprint(2, "out of memory during showpage: %r\n");
|
|
||||||
wexits("memory");
|
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
setcursor(mc, nil);
|
setcursor(mc, nil);
|
||||||
if(showbottom){
|
if(showbottom){
|
||||||
|
@ -268,7 +230,7 @@ void
|
||||||
viewer(Document *dd)
|
viewer(Document *dd)
|
||||||
{
|
{
|
||||||
int i, fd, n, oldpage;
|
int i, fd, n, oldpage;
|
||||||
int nxt;
|
int nxt, a;
|
||||||
Channel *cp;
|
Channel *cp;
|
||||||
Menu menu, midmenu;
|
Menu menu, midmenu;
|
||||||
Mouse m;
|
Mouse m;
|
||||||
|
@ -372,7 +334,10 @@ viewer(Document *dd)
|
||||||
* a fair amount. we don't care about doc->npage anymore, and
|
* a fair amount. we don't care about doc->npage anymore, and
|
||||||
* all that can be done is select the next page.
|
* all that can be done is select the next page.
|
||||||
*/
|
*/
|
||||||
switch(alt(alts)) {
|
unlockdisplay(display);
|
||||||
|
a = alt(alts);
|
||||||
|
lockdisplay(display);
|
||||||
|
switch(a) {
|
||||||
case CKeyboard:
|
case CKeyboard:
|
||||||
if(run <= 0xFF && isdigit(run)) {
|
if(run <= 0xFF && isdigit(run)) {
|
||||||
nxt = nxt*10+run-'0';
|
nxt = nxt*10+run-'0';
|
||||||
|
@ -622,22 +587,12 @@ viewer(Document *dd)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Rot: /* rotate 90 */
|
case Rot: /* rotate 90 */
|
||||||
setcursor(mc, &reading);
|
|
||||||
im = rot90(im);
|
|
||||||
setcursor(mc, nil);
|
|
||||||
angle = (angle+90) % 360;
|
angle = (angle+90) % 360;
|
||||||
redraw(screen);
|
showpage(page, &menu);
|
||||||
flushimage(display, 1);
|
|
||||||
break;
|
break;
|
||||||
case Upside: /* upside-down */
|
case Upside: /* upside-down */
|
||||||
if(im==nil)
|
|
||||||
break;
|
|
||||||
setcursor(mc, &reading);
|
|
||||||
rot180(im);
|
|
||||||
setcursor(mc, nil);
|
|
||||||
angle = (angle+180) % 360;
|
angle = (angle+180) % 360;
|
||||||
redraw(screen);
|
showpage(page, &menu);
|
||||||
flushimage(display, 1);
|
|
||||||
break;
|
break;
|
||||||
case Restore: /* restore */
|
case Restore: /* restore */
|
||||||
showpage(page, &menu);
|
showpage(page, &menu);
|
||||||
|
|
Loading…
Reference in a new issue