1 | use super::scalar_; |
2 | use crate::{prelude::*, scalar, Point, Point3, RSXform, Rect, Scalar, Size, Vector}; |
3 | use skia_bindings::{self as sb, SkMatrix}; |
4 | use std::{ |
5 | ops::{Index, IndexMut, Mul}, |
6 | slice, |
7 | }; |
8 | |
9 | pub use skia_bindings::SkApplyPerspectiveClip as ApplyPerspectiveClip; |
10 | variant_name!(ApplyPerspectiveClip::Yes); |
11 | |
12 | bitflags! { |
13 | // m85: On Windows the SkMatrix_TypeMask is defined as i32, |
14 | // but we stick to u32 (macOS / Linux), because there is no need to leak |
15 | // the platform difference to the Rust side. |
16 | #[derive (Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] |
17 | pub struct TypeMask: u32 { |
18 | const IDENTITY = sb::SkMatrix_TypeMask_kIdentity_Mask as _; |
19 | const TRANSLATE = sb::SkMatrix_TypeMask_kTranslate_Mask as _; |
20 | const SCALE = sb::SkMatrix_TypeMask_kScale_Mask as _; |
21 | const AFFINE = sb::SkMatrix_TypeMask_kAffine_Mask as _; |
22 | const PERSPECTIVE = sb::SkMatrix_TypeMask_kPerspective_Mask as _; |
23 | } |
24 | } |
25 | |
26 | impl TypeMask { |
27 | const UNKNOWN: u32 = sb::SkMatrix_kUnknown_Mask as _; |
28 | } |
29 | |
30 | pub use skia_bindings::SkMatrix_ScaleToFit as ScaleToFit; |
31 | variant_name!(ScaleToFit::Fill); |
32 | |
33 | #[repr (C)] |
34 | #[derive (Copy, Clone, Debug)] |
35 | pub struct Matrix { |
36 | mat: [scalar; 9usize], |
37 | type_mask: u32, |
38 | } |
39 | |
40 | native_transmutable!(SkMatrix, Matrix, matrix_layout); |
41 | |
42 | impl PartialEq for Matrix { |
43 | fn eq(&self, rhs: &Self) -> bool { |
44 | unsafe { sb::C_SkMatrix_Equals(self.native(), rhs:rhs.native()) } |
45 | } |
46 | } |
47 | |
48 | impl Mul for Matrix { |
49 | type Output = Self; |
50 | fn mul(self, rhs: Matrix) -> Self::Output { |
51 | Matrix::concat(&self, &rhs) |
52 | } |
53 | } |
54 | |
55 | #[derive (Copy, Clone, PartialEq, Eq, Debug)] |
56 | pub enum Member { |
57 | ScaleX = 0, |
58 | SkewX = 1, |
59 | TransX = 2, |
60 | SkewY = 3, |
61 | ScaleY = 4, |
62 | TransY = 5, |
63 | Persp0 = 6, |
64 | Persp1 = 7, |
65 | Persp2 = 8, |
66 | } |
67 | |
68 | #[derive (Copy, Clone, PartialEq, Eq, Debug)] |
69 | pub enum AffineMember { |
70 | ScaleX = 0, |
71 | SkewY = 1, |
72 | SkewX = 2, |
73 | ScaleY = 3, |
74 | TransX = 4, |
75 | TransY = 5, |
76 | } |
77 | |
78 | impl Index<Member> for Matrix { |
79 | type Output = scalar; |
80 | |
81 | fn index(&self, index: Member) -> &Self::Output { |
82 | &self[index as usize] |
83 | } |
84 | } |
85 | |
86 | impl Index<AffineMember> for Matrix { |
87 | type Output = scalar; |
88 | |
89 | fn index(&self, index: AffineMember) -> &Self::Output { |
90 | &self[index as usize] |
91 | } |
92 | } |
93 | |
94 | impl Index<usize> for Matrix { |
95 | type Output = scalar; |
96 | |
97 | fn index(&self, index: usize) -> &Self::Output { |
98 | &self.native().fMat[index] |
99 | } |
100 | } |
101 | |
102 | impl IndexMut<Member> for Matrix { |
103 | fn index_mut(&mut self, index: Member) -> &mut Self::Output { |
104 | self.index_mut(index as usize) |
105 | } |
106 | } |
107 | |
108 | impl IndexMut<AffineMember> for Matrix { |
109 | fn index_mut(&mut self, index: AffineMember) -> &mut Self::Output { |
110 | self.index_mut(index as usize) |
111 | } |
112 | } |
113 | |
114 | impl IndexMut<usize> for Matrix { |
115 | fn index_mut(&mut self, index: usize) -> &mut Self::Output { |
116 | unsafe { &mut *sb::C_SkMatrix_SubscriptMut(self.native_mut(), index) } |
117 | } |
118 | } |
119 | |
120 | impl Default for Matrix { |
121 | fn default() -> Self { |
122 | Matrix::new() |
123 | } |
124 | } |
125 | |
126 | impl Matrix { |
127 | const fn new() -> Self { |
128 | Self { |
129 | mat: [1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0], |
130 | type_mask: TypeMask::IDENTITY.bits() | 0x10, |
131 | } |
132 | } |
133 | |
134 | #[deprecated (since = "0.33.0" , note = "use Matrix::scale()" )] |
135 | pub fn new_scale(scale: (scalar, scalar)) -> Self { |
136 | Self::scale(scale) |
137 | } |
138 | |
139 | #[must_use ] |
140 | pub fn scale((sx, sy): (scalar, scalar)) -> Self { |
141 | let mut m = Self::new(); |
142 | m.set_scale((sx, sy), None); |
143 | m |
144 | } |
145 | |
146 | #[deprecated (since = "0.33.0" , note = "use Matrix::translate()" )] |
147 | pub fn new_trans(d: impl Into<Vector>) -> Self { |
148 | Self::translate(d) |
149 | } |
150 | |
151 | #[must_use ] |
152 | pub fn translate(d: impl Into<Vector>) -> Self { |
153 | let mut m = Self::new(); |
154 | m.set_translate(d); |
155 | m |
156 | } |
157 | |
158 | #[must_use ] |
159 | pub fn rotate_deg(deg: scalar) -> Self { |
160 | let mut m = Self::new(); |
161 | m.set_rotate(deg, None); |
162 | m |
163 | } |
164 | |
165 | #[must_use ] |
166 | pub fn rotate_deg_pivot(deg: scalar, pivot: impl Into<Point>) -> Self { |
167 | let mut m = Self::new(); |
168 | m.set_rotate(deg, pivot.into()); |
169 | m |
170 | } |
171 | |
172 | #[must_use ] |
173 | pub fn rotate_rad(rad: scalar) -> Self { |
174 | Self::rotate_deg(scalar_::radians_to_degrees(rad)) |
175 | } |
176 | |
177 | #[must_use ] |
178 | pub fn skew((kx, ky): (scalar, scalar)) -> Self { |
179 | let mut m = Self::new(); |
180 | m.set_skew((kx, ky), None); |
181 | m |
182 | } |
183 | |
184 | #[must_use ] |
185 | pub fn rect_to_rect( |
186 | src: impl AsRef<Rect>, |
187 | dst: impl AsRef<Rect>, |
188 | scale_to_fit: impl Into<Option<ScaleToFit>>, |
189 | ) -> Option<Self> { |
190 | Self::from_rect_to_rect(src, dst, scale_to_fit.into().unwrap_or(ScaleToFit::Fill)) |
191 | } |
192 | |
193 | #[must_use ] |
194 | #[allow (clippy::too_many_arguments)] |
195 | pub fn new_all( |
196 | scale_x: scalar, |
197 | skew_x: scalar, |
198 | trans_x: scalar, |
199 | skew_y: scalar, |
200 | scale_y: scalar, |
201 | trans_y: scalar, |
202 | pers_0: scalar, |
203 | pers_1: scalar, |
204 | pers_2: scalar, |
205 | ) -> Self { |
206 | let mut m = Self::new(); |
207 | m.set_all( |
208 | scale_x, skew_x, trans_x, skew_y, scale_y, trans_y, pers_0, pers_1, pers_2, |
209 | ); |
210 | m |
211 | } |
212 | |
213 | pub fn get_type(&self) -> TypeMask { |
214 | TypeMask::from_bits_truncate(unsafe { sb::C_SkMatrix_getType(self.native()) } as _) |
215 | } |
216 | |
217 | pub fn is_identity(&self) -> bool { |
218 | self.get_type() == TypeMask::IDENTITY |
219 | } |
220 | |
221 | pub fn is_scale_translate(&self) -> bool { |
222 | (self.get_type() & !(TypeMask::SCALE | TypeMask::TRANSLATE)).is_empty() |
223 | } |
224 | |
225 | pub fn is_translate(&self) -> bool { |
226 | (self.get_type() & !TypeMask::TRANSLATE).is_empty() |
227 | } |
228 | |
229 | pub fn rect_stays_rect(&self) -> bool { |
230 | unsafe { sb::C_SkMatrix_rectStaysRect(self.native()) } |
231 | } |
232 | |
233 | pub fn preserves_axis_alignment(&self) -> bool { |
234 | self.rect_stays_rect() |
235 | } |
236 | |
237 | pub fn has_perspective(&self) -> bool { |
238 | unsafe { sb::C_SkMatrix_hasPerspective(self.native()) } |
239 | } |
240 | |
241 | pub fn is_similarity(&self) -> bool { |
242 | unsafe { self.native().isSimilarity(scalar::NEARLY_ZERO) } |
243 | } |
244 | |
245 | pub fn preserves_right_angles(&self) -> bool { |
246 | unsafe { self.native().preservesRightAngles(scalar::NEARLY_ZERO) } |
247 | } |
248 | |
249 | pub fn rc(&self, r: usize, c: usize) -> scalar { |
250 | assert!(r <= 2); |
251 | assert!(c <= 2); |
252 | self[r * 3 + c] |
253 | } |
254 | |
255 | pub fn scale_x(&self) -> scalar { |
256 | self[Member::ScaleX] |
257 | } |
258 | |
259 | pub fn scale_y(&self) -> scalar { |
260 | self[Member::ScaleY] |
261 | } |
262 | |
263 | pub fn skew_y(&self) -> scalar { |
264 | self[Member::SkewY] |
265 | } |
266 | |
267 | pub fn skew_x(&self) -> scalar { |
268 | self[Member::SkewX] |
269 | } |
270 | |
271 | pub fn translate_x(&self) -> scalar { |
272 | self[Member::TransX] |
273 | } |
274 | |
275 | pub fn translate_y(&self) -> scalar { |
276 | self[Member::TransY] |
277 | } |
278 | |
279 | pub fn persp_x(&self) -> scalar { |
280 | self[Member::Persp0] |
281 | } |
282 | |
283 | pub fn persp_y(&self) -> scalar { |
284 | self[Member::Persp1] |
285 | } |
286 | |
287 | pub fn set_scale_x(&mut self, v: scalar) -> &mut Self { |
288 | self.set(Member::ScaleX, v) |
289 | } |
290 | |
291 | pub fn set_scale_y(&mut self, v: scalar) -> &mut Self { |
292 | self.set(Member::ScaleY, v) |
293 | } |
294 | |
295 | pub fn set_skew_y(&mut self, v: scalar) -> &mut Self { |
296 | self.set(Member::SkewY, v) |
297 | } |
298 | |
299 | pub fn set_skew_x(&mut self, v: scalar) -> &mut Self { |
300 | self.set(Member::SkewX, v) |
301 | } |
302 | |
303 | pub fn set_translate_x(&mut self, v: scalar) -> &mut Self { |
304 | self.set(Member::TransX, v) |
305 | } |
306 | |
307 | pub fn set_translate_y(&mut self, v: scalar) -> &mut Self { |
308 | self.set(Member::TransY, v) |
309 | } |
310 | |
311 | pub fn set_persp_x(&mut self, v: scalar) -> &mut Self { |
312 | self.set(Member::Persp0, v) |
313 | } |
314 | |
315 | pub fn set_persp_y(&mut self, v: scalar) -> &mut Self { |
316 | self.set(Member::Persp1, v) |
317 | } |
318 | |
319 | #[allow (clippy::too_many_arguments)] |
320 | pub fn set_all( |
321 | &mut self, |
322 | scale_x: scalar, |
323 | skew_x: scalar, |
324 | trans_x: scalar, |
325 | skew_y: scalar, |
326 | scale_y: scalar, |
327 | trans_y: scalar, |
328 | persp_0: scalar, |
329 | persp_1: scalar, |
330 | persp_2: scalar, |
331 | ) -> &mut Self { |
332 | self[Member::ScaleX] = scale_x; |
333 | self[Member::SkewX] = skew_x; |
334 | self[Member::TransX] = trans_x; |
335 | self[Member::SkewY] = skew_y; |
336 | self[Member::ScaleY] = scale_y; |
337 | self[Member::TransY] = trans_y; |
338 | self[Member::Persp0] = persp_0; |
339 | self[Member::Persp1] = persp_1; |
340 | self[Member::Persp2] = persp_2; |
341 | self.type_mask = TypeMask::UNKNOWN; |
342 | self |
343 | } |
344 | |
345 | pub fn get_9(&self, buffer: &mut [scalar; 9]) { |
346 | buffer.copy_from_slice(&self.mat) |
347 | } |
348 | |
349 | pub fn set_9(&mut self, buffer: &[scalar; 9]) -> &mut Self { |
350 | unsafe { |
351 | self.native_mut().set9(buffer.as_ptr()); |
352 | } |
353 | self |
354 | } |
355 | |
356 | pub fn reset(&mut self) -> &mut Self { |
357 | unsafe { |
358 | self.native_mut().reset(); |
359 | } |
360 | self |
361 | } |
362 | |
363 | pub fn set_identity(&mut self) -> &mut Self { |
364 | self.reset(); |
365 | self |
366 | } |
367 | |
368 | pub fn set_translate(&mut self, v: impl Into<Vector>) -> &mut Self { |
369 | let v = v.into(); |
370 | unsafe { |
371 | self.native_mut().setTranslate(v.x, v.y); |
372 | } |
373 | self |
374 | } |
375 | |
376 | pub fn set_scale( |
377 | &mut self, |
378 | (sx, sy): (scalar, scalar), |
379 | pivot: impl Into<Option<Point>>, |
380 | ) -> &mut Self { |
381 | let pivot = pivot.into().unwrap_or_default(); |
382 | unsafe { |
383 | self.native_mut().setScale(sx, sy, pivot.x, pivot.y); |
384 | } |
385 | self |
386 | } |
387 | |
388 | pub fn set_rotate(&mut self, degrees: scalar, pivot: impl Into<Option<Point>>) -> &mut Self { |
389 | let pivot = pivot.into().unwrap_or_default(); |
390 | unsafe { |
391 | self.native_mut().setRotate(degrees, pivot.x, pivot.y); |
392 | } |
393 | self |
394 | } |
395 | |
396 | pub fn set_sin_cos( |
397 | &mut self, |
398 | (sin_value, cos_value): (scalar, scalar), |
399 | pivot: impl Into<Option<Point>>, |
400 | ) -> &mut Self { |
401 | let pivot = pivot.into().unwrap_or_default(); |
402 | unsafe { |
403 | self.native_mut() |
404 | .setSinCos(sin_value, cos_value, pivot.x, pivot.y); |
405 | } |
406 | self |
407 | } |
408 | |
409 | pub fn set_rsxform(&mut self, rsxform: &RSXform) -> &mut Self { |
410 | unsafe { |
411 | self.native_mut().setRSXform(rsxform.native()); |
412 | } |
413 | self |
414 | } |
415 | |
416 | pub fn set_skew( |
417 | &mut self, |
418 | (kx, ky): (scalar, scalar), |
419 | pivot: impl Into<Option<Point>>, |
420 | ) -> &mut Self { |
421 | let pivot = pivot.into().unwrap_or_default(); |
422 | unsafe { |
423 | self.native_mut().setSkew(kx, ky, pivot.x, pivot.y); |
424 | } |
425 | self |
426 | } |
427 | |
428 | pub fn set_concat(&mut self, a: &Self, b: &Self) -> &mut Self { |
429 | unsafe { |
430 | self.native_mut().setConcat(a.native(), b.native()); |
431 | } |
432 | self |
433 | } |
434 | |
435 | pub fn pre_translate(&mut self, delta: impl Into<Vector>) -> &mut Self { |
436 | let delta = delta.into(); |
437 | unsafe { |
438 | self.native_mut().preTranslate(delta.x, delta.y); |
439 | } |
440 | self |
441 | } |
442 | |
443 | pub fn pre_scale( |
444 | &mut self, |
445 | (sx, sy): (scalar, scalar), |
446 | pivot: impl Into<Option<Point>>, |
447 | ) -> &mut Self { |
448 | let pivot = pivot.into().unwrap_or_default(); |
449 | unsafe { |
450 | self.native_mut().preScale(sx, sy, pivot.x, pivot.y); |
451 | } |
452 | self |
453 | } |
454 | |
455 | pub fn pre_rotate(&mut self, degrees: scalar, pivot: impl Into<Option<Point>>) -> &mut Self { |
456 | let pivot = pivot.into().unwrap_or_default(); |
457 | unsafe { |
458 | self.native_mut().preRotate(degrees, pivot.x, pivot.y); |
459 | } |
460 | self |
461 | } |
462 | |
463 | pub fn pre_skew( |
464 | &mut self, |
465 | (kx, ky): (scalar, scalar), |
466 | pivot: impl Into<Option<Point>>, |
467 | ) -> &mut Self { |
468 | let pivot = pivot.into().unwrap_or_default(); |
469 | unsafe { |
470 | self.native_mut().preSkew(kx, ky, pivot.x, pivot.y); |
471 | } |
472 | self |
473 | } |
474 | |
475 | pub fn pre_concat(&mut self, other: &Self) -> &mut Self { |
476 | unsafe { |
477 | self.native_mut().preConcat(other.native()); |
478 | } |
479 | self |
480 | } |
481 | |
482 | pub fn post_translate(&mut self, delta: impl Into<Vector>) -> &mut Self { |
483 | let delta = delta.into(); |
484 | unsafe { |
485 | self.native_mut().postTranslate(delta.x, delta.y); |
486 | } |
487 | self |
488 | } |
489 | |
490 | pub fn post_scale( |
491 | &mut self, |
492 | (sx, sy): (scalar, scalar), |
493 | pivot: impl Into<Option<Point>>, |
494 | ) -> &mut Self { |
495 | let pivot = pivot.into().unwrap_or_default(); |
496 | unsafe { |
497 | self.native_mut().postScale(sx, sy, pivot.x, pivot.y); |
498 | } |
499 | self |
500 | } |
501 | |
502 | #[deprecated ( |
503 | since = "0.27.0" , |
504 | note = "use post_scale((1.0 / x as scalar, 1.0 / y as scalar), None)" |
505 | )] |
506 | pub fn post_idiv(&mut self, (div_x, div_y): (i32, i32)) -> bool { |
507 | if div_x == 0 || div_y == 0 { |
508 | return false; |
509 | } |
510 | self.post_scale((1.0 / div_x as scalar, 1.0 / div_y as scalar), None); |
511 | true |
512 | } |
513 | |
514 | pub fn post_rotate(&mut self, degrees: scalar, pivot: impl Into<Option<Point>>) -> &mut Self { |
515 | let pivot = pivot.into().unwrap_or_default(); |
516 | unsafe { |
517 | self.native_mut().postRotate(degrees, pivot.x, pivot.y); |
518 | } |
519 | self |
520 | } |
521 | |
522 | pub fn post_skew( |
523 | &mut self, |
524 | (kx, ky): (scalar, scalar), |
525 | pivot: impl Into<Option<Point>>, |
526 | ) -> &mut Self { |
527 | let pivot = pivot.into().unwrap_or_default(); |
528 | unsafe { |
529 | self.native_mut().postSkew(kx, ky, pivot.x, pivot.y); |
530 | } |
531 | self |
532 | } |
533 | |
534 | pub fn post_concat(&mut self, other: &Matrix) -> &mut Self { |
535 | unsafe { |
536 | self.native_mut().postConcat(other.native()); |
537 | } |
538 | self |
539 | } |
540 | |
541 | pub fn set_rect_to_rect( |
542 | &mut self, |
543 | src: impl AsRef<Rect>, |
544 | dst: impl AsRef<Rect>, |
545 | stf: ScaleToFit, |
546 | ) -> bool { |
547 | unsafe { |
548 | self.native_mut() |
549 | .setRectToRect(src.as_ref().native(), dst.as_ref().native(), stf) |
550 | } |
551 | } |
552 | |
553 | pub fn from_rect_to_rect( |
554 | src: impl AsRef<Rect>, |
555 | dst: impl AsRef<Rect>, |
556 | stf: ScaleToFit, |
557 | ) -> Option<Self> { |
558 | let mut m = Self::new_identity(); |
559 | m.set_rect_to_rect(src, dst, stf).if_true_some(m) |
560 | } |
561 | |
562 | pub fn set_poly_to_poly(&mut self, src: &[Point], dst: &[Point]) -> bool { |
563 | if src.len() != dst.len() { |
564 | return false; |
565 | } |
566 | unsafe { |
567 | self.native_mut().setPolyToPoly( |
568 | src.native().as_ptr(), |
569 | dst.native().as_ptr(), |
570 | src.len().try_into().unwrap(), |
571 | ) |
572 | } |
573 | } |
574 | |
575 | pub fn from_poly_to_poly(src: &[Point], dst: &[Point]) -> Option<Matrix> { |
576 | let mut m = Matrix::new_identity(); |
577 | m.set_poly_to_poly(src, dst).if_true_some(m) |
578 | } |
579 | |
580 | #[must_use ] |
581 | pub fn invert(&self) -> Option<Matrix> { |
582 | let mut m = Matrix::new_identity(); |
583 | unsafe { sb::C_SkMatrix_invert(self.native(), m.native_mut()) }.if_true_some(m) |
584 | } |
585 | |
586 | pub fn set_affine_identity(affine: &mut [scalar; 6]) { |
587 | unsafe { SkMatrix::SetAffineIdentity(affine.as_mut_ptr()) } |
588 | } |
589 | |
590 | #[must_use ] |
591 | pub fn to_affine(self) -> Option<[scalar; 6]> { |
592 | let mut affine = [scalar::default(); 6]; |
593 | unsafe { self.native().asAffine(affine.as_mut_ptr()) }.if_true_some(affine) |
594 | } |
595 | |
596 | pub fn set_affine(&mut self, affine: &[scalar; 6]) -> &mut Self { |
597 | unsafe { self.native_mut().setAffine(affine.as_ptr()) }; |
598 | self |
599 | } |
600 | |
601 | pub fn from_affine(affine: &[scalar; 6]) -> Matrix { |
602 | let mut m = Matrix::new_identity(); |
603 | unsafe { |
604 | m.native_mut().setAffine(affine.as_ptr()); |
605 | } |
606 | m |
607 | } |
608 | |
609 | pub fn normalize_perspective(&mut self) { |
610 | unsafe { sb::C_SkMatrix_normalizePerspective(self.native_mut()) } |
611 | } |
612 | |
613 | pub fn map_points(&self, dst: &mut [Point], src: &[Point]) { |
614 | assert!(dst.len() >= src.len()); |
615 | |
616 | unsafe { |
617 | self.native().mapPoints( |
618 | dst.native_mut().as_mut_ptr(), |
619 | src.native().as_ptr(), |
620 | src.len().try_into().unwrap(), |
621 | ) |
622 | }; |
623 | } |
624 | |
625 | pub fn map_points_inplace(&self, pts: &mut [Point]) { |
626 | let ptr = pts.native_mut().as_mut_ptr(); |
627 | unsafe { |
628 | self.native() |
629 | .mapPoints(ptr, ptr, pts.len().try_into().unwrap()) |
630 | }; |
631 | } |
632 | |
633 | pub fn map_homogeneous_points(&self, dst: &mut [Point3], src: &[Point3]) { |
634 | assert!(dst.len() >= src.len()); |
635 | |
636 | unsafe { |
637 | self.native().mapHomogeneousPoints( |
638 | dst.native_mut().as_mut_ptr(), |
639 | src.native().as_ptr(), |
640 | src.len().try_into().unwrap(), |
641 | ) |
642 | }; |
643 | } |
644 | |
645 | pub fn map_homogeneous_points_2d(&self, dst: &mut [Point3], src: &[Point]) { |
646 | assert!(dst.len() >= src.len()); |
647 | |
648 | unsafe { |
649 | self.native().mapHomogeneousPoints1( |
650 | dst.native_mut().as_mut_ptr(), |
651 | src.native().as_ptr(), |
652 | src.len().try_into().unwrap(), |
653 | ) |
654 | }; |
655 | } |
656 | |
657 | pub fn map_point(&self, point: impl Into<Point>) -> Point { |
658 | let point = point.into(); |
659 | let mut p = Point::default(); |
660 | unsafe { self.native().mapXY(point.x, point.y, p.native_mut()) }; |
661 | p |
662 | } |
663 | |
664 | pub fn map_xy(&self, x: scalar, y: scalar) -> Point { |
665 | self.map_point((x, y)) |
666 | } |
667 | |
668 | pub fn map_origin(&self) -> Point { |
669 | let mut x = self.translate_x(); |
670 | let mut y = self.translate_y(); |
671 | if self.has_perspective() { |
672 | let mut w = self[Member::Persp2]; |
673 | if w != 0.0 { |
674 | w = 1.0 / w; |
675 | } |
676 | x *= w; |
677 | y *= w; |
678 | } |
679 | Point::new(x, y) |
680 | } |
681 | |
682 | pub fn map_vectors(&self, dst: &mut [Vector], src: &[Vector]) { |
683 | assert!(dst.len() >= src.len()); |
684 | unsafe { |
685 | self.native().mapVectors( |
686 | dst.native_mut().as_mut_ptr(), |
687 | src.native().as_ptr(), |
688 | src.len().try_into().unwrap(), |
689 | ) |
690 | } |
691 | } |
692 | |
693 | pub fn map_vectors_inplace(&self, vecs: &mut [Vector]) { |
694 | let ptr = vecs.native_mut().as_mut_ptr(); |
695 | unsafe { |
696 | self.native() |
697 | .mapVectors(ptr, ptr, vecs.len().try_into().unwrap()) |
698 | } |
699 | } |
700 | |
701 | pub fn map_vector(&self, vec: impl Into<Vector>) -> Vector { |
702 | let mut vec = vec.into(); |
703 | self.map_vectors_inplace(slice::from_mut(&mut vec)); |
704 | vec |
705 | } |
706 | |
707 | pub fn map_rect(&self, rect: impl AsRef<Rect>) -> (Rect, bool) { |
708 | self.map_rect_with_perspective_clip(rect, ApplyPerspectiveClip::Yes) |
709 | } |
710 | |
711 | pub fn map_rect_with_perspective_clip( |
712 | &self, |
713 | rect: impl AsRef<Rect>, |
714 | perspective_clip: ApplyPerspectiveClip, |
715 | ) -> (Rect, bool) { |
716 | let mut rect = *rect.as_ref(); |
717 | let ptr = rect.native_mut(); |
718 | let rect_stays_rect = unsafe { self.native().mapRect(ptr, ptr, perspective_clip) }; |
719 | (rect, rect_stays_rect) |
720 | } |
721 | |
722 | pub fn map_rect_to_quad(&self, rect: impl AsRef<Rect>) -> [Point; 4] { |
723 | let mut quad = rect.as_ref().to_quad(); |
724 | self.map_points_inplace(quad.as_mut()); |
725 | quad |
726 | } |
727 | |
728 | pub fn map_rect_scale_translate(&self, src: impl AsRef<Rect>) -> Option<Rect> { |
729 | if self.is_scale_translate() { |
730 | let mut rect = Rect::default(); |
731 | unsafe { |
732 | self.native() |
733 | .mapRectScaleTranslate(rect.native_mut(), src.as_ref().native()) |
734 | }; |
735 | Some(rect) |
736 | } else { |
737 | None |
738 | } |
739 | } |
740 | |
741 | pub fn map_radius(&self, radius: scalar) -> Option<scalar> { |
742 | if !self.has_perspective() { |
743 | Some(unsafe { self.native().mapRadius(radius) }) |
744 | } else { |
745 | None |
746 | } |
747 | } |
748 | |
749 | #[deprecated (since = "0.27.0" , note = "removed without replacement" )] |
750 | pub fn is_fixed_step_in_x(&self) -> ! { |
751 | unimplemented!("removed without replacement" ) |
752 | } |
753 | |
754 | #[deprecated (since = "0.27.0" , note = "removed without replacement" )] |
755 | pub fn fixed_step_in_x(&self, _y: scalar) -> ! { |
756 | unimplemented!("removed without replacement" ) |
757 | } |
758 | |
759 | #[deprecated (since = "0.27.0" , note = "removed without replacement" )] |
760 | pub fn cheap_equal_to(&self, _other: &Matrix) -> ! { |
761 | unimplemented!("removed without replacement" ) |
762 | } |
763 | |
764 | pub fn dump(&self) { |
765 | unsafe { self.native().dump() } |
766 | } |
767 | |
768 | pub fn min_scale(&self) -> scalar { |
769 | unsafe { self.native().getMinScale() } |
770 | } |
771 | |
772 | pub fn max_scale(&self) -> scalar { |
773 | unsafe { self.native().getMaxScale() } |
774 | } |
775 | |
776 | #[must_use ] |
777 | pub fn min_max_scales(&self) -> (scalar, scalar) { |
778 | let mut r: [scalar; 2] = Default::default(); |
779 | unsafe { self.native().getMinMaxScales(r.as_mut_ptr()) }; |
780 | #[allow (clippy::tuple_array_conversions)] |
781 | (r[0], r[1]) |
782 | } |
783 | |
784 | pub fn decompose_scale(&self, mut remaining: Option<&mut Matrix>) -> Option<Size> { |
785 | let mut size = Size::default(); |
786 | unsafe { |
787 | self.native() |
788 | .decomposeScale(size.native_mut(), remaining.native_ptr_or_null_mut()) |
789 | } |
790 | .if_true_some(size) |
791 | } |
792 | |
793 | pub fn i() -> &'static Matrix { |
794 | &IDENTITY |
795 | } |
796 | |
797 | pub fn invalid_matrix() -> &'static Matrix { |
798 | Self::from_native_ref(unsafe { &*sb::C_SkMatrix_InvalidMatrix() }) |
799 | } |
800 | |
801 | pub fn concat(a: &Matrix, b: &Matrix) -> Matrix { |
802 | let mut m = Matrix::new_identity(); |
803 | unsafe { m.native_mut().setConcat(a.native(), b.native()) }; |
804 | m |
805 | } |
806 | |
807 | pub fn dirty_matrix_type_cache(&mut self) { |
808 | self.native_mut().fTypeMask = 0x80; |
809 | } |
810 | |
811 | pub fn set_scale_translate( |
812 | &mut self, |
813 | (sx, sy): (scalar, scalar), |
814 | t: impl Into<Vector>, |
815 | ) -> &mut Self { |
816 | let t = t.into(); |
817 | unsafe { sb::C_SkMatrix_setScaleTranslate(self.native_mut(), sx, sy, t.x, t.y) } |
818 | self |
819 | } |
820 | |
821 | pub fn is_finite(&self) -> bool { |
822 | unsafe { sb::C_SkMatrix_isFinite(self.native()) } |
823 | } |
824 | |
825 | pub const fn new_identity() -> Self { |
826 | Self::new() |
827 | } |
828 | } |
829 | |
830 | impl IndexGet for Matrix {} |
831 | impl IndexSet for Matrix {} |
832 | |
833 | pub const IDENTITY: Matrix = Matrix::new_identity(); |
834 | |
835 | #[cfg (test)] |
836 | mod tests { |
837 | use super::{AffineMember, Matrix, TypeMask}; |
838 | use crate::prelude::*; |
839 | |
840 | #[test ] |
841 | fn test_get_set_trait_compilation() { |
842 | let mut m = Matrix::new_identity(); |
843 | let _x = m.get(AffineMember::ScaleX); |
844 | m.set(AffineMember::ScaleX, 1.0); |
845 | } |
846 | |
847 | #[test ] |
848 | #[allow (clippy::float_cmp)] |
849 | fn test_tuple_to_vector() { |
850 | let mut m = Matrix::new_identity(); |
851 | m.set_translate((10.0, 11.0)); |
852 | assert_eq!(10.0, m.translate_x()); |
853 | assert_eq!(11.0, m.translate_y()); |
854 | } |
855 | |
856 | #[test ] |
857 | fn setting_a_matrix_component_recomputes_typemask() { |
858 | let mut m = Matrix::default(); |
859 | assert_eq!(TypeMask::IDENTITY, m.get_type()); |
860 | m.set_persp_x(0.1); |
861 | assert_eq!( |
862 | TypeMask::TRANSLATE | TypeMask::SCALE | TypeMask::AFFINE | TypeMask::PERSPECTIVE, |
863 | m.get_type() |
864 | ); |
865 | } |
866 | } |
867 | |