Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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 "page.h"
11
 
12
typedef struct Cached Cached;
13
struct Cached
14
{
15
	Document *doc;
16
	int page;
17
	int angle;
18
	Image *im;
19
};
20
 
21
static Cached cache[5];
22
 
23
static Image*
24
questionmark(void)
25
{
26
	static Image *im;
27
 
28
	if(im)
29
		return im;	
30
	im = xallocimage(display, Rect(0,0,50,50), GREY1, 1, DBlack);
31
	if(im == nil)
32
		return nil;
33
	string(im, ZP, display->white, ZP, display->defaultfont, "?");
34
	return im;
35
}
36
 
37
void
38
cacheflush(void)
39
{
40
	int i;
41
	Cached *c;
42
 
43
	for(i=0; i<nelem(cache); i++){
44
		c = &cache[i];
45
		if(c->im)
46
			freeimage(c->im);
47
		c->im = nil;
48
		c->doc = nil;
49
	}
50
}
51
 
52
static Image*
53
_cachedpage(Document *doc, int angle, int page, char *ra)
54
{
55
	int i;
56
	Cached *c, old;
57
	Image *im, *tmp;
58
	static int lastpage = -1;
59
 
60
	if((page < 0 || page >= doc->npage) && !doc->fwdonly)
61
		return nil;
62
 
63
Again:
64
	for(i=0; i<nelem(cache); i++){
65
		c = &cache[i];
66
		if(c->doc == doc && c->angle == angle && c->page == page){
67
			if(chatty) fprint(2, "cache%s hit %d\n", ra, page);
68
			goto Found;
69
		}
70
		if(c->doc == nil)
71
			break;
72
	}
73
 
74
	if(i >= nelem(cache))
75
		i = nelem(cache)-1;
76
	c = &cache[i];
77
	if(c->im)
78
		freeimage(c->im);
79
	c->im = nil;
80
	c->doc = nil;
81
	c->page = -1;
82
 
83
	if(chatty) fprint(2, "cache%s load %d\n", ra, page);
84
	im = doc->drawpage(doc, page);
85
	if(im == nil){
86
		if(doc->fwdonly)	/* end of file */
87
			wexits(0);
88
		im = questionmark();
89
		if(im == nil){
90
		Flush:
91
			if(i > 0){
92
				cacheflush();
93
				goto Again;
94
			}
95
			fprint(2, "out of memory: %r\n");
96
			wexits("memory");
97
		}
98
		return im;
99
	}
100
 
101
	if(im->r.min.x != 0 || im->r.min.y != 0){
102
		/* translate to 0,0 */
103
		tmp = xallocimage(display, Rect(0, 0, Dx(im->r), Dy(im->r)), im->chan, 0, DNofill);
104
		if(tmp == nil){
105
			freeimage(im);
106
			goto Flush;
107
		}
108
		drawop(tmp, tmp->r, im, nil, im->r.min, S);
109
		freeimage(im);
110
		im = tmp;
111
	}
112
 
113
	switch(angle){
114
	case 90:
115
		im = rot90(im);
116
		break;
117
	case 180:
118
		rot180(im);
119
		break;
120
	case 270:
121
		im = rot270(im);
122
		break;
123
	}
124
	if(im == nil)
125
		goto Flush;
126
 
127
	c->doc = doc;
128
	c->page = page;
129
	c->angle = angle;
130
	c->im = im;
131
 
132
Found:
133
	if(chatty) fprint(2, "cache%s mtf %d @%d:", ra, c->page, i);
134
	old = *c;
135
	memmove(cache+1, cache, (c-cache)*sizeof cache[0]);
136
	cache[0] = old;
137
	if(chatty){
138
		for(i=0; i<nelem(cache); i++)
139
			fprint(2, " %d", cache[i].page);
140
		fprint(2, "\n");
141
	}
142
	if(chatty) fprint(2, "cache%s return %d %p\n", ra, old.page, old.im);
143
	return old.im;
144
}
145
 
146
Image*
147
cachedpage(Document *doc, int angle, int page)
148
{
149
	static int lastpage = -1;
150
	static int rabusy;
151
	Image *im;
152
	int ra;
153
 
154
	if(doc->npage < 1)
155
		return display->white;
156
 
157
	im = _cachedpage(doc, angle, page, "");
158
	if(im == nil)
159
		return nil;
160
 
161
	/* readahead */
162
	ra = -1;
163
	if(!rabusy){
164
		if(page == lastpage+1)
165
			ra = page+1;
166
		else if(page == lastpage-1)
167
			ra = page-1;
168
	}
169
	lastpage = page;
170
	if(ra >= 0){
171
		rabusy = 1;
172
		switch(rfork(RFPROC|RFMEM|RFNOWAIT)){
173
		case -1:
174
			rabusy = 0;
175
			break;
176
		case 0:
177
			lockdisplay(display);
178
			_cachedpage(doc, angle, ra, "-ra");
179
			rabusy = 0;
180
			unlockdisplay(display);
181
			_exits(nil);
182
		default:
183
			break;
184
		}
185
	}
186
	return im;
187
}