.{math, memory} := @use("../../stn/src/lib.hb"); .{dt_get} := @use("../../dt_api/src/lib.hb"); .{Color, Image} := @use("lib.hb"); .{Vec2} := math ctx := @as(Context, idk) Context := struct { fb: ^Color, bb: ^Color, buf: ^Color, width: int, height: int, pixels: int, double_buffer: bool, } init := fn(): void { width := dt_get(int, "framebuffer/fb0/width\0") height := dt_get(int, "framebuffer/fb0/height\0") pixels := width * height back_buffer := memory.alloc(Color, pixels * @bitcast(@sizeof(Color))) ctx = Context.{ fb: dt_get(^Color, "framebuffer/fb0/ptr\0"), 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 { return @inline(memory.set, Color, &color, ctx.buf, @bitcast(ctx.pixels)) } sync := fn(): void { return @inline(memory.copy, Color, ctx.buf, ctx.fb, @bitcast(ctx.pixels)) } width := fn(): int { return ctx.width } height := fn(): int { return ctx.height } screenidx := fn(x: int, y: int): int { return x + ctx.width * y } put_pixel := fn(pos: Vec2(int), color: Color): void { *(ctx.buf + @inline(screenidx, pos.x, pos.y)) = color return } put_filled_rect := fn(pos: Vec2(int), tr: Vec2(int), color: Color): void { start_idx := @inline(screenidx, pos.x, pos.y) end_idx := @inline(screenidx, pos.x, pos.y + tr.y) loop if start_idx >= end_idx break else { @inline(memory.set, Color, &color, ctx.buf + start_idx, @bitcast(tr.x)) start_idx += ctx.width } return } put_rect := fn(pos: Vec2(int), tr: Vec2(int), color: Color): void { start_idx := @inline(screenidx, pos.x, pos.y) end_idx := @inline(screenidx, pos.x, pos.y + tr.y) right_start_idx := @inline(screenidx, pos.x + tr.x, pos.y) loop if start_idx > end_idx break else { *(ctx.buf + start_idx) = color; *(ctx.buf + right_start_idx) = color start_idx += ctx.width right_start_idx += ctx.width } @inline(memory.set, Color, &color, ctx.buf + @inline(screenidx, pos.x, pos.y), @bitcast(tr.x + 1)) @inline(memory.set, Color, &color, ctx.buf + @inline(screenidx, pos.x, pos.y + tr.y), @bitcast(tr.x + 1)) return } put_line_low := fn(p0: Vec2(int), p1: Vec2(int), color: Color): void { dx := p1.x - p0.x dy := p1.y - p0.y yi := 1 if dy < 0 { yi = -1 dy = -dy } 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 } put_line_high := fn(p0: Vec2(int), p1: Vec2(int), color: Color): void { dx := p1.x - p0.x dy := p1.y - p0.y xi := 1 if dy < 0 { xi = -1 dx = -dx } 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 } 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) { 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 } dimensions := fn(): Vec2(int) { return .(ctx.width, ctx.height) } set_dimensions := fn(new: Vec2(int)): void { return } 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 start_idx := @inline(screenidx, pos.x, pos.y) end_idx := @inline(screenidx, pos.x, pos.y + image.height) cursor := image.width * image.height loop if start_idx >= end_idx break else { @inline(memory.copy, Color, image.buf + cursor, ctx.buf + start_idx, @intcast(image.width)) start_idx += ctx.width cursor -= image.width } 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 } return }