
//2D图形引擎

//注意事项:
//*  Z8*Z8容易溢出

//初版: 2013年5月
//实现图标的创建 旋转和显示

//V1: 2013年7月17日
//把接口参数(坐标)从Z16改为Z32,按照库的编写规则规范化
//修正了图标装载的BUG,避免Z8*Z8的溢出

//V1: 2014年1月9日
//源代码改为标准C语言格式


unit GUI
{
	//[i] linkinterface_map map;
	public link unit map {}
	
	//[i] var_int16 Line;
	public int16 Line;
	//[i] var_int16 Column;
	public int16 Column;
	
	//[i] struct icon;
	public struct icon
	{
		int8 Line;
		int8 Column;
		[uint8*?] buffer;
	}
	//[i] linkconst_int16_200 BufferLength;
	public const int16 BufferLength = 200;
	[uint8*BufferLength] icon_buffer;
	int16 HeapStart;
	
	//---------------------------------------------------
	//[i] function_void OS_init;
	public void OS_init()
	{
		Line = map.LineNumber;
		Column = map.AreaNumber * 8;
		HeapStart = 0;
	}
	//---------------------------------------------------
	//[i] function_void Clear;
	public void Clear()
	{
		map.Clear();
	}
	//---------------------------------------------------
	//[i] function_bitmap NewIcon int32 int32;
	public struct icon NewIcon( int32 l, int32 c )
	{
		->struct icon temp -> icon_buffer[HeapStart];
		temp.Line = (int8)(int16)l;
		temp.Column = (int8)(int16)c;
		
		HeapStart + (int16)(2 + l * (c / 8));
		return temp;
	}
	//---------------------------------------------------
	//[i] function_void LoadIcon bitmap bitmap;
	public void LoadIcon( [#.code uint8*?] buffer, struct icon icon )
	{
		int16 n = icon.Line;
		n * (icon.Column / 8);
		repeat n times; first int16 i = 0; each i + 1; {
			icon.buffer[i] = buffer[i + 2];
		}
	}
	//---------------------------------------------------
	//[i] function_void CopyIcon bitmap bitmap;
	public void CopyIcon( struct icon SourceIcon, struct icon TargetIcon )
	{
		int16 n = SourceIcon.Line;
		n * (SourceIcon.Column / 8);
		repeat n times; first int16 i = 0; each i + 1; {
			TargetIcon.buffer[i] = SourceIcon.buffer[i];
		}
	}
	//---------------------------------------------------
	//[i] function_void RolRightIcon bitmap bitmap;
	public void RolRightIcon( struct icon SourceIcon, struct icon TargetIcon )
	{
		int16 XBlockNumber = SourceIcon.Line / 8;
		int16 YBlockNumber = SourceIcon.Column / 8;
		
		//行列遍历
		repeat YBlockNumber times; first int16 YN = 0; each YN + 1; {
			repeat XBlockNumber times; first int16 XN = 0; each XN + 1; {
				int16 newYN = XN;
				int16 newXN = YBlockNumber - YN - 1;
				->[uint8*?] SourcePoint -> SourceIcon.buffer[YN * SourceIcon.Line + XN * 8];
				->[uint8*?] TargetPoint -> TargetIcon.buffer[newYN * SourceIcon.Line + newXN * 8];
				uint8 D0 = SourcePoint[0];
				uint8 D1 = SourcePoint[1];
				uint8 D2 = SourcePoint[2];
				uint8 D3 = SourcePoint[3];
				uint8 D4 = SourcePoint[4];
				uint8 D5 = SourcePoint[5];
				uint8 D6 = SourcePoint[6];
				uint8 D7 = SourcePoint[7];
				repeat 8 times; first int8 i = 0; each i + 1; {
					uint8 TD;
					TD.0(bit) = D0.7(bit); D0 << 1;
					TD.1(bit) = D1.7(bit); D1 << 1;
					TD.2(bit) = D2.7(bit); D2 << 1;
					TD.3(bit) = D3.7(bit); D3 << 1;
					TD.4(bit) = D4.7(bit); D4 << 1;
					TD.5(bit) = D5.7(bit); D5 << 1;
					TD.6(bit) = D6.7(bit); D6 << 1;
					TD.7(bit) = D7.7(bit); D7 << 1;
					TargetPoint[i] = TD;
				}
			}
		}
	}
	//---------------------------------------------------
	//[i] function_void RolLeftIcon bitmap bitmap;
	public void RolLeftIcon( struct icon SourceIcon, struct icon TargetIcon )
	{
		int16 XBlockNumber = SourceIcon.Line / 8;
		int16 YBlockNumber = SourceIcon.Column / 8;
		
		//行列遍历
		repeat YBlockNumber times; first int16 YN = 0; each YN + 1; {
			repeat XBlockNumber times; first int16 XN = 0; each XN + 1; {
				int16 newXN = YN;
				int16 newYN = YBlockNumber - XN - 1;
				->[uint8*?] SourcePoint -> SourceIcon.buffer[YN * SourceIcon.Line + XN * 8];
				->[uint8*?] TargetPoint -> TargetIcon.buffer[newYN * SourceIcon.Line + newXN * 8];
				uint8 D0 = SourcePoint[0];
				uint8 D1 = SourcePoint[1];
				uint8 D2 = SourcePoint[2];
				uint8 D3 = SourcePoint[3];
				uint8 D4 = SourcePoint[4];
				uint8 D5 = SourcePoint[5];
				uint8 D6 = SourcePoint[6];
				uint8 D7 = SourcePoint[7];
				repeat 8 times; first int8 i = 7; each i - 1; {
					uint8 TD;
					TD.7(bit) = D0.7(bit); D0 << 1;
					TD.6(bit) = D1.7(bit); D1 << 1;
					TD.5(bit) = D2.7(bit); D2 << 1;
					TD.4(bit) = D3.7(bit); D3 << 1;
					TD.3(bit) = D4.7(bit); D4 << 1;
					TD.2(bit) = D5.7(bit); D5 << 1;
					TD.1(bit) = D6.7(bit); D6 << 1;
					TD.0(bit) = D7.7(bit); D7 << 1;
					TargetPoint[i] = TD;
				}
			}
		}
	}
	//---------------------------------------------------
	//[i] function_void SwapLineIcon bitmap bitmap;
	public void SwapLineIcon( struct icon SourceIcon, struct icon TargetIcon )
	{
		int16 YBlockNumber = SourceIcon.Column / 8;
		
		//行列遍历
		repeat YBlockNumber times; first int16 YN = 0; each YN + 1; {
			repeat SourceIcon.Line times; first int8 i = 0; each i + 1; {
				uint8 d = SourceIcon.buffer[YN * SourceIcon.Line + i];
				uint8 swapData;
				swapData.0(bit) = d.7(bit);
				swapData.1(bit) = d.6(bit);
				swapData.2(bit) = d.5(bit);
				swapData.3(bit) = d.4(bit);
				swapData.4(bit) = d.3(bit);
				swapData.5(bit) = d.2(bit);
				swapData.6(bit) = d.1(bit);
				swapData.7(bit) = d.0(bit);
				TargetIcon.buffer[(YBlockNumber - YN - 1) * SourceIcon.Line + i] = swapData;
			}
		}
	}
	//---------------------------------------------------
	//[i] function_void SwapColumnIcon bitmap bitmap;
	public void SwapColumnIcon( struct icon SourceIcon, struct icon TargetIcon )
	{
		int16 YBlockNumber = SourceIcon.Column / 8;
		
		//行列遍历
		repeat YBlockNumber times; first int16 YN = 0; each YN + 1; {
			repeat SourceIcon.Line times; first int8 i = 0; each i + 1; {
				uint8 d = SourceIcon.buffer[YN * SourceIcon.Line + i];
				TargetIcon.buffer[YN * SourceIcon.Line + (SourceIcon.Line - i - 1)] = d;
			}
		}
	}
	//---------------------------------------------------
	//[i] function_void Show bitmap int32 int32;
	public void Show( [#.code uint8*?] pic_buffer, int32 XX, int32 YY )
	{
		int16 X = (int16)XX;
		int16 Y = (int16)YY;
		int16 AreaY;
		uint8 OffsetY;
		SawToothMod( Y, AreaY, OffsetY );
		
		->[#.code uint8*?] buffer -> pic_buffer[2];
		uint8 YBlockNumber = pic_buffer[1] / 8;
		uint8 Height = pic_buffer[0];
		
		//行列遍历输出图标
		int16 BufferIndex = 0;
		repeat YBlockNumber times; first int16 YN = 0; each YN + 1; {
			repeat Height times; first int16 i = 0; each i + 1; {
				uint16 data = buffer[BufferIndex];
				data << OffsetY;
				uint16 BackData;
				BackData.0(uint8) = map.get_uint8( X + i, AreaY + YN );
				BackData.8(uint8) = map.get_uint8( X + i, AreaY + YN + 1 );
				data ^ BackData;
				map.set_uint8( X + i, AreaY + YN, data.0(uint8) );
				map.set_uint8( X + i, AreaY + YN + 1, data.8(uint8) );
				BufferIndex + 1;
			}
		}
	}
	//---------------------------------------------------
	//[i] function_void DrawIcon bitmap int32 int32;
	public void DrawIcon( struct icon icon, int32 XX, int32 YY )
	{
		int16 X = (int16)XX;
		int16 Y = (int16)YY;
		int16 AreaY;
		uint8 OffsetY;
		SawToothMod( Y, AreaY, OffsetY );
		
		int16 YBlockNumber = icon.Column / 8;
		
		//行列遍历输出图标
		int16 BufferIndex = 0;
		repeat YBlockNumber times; first int8 YN = 0; each YN + 1; {
			repeat icon.Line times; first int8 i = 0; each i + 1; {
				uint16 data = icon.buffer[BufferIndex];
				data << OffsetY;
				uint16 BackData;
				BackData.0(uint8) = map.get_uint8( X + i, AreaY + YN );
				BackData.8(uint8) = map.get_uint8( X + i, AreaY + YN + 1 );
				data ^ BackData;
				map.set_uint8( X + i, AreaY + YN, data.0(uint8) );
				map.set_uint8( X + i, AreaY + YN + 1, data.8(uint8) );
				BufferIndex + 1;
			}
		}
	}
	//---------------------------------------------------
	//[i] function_void HitIcon bitmap int32 int32;
	public bool HitIcon( struct icon icon, int32 XX, int32 YY )
	{
		int16 X = (int16)XX;
		int16 Y = (int16)YY;
		int16 AreaY;
		uint8 OffsetY;
		SawToothMod( Y, AreaY, OffsetY );
		
		int16 YBlockNumber = icon.Column / 8;
		
		//行列遍历检查图标是否和背景碰撞
		int16 BufferIndex = 0;
		repeat YBlockNumber times; first int8 YN = 0; each YN + 1; {
			repeat icon.Line times; first int8 i = 0; each i + 1; {
				uint16 data = icon.buffer[BufferIndex];
				data << OffsetY;
				uint16 BackData;
				BackData.0(uint8) = map.get_uint8( X + i, AreaY + YN );
				BackData.8(uint8) = map.get_uint8( X + i, AreaY + YN + 1 );
				if( data & BackData != 0 ) return true;
				BufferIndex + 1;
			}
		}
		return false;
	}
	//---------------------------------------------------
	//锯齿取模函数, 计算一个数除以8的锯齿除法和锯齿余数(不是内置除法和取余)
	void SawToothMod( int16 n, #.base int16 Area, #.base uint8 Offset )
	{
		if( n > 0 ) {
			Area = n / 8;
			Offset = (uint)(int8)(n % 8);
		}
		else {
			Area = n / 8 - 1;
			Offset = 8 - (uint)(int8)(-n % 8);
		}
	}
}









