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) 2003 Hansruedi Baer (MacOS support, baer@karto.baug.eth.ch)
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 // Note from Hansruedi Baer:
27 // I tried to retain the original structure for the Win32 platform as far
28 // as possible. Currently, not all features are implemented but the examples
29 // should work properly.
30 // HB
31 //----------------------------------------------------------------------------
32
33 #include <Carbon.h>
34 #if defined(__MWERKS__)
35 #include "console.h"
36 #endif
37 #include <string.h>
38 #include <unistd.h>
39 #include "platform/agg_platform_support.h"
40 #include "platform/mac/agg_mac_pmap.h"
41 #include "util/agg_color_conv_rgb8.h"
42
43
44 namespace agg
45 {
46
47 pascal OSStatus DoWindowClose (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData);
48 pascal OSStatus DoWindowDrawContent (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData);
49 pascal OSStatus DoAppQuit (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData);
50 pascal OSStatus DoMouseDown (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData);
51 pascal OSStatus DoMouseUp (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData);
52 pascal OSStatus DoMouseDragged (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData);
53 pascal OSStatus DoKeyDown (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData);
54 pascal OSStatus DoKeyUp (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData);
55 pascal void DoPeriodicTask (EventLoopTimerRef theTimer, void* userData);
56
57
58 //------------------------------------------------------------------------
59 class platform_specific
60 {
61 public:
62 platform_specific(pix_format_e format, bool flip_y);
63
64 void create_pmap(unsigned width, unsigned height,
65 rendering_buffer* wnd);
66
67 void display_pmap(WindowRef window, const rendering_buffer* src);
68 bool load_pmap(const char* fn, unsigned idx,
69 rendering_buffer* dst);
70
71 bool save_pmap(const char* fn, unsigned idx,
72 const rendering_buffer* src);
73
74 unsigned translate(unsigned keycode);
75
76 pix_format_e m_format;
77 pix_format_e m_sys_format;
78 bool m_flip_y;
79 unsigned m_bpp;
80 unsigned m_sys_bpp;
81 WindowRef m_window;
82 pixel_map m_pmap_window;
83 pixel_map m_pmap_img[platform_support::max_images];
84 unsigned m_keymap[256];
85 unsigned m_last_translated_key;
86 int m_cur_x;
87 int m_cur_y;
88 unsigned m_input_flags;
89 bool m_redraw_flag;
90 UnsignedWide m_sw_freq;
91 UnsignedWide m_sw_start;
92 };
93
94
95 //------------------------------------------------------------------------
platform_specific(pix_format_e format,bool flip_y)96 platform_specific::platform_specific(pix_format_e format, bool flip_y) :
97 m_format(format),
98 m_sys_format(pix_format_undefined),
99 m_flip_y(flip_y),
100 m_bpp(0),
101 m_sys_bpp(0),
102 m_window(nil),
103 m_last_translated_key(0),
104 m_cur_x(0),
105 m_cur_y(0),
106 m_input_flags(0),
107 m_redraw_flag(true)
108 {
109 memset(m_keymap, 0, sizeof(m_keymap));
110
111 //Keyboard input is not yet fully supported nor tested
112 //m_keymap[VK_PAUSE] = key_pause;
113 m_keymap[kClearCharCode] = key_clear;
114
115 //m_keymap[VK_NUMPAD0] = key_kp0;
116 //m_keymap[VK_NUMPAD1] = key_kp1;
117 //m_keymap[VK_NUMPAD2] = key_kp2;
118 //m_keymap[VK_NUMPAD3] = key_kp3;
119 //m_keymap[VK_NUMPAD4] = key_kp4;
120 //m_keymap[VK_NUMPAD5] = key_kp5;
121 //m_keymap[VK_NUMPAD6] = key_kp6;
122 //m_keymap[VK_NUMPAD7] = key_kp7;
123 //m_keymap[VK_NUMPAD8] = key_kp8;
124 //m_keymap[VK_NUMPAD9] = key_kp9;
125 //m_keymap[VK_DECIMAL] = key_kp_period;
126 //m_keymap[VK_DIVIDE] = key_kp_divide;
127 //m_keymap[VK_MULTIPLY] = key_kp_multiply;
128 //m_keymap[VK_SUBTRACT] = key_kp_minus;
129 //m_keymap[VK_ADD] = key_kp_plus;
130
131 m_keymap[kUpArrowCharCode] = key_up;
132 m_keymap[kDownArrowCharCode] = key_down;
133 m_keymap[kRightArrowCharCode] = key_right;
134 m_keymap[kLeftArrowCharCode] = key_left;
135 //m_keymap[VK_INSERT] = key_insert;
136 m_keymap[kDeleteCharCode] = key_delete;
137 m_keymap[kHomeCharCode] = key_home;
138 m_keymap[kEndCharCode] = key_end;
139 m_keymap[kPageUpCharCode] = key_page_up;
140 m_keymap[kPageDownCharCode] = key_page_down;
141
142 //m_keymap[VK_F1] = key_f1;
143 //m_keymap[VK_F2] = key_f2;
144 //m_keymap[VK_F3] = key_f3;
145 //m_keymap[VK_F4] = key_f4;
146 //m_keymap[VK_F5] = key_f5;
147 //m_keymap[VK_F6] = key_f6;
148 //m_keymap[VK_F7] = key_f7;
149 //m_keymap[VK_F8] = key_f8;
150 //m_keymap[VK_F9] = key_f9;
151 //m_keymap[VK_F10] = key_f10;
152 //m_keymap[VK_F11] = key_f11;
153 //m_keymap[VK_F12] = key_f12;
154 //m_keymap[VK_F13] = key_f13;
155 //m_keymap[VK_F14] = key_f14;
156 //m_keymap[VK_F15] = key_f15;
157
158 //m_keymap[VK_NUMLOCK] = key_numlock;
159 //m_keymap[VK_CAPITAL] = key_capslock;
160 //m_keymap[VK_SCROLL] = key_scrollock;
161
162 switch(m_format)
163 {
164 case pix_format_gray8:
165 m_sys_format = pix_format_gray8;
166 m_bpp = 8;
167 m_sys_bpp = 8;
168 break;
169
170 case pix_format_rgb565:
171 case pix_format_rgb555:
172 m_sys_format = pix_format_rgb555;
173 m_bpp = 16;
174 m_sys_bpp = 16;
175 break;
176
177 case pix_format_rgb24:
178 case pix_format_bgr24:
179 m_sys_format = pix_format_rgb24;
180 m_bpp = 24;
181 m_sys_bpp = 24;
182 break;
183
184 case pix_format_bgra32:
185 case pix_format_abgr32:
186 case pix_format_argb32:
187 case pix_format_rgba32:
188 m_sys_format = pix_format_argb32;
189 m_bpp = 32;
190 m_sys_bpp = 32;
191 break;
192 }
193 ::Microseconds(&m_sw_freq);
194 ::Microseconds(&m_sw_start);
195 }
196
197
198 //------------------------------------------------------------------------
create_pmap(unsigned width,unsigned height,rendering_buffer * wnd)199 void platform_specific::create_pmap(unsigned width,
200 unsigned height,
201 rendering_buffer* wnd)
202 {
203 m_pmap_window.create(width, height, org_e(m_bpp));
204 wnd->attach(m_pmap_window.buf(),
205 m_pmap_window.width(),
206 m_pmap_window.height(),
207 m_flip_y ?
208 -m_pmap_window.row_bytes() :
209 m_pmap_window.row_bytes());
210 }
211
212
213 //------------------------------------------------------------------------
display_pmap(WindowRef window,const rendering_buffer * src)214 void platform_specific::display_pmap(WindowRef window, const rendering_buffer* src)
215 {
216 if(m_sys_format == m_format)
217 {
218 m_pmap_window.draw(window);
219 }
220 else
221 {
222 pixel_map pmap_tmp;
223 pmap_tmp.create(m_pmap_window.width(),
224 m_pmap_window.height(),
225 org_e(m_sys_bpp));
226
227 rendering_buffer rbuf_tmp;
228 rbuf_tmp.attach(pmap_tmp.buf(),
229 pmap_tmp.width(),
230 pmap_tmp.height(),
231 m_flip_y ?
232 -pmap_tmp.row_bytes() :
233 pmap_tmp.row_bytes());
234
235 switch(m_format)
236 {
237 case pix_format_gray8:
238 return;
239
240 case pix_format_rgb565:
241 color_conv(&rbuf_tmp, src, color_conv_rgb565_to_rgb555());
242 break;
243
244 case pix_format_bgr24:
245 color_conv(&rbuf_tmp, src, color_conv_bgr24_to_rgb24());
246 break;
247
248 case pix_format_abgr32:
249 color_conv(&rbuf_tmp, src, color_conv_abgr32_to_argb32());
250 break;
251
252 case pix_format_bgra32:
253 color_conv(&rbuf_tmp, src, color_conv_bgra32_to_argb32());
254 break;
255
256 case pix_format_rgba32:
257 color_conv(&rbuf_tmp, src, color_conv_rgba32_to_argb32());
258 break;
259 }
260 pmap_tmp.draw(window);
261 }
262 }
263
264
265 //------------------------------------------------------------------------
save_pmap(const char * fn,unsigned idx,const rendering_buffer * src)266 bool platform_specific::save_pmap(const char* fn, unsigned idx,
267 const rendering_buffer* src)
268 {
269 if(m_sys_format == m_format)
270 {
271 return m_pmap_img[idx].save_as_qt(fn);
272 }
273 else
274 {
275 pixel_map pmap_tmp;
276 pmap_tmp.create(m_pmap_img[idx].width(),
277 m_pmap_img[idx].height(),
278 org_e(m_sys_bpp));
279
280 rendering_buffer rbuf_tmp;
281 rbuf_tmp.attach(pmap_tmp.buf(),
282 pmap_tmp.width(),
283 pmap_tmp.height(),
284 m_flip_y ?
285 -pmap_tmp.row_bytes() :
286 pmap_tmp.row_bytes());
287 switch(m_format)
288 {
289 case pix_format_gray8:
290 return false;
291
292 case pix_format_rgb565:
293 color_conv(&rbuf_tmp, src, color_conv_rgb565_to_rgb555());
294 break;
295
296 case pix_format_rgb24:
297 color_conv(&rbuf_tmp, src, color_conv_rgb24_to_bgr24());
298 break;
299
300 case pix_format_abgr32:
301 color_conv(&rbuf_tmp, src, color_conv_abgr32_to_bgra32());
302 break;
303
304 case pix_format_argb32:
305 color_conv(&rbuf_tmp, src, color_conv_argb32_to_bgra32());
306 break;
307
308 case pix_format_rgba32:
309 color_conv(&rbuf_tmp, src, color_conv_rgba32_to_bgra32());
310 break;
311 }
312 return pmap_tmp.save_as_qt(fn);
313 }
314 return true;
315 }
316
317
318
319 //------------------------------------------------------------------------
load_pmap(const char * fn,unsigned idx,rendering_buffer * dst)320 bool platform_specific::load_pmap(const char* fn, unsigned idx,
321 rendering_buffer* dst)
322 {
323 pixel_map pmap_tmp;
324 if(!pmap_tmp.load_from_qt(fn)) return false;
325
326 rendering_buffer rbuf_tmp;
327 rbuf_tmp.attach(pmap_tmp.buf(),
328 pmap_tmp.width(),
329 pmap_tmp.height(),
330 m_flip_y ?
331 -pmap_tmp.row_bytes() :
332 pmap_tmp.row_bytes());
333
334 m_pmap_img[idx].create(pmap_tmp.width(),
335 pmap_tmp.height(),
336 org_e(m_bpp),
337 0);
338
339 dst->attach(m_pmap_img[idx].buf(),
340 m_pmap_img[idx].width(),
341 m_pmap_img[idx].height(),
342 m_flip_y ?
343 -m_pmap_img[idx].row_bytes() :
344 m_pmap_img[idx].row_bytes());
345
346 switch(m_format)
347 {
348 case pix_format_gray8:
349 return false;
350 break;
351
352 case pix_format_rgb555:
353 switch(pmap_tmp.bpp())
354 {
355 case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_rgb555()); break;
356 case 24: color_conv(dst, &rbuf_tmp, color_conv_rgb24_to_rgb555()); break;
357 case 32: color_conv(dst, &rbuf_tmp, color_conv_argb32_to_rgb555()); break;
358 }
359 break;
360
361 case pix_format_rgb565:
362 switch(pmap_tmp.bpp())
363 {
364 case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_rgb565()); break;
365 case 24: color_conv(dst, &rbuf_tmp, color_conv_rgb24_to_rgb565()); break;
366 case 32: color_conv(dst, &rbuf_tmp, color_conv_argb32_to_rgb565()); break;
367 }
368 break;
369
370 case pix_format_rgb24:
371 switch(pmap_tmp.bpp())
372 {
373 case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_rgb24()); break;
374 case 24: color_conv(dst, &rbuf_tmp, color_conv_rgb24_to_rgb24()); break;
375 case 32: color_conv(dst, &rbuf_tmp, color_conv_argb32_to_rgb24()); break;
376 }
377 break;
378
379 case pix_format_bgr24:
380 switch(pmap_tmp.bpp())
381 {
382 case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_bgr24()); break;
383 case 24: color_conv(dst, &rbuf_tmp, color_conv_rgb24_to_bgr24()); break;
384 case 32: color_conv(dst, &rbuf_tmp, color_conv_argb32_to_bgr24()); break;
385 }
386 break;
387
388 case pix_format_abgr32:
389 switch(pmap_tmp.bpp())
390 {
391 case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_abgr32()); break;
392 case 24: color_conv(dst, &rbuf_tmp, color_conv_rgb24_to_abgr32()); break;
393 case 32: color_conv(dst, &rbuf_tmp, color_conv_argb32_to_abgr32()); break;
394 }
395 break;
396
397 case pix_format_argb32:
398 switch(pmap_tmp.bpp())
399 {
400 case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_argb32()); break;
401 case 24: color_conv(dst, &rbuf_tmp, color_conv_rgb24_to_argb32()); break;
402 case 32: color_conv(dst, &rbuf_tmp, color_conv_argb32_to_argb32()); break;
403 }
404 break;
405
406 case pix_format_bgra32:
407 switch(pmap_tmp.bpp())
408 {
409 case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_bgra32()); break;
410 case 24: color_conv(dst, &rbuf_tmp, color_conv_rgb24_to_bgra32()); break;
411 case 32: color_conv(dst, &rbuf_tmp, color_conv_argb32_to_bgra32()); break;
412 }
413 break;
414
415 case pix_format_rgba32:
416 switch(pmap_tmp.bpp())
417 {
418 case 16: color_conv(dst, &rbuf_tmp, color_conv_rgb555_to_rgba32()); break;
419 case 24: color_conv(dst, &rbuf_tmp, color_conv_rgb24_to_rgba32()); break;
420 case 32: color_conv(dst, &rbuf_tmp, color_conv_argb32_to_rgba32()); break;
421 }
422 break;
423 }
424
425 return true;
426 }
427
428
429
430
431
432
433
434
435 //------------------------------------------------------------------------
translate(unsigned keycode)436 unsigned platform_specific::translate(unsigned keycode)
437 {
438 return m_last_translated_key = (keycode > 255) ? 0 : m_keymap[keycode];
439 }
440
441
442
443 //------------------------------------------------------------------------
platform_support(pix_format_e format,bool flip_y)444 platform_support::platform_support(pix_format_e format, bool flip_y) :
445 m_specific(new platform_specific(format, flip_y)),
446 m_format(format),
447 m_bpp(m_specific->m_bpp),
448 m_window_flags(0),
449 m_wait_mode(true),
450 m_flip_y(flip_y),
451 m_initial_width(10),
452 m_initial_height(10)
453 {
454 strcpy(m_caption, "Anti-Grain Geometry Application");
455 }
456
457
458 //------------------------------------------------------------------------
~platform_support()459 platform_support::~platform_support()
460 {
461 delete m_specific;
462 }
463
464
465
466 //------------------------------------------------------------------------
caption(const char * cap)467 void platform_support::caption(const char* cap)
468 {
469 strcpy(m_caption, cap);
470 if(m_specific->m_window)
471 {
472 SetWindowTitleWithCFString (m_specific->m_window, CFStringCreateWithCStringNoCopy (nil, cap, kCFStringEncodingASCII, nil));
473 }
474 }
475
476
477
478 //------------------------------------------------------------------------
get_key_flags(UInt32 wflags)479 static unsigned get_key_flags(UInt32 wflags)
480 {
481 unsigned flags = 0;
482
483 if(wflags & shiftKey) flags |= kbd_shift;
484 if(wflags & controlKey) flags |= kbd_ctrl;
485
486 return flags;
487 }
488
489
490 //------------------------------------------------------------------------
message(const char * msg)491 void platform_support::message(const char* msg)
492 {
493 SInt16 item;
494 Str255 p_msg;
495
496 ::CopyCStringToPascal (msg, p_msg);
497 ::StandardAlert (kAlertPlainAlert, (const unsigned char*) "\013AGG Message", p_msg, NULL, &item);
498 //::StandardAlert (kAlertPlainAlert, (const unsigned char*) "\pAGG Message", p_msg, NULL, &item);
499 }
500
501
502 //------------------------------------------------------------------------
start_timer()503 void platform_support::start_timer()
504 {
505 ::Microseconds (&(m_specific->m_sw_start));
506 }
507
508
509 //------------------------------------------------------------------------
elapsed_time() const510 double platform_support::elapsed_time() const
511 {
512 UnsignedWide stop;
513 ::Microseconds(&stop);
514 return double(stop.lo -
515 m_specific->m_sw_start.lo) * 1e6 /
516 double(m_specific->m_sw_freq.lo);
517 }
518
519
520 //------------------------------------------------------------------------
init(unsigned width,unsigned height,unsigned flags)521 bool platform_support::init(unsigned width, unsigned height, unsigned flags)
522 {
523 if(m_specific->m_sys_format == pix_format_undefined)
524 {
525 return false;
526 }
527
528 m_window_flags = flags;
529
530 // application
531 EventTypeSpec eventType;
532 EventHandlerUPP handlerUPP;
533
534 eventType.eventClass = kEventClassApplication;
535 eventType.eventKind = kEventAppQuit;
536
537 handlerUPP = NewEventHandlerUPP(DoAppQuit);
538
539 InstallApplicationEventHandler (handlerUPP, 1, &eventType, nil, nil);
540
541 eventType.eventClass = kEventClassMouse;
542 eventType.eventKind = kEventMouseDown;
543 handlerUPP = NewEventHandlerUPP(DoMouseDown);
544 InstallApplicationEventHandler (handlerUPP, 1, &eventType, this, nil);
545
546 eventType.eventKind = kEventMouseUp;
547 handlerUPP = NewEventHandlerUPP(DoMouseUp);
548 InstallApplicationEventHandler (handlerUPP, 1, &eventType, this, nil);
549
550 eventType.eventKind = kEventMouseDragged;
551 handlerUPP = NewEventHandlerUPP(DoMouseDragged);
552 InstallApplicationEventHandler (handlerUPP, 1, &eventType, this, nil);
553
554 eventType.eventClass = kEventClassKeyboard;
555 eventType.eventKind = kEventRawKeyDown;
556 handlerUPP = NewEventHandlerUPP(DoKeyDown);
557 InstallApplicationEventHandler (handlerUPP, 1, &eventType, this, nil);
558
559 eventType.eventKind = kEventRawKeyUp;
560 handlerUPP = NewEventHandlerUPP(DoKeyUp);
561 InstallApplicationEventHandler (handlerUPP, 1, &eventType, this, nil);
562
563 eventType.eventKind = kEventRawKeyRepeat;
564 handlerUPP = NewEventHandlerUPP(DoKeyDown); // 'key repeat' is translated to 'key down'
565 InstallApplicationEventHandler (handlerUPP, 1, &eventType, this, nil);
566
567 WindowAttributes windowAttrs;
568 Rect bounds;
569
570 // window
571 windowAttrs = kWindowCloseBoxAttribute | kWindowCollapseBoxAttribute | kWindowStandardHandlerAttribute;
572 SetRect (&bounds, 0, 0, width, height);
573 OffsetRect (&bounds, 100, 100);
574 CreateNewWindow (kDocumentWindowClass, windowAttrs, &bounds, &m_specific->m_window);
575
576 if(m_specific->m_window == nil)
577 {
578 return false;
579 }
580
581 // I assume the text is ASCII.
582 // Change to kCFStringEncodingMacRoman, kCFStringEncodingISOLatin1, kCFStringEncodingUTF8 or what else you need.
583 SetWindowTitleWithCFString (m_specific->m_window, CFStringCreateWithCStringNoCopy (nil, m_caption, kCFStringEncodingASCII, nil));
584
585 eventType.eventClass = kEventClassWindow;
586 eventType.eventKind = kEventWindowClose;
587
588 handlerUPP = NewEventHandlerUPP(DoWindowClose);
589 InstallWindowEventHandler (m_specific->m_window, handlerUPP, 1, &eventType, this, NULL);
590
591 eventType.eventKind = kEventWindowDrawContent;
592 handlerUPP = NewEventHandlerUPP(DoWindowDrawContent);
593 InstallWindowEventHandler (m_specific->m_window, handlerUPP, 1, &eventType, this, NULL);
594
595 // Periodic task
596 // Instead of an idle function I use the Carbon event timer.
597 // You may decide to change the wait value which is currently 50 milliseconds.
598 EventLoopRef mainLoop;
599 EventLoopTimerUPP timerUPP;
600 EventLoopTimerRef theTimer;
601
602 mainLoop = GetMainEventLoop();
603 timerUPP = NewEventLoopTimerUPP (DoPeriodicTask);
604 InstallEventLoopTimer (mainLoop, 0, 50 * kEventDurationMillisecond, timerUPP, this, &theTimer);
605
606 m_specific->create_pmap(width, height, &m_rbuf_window);
607 m_initial_width = width;
608 m_initial_height = height;
609 on_init();
610 on_resize(width, height);
611 m_specific->m_redraw_flag = true;
612
613 ShowWindow (m_specific->m_window);
614 SetPortWindowPort (m_specific->m_window);
615
616 return true;
617 }
618
619
620 //------------------------------------------------------------------------
run()621 int platform_support::run()
622 {
623
624 RunApplicationEventLoop ();
625 return true;
626 }
627
628
629 //------------------------------------------------------------------------
img_ext() const630 const char* platform_support::img_ext() const { return ".bmp"; }
631
632 //------------------------------------------------------------------------
full_file_name(const char * file_name)633 const char* platform_support::full_file_name(const char* file_name)
634 {
635 return file_name;
636 }
637
638 //------------------------------------------------------------------------
load_img(unsigned idx,const char * file)639 bool platform_support::load_img(unsigned idx, const char* file)
640 {
641 if(idx < max_images)
642 {
643 char fn[1024];
644 strcpy(fn, file);
645 int len = strlen(fn);
646 #if defined(__MWERKS__)
647 if(len < 4 || stricmp(fn + len - 4, ".BMP") != 0)
648 #else
649 if(len < 4 || strncasecmp(fn + len - 4, ".BMP", 4) != 0)
650 #endif
651 {
652 strcat(fn, ".bmp");
653 }
654 return m_specific->load_pmap(fn, idx, &m_rbuf_img[idx]);
655 }
656 return true;
657 }
658
659
660
661 //------------------------------------------------------------------------
save_img(unsigned idx,const char * file)662 bool platform_support::save_img(unsigned idx, const char* file)
663 {
664 if(idx < max_images)
665 {
666 char fn[1024];
667 strcpy(fn, file);
668 int len = strlen(fn);
669 #if defined(__MWERKS__)
670 if(len < 4 || stricmp(fn + len - 4, ".BMP") != 0)
671 #else
672 if(len < 4 || strncasecmp(fn + len - 4, ".BMP", 4) != 0)
673 #endif
674 {
675 strcat(fn, ".bmp");
676 }
677 return m_specific->save_pmap(fn, idx, &m_rbuf_img[idx]);
678 }
679 return true;
680 }
681
682
683
684 //------------------------------------------------------------------------
create_img(unsigned idx,unsigned width,unsigned height)685 bool platform_support::create_img(unsigned idx, unsigned width, unsigned height)
686 {
687 if(idx < max_images)
688 {
689 if(width == 0) width = m_specific->m_pmap_window.width();
690 if(height == 0) height = m_specific->m_pmap_window.height();
691 m_specific->m_pmap_img[idx].create(width, height, org_e(m_specific->m_bpp));
692 m_rbuf_img[idx].attach(m_specific->m_pmap_img[idx].buf(),
693 m_specific->m_pmap_img[idx].width(),
694 m_specific->m_pmap_img[idx].height(),
695 m_flip_y ?
696 -m_specific->m_pmap_img[idx].row_bytes() :
697 m_specific->m_pmap_img[idx].row_bytes());
698 return true;
699 }
700 return false;
701 }
702
703
704 //------------------------------------------------------------------------
force_redraw()705 void platform_support::force_redraw()
706 {
707 Rect bounds;
708
709 m_specific->m_redraw_flag = true;
710 // on_ctrl_change ();
711 on_draw();
712
713 SetRect(&bounds, 0, 0, m_rbuf_window.width(), m_rbuf_window.height());
714 InvalWindowRect(m_specific->m_window, &bounds);
715 }
716
717
718
719 //------------------------------------------------------------------------
update_window()720 void platform_support::update_window()
721 {
722 m_specific->display_pmap(m_specific->m_window, &m_rbuf_window);
723 }
724
725
726 //------------------------------------------------------------------------
on_init()727 void platform_support::on_init() {}
on_resize(int sx,int sy)728 void platform_support::on_resize(int sx, int sy) {}
on_idle()729 void platform_support::on_idle() {}
on_mouse_move(int x,int y,unsigned flags)730 void platform_support::on_mouse_move(int x, int y, unsigned flags) {}
on_mouse_button_down(int x,int y,unsigned flags)731 void platform_support::on_mouse_button_down(int x, int y, unsigned flags) {}
on_mouse_button_up(int x,int y,unsigned flags)732 void platform_support::on_mouse_button_up(int x, int y, unsigned flags) {}
on_key(int x,int y,unsigned key,unsigned flags)733 void platform_support::on_key(int x, int y, unsigned key, unsigned flags) {}
on_ctrl_change()734 void platform_support::on_ctrl_change() {}
on_draw()735 void platform_support::on_draw() {}
on_post_draw(void * raw_handler)736 void platform_support::on_post_draw(void* raw_handler) {}
737
738
739 //------------------------------------------------------------------------
DoWindowClose(EventHandlerCallRef nextHandler,EventRef theEvent,void * userData)740 pascal OSStatus DoWindowClose (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData)
741 {
742 userData;
743
744 QuitApplicationEventLoop ();
745
746 return CallNextEventHandler (nextHandler, theEvent);
747 }
748
749
750 //------------------------------------------------------------------------
DoAppQuit(EventHandlerCallRef nextHandler,EventRef theEvent,void * userData)751 pascal OSStatus DoAppQuit (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData)
752 {
753 userData;
754
755 return CallNextEventHandler (nextHandler, theEvent);
756 }
757
758
759 //------------------------------------------------------------------------
DoMouseDown(EventHandlerCallRef nextHandler,EventRef theEvent,void * userData)760 pascal OSStatus DoMouseDown (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData)
761 {
762 Point wheresMyMouse;
763 UInt32 modifier;
764
765 GetEventParameter (theEvent, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &wheresMyMouse);
766 GlobalToLocal (&wheresMyMouse);
767 GetEventParameter (theEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifier);
768
769 platform_support * app = reinterpret_cast<platform_support*>(userData);
770
771 app->m_specific->m_cur_x = wheresMyMouse.h;
772 if(app->flip_y())
773 {
774 app->m_specific->m_cur_y = app->rbuf_window().height() - wheresMyMouse.v;
775 }
776 else
777 {
778 app->m_specific->m_cur_y = wheresMyMouse.v;
779 }
780 app->m_specific->m_input_flags = mouse_left | get_key_flags(modifier);
781
782 app->m_ctrls.set_cur(app->m_specific->m_cur_x,
783 app->m_specific->m_cur_y);
784 if(app->m_ctrls.on_mouse_button_down(app->m_specific->m_cur_x,
785 app->m_specific->m_cur_y))
786 {
787 app->on_ctrl_change();
788 app->force_redraw();
789 }
790 else
791 {
792 if(app->m_ctrls.in_rect(app->m_specific->m_cur_x,
793 app->m_specific->m_cur_y))
794 {
795 if(app->m_ctrls.set_cur(app->m_specific->m_cur_x,
796 app->m_specific->m_cur_y))
797 {
798 app->on_ctrl_change();
799 app->force_redraw();
800 }
801 }
802 else
803 {
804 app->on_mouse_button_down(app->m_specific->m_cur_x,
805 app->m_specific->m_cur_y,
806 app->m_specific->m_input_flags);
807 }
808 }
809
810 return CallNextEventHandler (nextHandler, theEvent);
811 }
812
813
814 //------------------------------------------------------------------------
DoMouseUp(EventHandlerCallRef nextHandler,EventRef theEvent,void * userData)815 pascal OSStatus DoMouseUp (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData)
816 {
817 Point wheresMyMouse;
818 UInt32 modifier;
819
820 GetEventParameter (theEvent, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &wheresMyMouse);
821 GlobalToLocal (&wheresMyMouse);
822 GetEventParameter (theEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifier);
823
824 platform_support * app = reinterpret_cast<platform_support*>(userData);
825
826 app->m_specific->m_cur_x = wheresMyMouse.h;
827 if(app->flip_y())
828 {
829 app->m_specific->m_cur_y = app->rbuf_window().height() - wheresMyMouse.v;
830 }
831 else
832 {
833 app->m_specific->m_cur_y = wheresMyMouse.v;
834 }
835 app->m_specific->m_input_flags = mouse_left | get_key_flags(modifier);
836
837 if(app->m_ctrls.on_mouse_button_up(app->m_specific->m_cur_x,
838 app->m_specific->m_cur_y))
839 {
840 app->on_ctrl_change();
841 app->force_redraw();
842 }
843 app->on_mouse_button_up(app->m_specific->m_cur_x,
844 app->m_specific->m_cur_y,
845 app->m_specific->m_input_flags);
846
847 return CallNextEventHandler (nextHandler, theEvent);
848 }
849
850
851 //------------------------------------------------------------------------
DoMouseDragged(EventHandlerCallRef nextHandler,EventRef theEvent,void * userData)852 pascal OSStatus DoMouseDragged (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData)
853 {
854 Point wheresMyMouse;
855 UInt32 modifier;
856
857 GetEventParameter (theEvent, kEventParamMouseLocation, typeQDPoint, NULL, sizeof(Point), NULL, &wheresMyMouse);
858 GlobalToLocal (&wheresMyMouse);
859 GetEventParameter (theEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifier);
860
861 platform_support * app = reinterpret_cast<platform_support*>(userData);
862
863 app->m_specific->m_cur_x = wheresMyMouse.h;
864 if(app->flip_y())
865 {
866 app->m_specific->m_cur_y = app->rbuf_window().height() - wheresMyMouse.v;
867 }
868 else
869 {
870 app->m_specific->m_cur_y = wheresMyMouse.v;
871 }
872 app->m_specific->m_input_flags = mouse_left | get_key_flags(modifier);
873
874
875 if(app->m_ctrls.on_mouse_move(
876 app->m_specific->m_cur_x,
877 app->m_specific->m_cur_y,
878 (app->m_specific->m_input_flags & mouse_left) != 0))
879 {
880 app->on_ctrl_change();
881 app->force_redraw();
882 }
883 else
884 {
885 app->on_mouse_move(app->m_specific->m_cur_x,
886 app->m_specific->m_cur_y,
887 app->m_specific->m_input_flags);
888 }
889
890 return CallNextEventHandler (nextHandler, theEvent);
891 }
892
893
894 //------------------------------------------------------------------------
DoKeyDown(EventHandlerCallRef nextHandler,EventRef theEvent,void * userData)895 pascal OSStatus DoKeyDown (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData)
896 {
897 char key_code;
898 UInt32 modifier;
899
900 GetEventParameter (theEvent, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(char), NULL, &key_code);
901 GetEventParameter (theEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifier);
902
903 platform_support * app = reinterpret_cast<platform_support*>(userData);
904
905 app->m_specific->m_last_translated_key = 0;
906 switch(modifier)
907 {
908 case controlKey:
909 app->m_specific->m_input_flags |= kbd_ctrl;
910 break;
911
912 case shiftKey:
913 app->m_specific->m_input_flags |= kbd_shift;
914 break;
915
916 default:
917 app->m_specific->translate(key_code);
918 break;
919 }
920
921 if(app->m_specific->m_last_translated_key)
922 {
923 bool left = false;
924 bool up = false;
925 bool right = false;
926 bool down = false;
927
928 switch(app->m_specific->m_last_translated_key)
929 {
930 case key_left:
931 left = true;
932 break;
933
934 case key_up:
935 up = true;
936 break;
937
938 case key_right:
939 right = true;
940 break;
941
942 case key_down:
943 down = true;
944 break;
945
946 //On a Mac, screenshots are handled by the system.
947 case key_f2:
948 app->copy_window_to_img(agg::platform_support::max_images - 1);
949 app->save_img(agg::platform_support::max_images - 1, "screenshot");
950 break;
951 }
952
953
954 if(app->m_ctrls.on_arrow_keys(left, right, down, up))
955 {
956 app->on_ctrl_change();
957 app->force_redraw();
958 }
959 else
960 {
961 app->on_key(app->m_specific->m_cur_x,
962 app->m_specific->m_cur_y,
963 app->m_specific->m_last_translated_key,
964 app->m_specific->m_input_flags);
965 }
966 }
967
968 return CallNextEventHandler (nextHandler, theEvent);
969 }
970
971
972 //------------------------------------------------------------------------
DoKeyUp(EventHandlerCallRef nextHandler,EventRef theEvent,void * userData)973 pascal OSStatus DoKeyUp (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData)
974 {
975 char key_code;
976 UInt32 modifier;
977
978 GetEventParameter (theEvent, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(char), NULL, &key_code);
979 GetEventParameter (theEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifier);
980
981 platform_support * app = reinterpret_cast<platform_support*>(userData);
982
983 app->m_specific->m_last_translated_key = 0;
984 switch(modifier)
985 {
986 case controlKey:
987 app->m_specific->m_input_flags &= ~kbd_ctrl;
988 break;
989
990 case shiftKey:
991 app->m_specific->m_input_flags &= ~kbd_shift;
992 break;
993 }
994
995 return CallNextEventHandler (nextHandler, theEvent);
996 }
997
998
999 //------------------------------------------------------------------------
DoWindowDrawContent(EventHandlerCallRef nextHandler,EventRef theEvent,void * userData)1000 pascal OSStatus DoWindowDrawContent (EventHandlerCallRef nextHandler, EventRef theEvent, void* userData)
1001 {
1002 platform_support * app = reinterpret_cast<platform_support*>(userData);
1003
1004 if(app)
1005 {
1006 if(app->m_specific->m_redraw_flag)
1007 {
1008 app->on_draw();
1009 app->m_specific->m_redraw_flag = false;
1010 }
1011 app->m_specific->display_pmap(app->m_specific->m_window, &app->rbuf_window());
1012 }
1013
1014 return CallNextEventHandler (nextHandler, theEvent);
1015 }
1016
1017
1018 //------------------------------------------------------------------------
DoPeriodicTask(EventLoopTimerRef theTimer,void * userData)1019 pascal void DoPeriodicTask (EventLoopTimerRef theTimer, void* userData)
1020 {
1021 platform_support * app = reinterpret_cast<platform_support*>(userData);
1022
1023 if(!app->wait_mode())
1024 app->on_idle();
1025 }
1026
1027
1028 }
1029
1030
1031
1032
1033 //----------------------------------------------------------------------------
1034 int agg_main(int argc, char* argv[]);
1035
1036
1037 // Hm. Classic MacOS does not know command line input.
1038 // CodeWarrior provides a way to mimic command line input.
1039 // The function 'ccommand' can be used to get the command
1040 // line arguments.
1041 //----------------------------------------------------------------------------
main(int argc,char * argv[])1042 int main(int argc, char* argv[])
1043 {
1044 #if defined(__MWERKS__)
1045 // argc = ccommand (&argv);
1046 #endif
1047
1048 // Check if we are launched by double-clicking under OSX
1049 // Get rid of extra argument, this will confuse the standard argument parsing
1050 // calls used in the examples to get the name of the image file to be used
1051 if ( argc >= 2 && strncmp (argv[1], "-psn", 4) == 0 ) {
1052 argc = 1;
1053 }
1054
1055 launch:
1056 return agg_main(argc, argv);
1057 }