From faf79367f6f84d8d77ef226a1309ec03251629fb Mon Sep 17 00:00:00 2001 From: Roman Pytkov Date: Thu, 26 Feb 2026 00:32:59 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A2=D0=BE=D0=BB=D1=89=D0=B8=D0=BD=D0=B0=20?= =?UTF-8?q?=D0=BA=D1=80=D1=83=D0=B3=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/render/cpu/ellipse.zig | 14 ++++++++++++-- src/render/cpu/line.zig | 4 ++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/render/cpu/ellipse.zig b/src/render/cpu/ellipse.zig index fcb12be..bd66724 100644 --- a/src/render/cpu/ellipse.zig +++ b/src/render/cpu/ellipse.zig @@ -6,14 +6,24 @@ const Color = @import("dvui").Color; const Object = Document.Object; const default_stroke: Color.PMA = .{ .r = 0, .g = 0, .b = 0, .a = 255 }; +const default_thickness: f32 = 2.0; -/// Эллипс с центром (0,0) и полуосями radii (обводка). +/// Эллипс с центром (0,0) и полуосями radii (обводка с учётом thickness). 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 thickness = if (obj.getProperty(.thickness)) |t| t.thickness else default_thickness; + + // Полуширина обводки в нормализованных единицах (d = (x/rx)² + (y/ry)², граница при d=1). + const min_r = @min(rx, ry); + const half_norm = thickness / (2.0 * min_r); + const inner = @max(0.0, 1.0 - half_norm); + const outer = 1.0 + half_norm; + const d_inner_sq = inner * inner; + const d_outer_sq = outer * outer; const corners = [_]struct { x: f32, y: f32 }{ .{ .x = -rx, .y = -ry }, @@ -51,7 +61,7 @@ pub fn draw(ctx: *DrawContext, obj: *const Object) void { const nx = loc.x / rx; const ny = loc.y / ry; const d = nx * nx + ny * ny; - if (d >= 0.9 and d <= 1.1) { + if (d >= d_inner_sq and d <= d_outer_sq) { ctx.blendPixelAtBuffer(@intCast(bx), @intCast(by), stroke); } } diff --git a/src/render/cpu/line.zig b/src/render/cpu/line.zig index 1315a71..4a9a4c5 100644 --- a/src/render/cpu/line.zig +++ b/src/render/cpu/line.zig @@ -30,11 +30,11 @@ pub fn drawLine(ctx: *DrawContext, x0: f32, y0: f32, x1: f32, y1: f32, color: Co drawLineInBuffer(ctx, b0.x, b0.y, b1.x, b1.y, color, thickness_px); } -/// Точка (px, py) лежит внутри/на круге с центром (cx, cy) и радиусом в квадрате r_sq. +/// Точка (px, py) лежит строго внутри круга с центром (cx, cy) и радиусом в квадрате r_sq (граница не включается). fn insideCircle(px: i32, py: i32, cx: i32, cy: i32, r_sq: i32) bool { const dx = px - cx; const dy = py - cy; - return dx * dx + dy * dy <= r_sq; + return dx * dx + dy * dy < r_sq; } /// Заливает круг в буфере (для скруглённых концов отрезка).