Writing SWF Dimensions

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?