feat: implement stencils
This commit is contained in:
parent
ece4902a79
commit
32ec3cfdc0
|
@ -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 = .{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue