lumen-engine-text 0.2.0

Text layout and glyph data helpers for the Lumen engine.
Documentation
use bytemuck::{Pod, Zeroable};
use cosmic_text::{SwashContent, SwashImage};

#[cfg(feature = "experimental-msdf")]
use crate::MsdfGlyphPlacement;
use crate::{AtlasEntry, TextGlyph};

const GLYPH_MODE_RASTER_MASK: u32 = 0;
const GLYPH_MODE_RASTER_COLOR: u32 = 1;
#[cfg(feature = "experimental-msdf")]
const GLYPH_MODE_MSDF: u32 = 2;

#[repr(C)]
#[derive(Debug, Clone, Copy, Pod, Zeroable)]
pub struct GpuTextGlobals {
    pub target_size: [f32; 2],
    pub px_range: f32,
    pub glyph_count: u32,
}

#[repr(C)]
#[derive(Debug, Clone, Copy, Pod, Zeroable)]
pub struct GpuGlyphInstance {
    pub rect: [f32; 4],
    pub uv_rect: [f32; 4],
    pub color: [f32; 4],
    pub mode: u32,
    pub _padding: [u32; 3],
}

#[cfg(feature = "experimental-msdf")]
#[repr(C)]
#[derive(Debug, Clone, Copy, Pod, Zeroable)]
pub struct GpuMsdfGlobals {
    pub atlas_size: [u32; 2],
    pub job_count: u32,
    pub dirty_pixel_count: u32,
    pub _padding: [u32; 2],
}

#[cfg(feature = "experimental-msdf")]
#[repr(C)]
#[derive(Debug, Clone, Copy, Pod, Zeroable)]
pub struct GpuMsdfJob {
    pub atlas_rect: [u32; 4],
    pub segment_range: [u32; 2],
    pub pixel_range: [u32; 2],
    pub px_range: f32,
    pub _padding: [u32; 3],
}

#[cfg(feature = "experimental-msdf")]
#[repr(C)]
#[derive(Debug, Clone, Copy, Pod, Zeroable)]
pub struct GpuMsdfSegment {
    pub p0: [f32; 2],
    pub p1: [f32; 2],
    pub p2: [f32; 2],
    pub p3: [f32; 2],
    pub kind: u32,
    pub channels: u32,
    pub _padding: [u32; 2],
}

pub fn glyph_instance_for(
    glyph: &TextGlyph,
    atlas_entry: AtlasEntry,
    image: &SwashImage,
) -> GpuGlyphInstance {
    let x = glyph.x + image.placement.left as f32;
    let y = glyph.y - image.placement.top as f32;
    GpuGlyphInstance {
        rect: [
            x,
            y,
            image.placement.width as f32,
            image.placement.height as f32,
        ],
        uv_rect: [
            atlas_entry.uv_min[0],
            atlas_entry.uv_min[1],
            atlas_entry.uv_max[0],
            atlas_entry.uv_max[1],
        ],
        color: glyph.color,
        mode: if image.content == SwashContent::Color {
            GLYPH_MODE_RASTER_COLOR
        } else {
            GLYPH_MODE_RASTER_MASK
        },
        _padding: [0; 3],
    }
}

#[cfg(feature = "experimental-msdf")]
pub fn msdf_glyph_instance_for(
    glyph: &TextGlyph,
    atlas_entry: AtlasEntry,
    placement: &MsdfGlyphPlacement,
) -> GpuGlyphInstance {
    let x = glyph.x + placement.left;
    let y = glyph.y - placement.top;
    GpuGlyphInstance {
        rect: [x, y, placement.width as f32, placement.height as f32],
        uv_rect: [
            atlas_entry.uv_min[0],
            atlas_entry.uv_min[1],
            atlas_entry.uv_max[0],
            atlas_entry.uv_max[1],
        ],
        color: glyph.color,
        mode: GLYPH_MODE_MSDF,
        _padding: [0; 3],
    }
}

#[cfg(feature = "experimental-msdf")]
pub fn is_msdf_instance(instance: &GpuGlyphInstance) -> bool {
    instance.mode == GLYPH_MODE_MSDF
}