blob: f624c5a87c9e9a1a0d8ad913c16e47559ea4a8f3 [file] [log] [blame]
#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 ##