npage: zoom and enhance

This commit is contained in:
cinap_lenrek 2011-09-12 01:47:32 +02:00
parent 97f742c860
commit 8243c0e80b

View file

@ -25,6 +25,7 @@ struct Page {
Page *tail; Page *tail;
}; };
int zoom = 1;
int ppi = 100; int ppi = 100;
int imode; int imode;
int newwin; int newwin;
@ -55,6 +56,9 @@ char *menuitems[] = {
"fit width", "fit width",
"fit height", "fit height",
"", "",
"zoom in",
"zoom out",
"",
"next", "next",
"prev", "prev",
"zerox", "zerox",
@ -87,8 +91,9 @@ Cursor reading = {
0x00, 0x00, 0x01, 0xb6, 0x01, 0xb6, 0x00, 0x00, } 0x00, 0x00, 0x01, 0xb6, 0x01, 0xb6, 0x00, 0x00, }
}; };
void void showpage(Page *);
showpage(Page *); void drawpage(Page *);
Point pagesize(Page *);
Page* Page*
addpage(Page *up, char *label, int (*popen)(Page *), void *pdata, int fd) addpage(Page *up, char *label, int (*popen)(Page *), void *pdata, int fd)
@ -639,7 +644,6 @@ unloadpages(int age)
void void
loadpages(Page *p, int ahead, int oviewgen) loadpages(Page *p, int ahead, int oviewgen)
{ {
Point size;
int i; int i;
ahead++; /* load at least one */ ahead++; /* load at least one */
@ -654,16 +658,20 @@ loadpages(Page *p, int ahead, int oviewgen)
qunlock(p); qunlock(p);
break; break;
} }
size = p->image ? subpt(p->image->r.max, p->image->r.min) : ZP;
qunlock(p);
if(p == current){ if(p == current){
Point size;
esetcursor(nil);
size = pagesize(p);
if(size.x && size.y && newwin){ if(size.x && size.y && newwin){
newwin = 0; newwin = 0;
resizewin(size); resizewin(size);
} }
eresized(0); lockdisplay(display);
drawpage(p);
unlockdisplay(display);
} }
qunlock(p);
} }
} }
} }
@ -731,23 +739,64 @@ gendrawdiff(Image *dst, Rectangle bot, Rectangle top,
} }
void void
eresized(int new) zoomdraw(Image *d, Rectangle r, Rectangle top, Image *s, Point sp, int f)
{
int w, x, y;
Image *t;
Point a;
if(f <= 1){
gendrawdiff(d, r, top, s, sp, nil, ZP, S);
return;
}
a = ZP;
if(r.min.x < d->r.min.x){
sp.x += (d->r.min.x - r.min.x)/f;
a.x = (d->r.min.x - r.min.x)%f;
r.min.x = d->r.min.x;
}
if(r.min.y < d->r.min.y){
sp.y += (d->r.min.y - r.min.y)/f;
a.y = (d->r.min.y - r.min.y)%f;
r.min.y = d->r.min.y;
}
rectclip(&r, d->r);
w = s->r.max.x - sp.x;
if(w > Dx(r))
w = Dx(r);
t = allocimage(display, Rect(r.min.x, r.min.y, r.min.x+w, r.max.y), s->chan, 0, DNofill);
if(t == nil)
return;
for(y=r.min.y; y<r.max.y; y++){
draw(t, Rect(r.min.x, y, r.min.x+w, y+1), s, nil, sp);
if(++a.y == zoom){
a.y = 0;
sp.y++;
}
}
sp = t->r.min;
for(x=r.min.x; x<r.max.x; x++){
gendrawdiff(d, Rect(x, r.min.y, x+1, r.max.y), top, t, sp, nil, ZP, S);
if(++a.x == f){
a.x = 0;
sp.x++;
}
}
freeimage(t);
}
Point
pagesize(Page *p)
{
return p->image ? mulpt(subpt(p->image->r.max, p->image->r.min), zoom) : ZP;
}
void
drawpage(Page *p)
{ {
Rectangle r; Rectangle r;
Image *i; Image *i;
Page *p;
if(new){
lockdisplay(display);
if(getwindow(display, Refnone) == -1)
sysfatal("getwindow: %r");
unlockdisplay(display);
}
if((p = current) == nil)
return;
qlock(p);
lockdisplay(display);
if((i = p->image) == nil){ if((i = p->image) == nil){
char *s; char *s;
@ -760,15 +809,12 @@ eresized(int new)
draw(screen, r, display->white, nil, ZP); draw(screen, r, display->white, nil, ZP);
string(screen, r.min, display->black, ZP, font, s); string(screen, r.min, display->black, ZP, font, s);
} else { } else {
r = rectaddpt(rectaddpt(Rpt(ZP, subpt(i->r.max, i->r.min)), screen->r.min), pos); r = rectaddpt(Rpt(ZP, pagesize(p)), addpt(pos, screen->r.min));
draw(screen, r, i, nil, i->r.min); zoomdraw(screen, r, ZR, i, i->r.min, zoom);
} }
gendrawdiff(screen, screen->r, r, display->white, ZP, nil, ZP, S); gendrawdiff(screen, screen->r, r, display->white, ZP, nil, ZP, S);
border(screen, r, -Borderwidth, display->black, ZP); border(screen, r, -Borderwidth, display->black, ZP);
flushimage(display, 1); flushimage(display, 1);
esetcursor(nil);
unlockdisplay(display);
qunlock(p);
} }
void void
@ -777,35 +823,19 @@ translate(Page *p, Point d)
Rectangle r, or, nr; Rectangle r, or, nr;
Image *i; Image *i;
if(p == nil || d.x==0 && d.y==0) i = p->image;
if((i==0) || (d.x==0 && d.y==0))
return; return;
if(!canqlock(p)) r = rectaddpt(Rpt(ZP, pagesize(p)), addpt(pos, screen->r.min));
return; pos = addpt(pos, d);
if(i = p->image){ nr = rectaddpt(r, d);
r = rectaddpt(rectaddpt(Rpt(ZP, subpt(i->r.max, i->r.min)), screen->r.min), pos); or = r;
pos = addpt(pos, d); rectclip(&or, screen->r);
nr = rectaddpt(r, d); draw(screen, rectaddpt(or, d), screen, nil, or.min);
or = r; zoomdraw(screen, nr, rectaddpt(or, d), i, i->r.min, zoom);
rectclip(&or, screen->r); gendrawdiff(screen, screen->r, nr, display->white, ZP, nil, ZP, S);
draw(screen, rectaddpt(or, d), screen, nil, or.min); border(screen, nr, -Borderwidth, display->black, ZP);
gendrawdiff(screen, nr, rectaddpt(or, d), i, i->r.min, nil, ZP, S); flushimage(display, 1);
gendrawdiff(screen, screen->r, nr, display->white, ZP, nil, ZP, S);
border(screen, nr, -Borderwidth, display->black, ZP);
flushimage(display, 1);
}
qunlock(p);
}
Point
pagesize(Page *p)
{
Point t = ZP;
if(p && canqlock(p)){
if(p->image)
t = subpt(p->image->r.max, p->image->r.min);
qunlock(p);
}
return t;
} }
Page* Page*
@ -890,6 +920,23 @@ Out:
esetcursor(nil); esetcursor(nil);
} }
void
eresized(int new)
{
Page *p;
lockdisplay(display);
if(new && getwindow(display, Refnone) == -1)
sysfatal("getwindow: %r");
if(p = current){
if(canqlock(p)){
drawpage(p);
qunlock(p);
}
}
unlockdisplay(display);
}
void killcohort(void) void killcohort(void)
{ {
int i; int i;
@ -898,6 +945,7 @@ void killcohort(void)
sleep(1); sleep(1);
} }
} }
void drawerr(Display *, char *msg) void drawerr(Display *, char *msg)
{ {
sysfatal("draw: %s", msg); sysfatal("draw: %s", msg);
@ -985,6 +1033,8 @@ main(int argc, char *argv[])
lockdisplay(display); lockdisplay(display);
m = e.mouse; m = e.mouse;
if(m.buttons & 1){ if(m.buttons & 1){
if(current == nil || !canqlock(current))
goto Unlock;
for(;;) { for(;;) {
o = m.xy; o = m.xy;
m = emouse(); m = emouse();
@ -992,6 +1042,7 @@ main(int argc, char *argv[])
break; break;
translate(current, subpt(m.xy, o)); translate(current, subpt(m.xy, o));
} }
qunlock(current);
goto Unlock; goto Unlock;
} }
if(m.buttons & 2){ if(m.buttons & 2){
@ -1001,6 +1052,7 @@ main(int argc, char *argv[])
s = menuitems[i]; s = menuitems[i];
if(strcmp(s, "orig size")==0){ if(strcmp(s, "orig size")==0){
pos = ZP; pos = ZP;
zoom = 1;
resize = ZP; resize = ZP;
rotate = 0; rotate = 0;
Unload: Unload:
@ -1022,16 +1074,36 @@ main(int argc, char *argv[])
} }
if(strcmp(s, "fit width")==0){ if(strcmp(s, "fit width")==0){
pos = ZP; pos = ZP;
zoom = 1;
resize = subpt(screen->r.max, screen->r.min); resize = subpt(screen->r.max, screen->r.min);
resize.y = 0; resize.y = 0;
goto Unload; goto Unload;
} }
if(strcmp(s, "fit height")==0){ if(strcmp(s, "fit height")==0){
pos = ZP; pos = ZP;
zoom = 1;
resize = subpt(screen->r.max, screen->r.min); resize = subpt(screen->r.max, screen->r.min);
resize.x = 0; resize.x = 0;
goto Unload; goto Unload;
} }
if(strncmp(s, "zoom", 4)==0){
if(current && canqlock(current)){
o = subpt(m.xy, screen->r.min);
if(strstr(s, "in")){
if(zoom < 0x40000000){
zoom *= 2;
pos = addpt(mulpt(subpt(pos, o), 2), o);
}
}else{
if(zoom > 1){
zoom /= 2;
pos = addpt(divpt(subpt(pos, o), 2), o);
}
}
drawpage(current);
qunlock(current);
}
}
unlockdisplay(display); unlockdisplay(display);
if(strcmp(s, "next")==0) if(strcmp(s, "next")==0)
showpage(nextpage(current)); showpage(nextpage(current));
@ -1062,30 +1134,45 @@ main(int argc, char *argv[])
case Kdel: case Kdel:
case Keof: case Keof:
exits(0); exits(0);
case 'd':
qlock(current);
lockdisplay(display);
translate(current, Pt(-1, -1));
unlockdisplay(display);
qunlock(current);
break;
case Kup: case Kup:
if(current == nil || !canqlock(current))
break;
lockdisplay(display); lockdisplay(display);
if(pos.y < 0){ if(pos.y < 0){
translate(current, Pt(0, Dy(screen->r)/2)); translate(current, Pt(0, Dy(screen->r)/2));
unlockdisplay(display); unlockdisplay(display);
qunlock(current);
continue; continue;
} }
unlockdisplay(display);
qunlock(current);
if(prevpage(current)) if(prevpage(current))
pos.y = 0; pos.y = 0;
unlockdisplay(display);
case Kleft: case Kleft:
showpage(prevpage(current)); showpage(prevpage(current));
break; break;
case Kdown: case Kdown:
lockdisplay(display); if(current == nil || !canqlock(current))
break;
o = addpt(pos, pagesize(current)); o = addpt(pos, pagesize(current));
lockdisplay(display);
if(o.y > Dy(screen->r)){ if(o.y > Dy(screen->r)){
translate(current, Pt(0, -Dy(screen->r)/2)); translate(current, Pt(0, -Dy(screen->r)/2));
unlockdisplay(display); unlockdisplay(display);
qunlock(current);
continue; continue;
} }
unlockdisplay(display);
qunlock(current);
if(nextpage(current)) if(nextpage(current))
pos.y = 0; pos.y = 0;
unlockdisplay(display);
case ' ': case ' ':
case Kright: case Kright:
showpage(nextpage(current)); showpage(nextpage(current));