# include "fbcu.bi"
#include once "fbgfx.bi"

namespace fbc_tests.gfx.fb_image_expr

const TRUE = -1
const FALSE = 0

const SCREEN_W = 16
const SCREEN_H = 16

private function hScreenIsFilledWithColor( byval col as ulong ) as integer
	'' Assuming 32bit screen
	dim as integer w, h, depth, bpp, pitch
	screeninfo w, h, depth, bpp, pitch
	CU_ASSERT( w = SCREEN_W )
	CU_ASSERT( h = SCREEN_H )
	CU_ASSERT( depth = 32 )
	CU_ASSERT( bpp = 4 )
	CU_ASSERT( pitch = bpp*w )

	screenlock( )

	dim as ulong ptr p = screenptr( )
	CU_ASSERT( p <> NULL )

	function = TRUE
	for i as integer = 0 to (w * h)-1
		if( p[i] <> col ) then
			function = FALSE
			exit for
		end if
	next

	screenunlock( )
end function

private function hImageIsFilledWithColor( byval buffer as any ptr, byval col as ulong ) as integer
	dim as fb.IMAGE ptr img = buffer
	CU_ASSERT( img->width = SCREEN_W )
	CU_ASSERT( img->height = SCREEN_H )
	CU_ASSERT( img->bpp = 4 )
	CU_ASSERT( img->pitch = img->width * img->bpp )

	function = TRUE
	for i as integer = 0 to (img->width * img->height)-1
		if( cptr( ulong ptr, img + 1 )[i] <> col ) then
			function = FALSE
			exit for
		end if
	next
end function

private sub hResetImageToBlack( byval p as any ptr )
	line p, (0, 0) - (SCREEN_W-1, SCREEN_H-1), rgb(0,0,0), bf
	CU_ASSERT( hImageIsFilledWithColor( p, rgb(0,0,0) ) )
end sub

type ImageUdt1
	header as fb.IMAGE
	pixels(0 to (SCREEN_W*SCREEN_H)-1) as ulong  '' room for WxH 32bit pixels behind the header
end type

type SomeUdt1
	i as integer
	d as double
end type

type DerivedUdt1 extends SomeUdt1
	i as integer
	d as double
end type

type DerivedUdt2 extends object
	i as integer
	d as double
end type

type ByteUdtWithMatchingCast field = 1
	b as ubyte
	declare operator cast( ) as any ptr
end type

operator ByteUdtWithMatchingCast.cast( ) as any ptr
	operator = 0
end operator

const IMAGE_BUFFER_SIZE = sizeof(fb.IMAGE) + (SCREEN_W*SCREEN_H*4)

'' All the quirk gfx commands which have target/source image parameters
'' should work fine when they're used
private sub hTestAllGfxCommands( )
	dim as any ptr a = imagecreate( SCREEN_W, SCREEN_H, rgb(  0,0,0) )
	dim as any ptr b = imagecreate( SCREEN_W, SCREEN_H, rgb(255,0,0) )

	CU_ASSERT( hImageIsFilledWithColor( a, rgb(  0,0,0) ) )
	CU_ASSERT( hImageIsFilledWithColor( a, rgb(255,0,0) ) = FALSE )
	CU_ASSERT( hImageIsFilledWithColor( b, rgb(  0,0,0) ) = FALSE )
	CU_ASSERT( hImageIsFilledWithColor( b, rgb(255,0,0) ) )

	line a, (0, 0) - (SCREEN_W-1, SCREEN_H-1), rgb(255,0,0), bf
	CU_ASSERT( hImageIsFilledWithColor( a, rgb(255,0,0) ) )
	hResetImageToBlack( a )

	pset a, (0, 0), rgb(255,0,0)
	CU_ASSERT( hImageIsFilledWithColor( a, rgb(0,0,0) ) = FALSE )
	hResetImageToBlack( a )

	circle a, (0, 0), 2, rgb(255,0,0)
	CU_ASSERT( hImageIsFilledWithColor( a, rgb(0,0,0) ) = FALSE )
	hResetImageToBlack( a )

	paint a, (0, 0), rgb(255,0,0), rgb(255,255,255)
	CU_ASSERT( hImageIsFilledWithColor( a, rgb(255,0,0) ) )
	hResetImageToBlack( a )

	draw string a, (0, 0), "testing", rgb(255,0,0)
	CU_ASSERT( hImageIsFilledWithColor( a, rgb(0,0,0) ) = FALSE )
	hResetImageToBlack( a )

	'' TODO: Draw String custom font image

	draw a, "BM 0,0 P " & rgb(255,0,0) & "," & rgb(255,255,255)
	CU_ASSERT( hImageIsFilledWithColor( a, rgb(255,0,0) ) )
	hResetImageToBlack( a )

	'' TODO: Palette Using

	CU_ASSERT( hImageIsFilledWithColor( b, rgb(255,0,0) ) )
	put a, (0, 0), b, pset
	CU_ASSERT( hImageIsFilledWithColor( b, rgb(255,0,0) ) )
	CU_ASSERT( hImageIsFilledWithColor( a, rgb(255,0,0) ) )
	hResetImageToBlack( a )

	get b, (0, 0) - (SCREEN_W-1, SCREEN_H-1), a
	CU_ASSERT( hImageIsFilledWithColor( a, rgb(255,0,0) ) )
	hResetImageToBlack( a )

	CU_ASSERT( point( 0, 0, b ) = rgb(255,0,0) )

	imagedestroy( b )
	imagedestroy( a )
