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

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/skia/trunk/include/core/SkMatrix.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,703 @@
     1.4 +
     1.5 +/*
     1.6 + * Copyright 2006 The Android Open Source Project
     1.7 + *
     1.8 + * Use of this source code is governed by a BSD-style license that can be
     1.9 + * found in the LICENSE file.
    1.10 + */
    1.11 +
    1.12 +
    1.13 +#ifndef SkMatrix_DEFINED
    1.14 +#define SkMatrix_DEFINED
    1.15 +
    1.16 +#include "SkRect.h"
    1.17 +
    1.18 +class SkString;
    1.19 +
    1.20 +// TODO: can we remove these 3 (need to check chrome/android)
    1.21 +typedef SkScalar SkPersp;
    1.22 +#define SkScalarToPersp(x) (x)
    1.23 +#define SkPerspToScalar(x) (x)
    1.24 +
    1.25 +/** \class SkMatrix
    1.26 +
    1.27 +    The SkMatrix class holds a 3x3 matrix for transforming coordinates.
    1.28 +    SkMatrix does not have a constructor, so it must be explicitly initialized
    1.29 +    using either reset() - to construct an identity matrix, or one of the set
    1.30 +    functions (e.g. setTranslate, setRotate, etc.).
    1.31 +*/
    1.32 +class SK_API SkMatrix {
    1.33 +public:
    1.34 +    /** Enum of bit fields for the mask return by getType().
    1.35 +        Use this to identify the complexity of the matrix.
    1.36 +    */
    1.37 +    enum TypeMask {
    1.38 +        kIdentity_Mask      = 0,
    1.39 +        kTranslate_Mask     = 0x01,  //!< set if the matrix has translation
    1.40 +        kScale_Mask         = 0x02,  //!< set if the matrix has X or Y scale
    1.41 +        kAffine_Mask        = 0x04,  //!< set if the matrix skews or rotates
    1.42 +        kPerspective_Mask   = 0x08   //!< set if the matrix is in perspective
    1.43 +    };
    1.44 +
    1.45 +    /** Returns a bitfield describing the transformations the matrix may
    1.46 +        perform. The bitfield is computed conservatively, so it may include
    1.47 +        false positives. For example, when kPerspective_Mask is true, all
    1.48 +        other bits may be set to true even in the case of a pure perspective
    1.49 +        transform.
    1.50 +   */
    1.51 +    TypeMask getType() const {
    1.52 +        if (fTypeMask & kUnknown_Mask) {
    1.53 +            fTypeMask = this->computeTypeMask();
    1.54 +        }
    1.55 +        // only return the public masks
    1.56 +        return (TypeMask)(fTypeMask & 0xF);
    1.57 +    }
    1.58 +
    1.59 +    /** Returns true if the matrix is identity.
    1.60 +    */
    1.61 +    bool isIdentity() const {
    1.62 +        return this->getType() == 0;
    1.63 +    }
    1.64 +
    1.65 +    /** Returns true if will map a rectangle to another rectangle. This can be
    1.66 +        true if the matrix is identity, scale-only, or rotates a multiple of
    1.67 +        90 degrees.
    1.68 +    */
    1.69 +    bool rectStaysRect() const {
    1.70 +        if (fTypeMask & kUnknown_Mask) {
    1.71 +            fTypeMask = this->computeTypeMask();
    1.72 +        }
    1.73 +        return (fTypeMask & kRectStaysRect_Mask) != 0;
    1.74 +    }
    1.75 +    // alias for rectStaysRect()
    1.76 +    bool preservesAxisAlignment() const { return this->rectStaysRect(); }
    1.77 +
    1.78 +    /**
    1.79 +     *  Returns true if the matrix contains perspective elements.
    1.80 +     */
    1.81 +    bool hasPerspective() const {
    1.82 +        return SkToBool(this->getPerspectiveTypeMaskOnly() &
    1.83 +                        kPerspective_Mask);
    1.84 +    }
    1.85 +
    1.86 +    /** Returns true if the matrix contains only translation, rotation or uniform scale
    1.87 +        Returns false if other transformation types are included or is degenerate
    1.88 +     */
    1.89 +    bool isSimilarity(SkScalar tol = SK_ScalarNearlyZero) const;
    1.90 +
    1.91 +    /** Returns true if the matrix contains only translation, rotation or scale
    1.92 +        (non-uniform scale is allowed).
    1.93 +        Returns false if other transformation types are included or is degenerate
    1.94 +     */
    1.95 +    bool preservesRightAngles(SkScalar tol = SK_ScalarNearlyZero) const;
    1.96 +
    1.97 +    enum {
    1.98 +        kMScaleX,
    1.99 +        kMSkewX,
   1.100 +        kMTransX,
   1.101 +        kMSkewY,
   1.102 +        kMScaleY,
   1.103 +        kMTransY,
   1.104 +        kMPersp0,
   1.105 +        kMPersp1,
   1.106 +        kMPersp2
   1.107 +    };
   1.108 +
   1.109 +    /** Affine arrays are in column major order
   1.110 +        because that's how PDF and XPS like it.
   1.111 +     */
   1.112 +    enum {
   1.113 +        kAScaleX,
   1.114 +        kASkewY,
   1.115 +        kASkewX,
   1.116 +        kAScaleY,
   1.117 +        kATransX,
   1.118 +        kATransY
   1.119 +    };
   1.120 +
   1.121 +    SkScalar operator[](int index) const {
   1.122 +        SkASSERT((unsigned)index < 9);
   1.123 +        return fMat[index];
   1.124 +    }
   1.125 +
   1.126 +    SkScalar get(int index) const {
   1.127 +        SkASSERT((unsigned)index < 9);
   1.128 +        return fMat[index];
   1.129 +    }
   1.130 +
   1.131 +    SkScalar getScaleX() const { return fMat[kMScaleX]; }
   1.132 +    SkScalar getScaleY() const { return fMat[kMScaleY]; }
   1.133 +    SkScalar getSkewY() const { return fMat[kMSkewY]; }
   1.134 +    SkScalar getSkewX() const { return fMat[kMSkewX]; }
   1.135 +    SkScalar getTranslateX() const { return fMat[kMTransX]; }
   1.136 +    SkScalar getTranslateY() const { return fMat[kMTransY]; }
   1.137 +    SkPersp getPerspX() const { return fMat[kMPersp0]; }
   1.138 +    SkPersp getPerspY() const { return fMat[kMPersp1]; }
   1.139 +
   1.140 +    SkScalar& operator[](int index) {
   1.141 +        SkASSERT((unsigned)index < 9);
   1.142 +        this->setTypeMask(kUnknown_Mask);
   1.143 +        return fMat[index];
   1.144 +    }
   1.145 +
   1.146 +    void set(int index, SkScalar value) {
   1.147 +        SkASSERT((unsigned)index < 9);
   1.148 +        fMat[index] = value;
   1.149 +        this->setTypeMask(kUnknown_Mask);
   1.150 +    }
   1.151 +
   1.152 +    void setScaleX(SkScalar v) { this->set(kMScaleX, v); }
   1.153 +    void setScaleY(SkScalar v) { this->set(kMScaleY, v); }
   1.154 +    void setSkewY(SkScalar v) { this->set(kMSkewY, v); }
   1.155 +    void setSkewX(SkScalar v) { this->set(kMSkewX, v); }
   1.156 +    void setTranslateX(SkScalar v) { this->set(kMTransX, v); }
   1.157 +    void setTranslateY(SkScalar v) { this->set(kMTransY, v); }
   1.158 +    void setPerspX(SkPersp v) { this->set(kMPersp0, v); }
   1.159 +    void setPerspY(SkPersp v) { this->set(kMPersp1, v); }
   1.160 +
   1.161 +    void setAll(SkScalar scaleX, SkScalar skewX, SkScalar transX,
   1.162 +                SkScalar skewY, SkScalar scaleY, SkScalar transY,
   1.163 +                SkPersp persp0, SkPersp persp1, SkPersp persp2) {
   1.164 +        fMat[kMScaleX] = scaleX;
   1.165 +        fMat[kMSkewX]  = skewX;
   1.166 +        fMat[kMTransX] = transX;
   1.167 +        fMat[kMSkewY]  = skewY;
   1.168 +        fMat[kMScaleY] = scaleY;
   1.169 +        fMat[kMTransY] = transY;
   1.170 +        fMat[kMPersp0] = persp0;
   1.171 +        fMat[kMPersp1] = persp1;
   1.172 +        fMat[kMPersp2] = persp2;
   1.173 +        this->setTypeMask(kUnknown_Mask);
   1.174 +    }
   1.175 +
   1.176 +    /** Set the matrix to identity
   1.177 +    */
   1.178 +    void reset();
   1.179 +    // alias for reset()
   1.180 +    void setIdentity() { this->reset(); }
   1.181 +
   1.182 +    /** Set the matrix to translate by (dx, dy).
   1.183 +    */
   1.184 +    void setTranslate(SkScalar dx, SkScalar dy);
   1.185 +    void setTranslate(const SkVector& v) { this->setTranslate(v.fX, v.fY); }
   1.186 +
   1.187 +    /** Set the matrix to scale by sx and sy, with a pivot point at (px, py).
   1.188 +        The pivot point is the coordinate that should remain unchanged by the
   1.189 +        specified transformation.
   1.190 +    */
   1.191 +    void setScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py);
   1.192 +    /** Set the matrix to scale by sx and sy.
   1.193 +    */
   1.194 +    void setScale(SkScalar sx, SkScalar sy);
   1.195 +    /** Set the matrix to scale by 1/divx and 1/divy. Returns false and doesn't
   1.196 +        touch the matrix if either divx or divy is zero.
   1.197 +    */
   1.198 +    bool setIDiv(int divx, int divy);
   1.199 +    /** Set the matrix to rotate by the specified number of degrees, with a
   1.200 +        pivot point at (px, py). The pivot point is the coordinate that should
   1.201 +        remain unchanged by the specified transformation.
   1.202 +    */
   1.203 +    void setRotate(SkScalar degrees, SkScalar px, SkScalar py);
   1.204 +    /** Set the matrix to rotate about (0,0) by the specified number of degrees.
   1.205 +    */
   1.206 +    void setRotate(SkScalar degrees);
   1.207 +    /** Set the matrix to rotate by the specified sine and cosine values, with
   1.208 +        a pivot point at (px, py). The pivot point is the coordinate that
   1.209 +        should remain unchanged by the specified transformation.
   1.210 +    */
   1.211 +    void setSinCos(SkScalar sinValue, SkScalar cosValue,
   1.212 +                   SkScalar px, SkScalar py);
   1.213 +    /** Set the matrix to rotate by the specified sine and cosine values.
   1.214 +    */
   1.215 +    void setSinCos(SkScalar sinValue, SkScalar cosValue);
   1.216 +    /** Set the matrix to skew by sx and sy, with a pivot point at (px, py).
   1.217 +        The pivot point is the coordinate that should remain unchanged by the
   1.218 +        specified transformation.
   1.219 +    */
   1.220 +    void setSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py);
   1.221 +    /** Set the matrix to skew by sx and sy.
   1.222 +    */
   1.223 +    void setSkew(SkScalar kx, SkScalar ky);
   1.224 +    /** Set the matrix to the concatenation of the two specified matrices,
   1.225 +        returning true if the the result can be represented. Either of the
   1.226 +        two matrices may also be the target matrix. *this = a * b;
   1.227 +    */
   1.228 +    bool setConcat(const SkMatrix& a, const SkMatrix& b);
   1.229 +
   1.230 +    /** Preconcats the matrix with the specified translation.
   1.231 +        M' = M * T(dx, dy)
   1.232 +    */
   1.233 +    bool preTranslate(SkScalar dx, SkScalar dy);
   1.234 +    /** Preconcats the matrix with the specified scale.
   1.235 +        M' = M * S(sx, sy, px, py)
   1.236 +    */
   1.237 +    bool preScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py);
   1.238 +    /** Preconcats the matrix with the specified scale.
   1.239 +        M' = M * S(sx, sy)
   1.240 +    */
   1.241 +    bool preScale(SkScalar sx, SkScalar sy);
   1.242 +    /** Preconcats the matrix with the specified rotation.
   1.243 +        M' = M * R(degrees, px, py)
   1.244 +    */
   1.245 +    bool preRotate(SkScalar degrees, SkScalar px, SkScalar py);
   1.246 +    /** Preconcats the matrix with the specified rotation.
   1.247 +        M' = M * R(degrees)
   1.248 +    */
   1.249 +    bool preRotate(SkScalar degrees);
   1.250 +    /** Preconcats the matrix with the specified skew.
   1.251 +        M' = M * K(kx, ky, px, py)
   1.252 +    */
   1.253 +    bool preSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py);
   1.254 +    /** Preconcats the matrix with the specified skew.
   1.255 +        M' = M * K(kx, ky)
   1.256 +    */
   1.257 +    bool preSkew(SkScalar kx, SkScalar ky);
   1.258 +    /** Preconcats the matrix with the specified matrix.
   1.259 +        M' = M * other
   1.260 +    */
   1.261 +    bool preConcat(const SkMatrix& other);
   1.262 +
   1.263 +    /** Postconcats the matrix with the specified translation.
   1.264 +        M' = T(dx, dy) * M
   1.265 +    */
   1.266 +    bool postTranslate(SkScalar dx, SkScalar dy);
   1.267 +    /** Postconcats the matrix with the specified scale.
   1.268 +        M' = S(sx, sy, px, py) * M
   1.269 +    */
   1.270 +    bool postScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py);
   1.271 +    /** Postconcats the matrix with the specified scale.
   1.272 +        M' = S(sx, sy) * M
   1.273 +    */
   1.274 +    bool postScale(SkScalar sx, SkScalar sy);
   1.275 +    /** Postconcats the matrix by dividing it by the specified integers.
   1.276 +        M' = S(1/divx, 1/divy, 0, 0) * M
   1.277 +    */
   1.278 +    bool postIDiv(int divx, int divy);
   1.279 +    /** Postconcats the matrix with the specified rotation.
   1.280 +        M' = R(degrees, px, py) * M
   1.281 +    */
   1.282 +    bool postRotate(SkScalar degrees, SkScalar px, SkScalar py);
   1.283 +    /** Postconcats the matrix with the specified rotation.
   1.284 +        M' = R(degrees) * M
   1.285 +    */
   1.286 +    bool postRotate(SkScalar degrees);
   1.287 +    /** Postconcats the matrix with the specified skew.
   1.288 +        M' = K(kx, ky, px, py) * M
   1.289 +    */
   1.290 +    bool postSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py);
   1.291 +    /** Postconcats the matrix with the specified skew.
   1.292 +        M' = K(kx, ky) * M
   1.293 +    */
   1.294 +    bool postSkew(SkScalar kx, SkScalar ky);
   1.295 +    /** Postconcats the matrix with the specified matrix.
   1.296 +        M' = other * M
   1.297 +    */
   1.298 +    bool postConcat(const SkMatrix& other);
   1.299 +
   1.300 +    enum ScaleToFit {
   1.301 +        /**
   1.302 +         * Scale in X and Y independently, so that src matches dst exactly.
   1.303 +         * This may change the aspect ratio of the src.
   1.304 +         */
   1.305 +        kFill_ScaleToFit,
   1.306 +        /**
   1.307 +         * Compute a scale that will maintain the original src aspect ratio,
   1.308 +         * but will also ensure that src fits entirely inside dst. At least one
   1.309 +         * axis (X or Y) will fit exactly. kStart aligns the result to the
   1.310 +         * left and top edges of dst.
   1.311 +         */
   1.312 +        kStart_ScaleToFit,
   1.313 +        /**
   1.314 +         * Compute a scale that will maintain the original src aspect ratio,
   1.315 +         * but will also ensure that src fits entirely inside dst. At least one
   1.316 +         * axis (X or Y) will fit exactly. The result is centered inside dst.
   1.317 +         */
   1.318 +        kCenter_ScaleToFit,
   1.319 +        /**
   1.320 +         * Compute a scale that will maintain the original src aspect ratio,
   1.321 +         * but will also ensure that src fits entirely inside dst. At least one
   1.322 +         * axis (X or Y) will fit exactly. kEnd aligns the result to the
   1.323 +         * right and bottom edges of dst.
   1.324 +         */
   1.325 +        kEnd_ScaleToFit
   1.326 +    };
   1.327 +
   1.328 +    /** Set the matrix to the scale and translate values that map the source
   1.329 +        rectangle to the destination rectangle, returning true if the the result
   1.330 +        can be represented.
   1.331 +        @param src the source rectangle to map from.
   1.332 +        @param dst the destination rectangle to map to.
   1.333 +        @param stf the ScaleToFit option
   1.334 +        @return true if the matrix can be represented by the rectangle mapping.
   1.335 +    */
   1.336 +    bool setRectToRect(const SkRect& src, const SkRect& dst, ScaleToFit stf);
   1.337 +
   1.338 +    /** Set the matrix such that the specified src points would map to the
   1.339 +        specified dst points. count must be within [0..4].
   1.340 +        @param src  The array of src points
   1.341 +        @param dst  The array of dst points
   1.342 +        @param count The number of points to use for the transformation
   1.343 +        @return true if the matrix was set to the specified transformation
   1.344 +    */
   1.345 +    bool setPolyToPoly(const SkPoint src[], const SkPoint dst[], int count);
   1.346 +
   1.347 +    /** If this matrix can be inverted, return true and if inverse is not null,
   1.348 +        set inverse to be the inverse of this matrix. If this matrix cannot be
   1.349 +        inverted, ignore inverse and return false
   1.350 +    */
   1.351 +    bool SK_WARN_UNUSED_RESULT invert(SkMatrix* inverse) const {
   1.352 +        // Allow the trivial case to be inlined.
   1.353 +        if (this->isIdentity()) {
   1.354 +            if (NULL != inverse) {
   1.355 +                inverse->reset();
   1.356 +            }
   1.357 +            return true;
   1.358 +        }
   1.359 +        return this->invertNonIdentity(inverse);
   1.360 +    }
   1.361 +
   1.362 +    /** Fills the passed array with affine identity values
   1.363 +        in column major order.
   1.364 +        @param affine  The array to fill with affine identity values.
   1.365 +        Must not be NULL.
   1.366 +    */
   1.367 +    static void SetAffineIdentity(SkScalar affine[6]);
   1.368 +
   1.369 +    /** Fills the passed array with the affine values in column major order.
   1.370 +        If the matrix is a perspective transform, returns false
   1.371 +        and does not change the passed array.
   1.372 +        @param affine  The array to fill with affine values. Ignored if NULL.
   1.373 +    */
   1.374 +    bool asAffine(SkScalar affine[6]) const;
   1.375 +
   1.376 +    /** Apply this matrix to the array of points specified by src, and write
   1.377 +        the transformed points into the array of points specified by dst.
   1.378 +        dst[] = M * src[]
   1.379 +        @param dst  Where the transformed coordinates are written. It must
   1.380 +                    contain at least count entries
   1.381 +        @param src  The original coordinates that are to be transformed. It
   1.382 +                    must contain at least count entries
   1.383 +        @param count The number of points in src to read, and then transform
   1.384 +                     into dst.
   1.385 +    */
   1.386 +    void mapPoints(SkPoint dst[], const SkPoint src[], int count) const;
   1.387 +
   1.388 +    /** Apply this matrix to the array of points, overwriting it with the
   1.389 +        transformed values.
   1.390 +        dst[] = M * pts[]
   1.391 +        @param pts  The points to be transformed. It must contain at least
   1.392 +                    count entries
   1.393 +        @param count The number of points in pts.
   1.394 +    */
   1.395 +    void mapPoints(SkPoint pts[], int count) const {
   1.396 +        this->mapPoints(pts, pts, count);
   1.397 +    }
   1.398 +
   1.399 +    /** Like mapPoints but with custom byte stride between the points. Stride
   1.400 +     *  should be a multiple of sizeof(SkScalar).
   1.401 +     */
   1.402 +    void mapPointsWithStride(SkPoint pts[], size_t stride, int count) const {
   1.403 +        SkASSERT(stride >= sizeof(SkPoint));
   1.404 +        SkASSERT(0 == stride % sizeof(SkScalar));
   1.405 +        for (int i = 0; i < count; ++i) {
   1.406 +            this->mapPoints(pts, pts, 1);
   1.407 +            pts = (SkPoint*)((intptr_t)pts + stride);
   1.408 +        }
   1.409 +    }
   1.410 +
   1.411 +    /** Like mapPoints but with custom byte stride between the points.
   1.412 +    */
   1.413 +    void mapPointsWithStride(SkPoint dst[], SkPoint src[],
   1.414 +                             size_t stride, int count) const {
   1.415 +        SkASSERT(stride >= sizeof(SkPoint));
   1.416 +        SkASSERT(0 == stride % sizeof(SkScalar));
   1.417 +        for (int i = 0; i < count; ++i) {
   1.418 +            this->mapPoints(dst, src, 1);
   1.419 +            src = (SkPoint*)((intptr_t)src + stride);
   1.420 +            dst = (SkPoint*)((intptr_t)dst + stride);
   1.421 +        }
   1.422 +    }
   1.423 +
   1.424 +    /** Apply this matrix to the array of homogeneous points, specified by src,
   1.425 +        where a homogeneous point is defined by 3 contiguous scalar values,
   1.426 +        and write the transformed points into the array of scalars specified by dst.
   1.427 +        dst[] = M * src[]
   1.428 +        @param dst  Where the transformed coordinates are written. It must
   1.429 +                    contain at least 3 * count entries
   1.430 +        @param src  The original coordinates that are to be transformed. It
   1.431 +                    must contain at least 3 * count entries
   1.432 +        @param count The number of triples (homogeneous points) in src to read,
   1.433 +                     and then transform into dst.
   1.434 +    */
   1.435 +    void mapHomogeneousPoints(SkScalar dst[], const SkScalar src[], int count) const;
   1.436 +
   1.437 +    void mapXY(SkScalar x, SkScalar y, SkPoint* result) const {
   1.438 +        SkASSERT(result);
   1.439 +        this->getMapXYProc()(*this, x, y, result);
   1.440 +    }
   1.441 +
   1.442 +    /** Apply this matrix to the array of vectors specified by src, and write
   1.443 +        the transformed vectors into the array of vectors specified by dst.
   1.444 +        This is similar to mapPoints, but ignores any translation in the matrix.
   1.445 +        @param dst  Where the transformed coordinates are written. It must
   1.446 +                    contain at least count entries
   1.447 +        @param src  The original coordinates that are to be transformed. It
   1.448 +                    must contain at least count entries
   1.449 +        @param count The number of vectors in src to read, and then transform
   1.450 +                     into dst.
   1.451 +    */
   1.452 +    void mapVectors(SkVector dst[], const SkVector src[], int count) const;
   1.453 +
   1.454 +    /** Apply this matrix to the array of vectors specified by src, and write
   1.455 +        the transformed vectors into the array of vectors specified by dst.
   1.456 +        This is similar to mapPoints, but ignores any translation in the matrix.
   1.457 +        @param vecs The vectors to be transformed. It must contain at least
   1.458 +                    count entries
   1.459 +        @param count The number of vectors in vecs.
   1.460 +    */
   1.461 +    void mapVectors(SkVector vecs[], int count) const {
   1.462 +        this->mapVectors(vecs, vecs, count);
   1.463 +    }
   1.464 +
   1.465 +    /** Apply this matrix to the src rectangle, and write the transformed
   1.466 +        rectangle into dst. This is accomplished by transforming the 4 corners
   1.467 +        of src, and then setting dst to the bounds of those points.
   1.468 +        @param dst  Where the transformed rectangle is written.
   1.469 +        @param src  The original rectangle to be transformed.
   1.470 +        @return the result of calling rectStaysRect()
   1.471 +    */
   1.472 +    bool mapRect(SkRect* dst, const SkRect& src) const;
   1.473 +
   1.474 +    /** Apply this matrix to the rectangle, and write the transformed rectangle
   1.475 +        back into it. This is accomplished by transforming the 4 corners of
   1.476 +        rect, and then setting it to the bounds of those points
   1.477 +        @param rect The rectangle to transform.
   1.478 +        @return the result of calling rectStaysRect()
   1.479 +    */
   1.480 +    bool mapRect(SkRect* rect) const {
   1.481 +        return this->mapRect(rect, *rect);
   1.482 +    }
   1.483 +
   1.484 +    /** Apply this matrix to the src rectangle, and write the four transformed
   1.485 +        points into dst. The points written to dst will be the original top-left, top-right,
   1.486 +        bottom-right, and bottom-left points transformed by the matrix.
   1.487 +        @param dst  Where the transformed quad is written.
   1.488 +        @param rect The original rectangle to be transformed.
   1.489 +    */
   1.490 +    void mapRectToQuad(SkPoint dst[4], const SkRect& rect) const {
   1.491 +        // This could potentially be faster if we only transformed each x and y of the rect once.
   1.492 +        rect.toQuad(dst);
   1.493 +        this->mapPoints(dst, 4);
   1.494 +    }
   1.495 +
   1.496 +    /** Return the mean radius of a circle after it has been mapped by
   1.497 +        this matrix. NOTE: in perspective this value assumes the circle
   1.498 +        has its center at the origin.
   1.499 +    */
   1.500 +    SkScalar mapRadius(SkScalar radius) const;
   1.501 +
   1.502 +    typedef void (*MapXYProc)(const SkMatrix& mat, SkScalar x, SkScalar y,
   1.503 +                                 SkPoint* result);
   1.504 +
   1.505 +    static MapXYProc GetMapXYProc(TypeMask mask) {
   1.506 +        SkASSERT((mask & ~kAllMasks) == 0);
   1.507 +        return gMapXYProcs[mask & kAllMasks];
   1.508 +    }
   1.509 +
   1.510 +    MapXYProc getMapXYProc() const {
   1.511 +        return GetMapXYProc(this->getType());
   1.512 +    }
   1.513 +
   1.514 +    typedef void (*MapPtsProc)(const SkMatrix& mat, SkPoint dst[],
   1.515 +                                  const SkPoint src[], int count);
   1.516 +
   1.517 +    static MapPtsProc GetMapPtsProc(TypeMask mask) {
   1.518 +        SkASSERT((mask & ~kAllMasks) == 0);
   1.519 +        return gMapPtsProcs[mask & kAllMasks];
   1.520 +    }
   1.521 +
   1.522 +    MapPtsProc getMapPtsProc() const {
   1.523 +        return GetMapPtsProc(this->getType());
   1.524 +    }
   1.525 +
   1.526 +    /** If the matrix can be stepped in X (not complex perspective)
   1.527 +        then return true and if step[XY] is not null, return the step[XY] value.
   1.528 +        If it cannot, return false and ignore step.
   1.529 +    */
   1.530 +    bool fixedStepInX(SkScalar y, SkFixed* stepX, SkFixed* stepY) const;
   1.531 +
   1.532 +    /** Efficient comparison of two matrices. It distinguishes between zero and
   1.533 +     *  negative zero. It will return false when the sign of zero values is the
   1.534 +     *  only difference between the two matrices. It considers NaN values to be
   1.535 +     *  equal to themselves. So a matrix full of NaNs is "cheap equal" to
   1.536 +     *  another matrix full of NaNs iff the NaN values are bitwise identical
   1.537 +     *  while according to strict the strict == test a matrix with a NaN value
   1.538 +     *  is equal to nothing, including itself.
   1.539 +     */
   1.540 +    bool cheapEqualTo(const SkMatrix& m) const {
   1.541 +        return 0 == memcmp(fMat, m.fMat, sizeof(fMat));
   1.542 +    }
   1.543 +
   1.544 +    friend bool operator==(const SkMatrix& a, const SkMatrix& b);
   1.545 +    friend bool operator!=(const SkMatrix& a, const SkMatrix& b) {
   1.546 +        return !(a == b);
   1.547 +    }
   1.548 +
   1.549 +    enum {
   1.550 +        // writeTo/readFromMemory will never return a value larger than this
   1.551 +        kMaxFlattenSize = 9 * sizeof(SkScalar) + sizeof(uint32_t)
   1.552 +    };
   1.553 +    // return the number of bytes written, whether or not buffer is null
   1.554 +    size_t writeToMemory(void* buffer) const;
   1.555 +    /**
   1.556 +     * Reads data from the buffer parameter
   1.557 +     *
   1.558 +     * @param buffer Memory to read from
   1.559 +     * @param length Amount of memory available in the buffer
   1.560 +     * @return number of bytes read (must be a multiple of 4) or
   1.561 +     *         0 if there was not enough memory available
   1.562 +     */
   1.563 +    size_t readFromMemory(const void* buffer, size_t length);
   1.564 +
   1.565 +    SkDEVCODE(void dump() const;)
   1.566 +    SK_TO_STRING_NONVIRT()
   1.567 +
   1.568 +    /**
   1.569 +     * Calculates the minimum stretching factor of the matrix. If the matrix has
   1.570 +     * perspective -1 is returned.
   1.571 +     *
   1.572 +     * @return minumum strecthing factor
   1.573 +     */
   1.574 +    SkScalar getMinStretch() const;
   1.575 +
   1.576 +    /**
   1.577 +     * Calculates the maximum stretching factor of the matrix. If the matrix has
   1.578 +     * perspective -1 is returned.
   1.579 +     *
   1.580 +     * @return maximum strecthing factor
   1.581 +     */
   1.582 +    SkScalar getMaxStretch() const;
   1.583 +
   1.584 +    /**
   1.585 +     *  Return a reference to a const identity matrix
   1.586 +     */
   1.587 +    static const SkMatrix& I();
   1.588 +
   1.589 +    /**
   1.590 +     *  Return a reference to a const matrix that is "invalid", one that could
   1.591 +     *  never be used.
   1.592 +     */
   1.593 +    static const SkMatrix& InvalidMatrix();
   1.594 +
   1.595 +    /**
   1.596 +     * Testing routine; the matrix's type cache should never need to be
   1.597 +     * manually invalidated during normal use.
   1.598 +     */
   1.599 +    void dirtyMatrixTypeCache() {
   1.600 +        this->setTypeMask(kUnknown_Mask);
   1.601 +    }
   1.602 +
   1.603 +private:
   1.604 +    enum {
   1.605 +        /** Set if the matrix will map a rectangle to another rectangle. This
   1.606 +            can be true if the matrix is scale-only, or rotates a multiple of
   1.607 +            90 degrees.
   1.608 +
   1.609 +            This bit will be set on identity matrices
   1.610 +        */
   1.611 +        kRectStaysRect_Mask = 0x10,
   1.612 +
   1.613 +        /** Set if the perspective bit is valid even though the rest of
   1.614 +            the matrix is Unknown.
   1.615 +        */
   1.616 +        kOnlyPerspectiveValid_Mask = 0x40,
   1.617 +
   1.618 +        kUnknown_Mask = 0x80,
   1.619 +
   1.620 +        kORableMasks =  kTranslate_Mask |
   1.621 +                        kScale_Mask |
   1.622 +                        kAffine_Mask |
   1.623 +                        kPerspective_Mask,
   1.624 +
   1.625 +        kAllMasks = kTranslate_Mask |
   1.626 +                    kScale_Mask |
   1.627 +                    kAffine_Mask |
   1.628 +                    kPerspective_Mask |
   1.629 +                    kRectStaysRect_Mask
   1.630 +    };
   1.631 +
   1.632 +    SkScalar         fMat[9];
   1.633 +    mutable uint32_t fTypeMask;
   1.634 +
   1.635 +    uint8_t computeTypeMask() const;
   1.636 +    uint8_t computePerspectiveTypeMask() const;
   1.637 +
   1.638 +    void setTypeMask(int mask) {
   1.639 +        // allow kUnknown or a valid mask
   1.640 +        SkASSERT(kUnknown_Mask == mask || (mask & kAllMasks) == mask ||
   1.641 +                 ((kUnknown_Mask | kOnlyPerspectiveValid_Mask) & mask)
   1.642 +                 == (kUnknown_Mask | kOnlyPerspectiveValid_Mask));
   1.643 +        fTypeMask = SkToU8(mask);
   1.644 +    }
   1.645 +
   1.646 +    void orTypeMask(int mask) {
   1.647 +        SkASSERT((mask & kORableMasks) == mask);
   1.648 +        fTypeMask = SkToU8(fTypeMask | mask);
   1.649 +    }
   1.650 +
   1.651 +    void clearTypeMask(int mask) {
   1.652 +        // only allow a valid mask
   1.653 +        SkASSERT((mask & kAllMasks) == mask);
   1.654 +        fTypeMask &= ~mask;
   1.655 +    }
   1.656 +
   1.657 +    TypeMask getPerspectiveTypeMaskOnly() const {
   1.658 +        if ((fTypeMask & kUnknown_Mask) &&
   1.659 +            !(fTypeMask & kOnlyPerspectiveValid_Mask)) {
   1.660 +            fTypeMask = this->computePerspectiveTypeMask();
   1.661 +        }
   1.662 +        return (TypeMask)(fTypeMask & 0xF);
   1.663 +    }
   1.664 +
   1.665 +    /** Returns true if we already know that the matrix is identity;
   1.666 +        false otherwise.
   1.667 +    */
   1.668 +    bool isTriviallyIdentity() const {
   1.669 +        if (fTypeMask & kUnknown_Mask) {
   1.670 +            return false;
   1.671 +        }
   1.672 +        return ((fTypeMask & 0xF) == 0);
   1.673 +    }
   1.674 +
   1.675 +    bool SK_WARN_UNUSED_RESULT invertNonIdentity(SkMatrix* inverse) const;
   1.676 +
   1.677 +    static bool Poly2Proc(const SkPoint[], SkMatrix*, const SkPoint& scale);
   1.678 +    static bool Poly3Proc(const SkPoint[], SkMatrix*, const SkPoint& scale);
   1.679 +    static bool Poly4Proc(const SkPoint[], SkMatrix*, const SkPoint& scale);
   1.680 +
   1.681 +    static void Identity_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
   1.682 +    static void Trans_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
   1.683 +    static void Scale_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
   1.684 +    static void ScaleTrans_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
   1.685 +    static void Rot_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
   1.686 +    static void RotTrans_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
   1.687 +    static void Persp_xy(const SkMatrix&, SkScalar, SkScalar, SkPoint*);
   1.688 +
   1.689 +    static const MapXYProc gMapXYProcs[];
   1.690 +
   1.691 +    static void Identity_pts(const SkMatrix&, SkPoint[], const SkPoint[], int);
   1.692 +    static void Trans_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], int);
   1.693 +    static void Scale_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], int);
   1.694 +    static void ScaleTrans_pts(const SkMatrix&, SkPoint dst[], const SkPoint[],
   1.695 +                               int count);
   1.696 +    static void Rot_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], int);
   1.697 +    static void RotTrans_pts(const SkMatrix&, SkPoint dst[], const SkPoint[],
   1.698 +                             int count);
   1.699 +    static void Persp_pts(const SkMatrix&, SkPoint dst[], const SkPoint[], int);
   1.700 +
   1.701 +    static const MapPtsProc gMapPtsProcs[];
   1.702 +
   1.703 +    friend class SkPerspIter;
   1.704 +};
   1.705 +
   1.706 +#endif

mercurial