Fix:graphics_win32:Restored mingw32ce compatibility
[profile/ivi/navit.git] / navit / navit / graphics / win32 / graphics_win32.c
1 #include <windows.h>
2 #include <windowsx.h>
3 #include <wingdi.h>
4 #include <glib.h>
5 #include <math.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include "config.h"
9 #include "debug.h"
10 #include "point.h"
11 #include "graphics.h"
12 #include "color.h"
13 #include "callback.h"
14 #include "plugin.h"
15 #include "item.h"
16 #include "window.h"
17 #include "graphics_win32.h"
18 #include "xpm2bmp.h"
19 #include "support/win32/ConvertUTF.h"
20 #include "profile.h"
21 #include "keys.h"
22
23 #ifdef HAVE_API_WIN32_CE
24 #include "libc.h"
25 #endif
26
27 //#define FAST_TRANSPARENCY 1
28
29 #if defined(_WIN32_WCE) && _WIN32_WCE < 0x500 && !defined(__MINGW32CE__)
30
31 typedef struct {
32                 int BlendOp;
33                 int BlendFlags;
34                 int SourceConstantAlpha;
35                 int AlphaFormat;
36 } BLENDFUNCTION;
37
38 #define AC_SRC_OVER 1
39 #define AC_SRC_ALPHA 2
40 #endif
41
42 typedef BOOL (WINAPI *FP_AlphaBlend) ( HDC hdcDest,
43                                        int nXOriginDest,
44                                        int nYOriginDest,
45                                        int nWidthDest,
46                                        int nHeightDest,
47                                        HDC hdcSrc,
48                                        int nXOriginSrc,
49                                        int nYOriginSrc,
50                                        int nWidthSrc,
51                                        int nHeightSrc,
52                                        BLENDFUNCTION blendFunction
53                                      );
54
55 struct graphics_priv
56 {
57     struct navit *nav;
58     struct window window;
59     struct point p;
60     int width;
61     int height;
62     int disabled;
63     HANDLE wnd_parent_handle;
64     HANDLE wnd_handle;
65     COLORREF bg_color;
66     struct callback_list *cbl;
67     enum draw_mode_num mode;
68     struct graphics_priv* parent;
69     struct graphics_priv *overlays;
70     struct graphics_priv *next;
71     struct color transparent_color;
72     DWORD* pPixelData;
73     HDC hMemDC;
74     HDC hPrebuildDC;
75     HBITMAP hBitmap;
76     HBITMAP hPrebuildBitmap;
77     HBITMAP hOldBitmap;
78     HBITMAP hOldPrebuildBitmap;
79     FP_AlphaBlend AlphaBlend;
80     HANDLE hCoreDll;
81     GHashTable *image_cache_hash;
82 };
83
84 struct window_priv
85 {
86     HANDLE hBackLight;
87 };
88
89 static HWND g_hwnd = NULL;
90
91 #ifdef HAVE_API_WIN32_CE
92 static int fullscr = 0;
93 #endif
94
95
96 #ifndef GET_WHEEL_DELTA_WPARAM
97 #define GET_WHEEL_DELTA_WPARAM(wParam)  ((short)HIWORD(wParam))
98 #endif
99
100
101 HFONT EzCreateFont (HDC hdc, TCHAR * szFaceName, int iDeciPtHeight,
102                     int iDeciPtWidth, int iAttributes, BOOL fLogRes) ;
103
104 #define EZ_ATTR_BOLD          1
105 #define EZ_ATTR_ITALIC        2
106 #define EZ_ATTR_UNDERLINE     4
107 #define EZ_ATTR_STRIKEOUT     8
108
109 HFONT EzCreateFont (HDC hdc, TCHAR * szFaceName, int iDeciPtHeight,
110                     int iDeciPtWidth, int iAttributes, BOOL fLogRes)
111 {
112     FLOAT      cxDpi, cyDpi ;
113     HFONT      hFont ;
114     LOGFONT    lf ;
115     POINT      pt ;
116     TEXTMETRIC tm ;
117
118     SaveDC (hdc) ;
119
120 #ifndef HAVE_API_WIN32_CE
121     SetGraphicsMode (hdc, GM_ADVANCED) ;
122     ModifyWorldTransform (hdc, NULL, MWT_IDENTITY) ;
123 #endif
124     SetViewportOrgEx (hdc, 0, 0, NULL) ;
125 #ifndef HAVE_API_WIN32_CE
126     SetWindowOrgEx   (hdc, 0, 0, NULL) ;
127 #endif
128
129     if (fLogRes)
130     {
131         cxDpi = (FLOAT) GetDeviceCaps (hdc, LOGPIXELSX) ;
132         cyDpi = (FLOAT) GetDeviceCaps (hdc, LOGPIXELSY) ;
133     }
134     else
135     {
136         cxDpi = (FLOAT) (25.4 * GetDeviceCaps (hdc, HORZRES) /
137                          GetDeviceCaps (hdc, HORZSIZE)) ;
138
139         cyDpi = (FLOAT) (25.4 * GetDeviceCaps (hdc, VERTRES) /
140                          GetDeviceCaps (hdc, VERTSIZE)) ;
141     }
142
143     pt.x = (int) (iDeciPtWidth  * cxDpi / 72) ;
144     pt.y = (int) (iDeciPtHeight * cyDpi / 72) ;
145
146 #ifndef HAVE_API_WIN32_CE
147     DPtoLP (hdc, &pt, 1) ;
148 #endif
149     lf.lfHeight         = - (int) (fabs (pt.y) / 10.0 + 0.5) ;
150     lf.lfWidth          = 0 ;
151     lf.lfEscapement     = 0 ;
152     lf.lfOrientation    = 0 ;
153     lf.lfWeight         = iAttributes & EZ_ATTR_BOLD      ? 700 : 0 ;
154     lf.lfItalic         = iAttributes & EZ_ATTR_ITALIC    ?   1 : 0 ;
155     lf.lfUnderline      = iAttributes & EZ_ATTR_UNDERLINE ?   1 : 0 ;
156     lf.lfStrikeOut      = iAttributes & EZ_ATTR_STRIKEOUT ?   1 : 0 ;
157     lf.lfCharSet        = DEFAULT_CHARSET ;
158     lf.lfOutPrecision   = 0 ;
159     lf.lfClipPrecision  = 0 ;
160     lf.lfQuality        = 0 ;
161     lf.lfPitchAndFamily = 0 ;
162
163     lstrcpy (lf.lfFaceName, szFaceName) ;
164
165     hFont = CreateFontIndirect (&lf) ;
166
167     if (iDeciPtWidth != 0)
168     {
169         hFont = (HFONT) SelectObject (hdc, hFont) ;
170
171         GetTextMetrics (hdc, &tm) ;
172
173         DeleteObject (SelectObject (hdc, hFont)) ;
174
175         lf.lfWidth = (int) (tm.tmAveCharWidth *
176                             fabs (pt.x) / fabs (pt.y) + 0.5) ;
177
178         hFont = CreateFontIndirect (&lf) ;
179     }
180
181     RestoreDC (hdc, -1) ;
182     return hFont ;
183 }
184
185 struct graphics_image_priv
186 {
187     PXPM2BMP pxpm;
188         int width,height,row_bytes,channels;
189     unsigned char *png_pixels;
190     HBITMAP hBitmap;
191     struct point hot;
192 };
193
194
195 static void ErrorExit(LPTSTR lpszFunction)
196 {
197     // Retrieve the system error message for the last-error code
198
199         LPVOID lpMsgBuf;
200     LPVOID lpDisplayBuf;
201     DWORD dw = GetLastError();
202
203     FormatMessage(
204         FORMAT_MESSAGE_ALLOCATE_BUFFER |
205         FORMAT_MESSAGE_FROM_SYSTEM |
206         FORMAT_MESSAGE_IGNORE_INSERTS,
207         NULL,
208         dw,
209         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
210         (LPTSTR) &lpMsgBuf,
211         0, NULL );
212
213     lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
214                                       (lstrlen((LPCTSTR)lpMsgBuf)+lstrlen((LPCTSTR)lpszFunction)+40)*sizeof(TCHAR));
215     _tprintf((LPTSTR)lpDisplayBuf, TEXT("%s failed with error %d: %s"), lpszFunction, dw, lpMsgBuf);
216
217     dbg(0, "%s failed with error %d: %s", lpszFunction, dw, lpMsgBuf);
218     MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK);
219
220     LocalFree(lpMsgBuf);
221     LocalFree(lpDisplayBuf);
222     ExitProcess(dw);
223 }
224
225
226
227 struct graphics_gc_priv
228 {
229     HWND        hwnd;
230     int         line_width;
231     COLORREF    fg_color;
232     int         fg_alpha;
233     COLORREF    bg_color;
234     HPEN hpen;
235     HBRUSH hbrush;
236     struct graphics_priv *gr;
237 };
238
239
240 static void create_memory_dc(struct graphics_priv *gr)
241 {
242     HDC hdc;
243     BITMAPINFO bOverlayInfo;
244
245     if (gr->hMemDC)
246     {
247         (void)SelectBitmap(gr->hMemDC, gr->hOldBitmap);
248         DeleteBitmap(gr->hBitmap);
249         DeleteDC(gr->hMemDC);
250
251         (void)SelectBitmap(gr->hPrebuildDC, gr->hOldPrebuildBitmap);
252         DeleteBitmap(gr->hPrebuildBitmap);
253         DeleteDC(gr->hPrebuildDC);
254         gr->hPrebuildDC = 0;
255     }
256
257
258     hdc = GetDC( gr->wnd_handle );
259     // Creates memory DC
260     gr->hMemDC = CreateCompatibleDC(hdc);
261     dbg(0, "resize memDC to: %d %d \n", gr->width, gr->height );
262
263
264 #ifndef  FAST_TRANSPARENCY
265
266     memset(&bOverlayInfo, 0, sizeof(BITMAPINFO));
267     bOverlayInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
268     bOverlayInfo.bmiHeader.biWidth = gr->width;
269     bOverlayInfo.bmiHeader.biHeight = -gr->height;
270     bOverlayInfo.bmiHeader.biBitCount = 32;
271     bOverlayInfo.bmiHeader.biCompression = BI_RGB;
272     bOverlayInfo.bmiHeader.biPlanes = 1;
273     gr->hPrebuildDC = CreateCompatibleDC(NULL);
274     gr->hPrebuildBitmap = CreateDIBSection(gr->hMemDC, &bOverlayInfo, DIB_RGB_COLORS , (void **)&gr->pPixelData, NULL, 0);
275     gr->hOldPrebuildBitmap = SelectBitmap(gr->hPrebuildDC, gr->hPrebuildBitmap);
276
277 #endif
278     gr->hBitmap = CreateCompatibleBitmap(hdc, gr->width, gr->height );
279
280     if ( gr->hBitmap )
281     {
282         gr->hOldBitmap = SelectBitmap( gr->hMemDC, gr->hBitmap);
283     }
284     ReleaseDC( gr->wnd_handle, hdc );
285 }
286
287 static void HandleButtonClick( struct graphics_priv *gra_priv, int updown, int button, long lParam )
288 {
289     struct point pt = { LOWORD(lParam), HIWORD(lParam) };
290     callback_list_call_attr_3(gra_priv->cbl, attr_button, (void *)updown, (void *)button, (void *)&pt);
291 }
292
293 static void HandleKeyChar(struct graphics_priv *gra_priv, WPARAM wParam)
294 {
295     TCHAR key = (TCHAR) wParam;
296     char *s=NULL;
297     char k[]={0,0};
298     dbg(1,"HandleKey %d\n",key);
299         switch (key) {
300     default:
301                 k[0]=key;
302                 s=k;
303         break;
304     }
305     if (s) 
306         callback_list_call_attr_1(gra_priv->cbl, attr_keypress, (void *)s);
307 }
308
309 static void HandleKeyDown(struct graphics_priv *gra_priv, WPARAM wParam)
310 {
311     int key = (int) wParam;
312     char up[]={NAVIT_KEY_UP,0};
313     char down[]={NAVIT_KEY_DOWN,0};
314     char left[]={NAVIT_KEY_LEFT,0};
315     char right[]={NAVIT_KEY_RIGHT,0};
316     char *s=NULL;
317     dbg(1,"HandleKey %d\n",key);
318         switch (key) {
319     case 37:
320                 s=left;
321         break;
322     case 38:
323                 s=up;
324         break;
325     case 39:
326                 s=right;
327         break;
328     case 40:
329                 s=down;
330         break;
331     }
332     if (s) 
333         callback_list_call_attr_1(gra_priv->cbl, attr_keypress, (void *)s);
334 }
335
336
337 static LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
338 {
339
340     struct graphics_priv* gra_priv = (struct graphics_priv*)GetWindowLongPtr( hwnd , DWLP_USER );
341
342     switch (Message)
343     {
344     case WM_CREATE:
345     {
346         if ( gra_priv )
347         {
348             RECT rc ;
349
350             GetClientRect( hwnd, &rc );
351             gra_priv->width = rc.right;
352             gra_priv->height = rc.bottom;
353             create_memory_dc(gra_priv);
354         }
355     }
356     break;
357     case WM_COMMAND:
358         switch (LOWORD(wParam))
359         {
360         case WM_USER + 1:
361             break;
362         }
363         break;
364     case WM_CLOSE:
365         DestroyWindow(hwnd);
366         break;
367     case WM_USER+1:
368         if ( gra_priv )
369         {
370             RECT rc ;
371
372             GetClientRect( hwnd, &rc );
373             gra_priv->width = rc.right;
374             gra_priv->height = rc.bottom;
375
376             create_memory_dc(gra_priv);
377             callback_list_call_attr_2(gra_priv->cbl, attr_resize, (void *)gra_priv->width, (void *)gra_priv->height);
378         }
379         break;
380     case WM_USER+2:
381     {
382         struct callback_list *cbl = (struct callback_list*)wParam;
383 #ifdef HAVE_API_WIN32_CE
384         /* FIXME: Reset the idle timer  need a better place */
385         SystemIdleTimerReset();
386 #endif
387         callback_list_call_0(cbl);
388     }
389     break;
390
391     case WM_SIZE:
392         if ( gra_priv )
393         {
394             gra_priv->width = LOWORD( lParam );
395             gra_priv->height  = HIWORD( lParam );
396             create_memory_dc(gra_priv);
397             dbg(0, "resize gfx to: %d %d \n", gra_priv->width, gra_priv->height );
398             callback_list_call_attr_2(gra_priv->cbl, attr_resize, (void *)gra_priv->width, (void *)gra_priv->height);
399         }
400         break;
401     case WM_DESTROY:
402 #ifdef HAVE_API_WIN32_CE
403         if ( gra_priv && gra_priv->window.priv )
404         {
405             struct window_priv *win_priv = gra_priv->window.priv;
406             if (win_priv->hBackLight)
407             {
408                 ReleasePowerRequirement(win_priv->hBackLight);
409             }
410         }
411 #endif
412         PostQuitMessage(0);
413         break;
414     case WM_PAINT:
415         if ( gra_priv && gra_priv->hMemDC)
416         {
417             struct graphics_priv* overlay;
418             PAINTSTRUCT ps = { 0 };
419             HDC hdc;
420             profile(0, NULL);
421             dbg(1, "WM_PAINT\n");
422             overlay = gra_priv->overlays;
423
424 #ifndef FAST_TRANSPARENCY
425                         BitBlt( gra_priv->hPrebuildDC, 0, 0, gra_priv->width , gra_priv->height, gra_priv->hMemDC, 0, 0, SRCCOPY);
426 #endif
427                         while ( !gra_priv->disabled && overlay)
428                         {
429                                 if ( !overlay->disabled && overlay->p.x >= 0 &&
430                                          overlay->p.y >= 0 &&
431                                          overlay->p.x < gra_priv->width &&
432                                          overlay->p.y < gra_priv->height )
433                                 {
434                                         int x,y;
435                                         int destPixel, srcPixel;
436                     int h,w;
437 #ifdef FAST_TRANSPARENCY
438                                         if ( !overlay->hPrebuildDC )
439                                         {
440                                                 overlay->hPrebuildBitmap = CreateBitmap(overlay->width,overlay->height,1,1,NULL);
441                                                 overlay->hPrebuildDC = CreateCompatibleDC(NULL);
442                                                 overlay->hOldPrebuildBitmap = SelectBitmap( overlay->hPrebuildDC, overlay->hPrebuildBitmap);
443                                                 SetBkColor(overlay->hMemDC,RGB(overlay->transparent_color.r >> 8,overlay->transparent_color.g >> 8,overlay->transparent_color.b >> 8));
444                                                 BitBlt(overlay->hPrebuildDC,0,0,overlay->width,overlay->height,overlay->hMemDC,0,0,SRCCOPY);
445                                                 BitBlt(overlay->hMemDC,0,0,overlay->width,overlay->height,overlay->hPrebuildDC,0,0,SRCINVERT);
446                                         }
447
448 #else
449                                         const COLORREF transparent_color = RGB(overlay->transparent_color.r >> 8,overlay->transparent_color.g >> 8,overlay->transparent_color.b >> 8);
450
451                                         BitBlt( overlay->hPrebuildDC, 0, 0, overlay->width , overlay->height, overlay->hMemDC, 0, 0, SRCCOPY);
452
453                                         h=overlay->height;
454                                         w=overlay->width;
455                                         if (w > gra_priv->width-overlay->p.x)
456                                                 w=gra_priv->width-overlay->p.x;
457                                         if (h > gra_priv->height-overlay->p.y)
458                                                 h=gra_priv->height-overlay->p.y;
459                                         for ( y = 0; y < h ;y++ )
460                                         {
461                                                 for ( x = 0; x < w; x++ )
462                                                 {
463                                                         srcPixel = y*overlay->width+x;
464                                                         destPixel = ((overlay->p.y + y) * gra_priv->width) + (overlay->p.x + x);
465                                                         if ( overlay->pPixelData[srcPixel] == transparent_color )
466                                                         {
467                                                                 destPixel = ((overlay->p.y + y) * gra_priv->width) + (overlay->p.x + x);
468
469                                                                 gra_priv->pPixelData[destPixel] = RGB ( ((65535 - overlay->transparent_color.a) * GetRValue(gra_priv->pPixelData[destPixel]) + overlay->transparent_color.a * GetRValue(overlay->pPixelData[srcPixel])) / 65535,
470                                                                                                                                 ((65535 - overlay->transparent_color.a) * GetGValue(gra_priv->pPixelData[destPixel]) + overlay->transparent_color.a * GetGValue(overlay->pPixelData[srcPixel])) / 65535,
471                                                                                                                                 ((65535 - overlay->transparent_color.a) * GetBValue(gra_priv->pPixelData[destPixel]) + overlay->transparent_color.a * GetBValue(overlay->pPixelData[srcPixel])) / 65535);
472
473                                                         }
474                                                         else
475                                                         {
476                                                                 gra_priv->pPixelData[destPixel] = overlay->pPixelData[srcPixel];
477                                                         }
478                                                 }
479
480                                         }
481 #endif
482                                 }
483                                 overlay = overlay->next;
484                         }
485
486
487 #ifndef FAST_TRANSPARENCY
488             hdc = BeginPaint(hwnd, &ps);
489             BitBlt( hdc, 0, 0, gra_priv->width , gra_priv->height, gra_priv->hPrebuildDC, 0, 0, SRCCOPY );
490 #else
491             HDC hdc = BeginPaint(hwnd, &ps);
492
493             BitBlt( hdc, 0, 0, gra_priv->width , gra_priv->height, gra_priv->hMemDC, 0, 0, SRCCOPY );
494
495             overlay = gra_priv->overlays;
496             while ( !gra_priv->disabled && overlay && !overlay->disabled )
497             {
498                 if ( overlay->p.x > 0 &&
499                         overlay->p.y > 0 &&
500                         overlay->p.x + overlay->width < gra_priv->width &&
501                         overlay->p.y + overlay->height < gra_priv->height )
502                 {
503                     BitBlt(hdc,overlay->p.x,overlay->p.y,overlay->width,overlay->height,overlay->hPrebuildDC,0,0,SRCAND);
504                     BitBlt(hdc,overlay->p.x,overlay->p.y,overlay->width,overlay->height,overlay->hMemDC,0,0,SRCPAINT);
505                 }
506                 overlay = overlay->next;
507             }
508 #endif
509             EndPaint(hwnd, &ps);
510             profile(0, "WM_PAINT\n");
511         }
512         break;
513     case WM_MOUSEMOVE:
514     {
515         struct point pt = { LOWORD(lParam), HIWORD(lParam) };
516         callback_list_call_attr_1(gra_priv->cbl, attr_motion, (void *)&pt);
517     }
518     break;
519
520     case WM_LBUTTONDOWN:
521     {
522         dbg(1, "LBUTTONDOWN\n");
523         HandleButtonClick( gra_priv, 1, 1, lParam);
524     }
525     break;
526     case WM_LBUTTONUP:
527     {
528         dbg(1, "LBUTTONUP\n");
529         HandleButtonClick( gra_priv, 0, 1, lParam);
530     }
531     break;
532     case WM_RBUTTONDOWN:
533         HandleButtonClick( gra_priv, 1, 3,lParam );
534         break;
535     case WM_RBUTTONUP:
536         HandleButtonClick( gra_priv, 0, 3,lParam );
537         break;
538     case WM_LBUTTONDBLCLK:
539         dbg(1, "LBUTTONDBLCLK\n");
540         HandleButtonClick( gra_priv, 1, 6,lParam );
541         break;
542     case WM_CHAR:
543         HandleKeyChar( gra_priv, wParam);
544         break;
545     case WM_KEYDOWN:
546         HandleKeyDown( gra_priv, wParam);
547         break;
548 #ifdef HAVE_API_WIN32_CE
549     case WM_SETFOCUS:
550         if (fullscr) {
551            HWND hwndSip = FindWindow(L"MS_SIPBUTTON", NULL);
552            // deactivate the SIP button
553            ShowWindow(hwndSip, SW_HIDE);
554         }
555         break;
556    case WM_KILLFOCUS:
557         if (fullscr != 1) {
558            HWND hwndSip = FindWindow(L"MS_SIPBUTTON", NULL);
559            // active the SIP button
560            ShowWindow(hwndSip, SW_SHOW);
561         }
562         break;
563 #endif
564     default:
565         return DefWindowProc(hwnd, Message, wParam, lParam);
566     }
567     return 0;
568 }
569
570 static int fullscreen(struct window *win, int on)
571 {
572
573 #ifdef HAVE_API_WIN32_CE
574     HWND hwndTaskbar = FindWindow(L"HHTaskBar", NULL);
575     HWND hwndSip = FindWindow(L"MS_SIPBUTTON", NULL);
576     RECT taskbar_rect;
577     fullscr = on;
578         if (on) {
579         ShowWindow(hwndTaskbar, SW_HIDE);
580         MoveWindow(g_hwnd, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), FALSE);
581         
582         // deactivate the SIP button
583         ShowWindow(hwndSip, SW_HIDE);
584         
585         } else {
586         ShowWindow(hwndTaskbar, SW_SHOW);
587         GetWindowRect(  hwndTaskbar, &taskbar_rect);
588         MoveWindow(g_hwnd, 0, taskbar_rect.bottom, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN) - taskbar_rect.bottom, FALSE);
589     
590         // activate the SIP button
591         ShowWindow(hwndSip, SW_SHOW);
592     }
593
594 #else
595         if (on) {
596         ShowWindow(g_hwnd, SW_MAXIMIZE);
597         } else {
598         ShowWindow(g_hwnd, SW_RESTORE);
599     }
600
601 #endif
602
603     return 0;
604 }
605
606 extern void WINAPI SystemIdleTimerReset(void);
607 static struct event_timeout *
608             event_win32_add_timeout(int timeout, int multi, struct callback *cb);
609
610 static void disable_suspend(struct window *win)
611 {
612 #ifdef HAVE_API_WIN32_CE
613     struct window_priv *win_priv = win->priv;
614     if ( win_priv && !win_priv->hBackLight )
615     {
616         win_priv->hBackLight = SetPowerRequirement(TEXT("BKL1:"), 0, 0x01, NULL, 0);
617         event_win32_add_timeout(29000, 1, callback_new(SystemIdleTimerReset, 0, NULL));
618     }
619
620     SystemIdleTimerReset();
621 #endif
622 }
623
624 static const TCHAR g_szClassName[] = {'N','A','V','G','R','A','\0'};
625
626 static HANDLE CreateGraphicsWindows( struct graphics_priv* gr, HMENU hMenu )
627 {
628     int wStyle = WS_VISIBLE;
629     HWND hwnd;
630 #ifdef HAVE_API_WIN32_CE
631     WNDCLASS wc;
632 #else
633     WNDCLASSEX wc;
634     wc.cbSize            = sizeof(WNDCLASSEX);
635     wc.hIconSm           = NULL;
636 #endif
637
638     wc.style     = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
639     wc.lpfnWndProc      = WndProc;
640     wc.cbClsExtra       = 0;
641     wc.cbWndExtra       = 64;
642     wc.hInstance        = GetModuleHandle(NULL);
643     wc.hIcon    = NULL;
644     wc.hCursor  = LoadCursor(NULL, IDC_ARROW);
645     wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
646     wc.lpszMenuName  = NULL;
647     wc.lpszClassName = g_szClassName;
648
649
650 #ifdef HAVE_API_WIN32_CE
651     gr->width = GetSystemMetrics(SM_CXSCREEN);
652     gr->height = GetSystemMetrics(SM_CYSCREEN);
653
654 #if 0
655     HWND hwndTaskbar = FindWindow(L"HHTaskBar", NULL);
656     RECT taskbar_rect;
657     GetWindowRect(  hwndTaskbar, &taskbar_rect);
658
659     gr->height -= taskbar_rect.bottom;
660 #endif
661
662
663
664 #endif
665
666 #ifdef HAVE_API_WIN32_CE
667     if (!RegisterClass(&wc))
668 #else
669     if (!RegisterClassEx(&wc))
670 #endif
671     {
672         dbg(0, "Window registration failed\n");
673         return NULL;
674     }
675
676     if ( hMenu )
677     {
678         wStyle = WS_CHILD;
679         } else {
680         wStyle = WS_OVERLAPPED|WS_VISIBLE;
681     }
682
683 #ifdef HAVE_API_WIN32_CE
684     g_hwnd = hwnd = CreateWindow(g_szClassName,
685                                  TEXT("Navit"),
686                                  wStyle,
687                                  CW_USEDEFAULT,
688                                  CW_USEDEFAULT,
689                                  CW_USEDEFAULT,
690                                  CW_USEDEFAULT,
691                                  gr->wnd_parent_handle,
692                                  hMenu,
693                                  GetModuleHandle(NULL),
694                                  NULL);
695 #else
696     g_hwnd = hwnd = CreateWindow(g_szClassName,
697                                  TEXT("Navit"),
698                                  wStyle,
699                                  0,
700                                  0,
701                                  gr->width,
702                                  gr->height,
703                                  gr->wnd_parent_handle,
704                                  hMenu,
705                                  GetModuleHandle(NULL),
706                                  NULL);
707 #endif
708     if (hwnd == NULL)
709     {
710         dbg(0, "Window creation failed: %d\n",  GetLastError());
711         return NULL;
712     }
713     gr->wnd_handle = hwnd;
714
715     callback_list_call_attr_2(gr->cbl, attr_resize, (void *)gr->width, (void *)gr->height);
716     create_memory_dc(gr);
717
718     SetWindowLongPtr( hwnd , DWLP_USER, (LONG_PTR)gr );
719
720     ShowWindow( hwnd, SW_SHOW );
721     UpdateWindow( hwnd );
722
723     PostMessage( gr->wnd_parent_handle, WM_USER + 1, 0, 0 );
724
725     return hwnd;
726 }
727
728
729
730 static void graphics_destroy(struct graphics_priv *gr)
731 {
732     g_free( gr );
733 }
734
735
736 static void gc_destroy(struct graphics_gc_priv *gc)
737 {
738     DeleteObject( gc->hpen );
739     DeleteObject( gc->hbrush );
740     g_free( gc );
741 }
742
743 static void gc_set_linewidth(struct graphics_gc_priv *gc, int w)
744 {
745     DeleteObject (gc->hpen);
746     gc->line_width = w;
747     gc->hpen = CreatePen( PS_SOLID, gc->line_width, gc->fg_color );
748 }
749
750 static void gc_set_dashes(struct graphics_gc_priv *gc, int width, int offset, unsigned char dash_list[], int n)
751 {
752 //      gdk_gc_set_dashes(gc->gc, 0, (gint8 *)dash_list, n);
753 //      gdk_gc_set_line_attributes(gc->gc, 1, GDK_LINE_ON_OFF_DASH, GDK_CAP_ROUND, GDK_JOIN_ROUND);
754 }
755
756
757 static void gc_set_foreground(struct graphics_gc_priv *gc, struct color *c)
758 {
759     gc->fg_color = RGB( c->r >> 8, c->g >> 8, c->b >> 8);
760     gc->fg_alpha = c->a;
761
762     DeleteObject (gc->hpen);
763     DeleteObject (gc->hbrush);
764     gc->hpen = CreatePen( PS_SOLID, gc->line_width, gc->fg_color );
765     gc->hbrush = CreateSolidBrush( gc->fg_color );
766         if ( gc->gr && c->a < 0xFFFF )
767     {
768             gc->gr->transparent_color = *c;
769     }
770
771 }
772
773 static void gc_set_background(struct graphics_gc_priv *gc, struct color *c)
774 {
775     gc->bg_color = RGB( c->r >> 8, c->g >> 8, c->b >> 8);
776     if ( gc->gr && gc->gr->hMemDC )
777         SetBkColor( gc->gr->hMemDC, gc->bg_color );
778
779 }
780
781 static struct graphics_gc_methods gc_methods =
782 {
783     gc_destroy,
784     gc_set_linewidth,
785     gc_set_dashes,
786     gc_set_foreground,
787     gc_set_background,
788     NULL, //gc_set_stipple
789 };
790
791 static struct graphics_gc_priv *gc_new(struct graphics_priv *gr, struct graphics_gc_methods *meth)
792 {
793     struct graphics_gc_priv *gc=g_new(struct graphics_gc_priv, 1);
794     *meth=gc_methods;
795     gc->hwnd = gr->wnd_handle;
796     gc->line_width = 1;
797     gc->fg_color = RGB( 0,0,0 );
798     gc->bg_color = RGB( 255,255,255 );
799     gc->hpen = CreatePen( PS_SOLID, gc->line_width, gc->fg_color );
800     gc->hbrush = CreateSolidBrush( gc->fg_color );
801     gc->gr = gr;
802     return gc;
803 }
804
805
806 static void draw_lines(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int count)
807 {
808     int i;
809
810     HPEN hpenold = SelectObject( gr->hMemDC, gc->hpen );
811
812     int first = 1;
813     for ( i = 0; i< count; i++ )
814     {
815         if ( first )
816         {
817             first = 0;
818             MoveToEx( gr->hMemDC, p[0].x, p[0].y, NULL );
819         }
820         else
821         {
822             LineTo( gr->hMemDC, p[i].x, p[i].y );
823         }
824     }
825
826     SelectObject( gr->hMemDC, hpenold);
827 }
828
829 static void draw_polygon(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int count)
830 {
831     HPEN holdpen = SelectObject( gr->hMemDC, gc->hpen );
832     HBRUSH holdbrush = SelectObject( gr->hMemDC, gc->hbrush );
833     if (sizeof(POINT) != sizeof(struct point)) {
834             int i;
835             POINT* points=g_alloca(sizeof(POINT)*count);
836             for ( i=0;i< count; i++ )
837             {
838                 points[i].x = p[i].x;
839                 points[i].y = p[i].y;
840             }
841             Polygon( gr->hMemDC, points,count );
842     } else
843             Polygon( gr->hMemDC, (POINT *)p, count);
844     SelectObject( gr->hMemDC, holdbrush);
845     SelectObject( gr->hMemDC, holdpen);
846 }
847
848
849 static void draw_rectangle(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int w, int h)
850 {
851     HPEN holdpen = SelectObject( gr->hMemDC, gc->hpen );
852     HBRUSH holdbrush = SelectObject( gr->hMemDC, gc->hbrush );
853
854     Rectangle(gr->hMemDC, p->x, p->y, p->x+w, p->y+h);
855
856     SelectObject( gr->hMemDC, holdbrush);
857     SelectObject( gr->hMemDC, holdpen);
858 }
859
860 static void draw_circle(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int r)
861 {
862     HPEN holdpen = SelectObject( gr->hMemDC, gc->hpen );
863     HBRUSH holdbrush = SelectObject( gr->hMemDC, GetStockObject(NULL_BRUSH));
864
865     r=r/2;
866
867     Ellipse( gr->hMemDC, p->x - r, p->y -r, p->x + r, p->y + r );
868
869     SelectObject( gr->hMemDC, holdbrush);
870     SelectObject( gr->hMemDC, holdpen);
871 }
872
873
874
875 static void draw_restore(struct graphics_priv *gr, struct point *p, int w, int h)
876 {
877     InvalidateRect( gr->wnd_handle, NULL, FALSE );
878 }
879
880 static void draw_drag(struct graphics_priv *gr, struct point *p)
881 {
882     if ( p )
883     {
884         gr->p.x    = p->x;
885         gr->p.y    = p->y;
886
887         if ( p->x < 0 || p->y < 0 ||
888                 ( gr->parent && ((p->x + gr->width > gr->parent->width) || (p->y + gr->height > gr->parent->height) )))
889         {
890             gr->disabled = TRUE;
891         }
892         else
893         {
894             gr->disabled = FALSE;
895         }
896     }
897 }
898
899 static void draw_mode(struct graphics_priv *gr, enum draw_mode_num mode)
900 {
901     dbg( 1, "set draw_mode to %x, %d\n", gr, (int)mode );
902
903     if ( mode == draw_mode_begin )
904     {
905         if ( gr->wnd_handle == NULL )
906         {
907             CreateGraphicsWindows( gr, (HMENU)ID_CHILD_GFX );
908         }
909         if ( gr->mode != draw_mode_begin )
910         {
911             if ( gr->hMemDC )
912             {
913                 dbg(1, "Erase dc: %x, w: %d, h: %d, bg_color: %x\n", gr, gr->width, gr->height, gr->bg_color);
914 #ifdef  FAST_TRANSPARENCY
915                 if ( gr->hPrebuildDC )
916                 {
917                     (void)SelectBitmap(gr->hPrebuildDC, gr->hOldPrebuildBitmap );
918                     DeleteBitmap(gr->hPrebuildBitmap);
919                     DeleteDC(gr->hPrebuildDC);
920                     gr->hPrebuildDC = 0;
921                 }
922 #endif
923             }
924         }
925 #ifdef  FAST_TRANSPARENCY
926         else if ( gr->hPrebuildDC )
927         {
928             (void)SelectBitmap(gr->hPrebuildDC, gr->hOldPrebuildBitmap );
929             DeleteBitmap(gr->hPrebuildBitmap);
930             DeleteDC(gr->hPrebuildDC);
931             gr->hPrebuildDC = 0;
932         }
933 #endif
934     }
935
936     // force paint
937     if (mode == draw_mode_end && gr->mode == draw_mode_begin)
938     {
939         InvalidateRect( gr->wnd_handle, NULL, FALSE );
940     }
941
942     gr->mode=mode;
943
944 }
945
946
947 static void * get_data(struct graphics_priv *this_, char *type)
948 {
949     if ( strcmp( "wnd_parent_handle_ptr", type ) == 0 )
950     {
951         return &( this_->wnd_parent_handle );
952     }
953     if ( strcmp( "START_CLIENT", type ) == 0 )
954     {
955         CreateGraphicsWindows( this_, (HMENU)ID_CHILD_GFX );
956         return NULL;
957     }
958     if (!strcmp(type, "window"))
959     {
960         CreateGraphicsWindows( this_ , NULL);
961
962         this_->window.fullscreen = fullscreen;
963         this_->window.disable_suspend = disable_suspend;
964
965         this_->window.priv=g_new0(struct window_priv, 1);
966
967         return &this_->window;
968     }
969     return NULL;
970 }
971
972
973 static void background_gc(struct graphics_priv *gr, struct graphics_gc_priv *gc)
974 {
975     RECT rcClient = { 0, 0, gr->width, gr->height };
976     HBRUSH bgBrush;
977
978     bgBrush = CreateSolidBrush( gc->bg_color  );
979     gr->bg_color = gc->bg_color;
980
981     FillRect( gr->hMemDC, &rcClient, bgBrush );
982     DeleteObject( bgBrush );
983 }
984
985 struct graphics_font_priv
986 {
987     LOGFONT lf;
988     HFONT hfont;
989     int size;
990 };
991
992 static void draw_text(struct graphics_priv *gr, struct graphics_gc_priv *fg, struct graphics_gc_priv *bg, struct graphics_font_priv *font, char *text, struct point *p, int dx, int dy)
993 {
994     RECT rcClient;
995     int prevBkMode;
996     HFONT hOldFont;
997     double angle;
998
999     GetClientRect( gr->wnd_handle, &rcClient );
1000
1001     SetTextColor(gr->hMemDC, fg->fg_color);
1002     prevBkMode = SetBkMode( gr->hMemDC, TRANSPARENT );
1003
1004     if ( NULL == font->hfont )
1005     {
1006 #ifdef WIN_USE_SYSFONT
1007         font->hfont = (HFONT) GetStockObject (SYSTEM_FONT);
1008         GetObject (font->hfont, sizeof (LOGFONT), &font->lf);
1009 #else
1010         font->hfont = EzCreateFont (gr->hMemDC, TEXT ("Arial"), font->size/2, 0, 0, TRUE);
1011         GetObject ( font->hfont, sizeof (LOGFONT), &font->lf) ;
1012 #endif
1013     }
1014
1015
1016     angle = -atan2( dy, dx ) * 180 / 3.14159 ;
1017     if (angle < 0)
1018         angle += 360;
1019
1020     SetTextAlign (gr->hMemDC, TA_BASELINE) ;
1021     SetViewportOrgEx (gr->hMemDC, p->x, p->y, NULL) ;
1022     font->lf.lfEscapement = font->lf.lfOrientation = ( angle * 10 ) ;
1023     DeleteObject (font->hfont) ;
1024
1025     font->hfont = CreateFontIndirect (&font->lf);
1026     hOldFont = SelectObject(gr->hMemDC, font->hfont );
1027
1028     {
1029         wchar_t utf16[1024];
1030         const UTF8 *utf8 = (UTF8 *)text;
1031         UTF16 *utf16p = (UTF16 *) utf16;
1032         SetBkMode (gr->hMemDC, TRANSPARENT);
1033         if (ConvertUTF8toUTF16(&utf8, utf8+strlen(text),
1034                                &utf16p, utf16p+sizeof(utf16),
1035                                lenientConversion) == conversionOK)
1036         {
1037             ExtTextOutW(gr->hMemDC, 0, 0, 0, NULL,
1038                         utf16, (wchar_t*) utf16p - utf16, NULL);
1039         }
1040     }
1041
1042
1043     SelectObject(gr->hMemDC, hOldFont);
1044     DeleteObject (font->hfont) ;
1045
1046     SetBkMode( gr->hMemDC, prevBkMode );
1047
1048     SetViewportOrgEx (gr->hMemDC, 0, 0, NULL) ;
1049 }
1050
1051 static void font_destroy(struct graphics_font_priv *font)
1052 {
1053     if ( font->hfont )
1054     {
1055         DeleteObject(font->hfont);
1056     }
1057     g_free(font);
1058 }
1059
1060 static struct graphics_font_methods font_methods =
1061 {
1062     font_destroy
1063 };
1064
1065 static struct graphics_font_priv *font_new(struct graphics_priv *gr, struct graphics_font_methods *meth, char *name, int size, int flags)
1066 {
1067     struct graphics_font_priv *font=g_new(struct graphics_font_priv, 1);
1068     *meth = font_methods;
1069
1070     font->hfont = NULL;
1071     font->size = size;
1072
1073     return font;
1074 }
1075
1076 #include "png.h"
1077
1078 static int
1079 pngdecode(struct graphics_priv *gr, char *name, struct graphics_image_priv *img)
1080 {
1081     png_struct    *png_ptr = NULL;
1082     png_info      *info_ptr = NULL;
1083     png_byte      buf[8];
1084     png_byte      **row_pointers = NULL;
1085
1086     int           bit_depth;
1087     int           color_type;
1088     int           alpha_present;
1089     int           ret;
1090     int           i;
1091     FILE *png_file;
1092
1093     dbg(1,"enter %s\n",name);
1094     png_file=fopen(name, "rb");
1095     if (!png_file)
1096     {
1097         dbg(0,"failed to open %s\n",name);
1098         return FALSE;
1099     }
1100
1101
1102     /* read and check signature in PNG file */
1103     ret = fread (buf, 1, 8, png_file);
1104     if (ret != 8)
1105     {
1106         fclose(png_file);
1107         return FALSE;
1108     }
1109
1110     ret = png_check_sig (buf, 8);
1111     if (!ret)
1112     {
1113         fclose(png_file);
1114         return FALSE;
1115     }
1116
1117     /* create png and info structures */
1118
1119     png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING,
1120                                       NULL, NULL, NULL);
1121     if (!png_ptr)
1122     {
1123         fclose(png_file);
1124         return FALSE;   /* out of memory */
1125     }
1126
1127     info_ptr = png_create_info_struct (png_ptr);
1128     if (!info_ptr)
1129     {
1130         fclose(png_file);
1131         png_destroy_read_struct (&png_ptr, NULL, NULL);
1132         return FALSE;   /* out of memory */
1133     }
1134
1135     if (setjmp (png_jmpbuf(png_ptr)))
1136     {
1137         fclose(png_file);
1138         png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
1139         return FALSE;
1140     }
1141
1142     /* set up the input control for C streams */
1143     png_init_io (png_ptr, png_file);
1144     png_set_sig_bytes (png_ptr, 8);  /* we already read the 8 signature bytes */
1145
1146     /* read the file information */
1147     png_read_info (png_ptr, info_ptr);
1148
1149     /* get size and bit-depth of the PNG-image */
1150     png_get_IHDR (png_ptr, info_ptr,
1151                   (png_uint_32*)&img->width, (png_uint_32*)&img->height, &bit_depth, &color_type,
1152                   NULL, NULL, NULL);
1153
1154     /* set-up the transformations */
1155
1156     /* transform paletted images into full-color rgb */
1157     if (color_type == PNG_COLOR_TYPE_PALETTE)
1158         png_set_expand (png_ptr);
1159     /* expand images to bit-depth 8 (only applicable for grayscale images) */
1160     if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
1161         png_set_expand (png_ptr);
1162     /* transform transparency maps into full alpha-channel */
1163     if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
1164         png_set_expand (png_ptr);
1165
1166    png_set_bgr(png_ptr);
1167
1168     /* all transformations have been registered; now update info_ptr data,
1169      * get rowbytes and channels, and allocate image memory */
1170
1171     png_read_update_info (png_ptr, info_ptr);
1172
1173     /* get the new color-type and bit-depth (after expansion/stripping) */
1174     png_get_IHDR (png_ptr, info_ptr, (png_uint_32*)&img->width, (png_uint_32*)&img->height, &bit_depth, &color_type,
1175                   NULL, NULL, NULL);
1176
1177     /* calculate new number of channels and store alpha-presence */
1178     if (color_type == PNG_COLOR_TYPE_GRAY)
1179         img->channels = 1;
1180     else if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
1181         img->channels = 2;
1182     else if (color_type == PNG_COLOR_TYPE_RGB)
1183         img->channels = 3;
1184     else if (color_type == PNG_COLOR_TYPE_RGB_ALPHA)
1185         img->channels = 4;
1186     else
1187         img->channels = 0; /* should never happen */
1188     alpha_present = (img->channels - 1) % 2;
1189
1190     /* row_bytes is the width x number of channels x (bit-depth / 8) */
1191     img->row_bytes = png_get_rowbytes (png_ptr, info_ptr);
1192
1193     if (  gr->AlphaBlend && img->channels == 4 )
1194     {
1195         BITMAPINFO pnginfo;
1196         HDC dc;
1197         memset(&pnginfo, 0, sizeof(pnginfo));
1198         pnginfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1199         pnginfo.bmiHeader.biWidth = img->width;
1200         pnginfo.bmiHeader.biHeight = -img->height;
1201         pnginfo.bmiHeader.biBitCount = 32;
1202         pnginfo.bmiHeader.biCompression = BI_RGB;
1203         pnginfo.bmiHeader.biPlanes = 1;
1204         dc = CreateCompatibleDC(NULL);
1205         img->hBitmap = CreateDIBSection(dc, &pnginfo, DIB_RGB_COLORS , (void **)&img->png_pixels, NULL, 0);
1206         DeleteDC(dc);
1207
1208     }
1209     else
1210     {
1211         if ((img->png_pixels = (png_byte *) g_malloc (img->row_bytes * img->height * sizeof (png_byte))) == NULL)
1212         {
1213             fclose(png_file);
1214             png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
1215             return FALSE;
1216         }
1217     }
1218
1219     if ((row_pointers = (png_byte **) g_malloc (img->height * sizeof (png_bytep))) == NULL)
1220     {
1221         fclose(png_file);
1222         png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
1223         g_free (img->png_pixels);
1224         img->png_pixels = NULL;
1225         img->hBitmap = NULL;
1226         return FALSE;
1227     }
1228
1229     /* set the individual row_pointers to point at the correct offsets */
1230     for (i = 0; i < (img->height); i++)
1231         row_pointers[i] = img->png_pixels + i * img->row_bytes;
1232
1233     /* now we can go ahead and just read the whole image */
1234     png_read_image (png_ptr, row_pointers);
1235
1236     /* read rest of file, and get additional chunks in info_ptr - REQUIRED */
1237     png_read_end (png_ptr, info_ptr);
1238
1239     /* clean up after the read, and free any memory allocated - REQUIRED */
1240     png_destroy_read_struct (&png_ptr, &info_ptr, (png_infopp) NULL);
1241
1242     if (row_pointers != (unsigned char**) NULL)
1243         g_free (row_pointers);
1244     img->hot.x=img->width/2-1;
1245     img->hot.y=img->height/2-1;
1246     dbg(1,"ok\n");
1247     fclose(png_file);
1248     return TRUE;
1249
1250 } /* end of source */
1251
1252 static void
1253 pngrender(struct graphics_image_priv *img, struct graphics_priv *gr, int x0, int y0)
1254 {
1255         if (img->hBitmap)
1256         {
1257                 HDC hdc;
1258                 HBITMAP oldBitmap;
1259                 BLENDFUNCTION blendFunction ;
1260                 blendFunction.BlendOp = AC_SRC_OVER;
1261                 blendFunction.BlendFlags = 0;
1262                 blendFunction.SourceConstantAlpha = 255;
1263                 blendFunction.AlphaFormat = AC_SRC_ALPHA;
1264                 hdc = CreateCompatibleDC(NULL);
1265                 oldBitmap = SelectBitmap(hdc, img->hBitmap);
1266                 gr->AlphaBlend(gr->hMemDC, x0, y0, img->width, img->height, hdc, 0, 0, img->width, img->height, blendFunction);
1267                 (void)SelectBitmap(hdc, oldBitmap);
1268                 DeleteDC(hdc);
1269         }
1270         else
1271         {
1272                 int x, y;
1273                 HDC hdc=gr->hMemDC;
1274                 png_byte *pix_ptr = img->png_pixels;
1275                 COLORREF *pixeldata;
1276                 HDC dc;
1277                 HBITMAP bitmap;
1278                 HBITMAP oldBitmap;
1279
1280                 BITMAPINFO pnginfo;
1281
1282                 memset(&pnginfo, 0, sizeof(pnginfo));
1283                 pnginfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
1284                 pnginfo.bmiHeader.biWidth = img->width;
1285                 pnginfo.bmiHeader.biHeight = -img->height;
1286                 pnginfo.bmiHeader.biBitCount = 32;
1287                 pnginfo.bmiHeader.biCompression = BI_RGB;
1288                 pnginfo.bmiHeader.biPlanes = 1;
1289                 dc = CreateCompatibleDC(NULL);
1290                 bitmap = CreateDIBSection(hdc, &pnginfo, DIB_RGB_COLORS, (void **)&pixeldata, NULL, 0);
1291                 oldBitmap = SelectBitmap(dc, bitmap);
1292                 BitBlt(dc, 0, 0, img->width, img->height, hdc, x0, y0, SRCCOPY);
1293                 for (y=0 ; y < img->width ; y++)
1294                 {
1295                         for (x=0 ; x < img->height ; x++)
1296                         {
1297                                 int b = pix_ptr[0];
1298                                 int g = pix_ptr[1];
1299                                 int r = pix_ptr[2];
1300                                 int a = pix_ptr[3];
1301                                 if (a != 0xff)
1302                                 {
1303                                         int p = *pixeldata;
1304                                         int ai = 0xff - a;
1305                                         r = (r * a + ((p >> 16) & 0xff) * ai) / 255;
1306                                         g = (g * a + ((p >>  8) & 0xff) * ai) / 255;
1307                                         b = (b * a + ((p >>  0) & 0xff) * ai) / 255;
1308                                 }
1309                                 *pixeldata++ = (r << 16) | (g << 8) | b;
1310                                 pix_ptr+=img->channels;
1311                         }
1312                 }
1313
1314                 BitBlt(hdc, x0, y0, img->width, img->height, dc, 0, 0, SRCCOPY);
1315                 (void)SelectBitmap(dc, oldBitmap);
1316                 DeleteBitmap(bitmap);
1317                 DeleteDC(dc);
1318         }
1319 }
1320
1321 static int
1322 xpmdecode(char *name, struct graphics_image_priv *img)
1323 {
1324     img->pxpm = Xpm2bmp_new();
1325     if (Xpm2bmp_load( img->pxpm, name ) != 0)
1326     {
1327         g_free(img->pxpm);
1328         return FALSE;
1329     }
1330     img->width=img->pxpm->size_x;
1331     img->height=img->pxpm->size_y;
1332     img->hot.x=img->pxpm->hotspot_x;
1333     img->hot.y=img->pxpm->hotspot_y;
1334     return TRUE;
1335 }
1336
1337
1338 static struct graphics_image_priv *image_new(struct graphics_priv *gr, struct graphics_image_methods *meth, char *name, int *w, int *h, struct point *hot, int rotation)
1339 {
1340     struct graphics_image_priv* ret;
1341     
1342     if ( !g_hash_table_lookup_extended( gr->image_cache_hash, name, NULL, (gpointer)&ret) )
1343     {
1344         int len=strlen(name);
1345         int rc=0;
1346
1347         if (len >= 4)
1348         {
1349             char *ext;
1350             dbg(2, "loading image '%s'\n", name );
1351             ret = g_new0( struct graphics_image_priv, 1 );
1352             ext = name+len-4;
1353             if (!strcmp(ext,".xpm")) {
1354                 rc=xpmdecode(name, ret);
1355             } else if (!strcmp(ext,".png")) {
1356                 rc=pngdecode(gr, name, ret);
1357             }
1358         }
1359         if (!rc) {
1360             dbg(0, "failed loading '%s'\n", name );
1361             g_free(ret);
1362             ret=NULL;
1363         }
1364         g_hash_table_insert(gr->image_cache_hash, g_strdup( name ),  (gpointer)ret );
1365     }
1366     if (ret) {
1367         *w=ret->width;
1368         *h=ret->height;
1369         if (hot)
1370             *hot=ret->hot;
1371     }
1372     return ret;
1373 }
1374
1375 static void draw_image(struct graphics_priv *gr, struct graphics_gc_priv *fg, struct point *p, struct graphics_image_priv *img)
1376 {
1377     if (img->pxpm)
1378         Xpm2bmp_paint( img->pxpm , gr->hMemDC, p->x, p->y );
1379     if (img->png_pixels)
1380         pngrender(img, gr, p->x, p->y);
1381 }
1382
1383 static struct graphics_priv *
1384             graphics_win32_new_helper(struct graphics_methods *meth);
1385
1386 static void overlay_resize(struct graphics_priv *gr, struct point *p, int w, int h, int alpha, int wraparound)
1387 {
1388     dbg(1, "resize overlay: %x, x: %d, y: %d, w: %d, h: %d, alpha: %x, wraparound: %d\n", gr, p->x, p->y, w, h, alpha, wraparound);
1389
1390     if ( gr->width != w || gr->height != h )
1391     {
1392         gr->width  = w;
1393         gr->height = h;
1394         create_memory_dc(gr);
1395     }
1396     gr->p.x    = p->x;
1397     gr->p.y    = p->y;
1398
1399 }
1400
1401
1402 static struct graphics_priv *
1403             overlay_new(struct graphics_priv *gr, struct graphics_methods *meth, struct point *p, int w, int h, int alpha, int wraparound)
1404 {
1405     struct graphics_priv *this=graphics_win32_new_helper(meth);
1406     dbg(1, "overlay: %x, x: %d, y: %d, w: %d, h: %d, alpha: %x, wraparound: %d\n", this, p->x, p->y, w, h, alpha, wraparound);
1407     this->width  = w;
1408     this->height = h;
1409     this->parent = gr;
1410     this->p.x    = p->x;
1411     this->p.y    = p->y;
1412     this->disabled = 0;
1413     this->hPrebuildDC = 0;
1414     this->AlphaBlend = gr->AlphaBlend;
1415     this->image_cache_hash = gr->image_cache_hash;
1416     
1417     this->next = gr->overlays;
1418     gr->overlays = this;
1419     this->wnd_handle = gr->wnd_handle;
1420
1421     if (wraparound)
1422     {
1423         if ( p->x < 0 )
1424         {
1425             this->p.x += gr->width;
1426         }
1427
1428         if ( p->y < 0 )
1429         {
1430             this->p.y += gr->height;
1431         }
1432     }
1433
1434     create_memory_dc(this);
1435     return this;
1436 }
1437
1438 static void overlay_disable(struct graphics_priv *gr, int disable)
1439 {
1440     dbg(1, "overlay: %x, disable: %d\n", gr, disable);
1441     gr->disabled = disable;
1442 }
1443
1444 static void get_text_bbox(struct graphics_priv *gr, struct graphics_font_priv *font, char *text, int dx, int dy, struct point *ret, int estimate)
1445 {
1446     int len = g_utf8_strlen(text, -1);
1447     int xMin = 0;
1448     int yMin = 0;
1449     int yMax = 13*font->size/256;
1450     int xMax = 9*font->size*len/256;
1451
1452     dbg(2, "Get bbox for %s\n", text);
1453
1454     ret[0].x = xMin;
1455     ret[0].y = -yMin;
1456     ret[1].x = xMin;
1457     ret[1].y = -yMax;
1458     ret[2].x = xMax;
1459     ret[2].y = -yMax;
1460     ret[3].x = xMax;
1461     ret[3].y = -yMin;
1462 }
1463
1464
1465 static struct graphics_methods graphics_methods =
1466 {
1467     graphics_destroy,
1468     draw_mode,
1469     draw_lines,
1470     draw_polygon,
1471     draw_rectangle,
1472     draw_circle,
1473     draw_text,
1474     draw_image,
1475 #ifdef HAVE_IMLIB2
1476     NULL, // draw_image_warp,
1477 #else
1478     NULL,
1479 #endif
1480     draw_restore,
1481     draw_drag,
1482     font_new,
1483     gc_new,
1484     background_gc,
1485     overlay_new,
1486     image_new,
1487     get_data,
1488     NULL,   //image_free
1489     get_text_bbox,
1490     overlay_disable,
1491     overlay_resize,
1492 };
1493
1494
1495 static struct graphics_priv *
1496             graphics_win32_new_helper(struct graphics_methods *meth)
1497 {
1498     struct graphics_priv *this_=g_new0(struct graphics_priv,1);
1499     *meth=graphics_methods;
1500     this_->mode = -1;
1501     return this_;
1502 }
1503
1504
1505 static void set_alphablend(struct graphics_priv* gra_priv)
1506 {
1507 #if HAVE_API_WIN32_CE
1508     gra_priv->hCoreDll = LoadLibrary(TEXT("coredll.dll"));
1509 #else
1510     gra_priv->hCoreDll = LoadLibrary(TEXT("msimg32.dll"));
1511 #endif
1512     if ( gra_priv->hCoreDll )
1513     {
1514         gra_priv->AlphaBlend  = (FP_AlphaBlend)GetProcAddress(gra_priv->hCoreDll, TEXT("AlphaBlend") );
1515         if (!gra_priv->AlphaBlend)
1516         {
1517             FreeLibrary(gra_priv->hCoreDll);
1518             gra_priv->hCoreDll = NULL;
1519             dbg(1, "AlphaBlend not supported\n");
1520         }
1521     }
1522     else
1523     {
1524         dbg(0, "Error loading coredll\n");
1525     }
1526 }
1527
1528
1529
1530 static struct graphics_priv*
1531             graphics_win32_new( struct navit *nav, struct graphics_methods *meth, struct attr **attrs, struct callback_list *cbl)
1532 {
1533     struct attr *attr;
1534
1535     struct graphics_priv* this_;
1536     if (!event_request_system("win32","graphics_win32"))
1537         return NULL;
1538     this_=graphics_win32_new_helper(meth);
1539     this_->nav=nav;
1540     this_->width=792;
1541     if ((attr=attr_search(attrs, NULL, attr_w)))
1542         this_->width=attr->u.num;
1543     this_->height=547;
1544     if ((attr=attr_search(attrs, NULL, attr_h)))
1545         this_->height=attr->u.num;
1546     this_->overlays = NULL;
1547     this_->cbl=cbl;
1548     this_->parent = NULL;
1549     this_->window.priv = NULL;
1550     this_->image_cache_hash = g_hash_table_new(g_str_hash, g_str_equal);
1551     set_alphablend(this_);
1552     return this_;
1553 }
1554
1555
1556 static void
1557 event_win32_main_loop_run(void)
1558 {
1559     MSG msg;
1560
1561     dbg(0,"enter\n");
1562     while (GetMessage(&msg, 0, 0, 0))
1563     {
1564         TranslateMessage(&msg);       /*  Keyboard input.      */
1565         DispatchMessage(&msg);
1566     }
1567
1568 }
1569
1570 static void event_win32_main_loop_quit(void)
1571 {
1572 #ifdef HAVE_API_WIN32_CE
1573     HWND hwndTaskbar;
1574     HWND hwndSip;
1575 #endif
1576
1577     dbg(0,"enter\n");
1578
1579 #ifdef HAVE_API_WIN32_CE
1580     hwndTaskbar = FindWindow(L"HHTaskBar", NULL);
1581     hwndSip = FindWindow(L"MS_SIPBUTTON", NULL);
1582     // activate the SIP button
1583     ShowWindow(hwndSip, SW_SHOW);
1584     ShowWindow(hwndTaskbar, SW_SHOW);
1585 #endif
1586
1587     DestroyWindow(g_hwnd);
1588 }
1589
1590 static struct event_watch *
1591             event_win32_add_watch(void *h, enum event_watch_cond cond, struct callback *cb)
1592 {
1593     dbg(0,"enter\n");
1594     return NULL;
1595 }
1596
1597 static void
1598 event_win32_remove_watch(struct event_watch *ev)
1599 {
1600     dbg(0,"enter\n");
1601 }
1602
1603 static GList *timers;
1604 struct event_timeout
1605 {
1606     UINT_PTR timer_id;
1607     int multi;
1608     struct callback *cb;
1609     struct event_timeout *next;
1610 };
1611
1612 static void run_timer(UINT_PTR idEvent)
1613 {
1614     GList *l;
1615     struct event_timeout *t;
1616     l = timers;
1617     while (l)
1618     {
1619         t = l->data;
1620         if (t->timer_id == idEvent)
1621         {
1622             struct callback *cb = t->cb;
1623             dbg(2, "Timer %d (multi: %d)\n", t->timer_id, t->multi);
1624             if (!t->multi)
1625             {
1626                 KillTimer(NULL, t->timer_id);
1627                 timers = g_list_remove(timers, t);
1628                 g_free(t);
1629             }
1630             callback_call_0(cb);
1631             return;
1632         }
1633         l = g_list_next(l);
1634     }
1635     dbg(0, "timer %d not found\n", idEvent);
1636 }
1637
1638 static VOID CALLBACK win32_timer_cb(HWND hwnd, UINT uMsg,
1639                                     UINT_PTR idEvent,
1640                                     DWORD dwTime)
1641 {
1642     run_timer(idEvent);
1643 }
1644
1645 static struct event_timeout *
1646             event_win32_add_timeout(int timeout, int multi, struct callback *cb)
1647 {
1648     struct event_timeout *t;
1649     t = g_new0(struct event_timeout, 1);
1650     if (!t)
1651         return t;
1652     t->multi = multi;
1653     timers = g_list_prepend(timers, t);
1654     t->cb = cb;
1655     t->timer_id = SetTimer(NULL, 0, timeout, win32_timer_cb);
1656     dbg(1, "Started timer %d for %d (multi: %d)\n", t->timer_id, timeout, multi);
1657     return t;
1658 }
1659
1660 static void
1661 event_win32_remove_timeout(struct event_timeout *to)
1662 {
1663     if (to)
1664     {
1665         GList *l;
1666         struct event_timeout *t=NULL;
1667         dbg(1, "Try stopping timer %d\n", to->timer_id);
1668         l = timers;
1669         while (l)
1670         {
1671             t = l->data;
1672             /* Use the pointer not the ID, IDs are reused */
1673             if (t == to)
1674             {
1675                 KillTimer(NULL, t->timer_id);
1676                 timers = g_list_remove(timers, t);
1677                 g_free(t);
1678                 return;
1679             }
1680             l = g_list_next(l);
1681         }
1682         dbg(0, "Timer %d not found\n", to->timer_id);
1683         g_free(to);
1684     }
1685 }
1686
1687 static struct event_idle *
1688             event_win32_add_idle(int priority, struct callback *cb)
1689 {
1690         return (struct event_idle *)event_win32_add_timeout(1, 1, cb);
1691 }
1692
1693 static void
1694 event_win32_remove_idle(struct event_idle *ev)
1695 {
1696     event_win32_remove_timeout((struct event_timeout *)ev);
1697 }
1698
1699 static void
1700 event_win32_call_callback(struct callback_list *cb)
1701 {
1702     PostMessage(g_hwnd, WM_USER+2, (WPARAM)cb , (LPARAM)0);
1703 }
1704
1705 static struct event_methods event_win32_methods =
1706 {
1707     event_win32_main_loop_run,
1708     event_win32_main_loop_quit,
1709     event_win32_add_watch,
1710     event_win32_remove_watch,
1711     event_win32_add_timeout,
1712     event_win32_remove_timeout,
1713     event_win32_add_idle,
1714     event_win32_remove_idle,
1715     event_win32_call_callback,
1716 };
1717
1718 static struct event_priv *
1719             event_win32_new(struct event_methods *meth)
1720 {
1721     *meth=event_win32_methods;
1722     return NULL;
1723 }
1724
1725 void
1726 plugin_init(void)
1727 {
1728     plugin_register_graphics_type("win32", graphics_win32_new);
1729     plugin_register_event_type("win32", event_win32_new);
1730 }