61 lines
2.5 KiB
Zig
61 lines
2.5 KiB
Zig
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) до end_point. Растеризация в координатах буфера (без пробелов при зуме).
|
|
pub fn draw(ctx: *DrawContext, obj: *const Object) void {
|
|
const ep_prop = obj.getProperty(.end_point) orelse return;
|
|
const end_x = ep_prop.end_point.x;
|
|
const end_y = ep_prop.end_point.y;
|
|
const stroke = if (obj.getProperty(.stroke_rgba)) |s| pipeline.rgbaToPma(s.stroke_rgba) else default_stroke;
|
|
|
|
drawLine(ctx, 0, 0, end_x, end_y, stroke);
|
|
}
|
|
|
|
/// Линия по локальным координатам фигуры: переводит концы в буфер и рисует в пикселях буфера.
|
|
pub fn drawLine(ctx: *DrawContext, x0: f32, y0: f32, x1: f32, y1: f32, color: Color.PMA) void {
|
|
const w0 = ctx.localToWorld(x0, y0);
|
|
const w1 = ctx.localToWorld(x1, y1);
|
|
const b0 = ctx.worldToBufferF(w0.x, w0.y);
|
|
const b1 = ctx.worldToBufferF(w1.x, w1.y);
|
|
const bx0: i32 = @intFromFloat(std.math.round(b0.x));
|
|
const by0: i32 = @intFromFloat(std.math.round(b0.y));
|
|
const bx1: i32 = @intFromFloat(std.math.round(b1.x));
|
|
const by1: i32 = @intFromFloat(std.math.round(b1.y));
|
|
drawLineInBuffer(ctx, bx0, by0, bx1, by1, color);
|
|
}
|
|
|
|
/// Брезенхем в координатах буфера; пиксели вне [0, buf_width) x [0, buf_height) пропускаются.
|
|
pub fn drawLineInBuffer(ctx: *DrawContext, bx0: i32, by0: i32, bx1: i32, by1: i32, color: Color.PMA) void {
|
|
const bw: i32 = @intCast(ctx.buf_width);
|
|
const bh: i32 = @intCast(ctx.buf_height);
|
|
const dx: i32 = @intCast(@abs(bx1 - bx0));
|
|
const dy: i32 = -@as(i32, @intCast(@abs(by1 - by0)));
|
|
const sx: i32 = if (bx0 < bx1) 1 else -1;
|
|
const sy: i32 = if (by0 < by1) 1 else -1;
|
|
var err = dx + dy;
|
|
var x = bx0;
|
|
var y = by0;
|
|
|
|
while (true) {
|
|
if (x >= 0 and x < bw and y >= 0 and y < bh) {
|
|
ctx.blendPixelAtBuffer(@intCast(x), @intCast(y), color);
|
|
}
|
|
if (x == bx1 and y == by1) break;
|
|
const e2 = 2 * err;
|
|
if (e2 >= dy) {
|
|
err += dy;
|
|
x += sx;
|
|
}
|
|
if (e2 <= dx) {
|
|
err += dx;
|
|
y += sy;
|
|
}
|
|
}
|
|
}
|