A simple .swf file and it’s below the line representation

A simple .swf file and it’s below the line representation

 

       At some point along your journey to write your own .swf files, you are going to have to be able to read and understand the raw bits and bytes. I created a one frame flash movie that contained only a rectangle and saved it as Rectangle.swf. Let’s take a look at the way the file is represented in its .swf format. Below is the hexadecimal representation of Rectangle.swf. Let’s take a closer look…

 

000000 46 57 53 03 4F 00 00 00    78 00 05 5F 00 00 0F A0

000010 00 00 0C 01 00 43 02 FF    FF FF BF 00 23 00 00 00

000020 01 00 70 FB 49 97 0D 0C    7D 50 00 01 14 00 00 00

000030 00 01 25 C9 92 0D 21 ED    48 87 65 30 3B 6D E1 D8

000040 B4 00 00 86 06 06 01 00    01 00 00 40 00 00 00

 

   Every .swf file has two parts, the header block and a series of tagged data blocks. Let’s begin with the header. 

 

HEADER

 

       The header is always the first 21 bytes of the .swf file (true?). It describes the file version(1,2, or 3), length of the file in bytes, the frame size in TWIPS, frame rate in frames per second, and the frame count.

 

       Here is the “SWF File Reference’ description of the header:

 

Field

Type

Comment

Signature

UI8

Signature byte always ‘F’

Signature

UI8

Signature byte always ‘W’

Signature

UI8

Signature byte always ‘S’

Version

UI8

Single byte file version

File Length

UI32

Length of entire file in bytes

Frame Size

RECT

Frame size in TWIPS

Frame Rate

UI16

Frame delay in 8.8 fixed number of frames per second

Frame Count

UI16

Total number of frames in movie

 

 

The first three bytes are the standard signature for all .swf files. They are the ASCII values of the characters ‘F’, ‘W’, and ‘S’ in that order. The fourth byte indicates the version of the file. Although a file can be of version 1, 2, or 3, we will always be creating version 3 files so this value will also be fixed.

 

      0x46           ‘F’           0x57             ‘W’         0x53           ‘S’            0x03       3

 

The next 4 bytes represent an unsigned 32-bit integer indicating the file size. Here’s where it starts getting tricky and machine architecture gets involved! The next 4 bytes are 0x4F000000 so that would imply that the file length is 1325400064 bytes, a very large number which doesn’t make sense. What we failed to do is swap all the bytes.

In .swf files, bytes are swapped whenever reading words and dwords such that a 32 bit value B1B2B3B4 is written as B4B3B2B1, and a 16 bit value B1B2 is written as B2B1. Single bytes are written unchanged since there is NO bit- swapping. The reason for this is the differences in storage and retrieval between the Mac and PC processors.

 

Reversing the bytes we can read the 4 bytes correctly and see that file is 79 bytes long.

   

0 x4F000000                     0x0000004F            79

 

       The next 9 bytes represent a data structure used in the .swf format called a Rectangle. Here is the file description of a rectangle:

 

Field

Type

Comment

Nbits

nBits = UB[5]

Bits in each rect value field

Xmin

SB[nBits ]

X minimum position for rect

Xmax

SB[nBits ]

X maximum position for rect

Ymin

SB[nBits ]

Y minimum position for rect

Ymax

SB[nBits ]

Y maximum position for rect

 

To understand these bytes, we need to look at the individual bits.

 

78 00 05 5F 00 00 0F A0 00

 

 

 

0111 1 000 0000 0000 0000 0101 0101 1111 000 0 0000

0000 0000 00 00 1111 1010 0000 0 000 0000

 

       There are five fields in a rectangle structure: nBits, xmin, xmax, ymin, ymax. The unsigned nBits field occupies the first five bits of the rectangle and indicates how long the next four signed fields are. 

Here’s where we hit another subtle point about the .swf file representation. Reading and writing bits is different from reading and writing words and dwords. There is no swapping at all! This is because when Flash is reading an n-bit field, it reads a byte at a time until it has read all n bits. You don’t do any swapping inside of bytes so there is no swapping at all. So the next five bits are read in order and evaluate to 15. Although the nBit field usually varies, it appears fixed in the header so that header has a fixed size (It may just be because the movie dims are usually the same).

 

01111                15

 

       What if nBit has a value of sixteen? This is exactly the size of a word so do we read the following fields as words and swap bytes? No. Fields described by bit size are always read a byte at a time. No swapping, just read the next n bits in that order.

 

000000000000000                0  = xmin

010101011111000                11000 = xmax

000000000000000                0 = ymin

001111101000000                8000 = ymax

 

       For the header, the rectangle is used to store the movie dimensions with xmax corresponding to the movie width and ymax corresponding to the movie height, both in TWIPS. “What’s this TWIPS thing?” you ask. According to whatis.com :

A twip (twentieth of a point) is a measure used in laying out space or defining objects on a page or other area that is to be printed or displayed on a computer screen. A twip is 1/1440th of an inch or 1/567th of a centimeter. That is, there are 1440 twips to an inch or 567 twips to a centimeter. The twip is 1/20th of a point , a traditional measure in printing. A point is approximately 1/72nd of an inch.

For Flash a point corresponds to a pixel, so if we convert from TWIPS to pixels, we see that our movie is 550 x 400. 

       Now we have looked at all of the fields of the rectangle and evaluated them, but what about those last seven bits which are all 0’s. Well, they were just “filled.” 

 

0000000 = filled bits

 

After the end of any structure, if the structure does not completely fill up its last byte, then that last byte is filled with 0’s to keep the next item byte aligned. So if the next item is a word or dword, you can read it as such and not worry about being in the middle of a byte. In this case, only 1 bit in the last byte is used so the last 7 bits are filled with 0’s. 

       Next in the header is the frame rate, which is kind of weird. It is supposed to be stored as a 16bit integer, but the first byte (or last depending on how you look at it) is completely ignored. So the frame rate is 12 fps.

 

0x000C               0x0C00                   0x0C         12 = frame rate

 

       Next is the frame count, which is also a 16-bit integer. So the frame count is 1.

 

0x0100                 0x0001(byte swapping)           1 = frame count

 

       Now we are done with the header. After the header is a series of tagged data blocks. Here is the file description of a tag:

 

Short Tag

 

Field

Type

Comment

Tag

UB[10]

Tag id

Length

UB[6]

Length of tag

 

Long Tag

 

Field

Type

Comment

Tag

UB[10]

Tag id

Long Header Flag

UB[6]

Always 0x3F

Length

UI32

Length of tag

 

 

 

      There are 2 types of tags. They are the short and long data header. Regardless of which case you have, you begin by looking at the first word.

 

0x4302            0x0243               0000 0010 01 00 0011

 

The first 10 bits of the tag are the unsigned tag ID. The tag ID indicates what type of data is to follow in the body of the data block to follow. In this case the value of the tag ID is 9 which corresponds to a setBackgroundColor block. (APPENDIX SHOULD HAVE ALL ID MEANINGS). The last 6 unsigned bits of the tag indicate the length of the data block to follow if it is 62 bytes or less. If the length of the data block is more than 62 bytes, then this field has all 1’s and the length is indicated in the following dword. In this situation though the field does not have all 1’s so the field does indicate the actual length which is 3 bytes.

 

0000001001 = 9 = setBackgroundColor    000011 = 3 = body length

 

       Since we know that the length of the body is 3 bytes, let’s take a look at it. A setBackgroundColor block only contains the 3 byte rgb color description so we evaluate it as such. A color is its own 3 byte data type so there is no byte swapping.

 

0XFFFFFF = white

 

       The next tag is a long tag and is a defineShape tag.

 

0xBF00          0x00BF          0000 0000 10 11 1111

 

0000000010 = 3 = defineShape       111111 = body length (so we have to look at the

                                                                              next dword)

0x23000000               0x00000023           35 = body length

 

Here is the file description of defineShape:

 

Field

Type

Comment

Header

RECORDHEADER

Tag ID = 2

ShapeId

UI16

ID for this character

ShapeBounds

RECT

Bounds of the shape

Shapes

SHAPEWITHSTYLE

Shape information

 

              The body of a defineShape is composed of an unsigned 16-bit character ID, a rectangle defining the bounds for the shape, and a ShapeWithStyle structure which contains shape information.

 

0x0100       0x0001        1 = shape ID

 

Now the Rect which defines the boundaries:

 

70 FB 49 97 0D 0C 7D 50

 

 

 

 

0111 0 000 1111 1011 010 0 1001 1001 0111 0 000 1101   0000 110 0 0111 1101 0101 0 000

 

01110 = 14 = nBits

00011111011010 = 2010 = xmin /20 to covert to pixels from TWIPS   100.5

01001100101110 = 4910 = xmax                                          245.5

00011010000110 = 1670 = ymin                                    83.5

00111110101010 = 4010 = ymax                                          200.5

000 = fill bits

 

       The ShapeWithStyle structure has five parts. A fill style array, a line style array, a nFillBits field, a nLineBits field, and an array of shape records. Here is the file description:

 

Field

Type

Comment

FillStyles

FILLSTYLEARRAY

Array of fill styles

LineStyles

LINESTYLEARRAY

Array of line styles

NumFillBits

nFillBits = UB[4]

Number of fill index bits

NUML ineBits

nLineBits = UB[4]

Number of line index bits

ShapeRecords

SHAPEREC[one or more]

Shape records - see below

 

       A fill style array itself has three fields. The first field is an 8 bit integer count which indicates how many fill styles are in the array. This count works similar to the tag’s length field in that if it is all 1’s, you have to look at the next 16-bits to get the actual length. Here is the file description:

 

Field

Type

Comment

FillStyleCount

count = UI8

Count of fill styles

FillStyleCountExtended

If count = 0xFF count = UI16

Extended count of fill styles. Supported only for Shape2 and Shape3.

FillStyles

FILLSTYLE[count ]

Array of fill styles

 

 

In this case, the 8 bit count is equal to 0 so there is nothing to follow it.

 

0x00 = 0 = count         This is the end of the fill style array because it has no elements

 

       A line style array is exactly the same as a fill style array except it stores line styles. Here is the file description:

 

Field

Type

Comment

LineStyleCount

count = UI8

Count of line styles

LineStyleCountExtended

If count = 0xFF count = UI16

Extended count of line styles

LineStyles

LINESTYLE[count ]

Array of line styles

0x01 = 1 = count           So there is one line style in the array.

 

       A line style has two parts, an unsigned 16-bit integer indicating the width of a line in TWIPS, and a color. Here is the file description:

 

Field

Type

Comment

Width

UI16

Width of line in twips

Color

RGB (Shape1 or Shape2)
RGBA (Shape3)

Color value including alpha channel information for Shape3s

 

 

The color in this case is a 24-bit RGB, but if we were doing a defineShape3, it would be a 32-bit RGBA where alpha is the transparency of the color. 

 

0x1400          0x0014 = 20 = width = 1 pixel

0x000000 = RGB = black

 

       Back to the ShapeWithStyle, the nFillBits field is 4 bits, as is the nLineBits.

 

0x0 = 0 = nFillBits          0x1 = 1 = nLineBits

 

       Now for the array of shape records. There are three types of shape records. Here are the file descriptions:

 

Shape Record Type 0

 

Field

Type

Comment

TypeFlag

UB[1] = 0

Non-edge record flag

EndOfShape

UB[5] = 0

End of shape flag

 

 

Shape Record Type 1

 

Field

Type

Comment

TypeFlag

UB[1] = 0

Non-edge record flag

StateNewStyles

newStyles = UB[1]

New styles flag. Used by DefineShape2 and DefineShape3 only.

StateLineStyle

lineStyle = UB[1]

Line style change flag

StateFillStyle0

fillStyle0 = UB[1]

Fill style 0 change flag

StateFillStyle1

fillStyle1 = UB[1]

Fill style 1 change flag

StateMoveTo

moveTo = UB[1]

Move to flag

MoveBits

If moveTo nMoveBits = UB[5]

Move bit count

MoveDeltaX

If moveTo UB[nMoveBits ]

Delta X value

MoveDeltaY

If moveTo UB[nMoveBits ]

Delta Y value

Fill0Style

If fillStyle0 UB[nFillBits ]

Fill 0 Style

Fill1Style

If fillStyle1 UB[nFillBits ]

Fill 1 Style

LineStyle

If lineStyle UB[nLineBits ]

Line Style

FillStyles

If newStyles FILLSTYLEARRAY

Array of fill styles

LineStyles

If newStyles LINESTYLEARRAY

Array of line styles

 

 

Shape Record Type 2

 

Field

Type

Comment

TypeFlag

UB[1] = 1

This is an edge record

EdgeRecord

<think>嗯,用户问的是关于“Prints a representation of this object to the system log file.”的中文介绍。首先,我需要明确这个功能的具体应用场景和常见用途。这通常出现在编程中,特别是调试的时候,开发者需要将对象的状态输出到系统日志,方便跟踪问题。 接下来,我应该解释这个操作的基本概念。比如,它可能是某个编程语言中的方法,比如Java的toString()方法结合日志框架,或者是Android的Log.d()。需要说明这个方法的作用是将对象的字符串表示写入日志文件,帮助开发者了解程序运行时的状态。 然后,考虑用户可能的背景。可能是刚学习编程的新手,或者正在调试程序时遇到问题。他们可能想知道如何使用这个功能,或者为什么需要这样做。所以,需要举例子,比如在Android开发中使用Log类,或者Python中的logging模块。 还要注意区分不同编程语言中的实现方式,但用户可能没有指定具体语言,所以应该保持一般性,同时举几个常见语言的例子。比如Java、Python、JavaScript等。 另外,需要解释为什么这个功能重要。比如,在调试时查看对象的状态,或者在生产环境中记录关键信息。同时提醒用户注意不要在日志中记录敏感信息,避免安全问题。 最后,检查是否有遗漏的点,比如系统日志的位置,或者如何查看这些日志。不过可能不需要太深入,保持回答简洁明了。总结一下,分步骤解释概念、用途、示例和注意事项,确保用户能全面理解。</think>该描述通常指编程中将对象信息输出到系统日志的功能实现,常见于以下场景: ▌核心概念 通过调用特定方法(如`toString()`)将对象内容转换为字符串形式,并使用日志工具将该字符串写入系统日志文件。这是程序调试和运行监控的常用手段。 ▌典型代码示例 ```java // Android示例 public class User { String name; int age; @Override public String toString() { return "User{name='" + name + "', age=" + age + "}"; } public void logInfo() { Log.d("USER_DEBUG", this.toString()); // 输出到Android系统日志 } } ``` ▌主要作用 1. 调试追踪:实时查看对象状态变化 2. 异常分析:记录错误发生时的对象快照 3. 运行监控:跟踪对象在业务流程中的流转 4. 数据验证:检查序列化/反序列化结果 ▌实现方式差异 • Java:`System.out.println()` / Log4j / SLF4J • Python:`logging.info(obj.__dict__)` • JavaScript:`console.debug(JSON.stringify(obj))` • C#:`Debug.WriteLine(obj.ToString())` ▌注意事项 1. 敏感信息过滤:避免记录密码等隐私数据 2. 性能优化:高频日志需考虑字符串拼接开销 3. 日志分级:区分DEBUG/INFO等级别合理输出 4. 循环引用处理:防止对象相互引用导致栈溢出 ▌日志查看方法 • Android:Android Studio的Logcat窗口 • Linux:`tail -f /var/log/syslog` • Windows:事件查看器 → Windows日志 → 应用程序 • Web应用:通常写入指定路径的.log文件
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值