haku2: rest of functionality (hopefully) & Rust->Zig FFI
This commit is contained in:
parent
01d4514a65
commit
550227da34
7 changed files with 716 additions and 38 deletions
59
crates/haku2/src/render.zig
Normal file
59
crates/haku2/src/render.zig
Normal file
|
@ -0,0 +1,59 @@
|
|||
const std = @import("std");
|
||||
|
||||
const Canvas = @import("canvas.zig").Canvas;
|
||||
const value = @import("value.zig");
|
||||
const Value = value.Value;
|
||||
const Vm = @import("vm.zig");
|
||||
|
||||
fn notAScribble(vm: *Vm, val: Value) Vm.Error {
|
||||
return vm.throw(
|
||||
"the brush returned a {s}, which cannot be drawn. return a scribble (e.g. fill, stroke, list) instead",
|
||||
.{val.typeName()},
|
||||
);
|
||||
}
|
||||
|
||||
fn renderRec(vm: *Vm, canvas: *Canvas, val: Value, depth: usize, max_depth: usize) !void {
|
||||
if (depth > max_depth) {
|
||||
return vm.throw(
|
||||
"the brush returned a scribble that's nested too deep ({} levels). try generating lists that aren't as deep using the (map (range min max) f) idiom, or flatten your lists using the flatten function",
|
||||
.{max_depth},
|
||||
);
|
||||
}
|
||||
if (val != .ref) return notAScribble(vm, val);
|
||||
|
||||
switch (val.ref.*) {
|
||||
.scribble => {
|
||||
try canvas.begin();
|
||||
|
||||
switch (val.ref.scribble.shape) {
|
||||
.point => |point| try canvas.line(point, point),
|
||||
.line => |line| try canvas.line(line.start, line.end),
|
||||
.rect => |rect| try canvas.rect(rect.top_left, rect.size),
|
||||
.circle => |circle| try canvas.circle(circle.center, circle.radius),
|
||||
}
|
||||
|
||||
switch (val.ref.scribble.action) {
|
||||
.stroke => |stroke| try canvas.stroke(value.rgbaTo8(stroke.color), stroke.thickness),
|
||||
.fill => |fill| try canvas.fill(value.rgbaTo8(fill.color)),
|
||||
}
|
||||
},
|
||||
|
||||
.list => {
|
||||
for (val.ref.list) |nested| {
|
||||
try vm.consumeFuel(&vm.fuel, 1);
|
||||
try renderRec(vm, canvas, nested, depth + 1, max_depth);
|
||||
}
|
||||
},
|
||||
|
||||
.shape => {
|
||||
return vm.throw("the brush returned a bare shape, which cannot be drawn. try wrapping your shape in a fill or a stroke: (fill #000 <shape>)", .{});
|
||||
},
|
||||
|
||||
else => return notAScribble(vm, val),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn render(vm: *Vm, canvas: *Canvas, max_depth: usize) !void {
|
||||
const val = try vm.pop();
|
||||
try renderRec(vm, canvas, val, 0, max_depth);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue