/* $id: $
 ***************************************************************************
 *            wince_gfx.c
 *
 *  December 2009, Steffen Pohle steffen@gulpe.de
 ****************************************************************************/

/*
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */


#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <windows.h>
#include <commctrl.h>
#include <winbase.h>
#if defined(__MINGW32CE__) || defined(_WIN32_WCE)
	#include <aygshell.h>
#endif

#include <mmsystem.h>

#include "osmroute.h"
#include "wince_port.h"
#include "draw.h"
#include "memoryleak.h"


int draw_wm_paint = 0;
struct image *gfx_doublebuffer = NULL;
iPoint gfx_screensize;

void gfx_resize (int x, int y) {
	if (x == 0) x = 1;
	if (y == 0) y = 1;

	gfx_screensize.x = x;
	gfx_screensize.y = y;
	
	if (gfx_doublebuffer)
		gfx_img_free (gfx_doublebuffer);
	gfx_doublebuffer = gfx_img_alloc (x, y);
};


void gfx_flip () {
	HDC			hdc;
	PAINTSTRUCT	ps;

	/* komplett neuschreiben... */
	if (draw_wm_paint) {
		hdc = BeginPaint(hMainWnd, &ps);
	}
	else {
		hdc = GetDC(hMainWnd);
	}

	BitBlt(hdc, 0, 0, gfx_screensize.x, gfx_screensize.y, gfx_doublebuffer->hdc, 0, 0, SRCCOPY);
	
	/* komplett neuschreiben... */
	if (draw_wm_paint) {
		EndPaint(hMainWnd, &ps);	
	}
	else {
		ReleaseDC(hMainWnd, hdc);
	}
};


int gfx_color_alloc (struct color *c, unsigned short int r, unsigned short int g, unsigned short int b) {
	int r1, g1, b1;

	c->r = r;
	c->b = b;
	c->g = g;

	r1 = r >> 8;
	g1 = g >> 8;
	b1 = b >> 8;
	
	c->col = (b1 << 16) + (g1 << 8) + r1;
	if (c->alloc) {
		DeleteObject (c->brush);
		DeleteObject (c->pen);
		c->alloc = 0;
	}

	c->brush = CreateSolidBrush (c->col);
	c->pen = CreatePen (PS_SOLID, 1, c->col);
	c->alloc = 1;
	
	return 1;
};


void gfx_clear (struct image *dimg, struct color *c) {
	RECT r;

	if (dimg == NULL) dimg = gfx_doublebuffer;
	
	r.top = 0;
	r.left = 0;
	r.right = dimg->width;
	r.bottom = dimg->height;
	
	FillRect(dimg->hdc, &r, c->brush);
};


/*
 * draw line 
 */
void gfx_draw_line (struct image *dimg, int x1, int y1, int x2, int y2, struct line_style style) {
	static HPEN pen = NULL;
	HPEN tmp_pen = NULL;
	static int width = 0;
	static COLORREF c = 0;
	POINT p[2];

	if (dimg == NULL) dimg = gfx_doublebuffer;
	
	if (c != style.c.col || width != style.width || pen == NULL) {
		DeleteObject (pen);
		pen = CreatePen (PS_SOLID, style.width, style.c.col); 
		width = style.width;
		c = style.c.col;
	}	

	p[0].x = x1;
	p[0].y = y1;
	p[1].x = x2;
	p[1].y = y2;
	tmp_pen = SelectObject (dimg->hdc, pen);
	Polyline(dimg->hdc, p, 2);
	SelectObject (dimg->hdc, tmp_pen);
};


/*
 * draw polygon
 */
