[futurebasic] Re: [FB] FBtoC: compile error: "invalid operands to binary" and other

Message: < previous - next > : Reply : Subscribe : Cleanse
Home   : February 2008 : Group Archive : Group : All Groups

From: Robert Purves <listrp@...>
Date: Tue, 19 Feb 2008 14:09:29 +1300
Brian Stevens wrote:

> This code was sent to me offlist with a request for help using with  
> FBtoC.
>
> The syntax:  var;length = address as used by:
> SpriteRect;8 = SpriteWorld +_portRect
> looked suspect because SpriteWorld is a handle and not pointer.
>
> The line of compile failure is:
> a = peek(alphaPixMapAddr+offset*4+1)
> which translates into:
> a = *(unsigned char*)(alphaPixMapAddr + offset * 4 + 1);
>
> '-----------------------------------
> local fn GenerateSpriteAlpha (SpriteWorld as handle, alphaWorld as  
> handle)
> dim @SpritePixMapH as handle
> dim @SpritePixMapAddr as long
> dim @alphaPixMapH as handle
> dim @alphaPixMapAddr as long
> dim @offset as handle ,r,g,b,a
> dim @x as short
> dim @y as short
> dim @SpriteRect as rect
>
> SpritePixMapH = fn GetGWorldPixMap (SpriteWorld)
> SpritePixMapAddr = fn GetPixBaseAddr (SpritePixMapH)
>
> alphaPixMapH = fn GetGWorldPixMap (alphaWorld)
> alphaPixMapAddr = fn GetPixBaseAddr (alphaPixMapH)
>
> SpriteRect;8 = SpriteWorld+_portRect
> for x = 0 to SpriteRect.right-1
> for y = 0 to SpriteRect.bottom-1
> offset = x+y*(SpriteRect.right+4)
> a = peek(alphaPixMapAddr+offset*4+1)
> poke SpritePixMapAddr+offset*4+4,a
> next y
> next x
> end fn

The function gives a flood of warnings from gcc because many of the  
variable and parameter declarations are wrong.
The compilation error, also due to a wrong type, can be reproduced by  
this program:
'---------
dim as Handle offset
offset = offset*4 // error: invalid operands to binary *
'---------
The reason for the error is simple: a Handle is a kind of address, and  
gcc knows that it is senseless to multiply an address by anything.


The rewrite of GenerateSpriteAlpha() below specifies its var types  
correctly, obtains spriteRect by a correct method, and is formatted  
according to modern convention.

'----------
local fn GenerateSpriteAlpha( spriteWorld as CGrafPtr, alphaWorld as  
CGrafPtr )
'~'1
dim spritePixMapH as Handle to PixMap
dim alphaPixMapH as Handle to PixMap
dim as pointer spritePixMapAddr, alphaPixMapAddr
dim as long offset
dim as short x, y
dim as Rect spriteRect
dim as unsigned byte a

spritePixMapH = fn GetGWorldPixMap( spriteWorld )
spritePixMapAddr = fn GetPixBaseAddr( spritePixMapH )
alphaPixMapH = fn GetGWorldPixMap( alphaWorld )
alphaPixMapAddr = fn GetPixBaseAddr( alphaPixMapH )
spriteRect = spritePixMapH..bounds
for x = 0 to spriteRect.right - 1
for y = 0 to spriteRect.bottom - 1
offset = x + y*(spriteRect.right + 4) // •• buggy
a = peek( alphaPixMapAddr + offset*4 + 1 ) // •• buggy
poke spritePixMapAddr + offset*4 + 4, a // •• buggy
next y
next x
end fn
'----------

It compiles cleanly. So it must be ready to rock-and-roll?
Well, not if you care about correctness. The inner loop will in  
general read and write outside the PixMap bounds.
It's not really possible to traverse a PixMap correctly without  
obtaining its rowBytes:
toolbox fn GetPixRowBytes( PixMapHandle pm ) = long
dim as long offset
rowBytes = fn GetPixRowBytes( spritePixMapH )

There's also an off-by-one error: the pixel component set in  
alphaWorld derives from not from the corresponding pixel in  
spriteWorld, but from its neighbour.

Robert P.