diff --git a/src/models/shape/ellipse.zig b/src/models/shape/ellipse.zig index d18dcf1..fc1a192 100644 --- a/src/models/shape/ellipse.zig +++ b/src/models/shape/ellipse.zig @@ -9,6 +9,9 @@ const shape_mod = @import("shape.zig"); pub const default_shape_properties = [_]Property{ .{ .data = .{ .radii = .{ .x = 50, .y = 50 } } }, .{ .data = .{ .arc_percent = 100.0 } }, + .{ .data = .{ .closed = true } }, + .{ .data = .{ .filled = false } }, + .{ .data = .{ .fill_rgba = 0x000000FF } }, }; /// Теги обязательных свойств. diff --git a/src/render/cpu/ellipse.zig b/src/render/cpu/ellipse.zig index bfdd7c1..c5dd031 100644 --- a/src/render/cpu/ellipse.zig +++ b/src/render/cpu/ellipse.zig @@ -2,6 +2,7 @@ const std = @import("std"); const std_math = std.math; 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 basic_models = @import("../../models/basic_models.zig"); @@ -9,6 +10,7 @@ const Point2_f = basic_models.Point2_f; 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; /// Эллипс с центром (0,0) и полуосями radii. Обводка — полоса расстояния до контура (чёткая линия, не круги). @@ -23,6 +25,10 @@ pub fn draw(ctx: *DrawContext, obj: *const Object, allocator: std.mem.Allocator) 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 arc_percent = std_math.clamp(if (obj.getProperty(.arc_percent)) |p| p.arc_percent else 100.0, 0.0, 100.0); + const closed = if (obj.getProperty(.closed)) |c| c.closed else true; + const filled = if (obj.getProperty(.filled)) |f| f.filled else false; + const fill_color = if (obj.getProperty(.fill_rgba)) |f| pipeline.rgbaToPma(f.fill_rgba) else default_fill; + const do_fill = filled and (closed or arc_percent >= 100.0); const t = &ctx.transform; const min_r = @min(rx, ry); @@ -66,6 +72,10 @@ pub fn draw(ctx: *DrawContext, obj: *const Object, allocator: std.mem.Allocator) stroke_ctx.pixels = buffer; stroke_ctx.replace_mode = true; + if (do_fill) { + stroke_ctx.startFill(allocator) catch return; + } + const inv_rx = 1.0 / rx; const inv_ry = 1.0 / ry; const arc_len = 2.0 * std_math.pi * arc_percent / 100.0; @@ -91,5 +101,16 @@ pub fn draw(ctx: *DrawContext, obj: *const Object, allocator: std.mem.Allocator) } } + if (closed and arc_percent < 100.0) { + const end_x = rx * std_math.sin(arc_len); + const end_y = ry * std_math.cos(arc_len); + line.drawLine(&stroke_ctx, 0, 0, 0, ry, stroke, thickness, false); + line.drawLine(&stroke_ctx, 0, 0, end_x, end_y, stroke, thickness, false); + } + + if (do_fill) { + stroke_ctx.stopFill(allocator, fill_color); + } + ctx.compositeDrawerContext(&stroke_ctx, t.opacity); }