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