Skip to main content

GlyphAtlas

Struct GlyphAtlas 

Source
pub struct GlyphAtlas {
    pub size: u32,
    pub pixels: Vec<u8>,
    pub dirty: bool,
    pub epoch: u64,
    pub stamp: u64,
    /* private fields */
}
Expand description

How the page makes room. A slot handed out during a frame is never moved or overwritten before that frame is presented: the quads already emitted, the text templates built and the cell tables filled all carry its texel rect, and nothing walks them again. So a page that fills mid-frame is extended — doubled with its pixels kept where they are, which leaves every texel rect valid, since uv is in texels and the renderer divides by the page’s size at draw time — and the reset that reclaims it waits for the next begin_frame, before anything is emitted. The page then starts that frame empty at its base size and holds that frame’s set alone; if the set does not fit it, it is larger than the page and the page keeps the growth. Most fills never get as far as mid-frame: begin_frame sees one coming in the rows the last frames opened and empties the page first. A page at MAX_ATLAS_SIZE cannot extend: there the request is refused for this frame (the glyph is not drawn, an image draws from a texture of its own) and the next frame, which short asks for, starts on an empty page.

A page that began the frame empty and still refuses holds a set bigger than itself, and the next frame would refuse the same. Its refusals are kept, and until the page is next emptied the atlas measures what each frame looks up: stamp moves every frame, so the caches that keep slots look theirs up again, and each distinct slot’s texels are counted once. A frame that wanted a refused glyph and whose set fits in what the page held is short, and the next frame begins on an empty page that takes it — the view has scrolled to a part of the set. One that did not fit keeps the page as it is.

An emptied page is not drawn from again, but it is kept for the frame that begins on the empty one. A glyph or shape that frame looks up and the old page held is copied across, not rasterized again: the frame after a reset is the whole visible set looked up at once — kawoosh’s window, ~600 glyphs, was 2.5–5.3 ms of rasterizing where the copy is a fraction of one. Only what the frame looks up is copied, so the page still holds that frame’s set alone. clear, for a raster mode that changed, keeps nothing.

Fields§

§size: u32§pixels: Vec<u8>

RGBA, sizesize4.

§dirty: bool

Set when pixels changed since the renderer last consumed them.

§epoch: u64

Bumped whenever the page is replaced — reset, or resized — so renderers re-upload it whole and caches that stamped it re-look their slots up. A resize keeps every slot where it was.

§stamp: u64

What caches that keep slots across frames — text templates, cell tables — key them on: it moves with epoch, and on every frame while refusals are pending, so that those frames look every slot they use up again and are measured.

Implementations§

Source§

impl GlyphAtlas

Source

pub fn new() -> GlyphAtlas

Source

pub fn with_size(size: u32) -> GlyphAtlas

Source

pub fn begin_frame(&mut self)

A frame begins, before anything is emitted — the one point where the page can be emptied without a quad sampling what it dropped. It is emptied, back at its base size, when the last frame extended it or was refused room (short) — and when it is about to fill: fewer rows free than two frames open at the rate they lately have. A set that turns over a little each frame, a list scrolling through fonts, fills the page every so often, and the rows foresee it, so the frame that would have extended the page mid-emit — a page four times the size, its rows copied, a texture made and uploaded twice — begins on an empty one instead. A fill it does not foresee still extends.

A page that needs emptying within two frames of the last time is too small for its set and the rate it turns over at, and grows instead: an extension is kept, and a page about to fill doubles with its slots in place. That is F83’s thrash, a set between one page and two, measured by what the page does rather than by which glyphs come back; a fill long after the last empties it.

A page with refusals pending is emptied when the last frame wanted one and its set fits (see the type’s note); otherwise the frame ahead is measured.

Source

pub fn clear(&mut self)

Drops every cached glyph and image (they re-rasterize on demand) and bumps the epoch so renderers re-upload. Used when the raster mode changes under the cache — between frames, never during one.

