diff options
author | Cary Clark <caryclark@skia.org> | 2017-10-30 11:48:35 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-10-30 16:30:49 +0000 |
commit | cc309eb9b18a707dfb94d89866a474bebf7f2777 (patch) | |
tree | 5c12476cae12568a01efd93f0fa89698f56ae02a /include/core/SkMatrix.h | |
parent | d2b8af11520ae26e6e6afca636dfcb87036d600d (diff) |
generated include refresh
The latest, minor changes on includes already
generated, plus four new ones.
TBR=reed@google.com
Bug: skia:6898
Change-Id: If06ae9b9aaa3a0a9fae570aa7a6698ff340c43b8
Reviewed-on: https://skia-review.googlesource.com/62862
Commit-Queue: Cary Clark <caryclark@skia.org>
Reviewed-by: Cary Clark <caryclark@skia.org>
Diffstat (limited to 'include/core/SkMatrix.h')
-rw-r--r-- | include/core/SkMatrix.h | 1637 |
1 files changed, 1340 insertions, 297 deletions
diff --git a/include/core/SkMatrix.h b/include/core/SkMatrix.h index 49be97aa29..58bcff8fc4 100644 --- a/include/core/SkMatrix.h +++ b/include/core/SkMatrix.h @@ -1,4 +1,3 @@ - /* * Copyright 2006 The Android Open Source Project * @@ -17,52 +16,89 @@ struct SkPoint3; class SkString; /** \class SkMatrix + SkMatrix holds a 3x3 matrix for transforming coordinates. This allows mapping + SkPoint and SkVector with translation, scaling, skewing, rotation, and + perspective. - The SkMatrix class holds a 3x3 matrix for transforming coordinates. - SkMatrix does not have a constructor, so it must be explicitly initialized - using either reset() - to construct an identity matrix, or one of the set - functions (e.g. setTranslate, setRotate, etc.). + SkMatrix elements are in row major order. SkMatrix does not have a constructor, + so it must be explicitly initialized. setIdentity() initializes SkMatrix + so it has no effect. setTranslate(), setScale(), setSkew(), setRotate(), set9 and setAll() + initializes all SkMatrix elements with the corresponding mapping. - SkMatrix is not thread safe unless you've first called SkMatrix::getType(). + SkMatrix includes a hidden variable that classifies the type of matrix to + improve performance. SkMatrix is not thread safe unless getType() is called first. */ SK_BEGIN_REQUIRE_DENSE class SK_API SkMatrix { public: + + /** Sets SkMatrix to scale by (sx, sy). Returned matrix is: + + | sx 0 0 | + | 0 sy 0 | + | 0 0 1 | + + @param sx horizontal scale factor + @param sy vertical scale factor + @return SkMatrix with scale + */ static SkMatrix SK_WARN_UNUSED_RESULT MakeScale(SkScalar sx, SkScalar sy) { SkMatrix m; m.setScale(sx, sy); return m; } + /** Sets SkMatrix to scale by (scale, scale). Returned matrix is: + + | scale 0 0 | + | 0 scale 0 | + | 0 0 1 | + + @param scale horizontal and vertical scale factor + @return SkMatrix with scale + */ static SkMatrix SK_WARN_UNUSED_RESULT MakeScale(SkScalar scale) { SkMatrix m; m.setScale(scale, scale); return m; } + /** Sets SkMatrix to translate by (dx, dy). Returned matrix is: + + | 1 0 dx | + | 0 1 dy | + | 0 0 1 | + + @param dx horizontal translation + @param dy vertical translation + @return SkMatrix with translation + */ static SkMatrix SK_WARN_UNUSED_RESULT MakeTrans(SkScalar dx, SkScalar dy) { SkMatrix m; m.setTranslate(dx, dy); return m; } - /** Enum of bit fields for the mask return by getType(). - Use this to identify the complexity of the matrix. + /** \enum SkMatrix::TypeMask + Enum of bit fields for mask returned by getType(). + Used to identify the complexity of SkMatrix, to optimize performance. */ enum TypeMask { - kIdentity_Mask = 0, - kTranslate_Mask = 0x01, //!< set if the matrix has translation - kScale_Mask = 0x02, //!< set if the matrix has X or Y scale - kAffine_Mask = 0x04, //!< set if the matrix skews or rotates - kPerspective_Mask = 0x08, //!< set if the matrix is in perspective + kIdentity_Mask = 0, //!< all bits clear if SkMatrix is identity + kTranslate_Mask = 0x01, //!< set if SkMatrix has translation + kScale_Mask = 0x02, //!< set if SkMatrix has x or y scale + kAffine_Mask = 0x04, //!< set if SkMatrix skews or rotates + kPerspective_Mask = 0x08, //!< set if SkMatrix has perspective }; - /** Returns a bitfield describing the transformations the matrix may - perform. The bitfield is computed conservatively, so it may include - false positives. For example, when kPerspective_Mask is true, all - other bits may be set to true even in the case of a pure perspective - transform. - */ + /** Returns a bit field describing the transformations the matrix may + perform. The bit field is computed conservatively, so it may include + false positives. For example, when kPerspective_Mask is set, all + other bits are set. + + @return kIdentity_Mask, or combinations of: kTranslate_Mask, kScale_Mask, + kAffine_Mask, kPerspective_Mask + */ TypeMask getType() const { if (fTypeMask & kUnknown_Mask) { fTypeMask = this->computeTypeMask(); @@ -71,21 +107,61 @@ public: return (TypeMask)(fTypeMask & 0xF); } - /** Returns true if the matrix is identity. + /** Returns true if SkMatrix is identity. Identity matrix is: + + | 1 0 0 | + | 0 1 0 | + | 0 0 1 | + + @return true if SkMatrix has no effect */ bool isIdentity() const { return this->getType() == 0; } + /** Returns true if SkMatrix at most scales and translates. SkMatrix may be identity, + contain only scale elements, only translate elements, or both. SkMatrix form is: + + | scale-x 0 translate-x | + | 0 scale-y translate-y | + | 0 0 1 | + + @return true if SkMatrix is identity; or scales, translates, or both + */ bool isScaleTranslate() const { return !(this->getType() & ~(kScale_Mask | kTranslate_Mask)); } + /** Returns true if SkMatrix is identity, or translates. SkMatrix form is: + + | 1 0 translate-x | + | 0 1 translate-y | + | 0 0 1 | + + @return true if SkMatrix is identity, or translates + */ bool isTranslate() const { return !(this->getType() & ~(kTranslate_Mask)); } - /** Returns true if will map a rectangle to another rectangle. This can be - true if the matrix is identity, scale-only, or rotates a multiple of - 90 degrees, or mirrors in x or y. + /** Returns true SkMatrix maps SkRect to another SkRect. If true, SkMatrix is identity, + or scales, or rotates a multiple of 90 degrees, or mirrors in x or y. In all + cases, SkMatrix may also have translation. SkMatrix form is either: + + | scale-x 0 translate-x | + | 0 scale-y translate-y | + | 0 0 1 | + + or + + | 0 rotate-x translate-x | + | rotate-y 0 translate-y | + | 0 0 1 | + + for non-zero values of scale-x, scale-y, rotate-x, and rotate-y. + + Also called preservesAxisAlignment(); use the one that provides better inline + documentation. + + @return true if SkMatrix maps one SkRect into another */ bool rectStaysRect() const { if (fTypeMask & kUnknown_Mask) { @@ -93,50 +169,102 @@ public: } return (fTypeMask & kRectStaysRect_Mask) != 0; } - // alias for rectStaysRect() + + /** Returns true SkMatrix maps SkRect to another SkRect. If true, SkMatrix is identity, + or scales, or rotates a multiple of 90 degrees, or mirrors in x or y. In all + cases, SkMatrix may also have translation. SkMatrix form is either: + + | scale-x 0 translate-x | + | 0 scale-y translate-y | + | 0 0 1 | + + or + + | 0 rotate-x translate-x | + | rotate-y 0 translate-y | + | 0 0 1 | + + for non-zero values of scale-x, scale-y, rotate-x, and rotate-y. + + Also called rectStaysRect(); use the one that provides better inline + documentation. + + @return true if SkMatrix maps one SkRect into another + */ bool preservesAxisAlignment() const { return this->rectStaysRect(); } - /** - * Returns true if the matrix contains perspective elements. - */ + /** Returns true if the matrix contains perspective elements. SkMatrix form is: + + | -- -- -- | + | -- -- -- | + | perspective-x perspective-y perspective-scale | + + where perspective-x or perspective-y is non-zero, or perspective-scale is + not one. All other elements may have any value. + + @return true if SkMatrix is in most general form + */ bool hasPerspective() const { return SkToBool(this->getPerspectiveTypeMaskOnly() & kPerspective_Mask); } - /** Returns true if the matrix contains only translation, rotation/reflection or uniform scale - Returns false if other transformation types are included or is degenerate - */ + /** Returns true if SkMatrix contains only translation, rotation, reflection, and + uniform scale. + Returns false if SkMatrix contains different scales, skewing, perspective, or + degenerate forms that collapse to a line or point. + + Describes that the SkMatrix makes rendering with and without the matrix are + visually alike; a transformed circle remains a circle. Mathematically, this is + referred to as similarity of a Euclidean space, or a similarity transformation. + + Preserves right angles, keeping the arms of the angle equal lengths. + + @param tol to be deprecated + @return true if SkMatrix only rotates, uniformly scales, translates + */ bool isSimilarity(SkScalar tol = SK_ScalarNearlyZero) const; - /** Returns true if the matrix contains only translation, rotation/reflection or scale - (non-uniform scale is allowed). - Returns false if other transformation types are included or is degenerate - */ + /** Returns true if SkMatrix contains only translation, rotation, reflection, and + scale. Scale may differ along rotated axes. + Returns false if SkMatrix skewing, perspective, or degenerate forms that collapse + to a line or point. + + Preserves right angles, but not requiring that the arms of the angle + retain equal lengths. + + @param tol to be deprecated + @return true if SkMatrix only rotates, scales, translates + */ bool preservesRightAngles(SkScalar tol = SK_ScalarNearlyZero) const; + /** \enum + SkMatrix organizes its values in row order. These members correspond to + each value in SkMatrix. + */ enum { - kMScaleX, - kMSkewX, - kMTransX, - kMSkewY, - kMScaleY, - kMTransY, - kMPersp0, - kMPersp1, - kMPersp2, + kMScaleX, //!< horizontal scale factor + kMSkewX, //!< horizontal skew factor + kMTransX, //!< horizontal translation + kMSkewY, //!< vertical skew factor + kMScaleY, //!< vertical scale factor + kMTransY, //!< vertical translation + kMPersp0, //!< input x perspective factor + kMPersp1, //!< input y perspective factor + kMPersp2, //!< perspective bias }; - /** Affine arrays are in column major order - because that's how PDF and XPS like it. - */ + /** \enum + Affine arrays are in column major order to match the matrix used by + PDF and XPS. + */ enum { - kAScaleX, - kASkewY, - kASkewX, - kAScaleY, - kATransX, - kATransY, + kAScaleX, //!< horizontal scale factor + kASkewY, //!< vertical skew factor + kASkewX, //!< horizontal skew factor + kAScaleY, //!< vertical scale factor + kATransX, //!< horizontal translation + kATransY, //!< vertical translation }; SkScalar operator[](int index) const { @@ -144,41 +272,169 @@ public: return fMat[index]; } + /** Returns one matrix value. Asserts if index is out of range and SK_DEBUG is + defined. + + @param index one of: kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY, + kMPersp0, kMPersp1, kMPersp2 + @return value corresponding to index + */ SkScalar get(int index) const { SkASSERT((unsigned)index < 9); return fMat[index]; } + /** Returns scale factor multiplied by x input, contributing to x output. + With mapPoints(), scales SkPoint along the x-axis. + + @return horizontal scale factor + */ SkScalar getScaleX() const { return fMat[kMScaleX]; } + + /** Returns scale factor multiplied by y input, contributing to y output. + With mapPoints(), scales SkPoint along the y-axis. + + @return vertical scale factor + */ SkScalar getScaleY() const { return fMat[kMScaleY]; } + + /** Returns scale factor multiplied by x input, contributing to y output. + With mapPoints(), skews SkPoint along the y-axis. + Skew x and y together can rotate SkPoint. + + @return vertical skew factor + */ SkScalar getSkewY() const { return fMat[kMSkewY]; } + + /** Returns scale factor multiplied by y input, contributing to x output. + With mapPoints(), skews SkPoint along the x-axis. + Skew x and y together can rotate SkPoint. + + @return horizontal scale factor + */ SkScalar getSkewX() const { return fMat[kMSkewX]; } + + /** Returns translation contributing to x output. + With mapPoints(), moves SkPoint along the x-axis. + + @return horizontal translation factor + */ SkScalar getTranslateX() const { return fMat[kMTransX]; } + + /** Returns translation contributing to y output. + With mapPoints(), moves SkPoint along the y-axis. + + @return vertical translation factor + */ SkScalar getTranslateY() const { return fMat[kMTransY]; } + + /** Returns factor scaling input x relative to input y. + + @return input x perspective factor + */ SkScalar getPerspX() const { return fMat[kMPersp0]; } + + /** Returns factor scaling input y relative to input x. + + @return input y perspective factor + */ SkScalar getPerspY() const { return fMat[kMPersp1]; } + /** Returns writable SkMatrix value. Asserts if index is out of range and SK_DEBUG is + defined. Clears internal cache anticipating that caller will change SkMatrix value. + + Next call to read SkMatrix state may recompute cache; subsequent writes to SkMatrix + value must be followed by dirtyMatrixTypeCache(). + + @param index one of: kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY, + kMPersp0, kMPersp1, kMPersp2 + @return writable value corresponding to index + */ SkScalar& operator[](int index) { SkASSERT((unsigned)index < 9); this->setTypeMask(kUnknown_Mask); return fMat[index]; } + /** Sets SkMatrix value. Asserts if index is out of range and SK_DEBUG is + defined. Safer than operator[]; internal cache is always maintained. + + @param index one of: kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY, + kMPersp0, kMPersp1, kMPersp2 + @param value scalar to store in SkMatrix + */ void set(int index, SkScalar value) { SkASSERT((unsigned)index < 9); fMat[index] = value; this->setTypeMask(kUnknown_Mask); } + /** Sets horizontal scale factor. + + @param v horizontal scale factor to store + */ void setScaleX(SkScalar v) { this->set(kMScaleX, v); } + + /** Sets vertical scale factor. + + @param v vertical scale factor to store + */ void setScaleY(SkScalar v) { this->set(kMScaleY, v); } + + /** Sets vertical skew factor. + + @param v vertical skew factor to store + */ void setSkewY(SkScalar v) { this->set(kMSkewY, v); } + + /** Sets horizontal skew factor. + + @param v horizontal skew factor to store + */ void setSkewX(SkScalar v) { this->set(kMSkewX, v); } + + /** Sets horizontal translation. + + @param v horizontal translation to store + */ void setTranslateX(SkScalar v) { this->set(kMTransX, v); } + + /** Sets vertical translation. + + @param v vertical translation to store + */ void setTranslateY(SkScalar v) { this->set(kMTransY, v); } + + /** Sets input x perspective factor, which causes mapXY() to vary input x inversely + proportional to input y. + + @param v perspective factor + */ void setPerspX(SkScalar v) { this->set(kMPersp0, v); } + + /** Sets input y perspective factor, which causes mapXY() to vary input y inversely + proportional to input x. + + @param v perspective factor + */ void setPerspY(SkScalar v) { this->set(kMPersp1, v); } + /** Sets all values from parameters. Sets matrix to: + + | scaleX skewX transX | + | skewY scaleY transY | + | persp0 persp1 persp2 | + + @param scaleX horizontal scale factor to store + @param skewX horizontal skew factor to store + @param transX horizontal translation to store + @param skewY vertical skew factor to store + @param scaleY vertical scale factor to store + @param transY vertical translation to store + @param persp0 input x perspective factor to store + @param persp1 input y perspective factor to store + @param persp2 perspective scale factor to store + */ void setAll(SkScalar scaleX, SkScalar skewX, SkScalar transX, SkScalar skewY, SkScalar scaleY, SkScalar transY, SkScalar persp0, SkScalar persp1, SkScalar persp2) { @@ -194,200 +450,684 @@ public: this->setTypeMask(kUnknown_Mask); } - /** - * Copy the 9 scalars for this matrix into buffer, in the same order as the kMScaleX - * enum... scalex, skewx, transx, skewy, scaley, transy, persp0, persp1, persp2 - */ + /** Copies nine scalar values contained by SkMatrix into buffer, in member value + ascending order: kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY, + kMPersp0, kMPersp1, kMPersp2. + + @param buffer storage for nine scalar values + */ void get9(SkScalar buffer[9]) const { memcpy(buffer, fMat, 9 * sizeof(SkScalar)); } - /** - * Set this matrix to the 9 scalars from the buffer, in the same order as the kMScaleX - * enum... scalex, skewx, transx, skewy, scaley, transy, persp0, persp1, persp2 - * - * Note: calling set9 followed by get9 may not return the exact same values. Since the matrix - * is used to map non-homogeneous coordinates, it is free to rescale the 9 values as needed. - */ + /** Sets SkMatrix to nine scalar values in buffer, in member value ascending order: + kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY, kMPersp0, kMPersp1, + kMPersp2. + + Sets matrix to: + + | buffer[0] buffer[1] buffer[2] | + | buffer[3] buffer[4] buffer[5] | + | buffer[6] buffer[7] buffer[8] | + + In the future, set9 followed by get9 may not return the same values. Since SkMatrix + maps non-homogeneous coordinates, scaling all nine values produces an equivalent + transformation, possibly improving precision. + + @param buffer nine scalar values + */ void set9(const SkScalar buffer[9]); - /** Set the matrix to identity + /** Sets SkMatrix to identity; which has no effect on mapped SkPoint. Sets SkMatrix to: + + | 1 0 0 | + | 0 1 0 | + | 0 0 1 | + + Also called setIdentity(); use the one that provides better inline + documentation. */ void reset(); - // alias for reset() + + /** Sets SkMatrix to identity; which has no effect on mapped SkPoint. Sets SkMatrix to: + + | 1 0 0 | + | 0 1 0 | + | 0 0 1 | + + Also called reset(); use the one that provides better inline + documentation. + */ void setIdentity() { this->reset(); } - /** Set the matrix to translate by (dx, dy). + /** Sets SkMatrix to translate by (dx, dy). + + @param dx horizontal translation + @param dy vertical translation */ void setTranslate(SkScalar dx, SkScalar dy); + + /** Sets SkMatrix to translate by (v.fX, v.fY). + + @param v SkVector containing horizontal and vertical translation + */ void setTranslate(const SkVector& v) { this->setTranslate(v.fX, v.fY); } - /** Set the matrix to scale by sx and sy, with a pivot point at (px, py). - The pivot point is the coordinate that should remain unchanged by the - specified transformation. + /** Sets SkMatrix to scale by sx and sy, about a pivot point at (px, py). + The pivot point is unchanged when mapped with SkMatrix. + + @param sx horizontal scale factor + @param sy vertical scale factor + @param px pivot x + @param py pivot y */ void setScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py); - /** Set the matrix to scale by sx and sy. + + /** Sets SkMatrix to scale by sx and sy about at pivot point at (0, 0). + + @param sx horizontal scale factor + @param sy vertical scale factor */ void setScale(SkScalar sx, SkScalar sy); - /** Set the matrix to scale by 1/divx and 1/divy. Returns false and doesn't - touch the matrix if either divx or divy is zero. + + /** Sets SkMatrix to rotate by degrees about a pivot point at (px, py). + The pivot point is unchanged when mapped with SkMatrix. + + Positive degrees rotates clockwise. + + @param degrees angle of axes relative to upright axes + @param px pivot x + @param py pivot y */ void setRotate(SkScalar degrees, SkScalar px, SkScalar py); - /** Set the matrix to rotate about (0,0) by the specified number of degrees. + + /** Sets SkMatrix to rotate by degrees about a pivot point at (0, 0). + Positive degrees rotates clockwise. + + @param degrees angle of axes relative to upright axes */ void setRotate(SkScalar degrees); - /** Set the matrix to rotate by the specified sine and cosine values, with - a pivot point at (px, py). The pivot point is the coordinate that - should remain unchanged by the specified transformation. + + /** Sets SkMatrix to rotate by sinValue and cosValue, about a pivot point at (px, py). + The pivot point is unchanged when mapped with SkMatrix. + + SkVector (sinValue, cosValue) describes the angle of rotation relative to (0, 1). + SkVector length specifies scale. + + @param sinValue rotation vector x component + @param cosValue rotation vector y component + @param px pivot x + @param py pivot y */ void setSinCos(SkScalar sinValue, SkScalar cosValue, SkScalar px, SkScalar py); - /** Set the matrix to rotate by the specified sine and cosine values. + + /** Sets SkMatrix to rotate by sinValue and cosValue, about a pivot point at (0, 0). + + SkVector (sinValue, cosValue) describes the angle of rotation relative to (0, 1). + SkVector length specifies scale. + + @param sinValue rotation vector x component + @param cosValue rotation vector y component */ void setSinCos(SkScalar sinValue, SkScalar cosValue); + /** Sets SkMatrix to rotate, scale, and translate using a compressed matrix form. + + SkVector (rsxForm.fSSin, rsxForm.fSCos) describes the angle of rotation relative + to (0, 1). SkVector length specifies scale. Mapped point is rotated and scaled + by SkVector, then translated by (rsxForm.fTx, rsxForm.fTy). + + @param rsxForm compressed SkRSXform matrix + @return reference to SkMatrix + */ SkMatrix& setRSXform(const SkRSXform& rsxForm); - /** Set the matrix to skew by sx and sy, with a pivot point at (px, py). - The pivot point is the coordinate that should remain unchanged by the - specified transformation. + /** Sets SkMatrix to skew by kx and ky, about a pivot point at (px, py). + The pivot point is unchanged when mapped with SkMatrix. + + @param kx horizontal skew factor + @param ky vertical skew factor + @param px pivot x + @param py pivot y */ void setSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py); - /** Set the matrix to skew by sx and sy. + + /** Sets SkMatrix to skew by kx and ky, about a pivot point at (0, 0). + + @param kx horizontal skew factor + @param ky vertical skew factor */ void setSkew(SkScalar kx, SkScalar ky); - /** Set the matrix to the concatenation of the two specified matrices. - Either of the two matrices may also be the target matrix. - *this = a * b; + + /** Sets SkMatrix to SkMatrix a multiplied by SkMatrix b. Either a or b may be this. + + Given: + + | A B C | | J K L | + a = | D E F |, b = | M N O | + | G H I | | P Q R | + + sets SkMatrix to: + + | A B C | | J K L | | AJ+BM+CP AK+BN+CQ AL+BO+CR | + a * b = | D E F | * | M N O | = | DJ+EM+FP DK+EN+FQ DL+EO+FR | + | G H I | | P Q R | | GJ+HM+IP GK+HN+IQ GL+HO+IR | + + @param a SkMatrix on left side of multiply expression + @param b SkMatrix on right side of multiply expression */ void setConcat(const SkMatrix& a, const SkMatrix& b); - /** Preconcats the matrix with the specified translation. - M' = M * T(dx, dy) + /** Sets SkMatrix to SkMatrix multiplied by SkMatrix constructed from translation (dx, dy). + This can be thought of as moving the point to be mapped before applying SkMatrix. + + Given: + + | A B C | | 1 0 dx | + Matrix = | D E F |, T(dx, dy) = | 0 1 dy | + | G H I | | 0 0 1 | + + sets SkMatrix to: + + | A B C | | 1 0 dx | | A B A*dx+B*dy+C | + Matrix * T(dx, dy) = | D E F | | 0 1 dy | = | D E D*dx+E*dy+F | + | G H I | | 0 0 1 | | G H G*dx+H*dy+I | + + @param dx x translation before applying SkMatrix + @param dy y translation before applying SkMatrix */ void preTranslate(SkScalar dx, SkScalar dy); - /** Preconcats the matrix with the specified scale. - M' = M * S(sx, sy, px, py) + + /** Sets SkMatrix to SkMatrix multiplied by SkMatrix constructed from scaling by (sx, sy) + about pivot point (px, py). + This can be thought of as scaling about a pivot point before applying SkMatrix. + + Given: + + | A B C | | sx 0 dx | + Matrix = | D E F |, S(sx, sy, px, py) = | 0 sy dy | + | G H I | | 0 0 1 | + + where + + dx = px - sx * px + dy = py - sy * py + + sets SkMatrix to: + + | A B C | | sx 0 dx | | A*sx B*sy A*dx+B*dy+C | + Matrix * S(sx, sy, px, py) = | D E F | | 0 sy dy | = | D*sx E*sy D*dx+E*dy+F | + | G H I | | 0 0 1 | | G*sx H*sy G*dx+H*dy+I | + + @param sx horizontal scale factor + @param sy vertical scale factor + @param px pivot x + @param py pivot y */ void preScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py); - /** Preconcats the matrix with the specified scale. - M' = M * S(sx, sy) + + /** Sets SkMatrix to SkMatrix multiplied by SkMatrix constructed from scaling by (sx, sy) + about pivot point (0, 0). + This can be thought of as scaling about the origin before applying SkMatrix. + + Given: + + | A B C | | sx 0 0 | + Matrix = | D E F |, S(sx, sy) = | 0 sy 0 | + | G H I | | 0 0 1 | + + sets SkMatrix to: + + | A B C | | sx 0 0 | | A*sx B*sy C | + Matrix * S(sx, sy) = | D E F | | 0 sy 0 | = | D*sx E*sy F | + | G H I | | 0 0 1 | | G*sx H*sy I | + + @param sx horizontal scale factor + @param sy vertical scale factor */ void preScale(SkScalar sx, SkScalar sy); - /** Preconcats the matrix with the specified rotation. - M' = M * R(degrees, px, py) + + /** Sets SkMatrix to SkMatrix multiplied by SkMatrix constructed from rotating by degrees + about pivot point (px, py). + This can be thought of as rotating about a pivot point before applying SkMatrix. + + Positive degrees rotates clockwise. + + Given: + + | A B C | | c -s dx | + Matrix = | D E F |, R(degrees, px, py) = | s c dy | + | G H I | | 0 0 1 | + + where + + c = cos(degrees) + s = sin(degrees) + dx = s * py + (1 - c) * px + dy = -s * px + (1 - c) * py + + sets SkMatrix to: + + | A B C | | c -s dx | | Ac+Bs -As+Bc A*dx+B*dy+C | + Matrix * R(degrees, px, py) = | D E F | | s c dy | = | Dc+Es -Ds+Ec D*dx+E*dy+F | + | G H I | | 0 0 1 | | Gc+Hs -Gs+Hc G*dx+H*dy+I | + + @param degrees angle of axes relative to upright axes + @param px pivot x + @param py pivot y */ void preRotate(SkScalar degrees, SkScalar px, SkScalar py); - /** Preconcats the matrix with the specified rotation. - M' = M * R(degrees) + + /** Sets SkMatrix to SkMatrix multiplied by SkMatrix constructed from rotating by degrees + about pivot point (0, 0). + This can be thought of as rotating about the origin before applying SkMatrix. + + Positive degrees rotates clockwise. + + Given: + + | A B C | | c -s 0 | + Matrix = | D E F |, R(degrees, px, py) = | s c 0 | + | G H I | | 0 0 1 | + + where + + c = cos(degrees) + s = sin(degrees) + + sets SkMatrix to: + + | A B C | | c -s 0 | | Ac+Bs -As+Bc C | + Matrix * R(degrees, px, py) = | D E F | | s c 0 | = | Dc+Es -Ds+Ec F | + | G H I | | 0 0 1 | | Gc+Hs -Gs+Hc I | + + @param degrees angle of axes relative to upright axes */ void preRotate(SkScalar degrees); - /** Preconcats the matrix with the specified skew. - M' = M * K(kx, ky, px, py) + + /** Sets SkMatrix to SkMatrix multiplied by SkMatrix constructed from skewing by (kx, ky) + about pivot point (px, py). + This can be thought of as skewing about a pivot point before applying SkMatrix. + + Given: + + | A B C | | 1 kx dx | + Matrix = | D E F |, K(kx, ky, px, py) = | ky 1 dy | + | G H I | | 0 0 1 | + + where + + dx = -kx * py + dy = -ky * px + + sets SkMatrix to: + + | A B C | | 1 kx dx | | A+B*ky A*kx+B A*dx+B*dy+C | + Matrix * K(kx, ky, px, py) = | D E F | | ky 1 dy | = | D+E*ky D*kx+E D*dx+E*dy+F | + | G H I | | 0 0 1 | | G+H*ky G*kx+H G*dx+H*dy+I | + + @param kx horizontal skew factor + @param ky vertical skew factor + @param px pivot x + @param py pivot y */ void preSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py); - /** Preconcats the matrix with the specified skew. - M' = M * K(kx, ky) + + /** Sets SkMatrix to SkMatrix multiplied by SkMatrix constructed from skewing by (kx, ky) + about pivot point (0, 0). + This can be thought of as skewing about the origin before applying SkMatrix. + + Given: + + | A B C | | 1 kx 0 | + Matrix = | D E F |, K(kx, ky) = | ky 1 0 | + | G H I | | 0 0 1 | + + sets SkMatrix to: + + | A B C | | 1 kx 0 | | A+B*ky A*kx+B C | + Matrix * K(kx, ky) = | D E F | | ky 1 0 | = | D+E*ky D*kx+E F | + | G H I | | 0 0 1 | | G+H*ky G*kx+H I | + + @param kx horizontal skew factor + @param ky vertical skew factor */ void preSkew(SkScalar kx, SkScalar ky); - /** Preconcats the matrix with the specified matrix. - M' = M * other + + /** Sets SkMatrix to SkMatrix multiplied by SkMatrix other. + This can be thought of mapping by other before applying SkMatrix. + + Given: + + | A B C | | J K L | + Matrix = | D E F |, other = | M N O | + | G H I | | P Q R | + + sets SkMatrix to: + + | A B C | | J K L | | AJ+BM+CP AK+BN+CQ AL+BO+CR | + Matrix * other = | D E F | * | M N O | = | DJ+EM+FP DK+EN+FQ DL+EO+FR | + | G H I | | P Q R | | GJ+HM+IP GK+HN+IQ GL+HO+IR | + + @param other SkMatrix on right side of multiply expression */ void preConcat(const SkMatrix& other); - /** Postconcats the matrix with the specified translation. - M' = T(dx, dy) * M + /** Sets SkMatrix to SkMatrix constructed from translation (dx, dy) multiplied by SkMatrix. + This can be thought of as moving the point to be mapped after applying SkMatrix. + + Given: + + | J K L | | 1 0 dx | + Matrix = | M N O |, T(dx, dy) = | 0 1 dy | + | P Q R | | 0 0 1 | + + sets SkMatrix to: + + | 1 0 dx | | J K L | | J+dx*P K+dx*Q L+dx*R | + T(dx, dy) * Matrix = | 0 1 dy | | M N O | = | M+dy*P N+dy*Q O+dy*R | + | 0 0 1 | | P Q R | | P Q R | + + @param dx x translation after applying SkMatrix + @param dy y translation after applying SkMatrix */ void postTranslate(SkScalar dx, SkScalar dy); - /** Postconcats the matrix with the specified scale. - M' = S(sx, sy, px, py) * M + + /** Sets SkMatrix to SkMatrix constructed from scaling by (sx, sy) about pivot point + (px, py), multiplied by SkMatrix. + This can be thought of as scaling about a pivot point after applying SkMatrix. + + Given: + + | J K L | | sx 0 dx | + Matrix = | M N O |, S(sx, sy, px, py) = | 0 sy dy | + | P Q R | | 0 0 1 | + + where + + dx = px - sx * px + dy = py - sy * py + + sets SkMatrix to: + + | sx 0 dx | | J K L | | sx*J+dx*P sx*K+dx*Q sx*L+dx+R | + S(sx, sy, px, py) * Matrix = | 0 sy dy | | M N O | = | sy*M+dy*P sy*N+dy*Q sy*O+dy*R | + | 0 0 1 | | P Q R | | P Q R | + + @param sx horizontal scale factor + @param sy vertical scale factor + @param px pivot x + @param py pivot y */ void postScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py); - /** Postconcats the matrix with the specified scale. - M' = S(sx, sy) * M + + /** Sets SkMatrix to SkMatrix constructed from scaling by (sx, sy) about pivot point + (0, 0), multiplied by SkMatrix. + This can be thought of as scaling about the origin after applying SkMatrix. + + Given: + + | J K L | | sx 0 0 | + Matrix = | M N O |, S(sx, sy) = | 0 sy 0 | + | P Q R | | 0 0 1 | + + sets SkMatrix to: + + | sx 0 0 | | J K L | | sx*J sx*K sx*L | + S(sx, sy) * Matrix = | 0 sy 0 | | M N O | = | sy*M sy*N sy*O | + | 0 0 1 | | P Q R | | P Q R | + + @param sx horizontal scale factor + @param sy vertical scale factor */ void postScale(SkScalar sx, SkScalar sy); - /** Postconcats the matrix by dividing it by the specified integers. - M' = S(1/divx, 1/divy, 0, 0) * M + + /** Sets SkMatrix to SkMatrix constructed from scaling by (1/divx, 1/divy) about pivot point (px, py), multiplied by SkMatrix. + + Returns false if either divx or divy is zero. + + Given: + + | J K L | | sx 0 0 | + Matrix = | M N O |, I(divx, divy) = | 0 sy 0 | + | P Q R | | 0 0 1 | + + where + + sx = 1 / divx + sy = 1 / divy + + sets SkMatrix to: + + | sx 0 0 | | J K L | | sx*J sx*K sx*L | + I(divx, divy) * Matrix = | 0 sy 0 | | M N O | = | sy*M sy*N sy*O | + | 0 0 1 | | P Q R | | P Q R | + + @param divx integer divisor for inverse scale in x + @param divy integer divisor for inverse scale in y + @return true on successful scale */ bool postIDiv(int divx, int divy); - /** Postconcats the matrix with the specified rotation. - M' = R(degrees, px, py) * M + + /** Sets SkMatrix to SkMatrix constructed from rotating by degrees about pivot point + (px, py), multiplied by SkMatrix. + This can be thought of as rotating about a pivot point after applying SkMatrix. + + Positive degrees rotates clockwise. + + Given: + + | J K L | | c -s dx | + Matrix = | M N O |, R(degrees, px, py) = | s c dy | + | P Q R | | 0 0 1 | + + where + + c = cos(degrees) + s = sin(degrees) + dx = s * py + (1 - c) * px + dy = -s * px + (1 - c) * py + + sets SkMatrix to: + + |c -s dx| |J K L| |cJ-sM+dx*P cK-sN+dx*Q cL-sO+dx+R| + R(degrees, px, py) * Matrix = |s c dy| |M N O| = |sJ+cM+dy*P sK+cN+dy*Q sL+cO+dy*R| + |0 0 1| |P Q R| | P Q R| + + @param degrees angle of axes relative to upright axes + @param px pivot x + @param py pivot y */ void postRotate(SkScalar degrees, SkScalar px, SkScalar py); - /** Postconcats the matrix with the specified rotation. - M' = R(degrees) * M + + /** Sets SkMatrix to SkMatrix constructed from rotating by degrees about pivot point + (0, 0), multiplied by SkMatrix. + This can be thought of as rotating about the origin after applying SkMatrix. + + Positive degrees rotates clockwise. + + Given: + + | J K L | | c -s 0 | + Matrix = | M N O |, R(degrees, px, py) = | s c 0 | + | P Q R | | 0 0 1 | + + where + + c = cos(degrees) + s = sin(degrees) + + sets SkMatrix to: + + | c -s dx | | J K L | | cJ-sM cK-sN cL-sO | + R(degrees, px, py) * Matrix = | s c dy | | M N O | = | sJ+cM sK+cN sL+cO | + | 0 0 1 | | P Q R | | P Q R | + + @param degrees angle of axes relative to upright axes */ void postRotate(SkScalar degrees); - /** Postconcats the matrix with the specified skew. - M' = K(kx, ky, px, py) * M + + /** Sets SkMatrix to SkMatrix constructed from skewing by (kx, ky) about pivot point + (px, py), multiplied by SkMatrix. + This can be thought of as skewing about a pivot point after applying SkMatrix. + + Given: + + | J K L | | 1 kx dx | + Matrix = | M N O |, K(kx, ky, px, py) = | ky 1 dy | + | P Q R | | 0 0 1 | + + where + + dx = -kx * py + dy = -ky * px + + sets SkMatrix to: + + | 1 kx dx| |J K L| |J+kx*M+dx*P K+kx*N+dx*Q L+kx*O+dx+R| + K(kx, ky, px, py) * Matrix = |ky 1 dy| |M N O| = |ky*J+M+dy*P ky*K+N+dy*Q ky*L+O+dy*R| + | 0 0 1| |P Q R| | P Q R| + + @param kx horizontal skew factor + @param ky vertical skew factor + @param px pivot x + @param py pivot y */ void postSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py); - /** Postconcats the matrix with the specified skew. - M' = K(kx, ky) * M + + /** Sets SkMatrix to SkMatrix constructed from skewing by (kx, ky) about pivot point + (0, 0), multiplied by SkMatrix. + This can be thought of as skewing about the origin after applying SkMatrix. + + Given: + + | J K L | | 1 kx 0 | + Matrix = | M N O |, K(kx, ky) = | ky 1 0 | + | P Q R | | 0 0 1 | + + sets SkMatrix to: + + | 1 kx 0 | | J K L | | J+kx*M K+kx*N L+kx*O | + K(kx, ky) * Matrix = | ky 1 0 | | M N O | = | ky*J+M ky*K+N ky*L+O | + | 0 0 1 | | P Q R | | P Q R | + + @param kx horizontal skew factor + @param ky vertical skew factor */ void postSkew(SkScalar kx, SkScalar ky); - /** Postconcats the matrix with the specified matrix. - M' = other * M + + /** Sets SkMatrix to SkMatrix other multiplied by SkMatrix. + This can be thought of mapping by other after applying SkMatrix. + + Given: + + | J K L | | A B C | + Matrix = | M N O |, other = | D E F | + | P Q R | | G H I | + + sets SkMatrix to: + + | A B C | | J K L | | AJ+BM+CP AK+BN+CQ AL+BO+CR | + other * Matrix = | D E F | * | M N O | = | DJ+EM+FP DK+EN+FQ DL+EO+FR | + | G H I | | P Q R | | GJ+HM+IP GK+HN+IQ GL+HO+IR | + + @param other SkMatrix on left side of multiply expression */ void postConcat(const SkMatrix& other); + /** \enum SkMatrix::ScaleToFit + ScaleToFit describes how SkMatrix is constructed to map one SkRect to another. + ScaleToFit may allow SkMatrix to have unequal horizontal and vertical scaling, + or may restrict SkMatrix to square scaling. If restricted, ScaleToFit specifies + how SkMatrix maps to the side or center of the destination SkRect. + */ enum ScaleToFit { - /** - * Scale in X and Y independently, so that src matches dst exactly. - * This may change the aspect ratio of the src. - */ + /** Computes SkMatrix that scales in x and y independently, so that source SkRect is + mapped to completely fill destination SkRect. The aspect ratio of source SkRect + may change. + */ kFill_ScaleToFit, - /** - * Compute a scale that will maintain the original src aspect ratio, - * but will also ensure that src fits entirely inside dst. At least one - * axis (X or Y) will fit exactly. kStart aligns the result to the - * left and top edges of dst. - */ + + /** Computes SkMatrix that maintains source SkRect aspect ratio, mapping source SkRect + width or height to destination SkRect. Aligns mapping to left and top edges + of destination SkRect. + */ kStart_ScaleToFit, - /** - * Compute a scale that will maintain the original src aspect ratio, - * but will also ensure that src fits entirely inside dst. At least one - * axis (X or Y) will fit exactly. The result is centered inside dst. - */ + + /** Computes SkMatrix that maintains source SkRect aspect ratio, mapping source SkRect + width or height to destination SkRect. Aligns mapping to center of destination + SkRect. + */ kCenter_ScaleToFit, - /** - * Compute a scale that will maintain the original src aspect ratio, - * but will also ensure that src fits entirely inside dst. At least one - * axis (X or Y) will fit exactly. kEnd aligns the result to the - * right and bottom edges of dst. - */ + + /** Computes SkMatrix that maintains source SkRect aspect ratio, mapping source SkRect + width or height to destination SkRect. Aligns mapping to right and bottom + edges of destination SkRect. + */ kEnd_ScaleToFit, }; - /** Set the matrix to the scale and translate values that map the source - rectangle to the destination rectangle, returning true if the the result - can be represented. - @param src the source rectangle to map from. - @param dst the destination rectangle to map to. - @param stf the ScaleToFit option - @return true if the matrix can be represented by the rectangle mapping. + /** Sets SkMatrix to scale and translate src SkRect to dst SkRect. stf selects whether + mapping completely fills dst or preserves the aspect ratio, and how to align + src within dst. Returns false if src is empty, and sets SkMatrix to identity. + Returns true if dst is empty, and sets SkMatrix to: + + | 0 0 0 | + | 0 0 0 | + | 0 0 1 | + + @param src SkRect to map from + @param dst SkRect to map to + @param stf one of: kFill_ScaleToFit, kStart_ScaleToFit, + kCenter_ScaleToFit, kEnd_ScaleToFit + @return true if SkMatrix can represent SkRect mapping */ bool setRectToRect(const SkRect& src, const SkRect& dst, ScaleToFit stf); + + /** Returns SkMatrix set to scale and translate src SkRect to dst SkRect. stf selects + whether mapping completely fills dst or preserves the aspect ratio, and how to + align src within dst. Returns the identity SkMatrix if src is empty. If dst is + empty, returns SkMatrix set to: + + | 0 0 0 | + | 0 0 0 | + | 0 0 1 | + + @param src SkRect to map from + @param dst SkRect to map to + @param stf one of: kFill_ScaleToFit, kStart_ScaleToFit, + kCenter_ScaleToFit, kEnd_ScaleToFit + @return SkMatrix mapping src to dst + */ static SkMatrix MakeRectToRect(const SkRect& src, const SkRect& dst, ScaleToFit stf) { SkMatrix m; m.setRectToRect(src, dst, stf); return m; } - /** Set the matrix such that the specified src points would map to the - specified dst points. count must be within [0..4]. - @param src The array of src points - @param dst The array of dst points - @param count The number of points to use for the transformation - @return true if the matrix was set to the specified transformation + /** Sets SkMatrix to map src to dst. count must be zero or greater, and four or less. + + If count is zero, sets SkMatrix to identity and returns true. + If count is one, sets SkMatrix to translate and returns true. + If count is two or more, sets SkMatrix to map SkPoint if possible; returns false + if SkMatrix cannot be constructed. If count is four, SkMatrix may include + perspective. + + @param src SkPoint to map from + @param dst SkPoint to map to + @param count number of SkPoint in src and dst + @return true if SkMatrix was constructed successfully */ bool setPolyToPoly(const SkPoint src[], const SkPoint dst[], int count); - /** If this matrix can be inverted, return true and if inverse is not null, - set inverse to be the inverse of this matrix. If this matrix cannot be - inverted, ignore inverse and return false + /** Sets inverse to reciprocal matrix, returning true if SkMatrix can be inverted. + Geometrically, if SkMatrix maps from source to destination, inverse SkMatrix + maps from destination to source. If SkMatrix can not be inverted, inverse is + unchanged. + + @param inverse storage for inverted SkMatrix; may be nullptr + @return true if SkMatrix can be inverted */ bool SK_WARN_UNUSED_RESULT invert(SkMatrix* inverse) const { // Allow the trivial case to be inlined. @@ -400,34 +1140,71 @@ public: return this->invertNonIdentity(inverse); } - /** Fills the passed array with affine identity values - in column major order. - @param affine The array to fill with affine identity values. - Must not be NULL. + /** Fills affine with identity values in column major order. + Sets affine to: + + | 1 0 0 | + | 0 1 0 | + + Affine 3x2 matrices in column major order are used by OpenGL and XPS. + + @param affine storage for 3x2 affine matrix */ static void SetAffineIdentity(SkScalar affine[6]); - /** Fills the passed array with the affine values in column major order. - If the matrix is a perspective transform, returns false - and does not change the passed array. - @param affine The array to fill with affine values. Ignored if NULL. + /** Fills affine in column major order. Sets affine to: + + | scale-x skew-x translate-x | + | skew-y scale-y translate-y | + + If SkMatrix contains perspective, returns false and leaves affine unchanged. + + @param affine storage for 3x2 affine matrix; may be nullptr + @return true if SkMatrix does not contain perspective */ bool SK_WARN_UNUSED_RESULT asAffine(SkScalar affine[6]) const; - /** Set the matrix to the specified affine values. - * Note: these are passed in column major order. - */ + /** Sets SkMatrix to affine values, passed in column major order. Given affine, + column, then row, as: + + | scale-x skew-x translate-x | + | skew-y scale-y translate-y | + + SkMatrix is set, row, then column, to: + + | scale-x skew-x translate-x | + | skew-y scale-y translate-y | + | 0 0 1 | + + @param affine 3x2 affine matrix + */ void setAffine(const SkScalar affine[6]); - /** Apply this matrix to the array of points specified by src, and write - the transformed points into the array of points specified by dst. - dst[] = M * src[] - @param dst Where the transformed coordinates are written. It must - contain at least count entries - @param src The original coordinates that are to be transformed. It - must contain at least count entries - @param count The number of points in src to read, and then transform - into dst. + /** Maps src SkPoint array of length count to dst SkPoint array of equal or greater + length. SkPoint are mapped by multiplying each SkPoint by SkMatrix. Given: + + | A B C | | x | + Matrix = | D E F |, pt = | y | + | G H I | | 1 | + + where + + for (i = 0; i < count; ++i) { + x = src[i].fX + y = src[i].fY + } + + each dst SkPoint is computed as: + + |A B C| |x| Ax+By+C Dx+Ey+F + Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , ------- + |G H I| |1| Gx+Hy+I Gx+Hy+I + + src and dst may point to the same storage. + + @param dst storage for mapped SkPoint + @param src SkPoint to transform + @param count number of SkPoint to transform */ void mapPoints(SkPoint dst[], const SkPoint src[], int count) const { SkASSERT((dst && src && count > 0) || 0 == count); @@ -436,20 +1213,50 @@ public: this->getMapPtsProc()(*this, dst, src, count); } - /** Apply this matrix to the array of points, overwriting it with the - transformed values. - dst[] = M * pts[] - @param pts The points to be transformed. It must contain at least - count entries - @param count The number of points in pts. + /** Maps pts SkPoint array of length count in place. SkPoint are mapped by multiplying + each SkPoint by SkMatrix. Given: + + | A B C | | x | + Matrix = | D E F |, pt = | y | + | G H I | | 1 | + + where + + for (i = 0; i < count; ++i) { + x = pts[i].fX + y = pts[i].fY + } + + each resulting pts SkPoint is computed as: + + |A B C| |x| Ax+By+C Dx+Ey+F + Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , ------- + |G H I| |1| Gx+Hy+I Gx+Hy+I + + @param pts storage for mapped SkPoint + @param count number of SkPoint to transform */ void mapPoints(SkPoint pts[], int count) const { this->mapPoints(pts, pts, count); } - /** Like mapPoints but with custom byte stride between the points. Stride - * should be a multiple of sizeof(SkScalar). - */ + /** Maps count pts, skipping stride bytes to advance from one SkPoint to the next. + SkPoint are mapped by multiplying each SkPoint by SkMatrix. Given: + + | A B C | | x | + Matrix = | D E F |, pt = | y | + | G H I | | 1 | + + each resulting pts SkPoint is computed as: + + |A B C| |x| Ax+By+C Dx+Ey+F + Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , ------- + |G H I| |1| Gx+Hy+I Gx+Hy+I + + @param pts storage for mapped SkPoint + @param stride size of record starting with SkPoint, in bytes + @param count number of SkPoint to transform + */ void mapPointsWithStride(SkPoint pts[], size_t stride, int count) const { SkASSERT(stride >= sizeof(SkPoint)); SkASSERT(0 == stride % sizeof(SkScalar)); @@ -459,7 +1266,24 @@ public: } } - /** Like mapPoints but with custom byte stride between the points. + /** Maps src SkPoint array of length count to dst SkPoint array, skipping stride bytes + to advance from one SkPoint to the next. + SkPoint are mapped by multiplying each SkPoint by SkMatrix. Given: + + | A B C | | x | + Matrix = | D E F |, src = | y | + | G H I | | 1 | + + each resulting dst SkPoint is computed as: + + |A B C| |x| Ax+By+C Dx+Ey+F + Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , ------- + |G H I| |1| Gx+Hy+I Gx+Hy+I + + @param dst storage for mapped SkPoint + @param src SkPoint to transform + @param stride size of record starting with SkPoint, in bytes + @param count number of SkPoint to transform */ void mapPointsWithStride(SkPoint dst[], const SkPoint src[], size_t stride, int count) const { SkASSERT(stride >= sizeof(SkPoint)); @@ -471,88 +1295,216 @@ public: } } - /** Apply this matrix to the array of homogeneous points, specified by src, - where a homogeneous point is defined by 3 contiguous scalar values, - and write the transformed points into the array of scalars specified by dst. - dst[] = M * src[] - @param dst Where the transformed coordinates are written. It must - contain at least count entries - @param src The original coordinates that are to be transformed. It - must contain at least count entries - @param count The number of homogeneous points in src to read, - and then transform into dst. + /** Maps src SkPoint3 array of length count to dst SkPoint3 array, which must of length count or + greater. SkPoint3 array is mapped by multiplying each SkPoint3 by SkMatrix. Given: + + | A B C | | x | + Matrix = | D E F |, src = | y | + | G H I | | z | + + each resulting dst SkPoint is computed as: + + |A B C| |x| + Matrix * src = |D E F| |y| = |Ax+By+Cz Dx+Ey+Fz Gx+Hy+Iz| + |G H I| |z| + + @param dst storage for mapped SkPoint3 array + @param src SkPoint3 array to transform + @param count items in SkPoint3 array to transform */ void mapHomogeneousPoints(SkPoint3 dst[], const SkPoint3 src[], int count) const; + /** Maps SkPoint (x, y) to result. SkPoint is mapped by multiplying by SkMatrix. Given: + + | A B C | | x | + Matrix = | D E F |, pt = | y | + | G H I | | 1 | + + result is computed as: + + |A B C| |x| Ax+By+C Dx+Ey+F + Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , ------- + |G H I| |1| Gx+Hy+I Gx+Hy+I + + @param x x-coordinate of SkPoint to map + @param y y-coordinate of SkPoint to map + @param result storage for mapped SkPoint + */ void mapXY(SkScalar x, SkScalar y, SkPoint* result) const { SkASSERT(result); this->getMapXYProc()(*this, x, y, result); } + /** Returns SkPoint (x, y) multiplied by SkMatrix. Given: + + | A B C | | x | + Matrix = | D E F |, pt = | y | + | G H I | | 1 | + + result is computed as: + + |A B C| |x| Ax+By+C Dx+Ey+F + Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , ------- + |G H I| |1| Gx+Hy+I Gx+Hy+I + + @param x x-coordinate of SkPoint to map + @param y y-coordinate of SkPoint to map + @return mapped SkPoint + */ SkPoint mapXY(SkScalar x, SkScalar y) const { SkPoint result; this->getMapXYProc()(*this, x, y, &result); return result; } - /** Apply this matrix to the array of vectors specified by src, and write - the transformed vectors into the array of vectors specified by dst. - This is similar to mapPoints, but ignores any translation in the matrix. - @param dst Where the transformed coordinates are written. It must - contain at least count entries - @param src The original coordinates that are to be transformed. It - must contain at least count entries - @param count The number of vectors in src to read, and then transform - into dst. + /** Maps src SkVector array of length count to SkVector SkPoint array of equal or greater + length. SkVector are mapped by multiplying each SkVector by SkMatrix, treating + SkMatrix translation as zero. Given: + + | A B 0 | | x | + Matrix = | D E 0 |, src = | y | + | G H I | | 1 | + + where + + for (i = 0; i < count; ++i) { + x = src[i].fX + y = src[i].fY + } + + each dst SkVector is computed as: + + |A B 0| |x| Ax+By Dx+Ey + Matrix * src = |D E 0| |y| = |Ax+By Dx+Ey Gx+Hy+I| = ------- , ------- + |G H I| |1| Gx+Hy+I Gx+Hy+I + + src and dst may point to the same storage. + + @param dst storage for mapped SkVector + @param src SkVector to transform + @param count number of SkVector to transform */ void mapVectors(SkVector dst[], const SkVector src[], int count) const; - /** Apply this matrix to the array of vectors specified by src, and write - the transformed vectors into the array of vectors specified by dst. - This is similar to mapPoints, but ignores any translation in the matrix. - @param vecs The vectors to be transformed. It must contain at least - count entries - @param count The number of vectors in vecs. + /** Maps vecs SkVector array of length count in place, multiplying each SkVector by + SkMatrix, treating SkMatrix translation as zero. Given: + + | A B 0 | | x | + Matrix = | D E 0 |, vec = | y | + | G H I | | 1 | + + where + + for (i = 0; i < count; ++i) { + x = vecs[i].fX + y = vecs[i].fY + } + + each result SkVector is computed as: + + |A B 0| |x| Ax+By Dx+Ey + Matrix * vec = |D E 0| |y| = |Ax+By Dx+Ey Gx+Hy+I| = ------- , ------- + |G H I| |1| Gx+Hy+I Gx+Hy+I + + @param vecs SkVector to transform, and storage for mapped SkVector + @param count number of SkVector to transform */ void mapVectors(SkVector vecs[], int count) const { this->mapVectors(vecs, vecs, count); } + /** Maps SkVector (x, y) to result. SkVector is mapped by multiplying by SkMatrix, + treating SkMatrix translation as zero. Given: + + | A B 0 | | dx | + Matrix = | D E 0 |, vec = | dy | + | G H I | | 1 | + + each result SkVector is computed as: + + |A B 0| |dx| A*dx+B*dy D*dx+E*dy + Matrix * vec = |D E 0| |dy| = |A*dx+B*dy D*dx+E*dy G*dx+H*dy+I| = ----------- , ----------- + |G H I| | 1| G*dx+H*dy+I G*dx+*dHy+I + + @param dx x-coordinate of SkVector to map + @param dy y-coordinate of SkVector to map + @param result storage for mapped SkVector + */ void mapVector(SkScalar dx, SkScalar dy, SkVector* result) const { SkVector vec = { dx, dy }; this->mapVectors(result, &vec, 1); } + /** Returns SkVector (x, y) multiplied by SkMatrix, treating SkMatrix translation as zero. + Given: + + | A B 0 | | dx | + Matrix = | D E 0 |, vec = | dy | + | G H I | | 1 | + + each result SkVector is computed as: + + |A B 0| |dx| A*dx+B*dy D*dx+E*dy + Matrix * vec = |D E 0| |dy| = |A*dx+B*dy D*dx+E*dy G*dx+H*dy+I| = ----------- , ----------- + |G H I| | 1| G*dx+H*dy+I G*dx+*dHy+I + + @param dx x-coordinate of SkVector to map + @param dy y-coordinate of SkVector to map + @return mapped SkVector + */ SkVector mapVector(SkScalar dx, SkScalar dy) const { SkVector vec = { dx, dy }; this->mapVectors(&vec, &vec, 1); return vec; } - /** Apply this matrix to the src rectangle, and write the transformed - rectangle into dst. This is accomplished by transforming the 4 corners - of src, and then setting dst to the bounds of those points. - @param dst Where the transformed rectangle is written. - @param src The original rectangle to be transformed. - @return the result of calling rectStaysRect() + /** Sets dst to bounds of src corners mapped by SkMatrix. + Returns true if mapped corners are dst corners. + + Returned value is the same as calling rectStaysRect(). + + @param dst storage for bounds of mapped SkPoint + @param src SkRect to map + @return true if dst is equivalent to mapped src */ bool mapRect(SkRect* dst, const SkRect& src) const; - /** Apply this matrix to the rectangle, and write the transformed rectangle - back into it. This is accomplished by transforming the 4 corners of - rect, and then setting it to the bounds of those points - @param rect The rectangle to transform. - @return the result of calling rectStaysRect() + /** Sets rect to bounds of rect corners mapped by SkMatrix. + Returns true if mapped corners are computed rect corners. + + Returned value is the same as calling rectStaysRect(). + + @param rect rectangle to map, and storage for bounds of mapped corners + @return true if result is equivalent to mapped src */ bool mapRect(SkRect* rect) const { return this->mapRect(rect, *rect); } - /** Apply this matrix to the src rectangle, and write the four transformed - points into dst. The points written to dst will be the original top-left, top-right, - bottom-right, and bottom-left points transformed by the matrix. - @param dst Where the transformed quad is written. - @param rect The original rectangle to be transformed. + /** Maps four corners of rect to dst. SkPoint are mapped by multiplying each + rect corner by SkMatrix. rect corner is processed in this order: + (rect.fLeft, rect.fTop), (rect.fRight, rect.fTop), (rect.fRight, rect.fBottom), + (rect.fLeft, rect.fBottom). + + rect may be empty: rect.fLeft may be greater than or equal to rect.fRight; + rect.fTop may be greater than or equal to rect.fBottom. + + Given: + + | A B C | | x | + Matrix = | D E F |, pt = | y | + | G H I | | 1 | + + where pt is initialized from each of (rect.fLeft, rect.fTop), + (rect.fRight, rect.fTop), (rect.fRight, rect.fBottom), (rect.fLeft, rect.fBottom), + each dst SkPoint is computed as: + + |A B C| |x| Ax+By+C Dx+Ey+F + Matrix * pt = |D E F| |y| = |Ax+By+C Dx+Ey+F Gx+Hy+I| = ------- , ------- + |G H I| |1| Gx+Hy+I Gx+Hy+I + + @param dst storage for mapped corner SkPoint + @param rect SkRect to map */ void mapRectToQuad(SkPoint dst[4], const SkRect& rect) const { // This could potentially be faster if we only transformed each x and y of the rect once. @@ -560,119 +1512,208 @@ public: this->mapPoints(dst, 4); } - /** - * Maps a rect to another rect, asserting (in debug mode) that the matrix only contains - * scale and translate elements. If it contains other elements, the results are undefined. - */ + /** Sets dst to bounds of src corners mapped by SkMatrix. If matrix contains + elements other than scale or translate: asserts if SK_DEBUG is defined; + otherwise, results are undefined. + + @param dst storage for bounds of mapped SkPoint + @param src SkRect to map + */ void mapRectScaleTranslate(SkRect* dst, const SkRect& src) const; - /** Return the mean radius of a circle after it has been mapped by - this matrix. NOTE: in perspective this value assumes the circle - has its center at the origin. + /** Returns geometric mean radius of ellipse formed by constructing circle of + size radius, and mapping constructed circle with SkMatrix. The result squared is + equal to the major axis length times the minor axis length. + Result is not meaningful if SkMatrix contains perspective elements. + + @param radius circle size to map + @return average mapped radius */ SkScalar mapRadius(SkScalar radius) const; - /** Returns true if the matrix can be stepped in X (not complex - perspective). + /** Returns true if a unit step in x at some y mapped through SkMatrix can be + represented by a constant SkVector. Returns true if getType() returns kIdentity_Mask, + or combinations of: kTranslate_Mask, kScale_Mask, and kAffine_Mask. + + May return true if getType() returns kPerspective_Mask, but only when SkMatrix + does not include rotation or skewing along the y-axis. + + @return true if SkMatrix does not have complex perspective */ bool isFixedStepInX() const; - /** If the matrix can be stepped in X (not complex perspective) - then return the step value. - If it cannot, behavior is undefined. + /** Returns SkVector representing a unit step in x at y mapped through SkMatrix. + If isFixedStepInX() is false, returned value is undefined. + + @param y position of line parallel to x-axis + @return SkVector advance of mapped unit step in x */ SkVector fixedStepInX(SkScalar y) const; - /** Efficient comparison of two matrices. It distinguishes between zero and - * negative zero. It will return false when the sign of zero values is the - * only difference between the two matrices. It considers NaN values to be - * equal to themselves. So a matrix full of NaNs is "cheap equal" to - * another matrix full of NaNs iff the NaN values are bitwise identical - * while according to strict the strict == test a matrix with a NaN value - * is equal to nothing, including itself. - */ + /** Returns true if SkMatrix equals m, using an efficient comparison. + + Returns false when the sign of zero values is the different; when one + matrix has positive zero value and the other has negative zero value. + + Returns true even when both SkMatrix contain NaN. + + NaN never equals any value, including itself. To improve performance, NaN values + are treated as bit patterns that are equal if their bit patterns are equal. + + @param m SkMatrix to compare + @return true if m and SkMatrix are represented by identical bit patterns + */ bool cheapEqualTo(const SkMatrix& m) const { return 0 == memcmp(fMat, m.fMat, sizeof(fMat)); } - // mac chromium dbg requires SK_API to make operator== visible + /** Compares a and b; returns true if a and b are numerically equal. Returns true + even if sign of zero values are different. Returns false if either SkMatrix + contains NaN, even if the other SkMatrix also contains NaN. + + @param a SkMatrix to compare + @param b SkMatrix to compare + @return true if m and SkMatrix are numerically equal + */ friend SK_API bool operator==(const SkMatrix& a, const SkMatrix& b); + + /** Compares a and b; returns true if a and b are not numerically equal. Returns false + even if sign of zero values are different. Returns true if either SkMatrix + contains NaN, even if the other SkMatrix also contains NaN. + + @param a SkMatrix to compare + @param b SkMatrix to compare + @return true if m and SkMatrix are numerically not equal + */ friend SK_API bool operator!=(const SkMatrix& a, const SkMatrix& b) { return !(a == b); } + /** Writes text representation of SkMatrix to standard output. Floating point values + are written with limited precision; it may not be possible to reconstruct + original SkMatrix from output. + */ void dump() const; + + /** Creates string representation of SkMatrix. Floating point values + are written with limited precision; it may not be possible to reconstruct + original SkMatrix from output. + + @param str storage for string representation of SkMatrix + */ void toString(SkString* str) const; - /** - * Calculates the minimum scaling factor of the matrix as computed from the SVD of the upper - * left 2x2. If the max scale factor cannot be computed (for example overflow or perspective) - * -1 is returned. - * - * @return minimum scale factor - */ + /** Returns the minimum scaling factor of SkMatrix by decomposing the scaling and + skewing elements. + Returns -1 if scale factor overflows or SkMatrix contains perspective. + + @return minimum scale factor + */ SkScalar getMinScale() const; - /** - * Calculates the maximum scaling factor of the matrix as computed from the SVD of the upper - * left 2x2. If the max scale factor cannot be computed (for example overflow or perspective) - * -1 is returned. - * - * @return maximum scale factor - */ + /** Returns the maximum scaling factor of SkMatrix by decomposing the scaling and + skewing elements. + Returns -1 if scale factor overflows or SkMatrix contains perspective. + + @return maximum scale factor + */ SkScalar getMaxScale() const; - /** - * Gets both the min and max scale factors. The min scale factor is scaleFactors[0] and the max - * is scaleFactors[1]. If the min/max scale factors cannot be computed false is returned and the - * values of scaleFactors[] are undefined. - */ + /** Sets scaleFactors[0] to the minimum scaling factor, and scaleFactors[1] to the + maximum scaling factor. Scaling factors are computed by decomposing + the SkMatrix scaling and skewing elements. + + Returns true if scaleFactors are found; otherwise, returns false and sets + scaleFactors to undefined values. + + @param scaleFactors storage for minimum and maximum scale factors + @return true if scale factors were computed correctly + */ bool SK_WARN_UNUSED_RESULT getMinMaxScales(SkScalar scaleFactors[2]) const; - /** - * Attempt to decompose this matrix into a scale-only component and whatever remains, where - * the scale component is to be applied first. - * - * M -> Remaining * Scale - * - * On success, return true and assign the scale and remaining components (assuming their - * respective parameters are not null). On failure return false and ignore the parameters. - * - * Possible reasons to fail: perspective, one or more scale factors are zero. - */ + /** Decomposes SkMatrix into scale components and whatever remains. Returns false if + SkMatrix could not be decomposed. + + Sets scale to portion of SkMatrix that scales in x and y. Sets remaining to SkMatrix + with x and y scaling factored out. remaining may be passed as nullptr + to determine if SkMatrix can be decomposed without computing remainder. + + Returns true if scale components are found. scale and remaining are + unchanged if SkMatrix contains perspective; scale factors are not finite, or + are nearly zero. + + On success + Matrix = scale * Remaining + + @param scale x and y scaling factors; may be nullptr + @param remaining SkMatrix without scaling; may be nullptr + @return true if scale can be computed + */ bool decomposeScale(SkSize* scale, SkMatrix* remaining = nullptr) const; - /** - * Return a reference to a const identity matrix - */ + /** Returns reference to const identity SkMatrix. Returned SkMatrix is set to: + + | 1 0 0 | + | 0 1 0 | + | 0 0 1 | + + @return const identity SkMatrix + */ static const SkMatrix& I(); - /** - * Return a reference to a const matrix that is "invalid", one that could - * never be used. - */ + /** Returns reference to a const SkMatrix with invalid values. Returned SkMatrix is set + to: + + | SK_ScalarMax SK_ScalarMax SK_ScalarMax | + | SK_ScalarMax SK_ScalarMax SK_ScalarMax | + | SK_ScalarMax SK_ScalarMax SK_ScalarMax | + + @return const invalid SkMatrix + */ static const SkMatrix& InvalidMatrix(); - /** - * Return the concatenation of two matrices, a * b. - */ + /** Returns SkMatrix a multiplied by SkMatrix b. + + Given: + + | A B C | | J K L | + a = | D E F |, b = | M N O | + | G H I | | P Q R | + + sets SkMatrix to: + + | A B C | | J K L | | AJ+BM+CP AK+BN+CQ AL+BO+CR | + a * b = | D E F | * | M N O | = | DJ+EM+FP DK+EN+FQ DL+EO+FR | + | G H I | | P Q R | | GJ+HM+IP GK+HN+IQ GL+HO+IR | + + @param a SkMatrix on left side of multiply expression + @param b SkMatrix on right side of multiply expression + @return SkMatrix computed from a times b + */ static SkMatrix Concat(const SkMatrix& a, const SkMatrix& b) { SkMatrix result; result.setConcat(a, b); return result; } - /** - * Testing routine; the matrix's type cache should never need to be - * manually invalidated during normal use. - */ + /** Sets internal cache to unknown state. Use to force update after repeated + modifications to SkMatrix element reference returned by operator[](int index). + */ void dirtyMatrixTypeCache() { this->setTypeMask(kUnknown_Mask); } - /** - * Initialize the matrix to be scale + post-translate. - */ + /** Initializes SkMatrix with scale and translate elements. + + | sx 0 tx | + | 0 sy ty | + | 0 0 1 | + + @param sx horizontal scale factor to store + @param sy vertical scale factor to store + @param tx horizontal translation to store + @param ty vertical translation to store + */ void setScaleTranslate(SkScalar sx, SkScalar sy, SkScalar tx, SkScalar ty) { fMat[kMScaleX] = sx; fMat[kMSkewX] = 0; @@ -696,9 +1737,11 @@ public: this->setTypeMask(mask | kRectStaysRect_Mask); } - /** - * Are all elements of the matrix finite? - */ + /** Returns true if all elements of the matrix are finite. Returns false if any + element is infinity, or NaN. + + @return true if matrix has only finite elements + */ bool isFinite() const { return SkScalarsAreFinite(fMat, 9); } private: |