Skip to main content

AnnotOverlay

Struct AnnotOverlay 

Source
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

Source

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);
Source

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));
Source

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));
Source

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());
Source

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));
Source

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));
Source

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));
Source

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));
Source

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());
Source

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());
Source

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());
Source

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);
Source

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);
Source

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);
Source

pub fn len(&self) -> usize

How many annotations the overlay covers.

use pdfrum_doc::AnnotOverlay;

assert_eq!(AnnotOverlay::with_capacity(3).len(), 3);
Source

pub fn is_empty(&self) -> bool

Whether the overlay covers no annotations at all.

use pdfrum_doc::AnnotOverlay;

assert!(AnnotOverlay::with_capacity(0).is_empty());
assert!(!AnnotOverlay::with_capacity(1).is_empty());

Trait Implementations§

Source§

impl Clone for AnnotOverlay

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for AnnotOverlay

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for AnnotOverlay

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl PartialEq for AnnotOverlay

Source§

fn eq(&self, other: &Self) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl StructuralPartialEq for AnnotOverlay

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.