end sub

private sub hTestPointerTypes( )
	'' The target/source image expressions could be any pointer,
	'' the compiler does no type checking
	#macro checkType( T )
		scope
			dim as T ptr a = imagecreate( SCREEN_W, SCREEN_H, rgb(0,0,0) )
			CU_ASSERT( hImageIsFilledWithColor( a, rgb(0,0,0) ) )

			line a, (0, 0) - (SCREEN_W-1, SCREEN_H-1), rgb(255,0,0), bf
			CU_ASSERT( hImageIsFilledWithColor( a, rgb(255,0,0) ) )

			imagedestroy( a )
		end scope
	#endmacro

	'' Should definitely work (since imagecreate returns an ANY PTR currently):
	checkType( any )

	'' Should probably work while there's no real type safety for the image parameters:
	checkType( byte )
	checkType( ubyte )
	checkType( short )
	checkType( ushort )
	checkType( long )
	checkType( ulong )
	checkType( longint )
	checkType( ulongint )
	checkType( integer )
	checkType( uinteger )

	'' Questionable:
	checkType( single )
	checkType( double )
	checkType( string )
	checkType( zstring )
	checkType( wstring )

	'' UDT pointers have to work too, because currently fb.IMAGE is just another UDT, not a built-in:
	checkType( fb.IMAGE )
	checkType( ImageUdt1 )
	checkType( SomeUdt1 )
	checkType( DerivedUdt1 )
	checkType( DerivedUdt2 )
end sub

'' We support arrays instead of dynamically allocated image buffers too,
'' probably due to QB compatibility.
private sub hTestArrayTarget( )
	'' array on stack:
	scope
		dim array(0 to IMAGE_BUFFER_SIZE-1) as ubyte
		scope
			var a = imagecreate( SCREEN_W, SCREEN_H, rgb(0,0,0) )
			memcpy( @array(0), a, IMAGE_BUFFER_SIZE )
			imagedestroy( a )
		end scope
		CU_ASSERT( hImageIsFilledWithColor( @array(0), rgb(0,0,0) ) )

		'' NIDXARRAY
		line array, (0, 0) - (SCREEN_W-1, SCREEN_H-1), rgb(255,0,0), bf
		CU_ASSERT( hImageIsFilledWithColor( @array(0), rgb(255,0,0) ) )

		'' array(0)
		line array(0), (0, 0) - (SCREEN_W-1, SCREEN_H-1), rgb(0,0,255), bf
		CU_ASSERT( hImageIsFilledWithColor( @array(0), rgb(0,0,255) ) )

		'' @array(0)
		line @array(0), (0, 0) - (SCREEN_W-1, SCREEN_H-1), rgb(255,0,0), bf
		CU_ASSERT( hImageIsFilledWithColor( @array(0), rgb(255,0,0) ) )
	end scope

	'' array on heap:
	scope
		static array(0 to IMAGE_BUFFER_SIZE-1) as ubyte
		scope
			var a = imagecreate( SCREEN_W, SCREEN_H, rgb(0,0,0) )
			memcpy( @array(0), a, IMAGE_BUFFER_SIZE )
			imagedestroy( a )
		end scope
		CU_ASSERT( hImageIsFilledWithColor( @array(0), rgb(0,0,0) ) )

		'' NIDXARRAY
		line array, (0, 0) - (SCREEN_W-1, SCREEN_H-1), rgb(255,0,0), bf
		CU_ASSERT( hImageIsFilledWithColor( @array(0), rgb(255,0,0) ) )

		'' array(0)
		line array(0), (0, 0) - (SCREEN_W-1, SCREEN_H-1), rgb(0,0,255), bf
		CU_ASSERT( hImageIsFilledWithColor( @array(0), rgb(0,0,255) ) )

		'' @array(0)
		line @array(0), (0, 0) - (SCREEN_W-1, SCREEN_H-1), rgb(255,0,0), bf
		CU_ASSERT( hImageIsFilledWithColor( @array(0), rgb(255,0,0) ) )
	end scope

	'' dynamic array, descriptor on stack:
	scope
		redim array(0 to IMAGE_BUFFER_SIZE-1) as ubyte
		scope
			var a = imagecreate( SCREEN_W, SCREEN_H, rgb(0,0,0) )
			memcpy( @array(0), a, IMAGE_BUFFER_SIZE )
			imagedestroy( a )
		end scope
		CU_ASSERT( hImageIsFilledWithColor( @array(0), rgb(0,0,0) ) )

		'' NIDXARRAY
		line array, (0, 0) - (SCREEN_W-1, SCREEN_H-1), rgb(255,0,0), bf
		CU_ASSERT( hImageIsFilledWithColor( @array(0), rgb(255,0,0) ) )

		'' array(0)
		line array(0), (0, 0) - (SCREEN_W-1, SCREEN_H-1), rgb(0,0,255), bf
		CU_ASSERT( hImageIsFilledWithColor( @array(0), rgb(0,0,255) ) )

		'' @array(0)
		line @array(0), (0, 0) - (SCREEN_W-1, SCREEN_H-1), rgb(255,0,0), bf
		CU_ASSERT( hImageIsFilledWithColor( @array(0), rgb(255,0,0) ) )
	end scope

	'' array field:
	scope
		type UDT
			array(0 to IMAGE_BUFFER_SIZE-1) as ubyte
		end type
		dim udt as UDT
		dim pudt as UDT ptr = @udt
		scope
			var a = imagecreate( SCREEN_W, SCREEN_H, rgb(0,0,0) )
			memcpy( pudt, a, IMAGE_BUFFER_SIZE )
			imagedestroy( a )
		end scope

		'' pudt->array
		line pudt->array, (0, 0) - (SCREEN_W-1, SCREEN_H-1), rgb(255,0,0), bf
		CU_ASSERT( hImageIsFilledWithColor( @pudt->array(0), rgb(255,0,0) ) )

		'' pudt->array(0)
		line pudt->array(0), (0, 0) - (SCREEN_W-1, SCREEN_H-1), rgb(255,0,0), bf
		CU_ASSERT( hImageIsFilledWithColor( @pudt->array(0), rgb(255,0,0) ) )

		'' @pudt->array(0)
		line @pudt->array(0), (0, 0) - (SCREEN_W-1, SCREEN_H-1), rgb(255,0,0), bf
		CU_ASSERT( hImageIsFilledWithColor( @pudt->array(0), rgb(255,0,0) ) )
	end scope
