///|
fn normalized_text_measurement_width(width : Float) -> Float {
if font_descriptor_scalar_is_finite(width) && width > 0.0 {
width
} else {
1000000000.0
}
}
///|
/// Value-layer request for measuring or shaping a text run with stable cache
/// identity and explicit font/fallback dependencies.
pub(all) struct TextMeasurementDescriptor {
run : TextRunDescriptor
font_key : RendererResourceKey
width : Float
measure_bounds : Bool
shape : Bool
} derive(Debug, Eq)
///|
pub fn TextMeasurementDescriptor::new(
run? : TextRunDescriptor = TextRunDescriptor::new(),
font_key? : RendererResourceKey = RendererResourceKey::font(b""),
width? : Float = 1000000000.0,
measure_bounds? : Bool = true,
shape? : Bool = false,
) -> TextMeasurementDescriptor {
{
run,
font_key,
width: normalized_text_measurement_width(width),
measure_bounds,
shape,
}
}
///|
pub fn TextMeasurementDescriptor::is_shaped(
self : TextMeasurementDescriptor,
) -> Bool {
self.shape
}
///|
pub fn TextMeasurementDescriptor::with_run(
self : TextMeasurementDescriptor,
run : TextRunDescriptor,
) -> TextMeasurementDescriptor {
{ ..self, run, }
}
///|
pub fn TextMeasurementDescriptor::with_font_key(
self : TextMeasurementDescriptor,
font_key : RendererResourceKey,
) -> TextMeasurementDescriptor {
{ ..self, font_key, }
}
///|
pub fn TextMeasurementDescriptor::with_width(
self : TextMeasurementDescriptor,
width : Float,
) -> TextMeasurementDescriptor {
{ ..self, width: normalized_text_measurement_width(width) }
}
///|
pub fn TextMeasurementDescriptor::with_measure_bounds(
self : TextMeasurementDescriptor,
measure_bounds : Bool,
) -> TextMeasurementDescriptor {
{ ..self, measure_bounds, }
}
///|
pub fn TextMeasurementDescriptor::with_shape(
self : TextMeasurementDescriptor,
shape : Bool,
) -> TextMeasurementDescriptor {
{ ..self, shape, }
}
///|
pub fn TextMeasurementDescriptor::resource_key(
self : TextMeasurementDescriptor,
text : Bytes,
) -> RendererResourceKey {
RendererResourceKey::text_run(
b"moui_skia:text-measurement:v1" +
text_run_cache_bytes(self.run.resource_key(text, font_key=self.font_key).id) +
self.width.to_be_bytes() +
text_run_cache_bytes(text_run_cache_bool(self.measure_bounds)) +
text_run_cache_bytes(text_run_cache_bool(self.shape)),
)
}
///|
pub fn TextMeasurementDescriptor::resource_descriptor(
self : TextMeasurementDescriptor,
text : Bytes,
byte_size? : Int64 = -1L,
) -> RendererResourceDescriptor {
let id = self.resource_key(text).id
let measured_byte_size = if byte_size < 0L {
id.length().to_int64()
} else {
byte_size
}
RendererResourceDescriptor::text_run(id, byte_size=measured_byte_size)
}
///|
pub fn TextMeasurementDescriptor::resource_plan(
self : TextMeasurementDescriptor,
text : Bytes,
measurement_byte_size? : Int64 = -1L,
text_byte_size? : Int64 = -1L,
font_byte_size? : Int64 = 0L,
fallback_byte_size? : Int64 = -1L,
) -> RendererResourcePlan {
let descriptors : Array[RendererResourceDescriptor] = Array::new()
descriptors.push(
self.resource_descriptor(text, byte_size=measurement_byte_size),
)
for
descriptor in self.run.resource_plan(
text,
font_key=self.font_key,
text_byte_size~,
font_byte_size~,
fallback_byte_size~,
).descriptors {
descriptors.push(descriptor)
}
RendererResourcePlan::new(descriptors)
}
///|
fn normalized_measured_text_advance(advance : Float) -> Float {
if font_descriptor_scalar_is_finite(advance) && advance >= 0.0 {
advance
} else {
0.0
}
}
///|
fn normalized_measured_text_bounds(bounds : Rect?) -> Rect? {
match bounds {
None => None
Some(bounds) =>
if bounds.is_finite() {
Some(bounds.sorted())
} else {
None
}
}
}
///|
fn measured_text_bounds_cache_id(bounds : Rect?) -> Bytes {
match bounds {
None => b"none"
Some(bounds) =>
b"some" +
bounds.left().to_be_bytes() +
bounds.top().to_be_bytes() +
bounds.right().to_be_bytes() +
bounds.bottom().to_be_bytes()
}
}
///|
/// Value-layer metadata for a native text measurement result.
pub(all) struct MeasuredTextRunDescriptor {
measurement : TextMeasurementDescriptor
advance : Float
bounds : Rect?
} derive(Debug, Eq)
///|
pub fn MeasuredTextRunDescriptor::new(
measurement? : TextMeasurementDescriptor = TextMeasurementDescriptor::new(),
advance? : Float = 0.0,
bounds? : Rect? = None,
) -> MeasuredTextRunDescriptor {
{
measurement,
advance: normalized_measured_text_advance(advance),
bounds: normalized_measured_text_bounds(bounds),
}
}
///|
pub fn TextMeasurementDescriptor::measured_run_descriptor(
self : TextMeasurementDescriptor,
advance? : Float = 0.0,
bounds? : Rect? = None,
) -> MeasuredTextRunDescriptor {
MeasuredTextRunDescriptor::new(measurement=self, advance~, bounds~)
}
///|
pub fn MeasuredTextRunDescriptor::has_bounds(
self : MeasuredTextRunDescriptor,
) -> Bool {
self.bounds is Some(_)
}
///|
pub fn MeasuredTextRunDescriptor::is_valid(
self : MeasuredTextRunDescriptor,
) -> Bool {
let bounds_valid = match self.bounds {
None => true
Some(bounds) => bounds.is_finite() && bounds.is_sorted()
}
font_descriptor_scalar_is_finite(self.advance) &&
self.advance >= 0.0 &&
bounds_valid
}
///|
fn MeasuredTextRunDescriptor::resource_id(
self : MeasuredTextRunDescriptor,
text : Bytes,
) -> Bytes {
if !self.is_valid() {
b""
} else {
b"moui_skia:measured-text-run:v1" +
text_run_cache_bytes(self.measurement.resource_key(text).id) +
self.advance.to_be_bytes() +
measured_text_bounds_cache_id(self.bounds)
}
}
///|
pub fn MeasuredTextRunDescriptor::resource_key(
self : MeasuredTextRunDescriptor,
text : Bytes,
) -> RendererResourceKey {
RendererResourceKey::text_run(self.resource_id(text))
}
///|
pub fn MeasuredTextRunDescriptor::resource_descriptor(
self : MeasuredTextRunDescriptor,
text : Bytes,
byte_size? : Int64 = -1L,
) -> RendererResourceDescriptor {
let id = self.resource_id(text)
let measured_byte_size = if byte_size < 0L {
id.length().to_int64()
} else {
byte_size
}
RendererResourceDescriptor::text_run(id, byte_size=measured_byte_size)
}
///|
pub fn MeasuredTextRunDescriptor::resource_plan(
self : MeasuredTextRunDescriptor,
text : Bytes,
measured_byte_size? : Int64 = -1L,
measurement_byte_size? : Int64 = -1L,
text_byte_size? : Int64 = -1L,
font_byte_size? : Int64 = 0L,
fallback_byte_size? : Int64 = -1L,
) -> RendererResourcePlan {
let descriptors : Array[RendererResourceDescriptor] = Array::new()
descriptors.push(self.resource_descriptor(text, byte_size=measured_byte_size))
if self.is_valid() {
for
descriptor in self.measurement.resource_plan(
text,
measurement_byte_size~,
text_byte_size~,
font_byte_size~,
fallback_byte_size~,
).descriptors {
descriptors.push(descriptor)
}
}
RendererResourcePlan::new(descriptors)
}