1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.4
3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
4 //
5 // Permission to copy, use, modify, sell and distribute this software
6 // is granted provided this copyright notice appears in all copies.
7 // This software is provided "as is" without express or implied
8 // warranty, and with no claim as to its suitability for any purpose.
9 //
10 //----------------------------------------------------------------------------
11 // Contact: mcseem@antigrain.com
12 //          mcseemagg@yahoo.com
13 //          http://www.antigrain.com
14 //----------------------------------------------------------------------------
15 //
16 // class platform_support. SDL version.
17 //
18 //----------------------------------------------------------------------------
19 
20 #include <string.h>
21 #include "platform/agg_platform_support.h"
22 #include "SDL.h"
23 #include "SDL_byteorder.h"
24 
25 
26 namespace agg
27 {
28 
29     //------------------------------------------------------------------------
30     class platform_specific
31     {
32     public:
33         platform_specific(pix_format_e format, bool flip_y);
34         ~platform_specific();
35 
36         pix_format_e  m_format;
37         pix_format_e  m_sys_format;
38         bool          m_flip_y;
39         unsigned      m_bpp;
40         unsigned      m_sys_bpp;
41         unsigned      m_rmask;
42         unsigned      m_gmask;
43         unsigned      m_bmask;
44         unsigned      m_amask;
45         bool          m_update_flag;
46         bool          m_resize_flag;
47         bool          m_initialized;
48         SDL_Surface*  m_surf_screen;
49         SDL_Surface*  m_surf_window;
50         SDL_Surface*  m_surf_img[platform_support::max_images];
51         int           m_cur_x;
52         int           m_cur_y;
53 	int          m_sw_start;
54     };
55 
56 
57 
58     //------------------------------------------------------------------------
platform_specific(pix_format_e format,bool flip_y)59     platform_specific::platform_specific(pix_format_e format, bool flip_y) :
60         m_format(format),
61         m_sys_format(pix_format_undefined),
62         m_flip_y(flip_y),
63         m_bpp(0),
64         m_sys_bpp(0),
65         m_update_flag(true),
66         m_resize_flag(true),
67         m_initialized(false),
68         m_surf_screen(0),
69         m_surf_window(0),
70         m_cur_x(0),
71         m_cur_y(0)
72     {
73         memset(m_surf_img, 0, sizeof(m_surf_img));
74 
75         switch(m_format)
76         {
77 			case pix_format_gray8:
78             m_bpp = 8;
79             break;
80 
81         case pix_format_rgb565:
82             m_rmask = 0xF800;
83             m_gmask = 0x7E0;
84             m_bmask = 0x1F;
85             m_amask = 0;
86             m_bpp = 16;
87             break;
88 
89         case pix_format_rgb555:
90             m_rmask = 0x7C00;
91             m_gmask = 0x3E0;
92             m_bmask = 0x1F;
93             m_amask = 0;
94             m_bpp = 16;
95             break;
96 
97 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
98         case pix_format_rgb24:
99 			m_rmask = 0xFF;
100             m_gmask = 0xFF00;
101             m_bmask = 0xFF0000;
102             m_amask = 0;
103             m_bpp = 24;
104             break;
105 
106         case pix_format_bgr24:
107             m_rmask = 0xFF0000;
108             m_gmask = 0xFF00;
109             m_bmask = 0xFF;
110             m_amask = 0;
111             m_bpp = 24;
112             break;
113 
114         case pix_format_bgra32:
115             m_rmask = 0xFF0000;
116             m_gmask = 0xFF00;
117             m_bmask = 0xFF;
118             m_amask = 0xFF000000;
119             m_bpp = 32;
120             break;
121 
122         case pix_format_abgr32:
123             m_rmask = 0xFF000000;
124             m_gmask = 0xFF0000;
125             m_bmask = 0xFF00;
126             m_amask = 0xFF;
127             m_bpp = 32;
128             break;
129 
130         case pix_format_argb32:
131             m_rmask = 0xFF00;
132             m_gmask = 0xFF0000;
133             m_bmask = 0xFF000000;
134             m_amask = 0xFF;
135             m_bpp = 32;
136             break;
137 
138         case pix_format_rgba32:
139             m_rmask = 0xFF;
140             m_gmask = 0xFF00;
141             m_bmask = 0xFF0000;
142             m_amask = 0xFF000000;
143             m_bpp = 32;
144             break;
145 #else //SDL_BIG_ENDIAN (PPC)
146         case pix_format_rgb24:
147 			m_rmask = 0xFF0000;
148             m_gmask = 0xFF00;
149             m_bmask = 0xFF;
150             m_amask = 0;
151             m_bpp = 24;
152             break;
153 
154         case pix_format_bgr24:
155             m_rmask = 0xFF;
156             m_gmask = 0xFF00;
157             m_bmask = 0xFF0000;
158             m_amask = 0;
159             m_bpp = 24;
160             break;
161 
162         case pix_format_bgra32:
163             m_rmask = 0xFF00;
164             m_gmask = 0xFF0000;
165             m_bmask = 0xFF000000;
166             m_amask = 0xFF;
167             m_bpp = 32;
168             break;
169 
170         case pix_format_abgr32:
171             m_rmask = 0xFF;
172             m_gmask = 0xFF00;
173             m_bmask = 0xFF0000;
174             m_amask = 0xFF000000;
175             m_bpp = 32;
176             break;
177 
178         case pix_format_argb32:
179             m_rmask = 0xFF0000;
180             m_gmask = 0xFF00;
181             m_bmask = 0xFF;
182             m_amask = 0xFF000000;
183             m_bpp = 32;
184             break;
185 
186         case pix_format_rgba32:
187             m_rmask = 0xFF000000;
188             m_gmask = 0xFF0000;
189             m_bmask = 0xFF00;
190             m_amask = 0xFF;
191             m_bpp = 32;
192             break;
193 #endif
194         }
195     }
196 
197     //------------------------------------------------------------------------
~platform_specific()198     platform_specific::~platform_specific()
199     {
200         int i;
201         for(i = platform_support::max_images - 1; i >= 0; --i)
202         {
203             if(m_surf_img[i]) SDL_FreeSurface(m_surf_img[i]);
204         }
205         if(m_surf_window) SDL_FreeSurface(m_surf_window);
206         if(m_surf_screen) SDL_FreeSurface(m_surf_screen);
207     }
208 
209 
210 
211     //------------------------------------------------------------------------
platform_support(pix_format_e format,bool flip_y)212     platform_support::platform_support(pix_format_e format, bool flip_y) :
213         m_specific(new platform_specific(format, flip_y)),
214         m_format(format),
215         m_bpp(m_specific->m_bpp),
216         m_window_flags(0),
217         m_wait_mode(true),
218         m_flip_y(flip_y)
219     {
220         SDL_Init(SDL_INIT_VIDEO);
221         strcpy(m_caption, "Anti-Grain Geometry Application");
222     }
223 
224 
225     //------------------------------------------------------------------------
~platform_support()226     platform_support::~platform_support()
227     {
228         delete m_specific;
229     }
230 
231 
232 
233     //------------------------------------------------------------------------
caption(const char * cap)234     void platform_support::caption(const char* cap)
235     {
236         strcpy(m_caption, cap);
237         if(m_specific->m_initialized)
238         {
239             SDL_WM_SetCaption(cap, 0);
240         }
241     }
242 
243 
244 
245 
246 
247     //------------------------------------------------------------------------
init(unsigned width,unsigned height,unsigned flags)248     bool platform_support::init(unsigned width, unsigned height, unsigned flags)
249     {
250         m_window_flags = flags;
251         unsigned wflags = SDL_SWSURFACE;
252 
253         if(m_window_flags & window_hw_buffer)
254         {
255             wflags = SDL_HWSURFACE;
256         }
257 
258         if(m_window_flags & window_resize)
259         {
260             wflags |= SDL_RESIZABLE;
261         }
262 
263         if(m_specific->m_surf_screen) SDL_FreeSurface(m_specific->m_surf_screen);
264 
265         m_specific->m_surf_screen = SDL_SetVideoMode(width, height, m_bpp, wflags);
266         if(m_specific->m_surf_screen == 0)
267         {
268             fprintf(stderr,
269                     "Unable to set %dx%d %d bpp video: %s\n",
270                     width,
271                     height,
272                     m_bpp,
273                     ::SDL_GetError());
274             return false;
275         }
276 
277         SDL_WM_SetCaption(m_caption, 0);
278 
279         if(m_specific->m_surf_window) SDL_FreeSurface(m_specific->m_surf_window);
280 
281         m_specific->m_surf_window =
282             SDL_CreateRGBSurface(SDL_HWSURFACE,
283                                  m_specific->m_surf_screen->w,
284                                  m_specific->m_surf_screen->h,
285                                  m_specific->m_surf_screen->format->BitsPerPixel,
286                                  m_specific->m_rmask,
287                                  m_specific->m_gmask,
288                                  m_specific->m_bmask,
289                                  m_specific->m_amask);
290 
291         if(m_specific->m_surf_window == 0)
292         {
293             fprintf(stderr,
294                     "Unable to create image buffer %dx%d %d bpp: %s\n",
295                     width,
296                     height,
297                     m_bpp,
298                     SDL_GetError());
299             return false;
300         }
301 
302         m_rbuf_window.attach((unsigned char*)m_specific->m_surf_window->pixels,
303                              m_specific->m_surf_window->w,
304                              m_specific->m_surf_window->h,
305                              m_flip_y ? -m_specific->m_surf_window->pitch :
306                                          m_specific->m_surf_window->pitch);
307 
308         if(!m_specific->m_initialized)
309         {
310             m_initial_width = width;
311             m_initial_height = height;
312             on_init();
313             m_specific->m_initialized = true;
314         }
315         on_resize(m_rbuf_window.width(), m_rbuf_window.height());
316         m_specific->m_update_flag = true;
317         return true;
318     }
319 
320 
321 
322     //------------------------------------------------------------------------
update_window()323     void platform_support::update_window()
324     {
325         SDL_BlitSurface(m_specific->m_surf_window, 0, m_specific->m_surf_screen, 0);
326         SDL_UpdateRect(m_specific->m_surf_screen, 0, 0, 0, 0);
327     }
328 
329 
330     //------------------------------------------------------------------------
run()331     int platform_support::run()
332     {
333         SDL_Event event;
334         bool ev_flag = false;
335 
336         for(;;)
337         {
338             if(m_specific->m_update_flag)
339             {
340                 on_draw();
341                 update_window();
342                 m_specific->m_update_flag = false;
343             }
344 
345             ev_flag = false;
346             if(m_wait_mode)
347             {
348                 SDL_WaitEvent(&event);
349                 ev_flag = true;
350             }
351             else
352             {
353                 if(SDL_PollEvent(&event))
354                 {
355                     ev_flag = true;
356                 }
357                 else
358                 {
359                     on_idle();
360                 }
361             }
362 
363             if(ev_flag)
364             {
365                 if(event.type == SDL_QUIT)
366                 {
367                     break;
368                 }
369 
370                 int y;
371                 unsigned flags = 0;
372 
373                 switch (event.type)
374                 {
375                 case SDL_VIDEORESIZE:
376                     if(!init(event.resize.w, event.resize.h, m_window_flags)) return false;
377                     on_resize(m_rbuf_window.width(), m_rbuf_window.height());
378                     trans_affine_resizing(event.resize.w, event.resize.h);
379                     m_specific->m_update_flag = true;
380                     break;
381 
382                 case SDL_KEYDOWN:
383                     {
384                         flags = 0;
385                         if(event.key.keysym.mod & KMOD_SHIFT) flags |= kbd_shift;
386                         if(event.key.keysym.mod & KMOD_CTRL)  flags |= kbd_ctrl;
387 
388                         bool left  = false;
389                         bool up    = false;
390                         bool right = false;
391                         bool down  = false;
392 
393                         switch(event.key.keysym.sym)
394                         {
395                         case key_left:
396                             left = true;
397                             break;
398 
399                         case key_up:
400                             up = true;
401                             break;
402 
403                         case key_right:
404                             right = true;
405                             break;
406 
407                         case key_down:
408                             down = true;
409                             break;
410                         }
411 
412                         if(m_ctrls.on_arrow_keys(left, right, down, up))
413                         {
414                             on_ctrl_change();
415                             force_redraw();
416                         }
417                         else
418                         {
419                             on_key(m_specific->m_cur_x,
420                                    m_specific->m_cur_y,
421                                    event.key.keysym.sym,
422                                    flags);
423                         }
424                     }
425                     break;
426 
427                 case SDL_MOUSEMOTION:
428                     y = m_flip_y ?
429                         m_rbuf_window.height() - event.motion.y :
430                         event.motion.y;
431 
432                     m_specific->m_cur_x = event.motion.x;
433                     m_specific->m_cur_y = y;
434                     flags = 0;
435                     if(event.motion.state & SDL_BUTTON_LMASK) flags |= mouse_left;
436                     if(event.motion.state & SDL_BUTTON_RMASK) flags |= mouse_right;
437 
438                     if(m_ctrls.on_mouse_move(m_specific->m_cur_x,
439                                              m_specific->m_cur_y,
440                                              (flags & mouse_left) != 0))
441                     {
442                         on_ctrl_change();
443                         force_redraw();
444                     }
445                     else
446                     {
447                         on_mouse_move(m_specific->m_cur_x,
448                                       m_specific->m_cur_y,
449                                       flags);
450                     }
451 		    SDL_Event eventtrash;
452 		    while (SDL_PeepEvents(&eventtrash, 1, SDL_GETEVENT, SDL_EVENTMASK(SDL_MOUSEMOTION))!=0){;}
453                     break;
454 
455 		case SDL_MOUSEBUTTONDOWN:
456                     y = m_flip_y
457                         ? m_rbuf_window.height() - event.button.y
458                         : event.button.y;
459 
460                     m_specific->m_cur_x = event.button.x;
461                     m_specific->m_cur_y = y;
462                     flags = 0;
463                     switch(event.button.button)
464                     {
465                     case SDL_BUTTON_LEFT:
466                         {
467                             flags = mouse_left;
468 
469 if(m_ctrls.on_mouse_button_down(m_specific->m_cur_x,
470                                 m_specific->m_cur_y))
471                             {
472                                 m_ctrls.set_cur(m_specific->m_cur_x,
473                                     m_specific->m_cur_y);
474                                 on_ctrl_change();
475                                 force_redraw();
476                             }
477                             else
478                             {
479                                 if(m_ctrls.in_rect(m_specific->m_cur_x,
480                                     m_specific->m_cur_y))
481                                 {
482                                     if(m_ctrls.set_cur(m_specific->m_cur_x,
483                                         m_specific->m_cur_y))
484                                     {
485                                         on_ctrl_change();
486                                         force_redraw();
487                                     }
488                                 }
489                                 else
490                                 {
491                                     on_mouse_button_down(m_specific->m_cur_x,
492                                         m_specific->m_cur_y,
493                                         flags);
494                                 }
495                             }
496                         }
497                         break;
498                     case SDL_BUTTON_RIGHT:
499                         flags = mouse_right;
500                         on_mouse_button_down(m_specific->m_cur_x,
501                             m_specific->m_cur_y,
502                             flags);
503                         break;
504                     } //switch(event.button.button)
505                     break;
506 
507                 case SDL_MOUSEBUTTONUP:
508                     y = m_flip_y
509                         ? m_rbuf_window.height() - event.button.y
510                         : event.button.y;
511 
512                     m_specific->m_cur_x = event.button.x;
513                     m_specific->m_cur_y = y;
514                     flags = 0;
515                     if(m_ctrls.on_mouse_button_up(m_specific->m_cur_x,
516                                                   m_specific->m_cur_y))
517                     {
518                         on_ctrl_change();
519                         force_redraw();
520                     }
521                     on_mouse_button_up(m_specific->m_cur_x,
522                                        m_specific->m_cur_y,
523                                        flags);
524                     break;
525                 }
526             }
527         }
528         return 0;
529     }
530 
531 
532 
533     //------------------------------------------------------------------------
img_ext() const534     const char* platform_support::img_ext() const { return ".bmp"; }
535 
536     //------------------------------------------------------------------------
full_file_name(const char * file_name)537     const char* platform_support::full_file_name(const char* file_name)
538     {
539         return file_name;
540     }
541 
542     //------------------------------------------------------------------------
load_img(unsigned idx,const char * file)543     bool platform_support::load_img(unsigned idx, const char* file)
544     {
545         if(idx < max_images)
546         {
547             if(m_specific->m_surf_img[idx]) SDL_FreeSurface(m_specific->m_surf_img[idx]);
548 
549             char fn[1024];
550             strcpy(fn, file);
551             int len = strlen(fn);
552             if(len < 4 || strcmp(fn + len - 4, ".bmp") != 0)
553             {
554                 strcat(fn, ".bmp");
555             }
556 
557             SDL_Surface* tmp_surf = SDL_LoadBMP(fn);
558             if (tmp_surf == 0)
559             {
560                 fprintf(stderr, "Couldn't load %s: %s\n", fn, SDL_GetError());
561                 return false;
562             }
563 
564             SDL_PixelFormat format;
565             format.palette = 0;
566             format.BitsPerPixel = m_bpp;
567             format.BytesPerPixel = m_bpp >> 8;
568             format.Rmask = m_specific->m_rmask;
569             format.Gmask = m_specific->m_gmask;
570             format.Bmask = m_specific->m_bmask;
571             format.Amask = m_specific->m_amask;
572             format.Rshift = 0;
573             format.Gshift = 0;
574             format.Bshift = 0;
575             format.Ashift = 0;
576             format.Rloss = 0;
577             format.Gloss = 0;
578             format.Bloss = 0;
579             format.Aloss = 0;
580             format.colorkey = 0;
581             format.alpha = 0;
582 
583             m_specific->m_surf_img[idx] =
584                 SDL_ConvertSurface(tmp_surf,
585                                    &format,
586                                    SDL_SWSURFACE);
587 
588             SDL_FreeSurface(tmp_surf);
589 
590             if(m_specific->m_surf_img[idx] == 0) return false;
591 
592             m_rbuf_img[idx].attach((unsigned char*)m_specific->m_surf_img[idx]->pixels,
593                                    m_specific->m_surf_img[idx]->w,
594                                    m_specific->m_surf_img[idx]->h,
595                                    m_flip_y ? -m_specific->m_surf_img[idx]->pitch :
596                                                m_specific->m_surf_img[idx]->pitch);
597             return true;
598 
599         }
600         return false;
601     }
602 
603 
604 
605 
606     //------------------------------------------------------------------------
save_img(unsigned idx,const char * file)607     bool platform_support::save_img(unsigned idx, const char* file)
608     {
609         if(idx < max_images && m_specific->m_surf_img[idx])
610         {
611             char fn[1024];
612             strcpy(fn, file);
613             int len = strlen(fn);
614             if(len < 4 || strcmp(fn + len - 4, ".bmp") != 0)
615             {
616                 strcat(fn, ".bmp");
617             }
618             return SDL_SaveBMP(m_specific->m_surf_img[idx], fn) == 0;
619         }
620         return false;
621     }
622 
623 
624 
625     //------------------------------------------------------------------------
create_img(unsigned idx,unsigned width,unsigned height)626     bool platform_support::create_img(unsigned idx, unsigned width, unsigned height)
627     {
628         if(idx < max_images)
629         {
630 
631             if(m_specific->m_surf_img[idx]) SDL_FreeSurface(m_specific->m_surf_img[idx]);
632 
633              m_specific->m_surf_img[idx] =
634                  SDL_CreateRGBSurface(SDL_SWSURFACE,
635                                       width,
636                                       height,
637                                       m_specific->m_surf_screen->format->BitsPerPixel,
638                                       m_specific->m_rmask,
639                                       m_specific->m_gmask,
640                                       m_specific->m_bmask,
641                                       m_specific->m_amask);
642             if(m_specific->m_surf_img[idx] == 0)
643             {
644                 fprintf(stderr, "Couldn't create image: %s\n", SDL_GetError());
645                 return false;
646             }
647 
648             m_rbuf_img[idx].attach((unsigned char*)m_specific->m_surf_img[idx]->pixels,
649                                    m_specific->m_surf_img[idx]->w,
650                                    m_specific->m_surf_img[idx]->h,
651                                    m_flip_y ? -m_specific->m_surf_img[idx]->pitch :
652                                                m_specific->m_surf_img[idx]->pitch);
653 
654             return true;
655         }
656 
657         return false;
658     }
659 
660     //------------------------------------------------------------------------
start_timer()661     void platform_support::start_timer()
662     {
663         m_specific->m_sw_start = SDL_GetTicks();
664     }
665 
666     //------------------------------------------------------------------------
elapsed_time() const667     double platform_support::elapsed_time() const
668     {
669         int stop = SDL_GetTicks();
670         return double(stop - m_specific->m_sw_start);
671     }
672 
673     //------------------------------------------------------------------------
message(const char * msg)674     void platform_support::message(const char* msg)
675     {
676         fprintf(stderr, "%s\n", msg);
677     }
678 
679     //------------------------------------------------------------------------
force_redraw()680     void platform_support::force_redraw()
681     {
682         m_specific->m_update_flag = true;
683     }
684 
685 
686     //------------------------------------------------------------------------
on_init()687     void platform_support::on_init() {}
on_resize(int sx,int sy)688     void platform_support::on_resize(int sx, int sy) {}
on_idle()689     void platform_support::on_idle() {}
on_mouse_move(int x,int y,unsigned flags)690     void platform_support::on_mouse_move(int x, int y, unsigned flags) {}
on_mouse_button_down(int x,int y,unsigned flags)691     void platform_support::on_mouse_button_down(int x, int y, unsigned flags) {}
on_mouse_button_up(int x,int y,unsigned flags)692     void platform_support::on_mouse_button_up(int x, int y, unsigned flags) {}
on_key(int x,int y,unsigned key,unsigned flags)693     void platform_support::on_key(int x, int y, unsigned key, unsigned flags) {}
on_ctrl_change()694     void platform_support::on_ctrl_change() {}
on_draw()695     void platform_support::on_draw() {}
on_post_draw(void * raw_handler)696     void platform_support::on_post_draw(void* raw_handler) {}
697 
698 
699 }
700 
701 
702 int agg_main(int argc, char* argv[]);
703 
main(int argc,char * argv[])704 int main(int argc, char* argv[])
705 {
706     return agg_main(argc, argv);
707 }
708 
709