end sub

private sub hTestPtrArrayTarget( )
	'' An array access (excluding NIDXARRAY) with pointer type however is
	'' treated like any other pointer expression - i.e. the image is written
	'' into the pointed-to address, not into the array.
	scope
		dim array(0 to 1) as any ptr
		array(0) = imagecreate( SCREEN_W, SCREEN_H, rgb(0,0,0) )
		CU_ASSERT( hImageIsFilledWithColor( array(0), rgb(0,0,0) ) )

		'' array(0)
		line array(0), (0, 0) - (SCREEN_W-1, SCREEN_H-1), rgb(0,0,255), bf
		CU_ASSERT( hImageIsFilledWithColor( array(0), rgb(0,0,255) ) )

		'' GET into pointer from array access
		get (0, 0) - (SCREEN_W-1, SCREEN_H-1), array(0)
		CU_ASSERT( hImageIsFilledWithColor( array(0), rgb(0,255,0) ) )

		imagedestroy( array(0) )
	end scope

	'' NIDXARRAY: The image data is still stored into the array,
	'' regardless of what the array's dtype is.
	scope
		dim array(0 to (IMAGE_BUFFER_SIZE\sizeof(any ptr))-1) as any ptr

		get (0, 0) - (SCREEN_W-1, SCREEN_H-1), array
		CU_ASSERT( hImageIsFilledWithColor( @array(0), rgb(0,255,0) ) )

		line array, (0, 0) - (SCREEN_W-1, SCREEN_H-1), rgb(0,0,255), bf
		CU_ASSERT( hImageIsFilledWithColor( @array(0), rgb(0,0,255) ) )
	end scope

	'' @array(0): The type is an ANY PTR PTR which should be accepted too.
	scope
		dim array(0 to (IMAGE_BUFFER_SIZE\sizeof(any ptr))-1) as any ptr

		get (0, 0) - (SCREEN_W-1, SCREEN_H-1), @array(0)
		CU_ASSERT( hImageIsFilledWithColor( @array(0), rgb(0,255,0) ) )

		line @array(0), (0, 0) - (SCREEN_W-1, SCREEN_H-1), rgb(0,0,255), bf
		CU_ASSERT( hImageIsFilledWithColor( @array(0), rgb(0,0,255) ) )
	end scope

	'' @udt.array(0): Same as @array(0)
	scope
		type UDT
			array(0 to (IMAGE_BUFFER_SIZE\sizeof(any ptr))-1) as any ptr
		end type
		dim udt as UDT

		get (0, 0) - (SCREEN_W-1, SCREEN_H-1), @udt.array(0)
		CU_ASSERT( hImageIsFilledWithColor( @udt.array(0), rgb(0,255,0) ) )

		line @udt.array(0), (0, 0) - (SCREEN_W-1, SCREEN_H-1), rgb(0,0,255), bf
		CU_ASSERT( hImageIsFilledWithColor( @udt.array(0), rgb(0,0,255) ) )
	end scope
end sub

