1. 在画布 会使用 rotate ,translate,skew 方法,对画布旋转,移动。这些对画布的操作数据使用的是Matrix 对象存放的,是以一维 数组来存放3*3阶矩形数据.
2.3*3阶矩形是 有三行三列数据 如:
1 2 3
a= 1 2 3
1 2 3
3.a *b 的矩形如何计算的呢 (公式: c 第m行 第n 列的值等于 a 第m行的数据与b 第n列的数据进行相乘并相加)如:
1 0 2 2 0 1 1*2+0*5+2*8 1*0+0*4+2*7 1*1+0*3+2*6 18 14 13
a = 3 4 5 b = 5 4 3 c=axb= 3*2+4*5+5*8 3*0+4*4+5*5 3*1+3*3+5*6= 66 41 42
6 7 8 8 7 6 6*2+7*5+8*8 6*0+7*4+8*5 6*1+7*3+8*6 ..........
需要注意的是 a*b 不一定等于 b*a
4.preXXXX 和 postXXXX 对应矩形 运算的左乘与 右乘 ,假如this 来表示 a ,preXXXX或者postXXXX 设置的Matrix 为b
那么 preXXXX 运算是a*b ,postXXXX 是b*a. 在andorid 源码中并不是简单左乘 与右乘(缩放和移动两个实现是不同的,旋转和斜切是简单的左乘与右乘的操作区别)
5.preTranslate 的测试 :
android.graphics.Matrix matrix=new Matrix();
Log.e(TAG,"init:"+matrix.toString());
matrix.preTranslate(10,10);
Log.e(TAG,"preTranslation:"+matrix.toString());
结果 :2020-02-15 23:30:39.020 17089-17107/com.animation E/ExampleInstrumentedTest: init:Matrix{[1.0, 0.0, 0.0][0.0, 1.0, 0.0][0.0, 0.0, 1.0]}
2020-02-15 23:30:39.020 17089-17107/com.animation E/ExampleInstrumentedTest: preTranslation:Matrix{[1.0, 0.0, 10.0][0.0, 1.0, 10.0][0.0, 0.0, 1.0]}
第二次
android.graphics.Matrix matrix=new Matrix();
Log.e(TAG,"init:"+matrix.toString());
matrix.setScale(0.5f,0.5f);
Log.e(TAG,"setScale:"+matrix.toString());
matrix.preTranslate(10,10);
Log.e(TAG,"preTranslation:"+matrix.toString());
matrix.preTranslate(10,10);
结果:2020-02-15 23:34:16.755 17527-17558/? E/ExampleInstrumentedTest: init:Matrix{[1.0, 0.0, 0.0][0.0, 1.0, 0.0][0.0, 0.0, 1.0]}
2020-02-15 23:34:16.755 17527-17558/? E/ExampleInstrumentedTest: setScale:Matrix{[0.5, 0.0, 0.0][0.0, 0.5, 0.0][0.0, 0.0, 1.0]}
2020-02-15 23:34:16.755 17527-17558/? E/ExampleInstrumentedTest: preTranslation:Matrix{[0.5, 0.0, 5.0][0.0, 0.5, 5.0][0.0, 0.0, 1.0]}
都是 translation 10 ,为啥两次结果不一样呢 show fuck code: SKMatrix.cpp
static inline SkScalar sdot(SkScalar a, SkScalar b, SkScalar c, SkScalar d)
{ return a * b + c * d;
}
static inline SkScalar sdot(SkScalar a, SkScalar b, SkScalar c, SkScalar d, SkScalar e, SkScalar f) { return a * b + c * d + e * f; }
SkScalar 当做 float 就行了
void SkMatrix::preTranslate(SkScalar dx, SkScalar dy)
{
if (!dx && !dy) { return; }
if (this->hasPerspective()) { //没有触发 ,也不知道怎么触发
SkMatrix m;
m.setTranslate(dx, dy);
this->preConcat(m); }
else { 触发这个
fMat[kMTransX] += sdot(fMat[kMScaleX], dx, fMat[kMSkewX], dy); 0.5*10+0*10=5
fMat[kMTransY] += sdot(fMat[kMSkewY], dx, fMat[kMScaleY], dy); 0.5*10+0*10=5
this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
}
}
6.postTranslate 的测试 :
android.graphics.Matrix matrix=new Matrix();
Log.e(TAG,"init:"+matrix.toString());
matrix.postTranslate(10,10);
2020-02-15 23:50:20.018 20179-20195/com.animation E/ExampleInstrumentedTest: init:Matrix{[1.0, 0.0, 0.0][0.0, 1.0, 0.0][0.0, 0.0, 1.0]}
2020-02-15 23:50:20.019 20179-20195/com.animation E/ExampleInstrumentedTest: postTranslation:Matrix{[1.0, 0.0, 10.0][0.0, 1.0, 10.0][0.0, 0.0, 1.0]}
第二次
android.graphics.Matrix matrix=new Matrix();
Log.e(TAG,"init:"+matrix.toString());
matrix.setScale(0.5f,0.5f);
Log.e(TAG,"setScale:"+matrix.toString());
matrix.postTranslate(10,10);
Log.e(TAG,"postTranslation:"+matrix.toString());
2020-02-15 23:58:59.512 21983-21999/? E/ExampleInstrumentedTest: init:Matrix{[1.0, 0.0, 0.0][0.0, 1.0, 0.0][0.0, 0.0, 1.0]}
2020-02-15 23:58:59.512 21983-21999/? E/ExampleInstrumentedTest: setScale:Matrix{[0.5, 0.0, 0.0][0.0, 0.5, 0.0][0.0, 0.0, 1.0]}
2020-02-15 23:58:59.512 21983-21999/? E/ExampleInstrumentedTest: postTranslation:Matrix{[0.5, 0.0, 10.0][0.0, 0.5, 10.0][0.0, 0.0, 1.0]}
跟preTranslate结果不一样 show fuck code: SKMatrix.cpp
void SkMatrix::postTranslate(SkScalar dx, SkScalar dy) {
if (!dx && !dy) { return; }
if (this->hasPerspective()) {
SkMatrix m; m.setTranslate(dx, dy);
this->postConcat(m);
}
else {
fMat[kMTransX] += dx;
fMat[kMTransY] += dy; //直接加的
this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
}
}
7.preScale 测试:
android.graphics.Matrix matrix=new Matrix();
Log.e(TAG,"init:"+matrix.toString());
matrix.preScale(0.5f,0.5f);
Log.e(TAG,"preScale:"+matrix.toString());
matrix.preScale(0.5f,0.5f);
Log.e(TAG,"preScale:"+matrix.toString());
matrix.preTranslate(10,10);
结果: 2020-02-16 00:19:29.615 23989-24012/? E/ExampleInstrumentedTest: init:Matrix{[1.0, 0.0, 0.0][0.0, 1.0, 0.0][0.0, 0.0, 1.0]}
2020-02-16 00:19:29.615 23989-24012/? E/ExampleInstrumentedTest: preScale:Matrix{[0.5, 0.0, 0.0][0.0, 0.5, 0.0][0.0, 0.0, 1.0]}
2020-02-16 00:19:29.615 23989-24012/? E/ExampleInstrumentedTest: preScale:Matrix{[0.25, 0.0, 0.0][0.0, 0.25, 0.0][0.0, 0.0, 1.0]}
2020-02-16 00:19:29.615 23989-24012/? E/ExampleInstrumentedTest: preTranslation:Matrix{[0.25, 0.0, 2.5][0.0, 0.25, 2.5][0.0, 0.0, 1.0]}
SkMatrix.cpp:
void SkMatrix::preScale(SkScalar sx, SkScalar sy) {
if (1 == sx && 1 == sy) { return; } // the assumption is that these multiplies are very cheap, and that // a full concat and/or just computing the matrix type is more expensive. // Also, the fixed-point case checks for overflow, but the float doesn't, // so we can get away with these blind multiplies.
fMat[kMScaleX] *= sx;
fMat[kMSkewY] *= sx; // 直接乘原来的 0.5*0.5=0.25
fMat[kMPersp0] *= sx;
fMat[kMSkewX] *= sy;
fMat[kMScaleY] *= sy;
fMat[kMPersp1] *= sy;
this->orTypeMask(kScale_Mask);
}
8.postScale 测试:
android.graphics.Matrix matrix=new Matrix();
Log.e(TAG,"init:"+matrix.toString());
matrix.postScale(0.5f,0.5f);
Log.e(TAG,"postScale:"+matrix.toString());
matrix.postScale(0.5f,0.5f);
Log.e(TAG,"postScale:"+matrix.toString());
matrix.preTranslate(10,10);
Log.e(TAG,"preTranslation:"+matrix.toString());
matrix.postScale(1,1);
Log.e(TAG,"postScale:"+matrix.toString());
结果: 2020-02-16 00:28:11.342 25361-25377/? E/ExampleInstrumentedTest: init:Matrix{[1.0, 0.0, 0.0][0.0, 1.0, 0.0][0.0, 0.0, 1.0]}
2020-02-16 00:28:11.342 25361-25377/? E/ExampleInstrumentedTest: postScale:Matrix{[0.5, 0.0, 0.0][0.0, 0.5, 0.0][0.0, 0.0, 1.0]}
2020-02-16 00:28:11.342 25361-25377/? E/ExampleInstrumentedTest: postScale:Matrix{[0.25, 0.0, 0.0][0.0, 0.25, 0.0][0.0, 0.0, 1.0]}
2020-02-16 00:28:11.342 25361-25377/? E/ExampleInstrumentedTest: preTranslation:Matrix{[0.25, 0.0, 2.5][0.0, 0.25, 2.5][0.0, 0.0, 1.0]}
2020-02-16 00:28:11.342 25361-25377/? E/ExampleInstrumentedTest: postScale:Matrix{[0.25, 0.0, 2.5][0.0, 0.25, 2.5][0.0, 0.0, 1.0]}
SkMatrix.cpp:
void SkMatrix::postScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {
if (1 == sx && 1 == sy) { return; }
SkMatrix m;
m.setScale(sx, sy, px, py);
this->postConcat(m);
}
void SkMatrix::setScale(SkScalar sx, SkScalar sy, SkScalar px, SkScalar py) {
if (1 == sx && 1 == sy)
{ this->reset();
}
else {
this->setScaleTranslate(sx, sy, px - sx * px, py - sy * py); // 这里就很有意思了。你要想平移位置 到tx点,那么公式 tx+sx*px=等于传参px,ty同理. } } // 直接设置值
void SkMatrix::setScaleTranslate(SkScalar sx, SkScalar sy, SkScalar tx, SkScalar ty)
{
fMat[kMScaleX] = sx;
fMat[kMSkewX] = 0;
fMat[kMTransX] = tx;
fMat[kMSkewY] = 0;
fMat[kMScaleY] = sy;
fMat[kMTransY] = ty;
fMat[kMPersp0] = 0;
fMat[kMPersp1] = 0;
fMat[kMPersp2] = 1;
unsigned mask = 0;
if (sx != 1 || sy != 1)
{
mask |= kScale_Mask;
}
if (tx || ty)
{
mask |= kTranslate_Mask;
}
this->setTypeMask(mask | kRectStaysRect_Mask); }
9.preRotate 测试:
android.graphics.Matrix matrix=new Matrix();
Log.e(TAG,"init:"+matrix.toString());
matrix.setScale(0.5f,0.5f);
Log.e(TAG,"setScale:"+matrix.toString());
matrix.postTranslate(10,10);
Log.e(TAG,"postTranslate:"+matrix.toString());
matrix.postTranslate(10,10);
Log.e(TAG,"postTranslate:"+matrix.toString());
matrix.preRotate(40);
Log.e(TAG,"cosV="+Math.cos(Math.toRadians(40)));
Log.e(TAG,"sinV="+Math.sin(Math.toRadians(40)));
Log.e(TAG,"preRotate:"+matrix.toString());
matrix.postTranslate(10,10);
Log.e(TAG,"postTranslate:"+matrix.toString());
结果:
2020-02-16 11:21:18.811 3793-3813/? E/ExampleInstrumentedTest: init:Matrix{[1.0, 0.0, 0.0][0.0, 1.0, 0.0][0.0, 0.0, 1.0]}
2020-02-16 11:21:18.811 3793-3813/? E/ExampleInstrumentedTest: setScale:Matrix{[0.5, 0.0, 0.0][0.0, 0.5, 0.0][0.0, 0.0, 1.0]}
2020-02-16 11:21:18.811 3793-3813/? E/ExampleInstrumentedTest: postTranslate:Matrix{[0.5, 0.0, 10.0][0.0, 0.5, 10.0][0.0, 0.0, 1.0]}
2020-02-16 11:21:18.812 3793-3813/? E/ExampleInstrumentedTest: postTranslate:Matrix{[0.5, 0.0, 20.0][0.0, 0.5, 20.0][0.0, 0.0, 1.0]}
2020-02-16 11:21:18.812 3793-3813/? E/ExampleInstrumentedTest: cosV=0.766044443118978
2020-02-16 11:21:18.812 3793-3813/? E/ExampleInstrumentedTest: sinV=0.6427876096865393
2020-02-16 11:21:18.812 3793-3813/? E/ExampleInstrumentedTest: preRotate:Matrix{[0.38302222, -0.3213938, 20.0][0.3213938, 0.38302222, 20.0][0.0, 0.0, 1.0]}
2020-02-16 11:21:18.812 3793-3813/? E/ExampleInstrumentedTest: postTranslate:Matrix{[0.38302222, -0.3213938, 30.0][0.3213938, 0.38302222, 30.0][0.0, 0.0, 1.0]}
SKMatrix.cpp
void SkMatrix::preRotate(SkScalar degrees, SkScalar px, SkScalar py) {
SkMatrix m;
m.setRotate(degrees, px, py);
this->preConcat(m);
}
void SkMatrix::setRotate(SkScalar degrees) {
SkScalar sinV, cosV;
sinV = SkScalarSinCos(SkDegreesToRadians(degrees), &cosV);
this->setSinCos(sinV, cosV);
}
void SkMatrix::setSinCos(SkScalar sinV, SkScalar cosV) {
fMat[kMScaleX] = cosV;
fMat[kMSkewX] = -sinV;
fMat[kMTransX] = 0;
fMat[kMSkewY] = sinV;
fMat[kMScaleY] = cosV;
fMat[kMTransY] = 0;
fMat[kMPersp0] = fMat[kMPersp1] = 0;
fMat[kMPersp2] = 1;
this->setTypeMask(kUnknown_Mask | kOnlyPerspectiveValid_Mask);
}
通过上面的日记和源码计算出:
0.5 0 20 0.7660 -0.6427 0
this的矩形数据 a= 0 0.5 20 preRotate计算出来矩形数据b= 0.6427 0.7660 0
0 0 1 0 0 1
0.5*0.7660+0*0.6427+20*0 0.5*-0.6427+0*0.7660+20*0 0.5*0+0*0+20*1 0.383 - 0.32135 20
c=a*b= 0*0.7660+0.5*0.6427+20*0 0*-0.6427+0.5*0.7660+20*0 0.5*0+0*0+20*1 = 0.32135 0.383 20
0 0 1 0 0 1
对得上 这条日记 2020-02-16 11:21:18.812 3793-3813/? E/ExampleInstrumentedTest: preRotate:Matrix{[0.38302222, -0.3213938, 20.0][0.3213938, 0.38302222, 20.0][0.0, 0.0, 1.0]}
剩余prexxx和postxxx操作就是左乘与右乘区别
ps:打印具体内容是什么意思,喵Matrix.ava 源码.