I’m trying to write the RECT structure described on page 20 of the SWF specification to a ByteArray. I started with [URL=“http://opensource.adobe.com/svn/opensource/flex/sdk/trunk/modules/swfutils/src/java/flash/swf/SwfEncoder.java”]some Java code from Adobe that does the same thing (but in Java, not AS3).
This is my adaptation so far:
public static function writeRect(bytes:ByteArray, rect:Rectangle):void {
bitPos = 8;
currentByte = 0;
var left:int = rect.left * 20;
var right:int = rect.right * 20;
var top:int = rect.top * 20;
var bottom:int = rect.bottom * 20;
var max:int = Math.max(Math.abs(left), Math.abs(right), Math.abs(top), Math.abs(bottom));
var nBits:uint = Math.max(Math.ceil(Math.log(max) / Math.LN2), 1) + 1; // 1 extra for sign?
writeBits(bytes, nBits, 5);
writeBits(bytes, left, nBits);
writeBits(bytes, right, nBits);
writeBits(bytes, top, nBits);
writeBits(bytes, bottom, nBits);
}
private static var
bitPos:int,
currentByte:uint;
private static function writeBits(bytes:ByteArray, val:uint, nBits:uint):void {
while (nBits > 0){
if (nBits > bitPos){
//if more bits left to write than shift out what will fit
currentByte |= val << (32 - nBits) >>> (32 - bitPos);
currentByte %= 256; // modulo, because AS3 doesn't have a `byte` type
// shift all the way left, then right to right
// justify the data to be or'ed in
bytes.writeByte(currentByte);
nBits -= bitPos;
currentByte = 0;
bitPos = 8;
} else { // (nBits <= bytePos)
currentByte |= val << (32 - nBits) >>> (32 - bitPos);
currentByte %= 256;
bitPos -= nBits;
nBits = 0;
if (bitPos == 0){
//if current byte is filled
bytes.writeByte(currentByte);
currentByte = 0;
bitPos = 8;
}
}
}
}
In some code that I wrote to test this, it will read in an SWF that’s 400x250 and write those dimensions as 400x249.75, which is a little off. (-:
In binary, here’s a comparison of what the 5 RECT fields should be (first) and what they end up being after the above code writes them (last):
nBits: 11100
left: 00000000000000
right: 11111010000000
top: 00000000000000
bottom: **10011100010000**
00000000000001111000000001000000000100010000010001000010000000000
nBits: 11100
left: 00000000000000
right: 11111010000000
top: 00000000000000
bottom: **10011100000111**
10000000000000000101000100000100010000100000000000000000000000000
(the trailing bits are just what is next in the file… I thought it might be useful to include in case I’m not writing enough bits, or something)
It seems like the right calls are being made to writeBits
, because the values make sense as multiplied forms of the Rectangle dimensions:
writeBits 14 5
writeBits 0 14
writeBits 8000 14
writeBits 0 14
writeBits 5000 14
So, something seems to be wrong with how it’s writing the last field (or how it does its bit/byte position bookkeeping overall), but I’ve been trying to debug this code for quite a while without any luck.
Does anyone know what might be going on here?