pub struct AnnotOverlay { /* private fields */ }Expand description
Per-annotation generated appearances, keyed by /Annots index.
Besides the per-annotation entries the overlay carries at most one
Focus, because a session focuses one field at a time. It travels here
rather than as another parameter on the annotation pass for two reasons:
it is set by the same session that sets the appearances, from the same
index space, and adding it here left every existing caller compiling
unchanged.
use pdfrum_common::Diagnostics;
use pdfrum_doc::ap::generate_appearances;
use pdfrum_object::{Array, Dict, Name, NoResolve, Object};
let square = Dict::from_pairs([
(Name::from("Subtype"), Object::Name(Name::from("Square"))),
(
Name::from("Rect"),
Object::Array(Array::of([0, 0, 100, 50])),
),
]);
let page = Dict::from_pairs([(
Name::from("Annots"),
Object::Array(Array::of([Object::Dict(square)])),
)]);
// Every reader in this crate takes the overlay and consults it
// before the raw dictionary.
let mut diags = Diagnostics::default();
let overlay = generate_appearances(&page, &NoResolve, &mut diags);
assert!(overlay.get(0).is_some());Implementations§
Source§impl AnnotOverlay
impl AnnotOverlay
Sourcepub fn with_capacity(count: usize) -> AnnotOverlay
pub fn with_capacity(count: usize) -> AnnotOverlay
An overlay with room for count annotations and nothing generated.
use pdfrum_doc::{AnnotOverlay, ap::Appearance};
let overlay = AnnotOverlay::with_capacity(3);
assert_eq!(overlay.len(), 3);
assert_eq!(overlay.appearance(0), &Appearance::Untouched);Sourcepub fn set_focus(&mut self, focus: Focus)
pub fn set_focus(&mut self, focus: Focus)
Records which annotation holds the focus, and what to stroke over it.
The index is a raw /Annots index. It is not bounded by the
overlay’s length: an overlay sized for the appearances it carries can
still name a focused annotation past its end, and the annotation pass
keys on the index rather than on an entry.
use pdfrum_doc::{AnnotOverlay, Focus};
let mut overlay = AnnotOverlay::with_capacity(2);
// The index is a raw `/Annots` index and is not bounded by the length.
overlay.set_focus(Focus::at(7));
assert_eq!(overlay.focus().map(|f| f.annot), Some(7));Sourcepub fn focus(&self) -> Option<Focus>
pub fn focus(&self) -> Option<Focus>
Which annotation holds the focus, if any.
use pdfrum_doc::{AnnotOverlay, Focus};
let mut overlay = AnnotOverlay::with_capacity(2);
assert!(overlay.focus().is_none());
overlay.set_focus(Focus::at(1));
assert_eq!(overlay.focus().map(|f| f.annot), Some(1));Sourcepub fn set_hover(&mut self, annot: usize)
pub fn set_hover(&mut self, annot: usize)
Records which annotation the pointer is inside.
A raw /Annots index, like Self::set_focus’s, and equally
unbounded by the overlay’s length. Hover is a separate fact from focus
and the two move independently: a pointer resting on an annotation
leaves the keyboard focus wherever it was, and the annotation under the
pointer need not be focusable at all — a highlight is the case that
matters, since it is only reachable this way.
What it decides is whether that annotation’s synthesized pop-up note is open. A note card is drawn only while the pointer is inside its parent, and nothing a file can say opens one, so this is the whole of the signal.
use pdfrum_doc::AnnotOverlay;
let mut overlay = AnnotOverlay::with_capacity(4);
overlay.set_hover(1);
assert_eq!(overlay.hover(), Some(1));
// Hover and focus move independently.
assert!(overlay.focus().is_none());Sourcepub fn hover(&self) -> Option<usize>
pub fn hover(&self) -> Option<usize>
Which annotation the pointer is inside, if any.
use pdfrum_doc::AnnotOverlay;
let mut overlay = AnnotOverlay::with_capacity(4);
assert!(overlay.hover().is_none());
overlay.set_hover(0);
assert_eq!(overlay.hover(), Some(0));Sourcepub fn set_live_edit(&mut self, annot: usize)
pub fn set_live_edit(&mut self, annot: usize)
Records that one annotation’s supplied appearance is a live edit’s — the field the session is currently typing in.
A raw /Annots index, like Self::set_focus’s and equally unbounded
by the overlay’s length. At most one annotation can be under live edit,
because a session focuses one field at a time; a second call replaces
the first rather than accumulating.
It is a separate signal from focus, and the two are not
interchangeable. A field can hold the focus without being edited — it
was tabbed to and nothing has been typed — in which case the session
generates no appearance for it and there is nothing to mark. What this
records is that the appearance carried at this index came from an
editor, which is what makes the oracle draw its text with ClearType.
use pdfrum_doc::AnnotOverlay;
let mut overlay = AnnotOverlay::with_capacity(4);
overlay.set_live_edit(1);
// A second call replaces the first: one field is edited at a time.
overlay.set_live_edit(2);
assert_eq!(overlay.live_edit(), Some(2));Sourcepub fn live_edit(&self) -> Option<usize>
pub fn live_edit(&self) -> Option<usize>
Which annotation’s appearance is a live edit’s, if any.
use pdfrum_doc::AnnotOverlay;
let mut overlay = AnnotOverlay::with_capacity(4);
assert!(overlay.live_edit().is_none());
overlay.set_live_edit(3);
assert_eq!(overlay.live_edit(), Some(3));Sourcepub fn is_live_edit(&self, index: usize) -> bool
pub fn is_live_edit(&self, index: usize) -> bool
Whether the appearance at one /Annots index came from a live edit.
use pdfrum_doc::AnnotOverlay;
let mut overlay = AnnotOverlay::with_capacity(4);
overlay.set_live_edit(1);
assert!(overlay.is_live_edit(1));
assert!(!overlay.is_live_edit(0));Sourcepub fn set(&mut self, index: usize, generated: GeneratedAp)
pub fn set(&mut self, index: usize, generated: GeneratedAp)
Records a generated appearance at one /Annots index.
use pdfrum_common::Diagnostics;
use pdfrum_doc::ap::generate_appearances;
use pdfrum_object::{Array, Dict, Name, NoResolve, Object};
let square = Dict::from_pairs([
(Name::from("Subtype"), Object::Name(Name::from("Square"))),
(
Name::from("Rect"),
Object::Array(Array::of([0, 0, 100, 50])),
),
(
Name::from("IC"),
Object::Array(Array::of([1, 0, 0])),
),
]);
let page = Dict::from_pairs([(
Name::from("Annots"),
Object::Array(Array::of([Object::Dict(square)])),
)]);
let mut diags = Diagnostics::default();
let overlay = generate_appearances(&page, &NoResolve, &mut diags);
// The walk sets index 0; a caller can set any index the same way.
let generated = overlay.get(0).expect("a square has a generator").clone();
let mut mine = pdfrum_doc::AnnotOverlay::with_capacity(2);
mine.set(1, generated);
assert!(mine.get(1).is_some());Sourcepub fn set_appearance(&mut self, index: usize, appearance: Appearance)
pub fn set_appearance(&mut self, index: usize, appearance: Appearance)
Records any of the three states at one /Annots index.
use pdfrum_doc::{AnnotOverlay, ap::Appearance};
let mut overlay = AnnotOverlay::with_capacity(2);
overlay.set_appearance(0, Appearance::Suppressed);
assert_eq!(overlay.appearance(0), &Appearance::Suppressed);
// A suppressed entry has no stream to draw.
assert!(overlay.get(0).is_none());Sourcepub fn get(&self, index: usize) -> Option<&GeneratedAp>
pub fn get(&self, index: usize) -> Option<&GeneratedAp>
What was generated at one /Annots index, if anything.
A suppressed entry answers None, the same as an untouched one —
callers that only want a stream to draw need not distinguish them.
AnnotOverlay::appearance is what tells them apart.
use pdfrum_common::Diagnostics;
use pdfrum_doc::ap::generate_appearances;
use pdfrum_object::{Array, Dict, Name, NoResolve, Object};
let square = Dict::from_pairs([
(Name::from("Subtype"), Object::Name(Name::from("Square"))),
(
Name::from("Rect"),
Object::Array(Array::of([0, 0, 100, 50])),
),
(
Name::from("IC"),
Object::Array(Array::of([1, 0, 0])),
),
]);
let page = Dict::from_pairs([(
Name::from("Annots"),
Object::Array(Array::of([Object::Dict(square)])),
)]);
let mut diags = Diagnostics::default();
let overlay = generate_appearances(&page, &NoResolve, &mut diags);
assert!(overlay.get(0).is_some());
// Past the end is `None`, not a panic.
assert!(overlay.get(9).is_none());Sourcepub fn appearance(&self, index: usize) -> &Appearance
pub fn appearance(&self, index: usize) -> &Appearance
The full state at one /Annots index, suppression included.
An index past the overlay’s end reads as Appearance::Untouched,
which is what makes a short overlay safe to consult for any index.
use pdfrum_doc::{AnnotOverlay, ap::Appearance};
let overlay = AnnotOverlay::with_capacity(1);
// An index past the end reads as untouched, so a short overlay is
// safe to consult for any index.
assert_eq!(overlay.appearance(99), &Appearance::Untouched);Sourcepub fn merge_over(&mut self, other: &AnnotOverlay)
pub fn merge_over(&mut self, other: &AnnotOverlay)
Lays other’s entries over this one’s.
Every entry other has anything to say about — generated or
suppressed — replaces this overlay’s, and its Appearance::Untouched
entries leave this one’s alone. So a caller-supplied overlay wins
wherever it speaks and defers everywhere else, which is the merge a
live edit needs: the session has an opinion about the one field being
edited and none about the rest of the page.
Indices are raw /Annots indices in both overlays. An entry of
other past this overlay’s end is dropped, because there is no
annotation for it to apply to.
other’s Focus and its hover each replace this overlay’s when it
has one, and leave it alone when it does not — the same “wins wherever
it speaks” rule the entries follow. Unlike an entry, either one past
this overlay’s end survives: both name an annotation, not a slot.
use pdfrum_doc::{AnnotOverlay, ap::Appearance};
let mut page = AnnotOverlay::with_capacity(2);
page.set_appearance(0, Appearance::Suppressed);
// The session speaks about index 1 only.
let mut session = AnnotOverlay::with_capacity(2);
session.set_appearance(1, Appearance::Suppressed);
page.merge_over(&session);
assert_eq!(page.appearance(0), &Appearance::Suppressed);
assert_eq!(page.appearance(1), &Appearance::Suppressed);Sourcepub fn rect(&self, index: usize, raw: Rect) -> Rect
pub fn rect(&self, index: usize, raw: Rect) -> Rect
The rectangle an annotation should be read as having.
use pdfrum_doc::{AnnotOverlay, geom};
let overlay = AnnotOverlay::with_capacity(1);
let raw = geom::rect(0.0, 0.0, 100.0, 50.0);
// Nothing generated: the annotation keeps the rectangle it declared.
assert_eq!(overlay.rect(0, raw), raw);Trait Implementations§
Source§impl Clone for AnnotOverlay
impl Clone for AnnotOverlay
Source§fn clone(&self) -> AnnotOverlay
fn clone(&self) -> AnnotOverlay
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more