diff options
Diffstat (limited to 'src/panes.zig')
| -rw-r--r-- | src/panes.zig | 45 |
1 files changed, 35 insertions, 10 deletions
diff --git a/src/panes.zig b/src/panes.zig index f995986b..b3424385 100644 --- a/src/panes.zig +++ b/src/panes.zig @@ -3324,11 +3324,28 @@ pub const Image = struct { /// Construct an image pane from a path and optionally transferred dump bytes. /// `raw` must be image_gpa-owned and ownership transfers only on success. + /// Without them the file is read here, not at the first draw: a draw + /// must not go out into the host (`pardes.turn`), and the path may be a + /// mount this editor serves. A file that cannot be read draws blank. pub fn create(p: *pardes.Pardes, id: usize, path: []const u8, raw: []u8) !*pardes.Pane { + var bytes = raw; + var read_here = false; + if (bytes.len == 0) { + // The slot stays ours across the read: another request may + // make a pane meanwhile. + p.reserved_slots[id] = true; + defer p.reserved_slots[id] = false; + if (filesystem.read(p, path)) |from_disk| { + defer p.gpa.free(from_disk); + bytes = try p.image_gpa.dupe(u8, from_disk); + read_here = true; + } else |_| {} + } + errdefer if (read_here) p.image_gpa.free(bytes); const path_copy = try p.image_gpa.dupe(u8, path); errdefer p.image_gpa.free(path_copy); const pane = try p.newDocPane(id); - pane.image = .{ .path = path_copy, .raw = raw }; + pane.image = .{ .path = path_copy, .raw = bytes }; return pane; } @@ -3427,12 +3444,8 @@ pub const Image = struct { fn ensureDecoded(p: *pardes.Pardes, state: *State) void { if (state.tried) return; state.tried = true; - const bytes: []const u8 = if (state.raw.len > 0) - state.raw - else - filesystem.read(p, state.path) catch &.{}; - defer if (state.raw.len == 0) p.gpa.free(bytes); - if (image.decode(p.image_gpa, bytes)) |decoded| { + if (state.raw.len == 0) return; // nothing was readable at open + if (image.decode(p.image_gpa, state.raw)) |decoded| { state.rgba = decoded.rgba; state.iw = decoded.w; state.ih = decoded.h; @@ -3771,9 +3784,15 @@ pub const Pdf = struct { sections_output: ?SectionsOutput = null, outline_reveal_pending: ?pdf.OutlineInternalDestination = null, + /// Read whole and opened from memory (the bridge copies), never from + /// the file itself: MuPDF reads a file lazily at every page, and the + /// path may be a mount this editor serves, which only a read that + /// gives the turn up can come back from (`filesystem.readFile`). pub fn open(gpa: std.mem.Allocator, path: []const u8, page_one_based: usize) !@This() { const local = filesystem.localPath(path) orelse return error.NonLocalPath; - return initDocument(gpa, path, try Document.open(local), page_one_based); + const bytes = try filesystem.readFile(gpa, local); + defer gpa.free(bytes); + return initDocument(gpa, path, try Document.openBytes(bytes), page_one_based); } pub fn openBytes(gpa: std.mem.Allocator, path: []const u8, bytes: []const u8, page_one_based: usize) !@This() { @@ -5219,6 +5238,10 @@ pub const Pdf = struct { page_one_based: usize, ) !*pardes.Pane { if (comptime !enabled) return error.PdfDisabled; + // The slot stays ours across the read: another request may make a + // pane meanwhile. + core.reserved_slots[id] = true; + defer core.reserved_slots[id] = false; var state = if (filesystem.localPath(path) != null) try State.open(core.pdf_gpa, path, page_one_based) else virtual: { @@ -5903,9 +5926,11 @@ pub const Pdf = struct { null, }, .x = text_x, - .y = core.bodyTop(rect), + // Below the notice chips, like an image: a placed page is + // drawn after the cells and would paint a chip out. + .y = core.bodyTop(rect) + pane.notices.len, .w = text_width, - .h = rect.h -| pardes.BOX_H, + .h = (rect.h -| pardes.BOX_H) -| pane.notices.len, .rgba = placed.rgba, .iw = placed.width, // The texture contains the retained band, not the full page. |
