adding rect and fillrect to gfx2

This commit is contained in:
Irmen de Jong 2020-12-27 17:34:25 +01:00
parent cdcda27d07
commit dd82e550d5
7 changed files with 208 additions and 29 deletions

View File

@ -110,6 +110,8 @@ graphics {
sub circle(uword xcenter, ubyte ycenter, ubyte radius) {
; Midpoint algorithm
if radius==0
return
ubyte @zp ploty
ubyte @zp xx = radius
ubyte @zp yy = 0
@ -148,8 +150,10 @@ graphics {
sub disc(uword xcenter, ubyte ycenter, ubyte radius) {
; Midpoint algorithm, filled
ubyte xx = radius
ubyte yy = 0
if radius==0
return
ubyte @zp xx = radius
ubyte @zp yy = 0
byte decisionOver2 = 1-xx as byte
while xx>=yy {

View File

@ -98,7 +98,31 @@ gfx2 {
position(0, 0)
}
sub horizontal_line(uword x, uword y, ubyte length, ubyte color) {
sub rect(uword x, uword y, uword width, uword height, ubyte color) {
if width==0 or height==0
return
horizontal_line(x, y, width, color)
if height==1
return
horizontal_line(x, y+height-1, width, color)
vertical_line(x, y+1, height-2, color)
if width==1
return
vertical_line(x+width-1, y+1, height-2, color)
}
sub fillrect(uword x, uword y, uword width, uword height, ubyte color) {
if width==0
return
repeat height {
horizontal_line(x, y, width, color)
y++
}
}
sub horizontal_line(uword x, uword y, uword length, ubyte color) {
if length==0
return
when active_mode {
1 -> {
; 8bpp mode
@ -117,8 +141,108 @@ gfx2 {
}
}
sub circle(uword xcenter, uword ycenter, ubyte radius, ubyte color) {
sub vertical_line(uword x, uword y, uword height, ubyte color) {
; TODO optimize this to use vera special increment mode
repeat height {
plot(x, y, color)
y++
}
}
sub line(uword @zp x1, uword @zp y1, uword @zp x2, uword @zp y2, ubyte color) {
; Bresenham algorithm.
; This code special-cases various quadrant loops to allow simple ++ and -- operations.
; TODO rewrite this in optimized assembly
if y1>y2 {
; make sure dy is always positive to have only 4 instead of 8 special cases
swap(x1, x2)
swap(y1, y2)
}
word @zp dx = x2-x1 as word
word @zp dy = y2-y1 as word
if dx==0 {
vertical_line(x1, y1, abs(dy)+1 as uword, 255)
return
}
if dy==0 {
if x1>x2
x1=x2
horizontal_line(x1, y1, abs(dx)+1 as uword, 255)
return
}
word @zp d = 0
ubyte positive_ix = true
if dx < 0 {
dx = -dx
positive_ix = false
}
dx *= 2
dy *= 2
cx16.r14 = x1 ; internal plot X
if dx >= dy {
if positive_ix {
repeat {
plot(cx16.r14, y1, color)
if cx16.r14==x2
return
cx16.r14++
d += dy
if d > dx {
y1++
d -= dx
}
}
} else {
repeat {
plot(cx16.r14, y1, color)
if cx16.r14==x2
return
cx16.r14--
d += dy
if d > dx {
y1++
d -= dx
}
}
}
}
else {
if positive_ix {
repeat {
plot(cx16.r14, y1, color)
if y1 == y2
return
y1++
d += dx
if d > dy {
cx16.r14++
d -= dy
}
}
} else {
repeat {
plot(cx16.r14, y1, color)
if y1 == y2
return
y1++
d += dx
if d > dy {
cx16.r14--
d -= dy
}
}
}
}
}
sub circle(uword @zp xcenter, uword @zp ycenter, ubyte radius, ubyte color) {
; Midpoint algorithm.
if radius==0
return
ubyte @zp xx = radius
ubyte @zp yy = 0
word @zp decisionOver2 = (1 as word)-xx
@ -157,28 +281,29 @@ gfx2 {
}
}
sub disc(uword xcenter, uword ycenter, ubyte radius, ubyte color) {
sub disc(uword @zp xcenter, uword @zp ycenter, ubyte @zp radius, ubyte color) {
; Midpoint algorithm, filled
ubyte @zp xx = radius
if radius==0
return
ubyte @zp yy = 0
word @zp decisionOver2 = (1 as word)-xx
word @zp decisionOver2 = (1 as word)-radius
while xx>=yy {
horizontal_line(xcenter-xx, ycenter+yy, xx*2+1, color)
horizontal_line(xcenter-xx, ycenter-yy, xx*2+1, color)
horizontal_line(xcenter-yy, ycenter+xx, yy*2+1, color)
horizontal_line(xcenter-yy, ycenter-xx, yy*2+1, color)
while radius>=yy {
horizontal_line(xcenter-radius, ycenter+yy, radius*2+1, color)
horizontal_line(xcenter-radius, ycenter-yy, radius*2+1, color)
horizontal_line(xcenter-yy, ycenter+radius, yy*2+1, color)
horizontal_line(xcenter-yy, ycenter-radius, yy*2+1, color)
yy++
if decisionOver2<=0
decisionOver2 += (yy as word)*2+1
else {
xx--
decisionOver2 += (yy as word -xx)*2+1
radius--
decisionOver2 += (yy as word -radius)*2+1
}
}
}
sub plot(uword x, uword y, ubyte color) {
sub plot(uword @zp x, uword y, ubyte color) {
ubyte[8] bits = [128, 64, 32, 16, 8, 4, 2, 1]
uword addr
ubyte value
@ -204,7 +329,7 @@ gfx2 {
color = cx16.VERA_DATA0
}
sub position(uword x, uword y) {
sub position(uword @zp x, uword y) {
when active_mode {
0 -> {
cx16.r0 = y*(320/8) + x/8
@ -280,7 +405,7 @@ gfx2 {
}
}
sub text(uword x, uword y, ubyte color, uword sctextptr) {
sub text(uword @zp x, uword y, ubyte color, uword sctextptr) {
; -- Write some text at the given pixel position. The text string must be in screencode encoding (not petscii!).
; You must also have called text_charset() first to select and prepare the character set to use.
; NOTE: in monochrome (1bpp) screen modes, x position is currently constrained to mulitples of 8 !

View File

@ -44,6 +44,8 @@ graphics {
;cx16.GRAPH_draw_oval(false) ; currently this call is not implemented on cx16, does a BRK
; Midpoint algorithm
if radius==0
return
ubyte @zp xx = radius
ubyte @zp yy = 0
byte @zp decisionOver2 = 1-xx as byte
@ -94,8 +96,10 @@ graphics {
; cx16.r3 = radius*2
; cx16.GRAPH_draw_oval(true) ; currently this call is not implemented on cx16, does a BRK
ubyte xx = radius
ubyte yy = 0
if radius==0
return
ubyte @zp xx = radius
ubyte @zp yy = 0
byte decisionOver2 = 1-xx as byte
while xx>=yy {

View File

@ -94,7 +94,7 @@ Full-screen multicolor bitmap graphics routines, available on the Cx16 machine o
- clearing screen, switching screen mode
- drawing pixels
- drawing text inside the bitmap
- **TODO:** lines, circles, discs.
- lines, rectangles, circles, discs.
palette (cx16 only)

View File

@ -2,6 +2,7 @@
TODO
====
- implement gfx2's rect, fillrect, horizontal_line and vertical_line in graphics modules as well.
- detect variables that are written but never read - mark those as unused too and remove them, such as uword unused = memory("unused222", 20) - also remove the memory slab allocation
- hoist all variable declarations up to the subroutine scope *before* even the constant folding takes place (to avoid undefined symbol errors when referring to a variable from another nested scope in the subroutine)
- make it possible to use cpu opcodes such as 'nop' as variable names by prefixing all asm vars with something such as '_'

View File

@ -13,10 +13,6 @@ main {
for mode in modes {
gfx2.screen_mode(mode)
draw()
ubyte tp
for tp in 0 to 15 {
gfx2.text(19+tp,20+tp*11, 5, @"ScreenCODE text! 1234![]<>#$%&*()")
}
cx16.wait(200)
}
@ -25,6 +21,45 @@ main {
}
sub draw() {
gfx2.rect(10,10, 1, 1, 255)
gfx2.rect(20,10, 2, 1, 255)
gfx2.rect(30,10, 3, 1, 255)
gfx2.rect(40,10, 1, 2, 255)
gfx2.rect(50,10, 1, 3, 255)
gfx2.rect(60,10, 2, 2, 255)
gfx2.rect(70,10, 3, 3, 255)
gfx2.rect(80,10, 4, 4, 255)
gfx2.rect(90,10, 5, 5, 255)
gfx2.rect(100,10, 8, 8, 255)
gfx2.rect(110,10, 20, 5, 255)
gfx2.rect(80, 80, 200, 140, 255)
gfx2.fillrect(10,40, 1, 1, 5)
gfx2.fillrect(20,40, 2, 1, 5)
gfx2.fillrect(30,40, 3, 1, 5)
gfx2.fillrect(40,40, 1, 2, 5)
gfx2.fillrect(50,40, 1, 3, 5)
gfx2.fillrect(60,40, 2, 2, 5)
gfx2.fillrect(70,40, 3, 3, 5)
gfx2.fillrect(80,40, 4, 4, 5)
gfx2.fillrect(90,40, 5, 5, 5)
gfx2.fillrect(100,40, 8, 8, 5)
gfx2.fillrect(110,40, 20, 5, 5)
gfx2.fillrect(82, 82, 200-4, 140-4, 5)
ubyte i
for i in 0 to 255 step 4 {
uword x1 = ((gfx2.width-256)/2 as uword) + sin8u(i)
uword y1 = (gfx2.height-128)/2 + cos8u(i)/2
uword x2 = ((gfx2.width-64)/2 as uword) + sin8u(i)/4
uword y2 = (gfx2.height-64)/2 + cos8u(i)/4
gfx2.line(x1, y1, x2, y2, i)
}
cx16.wait(60)
gfx2.clear_screen()
ubyte radius
for radius in 110 downto 8 step -4 {
@ -32,10 +67,11 @@ main {
}
gfx2.disc(gfx2.width/2, gfx2.height/2, 108, 255)
ubyte tp
for tp in 0 to 15 {
gfx2.text(19+tp,20+tp*11, 5, @"ScreenCODE text! 1234![]<>#$%&*()")
}
}
}
gfx3 {
}

View File

@ -7,6 +7,15 @@ main {
sub start () {
uword length
if length>256 {
repeat length-1
gfx2.next_pixel(color)
} else {
repeat (length-1) as ubyte ; TODO lsb(length-1) doesn't work!?!?!?
gfx2.next_pixel(color)
}
test_stack.test()