Первая растеризация
This commit is contained in:
60
src/render/cpu/line.zig
Normal file
60
src/render/cpu/line.zig
Normal file
@@ -0,0 +1,60 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user