Skip to main content

FontCache

Struct FontCache 

Source
pub struct FontCache { /* private fields */ }
Expand description

Per-document caches: loaded fonts, and the font-identity counter.

A value the document owns rather than process-wide state, so two documents loaded on two threads never share a face or a font identity. Send + Sync and shared by Arc, so every session over one document — every worker of a parallel render, and a text run and a render run alike — loads each font once between them rather than once each.

§What is cached, and what is not

The key is the ObjRef that named the /Font resource. A font dictionary written inline, with no reference of its own, is not cached and is loaded afresh at every use: two inline copies genuinely are two fonts, and there is no document-scoped identity to key them on.

The value is an Arc<Font>, so a hit shares the whole loaded font — its parsed /ToUnicode, its CID tables and its glyph cache — rather than rebuilding them. Text extraction’s duplicate suppression compares fonts by that pointer, so sharing is load-bearing for correctness as well as speed.

A dictionary that would not load caches its None too: that is as stable an answer as a font, and re-deriving it per page is the same wasted work.

§Why the substitution options are not part of the key

Every load under one document must make the same substitution choice — a substitution that varied between two Tf operators naming the same resource would give one line of text different metrics from the next — so a cache is created for one set of options and used with those. The caller that owns the options owns the cache: pdfrum_page::BuildContext carries both, in one value, and hands this out by Arc.

Implementations§

Source§

impl FontCache

Source

pub fn new() -> Self

A fresh cache.

Source

pub fn get_or_load<F>(&self, reference: ObjRef, load: F) -> Option<Arc<Font>>
where F: FnOnce() -> Option<Font>,

The font reference names, loading it on the first ask and sharing it on every later one.

load runs at most once per reference per cache in the uncontended case, and never under the lock — two threads asking for two different fonts do not serialize on each other. Two threads racing on the same reference may both load; whichever inserts first is the shared instance and both callers get that one Arc, so the loser’s copy is dropped rather than replacing an instance another page already holds. That costs one duplicate parse and keeps the loader off the lock.

Trait Implementations§

Source§

impl Debug for FontCache

Source§

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

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

impl Default for FontCache

Source§

fn default() -> FontCache

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

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> 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, 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.