mirror of
https://github.com/storytold/pdfcraft.git
synced 2026-10-26 19:19:10 -06:00
* M3: rasters reach egui without a copy on the UI thread Every page, tile and thumbnail raster was copied pixel by pixel on the UI thread (`ColorImage::from_rgba_premultiplied`), because egui's `Color32` is 4-byte aligned and a `Vec<u8>` isn't. That is 0.5 ms per 1024² tile, 5.4 ms for a 33 MB page and 36 ms for a 197 MB page, against a 16.7 ms frame. hayro, vendored patch 7: `render_size` and `render_into` render into a buffer the caller allocates. `render` is `render_into` on a new pixmap, so its output is unchanged. pdfcraft-render renders straight into `Pixels`, the same premultiplied RGBA bytes kept in one 4-byte word per pixel. `Pixels` dereferences to `[u8]`, so every reader of `RenderedPage::rgba` compiles unchanged. The canvas reinterprets the words as `Color32`s and hands them to egui as they are. Pixels are identical: all 33 renders of #260's test file hash the same. The UI-thread copy is gone, and rendering a 6182×8000 page takes 67 ms instead of 71–76 ms. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * M3: render_into leaves a buffer of the wrong length untouched instead of reaching vello's assert * M3: regression test for render_into with a wrong-length buffer --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: Brandon Thomas <echelon@gmail.com>
38 lines
1.5 KiB
Rust
38 lines
1.5 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 pixels;
|
||
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 pixels::Pixels;
|
||
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),
|
||
}
|