cryoglyph/src/lib.rs
Héctor Ramón Jiménez a74ce29c1a Implement growing logic for TextAtlas
The `TextAtlas` will have an initial size of `256` (we could make this
configurable) and `try_allocate` will keep track of the glyphs in use
in the current frame, returning `None` when the LRU glyph is in use.

In that case, `TextRenderer::prepare` will return
`PrepareError::AtlasFull` with the `ContentType` of the atlas that is
full. The user of the library can then call `TextAtlas::grow` with the
provided `ContentType` to obtain a bigger atlas (by `256`).

A `TextAtlas::grow` call clears the whole atlas and, as a result, all of
the `prepare` calls need to be repeated in a frame until they all
succeed. Overall, the atlas will rarely need to grow and so the calls
will not need to be repated often.

Finally, the user needs to call `TextAtlas::trim` at the end of the
frame. This allows us to clear the glyphs in use collection in the atlas. Maybe
there is a better way to model this in an API that forces the user to
trim the atlas (e.g. make `trim` return a new type and changing `prepare` and `render` to take that type instead).
2023-07-04 14:54:05 -02:30

110 lines
3.1 KiB
Rust

//! Glyphon provides a simple way to render 2D text with [wpgu], [cosmic-text] and [etagere].
//!
//! [wpgu]: https://github.com/gfx-rs/wgpu
//! [cosmic-text]: https://github.com/pop-os/cosmic-text
//! [etagere]: https://github.com/nical/etagere
mod error;
mod text_atlas;
mod text_render;
pub use error::{PrepareError, RenderError};
pub use text_atlas::{ColorMode, TextAtlas};
pub use text_render::ContentType;
pub use text_render::TextRenderer;
// Re-export all top-level types from `cosmic-text` for convenience.
pub use cosmic_text::{
self, fontdb, Action, Affinity, Attrs, AttrsList, AttrsOwned, Buffer, BufferLine, CacheKey,
Color, Command, Cursor, Edit, Editor, Family, FamilyOwned, Font, FontSystem, LayoutCursor,
LayoutGlyph, LayoutLine, LayoutRun, LayoutRunIter, Metrics, ShapeGlyph, ShapeLine, ShapeSpan,
ShapeWord, Stretch, Style, SubpixelBin, SwashCache, SwashContent, SwashImage, Weight, Wrap,
};
use etagere::AllocId;
pub(crate) enum GpuCacheStatus {
InAtlas {
x: u16,
y: u16,
content_type: ContentType,
},
SkipRasterization,
}
pub(crate) struct GlyphDetails {
width: u16,
height: u16,
gpu_cache: GpuCacheStatus,
atlas_id: Option<AllocId>,
top: i16,
left: i16,
}
#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub(crate) struct GlyphToRender {
pos: [i32; 2],
dim: [u16; 2],
uv: [u16; 2],
color: u32,
content_type: u32,
depth: f32,
}
/// The screen resolution to use when rendering text.
#[repr(C)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Resolution {
/// The width of the screen in pixels.
pub width: u32,
/// The height of the screen in pixels.
pub height: u32,
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub(crate) struct Params {
screen_resolution: Resolution,
_pad: [u32; 2],
}
/// Controls the visible area of the text. Any text outside of the visible area will be clipped.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct TextBounds {
/// The position of the left edge of the visible area.
pub left: i32,
/// The position of the top edge of the visible area.
pub top: i32,
/// The position of the right edge of the visible area.
pub right: i32,
/// The position of the bottom edge of the visible area.
pub bottom: i32,
}
/// The default visible area doesn't clip any text.
impl Default for TextBounds {
fn default() -> Self {
Self {
left: i32::MIN,
top: i32::MIN,
right: i32::MAX,
bottom: i32::MAX,
}
}
}
/// A text area containing text to be rendered along with its overflow behavior.
pub struct TextArea<'a> {
/// The buffer containing the text to be rendered.
pub buffer: &'a Buffer,
/// The left edge of the buffer.
pub left: i32,
/// The top edge of the buffer.
pub top: i32,
/// The visible bounds of the text area. This is used to clip the text and doesn't have to
/// match the `left` and `top` values.
pub bounds: TextBounds,
// The default color of the text area.
pub default_color: Color,
}