gfx/skia/trunk/include/core/SkMatrix.h

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

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

mercurial