aboutsummaryrefslogtreecommitdiffhomepage
path: root/docs/SkMatrix_Reference.bmh
diff options
context:
space:
mode:
authorGravatar Cary Clark <caryclark@skia.org>2017-10-26 07:58:48 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-10-26 12:17:36 +0000
commit154beea85961f73ed7f0da047b7ebd16d2a2d829 (patch)
tree1e128ab8ce82ea6fd9c1a933d5bb36516dd9af4e /docs/SkMatrix_Reference.bmh
parent456b292956bbc8e90a50be74fc9ccb95ebf11ebd (diff)
Add docs for SkMatrix, SkRect, SkIRect, SkBitmap
Also minor changes to earlier docs. Many small changes to improve indentation in generated includes. Added support for matrix math illustrations. Docs-Preview: https://skia.org/?cl=58500 Bug: skia:6898 Change-Id: I7da58ad55f82d7fd41d19288beb2cd71730fb01f Reviewed-on: https://skia-review.googlesource.com/58500 Commit-Queue: Cary Clark <caryclark@skia.org> Reviewed-by: Cary Clark <caryclark@google.com> Reviewed-by: Cary Clark <caryclark@skia.org>
Diffstat (limited to 'docs/SkMatrix_Reference.bmh')
-rw-r--r--docs/SkMatrix_Reference.bmh3924
1 files changed, 2998 insertions, 926 deletions
diff --git a/docs/SkMatrix_Reference.bmh b/docs/SkMatrix_Reference.bmh
index 0db0fa881e..f91e0096b4 100644
--- a/docs/SkMatrix_Reference.bmh
+++ b/docs/SkMatrix_Reference.bmh
@@ -1,16 +1,20 @@
#Topic Matrix
+#Alias Matrices
#Alias Matrix_Reference
#Class SkMatrix
-Matrix holds a 3x3 matrix for transforming coordinates.
-Matrix elements are in column major order.
+Matrix holds a 3x3 matrix for transforming coordinates. This allows mapping
+Points and Vectors with translation, scaling, skewing, rotation, and
+perspective.
-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.).
+Matrix elements are in row major order. Matrix does not have a constructor,
+so it must be explicitly initialized. setIdentity initializes Matrix
+so it has no effect. setTranslate, setScale, setSkew, setRotate, set9 and setAll
+initializes all Matrix elements with the corresponding mapping.
-SkMatrix is not thread safe unless getType is called first.
+Matrix includes a hidden variable that classifies the type of matrix to
+improve performance. Matrix is not thread safe unless getType is called first.
#Topic Overview
@@ -26,111 +30,104 @@ SkMatrix is not thread safe unless getType is called first.
#Subtopic Operators
#Table
#Legend
-# description # function ##
+# function # description ##
#Legend ##
-# friend SK_API bool operator!=(const SkMatrix& a, const SkMatrix& b) # Returns true if members are unequal. ##
-# friend SK_API bool operator==(const SkMatrix& a, const SkMatrix& b) # Returns true if members are equal. ##
-# SkScalar operator[](int index) const # Returns one of nine Matrix values. ##
-# SkScalar& operator[](int index) # Returns a writable reference to one of nine Matrix values. ##
+# operator!=(const SkMatrix& a, const SkMatrix& b) # Returns true if members are unequal. ##
+# operator==(const SkMatrix& a, const SkMatrix& b) # Returns true if members are equal. ##
+# operator[](int index) const # Returns Matrix value. ##
+# operator[](int index) # Returns writable reference to Matrix value. ##
#Table ##
#Subtopic ##
#Subtopic Member_Functions
#Table
#Legend
-# description # function ##
+# function # description ##
#Legend ##
# Concat # Returns the concatenation of Matrix pair. ##
-# GetMapPtsProc # Returns optimal function to map Point array. ##
-# GetMapXYProc # Returns optimal function to map one Point. ##
# I # Returns a reference to a const identity Matrix. ##
# InvalidMatrix # Returns a reference to a const invalid Matrix. ##
# MakeRectToRect # Constructs from source Rect to destination Rect. ##
# MakeScale # Constructs from scale in x and y. ##
# MakeTrans # Constructs from translate in x and y. ##
-# SetAffineIdentity # Sets 2x3 array to identity. ##
-# asAffine # Copies to 2x3 array. ##
+# SetAffineIdentity # Sets 3x2 array to identity. ##
+# asAffine # Copies to 3x2 array. ##
# cheapEqualTo # Compares Matrix pair using memcmp(). ##
# decomposeScale # Separates scale if possible. ##
-# dirtyMatrixTypeCache # Private; used by testing. ##
-# dump # Sends text representation using floats to standard output. ##
+# dirtyMatrixTypeCache # Sets internal cache to unknown state. ##
+# dump() # Sends text representation using floats to standard output. ##
# fixedStepInX # Returns step in x for a position in y. ##
-# get # Returns one of nine Matrix values. ##
+# get() # Returns one of nine Matrix values. ##
# get9 # Returns all nine Matrix values. ##
-# getMapPtsProc # Returns optimal function to map Point array. ##
-# getMapXYProc # Returns optimal function to map one Point. ##
# getMaxScale # Returns maximum scaling, if possible. ##
# getMinMaxScales # Returns minimum and maximum scaling, if possible. ##
# getMinScale # Returns minimum scaling, if possible. ##
-# getPerspX # Returns horizontal perspective factor. ##
-# getPerspY # Returns vertical perspective factor. ##
+# getPerspX # Returns input x perspective factor. ##
+# getPerspY # Returns input y perspective factor. ##
# getScaleX # Returns horizontal scale factor. ##
-# getScaleY # Returns vertical scale factor.##
+# getScaleY # Returns vertical scale factor. ##
# getSkewX # Returns horizontal skew factor. ##
# getSkewY # Returns vertical skew factor. ##
-# getTranslateX # Returns horizontal translation factor. ##
-# getTranslateY # Returns vertical translation factor. ##
+# getTranslateX # Returns horizontal translation. ##
+# getTranslateY # Returns vertical translation. ##
# getType # Returns transform complexity. ##
# hasPerspective # Returns if transform includes perspective. ##
-# invert # Returns inverse, if possible. ##
+# invert() # Returns inverse, if possible. ##
# isFinite # Returns if all Matrix values are not infinity, NaN. ##
# isFixedStepInX # Returns if transformation supports fixed step in x. ##
# isIdentity # Returns if matrix equals the identity Matrix .##
# isScaleTranslate # Returns if transform is limited to scale and translate. ##
# isSimilarity # Returns if transform is limited to square scale and rotation. ##
# isTranslate # Returns if transform is limited to translate. ##
-# mapHomogeneousPoints # ##
-# mapPoints # ##
-# mapPointsWithStride # ##
-# mapRadius # ##
-# mapRect # ##
-# mapRectScaleTranslate # ##
-# mapRectToQuad # ##
-# mapVector # ##
-# mapVectors # ##
-# mapXY # ##
-# postConcat # ##
-# postIDiv # ##
-# postRotate # ##
-# postScale # ##
-# postSkew # ##
-# postTranslate # ##
-# preConcat # ##
-# preRotate # ##
-# preScale # ##
-# preSkew # ##
-# preTranslate # ##
-# preservesAxisAlignment # ##
-# preservesRightAngles # ##
-# readFromMemory # ##
-# rectStaysRect # ##
-# reset # ##
-# set # ##
-# set9 # ##
-# setAffine # ##
-# setAll # ##
-# setConcat # ##
-# setIDiv # ##
-# setIdentity # ##
-# setPerspX # ##
-# setPerspY # ##
-# setPolyToPoly # ##
-# setRSXform # ##
-# setRectToRect # ##
-# setRotate # ##
-# setScale # ##
-# setScaleTranslate # ##
-# setScaleX # ##
-# setScaleY # ##
-# setSinCos # ##
-# setSkew # ##
-# setSkewX # ##
-# setSkewY # ##
-# setTranslate # ##
-# setTranslateX # ##
-# setTranslateY # ##
-# toString # ##
-# writeToMemory # ##
+# mapHomogeneousPoints # Maps Point3 array. ##
+# mapPoints # Maps Point array. ##
+# mapPointsWithStride # Maps Point array with padding. ##
+# mapRadius # Returns mean radius of mapped Circle. ##
+# mapRect # Returns bounds of mapped Rect. ##
+# mapRectScaleTranslate # Returns bounds of mapped Rect. ##
+# mapRectToQuad # Maps Rect to Point array. ##
+# mapVector # Maps Vector. ##
+# mapVectors # Maps Vector array. ##
+# mapXY # Maps Point. ##
+# postConcat # Post-multiplies Matrix by Matrix parameter. ##
+# postIDiv # Post-multiplies Matrix by inverse scale. ##
+# postRotate # Post-multiplies Matrix by rotation. ##
+# postScale # Post-multiplies Matrix by scale. ##
+# postSkew # Post-multiplies Matrix by skew. ##
+# postTranslate # Post-multiplies Matrix by translation. ##
+# preConcat # Pre-multiplies Matrix by Matrix parameter.##
+# preRotate # Pre-multiplies Matrix by rotation. ##
+# preScale # Pre-multiplies Matrix by scale. ##
+# preSkew # Pre-multiplies Matrix by skew. ##
+# preTranslate # Pre-multiplies Matrix by translation. ##
+# preservesAxisAlignment # Returns if mapping restricts to 90 degree multiples and mirroring. ##
+# preservesRightAngles # Returns if mapped 90 angle remains 90 degrees. ##
+# rectStaysRect # Returns if mapped Rect can be represented by another Rect. ##
+# reset() # Sets Matrix to identity. ##
+# set() # Sets one value. ##
+# set9 # Sets all values from Scalar array. ##
+# setAffine # Sets left two columns. ##
+# setAll # Sets all values from parameters. ##
+# setConcat # Sets to Matrix parameter multiplied by Matrix parameter. ##
+# setIdentity # Sets Matrix to identity. ##
+# setPerspX # Sets input x perspective factor. ##
+# setPerspY # Sets input y perspective factor. ##
+# setPolyToPoly # Sets to map one to four points to an equal array of points. ##
+# setRSXform # Sets to rotate, scale, and translate. ##
+# setRectToRect # Sets to map one Rect to another. ##
+# setRotate # Sets to rotate about a point. ##
+# setScale # Sets to scale about a point. ##
+# setScaleTranslate # Sets to scale and translate. ##
+# setScaleX # Sets horizontal scale factor. ##
+# setScaleY # Sets vertical scale factor ##
+# setSinCos # Sets to rotate and scale about a point. ##
+# setSkew # Sets to skew about a point. ##
+# setSkewX # Sets horizontal skew factor. ##
+# setSkewY # Sets vertical skew factor. ##
+# setTranslate # Sets to translate in x and y. ##
+# setTranslateX # Sets horizontal translation. ##
+# setTranslateY # Sets vertical translation. ##
+# toString # Converts Matrix to machine readable form. ##
#Table ##
#Subtopic ##
@@ -140,16 +137,27 @@ SkMatrix is not thread safe unless getType is called first.
#Method static SkMatrix SK_WARN_UNUSED_RESULT MakeScale(SkScalar sx, SkScalar sy)
-#Param sx incomplete ##
-#Param sy incomplete ##
+Sets Matrix to scale by (sx, sy). Returned matrix is:
-#Return incomplete ##
+#Code
+#Literal
+| sx 0 0 |
+| 0 sy 0 |
+| 0 0 1 |
+##
+
+#Param sx horizontal scale factor ##
+#Param sy vertical scale factor ##
+
+#Return Matrix with scale ##
#Example
-// incomplete
+#Image 4
+canvas->concat(SkMatrix::MakeScale(4, 3));
+canvas->drawBitmap(source, 0, 0);
##
-#ToDo incomplete ##
+#SeeAlso setScale postScale preScale
##
@@ -157,15 +165,26 @@ SkMatrix is not thread safe unless getType is called first.
#Method static SkMatrix SK_WARN_UNUSED_RESULT MakeScale(SkScalar scale)
-#Param scale incomplete ##
+Sets Matrix to scale by (scale, scale). Returned matrix is:
+
+#Code
+#Literal
+| scale 0 0 |
+| 0 scale 0 |
+| 0 0 1 |
+##
+
+#Param scale horizontal and vertical scale factor ##
-#Return incomplete ##
+#Return Matrix with scale ##
#Example
-// incomplete
+#Image 4
+canvas->concat(SkMatrix::MakeScale(4));
+canvas->drawBitmap(source, 0, 0);
##
-#ToDo incomplete ##
+#SeeAlso setScale postScale preScale
##
@@ -173,16 +192,30 @@ SkMatrix is not thread safe unless getType is called first.
#Method static SkMatrix SK_WARN_UNUSED_RESULT MakeTrans(SkScalar dx, SkScalar dy)
-#Param dx incomplete ##
-#Param dy incomplete ##
+Sets Matrix to translate by (dx, dy). Returned matrix is:
-#Return incomplete ##
+#Code
+#Literal
+| 1 0 0 |
+| 0 1 0 |
+| dx dy 1 |
+##
+
+#Param dx horizontal translation ##
+#Param dy vertical translation ##
+
+#Return Matrix with translation ##
#Example
-// incomplete
+#Image 4
+SkMatrix matrix = SkMatrix::MakeTrans(64, 48);
+for (int i = 0; i < 4; ++i) {
+ canvas->drawBitmap(source, 0, 0);
+ canvas->concat(matrix);
+}
##
-#ToDo incomplete ##
+#SeeAlso setTranslate postTranslate preTranslate
##
@@ -200,29 +233,57 @@ SkMatrix is not thread safe unless getType is called first.
};
##
-Enum of bit fields for the mask return by getType().
-Use this to identify the complexity of the matrix.
+Enum of bit fields for mask returned by getType.
+Used to identify the complexity of Matrix, to optimize performance.
-#Const kIdentity_Mask = 0
+#Const kIdentity_Mask 0
+all bits clear if Matrix is identity
##
-#Const kTranslate_Mask = 0x01
-set if the matrix has translation
+#Const kTranslate_Mask 1
+set if Matrix has translation
##
-#Const kScale_Mask = 0x02
-set if the matrix has x or y scale
+#Const kScale_Mask 2
+set if Matrix has x or y scale
##
-#Const kAffine_Mask = 0x04
-set if the matrix skews or rotates
+#Const kAffine_Mask 4
+set if Matrix skews or rotates
##
-#Const kPerspective_Mask = 0x08
-set if the matrix is in perspective
+#Const kPerspective_Mask 8
+set if Matrix has perspective
##
#Example
-// incomplete
+ auto debugster = [](const char* prefix, const SkMatrix& matrix) -> void {
+ SkString typeMask;
+ typeMask += SkMatrix::kIdentity_Mask == matrix.getType() ? "kIdentity_Mask " : "";
+ typeMask += SkMatrix::kTranslate_Mask & matrix.getType() ? "kTranslate_Mask " : "";
+ typeMask += SkMatrix::kScale_Mask & matrix.getType() ? "kScale_Mask " : "";
+ typeMask += SkMatrix::kAffine_Mask & matrix.getType() ? "kAffine_Mask " : "";
+ typeMask += SkMatrix::kPerspective_Mask & matrix.getType() ? "kPerspective_Mask" : "";
+ SkDebugf("after %s: %s\n", prefix, typeMask.c_str());
+ };
+SkMatrix matrix;
+matrix.reset();
+debugster("reset", matrix);
+matrix.postTranslate(1, 0);
+debugster("postTranslate", matrix);
+matrix.postScale(2, 1);
+debugster("postScale", matrix);
+matrix.postRotate(45);
+debugster("postScale", matrix);
+SkPoint polys[][4] = {{{0, 0}, {0, 1}, {1, 1}, {1, 0}}, {{0, 0}, {0, 1}, {2, 1}, {1, 0}}};
+matrix.setPolyToPoly(polys[0], polys[1], 4);
+debugster("setPolyToPoly", matrix);
+#StdOut
+after reset: kIdentity_Mask
+after postTranslate: kTranslate_Mask
+after postScale: kTranslate_Mask kScale_Mask
+after postScale: kTranslate_Mask kScale_Mask kAffine_Mask
+after setPolyToPoly: kTranslate_Mask kScale_Mask kAffine_Mask kPerspective_Mask
+##
##
-#ToDo incomplete ##
+#SeeAlso getType
##
@@ -232,17 +293,26 @@ set if the matrix is in perspective
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 true, all
-other bits may be set to true even in the case of a pure perspective
-transform.
+false positives. For example, when kPerspective_Mask is set, all
+other bits are set.
-#Return incomplete ##
+#Return kIdentity_Mask, or combinations of: kTranslate_Mask, kScale_Mask,
+ kAffine_Mask, kPerspective_Mask
+##
#Example
-// incomplete
+SkMatrix matrix;
+matrix.setAll(1, 0, 0, 0, 1, 0, 0, 0, 1);
+SkDebugf("identity flags hex: %0x decimal: %d\n", matrix.getType(), matrix.getType());
+matrix.setAll(1, 0, 0, 0, 1, 0, 0, 0, .5f);
+SkDebugf("set all flags hex: %0x decimal: %d\n", matrix.getType(), matrix.getType());
+#StdOut
+identity flags hex: 0 decimal: 0
+set all flags hex: f decimal: 15
+##
##
-#ToDo incomplete ##
+#SeeAlso TypeMask
##
@@ -250,15 +320,30 @@ transform.
#Method bool isIdentity() const
-Returns true if the matrix is identity.
+Returns true if Matrix is identity. Identity matrix is:
+
+#Code
+#Literal
+| 1 0 0 |
+| 0 1 0 |
+| 0 0 1 |
+##
-#Return incomplete ##
+#Return true if Matrix has no effect ##
#Example
-// incomplete
+SkMatrix matrix;
+matrix.setAll(1, 0, 0, 0, 1, 0, 0, 0, 1);
+SkDebugf("is identity: %s\n", matrix.isIdentity() ? "true" : "false");
+matrix.setAll(1, 0, 0, 0, 1, 0, 0, 0, 2);
+SkDebugf("is identity: %s\n", matrix.isIdentity() ? "true" : "false");
+#StdOut
+is identity: true
+is identity: false
+##
##
-#ToDo incomplete ##
+#SeeAlso reset() setIdentity getType
##
@@ -266,13 +351,35 @@ Returns true if the matrix is identity.
#Method bool isScaleTranslate() const
-#Return incomplete ##
+Returns true if Matrix at most scales and translates. Matrix may be identity,
+contain only scale elements, only translate elements, or both. Matrix form is:
+
+#Code
+#Literal
+| scale-x 0 translate-x |
+| 0 scale-y translate-y |
+| 0 0 1 |
+##
+
+#Return true if Matrix is identity; or scales, translates, or both ##
#Example
-// incomplete
+SkMatrix matrix;
+for (SkScalar scaleX : { 1, 2 } ) {
+ for (SkScalar translateX : { 0, 20 } ) {
+ matrix.setAll(scaleX, 0, translateX, 0, 1, 0, 0, 0, 1);
+ SkDebugf("is scale-translate: %s\n", matrix.isScaleTranslate() ? "true" : "false");
+ }
+}
+#StdOut
+is scale-translate: true
+is scale-translate: true
+is scale-translate: true
+is scale-translate: true
+##
##
-#ToDo incomplete ##
+#SeeAlso setScale isTranslate setTranslate getType
##
@@ -280,13 +387,34 @@ Returns true if the matrix is identity.
#Method bool isTranslate() const
-#Return incomplete ##
+Returns true if Matrix is identity, or translates. Matrix form is:
+
+#Code
+#Literal
+| 1 0 translate-x |
+| 0 1 translate-y |
+| 0 0 1 |
+##
+
+#Return true if Matrix is identity, or translates ##
#Example
-// incomplete
+SkMatrix matrix;
+for (SkScalar scaleX : { 1, 2 } ) {
+ for (SkScalar translateX : { 0, 20 } ) {
+ matrix.setAll(scaleX, 0, translateX, 0, 1, 0, 0, 0, 1);
+ SkDebugf("is translate: %s\n", matrix.isTranslate() ? "true" : "false");
+ }
+}
+#StdOut
+is translate: true
+is translate: true
+is translate: false
+is translate: false
+##
##
-#ToDo incomplete ##
+#SeeAlso setTranslate getType
##
@@ -294,17 +422,48 @@ Returns true if the matrix is identity.
#Method bool rectStaysRect() const
-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 Matrix maps Rect to another Rect. If true, Matrix is identity,
+or scales, or rotates a multiple of 90 degrees, or mirrors in x or y. In all
+cases, Matrix may also have translation. Matrix form is either:
+
+#Code
+#Literal
+| scale-x 0 translate-x |
+| 0 scale-y translate-y |
+| 0 0 1 |
+##
+
+or
+
+#Code
+#Literal
+| 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 incomplete ##
+#Return true if Matrix maps one Rect into another ##
#Example
-// incomplete
+SkMatrix matrix;
+for (SkScalar angle: { 0, 90, 180, 270 } ) {
+ matrix.setRotate(angle);
+ SkDebugf("rectStaysRect: %s\n", matrix.rectStaysRect() ? "true" : "false");
+}
+#StdOut
+rectStaysRect: true
+rectStaysRect: true
+rectStaysRect: true
+rectStaysRect: true
+##
##
-#ToDo incomplete ##
+#SeeAlso preservesAxisAlignment preservesRightAngles
##
@@ -312,15 +471,49 @@ true if the matrix is identity, scale-only, or rotates a multiple of
#Method bool preservesAxisAlignment() const
-alias for rectStaysRect()
-#Return incomplete ##
+Returns true Matrix maps Rect to another Rect. If true, Matrix is identity,
+or scales, or rotates a multiple of 90 degrees, or mirrors in x or y. In all
+cases, Matrix may also have translation. Matrix form is either:
+
+#Code
+#Literal
+| scale-x 0 translate-x |
+| 0 scale-y translate-y |
+| 0 0 1 |
+##
+
+or
+
+#Code
+#Literal
+| 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 Matrix maps one Rect into another ##
#Example
-// incomplete
+SkMatrix matrix;
+for (SkScalar angle: { 0, 90, 180, 270 } ) {
+ matrix.setRotate(angle);
+ SkDebugf("preservesAxisAlignment: %s\n", matrix.preservesAxisAlignment() ? "true" : "false");
+}
+#StdOut
+preservesAxisAlignment: true
+preservesAxisAlignment: true
+preservesAxisAlignment: true
+preservesAxisAlignment: true
+##
##
-#ToDo incomplete ##
+#SeeAlso rectStaysRect preservesRightAngles
##
@@ -328,15 +521,37 @@ alias for rectStaysRect()
#Method bool hasPerspective() const
-Returns true if the matrix contains perspective elements.
+Returns true if the matrix contains perspective elements. Matrix form is:
-#Return incomplete ##
+#Code
+#Literal
+| -- -- -- |
+| -- -- -- |
+| 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 Matrix is in most general form ##
#Example
-// incomplete
+#Image 4
+SkMatrix matrix;
+SkPoint bitmapBounds[4], perspect[4] = {{50, 10}, {180, 40}, {236, 176}, {10, 206}};
+SkRect::Make(source.bounds()).toQuad(bitmapBounds);
+matrix.setPolyToPoly(bitmapBounds, perspect, 4);
+canvas->concat(matrix);
+SkString string;
+string.printf("hasPerspective %s", matrix.hasPerspective() ? "true" : "false");
+canvas->drawBitmap(source, 0, 0);
+SkPaint paint;
+paint.setAntiAlias(true);
+paint.setTextSize(48);
+canvas->drawString(string, 0, source.bounds().height() + 48, paint);
##
-#ToDo incomplete ##
+#SeeAlso setAll set9
##
@@ -344,18 +559,50 @@ Returns true if the matrix contains perspective elements.
#Method bool isSimilarity(SkScalar tol = SK_ScalarNearlyZero) const
-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 Matrix contains only translation, rotation, reflection, and
+uniform scale.
+Returns false if Matrix contains different scales, skewing, perspective, or
+degenerate forms that collapse to a line or point.
-#Param tol incomplete ##
+Describes that the Matrix 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.
-#Return incomplete ##
+Preserves right angles, keeping the arms of the angle equal lengths.
-#Example
-// incomplete
-##
+#Param tol to be deprecated ##
+
+#Return true if Matrix only rotates, uniformly scales, translates ##
-#ToDo incomplete ##
+#Example
+#Description
+String is drawn four times through but only two are visible. Drawing the pair
+with isSimilarity false reveals the pair not visible through the matrix.
+##
+ SkPaint p;
+ p.setAntiAlias(true);
+ SkMatrix m;
+ int below = 175;
+ for (SkScalar sx : { -1, 1 } ) {
+ for (SkScalar sy : { -1, 1 } ) {
+ m.setAll(sx, 1, 128, 1, sy, 32, 0, 0, 1);
+ bool isSimilarity = m.isSimilarity();
+ SkString str;
+ str.printf("sx: %g sy: %g sim: %s", sx, sy, isSimilarity ? "true" : "false");
+ {
+ SkAutoCanvasRestore autoRestore(canvas, true);
+ canvas->concat(m);
+ canvas->drawString(str, 0, 0, p);
+ }
+ if (!isSimilarity) {
+ canvas->drawString(str, 40, below, p);
+ below += 20;
+ }
+ }
+ }
+##
+
+#SeeAlso isScaleTranslate preservesRightAngles rectStaysRect isFixedStepInX
##
@@ -363,25 +610,52 @@ Returns false if other transformation types are included or is degenerate
#Method bool preservesRightAngles(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 Matrix contains only translation, rotation, reflection, and
+scale. Scale may differ along rotated axes.
+Returns false if Matrix skewing, perspective, or degenerate forms that collapse
+to a line or point.
-#Param tol incomplete ##
+Preserves right angles, but not requiring that the arms of the angle
+retain equal lengths.
-#Return incomplete ##
+#Param tol to be deprecated ##
-#Example
-// incomplete
-##
+#Return true if Matrix only rotates, scales, translates ##
-#ToDo incomplete ##
+#Example
+#Height 128
+#Description
+Equal scale is both similar and preserves right angles.
+Unequal scale is not similar but preserves right angles.
+Skews are not similar and do not preserve right angles.
+##
+SkPaint p;
+p.setAntiAlias(true);
+SkMatrix m;
+int pos = 0;
+for (SkScalar sx : { 1, 2 } ) {
+ for (SkScalar kx : { 0, 1 } ) {
+ m.setAll(sx, kx, 16, 0, 1, 32, 0, 0, 1);
+ bool isSimilarity = m.isSimilarity();
+ bool preservesRightAngles = m.preservesRightAngles();
+ SkString str;
+ str.printf("sx: %g kx: %g %s %s", sx, kx, isSimilarity ? "sim" : "",
+ preservesRightAngles ? "right" : "");
+ SkAutoCanvasRestore autoRestore(canvas, true);
+ canvas->concat(m);
+ canvas->drawString(str, 0, pos, p);
+ pos += 20;
+ }
+}
+##
+
+#SeeAlso isScaleTranslate isSimilarity rectStaysRect isFixedStepInX
##
# ------------------------------------------------------------------------------
-#Enum _anonymous
+#Enum
#Code
enum {
@@ -397,36 +671,65 @@ Returns false if other transformation types are included or is degenerate
};
##
+Matrix organizes its values in row order. These members correspond to
+each value in Matrix.
+
#Const kMScaleX 0
+horizontal scale factor
##
#Const kMSkewX 1
+horizontal skew factor
##
#Const kMTransX 2
+horizontal translation
##
#Const kMSkewY 3
+vertical skew factor
##
#Const kMScaleY 4
+vertical scale factor
##
#Const kMTransY 5
+vertical translation
##
#Const kMPersp0 6
+input x perspective factor
##
#Const kMPersp1 7
+input y perspective factor
##
#Const kMPersp2 8
+perspective bias
##
#Example
-// incomplete
-##
-
-#ToDo incomplete ##
+SkPaint black;
+black.setAntiAlias(true);
+black.setTextSize(48);
+SkPaint gray = black;
+gray.setColor(0xFF9f9f9f);
+SkScalar offset[] = { 1.5f, 1.5f, 20, 1.5f, 1.5f, 20, .03f, .01f, 2 };
+for (int i : { SkMatrix::kMScaleX, SkMatrix::kMSkewX, SkMatrix::kMTransX,
+ SkMatrix::kMSkewY, SkMatrix::kMScaleY, SkMatrix::kMTransY,
+ SkMatrix::kMPersp0, SkMatrix::kMPersp1, SkMatrix::kMPersp2 } ) {
+ SkMatrix m;
+ m.setIdentity();
+ m.set(i, offset[i]);
+ SkAutoCanvasRestore autoRestore(canvas, true);
+ canvas->translate(22 + (i % 3) * 88, 44 + (i / 3) * 88);
+ canvas->drawString("&", 0, 0, gray);
+ canvas->concat(m);
+ canvas->drawString("&", 0, 0, black);
+}
+##
+
+#SeeAlso get() set()
##
# ------------------------------------------------------------------------------
-#Enum _anonymous_2
+#Enum
#Code
enum {
@@ -439,27 +742,32 @@ Returns false if other transformation types are included or is degenerate
};
##
-Affine arrays are in column major order
-because that is how PDF and XPS like it.
+Affine arrays are in column major order to match the matrix used by
+PDF and XPS.
#Const kAScaleX 0
+horizontal scale factor
##
#Const kASkewY 1
+vertical skew factor
##
#Const kASkewX 2
+horizontal skew factor
##
#Const kAScaleY 3
+vertical scale factor
##
#Const kATransX 4
+horizontal translation
##
#Const kATransY 5
+vertical translation
##
-#Example
-// incomplete
+#NoExample
##
-#ToDo incomplete ##
+#SeeAlso SetAffineIdentity asAffine setAffine
##
@@ -467,15 +775,27 @@ because that is how PDF and XPS like it.
#Method SkScalar operator[](int index) const
-#Param index incomplete ##
+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 incomplete ##
+#Return value corresponding to index ##
#Example
-// incomplete
+SkMatrix matrix;
+matrix.setScale(42, 24);
+SkDebugf("matrix[SkMatrix::kMScaleX] %c= 42\n", matrix[SkMatrix::kMScaleX] == 42 ? '=' : '!');
+SkDebugf("matrix[SkMatrix::kMScaleY] %c= 24\n", matrix[SkMatrix::kMScaleY] == 24 ? '=' : '!');
+#StdOut
+matrix[SkMatrix::kMScaleX] == 42
+matrix[SkMatrix::kMScaleY] == 24
+##
##
-#ToDo incomplete ##
+#SeeAlso get set
##
@@ -483,15 +803,29 @@ because that is how PDF and XPS like it.
#Method SkScalar get(int index) const
-#Param index incomplete ##
+Returns one matrix value. Asserts if index is out of range and SK_DEBUG is
+defined.
-#Return incomplete ##
+#Param index one of: kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY,
+ kMPersp0, kMPersp1, kMPersp2
+##
+
+#Return value corresponding to index ##
#Example
-// incomplete
+SkMatrix matrix;
+matrix.setSkew(42, 24);
+SkDebugf("matrix.get(SkMatrix::kMSkewX) %c= 42\n",
+ matrix.get(SkMatrix::kMSkewX) == 42 ? '=' : '!');
+SkDebugf("matrix.get(SkMatrix::kMSkewY) %c= 24\n",
+ matrix.get(SkMatrix::kMSkewY) == 24 ? '=' : '!');
+#StdOut
+matrix.get(SkMatrix::kMSkewX) == 42
+matrix.get(SkMatrix::kMSkewY) == 24
+##
##
-#ToDo incomplete ##
+#SeeAlso operator[](int index) set
##
@@ -499,13 +833,21 @@ because that is how PDF and XPS like it.
#Method SkScalar getScaleX() const
-#Return incomplete ##
+Returns scale factor multiplied by x input, contributing to x output.
+With mapPoints, scales Points along the x-axis.
+
+#Return horizontal scale factor ##
#Example
-// incomplete
+SkMatrix matrix;
+matrix.setScale(42, 24);
+SkDebugf("matrix.getScaleX() %c= 42\n", matrix.getScaleX() == 42 ? '=' : '!');
+#StdOut
+matrix.getScaleX() == 42
+##
##
-#ToDo incomplete ##
+#SeeAlso get getScaleY setScaleX setScale
##
@@ -513,13 +855,21 @@ because that is how PDF and XPS like it.
#Method SkScalar getScaleY() const
-#Return incomplete ##
+Returns scale factor multiplied by y input, contributing to y output.
+With mapPoints, scales Points along the y-axis.
+
+#Return vertical scale factor ##
#Example
-// incomplete
+SkMatrix matrix;
+matrix.setScale(42, 24);
+SkDebugf("matrix.getScaleY() %c= 24\n", matrix.getScaleY() == 24 ? '=' : '!');
+#StdOut
+matrix.getScaleY() == 24
+##
##
-#ToDo incomplete ##
+#SeeAlso get getScaleX setScaleY setScale
##
@@ -527,13 +877,22 @@ because that is how PDF and XPS like it.
#Method SkScalar getSkewY() const
-#Return incomplete ##
+Returns scale factor multiplied by x input, contributing to y output.
+With mapPoints, skews Points along the y-axis.
+Skew x and y together can rotate Points.
+
+#Return vertical skew factor ##
#Example
-// incomplete
+SkMatrix matrix;
+matrix.setSkew(42, 24);
+SkDebugf("matrix.getSkewY() %c= 24\n", matrix.getSkewY() == 24 ? '=' : '!');
+#StdOut
+matrix.getSkewY() == 24
+##
##
-#ToDo incomplete ##
+#SeeAlso get getSkewX setSkewY setSkew
##
@@ -541,13 +900,22 @@ because that is how PDF and XPS like it.
#Method SkScalar getSkewX() const
-#Return incomplete ##
+Returns scale factor multiplied by y input, contributing to x output.
+With mapPoints, skews Points along the x-axis.
+Skew x and y together can rotate Points.
+
+#Return horizontal scale factor ##
#Example
-// incomplete
+SkMatrix matrix;
+matrix.setSkew(42, 24);
+SkDebugf("matrix.getSkewX() %c= 42\n", matrix.getSkewX() == 42 ? '=' : '!');
+#StdOut
+matrix.getSkewX() == 42
+##
##
-#ToDo incomplete ##
+#SeeAlso get getSkewY setSkewX setSkew
##
@@ -555,13 +923,21 @@ because that is how PDF and XPS like it.
#Method SkScalar getTranslateX() const
-#Return incomplete ##
+Returns translation contributing to x output.
+With mapPoints, moves Points along the x-axis.
+
+#Return horizontal translation factor ##
#Example
-// incomplete
+SkMatrix matrix;
+matrix.setTranslate(42, 24);
+SkDebugf("matrix.getTranslateX() %c= 42\n", matrix.getTranslateX() == 42 ? '=' : '!');
+#StdOut
+matrix.getTranslateX() == 42
+##
##
-#ToDo incomplete ##
+#SeeAlso get getTranslateY setTranslateX setTranslate
##
@@ -569,13 +945,21 @@ because that is how PDF and XPS like it.
#Method SkScalar getTranslateY() const
-#Return incomplete ##
+Returns translation contributing to y output.
+With mapPoints, moves Points along the y-axis.
+
+#Return vertical translation factor ##
#Example
-// incomplete
+SkMatrix matrix;
+matrix.setTranslate(42, 24);
+SkDebugf("matrix.getTranslateY() %c= 24\n", matrix.getTranslateY() == 24 ? '=' : '!');
+#StdOut
+matrix.getTranslateY() == 24
+##
##
-#ToDo incomplete ##
+#SeeAlso get getTranslateX setTranslateY setTranslate
##
@@ -583,13 +967,29 @@ because that is how PDF and XPS like it.
#Method SkScalar getPerspX() const
-#Return incomplete ##
+Returns factor scaling input x relative to input y.
+
+#Return input x perspective factor ##
#Example
-// incomplete
+ SkMatrix m;
+ m.setIdentity();
+ m.set(SkMatrix::kMPersp0, -0.004f);
+ SkAutoCanvasRestore autoRestore(canvas, true);
+ canvas->translate(22, 144);
+ SkPaint black;
+ black.setAntiAlias(true);
+ black.setTextSize(24);
+ SkPaint gray = black;
+ gray.setColor(0xFF9f9f9f);
+ SkString string;
+ string.appendScalar(m.getPerspX());
+ canvas->drawString(string, 0, -72, gray);
+ canvas->concat(m);
+ canvas->drawString(string, 0, 0, black);
##
-#ToDo incomplete ##
+#SeeAlso kMPersp0 getPerspY
##
@@ -597,29 +997,69 @@ because that is how PDF and XPS like it.
#Method SkScalar getPerspY() const
-#Return incomplete ##
+
+Returns factor scaling input y relative to input x.
+
+#Return input y perspective factor ##
#Example
-// incomplete
+ SkMatrix m;
+ m.setIdentity();
+ m.set(SkMatrix::kMPersp1, -0.004f);
+ SkAutoCanvasRestore autoRestore(canvas, true);
+ canvas->translate(22, 144);
+ SkPaint black;
+ black.setAntiAlias(true);
+ black.setTextSize(24);
+ SkPaint gray = black;
+ gray.setColor(0xFF9f9f9f);
+ SkString string;
+ string.appendScalar(m.getPerspY());
+ canvas->drawString(string, 0, -72, gray);
+ canvas->concat(m);
+ canvas->drawString(string, 0, 0, black);
##
-#ToDo incomplete ##
+#SeeAlso kMPersp1 getPerspX
##
# ------------------------------------------------------------------------------
-#Method SkScalar operator[](int index)
+#Method SkScalar& operator[](int index)
-#Param index incomplete ##
+Returns writable Matrix value. Asserts if index is out of range and SK_DEBUG is
+defined. Clears internal cache anticipating that caller will change Matrix value.
-#Return incomplete ##
+Next call to read Matrix state may recompute cache; subsequent writes to Matrix
+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 ##
#Example
-// incomplete
+SkMatrix matrix;
+matrix.setIdentity();
+SkDebugf("with identity matrix: x = %g\n", matrix.mapXY(24, 42).fX);
+SkScalar& skewRef = matrix[SkMatrix::kMSkewX];
+skewRef = 0;
+SkDebugf("after skew x mod: x = %g\n", matrix.mapXY(24, 42).fX);
+skewRef = 1;
+SkDebugf("after 2nd skew x mod: x = %g\n", matrix.mapXY(24, 42).fX);
+matrix.dirtyMatrixTypeCache();
+SkDebugf("after dirty cache: x = %g\n", matrix.mapXY(24, 42).fX);
+#StdOut
+with identity matrix: x = 24
+after skew x mod: x = 24
+after 2nd skew x mod: x = 24
+after dirty cache: x = 66
+##
##
-#ToDo incomplete ##
+#SeeAlso get dirtyMatrixTypeCache set
##
@@ -627,128 +1067,236 @@ because that is how PDF and XPS like it.
#Method void set(int index, SkScalar value)
-#Param index incomplete ##
-#Param value incomplete ##
+Sets Matrix 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 Matrix ##
#Example
-// incomplete
+SkMatrix matrix;
+matrix.setIdentity();
+SkDebugf("with identity matrix: x = %g\n", matrix.mapXY(24, 42).fX);
+matrix.set(SkMatrix::kMSkewX, 0);
+SkDebugf("after skew x mod: x = %g\n", matrix.mapXY(24, 42).fX);
+matrix.set(SkMatrix::kMSkewX, 1);
+SkDebugf("after 2nd skew x mod: x = %g\n", matrix.mapXY(24, 42).fX);
+#StdOut
+with identity matrix: x = 24
+after skew x mod: x = 24
+after 2nd skew x mod: x = 66
+##
##
-#ToDo incomplete ##
+#SeeAlso operator[] get
-##
+#Method ##
# ------------------------------------------------------------------------------
#Method void setScaleX(SkScalar v)
-#Param v incomplete ##
+Sets horizontal scale factor.
+
+#Param v horizontal scale factor to store ##
#Example
-// incomplete
+#Height 64
+SkPaint paint;
+paint.setAntiAlias(true);
+paint.setTextSize(24);
+canvas->drawString("normal", 12, 24, paint);
+SkMatrix matrix;
+matrix.setIdentity();
+matrix.setScaleX(3);
+canvas->concat(matrix);
+canvas->drawString("x scale", 0, 48, paint);
##
-#ToDo incomplete ##
+#SeeAlso set setScale setScaleY
-##
+#Method ##
# ------------------------------------------------------------------------------
#Method void setScaleY(SkScalar v)
-#Param v incomplete ##
+Sets vertical scale factor.
+
+#Param v vertical scale factor to store ##
#Example
-// incomplete
+#Height 192
+SkPaint paint;
+paint.setAntiAlias(true);
+paint.setTextSize(24);
+canvas->drawString("normal", 12, 24, paint);
+SkMatrix matrix;
+matrix.setIdentity();
+matrix.setScaleY(3);
+canvas->concat(matrix);
+canvas->drawString("y scale", 12, 48, paint);
##
-#ToDo incomplete ##
+#SeeAlso set setScale setScaleX
-##
+#Method ##
# ------------------------------------------------------------------------------
#Method void setSkewY(SkScalar v)
-#Param v incomplete ##
+Sets vertical skew factor.
+
+#Param v vertical skew factor to store ##
#Example
-// incomplete
+#Height 96
+SkPaint paint;
+paint.setAntiAlias(true);
+paint.setTextSize(24);
+canvas->drawString("normal", 12, 24, paint);
+SkMatrix matrix;
+matrix.setIdentity();
+matrix.setSkewY(.3f);
+canvas->concat(matrix);
+canvas->drawString("y skew", 12, 48, paint);
##
-#ToDo incomplete ##
+#SeeAlso set setSkew setSkewX
-##
+#Method ##
# ------------------------------------------------------------------------------
#Method void setSkewX(SkScalar v)
-#Param v incomplete ##
+Sets horizontal skew factor.
+
+#Param v horizontal skew factor to store ##
#Example
-// incomplete
+#Height 64
+SkPaint paint;
+paint.setAntiAlias(true);
+paint.setTextSize(24);
+canvas->drawString("normal", 12, 24, paint);
+SkMatrix matrix;
+matrix.setIdentity();
+matrix.setSkewX(-.7f);
+canvas->concat(matrix);
+canvas->drawString("x skew", 36, 48, paint);
##
-#ToDo incomplete ##
+#SeeAlso set setSkew setSkewX
-##
+#Method ##
# ------------------------------------------------------------------------------
#Method void setTranslateX(SkScalar v)
-#Param v incomplete ##
+Sets horizontal translation.
+
+#Param v horizontal translation to store ##
#Example
-// incomplete
+#Height 48
+SkPaint paint;
+paint.setAntiAlias(true);
+paint.setTextSize(24);
+canvas->drawString("normal", 8, 24, paint);
+SkMatrix matrix;
+matrix.setIdentity();
+matrix.setTranslateX(96);
+canvas->concat(matrix);
+canvas->drawString("x translate", 8, 24, paint);
##
-#ToDo incomplete ##
+#SeeAlso set setTranslate setTranslateY
-##
+#Method ##
# ------------------------------------------------------------------------------
#Method void setTranslateY(SkScalar v)
-#Param v incomplete ##
+Sets vertical translation.
+
+#Param v vertical translation to store ##
#Example
-// incomplete
+#Height 64
+SkPaint paint;
+paint.setAntiAlias(true);
+paint.setTextSize(24);
+canvas->drawString("normal", 8, 24, paint);
+SkMatrix matrix;
+matrix.setIdentity();
+matrix.setTranslateY(24);
+canvas->concat(matrix);
+canvas->drawString("y translate", 8, 24, paint);
##
-#ToDo incomplete ##
+#SeeAlso set setTranslate setTranslateX
-##
+#Method ##
# ------------------------------------------------------------------------------
#Method void setPerspX(SkScalar v)
-#Param v incomplete ##
+Sets input x perspective factor, which causes mapXY to vary input x inversely
+proportional to input y.
+
+#Param v perspective factor ##
#Example
-// incomplete
+#Image 4
+for (SkScalar perspX : { -.003f, 0.f, .003f, .012f } ) {
+ SkMatrix matrix;
+ matrix.setIdentity();
+ matrix.setPerspX(perspX);
+ canvas->save();
+ canvas->concat(matrix);
+ canvas->drawBitmap(source, 0, 0);
+ canvas->restore();
+ canvas->translate(64, 64);
+}
##
-#ToDo incomplete ##
+#SeeAlso getPerspX set setAll set9
-##
+#Method ##
# ------------------------------------------------------------------------------
#Method void setPerspY(SkScalar v)
-#Param v incomplete ##
+Sets input y perspective factor, which causes mapXY to vary input y inversely
+proportional to input x.
+
+#Param v perspective factor ##
#Example
-// incomplete
+#Image 4
+for (SkScalar perspX : { -.003f, 0.f, .003f, .012f } ) {
+ SkMatrix matrix;
+ matrix.setIdentity();
+ matrix.setPerspY(perspX);
+ canvas->save();
+ canvas->concat(matrix);
+ canvas->drawBitmap(source, 0, 0);
+ canvas->restore();
+ canvas->translate(64, 64);
+}
##
-#ToDo incomplete ##
+#SeeAlso getPerspY set setAll set9
-##
+#Method ##
# ------------------------------------------------------------------------------
@@ -756,528 +1304,1066 @@ because that is how PDF and XPS like it.
SkScalar skewY, SkScalar scaleY, SkScalar transY,
SkScalar persp0, SkScalar persp1, SkScalar persp2)
-#Param scaleX incomplete ##
-#Param skewX incomplete ##
-#Param transX incomplete ##
-#Param skewY incomplete ##
-#Param scaleY incomplete ##
-#Param transY incomplete ##
-#Param persp0 incomplete ##
-#Param persp1 incomplete ##
-#Param persp2 incomplete ##
+Sets all values from parameters. Sets matrix to:
+
+#Code
+#Literal
+| 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 ##
#Example
-// incomplete
+ SkPaint p;
+ p.setAntiAlias(true);
+ p.setTextSize(64);
+ SkMatrix m;
+ for (SkScalar sx : { -1, 1 } ) {
+ for (SkScalar sy : { -1, 1 } ) {
+ SkAutoCanvasRestore autoRestore(canvas, true);
+ m.setAll(sx, 1, 128, 0, sy, 128, 0, 0, 1);
+ canvas->concat(m);
+ canvas->drawString("K", 0, 0, p);
+ }
+ }
##
-#ToDo incomplete ##
+#SeeAlso set9
-##
+#Method ##
# ------------------------------------------------------------------------------
#Method void get9(SkScalar buffer[9]) const
-Copy the 9 scalars for this matrix into buffer, in member value ascending order:
-kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY, kMPersp0, kMPersp1, kMPersp2.
+Copies nine Scalar values contained by Matrix into buffer, in member value
+ascending order: kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY,
+kMPersp0, kMPersp1, kMPersp2.
-#Param buffer incomplete ##
+#Param buffer storage for nine Scalar values ##
#Example
-// incomplete
+SkMatrix matrix = SkMatrix::MakeRectToRect({0, 0, 1, 1}, {3, 4, 7, 9},
+ SkMatrix::kFill_ScaleToFit);
+SkScalar b[9];
+matrix.get9(b);
+SkDebugf("{%g, %g, %g},\n{%g, %g, %g},\n{%g, %g, %g}\n", b[0], b[1], b[2],
+ b[3], b[4], b[5], b[6], b[7], b[8]);
+#StdOut
+{4, 0, 3},
+{0, 5, 4},
+{0, 0, 1}
+##
##
-#ToDo incomplete ##
+#SeeAlso set9
-##
+#Method ##
# ------------------------------------------------------------------------------
#Method void set9(const SkScalar buffer[9])
-Set this matrix to the 9 scalars from the buffer, in member value ascending order:
-kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY, kMPersp0, kMPersp1, kMPersp2.
+Sets Matrix to nine Scalar values in buffer, in member value ascending order:
+kMScaleX, kMSkewX, kMTransX, kMSkewY, kMScaleY, kMTransY, kMPersp0, kMPersp1,
+kMPersp2.
+
+Sets matrix to:
-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 scale the 9 values as needed.
+#Code
+#Literal
+| 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 Matrix
+maps non-homogeneous coordinates, scaling all nine values produces an equivalent
+transformation, possibly improving precision.
-#Param buffer incomplete ##
+#Param buffer nine Scalar values ##
#Example
-// incomplete
+#Image 4
+SkMatrix m;
+SkScalar buffer[9] = {4, 0, 3, 0, 5, 4, 0, 0, 1};
+m.set9(buffer);
+canvas->concat(m);
+canvas->drawBitmap(source, 0, 0);
##
-#ToDo incomplete ##
+#SeeAlso setAll get9
-##
+#Method ##
# ------------------------------------------------------------------------------
#Method void reset()
-Set the matrix to identity
+Sets Matrix to identity; which has no effect on mapped Points. Sets Matrix to:
-#Example
-// incomplete
+#Code
+#Literal
+| 1 0 0 |
+| 0 1 0 |
+| 0 0 1 |
##
-#ToDo incomplete ##
+Also called setIdentity(); use the one that provides better inline
+documentation.
+#Example
+SkMatrix m;
+m.reset();
+SkDebugf("m.isIdentity(): %s\n", m.isIdentity() ? "true" : "false");
+#StdOut
+m.isIdentity(): true
+##
##
+#SeeAlso isIdentity setIdentity
+
+#Method ##
+
# ------------------------------------------------------------------------------
#Method void setIdentity()
-alias for reset()
+Sets Matrix to identity; which has no effect on mapped Points. Sets Matrix to:
-#Example
-// incomplete
+#Code
+#Literal
+| 1 0 0 |
+| 0 1 0 |
+| 0 0 1 |
##
-#ToDo incomplete ##
+Also called reset(); use the one that provides better inline
+documentation.
+#Example
+SkMatrix m;
+m.setIdentity();
+SkDebugf("m.isIdentity(): %s\n", m.isIdentity() ? "true" : "false");
+#StdOut
+m.isIdentity(): true
+##
##
+#SeeAlso isIdentity reset
+
+#Method ##
+
# ------------------------------------------------------------------------------
#Method void setTranslate(SkScalar dx, SkScalar dy)
-Set the matrix to translate by (dx, dy).
+Sets Matrix to translate by (dx, dy).
-#Param dx incomplete ##
-#Param dy incomplete ##
+#Param dx horizontal translation ##
+#Param dy vertical translation ##
#Example
-// incomplete
+#Height 64
+SkPaint paint;
+paint.setAntiAlias(true);
+paint.setTextSize(24);
+canvas->drawString("normal", 8, 24, paint);
+SkMatrix matrix;
+matrix.setTranslate(96, 24);
+canvas->concat(matrix);
+canvas->drawString("translate", 8, 24, paint);
##
-#ToDo incomplete ##
+#SeeAlso setTranslateX setTranslateY
-##
+#Method ##
# ------------------------------------------------------------------------------
#Method void setTranslate(const SkVector& v)
-#Param v incomplete ##
+Sets Matrix to translate by (v.fX, v.fY).
+
+#Param v Vector containing horizontal and vertical translation ##
#Example
-// incomplete
+#Height 64
+SkPaint paint;
+paint.setAntiAlias(true);
+paint.setTextSize(24);
+canvas->drawString("normal", 8, 24, paint);
+SkMatrix matrix;
+matrix.setTranslate({96, 24});
+canvas->concat(matrix);
+canvas->drawString("translate", 8, 24, paint);
##
-#ToDo incomplete ##
+#SeeAlso setTranslateX setTranslateY MakeTrans
-##
+#Method ##
# ------------------------------------------------------------------------------
#Method void setScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py)
-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 Matrix to scale by sx and sy, about a pivot point at (px, py).
+The pivot point is unchanged when mapped with Matrix.
-#Param sx incomplete ##
-#Param sy incomplete ##
-#Param px incomplete ##
-#Param py incomplete ##
+#Param sx horizontal scale factor ##
+#Param sy vertical scale factor ##
+#Param px pivot x ##
+#Param py pivot y ##
#Example
-// incomplete
+ SkPaint p;
+ p.setAntiAlias(true);
+ p.setTextSize(64);
+ SkMatrix m;
+ for (SkScalar sx : { -1, 1 } ) {
+ for (SkScalar sy : { -1, 1 } ) {
+ SkAutoCanvasRestore autoRestore(canvas, true);
+ m.setScale(sx, sy, 128, 128);
+ canvas->concat(m);
+ canvas->drawString("K", 128, 128, p);
+ }
+ }
##
-#ToDo incomplete ##
+#SeeAlso setScaleX setScaleY MakeScale preScale postScale
-##
+#Method ##
# ------------------------------------------------------------------------------
#Method void setScale(SkScalar sx, SkScalar sy)
-Set the matrix to scale by sx and sy.
-
-#Param sx incomplete ##
-#Param sy incomplete ##
-
-#Example
-// incomplete
-##
-
-#ToDo incomplete ##
-
-##
-
-# ------------------------------------------------------------------------------
-
-#Method bool setIDiv(int divx, int divy)
-
-Set the matrix to scale by 1/divx and 1/divy. Returns false and does not
-touch the matrix if either divx or divy is zero.
-
-#Param divx incomplete ##
-#Param divy incomplete ##
+Sets Matrix to scale by sx and sy about at pivot point at (0, 0).
-#Return incomplete ##
+#Param sx horizontal scale factor ##
+#Param sy vertical scale factor ##
#Example
-// incomplete
+ SkPaint p;
+ p.setAntiAlias(true);
+ p.setTextSize(64);
+ SkMatrix m;
+ for (SkScalar sx : { -1, 1 } ) {
+ for (SkScalar sy : { -1, 1 } ) {
+ SkAutoCanvasRestore autoRestore(canvas, true);
+ m.setScale(sx, sy);
+ m.postTranslate(128, 128);
+ canvas->concat(m);
+ canvas->drawString("K", 0, 0, p);
+ }
+ }
##
-#ToDo incomplete ##
+#SeeAlso setScaleX setScaleY MakeScale preScale postScale
-##
+#Method ##
# ------------------------------------------------------------------------------
#Method void setRotate(SkScalar degrees, SkScalar px, SkScalar py)
-Set the matrix to rotate by the specified number of degrees, with a
-pivot point at (px, py). The pivot point is the coordinate that should
-remain unchanged by the specified transformation.
+Sets Matrix to rotate by degrees about a pivot point at (px, py).
+The pivot point is unchanged when mapped with Matrix.
+
+Positive degrees rotates clockwise.
-#Param degrees incomplete ##
-#Param px incomplete ##
-#Param py incomplete ##
+#Param degrees angle of axes relative to upright axes ##
+#Param px pivot x ##
+#Param py pivot y ##
#Example
-// incomplete
+#Height 128
+ SkPaint paint;
+ paint.setColor(SK_ColorGRAY);
+ paint.setAntiAlias(true);
+ SkRect rect = {20, 20, 100, 100};
+ canvas->drawRect(rect, paint);
+ paint.setColor(SK_ColorRED);
+ SkMatrix matrix;
+ matrix.setRotate(25, rect.centerX(), rect.centerY());
+ canvas->concat(matrix);
+ canvas->drawRect(rect, paint);
##
-#ToDo incomplete ##
+#SeeAlso setSinCos preRotate postRotate
-##
+#Method ##
# ------------------------------------------------------------------------------
#Method void setRotate(SkScalar degrees)
-Set the matrix to rotate about (0,0) by the specified number of degrees.
+Sets Matrix to rotate by degrees about a pivot point at (0, 0).
+Positive degrees rotates clockwise.
-#Param degrees incomplete ##
+#Param degrees angle of axes relative to upright axes ##
#Example
-// incomplete
+#Height 128
+ SkPaint paint;
+ paint.setColor(SK_ColorGRAY);
+ paint.setAntiAlias(true);
+ SkRect rect = {20, 20, 100, 100};
+ canvas->drawRect(rect, paint);
+ paint.setColor(SK_ColorRED);
+ SkMatrix matrix;
+ matrix.setRotate(25);
+ canvas->translate(rect.centerX(), rect.centerY());
+ canvas->concat(matrix);
+ canvas->translate(-rect.centerX(), -rect.centerY());
+ canvas->drawRect(rect, paint);
##
-#ToDo incomplete ##
+#SeeAlso setSinCos preRotate postRotate
-##
+#Method ##
# ------------------------------------------------------------------------------
#Method void setSinCos(SkScalar sinValue, SkScalar cosValue,
SkScalar px, SkScalar py)
-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 Matrix to rotate by sinValue and cosValue, about a pivot point at (px, py).
+The pivot point is unchanged when mapped with Matrix.
+
+Vector (sinValue, cosValue) describes the angle of rotation relative to (0, 1).
+Vector length specifies scale.
-#Param sinValue incomplete ##
-#Param cosValue incomplete ##
-#Param px incomplete ##
-#Param py incomplete ##
+#Param sinValue rotation vector x component ##
+#Param cosValue rotation vector y component ##
+#Param px pivot x ##
+#Param py pivot y ##
#Example
-// incomplete
+#Height 128
+ SkPaint paint;
+ paint.setColor(SK_ColorGRAY);
+ paint.setAntiAlias(true);
+ SkRect rect = {20, 20, 100, 100};
+ canvas->drawRect(rect, paint);
+ paint.setColor(SK_ColorRED);
+ SkMatrix matrix;
+ matrix.setSinCos(.25f, .85f, rect.centerX(), rect.centerY());
+ canvas->concat(matrix);
+ canvas->drawRect(rect, paint);
##
-#ToDo incomplete ##
+#SeeAlso setRotate setScale setRSXform
-##
+#Method ##
# ------------------------------------------------------------------------------
#Method void setSinCos(SkScalar sinValue, SkScalar cosValue)
-Set the matrix to rotate by the specified sine and cosine values.
+Sets Matrix to rotate by sinValue and cosValue, about a pivot point at (0, 0).
+
+Vector (sinValue, cosValue) describes the angle of rotation relative to (0, 1).
+Vector length specifies scale.
-#Param sinValue incomplete ##
-#Param cosValue incomplete ##
+#Param sinValue rotation vector x component ##
+#Param cosValue rotation vector y component ##
#Example
-// incomplete
+#Description
+Canvas needs offset after applying Matrix to pivot about Rect center.
+##
+#Height 128
+ SkPaint paint;
+ paint.setColor(SK_ColorGRAY);
+ paint.setAntiAlias(true);
+ SkRect rect = {20, 20, 100, 100};
+ canvas->drawRect(rect, paint);
+ paint.setColor(SK_ColorRED);
+ SkMatrix matrix;
+ matrix.setSinCos(.25f, .85f);
+ matrix.postTranslate(rect.centerX(), rect.centerY());
+ canvas->concat(matrix);
+ canvas->translate(-rect.centerX(), -rect.centerY());
+ canvas->drawRect(rect, paint);
##
-#ToDo incomplete ##
+#SeeAlso setRotate setScale setRSXform
-##
+#Method ##
# ------------------------------------------------------------------------------
#Method SkMatrix& setRSXform(const SkRSXform& rsxForm)
-#Param rsxForm incomplete ##
+Sets Matrix to rotate, scale, and translate using a compressed matrix form.
+
+Vector (rsxForm.fSSin, rsxForm.fSCos) describes the angle of rotation relative
+to (0, 1). Vector length specifies scale. Mapped point is rotated and scaled
+by Vector, then translated by (rsxForm.fTx, rsxForm.fTy).
-#Return incomplete ##
+#Param rsxForm compressed RSXform matrix ##
+
+#Return reference to Matrix ##
#Example
-// incomplete
+#Description
+Canvas needs offset after applying Matrix to pivot about Rect center.
+##
+#Height 128
+ SkPaint paint;
+ paint.setColor(SK_ColorGRAY);
+ paint.setAntiAlias(true);
+ SkRect rect = {20, 20, 100, 100};
+ canvas->drawRect(rect, paint);
+ paint.setColor(SK_ColorRED);
+ SkMatrix matrix;
+ matrix.setRSXform(SkRSXform::Make(.85f, .25f, rect.centerX(), rect.centerY()));
+ canvas->concat(matrix);
+ canvas->translate(-rect.centerX(), -rect.centerY());
+ canvas->drawRect(rect, paint);
##
-#ToDo incomplete ##
+#SeeAlso setSinCos setScale setTranslate
-##
+#Method ##
# ------------------------------------------------------------------------------
#Method void setSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py)
-Set the matrix to skew by kx and ky, with a pivot point at (px, py).
-The pivot point is the coordinate that should remain unchanged by the
-specified transformation.
+Sets Matrix to skew by kx and ky, about a pivot point at (px, py).
+The pivot point is unchanged when mapped with Matrix.
-#Param kx incomplete ##
-#Param ky incomplete ##
-#Param px incomplete ##
-#Param py incomplete ##
+#Param kx horizontal skew factor ##
+#Param ky vertical skew factor ##
+#Param px pivot x ##
+#Param py pivot y ##
#Example
-// incomplete
+ SkPaint p;
+ p.setAntiAlias(true);
+ p.setTextSize(48);
+ SkMatrix m;
+ for (SkScalar sx : { -1, 0, 1 } ) {
+ for (SkScalar sy : { -1, 0, 1 } ) {
+ SkAutoCanvasRestore autoRestore(canvas, true);
+ m.setSkew(sx, sy, 96 + 64 * sx, 128 + 48 * sy);
+ canvas->concat(m);
+ canvas->drawString("K", 96 + 64 * sx, 128 + 48 * sy, p);
+ }
+ }
##
-#ToDo incomplete ##
+#SeeAlso setSkewX setSkewY preSkew postSkew
-##
+#Method ##
# ------------------------------------------------------------------------------
#Method void setSkew(SkScalar kx, SkScalar ky)
-Set the matrix to skew by kx and ky.
+Sets Matrix to skew by kx and ky, about a pivot point at (0, 0).
-#Param kx incomplete ##
-#Param ky incomplete ##
+#Param kx horizontal skew factor ##
+#Param ky vertical skew factor ##
#Example
-// incomplete
+ SkPaint p;
+ p.setAntiAlias(true);
+ p.setTextSize(48);
+ SkMatrix m;
+ for (SkScalar sx : { -1, 0, 1 } ) {
+ for (SkScalar sy : { -1, 0, 1 } ) {
+ SkAutoCanvasRestore autoRestore(canvas, true);
+ m.setSkew(sx, sy);
+ m.postTranslate(96 + 64 * sx, 128 + 48 * sy);
+ canvas->concat(m);
+ canvas->drawString("K", 0, 0, p);
+ }
+ }
##
-#ToDo incomplete ##
+#SeeAlso setSkewX setSkewY preSkew postSkew
-##
+#Method ##
# ------------------------------------------------------------------------------
#Method void setConcat(const SkMatrix& a, const SkMatrix& b)
-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 Matrix to Matrix a multiplied by Matrix b. Either a or b may be this.
-#Param a incomplete ##
-#Param b incomplete ##
+Given:
-#Example
-// incomplete
+#Code
+#Literal
+ | A B C | | J K L |
+a = | D E F |, b = | M N O |
+ | G H I | | P Q R |
##
-#ToDo incomplete ##
+sets Matrix to:
+#Code
+#Literal
+ | 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 Matrix on left side of multiply expression ##
+#Param b Matrix on right side of multiply expression ##
+
+#Example
+#Image 3
+#Description
+setPolyToPoly creates perspective matrices, one the inverse of the other.
+Multiplying the matrix by its inverse turns into an identity matrix.
+##
+SkMatrix matrix, matrix2;
+SkPoint bitmapBounds[4], perspect[4] = {{50, 10}, {180, 40}, {236, 176}, {10, 206}};
+SkRect::Make(source.bounds()).toQuad(bitmapBounds);
+matrix.setPolyToPoly(bitmapBounds, perspect, 4);
+matrix2.setPolyToPoly(perspect, bitmapBounds, 4);
+matrix.setConcat(matrix, matrix2);
+canvas->concat(matrix);
+canvas->drawBitmap(source, 0, 0);
+##
+
+#SeeAlso Concat preConcat postConcat SkCanvas::concat
+
+#Method ##
+
# ------------------------------------------------------------------------------
#Method void preTranslate(SkScalar dx, SkScalar dy)
-Preconcats the matrix with the specified translation.
-#Formula
-M' = M * T(dx, dy)
-##
+Sets Matrix to Matrix multiplied by Matrix constructed from translation (dx, dy).
+This can be thought of as moving the point to be mapped before applying Matrix.
-#Param dx incomplete ##
-#Param dy incomplete ##
+Given:
-#Example
-// incomplete
+#Code
+#Literal
+ | A B C | | 1 0 dx |
+Matrix = | D E F |, T(dx, dy) = | 0 1 dy |
+ | G H I | | 0 0 1 |
##
-#ToDo incomplete ##
+sets Matrix to:
+#Code
+#Literal
+ | 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 Matrix ##
+#Param dy y translation before applying Matrix ##
+
+#Example
+#Height 160
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ SkRect rect = {20, 20, 100, 100};
+ for (int i = 0; i < 2; ++i ) {
+ SkMatrix matrix;
+ i == 0 ? matrix.reset(): matrix.setRotate(25, rect.centerX(), 320);
+ {
+ SkAutoCanvasRestore acr(canvas, true);
+ canvas->concat(matrix);
+ paint.setColor(SK_ColorGRAY);
+ canvas->drawRect(rect, paint);
+ }
+ paint.setColor(SK_ColorRED);
+ for (int j = 0; j < 2; ++j ) {
+ SkAutoCanvasRestore acr(canvas, true);
+ matrix.preTranslate(40, 40);
+ canvas->concat(matrix);
+ canvas->drawCircle(0, 0, 3, paint);
+ }
+ }
+##
+
+#SeeAlso postTranslate setTranslate MakeTrans
+
+#Method ##
+
# ------------------------------------------------------------------------------
#Method void preScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py)
-Preconcats the matrix with the specified scale.
-#Formula
-M' = M * S(sx, sy, px, py)
+Sets Matrix to Matrix multiplied by Matrix constructed from scaling by (sx, sy)
+about pivot point (px, py).
+This can be thought of as scaling about a pivot point before applying Matrix.
+
+Given:
+
+#Code
+#Literal
+ | A B C | | sx 0 dx |
+Matrix = | D E F |, S(sx, sy, px, py) = | 0 sy dy |
+ | G H I | | 0 0 1 |
##
-#Param sx incomplete ##
-#Param sy incomplete ##
-#Param px incomplete ##
-#Param py incomplete ##
+where
-#Example
-// incomplete
+#Code
+#Literal
+dx = px - sx * px
+dy = py - sy * py
+##
+
+sets Matrix to:
+
+#Code
+#Literal
+ | 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 |
##
-#ToDo incomplete ##
+#Param sx horizontal scale factor ##
+#Param sy vertical scale factor ##
+#Param px pivot x ##
+#Param py pivot y ##
+#Example
+#Image 3
+SkMatrix matrix;
+SkPoint bitmapBounds[4], perspect[4] = {{50, 10}, {180, 40}, {236, 176}, {10, 206}};
+SkRect::Make(source.bounds()).toQuad(bitmapBounds);
+matrix.setPolyToPoly(bitmapBounds, perspect, 4);
+matrix.preScale(.75f, 1.5f, source.width() / 2, source.height() / 2);
+canvas->concat(matrix);
+canvas->drawBitmap(source, 0, 0);
##
+#SeeAlso postScale setScale MakeScale
+
+#Method ##
+
# ------------------------------------------------------------------------------
#Method void preScale(SkScalar sx, SkScalar sy)
-Preconcats the matrix with the specified scale.
-#Formula
-M' = M * S(sx, sy)
+Sets Matrix to Matrix multiplied by Matrix constructed from scaling by (sx, sy)
+about pivot point (0, 0).
+This can be thought of as scaling about the origin before applying Matrix.
+
+Given:
+
+#Code
+#Literal
+ | A B C | | sx 0 0 |
+Matrix = | D E F |, S(sx, sy) = | 0 sy 0 |
+ | G H I | | 0 0 1 |
##
-#Param sx incomplete ##
-#Param sy incomplete ##
+sets Matrix to:
-#Example
-// incomplete
+#Code
+#Literal
+ | 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 |
##
-#ToDo incomplete ##
+#Param sx horizontal scale factor ##
+#Param sy vertical scale factor ##
+#Example
+#Image 3
+SkMatrix matrix;
+SkPoint bitmapBounds[4], perspect[4] = {{50, 10}, {180, 40}, {236, 176}, {10, 206}};
+SkRect::Make(source.bounds()).toQuad(bitmapBounds);
+matrix.setPolyToPoly(bitmapBounds, perspect, 4);
+matrix.preScale(.75f, 1.5f);
+canvas->concat(matrix);
+canvas->drawBitmap(source, 0, 0);
##
+#SeeAlso postScale setScale MakeScale
+
+#Method ##
+
# ------------------------------------------------------------------------------
#Method void preRotate(SkScalar degrees, SkScalar px, SkScalar py)
-Preconcats the matrix with the specified rotation.
-#Formula
-M' = M * R(degrees, px, py)
+Sets Matrix to Matrix multiplied by Matrix constructed from rotating by degrees
+about pivot point (px, py).
+This can be thought of as rotating about a pivot point before applying Matrix.
+
+Positive degrees rotates clockwise.
+
+Given:
+
+#Code
+#Literal
+ | A B C | | c -s dx |
+Matrix = | D E F |, R(degrees, px, py) = | s c dy |
+ | G H I | | 0 0 1 |
##
-#Param degrees incomplete ##
-#Param px incomplete ##
-#Param py incomplete ##
+where
-#Example
-// incomplete
+#Code
+#Literal
+c = cos(degrees)
+s = sin(degrees)
+dx = s * py + (1 - c) * px
+dy = -s * px + (1 - c) * py
+##
+
+sets Matrix to:
+
+#Code
+#Literal
+ | 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 |
##
-#ToDo incomplete ##
+#Param degrees angle of axes relative to upright axes ##
+#Param px pivot x ##
+#Param py pivot y ##
+#Example
+#Image 3
+SkMatrix matrix;
+SkPoint bitmapBounds[4], perspect[4] = {{50, 10}, {180, 40}, {236, 176}, {10, 206}};
+SkRect::Make(source.bounds()).toQuad(bitmapBounds);
+matrix.setPolyToPoly(bitmapBounds, perspect, 4);
+matrix.preRotate(45, source.width() / 2, source.height() / 2);
+canvas->concat(matrix);
+canvas->drawBitmap(source, 0, 0);
##
+#SeeAlso postRotate setRotate
+
+#Method ##
+
# ------------------------------------------------------------------------------
#Method void preRotate(SkScalar degrees)
-Preconcats the matrix with the specified rotation.
-#Formula
-M' = M * R(degrees)
+Sets Matrix to Matrix multiplied by Matrix constructed from rotating by degrees
+about pivot point (0, 0).
+This can be thought of as rotating about the origin before applying Matrix.
+
+Positive degrees rotates clockwise.
+
+Given:
+
+#Code
+#Literal
+ | A B C | | c -s 0 |
+Matrix = | D E F |, R(degrees, px, py) = | s c 0 |
+ | G H I | | 0 0 1 |
##
-#Param degrees incomplete ##
+where
-#Example
-// incomplete
+#Code
+#Literal
+c = cos(degrees)
+s = sin(degrees)
+##
+
+sets Matrix to:
+
+#Code
+#Literal
+ | 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 |
##
-#ToDo incomplete ##
+#Param degrees angle of axes relative to upright axes ##
+#Example
+#Image 3
+SkMatrix matrix;
+SkPoint bitmapBounds[4], perspect[4] = {{50, 10}, {180, 40}, {236, 176}, {10, 206}};
+SkRect::Make(source.bounds()).toQuad(bitmapBounds);
+matrix.setPolyToPoly(bitmapBounds, perspect, 4);
+matrix.preRotate(45);
+canvas->concat(matrix);
+canvas->drawBitmap(source, 0, 0);
##
+#SeeAlso postRotate setRotate
+
+#Method ##
+
# ------------------------------------------------------------------------------
#Method void preSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py)
-Preconcats the matrix with the specified skew.
-#Formula
-M' = M * K(kx, ky, px, py)
+Sets Matrix to Matrix multiplied by Matrix constructed from skewing by (kx, ky)
+about pivot point (px, py).
+This can be thought of as skewing about a pivot point before applying Matrix.
+
+Given:
+
+#Code
+#Literal
+ | A B C | | 1 kx dx |
+Matrix = | D E F |, K(kx, ky, px, py) = | ky 1 dy |
+ | G H I | | 0 0 1 |
##
-#Param kx incomplete ##
-#Param ky incomplete ##
-#Param px incomplete ##
-#Param py incomplete ##
+where
-#Example
-// incomplete
+#Code
+#Literal
+dx = -kx * py
+dy = -ky * px
##
-#ToDo incomplete ##
+sets Matrix to:
+#Code
+#Literal
+ | 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 ##
+
+#Example
+#Image 3
+SkMatrix matrix;
+SkPoint bitmapBounds[4], perspect[4] = {{50, 10}, {180, 40}, {236, 176}, {10, 206}};
+SkRect::Make(source.bounds()).toQuad(bitmapBounds);
+matrix.setPolyToPoly(bitmapBounds, perspect, 4);
+matrix.preSkew(.5f, 0, source.width() / 2, source.height() / 2);
+canvas->concat(matrix);
+canvas->drawBitmap(source, 0, 0);
+##
+
+#SeeAlso postSkew setSkew
+
+#Method ##
+
# ------------------------------------------------------------------------------
#Method void preSkew(SkScalar kx, SkScalar ky)
-Preconcats the matrix with the specified skew.
-#Formula
-M' = M * K(kx, ky)
+Sets Matrix to Matrix multiplied by Matrix constructed from skewing by (kx, ky)
+about pivot point (0, 0).
+This can be thought of as skewing about the origin before applying Matrix.
+
+Given:
+
+#Code
+#Literal
+ | A B C | | 1 kx 0 |
+Matrix = | D E F |, K(kx, ky) = | ky 1 0 |
+ | G H I | | 0 0 1 |
##
-#Param kx incomplete ##
-#Param ky incomplete ##
+sets Matrix to:
-#Example
-// incomplete
+#Code
+#Literal
+ | 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 |
##
-#ToDo incomplete ##
+#Param kx horizontal skew factor ##
+#Param ky vertical skew factor ##
+#Example
+#Image 3
+SkMatrix matrix;
+SkPoint bitmapBounds[4], perspect[4] = {{50, 10}, {180, 40}, {236, 176}, {10, 206}};
+SkRect::Make(source.bounds()).toQuad(bitmapBounds);
+matrix.setPolyToPoly(bitmapBounds, perspect, 4);
+matrix.preSkew(.5f, 0);
+canvas->concat(matrix);
+canvas->drawBitmap(source, 0, 0);
##
+#SeeAlso postSkew setSkew
+
+#Method ##
+
# ------------------------------------------------------------------------------
#Method void preConcat(const SkMatrix& other)
-Preconcats the matrix with the specified matrix.
-#Formula
-M' = M * other
+Sets Matrix to Matrix multiplied by Matrix other.
+This can be thought of mapping by other before applying Matrix.
+
+Given:
+
+#Code
+#Literal
+ | A B C | | J K L |
+Matrix = | D E F |, other = | M N O |
+ | G H I | | P Q R |
##
-#Param other incomplete ##
+sets Matrix to:
-#Example
-// incomplete
+#Code
+#Literal
+ | 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 |
##
-#ToDo incomplete ##
+#Param other Matrix on right side of multiply expression ##
+#Example
+#Image 3
+#Description
+setPolyToPoly creates perspective matrices, one the inverse of the other.
+Multiplying the matrix by its inverse turns into an identity matrix.
+##
+SkMatrix matrix, matrix2;
+SkPoint bitmapBounds[4], perspect[4] = {{50, 10}, {180, 40}, {236, 176}, {10, 206}};
+SkRect::Make(source.bounds()).toQuad(bitmapBounds);
+matrix.setPolyToPoly(bitmapBounds, perspect, 4);
+matrix2.setPolyToPoly(perspect, bitmapBounds, 4);
+matrix.preConcat(matrix2);
+canvas->concat(matrix);
+canvas->drawBitmap(source, 0, 0);
##
+#SeeAlso postConcat setConcat Concat
+
+#Method ##
+
# ------------------------------------------------------------------------------
#Method void postTranslate(SkScalar dx, SkScalar dy)
-Postconcats the matrix with the specified translation.
-#Formula
-M' = T(dx, dy) * M
-##
+Sets Matrix to Matrix constructed from translation (dx, dy) multiplied by Matrix.
+This can be thought of as moving the point to be mapped after applying Matrix.
-#Param dx incomplete ##
-#Param dy incomplete ##
+Given:
-#Example
-// incomplete
+#Code
+#Literal
+ | J K L | | 1 0 dx |
+Matrix = | M N O |, T(dx, dy) = | 0 1 dy |
+ | P Q R | | 0 0 1 |
##
-#ToDo incomplete ##
+sets Matrix to:
+#Code
+#Literal
+ | 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 Matrix ##
+#Param dy y translation after applying Matrix ##
+
+#Example
+#Height 160
+#Description
+Compare with preTranslate example.
+##
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ SkRect rect = {20, 20, 100, 100};
+ for (int i = 0; i < 2; ++i ) {
+ SkMatrix matrix;
+ i == 0 ? matrix.reset(): matrix.setRotate(25, rect.centerX(), 320);
+ {
+ SkAutoCanvasRestore acr(canvas, true);
+ canvas->concat(matrix);
+ paint.setColor(SK_ColorGRAY);
+ canvas->drawRect(rect, paint);
+ }
+ paint.setColor(SK_ColorRED);
+ for (int j = 0; j < 2; ++j ) {
+ SkAutoCanvasRestore acr(canvas, true);
+ matrix.postTranslate(40, 40);
+ canvas->concat(matrix);
+ canvas->drawCircle(0, 0, 3, paint);
+ }
+ }
+##
+
+#SeeAlso preTranslate setTranslate MakeTrans
+
+#Method ##
+
# ------------------------------------------------------------------------------
#Method void postScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py)
-Postconcats the matrix with the specified scale.
-#Formula
-M' = S(sx, sy, px, py) * M
+Sets Matrix to Matrix constructed from scaling by (sx, sy) about pivot point
+(px, py), multiplied by Matrix.
+This can be thought of as scaling about a pivot point after applying Matrix.
+
+Given:
+
+#Code
+#Literal
+ | J K L | | sx 0 dx |
+Matrix = | M N O |, S(sx, sy, px, py) = | 0 sy dy |
+ | P Q R | | 0 0 1 |
##
-#Param sx incomplete ##
-#Param sy incomplete ##
-#Param px incomplete ##
-#Param py incomplete ##
+where
+
+#Code
+#Literal
+dx = px - sx * px
+dy = py - sy * py
+##
+
+sets Matrix to:
+
+#Code
+#Literal
+ | 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 ##
#Example
-// incomplete
+#Image 3
+SkMatrix matrix;
+SkPoint bitmapBounds[4], perspect[4] = {{50, 10}, {180, 40}, {236, 176}, {10, 206}};
+SkRect::Make(source.bounds()).toQuad(bitmapBounds);
+matrix.setPolyToPoly(bitmapBounds, perspect, 4);
+matrix.postScale(.75f, 1.5f, source.width() / 2, source.height() / 2);
+canvas->concat(matrix);
+canvas->drawBitmap(source, 0, 0);
##
-#ToDo incomplete ##
+#SeeAlso preScale setScale MakeScale
##
@@ -1285,19 +2371,43 @@ M' = S(sx, sy, px, py) * M
#Method void postScale(SkScalar sx, SkScalar sy)
-Postconcats the matrix with the specified scale.
-#Formula
-M' = S(sx, sy) * M
+Sets Matrix to Matrix constructed from scaling by (sx, sy) about pivot point
+(0, 0), multiplied by Matrix.
+This can be thought of as scaling about the origin after applying Matrix.
+
+Given:
+
+#Code
+#Literal
+ | J K L | | sx 0 0 |
+Matrix = | M N O |, S(sx, sy) = | 0 sy 0 |
+ | P Q R | | 0 0 1 |
##
-#Param sx incomplete ##
-#Param sy incomplete ##
+sets Matrix to:
+
+#Code
+#Literal
+ | 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 ##
#Example
-// incomplete
+#Image 3
+SkMatrix matrix;
+SkPoint bitmapBounds[4], perspect[4] = {{50, 10}, {180, 40}, {236, 176}, {10, 206}};
+SkRect::Make(source.bounds()).toQuad(bitmapBounds);
+matrix.setPolyToPoly(bitmapBounds, perspect, 4);
+matrix.postScale(.75f, 1.5f);
+canvas->concat(matrix);
+canvas->drawBitmap(source, 0, 0);
##
-#ToDo incomplete ##
+#SeeAlso preScale setScale MakeScale
##
@@ -1305,21 +2415,57 @@ M' = S(sx, sy) * M
#Method bool postIDiv(int divx, int divy)
-Postconcats the matrix by dividing it by the specified integers.
+Sets Matrix to Matrix constructed from scaling by
#Formula
-M' = S(1/divx, 1/divy, 0, 0) * M
+(1/divx, 1/divy)
##
+about pivot point (px, py), multiplied by Matrix.
-#Param divx incomplete ##
-#Param divy incomplete ##
+Returns false if either divx or divy is zero.
-#Return incomplete ##
+Given:
+
+#Code
+#Literal
+ | J K L | | sx 0 0 |
+Matrix = | M N O |, I(divx, divy) = | 0 sy 0 |
+ | P Q R | | 0 0 1 |
+##
+
+where
+
+#Code
+#Literal
+sx = 1 / divx
+sy = 1 / divy
+##
+
+sets Matrix to:
+
+#Code
+#Literal
+ | 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 ##
#Example
-// incomplete
+#Image 3
+SkMatrix matrix, matrix2;
+SkPoint bitmapBounds[4], perspect[4] = {{50, 10}, {180, 40}, {236, 176}, {10, 206}};
+SkRect::Make(source.bounds()).toQuad(bitmapBounds);
+matrix.setPolyToPoly(bitmapBounds, perspect, 4);
+matrix.postIDiv(1, 2);
+canvas->concat(matrix);
+canvas->drawBitmap(source, 0, 0);
##
-#ToDo incomplete ##
+#SeeAlso postScale MakeScale
##
@@ -1327,20 +2473,56 @@ M' = S(1/divx, 1/divy, 0, 0) * M
#Method void postRotate(SkScalar degrees, SkScalar px, SkScalar py)
-Postconcats the matrix with the specified rotation.
-#Formula
-M' = R(degrees, px, py) * M
+Sets Matrix to Matrix constructed from rotating by degrees about pivot point
+(px, py), multiplied by Matrix.
+This can be thought of as rotating about a pivot point after applying Matrix.
+
+Positive degrees rotates clockwise.
+
+Given:
+
+#Code
+#Literal
+ | J K L | | c -s dx |
+Matrix = | M N O |, R(degrees, px, py) = | s c dy |
+ | P Q R | | 0 0 1 |
##
-#Param degrees incomplete ##
-#Param px incomplete ##
-#Param py incomplete ##
+where
+
+#Code
+#Literal
+c = cos(degrees)
+s = sin(degrees)
+dx = s * py + (1 - c) * px
+dy = -s * px + (1 - c) * py
+##
+
+sets Matrix to:
+
+#Code
+#Literal
+ |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 ##
#Example
-// incomplete
+#Image 3
+SkMatrix matrix;
+SkPoint bitmapBounds[4], perspect[4] = {{50, 10}, {180, 40}, {236, 176}, {10, 206}};
+SkRect::Make(source.bounds()).toQuad(bitmapBounds);
+matrix.setPolyToPoly(bitmapBounds, perspect, 4);
+matrix.postRotate(45, source.width() / 2, source.height() / 2);
+canvas->concat(matrix);
+canvas->drawBitmap(source, 0, 0);
##
-#ToDo incomplete ##
+#SeeAlso preRotate setRotate
##
@@ -1348,18 +2530,52 @@ M' = R(degrees, px, py) * M
#Method void postRotate(SkScalar degrees)
-Postconcats the matrix with the specified rotation.
-#Formula
-M' = R(degrees) * M
+Sets Matrix to Matrix constructed from rotating by degrees about pivot point
+(0, 0), multiplied by Matrix.
+This can be thought of as rotating about the origin after applying Matrix.
+
+Positive degrees rotates clockwise.
+
+Given:
+
+#Code
+#Literal
+ | J K L | | c -s 0 |
+Matrix = | M N O |, R(degrees, px, py) = | s c 0 |
+ | P Q R | | 0 0 1 |
+##
+
+where
+
+#Code
+#Literal
+c = cos(degrees)
+s = sin(degrees)
##
-#Param degrees incomplete ##
+sets Matrix to:
+
+#Code
+#Literal
+ | 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 ##
#Example
-// incomplete
+#Image 3
+SkMatrix matrix;
+SkPoint bitmapBounds[4], perspect[4] = {{50, 10}, {180, 40}, {236, 176}, {10, 206}};
+SkRect::Make(source.bounds()).toQuad(bitmapBounds);
+matrix.setPolyToPoly(bitmapBounds, perspect, 4);
+matrix.postRotate(45);
+canvas->concat(matrix);
+canvas->drawBitmap(source, 0, 0);
##
-#ToDo incomplete ##
+#SeeAlso preRotate setRotate
##
@@ -1367,21 +2583,53 @@ M' = R(degrees) * M
#Method void postSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py)
-Postconcats the matrix with the specified skew.
-#Formula
-M' = K(kx, ky, px, py) * M
+Sets Matrix to Matrix constructed from skewing by (kx, ky) about pivot point
+(px, py), multiplied by Matrix.
+This can be thought of as skewing about a pivot point after applying Matrix.
+
+Given:
+
+#Code
+#Literal
+ | 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
+
+#Code
+#Literal
+dx = -kx * py
+dy = -ky * px
##
-#Param kx incomplete ##
-#Param ky incomplete ##
-#Param px incomplete ##
-#Param py incomplete ##
+sets Matrix to:
+
+#Code
+#Literal
+ | 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 ##
#Example
-// incomplete
+#Image 3
+SkMatrix matrix;
+SkPoint bitmapBounds[4], perspect[4] = {{50, 10}, {180, 40}, {236, 176}, {10, 206}};
+SkRect::Make(source.bounds()).toQuad(bitmapBounds);
+matrix.setPolyToPoly(bitmapBounds, perspect, 4);
+matrix.postSkew(.5f, 0, source.width() / 2, source.height() / 2);
+canvas->concat(matrix);
+canvas->drawBitmap(source, 0, 0);
##
-#ToDo incomplete ##
+#SeeAlso preSkew setSkew
##
@@ -1389,19 +2637,43 @@ M' = K(kx, ky, px, py) * M
#Method void postSkew(SkScalar kx, SkScalar ky)
-Postconcats the matrix with the specified skew.
-#Formula
-M' = K(kx, ky) * M
+Sets Matrix to Matrix constructed from skewing by (kx, ky) about pivot point
+(0, 0), multiplied by Matrix.
+This can be thought of as skewing about the origin after applying Matrix.
+
+Given:
+
+#Code
+#Literal
+ | J K L | | 1 kx 0 |
+Matrix = | M N O |, K(kx, ky) = | ky 1 0 |
+ | P Q R | | 0 0 1 |
##
-#Param kx incomplete ##
-#Param ky incomplete ##
+sets Matrix to:
+
+#Code
+#Literal
+ | 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 ##
#Example
-// incomplete
+#Image 3
+SkMatrix matrix;
+SkPoint bitmapBounds[4], perspect[4] = {{50, 10}, {180, 40}, {236, 176}, {10, 206}};
+SkRect::Make(source.bounds()).toQuad(bitmapBounds);
+matrix.setPolyToPoly(bitmapBounds, perspect, 4);
+matrix.postSkew(.5f, 0);
+canvas->concat(matrix);
+canvas->drawBitmap(source, 0, 0);
##
-#ToDo incomplete ##
+#SeeAlso preSkew setSkew
##
@@ -1409,18 +2681,42 @@ M' = K(kx, ky) * M
#Method void postConcat(const SkMatrix& other)
-Postconcats the matrix with the specified matrix.
-#Formula
-M' = other * M
+Sets Matrix to Matrix other multiplied by Matrix.
+This can be thought of mapping by other after applying Matrix.
+
+Given:
+
+#Code
+#Literal
+ | J K L | | A B C |
+Matrix = | M N O |, other = | D E F |
+ | P Q R | | G H I |
##
-#Param other incomplete ##
+sets Matrix to:
+
+#Code
+#Literal
+ | 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 Matrix on left side of multiply expression ##
#Example
-// incomplete
+#Image 3
+#Height 64
+SkMatrix matrix, matrix2;
+SkPoint bitmapBounds[4], perspect[4] = {{50, 10}, {180, 40}, {236, 176}, {10, 206}};
+SkRect::Make(source.bounds()).toQuad(bitmapBounds);
+matrix.setPolyToPoly(bitmapBounds, perspect, 4);
+matrix.postConcat(matrix);
+canvas->concat(matrix);
+canvas->drawBitmap(source, 0, 0);
##
-#ToDo incomplete ##
+#SeeAlso preConcat setConcat Concat
##
@@ -1437,33 +2733,57 @@ M' = other * M
};
##
-#Const kFill_ScaleToFit
-Scale in X and Y independently, so that src matches dst exactly.
-This may change the aspect ratio of the src.
+ScaleToFit describes how Matrix is constructed to map one Rect to another.
+ScaleToFit may allow Matrix to have unequal horizontal and vertical scaling,
+or may restrict Matrix to square scaling. If restricted, ScaleToFit specifies
+how Matrix maps to the side or center of the destination Rect.
+
+#Const kFill_ScaleToFit 0
+ Computes Matrix that scales in x and y independently, so that source Rect is
+ mapped to completely fill destination Rect. The aspect ratio of source Rect
+ may change.
##
-#Const 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. Aligns the result to the
-left and top edges of dst.
+#Const kStart_ScaleToFit 1
+ Computes Matrix that maintains source Rect aspect ratio, mapping source Rect
+ width or height to destination Rect. Aligns mapping to left and top edges
+ of destination Rect.
##
-#Const 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. The result is centered inside dst.
+#Const kCenter_ScaleToFit 2
+ Computes Matrix that maintains source Rect aspect ratio, mapping source Rect
+ width or height to destination Rect. Aligns mapping to center of destination
+ Rect.
##
-#Const kEnd_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. Aligns the result to the
-right and bottom edges of dst.
+#Const kEnd_ScaleToFit 3
+ Computes Matrix that maintains source Rect aspect ratio, mapping source Rect
+ width or height to destination Rect. Aligns mapping to right and bottom
+ edges of destination Rect.
##
#Example
-// incomplete
-##
-
-#ToDo incomplete ##
+ const char* labels[] = { "Fill", "Start", "Center", "End" };
+ SkRect rects[] = {{5, 5, 59, 59}, {5, 74, 59, 108}, {10, 123, 44, 172}, {10, 187, 54, 231}};
+ SkRect bounds;
+ source.getBounds(&bounds);
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ for (auto fit : { SkMatrix::kFill_ScaleToFit, SkMatrix::kStart_ScaleToFit,
+ SkMatrix::kCenter_ScaleToFit, SkMatrix::kEnd_ScaleToFit } ) {
+ for (auto rect : rects ) {
+ canvas->drawRect(rect, paint);
+ SkMatrix matrix;
+ if (!matrix.setRectToRect(bounds, rect, fit)) {
+ continue;
+ }
+ SkAutoCanvasRestore acr(canvas, true);
+ canvas->concat(matrix);
+ canvas->drawBitmap(source, 0, 0);
+ }
+ canvas->drawString(labels[fit], 10, 255, paint);
+ canvas->translate(64, 0);
+ }
+##
+
+#SeeAlso setRectToRect MakeRectToRect setPolyToPoly
##
@@ -1471,25 +2791,53 @@ right and bottom edges of dst.
#Method bool setRectToRect(const SkRect& src, const SkRect& dst, ScaleToFit stf)
-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.
+Sets Matrix to scale and translate src Rect to dst Rect. 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 Matrix to identity.
+Returns true if dst is empty, and sets Matrix to:
-#Param src the source rectangle to map from
-##
-#Param dst the destination rectangle to map to
-##
-#Param stf the ScaleToFit option
+#Code
+#Literal
+| 0 0 0 |
+| 0 0 0 |
+| 0 0 1 |
##
-#Return true if the matrix can be represented by the rectangle mapping
+#Param src Rect to map from ##
+#Param dst Rect to map to ##
+#Param stf one of: kFill_ScaleToFit, kStart_ScaleToFit,
+ kCenter_ScaleToFit, kEnd_ScaleToFit
##
-#Example
-// incomplete
-##
+#Return true if Matrix can represent Rect mapping ##
-#ToDo incomplete ##
+#Example
+ const SkRect srcs[] = { {0, 0, 0, 0}, {1, 2, 3, 4} };
+ const SkRect dsts[] = { {0, 0, 0, 0}, {5, 6, 8, 9} };
+ for (auto src : srcs) {
+ for (auto dst : dsts) {
+ SkMatrix matrix;
+ matrix.setAll(-1, -1, -1, -1, -1, -1, -1, -1, -1);
+ bool success = matrix.setRectToRect(src, dst, SkMatrix::kFill_ScaleToFit);
+ SkDebugf("src: %g, %g, %g, %g dst: %g, %g, %g, %g success: %s\n",
+ src.fLeft, src.fTop, src.fRight, src.fBottom,
+ dst.fLeft, dst.fTop, dst.fRight, dst.fBottom, success ? "true" : "false");
+ matrix.dump();
+ }
+ }
+#StdOut
+src: 0, 0, 0, 0 dst: 0, 0, 0, 0 success: false
+[ 1.0000 0.0000 0.0000][ 0.0000 1.0000 0.0000][ 0.0000 0.0000 1.0000]
+src: 0, 0, 0, 0 dst: 5, 6, 8, 9 success: false
+[ 1.0000 0.0000 0.0000][ 0.0000 1.0000 0.0000][ 0.0000 0.0000 1.0000]
+src: 1, 2, 3, 4 dst: 0, 0, 0, 0 success: true
+[ 0.0000 0.0000 0.0000][ 0.0000 0.0000 0.0000][ 0.0000 0.0000 1.0000]
+src: 1, 2, 3, 4 dst: 5, 6, 8, 9 success: true
+[ 1.5000 0.0000 3.5000][ 0.0000 1.5000 3.0000][ 0.0000 0.0000 1.0000]
+##
+##
+
+#SeeAlso MakeRectToRect ScaleToFit setPolyToPoly SkRect::isEmpty
##
@@ -1497,17 +2845,51 @@ can be represented.
#Method static SkMatrix MakeRectToRect(const SkRect& src, const SkRect& dst, ScaleToFit stf)
-#Param src incomplete ##
-#Param dst incomplete ##
-#Param stf incomplete ##
+Returns Matrix set to scale and translate src Rect to dst Rect. stf selects
+whether mapping completely fills dst or preserves the aspect ratio, and how to
+align src within dst. Returns the identity Matrix if src is empty. If dst is
+empty, returns Matrix set to:
+
+#Code
+#Literal
+| 0 0 0 |
+| 0 0 0 |
+| 0 0 1 |
+##
+
+#Param src Rect to map from ##
+#Param dst Rect to map to ##
+#Param stf one of: kFill_ScaleToFit, kStart_ScaleToFit,
+ kCenter_ScaleToFit, kEnd_ScaleToFit
+##
-#Return incomplete ##
+#Return Matrix mapping src to dst ##
#Example
-// incomplete
+ const SkRect srcs[] = { {0, 0, 0, 0}, {1, 2, 3, 4} };
+ const SkRect dsts[] = { {0, 0, 0, 0}, {5, 6, 8, 9} };
+ for (auto src : srcs) {
+ for (auto dst : dsts) {
+ SkMatrix matrix = SkMatrix::MakeRectToRect(src, dst, SkMatrix::kFill_ScaleToFit);
+ SkDebugf("src: %g, %g, %g, %g dst: %g, %g, %g, %g\n",
+ src.fLeft, src.fTop, src.fRight, src.fBottom,
+ dst.fLeft, dst.fTop, dst.fRight, dst.fBottom);
+ matrix.dump();
+ }
+ }
+#StdOut
+src: 0, 0, 0, 0 dst: 0, 0, 0, 0
+[ 1.0000 0.0000 0.0000][ 0.0000 1.0000 0.0000][ 0.0000 0.0000 1.0000]
+src: 0, 0, 0, 0 dst: 5, 6, 8, 9
+[ 1.0000 0.0000 0.0000][ 0.0000 1.0000 0.0000][ 0.0000 0.0000 1.0000]
+src: 1, 2, 3, 4 dst: 0, 0, 0, 0
+[ 0.0000 0.0000 0.0000][ 0.0000 0.0000 0.0000][ 0.0000 0.0000 1.0000]
+src: 1, 2, 3, 4 dst: 5, 6, 8, 9
+[ 1.5000 0.0000 3.5000][ 0.0000 1.5000 3.0000][ 0.0000 0.0000 1.0000]
+##
##
-#ToDo incomplete ##
+#SeeAlso setRectToRect ScaleToFit setPolyToPoly SkRect::isEmpty
##
@@ -1515,24 +2897,49 @@ can be represented.
#Method bool setPolyToPoly(const SkPoint src[], const SkPoint dst[], int count)
-Set the matrix such that the specified src points would map to the
-specified dst points. count must be within [0..4].
+Sets Matrix to map src to dst. count must be zero or greater, and four or less.
-#Param src array of src points
-##
-#Param dst array of dst points
-##
-#Param count number of points to use for the transformation
-##
+If count is zero, sets Matrix to identity and returns true.
+If count is one, sets Matrix to translate and returns true.
+If count is two or more, sets Matrix to map Points if possible; returns false
+if Matrix cannot be constructed. If count is four, Matrix may include
+perspective.
-#Return true if the matrix was set to the specified transformation
-##
+#Param src Points to map from ##
+#Param dst Points to map to ##
+#Param count number of Points in src and dst ##
-#Example
-// incomplete
+#Return true if Matrix was constructed successfully
##
-#ToDo incomplete ##
+#Example
+ const SkPoint src[] = { { 0, 0}, {30, 0}, {30, -30}, { 0, -30} };
+ const SkPoint dst[] = { {50, 0}, {80, -10}, {90, -30}, {60, -40} };
+ SkPaint blackPaint;
+ blackPaint.setAntiAlias(true);
+ blackPaint.setTextSize(42);
+ SkPaint redPaint = blackPaint;
+ redPaint.setColor(SK_ColorRED);
+ for (int count : { 1, 2, 3, 4 } ) {
+ canvas->translate(35, 55);
+ for (int index = 0; index < count; ++index) {
+ canvas->drawCircle(src[index], 3, blackPaint);
+ canvas->drawCircle(dst[index], 3, blackPaint);
+ if (index > 0) {
+ canvas->drawLine(src[index], src[index - 1], blackPaint);
+ canvas->drawLine(dst[index], dst[index - 1], blackPaint);
+ }
+ }
+ SkMatrix matrix;
+ matrix.setPolyToPoly(src, dst, count);
+ canvas->drawString("A", src[0].fX, src[0].fY, redPaint);
+ SkAutoCanvasRestore acr(canvas, true);
+ canvas->concat(matrix);
+ canvas->drawString("A", src[0].fX, src[0].fY, redPaint);
+ }
+##
+
+#SeeAlso setRectToRect MakeRectToRect
##
@@ -1540,19 +2947,35 @@ specified dst points. count must be within [0..4].
#Method bool SK_WARN_UNUSED_RESULT invert(SkMatrix* inverse) const
-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 Matrix can be inverted.
+Geometrically, if Matrix maps from source to destination, inverse Matrix
+maps from destination to source. If Matrix can not be inverted, inverse is
+unchanged.
-#Param inverse incomplete ##
+#Param inverse storage for inverted Matrix; may be nullptr ##
-#Return incomplete ##
+#Return true if Matrix can be inverted ##
#Example
-// incomplete
+#Height 128
+ const SkPoint src[] = { { 10, 120}, {120, 120}, {120, 10}, { 10, 10} };
+ const SkPoint dst[] = { {150, 120}, {200, 100}, {240, 30}, { 130, 40} };
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ SkMatrix matrix;
+ matrix.setPolyToPoly(src, dst, 4);
+ canvas->drawPoints(SkCanvas::kPolygon_PointMode, 4, src, paint);
+ canvas->drawPoints(SkCanvas::kPolygon_PointMode, 4, dst, paint);
+ paint.setColor(SK_ColorBLUE);
+ paint.setStrokeWidth(3);
+ paint.setStrokeCap(SkPaint::kRound_Cap);
+ canvas->drawPoints(SkCanvas::kPoints_PointMode, 4, dst, paint);
+ matrix.invert(&matrix);
+ canvas->concat(matrix);
+ canvas->drawPoints(SkCanvas::kPoints_PointMode, 4, dst, paint);
##
-#ToDo incomplete ##
+#SeeAlso Concat
##
@@ -1560,19 +2983,33 @@ inverted, ignore inverse and return false
#Method static void SetAffineIdentity(SkScalar affine[6])
-Fills the passed array with affine identity values
-in column major order.
+Fills affine with identity values in column major order.
+Sets affine to:
-#Param affine array to fill with affine identity values; must not be nullptr
+#Code
+#Literal
+| 1 0 0 |
+| 0 1 0 |
##
-#Return incomplete ##
+Affine 3x2 matrices in column major order are used by OpenGL and XPS.
+
+#Param affine storage for 3x2 affine matrix ##
#Example
-// incomplete
+ SkScalar affine[6];
+ SkMatrix::SetAffineIdentity(affine);
+ const char* names[] = { "ScaleX", "SkewY", "SkewX", "ScaleY", "TransX", "TransY" };
+ for (int i = 0; i < 6; ++i) {
+ SkDebugf("%s: %g ", names[i], affine[i]);
+ }
+ SkDebugf("\n");
+#StdOut
+ScaleX: 1 SkewY: 0 SkewX: 0 ScaleY: 1 TransX: 0 TransY: 0
+##
##
-#ToDo incomplete ##
+#SeeAlso setAffine asAffine
##
@@ -1580,20 +3017,36 @@ in column major order.
#Method bool SK_WARN_UNUSED_RESULT asAffine(SkScalar affine[6]) const
-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.
+Fills affine in column major order. Sets affine to:
-#Param affine array to fill with affine values; ignored if nullptr
+#Code
+#Literal
+| scale-x skew-x translate-x |
+| skew-y scale-y translate-y |
##
-#Return incomplete ##
+If Matrix contains perspective, returns false and leaves affine unchanged.
+
+#Param affine storage for 3x2 affine matrix; may be nullptr ##
+
+#Return true if Matrix does not contain perspective ##
#Example
-// incomplete
+SkMatrix matrix;
+matrix.setAll(2, 3, 4, 5, 6, 7, 0, 0, 1);
+SkScalar affine[6];
+matrix.asAffine(affine);
+const char* names[] = { "ScaleX", "SkewY", "SkewX", "ScaleY", "TransX", "TransY" };
+for (int i = 0; i < 6; ++i) {
+ SkDebugf("%s: %g ", names[i], affine[i]);
+}
+SkDebugf("\n");
+#StdOut
+ScaleX: 2 SkewY: 5 SkewX: 3 ScaleY: 6 TransX: 4 TransY: 7
+##
##
-#ToDo incomplete ##
+#SeeAlso setAffine SetAffineIdentity
##
@@ -1601,16 +3054,46 @@ and does not change the passed array.
#Method void setAffine(const SkScalar affine[6])
-Set the matrix to the specified affine values.
-Note: these are passed in column major order.
+Sets Matrix to affine values, passed in column major order. Given affine,
+column, then row, as:
+
+#Code
+#Literal
+| scale-x skew-x translate-x |
+| skew-y scale-y translate-y |
+##
-#Param affine incomplete ##
+Matrix is set, row, then column, to:
+
+#Code
+#Literal
+| scale-x skew-x translate-x |
+| skew-y scale-y translate-y |
+| 0 0 1 |
+##
+
+#Param affine 3x2 affine matrix ##
#Example
-// incomplete
+SkMatrix matrix;
+matrix.setAll(2, 3, 4, 5, 6, 7, 0, 0, 1);
+SkScalar affine[6];
+matrix.asAffine(affine);
+const char* names[] = { "ScaleX", "SkewY", "SkewX", "ScaleY", "TransX", "TransY" };
+for (int i = 0; i < 6; ++i) {
+ SkDebugf("%s: %g ", names[i], affine[i]);
+}
+SkDebugf("\n");
+matrix.reset();
+matrix.setAffine(affine);
+matrix.dump();
+#StdOut
+ScaleX: 2 SkewY: 5 SkewX: 3 ScaleY: 6 TransX: 4 TransY: 7
+[ 2.0000 3.0000 4.0000][ 5.0000 6.0000 7.0000][ 0.0000 0.0000 1.0000]
+##
##
-#ToDo incomplete ##
+#SeeAlso asAffine SetAffineIdentity
##
@@ -1618,27 +3101,58 @@ Note: these are passed in column major order.
#Method void mapPoints(SkPoint dst[], const SkPoint src[], int count) const
-Apply this matrix to the array of points specified by src, and write
-the transformed points into the array of points specified by dst.
-#Formula
-dst[] = M * src[]
-##
+Maps src Point array of length count to dst Point array of equal or greater
+length. Points are mapped by multiplying each Point by Matrix. Given:
-#Param dst storage for transformed coordinates; must
- allow count entries
+#Code
+#Literal
+ | A B C | | x |
+Matrix = | D E F |, pt = | y |
+ | G H I | | 1 |
##
-#Param src original coordinates that are to be transformed;
- must allow count entries
+
+where
+
+#Code
+#Literal
+for (i = 0; i < count; ++i) {
+ x = src[i].fX
+ y = src[i].fY
+}
##
-#Param count number of points in src to read, and then transform
- into dst
+
+each dst Point is computed as:
+
+#Code
+#Literal
+ |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 Points ##
+#Param src Points to transform ##
+#Param count number of Points to transform ##
+
#Example
-// incomplete
+ SkMatrix matrix;
+ matrix.reset();
+ const int count = 4;
+ SkPoint src[count];
+ matrix.mapRectToQuad(src, {40, 70, 180, 220} );
+ SkPaint paint;
+ paint.setARGB(77, 23, 99, 154);
+ for (int i = 0; i < 5; ++i) {
+ SkPoint dst[count];
+ matrix.mapPoints(dst, src, count);
+ canvas->drawPoints(SkCanvas::kPolygon_PointMode, count, dst, paint);
+ matrix.preRotate(35, 128, 128);
+ }
##
-#ToDo incomplete ##
+#SeeAlso mapPointsWithStride mapXY mapHomogeneousPoints mapVectors
##
@@ -1646,22 +3160,53 @@ dst[] = M * src[]
#Method void mapPoints(SkPoint pts[], int count) const
-Apply this matrix to the array of points, overwriting it with the
-transformed values.
-#Formula
-dst[] = M * pts[]
+Maps pts Point array of length count in place. Points are mapped by multiplying
+each Point by Matrix. Given:
+
+#Code
+#Literal
+ | A B C | | x |
+Matrix = | D E F |, pt = | y |
+ | G H I | | 1 |
##
-#Param pts storage for transformed points; must allow count entries
+where
+
+#Code
+#Literal
+for (i = 0; i < count; ++i) {
+ x = pts[i].fX
+ y = pts[i].fY
+}
##
-#Param count number of points in pts
+
+each resulting pts Point is computed as:
+
+#Code
+#Literal
+ |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 Points ##
+#Param count number of Points to transform ##
+
#Example
-// incomplete
+ SkMatrix matrix;
+ matrix.setRotate(35, 128, 128);
+ const int count = 4;
+ SkPoint pts[count];
+ matrix.mapRectToQuad(pts, {40, 70, 180, 220} );
+ SkPaint paint;
+ paint.setARGB(77, 23, 99, 154);
+ for (int i = 0; i < 5; ++i) {
+ canvas->drawPoints(SkCanvas::kPolygon_PointMode, count, pts, paint);
+ matrix.mapPoints(pts, count);
+ }
##
-#ToDo incomplete ##
+#SeeAlso mapPointsWithStride mapXY mapHomogeneousPoints mapVectors
##
@@ -1669,507 +3214,862 @@ dst[] = M * pts[]
#Method void mapPointsWithStride(SkPoint pts[], size_t stride, int count) const
-Like mapPoints but with custom byte stride between the points. Stride
-should be a multiple of
-#Formula
-sizeof(SkScalar)
-##
-.
-
-#Param pts incomplete ##
-#Param stride incomplete ##
-#Param count incomplete ##
+Maps count pts, skipping stride bytes to advance from one Point to the next.
+Points are mapped by multiplying each Point by Matrix. Given:
-#Example
-// incomplete
+#Code
+#Literal
+ | A B C | | x |
+Matrix = | D E F |, pt = | y |
+ | G H I | | 1 |
##
-#ToDo incomplete ##
+each resulting pts Point is computed as:
+#Code
+#Literal
+ |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
##
-# ------------------------------------------------------------------------------
-
-#Method void mapPointsWithStride(SkPoint dst[], const SkPoint src[], size_t stride, int count) const
-
-Like mapPoints but with custom byte stride between the points.
-
-#Param dst incomplete ##
-#Param src incomplete ##
-#Param stride incomplete ##
-#Param count incomplete ##
+#Param pts storage for mapped Points ##
+#Param stride size of record starting with Point, in bytes ##
+#Param count number of Points to transform ##
#Example
-// incomplete
+ SkMatrix matrix;
+ matrix.reset();
+ struct PointZ {
+ SkPoint fPt;
+ SkPoint fStationary;
+ } pts[] = {{{40, 70}, {40, 70}}, {{180, 70}, {180, 70}}, {{180, 220}, {180, 220}},
+ {{40, 220}, {40, 220}}};
+ constexpr int count = SK_ARRAY_COUNT(pts);
+ SkPaint paint;
+ paint.setARGB(77, 23, 99, 154);
+ for (int i = 0; i < 5; ++i) {
+ matrix.preRotate(10, 128, 128);
+ matrix.mapPointsWithStride(&pts[0].fPt, sizeof(PointZ), count);
+ canvas->drawPoints(SkCanvas::kPolygon_PointMode, count * 2, &pts[0].fPt, paint);
+ }
##
-#ToDo incomplete ##
+#SeeAlso mapPoints mapXY mapHomogeneousPoints mapVectors
##
# ------------------------------------------------------------------------------
-#Method void mapHomogeneousPoints(SkScalar dst[], const SkScalar src[], int count) const
+#Method void mapPointsWithStride(SkPoint dst[], const SkPoint src[], size_t stride, int count) const
-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.
-#Formula
-dst[] = M * src[]
-##
+Maps src Point array of length count to dst Point array, skipping stride bytes
+to advance from one Point to the next.
+Points are mapped by multiplying each Point by Matrix. Given:
-#Param dst storage for transformed coordinates; must
- allow 3 * count entries
-##
-#Param src original coordinates to be transformed;
- must contain at least 3 * count entries
+#Code
+#Literal
+ | A B C | | x |
+Matrix = | D E F |, src = | y |
+ | G H I | | 1 |
##
-#Param count number of triples (homogeneous points) in src to read,
- and then transform into dst
+
+each resulting dst Point is computed as:
+
+#Code
+#Literal
+ |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 Points ##
+#Param src Points to transform ##
+#Param stride size of record starting with Point, in bytes ##
+#Param count number of Points to transform ##
+
#Example
-// incomplete
+ struct PointZ {
+ SkPoint fPt;
+ const SkPoint fStationary;
+ };
+ const PointZ src[] = {{{40, 70}, {40, 70}}, {{180, 70}, {180, 70}}, {{180, 220}, {180, 220}},
+ {{40, 220}, {40, 220}}};
+ PointZ dst[] = {{{0, 0}, {60, 80}}, {{0, 0}, {150, 40}}, {{0, 0}, {100, 240}},
+ {{0, 0}, {10, 250}}};
+ constexpr int count = SK_ARRAY_COUNT(src);
+ SkPaint paint;
+ paint.setARGB(77, 23, 99, 154);
+ for (int i = 0; i < 5; ++i) {
+ SkMatrix matrix;
+ matrix.setRotate(10 * i, 128, 128);
+ matrix.mapPointsWithStride(&dst[0].fPt, &src[0].fPt, sizeof(PointZ), count);
+ canvas->drawPoints(SkCanvas::kPolygon_PointMode, count * 2, &dst[0].fPt, paint);
+ }
##
-#ToDo incomplete ##
+#SeeAlso mapPoints mapXY mapHomogeneousPoints mapVectors
##
# ------------------------------------------------------------------------------
-#Method void mapXY(SkScalar x, SkScalar y, SkPoint* result) const
+#Method void mapHomogeneousPoints(SkPoint3 dst[], const SkPoint3 src[], int count) const
-#Param x incomplete ##
-#Param y incomplete ##
-#Param result incomplete ##
+Maps src Point3 array of length count to dst Point3 array, which must of length count or
+greater. Point3 array is mapped by multiplying each Point3 by Matrix. Given:
-#Example
-// incomplete
+#Code
+#Literal
+ | A B C | | x |
+Matrix = | D E F |, src = | y |
+ | G H I | | z |
##
-#ToDo incomplete ##
+each resulting dst Point is computed as:
+#Code
+#Literal
+ |A B C| |x|
+Matrix * src = |D E F| |y| = |Ax+By+Cz Dx+Ey+Fz Gx+Hy+Iz|
+ |G H I| |z|
##
-# ------------------------------------------------------------------------------
-
-#Method SkPoint mapXY(SkScalar x, SkScalar y) const
-
-#Param x incomplete ##
-#Param y incomplete ##
-
-#Return incomplete ##
+#Param dst storage for mapped Point3 array ##
+#Param src Point3 array to transform ##
+#Param count items in Point3 array to transform ##
#Example
-// incomplete
+ SkPoint3 src[] = {{3, 3, 1}, {8, 2, 2}, {5, 0, 4}, {0, 1, 3},
+ {3, 7, 1}, {8, 6, 2}, {5, 4, 4}, {0, 5, 3}};
+ int lines[] = { 0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7 };
+ constexpr int count = SK_ARRAY_COUNT(src);
+ auto debugster = [=](SkPoint3 src[]) -> void {
+ for (size_t i = 0; i < SK_ARRAY_COUNT(lines); i += 2) {
+ const SkPoint3& s = src[lines[i]];
+ const SkPoint3& e = src[lines[i + 1]];
+ SkPaint paint;
+ paint.setARGB(77, 23, 99, 154);
+ canvas->drawLine(s.fX / s.fZ, s.fY / s.fZ, e.fX / e.fZ, e.fY / e.fZ, paint);
+ }
+ };
+ canvas->save();
+ canvas->translate(5, 5);
+ canvas->scale(15, 15);
+ debugster(src);
+ canvas->restore();
+ canvas->translate(128, 128);
+ SkMatrix matrix;
+ matrix.setAll(15, 0, 0, 0, 15, 0, -0.08, 0.04, 1);
+ matrix.mapHomogeneousPoints(&src[0].fX, &src[0].fX, count);
+ debugster(src);
##
-#ToDo incomplete ##
+#SeeAlso mapPoints mapXY mapPointsWithStride mapVectors
##
# ------------------------------------------------------------------------------
-#Method void mapVectors(SkVector dst[], const SkVector src[], int count) const
+#Method void mapXY(SkScalar x, SkScalar y, SkPoint* result) 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.
+Maps Point (x, y) to result. Point is mapped by multiplying by Matrix. Given:
-#Param dst storage for transformed coordinates; must
- allow count entries
-##
-#Param src coordinates to be transformed;
- must contain at least count entries
+#Code
+#Literal
+ | A B C | | x |
+Matrix = | D E F |, pt = | y |
+ | G H I | | 1 |
##
-#Param count number of vectors in src to read and transform
- into dst
+
+result is computed as:
+
+#Code
+#Literal
+ |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 Point to map ##
+#Param y y-coordinate of Point to map ##
+#Param result storage for mapped Point ##
+
#Example
-// incomplete
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ SkMatrix matrix;
+ matrix.setRotate(60, 128, 128);
+ SkPoint lines[] = {{50, 50}, {150, 50}, {150, 150}};
+ for (size_t i = 0; i < SK_ARRAY_COUNT(lines); ++i) {
+ SkPoint pt;
+ matrix.mapXY(lines[i].fX, lines[i].fY, &pt);
+ canvas->drawCircle(pt.fX, pt.fY, 3, paint);
+ }
+ canvas->concat(matrix);
+ canvas->drawPoints(SkCanvas::kPolygon_PointMode, SK_ARRAY_COUNT(lines), lines, paint);
##
-#ToDo incomplete ##
+#SeeAlso mapPoints mapPointsWithStride mapVectors
##
# ------------------------------------------------------------------------------
-#Method void mapVectors(SkVector vecs[], int count) const
+#Method SkPoint mapXY(SkScalar x, SkScalar y) const
-Apply this matrix to count vectors in array vecs.
-This is similar to mapPoints, but ignores any translation in the matrix.
+Returns Point (x, y) multiplied by Matrix. Given:
-#Param vecs vectors to transform; must contain at least
- count entries
+#Code
+#Literal
+ | A B C | | x |
+Matrix = | D E F |, pt = | y |
+ | G H I | | 1 |
##
-#Param count number of vectors in vecs
+
+result is computed as:
+
+#Code
+#Literal
+ |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 Point to map ##
+#Param y y-coordinate of Point to map ##
+
+#Return mapped Point ##
+
#Example
-// incomplete
+#Image 4
+SkMatrix matrix;
+SkPoint bitmapBounds[4], perspect[4] = {{50, 10}, {180, 40}, {236, 176}, {30, 206}};
+SkRect::Make(source.bounds()).toQuad(bitmapBounds);
+matrix.setPolyToPoly(bitmapBounds, perspect, 4);
+SkPaint paint;
+paint.setAntiAlias(true);
+paint.setStrokeWidth(3);
+for (int x : { 0, source.width() } ) {
+ for (int y : { 0, source.height() } ) {
+ canvas->drawPoint(matrix.mapXY(x, y), paint);
+ }
+}
+canvas->concat(matrix);
+canvas->drawBitmap(source, 0, 0);
##
-#ToDo incomplete ##
+#SeeAlso mapPoints mapPointsWithStride mapVectors
##
# ------------------------------------------------------------------------------
-#Method void mapVector(SkScalar dx, SkScalar dy, SkVector* result) const
+#Method void mapVectors(SkVector dst[], const SkVector src[], int count) const
-#Param dx incomplete ##
-#Param dy incomplete ##
-#Param result incomplete ##
+Maps src Vector array of length count to Vector Point array of equal or greater
+length. Vectors are mapped by multiplying each Vector by Matrix, treating
+Matrix translation as zero. Given:
-#Example
-// incomplete
+#Code
+#Literal
+ | A B 0 | | x |
+Matrix = | D E 0 |, src = | y |
+ | G H I | | 1 |
##
-#ToDo incomplete ##
+where
+#Code
+#Literal
+for (i = 0; i < count; ++i) {
+ x = src[i].fX
+ y = src[i].fY
+}
##
-# ------------------------------------------------------------------------------
+each dst Vector is computed as:
-#Method SkVector mapVector(SkScalar dx, SkScalar dy) const
+#Code
+#Literal
+ |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
+##
-#Param dx incomplete ##
-#Param dy incomplete ##
+src and dst may point to the same storage.
-#Return incomplete ##
+#Param dst storage for mapped Vectors ##
+#Param src Vectors to transform ##
+#Param count number of Vectors to transform ##
#Example
-// incomplete
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setStyle(SkPaint::kStroke_Style);
+ SkMatrix matrix;
+ matrix.reset();
+ const SkVector radii[] = {{8, 4}, {9, 1}, {6, 2}, {7, 3}};
+ for (int i = 0; i < 4; ++i) {
+ SkVector rScaled[4];
+ matrix.preScale(1.5f, 2.f);
+ matrix.mapVectors(rScaled, radii, SK_ARRAY_COUNT(radii));
+ SkRRect rrect;
+ rrect.setRectRadii({20, 20, 180, 70}, rScaled);
+ canvas->drawRRect(rrect, paint);
+ canvas->translate(0, 60);
+ }
##
-#ToDo incomplete ##
+#SeeAlso mapVector mapPoints mapPointsWithStride mapXY
##
# ------------------------------------------------------------------------------
-#Method bool mapRect(SkRect* dst, const SkRect& src) const
-
-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 storage for transformed rectangle ##
-#Param src rectangle to transform ##
+#Method void mapVectors(SkVector vecs[], int count) const
-#Return result of calling rectStaysRect
-##
+Maps vecs Vector array of length count in place, multiplying each Vector by
+Matrix, treating Matrix translation as zero. Given:
-#Example
-// incomplete
+#Code
+#Literal
+ | A B 0 | | x |
+Matrix = | D E 0 |, vec = | y |
+ | G H I | | 1 |
##
-#ToDo incomplete ##
+where
+#Code
+#Literal
+for (i = 0; i < count; ++i) {
+ x = vecs[i].fX
+ y = vecs[i].fY
+}
##
-# ------------------------------------------------------------------------------
-
-#Method bool mapRect(SkRect* rect) 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
+each result Vector is computed as:
-#Param rect rectangle to transform
+#Code
+#Literal
+ |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
##
-#Return the result of calling rectStaysRect
-##
+#Param vecs Vectors to transform, and storage for mapped Vectors ##
+#Param count number of Vectors to transform ##
#Example
-// incomplete
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setStyle(SkPaint::kStroke_Style);
+ SkMatrix matrix;
+ matrix.setScale(2, 3);
+ SkVector radii[] = {{7, 7}, {3, 3}, {2, 2}, {4, 0}};
+ for (int i = 0; i < 4; ++i) {
+ SkRRect rrect;
+ rrect.setRectRadii({20, 20, 180, 70}, radii);
+ canvas->drawRRect(rrect, paint);
+ canvas->translate(0, 60);
+ matrix.mapVectors(radii, SK_ARRAY_COUNT(radii));
+ }
##
-#ToDo incomplete ##
+#SeeAlso mapVector mapPoints mapPointsWithStride mapXY
##
# ------------------------------------------------------------------------------
-#Method void mapRectToQuad(SkPoint dst[4], const SkRect& rect) const
+#Method void mapVector(SkScalar dx, SkScalar dy, SkVector* result) const
-Applies Matrix to rect, 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 Matrix.
+Maps Vector (x, y) to result. Vector is mapped by multiplying by Matrix,
+treating Matrix translation as zero. Given:
-#Param dst storage for transformed quad
+#Code
+#Literal
+ | A B 0 | | dx |
+Matrix = | D E 0 |, vec = | dy |
+ | G H I | | 1 |
##
-#Param rect rectangle to transform
+
+each result Vector is computed as:
+
+#Code
+#Literal
+#Outdent
+ |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 Vector to map ##
+#Param dy y-coordinate of Vector to map ##
+#Param result storage for mapped Vector ##
+
#Example
-// incomplete
+ SkPaint paint;
+ paint.setColor(SK_ColorGREEN);
+ paint.setAntiAlias(true);
+ paint.setTextSize(48);
+ SkMatrix matrix;
+ matrix.setRotate(90);
+ SkVector offset = { 7, 7 };
+ for (int i = 0; i < 4; ++i) {
+ paint.setImageFilter(SkDropShadowImageFilter::Make(offset.fX, offset.fY, 3, 3,
+ SK_ColorBLUE, SkDropShadowImageFilter::kDrawShadowAndForeground_ShadowMode, nullptr));
+ matrix.mapVector(offset.fX, offset.fY, &offset);
+ canvas->translate(0, 60);
+ canvas->drawString("Text", 50, 0, paint);
+ }
##
-#ToDo incomplete ##
+#SeeAlso mapVectors mapPoints mapPointsWithStride mapXY
##
# ------------------------------------------------------------------------------
-#Method void mapRectScaleTranslate(SkRect* dst, const SkRect& src) const
-
-Maps a rectangle to another rectangle, asserting (in debug mode) that the matrix only contains
-scale and translate elements. If it contains other elements, the results are undefined.
+#Method SkVector mapVector(SkScalar dx, SkScalar dy) const
-#Param dst incomplete ##
-#Param src incomplete ##
+Returns Vector (x, y) multiplied by Matrix, treating Matrix translation as zero.
+Given:
-#Example
-// incomplete
+#Code
+#Literal
+ | A B 0 | | dx |
+Matrix = | D E 0 |, vec = | dy |
+ | G H I | | 1 |
##
-#ToDo incomplete ##
+each result Vector is computed as:
+#Code
+#Literal
+#Outdent
+ |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
##
-# ------------------------------------------------------------------------------
-
-#Method SkScalar mapRadius(SkScalar radius) const
+#Param dx x-coordinate of Vector to map ##
+#Param dy y-coordinate of Vector to map ##
-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.
-
-#Param radius incomplete ##
-
-#Return incomplete ##
+#Return mapped Vector ##
#Example
-// incomplete
+ SkPaint paint;
+ paint.setColor(SK_ColorGREEN);
+ paint.setAntiAlias(true);
+ paint.setTextSize(48);
+ SkMatrix matrix;
+ matrix.setRotate(90);
+ SkVector offset = { 7, 7 };
+ for (int i = 0; i < 4; ++i) {
+ paint.setImageFilter(SkDropShadowImageFilter::Make(offset.fX, offset.fY, 3, 3,
+ SK_ColorBLUE, SkDropShadowImageFilter::kDrawShadowAndForeground_ShadowMode, nullptr));
+ offset = matrix.mapVector(offset.fX, offset.fY);
+ canvas->translate(0, 60);
+ canvas->drawString("Text", 50, 0, paint);
+ }
##
-#ToDo incomplete ##
+#SeeAlso mapVectors mapPoints mapPointsWithStride mapXY
##
# ------------------------------------------------------------------------------
-#Method static MapXYProc GetMapXYProc(TypeMask mask)
+#Method bool mapRect(SkRect* dst, const SkRect& src) const
+
+Sets dst to bounds of src corners mapped by Matrix.
+Returns true if mapped corners are dst corners.
+
+Returned value is the same as calling rectStaysRect.
-#Param mask incomplete ##
+#Param dst storage for bounds of mapped Points ##
+#Param src Rect to map ##
-#Return incomplete ##
+#Return true if dst is equivalent to mapped src ##
#Example
-// incomplete
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ SkMatrix matrix;
+ matrix.setRotate(45, 128, 128);
+ SkRect rotatedBounds, bounds = {40, 50, 190, 200};
+ matrix.mapRect(&rotatedBounds, bounds );
+ paint.setColor(SK_ColorGRAY);
+ canvas->drawRect(rotatedBounds, paint);
+ canvas->concat(matrix);
+ paint.setColor(SK_ColorRED);
+ canvas->drawRect(bounds, paint);
##
-#ToDo incomplete ##
+#SeeAlso mapPoints rectStaysRect
##
# ------------------------------------------------------------------------------
-#Method MapXYProc getMapXYProc() const
+#Method bool mapRect(SkRect* rect) const
+
+Sets rect to bounds of rect corners mapped by Matrix.
+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 incomplete ##
+#Return true if result is equivalent to mapped src ##
#Example
-// incomplete
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ SkMatrix matrix;
+ matrix.setRotate(45, 128, 128);
+ SkRect bounds = {40, 50, 190, 200};
+ matrix.mapRect(&bounds);
+ paint.setColor(SK_ColorGRAY);
+ canvas->drawRect(bounds, paint);
+ canvas->concat(matrix);
+ paint.setColor(SK_ColorRED);
+ canvas->drawRect({40, 50, 190, 200}, paint);
##
-#ToDo incomplete ##
+#SeeAlso mapRectScaleTranslate mapPoints rectStaysRect
##
# ------------------------------------------------------------------------------
-#Method static MapPtsProc GetMapPtsProc(TypeMask mask)
+#Method void mapRectToQuad(SkPoint dst[4], const SkRect& rect) const
-#Param mask incomplete ##
+Maps four corners of rect to dst. Points are mapped by multiplying each
+rect corner by Matrix. rect corner is processed in this order:
+(rect.fLeft, rect.fTop), (rect.fRight, rect.fTop), (rect.fRight, rect.fBottom),
+(rect.fLeft, rect.fBottom).
-#Return incomplete ##
+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.
-#Example
-// incomplete
-##
-
-#ToDo incomplete ##
+Given:
+#Code
+#Literal
+ | 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 Point is computed as:
-#Method MapPtsProc getMapPtsProc() const
+#Code
+#Literal
+ |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
+##
-#Return incomplete ##
+#Param dst storage for mapped corner Points ##
+#Param rect Rect to map ##
#Example
-// incomplete
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ SkMatrix matrix;
+ matrix.setRotate(60, 128, 128);
+ SkRect rect = {50, 50, 150, 150};
+ SkPoint pts[4];
+ matrix.mapRectToQuad(pts, rect);
+ for (int i = 0; i < 4; ++i) {
+ canvas->drawCircle(pts[i].fX, pts[i].fY, 3, paint);
+ }
+ canvas->concat(matrix);
+ paint.setStyle(SkPaint::kStroke_Style);
+ canvas->drawRect(rect, paint);
##
-#ToDo incomplete ##
+#SeeAlso mapRect mapRectScaleTranslate
##
# ------------------------------------------------------------------------------
-#Method bool isFixedStepInX() const
+#Method void mapRectScaleTranslate(SkRect* dst, const SkRect& src) const
-Returns true if the matrix can be stepped in x (not complex
-perspective).
+Sets dst to bounds of src corners mapped by Matrix. If matrix contains
+elements other than scale or translate: asserts if SK_DEBUG is defined;
+otherwise, results are undefined.
-#Return incomplete ##
+#Param dst storage for bounds of mapped Points ##
+#Param src Rect to map ##
#Example
-// incomplete
+ SkPaint paint;
+ SkMatrix matrix;
+ SkRect rect = {100, 50, 150, 180};
+ matrix.setScale(2, .5f, rect.centerX(), rect.centerY());
+ SkRect rotated;
+ matrix.mapRectScaleTranslate(&rotated, rect);
+ paint.setStyle(SkPaint::kStroke_Style);
+ canvas->drawRect(rect, paint);
+ paint.setColor(SK_ColorRED);
+ canvas->drawRect(rotated, paint);
##
-#ToDo incomplete ##
+#SeeAlso mapRect mapRectToQuad isScaleTranslate rectStaysRect
##
# ------------------------------------------------------------------------------
-#Method SkVector fixedStepInX(SkScalar y) const
+#Method SkScalar mapRadius(SkScalar radius) const
-If the matrix can be stepped in x (not complex perspective)
-then return the step value.
-If it cannot, behavior is undefined.
+Returns geometric mean radius of ellipse formed by constructing Circle of
+size radius, and mapping constructed Circle with Matrix. The result squared is
+equal to the major axis length times the minor axis length.
+Result is not meaningful if Matrix contains perspective elements.
-#Param y incomplete ##
+#Param radius Circle size to map ##
-#Return incomplete ##
+#Return average mapped radius ##
#Example
-// incomplete
-##
-
-#ToDo incomplete ##
+#Description
+The area enclosed by a square with sides equal to mappedRadius is the same as
+the area enclosed by the ellipse major and minor axes.
+##
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ SkMatrix matrix;
+ const SkPoint center = {108, 93};
+ matrix.setScale(2, .5f, center.fX, center.fY);
+ matrix.postRotate(45, center.fX, center.fY);
+ const SkScalar circleRadius = 50;
+ SkScalar mappedRadius = matrix.mapRadius(circleRadius);
+ SkVector minorAxis, majorAxis;
+ matrix.mapVector(0, circleRadius, &minorAxis);
+ matrix.mapVector(circleRadius, 0, &majorAxis);
+ SkString mappedArea;
+ mappedArea.printf("area = %g", mappedRadius * mappedRadius);
+ canvas->drawString(mappedArea, 145, 250, paint);
+ canvas->drawString("mappedRadius", center.fX + mappedRadius + 3, center.fY, paint);
+ paint.setColor(SK_ColorRED);
+ SkString axArea;
+ axArea.printf("area = %g", majorAxis.length() * minorAxis.length());
+ paint.setStyle(SkPaint::kFill_Style);
+ canvas->drawString(axArea, 15, 250, paint);
+ paint.setStyle(SkPaint::kStroke_Style);
+ canvas->drawRect({10, 200, 10 + majorAxis.length(), 200 + minorAxis.length()}, paint);
+ paint.setColor(SK_ColorBLACK);
+ canvas->drawLine(center.fX, center.fY, center.fX + mappedRadius, center.fY, paint);
+ canvas->drawLine(center.fX, center.fY, center.fX, center.fY + mappedRadius, paint);
+ canvas->drawRect({140, 180, 140 + mappedRadius, 180 + mappedRadius}, paint);
+ canvas->concat(matrix);
+ canvas->drawCircle(center.fX, center.fY, circleRadius, paint);
+ paint.setColor(SK_ColorRED);
+ canvas->drawLine(center.fX, center.fY, center.fX + circleRadius, center.fY, paint);
+ canvas->drawLine(center.fX, center.fY, center.fX, center.fY + circleRadius, paint);
+##
+
+#SeeAlso mapVector
##
# ------------------------------------------------------------------------------
-#Method bool cheapEqualTo(const SkMatrix& m) const
-
-Returns true if Matrix equals m, using an efficient comparison.
-
-Return false when the sign of zero values is the different, that is, one
-matrix has positive zero value and the other has negative zero value.
+#Method bool isFixedStepInX() const
-Normally, comparing NaN prevents the value from equaling any other value,
-including itself. To improve performance, NaN values are treated as bit patterns
-that are equal if their bit patterns are equal.
+Returns true if a unit step in x at some y mapped through Matrix can be
+represented by a constant Vector. Returns true if getType returns kIdentity_Mask,
+or combinations of: kTranslate_Mask, kScale_Mask, and kAffine_Mask.
-#Param m incomplete ##
+May return true if getType returns kPerspective_Mask, but only when Matrix
+does not include rotation or skewing along the y-axis.
-#Return incomplete ##
+#Return true if Matrix does not have complex perspective ##
#Example
-// incomplete
-##
-
-#ToDo incomplete ##
+ SkMatrix matrix;
+ for (SkScalar px : { 0.0f, 0.1f } ) {
+ for (SkScalar py : { 0.0f, 0.1f } ) {
+ for (SkScalar sy : { 1, 2 } ) {
+ matrix.setAll(1, 0, 0, 0, sy, 0, px, py, 1);
+ matrix.dump();
+ SkDebugf("isFixedStepInX: %s\n", matrix.isFixedStepInX() ? "true" : "false");
+ }
+ }
+ }
+#StdOut
+[ 1.0000 0.0000 0.0000][ 0.0000 1.0000 0.0000][ 0.0000 0.0000 1.0000]
+isFixedStepInX: true
+[ 1.0000 0.0000 0.0000][ 0.0000 2.0000 0.0000][ 0.0000 0.0000 1.0000]
+isFixedStepInX: true
+[ 1.0000 0.0000 0.0000][ 0.0000 1.0000 0.0000][ 0.0000 0.1000 1.0000]
+isFixedStepInX: true
+[ 1.0000 0.0000 0.0000][ 0.0000 2.0000 0.0000][ 0.0000 0.1000 1.0000]
+isFixedStepInX: true
+[ 1.0000 0.0000 0.0000][ 0.0000 1.0000 0.0000][ 0.1000 0.0000 1.0000]
+isFixedStepInX: false
+[ 1.0000 0.0000 0.0000][ 0.0000 2.0000 0.0000][ 0.1000 0.0000 1.0000]
+isFixedStepInX: false
+[ 1.0000 0.0000 0.0000][ 0.0000 1.0000 0.0000][ 0.1000 0.1000 1.0000]
+isFixedStepInX: false
+[ 1.0000 0.0000 0.0000][ 0.0000 2.0000 0.0000][ 0.1000 0.1000 1.0000]
+isFixedStepInX: false
+##
+##
+
+#SeeAlso fixedStepInX getType
##
# ------------------------------------------------------------------------------
-#Method friend SK_API bool operator==(const SkMatrix& a, const SkMatrix& b)
+#Method SkVector fixedStepInX(SkScalar y) const
-mac chromium debug build requires SK_API to make operator== visible
+Returns Vector representing a unit step in x at y mapped through Matrix.
+If isFixedStepInX is false, returned value is undefined.
-#Param a incomplete ##
-#Param b incomplete ##
+#Param y position of line parallel to x-axis ##
-#Return incomplete ##
+#Return Vector advance of mapped unit step in x ##
#Example
-// incomplete
-##
-
-#ToDo incomplete ##
+#Image 3
+ SkMatrix matrix;
+ const SkPoint center = { 128, 128 };
+ matrix.setScale(20, 25, center.fX, center.fY);
+ matrix.postRotate(75, center.fX, center.fY);
+ {
+ SkAutoCanvasRestore acr(canvas, true);
+ canvas->concat(matrix);
+ canvas->drawBitmap(source, 0, 0);
+ }
+ if (matrix.isFixedStepInX()) {
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ SkVector step = matrix.fixedStepInX(128);
+ SkVector end = center + step;
+ canvas->drawLine(center, end, paint);
+ SkVector arrow = { step.fX + step.fY, step.fY - step.fX};
+ arrow = arrow * .25f;
+ canvas->drawLine(end, end - arrow, paint);
+ canvas->drawLine(end, {end.fX + arrow.fY, end.fY - arrow.fX}, paint);
+ }
+##
+
+#SeeAlso isFixedStepInX getType
##
# ------------------------------------------------------------------------------
-#Method friend SK_API bool operator!=(const SkMatrix& a, const SkMatrix& b)
-
-#Param a incomplete ##
-#Param b incomplete ##
+#Method bool cheapEqualTo(const SkMatrix& m) const
-#Return incomplete ##
+Returns true if Matrix equals m, using an efficient comparison.
-#Example
-// incomplete
-##
+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.
-#ToDo incomplete ##
+Returns true even when both Matrices 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 Matrix to compare ##
-#Enum _anonymous_3
+#Return true if m and Matrix are represented by identical bit patterns ##
-#Code
- enum {
- kMaxFlattenSize = 9 * sizeof(SkScalar) + sizeof(uint32_t),
+#Example
+ auto debugster = [](const char* prefix, const SkMatrix& a, const SkMatrix& b) -> void {
+ SkDebugf("%s: a %c= b a.cheapEqualTo(b): %s\n", prefix,
+ a == b ? '=' : '!', a.cheapEqualTo(b) ? "true" : "false");
};
+ SkMatrix a, b;
+ a.setAll(1, 0, 0, 0, 1, 0, 0, 0, 1);
+ b.setIdentity();
+ debugster("identity", a, b);
+ a.setAll(1, -0.0f, 0, 0, 1, 0, 0, 0, 1);
+ debugster("neg zero", a, b);
+ a.setAll(1, SK_ScalarNaN, 0, 0, 1, 0, 0, 0, 1);
+ debugster(" one NaN", a, b);
+ b.setAll(1, SK_ScalarNaN, 0, 0, 1, 0, 0, 0, 1);
+ debugster("both NaN", a, b);
+#StdOut
+identity: a == b a.cheapEqualTo(b): true
+neg zero: a == b a.cheapEqualTo(b): false
+ one NaN: a != b a.cheapEqualTo(b): false
+both NaN: a != b a.cheapEqualTo(b): true
##
-
-#Const kMaxFlattenSize = 9 * sizeof(SkScalar) + sizeof(uint32_t)
- writeToMemory and readFromMemory will never return a value larger than this
-##
-
-#Example
-// incomplete
##
-#ToDo incomplete ##
+#SeeAlso operator==(const SkMatrix& a, const SkMatrix& b)
##
# ------------------------------------------------------------------------------
-#Method size_t writeToMemory(void* buffer) const
+#Method bool operator==(const SkMatrix& a, const SkMatrix& b)
-return the number of bytes written, whether or not buffer is null
+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 Matrix
+contains NaN, even if the other Matrix also contains NaN.
-#Param buffer incomplete ##
+#Param a Matrix to compare ##
+#Param b Matrix to compare ##
-#Return incomplete ##
+#Return true if m and Matrix are numerically equal ##
#Example
-// incomplete
+ auto debugster = [](const char* prefix, const SkMatrix& a, const SkMatrix& b) -> void {
+ SkDebugf("%s: a %c= b a.cheapEqualTo(b): %s\n", prefix,
+ a == b ? '=' : '!', a.cheapEqualTo(b) ? "true" : "false");
+ };
+ SkMatrix a, b;
+ a.setAll(1, 0, 0, 0, 1, 0, 0, 0, 1);
+ b.setScale(2, 4);
+ b.postScale(0.5f, 0.25f);
+ debugster("identity", a, b);
+#StdOut
+identity: a == b a.cheapEqualTo(b): true
+##
##
-#ToDo incomplete ##
+#SeeAlso cheapEqualTo operator!=(const SkMatrix& a, const SkMatrix& b)
##
# ------------------------------------------------------------------------------
-#Method size_t readFromMemory(const void* buffer, size_t length)
+#Method bool operator!=(const SkMatrix& a, const SkMatrix& b)
-Reads data from the buffer parameter
+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 Matrix
+contains NaN, even if the other Matrix also contains NaN.
-#Param buffer memory to read from
-##
-#Param length amount of memory available in the buffer
-##
+#Param a Matrix to compare ##
+#Param b Matrix to compare ##
-#Return number of bytes read (must be a multiple of 4) or
- 0 if there was not enough memory available
-##
+#Return true if m and Matrix are numerically not equal ##
#Example
-// incomplete
+ auto debugster = [](const char* prefix, const SkMatrix& a, const SkMatrix& b) -> void {
+ SkDebugf("%s: a %c= b a.cheapEqualTo(b): %s\n", prefix,
+ a != b ? '!' : '=', a.cheapEqualTo(b) ? "true" : "false");
+ };
+ SkMatrix a, b;
+ a.setAll(1, 0, 0, 0, 1, 0, 1, 0, 1);
+ a.invert(&b);
+ debugster("identity", a, b);
##
-#ToDo incomplete ##
+#SeeAlso cheapEqualTo operator==(const SkMatrix& a, const SkMatrix& b)
##
@@ -2177,11 +4077,26 @@ Reads data from the buffer parameter
#Method void dump() const
+Writes text representation of Matrix to standard output. Floating point values
+are written with limited precision; it may not be possible to reconstruct
+original Matrix from output.
+
#Example
-// incomplete
+ SkMatrix matrix;
+ matrix.setRotate(45);
+ matrix.dump();
+ SkMatrix nearlyEqual;
+ nearlyEqual.setAll(0.7071f, -0.7071f, 0, 0.7071f, 0.7071f, 0, 0, 0, 1);
+ nearlyEqual.dump();
+ SkDebugf("matrix %c= nearlyEqual\n", matrix == nearlyEqual ? '=' : '!');
+#StdOut
+[ 0.7071 -0.7071 0.0000][ 0.7071 0.7071 0.0000][ 0.0000 0.0000 1.0000]
+[ 0.7071 -0.7071 0.0000][ 0.7071 0.7071 0.0000][ 0.0000 0.0000 1.0000]
+matrix != nearlyEqual
+##
##
-#ToDo incomplete ##
+#SeeAlso toString
##
@@ -2189,13 +4104,31 @@ Reads data from the buffer parameter
#Method void toString(SkString* str) const
-#Param str incomplete ##
+Creates string representation of Matrix. Floating point values
+are written with limited precision; it may not be possible to reconstruct
+original Matrix from output.
+
+#Param str storage for string representation of Matrix ##
#Example
-// incomplete
+ SkMatrix matrix;
+ matrix.setRotate(45);
+ SkString mStr, neStr;
+ matrix.toString(&mStr);
+ SkMatrix nearlyEqual;
+ nearlyEqual.setAll(0.7071f, -0.7071f, 0, 0.7071f, 0.7071f, 0, 0, 0, 1);
+ nearlyEqual.toString(&neStr);
+ SkDebugf("mStr %s\n", mStr.c_str());
+ SkDebugf("neStr %s\n", neStr.c_str());
+ SkDebugf("matrix %c= nearlyEqual\n", matrix == nearlyEqual ? '=' : '!');
+#StdOut
+mStr [ 0.7071 -0.7071 0.0000][ 0.7071 0.7071 0.0000][ 0.0000 0.0000 1.0000]
+neStr [ 0.7071 -0.7071 0.0000][ 0.7071 0.7071 0.0000][ 0.0000 0.0000 1.0000]
+matrix != nearlyEqual
+##
##
-#ToDo incomplete ##
+#SeeAlso dump
##
@@ -2203,19 +4136,23 @@ Reads data from the buffer parameter
#Method SkScalar getMinScale() const
-Calculates the minimum scaling factor of the matrix as computed from the
-singular value decomposition of the upper
-left 2x2. If the max scale factor cannot be computed (for example overflow or perspective)
--1 is returned.
+Returns the minimum scaling factor of Matrix by decomposing the scaling and
+skewing elements.
+Returns -1 if scale factor overflows or Matrix contains perspective.
#Return minimum scale factor
##
#Example
-// incomplete
+ SkMatrix matrix;
+ matrix.setScale(42, 24);
+ SkDebugf("matrix.getMinScale() %g\n", matrix.getMinScale());
+#StdOut
+matrix.getMinScale() 24
+##
##
-#ToDo incomplete ##
+#SeeAlso getMaxScale getMinMaxScales
##
@@ -2223,19 +4160,23 @@ left 2x2. If the max scale factor cannot be computed (for example overflow or pe
#Method SkScalar getMaxScale() const
-Calculates the maximum scaling factor of the matrix as computed from the
-singular value decomposition of the upper
-left 2x2. If the max scale factor cannot be computed (for example overflow or perspective)
--1 is returned.
+Returns the maximum scaling factor of Matrix by decomposing the scaling and
+skewing elements.
+Returns -1 if scale factor overflows or Matrix contains perspective.
#Return maximum scale factor
##
#Example
-// incomplete
+ SkMatrix matrix;
+ matrix.setScale(42, 24);
+ SkDebugf("matrix.getMaxScale() %g\n", matrix.getMaxScale());
+#StdOut
+matrix.getMaxScale() 42
+##
##
-#ToDo incomplete ##
+#SeeAlso getMinScale getMinMaxScales
##
@@ -2243,19 +4184,30 @@ left 2x2. If the max scale factor cannot be computed (for example overflow or pe
#Method bool SK_WARN_UNUSED_RESULT getMinMaxScales(SkScalar scaleFactors[2]) 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 Matrix scaling and skewing elements.
+
+Returns true if scaleFactors are found; otherwise, returns false and sets
+scaleFactors to undefined values.
-#Param scaleFactors incomplete ##
+#Param scaleFactors storage for minimum and maximum scale factors ##
-#Return incomplete ##
+#Return true if scale factors were computed correctly ##
#Example
-// incomplete
+ SkMatrix matrix;
+ matrix.setAll(1, 0, 0, 0, 1, 0, 0, 0, 0);
+ matrix.invert(&matrix);
+ SkScalar factor[2] = {2, 2};
+ bool result = matrix.getMinMaxScales(factor);
+ SkDebugf("matrix.getMinMaxScales() %s %g %g\n", result ? "true" : "false", factor[0], factor[1]);
+#StdOut
+matrix.getMinMaxScales() false 2 2
+##
##
-#ToDo incomplete ##
+#SeeAlso getMinScale getMaxScale
##
@@ -2263,25 +4215,52 @@ values of scaleFactors[] are undefined.
#Method bool decomposeScale(SkSize* scale, SkMatrix* remaining = nullptr) const
-Attempt to decompose this matrix into a scale-only component and whatever remains, where
-the scale component is to be applied first.
+Decomposes Matrix into scale components and whatever remains. Returns false if
+Matrix could not be decomposed.
+
+Sets scale to portion of Matrix that scales in x and y. Sets remaining to Matrix
+with x and y scaling factored out. remaining may be passed as nullptr
+to determine if Matrix can be decomposed without computing remainder.
+
+Returns true if scale components are found. scale and remaining are
+unchanged if Matrix contains perspective; scale factors are not finite, or
+are nearly zero.
+
+On success
+
#Formula
-M -> Remaining * Scale
+Matrix = scale * Remaining
##
-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.
-#Param scale incomplete ##
-#Param remaining incomplete ##
+#Param scale x and y scaling factors; may be nullptr ##
+#Param remaining Matrix without scaling; may be nullptr ##
-#Return incomplete ##
+#Return true if scale can be computed ##
#Example
-// incomplete
+ SkMatrix matrix;
+ matrix.setRotate(90 * SK_Scalar1);
+ matrix.postScale(1.f / 4, 1.f / 2);
+ matrix.dump();
+ SkSize scale = {SK_ScalarNaN, SK_ScalarNaN};
+ SkMatrix remaining;
+ remaining.reset();
+ bool success = matrix.decomposeScale(&scale, &remaining);
+ SkDebugf("success: %s ", success ? "true" : "false");
+ SkDebugf("scale: %g, %g\n", scale.width(), scale.height());
+ remaining.dump();
+ SkMatrix scaleMatrix = SkMatrix::MakeScale(scale.width(), scale.height());
+ SkMatrix combined = SkMatrix::Concat(scaleMatrix, remaining);
+ combined.dump();
+#StdOut
+[ 0.0000 -0.2500 0.0000][ 0.5000 0.0000 0.0000][ 0.0000 0.0000 1.0000]
+success: true scale: 0.5, 0.25
+[ 0.0000 -0.5000 0.0000][ 2.0000 0.0000 0.0000][ 0.0000 0.0000 1.0000]
+[ 0.0000 -0.2500 0.0000][ 0.5000 0.0000 0.0000][ 0.0000 0.0000 1.0000]
+##
##
-#ToDo incomplete ##
+#SeeAlso setScale MakeScale
##
@@ -2289,15 +4268,31 @@ Possible reasons to fail: perspective, one or more scale factors are zero.
#Method static const SkMatrix& I()
-Return a reference to a const identity matrix
+Returns reference to const identity Matrix. Returned Matrix is set to:
-#Return incomplete ##
+#Code
+#Literal
+| 1 0 0 |
+| 0 1 0 |
+| 0 0 1 |
+##
+
+#Return const identity Matrix ##
#Example
-// incomplete
+ SkMatrix m1, m2, m3;
+ m1.reset();
+ m2.setIdentity();
+ m3 = SkMatrix::I();
+ SkDebugf("m1 %c= m2\n", m1 == m2 ? '=' : '!');
+ SkDebugf("m2 %c= m3\n", m1 == m2 ? '=' : '!');
+#StdOut
+m1 == m2
+m2 == m3
+##
##
-#ToDo incomplete ##
+#SeeAlso reset() setIdentity
##
@@ -2305,16 +4300,26 @@ Return a reference to a const identity matrix
#Method static const SkMatrix& InvalidMatrix()
-Return a reference to a const matrix that is "invalid", one that could
-never be used.
+Returns reference to a const Matrix with invalid values. Returned Matrix is set
+to:
+
+#Code
+#Literal
+| SK_ScalarMax SK_ScalarMax SK_ScalarMax |
+| SK_ScalarMax SK_ScalarMax SK_ScalarMax |
+| SK_ScalarMax SK_ScalarMax SK_ScalarMax |
+##
-#Return incomplete ##
+#Return const invalid Matrix ##
#Example
-// incomplete
+ SkDebugf("scaleX %g\n", SkMatrix::InvalidMatrix().getScaleX());
+#StdOut
+scaleX 3.40282e+38
+##
##
-#ToDo incomplete ##
+#SeeAlso SeeAlso getType
##
@@ -2322,18 +4327,49 @@ never be used.
#Method static SkMatrix Concat(const SkMatrix& a, const SkMatrix& b)
-Return the concatenation of two matrices, a * b.
+Returns Matrix a multiplied by Matrix b.
+
+Given:
+
+#Code
+#Literal
+ | A B C | | J K L |
+a = | D E F |, b = | M N O |
+ | G H I | | P Q R |
+##
+
+sets Matrix to:
+
+#Code
+#Literal
+ | 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 incomplete ##
-#Param b incomplete ##
+#Param a Matrix on left side of multiply expression ##
+#Param b Matrix on right side of multiply expression ##
-#Return incomplete ##
+#Return Matrix computed from a times b ##
#Example
-// incomplete
+#Height 64
+#Image 4
+#Description
+setPolyToPoly creates perspective matrices, one the inverse of the other.
+Multiplying the matrix by its inverse turns into an identity matrix.
+##
+SkMatrix matrix, matrix2;
+SkPoint bitmapBounds[4], perspect[4] = {{50, 10}, {180, 40}, {236, 176}, {10, 206}};
+SkRect::Make(source.bounds()).toQuad(bitmapBounds);
+matrix.setPolyToPoly(bitmapBounds, perspect, 4);
+matrix2.setPolyToPoly(perspect, bitmapBounds, 4);
+SkMatrix concat = SkMatrix::Concat(matrix, matrix2);
+canvas->concat(concat);
+canvas->drawBitmap(source, 0, 0);
##
-#ToDo incomplete ##
+#SeeAlso preConcat postConcat
##
@@ -2341,14 +4377,29 @@ Return the concatenation of two matrices, a * b.
#Method void dirtyMatrixTypeCache()
-Testing routine; the matrix 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 Matrix element reference returned by operator[](int index).
#Example
-// incomplete
+SkMatrix matrix;
+matrix.setIdentity();
+SkDebugf("with identity matrix: x = %g\n", matrix.mapXY(24, 42).fX);
+SkScalar& skewRef = matrix[SkMatrix::kMSkewX];
+skewRef = 0;
+SkDebugf("after skew x mod: x = %g\n", matrix.mapXY(24, 42).fX);
+skewRef = 1;
+SkDebugf("after 2nd skew x mod: x = %g\n", matrix.mapXY(24, 42).fX);
+matrix.dirtyMatrixTypeCache();
+SkDebugf("after dirty cache: x = %g\n", matrix.mapXY(24, 42).fX);
+#StdOut
+with identity matrix: x = 24
+after skew x mod: x = 24
+after 2nd skew x mod: x = 24
+after dirty cache: x = 66
+##
##
-#ToDo incomplete ##
+#SeeAlso operator[](int index) getType
##
@@ -2356,18 +4407,30 @@ manually invalidated during normal use.
#Method void setScaleTranslate(SkScalar sx, SkScalar sy, SkScalar tx, SkScalar ty)
-Initialize the matrix to be scale + post-translate.
+Initializes Matrix with scale and translate elements.
-#Param sx incomplete ##
-#Param sy incomplete ##
-#Param tx incomplete ##
-#Param ty incomplete ##
+#Code
+#Literal
+| 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 ##
#Example
-// incomplete
+SkMatrix matrix;
+matrix.setScaleTranslate(1, 2, 3, 4);
+matrix.dump();
+#StdOut
+[ 1.0000 0.0000 3.0000][ 0.0000 2.0000 4.0000][ 0.0000 0.0000 1.0000]
+##
##
-#ToDo incomplete ##
+#SeeAlso setScale preTranslate postTranslate
##
@@ -2375,15 +4438,24 @@ Initialize the matrix to be scale + post-translate.
#Method bool isFinite() const
-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 incomplete ##
+#Return true if matrix has only finite elements ##
#Example
-// incomplete
+SkMatrix matrix = SkMatrix::MakeTrans(SK_ScalarNaN, 0);
+matrix.dump();
+SkDebugf("matrix is finite: %s\n", matrix.isFinite() ? "true" : "false");
+SkDebugf("matrix %c= matrix\n", matrix == matrix ? '=' : '!');
+#StdOut
+[ 1.0000 0.0000 nan][ 0.0000 1.0000 0.0000][ 0.0000 0.0000 1.0000]
+matrix is finite: false
+matrix != matrix
+##
##
-#ToDo incomplete ##
+#SeeAlso operator==
##