Expand description
Shared PDF-editor wire/model types (Dispatch A, lane A1).
Owns every Rust type other PDF-editor lanes compile against, per
docs/PDF-EDITOR-NOW.md §5.1 (wire models), §5.2 (inspection state types), §7.2 (font catalog
API), and §11 (typed errors), plus the digest helpers those sections describe and the shared
PdfEditCommand/ComposedCandidate types the frozen composer signature depends on
(docs/PDF-EDITOR-DISPATCH.md, “Frozen cross-lane seams”):
pub fn compose_candidate(
source: &[u8],
commands: &[PdfEditCommand],
fonts: &dyn PdfFontResolver,
) -> Result<ComposedCandidate, PdfEditError>;That function itself is defined by pdf_compose.rs (Dispatch C, lane C1) — this module only
provides the types its signature depends on, so downstream lanes can build and test against a
stable contract before the real implementation lands. Likewise inspect_pdf_page’s stateful
content walker (§5.2’s visit_text_show, §5.3’s may_join/painted-bounds inventory) is
pdf_inspect.rs (lane B1); this module owns only the Matrix/TextState/PositionedGlyph
family of types that walker is built from.
This file makes no filesystem or Tauri-state assumptions and defines no #[tauri::command] —
every command in this effort (inspect_pdf_page, list_pdf_fonts, compose_pdf_preview,
prepare_pdf_save, commit_pdf_save) belongs to a later lane’s file.
Structs§
- Composed
Candidate - Result of composing a source-command batch against fresh source bytes — the frozen
compose_candidate’s success type (PDF-EDITOR-DISPATCH.md).pdf_compose.rs(lane C1) produces this;pdf_save.rs(lane C2) and thecompose_pdf_previewcommand (§9.4) consume it —bytesbecomes candidate/preview bytes,affected_pagesbecomesPreparedPdfSave.affected_pages(§10.1) and the pagescompose_pdf_previewtells the frontend to re-render. - Decoded
Glyph - One decoded glyph from a
Tj/TJshow operand.source_rangeis the glyph’s byte range within the decoded operand string (start inclusive, end exclusive) and feedsSourceAddress::with_glyphfor later island-span grouping (§5.3).bbox, when the font decoder can supply it, is the glyph’s font-unit bounding box (x_min, y_min, x_max, y_max, scaled to/1000em units) used byTextState::glyph_quadfor exact geometry; when absent,glyph_quadfalls back to an advance-width approximation. - GlyphId
- One glyph identifier within a resolved font’s own glyph index space, matching
ttf_parser::GlyphId’s representation (a 16-bit glyph index) sopdf_font.rs(lane B2) andpdf_compose.rs(lane C1) can convert between the two without an extra newtype hop. - Glyph
Source Address - One glyph’s source address — the same shape as
PdfSourceSpanminus the fields (expected_text,expected_digest) that only become knowable once island grouping has concatenated a run of glyphs’ decoded text. - Matrix
- 2D affine transform in PDF row-vector convention:
(x' y' 1) = (x y 1) x M. Used for both the graphics-state CTM (cm/q/Q) and the text matrix/text-line matrix (Tm/Td/TD/T*). - Paint
State - Paint identity of a run of text, used by §5.3’s
compatible_paintto decide whether two adjacent glyphs may join into the same island. - Painted
Bounds - Conservative axis-aligned device-space bounding box for path paint (
S,s,f,F,f*,B,B*,b,b*) orXObject Doplacement, per §5.3’s coarse painted-bounds inventory.B1records these while walking;unrelatedflags an entry as belonging to content other than the island/run currently being evaluated, matching §8’svalidate_layoutcollision check (item.unrelated && item.bounds.intersects(run.bounds)). - PdfColor
- RGBA color for text-fill appearance. Mirrors frontend
PdfTextAppearance["color"](§6). - PdfDocument
Revision - PdfFont
Catalog Entry - PdfPage
Graph - PdfPoint
- One point in unrotated PDF user-space (or device space, depending on call site — callers
document which). Mirrors frontend
PdfPoint(§6, owned bypdfEditModel.ts). - PdfRect
- Axis-aligned rectangle in PDF user-space points. Mirrors frontend
PdfRect(§6/§8, owned bypdfEditModel.ts). Used for §8 layout validation (available.contains(run.bounds)) and §5.3’s painted-bounds inventory. - PdfSource
Locator - PdfSource
Span - PdfText
Appearance - Requested/applied text appearance for an edit. Mirrors frontend
PdfTextAppearance(§6) verbatim (field order/names), used byPdfTextIsland::appearanceand byPdfEditCommand. - PdfText
Edit State - Rust mirror of frontend
PdfSourceEdit/PdfAddText’s shared{ text, appearance }shape (§6). Used for bothbefore/afteron a replace-source-text command. - PdfText
Gap - A word gap the walker synthesised as a space in
PdfTextIsland::text: PDF text from TeX and similar producers has no space glyphs, onlyTJadjustments or position moves. - PdfText
Island - Positioned
Glyph - One glyph positioned in both PDF user-space (via
text_matrix/ctm) and device space (viaquad), as produced byvisit_text_show(§5.2) and consumed by §5.3’smay_joingrouping and painted-bounds inventory. - Resolved
PdfFont - A catalog font resolved to its actual font-program bytes, ready for glyph mapping (§7.3) and
subsetting/embedding (§7.4).
idmatchesPdfFontCatalogEntry::id— the font ID, not the family label, is what crosses the Save boundary (§7.2). - Source
Address - Address of one show-operand (
Tj, or one string item inside aTJarray) before any glyph index is known — built once per operator, then narrowed per glyph viaSourceAddress::with_glyph. - Text
State - Running text-object state for one page’s content-stream scan: the CTM, text matrix/text-line
matrix, and the spacing/scale/leading/rise/render-mode parameters §5.2 requires tracking across
q/Q/cm;BT/ET;Tm/Td/TD/T*;Tf/Tz/Tc/Tw/TL/Ts/Tr.
Enums§
- PdfEdit
Blocker - Why an island’s own font cannot be used to write replacement text. Serialized as a snake_case
string in
PdfTextIsland::edit_blocker.editable == falsewith one of these means “no replacement can be written through this island’s font at all”; a replacement that merely needs a glyph the font lacks is not a blocker (seePdfEditError::MissingGlyphs). - PdfEdit
Command - Rust mirror of frontend
PdfEditCommand(§6:PdfSourceEdit | PdfAddText).#[serde(tag = "kind", rename_all = "camelCase")]on aPascalCasevariant name serializes/deserializes to exactly the same"replaceSourceText"/"addText"discriminant the frontend sends, so the two sides share one wire shape without a hand-written tag. This is thecommands: &[PdfEditCommand]parameter of the frozencompose_candidatesignature (PDF-EDITOR-DISPATCH.md) and thesource_commandsfield ofprepare_pdf_save/compose_pdf_previewrequests (§9.4/§10.1). - PdfEdit
Error - Stable, typed rejection reasons for PDF-editor commands. Crosses Tauri IPC as a JSON tag +
message;
thiserror::Errorgives each variant the exact user-facing string from §11. Kept verbatim against the contract — do not add fields or reorder variants without updating §11 first, since every lane (B1 inspection, B2 fonts, C1 composition, C2 save) matches on these by name. - PdfFont
Source - Where a catalog font’s data comes from — bundled with RightKit (e.g. Source Serif 4) or
discovered on the host system via
fontdb(§7.1). - PdfOcr
Background Proof - Proof supplied by OCR/UI inspection that a line’s background is safe to cover with an opaque rectangle. Only near-uniform backgrounds are accepted by the sparse OCR correction composer.
- Text
Render Mode - Text-object render mode (
Tr), per PDF spec 9.3.6. Only fill/stroke visibility matters for island grouping’scompatible_paint(§5.3); modes 4-7 (clipping variants) are represented but current scope treats any clipping mode as unsupported at the call site, not here. - Writing
Direction - Text writing direction. Current scope supports left-to-right only (§7.3); the other variants exist so a walker can classify and then reject unsupported content with a typed error instead of silently misinterpreting it.
Traits§
- PdfFont
Resolver - Resolves catalog font IDs to usable font data and maps text to glyphs (§7.2). Implemented by
pdf_font.rs(lane B2); consumed by the frozencompose_candidatesignature (PDF-EDITOR-DISPATCH.md) asfonts: &dyn PdfFontResolver, sopdf_compose.rs(lane C1) can build and test against this trait before B2’s real implementation lands. - Text
State Font - Per-page active font handle used while walking a content stream (§5.2’s
visit_text_show). Implemented by whatever page-font resolverpdf_inspect.rs(lane B1) builds from a page’s/Resources/Font— distinct fromPdfFontResolver(§7.2), which resolves catalog fonts for composition/embedding, not content-stream decoding.
Functions§
- compute_
island_ digest island_digest: binds an island’s ordered spans, decoded glyph sequence, font identity, active matrices, paint, and geometry into one digest (§5.1) — a stronger identity check thanexpected_digestalone, since two visibly-identical runs of text (e.g. repeated labels) can still be told apart by their distinct source spans and transforms. Field order below is significant and part of this function’s contract: callers on either side of a save must hash the same canonicalization to agree on a digest.- document_
sha256 document_sha256: identifies the exact backing bytes aPdfDocumentRevision/PdfSourceLocatorwas computed against, so a command carrying a stale locator can be rejected withPdfEditError::StaleSourcebefore it touches content streams.- expected_
text_ digest expected_digest: verifies onePdfSourceSpan’s operand text hasn’t changed since the locator was built, independent of the whole-document hash — lets a save distinguish “unrelated edit elsewhere in the document” (safe) from “this exact operand changed” (reject withPdfEditError::SourceDigestMismatch).- sha256_
hex - Lowercase-hex SHA-256 of
bytes. Backs every digest helper below and is directly usable forPdfDocumentRevision::document_sha256/PdfSourceLocator::document_sha256.