1 | use crate::prelude::*; |
2 | use sb::SkFontArguments_Palette; |
3 | use skia_bindings::{self as sb, SkFontArguments, SkFontArguments_VariationPosition}; |
4 | use std::{fmt, marker::PhantomData, mem}; |
5 | |
6 | #[derive (Clone, Debug)] |
7 | pub struct VariationPosition<'a> { |
8 | pub coordinates: &'a [variation_position::Coordinate], |
9 | } |
10 | |
11 | pub 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)] |
30 | pub struct Palette<'a> { |
31 | pub index: i32, |
32 | pub overrides: &'a [palette::Override], |
33 | } |
34 | |
35 | pub 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)] |
50 | pub struct FontArguments<'vp, 'p> { |
51 | args: SkFontArguments, |
52 | pd_vp: PhantomData<&'vp [variation_position::Coordinate]>, |
53 | pd_p: PhantomData<&'p [palette::Override]>, |
54 | } |
55 | |
56 | native_transmutable!( |
57 | SkFontArguments, |
58 | FontArguments<'_, '_>, |
59 | font_arguments_layout |
60 | ); |
61 | |
62 | impl Drop for FontArguments<'_, '_> { |
63 | fn drop(&mut self) { |
64 | unsafe { sb::C_SkFontArguments_destruct(self.native_mut()) } |
65 | } |
66 | } |
67 | |
68 | impl Default for FontArguments<'_, '_> { |
69 | fn default() -> Self { |
70 | FontArguments::new() |
71 | } |
72 | } |
73 | |
74 | impl 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 | |
87 | impl 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 ] |
161 | fn 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)] |
169 | fn 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 | |