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