private sub hTestUdtWithoutMatchingCastArrayTarget( )
	type UDT field = 1
		b as ubyte
	end type

	dim array(0 to IMAGE_BUFFER_SIZE-1) as UDT

	'' These cases should work despite the UDT not having a cast() overload

	'' NIDXARRAY
	get (0, 0) - (SCREEN_W-1, SCREEN_H-1), array
	CU_ASSERT( hImageIsFilledWithColor( @array(0), rgb(0,255,0) ) )

	'' array(0)
	get (0, 0) - (SCREEN_W-1, SCREEN_H-1), array(0)
	CU_ASSERT( hImageIsFilledWithColor( @array(0), rgb(0,255,0) ) )

	'' @array(0)
	get (0, 0) - (SCREEN_W-1, SCREEN_H-1), @array(0)
	CU_ASSERT( hImageIsFilledWithColor( @array(0), rgb(0,255,0) ) )
end sub

private sub hTestUdtWithMatchingCastArrayTarget( )
	dim array(0 to IMAGE_BUFFER_SIZE-1) as ByteUdtWithMatchingCast

	'' The cast() overload shouldn't be used in these cases

	'' NIDXARRAY
	get (0, 0) - (SCREEN_W-1, SCREEN_H-1), array
	CU_ASSERT( hImageIsFilledWithColor( @array(0), rgb(0,255,0) ) )

	'' @array(0)
	get (0, 0) - (SCREEN_W-1, SCREEN_H-1), @array(0)
	CU_ASSERT( hImageIsFilledWithColor( @array(0), rgb(0,255,0) ) )
end sub

'' GET from screen into some array...
private sub hTestGetIntoUByteArray( )
	'' NIDXARRAY, array on stack
	scope
		dim array(0 to IMAGE_BUFFER_SIZE-1) as ubyte
		get (0, 0) - (SCREEN_W-1, SCREEN_H-1), array
		CU_ASSERT( hImageIsFilledWithColor( @array(0), rgb(0,255,0) ) )
	end scope

	'' NIDXARRAY, array on heap
	scope
		static array(0 to IMAGE_BUFFER_SIZE-1) as ubyte
		get (0, 0) - (SCREEN_W-1, SCREEN_H-1), array
		CU_ASSERT( hImageIsFilledWithColor( @array(0), rgb(0,255,0) ) )
	end scope

	'' NIDXARRAY, dynamic array, descriptor on stack
	scope
		redim array(0 to IMAGE_BUFFER_SIZE-1) as ubyte
		get (0, 0) - (SCREEN_W-1, SCREEN_H-1), array
		CU_ASSERT( hImageIsFilledWithColor( @array(0), rgb(0,255,0) ) )
	end scope

	'' array(0)
	scope
		dim array(0 to IMAGE_BUFFER_SIZE-1) as ubyte
		get (0, 0) - (SCREEN_W-1, SCREEN_H-1), array(0)
		CU_ASSERT( hImageIsFilledWithColor( @array(0), rgb(0,255,0) ) )
	end scope

	'' array(1)
	scope
		dim array(0 to IMAGE_BUFFER_SIZE+1-1) as ubyte
		get (0, 0) - (SCREEN_W-1, SCREEN_H-1), array(1)
		CU_ASSERT( hImageIsFilledWithColor( @array(1), rgb(0,255,0) ) )
	end scope

	'' array(i)
	scope
		dim array(0 to IMAGE_BUFFER_SIZE+50-1) as ubyte
		var i = 50
		get (0, 0) - (SCREEN_W-1, SCREEN_H-1), array(i)
		CU_ASSERT( hImageIsFilledWithColor( @array(i), rgb(0,255,0) ) )
	end scope

	'' @array(0)
	scope
		dim array(0 to IMAGE_BUFFER_SIZE-1) as ubyte
		get (0, 0) - (SCREEN_W-1, SCREEN_H-1), @array(0)
		CU_ASSERT( hImageIsFilledWithColor( @array(0), rgb(0,255,0) ) )
	end scope

	'' @array(1)
	scope
		dim array(0 to IMAGE_BUFFER_SIZE+1-1) as ubyte
		get (0, 0) - (SCREEN_W-1, SCREEN_H-1), @array(1)
		CU_ASSERT( hImageIsFilledWithColor( @array(1), rgb(0,255,0) ) )
	end scope

	'' @array(i)
	scope
		dim array(0 to IMAGE_BUFFER_SIZE+50-1) as ubyte
		var i = 50
		get (0, 0) - (SCREEN_W-1, SCREEN_H-1), @array(i)
		CU_ASSERT( hImageIsFilledWithColor( @array(i), rgb(0,255,0) ) )
	end scope

	'' udt.array(0)
	scope
		type UDT
			array(0 to IMAGE_BUFFER_SIZE-1) as ubyte
		end type
		dim udt as UDT
		get (0, 0) - (SCREEN_W-1, SCREEN_H-1), udt.array(0)
		CU_ASSERT( hImageIsFilledWithColor( @udt.array(0), rgb(0,255,0) ) )
	end scope

	'' udt.array(1)
	scope
		type UDT
			array(0 to IMAGE_BUFFER_SIZE+1-1) as ubyte
		end type
		dim udt as UDT
		get (0, 0) - (SCREEN_W-1, SCREEN_H-1), udt.array(1)
		CU_ASSERT( hImageIsFilledWithColor( @udt.array(1), rgb(0,255,0) ) )
	end scope

	'' udt.array(i)
	scope
		type UDT
			array(0 to IMAGE_BUFFER_SIZE+50-1) as ubyte
		end type
		dim udt as UDT
		var i = 50
		get (0, 0) - (SCREEN_W-1, SCREEN_H-1), udt.array(i)
		CU_ASSERT( hImageIsFilledWithColor( @udt.array(i), rgb(0,255,0) ) )
	end scope

	'' @udt.array(0)
	scope
		type UDT
			array(0 to IMAGE_BUFFER_SIZE-1) as ubyte
		end type
		dim udt as UDT
		get (0, 0) - (SCREEN_W-1, SCREEN_H-1), @udt.array(0)
		CU_ASSERT( hImageIsFilledWithColor( @udt.array(0), rgb(0,255,0) ) )
	end scope

	'' @udt.array(1)
	scope
		type UDT
			array(0 to IMAGE_BUFFER_SIZE+1-1) as ubyte
		end type
		dim udt as UDT
		get (0, 0) - (SCREEN_W-1, SCREEN_H-1), @udt.array(1)
		CU_ASSERT( hImageIsFilledWithColor( @udt.array(1), rgb(0,255,0) ) )
	end scope

	'' @udt.array(i)
	scope
		type UDT
			array(0 to IMAGE_BUFFER_SIZE+50-1) as ubyte
		end type
		dim udt as UDT
		var i = 50
		get (0, 0) - (SCREEN_W-1, SCREEN_H-1), @udt.array(i)
		CU_ASSERT( hImageIsFilledWithColor( @udt.array(i), rgb(0,255,0) ) )
	end scope
