const std = @import("std"); const Document = @import("../../models/Document.zig"); const pipeline = @import("pipeline.zig"); const line = @import("line.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 }; const default_fill: Color.PMA = .{ .r = 0, .g = 0, .b = 0, .a = 0 }; const default_thickness: f32 = 2.0; /// Ломаная по точкам, обводка stroke_rgba. При closed — отрезок последняя–первая точка и заливка fill_rgba. pub fn draw( ctx: *DrawContext, obj: *const Object, allocator: std.mem.Allocator, ) !void { const p_prop = obj.getProperty(.points) orelse return; const pts = p_prop.points; if (pts.len < 2) return; const stroke = if (obj.getProperty(.stroke_rgba)) |s| pipeline.rgbaToPma(s.stroke_rgba) else default_stroke; const thickness = if (obj.getProperty(.thickness)) |t| t.thickness else default_thickness; const closed = if (obj.getProperty(.closed)) |c| c.closed else false; const filled = if (obj.getProperty(.filled)) |f| f.filled else true; const fill_color = if (obj.getProperty(.fill_rgba)) |f| pipeline.rgbaToPma(f.fill_rgba) else default_fill; const buffer = try allocator.alloc(Color.PMA, ctx.buf_width * ctx.buf_height); @memset(buffer, .{ .r = 0, .g = 0, .b = 0, .a = 0 }); defer allocator.free(buffer); var copy_ctx = ctx.*; copy_ctx.pixels = buffer; copy_ctx.replace_mode = true; const do_fill = closed and filled; if (do_fill) { copy_ctx.startFill(allocator) catch return; } var i: usize = 0; while (i + 1 < pts.len) : (i += 1) { line.drawLine(©_ctx, pts[i].x, pts[i].y, pts[i + 1].x, pts[i + 1].y, stroke, thickness, true); } if (closed and pts.len >= 2) { const last = pts.len - 1; line.drawLine(©_ctx, pts[last].x, pts[last].y, pts[0].x, pts[0].y, stroke, thickness, true); } if (do_fill) { copy_ctx.stopFill(allocator, fill_color); } ctx.compositeDrawerContext(©_ctx, copy_ctx.transform.opacity); }