Source

pub fn get_or_insert( &mut self, key: CacheKey, raster: impl FnOnce() -> Option<RasterGlyph>, ) -> Option<GlyphSlot>

Cached lookup; rasterizes on miss — or, the frame after the page was emptied, copies what the old page held. None means unrasterizable (e.g. whitespace) and is cached as such.

Source

pub fn get_or_insert_synth( &mut self, ch: char, w: u32, h: u32, coverage: impl FnOnce() -> Vec<u8>, ) -> Option<GlyphSlot>

Cached lookup for a shape drawn to a w × h cell; coverage is called on a miss for w * h alpha bytes, which land as a white mask the renderer tints like any glyph’s. None means the cell does not fit a MAX_ATLAS_SIZE page.

Source

pub fn get_or_insert_path( &mut self, key: u64, w: u32, h: u32, coverage: impl FnOnce() -> Vec<u8>, ) -> Option<GlyphSlot>

Cached lookup for a path’s mask under key (the hash of its ops, scale, bin and paint — the caller’s to make); coverage is called on a miss for w * h alpha bytes, which land as a white mask the renderer tints like any glyph’s, or the mask is copied from the page begin_frame emptied when that page held it. None means the mask does not fit the page this frame, or no page at all; the caller draws it from a texture of its own.

Source

pub fn get_or_insert_gradient( &mut self, key: u64, w: u32, h: u32, rgba: impl FnOnce() -> Vec<u8>, ) -> Option<GlyphSlot>

Cached lookup for a gradient’s raster (docs/adr/0042-a-gradient-is-an-image-the-core-paints.md): w × h texels of straight RGBA under key, made by rgba on a miss and copied across a reset like a path’s mask, whose table it shares — the caller’s key is of a different domain. None when no page can hold it.

Source

pub fn has_path(&self, key: u64) -> bool

Whether the page holds a mask under key this frame: for a test of what a path’s second frame costs.

Source

pub fn get_or_insert_image( &mut self, id: ImageId, w: u32, h: u32, rgba: &[u8], ) -> Option<GlyphSlot>

Cached lookup for a registered image; blits rgba (wh4) on miss. None means it can’t fit even a MAX_ATLAS_SIZE page.

Source

pub fn evict_image(&mut self, id: ImageId)

Forget an image’s slot (its pixels are reclaimed at the next reset). Call when the host removes the image from Resources.

Source

pub fn retain_images(&mut self, live: impl Fn(ImageId) -> bool)

Keeps the slots of the images live says still exist and forgets the rest — how a window learns of removals made through another window of its session.

Source

pub fn has_image(&self, id: ImageId) -> bool

Whether the atlas holds a slot for id.

Trait Implementations§

Source§

impl Default for GlyphAtlas

Source§

fn default() -> GlyphAtlas

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<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
Source§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Source§

impl<T> Downcast<T> for T

Source§

fn downcast(&self) -> &T

Source§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

Source§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Sync + Send> ⓘ

Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be further downcast into Arc<ConcreteType> where ConcreteType implements Trait.
Source§

impl<S, T> Duplex<S> for T
where T: FromSample<S> + ToSample<S>,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<S> FromSample<S> for S

Source§

fn from_sample_(s: S) -> S

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
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<F, T> IntoSample<T> for F
where T: FromSample<F>,

Source§

fn into_sample(self) -> T

Source§

impl<T> NoneValue for T
where T: Default,

Source§

type NoneType = T

Source§

fn null_value() -> T

The none-equivalent value.
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T, U> ToSample<U> for T
where U: FromSample<T>,

Source§

fn to_sample_(self) -> U

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.
Source§

impl<T> Upcast<T> for T

Source§

fn upcast(&self) -> Option<&T>

Source§

impl<T> WasmNotSend for T
where T: Send,

Source§

impl<T> WasmNotSendSync for T

Source§

impl<T> WasmNotSync for T
where T: Sync,

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more