ref: cb6f6fc863f56fecdf9adc97e0cd48255b14841c
dir: /canvas.c/
#include <u.h> #include <libc.h> #include <draw.h> #include "dat.h" #include "fns.h" Image *back; Image *canvas; Image *canvas2; Point spos; /* position on screen */ Point cpos; /* position on canvas */ static Image **pages; static int npages; static int nundo = 0; static Image *undo[1024]; Point s2c(Point p) { p = subpt(p, spos); if(p.x < 0) p.x -= zoom-1; if(p.y < 0) p.y -= zoom-1; return addpt(divpt(p, zoom), cpos); } Point c2s(Point p) { return addpt(mulpt(subpt(p, cpos), zoom), spos); } Rectangle c2sr(Rectangle r) { return Rpt(c2s(r.min), c2s(r.max)); } void save(Rectangle r, int flip) { Image *tmp; int x; if(canvas==nil || nundo<0) return; if(!rectclip(&r, canvas->r)) return; if(flip){ draw(canvas2, r, canvas, nil, ZP); return; } if((tmp = allocimage(display, r, canvas->chan, 0, DNofill)) == nil) return; draw(tmp, r, canvas, nil, r.min); x = nundo++ % nelem(undo); if(undo[x]) freeimage(undo[x]); undo[x] = tmp; } void shrinksaved(Rectangle r) { Image *tmp; int x; if(canvas==nil || canvas2==nil) return; if(!rectclip(&r, canvas2->r)) return; if((tmp = allocimage(display, r, canvas->chan, 0, DNofill)) == nil) return; draw(tmp, r, canvas2, nil, r.min); x = nundo++ % nelem(undo); if(undo[x]) freeimage(undo[x]); undo[x] = tmp; } void restore(int n) { Image *tmp; int x; while(nundo > 0){ if(n-- == 0) return; x = --nundo % nelem(undo); if((tmp = undo[x]) == nil) return; undo[x] = nil; if(canvas == nil || canvas->chan != tmp->chan){ freeimage(canvas); canvas = tmp; update(nil); } else { expand(tmp->r); draw(canvas, tmp->r, tmp, nil, tmp->r.min); update(&tmp->r); freeimage(tmp); } } } // FIXME: don't change canvas size once set void expand(Rectangle r) { Rectangle nr; Image *tmp; if(canvas==nil){ if((canvas = allocimage(display, r, screen->chan, 0, DNofill)) == nil || (canvas2 = allocimage(display, r, screen->chan, 0, DNofill)) == nil) sysfatal("allocimage: %r"); draw(canvas, canvas->r, back, nil, ZP); return; } nr = canvas->r; combinerect(&nr, r); if(eqrect(nr, canvas->r)) return; if((tmp = allocimage(display, nr, canvas->chan, 0, DNofill)) == nil) return; draw(tmp, canvas->r, canvas, nil, canvas->r.min); gendrawdiff(tmp, tmp->r, canvas->r, back, ZP, nil, ZP, SoverD); freeimage(canvas); canvas = tmp; } void initcnv(Point sz, char *file) { int fd; Rectangle r; if(file != nil){ if((fd = open(file, OREAD)) < 0) sysfatal("open: %r"); if((canvas = readimage(display, fd, 0)) == nil) sysfatal("readimage: %r"); close(fd); if((canvas2 = allocimage(display, canvas->r, screen->chan, 0, DNofill)) == nil) sysfatal("allocimage: %r"); return; }else if(!eqpt(sz, ZP)) r = Rpt(ZP, sz); else r = rectsubpt(screen->r, screen->r.min); expand(r); }