source: gitlab/src/sdlscreen.c

Last change on this file was 923da28, checked in by Thomas Bernard <miniupnp@…>, 6 weeks ago

remove MAX_PATH_CHARACTERS in Define_icon()

  • Property mode set to 100644
File size: 21.1 KB
Line 
1/* vim:expandtab:ts=2 sw=2:
2*/
3/*  Grafx2 - The Ultimate 256-color bitmap paint program
4
5    Copyright 2014 Sergii Pylypenko
6    Copyright 2011 Pawel Góralski
7    Copyright 2008 Yves Rizoud
8    Copyright 2008 Franck Charlet
9    Copyright 2007 Adrien Destugues
10    Copyright 1996-2001 Sunset Design (Guillaume Dorme & Karl Maritaud)
11
12    Grafx2 is free software; you can redistribute it and/or
13    modify it under the terms of the GNU General Public License
14    as published by the Free Software Foundation; version 2
15    of the License.
16
17    Grafx2 is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20    GNU General Public License for more details.
21
22    You should have received a copy of the GNU General Public License
23    along with Grafx2; if not, see <http://www.gnu.org/licenses/>
24*/
25#include <string.h>
26#include <stdlib.h>
27#include <SDL.h>
28#include <SDL_endian.h>
29#include <SDL_image.h>
30#if defined(__WIN32__)
31    #include <windows.h>
32#endif
33// There is no WM on the GP2X...
34#ifndef __GP2X__
35    #include <SDL_syswm.h>
36#endif
37
38#include "global.h"
39#include "sdlscreen.h"
40#include "errors.h"
41#include "misc.h"
42#include "gfx2log.h"
43#include "io.h"
44
45// Update method that does a large number of small rectangles, aiming
46// for a minimum number of total pixels updated.
47#define UPDATE_METHOD_MULTI_RECTANGLE 1
48// Intermediate update method, does only one update with the smallest
49// rectangle that includes all modified pixels.
50#define UPDATE_METHOD_CUMULATED       2
51// Total screen update, for platforms that impose a Vsync on each SDL update.
52#define UPDATE_METHOD_FULL_PAGE       3
53
54// UPDATE_METHOD can be set from makefile, otherwise it's selected here
55// depending on the platform :
56#ifndef UPDATE_METHOD
57  #if defined(__macosx__)
58    #define UPDATE_METHOD     UPDATE_METHOD_FULL_PAGE
59  #elif defined(__MINT__)
60    #define UPDATE_METHOD     UPDATE_METHOD_CUMULATED
61  #elif defined(GCWZERO)
62    #define UPDATE_METHOD     UPDATE_METHOD_FULL_PAGE
63  #elif defined(__ANDROID__)
64    #define UPDATE_METHOD     UPDATE_METHOD_FULL_PAGE
65  #elif defined(__SWITCH__)
66    #define UPDATE_METHOD     UPDATE_METHOD_CUMULATED
67  #else
68    #define UPDATE_METHOD     UPDATE_METHOD_CUMULATED
69  #endif
70#endif
71
72static SDL_Surface * Screen_SDL = NULL;
73#if defined(USE_SDL2)
74static SDL_Window * Window_SDL = NULL;
75static SDL_Renderer * Renderer_SDL = NULL;
76static SDL_Texture * Texture_SDL = NULL;
77static SDL_Surface * icon = NULL;
78#endif
79
80volatile int Allow_colorcycling=1;
81
82byte Get_Screen_pixel(int x, int y)
83{
84  if (y < 0 || x < 0 || y >= Screen_SDL->h || x >= Screen_SDL->w)
85  {
86    Warning("Get_Screen_pixel() coordinates out of bound");
87    return 0;
88  }
89  return ((byte *)Screen_SDL->pixels)[x + y*(Screen_SDL->pitch)];
90}
91
92void Set_Screen_pixel(int x, int y, byte value)
93{
94  if (y < 0 || x < 0 || y >= Screen_SDL->h || x >= Screen_SDL->w)
95  {
96    Warning("Set_Screen_pixel() coordinates out of bound");
97    return;
98  }
99  ((byte *)Screen_SDL->pixels)[x + y*(Screen_SDL->pitch)] = value;
100}
101
102byte* Get_Screen_pixel_ptr(int x, int y)
103{
104  if (y < 0 || x < 0 || y >= Screen_SDL->h || x >= Screen_SDL->w)
105  {
106    GFX2_Log(GFX2_WARNING, "Get_Screen_pixel_ptr(%d, %d): coordinates out of bound\n", x, y);
107    return NULL;
108  }
109  return (byte *)Screen_SDL->pixels + x + y*(Screen_SDL->pitch);
110}
111
112void Screen_FillRect(int x, int y, int w, int h, byte color)
113{
114  SDL_Rect rectangle;
115  rectangle.x = x;
116  rectangle.y = y;
117  rectangle.w = w;
118  rectangle.h = h;
119  SDL_FillRect(Screen_SDL,&rectangle,color);
120}
121
122/// Sets the new screen/window dimensions.
123void GFX2_Set_mode(int *width, int *height, int fullscreen)
124{
125  static SDL_Cursor* cur = NULL;
126  static byte cursorData = 0;
127
128#if defined(USE_SDL)
129#ifdef GCWZERO
130  Screen_SDL=SDL_SetVideoMode(*width,*height,8,SDL_HWSURFACE|SDL_TRIPLEBUF|(fullscreen?SDL_FULLSCREEN:0)|SDL_RESIZABLE);
131#else
132  Screen_SDL=SDL_SetVideoMode(*width,*height,8,(fullscreen?SDL_FULLSCREEN:0)|SDL_RESIZABLE);
133#endif
134  if(Screen_SDL != NULL)
135  {
136    // Check the mode we got, in case it was different from the one we requested.
137    if (Screen_SDL->w != *width || Screen_SDL->h != *height)
138    {
139      GFX2_Log(GFX2_WARNING, "Got a different video mode than the requested one! %dx%d => %dx%d\n", *width, *height, Screen_SDL->w, Screen_SDL->h);
140      *width = Screen_SDL->w;
141      *height = Screen_SDL->h;
142    }
143    //Screen_pixels=Screen_SDL->pixels;
144  }
145  else
146  {
147    GFX2_Log(GFX2_ERROR, "Unable to change video mode!\n");
148  }
149#else
150  // SDL2
151  if (Window_SDL == NULL)
152  {
153    Window_SDL = SDL_CreateWindow("GrafX2", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
154                                  *width, *height, (fullscreen?SDL_WINDOW_FULLSCREEN:SDL_WINDOW_RESIZABLE));
155    SDL_SetWindowIcon(Window_SDL, icon);
156    Renderer_SDL = SDL_CreateRenderer(Window_SDL, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
157  }
158  else
159  {
160    SDL_SetWindowSize(Window_SDL, *width, *height);
161    SDL_SetWindowFullscreen(Window_SDL, fullscreen?SDL_WINDOW_FULLSCREEN:0);
162  }
163  //SDL_GetWindowSize(Window_SDL, width, height);
164  if (Texture_SDL != NULL)
165    SDL_DestroyTexture(Texture_SDL);
166  Texture_SDL = SDL_CreateTexture(Renderer_SDL, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, *width, *height);
167  if (Screen_SDL != NULL)
168    SDL_FreeSurface(Screen_SDL);
169  Screen_SDL = SDL_CreateRGBSurface(0, *width, *height, 8, 0, 0, 0, 0);
170#endif
171
172  // Trick borrowed to Barrage (http://www.mail-archive.com/debian-bugs-dist@lists.debian.org/msg737265.html) :
173  // Showing the cursor but setting it to fully transparent allows us to get absolute mouse coordinates,
174  // this means we can use tablet in fullscreen mode.
175
176  SDL_FreeCursor(cur);
177  cur = SDL_CreateCursor(&cursorData, &cursorData, 1,1,0,0);
178  if (cur != NULL)
179  {
180    SDL_SetCursor(cur);
181    SDL_ShowCursor(SDL_ENABLE); // show the SDL 1 pixel transparent cursor
182  }
183  else
184  {
185    // failed to create the 1 pixel transparent cursor
186    SDL_ShowCursor(SDL_DISABLE); // Hide the SDL mouse cursor, we use our own internal one
187  }
188}
189
190#if defined(USE_SDL2)
191static void GFX2_UpdateRect(int x, int y, int width, int height)
192{
193  byte * pixels;
194  int pitch;
195  int line;
196  static SDL_Surface *RGBcopy = NULL;
197  SDL_Rect source_rect;
198
199  source_rect.x = x;
200  source_rect.y = y;
201  if (width == 0 && height == 0) {
202    source_rect.w = Screen_SDL->w;
203    source_rect.h = Screen_SDL->h;
204  } else {
205    source_rect.w = width;
206    source_rect.h = height;
207  }
208
209  if (RGBcopy != NULL && (Screen_SDL->w > RGBcopy->w || Screen_SDL->h > RGBcopy->h))
210  {
211    SDL_FreeSurface(RGBcopy);
212    RGBcopy = NULL;
213  }
214
215  if (RGBcopy == NULL)
216  {
217    RGBcopy = SDL_CreateRGBSurface(0,
218    Screen_SDL->w, Screen_SDL->h,
219    32, 0, 0, 0, 0);
220  }
221  // conversion ARGB
222  SDL_BlitSurface(Screen_SDL, &source_rect, RGBcopy, &source_rect);
223  // upload texture
224  SDL_LockTexture(Texture_SDL, &source_rect, (void **)(&pixels), &pitch );
225  for (line = 0; line < source_rect.h; line++)
226  {
227     memcpy(pixels + line * pitch, (const byte *)RGBcopy->pixels + source_rect.x * 4 + (source_rect.y+line)* RGBcopy->pitch, source_rect.w * 4 );
228  }
229  SDL_UnlockTexture(Texture_SDL);
230  //SDL_RenderCopy(Renderer_SDL, Texture_SDL, &source_rect, &source_rect);
231}
232
233void GFX2_UpdateScreen(void)
234{
235  SDL_RenderCopy(Renderer_SDL, Texture_SDL, NULL, NULL);
236  SDL_RenderPresent(Renderer_SDL);
237}
238#endif
239
240#if (UPDATE_METHOD == UPDATE_METHOD_CUMULATED)
241short Min_X=0;
242short Min_Y=0;
243short Max_X=10000;
244short Max_Y=10000;
245short Status_line_dirty_begin=0;
246short Status_line_dirty_end=0;
247#endif
248
249#if (UPDATE_METHOD == UPDATE_METHOD_FULL_PAGE)
250  int update_is_required=0;
251#endif
252
253void Flush_update(void)
254{
255#if (UPDATE_METHOD == UPDATE_METHOD_FULL_PAGE)
256  // Do a full screen update
257  if (update_is_required)
258  {
259#ifdef GCWZERO
260    SDL_Flip(Screen_SDL);
261#elif defined(USE_SDL)
262    SDL_UpdateRect(Screen_SDL, 0, 0, 0, 0);
263#else
264    GFX2_UpdateRect(0, 0, 0, 0);
265#endif
266    update_is_required=0;
267  }
268#endif
269  #if (UPDATE_METHOD == UPDATE_METHOD_CUMULATED)
270  if (Min_X>=Max_X || Min_Y>=Max_Y)
271  {
272    ; // Nothing to do
273  }
274  else
275  {
276    if (Min_X<0)
277      Min_X=0;
278    if (Min_Y<0)
279      Min_Y=0;
280#if defined(USE_SDL)
281    SDL_UpdateRect(Screen_SDL, Min_X*Pixel_width, Min_Y*Pixel_height, Min(Screen_width-Min_X, Max_X-Min_X)*Pixel_width, Min(Screen_height-Min_Y, Max_Y-Min_Y)*Pixel_height);
282#else
283    GFX2_UpdateRect(Min_X*Pixel_width, Min_Y*Pixel_height, Min(Screen_width-Min_X, Max_X-Min_X)*Pixel_width, Min(Screen_height-Min_Y, Max_Y-Min_Y)*Pixel_height);
284#endif
285
286    Min_X=Min_Y=10000;
287    Max_X=Max_Y=0;
288  }
289  if (Status_line_dirty_end)
290  {
291#if defined(USE_SDL)
292    SDL_UpdateRect(Screen_SDL, (18+(Status_line_dirty_begin*8))*Menu_factor_X*Pixel_width,Menu_status_Y*Pixel_height,(Status_line_dirty_end-Status_line_dirty_begin)*8*Menu_factor_X*Pixel_width,8*Menu_factor_Y*Pixel_height);
293#else
294    GFX2_UpdateRect((18+(Status_line_dirty_begin*8))*Menu_factor_X*Pixel_width,Menu_status_Y*Pixel_height,(Status_line_dirty_end-Status_line_dirty_begin)*8*Menu_factor_X*Pixel_width,8*Menu_factor_Y*Pixel_height);
295#endif
296  }
297  Status_line_dirty_begin=25;
298  Status_line_dirty_end=0;
299
300    #endif
301
302}
303
304void Update_rect(short x, short y, unsigned short width, unsigned short height)
305{
306  #if (UPDATE_METHOD == UPDATE_METHOD_MULTI_RECTANGLE)
307    #if defined(USE_SDL)
308    SDL_UpdateRect(Screen_SDL, x*Pixel_width, y*Pixel_height, width*Pixel_width, height*Pixel_height);
309    #else
310    GFX2_UpdateRect(x*Pixel_width, y*Pixel_height, width*Pixel_width, height*Pixel_height);
311    #endif
312  #endif
313
314  #if (UPDATE_METHOD == UPDATE_METHOD_CUMULATED)
315  if (width==0 || height==0)
316  {
317    Min_X=Min_Y=0;
318    Max_X=Max_Y=10000;
319  }
320  else
321  {
322    if (x < Min_X)
323      Min_X = x;
324    if (y < Min_Y)
325      Min_Y = y;
326    if (x+width>Max_X)
327      Max_X=x+width;
328    if (y+height>Max_Y)
329      Max_Y=y+height;
330  }
331  #endif
332
333  #if (UPDATE_METHOD == UPDATE_METHOD_FULL_PAGE)
334  (void)x; (void)y; (void)width; (void)height; // unused
335  update_is_required=1;
336  #endif
337
338}
339
340void Update_status_line(short char_pos, short width)
341{
342  #if (UPDATE_METHOD == UPDATE_METHOD_MULTI_RECTANGLE)
343  #if defined(USE_SDL)
344  SDL_UpdateRect(Screen_SDL, (18+char_pos*8)*Menu_factor_X*Pixel_width,Menu_status_Y*Pixel_height,width*8*Menu_factor_X*Pixel_width,8*Menu_factor_Y*Pixel_height);
345  #else
346  GFX2_UpdateRect((18+char_pos*8)*Menu_factor_X*Pixel_width,Menu_status_Y*Pixel_height,width*8*Menu_factor_X*Pixel_width,8*Menu_factor_Y*Pixel_height);
347  #endif
348  #endif
349
350  #if (UPDATE_METHOD == UPDATE_METHOD_CUMULATED)
351  // Merge the ranges
352  if (Status_line_dirty_end < char_pos+width)
353    Status_line_dirty_end=char_pos+width;
354  if (Status_line_dirty_begin > char_pos)
355    Status_line_dirty_begin=char_pos;
356  #endif
357
358  #if (UPDATE_METHOD == UPDATE_METHOD_FULL_PAGE)
359  (void)char_pos; // unused parameter
360  (void)width; // unused parameter
361  update_is_required=1;
362  #endif
363
364}
365
366///
367/// Converts a SDL_Surface (indexed colors or RGB) into an array of bytes
368/// (indexed colors).
369/// If dest is NULL, it's allocated by malloc(). Otherwise, be sure to
370/// pass a buffer of the right dimensions.
371byte * Surface_to_bytefield(SDL_Surface *source, byte * dest)
372{
373  byte *src;
374  byte *dest_ptr;
375  int y;
376  int remainder;
377
378  // Support seulement des images 256 couleurs
379  if (source->format->BytesPerPixel != 1)
380    return NULL;
381
382  if (source->w & 3)
383    remainder=4-(source->w&3);
384  else
385    remainder=0;
386
387  if (dest==NULL)
388    dest=(byte *)malloc(source->w*source->h);
389
390  dest_ptr=dest;
391  src=(byte *)(source->pixels);
392  for(y=0; y < source->h; y++)
393  {
394    memcpy(dest_ptr, src,source->w);
395    dest_ptr += source->w;
396    src += source->w + remainder;
397  }
398  return dest;
399
400}
401
402/// Gets the RGB 24-bit color currently associated with a palette index.
403SDL_Color Color_to_SDL_color(byte index)
404{
405  SDL_Color color;
406  color.r = Main.palette[index].R;
407  color.g = Main.palette[index].G;
408  color.b = Main.palette[index].B;
409#if defined(USE_SDL)
410  color.unused = 255;
411#else
412  color.a = 255;
413#endif
414  return color;
415}
416
417/// Reads a pixel in a 8-bit SDL surface.
418byte Get_SDL_pixel_8(const SDL_Surface *bmp, int x, int y)
419{
420  return ((byte *)(bmp->pixels))[(y*bmp->pitch+x)];
421}
422
423/// Writes a pixel in a 8-bit SDL surface.
424void Set_SDL_pixel_8(SDL_Surface *bmp, int x, int y, byte color)
425{
426  ((byte *)(bmp->pixels))[(y*bmp->pitch+x)]=color;
427}
428
429
430/// Reads a pixel in a multi-byte SDL surface.
431dword Get_SDL_pixel_hicolor(const SDL_Surface *bmp, int x, int y)
432{
433  byte * ptr;
434
435  switch(bmp->format->BytesPerPixel)
436  {
437    case 4:
438    default:
439      return *((dword *)((byte *)bmp->pixels+(y*bmp->pitch+x*4)));
440    case 3:
441      // Reading a 4-byte number starting at an address that isn't a multiple
442      // of 2 (or 4?) is not supported on Caanoo console at least (ARM CPU)
443      // So instead, we will read the 3 individual bytes, and re-construct the
444      // "dword" expected by SDL.
445      ptr = ((byte *)bmp->pixels)+(y*bmp->pitch+x*3);
446      #ifdef SDL_LIL_ENDIAN
447      // Read ABC, output _CBA : Most Significant Byte is zero.
448      return (*ptr) | (*(ptr+1)<<8) | (*(ptr+2)<<16);
449      #else
450      // Read ABC, output ABC_ : Least Significant Byte is zero.
451      return ((*ptr)<<24) | (*(ptr+1)<<16) | (*(ptr+2)<<8);
452      #endif
453    case 2:
454      return *((word *)((byte *)bmp->pixels+(y*bmp->pitch+x*2)));
455  }
456}
457
458/// Convert a SDL Palette to a grafx2 palette
459void Get_SDL_Palette(const SDL_Palette * sdl_palette, T_Palette palette)
460{
461  int i;
462
463  for (i=0; i<256; i++)
464  {
465    palette[i].R=sdl_palette->colors[i].r;
466    palette[i].G=sdl_palette->colors[i].g;
467    palette[i].B=sdl_palette->colors[i].b;
468  }
469
470}
471
472int SetPalette(const T_Components * colors, int firstcolor, int ncolors)
473{
474  int i;
475  SDL_Color PaletteSDL[256];
476
477  for (i = 0; i < ncolors; i++) {
478    PaletteSDL[i].r = colors[i].R;
479    PaletteSDL[i].g = colors[i].G;
480    PaletteSDL[i].b = colors[i].B;
481  }
482#if defined(USE_SDL)
483  return SDL_SetPalette(Screen_SDL, SDL_PHYSPAL | SDL_LOGPAL, PaletteSDL, firstcolor, ncolors);
484#else
485  // When using SDL2, we need to force screen update so the
486  // 8bit => True color conversion will be performed
487  i = SDL_SetPaletteColors(Screen_SDL->format->palette, PaletteSDL, firstcolor, ncolors);
488  if (i == 0)
489    Update_rect(0, 0, Screen_SDL->w, Screen_SDL->h);
490  return i;
491#endif
492}
493
494void Clear_border(byte color)
495{
496  int width;
497  int height;
498
499  // This function can be called before the graphics mode is set.
500  // Nothing to do then.
501  if (!Screen_SDL)
502    return;
503
504  width = Screen_SDL->w - Screen_width*Pixel_width;
505  height = Screen_SDL->h - Screen_height*Pixel_height;
506  if (width)
507  {
508    SDL_Rect r;
509    r.x=Screen_SDL->w - width;
510    r.y=0;
511    r.h=Screen_SDL->h;
512    r.w=width;
513    SDL_FillRect(Screen_SDL,&r,color);
514#if defined(USE_SDL)
515    SDL_UpdateRect(Screen_SDL, r.x, r.y, r.w, r.h);
516#else
517    //SDL_RenderPresent(
518#endif
519  }
520  if (height)
521  {
522    SDL_Rect r;
523    r.x=0;
524    r.y=Screen_SDL->h - height;
525    r.h=height;
526    r.w=Screen_SDL->w - height;
527    SDL_FillRect(Screen_SDL,&r,color);
528#if defined(USE_SDL)
529    SDL_UpdateRect(Screen_SDL, r.x, r.y, r.w, r.h);
530#else
531// TODO
532#endif
533  }
534}
535
536#ifdef WIN32
537HWND GFX2_Get_Window_Handle(void)
538{
539  SDL_SysWMinfo wminfo;
540
541  SDL_VERSION(&wminfo.version);
542#if defined(USE_SDL)
543  if (SDL_GetWMInfo(&wminfo) <= 0)
544    return NULL;
545  return wminfo.window;
546#else
547  if (Window_SDL == NULL)
548    return NULL;
549  if (!SDL_GetWindowWMInfo(Window_SDL, &wminfo))
550    return NULL;
551  return wminfo.info.win.window;
552#endif
553}
554#endif
555
556#ifdef SDL_VIDEO_DRIVER_X11
557int GFX2_Get_X11_Display_Window(Display * * display, Window * window)
558{
559  SDL_SysWMinfo wminfo;
560
561  SDL_VERSION(&wminfo.version);
562#if defined(USE_SDL)
563  // SDL 1.x
564  if (SDL_GetWMInfo(&wminfo) <= 0)
565    return 0;
566  *display = wminfo.info.x11.display;
567  *window = wminfo.info.x11.wmwindow;
568#else
569  // SDL 2.x
570  if (Window_SDL == NULL)
571    return 0;
572  if (!SDL_GetWindowWMInfo(Window_SDL, &wminfo))
573    return 0;
574  *display = wminfo.info.x11.display;
575  *window = wminfo.info.x11.window;
576#endif
577  return 1;
578}
579#endif
580
581/// Activates or desactivates file drag-dropping in program window.
582void Allow_drag_and_drop(int flag)
583{
584#if defined(USE_SDL2)
585  // SDL 2.x
586  SDL_EventState(SDL_DROPFILE, flag ? SDL_ENABLE : SDL_DISABLE);
587#else
588  // SDL 1.x
589  // Inform Windows that we accept drag-n-drop events or not
590#ifdef __WIN32__
591  DragAcceptFiles(GFX2_Get_Window_Handle(), flag?TRUE:FALSE);
592  SDL_EventState (SDL_SYSWMEVENT, flag?SDL_ENABLE:SDL_DISABLE);
593#elif defined(SDL_VIDEO_DRIVER_X11) && !defined(NO_X11)
594  Atom version = flag ? 5 : 0;
595  Display * display;
596  Window window;
597
598  if (GFX2_Get_X11_Display_Window(&display, &window))
599  {
600    if (display == NULL)
601    {
602      if (flag)
603        GFX2_Log(GFX2_WARNING, "Drag&Drop with SDL needs the x11 video driver\n");
604      return;
605    }
606    XChangeProperty(display, window,
607                    XInternAtom(display, "XdndAware", False),
608                    XA_ATOM, 32, PropModeReplace, (unsigned char *)&version, 1);
609    SDL_EventState (SDL_SYSWMEVENT, flag?SDL_ENABLE:SDL_DISABLE);
610  }
611#else
612  (void)flag; // unused
613#endif
614#endif
615}
616
617/// Set application icon(s)
618void Define_icon(void)
619{
620#ifdef WIN32
621  // Specific code for Win32:
622  // Load icon from embedded resource.
623  // This will provide both the 16x16 and 32x32 versions.
624  do
625  {
626    HICON hicon;
627    HRSRC hresource;
628    HINSTANCE hInstance;
629    LPVOID lpResIconDir;
630    LPVOID lpResIcon16;
631    LPVOID lpResIcon32;
632    HGLOBAL hMem;
633    WORD nID;
634
635    hInstance = (HINSTANCE)GetModuleHandle(NULL);
636    if (hInstance==NULL)
637      break;
638
639    // Icon is resource #1
640    hresource = FindResource(hInstance,
641      MAKEINTRESOURCE(100),
642      RT_GROUP_ICON);
643    if (hresource==NULL)
644      break;
645
646    // Load and lock the icon directory.
647    hMem = LoadResource(hInstance, hresource);
648    if (hMem==NULL)
649      break;
650
651    lpResIconDir = LockResource(hMem);
652    if (lpResIconDir==NULL)
653      break;
654
655    //
656    // 16x16
657    //
658
659    // Get the identifier of the 16x16 icon
660    nID = LookupIconIdFromDirectoryEx((PBYTE) lpResIconDir, TRUE,
661        16, 16, LR_DEFAULTCOLOR);
662    if (nID==0)
663      break;
664
665    // Find the bits for the nID icon.
666    hresource = FindResource(hInstance,
667        MAKEINTRESOURCE(nID),
668        MAKEINTRESOURCE((long)RT_ICON));
669    if (hresource==NULL)
670      break;
671
672    // Load and lock the icon.
673    hMem = LoadResource(hInstance, hresource);
674    if (hMem==NULL)
675      break;
676    lpResIcon16 = LockResource(hMem);
677    if (lpResIcon16==NULL)
678      break;
679
680    // Create a handle to the icon.
681    hicon = CreateIconFromResourceEx((PBYTE) lpResIcon16,
682        SizeofResource(hInstance, hresource), TRUE, 0x00030000,
683        16, 16, LR_DEFAULTCOLOR);
684    if (hicon==NULL)
685      break;
686
687    // Set it
688                SetClassLongPtr(GFX2_Get_Window_Handle(), GCL_HICONSM, (LONG_PTR)hicon);
689
690
691    //
692    // 32x32
693    //
694
695    // Get the identifier of the 32x32 icon
696    nID = LookupIconIdFromDirectoryEx((PBYTE) lpResIconDir, TRUE,
697        32, 32, LR_DEFAULTCOLOR);
698    if (nID==0)
699      break;
700
701    // Find the bits for the nID icon.
702    hresource = FindResource(hInstance,
703        MAKEINTRESOURCE(nID),
704        MAKEINTRESOURCE((long)RT_ICON));
705    if (hresource==NULL)
706      break;
707
708    // Load and lock the icon.
709    hMem = LoadResource(hInstance, hresource);
710    if (hMem==NULL)
711      break;
712    lpResIcon32 = LockResource(hMem);
713    if (lpResIcon32==NULL)
714      break;
715
716    // Create a handle to the icon.
717    hicon = CreateIconFromResourceEx((PBYTE) lpResIcon32,
718        SizeofResource(hInstance, hresource), TRUE, 0x00030000,
719        32, 32, LR_DEFAULTCOLOR);
720    if (hicon==NULL)
721      break;
722
723    // Set it
724                SetClassLongPtr(GFX2_Get_Window_Handle(), GCL_HICON, (LONG_PTR)hicon);
725
726
727                // Success
728                return;
729  } while (0);
730  // Failure: fall back on normal SDL version:
731
732#endif
733
734  // General version: Load icon from file
735  {
736#if defined(USE_SDL)
737    SDL_Surface * icon;
738#endif
739    char * icon_path;
740
741    // gfx2.gif : 32x32
742    // gfx2.png : 48x48
743    icon_path = Filepath_append_to_dir(Data_directory, "gfx2.png");
744    icon = IMG_Load(icon_path);
745    if (icon == NULL)
746      GFX2_Log(GFX2_WARNING, "Failed to load icon %s\n", icon_path);
747    else
748    {
749      Uint32 pink;
750      pink = SDL_MapRGB(icon->format, 255, 0, 255);
751
752      if (icon->format->BitsPerPixel == 8)
753      {
754        // NOTE : disable use of color key because SDL/SDL2
755        // gets the transparency information from the .gif and .png
756        // files by itself.
757        // 8bit image: use color key
758#if defined(USE_SDL)
759        //SDL_SetColorKey(icon, SDL_SRCCOLORKEY, pink);
760        SDL_WM_SetIcon(icon, NULL);
761#else
762        //SDL_SetColorKey(icon, SDL_TRUE, pink);
763#endif
764      }
765      else
766      {
767        // 24bit image: need to build a mask on magic pink
768        byte *icon_mask;
769        int x,y;
770
771        icon_mask = (byte *)malloc(icon->w * icon->h / 8);
772        memset(icon_mask, 0, icon->w * icon->h / 8);
773        for (y=0; y<icon->h; y++)
774          for (x=0; x<icon->w; x++)
775            if (Get_SDL_pixel_hicolor(icon, x, y) != pink)
776              icon_mask[(y*icon->w+x)/8] |= 0x80 >> (x&7);
777#if defined(USE_SDL)
778        SDL_WM_SetIcon(icon, icon_mask);
779#endif
780        free(icon_mask);
781        icon_mask = NULL;
782      }
783#if defined(USE_SDL)
784      SDL_FreeSurface(icon);
785#endif
786    }
787    free(icon_path);
788  }
789}
790
791void Set_mouse_position(void)
792{
793#if defined(USE_SDL)
794  SDL_WarpMouse(Mouse_X*Pixel_width, Mouse_Y*Pixel_height);
795#elif defined(USE_SDL2)
796  SDL_WarpMouseInWindow(NULL, Mouse_X*Pixel_width, Mouse_Y*Pixel_height);
797#endif
798}
Note: See TracBrowser for help on using the repository browser.