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