end sub

private sub hTestGetIntoULongArray( )
	'' NIDXARRAY, array on stack
	scope
		dim array(0 to (IMAGE_BUFFER_SIZE\4)-1) as ulong
		get (0, 0) - (SCREEN_W-1, SCREEN_H-1), array
		CU_ASSERT( hImageIsFilledWithColor( @array(0), rgb(0,255,0) ) )
	end scope

	'' NIDXARRAY, array on heap
	scope
		static array(0 to (IMAGE_BUFFER_SIZE\4)-1) as ulong
		get (0, 0) - (SCREEN_W-1, SCREEN_H-1), array
		CU_ASSERT( hImageIsFilledWithColor( @array(0), rgb(0,255,0) ) )
	end scope

	'' NIDXARRAY, dynamic array, descriptor on stack
	scope
		redim array(0 to (IMAGE_BUFFER_SIZE\4)-1) as ulong
		get (0, 0) - (SCREEN_W-1, SCREEN_H-1), array
		CU_ASSERT( hImageIsFilledWithColor( @array(0), rgb(0,255,0) ) )
	end scope

	'' array(0)
	scope
		dim array(0 to (IMAGE_BUFFER_SIZE\4)-1) as ulong
		get (0, 0) - (SCREEN_W-1, SCREEN_H-1), array(0)
		CU_ASSERT( hImageIsFilledWithColor( @array(0), rgb(0,255,0) ) )
	end scope

	'' array(1)
	scope
		dim array(0 to (IMAGE_BUFFER_SIZE\4)+1-1) as ulong
		get (0, 0) - (SCREEN_W-1, SCREEN_H-1), array(1)
		CU_ASSERT( hImageIsFilledWithColor( @array(1), rgb(0,255,0) ) )
	end scope

	'' array(i)
	scope
		dim array(0 to (IMAGE_BUFFER_SIZE\4)+50-1) as ulong
		var i = 50
		get (0, 0) - (SCREEN_W-1, SCREEN_H-1), array(i)
		CU_ASSERT( hImageIsFilledWithColor( @array(i), rgb(0,255,0) ) )
	end scope

	'' @array(0)
	scope
		dim array(0 to (IMAGE_BUFFER_SIZE\4)-1) as ulong
		get (0, 0) - (SCREEN_W-1, SCREEN_H-1), @array(0)
		CU_ASSERT( hImageIsFilledWithColor( @array(0), rgb(0,255,0) ) )
	end scope

	'' @array(1)
	scope
		dim array(0 to (IMAGE_BUFFER_SIZE\4)+1-1) as ulong
		get (0, 0) - (SCREEN_W-1, SCREEN_H-1), @array(1)
		CU_ASSERT( hImageIsFilledWithColor( @array(1), rgb(0,255,0) ) )
	end scope

	'' @array(i)
	scope
		dim array(0 to (IMAGE_BUFFER_SIZE\4)+50-1) as ulong
		var i = 50
		get (0, 0) - (SCREEN_W-1, SCREEN_H-1), @array(i)
		CU_ASSERT( hImageIsFilledWithColor( @array(i), rgb(0,255,0) ) )
	end scope

	'' udt.array(0)
	scope
		type UDT
			array(0 to (IMAGE_BUFFER_SIZE\4)-1) as ulong
		end type
		dim udt as UDT
		get (0, 0) - (SCREEN_W-1, SCREEN_H-1), udt.array(0)
		CU_ASSERT( hImageIsFilledWithColor( @udt.array(0), rgb(0,255,0) ) )
	end scope

	'' udt.array(1)
	scope
		type UDT
			array(0 to (IMAGE_BUFFER_SIZE\4)+1-1) as ulong
		end type
		dim udt as UDT
		get (0, 0) - (SCREEN_W-1, SCREEN_H-1), udt.array(1)
		CU_ASSERT( hImageIsFilledWithColor( @udt.array(1), rgb(0,255,0) ) )
	end scope

	'' udt.array(i)
	scope
		type UDT
			array(0 to (IMAGE_BUFFER_SIZE\4)+50-1) as ulong
		end type
		dim udt as UDT
		var i = 50
		get (0, 0) - (SCREEN_W-1, SCREEN_H-1), udt.array(i)
		CU_ASSERT( hImageIsFilledWithColor( @udt.array(i), rgb(0,255,0) ) )
	end scope

	'' @udt.array(0)
	scope
		type UDT
			array(0 to (IMAGE_BUFFER_SIZE\4)-1) as ulong
		end type
		dim udt as UDT
		get (0, 0) - (SCREEN_W-1, SCREEN_H-1), @udt.array(0)
		CU_ASSERT( hImageIsFilledWithColor( @udt.array(0), rgb(0,255,0) ) )
	end scope

	'' @udt.array(1)
	scope
		type UDT
			array(0 to (IMAGE_BUFFER_SIZE\4)+1-1) as ulong
		end type
		dim udt as UDT
		get (0, 0) - (SCREEN_W-1, SCREEN_H-1), @udt.array(1)
		CU_ASSERT( hImageIsFilledWithColor( @udt.array(1), rgb(0,255,0) ) )
	end scope

	'' @udt.array(i)
	scope
		type UDT
			array(0 to (IMAGE_BUFFER_SIZE\4)+50-1) as ulong
		end type
		dim udt as UDT
		var i = 50
		get (0, 0) - (SCREEN_W-1, SCREEN_H-1), @udt.array(i)
		CU_ASSERT( hImageIsFilledWithColor( @udt.array(i), rgb(0,255,0) ) )
	end scope
