|  | #Topic Matrix | 
|  | #Alias Matrices ## | 
|  | #Alias Matrix_Reference ## | 
|  |  | 
|  | #Class SkMatrix | 
|  |  | 
|  | #Code | 
|  | #Populate | 
|  | ## | 
|  |  | 
|  | Matrix holds a 3 by 3 matrix for transforming coordinates. This allows mapping | 
|  | Points and Vectors with translation, scaling, skewing, rotation, and | 
|  | perspective. | 
|  |  | 
|  | 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. | 
|  |  | 
|  | Matrix includes a hidden variable that classifies the type of matrix to | 
|  | improve performance. Matrix is not thread safe unless getType is called first. | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method static SkMatrix MakeScale(SkScalar sx, SkScalar sy) | 
|  | #In Constructors | 
|  | #Line # constructs from scale on x-axis and y-axis ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | #Image 4 | 
|  | canvas->concat(SkMatrix::MakeScale(4, 3)); | 
|  | canvas->drawBitmap(source, 0, 0); | 
|  | ## | 
|  |  | 
|  | #SeeAlso setScale postScale preScale | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method static SkMatrix MakeScale(SkScalar scale) | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | #Image 4 | 
|  | canvas->concat(SkMatrix::MakeScale(4)); | 
|  | canvas->drawBitmap(source, 0, 0); | 
|  | ## | 
|  |  | 
|  | #SeeAlso setScale postScale preScale | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method static SkMatrix MakeTrans(SkScalar dx, SkScalar dy) | 
|  | #In Constructors | 
|  | #Line # constructs from translate on x-axis and y-axis ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | #Image 4 | 
|  | SkMatrix matrix = SkMatrix::MakeTrans(64, 48); | 
|  | for (int i = 0; i < 4; ++i) { | 
|  | canvas->drawBitmap(source, 0, 0); | 
|  | canvas->concat(matrix); | 
|  | } | 
|  | ## | 
|  |  | 
|  | #SeeAlso setTranslate postTranslate preTranslate | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method static SkMatrix MakeAll(SkScalar scaleX, SkScalar skewX,  SkScalar transX, | 
|  | SkScalar skewY,  SkScalar scaleY, SkScalar transY, | 
|  | SkScalar pers0, SkScalar pers1, SkScalar pers2) | 
|  | #In Constructors | 
|  | #Line # constructs all nine values ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | SkPaint p; | 
|  | p.setAntiAlias(true); | 
|  | p.setTextSize(64); | 
|  | for (SkScalar sx : { -1, 1 } ) { | 
|  | for (SkScalar sy : { -1, 1 } ) { | 
|  | SkAutoCanvasRestore autoRestore(canvas, true); | 
|  | SkMatrix m = SkMatrix::MakeAll(sx, 1, 128,    0, sy, 128,   0, 0, 1); | 
|  | canvas->concat(m); | 
|  | canvas->drawString("K", 0, 0, p); | 
|  | } | 
|  | } | 
|  | ## | 
|  |  | 
|  | #SeeAlso setAll set9 postConcat preConcat | 
|  |  | 
|  | ## | 
|  |  | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Enum TypeMask | 
|  | #Line # bit field for Matrix complexity ## | 
|  | #Code | 
|  | #Populate | 
|  | ## | 
|  |  | 
|  | Enumeration of bit fields for mask returned by getType. | 
|  | Used to identify the complexity of Matrix, to optimize performance. | 
|  |  | 
|  | #Const kIdentity_Mask 0 | 
|  | #Line # identity Matrix; all bits clear ## | 
|  | all bits clear if Matrix is identity | 
|  | ## | 
|  | #Const kTranslate_Mask 1 | 
|  | #Line # translation Matrix ## | 
|  | set if Matrix has translation | 
|  | ## | 
|  | #Const kScale_Mask 2 | 
|  | #Line # scale Matrix ## | 
|  | set if Matrix scales x-axis or y-axis | 
|  | ## | 
|  | #Const kAffine_Mask 4 | 
|  | #Line # skew or rotate Matrix ## | 
|  | set if Matrix skews or rotates | 
|  | ## | 
|  | #Const kPerspective_Mask 8 | 
|  | #Line # perspective Matrix ## | 
|  | set if Matrix has perspective | 
|  | ## | 
|  |  | 
|  | #Example | 
|  | 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 | 
|  | ## | 
|  | ## | 
|  |  | 
|  | #SeeAlso getType | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  | #Subtopic Property | 
|  | #Line # values and attributes ## | 
|  | ## | 
|  |  | 
|  | #Method TypeMask getType() const | 
|  | #In Property | 
|  | #Line # returns transform complexity ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | 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 | 
|  | ## | 
|  | ## | 
|  |  | 
|  | #SeeAlso TypeMask | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method bool isIdentity() const | 
|  | #In Property | 
|  | #Line # returns if matrix equals the identity Matrix  ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | 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 | 
|  | ## | 
|  | ## | 
|  |  | 
|  | #SeeAlso reset() setIdentity getType | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method bool isScaleTranslate() const | 
|  | #In Property | 
|  | #Line # returns if transform is limited to scale and translate ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | 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 | 
|  | ## | 
|  | ## | 
|  |  | 
|  | #SeeAlso setScale isTranslate setTranslate getType | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method bool isTranslate() const | 
|  | #In Property | 
|  | #Line # returns if transform is limited to translate ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | 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 | 
|  | ## | 
|  | ## | 
|  |  | 
|  | #SeeAlso setTranslate getType | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method bool rectStaysRect() const | 
|  | #In Property | 
|  | #Line # returns if mapped Rect can be represented by another Rect ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | 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 | 
|  | ## | 
|  | ## | 
|  |  | 
|  | #SeeAlso preservesAxisAlignment preservesRightAngles | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method bool preservesAxisAlignment() const | 
|  | #In Property | 
|  | #Line # returns if mapping restricts to 90 degree multiples and mirroring ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | 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 | 
|  | ## | 
|  | ## | 
|  |  | 
|  | #SeeAlso rectStaysRect preservesRightAngles | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method bool hasPerspective() const | 
|  | #In Property | 
|  | #Line # returns if transform includes perspective ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | #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); | 
|  | ## | 
|  |  | 
|  | #SeeAlso setAll set9 MakeAll | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method bool isSimilarity(SkScalar tol = SK_ScalarNearlyZero) const | 
|  | #In Property | 
|  | #Line # returns if transform is limited to square scale and rotation ## | 
|  | #Populate | 
|  |  | 
|  | #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 | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method bool preservesRightAngles(SkScalar tol = SK_ScalarNearlyZero) const | 
|  | #In Property | 
|  | #Line # returns if mapped 90 angle remains 90 degrees ## | 
|  | #Populate | 
|  |  | 
|  | #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 | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Subtopic MemberIndex | 
|  | #In Constant | 
|  | #Line # member indices ## | 
|  | #Filter kM | 
|  | #Code | 
|  | #Populate | 
|  | ## | 
|  |  | 
|  | Matrix organizes its values in row order. These members correspond to | 
|  | each value in Matrix. | 
|  |  | 
|  | #Const kMScaleX 0 | 
|  | #Line # horizontal scale factor ## | 
|  | ## | 
|  | #Const kMSkewX 1 | 
|  | #Line # horizontal skew factor ## | 
|  | ## | 
|  | #Const kMTransX 2 | 
|  | #Line # horizontal translation ## | 
|  | ## | 
|  | #Const kMSkewY 3 | 
|  | #Line # vertical skew factor ## | 
|  | ## | 
|  | #Const kMScaleY 4 | 
|  | #Line # vertical scale factor ## | 
|  | ## | 
|  | #Const kMTransY 5 | 
|  | #Line # vertical translation ## | 
|  | ## | 
|  | #Const kMPersp0 6 | 
|  | #Line # input x perspective factor ## | 
|  | ## | 
|  | #Const kMPersp1 7 | 
|  | #Line # input y perspective factor ## | 
|  | ## | 
|  | #Const kMPersp2 8 | 
|  | #Line # perspective bias ## | 
|  | ## | 
|  |  | 
|  | #Example | 
|  | 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() | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Subtopic AffineIndex | 
|  | #In Constant | 
|  | #Line # affine member indices ## | 
|  | #Filter KA | 
|  |  | 
|  | #Code | 
|  | #Populate | 
|  | ## | 
|  |  | 
|  | Affine arrays are in column major order to match the matrix used by | 
|  | PDF and XPS. | 
|  |  | 
|  | #Const kAScaleX 0 | 
|  | #Line # horizontal scale factor ## | 
|  | ## | 
|  | #Const kASkewY 1 | 
|  | #Line # vertical skew factor ## | 
|  | ## | 
|  | #Const kASkewX 2 | 
|  | #Line # horizontal skew factor ## | 
|  | ## | 
|  | #Const kAScaleY 3 | 
|  | #Line # vertical scale factor ## | 
|  | ## | 
|  | #Const kATransX 4 | 
|  | #Line # horizontal translation ## | 
|  | ## | 
|  | #Const kATransY 5 | 
|  | #Line # vertical translation ## | 
|  | ## | 
|  |  | 
|  | #NoExample | 
|  | ## | 
|  |  | 
|  | #SeeAlso SetAffineIdentity asAffine setAffine | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method SkScalar operator[](int index) const | 
|  |  | 
|  | #Line # returns Matrix value ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | 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 | 
|  | ## | 
|  | ## | 
|  |  | 
|  | #SeeAlso get set | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method SkScalar get(int index) const | 
|  | #In Property | 
|  | #Line # returns one of nine Matrix values ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | 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 | 
|  | ## | 
|  | ## | 
|  |  | 
|  | #SeeAlso operator[](int index) set | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method SkScalar getScaleX() const | 
|  | #In Property | 
|  | #Line # returns horizontal scale factor ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | SkMatrix matrix; | 
|  | matrix.setScale(42, 24); | 
|  | SkDebugf("matrix.getScaleX() %c= 42\n", matrix.getScaleX() == 42 ? '=' : '!'); | 
|  | #StdOut | 
|  | matrix.getScaleX() == 42 | 
|  | ## | 
|  | ## | 
|  |  | 
|  | #SeeAlso get getScaleY setScaleX setScale | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method SkScalar getScaleY() const | 
|  | #In Property | 
|  | #Line # returns vertical scale factor ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | SkMatrix matrix; | 
|  | matrix.setScale(42, 24); | 
|  | SkDebugf("matrix.getScaleY() %c= 24\n", matrix.getScaleY() == 24 ? '=' : '!'); | 
|  | #StdOut | 
|  | matrix.getScaleY() == 24 | 
|  | ## | 
|  | ## | 
|  |  | 
|  | #SeeAlso get getScaleX setScaleY setScale | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method SkScalar getSkewY() const | 
|  | #In Property | 
|  | #Line # returns vertical skew factor ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | SkMatrix matrix; | 
|  | matrix.setSkew(42, 24); | 
|  | SkDebugf("matrix.getSkewY() %c= 24\n", matrix.getSkewY() == 24 ? '=' : '!'); | 
|  | #StdOut | 
|  | matrix.getSkewY() == 24 | 
|  | ## | 
|  | ## | 
|  |  | 
|  | #SeeAlso get getSkewX setSkewY setSkew | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method SkScalar getSkewX() const | 
|  | #In Property | 
|  | #Line # returns horizontal skew factor ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | SkMatrix matrix; | 
|  | matrix.setSkew(42, 24); | 
|  | SkDebugf("matrix.getSkewX() %c= 42\n", matrix.getSkewX() == 42 ? '=' : '!'); | 
|  | #StdOut | 
|  | matrix.getSkewX() == 42 | 
|  | ## | 
|  | ## | 
|  |  | 
|  | #SeeAlso get getSkewY setSkewX setSkew | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method SkScalar getTranslateX() const | 
|  | #In Property | 
|  | #Line # returns horizontal translation ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | SkMatrix matrix; | 
|  | matrix.setTranslate(42, 24); | 
|  | SkDebugf("matrix.getTranslateX() %c= 42\n", matrix.getTranslateX() == 42 ? '=' : '!'); | 
|  | #StdOut | 
|  | matrix.getTranslateX() == 42 | 
|  | ## | 
|  | ## | 
|  |  | 
|  | #SeeAlso get getTranslateY setTranslateX setTranslate | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method SkScalar getTranslateY() const | 
|  | #In Property | 
|  | #Line # returns vertical translation ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | SkMatrix matrix; | 
|  | matrix.setTranslate(42, 24); | 
|  | SkDebugf("matrix.getTranslateY() %c= 24\n", matrix.getTranslateY() == 24 ? '=' : '!'); | 
|  | #StdOut | 
|  | matrix.getTranslateY() == 24 | 
|  | ## | 
|  | ## | 
|  |  | 
|  | #SeeAlso get getTranslateX setTranslateY setTranslate | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method SkScalar getPerspX() const | 
|  | #In Property | 
|  | #Line # returns input x perspective factor ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | 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); | 
|  | ## | 
|  |  | 
|  | #SeeAlso kMPersp0 getPerspY | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method SkScalar getPerspY() const | 
|  | #In Property | 
|  | #Line # returns input y perspective factor ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | 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); | 
|  | ## | 
|  |  | 
|  | #SeeAlso kMPersp1 getPerspX | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method SkScalar& operator[](int index) | 
|  |  | 
|  | #Line # returns writable reference to Matrix value ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | 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 | 
|  | ## | 
|  | ## | 
|  |  | 
|  | #SeeAlso get dirtyMatrixTypeCache set | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  | #Subtopic Set | 
|  | #Line # sets one or more matrix values ## | 
|  | ## | 
|  |  | 
|  | #Method void set(int index, SkScalar value) | 
|  | #In Set | 
|  | #Line # sets one value ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | 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 | 
|  | ## | 
|  | ## | 
|  |  | 
|  | #SeeAlso operator[] get | 
|  |  | 
|  | #Method ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method void setScaleX(SkScalar v) | 
|  | #In Set | 
|  | #Line # sets horizontal scale factor ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | #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); | 
|  | ## | 
|  |  | 
|  | #SeeAlso set setScale setScaleY | 
|  |  | 
|  | #Method ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method void setScaleY(SkScalar v) | 
|  | #In Set | 
|  | #Line # sets vertical scale factor ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | #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); | 
|  | ## | 
|  |  | 
|  | #SeeAlso set setScale setScaleX | 
|  |  | 
|  | #Method ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method void setSkewY(SkScalar v) | 
|  | #In Set | 
|  | #Line # sets vertical skew factor ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | #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); | 
|  | ## | 
|  |  | 
|  | #SeeAlso set setSkew setSkewX | 
|  |  | 
|  | #Method ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method void setSkewX(SkScalar v) | 
|  | #In Set | 
|  | #Line # sets horizontal skew factor ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | #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); | 
|  | ## | 
|  |  | 
|  | #SeeAlso set setSkew setSkewX | 
|  |  | 
|  | #Method ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method void setTranslateX(SkScalar v) | 
|  | #In Set | 
|  | #Line # sets horizontal translation ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | #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); | 
|  | ## | 
|  |  | 
|  | #SeeAlso set setTranslate setTranslateY | 
|  |  | 
|  | #Method ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method void setTranslateY(SkScalar v) | 
|  | #In Set | 
|  | #Line # sets vertical translation ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | #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); | 
|  | ## | 
|  |  | 
|  | #SeeAlso set setTranslate setTranslateX | 
|  |  | 
|  | #Method ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method void setPerspX(SkScalar v) | 
|  | #In Set | 
|  | #Line # sets input x perspective factor ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | #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); | 
|  | } | 
|  | ## | 
|  |  | 
|  | #SeeAlso getPerspX set setAll set9 MakeAll | 
|  |  | 
|  | #Method ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method void setPerspY(SkScalar v) | 
|  | #In Set | 
|  | #Line # sets input y perspective factor ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | #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); | 
|  | } | 
|  | ## | 
|  |  | 
|  | #SeeAlso getPerspY set setAll set9 MakeAll | 
|  |  | 
|  | #Method ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method void setAll(SkScalar scaleX, SkScalar skewX,  SkScalar transX, | 
|  | SkScalar skewY,  SkScalar scaleY, SkScalar transY, | 
|  | SkScalar persp0, SkScalar persp1, SkScalar persp2) | 
|  | #In Set | 
|  | #Line # sets all values from parameters ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | #Height 128 | 
|  | 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, 64,   0, 0, 1); | 
|  | canvas->concat(m); | 
|  | canvas->drawString("K", 0, 0, p); | 
|  | } | 
|  | } | 
|  | ## | 
|  |  | 
|  | #SeeAlso set9 MakeAll | 
|  |  | 
|  | #Method ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method void get9(SkScalar buffer[9]) const | 
|  | #In Property | 
|  | #Line # returns all nine Matrix values ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | 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} | 
|  | ## | 
|  | ## | 
|  |  | 
|  | #SeeAlso set9 | 
|  |  | 
|  | #Method ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method void set9(const SkScalar buffer[9]) | 
|  | #In Set | 
|  | #In Constructors | 
|  | #Line # sets all values from Scalar array ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | #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); | 
|  | ## | 
|  |  | 
|  | #SeeAlso setAll get9 MakeAll | 
|  |  | 
|  | #Method ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method void reset() | 
|  | #In Constructors | 
|  | #In Set | 
|  | #Line # sets Matrix to identity ## | 
|  | #Populate | 
|  |  | 
|  | #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() | 
|  | #In Constructors | 
|  | #In Set | 
|  | #Line # sets Matrix to identity ## | 
|  | #Populate | 
|  |  | 
|  | #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) | 
|  | #In Constructors | 
|  | #In Set | 
|  | #Line # sets to translate on x-axis and y-axis ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | #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); | 
|  | ## | 
|  |  | 
|  | #SeeAlso setTranslateX setTranslateY | 
|  |  | 
|  | #Method ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method void setTranslate(const SkVector& v) | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | #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); | 
|  | ## | 
|  |  | 
|  | #SeeAlso setTranslateX setTranslateY MakeTrans | 
|  |  | 
|  | #Method ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method void setScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) | 
|  | #In Constructors | 
|  | #In Set | 
|  | #Line # sets to scale about a point ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | #Height 128 | 
|  | 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, 64); | 
|  | canvas->concat(m); | 
|  | canvas->drawString("%", 128, 64, p); | 
|  | } | 
|  | } | 
|  | ## | 
|  |  | 
|  | #SeeAlso setScaleX setScaleY MakeScale preScale postScale | 
|  |  | 
|  | #Method ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method void setScale(SkScalar sx, SkScalar sy) | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | #Height 128 | 
|  | 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, 64); | 
|  | canvas->concat(m); | 
|  | canvas->drawString("@", 0, 0, p); | 
|  | } | 
|  | } | 
|  | ## | 
|  |  | 
|  | #SeeAlso setScaleX setScaleY MakeScale preScale postScale | 
|  |  | 
|  | #Method ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method void setRotate(SkScalar degrees, SkScalar px, SkScalar py) | 
|  | #In Constructors | 
|  | #In Set | 
|  | #Line # sets to rotate about a point ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | #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); | 
|  | ## | 
|  |  | 
|  | #SeeAlso setSinCos preRotate postRotate | 
|  |  | 
|  | #Method ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method void setRotate(SkScalar degrees) | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | #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); | 
|  | ## | 
|  |  | 
|  | #SeeAlso setSinCos preRotate postRotate | 
|  |  | 
|  | #Method ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method void setSinCos(SkScalar sinValue, SkScalar cosValue, | 
|  | SkScalar px, SkScalar py) | 
|  | #In Constructors | 
|  | #In Set | 
|  | #Line # sets to rotate and scale about a point ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | #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); | 
|  | ## | 
|  |  | 
|  | #SeeAlso setRotate setScale setRSXform | 
|  |  | 
|  | #Method ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method void setSinCos(SkScalar sinValue, SkScalar cosValue) | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | #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); | 
|  | ## | 
|  |  | 
|  | #SeeAlso setRotate setScale setRSXform | 
|  |  | 
|  | #Method ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method SkMatrix& setRSXform(const SkRSXform& rsxForm) | 
|  | #In Constructors | 
|  | #In Set | 
|  | #Line # sets to rotate, scale, and translate ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | #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); | 
|  | ## | 
|  |  | 
|  | #SeeAlso setSinCos setScale setTranslate | 
|  |  | 
|  | #Method ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method void setSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py) | 
|  | #In Constructors | 
|  | #In Set | 
|  | #Line # sets to skew about a point ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | 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); | 
|  | } | 
|  | } | 
|  | ## | 
|  |  | 
|  | #SeeAlso setSkewX setSkewY preSkew postSkew | 
|  |  | 
|  | #Method ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method void setSkew(SkScalar kx, SkScalar ky) | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | 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); | 
|  | } | 
|  | } | 
|  | ## | 
|  |  | 
|  | #SeeAlso setSkewX setSkewY preSkew postSkew | 
|  |  | 
|  | #Method ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method void setConcat(const SkMatrix& a, const SkMatrix& b) | 
|  | #In Constructors | 
|  | #In Set | 
|  | #Line # sets to Matrix parameter multiplied by Matrix parameter ## | 
|  | #Populate | 
|  |  | 
|  | #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) | 
|  | #In Set | 
|  | #In Operators | 
|  | #Line # pre-multiplies Matrix by translation ## | 
|  | #Populate | 
|  |  | 
|  | #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) | 
|  | #In Set | 
|  | #In Operators | 
|  | #Line # pre-multiplies Matrix by scale ## | 
|  | #Populate | 
|  |  | 
|  | #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) | 
|  | #In Set | 
|  | #In Operators | 
|  | #Populate | 
|  |  | 
|  | #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) | 
|  | #In Set | 
|  | #In Operators | 
|  | #Line # pre-multiplies Matrix by rotation ## | 
|  | #Populate | 
|  |  | 
|  | #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) | 
|  | #Populate | 
|  |  | 
|  | #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) | 
|  | #In Set | 
|  | #In Operators | 
|  | #Line # pre-multiplies Matrix by skew ## | 
|  | #Populate | 
|  |  | 
|  | #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) | 
|  | #Populate | 
|  |  | 
|  | #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) | 
|  | #In Set | 
|  | #In Operators | 
|  | #Line # pre-multiplies Matrix by Matrix parameter ## | 
|  | #Populate | 
|  |  | 
|  | #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) | 
|  | #In Set | 
|  | #In Operators | 
|  | #Line # post-multiplies Matrix by translation ## | 
|  | #Populate | 
|  |  | 
|  | #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) | 
|  | #In Set | 
|  | #In Operators | 
|  | #Line # post-multiplies Matrix by scale ## | 
|  | #Populate | 
|  |  | 
|  | #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.postScale(.75f, 1.5f, source.width() / 2, source.height() / 2); | 
|  | canvas->concat(matrix); | 
|  | canvas->drawBitmap(source, 0, 0); | 
|  | ## | 
|  |  | 
|  | #SeeAlso preScale setScale MakeScale | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method void postScale(SkScalar sx, SkScalar sy) | 
|  | #Populate | 
|  |  | 
|  | #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.postScale(.75f, 1.5f); | 
|  | canvas->concat(matrix); | 
|  | canvas->drawBitmap(source, 0, 0); | 
|  | ## | 
|  |  | 
|  | #SeeAlso preScale setScale MakeScale | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method bool postIDiv(int divx, int divy) | 
|  | #In Set | 
|  | #In Operators | 
|  | #Line # post-multiplies Matrix by inverse scale ## | 
|  | Sets Matrix to Matrix constructed from scaling by (1/divx, 1/divy), | 
|  | multiplied by Matrix. | 
|  |  | 
|  | Returns false if either divx or divy is zero. | 
|  |  | 
|  | 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 on x-axis ## | 
|  | #Param divy  integer divisor for inverse scale on y-axis ## | 
|  |  | 
|  | #Return  true on successful scale ## | 
|  |  | 
|  | #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.postIDiv(1, 2); | 
|  | canvas->concat(matrix); | 
|  | canvas->drawBitmap(source, 0, 0); | 
|  | ## | 
|  |  | 
|  | #SeeAlso postScale MakeScale | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method void postRotate(SkScalar degrees, SkScalar px, SkScalar py) | 
|  | #In Set | 
|  | #In Operators | 
|  | #Line # post-multiplies Matrix by rotation ## | 
|  | #Populate | 
|  |  | 
|  | #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.postRotate(45, source.width() / 2, source.height() / 2); | 
|  | canvas->concat(matrix); | 
|  | canvas->drawBitmap(source, 0, 0); | 
|  | ## | 
|  |  | 
|  | #SeeAlso preRotate setRotate | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method void postRotate(SkScalar degrees) | 
|  | #Populate | 
|  |  | 
|  | #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.postRotate(45); | 
|  | canvas->concat(matrix); | 
|  | canvas->drawBitmap(source, 0, 0); | 
|  | ## | 
|  |  | 
|  | #SeeAlso preRotate setRotate | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method void postSkew(SkScalar kx, SkScalar ky, SkScalar px, SkScalar py) | 
|  | #In Set | 
|  | #In Operators | 
|  | #Line # post-multiplies Matrix by skew ## | 
|  | #Populate | 
|  |  | 
|  | #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.postSkew(.5f, 0, source.width() / 2, source.height() / 2); | 
|  | canvas->concat(matrix); | 
|  | canvas->drawBitmap(source, 0, 0); | 
|  | ## | 
|  |  | 
|  | #SeeAlso preSkew setSkew | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method void postSkew(SkScalar kx, SkScalar ky) | 
|  | #Populate | 
|  |  | 
|  | #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.postSkew(.5f, 0); | 
|  | canvas->concat(matrix); | 
|  | canvas->drawBitmap(source, 0, 0); | 
|  | ## | 
|  |  | 
|  | #SeeAlso preSkew setSkew | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method void postConcat(const SkMatrix& other) | 
|  | #In Set | 
|  | #In Operators | 
|  | #Line # post-multiplies Matrix by Matrix parameter ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | #Image 3 | 
|  | #Height 64 | 
|  | 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.postConcat(matrix); | 
|  | canvas->concat(matrix); | 
|  | canvas->drawBitmap(source, 0, 0); | 
|  | ## | 
|  |  | 
|  | #SeeAlso preConcat setConcat Concat | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Enum ScaleToFit | 
|  | #Line # options to map Rects ## | 
|  | #Code | 
|  | enum ScaleToFit { | 
|  | kFill_ScaleToFit, | 
|  | kStart_ScaleToFit, | 
|  | kCenter_ScaleToFit, | 
|  | kEnd_ScaleToFit, | 
|  | }; | 
|  | ## | 
|  |  | 
|  | 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 | 
|  | #Line # scales about x-axis and y-axis to fill destination Rect ## | 
|  | Computes Matrix that scales about x-axis and y-axis independently, so that | 
|  | source Rect is mapped to completely fill destination Rect. The aspect ratio | 
|  | of source Rect may change. | 
|  | ## | 
|  | #Const kStart_ScaleToFit 1 | 
|  | #Line # scales and aligns to left and top ## | 
|  | 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 2 | 
|  | #Line # scales and aligns to center ## | 
|  | 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 3 | 
|  | #Line # scales and aligns to right and bottom ## | 
|  | 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 | 
|  | 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 | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method bool setRectToRect(const SkRect& src, const SkRect& dst, ScaleToFit stf) | 
|  | #In Set | 
|  | #Line # sets to map one Rect to another ## | 
|  | #Populate | 
|  |  | 
|  | #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 | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method static SkMatrix MakeRectToRect(const SkRect& src, const SkRect& dst, ScaleToFit stf) | 
|  | #In Constructors | 
|  | #Line # constructs from source Rect to destination Rect ## | 
|  | #Populate | 
|  |  | 
|  | #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 = 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] | 
|  | ## | 
|  | ## | 
|  |  | 
|  | #SeeAlso setRectToRect ScaleToFit setPolyToPoly SkRect::isEmpty | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method bool setPolyToPoly(const SkPoint src[], const SkPoint dst[], int count) | 
|  | #In Set | 
|  | #Line # sets to map one to four points to an equal array of points ## | 
|  | #Populate | 
|  |  | 
|  | #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 | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method bool invert(SkMatrix* inverse) const | 
|  | #In Operators | 
|  | #Line # returns inverse, if possible ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | #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); | 
|  | if (matrix.invert(&matrix)) { | 
|  | canvas->concat(matrix); | 
|  | canvas->drawPoints(SkCanvas::kPoints_PointMode, 4, dst, paint); | 
|  | } | 
|  | ## | 
|  |  | 
|  | #SeeAlso Concat | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method static void SetAffineIdentity(SkScalar affine[6]) | 
|  | #In Constructors | 
|  | #Line # sets 3x2 array to identity ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | 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 | 
|  | ## | 
|  | ## | 
|  |  | 
|  | #SeeAlso setAffine asAffine | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method bool asAffine(SkScalar affine[6]) const | 
|  | #In Constructors | 
|  | #Line # copies to 3x2 array ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | SkMatrix matrix; | 
|  | matrix.setAll(2, 3, 4, 5, 6, 7, 0, 0, 1); | 
|  | SkScalar affine[6]; | 
|  | if (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 | 
|  | ## | 
|  | ## | 
|  |  | 
|  | #SeeAlso setAffine SetAffineIdentity | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method void setAffine(const SkScalar affine[6]) | 
|  | #In Constructors | 
|  | #In Set | 
|  | #Line # sets left two columns ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | SkMatrix matrix; | 
|  | matrix.setAll(2, 3, 4, 5, 6, 7, 0, 0, 1); | 
|  | SkScalar affine[6]; | 
|  | if (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] | 
|  | ## | 
|  | ## | 
|  |  | 
|  | #SeeAlso asAffine SetAffineIdentity | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  | #Subtopic Transform | 
|  | #Line # map points with Matrix ## | 
|  | ## | 
|  |  | 
|  | #Method void mapPoints(SkPoint dst[], const SkPoint src[], int count) const | 
|  | #In Transform | 
|  | #Line # maps Point array ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | 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); | 
|  | } | 
|  | ## | 
|  |  | 
|  | #SeeAlso mapXY mapHomogeneousPoints mapVectors | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method void mapPoints(SkPoint pts[], int count) const | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | 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); | 
|  | } | 
|  | ## | 
|  |  | 
|  | #SeeAlso mapXY mapHomogeneousPoints mapVectors | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method void mapHomogeneousPoints(SkPoint3 dst[], const SkPoint3 src[], int count) const | 
|  | #In Transform | 
|  | #Line # maps Point3 array ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | 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, src, count); | 
|  | debugster(src); | 
|  | ## | 
|  |  | 
|  | #SeeAlso mapPoints mapXY mapVectors | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method void mapXY(SkScalar x, SkScalar y, SkPoint* result) const | 
|  | #In Transform | 
|  | #Line # maps Point ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | 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); | 
|  | ## | 
|  |  | 
|  | #SeeAlso mapPoints mapVectors | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method SkPoint mapXY(SkScalar x, SkScalar y) const | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | #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); | 
|  | ## | 
|  |  | 
|  | #SeeAlso mapPoints mapVectors | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method void mapVectors(SkVector dst[], const SkVector src[], int count) const | 
|  | #In Transform | 
|  | #Line # maps Vector array ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | 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); | 
|  | } | 
|  | ## | 
|  |  | 
|  | #SeeAlso mapVector mapPoints mapXY | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method void mapVectors(SkVector vecs[], int count) const | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | 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)); | 
|  | } | 
|  | ## | 
|  |  | 
|  | #SeeAlso mapVector mapPoints mapXY | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method void mapVector(SkScalar dx, SkScalar dy, SkVector* result) const | 
|  | #In Transform | 
|  | #Line # maps Vector ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | 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); | 
|  | } | 
|  | ## | 
|  |  | 
|  | #SeeAlso mapVectors mapPoints mapXY | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method SkVector mapVector(SkScalar dx, SkScalar dy) const | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | 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); | 
|  | } | 
|  | ## | 
|  |  | 
|  | #SeeAlso mapVectors mapPoints mapXY | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method bool mapRect(SkRect* dst, const SkRect& src) const | 
|  | #In Transform | 
|  | #Line # returns bounds of mapped Rect ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | 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); | 
|  | ## | 
|  |  | 
|  | #SeeAlso mapPoints rectStaysRect | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method bool mapRect(SkRect* rect) const | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | 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); | 
|  | ## | 
|  |  | 
|  | #SeeAlso mapRectScaleTranslate mapPoints rectStaysRect | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method SkRect mapRect(const SkRect& src) const | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | SkRect rect{110, 50, 180, 100}; | 
|  | SkMatrix matrix; | 
|  | matrix.setRotate(50, 28, 28); | 
|  | SkRect mapped = matrix.mapRect(rect); | 
|  | SkPaint paint; | 
|  | paint.setAntiAlias(true); | 
|  | paint.setStyle(SkPaint::kStroke_Style); | 
|  | canvas->drawRect(rect, paint); | 
|  | canvas->drawRect(mapped, paint); | 
|  | canvas->concat(matrix); | 
|  | canvas->drawRect(rect, paint); | 
|  | ## | 
|  |  | 
|  | #SeeAlso mapRectToQuad mapRectScaleTranslate | 
|  | #Method ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method void mapRectToQuad(SkPoint dst[4], const SkRect& rect) const | 
|  | #In Transform | 
|  | #Line # maps Rect to Point array ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | #Height 192 | 
|  | 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); | 
|  | ## | 
|  |  | 
|  | #SeeAlso mapRect mapRectScaleTranslate | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method void mapRectScaleTranslate(SkRect* dst, const SkRect& src) const | 
|  | #In Transform | 
|  | #Line # returns bounds of mapped Rect ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | 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); | 
|  | ## | 
|  |  | 
|  | #SeeAlso mapRect mapRectToQuad isScaleTranslate rectStaysRect | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method SkScalar mapRadius(SkScalar radius) const | 
|  | #In Transform | 
|  | #Line # returns mean radius of mapped Circle ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | #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 isFixedStepInX() const | 
|  | #In Property | 
|  | #Line # returns if transformation supports fixed step on x-axis ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | 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 SkVector fixedStepInX(SkScalar y) const | 
|  | #In Property | 
|  | #Line # returns step on x-axis for a position on y-axis ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | #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 bool cheapEqualTo(const SkMatrix& m) const | 
|  | #In Operators | 
|  | #Line # compares Matrix pair using memcmp() ## | 
|  | #Populate | 
|  |  | 
|  | #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 | 
|  | ## | 
|  | ## | 
|  |  | 
|  | #SeeAlso operator==(const SkMatrix& a, const SkMatrix& b) | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method bool operator==(const SkMatrix& a, const SkMatrix& b) | 
|  |  | 
|  | #Line # returns true if members are equal ## | 
|  | #Populate | 
|  |  | 
|  | #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.setScale(2, 4); | 
|  | b.postScale(0.5f, 0.25f); | 
|  | debugster("identity", a, b); | 
|  | #StdOut | 
|  | identity: a == b a.cheapEqualTo(b): true | 
|  | ## | 
|  | ## | 
|  |  | 
|  | #SeeAlso  cheapEqualTo operator!=(const SkMatrix& a, const SkMatrix& b) | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method bool operator!=(const SkMatrix& a, const SkMatrix& b) | 
|  |  | 
|  | #Line # returns true if members are unequal ## | 
|  | #Populate | 
|  |  | 
|  | #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,  1, 0, 1); | 
|  | if (a.invert(&b)) { | 
|  | debugster("identity", a, b); | 
|  | } | 
|  | ## | 
|  |  | 
|  | #SeeAlso cheapEqualTo operator==(const SkMatrix& a, const SkMatrix& b) | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  | #Subtopic Utility | 
|  | #Line # rarely called management functions ## | 
|  | ## | 
|  |  | 
|  | #Method void dump() const | 
|  | #In Utility | 
|  | #Line # sends text representation using floats to standard output ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | 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 | 
|  | ## | 
|  | ## | 
|  |  | 
|  | #SeeAlso SkPath::dump | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method SkScalar getMinScale() const | 
|  | #In Property | 
|  | #Line # returns minimum scaling, if possible ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | SkMatrix matrix; | 
|  | matrix.setScale(42, 24); | 
|  | SkDebugf("matrix.getMinScale() %g\n", matrix.getMinScale()); | 
|  | #StdOut | 
|  | matrix.getMinScale() 24 | 
|  | ## | 
|  | ## | 
|  |  | 
|  | #SeeAlso getMaxScale getMinMaxScales | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method SkScalar getMaxScale() const | 
|  | #In Property | 
|  | #Line # returns maximum scaling, if possible ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | SkMatrix matrix; | 
|  | matrix.setScale(42, 24); | 
|  | SkDebugf("matrix.getMaxScale() %g\n", matrix.getMaxScale()); | 
|  | #StdOut | 
|  | matrix.getMaxScale() 42 | 
|  | ## | 
|  | ## | 
|  |  | 
|  | #SeeAlso getMinScale getMinMaxScales | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method bool getMinMaxScales(SkScalar scaleFactors[2]) const | 
|  | #In Property | 
|  | #Line # returns minimum and maximum scaling, if possible ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | SkMatrix matrix; | 
|  | matrix.setAll(1, 0, 0,  0, 1, 0,   0, 0, 0); | 
|  | if (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 | 
|  | ## | 
|  | ## | 
|  |  | 
|  | #SeeAlso getMinScale getMaxScale | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method bool decomposeScale(SkSize* scale, SkMatrix* remaining = nullptr) const | 
|  | #In Property | 
|  | #Line # separates scale if possible ## | 
|  | Decomposes Matrix into scale components and whatever remains. Returns false if | 
|  | Matrix could not be decomposed. | 
|  |  | 
|  | Sets scale to portion of Matrix that scale axes. Sets remaining to Matrix | 
|  | with 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 # Matrix = scale * Remaining ##. | 
|  |  | 
|  | #Param scale  axes scaling factors; may be nullptr ## | 
|  | #Param remaining  Matrix without scaling; may be nullptr ## | 
|  |  | 
|  | #Return  true if scale can be computed ## | 
|  |  | 
|  | #Example | 
|  | 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] | 
|  | ## | 
|  | ## | 
|  |  | 
|  | #SeeAlso setScale MakeScale | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method static const SkMatrix& I() | 
|  | #In Constructors | 
|  | #Line # returns a reference to a const identity Matrix ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | 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 | 
|  | ## | 
|  | ## | 
|  |  | 
|  | #SeeAlso reset() setIdentity | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method static const SkMatrix& InvalidMatrix() | 
|  | #In Constructors | 
|  | #Line # returns a reference to a const invalid Matrix ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | SkDebugf("scaleX %g\n", SkMatrix::InvalidMatrix().getScaleX()); | 
|  | #StdOut | 
|  | scaleX 3.40282e+38 | 
|  | ## | 
|  | ## | 
|  |  | 
|  | #SeeAlso getType | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method static SkMatrix Concat(const SkMatrix& a, const SkMatrix& b) | 
|  | #In Operators | 
|  | #Line # returns the concatenation of Matrix pair ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | #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); | 
|  | ## | 
|  |  | 
|  | #SeeAlso preConcat postConcat | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method void dirtyMatrixTypeCache() | 
|  | #In Utility | 
|  | #Line # sets internal cache to unknown state ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | 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 | 
|  | ## | 
|  | ## | 
|  |  | 
|  | #SeeAlso operator[](int index) getType | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method void setScaleTranslate(SkScalar sx, SkScalar sy, SkScalar tx, SkScalar ty) | 
|  | #In Constructors | 
|  | #In Set | 
|  | #Line # sets to scale and translate ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | 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] | 
|  | ## | 
|  | ## | 
|  |  | 
|  | #SeeAlso setScale preTranslate postTranslate | 
|  |  | 
|  | ## | 
|  |  | 
|  | # ------------------------------------------------------------------------------ | 
|  |  | 
|  | #Method bool isFinite() const | 
|  | #In Property | 
|  | #Line # returns if all Matrix values are not infinity, NaN ## | 
|  | #Populate | 
|  |  | 
|  | #Example | 
|  | 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 | 
|  | ## | 
|  | ## | 
|  |  | 
|  | #SeeAlso operator== | 
|  |  | 
|  | ## | 
|  |  | 
|  | #Class SkMatrix ## | 
|  |  | 
|  | #Topic Matrix ## |