Skip to main content
← PSoXide SDK guides and examples · SDK f2fec1c301f1 · All Cargo features enabled; check feature gates before use.

FontAtlas

Struct FontAtlas 

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

A BitmapFont installed in VRAM and ready to draw from.

Hold on to the returned handle for the lifetime you want glyphs to stay drawable. Uploading costs ~1 GP0 0xA0 transfer of glyph_count × glyph_w × glyph_h / 4 bytes (plus 2 halfwords for the CLUT); draw calls cost 4 GP0 words per glyph.

Implementations§

Source§

impl FontAtlas

Source

pub fn upload(font: &'static BitmapFont, tpage: TexturePage, clut: Clut) -> Self

Upload font as a 4bpp CLUT texture at tpage, with a 2-entry CLUT (transparent, white) at clut.

The caller picks the tpage / clut locations – typically TexturePage::new(768, 0, TextureDepth::Bit4) for the standard off-display region, and a Clut::new(768, 480) for the CLUT row. Both must live inside VRAM and not overlap the active framebuffer.

Atlas layout picks glyphs_per_row so the texture’s pixel width stays within MAX_ATLAS_W_TEXELS. For 8-wide fonts that’s 32 glyphs per row; 16-wide fonts get 16 per row.

Source

pub fn text_width(&self, text: &str) -> u16

Pixel width of text when rendered with this atlas.

Source

pub fn glyph_advance(&self, ch: char) -> u8

Pixel advance of one character, the per-glyph term FontAtlas::text_width sums.

Exposed so a caller scanning a string can carry a running width instead of re-measuring every prefix: word wrap is quadratic otherwise, which on R3000 is the most expensive thing a text layout does. text_width(s) stays exactly s.chars().map(glyph_advance).fold(0, u16::saturating_add).

Source

pub fn text_width_with_spacing(&self, text: &str, letter_spacing: i8) -> u16

Pixel width of text using this atlas’s font metrics plus signed spacing inserted between adjacent characters.

Source

pub fn line_height(&self) -> u16

Pixel height of a single text line. Usually == glyph_h.

Source

pub fn draw_text(&self, x: i16, y: i16, text: &str, tint: (u8, u8, u8))

Draw text at screen-space (x, y) with the given tint.

(0x80, 0x80, 0x80) = unmodulated white; any other value recolours every glyph via the PSX per-texel multiplier (output = texel * tint / 128).

Fast path – uses textured rectangles (GP0 0x64, 4 words per glyph). For any transform or per-vertex colour needs, reach for Self::draw_text_scaled, Self::draw_text_rotated, Self::draw_text_affine, or Self::draw_text_gradient.

Characters outside the font’s codepoint range are skipped – they still advance the cursor so the rest of the string lines up as the caller intended. Iteration is per-char, so any &str is valid input; a Latin-1 atlas with first_char = 0xA0 picks up é, ü, etc. automatically.

Sets the GP0(0xE1) draw-mode tpage to our atlas once at the start of the call – if the caller was rendering with a different tpage, they’ll need to re-apply theirs after draw_text returns.

§Example
ⓘ
atlas.draw_text(8, 8, "SCORE 0042", (0x80, 0x80, 0x80));
Source

pub fn emit_text_packets( &self, x: i16, y: i16, text: &str, tint: (u8, u8, u8), emit: impl FnMut(&[u32]) -> bool, ) -> bool

Emit ordered GP0 packets for deferred, axis-aligned text drawing.

The sink receives one two-word draw-mode/texture-window packet followed by one four-word textured rectangle per supported glyph. Atlas padding, packed-page origin, CLUT and character advances are owned by this atlas, just as they are for immediate drawing. No GPU access occurs here.

The sink must copy each borrowed packet before returning. Returning false stops emission immediately, allowing a fixed packet arena to reject a full run without writing beyond its capacity. Earlier packets remain accepted; the return value says whether the entire run fit.

Source

pub fn draw_text_with_spacing( &self, x: i16, y: i16, text: &str, letter_spacing: i8, tint: (u8, u8, u8), )

Draw text with signed spacing inserted between adjacent characters. letter_spacing is measured in final screen pixels and is not applied after the last character.

Source

pub fn draw_text_blended( &self, x: i16, y: i16, text: &str, tint: (u8, u8, u8), blend: TextBlend, )

Draw text with the GPU’s semi-transparency enabled, blending each glyph against the framebuffer with blend’s equation.

Fast path – same GP0 0x64 textured rectangle and same 4 words per glyph as Self::draw_text, with the primitive’s semi-transparency bit set and the draw mode’s ABR field carrying the equation. The only extra cost is the one draw-mode word at the start and the one that restores the opaque mode at the end.

Why this exists: the opaque path can only recolour a glyph, and a tint ramped toward black draws a black glyph, not an absent one. TextBlend::Add plus a ramped tint is the PS1’s real fade – at tint zero the glyph contributes nothing and vanishes.

Restores the atlas’s opaque draw mode before returning, so a blended run cannot leave a stray blend equation on the GPU for whatever draws next. As with Self::draw_text, the tpage slot is left pointing at this atlas.

Source

pub fn draw_text_blended_with_spacing( &self, x: i16, y: i16, text: &str, letter_spacing: i8, tint: (u8, u8, u8), blend: TextBlend, )

Self::draw_text_blended with signed inter-character spacing, measured in screen pixels and not applied after the last glyph.

Source

pub fn draw_backdrop_blended( &self, x: i16, y: i16, w: u16, h: u16, tint: (u8, u8, u8), blend: TextBlend, )

Draw a flat semi-transparent rectangle in blend’s equation – a backing plate for a run of text drawn on top of it.

This is a method on the atlas rather than a free function because the blend equation is carried by the GP0(E1h) draw-mode word, which also names a texture page. Setting one means setting the other, so whatever changes the equation has to know which page the glyphs that follow will want back – and the atlas is what knows that. It restores the atlas’s opaque draw mode on the way out, exactly as Self::draw_text_blended does.

TextBlend::Subtract is the equation to reach for behind text: it darkens whatever is under it and, because it scales with the tint, it fades to nothing along with the text it seats. TextBlend::Average cannot fade – at tint zero it still halves the background, so a plate drawn with it outlives the glyphs and is left behind as a grey box.

Source

pub fn draw_text_scaled( &self, x: i16, y: i16, text: &str, scale_x: u8, scale_y: u8, tint: (u8, u8, u8), )

Draw text at screen-space (x, y) scaled by (scale_x, scale_y). scale=(1, 1) matches Self::draw_text’s output, but via the quad path instead of the rect path – so prefer draw_text for native-size.

Quad path – uses textured quads (GP0 0x2C, 9 words per glyph). PSX samples textures with nearest-neighbour, so integer scales (2×, 3×, 4×) produce crisp pixel-doubled output. Use Self::draw_text_scaled_q8 for fractional screen-space sizes.

§Example
ⓘ
atlas.draw_text_scaled(80, 100, "GAME OVER", 3, 3, (220, 40, 40));
Source

pub fn draw_text_scaled_q8( &self, x: i16, y: i16, text: &str, scale_x_q8: u16, scale_y_q8: u16, tint: (u8, u8, u8), )

Draw text with Q8 fixed-point scale factors (256 = 1.0x). This keeps the font atlas monochrome while allowing fractional screen-space glyph sizes such as 1.5x (384).

Source

pub fn draw_text_scaled_with_spacing( &self, x: i16, y: i16, text: &str, scale_x: u8, scale_y: u8, letter_spacing: i8, tint: (u8, u8, u8), )

Draw scaled text with signed spacing inserted between adjacent characters. letter_spacing is measured in final screen pixels, not source-glyph pixels.

Source

pub fn draw_text_scaled_with_spacing_q8( &self, x: i16, y: i16, text: &str, scale_x_q8: u16, scale_y_q8: u16, letter_spacing: i8, tint: (u8, u8, u8), )

Draw scaled text with Q8 fixed-point scale and signed spacing inserted between adjacent characters. letter_spacing is measured in final screen pixels, not source-glyph pixels.

Source

pub fn draw_text_rotated( &self, cx: i16, cy: i16, text: &str, angle_q12: u16, tint: (u8, u8, u8), )

Draw text rotated around the pivot (cx, cy) by angle_q12 (Q0.12, one revolution = 4096). The string is centred on the pivot at angle 0 – its natural extent is text_width × glyph_h, anchored so (cx, cy) sits at the centre of the baseline.

Quad path – 9 GP0 words per glyph. Sin/cos come from a compact 256-entry Q1.12 table ([sincos]), good to ~1.4° – imperceptible at 8px glyph scale.

See crate-level docs for the Q0.12 angle convention.

§Example
ⓘ
// Spin a title once per second (frame_idx updates each vsync).
let angle = ((frame_idx * 68) & 0xFFF) as u16; // ~4096/60 ≈ 68
atlas.draw_text_rotated(160, 120, "SPIN", angle, (255, 255, 255));
Source

pub fn draw_text_affine( &self, origin: (i16, i16), text: &str, m: [[i16; 2]; 2], tint: (u8, u8, u8), )

Draw text through an arbitrary 2×2 affine transform.

The matrix m is Q3.12 fixed-point – m = [[4096, 0], [0, 4096]] is the identity (native size, axis-aligned). Each glyph’s local corner (lx, ly) maps onto screen space as (origin.0 + (m[0][0]*lx + m[0][1]*ly) >> 12, origin.1 + (m[1][0]*lx + m[1][1]*ly) >> 12).

Covers rotation, non-uniform scale, shear, reflection, and any combination – the other quad-path methods are all specializations of this one.

Quad path – 9 GP0 words per glyph.

§Example: horizontal shear
ⓘ
// Skew 30° right: x' = x + 0.577·y. 0.577 × 4096 ≈ 2365.
let m = [[4096, 2365], [0, 4096]];
atlas.draw_text_affine((40, 40), "SKEW", m, (200, 200, 200));
Source

pub fn draw_text_gradient( &self, x: i16, y: i16, text: &str, top: (u8, u8, u8), bottom: (u8, u8, u8), )

Draw text with a top-to-bottom colour gradient.

Top of each glyph is tinted top; bottom is tinted bottom. The GPU gouraud-interpolates down each glyph, producing a smooth vertical gradient across the whole line.

Gouraud quad path – 12 GP0 words per glyph (GP0 0x3C). Use when you want a rainbow title, a torch-lit dialogue box, or any per-vertex colour effect; prefer the single- tint Self::draw_text otherwise.

§Example
ⓘ
// Classic "red hot" gradient.
atlas.draw_text_gradient(
    40, 10, "INFERNO",
    (255, 240, 80),  // bright yellow at the top
    (180, 30, 20),   // deep red at the bottom
);
Source

pub fn draw_text_scaled_gradient( &self, x: i16, y: i16, text: &str, scale_x: u8, scale_y: u8, top: (u8, u8, u8), bottom: (u8, u8, u8), )

Draw text with a top-to-bottom gradient, scaled by (scale_x, scale_y). Combines Self::draw_text_scaled and Self::draw_text_gradient in one draw – a 3× title with a fire-colour sweep costs the same 12 words per glyph as a 1× gradient.

Nearest-neighbour sampling still applies, so integer scales produce crisp pixel-doubled output.

§Example
ⓘ
// 3× "TITLE" with yellow→red gradient.
atlas.draw_text_scaled_gradient(
    64, 10, "TITLE", 3, 3,
    (255, 220, 80), (200, 40, 20),
);
Source

pub fn draw_text_scaled_gouraud_with_spacing_q8( &self, x: i16, y: i16, text: &str, scale_x_q8: u16, scale_y_q8: u16, letter_spacing: i8, colors: [(u8, u8, u8); 4], )

Draw text with per-vertex glyph colours, Q8 scaling, and authored letter spacing.

colors are ordered top-left, top-right, bottom-left, bottom-right, matching psx_gpu::draw_quad_textured_gouraud. This is the general-purpose path behind gradient UI text: vertical gradients use [top, top, bottom, bottom], horizontal gradients use [left, right, left, right].

Source

pub fn font(&self) -> &'static BitmapFont

Access the underlying BitmapFont. Useful for UI code that needs glyph dimensions for its own layout math.

Source

pub fn texture_page(&self) -> TexturePage

Texture page the atlas is installed at – useful if the caller wants to restore it after drawing with a different tpage. Always 4bpp, always inside a valid VRAM page-aligned slot.

Trait Implementations§

Source§

impl Clone for FontAtlas

Source§

fn clone(&self) -> FontAtlas

Returns a duplicate of the value. Read more
1.0.0§

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

Performs copy-assignment from source. Read more
Source§

impl Debug for FontAtlas

Source§

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

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

impl TextSink for FontAtlas

Source§

fn draw(&self, x: i16, y: i16, text: &str, tint: (u8, u8, u8))

Draw text with its top-left corner at (x, y).
Source§

fn width(&self, text: &str) -> i16

Width of text in screen pixels, using the same metrics draw will.
Source§

fn line_height(&self) -> i16

Baseline-to-baseline distance for stacked rows.
Source§

fn draw_centered(&self, x: i16, y: i16, text: &str, tint: (u8, u8, u8))

Draw text centred on x. Provided so every caller does not repeat the half-width arithmetic, and so a renderer with non-integer metrics can override the rounding.
Source§

impl Copy for FontAtlas

Auto Trait Implementations§

§

impl Freeze for FontAtlas

§

impl RefUnwindSafe for FontAtlas

§

impl Send for FontAtlas

§

impl Sync for FontAtlas

§

impl Unpin for FontAtlas

§

impl UnsafeUnpin for FontAtlas

§

impl UnwindSafe for FontAtlas

Blanket Implementations§

§

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

§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
§

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

§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
§

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

§

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

Mutably borrows from an owned value. Read more
§

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

§

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
§

impl<T> From<T> for T

§

fn from(t: T) -> T

Returns the argument unchanged.

§

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

§

fn into(self) -> U

Calls U::from(self).

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

§

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

§

type Error = Infallible

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

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
§

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

§

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

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

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

Performs the conversion.