#include "paint.h" /* pos is a point on the unmagnified image */ static void centercanvas(Widget *w, Point pos) { Canvas *c; Point valid; c = w->aux; pos = mtoipt(pos, w); pos = subpt(pos, divpt(rectdim(w->r), 2)); valid = subpt(mulpt(rectdim(c->s->mem->r), c->mag), rectdim(w->r)); c->pos = clamppt(pos, Rpt(ZP, valid)); } static int mouse(Widget *w, Mousectl *mctl) { Widget *root; Canvas *c; int but, mag; Point p, q, mc; Rectangle s, m; root = findrootwidget(w); c = w->aux; fastsetcursor(mctl, &sweepcursor); do { if((mctl->buttons & 7) == 0) { readmouse(mctl); } else { but = mctl->buttons; p = mctl->xy; do { q = mctl->xy; s = clamprect(canonrect(Rpt(p, q)), mtosrect(c->s->mem->r, w)); w->redraw(w, RDall); antsrect(w->screen, w->r, s); readmouse(mctl); } while((mctl->buttons & 7) == but); if(mctl->buttons) { w->redraw(w, RDall); while(mctl->buttons) readmouse(mctl); continue; } m = stomrect(s, w); mc = divpt(addpt(m.min, m.max), 2); switch(but) { case 1: if(Dx(m) == 0 || Dy(m) == 0) c->mag = 1; else c->mag = max(c->mag * fmax((float)Dx(s)/Dx(w->r), (float)Dy(s)/Dy(w->r)), 1); centercanvas(w, mc); if(synccanvasimg(c, c->img->r) < 0) { fprint(2, "zoom: sync: %r\n"); goto err; } root->resize(root, INFDIM); /* w->resize might do a redundant sync */ root->redraw(root, RDall); break; case 2: w->redraw(w, RDall); if((w = newzeroxwindow(w)) == nil) { fprint(2, "zerox: %r\n"); goto err; } c = w->aux; root = findrootwidget(w); if(Dx(m) != 0 && Dy(m) != 0) c->mag = max(min((float)Dx(w->r)/Dx(m), (float)Dy(w->r)/Dy(m)), 1); centercanvas(w, mc); if(synccanvasimg(c, c->img->r) < 0) { fprint(2, "zerox: sync: %r\n"); goto err; } root->redraw(root, RDall); goto done; case 4: if(Dx(m) == 0 || Dy(m) == 0) mag = c->mag + 1; else mag = max(min((float)Dx(w->r)/Dx(m), (float)Dy(w->r)/Dy(m)), 1); if(mag <= c->mag) mag = c->mag + 1; c->mag = mag; centercanvas(w, mc); if(synccanvasimg(c, c->img->r) < 0) { fprint(2, "zoom: sync: %r\n"); goto err; } /* w->resize might do a redundant sync */ root->resize(root, INFDIM); root->redraw(root, RDall); break; } } } while(ptinrect(mctl->xy, w->r)); done: fastsetcursor(mctl, nil); return 0; err: fastsetcursor(mctl, nil); return -1; } CanvasTool zoom = { mouse, };