### Load and Rasterize Font Glyph in Rust Source: https://github.com/alexheretic/ab-glyph/blob/main/glyph/README.md Demonstrates loading a font from a byte slice, getting a glyph for a character, scaling and positioning it, and then outlining and drawing the glyph. Requires the `ab_glyph` crate. ```rust use ab_glyph::{FontRef, Font, Glyph, point}; let font = FontRef::try_from_slice(include_bytes!("../../dev/fonts/Exo2-Light.otf"))?; // Get a glyph for 'q' with a scale & position. let q_glyph: Glyph = font.glyph_id('q').with_scale_and_position(24.0, point(100.0, 0.0)); // Draw it. if let Some(q) = font.outline_glyph(q_glyph) { q.draw(|x, y, c| { /* draw pixel `(x, y)` with coverage: `c` */ }); } ``` -------------------------------- ### Get Pre-rendered Glyph Image (Emoji/Bitmap Fonts) Source: https://context7.com/alexheretic/ab-glyph/llms.txt Retrieves raw raster image data for glyphs that lack vector outlines, such as color emoji. Useful for handling emoji or bitmap font glyphs. Requires a font that supports raster images. ```rust use ab_glyph::{Font, FontRef, GlyphId, v2::GlyphImage, GlyphImageFormat, InvalidFont}; fn try_get_emoji_image(font: &impl Font, ch: char) -> Option<()> { let id = font.glyph_id(ch); // Request the largest available strike if let Some(img) = font.glyph_raster_image2(id, u16::MAX) { println!( "Raster image: {}x{} px, {} bytes, format={:?}, pixels_per_em={}", img.width, img.height, img.data.len(), img.format, img.pixels_per_em ); // For PNG: decode with an image library and scale to target size // For BitmapGray8: each byte is one pixel of grayscale coverage } None } fn main() -> Result<(), InvalidFont> { // Emoji fonts would return Some here; outline fonts return None let font = FontRef::try_from_slice(include_bytes!("fonts/Exo2-Light.otf"))?; let result = font.glyph_raster_image2(font.glyph_id('A'), u16::MAX); assert!(result.is_none(), "outline font has no raster images"); Ok(()) } ``` -------------------------------- ### Get Layout-Space Bounding Box of Glyph with ab-glyph Source: https://context7.com/alexheretic/ab-glyph/llms.txt Use `Font::glyph_bounds` to get the layout-space bounding rectangle of a glyph, which is based on typographic metrics and suitable for layout calculations. This differs from `px_bounds` which is for pixel rendering. ```rust use ab_glyph::{Font, FontRef, point, InvalidFont}; fn main() -> Result<(), InvalidFont> { let font = FontRef::try_from_slice(include_bytes!("fonts/Exo2-Light.otf"))?; let glyph = font.glyph_id('H').with_scale_and_position(48.0, point(0.0, 0.0)); let layout_rect = font.glyph_bounds(&glyph); println!( "Layout bounds: x={:.2}..{:.2}, y={:.2}..{:.2}", layout_rect.min.x, layout_rect.max.x, layout_rect.min.y, layout_rect.max.y ); Ok(()) } ``` -------------------------------- ### Get Pixel Bounding Box of Glyph Outline with ab-glyph Source: https://context7.com/alexheretic/ab-glyph/llms.txt Use `OutlinedGlyph::px_bounds` to obtain the exact pixel-space bounding box of a glyph outline. These coordinates are suitable for direct pixel placement. ```rust use ab_glyph::{Font, FontRef, point, Rect, InvalidFont}; fn main() -> Result<(), InvalidFont> { let font = FontRef::try_from_slice(include_bytes!("fonts/Exo2-Light.otf"))?; let glyph = font.glyph_id('g').with_scale_and_position(40.0, point(10.0, 30.0)); if let Some(outlined) = font.outline_glyph(glyph) { let Rect { min, max } = outlined.px_bounds(); println!("min=({}, {}), max=({}, {})", min.x, min.y, max.x, max.y); println!("size: {}x{}", max.x - min.x, max.y - min.y); } Ok(()) } ``` -------------------------------- ### Get Raw SVG Glyph Data Source: https://context7.com/alexheretic/ab-glyph/llms.txt Retrieves raw SVG or SVGZ bytes for a range of glyphs. The caller must handle rendering and scaling of the SVG data. Returns `None` if no SVG data is available for the glyph. ```rust use ab_glyph::{Font, FontArc, InvalidFont}; fn main() -> Result<(), InvalidFont> { let font = FontArc::try_from_slice(include_bytes!("fonts/Exo2-Light.otf"))?; let id = font.glyph_id('A'); match font.glyph_svg_image(id) { Some(svg) => { println!( "SVG data: {} bytes, glyph range GlyphId({})..=GlyphId({})", svg.data.len(), svg.start_glyph_id.0, svg.end_glyph_id.0 ); // Pass svg.data to an SVG renderer (e.g., resvg) } None => println!("No SVG data for this glyph"), } Ok(()) } ``` -------------------------------- ### Configure ab_glyph for no_std Environments Source: https://github.com/alexheretic/ab-glyph/blob/main/glyph/README.md Shows how to configure the ab_glyph crate for no_std environments by disabling default features and enabling the 'libm' feature for mathematical operations. ```toml ab_glyph = { default-features = false, features = ["libm"] } ``` -------------------------------- ### Scale Font to Pixels with `as_scaled` and `into_scaled` Source: https://context7.com/alexheretic/ab-glyph/llms.txt Use `as_scaled` for a borrowed `PxScaleFont` or `into_scaled` to consume the font and create a `PxScaleFont`. This provides pre-scaled typographic metrics in pixels. The scale can be changed on a `PxScaleFont` using `with_scale`. ```rust use ab_glyph::{Font, FontRef, PxScale, ScaleFont, InvalidFont}; fn main() -> Result<(), InvalidFont> { let font = FontRef::try_from_slice(include_bytes!("fonts/Exo2-Light.otf"))?; // Borrow-based: font is still usable afterward let scaled = font.as_scaled(PxScale::from(45.0)); assert_eq!(scaled.height(), 45.0); let b_advance = scaled.h_advance(scaled.glyph_id('b')); println!("'b' h_advance at 45px: {:.3}", b_advance); // => 21.225 // Switch scale on the same PxScaleFont let bigger = scaled.with_scale(180.0); assert_eq!(bigger.height(), 180.0); println!("'b' h_advance at 180px: {:.1}", bigger.h_advance(bigger.glyph_id('b'))); // => 84.9 // Consuming version — moves font into the PxScaleFont let owned_scaled = font.into_scaled(24.0); println!("descent at 24px: {:.4}", owned_scaled.descent()); // => -4.0200 Ok(()) } ``` -------------------------------- ### Create a new coverage rasterizer Source: https://context7.com/alexheretic/ab-glyph/llms.txt Allocates a width x height pixel grid initialized to zero coverage. Automatically selects the best available SIMD implementation at first construction. ```rust use ab_glyph_rasterizer::{Rasterizer, point}; let mut r = Rasterizer::new(14, 38); assert_eq!(r.dimensions(), (14, 38)); println!("{:?}", r); // => Rasterizer { width: 14, height: 38 } ``` -------------------------------- ### Enable no_std Support with libm Feature Source: https://github.com/alexheretic/ab-glyph/blob/main/rasterizer/README.md Configure Cargo.toml to use ab_glyph_rasterizer in a no_std environment by disabling default features and enabling the 'libm' feature. ```toml ab_glyph_rasterizer = { default-features = false, features = ["libm"] } ``` -------------------------------- ### Create Positioned and Scaled Glyph with ab-glyph Source: https://context7.com/alexheretic/ab-glyph/llms.txt Use `with_scale_and_position` to create a `Glyph` ready for outlining. A shorthand `with_scale` is available for positioning at (0.0, 0.0). ```rust use ab_glyph::{Font, FontRef, Glyph, GlyphId, PxScale, point, InvalidFont}; fn main() -> Result<(), InvalidFont> { let font = FontRef::try_from_slice(include_bytes!("fonts/Exo2-Light.otf"))?; // Glyph 'q' at 24px, positioned at (100.0, 50.0) let q_glyph: Glyph = font .glyph_id('q') .with_scale_and_position(24.0, point(100.0, 50.0)); assert_eq!(q_glyph.scale, PxScale::from(24.0)); assert_eq!(q_glyph.position, point(100.0, 50.0)); // Shorthand: scale only, position defaults to (0.0, 0.0) let w_glyph: Glyph = font.glyph_id('w').with_scale(48.0); assert_eq!(w_glyph.position, point(0.0, 0.0)); Ok(()) } ``` -------------------------------- ### `Font::as_scaled` / `Font::into_scaled` Source: https://context7.com/alexheretic/ab-glyph/llms.txt Returns a `PxScaleFont` that provides pre-scaled typographic metrics (ascent, descent, h_advance, kern, etc.) directly in pixels. `as_scaled` borrows the font, while `into_scaled` consumes it. ```APIDOC ## `Font::as_scaled` / `Font::into_scaled` — Associate a font with a pixel scale Returns a `PxScaleFont` that provides pre-scaled typographic metrics (ascent, descent, h_advance, kern, etc.) directly in pixels. ```rust use ab_glyph::{Font, FontRef, PxScale, ScaleFont, InvalidFont}; fn main() -> Result<(), InvalidFont> { let font = FontRef::try_from_slice(include_bytes!("fonts/Exo2-Light.otf"))?; // Borrow-based: font is still usable afterward let scaled = font.as_scaled(PxScale::from(45.0)); assert_eq!(scaled.height(), 45.0); let b_advance = scaled.h_advance(scaled.glyph_id('b')); println!("'b' h_advance at 45px: {:.3}", b_advance); // => 21.225 // Switch scale on the same PxScaleFont let bigger = scaled.with_scale(180.0); assert_eq!(bigger.height(), 180.0); println!("'b' h_advance at 180px: {:.1}", bigger.h_advance(bigger.glyph_id('b'))); // => 84.9 // Consuming version — moves font into the PxScaleFont let owned_scaled = font.into_scaled(24.0); println!("descent at 24px: {:.4}", owned_scaled.descent()); // => -4.0200 Ok(()) } ``` ``` -------------------------------- ### Rasterizer::new Source: https://context7.com/alexheretic/ab-glyph/llms.txt Creates a new coverage rasterizer with a specified width and height. It initializes a pixel grid to zero coverage and automatically selects the best available SIMD implementation. ```APIDOC ## Rasterizer::new — Create a new coverage rasterizer Allocates a `width × height` pixel grid initialized to zero coverage. Automatically selects the best available SIMD implementation (AVX2 or SSE4.2 on x86/x86_64 with the `std` feature) at first construction. ```rust use ab_glyph_rasterizer::{Rasterizer, point}; let mut r = Rasterizer::new(14, 38); assert_eq!(r.dimensions(), (14, 38)); println!("{:?}", r); // => Rasterizer { width: 14, height: 38 } ``` ``` -------------------------------- ### Convert Point Sizes to Pixel Scale with `pt_to_px_scale` Source: https://context7.com/alexheretic/ab-glyph/llms.txt Convert typographic point sizes to `PxScale` by accounting for screen DPI (defaults to 96 DPI). This is useful for rendering text at consistent sizes across different displays. For HiDPI screens, multiply the point size by the scale factor before conversion. ```rust use ab_glyph::{Font, FontRef, ScaleFont, InvalidFont}; fn main() -> Result<(), InvalidFont> { let font = FontRef::try_from_slice(include_bytes!("fonts/Exo2-Light.otf"))?; // Convert 12pt at 96 DPI to a PxScale let px_scale = font.pt_to_px_scale(12.0).expect("valid font"); println!("12pt => PxScale {{ x: {:.4}, y: {:.4} }}", px_scale.x, px_scale.y); // => 12pt => PxScale { x: 16.0000, y: 16.0000 } // For HiDPI (2x): multiply pt_size by scale factor let hidpi_scale = font.pt_to_px_scale(12.0 * 2.0).expect("valid font"); println!("12pt @2x => {:.1}px height", hidpi_scale.y); // => 12pt @2x => 32.0px height Ok(()) } ``` -------------------------------- ### Draw a Glyph with ab_glyph_rasterizer Source: https://github.com/alexheretic/ab-glyph/blob/main/rasterizer/README.md Demonstrates drawing a character by sequentially calling draw_cubic and draw_line methods. After drawing, iterate over pixel alphas using for_each_pixel. ```rust let mut rasterizer = ab_glyph_rasterizer::Rasterizer::new(106, 183); // draw a 300px 'ę' character rasterizer.draw_cubic(point(103.0, 163.5), point(86.25, 169.25), point(77.0, 165.0), point(82.25, 151.5)); rasterizer.draw_cubic(point(82.25, 151.5), point(86.75, 139.75), point(94.0, 130.75), point(102.0, 122.0)); rasterizer.draw_line(point(102.0, 122.0), point(100.25, 111.25)); rasterizer.draw_cubic(point(100.25, 111.25), point(89.0, 112.75), point(72.75, 114.25), point(58.5, 114.25)); rasterizer.draw_cubic(point(58.5, 114.25), point(30.75, 114.25), point(18.5, 105.25), point(16.75, 72.25)); rasterizer.draw_line(point(16.75, 72.25), point(77.0, 72.25)); rasterizer.draw_cubic(point(77.0, 72.25), point(97.0, 72.25), point(105.25, 60.25), point(104.75, 38.5)); rasterizer.draw_cubic(point(104.75, 38.5), point(104.5, 13.5), point(89.0, 0.75), point(54.25, 0.75)); rasterizer.draw_cubic(point(54.25, 0.75), point(16.0, 0.75), point(0.0, 16.75), point(0.0, 64.0)); rasterizer.draw_cubic(point(0.0, 64.0), point(0.0, 110.5), point(16.0, 128.0), point(56.5, 128.0)); rasterizer.draw_cubic(point(56.5, 128.0), point(66.0, 128.0), point(79.5, 127.0), point(90.0, 125.0)); rasterizer.draw_cubic(point(90.0, 125.0), point(78.75, 135.25), point(73.25, 144.5), point(70.75, 152.0)); rasterizer.draw_cubic(point(70.75, 152.0), point(64.5, 169.0), point(75.5, 183.0), point(105.0, 170.5)); rasterizer.draw_line(point(105.0, 170.5), point(103.0, 163.5)); rasterizer.draw_cubic(point(55.0, 14.5), point(78.5, 14.5), point(88.5, 21.75), point(88.75, 38.75)); rasterizer.draw_cubic(point(88.75, 38.75), point(89.0, 50.75), point(85.75, 59.75), point(73.5, 59.75)); rasterizer.draw_line(point(73.5, 59.75), point(16.5, 59.75)); rasterizer.draw_cubic(point(16.5, 59.75), point(17.25, 25.5), point(27.0, 14.5), point(55.0, 14.5)); rasterizer.draw_line(point(55.0, 14.5), point(55.0, 14.5)); // iterate over the resultant pixel alphas, e.g. save pixel to a buffer rasterizer.for_each_pixel(|index, alpha| { // ... }); ``` -------------------------------- ### Iterate pixel coverage by flat index Source: https://context7.com/alexheretic/ab-glyph/llms.txt Calls FnMut(usize, f32) for every pixel in row-major order. The index runs from 0 to width * height - 1. ```rust use ab_glyph_rasterizer::{Rasterizer, point}; let (w, h) = (8, 8); let mut r = Rasterizer::new(w, h); r.draw_line(point(0.0, 0.0), point(8.0, 8.0)); let mut pixels = vec![0u8; w * h]; r.for_each_pixel(|index, alpha| { pixels[index] = (alpha.min(1.0) * 255.0) as u8; }); println!("Non-zero pixels: {}", pixels.iter().filter(|&&v| v > 0).count()); ``` -------------------------------- ### Rasterize a quadratic Bézier curve Source: https://context7.com/alexheretic/ab-glyph/llms.txt Tessellates a quadratic Bézier from p0 to p2 (control point p1) into line segments and accumulates coverage. ```rust use ab_glyph_rasterizer::{Rasterizer, point}; let mut r = Rasterizer::new(14, 38); // Quadratic Bézier: start, control, end r.draw_quad( point(6.2, 34.5), // start point(7.2, 34.5), // control point(9.2, 34.0), // end ); let mut pixels = vec![0u8; 14 * 38]; r.for_each_pixel(|idx, alpha| { pixels[idx] = (alpha.min(1.0) * 255.0) as u8; }); ``` -------------------------------- ### Iterate pixel coverage by (x, y) Source: https://context7.com/alexheretic/ab-glyph/llms.txt Convenience wrapper over for_each_pixel that yields (x: u32, y: u32, alpha: f32) coordinates directly. ```rust use ab_glyph_rasterizer::{Rasterizer, point}; let (w, h) = (16, 16); let mut r = Rasterizer::new(w, h); r.draw_quad(point(2.0, 14.0), point(8.0, 2.0), point(14.0, 14.0)); // Write into an RGBA image buffer let mut image = vec![0u8; w * h * 4]; r.for_each_pixel_2d(|x, y, alpha| { let idx = (y as usize * w + x as usize) * 4; let val = (alpha.min(1.0) * 255.0) as u8; image[idx] = val; // R image[idx + 1] = val; // G image[idx + 2] = val; // B image[idx + 3] = val; // A }); ``` -------------------------------- ### GlyphId::with_scale_and_position Source: https://context7.com/alexheretic/ab-glyph/llms.txt Creates a Glyph ready for outlining by attaching a PxScale and a Point position to a GlyphId. Supports shorthand for scale-only creation. ```APIDOC ## GlyphId::with_scale_and_position — Create a positioned, scaled glyph Attaches a `PxScale` and a `Point` position to a `GlyphId` to produce a `Glyph` ready for outlining. ### Method Signature `GlyphId::with_scale_and_position(scale: impl Into, position: Point) GlyphId::with_scale(scale: impl Into)` ### Parameters - `scale`: The desired scale for the glyph. - `position`: The desired position for the glyph. ### Example ```rust use ab_glyph::{Font, FontRef, Glyph, GlyphId, PxScale, point, InvalidFont}; fn main() -> Result<(), InvalidFont> { let font = FontRef::try_from_slice(include_bytes!("fonts/Exo2-Light.otf"))?; // Glyph 'q' at 24px, positioned at (100.0, 50.0) let q_glyph: Glyph = font .glyph_id('q') .with_scale_and_position(24.0, point(100.0, 50.0)); // Shorthand: scale only, position defaults to (0.0, 0.0) let w_glyph: Glyph = font.glyph_id('w').with_scale(48.0); Ok(()) } ``` ``` -------------------------------- ### `PxScale` Type Source: https://context7.com/alexheretic/ab-glyph/llms.txt Represents horizontal and vertical pixel-height scaling. `From` provides uniform scaling, while direct construction allows asymmetric values for stretched text rendering. Includes a `round()` method. ```APIDOC ## `PxScale` — Pixel scale type Represents horizontal and vertical pixel-height scaling. `From` gives uniform scaling (`x == y`). Can be constructed with asymmetric values for stretched text rendering. ```rust use ab_glyph::PxScale; // Uniform: 24 pixels tall let uniform = PxScale::from(24.0); assert_eq!(uniform.x, 24.0); assert_eq!(uniform.y, 24.0); // Asymmetric: 2× horizontal stretch (useful for ASCII art rendering) let stretched = PxScale { x: 48.0, y: 24.0 }; // Round to nearest integer pixel scale let rounded = PxScale { x: 23.7, y: 23.7 }.round(); assert_eq!(rounded, PxScale::from(24.0)); ``` ``` -------------------------------- ### Reuse Rasterizer without reallocating Source: https://context7.com/alexheretic/ab-glyph/llms.txt reset(w, h) resizes and zeroes the grid (no alloc if total pixels <= current capacity). clear() zeroes the grid keeping the same dimensions. ```rust use ab_glyph_rasterizer::Rasterizer; let mut r = Rasterizer::new(14, 38); // Resize to a smaller glyph — no allocation r.reset(12, 24); assert_eq!(r.dimensions(), (12, 24)); // Re-draw on the same allocator, different glyph r.clear(); assert_eq!(r.dimensions(), (12, 24)); ``` -------------------------------- ### Load Font from Static Byte Slice with FontRef Source: https://context7.com/alexheretic/ab-glyph/llms.txt Use `FontRef::try_from_slice` to load font data embedded as a static byte slice. This method is efficient as it avoids copying the font data. It returns a `Result`. ```rust use ab_glyph::{FontRef, Font, InvalidFont}; fn main() -> Result<(), InvalidFont> { // Load an OTF or TTF font from a static byte slice let font = FontRef::try_from_slice(include_bytes!("fonts/Exo2-Light.otf"))?; println!("Glyph count: {}", font.glyph_count()); // => Glyph count: 908 println!("Units per em: {:?}", font.units_per_em()); // => Units per em: Some(1000.0) println!("Ascent (unscaled): {}", font.ascent_unscaled()); // => Ascent (unscaled): 800.0 println!("Descent (unscaled): {}", font.descent_unscaled()); // => Descent (unscaled): -201.0 println!("Italic angle: {}", font.italic_angle()); // => Italic angle: 0.0 (non-italic fonts return 0.0) Ok(()) } ``` -------------------------------- ### Rasterize a cubic Bézier curve Source: https://context7.com/alexheretic/ab-glyph/llms.txt Tessellates a cubic Bézier from p0 to p3 (control points p1, p2) using a recursive subdivision approach. ```rust use ab_glyph_rasterizer::{Rasterizer, point}; let mut r = Rasterizer::new(12, 20); r.draw_cubic( point(10.3, 16.4), // start point(8.6, 16.9), // control 1 point(7.7, 16.5), // control 2 point(8.2, 15.2), // end ); let mut coverage = vec![0.0f32; 12 * 20]; r.for_each_pixel(|idx, alpha| { coverage[idx] = alpha; }); ``` -------------------------------- ### `ScaleFont` Trait Source: https://context7.com/alexheretic/ab-glyph/llms.txt The `ScaleFont` trait provides pixel-scaled versions of all layout metrics, implemented by `PxScaleFont`. Key methods include `ascent()`, `descent()`, `height()`, `line_gap()`, `h_advance(id)`, `h_side_bearing(id)`, `kern(first, second)`, and `scaled_glyph(c)`. ```APIDOC ## `ScaleFont` — Trait for scaled font metrics `ScaleFont` is implemented by `PxScaleFont` and provides pixel-scaled versions of all layout metrics. Key methods: `ascent()`, `descent()`, `height()`, `line_gap()`, `h_advance(id)`, `h_side_bearing(id)`, `kern(first, second)`, `scaled_glyph(c)`. ```rust use ab_glyph::{Font, FontRef, PxScale, ScaleFont, point, InvalidFont}; fn layout_word(text: &str) -> Result<(), InvalidFont> { let font = FontRef::try_from_slice(include_bytes!("fonts/Exo2-Light.otf"))?; let sf = font.as_scaled(PxScale::from(32.0)); println!("ascent={:.2} descent={:.2} line_gap={:.2}", sf.ascent(), sf.descent(), sf.line_gap()); let mut x = 0.0f32; let mut prev_id = None; for ch in text.chars() { let id = sf.glyph_id(ch); // Apply kerning from the previous glyph if let Some(prev) = prev_id { x += sf.kern(prev, id); } let glyph = sf.scaled_glyph(ch); println!(" '{}' at x={:.2} advance={:.2}", ch, x, sf.h_advance(id)); x += sf.h_advance(id); prev_id = Some(id); } Ok(()) } fn main() -> Result<(), ab_glyph::InvalidFont> { layout_word("Hi") // ascent=25.60 descent=-6.43 line_gap=0.00 // 'H' at x=0.00 advance=22.94 // 'i' at x=22.94 advance=9.34 } ``` ``` -------------------------------- ### Low-Level Unscaled Outline Access Source: https://context7.com/alexheretic/ab-glyph/llms.txt Provides access to the raw Bézier curves and unscaled bounding box of a glyph. This is useful for custom rendering pipelines that require direct manipulation of the glyph's geometry. ```rust use ab_glyph::{Font, FontRef, OutlineCurve, InvalidFont}; fn main() -> Result<(), InvalidFont> { let font = FontRef::try_from_slice(include_bytes!("fonts/Exo2-Light.otf"))?; let id = font.glyph_id('S'); if let Some(outline) = font.outline(id) { println!("Unscaled bounds: {:?}", outline.bounds); for curve in &outline.curves { match curve { OutlineCurve::Line(p0, p1) => println!(" Line {:?} -> {:?}", p0, p1), OutlineCurve::Quad(p0, p1, p2) => println!(" Quad {:?} {:?} {:?}", p0, p1, p2), OutlineCurve::Cubic(p0,p1,p2,p3) => println!(" Cubic {:?} {:?} {:?} {:?}", p0,p1,p2,p3), } } println!("Total curves: {}", outline.curves.len()); } Ok(()) } ``` -------------------------------- ### Rasterizer::reset / Rasterizer::clear Source: https://context7.com/alexheretic/ab-glyph/llms.txt Provides methods to reuse the rasterizer without reallocating. `reset(w, h)` resizes and zeroes the grid, while `clear()` zeroes the grid keeping the same dimensions. ```APIDOC ## Rasterizer::reset / Rasterizer::clear — Reuse without reallocating `reset(w, h)` resizes and zeroes the grid (no alloc if total pixels ≤ current capacity). `clear()` zeroes the grid keeping the same dimensions. ```rust use ab_glyph_rasterizer::Rasterizer; let mut r = Rasterizer::new(14, 38); // Resize to a smaller glyph — no allocation r.reset(12, 24); assert_eq!(r.dimensions(), (12, 24)); // Re-draw on the same allocator, different glyph r.clear(); assert_eq!(r.dimensions(), (12, 24)); ``` ``` -------------------------------- ### Rasterizer::for_each_pixel Source: https://context7.com/alexheretic/ab-glyph/llms.txt Iterates over each pixel's coverage by its flat index in row-major order. The index ranges from 0 to width * height - 1. ```APIDOC ## Rasterizer::for_each_pixel — Iterate pixel coverage by flat index Calls `FnMut(usize, f32)` for every pixel in row-major order. The index runs from `0` to `width * height - 1`. ```rust use ab_glyph_rasterizer::{Rasterizer, point}; let (w, h) = (8, 8); let mut r = Rasterizer::new(w, h); r.draw_line(point(0.0, 0.0), point(8.0, 8.0)); let mut pixels = vec![0u8; w * h]; r.for_each_pixel(|index, alpha| { pixels[index] = (alpha.min(1.0) * 255.0) as u8; }); println!("Non-zero pixels: {}", pixels.iter().filter(|&&v| v > 0).count()); ``` ``` -------------------------------- ### Rasterizer::for_each_pixel_2d Source: https://context7.com/alexheretic/ab-glyph/llms.txt A convenience wrapper for `for_each_pixel` that yields pixel coverage with (x, y) coordinates directly. ```APIDOC ## Rasterizer::for_each_pixel_2d — Iterate pixel coverage by (x, y) Convenience wrapper over `for_each_pixel` that yields `(x: u32, y: u32, alpha: f32)` coordinates directly. ```rust use ab_glyph_rasterizer::{Rasterizer, point}; let (w, h) = (16, 16); let mut r = Rasterizer::new(w, h); r.draw_quad(point(2.0, 14.0), point(8.0, 2.0), point(14.0, 14.0)); // Write into an RGBA image buffer let mut image = vec![0u8; w * h * 4]; r.for_each_pixel_2d(|x, y, alpha| { let idx = (y as usize * w + x as usize) * 4; let val = (alpha.min(1.0) * 255.0) as u8; image[idx] = val; // R image[idx + 1] = val; // G image[idx + 2] = val; // B image[idx + 3] = val; // A }); ``` ``` -------------------------------- ### Load Font with Arc for Shared Ownership Source: https://context7.com/alexheretic/ab-glyph/llms.txt Use `FontArc::try_from_slice` or `FontArc::try_from_vec` to wrap font data in an `Arc`. This allows for cheap cloning and type-erased sharing across threads, making it `Send + Sync`. ```rust use ab_glyph::{FontArc, Font, GlyphId, InvalidFont}; use std::sync::Arc; use std::thread; fn main() -> Result<(), InvalidFont> { // From a static slice (wraps FontRef internally) let font = FontArc::try_from_slice(include_bytes!("fonts/Exo2-Light.otf"))?; assert_eq!(font.glyph_id('s'), GlyphId(56)); // Cheap clone — shares the underlying Arc let font_clone = font.clone(); let handle = thread::spawn(move || { println!("Thread glyph count: {}", font_clone.glyph_count()); }); handle.join().unwrap(); // From owned bytes (wraps FontVec internally) let owned_data = include_bytes!("fonts/Exo2-Light.otf").to_vec(); let font2 = FontArc::try_from_vec(owned_data)?; assert_eq!(font2.font_data().len(), font.font_data().len()); Ok(()) } ``` -------------------------------- ### Access Scaled Font Metrics with `ScaleFont` Trait Source: https://context7.com/alexheretic/ab-glyph/llms.txt The `ScaleFont` trait provides pixel-scaled layout metrics like ascent, descent, height, and kerning. Implementations include `PxScaleFont`. Use methods like `ascent()`, `descent()`, `height()`, `line_gap()`, `h_advance(id)`, `kern(first, second)`, and `scaled_glyph(c)`. ```rust use ab_glyph::{Font, FontRef, PxScale, ScaleFont, point, InvalidFont}; fn layout_word(text: &str) -> Result<(), InvalidFont> { let font = FontRef::try_from_slice(include_bytes!("fonts/Exo2-Light.otf"))?; let sf = font.as_scaled(PxScale::from(32.0)); println!("ascent={:.2} descent={:.2} line_gap={:.2}", sf.ascent(), sf.descent(), sf.line_gap()); let mut x = 0.0f32; let mut prev_id = None; for ch in text.chars() { let id = sf.glyph_id(ch); // Apply kerning from the previous glyph if let Some(prev) = prev_id { x += sf.kern(prev, id); } let glyph = sf.scaled_glyph(ch); println!(" '{}' at x={:.2} advance={:.2}", ch, x, sf.h_advance(id)); x += sf.h_advance(id); prev_id = Some(id); } Ok(()) } fn main() -> Result<(), ab_glyph::InvalidFont> { layout_word("Hi") // ascent=25.60 descent=-6.43 line_gap=0.00 // 'H' at x=0.00 advance=22.94 // 'i' at x=22.94 advance=9.34 } ``` -------------------------------- ### Load Font from Owned Bytes with FontVec Source: https://context7.com/alexheretic/ab-glyph/llms.txt Use `FontVec::try_from_vec` when font data is loaded at runtime into an owned `Vec`. This method consumes the vector. ```rust use ab_glyph::{FontVec, Font, InvalidFont}; use std::fs; fn main() -> Result<(), InvalidFont> { let data = fs::read("fonts/Exo2-Light.otf").expect("font file not found"); let font = FontVec::try_from_vec(data)?; println!("Glyph count: {}", font.glyph_count()); Ok(()) } ``` -------------------------------- ### Font::outline Source: https://context7.com/alexheretic/ab-glyph/llms.txt Provides low-level access to the unscaled outline data of a glyph. It returns a raw `Outline` struct containing the bounding box and a vector of Bézier curves, suitable for custom rendering pipelines. ```APIDOC ## Font::outline ### Description Returns a raw `Outline` (unscaled bounding box + `Vec`) for a glyph ID. This is useful when you need the raw Bézier curves for custom rendering pipelines. ### Method This is a method on the `Font` trait. ### Parameters - **glyph_id** (`GlyphId`) - The ID of the glyph for which to retrieve the outline. ### Response - `Some(Outline)` - If outline data is available for the glyph. The `Outline` struct contains bounds and a vector of `OutlineCurve`. - `None` - If the glyph does not have outline data. ### Response Structure (`Outline`) - **bounds** (`ab_glyph::Rect`) - The unscaled bounding box of the glyph outline. - **curves** (`Vec`) - A vector of Bézier curves defining the glyph shape. ### Response Structure (`OutlineCurve` variants) - `OutlineCurve::Line(p0, p1)` - `OutlineCurve::Quad(p0, p1, p2)` - `OutlineCurve::Cubic(p0, p1, p2, p3)` ### Request Example ```rust use ab_glyph::{Font, FontRef, OutlineCurve, InvalidFont}; fn get_glyph_outline(font: &impl Font, ch: char) -> Option { let id = font.glyph_id(ch); font.outline(id) } ``` ### Usage Example ```rust let font = FontRef::try_from_slice(include_bytes!("fonts/Exo2-Light.otf"))?; if let Some(outline) = get_glyph_outline(&font, 'S') { println!("Unscaled bounds: {:?}", outline.bounds); for curve in &outline.curves { match curve { OutlineCurve::Line(p0, p1) => println!(" Line {:?} -> {:?}", p0, p1), OutlineCurve::Quad(p0, p1, p2) => println!(" Quad {:?} {:?} {:?}", p0, p1, p2), OutlineCurve::Cubic(p0,p1,p2,p3) => println!(" Cubic {:?} {:?} {:?} {:?}", p0,p1,p2,p3), } } println!("Total curves: {}", outline.curves.len()); } ``` ``` -------------------------------- ### Rasterizer::draw_quad Source: https://context7.com/alexheretic/ab-glyph/llms.txt Rasterizes a quadratic Bézier curve from p0 to p2 (with control point p1) by tessellating it into line segments and accumulating coverage. ```APIDOC ## Rasterizer::draw_quad — Rasterize a quadratic Bézier curve Tessellates a quadratic Bézier from `p0` to `p2` (control point `p1`) into line segments and accumulates coverage. ```rust use ab_glyph_rasterizer::{Rasterizer, point}; let mut r = Rasterizer::new(14, 38); // Quadratic Bézier: start, control, end r.draw_quad( point(6.2, 34.5), // start point(7.2, 34.5), // control point(9.2, 34.0), // end ); let mut pixels = vec![0u8; 14 * 38]; r.for_each_pixel(|idx, alpha| { pixels[idx] = (alpha.min(1.0) * 255.0) as u8; }); ``` ``` -------------------------------- ### `Font::pt_to_px_scale` Source: https://context7.com/alexheretic/ab-glyph/llms.txt Converts a typographic point size (e.g. `12pt`) to `PxScale`, taking screen DPI into account (assumes 96 DPI). Useful for converting standard point sizes to pixel scaling factors. ```APIDOC ## `Font::pt_to_px_scale` — Convert point sizes to PxScale Converts a typographic point size (e.g. `12pt`) to `PxScale` taking screen DPI into account (assumes 96 DPI). ```rust use ab_glyph::{Font, FontRef, ScaleFont, InvalidFont}; fn main() -> Result<(), InvalidFont> { let font = FontRef::try_from_slice(include_bytes!("fonts/Exo2-Light.otf"))?; // Convert 12pt at 96 DPI to a PxScale let px_scale = font.pt_to_px_scale(12.0).expect("valid font"); println!("12pt => PxScale {{ x: {:.4}, y: {:.4} }}", px_scale.x, px_scale.y); // => 12pt => PxScale { x: 16.0000, y: 16.0000 } // For HiDPI (2x): multiply pt_size by scale factor let hidpi_scale = font.pt_to_px_scale(12.0 * 2.0).expect("valid font"); println!("12pt @2x => {:.1}px height", hidpi_scale.y); // => 12pt @2x => 32.0px height Ok(()) } ``` ``` -------------------------------- ### FontRef::try_from_slice Source: https://context7.com/alexheretic/ab-glyph/llms.txt Loads an OpenType font from a static byte slice (`&'static [u8]`). This is efficient when font data is embedded using `include_bytes!` or already has a static lifetime. ```APIDOC ## FontRef::try_from_slice — Load a font from a static byte slice Parses OpenType font data from a `&'static [u8]` without copying. Returns `Result`. Prefer this when the font bytes are embedded via `include_bytes!` or have a `'static` lifetime. ### Method ```rust FontRef::try_from_slice(bytes: &'static [u8]) -> Result ``` ### Parameters - **bytes** (`&'static [u8]`) - The static byte slice containing the font data. ### Returns - `Ok(FontRef)` on successful parsing. - `Err(InvalidFont)` if the font data is invalid. ### Example ```rust use ab_glyph::{FontRef, Font, InvalidFont}; fn main() -> Result<(), InvalidFont> { let font = FontRef::try_from_slice(include_bytes!("fonts/Exo2-Light.otf"))?; println!("Glyph count: {}", font.glyph_count()); Ok(()) } ``` ``` -------------------------------- ### Rasterize a straight line segment Source: https://context7.com/alexheretic/ab-glyph/llms.txt Accumulates coverage for a straight line from p0 to p1 into the pixel grid using a scanline algorithm. ```rust use ab_glyph_rasterizer::{Rasterizer, point}; let mut r = Rasterizer::new(9, 8); // Draw a nearly-horizontal line r.draw_line(point(0.0, 0.48), point(8.0, 0.48)); let mut pixels = vec![0u8; 9 * 8]; r.for_each_pixel(|idx, alpha| { pixels[idx] = (alpha * 255.0) as u8; }); ``` -------------------------------- ### Represent Pixel Scaling with `PxScale` Type Source: https://context7.com/alexheretic/ab-glyph/llms.txt The `PxScale` type represents horizontal and vertical pixel-height scaling. It can be constructed with uniform values (using `From`) or asymmetric values for stretched text rendering. Use `.round()` to round to the nearest integer pixel scale. ```rust use ab_glyph::PxScale; // Uniform: 24 pixels tall let uniform = PxScale::from(24.0); assert_eq!(uniform.x, 24.0); assert_eq!(uniform.y, 24.0); // Asymmetric: 2× horizontal stretch (useful for ASCII art rendering) let stretched = PxScale { x: 48.0, y: 24.0 }; // Round to nearest integer pixel scale let rounded = PxScale { x: 23.7, y: 23.7 }.round(); assert_eq!(rounded, PxScale::from(24.0)); ``` -------------------------------- ### Rasterize Glyph Outline to Pixel Coverage with ab-glyph Source: https://context7.com/alexheretic/ab-glyph/llms.txt Use `OutlinedGlyph::draw` to rasterize a glyph's outline. It calls a closure for each pixel within the bounding box, providing coverage values from 0.0 to 1.0. ```rust use ab_glyph::{Font, FontRef, point, InvalidFont}; fn main() -> Result<(), InvalidFont> { let font = FontRef::try_from_slice(include_bytes!("fonts/Exo2-Light.otf"))?; let glyph = font.glyph_id('A').with_scale_and_position(32.0, point(0.0, 0.0)); if let Some(outlined) = font.outline_glyph(glyph) { let bounds = outlined.px_bounds(); let width = bounds.width() as usize; let height = bounds.height() as usize; // Allocate a grayscale pixel buffer let mut pixels = vec![0u8; width * height]; outlined.draw(|x, y, coverage| { // x and y are relative to the bounding box origin let idx = x as usize + y as usize * width; pixels[idx] = (coverage.min(1.0) * 255.0) as u8; }); println!("Rendered 'A' into a {}x{} pixel buffer.", width, height); // Rendered 'A' into a 21x25 pixel buffer. } Ok(()) } ```