Android Matrix 理解与源码阅读

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 源码.

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值