| 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::new(); |
| 163 | let coordinates = 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::new([variation_position::Coordinate { |
| 171 | axis: 0.into(), |
| 172 | value: 1.0, |
| 173 | }]); |
| 174 | let args = FontArguments::new(); |
| 175 | let pos = VariationPosition { |
| 176 | coordinates: coordinates.as_ref(), |
| 177 | }; |
| 178 | let args = args.set_variation_design_position(pos); |
| 179 | assert_eq!(args.variation_design_position().coordinates[0].value, 1.0); |
| 180 | drop(args); |
| 181 | } |
| 182 | |