soui 5.0.0.1
Soui5 Doc
 
Loading...
Searching...
No Matches
SMatrix.h
1
2#ifndef _SMatrix_DEFINED_
3#define _SMatrix_DEFINED_
4
5#include "SRect.h"
6#include <interface/SRender-i.h>
7#include <interface/SMatrix-i.h>
8
9#define SToBool(cond) ((cond) != 0)
10
11SNSBEGIN
12
13/**
14 * @class SMatrix
15 * @brief The SMatrix class holds a 3x3 matrix for transforming coordinates.
16 * SMatrix does not have a constructor, so it must be explicitly initialized
17 * using either reset() - to construct an identity matrix, or one of the set
18 * functions (e.g., setTranslate, setRotate, etc.).
19 */
20class SOUI_EXP SMatrix
21 : public IxForm
22 , public IMatrix {
23 public:
24 /**
25 * @brief Default constructor, initializes the matrix to identity.
26 */
28 {
29 reset();
30 }
31
32 /**
33 * @brief Constructor that initializes the matrix with the given data array.
34 * @param data Array of 9 floats representing the matrix elements.
35 */
36 SMatrix(const float data[9]);
37
38 public:
39 /**
40 * @brief Multiplies the matrix by another matrix.
41 * @param src The matrix to multiply with.
42 * @return Reference to the modified matrix.
43 */
44 SMatrix &operator*=(const SMatrix &src);
45
46 /**
47 * @brief Multiplies the matrix by another matrix.
48 * @param src The matrix to multiply with.
49 * @return New matrix resulting from the multiplication.
50 */
51 SMatrix operator*(const SMatrix &src) const;
52
53 /**
54 * @brief Assignment operator.
55 * @param src The matrix to assign from.
56 * @return Reference to the modified matrix.
57 */
58 SMatrix &operator=(const SMatrix &src);
59
60 /**
61 * @brief Equality operator.
62 * @param a First matrix.
63 * @param b Second matrix.
64 * @return True if matrices are equal, false otherwise.
65 */
66 friend bool operator==(const SMatrix &a, const SMatrix &b);
67
68 /**
69 * @brief Inequality operator.
70 * @param a First matrix.
71 * @param b Second matrix.
72 * @return True if matrices are not equal, false otherwise.
73 */
74 friend bool operator!=(const SMatrix &a, const SMatrix &b)
75 {
76 return !(a == b);
77 }
78
79 public:
80 /**
81 * @brief Post-concats the matrix with a translation.
82 * @param dx Translation in the x-direction.
83 * @param dy Translation in the y-direction.
84 * @return Reference to the modified matrix.
85 */
86 SMatrix &translate(float dx, float dy)
87 {
88 postTranslate(dx, dy);
89 return *this;
90 }
91
92 /**
93 * @brief Post-concats the matrix with a scale.
94 * @param sx Scale factor in the x-direction.
95 * @param sy Scale factor in the y-direction.
96 * @return Reference to the modified matrix.
97 */
98 SMatrix &scale(float sx, float sy)
99 {
100 postScale(sx, sy);
101 return *this;
102 }
103
104 /**
105 * @brief Post-concats the matrix with a shear.
106 * @param sh Shear factor in the x-direction.
107 * @param sv Shear factor in the y-direction.
108 * @return Reference to the modified matrix.
109 */
110 SMatrix &shear(float sh, float sv)
111 {
112 postSkew(sh, sv);
113 return *this;
114 }
115
116 /**
117 * @brief Post-concats the matrix with a rotation.
118 * @param deg Rotation angle in degrees.
119 * @return Reference to the modified matrix.
120 */
121 SMatrix &rotate(float deg)
122 {
123 postRotate(deg);
124 return *this;
125 }
126
127 public:
128 /**
129 * @brief Returns a pointer to the matrix data.
130 * @return Pointer to the matrix data.
131 */
132 STDMETHOD_(IxForm *, Data)(THIS) SCONST OVERRIDE;
133
134 /**
135 * @brief Resets the matrix to the identity matrix.
136 */
137 STDMETHOD_(void, reset)(THIS) OVERRIDE;
138
139 /**
140 * @brief Sets the matrix to the identity matrix.
141 */
142 STDMETHOD_(void, setIdentity)(THIS) OVERRIDE;
143
144 /**
145 * @brief Checks if the matrix is the identity matrix.
146 * @return True if the matrix is identity, false otherwise.
147 */
148 STDMETHOD_(BOOL, isIdentity)(THIS) SCONST OVERRIDE;
149
150 /**
151 * @brief Sets the matrix to a translation.
152 * @param dx Translation in the x-direction.
153 * @param dy Translation in the y-direction.
154 */
155 STDMETHOD_(void, setTranslate)(THIS_ float dx, float dy) OVERRIDE;
156
157 /**
158 * @brief Sets the matrix to a scale.
159 * @param sx Scale factor in the x-direction.
160 * @param sy Scale factor in the y-direction.
161 */
162 STDMETHOD_(void, setScale)(THIS_ float sx, float sy) OVERRIDE;
163
164 /**
165 * @brief Sets the matrix to a scale with pivot point.
166 * @param sx Scale factor in the x-direction.
167 * @param sy Scale factor in the y-direction.
168 * @param px Pivot point x-coordinate.
169 * @param py Pivot point y-coordinate.
170 */
171 STDMETHOD_(void, setScale2)(THIS_ float sx, float sy, float px, float py) OVERRIDE;
172
173 /**
174 * @brief Sets the matrix to a rotation.
175 * @param degrees Rotation angle in degrees.
176 */
177 STDMETHOD_(void, setRotate)(THIS_ float degrees) OVERRIDE;
178
179 /**
180 * @brief Sets the matrix to a rotation with pivot point.
181 * @param degrees Rotation angle in degrees.
182 * @param px Pivot point x-coordinate.
183 * @param py Pivot point y-coordinate.
184 */
185 STDMETHOD_(void, setRotate2)(THIS_ float degrees, float px, float py) OVERRIDE;
186
187 /**
188 * @brief Sets the matrix to a skew.
189 * @param kx Skew factor in the x-direction.
190 * @param ky Skew factor in the y-direction.
191 */
192 STDMETHOD_(void, setSkew)(THIS_ float kx, float ky) OVERRIDE;
193
194 /**
195 * @brief Sets the matrix to a skew with pivot point.
196 * @param kx Skew factor in the x-direction.
197 * @param ky Skew factor in the y-direction.
198 * @param px Pivot point x-coordinate.
199 * @param py Pivot point y-coordinate.
200 */
201 STDMETHOD_(void, setSkew2)(THIS_ float kx, float ky, float px, float py) OVERRIDE;
202
203 public:
204 /**
205 * @enum TypeMask
206 * @brief Enum of bit fields for the mask returned by getType().
207 * Use this to identify the complexity of the matrix.
208 */
210 {
211 kIdentity_Mask = 0, //!< Set if the matrix is identity
212 kTranslate_Mask = 0x01, //!< Set if the matrix has translation
213 kScale_Mask = 0x02, //!< Set if the matrix has X or Y scale
214 kAffine_Mask = 0x04, //!< Set if the matrix skews or rotates
215 kPerspective_Mask = 0x08 //!< Set if the matrix is in perspective
216 };
217
218 /**
219 * @brief Returns a bitfield describing the transformations the matrix may perform.
220 * The bitfield is computed conservatively, so it may include false positives.
221 * For example, when kPerspective_Mask is true, all other bits may be set to true
222 * even in the case of a non-perspective transform.
223 * @return Bitfield describing the transformations.
224 */
226 {
227 if (fTypeMask & kUnknown_Mask)
228 {
229 fTypeMask = this->computeTypeMask();
230 }
231 // only return the public masks
232 return (TypeMask)(fTypeMask & 0xF);
233 }
234
235 /**
236 * @brief Checks if the matrix contains only scale and translation.
237 * @return True if the matrix contains only scale and translation, false otherwise.
238 */
239 bool isScaleTranslate() const
240 {
241 return !(this->getType() & ~(kScale_Mask | kTranslate_Mask));
242 }
243
244 /**
245 * @brief Returns true if the matrix will map a rectangle to another rectangle.
246 * This can be true if the matrix is identity, scale-only, or rotates a multiple of 90 degrees.
247 * @return True if the matrix preserves rectangle shape, false otherwise.
248 */
249 bool rectStaysRect() const
250 {
251 if (fTypeMask & kUnknown_Mask)
252 {
253 fTypeMask = this->computeTypeMask();
254 }
255 return (fTypeMask & kRectStaysRect_Mask) != 0;
256 }
257
258 /**
259 * @brief Alias for rectStaysRect().
260 * @return True if the matrix preserves rectangle shape, false otherwise.
261 */
263 {
264 return this->rectStaysRect();
265 }
266
267 /**
268 * @brief Checks if the matrix contains perspective elements.
269 * @return True if the matrix has perspective elements, false otherwise.
270 */
271 bool hasPerspective() const
272 {
273 return SToBool(this->getPerspectiveTypeMaskOnly() & kPerspective_Mask);
274 }
275
276 /**
277 * @brief Checks if the matrix contains only translation, rotation/reflection, or uniform scale.
278 * Returns false if other transformation types are included or if the matrix is degenerate.
279 * @param tol Tolerance for floating-point comparison (default is SK_ScalarNearlyZero).
280 * @return True if the matrix is a similarity transform, false otherwise.
281 */
282 bool isSimilarity(float tol = SK_ScalarNearlyZero) const;
283
284 /**
285 * @brief Checks if the matrix contains only translation, rotation/reflection, or scale (non-uniform scale is allowed).
286 * Returns false if other transformation types are included or if the matrix is degenerate.
287 * @param tol Tolerance for floating-point comparison (default is SK_ScalarNearlyZero).
288 * @return True if the matrix preserves right angles, false otherwise.
289 */
290 bool preservesRightAngles(float tol = SK_ScalarNearlyZero) const;
291
292 /**
293 * @brief Enum for affine array indices.
294 * Affine arrays are in column major order because that's how PDF and XPS like it.
295 */
296 enum
297 {
298 kAScaleX,
299 kASkewY,
300 kASkewX,
301 kAScaleY,
302 kATransX,
303 kATransY
304 };
305
306 /**
307 * @brief Accesses the matrix element at the specified index.
308 * @param index Index of the matrix element.
309 * @return Matrix element value.
310 */
311 float operator[](int index) const
312 {
313 SASSERT((unsigned)index < 9);
314 return fMat[index];
315 }
316
317 /**
318 * @brief Accesses the matrix element at the specified index.
319 * @param index Index of the matrix element.
320 * @return Matrix element value.
321 */
322 float get(int index) const
323 {
324 SASSERT((unsigned)index < 9);
325 return fMat[index];
326 }
327
328 /**
329 * @brief Accesses the matrix element at the specified index.
330 * @param index Index of the matrix element.
331 * @return Reference to the matrix element.
332 */
333 float &operator[](int index)
334 {
335 SASSERT((unsigned)index < 9);
336 this->setTypeMask(kUnknown_Mask);
337 return fMat[index];
338 }
339
340 /**
341 * @brief Sets the matrix element at the specified index.
342 * @param index Index of the matrix element.
343 * @param value New value for the matrix element.
344 */
345 void set(int index, float value)
346 {
347 SASSERT((unsigned)index < 9);
348 fMat[index] = value;
349 this->setTypeMask(kUnknown_Mask);
350 }
351
352 /**
353 * @brief Sets the matrix to the specified data array.
354 * @param data Array of 9 floats representing the matrix elements.
355 * @param matType Type mask for the matrix (default is kUnknown_Mask).
356 */
357 void setMatrix(const float data[9], int matType = kUnknown_Mask);
358
359 /**
360 * @brief Sets the matrix to a translation.
361 * @param v Translation vector.
362 */
363 void setTranslate(const SVector2D &v)
364 {
365 this->setTranslate(v.fX, v.fY);
366 }
367
368 /**
369 * @brief Sets the matrix to scale by 1/divx and 1/divy.
370 * @param divx Division factor in the x-direction.
371 * @param divy Division factor in the y-direction.
372 * @return True if successful, false if either divx or divy is zero.
373 */
374 bool setIDiv(int divx, int divy);
375
376 /**
377 * @brief Sets the matrix to rotate by the specified sine and cosine values, with a pivot point at (px, py).
378 * @param sinValue Sine of the rotation angle.
379 * @param cosValue Cosine of the rotation angle.
380 * @param px Pivot point x-coordinate.
381 * @param py Pivot point y-coordinate.
382 */
383 void setSinCos(float sinValue, float cosValue, float px, float py);
384
385 /**
386 * @brief Sets the matrix to rotate by the specified sine and cosine values.
387 * @param sinValue Sine of the rotation angle.
388 * @param cosValue Cosine of the rotation angle.
389 */
390 void setSinCos(float sinValue, float cosValue);
391
392 /**
393 * @brief Sets the matrix to the concatenation of the two specified matrices.
394 * @param a First matrix.
395 * @param b Second matrix.
396 */
397 void setConcat(const SMatrix &a, const SMatrix &b);
398
399 /**
400 * @brief Pre-concats the matrix with the specified translation.
401 * @param dx Translation in the x-direction.
402 * @param dy Translation in the y-direction.
403 */
404 void preTranslate(float dx, float dy);
405
406 /**
407 * @brief Pre-concats the matrix with the specified translation.
408 * @param dx Translation in the x-direction.
409 * @param dy Translation in the y-direction.
410 */
411 void preTranslate(int dx, int dy);
412
413 /**
414 * @brief Pre-concats the matrix with the specified scale.
415 * @param sx Scale factor in the x-direction.
416 * @param sy Scale factor in the y-direction.
417 * @param px Pivot point x-coordinate.
418 * @param py Pivot point y-coordinate.
419 */
420 void preScale(float sx, float sy, float px, float py);
421
422 /**
423 * @brief Pre-concats the matrix with the specified scale.
424 * @param sx Scale factor in the x-direction.
425 * @param sy Scale factor in the y-direction.
426 */
427 void preScale(float sx, float sy);
428
429 /**
430 * @brief Pre-concats the matrix with the specified rotation.
431 * @param degrees Rotation angle in degrees.
432 * @param px Pivot point x-coordinate.
433 * @param py Pivot point y-coordinate.
434 */
435 void preRotate(float degrees, float px, float py);
436
437 /**
438 * @brief Pre-concats the matrix with the specified rotation.
439 * @param degrees Rotation angle in degrees.
440 */
441 void preRotate(float degrees);
442
443 /**
444 * @brief Pre-concats the matrix with the specified skew.
445 * @param kx Skew factor in the x-direction.
446 * @param ky Skew factor in the y-direction.
447 * @param px Pivot point x-coordinate.
448 * @param py Pivot point y-coordinate.
449 */
450 void preSkew(float kx, float ky, float px, float py);
451
452 /**
453 * @brief Pre-concats the matrix with the specified skew.
454 * @param kx Skew factor in the x-direction.
455 * @param ky Skew factor in the y-direction.
456 */
457 void preSkew(float kx, float ky);
458
459 /**
460 * @brief Pre-concats the matrix with the specified matrix.
461 * @param other Matrix to pre-concatenate.
462 */
463 void preConcat(const SMatrix &other);
464
465 /**
466 * @brief Post-concats the matrix with the specified translation.
467 * @param dx Translation in the x-direction.
468 * @param dy Translation in the y-direction.
469 */
470 void postTranslate(float dx, float dy);
471
472 /**
473 * @brief Post-concats the matrix with the specified translation.
474 * @param dx Translation in the x-direction.
475 * @param dy Translation in the y-direction.
476 */
477 void postTranslate(int dx, int dy);
478
479 /**
480 * @brief Post-concats the matrix with the specified scale.
481 * @param sx Scale factor in the x-direction.
482 * @param sy Scale factor in the y-direction.
483 * @param px Pivot point x-coordinate.
484 * @param py Pivot point y-coordinate.
485 */
486 void postScale(float sx, float sy, float px, float py);
487
488 /**
489 * @brief Post-concats the matrix with the specified scale.
490 * @param sx Scale factor in the x-direction.
491 * @param sy Scale factor in the y-direction.
492 */
493 void postScale(float sx, float sy);
494
495 /**
496 * @brief Post-concats the matrix by dividing it by the specified integers.
497 * @param divx Division factor in the x-direction.
498 * @param divy Division factor in the y-direction.
499 * @return True if successful, false if either divx or divy is zero.
500 */
501 bool postIDiv(int divx, int divy);
502
503 /**
504 * @brief Post-concats the matrix with the specified rotation.
505 * @param degrees Rotation angle in degrees.
506 * @param px Pivot point x-coordinate.
507 * @param py Pivot point y-coordinate.
508 */
509 void postRotate(float degrees, float px, float py);
510
511 /**
512 * @brief Post-concats the matrix with the specified rotation.
513 * @param degrees Rotation angle in degrees.
514 */
515 void postRotate(float degrees);
516
517 /**
518 * @brief Post-concats the matrix with the specified skew.
519 * @param kx Skew factor in the x-direction.
520 * @param ky Skew factor in the y-direction.
521 * @param px Pivot point x-coordinate.
522 * @param py Pivot point y-coordinate.
523 */
524 void postSkew(float kx, float ky, float px, float py);
525
526 /**
527 * @brief Post-concats the matrix with the specified skew.
528 * @param kx Skew factor in the x-direction.
529 * @param ky Skew factor in the y-direction.
530 */
531 void postSkew(float kx, float ky);
532
533 /**
534 * @brief Post-concats the matrix with the specified matrix.
535 * @param other Matrix to post-concatenate.
536 */
537 void postConcat(const SMatrix &other);
538
539 /**
540 * @enum ScaleToFit
541 * @brief Enum for scale-to-fit options.
542 */
544 {
545 /**
546 * Scale in X and Y independently, so that src matches dst exactly.
547 * This may change the aspect ratio of the src.
548 */
550 /**
551 * Compute a scale that will maintain the original src aspect ratio,
552 * but will also ensure that src fits entirely inside dst. At least one
553 * axis (X or Y) will fit exactly. kStart aligns the result to the
554 * left and top edges of dst.
555 */
557 /**
558 * Compute a scale that will maintain the original src aspect ratio,
559 * but will also ensure that src fits entirely inside dst. At least one
560 * axis (X or Y) will fit exactly. The result is centered inside dst.
561 */
563 /**
564 * Compute a scale that will maintain the original src aspect ratio,
565 * but will also ensure that src fits entirely inside dst. At least one
566 * axis (X or Y) will fit exactly. kEnd aligns the result to the
567 * right and bottom edges of dst.
568 */
570 };
571
572 /**
573 * @brief Set the matrix to the scale and translate values that map the source
574 * rectangle to the destination rectangle, returning true if the result
575 * can be represented.
576 * @param src Source rectangle to map from.
577 * @param dst Destination rectangle to map to.
578 * @param stf ScaleToFit option.
579 * @return True if the matrix can be represented by the rectangle mapping.
580 */
581 bool setRectToRect(const SRect &src, const SRect &dst, ScaleToFit stf);
582
583 /**
584 * @brief Set the matrix such that the specified src points would map to the
585 * specified dst points. count must be within [0..4].
586 * @param src Array of source points.
587 * @param dst Array of destination points.
588 * @param count Number of points to use for the transformation.
589 * @return True if the matrix was set to the specified transformation.
590 */
591 bool setPolyToPoly(const SPoint src[], const SPoint dst[], int count);
592
593 /**
594 * @brief If this matrix can be inverted, return true and if inverse is not null,
595 * set inverse to be the inverse of this matrix. If this matrix cannot be
596 * inverted, ignore inverse and return false.
597 * @param inverse Pointer to the matrix to store the inverse.
598 * @return True if the matrix can be inverted, false otherwise.
599 */
600 bool invert(SMatrix *inverse) const
601 {
602 // Allow the trivial case to be inlined.
603 if (this->isIdentity())
604 {
605 if (inverse)
606 {
607 inverse->reset();
608 }
609 return true;
610 }
611 return this->invertNonIdentity(inverse);
612 }
613
614 /**
615 * @brief Fills the passed array with affine identity values in column major order.
616 * @param affine Array to fill with affine identity values. Must not be NULL.
617 */
618 static void SetAffineIdentity(float affine[6]);
619
620 /**
621 * @brief Fills the passed array with the affine values in column major order.
622 * If the matrix is a perspective transform, returns false and does not
623 * change the passed array.
624 * @param affine Array to fill with affine values. Ignored if NULL.
625 * @return True if the matrix is affine, false otherwise.
626 */
627 bool asAffine(float affine[6]) const;
628
629 /**
630 * @brief Apply this matrix to the array of points specified by src, and write
631 * the transformed points into the array of points specified by dst.
632 * dst[] = M * src[]
633 * @param dst Where the transformed coordinates are written. It must contain at least count entries.
634 * @param src The original coordinates that are to be transformed. It must contain at least count entries.
635 * @param count The number of points in src to read, and then transform into dst.
636 */
637 void mapPoints(SPoint dst[], const SPoint src[], int count) const;
638
639 /**
640 * @brief Apply this matrix to the array of points, overwriting it with the
641 * transformed values.
642 * dst[] = M * pts[]
643 * @param pts The points to be transformed. It must contain at least count entries.
644 * @param count The number of points in pts.
645 */
646 void mapPoints(SPoint pts[], int count) const
647 {
648 this->mapPoints(pts, pts, count);
649 }
650
651 /**
652 * @brief Like mapPoints but with custom byte stride between the points. Stride
653 * should be a multiple of sizeof(float).
654 * @param pts Array of points to transform.
655 * @param stride Byte stride between points.
656 * @param count Number of points to transform.
657 */
658 void mapPointsWithStride(SPoint pts[], size_t stride, int count) const
659 {
660 SASSERT(stride >= sizeof(SPoint));
661 SASSERT(0 == stride % sizeof(float));
662 for (int i = 0; i < count; ++i)
663 {
664 this->mapPoints(pts, pts, 1);
665 pts = (SPoint *)((intptr_t)pts + stride);
666 }
667 }
668
669 /**
670 * @brief Like mapPoints but with custom byte stride between the points.
671 * @param dst Array of transformed points.
672 * @param src Array of original points.
673 * @param stride Byte stride between points.
674 * @param count Number of points to transform.
675 */
676 void mapPointsWithStride(SPoint dst[], SPoint src[], size_t stride, int count) const
677 {
678 SASSERT(stride >= sizeof(SPoint));
679 SASSERT(0 == stride % sizeof(float));
680 for (int i = 0; i < count; ++i)
681 {
682 this->mapPoints(dst, src, 1);
683 src = (SPoint *)((intptr_t)src + stride);
684 dst = (SPoint *)((intptr_t)dst + stride);
685 }
686 }
687
688 /**
689 * @brief Apply this matrix to the array of homogeneous points, specified by src,
690 * where a homogeneous point is defined by 3 contiguous scalar values,
691 * and write the transformed points into the array of scalars specified by dst.
692 * dst[] = M * src[]
693 * @param dst Where the transformed coordinates are written. It must contain at least 3 * count entries.
694 * @param src The original coordinates that are to be transformed. It must contain at least 3 * count entries.
695 * @param count The number of triples (homogeneous points) in src to read, and then transform into dst.
696 */
697 void mapHomogeneousPoints(float dst[], const float src[], int count) const;
698
699 /**
700 * @brief Apply this matrix to the point (x, y) and store the result in *result.
701 * @param x X-coordinate of the point.
702 * @param y Y-coordinate of the point.
703 * @param result Pointer to store the transformed point.
704 */
705 void mapXY(float x, float y, SPoint *result) const
706 {
707 SASSERT(result);
708 this->getMapXYProc()(*this, x, y, result);
709 }
710
711 /**
712 * @brief Apply this matrix to the array of vectors specified by src, and write
713 * the transformed vectors into the array of vectors specified by dst.
714 * This is similar to mapPoints, but ignores any translation in the matrix.
715 * @param dst Where the transformed coordinates are written. It must contain at least count entries.
716 * @param src The original coordinates that are to be transformed. It must contain at least count entries.
717 * @param count The number of vectors in src to read, and then transform into dst.
718 */
719 void mapVectors(SVector2D dst[], const SVector2D src[], int count) const;
720
721 /**
722 * @brief Apply this matrix to the array of vectors specified by src, and write
723 * the transformed vectors into the array of vectors specified by dst.
724 * This is similar to mapPoints, but ignores any translation in the matrix.
725 * @param vecs The vectors to be transformed. It must contain at least count entries.
726 * @param count The number of vectors in vecs.
727 */
728 void mapVectors(SVector2D vecs[], int count) const
729 {
730 this->mapVectors(vecs, vecs, count);
731 }
732
733 /**
734 * @brief Apply this matrix to the src rectangle, and write the transformed
735 * rectangle into dst. This is accomplished by transforming the 4 corners
736 * of src, and then setting dst to the bounds of those points.
737 * @param dst Where the transformed rectangle is written.
738 * @param src The original rectangle to be transformed.
739 * @return The result of calling rectStaysRect().
740 */
741 bool mapRect(SRect *dst, const SRect &src) const;
742
743 /**
744 * @brief Apply this matrix to the rectangle, and write the transformed rectangle
745 * back into it. This is accomplished by transforming the 4 corners of
746 * rect, and then setting it to the bounds of those points.
747 * @param rect The rectangle to transform.
748 * @return The result of calling rectStaysRect().
749 */
750 bool mapRect(SRect *rect) const
751 {
752 return this->mapRect(rect, *rect);
753 }
754
755 /**
756 * @brief Apply this matrix to the src rectangle, and write the four transformed
757 * points into dst. The points written to dst will be the original top-left, top-right,
758 * bottom-right, and bottom-left points transformed by the matrix.
759 * @param dst Where the transformed quad is written.
760 * @param rect The original rectangle to be transformed.
761 */
762 void mapRectToQuad(SPoint dst[4], const SRect &rect) const
763 {
764 // This could potentially be faster if we only transformed each x and y of the rect once.
765 rect.toQuad(dst);
766 this->mapPoints(dst, 4);
767 }
768
769 /**
770 * @brief Return the mean radius of a circle after it has been mapped by
771 * this matrix. NOTE: in perspective this value assumes the circle
772 * has its center at the origin.
773 * @param radius Original radius of the circle.
774 * @return Mapped radius of the circle.
775 */
776 float mapRadius(float radius) const;
777
778 /**
779 * @typedef MapXYProc
780 * @brief Function pointer type for mapping a single point (x, y) to a transformed point.
781 */
782 typedef void (*MapXYProc)(const SMatrix &mat, float x, float y, SPoint *result);
783
784 /**
785 * @brief Get the appropriate MapXYProc for the given type mask.
786 * @param mask Type mask of the matrix.
787 * @return Pointer to the MapXYProc function.
788 */
790 {
791 SASSERT((mask & ~kAllMasks) == 0);
792 return gMapXYProcs[mask & kAllMasks];
793 }
794
795 /**
796 * @brief Get the appropriate MapXYProc for this matrix.
797 * @return Pointer to the MapXYProc function.
798 */
800 {
801 return GetMapXYProc(this->getType());
802 }
803
804 /**
805 * @typedef MapPtsProc
806 * @brief Function pointer type for mapping an array of points.
807 */
808 typedef void (*MapPtsProc)(const SMatrix &mat, SPoint dst[], const SPoint src[], int count);
809
810 /**
811 * @brief Get the appropriate MapPtsProc for the given type mask.
812 * @param mask Type mask of the matrix.
813 * @return Pointer to the MapPtsProc function.
814 */
816 {
817 SASSERT((mask & ~kAllMasks) == 0);
818 return gMapPtsProcs[mask & kAllMasks];
819 }
820
821 /**
822 * @brief Get the appropriate MapPtsProc for this matrix.
823 * @return Pointer to the MapPtsProc function.
824 */
826 {
827 return GetMapPtsProc(this->getType());
828 }
829
830 /**
831 * @brief Efficient comparison of two matrices. It distinguishes between zero and
832 * negative zero. It will return false when the sign of zero values is the
833 * only difference between the two matrices. It considers NaN values to be
834 * equal to themselves. So a matrix full of NaNs is "cheap equal" to
835 * another matrix full of NaNs iff the NaN values are bitwise identical
836 * while according to strict the strict == test a matrix with a NaN value
837 * is equal to nothing, including itself.
838 * @param m Matrix to compare with.
839 * @return True if matrices are cheaply equal, false otherwise.
840 */
841 bool cheapEqualTo(const SMatrix &m) const
842 {
843 return 0 == memcmp(fMat, m.fMat, sizeof(fMat));
844 }
845
846 enum
847 {
848 // writeTo/readFromMemory will never return a value larger than this
849 kMaxFlattenSize = 9 * sizeof(float) + sizeof(uint32_t)
850 };
851
852 /**
853 * @brief Calculates the minimum scaling factor of the matrix as computed from the SVD of the upper
854 * left 2x2. If the matrix has perspective -1 is returned.
855 * @return Minimum scale factor.
856 */
857 float getMinScale() const;
858
859 /**
860 * @brief Calculates the maximum scaling factor of the matrix as computed from the SVD of the upper
861 * left 2x2. If the matrix has perspective -1 is returned.
862 * @return Maximum scale factor.
863 */
864 float getMaxScale() const;
865
866 /**
867 * @brief Gets both the min and max scale factors. The min scale factor is scaleFactors[0] and the max
868 * is scaleFactors[1]. If the matrix has perspective false will be returned and scaleFactors
869 * will be unchanged.
870 * @param scaleFactors Array to store the min and max scale factors.
871 * @return True if the matrix does not have perspective, false otherwise.
872 */
873 bool getMinMaxScales(float scaleFactors[2]) const;
874
875 /**
876 * @brief Return a reference to a const identity matrix.
877 * @return Reference to the identity matrix.
878 */
879 static const SMatrix &I();
880
881 /**
882 * @brief Return a reference to a const matrix that is "invalid", one that could
883 * never be used.
884 * @return Reference to the invalid matrix.
885 */
886 static const SMatrix &InvalidMatrix();
887
888 /**
889 * @brief Return the concatenation of two matrices, a * b.
890 * @param a First matrix.
891 * @param b Second matrix.
892 * @return Resulting matrix.
893 */
894 static SMatrix Concat(const SMatrix &a, const SMatrix &b)
895 {
896 SMatrix result;
897 result.setConcat(a, b);
898 return result;
899 }
900
901 /**
902 * @brief Testing routine; the matrix's type cache should never need to be
903 * manually invalidated during normal use.
904 */
906 {
907 this->setTypeMask(kUnknown_Mask);
908 }
909
910 private:
911 enum
912 {
913 /** Set if the matrix will map a rectangle to another rectangle. This
914 can be true if the matrix is scale-only, or rotates a multiple of
915 90 degrees.
916
917 This bit will be set on identity matrices
918 */
919 kRectStaysRect_Mask = 0x10,
920
921 /** Set if the perspective bit is valid even though the rest of
922 the matrix is Unknown.
923 */
924 kOnlyPerspectiveValid_Mask = 0x40,
925
926 kUnknown_Mask = 0x80,
927
928 kORableMasks = kTranslate_Mask | kScale_Mask | kAffine_Mask | kPerspective_Mask,
929
930 kAllMasks = kTranslate_Mask | kScale_Mask | kAffine_Mask | kPerspective_Mask | kRectStaysRect_Mask
931 };
932
933 mutable uint32_t fTypeMask;
934
935 uint8_t computeTypeMask() const;
936 uint8_t computePerspectiveTypeMask() const;
937
938 void setTypeMask(int mask);
939
940 void orTypeMask(int mask);
941
942 void clearTypeMask(int mask)
943 {
944 // only allow a valid mask
945 SASSERT((mask & kAllMasks) == mask);
946 fTypeMask = fTypeMask & ~mask;
947 }
948
949 TypeMask getPerspectiveTypeMaskOnly() const
950 {
951 if ((fTypeMask & kUnknown_Mask) && !(fTypeMask & kOnlyPerspectiveValid_Mask))
952 {
953 fTypeMask = this->computePerspectiveTypeMask();
954 }
955 return (TypeMask)(fTypeMask & 0xF);
956 }
957
958 /** Returns true if we already know that the matrix is identity;
959 false otherwise.
960 */
961 bool isTriviallyIdentity() const
962 {
963 if (fTypeMask & kUnknown_Mask)
964 {
965 return false;
966 }
967 return ((fTypeMask & 0xF) == 0);
968 }
969
970 bool invertNonIdentity(SMatrix *inverse) const;
971
972 static bool Poly2Proc(const SPoint[], SMatrix *, const SPoint &scale);
973 static bool Poly3Proc(const SPoint[], SMatrix *, const SPoint &scale);
974 static bool Poly4Proc(const SPoint[], SMatrix *, const SPoint &scale);
975
976 static void Identity_xy(const SMatrix &, float, float, SPoint *);
977 static void Trans_xy(const SMatrix &, float, float, SPoint *);
978 static void Scale_xy(const SMatrix &, float, float, SPoint *);
979 static void ScaleTrans_xy(const SMatrix &, float, float, SPoint *);
980 static void Rot_xy(const SMatrix &, float, float, SPoint *);
981 static void RotTrans_xy(const SMatrix &, float, float, SPoint *);
982 static void Persp_xy(const SMatrix &, float, float, SPoint *);
983
984 static const MapXYProc gMapXYProcs[];
985
986 static void Identity_pts(const SMatrix &, SPoint[], const SPoint[], int);
987 static void Trans_pts(const SMatrix &, SPoint dst[], const SPoint[], int);
988 static void Scale_pts(const SMatrix &, SPoint dst[], const SPoint[], int);
989 static void ScaleTrans_pts(const SMatrix &, SPoint dst[], const SPoint[], int count);
990 static void Rot_pts(const SMatrix &, SPoint dst[], const SPoint[], int);
991 static void RotTrans_pts(const SMatrix &, SPoint dst[], const SPoint[], int count);
992 static void Persp_pts(const SMatrix &, SPoint dst[], const SPoint[], int);
993 static const MapPtsProc gMapPtsProcs[];
994
995 friend class SkPerspIter;
996
997 public:
998 static float SFloatSinCos(float radians, float *cosValue);
999};
1000
1001SNSEND
1002#endif
The SMatrix class holds a 3x3 matrix for transforming coordinates. SMatrix does not have a constructo...
Definition SMatrix.h:22
float get(int index) const
Accesses the matrix element at the specified index.
Definition SMatrix.h:322
void postRotate(float degrees, float px, float py)
Post-concats the matrix with the specified rotation.
Definition SMatrix.cpp:541
void mapPointsWithStride(SPoint dst[], SPoint src[], size_t stride, int count) const
Like mapPoints but with custom byte stride between the points.
Definition SMatrix.h:676
bool invert(SMatrix *inverse) const
If this matrix can be inverted, return true and if inverse is not null, set inverse to be the inverse...
Definition SMatrix.h:600
void postTranslate(float dx, float dy)
Post-concats the matrix with the specified translation.
Definition SMatrix.cpp:300
float & operator[](int index)
Accesses the matrix element at the specified index.
Definition SMatrix.h:333
void mapRectToQuad(SPoint dst[4], const SRect &rect) const
Apply this matrix to the src rectangle, and write the four transformed points into dst....
Definition SMatrix.h:762
void mapPoints(SPoint dst[], const SPoint src[], int count) const
Apply this matrix to the array of points specified by src, and write the transformed points into the ...
Definition SMatrix.cpp:1135
bool hasPerspective() const
Checks if the matrix contains perspective elements.
Definition SMatrix.h:271
SMatrix & rotate(float deg)
Post-concats the matrix with a rotation.
Definition SMatrix.h:121
static MapPtsProc GetMapPtsProc(TypeMask mask)
Get the appropriate MapPtsProc for the given type mask.
Definition SMatrix.h:815
bool mapRect(SRect *dst, const SRect &src) const
Apply this matrix to the src rectangle, and write the transformed rectangle into dst....
Definition SMatrix.cpp:1216
void reset() OVERRIDE
Resets the matrix to the identity matrix.
Definition SMatrix.cpp:46
void mapVectors(SVector2D vecs[], int count) const
Apply this matrix to the array of vectors specified by src, and write the transformed vectors into th...
Definition SMatrix.h:728
bool isScaleTranslate() const
Checks if the matrix contains only scale and translation.
Definition SMatrix.h:239
bool mapRect(SRect *rect) const
Apply this matrix to the rectangle, and write the transformed rectangle back into it....
Definition SMatrix.h:750
SMatrix & shear(float sh, float sv)
Post-concats the matrix with a shear.
Definition SMatrix.h:110
TypeMask getType() const
Returns a bitfield describing the transformations the matrix may perform. The bitfield is computed co...
Definition SMatrix.h:225
friend bool operator!=(const SMatrix &a, const SMatrix &b)
Inequality operator.
Definition SMatrix.h:74
MapPtsProc getMapPtsProc() const
Get the appropriate MapPtsProc for this matrix.
Definition SMatrix.h:825
void setConcat(const SMatrix &a, const SMatrix &b)
Sets the matrix to the concatenation of the two specified matrices.
Definition SMatrix.cpp:724
bool cheapEqualTo(const SMatrix &m) const
Efficient comparison of two matrices. It distinguishes between zero and negative zero....
Definition SMatrix.h:841
bool rectStaysRect() const
Returns true if the matrix will map a rectangle to another rectangle. This can be true if the matrix ...
Definition SMatrix.h:249
ScaleToFit
Enum for scale-to-fit options.
Definition SMatrix.h:544
@ kEnd_ScaleToFit
Definition SMatrix.h:569
@ kFill_ScaleToFit
Definition SMatrix.h:549
@ kCenter_ScaleToFit
Definition SMatrix.h:562
@ kStart_ScaleToFit
Definition SMatrix.h:556
bool preservesAxisAlignment() const
Alias for rectStaysRect().
Definition SMatrix.h:262
void setTranslate(const SVector2D &v)
Sets the matrix to a translation.
Definition SMatrix.h:363
SMatrix & scale(float sx, float sy)
Post-concats the matrix with a scale.
Definition SMatrix.h:98
BOOL isIdentity() SCONST OVERRIDE
Checks if the matrix is the identity matrix.
Definition SMatrix.cpp:1777
void postSkew(float kx, float ky, float px, float py)
Post-concats the matrix with the specified skew.
Definition SMatrix.cpp:603
void mapPointsWithStride(SPoint pts[], size_t stride, int count) const
Like mapPoints but with custom byte stride between the points. Stride should be a multiple of sizeof(...
Definition SMatrix.h:658
void setTranslate(float dx, float dy) OVERRIDE
Sets the matrix to a translation.
Definition SMatrix.cpp:256
SMatrix & translate(float dx, float dy)
Post-concats the matrix with a translation.
Definition SMatrix.h:86
static MapXYProc GetMapXYProc(TypeMask mask)
Get the appropriate MapXYProc for the given type mask.
Definition SMatrix.h:789
MapXYProc getMapXYProc() const
Get the appropriate MapXYProc for this matrix.
Definition SMatrix.h:799
void postScale(float sx, float sy, float px, float py)
Post-concats the matrix with the specified scale.
Definition SMatrix.cpp:411
float operator[](int index) const
Accesses the matrix element at the specified index.
Definition SMatrix.h:311
TypeMask
Enum of bit fields for the mask returned by getType(). Use this to identify the complexity of the mat...
Definition SMatrix.h:210
@ kAffine_Mask
Set if the matrix skews or rotates.
Definition SMatrix.h:214
@ kPerspective_Mask
Set if the matrix is in perspective.
Definition SMatrix.h:215
@ kScale_Mask
Set if the matrix has X or Y scale.
Definition SMatrix.h:213
@ kIdentity_Mask
Set if the matrix is identity.
Definition SMatrix.h:211
@ kTranslate_Mask
Set if the matrix has translation.
Definition SMatrix.h:212
void(* MapXYProc)(const SMatrix &mat, float x, float y, SPoint *result)
Function pointer type for mapping a single point (x, y) to a transformed point.
Definition SMatrix.h:782
void mapVectors(SVector2D dst[], const SVector2D src[], int count) const
Apply this matrix to the array of vectors specified by src, and write the transformed vectors into th...
Definition SMatrix.cpp:1189
void(* MapPtsProc)(const SMatrix &mat, SPoint dst[], const SPoint src[], int count)
Function pointer type for mapping an array of points.
Definition SMatrix.h:808
SMatrix()
Default constructor, initializes the matrix to identity.
Definition SMatrix.h:27
void dirtyMatrixTypeCache()
Testing routine; the matrix's type cache should never need to be manually invalidated during normal u...
Definition SMatrix.h:905
void set(int index, float value)
Sets the matrix element at the specified index.
Definition SMatrix.h:345
static SMatrix Concat(const SMatrix &a, const SMatrix &b)
Return the concatenation of two matrices, a * b.
Definition SMatrix.h:894
void mapPoints(SPoint pts[], int count) const
Apply this matrix to the array of points, overwriting it with the transformed values....
Definition SMatrix.h:646
void mapXY(float x, float y, SPoint *result) const
Apply this matrix to the point (x, y) and store the result in *result.
Definition SMatrix.h:705
float fMat[kMCount]
Array of floats representing the matrix elements.
Definition SRender-i.h:975