17 #include "graphics_win32.h"
19 #include "support/win32/ConvertUTF.h"
23 #ifdef HAVE_API_WIN32_CE
27 //#define FAST_TRANSPARENCY 1
29 #if defined(_WIN32_WCE) && _WIN32_WCE < 0x500 && !defined(__MINGW32CE__)
34 int SourceConstantAlpha;
39 #define AC_SRC_ALPHA 2
42 typedef BOOL (WINAPI *FP_AlphaBlend) ( HDC hdcDest,
52 BLENDFUNCTION blendFunction
63 HANDLE wnd_parent_handle;
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;
76 HBITMAP hPrebuildBitmap;
78 HBITMAP hOldPrebuildBitmap;
79 FP_AlphaBlend AlphaBlend;
81 GHashTable *image_cache_hash;
89 static HWND g_hwnd = NULL;
91 #ifdef HAVE_API_WIN32_CE
92 static int fullscr = 0;
96 #ifndef GET_WHEEL_DELTA_WPARAM
97 #define GET_WHEEL_DELTA_WPARAM(wParam) ((short)HIWORD(wParam))
101 HFONT EzCreateFont (HDC hdc, TCHAR * szFaceName, int iDeciPtHeight,
102 int iDeciPtWidth, int iAttributes, BOOL fLogRes) ;
104 #define EZ_ATTR_BOLD 1
105 #define EZ_ATTR_ITALIC 2
106 #define EZ_ATTR_UNDERLINE 4
107 #define EZ_ATTR_STRIKEOUT 8
109 HFONT EzCreateFont (HDC hdc, TCHAR * szFaceName, int iDeciPtHeight,
110 int iDeciPtWidth, int iAttributes, BOOL fLogRes)
120 #ifndef HAVE_API_WIN32_CE
121 SetGraphicsMode (hdc, GM_ADVANCED) ;
122 ModifyWorldTransform (hdc, NULL, MWT_IDENTITY) ;
124 SetViewportOrgEx (hdc, 0, 0, NULL) ;
125 #ifndef HAVE_API_WIN32_CE
126 SetWindowOrgEx (hdc, 0, 0, NULL) ;
131 cxDpi = (FLOAT) GetDeviceCaps (hdc, LOGPIXELSX) ;
132 cyDpi = (FLOAT) GetDeviceCaps (hdc, LOGPIXELSY) ;
136 cxDpi = (FLOAT) (25.4 * GetDeviceCaps (hdc, HORZRES) /
137 GetDeviceCaps (hdc, HORZSIZE)) ;
139 cyDpi = (FLOAT) (25.4 * GetDeviceCaps (hdc, VERTRES) /
140 GetDeviceCaps (hdc, VERTSIZE)) ;
143 pt.x = (int) (iDeciPtWidth * cxDpi / 72) ;
144 pt.y = (int) (iDeciPtHeight * cyDpi / 72) ;
146 #ifndef HAVE_API_WIN32_CE
147 DPtoLP (hdc, &pt, 1) ;
149 lf.lfHeight = - (int) (fabs (pt.y) / 10.0 + 0.5) ;
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 ;
161 lf.lfPitchAndFamily = 0 ;
163 lstrcpy (lf.lfFaceName, szFaceName) ;
165 hFont = CreateFontIndirect (&lf) ;
167 if (iDeciPtWidth != 0)
169 hFont = (HFONT) SelectObject (hdc, hFont) ;
171 GetTextMetrics (hdc, &tm) ;
173 DeleteObject (SelectObject (hdc, hFont)) ;
175 lf.lfWidth = (int) (tm.tmAveCharWidth *
176 fabs (pt.x) / fabs (pt.y) + 0.5) ;
178 hFont = CreateFontIndirect (&lf) ;
181 RestoreDC (hdc, -1) ;
185 struct graphics_image_priv
188 int width,height,row_bytes,channels;
189 unsigned char *png_pixels;
195 static void ErrorExit(LPTSTR lpszFunction)
197 // Retrieve the system error message for the last-error code
201 DWORD dw = GetLastError();
204 FORMAT_MESSAGE_ALLOCATE_BUFFER |
205 FORMAT_MESSAGE_FROM_SYSTEM |
206 FORMAT_MESSAGE_IGNORE_INSERTS,
209 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
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);
217 dbg(0, "%s failed with error %d: %s", lpszFunction, dw, lpMsgBuf);
218 MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK);
221 LocalFree(lpDisplayBuf);
227 struct graphics_gc_priv
236 struct graphics_priv *gr;
240 static void create_memory_dc(struct graphics_priv *gr)
243 BITMAPINFO bOverlayInfo;
247 (void)SelectBitmap(gr->hMemDC, gr->hOldBitmap);
248 DeleteBitmap(gr->hBitmap);
249 DeleteDC(gr->hMemDC);
251 (void)SelectBitmap(gr->hPrebuildDC, gr->hOldPrebuildBitmap);
252 DeleteBitmap(gr->hPrebuildBitmap);
253 DeleteDC(gr->hPrebuildDC);
258 hdc = GetDC( gr->wnd_handle );
260 gr->hMemDC = CreateCompatibleDC(hdc);
261 dbg(0, "resize memDC to: %d %d \n", gr->width, gr->height );
264 #ifndef FAST_TRANSPARENCY
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);
278 gr->hBitmap = CreateCompatibleBitmap(hdc, gr->width, gr->height );
282 gr->hOldBitmap = SelectBitmap( gr->hMemDC, gr->hBitmap);
284 ReleaseDC( gr->wnd_handle, hdc );
287 static void HandleButtonClick( struct graphics_priv *gra_priv, int updown, int button, long lParam )
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);
293 static void HandleKeyChar(struct graphics_priv *gra_priv, WPARAM wParam)
295 TCHAR key = (TCHAR) wParam;
298 dbg(1,"HandleKey %d\n",key);
306 callback_list_call_attr_1(gra_priv->cbl, attr_keypress, (void *)s);
309 static void HandleKeyDown(struct graphics_priv *gra_priv, WPARAM wParam)
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};
317 dbg(1,"HandleKey %d\n",key);
333 callback_list_call_attr_1(gra_priv->cbl, attr_keypress, (void *)s);
337 static LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
340 struct graphics_priv* gra_priv = (struct graphics_priv*)GetWindowLongPtr( hwnd , DWLP_USER );
350 GetClientRect( hwnd, &rc );
351 gra_priv->width = rc.right;
352 gra_priv->height = rc.bottom;
353 create_memory_dc(gra_priv);
358 switch (LOWORD(wParam))
372 GetClientRect( hwnd, &rc );
373 gra_priv->width = rc.right;
374 gra_priv->height = rc.bottom;
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);
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();
387 callback_list_call_0(cbl);
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);
402 #ifdef HAVE_API_WIN32_CE
403 if ( gra_priv && gra_priv->window.priv )
405 struct window_priv *win_priv = gra_priv->window.priv;
406 if (win_priv->hBackLight)
408 ReleasePowerRequirement(win_priv->hBackLight);
415 if ( gra_priv && gra_priv->hMemDC)
417 struct graphics_priv* overlay;
418 PAINTSTRUCT ps = { 0 };
421 dbg(1, "WM_PAINT\n");
422 overlay = gra_priv->overlays;
424 #ifndef FAST_TRANSPARENCY
425 BitBlt( gra_priv->hPrebuildDC, 0, 0, gra_priv->width , gra_priv->height, gra_priv->hMemDC, 0, 0, SRCCOPY);
427 while ( !gra_priv->disabled && overlay)
429 if ( !overlay->disabled && overlay->p.x >= 0 &&
431 overlay->p.x < gra_priv->width &&
432 overlay->p.y < gra_priv->height )
435 int destPixel, srcPixel;
437 #ifdef FAST_TRANSPARENCY
438 if ( !overlay->hPrebuildDC )
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);
449 const COLORREF transparent_color = RGB(overlay->transparent_color.r >> 8,overlay->transparent_color.g >> 8,overlay->transparent_color.b >> 8);
451 BitBlt( overlay->hPrebuildDC, 0, 0, overlay->width , overlay->height, overlay->hMemDC, 0, 0, SRCCOPY);
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++ )
461 for ( x = 0; x < w; x++ )
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 )
467 destPixel = ((overlay->p.y + y) * gra_priv->width) + (overlay->p.x + x);
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);
476 gra_priv->pPixelData[destPixel] = overlay->pPixelData[srcPixel];
483 overlay = overlay->next;
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 );
491 HDC hdc = BeginPaint(hwnd, &ps);
493 BitBlt( hdc, 0, 0, gra_priv->width , gra_priv->height, gra_priv->hMemDC, 0, 0, SRCCOPY );
495 overlay = gra_priv->overlays;
496 while ( !gra_priv->disabled && overlay && !overlay->disabled )
498 if ( overlay->p.x > 0 &&
500 overlay->p.x + overlay->width < gra_priv->width &&
501 overlay->p.y + overlay->height < gra_priv->height )
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);
506 overlay = overlay->next;
510 profile(0, "WM_PAINT\n");
515 struct point pt = { LOWORD(lParam), HIWORD(lParam) };
516 callback_list_call_attr_1(gra_priv->cbl, attr_motion, (void *)&pt);
522 dbg(1, "LBUTTONDOWN\n");
523 HandleButtonClick( gra_priv, 1, 1, lParam);
528 dbg(1, "LBUTTONUP\n");
529 HandleButtonClick( gra_priv, 0, 1, lParam);
533 HandleButtonClick( gra_priv, 1, 3,lParam );
536 HandleButtonClick( gra_priv, 0, 3,lParam );
538 case WM_LBUTTONDBLCLK:
539 dbg(1, "LBUTTONDBLCLK\n");
540 HandleButtonClick( gra_priv, 1, 6,lParam );
543 HandleKeyChar( gra_priv, wParam);
546 HandleKeyDown( gra_priv, wParam);
548 #ifdef HAVE_API_WIN32_CE
551 HWND hwndSip = FindWindow(L"MS_SIPBUTTON", NULL);
552 // deactivate the SIP button
553 ShowWindow(hwndSip, SW_HIDE);
558 HWND hwndSip = FindWindow(L"MS_SIPBUTTON", NULL);
559 // active the SIP button
560 ShowWindow(hwndSip, SW_SHOW);
565 return DefWindowProc(hwnd, Message, wParam, lParam);
570 static int fullscreen(struct window *win, int on)
573 #ifdef HAVE_API_WIN32_CE
574 HWND hwndTaskbar = FindWindow(L"HHTaskBar", NULL);
575 HWND hwndSip = FindWindow(L"MS_SIPBUTTON", NULL);
579 ShowWindow(hwndTaskbar, SW_HIDE);
580 MoveWindow(g_hwnd, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN), FALSE);
582 // deactivate the SIP button
583 ShowWindow(hwndSip, SW_HIDE);
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);
590 // activate the SIP button
591 ShowWindow(hwndSip, SW_SHOW);
596 ShowWindow(g_hwnd, SW_MAXIMIZE);
598 ShowWindow(g_hwnd, SW_RESTORE);
606 extern void WINAPI SystemIdleTimerReset(void);
607 static struct event_timeout *
608 event_win32_add_timeout(int timeout, int multi, struct callback *cb);
610 static void disable_suspend(struct window *win)
612 #ifdef HAVE_API_WIN32_CE
613 struct window_priv *win_priv = win->priv;
614 if ( win_priv && !win_priv->hBackLight )
616 win_priv->hBackLight = SetPowerRequirement(TEXT("BKL1:"), 0, 0x01, NULL, 0);
617 event_win32_add_timeout(29000, 1, callback_new(SystemIdleTimerReset, 0, NULL));
620 SystemIdleTimerReset();
624 static const TCHAR g_szClassName[] = {'N','A','V','G','R','A','\0'};
626 static HANDLE CreateGraphicsWindows( struct graphics_priv* gr, HMENU hMenu )
628 int wStyle = WS_VISIBLE;
630 #ifdef HAVE_API_WIN32_CE
634 wc.cbSize = sizeof(WNDCLASSEX);
638 wc.style = CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS;
639 wc.lpfnWndProc = WndProc;
642 wc.hInstance = GetModuleHandle(NULL);
644 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
645 wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
646 wc.lpszMenuName = NULL;
647 wc.lpszClassName = g_szClassName;
650 #ifdef HAVE_API_WIN32_CE
651 gr->width = GetSystemMetrics(SM_CXSCREEN);
652 gr->height = GetSystemMetrics(SM_CYSCREEN);
655 HWND hwndTaskbar = FindWindow(L"HHTaskBar", NULL);
657 GetWindowRect( hwndTaskbar, &taskbar_rect);
659 gr->height -= taskbar_rect.bottom;
666 #ifdef HAVE_API_WIN32_CE
667 if (!RegisterClass(&wc))
669 if (!RegisterClassEx(&wc))
672 dbg(0, "Window registration failed\n");
680 wStyle = WS_OVERLAPPED|WS_VISIBLE;
683 #ifdef HAVE_API_WIN32_CE
684 g_hwnd = hwnd = CreateWindow(g_szClassName,
691 gr->wnd_parent_handle,
693 GetModuleHandle(NULL),
696 g_hwnd = hwnd = CreateWindow(g_szClassName,
703 gr->wnd_parent_handle,
705 GetModuleHandle(NULL),
710 dbg(0, "Window creation failed: %d\n", GetLastError());
713 gr->wnd_handle = hwnd;
715 callback_list_call_attr_2(gr->cbl, attr_resize, (void *)gr->width, (void *)gr->height);
716 create_memory_dc(gr);
718 SetWindowLongPtr( hwnd , DWLP_USER, (LONG_PTR)gr );
720 ShowWindow( hwnd, SW_SHOW );
721 UpdateWindow( hwnd );
723 PostMessage( gr->wnd_parent_handle, WM_USER + 1, 0, 0 );
730 static void graphics_destroy(struct graphics_priv *gr)
736 static void gc_destroy(struct graphics_gc_priv *gc)
738 DeleteObject( gc->hpen );
739 DeleteObject( gc->hbrush );
743 static void gc_set_linewidth(struct graphics_gc_priv *gc, int w)
745 DeleteObject (gc->hpen);
747 gc->hpen = CreatePen( PS_SOLID, gc->line_width, gc->fg_color );
750 static void gc_set_dashes(struct graphics_gc_priv *gc, int width, int offset, unsigned char dash_list[], int n)
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);
757 static void gc_set_foreground(struct graphics_gc_priv *gc, struct color *c)
759 gc->fg_color = RGB( c->r >> 8, c->g >> 8, c->b >> 8);
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 )
768 gc->gr->transparent_color = *c;
773 static void gc_set_background(struct graphics_gc_priv *gc, struct color *c)
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 );
781 static struct graphics_gc_methods gc_methods =
788 NULL, //gc_set_stipple
791 static struct graphics_gc_priv *gc_new(struct graphics_priv *gr, struct graphics_gc_methods *meth)
793 struct graphics_gc_priv *gc=g_new(struct graphics_gc_priv, 1);
795 gc->hwnd = gr->wnd_handle;
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 );
806 static void draw_lines(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int count)
810 HPEN hpenold = SelectObject( gr->hMemDC, gc->hpen );
813 for ( i = 0; i< count; i++ )
818 MoveToEx( gr->hMemDC, p[0].x, p[0].y, NULL );
822 LineTo( gr->hMemDC, p[i].x, p[i].y );
826 SelectObject( gr->hMemDC, hpenold);
829 static void draw_polygon(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int count)
831 HPEN holdpen = SelectObject( gr->hMemDC, gc->hpen );
832 HBRUSH holdbrush = SelectObject( gr->hMemDC, gc->hbrush );
833 if (sizeof(POINT) != sizeof(struct point)) {
835 POINT* points=g_alloca(sizeof(POINT)*count);
836 for ( i=0;i< count; i++ )
838 points[i].x = p[i].x;
839 points[i].y = p[i].y;
841 Polygon( gr->hMemDC, points,count );
843 Polygon( gr->hMemDC, (POINT *)p, count);
844 SelectObject( gr->hMemDC, holdbrush);
845 SelectObject( gr->hMemDC, holdpen);
849 static void draw_rectangle(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int w, int h)
851 HPEN holdpen = SelectObject( gr->hMemDC, gc->hpen );
852 HBRUSH holdbrush = SelectObject( gr->hMemDC, gc->hbrush );
854 Rectangle(gr->hMemDC, p->x, p->y, p->x+w, p->y+h);
856 SelectObject( gr->hMemDC, holdbrush);
857 SelectObject( gr->hMemDC, holdpen);
860 static void draw_circle(struct graphics_priv *gr, struct graphics_gc_priv *gc, struct point *p, int r)
862 HPEN holdpen = SelectObject( gr->hMemDC, gc->hpen );
863 HBRUSH holdbrush = SelectObject( gr->hMemDC, GetStockObject(NULL_BRUSH));
867 Ellipse( gr->hMemDC, p->x - r, p->y -r, p->x + r, p->y + r );
869 SelectObject( gr->hMemDC, holdbrush);
870 SelectObject( gr->hMemDC, holdpen);
875 static void draw_restore(struct graphics_priv *gr, struct point *p, int w, int h)
877 InvalidateRect( gr->wnd_handle, NULL, FALSE );
880 static void draw_drag(struct graphics_priv *gr, struct point *p)
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) )))
894 gr->disabled = FALSE;
899 static void draw_mode(struct graphics_priv *gr, enum draw_mode_num mode)
901 dbg( 1, "set draw_mode to %x, %d\n", gr, (int)mode );
903 if ( mode == draw_mode_begin )
905 if ( gr->wnd_handle == NULL )
907 CreateGraphicsWindows( gr, (HMENU)ID_CHILD_GFX );
909 if ( gr->mode != draw_mode_begin )
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 )
917 (void)SelectBitmap(gr->hPrebuildDC, gr->hOldPrebuildBitmap );
918 DeleteBitmap(gr->hPrebuildBitmap);
919 DeleteDC(gr->hPrebuildDC);
925 #ifdef FAST_TRANSPARENCY
926 else if ( gr->hPrebuildDC )
928 (void)SelectBitmap(gr->hPrebuildDC, gr->hOldPrebuildBitmap );
929 DeleteBitmap(gr->hPrebuildBitmap);
930 DeleteDC(gr->hPrebuildDC);
937 if (mode == draw_mode_end && gr->mode == draw_mode_begin)
939 InvalidateRect( gr->wnd_handle, NULL, FALSE );
947 static void * get_data(struct graphics_priv *this_, char *type)
949 if ( strcmp( "wnd_parent_handle_ptr", type ) == 0 )
951 return &( this_->wnd_parent_handle );
953 if ( strcmp( "START_CLIENT", type ) == 0 )
955 CreateGraphicsWindows( this_, (HMENU)ID_CHILD_GFX );
958 if (!strcmp(type, "window"))
960 CreateGraphicsWindows( this_ , NULL);
962 this_->window.fullscreen = fullscreen;
963 this_->window.disable_suspend = disable_suspend;
965 this_->window.priv=g_new0(struct window_priv, 1);
967 return &this_->window;
973 static void background_gc(struct graphics_priv *gr, struct graphics_gc_priv *gc)
975 RECT rcClient = { 0, 0, gr->width, gr->height };
978 bgBrush = CreateSolidBrush( gc->bg_color );
979 gr->bg_color = gc->bg_color;
981 FillRect( gr->hMemDC, &rcClient, bgBrush );
982 DeleteObject( bgBrush );
985 struct graphics_font_priv
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)
999 GetClientRect( gr->wnd_handle, &rcClient );
1001 SetTextColor(gr->hMemDC, fg->fg_color);
1002 prevBkMode = SetBkMode( gr->hMemDC, TRANSPARENT );
1004 if ( NULL == font->hfont )
1006 #ifdef WIN_USE_SYSFONT
1007 font->hfont = (HFONT) GetStockObject (SYSTEM_FONT);
1008 GetObject (font->hfont, sizeof (LOGFONT), &font->lf);
1010 font->hfont = EzCreateFont (gr->hMemDC, TEXT ("Arial"), font->size/2, 0, 0, TRUE);
1011 GetObject ( font->hfont, sizeof (LOGFONT), &font->lf) ;
1016 angle = -atan2( dy, dx ) * 180 / 3.14159 ;
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) ;
1025 font->hfont = CreateFontIndirect (&font->lf);
1026 hOldFont = SelectObject(gr->hMemDC, font->hfont );
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)
1037 ExtTextOutW(gr->hMemDC, 0, 0, 0, NULL,
1038 utf16, (wchar_t*) utf16p - utf16, NULL);
1043 SelectObject(gr->hMemDC, hOldFont);
1044 DeleteObject (font->hfont) ;
1046 SetBkMode( gr->hMemDC, prevBkMode );
1048 SetViewportOrgEx (gr->hMemDC, 0, 0, NULL) ;
1051 static void font_destroy(struct graphics_font_priv *font)
1055 DeleteObject(font->hfont);
1060 static struct graphics_font_methods font_methods =
1065 static struct graphics_font_priv *font_new(struct graphics_priv *gr, struct graphics_font_methods *meth, char *name, int size, int flags)
1067 struct graphics_font_priv *font=g_new(struct graphics_font_priv, 1);
1068 *meth = font_methods;
1079 pngdecode(struct graphics_priv *gr, char *name, struct graphics_image_priv *img)
1081 png_struct *png_ptr = NULL;
1082 png_info *info_ptr = NULL;
1084 png_byte **row_pointers = NULL;
1093 dbg(1,"enter %s\n",name);
1094 png_file=fopen(name, "rb");
1097 dbg(0,"failed to open %s\n",name);
1102 /* read and check signature in PNG file */
1103 ret = fread (buf, 1, 8, png_file);
1110 ret = png_check_sig (buf, 8);
1117 /* create png and info structures */
1119 png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING,
1124 return FALSE; /* out of memory */
1127 info_ptr = png_create_info_struct (png_ptr);
1131 png_destroy_read_struct (&png_ptr, NULL, NULL);
1132 return FALSE; /* out of memory */
1135 if (setjmp (png_jmpbuf(png_ptr)))
1138 png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
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 */
1146 /* read the file information */
1147 png_read_info (png_ptr, info_ptr);
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,
1154 /* set-up the transformations */
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);
1166 png_set_bgr(png_ptr);
1168 /* all transformations have been registered; now update info_ptr data,
1169 * get rowbytes and channels, and allocate image memory */
1171 png_read_update_info (png_ptr, info_ptr);
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,
1177 /* calculate new number of channels and store alpha-presence */
1178 if (color_type == PNG_COLOR_TYPE_GRAY)
1180 else if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
1182 else if (color_type == PNG_COLOR_TYPE_RGB)
1184 else if (color_type == PNG_COLOR_TYPE_RGB_ALPHA)
1187 img->channels = 0; /* should never happen */
1188 alpha_present = (img->channels - 1) % 2;
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);
1193 if ( gr->AlphaBlend && img->channels == 4 )
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);
1211 if ((img->png_pixels = (png_byte *) g_malloc (img->row_bytes * img->height * sizeof (png_byte))) == NULL)
1214 png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
1219 if ((row_pointers = (png_byte **) g_malloc (img->height * sizeof (png_bytep))) == NULL)
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;
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;
1233 /* now we can go ahead and just read the whole image */
1234 png_read_image (png_ptr, row_pointers);
1236 /* read rest of file, and get additional chunks in info_ptr - REQUIRED */
1237 png_read_end (png_ptr, info_ptr);
1239 /* clean up after the read, and free any memory allocated - REQUIRED */
1240 png_destroy_read_struct (&png_ptr, &info_ptr, (png_infopp) NULL);
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;
1250 } /* end of source */
1253 pngrender(struct graphics_image_priv *img, struct graphics_priv *gr, int x0, int y0)
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);
1274 png_byte *pix_ptr = img->png_pixels;
1275 COLORREF *pixeldata;
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++)
1295 for (x=0 ; x < img->height ; x++)
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;
1309 *pixeldata++ = (r << 16) | (g << 8) | b;
1310 pix_ptr+=img->channels;
1314 BitBlt(hdc, x0, y0, img->width, img->height, dc, 0, 0, SRCCOPY);
1315 (void)SelectBitmap(dc, oldBitmap);
1316 DeleteBitmap(bitmap);
1322 xpmdecode(char *name, struct graphics_image_priv *img)
1324 img->pxpm = Xpm2bmp_new();
1325 if (Xpm2bmp_load( img->pxpm, name ) != 0)
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;
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)
1340 struct graphics_image_priv* ret;
1342 if ( !g_hash_table_lookup_extended( gr->image_cache_hash, name, NULL, (gpointer)&ret) )
1344 int len=strlen(name);
1350 dbg(2, "loading image '%s'\n", name );
1351 ret = g_new0( struct graphics_image_priv, 1 );
1353 if (!strcmp(ext,".xpm")) {
1354 rc=xpmdecode(name, ret);
1355 } else if (!strcmp(ext,".png")) {
1356 rc=pngdecode(gr, name, ret);
1360 dbg(0, "failed loading '%s'\n", name );
1364 g_hash_table_insert(gr->image_cache_hash, g_strdup( name ), (gpointer)ret );
1375 static void draw_image(struct graphics_priv *gr, struct graphics_gc_priv *fg, struct point *p, struct graphics_image_priv *img)
1378 Xpm2bmp_paint( img->pxpm , gr->hMemDC, p->x, p->y );
1379 if (img->png_pixels)
1380 pngrender(img, gr, p->x, p->y);
1383 static struct graphics_priv *
1384 graphics_win32_new_helper(struct graphics_methods *meth);
1386 static void overlay_resize(struct graphics_priv *gr, struct point *p, int w, int h, int alpha, int wraparound)
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);
1390 if ( gr->width != w || gr->height != h )
1394 create_memory_dc(gr);
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)
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);
1413 this->hPrebuildDC = 0;
1414 this->AlphaBlend = gr->AlphaBlend;
1415 this->image_cache_hash = gr->image_cache_hash;
1417 this->next = gr->overlays;
1418 gr->overlays = this;
1419 this->wnd_handle = gr->wnd_handle;
1425 this->p.x += gr->width;
1430 this->p.y += gr->height;
1434 create_memory_dc(this);
1438 static void overlay_disable(struct graphics_priv *gr, int disable)
1440 dbg(1, "overlay: %x, disable: %d\n", gr, disable);
1441 gr->disabled = disable;
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)
1446 int len = g_utf8_strlen(text, -1);
1449 int yMax = 13*font->size/256;
1450 int xMax = 9*font->size*len/256;
1452 dbg(2, "Get bbox for %s\n", text);
1465 static struct graphics_methods graphics_methods =
1476 NULL, // draw_image_warp,
1495 static struct graphics_priv *
1496 graphics_win32_new_helper(struct graphics_methods *meth)
1498 struct graphics_priv *this_=g_new0(struct graphics_priv,1);
1499 *meth=graphics_methods;
1505 static void set_alphablend(struct graphics_priv* gra_priv)
1507 #if HAVE_API_WIN32_CE
1508 gra_priv->hCoreDll = LoadLibrary(TEXT("coredll.dll"));
1510 gra_priv->hCoreDll = LoadLibrary(TEXT("msimg32.dll"));
1512 if ( gra_priv->hCoreDll )
1514 gra_priv->AlphaBlend = (FP_AlphaBlend)GetProcAddress(gra_priv->hCoreDll, TEXT("AlphaBlend") );
1515 if (!gra_priv->AlphaBlend)
1517 FreeLibrary(gra_priv->hCoreDll);
1518 gra_priv->hCoreDll = NULL;
1519 dbg(1, "AlphaBlend not supported\n");
1524 dbg(0, "Error loading coredll\n");
1530 static struct graphics_priv*
1531 graphics_win32_new( struct navit *nav, struct graphics_methods *meth, struct attr **attrs, struct callback_list *cbl)
1535 struct graphics_priv* this_;
1536 if (!event_request_system("win32","graphics_win32"))
1538 this_=graphics_win32_new_helper(meth);
1541 if ((attr=attr_search(attrs, NULL, attr_w)))
1542 this_->width=attr->u.num;
1544 if ((attr=attr_search(attrs, NULL, attr_h)))
1545 this_->height=attr->u.num;
1546 this_->overlays = NULL;
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_);
1557 event_win32_main_loop_run(void)
1562 while (GetMessage(&msg, 0, 0, 0))
1564 TranslateMessage(&msg); /* Keyboard input. */
1565 DispatchMessage(&msg);
1570 static void event_win32_main_loop_quit(void)
1572 #ifdef HAVE_API_WIN32_CE
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);
1587 DestroyWindow(g_hwnd);
1590 static struct event_watch *
1591 event_win32_add_watch(void *h, enum event_watch_cond cond, struct callback *cb)
1598 event_win32_remove_watch(struct event_watch *ev)
1603 static GList *timers;
1604 struct event_timeout
1608 struct callback *cb;
1609 struct event_timeout *next;
1612 static void run_timer(UINT_PTR idEvent)
1615 struct event_timeout *t;
1620 if (t->timer_id == idEvent)
1622 struct callback *cb = t->cb;
1623 dbg(2, "Timer %d (multi: %d)\n", t->timer_id, t->multi);
1626 KillTimer(NULL, t->timer_id);
1627 timers = g_list_remove(timers, t);
1630 callback_call_0(cb);
1635 dbg(0, "timer %d not found\n", idEvent);
1638 static VOID CALLBACK win32_timer_cb(HWND hwnd, UINT uMsg,
1645 static struct event_timeout *
1646 event_win32_add_timeout(int timeout, int multi, struct callback *cb)
1648 struct event_timeout *t;
1649 t = g_new0(struct event_timeout, 1);
1653 timers = g_list_prepend(timers, t);
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);
1661 event_win32_remove_timeout(struct event_timeout *to)
1666 struct event_timeout *t=NULL;
1667 dbg(1, "Try stopping timer %d\n", to->timer_id);
1672 /* Use the pointer not the ID, IDs are reused */
1675 KillTimer(NULL, t->timer_id);
1676 timers = g_list_remove(timers, t);
1682 dbg(0, "Timer %d not found\n", to->timer_id);
1687 static struct event_idle *
1688 event_win32_add_idle(int priority, struct callback *cb)
1690 return (struct event_idle *)event_win32_add_timeout(1, 1, cb);
1694 event_win32_remove_idle(struct event_idle *ev)
1696 event_win32_remove_timeout((struct event_timeout *)ev);
1700 event_win32_call_callback(struct callback_list *cb)
1702 PostMessage(g_hwnd, WM_USER+2, (WPARAM)cb , (LPARAM)0);
1705 static struct event_methods event_win32_methods =
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,
1718 static struct event_priv *
1719 event_win32_new(struct event_methods *meth)
1721 *meth=event_win32_methods;
1728 plugin_register_graphics_type("win32", graphics_win32_new);
1729 plugin_register_event_type("win32", event_win32_new);