void gfx_draw_polygon (struct image *dimg, iPoint *p, int pcnt, struct line_style style, struct color *c) {
	static POINT *polygon = NULL;
	static int polygon_cnt = 0;
	int i;
	HPEN tmp_pen;
	HBRUSH tmp_brush;

	if (dimg == NULL) dimg = gfx_doublebuffer;

	if (polygon_cnt < pcnt) {
		polygon_cnt = pcnt;
		if (polygon != NULL)
			polygon = (POINT *) ml_realloc (polygon, sizeof (POINT) * polygon_cnt);
		else
			polygon = (POINT *) ml_malloc (sizeof (POINT) * polygon_cnt);
	}

	for (i = 0; i < pcnt; i++) {
		polygon[i].x = p[i].x;
		polygon[i].y = p[i].y;
	}

	tmp_brush = SelectObject (dimg->hdc, c->brush);
	tmp_pen = SelectObject (dimg->hdc, c->pen);
	Polygon (dimg->hdc, polygon, pcnt);
	SelectObject (dimg->hdc, tmp_brush);
	SelectObject (dimg->hdc, tmp_pen);
};


/*
 * text drawing functions
 */
void gfx_draw_text (struct image *dimg, int x, int y, char *text, struct color *c) {
	static WCHAR wtext[256];
	RECT r;
	int l;

	if (dimg == NULL) dimg = gfx_doublebuffer;

	r.left = x;
	r.top = y;
	r.right = gfx_screensize.x - x;
	r.bottom = gfx_screensize.y - y;

	l = char2wchar (wtext, 256, text);
	wtext[l] = 0;

	SetTextColor (dimg->hdc, c->col);
	SetBkColor (dimg->hdc, color[COLOR_white][0].col);
	SetBkMode (dimg->hdc, TRANSPARENT);
#if defined(__MINGW32CE__) || defined(_WIN32_WCE)
	DrawText (dimg->hdc, wtext, l, &r, DT_NOCLIP);
#else
	static char otext[256];
	l = wchar2oem (otext, 256, wtext);
	DrawText (dimg->hdc, otext, l, &r, DT_NOCLIP);
#endif
};


/*
 * drawing bitmap into a bitmap
 */
void gfx_draw_img (struct image *dimg, int dx, int dy, int dw, int dh, struct image *simg, int sx, int sy) {
	if (dimg == NULL) dimg = gfx_doublebuffer;

	/* check for boundrys, do clipping */
	if (sx + dw > simg->width) dw = simg->width - sx;
	if (dx + dw > dimg->width) dw = dimg->width - dx;
	if (sy + dh > simg->height) dh = simg->height - sy;
	if (dy + dh > dimg->height) dh = dimg->height - dy;
	if (dw <= 0 || dh <= 0) return;
	BitBlt(dimg->hdc, dx, dy, dw, dh, simg->hdc, sx, sy, SRCCOPY);
};


/*
 * allocate memory bitmap
 */
struct image *gfx_img_alloc (int w, int h) {
	struct image *img = (struct image *) ml_malloc (sizeof (struct image));
	HBITMAP tmp_bitmap;
	HDC			hdc;

	hdc = GetDC(hMainWnd);

	img->hdc = CreateCompatibleDC (hdc);
    img->bitmap = CreateCompatibleBitmap (hdc, w, h);
    tmp_bitmap = SelectObject (img->hdc, img->bitmap);
	img->width = w;
	img->height = h;
	
	return img;
};


void gfx_img_free (struct image *img) {
	DeleteObject (img->hdc);
	DeleteObject (img->bitmap);
	ml_free (img);
};


void gfx_draw_rect (struct image *dimg, int x1, int y1, int x2, int y2, struct color *c) {
	HPEN tmp_pen;
	HBRUSH tmp_brush;

	if (dimg == NULL) dimg = gfx_doublebuffer;

	tmp_pen = SelectObject (dimg->hdc, c->pen);
	tmp_brush = SelectObject (dimg->hdc, c->brush);
	Rectangle (dimg->hdc, x1, y1, x2, y2);
	SelectObject (dimg->hdc, tmp_brush);
	SelectObject (dimg->hdc, tmp_pen);
};

