Первая растеризация

This commit is contained in:
2026-02-24 21:56:15 +03:00
parent ef768e9fe7
commit e5dd455d14
8 changed files with 376 additions and 85 deletions

View File

@@ -0,0 +1,59 @@
const std = @import("std");
const Document = @import("../../models/Document.zig");
const pipeline = @import("pipeline.zig");
const DrawContext = pipeline.DrawContext;
const Color = @import("dvui").Color;
const Object = Document.Object;
const default_stroke: Color.PMA = .{ .r = 0, .g = 0, .b = 0, .a = 255 };
/// Рисует эллипс: центр (0,0), полуоси radii. Растеризация в координатах буфера (обводка кольцом).
pub fn draw(ctx: *DrawContext, obj: *const Object) void {
const r_prop = obj.getProperty(.radii) orelse return;
const rx = r_prop.radii.x;
const ry = r_prop.radii.y;
if (rx <= 0 or ry <= 0) return;
const stroke = if (obj.getProperty(.stroke_rgba)) |s| pipeline.rgbaToPma(s.stroke_rgba) else default_stroke;
const corners = [_]struct { x: f32, y: f32 }{
.{ .x = -rx, .y = -ry },
.{ .x = rx, .y = -ry },
.{ .x = rx, .y = ry },
.{ .x = -rx, .y = ry },
};
const w0 = ctx.localToWorld(corners[0].x, corners[0].y);
const b0 = ctx.worldToBufferF(w0.x, w0.y);
var min_bx: f32 = b0.x;
var min_by: f32 = b0.y;
var max_bx: f32 = b0.x;
var max_by: f32 = b0.y;
for (corners[1..]) |c| {
const w = ctx.localToWorld(c.x, c.y);
const b = ctx.worldToBufferF(w.x, w.y);
min_bx = @min(min_bx, b.x);
min_by = @min(min_by, b.y);
max_bx = @max(max_bx, b.x);
max_by = @max(max_by, b.y);
}
const buf_w: i32 = @intCast(ctx.buf_width);
const buf_h: i32 = @intCast(ctx.buf_height);
const x0: i32 = @max(0, @as(i32, @intFromFloat(std.math.floor(min_bx))));
const y0: i32 = @max(0, @as(i32, @intFromFloat(std.math.floor(min_by))));
const x1: i32 = @min(buf_w, @as(i32, @intFromFloat(std.math.ceil(max_bx))) + 1);
const y1: i32 = @min(buf_h, @as(i32, @intFromFloat(std.math.ceil(max_by))) + 1);
var by: i32 = y0;
while (by < y1) : (by += 1) {
var bx: i32 = x0;
while (bx < x1) : (bx += 1) {
const w = ctx.bufferToWorld(@as(f32, @floatFromInt(bx)) + 0.5, @as(f32, @floatFromInt(by)) + 0.5);
const loc = ctx.worldToLocal(w.x, w.y);
const nx = loc.x / rx;
const ny = loc.y / ry;
const d = nx * nx + ny * ny;
if (d >= 0.9 and d <= 1.1) {
ctx.blendPixelAtBuffer(@intCast(bx), @intCast(by), stroke);
}
}
}
}