use super::*;
use crate::abi;
use crate::resolve;
use core::ffi::c_void;
use crate::mangle::{self, swift_type};
pub(crate) unsafe fn system_font(size: f64, bold: bool) -> u64 {
let design_meta = unsafe { crate::type_by_name!(swift_type!(opt enum SwiftUI.Font.Design).as_bytes()) };
assert!(!design_meta.is_null(), "Optional<Font.Design> metadata");
let mut design = vec![0u8; unsafe { abi::type_bytes(design_meta) }];
unsafe {
abi::store_optional_tag(&mut design, design_payload_meta(), false);
}
let (weight_payload, weight_tag) = if bold {
let w = unsafe { static_getter_f64(resolve::font_weight_bold(), resolve::font_weight_meta()) };
(w.to_bits(), 0u64)
} else {
(0u64, 1u64)
};
let font: u64;
unsafe {
core::arch::asm!("blr {f}", f = in(reg) resolve::font_system(),
in("d0") size,
in("x0") weight_payload,
in("x1") weight_tag,
in("x2") design.as_mut_ptr(),
in("x20") resolve::font_meta(),
lateout("x0") font,
lateout("x1") _, lateout("x3") _, lateout("x4") _, lateout("x5") _,
lateout("x6") _, lateout("x7") _, lateout("x8") _, lateout("x9") _,
lateout("x10") _, lateout("x11") _, lateout("x12") _, lateout("x13") _,
lateout("x14") _, lateout("x15") _, lateout("x16") _, lateout("x17") _,
lateout("lr") _, lateout("x21") _, clobber_abi("C"),
);
}
font
}
pub fn font(view: &ViewHandle, size: f64, bold: bool) -> ViewHandle {
unsafe {
let f = system_font(size, bold);
let (_, _, out_size) = FONT_T.applied_to(view.meta);
let mut result = vec![0u8; out_size];
let self_storage = view.value_ptr();
core::arch::asm!("blr {fun}", fun = in(reg) resolve::font_fn(),
in("x0") f,
in("x1") view.meta,
in("x2") view.wt,
in("x8") result.as_mut_ptr(),
in("x20") self_storage,
lateout("x3") _, lateout("x4") _, lateout("x5") _, lateout("x6") _, lateout("x7") _,
lateout("x9") _, lateout("x10") _, lateout("x11") _,
lateout("x12") _, lateout("x13") _, lateout("x14") _, lateout("x15") _,
lateout("x16") _, lateout("x17") _, lateout("lr") _, lateout("x21") _,
clobber_abi("C"),
);
wrap_modified(result, &FONT_T, view)
}
}
pub fn font_size(view: &ViewHandle, size: f64) -> ViewHandle {
font(view, size, false)
}
pub fn bold(view: &ViewHandle) -> ViewHandle {
unsafe {
let (_, _, size) = BOLD_T.applied_to(view.meta);
let mut result = vec![0u8; size];
let self_storage = view.value_ptr();
core::arch::asm!("blr {f}", f = in(reg) resolve::bold_fn(),
in("x0") 1u64,
in("x1") view.meta,
in("x2") view.wt,
in("x8") result.as_mut_ptr(),
in("x20") self_storage,
lateout("x3") _, lateout("x4") _, lateout("x5") _, lateout("x6") _, lateout("x7") _,
lateout("x9") _, lateout("x10") _, lateout("x11") _,
lateout("x12") _, lateout("x13") _, lateout("x14") _, lateout("x15") _,
lateout("x16") _, lateout("x17") _, lateout("lr") _, lateout("x21") _,
clobber_abi("C"),
);
wrap_modified(result, &BOLD_T, view)
}
}
pub fn foreground_style_color(view: &ViewHandle, r: f64, g: f64, b: f64, a: f64) -> ViewHandle {
unsafe { foreground_style_value(view, color_value(r, g, b, a)) }
}
pub fn foreground_style_pair(view: &ViewHandle, primary: u64, secondary: u64) -> ViewHandle {
unsafe {
let (_, _, size) = FOREGROUND2_T.applied_to(view.meta);
let mut result = vec![0u8; size];
let self_storage = view.value_ptr();
let mut a: u64 = primary;
let mut b: u64 = secondary;
core::arch::asm!("blr {f}", f = in(reg) resolve::foreground_style2_fn(),
in("x0") &mut a as *mut u64,
in("x1") &mut b as *mut u64,
in("x2") view.meta,
in("x3") resolve::color_meta(),
in("x4") resolve::color_meta(),
in("x5") view.wt,
in("x6") resolve::color_shapestyle_wt(),
in("x7") resolve::color_shapestyle_wt(),
in("x8") result.as_mut_ptr(),
in("x20") self_storage,
lateout("x9") _, lateout("x10") _, lateout("x11") _, lateout("x12") _,
lateout("x13") _, lateout("x14") _, lateout("x15") _, lateout("x16") _,
lateout("x17") _, lateout("lr") _, lateout("x21") _,
clobber_abi("C"),
);
wrap_modified(result, &FOREGROUND2_T, view)
}
}
pub fn foreground_style_triple(
view: &ViewHandle,
primary: u64,
secondary: u64,
tertiary: u64,
) -> ViewHandle {
unsafe {
let (_, _, size) = FOREGROUND3_T.applied_to(view.meta);
let mut result = vec![0u8; size];
let self_storage = view.value_ptr();
let mut a: u64 = primary;
let mut b: u64 = secondary;
let mut c: u64 = tertiary;
let color = resolve::color_meta();
let style_wt = resolve::color_shapestyle_wt();
core::arch::asm!(
"sub sp, sp, #32",
"stp {w1}, {w2}, [sp]",
"str {w3}, [sp, #16]",
"blr {f}",
"add sp, sp, #32",
f = in(reg) resolve::foreground_style3_fn(),
w1 = in(reg) style_wt,
w2 = in(reg) style_wt,
w3 = in(reg) style_wt,
in("x0") &mut a as *mut u64,
in("x1") &mut b as *mut u64,
in("x2") &mut c as *mut u64,
in("x3") view.meta,
in("x4") color,
in("x5") color,
in("x6") color,
in("x7") view.wt,
in("x8") result.as_mut_ptr(),
in("x20") self_storage,
lateout("x9") _, lateout("x10") _, lateout("x11") _, lateout("x12") _,
lateout("x13") _, lateout("x14") _, lateout("x15") _, lateout("x16") _,
lateout("x17") _, lateout("lr") _, lateout("x21") _,
clobber_abi("C"),
);
wrap_modified(result, &FOREGROUND3_T, view)
}
}
pub fn foreground_style_value(view: &ViewHandle, color: u64) -> ViewHandle {
let bytes = color.to_le_bytes();
unsafe {
foreground_style_of(
view,
&bytes,
resolve::color_meta(),
resolve::color_shapestyle_wt(),
&FOREGROUND_T,
)
}
}
pub fn foreground_style_hierarchical(
view: &ViewHandle,
level: super::Hierarchical,
) -> ViewHandle {
let (style, meta, wt) = super::hierarchical_style(level);
unsafe { foreground_style_of(view, &style, meta, wt, &FOREGROUND_HIERARCHICAL_T) }
}
pub fn foreground_style_linear_gradient(
view: &ViewHandle,
colors: &[u64],
start: (f64, f64),
end: (f64, f64),
) -> ViewHandle {
let (style, meta, wt) = super::linear_gradient_style_of(colors, start, end);
unsafe { foreground_style_of(view, &style, meta, wt, &FOREGROUND_GRADIENT_T) }
}
pub unsafe fn foreground_style_of(
view: &ViewHandle,
style: &[u8],
style_meta: *const c_void,
style_wt: *const c_void,
modifier: &ModifierType,
) -> ViewHandle {
unsafe {
let (_, _, size) = modifier.applied_to(view.meta);
let mut result = vec![0u8; size];
let self_storage = view.value_ptr();
let mut arg = style.to_vec();
arg.resize(abi::type_bytes(style_meta).max(style.len()).max(1), 0);
core::arch::asm!("blr {f}", f = in(reg) resolve::foreground_style_fn(),
in("x0") arg.as_mut_ptr(),
in("x1") view.meta,
in("x2") style_meta,
in("x3") view.wt,
in("x4") style_wt,
in("x8") result.as_mut_ptr(),
in("x20") self_storage,
lateout("x5") _, lateout("x6") _, lateout("x7") _,
lateout("x9") _, lateout("x10") _, lateout("x11") _,
lateout("x12") _, lateout("x13") _, lateout("x14") _, lateout("x15") _,
lateout("x16") _, lateout("x17") _, lateout("lr") _, lateout("x21") _,
clobber_abi("C"),
);
wrap_modified(result, modifier, view)
}
}
mangle::modifier_types! {
pub(crate) CGFLOAT_ENV_T = ty("_EnvironmentKeyWritingModifier").of(vec![Type::Nominal { module: "CoreGraphics", path: vec!["CGFloat"], kind: Kind::Struct }]);
pub(crate) LINE_LIMIT_T = ty("_EnvironmentKeyWritingModifier").of(vec![opt(Type::Verbatim("Si".into()))]);
pub(crate) TEXT_ALIGN_T = ty("_EnvironmentKeyWritingModifier").of(vec![ty_enum("TextAlignment")]);
}
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum Weight {
UltraLight,
Thin,
Light,
Regular,
Medium,
Semibold,
Bold,
Heavy,
Black,
}
impl Weight {
pub(crate) fn getter(self) -> &'static core::ffi::CStr {
match self {
Weight::UltraLight => c"$s7SwiftUI4FontV6WeightV10ultraLightAEvgZ",
Weight::Thin => c"$s7SwiftUI4FontV6WeightV4thinAEvgZ",
Weight::Light => c"$s7SwiftUI4FontV6WeightV5lightAEvgZ",
Weight::Regular => c"$s7SwiftUI4FontV6WeightV7regularAEvgZ",
Weight::Medium => c"$s7SwiftUI4FontV6WeightV6mediumAEvgZ",
Weight::Semibold => c"$s7SwiftUI4FontV6WeightV8semiboldAEvgZ",
Weight::Bold => c"$s7SwiftUI4FontV6WeightV4boldAEvgZ",
Weight::Heavy => c"$s7SwiftUI4FontV6WeightV5heavyAEvgZ",
Weight::Black => c"$s7SwiftUI4FontV6WeightV5blackAEvgZ",
}
}
pub fn value(self) -> f64 {
unsafe { static_getter_f64(resolve::require(self.getter()), resolve::font_weight_meta()) }
}
}
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
#[repr(u8)]
pub enum Design {
Default = 0,
Serif = 1,
Rounded = 2,
Monospaced = 3,
}
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum TextStyle {
LargeTitle,
Title,
Title2,
Title3,
Headline,
Subheadline,
Body,
Callout,
Footnote,
Caption,
Caption2,
}
impl TextStyle {
pub(crate) fn getter(self) -> &'static core::ffi::CStr {
match self {
TextStyle::LargeTitle => c"$s7SwiftUI4FontV10largeTitleACvgZ",
TextStyle::Title => c"$s7SwiftUI4FontV5titleACvgZ",
TextStyle::Title2 => c"$s7SwiftUI4FontV6title2ACvgZ",
TextStyle::Title3 => c"$s7SwiftUI4FontV6title3ACvgZ",
TextStyle::Headline => c"$s7SwiftUI4FontV8headlineACvgZ",
TextStyle::Subheadline => c"$s7SwiftUI4FontV11subheadlineACvgZ",
TextStyle::Body => c"$s7SwiftUI4FontV4bodyACvgZ",
TextStyle::Callout => c"$s7SwiftUI4FontV7calloutACvgZ",
TextStyle::Footnote => c"$s7SwiftUI4FontV8footnoteACvgZ",
TextStyle::Caption => c"$s7SwiftUI4FontV7captionACvgZ",
TextStyle::Caption2 => c"$s7SwiftUI4FontV8caption2ACvgZ",
}
}
}
pub unsafe fn system_font_full(size: f64, weight: Option<Weight>, design: Option<Design>) -> u64 {
let mut design_buf = unsafe { optional_design(design) };
let (payload, tag) = match weight {
Some(w) => (w.value().to_bits(), 0u64),
None => (0u64, 1u64),
};
let font: u64;
unsafe {
core::arch::asm!("blr {f}", f = in(reg) resolve::font_system(),
in("d0") size,
in("x0") payload,
in("x1") tag,
in("x2") design_buf.as_mut_ptr(),
in("x20") resolve::font_meta(),
lateout("x0") font,
lateout("x1") _, lateout("x3") _, lateout("x4") _, lateout("x5") _,
lateout("x6") _, lateout("x7") _, lateout("x8") _, lateout("x9") _,
lateout("x10") _, lateout("x11") _, lateout("x12") _, lateout("x13") _,
lateout("x14") _, lateout("x15") _, lateout("x16") _, lateout("x17") _,
lateout("lr") _, lateout("x21") _, clobber_abi("C"),
);
}
font
}
pub unsafe fn custom_font(name: &str, size: f64) -> u64 {
let ss = unsafe { abi::swift_string(name) };
let s0 = u64::from_le_bytes(ss[..8].try_into().unwrap());
let s1 = u64::from_le_bytes(ss[8..].try_into().unwrap());
let font: u64;
unsafe {
core::arch::asm!("blr {f}", f = in(reg) resolve::font_custom(),
in("x0") s0, in("x1") s1, in("d0") size,
in("x20") resolve::font_meta(),
lateout("x0") font,
lateout("x1") _, lateout("x2") _, lateout("x3") _, lateout("x4") _,
lateout("x5") _, lateout("x6") _, lateout("x7") _, lateout("x8") _,
lateout("x9") _, lateout("x10") _, lateout("x11") _, lateout("x12") _,
lateout("x13") _, lateout("x14") _, lateout("x15") _, lateout("x16") _,
lateout("x17") _, lateout("lr") _, lateout("x21") _, clobber_abi("C"),
);
}
font
}
pub struct Font(u64);
impl Font {
pub fn system(size: f64, weight: Option<Weight>, design: Option<Design>) -> Self {
Self(unsafe { system_font_full(size, weight, design) })
}
pub fn custom(name: &str, size: f64) -> Self {
Self(unsafe { custom_font(name, size) })
}
pub fn text_style(style: TextStyle) -> Self {
Self(unsafe {
let (f, _) = static_getter(resolve::require(style.getter()), resolve::font_meta());
f
})
}
pub fn raw(&self) -> u64 {
self.0
}
}
impl Clone for Font {
fn clone(&self) -> Self {
unsafe { swift_runtime_sys::RuntimeRaw::swift_retain(self.0 as *mut c_void) };
Self(self.0)
}
}
impl Drop for Font {
fn drop(&mut self) {
unsafe { swift_runtime_sys::RuntimeRaw::swift_release(self.0 as *mut c_void) };
}
}
pub fn font_ref(view: &ViewHandle, font: &Font) -> ViewHandle {
unsafe { apply_font(view, font.raw()) }
}
pub fn font_apply(view: &ViewHandle, font: u64) -> ViewHandle {
unsafe { apply_font(view, font) }
}
pub(crate) unsafe fn apply_font(view: &ViewHandle, font: u64) -> ViewHandle {
unsafe {
let (_, _, size) = FONT_T.applied_to(view.meta);
let r = abi::call_modifier(resolve::font_fn(), view.value_ptr(), view.meta, view.wt, &[font], [0.0; 4], size);
wrap_modified(r, &FONT_T, view)
}
}
pub fn font_system(
view: &ViewHandle,
size: f64,
weight: Option<Weight>,
design: Option<Design>,
) -> ViewHandle {
unsafe { apply_font(view, system_font_full(size, weight, design)) }
}
pub fn font_custom(view: &ViewHandle, name: &str, size: f64) -> ViewHandle {
unsafe { apply_font(view, custom_font(name, size)) }
}
pub fn font_text_style(view: &ViewHandle, style: TextStyle) -> ViewHandle {
unsafe {
let (f, _) = static_getter(resolve::require(style.getter()), resolve::font_meta());
apply_font(view, f)
}
}
pub fn italic(view: &ViewHandle) -> ViewHandle {
unsafe {
let (_, _, size) = BOLD_T.applied_to(view.meta);
let r = abi::call_modifier(resolve::italic_fn(), view.value_ptr(), view.meta, view.wt, &[1], [0.0; 4], size);
wrap_modified(r, &BOLD_T, view)
}
}
pub fn monospaced(view: &ViewHandle) -> ViewHandle {
unsafe {
let (_, _, size) = BOLD_T.applied_to(view.meta);
let r = abi::call_modifier(resolve::monospaced_fn(), view.value_ptr(), view.meta, view.wt, &[1], [0.0; 4], size);
wrap_modified(r, &BOLD_T, view)
}
}
pub fn font_weight(view: &ViewHandle, weight: Weight) -> ViewHandle {
unsafe {
let (_, _, size) = BOLD_T.applied_to(view.meta);
let r = abi::call_modifier(resolve::font_weight_fn(), view.value_ptr(), view.meta, view.wt,
&[weight.value().to_bits(), 0],
[0.0; 4],
size,
);
wrap_modified(r, &BOLD_T, view)
}
}
pub(crate) unsafe fn optional_design(design: Option<Design>) -> Vec<u8> {
let meta = unsafe { crate::type_by_name!(swift_type!(opt enum SwiftUI.Font.Design).as_bytes()) };
assert!(!meta.is_null(), "Optional<Font.Design> metadata");
let mut buf = vec![0u8; unsafe { abi::type_bytes(meta) }];
match design {
Some(d) => buf[0] = d as u8,
None => unsafe { abi::store_optional_tag(&mut buf, design_payload_meta(), false) },
}
buf
}
pub(crate) fn design_payload_meta() -> *const c_void {
let meta = unsafe { crate::type_by_name!(swift_type!(enum SwiftUI.Font.Design).as_bytes()) };
assert!(!meta.is_null(), "Font.Design metadata");
meta
}
pub fn font_design(view: &ViewHandle, design: Design) -> ViewHandle {
unsafe {
let (_, _, size) = BOLD_T.applied_to(view.meta);
let mut buf = optional_design(Some(design));
let r = abi::call_modifier(resolve::font_design_fn(), view.value_ptr(), view.meta, view.wt,
&[buf.as_mut_ptr() as u64],
[0.0; 4],
size,
);
wrap_modified(r, &BOLD_T, view)
}
}
pub fn kerning(view: &ViewHandle, amount: f64) -> ViewHandle {
unsafe {
let (_, _, size) = CGFLOAT_ENV_T.applied_to(view.meta);
let r = abi::call_modifier(resolve::kerning_fn(), view.value_ptr(), view.meta, view.wt, &[], [amount, 0.0, 0.0, 0.0], size);
wrap_modified(r, &CGFLOAT_ENV_T, view)
}
}
pub fn tracking(view: &ViewHandle, amount: f64) -> ViewHandle {
unsafe {
let (_, _, size) = CGFLOAT_ENV_T.applied_to(view.meta);
let r = abi::call_modifier(resolve::tracking_fn(), view.value_ptr(), view.meta, view.wt, &[], [amount, 0.0, 0.0, 0.0], size);
wrap_modified(r, &CGFLOAT_ENV_T, view)
}
}
pub fn line_spacing(view: &ViewHandle, amount: f64) -> ViewHandle {
unsafe {
let (_, _, size) = CGFLOAT_ENV_T.applied_to(view.meta);
let r =
abi::call_modifier(resolve::line_spacing_fn(), view.value_ptr(), view.meta, view.wt, &[], [amount, 0.0, 0.0, 0.0], size);
wrap_modified(r, &CGFLOAT_ENV_T, view)
}
}
pub fn line_limit(view: &ViewHandle, limit: Option<i64>) -> ViewHandle {
unsafe {
let (_, _, size) = LINE_LIMIT_T.applied_to(view.meta);
let ints = match limit {
Some(n) => [n as u64, 0],
None => [0, 1],
};
let r = abi::call_modifier(resolve::line_limit_fn(), view.value_ptr(), view.meta, view.wt, &ints, [0.0; 4], size);
wrap_modified(r, &LINE_LIMIT_T, view)
}
}
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
#[repr(u8)]
pub enum TextAlign {
Leading = 0,
Center = 1,
Trailing = 2,
}
pub fn multiline_alignment(view: &ViewHandle, align: TextAlign) -> ViewHandle {
unsafe {
let (_, _, size) = TEXT_ALIGN_T.applied_to(view.meta);
let r = abi::call_modifier(resolve::multiline_align_fn(), view.value_ptr(), view.meta, view.wt,
&[align as u64],
[0.0; 4],
size,
);
wrap_modified(r, &TEXT_ALIGN_T, view)
}
}
pub fn locale_language_thai() -> Vec<u8> {
unsafe {
let code_meta = abi::metadata0(resolve::language_code_ma());
assert!(!code_meta.is_null(), "Locale.LanguageCode metadata");
let opt_code = abi::resolve_type_by_mangled_name(b"10Foundation6LocaleV12LanguageCodeVSg");
assert!(!opt_code.is_null(), "Optional<Locale.LanguageCode>");
let th = abi::swift_string("th");
let mut code = vec![0u8; abi::type_bytes(opt_code)];
code[..16].copy_from_slice(&th);
code[16..32].copy_from_slice(&th);
let mut script = nil_of(b"10Foundation6LocaleV6ScriptVSg");
let mut region = nil_of(b"10Foundation6LocaleV6RegionVSg");
let lang_meta = abi::metadata0(resolve::locale_language_ma());
assert!(!lang_meta.is_null(), "Locale.Language metadata");
let mut out = vec![0u8; abi::type_bytes(lang_meta)];
core::arch::asm!("blr {f}", f = in(reg) resolve::locale_language_init(),
in("x0") code.as_mut_ptr(),
in("x1") script.as_mut_ptr(),
in("x2") region.as_mut_ptr(),
in("x8") out.as_mut_ptr(),
lateout("x3") _, lateout("x4") _, lateout("x5") _, lateout("x6") _,
lateout("x7") _, lateout("x9") _, lateout("x10") _, lateout("x11") _,
lateout("x12") _, lateout("x13") _, lateout("x14") _, lateout("x15") _,
lateout("x16") _, lateout("x17") _, lateout("lr") _, lateout("x20") _,
lateout("x21") _, clobber_abi("C"),
);
out
}
}
unsafe fn nil_of(mangled: &[u8]) -> Vec<u8> {
unsafe {
let meta = abi::resolve_type_by_mangled_name(mangled);
assert!(!meta.is_null(), "{}", crate::mangle::demangle(&String::from_utf8_lossy(mangled)));
let mut buf = vec![0u8; abi::type_bytes(meta)];
abi::inject_enum_tag(&mut buf, meta, 1);
buf
}
}
pub fn text_verbatim(s: &str) -> ViewHandle {
unsafe { wrap_text(text_verbatim_words(s)) }
}
pub unsafe fn text_verbatim_words(s: &str) -> [u64; 4] {
unsafe {
let ss = abi::swift_string(s);
let s0 = u64::from_le_bytes(ss[..8].try_into().expect("lo"));
let s1 = u64::from_le_bytes(ss[8..].try_into().expect("hi"));
let (t0, t1, t2, t3): (u64, u64, u64, u64);
core::arch::asm!("blr {f}", f = in(reg) resolve::text_verbatim_init(),
inout("x0") s0 => t0, inout("x1") s1 => t1,
lateout("x2") t2, lateout("x3") t3,
in("x20") resolve::text_meta(),
lateout("x4") _, lateout("x5") _, lateout("x6") _, lateout("x7") _,
lateout("x8") _, lateout("x9") _, lateout("x10") _, lateout("x11") _,
lateout("x12") _, lateout("x13") _, lateout("x14") _, lateout("x15") _,
lateout("x16") _, lateout("x17") _, lateout("lr") _, lateout("x21") _,
clobber_abi("C"),
);
[t0, t1, t2, t3]
}
}
pub fn text_typesetting_language(words: [u64; 4], language: &[u8], enabled: bool) -> ViewHandle {
unsafe { wrap_text(typesetting_call(resolve::text_typesetting_language_fn(), words, language, enabled)) }
}
pub fn text_typesetting_explicit(words: [u64; 4], language: &[u8], enabled: bool) -> ViewHandle {
unsafe {
let meta = abi::metadata0(resolve::typesetting_language_ma());
assert!(!meta.is_null(), "TypesettingLanguage metadata");
let mut lang = language.to_vec();
let mut explicit = vec![0u8; abi::type_bytes(meta)];
core::arch::asm!("blr {f}", f = in(reg) resolve::typesetting_explicit_of(),
in("x0") lang.as_mut_ptr(),
in("x8") explicit.as_mut_ptr(),
lateout("x1") _, lateout("x2") _, lateout("x3") _, lateout("x4") _,
lateout("x5") _, lateout("x6") _, lateout("x7") _, lateout("x9") _,
lateout("x10") _, lateout("x11") _, lateout("x12") _, lateout("x13") _,
lateout("x14") _, lateout("x15") _, lateout("x16") _, lateout("x17") _,
lateout("lr") _, lateout("x20") _, lateout("x21") _, clobber_abi("C"),
);
wrap_text(typesetting_call(
resolve::text_typesetting_explicit_fn(),
words,
&explicit,
enabled,
))
}
}
unsafe fn typesetting_call(
func: *const c_void,
words: [u64; 4],
value: &[u8],
enabled: bool,
) -> [u64; 4] {
unsafe {
let mut arg = value.to_vec();
let (t0, t1, t2, t3): (u64, u64, u64, u64);
core::arch::asm!("blr {f}", f = in(reg) func,
inout("x0") arg.as_mut_ptr() => t0,
inout("x1") u64::from(enabled) => t1,
inout("x2") words[0] => t2,
inout("x3") words[1] => t3,
in("x4") words[2], in("x5") words[3],
lateout("x6") _, lateout("x7") _, lateout("x8") _, lateout("x9") _,
lateout("x10") _, lateout("x11") _, lateout("x12") _, lateout("x13") _,
lateout("x14") _, lateout("x15") _, lateout("x16") _, lateout("x17") _,
lateout("lr") _, lateout("x20") _, lateout("x21") _, clobber_abi("C"),
);
[t0, t1, t2, t3]
}
}
pub(crate) unsafe fn wrap_text(words: [u64; 4]) -> ViewHandle {
unsafe {
ViewHandle::wrap(
words.as_ptr() as *const c_void,
resolve::text_meta(),
resolve::text_wt(),
)
}
}
unsafe fn text_words(view: &ViewHandle) -> (u64, u64, u64, u64) {
unsafe {
let p = view.value_ptr() as *const u8;
(
(p as *const u64).read_unaligned(),
(p.add(8) as *const u64).read_unaligned(),
u64::from(p.add(16).read()),
(p.add(24) as *const u64).read_unaligned(),
)
}
}
unsafe fn text_from_words(view: &ViewHandle, w: (u64, u64, u64, u64)) -> ViewHandle {
unsafe {
let mut out = vec![0u8; abi::type_bytes(view.meta)];
let p: *mut u8 = out.as_mut_ptr();
(p as *mut u64).write_unaligned(w.0);
(p.add(8) as *mut u64).write_unaligned(w.1);
p.add(16).write(w.2 as u8);
(p.add(24) as *mut u64).write_unaligned(w.3);
super::wrap_owned(out, view.meta, view.wt)
}
}
fn is_text(view: &ViewHandle) -> bool {
crate::diag::type_name(view.meta) == "SwiftUI.Text"
}
unsafe fn text_call0(view: &ViewHandle, f: *const c_void) -> ViewHandle {
unsafe {
let (a, b, c, d) = text_words(view);
let (r0, r1, r2, r3): (u64, u64, u64, u64);
core::arch::asm!("blr {f}", f = in(reg) f,
inout("x0") a => r0, inout("x1") b => r1,
inout("x2") c => r2, inout("x3") d => r3,
lateout("x4") _, lateout("x5") _, lateout("x6") _, lateout("x7") _,
lateout("x8") _, lateout("x9") _, lateout("x10") _, lateout("x11") _,
lateout("x12") _, lateout("x13") _, lateout("x14") _, lateout("x15") _,
lateout("x16") _, lateout("x17") _, lateout("lr") _, lateout("x20") _,
lateout("x21") _, clobber_abi("C"),
);
text_from_words(view, (r0, r1, r2, r3))
}
}
unsafe fn text_call1(view: &ViewHandle, f: *const c_void, w: u64) -> ViewHandle {
unsafe {
let (a, b, c, d) = text_words(view);
let (r0, r1, r2, r3): (u64, u64, u64, u64);
core::arch::asm!("blr {f}", f = in(reg) f,
inout("x0") w => r0, inout("x1") a => r1,
inout("x2") b => r2, inout("x3") c => r3,
inout("x4") d => _,
lateout("x5") _, lateout("x6") _, lateout("x7") _,
lateout("x8") _, lateout("x9") _, lateout("x10") _, lateout("x11") _,
lateout("x12") _, lateout("x13") _, lateout("x14") _, lateout("x15") _,
lateout("x16") _, lateout("x17") _, lateout("lr") _, lateout("x20") _,
lateout("x21") _, clobber_abi("C"),
);
text_from_words(view, (r0, r1, r2, r3))
}
}
unsafe fn text_call_f64(view: &ViewHandle, f: *const c_void, x: f64) -> ViewHandle {
unsafe {
let (a, b, c, d) = text_words(view);
let (r0, r1, r2, r3): (u64, u64, u64, u64);
core::arch::asm!("blr {f}", f = in(reg) f,
in("d0") x,
inout("x0") a => r0, inout("x1") b => r1,
inout("x2") c => r2, inout("x3") d => r3,
lateout("x4") _, lateout("x5") _, lateout("x6") _, lateout("x7") _,
lateout("x8") _, lateout("x9") _, lateout("x10") _, lateout("x11") _,
lateout("x12") _, lateout("x13") _, lateout("x14") _, lateout("x15") _,
lateout("x16") _, lateout("x17") _, lateout("lr") _, lateout("x20") _,
lateout("x21") _, clobber_abi("C"),
);
text_from_words(view, (r0, r1, r2, r3))
}
}
pub fn text_bold(view: &ViewHandle) -> ViewHandle {
if !is_text(view) {
return super::bold(view);
}
unsafe { text_call0(view, resolve::text_bold()) }
}
pub fn text_italic(view: &ViewHandle) -> ViewHandle {
if !is_text(view) {
return super::italic(view);
}
unsafe { text_call0(view, resolve::text_italic()) }
}
pub fn text_monospaced(view: &ViewHandle) -> ViewHandle {
if !is_text(view) {
return super::monospaced(view);
}
unsafe { text_call1(view, resolve::text_monospaced(), 1) }
}
pub fn text_foreground_color(view: &ViewHandle, color: crate::Color) -> ViewHandle {
if !is_text(view) {
return super::foreground_style_color(view, color.r, color.g, color.b, color.a);
}
unsafe { text_call1(view, resolve::text_fg_color(), super::color_value_of(color)) }
}
pub fn text_kerning(view: &ViewHandle, amount: f64) -> ViewHandle {
if !is_text(view) {
return super::kerning(view, amount);
}
unsafe { text_call_f64(view, resolve::text_kerning(), amount) }
}
pub fn text_tracking(view: &ViewHandle, amount: f64) -> ViewHandle {
if !is_text(view) {
return super::tracking(view, amount);
}
unsafe { text_call_f64(view, resolve::text_tracking(), amount) }
}
pub fn text_baseline_offset(view: &ViewHandle, amount: f64) -> ViewHandle {
if !is_text(view) {
return view.clone();
}
unsafe { text_call_f64(view, resolve::text_baseline(), amount) }
}
pub fn text_font(view: &ViewHandle, font: Option<&super::Font>) -> ViewHandle {
if !is_text(view) {
return match font {
Some(f) => super::font_ref(view, f),
None => view.clone(),
};
}
unsafe { text_call1(view, resolve::text_font(), font.map_or(0, super::Font::raw)) }
}
pub fn text_font_weight(view: &ViewHandle, weight: Option<super::Weight>) -> ViewHandle {
if !is_text(view) {
return match weight {
Some(w) => super::font_weight(view, w),
None => view.clone(),
};
}
unsafe {
let (a, b, c, d) = text_words(view);
let (w0, w1) = match weight {
Some(w) => (w.value().to_bits(), 0u64),
None => (0, 1),
};
let (r0, r1, r2, r3): (u64, u64, u64, u64);
core::arch::asm!("blr {f}", f = in(reg) resolve::text_font_weight(),
inout("x0") w0 => r0, inout("x1") w1 => r1,
inout("x2") a => r2, inout("x3") b => r3,
inout("x4") c => _, inout("x5") d => _,
lateout("x6") _, lateout("x7") _,
lateout("x8") _, lateout("x9") _, lateout("x10") _, lateout("x11") _,
lateout("x12") _, lateout("x13") _, lateout("x14") _, lateout("x15") _,
lateout("x16") _, lateout("x17") _, lateout("lr") _, lateout("x20") _,
lateout("x21") _, clobber_abi("C"),
);
text_from_words(view, (r0, r1, r2, r3))
}
}
pub unsafe fn text_foreground_style(
view: &ViewHandle,
style: &[u8],
style_meta: *const c_void,
style_wt: *const c_void,
) -> ViewHandle {
if !is_text(view) {
return unsafe { foreground_style_of(view, style, style_meta, style_wt, &FOREGROUND_GRADIENT_T) };
}
unsafe {
let (a, b, c, d) = text_words(view);
let mut buf = style.to_vec();
let (r0, r1, r2, r3): (u64, u64, u64, u64);
core::arch::asm!("blr {f}", f = in(reg) resolve::text_fg_style(),
inout("x0") buf.as_mut_ptr() as u64 => r0,
inout("x1") a => r1, inout("x2") b => r2, inout("x3") c => r3,
inout("x4") d => _,
in("x5") style_meta, in("x6") style_wt,
lateout("x7") _,
lateout("x8") _, lateout("x9") _, lateout("x10") _, lateout("x11") _,
lateout("x12") _, lateout("x13") _, lateout("x14") _, lateout("x15") _,
lateout("x16") _, lateout("x17") _, lateout("lr") _, lateout("x20") _,
lateout("x21") _, clobber_abi("C"),
);
text_from_words(view, (r0, r1, r2, r3))
}
}
pub fn text_foreground_linear_gradient(
view: &ViewHandle,
colors: &[u64],
start: (f64, f64),
end: (f64, f64),
) -> ViewHandle {
let (style, meta, wt) = super::linear_gradient_style_of(colors, start, end);
unsafe { text_foreground_style(view, &style, meta, wt) }
}
pub fn text_foreground_hierarchical(
view: &ViewHandle,
level: super::Hierarchical,
) -> ViewHandle {
let (style, meta, wt) = super::hierarchical_style(level);
unsafe { text_foreground_style(view, &style, meta, wt) }
}