end sub

private sub hTestFieldTarget( )
	type UDT
		p as fb.IMAGE ptr
	end type
	dim x as UDT
	var px = @x

	x.p = imagecreate( SCREEN_W, SCREEN_H, rgb(0,0,0) )
	CU_ASSERT( hImageIsFilledWithColor( x.p, rgb(0,0,0) ) )

	'' x.p
	line x.p, (0, 0) - (SCREEN_W-1, SCREEN_H-1), rgb(255,0,0), bf
	CU_ASSERT( hImageIsFilledWithColor( x.p, rgb(255,0,0) ) )

	'' px->p
	line px->p, (0, 0) - (SCREEN_W-1, SCREEN_H-1), rgb(0,0,255), bf
	CU_ASSERT( hImageIsFilledWithColor( x.p, rgb(0,0,255) ) )
end sub

private sub hTestConstSource( )
	CU_ASSERT( hScreenIsFilledWithColor( rgb(0,255,0) ) )

	dim a as const FB.IMAGE ptr = imagecreate( SCREEN_W, SCREEN_H, rgb(0,0,0) )
	put (0, 0), a, pset
	CU_ASSERT( hScreenIsFilledWithColor( rgb(0,0,0) ) )
	imagedestroy( a )

	line (0, 0) - (SCREEN_W-1, SCREEN_H-1), rgb(0,255,0), bf
	CU_ASSERT( hScreenIsFilledWithColor( rgb(0,255,0) ) )
end sub

type PropertyUdt
	gets as integer
	sets as integer
	p as any ptr
	declare property image() as any ptr
	declare property image(byval as any ptr)
end type

property PropertyUdt.image() as any ptr
	gets += 1
	property = p
end property

property PropertyUdt.image(byval p as any ptr)
	sets += 1
	this.p = p
end property

private sub hTestProperty( )
	dim x as PropertyUdt
	x.p = imagecreate( SCREEN_W, SCREEN_H, rgb(0,0,0) )
	CU_ASSERT( hImageIsFilledWithColor( x.p, rgb(0,0,0) ) )

	CU_ASSERT( x.sets = 0 )
	CU_ASSERT( x.gets = 0 )

	line x.image, (0, 0) - (SCREEN_W-1, SCREEN_H-1), rgb(255,0,0), bf
	CU_ASSERT( hImageIsFilledWithColor( x.p, rgb(255,0,0) ) )

	CU_ASSERT( x.sets = 0 )
	CU_ASSERT( x.gets = 1 )

	CU_ASSERT( hScreenIsFilledWithColor( rgb(0,255,0) ) )
	put (0, 0), x.image, pset
	CU_ASSERT( hScreenIsFilledWithColor( rgb(255,0,0) ) )
	line (0, 0) - (SCREEN_W-1, SCREEN_H-1), rgb(0,255,0), bf

	CU_ASSERT( x.sets = 0 )
	CU_ASSERT( x.gets = 2 )

	imagedestroy( x.p )
end sub

