1use crate::prelude::*;
2use sb::SkFontArguments_Palette;
3use skia_bindings::{self as sb, SkFontArguments, SkFontArguments_VariationPosition};
4use std::{fmt, marker::PhantomData, mem};
5
6#[derive(Clone, Debug)]
7pub struct VariationPosition<'a> {
8 pub coordinates: &'a [variation_position::Coordinate],
9}
10
11pub mod variation_position {
12 use crate::FourByteTag;
13 use skia_bindings::SkFontArguments_VariationPosition_Coordinate;
14
15 #[derive(Copy, Clone, PartialEq, Default, Debug)]
16 #[repr(C)]
17 pub struct Coordinate {
18 pub axis: FourByteTag,
19 pub value: f32,
20 }
21
22 native_transmutable!(
23 SkFontArguments_VariationPosition_Coordinate,
24 Coordinate,
25 coordinate_layout
26 );
27}
28
29#[derive(Clone, Debug)]
30pub struct Palette<'a> {
31 pub index: i32,
32 pub overrides: &'a [palette::Override],
33}
34
35pub mod palette {
36 use crate::Color;
37 use skia_bindings::SkFontArguments_Palette_Override;
38
39 #[derive(Copy, Clone, PartialEq, Eq, Default, Debug)]
40 #[repr(C)]
41 pub struct Override {
42 pub index: u16,
43 pub color: Color,
44 }
45
46 native_transmutable!(SkFontArguments_Palette_Override, Override, override_layout);
47}
48
49#[repr(C)]
50pub struct FontArguments<'vp, 'p> {
51 args: SkFontArguments,
52 pd_vp: PhantomData<&'vp [variation_position::Coordinate]>,
53 pd_p: PhantomData<&'p [palette::Override]>,
54}
55
56native_transmutable!(
57 SkFontArguments,
58 FontArguments<'_, '_>,
59 font_arguments_layout
60);
61
62impl Drop for FontArguments<'_, '_> {
63 fn drop(&mut self) {
64 unsafe { sb::C_SkFontArguments_destruct(self.native_mut()) }
65 }
66}
67
68impl Default for FontArguments<'_, '_> {
69 fn default() -> Self {
70 FontArguments::new()
71 }
72}
73
74impl fmt::Debug for FontArguments<'_, '_> {
75 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
76 f&mut DebugStruct<'_, '_>.debug_struct("FontArguments")
77 .field("collection_index", &self.collection_index())
78 .field(
79 "variation_design_position",
80 &self.variation_design_position(),
81 )
82 .field(name:"palette", &self.palette())
83 .finish()
84 }
85}
86
87impl FontArguments<'_, '_> {
88 pub fn new() -> Self {
89 Self::construct(|fa| unsafe {
90 sb::C_SkFontArguments_construct(fa);
91 })
92 }
93
94 pub fn set_collection_index(&mut self, collection_index: usize) -> &mut Self {
95 self.native_mut().fCollectionIndex = collection_index.try_into().unwrap();
96 self
97 }
98
99 // This function consumes self for it to be able to change its lifetime,
100 // because it borrows the coordinates referenced by [`VariationPosition`].
101 //
102 // If we would return `Self`, position's Coordinates would not be borrowed.
103 pub fn set_variation_design_position(mut self, position: VariationPosition) -> FontArguments {
104 let position = SkFontArguments_VariationPosition {
105 coordinates: position.coordinates.native().as_ptr(),
106 coordinateCount: position.coordinates.len().try_into().unwrap(),
107 };
108 unsafe {
109 sb::C_SkFontArguments_setVariationDesignPosition(self.native_mut(), position);
110 // note: we are _not_ returning Self here, but VariationPosition with a
111 // changed lifetime.
112 mem::transmute(self)
113 }
114 }
115
116 pub fn collection_index(&self) -> usize {
117 self.native().fCollectionIndex.try_into().unwrap()
118 }
119
120 pub fn variation_design_position(&self) -> VariationPosition {
121 unsafe {
122 let position = sb::C_SkFontArguments_getVariationDesignPosition(self.native());
123 VariationPosition {
124 coordinates: safer::from_raw_parts(
125 position.coordinates as *const _,
126 position.coordinateCount.try_into().unwrap(),
127 ),
128 }
129 }
130 }
131
132 // This function consumes `self` for it to be able to change its lifetime, because it borrows
133 // the coordinates referenced by `[Palette]`.
134 pub fn set_palette(mut self, palette: Palette) -> FontArguments {
135 let palette = SkFontArguments_Palette {
136 index: palette.index,
137 overrides: palette.overrides.native().as_ptr(),
138 overrideCount: palette.overrides.len().try_into().unwrap(),
139 };
140 unsafe {
141 sb::C_SkFontArguments_setPalette(self.native_mut(), palette);
142 mem::transmute(self)
143 }
144 }
145
146 pub fn palette(&self) -> Palette {
147 unsafe {
148 let palette = sb::C_SkFontArguments_getPalette(self.native());
149 Palette {
150 index: palette.index,
151 overrides: safer::from_raw_parts(
152 palette.overrides as *const _,
153 palette.overrideCount.try_into().unwrap(),
154 ),
155 }
156 }
157 }
158}
159
160#[test]
161fn test_font_arguments_with_no_coordinates() {
162 let fa: FontArguments<'_, '_> = FontArguments::new();
163 let coordinates: VariationPosition<'_> = fa.variation_design_position();
164 assert_eq!(coordinates.coordinates, []);
165}
166
167#[test]
168#[allow(clippy::float_cmp)]
169fn access_coordinates() {
170 let coordinates: Box<[Coordinate; 1]> = Box::new([variation_position::Coordinate {
171 axis: 0.into(),
172 value: 1.0,
173 }]);
174 let args: FontArguments<'_, '_> = FontArguments::new();
175 let pos: VariationPosition<'_> = VariationPosition {
176 coordinates: coordinates.as_ref(),
177 };
178 let args: FontArguments<'_, '_> = args.set_variation_design_position(pos);
179 assert_eq!(args.variation_design_position().coordinates[0].value, 1.0);
180 drop(args);
181}
182