From b6012f1fc4bf10015db89817ff0c66bf5d833425 Mon Sep 17 00:00:00 2001 From: Roman Pytkov Date: Sun, 22 Feb 2026 22:25:49 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9E=D0=B3=D1=80=D0=B0=D0=BD=D0=B8=D1=87?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=87=D0=B0=D1=81=D1=82=D0=BE=D1=82?= =?UTF-8?q?=D1=8B=20=D0=BF=D0=B5=D1=80=D0=B5=D1=80=D0=B8=D1=81=D0=BE=D0=B2?= =?UTF-8?q?=D0=BA=D0=B8=20=D0=B4=D0=BE=2020=20=D1=84=D0=BF=D1=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Canvas.zig | 27 ++++++++++++++++++++++++++- src/main.zig | 5 ++++- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/src/Canvas.zig b/src/Canvas.zig index fbf88a4..9ec7692 100644 --- a/src/Canvas.zig +++ b/src/Canvas.zig @@ -18,8 +18,12 @@ scroll: dvui.ScrollInfo = .{ .horizontal = .auto, }, native_scaling: bool = true, +/// Максимальная частота перерисовки при зуме. 0 = без ограничения. +redraw_throttle_ms: u32 = 40, _visible_rect: ?ImageRect = null, _zoom: f32 = 1, +_redraw_pending: bool = false, +_last_redraw_time_ms: i64 = 0, pub fn init(allocator: std.mem.Allocator, document: *Document, engine: RenderEngine) Canvas { return .{ @@ -60,6 +64,7 @@ pub fn redrawExample(self: *Canvas) !void { self.texture = tex; } + self._last_redraw_time_ms = std.time.milliTimestamp(); } // Ресетнуть example изображение в renderEngine @@ -77,6 +82,26 @@ pub fn addZoom(self: *Canvas, value: f32) void { self._zoom = @max(self._zoom, 0.01); } +/// Запросить перерисовку (выполнится с учётом redraw_throttle_ms при вызове processPendingRedraw). +pub fn requestRedraw(self: *Canvas) void { + self._redraw_pending = true; +} + +/// Выполнить отложенную перерисовку, если прошло не менее redraw_throttle_ms с прошлой отрисовки. +pub fn processPendingRedraw(self: *Canvas) !void { + if (!self._redraw_pending) return; + if (self.redraw_throttle_ms == 0) { + self._redraw_pending = false; + try self.redrawExample(); + return; + } + const now_ms = std.time.milliTimestamp(); + const elapsed: i64 = if (self._last_redraw_time_ms == 0) self.redraw_throttle_ms else now_ms - self._last_redraw_time_ms; + if (elapsed < @as(i64, @intCast(self.redraw_throttle_ms))) return; + self._redraw_pending = false; + try self.redrawExample(); +} + pub fn getScaledImageSize(self: Canvas) ImageRect { const doc = self.document; return .{ @@ -103,7 +128,7 @@ pub fn updateVisibleImageRect(self: *Canvas, viewport: dvui.Rect, scroll_offset: std.debug.print("Visible Image Rect: {{ x: {}, y: {}, w: {}, h: {} }}\n", .{ next.x, next.y, next.w, next.h }); } if (changed or self.texture == null) { - try self.redrawExample(); + requestRedraw(self); } } diff --git a/src/main.zig b/src/main.zig index a449eb1..eb264a0 100644 --- a/src/main.zig +++ b/src/main.zig @@ -189,6 +189,9 @@ fn gui_frame(ctx: *WindowContext) bool { canvas.updateVisibleImageRect(viewport_px, scroll_px) catch |err| { std.debug.print("updateVisibleImageRect error: {}\n", .{err}); }; + canvas.processPendingRedraw() catch |err| { + std.debug.print("processPendingRedraw error: {}\n", .{err}); + }; const content_w_px: u32 = img_size.x + img_size.w; const content_h_px: u32 = img_size.y + img_size.h; @@ -237,7 +240,7 @@ fn gui_frame(ctx: *WindowContext) bool { switch (action) { .wheel_y => |y| { canvas.addZoom(y / 1000); - canvas.redrawExample() catch {}; + canvas.requestRedraw(); }, else => {}, }