mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-11-13 01:41:18 +00:00
Every destination was reduced to a page index (`dest_page` in the inspector), so a bookmark written as [p1 /XYZ 0 420 0] went to the top of page 1 instead of putting y 420 at the top of the window, and /FitH, /FitV, /FitR and an /XYZ zoom were ignored. Destinations now keep their view (ISO 32000-2 §12.3.2.2): - render: `DestView` (Top, Xyz, Fit, FitH, FitV, FitR) parsed from explicit arrays, /D dictionaries and named destinations (/Names /Dests and /Dests). `OutlineItem` gains `view`; `LinkTarget::Page` carries it. Missing, wrong-typed or non-finite operands are null, a zoom that isn't positive keeps the zoom, and an unknown type or a /FitR without four numbers falls back to the page top. `PageInfo::dest_fraction` maps a user-space point to the displayed page through the crop box origin, /Rotate and the view rotation, clamped to the page. - ui: `DocView::go_to_dest` applies it for bookmark and link clicks (and so for `ui.click` on the control channel): /XYZ puts (left, top) at the window's top-left (beside the quick-action gutter) at its zoom; /Fit, /FitH and /FitV switch to fit page, width and height with top/left at the edge; /FitR zooms so the rectangle fits, centred. The /FitB* content box is read as the whole page. Tests: operand parsing incl. hostile values, a fixture with every form (named, GoTo, wrong types, huge numbers, no page), point mapping under crop offsets and rotations, go_to_dest state, and kittest bookmark and link clicks checking the point lands at the window's top. Co-authored-by: lloyd <lloyd@stackworx.io> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
36 lines
1.4 KiB
Rust
36 lines
1.4 KiB
Rust
//! pdfcraft-render — page rasterization and document inspection.
|
||
//!
|
||
//! **Bootstrap status (see ADR-0004):** rasterization goes straight through the `hayro` crate
|
||
//! (hayro-interpret + vello_cpu), and inspection (outline, annotations, fields, layers,
|
||
//! attachments, metadata) uses `lopdf`. Both are replaced by our own `cos`/`model` crates and the
|
||
//! DisplayList device design in M1–M2. The public API here is what the engine and UI rely on, so
|
||
//! the swap stays internal to this crate.
|
||
|
||
#![deny(clippy::unwrap_used, clippy::expect_used, clippy::panic, clippy::unimplemented, clippy::todo, clippy::unreachable)]
|
||
|
||
mod inspect;
|
||
mod raster;
|
||
pub mod text;
|
||
|
||
pub use inspect::{
|
||
Annotation, Attachment, AttachmentSource, DestView, DocInfo, Field, FieldKind, FontInfo, Layer, LayerOp, Link, LinkTarget, OutlineItem, PageInfo,
|
||
Xfa, attachment_data, inspect, pretty_date,
|
||
};
|
||
pub use raster::{
|
||
MAX_PIXELS, MAX_SIDE, PageRenderer, RenderConfig, RenderPool, RenderRequest, RenderedPage, RequestKind, Tile, device_pixels, effective_scale,
|
||
};
|
||
pub use text::{PageText, TextGlyph};
|
||
|
||
/// Errors surfaced to the user when a document cannot be opened.
|
||
#[derive(Debug, thiserror::Error)]
|
||
pub enum OpenError {
|
||
#[error("the file is not a readable PDF: {0}")]
|
||
Invalid(String),
|
||
#[error("the document is protected by a password")]
|
||
NeedsPassword,
|
||
#[error("the password is incorrect")]
|
||
WrongPassword,
|
||
#[error("{0}")]
|
||
Unsupported(String),
|
||
}
|