summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrodri <rgl@antares-labs.eu>2022-06-22 21:20:41 +0000
committerrodri <rgl@antares-labs.eu>2022-06-22 21:20:41 +0000
commit667fd01d924ecc99c1579e155b39cd12fd201f4b (patch)
tree618a253270065059dc7154da09d94e8917318d08
downloadtinyrend-667fd01d924ecc99c1579e155b39cd12fd201f4b.tar.gz
tinyrend-667fd01d924ecc99c1579e155b39cd12fd201f4b.tar.bz2
tinyrend-667fd01d924ecc99c1579e155b39cd12fd201f4b.zip
Lesson 0: Bresenham's Line Drawing Algorithm—First attempt
-rw-r--r--main.c222
-rw-r--r--mkfile24
2 files changed, 246 insertions, 0 deletions
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..0cd9e9a
--- /dev/null
+++ b/main.c
@@ -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();
+}
diff --git a/mkfile b/mkfile
new file mode 100644
index 0000000..d6883d8
--- /dev/null
+++ b/mkfile
@@ -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}