diff --git a/src/render/cpu/ellipse.zig b/src/render/cpu/ellipse.zig index bd66724..82d59c3 100644 --- a/src/render/cpu/ellipse.zig +++ b/src/render/cpu/ellipse.zig @@ -52,14 +52,41 @@ pub fn draw(ctx: *DrawContext, obj: *const Object) void { 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); + // Один раз считаем аффин buffer -> local, чтобы в цикле не вызывать cos/sin и лишние функции. + const t = &ctx.transform; + const ctx_sx = if (ctx.scale_x != 0) ctx.scale_x else 1.0; + const ctx_sy = if (ctx.scale_y != 0) ctx.scale_y else 1.0; + const inv_ctx_sx = 1.0 / ctx_sx; + const inv_ctx_sy = 1.0 / ctx_sy; + const vx = @as(f32, @floatFromInt(ctx.visible_rect.x)); + const vy = @as(f32, @floatFromInt(ctx.visible_rect.y)); + const t_sx = if (t.scale.scale_x != 0) t.scale.scale_x else 1.0; + const t_sy = if (t.scale.scale_y != 0) t.scale.scale_y else 1.0; + const ca = std.math.cos(-t.angle); + const sa = std.math.sin(-t.angle); + const dx_off = vx * inv_ctx_sx - t.position.x; + const dy_off = vy * inv_ctx_sy - t.position.y; + const loc_x_off = (dx_off * ca - dy_off * sa) / t_sx; + const loc_y_off = (dx_off * sa + dy_off * ca) / t_sy; + const m00 = inv_ctx_sx * ca / t_sx; + const m01 = -inv_ctx_sy * sa / t_sx; + const m10 = inv_ctx_sx * sa / t_sy; + const m11 = inv_ctx_sy * ca / t_sy; + const inv_rx = 1.0 / rx; + const inv_ry = 1.0 / ry; + var by: i32 = y0; while (by < y1) : (by += 1) { + const buf_y = @as(f32, @floatFromInt(by)) + 0.5; + const row_loc_x_off = buf_y * m01 + loc_x_off; + const row_loc_y_off = buf_y * m11 + loc_y_off; 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 buf_x = @as(f32, @floatFromInt(bx)) + 0.5; + const loc_x = buf_x * m00 + row_loc_x_off; + const loc_y = buf_x * m10 + row_loc_y_off; + const nx = loc_x * inv_rx; + const ny = loc_y * inv_ry; const d = nx * nx + ny * ny; if (d >= d_inner_sq and d <= d_outer_sq) { ctx.blendPixelAtBuffer(@intCast(bx), @intCast(by), stroke);