1
2/*
3 * Copyright 2006 The Android Open Source Project
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9
10#ifndef SkMatrix_DEFINED
11#define SkMatrix_DEFINED
12
13#include "SkRect.h"
14
15struct SkRSXform;
16class SkString;
17
18/** \class SkMatrix
19
20    The SkMatrix class holds a 3x3 matrix for transforming coordinates.
21    SkMatrix does not have a constructor, so it must be explicitly initialized
22    using either reset() - to construct an identity matrix, or one of the set
23    functions (e.g. setTranslate, setRotate, etc.).
24
25    SkMatrix is not thread safe unless you've first called SkMatrix::getType().
26*/
27SK_BEGIN_REQUIRE_DENSE
28class SK_API SkMatrix {
29public:
30    static SkMatrix SK_WARN_UNUSED_RESULT MakeScale(SkScalar sx, SkScalar sy) {
31        SkMatrix m;
32        m.setScale(sx, sy);
33        return m;
34    }
35
36    static SkMatrix SK_WARN_UNUSED_RESULT MakeScale(SkScalar scale) {
37        SkMatrix m;
38        m.setScale(scale, scale);
39        return m;
40    }
41
42    static SkMatrix SK_WARN_UNUSED_RESULT MakeTrans(SkScalar dx, SkScalar dy) {
43        SkMatrix m;
44        m.setTranslate(dx, dy);
45        return m;
46    }
47
48    /** Enum of bit fields for the mask return by getType().
49        Use this to identify the complexity of the matrix.
50    */
51    enum TypeMask {
52        kIdentity_Mask      = 0,
53        kTranslate_Mask     = 0x01,  //!< set if the matrix has translation
54        kScale_Mask         = 0x02,  //!< set if the matrix has X or Y scale
55        kAffine_Mask        = 0x04,  //!< set if the matrix skews or rotates
56        kPerspective_Mask   = 0x08   //!< set if the matrix is in perspective
57    };
58
59    /** Returns a bitfield describing the transformations the matrix may
60        perform. The bitfield is computed conservatively, so it may include
61        false positives. For example, when kPerspective_Mask is true, all
62        other bits may be set to true even in the case of a pure perspective
63        transform.
64   */
65    TypeMask getType() const {
66        if (fTypeMask & kUnknown_Mask) {
67            fTypeMask = this->computeTypeMask();
68        }
69        // only return the public masks
70        return (TypeMask)(fTypeMask & 0xF);
71    }
72
73    /** Returns true if the matrix is identity.
74    */
75    bool isIdentity() const {
76        return this->getType() == 0;
77    }
78
79    bool isScaleTranslate() const {
80        return !(this->getType() & ~(kScale_Mask | kTranslate_Mask));
81    }
82
83    /** Returns true if will map a rectangle to another rectangle. This can be
84        true if the matrix is identity, scale-only, or rotates a multiple of
85        90 degrees, or mirrors in x or y.
86    */
87    bool rectStaysRect() const {
88        if (fTypeMask & kUnknown_Mask) {
89            fTypeMask = this->computeTypeMask();
90        }
91        return (fTypeMask & kRectStaysRect_Mask) != 0;
92    }
93    // alias for rectStaysRect()
94    bool preservesAxisAlignment() const { return this->rectStaysRect(); }
95
96    /**
97     *  Returns true if the matrix contains perspective elements.
98     */
99    bool hasPerspective() const {
100        return SkToBool(this->getPerspectiveTypeMaskOnly() &
101                        kPerspective_Mask);
102    }
103
104    /** Returns true if the matrix contains only translation, rotation/reflection or uniform scale
105        Returns false if other transformation types are included or is degenerate
106     */
107    bool isSimilarity(SkScalar tol = SK_ScalarNearlyZero) const;
108
109    /** Returns true if the matrix contains only translation, rotation/reflection or scale
110        (non-uniform scale is allowed).
111        Returns false if other transformation types are included or is degenerate
112     */
113    bool preservesRightAngles(SkScalar tol = SK_ScalarNearlyZero) const;
114
115    enum {
116        kMScaleX,
117        kMSkewX,
118        kMTransX,
119        kMSkewY,
120        kMScaleY,
121        kMTransY,
122        kMPersp0,
123        kMPersp1,
124        kMPersp2
125    };
126
127    /** Affine arrays are in column major order
128        because that's how PDF and XPS like it.
129     */
130    enum {
131        kAScaleX,
132        kASkewY,
133        kASkewX,
134        kAScaleY,
135        kATransX,
136        kATransY
137    };
138
139    SkScalar operator[](int index) const {
140        SkASSERT((unsigned)index < 9);
141        return fMat[index];
142    }
143
144    SkScalar get(int index) const {
145        SkASSERT((unsigned)index < 9);
146        return fMat[index];
147    }
148
149    SkScalar getScaleX() const { return fMat[kMScaleX]; }
150    SkScalar getScaleY() const { return fMat[kMScaleY]; }
151    SkScalar getSkewY() const { return fMat[kMSkewY]; }
152    SkScalar getSkewX() const { return fMat[kMSkewX]; }
153    SkScalar getTranslateX() const { return fMat[kMTransX]; }
154    SkScalar getTranslateY() const { return fMat[kMTransY]; }
155    SkScalar getPerspX() const { return fMat[kMPersp0]; }
156    SkScalar getPerspY() const { return fMat[kMPersp1]; }
157
158    SkScalar& operator[](int index) {
159        SkASSERT((unsigned)index < 9);
160        this->setTypeMask(kUnknown_Mask);
161        return fMat[index];
162    }
163
164    void set(int index, SkScalar value) {
165        SkASSERT((unsigned)index < 9);
166        fMat[index] = value;
167        this->setTypeMask(kUnknown_Mask);
168    }
169
170    void setScaleX(SkScalar v) { this->set(kMScaleX, v); }
171    void setScaleY(SkScalar v) { this->set(kMScaleY, v); }
172    void setSkewY(SkScalar v) { this->set(kMSkewY, v); }
173    void setSkewX(SkScalar v) { this->set(kMSkewX, v); }
174    void setTranslateX(SkScalar v) { this->set(kMTransX, v); }
175    void setTranslateY(SkScalar v) { this->set(kMTransY, v); }
176    void setPerspX(SkScalar v) { this->set(kMPersp0, v); }
177    void setPerspY(SkScalar v) { this->set(kMPersp1, v); }
178
179    void setAll(SkScalar scaleX, SkScalar skewX,  SkScalar transX,
180                SkScalar skewY,  SkScalar scaleY, SkScalar transY,
181                SkScalar persp0, SkScalar persp1, SkScalar persp2) {
182        fMat[kMScaleX] = scaleX;
183        fMat[kMSkewX]  = skewX;
184        fMat[kMTransX] = transX;
185        fMat[kMSkewY]  = skewY;
186        fMat[kMScaleY] = scaleY;
187        fMat[kMTransY] = transY;
188        fMat[kMPersp0] = persp0;
189        fMat[kMPersp1] = persp1;
190        fMat[kMPersp2] = persp2;
191        this->setTypeMask(kUnknown_Mask);
192    }
193
194    /**
195     *  Copy the 9 scalars for this matrix into buffer, in the same order as the kMScaleX
196     *  enum... scalex, skewx, transx, skewy, scaley, transy, persp0, persp1, persp2
197     */
198    void get9(SkScalar buffer[9]) const {
199        memcpy(buffer, fMat, 9 * sizeof(SkScalar));
200    }
201
202    /**
203     *  Set this matrix to the 9 scalars from the buffer, in the same order as the kMScaleX
204     *  enum... scalex, skewx, transx, skewy, scaley, transy, persp0, persp1, persp2
205     *
206     *  Note: calling set9 followed by get9 may not return the exact same values. Since the matrix
207     *  is used to map non-homogeneous coordinates, it is free to rescale the 9 values as needed.
208     */
209    void set9(const SkScalar buffer[9]);
210
211    /** Set the matrix to identity
212    */
213    void reset();
214    // alias for reset()
215    void setIdentity() { this->reset(); }
216
217    /** Set the matrix to translate by (dx, dy).
218    */
219    void setTranslate(SkScalar dx, SkScalar dy);
220    void setTranslate(const SkVector& v) { this->setTranslate(v.fX, v.fY); }
221
222    /** Set the matrix to scale by sx and sy, with a pivot point at (px, py).
223        The pivot point is the coordinate that should remain unchanged by the
224        specified transformation.
225    */
226    void setScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py);
227    /** Set the matrix to scale by sx and sy.
228    */
229    void setScale(SkScalar sx, SkScalar sy);
230    /** Set the matrix to scale by 1/divx and 1/divy. Returns false and doesn't
231        touch the matrix if either divx or divy is zero.
232    */
233    bool setIDiv(int divx, int divy);
234    /** Set the matrix to rotate by the specified number of degrees, with a
235        pivot point at (px, py). The pivot point is the coordinate that should
236        remain unchanged by the specified transformation.
237    */
238    void setRotate(SkScalar degrees, SkScalar px, SkScalar py);
239    /** Set the matrix to rotate about (0,0) by the specified number of degrees.
240    */
241    void setRotate(SkScalar degrees);
242    /** Set the matrix to rotate by the specified sine and cosine values, with
243        a pivot point at (px, py). The pivot point is the coordinate that
244        should remain unchanged by the specified transformation.
245    */
246    void setSinCos(SkScalar sinValue, SkScalar cosValue,
247                   SkScalar px, SkScalar py);
248    /** Set the matrix to rotate by the specified sine and cosine values.
249    */
250    void setSinCos(SkScalar sinValue, SkScalar cosValue);
251
252    SkMatrix& setRSXform(const SkRSXform&);
253
254    /** Set the matrix to skew by sx and sy, with a pivot point at (px, py).
255        The pivot point is the coordinate that should remain unchanged by the
256        specified transformation.
257    */
258    void setSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py);
259    /** Set the matrix to skew by sx and sy.
260    */
261    void setSkew(SkScalar kx, SkScalar ky);
262    /** Set the matrix to the concatenation of the two specified matrices.
263        Either of the two matrices may also be the target matrix.
264        *this = a * b;
265    */
266    void setConcat(const SkMatrix& a, const SkMatrix& b);
267
268    /** Preconcats the matrix with the specified translation.
269        M' = M * T(dx, dy)
270    */
271    void preTranslate(SkScalar dx, SkScalar dy);
272    /** Preconcats the matrix with the specified scale.
273        M' = M * S(sx, sy, px, py)
274    */
275    void preScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py);
276    /** Preconcats the matrix with the specified scale.
277        M' = M * S(sx, sy)
278    */
279    void preScale(SkScalar sx, SkScalar sy);
280    /** Preconcats the matrix with the specified rotation.
281        M' = M * R(degrees, px, py)
282    */
283    void preRotate(SkScalar degrees, SkScalar px, SkScalar py);
284    /** Preconcats the matrix with the specified rotation.
285        M' = M * R(degrees)
286    */
287    void preRotate(SkScalar degrees);
288    /** Preconcats the matrix with the specified skew.
289        M' = M * K(kx, ky, px, py)
290    */
291    void preSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py);
292    /** Preconcats the matrix with the specified skew.
293        M' = M * K(kx, ky)
294    */
295    void preSkew(SkScalar kx, SkScalar ky);
296    /** Preconcats the matrix with the specified matrix.
297        M' = M * other
298    */
299    void preConcat(const SkMatrix& other);
300
301    /** Postconcats the matrix with the specified translation.
302        M' = T(dx, dy) * M
303    */
304    void postTranslate(SkScalar dx, SkScalar dy);
305    /** Postconcats the matrix with the specified scale.
306        M' = S(sx, sy, px, py) * M
307    */
308    void postScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py);
309    /** Postconcats the matrix with the specified scale.
310        M' = S(sx, sy) * M
311    */
312    void postScale(SkScalar sx, SkScalar sy);
313    /** Postconcats the matrix by dividing it by the specified integers.
314        M' = S(1/divx, 1/divy, 0, 0) * M
315    */
316    bool postIDiv(int divx, int divy);
317    /** Postconcats the matrix with the specified rotation.
318        M' = R(degrees, px, py) * M
319    */
320    void postRotate(SkScalar degrees, SkScalar px, SkScalar py);
321    /** Postconcats the matrix with the specified rotation.
322        M' = R(degrees) * M
323    */
324    void postRotate(SkScalar degrees);
325    /** Postconcats the matrix with the specified skew.
326        M' = K(kx, ky, px, py) * M
327    */
328    void postSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py);
329    /** Postconcats the matrix with the specified skew.
330        M' = K(kx, ky) * M
331    */
332    void postSkew(SkScalar kx, SkScalar ky);
333    /** Postconcats the matrix with the specified matrix.
334        M' = other * M
335    */
336    void postConcat(const SkMatrix& other);
337
338    enum ScaleToFit {
339        /**
340         * Scale in X and Y independently, so that src matches dst exactly.
341         * This may change the aspect ratio of the src.
342         */
343        kFill_ScaleToFit,
344        /**
345         * Compute a scale that will maintain the original src aspect ratio,
346         * but will also ensure that src fits entirely inside dst. At least one
347         * axis (X or Y) will fit exactly. kStart aligns the result to the
348         * left and top edges of dst.
349         */
350        kStart_ScaleToFit,
351        /**
352         * Compute a scale that will maintain the original src aspect ratio,
353         * but will also ensure that src fits entirely inside dst. At least one
354         * axis (X or Y) will fit exactly. The result is centered inside dst.
355         */
356        kCenter_ScaleToFit,
357        /**
358         * Compute a scale that will maintain the original src aspect ratio,
359         * but will also ensure that src fits entirely inside dst. At least one
360         * axis (X or Y) will fit exactly. kEnd aligns the result to the
361         * right and bottom edges of dst.
362         */
363        kEnd_ScaleToFit
364    };
365
366    /** Set the matrix to the scale and translate values that map the source
367        rectangle to the destination rectangle, returning true if the the result
368        can be represented.
369        @param src the source rectangle to map from.
370        @param dst the destination rectangle to map to.
371        @param stf the ScaleToFit option
372        @return true if the matrix can be represented by the rectangle mapping.
373    */
374    bool setRectToRect(const SkRect& src, const SkRect& dst, ScaleToFit stf);
375    static SkMatrix MakeRectToRect(const SkRect& src, const SkRect& dst, ScaleToFit stf) {
376        SkMatrix m;
377        m.setRectToRect(src, dst, stf);
378        return m;
379    }
380
381    /** Set the matrix such that the specified src points would map to the
382        specified dst points. count must be within [0..4].
383        @param src  The array of src points
384        @param dst  The array of dst points
385        @param count The number of points to use for the transformation
386        @return true if the matrix was set to the specified transformation
387    */
388    bool setPolyToPoly(const SkPoint src[], const SkPoint dst[], int count);
389
390    /** If this matrix can be inverted, return true and if inverse is not null,
391        set inverse to be the inverse of this matrix. If this matrix cannot be
392        inverted, ignore inverse and return false
393    */
394    bool SK_WARN_UNUSED_RESULT invert(SkMatrix* inverse) const {
395        // Allow the trivial case to be inlined.
396        if (this->isIdentity()) {
397            if (inverse) {
398                inverse->reset();
399            }
400            return true;
401        }
402        return this->invertNonIdentity(inverse);
403    }
404
405    /** Fills the passed array with affine identity values
406        in column major order.
407        @param affine  The array to fill with affine identity values.
408        Must not be NULL.
409    */
410    static void SetAffineIdentity(SkScalar affine[6]);
411
412    /** Fills the passed array with the affine values in column major order.
413        If the matrix is a perspective transform, returns false
414        and does not change the passed array.
415        @param affine  The array to fill with affine values. Ignored if NULL.
416    */
417    bool SK_WARN_UNUSED_RESULT asAffine(SkScalar affine[6]) const;
418
419    /** Set the matrix to the specified affine values.
420     *  Note: these are passed in column major order.
421     */
422    void setAffine(const SkScalar affine[6]);
423
424    /** Apply this matrix to the array of points specified by src, and write
425        the transformed points into the array of points specified by dst.
426        dst[] = M * src[]
427        @param dst  Where the transformed coordinates are written. It must
428                    contain at least count entries
429        @param src  The original coordinates that are to be transformed. It
430                    must contain at least count entries
431        @param count The number of points in src to read, and then transform
432                     into dst.
433    */
434    void mapPoints(SkPoint dst[], const SkPoint src[], int count) const {
435        SkASSERT((dst && src && count > 0) || 0 == count);
436        // no partial overlap
437        SkASSERT(src == dst || &dst[count] <= &src[0] || &src[count] <= &dst[0]);
438        this->getMapPtsProc()(*this, dst, src, count);
439    }
440
441    /** Apply this matrix to the array of points, overwriting it with the
442        transformed values.
443        dst[] = M * pts[]
444        @param pts  The points to be transformed. It must contain at least
445                    count entries
446        @param count The number of points in pts.
447    */
448    void mapPoints(SkPoint pts[], int count) const {
449        this->mapPoints(pts, pts, count);
450    }
451
452    /** Like mapPoints but with custom byte stride between the points. Stride
453     *  should be a multiple of sizeof(SkScalar).
454     */
455    void mapPointsWithStride(SkPoint pts[], size_t stride, int count) const {
456        SkASSERT(stride >= sizeof(SkPoint));
457        SkASSERT(0 == stride % sizeof(SkScalar));
458        for (int i = 0; i < count; ++i) {
459            this->mapPoints(pts, pts, 1);
460            pts = (SkPoint*)((intptr_t)pts + stride);
461        }
462    }
463
464    /** Like mapPoints but with custom byte stride between the points.
465    */
466    void mapPointsWithStride(SkPoint dst[], const SkPoint src[], size_t stride, int count) const {
467        SkASSERT(stride >= sizeof(SkPoint));
468        SkASSERT(0 == stride % sizeof(SkScalar));
469        for (int i = 0; i < count; ++i) {
470            this->mapPoints(dst, src, 1);
471            src = (SkPoint*)((intptr_t)src + stride);
472            dst = (SkPoint*)((intptr_t)dst + stride);
473        }
474    }
475
476    /** Apply this matrix to the array of homogeneous points, specified by src,
477        where a homogeneous point is defined by 3 contiguous scalar values,
478        and write the transformed points into the array of scalars specified by dst.
479        dst[] = M * src[]
480        @param dst  Where the transformed coordinates are written. It must
481                    contain at least 3 * count entries
482        @param src  The original coordinates that are to be transformed. It
483                    must contain at least 3 * count entries
484        @param count The number of triples (homogeneous points) in src to read,
485                     and then transform into dst.
486    */
487    void mapHomogeneousPoints(SkScalar dst[], const SkScalar src[], int count) const;
488
489    void mapXY(SkScalar x, SkScalar y, SkPoint* result) const {
490        SkASSERT(result);
491        this->getMapXYProc()(*this, x, y, result);
492    }
493
494    SkPoint mapXY(SkScalar x, SkScalar y) const {
495        SkPoint result;
496        this->getMapXYProc()(*this, x, y, &result);
497        return result;
498    }
499
500    /** Apply this matrix to the array of vectors specified by src, and write
501        the transformed vectors into the array of vectors specified by dst.
502        This is similar to mapPoints, but ignores any translation in the matrix.
503        @param dst  Where the transformed coordinates are written. It must
504                    contain at least count entries
505        @param src  The original coordinates that are to be transformed. It
506                    must contain at least count entries
507        @param count The number of vectors in src to read, and then transform
508                     into dst.
509    */
510    void mapVectors(SkVector dst[], const SkVector src[], int count) const;
511
512    /** Apply this matrix to the array of vectors specified by src, and write
513        the transformed vectors into the array of vectors specified by dst.
514        This is similar to mapPoints, but ignores any translation in the matrix.
515        @param vecs The vectors to be transformed. It must contain at least
516                    count entries
517        @param count The number of vectors in vecs.
518    */
519    void mapVectors(SkVector vecs[], int count) const {
520        this->mapVectors(vecs, vecs, count);
521    }
522
523    void mapVector(SkScalar dx, SkScalar dy, SkVector* result) const {
524        SkVector vec = { dx, dy };
525        this->mapVectors(result, &vec, 1);
526    }
527
528    SkVector mapVector(SkScalar dx, SkScalar dy) const {
529        SkVector vec = { dx, dy };
530        this->mapVectors(&vec, &vec, 1);
531        return vec;
532    }
533
534    /** Apply this matrix to the src rectangle, and write the transformed
535        rectangle into dst. This is accomplished by transforming the 4 corners
536        of src, and then setting dst to the bounds of those points.
537        @param dst  Where the transformed rectangle is written.
538        @param src  The original rectangle to be transformed.
539        @return the result of calling rectStaysRect()
540    */
541    bool mapRect(SkRect* dst, const SkRect& src) const;
542
543    /** Apply this matrix to the rectangle, and write the transformed rectangle
544        back into it. This is accomplished by transforming the 4 corners of
545        rect, and then setting it to the bounds of those points
546        @param rect The rectangle to transform.
547        @return the result of calling rectStaysRect()
548    */
549    bool mapRect(SkRect* rect) const {
550        return this->mapRect(rect, *rect);
551    }
552
553    /** Apply this matrix to the src rectangle, and write the four transformed
554        points into dst. The points written to dst will be the original top-left, top-right,
555        bottom-right, and bottom-left points transformed by the matrix.
556        @param dst  Where the transformed quad is written.
557        @param rect The original rectangle to be transformed.
558    */
559    void mapRectToQuad(SkPoint dst[4], const SkRect& rect) const {
560        // This could potentially be faster if we only transformed each x and y of the rect once.
561        rect.toQuad(dst);
562        this->mapPoints(dst, 4);
563    }
564
565    /**
566     *  Maps a rect to another rect, asserting (in debug mode) that the matrix only contains
567     *  scale and translate elements. If it contains other elements, the results are undefined.
568     */
569    void mapRectScaleTranslate(SkRect* dst, const SkRect& src) const;
570
571    /** Return the mean radius of a circle after it has been mapped by
572        this matrix. NOTE: in perspective this value assumes the circle
573        has its center at the origin.
574    */
575    SkScalar mapRadius(SkScalar radius) const;
576
577    typedef void (*MapXYProc)(const SkMatrix& mat, SkScalar x, SkScalar y,
578                                 SkPoint* result);
579
580    static MapXYProc GetMapXYProc(TypeMask mask) {
581        SkASSERT((mask & ~kAllMasks) == 0);
582        return gMapXYProcs[mask & kAllMasks];
583    }
584
585    MapXYProc getMapXYProc() const {
586        return GetMapXYProc(this->getType());
587    }
588
589    typedef void (*MapPtsProc)(const SkMatrix& mat, SkPoint dst[],
590                                  const SkPoint src[], int count);
591
592    static MapPtsProc GetMapPtsProc(TypeMask mask) {
593        SkASSERT((mask & ~kAllMasks) == 0);
594        return gMapPtsProcs[mask & kAllMasks];
595    }
596
597    MapPtsProc getMapPtsProc() const {
598        return GetMapPtsProc(this->getType());
599    }
600
601    /** Returns true if the matrix can be stepped in X (not complex
602        perspective).
603    */
604    bool isFixedStepInX() const;
605
606    /** If the matrix can be stepped in X (not complex perspective)
607        then return the step value.
608        If it cannot, behavior is undefined.
609    */
610    SkVector fixedStepInX(SkScalar y) const;
611
612    /** Efficient comparison of two matrices. It distinguishes between zero and
613     *  negative zero. It will return false when the sign of zero values is the
614     *  only difference between the two matrices. It considers NaN values to be
615     *  equal to themselves. So a matrix full of NaNs is "cheap equal" to
616     *  another matrix full of NaNs iff the NaN values are bitwise identical
617     *  while according to strict the strict == test a matrix with a NaN value
618     *  is equal to nothing, including itself.
619     */
620    bool cheapEqualTo(const SkMatrix& m) const {
621        return 0 == memcmp(fMat, m.fMat, sizeof(fMat));
622    }
623
624    friend SK_API bool operator==(const SkMatrix& a, const SkMatrix& b);
625    friend SK_API bool operator!=(const SkMatrix& a, const SkMatrix& b) {
626        return !(a == b);
627    }
628
629    enum {
630        // writeTo/readFromMemory will never return a value larger than this
631        kMaxFlattenSize = 9 * sizeof(SkScalar) + sizeof(uint32_t)
632    };
633    // return the number of bytes written, whether or not buffer is null
634    size_t writeToMemory(void* buffer) const;
635    /**
636     * Reads data from the buffer parameter
637     *
638     * @param buffer Memory to read from
639     * @param length Amount of memory available in the buffer
640     * @return number of bytes read (must be a multiple of 4) or
641     *         0 if there was not enough memory available
642     */
643    size_t readFromMemory(const void* buffer, size_t length);
644
645    void dump() const;
646    void toString(SkString*) const;
647
648    /**
649     * Calculates the minimum scaling factor of the matrix as computed from the SVD of the upper
650     * left 2x2. If the max scale factor cannot be computed (for example overflow or perspective)
651     * -1 is returned.
652     *
653     * @return minimum scale factor
654     */
655    SkScalar getMinScale() const;
656
657    /**
658     * Calculates the maximum scaling factor of the matrix as computed from the SVD of the upper
659     * left 2x2. If the max scale factor cannot be computed (for example overflow or perspective)
660     * -1 is returned.
661     *
662     * @return maximum scale factor
663     */
664    SkScalar getMaxScale() const;
665
666    /**
667     * Gets both the min and max scale factors. The min scale factor is scaleFactors[0] and the max
668     * is scaleFactors[1]. If the min/max scale factors cannot be computed false is returned and the
669     * values of scaleFactors[] are undefined.
670     */
671    bool SK_WARN_UNUSED_RESULT getMinMaxScales(SkScalar scaleFactors[2]) const;
672
673    /**
674     *  Attempt to decompose this matrix into a scale-only component and whatever remains, where
675     *  the scale component is to be applied first.
676     *
677     *  M -> Remaining * Scale
678     *
679     *  On success, return true and assign the scale and remaining components (assuming their
680     *  respective parameters are not null). On failure return false and ignore the parameters.
681     *
682     *  Possible reasons to fail: perspective, one or more scale factors are zero.
683     */
684    bool decomposeScale(SkSize* scale, SkMatrix* remaining = NULL) const;
685
686    /**
687     *  Return a reference to a const identity matrix
688     */
689    static const SkMatrix& I();
690
691    /**
692     *  Return a reference to a const matrix that is "invalid", one that could
693     *  never be used.
694     */
695    static const SkMatrix& InvalidMatrix();
696
697    /**
698     * Return the concatenation of two matrices, a * b.
699     */
700    static SkMatrix Concat(const SkMatrix& a, const SkMatrix& b) {
701        SkMatrix result;
702        result.setConcat(a, b);
703        return result;
704    }
705
706    /**
707     * Testing routine; the matrix's type cache should never need to be
708     * manually invalidated during normal use.
709     */
710    void dirtyMatrixTypeCache() {
711        this->setTypeMask(kUnknown_Mask);
712    }
713
714    /**
715     *  Initialize the matrix to be scale + post-translate.
716     */
717    void setScaleTranslate(SkScalar sx, SkScalar sy, SkScalar tx, SkScalar ty) {
718        fMat[kMScaleX] = sx;
719        fMat[kMSkewX]  = 0;
720        fMat[kMTransX] = tx;
721
722        fMat[kMSkewY]  = 0;
723        fMat[kMScaleY] = sy;
724        fMat[kMTransY] = ty;
725
726        fMat[kMPersp0] = 0;
727        fMat[kMPersp1] = 0;
728        fMat[kMPersp2] = 1;
729
730        unsigned mask = 0;
731        if (sx != 1 || sy != 1) {
732            mask |= kScale_Mask;
733        }
734        if (tx || ty) {
735            mask |= kTranslate_Mask;
736        }
737        this->setTypeMask(mask | kRectStaysRect_Mask);
738    }
739
740    /**
741     *  Are all elements of the matrix finite?
742     */
743    bool isFinite() const { return SkScalarsAreFinite(fMat, 9); }
744
745private:
746    enum {
747        /** Set if the matrix will map a rectangle to another rectangle. This
748            can be true if the matrix is scale-only, or rotates a multiple of
749            90 degrees.
750
751            This bit will be set on identity matrices
752        */
753        kRectStaysRect_Mask = 0x10,
754
755        /** Set if the perspective bit is valid even though the rest of
756            the matrix is Unknown.
757        */
758        kOnlyPerspectiveValid_Mask = 0x40,
759
760        kUnknown_Mask = 0x80,
761
762        kORableMasks =  kTranslate_Mask |
763                        kScale_Mask |
764                        kAffine_Mask |
765                        kPerspective_Mask,
766
767        kAllMasks = kTranslate_Mask |
768                    kScale_Mask |
769                    kAffine_Mask |
770                    kPerspective_Mask |
771                    kRectStaysRect_Mask
772    };
773
774    SkScalar         fMat[9];
775    mutable uint32_t fTypeMask;
776
777    static void ComputeInv(SkScalar dst[9], const SkScalar src[9], double invDet, bool isPersp);
778
779    uint8_t computeTypeMask() const;
780    uint8_t computePerspectiveTypeMask() const;
781
782    void setTypeMask(int mask) {
783        // allow kUnknown or a valid mask
784        SkASSERT(kUnknown_Mask == mask || (mask & kAllMasks) == mask ||
785                 ((kUnknown_Mask | kOnlyPerspectiveValid_Mask) & mask)
786                 == (kUnknown_Mask | kOnlyPerspectiveValid_Mask));
787        fTypeMask = SkToU8(mask);
788    }
789
790    void orTypeMask(int mask) {
791        SkASSERT((mask & kORableMasks) == mask);
792        fTypeMask = SkToU8(fTypeMask | mask);
793    }
794
795    void clearTypeMask(int mask) {
796        // only allow a valid mask
797        SkASSERT((mask & kAllMasks) == mask);
798        fTypeMask = fTypeMask & ~mask;
799    }
800
801    TypeMask getPerspectiveTypeMaskOnly() const {
802        if ((fTypeMask & kUnknown_Mask) &&
803            !(fTypeMask & kOnlyPerspectiveValid_Mask)) {
804            fTypeMask = this->computePerspectiveTypeMask();
805        }
806        return (TypeMask)(fTypeMask & 0xF);
807    }
808
809    /** Returns true if we already know that the matrix is identity;
810        false otherwise.
811    */
812    bool isTriviallyIdentity() const {
813        if (fTypeMask & kUnknown_Mask) {
814            return false;
815        }
816        return ((fTypeMask & 0xF) == 0);
817    }
818
819    inline void updateTranslateMask() {
820        if ((fMat[kMTransX] != 0) | (fMat[kMTransY] != 0)) {
821            fTypeMask |= kTranslate_Mask;
822        } else {
823            fTypeMask &= ~kTranslate_Mask;
824        }
825    }
826
827    bool SK_WARN_UNUSED_RESULT invertNonIdentity(SkMatrix* inverse) const;
828
829    static bool Poly2Proc(const SkPoint[], SkMatrix*, const SkPoint& scale);
830    static bool Poly3Proc(const SkPoint[], SkMatrix*, const SkPoint& scale);
831    static bool Poly4Proc(const SkPoint[], SkMatrix*, const SkPoint& scale);
832
833    static void Identity_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
834    static void Trans_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
835    static void Scale_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
836    static void ScaleTrans_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
837    static void Rot_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
838    static void RotTrans_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
839    static void Persp_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
840
841    static const MapXYProc gMapXYProcs[];
842
843    static void Identity_pts(const SkMatrix&, SkPoint[], const SkPoint[], int);
844    static void Trans_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], int);
845    static void Scale_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], int);
846    static void ScaleTrans_pts(const SkMatrix&, SkPoint dst[], const SkPoint[],
847                               int count);
848    static void Persp_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], int);
849
850    static void Affine_vpts(const SkMatrix&, SkPoint dst[], const SkPoint[], int);
851
852    static const MapPtsProc gMapPtsProcs[];
853
854    friend class SkPerspIter;
855    friend class SkMatrixPriv;
856};
857SK_END_REQUIRE_DENSE
858
859#endif
860