///|
extern "C" fn native_font_default(size : Float) -> FontHandle = "moonbit_skia_font_default"
///|
extern "C" fn native_font_empty(size : Float) -> FontHandle = "moonbit_skia_font_empty"
///|
#borrow(typeface)
extern "C" fn native_font_from_typeface(
typeface : TypefaceHandle,
size : Float,
) -> FontHandle = "moonbit_skia_font_from_typeface"
///|
#borrow(font)
extern "C" fn native_font_is_null(font : FontHandle) -> Bool = "moonbit_skia_font_is_null"
///|
#borrow(font)
extern "C" fn native_font_size(font : FontHandle) -> Float = "moonbit_skia_font_size"
///|
#borrow(font)
extern "C" fn native_font_set_size(font : FontHandle, size : Float) -> Unit = "moonbit_skia_font_set_size"
///|
#borrow(font, text)
extern "C" fn native_font_measure_text_utf8(
font : FontHandle,
text : Bytes,
) -> Float = "moonbit_skia_font_measure_text_utf8"
///|
#borrow(font, text)
extern "C" fn native_font_count_text_utf8(
font : FontHandle,
text : Bytes,
) -> Int = "moonbit_skia_font_count_text_utf8"
///|
#borrow(font, text)
extern "C" fn native_font_text_to_glyphs_utf8_value(
font : FontHandle,
text : Bytes,
index : Int,
) -> Int = "moonbit_skia_font_text_to_glyphs_utf8_value"
///|
#borrow(font)
extern "C" fn native_font_glyph_width(font : FontHandle, glyph : Int) -> Float = "moonbit_skia_font_glyph_width"
///|
#borrow(font)
extern "C" fn native_font_glyph_bounds_left(
font : FontHandle,
glyph : Int,
) -> Float = "moonbit_skia_font_glyph_bounds_left"
///|
#borrow(font)
extern "C" fn native_font_glyph_bounds_top(
font : FontHandle,
glyph : Int,
) -> Float = "moonbit_skia_font_glyph_bounds_top"
///|
#borrow(font)
extern "C" fn native_font_glyph_bounds_right(
font : FontHandle,
glyph : Int,
) -> Float = "moonbit_skia_font_glyph_bounds_right"
///|
#borrow(font)
extern "C" fn native_font_glyph_bounds_bottom(
font : FontHandle,
glyph : Int,
) -> Float = "moonbit_skia_font_glyph_bounds_bottom"
///|
#borrow(font, text)
extern "C" fn native_font_measure_text_bounds_utf8(
font : FontHandle,
text : Bytes,
) -> Bool = "moonbit_skia_font_measure_text_bounds_utf8"
///|
#borrow(font, text)
extern "C" fn native_font_measure_text_bounds_utf8_left(
font : FontHandle,
text : Bytes,
) -> Float = "moonbit_skia_font_measure_text_bounds_utf8_left"
///|
#borrow(font, text)
extern "C" fn native_font_measure_text_bounds_utf8_top(
font : FontHandle,
text : Bytes,
) -> Float = "moonbit_skia_font_measure_text_bounds_utf8_top"
///|
#borrow(font, text)
extern "C" fn native_font_measure_text_bounds_utf8_right(
font : FontHandle,
text : Bytes,
) -> Float = "moonbit_skia_font_measure_text_bounds_utf8_right"
///|
#borrow(font, text)
extern "C" fn native_font_measure_text_bounds_utf8_bottom(
font : FontHandle,
text : Bytes,
) -> Float = "moonbit_skia_font_measure_text_bounds_utf8_bottom"
///|
#borrow(font)
extern "C" fn native_font_metrics_value(
font : FontHandle,
metric : Int,
) -> Float = "moonbit_skia_font_metrics_value"
///|
#borrow(font)
extern "C" fn native_font_metrics_has(font : FontHandle, metric : Int) -> Bool = "moonbit_skia_font_metrics_has"
///|
#borrow(font, text)
extern "C" fn native_font_shape_text_utf8(
font : FontHandle,
text : Bytes,
width : Float,
left_to_right : Bool,
) -> ShapedTextRunHandle = "moonbit_skia_font_shape_text_utf8"
///|
#borrow(run)
extern "C" fn native_shaped_text_run_is_null(run : ShapedTextRunHandle) -> Bool = "moonbit_skia_shaped_text_run_is_null"
///|
#borrow(run)
extern "C" fn native_shaped_text_run_glyph_count(
run : ShapedTextRunHandle,
) -> Int = "moonbit_skia_shaped_text_run_glyph_count"
///|
#borrow(run)
extern "C" fn native_shaped_text_run_advance_x(
run : ShapedTextRunHandle,
) -> Float = "moonbit_skia_shaped_text_run_advance_x"
///|
#borrow(run)
extern "C" fn native_shaped_text_run_advance_y(
run : ShapedTextRunHandle,
) -> Float = "moonbit_skia_shaped_text_run_advance_y"
///|
#borrow(run)
extern "C" fn native_shaped_text_run_glyph_value(
run : ShapedTextRunHandle,
index : Int,
) -> Int = "moonbit_skia_shaped_text_run_glyph_value"
///|
#borrow(run)
extern "C" fn native_shaped_text_run_position_x(
run : ShapedTextRunHandle,
index : Int,
) -> Float = "moonbit_skia_shaped_text_run_position_x"
///|
#borrow(run)
extern "C" fn native_shaped_text_run_position_y(
run : ShapedTextRunHandle,
index : Int,
) -> Float = "moonbit_skia_shaped_text_run_position_y"
///|
#borrow(run)
extern "C" fn native_shaped_text_run_cluster_value(
run : ShapedTextRunHandle,
index : Int,
) -> Int = "moonbit_skia_shaped_text_run_cluster_value"
///|
extern "C" fn native_typeface_default() -> TypefaceHandle = "moonbit_skia_typeface_default"
///|
extern "C" fn native_font_mgr_default() -> FontMgrHandle = "moonbit_skia_font_mgr_default"
///|
#borrow(font_mgr)
extern "C" fn native_font_mgr_is_null(font_mgr : FontMgrHandle) -> Bool = "moonbit_skia_font_mgr_is_null"
///|
#borrow(font_mgr)
extern "C" fn native_font_mgr_count_families(font_mgr : FontMgrHandle) -> Int = "moonbit_skia_font_mgr_count_families"
///|
#borrow(font_mgr)
extern "C" fn native_font_mgr_family_name(
font_mgr : FontMgrHandle,
index : Int,
) -> Bytes = "moonbit_skia_font_mgr_family_name"
///|
#borrow(font_mgr, family_name)
extern "C" fn native_font_mgr_match_family_style(
font_mgr : FontMgrHandle,
family_name : Bytes,
weight : Int,
width : Int,
slant : Int,
) -> TypefaceHandle = "moonbit_skia_font_mgr_match_family_style"
///|
#borrow(font_mgr, family_name, language_tag)
extern "C" fn native_font_mgr_match_family_style_character(
font_mgr : FontMgrHandle,
family_name : Bytes,
language_tag : Bytes,
character : Int,
weight : Int,
width : Int,
slant : Int,
) -> TypefaceHandle = "moonbit_skia_font_mgr_match_family_style_character"
///|
#borrow(family_name)
extern "C" fn native_typeface_from_name(
family_name : Bytes,
weight : Int,
width : Int,
slant : Int,
) -> TypefaceHandle = "moonbit_skia_typeface_from_name"
///|
#borrow(path)
extern "C" fn native_typeface_from_file(
path : Bytes,
index : Int,
) -> TypefaceHandle = "moonbit_skia_typeface_from_file"
///|
/// Creates a typeface from in-memory font data (e.g. an embedded TTF/OTF) via
/// the default font manager. The typeface is not registered anywhere; use
/// `register_data` when the family must also be visible to paragraph layout.
#borrow(data)
extern "C" fn native_typeface_from_data(
data : Bytes,
index : Int,
) -> TypefaceHandle = "moonbit_skia_typeface_from_data"
///|
/// Creates a typeface from in-memory font data and registers it under
/// `alias` (plus its own family name) in the C++ embedded-font registry so
/// that paragraph layout can resolve the family too.
#borrow(family_alias, data)
extern "C" fn native_typeface_register_data(
family_alias : Bytes,
data : Bytes,
index : Int,
) -> TypefaceHandle = "moonbit_skia_typeface_register_data"
///|
/// Returns a cloned typeface with one variation axis applied. `axis` is the
/// 4-byte OpenType tag (e.g. b"wght"). The clone inherits the typeface's
/// existing variation coordinates, so calls compose.
#borrow(typeface, axis)
extern "C" fn native_typeface_clone_variation(
typeface : TypefaceHandle,
axis : Bytes,
value : Float,
) -> TypefaceHandle = "moonbit_skia_typeface_clone_variation"
///|
#borrow(typeface)
extern "C" fn native_typeface_is_null(typeface : TypefaceHandle) -> Bool = "moonbit_skia_typeface_is_null"
///|
#borrow(typeface)
extern "C" fn native_typeface_is_bold(typeface : TypefaceHandle) -> Bool = "moonbit_skia_typeface_is_bold"
///|
#borrow(typeface)
extern "C" fn native_typeface_is_italic(typeface : TypefaceHandle) -> Bool = "moonbit_skia_typeface_is_italic"
///|
#borrow(typeface)
extern "C" fn native_typeface_is_fixed_pitch(typeface : TypefaceHandle) -> Bool = "moonbit_skia_typeface_is_fixed_pitch"
///|
#borrow(typeface)
extern "C" fn native_typeface_family_name(typeface : TypefaceHandle) -> Bytes = "moonbit_skia_typeface_family_name"
///|
#borrow(typeface)
extern "C" fn native_typeface_has_color_glyphs(
typeface : TypefaceHandle,
) -> Bool = "moonbit_skia_typeface_has_color_glyphs"
///|
fn Font::from_handle(handle : FontHandle) -> Font? {
if native_font_is_null(handle) {
None
} else {
Some({ handle, })
}
}
///|
fn native_font_scalar_is_finite(value : Float) -> Bool {
value == value && value - value == 0.0
}
///|
fn native_font_positive_scalar_is_valid(value : Float) -> Bool {
native_font_scalar_is_finite(value) && value > 0.0
}
///|
fn native_font_position_scalar(value : Float) -> Float {
if native_font_scalar_is_finite(value) {
value
} else {
0.0
}
}
///|
fn native_font_position_origin(origin : @skia.Point) -> @skia.Point {
@skia.Point::new(
native_font_position_scalar(origin.x),
native_font_position_scalar(origin.y),
)
}
///|
pub fn Font::default(size? : Float = 12.0) -> Font? {
if !native_font_positive_scalar_is_valid(size) {
None
} else {
Font::from_handle(native_font_default(size))
}
}
///|
pub fn Font::empty(size? : Float = 12.0) -> Font? {
if !native_font_positive_scalar_is_valid(size) {
None
} else {
Font::from_handle(native_font_empty(size))
}
}
///|
pub fn Font::from_typeface(typeface : Typeface, size? : Float = 12.0) -> Font? {
if !native_font_positive_scalar_is_valid(size) {
None
} else {
Font::from_handle(native_font_from_typeface(typeface.handle, size))
}
}
///|
pub fn Font::is_available(self : Font) -> Bool {
!native_font_is_null(self.handle)
}
///|
pub fn Font::size(self : Font) -> Float {
native_font_size(self.handle)
}
///|
pub fn Font::set_size(self : Font, size : Float) -> Unit {
if native_font_positive_scalar_is_valid(size) {
native_font_set_size(self.handle, size)
}
}
///|
pub fn Font::measure_text_utf8(self : Font, text : Bytes) -> Float {
if text.is_empty() {
0.0
} else {
native_font_measure_text_utf8(self.handle, text)
}
}
///|
pub fn Font::count_text_utf8(self : Font, text : Bytes) -> Int {
if text.is_empty() {
0
} else {
native_font_count_text_utf8(self.handle, text)
}
}
///|
pub fn Font::text_to_glyphs_utf8(self : Font, text : Bytes) -> Array[GlyphId] {
if text.is_empty() {
[]
} else {
let count = native_font_count_text_utf8(self.handle, text)
let glyphs : Array[GlyphId] = Array::new(capacity=count)
for i in 0.. Float {
native_font_glyph_width(self.handle, glyph.to_int())
}
///|
pub fn Font::glyph_widths(self : Font, glyphs : Array[GlyphId]) -> Array[Float] {
// Build the result in MoonBit rather than calling the C batch function
// native_font_glyph_widths. The C function returns MoonbitSkiaFloatArray*
// (a regular object with a buffer pointer), whose memory layout is
// incompatible with MoonBit's Array[Float] (a val array with inline data
// and length stored in the object header meta). Calling it directly causes
// garbage lengths and data to be read, failing the native smoke test.
let widths : Array[Float] = Array::new(capacity=glyphs.length())
for glyph in glyphs {
widths.push(self.glyph_width(glyph))
}
widths
}
///|
pub fn Font::glyph_x_positions(
self : Font,
glyphs : Array[GlyphId],
origin? : Float = 0.0,
) -> Array[Float] {
let positions : Array[Float] = Array::new(capacity=glyphs.length())
let origin = native_font_position_scalar(origin)
for x = origin, i = 0; i < glyphs.length(); i = i + 1 {
positions.push(x)
continue x + self.glyph_width(glyphs[i]), i + 1
}
positions
}
///|
pub fn Font::glyph_positions(
self : Font,
glyphs : Array[GlyphId],
origin? : @skia.Point = @skia.Point::new(0.0, 0.0),
) -> Array[@skia.Point] {
let positions : Array[@skia.Point] = Array::new(capacity=glyphs.length())
let origin = native_font_position_origin(origin)
let x_positions = self.glyph_x_positions(glyphs, origin=origin.x)
for x in x_positions {
positions.push(@skia.Point::new(x, origin.y))
}
positions
}
///|
pub fn Font::text_glyph_x_positions_utf8(
self : Font,
text : Bytes,
origin? : Float = 0.0,
) -> Array[Float] {
// Build the result in MoonBit rather than calling the C batch function
// native_font_text_glyph_x_positions_utf8. The C function returns
// MoonbitSkiaFloatArray* whose memory layout is incompatible with
// MoonBit's Array[Float] (val array with inline data).
if text.is_empty() {
[]
} else {
let glyphs = self.text_to_glyphs_utf8(text)
self.glyph_x_positions(glyphs, origin~)
}
}
///|
pub fn Font::text_glyph_positions_utf8(
self : Font,
text : Bytes,
origin? : @skia.Point = @skia.Point::new(0.0, 0.0),
) -> Array[@skia.Point] {
// Build the result in MoonBit rather than calling the C batch function
// native_font_text_glyph_positions_utf8. The C function returns
// MoonbitSkiaPointArray* whose memory layout is incompatible with
// MoonBit's Array[@skia.Point].
if text.is_empty() {
[]
} else {
let glyphs = self.text_to_glyphs_utf8(text)
self.glyph_positions(glyphs, origin~)
}
}
///|
pub fn Font::glyph_bounds(self : Font, glyph : GlyphId) -> @skia.Rect {
let glyph_int = glyph.to_int()
@skia.Rect::new(
native_font_glyph_bounds_left(self.handle, glyph_int),
native_font_glyph_bounds_top(self.handle, glyph_int),
native_font_glyph_bounds_right(self.handle, glyph_int),
native_font_glyph_bounds_bottom(self.handle, glyph_int),
)
}
///|
pub fn Font::glyph_bounds_many(
self : Font,
glyphs : Array[GlyphId],
) -> Array[@skia.Rect] {
// Build the result in MoonBit rather than calling the C batch function
// native_font_glyph_bounds_many. The C function returns
// MoonbitSkiaRectArray* whose memory layout is incompatible with
// MoonBit's Array[@skia.Rect].
let bounds : Array[@skia.Rect] = Array::new(capacity=glyphs.length())
for glyph in glyphs {
bounds.push(self.glyph_bounds(glyph))
}
bounds
}
///|
pub fn Font::measure_text_bounds_utf8(self : Font, text : Bytes) -> @skia.Rect? {
if text.is_empty() || !native_font_measure_text_bounds_utf8(self.handle, text) {
None
} else {
Some(
@skia.Rect::new(
native_font_measure_text_bounds_utf8_left(self.handle, text),
native_font_measure_text_bounds_utf8_top(self.handle, text),
native_font_measure_text_bounds_utf8_right(self.handle, text),
native_font_measure_text_bounds_utf8_bottom(self.handle, text),
),
)
}
}
///|
fn font_metric_optional(font : FontHandle, metric : Int) -> Float? {
if native_font_metrics_has(font, metric) {
Some(native_font_metrics_value(font, metric))
} else {
None
}
}
///|
pub fn Font::metrics(self : Font) -> FontMetrics {
let font = self.handle
{
top: native_font_metrics_value(font, 0),
ascent: native_font_metrics_value(font, 1),
descent: native_font_metrics_value(font, 2),
bottom: native_font_metrics_value(font, 3),
leading: native_font_metrics_value(font, 4),
average_char_width: native_font_metrics_value(font, 5),
max_char_width: native_font_metrics_value(font, 6),
x_min: native_font_metrics_value(font, 7),
x_max: native_font_metrics_value(font, 8),
x_height: native_font_metrics_value(font, 9),
cap_height: native_font_metrics_value(font, 10),
underline_thickness: font_metric_optional(font, 11),
underline_position: font_metric_optional(font, 12),
strikeout_thickness: font_metric_optional(font, 13),
strikeout_position: font_metric_optional(font, 14),
has_bounds: native_font_metrics_has(font, 15),
}
}
///|
fn ShapedTextRun::from_handle(handle : ShapedTextRunHandle) -> ShapedTextRun? {
if native_shaped_text_run_is_null(handle) {
None
} else {
Some({ handle, })
}
}
///|
pub fn Font::shape_text_utf8(
self : Font,
text : Bytes,
// Unconstrained wrap width for single-line runs. Keep finite and moderate so
// native shapers never allocate pathological run buffers.
width? : Float = 1000000.0,
left_to_right? : Bool = true,
) -> ShapedTextRun? {
if text.is_empty() || !native_font_positive_scalar_is_valid(width) {
None
} else {
ShapedTextRun::from_handle(
native_font_shape_text_utf8(self.handle, text, width, left_to_right),
)
}
}
///|
fn text_run_bytes_for_shaping(
text : Bytes,
run : @skia.TextRunDescriptor,
) -> Bytes {
let text_length = text.length()
let start = run.range.start.clamp(min=0, max=text_length)
let end = run.range.end.clamp(min=start, max=text_length)
if end <= start {
b""
} else {
let bytes : Array[Byte] = Array::new(capacity=end - start)
for index in start.. @skia.ShapedGlyphRunDescriptor? {
let run_text = text_run_bytes_for_shaping(text, shaping.run)
if run_text.is_empty() || shaping.run.is_empty() {
None
} else {
match
self.shape_text_utf8(
run_text,
width=shaping.width,
left_to_right=shaping.run.direction.is_left_to_right(),
) {
None => None
Some(run) => {
let glyphs = run.glyphs()
let glyph_ids : Array[Int] = Array::new(capacity=glyphs.length())
for glyph in glyphs {
glyph_ids.push(glyph.to_int())
}
let positions = run.positions()
let clusters = run.clusters()
let glyph_count = run.glyph_count()
if glyph_count <= 0 ||
glyphs.length() != glyph_count ||
positions.length() != glyph_count ||
clusters.length() != glyph_count {
return None
}
let shaped_run = shaping.shaped_run_descriptor(
glyph_count~,
cluster_count=clusters.length(),
advance=run.advance(),
)
let descriptor = shaped_run.glyph_run_descriptor(
glyph_ids~,
positions~,
clusters~,
)
if descriptor.is_valid() {
Some(descriptor)
} else {
None
}
}
}
}
}
///|
pub fn ShapedTextRun::is_available(self : ShapedTextRun) -> Bool {
!native_shaped_text_run_is_null(self.handle)
}
///|
pub fn ShapedTextRun::glyph_count(self : ShapedTextRun) -> Int {
native_shaped_text_run_glyph_count(self.handle)
}
///|
pub fn ShapedTextRun::advance(self : ShapedTextRun) -> @skia.Point {
@skia.Point::new(
native_shaped_text_run_advance_x(self.handle),
native_shaped_text_run_advance_y(self.handle),
)
}
///|
pub fn ShapedTextRun::glyphs(self : ShapedTextRun) -> Array[GlyphId] {
let count = self.glyph_count()
let glyphs : Array[GlyphId] = Array::new(capacity=count)
for index in 0.. Array[@skia.Point] {
let count = self.glyph_count()
let positions : Array[@skia.Point] = Array::new(capacity=count)
for index in 0.. Array[Int] {
let count = self.glyph_count()
let clusters : Array[Int] = Array::new(capacity=count)
for index in 0.. Float {
let metrics = self.metrics()
metrics.descent - metrics.ascent + metrics.leading
}
///|
fn Typeface::from_handle(handle : TypefaceHandle) -> Typeface? {
if native_typeface_is_null(handle) {
None
} else {
Some({ handle, })
}
}
///|
pub fn Typeface::default() -> Typeface? {
Typeface::from_handle(native_typeface_default())
}
///|
fn skia_font_style_weight(weight : Int) -> Int {
weight.clamp(min=1, max=1000)
}
///|
fn skia_font_style_width(width : Int) -> Int {
width.clamp(min=1, max=9)
}
///|
fn skia_font_style_slant(slant : Int) -> Int {
slant.clamp(min=0, max=2)
}
///|
pub fn Typeface::from_name(
family_name : Bytes,
weight? : Int = 400,
width? : Int = 5,
slant? : Int = 0,
) -> Typeface? {
if family_name.is_empty() {
None
} else {
Typeface::from_handle(
native_typeface_from_name(
family_name,
skia_font_style_weight(weight),
skia_font_style_width(width),
skia_font_style_slant(slant),
),
)
}
}
///|
pub fn Typeface::from_name_style(
family_name : Bytes,
style : @skia.FontStyleRequest,
) -> Typeface? {
Typeface::from_name(
family_name,
weight=style.weight,
width=style.width,
slant=style.slant,
)
}
///|
pub fn Typeface::from_file(path : Bytes, index? : Int = 0) -> Typeface? {
if path.is_empty() || index < 0 {
None
} else {
Typeface::from_handle(native_typeface_from_file(path, index))
}
}
///|
/// Creates a typeface from in-memory font data (embedded TTF/OTF bytes).
/// `index` selects a face from a TTC collection. The resulting typeface is
/// usable for measurement and drawing but is not registered for family-name
/// resolution; use `register_data` when paragraph layout must resolve it too.
pub fn Typeface::from_data(data : Bytes, index? : Int = 0) -> Typeface? {
if data.is_empty() || index < 0 {
None
} else {
Typeface::from_handle(native_typeface_from_data(data, index))
}
}
///|
/// Creates a typeface from in-memory font data and registers it under `alias`
/// (plus the font's own family name) in the embedded-font registry, so that
/// paragraph layout can resolve the family by name as well.
pub fn Typeface::register_data(
family_alias : Bytes,
data : Bytes,
index? : Int = 0,
) -> Typeface? {
if family_alias.is_empty() || data.is_empty() || index < 0 {
None
} else {
Typeface::from_handle(
native_typeface_register_data(family_alias, data, index),
)
}
}
///|
/// Returns a typeface with the given variation axes applied. Each pair is the
/// 4-byte OpenType axis tag (e.g. `b"wght"`) and the desired value. The clone
/// composes with any variations already baked into the typeface. Returns
/// `None` if the typeface does not support variation cloning; an empty
/// `variations` list returns the original typeface unchanged.
pub fn Typeface::with_variations(
self : Typeface,
variations : Array[(Bytes, Float)],
) -> Typeface? {
if variations.is_empty() {
return Some(self)
}
let mut current = self
for pair in variations {
let (axis, value) = pair
match
Typeface::from_handle(
native_typeface_clone_variation(current.handle, axis, value),
) {
Some(clone) => current = clone
None => return None
}
}
Some(current)
}
///|
fn FontMgr::from_handle(handle : FontMgrHandle) -> FontMgr? {
if native_font_mgr_is_null(handle) {
None
} else {
Some({ handle, })
}
}
///|
pub fn FontMgr::default() -> FontMgr? {
FontMgr::from_handle(native_font_mgr_default())
}
///|
pub fn FontMgr::is_available(self : FontMgr) -> Bool {
!native_font_mgr_is_null(self.handle)
}
///|
pub fn FontMgr::count_families(self : FontMgr) -> Int {
native_font_mgr_count_families(self.handle)
}
///|
pub fn FontMgr::family_name(self : FontMgr, index : Int) -> Bytes? {
if index < 0 || index >= self.count_families() {
None
} else {
let name = native_font_mgr_family_name(self.handle, index)
if name.is_empty() {
None
} else {
Some(name)
}
}
}
///|
pub fn FontMgr::match_family_style(
self : FontMgr,
family_name : Bytes,
weight? : Int = 400,
width? : Int = 5,
slant? : Int = 0,
) -> Typeface? {
if family_name.is_empty() {
None
} else {
Typeface::from_handle(
native_font_mgr_match_family_style(
self.handle,
family_name,
skia_font_style_weight(weight),
skia_font_style_width(width),
skia_font_style_slant(slant),
),
)
}
}
///|
pub fn FontMgr::match_family_style_request(
self : FontMgr,
family_name : Bytes,
style : @skia.FontStyleRequest,
) -> Typeface? {
self.match_family_style(
family_name,
weight=style.weight,
width=style.width,
slant=style.slant,
)
}
///|
fn FontMgr::match_family_style_character_language(
self : FontMgr,
family_name : Bytes,
language_tag : Bytes,
character : Int,
style : @skia.FontStyleRequest,
) -> Typeface? {
if character <= 0 {
None
} else {
Typeface::from_handle(
native_font_mgr_match_family_style_character(
self.handle,
family_name,
language_tag,
character,
style.weight,
style.width,
style.slant,
),
)
}
}
///|
pub fn FontMgr::match_family_style_character(
self : FontMgr,
family_name : Bytes,
bcp47 : Array[Bytes],
character : Int,
style? : @skia.FontStyleRequest = @skia.FontStyleRequest::new(),
) -> Typeface? {
if character <= 0 {
None
} else if bcp47.is_empty() {
self.match_family_style_character_language(
family_name, b"", character, style,
)
} else {
let mut matched : Typeface? = None
for language_tag in bcp47 {
match matched {
Some(_) => ()
None =>
matched = self.match_family_style_character_language(
family_name, language_tag, character, style,
)
}
}
matched
}
}
///|
pub fn FontMgr::match_fallback_request(
self : FontMgr,
request : @skia.FontFallbackRequest,
) -> Typeface? {
let mut matched : Typeface? = None
if request.has_character() {
let family_count = request.families.length()
if family_count == 0 {
matched = self.match_family_style_character(
b"",
request.bcp47,
request.character,
style=request.style,
)
} else {
for index in 0.. ()
None =>
match request.families.family_at(index) {
None => ()
Some(family) =>
matched = self.match_family_style_character(
family,
request.bcp47,
request.character,
style=request.style,
)
}
}
}
match matched {
Some(_) => ()
None =>
matched = self.match_family_style_character(
b"",
request.bcp47,
request.character,
style=request.style,
)
}
}
} else {
for index in 0.. ()
None =>
match request.families.family_at(index) {
None => ()
Some(family) =>
matched = self.match_family_style_request(family, request.style)
}
}
}
}
matched
}
///|
pub fn FontMgr::resolve_fallback_request(
self : FontMgr,
request : @skia.FontFallbackRequest,
) -> ResolvedTypeface? {
if request.is_empty() {
None
} else {
match self.match_fallback_request(request) {
None => None
Some(typeface) =>
match typeface.family_name() {
None => None
Some(family_name) =>
if family_name.is_empty() {
None
} else {
let resolution = request.resolution_descriptor(family_name)
if resolution.is_valid() {
Some({ typeface, resolution })
} else {
None
}
}
}
}
}
}
///|
pub fn Typeface::from_font_mgr_family(
font_mgr : FontMgr,
family_name : Bytes,
weight? : Int = 400,
width? : Int = 5,
slant? : Int = 0,
) -> Typeface? {
font_mgr.match_family_style(family_name, weight~, width~, slant~)
}
///|
pub fn Typeface::from_font_mgr_request(
font_mgr : FontMgr,
request : @skia.FontFallbackRequest,
) -> Typeface? {
font_mgr.match_fallback_request(request)
}
///|
pub fn Typeface::is_available(self : Typeface) -> Bool {
!native_typeface_is_null(self.handle)
}
///|
pub fn Typeface::is_bold(self : Typeface) -> Bool {
native_typeface_is_bold(self.handle)
}
///|
pub fn Typeface::is_italic(self : Typeface) -> Bool {
native_typeface_is_italic(self.handle)
}
///|
pub fn Typeface::is_fixed_pitch(self : Typeface) -> Bool {
native_typeface_is_fixed_pitch(self.handle)
}
///|
pub fn Typeface::family_name(self : Typeface) -> Bytes? {
let family_name = native_typeface_family_name(self.handle)
if family_name.is_empty() {
None
} else {
Some(family_name)
}
}
///|
pub fn Typeface::has_color_glyphs(self : Typeface) -> Bool {
native_typeface_has_color_glyphs(self.handle)
}