1
0
Fork 0

feat: implement stencils

This commit is contained in:
LordMZTE 2024-02-19 22:49:44 +01:00
parent ece4902a79
commit 32ec3cfdc0
Signed by: LordMZTE
GPG key ID: B64802DC33A64FF6
3 changed files with 68 additions and 15 deletions

View file

@ -9,8 +9,8 @@
.dependencies = .{
.zenolith = .{
.url = "git+https://git.mzte.de/zenolith/zenolith.git#6f318242d7bb5dad079e5ad6421900744e5d03b4",
.hash = "122034a7efb688149b6251c939407e31b1574de418c947a9b25478957d91aad69f5f",
.url = "git+https://git.mzte.de/zenolith/zenolith.git#431cd4adf7f141a83887a7c09375628d79d1962a",
.hash = "12206042c1f7851e8b1626d5b57b6054ac9f01a0476525823d34ab62f543e31aec23",
},
.sdl2 = .{

View file

@ -13,9 +13,15 @@ const Sdl2Painter = @This();
pub fn rect(
self: *Sdl2Painter,
selfp: *zenolith.painter.Painter,
rectangle: zenolith.layout.Rectangle,
color: zenolith.Color,
) !void {
const clip_rect = if (selfp.data.peekStencil()) |stenc|
rectangle.intersection(stenc) orelse return
else
rectangle;
if (c.SDL_SetRenderDrawColor(
self.renderer,
color.r,
@ -24,25 +30,54 @@ pub fn rect(
color.a,
) != 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(
self: *Sdl2Painter,
selfp: *zenolith.painter.Painter,
src: zenolith.layout.Rectangle,
dest: zenolith.layout.Rectangle,
texture: *zenolith.texture.Texture,
) !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(
self.renderer,
(texture.downcast(Sdl2Texture) orelse unreachable).tex,
&util.toSdlRect(src),
&util.toSdlRect(dest),
&util.toSdlRect(clip_src),
&util.toSdlRect(clip_dest),
) != 0) return error.Render;
}
pub fn span(
self: *Sdl2Painter,
selfp: *zenolith.painter.Painter,
pos: zenolith.layout.Position,
zspan: zenolith.text.Span,
) !void {
@ -57,18 +92,32 @@ pub fn span(
if (c.SDL_SetTextureAlphaMod(font.atlas, zspan.style.color.a) != 0) return error.Render;
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(
self.renderer,
font.atlas,
&util.toSdlRect(
// This is sound as the span will have already gotten the glyph from the font,
// 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,
}),
&util.toSdlRect(sprite_clip),
&util.toSdlRect(clip_rect),
) != 0) return error.Render;
}
}

View file

@ -290,7 +290,11 @@ pub fn run(
if (c.SDL_SetRenderDrawColor(self.renderer, 0, 0, 0, 0xff) != 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();
try zenolith.treevent.fire(root, zenolith.treevent.Draw{
.painter = &painter,