Monorepo for Aesthetic.Computer aesthetic.computer
at main 106 lines 3.9 kB view raw
1;;; Graphics primitives — wipe, ink, plot, line, box, circle 2 3(in-package :ac-native.graph) 4 5(defstruct graph 6 "Immediate-mode 2D graphics context." 7 (fb nil) ; ac-native.framebuffer:framebuffer 8 (screen nil) ; ac-native.framebuffer:framebuffer 9 (ink-color (make-color :r 255 :g 255 :b 255 :a 255))) 10 11(defun graph-wipe (g color) 12 "Clear the screen with COLOR." 13 (fb-clear (graph-fb g) (color-pack-argb32 color))) 14 15(defun graph-ink (g color) 16 "Set the current drawing color." 17 (setf (graph-ink-color g) color)) 18 19(defun graph-plot (g x y) 20 "Plot a single pixel at (X, Y) using the current ink." 21 (let ((c (graph-ink-color g))) 22 (if (= (color-a c) 255) 23 (fb-put-pixel (graph-fb g) x y (color-pack-argb32 c)) 24 (fb-blend-pixel (graph-fb g) x y c)))) 25 26(defun graph-line (g x0 y0 x1 y1) 27 "Draw a line from (X0,Y0) to (X1,Y1) using Bresenham's algorithm." 28 (declare (optimize (speed 3) (safety 1)) 29 (type fixnum x0 y0 x1 y1)) 30 (let ((dx (abs (- x1 x0))) 31 (dy (- (abs (- y1 y0)))) 32 (sx (if (< x0 x1) 1 -1)) 33 (sy (if (< y0 y1) 1 -1))) 34 (let ((err (+ dx dy)) 35 (x x0) (y y0)) 36 (declare (type fixnum err x y)) 37 (loop 38 (graph-plot g x y) 39 (when (and (= x x1) (= y y1)) (return)) 40 (let ((e2 (* 2 err))) 41 (when (>= e2 dy) 42 (incf err dy) 43 (incf x sx)) 44 (when (<= e2 dx) 45 (incf err dx) 46 (incf y sy))))))) 47 48(defun graph-box (g x y w h &optional (filled t)) 49 "Draw a rectangle. If FILLED, fill it; otherwise draw outline." 50 (declare (optimize (speed 3) (safety 1)) 51 (type fixnum x y w h)) 52 (let ((c (graph-ink-color g)) 53 (fb (graph-fb g))) 54 (if filled 55 ;; Filled box — hot path, optimize 56 (let ((c32 (color-pack-argb32 c)) 57 (opaque (= (color-a c) 255))) 58 (dotimes (row h) 59 (let ((py (+ y row))) 60 (when (and (>= py 0) (< py (fb-height fb))) 61 (dotimes (col w) 62 (let ((px (+ x col))) 63 (when (and (>= px 0) (< px (fb-width fb))) 64 (if opaque 65 (fb-put-pixel fb px py c32) 66 (fb-blend-pixel fb px py c))))))))) 67 ;; Outline 68 (progn 69 (graph-line g x y (+ x w -1) y) 70 (graph-line g x (+ y h -1) (+ x w -1) (+ y h -1)) 71 (graph-line g x y x (+ y h -1)) 72 (graph-line g (+ x w -1) y (+ x w -1) (+ y h -1)))))) 73 74(defun graph-circle (g cx cy r &optional (filled t)) 75 "Draw a circle using the midpoint algorithm." 76 (declare (optimize (speed 3) (safety 1)) 77 (type fixnum cx cy r)) 78 (if filled 79 ;; Filled circle — draw horizontal spans 80 (let ((x 0) (y r) (d (- 1 r))) 81 (declare (type fixnum x y d)) 82 (loop while (<= x y) do 83 (graph-line g (- cx x) (+ cy y) (+ cx x) (+ cy y)) 84 (graph-line g (- cx x) (- cy y) (+ cx x) (- cy y)) 85 (graph-line g (- cx y) (+ cy x) (+ cx y) (+ cy x)) 86 (graph-line g (- cx y) (- cy x) (+ cx y) (- cy x)) 87 (incf x) 88 (if (< d 0) 89 (incf d (+ (* 2 x) 1)) 90 (progn (decf y) (incf d (+ (* 2 (- x y)) 1)))))) 91 ;; Outline circle 92 (let ((x 0) (y r) (d (- 1 r))) 93 (declare (type fixnum x y d)) 94 (loop while (<= x y) do 95 (graph-plot g (+ cx x) (+ cy y)) 96 (graph-plot g (- cx x) (+ cy y)) 97 (graph-plot g (+ cx x) (- cy y)) 98 (graph-plot g (- cx x) (- cy y)) 99 (graph-plot g (+ cx y) (+ cy x)) 100 (graph-plot g (- cx y) (+ cy x)) 101 (graph-plot g (+ cx y) (- cy x)) 102 (graph-plot g (- cx y) (- cy x)) 103 (incf x) 104 (if (< d 0) 105 (incf d (+ (* 2 x) 1)) 106 (progn (decf y) (incf d (+ (* 2 (- x y)) 1))))))))