LCOV - code coverage report
Current view: directory - objdir/dist/include/skia - SkMatrix.h (source / functions) Found Hit Coverage
Test: app.info Lines: 23 0 0.0 %
Date: 2012-06-02 Functions: 5 0 0.0 %

       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                 : class SkString;
      16                 : 
      17                 : #ifdef SK_SCALAR_IS_FLOAT
      18                 :     typedef SkScalar SkPersp;
      19                 :     #define SkScalarToPersp(x) (x)
      20                 :     #define SkPerspToScalar(x) (x)
      21                 : #else
      22                 :     typedef SkFract SkPersp;
      23                 :     #define SkScalarToPersp(x) SkFixedToFract(x)
      24                 :     #define SkPerspToScalar(x) SkFractToFixed(x)
      25                 : #endif
      26                 : 
      27                 : /** \class SkMatrix
      28                 : 
      29                 :     The SkMatrix class holds a 3x3 matrix for transforming coordinates.
      30                 :     SkMatrix does not have a constructor, so it must be explicitly initialized
      31                 :     using either reset() - to construct an identity matrix, or one of the set
      32                 :     functions (e.g. setTranslate, setRotate, etc.).
      33                 : */
      34                 : class SK_API SkMatrix {
      35                 : public:
      36                 :     /** Enum of bit fields for the mask return by getType().
      37                 :         Use this to identify the complexity of the matrix.
      38                 :     */
      39                 :     enum TypeMask {
      40                 :         kIdentity_Mask      = 0,
      41                 :         kTranslate_Mask     = 0x01,  //!< set if the matrix has translation
      42                 :         kScale_Mask         = 0x02,  //!< set if the matrix has X or Y scale
      43                 :         kAffine_Mask        = 0x04,  //!< set if the matrix skews or rotates
      44                 :         kPerspective_Mask   = 0x08   //!< set if the matrix is in perspective
      45                 :     };
      46                 : 
      47                 :     /** Returns a mask bitfield describing the types of transformations
      48                 :         that the matrix will perform. This information is used by routines
      49                 :         like mapPoints, to optimize its inner loops to only perform as much
      50                 :         arithmetic as is necessary.
      51                 :     */
      52                 :     TypeMask getType() const {
      53                 :         if (fTypeMask & kUnknown_Mask) {
      54                 :             fTypeMask = this->computeTypeMask();
      55                 :         }
      56                 :         // only return the public masks
      57                 :         return (TypeMask)(fTypeMask & 0xF);
      58                 :     }
      59                 : 
      60                 :     /** Returns true if the matrix is identity.
      61                 :     */
      62                 :     bool isIdentity() const {
      63                 :         return this->getType() == 0;
      64                 :     }
      65                 : 
      66                 :     /** Returns true if will map a rectangle to another rectangle. This can be
      67                 :         true if the matrix is identity, scale-only, or rotates a multiple of
      68                 :         90 degrees.
      69                 :     */
      70                 :     bool rectStaysRect() const {
      71                 :         if (fTypeMask & kUnknown_Mask) {
      72                 :             fTypeMask = this->computeTypeMask();
      73                 :         }
      74                 :         return (fTypeMask & kRectStaysRect_Mask) != 0;
      75                 :     }
      76                 :     // alias for rectStaysRect()
      77                 :     bool preservesAxisAlignment() const { return this->rectStaysRect(); }
      78                 : 
      79                 :     /**
      80                 :      *  Returns true if the matrix contains perspective elements.
      81                 :      */
      82                 :     bool hasPerspective() const {
      83                 :         return SkToBool(this->getPerspectiveTypeMaskOnly() &
      84                 :                         kPerspective_Mask);
      85                 :     }
      86                 : 
      87                 :     enum {
      88                 :         kMScaleX,
      89                 :         kMSkewX,
      90                 :         kMTransX,
      91                 :         kMSkewY,
      92                 :         kMScaleY,
      93                 :         kMTransY,
      94                 :         kMPersp0,
      95                 :         kMPersp1,
      96                 :         kMPersp2
      97                 :     };
      98                 :     
      99                 :     /** Affine arrays are in column major order
     100                 :         because that's how PDF and XPS like it.
     101                 :      */
     102                 :     enum {
     103                 :         kAScaleX,
     104                 :         kASkewY,
     105                 :         kASkewX,
     106                 :         kAScaleY,
     107                 :         kATransX,
     108                 :         kATransY
     109                 :     };
     110                 : 
     111                 :     SkScalar operator[](int index) const {
     112                 :         SkASSERT((unsigned)index < 9);
     113                 :         return fMat[index];
     114                 :     }
     115                 :     
     116                 :     SkScalar get(int index) const {
     117                 :         SkASSERT((unsigned)index < 9);
     118                 :         return fMat[index];
     119                 :     }
     120                 :     
     121                 :     SkScalar getScaleX() const { return fMat[kMScaleX]; }
     122                 :     SkScalar getScaleY() const { return fMat[kMScaleY]; }
     123                 :     SkScalar getSkewY() const { return fMat[kMSkewY]; }
     124                 :     SkScalar getSkewX() const { return fMat[kMSkewX]; }
     125                 :     SkScalar getTranslateX() const { return fMat[kMTransX]; }
     126                 :     SkScalar getTranslateY() const { return fMat[kMTransY]; }
     127                 :     SkPersp getPerspX() const { return fMat[kMPersp0]; }
     128                 :     SkPersp getPerspY() const { return fMat[kMPersp1]; }
     129                 : 
     130                 :     SkScalar& operator[](int index) {
     131                 :         SkASSERT((unsigned)index < 9);
     132                 :         this->setTypeMask(kUnknown_Mask);
     133                 :         return fMat[index];
     134                 :     }
     135                 : 
     136               0 :     void set(int index, SkScalar value) {
     137               0 :         SkASSERT((unsigned)index < 9);
     138               0 :         fMat[index] = value;
     139               0 :         this->setTypeMask(kUnknown_Mask);
     140               0 :     }
     141                 : 
     142                 :     void setScaleX(SkScalar v) { this->set(kMScaleX, v); }
     143                 :     void setScaleY(SkScalar v) { this->set(kMScaleY, v); }
     144                 :     void setSkewY(SkScalar v) { this->set(kMSkewY, v); }
     145                 :     void setSkewX(SkScalar v) { this->set(kMSkewX, v); }
     146               0 :     void setTranslateX(SkScalar v) { this->set(kMTransX, v); }
     147               0 :     void setTranslateY(SkScalar v) { this->set(kMTransY, v); }
     148                 :     void setPerspX(SkPersp v) { this->set(kMPersp0, v); }
     149                 :     void setPerspY(SkPersp v) { this->set(kMPersp1, v); }
     150                 : 
     151               0 :     void setAll(SkScalar scaleX, SkScalar skewX, SkScalar transX,
     152                 :                 SkScalar skewY, SkScalar scaleY, SkScalar transY,
     153                 :                 SkPersp persp0, SkPersp persp1, SkPersp persp2) {
     154               0 :         fMat[kMScaleX] = scaleX;
     155               0 :         fMat[kMSkewX]  = skewX;
     156               0 :         fMat[kMTransX] = transX;
     157               0 :         fMat[kMSkewY]  = skewY;
     158               0 :         fMat[kMScaleY] = scaleY;
     159               0 :         fMat[kMTransY] = transY;
     160               0 :         fMat[kMPersp0] = persp0;
     161               0 :         fMat[kMPersp1] = persp1;
     162               0 :         fMat[kMPersp2] = persp2;
     163               0 :         this->setTypeMask(kUnknown_Mask);
     164               0 :     }
     165                 :         
     166                 :     /** Set the matrix to identity
     167                 :     */
     168                 :     void reset();
     169                 :     // alias for reset()
     170                 :     void setIdentity() { this->reset(); }
     171                 : 
     172                 :     /** Set the matrix to translate by (dx, dy).
     173                 :     */
     174                 :     void setTranslate(SkScalar dx, SkScalar dy);
     175                 :     /** Set the matrix to scale by sx and sy, with a pivot point at (px, py).
     176                 :         The pivot point is the coordinate that should remain unchanged by the
     177                 :         specified transformation.
     178                 :     */
     179                 :     void setScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py);
     180                 :     /** Set the matrix to scale by sx and sy.
     181                 :     */
     182                 :     void setScale(SkScalar sx, SkScalar sy);
     183                 :     /** Set the matrix to scale by 1/divx and 1/divy. Returns false and doesn't
     184                 :         touch the matrix if either divx or divy is zero.
     185                 :     */
     186                 :     bool setIDiv(int divx, int divy);
     187                 :     /** Set the matrix to rotate by the specified number of degrees, with a
     188                 :         pivot point at (px, py). The pivot point is the coordinate that should
     189                 :         remain unchanged by the specified transformation.
     190                 :     */
     191                 :     void setRotate(SkScalar degrees, SkScalar px, SkScalar py);
     192                 :     /** Set the matrix to rotate about (0,0) by the specified number of degrees.
     193                 :     */
     194                 :     void setRotate(SkScalar degrees);
     195                 :     /** Set the matrix to rotate by the specified sine and cosine values, with
     196                 :         a pivot point at (px, py). The pivot point is the coordinate that
     197                 :         should remain unchanged by the specified transformation.
     198                 :     */
     199                 :     void setSinCos(SkScalar sinValue, SkScalar cosValue,
     200                 :                    SkScalar px, SkScalar py);
     201                 :     /** Set the matrix to rotate by the specified sine and cosine values.
     202                 :     */
     203                 :     void setSinCos(SkScalar sinValue, SkScalar cosValue);
     204                 :     /** Set the matrix to skew by sx and sy, with a pivot point at (px, py).
     205                 :         The pivot point is the coordinate that should remain unchanged by the
     206                 :         specified transformation.
     207                 :     */
     208                 :     void setSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py);
     209                 :     /** Set the matrix to skew by sx and sy.
     210                 :     */
     211                 :     void setSkew(SkScalar kx, SkScalar ky);
     212                 :     /** Set the matrix to the concatenation of the two specified matrices,
     213                 :         returning true if the the result can be represented. Either of the
     214                 :         two matrices may also be the target matrix. *this = a * b;
     215                 :     */
     216                 :     bool setConcat(const SkMatrix& a, const SkMatrix& b);
     217                 : 
     218                 :     /** Preconcats the matrix with the specified translation.
     219                 :         M' = M * T(dx, dy)
     220                 :     */
     221                 :     bool preTranslate(SkScalar dx, SkScalar dy);
     222                 :     /** Preconcats the matrix with the specified scale.
     223                 :         M' = M * S(sx, sy, px, py)
     224                 :     */
     225                 :     bool preScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py);
     226                 :     /** Preconcats the matrix with the specified scale.
     227                 :         M' = M * S(sx, sy)
     228                 :     */
     229                 :     bool preScale(SkScalar sx, SkScalar sy);
     230                 :     /** Preconcats the matrix with the specified rotation.
     231                 :         M' = M * R(degrees, px, py)
     232                 :     */
     233                 :     bool preRotate(SkScalar degrees, SkScalar px, SkScalar py);
     234                 :     /** Preconcats the matrix with the specified rotation.
     235                 :         M' = M * R(degrees)
     236                 :     */
     237                 :     bool preRotate(SkScalar degrees);
     238                 :     /** Preconcats the matrix with the specified skew.
     239                 :         M' = M * K(kx, ky, px, py)
     240                 :     */
     241                 :     bool preSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py);
     242                 :     /** Preconcats the matrix with the specified skew.
     243                 :         M' = M * K(kx, ky)
     244                 :     */
     245                 :     bool preSkew(SkScalar kx, SkScalar ky);
     246                 :     /** Preconcats the matrix with the specified matrix.
     247                 :         M' = M * other
     248                 :     */
     249                 :     bool preConcat(const SkMatrix& other);
     250                 : 
     251                 :     /** Postconcats the matrix with the specified translation.
     252                 :         M' = T(dx, dy) * M
     253                 :     */
     254                 :     bool postTranslate(SkScalar dx, SkScalar dy);
     255                 :     /** Postconcats the matrix with the specified scale.
     256                 :         M' = S(sx, sy, px, py) * M
     257                 :     */
     258                 :     bool postScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py);
     259                 :     /** Postconcats the matrix with the specified scale.
     260                 :         M' = S(sx, sy) * M
     261                 :     */
     262                 :     bool postScale(SkScalar sx, SkScalar sy);
     263                 :     /** Postconcats the matrix by dividing it by the specified integers.
     264                 :         M' = S(1/divx, 1/divy, 0, 0) * M
     265                 :     */
     266                 :     bool postIDiv(int divx, int divy);
     267                 :     /** Postconcats the matrix with the specified rotation.
     268                 :         M' = R(degrees, px, py) * M
     269                 :     */
     270                 :     bool postRotate(SkScalar degrees, SkScalar px, SkScalar py);
     271                 :     /** Postconcats the matrix with the specified rotation.
     272                 :         M' = R(degrees) * M
     273                 :     */
     274                 :     bool postRotate(SkScalar degrees);
     275                 :     /** Postconcats the matrix with the specified skew.
     276                 :         M' = K(kx, ky, px, py) * M
     277                 :     */
     278                 :     bool postSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py);
     279                 :     /** Postconcats the matrix with the specified skew.
     280                 :         M' = K(kx, ky) * M
     281                 :     */
     282                 :     bool postSkew(SkScalar kx, SkScalar ky);
     283                 :     /** Postconcats the matrix with the specified matrix.
     284                 :         M' = other * M
     285                 :     */
     286                 :     bool postConcat(const SkMatrix& other);
     287                 : 
     288                 :     enum ScaleToFit {
     289                 :         /**
     290                 :          * Scale in X and Y independently, so that src matches dst exactly.
     291                 :          * This may change the aspect ratio of the src.
     292                 :          */
     293                 :         kFill_ScaleToFit,
     294                 :         /**
     295                 :          * Compute a scale that will maintain the original src aspect ratio,
     296                 :          * but will also ensure that src fits entirely inside dst. At least one
     297                 :          * axis (X or Y) will fit exactly. kStart aligns the result to the
     298                 :          * left and top edges of dst.
     299                 :          */
     300                 :         kStart_ScaleToFit,
     301                 :         /**
     302                 :          * Compute a scale that will maintain the original src aspect ratio,
     303                 :          * but will also ensure that src fits entirely inside dst. At least one
     304                 :          * axis (X or Y) will fit exactly. The result is centered inside dst.
     305                 :          */
     306                 :         kCenter_ScaleToFit,
     307                 :         /**
     308                 :          * Compute a scale that will maintain the original src aspect ratio,
     309                 :          * but will also ensure that src fits entirely inside dst. At least one
     310                 :          * axis (X or Y) will fit exactly. kEnd aligns the result to the
     311                 :          * right and bottom edges of dst.
     312                 :          */
     313                 :         kEnd_ScaleToFit
     314                 :     };
     315                 : 
     316                 :     /** Set the matrix to the scale and translate values that map the source
     317                 :         rectangle to the destination rectangle, returning true if the the result
     318                 :         can be represented.
     319                 :         @param src the source rectangle to map from.
     320                 :         @param dst the destination rectangle to map to.
     321                 :         @param stf the ScaleToFit option
     322                 :         @return true if the matrix can be represented by the rectangle mapping.
     323                 :     */
     324                 :     bool setRectToRect(const SkRect& src, const SkRect& dst, ScaleToFit stf);
     325                 :     
     326                 :     /** Set the matrix such that the specified src points would map to the
     327                 :         specified dst points. count must be within [0..4].
     328                 :         @param src  The array of src points
     329                 :         @param dst  The array of dst points
     330                 :         @param count The number of points to use for the transformation
     331                 :         @return true if the matrix was set to the specified transformation
     332                 :     */
     333                 :     bool setPolyToPoly(const SkPoint src[], const SkPoint dst[], int count);
     334                 : 
     335                 :     /** If this matrix can be inverted, return true and if inverse is not null,
     336                 :         set inverse to be the inverse of this matrix. If this matrix cannot be
     337                 :         inverted, ignore inverse and return false
     338                 :     */
     339                 :     bool invert(SkMatrix* inverse) const;
     340                 : 
     341                 :     /** Fills the passed array with affine identity values
     342                 :         in column major order.
     343                 :         @param affine  The array to fill with affine identity values.
     344                 :         Must not be NULL.
     345                 :     */
     346                 :     static void SetAffineIdentity(SkScalar affine[6]);
     347                 : 
     348                 :     /** Fills the passed array with the affine values in column major order.
     349                 :         If the matrix is a perspective transform, returns false
     350                 :         and does not change the passed array.
     351                 :         @param affine  The array to fill with affine values. Ignored if NULL.
     352                 :     */
     353                 :     bool asAffine(SkScalar affine[6]) const;
     354                 : 
     355                 :     /** Apply this matrix to the array of points specified by src, and write
     356                 :         the transformed points into the array of points specified by dst.
     357                 :         dst[] = M * src[]
     358                 :         @param dst  Where the transformed coordinates are written. It must
     359                 :                     contain at least count entries
     360                 :         @param src  The original coordinates that are to be transformed. It
     361                 :                     must contain at least count entries
     362                 :         @param count The number of points in src to read, and then transform
     363                 :                      into dst.
     364                 :     */
     365                 :     void mapPoints(SkPoint dst[], const SkPoint src[], int count) const;
     366                 : 
     367                 :     /** Apply this matrix to the array of points, overwriting it with the
     368                 :         transformed values.
     369                 :         dst[] = M * pts[]
     370                 :         @param pts  The points to be transformed. It must contain at least
     371                 :                     count entries
     372                 :         @param count The number of points in pts.
     373                 :     */
     374                 :     void mapPoints(SkPoint pts[], int count) const {
     375                 :         this->mapPoints(pts, pts, count);
     376                 :     }
     377                 :     
     378                 :     /** Like mapPoints but with custom byte stride between the points. Stride
     379                 :      *  should be a multiple of sizeof(SkScalar).
     380                 :      */
     381                 :     void mapPointsWithStride(SkPoint pts[], size_t stride, int count) const {
     382                 :         SkASSERT(stride >= sizeof(SkPoint));
     383                 :         SkASSERT(0 == stride % sizeof(SkScalar));
     384                 :         for (int i = 0; i < count; ++i) {
     385                 :             this->mapPoints(pts, pts, 1);
     386                 :             pts = (SkPoint*)((intptr_t)pts + stride);
     387                 :         }
     388                 :     }
     389                 : 
     390                 :     /** Like mapPoints but with custom byte stride between the points.
     391                 :     */
     392                 :     void mapPointsWithStride(SkPoint dst[], SkPoint src[],
     393                 :                              size_t stride, int count) const {
     394                 :         SkASSERT(stride >= sizeof(SkPoint));
     395                 :         SkASSERT(0 == stride % sizeof(SkScalar));
     396                 :         for (int i = 0; i < count; ++i) {
     397                 :             this->mapPoints(dst, src, 1);
     398                 :             src = (SkPoint*)((intptr_t)src + stride);
     399                 :             dst = (SkPoint*)((intptr_t)dst + stride);
     400                 :         }
     401                 :     }
     402                 : 
     403                 :     void mapXY(SkScalar x, SkScalar y, SkPoint* result) const {
     404                 :         SkASSERT(result);
     405                 :         this->getMapXYProc()(*this, x, y, result);
     406                 :     }
     407                 : 
     408                 :     /** Apply this matrix to the array of vectors specified by src, and write
     409                 :         the transformed vectors into the array of vectors specified by dst.
     410                 :         This is similar to mapPoints, but ignores any translation in the matrix.
     411                 :         @param dst  Where the transformed coordinates are written. It must
     412                 :                     contain at least count entries
     413                 :         @param src  The original coordinates that are to be transformed. It
     414                 :                     must contain at least count entries
     415                 :         @param count The number of vectors in src to read, and then transform
     416                 :                      into dst.
     417                 :     */
     418                 :     void mapVectors(SkVector dst[], const SkVector src[], int count) const;
     419                 : 
     420                 :     /** Apply this matrix to the array of vectors specified by src, and write
     421                 :         the transformed vectors into the array of vectors specified by dst.
     422                 :         This is similar to mapPoints, but ignores any translation in the matrix.
     423                 :         @param vecs The vectors to be transformed. It must contain at least
     424                 :                     count entries
     425                 :         @param count The number of vectors in vecs.
     426                 :     */
     427                 :     void mapVectors(SkVector vecs[], int count) const {
     428                 :         this->mapVectors(vecs, vecs, count);
     429                 :     }
     430                 : 
     431                 :     /** Apply this matrix to the src rectangle, and write the transformed
     432                 :         rectangle into dst. This is accomplished by transforming the 4 corners
     433                 :         of src, and then setting dst to the bounds of those points.
     434                 :         @param dst  Where the transformed rectangle is written.
     435                 :         @param src  The original rectangle to be transformed.
     436                 :         @return the result of calling rectStaysRect()
     437                 :     */
     438                 :     bool mapRect(SkRect* dst, const SkRect& src) const;
     439                 : 
     440                 :     /** Apply this matrix to the rectangle, and write the transformed rectangle
     441                 :         back into it. This is accomplished by transforming the 4 corners of
     442                 :         rect, and then setting it to the bounds of those points
     443                 :         @param rect The rectangle to transform.
     444                 :         @return the result of calling rectStaysRect()
     445                 :     */
     446                 :     bool mapRect(SkRect* rect) const {
     447                 :         return this->mapRect(rect, *rect);
     448                 :     }
     449                 : 
     450                 :     /** Return the mean radius of a circle after it has been mapped by
     451                 :         this matrix. NOTE: in perspective this value assumes the circle
     452                 :         has its center at the origin.
     453                 :     */
     454                 :     SkScalar mapRadius(SkScalar radius) const;
     455                 : 
     456                 :     typedef void (*MapXYProc)(const SkMatrix& mat, SkScalar x, SkScalar y,
     457                 :                                  SkPoint* result);
     458                 : 
     459                 :     static MapXYProc GetMapXYProc(TypeMask mask) {
     460                 :         SkASSERT((mask & ~kAllMasks) == 0);
     461                 :         return gMapXYProcs[mask & kAllMasks];
     462                 :     }
     463                 :     
     464                 :     MapXYProc getMapXYProc() const {
     465                 :         return GetMapXYProc(this->getType());
     466                 :     }
     467                 : 
     468                 :     typedef void (*MapPtsProc)(const SkMatrix& mat, SkPoint dst[],
     469                 :                                   const SkPoint src[], int count);
     470                 : 
     471                 :     static MapPtsProc GetMapPtsProc(TypeMask mask) {
     472                 :         SkASSERT((mask & ~kAllMasks) == 0);
     473                 :         return gMapPtsProcs[mask & kAllMasks];
     474                 :     }
     475                 :     
     476                 :     MapPtsProc getMapPtsProc() const {
     477                 :         return GetMapPtsProc(this->getType());
     478                 :     }
     479                 : 
     480                 :     /** If the matrix can be stepped in X (not complex perspective)
     481                 :         then return true and if step[XY] is not null, return the step[XY] value.
     482                 :         If it cannot, return false and ignore step.
     483                 :     */
     484                 :     bool fixedStepInX(SkScalar y, SkFixed* stepX, SkFixed* stepY) const;
     485                 : 
     486                 : #ifdef SK_SCALAR_IS_FIXED
     487                 :     friend bool operator==(const SkMatrix& a, const SkMatrix& b) {
     488                 :         return memcmp(a.fMat, b.fMat, sizeof(a.fMat)) == 0;
     489                 :     }
     490                 : 
     491                 :     friend bool operator!=(const SkMatrix& a, const SkMatrix& b) {
     492                 :         return memcmp(a.fMat, b.fMat, sizeof(a.fMat)) != 0;
     493                 :     }
     494                 : #else
     495                 :     friend bool operator==(const SkMatrix& a, const SkMatrix& b);    
     496                 :     friend bool operator!=(const SkMatrix& a, const SkMatrix& b) {
     497                 :         return !(a == b);
     498                 :     }
     499                 : #endif
     500                 : 
     501                 :     enum {
     502                 :         // flatten/unflatten will never return a value larger than this
     503                 :         kMaxFlattenSize = 9 * sizeof(SkScalar) + sizeof(uint32_t)
     504                 :     };
     505                 :     // return the number of bytes written, whether or not buffer is null
     506                 :     uint32_t flatten(void* buffer) const;
     507                 :     // return the number of bytes read
     508                 :     uint32_t unflatten(const void* buffer);
     509                 :     
     510                 :     void dump() const;
     511                 :     void toDumpString(SkString*) const;
     512                 : 
     513                 :     /**
     514                 :      * Calculates the maximum stretching factor of the matrix. If the matrix has
     515                 :      * perspective -1 is returned.
     516                 :      *
     517                 :      * @return maximum strecthing factor
     518                 :      */
     519                 :     SkScalar getMaxStretch() const;
     520                 : 
     521                 :     /**
     522                 :      *  Return a reference to a const identity matrix
     523                 :      */
     524                 :     static const SkMatrix& I();
     525                 : 
     526                 :     /**
     527                 :      *  Return a reference to a const matrix that is "invalid", one that could
     528                 :      *  never be used.
     529                 :      */
     530                 :     static const SkMatrix& InvalidMatrix();
     531                 : 
     532                 :     /**
     533                 :      * Testing routine; the matrix's type cache should never need to be
     534                 :      * manually invalidated during normal use.
     535                 :      */
     536                 :     void dirtyMatrixTypeCache() {
     537                 :         this->setTypeMask(kUnknown_Mask);
     538                 :     }
     539                 : 
     540                 : private:
     541                 :     enum {
     542                 :         /** Set if the matrix will map a rectangle to another rectangle. This
     543                 :             can be true if the matrix is scale-only, or rotates a multiple of
     544                 :             90 degrees. This bit is not set if the matrix is identity.
     545                 :              
     546                 :             This bit will be set on identity matrices
     547                 :         */
     548                 :         kRectStaysRect_Mask = 0x10,
     549                 : 
     550                 :         /** Set if the perspective bit is valid even though the rest of
     551                 :             the matrix is Unknown.
     552                 :         */
     553                 :         kOnlyPerspectiveValid_Mask = 0x40,
     554                 : 
     555                 :         kUnknown_Mask = 0x80,
     556                 : 
     557                 :         kORableMasks =  kTranslate_Mask |
     558                 :                         kScale_Mask |
     559                 :                         kAffine_Mask |
     560                 :                         kPerspective_Mask,
     561                 : 
     562                 :         kAllMasks = kTranslate_Mask |
     563                 :                     kScale_Mask |
     564                 :                     kAffine_Mask |
     565                 :                     kPerspective_Mask |
     566                 :                     kRectStaysRect_Mask
     567                 :     };
     568                 : 
     569                 :     SkScalar        fMat[9];
     570                 :     mutable uint8_t fTypeMask;
     571                 : 
     572                 :     uint8_t computeTypeMask() const;
     573                 :     uint8_t computePerspectiveTypeMask() const;
     574                 : 
     575               0 :     void setTypeMask(int mask) {
     576                 :         // allow kUnknown or a valid mask
     577               0 :         SkASSERT(kUnknown_Mask == mask || (mask & kAllMasks) == mask ||
     578                 :                  ((kUnknown_Mask | kOnlyPerspectiveValid_Mask | kPerspective_Mask) & mask)
     579                 :                  == mask);
     580               0 :         fTypeMask = SkToU8(mask);
     581               0 :     }
     582                 : 
     583                 :     void orTypeMask(int mask) {
     584                 :         SkASSERT((mask & kORableMasks) == mask);
     585                 :         fTypeMask = SkToU8(fTypeMask | mask);
     586                 :     }
     587                 : 
     588                 :     void clearTypeMask(int mask) {
     589                 :         // only allow a valid mask
     590                 :         SkASSERT((mask & kAllMasks) == mask);
     591                 :         fTypeMask &= ~mask;
     592                 :     }
     593                 : 
     594                 :     TypeMask getPerspectiveTypeMaskOnly() const {
     595                 :         if ((fTypeMask & kUnknown_Mask) &&
     596                 :             !(fTypeMask & kOnlyPerspectiveValid_Mask)) {
     597                 :             fTypeMask = this->computePerspectiveTypeMask();
     598                 :         }
     599                 :         return (TypeMask)(fTypeMask & 0xF);
     600                 :     }
     601                 : 
     602                 :     /** Returns true if we already know that the matrix is identity;
     603                 :         false otherwise.
     604                 :     */
     605                 :     bool isTriviallyIdentity() const {
     606                 :         if (fTypeMask & kUnknown_Mask) {
     607                 :             return false;
     608                 :         }
     609                 :         return ((fTypeMask & 0xF) == 0);
     610                 :     }
     611                 :     
     612                 :     static bool Poly2Proc(const SkPoint[], SkMatrix*, const SkPoint& scale);
     613                 :     static bool Poly3Proc(const SkPoint[], SkMatrix*, const SkPoint& scale);
     614                 :     static bool Poly4Proc(const SkPoint[], SkMatrix*, const SkPoint& scale);
     615                 : 
     616                 :     static void Identity_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
     617                 :     static void Trans_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
     618                 :     static void Scale_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
     619                 :     static void ScaleTrans_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
     620                 :     static void Rot_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
     621                 :     static void RotTrans_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
     622                 :     static void Persp_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
     623                 :     
     624                 :     static const MapXYProc gMapXYProcs[];
     625                 :     
     626                 :     static void Identity_pts(const SkMatrix&, SkPoint[], const SkPoint[], int);
     627                 :     static void Trans_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], int);
     628                 :     static void Scale_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], int);
     629                 :     static void ScaleTrans_pts(const SkMatrix&, SkPoint dst[], const SkPoint[],
     630                 :                                int count);
     631                 :     static void Rot_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], int);
     632                 :     static void RotTrans_pts(const SkMatrix&, SkPoint dst[], const SkPoint[],
     633                 :                              int count);
     634                 :     static void Persp_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], int);
     635                 :     
     636                 :     static const MapPtsProc gMapPtsProcs[];
     637                 : 
     638                 :     friend class SkPerspIter;
     639                 : };
     640                 : 
     641                 : #endif

Generated by: LCOV version 1.7