Первая растеризация
This commit is contained in:
59
src/render/cpu/ellipse.zig
Normal file
59
src/render/cpu/ellipse.zig
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user