开机动画desc.txt描述文件的分析

转自  https://blog.csdn.net/u010753159/article/details/51356331


1 desc.txt文件格式分析

desc.txt文件由若干行组成,每一行代表一种描述。下面以一个具体的例子为例,具体说明

[html] view plain copy
  1. 480 640 20  
  2. p 1 0 folder1  
  3. p 2 20 folder2  
  4. c 0 0 folder3  
  5. c 1 0 folder4  
  6.    

第1行用来描述开机动画在屏幕显示的大小及速度。具体为:开机动画的宽度为480个像素,高度为640个像素,显示频率为每秒20帧,即每帧显示1/20秒。

下面的每一行代表一个片段,显示的时候会按照顺序从上到下依次显示。第1个字符为片段类型,有'c'和'p'两种,两者的区别后面会结合代码说明。

第2个数字为该片段重复显示的次数,如果为‘0’,表示会无限重复显示;第3个数字为两次显示之间的间隔,单位为第一行中定义的每帧显示的时间;第4个字符串为该片段所在的文件夹,一个片段可以由多个png图片组成,都存放在folder文件夹中。

“p 1 0 folder1”代表该片段显示1次,与下一个片段间隔0s,该片段的显示图片路径为bootanimation.zip/folder1。

“p 2 20 folder2”代表该片段显示2次,且两次之间显示的间隔为20*(1/20)=1s,与下一个片段间隔20*(1/20)=1s,该片段的显示图片路径为bootanimation.zip/folder2。

“c 0 0 folder3”代表该片段无限循环显示,且两次显示的间隔为0s,与下一个片段间隔0s,该片段的显示图路径为bootanimation.zip/folder3。

“c 1 10 folder4”代表该片段显示1次,显示后暂停10*(1/20)=0.5s,该片段的显示图路径为bootanimation.zip/folder4。

2 "p"片段和“c”片段的区别

在早期Android版本中只有“p”片段,且movie()中的显示代码如下:

[html] view plain copy
  1. for (int i=0 ; i<pcount && !exitPending() ; i++) {    
  2.         const Animation::Part& part(animation.parts[i]);    
  3.         const size_t fcount = part.frames.size();    
  4.         glBindTexture(GL_TEXTURE_2D, 0);    
  5.     
  6.         for (int r=0 ; !part.count || r<part.count ; r++) {    
  7.             for (int j=0 ; j<fcount && !exitPending(); j++) {    
  8.                 const Animation::Frame& frame(part.frames[j]);    
  9.   
  10.             .......  
  11.   
  12.     .....  
  13. }  
里面的主要参数和函数说吗如下:

pcount---显示片段的数量,比如上面的例子,pcount=4

p.count---该片段的重复显示次数。

fcount---该片段中png图片的数量
exitPending()---如果SurfaceFlinger服务通知bootanimation停止显示动画,则该函数返回值为true,否则为false。

第一个for循环用于顺序显示所有片段,第二个for循环用于重复显示该片段,第三个for循环用于顺序显示该片段中所有的png图片。

分析代码,可知:若exitPending()返回值为true,即SurfaceFlinger服务要求bootanimation停止显示动画,则不管当前显示到哪个片段或png图片,都会导致退出for循环,从而停止开机动画的显示。

在Android5.1中,加入了“c”片段。对与以"c"标识的片段,即使exitPending()返回值为true,也会继续显示。

我们分析一下源码,首先看一下movie()中解析desc.txt的代码:

[html] view plain copy
  1. // Parse the description file    
  2. for (;;) {    
  3.     ......   
  4.     if (sscanf(l, "%d %d %d %d", &width, &height, &fps, &flg) >= 3) {    
  5.         animation.width = width;    
  6.         animation.height = height;    
  7.         animation.fps = fps;    
  8.     }    
  9.     else if (sscanf(l, " %c %d %d %s #%6s", &pathType, &count, &pause, path, color) >= 4) {    
  10.         Animation::Part part;    
  11.         part.playUntilComplete = pathType == 'c';    
  12.         part.count = count;    
  13.         part.pause = pause;    
  14.         part.path = path;    
  15.         part.audioFile = NULL;    
  16.         if (!parseColor(color, part.backgroundColor)) {    
  17.             ALOGE("> invalid color '#%s'", color);    
  18.             part.backgroundColor[0] = 0.0f;    
  19.             part.backgroundColor[1] = 0.0f;    
  20.             part.backgroundColor[2] = 0.0f;    
  21.         }    
  22.         animation.parts.add(part);    
  23.     }    
  24.   
  25.     s = ++endl;    
  26. }  
可以看到,如果pathType==‘c’,part.playUntilComplete等于true,否则为false。接着,看一下显示代码:
[html] view plain copy
  1. for (size_t i=0 ; i<pcount ; i++) {    
  2.         const Animation::Part& part(animation.parts[i]);    
  3.         const size_t fcount = part.frames.size();    
  4.         glBindTexture(GL_TEXTURE_2D, 0);    
  5.     
  6.         for (int r=0 ; !part.count || r<part.count ; r++) {    
  7.             // Exit any non playuntil complete parts immediately    
  8.             if(exitPending() && !part.playUntilComplete)    
  9.                 break;    
  10.    
  11.             ......  
  12.   
  13.             for (size_t j=0 ; j<fcount && (!exitPending() || part.playUntilComplete) ; j++) {    
  14.                   
  15.         ......  
  16.     
  17.                 checkExit();    
  18.             }    
  19.     
  20.             usleep(part.pause * ns2us(frameDuration));    
  21.     
  22.             // For infinite parts, we've now played them at least once, so perhaps exit    
  23.             if(exitPending() && !part.count)    
  24.                 break;    
  25.         }    
  26.     
  27.         ......    
  28.     }   
可以看到,如果exitPending()返回值为true且part.playUntilComplete=false,则会break。即:当SurfaceFlinger服务要求bootanimation停止显示动画时,以‘p’标识的片段会停止,而以'c'标识的片段会继续显示。这就是两者之间的主要区别。

这里有个问题:重复循环显示的'c'标识片段,会不受任何约束的一直显示下去,这显然是不合适的。
于是在第二个for循环体最后,有如下代码:

[html] view plain copy
  1. // For infinite parts, we've now played them at least once, so perhaps exit    
  2.             if(exitPending() && !part.count)    
  3.                 break;   
意思是,如果检测到SurfaceFlinger服务要求bootanimation停止显示,且该片段的显示次数为'0',即重复循环显示,则会break停止显示。


我猜想"c"标识的意思是continue,即:即使SurfaceFlinger要求bootanimation停止动画,bootanimation也不会立刻停止动画,它会等c标识片段都显示完毕后,再停止。

这样,我们可以利用'c'和'p'片段的区别,设计出更灵活的开机动画。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值