diff options
| author | Joel Bodenmann <joel@unormal.org> | 2013-11-10 21:07:16 +0100 | 
|---|---|---|
| committer | Joel Bodenmann <joel@unormal.org> | 2013-11-10 21:07:16 +0100 | 
| commit | da2740b706d720292113445ee1db30f8a9873dc4 (patch) | |
| tree | 8f8b1902d4af6a23b3daf26990f580b76ea31ea4 /src | |
| parent | 6ca3537a696e7ace8098771a9a7105380604253d (diff) | |
| parent | a8ce005e2621b0108863297948cea0fa52c8bf2a (diff) | |
| download | uGFX-da2740b706d720292113445ee1db30f8a9873dc4.tar.gz uGFX-da2740b706d720292113445ee1db30f8a9873dc4.tar.bz2 uGFX-da2740b706d720292113445ee1db30f8a9873dc4.zip  | |
merging GDISPStreaming
Diffstat (limited to 'src')
| -rw-r--r-- | src/gdisp/gdisp.c | 3098 | ||||
| -rw-r--r-- | src/gdisp/image.c | 17 | ||||
| -rw-r--r-- | src/gdisp/image_bmp.c | 12 | ||||
| -rw-r--r-- | src/gdisp/image_gif.c | 98 | ||||
| -rw-r--r-- | src/gdisp/image_native.c | 6 | ||||
| -rw-r--r-- | src/gfx.c | 1 | ||||
| -rw-r--r-- | src/ginput/mouse.c | 99 | ||||
| -rw-r--r-- | src/gmisc/trig.c | 44 | ||||
| -rw-r--r-- | src/gwin/button.c | 66 | ||||
| -rw-r--r-- | src/gwin/checkbox.c | 20 | ||||
| -rw-r--r-- | src/gwin/console.c | 16 | ||||
| -rw-r--r-- | src/gwin/gimage.c | 22 | ||||
| -rw-r--r-- | src/gwin/graph.c | 20 | ||||
| -rw-r--r-- | src/gwin/gwidget.c | 10 | ||||
| -rw-r--r-- | src/gwin/gwin.c | 99 | ||||
| -rw-r--r-- | src/gwin/gwm.c | 22 | ||||
| -rw-r--r-- | src/gwin/label.c | 16 | ||||
| -rw-r--r-- | src/gwin/list.c | 26 | ||||
| -rw-r--r-- | src/gwin/radio.c | 34 | ||||
| -rw-r--r-- | src/gwin/slider.c | 50 | 
20 files changed, 2936 insertions, 840 deletions
diff --git a/src/gdisp/gdisp.c b/src/gdisp/gdisp.c index 176839b4..2af30f15 100644 --- a/src/gdisp/gdisp.c +++ b/src/gdisp/gdisp.c @@ -19,481 +19,2492 @@  /* Include the low level driver information */  #include "gdisp/lld/gdisp_lld.h" +#if 1 +	#undef INLINE +	#define INLINE	inline +#else +	#undef INLINE +	#define INLINE +#endif + +// Number of milliseconds for the startup logo - 0 means disabled. +#define GDISP_STARTUP_LOGO_TIMEOUT		1000 + +// The color to clear the display on startup +#define GDISP_STARTUP_COLOR				Black +  /*===========================================================================*/  /* Driver local variables.                                                   */  /*===========================================================================*/ -#if GDISP_NEED_MULTITHREAD || GDISP_NEED_ASYNC -	static gfxMutex			gdispMutex; +// The controller array, the display array and the default display +#if GDISP_TOTAL_CONTROLLERS > 1 +	typedef const struct GDISPVMT const	VMTEL[1]; +	extern VMTEL			GDISP_CONTROLLER_LIST; +	static const struct GDISPVMT const *	ControllerList[GDISP_TOTAL_CONTROLLERS] = {GDISP_CONTROLLER_LIST}; +	static const unsigned					DisplayCountList[GDISP_TOTAL_CONTROLLERS] = {GDISP_CONTROLLER_DISPLAYS}; +#endif + +#if GDISP_NEED_TIMERFLUSH +	static GTimer	FlushTimer;  #endif -#if GDISP_NEED_ASYNC -	#define GDISP_THREAD_STACK_SIZE	256		/* Just a number - not yet a reflection of actual use */ -	#define GDISP_QUEUE_SIZE		8		/* We only allow a short queue */ +static GDisplay GDisplayArray[GDISP_TOTAL_DISPLAYS]; +GDisplay	*GDISP = GDisplayArray; -	static gfxQueue 		gdispQueue; -	static gfxMutex			gdispMsgsMutex; -	static gfxSem			gdispMsgsSem; -	static gdisp_lld_msg_t	gdispMsgs[GDISP_QUEUE_SIZE]; -	static 					DECLARE_THREAD_STACK(waGDISPThread, GDISP_THREAD_STACK_SIZE); +#if GDISP_NEED_MULTITHREAD +	#define MUTEX_INIT(g)		gfxMutexInit(&(g)->mutex) +	#define MUTEX_ENTER(g)		gfxMutexEnter(&(g)->mutex) +	#define MUTEX_EXIT(g)		gfxMutexExit(&(g)->mutex) +#else +	#define MUTEX_INIT(g) +	#define MUTEX_ENTER(g) +	#define MUTEX_EXIT(g)  #endif -/*===========================================================================*/ -/* Driver local functions.                                                   */ -/*===========================================================================*/ +#define NEED_CLIPPING	(GDISP_HARDWARE_CLIP != TRUE && (GDISP_NEED_VALIDATION || GDISP_NEED_CLIP)) + +#if !NEED_CLIPPING +	#define TEST_CLIP_AREA(g) +#elif GDISP_HARDWARE_CLIP == HARDWARE_AUTODETECT +	#define TEST_CLIP_AREA(g)																					\ +			if (!g->vmt->setclip) {																				\ +				if ((g)->p.x < (g)->clipx0) { (g)->p.cx -= (g)->clipx0 - (g)->p.x; (g)->p.x = (g)->clipx0; }	\ +				if ((g)->p.y < (g)->clipy0) { (g)->p.cy -= (g)->clipy0 - (g)->p.y; (g)->p.y = (g)->clipy0; }	\ +				if ((g)->p.x + (g)->p.cx > (g)->clipx1)	(g)->p.cx = (g)->clipx1 - (g)->p.x;						\ +				if ((g)->p.y + (g)->p.cy > (g)->clipy1)	(g)->p.cy = (g)->clipy1 - (g)->p.y;						\ +			}																									\ +			if ((g)->p.cx > 0 && (g)->p.cy > 0) +#else +	#define TEST_CLIP_AREA(g)																				\ +			if ((g)->p.x < (g)->clipx0) { (g)->p.cx -= (g)->clipx0 - (g)->p.x; (g)->p.x = (g)->clipx0; }	\ +			if ((g)->p.y < (g)->clipy0) { (g)->p.cy -= (g)->clipy0 - (g)->p.y; (g)->p.y = (g)->clipy0; }	\ +			if ((g)->p.x + (g)->p.cx > (g)->clipx1)	(g)->p.cx = (g)->clipx1 - (g)->p.x;						\ +			if ((g)->p.y + (g)->p.cy > (g)->clipy1)	(g)->p.cy = (g)->clipy1 - (g)->p.y;						\ +			if ((g)->p.cx > 0 && (g)->p.cy > 0) +#endif -#if GDISP_NEED_ASYNC -	static DECLARE_THREAD_FUNCTION(GDISPThreadHandler, arg) { -		(void)arg; -		gdisp_lld_msg_t	*pmsg; +/*==========================================================================*/ +/* Internal functions.														*/ +/*==========================================================================*/ -		while(1) { -			/* Wait for msg with work to do. */ -			pmsg = (gdisp_lld_msg_t *)gfxQueueGet(&gdispQueue, TIME_INFINITE); +#if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE +	static INLINE void setglobalwindow(GDisplay *g) { +		coord_t	x, y; +		x = g->p.x; y = g->p.y; +		g->p.x = g->p.y = 0; +		g->p.cx = g->g.Width; g->p.cy = g->g.Height; +		gdisp_lld_write_start(g); +		g->p.x = x; g->p.y = y; +		g->flags |= GDISP_FLG_SCRSTREAM; +	} +#endif -			/* OK - we need to obtain the mutex in case a synchronous operation is occurring */ -			gfxMutexEnter(&gdispMutex); +#if GDISP_NEED_AUTOFLUSH && GDISP_HARDWARE_FLUSH == HARDWARE_AUTODETECT +	#define autoflush_stopdone(g)	if (g->vmt->flush) gdisp_lld_flush(g) +#elif GDISP_NEED_AUTOFLUSH && GDISP_HARDWARE_FLUSH +	#define autoflush_stopdone(g)	gdisp_lld_flush(g) +#else +	#define autoflush_stopdone(g) +#endif -			gdisp_lld_msg_dispatch(pmsg); +#if GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE +	#define autoflush(g)									\ +			{												\ +				if ((g->flags & GDISP_FLG_SCRSTREAM)) {		\ +					gdisp_lld_write_stop(g);				\ +					g->flags &= ~GDISP_FLG_SCRSTREAM;		\ +				}											\ +				autoflush_stopdone(g);						\ +			} +#else +	#define autoflush(g)		autoflush_stopdone(g) +#endif -			/* Mark the message as free */ -			pmsg->action = GDISP_LLD_MSG_NOP; +// drawpixel(g) +// Parameters:	x,y +// Alters:		cx, cy (if using streaming) +// Does not clip +static INLINE void drawpixel(GDisplay *g) { -			gfxMutexExit(&gdispMutex); +	// Best is hardware accelerated pixel draw +	#if GDISP_HARDWARE_DRAWPIXEL +		#if GDISP_HARDWARE_DRAWPIXEL == HARDWARE_AUTODETECT +			if (g->vmt->pixel) +		#endif +		{ +			gdisp_lld_draw_pixel(g); +			return;  		} -		return 0; -	} +	#endif + +	// Next best is cursor based streaming +	#if GDISP_HARDWARE_DRAWPIXEL != TRUE && GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE +		#if GDISP_HARDWARE_STREAM_POS == HARDWARE_AUTODETECT +			if (g->vmt->writepos) +		#endif +		{ +			if (!(g->flags & GDISP_FLG_SCRSTREAM)) +				setglobalwindow(g); +			gdisp_lld_write_pos(g); +			gdisp_lld_write_color(g); +			return; +		} +	#endif -	static gdisp_lld_msg_t *gdispAllocMsg(gdisp_msgaction_t action) { -		gdisp_lld_msg_t	*p; +	// Worst is general streaming +	#if GDISP_HARDWARE_DRAWPIXEL != TRUE && GDISP_HARDWARE_STREAM_POS != TRUE && GDISP_HARDWARE_STREAM_WRITE +		// The following test is unneeded because we are guaranteed to have streaming if we don't have drawpixel +		//#if GDISP_HARDWARE_STREAM_WRITE == HARDWARE_AUTODETECT +		//	if (g->vmt->writestart) +		//#endif +		{ +			g->p.cx = g->p.cy = 1; +			gdisp_lld_write_start(g); +			gdisp_lld_write_color(g); +			gdisp_lld_write_stop(g); +			return; +		} +	#endif +} -		while(1) {		/* To be sure, to be sure */ +// drawpixel_clip(g) +// Parameters:	x,y +// Alters:		cx, cy (if using streaming) +#if NEED_CLIPPING +	static INLINE void drawpixel_clip(GDisplay *g) { +		#if GDISP_HARDWARE_CLIP == HARDWARE_AUTODETECT +			if (!g->vmt->setclip) +		#endif +		{ +			if (g->p.x < g->clipx0 || g->p.x >= g->clipx1 || g->p.y < g->clipy0 || g->p.y >= g->clipy1) +				return; +		} +		drawpixel(g); +	} +#else +	#define drawpixel_clip(g)		drawpixel(g) +#endif -			/* Wait for a slot */ -			gfxSemWait(&gdispMsgsSem, TIME_INFINITE); +// fillarea(g) +// Parameters:	x,y cx,cy and color +// Alters:		nothing +// Note:		This is not clipped +// Resets the streaming area if GDISP_HARDWARE_STREAM_WRITE and GDISP_HARDWARE_STREAM_POS is set. +static INLINE void fillarea(GDisplay *g) { + +	// Best is hardware accelerated area fill +	#if GDISP_HARDWARE_FILLS +		#if GDISP_HARDWARE_FILLS == HARDWARE_AUTODETECT +			if (g->vmt->fill) +		#endif +		{ +			gdisp_lld_fill_area(g); +			return; +		} +	#endif -			/* Find the slot */ -			gfxMutexEnter(&gdispMsgsMutex); -			for(p=gdispMsgs; p < &gdispMsgs[GDISP_QUEUE_SIZE]; p++) { -				if (p->action == GDISP_LLD_MSG_NOP) { -					/* Allocate it */ -					p->action = action; -					gfxMutexExit(&gdispMsgsMutex); -					return p; +	// Next best is hardware streaming +	#if GDISP_HARDWARE_FILLS != TRUE && GDISP_HARDWARE_STREAM_WRITE +		#if GDISP_HARDWARE_STREAM_WRITE == HARDWARE_AUTODETECT +			if (g->vmt->writestart) +		#endif +		{ +			uint32_t	area; + +			#if GDISP_HARDWARE_STREAM_POS +				if ((g->flags & GDISP_FLG_SCRSTREAM)) { +					gdisp_lld_write_stop(g); +					g->flags &= ~GDISP_FLG_SCRSTREAM;  				} -			} -			gfxMutexExit(&gdispMsgsMutex); +			#endif + +			area = (uint32_t)g->p.cx * g->p.cy; +			gdisp_lld_write_start(g); +			#if GDISP_HARDWARE_STREAM_POS +				#if GDISP_HARDWARE_STREAM_POS == HARDWARE_AUTODETECT +					if (g->vmt->writepos) +				#endif +				gdisp_lld_write_pos(g); +			#endif +			for(; area; area--) +				gdisp_lld_write_color(g); +			gdisp_lld_write_stop(g); +			return; +		} +	#endif -			/* Oops - none found, try again */ -			gfxSemSignal(&gdispMsgsSem); +	// Worst is pixel drawing +	#if GDISP_HARDWARE_FILLS != TRUE && GDISP_HARDWARE_STREAM_WRITE != TRUE && GDISP_HARDWARE_DRAWPIXEL +		// The following test is unneeded because we are guaranteed to have draw pixel if we don't have streaming +		//#if GDISP_HARDWARE_DRAWPIXEL == HARDWARE_AUTODETECT +		//	if (g->vmt->pixel) +		//#endif +		{ +			coord_t x0, y0, x1, y1; + +			x0 = g->p.x; +			y0 = g->p.y; +			x1 = g->p.x + g->p.cx; +			y1 = g->p.y + g->p.cy; +			for(; g->p.y < y1; g->p.y++, g->p.x = x0) +				for(; g->p.x < x1; g->p.x++) +					gdisp_lld_draw_pixel(g); +			g->p.y = y0; +			return;  		} +	#endif +} + +// Parameters:	x,y and x1 +// Alters:		x,y x1,y1 cx,cy +// Assumes the window covers the screen and a write_stop() will occur later +//	if GDISP_HARDWARE_STREAM_WRITE and GDISP_HARDWARE_STREAM_POS is set. +static void hline_clip(GDisplay *g) { +	// Swap the points if necessary so it always goes from x to x1 +	if (g->p.x1 < g->p.x) { +		g->p.cx = g->p.x; g->p.x = g->p.x1; g->p.x1 = g->p.cx;  	} -#endif -/*===========================================================================*/ -/* Driver exported functions.                                                */ -/*===========================================================================*/ +	// Clipping +	#if NEED_CLIPPING +		#if GDISP_HARDWARE_CLIP == HARDWARE_AUTODETECT +			if (!g->vmt->setclip) +		#endif +		{ +			if (g->p.y < g->clipy0 || g->p.y >= g->clipy1) return; +			if (g->p.x < g->clipx0) g->p.x = g->clipx0; +			if (g->p.x1 >= g->clipx1) g->p.x1 = g->clipx1 - 1; +			if (g->p.x1 < g->p.x) return; +		} +	#endif -/* Our module initialiser */ -#if GDISP_NEED_MULTITHREAD -	void _gdispInit(void) { -		/* Initialise Mutex */ -		gfxMutexInit(&gdispMutex); - -		/* Initialise driver */ -		gfxMutexEnter(&gdispMutex); -		gdisp_lld_init(); -		gfxMutexExit(&gdispMutex); -	} -#elif GDISP_NEED_ASYNC -	void _gdispInit(void) { -		unsigned		i; -		gfxThreadHandle	hth; - -		/* Mark all the Messages as free */ -		for(i=0; i < GDISP_QUEUE_SIZE; i++) -			gdispMsgs[i].action = GDISP_LLD_MSG_NOP; - -		/* Initialise our Queue, Mutex's and Counting Semaphore. -		 * 	A Mutex is required as well as the Queue and Thread because some calls have to be synchronous. -		 *	Synchronous calls get handled by the calling thread, asynchronous by our worker thread. -		 */ -		gfxQueueInit(&gdispQueue); -		gfxMutexInit(&gdispMutex); -		gfxMutexInit(&gdispMsgsMutex); -		gfxSemInit(&gdispMsgsSem, GDISP_QUEUE_SIZE, GDISP_QUEUE_SIZE); - -		hth = gfxThreadCreate(waGDISPThread, sizeof(waGDISPThread), GDISP_THREAD_PRIORITY, GDISPThreadHandler, NULL); -		if (hth) gfxThreadClose(hth); - -		/* Initialise driver - synchronous */ -		gfxMutexEnter(&gdispMutex); -		gdisp_lld_init(); -		gfxMutexExit(&gdispMutex); +	// This is an optimization for the point case. It is only worthwhile however if we +	// have hardware fills or if we support both hardware pixel drawing and hardware streaming +	#if GDISP_HARDWARE_FILLS || (GDISP_HARDWARE_DRAWPIXEL && GDISP_HARDWARE_STREAM_WRITE) +		// Is this a point +		if (g->p.x == g->p.x1) { +			drawpixel(g); +			return; +		} +	#endif + +	// Best is hardware accelerated area fill +	#if GDISP_HARDWARE_FILLS +		#if GDISP_HARDWARE_FILLS == HARDWARE_AUTODETECT +			if (g->vmt->fill) +		#endif +		{ +			g->p.cx = g->p.x1 - g->p.x + 1; +			g->p.cy = 1; +			gdisp_lld_fill_area(g); +			return; +		} +	#endif + +	// Next best is cursor based streaming +	#if GDISP_HARDWARE_FILLS != TRUE && GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE +		#if GDISP_HARDWARE_STREAM_POS == HARDWARE_AUTODETECT +			if (g->vmt->writepos) +		#endif +		{ +			if (!(g->flags & GDISP_FLG_SCRSTREAM)) +				setglobalwindow(g); +			g->p.cx = g->p.x1 - g->p.x + 1; +			gdisp_lld_write_pos(g); +			do { gdisp_lld_write_color(g); } while(--g->p.cx); +			return; +		} +	#endif + +	// Next best is streaming +	#if GDISP_HARDWARE_FILLS != TRUE && GDISP_HARDWARE_STREAM_POS != TRUE && GDISP_HARDWARE_STREAM_WRITE +		#if GDISP_HARDWARE_STREAM_WRITE == HARDWARE_AUTODETECT +			if (g->vmt->writestart) +		#endif +		{ +			g->p.cx = g->p.x1 - g->p.x + 1; +			g->p.cy = 1; +			gdisp_lld_write_start(g); +			do { gdisp_lld_write_color(g); } while(--g->p.cx); +			gdisp_lld_write_stop(g); +			return; +		} +	#endif + +	// Worst is drawing pixels +	#if GDISP_HARDWARE_FILLS != TRUE && GDISP_HARDWARE_STREAM_WRITE != TRUE && GDISP_HARDWARE_DRAWPIXEL +		// The following test is unneeded because we are guaranteed to have draw pixel if we don't have streaming +		//#if GDISP_HARDWARE_DRAWPIXEL == HARDWARE_AUTODETECT +		//	if (g->vmt->pixel) +		//#endif +		{ +			for(; g->p.x <= g->p.x1; g->p.x++) +				gdisp_lld_draw_pixel(g); +			return; +		} +	#endif +} + +// Parameters:	x,y and y1 +// Alters:		x,y x1,y1 cx,cy +static void vline_clip(GDisplay *g) { +	// Swap the points if necessary so it always goes from y to y1 +	if (g->p.y1 < g->p.y) { +		g->p.cy = g->p.y; g->p.y = g->p.y1; g->p.y1 = g->p.cy;  	} -#else -	void _gdispInit(void) { -		gdisp_lld_init(); + +	// Clipping +	#if NEED_CLIPPING +		#if GDISP_HARDWARE_CLIP == HARDWARE_AUTODETECT +			if (!g->vmt->setclip) +		#endif +		{ +			if (g->p.x < g->clipx0 || g->p.x >= g->clipx1) return; +			if (g->p.y < g->clipy0) g->p.y = g->clipy0; +			if (g->p.y1 >= g->clipy1) g->p.y1 = g->clipy1 - 1; +			if (g->p.y1 < g->p.y) return; +		} +	#endif + +	// This is an optimization for the point case. It is only worthwhile however if we +	// have hardware fills or if we support both hardware pixel drawing and hardware streaming +	#if GDISP_HARDWARE_FILLS || (GDISP_HARDWARE_DRAWPIXEL && GDISP_HARDWARE_STREAM_WRITE) || (GDISP_HARDWARE_STREAM_POS && GDISP_HARDWARE_STREAM_WRITE) +		// Is this a point +		if (g->p.y == g->p.y1) { +			drawpixel(g); +			return; +		} +	#endif + +	// Best is hardware accelerated area fill +	#if GDISP_HARDWARE_FILLS +		#if GDISP_HARDWARE_FILLS == HARDWARE_AUTODETECT +			if (g->vmt->fill) +		#endif +		{ +			g->p.cy = g->p.y1 - g->p.y + 1; +			g->p.cx = 1; +			gdisp_lld_fill_area(g); +			return; +		} +	#endif + +	// Next best is streaming +	#if GDISP_HARDWARE_FILLS != TRUE && GDISP_HARDWARE_STREAM_WRITE +		#if GDISP_HARDWARE_STREAM_WRITE == HARDWARE_AUTODETECT +			if (g->vmt->writestart) +		#endif +		{ +			#if GDISP_HARDWARE_STREAM_POS +				if ((g->flags & GDISP_FLG_SCRSTREAM)) { +					gdisp_lld_write_stop(g); +					g->flags &= ~GDISP_FLG_SCRSTREAM; +				} +			#endif +			g->p.cy = g->p.y1 - g->p.y + 1; +			g->p.cx = 1; +			gdisp_lld_write_start(g); +			#if GDISP_HARDWARE_STREAM_POS +				#if GDISP_HARDWARE_STREAM_POS == HARDWARE_AUTODETECT +					if (g->vmt->writepos) +				#endif +				gdisp_lld_write_pos(g); +			#endif +			do { gdisp_lld_write_color(g); } while(--g->p.cy); +			gdisp_lld_write_stop(g); +			return; +		} +	#endif + +	// Worst is drawing pixels +	#if GDISP_HARDWARE_FILLS != TRUE && GDISP_HARDWARE_STREAM_WRITE != TRUE && GDISP_HARDWARE_DRAWPIXEL +		// The following test is unneeded because we are guaranteed to have draw pixel if we don't have streaming +		//#if GDISP_HARDWARE_DRAWPIXEL == HARDWARE_AUTODETECT +		//	if (g->vmt->pixel) +		//#endif +		{ +			for(; g->p.y <= g->p.y1; g->p.y++) +				gdisp_lld_draw_pixel(g); +			return; +		} +	#endif +} + +// Parameters:	x,y and x1,y1 +// Alters:		x,y x1,y1 cx,cy +static void line_clip(GDisplay *g) { +	int16_t dy, dx; +	int16_t addx, addy; +	int16_t P, diff, i; + +	// Is this a horizontal line (or a point) +	if (g->p.y == g->p.y1) { +		hline_clip(g); +		return;  	} -#endif -#if GDISP_NEED_MULTITHREAD -	bool_t gdispIsBusy(void) { -		return FALSE; +	// Is this a vertical line (or a point) +	if (g->p.x == g->p.x1) { +		vline_clip(g); +		return;  	} -#elif GDISP_NEED_ASYNC -	bool_t gdispIsBusy(void) { -		return !gfxQueueIsEmpty(&gdispQueue); + +	// Not horizontal or vertical + +	// Use Bresenham's line drawing algorithm. +	//	This should be replaced with fixed point slope based line drawing +	//	which is more efficient on modern processors as it branches less. +	//	When clipping is needed, all the clipping could also be done up front +	//	instead of on each pixel. + +	if (g->p.x1 >= g->p.x) { +		dx = g->p.x1 - g->p.x; +		addx = 1; +	} else { +		dx = g->p.x - g->p.x1; +		addx = -1; +	} +	if (g->p.y1 >= g->p.y) { +		dy = g->p.y1 - g->p.y; +		addy = 1; +	} else { +		dy = g->p.y - g->p.y1; +		addy = -1;  	} -#endif -#if GDISP_NEED_MULTITHREAD -	void gdispClear(color_t color) { -		gfxMutexEnter(&gdispMutex); -		gdisp_lld_clear(color); -		gfxMutexExit(&gdispMutex); +	if (dx >= dy) { +		dy <<= 1; +		P = dy - dx; +		diff = P - dx; + +		for(i=0; i<=dx; ++i) { +			drawpixel_clip(g); +			if (P < 0) { +				P  += dy; +				g->p.x += addx; +			} else { +				P  += diff; +				g->p.x += addx; +				g->p.y += addy; +			} +		} +	} else { +		dx <<= 1; +		P = dx - dy; +		diff = P - dy; + +		for(i=0; i<=dy; ++i) { +			drawpixel_clip(g); +			if (P < 0) { +				P  += dx; +				g->p.y += addy; +			} else { +				P  += diff; +				g->p.x += addx; +				g->p.y += addy; +			} +		}  	} -#elif GDISP_NEED_ASYNC -	void gdispClear(color_t color) { -		gdisp_lld_msg_t *p = gdispAllocMsg(GDISP_LLD_MSG_CLEAR); -		p->clear.color = color; -		gfxQueuePut(&gdispQueue, &p->qi, TIME_IMMEDIATE); +} + +#if GDISP_STARTUP_LOGO_TIMEOUT > 0 +	static void StatupLogoDisplay(GDisplay *g) { +		coord_t			x, y, w; +		const coord_t *	p; +		static const coord_t blks[] = { +				// u +				2, 6, 1, 10, +				3, 11, 4, 1, +				6, 6, 1, 6, +				// G +				8, 0, 1, 12, +				9, 0, 6, 1, +				9, 11, 6, 1, +				14, 6, 1, 5, +				12, 6, 2, 1, +				// F +				16, 0, 1, 12, +				17, 0, 6, 1, +				17, 6, 3, 1, +				// X +				22, 6, 7, 1, +				24, 0, 1, 6, +				22, 7, 1, 5, +				28, 0, 1, 6, +				26, 7, 1, 5, +		}; + +		// Get a starting position and a scale +		// Work on a 8x16 grid for each char, 4 chars (uGFX) in 1 line, using half the screen +		w = g->g.Width/(8*4*2); +		if (!w) w = 1; +		x = (g->g.Width - (8*4)*w)/2; +		y = (g->g.Height - (16*1)*w)/2; + +		// Simple but crude! +		for(p = blks; p < blks+sizeof(blks)/sizeof(blks[0]); p+=4) +			gdispGFillArea(g, x+p[0]*w, y+p[1]*w, p[2]*w, p[3]*w, Blue);  	}  #endif -#if GDISP_NEED_MULTITHREAD -	void gdispDrawPixel(coord_t x, coord_t y, color_t color) { -		gfxMutexEnter(&gdispMutex); -		gdisp_lld_draw_pixel(x, y, color); -		gfxMutexExit(&gdispMutex); -	} -#elif GDISP_NEED_ASYNC -	void gdispDrawPixel(coord_t x, coord_t y, color_t color) { -		gdisp_lld_msg_t *p = gdispAllocMsg(GDISP_LLD_MSG_DRAWPIXEL); -		p->drawpixel.x = x; -		p->drawpixel.y = y; -		p->drawpixel.color = color; -		gfxQueuePut(&gdispQueue, &p->qi, TIME_IMMEDIATE); +#if GDISP_NEED_TIMERFLUSH +	static void FlushTimerFn(void *param) { +		GDisplay *	g; +		(void)		param; + +		for(g = GDisplayArray; g < &GDisplayArray[GDISP_TOTAL_DISPLAYS]; g++) +			gdispGFlush(g);  	}  #endif -	 -#if GDISP_NEED_MULTITHREAD -	void gdispDrawLine(coord_t x0, coord_t y0, coord_t x1, coord_t y1, color_t color) { -		gfxMutexEnter(&gdispMutex); -		gdisp_lld_draw_line(x0, y0, x1, y1, color); -		gfxMutexExit(&gdispMutex); -	} -#elif GDISP_NEED_ASYNC -	void gdispDrawLine(coord_t x0, coord_t y0, coord_t x1, coord_t y1, color_t color) { -		gdisp_lld_msg_t *p = gdispAllocMsg(GDISP_LLD_MSG_DRAWLINE); -		p->drawline.x0 = x0; -		p->drawline.y0 = y0; -		p->drawline.x1 = x1; -		p->drawline.y1 = y1; -		p->drawline.color = color; -		gfxQueuePut(&gdispQueue, &p->qi, TIME_IMMEDIATE); + +/*===========================================================================*/ +/* Driver exported functions.                                                */ +/*===========================================================================*/ + +/* Our module initialiser */ +void _gdispInit(void) { +	GDisplay		*g; +	uint16_t		i; +	#if GDISP_TOTAL_CONTROLLERS > 1 +		uint16_t	j; +	#endif + +	/* Initialise driver */ +	#if GDISP_TOTAL_CONTROLLERS > 1 +		for(g = GDisplayArray, j=0; j < GDISP_TOTAL_CONTROLLERS; j++) +			for(i = 0; i < DisplayCountList[j]; g++, i++) { +				g->vmt = ControllerList[j]; +				g->systemdisplay = j*GDISP_TOTAL_CONTROLLERS+i; +				g->controllerdisplay = i; +	#else +		for(g = GDisplayArray, i = 0; i < GDISP_TOTAL_DISPLAYS; g++, i++) { +			g->systemdisplay = i; +			g->controllerdisplay = i; +	#endif +			MUTEX_INIT(g); +			MUTEX_ENTER(g); +			g->flags = 0; +			gdisp_lld_init(g); + +			#if defined(GDISP_DEFAULT_ORIENTATION) && GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL +				g->p.x = GDISP_CONTROL_ORIENTATION; +				g->p.ptr = (void *)GDISP_DEFAULT_ORIENTATION; +				#if GDISP_HARDWARE_CONTROL == HARDWARE_AUTODETECT +					if (g->vmt->control) +				#endif +				gdisp_lld_control(g); +			#endif + +			// Set the initial clipping region +			#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP + +				// Best is hardware clipping +				#if GDISP_HARDWARE_CLIP +					#if GDISP_HARDWARE_CLIP == HARDWARE_AUTODETECT +						if (g->vmt->setclip) +					#endif +					{ +						g->p.x = 0; +						g->p.y = 0; +						g->p.cx = g->g.Width; +						g->p.cy = g->g.Height; +						gdisp_lld_set_clip(g); +					} +					#if GDISP_HARDWARE_CLIP == HARDWARE_AUTODETECT +						else +					#endif +				#endif + +				// Worst is software clipping +				#if GDISP_HARDWARE_CLIP != TRUE +					{ +						g->clipx0 = 0; +						g->clipy0 = 0; +						g->clipx1 = g->g.Width; +						g->clipy1 = g->g.Height; +					} +				#endif +			#endif +			MUTEX_EXIT(g); +			gdispGClear(g, GDISP_STARTUP_COLOR); +			#if GDISP_STARTUP_LOGO_TIMEOUT > 0 +				StatupLogoDisplay(g); +			#endif +			#if !GDISP_NEED_AUTOFLUSH && GDISP_HARDWARE_FLUSH +				gdispGFlush(g); +			#endif  	} -#endif +	#if GDISP_STARTUP_LOGO_TIMEOUT > 0 +		gfxSleepMilliseconds(GDISP_STARTUP_LOGO_TIMEOUT); +		for(g = GDisplayArray, i = 0; i < GDISP_TOTAL_DISPLAYS; g++, i++) { +			gdispGClear(g, GDISP_STARTUP_COLOR); +			#if !GDISP_NEED_AUTOFLUSH && GDISP_HARDWARE_FLUSH +				gdispGFlush(g); +			#endif +		} +	#endif -#if GDISP_NEED_MULTITHREAD -	void gdispFillArea(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { -		gfxMutexEnter(&gdispMutex); -		gdisp_lld_fill_area(x, y, cx, cy, color); -		gfxMutexExit(&gdispMutex); -	} -#elif GDISP_NEED_ASYNC -	void gdispFillArea(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { -		gdisp_lld_msg_t *p = gdispAllocMsg(GDISP_LLD_MSG_FILLAREA); -		p->fillarea.x = x; -		p->fillarea.y = y; -		p->fillarea.cx = cx; -		p->fillarea.cy = cy; -		p->fillarea.color = color; -		gfxQueuePut(&gdispQueue, &p->qi, TIME_IMMEDIATE); +	#if GDISP_NEED_TIMERFLUSH +		gtimerInit(&FlushTimer); +		gtimerStart(&FlushTimer, FlushTimerFn, 0, TRUE, GDISP_NEED_TIMERFLUSH); +	#endif +} + +GDisplay *gdispGetDisplay(unsigned display) { +	if (display >= GDISP_TOTAL_DISPLAYS) +		return 0; +	return &GDisplayArray[display]; +} + +void gdispSetDisplay(GDisplay *g) { +	if (g) GDISP = g; +} + +void gdispGFlush(GDisplay *g) { +	#if GDISP_HARDWARE_FLUSH +		#if GDISP_HARDWARE_FLUSH == HARDWARE_AUTODETECT +			if (g->vmt->flush) +		#endif +		{ +			MUTEX_ENTER(g); +			gdisp_lld_flush(g); +			MUTEX_EXIT(g); +		} +	#else +		(void) g; +	#endif +} + +#if GDISP_NEED_STREAMING +	void gdispGStreamStart(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy) { +		MUTEX_ENTER(g); + +		#if NEED_CLIPPING +			#if GDISP_HARDWARE_CLIP == HARDWARE_AUTODETECT +				if (!g->vmt->setclip) +			#endif +			// Test if the area is valid - if not then exit +			if (x < g->clipx0 || x+cx > g->clipx1 || y < g->clipy0 || y+cy > g->clipy1) { +				MUTEX_EXIT(g); +				return; +			} +		#endif + +		g->flags |= GDISP_FLG_INSTREAM; + +		// Best is hardware streaming +		#if GDISP_HARDWARE_STREAM_WRITE +			#if GDISP_HARDWARE_STREAM_WRITE == HARDWARE_AUTODETECT +				if (g->vmt->writestart) +			#endif +			{ +				g->p.x = x; +				g->p.y = y; +				g->p.cx = cx; +				g->p.cy = cy; +				gdisp_lld_write_start(g); +				#if GDISP_HARDWARE_STREAM_POS +					#if GDISP_HARDWARE_STREAM_POS == HARDWARE_AUTODETECT +						if (g->vmt->writepos) +					#endif +					gdisp_lld_write_pos(g); +				#endif +				return; +			} +		#endif + +		// Worst - save the parameters and use pixel drawing and/or area fills +		#if GDISP_HARDWARE_STREAM_WRITE != TRUE && GDISP_HARDWARE_DRAWPIXEL +			// The following test is unneeded because we are guaranteed to have draw pixel if we don't have streaming +			//#if GDISP_HARDWARE_DRAWPIXEL == HARDWARE_AUTODETECT +			//	if (g->vmt->pixel) +			//#endif +			{ +				// Use x,y as the current position, x1,y1 as the save position and x2,y2 as the end position, cx = bufpos +				g->p.x1 = g->p.x = x; +				g->p.y1 = g->p.y = y; +				g->p.x2 = x + cx; +				g->p.y2 = y + cy; +				#if (GDISP_LINEBUF_SIZE != 0 && GDISP_HARDWARE_BITFILLS) || GDISP_HARDWARE_FILLS +					g->p.cx = 0; +					g->p.cy = 1; +				#endif +				return; +			} +		#endif + +		// Don't release the mutex as gdispStreamEnd() will do that. +	} + +	void gdispGStreamColor(GDisplay *g, color_t color) { +		#if !GDISP_HARDWARE_STREAM_WRITE && GDISP_LINEBUF_SIZE != 0 && GDISP_HARDWARE_BITFILLS +			coord_t	 sx1, sy1; +		#endif + +		// Don't touch the mutex as we should already own it + +		// Ignore this call if we are not streaming +		if (!(g->flags & GDISP_FLG_INSTREAM)) +			return; + +		// Best is hardware streaming +		#if GDISP_HARDWARE_STREAM_WRITE +			#if GDISP_HARDWARE_STREAM_WRITE == HARDWARE_AUTODETECT +				if (g->vmt->writestart) +			#endif +			{ +				g->p.color = color; +				gdisp_lld_write_color(g); +				return; +			} +		#endif + +		// Next best is to use bitfills with our line buffer +		#if GDISP_HARDWARE_STREAM_WRITE != TRUE && GDISP_LINEBUF_SIZE != 0 && GDISP_HARDWARE_BITFILLS +			#if GDISP_HARDWARE_BITFILLS == HARDWARE_AUTODETECT +				if (g->vmt->blit) +			#endif +			{ +				g->linebuf[g->p.cx++] = color; +				if (g->p.cx >= GDISP_LINEBUF_SIZE) { +					sx1 = g->p.x1; +					sy1 = g->p.y1; +					g->p.x1 = 0; +					g->p.y1 = 0; +					g->p.ptr = (void *)g->linebuf; +					gdisp_lld_blit_area(g); +					g->p.x1 = sx1; +					g->p.y1 = sy1; +					g->p.x += g->p.cx; +					g->p.cx = 0; +				} + +				// Just wrap at end-of-line and end-of-buffer +				if (g->p.x+g->p.cx >= g->p.x2) { +					if (g->p.cx) { +						sx1 = g->p.x1; +						sy1 = g->p.y1; +						g->p.x1 = 0; +						g->p.y1 = 0; +						g->p.ptr = (void *)g->linebuf; +						gdisp_lld_blit_area(g); +						g->p.x1 = sx1; +						g->p.y1 = sy1; +						g->p.cx = 0; +					} +					g->p.x = g->p.x1; +					if (++g->p.y >= g->p.y2) +						g->p.y = g->p.y1; +				} +			} +		#endif + +		// Only slightly better than drawing pixels is to look for runs and use fillarea +		#if GDISP_HARDWARE_STREAM_WRITE != TRUE && (GDISP_LINEBUF_SIZE == 0 || GDISP_HARDWARE_BITFILLS != TRUE) && GDISP_HARDWARE_FILLS +			// We don't need to test for auto-detect on drawpixel as we know we have it because we don't have streaming. +			#if GDISP_HARDWARE_FILLS == HARDWARE_AUTODETECT +				if (g->vmt->fill) +			#endif +			{ +				if (!g->p.cx || g->p.color == color) { +					g->p.cx++; +					g->p.color = color; +				} else { +					if (g->p.cx == 1) +						gdisp_lld_draw_pixel(g); +					else +						gdisp_lld_fill_area(g); +					g->p.x += g->p.cx; +					g->p.color = color; +					g->p.cx = 1; +				} +				// Just wrap at end-of-line and end-of-buffer +				if (g->p.x+g->p.cx >= g->p.x2) { +					if (g->p.cx) { +						if (g->p.cx == 1) +							gdisp_lld_draw_pixel(g); +						else +							gdisp_lld_fill_area(g); +						g->p.cx = 0; +					} +					g->p.x = g->p.x1; +					if (++g->p.y >= g->p.y2) +						g->p.y = g->p.y1; +				} +				return; +			} +		#endif + +		// Worst is using pixel drawing +		#if GDISP_HARDWARE_STREAM_WRITE != TRUE && (GDISP_LINEBUF_SIZE == 0 || GDISP_HARDWARE_BITFILLS != TRUE) && GDISP_HARDWARE_FILLS != TRUE && GDISP_HARDWARE_DRAWPIXEL +			// The following test is unneeded because we are guaranteed to have draw pixel if we don't have streaming +			//#if GDISP_HARDWARE_DRAWPIXEL == HARDWARE_AUTODETECT +			//	if (g->vmt->pixel) +			//#endif +			{ +				g->p.color = color; +				gdisp_lld_draw_pixel(g); + +				// Just wrap at end-of-line and end-of-buffer +				if (++g->p.x >= g->p.x2) { +					g->p.x = g->p.x1; +					if (++g->p.y >= g->p.y2) +						g->p.y = g->p.y1; +				} +				return; +			} +		#endif +	} + +	void gdispGStreamStop(GDisplay *g) { +		// Only release the mutex and end the stream if we are actually streaming. +		if (!(g->flags & GDISP_FLG_INSTREAM)) +			return; + +		// Clear the flag +		g->flags &= ~GDISP_FLG_INSTREAM; + +		// The cleanup below must match the streaming code above. + +		#if GDISP_HARDWARE_STREAM_WRITE +			#if GDISP_HARDWARE_STREAM_WRITE == HARDWARE_AUTODETECT +				if (g->vmt->writestart) +			#endif +			{ +					gdisp_lld_write_stop(g); +					autoflush_stopdone(g); +					MUTEX_EXIT(g); +					return; +			} +		#endif + +		#if GDISP_HARDWARE_STREAM_WRITE != TRUE && GDISP_LINEBUF_SIZE != 0 && GDISP_HARDWARE_BITFILLS +			#if GDISP_HARDWARE_BITFILLS == HARDWARE_AUTODETECT +				if (g->vmt->blit) +			#endif +			{ +				if (g->p.cx) { +					g->p.x1 = 0; +					g->p.y1 = 0; +					g->p.ptr = (void *)g->linebuf; +					gdisp_lld_blit_area(g); +				} +				autoflush_stopdone(g); +				MUTEX_EXIT(g); +				return; +			} +		#endif + +		#if GDISP_HARDWARE_STREAM_WRITE != TRUE && (GDISP_LINEBUF_SIZE == 0 || GDISP_HARDWARE_BITFILLS != TRUE) && GDISP_HARDWARE_FILLS +			// We don't need to test for auto-detect on drawpixel as we know we have it because we don't have streaming. +			#if GDISP_HARDWARE_FILLS == HARDWARE_AUTODETECT +				if (g->vmt->fill) +			#endif +			{ +				if (g->p.cx) { +					if (g->p.cx == 1) +						gdisp_lld_draw_pixel(g); +					else +						gdisp_lld_fill_area(g); +				} +				autoflush_stopdone(g); +				MUTEX_EXIT(g); +				return; +			} +		#endif + +		#if GDISP_HARDWARE_STREAM_WRITE != TRUE && (GDISP_LINEBUF_SIZE == 0 || GDISP_HARDWARE_BITFILLS != TRUE) && GDISP_HARDWARE_FILLS != TRUE +			{ +				autoflush_stopdone(g); +				MUTEX_EXIT(g); +			} +		#endif  	}  #endif + +void gdispGDrawPixel(GDisplay *g, coord_t x, coord_t y, color_t color) { +	MUTEX_ENTER(g); +	g->p.x		= x; +	g->p.y		= y; +	g->p.color	= color; +	drawpixel_clip(g); +	autoflush(g); +	MUTEX_EXIT(g); +} -#if GDISP_NEED_MULTITHREAD -	void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, coord_t srcy, coord_t srccx, const pixel_t *buffer) { -		gfxMutexEnter(&gdispMutex); -		gdisp_lld_blit_area_ex(x, y, cx, cy, srcx, srcy, srccx, buffer); -		gfxMutexExit(&gdispMutex); -	} -#elif GDISP_NEED_ASYNC -	void gdispBlitAreaEx(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, coord_t srcy, coord_t srccx, const pixel_t *buffer) { -		gdisp_lld_msg_t *p = gdispAllocMsg(GDISP_LLD_MSG_BLITAREA); -		p->blitarea.x = x; -		p->blitarea.y = y; -		p->blitarea.cx = cx; -		p->blitarea.cy = cy; -		p->blitarea.srcx = srcx; -		p->blitarea.srcy = srcy; -		p->blitarea.srccx = srccx; -		p->blitarea.buffer = buffer; -		gfxQueuePut(&gdispQueue, &p->qi, TIME_IMMEDIATE); +void gdispGDrawLine(GDisplay *g, coord_t x0, coord_t y0, coord_t x1, coord_t y1, color_t color) { +	MUTEX_ENTER(g); +	g->p.x = x0; +	g->p.y = y0; +	g->p.x1 = x1; +	g->p.y1 = y1; +	g->p.color = color; +	line_clip(g); +	autoflush(g); +	MUTEX_EXIT(g); +} + +void gdispGClear(GDisplay *g, color_t color) { +	// Note - clear() ignores the clipping area. It clears the screen. +	MUTEX_ENTER(g); + +	// Best is hardware accelerated clear +	#if GDISP_HARDWARE_CLEARS +		#if GDISP_HARDWARE_CLEARS == HARDWARE_AUTODETECT +			if (g->vmt->clear) +		#endif +		{ +			g->p.color = color; +			gdisp_lld_clear(g); +			autoflush_stopdone(g); +			MUTEX_EXIT(g); +			return; +		} +	#endif + +	// Next best is hardware accelerated area fill +	#if GDISP_HARDWARE_CLEARS != TRUE && GDISP_HARDWARE_FILLS +		#if GDISP_HARDWARE_FILLS == HARDWARE_AUTODETECT +			if (g->vmt->fill) +		#endif +		{ +			g->p.x = g->p.y = 0; +			g->p.cx = g->g.Width; +			g->p.cy = g->g.Height; +			g->p.color = color; +			gdisp_lld_fill_area(g); +			autoflush_stopdone(g); +			MUTEX_EXIT(g); +			return; +		} +	#endif + +	// Next best is streaming +	#if GDISP_HARDWARE_CLEARS != TRUE && GDISP_HARDWARE_FILLS != TRUE && GDISP_HARDWARE_STREAM_WRITE +		#if GDISP_HARDWARE_STREAM_WRITE == HARDWARE_AUTODETECT +			if (g->vmt->writestart) +		#endif +		{ +			uint32_t	area; + +			g->p.x = g->p.y = 0; +			g->p.cx = g->g.Width; +			g->p.cy = g->g.Height; +			g->p.color = color; +			area = (uint32_t)g->p.cx * g->p.cy; + +			gdisp_lld_write_start(g); +			#if GDISP_HARDWARE_STREAM_POS +				#if GDISP_HARDWARE_STREAM_POS == HARDWARE_AUTODETECT +					if (g->vmt->writepos) +				#endif +				gdisp_lld_write_pos(g); +			#endif +			for(; area; area--) +				gdisp_lld_write_color(g); +			gdisp_lld_write_stop(g); +			autoflush_stopdone(g); +			MUTEX_EXIT(g); +			return; +		} +	#endif + +	// Worst is drawing pixels +	#if GDISP_HARDWARE_CLEARS != TRUE && GDISP_HARDWARE_FILLS != TRUE && GDISP_HARDWARE_STREAM_WRITE != TRUE && GDISP_HARDWARE_DRAWPIXEL +		// The following test is unneeded because we are guaranteed to have draw pixel if we don't have streaming +		//#if GDISP_HARDWARE_DRAWPIXEL == HARDWARE_AUTODETECT +		//	if (g->vmt->pixel) +		//#endif +		{ +			g->p.color = color; +			for(g->p.y = 0; g->p.y < g->g.Height; g->p.y++) +				for(g->p.x = 0; g->p.x < g->g.Width; g->p.x++) +					gdisp_lld_draw_pixel(g); +			autoflush_stopdone(g); +			MUTEX_EXIT(g); +			return; +		} +	#endif +} + +void gdispGFillArea(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { +	MUTEX_ENTER(g); +	g->p.x = x; +	g->p.y = y; +	g->p.cx = cx; +	g->p.cy = cy; +	g->p.color = color; +	TEST_CLIP_AREA(g) { +		fillarea(g);  	} -#endif +	autoflush_stopdone(g); +	MUTEX_EXIT(g); +} +	 +void gdispGBlitArea(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, coord_t srcy, coord_t srccx, const pixel_t *buffer) { +	MUTEX_ENTER(g); + +	#if NEED_CLIPPING +		#if GDISP_HARDWARE_CLIP == HARDWARE_AUTODETECT +			if (!g->vmt->setclip) +		#endif +		{ +			// This is a different clipping to fillarea(g) as it needs to take into account srcx,srcy +			if (x < g->clipx0) { cx -= g->clipx0 - x; srcx += g->clipx0 - x; x = g->clipx0; } +			if (y < g->clipy0) { cy -= g->clipy0 - y; srcy += g->clipy0 - x; y = g->clipy0; } +			if (x+cx > g->clipx1)	cx = g->clipx1 - x; +			if (y+cy > g->clipy1)	cy = g->clipy1 - y; +			if (srcx+cx > srccx) cx = srccx - srcx; +			if (cx <= 0 || cy <= 0) { MUTEX_EXIT(g); return; } +		} +	#endif + +	// Best is hardware bitfills +	#if GDISP_HARDWARE_BITFILLS +		#if GDISP_HARDWARE_BITFILLS == HARDWARE_AUTODETECT +			if (g->vmt->blit) +		#endif +		{ +			g->p.x = x; +			g->p.y = y; +			g->p.cx = cx; +			g->p.cy = cy; +			g->p.x1 = srcx; +			g->p.y1 = srcy; +			g->p.x2 = srccx; +			g->p.ptr = (void *)buffer; +			gdisp_lld_blit_area(g); +			autoflush_stopdone(g); +			MUTEX_EXIT(g); +			return; +		} +	#endif + +	// Next best is hardware streaming +	#if GDISP_HARDWARE_BITFILLS != TRUE && GDISP_HARDWARE_STREAM_WRITE +		#if GDISP_HARDWARE_STREAM_WRITE == HARDWARE_AUTODETECT +			if (g->vmt->writestart) +		#endif +		{ +			// Translate buffer to the real image data, use srcx,srcy as the end point, srccx as the buffer line gap +			buffer += srcy*srccx+srcx; +			srcx = x + cx; +			srcy = y + cy; +			srccx -= cx; + +			g->p.x = x; +			g->p.y = y; +			g->p.cx = cx; +			g->p.cy = cy; +			gdisp_lld_write_start(g); +			#if GDISP_HARDWARE_STREAM_POS +				#if GDISP_HARDWARE_STREAM_POS == HARDWARE_AUTODETECT +					if (g->vmt->writepos) +				#endif +				gdisp_lld_write_pos(g); +			#endif +			for(g->p.y = y; g->p.y < srcy; g->p.y++, buffer += srccx) { +				for(g->p.x = x; g->p.x < srcx; g->p.x++) { +					g->p.color = *buffer++; +					gdisp_lld_write_color(g); +				} +			} +			gdisp_lld_write_stop(g); +			autoflush_stopdone(g); +			MUTEX_EXIT(g); +			return; +		} +	#endif + +	// Only slightly better than drawing pixels is to look for runs and use fill area +	#if GDISP_HARDWARE_BITFILLS != TRUE && GDISP_HARDWARE_STREAM_WRITE != TRUE && GDISP_HARDWARE_FILLS +		// We don't need to test for auto-detect on drawpixel as we know we have it because we don't have streaming. +		#if GDISP_HARDWARE_FILLS == HARDWARE_AUTODETECT +			if (g->vmt->fill) +		#endif +		{ +			// Translate buffer to the real image data, use srcx,srcy as the end point, srccx as the buffer line gap +			buffer += srcy*srccx+srcx; +			srcx = x + cx; +			srcy = y + cy; +			srccx -= cx; + +			g->p.cy = 1; +			for(g->p.y = y; g->p.y < srcy; g->p.y++, buffer += srccx) { +				for(g->p.x=x; g->p.x < srcx; g->p.x += g->p.cx) { +					g->p.cx=1; +					g->p.color = *buffer++; +					while(g->p.x+g->p.cx < srcx && *buffer == g->p.color) { +						g->p.cx++; +						buffer++; +					} +					if (g->p.cx == 1) { +						gdisp_lld_draw_pixel(g); +					} else { +						gdisp_lld_fill_area(g); +					} +				} +			} +			autoflush_stopdone(g); +			MUTEX_EXIT(g); +			return; +		} +	#endif + +	// Worst is drawing pixels +	#if GDISP_HARDWARE_BITFILLS != TRUE && GDISP_HARDWARE_STREAM_WRITE != TRUE && GDISP_HARDWARE_FILLS != TRUE && GDISP_HARDWARE_DRAWPIXEL +		// The following test is unneeded because we are guaranteed to have draw pixel if we don't have streaming +		//#if GDISP_HARDWARE_DRAWPIXEL == HARDWARE_AUTODETECT +		//	if (g->vmt->pixel) +		//#endif +		{ +			// Translate buffer to the real image data, use srcx,srcy as the end point, srccx as the buffer line gap +			buffer += srcy*srccx+srcx; +			srcx = x + cx; +			srcy = y + cy; +			srccx -= cx; + +			for(g->p.y = y; g->p.y < srcy; g->p.y++, buffer += srccx) { +				for(g->p.x=x; g->p.x < srcx; g->p.x++) { +					g->p.color = *buffer++; +					gdisp_lld_draw_pixel(g); +				} +			} +			autoflush_stopdone(g); +			MUTEX_EXIT(g); +			return; +		} +	#endif +} -#if (GDISP_NEED_CLIP && GDISP_NEED_MULTITHREAD) -	void gdispSetClip(coord_t x, coord_t y, coord_t cx, coord_t cy) { -		gfxMutexEnter(&gdispMutex); -		gdisp_lld_set_clip(x, y, cx, cy); -		gfxMutexExit(&gdispMutex); -	} -#elif GDISP_NEED_CLIP && GDISP_NEED_ASYNC -	void gdispSetClip(coord_t x, coord_t y, coord_t cx, coord_t cy) { -		gdisp_lld_msg_t *p = gdispAllocMsg(GDISP_LLD_MSG_SETCLIP); -		p->setclip.x = x; -		p->setclip.y = y; -		p->setclip.cx = cx; -		p->setclip.cy = cy; -		gfxQueuePut(&gdispQueue, &p->qi, TIME_IMMEDIATE); +#if GDISP_NEED_CLIP +	void gdispGSetClip(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy) { +		MUTEX_ENTER(g); + +		// Best is using hardware clipping +		#if GDISP_HARDWARE_CLIP +			#if GDISP_HARDWARE_CLIP == HARDWARE_AUTODETECT +				if (g->vmt->setclip) +			#endif +			{ +				g->p.x = x; +				g->p.y = y; +				g->p.cx = cx; +				g->p.cy = cy; +				gdisp_lld_set_clip(g); +			} +			#if GDISP_HARDWARE_CLIP == HARDWARE_AUTODETECT +				else +			#endif +		#endif + +		// Worst is using software clipping +		#if GDISP_HARDWARE_CLIP != TRUE +			{ +				if (x < 0) { cx += x; x = 0; } +				if (y < 0) { cy += y; y = 0; } +				if (cx <= 0 || cy <= 0 || x >= g->g.Width || y >= g->g.Height) { MUTEX_EXIT(g); return; } +				g->clipx0 = x; +				g->clipy0 = y; +				g->clipx1 = x+cx;	if (g->clipx1 > g->g.Width) g->clipx1 = g->g.Width; +				g->clipy1 = y+cy;	if (g->clipy1 > g->g.Height) g->clipy1 = g->g.Height; +			} +		#endif +		MUTEX_EXIT(g);  	}  #endif -#if (GDISP_NEED_CIRCLE && GDISP_NEED_MULTITHREAD) -	void gdispDrawCircle(coord_t x, coord_t y, coord_t radius, color_t color) { -		gfxMutexEnter(&gdispMutex); -		gdisp_lld_draw_circle(x, y, radius, color); -		gfxMutexExit(&gdispMutex); -	} -#elif GDISP_NEED_CIRCLE && GDISP_NEED_ASYNC -	void gdispDrawCircle(coord_t x, coord_t y, coord_t radius, color_t color) { -		gdisp_lld_msg_t *p = gdispAllocMsg(GDISP_LLD_MSG_DRAWCIRCLE); -		p->drawcircle.x = x; -		p->drawcircle.y = y; -		p->drawcircle.radius = radius; -		p->drawcircle.color = color; -		gfxQueuePut(&gdispQueue, &p->qi, TIME_IMMEDIATE); +#if GDISP_NEED_CIRCLE +	void gdispGDrawCircle(GDisplay *g, coord_t x, coord_t y, coord_t radius, color_t color) { +		coord_t a, b, P; + +		MUTEX_ENTER(g); + +		// Calculate intermediates +		a = 1; +		b = radius; +		P = 4 - radius; +		g->p.color = color; + +		// Away we go using Bresenham's circle algorithm +		// Optimized to prevent double drawing +		g->p.x = x; g->p.y = y + b; drawpixel_clip(g); +		g->p.x = x; g->p.y = y - b; drawpixel_clip(g); +		g->p.x = x + b; g->p.y = y; drawpixel_clip(g); +		g->p.x = x - b; g->p.y = y; drawpixel_clip(g); +		do { +			g->p.x = x + a; g->p.y = y + b; drawpixel_clip(g); +			g->p.x = x + a; g->p.y = y - b; drawpixel_clip(g); +			g->p.x = x + b; g->p.y = y + a; drawpixel_clip(g); +			g->p.x = x - b; g->p.y = y + a; drawpixel_clip(g); +			g->p.x = x - a; g->p.y = y + b; drawpixel_clip(g); +			g->p.x = x - a; g->p.y = y - b; drawpixel_clip(g); +			g->p.x = x + b; g->p.y = y - a; drawpixel_clip(g); +			g->p.x = x - b; g->p.y = y - a; drawpixel_clip(g); +			if (P < 0) +				P += 3 + 2*a++; +			else +				P += 5 + 2*(a++ - b--); +		} while(a < b); +		g->p.x = x + a; g->p.y = y + b; drawpixel_clip(g); +		g->p.x = x + a; g->p.y = y - b; drawpixel_clip(g); +		g->p.x = x - a; g->p.y = y + b; drawpixel_clip(g); +		g->p.x = x - a; g->p.y = y - b; drawpixel_clip(g); + +		autoflush(g); +		MUTEX_EXIT(g);  	}  #endif -	 -#if (GDISP_NEED_CIRCLE && GDISP_NEED_MULTITHREAD) -	void gdispFillCircle(coord_t x, coord_t y, coord_t radius, color_t color) { -		gfxMutexEnter(&gdispMutex); -		gdisp_lld_fill_circle(x, y, radius, color); -		gfxMutexExit(&gdispMutex); -	} -#elif GDISP_NEED_CIRCLE && GDISP_NEED_ASYNC -	void gdispFillCircle(coord_t x, coord_t y, coord_t radius, color_t color) { -		gdisp_lld_msg_t *p = gdispAllocMsg(GDISP_LLD_MSG_FILLCIRCLE); -		p->fillcircle.x = x; -		p->fillcircle.y = y; -		p->fillcircle.radius = radius; -		p->fillcircle.color = color; -		gfxQueuePut(&gdispQueue, &p->qi, TIME_IMMEDIATE); + +#if GDISP_NEED_CIRCLE +	void gdispGFillCircle(GDisplay *g, coord_t x, coord_t y, coord_t radius, color_t color) { +		coord_t a, b, P; + +		MUTEX_ENTER(g); + +		// Calculate intermediates +		a = 1; +		b = radius; +		P = 4 - radius; +		g->p.color = color; + +		// Away we go using Bresenham's circle algorithm +		// This is optimized to prevent overdrawing by drawing a line only when a variable is about to change value +		g->p.y = y; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); +		g->p.y = y+b; g->p.x = x; drawpixel_clip(g); +		g->p.y = y-b; g->p.x = x; drawpixel_clip(g); +		do { +			g->p.y = y+a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); +			g->p.y = y-a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); +			if (P < 0) { +				P += 3 + 2*a++; +			} else { +				g->p.y = y+b; g->p.x = x-a; g->p.x1 = x+a; hline_clip(g); +				g->p.y = y-b; g->p.x = x-a; g->p.x1 = x+a; hline_clip(g); +				P += 5 + 2*(a++ - b--); +			} +		} while(a < b); +		g->p.y = y+a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); +		g->p.y = y-a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); + +		autoflush(g); +		MUTEX_EXIT(g);  	}  #endif -#if (GDISP_NEED_ELLIPSE && GDISP_NEED_MULTITHREAD) -	void gdispDrawEllipse(coord_t x, coord_t y, coord_t a, coord_t b, color_t color) { -		gfxMutexEnter(&gdispMutex); -		gdisp_lld_draw_ellipse(x, y, a, b, color); -		gfxMutexExit(&gdispMutex); -	} -#elif GDISP_NEED_ELLIPSE && GDISP_NEED_ASYNC -	void gdispDrawEllipse(coord_t x, coord_t y, coord_t a, coord_t b, color_t color) { -		gdisp_lld_msg_t *p = gdispAllocMsg(GDISP_LLD_MSG_DRAWELLIPSE); -		p->drawellipse.x = x; -		p->drawellipse.y = y; -		p->drawellipse.a = a; -		p->drawellipse.b = b; -		p->drawellipse.color = color; -		gfxQueuePut(&gdispQueue, &p->qi, TIME_IMMEDIATE); +#if GDISP_NEED_ELLIPSE +	void gdispGDrawEllipse(GDisplay *g, coord_t x, coord_t y, coord_t a, coord_t b, color_t color) { +		coord_t	dx, dy; +		int32_t	a2, b2; +		int32_t	err, e2; + +		MUTEX_ENTER(g); + +		// Calculate intermediates +		dx = 0; +		dy = b; +		a2 = a*a; +		b2 = b*b; +		err = b2-(2*b-1)*a2; +		g->p.color = color; + +		// Away we go using Bresenham's ellipse algorithm +		do { +			g->p.x = x + dx; g->p.y = y + dy; drawpixel_clip(g); +			g->p.x = x - dx; g->p.y = y + dy; drawpixel_clip(g); +			g->p.x = x - dx; g->p.y = y - dy; drawpixel_clip(g); +			g->p.x = x + dx; g->p.y = y - dy; drawpixel_clip(g); + +			e2 = 2*err; +			if(e2 <  (2*dx+1)*b2) { +				dx++; +				err += (2*dx+1)*b2; +			} +			if(e2 > -(2*dy-1)*a2) { +				dy--; +				err -= (2*dy-1)*a2; +			} +		} while(dy >= 0); + +		autoflush(g); +		MUTEX_EXIT(g);  	}  #endif -#if (GDISP_NEED_ELLIPSE && GDISP_NEED_MULTITHREAD) -	void gdispFillEllipse(coord_t x, coord_t y, coord_t a, coord_t b, color_t color) { -		gfxMutexEnter(&gdispMutex); -		gdisp_lld_fill_ellipse(x, y, a, b, color); -		gfxMutexExit(&gdispMutex); -	} -#elif GDISP_NEED_ELLIPSE && GDISP_NEED_ASYNC -	void gdispFillEllipse(coord_t x, coord_t y, coord_t a, coord_t b, color_t color) { -		gdisp_lld_msg_t *p = gdispAllocMsg(GDISP_LLD_MSG_FILLELLIPSE); -		p->fillellipse.x = x; -		p->fillellipse.y = y; -		p->fillellipse.a = a; -		p->fillellipse.b = b; -		p->fillellipse.color = color; -		gfxQueuePut(&gdispQueue, &p->qi, TIME_IMMEDIATE); +#if GDISP_NEED_ELLIPSE +	void gdispGFillEllipse(GDisplay *g, coord_t x, coord_t y, coord_t a, coord_t b, color_t color) { +		coord_t	dx, dy; +		int32_t	a2, b2; +		int32_t	err, e2; + +		MUTEX_ENTER(g); + +		// Calculate intermediates +		dx = 0; +		dy = b; +		a2 = a*a; +		b2 = b*b; +		err = b2-(2*b-1)*a2; +		g->p.color = color; + +		// Away we go using Bresenham's ellipse algorithm +		// This is optimized to prevent overdrawing by drawing a line only when a y is about to change value +		do { +			e2 = 2*err; +			if(e2 <  (2*dx+1)*b2) { +				dx++; +				err += (2*dx+1)*b2; +			} +			if(e2 > -(2*dy-1)*a2) { +				g->p.y = y + dy; g->p.x = x - dx; g->p.x1 = x + dx; hline_clip(g); +				if (y) { g->p.y = y - dy; g->p.x = x - dx; g->p.x1 = x + dx; hline_clip(g); } +				dy--; +				err -= (2*dy-1)*a2; +			} +		} while(dy >= 0); + +		autoflush(g); +		MUTEX_EXIT(g);  	}  #endif -#if (GDISP_NEED_ARC && GDISP_NEED_MULTITHREAD) -	void gdispDrawArc(coord_t x, coord_t y, coord_t radius, coord_t start, coord_t end, color_t color) { -		gfxMutexEnter(&gdispMutex); -		gdisp_lld_draw_arc(x, y, radius, start, end, color); -		gfxMutexExit(&gdispMutex); -	} -#elif GDISP_NEED_ARC && GDISP_NEED_ASYNC -	void gdispDrawArc(coord_t x, coord_t y, coord_t radius, coord_t start, coord_t end, color_t color) { -		gdisp_lld_msg_t *p = gdispAllocMsg(GDISP_LLD_MSG_DRAWARC); -		p->drawarc.x = x; -		p->drawarc.y = y; -		p->drawarc.radius = radius; -		p->drawarc.start = start; -		p->drawarc.end = end; -		p->drawarc.color = color; -		gfxQueuePut(&gdispQueue, &p->qi, TIME_IMMEDIATE); +#if GDISP_NEED_ARC +	#if !GMISC_NEED_FIXEDTRIG && !GMISC_NEED_FASTTRIG +		#include <math.h> +	#endif + +	void gdispGDrawArc(GDisplay *g, coord_t x, coord_t y, coord_t radius, coord_t start, coord_t end, color_t color) { +		coord_t a, b, P, sedge, eedge; +		uint8_t	full, sbit, ebit, tbit; + +		// Normalize the angles +		if (start < 0) +			start -= (start/360-1)*360; +		else if (start >= 360) +			start %= 360; +		if (end < 0) +			end -= (end/360-1)*360; +		else if (end >= 360) +			end %= 360; + +		sbit = 1<<(start/45); +		ebit = 1<<(end/45); +		full = 0; +		if (start == end) { +			full = 0xFF; +		} else if (end < start) { +			for(tbit=sbit<<1; tbit; tbit<<=1) full |= tbit; +			for(tbit=ebit>>1; tbit; tbit>>=1) full |= tbit; +		} else if (sbit < 0x80) { +			for(tbit=sbit<<1; tbit < ebit; tbit<<=1) full |= tbit; +		} + +		MUTEX_ENTER(g); +		g->p.color = color; + +		if (full) { +			// Draw full sectors +			// Optimized to prevent double drawing +			a = 1; +			b = radius; +			P = 4 - radius; +			if (full & 0x60) { g->p.y = y+b; g->p.x = x; drawpixel_clip(g); } +			if (full & 0x06) { g->p.y = y-b; g->p.x = x; drawpixel_clip(g); } +			if (full & 0x81) { g->p.y = y; g->p.x = x+b; drawpixel_clip(g); } +			if (full & 0x18) { g->p.y = y; g->p.x = x-b; drawpixel_clip(g); } +			do { +				if (full & 0x01) { g->p.x = x+b; g->p.y = y-a; drawpixel_clip(g); } +				if (full & 0x02) { g->p.x = x+a; g->p.y = y-b; drawpixel_clip(g); } +				if (full & 0x04) { g->p.x = x-a; g->p.y = y-b; drawpixel_clip(g); } +				if (full & 0x08) { g->p.x = x-b; g->p.y = y-a; drawpixel_clip(g); } +				if (full & 0x10) { g->p.x = x-b; g->p.y = y+a; drawpixel_clip(g); } +				if (full & 0x20) { g->p.x = x-a; g->p.y = y+b; drawpixel_clip(g); } +				if (full & 0x40) { g->p.x = x+a; g->p.y = y+b; drawpixel_clip(g); } +				if (full & 0x80) { g->p.x = x+b; g->p.y = y+a; drawpixel_clip(g); } +				if (P < 0) +					P += 3 + 2*a++; +				else +					P += 5 + 2*(a++ - b--); +			} while(a < b); +			if (full & 0xC0) { g->p.x = x+a; g->p.y = y+b; drawpixel_clip(g); } +			if (full & 0x0C) { g->p.x = x-a; g->p.y = y-b; drawpixel_clip(g); } +			if (full & 0x03) { g->p.x = x+a; g->p.y = y-b; drawpixel_clip(g); } +			if (full & 0x30) { g->p.x = x-a; g->p.y = y+b; drawpixel_clip(g); } +			if (full == 0xFF) { +				autoflush(g); +				MUTEX_EXIT; +				return; +			} +		} + +		#if GFX_USE_GMISC && GMISC_NEED_FIXEDTRIG +			sedge = NONFIXED(radius * ((sbit & 0x99) ? ffsin(start) : ffcos(start)) + FIXED0_5); +			eedge = NONFIXED(radius * ((ebit & 0x99) ? ffsin(end) : ffcos(end)) + FIXED0_5); +		#elif GFX_USE_GMISC && GMISC_NEED_FASTTRIG +			sedge = round(radius * ((sbit & 0x99) ? fsin(start) : fcos(start))); +			eedge = round(radius * ((ebit & 0x99) ? fsin(end) : fcos(end))); +		#else +			sedge = round(radius * ((sbit & 0x99) ? sin(start*M_PI/180) : cos(start*M_PI/180))); +			eedge = round(radius * ((ebit & 0x99) ? sin(end*M_PI/180) : cos(end*M_PI/180))); +		#endif +		if (sbit & 0xB4) sedge = -sedge; +		if (ebit & 0xB4) eedge = -eedge; + +		if (sbit != ebit) { +			// Draw start and end sectors +			// Optimized to prevent double drawing +			a = 1; +			b = radius; +			P = 4 - radius; +			if ((sbit & 0x20) || (ebit & 0x40)) { g->p.x = x; g->p.y = y+b; drawpixel_clip(g); } +			if ((sbit & 0x02) || (ebit & 0x04)) { g->p.x = x; g->p.y = y-b; drawpixel_clip(g); } +			if ((sbit & 0x80) || (ebit & 0x01)) { g->p.x = x+b; g->p.y = y; drawpixel_clip(g); } +			if ((sbit & 0x08) || (ebit & 0x10)) { g->p.x = x-b; g->p.y = y; drawpixel_clip(g); } +			do { +				if (((sbit & 0x01) && a >= sedge) || ((ebit & 0x01) && a <= eedge)) { g->p.x = x+b; g->p.y = y-a; drawpixel_clip(g); } +				if (((sbit & 0x02) && a <= sedge) || ((ebit & 0x02) && a >= eedge)) { g->p.x = x+a; g->p.y = y-b; drawpixel_clip(g); } +				if (((sbit & 0x04) && a >= sedge) || ((ebit & 0x04) && a <= eedge)) { g->p.x = x-a; g->p.y = y-b; drawpixel_clip(g); } +				if (((sbit & 0x08) && a <= sedge) || ((ebit & 0x08) && a >= eedge)) { g->p.x = x-b; g->p.y = y-a; drawpixel_clip(g); } +				if (((sbit & 0x10) && a >= sedge) || ((ebit & 0x10) && a <= eedge)) { g->p.x = x-b; g->p.y = y+a; drawpixel_clip(g); } +				if (((sbit & 0x20) && a <= sedge) || ((ebit & 0x20) && a >= eedge)) { g->p.x = x-a; g->p.y = y+b; drawpixel_clip(g); } +				if (((sbit & 0x40) && a >= sedge) || ((ebit & 0x40) && a <= eedge)) { g->p.x = x+a; g->p.y = y+b; drawpixel_clip(g); } +				if (((sbit & 0x80) && a <= sedge) || ((ebit & 0x80) && a >= eedge)) { g->p.x = x+b; g->p.y = y+a; drawpixel_clip(g); } +				if (P < 0) +					P += 3 + 2*a++; +				else +					P += 5 + 2*(a++ - b--); +			} while(a < b); +			if (((sbit & 0x40) && a >= sedge) || ((ebit & 0x40) && a <= eedge) || ((sbit & 0x80) && a <= sedge) || ((ebit & 0x80) && a >= eedge)) +				{ g->p.x = x+a; g->p.y = y+b; drawpixel_clip(g); } +			if (((sbit & 0x04) && a >= sedge) || ((ebit & 0x04) && a <= eedge) || ((sbit & 0x08) && a <= sedge) || ((ebit & 0x08) && a >= eedge)) +				{ g->p.x = x-a; g->p.y = y-b; drawpixel_clip(g); } +			if (((sbit & 0x01) && a >= sedge) || ((ebit & 0x01) && a <= eedge) || ((sbit & 0x02) && a <= sedge) || ((ebit & 0x02) && a >= eedge)) +				{ g->p.x = x+a; g->p.y = y-b; drawpixel_clip(g); } +			if (((sbit & 0x10) && a >= sedge) || ((ebit & 0x10) && a <= eedge) || ((sbit & 0x20) && a <= sedge) || ((ebit & 0x20) && a >= eedge)) +				{ g->p.x = x-a; g->p.y = y+b; drawpixel_clip(g); } +		} else if (end < start) { +			// Draw start/end sector where it is a non-internal angle +			// Optimized to prevent double drawing +			a = 1; +			b = radius; +			P = 4 - radius; +			if (sbit & 0x60) { g->p.x = x; g->p.y = y+b; drawpixel_clip(g); } +			if (sbit & 0x06) { g->p.x = x; g->p.y = y-b; drawpixel_clip(g); } +			if (sbit & 0x81) { g->p.x = x+b; g->p.y = y; drawpixel_clip(g); } +			if (sbit & 0x18) { g->p.x = x-b; g->p.y = y; drawpixel_clip(g); } +			do { +				if ((sbit & 0x01) && (a >= sedge || a <= eedge)) { g->p.x = x+b; g->p.y = y-a; drawpixel_clip(g); } +				if ((sbit & 0x02) && (a <= sedge || a >= eedge)) { g->p.x = x+a; g->p.y = y-b; drawpixel_clip(g); } +				if ((sbit & 0x04) && (a >= sedge || a <= eedge)) { g->p.x = x-a; g->p.y = y-b; drawpixel_clip(g); } +				if ((sbit & 0x08) && (a <= sedge || a >= eedge)) { g->p.x = x-b; g->p.y = y-a; drawpixel_clip(g); } +				if ((sbit & 0x10) && (a >= sedge || a <= eedge)) { g->p.x = x-b; g->p.y = y+a; drawpixel_clip(g); } +				if ((sbit & 0x20) && (a <= sedge || a >= eedge)) { g->p.x = x-a; g->p.y = y+b; drawpixel_clip(g); } +				if ((sbit & 0x40) && (a >= sedge || a <= eedge)) { g->p.x = x+a; g->p.y = y+b; drawpixel_clip(g); } +				if ((sbit & 0x80) && (a <= sedge || a >= eedge)) { g->p.x = x+b; g->p.y = y+a; drawpixel_clip(g); } +				if (P < 0) +					P += 3 + 2*a++; +				else +					P += 5 + 2*(a++ - b--); +			} while(a < b); +			if (((sbit & 0x04) && (a >= sedge || a <= eedge)) || ((sbit & 0x08) && (a <= sedge || a >= eedge))) +				{ g->p.x = x-a; g->p.y = y-b; drawpixel_clip(g); } +			if (((sbit & 0x40) && (a >= sedge || a <= eedge)) || ((sbit & 0x80) && (a <= sedge || a >= eedge))) +				{ g->p.x = x+a; g->p.y = y+b; drawpixel_clip(g); } +			if (((sbit & 0x01) && (a >= sedge || a <= eedge)) || ((sbit & 0x02) && (a <= sedge || a >= eedge))) +				{ g->p.x = x+a; g->p.y = y-b; drawpixel_clip(g); } +			if (((sbit & 0x10) && (a >= sedge || a <= eedge)) || ((sbit & 0x20) && (a <= sedge || a >= eedge))) +				{ g->p.x = x-a; g->p.y = y+b; drawpixel_clip(g); } +		} else { +			// Draw start/end sector where it is a internal angle +			// Optimized to prevent double drawing +			a = 1; +			b = radius; +			P = 4 - radius; +			if (((sbit & 0x20) && !eedge) || ((sbit & 0x40) && !sedge)) { g->p.x = x; g->p.y = y+b; drawpixel_clip(g); } +			if (((sbit & 0x02) && !eedge) || ((sbit & 0x04) && !sedge)) { g->p.x = x; g->p.y = y-b; drawpixel_clip(g); } +			if (((sbit & 0x80) && !eedge) || ((sbit & 0x01) && !sedge)) { g->p.x = x+b; g->p.y = y; drawpixel_clip(g); } +			if (((sbit & 0x08) && !eedge) || ((sbit & 0x10) && !sedge)) { g->p.x = x-b; g->p.y = y; drawpixel_clip(g); } +			do { +				if (((sbit & 0x01) && a >= sedge && a <= eedge)) { g->p.x = x+b; g->p.y = y-a; drawpixel_clip(g); } +				if (((sbit & 0x02) && a <= sedge && a >= eedge)) { g->p.x = x+a; g->p.y = y-b; drawpixel_clip(g); } +				if (((sbit & 0x04) && a >= sedge && a <= eedge)) { g->p.x = x-a; g->p.y = y-b; drawpixel_clip(g); } +				if (((sbit & 0x08) && a <= sedge && a >= eedge)) { g->p.x = x-b; g->p.y = y-a; drawpixel_clip(g); } +				if (((sbit & 0x10) && a >= sedge && a <= eedge)) { g->p.x = x-b; g->p.y = y+a; drawpixel_clip(g); } +				if (((sbit & 0x20) && a <= sedge && a >= eedge)) { g->p.x = x-a; g->p.y = y+b; drawpixel_clip(g); } +				if (((sbit & 0x40) && a >= sedge && a <= eedge)) { g->p.x = x+a; g->p.y = y+b; drawpixel_clip(g); } +				if (((sbit & 0x80) && a <= sedge && a >= eedge)) { g->p.x = x+b; g->p.y = y+a; drawpixel_clip(g); } +				if (P < 0) +					P += 3 + 2*a++; +				else +					P += 5 + 2*(a++ - b--); +			} while(a < b); +			if (((sbit & 0x04) && a >= sedge && a <= eedge) || ((sbit & 0x08) && a <= sedge && a >= eedge)) +				{ g->p.x = x-a; g->p.y = y-b; drawpixel_clip(g); } +			if (((sbit & 0x40) && a >= sedge && a <= eedge) || ((sbit & 0x80) && a <= sedge && a >= eedge)) +				{ g->p.x = x+a; g->p.y = y+b; drawpixel_clip(g); } +			if (((sbit & 0x01) && a >= sedge && a <= eedge) || ((sbit & 0x02) && a <= sedge && a >= eedge)) +				{ g->p.x = x+a; g->p.y = y-b; drawpixel_clip(g); } +			if (((sbit & 0x10) && a >= sedge && a <= eedge) || ((sbit & 0x20) && a <= sedge && a >= eedge)) +				{ g->p.x = x-a; g->p.y = y+b; drawpixel_clip(g); } +		} + +		autoflush(g); +		MUTEX_EXIT(g);  	}  #endif -#if (GDISP_NEED_ARC && GDISP_NEED_MULTITHREAD) -	void gdispFillArc(coord_t x, coord_t y, coord_t radius, coord_t start, coord_t end, color_t color) { -		gfxMutexEnter(&gdispMutex); -		gdisp_lld_fill_arc(x, y, radius, start, end, color); -		gfxMutexExit(&gdispMutex); -	} -#elif GDISP_NEED_ARC && GDISP_NEED_ASYNC -	void gdispFillArc(coord_t x, coord_t y, coord_t radius, coord_t start, coord_t end, color_t color) { -		gdisp_lld_msg_t *p = gdispAllocMsg(GDISP_LLD_MSG_FILLARC); -		p->fillarc.x = x; -		p->fillarc.y = y; -		p->fillarc.radius = radius; -		p->fillarc.start = start; -		p->fillarc.end = end; -		p->fillarc.color = color; -		gfxQueuePut(&gdispQueue, &p->qi, TIME_IMMEDIATE); +#if GDISP_NEED_ARC +	void gdispGFillArc(GDisplay *g, coord_t x, coord_t y, coord_t radius, coord_t start, coord_t end, color_t color) { +		coord_t a, b, P; +		coord_t	sy, ey; +		fixed	sxa, sxb, sxd, exa, exb, exd; +		uint8_t	qtr; + +		MUTEX_ENTER(g); + +		// Do the trig to get the formulas for the start and end lines. +		sxa = exa = FIXED(x)+FIXED0_5; +		#if GFX_USE_GMISC && GMISC_NEED_FIXEDTRIG +			sxb = radius*ffcos(start);	sy = -NONFIXED(radius*ffsin(start) + FIXED0_5); +			exb = radius*ffcos(end);	ey = -NONFIXED(radius*ffsin(end) + FIXED0_5); +		#elif GFX_USE_GMISC && GMISC_NEED_FASTTRIG +			sxb = FP2FIXED(radius*fcos(start));	sy = -round(radius*fsin(start)); +			exb = FP2FIXED(radius*fcos(end));	ey = -round(radius*fsin(end)); +		#else +			sxb = FP2FIXED(radius*cos(start*M_PI/180));	sy = -round(radius*sin(start*M_PI/180)); +			exb = FP2FIXED(radius*cos(end*M_PI/180));	ey = -round(radius*sin(end*M_PI/180)); +		#endif +		sxd = sy ? sxb/sy : sxb; +		exd = ey ? exb/ey : exb; + +		// Calculate which quarters and which direction we are traveling +		qtr = 0; +		if (sxb > 0)	qtr |= 0x01;		// S1=0001(1), S2=0000(0), S3=0010(2), S4=0011(3) +		if (sy > 0) 	qtr |= 0x02; +		if (exb > 0)	qtr |= 0x04;		// E1=0100(4), E2=0000(0), E3=1000(8), E4=1100(12) +		if (ey > 0) 	qtr |= 0x08; +		if (sy > ey)	qtr |= 0x10;		// order of start and end lines + +		// Calculate intermediates +		a = 1; +		b = radius; +		P = 4 - radius; +		g->p.color = color; +		sxb += sxa; +		exb += exa; + +		// Away we go using Bresenham's circle algorithm +		// This is optimized to prevent overdrawing by drawing a line only when a variable is about to change value + +		switch(qtr) { +		case 0:		// S2E2 sy <= ey +		case 1:		// S1E2 sy <= ey +			if (ey && sy) { +				g->p.x = x; g->p.x1 = x;									// E2S +				sxa -= sxd; exa -= exd; +			} else if (sy) { +				g->p.x = x-b; g->p.x1 = x;								// C2S +				sxa -= sxd; +			} else if (ey) { +				g->p.x = x; g->p.x1 = x+b;								// E2C +				exa -= exd; +			} else { +				g->p.x = x-b; g->p.x1 = x+b;								// C2C +			} +			g->p.y = y; +			hline_clip(g); +			do { +				if (-a >= ey) { +					g->p.y = y-a; g->p.x = NONFIXED(exa); g->p.x1 = NONFIXED(sxa); hline_clip(g);		// E2S +					sxa -= sxd; exa -= exd; +				} else if (-a >= sy) { +					g->p.y = y-a; g->p.x = x-b; g->p.x1 = NONFIXED(sxa); hline_clip(g);				// C2S +					sxa -= sxd; +				} else if (qtr & 1) { +					g->p.y = y-a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g);							// C2C +				} +				if (P < 0) { +					P += 3 + 2*a++; +				} else { +					if (-b >= ey) { +						g->p.y = y-b; g->p.x = NONFIXED(exb); g->p.x1 = NONFIXED(sxb); hline_clip(g);	// E2S +						sxb += sxd; exb += exd; +					} else if (-b >= sy) { +						g->p.y = y-b; g->p.x = x-a; g->p.x1 = NONFIXED(sxb); hline_clip(g);			// C2S +						sxb += sxd; +					} else if (qtr & 1) { +						g->p.y = y-b; g->p.x = x-a; g->p.x1 = x+a; hline_clip(g);						// C2C +					} +					P += 5 + 2*(a++ - b--); +				} +			} while(a < b); +			if (-a >= ey) { +				g->p.y = y-a; g->p.x = NONFIXED(exa); g->p.x1 = NONFIXED(sxa); hline_clip(g);			// E2S +			} else if (-a >= sy) { +				g->p.y = y-a; g->p.x = x-b; g->p.x1 = NONFIXED(sxa); hline_clip(g);					// C2S +			} else if (qtr & 1) { +				g->p.y = y-a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g);								// C2C +			} +			break; + +		case 2:		// S3E2 sy <= ey +		case 3:		// S4E2 sy <= ey +		case 6:		// S3E1 sy <= ey +		case 7:		// S4E1 sy <= ey +		case 18:	// S3E2 sy > ey +		case 19:	// S4E2 sy > ey +		case 22:	// S3E1 sy > ey +		case 23:	// S4E1 sy > ey +			g->p.y = y; g->p.x = x; g->p.x1 = x+b; hline_clip(g);								// SE2C +			sxa += sxd; exa -= exd; +			do { +				if (-a >= ey) { +					g->p.y = y-a; g->p.x = NONFIXED(exa); g->p.x1 = x+b; hline_clip(g);		// E2C +					exa -= exd; +				} else if (!(qtr & 4)) { +					g->p.y = y-a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g);					// C2C +				} +				if (a <= sy) { +					g->p.y = y+a; g->p.x = NONFIXED(sxa); g->p.x1 = x+b; hline_clip(g);		// S2C +					sxa += sxd; +				} else if (!(qtr & 1)) { +					g->p.y = y+a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g);					// C2C +				} +				if (P < 0) { +					P += 3 + 2*a++; +				} else { +					if (-b >= ey) { +						g->p.y = y-b; g->p.x = NONFIXED(exb); g->p.x1 = x+a; hline_clip(g);		// E2C +						exb += exd; +					} else if (!(qtr & 4)) { +						g->p.y = y-b; g->p.x = x-a; g->p.x1 = x+a; hline_clip(g);					// C2C +					} +					if (b <= sy) { +						g->p.y = y+b; g->p.x = NONFIXED(sxb); g->p.x1 = x+a; hline_clip(g);		// S2C +						sxb -= sxd; +					} else if (!(qtr & 1)) { +						g->p.y = y+b; g->p.x = x-a; g->p.x1 = x+a; hline_clip(g); 				// C2C +					} +					P += 5 + 2*(a++ - b--); +				} +			} while(a < b); +			if (-a >= ey) { +				g->p.y = y-a; g->p.x = NONFIXED(exa); g->p.x1 = x+b; hline_clip(g);				// E2C +			} else if (!(qtr & 4)) { +				g->p.y = y-a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g);							// C2C +			} +			if (a <= sy) { +				g->p.y = y+a; g->p.x = NONFIXED(sxa); g->p.x1 = x+a; hline_clip(g);				// S2C +			} else if (!(qtr & 1)) { +				g->p.y = y+a; g->p.x = x-b; g->p.x1 = x+a; hline_clip(g);							// C2C +			} +			break; + +		case 4:		// S2E1 sy <= ey +		case 5:		// S1E1 sy <= ey +			g->p.y = y; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g);									// C2C +			do { +				if (-a >= ey) { +					g->p.y = y-a; g->p.x = x-b; g->p.x1 = NONFIXED(sxa); hline_clip(g);				// C2S +					g->p.y = y-a; g->p.x = NONFIXED(exa); g->p.x1 = x+b; hline_clip(g);				// E2C +					sxa -= sxd; exa -= exd; +				} else if (-a >= sy) { +					g->p.y = y-a; g->p.x = x-b; g->p.x1 = NONFIXED(sxa); hline_clip(g);				// C2S +					sxa -= sxd; +				} else if (qtr & 1) { +					g->p.y = y-a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g);							// C2C +				} +				g->p.y = y+a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g);								// C2C +				if (P < 0) { +					P += 3 + 2*a++; +				} else { +					if (-b >= ey) { +						g->p.y = y-b; g->p.x = x-a; g->p.x1 = NONFIXED(sxb); hline_clip(g);			// C2S +						g->p.y = y-b; g->p.x = NONFIXED(exb); g->p.x1 = x+a; hline_clip(g);			// E2C +						sxb += sxd; exb += exd; +					} else if (-b >= sy) { +						g->p.y = y-b; g->p.x = x-a; g->p.x1 = NONFIXED(sxb); hline_clip(g);			// C2S +						sxb += sxd; +					} else if (qtr & 1) { +						g->p.y = y-b; g->p.x = x-a; g->p.x1 = x+a; hline_clip(g);						// C2C +					} +					g->p.y = y+b; g->p.x = x-a; g->p.x1 = x+a; hline_clip(g);							// C2C +					P += 5 + 2*(a++ - b--); +				} +			} while(a < b); +			if (-a >= ey) { +				g->p.y = y-a; g->p.x = x-b; g->p.x1 = NONFIXED(sxa); hline_clip(g);					// C2S +				g->p.y = y-a; g->p.x = NONFIXED(exa); g->p.x1 = x+b; hline_clip(g);					// E2C +			} else if (-a >= sy) { +				g->p.y = y-a; g->p.x = x-b; g->p.x1 = NONFIXED(sxa); hline_clip(g);					// C2S +			} else if (qtr & 1) { +				g->p.y = y-a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g);								// C2C +			} +			g->p.y = y+b; g->p.x = x-a; g->p.x1 = x+a; hline_clip(g);									// C2C +			break; + +		case 8:		// S2E3 sy <= ey +		case 9:		// S1E3 sy <= ey +		case 12:	// S2E4 sy <= ey +		case 13:	// S1E4 sy <= ey +		case 24:	// S2E3 sy > ey +		case 25:	// S1E3 sy > ey +		case 28:	// S2E3 sy > ey +		case 29:	// S1E3 sy > ey +			g->p.y = y; g->p.x = x-b; g->p.x1 = x; hline_clip(g);								// C2SE +			sxa -= sxd; exa += exd; +			do { +				if (-a >= sy) { +					g->p.y = y-a; g->p.x = x-b; g->p.x1 = NONFIXED(sxa); hline_clip(g);		// C2S +					sxa -= sxd; +				} else if (qtr & 1) { +					g->p.y = y-a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g);					// C2C +				} +				if (a <= ey) { +					g->p.y = y+a; g->p.x = x-b; g->p.x1 = NONFIXED(exa); hline_clip(g);		// C2E +					exa += exd; +				} else if (qtr & 4) { +					g->p.y = y+a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g);					// C2C +				} +				if (P < 0) { +					P += 3 + 2*a++; +				} else { +					if (-b >= sy) { +						g->p.y = y-b; g->p.x = x-a; g->p.x1 = NONFIXED(sxb); hline_clip(g);		// C2S +						sxb += sxd; +					} else if (qtr & 1) { +						g->p.y = y-b; g->p.x = x-a; g->p.x1 = x+a; hline_clip(g);					// C2C +					} +					if (b <= ey) { +						g->p.y = y+b; g->p.x = x-a; g->p.x1 = NONFIXED(exb); hline_clip(g);		// C2E +						exb -= exd; +					} else if (qtr & 4) { +						g->p.y = y+b; g->p.x = x-a; g->p.x1 = x+a; hline_clip(g); 				// C2C +					} +					P += 5 + 2*(a++ - b--); +				} +			} while(a < b); +			if (-a >= sy) { +				g->p.y = y-a; g->p.x = x-b; g->p.x1 = NONFIXED(sxa); hline_clip(g);				// C2S +			} else if (qtr & 1) { +				g->p.y = y-a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g);							// C2C +			} +			if (a <= ey) { +				g->p.y = y+a; g->p.x = x-b; g->p.x1 = NONFIXED(exa); hline_clip(g);				// C2E +			} else if (qtr & 4) { +				g->p.y = y+a; g->p.x = x-b; g->p.x1 = x+a; hline_clip(g);							// C2C +			} +			break; + +		case 10:	// S3E3 sy <= ey +		case 14:	// S3E4 sy <= ey +			g->p.y = y; g->p.x = x; drawpixel_clip(g);													// S2E +			sxa += sxd; exa += exd; +			do { +				if (a <= sy) { +					g->p.y = y+a; g->p.x = NONFIXED(sxa); g->p.x1 = NONFIXED(exa); hline_clip(g);		// S2E +					sxa += sxd; exa += exd; +				} else if (a <= ey) { +					g->p.y = y+a; g->p.x = x-b; g->p.x1 = NONFIXED(exa); hline_clip(g);				// C2E +					exa += exd; +				} else if (qtr & 4) { +					g->p.y = y+a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g);							// C2C +				} +				if (P < 0) { +					P += 3 + 2*a++; +				} else { +					if (b <= sy) { +						g->p.y = y+b; g->p.x = NONFIXED(sxb); g->p.x1 = NONFIXED(exb); hline_clip(g);		// S2E +						sxb -= sxd; exb -= exd; +					} else if (b <= ey) { +						g->p.y = y+b; g->p.x = x-a; g->p.x1 = NONFIXED(exb); hline_clip(g);				// C2E +						exb -= exd; +					} else if (qtr & 4) { +						g->p.y = y+b; g->p.x = x-a; g->p.x1 = x+a; hline_clip(g);							// C2C +					} +					P += 5 + 2*(a++ - b--); +				} +			} while(a < b); +			if (a <= sy) { +				g->p.y = y+a; g->p.x = NONFIXED(sxa); g->p.x1 = NONFIXED(exa); hline_clip(g);		// S2E +			} else if (a <= ey) { +				g->p.y = y+a; g->p.x = x-b; g->p.x1 = NONFIXED(exa); hline_clip(g);				// C2E +			} else if (qtr & 4) { +				g->p.y = y+a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g);							// C2C +			} +			break; + +		case 11:	// S4E3 sy <= ey +		case 15:	// S4E4 sy <= ey +			g->p.y = y; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g);									// C2C +			do { +				g->p.y = y-a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g);								// C2C +				if (a <= sy) { +					g->p.y = y+a; g->p.x = x-b; g->p.x1 = NONFIXED(exa); hline_clip(g);				// C2E +					g->p.y = y+a; g->p.x = NONFIXED(sxa); g->p.x1 = x+b; hline_clip(g);				// S2C +					sxa += sxd; exa += exd; +				} else if (a <= ey) { +					g->p.y = y+a; g->p.x = x-b; g->p.x1 = NONFIXED(exa); hline_clip(g);				// C2E +					exa += exd; +				} else if (qtr & 4) { +					g->p.y = y+a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g);							// C2C +				} +				if (P < 0) { +					P += 3 + 2*a++; +				} else { +					g->p.y = y-b; g->p.x = x-a; g->p.x1 = x+a; hline_clip(g);							// C2C +					if (b <= sy) { +						g->p.y = y+b; g->p.x = x-a; g->p.x1 = NONFIXED(exb); hline_clip(g);			// C2E +						g->p.y = y+b; g->p.x = NONFIXED(sxb); g->p.x1 = x+a; hline_clip(g);			// S2C +						sxb -= sxd; exb -= exd; +					} else if (b <= ey) { +						g->p.y = y+b; g->p.x = x-a; g->p.x1 = NONFIXED(exb); hline_clip(g);			// C2E +						exb -= exd; +					} else if (qtr & 4) { +						g->p.y = y+b; g->p.x = x-a; g->p.x1 = x+a; hline_clip(g);						// C2C +					} +					P += 5 + 2*(a++ - b--); +				} +			} while(a < b); +			g->p.y = y-a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g);									// C2C +			if (a <= sy) { +				g->p.y = y+a; g->p.x = x-b; g->p.x1 = NONFIXED(exa); hline_clip(g);					// C2E +				g->p.y = y+a; g->p.x = NONFIXED(sxa); g->p.x1 = x+b; hline_clip(g);					// S2C +			} else if (a <= ey) { +				g->p.y = y+a; g->p.x = x-b; g->p.x1 = NONFIXED(exa); hline_clip(g);					// C2E +			} else if (qtr & 4) { +				g->p.y = y+a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g);								// C2C +			} +			break; + +		case 16:	// S2E2	sy > ey +		case 20:	// S2E1 sy > ey +			g->p.y = y; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g);									// C2C +			sxa -= sxd; exa -= exd; +			do { +				if (-a >= sy) { +					g->p.y = y-a; g->p.x = x-b; g->p.x1 = NONFIXED(sxa); hline_clip(g);				// C2S +					g->p.y = y-a; g->p.x = NONFIXED(exa); g->p.x1 = x+b; hline_clip(g);				// E2C +					sxa -= sxd; exa -= exd; +				} else if (-a >= ey) { +					g->p.y = y-a; g->p.x = NONFIXED(exa); g->p.x1 = x+b; hline_clip(g);				// E2C +					exa -= exd; +				} else if (!(qtr & 4)){ +					g->p.y = y-a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); 						// C2C +				} +				g->p.y = y+a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); 							// C2C +				if (P < 0) { +					P += 3 + 2*a++; +				} else { +					if (-b >= sy) { +						g->p.y = y-b; g->p.x = x-a; g->p.x1 = NONFIXED(sxb); hline_clip(g);			// C2S +						g->p.y = y-b; g->p.x = NONFIXED(exb); g->p.x1 = x+a; hline_clip(g);			// E2C +						sxb += sxd; exb += exd; +					} else if (-b >= ey) { +						g->p.y = y-b; g->p.x = NONFIXED(exb); g->p.x1 = x+a; hline_clip(g);			// E2C +						exb += exd; +					} else if (!(qtr & 4)){ +						g->p.y = y-b; g->p.x = x-a; g->p.x1 = x+a; hline_clip(g); 					// C2C +					} +					g->p.y = y+b; g->p.x = x-a; g->p.x1 = x+a; hline_clip(g); 						// C2C +					P += 5 + 2*(a++ - b--); +				} +			} while(a < b); +			if (-a >= sy) { +				g->p.y = y-a; g->p.x = x-b; g->p.x1 = NONFIXED(sxa); hline_clip(g);					// C2S +				g->p.y = y-a; g->p.x = NONFIXED(exa); g->p.x1 = x+b; hline_clip(g);					// E2C +			} else if (-a >= ey) { +				g->p.y = y-a; g->p.x = NONFIXED(exa); g->p.x1 = x+b; hline_clip(g);					// E2C +			} else if (!(qtr & 4)){ +				g->p.y = y-a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); 							// C2C +			} +			g->p.y = y+a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g); 								// C2C +			break; + +		case 17:	// S1E2 sy > ey +		case 21:	// S1E1 sy > ey +			if (sy) { +				g->p.x = x; g->p.x1 = x;																// E2S +				sxa -= sxd; exa -= exd; +			} else { +				g->p.x = x; g->p.x1 = x+b;															// E2C +				exa -= exd; +			} +			g->p.y = y; +			hline_clip(g); +			do { +				if (-a >= sy) { +					g->p.y = y-a; g->p.x = NONFIXED(exa); g->p.x1 = NONFIXED(sxa); hline_clip(g);		// E2S +					sxa -= sxd; exa -= exd; +				} else if (-a >= ey) { +					g->p.y = y-a; g->p.x = NONFIXED(exa); g->p.x1 = x+b; hline_clip(g);				// E2C +					exa -= exd; +				} else if (!(qtr & 4)) { +					g->p.y = y-a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g);							// C2C +				} +				if (P < 0) { +					P += 3 + 2*a++; +				} else { +					if (-b >= sy) { +						g->p.y = y-b; g->p.x = NONFIXED(exb); g->p.x1 = NONFIXED(sxb); hline_clip(g);	// E2S +						sxb += sxd; exb += exd; +					} else if (-b >= ey) { +						g->p.y = y-b; g->p.x = NONFIXED(exb); g->p.x1 = x+a; hline_clip(g);			// E2C +						exb += exd; +					} else if (!(qtr & 4)) { +						g->p.y = y-b; g->p.x = x-a; g->p.x1 = x+a; hline_clip(g);						// C2C +					} +					P += 5 + 2*(a++ - b--); +				} +			} while(a < b); +			if (-a >= sy) { +				g->p.y = y-a; g->p.x = NONFIXED(exa); g->p.x1 = NONFIXED(sxa); hline_clip(g);			// E2S +			} else if (-a >= ey) { +				g->p.y = y-a; g->p.x = NONFIXED(exa); g->p.x1 = x+b; hline_clip(g);					// E2C +			} else if (!(qtr & 4)) { +				g->p.y = y-a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g);								// C2C +			} +			break; + +		case 26:	// S3E3 sy > ey +		case 27:	// S4E3 sy > ey +			g->p.y = y; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g);									// C2C +			do { +				g->p.y = y-a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g);								// C2C +				if (a <= ey) { +					g->p.y = y+a; g->p.x = x-b; g->p.x1 = NONFIXED(exa); hline_clip(g);				// C2E +					g->p.y = y+a; g->p.x = NONFIXED(sxa); g->p.x1 = x+b; hline_clip(g);				// S2C +					sxa += sxd; exa += exd; +				} else if (a <= sy) { +					g->p.y = y+a; g->p.x = NONFIXED(sxa); g->p.x1 = x+b; hline_clip(g);				// S2C +					sxa += sxd; +				} else if (!(qtr & 1)) { +					g->p.y = y+a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g);							// C2C +				} +				if (P < 0) { +					P += 3 + 2*a++; +				} else { +					g->p.y = y-b; g->p.x = x-a; g->p.x1 = x+a; hline_clip(g);							// C2C +					if (b <= ey) { +						g->p.y = y+b; g->p.x = x-a; g->p.x1 = NONFIXED(exb); hline_clip(g);			// C2E +						g->p.y = y+b; g->p.x = NONFIXED(sxb); g->p.x1 = x+a; hline_clip(g);			// S2C +						sxb -= sxd; exb -= exd; +					} else if (b <= sy) { +						g->p.y = y+b; g->p.x = NONFIXED(sxb); g->p.x1 = x+a; hline_clip(g);			// S2C +						sxb -= sxd; +					} else if (!(qtr & 1)) { +						g->p.y = y+b; g->p.x = x-a; g->p.x1 = x+a; hline_clip(g);						// C2C +					} +					P += 5 + 2*(a++ - b--); +				} +			} while(a < b); +			g->p.y = y-a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g);									// C2C +			if (a <= ey) { +				g->p.y = y+a; g->p.x = x-b; g->p.x1 = NONFIXED(exa); hline_clip(g);					// C2E +				g->p.y = y+a; g->p.x = NONFIXED(sxa); g->p.x1 = x+b; hline_clip(g);					// S2C +			} else if (a <= sy) { +				g->p.y = y+a; g->p.x = NONFIXED(sxa); g->p.x1 = x+b; hline_clip(g);					// S2C +			} else if (!(qtr & 4)) { +				g->p.y = y+a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g);								// C2C +			} +			break; + +		case 30:	// S3E4 sy > ey +		case 31:	// S4E4 sy > ey +			do { +				if (a <= ey) { +					g->p.y = y+a; g->p.x = NONFIXED(sxa); g->p.x1 = NONFIXED(exa); hline_clip(g);		// S2E +					sxa += sxd; exa += exd; +				} else if (a <= sy) { +					g->p.y = y+a; g->p.x = NONFIXED(sxa); g->p.x1 = x+b; hline_clip(g);				// S2C +					sxa += sxd; +				} else if (!(qtr & 1)) { +					g->p.y = y+a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g);							// C2C +				} +				if (P < 0) { +					P += 3 + 2*a++; +				} else { +					if (b <= ey) { +						g->p.y = y+b; g->p.x = NONFIXED(sxb); g->p.x1 = NONFIXED(exb); hline_clip(g);	// S2E +						sxb -= sxd; exb -= exd; +					} else if (b <= sy) { +						g->p.y = y+b; g->p.x = NONFIXED(sxb); g->p.x1 = x+a; hline_clip(g);			// S2C +						sxb -= sxd; +					} else if (!(qtr & 1)) { +						g->p.y = y+b; g->p.x = x-a; g->p.x1 = x+a; hline_clip(g);						// C2C +					} +					P += 5 + 2*(a++ - b--); +				} +			} while(a < b); +			if (a <= ey) { +				g->p.y = y+a; g->p.x = NONFIXED(sxa); g->p.x1 = x+b; hline_clip(g);				// S2C +			} else if (a <= sy) { +				g->p.y = y+a; g->p.x = NONFIXED(sxa); g->p.x1 = x+b; hline_clip(g);					// S2C +			} else if (!(qtr & 4)) { +				g->p.y = y+a; g->p.x = x-b; g->p.x1 = x+b; hline_clip(g);								// C2C +			} +			break; +		} + +		autoflush(g); +		MUTEX_EXIT(g);  	} +  #endif  #if GDISP_NEED_ARC -void gdispDrawRoundedBox(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t radius, color_t color) { -	if (2*radius > cx || 2*radius > cy) { -		gdispDrawBox(x, y, cx, cy, color); -		return; +	void gdispGDrawRoundedBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t radius, color_t color) { +		if (2*radius > cx || 2*radius > cy) { +			gdispDrawBox(x, y, cx, cy, color); +			return; +		} +		gdispDrawArc(x+radius, y+radius, radius, 90, 180, color); +		gdispDrawLine(x+radius+1, y, x+cx-2-radius, y, color); +		gdispDrawArc(x+cx-1-radius, y+radius, radius, 0, 90, color); +		gdispDrawLine(x+cx-1, y+radius+1, x+cx-1, y+cy-2-radius, color); +		gdispDrawArc(x+cx-1-radius, y+cy-1-radius, radius, 270, 360, color); +		gdispDrawLine(x+radius+1, y+cy-1, x+cx-2-radius, y+cy-1, color); +		gdispDrawArc(x+radius, y+cy-1-radius, radius, 180, 270, color); +		gdispDrawLine(x, y+radius+1, x, y+cy-2-radius, color);  	} -	gdispDrawArc(x+radius, y+radius, radius, 90, 180, color); -	gdispDrawLine(x+radius+1, y, x+cx-2-radius, y, color); -	gdispDrawArc(x+cx-1-radius, y+radius, radius, 0, 90, color); -	gdispDrawLine(x+cx-1, y+radius+1, x+cx-1, y+cy-2-radius, color); -	gdispDrawArc(x+cx-1-radius, y+cy-1-radius, radius, 270, 360, color); -	gdispDrawLine(x+radius+1, y+cy-1, x+cx-2-radius, y+cy-1, color); -	gdispDrawArc(x+radius, y+cy-1-radius, radius, 180, 270, color); -	gdispDrawLine(x, y+radius+1, x, y+cy-2-radius, color); -}  #endif  #if GDISP_NEED_ARC -void gdispFillRoundedBox(coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t radius, color_t color) { -	coord_t radius2; +	void gdispGFillRoundedBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t radius, color_t color) { +		coord_t radius2; -	radius2 = radius*2; -	if (radius2 > cx || radius2 > cy) { -		gdispFillArea(x, y, cx, cy, color); -		return; +		radius2 = radius*2; +		if (radius2 > cx || radius2 > cy) { +			gdispFillArea(x, y, cx, cy, color); +			return; +		} +		gdispFillArc(x+radius, y+radius, radius, 90, 180, color); +		gdispFillArea(x+radius+1, y, cx-radius2, radius, color); +		gdispFillArc(x+cx-1-radius, y+radius, radius, 0, 90, color); +		gdispFillArc(x+cx-1-radius, y+cy-1-radius, radius, 270, 360, color); +		gdispFillArea(x+radius+1, y+cy-radius, cx-radius2, radius, color); +		gdispFillArc(x+radius, y+cy-1-radius, radius, 180, 270, color); +		gdispFillArea(x, y+radius, cx, cy-radius2, color);  	} -	gdispFillArc(x+radius, y+radius, radius, 90, 180, color); -	gdispFillArea(x+radius+1, y, cx-radius2, radius, color); -	gdispFillArc(x+cx-1-radius, y+radius, radius, 0, 90, color); -	gdispFillArc(x+cx-1-radius, y+cy-1-radius, radius, 270, 360, color); -	gdispFillArea(x+radius+1, y+cy-radius, cx-radius2, radius, color); -	gdispFillArc(x+radius, y+cy-1-radius, radius, 180, 270, color); -	gdispFillArea(x, y+radius, cx, cy-radius2, color); -}  #endif -#if (GDISP_NEED_PIXELREAD && (GDISP_NEED_MULTITHREAD || GDISP_NEED_ASYNC)) -	color_t gdispGetPixelColor(coord_t x, coord_t y) { +#if GDISP_NEED_PIXELREAD +	color_t gdispGGetPixelColor(GDisplay *g, coord_t x, coord_t y) {  		color_t		c;  		/* Always synchronous as it must return a value */ -		gfxMutexEnter(&gdispMutex); -		c = gdisp_lld_get_pixel_color(x, y); -		gfxMutexExit(&gdispMutex); - -		return c; +		MUTEX_ENTER(g); +		#if GDISP_HARDWARE_PIXELREAD +			#if GDISP_HARDWARE_PIXELREAD == HARDWARE_AUTODETECT +				if (g->vmt->get) +			#endif +			{ +				// Best is direct pixel read +				g->p.x = x; +				g->p.y = y; +				c = gdisp_lld_get_pixel_color(g); +				MUTEX_EXIT(g); +				return c; +			} +		#endif +		#if GDISP_HARDWARE_PIXELREAD != TRUE && GDISP_HARDWARE_STREAM_READ +			#if GDISP_HARDWARE_STREAM_READ == HARDWARE_AUTODETECT +				if (g->vmt->readcolor) +			#endif +			{ +				// Next best is hardware streaming +				g->p.x = x; +				g->p.y = y; +				g->p.cx = 1; +				g->p.cy = 1; +				gdisp_lld_read_start(g); +				c = gdisp_lld_read_color(g); +				gdisp_lld_read_stop(g); +				MUTEX_EXIT(g); +				return c; +			} +		#endif +		#if GDISP_HARDWARE_PIXELREAD != TRUE && GDISP_HARDWARE_STREAM_READ != TRUE +			#if !GDISP_HARDWARE_PIXELREAD && !GDISP_HARDWARE_STREAM_READ +				// Worst is "not possible" +				#error "GDISP: GDISP_NEED_PIXELREAD has been set but there is no hardware support for reading the display" +			#endif +			MUTEX_EXIT(g); +			return 0; +		#endif  	}  #endif -#if (GDISP_NEED_SCROLL && GDISP_NEED_MULTITHREAD) -	void gdispVerticalScroll(coord_t x, coord_t y, coord_t cx, coord_t cy, int lines, color_t bgcolor) { -		gfxMutexEnter(&gdispMutex); -		gdisp_lld_vertical_scroll(x, y, cx, cy, lines, bgcolor); -		gfxMutexExit(&gdispMutex); -	} -#elif GDISP_NEED_SCROLL && GDISP_NEED_ASYNC -	void gdispVerticalScroll(coord_t x, coord_t y, coord_t cx, coord_t cy, int lines, color_t bgcolor) { -		gdisp_lld_msg_t *p = gdispAllocMsg(GDISP_LLD_MSG_VERTICALSCROLL); -		p->verticalscroll.x = x; -		p->verticalscroll.y = y; -		p->verticalscroll.cx = cx; -		p->verticalscroll.cy = cy; -		p->verticalscroll.lines = lines; -		p->verticalscroll.bgcolor = bgcolor; -		gfxQueuePut(&gdispQueue, &p->qi, TIME_IMMEDIATE); -	} -#endif +#if GDISP_NEED_SCROLL +	void gdispGVerticalScroll(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, int lines, color_t bgcolor) { +		coord_t		abslines; +		#if GDISP_HARDWARE_SCROLL != TRUE +			coord_t 	fy, dy, ix, fx, i, j; +		#endif -#if (GDISP_NEED_CONTROL && GDISP_NEED_MULTITHREAD) -	void gdispControl(unsigned what, void *value) { -		gfxMutexEnter(&gdispMutex); -		gdisp_lld_control(what, value); -		gfxMutexExit(&gdispMutex); -	} -#elif GDISP_NEED_CONTROL && GDISP_NEED_ASYNC -	void gdispControl(unsigned what, void *value) { -		gdisp_lld_msg_t *p = gdispAllocMsg(GDISP_LLD_MSG_CONTROL); -		p->control.what = what; -		p->control.value = value; -		gfxQueuePut(&gdispQueue, &p->qi, TIME_IMMEDIATE); +		MUTEX_ENTER(g); +		#if NEED_CLIPPING +			#if GDISP_HARDWARE_CLIP == HARDWARE_AUTODETECT +				if (!g->vmt->setclip) +			#endif +			{ +				if (x < g->clipx0) { cx -= g->clipx0 - x; x = g->clipx0; } +				if (y < g->clipy0) { cy -= g->clipy0 - y; y = g->clipy0; } +				if (!lines || cx <= 0 || cy <= 0 || x >= g->clipx1 || y >= g->clipy1) { MUTEX_EXIT(g); return; } +				if (x+cx > g->clipx1)	cx = g->clipx1 - x; +				if (y+cy > g->clipy1)	cy = g->clipy1 - y; +			} +		#endif + +		abslines = lines < 0 ? -lines : lines; +		if (abslines >= cy) { +			abslines = cy; +			cy = 0; +		} else { +			// Best is hardware scroll +			#if GDISP_HARDWARE_SCROLL +				#if GDISP_HARDWARE_SCROLL == HARDWARE_AUTODETECT +					if (g->vmt->vscroll) +				#endif +				{ +					g->p.x = x; +					g->p.y = y; +					g->p.cx = cx; +					g->p.cy = cy; +					g->p.y1 = lines; +					g->p.color = bgcolor; +					gdisp_lld_vertical_scroll(g); +					cy -= abslines; +				} +				#if GDISP_HARDWARE_SCROLL == HARDWARE_AUTODETECT +					else +				#endif +			#elif GDISP_LINEBUF_SIZE == 0 +				#error "GDISP: GDISP_NEED_SCROLL is set but there is no hardware support and GDISP_LINEBUF_SIZE is zero." +			#endif + +			// Scroll Emulation +			#if GDISP_HARDWARE_SCROLL != TRUE +				{ +					cy -= abslines; +					if (lines < 0) { +						fy = y+cy-1; +						dy = -1; +					} else { +						fy = y; +						dy = 1; +					} +					// Move the screen - one line at a time +					for(i = 0; i < cy; i++, fy += dy) { + +						// Handle where the buffer is smaller than a line +						for(ix=0; ix < cx; ix += GDISP_LINEBUF_SIZE) { + +							// Calculate the data we can move in one operation +							fx = cx - ix; +							if (fx > GDISP_LINEBUF_SIZE) +								fx = GDISP_LINEBUF_SIZE; + +							// Read one line of data from the screen + +							// Best line read is hardware streaming +							#if GDISP_HARDWARE_STREAM_READ +								#if GDISP_HARDWARE_STREAM_READ == HARDWARE_AUTODETECT +									if (g->vmt->readstart) +								#endif +								{ +									g->p.x = x+ix; +									g->p.y = fy+lines; +									g->p.cx = fx; +									g->p.cy = 1; +									gdisp_lld_read_start(g); +									for(j=0; j < fx; j++) +										g->linebuf[j] = gdisp_lld_read_color(g); +									gdisp_lld_read_stop(g); +								} +								#if GDISP_HARDWARE_STREAM_READ == HARDWARE_AUTODETECT +									else +								#endif +							#endif + +							// Next best line read is single pixel reads +							#if GDISP_HARDWARE_STREAM_READ != TRUE && GDISP_HARDWARE_PIXELREAD +								#if GDISP_HARDWARE_PIXELREAD == HARDWARE_AUTODETECT +									if (g->vmt->get) +								#endif +								{ +									for(j=0; j < fx; j++) { +										g->p.x = x+ix+j; +										g->p.y = fy+lines; +										g->linebuf[j] = gdisp_lld_get_pixel_color(g); +									} +								} +								#if GDISP_HARDWARE_PIXELREAD == HARDWARE_AUTODETECT +									else { +										// Worst is "not possible" +										MUTEX_EXIT(g); +										return; +									} +								#endif +							#endif + +							// Worst is "not possible" +							#if !GDISP_HARDWARE_STREAM_READ && !GDISP_HARDWARE_PIXELREAD +								#error "GDISP: GDISP_NEED_SCROLL is set but there is no hardware support for scrolling or reading pixels." +							#endif + +							// Write that line to the new location + +							// Best line write is hardware bitfills +							#if GDISP_HARDWARE_BITFILLS +								#if GDISP_HARDWARE_BITFILLS == HARDWARE_AUTODETECT +									if (g->vmt->blit) +								#endif +								{ +									g->p.x = x+ix; +									g->p.y = fy; +									g->p.cx = fx; +									g->p.cy = 1; +									g->p.x1 = 0; +									g->p.y1 = 0; +									g->p.x2 = fx; +									g->p.ptr = (void *)g->linebuf; +									gdisp_lld_blit_area(g); +								} +								#if GDISP_HARDWARE_BITFILLS == HARDWARE_AUTODETECT +									else +								#endif +							#endif + +							// Next best line write is hardware streaming +							#if GDISP_HARDWARE_BITFILLS != TRUE && GDISP_HARDWARE_STREAM_WRITE +								#if GDISP_HARDWARE_STREAM_WRITE == HARDWARE_AUTODETECT +									if (g->vmt->writestart) +								#endif +								{ +									g->p.x = x+ix; +									g->p.y = fy; +									g->p.cx = fx; +									g->p.cy = 1; +									gdisp_lld_write_start(g); +									#if GDISP_HARDWARE_STREAM_POS +										gdisp_lld_write_pos(g); +									#endif +									for(j = 0; j < fx; j++) { +										g->p.color = g->linebuf[j]; +										gdisp_lld_write_color(g); +									} +									gdisp_lld_write_stop(g); +								} +								#if GDISP_HARDWARE_STREAM_WRITE == HARDWARE_AUTODETECT +									else +								#endif +							#endif + +							// Next best line write is drawing pixels in combination with filling +							#if GDISP_HARDWARE_BITFILLS != TRUE && GDISP_HARDWARE_STREAM_WRITE != TRUE && GDISP_HARDWARE_FILLS && GDISP_HARDWARE_DRAWPIXEL +								// We don't need to test for auto-detect on drawpixel as we know we have it because we don't have streaming. +								#if GDISP_HARDWARE_FILLS == HARDWARE_AUTODETECT +									if (g->vmt->fill) +								#endif +								{ +									g->p.y = fy; +									g->p.cy = 1; +									g->p.x = x+ix; +									g->p.cx = 1; +									for(j = 0; j < fx; ) { +										g->p.color = g->linebuf[j]; +										if (j + g->p.cx < fx && g->linebuf[j] == g->linebuf[j + g->p.cx]) +											g->p.cx++; +										else if (g->p.cx == 1) { +											gdisp_lld_draw_pixel(g); +											j++; +											g->p.x++; +										} else { +											gdisp_lld_fill_area(g); +											j += g->p.cx; +											g->p.x += g->p.cx; +											g->p.cx = 1; +										} +									} +								} +								#if GDISP_HARDWARE_FILLS == HARDWARE_AUTODETECT +									else +								#endif +							#endif + +							// Worst line write is drawing pixels +							#if GDISP_HARDWARE_BITFILLS != TRUE && GDISP_HARDWARE_STREAM_WRITE != TRUE && GDISP_HARDWARE_FILLS != TRUE && GDISP_HARDWARE_DRAWPIXEL +								// The following test is unneeded because we are guaranteed to have draw pixel if we don't have streaming +								//#if GDISP_HARDWARE_DRAWPIXEL == HARDWARE_AUTODETECT +								//	if (g->vmt->pixel) +								//#endif +								{ +									g->p.y = fy; +									for(g->p.x = x+ix, j = 0; j < fx; g->p.x++, j++) { +										g->p.color = g->linebuf[j]; +										gdisp_lld_draw_pixel(g); +									} +								} +							#endif +						} +					} +				} +			#endif +		} + +		/* fill the remaining gap */ +		g->p.x = x; +		g->p.y = lines > 0 ? (y+cy) : y; +		g->p.cx = cx; +		g->p.cy = abslines; +		g->p.color = bgcolor; +		fillarea(g); +		autoflush_stopdone(g); +		MUTEX_EXIT(g);  	}  #endif -#if (GDISP_NEED_MULTITHREAD || GDISP_NEED_ASYNC) && GDISP_NEED_QUERY -	void *gdispQuery(unsigned what) { -		void *res; +#if GDISP_NEED_CONTROL +	#if GDISP_HARDWARE_CONTROL +		void gdispGControl(GDisplay *g, unsigned what, void *value) { +			#if GDISP_HARDWARE_CONTROL == HARDWARE_AUTODETECT +				if (!g->vmt->control) +					return; +			#endif +			MUTEX_ENTER(g); +			g->p.x = what; +			g->p.ptr = value; +			if (what == GDISP_CONTROL_ORIENTATION) { +				switch ((orientation_t) value) { +				case GDISP_ROTATE_LANDSCAPE: +					g->p.ptr = g->g.Width >= g->g.Height ? (void *)GDISP_ROTATE_0 : (void *)GDISP_ROTATE_90; +					break; +				case GDISP_ROTATE_PORTRAIT: +					g->p.ptr = g->g.Width >= g->g.Height ? (void *)GDISP_ROTATE_90 : (void *)GDISP_ROTATE_0; +					break; +				default: +					break; +				} +			} +			gdisp_lld_control(g); +			#if GDISP_NEED_CLIP || GDISP_NEED_VALIDATION +				if (what == GDISP_CONTROL_ORIENTATION) { +					// Best is hardware clipping +					#if GDISP_HARDWARE_CLIP +						#if GDISP_HARDWARE_CLIP == HARDWARE_AUTODETECT +							if (g->vmt->setclip) +						#endif +						{ +							g->p.x = 0; +							g->p.y = 0; +							g->p.cx = g->g.Width; +							g->p.cy = g->g.Height; +							gdisp_lld_set_clip(g); +						} +						#if GDISP_HARDWARE_CLIP == HARDWARE_AUTODETECT +							else +						#endif +					#endif + +					// Worst is software clipping +					#if GDISP_HARDWARE_CLIP != TRUE +						{ +							g->clipx0 = 0; +							g->clipy0 = 0; +							g->clipx1 = g->g.Width; +							g->clipy1 = g->g.Height; +						} +					#endif +				} +			#endif +			MUTEX_EXIT(g); +		} +	#else +		void gdispGControl(GDisplay *g, unsigned what, void *value) { +			(void)g; +			(void)what; +			(void)value; +			/* Ignore everything */ +		} +	#endif +#endif -		gfxMutexEnter(&gdispMutex); -		res = gdisp_lld_query(what); -		gfxMutexExit(&gdispMutex); -		return res; -	} +#if GDISP_NEED_QUERY +	#if GDISP_HARDWARE_QUERY +		void *gdispGQuery(GDisplay *g, unsigned what) { +			void *res; + +			#if GDISP_HARDWARE_QUERY == HARDWARE_AUTODETECT +				if (!g->vmt->query) +					return -1; +			#endif +			MUTEX_ENTER(g); +			g->p.x = (coord_t)what; +			res = gdisp_lld_query(g); +			MUTEX_EXIT(g); +			return res; +		} +	#else +		void *gdispGQuery(GDisplay *g, unsigned what) { +			(void) what; +			return (void *)-1; +		} +	#endif  #endif  /*===========================================================================*/  /* High Level Driver Routines.                                               */  /*===========================================================================*/ -void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { -	/* No mutex required as we only call high level functions which have their own mutex */ -	coord_t	x1, y1; +void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) { +	if (cx <= 0 || cy <= 0) return; +	cx = x+cx-1; cy = y+cy-1;			// cx, cy are now the end point. -	x1 = x+cx-1; -	y1 = y+cy-1; +	MUTEX_ENTER(g); -	if (cx > 2) { -		if (cy >= 1) { -			gdispDrawLine(x, y, x1, y, color); -			if (cy >= 2) { -				gdispDrawLine(x, y1, x1, y1, color); -				if (cy > 2) { -					gdispDrawLine(x, y+1, x, y1-1, color); -					gdispDrawLine(x1, y+1, x1, y1-1, color); -				} +	g->p.color = color; + +	if (cx - x > 2) { +		g->p.x = x; g->p.y = y; g->p.x1 = cx; hline_clip(g); +		if (y != cy) { +			g->p.x = x; g->p.y = cy; g->p.x1 = cx; hline_clip(g); +			if (cy - y > 2) { +				y++; cy--; +				g->p.x = x; g->p.y = y; g->p.y1 = cy; vline_clip(g); +				g->p.x = cx; g->p.y = y; g->p.y1 = cy; vline_clip(g);  			}  		} -	} else if (cx == 2) { -		gdispDrawLine(x, y, x, y1, color); -		gdispDrawLine(x1, y, x1, y1, color); -	} else if (cx == 1) { -		gdispDrawLine(x, y, x, y1, color); +	} else { +		g->p.x = x; g->p.y = y; g->p.y1 = cy; vline_clip(g); +		if (x != cx) { +			g->p.x = cx; g->p.y = y; g->p.y1 = cy; vline_clip(g); +		}  	} + +	autoflush(g); +	MUTEX_EXIT(g);  }  #if GDISP_NEED_CONVEX_POLYGON -	void gdispDrawPoly(coord_t tx, coord_t ty, const point *pntarray, unsigned cnt, color_t color) { +	void gdispGDrawPoly(GDisplay *g, coord_t tx, coord_t ty, const point *pntarray, unsigned cnt, color_t color) {  		const point	*epnt, *p;  		epnt = &pntarray[cnt-1]; -		for(p = pntarray; p < epnt; p++) -			gdispDrawLine(tx+p->x, ty+p->y, tx+p[1].x, ty+p[1].y, color); -		gdispDrawLine(tx+p->x, ty+p->y, tx+pntarray->x, ty+pntarray->y, color); + +		MUTEX_ENTER(g); +		g->p.color = color; +		for(p = pntarray; p < epnt; p++) { +			g->p.x=tx+p->x; g->p.y=ty+p->y; g->p.x1=tx+p[1].x; g->p.y1=ty+p[1].y; line_clip(g); +		} +		g->p.x=tx+p->x; g->p.y=ty+p->y; g->p.x1=tx+pntarray->x; g->p.y1=ty+pntarray->y; line_clip(g); + +		autoflush(g); +		MUTEX_EXIT(g);  	} -	void gdispFillConvexPoly(coord_t tx, coord_t ty, const point *pntarray, unsigned cnt, color_t color) { +	void gdispGFillConvexPoly(GDisplay *g, coord_t tx, coord_t ty, const point *pntarray, unsigned cnt, color_t color) {  		const point	*lpnt, *rpnt, *epnts;  		fixed		lx, rx, lk, rk;  		coord_t		y, ymax, lxc, rxc; @@ -510,21 +2521,21 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) {  		y = rpnt->y;  		/* Work out the slopes of the two attached line segs */ -		lpnt = rpnt <= pntarray ? epnts : rpnt-1; -		while (lpnt->y == y) { +		for (lpnt = rpnt <= pntarray ? epnts : rpnt-1; lpnt->y == y; cnt--) { +			if (!cnt) return;  			lx = FIXED(lpnt->x);  			lpnt = lpnt <= pntarray ? epnts : lpnt-1; -			if (!cnt--) return;  		} -		rpnt = rpnt >= epnts ? pntarray : rpnt+1; -		while (rpnt->y == y) { -			rx = rpnt->x<<16; +		for (rpnt = rpnt >= epnts ? pntarray : rpnt+1; rpnt->y == y; cnt--) { +			if (!cnt) return; +			rx = FIXED(rpnt->x);  			rpnt = rpnt >= epnts ? pntarray : rpnt+1; -			if (!cnt--) return;  		}  		lk = (FIXED(lpnt->x) - lx) / (lpnt->y - y);  		rk = (FIXED(rpnt->x) - rx) / (rpnt->y - y); +		MUTEX_ENTER(g); +		g->p.color = color;  		while(1) {  			/* Determine our boundary */  			ymax = rpnt->y < lpnt->y ? rpnt->y : lpnt->y; @@ -539,38 +2550,43 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) {  				 * of pixels.  				 */  				if (lxc < rxc) { -					if (rxc - lxc == 1) -						gdispDrawPixel(tx+lxc, ty+y, color); -					else -						gdispDrawLine(tx+lxc, ty+y, tx+rxc-1, ty+y, color); +					g->p.x=tx+lxc; g->p.y=ty+y; g->p.x1=tx+rxc-1; hline_clip(g);  				} else if (lxc > rxc) { -					if (lxc - rxc == 1) -						gdispDrawPixel(tx+rxc, ty+y, color); -					else -						gdispDrawLine(tx+rxc, ty+y, tx+lxc-1, ty+y, color); +					g->p.x=tx+rxc; g->p.y=ty+y; g->p.x1=tx+lxc-1; hline_clip(g);  				}  				lx += lk;  				rx += rk;  			} -			if (!cnt--) return; +			if (!cnt) { +				autoflush(g); +				MUTEX_EXIT(g); +				return; +			} +			cnt--;  			/* Replace the appropriate point */  			if (ymax == lpnt->y) { -				lpnt = lpnt <= pntarray ? epnts : lpnt-1; -				while (lpnt->y == y) { +				for (lpnt = lpnt <= pntarray ? epnts : lpnt-1; lpnt->y == y; cnt--) { +					if (!cnt) { +						autoflush(g); +						MUTEX_EXIT(g); +						return; +					}  					lx = FIXED(lpnt->x);  					lpnt = lpnt <= pntarray ? epnts : lpnt-1; -					if (!cnt--) return;  				}  				lk = (FIXED(lpnt->x) - lx) / (lpnt->y - y);  			} else { -				rpnt = rpnt >= epnts ? pntarray : rpnt+1; -				while (rpnt->y == y) { +				for (rpnt = rpnt >= epnts ? pntarray : rpnt+1; rpnt->y == y; cnt--) { +					if (!cnt) { +						autoflush(g); +						MUTEX_EXIT(g); +						return; +					}  					rx = FIXED(rpnt->x);  					rpnt = rpnt >= epnts ? pntarray : rpnt+1; -					if (!cnt--) return;  				}  				rk = (FIXED(rpnt->x) - rx) / (rpnt->y - y);  			} @@ -581,178 +2597,142 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) {  #if GDISP_NEED_TEXT  	#include "mcufont.h" -	#if GDISP_NEED_ANTIALIAS && GDISP_NEED_PIXELREAD -		static void text_draw_char_callback(int16_t x, int16_t y, uint8_t count, uint8_t alpha, void *state) { +	#if GDISP_NEED_ANTIALIAS && GDISP_HARDWARE_PIXELREAD +		static void drawcharline(int16_t x, int16_t y, uint8_t count, uint8_t alpha, void *state) { +			#define GD	((GDisplay *)state) +			if (y < GD->t.clipy0 || y >= GD->t.clipy1 || x < GD->t.clipx0 || x+count > GD->t.clipx1) return;  			if (alpha == 255) { -				if (count == 1) -					gdispDrawPixel(x, y, ((color_t *)state)[0]); -				else -					gdispFillArea(x, y, count, 1, ((color_t *)state)[0]); +				GD->p.x = x; GD->p.y = y; GD->p.x1 = x+count-1; GD->p.color = GD->t.color; +				hline_clip(GD);  			} else { -				while (count--) { -					gdispDrawPixel(x, y, gdispBlendColor(((color_t *)state)[0], gdispGetPixelColor(x, y), alpha)); -					x++; +				for (; count; count--, x++) { +					GD->p.x = x; GD->p.y = y; +					GD->p.color = gdispBlendColor(GD->t.color, gdisp_lld_get_pixel_color(GD), alpha); +					drawpixel_clip(GD);  				}  			} +			#undef GD  		}  	#else -		static void text_draw_char_callback(int16_t x, int16_t y, uint8_t count, uint8_t alpha, void *state) { +		static void drawcharline(int16_t x, int16_t y, uint8_t count, uint8_t alpha, void *state) { +			#define GD	((GDisplay *)state) +			if (y < GD->t.clipy0 || y >= GD->t.clipy1 || x < GD->t.clipx0 || x+count > GD->t.clipx1) return;  			if (alpha > 0x80) {			// A best approximation when using anti-aliased fonts but we can't actually draw them anti-aliased -				if (count == 1) -					gdispDrawPixel(x, y, ((color_t *)state)[0]); -				else -					gdispFillArea(x, y, count, 1, ((color_t *)state)[0]); +				GD->p.x = x; GD->p.y = y; GD->p.x1 = x+count-1; GD->p.color = GD->t.color; +				hline_clip(GD);  			} +			#undef GD  		}  	#endif -	void gdispDrawChar(coord_t x, coord_t y, uint16_t c, font_t font, color_t color) { -		/* No mutex required as we only call high level functions which have their own mutex */ -		mf_render_character(font, x, y, c, text_draw_char_callback, &color); -	} -  	#if GDISP_NEED_ANTIALIAS -		static void text_fill_char_callback(int16_t x, int16_t y, uint8_t count, uint8_t alpha, void *state) { +		static void fillcharline(int16_t x, int16_t y, uint8_t count, uint8_t alpha, void *state) { +			#define GD	((GDisplay *)state) +			if (y < GD->t.clipy0 || y >= GD->t.clipy1 || x < GD->t.clipx0 || x+count > GD->t.clipx1) return;  			if (alpha == 255) { -				if (count == 1) -					gdispDrawPixel(x, y, ((color_t *)state)[0]); -				else -					gdispFillArea(x, y, count, 1, ((color_t *)state)[0]); +				GD->p.color = GD->t.color;  			} else { -				while (count--) { -					gdispDrawPixel(x, y, gdispBlendColor(((color_t *)state)[0], ((color_t *)state)[1], alpha)); -					x++; -				} +				GD->p.color = gdispBlendColor(GD->t.color, GD->t.bgcolor, alpha);  			} +			GD->p.x = x; GD->p.y = y; GD->p.x1 = x+count-1; +			hline_clip(GD); +			#undef GD  		}  	#else -		#define text_fill_char_callback	text_draw_char_callback +		#define fillcharline	drawcharline  	#endif -	void gdispFillChar(coord_t x, coord_t y, uint16_t c, font_t font, color_t color, color_t bgcolor) { -		/* No mutex required as we only call high level functions which have their own mutex */ -		color_t		state[2]; +	/* Callback to render characters. */ +	static uint8_t drawcharglyph(int16_t x, int16_t y, mf_char ch, void *state) { +		#define GD	((GDisplay *)state) +			return mf_render_character(GD->t.font, x, y, ch, drawcharline, state); +		#undef GD +	} -		state[0] = color; -		state[1] = bgcolor; +	/* Callback to render characters. */ +	static uint8_t fillcharglyph(int16_t x, int16_t y, mf_char ch, void *state) { +		#define GD	((GDisplay *)state) +			return mf_render_character(GD->t.font, x, y, ch, fillcharline, state); +		#undef GD +	} -		gdispFillArea(x, y, mf_character_width(font, c) + font->baseline_x, font->height, bgcolor); -		mf_render_character(font, x, y, c, text_fill_char_callback, state); +	void gdispGDrawChar(GDisplay *g, coord_t x, coord_t y, uint16_t c, font_t font, color_t color) { +		MUTEX_ENTER(g); +		g->t.font = font; +		g->t.clipx0 = x; +		g->t.clipy0 = y; +		g->t.clipx1 = x + mf_character_width(font, c) + font->baseline_x; +		g->t.clipy1 = y + font->height; +		g->t.color = color; +		mf_render_character(font, x, y, c, drawcharline, g); +		autoflush(g); +		MUTEX_EXIT(g);  	} -	typedef struct -	{ -		font_t font; -		color_t color; -		coord_t	x, y; -		coord_t	cx, cy; -	} gdispDrawString_state_t; +	void gdispGFillChar(GDisplay *g, coord_t x, coord_t y, uint16_t c, font_t font, color_t color, color_t bgcolor) { +		MUTEX_ENTER(g); +		g->p.cx = mf_character_width(font, c) + font->baseline_x; +		g->p.cy = font->height; +		g->t.font = font; +		g->t.clipx0 = g->p.x = x; +		g->t.clipy0 = g->p.y = y; +		g->t.clipx1 = g->p.x+g->p.cx; +		g->t.clipy1 = g->p.y+g->p.cy; +		g->t.color = color; +		g->t.bgcolor = g->p.color = bgcolor; + +		TEST_CLIP_AREA(g) { +			fillarea(g); +			mf_render_character(font, x, y, c, fillcharline, g); +		} +		autoflush(g); +		MUTEX_EXIT(g); +	} -	/* Callback to render characters. */ -	static uint8_t gdispDrawString_callback(int16_t x, int16_t y, mf_char character, void *state) -	{ -		gdispDrawString_state_t *s = state; -		uint8_t w; -		 -		w = mf_character_width(s->font, character); -		if (x >= s->x && x+w < s->x + s->cx && y >= s->y && y+s->font->height <= s->y + s->cy) -			mf_render_character(s->font, x, y, character, text_draw_char_callback, &s->color); -		return w; -	} - -	void gdispDrawString(coord_t x, coord_t y, const char *str, font_t font, color_t color) { -		/* No mutex required as we only call high level functions which have their own mutex */ -		gdispDrawString_state_t state; -		 -		state.font = font; -		state.color = color; -		state.x = x; -		state.y = y; -		state.cx = GDISP.Width - x; -		state.cy = GDISP.Height - y; -		 -		x += font->baseline_x; -		mf_render_aligned(font, x, y, MF_ALIGN_LEFT, str, 0, gdispDrawString_callback, &state); -	} - -	typedef struct -	{ -		font_t font; -		color_t color[2]; -		coord_t	x, y; -		coord_t	cx, cy; -	} gdispFillString_state_t; +	void gdispGDrawString(GDisplay *g, coord_t x, coord_t y, const char *str, font_t font, color_t color) { +		MUTEX_ENTER(g); +		g->t.font = font; +		g->t.clipx0 = x; +		g->t.clipy0 = y; +		g->t.clipx1 = x + mf_get_string_width(font, str, 0, 0); +		g->t.clipy1 = y + font->height; +		g->t.color = color; + +		mf_render_aligned(font, x+font->baseline_x, y, MF_ALIGN_LEFT, str, 0, drawcharglyph, g); +		autoflush(g); +		MUTEX_EXIT(g); +	} -	/* Callback to render characters. */ -	static uint8_t gdispFillString_callback(int16_t x, int16_t y, mf_char character, void *state) -	{ -		gdispFillString_state_t *s = state; -		uint8_t w; - -		w = mf_character_width(s->font, character); -		if (x >= s->x && x+w < s->x + s->cx && y >= s->y && y+s->font->height <= s->y + s->cy) -			mf_render_character(s->font, x, y, character, text_fill_char_callback, s->color); -		return w; -	} - -	void gdispFillString(coord_t x, coord_t y, const char *str, font_t font, color_t color, color_t bgcolor) { -		/* No mutex required as we only call high level functions which have their own mutex */ -		gdispFillString_state_t state; -		 -		state.font = font; -		state.color[0] = color; -		state.color[1] = bgcolor; -		state.x = x; -		state.y = y; -		state.cx = mf_get_string_width(font, str, 0, 0); -		state.cy = font->height; -		 -		gdispFillArea(x, y, state.cx, state.cy, bgcolor); -		mf_render_aligned(font, x+font->baseline_x, y, MF_ALIGN_LEFT, str, 0, gdispFillString_callback, &state); -	} - -	void gdispDrawStringBox(coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, font_t font, color_t color, justify_t justify) { -		/* No mutex required as we only call high level functions which have their own mutex */ -		gdispDrawString_state_t state; -		 -		state.font = font; -		state.color = color; -		state.x = x; -		state.y = y; -		state.cx = cx; -		state.cy = cy; -		 -		/* Select the anchor position */ -		switch(justify) { -		case justifyCenter: -			x += (cx + 1) / 2; -			break; -		case justifyRight: -			x += cx; -			break; -		default:	// justifyLeft -			x += font->baseline_x; -			break; +	void gdispGFillString(GDisplay *g, coord_t x, coord_t y, const char *str, font_t font, color_t color, color_t bgcolor) { +		MUTEX_ENTER(g); +		g->p.cx = mf_get_string_width(font, str, 0, 0); +		g->p.cy = font->height; +		g->t.font = font; +		g->t.clipx0 = g->p.x = x; +		g->t.clipy0 = g->p.y = y; +		g->t.clipx1 = g->p.x+g->p.cx; +		g->t.clipy1 = g->p.y+g->p.cy; +		g->t.color = color; +		g->t.bgcolor = g->p.color = bgcolor; + +		TEST_CLIP_AREA(g) { +			fillarea(g); +			mf_render_aligned(font, x+font->baseline_x, y, MF_ALIGN_LEFT, str, 0, fillcharglyph, g);  		} -		y += (cy+1 - font->height)/2; -		mf_render_aligned(font, x, y, justify, str, 0, gdispDrawString_callback, &state); +		autoflush(g); +		MUTEX_EXIT(g);  	} -	void gdispFillStringBox(coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, font_t font, color_t color, color_t bgcolor, justify_t justify) { -		/* No mutex required as we only call high level functions which have their own mutex */ -		gdispFillString_state_t state; - -		state.font = font; -		state.color[0] = color; -		state.color[1] = bgcolor; -		state.x = x; -		state.y = y; -		state.cx = cx; -		state.cy = cy; +	void gdispGDrawStringBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, font_t font, color_t color, justify_t justify) { +		MUTEX_ENTER(g); +		g->t.font = font; +		g->t.clipx0 = x; +		g->t.clipy0 = y; +		g->t.clipx1 = x+cx; +		g->t.clipy1 = y+cy; +		g->t.color = color; -		gdispFillArea(x, y, cx, cy, bgcolor); -		  		/* Select the anchor position */  		switch(justify) {  		case justifyCenter: @@ -766,9 +2746,50 @@ void gdispDrawBox(coord_t x, coord_t y, coord_t cx, coord_t cy, color_t color) {  			break;  		}  		y += (cy+1 - font->height)/2; -		 -		/* Render */ -		mf_render_aligned(font, x, y, justify, str, 0, gdispFillString_callback, &state); + +		mf_render_aligned(font, x, y, justify, str, 0, drawcharglyph, g); + +		autoflush(g); +		MUTEX_EXIT(g); +	} + +	void gdispGFillStringBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, font_t font, color_t color, color_t bgcolor, justify_t justify) { +		MUTEX_ENTER(g); +		g->p.cx = cx; +		g->p.cy = cy; +		g->t.font = font; +		g->t.clipx0 = g->p.x = x; +		g->t.clipy0 = g->p.y = y; +		g->t.clipx1 = x+cx; +		g->t.clipy1 = y+cy; +		g->t.color = color; +		g->t.bgcolor = g->p.color = bgcolor; + +		TEST_CLIP_AREA(g) { + +			// background fill +			fillarea(g); + +			/* Select the anchor position */ +			switch(justify) { +			case justifyCenter: +				x += (cx + 1) / 2; +				break; +			case justifyRight: +				x += cx; +				break; +			default:	// justifyLeft +				x += font->baseline_x; +				break; +			} +			y += (cy+1 - font->height)/2; + +			/* Render */ +			mf_render_aligned(font, x, y, justify, str, 0, fillcharglyph, g); +		} + +		autoflush(g); +		MUTEX_EXIT(g);  	}  	coord_t gdispGetFontMetric(font_t font, fontmetric_t metric) { @@ -831,5 +2852,6 @@ color_t gdispBlendColor(color_t fg, color_t bg, uint8_t alpha)  	}  #endif +  #endif /* GFX_USE_GDISP */  /** @} */ diff --git a/src/gdisp/image.c b/src/gdisp/image.c index 1e9ac3d6..62af0aeb 100644 --- a/src/gdisp/image.c +++ b/src/gdisp/image.c @@ -23,7 +23,8 @@ typedef struct gdispImageHandlers {  	gdispImageError	(*open)(gdispImage *img);			/* The open function */  	void			(*close)(gdispImage *img);			/* The close function */  	gdispImageError	(*cache)(gdispImage *img);			/* The cache function */ -	gdispImageError	(*draw)(gdispImage *img, +	gdispImageError	(*draw)(GDisplay *g, +							gdispImage *img,  							coord_t x, coord_t y,  							coord_t cx, coord_t cy,  							coord_t sx, coord_t sy);	/* The draw function */ @@ -33,27 +34,27 @@ typedef struct gdispImageHandlers {  static gdispImageHandlers ImageHandlers[] = {  	#if GDISP_NEED_IMAGE_NATIVE  		{	gdispImageOpen_NATIVE,	gdispImageClose_NATIVE, -			gdispImageCache_NATIVE,	gdispImageDraw_NATIVE,	gdispImageNext_NATIVE, +			gdispImageCache_NATIVE,	gdispGImageDraw_NATIVE,	gdispImageNext_NATIVE,  		},  	#endif  	#if GDISP_NEED_IMAGE_GIF  		{	gdispImageOpen_GIF,		gdispImageClose_GIF, -			gdispImageCache_GIF,	gdispImageDraw_GIF,		gdispImageNext_GIF, +			gdispImageCache_GIF,	gdispGImageDraw_GIF,	gdispImageNext_GIF,  		},  	#endif  	#if GDISP_NEED_IMAGE_BMP  		{	gdispImageOpen_BMP,		gdispImageClose_BMP, -			gdispImageCache_BMP,	gdispImageDraw_BMP,		gdispImageNext_BMP, +			gdispImageCache_BMP,	gdispGImageDraw_BMP,	gdispImageNext_BMP,  		},  	#endif  	#if GDISP_NEED_IMAGE_JPG  		{	gdispImageOpen_JPG,		gdispImageClose_JPG, -			gdispImageCache_JPG,	gdispImageDraw_JPG,		gdispImageNext_JPG, +			gdispImageCache_JPG,	gdispGImageDraw_JPG,	gdispImageNext_JPG,  		},  	#endif  	#if GDISP_NEED_IMAGE_PNG  		{	gdispImageOpen_PNG,		gdispImageClose_PNG, -			gdispImageCache_PNG,	gdispImageDraw_PNG,		gdispImageNext_PNG, +			gdispImageCache_PNG,	gdispGImageDraw_PNG,	gdispImageNext_PNG,  		},  	#endif  }; @@ -205,9 +206,9 @@ gdispImageError gdispImageCache(gdispImage *img) {  	return img->fns->cache(img);  } -gdispImageError gdispImageDraw(gdispImage *img, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t sx, coord_t sy) { +gdispImageError gdispGImageDraw(GDisplay *g, gdispImage *img, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t sx, coord_t sy) {  	if (!img->fns) return GDISP_IMAGE_ERR_BADFORMAT; -	return img->fns->draw(img, x, y, cx, cy, sx, sy); +	return img->fns->draw(g, img, x, y, cx, cy, sx, sy);  }  delaytime_t gdispImageNext(gdispImage *img) { diff --git a/src/gdisp/image_bmp.c b/src/gdisp/image_bmp.c index e23d0fb1..158d6edc 100644 --- a/src/gdisp/image_bmp.c +++ b/src/gdisp/image_bmp.c @@ -828,7 +828,7 @@ gdispImageError gdispImageCache_BMP(gdispImage *img) {  	return GDISP_IMAGE_ERR_OK;  } -gdispImageError gdispImageDraw_BMP(gdispImage *img, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t sx, coord_t sy) { +gdispImageError gdispGImageDraw_BMP(GDisplay *g, gdispImage *img, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t sx, coord_t sy) {  	gdispImagePrivate *	priv;  	coord_t				mx, my;  	coord_t				pos, len, st; @@ -842,7 +842,7 @@ gdispImageError gdispImageDraw_BMP(gdispImage *img, coord_t x, coord_t y, coord_  	/* Draw from the image cache - if it exists */  	if (priv->frame0cache) { -		gdispBlitAreaEx(x, y, cx, cy, sx, sy, img->width, priv->frame0cache); +		gdispGBlitArea(g, x, y, cx, cy, sx, sy, img->width, priv->frame0cache);  		return GDISP_IMAGE_ERR_OK;  	} @@ -864,9 +864,9 @@ gdispImageError gdispImageDraw_BMP(gdispImage *img, coord_t x, coord_t y, coord_  					len = pos-st;  					if (mx+st+len > sx+cx) len = sx+cx-mx-st;  					if (len == 1) -						gdispDrawPixel(x+mx+st-sx, y+my-sy, priv->buf[st]); +						gdispGDrawPixel(g, x+mx+st-sx, y+my-sy, priv->buf[st]);  					else -						gdispBlitAreaEx(x+mx+st-sx, y+my-sy, len, 1, st, 0, pos, priv->buf); +						gdispGBlitArea(g, x+mx+st-sx, y+my-sy, len, 1, st, 0, pos, priv->buf);  				}  				mx += pos;  			} @@ -882,9 +882,9 @@ gdispImageError gdispImageDraw_BMP(gdispImage *img, coord_t x, coord_t y, coord_  					len = pos-st;  					if (mx+st+len > sx+cx) len = sx+cx-mx-st;  					if (len == 1) -						gdispDrawPixel(x+mx+st-sx, y+my-sy, priv->buf[st]); +						gdispGDrawPixel(g, x+mx+st-sx, y+my-sy, priv->buf[st]);  					else -						gdispBlitAreaEx(x+mx+st-sx, y+my-sy, len, 1, st, 0, pos, priv->buf); +						gdispGBlitArea(g, x+mx+st-sx, y+my-sy, len, 1, st, 0, pos, priv->buf);  				}  				mx += pos;  			} diff --git a/src/gdisp/image_gif.c b/src/gdisp/image_gif.c index d067bd0f..1ff72ff0 100644 --- a/src/gdisp/image_gif.c +++ b/src/gdisp/image_gif.c @@ -820,7 +820,7 @@ baddatacleanup:  	return GDISP_IMAGE_ERR_BADDATA;  } -gdispImageError gdispImageDraw_GIF(gdispImage *img, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t sx, coord_t sy) { +gdispImageError gdispGImageDraw_GIF(GDisplay *g, gdispImage *img, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t sx, coord_t sy) {  	gdispImagePrivate *	priv;  	imgdecode *			decode;  	uint8_t *			q = 0; @@ -847,9 +847,9 @@ gdispImageError gdispImageDraw_GIF(gdispImage *img, coord_t x, coord_t y, coord_  			// The spec says to restore the backgound color (priv->bgcolor) but in practice if there is transparency  			//	image decoders tend to assume that a restore to the transparent color is required instead  			if (((priv->dispose.flags & GIFL_TRANSPARENT) /*&& priv->dispose.paltrans == priv->bgcolor*/) || priv->bgcolor >= priv->palsize) -				gdispFillArea(x+mx-sx, y+my-sy, fx-mx, fy-my, img->bgcolor); +				gdispGFillArea(g, x+mx-sx, y+my-sy, fx-mx, fy-my, img->bgcolor);  			else -				gdispFillArea(x+mx-sx, y+my-sy, fx-mx, fy-my, priv->palette[priv->bgcolor]); +				gdispGFillArea(g, x+mx-sx, y+my-sy, fx-mx, fy-my, priv->palette[priv->bgcolor]);  		}  	} @@ -881,23 +881,23 @@ gdispImageError gdispImageDraw_GIF(gdispImage *img, coord_t x, coord_t y, coord_  					// We have a transparent pixel - dump the buffer to the display  					switch(gcnt) {  					case 0:																							break; -					case 1:		gdispDrawPixel(x+mx-sx-gcnt, y+my-sy, priv->buf[0]); gcnt = 0;						break; -					default:	gdispBlitAreaEx(x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); gcnt = 0;	break; +					case 1:		gdispGDrawPixel(g, x+mx-sx-gcnt, y+my-sy, priv->buf[0]); gcnt = 0;					break; +					default:	gdispGBlitArea(g, x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); gcnt = 0;	break;  					}  					continue;  				}  				priv->buf[gcnt++] = cache->palette[col];  				if (gcnt >= BLIT_BUFFER_SIZE) {  					// We have run out of buffer - dump it to the display -					gdispBlitAreaEx(x+mx-sx-gcnt+1, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); +					gdispGBlitArea(g, x+mx-sx-gcnt+1, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf);  					gcnt = 0;  				}  			}  			// We have finished the line - dump the buffer to the display  			switch(gcnt) { -			case 0:																				break; -			case 1:		gdispDrawPixel(x+mx-sx-gcnt, y+my-sy, priv->buf[0]);					break; -			default:	gdispBlitAreaEx(x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf);	break; +			case 0:																					break; +			case 1:		gdispGDrawPixel(g, x+mx-sx-gcnt, y+my-sy, priv->buf[0]);					break; +			default:	gdispGBlitArea(g, x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf);	break;  			}  		} @@ -935,15 +935,15 @@ gdispImageError gdispImageDraw_GIF(gdispImage *img, coord_t x, coord_t y, coord_  						// We have a transparent pixel - dump the buffer to the display  						switch(gcnt) {  						case 0:																							break; -						case 1:		gdispDrawPixel(x+mx-sx-gcnt, y+my-sy, priv->buf[0]); gcnt = 0;						break; -						default:	gdispBlitAreaEx(x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); gcnt = 0;	break; +						case 1:		gdispGDrawPixel(g, x+mx-sx-gcnt, y+my-sy, priv->buf[0]); gcnt = 0;					break; +						default:	gdispGBlitArea(g, x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); gcnt = 0;	break;  						}  						continue;  					}  					priv->buf[gcnt++] = decode->palette[col];  					if (gcnt >= BLIT_BUFFER_SIZE) {  						// We have run out of buffer - dump it to the display -						gdispBlitAreaEx(x+mx-sx-gcnt+1, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); +						gdispGBlitArea(g, x+mx-sx-gcnt+1, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf);  						gcnt = 0;  					}  					continue; @@ -951,15 +951,15 @@ gdispImageError gdispImageDraw_GIF(gdispImage *img, coord_t x, coord_t y, coord_  				// We have finished the visible area - dump the buffer to the display  				switch(gcnt) {  				case 0:																							break; -				case 1:		gdispDrawPixel(x+mx-sx-gcnt, y+my-sy, priv->buf[0]); gcnt = 0;						break; -				default:	gdispBlitAreaEx(x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); gcnt = 0;	break; +				case 1:		gdispGDrawPixel(g, x+mx-sx-gcnt, y+my-sy, priv->buf[0]); gcnt = 0;					break; +				default:	gdispGBlitArea(g, x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); gcnt = 0;	break;  				}  			}  			// We have finished the line - dump the buffer to the display  			switch(gcnt) { -			case 0:																				break; -			case 1:		gdispDrawPixel(x+mx-sx-gcnt, y+my-sy, priv->buf[0]);					break; -			default:	gdispBlitAreaEx(x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf);	break; +			case 0:																					break; +			case 1:		gdispGDrawPixel(g, x+mx-sx-gcnt, y+my-sy, priv->buf[0]);					break; +			default:	gdispGBlitArea(g, x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf);	break;  			}  		}  		// Every 8th row starting at row 4 @@ -981,15 +981,15 @@ gdispImageError gdispImageDraw_GIF(gdispImage *img, coord_t x, coord_t y, coord_  						// We have a transparent pixel - dump the buffer to the display  						switch(gcnt) {  						case 0:																							break; -						case 1:		gdispDrawPixel(x+mx-sx-gcnt, y+my-sy, priv->buf[0]); gcnt = 0;						break; -						default:	gdispBlitAreaEx(x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); gcnt = 0;	break; +						case 1:		gdispGDrawPixel(g, x+mx-sx-gcnt, y+my-sy, priv->buf[0]); gcnt = 0;					break; +						default:	gdispGBlitArea(g, x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); gcnt = 0;	break;  						}  						continue;  					}  					priv->buf[gcnt++] = decode->palette[col];  					if (gcnt >= BLIT_BUFFER_SIZE) {  						// We have run out of buffer - dump it to the display -						gdispBlitAreaEx(x+mx-sx-gcnt+1, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); +						gdispGBlitArea(g, x+mx-sx-gcnt+1, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf);  						gcnt = 0;  					}  					continue; @@ -997,15 +997,15 @@ gdispImageError gdispImageDraw_GIF(gdispImage *img, coord_t x, coord_t y, coord_  				// We have finished the visible area - dump the buffer to the display  				switch(gcnt) {  				case 0:																							break; -				case 1:		gdispDrawPixel(x+mx-sx-gcnt, y+my-sy, priv->buf[0]); gcnt = 0;						break; -				default:	gdispBlitAreaEx(x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); gcnt = 0;	break; +				case 1:		gdispGDrawPixel(g, x+mx-sx-gcnt, y+my-sy, priv->buf[0]); gcnt = 0;					break; +				default:	gdispGBlitArea(g, x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); gcnt = 0;	break;  				}  			}  			// We have finished the line - dump the buffer to the display  			switch(gcnt) { -			case 0:																				break; -			case 1:		gdispDrawPixel(x+mx-sx-gcnt, y+my-sy, priv->buf[0]);					break; -			default:	gdispBlitAreaEx(x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf);	break; +			case 0:																					break; +			case 1:		gdispGDrawPixel(g, x+mx-sx-gcnt, y+my-sy, priv->buf[0]);					break; +			default:	gdispGBlitArea(g, x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf);	break;  			}  		}  		// Every 4th row starting at row 2 @@ -1027,15 +1027,15 @@ gdispImageError gdispImageDraw_GIF(gdispImage *img, coord_t x, coord_t y, coord_  						// We have a transparent pixel - dump the buffer to the display  						switch(gcnt) {  						case 0:																							break; -						case 1:		gdispDrawPixel(x+mx-sx-gcnt, y+my-sy, priv->buf[0]); gcnt = 0;						break; -						default:	gdispBlitAreaEx(x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); gcnt = 0;	break; +						case 1:		gdispGDrawPixel(g, x+mx-sx-gcnt, y+my-sy, priv->buf[0]); gcnt = 0;					break; +						default:	gdispGBlitArea(g, x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); gcnt = 0;	break;  						}  						continue;  					}  					priv->buf[gcnt++] = decode->palette[col];  					if (gcnt >= BLIT_BUFFER_SIZE) {  						// We have run out of buffer - dump it to the display -						gdispBlitAreaEx(x+mx-sx-gcnt+1, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); +						gdispGBlitArea(g, x+mx-sx-gcnt+1, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf);  						gcnt = 0;  					}  					continue; @@ -1043,15 +1043,15 @@ gdispImageError gdispImageDraw_GIF(gdispImage *img, coord_t x, coord_t y, coord_  				// We have finished the visible area - dump the buffer to the display  				switch(gcnt) {  				case 0:																							break; -				case 1:		gdispDrawPixel(x+mx-sx-gcnt, y+my-sy, priv->buf[0]); gcnt = 0;						break; -				default:	gdispBlitAreaEx(x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); gcnt = 0;	break; +				case 1:		gdispGDrawPixel(g, x+mx-sx-gcnt, y+my-sy, priv->buf[0]); gcnt = 0;					break; +				default:	gdispGBlitArea(g, x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); gcnt = 0;	break;  				}  			}  			// We have finished the line - dump the buffer to the display  			switch(gcnt) { -			case 0:																				break; -			case 1:		gdispDrawPixel(x+mx-sx-gcnt, y+my-sy, priv->buf[0]);					break; -			default:	gdispBlitAreaEx(x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf);	break; +			case 0:																					break; +			case 1:		gdispGDrawPixel(g, x+mx-sx-gcnt, y+my-sy, priv->buf[0]);					break; +			default:	gdispGBlitArea(g, x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf);	break;  			}  		}  		// Every 2nd row starting at row 1 @@ -1073,15 +1073,15 @@ gdispImageError gdispImageDraw_GIF(gdispImage *img, coord_t x, coord_t y, coord_  						// We have a transparent pixel - dump the buffer to the display  						switch(gcnt) {  						case 0:																							break; -						case 1:		gdispDrawPixel(x+mx-sx-gcnt, y+my-sy, priv->buf[0]); gcnt = 0;						break; -						default:	gdispBlitAreaEx(x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); gcnt = 0;	break; +						case 1:		gdispGDrawPixel(g, x+mx-sx-gcnt, y+my-sy, priv->buf[0]); gcnt = 0;					break; +						default:	gdispGBlitArea(g, x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); gcnt = 0;	break;  						}  						continue;  					}  					priv->buf[gcnt++] = decode->palette[col];  					if (gcnt >= BLIT_BUFFER_SIZE) {  						// We have run out of buffer - dump it to the display -						gdispBlitAreaEx(x+mx-sx-gcnt+1, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); +						gdispGBlitArea(g, x+mx-sx-gcnt+1, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf);  						gcnt = 0;  					}  					continue; @@ -1089,15 +1089,15 @@ gdispImageError gdispImageDraw_GIF(gdispImage *img, coord_t x, coord_t y, coord_  				// We have finished the visible area - dump the buffer to the display  				switch(gcnt) {  				case 0:																							break; -				case 1:		gdispDrawPixel(x+mx-sx-gcnt, y+my-sy, priv->buf[0]); gcnt = 0;						break; -				default:	gdispBlitAreaEx(x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); gcnt = 0;	break; +				case 1:		gdispGDrawPixel(g, x+mx-sx-gcnt, y+my-sy, priv->buf[0]); gcnt = 0;					break; +				default:	gdispGBlitArea(g, x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); gcnt = 0;	break;  				}  			}  			// We have finished the line - dump the buffer to the display  			switch(gcnt) { -			case 0:																				break; -			case 1:		gdispDrawPixel(x+mx-sx-gcnt, y+my-sy, priv->buf[0]);					break; -			default:	gdispBlitAreaEx(x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf);	break; +			case 0:																					break; +			case 1:		gdispGDrawPixel(g, x+mx-sx-gcnt, y+my-sy, priv->buf[0]);					break; +			default:	gdispGBlitArea(g, x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf);	break;  			}  		}  	} else { @@ -1120,15 +1120,15 @@ gdispImageError gdispImageDraw_GIF(gdispImage *img, coord_t x, coord_t y, coord_  						// We have a transparent pixel - dump the buffer to the display  						switch(gcnt) {  						case 0:																							break; -						case 1:		gdispDrawPixel(x+mx-sx-gcnt, y+my-sy, priv->buf[0]); gcnt = 0;						break; -						default:	gdispBlitAreaEx(x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); gcnt = 0;	break; +						case 1:		gdispGDrawPixel(g, x+mx-sx-gcnt, y+my-sy, priv->buf[0]); gcnt = 0;					break; +						default:	gdispGBlitArea(g, x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); gcnt = 0;	break;  						}  						continue;  					}  					priv->buf[gcnt++] = decode->palette[col];  					if (gcnt >= BLIT_BUFFER_SIZE) {  						// We have run out of buffer - dump it to the display -						gdispBlitAreaEx(x+mx-sx-gcnt+1, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); +						gdispGBlitArea(g, x+mx-sx-gcnt+1, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf);  						gcnt = 0;  					}  					continue; @@ -1136,15 +1136,15 @@ gdispImageError gdispImageDraw_GIF(gdispImage *img, coord_t x, coord_t y, coord_  				// We have finished the visible area - dump the buffer to the display  				switch(gcnt) {  				case 0:																							break; -				case 1:		gdispDrawPixel(x+mx-sx-gcnt, y+my-sy, priv->buf[0]); gcnt = 0;						break; -				default:	gdispBlitAreaEx(x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); gcnt = 0;	break; +				case 1:		gdispGDrawPixel(g, x+mx-sx-gcnt, y+my-sy, priv->buf[0]); gcnt = 0;					break; +				default:	gdispGBlitArea(g, x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf); gcnt = 0;	break;  				}  			}  			// We have finished the line - dump the buffer to the display  			switch(gcnt) { -			case 0:																				break; -			case 1:		gdispDrawPixel(x+mx-sx-gcnt, y+my-sy, priv->buf[0]);					break; -			default:	gdispBlitAreaEx(x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf);	break; +			case 0:																					break; +			case 1:		gdispGDrawPixel(g, x+mx-sx-gcnt, y+my-sy, priv->buf[0]);					break; +			default:	gdispGBlitArea(g, x+mx-sx-gcnt, y+my-sy, gcnt, 1, 0, 0, gcnt, priv->buf);	break;  			}  		}  	} diff --git a/src/gdisp/image_native.c b/src/gdisp/image_native.c index 24aed81f..72ae8b61 100644 --- a/src/gdisp/image_native.c +++ b/src/gdisp/image_native.c @@ -91,7 +91,7 @@ gdispImageError gdispImageCache_NATIVE(gdispImage *img) {  	return GDISP_IMAGE_ERR_OK;  } -gdispImageError gdispImageDraw_NATIVE(gdispImage *img, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t sx, coord_t sy) { +gdispImageError gdispImageGDraw_NATIVE(GDisplay *g, gdispImage *img, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t sx, coord_t sy) {  	coord_t		mx, mcx;  	size_t		pos, len; @@ -102,7 +102,7 @@ gdispImageError gdispImageDraw_NATIVE(gdispImage *img, coord_t x, coord_t y, coo  	/* Draw from the image cache - if it exists */  	if (img->priv->frame0cache) { -		gdispBlitAreaEx(x, y, cx, cy, sx, sy, img->width, img->priv->frame0cache); +		gdispGBlitArea(g, x, y, cx, cy, sx, sy, img->width, img->priv->frame0cache);  		return GDISP_IMAGE_ERR_OK;  	} @@ -125,7 +125,7 @@ gdispImageError gdispImageDraw_NATIVE(gdispImage *img, coord_t x, coord_t y, coo  				return GDISP_IMAGE_ERR_BADDATA;  			/* Blit the chunk of data */ -			gdispBlitAreaEx(mx, y, len, 1, 0, 0, len, img->priv->buf); +			gdispGBlitArea(g, mx, y, len, 1, 0, 0, len, img->priv->buf);  		}  		/* Get the position for the start of the next line */ @@ -71,7 +71,6 @@ void gfxInit(void) {  	#endif  	#if GFX_USE_GDISP  		_gdispInit(); -		gdispClear(Black);  	#endif  	#if GFX_USE_GWIN  		_gwinInit(); diff --git a/src/ginput/mouse.c b/src/ginput/mouse.c index 74b5a990..80a4ed20 100644 --- a/src/ginput/mouse.c +++ b/src/ginput/mouse.c @@ -65,35 +65,37 @@ static struct MouseConfig_t {  			#define FLG_CAL_OK			0x0020  			#define FLG_CAL_SAVED		0x0040  			#define FLG_CAL_FREE		0x0080 +			#define FLG_CAL_RAW			0x0100  	#if GINPUT_MOUSE_NEED_CALIBRATION  		GMouseCalibrationSaveRoutine	fnsavecal;  		GMouseCalibrationLoadRoutine	fnloadcal;  		Calibration						caldata;  	#endif +	GDisplay *							display;  	} MouseConfig;  #if GINPUT_MOUSE_NEED_CALIBRATION  	static inline void _tsDrawCross(const MousePoint *pp) { -		gdispDrawLine(pp->x-15, pp->y, pp->x-2, pp->y, White); -		gdispDrawLine(pp->x+2, pp->y, pp->x+15, pp->y, White); -		gdispDrawLine(pp->x, pp->y-15, pp->x, pp->y-2, White); -		gdispDrawLine(pp->x, pp->y+2, pp->x, pp->y+15, White); +		gdispGDrawLine(MouseConfig.display, pp->x-15, pp->y, pp->x-2, pp->y, White); +		gdispGDrawLine(MouseConfig.display, pp->x+2, pp->y, pp->x+15, pp->y, White); +		gdispGDrawLine(MouseConfig.display, pp->x, pp->y-15, pp->x, pp->y-2, White); +		gdispGDrawLine(MouseConfig.display, pp->x, pp->y+2, pp->x, pp->y+15, White); -		gdispDrawLine(pp->x-15, pp->y+15, pp->x-7, pp->y+15, RGB2COLOR(184,158,131)); -		gdispDrawLine(pp->x-15, pp->y+7, pp->x-15, pp->y+15, RGB2COLOR(184,158,131)); +		gdispGDrawLine(MouseConfig.display, pp->x-15, pp->y+15, pp->x-7, pp->y+15, RGB2COLOR(184,158,131)); +		gdispGDrawLine(MouseConfig.display, pp->x-15, pp->y+7, pp->x-15, pp->y+15, RGB2COLOR(184,158,131)); -		gdispDrawLine(pp->x-15, pp->y-15, pp->x-7, pp->y-15, RGB2COLOR(184,158,131)); -		gdispDrawLine(pp->x-15, pp->y-7, pp->x-15, pp->y-15, RGB2COLOR(184,158,131)); +		gdispGDrawLine(MouseConfig.display, pp->x-15, pp->y-15, pp->x-7, pp->y-15, RGB2COLOR(184,158,131)); +		gdispGDrawLine(MouseConfig.display, pp->x-15, pp->y-7, pp->x-15, pp->y-15, RGB2COLOR(184,158,131)); -		gdispDrawLine(pp->x+7, pp->y+15, pp->x+15, pp->y+15, RGB2COLOR(184,158,131)); -		gdispDrawLine(pp->x+15, pp->y+7, pp->x+15, pp->y+15, RGB2COLOR(184,158,131)); +		gdispGDrawLine(MouseConfig.display, pp->x+7, pp->y+15, pp->x+15, pp->y+15, RGB2COLOR(184,158,131)); +		gdispGDrawLine(MouseConfig.display, pp->x+15, pp->y+7, pp->x+15, pp->y+15, RGB2COLOR(184,158,131)); -		gdispDrawLine(pp->x+7, pp->y-15, pp->x+15, pp->y-15, RGB2COLOR(184,158,131)); -		gdispDrawLine(pp->x+15, pp->y-15, pp->x+15, pp->y-7, RGB2COLOR(184,158,131)); +		gdispGDrawLine(MouseConfig.display, pp->x+7, pp->y-15, pp->x+15, pp->y-15, RGB2COLOR(184,158,131)); +		gdispGDrawLine(MouseConfig.display, pp->x+15, pp->y-15, pp->x+15, pp->y-7, RGB2COLOR(184,158,131));  	}  	static inline void _tsClearCross(const MousePoint *pp) { -		gdispFillArea(pp->x - 15, pp->y - 15, 42, 42, Blue); +		gdispGFillArea(MouseConfig.display, pp->x - 15, pp->y - 15, 42, 42, Blue);  	}  	static inline void _tsTransform(MouseReading *pt, const Calibration *c) { @@ -169,8 +171,8 @@ static void get_calibrated_reading(MouseReading *pt) {  	get_raw_reading(pt);  	#if GINPUT_MOUSE_NEED_CALIBRATION || GDISP_NEED_CONTROL -		w = gdispGetWidth(); -		h = gdispGetHeight(); +		w = gdispGGetWidth(MouseConfig.display); +		h = gdispGGetHeight(MouseConfig.display);  	#endif  	#if GINPUT_MOUSE_NEED_CALIBRATION @@ -178,14 +180,14 @@ static void get_calibrated_reading(MouseReading *pt) {  	#endif  	#if GDISP_NEED_CONTROL -		switch(gdispGetOrientation()) { +		switch(gdispGGetOrientation(MouseConfig.display)) {  			case GDISP_ROTATE_0:  				break;  			case GDISP_ROTATE_90:  				{ -					coord_t t = pt->y; -					pt->y = h - 1 - pt->x; -					pt->x = t; +					coord_t t = pt->x; +					pt->x = w - 1 - pt->y; +					pt->y = t;  				}  				break;  			case GDISP_ROTATE_180: @@ -194,19 +196,23 @@ static void get_calibrated_reading(MouseReading *pt) {  				break;  			case GDISP_ROTATE_270:  				{ -					coord_t t = pt->x; -					pt->x = w - 1 - pt->y; -					pt->y = t; +					coord_t t = pt->y; +					pt->y = h - 1 - pt->x; +					pt->x = t;  				}  				break; +			default: +				break;  		}  	#endif  	#if GINPUT_MOUSE_NEED_CALIBRATION +	if (!(MouseConfig.flags & FLG_CAL_RAW)) {  		if (pt->x < 0)	pt->x = 0;  		else if (pt->x >= w) pt->x = w-1;  		if (pt->y < 0)	pt->y = 0;  		else if (pt->y >= h) pt->y = h-1; +	}  	#endif  } @@ -303,6 +309,7 @@ static void MousePoll(void *param) {  				pe->meta |= psl->srcflags;  				psl->srcflags = 0;  			} +			pe->display = MouseConfig.display;  			geventSendEvent(psl);  		}  	} @@ -319,6 +326,10 @@ GSourceHandle ginputGetMouse(uint16_t instance) {  	if (instance && instance != 9999)  		return 0; +	// Make sure we have a valid mouse display +	if (!MouseConfig.display) +		MouseConfig.display = GDISP; +  	// Do we need to initialise the mouse subsystem?  	if (!(MouseConfig.flags & FLG_INIT_DONE)) {  		ginput_lld_mouse_init(); @@ -344,7 +355,7 @@ GSourceHandle ginputGetMouse(uint16_t instance) {  				MouseConfig.caldata.ay = 0;  				MouseConfig.caldata.by = 1;  				MouseConfig.caldata.cy = 0; -				MouseConfig.flags |= (FLG_CAL_OK|FLG_CAL_SAVED); +				MouseConfig.flags |= (FLG_CAL_OK|FLG_CAL_SAVED|FLG_CAL_RAW);  			} else  				ginputCalibrateMouse(instance);  		#endif @@ -362,6 +373,20 @@ GSourceHandle ginputGetMouse(uint16_t instance) {  	return (GSourceHandle)&MouseConfig;  } +void ginputSetMouseDisplay(uint16_t instance, GDisplay *g) { +	if (instance) +		return; + +	MouseConfig.display = g ? g : GDISP; +} + +GDisplay *ginputGetMouseDisplay(uint16_t instance) { +	if (instance) +		return 0; + +	return MouseConfig.display; +} +  bool_t ginputGetMouseStatus(uint16_t instance, GEventMouse *pe) {  	// Win32 threads don't seem to recognise priority and/or pre-emption  	// so we add a sleep here to prevent 100% polled applications from locking up. @@ -393,8 +418,8 @@ bool_t ginputCalibrateMouse(uint16_t instance) {  		return FALSE;  	#else -		const coord_t height  =  gdispGetHeight(); -		const coord_t width  =  gdispGetWidth(); +		const coord_t height  =  gdispGGetHeight(MouseConfig.display); +		const coord_t width  =  gdispGGetWidth(MouseConfig.display);  		const MousePoint cross[]  =  {{(width / 4), (height / 4)},  										{(width - (width / 4)) , (height / 4)},  										{(width - (width / 4)) , (height - (height / 4))}, @@ -417,22 +442,22 @@ bool_t ginputCalibrateMouse(uint16_t instance) {  		MouseConfig.flags |= FLG_IN_CAL;  		gtimerStop(&MouseTimer); -		MouseConfig.flags &= ~(FLG_CAL_OK|FLG_CAL_SAVED); +		MouseConfig.flags &= ~(FLG_CAL_OK|FLG_CAL_SAVED|FLG_CAL_RAW);  		#if GDISP_NEED_CONTROL -			gdispSetOrientation(GDISP_ROTATE_0); +			gdispGSetOrientation(MouseConfig.display, GDISP_ROTATE_0);  		#endif  		#if GDISP_NEED_CLIP -			gdispSetClip(0, 0, width, height); +			gdispGSetClip(MouseConfig.display, 0, 0, width, height);  		#endif  		#if GINPUT_MOUSE_MAX_CALIBRATION_ERROR >= 0  			while(1) {  		#endif -				gdispClear(Blue); +				gdispGClear(MouseConfig.display, Blue); -				gdispFillStringBox(0, 5, width, 30, GINPUT_MOUSE_CALIBRATION_TEXT, font1,  White, Blue, justifyCenter); +				gdispGFillStringBox(MouseConfig.display, 0, 5, width, 30, GINPUT_MOUSE_CALIBRATION_TEXT, font1,  White, Blue, justifyCenter);  				for(i = 0, pt = points, pc = cross; i < GINPUT_MOUSE_CALIBRATION_POINTS; i++, pt++, pc++) {  					_tsDrawCross(pc); @@ -461,9 +486,9 @@ bool_t ginputCalibrateMouse(uint16_t instance) {  					_tsClearCross(pc);  					if (i >= 1 && pt->x == (pt-1)->x && pt->y == (pt-1)->y) { -						gdispFillStringBox(0, 35, width, 40, GINPUT_MOUSE_CALIBRATION_SAME_TEXT, font2,  Red, Yellow, justifyCenter); +						gdispGFillStringBox(MouseConfig.display, 0, 35, width, 40, GINPUT_MOUSE_CALIBRATION_SAME_TEXT, font2,  Red, Yellow, justifyCenter);  						gfxSleepMilliseconds(5000); -						gdispFillArea(0, 35, width, 40, Blue); +						gdispGFillArea(MouseConfig.display, 0, 35, width, 40, Blue);  					}  				} @@ -489,7 +514,7 @@ bool_t ginputCalibrateMouse(uint16_t instance) {  				if (err <= GINPUT_MOUSE_MAX_CALIBRATION_ERROR * GINPUT_MOUSE_MAX_CALIBRATION_ERROR)  					break; -				gdispFillStringBox(0, 35, width, 40, GINPUT_MOUSE_CALIBRATION_ERROR_TEXT, font2,  Red, Yellow, justifyCenter); +				gdispGFillStringBox(MouseConfig.display, 0, 35, width, 40, GINPUT_MOUSE_CALIBRATION_ERROR_TEXT, font2,  Red, Yellow, justifyCenter);  				gfxSleepMilliseconds(5000);  			}  		#endif @@ -512,9 +537,9 @@ bool_t ginputCalibrateMouse(uint16_t instance) {  		// Clear the screen using the GWIN default background color  		#if GFX_USE_GWIN -			gdispClear(gwinGetDefaultBgColor()); +			gdispGClear(MouseConfig.display, gwinGetDefaultBgColor());  		#else -			gdispClear(Black); +			gdispGClear(MouseConfig.display, Black);  		#endif  		return TRUE; @@ -523,8 +548,8 @@ bool_t ginputCalibrateMouse(uint16_t instance) {  /* Set the routines to save and fetch calibration data.   * This function should be called before first calling ginputGetMouse() for a particular instance - *	as the gdispGetMouse() routine may attempt to fetch calibration data and perform a startup calibration if there is no way to get it. - *	If this is called after gdispGetMouse() has been called and the driver requires calibration storage, it will immediately save the data is has already obtained. + *	as the ginputGetMouse() routine may attempt to fetch calibration data and perform a startup calibration if there is no way to get it. + *	If this is called after ginputGetMouse() has been called and the driver requires calibration storage, it will immediately save the data is has already obtained.   * The 'requireFree' parameter indicates if the fetch buffer must be free()'d to deallocate the buffer provided by the Fetch routine.   */  void ginputSetMouseCalibrationRoutines(uint16_t instance, GMouseCalibrationSaveRoutine fnsave, GMouseCalibrationLoadRoutine fnload, bool_t requireFree) { diff --git a/src/gmisc/trig.c b/src/gmisc/trig.c index 510ee597..3c6dd461 100644 --- a/src/gmisc/trig.c +++ b/src/gmisc/trig.c @@ -142,5 +142,49 @@  #endif +#if GMISC_NEED_INVSQRT +	// Algorithm based on Quake code. +	#if GMISC_INVSQRT_REAL_SLOW +		#include <math.h> +		float invsqrt(float n) { +			return 1.0/sqrt(n); +		} +	#else +		float invsqrt(float n) { +			int32_t		i; +			float		x2; + +			x2 = n * 0.5F; + +			// Convert into an int32 (no binary format conversion) +			#if GMISC_INVSQRT_MIXED_ENDIAN +				((char *)&i)[0] = ((char *)&n)[3]; +				((char *)&i)[1] = ((char *)&n)[2]; +				((char *)&i)[2] = ((char *)&n)[1]; +				((char *)&i)[3] = ((char *)&n)[0]; +			#else +				i  = *(int32_t *)&n; +			#endif + +			// evil floating point bit level hacking +			i  = 0x5F375A86 - (i >> 1);					// The quake code used 0x5F3759DF but this is better. + +			// Convert back to a float (no binary format conversion) +			#if GMISC_INVSQRT_MIXED_ENDIAN +				((char *)&n)[0] = ((char *)&i)[3]; +				((char *)&n)[1] = ((char *)&i)[2]; +				((char *)&n)[2] = ((char *)&i)[1]; +				((char *)&n)[3] = ((char *)&i)[0]; +			#else +				n  = *(float *)&i; +			#endif + +			n  = n * (1.5F - (x2 * n * n));				// 1st iteration +			//n  = n * (1.5F - (x2 * n * n));			// 2nd iteration for extra precision, this can be removed +			return n; +		} +	#endif +#endif +  #endif /* GFX_USE_GMISC */  /** @} */ diff --git a/src/gwin/button.c b/src/gwin/button.c index 4e4e67ee..b0fd973a 100644 --- a/src/gwin/button.c +++ b/src/gwin/button.c @@ -136,8 +136,8 @@ static const gwidgetVMT buttonVMT = {  	#endif  }; -GHandle gwinButtonCreate(GButtonObject *gw, const GWidgetInit *pInit) { -	if (!(gw = (GButtonObject *)_gwidgetCreate(&gw->w, pInit, &buttonVMT))) +GHandle gwinGButtonCreate(GDisplay *g, GButtonObject *gw, const GWidgetInit *pInit) { +	if (!(gw = (GButtonObject *)_gwidgetCreate(g, &gw->w, pInit, &buttonVMT)))  		return 0;  	#if GINPUT_NEED_TOGGLE @@ -171,9 +171,9 @@ void gwinButtonDraw_3D(GWidgetObject *gw, void *param) {  	if (gw->g.vmt != (gwinVMT *)&buttonVMT)	return;  	pcol = getDrawColors(gw); -	gdispFillStringBox(gw->g.x, gw->g.y, gw->g.width-1, gw->g.height-1, gw->text, gw->g.font, pcol->text, pcol->fill, justifyCenter); -	gdispDrawLine(gw->g.x+gw->g.width-1, gw->g.y, gw->g.x+gw->g.width-1, gw->g.y+gw->g.height-1, pcol->edge); -	gdispDrawLine(gw->g.x, gw->g.y+gw->g.height-1, gw->g.x+gw->g.width-2, gw->g.y+gw->g.height-1, pcol->edge); +	gdispGFillStringBox(gw->g.display, gw->g.x, gw->g.y, gw->g.width-1, gw->g.height-1, gw->text, gw->g.font, pcol->text, pcol->fill, justifyCenter); +	gdispGDrawLine(gw->g.display, gw->g.x+gw->g.width-1, gw->g.y, gw->g.x+gw->g.width-1, gw->g.y+gw->g.height-1, pcol->edge); +	gdispGDrawLine(gw->g.display, gw->g.x, gw->g.y+gw->g.height-1, gw->g.x+gw->g.width-2, gw->g.y+gw->g.height-1, pcol->edge);  }  #if GDISP_NEED_ARC @@ -184,14 +184,14 @@ void gwinButtonDraw_3D(GWidgetObject *gw, void *param) {  		if (gw->g.vmt != (gwinVMT *)&buttonVMT)	return;  		pcol = getDrawColors(gw); -		gdispFillArea(gw->g.x, gw->g.y, gw->g.width, gw->g.height, gw->pstyle->background); +		gdispGFillArea(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gw->g.height, gw->pstyle->background);  		if (gw->g.width >= 2*RND_CNR_SIZE+10) { -			gdispFillRoundedBox(gw->g.x+1, gw->g.y+1, gw->g.width-2, gw->g.height-2, RND_CNR_SIZE-1, pcol->fill); -			gdispDrawStringBox(gw->g.x+1, gw->g.y+RND_CNR_SIZE, gw->g.width-2, gw->g.height-(2*RND_CNR_SIZE), gw->text, gw->g.font, pcol->text, justifyCenter); -			gdispDrawRoundedBox(gw->g.x, gw->g.y, gw->g.width, gw->g.height, RND_CNR_SIZE, pcol->edge); +			gdispGFillRoundedBox(gw->g.display, gw->g.x+1, gw->g.y+1, gw->g.width-2, gw->g.height-2, RND_CNR_SIZE-1, pcol->fill); +			gdispGDrawStringBox(gw->g.display, gw->g.x+1, gw->g.y+RND_CNR_SIZE, gw->g.width-2, gw->g.height-(2*RND_CNR_SIZE), gw->text, gw->g.font, pcol->text, justifyCenter); +			gdispGDrawRoundedBox(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gw->g.height, RND_CNR_SIZE, pcol->edge);  		} else { -			gdispFillStringBox(gw->g.x+1, gw->g.y+1, gw->g.width-2, gw->g.height-2, gw->text, gw->g.font, pcol->text, pcol->fill, justifyCenter); -			gdispDrawBox(gw->g.x, gw->g.y, gw->g.width, gw->g.height, pcol->edge); +			gdispGFillStringBox(gw->g.display, gw->g.x+1, gw->g.y+1, gw->g.width-2, gw->g.height-2, gw->text, gw->g.font, pcol->text, pcol->fill, justifyCenter); +			gdispGDrawBox(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gw->g.height, pcol->edge);  		}  	}  #endif @@ -204,10 +204,10 @@ void gwinButtonDraw_3D(GWidgetObject *gw, void *param) {  		if (gw->g.vmt != (gwinVMT *)&buttonVMT)	return;  		pcol = getDrawColors(gw); -		gdispFillArea(gw->g.x, gw->g.y, gw->g.width, gw->g.height, gw->pstyle->background); -		gdispFillEllipse(gw->g.x+1, gw->g.y+1, gw->g.width/2-1, gw->g.height/2-1, pcol->fill); -		gdispDrawStringBox(gw->g.x+1, gw->g.y+1, gw->g.width-2, gw->g.height-2, gw->text, gw->g.font, pcol->text, justifyCenter); -		gdispDrawEllipse(gw->g.x, gw->g.y, gw->g.width/2, gw->g.height/2, pcol->edge); +		gdispGFillArea(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gw->g.height, gw->pstyle->background); +		gdispGFillEllipse(gw->g.display, gw->g.x+1, gw->g.y+1, gw->g.width/2-1, gw->g.height/2-1, pcol->fill); +		gdispGDrawStringBox(gw->g.display, gw->g.x+1, gw->g.y+1, gw->g.width-2, gw->g.height-2, gw->text, gw->g.font, pcol->text, justifyCenter); +		gdispGDrawEllipse(gw->g.display, gw->g.x, gw->g.y, gw->g.width/2, gw->g.height/2, pcol->edge);  	}  #endif @@ -228,10 +228,10 @@ void gwinButtonDraw_3D(GWidgetObject *gw, void *param) {  		arw[5].x = (gw->g.width - gw->g.width/ARROWBODY_DIVIDER)/2; arw[5].y = gw->g.height/ARROWHEAD_DIVIDER;  		arw[6].x = 0; arw[6].y = gw->g.height/ARROWHEAD_DIVIDER; -		gdispFillArea(gw->g.x, gw->g.y, gw->g.width, gw->g.height, gw->pstyle->background); -		gdispFillConvexPoly(gw->g.x, gw->g.y, arw, 7, pcol->fill); -		gdispDrawPoly(gw->g.x, gw->g.y, arw, 7, pcol->edge); -		gdispDrawStringBox(gw->g.x+1, gw->g.y+1, gw->g.width-2, gw->g.height-2, gw->text, gw->g.font, pcol->text, justifyCenter); +		gdispGFillArea(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gw->g.height, gw->pstyle->background); +		gdispGFillConvexPoly(gw->g.display, gw->g.x, gw->g.y, arw, 7, pcol->fill); +		gdispGDrawPoly(gw->g.display, gw->g.x, gw->g.y, arw, 7, pcol->edge); +		gdispGDrawStringBox(gw->g.display, gw->g.x+1, gw->g.y+1, gw->g.width-2, gw->g.height-2, gw->text, gw->g.font, pcol->text, justifyCenter);  	}  	void gwinButtonDraw_ArrowDown(GWidgetObject *gw, void *param) { @@ -250,10 +250,10 @@ void gwinButtonDraw_3D(GWidgetObject *gw, void *param) {  		arw[5].x = (gw->g.width - gw->g.width/ARROWBODY_DIVIDER)/2; arw[5].y = gw->g.height-1-gw->g.height/ARROWHEAD_DIVIDER;  		arw[6].x = 0; arw[6].y = gw->g.height-1-gw->g.height/ARROWHEAD_DIVIDER; -		gdispFillArea(gw->g.x, gw->g.y, gw->g.width, gw->g.height, gw->pstyle->background); -		gdispFillConvexPoly(gw->g.x, gw->g.y, arw, 7, pcol->fill); -		gdispDrawPoly(gw->g.x, gw->g.y, arw, 7, pcol->edge); -		gdispDrawStringBox(gw->g.x+1, gw->g.y+1, gw->g.width-2, gw->g.height-2, gw->text, gw->g.font, pcol->text, justifyCenter); +		gdispGFillArea(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gw->g.height, gw->pstyle->background); +		gdispGFillConvexPoly(gw->g.display, gw->g.x, gw->g.y, arw, 7, pcol->fill); +		gdispGDrawPoly(gw->g.display, gw->g.x, gw->g.y, arw, 7, pcol->edge); +		gdispGDrawStringBox(gw->g.display, gw->g.x+1, gw->g.y+1, gw->g.width-2, gw->g.height-2, gw->text, gw->g.font, pcol->text, justifyCenter);  	}  	void gwinButtonDraw_ArrowLeft(GWidgetObject *gw, void *param) { @@ -272,10 +272,10 @@ void gwinButtonDraw_3D(GWidgetObject *gw, void *param) {  		arw[5].x = gw->g.width/ARROWHEAD_DIVIDER; arw[5].y = (gw->g.height + gw->g.height/ARROWBODY_DIVIDER)/2;  		arw[6].x = gw->g.width/ARROWHEAD_DIVIDER; arw[6].y = gw->g.height-1; -		gdispFillArea(gw->g.x, gw->g.y, gw->g.width, gw->g.height, gw->pstyle->background); -		gdispFillConvexPoly(gw->g.x, gw->g.y, arw, 7, pcol->fill); -		gdispDrawPoly(gw->g.x, gw->g.y, arw, 7, pcol->edge); -		gdispDrawStringBox(gw->g.x+1, gw->g.y+1, gw->g.width-2, gw->g.height-2, gw->text, gw->g.font, pcol->text, justifyCenter); +		gdispGFillArea(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gw->g.height, gw->pstyle->background); +		gdispGFillConvexPoly(gw->g.display, gw->g.x, gw->g.y, arw, 7, pcol->fill); +		gdispGDrawPoly(gw->g.display, gw->g.x, gw->g.y, arw, 7, pcol->edge); +		gdispGDrawStringBox(gw->g.display, gw->g.x+1, gw->g.y+1, gw->g.width-2, gw->g.height-2, gw->text, gw->g.font, pcol->text, justifyCenter);  	}  	void gwinButtonDraw_ArrowRight(GWidgetObject *gw, void *param) { @@ -294,10 +294,10 @@ void gwinButtonDraw_3D(GWidgetObject *gw, void *param) {  		arw[5].x = gw->g.width-1-gw->g.width/ARROWHEAD_DIVIDER; arw[5].y = (gw->g.height + gw->g.height/ARROWBODY_DIVIDER)/2;  		arw[6].x = gw->g.width-1-gw->g.width/ARROWHEAD_DIVIDER; arw[6].y = gw->g.height-1; -		gdispFillArea(gw->g.x, gw->g.y, gw->g.width, gw->g.height, gw->pstyle->background); -		gdispFillConvexPoly(gw->g.x, gw->g.y, arw, 7, pcol->fill); -		gdispDrawPoly(gw->g.x, gw->g.y, arw, 7, pcol->edge); -		gdispDrawStringBox(gw->g.x+1, gw->g.y+1, gw->g.width-2, gw->g.height-2, gw->text, gw->g.font, pcol->text, justifyCenter); +		gdispGFillArea(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gw->g.height, gw->pstyle->background); +		gdispGFillConvexPoly(gw->g.display, gw->g.x, gw->g.y, arw, 7, pcol->fill); +		gdispGDrawPoly(gw->g.display, gw->g.x, gw->g.y, arw, 7, pcol->edge); +		gdispGDrawStringBox(gw->g.display, gw->g.x+1, gw->g.y+1, gw->g.width-2, gw->g.height-2, gw->text, gw->g.font, pcol->text, justifyCenter);  	}  #endif @@ -317,8 +317,8 @@ void gwinButtonDraw_3D(GWidgetObject *gw, void *param) {  			sy = 0;  		} -		gdispImageDraw((gdispImage *)param, gw->g.x, gw->g.y, gw->g.width, gw->g.height, 0, sy); -		gdispDrawStringBox(gw->g.x+1, gw->g.y+1, gw->g.width-2, gw->g.height-2, gw->text, gw->g.font, pcol->text, justifyCenter); +		gdispGImageDraw(gw->g.display, (gdispImage *)param, gw->g.x, gw->g.y, gw->g.width, gw->g.height, 0, sy); +		gdispGDrawStringBox(gw->g.display, gw->g.x+1, gw->g.y+1, gw->g.width-2, gw->g.height-2, gw->text, gw->g.font, pcol->text, justifyCenter);  	}  #endif diff --git a/src/gwin/checkbox.c b/src/gwin/checkbox.c index 7a6198de..13730d50 100644 --- a/src/gwin/checkbox.c +++ b/src/gwin/checkbox.c @@ -108,8 +108,8 @@ static const gwidgetVMT checkboxVMT = {  	#endif  }; -GHandle gwinCheckboxCreate(GCheckboxObject *gb, const GWidgetInit *pInit) { -	if (!(gb = (GCheckboxObject *)_gwidgetCreate(&gb->w, pInit, &checkboxVMT))) +GHandle gwinGCheckboxCreate(GDisplay *g, GCheckboxObject *gb, const GWidgetInit *pInit) { +	if (!(gb = (GCheckboxObject *)_gwidgetCreate(g, &gb->w, pInit, &checkboxVMT)))  		return 0;  	#if GINPUT_NEED_TOGGLE @@ -161,14 +161,14 @@ void gwinCheckboxDraw_CheckOnLeft(GWidgetObject *gw, void *param) {  	pcol = getDrawColors(gw);  	ld = gw->g.width < gw->g.height ? gw->g.width : gw->g.height; -	gdispFillArea(gw->g.x+1, gw->g.y+1, ld, ld-2, gw->pstyle->background); -	gdispDrawBox(gw->g.x, gw->g.y, ld, ld, pcol->edge); +	gdispGFillArea(gw->g.display, gw->g.x+1, gw->g.y+1, ld, ld-2, gw->pstyle->background); +	gdispGDrawBox(gw->g.display, gw->g.x, gw->g.y, ld, ld, pcol->edge);  	df = ld < 4 ? 1 : 2;  	if (gw->g.flags & GCHECKBOX_FLG_CHECKED) -		gdispFillArea(gw->g.x+df, gw->g.y+df, ld-2*df, ld-2*df, pcol->fill); +		gdispGFillArea(gw->g.display, gw->g.x+df, gw->g.y+df, ld-2*df, ld-2*df, pcol->fill); -	gdispFillStringBox(gw->g.x+ld+1, gw->g.y, gw->g.width-ld-1, gw->g.height, gw->text, gw->g.font, pcol->text, gw->pstyle->background, justifyLeft); +	gdispGFillStringBox(gw->g.display, gw->g.x+ld+1, gw->g.y, gw->g.width-ld-1, gw->g.height, gw->text, gw->g.font, pcol->text, gw->pstyle->background, justifyLeft);  	#undef gcw  } @@ -183,14 +183,14 @@ void gwinCheckboxDraw_CheckOnRight(GWidgetObject *gw, void *param) {  	ld = gw->g.width < gw->g.height ? gw->g.width : gw->g.height;  	ep = gw->g.width-ld-1; -	gdispFillArea(gw->g.x+ep-1, gw->g.y+1, ld, ld-2, gw->pstyle->background); -	gdispDrawBox(gw->g.x+ep, gw->g.y, ld, ld, pcol->edge); +	gdispGFillArea(gw->g.display, gw->g.x+ep-1, gw->g.y+1, ld, ld-2, gw->pstyle->background); +	gdispGDrawBox(gw->g.display, gw->g.x+ep, gw->g.y, ld, ld, pcol->edge);  	df = ld < 4 ? 1 : 2;  	if (gw->g.flags & GCHECKBOX_FLG_CHECKED) -		gdispFillArea(gw->g.x+ep+df, gw->g.y+df, ld-2*df, ld-2*df, pcol->fill); +		gdispGFillArea(gw->g.display, gw->g.x+ep+df, gw->g.y+df, ld-2*df, ld-2*df, pcol->fill); -	gdispFillStringBox(gw->g.x, gw->g.y, ep-1, gw->g.height, gw->text, gw->g.font, pcol->text, gw->pstyle->background, justifyRight); +	gdispGFillStringBox(gw->g.display, gw->g.x, gw->g.y, ep-1, gw->g.height, gw->text, gw->g.font, pcol->text, gw->pstyle->background, justifyRight);  	#undef gcw  } diff --git a/src/gwin/console.c b/src/gwin/console.c index b6a20dea..1be18662 100644 --- a/src/gwin/console.c +++ b/src/gwin/console.c @@ -66,8 +66,8 @@ static const gwinVMT consoleVMT = {  		AfterClear,				// The after-clear routine  }; -GHandle gwinConsoleCreate(GConsoleObject *gc, const GWindowInit *pInit) { -	if (!(gc = (GConsoleObject *)_gwindowCreate(&gc->g, pInit, &consoleVMT, 0))) +GHandle gwinGConsoleCreate(GDisplay *g, GConsoleObject *gc, const GWindowInit *pInit) { +	if (!(gc = (GConsoleObject *)_gwindowCreate(g, &gc->g, pInit, &consoleVMT, 0)))  		return 0;  	#if GFX_USE_OS_CHIBIOS && GWIN_CONSOLE_USE_BASESTREAM  		gc->stream.vmt = &GWindowConsoleVMT; @@ -97,7 +97,7 @@ void gwinPutChar(GHandle gh, char c) {  	fp = gdispGetFontMetric(gh->font, fontCharPadding);  	#if GDISP_NEED_CLIP -		gdispSetClip(gh->x, gh->y, gh->width, gh->height); +		gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);  	#endif  	if (c == '\n') { @@ -116,13 +116,13 @@ void gwinPutChar(GHandle gh, char c) {  		if (gcw->cy + fy > gh->height) {  #if GDISP_NEED_SCROLL  			/* scroll the console */ -			gdispVerticalScroll(gh->x, gh->y, gh->width, gh->height, fy, gh->bgcolor); +			gdispGVerticalScroll(gh->display, gh->x, gh->y, gh->width, gh->height, fy, gh->bgcolor);  			/* reset the cursor to the start of the last line */  			gcw->cx = 0;  			gcw->cy = (((coord_t)(gh->height/fy))-1)*fy;  #else  			/* clear the console */ -			gdispFillArea(gh->x, gh->y, gh->width, gh->height, gh->bgcolor); +			gdispGFillArea(gh->display, gh->x, gh->y, gh->width, gh->height, gh->bgcolor);  			/* reset the cursor to the top of the window */  			gcw->cx = 0;  			gcw->cy = 0; @@ -132,12 +132,12 @@ void gwinPutChar(GHandle gh, char c) {  #if GWIN_CONSOLE_USE_CLEAR_LINES  		/* clear to the end of the line */  		if (gcw->cx == 0) -			gdispFillArea(gh->x, gh->y + gcw->cy, gh->width, fy, gh->bgcolor); +			gdispGFillArea(gh->display, gh->x, gh->y + gcw->cy, gh->width, fy, gh->bgcolor);  #endif  #if GWIN_CONSOLE_USE_FILLED_CHARS -		gdispFillChar(gh->x + gcw->cx, gh->y + gcw->cy, c, gh->font, gh->color, gh->bgcolor); +		gdispGFillChar(gh->display, gh->x + gcw->cx, gh->y + gcw->cy, c, gh->font, gh->color, gh->bgcolor);  #else -		gdispDrawChar(gh->x + gcw->cx, gh->y + gcw->cy, c, gh->font, gh->color); +		gdispGDrawChar(gh->display, gh->x + gcw->cx, gh->y + gcw->cy, c, gh->font, gh->color);  #endif  		/* update cursor */ diff --git a/src/gwin/gimage.c b/src/gwin/gimage.c index 8eed3ac7..b1f8e078 100644 --- a/src/gwin/gimage.c +++ b/src/gwin/gimage.c @@ -51,7 +51,7 @@ static void _redraw(GHandle gh) {  	// If the image isn't open just clear the area  	if (!gdispImageIsOpen(&widget(gh)->image)) { -		gdispFillArea(x, y, w, h, bg); +		gdispGFillArea(gh->display, x, y, w, h, bg);  		return;  	} @@ -61,8 +61,8 @@ static void _redraw(GHandle gh) {  		dx = (gh->width-w)/2;  		x += dx;  		if (dx) -			gdispFillArea(gh->x, y, dx, h, bg); -		gdispFillArea(x+w, y, gh->width-dx-w, h, bg); +			gdispGFillArea(gh->display, gh->x, y, dx, h, bg); +		gdispGFillArea(gh->display, x+w, y, gh->width-dx-w, h, bg);  		dx = 0;  	} @@ -77,8 +77,8 @@ static void _redraw(GHandle gh) {  		dy = (gh->height-h)/2;  		y += dy;  		if (dy) -			gdispFillArea(x, gh->y, w, dy, bg); -		gdispFillArea(x, y+h, w, gh->height-dy-h, bg); +			gdispGFillArea(gh->display, x, gh->y, w, dy, bg); +		gdispGFillArea(gh->display, x, y+h, w, gh->height-dy-h, bg);  		dy = 0;  	} @@ -91,7 +91,7 @@ static void _redraw(GHandle gh) {  	gdispImageSetBgColor(&widget(gh)->image, bg);  	// Display the image -	gdispImageDraw(&widget(gh)->image, x, y, w, h, dx, dy); +	gdispGImageDraw(gh->display, &widget(gh)->image, x, y, w, h, dx, dy);  	#if GWIN_NEED_IMAGE_ANIMATION  		// read the delay for the next frame @@ -122,8 +122,8 @@ static const gwinVMT imageVMT = {  	0,							// The after-clear routine  }; -GHandle gwinImageCreate(GImageObject *gobj, GWindowInit *pInit) { -	if (!(gobj = (GImageObject *)_gwindowCreate(&gobj->g, pInit, &imageVMT, 0))) +GHandle gwinGImageCreate(GDisplay *g, GImageObject *gobj, GWindowInit *pInit) { +	if (!(gobj = (GImageObject *)_gwindowCreate(g, &gobj->g, pInit, &imageVMT, 0)))  		return 0;  	// Ensure the gdispImageIsOpen() gives valid results @@ -153,7 +153,7 @@ bool_t gwinImageOpenMemory(GHandle gh, const void* memory) {  		// Setting the clip here shouldn't be necessary if the redraw doesn't overdraw  		//	but we put it in for safety anyway  		#if GDISP_NEED_CLIP -			gdispSetClip(gh->x, gh->y, gh->width, gh->height); +			gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);  		#endif  		_redraw(gh);  	} @@ -176,7 +176,7 @@ bool_t gwinImageOpenFile(GHandle gh, const char* filename) {  		// Setting the clip here shouldn't be necessary if the redraw doesn't overdraw  		//	but we put it in for safety anyway  		#if GDISP_NEED_CLIP -			gdispSetClip(gh->x, gh->y, gh->width, gh->height); +			gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);  		#endif  		_redraw(gh);  	} @@ -200,7 +200,7 @@ bool_t gwinImageOpenStream(GHandle gh, void *streamPtr) {  		// Setting the clip here shouldn't be necessary if the redraw doesn't overdraw  		//	but we put it in for safety anyway  		#if GDISP_NEED_CLIP -			gdispSetClip(gh->x, gh->y, gh->width, gh->height); +			gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);  		#endif  		_redraw(gh);  	} diff --git a/src/gwin/graph.c b/src/gwin/graph.c index 8cab05a4..1d513290 100644 --- a/src/gwin/graph.c +++ b/src/gwin/graph.c @@ -46,22 +46,22 @@ static void pointto(GGraphObject *gg, coord_t x, coord_t y, const GGraphPointSty  	y = gg->g.y + gg->g.height - 1 - gg->yorigin - y;  	if (style->size <= 1) { -		gdispDrawPixel(x, y, style->color); +		gdispGDrawPixel(gg->g.display, x, y, style->color);  		return;  	}  	switch(style->type) {  	case GGRAPH_POINT_SQUARE: -		gdispDrawBox(x-style->size, y-style->size, 2*style->size, 2*style->size, style->color); +		gdispGDrawBox(gg->g.display, x-style->size, y-style->size, 2*style->size, 2*style->size, style->color);  		break;  #if GDISP_NEED_CIRCLE  	case GGRAPH_POINT_CIRCLE: -		gdispDrawCircle(x, y, style->size, style->color); +		gdispGDrawCircle(gg->g.display, x, y, style->size, style->color);  		break;  #endif  	case GGRAPH_POINT_DOT:  	default: -		gdispDrawPixel(x, y, style->color); +		gdispGDrawPixel(gg->g.display, x, y, style->color);  		break;  	}  } @@ -83,7 +83,7 @@ static void lineto(GGraphObject *gg, coord_t x0, coord_t y0, coord_t x1, coord_t  	if (style->size <= 0) {  		// Use the driver to draw a solid line -		gdispDrawLine(x0, y0, x1, y1, style->color); +		gdispGDrawLine(gg->g.display, x0, y0, x1, y1, style->color);  		return;  	} @@ -101,7 +101,7 @@ static void lineto(GGraphObject *gg, coord_t x0, coord_t y0, coord_t x1, coord_t  	case GGRAPH_LINE_SOLID:  	default:  		// Use the driver to draw a solid line -		gdispDrawLine(x0, y0, x1, y1, style->color); +		gdispGDrawLine(gg->g.display, x0, y0, x1, y1, style->color);  		return;  	} @@ -131,7 +131,7 @@ static void lineto(GGraphObject *gg, coord_t x0, coord_t y0, coord_t x1, coord_t  			if (run++ >= 0) {  				if (run >= run_on)  					run = run_off; -				gdispDrawPixel(x0, y0, style->color); +				gdispGDrawPixel(gg->g.display, x0, y0, style->color);  			}  			if (P < 0) {  				P  += dy; @@ -151,7 +151,7 @@ static void lineto(GGraphObject *gg, coord_t x0, coord_t y0, coord_t x1, coord_t  			if (run++ >= 0) {  				if (run >= run_on)  					run = run_off; -				gdispDrawPixel(x0, y0, style->color); +				gdispGDrawPixel(gg->g.display, x0, y0, style->color);  			}  			if (P < 0) {  				P  += dx; @@ -165,8 +165,8 @@ static void lineto(GGraphObject *gg, coord_t x0, coord_t y0, coord_t x1, coord_t  	}  } -GHandle gwinGraphCreate(GGraphObject *gg, const GWindowInit *pInit) { -	if (!(gg = (GGraphObject *)_gwindowCreate(&gg->g, pInit, &graphVMT, 0))) +GHandle gwinGGraphCreate(GDisplay *g, GGraphObject *gg, const GWindowInit *pInit) { +	if (!(gg = (GGraphObject *)_gwindowCreate(g, &gg->g, pInit, &graphVMT, 0)))  		return 0;  	gg->xorigin = gg->yorigin = 0;  	gg->lastx = gg->lasty = 0; diff --git a/src/gwin/gwidget.c b/src/gwin/gwidget.c index 111777a2..db9dc9fa 100644 --- a/src/gwin/gwidget.c +++ b/src/gwin/gwidget.c @@ -102,6 +102,10 @@ static void gwidgetEvent(void *param, GEvent *pe) {  		// Cycle through all windows  		for(qi = gfxQueueASyncPeek(&_GWINList); qi; qi = gfxQueueASyncNext(qi)) { +			// check if the widget matches this display +			if (gh->display != pme->display) +				continue; +  			// check if it a widget that is enabled and visible  			if ((gh->flags & (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_VISIBLE)) != (GWIN_FLG_WIDGET|GWIN_FLG_ENABLED|GWIN_FLG_VISIBLE))  				continue; @@ -225,8 +229,8 @@ void _gwidgetInit(void) {  	geventRegisterCallback(&gl, gwidgetEvent, 0);  } -GHandle _gwidgetCreate(GWidgetObject *pgw, const GWidgetInit *pInit, const gwidgetVMT *vmt) { -	if (!(pgw = (GWidgetObject *)_gwindowCreate(&pgw->g, &pInit->g, &vmt->g, GWIN_FLG_WIDGET|GWIN_FLG_ENABLED))) +GHandle _gwidgetCreate(GDisplay *g, GWidgetObject *pgw, const GWidgetInit *pInit, const gwidgetVMT *vmt) { +	if (!(pgw = (GWidgetObject *)_gwindowCreate(g, &pgw->g, &pInit->g, &vmt->g, GWIN_FLG_WIDGET|GWIN_FLG_ENABLED)))  		return 0;  	pgw->text = pInit->text ? pInit->text : ""; @@ -281,7 +285,7 @@ void _gwidgetRedraw(GHandle gh) {  		return;  	#if GDISP_NEED_CLIP -		gdispSetClip(gh->x, gh->y, gh->width, gh->height); +		gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);  	#endif  	gw->fnDraw(gw, gw->fnParam); diff --git a/src/gwin/gwin.c b/src/gwin/gwin.c index 44d4143c..bb425e0f 100644 --- a/src/gwin/gwin.c +++ b/src/gwin/gwin.c @@ -90,7 +90,7 @@ void _gwinInit(void) {  // Internal routine for use by GWIN components only  // Initialise a window creating it dynamically if required. -GHandle _gwindowCreate(GWindowObject *pgw, const GWindowInit *pInit, const gwinVMT *vmt, uint16_t flags) { +GHandle _gwindowCreate(GDisplay *g, GWindowObject *pgw, const GWindowInit *pInit, const gwinVMT *vmt, uint16_t flags) {  	// Allocate the structure if necessary  	if (!pgw) {  		if (!(pgw = (GWindowObject *)gfxAlloc(vmt->size))) @@ -100,6 +100,7 @@ GHandle _gwindowCreate(GWindowObject *pgw, const GWindowInit *pInit, const gwinV  		pgw->flags = flags;  	// Initialise all basic fields +	pgw->display = g;  	pgw->vmt = vmt;  	pgw->color = defaultFgColor;  	pgw->bgcolor = defaultBgColor; @@ -154,8 +155,8 @@ color_t gwinGetDefaultBgColor(void) {   * The GWindow Routines   *-----------------------------------------------*/ -GHandle gwinWindowCreate(GWindowObject *pgw, const GWindowInit *pInit) { -	if (!(pgw = _gwindowCreate(pgw, pInit, &basegwinVMT, 0))) +GHandle gwinGWindowCreate(GDisplay *g, GWindowObject *pgw, const GWindowInit *pInit) { +	if (!(pgw = _gwindowCreate(g, pgw, pInit, &basegwinVMT, 0)))  		return 0;  	gwinSetVisible(pgw, pInit->show);  	return pgw; @@ -213,7 +214,7 @@ void gwinSetEnabled(GHandle gh, bool_t enabled) {  			gh->flags |= GWIN_FLG_ENABLED;  			if ((gh->flags & GWIN_FLG_VISIBLE) && gh->vmt->Redraw) {  				#if GDISP_NEED_CLIP -					gdispSetClip(gh->x, gh->y, gh->width, gh->height); +					gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);  				#endif  				gh->vmt->Redraw(gh);  			} @@ -223,7 +224,7 @@ void gwinSetEnabled(GHandle gh, bool_t enabled) {  			gh->flags &= ~GWIN_FLG_ENABLED;  			if ((gh->flags & GWIN_FLG_VISIBLE) && gh->vmt->Redraw) {  				#if GDISP_NEED_CLIP -					gdispSetClip(gh->x, gh->y, gh->width, gh->height); +					gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);  				#endif  				gh->vmt->Redraw(gh);  			} @@ -271,9 +272,9 @@ void gwinClear(GHandle gh) {  		return;  	#if GDISP_NEED_CLIP -		gdispSetClip(gh->x, gh->y, gh->width, gh->height); +		gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);  	#endif -	gdispFillArea(gh->x, gh->y, gh->width, gh->height, gh->bgcolor); +	gdispGFillArea(gh->display, gh->x, gh->y, gh->width, gh->height, gh->bgcolor);  	if (gh->vmt->AfterClear)  		gh->vmt->AfterClear(gh);  } @@ -283,9 +284,9 @@ void gwinDrawPixel(GHandle gh, coord_t x, coord_t y) {  		return;  	#if GDISP_NEED_CLIP -		gdispSetClip(gh->x, gh->y, gh->width, gh->height); +		gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);  	#endif -	gdispDrawPixel(gh->x+x, gh->y+y, gh->color); +	gdispGDrawPixel(gh->display, gh->x+x, gh->y+y, gh->color);  }  void gwinDrawLine(GHandle gh, coord_t x0, coord_t y0, coord_t x1, coord_t y1) { @@ -293,9 +294,9 @@ void gwinDrawLine(GHandle gh, coord_t x0, coord_t y0, coord_t x1, coord_t y1) {  		return;  	#if GDISP_NEED_CLIP -		gdispSetClip(gh->x, gh->y, gh->width, gh->height); +		gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);  	#endif -	gdispDrawLine(gh->x+x0, gh->y+y0, gh->x+x1, gh->y+y1, gh->color); +	gdispGDrawLine(gh->display, gh->x+x0, gh->y+y0, gh->x+x1, gh->y+y1, gh->color);  }  void gwinDrawBox(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy) { @@ -303,9 +304,9 @@ void gwinDrawBox(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy) {  		return;  	#if GDISP_NEED_CLIP -		gdispSetClip(gh->x, gh->y, gh->width, gh->height); +		gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);  	#endif -	gdispDrawBox(gh->x+x, gh->y+y, cx, cy, gh->color); +	gdispGDrawBox(gh->display, gh->x+x, gh->y+y, cx, cy, gh->color);  }  void gwinFillArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy) { @@ -313,9 +314,9 @@ void gwinFillArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy) {  		return;  	#if GDISP_NEED_CLIP -		gdispSetClip(gh->x, gh->y, gh->width, gh->height); +		gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);  	#endif -	gdispFillArea(gh->x+x, gh->y+y, cx, cy, gh->color); +	gdispGFillArea(gh->display, gh->x+x, gh->y+y, cx, cy, gh->color);  }  void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t srcx, coord_t srcy, coord_t srccx, const pixel_t *buffer) { @@ -323,9 +324,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor  		return;  	#if GDISP_NEED_CLIP -		gdispSetClip(gh->x, gh->y, gh->width, gh->height); +		gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);  	#endif -	gdispBlitAreaEx(gh->x+x, gh->y+y, cx, cy, srcx, srcy, srccx, buffer); +	gdispGBlitArea(gh->display, gh->x+x, gh->y+y, cx, cy, srcx, srcy, srccx, buffer);  }  #if GDISP_NEED_CIRCLE @@ -334,9 +335,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor  			return;  		#if GDISP_NEED_CLIP -			gdispSetClip(gh->x, gh->y, gh->width, gh->height); +			gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);  		#endif -		gdispDrawCircle(gh->x+x, gh->y+y, radius, gh->color); +		gdispGDrawCircle(gh->display, gh->x+x, gh->y+y, radius, gh->color);  	}  	void gwinFillCircle(GHandle gh, coord_t x, coord_t y, coord_t radius) { @@ -344,9 +345,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor  			return;  		#if GDISP_NEED_CLIP -			gdispSetClip(gh->x, gh->y, gh->width, gh->height); +			gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);  		#endif -		gdispFillCircle(gh->x+x, gh->y+y, radius, gh->color); +		gdispGFillCircle(gh->display, gh->x+x, gh->y+y, radius, gh->color);  	}  #endif @@ -356,9 +357,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor  			return;  		#if GDISP_NEED_CLIP -			gdispSetClip(gh->x, gh->y, gh->width, gh->height); +			gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);  		#endif -		gdispDrawEllipse(gh->x+x, gh->y+y, a, b, gh->color); +		gdispGDrawEllipse(gh->display, gh->x+x, gh->y+y, a, b, gh->color);  	}  	void gwinFillEllipse(GHandle gh, coord_t x, coord_t y, coord_t a, coord_t b) { @@ -366,9 +367,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor  			return;  		#if GDISP_NEED_CLIP -			gdispSetClip(gh->x, gh->y, gh->width, gh->height); +			gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);  		#endif -		gdispFillEllipse(gh->x+x, gh->y+y, a, b, gh->color); +		gdispGFillEllipse(gh->display, gh->x+x, gh->y+y, a, b, gh->color);  	}  #endif @@ -378,9 +379,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor  			return;  		#if GDISP_NEED_CLIP -			gdispSetClip(gh->x, gh->y, gh->width, gh->height); +			gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);  		#endif -		gdispDrawArc(gh->x+x, gh->y+y, radius, startangle, endangle, gh->color); +		gdispGDrawArc(gh->display, gh->x+x, gh->y+y, radius, startangle, endangle, gh->color);  	}  	void gwinFillArc(GHandle gh, coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle) { @@ -388,9 +389,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor  			return;  		#if GDISP_NEED_CLIP -			gdispSetClip(gh->x, gh->y, gh->width, gh->height); +			gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);  		#endif -		gdispFillArc(gh->x+x, gh->y+y, radius, startangle, endangle, gh->color); +		gdispGFillArc(gh->display, gh->x+x, gh->y+y, radius, startangle, endangle, gh->color);  	}  #endif @@ -400,9 +401,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor  			return defaultBgColor;  		#if GDISP_NEED_CLIP -			gdispSetClip(gh->x, gh->y, gh->width, gh->height); +			gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);  		#endif -		return gdispGetPixelColor(gh->x+x, gh->y+y); +		return gdispGGetPixelColor(gh->display, gh->x+x, gh->y+y);  	}  #endif @@ -412,9 +413,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor  			return;  		#if GDISP_NEED_CLIP -			gdispSetClip(gh->x, gh->y, gh->width, gh->height); +			gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);  		#endif -		gdispDrawChar(gh->x+x, gh->y+y, c, gh->font, gh->color); +		gdispGDrawChar(gh->display, gh->x+x, gh->y+y, c, gh->font, gh->color);  	}  	void gwinFillChar(GHandle gh, coord_t x, coord_t y, char c) { @@ -422,9 +423,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor  			return;  		#if GDISP_NEED_CLIP -			gdispSetClip(gh->x, gh->y, gh->width, gh->height); +			gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);  		#endif -		gdispFillChar(gh->x+x, gh->y+y, c, gh->font, gh->color, gh->bgcolor); +		gdispGFillChar(gh->display, gh->x+x, gh->y+y, c, gh->font, gh->color, gh->bgcolor);  	}  	void gwinDrawString(GHandle gh, coord_t x, coord_t y, const char *str) { @@ -432,9 +433,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor  			return;  		#if GDISP_NEED_CLIP -			gdispSetClip(gh->x, gh->y, gh->width, gh->height); +			gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);  		#endif -		gdispDrawString(gh->x+x, gh->y+y, str, gh->font, gh->color); +		gdispGDrawString(gh->display, gh->x+x, gh->y+y, str, gh->font, gh->color);  	}  	void gwinFillString(GHandle gh, coord_t x, coord_t y, const char *str) { @@ -442,9 +443,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor  			return;  		#if GDISP_NEED_CLIP -			gdispSetClip(gh->x, gh->y, gh->width, gh->height); +			gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);  		#endif -		gdispFillString(gh->x+x, gh->y+y, str, gh->font, gh->color, gh->bgcolor); +		gdispGFillString(gh->display, gh->x+x, gh->y+y, str, gh->font, gh->color, gh->bgcolor);  	}  	void gwinDrawStringBox(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, justify_t justify) { @@ -452,9 +453,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor  			return;  		#if GDISP_NEED_CLIP -			gdispSetClip(gh->x, gh->y, gh->width, gh->height); +			gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);  		#endif -		gdispDrawStringBox(gh->x+x, gh->y+y, cx, cy, str, gh->font, gh->color, justify); +		gdispGDrawStringBox(gh->display, gh->x+x, gh->y+y, cx, cy, str, gh->font, gh->color, justify);  	}  	void gwinFillStringBox(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, const char* str, justify_t justify) { @@ -462,9 +463,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor  			return;  		#if GDISP_NEED_CLIP -			gdispSetClip(gh->x, gh->y, gh->width, gh->height); +			gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);  		#endif -		gdispFillStringBox(gh->x+x, gh->y+y, cx, cy, str, gh->font, gh->color, gh->bgcolor, justify); +		gdispGFillStringBox(gh->display, gh->x+x, gh->y+y, cx, cy, str, gh->font, gh->color, gh->bgcolor, justify);  	}  #endif @@ -474,9 +475,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor  			return;  		#if GDISP_NEED_CLIP -			gdispSetClip(gh->x, gh->y, gh->width, gh->height); +			gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);  		#endif -		gdispDrawPoly(tx+gh->x, ty+gh->y, pntarray, cnt, gh->color); +		gdispGDrawPoly(gh->display, tx+gh->x, ty+gh->y, pntarray, cnt, gh->color);  	}  	void gwinFillConvexPoly(GHandle gh, coord_t tx, coord_t ty, const point *pntarray, unsigned cnt) { @@ -484,9 +485,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor  			return;  		#if GDISP_NEED_CLIP -			gdispSetClip(gh->x, gh->y, gh->width, gh->height); +			gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);  		#endif -		gdispFillConvexPoly(tx+gh->x, ty+gh->y, pntarray, cnt, gh->color); +		gdispGFillConvexPoly(gh->display, tx+gh->x, ty+gh->y, pntarray, cnt, gh->color);  	}  #endif @@ -496,9 +497,9 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor  			return GDISP_IMAGE_ERR_OK;  		#if GDISP_NEED_CLIP -			gdispSetClip(gh->x, gh->y, gh->width, gh->height); +			gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);  		#endif -		return gdispImageDraw(img, gh->x+x, gh->y+y, cx, cy, sx, sy); +		return gdispGImageDraw(gh->display, img, gh->x+x, gh->y+y, cx, cy, sx, sy);  	}  #endif diff --git a/src/gwin/gwm.c b/src/gwin/gwm.c index a8654089..d05a8177 100644 --- a/src/gwin/gwm.c +++ b/src/gwin/gwm.c @@ -119,7 +119,7 @@ static void WM_Delete(GHandle gh) {  	// Make the window invisible and clear the area underneath  	if ((gh->flags & GWIN_FLG_VISIBLE)) {  		gh->flags &= ~GWIN_FLG_VISIBLE; -		gdispFillArea(gh->x, gh->y, gh->width, gh->height, gwinGetDefaultBgColor()); +		gdispGFillArea(gh->display, gh->x, gh->y, gh->width, gh->height, gwinGetDefaultBgColor());  	}  	// Remove it from the queue @@ -128,16 +128,16 @@ static void WM_Delete(GHandle gh) {  static void WM_Visible(GHandle gh) {  	#if GDISP_NEED_CLIP -		gdispSetClip(gh->x, gh->y, gh->width, gh->height); +		gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);  	#endif  	if ((gh->flags & GWIN_FLG_VISIBLE)) {  		if (gh->vmt->Redraw)  			gh->vmt->Redraw(gh);  		else -			gdispFillArea(gh->x, gh->y, gh->width, gh->height, gh->bgcolor); +			gdispGFillArea(gh->display, gh->x, gh->y, gh->width, gh->height, gh->bgcolor);  		// A real window manager would also redraw the borders here  	} else -		gdispFillArea(gh->x, gh->y, gh->width, gh->height, gwinGetDefaultBgColor()); +		gdispGFillArea(gh->display, gh->x, gh->y, gh->width, gh->height, gwinGetDefaultBgColor());  }  static void WM_Redim(GHandle gh, coord_t x, coord_t y, coord_t w, coord_t h) { @@ -145,12 +145,12 @@ static void WM_Redim(GHandle gh, coord_t x, coord_t y, coord_t w, coord_t h) {  	// If it won't fit on the screen move it around until it does.  	if (x < 0) { w += x; x = 0; }  	if (y < 0) { h += y; y = 0; } -	if (x > gdispGetWidth()-MIN_WIN_WIDTH)		x = gdispGetWidth()-MIN_WIN_WIDTH; -	if (y > gdispGetHeight()-MIN_WIN_HEIGHT)	y = gdispGetHeight()-MIN_WIN_HEIGHT; +	if (x > gdispGGetWidth(gh->display)-MIN_WIN_WIDTH)		x = gdispGGetWidth(gh->display)-MIN_WIN_WIDTH; +	if (y > gdispGGetHeight(gh->display)-MIN_WIN_HEIGHT)	y = gdispGGetHeight(gh->display)-MIN_WIN_HEIGHT;  	if (w < MIN_WIN_WIDTH) { w = MIN_WIN_WIDTH; }  	if (h < MIN_WIN_HEIGHT) { h = MIN_WIN_HEIGHT; } -	if (x+w > gdispGetWidth()) w = gdispGetWidth() - x; -	if (y+h > gdispGetHeight()) h = gdispGetHeight() - y; +	if (x+w > gdispGGetWidth(gh->display)) w = gdispGGetWidth(gh->display) - x; +	if (y+h > gdispGGetHeight(gh->display)) h = gdispGGetHeight(gh->display) - y;  	// If there has been no resize just exit  	if (gh->x == x && gh->y == y && gh->width == w && gh->height == h) @@ -158,7 +158,7 @@ static void WM_Redim(GHandle gh, coord_t x, coord_t y, coord_t w, coord_t h) {  	// Clear the old area  	if ((gh->flags & GWIN_FLG_VISIBLE)) -		gdispFillArea(gh->x, gh->y, gh->width, gh->height, gwinGetDefaultBgColor()); +		gdispGFillArea(gh->display, gh->x, gh->y, gh->width, gh->height, gwinGetDefaultBgColor());  	// Set the new size  	gh->x = x; gh->y = y; @@ -168,7 +168,7 @@ static void WM_Redim(GHandle gh, coord_t x, coord_t y, coord_t w, coord_t h) {  	if ((gh->flags & GWIN_FLG_VISIBLE)) {  		if (gh->vmt->Redraw) {  			#if GDISP_NEED_CLIP -				gdispSetClip(gh->x, gh->y, gh->width, gh->height); +				gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);  			#endif  			gh->vmt->Redraw(gh);  		} @@ -190,7 +190,7 @@ static void WM_Raise(GHandle gh) {  	if ((gh->flags & GWIN_FLG_VISIBLE)) {  		if (gh->vmt->Redraw) {  			#if GDISP_NEED_CLIP -				gdispSetClip(gh->x, gh->y, gh->width, gh->height); +				gdispGSetClip(gh->display, gh->x, gh->y, gh->width, gh->height);  			#endif  			gh->vmt->Redraw(gh);  		} diff --git a/src/gwin/label.c b/src/gwin/label.c index 65afff7e..5619761a 100644 --- a/src/gwin/label.c +++ b/src/gwin/label.c @@ -48,8 +48,8 @@ static void gwinLabelDefaultDraw(GWidgetObject *gw, void *param) {  	coord_t				w, h;  	(void)				param; -	w = (gw->g.flags & GLABEL_FLG_WAUTO) ? getwidth(gw->text, gw->g.font, gdispGetWidth() - gw->g.x) : gw->g.width; -	h = (gw->g.flags & GLABEL_FLG_HAUTO) ? getheight(gw->text, gw->g.font, gdispGetWidth() - gw->g.x) : gw->g.height; +	w = (gw->g.flags & GLABEL_FLG_WAUTO) ? getwidth(gw->text, gw->g.font, gdispGGetWidth(gw->g.display) - gw->g.x) : gw->g.width; +	h = (gw->g.flags & GLABEL_FLG_HAUTO) ? getheight(gw->text, gw->g.font, gdispGGetWidth(gw->g.display) - gw->g.x) : gw->g.height;  	if (gw->g.width != w || gw->g.height != h) {  		gwinResize(&gw->g, w, h); @@ -58,13 +58,13 @@ static void gwinLabelDefaultDraw(GWidgetObject *gw, void *param) {  	}  	// render the text -	gdispFillStringBox(gw->g.x, gw->g.y, gw->g.width, gw->g.height, gw->text, gw->g.font, +	gdispGFillStringBox(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gw->g.height, gw->text, gw->g.font,  			(gw->g.flags & GWIN_FLG_ENABLED) ? gw->pstyle->enabled.text : gw->pstyle->disabled.text, gw->pstyle->background,  			justifyLeft);  	// render the border (if any)  	if (gw->g.flags & GLABEL_FLG_BORDER) -		gdispDrawBox(gw->g.x, gw->g.y, gw->g.width, gw->g.height, (gw->g.flags & GWIN_FLG_ENABLED) ? gw->pstyle->enabled.edge : gw->pstyle->disabled.edge); +		gdispGDrawBox(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gw->g.height, (gw->g.flags & GWIN_FLG_ENABLED) ? gw->pstyle->enabled.edge : gw->pstyle->disabled.edge);  }  static const gwidgetVMT labelVMT = { @@ -102,23 +102,23 @@ static const gwidgetVMT labelVMT = {  	#endif  }; -GHandle gwinLabelCreate(GLabelObject *widget, GWidgetInit *pInit) { +GHandle gwinGLabelCreate(GDisplay *g, GLabelObject *widget, GWidgetInit *pInit) {  	uint16_t flags = 0;  	// auto assign width  	if (pInit->g.width <= 0) {  		flags |= GLABEL_FLG_WAUTO; -		pInit->g.width = getwidth(pInit->text, gwinGetDefaultFont(), gdispGetWidth() - pInit->g.x); +		pInit->g.width = getwidth(pInit->text, gwinGetDefaultFont(), gdispGGetWidth(g) - pInit->g.x);  	}  	// auto assign height  	if (pInit->g.height <= 0) {  		flags |= GLABEL_FLG_HAUTO; -		pInit->g.height = getheight(pInit->text, gwinGetDefaultFont(), gdispGetWidth() - pInit->g.x); +		pInit->g.height = getheight(pInit->text, gwinGetDefaultFont(), gdispGGetWidth(g) - pInit->g.x);  	} -	if (!(widget = (GLabelObject *)_gwidgetCreate(&widget->w, pInit, &labelVMT))) +	if (!(widget = (GLabelObject *)_gwidgetCreate(g, &widget->w, pInit, &labelVMT)))  		return 0;  	// no borders by default diff --git a/src/gwin/list.c b/src/gwin/list.c index 57046102..1662277d 100644 --- a/src/gwin/list.c +++ b/src/gwin/list.c @@ -96,15 +96,15 @@ static void gwinListDefaultDraw(GWidgetObject* gw, void* param) {  	// the scroll area  	if ((gw2obj->cnt > (gw->g.height-2) / iheight) || (gw->g.flags & GLIST_FLG_SCROLLALWAYS)) {  		iwidth = gw->g.width - (SCROLLWIDTH+3); -		gdispFillArea(gw->g.x+iwidth+2, gw->g.y+1, SCROLLWIDTH, gw->g.height-2, gdispBlendColor(ps->fill, gw->pstyle->background, 128)); -		gdispDrawLine(gw->g.x+iwidth+1, gw->g.y+1, gw->g.x+iwidth+1, gw->g.y+gw->g.height-2, ps->edge); +		gdispGFillArea(gw->g.display, gw->g.x+iwidth+2, gw->g.y+1, SCROLLWIDTH, gw->g.height-2, gdispBlendColor(ps->fill, gw->pstyle->background, 128)); +		gdispGDrawLine(gw->g.display, gw->g.x+iwidth+1, gw->g.y+1, gw->g.x+iwidth+1, gw->g.y+gw->g.height-2, ps->edge);  		#if GDISP_NEED_CONVEX_POLYGON -			gdispFillConvexPoly(gw->g.x+iwidth+((SCROLLWIDTH-ARROW)/2+2), gw->g.y+(ARROW/2+1), upArrow, 3, ps->fill); -			gdispFillConvexPoly(gw->g.x+iwidth+((SCROLLWIDTH-ARROW)/2+2), gw->g.y+gw->g.height-(ARROW+ARROW/2+1), downArrow, 3, ps->fill); +			gdispGFillConvexPoly(gw->g.display, gw->g.x+iwidth+((SCROLLWIDTH-ARROW)/2+2), gw->g.y+(ARROW/2+1), upArrow, 3, ps->fill); +			gdispGFillConvexPoly(gw->g.display, gw->g.x+iwidth+((SCROLLWIDTH-ARROW)/2+2), gw->g.y+gw->g.height-(ARROW+ARROW/2+1), downArrow, 3, ps->fill);  		#else  			#warning "GWIN: Lists display better when GDISP_NEED_CONVEX_POLGON is turned on" -			gdispFillArea(gw->g.x+iwidth+((SCROLLWIDTH-ARROW)/2+2), gw->g.y+(ARROW/2+1), ARROW, ARROW, ps->fill); -			gdispFillArea(gw->g.x+iwidth+((SCROLLWIDTH-ARROW)/2+2), gw->g.y+gw->g.height-(ARROW+ARROW/2+1), ARROW, ARROW, ps->fill); +			gdispGFillArea(gw->g.display, gw->g.x+iwidth+((SCROLLWIDTH-ARROW)/2+2), gw->g.y+(ARROW/2+1), ARROW, ARROW, ps->fill); +			gdispGFillArea(gw->g.display, gw->g.x+iwidth+((SCROLLWIDTH-ARROW)/2+2), gw->g.y+gw->g.height-(ARROW+ARROW/2+1), ARROW, ARROW, ps->fill);  		#endif  	} else  		iwidth = gw->g.width - 2; @@ -126,7 +126,7 @@ static void gwinListDefaultDraw(GWidgetObject* gw, void* param) {  		#if GWIN_NEED_LIST_IMAGES  			if ((gw->g.flags & GLIST_FLG_HASIMAGES)) {  				// Clear the image area -				gdispFillArea(gw->g.x+1, gw->g.y+y, x-1, iheight, fill); +				gdispGFillArea(gw->g.display, gw->g.x+1, gw->g.y+y, x-1, iheight, fill);  				if (qi2li->pimg && gdispImageIsOpen(qi2li->pimg)) {  					// Calculate which image  					sy = (qi2li->flags & GLIST_FLG_SELECTED) ? 0 : (iheight-TEXTGAP); @@ -136,19 +136,19 @@ static void gwinListDefaultDraw(GWidgetObject* gw, void* param) {  						sy -= iheight-TEXTGAP;  					// Draw the image  					gdispImageSetBgColor(qi2li->pimg, fill); -					gdispImageDraw(qi2li->pimg, gw->g.x+1, gw->g.y+y, iheight-TEXTGAP, iheight-TEXTGAP, 0, sy); +					gdispGImageDraw(gw->g.display, qi2li->pimg, gw->g.x+1, gw->g.y+y, iheight-TEXTGAP, iheight-TEXTGAP, 0, sy);  				}  			}  		#endif -		gdispFillStringBox(gw->g.x+x, gw->g.y+y, iwidth, iheight, qi2li->text, gw->g.font, ps->text, fill, justifyLeft); +		gdispGFillStringBox(gw->g.display, gw->g.x+x, gw->g.y+y, iwidth, iheight, qi2li->text, gw->g.font, ps->text, fill, justifyLeft);  	}  	// Fill any remaining item space  	if (y < gw->g.height-1) -		gdispFillArea(gw->g.x+1, gw->g.y+y, iwidth, gw->g.height-1-y, gw->pstyle->background); +		gdispGFillArea(gw->g.display, gw->g.x+1, gw->g.y+y, iwidth, gw->g.height-1-y, gw->pstyle->background);  	// the list frame -	gdispDrawBox(gw->g.x, gw->g.y, gw->g.width, gw->g.height, ps->edge); +	gdispGDrawBox(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gw->g.height, ps->edge);  }  #if GINPUT_NEED_MOUSE @@ -318,8 +318,8 @@ static const gwidgetVMT listVMT = {  	#endif  }; -GHandle gwinListCreate(GListObject* gobj, GWidgetInit* pInit, bool_t multiselect) { -	if (!(gobj = (GListObject *)_gwidgetCreate(&gobj->w, pInit, &listVMT))) +GHandle gwinGListCreate(GDisplay *g, GListObject* gobj, GWidgetInit* pInit, bool_t multiselect) { +	if (!(gobj = (GListObject *)_gwidgetCreate(g, &gobj->w, pInit, &listVMT)))  		return 0;  	// initialize the item queue diff --git a/src/gwin/radio.c b/src/gwin/radio.c index c9d089b0..7507634c 100644 --- a/src/gwin/radio.c +++ b/src/gwin/radio.c @@ -108,8 +108,8 @@ static const gwidgetVMT radioVMT = {  	#endif  }; -GHandle gwinRadioCreate(GRadioObject *gw, const GWidgetInit *pInit, uint16_t group) { -	if (!(gw = (GRadioObject *)_gwidgetCreate(&gw->w, pInit, &radioVMT))) +GHandle gwinGRadioCreate(GDisplay *g, GRadioObject *gw, const GWidgetInit *pInit, uint16_t group) { +	if (!(gw = (GRadioObject *)_gwidgetCreate(g, &gw->w, pInit, &radioVMT)))  		return 0;  	#if GINPUT_NEED_TOGGLE @@ -177,21 +177,21 @@ void gwinRadioDraw_Radio(GWidgetObject *gw, void *param) {  	#if GDISP_NEED_CIRCLE  		df = (ld-1)/2; -		gdispFillArea(gw->g.x, gw->g.y, ld, ld, gw->pstyle->background); -		gdispDrawCircle(gw->g.x+df, gw->g.y+df, df, pcol->edge); +		gdispGFillArea(gw->g.display, gw->g.x, gw->g.y, ld, ld, gw->pstyle->background); +		gdispGDrawCircle(gw->g.display, gw->g.x+df, gw->g.y+df, df, pcol->edge);  		if (gw->g.flags & GRADIO_FLG_PRESSED) -			gdispFillCircle(gw->g.x+df, gw->g.y+df, df <= 2 ? 1 : (df-2), pcol->fill); +			gdispGFillCircle(gw->g.display, gw->g.x+df, gw->g.y+df, df <= 2 ? 1 : (df-2), pcol->fill);  	#else -		gdispFillArea(gw->g.x+1, gw->g.y+1, ld, ld-2, gw->pstyle->background); -		gdispDrawBox(gw->g.x, gw->g.y, ld, ld, pcol->edge); +		gdispGFillArea(gw->g.display, gw->g.x+1, gw->g.y+1, ld, ld-2, gw->pstyle->background); +		gdispGDrawBox(gw->g.display, gw->g.x, gw->g.y, ld, ld, pcol->edge);  		df = ld < 4 ? 1 : 2;  		if (gw->g.flags & GRADIO_FLG_PRESSED) -			gdispFillArea(gw->g.x+df, gw->g.y+df, ld-2*df, ld-2*df, pcol->fill); +			gdispGFillArea(gw->g.display, gw->g.x+df, gw->g.y+df, ld-2*df, ld-2*df, pcol->fill);  	#endif -	gdispFillStringBox(gw->g.x+ld+1, gw->g.y, gw->g.width-ld-1, gw->g.height, gw->text, gw->g.font, pcol->text, gw->pstyle->background, justifyLeft); +	gdispGFillStringBox(gw->g.display, gw->g.x+ld+1, gw->g.y, gw->g.width-ld-1, gw->g.height, gw->text, gw->g.font, pcol->text, gw->pstyle->background, justifyLeft);  	#undef gcw  } @@ -202,9 +202,9 @@ void gwinRadioDraw_Button(GWidgetObject *gw, void *param) {  	if (gw->g.vmt != (gwinVMT *)&radioVMT) return;  	pcol = getDrawColors(gw); -	gdispFillStringBox(gw->g.x, gw->g.y, gw->g.width-1, gw->g.height-1, gw->text, gw->g.font, pcol->text, pcol->fill, justifyCenter); -	gdispDrawLine(gw->g.x+gw->g.width-1, gw->g.y, gw->g.x+gw->g.width-1, gw->g.y+gw->g.height-1, pcol->edge); -	gdispDrawLine(gw->g.x, gw->g.y+gw->g.height-1, gw->g.x+gw->g.width-2, gw->g.y+gw->g.height-1, pcol->edge); +	gdispGFillStringBox(gw->g.display, gw->g.x, gw->g.y, gw->g.width-1, gw->g.height-1, gw->text, gw->g.font, pcol->text, pcol->fill, justifyCenter); +	gdispGDrawLine(gw->g.display, gw->g.x+gw->g.width-1, gw->g.y, gw->g.x+gw->g.width-1, gw->g.y+gw->g.height-1, pcol->edge); +	gdispGDrawLine(gw->g.display, gw->g.x, gw->g.y+gw->g.height-1, gw->g.x+gw->g.width-2, gw->g.y+gw->g.height-1, pcol->edge);  }  void gwinRadioDraw_Tab(GWidgetObject *gw, void *param) { @@ -215,12 +215,12 @@ void gwinRadioDraw_Tab(GWidgetObject *gw, void *param) {  	pcol = getDrawColors(gw);  	if ((gw->g.flags & GRADIO_FLG_PRESSED)) { -		gdispDrawBox(gw->g.x, gw->g.y, gw->g.width, gw->g.height, pcol->edge); -		gdispFillStringBox(gw->g.x+1, gw->g.y+1, gw->g.width-2, gw->g.height-1, gw->text, gw->g.font, pcol->text, pcol->fill, justifyCenter); +		gdispGDrawBox(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gw->g.height, pcol->edge); +		gdispGFillStringBox(gw->g.display, gw->g.x+1, gw->g.y+1, gw->g.width-2, gw->g.height-1, gw->text, gw->g.font, pcol->text, pcol->fill, justifyCenter);  	} else { -		gdispFillStringBox(gw->g.x, gw->g.y, gw->g.width-1, gw->g.height-1, gw->text, gw->g.font, pcol->text, pcol->fill, justifyCenter); -		gdispDrawLine(gw->g.x+gw->g.width-1, gw->g.y, gw->g.x+gw->g.width-1, gw->g.y+gw->g.height-1, pcol->edge); -		gdispDrawLine(gw->g.x, gw->g.y+gw->g.height-1, gw->g.x+gw->g.width-2, gw->g.y+gw->g.height-1, pcol->edge); +		gdispGFillStringBox(gw->g.display, gw->g.x, gw->g.y, gw->g.width-1, gw->g.height-1, gw->text, gw->g.font, pcol->text, pcol->fill, justifyCenter); +		gdispGDrawLine(gw->g.display, gw->g.x+gw->g.width-1, gw->g.y, gw->g.x+gw->g.width-1, gw->g.y+gw->g.height-1, pcol->edge); +		gdispGDrawLine(gw->g.display, gw->g.x, gw->g.y+gw->g.height-1, gw->g.x+gw->g.width-2, gw->g.y+gw->g.height-1, pcol->edge);  	}  } diff --git a/src/gwin/slider.c b/src/gwin/slider.c index fdc31ead..a4ac5d95 100644 --- a/src/gwin/slider.c +++ b/src/gwin/slider.c @@ -223,8 +223,8 @@ static const gwidgetVMT sliderVMT = {  	#endif  }; -GHandle gwinSliderCreate(GSliderObject *gs, const GWidgetInit *pInit) { -	if (!(gs = (GSliderObject *)_gwidgetCreate(&gs->w, pInit, &sliderVMT))) +GHandle gwinGSliderCreate(GDisplay *g, GSliderObject *gs, const GWidgetInit *pInit) { +	if (!(gs = (GSliderObject *)_gwidgetCreate(g, &gs->w, pInit, &sliderVMT)))  		return 0;  	#if GINPUT_NEED_TOGGLE  		gs->t_dn = GWIDGET_NO_INSTANCE; @@ -294,35 +294,35 @@ void gwinSliderDraw_Std(GWidgetObject *gw, void *param) {  	if (gw->g.width < gw->g.height) {			// Vertical slider  		if (gsw->dpos != gw->g.height-1) -			gdispFillArea(gw->g.x, gw->g.y+gsw->dpos, gw->g.width, gw->g.height - gsw->dpos, pcol->progress);	// Active Area +			gdispGFillArea(gw->g.display, gw->g.x, gw->g.y+gsw->dpos, gw->g.width, gw->g.height - gsw->dpos, pcol->progress);	// Active Area  		if (gsw->dpos != 0) -			gdispFillArea(gw->g.x, gw->g.y, gw->g.width, gsw->dpos, gw->pstyle->enabled.progress);			// Inactive area -		gdispDrawBox(gw->g.x, gw->g.y, gw->g.width, gw->g.height, pcol->edge);								// Edge -		gdispDrawLine(gw->g.x, gw->g.y+gsw->dpos, gw->g.x+gw->g.width-1, gw->g.y+gsw->dpos, pcol->edge);	// Thumb +			gdispGFillArea(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gsw->dpos, gw->pstyle->enabled.progress);			// Inactive area +		gdispGDrawBox(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gw->g.height, pcol->edge);								// Edge +		gdispGDrawLine(gw->g.display, gw->g.x, gw->g.y+gsw->dpos, gw->g.x+gw->g.width-1, gw->g.y+gsw->dpos, pcol->edge);	// Thumb  		if (gsw->dpos >= 2) -			gdispDrawLine(gw->g.x, gw->g.y+gsw->dpos-2, gw->g.x+gw->g.width-1, gw->g.y+gsw->dpos-2, pcol->edge);	// Thumb +			gdispGDrawLine(gw->g.display, gw->g.x, gw->g.y+gsw->dpos-2, gw->g.x+gw->g.width-1, gw->g.y+gsw->dpos-2, pcol->edge);	// Thumb  		if (gsw->dpos <= gw->g.height-2) -			gdispDrawLine(gw->g.x, gw->g.y+gsw->dpos+2, gw->g.x+gw->g.width-1, gw->g.y+gsw->dpos+2, pcol->edge);	// Thumb +			gdispGDrawLine(gw->g.display, gw->g.x, gw->g.y+gsw->dpos+2, gw->g.x+gw->g.width-1, gw->g.y+gsw->dpos+2, pcol->edge);	// Thumb  	// Horizontal slider  	} else {  		if (gsw->dpos != gw->g.width-1) -			gdispFillArea(gw->g.x+gsw->dpos, gw->g.y, gw->g.width-gsw->dpos, gw->g.height, gw->pstyle->enabled.progress);	// Inactive area +			gdispGFillArea(gw->g.display, gw->g.x+gsw->dpos, gw->g.y, gw->g.width-gsw->dpos, gw->g.height, gw->pstyle->enabled.progress);	// Inactive area  		if (gsw->dpos != 0) -			gdispFillArea(gw->g.x, gw->g.y, gsw->dpos, gw->g.height, pcol->progress);	// Active Area -		gdispDrawBox(gw->g.x, gw->g.y, gw->g.width, gw->g.height, pcol->edge);								// Edge -		gdispDrawLine(gw->g.x+gsw->dpos, gw->g.y, gw->g.x+gsw->dpos, gw->g.y+gw->g.height-1, pcol->edge);	// Thumb +			gdispGFillArea(gw->g.display, gw->g.x, gw->g.y, gsw->dpos, gw->g.height, pcol->progress);	// Active Area +		gdispGDrawBox(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gw->g.height, pcol->edge);								// Edge +		gdispGDrawLine(gw->g.display, gw->g.x+gsw->dpos, gw->g.y, gw->g.x+gsw->dpos, gw->g.y+gw->g.height-1, pcol->edge);	// Thumb  		if (gsw->dpos >= 2) -			gdispDrawLine(gw->g.x+gsw->dpos-2, gw->g.y, gw->g.x+gsw->dpos-2, gw->g.y+gw->g.height-1, pcol->edge);	// Thumb +			gdispGDrawLine(gw->g.display, gw->g.x+gsw->dpos-2, gw->g.y, gw->g.x+gsw->dpos-2, gw->g.y+gw->g.height-1, pcol->edge);	// Thumb  		if (gsw->dpos <= gw->g.width-2) -			gdispDrawLine(gw->g.x+gsw->dpos+2, gw->g.y, gw->g.x+gsw->dpos+2, gw->g.y+gw->g.height-1, pcol->edge);	// Thumb +			gdispGDrawLine(gw->g.display, gw->g.x+gsw->dpos+2, gw->g.y, gw->g.x+gsw->dpos+2, gw->g.y+gw->g.height-1, pcol->edge);	// Thumb  	} -	gdispDrawStringBox(gw->g.x+1, gw->g.y+1, gw->g.width-2, gw->g.height-2, gw->text, gw->g.font, pcol->text, justifyCenter); +	gdispGDrawStringBox(gw->g.display, gw->g.x+1, gw->g.y+1, gw->g.width-2, gw->g.height-2, gw->text, gw->g.font, pcol->text, justifyCenter);  	#undef gsw  } -#if GDISP_NEED_IMAGE || defined(__DOXYGEN__) +#if GDISP_NEED_IMAGE  void gwinSliderDraw_Image(GWidgetObject *gw, void *param) {  	#define gsw			((GSliderObject *)gw)  	#define gi			((gdispImage *)param) @@ -339,7 +339,7 @@ void gwinSliderDraw_Image(GWidgetObject *gw, void *param) {  	if (gw->g.width < gw->g.height) {			// Vertical slider  		if (gsw->dpos != 0)							// The unfilled area -			gdispFillArea(gw->g.x, gw->g.y, gw->g.width, gsw->dpos, gw->pstyle->enabled.progress);	// Inactive area +			gdispGFillArea(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gsw->dpos, gw->pstyle->enabled.progress);	// Inactive area  		if (gsw->dpos != gw->g.height-1) {			// The filled area  			for(z=gw->g.height, v=gi->height; z > gsw->dpos;) {  				z -= v; @@ -347,27 +347,27 @@ void gwinSliderDraw_Image(GWidgetObject *gw, void *param) {  					v -= gsw->dpos - z;  					z = gsw->dpos;  				} -				gdispImageDraw(gi, gw->g.x, gw->g.y+z, gw->g.width, v, 0, gi->height-v); +				gdispGImageDraw(gw->g.display, gi, gw->g.x, gw->g.y+z, gw->g.width, v, 0, gi->height-v);  			}  		} -		gdispDrawBox(gw->g.x, gw->g.y, gw->g.width, gw->g.height, pcol->edge);								// Edge -		gdispDrawLine(gw->g.x, gw->g.y+gsw->dpos, gw->g.x+gw->g.width-1, gw->g.y+gsw->dpos, pcol->edge);	// Thumb +		gdispGDrawBox(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gw->g.height, pcol->edge);								// Edge +		gdispGDrawLine(gw->g.display, gw->g.x, gw->g.y+gsw->dpos, gw->g.x+gw->g.width-1, gw->g.y+gsw->dpos, pcol->edge);	// Thumb  	// Horizontal slider  	} else {  		if (gsw->dpos != gw->g.width-1)				// The unfilled area -			gdispFillArea(gw->g.x+gsw->dpos, gw->g.y, gw->g.width-gsw->dpos, gw->g.height, gw->pstyle->enabled.progress);	// Inactive area +			gdispGFillArea(gw->g.display, gw->g.x+gsw->dpos, gw->g.y, gw->g.width-gsw->dpos, gw->g.height, gw->pstyle->enabled.progress);	// Inactive area  		if (gsw->dpos != 0) {						// The filled area  			for(z=0, v=gi->width; z < gsw->dpos; z += v) {  				if (z+v > gsw->dpos)  					v -= z+v - gsw->dpos; -				gdispImageDraw(gi, gw->g.x+z, gw->g.y, v, gw->g.height, 0, 0); +				gdispGImageDraw(gw->g.display, gi, gw->g.x+z, gw->g.y, v, gw->g.height, 0, 0);  			}  		} -		gdispDrawBox(gw->g.x, gw->g.y, gw->g.width, gw->g.height, pcol->edge);								// Edge -		gdispDrawLine(gw->g.x+gsw->dpos, gw->g.y, gw->g.x+gsw->dpos, gw->g.y+gw->g.height-1, pcol->edge);	// Thumb +		gdispGDrawBox(gw->g.display, gw->g.x, gw->g.y, gw->g.width, gw->g.height, pcol->edge);								// Edge +		gdispGDrawLine(gw->g.display, gw->g.x+gsw->dpos, gw->g.y, gw->g.x+gsw->dpos, gw->g.y+gw->g.height-1, pcol->edge);	// Thumb  	} -	gdispDrawStringBox(gw->g.x+1, gw->g.y+1, gw->g.width-2, gw->g.height-2, gw->text, gw->g.font, pcol->text, justifyCenter); +	gdispGDrawStringBox(gw->g.display, gw->g.x+1, gw->g.y+1, gw->g.width-2, gw->g.height-2, gw->text, gw->g.font, pcol->text, justifyCenter);  	#undef gsw  }  | 
