1/*
2 * Copyright 2006 The Android Open Source Project
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef SkMatrix_DEFINED
9#define SkMatrix_DEFINED
10
11#include "include/core/SkPoint.h"
12#include "include/core/SkRect.h"
13#include "include/core/SkScalar.h"
14#include "include/core/SkTypes.h"
15#include "include/private/base/SkMacros.h"
16#include "include/private/base/SkTo.h"
17
18#include <cstdint>
19#include <cstring>
20
21struct SkPoint3;
22struct SkRSXform;
23struct SkSize;
24
25// Remove when clients are updated to live without this
26#define SK_SUPPORT_LEGACY_MATRIX_RECTTORECT
27
28/**
29 * When we transform points through a matrix containing perspective (the bottom row is something
30 * other than 0,0,1), the bruteforce math can produce confusing results (since we might divide
31 * by 0, or a negative w value). By default, methods that map rects and paths will apply
32 * perspective clipping, but this can be changed by specifying kYes to those methods.
33 */
34enum class SkApplyPerspectiveClip {
35 kNo, //!< Don't pre-clip the geometry before applying the (perspective) matrix
36 kYes, //!< Do pre-clip the geometry before applying the (perspective) matrix
37};
38
39/** \class SkMatrix
40 SkMatrix holds a 3x3 matrix for transforming coordinates. This allows mapping
41 SkPoint and vectors with translation, scaling, skewing, rotation, and
42 perspective.
43
44 SkMatrix elements are in row major order.
45 SkMatrix constexpr default constructs to identity.
46
47 SkMatrix includes a hidden variable that classifies the type of matrix to
48 improve performance. SkMatrix is not thread safe unless getType() is called first.
49
50 example: https://fiddle.skia.org/c/@Matrix_063
51*/
52SK_BEGIN_REQUIRE_DENSE
53class SK_API SkMatrix {
54public:
55
56 /** Creates an identity SkMatrix:
57
58 | 1 0 0 |
59 | 0 1 0 |
60 | 0 0 1 |
61 */
62 constexpr SkMatrix() : SkMatrix(1,0,0, 0,1,0, 0,0,1, kIdentity_Mask | kRectStaysRect_Mask) {}
63
64 /** Sets SkMatrix to scale by (sx, sy). Returned matrix is:
65
66 | sx 0 0 |
67 | 0 sy 0 |
68 | 0 0 1 |
69
70 @param sx horizontal scale factor
71 @param sy vertical scale factor
72 @return SkMatrix with scale
73 */
74 [[nodiscard]] static SkMatrix Scale(SkScalar sx, SkScalar sy) {
75 SkMatrix m;
76 m.setScale(sx, sy);
77 return m;
78 }
79
80 /** Sets SkMatrix to translate by (dx, dy). Returned matrix is:
81
82 | 1 0 dx |
83 | 0 1 dy |
84 | 0 0 1 |
85
86 @param dx horizontal translation
87 @param dy vertical translation
88 @return SkMatrix with translation
89 */
90 [[nodiscard]] static SkMatrix Translate(SkScalar dx, SkScalar dy) {
91 SkMatrix m;
92 m.setTranslate(dx, dy);
93 return m;
94 }
95 [[nodiscard]] static SkMatrix Translate(SkVector t) { return Translate(dx: t.x(), dy: t.y()); }
96 [[nodiscard]] static SkMatrix Translate(SkIVector t) { return Translate(dx: t.x(), dy: t.y()); }
97
98 /** Sets SkMatrix to rotate by |deg| about a pivot point at (0, 0).
99
100 @param deg rotation angle in degrees (positive rotates clockwise)
101 @return SkMatrix with rotation
102 */
103 [[nodiscard]] static SkMatrix RotateDeg(SkScalar deg) {
104 SkMatrix m;
105 m.setRotate(deg);
106 return m;
107 }
108 [[nodiscard]] static SkMatrix RotateDeg(SkScalar deg, SkPoint pt) {
109 SkMatrix m;
110 m.setRotate(degrees: deg, px: pt.x(), py: pt.y());
111 return m;
112 }
113 [[nodiscard]] static SkMatrix RotateRad(SkScalar rad) {
114 return RotateDeg(SkRadiansToDegrees(rad));
115 }
116
117 /** Sets SkMatrix to skew by (kx, ky) about pivot point (0, 0).
118
119 @param kx horizontal skew factor
120 @param ky vertical skew factor
121 @return SkMatrix with skew
122 */
123 [[nodiscard]] static SkMatrix Skew(SkScalar kx, SkScalar ky) {
124 SkMatrix m;
125 m.setSkew(kx, ky);
126 return m;
127 }
128
129 /** \enum SkMatrix::ScaleToFit
130 ScaleToFit describes how SkMatrix is constructed to map one SkRect to another.
131 ScaleToFit may allow SkMatrix to have unequal horizontal and vertical scaling,
132 or may restrict SkMatrix to square scaling. If restricted, ScaleToFit specifies
133 how SkMatrix maps to the side or center of the destination SkRect.
134 */
135 enum ScaleToFit {
136 kFill_ScaleToFit, //!< scales in x and y to fill destination SkRect
137 kStart_ScaleToFit, //!< scales and aligns to left and top
138 kCenter_ScaleToFit, //!< scales and aligns to center
139 kEnd_ScaleToFit, //!< scales and aligns to right and bottom
140 };
141
142 /** Returns SkMatrix set to scale and translate src to dst. ScaleToFit selects
143 whether mapping completely fills dst or preserves the aspect ratio, and how to
144 align src within dst. Returns the identity SkMatrix if src is empty. If dst is
145 empty, returns SkMatrix set to:
146
147 | 0 0 0 |
148 | 0 0 0 |
149 | 0 0 1 |
150
151 @param src SkRect to map from
152 @param dst SkRect to map to
153 @param mode How to handle the mapping
154 @return SkMatrix mapping src to dst
155 */
156 [[nodiscard]] static SkMatrix RectToRect(const SkRect& src, const SkRect& dst,
157 ScaleToFit mode = kFill_ScaleToFit) {
158 return MakeRectToRect(src, dst, stf: mode);
159 }
160
161 /** Sets SkMatrix to:
162
163 | scaleX skewX transX |
164 | skewY scaleY transY |
165 | pers0 pers1 pers2 |
166
167 @param scaleX horizontal scale factor
168 @param skewX horizontal skew factor
169 @param transX horizontal translation
170 @param skewY vertical skew factor
171 @param scaleY vertical scale factor
172 @param transY vertical translation
173 @param pers0 input x-axis perspective factor
174 @param pers1 input y-axis perspective factor
175 @param pers2 perspective scale factor
176 @return SkMatrix constructed from parameters
177 */
178 [[nodiscard]] static SkMatrix MakeAll(SkScalar scaleX, SkScalar skewX, SkScalar transX,
179 SkScalar skewY, SkScalar scaleY, SkScalar transY,
180 SkScalar pers0, SkScalar pers1, SkScalar pers2) {
181 SkMatrix m;
182 m.setAll(scaleX, skewX, transX, skewY, scaleY, transY, persp0: pers0, persp1: pers1, persp2: pers2);
183 return m;
184 }
185
186 /** \enum SkMatrix::TypeMask
187 Enum of bit fields for mask returned by getType().
188 Used to identify the complexity of SkMatrix, to optimize performance.
189 */
190 enum TypeMask {
191 kIdentity_Mask = 0, //!< identity SkMatrix; all bits clear
192 kTranslate_Mask = 0x01, //!< translation SkMatrix
193 kScale_Mask = 0x02, //!< scale SkMatrix
194 kAffine_Mask = 0x04, //!< skew or rotate SkMatrix
195 kPerspective_Mask = 0x08, //!< perspective SkMatrix
196 };
197
198 /** Returns a bit field describing the transformations the matrix may
199 perform. The bit field is computed conservatively, so it may include
200 false positives. For example, when kPerspective_Mask is set, all
201 other bits are set.
202
203 @return kIdentity_Mask, or combinations of: kTranslate_Mask, kScale_Mask,
204 kAffine_Mask, kPerspective_Mask
205 */
206 TypeMask getType() const {
207 if (fTypeMask & kUnknown_Mask) {
208 fTypeMask = this->computeTypeMask();
209 }
210 // only return the public masks
211 return (TypeMask)(fTypeMask & 0xF);
212 }
213
214 /** Returns true if SkMatrix is identity. Identity matrix is:
215
216 | 1 0 0 |
217 | 0 1 0 |
218 | 0 0 1 |
219
220 @return true if SkMatrix has no effect
221 */
222 bool isIdentity() const {
223 return this->getType() == 0;
224 }
225
226 /** Returns true if SkMatrix at most scales and translates. SkMatrix may be identity,
227 contain only scale elements, only translate elements, or both. SkMatrix form is:
228
229 | scale-x 0 translate-x |
230 | 0 scale-y translate-y |
231 | 0 0 1 |
232
233 @return true if SkMatrix is identity; or scales, translates, or both
234 */
235 bool isScaleTranslate() const {
236 return !(this->getType() & ~(kScale_Mask | kTranslate_Mask));
237 }
238
239 /** Returns true if SkMatrix is identity, or translates. SkMatrix form is:
240
241 | 1 0 translate-x |
242 | 0 1 translate-y |
243 | 0 0 1 |
244
245 @return true if SkMatrix is identity, or translates
246 */
247 bool isTranslate() const { return !(this->getType() & ~(kTranslate_Mask)); }
248
249 /** Returns true SkMatrix maps SkRect to another SkRect. If true, SkMatrix is identity,
250 or scales, or rotates a multiple of 90 degrees, or mirrors on axes. In all
251 cases, SkMatrix may also have translation. SkMatrix form is either:
252
253 | scale-x 0 translate-x |
254 | 0 scale-y translate-y |
255 | 0 0 1 |
256
257 or
258
259 | 0 rotate-x translate-x |
260 | rotate-y 0 translate-y |
261 | 0 0 1 |
262
263 for non-zero values of scale-x, scale-y, rotate-x, and rotate-y.
264
265 Also called preservesAxisAlignment(); use the one that provides better inline
266 documentation.
267
268 @return true if SkMatrix maps one SkRect into another
269 */
270 bool rectStaysRect() const {
271 if (fTypeMask & kUnknown_Mask) {
272 fTypeMask = this->computeTypeMask();
273 }
274 return (fTypeMask & kRectStaysRect_Mask) != 0;
275 }
276
277 /** Returns true SkMatrix maps SkRect to another SkRect. If true, SkMatrix is identity,
278 or scales, or rotates a multiple of 90 degrees, or mirrors on axes. In all
279 cases, SkMatrix may also have translation. SkMatrix form is either:
280
281 | scale-x 0 translate-x |
282 | 0 scale-y translate-y |
283 | 0 0 1 |
284
285 or
286
287 | 0 rotate-x translate-x |
288 | rotate-y 0 translate-y |
289 | 0 0 1 |
290
291 for non-zero values of scale-x, scale-y, rotate-x, and rotate-y.
292
293 Also called rectStaysRect(); use the one that provides better inline
294 documentation.
295
296 @return true if SkMatrix maps one SkRect into another
297 */
298 bool preservesAxisAlignment() const { return this->rectStaysRect(); }
299
300 /** Returns true if the matrix contains perspective elements. SkMatrix form is:
301
302 | -- -- -- |
303 | -- -- -- |
304 | perspective-x perspective-y perspective-scale |
305
306 where perspective-x or perspective-y is non-zero, or perspective-scale is
307 not one. All other elements may have any value.
308
309 @return true if SkMatrix is in most general form
310 */
311 bool hasPerspective() const {
312 return SkToBool(x: this->getPerspectiveTypeMaskOnly() &
313 kPerspective_Mask);
314 }
315
316 /** Returns true if SkMatrix contains only translation, rotation, reflection, and
317 uniform scale.
318 Returns false if SkMatrix contains different scales, skewing, perspective, or
319 degenerate forms that collapse to a line or point.
320
321 Describes that the SkMatrix makes rendering with and without the matrix are
322 visually alike; a transformed circle remains a circle. Mathematically, this is
323 referred to as similarity of a Euclidean space, or a similarity transformation.
324
325 Preserves right angles, keeping the arms of the angle equal lengths.
326
327 @param tol to be deprecated
328 @return true if SkMatrix only rotates, uniformly scales, translates
329
330 example: https://fiddle.skia.org/c/@Matrix_isSimilarity
331 */
332 bool isSimilarity(SkScalar tol = SK_ScalarNearlyZero) const;
333
334 /** Returns true if SkMatrix contains only translation, rotation, reflection, and
335 scale. Scale may differ along rotated axes.
336 Returns false if SkMatrix skewing, perspective, or degenerate forms that collapse
337 to a line or point.
338
339 Preserves right angles, but not requiring that the arms of the angle
340 retain equal lengths.
341
342 @param tol to be deprecated
343 @return true if SkMatrix only rotates, scales, translates
344
345 example: https://fiddle.skia.org/c/@Matrix_preservesRightAngles
346 */
347 bool preservesRightAngles(SkScalar tol = SK_ScalarNearlyZero) const;
348
349 /** SkMatrix organizes its values in row-major order. These members correspond to
350 each value in SkMatrix.
351 */
352 static constexpr int kMScaleX = 0; //!< horizontal scale factor
353 static constexpr int kMSkewX = 1; //!< horizontal skew factor
354 static constexpr int kMTransX = 2; //!< horizontal translation
355 static constexpr int kMSkewY = 3; //!< vertical skew factor
356 static constexpr int kMScaleY = 4; //!< vertical scale factor
357 static constexpr int kMTransY = 5; //!< vertical translation
358 static constexpr int kMPersp0 = 6; //!< input x perspective factor
359 static constexpr int kMPersp1 = 7; //!< input y perspective factor
360 static constexpr int kMPersp2 = 8; //!< perspective bias
361
362 /** Affine arrays are in column-major order to match the matrix used by
363 PDF and XPS.
364 */
365 static constexpr int kAScaleX = 0; //!< horizontal scale factor
366 static constexpr int kASkewY = 1; //!< vertical skew factor
367 static constexpr int kASkewX = 2; //!< horizontal skew factor
368 static constexpr int kAScaleY = 3; //!< vertical scale factor
369 static constexpr int kATransX = 4; //!< horizontal translation
370 static constexpr int kATransY = 5; //!< vertical translation
371
372 /** Returns one matrix value. Asserts if index is out of range and SK_DEBUG is
373 defined.
374
375 @param index one of: kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY,
376 kMPersp0, kMPersp1, kMPersp2
377 @return value corresponding to index
378 */
379 SkScalar operator[](int index) const {
380 SkASSERT((unsigned)index < 9);
381 return fMat[index];
382 }
383
384 /** Returns one matrix value. Asserts if index is out of range and SK_DEBUG is
385 defined.
386
387 @param index one of: kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY,
388 kMPersp0, kMPersp1, kMPersp2
389 @return value corresponding to index
390 */
391 SkScalar get(int index) const {
392 SkASSERT((unsigned)index < 9);
393 return fMat[index];
394 }
395
396 /** Returns one matrix value from a particular row/column. Asserts if index is out
397 of range and SK_DEBUG is defined.
398
399 @param r matrix row to fetch
400 @param c matrix column to fetch
401 @return value at the given matrix position
402 */
403 SkScalar rc(int r, int c) const {
404 SkASSERT(r >= 0 && r <= 2);
405 SkASSERT(c >= 0 && c <= 2);
406 return fMat[r*3 + c];
407 }
408
409 /** Returns scale factor multiplied by x-axis input, contributing to x-axis output.
410 With mapPoints(), scales SkPoint along the x-axis.
411
412 @return horizontal scale factor
413 */
414 SkScalar getScaleX() const { return fMat[kMScaleX]; }
415
416 /** Returns scale factor multiplied by y-axis input, contributing to y-axis output.
417 With mapPoints(), scales SkPoint along the y-axis.
418
419 @return vertical scale factor
420 */
421 SkScalar getScaleY() const { return fMat[kMScaleY]; }
422
423 /** Returns scale factor multiplied by x-axis input, contributing to y-axis output.
424 With mapPoints(), skews SkPoint along the y-axis.
425 Skewing both axes can rotate SkPoint.
426
427 @return vertical skew factor
428 */
429 SkScalar getSkewY() const { return fMat[kMSkewY]; }
430
431 /** Returns scale factor multiplied by y-axis input, contributing to x-axis output.
432 With mapPoints(), skews SkPoint along the x-axis.
433 Skewing both axes can rotate SkPoint.
434
435 @return horizontal scale factor
436 */
437 SkScalar getSkewX() const { return fMat[kMSkewX]; }
438
439 /** Returns translation contributing to x-axis output.
440 With mapPoints(), moves SkPoint along the x-axis.
441
442 @return horizontal translation factor
443 */
444 SkScalar getTranslateX() const { return fMat[kMTransX]; }
445
446 /** Returns translation contributing to y-axis output.
447 With mapPoints(), moves SkPoint along the y-axis.
448
449 @return vertical translation factor
450 */
451 SkScalar getTranslateY() const { return fMat[kMTransY]; }
452
453 /** Returns factor scaling input x-axis relative to input y-axis.
454
455 @return input x-axis perspective factor
456 */
457 SkScalar getPerspX() const { return fMat[kMPersp0]; }
458
459 /** Returns factor scaling input y-axis relative to input x-axis.
460
461 @return input y-axis perspective factor
462 */
463 SkScalar getPerspY() const { return fMat[kMPersp1]; }
464
465 /** Returns writable SkMatrix value. Asserts if index is out of range and SK_DEBUG is
466 defined. Clears internal cache anticipating that caller will change SkMatrix value.
467
468 Next call to read SkMatrix state may recompute cache; subsequent writes to SkMatrix
469 value must be followed by dirtyMatrixTypeCache().
470
471 @param index one of: kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY,
472 kMPersp0, kMPersp1, kMPersp2
473 @return writable value corresponding to index
474 */
475 SkScalar& operator[](int index) {
476 SkASSERT((unsigned)index < 9);
477 this->setTypeMask(kUnknown_Mask);
478 return fMat[index];
479 }
480
481 /** Sets SkMatrix value. Asserts if index is out of range and SK_DEBUG is
482 defined. Safer than operator[]; internal cache is always maintained.
483
484 @param index one of: kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY,
485 kMPersp0, kMPersp1, kMPersp2
486 @param value scalar to store in SkMatrix
487 */
488 SkMatrix& set(int index, SkScalar value) {
489 SkASSERT((unsigned)index < 9);
490 fMat[index] = value;
491 this->setTypeMask(kUnknown_Mask);
492 return *this;
493 }
494
495 /** Sets horizontal scale factor.
496
497 @param v horizontal scale factor to store
498 */
499 SkMatrix& setScaleX(SkScalar v) { return this->set(index: kMScaleX, value: v); }
500
501 /** Sets vertical scale factor.
502
503 @param v vertical scale factor to store
504 */
505 SkMatrix& setScaleY(SkScalar v) { return this->set(index: kMScaleY, value: v); }
506
507 /** Sets vertical skew factor.
508
509 @param v vertical skew factor to store
510 */
511 SkMatrix& setSkewY(SkScalar v) { return this->set(index: kMSkewY, value: v); }
512
513 /** Sets horizontal skew factor.
514
515 @param v horizontal skew factor to store
516 */
517 SkMatrix& setSkewX(SkScalar v) { return this->set(index: kMSkewX, value: v); }
518
519 /** Sets horizontal translation.
520
521 @param v horizontal translation to store
522 */
523 SkMatrix& setTranslateX(SkScalar v) { return this->set(index: kMTransX, value: v); }
524
525 /** Sets vertical translation.
526
527 @param v vertical translation to store
528 */
529 SkMatrix& setTranslateY(SkScalar v) { return this->set(index: kMTransY, value: v); }
530
531 /** Sets input x-axis perspective factor, which causes mapXY() to vary input x-axis values
532 inversely proportional to input y-axis values.
533
534 @param v perspective factor
535 */
536 SkMatrix& setPerspX(SkScalar v) { return this->set(index: kMPersp0, value: v); }
537
538 /** Sets input y-axis perspective factor, which causes mapXY() to vary input y-axis values
539 inversely proportional to input x-axis values.
540
541 @param v perspective factor
542 */
543 SkMatrix& setPerspY(SkScalar v) { return this->set(index: kMPersp1, value: v); }
544
545 /** Sets all values from parameters. Sets matrix to:
546
547 | scaleX skewX transX |
548 | skewY scaleY transY |
549 | persp0 persp1 persp2 |
550
551 @param scaleX horizontal scale factor to store
552 @param skewX horizontal skew factor to store
553 @param transX horizontal translation to store
554 @param skewY vertical skew factor to store
555 @param scaleY vertical scale factor to store
556 @param transY vertical translation to store
557 @param persp0 input x-axis values perspective factor to store
558 @param persp1 input y-axis values perspective factor to store
559 @param persp2 perspective scale factor to store
560 */
561 SkMatrix& setAll(SkScalar scaleX, SkScalar skewX, SkScalar transX,
562 SkScalar skewY, SkScalar scaleY, SkScalar transY,
563 SkScalar persp0, SkScalar persp1, SkScalar persp2) {
564 fMat[kMScaleX] = scaleX;
565 fMat[kMSkewX] = skewX;
566 fMat[kMTransX] = transX;
567 fMat[kMSkewY] = skewY;
568 fMat[kMScaleY] = scaleY;
569 fMat[kMTransY] = transY;
570 fMat[kMPersp0] = persp0;
571 fMat[kMPersp1] = persp1;
572 fMat[kMPersp2] = persp2;
573 this->setTypeMask(kUnknown_Mask);
574 return *this;
575 }
576
577 /** Copies nine scalar values contained by SkMatrix into buffer, in member value
578 ascending order: kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY,
579 kMPersp0, kMPersp1, kMPersp2.
580
581 @param buffer storage for nine scalar values
582 */
583 void get9(SkScalar buffer[9]) const {
584 memcpy(dest: buffer, src: fMat, n: 9 * sizeof(SkScalar));
585 }
586
587 /** Sets SkMatrix to nine scalar values in buffer, in member value ascending order:
588 kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY, kMPersp0, kMPersp1,
589 kMPersp2.
590
591 Sets matrix to:
592
593 | buffer[0] buffer[1] buffer[2] |
594 | buffer[3] buffer[4] buffer[5] |
595 | buffer[6] buffer[7] buffer[8] |
596
597 In the future, set9 followed by get9 may not return the same values. Since SkMatrix
598 maps non-homogeneous coordinates, scaling all nine values produces an equivalent
599 transformation, possibly improving precision.
600
601 @param buffer nine scalar values
602 */
603 SkMatrix& set9(const SkScalar buffer[9]);
604
605 /** Sets SkMatrix to identity; which has no effect on mapped SkPoint. Sets SkMatrix to:
606
607 | 1 0 0 |
608 | 0 1 0 |
609 | 0 0 1 |
610
611 Also called setIdentity(); use the one that provides better inline
612 documentation.
613 */
614 SkMatrix& reset();
615
616 /** Sets SkMatrix to identity; which has no effect on mapped SkPoint. Sets SkMatrix to:
617
618 | 1 0 0 |
619 | 0 1 0 |
620 | 0 0 1 |
621
622 Also called reset(); use the one that provides better inline
623 documentation.
624 */
625 SkMatrix& setIdentity() { return this->reset(); }
626
627 /** Sets SkMatrix to translate by (dx, dy).
628
629 @param dx horizontal translation
630 @param dy vertical translation
631 */
632 SkMatrix& setTranslate(SkScalar dx, SkScalar dy);
633
634 /** Sets SkMatrix to translate by (v.fX, v.fY).
635
636 @param v vector containing horizontal and vertical translation
637 */
638 SkMatrix& setTranslate(const SkVector& v) { return this->setTranslate(dx: v.fX, dy: v.fY); }
639
640 /** Sets SkMatrix to scale by sx and sy, about a pivot point at (px, py).
641 The pivot point is unchanged when mapped with SkMatrix.
642
643 @param sx horizontal scale factor
644 @param sy vertical scale factor
645 @param px pivot on x-axis
646 @param py pivot on y-axis
647 */
648 SkMatrix& setScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py);
649
650 /** Sets SkMatrix to scale by sx and sy about at pivot point at (0, 0).
651
652 @param sx horizontal scale factor
653 @param sy vertical scale factor
654 */
655 SkMatrix& setScale(SkScalar sx, SkScalar sy);
656
657 /** Sets SkMatrix to rotate by degrees about a pivot point at (px, py).
658 The pivot point is unchanged when mapped with SkMatrix.
659
660 Positive degrees rotates clockwise.
661
662 @param degrees angle of axes relative to upright axes
663 @param px pivot on x-axis
664 @param py pivot on y-axis
665 */
666 SkMatrix& setRotate(SkScalar degrees, SkScalar px, SkScalar py);
667
668 /** Sets SkMatrix to rotate by degrees about a pivot point at (0, 0).
669 Positive degrees rotates clockwise.
670
671 @param degrees angle of axes relative to upright axes
672 */
673 SkMatrix& setRotate(SkScalar degrees);
674
675 /** Sets SkMatrix to rotate by sinValue and cosValue, about a pivot point at (px, py).
676 The pivot point is unchanged when mapped with SkMatrix.
677
678 Vector (sinValue, cosValue) describes the angle of rotation relative to (0, 1).
679 Vector length specifies scale.
680
681 @param sinValue rotation vector x-axis component
682 @param cosValue rotation vector y-axis component
683 @param px pivot on x-axis
684 @param py pivot on y-axis
685 */
686 SkMatrix& setSinCos(SkScalar sinValue, SkScalar cosValue,
687 SkScalar px, SkScalar py);
688
689 /** Sets SkMatrix to rotate by sinValue and cosValue, about a pivot point at (0, 0).
690
691 Vector (sinValue, cosValue) describes the angle of rotation relative to (0, 1).
692 Vector length specifies scale.
693
694 @param sinValue rotation vector x-axis component
695 @param cosValue rotation vector y-axis component
696 */
697 SkMatrix& setSinCos(SkScalar sinValue, SkScalar cosValue);
698
699 /** Sets SkMatrix to rotate, scale, and translate using a compressed matrix form.
700
701 Vector (rsxForm.fSSin, rsxForm.fSCos) describes the angle of rotation relative
702 to (0, 1). Vector length specifies scale. Mapped point is rotated and scaled
703 by vector, then translated by (rsxForm.fTx, rsxForm.fTy).
704
705 @param rsxForm compressed SkRSXform matrix
706 @return reference to SkMatrix
707
708 example: https://fiddle.skia.org/c/@Matrix_setRSXform
709 */
710 SkMatrix& setRSXform(const SkRSXform& rsxForm);
711
712 /** Sets SkMatrix to skew by kx and ky, about a pivot point at (px, py).
713 The pivot point is unchanged when mapped with SkMatrix.
714
715 @param kx horizontal skew factor
716 @param ky vertical skew factor
717 @param px pivot on x-axis
718 @param py pivot on y-axis
719 */
720 SkMatrix& setSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py);
721
722 /** Sets SkMatrix to skew by kx and ky, about a pivot point at (0, 0).
723
724 @param kx horizontal skew factor
725 @param ky vertical skew factor
726 */
727 SkMatrix& setSkew(SkScalar kx, SkScalar ky);
728
729 /** Sets SkMatrix to SkMatrix a multiplied by SkMatrix b. Either a or b may be this.
730
731 Given:
732
733 | A B C | | J K L |
734 a = | D E F |, b = | M N O |
735 | G H I | | P Q R |
736
737 sets SkMatrix to:
738
739 | A B C | | J K L | | AJ+BM+CP AK+BN+CQ AL+BO+CR |
740 a * b = | D E F | * | M N O | = | DJ+EM+FP DK+EN+FQ DL+EO+FR |
741 | G H I | | P Q R | | GJ+HM+IP GK+HN+IQ GL+HO+IR |
742
743 @param a SkMatrix on left side of multiply expression
744 @param b SkMatrix on right side of multiply expression
745 */
746 SkMatrix& setConcat(const SkMatrix& a, const SkMatrix& b);
747
748 /** Sets SkMatrix to SkMatrix multiplied by SkMatrix constructed from translation (dx, dy).
749 This can be thought of as moving the point to be mapped before applying SkMatrix.
750
751 Given:
752
753 | A B C | | 1 0 dx |
754 Matrix = | D E F |, T(dx, dy) = | 0 1 dy |
755 | G H I | | 0 0 1 |
756
757 sets SkMatrix to:
758
759 | A B C | | 1 0 dx | | A B A*dx+B*dy+C |
760 Matrix * T(dx, dy) = | D E F | | 0 1 dy | = | D E D*dx+E*dy+F |
761 | G H I | | 0 0 1 | | G H G*dx+H*dy+I |
762
763 @param dx x-axis translation before applying SkMatrix
764 @param dy y-axis translation before applying SkMatrix
765 */
766 SkMatrix& preTranslate(SkScalar dx, SkScalar dy);
767
768 /** Sets SkMatrix to SkMatrix multiplied by SkMatrix constructed from scaling by (sx, sy)
769 about pivot point (px, py).
770 This can be thought of as scaling about a pivot point before applying SkMatrix.
771
772 Given:
773
774 | A B C | | sx 0 dx |
775 Matrix = | D E F |, S(sx, sy, px, py) = | 0 sy dy |
776 | G H I | | 0 0 1 |
777
778 where
779
780 dx = px - sx * px
781 dy = py - sy * py
782
783 sets SkMatrix to:
784
785 | A B C | | sx 0 dx | | A*sx B*sy A*dx+B*dy+C |
786 Matrix * S(sx, sy, px, py) = | D E F | | 0 sy dy | = | D*sx E*sy D*dx+E*dy+F |
787 | G H I | | 0 0 1 | | G*sx H*sy G*dx+H*dy+I |
788
789 @param sx horizontal scale factor
790 @param sy vertical scale factor
791 @param px pivot on x-axis
792 @param py pivot on y-axis
793 */
794 SkMatrix& preScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py);
795
796 /** Sets SkMatrix to SkMatrix multiplied by SkMatrix constructed from scaling by (sx, sy)
797 about pivot point (0, 0).
798 This can be thought of as scaling about the origin before applying SkMatrix.
799
800 Given:
801
802 | A B C | | sx 0 0 |
803 Matrix = | D E F |, S(sx, sy) = | 0 sy 0 |
804 | G H I | | 0 0 1 |
805
806 sets SkMatrix to:
807
808 | A B C | | sx 0 0 | | A*sx B*sy C |
809 Matrix * S(sx, sy) = | D E F | | 0 sy 0 | = | D*sx E*sy F |
810 | G H I | | 0 0 1 | | G*sx H*sy I |
811
812 @param sx horizontal scale factor
813 @param sy vertical scale factor
814 */
815 SkMatrix& preScale(SkScalar sx, SkScalar sy);
816
817 /** Sets SkMatrix to SkMatrix multiplied by SkMatrix constructed from rotating by degrees
818 about pivot point (px, py).
819 This can be thought of as rotating about a pivot point before applying SkMatrix.
820
821 Positive degrees rotates clockwise.
822
823 Given:
824
825 | A B C | | c -s dx |
826 Matrix = | D E F |, R(degrees, px, py) = | s c dy |
827 | G H I | | 0 0 1 |
828
829 where
830
831 c = cos(degrees)
832 s = sin(degrees)
833 dx = s * py + (1 - c) * px
834 dy = -s * px + (1 - c) * py
835
836 sets SkMatrix to:
837
838 | A B C | | c -s dx | | Ac+Bs -As+Bc A*dx+B*dy+C |
839 Matrix * R(degrees, px, py) = | D E F | | s c dy | = | Dc+Es -Ds+Ec D*dx+E*dy+F |
840 | G H I | | 0 0 1 | | Gc+Hs -Gs+Hc G*dx+H*dy+I |
841
842 @param degrees angle of axes relative to upright axes
843 @param px pivot on x-axis
844 @param py pivot on y-axis
845 */
846 SkMatrix& preRotate(SkScalar degrees, SkScalar px, SkScalar py);
847
848 /** Sets SkMatrix to SkMatrix multiplied by SkMatrix constructed from rotating by degrees
849 about pivot point (0, 0).
850 This can be thought of as rotating about the origin before applying SkMatrix.
851
852 Positive degrees rotates clockwise.
853
854 Given:
855
856 | A B C | | c -s 0 |
857 Matrix = | D E F |, R(degrees, px, py) = | s c 0 |
858 | G H I | | 0 0 1 |
859
860 where
861
862 c = cos(degrees)
863 s = sin(degrees)
864
865 sets SkMatrix to:
866
867 | A B C | | c -s 0 | | Ac+Bs -As+Bc C |
868 Matrix * R(degrees, px, py) = | D E F | | s c 0 | = | Dc+Es -Ds+Ec F |
869 | G H I | | 0 0 1 | | Gc+Hs -Gs+Hc I |
870
871 @param degrees angle of axes relative to upright axes
872 */
873 SkMatrix& preRotate(SkScalar degrees);
874
875 /** Sets SkMatrix to SkMatrix multiplied by SkMatrix constructed from skewing by (kx, ky)
876 about pivot point (px, py).
877 This can be thought of as skewing about a pivot point before applying SkMatrix.
878
879 Given:
880
881 | A B C | | 1 kx dx |
882 Matrix = | D E F |, K(kx, ky, px, py) = | ky 1 dy |
883 | G H I | | 0 0 1 |
884
885 where
886
887 dx = -kx * py
888 dy = -ky * px
889
890 sets SkMatrix to:
891
892 | A B C | | 1 kx dx | | A+B*ky A*kx+B A*dx+B*dy+C |
893 Matrix * K(kx, ky, px, py) = | D E F | | ky 1 dy | = | D+E*ky D*kx+E D*dx+E*dy+F |
894 | G H I | | 0 0 1 | | G+H*ky G*kx+H G*dx+H*dy+I |
895
896 @param kx horizontal skew factor
897 @param ky vertical skew factor
898 @param px pivot on x-axis
899 @param py pivot on y-axis
900 */
901 SkMatrix& preSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py);
902
903 /** Sets SkMatrix to SkMatrix multiplied by SkMatrix constructed from skewing by (kx, ky)
904 about pivot point (0, 0).
905 This can be thought of as skewing about the origin before applying SkMatrix.
906
907 Given:
908
909 | A B C | | 1 kx 0 |
910 Matrix = | D E F |, K(kx, ky) = | ky 1 0 |
911 | G H I | | 0 0 1 |
912
913 sets SkMatrix to:
914
915 | A B C | | 1 kx 0 | | A+B*ky A*kx+B C |
916 Matrix * K(kx, ky) = | D E F | | ky 1 0 | = | D+E*ky D*kx+E F |
917 | G H I | | 0 0 1 | | G+H*ky G*kx+H I |
918
919 @param kx horizontal skew factor
920 @param ky vertical skew factor
921 */
922 SkMatrix& preSkew(SkScalar kx, SkScalar ky);
923
924 /** Sets SkMatrix to SkMatrix multiplied by SkMatrix other.
925 This can be thought of mapping by other before applying SkMatrix.
926
927 Given:
928
929 | A B C | | J K L |
930 Matrix = | D E F |, other = | M N O |
931 | G H I | | P Q R |
932
933 sets SkMatrix to:
934
935 | A B C | | J K L | | AJ+BM+CP AK+BN+CQ AL+BO+CR |
936 Matrix * other = | D E F | * | M N O | = | DJ+EM+FP DK+EN+FQ DL+EO+FR |
937 | G H I | | P Q R | | GJ+HM+IP GK+HN+IQ GL+HO+IR |
938
939 @param other SkMatrix on right side of multiply expression
940 */
941 SkMatrix& preConcat(const SkMatrix& other);
942
943 /** Sets SkMatrix to SkMatrix constructed from translation (dx, dy) multiplied by SkMatrix.
944 This can be thought of as moving the point to be mapped after applying SkMatrix.
945
946 Given:
947
948 | J K L | | 1 0 dx |
949 Matrix = | M N O |, T(dx, dy) = | 0 1 dy |
950 | P Q R | | 0 0 1 |
951
952 sets SkMatrix to:
953
954 | 1 0 dx | | J K L | | J+dx*P K+dx*Q L+dx*R |
955 T(dx, dy) * Matrix = | 0 1 dy | | M N O | = | M+dy*P N+dy*Q O+dy*R |
956 | 0 0 1 | | P Q R | | P Q R |
957
958 @param dx x-axis translation after applying SkMatrix
959 @param dy y-axis translation after applying SkMatrix
960 */
961 SkMatrix& postTranslate(SkScalar dx, SkScalar dy);
962
963 /** Sets SkMatrix to SkMatrix constructed from scaling by (sx, sy) about pivot point
964 (px, py), multiplied by SkMatrix.
965 This can be thought of as scaling about a pivot point after applying SkMatrix.
966
967 Given:
968
969 | J K L | | sx 0 dx |
970 Matrix = | M N O |, S(sx, sy, px, py) = | 0 sy dy |
971 | P Q R | | 0 0 1 |
972
973 where
974
975 dx = px - sx * px
976 dy = py - sy * py
977
978 sets SkMatrix to:
979
980 | sx 0 dx | | J K L | | sx*J+dx*P sx*K+dx*Q sx*L+dx+R |
981 S(sx, sy, px, py) * Matrix = | 0 sy dy | | M N O | = | sy*M+dy*P sy*N+dy*Q sy*O+dy*R |
982 | 0 0 1 | | P Q R | | P Q R |
983
984 @param sx horizontal scale factor
985 @param sy vertical scale factor
986 @param px pivot on x-axis
987 @param py pivot on y-axis
988 */
989 SkMatrix& postScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py);
990
991 /** Sets SkMatrix to SkMatrix constructed from scaling by (sx, sy) about pivot point
992 (0, 0), multiplied by SkMatrix.
993 This can be thought of as scaling about the origin after applying SkMatrix.
994
995 Given:
996
997 | J K L | | sx 0 0 |
998 Matrix = | M N O |, S(sx, sy) = | 0 sy 0 |
999 | P Q R | | 0 0 1 |
1000
1001 sets SkMatrix to:
1002
1003 | sx 0 0 | | J K L | | sx*J sx*K sx*L |
1004 S(sx, sy) * Matrix = | 0 sy 0 | | M N O | = | sy*M sy*N sy*O |
1005 | 0 0 1 | | P Q R | | P Q R |
1006
1007 @param sx horizontal scale factor
1008 @param sy vertical scale factor
1009 */
1010 SkMatrix& postScale(SkScalar sx, SkScalar sy);
1011
1012 /** Sets SkMatrix to SkMatrix constructed from rotating by degrees about pivot point
1013 (px, py), multiplied by SkMatrix.
1014 This can be thought of as rotating about a pivot point after applying SkMatrix.
1015
1016 Positive degrees rotates clockwise.
1017
1018 Given:
1019
1020 | J K L | | c -s dx |
1021 Matrix = | M N O |, R(degrees, px, py) = | s c dy |
1022 | P Q R | | 0 0 1 |
1023
1024 where
1025
1026 c = cos(degrees)
1027 s = sin(degrees)
1028 dx = s * py + (1 - c) * px
1029 dy = -s * px + (1 - c) * py
1030
1031 sets SkMatrix to:
1032
1033 |c -s dx| |J K L| |cJ-sM+dx*P cK-sN+dx*Q cL-sO+dx+R|
1034 R(degrees, px, py) * Matrix = |s c dy| |M N O| = |sJ+cM+dy*P sK+cN+dy*Q sL+cO+dy*R|
1035 |0 0 1| |P Q R| | P Q R|
1036
1037 @param degrees angle of axes relative to upright axes
1038 @param px pivot on x-axis
1039 @param py pivot on y-axis
1040 */
1041 SkMatrix& postRotate(SkScalar degrees, SkScalar px, SkScalar py);
1042
1043 /** Sets SkMatrix to SkMatrix constructed from rotating by degrees about pivot point
1044 (0, 0), multiplied by SkMatrix.
1045 This can be thought of as rotating about the origin after applying SkMatrix.
1046
1047 Positive degrees rotates clockwise.
1048
1049 Given:
1050
1051 | J K L | | c -s 0 |
1052 Matrix = | M N O |, R(degrees, px, py) = | s c 0 |
1053 | P Q R | | 0 0 1 |
1054
1055 where
1056
1057 c = cos(degrees)
1058 s = sin(degrees)
1059
1060 sets SkMatrix to:
1061
1062 | c -s dx | | J K L | | cJ-sM cK-sN cL-sO |
1063 R(degrees, px, py) * Matrix = | s c dy | | M N O | = | sJ+cM sK+cN sL+cO |
1064 | 0 0 1 | | P Q R | | P Q R |
1065
1066 @param degrees angle of axes relative to upright axes
1067 */
1068 SkMatrix& postRotate(SkScalar degrees);
1069
1070 /** Sets SkMatrix to SkMatrix constructed from skewing by (kx, ky) about pivot point
1071 (px, py), multiplied by SkMatrix.
1072 This can be thought of as skewing about a pivot point after applying SkMatrix.
1073
1074 Given:
1075
1076 | J K L | | 1 kx dx |
1077 Matrix = | M N O |, K(kx, ky, px, py) = | ky 1 dy |
1078 | P Q R | | 0 0 1 |
1079
1080 where
1081
1082 dx = -kx * py
1083 dy = -ky * px
1084
1085 sets SkMatrix to:
1086
1087 | 1 kx dx| |J K L| |J+kx*M+dx*P K+kx*N+dx*Q L+kx*O+dx+R|
1088 K(kx, ky, px, py) * Matrix = |ky 1 dy| |M N O| = |ky*J+M+dy*P ky*K+N+dy*Q ky*L+O+dy*R|
1089 | 0 0 1| |P Q R| | P Q R|
1090
1091 @param kx horizontal skew factor
1092 @param ky vertical skew factor
1093 @param px pivot on x-axis
1094 @param py pivot on y-axis
1095 */
1096 SkMatrix& postSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py);
1097
1098 /** Sets SkMatrix to SkMatrix constructed from skewing by (kx, ky) about pivot point
1099 (0, 0), multiplied by SkMatrix.
1100 This can be thought of as skewing about the origin after applying SkMatrix.
1101
1102 Given:
1103
1104 | J K L | | 1 kx 0 |
1105 Matrix = | M N O |, K(kx, ky) = | ky 1 0 |
1106 | P Q R | | 0 0 1 |
1107
1108 sets SkMatrix to:
1109
1110 | 1 kx 0 | | J K L | | J+kx*M K+kx*N L+kx*O |
1111 K(kx, ky) * Matrix = | ky 1 0 | | M N O | = | ky*J+M ky*K+N ky*L+O |
1112 | 0 0 1 | | P Q R | | P Q R |
1113
1114 @param kx horizontal skew factor
1115 @param ky vertical skew factor
1116 */
1117 SkMatrix& postSkew(SkScalar kx, SkScalar ky);
1118
1119 /** Sets SkMatrix to SkMatrix other multiplied by SkMatrix.
1120 This can be thought of mapping by other after applying SkMatrix.
1121
1122 Given:
1123
1124 | J K L | | A B C |
1125 Matrix = | M N O |, other = | D E F |
1126 | P Q R | | G H I |
1127
1128 sets SkMatrix to:
1129
1130 | A B C | | J K L | | AJ+BM+CP AK+BN+CQ AL+BO+CR |
1131 other * Matrix = | D E F | * | M N O | = | DJ+EM+FP DK+EN+FQ DL+EO+FR |
1132 | G H I | | P Q R | | GJ+HM+IP GK+HN+IQ GL+HO+IR |
1133
1134 @param other SkMatrix on left side of multiply expression
1135 */
1136 SkMatrix& postConcat(const SkMatrix& other);
1137
1138#ifndef SK_SUPPORT_LEGACY_MATRIX_RECTTORECT
1139private:
1140#endif
1141 /** Sets SkMatrix to scale and translate src SkRect to dst SkRect. stf selects whether
1142 mapping completely fills dst or preserves the aspect ratio, and how to align
1143 src within dst. Returns false if src is empty, and sets SkMatrix to identity.
1144 Returns true if dst is empty, and sets SkMatrix to:
1145
1146 | 0 0 0 |
1147 | 0 0 0 |
1148 | 0 0 1 |
1149
1150 @param src SkRect to map from
1151 @param dst SkRect to map to
1152 @return true if SkMatrix can represent SkRect mapping
1153
1154 example: https://fiddle.skia.org/c/@Matrix_setRectToRect
1155 */
1156 bool setRectToRect(const SkRect& src, const SkRect& dst, ScaleToFit stf);
1157
1158 /** Returns SkMatrix set to scale and translate src SkRect to dst SkRect. stf selects
1159 whether mapping completely fills dst or preserves the aspect ratio, and how to
1160 align src within dst. Returns the identity SkMatrix if src is empty. If dst is
1161 empty, returns SkMatrix set to:
1162
1163 | 0 0 0 |
1164 | 0 0 0 |
1165 | 0 0 1 |
1166
1167 @param src SkRect to map from
1168 @param dst SkRect to map to
1169 @return SkMatrix mapping src to dst
1170 */
1171 static SkMatrix MakeRectToRect(const SkRect& src, const SkRect& dst, ScaleToFit stf) {
1172 SkMatrix m;
1173 m.setRectToRect(src, dst, stf);
1174 return m;
1175 }
1176#ifndef SK_SUPPORT_LEGACY_MATRIX_RECTTORECT
1177public:
1178#endif
1179
1180 /** Sets SkMatrix to map src to dst. count must be zero or greater, and four or less.
1181
1182 If count is zero, sets SkMatrix to identity and returns true.
1183 If count is one, sets SkMatrix to translate and returns true.
1184 If count is two or more, sets SkMatrix to map SkPoint if possible; returns false
1185 if SkMatrix cannot be constructed. If count is four, SkMatrix may include
1186 perspective.
1187
1188 @param src SkPoint to map from
1189 @param dst SkPoint to map to
1190 @param count number of SkPoint in src and dst
1191 @return true if SkMatrix was constructed successfully
1192
1193 example: https://fiddle.skia.org/c/@Matrix_setPolyToPoly
1194 */
1195 bool setPolyToPoly(const SkPoint src[], const SkPoint dst[], int count);
1196
1197 /** Sets inverse to reciprocal matrix, returning true if SkMatrix can be inverted.
1198 Geometrically, if SkMatrix maps from source to destination, inverse SkMatrix
1199 maps from destination to source. If SkMatrix can not be inverted, inverse is
1200 unchanged.
1201
1202 @param inverse storage for inverted SkMatrix; may be nullptr
1203 @return true if SkMatrix can be inverted
1204 */
1205 [[nodiscard]] bool invert(SkMatrix* inverse) const {
1206 // Allow the trivial case to be inlined.
1207 if (this->isIdentity()) {
1208 if (inverse) {
1209 inverse->reset();
1210 }
1211 return true;
1212 }
1213 return this->invertNonIdentity(inverse);
1214 }
1215
1216 /** Fills affine with identity values in column major order.
1217 Sets affine to:
1218
1219 | 1 0 0 |
1220 | 0 1 0 |
1221
1222 Affine 3 by 2 matrices in column major order are used by OpenGL and XPS.
1223
1224 @param affine storage for 3 by 2 affine matrix
1225
1226 example: https://fiddle.skia.org/c/@Matrix_SetAffineIdentity
1227 */
1228 static void SetAffineIdentity(SkScalar affine[6]);
1229
1230 /** Fills affine in column major order. Sets affine to:
1231
1232 | scale-x skew-x translate-x |
1233 | skew-y scale-y translate-y |
1234
1235 If SkMatrix contains perspective, returns false and leaves affine unchanged.
1236
1237 @param affine storage for 3 by 2 affine matrix; may be nullptr
1238 @return true if SkMatrix does not contain perspective
1239 */
1240 [[nodiscard]] bool asAffine(SkScalar affine[6]) const;
1241
1242 /** Sets SkMatrix to affine values, passed in column major order. Given affine,
1243 column, then row, as:
1244
1245 | scale-x skew-x translate-x |
1246 | skew-y scale-y translate-y |
1247
1248 SkMatrix is set, row, then column, to:
1249
1250 | scale-x skew-x translate-x |
1251 | skew-y scale-y translate-y |
1252 | 0 0 1 |
1253
1254 @param affine 3 by 2 affine matrix
1255 */
1256 SkMatrix& setAffine(const SkScalar affine[6]);
1257
1258 /**
1259 * A matrix is categorized as 'perspective' if the bottom row is not [0, 0, 1].
1260 * However, for most uses (e.g. mapPoints) a bottom row of [0, 0, X] behaves like a
1261 * non-perspective matrix, though it will be categorized as perspective. Calling
1262 * normalizePerspective() will change the matrix such that, if its bottom row was [0, 0, X],
1263 * it will be changed to [0, 0, 1] by scaling the rest of the matrix by 1/X.
1264 *
1265 * | A B C | | A/X B/X C/X |
1266 * | D E F | -> | D/X E/X F/X | for X != 0
1267 * | 0 0 X | | 0 0 1 |
1268 */
1269 void normalizePerspective() {
1270 if (fMat[8] != 1) {
1271 this->doNormalizePerspective();
1272 }
1273 }
1274
1275 /** Maps src SkPoint array of length count to dst SkPoint array of equal or greater
1276 length. SkPoint are mapped by multiplying each SkPoint by SkMatrix. Given:
1277
1278 | A B C | | x |
1279 Matrix = | D E F |, pt = | y |
1280 | G H I | | 1 |
1281
1282 where
1283
1284 for (i = 0; i < count; ++i) {
1285 x = src[i].fX
1286 y = src[i].fY
1287 }
1288
1289 each dst SkPoint is computed as:
1290
1291 |A B C| |x| Ax+By+C Dx+Ey+F
1292 Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , -------
1293 |G H I| |1| Gx+Hy+I Gx+Hy+I
1294
1295 src and dst may point to the same storage.
1296
1297 @param dst storage for mapped SkPoint
1298 @param src SkPoint to transform
1299 @param count number of SkPoint to transform
1300
1301 example: https://fiddle.skia.org/c/@Matrix_mapPoints
1302 */
1303 void mapPoints(SkPoint dst[], const SkPoint src[], int count) const;
1304
1305 /** Maps pts SkPoint array of length count in place. SkPoint are mapped by multiplying
1306 each SkPoint by SkMatrix. Given:
1307
1308 | A B C | | x |
1309 Matrix = | D E F |, pt = | y |
1310 | G H I | | 1 |
1311
1312 where
1313
1314 for (i = 0; i < count; ++i) {
1315 x = pts[i].fX
1316 y = pts[i].fY
1317 }
1318
1319 each resulting pts SkPoint is computed as:
1320
1321 |A B C| |x| Ax+By+C Dx+Ey+F
1322 Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , -------
1323 |G H I| |1| Gx+Hy+I Gx+Hy+I
1324
1325 @param pts storage for mapped SkPoint
1326 @param count number of SkPoint to transform
1327 */
1328 void mapPoints(SkPoint pts[], int count) const {
1329 this->mapPoints(dst: pts, src: pts, count);
1330 }
1331
1332 /** Maps src SkPoint3 array of length count to dst SkPoint3 array, which must of length count or
1333 greater. SkPoint3 array is mapped by multiplying each SkPoint3 by SkMatrix. Given:
1334
1335 | A B C | | x |
1336 Matrix = | D E F |, src = | y |
1337 | G H I | | z |
1338
1339 each resulting dst SkPoint is computed as:
1340
1341 |A B C| |x|
1342 Matrix * src = |D E F| |y| = |Ax+By+Cz Dx+Ey+Fz Gx+Hy+Iz|
1343 |G H I| |z|
1344
1345 @param dst storage for mapped SkPoint3 array
1346 @param src SkPoint3 array to transform
1347 @param count items in SkPoint3 array to transform
1348
1349 example: https://fiddle.skia.org/c/@Matrix_mapHomogeneousPoints
1350 */
1351 void mapHomogeneousPoints(SkPoint3 dst[], const SkPoint3 src[], int count) const;
1352
1353 /**
1354 * Returns homogeneous points, starting with 2D src points (with implied w = 1).
1355 */
1356 void mapHomogeneousPoints(SkPoint3 dst[], const SkPoint src[], int count) const;
1357
1358 /** Returns SkPoint pt multiplied by SkMatrix. Given:
1359
1360 | A B C | | x |
1361 Matrix = | D E F |, pt = | y |
1362 | G H I | | 1 |
1363
1364 result is computed as:
1365
1366 |A B C| |x| Ax+By+C Dx+Ey+F
1367 Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , -------
1368 |G H I| |1| Gx+Hy+I Gx+Hy+I
1369
1370 @param p SkPoint to map
1371 @return mapped SkPoint
1372 */
1373 SkPoint mapPoint(SkPoint pt) const {
1374 SkPoint result;
1375 this->mapXY(x: pt.x(), y: pt.y(), result: &result);
1376 return result;
1377 }
1378
1379 /** Maps SkPoint (x, y) to result. SkPoint is mapped by multiplying by SkMatrix. Given:
1380
1381 | A B C | | x |
1382 Matrix = | D E F |, pt = | y |
1383 | G H I | | 1 |
1384
1385 result is computed as:
1386
1387 |A B C| |x| Ax+By+C Dx+Ey+F
1388 Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , -------
1389 |G H I| |1| Gx+Hy+I Gx+Hy+I
1390
1391 @param x x-axis value of SkPoint to map
1392 @param y y-axis value of SkPoint to map
1393 @param result storage for mapped SkPoint
1394
1395 example: https://fiddle.skia.org/c/@Matrix_mapXY
1396 */
1397 void mapXY(SkScalar x, SkScalar y, SkPoint* result) const;
1398
1399 /** Returns SkPoint (x, y) multiplied by SkMatrix. Given:
1400
1401 | A B C | | x |
1402 Matrix = | D E F |, pt = | y |
1403 | G H I | | 1 |
1404
1405 result is computed as:
1406
1407 |A B C| |x| Ax+By+C Dx+Ey+F
1408 Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , -------
1409 |G H I| |1| Gx+Hy+I Gx+Hy+I
1410
1411 @param x x-axis value of SkPoint to map
1412 @param y y-axis value of SkPoint to map
1413 @return mapped SkPoint
1414 */
1415 SkPoint mapXY(SkScalar x, SkScalar y) const {
1416 SkPoint result;
1417 this->mapXY(x,y, result: &result);
1418 return result;
1419 }
1420
1421
1422 /** Returns (0, 0) multiplied by SkMatrix. Given:
1423
1424 | A B C | | 0 |
1425 Matrix = | D E F |, pt = | 0 |
1426 | G H I | | 1 |
1427
1428 result is computed as:
1429
1430 |A B C| |0| C F
1431 Matrix * pt = |D E F| |0| = |C F I| = - , -
1432 |G H I| |1| I I
1433
1434 @return mapped (0, 0)
1435 */
1436 SkPoint mapOrigin() const {
1437 SkScalar x = this->getTranslateX(),
1438 y = this->getTranslateY();
1439 if (this->hasPerspective()) {
1440 SkScalar w = fMat[kMPersp2];
1441 if (w) { w = 1 / w; }
1442 x *= w;
1443 y *= w;
1444 }
1445 return {.fX: x, .fY: y};
1446 }
1447
1448 /** Maps src vector array of length count to vector SkPoint array of equal or greater
1449 length. Vectors are mapped by multiplying each vector by SkMatrix, treating
1450 SkMatrix translation as zero. Given:
1451
1452 | A B 0 | | x |
1453 Matrix = | D E 0 |, src = | y |
1454 | G H I | | 1 |
1455
1456 where
1457
1458 for (i = 0; i < count; ++i) {
1459 x = src[i].fX
1460 y = src[i].fY
1461 }
1462
1463 each dst vector is computed as:
1464
1465 |A B 0| |x| Ax+By Dx+Ey
1466 Matrix * src = |D E 0| |y| = |Ax+By Dx+Ey Gx+Hy+I| = ------- , -------
1467 |G H I| |1| Gx+Hy+I Gx+Hy+I
1468
1469 src and dst may point to the same storage.
1470
1471 @param dst storage for mapped vectors
1472 @param src vectors to transform
1473 @param count number of vectors to transform
1474
1475 example: https://fiddle.skia.org/c/@Matrix_mapVectors
1476 */
1477 void mapVectors(SkVector dst[], const SkVector src[], int count) const;
1478
1479 /** Maps vecs vector array of length count in place, multiplying each vector by
1480 SkMatrix, treating SkMatrix translation as zero. Given:
1481
1482 | A B 0 | | x |
1483 Matrix = | D E 0 |, vec = | y |
1484 | G H I | | 1 |
1485
1486 where
1487
1488 for (i = 0; i < count; ++i) {
1489 x = vecs[i].fX
1490 y = vecs[i].fY
1491 }
1492
1493 each result vector is computed as:
1494
1495 |A B 0| |x| Ax+By Dx+Ey
1496 Matrix * vec = |D E 0| |y| = |Ax+By Dx+Ey Gx+Hy+I| = ------- , -------
1497 |G H I| |1| Gx+Hy+I Gx+Hy+I
1498
1499 @param vecs vectors to transform, and storage for mapped vectors
1500 @param count number of vectors to transform
1501 */
1502 void mapVectors(SkVector vecs[], int count) const {
1503 this->mapVectors(dst: vecs, src: vecs, count);
1504 }
1505
1506 /** Maps vector (dx, dy) to result. Vector is mapped by multiplying by SkMatrix,
1507 treating SkMatrix translation as zero. Given:
1508
1509 | A B 0 | | dx |
1510 Matrix = | D E 0 |, vec = | dy |
1511 | G H I | | 1 |
1512
1513 each result vector is computed as:
1514
1515 |A B 0| |dx| A*dx+B*dy D*dx+E*dy
1516 Matrix * vec = |D E 0| |dy| = |A*dx+B*dy D*dx+E*dy G*dx+H*dy+I| = ----------- , -----------
1517 |G H I| | 1| G*dx+H*dy+I G*dx+*dHy+I
1518
1519 @param dx x-axis value of vector to map
1520 @param dy y-axis value of vector to map
1521 @param result storage for mapped vector
1522 */
1523 void mapVector(SkScalar dx, SkScalar dy, SkVector* result) const {
1524 SkVector vec = { .fX: dx, .fY: dy };
1525 this->mapVectors(dst: result, src: &vec, count: 1);
1526 }
1527
1528 /** Returns vector (dx, dy) multiplied by SkMatrix, treating SkMatrix translation as zero.
1529 Given:
1530
1531 | A B 0 | | dx |
1532 Matrix = | D E 0 |, vec = | dy |
1533 | G H I | | 1 |
1534
1535 each result vector is computed as:
1536
1537 |A B 0| |dx| A*dx+B*dy D*dx+E*dy
1538 Matrix * vec = |D E 0| |dy| = |A*dx+B*dy D*dx+E*dy G*dx+H*dy+I| = ----------- , -----------
1539 |G H I| | 1| G*dx+H*dy+I G*dx+*dHy+I
1540
1541 @param dx x-axis value of vector to map
1542 @param dy y-axis value of vector to map
1543 @return mapped vector
1544 */
1545 SkVector mapVector(SkScalar dx, SkScalar dy) const {
1546 SkVector vec = { .fX: dx, .fY: dy };
1547 this->mapVectors(dst: &vec, src: &vec, count: 1);
1548 return vec;
1549 }
1550
1551 /** Sets dst to bounds of src corners mapped by SkMatrix.
1552 Returns true if mapped corners are dst corners.
1553
1554 Returned value is the same as calling rectStaysRect().
1555
1556 @param dst storage for bounds of mapped SkPoint
1557 @param src SkRect to map
1558 @param pc whether to apply perspective clipping
1559 @return true if dst is equivalent to mapped src
1560
1561 example: https://fiddle.skia.org/c/@Matrix_mapRect
1562 */
1563 bool mapRect(SkRect* dst, const SkRect& src,
1564 SkApplyPerspectiveClip pc = SkApplyPerspectiveClip::kYes) const;
1565
1566 /** Sets rect to bounds of rect corners mapped by SkMatrix.
1567 Returns true if mapped corners are computed rect corners.
1568
1569 Returned value is the same as calling rectStaysRect().
1570
1571 @param rect rectangle to map, and storage for bounds of mapped corners
1572 @param pc whether to apply perspective clipping
1573 @return true if result is equivalent to mapped rect
1574 */
1575 bool mapRect(SkRect* rect, SkApplyPerspectiveClip pc = SkApplyPerspectiveClip::kYes) const {
1576 return this->mapRect(dst: rect, src: *rect, pc);
1577 }
1578
1579 /** Returns bounds of src corners mapped by SkMatrix.
1580
1581 @param src rectangle to map
1582 @return mapped bounds
1583 */
1584 SkRect mapRect(const SkRect& src,
1585 SkApplyPerspectiveClip pc = SkApplyPerspectiveClip::kYes) const {
1586 SkRect dst;
1587 (void)this->mapRect(dst: &dst, src, pc);
1588 return dst;
1589 }
1590
1591 /** Maps four corners of rect to dst. SkPoint are mapped by multiplying each
1592 rect corner by SkMatrix. rect corner is processed in this order:
1593 (rect.fLeft, rect.fTop), (rect.fRight, rect.fTop), (rect.fRight, rect.fBottom),
1594 (rect.fLeft, rect.fBottom).
1595
1596 rect may be empty: rect.fLeft may be greater than or equal to rect.fRight;
1597 rect.fTop may be greater than or equal to rect.fBottom.
1598
1599 Given:
1600
1601 | A B C | | x |
1602 Matrix = | D E F |, pt = | y |
1603 | G H I | | 1 |
1604
1605 where pt is initialized from each of (rect.fLeft, rect.fTop),
1606 (rect.fRight, rect.fTop), (rect.fRight, rect.fBottom), (rect.fLeft, rect.fBottom),
1607 each dst SkPoint is computed as:
1608
1609 |A B C| |x| Ax+By+C Dx+Ey+F
1610 Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , -------
1611 |G H I| |1| Gx+Hy+I Gx+Hy+I
1612
1613 @param dst storage for mapped corner SkPoint
1614 @param rect SkRect to map
1615
1616 Note: this does not perform perspective clipping (as that might result in more than
1617 4 points, so results are suspect if the matrix contains perspective.
1618 */
1619 void mapRectToQuad(SkPoint dst[4], const SkRect& rect) const {
1620 // This could potentially be faster if we only transformed each x and y of the rect once.
1621 rect.toQuad(quad: dst);
1622 this->mapPoints(pts: dst, count: 4);
1623 }
1624
1625 /** Sets dst to bounds of src corners mapped by SkMatrix. If matrix contains
1626 elements other than scale or translate: asserts if SK_DEBUG is defined;
1627 otherwise, results are undefined.
1628
1629 @param dst storage for bounds of mapped SkPoint
1630 @param src SkRect to map
1631
1632 example: https://fiddle.skia.org/c/@Matrix_mapRectScaleTranslate
1633 */
1634 void mapRectScaleTranslate(SkRect* dst, const SkRect& src) const;
1635
1636 /** Returns geometric mean radius of ellipse formed by constructing circle of
1637 size radius, and mapping constructed circle with SkMatrix. The result squared is
1638 equal to the major axis length times the minor axis length.
1639 Result is not meaningful if SkMatrix contains perspective elements.
1640
1641 @param radius circle size to map
1642 @return average mapped radius
1643
1644 example: https://fiddle.skia.org/c/@Matrix_mapRadius
1645 */
1646 SkScalar mapRadius(SkScalar radius) const;
1647
1648 /** Compares a and b; returns true if a and b are numerically equal. Returns true
1649 even if sign of zero values are different. Returns false if either SkMatrix
1650 contains NaN, even if the other SkMatrix also contains NaN.
1651
1652 @param a SkMatrix to compare
1653 @param b SkMatrix to compare
1654 @return true if SkMatrix a and SkMatrix b are numerically equal
1655 */
1656 friend SK_API bool operator==(const SkMatrix& a, const SkMatrix& b);
1657
1658 /** Compares a and b; returns true if a and b are not numerically equal. Returns false
1659 even if sign of zero values are different. Returns true if either SkMatrix
1660 contains NaN, even if the other SkMatrix also contains NaN.
1661
1662 @param a SkMatrix to compare
1663 @param b SkMatrix to compare
1664 @return true if SkMatrix a and SkMatrix b are numerically not equal
1665 */
1666 friend SK_API bool operator!=(const SkMatrix& a, const SkMatrix& b) {
1667 return !(a == b);
1668 }
1669
1670 /** Writes text representation of SkMatrix to standard output. Floating point values
1671 are written with limited precision; it may not be possible to reconstruct
1672 original SkMatrix from output.
1673
1674 example: https://fiddle.skia.org/c/@Matrix_dump
1675 */
1676 void dump() const;
1677
1678 /** Returns the minimum scaling factor of SkMatrix by decomposing the scaling and
1679 skewing elements.
1680 Returns -1 if scale factor overflows or SkMatrix contains perspective.
1681
1682 @return minimum scale factor
1683
1684 example: https://fiddle.skia.org/c/@Matrix_getMinScale
1685 */
1686 SkScalar getMinScale() const;
1687
1688 /** Returns the maximum scaling factor of SkMatrix by decomposing the scaling and
1689 skewing elements.
1690 Returns -1 if scale factor overflows or SkMatrix contains perspective.
1691
1692 @return maximum scale factor
1693
1694 example: https://fiddle.skia.org/c/@Matrix_getMaxScale
1695 */
1696 SkScalar getMaxScale() const;
1697
1698 /** Sets scaleFactors[0] to the minimum scaling factor, and scaleFactors[1] to the
1699 maximum scaling factor. Scaling factors are computed by decomposing
1700 the SkMatrix scaling and skewing elements.
1701
1702 Returns true if scaleFactors are found; otherwise, returns false and sets
1703 scaleFactors to undefined values.
1704
1705 @param scaleFactors storage for minimum and maximum scale factors
1706 @return true if scale factors were computed correctly
1707 */
1708 [[nodiscard]] bool getMinMaxScales(SkScalar scaleFactors[2]) const;
1709
1710 /** Decomposes SkMatrix into scale components and whatever remains. Returns false if
1711 SkMatrix could not be decomposed.
1712
1713 Sets scale to portion of SkMatrix that scale axes. Sets remaining to SkMatrix
1714 with scaling factored out. remaining may be passed as nullptr
1715 to determine if SkMatrix can be decomposed without computing remainder.
1716
1717 Returns true if scale components are found. scale and remaining are
1718 unchanged if SkMatrix contains perspective; scale factors are not finite, or
1719 are nearly zero.
1720
1721 On success: Matrix = Remaining * scale.
1722
1723 @param scale axes scaling factors; may be nullptr
1724 @param remaining SkMatrix without scaling; may be nullptr
1725 @return true if scale can be computed
1726
1727 example: https://fiddle.skia.org/c/@Matrix_decomposeScale
1728 */
1729 bool decomposeScale(SkSize* scale, SkMatrix* remaining = nullptr) const;
1730
1731 /** Returns reference to const identity SkMatrix. Returned SkMatrix is set to:
1732
1733 | 1 0 0 |
1734 | 0 1 0 |
1735 | 0 0 1 |
1736
1737 @return const identity SkMatrix
1738
1739 example: https://fiddle.skia.org/c/@Matrix_I
1740 */
1741 static const SkMatrix& I();
1742
1743 /** Returns reference to a const SkMatrix with invalid values. Returned SkMatrix is set
1744 to:
1745
1746 | SK_ScalarMax SK_ScalarMax SK_ScalarMax |
1747 | SK_ScalarMax SK_ScalarMax SK_ScalarMax |
1748 | SK_ScalarMax SK_ScalarMax SK_ScalarMax |
1749
1750 @return const invalid SkMatrix
1751
1752 example: https://fiddle.skia.org/c/@Matrix_InvalidMatrix
1753 */
1754 static const SkMatrix& InvalidMatrix();
1755
1756 /** Returns SkMatrix a multiplied by SkMatrix b.
1757
1758 Given:
1759
1760 | A B C | | J K L |
1761 a = | D E F |, b = | M N O |
1762 | G H I | | P Q R |
1763
1764 sets SkMatrix to:
1765
1766 | A B C | | J K L | | AJ+BM+CP AK+BN+CQ AL+BO+CR |
1767 a * b = | D E F | * | M N O | = | DJ+EM+FP DK+EN+FQ DL+EO+FR |
1768 | G H I | | P Q R | | GJ+HM+IP GK+HN+IQ GL+HO+IR |
1769
1770 @param a SkMatrix on left side of multiply expression
1771 @param b SkMatrix on right side of multiply expression
1772 @return SkMatrix computed from a times b
1773 */
1774 static SkMatrix Concat(const SkMatrix& a, const SkMatrix& b) {
1775 SkMatrix result;
1776 result.setConcat(a, b);
1777 return result;
1778 }
1779
1780 friend SkMatrix operator*(const SkMatrix& a, const SkMatrix& b) {
1781 return Concat(a, b);
1782 }
1783
1784 /** Sets internal cache to unknown state. Use to force update after repeated
1785 modifications to SkMatrix element reference returned by operator[](int index).
1786 */
1787 void dirtyMatrixTypeCache() {
1788 this->setTypeMask(kUnknown_Mask);
1789 }
1790
1791 /** Initializes SkMatrix with scale and translate elements.
1792
1793 | sx 0 tx |
1794 | 0 sy ty |
1795 | 0 0 1 |
1796
1797 @param sx horizontal scale factor to store
1798 @param sy vertical scale factor to store
1799 @param tx horizontal translation to store
1800 @param ty vertical translation to store
1801 */
1802 void setScaleTranslate(SkScalar sx, SkScalar sy, SkScalar tx, SkScalar ty) {
1803 fMat[kMScaleX] = sx;
1804 fMat[kMSkewX] = 0;
1805 fMat[kMTransX] = tx;
1806
1807 fMat[kMSkewY] = 0;
1808 fMat[kMScaleY] = sy;
1809 fMat[kMTransY] = ty;
1810
1811 fMat[kMPersp0] = 0;
1812 fMat[kMPersp1] = 0;
1813 fMat[kMPersp2] = 1;
1814
1815 int mask = 0;
1816 if (sx != 1 || sy != 1) {
1817 mask |= kScale_Mask;
1818 }
1819 if (tx != 0.0f || ty != 0.0f) {
1820 mask |= kTranslate_Mask;
1821 }
1822 if (sx != 0 && sy != 0) {
1823 mask |= kRectStaysRect_Mask;
1824 }
1825 this->setTypeMask(mask);
1826 }
1827
1828 /** Returns true if all elements of the matrix are finite. Returns false if any
1829 element is infinity, or NaN.
1830
1831 @return true if matrix has only finite elements
1832 */
1833 bool isFinite() const { return SkScalarsAreFinite(array: fMat, count: 9); }
1834
1835private:
1836 /** Set if the matrix will map a rectangle to another rectangle. This
1837 can be true if the matrix is scale-only, or rotates a multiple of
1838 90 degrees.
1839
1840 This bit will be set on identity matrices
1841 */
1842 static constexpr int kRectStaysRect_Mask = 0x10;
1843
1844 /** Set if the perspective bit is valid even though the rest of
1845 the matrix is Unknown.
1846 */
1847 static constexpr int kOnlyPerspectiveValid_Mask = 0x40;
1848
1849 static constexpr int kUnknown_Mask = 0x80;
1850
1851 static constexpr int kORableMasks = kTranslate_Mask |
1852 kScale_Mask |
1853 kAffine_Mask |
1854 kPerspective_Mask;
1855
1856 static constexpr int kAllMasks = kTranslate_Mask |
1857 kScale_Mask |
1858 kAffine_Mask |
1859 kPerspective_Mask |
1860 kRectStaysRect_Mask;
1861
1862 SkScalar fMat[9];
1863 mutable int32_t fTypeMask;
1864
1865 constexpr SkMatrix(SkScalar sx, SkScalar kx, SkScalar tx,
1866 SkScalar ky, SkScalar sy, SkScalar ty,
1867 SkScalar p0, SkScalar p1, SkScalar p2, int typeMask)
1868 : fMat{sx, kx, tx,
1869 ky, sy, ty,
1870 p0, p1, p2}
1871 , fTypeMask(typeMask) {}
1872
1873 static void ComputeInv(SkScalar dst[9], const SkScalar src[9], double invDet, bool isPersp);
1874
1875 uint8_t computeTypeMask() const;
1876 uint8_t computePerspectiveTypeMask() const;
1877
1878 void setTypeMask(int mask) {
1879 // allow kUnknown or a valid mask
1880 SkASSERT(kUnknown_Mask == mask || (mask & kAllMasks) == mask ||
1881 ((kUnknown_Mask | kOnlyPerspectiveValid_Mask) & mask)
1882 == (kUnknown_Mask | kOnlyPerspectiveValid_Mask));
1883 fTypeMask = mask;
1884 }
1885
1886 void orTypeMask(int mask) {
1887 SkASSERT((mask & kORableMasks) == mask);
1888 fTypeMask |= mask;
1889 }
1890
1891 void clearTypeMask(int mask) {
1892 // only allow a valid mask
1893 SkASSERT((mask & kAllMasks) == mask);
1894 fTypeMask &= ~mask;
1895 }
1896
1897 TypeMask getPerspectiveTypeMaskOnly() const {
1898 if ((fTypeMask & kUnknown_Mask) &&
1899 !(fTypeMask & kOnlyPerspectiveValid_Mask)) {
1900 fTypeMask = this->computePerspectiveTypeMask();
1901 }
1902 return (TypeMask)(fTypeMask & 0xF);
1903 }
1904
1905 /** Returns true if we already know that the matrix is identity;
1906 false otherwise.
1907 */
1908 bool isTriviallyIdentity() const {
1909 if (fTypeMask & kUnknown_Mask) {
1910 return false;
1911 }
1912 return ((fTypeMask & 0xF) == 0);
1913 }
1914
1915 inline void updateTranslateMask() {
1916 if ((fMat[kMTransX] != 0) | (fMat[kMTransY] != 0)) {
1917 fTypeMask |= kTranslate_Mask;
1918 } else {
1919 fTypeMask &= ~kTranslate_Mask;
1920 }
1921 }
1922
1923 typedef void (*MapXYProc)(const SkMatrix& mat, SkScalar x, SkScalar y,
1924 SkPoint* result);
1925
1926 static MapXYProc GetMapXYProc(TypeMask mask) {
1927 SkASSERT((mask & ~kAllMasks) == 0);
1928 return gMapXYProcs[mask & kAllMasks];
1929 }
1930
1931 MapXYProc getMapXYProc() const {
1932 return GetMapXYProc(mask: this->getType());
1933 }
1934
1935 typedef void (*MapPtsProc)(const SkMatrix& mat, SkPoint dst[],
1936 const SkPoint src[], int count);
1937
1938 static MapPtsProc GetMapPtsProc(TypeMask mask) {
1939 SkASSERT((mask & ~kAllMasks) == 0);
1940 return gMapPtsProcs[mask & kAllMasks];
1941 }
1942
1943 MapPtsProc getMapPtsProc() const {
1944 return GetMapPtsProc(mask: this->getType());
1945 }
1946
1947 [[nodiscard]] bool invertNonIdentity(SkMatrix* inverse) const;
1948
1949 static bool Poly2Proc(const SkPoint[], SkMatrix*);
1950 static bool Poly3Proc(const SkPoint[], SkMatrix*);
1951 static bool Poly4Proc(const SkPoint[], SkMatrix*);
1952
1953 static void Identity_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
1954 static void Trans_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
1955 static void Scale_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
1956 static void ScaleTrans_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
1957 static void Rot_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
1958 static void RotTrans_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
1959 static void Persp_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
1960
1961 static const MapXYProc gMapXYProcs[];
1962
1963 static void Identity_pts(const SkMatrix&, SkPoint[], const SkPoint[], int);
1964 static void Trans_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], int);
1965 static void Scale_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], int);
1966 static void ScaleTrans_pts(const SkMatrix&, SkPoint dst[], const SkPoint[],
1967 int count);
1968 static void Persp_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], int);
1969
1970 static void Affine_vpts(const SkMatrix&, SkPoint dst[], const SkPoint[], int);
1971
1972 static const MapPtsProc gMapPtsProcs[];
1973
1974 // return the number of bytes written, whether or not buffer is null
1975 size_t writeToMemory(void* buffer) const;
1976 /**
1977 * Reads data from the buffer parameter
1978 *
1979 * @param buffer Memory to read from
1980 * @param length Amount of memory available in the buffer
1981 * @return number of bytes read (must be a multiple of 4) or
1982 * 0 if there was not enough memory available
1983 */
1984 size_t readFromMemory(const void* buffer, size_t length);
1985
1986 // legacy method -- still needed? why not just postScale(1/divx, ...)?
1987 bool postIDiv(int divx, int divy);
1988 void doNormalizePerspective();
1989
1990 friend class SkPerspIter;
1991 friend class SkMatrixPriv;
1992 friend class SerializationTest;
1993};
1994SK_END_REQUIRE_DENSE
1995
1996#endif
1997

source code of flutter_engine/third_party/skia/include/core/SkMatrix.h