From 8f462cc93b2c1cd31b90ab07222718b061f40fe0 Mon Sep 17 00:00:00 2001 From: Roman Pytkov Date: Sat, 20 Dec 2025 21:16:52 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9C=D0=B8=D0=BD=D0=B8=D1=87=D0=B8=D1=81?= =?UTF-8?q?=D1=82=D0=BA=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Canvas.zig | 10 ++----- src/main.zig | 71 ++++++++++++++++---------------------------------- 2 files changed, 24 insertions(+), 57 deletions(-) diff --git a/src/Canvas.zig b/src/Canvas.zig index 811098b..804ac59 100644 --- a/src/Canvas.zig +++ b/src/Canvas.zig @@ -44,11 +44,7 @@ pub fn redrawGradient(self: *Canvas) !void { const full_w: u32 = full.w; const full_h: u32 = full.h; - var vis: ImageRect = self.visible_rect orelse ImageRect{ .x = 0, .y = 0, .w = 0, .h = 0 }; - if (vis.w == 0 or vis.h == 0) { - // Если viewport ещё не известен, рисуем целиком. - vis = .{ .x = 0, .y = 0, .w = full_w, .h = full_h }; - } + const vis: ImageRect = self.visible_rect orelse ImageRect{ .x = 0, .y = 0, .w = 0, .h = 0 }; if (vis.w == 0 or vis.h == 0) { if (self.texture) |tex| { @@ -123,7 +119,7 @@ pub fn getScaledImageSize(self: Canvas) ImageRect { }; } -/// Обновить видимую часть изображения (в пикселях изображения) и сохранить в `visible_rect`. +/// Обновить видимую часть изображения (в пикселях холста) и сохранить в `visible_rect`. /// /// `viewport` и `scroll_offset` ожидаются в *physical* пикселях (т.е. уже умноженные на windowNaturalScale). /// @@ -135,8 +131,6 @@ pub fn updateVisibleImageRect(self: *Canvas, viewport: dvui.Rect, scroll_offset: changed |= next.x != vis.x or next.y != vis.y or next.w != vis.w or next.h != vis.h; } self.visible_rect = next; - std.debug.print("Visible: {any}\n", .{next}); - if (changed or self.texture == null) { try self.redrawGradient(); } diff --git a/src/main.zig b/src/main.zig index f343d7a..851fddc 100644 --- a/src/main.zig +++ b/src/main.zig @@ -140,36 +140,9 @@ fn gui_frame(ctx: *WindowContext) bool { }, ); { - // Canvas область внутри scroll area (полный размер изображения). - // Важно: мы НЕ двигаем отдельный image-виджет под visible_rect; - // вместо этого рисуем частичную текстуру внутри этой области со сдвигом. - const natural_scale = dvui.windowNaturalScale(); - const img_area_divider = if (canvas.native_scaling) 1 else natural_scale; + const natural_scale = if (canvas.native_scaling) 1 else dvui.windowNaturalScale(); const img_size = canvas.getScaledImageSize(); - var img_area = dvui.box( - @src(), - .{ .dir = .vertical }, - .{ - .background = false, - .margin = .{ - .x = @as(f32, @floatFromInt(img_size.x)) / img_area_divider, - .y = @as(f32, @floatFromInt(img_size.y)) / img_area_divider, - .w = @as(f32, @floatFromInt(img_size.x)) / img_area_divider, - .h = @as(f32, @floatFromInt(img_size.y)) / img_area_divider, - }, - .min_size_content = .{ - .w = @as(f32, @floatFromInt(img_size.w)) / img_area_divider, - .h = @as(f32, @floatFromInt(img_size.h)) / img_area_divider, - }, - .max_size_content = .{ - .w = @as(f32, @floatFromInt(img_size.w)) / img_area_divider, - .h = @as(f32, @floatFromInt(img_size.h)) / img_area_divider, - }, - }, - ); - defer img_area.deinit(); - // Получить viewport и scroll offset const viewport_rect = scroll.data().contentRect(); const scroll_current = dvui.Point{ .x = canvas.scroll.viewport.x, .y = canvas.scroll.viewport.y }; @@ -177,39 +150,40 @@ fn gui_frame(ctx: *WindowContext) bool { // viewport_rect/scroll_current — в natural единицах. // Для расчёта видимой области в пикселях изображения переводим в physical. const viewport_px = dvui.Rect{ - .x = viewport_rect.x * img_area_divider, - .y = viewport_rect.y * img_area_divider, - .w = viewport_rect.w * img_area_divider, - .h = viewport_rect.h * img_area_divider, + .x = viewport_rect.x * natural_scale, + .y = viewport_rect.y * natural_scale, + .w = viewport_rect.w * natural_scale, + .h = viewport_rect.h * natural_scale, }; const scroll_px = dvui.Point{ - .x = scroll_current.x * img_area_divider, - .y = scroll_current.y * img_area_divider, + .x = scroll_current.x * natural_scale, + .y = scroll_current.y * natural_scale, }; canvas.updateVisibleImageRect(viewport_px, scroll_px) catch |err| { std.debug.print("updateVisibleImageRect error: {}\n", .{err}); }; - // if (canvas.visible_rect) |vis| { - // if (vis.w != 0 and vis.h != 0) { - // const area_rs = img_area.data().contentRectScale(); - // var part_rs = area_rs; - // part_rs.r = .{ - // .x = area_rs.r.x + @as(f32, @floatFromInt(vis.x)), - // .y = area_rs.r.y + @as(f32, @floatFromInt(vis.y)), - // .w = @as(f32, @floatFromInt(vis.w)), - // .h = @as(f32, @floatFromInt(vis.h)), - // }; - // canvas.render(part_rs) catch {}; - // } - // } if (canvas.texture) |tex| { _ = dvui.image( @src(), .{ .source = .{ .texture = tex } }, .{ - .expand = .both, + .background = false, + .margin = .{ + .x = @as(f32, @floatFromInt(img_size.x)) / natural_scale, + .y = @as(f32, @floatFromInt(img_size.y)) / natural_scale, + .w = @as(f32, @floatFromInt(img_size.x)) / natural_scale, + .h = @as(f32, @floatFromInt(img_size.y)) / natural_scale, + }, + .min_size_content = .{ + .w = @as(f32, @floatFromInt(img_size.w)) / natural_scale, + .h = @as(f32, @floatFromInt(img_size.h)) / natural_scale, + }, + .max_size_content = .{ + .w = @as(f32, @floatFromInt(img_size.w)) / natural_scale, + .h = @as(f32, @floatFromInt(img_size.h)) / natural_scale, + }, }, ); } @@ -223,7 +197,6 @@ fn gui_frame(ctx: *WindowContext) bool { if (dvui.eventMatchSimple(e, scroll.data()) and (action == .wheel_x or action == .wheel_y)) { switch (action) { .wheel_y => |y| { - canvas.updateVisibleImageRect(viewport_px, scroll_px) catch {}; canvas.addZoom(y / 1000); canvas.redrawGradient() catch {}; },