Первая растеризация
This commit is contained in:
@@ -3,8 +3,8 @@ const builtin = @import("builtin");
|
||||
const dvui = @import("dvui");
|
||||
const RenderEngine = @import("RenderEngine.zig").RenderEngine;
|
||||
const Document = @import("../models/Document.zig");
|
||||
const shape = @import("../models/shape/shape.zig");
|
||||
const basic_models = @import("../models/basic_models.zig");
|
||||
const cpu_draw = @import("cpu/draw.zig");
|
||||
const ImageSize = basic_models.ImageSize;
|
||||
const ImageRect = basic_models.ImageRect;
|
||||
const Allocator = std.mem.Allocator;
|
||||
@@ -174,94 +174,15 @@ pub fn renderEngine(self: *CpuRenderEngine) RenderEngine {
|
||||
return .{ .cpu = self };
|
||||
}
|
||||
|
||||
/// Растеризует документ: фон + контуры AABB всех объектов по getLocalBounds и position.
|
||||
/// Растеризует документ: фон + рекурсивная отрисовка фигур через конвейер (трансформ, прозрачность, наложение).
|
||||
pub fn renderDocument(self: *CpuRenderEngine, document: *const Document, canvas_size: ImageSize, visible_rect: ImageRect) !?dvui.Texture {
|
||||
const width = visible_rect.w;
|
||||
const height = visible_rect.h;
|
||||
const pixels = try self._allocator.alloc(Color.PMA, @as(usize, width) * height);
|
||||
defer self._allocator.free(pixels);
|
||||
|
||||
const scale_x: f32 = if (document.size.width > 0) @as(f32, @floatFromInt(canvas_size.w)) / document.size.width else 0;
|
||||
const scale_y: f32 = if (document.size.height > 0) @as(f32, @floatFromInt(canvas_size.h)) / document.size.height else 0;
|
||||
|
||||
// Фон
|
||||
for (pixels) |*p| p.* = .{ .r = 255, .g = 255, .b = 255, .a = 255 };
|
||||
|
||||
const default_stroke: Color.PMA = .{ .r = 0, .g = 0, .b = 0, .a = 255 };
|
||||
for (document.objects.items) |*obj| {
|
||||
const local_bounds = shape.getLocalBounds(obj) catch continue;
|
||||
const pos = if (obj.getProperty(.position)) |p| p.position else basic_models.Point2{ .x = 0, .y = 0 };
|
||||
const world_x = local_bounds.x + pos.x;
|
||||
const world_y = local_bounds.y + pos.y;
|
||||
const px_min_x: i32 = @intFromFloat(world_x * scale_x);
|
||||
const px_min_y: i32 = @intFromFloat(world_y * scale_y);
|
||||
const px_max_x: i32 = @intFromFloat((world_x + local_bounds.w) * scale_x);
|
||||
const px_max_y: i32 = @intFromFloat((world_y + local_bounds.h) * scale_y);
|
||||
|
||||
const stroke = if (obj.getProperty(.stroke_rgba)) |s| rgbaToPma(s.stroke_rgba) else default_stroke;
|
||||
drawRectOutline(pixels, width, height, visible_rect, px_min_x, px_min_y, px_max_x, px_max_y, stroke);
|
||||
}
|
||||
cpu_draw.drawDocument(pixels, width, height, visible_rect, document, canvas_size);
|
||||
|
||||
return try dvui.textureCreate(pixels, width, height, .nearest);
|
||||
}
|
||||
|
||||
fn rgbaToPma(rgba: u32) Color.PMA {
|
||||
const r: u8 = @intCast((rgba >> 0) & 0xFF);
|
||||
const g: u8 = @intCast((rgba >> 8) & 0xFF);
|
||||
const b: u8 = @intCast((rgba >> 16) & 0xFF);
|
||||
const a: u8 = @intCast((rgba >> 24) & 0xFF);
|
||||
if (a == 0) return .{ .r = 0, .g = 0, .b = 0, .a = 0 };
|
||||
const af: f32 = @as(f32, @floatFromInt(a)) / 255.0;
|
||||
return .{
|
||||
.r = @intFromFloat(@as(f32, @floatFromInt(r)) * af),
|
||||
.g = @intFromFloat(@as(f32, @floatFromInt(g)) * af),
|
||||
.b = @intFromFloat(@as(f32, @floatFromInt(b)) * af),
|
||||
.a = a,
|
||||
};
|
||||
}
|
||||
|
||||
fn drawRectOutline(
|
||||
pixels: []Color.PMA,
|
||||
buf_width: u32,
|
||||
buf_height: u32,
|
||||
visible_rect: ImageRect,
|
||||
px_min_x: i32,
|
||||
px_min_y: i32,
|
||||
px_max_x: i32,
|
||||
px_max_y: i32,
|
||||
color: Color.PMA,
|
||||
) void {
|
||||
_ = buf_height;
|
||||
const vx: i32 = @intCast(visible_rect.x);
|
||||
const vy: i32 = @intCast(visible_rect.y);
|
||||
const vw: i32 = @intCast(visible_rect.w);
|
||||
const vh: i32 = @intCast(visible_rect.h);
|
||||
|
||||
const x0 = std.math.clamp(px_min_x, vx, vx + vw - 1);
|
||||
const x1 = std.math.clamp(px_max_x, vx, vx + vw - 1);
|
||||
const y0 = std.math.clamp(px_min_y, vy, vy + vh - 1);
|
||||
const y1 = std.math.clamp(px_max_y, vy, vy + vh - 1);
|
||||
|
||||
const y_edges = [_]i32{ y0, y1 };
|
||||
for (y_edges) |cy| {
|
||||
if (cy < vy or cy >= vy + vh) continue;
|
||||
const by: u32 = @intCast(cy - vy);
|
||||
var cx = x0;
|
||||
while (cx <= x1) : (cx += 1) {
|
||||
if (cx < vx or cx >= vx + vw) continue;
|
||||
const bx: u32 = @intCast(cx - vx);
|
||||
pixels[by * buf_width + bx] = color;
|
||||
}
|
||||
}
|
||||
const x_edges = [_]i32{ x0, x1 };
|
||||
for (x_edges) |cx| {
|
||||
if (cx < vx or cx >= vx + vw) continue;
|
||||
const bx: u32 = @intCast(cx - vx);
|
||||
var cy = y0;
|
||||
while (cy <= y1) : (cy += 1) {
|
||||
if (cy < vy or cy >= vy + vh) continue;
|
||||
const by: u32 = @intCast(cy - vy);
|
||||
pixels[by * buf_width + bx] = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user