///|
let atlas_width : Int = 1024
///|
let atlas_height : Int = 1024
///|
let atlas_padding : Int = 1
///|
priv struct NativeFontCache {
text_engine : NativeTextEngine
}
///|
// Opaque native text engine selected by platform hosts. Platform packages
// construct one with `native_platform_text_engine`; optional fallback behavior
// is explicit so renderer/wgpu stays independent from concrete text engines.
pub struct NativeTextEngine {
priv provider : NativePlatformTextProvider
priv fallback : NativePlatformTextProvider?
}
///|
pub(all) enum NativeTextEngineSetting {
MoonCosmic
PlatformDefault
} derive(Eq, Debug, ToJson)
///|
// Callback bundle implemented by a platform text engine such as CoreText,
// DirectWrite, or fontconfig/HarfBuzz/FreeType.
pub struct NativePlatformTextProvider {
priv id : String
priv measure : (@core.TextLayoutInput) -> NativeTextLayout?
priv layout_run : (@core.TextRun, Double) -> NativeTextLayout?
priv raster_glyph : (String, Bytes) -> NativeRasterGlyph?
priv register_font_data : (@core.FontFamily, Bytes) -> Unit
}
///|
priv struct GlyphAtlasEntry {
x : Int
y : Int
width : Int
height : Int
bearing_x : Int
bearing_y : Int
format : NativeRasterGlyphFormat
}
///|
// Renderer-private glyph key. Platform providers own the payload encoding;
// `cache_key` must be stable across frames and include all raster-affecting
// fields such as glyph identity, size, style, and scale.
pub struct NativeGlyphKey {
priv cache_key : String
priv payload : Bytes
}
///|
pub(all) enum NativeRasterGlyphFormat {
AlphaMask
ColorRgba
} derive(Eq, Debug, ToJson)
///|
// Positioned glyph produced by platform text layout. Coordinates are logical
// pixels relative to the text run before frame alignment is applied.
pub struct NativeGlyphPlacement {
priv key : NativeGlyphKey
priv x : Double
priv y : Double
}
///|
// Text layout returned by platform providers. Measurement must provide a
// monotonic caret array covering the input text; render layout may omit carets
// but must provide valid metrics and glyph placements.
pub struct NativeTextLayout {
priv size : @core.Size
priv baseline : Double
priv caret_positions : Array[Double]
priv glyphs : Array[NativeGlyphPlacement]
}
///|
// Glyph bitmap returned by a native text provider. Alpha glyphs are tinted by
// the text run color; color glyphs carry RGBA pixel payloads and preserve
// native emoji/color-font raster output while still applying run opacity.
pub struct NativeRasterGlyph {
priv width : Int
priv height : Int
priv bearing_x : Int
priv bearing_y : Int
priv format : NativeRasterGlyphFormat
priv pixels : Bytes
}
///|
priv enum GlyphLookup {
GlyphReady(GlyphAtlasEntry)
GlyphMissing
GlyphAtlasFull
}
///|
priv struct GlyphAtlas {
width : Int
height : Int
padding : Int
mut next_x : Int
mut next_y : Int
mut shelf_height : Int
mut entries : Map[String, GlyphAtlasEntry]
mut pixels : Array[Byte]
mut dirty : Bool
}
///|
priv struct TextVertex {
x : Double
y : Double
u : Double
v : Double
r : Double
g : Double
b : Double
a : Double
color_glyph : Double
}
///|
let text_vertex_stride : UInt64 = 36UL
///|
priv struct TextRunBuildResult {
vertices : Array[TextVertex]
atlas_full : Bool
}
///|
priv enum TextRunAppendResult {
TextRunAppendComplete(Bool)
TextRunAppendNeedsFallback
}
///|
fn NativeFontCache::new() -> NativeFontCache {
NativeFontCache::new_with_engine(native_noop_text_engine())
}
///|
fn NativeFontCache::new_with_engine(
text_engine : NativeTextEngine,
) -> NativeFontCache {
{ text_engine, }
}
///|
fn NativeTextEngine::id(self : NativeTextEngine) -> String {
self.provider.id
}
///|
pub fn NativeTextEngine::provider_id(self : NativeTextEngine) -> String {
self.provider.id
}
///|
pub fn NativeTextEngine::fallback_provider_id(
self : NativeTextEngine,
) -> String {
match self.fallback {
Some(provider) => provider.id
None => ""
}
}
///|
pub fn NativePlatformTextProvider::new(
id~ : String,
measure~ : (@core.TextLayoutInput) -> NativeTextLayout?,
layout_run~ : (@core.TextRun, Double) -> NativeTextLayout?,
raster_glyph~ : (String, Bytes) -> NativeRasterGlyph?,
register_font_data? : (@core.FontFamily, Bytes) -> Unit = (_family, _data) => {
()
},
) -> NativePlatformTextProvider {
{ id, measure, layout_run, raster_glyph, register_font_data }
}
///|
pub fn native_platform_text_engine(
provider : NativePlatformTextProvider,
) -> NativeTextEngine {
{ provider, fallback: None }
}
///|
pub fn native_platform_text_engine_with_fallback(
provider : NativePlatformTextProvider,
fallback~ : NativeTextEngine,
) -> NativeTextEngine {
{ provider, fallback: Some(fallback.provider) }
}
///|
fn native_noop_text_engine() -> NativeTextEngine {
native_platform_text_engine(
NativePlatformTextProvider::new(
id="native-wgpu-noop-text",
measure=_input => None,
layout_run=(_run, _scale_factor) => None,
raster_glyph=(_cache_key, _payload) => None,
),
)
}
///|
// Create a platform glyph key. The renderer treats payload as opaque data and
// passes it back to the provider's raster callback.
pub fn native_platform_glyph_key(
cache_key~ : String,
payload~ : Bytes,
) -> NativeGlyphKey {
{ cache_key, payload }
}
///|
// Create a positioned platform glyph in logical run coordinates.
pub fn NativeGlyphPlacement::new(
key~ : NativeGlyphKey,
x~ : Double,
y? : Double = 0.0,
) -> NativeGlyphPlacement {
{ key, x, y }
}
///|
pub fn NativeGlyphPlacement::key(self : NativeGlyphPlacement) -> NativeGlyphKey {
self.key
}
///|
pub fn NativeGlyphPlacement::x(self : NativeGlyphPlacement) -> Double {
self.x
}
///|
pub fn NativeGlyphPlacement::y(self : NativeGlyphPlacement) -> Double {
self.y
}
///|
// Create a provider layout value. Invalid metrics or non-monotonic carets are
// filtered by the renderer and trigger fallback.
pub fn NativeTextLayout::new(
size~ : @core.Size,
baseline~ : Double,
caret_positions? : Array[Double] = [],
glyphs? : Array[NativeGlyphPlacement] = [],
) -> NativeTextLayout {
{ size, baseline, caret_positions, glyphs }
}
///|
pub fn NativeTextLayout::size(self : NativeTextLayout) -> @core.Size {
self.size
}
///|
pub fn NativeTextLayout::baseline(self : NativeTextLayout) -> Double {
self.baseline
}
///|
pub fn NativeTextLayout::caret_positions(
self : NativeTextLayout,
) -> Array[Double] {
self.caret_positions
}
///|
pub fn NativeTextLayout::glyphs(
self : NativeTextLayout,
) -> Array[NativeGlyphPlacement] {
self.glyphs
}
///|
// Create a provider raster glyph. The renderer validates dimensions against the
// pixel buffer before uploading it to the atlas.
pub fn NativeRasterGlyph::new(
width~ : Int,
height~ : Int,
bearing_x~ : Int,
bearing_y~ : Int,
format? : NativeRasterGlyphFormat = NativeRasterGlyphFormat::AlphaMask,
pixels~ : Bytes,
) -> NativeRasterGlyph {
{ width, height, bearing_x, bearing_y, format, pixels }
}
///|
pub fn NativeRasterGlyph::width(self : NativeRasterGlyph) -> Int {
self.width
}
///|
pub fn NativeRasterGlyph::height(self : NativeRasterGlyph) -> Int {
self.height
}
///|
pub fn NativeRasterGlyph::bearing_x(self : NativeRasterGlyph) -> Int {
self.bearing_x
}
///|
pub fn NativeRasterGlyph::bearing_y(self : NativeRasterGlyph) -> Int {
self.bearing_y
}
///|
pub fn NativeRasterGlyph::format(
self : NativeRasterGlyph,
) -> NativeRasterGlyphFormat {
self.format
}
///|
pub fn NativeRasterGlyph::pixels(self : NativeRasterGlyph) -> Bytes {
self.pixels
}