LCOV - code coverage report
Current view: top level - gfx/skia/skia/include/core - SkMatrix.h (source / functions) Hit Total Coverage
Test: output.info Lines: 104 176 59.1 %
Date: 2017-07-14 16:53:18 Functions: 30 53 56.6 %
Legend: Lines: hit not hit

          Line data    Source code
       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             : 
      15             : struct SkRSXform;
      16             : class 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             : */
      27             : SK_BEGIN_REQUIRE_DENSE
      28             : class SK_API SkMatrix {
      29             : public:
      30           0 :     static SkMatrix SK_WARN_UNUSED_RESULT MakeScale(SkScalar sx, SkScalar sy) {
      31             :         SkMatrix m;
      32           0 :         m.setScale(sx, sy);
      33           0 :         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           4 :     static SkMatrix SK_WARN_UNUSED_RESULT MakeTrans(SkScalar dx, SkScalar dy) {
      43             :         SkMatrix m;
      44           4 :         m.setTranslate(dx, dy);
      45           4 :         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       17266 :     TypeMask getType() const {
      66       17266 :         if (fTypeMask & kUnknown_Mask) {
      67        4004 :             fTypeMask = this->computeTypeMask();
      68             :         }
      69             :         // only return the public masks
      70       17266 :         return (TypeMask)(fTypeMask & 0xF);
      71             :     }
      72             : 
      73             :     /** Returns true if the matrix is identity.
      74             :     */
      75        1253 :     bool isIdentity() const {
      76        1253 :         return this->getType() == 0;
      77             :     }
      78             : 
      79        3733 :     bool isScaleTranslate() const {
      80        3733 :         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         355 :     bool rectStaysRect() const {
      88         355 :         if (fTypeMask & kUnknown_Mask) {
      89          81 :             fTypeMask = this->computeTypeMask();
      90             :         }
      91         355 :         return (fTypeMask & kRectStaysRect_Mask) != 0;
      92             :     }
      93             :     // alias for rectStaysRect()
      94           0 :     bool preservesAxisAlignment() const { return this->rectStaysRect(); }
      95             : 
      96             :     /**
      97             :      *  Returns true if the matrix contains perspective elements.
      98             :      */
      99         999 :     bool hasPerspective() const {
     100         999 :         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         170 :     SkScalar operator[](int index) const {
     140         170 :         SkASSERT((unsigned)index < 9);
     141         170 :         return fMat[index];
     142             :     }
     143             : 
     144           0 :     SkScalar get(int index) const {
     145           0 :         SkASSERT((unsigned)index < 9);
     146           0 :         return fMat[index];
     147             :     }
     148             : 
     149        5858 :     SkScalar getScaleX() const { return fMat[kMScaleX]; }
     150        2183 :     SkScalar getScaleY() const { return fMat[kMScaleY]; }
     151         286 :     SkScalar getSkewY() const { return fMat[kMSkewY]; }
     152           4 :     SkScalar getSkewX() const { return fMat[kMSkewX]; }
     153         844 :     SkScalar getTranslateX() const { return fMat[kMTransX]; }
     154         844 :     SkScalar getTranslateY() const { return fMat[kMTransY]; }
     155           0 :     SkScalar getPerspX() const { return fMat[kMPersp0]; }
     156           0 :     SkScalar getPerspY() const { return fMat[kMPersp1]; }
     157             : 
     158           0 :     SkScalar& operator[](int index) {
     159           0 :         SkASSERT((unsigned)index < 9);
     160           0 :         this->setTypeMask(kUnknown_Mask);
     161           0 :         return fMat[index];
     162             :     }
     163             : 
     164           0 :     void set(int index, SkScalar value) {
     165           0 :         SkASSERT((unsigned)index < 9);
     166           0 :         fMat[index] = value;
     167           0 :         this->setTypeMask(kUnknown_Mask);
     168           0 :     }
     169             : 
     170           0 :     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           0 :     void setTranslateX(SkScalar v) { this->set(kMTransX, v); }
     175           0 :     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        2162 :     void setAll(SkScalar scaleX, SkScalar skewX,  SkScalar transX,
     180             :                 SkScalar skewY,  SkScalar scaleY, SkScalar transY,
     181             :                 SkScalar persp0, SkScalar persp1, SkScalar persp2) {
     182        2162 :         fMat[kMScaleX] = scaleX;
     183        2162 :         fMat[kMSkewX]  = skewX;
     184        2162 :         fMat[kMTransX] = transX;
     185        2162 :         fMat[kMSkewY]  = skewY;
     186        2162 :         fMat[kMScaleY] = scaleY;
     187        2162 :         fMat[kMTransY] = transY;
     188        2162 :         fMat[kMPersp0] = persp0;
     189        2162 :         fMat[kMPersp1] = persp1;
     190        2162 :         fMat[kMPersp2] = persp2;
     191        2162 :         this->setTypeMask(kUnknown_Mask);
     192        2162 :     }
     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           0 :     void get9(SkScalar buffer[9]) const {
     199           0 :         memcpy(buffer, fMat, 9 * sizeof(SkScalar));
     200           0 :     }
     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          58 :     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           0 :     static SkMatrix MakeRectToRect(const SkRect& src, const SkRect& dst, ScaleToFit stf) {
     376             :         SkMatrix m;
     377           0 :         m.setRectToRect(src, dst, stf);
     378           0 :         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         572 :     bool SK_WARN_UNUSED_RESULT invert(SkMatrix* inverse) const {
     395             :         // Allow the trivial case to be inlined.
     396         572 :         if (this->isIdentity()) {
     397          56 :             if (inverse) {
     398          31 :                 inverse->reset();
     399             :             }
     400          56 :             return true;
     401             :         }
     402         516 :         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         318 :     void mapPoints(SkPoint dst[], const SkPoint src[], int count) const {
     435         318 :         SkASSERT((dst && src && count > 0) || 0 == count);
     436             :         // no partial overlap
     437         318 :         SkASSERT(src == dst || &dst[count] <= &src[0] || &src[count] <= &dst[0]);
     438         318 :         this->getMapPtsProc()(*this, dst, src, count);
     439         318 :     }
     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           0 :     void mapPoints(SkPoint pts[], int count) const {
     449           0 :         this->mapPoints(pts, pts, count);
     450           0 :     }
     451             : 
     452             :     /** Like mapPoints but with custom byte stride between the points. Stride
     453             :      *  should be a multiple of sizeof(SkScalar).
     454             :      */
     455           0 :     void mapPointsWithStride(SkPoint pts[], size_t stride, int count) const {
     456           0 :         SkASSERT(stride >= sizeof(SkPoint));
     457           0 :         SkASSERT(0 == stride % sizeof(SkScalar));
     458           0 :         for (int i = 0; i < count; ++i) {
     459           0 :             this->mapPoints(pts, pts, 1);
     460           0 :             pts = (SkPoint*)((intptr_t)pts + stride);
     461             :         }
     462           0 :     }
     463             : 
     464             :     /** Like mapPoints but with custom byte stride between the points.
     465             :     */
     466           0 :     void mapPointsWithStride(SkPoint dst[], const SkPoint src[], size_t stride, int count) const {
     467           0 :         SkASSERT(stride >= sizeof(SkPoint));
     468           0 :         SkASSERT(0 == stride % sizeof(SkScalar));
     469           0 :         for (int i = 0; i < count; ++i) {
     470           0 :             this->mapPoints(dst, src, 1);
     471           0 :             src = (SkPoint*)((intptr_t)src + stride);
     472           0 :             dst = (SkPoint*)((intptr_t)dst + stride);
     473             :         }
     474           0 :     }
     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           0 :     void mapXY(SkScalar x, SkScalar y, SkPoint* result) const {
     490           0 :         SkASSERT(result);
     491           0 :         this->getMapXYProc()(*this, x, y, result);
     492           0 :     }
     493             : 
     494           0 :     SkPoint mapXY(SkScalar x, SkScalar y) const {
     495             :         SkPoint result;
     496           0 :         this->getMapXYProc()(*this, x, y, &result);
     497           0 :         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           0 :     void mapVectors(SkVector vecs[], int count) const {
     520           0 :         this->mapVectors(vecs, vecs, count);
     521           0 :     }
     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           0 :     SkVector mapVector(SkScalar dx, SkScalar dy) const {
     529           0 :         SkVector vec = { dx, dy };
     530           0 :         this->mapVectors(&vec, &vec, 1);
     531           0 :         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          39 :     bool mapRect(SkRect* rect) const {
     550          39 :         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           0 :     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           0 :         rect.toQuad(dst);
     562           0 :         this->mapPoints(dst, 4);
     563           0 :     }
     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         187 :     static MapXYProc GetMapXYProc(TypeMask mask) {
     581         187 :         SkASSERT((mask & ~kAllMasks) == 0);
     582         187 :         return gMapXYProcs[mask & kAllMasks];
     583             :     }
     584             : 
     585         187 :     MapXYProc getMapXYProc() const {
     586         187 :         return GetMapXYProc(this->getType());
     587             :     }
     588             : 
     589             :     typedef void (*MapPtsProc)(const SkMatrix& mat, SkPoint dst[],
     590             :                                   const SkPoint src[], int count);
     591             : 
     592         333 :     static MapPtsProc GetMapPtsProc(TypeMask mask) {
     593         333 :         SkASSERT((mask & ~kAllMasks) == 0);
     594         333 :         return gMapPtsProcs[mask & kAllMasks];
     595             :     }
     596             : 
     597         333 :     MapPtsProc getMapPtsProc() const {
     598         333 :         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           0 :     bool cheapEqualTo(const SkMatrix& m) const {
     621           0 :         return 0 == memcmp(fMat, m.fMat, sizeof(fMat));
     622             :     }
     623             : 
     624             :     friend SK_API bool operator==(const SkMatrix& a, const SkMatrix& b);
     625           0 :     friend SK_API bool operator!=(const SkMatrix& a, const SkMatrix& b) {
     626           0 :         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         617 :     static SkMatrix Concat(const SkMatrix& a, const SkMatrix& b) {
     701             :         SkMatrix result;
     702         617 :         result.setConcat(a, b);
     703         617 :         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         221 :     void setScaleTranslate(SkScalar sx, SkScalar sy, SkScalar tx, SkScalar ty) {
     718         221 :         fMat[kMScaleX] = sx;
     719         221 :         fMat[kMSkewX]  = 0;
     720         221 :         fMat[kMTransX] = tx;
     721             :         
     722         221 :         fMat[kMSkewY]  = 0;
     723         221 :         fMat[kMScaleY] = sy;
     724         221 :         fMat[kMTransY] = ty;
     725             :         
     726         221 :         fMat[kMPersp0] = 0;
     727         221 :         fMat[kMPersp1] = 0;
     728         221 :         fMat[kMPersp2] = 1;
     729             :         
     730         221 :         unsigned mask = 0;
     731         221 :         if (sx != 1 || sy != 1) {
     732          20 :             mask |= kScale_Mask;
     733             :         }
     734         221 :         if (tx || ty) {
     735          93 :             mask |= kTranslate_Mask;
     736             :         }
     737         221 :         this->setTypeMask(mask | kRectStaysRect_Mask);
     738         221 :     }
     739             :     
     740             :     /**
     741             :      *  Are all elements of the matrix finite?
     742             :      */
     743          25 :     bool isFinite() const { return SkScalarsAreFinite(fMat, 9); }
     744             : 
     745             : private:
     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        3163 :     void setTypeMask(int mask) {
     783             :         // allow kUnknown or a valid mask
     784        3163 :         SkASSERT(kUnknown_Mask == mask || (mask & kAllMasks) == mask ||
     785             :                  ((kUnknown_Mask | kOnlyPerspectiveValid_Mask) & mask)
     786             :                  == (kUnknown_Mask | kOnlyPerspectiveValid_Mask));
     787        3163 :         fTypeMask = SkToU8(mask);
     788        3163 :     }
     789             : 
     790           0 :     void orTypeMask(int mask) {
     791           0 :         SkASSERT((mask & kORableMasks) == mask);
     792           0 :         fTypeMask = SkToU8(fTypeMask | mask);
     793           0 :     }
     794             : 
     795          15 :     void clearTypeMask(int mask) {
     796             :         // only allow a valid mask
     797          15 :         SkASSERT((mask & kAllMasks) == mask);
     798          15 :         fTypeMask = fTypeMask & ~mask;
     799          15 :     }
     800             : 
     801         999 :     TypeMask getPerspectiveTypeMaskOnly() const {
     802        1430 :         if ((fTypeMask & kUnknown_Mask) &&
     803         431 :             !(fTypeMask & kOnlyPerspectiveValid_Mask)) {
     804         394 :             fTypeMask = this->computePerspectiveTypeMask();
     805             :         }
     806         999 :         return (TypeMask)(fTypeMask & 0xF);
     807             :     }
     808             : 
     809             :     /** Returns true if we already know that the matrix is identity;
     810             :         false otherwise.
     811             :     */
     812        1327 :     bool isTriviallyIdentity() const {
     813        1327 :         if (fTypeMask & kUnknown_Mask) {
     814           0 :             return false;
     815             :         }
     816        1327 :         return ((fTypeMask & 0xF) == 0);
     817             :     }
     818             : 
     819         644 :     inline void updateTranslateMask() {
     820         644 :         if ((fMat[kMTransX] != 0) | (fMat[kMTransY] != 0)) {
     821         458 :             fTypeMask |= kTranslate_Mask;
     822             :         } else {
     823         186 :             fTypeMask &= ~kTranslate_Mask;
     824             :         }
     825         644 :     }
     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             : };
     857             : SK_END_REQUIRE_DENSE
     858             : 
     859             : #endif

Generated by: LCOV version 1.13