| 1 | use crate::{interop, prelude::*, scalar, Matrix, Rect, Vector}; |
| 2 | use skia_bindings::{self as sb, SkRRect}; |
| 3 | use std::{fmt, mem, ptr}; |
| 4 | |
| 5 | pub use skia_bindings::SkRRect_Type as Type; |
| 6 | variant_name!(Type::Complex); |
| 7 | |
| 8 | pub use skia_bindings::SkRRect_Corner as Corner; |
| 9 | variant_name!(Corner::LowerLeft); |
| 10 | |
| 11 | #[derive (Copy, Clone)] |
| 12 | #[repr (transparent)] |
| 13 | pub struct RRect(SkRRect); |
| 14 | |
| 15 | native_transmutable!(SkRRect, RRect, rrect_layout); |
| 16 | |
| 17 | impl PartialEq for RRect { |
| 18 | fn eq(&self, rhs: &Self) -> bool { |
| 19 | unsafe { sb::C_SkRRect_Equals(self.native(), rhs.native()) } |
| 20 | } |
| 21 | } |
| 22 | |
| 23 | impl Default for RRect { |
| 24 | fn default() -> Self { |
| 25 | Self::new() |
| 26 | } |
| 27 | } |
| 28 | |
| 29 | impl fmt::Debug for RRect { |
| 30 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
| 31 | f&mut DebugStruct<'_, '_>.debug_struct("RRect" ) |
| 32 | .field("rect" , &self.rect()) |
| 33 | .field( |
| 34 | "radii" , |
| 35 | &[ |
| 36 | self.radii(Corner::UpperLeft), |
| 37 | self.radii(Corner::UpperRight), |
| 38 | self.radii(Corner::LowerRight), |
| 39 | self.radii(Corner::LowerLeft), |
| 40 | ], |
| 41 | ) |
| 42 | .field(name:"type" , &self.get_type()) |
| 43 | .finish() |
| 44 | } |
| 45 | } |
| 46 | |
| 47 | impl AsRef<RRect> for RRect { |
| 48 | fn as_ref(&self) -> &RRect { |
| 49 | self |
| 50 | } |
| 51 | } |
| 52 | |
| 53 | impl RRect { |
| 54 | pub fn new() -> Self { |
| 55 | RRect::construct(|rr| unsafe { sb::C_SkRRect_Construct(rr) }) |
| 56 | } |
| 57 | |
| 58 | pub fn get_type(&self) -> Type { |
| 59 | unsafe { sb::C_SkRRect_getType(self.native()) } |
| 60 | } |
| 61 | |
| 62 | pub fn is_empty(&self) -> bool { |
| 63 | self.get_type() == Type::Empty |
| 64 | } |
| 65 | |
| 66 | pub fn is_rect(&self) -> bool { |
| 67 | self.get_type() == Type::Rect |
| 68 | } |
| 69 | |
| 70 | pub fn is_oval(&self) -> bool { |
| 71 | self.get_type() == Type::Oval |
| 72 | } |
| 73 | |
| 74 | pub fn is_simple(&self) -> bool { |
| 75 | self.get_type() == Type::Simple |
| 76 | } |
| 77 | |
| 78 | pub fn is_nine_patch(&self) -> bool { |
| 79 | self.get_type() == Type::NinePatch |
| 80 | } |
| 81 | |
| 82 | pub fn is_complex(&self) -> bool { |
| 83 | self.get_type() == Type::Complex |
| 84 | } |
| 85 | |
| 86 | pub fn width(&self) -> scalar { |
| 87 | self.rect().width() |
| 88 | } |
| 89 | |
| 90 | pub fn height(&self) -> scalar { |
| 91 | self.rect().height() |
| 92 | } |
| 93 | |
| 94 | pub fn simple_radii(&self) -> Vector { |
| 95 | self.radii(Corner::UpperLeft) |
| 96 | } |
| 97 | |
| 98 | pub fn set_empty(&mut self) { |
| 99 | *self = Self::new() |
| 100 | } |
| 101 | |
| 102 | pub fn set_rect(&mut self, rect: impl AsRef<Rect>) { |
| 103 | unsafe { sb::C_SkRRect_setRect(self.native_mut(), rect.as_ref().native()) } |
| 104 | } |
| 105 | |
| 106 | pub fn new_empty() -> Self { |
| 107 | Self::new() |
| 108 | } |
| 109 | |
| 110 | // TODO: consider to rename all the following new_* function to from_* functions? |
| 111 | // is it possible to find a proper convention here (new_ vs from_?)? |
| 112 | |
| 113 | pub fn new_rect(rect: impl AsRef<Rect>) -> Self { |
| 114 | let mut rr = Self::default(); |
| 115 | rr.set_rect(rect); |
| 116 | rr |
| 117 | } |
| 118 | |
| 119 | pub fn new_oval(oval: impl AsRef<Rect>) -> Self { |
| 120 | let mut rr = Self::default(); |
| 121 | rr.set_oval(oval); |
| 122 | rr |
| 123 | } |
| 124 | |
| 125 | pub fn new_rect_xy(rect: impl AsRef<Rect>, x_rad: scalar, y_rad: scalar) -> Self { |
| 126 | let mut rr = Self::default(); |
| 127 | rr.set_rect_xy(rect.as_ref(), x_rad, y_rad); |
| 128 | rr |
| 129 | } |
| 130 | |
| 131 | pub fn new_nine_patch( |
| 132 | rect: impl AsRef<Rect>, |
| 133 | left_rad: scalar, |
| 134 | top_rad: scalar, |
| 135 | right_rad: scalar, |
| 136 | bottom_rad: scalar, |
| 137 | ) -> Self { |
| 138 | let mut r = Self::default(); |
| 139 | unsafe { |
| 140 | r.native_mut().setNinePatch( |
| 141 | rect.as_ref().native(), |
| 142 | left_rad, |
| 143 | top_rad, |
| 144 | right_rad, |
| 145 | bottom_rad, |
| 146 | ) |
| 147 | } |
| 148 | r |
| 149 | } |
| 150 | |
| 151 | pub fn new_rect_radii(rect: impl AsRef<Rect>, radii: &[Vector; 4]) -> Self { |
| 152 | let mut r = Self::default(); |
| 153 | unsafe { |
| 154 | r.native_mut() |
| 155 | .setRectRadii(rect.as_ref().native(), radii.native().as_ptr()) |
| 156 | } |
| 157 | r |
| 158 | } |
| 159 | |
| 160 | pub fn set_oval(&mut self, oval: impl AsRef<Rect>) { |
| 161 | unsafe { self.native_mut().setOval(oval.as_ref().native()) } |
| 162 | } |
| 163 | |
| 164 | pub fn set_rect_xy(&mut self, rect: impl AsRef<Rect>, x_rad: scalar, y_rad: scalar) { |
| 165 | unsafe { |
| 166 | self.native_mut() |
| 167 | .setRectXY(rect.as_ref().native(), x_rad, y_rad) |
| 168 | } |
| 169 | } |
| 170 | |
| 171 | pub fn set_nine_patch( |
| 172 | &mut self, |
| 173 | rect: impl AsRef<Rect>, |
| 174 | left_rad: scalar, |
| 175 | top_rad: scalar, |
| 176 | right_rad: scalar, |
| 177 | bottom_rad: scalar, |
| 178 | ) { |
| 179 | unsafe { |
| 180 | self.native_mut().setNinePatch( |
| 181 | rect.as_ref().native(), |
| 182 | left_rad, |
| 183 | top_rad, |
| 184 | right_rad, |
| 185 | bottom_rad, |
| 186 | ) |
| 187 | } |
| 188 | } |
| 189 | |
| 190 | pub fn set_rect_radii(&mut self, rect: impl AsRef<Rect>, radii: &[Vector; 4]) { |
| 191 | unsafe { |
| 192 | self.native_mut() |
| 193 | .setRectRadii(rect.as_ref().native(), radii.native().as_ptr()) |
| 194 | } |
| 195 | } |
| 196 | |
| 197 | pub fn rect(&self) -> &Rect { |
| 198 | Rect::from_native_ref(&self.native().fRect) |
| 199 | } |
| 200 | |
| 201 | pub fn radii(&self, corner: Corner) -> Vector { |
| 202 | Vector::from_native_c(self.native().fRadii[corner as usize]) |
| 203 | } |
| 204 | |
| 205 | pub fn radii_ref(&self) -> &[Vector; 4] { |
| 206 | Vector::from_native_array_ref(&self.native().fRadii) |
| 207 | } |
| 208 | |
| 209 | pub fn bounds(&self) -> &Rect { |
| 210 | self.rect() |
| 211 | } |
| 212 | |
| 213 | pub fn inset(&mut self, delta: impl Into<Vector>) { |
| 214 | *self = self.with_inset(delta) |
| 215 | } |
| 216 | |
| 217 | #[must_use ] |
| 218 | pub fn with_inset(&self, delta: impl Into<Vector>) -> Self { |
| 219 | let delta = delta.into(); |
| 220 | let mut r = Self::default(); |
| 221 | unsafe { self.native().inset(delta.x, delta.y, r.native_mut()) }; |
| 222 | r |
| 223 | } |
| 224 | |
| 225 | pub fn outset(&mut self, delta: impl Into<Vector>) { |
| 226 | *self = self.with_outset(delta) |
| 227 | } |
| 228 | |
| 229 | #[must_use ] |
| 230 | pub fn with_outset(&self, delta: impl Into<Vector>) -> Self { |
| 231 | self.with_inset(-delta.into()) |
| 232 | } |
| 233 | |
| 234 | pub fn offset(&mut self, delta: impl Into<Vector>) { |
| 235 | Rect::from_native_ref_mut(&mut self.native_mut().fRect).offset(delta) |
| 236 | } |
| 237 | |
| 238 | #[must_use ] |
| 239 | pub fn with_offset(&self, delta: impl Into<Vector>) -> Self { |
| 240 | let mut copied = *self; |
| 241 | copied.offset(delta); |
| 242 | copied |
| 243 | } |
| 244 | |
| 245 | pub fn contains(&self, rect: impl AsRef<Rect>) -> bool { |
| 246 | unsafe { self.native().contains(rect.as_ref().native()) } |
| 247 | } |
| 248 | |
| 249 | pub fn is_valid(&self) -> bool { |
| 250 | unsafe { self.native().isValid() } |
| 251 | } |
| 252 | |
| 253 | pub const SIZE_IN_MEMORY: usize = mem::size_of::<Self>(); |
| 254 | |
| 255 | pub fn write_to_memory(&self, buffer: &mut Vec<u8>) { |
| 256 | unsafe { |
| 257 | let size = self.native().writeToMemory(ptr::null_mut()); |
| 258 | buffer.resize(size, 0); |
| 259 | let written = self.native().writeToMemory(buffer.as_mut_ptr() as _); |
| 260 | debug_assert_eq!(written, size); |
| 261 | } |
| 262 | } |
| 263 | |
| 264 | pub fn read_from_memory(&mut self, buffer: &[u8]) -> usize { |
| 265 | unsafe { |
| 266 | self.native_mut() |
| 267 | .readFromMemory(buffer.as_ptr() as _, buffer.len()) |
| 268 | } |
| 269 | } |
| 270 | |
| 271 | #[must_use ] |
| 272 | pub fn transform(&self, matrix: &Matrix) -> Option<Self> { |
| 273 | let mut r = Self::default(); |
| 274 | unsafe { self.native().transform(matrix.native(), r.native_mut()) }.if_true_some(r) |
| 275 | } |
| 276 | |
| 277 | pub fn dump(&self, as_hex: impl Into<Option<bool>>) { |
| 278 | unsafe { self.native().dump(as_hex.into().unwrap_or_default()) } |
| 279 | } |
| 280 | |
| 281 | pub fn dump_to_string(&self, as_hex: bool) -> String { |
| 282 | let mut str = interop::String::default(); |
| 283 | unsafe { sb::C_SkRRect_dumpToString(self.native(), as_hex, str.native_mut()) } |
| 284 | str.to_string() |
| 285 | } |
| 286 | |
| 287 | pub fn dump_hex(&self) { |
| 288 | self.dump(true) |
| 289 | } |
| 290 | } |
| 291 | |