namespace castOverloadAnyPtr
	dim shared as integer casts_anyptr

	type UDT
		p as any ptr
		declare operator cast( ) as any ptr
	end type

	operator UDT.cast( ) as any ptr
		casts_anyptr += 1
		operator = p
	end operator

	private sub hTest( )
		dim x as UDT
		x.p = imagecreate( SCREEN_W, SCREEN_H, rgb(255,0,0) )
		CU_ASSERT( hImageIsFilledWithColor( x.p, rgb(255,0,0) ) )

		CU_ASSERT( casts_anyptr = 0 )
		line x, (0, 0) - (SCREEN_W-1, SCREEN_H-1), rgb(0,0,255), bf
		CU_ASSERT( casts_anyptr = 1 )
		CU_ASSERT( hImageIsFilledWithColor( x.p, rgb(0,0,255) ) )

		imagedestroy( x.p )
	end sub
end namespace

namespace castOverloadFbImagePtr
	dim shared as integer casts_fbimageptr

	type UDT
		p as any ptr
		declare operator cast( ) as FB.IMAGE ptr
	end type

	operator UDT.cast( ) as FB.IMAGE ptr
		casts_fbimageptr += 1
		operator = p
	end operator

	private sub hTest( )
		dim x as UDT
		x.p = imagecreate( SCREEN_W, SCREEN_H, rgb(255,0,0) )
		CU_ASSERT( hImageIsFilledWithColor( x.p, rgb(255,0,0) ) )

		CU_ASSERT( casts_fbimageptr = 0 )
		line x, (0, 0) - (SCREEN_W-1, SCREEN_H-1), rgb(0,0,255), bf
		CU_ASSERT( casts_fbimageptr = 1 )
		CU_ASSERT( hImageIsFilledWithColor( x.p, rgb(0,0,255) ) )

		imagedestroy( x.p )
	end sub
end namespace

namespace castOverloadAnyPtrFbImagePtr
	dim shared as integer casts_anyptr, casts_fbimageptr

	type UDT
		p as any ptr
		declare operator cast( ) as any ptr
		declare operator cast( ) as FB.IMAGE ptr
	end type

	operator UDT.cast( ) as any ptr
		casts_anyptr += 1
		operator = p
	end operator

	operator UDT.cast( ) as FB.IMAGE ptr
		casts_fbimageptr += 1
		operator = p
	end operator

	private sub hTest( )
		dim x as UDT
		x.p = imagecreate( SCREEN_W, SCREEN_H, rgb(255,0,0) )
		CU_ASSERT( hImageIsFilledWithColor( x.p, rgb(255,0,0) ) )

		CU_ASSERT( casts_anyptr = 0 )
		CU_ASSERT( casts_fbimageptr = 0 )
		line x, (0, 0) - (SCREEN_W-1, SCREEN_H-1), rgb(0,0,255), bf
		CU_ASSERT( casts_anyptr = 1 )
		CU_ASSERT( casts_fbimageptr = 0 )
		CU_ASSERT( hImageIsFilledWithColor( x.p, rgb(0,0,255) ) )

		imagedestroy( x.p )
	end sub
end namespace

namespace castOverloadAnyPtrInteger
	dim shared as integer casts_anyptr, casts_integer

	type UDT
		p as any ptr
		declare operator cast( ) as any ptr
		declare operator cast( ) as integer
	end type

	operator UDT.cast( ) as any ptr
		casts_anyptr += 1
		operator = p
	end operator

	operator UDT.cast( ) as integer
		casts_integer += 1
		operator = 0
	end operator

	private sub hTest( )
		dim x as UDT
		x.p = imagecreate( SCREEN_W, SCREEN_H, rgb(255,0,0) )
		CU_ASSERT( hImageIsFilledWithColor( x.p, rgb(255,0,0) ) )

		CU_ASSERT( casts_anyptr = 0 )
		CU_ASSERT( casts_integer = 0 )
		line x, (0, 0) - (SCREEN_W-1, SCREEN_H-1), rgb(0,0,255), bf
		CU_ASSERT( casts_anyptr = 1 )
		CU_ASSERT( casts_integer = 0 )
		CU_ASSERT( hImageIsFilledWithColor( x.p, rgb(0,0,255) ) )

		imagedestroy( x.p )
	end sub
end namespace

