1use super::*;
6use crate::abi;
7use crate::resolve;
8use core::ffi::c_void;
9use crate::mangle::{self, swift_type};
10
11pub(crate) unsafe fn system_font(size: f64, bold: bool) -> u64 {
19 let design_meta = unsafe { crate::type_by_name!(swift_type!(opt enum SwiftUI.Font.Design).as_bytes()) };
20 assert!(!design_meta.is_null(), "Optional<Font.Design> metadata");
21 let mut design = vec![0u8; unsafe { abi::type_bytes(design_meta) }];
22 unsafe {
23 abi::store_optional_tag(&mut design, design_payload_meta(), false);
24 }
25
26 let (weight_payload, weight_tag) = if bold {
30 let w = unsafe { static_getter_f64(resolve::font_weight_bold(), resolve::font_weight_meta()) };
31 (w.to_bits(), 0u64)
32 } else {
33 (0u64, 1u64)
34 };
35
36 let font: u64;
37 unsafe {
38 core::arch::asm!("blr {f}", f = in(reg) resolve::font_system(),
39 in("d0") size,
40 in("x0") weight_payload,
41 in("x1") weight_tag,
42 in("x2") design.as_mut_ptr(),
43 in("x20") resolve::font_meta(),
44 lateout("x0") font,
45 lateout("x1") _, lateout("x3") _, lateout("x4") _, lateout("x5") _,
46 lateout("x6") _, lateout("x7") _, lateout("x8") _, lateout("x9") _,
47 lateout("x10") _, lateout("x11") _, lateout("x12") _, lateout("x13") _,
48 lateout("x14") _, lateout("x15") _, lateout("x16") _, lateout("x17") _,
49 lateout("lr") _, lateout("x21") _, clobber_abi("C"),
50 );
51 }
52 font
53}
54
55pub fn font(view: &ViewHandle, size: f64, bold: bool) -> ViewHandle {
57 unsafe {
58 let f = system_font(size, bold);
59 let (_, _, out_size) = FONT_T.applied_to(view.meta);
60 let mut result = vec![0u8; out_size];
61 let self_storage = view.value_ptr();
62 core::arch::asm!("blr {fun}", fun = in(reg) resolve::font_fn(),
64 in("x0") f,
65 in("x1") view.meta,
66 in("x2") view.wt,
67 in("x8") result.as_mut_ptr(),
68 in("x20") self_storage,
69 lateout("x3") _, lateout("x4") _, lateout("x5") _, lateout("x6") _, lateout("x7") _,
70 lateout("x9") _, lateout("x10") _, lateout("x11") _,
71 lateout("x12") _, lateout("x13") _, lateout("x14") _, lateout("x15") _,
72 lateout("x16") _, lateout("x17") _, lateout("lr") _, lateout("x21") _,
73 clobber_abi("C"),
74 );
75 wrap_modified(result, &FONT_T, view)
76 }
77}
78
79pub fn font_size(view: &ViewHandle, size: f64) -> ViewHandle {
81 font(view, size, false)
82}
83
84pub fn bold(view: &ViewHandle) -> ViewHandle {
86 unsafe {
87 let (_, _, size) = BOLD_T.applied_to(view.meta);
88 let mut result = vec![0u8; size];
89 let self_storage = view.value_ptr();
90 core::arch::asm!("blr {f}", f = in(reg) resolve::bold_fn(),
91 in("x0") 1u64,
92 in("x1") view.meta,
93 in("x2") view.wt,
94 in("x8") result.as_mut_ptr(),
95 in("x20") self_storage,
96 lateout("x3") _, lateout("x4") _, lateout("x5") _, lateout("x6") _, lateout("x7") _,
97 lateout("x9") _, lateout("x10") _, lateout("x11") _,
98 lateout("x12") _, lateout("x13") _, lateout("x14") _, lateout("x15") _,
99 lateout("x16") _, lateout("x17") _, lateout("lr") _, lateout("x21") _,
100 clobber_abi("C"),
101 );
102 wrap_modified(result, &BOLD_T, view)
103 }
104}
105
106pub fn foreground_style_color(view: &ViewHandle, r: f64, g: f64, b: f64, a: f64) -> ViewHandle {
115 unsafe { foreground_style_value(view, color_value(r, g, b, a)) }
116}
117
118pub fn foreground_style_pair(view: &ViewHandle, primary: u64, secondary: u64) -> ViewHandle {
123 unsafe {
124 let (_, _, size) = FOREGROUND2_T.applied_to(view.meta);
125 let mut result = vec![0u8; size];
126 let self_storage = view.value_ptr();
127 let mut a: u64 = primary;
128 let mut b: u64 = secondary;
129 core::arch::asm!("blr {f}", f = in(reg) resolve::foreground_style2_fn(),
134 in("x0") &mut a as *mut u64,
135 in("x1") &mut b as *mut u64,
136 in("x2") view.meta,
137 in("x3") resolve::color_meta(),
138 in("x4") resolve::color_meta(),
139 in("x5") view.wt,
140 in("x6") resolve::color_shapestyle_wt(),
141 in("x7") resolve::color_shapestyle_wt(),
142 in("x8") result.as_mut_ptr(),
143 in("x20") self_storage,
144 lateout("x9") _, lateout("x10") _, lateout("x11") _, lateout("x12") _,
145 lateout("x13") _, lateout("x14") _, lateout("x15") _, lateout("x16") _,
146 lateout("x17") _, lateout("lr") _, lateout("x21") _,
147 clobber_abi("C"),
148 );
149 wrap_modified(result, &FOREGROUND2_T, view)
150 }
151}
152
153pub fn foreground_style_triple(
171 view: &ViewHandle,
172 primary: u64,
173 secondary: u64,
174 tertiary: u64,
175) -> ViewHandle {
176 unsafe {
177 let (_, _, size) = FOREGROUND3_T.applied_to(view.meta);
178 let mut result = vec![0u8; size];
179 let self_storage = view.value_ptr();
180 let mut a: u64 = primary;
181 let mut b: u64 = secondary;
182 let mut c: u64 = tertiary;
183 let color = resolve::color_meta();
184 let style_wt = resolve::color_shapestyle_wt();
185 core::arch::asm!(
186 "sub sp, sp, #32",
187 "stp {w1}, {w2}, [sp]",
188 "str {w3}, [sp, #16]",
189 "blr {f}",
190 "add sp, sp, #32",
191 f = in(reg) resolve::foreground_style3_fn(),
192 w1 = in(reg) style_wt,
193 w2 = in(reg) style_wt,
194 w3 = in(reg) style_wt,
195 in("x0") &mut a as *mut u64,
196 in("x1") &mut b as *mut u64,
197 in("x2") &mut c as *mut u64,
198 in("x3") view.meta,
199 in("x4") color,
200 in("x5") color,
201 in("x6") color,
202 in("x7") view.wt,
203 in("x8") result.as_mut_ptr(),
204 in("x20") self_storage,
205 lateout("x9") _, lateout("x10") _, lateout("x11") _, lateout("x12") _,
206 lateout("x13") _, lateout("x14") _, lateout("x15") _, lateout("x16") _,
207 lateout("x17") _, lateout("lr") _, lateout("x21") _,
208 clobber_abi("C"),
209 );
210 wrap_modified(result, &FOREGROUND3_T, view)
211 }
212}
213
214pub fn foreground_style_value(view: &ViewHandle, color: u64) -> ViewHandle {
221 let bytes = color.to_le_bytes();
222 unsafe {
223 foreground_style_of(
224 view,
225 &bytes,
226 resolve::color_meta(),
227 resolve::color_shapestyle_wt(),
228 &FOREGROUND_T,
229 )
230 }
231}
232
233pub fn foreground_style_hierarchical(
240 view: &ViewHandle,
241 level: super::Hierarchical,
242) -> ViewHandle {
243 let (style, meta, wt) = super::hierarchical_style(level);
244 unsafe { foreground_style_of(view, &style, meta, wt, &FOREGROUND_HIERARCHICAL_T) }
245}
246
247pub fn foreground_style_linear_gradient(
248 view: &ViewHandle,
249 colors: &[u64],
250 start: (f64, f64),
251 end: (f64, f64),
252) -> ViewHandle {
253 let (style, meta, wt) = super::linear_gradient_style_of(colors, start, end);
254 unsafe { foreground_style_of(view, &style, meta, wt, &FOREGROUND_GRADIENT_T) }
255}
256
257pub unsafe fn foreground_style_of(
271 view: &ViewHandle,
272 style: &[u8],
273 style_meta: *const c_void,
274 style_wt: *const c_void,
275 modifier: &ModifierType,
276) -> ViewHandle {
277 unsafe {
278 let (_, _, size) = modifier.applied_to(view.meta);
279 let mut result = vec![0u8; size];
280 let self_storage = view.value_ptr();
281 let mut arg = style.to_vec();
282 arg.resize(abi::type_bytes(style_meta).max(style.len()).max(1), 0);
283 core::arch::asm!("blr {f}", f = in(reg) resolve::foreground_style_fn(),
287 in("x0") arg.as_mut_ptr(),
288 in("x1") view.meta,
289 in("x2") style_meta,
290 in("x3") view.wt,
291 in("x4") style_wt,
292 in("x8") result.as_mut_ptr(),
293 in("x20") self_storage,
294 lateout("x5") _, lateout("x6") _, lateout("x7") _,
295 lateout("x9") _, lateout("x10") _, lateout("x11") _,
296 lateout("x12") _, lateout("x13") _, lateout("x14") _, lateout("x15") _,
297 lateout("x16") _, lateout("x17") _, lateout("lr") _, lateout("x21") _,
298 clobber_abi("C"),
299 );
300 wrap_modified(result, modifier, view)
301 }
302}
303
304mangle::modifier_types! {
310 pub(crate) CGFLOAT_ENV_T = ty("_EnvironmentKeyWritingModifier").of(vec![Type::Nominal { module: "CoreGraphics", path: vec!["CGFloat"], kind: Kind::Struct }]);
313 pub(crate) LINE_LIMIT_T = ty("_EnvironmentKeyWritingModifier").of(vec![opt(Type::Verbatim("Si".into()))]);
316 pub(crate) TEXT_ALIGN_T = ty("_EnvironmentKeyWritingModifier").of(vec![ty_enum("TextAlignment")]);
319}
320
321
322
323#[derive(Clone, Copy, PartialEq, Eq, Debug)]
326pub enum Weight {
327 UltraLight,
328 Thin,
329 Light,
330 Regular,
331 Medium,
332 Semibold,
333 Bold,
334 Heavy,
335 Black,
336}
337
338impl Weight {
339 pub(crate) fn getter(self) -> &'static core::ffi::CStr {
340 match self {
341 Weight::UltraLight => c"$s7SwiftUI4FontV6WeightV10ultraLightAEvgZ",
342 Weight::Thin => c"$s7SwiftUI4FontV6WeightV4thinAEvgZ",
343 Weight::Light => c"$s7SwiftUI4FontV6WeightV5lightAEvgZ",
344 Weight::Regular => c"$s7SwiftUI4FontV6WeightV7regularAEvgZ",
345 Weight::Medium => c"$s7SwiftUI4FontV6WeightV6mediumAEvgZ",
346 Weight::Semibold => c"$s7SwiftUI4FontV6WeightV8semiboldAEvgZ",
347 Weight::Bold => c"$s7SwiftUI4FontV6WeightV4boldAEvgZ",
348 Weight::Heavy => c"$s7SwiftUI4FontV6WeightV5heavyAEvgZ",
349 Weight::Black => c"$s7SwiftUI4FontV6WeightV5blackAEvgZ",
350 }
351 }
352
353 pub fn value(self) -> f64 {
355 unsafe { static_getter_f64(resolve::require(self.getter()), resolve::font_weight_meta()) }
356 }
357}
358
359#[derive(Clone, Copy, PartialEq, Eq, Debug)]
361#[repr(u8)]
362pub enum Design {
363 Default = 0,
364 Serif = 1,
365 Rounded = 2,
366 Monospaced = 3,
367}
368
369#[derive(Clone, Copy, PartialEq, Eq, Debug)]
371pub enum TextStyle {
372 LargeTitle,
373 Title,
374 Title2,
375 Title3,
376 Headline,
377 Subheadline,
378 Body,
379 Callout,
380 Footnote,
381 Caption,
382 Caption2,
383}
384
385impl TextStyle {
386 pub(crate) fn getter(self) -> &'static core::ffi::CStr {
387 match self {
388 TextStyle::LargeTitle => c"$s7SwiftUI4FontV10largeTitleACvgZ",
389 TextStyle::Title => c"$s7SwiftUI4FontV5titleACvgZ",
390 TextStyle::Title2 => c"$s7SwiftUI4FontV6title2ACvgZ",
391 TextStyle::Title3 => c"$s7SwiftUI4FontV6title3ACvgZ",
392 TextStyle::Headline => c"$s7SwiftUI4FontV8headlineACvgZ",
393 TextStyle::Subheadline => c"$s7SwiftUI4FontV11subheadlineACvgZ",
394 TextStyle::Body => c"$s7SwiftUI4FontV4bodyACvgZ",
395 TextStyle::Callout => c"$s7SwiftUI4FontV7calloutACvgZ",
396 TextStyle::Footnote => c"$s7SwiftUI4FontV8footnoteACvgZ",
397 TextStyle::Caption => c"$s7SwiftUI4FontV7captionACvgZ",
398 TextStyle::Caption2 => c"$s7SwiftUI4FontV8caption2ACvgZ",
399 }
400 }
401}
402
403pub unsafe fn system_font_full(size: f64, weight: Option<Weight>, design: Option<Design>) -> u64 {
411 let mut design_buf = unsafe { optional_design(design) };
412
413 let (payload, tag) = match weight {
415 Some(w) => (w.value().to_bits(), 0u64),
416 None => (0u64, 1u64),
417 };
418
419 let font: u64;
420 unsafe {
421 core::arch::asm!("blr {f}", f = in(reg) resolve::font_system(),
422 in("d0") size,
423 in("x0") payload,
424 in("x1") tag,
425 in("x2") design_buf.as_mut_ptr(),
426 in("x20") resolve::font_meta(),
427 lateout("x0") font,
428 lateout("x1") _, lateout("x3") _, lateout("x4") _, lateout("x5") _,
429 lateout("x6") _, lateout("x7") _, lateout("x8") _, lateout("x9") _,
430 lateout("x10") _, lateout("x11") _, lateout("x12") _, lateout("x13") _,
431 lateout("x14") _, lateout("x15") _, lateout("x16") _, lateout("x17") _,
432 lateout("lr") _, lateout("x21") _, clobber_abi("C"),
433 );
434 }
435 font
436}
437
438pub unsafe fn custom_font(name: &str, size: f64) -> u64 {
442 let ss = unsafe { abi::swift_string(name) };
443 let s0 = u64::from_le_bytes(ss[..8].try_into().unwrap());
444 let s1 = u64::from_le_bytes(ss[8..].try_into().unwrap());
445 let font: u64;
446 unsafe {
447 core::arch::asm!("blr {f}", f = in(reg) resolve::font_custom(),
448 in("x0") s0, in("x1") s1, in("d0") size,
449 in("x20") resolve::font_meta(),
450 lateout("x0") font,
451 lateout("x1") _, lateout("x2") _, lateout("x3") _, lateout("x4") _,
452 lateout("x5") _, lateout("x6") _, lateout("x7") _, lateout("x8") _,
453 lateout("x9") _, lateout("x10") _, lateout("x11") _, lateout("x12") _,
454 lateout("x13") _, lateout("x14") _, lateout("x15") _, lateout("x16") _,
455 lateout("x17") _, lateout("lr") _, lateout("x21") _, clobber_abi("C"),
456 );
457 }
458 font
459}
460
461pub struct Font(u64);
476
477impl Font {
478 pub fn system(size: f64, weight: Option<Weight>, design: Option<Design>) -> Self {
480 Self(unsafe { system_font_full(size, weight, design) })
481 }
482
483 pub fn custom(name: &str, size: f64) -> Self {
485 Self(unsafe { custom_font(name, size) })
486 }
487
488 pub fn text_style(style: TextStyle) -> Self {
490 Self(unsafe {
491 let (f, _) = static_getter(resolve::require(style.getter()), resolve::font_meta());
492 f
493 })
494 }
495
496 pub fn raw(&self) -> u64 {
498 self.0
499 }
500
501}
502
503impl Clone for Font {
504 fn clone(&self) -> Self {
505 unsafe { swift_runtime_sys::RuntimeRaw::swift_retain(self.0 as *mut c_void) };
506 Self(self.0)
507 }
508}
509
510impl Drop for Font {
511 fn drop(&mut self) {
512 unsafe { swift_runtime_sys::RuntimeRaw::swift_release(self.0 as *mut c_void) };
513 }
514}
515
516pub fn font_ref(view: &ViewHandle, font: &Font) -> ViewHandle {
518 unsafe { apply_font(view, font.raw()) }
519}
520
521pub fn font_apply(view: &ViewHandle, font: u64) -> ViewHandle {
523 unsafe { apply_font(view, font) }
524}
525
526pub(crate) unsafe fn apply_font(view: &ViewHandle, font: u64) -> ViewHandle {
528 unsafe {
529 let (_, _, size) = FONT_T.applied_to(view.meta);
530 let r = abi::call_modifier(resolve::font_fn(), view.value_ptr(), view.meta, view.wt, &[font], [0.0; 4], size);
531 wrap_modified(r, &FONT_T, view)
532 }
533}
534
535pub fn font_system(
537 view: &ViewHandle,
538 size: f64,
539 weight: Option<Weight>,
540 design: Option<Design>,
541) -> ViewHandle {
542 unsafe { apply_font(view, system_font_full(size, weight, design)) }
543}
544
545pub fn font_custom(view: &ViewHandle, name: &str, size: f64) -> ViewHandle {
547 unsafe { apply_font(view, custom_font(name, size)) }
548}
549
550pub fn font_text_style(view: &ViewHandle, style: TextStyle) -> ViewHandle {
552 unsafe {
553 let (f, _) = static_getter(resolve::require(style.getter()), resolve::font_meta());
554 apply_font(view, f)
555 }
556}
557
558pub fn italic(view: &ViewHandle) -> ViewHandle {
560 unsafe {
561 let (_, _, size) = BOLD_T.applied_to(view.meta);
562 let r = abi::call_modifier(resolve::italic_fn(), view.value_ptr(), view.meta, view.wt, &[1], [0.0; 4], size);
563 wrap_modified(r, &BOLD_T, view)
564 }
565}
566
567pub fn monospaced(view: &ViewHandle) -> ViewHandle {
569 unsafe {
570 let (_, _, size) = BOLD_T.applied_to(view.meta);
571 let r = abi::call_modifier(resolve::monospaced_fn(), view.value_ptr(), view.meta, view.wt, &[1], [0.0; 4], size);
572 wrap_modified(r, &BOLD_T, view)
573 }
574}
575
576pub fn font_weight(view: &ViewHandle, weight: Weight) -> ViewHandle {
578 unsafe {
579 let (_, _, size) = BOLD_T.applied_to(view.meta);
580 let r = abi::call_modifier(resolve::font_weight_fn(), view.value_ptr(), view.meta, view.wt,
582 &[weight.value().to_bits(), 0],
583 [0.0; 4],
584 size,
585 );
586 wrap_modified(r, &BOLD_T, view)
587 }
588}
589
590pub(crate) unsafe fn optional_design(design: Option<Design>) -> Vec<u8> {
595 let meta = unsafe { crate::type_by_name!(swift_type!(opt enum SwiftUI.Font.Design).as_bytes()) };
596 assert!(!meta.is_null(), "Optional<Font.Design> metadata");
597 let mut buf = vec![0u8; unsafe { abi::type_bytes(meta) }];
598 match design {
599 Some(d) => buf[0] = d as u8,
600 None => unsafe { abi::store_optional_tag(&mut buf, design_payload_meta(), false) },
601 }
602 buf
603}
604
605pub(crate) fn design_payload_meta() -> *const c_void {
607 let meta = unsafe { crate::type_by_name!(swift_type!(enum SwiftUI.Font.Design).as_bytes()) };
608 assert!(!meta.is_null(), "Font.Design metadata");
609 meta
610}
611
612pub fn font_design(view: &ViewHandle, design: Design) -> ViewHandle {
614 unsafe {
615 let (_, _, size) = BOLD_T.applied_to(view.meta);
616 let mut buf = optional_design(Some(design));
617 let r = abi::call_modifier(resolve::font_design_fn(), view.value_ptr(), view.meta, view.wt,
618 &[buf.as_mut_ptr() as u64],
619 [0.0; 4],
620 size,
621 );
622 wrap_modified(r, &BOLD_T, view)
623 }
624}
625
626pub fn kerning(view: &ViewHandle, amount: f64) -> ViewHandle {
628 unsafe {
629 let (_, _, size) = CGFLOAT_ENV_T.applied_to(view.meta);
630 let r = abi::call_modifier(resolve::kerning_fn(), view.value_ptr(), view.meta, view.wt, &[], [amount, 0.0, 0.0, 0.0], size);
631 wrap_modified(r, &CGFLOAT_ENV_T, view)
632 }
633}
634
635pub fn tracking(view: &ViewHandle, amount: f64) -> ViewHandle {
637 unsafe {
638 let (_, _, size) = CGFLOAT_ENV_T.applied_to(view.meta);
639 let r = abi::call_modifier(resolve::tracking_fn(), view.value_ptr(), view.meta, view.wt, &[], [amount, 0.0, 0.0, 0.0], size);
640 wrap_modified(r, &CGFLOAT_ENV_T, view)
641 }
642}
643
644pub fn line_spacing(view: &ViewHandle, amount: f64) -> ViewHandle {
646 unsafe {
647 let (_, _, size) = CGFLOAT_ENV_T.applied_to(view.meta);
648 let r =
649 abi::call_modifier(resolve::line_spacing_fn(), view.value_ptr(), view.meta, view.wt, &[], [amount, 0.0, 0.0, 0.0], size);
650 wrap_modified(r, &CGFLOAT_ENV_T, view)
651 }
652}
653
654pub fn line_limit(view: &ViewHandle, limit: Option<i64>) -> ViewHandle {
656 unsafe {
657 let (_, _, size) = LINE_LIMIT_T.applied_to(view.meta);
658 let ints = match limit {
660 Some(n) => [n as u64, 0],
661 None => [0, 1],
662 };
663 let r = abi::call_modifier(resolve::line_limit_fn(), view.value_ptr(), view.meta, view.wt, &ints, [0.0; 4], size);
664 wrap_modified(r, &LINE_LIMIT_T, view)
665 }
666}
667
668#[derive(Clone, Copy, PartialEq, Eq, Debug)]
670#[repr(u8)]
671pub enum TextAlign {
672 Leading = 0,
673 Center = 1,
674 Trailing = 2,
675}
676
677pub fn multiline_alignment(view: &ViewHandle, align: TextAlign) -> ViewHandle {
679 unsafe {
680 let (_, _, size) = TEXT_ALIGN_T.applied_to(view.meta);
681 let r = abi::call_modifier(resolve::multiline_align_fn(), view.value_ptr(), view.meta, view.wt,
682 &[align as u64],
683 [0.0; 4],
684 size,
685 );
686 wrap_modified(r, &TEXT_ALIGN_T, view)
687 }
688}
689
690pub fn locale_language_thai() -> Vec<u8> {
699 unsafe {
700 let code_meta = abi::metadata0(resolve::language_code_ma());
701 assert!(!code_meta.is_null(), "Locale.LanguageCode metadata");
702 let opt_code = abi::resolve_type_by_mangled_name(b"10Foundation6LocaleV12LanguageCodeVSg");
703 assert!(!opt_code.is_null(), "Optional<Locale.LanguageCode>");
704
705 let th = abi::swift_string("th");
706 let mut code = vec![0u8; abi::type_bytes(opt_code)];
707 code[..16].copy_from_slice(&th);
708 code[16..32].copy_from_slice(&th);
709
710 let mut script = nil_of(b"10Foundation6LocaleV6ScriptVSg");
711 let mut region = nil_of(b"10Foundation6LocaleV6RegionVSg");
712
713 let lang_meta = abi::metadata0(resolve::locale_language_ma());
714 assert!(!lang_meta.is_null(), "Locale.Language metadata");
715 let mut out = vec![0u8; abi::type_bytes(lang_meta)];
716 core::arch::asm!("blr {f}", f = in(reg) resolve::locale_language_init(),
717 in("x0") code.as_mut_ptr(),
718 in("x1") script.as_mut_ptr(),
719 in("x2") region.as_mut_ptr(),
720 in("x8") out.as_mut_ptr(),
721 lateout("x3") _, lateout("x4") _, lateout("x5") _, lateout("x6") _,
722 lateout("x7") _, lateout("x9") _, lateout("x10") _, lateout("x11") _,
723 lateout("x12") _, lateout("x13") _, lateout("x14") _, lateout("x15") _,
724 lateout("x16") _, lateout("x17") _, lateout("lr") _, lateout("x20") _,
725 lateout("x21") _, clobber_abi("C"),
726 );
727 out
728 }
729}
730
731unsafe fn nil_of(mangled: &[u8]) -> Vec<u8> {
733 unsafe {
734 let meta = abi::resolve_type_by_mangled_name(mangled);
735 assert!(!meta.is_null(), "{}", crate::mangle::demangle(&String::from_utf8_lossy(mangled)));
736 let mut buf = vec![0u8; abi::type_bytes(meta)];
737 abi::inject_enum_tag(&mut buf, meta, 1);
738 buf
739 }
740}
741
742pub fn text_verbatim(s: &str) -> ViewHandle {
744 unsafe { wrap_text(text_verbatim_words(s)) }
745}
746
747pub unsafe fn text_verbatim_words(s: &str) -> [u64; 4] {
752 unsafe {
753 let ss = abi::swift_string(s);
754 let s0 = u64::from_le_bytes(ss[..8].try_into().expect("lo"));
755 let s1 = u64::from_le_bytes(ss[8..].try_into().expect("hi"));
756 let (t0, t1, t2, t3): (u64, u64, u64, u64);
759 core::arch::asm!("blr {f}", f = in(reg) resolve::text_verbatim_init(),
760 inout("x0") s0 => t0, inout("x1") s1 => t1,
761 lateout("x2") t2, lateout("x3") t3,
762 in("x20") resolve::text_meta(),
763 lateout("x4") _, lateout("x5") _, lateout("x6") _, lateout("x7") _,
764 lateout("x8") _, lateout("x9") _, lateout("x10") _, lateout("x11") _,
765 lateout("x12") _, lateout("x13") _, lateout("x14") _, lateout("x15") _,
766 lateout("x16") _, lateout("x17") _, lateout("lr") _, lateout("x21") _,
767 clobber_abi("C"),
768 );
769 [t0, t1, t2, t3]
770 }
771}
772
773pub fn text_typesetting_language(words: [u64; 4], language: &[u8], enabled: bool) -> ViewHandle {
780 unsafe { wrap_text(typesetting_call(resolve::text_typesetting_language_fn(), words, language, enabled)) }
781}
782
783pub fn text_typesetting_explicit(words: [u64; 4], language: &[u8], enabled: bool) -> ViewHandle {
785 unsafe {
786 let meta = abi::metadata0(resolve::typesetting_language_ma());
787 assert!(!meta.is_null(), "TypesettingLanguage metadata");
788 let mut lang = language.to_vec();
789 let mut explicit = vec![0u8; abi::type_bytes(meta)];
790 core::arch::asm!("blr {f}", f = in(reg) resolve::typesetting_explicit_of(),
791 in("x0") lang.as_mut_ptr(),
792 in("x8") explicit.as_mut_ptr(),
793 lateout("x1") _, lateout("x2") _, lateout("x3") _, lateout("x4") _,
794 lateout("x5") _, lateout("x6") _, lateout("x7") _, lateout("x9") _,
795 lateout("x10") _, lateout("x11") _, lateout("x12") _, lateout("x13") _,
796 lateout("x14") _, lateout("x15") _, lateout("x16") _, lateout("x17") _,
797 lateout("lr") _, lateout("x20") _, lateout("x21") _, clobber_abi("C"),
798 );
799 wrap_text(typesetting_call(
800 resolve::text_typesetting_explicit_fn(),
801 words,
802 &explicit,
803 enabled,
804 ))
805 }
806}
807
808unsafe fn typesetting_call(
809 func: *const c_void,
810 words: [u64; 4],
811 value: &[u8],
812 enabled: bool,
813) -> [u64; 4] {
814 unsafe {
815 let mut arg = value.to_vec();
816 let (t0, t1, t2, t3): (u64, u64, u64, u64);
817 core::arch::asm!("blr {f}", f = in(reg) func,
818 inout("x0") arg.as_mut_ptr() => t0,
819 inout("x1") u64::from(enabled) => t1,
820 inout("x2") words[0] => t2,
821 inout("x3") words[1] => t3,
822 in("x4") words[2], in("x5") words[3],
823 lateout("x6") _, lateout("x7") _, lateout("x8") _, lateout("x9") _,
824 lateout("x10") _, lateout("x11") _, lateout("x12") _, lateout("x13") _,
825 lateout("x14") _, lateout("x15") _, lateout("x16") _, lateout("x17") _,
826 lateout("lr") _, lateout("x20") _, lateout("x21") _, clobber_abi("C"),
827 );
828 [t0, t1, t2, t3]
829 }
830}
831
832pub(crate) unsafe fn wrap_text(words: [u64; 4]) -> ViewHandle {
834 unsafe {
835 ViewHandle::wrap(
836 words.as_ptr() as *const c_void,
837 resolve::text_meta(),
838 resolve::text_wt(),
839 )
840 }
841}
842
843unsafe fn text_words(view: &ViewHandle) -> (u64, u64, u64, u64) {
862 unsafe {
863 let p = view.value_ptr() as *const u8;
864 (
865 (p as *const u64).read_unaligned(),
866 (p.add(8) as *const u64).read_unaligned(),
867 u64::from(p.add(16).read()),
868 (p.add(24) as *const u64).read_unaligned(),
869 )
870 }
871}
872
873unsafe fn text_from_words(view: &ViewHandle, w: (u64, u64, u64, u64)) -> ViewHandle {
879 unsafe {
880 let mut out = vec![0u8; abi::type_bytes(view.meta)];
881 let p: *mut u8 = out.as_mut_ptr();
882 (p as *mut u64).write_unaligned(w.0);
883 (p.add(8) as *mut u64).write_unaligned(w.1);
884 p.add(16).write(w.2 as u8);
885 (p.add(24) as *mut u64).write_unaligned(w.3);
886 super::wrap_owned(out, view.meta, view.wt)
887 }
888}
889
890fn is_text(view: &ViewHandle) -> bool {
895 crate::diag::type_name(view.meta) == "SwiftUI.Text"
896}
897
898unsafe fn text_call0(view: &ViewHandle, f: *const c_void) -> ViewHandle {
905 unsafe {
906 let (a, b, c, d) = text_words(view);
907 let (r0, r1, r2, r3): (u64, u64, u64, u64);
908 core::arch::asm!("blr {f}", f = in(reg) f,
909 inout("x0") a => r0, inout("x1") b => r1,
910 inout("x2") c => r2, inout("x3") d => r3,
911 lateout("x4") _, lateout("x5") _, lateout("x6") _, lateout("x7") _,
912 lateout("x8") _, lateout("x9") _, lateout("x10") _, lateout("x11") _,
913 lateout("x12") _, lateout("x13") _, lateout("x14") _, lateout("x15") _,
914 lateout("x16") _, lateout("x17") _, lateout("lr") _, lateout("x20") _,
915 lateout("x21") _, clobber_abi("C"),
916 );
917 text_from_words(view, (r0, r1, r2, r3))
918 }
919}
920
921unsafe fn text_call1(view: &ViewHandle, f: *const c_void, w: u64) -> ViewHandle {
926 unsafe {
927 let (a, b, c, d) = text_words(view);
928 let (r0, r1, r2, r3): (u64, u64, u64, u64);
929 core::arch::asm!("blr {f}", f = in(reg) f,
930 inout("x0") w => r0, inout("x1") a => r1,
931 inout("x2") b => r2, inout("x3") c => r3,
932 inout("x4") d => _,
933 lateout("x5") _, lateout("x6") _, lateout("x7") _,
934 lateout("x8") _, lateout("x9") _, lateout("x10") _, lateout("x11") _,
935 lateout("x12") _, lateout("x13") _, lateout("x14") _, lateout("x15") _,
936 lateout("x16") _, lateout("x17") _, lateout("lr") _, lateout("x20") _,
937 lateout("x21") _, clobber_abi("C"),
938 );
939 text_from_words(view, (r0, r1, r2, r3))
940 }
941}
942
943unsafe fn text_call_f64(view: &ViewHandle, f: *const c_void, x: f64) -> ViewHandle {
949 unsafe {
950 let (a, b, c, d) = text_words(view);
951 let (r0, r1, r2, r3): (u64, u64, u64, u64);
952 core::arch::asm!("blr {f}", f = in(reg) f,
953 in("d0") x,
954 inout("x0") a => r0, inout("x1") b => r1,
955 inout("x2") c => r2, inout("x3") d => r3,
956 lateout("x4") _, lateout("x5") _, lateout("x6") _, lateout("x7") _,
957 lateout("x8") _, lateout("x9") _, lateout("x10") _, lateout("x11") _,
958 lateout("x12") _, lateout("x13") _, lateout("x14") _, lateout("x15") _,
959 lateout("x16") _, lateout("x17") _, lateout("lr") _, lateout("x20") _,
960 lateout("x21") _, clobber_abi("C"),
961 );
962 text_from_words(view, (r0, r1, r2, r3))
963 }
964}
965
966pub fn text_bold(view: &ViewHandle) -> ViewHandle {
971 if !is_text(view) {
972 return super::bold(view);
973 }
974 unsafe { text_call0(view, resolve::text_bold()) }
975}
976
977pub fn text_italic(view: &ViewHandle) -> ViewHandle {
979 if !is_text(view) {
980 return super::italic(view);
981 }
982 unsafe { text_call0(view, resolve::text_italic()) }
983}
984
985pub fn text_monospaced(view: &ViewHandle) -> ViewHandle {
987 if !is_text(view) {
988 return super::monospaced(view);
989 }
990 unsafe { text_call1(view, resolve::text_monospaced(), 1) }
991}
992
993pub fn text_foreground_color(view: &ViewHandle, color: crate::Color) -> ViewHandle {
995 if !is_text(view) {
996 return super::foreground_style_color(view, color.r, color.g, color.b, color.a);
997 }
998 unsafe { text_call1(view, resolve::text_fg_color(), super::color_value_of(color)) }
999}
1000
1001pub fn text_kerning(view: &ViewHandle, amount: f64) -> ViewHandle {
1003 if !is_text(view) {
1004 return super::kerning(view, amount);
1005 }
1006 unsafe { text_call_f64(view, resolve::text_kerning(), amount) }
1007}
1008
1009pub fn text_tracking(view: &ViewHandle, amount: f64) -> ViewHandle {
1012 if !is_text(view) {
1013 return super::tracking(view, amount);
1014 }
1015 unsafe { text_call_f64(view, resolve::text_tracking(), amount) }
1016}
1017
1018pub fn text_baseline_offset(view: &ViewHandle, amount: f64) -> ViewHandle {
1020 if !is_text(view) {
1021 return view.clone();
1022 }
1023 unsafe { text_call_f64(view, resolve::text_baseline(), amount) }
1024}
1025pub fn text_font(view: &ViewHandle, font: Option<&super::Font>) -> ViewHandle {
1032 if !is_text(view) {
1033 return match font {
1034 Some(f) => super::font_ref(view, f),
1035 None => view.clone(),
1036 };
1037 }
1038 unsafe { text_call1(view, resolve::text_font(), font.map_or(0, super::Font::raw)) }
1039}
1040
1041pub fn text_font_weight(view: &ViewHandle, weight: Option<super::Weight>) -> ViewHandle {
1047 if !is_text(view) {
1048 return match weight {
1049 Some(w) => super::font_weight(view, w),
1050 None => view.clone(),
1051 };
1052 }
1053 unsafe {
1054 let (a, b, c, d) = text_words(view);
1055 let (w0, w1) = match weight {
1059 Some(w) => (w.value().to_bits(), 0u64),
1062 None => (0, 1),
1063 };
1064 let (r0, r1, r2, r3): (u64, u64, u64, u64);
1065 core::arch::asm!("blr {f}", f = in(reg) resolve::text_font_weight(),
1066 inout("x0") w0 => r0, inout("x1") w1 => r1,
1067 inout("x2") a => r2, inout("x3") b => r3,
1068 inout("x4") c => _, inout("x5") d => _,
1069 lateout("x6") _, lateout("x7") _,
1070 lateout("x8") _, lateout("x9") _, lateout("x10") _, lateout("x11") _,
1071 lateout("x12") _, lateout("x13") _, lateout("x14") _, lateout("x15") _,
1072 lateout("x16") _, lateout("x17") _, lateout("lr") _, lateout("x20") _,
1073 lateout("x21") _, clobber_abi("C"),
1074 );
1075 text_from_words(view, (r0, r1, r2, r3))
1076 }
1077}
1078
1079pub unsafe fn text_foreground_style(
1090 view: &ViewHandle,
1091 style: &[u8],
1092 style_meta: *const c_void,
1093 style_wt: *const c_void,
1094) -> ViewHandle {
1095 if !is_text(view) {
1096 return unsafe { foreground_style_of(view, style, style_meta, style_wt, &FOREGROUND_GRADIENT_T) };
1097 }
1098 unsafe {
1099 let (a, b, c, d) = text_words(view);
1100 let mut buf = style.to_vec();
1101 let (r0, r1, r2, r3): (u64, u64, u64, u64);
1102 core::arch::asm!("blr {f}", f = in(reg) resolve::text_fg_style(),
1103 inout("x0") buf.as_mut_ptr() as u64 => r0,
1104 inout("x1") a => r1, inout("x2") b => r2, inout("x3") c => r3,
1105 inout("x4") d => _,
1106 in("x5") style_meta, in("x6") style_wt,
1107 lateout("x7") _,
1108 lateout("x8") _, lateout("x9") _, lateout("x10") _, lateout("x11") _,
1109 lateout("x12") _, lateout("x13") _, lateout("x14") _, lateout("x15") _,
1110 lateout("x16") _, lateout("x17") _, lateout("lr") _, lateout("x20") _,
1111 lateout("x21") _, clobber_abi("C"),
1112 );
1113 text_from_words(view, (r0, r1, r2, r3))
1114 }
1115}
1116
1117pub fn text_foreground_linear_gradient(
1119 view: &ViewHandle,
1120 colors: &[u64],
1121 start: (f64, f64),
1122 end: (f64, f64),
1123) -> ViewHandle {
1124 let (style, meta, wt) = super::linear_gradient_style_of(colors, start, end);
1125 unsafe { text_foreground_style(view, &style, meta, wt) }
1126}
1127
1128pub fn text_foreground_hierarchical(
1130 view: &ViewHandle,
1131 level: super::Hierarchical,
1132) -> ViewHandle {
1133 let (style, meta, wt) = super::hierarchical_style(level);
1134 unsafe { text_foreground_style(view, &style, meta, wt) }
1135}