diff options
author | rodri <rgl@antares-labs.eu> | 2022-06-22 21:20:41 +0000 |
---|---|---|
committer | rodri <rgl@antares-labs.eu> | 2022-06-22 21:20:41 +0000 |
commit | 667fd01d924ecc99c1579e155b39cd12fd201f4b (patch) | |
tree | 618a253270065059dc7154da09d94e8917318d08 | |
download | tinyrend-667fd01d924ecc99c1579e155b39cd12fd201f4b.tar.gz tinyrend-667fd01d924ecc99c1579e155b39cd12fd201f4b.tar.bz2 tinyrend-667fd01d924ecc99c1579e155b39cd12fd201f4b.zip |
Lesson 0: Bresenham's Line Drawing Algorithm—First attempt
-rw-r--r-- | main.c | 222 | ||||
-rw-r--r-- | mkfile | 24 |
2 files changed, 246 insertions, 0 deletions
@@ -0,0 +1,222 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> +#include <thread.h> +#include <draw.h> +#include <memdraw.h> +#include <mouse.h> +#include <keyboard.h> +#include "libgeometry/geometry.h" + + +Memimage *fb; +Memimage *red; + +void resized(void); + +void* +emalloc(ulong n) +{ + void *p; + + p = malloc(n); + if(p == nil) + sysfatal("malloc: %r"); + setmalloctag(p, getcallerpc(&n)); + return p; +} + +void* +erealloc(void *p, ulong n) +{ + void *np; + + np = realloc(p, n); + if(np == nil){ + if(n == 0) + return nil; + sysfatal("realloc: %r"); + } + if(p == nil) + setmalloctag(np, getcallerpc(&p)); + else + setrealloctag(np, getcallerpc(&p)); + return np; +} + +Image* +eallocimage(Display *d, Rectangle r, ulong chan, int repl, ulong col) +{ + Image *i; + + i = allocimage(d, r, chan, repl, col); + if(i == nil) + sysfatal("allocimage: %r"); + return i; +} + +Memimage* +eallocmemimage(Rectangle r, ulong chan) +{ + Memimage *i; + + i = allocmemimage(r, chan); + if(i == nil) + sysfatal("allocmemimage: %r"); + memfillcolor(i, DTransparent); + return i; +} + +Memimage* +rgb(ulong c) +{ + Memimage *i; + + i = eallocmemimage(Rect(0,0,1,1), screen->chan); + i->flags |= Frepl; + i->clipr = Rect(-1e6, -1e6, 1e6, 1e6); + memfillcolor(i, c); + return i; +} + +void +pixel(Memimage *dst, Point p, Memimage *src) +{ + Rectangle r; + + r.min = addpt(dst->r.min, p); + r.max = addpt(r.min, Pt(1,1)); + + memimagedraw(dst, r, src, ZP, nil, ZP, SoverD); +} + +void +bresenham(Memimage *dst, Point p0, Point p1, Memimage *src) +{ + double t, dt; + Point p; + + dt = 0.01; + + for(t = 0; t < 1; t += dt){ + p = Pt( + flerp(p0.x, p1.x, t), + flerp(p0.y, p1.y, t) + ); + pixel(dst, p, src); + } +} + +void +redraw(void) +{ + lockdisplay(display); + draw(screen, screen->r, display->black, nil, ZP); + loadimage(screen, screen->r, byteaddr(fb, fb->r.min), bytesperline(fb->r, fb->depth)*Dy(fb->r)); + flushimage(display, 1); + unlockdisplay(display); +} + +void +rmb(Mousectl *, Keyboardctl *) +{ +} + +void +lmb(Mousectl *, Keyboardctl *) +{ +} + +void +mouse(Mousectl *mc, Keyboardctl *kc) +{ + if((mc->buttons&1) != 0) + lmb(mc, kc); + if((mc->buttons&4) != 0) + rmb(mc, kc); +} + +void +key(Rune r) +{ + switch(r){ + case Kdel: + case 'q': + threadexitsall(nil); + } +} + +void +usage(void) +{ + fprint(2, "usage: %s\n", argv0); + exits("usage"); +} + +void +threadmain(int argc, char *argv[]) +{ + Mousectl *mc; + Keyboardctl *kc; + Rune r; + + GEOMfmtinstall(); + ARGBEGIN{ + default: usage(); + }ARGEND; + if(argc > 0) + usage(); + + if(newwindow(nil) < 0) + sysfatal("newwindow: %r"); + if(initdraw(nil, nil, nil) < 0) + sysfatal("initdraw: %r"); + if(memimageinit() != 0) + sysfatal("memimageinit: %r"); + if((mc = initmouse(nil, screen)) == nil) + sysfatal("initmouse: %r"); + if((kc = initkeyboard(nil)) == nil) + sysfatal("initkeyboard: %r"); + + fb = eallocmemimage(screen->r, screen->chan); + red = rgb(DRed); + bresenham(fb, Pt(40,40), Pt(300,300), red); + + display->locking = 1; + unlockdisplay(display); + redraw(); + + for(;;){ + enum { MOUSE, RESIZE, KEYBOARD }; + Alt a[] = { + {mc->c, &mc->Mouse, CHANRCV}, + {mc->resizec, nil, CHANRCV}, + {kc->c, &r, CHANRCV}, + {nil, nil, CHANEND} + }; + + switch(alt(a)){ + case MOUSE: + mouse(mc, kc); + break; + case RESIZE: + resized(); + break; + case KEYBOARD: + key(r); + break; + } + + redraw(); + } +} + +void +resized(void) +{ + lockdisplay(display); + if(getwindow(display, Refnone) < 0) + sysfatal("couldn't resize"); + unlockdisplay(display); + redraw(); +} @@ -0,0 +1,24 @@ +</$objtype/mkfile + +BIN=/$objtype/bin/musw +TARG=tinyrend +OFILES=\ + main.$O\ + +HFILES=\ + ./libgeometry/geometry.h\ + +LIB=\ + ./libgeometry/libgeometry.a$O\ + +CFLAGS=$CFLAGS + +</sys/src/cmd/mkone + +./libgeometry/libgeometry.a$O: + cd ./libgeometry + mk install + +clean nuke:V: + rm -f *.[$OS] [$OS].??* $TARG + @{cd ./libgeometry; mk $target} |