Expand description
PDF viewing for GPUI — a page-virtualized viewer
built on the pure-Rust hayro rasterizer (no
native libraries, no system-font dependency).
Two layers, use whichever fits:
- Low-level primitives (host-agnostic, pure):
parsea PDF once, read page sizes withpage_dims, rasterize a page to agpui::RenderImagewithrender_page, and compute the on-screen page range withkeep_window. Build your own viewer on these. - A ready component:
PdfView— a self-contained gpui entity that owns its document, scroll position, off-thread rendering, and viewport eviction, so an 800-page file stays as light as a one-pager. It also has built-in zoom, page navigation (including a jump-to-page input), and DPI-aware rendering with a host-settable quality multiplier. Construct it insidecx.newand render theEntity<PdfView>like any child view.
let view = cx.new(|cx| {
PdfView::new(path, Rc::new(PdfStyle::default), Rc::new(|| 1.0), cx)
});
// then `view.clone()` into your element tree; call `view.update(cx, |v, cx|
// v.release(window, cx))` before dropping it (e.g. when its tab closes).Structs§
- Form
Field - One form widget, described for a host UI: where it is, what it takes, and what it currently holds.
- Highlight
- A highlight to draw on the PDF, located by its quote. The host derives these from
its own store (e.g. the markdown blocks that link this PDF) and hands them to the
viewer via
PdfView::set_highlights; the viewer finds the quote with the text layer and draws a translucent box over each line it spans. (markupfeature.) - Norm
Point - A point in normalized page coordinates (0..1 of width/height, top-left origin).
- Norm
Rect - A rectangle in normalized page coordinates: each component is a fraction (0..1) of the page’s width/height, origin at the top-left. Resolution- and zoom-independent, so a host maps it to the on-screen page rect at paint time.
- Outline
Item - One entry in a PDF’s outline, flattened depth-first.
- Page
Text - A page’s extracted text: the runs in draw order, plus a whitespace-stripped, lowercased index for robust quote matching.
- PdfLink
- A clickable
/Linkannotation: its rectangle in normalized page coordinates (0..1 of the crop box, top-left origin, matching the rendered image) and target. - PdfStyle
- Colors for the
PdfViewchrome. Map your theme onto this;PdfStyle::defaultis a neutral dark palette. - PdfView
- Construct with
PdfView::newinsidecx.new; it loads and measures the file off-thread. Render the resultingEntity<PdfView>like any child view. Callreleasebefore dropping it (e.g. when its tab closes) to free the atlas textures gpui won’t free on plain drop. - Selection
- The result of a drag selection: the selected text (as a single-line quote), which occurrence of that quote on the page it is (so it re-locates unambiguously), and the rects to draw while selecting.
Enums§
- Field
Kind - What kind of input a form field takes.
- FitMode
- Automatic zoom-to-fit modes — see
PdfView::fit_width/PdfView::fit_page. - Link
Target - Where a clickable PDF link points.
- Load
Error - Why loading a PDF failed.
- PdfEvent
- A page-virtualized PDF viewer: a scrollable column of page slots, each sized from the PDF’s page dimensions up front (so the scrollbar is correct for the whole document) but only rasterized while near the viewport. Pages scrolled away are freed — CPU pixel buffer and GPU atlas texture — so memory is bounded by what’s on screen rather than the page count.
Constants§
- PAGE_
WIDTH - Base on-screen page width (points) at zoom 1.0; pages keep their aspect ratio.
Functions§
- extract_
page_ text - Extract the text layer of page
index(0-based). Runs a non-rasterizing interpret pass — cheaper than rendering, but still parses the page, so a host should cache the result. ReturnsNoneif the page doesn’t exist. - form_
fields - Every form-field widget in the document, in page order — what a host needs to overlay inputs on the viewer. Pushbuttons (no value) are skipped; an encrypted or unparseable file yields an empty list.
- is_pdf
- True if a link/image
srcpoints at a PDF (by extension, case-insensitive). - keep_
window - The inclusive page-index range
(start, end)to keep rasterized for the given scroll position: the pages intersecting the viewport, padded by [MARGIN]. Pure (mirrorsPdfView’s slot layout) so it’s unit-testable.page_widthis the on-screen column width (base × zoom);scroll_yis how far the content is scrolled down (px ≥ 0);viewport_his the visible height (px). - normalize_
form_ appearances - Rewrite
bytesso every form widget has a directly-renderable appearance stream.Some(fixed)only when something actually changed;Nonemeans nothing to do (no forms, already normalized, encrypted, or unparseable) — the caller keeps the original bytes either way. - outline
- Extract the document outline (bookmarks), flattened depth-first. Returns an
empty vec when the PDF has no
/Outlines. - page_
dims - Each page’s
(width, height)in points — cheap to read (no rasterization), so a viewer can lay out correctly-sized page slots before any page renders. - page_
links - Extract the clickable
/Linkannotations for every page, indexed by page; pages with none get an empty vec. Rotated pages are skipped for now (their annotation rectangles would need rotating to line up with the render). - parse
- Parse a PDF’s bytes into a reusable
Document. TheDocumentowns the bytes, so the caller can drop its own copy. ReturnsLoadError::Lockedfor a password-protected file (retry withparse_with_password). - parse_
with_ password - Like
parse, but supplies a decryptionpasswordfor an encrypted PDF. ReturnsLoadError::Lockedif the file is password-protected andpasswordis missing or incorrect. - render_
page - Rasterize a single page (0-based) of an already-parsed
Documentatscale(PDF point-size × this) to a BGRARenderImagecomposited onto white. Higher scale = sharper but more memory;PdfViewpicksscalefrom the display’s pixel ratio, zoom, and quality so pages are crisp without wasting memory. - set_
form_ value - Set the value of the field named
name(fully qualified, as reported byform_fields) and regenerate its appearance so the result renders in any viewer — not just ours. ForText/Choicepass the literal text; forCheckbox/Radiopass an on-state name fromFormField::options(or"Off"to clear). Returns the rewritten bytes, orNonewhen nothing matched (unknown/read-only/signature field, encrypted or unparseable file).
Type Aliases§
- Create
Area Fn - Invoked when the user finishes a box-drag in “area mode”: the page (0-based), the
dragged rect in normalized page coordinates, and the label of the picked color.
The host stores it and hands it back as a
Highlightwithregionset. (markupfeature.) - Create
Highlight Fn - Invoked when the user finishes a drag-selection in “highlight mode”: the page
(0-based), the selected one-line quote, which occurrence of it on the page, and the
label of the picked color (the opaque tag from [
set_highlight_palette], for the host to store). The host turns this into a stored note. (markupfeature.) - Document
- A parsed PDF. Parse once (not per page) — re-parsing a large file for every page
is slow and churns the allocator.
hayro’sPdfisSend + Sync(std feature) and caches pages internally, so it’s shared viaArcacross the background render tasks. - Highlight
Click Fn - Invoked with a
Highlight’sidwhen the user clicks it. (markupfeature.) - Open
External Fn - Invoked from the load-failure pane’s “Open in system viewer” button, so the
host can hand the file to the OS default app — the viewer itself stays
host-agnostic (no process spawning). Set via
PdfView::set_on_open_external; without it the pane shows no button. - PdfQuality
Fn - Supplies the current render-quality multiplier at paint time (1.0 = native DPI;
< 1 is faster and softer, > 1 supersamples). Read like
PdfStyleFn, so a host setting change (e.g. a Settings slider) re-renders all open viewers — in every window — automatically. Clamped to a sane range internally. - PdfStyle
Fn - Supplies the current
PdfStyleat paint time. BecausePdfViewis a persistent entity (not rebuilt by its parent each frame), it reads its colors through this closure — returning fresh colors each call lets the viewer follow live theme changes (and differ per window) without the host pushing updates.