代码位置 | 结构含义 | 备注 | ||||||||||||||||||
0.1.2 | 固定为46 57 53,也就是字母‘F’‘W’‘S’ | “F”表示未压缩,“C”表示压缩式的,“W”无特殊意义 “S”无特殊意义 | ||||||||||||||||||
3 | 文件版本号 | 可根据此值与当前播放器控件的版本号比较,看是否需要更新 | ||||||||||||||||||
4.5.6.7 | 文件大小 | 正确的文件大小应该是按7、6、5、4的顺序来排列得到的十六进制数,单位是字节。 | ||||||||||||||||||
8.9.a.b.c.d.e.f.10h-0 | 影片宽高数据控制码
| 78 00 05 5F 00 00 0F A0 00
先取前5位二进制, 换成二进制,按照15位分割 0111 1||000 0000 0000 0000 ||0101 0101 1111 000||0 0000 0000 0000 00|| 00 1111 1010 0000 0||000 0000 Xmin = (000 0000 0000 0000)2=(0)10
Xmax = (0101 0101 1111 000)2= (11000)10
Ymin = (0 0000 0000 0000 00)2 =(0)10
Ymax = (00 1111 1010 0000 0) 2= (8000)10
是11000 * 8000;一般情况下,1 twip等于1/20象素。 550*400
| ||||||||||||||||||
10h-1,10h-2 | 表示帧速为 | 00 18 表示为16+8=24 | ||||||||||||||||||
10h-3.10h-4 | 影片的总帧数 | 02 00 表示为总数为2帧 | ||||||||||||||||||
Flash 生成的文件二进制数据码头文件标志结束,以下就是swf文件结构的一个形象概念: (文件header)(文件body) |
(tag 1)(tag 2)(tag 3)(……)
|
(tag header)(tag body)
|
(tag 类型代码)(tag 长度) |
截取图片
以下是关于SWF文件头的官方说明
区域 | 数据类型 | 含义 |
标识 | UI8(8位二进制无符号整数) | "F"表示该文件是未压缩的 "C"表示压缩文件(SWF6及后续版本支持) |
标识 | UI8 | 总是"W" |
标识 | UI8 | 总是 "S" |
版本 | UI8 | SWF文件版本 |
文件大小 | UI32 | 文件字节大小 |
画面尺寸 | RECT | 以twips为单位 |
帧速 | UI16 | 8.8形式的定点小数 |
总帧数 | UI16 | 总帧数 |
图片中16位:44 11,将小尾字节顺序转换成大尾顺序就是11 44,单个转换成为二进制字节即为:0001 0001 0100 0100,取高10位是(0001 0001 01)2=(69)10,低6位是(00 0100)2=(4)10.根据高10位的69,查询swf文件中的tag值和action值,可以知道TagType为69的是FileAttribute Tag。低6位的值4表示Tag数据大小占4个字节,因此我们取出后续4个字节为:00 00 00 00。
FileAttributes Tag的结构说明(FileAttributes Tag只在8及后续版本中)
域 | 数据类型 | 含义 |
Tag头 | RECORDHEADER | TagType=69 |
Reserved | UB[3] | 总是0 |
hasMetaData | UB[1] | 为1表示含有MetaData标签 为0表示不含 |
Reserved | UB[3] | 总是0 |
UseNetWork | UB[1] | 如果为1,则在本地加载时该文件有网络权限。为0,则在本地加载时该文件只有本地权限。 |
Reserved | UB[24] | 总是0 |
取下一个Tag,依然取2个字节43 02,转化成02 43,然后高十位=(0000 0010 01)2=(9)10,低6位=(00 0011)2=(3)10,高10位的9表明这是一个SetBackgroundColor tag,低6位的3表明数据占3个字节,OK,我们取出后续的3个字节是 FF FF FF,这背景颜色:白色。
再取下一个Tag 3F 03转化成03 3F,高10位=(0000 0011 00)2=(12)10,低6位(11 1111)2=(63)10,高十位的12表示这是个DoAction标签,低6位的63表明数据长度有后续的4个字节决定,再取后续的4个字节为02 00 00 00,它表明这个Tag的数据长度占2个字节,再取后续的2个字节是07 00,07表示Action代码,查Action代码就可以知道它表示ActionStop,也就是写在第一帧的代码AS Code /*stop();*/07后面的00,就表示DoAction Tag结束了。
取下一个Tag FF 0A转换0A FF,高10位=(0000 1010 11)2=(43)10,低6位=(11 1111)2=(63)10,高10位的43表明这是一个FrameLabel标签,低6位的63表明数据大小由后续的4个字节指明,取出后续的4个字节为06 00 00 00,也就说该Tag的数据占6个字节,继续取后续的6个字节,73 74 61 72 74 00,将16进制值转换成字符串就是"start",00是字符串结束标志。
Next Tag ,40 00,转换成 00 40,高10位=(0000 0000 01)2=(1)10,低6位=(00 0000)2=(0)10,高十位的1表明这是一个ShowFrame Tag,当前帧的内容都已进行完毕,可以显示当前帧了。
Next Tag , 3F 03与前面相同,接着取2个字节:05 00,05 代码表示ActionPrevFrame,也就是写的函数的AS Code “prevFrame();” ,00表示DoAction Tag结束了。
Next Tag,FF 0A,表明这是一个FrameLabel标签,也就是我们所说的帧标签。低6位的63表明数据大小由后续的4个字节指明,我们取出后续的4个字节为04 00 00 00,也就说该Tag的数据占4个字节,继续取后续的4个字节,65 6E 64 00,将16进制值转换成字符串,就是"end",00,是字符串结束标志。
Next Tag,40 00,转换成 00 40,高十位=(0000 0000 01)2=(1)10,低6位=(00 0000)2=(0)10,高十位的1表明这是一个ShowFrame Tag,就是当前帧内容都已准备完毕,可以显示当前帧了。
Next Tag 00 00,不用转换了,高十位是0,低6位也是0,表明这是个End Tag。
文件中的基本数据类型有整型(包括8,16,32的有符号和无符号,但是我在变成中感觉不到两者的区别),定点数,浮点数,变长数。下面的数据类型也是样式书中定义的基本类型,但是他们的定义都是以上面的4中作为基础的:
UIx x位无符号整型;(如UI8表示8位无符号整型,即一个byte的无符号整型)
SIx x位有符号整型;
UIx[n] x位无符号整型的长度是n的数组;
SIx[n] x位有符号整型的长度是n的数组;
FIXED 32位 16.16定点数
FIXED8 16位 8.8定点数
FLOAT16 16位半精度浮点数
FLOAT 32位单精度浮点数
DOUBLE 64位双精度浮点数
UB[n] n位变长数表示无符号整型
SB[n] n位变长数表示有符号整型
FB[n] n位变长数表示定点数
在swf中基本的数据结构:
1,swf的长度单位,swf使用twips表示坐标中的距离,1 twips=1/20 pixel。(我现在知道拉!flash的反走样是使用超采样地~~)这样分数的pixel可以使用整数的twips表示。样式书还说明了其他的好处,不过这和我有什么关系?
2,整型和字节顺序
swf使用8位,16位,32位,64位,有符号和无符号整形类型。所有的整形都是用little-endian的字节顺序(即数值低位储存在字节高位)。然后在每一个字节中采用big-endian编序。这样你就不会误会,字节80表示的确实是 128,而不是1 例子:16位的0xe712 被保存成 12 e7.32位的0x456e7120 被保存成20 71 6e 45.
3,定点数
swf中有两种定点数16位(8.8)和32位(16.16)。使用little-endian字节顺序
4,浮点数
有16位(半精度half),32位(单精度float),64位两种(双精度double)。
5,变长数(bit value)
长度可变的数,变长数可以表示无符号,有符号,和16.16定点数。
变长数不须要byte对齐(其他类型须要),如果需要byte对齐的类型紧接着变长数出现,需要补零。bit value作为不同的类型(前面说的3中)在解释上使用补0补1的方法。比如SB[4](有符号4位变长数) = 1110解释成16位有符号整形为 1111111111111110 = –2。
字符串,字符串是以全0结束的byte序列,采用utf-8编码。有关utf-8可以参考http://www.unicode.org/unicode/faq/utf_bom.html#UTF8。
语言种类是一个byte,描述的不是编码而是自然语言。用来处理字体还有在需要换行的时候处理断字,比如一个很长的英文单词出现在行尾但显示不下,可能会被处理显示到行首。
record,这个有点像C语言的structure,或者支持类的语言中没有方法的类。它按照格式顺序的储存一些上述的类型。
RGB color record
项目 | 类型 | 说明 |
Red | UI8 | 红色值 |
Green | UI8 | 绿色值 |
Blue | UI8 | 蓝色值 |
ARGB
Aplha | UI8 | 透明值,0为完全透明 |
Red | UI8 | 红色值 |
Green | UI8 | 绿色值 |
Blue | UI8 | 蓝色值 |
RGBA
Red | UI8 | 红色值 |
Green | UI8 | 绿色值 |
Blue | UI8 | 蓝色值 |
Aplha | UI8 | 透明值,0为完全透明 |
上面的3个是表示颜色的
Matrix 表示的是一个形状的仿射变换,有关仿射变换可以参考java.awt.geom.AffineTranform类,或者flash.geom.Matrix类的说明,或者任何一本大学的几何教材。
项目 | 类型 | 说明 |
HasScale | UB[1] | 如果包含缩放,则为1 |
NScaleBits | 如果HasScale=1,UB[5]否则没有该项 | 指示下面两项,每项要使用的bit数 |
ScaleX | 如果HasScale=1,FB[NScaleBits] | x方向上的缩放 |
ScaleY | 如果HasScale=1,FB[NScaleBits] | y方向上的缩放 |
HasRotate | UB[1] | 如果包含旋转,或者扭曲,则为1 |
NRotateBits | 如果HasRotate=1,UB[5] | 指示下面两项,每项要使用的bit数 |
RotateSkew0 | 如果HasRotate=1,FB[NScaleBits] | 有关旋转和扭曲的第一个值 |
RotateSkew0 | 如果HasRotate=1,FB[NScaleBits] | 有关旋转和扭曲的第二个值 |
NTranslateBits | UB[5] | 指示下面两项,每项要使用的bit数 |
TranslateX | SB[NTranslateBits] | x方向上平移的量,单位是twips |
TranslateY | SB[NTranslateBits] | y方向上平移的量,单位是twips |
这个matrix record对应一个2x3矩阵:
ScaleX RotateSkew0
( RotateSkew1 ScaleY )
TranslateX TranslateY
对于在一个坐标系中的(x, y),变换后的 (x', y')按照如下方法得到:
x' = x * ScaleX + y * RotateSkew1 + TranslateX
y' = x * RotateSkew0 + y * ScaleY + TranslateY
还有两个:Color Matrix record和Color Matrix with aplha record,是处理颜色转换,这和我暂时没有很大关系,所以如果将来感兴趣了再去参考吧。注意到这些后面的这些record上都对应了flash.geom包的类,但是它们却并非flash8中加入的新成员。所以不要以为只关心7以前的版本就完全没有必要看它们。
文件结构
至此,一个深刻的问题出现在我的面前。我要怎么使用这些类型?这里连一个声明/调用的语法都没有。要注意,现在我的事情是理解swf文件的结构(最后要生成一个)。这不是编程,而是编码。所以我必须按照swf的文件结构,按照一定的顺序把正确类型的数据放在正确的位置。这个就是本文的正体,上面噜苏的一堆其实算是对上一篇的补完。
swf文件是文件头和一些叫做tag的组成的。
上次介绍了header,这次来看一看tag:
tag的头
tag是以tag的类别和一个表述该tag的长度的域开始的,根据这个tag的长度不同,这个tag的头有两种:短格式的头和长格式的。短格式的tag要求数据内容(不包括头)的长度不超过62 bytes;而长格式则可以最多达4GB。
短格式
项目 | 类型 | 说明 |
TagCodeAndLength | UI16 | 高10位是tag类别,低6位是长度 |
长格式
项目 | 类型 | 说明 |
TagCodeAndLength | UI16 | 形式上和短格式一致,但是低6位的长度的数值固定为0x3f |
Length | SI32 | 数据长度 |
tag的种类
在一个swf中包含两中tag分别是Definition(定义)和Control(控制)。定义块中包含了对swf要包含内容的定义。比如一个图形,文字之类。定义块中要为每一个内容的定义指派一个唯一的id叫做character id(不要误会character的意义,这里不是指字符,而大约是标志的意思,而我想从这里开始使用标志这个词)。swf把这些标志(character)存放在一个叫做字典(dictionary)的结构中。注意定义块不会导致任何的屏幕绘制。
控制块处理,创建字典中标志的实例,绘制屏幕,控制流程等。
顺序
除了FileAttribute要放在最前(这是一些全局的东西),end它要放在最末。块之间不需要顺序。但是要保证依存关系,比如块B要引用块A的标志,就不能在A的前面出现。Stream块需要按照顺序。
关于DefineFont2介绍
这个tag的作用是定义一个字体,或者一组静态轮廓字,用以给DefineEdit Text使用。
关于文字的几乎所有信息,都可以在这个tag中进行设置,
它的结构如下:
其实如果单纯分析动态文本的这个tag的信息,只需要分析到下面的fontName部分就足够了,其他信息只对轮廓字,也就是静态文字有效。动态文字在信息上,关键的只有一个字体名,而静态文字却包含了他的轮廓信息(包含在shape里),这就是动态文字和静态文字最大的不同。
长度(bit) | 名称 | 说明 |
Headerlength | Header | Tag head, type of head 48 |
16 | FontID | 字符标号唯一的标签 |
1 | FontFlagsHasLayout | 根据字面解释,判断是否有变型的标记 |
1 | FontFlagsShiftJIS | 是否使用ShiftJIS编码 |
1 | FontFlagsSmallText | 是否使用小字体显示 |
1 | FontFlagsANSI | 是否使用ANSI编码 |
1 | FontFlagsWideOffsets | 是否使用32位偏移量 |
1 | FontFlagsWideCodes | 是否使用16位文字编码 |
1 | FontFlagsItalic | 文字是否是斜体 |
1 | FontFlagsBold | 文字是否是粗体 |
8 | LanguageCode | 语言编码有相应编码表对应 |
8 | FontNameLen | 文件名长度 |
FontNameLen*8 | FontName | 文件名称(使用utf8编码) |
16 | NumGlyphs | 轮廓字个数 |
32/16 | OffsetTable | 根据FontFlagsWideOffsets,为32位,否则为16位 |
32/16 | CodeTableOffset | 同上 |
不定*NumGlyphs | GlyphShapeTable | 轮廓字信息,为shape结构(又是一个复杂结构) |
16/8 | CodeTable | 根据FontFlagsWideCodes16位,编码表为固定值UCS-2 |
16/0 | FontAscent | 根据FontFlagsHasLayout,为16位,否则没有该字段 |
16/0 | FontDescent | 根据FontFlagsHasLayout,为16位,否则没有该字段 |
16/0 | FontLeading | 根据FontFlagsHasLayout,为16位,否则没有该字段 |
16/0*NumGlyphs | FontAdvanceTable | 根据FontFlagsHasLayout,为16位,否则没有该字段 |
RECT*NumGlyphs | FontBoundsTable | 根据FontFlagsHasLayout,为16位,否则没有该字段 |
16/0 | KerningCount | 根据FontFlagsHasLayout,为16位,否则没有该字段 |
KERNINGRECORD*KerningCount | FontKerningTable | 根据FontFlagsHasLayout,为16位,否则没有该字段 |