private sub hTestDrawSyntax( )
	scope
		CU_ASSERT( hScreenIsFilledWithColor( rgb(0,255,0) ) )
		draw "BM 0,0 P " & rgb(0,0,255) & "," & rgb(255,255,255)
		CU_ASSERT( hScreenIsFilledWithColor( rgb(0,0,255) ) )
		line (0, 0) - (SCREEN_W-1, SCREEN_H-1), rgb(0,255,0), bf
	end scope

	scope
		var s = "BM 0,0 P " & rgb(0,0,255) & "," & rgb(255,255,255)
		CU_ASSERT( hScreenIsFilledWithColor( rgb(0,255,0) ) )
		draw s
		CU_ASSERT( hScreenIsFilledWithColor( rgb(0,0,255) ) )
		line (0, 0) - (SCREEN_W-1, SCREEN_H-1), rgb(0,255,0), bf
	end scope

	scope
		dim s(0 to 0) as string = { "BM 0,0 P " & rgb(0,0,255) & "," & rgb(255,255,255) }
		CU_ASSERT( hScreenIsFilledWithColor( rgb(0,255,0) ) )
		draw s(0)
		CU_ASSERT( hScreenIsFilledWithColor( rgb(0,0,255) ) )
		line (0, 0) - (SCREEN_W-1, SCREEN_H-1), rgb(0,255,0), bf
	end scope

	scope
		type UDT
			p as any ptr
		end type
		dim x as UDT
		var px = @x
		var p = imagecreate( SCREEN_W, SCREEN_H, rgb(255,0,0) )
		x.p = p
		dim array(0 to 0) as any ptr = { p }

		CU_ASSERT( hImageIsFilledWithColor( p, rgb(255,0,0) ) )
		draw p, "BM 0,0 P " & rgb(0,255,0) & "," & rgb(255,255,255)
		CU_ASSERT( hImageIsFilledWithColor( p, rgb(0,255,0) ) )
		line p, (0, 0) - (SCREEN_W-1, SCREEN_H-1), rgb(255,0,0), bf

		CU_ASSERT( hImageIsFilledWithColor( p, rgb(255,0,0) ) )
		draw x.p, "BM 0,0 P " & rgb(0,255,0) & "," & rgb(255,255,255)
		CU_ASSERT( hImageIsFilledWithColor( p, rgb(0,255,0) ) )
		line p, (0, 0) - (SCREEN_W-1, SCREEN_H-1), rgb(255,0,0), bf

		CU_ASSERT( hImageIsFilledWithColor( p, rgb(255,0,0) ) )
		draw px->p, "BM 0,0 P " & rgb(0,255,0) & "," & rgb(255,255,255)
		CU_ASSERT( hImageIsFilledWithColor( p, rgb(0,255,0) ) )
		line p, (0, 0) - (SCREEN_W-1, SCREEN_H-1), rgb(255,0,0), bf

		imagedestroy( p )
	end scope

	scope
		dim array(0 to IMAGE_BUFFER_SIZE-1) as ubyte
		scope
			var a = imagecreate( SCREEN_W, SCREEN_H, rgb(255,0,0) )
			memcpy( @array(0), a, IMAGE_BUFFER_SIZE )
			imagedestroy( a )
		end scope
		CU_ASSERT( hImageIsFilledWithColor( @array(0), rgb(255,0,0) ) )

		'' NIDXARRAY
		CU_ASSERT( hImageIsFilledWithColor( @array(0), rgb(255,0,0) ) )
		draw array, "BM 0,0 P " & rgb(0,255,0) & "," & rgb(255,255,255)
		CU_ASSERT( hImageIsFilledWithColor( @array(0), rgb(0,255,0) ) )
		line array, (0, 0) - (SCREEN_W-1, SCREEN_H-1), rgb(255,0,0), bf

		'' array(0)
		CU_ASSERT( hImageIsFilledWithColor( @array(0), rgb(255,0,0) ) )
		draw array(0), "BM 0,0 P " & rgb(0,255,0) & "," & rgb(255,255,255)
		CU_ASSERT( hImageIsFilledWithColor( @array(0), rgb(0,255,0) ) )
		line array, (0, 0) - (SCREEN_W-1, SCREEN_H-1), rgb(255,0,0), bf

		'' @array(0)
		CU_ASSERT( hImageIsFilledWithColor( @array(0), rgb(255,0,0) ) )
		draw @array(0), "BM 0,0 P " & rgb(0,255,0) & "," & rgb(255,255,255)
		CU_ASSERT( hImageIsFilledWithColor( @array(0), rgb(0,255,0) ) )
		line array, (0, 0) - (SCREEN_W-1, SCREEN_H-1), rgb(255,0,0), bf
	end scope
end sub

private sub test cdecl( )
	CU_ASSERT( screenres( SCREEN_W, SCREEN_H, 32, , fb.GFX_NULL ) = 0 )

	line (0, 0) - (SCREEN_W-1, SCREEN_H-1), rgb(0,255,0), bf
	CU_ASSERT( hScreenIsFilledWithColor( rgb(0,255,0) ) )
	CU_ASSERT( hScreenIsFilledWithColor( rgb(0,0,0) ) = FALSE )

	hTestAllGfxCommands( )
	hTestPointerTypes( )
	hTestArrayTarget( )
	hTestPtrArrayTarget( )
	hTestUdtWithoutMatchingCastArrayTarget( )
	hTestUdtWithMatchingCastArrayTarget( )
	hTestGetIntoUByteArray( )
	hTestGetIntoULongArray( )
	hTestFieldTarget( )
	hTestConstSource( )
	hTestProperty( )
	castOverloadAnyPtr.hTest( )
	castOverloadFbImagePtr.hTest( )
	castOverloadAnyPtrFbImagePtr.hTest( )
	castOverloadAnyPtrInteger.hTest( )
	hTestDrawSyntax( )
end sub

private sub ctor( ) constructor
	fbcu.add_suite( "tests/gfx/fb-image-expr" )
	fbcu.add_test( "1", @test )
end sub

end namespace
