Edit this page

Line drawing routines for forth

For this to work, you'll need write access to the frame buffer. And you'll need to tweak it a bit so it can work with the resolution and bit depth of your display.

I think this is basically the Breshenham algorithm. I tweaked the setup a bit to get more accurate lines (not sure if these tweaks are part of the Breshenham algorithm.)


\ This file contains the functions to:
\
\ * manage a buffer, and write it to /dev/fb/0
\ * draw colored lines
\ * clear the screen
\
\
\ To set this up you must do the following:
\
\ * set width to the width of your framebuffer (number of pixels)
\ * set pixel to the number of bytes in a pixel
\ * rewrite pixel! to store a pixel (it now works only on Big Endian machines in 15 or 16 bit color)
\ * make sure your forth system has enough memory. with gforth do:
\       gforth -m <number of bytes>
\
\ And will probably want to:
\
\ * set height to the number of lines your pixel buffer will be (this will be displayed at the top of the screen)
\ * rewrite rgb to pack your pixel format if you want (type fbset at the terminal and it tells you your pixel format)
\
\ EXAMPLE CODE
\
\ See the word "test" at the bottom for a good test and example.


1280 constant width \ CHANGE THIS
1024 constant height \ CHANGE THIS

4 constant pixel  \ Size (in bytes) of a pixel CHANGE THIS
: pixels 4 * ; \ CHANGE THIS
: pixel! ( pixel addr --     store a pixel )
	! ;    \ CHANGE THIS

variable color -1 color !

: rgb ( r g b --   set color from rgb)
	swap 8 lshift + \ CHANGE THIS
	swap 16 lshift +
	color ! ;




create buff width height * pixels dup allot
constant buff-size

: assert dup if . abort" <---file error" then drop ;

s" /dev/fb/0" w/o open-file assert constant file   \ FIX: error detection etc.

: write-buffer buff buff-size file write-file assert file flush-file assert 0 0 file reposition-file assert ;
: clear buff buff-size 4 / 0 do 0 over ! 4 + loop drop ;

clear

variable x 0 x !
variable y 0 y !


: c2a ( x y -- addr   convert x,y to pixel address)
	1+ height swap -  \ invert y
	width * + pixels buff + ;
: setpixel ( x y --   colors pixel at x,y)
	c2a color @ swap pixel! ;

: moveto y ! x ! ;


width pixels constant linebytes

variable h
variable w
variable c
variable r
variable d
variable startx
variable starty

: setxy ( x y -- )
	x @ startx !
	y @ starty !
	y ! x ! ;
: sethw
	x @ startx @ - w !
	y @ starty @ - h ! ;
: line-defaults ( x y -- )
	setxy
	sethw
	pixel r !
	0 linebytes - d ! ;
: r-l ( --  change control variables for line if line is going right)
	w @ 0 < if x @ startx ! y @ starty ! w @ -1 * w ! h @ -1 * h ! then ;
: u-d ( --  change control variables for line if line is going up)
	h @ 0 < if linebytes d ! h @ -1 * h ! then ;
: h-v ( --  change control variables if line is predominantly verticle)
	h @ w @ > if h @ w @ h ! w !  r @ d @ r ! d ! then ;
: pinit ( x y --   setup variables for drawing line to x,y)
	line-defaults r-l u-d h-v ;

: cinit ( --   set c to w, then double w and h)
	w @ 1+ 2 / c ! ;

: line-setup ( x y -- addr "w"   setup everything for line)
	pinit
	startx @ starty @ c2a w @ cinit ;

: w- ( h+c --   decrement c by w)
	w @ - c ! ;

: right ( addr -- addr2  move the pixel address "right")
	r @ + ;

: down ( addr -- addr2  move the pixel address "down")
	d @ + ;

: slant? ( -- h+c w>? )
	c @ h @ + dup w @ > ;

: colorit ( addr --   color the pixel at addr)
	color @ swap pixel! ;

: nextp ( addr -- addr2  move addr to the next pixel in the line. use h, w, and c)
	right slant? if w- down else c ! then ;

: lineto ( x y )
	line-setup over colorit 0 do nextp dup colorit loop drop ;



\ INTERACTIVE COMMANDS (Only useful for calling directly)
\ see also: rgb moveto clear

: l ( x y --   draw a line to x,y)
	lineto write-buffer ;

: test ( spacing --   spacing=how far to spread the lines out. try 12)
	clear
	width height min 1 - over / over *
	\ stack: spacing width
	dup 1+ 0 do 0 i moveto dup i - 0 lineto over +loop
	dup 1+ 0 do i over moveto 0 i lineto over +loop
	dup 1+ 0 do dup dup i - moveto i over lineto over +loop
	2drop
	write-buffer ;

Edit this page · home ·