#! /usr/bin/env ueforth \ Copyright 2022 Bradley D. Nelson \ \ Licensed under the Apache License, Version 2.0 (the "License"); \ you may not use this file except in compliance with the License. \ You may obtain a copy of the License at \ \ http://www.apache.org/licenses/LICENSE-2.0 \ \ Unless required by applicable law or agreed to in writing, software \ distributed under the License is distributed on an "AS IS" BASIS, \ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. \ See the License for the specific language governing permissions and \ limitations under the License. also graphics also structures struct ScanSpan ptr field ->next ptr field ->edge 1024 constant max-scanlines create scanlines max-scanlines cells allot scanlines max-scanlines cells erase 0 value free-edges : new-edge ( n next -- a ) free-edges if free-edges dup ->next @ to free-edges else ScanSpan allocate throw then { np } np ->next ! np ->edge ! np ; : row-span ( y -- a ) cells scanlines + ; : add-edge { x y } y row-span { yp } begin yp @ while x yp @ ->edge @ <= if x yp @ new-edge yp ! exit then yp @ ->next to yp repeat x yp @ new-edge yp ! ; : remove-edge ( y -- x ) row-span { yp } yp @ 0= if 10000 exit then yp @ { old } yp @ ->edge @ yp @ ->next @ yp ! free-edges old ->next ! old to free-edges ; : draw-row { y } begin y row-span @ while y remove-edge y remove-edge over - y swap 1 box repeat ; : draw-spans max-scanlines 0 do i draw-row loop ; : 2span { a b -- n } a b max a b min - ; : 3span { a b c -- n } a b max c max a b min c min - ; : raw-bezier 0 0 { x1 y1 x2 y2 x3 y3 d xn yn } y1 d rshift y2 d rshift y3 d rshift 3span 2 < if y1 d rshift y3 d rshift 2span if y1 y3 = if x1 x3 + 2/ d lshift y1 d rshift add-edge exit then y1 y3 < if x1 x3 x1 - y1 1 d lshift 1- and y3 y1 - */ - d rshift y1 d rshift add-edge else x3 x1 x3 - y3 1 d lshift 1- and y1 y3 - */ - d rshift y3 d rshift add-edge then then else x1 x2 2* + x3 + to xn y1 y2 2* + y3 + to yn x1 4* y1 4* x1 x2 + 2* y1 y2 + 2* xn yn d 2 + recurse xn yn x2 x3 + 2* y2 y3 + 2* x3 4* y3 4* d 2 + recurse then ; ( : line 0 0 { x1 y1 x2 y2 dx dy } y1 y2 > if y1 y2 to y1 to y2 x1 x2 to x1 to x2 then y2 y1 - 0.>> to dy x2 x1 - to dx dy 0 ?do x1 dx i dy */ + 0.>> y1 0.>> i + add-edge loop ; ) : bezier 0 raw-bezier ; : line ( x1 y1 x2 y2 ) 2dup bezier ; 0 value pen-x 0 value pen-y : move-to { x y } x to pen-x y to pen-y ; : line-to { x y } pen-x pen-y x y line x y move-to ; : bezier-to { x' y' x y } pen-x pen-y x' y' x y bezier x y move-to ; -1 -1 window $ff0000 constant red $ffff00 constant yellow $ffffff constant white $000000 constant black $0000bb constant blue : draw black to color 0 0 width height box yellow to color 0 0 width 2/ height 2/ box red to color width 3 / 100 move-to mouse-x 1 mouse-x mouse-y bezier-to mouse-x 2/ 1 line-to 300 200 200 400 bezier-to 1 mouse-y 2 3 */ line-to width 3 / 100 line-to blue to color draw-spans flip ; : run begin poll IDLE event = if draw then event FINISHED = until bye ; run