git: 9front

Download patch

ref: d41b16f380a163fff247287cc947d6f777090beb
parent: 0beb5f7a25d57e70dc4bec5b53cb9b13fe78231e
author: cinap_lenrek <cinap_lenrek@centraldogma>
date: Sun Sep 11 21:47:32 EDT 2011

npage: zoom and enhance

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