2024-09-13 16:41:31 -05:00
|
|
|
.{math, memory} := @use("../../stn/src/lib.hb");
|
2024-09-14 05:26:32 -05:00
|
|
|
.{dt_get} := @use("../../dt_api/src/lib.hb");
|
2024-10-13 17:38:43 -05:00
|
|
|
.{Color, Image} := @use("lib.hb");
|
2024-10-12 15:39:09 -05:00
|
|
|
.{Vec2} := math
|
2024-09-13 16:41:31 -05:00
|
|
|
|
|
|
|
ctx := @as(Context, idk)
|
|
|
|
|
|
|
|
Context := struct {
|
|
|
|
fb: ^Color,
|
|
|
|
bb: ^Color,
|
|
|
|
buf: ^Color,
|
|
|
|
width: int,
|
|
|
|
height: int,
|
|
|
|
pixels: int,
|
|
|
|
double_buffer: bool,
|
|
|
|
}
|
|
|
|
|
|
|
|
init := fn(): void {
|
2024-10-13 17:38:43 -05:00
|
|
|
width := dt_get(int, "framebuffer/fb0/width\0")
|
|
|
|
height := dt_get(int, "framebuffer/fb0/height\0")
|
2024-09-13 16:41:31 -05:00
|
|
|
pixels := width * height
|
2024-10-13 17:38:43 -05:00
|
|
|
back_buffer := memory.alloc(Color, pixels * @bitcast(@sizeof(Color)))
|
2024-09-13 16:41:31 -05:00
|
|
|
ctx = Context.{
|
2024-10-13 17:38:43 -05:00
|
|
|
fb: dt_get(^Color, "framebuffer/fb0/ptr\0"),
|
2024-09-13 16:41:31 -05:00
|
|
|
bb: back_buffer,
|
|
|
|
buf: back_buffer,
|
|
|
|
width,
|
|
|
|
height,
|
|
|
|
pixels,
|
|
|
|
double_buffer: true,
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
doublebuffer := fn(enable: bool): void {
|
|
|
|
if enable {
|
|
|
|
ctx.buf = ctx.bb
|
|
|
|
} else {
|
|
|
|
ctx.buf = ctx.fb
|
|
|
|
}
|
|
|
|
ctx.double_buffer = enable
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
clear := fn(color: Color): void {
|
2024-10-13 17:38:43 -05:00
|
|
|
return @inline(memory.set, Color, &color, ctx.buf, @bitcast(ctx.pixels))
|
2024-09-13 16:41:31 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
sync := fn(): void {
|
2024-10-13 17:38:43 -05:00
|
|
|
return @inline(memory.copy, Color, ctx.buf, ctx.fb, @bitcast(ctx.pixels))
|
2024-09-13 16:41:31 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
width := fn(): int {
|
|
|
|
return ctx.width
|
|
|
|
}
|
|
|
|
|
|
|
|
height := fn(): int {
|
|
|
|
return ctx.height
|
|
|
|
}
|
|
|
|
|
|
|
|
screenidx := fn(x: int, y: int): int {
|
|
|
|
return x + ctx.width * y
|
|
|
|
}
|
|
|
|
|
2024-10-12 15:39:09 -05:00
|
|
|
put_pixel := fn(pos: Vec2(int), color: Color): void {
|
2024-09-13 16:41:31 -05:00
|
|
|
*(ctx.buf + @inline(screenidx, pos.x, pos.y)) = color
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2024-10-12 15:39:09 -05:00
|
|
|
put_filled_rect := fn(pos: Vec2(int), tr: Vec2(int), color: Color): void {
|
2024-09-13 16:41:31 -05:00
|
|
|
y := pos.y
|
2024-10-13 17:38:43 -05:00
|
|
|
end_y := y + tr.y
|
|
|
|
loop if y == end_y break else {
|
|
|
|
@inline(memory.set, Color, &color, ctx.buf + @inline(screenidx, pos.x, y), @bitcast(tr.x))
|
|
|
|
y += 1
|
2024-09-13 16:41:31 -05:00
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2024-10-12 15:39:09 -05:00
|
|
|
put_rect := fn(pos: Vec2(int), tr: Vec2(int), color: Color): void {
|
2024-09-13 16:41:31 -05:00
|
|
|
y := pos.y
|
2024-10-13 17:38:43 -05:00
|
|
|
end_y := y + tr.y
|
|
|
|
loop if y == end_y break else {
|
|
|
|
*(ctx.buf + @inline(screenidx, pos.x, y)) = color;
|
|
|
|
*(ctx.buf + @inline(screenidx, pos.x + tr.x, y)) = color
|
2024-09-13 16:41:31 -05:00
|
|
|
y += 1
|
|
|
|
}
|
2024-10-13 17:38:43 -05:00
|
|
|
@inline(memory.set, Color, &color, ctx.buf + @inline(screenidx, pos.x, y), @bitcast(tr.x))
|
|
|
|
@inline(memory.set, Color, &color, ctx.buf + @inline(screenidx, pos.x, y - tr.y), @bitcast(tr.x))
|
2024-09-13 16:41:31 -05:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2024-10-12 15:39:09 -05:00
|
|
|
put_line_low := fn(p0: Vec2(int), p1: Vec2(int), color: Color): void {
|
2024-09-13 16:41:31 -05:00
|
|
|
dx := p1.x - p0.x
|
|
|
|
dy := p1.y - p0.y
|
|
|
|
yi := 1
|
|
|
|
if dy < 0 {
|
2024-09-14 05:26:32 -05:00
|
|
|
yi = -1
|
|
|
|
dy = -dy
|
2024-09-13 16:41:31 -05:00
|
|
|
}
|
|
|
|
D := 2 * dy - dx
|
|
|
|
y := p0.y
|
|
|
|
x := p0.x
|
|
|
|
loop if x == p1.x break else {
|
|
|
|
*(ctx.buf + @inline(screenidx, x, y)) = color
|
|
|
|
if D > 0 {
|
|
|
|
y += yi
|
|
|
|
D += 2 * (dy - dx)
|
|
|
|
} else {
|
|
|
|
D += 2 * dy
|
|
|
|
}
|
|
|
|
x += 1
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2024-10-12 15:39:09 -05:00
|
|
|
put_line_high := fn(p0: Vec2(int), p1: Vec2(int), color: Color): void {
|
2024-09-13 16:41:31 -05:00
|
|
|
dx := p1.x - p0.x
|
|
|
|
dy := p1.y - p0.y
|
|
|
|
xi := 1
|
|
|
|
if dy < 0 {
|
2024-09-14 05:26:32 -05:00
|
|
|
xi = -1
|
|
|
|
dx = -dx
|
2024-09-13 16:41:31 -05:00
|
|
|
}
|
|
|
|
D := 2 * dx - dy
|
|
|
|
x := p0.x
|
|
|
|
y := p0.y
|
|
|
|
loop if y == p1.y break else {
|
|
|
|
*(ctx.buf + @inline(screenidx, x, y)) = color
|
|
|
|
if D > 0 {
|
|
|
|
x += xi
|
|
|
|
D += 2 * (dx - dy)
|
|
|
|
} else {
|
|
|
|
D += 2 * dx
|
|
|
|
}
|
|
|
|
y += 1
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2024-10-12 15:39:09 -05:00
|
|
|
put_line := fn(p0: Vec2(int), p1: Vec2(int), color: Color): void {
|
|
|
|
if math.abs(int, p1.y - p0.y) < math.abs(int, p1.x - p0.x) {
|
2024-09-13 16:41:31 -05:00
|
|
|
if p0.x > p1.x {
|
|
|
|
@inline(put_line_low, p1, p0, color)
|
|
|
|
} else {
|
|
|
|
@inline(put_line_low, p0, p1, color)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if p0.y > p1.y {
|
|
|
|
@inline(put_line_high, p1, p0, color)
|
|
|
|
} else {
|
|
|
|
@inline(put_line_high, p0, p1, color)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
set_height := fn(new: int): void {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
set_width := fn(new: int): void {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2024-10-12 15:39:09 -05:00
|
|
|
dimensions := fn(): Vec2(int) {
|
2024-09-13 16:41:31 -05:00
|
|
|
return .(ctx.width, ctx.height)
|
|
|
|
}
|
|
|
|
|
2024-10-12 15:39:09 -05:00
|
|
|
set_dimensions := fn(new: Vec2(int)): void {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2024-10-13 17:38:43 -05:00
|
|
|
put_image := fn(image: Image, pos: Vec2(int)): void {
|
|
|
|
y := 0
|
|
|
|
loop if y == image.height break else {
|
|
|
|
@inline(memory.copy, Color, image.buf + y * image.width, ctx.buf + @inline(screenidx, pos.x, pos.y + image.height - y), @intcast(image.width))
|
|
|
|
y += 1
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// peony-made
|
|
|
|
put_trirect := fn(pos: Vec2(int), size: Vec2(int), color0: Color, color1: Color): void {
|
|
|
|
step := Vec2(int).(1, 1)
|
|
|
|
if size.x < 0 {
|
|
|
|
step.x = -1
|
|
|
|
}
|
|
|
|
if size.y < 0 {
|
|
|
|
step.y = size.y / size.x
|
|
|
|
}
|
|
|
|
|
|
|
|
start_y := pos.y
|
|
|
|
target := pos + size
|
|
|
|
|
|
|
|
loop if pos.x == target.x break else {
|
|
|
|
put_vline(pos.x, pos.y, target.y, color0)
|
|
|
|
@inline(put_vline, pos.x, pos.y, start_y, color1)
|
|
|
|
pos += step
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// peony-made
|
|
|
|
put_vline := fn(x: int, y0: int, y1: int, color: Color): void {
|
|
|
|
if y1 < y0 {
|
|
|
|
tmp := y0
|
|
|
|
y0 = y1
|
|
|
|
y1 = tmp
|
|
|
|
}
|
|
|
|
y := y0
|
|
|
|
|
|
|
|
loop if y == y1 break else {
|
|
|
|
*(ctx.buf + @inline(screenidx, x, y)) = color
|
|
|
|
y += 1
|
|
|
|
}
|
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// peony-made
|
|
|
|
put_hline := fn(y: int, x0: int, x1: int, color: Color): void {
|
|
|
|
if x1 < x0 {
|
|
|
|
tmp := x0
|
|
|
|
x0 = x1
|
|
|
|
x1 = tmp
|
|
|
|
}
|
|
|
|
x := x0
|
|
|
|
|
|
|
|
loop if x == x1 break else {
|
|
|
|
*(ctx.buf + @inline(screenidx, x, y)) = color
|
|
|
|
x += 1
|
|
|
|
}
|
|
|
|
|
2024-09-13 16:41:31 -05:00
|
|
|
return
|
|
|
|
}
|