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