矩阵的数据结构其实是个一维数组:0、1、2代表第一行,3、4、5代表第二行,6、7、8代表第三行,如下:
[0, 1, 2,
3, 4, 5,
6, 7, 8]
每个位置代表的值:
[scaleX, skewX, translateX, //第一行为x方向的值
skewY, scaleY, translateY, //第二行为y方向的值
perspective0, perspective1, perspective2] //第三行为透视相关值
[横向缩放因子, 横向扭曲因子, 横向位移,
竖向扭曲因子, 竖向缩放因子, 竖向位移,
x轴透视因子, y轴透视因子, 透视因子]
preTranslate 和 postTranslate 的区别不仅仅是右乘和左乘,native层源码如下。
//矩阵的数据结构其实是个一维数组:0、1、2代表第一行,3、4、5代表第二行,6、7、8代表第三行,
//[0, 1, 2,
// 3, 4, 5,
// 6, 7, 8]
//
//[scaleX, skewX, translateX, //第一行为x方向的值
// skewY, scaleY, translateY, //第二行为y方向的值
// perspective0, perspective1, perspective2] //第三行为透视相关值
//
//[横向缩放因子, 横向扭曲因子, 横向位移,
// 竖向扭曲因子, 竖向缩放因子, 竖向位移,
// x轴透视因子, y轴透视因子, 透视因子]
enum {
kMScaleX, //!< horizontal scale factor
kMSkewX, //!< horizontal skew factor
kMTransX, //!< horizontal translation
kMSkewY, //!< vertical skew factor
kMScaleY, //!< vertical scale factor
kMTransY, //!< vertical translation
kMPersp0, //!< input x perspective factor
kMPersp1, //!< input y perspective factor
kMPersp2, //!< perspective bias
};
enum TypeMask {
kIdentity_Mask = 0, //!< all bits clear if SkMatrix is identity
kTranslate_Mask = 0x01, //!< set if SkMatrix has translation
kScale_Mask = 0x02, //!< set if SkMatrix has x or y scale
kAffine_Mask = 0x04, //!< set if SkMatrix skews or rotates
kPerspective_Mask = 0x08, //!< set if SkMatrix has perspective
};
static inline SkScalar sdot(SkScalar a, SkScalar b, SkScalar c, SkScalar d) {
return a * b + c * d;
}
void SkMatrix::preTranslate(SkScalar dx, SkScalar dy) {
const unsigned mask = this->getType();
if (mask <= kTranslate_Mask) {
//如果当前矩阵没有过变化,或者只有translate的变化
fMat[kMTransX] += dx;
fMat[kMTransY] += dy;
} else if (mask & kPerspective_Mask) {
//如果当前矩阵有透视的变化
SkMatrix m;
m.setTranslate(dx, dy);
this->preConcat(m);
return;
} else {
//有 缩放 或者 扭曲
fMat[kMTransX] += sdot(fMat[kMScaleX], dx, fMat[kMSkewX], dy);
fMat[kMTransY] += sdot(fMat[kMSkewY], dx, fMat[kMScaleY], dy);
}
this->updateTranslateMask();
}
void SkMatrix::postTranslate(SkScalar dx, SkScalar dy) {
if (this->hasPerspective()) {
//如果当前矩阵有透视
SkMatrix m;
m.setTranslate(dx, dy);
this->postConcat(m);
} else {
fMat[kMTransX] += dx;
fMat[kMTransY] += dy;
this->updateTranslateMask();
}
}
void SkMatrix::preConcat(const SkMatrix& mat) {
// check for identity first, so we don't do a needless copy of ourselves
// to ourselves inside setConcat()
if(!mat.isIdentity()) {
this->setConcat(*this, mat);
}
}
void SkMatrix::postConcat(const SkMatrix& mat) {
// check for identity first, so we don't do a needless copy of ourselves
// to ourselves inside setConcat()
if (!mat.isIdentity()) {
this->setConcat(mat, *this);
}
}
static inline float SkDoubleToFloat(double x) {
return static_cast<float>(x);
}
static inline float muladdmul(float a, float b, float c, float d) {
return SkDoubleToFloat((double)a * b + (double)c * d);
}
/**
* 参数为地址,c++操作: 地址[n] = 向后寻址n位
**/
static inline float rowcol3(const float row[], const float col[]) {
return row[0] * col[0] + row[1] * col[3] + row[2] * col[6];
}
static bool only_scale_and_translate(unsigned mask) {
return 0 == (mask & (SkMatrix::kAffine_Mask | SkMatrix::kPerspective_Mask));
}
/**
* 合并矩阵
**/
void SkMatrix::setConcat(const SkMatrix& a, const SkMatrix& b) {
TypeMask aType = a.getType();
TypeMask bType = b.getType();
if (a.isTriviallyIdentity()) {
//a矩阵没有改变过
*this = b;
} else if (b.isTriviallyIdentity()) {
//b矩阵没有改变过
*this = a;
} else if (only_scale_and_translate(aType | bType)) {
//只有缩放和位移
this->setScaleTranslate(a.fMat[kMScaleX] * b.fMat[kMScaleX],
a.fMat[kMScaleY] * b.fMat[kMScaleY],
a.fMat[kMScaleX] * b.fMat[kMTransX] + a.fMat[kMTransX],
a.fMat[kMScaleY] * b.fMat[kMTransY] + a.fMat[kMTransY]);
} else {
SkMatrix tmp;
if ((aType | bType) & kPerspective_Mask) {
//矩阵乘法,x行 与 y列的乘积的和为结果矩阵的的 x行y列位置
tmp.fMat[kMScaleX] = rowcol3(&a.fMat[0], &b.fMat[0]);
tmp.fMat[kMSkewX] = rowcol3(&a.fMat[0], &b.fMat[1]);
tmp.fMat[kMTransX] = rowcol3(&a.fMat[0], &b.fMat[2]);
tmp.fMat[kMSkewY] = rowcol3(&a.fMat[3], &b.fMat[0]);
tmp.fMat[kMScaleY] = rowcol3(&a.fMat[3], &b.fMat[1]);
tmp.fMat[kMTransY] = rowcol3(&a.fMat[3], &b.fMat[2]);
tmp.fMat[kMPersp0] = rowcol3(&a.fMat[6], &b.fMat[0]);
tmp.fMat[kMPersp1] = rowcol3(&a.fMat[6], &b.fMat[1]);
tmp.fMat[kMPersp2] = rowcol3(&a.fMat[6], &b.fMat[2]);
normalize_perspective(tmp.fMat);
tmp.setTypeMask(kUnknown_Mask);
} else {
tmp.fMat[kMScaleX] = muladdmul(a.fMat[kMScaleX],
b.fMat[kMScaleX],
a.fMat[kMSkewX],
b.fMat[kMSkewY]);
tmp.fMat[kMSkewX] = muladdmul(a.fMat[kMScaleX],
b.fMat[kMSkewX],
a.fMat[kMSkewX],
b.fMat[kMScaleY]);
tmp.fMat[kMTransX] = muladdmul(a.fMat[kMScaleX],
b.fMat[kMTransX],
a.fMat[kMSkewX],
b.fMat[kMTransY]) + a.fMat[kMTransX];
tmp.fMat[kMSkewY] = muladdmul(a.fMat[kMSkewY],
b.fMat[kMScaleX],
a.fMat[kMScaleY],
b.fMat[kMSkewY]);
tmp.fMat[kMScaleY] = muladdmul(a.fMat[kMSkewY],
b.fMat[kMSkewX],
a.fMat[kMScaleY],
b.fMat[kMScaleY]);
tmp.fMat[kMTransY] = muladdmul(a.fMat[kMSkewY],
b.fMat[kMTransX],
a.fMat[kMScaleY],
b.fMat[kMTransY]) + a.fMat[kMTransY];
tmp.fMat[kMPersp0] = 0;
tmp.fMat[kMPersp1] = 0;
tmp.fMat[kMPersp2] = 1;
//SkDebugf("Concat mat non-persp type: %d\n", tmp.getType());
//SkASSERT(!(tmp.getType() & kPerspective_Mask));
tmp.setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
}
*this = tmp;
}
}
源码位置:
/external/skia/include/core/SkMatrix.h