All pastes #594632 Raw Edit

Something

public cpp v1 · immutable
#594632 ·published 2007-06-29 00:48 UTC
rendered paste body
/*    SEL - Simple DirectMedia Layer Extension Library    Copyright (C) 2002 Matej Knopp <knopp@users.sf.net>    This library is free software; you can redistribute it and/or    modify it under the terms of the GNU Library General Public    License as published by the Free Software Foundation; either    version 2 of the License, or (at your option) any later version.    This library is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU    Library General Public License for more details.    You should have received a copy of the GNU Library General Public    License along with this library; if not, write to the Free    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA*/#include "../sel-config.h"#include "painter.h"#include "../base/surface.h"#include "../base/error.h"namespace SEL{//////////////////////////////////////////////////////////////////////////////////// EMPTY (to avoid crashing) drawing functions ////////////////////////////////////////////////////////////////////////////////////static voidputPixelInvalid (Surface *, Uint16, Uint16, Uint32){}static voiddrawHLineInvalid (Surface *, Uint16, Uint16, Uint16, Uint32){}static voiddrawVLineInvalid (Surface *, Uint16, Uint16, Uint16, Uint32){}static voiddrawLineInvalid (Surface *, Uint16, Uint16, Uint16, Uint16, Uint32){}GFXTable GFXInvalid  = { putPixelInvalid, drawHLineInvalid, drawVLineInvalid, drawLineInvalid  };#define __SET_PIXEL(bpp, pixelData, color) \	*(Uint##bpp*)pixelData = color;// anyone knows about something faster?#if SDL_BYTEORDER == SDL_BIG_ENDIAN#  define __SET_PIXEL24(data, b1, b2, b3) \	data [0] = (b3); data [1] = (b2); data[2] = (b1);#else#  define __SET_PIXEL24(data, b1, b2, b3) \	data [0] = (b1); data[1] = (b2); data[2] = (b3);#endif		//////////////////////////////////////////////////////////////////////////////////// SOLID (not alpha blended) drawing functions ////////////////////////////////////////////////////////////////////////////////////static void putPixelSolid8 (Surface *surface, Uint16 x, Uint16 y, Uint32 color){	Uint8 *data = (Uint8*) surface->pixels () + y * surface->pitch () + x;	__SET_PIXEL (8, data, color);}static void putPixelSolid16 (Surface *surface, Uint16 x, Uint16 y, Uint32 color){	Uint8 *data = 		(Uint8*) surface->pixels () + y * surface->pitch () + 2 * x;	__SET_PIXEL (16, data, color);}static void putPixelSolid24 (Surface *surface, Uint16 x, Uint16 y, Uint32 color){	Uint8 *data = 		(Uint8*) surface->pixels () + y * surface->pitch () + 3 * x;	__SET_PIXEL24 (data, color & 0xFF, (color >> 8) & 0xFF,		       (color >> 16) & 0xFF);}static void putPixelSolid32 (Surface *surface, Uint16 x, Uint16 y, Uint32 color){	Uint8 *data = 		(Uint8*) surface->pixels () + y * surface->pitch () + 4 * x;	__SET_PIXEL (32, data, color);}static voiddrawHLineSolid8 (Surface *surface, Uint16 x, Uint16 y, Uint16 w, Uint32 color){	Uint8 *data = 		(Uint8*) surface->pixels () + y * surface->pitch () + x;	while (w > 0)	{	  	__SET_PIXEL (8, data, color);		++data;		--w;	}		}static voiddrawHLineSolid16 (Surface *surface, Uint16 x, Uint16 y, Uint16 w, Uint32 color){	Uint16 *data = (Uint16*)		((Uint8*) surface->pixels () + y * surface->pitch () + 2 * x);	while (w > 0)	{	  	__SET_PIXEL (16, data, color);		++data;		--w;	}		}static voiddrawHLineSolid24 (Surface *surface, Uint16 x, Uint16 y, Uint16 w, Uint32 color){	Uint8 *data = 		(Uint8*) surface->pixels () + y * surface->pitch () + 3 * x;		Uint8 c1 = color & 0xFF;	Uint8 c2 = (color >> 8) & 0xFF;		Uint8 c3 = (color >> 16) & 0xFF;		while (w > 0)	{		__SET_PIXEL24 (data, c1, c2, c3);		data += 3;		--w;	}		}static voiddrawHLineSolid32 (Surface *surface, Uint16 x, Uint16 y, Uint16 w, Uint32 color){	Uint32 *data = (Uint32*)		((Uint8*) surface->pixels () + y * surface->pitch () + 4 * x);	while (w > 0)	{	  	__SET_PIXEL (32, data, color);		++data;		--w;	}		}static voiddrawVLineSolid8 (Surface *surface, Uint16 x, Uint16 y, Uint16 h, Uint32 color){	Uint16 pitch = surface->pitch ();	Uint8 *data = 		(Uint8*) surface->pixels () + (y * pitch) + x;	while (h > 0)	{	  	__SET_PIXEL (8, data, color);		data += pitch;		--h;	}		}static voiddrawVLineSolid16 (Surface *surface, Uint16 x, Uint16 y, Uint16 h, Uint32 color){	Uint16 pitch = surface->pitch ();	Uint8 *data = 		(Uint8*) surface->pixels () + (y * pitch) + (2 * x);	while (h > 0)	{	  	__SET_PIXEL (16, data, color);		data += pitch;		--h;	}		}static voiddrawVLineSolid24 (Surface *surface, Uint16 x, Uint16 y, Uint16 h, Uint32 color){	Uint16 pitch = surface->pitch ();	Uint8 *data = 		(Uint8*) surface->pixels () + (y * pitch) + (3 * x);	Uint8 c1 = color & 0xFF;	Uint8 c2 = (color >> 8) & 0xFF;		Uint8 c3 = (color >> 16) & 0xFF;		while (h > 0)	{				__SET_PIXEL24 (data, c1, c2, c3);		data += pitch;		--h;	}		}static voiddrawVLineSolid32 (Surface *surface, Uint16 x, Uint16 y, Uint16 h, Uint32 color){	Uint16 pitch = surface->pitch ();		Uint8 *data = 		(Uint8*) surface->pixels () + (y * pitch) + (4 * x);		while (h > 0)	{	  	__SET_PIXEL (32, data, color);		data += pitch;		--h;	}		}// Line drawing algorithm (Bresenham)#define __DO_LINE(x1, y1, x2, y2, command, surface) \{ \	Sint16 dx = x2 - x1; \	Sint16 dy = y2 - y1; \	Uint16 x = 0; \	Uint16 y = 0; \	Uint8 *data = \		(Uint8*) surface->pixels () + y1 * surface->pitch () + x1 * surface->format ()->BytesPerPixel; \	Sint16 d_pitch = (dy < 0) ? -surface->pitch () : surface->pitch (); \	Sint16 d_data = (dx < 0) ? -surface->format ()->BytesPerPixel : surface->format ()->BytesPerPixel; \	dx = abs (dx); \	dy = abs (dy); \	\	if (dx >= dy) \	{ \		for (x = 0; x <= dx; x++) \		{ \			{ command; } \			\			y += dy; \			if (y >= dx) \			{ \				y -= dx; \				data += d_pitch; \    			} \			\			data += d_data; \		} \	} \	else \	{ \		for (y = 0; y <= dy; y++) \		{ \			{ command; } \			\			x += dx; \			if (x >= dy) \			{ \				x -= dy; \				data += d_data; \			} \			data += d_pitch; \		} \	} \}static voiddrawLineSolid8 (Surface *surface, Uint16 x1, Uint16 y1, Uint16 x2, Uint16 y2,                Uint32 color){	__DO_LINE (x1, y1, x2, y2, __SET_PIXEL (8, data, color), surface);}		static voiddrawLineSolid16 (Surface *surface, Uint16 x1, Uint16 y1, Uint16 x2, Uint16 y2,                 Uint32 color){	__DO_LINE (x1, y1, x2, y2, __SET_PIXEL (16, data, color), surface);}static voiddrawLineSolid24 (Surface *surface, Uint16 x1, Uint16 y1, Uint16 x2, Uint16 y2,                 Uint32 color){	Uint8 c1 = color & 0xFF;	Uint8 c2 = (color >> 8) & 0xFF;		Uint8 c3 = (color >> 16) & 0xFF;		__DO_LINE (x1, y1, x2, y2, __SET_PIXEL24 (data, c1, c2, c3), surface);}static voiddrawLineSolid32 (Surface *surface, Uint16 x1, Uint16 y1, Uint16 x2, Uint16 y2,                 Uint32 color){	__DO_LINE (x1, y1, x2, y2, __SET_PIXEL (32, data, color), surface);}#define __MAKE_LOCKED_PUT_PIXEL(type) \static void \putPixel##type##L (Surface *surface, Uint16 x, Uint16 y, Uint32 color) \{ \	surface->lock (); \	putPixel##type (surface, x, y, color); \	surface->unlock (); \}#define __MAKE_LOCKED_H_LINE(type) \static void \drawHLine##type##L (Surface *surface, Uint16 x, Uint16 y, Uint16 w, Uint32 color) \{ \	surface->lock (); \	drawHLine##type (surface, x, y, w, color); \	surface->unlock (); \}#define __MAKE_LOCKED_V_LINE(type) \static void \drawVLine##type##L (Surface *surface, Uint16 x, Uint16 y, Uint16 h, Uint32 color) \{ \	surface->lock (); \	drawVLine##type (surface, x, y, h, color); \	surface->unlock (); \}#define __MAKE_LOCKED_LINE(type) \static void \drawLine##type##L (Surface *surface, Uint16 x, Uint16 y, Uint16 x2, Uint16 y2, Uint32 color) \{ \	surface->lock (); \	drawLine##type (surface, x, y, x2, y2, color); \	surface->unlock (); \}__MAKE_LOCKED_PUT_PIXEL (Solid8);__MAKE_LOCKED_H_LINE    (Solid8);__MAKE_LOCKED_V_LINE    (Solid8);__MAKE_LOCKED_LINE      (Solid8);__MAKE_LOCKED_PUT_PIXEL (Solid16);__MAKE_LOCKED_H_LINE    (Solid16);__MAKE_LOCKED_V_LINE    (Solid16);__MAKE_LOCKED_LINE      (Solid16);__MAKE_LOCKED_PUT_PIXEL (Solid24);__MAKE_LOCKED_H_LINE    (Solid24);__MAKE_LOCKED_V_LINE    (Solid24);__MAKE_LOCKED_LINE      (Solid24);__MAKE_LOCKED_PUT_PIXEL (Solid32);__MAKE_LOCKED_H_LINE    (Solid32);__MAKE_LOCKED_V_LINE    (Solid32);__MAKE_LOCKED_LINE      (Solid32);//////////////////////////////////////////////////////////////////////////////////// ALPHA BLENDED (transparency aware) drawing functions ////////////////////////////////////////////////////////////////////////////////////// macros for color manipulation (some are taken from SDL)#define __RGBA_FROM_RGBA8888(pixel, r, g, b, a)	\{                                               \    r = (pixel>>24);                            \    g = ((pixel>>16)&0xFF);	                    \    b = ((pixel>>8)&0xFF);	                    \    a = (pixel&0xFF);                           \}#define __RGB_FROM_RGB565(pixel, r, g, b)       \{                                               \    r = (((pixel&0xF800)>>11)<<3);              \    g = (((pixel&0x07E0)>>5)<<2);               \    b = ((pixel&0x001F)<<3);                    \}#define __RGB_FROM_RGB888(pixel, r, g, b)       \{                                               \    r = ((pixel&0xFF0000)>>16);                 \    g = ((pixel&0xFF00)>>8);                    \    b = (pixel&0xFF);                           \}#define __RGB565_FROM_RGB(pixel, r, g, b)       \{                                               \    pixel = ((r>>3)<<11)|((g>>2)<<5)|(b>>3);    \}#define __RGB888_FROM_RGB(pixel, r, g, b)       \{                                               \    pixel = (r<<16)|(g<<8)|b;                   \}// Blend the RGB values of two pixels based on a source alpha value */#define __ALPHA_BLEND(sR, sG, sB, A, dR, dG, dB) \do {                                             \    dR = ((((sR-dR)*(A))>>8)+dR) & 0xFF;         \    dG = ((((sG-dG)*(A))>>8)+dG) & 0xFF;         \    dB = ((((sB-dB)*(A))>>8)+dB) & 0xFF;         \} while(0)// this is in fact 128 (~127)#define __ALPHA_HALF 127 // Blend the RGB values two pixel with alpha = 128 (~127) - optimized#define __ALPHA_BLEND_HALF(sR, sG, sB, dR, dG, dB)  \do {                                                \    dR = ((sR + dR) >> 1);                          \    dG = ((sG + dG) >> 1);                          \    dB = ((sB + dB) >> 1);                          \} while (0)#define __ALPHA_BLEND_AUTO(sR, sG, sB, A, dR, dG, dB) \{                                                     \    if (a == 127)                                     \        __ALPHA_BLEND_HALF (sR, sG, sB, dR, dG, dB);  \    else                                              \        __ALPHA_BLEND (sR, sG, sB, A, dR, dG, dB);    \}static void putPixelBlend16 (Surface *surface, Uint16 x, Uint16 y, Uint32 color){	Uint8 dr, dg, db, a;	__RGBA_FROM_RGBA8888 (color, dr, dg, db, a);    	if (a == 0)		return;		Uint16 *data = (Uint16*)		((Uint8*) surface->pixels () + y * surface->pitch () + 2 * x);	if (a == 255) 	{		__RGB565_FROM_RGB (*data, dr, dg, db);		return;	}	Uint8 sr, sg, sb;    	__RGB_FROM_RGB565 (*data, sr, sg, sb);	a = ~a;		__ALPHA_BLEND_AUTO (sr, sg, sb, a, dr, dg, db);	__RGB565_FROM_RGB (*data, dr, dg, db);}static void putPixelBlend24 (Surface *surface, Uint16 x, Uint16 y, Uint32 color){	Uint8 dr, dg, db, a;	__RGBA_FROM_RGBA8888 (color, dr, dg, db, a);    	if (a == 0)		return;		Uint32 *data = (Uint32*)		((Uint8*) surface->pixels () + y * surface->pitch () + 3 * x);	if (a == 255) 	{		__SET_PIXEL24 (((Uint8*)data), db, dg, dr);		return;	}	Uint8 sr, sg, sb;    	__RGB_FROM_RGB888 (*data, sr, sg, sb);	a = ~a;		__ALPHA_BLEND_AUTO (sr, sg, sb, a, dr, dg, db);	__SET_PIXEL24 (((Uint8*)data), db, dg, dr);	}static void putPixelBlend32 (Surface *surface, Uint16 x, Uint16 y, Uint32 color){	Uint8 dr, dg, db, a;	__RGBA_FROM_RGBA8888 (color, dr, dg, db, a);    	if (a == 0)		return;		Uint32 *data = (Uint32*)		((Uint8*) surface->pixels () + y * surface->pitch () + 4 * x);	if (a == 255) 	{		__RGB888_FROM_RGB (*data, dr, dg, db);		return;	}	Uint8 sr, sg, sb;    	__RGB_FROM_RGB888 (*data, sr, sg, sb);	a = ~a;		__ALPHA_BLEND_AUTO (sr, sg, sb, a, dr, dg, db);	__RGB888_FROM_RGB (*data, dr, dg, db);}static void drawHLineBlend16 (Surface *surface, Uint16 x, Uint16 y, Uint16 w, Uint32 color){	Uint8 dr, dg, db, a;	__RGBA_FROM_RGBA8888 (color, dr, dg, db, a);    	if (a == 0)		return;								if (a == 255) 	{    		__RGB565_FROM_RGB (color, dr, dg, db);		drawHLineSolid16 (surface, x, y, w, color);		return;	}	Uint16 *data = (Uint16*)		((Uint8*) surface->pixels () + y * surface->pitch () + 2 * x);	Uint8 sr, sg, sb;	Uint8 dr_, dg_, db_;    	a = ~a;	if (a == __ALPHA_HALF)	{		while (w > 0)		{			__RGB_FROM_RGB565 (*data, sr, sg, sb);			dr_ = dr; dg_ = dg; db_ = db;			__ALPHA_BLEND_HALF (sr, sg, sb, dr_, dg_, db_);			__RGB565_FROM_RGB (*data, dr_, dg_, db_);			++data;			--w;		}	}			else	{		while (w > 0)		{			__RGB_FROM_RGB565 (*data, sr, sg, sb);			dr_ = dr; dg_ = dg; db_ = db;			__ALPHA_BLEND (sr, sg, sb, a, dr_, dg_, db_);			__RGB565_FROM_RGB (*data, dr_, dg_, db_);			++data;			--w;		}	}		}static void drawHLineBlend24 (Surface *surface, Uint16 x, Uint16 y, Uint16 w, Uint32 color){	Uint8 dr, dg, db, a;	__RGBA_FROM_RGBA8888 (color, dr, dg, db, a);    	if (a == 0)		return;								if (a == 255) 	{    		__RGB888_FROM_RGB (color, dr, dg, db);		drawHLineSolid24 (surface, x, y, w, color);		return;	}	Uint32 *data = (Uint32*)		((Uint8*) surface->pixels () + y * surface->pitch () + 3 * x);	Uint8 sr, sg, sb;	Uint8 dr_, dg_, db_;	a = ~a;	if (a == __ALPHA_HALF)	{		while (w > 0)		{			__RGB_FROM_RGB888 (*data, sr, sg, sb);			dr_ = dr; dg_ = dg; db_ = db;			__ALPHA_BLEND_HALF (sr, sg, sb, dr_, dg_, db_);						__SET_PIXEL24 (((Uint8*)data), db_, dg_, dr_);#ifdef _MSC_VER			data = (Uint32*) ((Uint8*)data + 3);#else			((Uint8*)data) += 3;#endif			--w;		}	}			else	{		while (w > 0)		{			__RGB_FROM_RGB888 (*data, sr, sg, sb);			dr_ = dr; dg_ = dg; db_ = db;			__ALPHA_BLEND (sr, sg, sb, a, dr_, dg_, db_);			__SET_PIXEL24 (((Uint8*)data), db_, dg_, dr_);#ifdef _MSC_VER			data = (Uint32*) ((Uint8*)data + 3);#else			((Uint8*)data) += 3;#endif						--w;		}	}		}static void drawHLineBlend32 (Surface *surface, Uint16 x, Uint16 y, Uint16 w, Uint32 color){	Uint8 dr, dg, db, a;	__RGBA_FROM_RGBA8888 (color, dr, dg, db, a);    	if (a == 0)		return;								if (a == 255) 	{    		__RGB888_FROM_RGB (color, dr, dg, db);		drawHLineSolid32 (surface, x, y, w, color);		return;	}	Uint32 *data = (Uint32*)		((Uint8*) surface->pixels () + y * surface->pitch () + 4 * x);	Uint8 sr, sg, sb;	Uint8 dr_, dg_, db_;    	a = ~a;	if (a == __ALPHA_HALF)	{		while (w > 0)		{			__RGB_FROM_RGB888 (*data, sr, sg, sb);			dr_ = dr; dg_ = dg; db_ = db;			__ALPHA_BLEND_HALF (sr, sg, sb, dr_, dg_, db_);			__RGB888_FROM_RGB (*data, dr_, dg_, db_);			++data;			--w;		}	}			else	{		while (w > 0)		{			__RGB_FROM_RGB888 (*data, sr, sg, sb);			dr_ = dr; dg_ = dg; db_ = db;			__ALPHA_BLEND (sr, sg, sb, a, dr_, dg_, db_);			__RGB888_FROM_RGB (*data, dr_, dg_, db_);			++data;			--w;		}	}		}static void drawVLineBlend16 (Surface *surface, Uint16 x, Uint16 y, Uint16 h, Uint32 color){	Uint8 dr, dg, db, a;	__RGBA_FROM_RGBA8888 (color, dr, dg, db, a);    	if (a == 0)		return;								if (a == 255) 	{    		__RGB565_FROM_RGB (color, dr, dg, db);		drawVLineSolid16 (surface, x, y, h, color);		return;	}	Uint16 pitch = surface->pitch ();	Uint16 *data = (Uint16*)		((Uint8*) surface->pixels () + (y * pitch) + (2 * x));	Uint8 sr, sg, sb;	Uint8 dr_, dg_, db_;    	a = ~a;	if (a == __ALPHA_HALF)	{		while (h > 0)		{			__RGB_FROM_RGB565 (*data, sr, sg, sb);			dr_ = dr; dg_ = dg; db_ = db;			__ALPHA_BLEND_HALF (sr, sg, sb, dr_, dg_, db_);			__RGB565_FROM_RGB (*data, dr_, dg_, db_);#ifdef _MSC_VER			data = (Uint16*) ((Uint8*)data + pitch);#else			((Uint8*)data) += pitch;#endif			--h;		}	}			else	{		while (h > 0)		{			__RGB_FROM_RGB565 (*data, sr, sg, sb);			dr_ = dr; dg_ = dg; db_ = db;			__ALPHA_BLEND (sr, sg, sb, a, dr_, dg_, db_);			__RGB565_FROM_RGB (*data, dr_, dg_, db_);			#ifdef _MSC_VER			data = (Uint16*) ((Uint8*)data + pitch);#else			((Uint8*)data) += pitch;#endif			--h;					}	}		}static void drawVLineBlend24 (Surface *surface, Uint16 x, Uint16 y, Uint16 h, Uint32 color){	Uint8 dr, dg, db, a;	__RGBA_FROM_RGBA8888 (color, dr, dg, db, a);    	if (a == 0)		return;								if (a == 255) 	{    		__RGB888_FROM_RGB (color, dr, dg, db);		drawVLineSolid24 (surface, x, y, h, color);		return;	}	Uint16 pitch = surface->pitch ();	Uint32 *data = (Uint32*)		((Uint8*) surface->pixels () + (y * pitch) + (3 * x));	Uint8 sr, sg, sb;	Uint8 dr_, dg_, db_;    	a = ~a;	if (a == __ALPHA_HALF)	{		while (h > 0)		{			__RGB_FROM_RGB888 (*data, sr, sg, sb);			dr_ = dr; dg_ = dg; db_ = db;			__ALPHA_BLEND_HALF (sr, sg, sb, dr_, dg_, db_);			__SET_PIXEL24 (((Uint8*)data), db_, dg_, dr_);#ifdef _MSC_VER			data = (Uint32*) ((Uint8*)data + pitch);#else			((Uint8*)data) += pitch;#endif			--h;		}	}			else	{		while (h > 0)		{			__RGB_FROM_RGB888 (*data, sr, sg, sb);			dr_ = dr; dg_ = dg; db_ = db;			__ALPHA_BLEND (sr, sg, sb, a, dr_, dg_, db_);			__SET_PIXEL24 (((Uint8*)data), db_, dg_, dr_);#ifdef _MSC_VER			data = (Uint32*) ((Uint8*)data + pitch);#else			((Uint8*)data) += pitch;#endif			--h;					}	}		}static void drawVLineBlend32 (Surface *surface, Uint16 x, Uint16 y, Uint16 h, Uint32 color){	Uint8 dr, dg, db, a;	__RGBA_FROM_RGBA8888 (color, dr, dg, db, a);    	if (a == 0)		return;								if (a == 255) 	{    		__RGB888_FROM_RGB (color, dr, dg, db);		drawVLineSolid32 (surface, x, y, h, color);		return;	}	Uint16 pitch = surface->pitch ();	Uint32 *data = (Uint32*)		((Uint8*) surface->pixels () + (y * pitch) + (4 * x));	Uint8 sr, sg, sb;	Uint8 dr_, dg_, db_;    	a = ~a;	if (a == __ALPHA_HALF)	{		while (h > 0)		{			__RGB_FROM_RGB888 (*data, sr, sg, sb);			dr_ = dr; dg_ = dg; db_ = db;			__ALPHA_BLEND_HALF (sr, sg, sb, dr_, dg_, db_);			__RGB888_FROM_RGB (*data, dr_, dg_, db_);#ifdef _MSC_VER			data = (Uint32*) ((Uint8*)data + pitch);#else			((Uint8*)data) += pitch;#endif			--h;		}	}			else	{		while (h > 0)		{			__RGB_FROM_RGB888 (*data, sr, sg, sb);			dr_ = dr; dg_ = dg; db_ = db;			__ALPHA_BLEND (sr, sg, sb, a, dr_, dg_, db_);			__RGB888_FROM_RGB (*data, dr_, dg_, db_);#ifdef _MSC_VER			data = (Uint32*) ((Uint8*)data + pitch);#else			((Uint8*)data) += pitch;#endif			--h;					}	}		}static voiddrawLineBlend16 (Surface *surface, Uint16 x1, Uint16 y1, Uint16 x2, Uint16 y2,                 Uint32 color){	Uint8 dr, dg, db, a;	__RGBA_FROM_RGBA8888 (color, dr, dg, db, a);    	if (a == 0)		return;								if (a == 255) 	{    		__RGB565_FROM_RGB (color, dr, dg, db);		drawLineSolid16 (surface, x1, y1, x2, y2, color);		return;	}	Uint8 sr, sg, sb;	Uint8 dr_, dg_, db_;    	a = ~a;	Uint16 *data_;	if (a == __ALPHA_HALF)	{				__DO_LINE (x1, y1, x2, y2, 		           data_ = (Uint16*)data;		           __RGB_FROM_RGB565 (*data_, sr, sg, sb); 		           dr_ = dr; dg_= dg; db_ = db; 		           __ALPHA_BLEND_HALF (sr, sg, sb, dr_, dg_, db_); 		           __RGB565_FROM_RGB (*data_, dr_, dg_, db_),		           surface);	}			else	{		__DO_LINE (x1, y1, x2, y2, 		           data_ = (Uint16*)data;				           __RGB_FROM_RGB565 (*data_, sr, sg, sb); 		           dr_ = dr; dg_= dg; db_ = db; 		           __ALPHA_BLEND (sr, sg, sb, a, dr_, dg_, db_); 		           __RGB565_FROM_RGB (*data_, dr_, dg_, db_),		           surface);	}		}static voiddrawLineBlend24 (Surface *surface, Uint16 x1, Uint16 y1, Uint16 x2, Uint16 y2,                 Uint32 color){	Uint8 dr, dg, db, a;	__RGBA_FROM_RGBA8888 (color, dr, dg, db, a);    	if (a == 0)		return;								if (a == 255) 	{    		__RGB888_FROM_RGB (color, dr, dg, db);		drawLineSolid24 (surface, x1, y1, x2, y2, color);		return;	}	Uint8 sr, sg, sb;	Uint8 dr_, dg_, db_;    	a = ~a;	Uint32 *data_;	if (a == __ALPHA_HALF)	{				__DO_LINE (x1, y1, x2, y2, 		           data_ = (Uint32*)data;		           __RGB_FROM_RGB888 (*data_, sr, sg, sb); 		           dr_ = dr; dg_= dg; db_ = db; 		           __ALPHA_BLEND_HALF (sr, sg, sb, dr_, dg_, db_); 		           __SET_PIXEL24 (data, db_, dg_, dr_),		           surface);	}			else	{		__DO_LINE (x1, y1, x2, y2, 		           data_ = (Uint32*)data;				           __RGB_FROM_RGB888 (*data_, sr, sg, sb); 		           dr_ = dr; dg_= dg; db_ = db; 		           __ALPHA_BLEND (sr, sg, sb, a, dr_, dg_, db_); 		           __SET_PIXEL24 (data, db_, dg_, dr_),		           surface);	}		}static voiddrawLineBlend32 (Surface *surface, Uint16 x1, Uint16 y1, Uint16 x2, Uint16 y2,	 	 Uint32 color){	Uint8 dr, dg, db, a;	__RGBA_FROM_RGBA8888 (color, dr, dg, db, a);    	if (a == 0)		return;								if (a == 255) 	{    		__RGB888_FROM_RGB (color, dr, dg, db);		drawLineSolid32 (surface, x1, y1, x2, y2, color);		return;	}	Uint8 sr, sg, sb;	Uint8 dr_, dg_, db_;    	a = ~a;	Uint32 *data_;	if (a == __ALPHA_HALF)	{				__DO_LINE (x1, y1, x2, y2, 		           data_ = (Uint32*)data;		           __RGB_FROM_RGB888 (*data_, sr, sg, sb); 		           dr_ = dr; dg_= dg; db_ = db; 		           __ALPHA_BLEND_HALF (sr, sg, sb, dr_, dg_, db_); 		           __RGB888_FROM_RGB (*data_, dr_, dg_, db_),		           surface);	}			else	{		__DO_LINE (x1, y1, x2, y2, 		           data_ = (Uint32*)data;				           __RGB_FROM_RGB888 (*data_, sr, sg, sb); 		           dr_ = dr; dg_= dg; db_ = db; 		           __ALPHA_BLEND (sr, sg, sb, a, dr_, dg_, db_); 		           __RGB888_FROM_RGB (*data_, dr_, dg_, db_),		           surface);	}		}#undef __DO_LINE__MAKE_LOCKED_PUT_PIXEL (Blend16);__MAKE_LOCKED_H_LINE    (Blend16);__MAKE_LOCKED_V_LINE    (Blend16);__MAKE_LOCKED_LINE      (Blend16);__MAKE_LOCKED_PUT_PIXEL (Blend24);__MAKE_LOCKED_H_LINE    (Blend24);__MAKE_LOCKED_V_LINE    (Blend24);__MAKE_LOCKED_LINE      (Blend24);__MAKE_LOCKED_PUT_PIXEL (Blend32);__MAKE_LOCKED_H_LINE    (Blend32);__MAKE_LOCKED_V_LINE    (Blend32);__MAKE_LOCKED_LINE      (Blend32);GFXTable Painter::m_gfx_tables [2][2][4] = {  {     {      { putPixelSolid8,  drawHLineSolid8,  drawVLineSolid8,  drawLineSolid8  },      { putPixelSolid16, drawHLineSolid16, drawVLineSolid16, drawLineSolid16 },      { putPixelSolid24, drawHLineSolid24, drawVLineSolid24, drawLineSolid24 },      { putPixelSolid32, drawHLineSolid32, drawVLineSolid32, drawLineSolid32 }    },    {      { putPixelSolid8L,  drawHLineSolid8L,  drawVLineSolid8L,  drawLineSolid8L  },      { putPixelSolid16L, drawHLineSolid16L, drawVLineSolid16L, drawLineSolid16L },      { putPixelSolid24L, drawHLineSolid24L, drawVLineSolid24L, drawLineSolid24L },      { putPixelSolid32L, drawHLineSolid32L, drawVLineSolid32L, drawLineSolid32L }    }  },  {     {      { putPixelSolid8,  drawHLineSolid8,  drawVLineSolid8,  drawLineSolid8  },      { putPixelBlend16, drawHLineBlend16, drawVLineBlend16, drawLineBlend16 },      { putPixelBlend24, drawHLineBlend24, drawVLineBlend24, drawLineBlend24 },      { putPixelBlend32, drawHLineBlend32, drawVLineBlend32, drawLineBlend32 }    },    {      { putPixelSolid8L,  drawHLineSolid8L,  drawVLineSolid8L,  drawLineSolid8L  },      { putPixelBlend16L, drawHLineBlend16L, drawVLineBlend16L, drawLineBlend16L },      { putPixelBlend24L, drawHLineBlend24L, drawVLineBlend24L, drawLineBlend24L },      { putPixelBlend32L, drawHLineBlend32L, drawVLineBlend32L, drawLineBlend32L }    }  }};#if 0 // this will not be included in the GFX table// shamelessly taken from allegro...staticvoid do_circle (Surface *surface, Uint16 x, Uint16 y, Uint16 radius, int d,	        void (*proc)(Surface *, int, int, int)){	Sint16 cx = 0;	Sint16 cy = radius;	Sint16 df = 1 - radius; 	Sint16 d_e = 3;	Sint16 d_se = -2 * radius + 5;	do {		proc (surface, x+cx, y+cy, d);		if (cx) 			proc (surface, x-cx, y+cy, d); 		if (cy) 			proc (surface, x+cx, y-cy, d);		if ((cx) && (cy)) 			proc (surface, x-cx, y-cy, d); 		if (cx != cy) 		{			proc (surface, x+cy, y+cx, d); 			if (cx) 				proc (surface, x+cy, y-cx, d);			if (cy) 				proc (surface, x-cy, y+cx, d); 			if (cx && cy) 				proc (surface, x-cy, y-cx, d); 		}		if (df < 0)		{			df += d_e;			d_e += 2;			d_se += 2;		}		else 		{	 			df += d_se;			d_e += 2;			d_se += 4;			cy--;		} 		cx++; 	} while (cx <= cy);}#endif // 0//////////////////////////////////////////////////////////////////////////////////////// The Painter Class ////////////////////////////////////////////////////////////////////////////////////////Painter::Painter (Surface *target, int mode, bool nothrow)	: m_gfx (&GFXInvalid), m_target_surface (target), m_mode (mode), 	  m_clipping (true), m_auto_lock (true){ 	if (!target) 	{			warning ("Painter: Cannot operate on NULL surface !");		if (!nothrow)			throw Error ("Couldn't create painter with NULL target surface");	}	else	{			        updateGFXTable ();		target->ref ();	}	resetClipRect ();}Painter::~Painter (){	if (m_target_surface)		m_target_surface->unref ();}boolPainter::updateGFXTable (){	m_gfx = &GFXInvalid;	return_val_if_fail (m_target_surface != NULL, false);	if (m_mode != ModeSolid && m_mode != ModeBlended)	{		warning ("Unknown drawing mode!");		return false;	}		int depth = m_target_surface->format ()->BytesPerPixel;		if (depth < 1 || depth > 4)	{		warning ("Unknown bit-depth of the target surface !");		return false;	}	    		m_gfx = &m_gfx_tables [m_mode][m_auto_lock][depth - 1];	return true;}void Painter::setMode (int mode){	m_mode = mode;	updateGFXTable ();}voidPainter::setTarget (Surface *target){	releaseTarget ();	m_target_surface = target;	updateGFXTable ();	resetClipRect ();	if (target)		target->ref ();}voidPainter::releaseTarget (){	if (m_target_surface)		m_target_surface->unref ();	m_target_surface = NULL;	m_gfx = NULL;	m_clip_rect = Rect (0, 0, 0, 0);		}voidPainter::setClipping (bool clipping){	m_clipping = clipping;}voidPainter::setAutoLock (bool auto_lock){	m_auto_lock = auto_lock;	updateGFXTable ();}voidPainter::setClipRect (const Rect & rect){	m_clip_rect = rect;	m_clip_x2 = rect.x + rect.w - 1;	m_clip_y2 = rect.y + rect.h - 1;}voidPainter::retrieveClipRect (){	if (!m_target_surface)		setClipRect (Rect (0, 0, 0, 0));	else		setClipRect (m_target_surface->clipRect ());}voidPainter::resetClipRect (){	if (!m_target_surface)		setClipRect (Rect (0, 0, 0, 0));	else		setClipRect (Rect (0, 0, m_target_surface->w (),		             m_target_surface->h ()));}voidPainter::putPixel (Uint16 x, Uint16 y, Uint32 color){	if (m_clipping)	{		if (x < m_clip_rect.x || x > m_clip_x2 ||		    y < m_clip_rect.y || y > m_clip_y2)			return;	}		m_gfx->putPixel (m_target_surface, x, y, color);}voidPainter::drawHLine (Uint16 x, Uint16 y, Uint16 w, Uint32 color){	if (w == 0)		return;		if (m_clipping)	{		if (y < m_clip_rect.y || y > m_clip_y2)			return;		if ((x + w - 1) < m_clip_rect.x)			return;		if (x > m_clip_x2)			return;		if (x < m_clip_rect.x)		{			w -= (m_clip_rect.x - x);			x = m_clip_rect.x;		}				if ((x + w) > (m_clip_x2 + 1))		{			w -= (w + x) - m_clip_x2 - 1;		}	}	m_gfx->drawHLine (m_target_surface, x, y, w, color);}voidPainter::drawVLine (Uint16 x, Uint16 y, Uint16 h, Uint32 color){	if (h == 0)		return;	if (m_clipping)	{		if (x < m_clip_rect.x || x > m_clip_x2)			return;		if ((y + h - 1) < m_clip_rect.y)			return;		if (y > m_clip_y2)			return;		if (y < m_clip_rect.y)		{			h -= (m_clip_rect.y - y);			y = m_clip_rect.y;		}				if ((y + h) > (m_clip_y2 + 1))		{			h -= (h + y) - m_clip_y2 - 1;		}	}	m_gfx->drawVLine (m_target_surface, x, y, h, color);}// This function was ripped from "Tricks of the Windows game programming gurus" // written by Andre Lamothe ISBN: 0-672-31361-8// Then it was ripped from ClanLib and slightly adapted to work with SEL.// It returns false if the line is totally outside the clipping area and true// if the line was successfully clippedstatic bool clipLine (Uint16 &x1, Uint16 &y1, Uint16 &x2, Uint16 &y2, Uint16 min_clip_x,	      Uint16 max_clip_x, Uint16 min_clip_y, Uint16 max_clip_y){// internal clipping codes#define CLIP_CODE_C  0x0000#define CLIP_CODE_N  0x0008#define CLIP_CODE_S  0x0004#define CLIP_CODE_E  0x0002#define CLIP_CODE_W  0x0001#define CLIP_CODE_NE 0x000a#define CLIP_CODE_SE 0x0006#define CLIP_CODE_NW 0x0009#define CLIP_CODE_SW 0x0005	Uint16 xc1 = x1;	Uint16 yc1 = y1;	Uint16 xc2 = x2;	Uint16 yc2 = y2;	int p1_code = 0;	int p2_code = 0;	// determine codes for p1 and p2	if (y1 < min_clip_y)	{		p1_code |= CLIP_CODE_N;	}	else if (y1 > max_clip_y)	{		p1_code |= CLIP_CODE_S;	}	if (x1 < min_clip_x)	{		p1_code |= CLIP_CODE_W;	}	else if (x1 > max_clip_x)	{		p1_code |= CLIP_CODE_E;	}	if (y2 < min_clip_y)	{		p2_code |= CLIP_CODE_N;	}	else if (y2 > max_clip_y)	{		p2_code |= CLIP_CODE_S;	}	if (x2 < min_clip_x)	{		p2_code |= CLIP_CODE_W;	}	else if (x2 > max_clip_x)	{		p2_code |= CLIP_CODE_E;	}	// try and trivially reject	if ((p1_code & p2_code))	{		return 0;	}	// test for totally visible, if so leave points untouched	if (p1_code == 0 && p2_code == 0)	{		return 1;	}	// determine end clip point for p1	switch (p1_code)	{	case CLIP_CODE_C: 		break;	case CLIP_CODE_N:				yc1 = (Uint16) min_clip_y;		xc1 = (Uint16) (x1 + 0.5 + (min_clip_y - y1)		                * (x2 - x1) / (y2 - y1));		break;	case CLIP_CODE_S:		yc1 = (Uint16) max_clip_y;		xc1 = (Uint16) (x1 + 0.5 + (max_clip_y-y1) 		                * (x2 - x1) / (y2 - y1));		break;	case CLIP_CODE_W:		xc1 = (Uint16) min_clip_x;		yc1 = (Uint16) (y1 + 0.5 + (min_clip_x - x1)		                * (y2 - y1) / (x2 - x1));		break;			case CLIP_CODE_E:		xc1 = (Uint16) max_clip_x;		yc1 = (Uint16) (y1 + 0.5 + (max_clip_x - x1)		                * (y2 - y1) / (x2 - x1));		break;	// these cases are more complex, must compute 2 intersections	case CLIP_CODE_NE:		// north hline intersection		yc1 = (Uint16) min_clip_y;		xc1 = (Uint16) (x1 + 0.5 + (min_clip_y - y1)		                * (x2 - x1) / (y2 - y1));		// test if intersection is valid, of so then done, else compute next		if (xc1 < min_clip_x || xc1 > max_clip_x)		{				// east vline intersection			xc1 = (Uint16) max_clip_x;			yc1 = (Uint16) (y1 + 0.5 + (max_clip_x - x1)			                * (y2 - y1) / (x2 - x1));		}			break;		case CLIP_CODE_SE:		// south hline intersection		yc1 = (Uint16) max_clip_y;		xc1 = (Uint16) (x1 + 0.5 + (max_clip_y - y1)		                * (x2 - x1) / (y2 - y1));			// test if intersection is valid, of so then done, else compute next		if (xc1 < min_clip_x || xc1 > max_clip_x)		{			// east vline intersection			xc1 = (Uint16) max_clip_x;			yc1 = (Uint16) (y1 + 0.5 + (max_clip_x - x1)			                * (y2 - y1) / (x2 - x1));		}		break;		case CLIP_CODE_NW:		// north hline intersection		yc1 = (Uint16) min_clip_y;		xc1 = (Uint16) (x1 + 0.5 + (min_clip_y - y1) 		                * (x2 - x1) / (y2 - y1));					// test if intersection is valid, of so then done, else compute next		if (xc1 < min_clip_x || xc1 > max_clip_x)		{			xc1 = (Uint16) min_clip_x;			yc1 = (Uint16) (y1 + 0.5 + (min_clip_x - x1)			                * (y2 - y1) / (x2 - x1));			} 		break;	  		case CLIP_CODE_SW:		// south hline intersection		yc1 = (Uint16) max_clip_y;		xc1 = (Uint16) (x1 + 0.5 + (max_clip_y - y1) 		                * (x2-x1)/(y2-y1));			// test if intersection is valid, of so then done, else compute next		if (xc1 < min_clip_x || xc1 > max_clip_x)		{			xc1 = (Uint16) min_clip_x;			yc1 = (Uint16) (y1 + 0.5 + (min_clip_x - x1)			                * (y2 - y1) / (x2 - x1));			} 		break;	default:		break;	} // switch	// determine clip point for p2	switch (p2_code)	{	case CLIP_CODE_C: 		break;	case CLIP_CODE_N:		yc2 = (Uint16) min_clip_y;		xc2 = (Uint16) (x2 + (min_clip_y - y2) * (x1 - x2) / (y1 - y2));		break;	case CLIP_CODE_S:		yc2 = (Uint16) max_clip_y;		xc2 = (Uint16) (x2 + (max_clip_y - y2) * (x1 - x2) / (y1 - y2));		break;	case CLIP_CODE_W:		xc2 = (Uint16) min_clip_x;		yc2 = (Uint16) (y2 + (min_clip_x - x2) * (y1 - y2) / (x1 - x2));		break;	case CLIP_CODE_E:		xc2 = (Uint16) max_clip_x;		yc2 = (Uint16) (y2 + (max_clip_x - x2) * (y1 - y2) / (x1 - x2));		break;	// these cases are more complex, must compute 2 intersections	case CLIP_CODE_NE:		// north hline intersection		yc2 = (Uint16) min_clip_y;		xc2 = (Uint16) (x2 + 0.5 + (min_clip_y - y2) 		                * (x1 - x2) / (y1 - y2));		// test if intersection is valid, of so then done, else compute next		if (xc2 < min_clip_x || xc2 > max_clip_x)		{			// east vline intersection			xc2 = (Uint16) max_clip_x;			yc2 = (Uint16) (y2 + 0.5 + (max_clip_x - x2) 			                * (y1 - y2) / (x1 - x2));		} 		break;	case CLIP_CODE_SE:		// south hline intersection		yc2 = (Uint16) max_clip_y;		xc2 = (Uint16) (x2 + 0.5 + (max_clip_y - y2) 		                * (x1 - x2) / (y1 - y2));			// test if intersection is valid, of so then done, else compute next		if (xc2 < min_clip_x || xc2 > max_clip_x)		{			// east vline intersection			xc2 = (Uint16) max_clip_x;			yc2 = (Uint16) (y2 + 0.5 + (max_clip_x - x2)			                * (y1 - y2) / (x1 - x2));		} 		break;	case CLIP_CODE_NW:		// north hline intersection		yc2 = (Uint16) min_clip_y;		xc2 = (Uint16) (x2 + 0.5 + (min_clip_y - y2)		                * (x1 - x2) / (y1 - y2));		// test if intersection is valid, of so then done, else compute next		if (xc2 < min_clip_x || xc2 > max_clip_x)		{			xc2 = (Uint16) min_clip_x;			yc2 = (Uint16) (y2 + 0.5 + (min_clip_x - x2)			                * (y1 - y2) / (x1 - x2));			} 		break;	case CLIP_CODE_SW:		// south hline intersection		yc2 = (Uint16) max_clip_y;		xc2 = (Uint16) (x2 + 0.5 + (max_clip_y - y2) 		                * (x1 - x2) / (y1 - y2));	 		// test if intersection is valid, of so then done, else compute next		if (xc2 < min_clip_x || xc2 > max_clip_x)		{			xc2 = (Uint16) min_clip_x;			yc2 = (Uint16) (y2 + 0.5 + (min_clip_x - x2)			                * (y1 - y2) / (x1 - x2));			} 		break;	default:		break;	} // switch	// do bounds check	if ((xc1 < min_clip_x) || (xc1 > max_clip_x) ||	    (yc1 < min_clip_y) || (yc1 > max_clip_y) ||	    (xc2 < min_clip_x) || (xc2 > max_clip_x) ||	    (yc2 < min_clip_y) || (yc2 > max_clip_y) )	{		return 0;	} 	// store vars back	x1 = xc1;	y1 = yc1;	x2 = xc2;	y2 = yc2;	return 1;#undef CLIP_CODE_C  #undef CLIP_CODE_N #undef CLIP_CODE_S #undef CLIP_CODE_E #undef CLIP_CODE_W #undef CLIP_CODE_NE #undef CLIP_CODE_SE #undef CLIP_CODE_NW #undef CLIP_CODE_SW }void Painter::drawLine (Uint16 x, Uint16 y, Uint16 x2, Uint16 y2, Uint32 color){	if (y == y2) 	{		Uint16 w;		x > x2 ? w = x - x2 + 1, x = x2 : w = x2 - x + 1;		drawHLine (x, y, w, color);		return;	}	else if (x == x2)	{		Uint16 h;		y > y2 ? h = y - y2 + 1, y = y2 : h = y2 - y + 1;		drawVLine (x, y, h, color);		return;	}	if (m_clipping)	{		if (!clipLine (x, y, x2, y2, m_clip_rect.x, m_clip_x2,			       m_clip_rect.y, m_clip_y2))		return;	}						  	m_gfx->drawLine (m_target_surface, x, y, x2, y2, color);}voidPainter::drawRect (Uint16 x, Uint16 y, Uint16 w, Uint16 h, Uint32 color){	if (w == 0 || h == 0)		return;	if (w == 1 && h == 1)	{		putPixel (x, y, color);		return;	}	if (h == 1)	{		drawHLine (x, y, w, color);		return;	}			if (w == 1)	{		drawVLine (x, y, h, color);		return;	}	drawHLine (x, y, w, color);	drawHLine (x, y + h - 1, w, color);	if (h > 2)	{		drawVLine (x, y + 1, h - 2, color);		drawVLine (x + w - 1, y + 1, h - 2, color);	}}voidPainter::fillRect (Uint16 x, Uint16 y, Uint16 w, Uint16 h, Uint32 color){	Uint16 _x;	Uint16 _y;	Uint16 _w;	Uint16 _h;#define ___MIN(a,b) (a < b ? a : b)#define ___MAX(a,b) (a > b ? a : b)	if (m_clipping)	{		if (x > m_clip_x2 || y > m_clip_y2)			return;		if (x + w < m_clip_rect.x + 1 ||		    y + h < m_clip_rect.y + 1)						return;			_x = ___MAX (x, m_clip_rect.x);		_y = ___MAX (y, m_clip_rect.y);		_w = ___MIN (x + w - 1, m_clip_x2) - _x + 1;		_h = ___MIN (y + h - 1, m_clip_y2) - _y + 1;	}	else	{		_x = x;		_y = y;		_w = w;		_h = h;	}		#undef ___MIN#undef ___MAX	if (_w == 0 || _h == 0)		return;		if (_w == 1 && h == 1)	{		m_gfx->putPixel (m_target_surface, _x, _y, color);		return;	}			if (_h == 1)	{		m_gfx->drawHLine (m_target_surface, _x, _y, _w, color);		return;	}			if (_w == 1)	{		m_gfx->drawVLine (m_target_surface, _x, _y, _h, color);		return;	}			Uint16 i;		if (_h > _w)	{		for (i = 0; i < _w; ++i)		{			m_gfx->drawVLine (m_target_surface, _x + i, _y, _h,					  color);		}	}	else	{		for (i = 0; i < _h; ++i)		{			m_gfx->drawHLine (m_target_surface, _x, _y + i, _w,					  color);		}	}}} // namespace SEL