feat: implement stencils
This commit is contained in:
parent
ece4902a79
commit
32ec3cfdc0
|
@ -9,8 +9,8 @@
|
||||||
|
|
||||||
.dependencies = .{
|
.dependencies = .{
|
||||||
.zenolith = .{
|
.zenolith = .{
|
||||||
.url = "git+https://git.mzte.de/zenolith/zenolith.git#6f318242d7bb5dad079e5ad6421900744e5d03b4",
|
.url = "git+https://git.mzte.de/zenolith/zenolith.git#431cd4adf7f141a83887a7c09375628d79d1962a",
|
||||||
.hash = "122034a7efb688149b6251c939407e31b1574de418c947a9b25478957d91aad69f5f",
|
.hash = "12206042c1f7851e8b1626d5b57b6054ac9f01a0476525823d34ab62f543e31aec23",
|
||||||
},
|
},
|
||||||
|
|
||||||
.sdl2 = .{
|
.sdl2 = .{
|
||||||
|
|
|
@ -13,9 +13,15 @@ const Sdl2Painter = @This();
|
||||||
|
|
||||||
pub fn rect(
|
pub fn rect(
|
||||||
self: *Sdl2Painter,
|
self: *Sdl2Painter,
|
||||||
|
selfp: *zenolith.painter.Painter,
|
||||||
rectangle: zenolith.layout.Rectangle,
|
rectangle: zenolith.layout.Rectangle,
|
||||||
color: zenolith.Color,
|
color: zenolith.Color,
|
||||||
) !void {
|
) !void {
|
||||||
|
const clip_rect = if (selfp.data.peekStencil()) |stenc|
|
||||||
|
rectangle.intersection(stenc) orelse return
|
||||||
|
else
|
||||||
|
rectangle;
|
||||||
|
|
||||||
if (c.SDL_SetRenderDrawColor(
|
if (c.SDL_SetRenderDrawColor(
|
||||||
self.renderer,
|
self.renderer,
|
||||||
color.r,
|
color.r,
|
||||||
|
@ -24,25 +30,54 @@ pub fn rect(
|
||||||
color.a,
|
color.a,
|
||||||
) != 0) return error.Render;
|
) != 0) return error.Render;
|
||||||
|
|
||||||
if (c.SDL_RenderFillRect(self.renderer, &util.toSdlRect(rectangle)) != 0) return error.Render;
|
if (c.SDL_RenderFillRect(self.renderer, &util.toSdlRect(clip_rect)) != 0) return error.Render;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn texturedRect(
|
pub fn texturedRect(
|
||||||
self: *Sdl2Painter,
|
self: *Sdl2Painter,
|
||||||
|
selfp: *zenolith.painter.Painter,
|
||||||
src: zenolith.layout.Rectangle,
|
src: zenolith.layout.Rectangle,
|
||||||
dest: zenolith.layout.Rectangle,
|
dest: zenolith.layout.Rectangle,
|
||||||
texture: *zenolith.texture.Texture,
|
texture: *zenolith.texture.Texture,
|
||||||
) !void {
|
) !void {
|
||||||
|
const clip_dest = if (selfp.data.peekStencil()) |stenc|
|
||||||
|
dest.intersection(stenc) orelse return
|
||||||
|
else
|
||||||
|
dest;
|
||||||
|
|
||||||
|
// TODO: this is simply inacceptable... but it works
|
||||||
|
const x_scale: f64 = @as(f64, @floatFromInt(clip_dest.size.width)) /
|
||||||
|
@as(f64, @floatFromInt(dest.size.width));
|
||||||
|
const y_scale: f64 = @as(f64, @floatFromInt(clip_dest.size.height)) /
|
||||||
|
@as(f64, @floatFromInt(dest.size.height));
|
||||||
|
|
||||||
|
const x_mv_scale: f64 = @as(f64, @floatFromInt(clip_dest.pos.x - dest.pos.x)) /
|
||||||
|
@as(f64, @floatFromInt(dest.size.width));
|
||||||
|
const y_mv_scale: f64 = @as(f64, @floatFromInt(clip_dest.pos.y - dest.pos.y)) /
|
||||||
|
@as(f64, @floatFromInt(dest.size.height));
|
||||||
|
|
||||||
|
const clip_src = zenolith.layout.Rectangle{
|
||||||
|
.pos = .{
|
||||||
|
.x = src.pos.x + @as(i32, @intFromFloat(@as(f64, @floatFromInt(src.size.width)) * x_mv_scale)),
|
||||||
|
.y = src.pos.y + @as(i32, @intFromFloat(@as(f64, @floatFromInt(src.size.height)) * y_mv_scale)),
|
||||||
|
},
|
||||||
|
.size = .{
|
||||||
|
.width = @intFromFloat(@as(f64, @floatFromInt(src.size.width)) * x_scale),
|
||||||
|
.height = @intFromFloat(@as(f64, @floatFromInt(src.size.height)) * y_scale),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
if (c.SDL_RenderCopy(
|
if (c.SDL_RenderCopy(
|
||||||
self.renderer,
|
self.renderer,
|
||||||
(texture.downcast(Sdl2Texture) orelse unreachable).tex,
|
(texture.downcast(Sdl2Texture) orelse unreachable).tex,
|
||||||
&util.toSdlRect(src),
|
&util.toSdlRect(clip_src),
|
||||||
&util.toSdlRect(dest),
|
&util.toSdlRect(clip_dest),
|
||||||
) != 0) return error.Render;
|
) != 0) return error.Render;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn span(
|
pub fn span(
|
||||||
self: *Sdl2Painter,
|
self: *Sdl2Painter,
|
||||||
|
selfp: *zenolith.painter.Painter,
|
||||||
pos: zenolith.layout.Position,
|
pos: zenolith.layout.Position,
|
||||||
zspan: zenolith.text.Span,
|
zspan: zenolith.text.Span,
|
||||||
) !void {
|
) !void {
|
||||||
|
@ -57,18 +92,32 @@ pub fn span(
|
||||||
if (c.SDL_SetTextureAlphaMod(font.atlas, zspan.style.color.a) != 0) return error.Render;
|
if (c.SDL_SetTextureAlphaMod(font.atlas, zspan.style.color.a) != 0) return error.Render;
|
||||||
|
|
||||||
for (zspan.glyphs.items) |g| {
|
for (zspan.glyphs.items) |g| {
|
||||||
|
// This is sound as the span will have already gotten the glyph from the font,
|
||||||
|
// causing it to add it to the map.
|
||||||
|
const sprite_rect = font.getSprite(g.glyph.codepoint, zspan.style.size) orelse unreachable;
|
||||||
|
|
||||||
|
const rectangle = zenolith.layout.Rectangle{
|
||||||
|
.pos = pos.add(g.position),
|
||||||
|
.size = g.glyph.size,
|
||||||
|
};
|
||||||
|
|
||||||
|
const clip_rect = if (selfp.data.peekStencil()) |stenc|
|
||||||
|
rectangle.intersection(stenc) orelse continue
|
||||||
|
else
|
||||||
|
rectangle;
|
||||||
|
|
||||||
|
std.debug.assert(std.meta.eql(sprite_rect.size, rectangle.size));
|
||||||
|
|
||||||
|
const sprite_clip = zenolith.layout.Rectangle{
|
||||||
|
.pos = sprite_rect.pos.add(clip_rect.pos.sub(rectangle.pos)),
|
||||||
|
.size = clip_rect.size,
|
||||||
|
};
|
||||||
|
|
||||||
if (c.SDL_RenderCopy(
|
if (c.SDL_RenderCopy(
|
||||||
self.renderer,
|
self.renderer,
|
||||||
font.atlas,
|
font.atlas,
|
||||||
&util.toSdlRect(
|
&util.toSdlRect(sprite_clip),
|
||||||
// This is sound as the span will have already gotten the glyph from the font,
|
&util.toSdlRect(clip_rect),
|
||||||
// causing it to add it to the map.
|
|
||||||
font.getSprite(g.glyph.codepoint, zspan.style.size) orelse unreachable,
|
|
||||||
),
|
|
||||||
&util.toSdlRect(.{
|
|
||||||
.pos = pos.add(g.position),
|
|
||||||
.size = g.glyph.size,
|
|
||||||
}),
|
|
||||||
) != 0) return error.Render;
|
) != 0) return error.Render;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -290,7 +290,11 @@ pub fn run(
|
||||||
if (c.SDL_SetRenderDrawColor(self.renderer, 0, 0, 0, 0xff) != 0) return error.Render;
|
if (c.SDL_SetRenderDrawColor(self.renderer, 0, 0, 0, 0xff) != 0) return error.Render;
|
||||||
if (c.SDL_RenderClear(self.renderer) != 0) return error.Render;
|
if (c.SDL_RenderClear(self.renderer) != 0) return error.Render;
|
||||||
|
|
||||||
var painter = zenolith.painter.Painter.create(Sdl2Painter{ .renderer = self.renderer }, {});
|
var painter = zenolith.painter.Painter.create(
|
||||||
|
Sdl2Painter{ .renderer = self.renderer },
|
||||||
|
zenolith.painter.PainterData.init(root.data.allocator),
|
||||||
|
);
|
||||||
|
defer painter.data.deinit();
|
||||||
const current_time = std.time.nanoTimestamp();
|
const current_time = std.time.nanoTimestamp();
|
||||||
try zenolith.treevent.fire(root, zenolith.treevent.Draw{
|
try zenolith.treevent.fire(root, zenolith.treevent.Draw{
|
||||||
.painter = &painter,
|
.painter = &painter,
|
||||||
|
|
Loading…
Reference in a new issue