summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/corelib/render/software/platform/linux/agg_platform_support.pas5030
-rw-r--r--src/corelib/render/software/platform/linux/file_utils_.pas1552
-rw-r--r--src/corelib/render/software/platform/mac/agg_mac_pmap.pas942
-rw-r--r--src/corelib/render/software/platform/mac/agg_platform_support.pas4424
-rw-r--r--src/corelib/render/software/platform/mac/file_utils_.pas1692
-rw-r--r--src/corelib/render/software/platform/win/agg_platform_support.pas4242
-rw-r--r--src/corelib/render/software/platform/win/agg_win32_bmp.pas1438
-rw-r--r--src/corelib/render/software/platform/win/file_utils_.pas1552
8 files changed, 10436 insertions, 10436 deletions
diff --git a/src/corelib/render/software/platform/linux/agg_platform_support.pas b/src/corelib/render/software/platform/linux/agg_platform_support.pas
index cd3b33ac..8b14eb4e 100644
--- a/src/corelib/render/software/platform/linux/agg_platform_support.pas
+++ b/src/corelib/render/software/platform/linux/agg_platform_support.pas
@@ -1,2515 +1,2515 @@
-//----------------------------------------------------------------------------
-// Anti-Grain Geometry - Version 2.4 (Public License)
-// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
-//
-// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
-// Pascal Port By: Milan Marusinec alias Milano
-// milan@marusinec.sk
-// http://www.aggpas.org
-// Copyright (c) 2005-2006
-//
-// Permission to copy, use, modify, sell and distribute this software
-// is granted provided this copyright notice appears in all copies.
-// This software is provided "as is" without express or implied
-// warranty, and with no claim as to its suitability for any purpose.
-//
-//----------------------------------------------------------------------------
-// Contact: mcseem@antigrain.com
-// mcseemagg@yahoo.com
-// http://www.antigrain.com
-//
-//----------------------------------------------------------------------------
-//
-// class platform_support
-//
-// It's not a part of the AGG library, it's just a helper class to create
-// interactive demo examples. Since the examples should not be too complex
-// this class is provided to support some very basic interactive graphical
-// funtionality, such as putting the rendered image to the window, simple
-// keyboard and mouse input, window resizing, setting the window title,
-// and catching the "idle" events.
-//
-// The most popular platforms are:
-//
-// Windows-32 API
-// X-Window API
-// SDL library (see http://www.libsdl.org/)
-// MacOS C/C++ API
-//
-// All the system dependent stuff sits in the platform_specific class.
-// The platform_support class has just a pointer to it and it's
-// the responsibility of the implementation to create/delete it.
-// This class being defined in the implementation file can have
-// any platform dependent stuff such as HWND, X11 Window and so on.
-//
-// [Pascal Port History] -----------------------------------------------------
-//
-// 23.06.2006-Milano: ptrcomp adjustments
-// 29.03.2006-Milano: finished & tested OK
-// 28.03.2006-Milano: platform_specific & platform_support
-// 20.03.2006-Milano: Unit port establishment
-//
-{ agg_platform_support.pas }
-unit
- agg_platform_support ;
-
-INTERFACE
-
-{$I agg_mode.inc }
-{$I- }
-uses
- X ,Xlib ,Xutil ,Xatom ,keysym ,CTypes ,SysUtils ,
- agg_linux_mini_libc ,
- agg_basics ,
- agg_ctrl ,
- agg_rendering_buffer ,
- agg_trans_affine ,
- agg_trans_viewport ,
- agg_color_conv ,
- file_utils_ ;
-
-const
- {$IFDEF Ver2_2}
- xFalse = False;
- xTrue = True;
- {$ELSE}
- xFalse = 0;
- xTrue = 1;
- {$ENDIF}
-
-{ TYPES DEFINITION }
-const
-//----------------------------------------------------------window_flag_e
-// These are flags used in method init(). Not all of them are
-// applicable on different platforms, for example the win32_api
-// cannot use a hardware buffer (window_hw_buffer).
-// The implementation should simply ignore unsupported flags.
- window_resize = 1;
- window_hw_buffer = 2;
- window_keep_aspect_ratio = 4;
- window_process_all_keys = 8;
-
-type
-//-----------------------------------------------------------pix_format_e
-// Possible formats of the rendering buffer. Initially I thought that it's
-// reasonable to create the buffer and the rendering functions in
-// accordance with the native pixel format of the system because it
-// would have no overhead for pixel format conversion.
-// But eventually I came to a conclusion that having a possibility to
-// convert pixel formats on demand is a good idea. First, it was X11 where
-// there lots of different formats and visuals and it would be great to
-// render everything in, say, RGB-24 and display it automatically without
-// any additional efforts. The second reason is to have a possibility to
-// debug renderers for different pixel formats and colorspaces having only
-// one computer and one system.
-//
-// This stuff is not included into the basic AGG functionality because the
-// number of supported pixel formats (and/or colorspaces) can be great and
-// if one needs to add new format it would be good only to add new
-// rendering files without having to modify any existing ones (a general
-// principle of incapsulation and isolation).
-//
-// Using a particular pixel format doesn't obligatory mean the necessity
-// of software conversion. For example, win32 API can natively display
-// gray8, 15-bit RGB, 24-bit BGR, and 32-bit BGRA formats.
-// This list can be (and will be!) extended in future.
- pix_format_e = (
-
- pix_format_undefined , // By default. No conversions are applied
- pix_format_bw, // 1 bit per color B/W
- pix_format_gray8, // Simple 256 level grayscale
- pix_format_gray16, // Simple 65535 level grayscale
- pix_format_rgb555, // 15 bit rgb. Depends on the byte ordering!
- pix_format_rgb565, // 16 bit rgb. Depends on the byte ordering!
- pix_format_rgbAAA, // 30 bit rgb. Depends on the byte ordering!
- pix_format_rgbBBA, // 32 bit rgb. Depends on the byte ordering!
- pix_format_bgrAAA, // 30 bit bgr. Depends on the byte ordering!
- pix_format_bgrABB, // 32 bit bgr. Depends on the byte ordering!
- pix_format_rgb24, // R-G-B, one byte per color component
- pix_format_bgr24, // B-G-R, native win32 BMP format.
- pix_format_rgba32, // R-G-B-A, one byte per color component
- pix_format_argb32, // A-R-G-B, native MAC format
- pix_format_abgr32, // A-B-G-R, one byte per color component
- pix_format_bgra32, // B-G-R-A, native win32 BMP format
- pix_format_rgb48, // R-G-B, 16 bits per color component
- pix_format_bgr48, // B-G-R, native win32 BMP format.
- pix_format_rgba64, // R-G-B-A, 16 bits byte per color component
- pix_format_argb64, // A-R-G-B, native MAC format
- pix_format_abgr64, // A-B-G-R, one byte per color component
- pix_format_bgra64, // B-G-R-A, native win32 BMP format
-
- end_of_pix_formats );
-
-const
-//-------------------------------------------------------------input_flag_e
-// Mouse and keyboard flags. They can be different on different platforms
-// and the ways they are obtained are also different. But in any case
-// the system dependent flags should be mapped into these ones. The meaning
-// of that is as follows. For example, if kbd_ctrl is set it means that the
-// ctrl key is pressed and being held at the moment. They are also used in
-// the overridden methods such as on_mouse_move(), on_mouse_button_down(),
-// on_mouse_button_dbl_click(), on_mouse_button_up(), on_key().
-// In the method on_mouse_button_up() the mouse flags have different
-// meaning. They mean that the respective button is being released, but
-// the meaning of the keyboard flags remains the same.
-// There's absolut minimal set of flags is used because they'll be most
-// probably supported on different platforms. Even the mouse_right flag
-// is restricted because Mac's mice have only one button, but AFAIK
-// it can be simulated with holding a special key on the keydoard.
- mouse_left = 1;
- mouse_right = 2;
- kbd_shift = 4;
- kbd_ctrl = 8;
-
-//--------------------------------------------------------------key_code_e
-// Keyboard codes. There's also a restricted set of codes that are most
-// probably supported on different platforms. Any platform dependent codes
-// should be converted into these ones. There're only those codes are
-// defined that cannot be represented as printable ASCII-characters.
-// All printable ASCII-set can be used in a regilar C/C++ manner:
-// ' ', 'A', '0' '+' and so on.
-// Since the clasas is used for creating very simple demo-applications
-// we don't need very rich possibilities here, just basic ones.
-// Actually the numeric key codes are taken from the SDL library, so,
-// the implementation of the SDL support does not require any mapping.
-// ASCII set. Should be supported everywhere
- key_backspace = 8;
- key_tab = 9;
- key_clear = 12;
- key_return = 13;
- key_pause = 19;
- key_escape = 27;
-
-// Keypad
- key_delete = 127;
- key_kp0 = 256;
- key_kp1 = 257;
- key_kp2 = 258;
- key_kp3 = 259;
- key_kp4 = 260;
- key_kp5 = 261;
- key_kp6 = 262;
- key_kp7 = 263;
- key_kp8 = 264;
- key_kp9 = 265;
- key_kp_period = 266;
- key_kp_divide = 267;
- key_kp_multiply = 268;
- key_kp_minus = 269;
- key_kp_plus = 270;
- key_kp_enter = 271;
- key_kp_equals = 272;
-
-// Arrow-keys and stuff
- key_up = 273;
- key_down = 274;
- key_right = 275;
- key_left = 276;
- key_insert = 277;
- key_home = 278;
- key_end = 279;
- key_page_up = 280;
- key_page_down = 281;
-
-// Functional keys. You'd better avoid using
-// f11...f15 in your applications if you want
-// the applications to be portable
- key_f1 = 282;
- key_f2 = 283;
- key_f3 = 284;
- key_f4 = 285;
- key_f5 = 286;
- key_f6 = 287;
- key_f7 = 288;
- key_f8 = 289;
- key_f9 = 290;
- key_f10 = 291;
- key_f11 = 292;
- key_f12 = 293;
- key_f13 = 294;
- key_f14 = 295;
- key_f15 = 296;
-
-// The possibility of using these keys is
-// very restricted. Actually it's guaranteed
-// only in win32_api and win32_sdl implementations
- key_numlock = 300;
- key_capslock = 301;
- key_scrollock = 302;
-
- max_ctrl = 128;
-
-type
-//----------------------------------------------------------ctrl_container
-// A helper class that contains pointers to a number of controls.
-// This class is used to ease the event handling with controls.
-// The implementation should simply call the appropriate methods
-// of this class when appropriate events occure.
- crtl_container_ptr = ^ctrl_container;
- ctrl_container = object
- m_ctrl : array[0..max_ctrl - 1 ] of ctrl_ptr;
-
- m_num_ctrl : unsigned;
- m_cur_ctrl : int;
-
- constructor Construct;
- destructor Destruct;
-
- procedure add(c : ctrl_ptr );
-
- function in_rect(x ,y : double ) : boolean;
-
- function on_mouse_button_down(x ,y : double ) : boolean;
- function on_mouse_button_up (x ,y : double ) : boolean;
-
- function on_mouse_move(x ,y : double; button_flag : boolean ) : boolean;
- function on_arrow_keys(left ,right ,down ,up : boolean ) : boolean;
-
- function set_cur(x ,y : double ) : boolean;
-
- end;
-
-//---------------------------------------------------------platform_support
-// This class is a base one to the apllication classes. It can be used
-// as follows:
-//
-// the_application = object(platform_support )
-//
-// constructor Construct(bpp : unsigned; flip_y : boolean );
-// . . .
-//
-// //override stuff . . .
-// procedure on_init; virtual;
-// procedure on_draw; virtual;
-// procedure on_resize(sx ,sy : int ); virtual;
-// // . . . and so on, see virtual functions
-//
-// //any your own stuff . . .
-// };
-//
-// VAR
-// app : the_application;
-//
-// BEGIN
-// app.Construct(pix_format_rgb24 ,true );
-// app.caption ("AGG Example. Lion" );
-//
-// if app.init(500 ,400 ,window_resize ) then
-// app.run;
-//
-// app.Destruct;
-//
-// END.
-//
-const
- max_images = 16;
-
-type
- platform_specific_ptr = ^platform_specific;
- platform_specific = object
- m_format ,
- m_sys_format : pix_format_e;
- m_byte_order : int;
-
- m_flip_y : boolean;
- m_bpp ,
- m_sys_bpp : unsigned;
- m_display : PDisplay;
- m_screen ,
- m_depth : int;
- m_visual : PVisual;
- m_window : TWindow;
- m_gc : TGC;
-
- m_window_attributes : TXSetWindowAttributes;
-
- m_ximg_window : PXImage;
- m_close_atom : TAtom;
- m_buf_window : pointer;
- m_buf_alloc : unsigned;
- m_buf_img : array[0..max_images - 1 ] of pointer;
- m_img_alloc : array[0..max_images - 1 ] of unsigned;
-
- m_keymap : array[0..255 ] of unsigned;
-
- m_update_flag ,
- m_resize_flag ,
- m_initialized : boolean;
-
- //m_wait_mode : boolean;
- m_sw_start : clock_t;
-
- constructor Construct(format : pix_format_e; flip_y : boolean );
- destructor Destruct;
-
- procedure caption_ (capt : PChar );
- procedure put_image(src : rendering_buffer_ptr );
-
- end;
-
- platform_support_ptr = ^platform_support;
- platform_support = object
- m_specific : platform_specific_ptr;
- m_ctrls : ctrl_container;
-
- m_format : pix_format_e;
-
- m_bpp : unsigned;
-
- m_rbuf_window : rendering_buffer;
- m_rbuf_img : array[0..max_images - 1 ] of rendering_buffer;
-
- m_window_flags : unsigned;
- m_wait_mode ,
- m_flip_y : boolean; // flip_y - true if you want to have the Y-axis flipped vertically
- m_caption : shortstring;
- m_resize_mtx : trans_affine;
-
- m_initial_width ,
- m_initial_height : int;
-
- m_quit : boolean;
-
- constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
- destructor Destruct;
-
- // Setting the windows caption (title). Should be able
- // to be called at least before calling init().
- // It's perfect if they can be called anytime.
- procedure caption_(cap : shortstring );
-
- // These 3 menthods handle working with images. The image
- // formats are the simplest ones, such as .BMP in Windows or
- // .ppm in Linux. In the applications the names of the files
- // should not have any file extensions. Method load_img() can
- // be called before init(), so, the application could be able
- // to determine the initial size of the window depending on
- // the size of the loaded image.
- // The argument "idx" is the number of the image 0...max_images-1
- function load_img (idx : unsigned; file_ : shortstring ) : boolean;
- function save_img (idx : unsigned; file_ : shortstring ) : boolean;
- function create_img(idx : unsigned; width_ : unsigned = 0; height_ : unsigned = 0 ) : boolean;
-
- // init() and run(). See description before the class for details.
- // The necessity of calling init() after creation is that it's
- // impossible to call the overridden virtual function (on_init())
- // from the constructor. On the other hand it's very useful to have
- // some on_init() event handler when the window is created but
- // not yet displayed. The rbuf_window() method (see below) is
- // accessible from on_init().
- function init(width_ ,height_ ,flags : unsigned ) : boolean;
- function run : int;
- procedure quit;
-
- // The very same parameters that were used in the constructor
- function _format : pix_format_e;
- function _flip_y : boolean;
- function _bpp : unsigned;
-
- // The following provides a very simple mechanism of doing someting
- // in background. It's not multitheading. When whait_mode is true
- // the class waits for the events and it does not ever call on_idle().
- // When it's false it calls on_idle() when the event queue is empty.
- // The mode can be changed anytime. This mechanism is satisfactory
- // for creation very simple animations.
- function _wait_mode : boolean;
- procedure wait_mode_(wait_mode : boolean );
-
- // These two functions control updating of the window.
- // force_redraw() is an analog of the Win32 InvalidateRect() function.
- // Being called it sets a flag (or sends a message) which results
- // in calling on_draw() and updating the content of the window
- // when the next event cycle comes.
- // update_window() results in just putting immediately the content
- // of the currently rendered buffer to the window without calling
- // on_draw().
- procedure force_redraw;
- procedure update_window;
-
- // So, finally, how to draw anythig with AGG? Very simple.
- // rbuf_window() returns a reference to the main rendering
- // buffer which can be attached to any rendering class.
- // rbuf_img() returns a reference to the previously created
- // or loaded image buffer (see load_img()). The image buffers
- // are not displayed directly, they should be copied to or
- // combined somehow with the rbuf_window(). rbuf_window() is
- // the only buffer that can be actually displayed.
- function rbuf_window : rendering_buffer_ptr;
- function rbuf_img(idx : unsigned ) : rendering_buffer_ptr;
-
- // Returns file extension used in the implemenation for the particular
- // system.
- function _img_ext : shortstring;
-
- //
- procedure copy_img_to_window(idx : unsigned );
- procedure copy_window_to_img(idx : unsigned );
- procedure copy_img_to_img (idx_to ,idx_from : unsigned );
-
- // Event handlers. They are not pure functions, so you don't have
- // to override them all.
- // In my demo applications these functions are defined inside
- // the the_application class
- procedure on_init; virtual;
- procedure on_resize(sx ,sy : int ); virtual;
- procedure on_idle; virtual;
-
- procedure on_mouse_move(x ,y : int; flags : unsigned ); virtual;
-
- procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual;
- procedure on_mouse_button_up (x ,y : int; flags : unsigned ); virtual;
-
- procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
- procedure on_ctrl_change; virtual;
- procedure on_draw; virtual;
- procedure on_post_draw(raw_handler : pointer ); virtual;
-
- // Adding control elements. A control element once added will be
- // working and reacting to the mouse and keyboard events. Still, you
- // will have to render them in the on_draw() using function
- // render_ctrl() because platform_support doesn't know anything about
- // renderers you use. The controls will be also scaled automatically
- // if they provide a proper scaling mechanism (all the controls
- // included into the basic AGG package do).
- // If you don't need a particular control to be scaled automatically
- // call ctrl::no_transform() after adding.
- procedure add_ctrl(c : ctrl_ptr );
-
- // Auxiliary functions. trans_affine_resizing() modifier sets up the resizing
- // matrix on the basis of the given width and height and the initial
- // width and height of the window. The implementation should simply
- // call this function every time when it catches the resizing event
- // passing in the new values of width and height of the window.
- // Nothing prevents you from "cheating" the scaling matrix if you
- // call this function from somewhere with wrong arguments.
- // trans_affine_resizing() accessor simply returns current resizing matrix
- // which can be used to apply additional scaling of any of your
- // stuff when the window is being resized.
- // width(), height(), initial_width(), and initial_height() must be
- // clear to understand with no comments :-)
- procedure trans_affine_resizing_(width_ ,height_ : int );
- function _trans_affine_resizing : trans_affine_ptr;
-
- function _width : double;
- function _height : double;
- function _initial_width : double;
- function _initial_height : double;
- function _window_flags : unsigned;
-
- // Get raw display handler depending on the system.
- // For win32 its an HDC, for other systems it can be a pointer to some
- // structure. See the implementation files for detals.
- // It's provided "as is", so, first you should check if it's not null.
- // If it's null the raw_display_handler is not supported. Also, there's
- // no guarantee that this function is implemented, so, in some
- // implementations you may have simply an unresolved symbol when linking.
- function _raw_display_handler : pointer;
-
- // display message box or print the message to the console
- // (depending on implementation)
- procedure message_(msg : PChar );
-
- // Stopwatch functions. Function elapsed_time() returns time elapsed
- // since the latest start_timer() invocation in millisecods.
- // The resolutoin depends on the implementation.
- // In Win32 it uses QueryPerformanceFrequency() / QueryPerformanceCounter().
- procedure start_timer;
- function elapsed_time : double;
-
- // Get the full file name. In most cases it simply returns
- // file_name. As it's appropriate in many systems if you open
- // a file by its name without specifying the path, it tries to
- // open it in the current directory. The demos usually expect
- // all the supplementary files to be placed in the current
- // directory, that is usually coincides with the directory where
- // the the executable is. However, in some systems (BeOS) it's not so.
- // For those kinds of systems full_file_name() can help access files
- // preserving commonly used policy.
- // So, it's a good idea to use in the demos the following:
- // FILE* fd = fopen(full_file_name("some.file"), "r");
- // instead of
- // FILE* fd = fopen("some.file", "r");
- function full_file_name(file_name : shortstring ) : shortstring;
- function file_source (path ,fname : shortstring ) : shortstring;
-
- end;
-
-{ GLOBAL PROCEDURES }
-
-
-IMPLEMENTATION
-{ LOCAL VARIABLES & CONSTANTS }
-{ UNIT IMPLEMENTATION }
-{ CONSTRUCT }
-constructor ctrl_container.Construct;
-begin
- m_num_ctrl:=0;
- m_cur_ctrl:=-1;
-
-end;
-
-{ DESTRUCT }
-destructor ctrl_container.Destruct;
-begin
-end;
-
-{ ADD }
-procedure ctrl_container.add;
-begin
- if m_num_ctrl < max_ctrl then
- begin
- m_ctrl[m_num_ctrl ]:=c;
-
- inc(m_num_ctrl );
-
- end;
-
-end;
-
-{ IN_RECT }
-function ctrl_container.in_rect;
-var
- i : unsigned;
-
-begin
- result:=false;
-
- if m_num_ctrl > 0 then
- for i:=0 to m_num_ctrl - 1 do
- if m_ctrl[i ].in_rect(x ,y ) then
- begin
- result:=true;
-
- exit;
-
- end;
-
-end;
-
-{ ON_MOUSE_BUTTON_DOWN }
-function ctrl_container.on_mouse_button_down;
-var
- i : unsigned;
-
-begin
- result:=false;
-
- if m_num_ctrl > 0 then
- for i:=0 to m_num_ctrl - 1 do
- if m_ctrl[i ].on_mouse_button_down(x ,y ) then
- begin
- result:=true;
-
- exit;
-
- end;
-
-end;
-
-{ ON_MOUSE_BUTTON_UP }
-function ctrl_container.on_mouse_button_up;
-var
- i : unsigned;
-
-begin
- result:=false;
-
- if m_num_ctrl > 0 then
- for i:=0 to m_num_ctrl - 1 do
- if m_ctrl[i ].on_mouse_button_up(x ,y ) then
- begin
- result:=true;
-
- exit;
-
- end;
-
-end;
-
-{ ON_MOUSE_MOVE }
-function ctrl_container.on_mouse_move;
-var
- i : unsigned;
-
-begin
- result:=false;
-
- if m_num_ctrl > 0 then
- for i:=0 to m_num_ctrl - 1 do
- if m_ctrl[i ].on_mouse_move(x ,y ,button_flag ) then
- begin
- result:=true;
-
- exit;
-
- end;
-
-end;
-
-{ ON_ARROW_KEYS }
-function ctrl_container.on_arrow_keys;
-begin
- result:=false;
-
- if m_cur_ctrl >= 0 then
- result:=m_ctrl[m_cur_ctrl ].on_arrow_keys(left ,right ,down ,up );
-
-end;
-
-{ SET_CUR }
-function ctrl_container.set_cur;
-var
- i : unsigned;
-
-begin
- result:=false;
-
- if m_num_ctrl > 0 then
- for i:=0 to m_num_ctrl - 1 do
- if m_ctrl[i ].in_rect(x ,y ) then
- begin
- if m_cur_ctrl <> i then
- begin
- m_cur_ctrl:=i;
-
- result:=true;
-
- end;
-
- exit;
-
- end;
-
- if m_cur_ctrl <> -1 then
- begin
- m_cur_ctrl:=-1;
-
- result:=true;
-
- end;
-
-end;
-
-{ CONSTRUCT }
-constructor platform_specific.Construct;
-var
- i : unsigned;
-
-begin
- m_format :=format;
- m_sys_format:=pix_format_undefined;
- m_byte_order:=LSBFirst;
- m_flip_y :=flip_y;
-
- m_bpp :=0;
- m_sys_bpp:=0;
- m_display:=NIL;
- m_screen :=0;
- m_depth :=0;
- m_visual :=NIL;
- m_window :=0;
- m_gc :=NIL;
-
- m_ximg_window:=NIL;
- m_close_atom :=0;
- m_buf_window :=NIL;
- m_buf_alloc :=0;
-
- m_update_flag:=true;
- m_resize_flag:=true;
- m_initialized:=false;
- //m_wait_mode:=true;
-
- fillchar(m_buf_img[0 ] ,sizeof(m_buf_img ) ,0 );
-
- for i:=0 to 255 do
- m_keymap[i ]:=i;
-
- m_keymap[XK_Pause and $FF ]:=key_pause;
- m_keymap[XK_Clear and $FF ]:=key_clear;
-
- m_keymap[XK_KP_0 and $FF ]:=key_kp0;
- m_keymap[XK_KP_1 and $FF ]:=key_kp1;
- m_keymap[XK_KP_2 and $FF ]:=key_kp2;
- m_keymap[XK_KP_3 and $FF ]:=key_kp3;
- m_keymap[XK_KP_4 and $FF ]:=key_kp4;
- m_keymap[XK_KP_5 and $FF ]:=key_kp5;
- m_keymap[XK_KP_6 and $FF ]:=key_kp6;
- m_keymap[XK_KP_7 and $FF ]:=key_kp7;
- m_keymap[XK_KP_8 and $FF ]:=key_kp8;
- m_keymap[XK_KP_9 and $FF ]:=key_kp9;
-
- m_keymap[XK_KP_Insert and $FF ] :=key_kp0;
- m_keymap[XK_KP_End and $FF ] :=key_kp1;
- m_keymap[XK_KP_Down and $FF ] :=key_kp2;
- m_keymap[XK_KP_Page_Down and $FF ]:=key_kp3;
- m_keymap[XK_KP_Left and $FF ] :=key_kp4;
- m_keymap[XK_KP_Begin and $FF ] :=key_kp5;
- m_keymap[XK_KP_Right and $FF ] :=key_kp6;
- m_keymap[XK_KP_Home and $FF ] :=key_kp7;
- m_keymap[XK_KP_Up and $FF ] :=key_kp8;
- m_keymap[XK_KP_Page_Up and $FF ] :=key_kp9;
- m_keymap[XK_KP_Delete and $FF ] :=key_kp_period;
- m_keymap[XK_KP_Decimal and $FF ] :=key_kp_period;
- m_keymap[XK_KP_Divide and $FF ] :=key_kp_divide;
- m_keymap[XK_KP_Multiply and $FF ] :=key_kp_multiply;
- m_keymap[XK_KP_Subtract and $FF ] :=key_kp_minus;
- m_keymap[XK_KP_Add and $FF ] :=key_kp_plus;
- m_keymap[XK_KP_Enter and $FF ] :=key_kp_enter;
- m_keymap[XK_KP_Equal and $FF ] :=key_kp_equals;
-
- m_keymap[XK_Up and $FF ] :=key_up;
- m_keymap[XK_Down and $FF ] :=key_down;
- m_keymap[XK_Right and $FF ] :=key_right;
- m_keymap[XK_Left and $FF ] :=key_left;
- m_keymap[XK_Insert and $FF ] :=key_insert;
- m_keymap[XK_Home and $FF ] :=key_delete;
- m_keymap[XK_End and $FF ] :=key_end;
- m_keymap[XK_Page_Up and $FF ] :=key_page_up;
- m_keymap[XK_Page_Down and $FF ]:=key_page_down;
-
- m_keymap[XK_F1 and $FF ] :=key_f1;
- m_keymap[XK_F2 and $FF ] :=key_f2;
- m_keymap[XK_F3 and $FF ] :=key_f3;
- m_keymap[XK_F4 and $FF ] :=key_f4;
- m_keymap[XK_F5 and $FF ] :=key_f5;
- m_keymap[XK_F6 and $FF ] :=key_f6;
- m_keymap[XK_F7 and $FF ] :=key_f7;
- m_keymap[XK_F8 and $FF ] :=key_f8;
- m_keymap[XK_F9 and $FF ] :=key_f9;
- m_keymap[XK_F10 and $FF ]:=key_f10;
- m_keymap[XK_F11 and $FF ]:=key_f11;
- m_keymap[XK_F12 and $FF ]:=key_f12;
- m_keymap[XK_F13 and $FF ]:=key_f13;
- m_keymap[XK_F14 and $FF ]:=key_f14;
- m_keymap[XK_F15 and $FF ]:=key_f15;
-
- m_keymap[XK_Num_Lock and $FF ] :=key_numlock;
- m_keymap[XK_Caps_Lock and $FF ] :=key_capslock;
- m_keymap[XK_Scroll_Lock and $FF ]:=key_scrollock;
-
- case m_format of
- pix_format_gray8 :
- m_bpp:=8;
-
- pix_format_rgb565 ,
- pix_format_rgb555 :
- m_bpp:=16;
-
- pix_format_rgb24 ,
- pix_format_bgr24 :
- m_bpp:=24;
-
- pix_format_bgra32 ,
- pix_format_abgr32 ,
- pix_format_argb32 ,
- pix_format_rgba32 :
- m_bpp:=32;
-
- end;
-
- m_sw_start:=clock;
-
-end;
-
-{ DESTRUCT }
-destructor platform_specific.Destruct;
-begin
-end;
-
-{ CAPTION_ }
-procedure platform_specific.caption_;
-var
- tp : TXTextProperty;
-
-begin
- tp.value :=PCUChar(@capt[1 ] );
- tp.encoding:=XA_WM_NAME;
- tp.format :=8;
- tp.nitems :=strlen(capt );
-
- XSetWMName (m_display ,m_window ,@tp );
- XStoreName (m_display ,m_window ,capt );
- XSetIconName (m_display ,m_window ,capt );
- XSetWMIconName(m_display ,m_window ,@tp );
-
-end;
-
-{ PUT_IMAGE }
-procedure platform_specific.put_image;
-var
- row_len : int;
- buf_tmp : pointer;
-
- rbuf_tmp : rendering_buffer;
-
-begin
- if m_ximg_window = NIL then
- exit;
-
- m_ximg_window.data:=m_buf_window;
-
- if m_format = m_sys_format then
- XPutImage(
- m_display ,
- m_window ,
- m_gc ,
- m_ximg_window ,
- 0 ,0 ,0 ,0 ,
- src._width ,
- src._height )
-
- else
- begin
- row_len:=src._width * m_sys_bpp div 8;
-
- agg_getmem(buf_tmp ,row_len * src._height );
-
- rbuf_tmp.Construct;
-
- if m_flip_y then
- rbuf_tmp.attach(
- buf_tmp ,
- src._width,
- src._height ,
- -row_len )
- else
- rbuf_tmp.attach(
- buf_tmp ,
- src._width,
- src._height ,
- row_len );
-
- case m_sys_format of
- pix_format_rgb555 :
- case m_format of
- pix_format_rgb555 : color_conv(@rbuf_tmp ,src ,color_conv_rgb555_to_rgb555 );
- pix_format_rgb565 : color_conv(@rbuf_tmp ,src ,color_conv_rgb565_to_rgb555 );
- //pix_format_rgb24 : color_conv(@rbuf_tmp ,src ,color_conv_rgb24_to_rgb555 );
- pix_format_bgr24 : color_conv(@rbuf_tmp ,src ,color_conv_bgr24_to_rgb555 );
- //pix_format_rgba32 : color_conv(@rbuf_tmp ,src ,color_conv_rgba32_to_rgb555 );
- //pix_format_argb32 : color_conv(@rbuf_tmp ,src ,color_conv_argb32_to_rgb555 );
- pix_format_bgra32 : color_conv(@rbuf_tmp ,src ,color_conv_bgra32_to_rgb555 );
- //pix_format_abgr32 : color_conv(@rbuf_tmp ,src ,color_conv_abgr32_to_rgb555 );
-
- end;
-
- pix_format_rgb565 :
- case m_format of
- pix_format_rgb555 : color_conv(@rbuf_tmp ,src ,color_conv_rgb555_to_rgb565 );
- //pix_format_rgb565 : color_conv(@rbuf_tmp ,src ,color_conv_rgb565_to_rgb565 );
- //pix_format_rgb24 : color_conv(@rbuf_tmp ,src ,color_conv_rgb24_to_rgb565 );
- pix_format_bgr24 : color_conv(@rbuf_tmp ,src ,color_conv_bgr24_to_rgb565 );
- //pix_format_rgba32 : color_conv(@rbuf_tmp ,src ,color_conv_rgba32_to_rgb565 );
- //pix_format_argb32 : color_conv(@rbuf_tmp ,src ,color_conv_argb32_to_rgb565 );
- pix_format_bgra32 : color_conv(@rbuf_tmp ,src ,color_conv_bgra32_to_rgb565 );
- //pix_format_abgr32 : color_conv(@rbuf_tmp ,src ,color_conv_abgr32_to_rgb565 );
-
- end;
-
- pix_format_rgba32 :
- case m_format of
- pix_format_rgb555 : color_conv(@rbuf_tmp ,src ,color_conv_rgb555_to_rgba32 );
- //pix_format_rgb565 : color_conv(@rbuf_tmp ,src ,color_conv_rgb565_to_rgba32 );
- //pix_format_rgb24 : color_conv(@rbuf_tmp ,src ,color_conv_rgb24_to_rgba32 );
- pix_format_bgr24 : color_conv(@rbuf_tmp ,src ,color_conv_bgr24_to_rgba32 );
- //pix_format_rgba32 : color_conv(@rbuf_tmp ,src ,color_conv_rgba32_to_rgba32 );
- //pix_format_argb32 : color_conv(@rbuf_tmp ,src ,color_conv_argb32_to_rgba32 );
- pix_format_bgra32 : color_conv(@rbuf_tmp ,src ,color_conv_bgra32_to_rgba32 );
- //pix_format_abgr32 : color_conv(@rbuf_tmp ,src ,color_conv_abgr32_to_rgba32 );
-
- end;
-
- pix_format_abgr32 :
- case m_format of
- pix_format_rgb555 : color_conv(@rbuf_tmp ,src ,color_conv_rgb555_to_abgr32 );
- //pix_format_rgb565 : color_conv(@rbuf_tmp ,src ,color_conv_rgb565_to_abgr32 );
- //pix_format_rgb24 : color_conv(@rbuf_tmp ,src ,color_conv_rgb24_to_abgr32 );
- pix_format_bgr24 : color_conv(@rbuf_tmp ,src ,color_conv_bgr24_to_abgr32 );
- //pix_format_abgr32 : color_conv(@rbuf_tmp ,src ,color_conv_abgr32_to_abgr32 );
- //pix_format_rgba32 : color_conv(@rbuf_tmp ,src ,color_conv_rgba32_to_abgr32 );
- //pix_format_argb32 : color_conv(@rbuf_tmp ,src ,color_conv_argb32_to_abgr32 );
- pix_format_bgra32 : color_conv(@rbuf_tmp ,src ,color_conv_bgra32_to_abgr32 );
-
- end;
-
- pix_format_argb32 :
- case m_format of
- pix_format_rgb555 : color_conv(@rbuf_tmp ,src ,color_conv_rgb555_to_argb32 );
- //pix_format_rgb565 : color_conv(@rbuf_tmp ,src ,color_conv_rgb565_to_argb32 );
- //pix_format_rgb24 : color_conv(@rbuf_tmp ,src ,color_conv_rgb24_to_argb32 );
- pix_format_bgr24 : color_conv(@rbuf_tmp ,src ,color_conv_bgr24_to_argb32 );
- pix_format_rgba32 : color_conv(@rbuf_tmp ,src ,color_conv_rgba32_to_argb32 );
- //pix_format_argb32 : color_conv(@rbuf_tmp ,src ,color_conv_argb32_to_argb32 );
- pix_format_abgr32 : color_conv(@rbuf_tmp ,src ,color_conv_abgr32_to_argb32 );
- pix_format_bgra32 : color_conv(@rbuf_tmp ,src ,color_conv_bgra32_to_argb32 );
-
- end;
-
- pix_format_bgra32 :
- case m_format of
- pix_format_rgb555 : color_conv(@rbuf_tmp ,src ,color_conv_rgb555_to_bgra32 );
- //pix_format_rgb565 : color_conv(@rbuf_tmp ,src ,color_conv_rgb565_to_bgra32 );
- //pix_format_rgb24 : color_conv(@rbuf_tmp ,src ,color_conv_rgb24_to_bgra32 );
- pix_format_bgr24 : color_conv(@rbuf_tmp ,src ,color_conv_bgr24_to_bgra32 );
- pix_format_rgba32 : color_conv(@rbuf_tmp ,src ,color_conv_rgba32_to_bgra32 );
- pix_format_argb32 : color_conv(@rbuf_tmp ,src ,color_conv_argb32_to_bgra32 );
- pix_format_abgr32 : color_conv(@rbuf_tmp ,src ,color_conv_abgr32_to_bgra32 );
- pix_format_bgra32 : color_conv(@rbuf_tmp ,src ,color_conv_bgra32_to_bgra32 );
-
- end;
-
- end;
-
- m_ximg_window.data:=buf_tmp;
-
- XPutImage(
- m_display ,
- m_window ,
- m_gc ,
- m_ximg_window ,
- 0 ,0 ,0 ,0 ,
- src._width ,
- src._height );
-
- agg_freemem(buf_tmp ,row_len * src._height );
-
- rbuf_tmp.Destruct;
-
- end;
-
-end;
-
-{ CONSTRUCT }
-constructor platform_support.Construct;
-var
- i : unsigned;
-
- p ,n ,x : shortstring;
-
-begin
- new(m_specific ,Construct(format_ ,flip_y_ ) );
-
- m_ctrls.Construct;
- m_rbuf_window.Construct;
-
- for i:=0 to max_images - 1 do
- m_rbuf_img[i ].Construct;
-
- m_resize_mtx.Construct;
-
- m_format:=format_;
-
- m_bpp:=m_specific.m_bpp;
-
- m_window_flags:=0;
- m_wait_mode :=true;
- m_flip_y :=flip_y_;
-
- m_initial_width :=10;
- m_initial_height:=10;
-
- m_caption:='Anti-Grain Geometry Application'#0;
-
-// Change working dir to the application one
- spread_name(ParamStr(0 ) ,p ,n ,x );
-
- p:=p + #0;
-
- SetCurrentDir(p);
-
-end;
-
-{ DESTRUCT }
-destructor platform_support.Destruct;
-var
- i : unsigned;
-
-begin
- dispose(m_specific ,Destruct );
-
- m_ctrls.Destruct;
- m_rbuf_window.Destruct;
-
- for i:=0 to max_images - 1 do
- m_rbuf_img[i ].Destruct;
-
-end;
-
-{ CAPTION_ }
-procedure platform_support.caption_;
-begin
- m_caption:=cap + #0;
-
- dec(byte(m_caption[0 ] ) );
-
- if m_specific.m_initialized then
- m_specific.caption_(PChar(@m_caption[1 ] ) );
-
-end;
-
-{ isdigit }
-function isdigit(c : char ) : boolean;
-begin
- case c of
- '0'..'9' :
- result:=true;
-
- else
- result:=false;
-
- end;
-
-end;
-
-{ atoi }
-function atoi(c : char_ptr ) : int;
-var
- s : shortstring;
- e : int;
-
-begin
- s:='';
-
- repeat
- case c^ of
- '0'..'9' :
- s:=s + c^;
-
- else
- break;
-
- end;
-
- inc(ptrcomp(c ) );
-
- until false;
-
- val(s ,result ,e );
-
-end;
-
-{ LOAD_IMG }
-function platform_support.load_img;
-var
- fd : file;
- buf : array[0..1023 ] of char;
- len : int;
- ptr : char_ptr;
- ret : boolean;
-
- width ,height : unsigned;
-
- buf_img : pointer;
- rbuf_img_ : rendering_buffer;
-
-begin
- result:=false;
-
- if idx < max_images then
- begin
- file_:=file_ + _img_ext;
-
- if not file_exists(file_ ) then
- file_:='ppm/' + file_;
-
- AssignFile(fd ,file_ );
- reset (fd ,1 );
-
- if IOResult <> 0 then
- exit;
-
- blockread(fd ,buf ,1022 ,len );
-
- if len = 0 then
- begin
- close(fd );
- exit;
-
- end;
-
- buf[len ]:=#0;
-
- if (buf[0 ] <> 'P' ) and
- (buf[1 ] <> '6' ) then
- begin
- close(fd );
- exit;
-
- end;
-
- ptr:=@buf[2 ];
-
- while (ptr^ <> #0 ) and
- not isdigit(ptr^ ) do
- inc(ptrcomp(ptr ) );
-
- if ptr^ = #0 then
- begin
- close(fd );
- exit;
-
- end;
-
- width:=atoi(ptr );
-
- if (width = 0 ) or
- (width > 4096 ) then
- begin
- close(fd );
- exit;
-
- end;
-
- while (ptr^ <> #0 ) and
- isdigit(ptr^ ) do
- inc(ptrcomp(ptr ) );
-
- while (ptr^ <> #0 ) and
- not isdigit(ptr^ ) do
- inc(ptrcomp(ptr ) );
-
- if ptr^ = #0 then
- begin
- close(fd );
- exit;
-
- end;
-
- height:=atoi(ptr );
-
- if (height = 0 ) or
- (height > 4096 ) then
- begin
- close(fd );
- exit;
-
- end;
-
- while (ptr^ <> #0 ) and
- isdigit(ptr^ ) do
- inc(ptrcomp(ptr ) );
-
- while (ptr^ <> #0 ) and
- not isdigit(ptr^ ) do
- inc(ptrcomp(ptr ) );
-
- if atoi(ptr ) <> 255 then
- begin
- close(fd );
- exit;
-
- end;
-
- while (ptr^ <> #0 ) and
- isdigit(ptr^ ) do
- inc(ptrcomp(ptr ) );
-
- if ptr^ = #0 then
- begin
- close(fd );
- exit;
-
- end;
-
- inc (ptrcomp(ptr ) );
- seek (fd ,ptrcomp(ptr ) - ptrcomp(@buf ) );
- create_img(idx ,width ,height );
-
- ret:=true;
-
- if m_format = pix_format_rgb24 then
- blockread(fd ,m_specific.m_buf_img[idx ]^ ,width * height * 3 )
- else
- begin
- agg_getmem(buf_img ,width * height * 3 );
-
- rbuf_img_.Construct;
-
- if m_flip_y then
- rbuf_img_.attach(buf_img ,width ,height ,-width * 3 )
- else
- rbuf_img_.attach(buf_img ,width ,height ,width * 3 );
-
- blockread(fd ,buf_img^ ,width * height * 3 );
-
- case m_format of
- //pix_format_rgb555 : color_conv(@m_rbuf_img[idx ] ,@rbuf_img_ ,color_conv_rgb24_to_rgb555 );
- //pix_format_rgb565 : color_conv(@m_rbuf_img[idx ] ,@rbuf_img_ ,color_conv_rgb24_to_rgb565 );
- pix_format_bgr24 : color_conv(@m_rbuf_img[idx ] ,@rbuf_img_ ,color_conv_rgb24_to_bgr24 );
- //pix_format_rgba32 : color_conv(@m_rbuf_img[idx ] ,@rbuf_img_ ,color_conv_rgb24_to_rgba32 );
- //pix_format_argb32 : color_conv(@m_rbuf_img[idx ] ,@rbuf_img_ ,color_conv_rgb24_to_argb32 );
- pix_format_bgra32 : color_conv(@m_rbuf_img[idx ] ,@rbuf_img_ ,color_conv_rgb24_to_bgra32 );
- //pix_format_abgr32 : color_conv(@m_rbuf_img[idx ] ,@rbuf_img_ ,color_conv_rgb24_to_abgr32 );
- else
- ret:=false;
-
- end;
-
- agg_freemem(buf_img ,width * height * 3 );
-
- rbuf_img_.Destruct;
-
- end;
-
- close(fd );
-
- result:=ret;
-
- end;
-
-end;
-
-{ SAVE_IMG }
-function platform_support.save_img;
-var
- fd : file;
-
- s ,c : shortstring;
-
- w ,h ,y : unsigned;
-
- tmp_buf ,src : pointer;
-
-begin
- result:=false;
-
- if (idx < max_images ) and
- (rbuf_img(idx )._buf <> NIL ) then
- begin
- AssignFile(fd ,file_ );
- rewrite (fd ,1 );
-
- if IOResult <> 0 then
- exit;
-
- w:=rbuf_img(idx )._width;
- h:=rbuf_img(idx )._height;
-
- str(w ,c );
-
- s:='P6'#13 + c + ' ';
-
- str(h ,c );
-
- s:=s + c + #13'255'#13;
-
- blockwrite(fd ,s[1 ] ,length(s ) );
-
- agg_getmem(tmp_buf ,w * 3 );
-
- y:=0;
-
- while y < rbuf_img(idx )._height do
- begin
- if m_flip_y then
- src:=rbuf_img(idx ).row(h - 1 - y )
- else
- src:=rbuf_img(idx ).row(y );
-
- case m_format of
- pix_format_rgb555 : color_conv_rgb555_to_rgb24(tmp_buf ,src ,w );
- //pix_format_rgb565 : color_conv_rgb565_to_rgb24(tmp_buf ,src ,w );
- pix_format_bgr24 : color_conv_bgr24_to_rgb24 (tmp_buf ,src ,w );
- //pix_format_rgb24 : color_conv_rgb24_to_rgb24 (tmp_buf ,src ,w );
- //pix_format_rgba32 : color_conv_rgba32_to_rgb24(tmp_buf ,src ,w );
- //pix_format_argb32 : color_conv_argb32_to_rgb24(tmp_buf ,src ,w );
- pix_format_bgra32 : color_conv_bgra32_to_rgb24(tmp_buf ,src ,w );
- //pix_format_abgr32 : color_conv_abgr32_to_rgb24(tmp_buf ,src ,w );
-
- end;
-
- blockwrite(fd ,tmp_buf^ ,w * 3 );
- inc (y );
-
- end;
-
- agg_getmem(tmp_buf ,w * 3 );
- close (fd );
-
- result:=true;
-
- end;
-
-end;
-
-{ CREATE_IMG }
-function platform_support.create_img;
-begin
- result:=false;
-
- if idx < max_images then
- begin
- if width_ = 0 then
- width_:=trunc(rbuf_window._width );
-
- if height_ = 0 then
- height_:=trunc(rbuf_window._height );
-
- agg_freemem(m_specific.m_buf_img[idx ] ,m_specific.m_img_alloc[idx ] );
-
- m_specific.m_img_alloc[idx ]:=width_ * height_ * (m_bpp div 8 );
-
- agg_getmem(m_specific.m_buf_img[idx ] ,m_specific.m_img_alloc[idx ] );
-
- if m_flip_y then
- m_rbuf_img[idx ].attach(
- m_specific.m_buf_img[idx ] ,
- width_ ,height_ ,
- -width_ * (m_bpp div 8 ) )
- else
- m_rbuf_img[idx ].attach(
- m_specific.m_buf_img[idx ] ,
- width_ ,height_ ,
- width_ * (m_bpp div 8 ) );
-
- result:=true;
-
- end;
-
-end;
-
-{ INIT }
-function platform_support.init;
-const
- xevent_mask =
- PointerMotionMask or
- ButtonPressMask or
- ButtonReleaseMask or
- ExposureMask or
- KeyPressMask or
- StructureNotifyMask;
-
-var
- r_mask ,g_mask ,b_mask ,window_mask : unsigned;
-
- t ,hw_byte_order : int;
-
- hints : PXSizeHints;
-
-begin
- m_window_flags:=flags;
-
- m_specific.m_display:=XOpenDisplay(NIL );
-
- if m_specific.m_display = NIL then
- begin
- writeln(stderr ,'Unable to open DISPLAY!' );
-
- result:=false;
-
- exit;
-
- end;
-
- m_specific.m_screen:=XDefaultScreen(m_specific.m_display );
- m_specific.m_depth :=XDefaultDepth (m_specific.m_display ,m_specific.m_screen );
- m_specific.m_visual:=XDefaultVisual(m_specific.m_display ,m_specific.m_screen );
-
- r_mask:=m_specific.m_visual.red_mask;
- g_mask:=m_specific.m_visual.green_mask;
- b_mask:=m_specific.m_visual.blue_mask;
-
- if (m_specific.m_depth < 15 ) or
- (r_mask = 0 ) or
- (g_mask = 0 ) or
- (b_mask = 0 ) then
- begin
- writeln(stderr ,'There''s no Visual compatible with minimal AGG requirements:' );
- writeln(stderr ,'At least 15-bit color depth and True- or DirectColor class.' );
- writeln(stderr );
-
- XCloseDisplay(m_specific.m_display );
-
- result:=false;
-
- exit;
-
- end;
-
- t:=1;
-
- hw_byte_order:=LSBFirst;
-
- if byte(pointer(@t )^ ) = 0 then
- hw_byte_order:=MSBFirst;
-
-// Perceive SYS-format by mask
- case m_specific.m_depth of
- 15 :
- begin
- m_specific.m_sys_bpp:=16;
-
- if (r_mask = $7C00 ) and
- (g_mask = $3E0 ) and
- (b_mask = $1F ) then
- begin
- m_specific.m_sys_format:=pix_format_rgb555;
- m_specific.m_byte_order:=hw_byte_order;
-
- end;
-
- end;
-
- 16 :
- begin
- m_specific.m_sys_bpp:=16;
-
- if (r_mask = $F800 ) and
- (g_mask = $7E0 ) and
- (b_mask = $1F ) then
- begin
- m_specific.m_sys_format:=pix_format_rgb565;
- m_specific.m_byte_order:=hw_byte_order;
-
- end;
-
- end;
-
- 24 ,32 :
- begin
- m_specific.m_sys_bpp:=32;
-
- if g_mask = $FF00 then
- begin
- if (r_mask = $FF ) and
- (b_mask = $FF0000 ) then
- case m_specific.m_format of
- pix_format_rgba32 :
- begin
- m_specific.m_sys_format:=pix_format_rgba32;
- m_specific.m_byte_order:=LSBFirst;
-
- end;
-
- pix_format_abgr32 :
- begin
- m_specific.m_sys_format:=pix_format_abgr32;
- m_specific.m_byte_order:=MSBFirst;
-
- end;
-
- else
- begin
- m_specific.m_byte_order:=hw_byte_order;
-
- if hw_byte_order = LSBFirst then
- m_specific.m_sys_format:=pix_format_rgba32
- else
- m_specific.m_sys_format:=pix_format_abgr32;
-
- end;
-
- end;
-
- if (r_mask = $FF0000 ) and
- (b_mask = $FF ) then
- case m_specific.m_format of
- pix_format_argb32 :
- begin
- m_specific.m_sys_format:=pix_format_argb32;
- m_specific.m_byte_order:=MSBFirst;
-
- end;
-
- pix_format_bgra32 :
- begin
- m_specific.m_sys_format:=pix_format_bgra32;
- m_specific.m_byte_order:=LSBFirst;
-
- end;
-
- else
- begin
- m_specific.m_byte_order:=hw_byte_order;
-
- if hw_byte_order = MSBFirst then
- m_specific.m_sys_format:=pix_format_argb32
- else
- m_specific.m_sys_format:=pix_format_bgra32;
-
- end;
-
- end;
-
- end;
-
- end;
-
- end;
-
- if m_specific.m_sys_format = pix_format_undefined then
- begin
- writeln(stderr ,'RGB masks are not compatible with AGG pixel formats:' );
- write (stderr ,'R=' ,r_mask ,'G=' ,g_mask ,'B=' ,b_mask );
-
- XCloseDisplay(m_specific.m_display );
-
- result:=false;
-
- exit;
-
- end;
-
- fillchar(
- m_specific.m_window_attributes ,
- sizeof(m_specific.m_window_attributes ) ,0 );
-
- m_specific.m_window_attributes.border_pixel:=
- XBlackPixel(m_specific.m_display ,m_specific.m_screen );
-
- m_specific.m_window_attributes.background_pixel:=
- XWhitePixel(m_specific.m_display ,m_specific.m_screen );
-
- m_specific.m_window_attributes.override_redirect:=xfalse;
-
- window_mask:=CWBackPixel or CWBorderPixel;
-
- m_specific.m_window:=
- XCreateWindow(
- m_specific.m_display ,
- XDefaultRootWindow(m_specific.m_display ) ,
- 0 ,0 ,
- width_ ,height_ ,
- 0 ,
- m_specific.m_depth ,
- InputOutput ,
- CopyFromParent ,
- window_mask ,
- @m_specific.m_window_attributes );
-
- m_specific.m_gc:=XCreateGC(m_specific.m_display ,m_specific.m_window ,0 ,0 );
-
- m_specific.m_buf_alloc:=width_ * height_ * (m_bpp div 8 );
-
- agg_getmem(m_specific.m_buf_window ,m_specific.m_buf_alloc );
- fillchar (m_specific.m_buf_window^ ,m_specific.m_buf_alloc ,255 );
-
- if m_flip_y then
- m_rbuf_window.attach(
- m_specific.m_buf_window ,
- width_ ,height_ ,
- -width_ * (m_bpp div 8 ) )
- else
- m_rbuf_window.attach(
- m_specific.m_buf_window ,
- width_ ,height_ ,
- width_ * (m_bpp div 8 ) );
-
- m_specific.m_ximg_window:=
- XCreateImage(
- m_specific.m_display ,
- m_specific.m_visual , //CopyFromParent,
- m_specific.m_depth ,
- ZPixmap ,
- 0 ,
- m_specific.m_buf_window ,
- width_ ,height_ ,
- m_specific.m_sys_bpp ,
- width_ * (m_specific.m_sys_bpp div 8 ) );
-
- m_specific.m_ximg_window.byte_order:=m_specific.m_byte_order;
-
- m_specific.caption_(PChar(@m_caption[1 ] ) );
-
- m_initial_width :=width_;
- m_initial_height:=height_;
-
- if not m_specific.m_initialized then
- begin
- on_init;
-
- m_specific.m_initialized:=true;
-
- end;
-
- trans_affine_resizing_(width_ ,height_ );
-
- on_resize(width_ ,height_ );
-
- m_specific.m_update_flag:=true;
-
- hints:=XAllocSizeHints;
-
- if hints <> NIL then
- begin
- if flags and window_resize <> 0 then
- begin
- hints.min_width :=32;
- hints.min_height:=32;
- hints.max_width :=4096;
- hints.max_height:=4096;
-
- end
- else
- begin
- hints.min_width :=width_;
- hints.min_height:=height_;
- hints.max_width :=width_;
- hints.max_height:=height_;
-
- end;
-
- hints.flags:=PMaxSize or PMinSize;
-
- XSetWMNormalHints(m_specific.m_display ,m_specific.m_window ,hints );
- XFree (hints );
-
- end;
-
- XMapWindow (m_specific.m_display ,m_specific.m_window );
- XSelectInput(m_specific.m_display ,m_specific.m_window ,xevent_mask );
-
- m_specific.m_close_atom:=
- XInternAtom(m_specific.m_display ,'WM_DELETE_WINDOW' ,false );
-
- XSetWMProtocols(
- m_specific.m_display ,
- m_specific.m_window ,
- @m_specific.m_close_atom ,1 );
-
- result:=true;
-
-end;
-
-{ RUN }
-function platform_support.run;
-var
- flags ,i : unsigned;
-
- cur_x ,cur_y ,width ,height : int;
-
- x_event ,te : TXEvent;
-
- key : TKeySym;
-
- left ,up ,right ,down : boolean;
-
-begin
- XFlush(m_specific.m_display );
-
- m_quit:=false;
-
- while not m_quit do
- begin
- if m_specific.m_update_flag then
- begin
- on_draw;
- update_window;
-
- m_specific.m_update_flag:=false;
-
- end;
-
- if not m_wait_mode then
- if XPending(m_specific.m_display ) = 0 then
- begin
- on_idle;
- continue;
-
- end;
-
- XNextEvent(m_specific.m_display ,@x_event );
-
- // In the Idle mode discard all intermediate MotionNotify events
- if not m_wait_mode and
- (x_event._type = MotionNotify ) then
- begin
- te:=x_event;
-
- repeat
- if XPending(m_specific.m_display ) = 0 then
- break;
-
- XNextEvent(m_specific.m_display ,@te );
-
- if te._type <> MotionNotify then
- break;
-
- until false;
-
- x_event:=te;
-
- end;
-
- case x_event._type of
- ConfigureNotify :
- if (x_event.xconfigure.width <> trunc(m_rbuf_window._width ) ) or
- (x_event.xconfigure.height <> trunc(m_rbuf_window._height ) ) then
- begin
- width :=x_event.xconfigure.width;
- height:=x_event.xconfigure.height;
-
- agg_freemem(m_specific.m_buf_window ,m_specific.m_buf_alloc );
-
- m_specific.m_ximg_window.data:=0;
-
- XDestroyImage(m_specific.m_ximg_window );
-
- m_specific.m_buf_alloc:=width * height * (m_bpp div 8 );
-
- agg_getmem(m_specific.m_buf_window ,m_specific.m_buf_alloc );
-
- if m_flip_y then
- m_rbuf_window.attach(
- m_specific.m_buf_window ,
- width ,height ,
- -width * (m_bpp div 8 ) )
- else
- m_rbuf_window.attach(
- m_specific.m_buf_window ,
- width ,height ,
- width * (m_bpp div 8 ) );
-
- m_specific.m_ximg_window:=
- XCreateImage(m_specific.m_display ,
- m_specific.m_visual , //CopyFromParent,
- m_specific.m_depth ,
- ZPixmap ,
- 0 ,
- m_specific.m_buf_window ,
- width ,height ,
- m_specific.m_sys_bpp ,
- width * (m_specific.m_sys_bpp div 8 ) );
-
- m_specific.m_ximg_window.byte_order:=m_specific.m_byte_order;
-
- trans_affine_resizing_(width ,height );
-
- on_resize(width ,height );
- on_draw;
- update_window;
-
- end;
-
- Expose :
- begin
- m_specific.put_image(@m_rbuf_window );
-
- XFlush(m_specific.m_display );
- XSync (m_specific.m_display ,false );
-
- end;
-
- KeyPress :
- begin
- key :=XLookupKeysym(@x_event.xkey ,0 );
- flags:=0;
-
- if x_event.xkey.state and Button1Mask <> 0 then
- flags:=flags or mouse_left;
-
- if x_event.xkey.state and Button3Mask <> 0 then
- flags:=flags or mouse_right;
-
- if x_event.xkey.state and ShiftMask <> 0 then
- flags:=flags or kbd_shift;
-
- if x_event.xkey.state and ControlMask <> 0 then
- flags:=flags or kbd_ctrl;
-
- left :=false;
- up :=false;
- right:=false;
- down :=false;
-
- case m_specific.m_keymap[key and $FF ] of
- key_left : left :=true;
- key_up : up :=true;
- key_right : right:=true;
- key_down : down :=true;
-
- key_f2 :
- begin
- copy_window_to_img(max_images - 1 );
- save_img (max_images - 1 ,'screenshot.ppm' );
-
- end;
-
- end;
-
- if m_ctrls.on_arrow_keys(left ,right ,down ,up ) then
- begin
- on_ctrl_change;
- force_redraw;
-
- end
- else
- if m_flip_y then
- on_key(
- x_event.xkey.x ,
- trunc(m_rbuf_window._height ) - x_event.xkey.y ,
- m_specific.m_keymap[key and $FF ] ,flags )
- else
- on_key(
- x_event.xkey.x ,
- x_event.xkey.y ,
- m_specific.m_keymap[key and $FF ] ,flags )
-
- end;
-
- ButtonPress :
- begin
- flags:=0;
-
- if x_event.xbutton.state and ShiftMask <> 0 then
- flags:=flags or kbd_shift;
-
- if x_event.xbutton.state and ControlMask <> 0 then
- flags:=flags or kbd_ctrl;
-
- if x_event.xbutton.button = Button1 then
- flags:=flags or mouse_left;
-
- if x_event.xbutton.button = Button3 then
- flags:=flags or mouse_right;
-
- cur_x:=x_event.xbutton.x;
-
- if m_flip_y then
- cur_y:=trunc(m_rbuf_window._height ) - x_event.xbutton.y
- else
- cur_y:=x_event.xbutton.y;
-
- if flags and mouse_left <> 0 then
- if m_ctrls.on_mouse_button_down(cur_x ,cur_y ) then
- begin
- m_ctrls.set_cur(cur_x ,cur_y );
- on_ctrl_change;
- force_redraw;
-
- end
- else
- if m_ctrls.in_rect(cur_x ,cur_y ) then
- if m_ctrls.set_cur(cur_x ,cur_y ) then
- begin
- on_ctrl_change;
- force_redraw;
-
- end
- else
- else
- on_mouse_button_down(cur_x ,cur_y ,flags );
-
- if flags and mouse_right <> 0 then
- on_mouse_button_down(cur_x ,cur_y ,flags );
-
- //m_specific.m_wait_mode:=m_wait_mode;
- //m_wait_mode :=true;
-
- end;
-
- MotionNotify :
- begin
- flags:=0;
-
- if x_event.xmotion.state and Button1Mask <> 0 then
- flags:=flags or mouse_left;
-
- if x_event.xmotion.state and Button3Mask <> 0 then
- flags:=flags or mouse_right;
-
- if x_event.xmotion.state and ShiftMask <> 0 then
- flags:=flags or kbd_shift;
-
- if x_event.xmotion.state and ControlMask <> 0 then
- flags:=flags or kbd_ctrl;
-
- cur_x:=x_event.xbutton.x;
-
- if m_flip_y then
- cur_y:=trunc(m_rbuf_window._height ) - x_event.xbutton.y
- else
- cur_y:=x_event.xbutton.y;
-
- if m_ctrls.on_mouse_move(cur_x ,cur_y ,flags and mouse_left <> 0 ) then
- begin
- on_ctrl_change;
- force_redraw;
-
- end
- else
- if not m_ctrls.in_rect(cur_x ,cur_y ) then
- on_mouse_move(cur_x ,cur_y ,flags );
-
- end;
-
- ButtonRelease :
- begin
- flags:=0;
-
- if x_event.xbutton.state and ShiftMask <> 0 then
- flags:=flags or kbd_shift;
-
- if x_event.xbutton.state and ControlMask <> 0 then
- flags:=flags or kbd_ctrl;
-
- if x_event.xbutton.button = Button1 then
- flags:=flags or mouse_left;
-
- if x_event.xbutton.button = Button3 then
- flags:=flags or mouse_right;
-
- cur_x:=x_event.xbutton.x;
-
- if m_flip_y then
- cur_y:=trunc(m_rbuf_window._height ) - x_event.xbutton.y
- else
- cur_y:=x_event.xbutton.y;
-
- if flags and mouse_left <> 0 then
- if m_ctrls.on_mouse_button_up(cur_x ,cur_y ) then
- begin
- on_ctrl_change;
- force_redraw;
-
- end;
-
- if flags and (mouse_left or mouse_right ) <> 0 then
- on_mouse_button_up(cur_x ,cur_y ,flags );
-
- //m_wait_mode:=m_specific.m_wait_mode;
-
- end;
-
- ClientMessage :
- if (x_event.xclient.format = 32 ) and
- (x_event.xclient.data.l[0 ] = int(m_specific.m_close_atom ) ) then
- m_quit:=true;
-
- end;
-
- end;
-
- i:=max_images;
-
- while i <> 0 do
- begin
- dec(i );
-
- if m_specific.m_buf_img[i ] <> NIL then
- agg_freemem(m_specific.m_buf_img[i ] ,m_specific.m_img_alloc[i ] );
-
- end;
-
- agg_freemem(m_specific.m_buf_window ,m_specific.m_buf_alloc );
-
- m_specific.m_ximg_window.data:=NIL;
-
- XDestroyImage (m_specific.m_ximg_window );
- XFreeGC (m_specific.m_display ,m_specific.m_gc );
- XDestroyWindow(m_specific.m_display ,m_specific.m_window );
- XCloseDisplay (m_specific.m_display );
-
- result:=0;
-
-end;
-
-{ QUIT }
-procedure platform_support.quit;
-begin
- m_quit:=true;
-
-end;
-
-{ _FORMAT }
-function platform_support._format;
-begin
- result:=m_format;
-
-end;
-
-{ _FLIP_Y }
-function platform_support._flip_y;
-begin
- result:=m_flip_y;
-
-end;
-
-{ _BPP }
-function platform_support._bpp;
-begin
- result:=m_bpp;
-
-end;
-
-{ _WAIT_MODE }
-function platform_support._wait_mode;
-begin
- result:=m_wait_mode;
-
-end;
-
-{ WAIT_MODE_ }
-procedure platform_support.wait_mode_;
-begin
- m_wait_mode:=wait_mode;
-
-end;
-
-{ FORCE_REDRAW }
-procedure platform_support.force_redraw;
-begin
- m_specific.m_update_flag:=true;
-
-end;
-
-{ UPDATE_WINDOW }
-procedure platform_support.update_window;
-begin
- m_specific.put_image(@m_rbuf_window );
-
-// When m_wait_mode is true we can discard all the events
-// came while the image is being drawn. In this case
-// the X server does not accumulate mouse motion events.
-// When m_wait_mode is false, i.e. we have some idle drawing
-// we cannot afford to miss any events
- XSync(m_specific.m_display ,m_wait_mode );
-
-end;
-
-{ RBUF_WINDOW }
-function platform_support.rbuf_window;
-begin
- result:=@m_rbuf_window;
-
-end;
-
-{ RBUF_IMG }
-function platform_support.rbuf_img;
-begin
- result:=@m_rbuf_img[idx ];
-
-end;
-
-{ _IMG_EXT }
-function platform_support._img_ext;
-begin
- result:='.ppm';
-
-end;
-
-{ COPY_IMG_TO_WINDOW }
-procedure platform_support.copy_img_to_window;
-begin
- if (idx < max_images ) and
- (rbuf_img(idx )._buf <> NIL ) then
- rbuf_window.copy_from(rbuf_img(idx ) );
-
-end;
-
-{ COPY_WINDOW_TO_IMG }
-procedure platform_support.copy_window_to_img;
-begin
- if idx < max_images then
- begin
- create_img(idx ,rbuf_window._width ,rbuf_window._height );
- rbuf_img (idx ).copy_from(rbuf_window );
-
- end;
-
-end;
-
-{ COPY_IMG_TO_IMG }
-procedure platform_support.copy_img_to_img;
-begin
- if (idx_from < max_images ) and
- (idx_to < max_images ) and
- (rbuf_img(idx_from )._buf <> NIL ) then
- begin
- create_img(
- idx_to ,
- rbuf_img(idx_from )._width ,
- rbuf_img(idx_from )._height );
-
- rbuf_img(idx_to ).copy_from(rbuf_img(idx_from ) );
-
- end;
-
-end;
-
-{ ON_INIT }
-procedure platform_support.on_init;
-begin
-end;
-
-{ ON_RESIZE }
-procedure platform_support.on_resize;
-begin
-end;
-
-{ ON_IDLE }
-procedure platform_support.on_idle;
-begin
-end;
-
-{ ON_MOUSE_MOVE }
-procedure platform_support.on_mouse_move;
-begin
-end;
-
-{ ON_MOUSE_BUTTON_DOWN }
-procedure platform_support.on_mouse_button_down;
-begin
-end;
-
-{ ON_MOUSE_BUTTON_UP }
-procedure platform_support.on_mouse_button_up;
-begin
-end;
-
-{ ON_KEY }
-procedure platform_support.on_key;
-begin
-end;
-
-{ ON_CTRL_CHANGE }
-procedure platform_support.on_ctrl_change;
-begin
-end;
-
-{ ON_DRAW }
-procedure platform_support.on_draw;
-begin
-end;
-
-{ ON_POST_DRAW }
-procedure platform_support.on_post_draw;
-begin
-end;
-
-{ ADD_CTRL }
-procedure platform_support.add_ctrl;
-begin
- m_ctrls.add(c );
-
- c.transform(@m_resize_mtx );
-
-end;
-
-{ TRANS_AFFINE_RESIZING_ }
-procedure platform_support.trans_affine_resizing_;
-var
- vp : trans_viewport;
- ts : trans_affine_scaling;
-
-begin
- if m_window_flags and window_keep_aspect_ratio <> 0 then
- begin
- vp.Construct;
- vp.preserve_aspect_ratio(0.5 ,0.5 ,aspect_ratio_meet );
-
- vp.device_viewport(0 ,0 ,width_ ,height_ );
- vp.world_viewport (0 ,0 ,m_initial_width ,m_initial_height );
-
- vp.to_affine(@m_resize_mtx );
-
- end
- else
- begin
- ts.Construct(
- width_ / m_initial_width ,
- height_ / m_initial_height );
-
- m_resize_mtx.assign(@ts );
-
- end;
-
-end;
-
-{ _TRANS_AFFINE_RESIZING }
-function platform_support._trans_affine_resizing;
-begin
- result:=@m_resize_mtx;
-
-end;
-
-{ _WIDTH }
-function platform_support._width;
-begin
- result:=m_rbuf_window._width;
-
-end;
-
-{ _HEIGHT }
-function platform_support._height;
-begin
- result:=m_rbuf_window._height;
-
-end;
-
-{ _INITIAL_WIDTH }
-function platform_support._initial_width;
-begin
- result:=m_initial_width;
-
-end;
-
-{ _INITIAL_HEIGHT }
-function platform_support._initial_height;
-begin
- result:=m_initial_height;
-
-end;
-
-{ _WINDOW_FLAGS }
-function platform_support._window_flags;
-begin
- result:=m_window_flags;
-
-end;
-
-{ _RAW_DISPLAY_HANDLER }
-function platform_support._raw_display_handler;
-begin
-end;
-
-{ MESSAGE_ }
-procedure platform_support.message_;
-const
- x_event_mask =
- ExposureMask or
- KeyPressMask;
-
- capt = ' PRESS ANY KEY TO CONTINUE THE AGGPAS DEMO ...';
- plus = 4;
-
-var
- x_display : PDisplay;
- x_window : TWindow;
- x_event : TXEvent;
- x_close : TAtom;
- x_changes : TXWindowChanges;
- x_hints : PXSizeHints;
-
- x_gc : TGC;
- x_tp : TXTextProperty;
- x_tx : TXTextItem;
-
- str ,cur : char_ptr;
-
- y ,len ,cnt ,max ,x_dx ,x_dy : unsigned;
-
- font_dir ,font_ascent ,font_descent : int;
-
- font_str : TXCharStruct;
-
-procedure draw_text;
-begin
- x_dx:=0;
- x_dy:=0;
-
- y :=20;
- cur:=PChar(@msg[0 ] );
- max:=strlen(msg );
- len:=0;
- cnt:=0;
-
- while cnt < max do
- begin
- if len = 0 then
- str:=cur;
-
- case cur^ of
- #13 :
- begin
- XDrawString (x_display ,x_window ,x_gc ,10 ,y ,str ,len );
- XQueryTextExtents(
- x_display ,XGContextFromGC(x_gc) ,
- str ,len ,
- @font_dir ,
- @font_ascent ,
- @font_descent ,
- @font_str );
-
- inc(y ,font_str.ascent + font_str.descent + plus );
- inc(x_dy ,font_str.ascent + font_str.descent + plus );
-
- if font_str.width > x_dx then
- x_dx:=font_str.width;
-
- len:=0;
-
- end;
-
- else
- inc(len );
-
- end;
-
- inc(ptrcomp(cur ) );
- inc(cnt );
-
- end;
-
- if len > 0 then
- begin
- XDrawString (x_display ,x_window ,x_gc ,10 ,y ,str ,len );
- XQueryTextExtents(
- x_display ,XGContextFromGC(x_gc) ,
- str ,len ,
- @font_dir ,
- @font_ascent ,
- @font_descent ,
- @font_str );
-
- inc(x_dy ,font_str.ascent + font_str.descent + plus );
-
- if font_str.width > x_dx then
- x_dx:=font_str.width;
-
- end;
-
-end;
-
-begin
- x_display:=XOpenDisplay(NIL );
-
- if x_display <> NIL then
- begin
- x_window :=
- XCreateSimpleWindow(
- x_display ,
- XDefaultRootWindow(x_display ) ,
- 50 ,50 ,
- 550 ,300 ,
- 0 ,0 ,
- 255 + (255 shl 8 ) + (255 shl 16 ) );
-
- x_gc:=XCreateGC(x_display ,x_window ,0 ,0 );
-
- draw_text;
- XResizeWindow(x_display ,x_window ,x_dx + 20 ,x_dy + 40 );
-
- x_hints:=XAllocSizeHints;
-
- if x_hints <> NIL then
- begin
- x_hints.min_width :=x_dx + 20;
- x_hints.min_height:=x_dy + 40;
- x_hints.max_width :=x_dx + 20;
- x_hints.max_height:=x_dy + 40;
-
- x_hints.flags:=PMaxSize or PMinSize;
-
- XSetWMNormalHints(x_display ,x_window ,x_hints );
- XFree (x_hints );
-
- end;
-
- x_tp.value :=PCUChar(@capt[1 ] );
- x_tp.encoding:=XA_WM_NAME;
- x_tp.format :=8;
- x_tp.nitems := Length(capt);
-
- XSetWMName (x_display ,x_window ,@x_tp );
- XStoreName (x_display ,x_window ,capt );
- XSetIconName (x_display ,x_window ,capt );
- XSetWMIconName(x_display ,x_window ,@x_tp );
-
- XMapWindow (x_display ,x_window );
- XSelectInput(x_display ,x_window ,x_event_mask );
-
- x_close:=
- XInternAtom(x_display ,'WM_DELETE_WINDOW' ,false );
-
- XSetWMProtocols(
- x_display ,
- x_window ,
- @x_close ,1 );
-
- XFlush(x_display );
-
- repeat
- XNextEvent(x_display ,@x_event );
-
- XFlush(x_display );
- XSync (x_display ,true );
-
- case x_event._type of
- Expose :
- draw_text;
-
- KeyPress :
- break;
-
- ClientMessage :
- if (x_event.xclient.format = 32 ) and
- (x_event.xclient.data.l[0 ] = int(x_close ) ) then
- break;
-
- end;
-
-
- until false;
-
- while XPending(x_display ) > 0 do
- begin
- XNextEvent(x_display ,@x_event );
-
- XFlush(x_display );
- XSync (x_display ,true );
-
- end;
-
- XFreeGC (x_display ,x_gc );
- XDestroyWindow(x_display ,x_window );
- XCloseDisplay (x_display );
-
- end
- else
- writeln(stderr ,msg );
-
-end;
-
-{ START_TIMER }
-procedure platform_support.start_timer;
-begin
- m_specific.m_sw_start:=clock;
-
-end;
-
-{ ELAPSED_TIME }
-function platform_support.elapsed_time;
-var
- stop : clock_t;
-
-begin
- stop:=clock;
-
- result:=(stop - m_specific.m_sw_start ) * 1000.0 / CLOCKS_PER_SEC;
-
-end;
-
-{ FULL_FILE_NAME }
-function platform_support.full_file_name;
-begin
- result:=file_name;
-
-end;
-
-{ FILE_SOURCE }
-function platform_support.file_source;
-var
- f : file;
- e : integer;
-
-begin
- result:=fname;
-
- e:=ioresult;
-
- AssignFile(f ,result );
- reset (f ,1 );
-
- if ioresult <> 0 then
- result:=path + '/' + fname;
-
- close(f );
-
- e:=ioresult;
-
-end;
-
-END.
-
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// class platform_support
+//
+// It's not a part of the AGG library, it's just a helper class to create
+// interactive demo examples. Since the examples should not be too complex
+// this class is provided to support some very basic interactive graphical
+// funtionality, such as putting the rendered image to the window, simple
+// keyboard and mouse input, window resizing, setting the window title,
+// and catching the "idle" events.
+//
+// The most popular platforms are:
+//
+// Windows-32 API
+// X-Window API
+// SDL library (see http://www.libsdl.org/)
+// MacOS C/C++ API
+//
+// All the system dependent stuff sits in the platform_specific class.
+// The platform_support class has just a pointer to it and it's
+// the responsibility of the implementation to create/delete it.
+// This class being defined in the implementation file can have
+// any platform dependent stuff such as HWND, X11 Window and so on.
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 29.03.2006-Milano: finished & tested OK
+// 28.03.2006-Milano: platform_specific & platform_support
+// 20.03.2006-Milano: Unit port establishment
+//
+{ agg_platform_support.pas }
+unit
+ agg_platform_support ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+{$I- }
+uses
+ X ,Xlib ,Xutil ,Xatom ,keysym ,CTypes ,SysUtils ,
+ agg_linux_mini_libc ,
+ agg_basics ,
+ agg_ctrl ,
+ agg_rendering_buffer ,
+ agg_trans_affine ,
+ agg_trans_viewport ,
+ agg_color_conv ,
+ file_utils_ ;
+
+const
+ {$IFDEF Ver2_2}
+ xFalse = False;
+ xTrue = True;
+ {$ELSE}
+ xFalse = 0;
+ xTrue = 1;
+ {$ENDIF}
+
+{ TYPES DEFINITION }
+const
+//----------------------------------------------------------window_flag_e
+// These are flags used in method init(). Not all of them are
+// applicable on different platforms, for example the win32_api
+// cannot use a hardware buffer (window_hw_buffer).
+// The implementation should simply ignore unsupported flags.
+ window_resize = 1;
+ window_hw_buffer = 2;
+ window_keep_aspect_ratio = 4;
+ window_process_all_keys = 8;
+
+type
+//-----------------------------------------------------------pix_format_e
+// Possible formats of the rendering buffer. Initially I thought that it's
+// reasonable to create the buffer and the rendering functions in
+// accordance with the native pixel format of the system because it
+// would have no overhead for pixel format conversion.
+// But eventually I came to a conclusion that having a possibility to
+// convert pixel formats on demand is a good idea. First, it was X11 where
+// there lots of different formats and visuals and it would be great to
+// render everything in, say, RGB-24 and display it automatically without
+// any additional efforts. The second reason is to have a possibility to
+// debug renderers for different pixel formats and colorspaces having only
+// one computer and one system.
+//
+// This stuff is not included into the basic AGG functionality because the
+// number of supported pixel formats (and/or colorspaces) can be great and
+// if one needs to add new format it would be good only to add new
+// rendering files without having to modify any existing ones (a general
+// principle of incapsulation and isolation).
+//
+// Using a particular pixel format doesn't obligatory mean the necessity
+// of software conversion. For example, win32 API can natively display
+// gray8, 15-bit RGB, 24-bit BGR, and 32-bit BGRA formats.
+// This list can be (and will be!) extended in future.
+ pix_format_e = (
+
+ pix_format_undefined , // By default. No conversions are applied
+ pix_format_bw, // 1 bit per color B/W
+ pix_format_gray8, // Simple 256 level grayscale
+ pix_format_gray16, // Simple 65535 level grayscale
+ pix_format_rgb555, // 15 bit rgb. Depends on the byte ordering!
+ pix_format_rgb565, // 16 bit rgb. Depends on the byte ordering!
+ pix_format_rgbAAA, // 30 bit rgb. Depends on the byte ordering!
+ pix_format_rgbBBA, // 32 bit rgb. Depends on the byte ordering!
+ pix_format_bgrAAA, // 30 bit bgr. Depends on the byte ordering!
+ pix_format_bgrABB, // 32 bit bgr. Depends on the byte ordering!
+ pix_format_rgb24, // R-G-B, one byte per color component
+ pix_format_bgr24, // B-G-R, native win32 BMP format.
+ pix_format_rgba32, // R-G-B-A, one byte per color component
+ pix_format_argb32, // A-R-G-B, native MAC format
+ pix_format_abgr32, // A-B-G-R, one byte per color component
+ pix_format_bgra32, // B-G-R-A, native win32 BMP format
+ pix_format_rgb48, // R-G-B, 16 bits per color component
+ pix_format_bgr48, // B-G-R, native win32 BMP format.
+ pix_format_rgba64, // R-G-B-A, 16 bits byte per color component
+ pix_format_argb64, // A-R-G-B, native MAC format
+ pix_format_abgr64, // A-B-G-R, one byte per color component
+ pix_format_bgra64, // B-G-R-A, native win32 BMP format
+
+ end_of_pix_formats );
+
+const
+//-------------------------------------------------------------input_flag_e
+// Mouse and keyboard flags. They can be different on different platforms
+// and the ways they are obtained are also different. But in any case
+// the system dependent flags should be mapped into these ones. The meaning
+// of that is as follows. For example, if kbd_ctrl is set it means that the
+// ctrl key is pressed and being held at the moment. They are also used in
+// the overridden methods such as on_mouse_move(), on_mouse_button_down(),
+// on_mouse_button_dbl_click(), on_mouse_button_up(), on_key().
+// In the method on_mouse_button_up() the mouse flags have different
+// meaning. They mean that the respective button is being released, but
+// the meaning of the keyboard flags remains the same.
+// There's absolut minimal set of flags is used because they'll be most
+// probably supported on different platforms. Even the mouse_right flag
+// is restricted because Mac's mice have only one button, but AFAIK
+// it can be simulated with holding a special key on the keydoard.
+ mouse_left = 1;
+ mouse_right = 2;
+ kbd_shift = 4;
+ kbd_ctrl = 8;
+
+//--------------------------------------------------------------key_code_e
+// Keyboard codes. There's also a restricted set of codes that are most
+// probably supported on different platforms. Any platform dependent codes
+// should be converted into these ones. There're only those codes are
+// defined that cannot be represented as printable ASCII-characters.
+// All printable ASCII-set can be used in a regilar C/C++ manner:
+// ' ', 'A', '0' '+' and so on.
+// Since the clasas is used for creating very simple demo-applications
+// we don't need very rich possibilities here, just basic ones.
+// Actually the numeric key codes are taken from the SDL library, so,
+// the implementation of the SDL support does not require any mapping.
+// ASCII set. Should be supported everywhere
+ key_backspace = 8;
+ key_tab = 9;
+ key_clear = 12;
+ key_return = 13;
+ key_pause = 19;
+ key_escape = 27;
+
+// Keypad
+ key_delete = 127;
+ key_kp0 = 256;
+ key_kp1 = 257;
+ key_kp2 = 258;
+ key_kp3 = 259;
+ key_kp4 = 260;
+ key_kp5 = 261;
+ key_kp6 = 262;
+ key_kp7 = 263;
+ key_kp8 = 264;
+ key_kp9 = 265;
+ key_kp_period = 266;
+ key_kp_divide = 267;
+ key_kp_multiply = 268;
+ key_kp_minus = 269;
+ key_kp_plus = 270;
+ key_kp_enter = 271;
+ key_kp_equals = 272;
+
+// Arrow-keys and stuff
+ key_up = 273;
+ key_down = 274;
+ key_right = 275;
+ key_left = 276;
+ key_insert = 277;
+ key_home = 278;
+ key_end = 279;
+ key_page_up = 280;
+ key_page_down = 281;
+
+// Functional keys. You'd better avoid using
+// f11...f15 in your applications if you want
+// the applications to be portable
+ key_f1 = 282;
+ key_f2 = 283;
+ key_f3 = 284;
+ key_f4 = 285;
+ key_f5 = 286;
+ key_f6 = 287;
+ key_f7 = 288;
+ key_f8 = 289;
+ key_f9 = 290;
+ key_f10 = 291;
+ key_f11 = 292;
+ key_f12 = 293;
+ key_f13 = 294;
+ key_f14 = 295;
+ key_f15 = 296;
+
+// The possibility of using these keys is
+// very restricted. Actually it's guaranteed
+// only in win32_api and win32_sdl implementations
+ key_numlock = 300;
+ key_capslock = 301;
+ key_scrollock = 302;
+
+ max_ctrl = 128;
+
+type
+//----------------------------------------------------------ctrl_container
+// A helper class that contains pointers to a number of controls.
+// This class is used to ease the event handling with controls.
+// The implementation should simply call the appropriate methods
+// of this class when appropriate events occure.
+ crtl_container_ptr = ^ctrl_container;
+ ctrl_container = object
+ m_ctrl : array[0..max_ctrl - 1 ] of ctrl_ptr;
+
+ m_num_ctrl : unsigned;
+ m_cur_ctrl : int;
+
+ constructor Construct;
+ destructor Destruct;
+
+ procedure add(c : ctrl_ptr );
+
+ function in_rect(x ,y : double ) : boolean;
+
+ function on_mouse_button_down(x ,y : double ) : boolean;
+ function on_mouse_button_up (x ,y : double ) : boolean;
+
+ function on_mouse_move(x ,y : double; button_flag : boolean ) : boolean;
+ function on_arrow_keys(left ,right ,down ,up : boolean ) : boolean;
+
+ function set_cur(x ,y : double ) : boolean;
+
+ end;
+
+//---------------------------------------------------------platform_support
+// This class is a base one to the apllication classes. It can be used
+// as follows:
+//
+// the_application = object(platform_support )
+//
+// constructor Construct(bpp : unsigned; flip_y : boolean );
+// . . .
+//
+// //override stuff . . .
+// procedure on_init; virtual;
+// procedure on_draw; virtual;
+// procedure on_resize(sx ,sy : int ); virtual;
+// // . . . and so on, see virtual functions
+//
+// //any your own stuff . . .
+// };
+//
+// VAR
+// app : the_application;
+//
+// BEGIN
+// app.Construct(pix_format_rgb24 ,true );
+// app.caption ("AGG Example. Lion" );
+//
+// if app.init(500 ,400 ,window_resize ) then
+// app.run;
+//
+// app.Destruct;
+//
+// END.
+//
+const
+ max_images = 16;
+
+type
+ platform_specific_ptr = ^platform_specific;
+ platform_specific = object
+ m_format ,
+ m_sys_format : pix_format_e;
+ m_byte_order : int;
+
+ m_flip_y : boolean;
+ m_bpp ,
+ m_sys_bpp : unsigned;
+ m_display : PDisplay;
+ m_screen ,
+ m_depth : int;
+ m_visual : PVisual;
+ m_window : TWindow;
+ m_gc : TGC;
+
+ m_window_attributes : TXSetWindowAttributes;
+
+ m_ximg_window : PXImage;
+ m_close_atom : TAtom;
+ m_buf_window : pointer;
+ m_buf_alloc : unsigned;
+ m_buf_img : array[0..max_images - 1 ] of pointer;
+ m_img_alloc : array[0..max_images - 1 ] of unsigned;
+
+ m_keymap : array[0..255 ] of unsigned;
+
+ m_update_flag ,
+ m_resize_flag ,
+ m_initialized : boolean;
+
+ //m_wait_mode : boolean;
+ m_sw_start : clock_t;
+
+ constructor Construct(format : pix_format_e; flip_y : boolean );
+ destructor Destruct;
+
+ procedure caption_ (capt : PChar );
+ procedure put_image(src : rendering_buffer_ptr );
+
+ end;
+
+ platform_support_ptr = ^platform_support;
+ platform_support = object
+ m_specific : platform_specific_ptr;
+ m_ctrls : ctrl_container;
+
+ m_format : pix_format_e;
+
+ m_bpp : unsigned;
+
+ m_rbuf_window : rendering_buffer;
+ m_rbuf_img : array[0..max_images - 1 ] of rendering_buffer;
+
+ m_window_flags : unsigned;
+ m_wait_mode ,
+ m_flip_y : boolean; // flip_y - true if you want to have the Y-axis flipped vertically
+ m_caption : shortstring;
+ m_resize_mtx : trans_affine;
+
+ m_initial_width ,
+ m_initial_height : int;
+
+ m_quit : boolean;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ // Setting the windows caption (title). Should be able
+ // to be called at least before calling init().
+ // It's perfect if they can be called anytime.
+ procedure caption_(cap : shortstring );
+
+ // These 3 menthods handle working with images. The image
+ // formats are the simplest ones, such as .BMP in Windows or
+ // .ppm in Linux. In the applications the names of the files
+ // should not have any file extensions. Method load_img() can
+ // be called before init(), so, the application could be able
+ // to determine the initial size of the window depending on
+ // the size of the loaded image.
+ // The argument "idx" is the number of the image 0...max_images-1
+ function load_img (idx : unsigned; file_ : shortstring ) : boolean;
+ function save_img (idx : unsigned; file_ : shortstring ) : boolean;
+ function create_img(idx : unsigned; width_ : unsigned = 0; height_ : unsigned = 0 ) : boolean;
+
+ // init() and run(). See description before the class for details.
+ // The necessity of calling init() after creation is that it's
+ // impossible to call the overridden virtual function (on_init())
+ // from the constructor. On the other hand it's very useful to have
+ // some on_init() event handler when the window is created but
+ // not yet displayed. The rbuf_window() method (see below) is
+ // accessible from on_init().
+ function init(width_ ,height_ ,flags : unsigned ) : boolean;
+ function run : int;
+ procedure quit;
+
+ // The very same parameters that were used in the constructor
+ function _format : pix_format_e;
+ function _flip_y : boolean;
+ function _bpp : unsigned;
+
+ // The following provides a very simple mechanism of doing someting
+ // in background. It's not multitheading. When whait_mode is true
+ // the class waits for the events and it does not ever call on_idle().
+ // When it's false it calls on_idle() when the event queue is empty.
+ // The mode can be changed anytime. This mechanism is satisfactory
+ // for creation very simple animations.
+ function _wait_mode : boolean;
+ procedure wait_mode_(wait_mode : boolean );
+
+ // These two functions control updating of the window.
+ // force_redraw() is an analog of the Win32 InvalidateRect() function.
+ // Being called it sets a flag (or sends a message) which results
+ // in calling on_draw() and updating the content of the window
+ // when the next event cycle comes.
+ // update_window() results in just putting immediately the content
+ // of the currently rendered buffer to the window without calling
+ // on_draw().
+ procedure force_redraw;
+ procedure update_window;
+
+ // So, finally, how to draw anythig with AGG? Very simple.
+ // rbuf_window() returns a reference to the main rendering
+ // buffer which can be attached to any rendering class.
+ // rbuf_img() returns a reference to the previously created
+ // or loaded image buffer (see load_img()). The image buffers
+ // are not displayed directly, they should be copied to or
+ // combined somehow with the rbuf_window(). rbuf_window() is
+ // the only buffer that can be actually displayed.
+ function rbuf_window : rendering_buffer_ptr;
+ function rbuf_img(idx : unsigned ) : rendering_buffer_ptr;
+
+ // Returns file extension used in the implemenation for the particular
+ // system.
+ function _img_ext : shortstring;
+
+ //
+ procedure copy_img_to_window(idx : unsigned );
+ procedure copy_window_to_img(idx : unsigned );
+ procedure copy_img_to_img (idx_to ,idx_from : unsigned );
+
+ // Event handlers. They are not pure functions, so you don't have
+ // to override them all.
+ // In my demo applications these functions are defined inside
+ // the the_application class
+ procedure on_init; virtual;
+ procedure on_resize(sx ,sy : int ); virtual;
+ procedure on_idle; virtual;
+
+ procedure on_mouse_move(x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_up (x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+ procedure on_ctrl_change; virtual;
+ procedure on_draw; virtual;
+ procedure on_post_draw(raw_handler : pointer ); virtual;
+
+ // Adding control elements. A control element once added will be
+ // working and reacting to the mouse and keyboard events. Still, you
+ // will have to render them in the on_draw() using function
+ // render_ctrl() because platform_support doesn't know anything about
+ // renderers you use. The controls will be also scaled automatically
+ // if they provide a proper scaling mechanism (all the controls
+ // included into the basic AGG package do).
+ // If you don't need a particular control to be scaled automatically
+ // call ctrl::no_transform() after adding.
+ procedure add_ctrl(c : ctrl_ptr );
+
+ // Auxiliary functions. trans_affine_resizing() modifier sets up the resizing
+ // matrix on the basis of the given width and height and the initial
+ // width and height of the window. The implementation should simply
+ // call this function every time when it catches the resizing event
+ // passing in the new values of width and height of the window.
+ // Nothing prevents you from "cheating" the scaling matrix if you
+ // call this function from somewhere with wrong arguments.
+ // trans_affine_resizing() accessor simply returns current resizing matrix
+ // which can be used to apply additional scaling of any of your
+ // stuff when the window is being resized.
+ // width(), height(), initial_width(), and initial_height() must be
+ // clear to understand with no comments :-)
+ procedure trans_affine_resizing_(width_ ,height_ : int );
+ function _trans_affine_resizing : trans_affine_ptr;
+
+ function _width : double;
+ function _height : double;
+ function _initial_width : double;
+ function _initial_height : double;
+ function _window_flags : unsigned;
+
+ // Get raw display handler depending on the system.
+ // For win32 its an HDC, for other systems it can be a pointer to some
+ // structure. See the implementation files for detals.
+ // It's provided "as is", so, first you should check if it's not null.
+ // If it's null the raw_display_handler is not supported. Also, there's
+ // no guarantee that this function is implemented, so, in some
+ // implementations you may have simply an unresolved symbol when linking.
+ function _raw_display_handler : pointer;
+
+ // display message box or print the message to the console
+ // (depending on implementation)
+ procedure message_(msg : PChar );
+
+ // Stopwatch functions. Function elapsed_time() returns time elapsed
+ // since the latest start_timer() invocation in millisecods.
+ // The resolutoin depends on the implementation.
+ // In Win32 it uses QueryPerformanceFrequency() / QueryPerformanceCounter().
+ procedure start_timer;
+ function elapsed_time : double;
+
+ // Get the full file name. In most cases it simply returns
+ // file_name. As it's appropriate in many systems if you open
+ // a file by its name without specifying the path, it tries to
+ // open it in the current directory. The demos usually expect
+ // all the supplementary files to be placed in the current
+ // directory, that is usually coincides with the directory where
+ // the the executable is. However, in some systems (BeOS) it's not so.
+ // For those kinds of systems full_file_name() can help access files
+ // preserving commonly used policy.
+ // So, it's a good idea to use in the demos the following:
+ // FILE* fd = fopen(full_file_name("some.file"), "r");
+ // instead of
+ // FILE* fd = fopen("some.file", "r");
+ function full_file_name(file_name : shortstring ) : shortstring;
+ function file_source (path ,fname : shortstring ) : shortstring;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor ctrl_container.Construct;
+begin
+ m_num_ctrl:=0;
+ m_cur_ctrl:=-1;
+
+end;
+
+{ DESTRUCT }
+destructor ctrl_container.Destruct;
+begin
+end;
+
+{ ADD }
+procedure ctrl_container.add;
+begin
+ if m_num_ctrl < max_ctrl then
+ begin
+ m_ctrl[m_num_ctrl ]:=c;
+
+ inc(m_num_ctrl );
+
+ end;
+
+end;
+
+{ IN_RECT }
+function ctrl_container.in_rect;
+var
+ i : unsigned;
+
+begin
+ result:=false;
+
+ if m_num_ctrl > 0 then
+ for i:=0 to m_num_ctrl - 1 do
+ if m_ctrl[i ].in_rect(x ,y ) then
+ begin
+ result:=true;
+
+ exit;
+
+ end;
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+function ctrl_container.on_mouse_button_down;
+var
+ i : unsigned;
+
+begin
+ result:=false;
+
+ if m_num_ctrl > 0 then
+ for i:=0 to m_num_ctrl - 1 do
+ if m_ctrl[i ].on_mouse_button_down(x ,y ) then
+ begin
+ result:=true;
+
+ exit;
+
+ end;
+
+end;
+
+{ ON_MOUSE_BUTTON_UP }
+function ctrl_container.on_mouse_button_up;
+var
+ i : unsigned;
+
+begin
+ result:=false;
+
+ if m_num_ctrl > 0 then
+ for i:=0 to m_num_ctrl - 1 do
+ if m_ctrl[i ].on_mouse_button_up(x ,y ) then
+ begin
+ result:=true;
+
+ exit;
+
+ end;
+
+end;
+
+{ ON_MOUSE_MOVE }
+function ctrl_container.on_mouse_move;
+var
+ i : unsigned;
+
+begin
+ result:=false;
+
+ if m_num_ctrl > 0 then
+ for i:=0 to m_num_ctrl - 1 do
+ if m_ctrl[i ].on_mouse_move(x ,y ,button_flag ) then
+ begin
+ result:=true;
+
+ exit;
+
+ end;
+
+end;
+
+{ ON_ARROW_KEYS }
+function ctrl_container.on_arrow_keys;
+begin
+ result:=false;
+
+ if m_cur_ctrl >= 0 then
+ result:=m_ctrl[m_cur_ctrl ].on_arrow_keys(left ,right ,down ,up );
+
+end;
+
+{ SET_CUR }
+function ctrl_container.set_cur;
+var
+ i : unsigned;
+
+begin
+ result:=false;
+
+ if m_num_ctrl > 0 then
+ for i:=0 to m_num_ctrl - 1 do
+ if m_ctrl[i ].in_rect(x ,y ) then
+ begin
+ if m_cur_ctrl <> i then
+ begin
+ m_cur_ctrl:=i;
+
+ result:=true;
+
+ end;
+
+ exit;
+
+ end;
+
+ if m_cur_ctrl <> -1 then
+ begin
+ m_cur_ctrl:=-1;
+
+ result:=true;
+
+ end;
+
+end;
+
+{ CONSTRUCT }
+constructor platform_specific.Construct;
+var
+ i : unsigned;
+
+begin
+ m_format :=format;
+ m_sys_format:=pix_format_undefined;
+ m_byte_order:=LSBFirst;
+ m_flip_y :=flip_y;
+
+ m_bpp :=0;
+ m_sys_bpp:=0;
+ m_display:=NIL;
+ m_screen :=0;
+ m_depth :=0;
+ m_visual :=NIL;
+ m_window :=0;
+ m_gc :=NIL;
+
+ m_ximg_window:=NIL;
+ m_close_atom :=0;
+ m_buf_window :=NIL;
+ m_buf_alloc :=0;
+
+ m_update_flag:=true;
+ m_resize_flag:=true;
+ m_initialized:=false;
+ //m_wait_mode:=true;
+
+ fillchar(m_buf_img[0 ] ,sizeof(m_buf_img ) ,0 );
+
+ for i:=0 to 255 do
+ m_keymap[i ]:=i;
+
+ m_keymap[XK_Pause and $FF ]:=key_pause;
+ m_keymap[XK_Clear and $FF ]:=key_clear;
+
+ m_keymap[XK_KP_0 and $FF ]:=key_kp0;
+ m_keymap[XK_KP_1 and $FF ]:=key_kp1;
+ m_keymap[XK_KP_2 and $FF ]:=key_kp2;
+ m_keymap[XK_KP_3 and $FF ]:=key_kp3;
+ m_keymap[XK_KP_4 and $FF ]:=key_kp4;
+ m_keymap[XK_KP_5 and $FF ]:=key_kp5;
+ m_keymap[XK_KP_6 and $FF ]:=key_kp6;
+ m_keymap[XK_KP_7 and $FF ]:=key_kp7;
+ m_keymap[XK_KP_8 and $FF ]:=key_kp8;
+ m_keymap[XK_KP_9 and $FF ]:=key_kp9;
+
+ m_keymap[XK_KP_Insert and $FF ] :=key_kp0;
+ m_keymap[XK_KP_End and $FF ] :=key_kp1;
+ m_keymap[XK_KP_Down and $FF ] :=key_kp2;
+ m_keymap[XK_KP_Page_Down and $FF ]:=key_kp3;
+ m_keymap[XK_KP_Left and $FF ] :=key_kp4;
+ m_keymap[XK_KP_Begin and $FF ] :=key_kp5;
+ m_keymap[XK_KP_Right and $FF ] :=key_kp6;
+ m_keymap[XK_KP_Home and $FF ] :=key_kp7;
+ m_keymap[XK_KP_Up and $FF ] :=key_kp8;
+ m_keymap[XK_KP_Page_Up and $FF ] :=key_kp9;
+ m_keymap[XK_KP_Delete and $FF ] :=key_kp_period;
+ m_keymap[XK_KP_Decimal and $FF ] :=key_kp_period;
+ m_keymap[XK_KP_Divide and $FF ] :=key_kp_divide;
+ m_keymap[XK_KP_Multiply and $FF ] :=key_kp_multiply;
+ m_keymap[XK_KP_Subtract and $FF ] :=key_kp_minus;
+ m_keymap[XK_KP_Add and $FF ] :=key_kp_plus;
+ m_keymap[XK_KP_Enter and $FF ] :=key_kp_enter;
+ m_keymap[XK_KP_Equal and $FF ] :=key_kp_equals;
+
+ m_keymap[XK_Up and $FF ] :=key_up;
+ m_keymap[XK_Down and $FF ] :=key_down;
+ m_keymap[XK_Right and $FF ] :=key_right;
+ m_keymap[XK_Left and $FF ] :=key_left;
+ m_keymap[XK_Insert and $FF ] :=key_insert;
+ m_keymap[XK_Home and $FF ] :=key_delete;
+ m_keymap[XK_End and $FF ] :=key_end;
+ m_keymap[XK_Page_Up and $FF ] :=key_page_up;
+ m_keymap[XK_Page_Down and $FF ]:=key_page_down;
+
+ m_keymap[XK_F1 and $FF ] :=key_f1;
+ m_keymap[XK_F2 and $FF ] :=key_f2;
+ m_keymap[XK_F3 and $FF ] :=key_f3;
+ m_keymap[XK_F4 and $FF ] :=key_f4;
+ m_keymap[XK_F5 and $FF ] :=key_f5;
+ m_keymap[XK_F6 and $FF ] :=key_f6;
+ m_keymap[XK_F7 and $FF ] :=key_f7;
+ m_keymap[XK_F8 and $FF ] :=key_f8;
+ m_keymap[XK_F9 and $FF ] :=key_f9;
+ m_keymap[XK_F10 and $FF ]:=key_f10;
+ m_keymap[XK_F11 and $FF ]:=key_f11;
+ m_keymap[XK_F12 and $FF ]:=key_f12;
+ m_keymap[XK_F13 and $FF ]:=key_f13;
+ m_keymap[XK_F14 and $FF ]:=key_f14;
+ m_keymap[XK_F15 and $FF ]:=key_f15;
+
+ m_keymap[XK_Num_Lock and $FF ] :=key_numlock;
+ m_keymap[XK_Caps_Lock and $FF ] :=key_capslock;
+ m_keymap[XK_Scroll_Lock and $FF ]:=key_scrollock;
+
+ case m_format of
+ pix_format_gray8 :
+ m_bpp:=8;
+
+ pix_format_rgb565 ,
+ pix_format_rgb555 :
+ m_bpp:=16;
+
+ pix_format_rgb24 ,
+ pix_format_bgr24 :
+ m_bpp:=24;
+
+ pix_format_bgra32 ,
+ pix_format_abgr32 ,
+ pix_format_argb32 ,
+ pix_format_rgba32 :
+ m_bpp:=32;
+
+ end;
+
+ m_sw_start:=clock;
+
+end;
+
+{ DESTRUCT }
+destructor platform_specific.Destruct;
+begin
+end;
+
+{ CAPTION_ }
+procedure platform_specific.caption_;
+var
+ tp : TXTextProperty;
+
+begin
+ tp.value :=PCUChar(@capt[1 ] );
+ tp.encoding:=XA_WM_NAME;
+ tp.format :=8;
+ tp.nitems :=strlen(capt );
+
+ XSetWMName (m_display ,m_window ,@tp );
+ XStoreName (m_display ,m_window ,capt );
+ XSetIconName (m_display ,m_window ,capt );
+ XSetWMIconName(m_display ,m_window ,@tp );
+
+end;
+
+{ PUT_IMAGE }
+procedure platform_specific.put_image;
+var
+ row_len : int;
+ buf_tmp : pointer;
+
+ rbuf_tmp : rendering_buffer;
+
+begin
+ if m_ximg_window = NIL then
+ exit;
+
+ m_ximg_window.data:=m_buf_window;
+
+ if m_format = m_sys_format then
+ XPutImage(
+ m_display ,
+ m_window ,
+ m_gc ,
+ m_ximg_window ,
+ 0 ,0 ,0 ,0 ,
+ src._width ,
+ src._height )
+
+ else
+ begin
+ row_len:=src._width * m_sys_bpp div 8;
+
+ agg_getmem(buf_tmp ,row_len * src._height );
+
+ rbuf_tmp.Construct;
+
+ if m_flip_y then
+ rbuf_tmp.attach(
+ buf_tmp ,
+ src._width,
+ src._height ,
+ -row_len )
+ else
+ rbuf_tmp.attach(
+ buf_tmp ,
+ src._width,
+ src._height ,
+ row_len );
+
+ case m_sys_format of
+ pix_format_rgb555 :
+ case m_format of
+ pix_format_rgb555 : color_conv(@rbuf_tmp ,src ,color_conv_rgb555_to_rgb555 );
+ pix_format_rgb565 : color_conv(@rbuf_tmp ,src ,color_conv_rgb565_to_rgb555 );
+ //pix_format_rgb24 : color_conv(@rbuf_tmp ,src ,color_conv_rgb24_to_rgb555 );
+ pix_format_bgr24 : color_conv(@rbuf_tmp ,src ,color_conv_bgr24_to_rgb555 );
+ //pix_format_rgba32 : color_conv(@rbuf_tmp ,src ,color_conv_rgba32_to_rgb555 );
+ //pix_format_argb32 : color_conv(@rbuf_tmp ,src ,color_conv_argb32_to_rgb555 );
+ pix_format_bgra32 : color_conv(@rbuf_tmp ,src ,color_conv_bgra32_to_rgb555 );
+ //pix_format_abgr32 : color_conv(@rbuf_tmp ,src ,color_conv_abgr32_to_rgb555 );
+
+ end;
+
+ pix_format_rgb565 :
+ case m_format of
+ pix_format_rgb555 : color_conv(@rbuf_tmp ,src ,color_conv_rgb555_to_rgb565 );
+ //pix_format_rgb565 : color_conv(@rbuf_tmp ,src ,color_conv_rgb565_to_rgb565 );
+ //pix_format_rgb24 : color_conv(@rbuf_tmp ,src ,color_conv_rgb24_to_rgb565 );
+ pix_format_bgr24 : color_conv(@rbuf_tmp ,src ,color_conv_bgr24_to_rgb565 );
+ //pix_format_rgba32 : color_conv(@rbuf_tmp ,src ,color_conv_rgba32_to_rgb565 );
+ //pix_format_argb32 : color_conv(@rbuf_tmp ,src ,color_conv_argb32_to_rgb565 );
+ pix_format_bgra32 : color_conv(@rbuf_tmp ,src ,color_conv_bgra32_to_rgb565 );
+ //pix_format_abgr32 : color_conv(@rbuf_tmp ,src ,color_conv_abgr32_to_rgb565 );
+
+ end;
+
+ pix_format_rgba32 :
+ case m_format of
+ pix_format_rgb555 : color_conv(@rbuf_tmp ,src ,color_conv_rgb555_to_rgba32 );
+ //pix_format_rgb565 : color_conv(@rbuf_tmp ,src ,color_conv_rgb565_to_rgba32 );
+ //pix_format_rgb24 : color_conv(@rbuf_tmp ,src ,color_conv_rgb24_to_rgba32 );
+ pix_format_bgr24 : color_conv(@rbuf_tmp ,src ,color_conv_bgr24_to_rgba32 );
+ //pix_format_rgba32 : color_conv(@rbuf_tmp ,src ,color_conv_rgba32_to_rgba32 );
+ //pix_format_argb32 : color_conv(@rbuf_tmp ,src ,color_conv_argb32_to_rgba32 );
+ pix_format_bgra32 : color_conv(@rbuf_tmp ,src ,color_conv_bgra32_to_rgba32 );
+ //pix_format_abgr32 : color_conv(@rbuf_tmp ,src ,color_conv_abgr32_to_rgba32 );
+
+ end;
+
+ pix_format_abgr32 :
+ case m_format of
+ pix_format_rgb555 : color_conv(@rbuf_tmp ,src ,color_conv_rgb555_to_abgr32 );
+ //pix_format_rgb565 : color_conv(@rbuf_tmp ,src ,color_conv_rgb565_to_abgr32 );
+ //pix_format_rgb24 : color_conv(@rbuf_tmp ,src ,color_conv_rgb24_to_abgr32 );
+ pix_format_bgr24 : color_conv(@rbuf_tmp ,src ,color_conv_bgr24_to_abgr32 );
+ //pix_format_abgr32 : color_conv(@rbuf_tmp ,src ,color_conv_abgr32_to_abgr32 );
+ //pix_format_rgba32 : color_conv(@rbuf_tmp ,src ,color_conv_rgba32_to_abgr32 );
+ //pix_format_argb32 : color_conv(@rbuf_tmp ,src ,color_conv_argb32_to_abgr32 );
+ pix_format_bgra32 : color_conv(@rbuf_tmp ,src ,color_conv_bgra32_to_abgr32 );
+
+ end;
+
+ pix_format_argb32 :
+ case m_format of
+ pix_format_rgb555 : color_conv(@rbuf_tmp ,src ,color_conv_rgb555_to_argb32 );
+ //pix_format_rgb565 : color_conv(@rbuf_tmp ,src ,color_conv_rgb565_to_argb32 );
+ //pix_format_rgb24 : color_conv(@rbuf_tmp ,src ,color_conv_rgb24_to_argb32 );
+ pix_format_bgr24 : color_conv(@rbuf_tmp ,src ,color_conv_bgr24_to_argb32 );
+ pix_format_rgba32 : color_conv(@rbuf_tmp ,src ,color_conv_rgba32_to_argb32 );
+ //pix_format_argb32 : color_conv(@rbuf_tmp ,src ,color_conv_argb32_to_argb32 );
+ pix_format_abgr32 : color_conv(@rbuf_tmp ,src ,color_conv_abgr32_to_argb32 );
+ pix_format_bgra32 : color_conv(@rbuf_tmp ,src ,color_conv_bgra32_to_argb32 );
+
+ end;
+
+ pix_format_bgra32 :
+ case m_format of
+ pix_format_rgb555 : color_conv(@rbuf_tmp ,src ,color_conv_rgb555_to_bgra32 );
+ //pix_format_rgb565 : color_conv(@rbuf_tmp ,src ,color_conv_rgb565_to_bgra32 );
+ //pix_format_rgb24 : color_conv(@rbuf_tmp ,src ,color_conv_rgb24_to_bgra32 );
+ pix_format_bgr24 : color_conv(@rbuf_tmp ,src ,color_conv_bgr24_to_bgra32 );
+ pix_format_rgba32 : color_conv(@rbuf_tmp ,src ,color_conv_rgba32_to_bgra32 );
+ pix_format_argb32 : color_conv(@rbuf_tmp ,src ,color_conv_argb32_to_bgra32 );
+ pix_format_abgr32 : color_conv(@rbuf_tmp ,src ,color_conv_abgr32_to_bgra32 );
+ pix_format_bgra32 : color_conv(@rbuf_tmp ,src ,color_conv_bgra32_to_bgra32 );
+
+ end;
+
+ end;
+
+ m_ximg_window.data:=buf_tmp;
+
+ XPutImage(
+ m_display ,
+ m_window ,
+ m_gc ,
+ m_ximg_window ,
+ 0 ,0 ,0 ,0 ,
+ src._width ,
+ src._height );
+
+ agg_freemem(buf_tmp ,row_len * src._height );
+
+ rbuf_tmp.Destruct;
+
+ end;
+
+end;
+
+{ CONSTRUCT }
+constructor platform_support.Construct;
+var
+ i : unsigned;
+
+ p ,n ,x : shortstring;
+
+begin
+ new(m_specific ,Construct(format_ ,flip_y_ ) );
+
+ m_ctrls.Construct;
+ m_rbuf_window.Construct;
+
+ for i:=0 to max_images - 1 do
+ m_rbuf_img[i ].Construct;
+
+ m_resize_mtx.Construct;
+
+ m_format:=format_;
+
+ m_bpp:=m_specific.m_bpp;
+
+ m_window_flags:=0;
+ m_wait_mode :=true;
+ m_flip_y :=flip_y_;
+
+ m_initial_width :=10;
+ m_initial_height:=10;
+
+ m_caption:='Anti-Grain Geometry Application'#0;
+
+// Change working dir to the application one
+ spread_name(ParamStr(0 ) ,p ,n ,x );
+
+ p:=p + #0;
+
+ SetCurrentDir(p);
+
+end;
+
+{ DESTRUCT }
+destructor platform_support.Destruct;
+var
+ i : unsigned;
+
+begin
+ dispose(m_specific ,Destruct );
+
+ m_ctrls.Destruct;
+ m_rbuf_window.Destruct;
+
+ for i:=0 to max_images - 1 do
+ m_rbuf_img[i ].Destruct;
+
+end;
+
+{ CAPTION_ }
+procedure platform_support.caption_;
+begin
+ m_caption:=cap + #0;
+
+ dec(byte(m_caption[0 ] ) );
+
+ if m_specific.m_initialized then
+ m_specific.caption_(PChar(@m_caption[1 ] ) );
+
+end;
+
+{ isdigit }
+function isdigit(c : char ) : boolean;
+begin
+ case c of
+ '0'..'9' :
+ result:=true;
+
+ else
+ result:=false;
+
+ end;
+
+end;
+
+{ atoi }
+function atoi(c : char_ptr ) : int;
+var
+ s : shortstring;
+ e : int;
+
+begin
+ s:='';
+
+ repeat
+ case c^ of
+ '0'..'9' :
+ s:=s + c^;
+
+ else
+ break;
+
+ end;
+
+ inc(ptrcomp(c ) );
+
+ until false;
+
+ val(s ,result ,e );
+
+end;
+
+{ LOAD_IMG }
+function platform_support.load_img;
+var
+ fd : file;
+ buf : array[0..1023 ] of char;
+ len : int;
+ ptr : char_ptr;
+ ret : boolean;
+
+ width ,height : unsigned;
+
+ buf_img : pointer;
+ rbuf_img_ : rendering_buffer;
+
+begin
+ result:=false;
+
+ if idx < max_images then
+ begin
+ file_:=file_ + _img_ext;
+
+ if not file_exists(file_ ) then
+ file_:='ppm/' + file_;
+
+ AssignFile(fd ,file_ );
+ reset (fd ,1 );
+
+ if IOResult <> 0 then
+ exit;
+
+ blockread(fd ,buf ,1022 ,len );
+
+ if len = 0 then
+ begin
+ close(fd );
+ exit;
+
+ end;
+
+ buf[len ]:=#0;
+
+ if (buf[0 ] <> 'P' ) and
+ (buf[1 ] <> '6' ) then
+ begin
+ close(fd );
+ exit;
+
+ end;
+
+ ptr:=@buf[2 ];
+
+ while (ptr^ <> #0 ) and
+ not isdigit(ptr^ ) do
+ inc(ptrcomp(ptr ) );
+
+ if ptr^ = #0 then
+ begin
+ close(fd );
+ exit;
+
+ end;
+
+ width:=atoi(ptr );
+
+ if (width = 0 ) or
+ (width > 4096 ) then
+ begin
+ close(fd );
+ exit;
+
+ end;
+
+ while (ptr^ <> #0 ) and
+ isdigit(ptr^ ) do
+ inc(ptrcomp(ptr ) );
+
+ while (ptr^ <> #0 ) and
+ not isdigit(ptr^ ) do
+ inc(ptrcomp(ptr ) );
+
+ if ptr^ = #0 then
+ begin
+ close(fd );
+ exit;
+
+ end;
+
+ height:=atoi(ptr );
+
+ if (height = 0 ) or
+ (height > 4096 ) then
+ begin
+ close(fd );
+ exit;
+
+ end;
+
+ while (ptr^ <> #0 ) and
+ isdigit(ptr^ ) do
+ inc(ptrcomp(ptr ) );
+
+ while (ptr^ <> #0 ) and
+ not isdigit(ptr^ ) do
+ inc(ptrcomp(ptr ) );
+
+ if atoi(ptr ) <> 255 then
+ begin
+ close(fd );
+ exit;
+
+ end;
+
+ while (ptr^ <> #0 ) and
+ isdigit(ptr^ ) do
+ inc(ptrcomp(ptr ) );
+
+ if ptr^ = #0 then
+ begin
+ close(fd );
+ exit;
+
+ end;
+
+ inc (ptrcomp(ptr ) );
+ seek (fd ,ptrcomp(ptr ) - ptrcomp(@buf ) );
+ create_img(idx ,width ,height );
+
+ ret:=true;
+
+ if m_format = pix_format_rgb24 then
+ blockread(fd ,m_specific.m_buf_img[idx ]^ ,width * height * 3 )
+ else
+ begin
+ agg_getmem(buf_img ,width * height * 3 );
+
+ rbuf_img_.Construct;
+
+ if m_flip_y then
+ rbuf_img_.attach(buf_img ,width ,height ,-width * 3 )
+ else
+ rbuf_img_.attach(buf_img ,width ,height ,width * 3 );
+
+ blockread(fd ,buf_img^ ,width * height * 3 );
+
+ case m_format of
+ //pix_format_rgb555 : color_conv(@m_rbuf_img[idx ] ,@rbuf_img_ ,color_conv_rgb24_to_rgb555 );
+ //pix_format_rgb565 : color_conv(@m_rbuf_img[idx ] ,@rbuf_img_ ,color_conv_rgb24_to_rgb565 );
+ pix_format_bgr24 : color_conv(@m_rbuf_img[idx ] ,@rbuf_img_ ,color_conv_rgb24_to_bgr24 );
+ //pix_format_rgba32 : color_conv(@m_rbuf_img[idx ] ,@rbuf_img_ ,color_conv_rgb24_to_rgba32 );
+ //pix_format_argb32 : color_conv(@m_rbuf_img[idx ] ,@rbuf_img_ ,color_conv_rgb24_to_argb32 );
+ pix_format_bgra32 : color_conv(@m_rbuf_img[idx ] ,@rbuf_img_ ,color_conv_rgb24_to_bgra32 );
+ //pix_format_abgr32 : color_conv(@m_rbuf_img[idx ] ,@rbuf_img_ ,color_conv_rgb24_to_abgr32 );
+ else
+ ret:=false;
+
+ end;
+
+ agg_freemem(buf_img ,width * height * 3 );
+
+ rbuf_img_.Destruct;
+
+ end;
+
+ close(fd );
+
+ result:=ret;
+
+ end;
+
+end;
+
+{ SAVE_IMG }
+function platform_support.save_img;
+var
+ fd : file;
+
+ s ,c : shortstring;
+
+ w ,h ,y : unsigned;
+
+ tmp_buf ,src : pointer;
+
+begin
+ result:=false;
+
+ if (idx < max_images ) and
+ (rbuf_img(idx )._buf <> NIL ) then
+ begin
+ AssignFile(fd ,file_ );
+ rewrite (fd ,1 );
+
+ if IOResult <> 0 then
+ exit;
+
+ w:=rbuf_img(idx )._width;
+ h:=rbuf_img(idx )._height;
+
+ str(w ,c );
+
+ s:='P6'#13 + c + ' ';
+
+ str(h ,c );
+
+ s:=s + c + #13'255'#13;
+
+ blockwrite(fd ,s[1 ] ,length(s ) );
+
+ agg_getmem(tmp_buf ,w * 3 );
+
+ y:=0;
+
+ while y < rbuf_img(idx )._height do
+ begin
+ if m_flip_y then
+ src:=rbuf_img(idx ).row(h - 1 - y )
+ else
+ src:=rbuf_img(idx ).row(y );
+
+ case m_format of
+ pix_format_rgb555 : color_conv_rgb555_to_rgb24(tmp_buf ,src ,w );
+ //pix_format_rgb565 : color_conv_rgb565_to_rgb24(tmp_buf ,src ,w );
+ pix_format_bgr24 : color_conv_bgr24_to_rgb24 (tmp_buf ,src ,w );
+ //pix_format_rgb24 : color_conv_rgb24_to_rgb24 (tmp_buf ,src ,w );
+ //pix_format_rgba32 : color_conv_rgba32_to_rgb24(tmp_buf ,src ,w );
+ //pix_format_argb32 : color_conv_argb32_to_rgb24(tmp_buf ,src ,w );
+ pix_format_bgra32 : color_conv_bgra32_to_rgb24(tmp_buf ,src ,w );
+ //pix_format_abgr32 : color_conv_abgr32_to_rgb24(tmp_buf ,src ,w );
+
+ end;
+
+ blockwrite(fd ,tmp_buf^ ,w * 3 );
+ inc (y );
+
+ end;
+
+ agg_getmem(tmp_buf ,w * 3 );
+ close (fd );
+
+ result:=true;
+
+ end;
+
+end;
+
+{ CREATE_IMG }
+function platform_support.create_img;
+begin
+ result:=false;
+
+ if idx < max_images then
+ begin
+ if width_ = 0 then
+ width_:=trunc(rbuf_window._width );
+
+ if height_ = 0 then
+ height_:=trunc(rbuf_window._height );
+
+ agg_freemem(m_specific.m_buf_img[idx ] ,m_specific.m_img_alloc[idx ] );
+
+ m_specific.m_img_alloc[idx ]:=width_ * height_ * (m_bpp div 8 );
+
+ agg_getmem(m_specific.m_buf_img[idx ] ,m_specific.m_img_alloc[idx ] );
+
+ if m_flip_y then
+ m_rbuf_img[idx ].attach(
+ m_specific.m_buf_img[idx ] ,
+ width_ ,height_ ,
+ -width_ * (m_bpp div 8 ) )
+ else
+ m_rbuf_img[idx ].attach(
+ m_specific.m_buf_img[idx ] ,
+ width_ ,height_ ,
+ width_ * (m_bpp div 8 ) );
+
+ result:=true;
+
+ end;
+
+end;
+
+{ INIT }
+function platform_support.init;
+const
+ xevent_mask =
+ PointerMotionMask or
+ ButtonPressMask or
+ ButtonReleaseMask or
+ ExposureMask or
+ KeyPressMask or
+ StructureNotifyMask;
+
+var
+ r_mask ,g_mask ,b_mask ,window_mask : unsigned;
+
+ t ,hw_byte_order : int;
+
+ hints : PXSizeHints;
+
+begin
+ m_window_flags:=flags;
+
+ m_specific.m_display:=XOpenDisplay(NIL );
+
+ if m_specific.m_display = NIL then
+ begin
+ writeln(stderr ,'Unable to open DISPLAY!' );
+
+ result:=false;
+
+ exit;
+
+ end;
+
+ m_specific.m_screen:=XDefaultScreen(m_specific.m_display );
+ m_specific.m_depth :=XDefaultDepth (m_specific.m_display ,m_specific.m_screen );
+ m_specific.m_visual:=XDefaultVisual(m_specific.m_display ,m_specific.m_screen );
+
+ r_mask:=m_specific.m_visual.red_mask;
+ g_mask:=m_specific.m_visual.green_mask;
+ b_mask:=m_specific.m_visual.blue_mask;
+
+ if (m_specific.m_depth < 15 ) or
+ (r_mask = 0 ) or
+ (g_mask = 0 ) or
+ (b_mask = 0 ) then
+ begin
+ writeln(stderr ,'There''s no Visual compatible with minimal AGG requirements:' );
+ writeln(stderr ,'At least 15-bit color depth and True- or DirectColor class.' );
+ writeln(stderr );
+
+ XCloseDisplay(m_specific.m_display );
+
+ result:=false;
+
+ exit;
+
+ end;
+
+ t:=1;
+
+ hw_byte_order:=LSBFirst;
+
+ if byte(pointer(@t )^ ) = 0 then
+ hw_byte_order:=MSBFirst;
+
+// Perceive SYS-format by mask
+ case m_specific.m_depth of
+ 15 :
+ begin
+ m_specific.m_sys_bpp:=16;
+
+ if (r_mask = $7C00 ) and
+ (g_mask = $3E0 ) and
+ (b_mask = $1F ) then
+ begin
+ m_specific.m_sys_format:=pix_format_rgb555;
+ m_specific.m_byte_order:=hw_byte_order;
+
+ end;
+
+ end;
+
+ 16 :
+ begin
+ m_specific.m_sys_bpp:=16;
+
+ if (r_mask = $F800 ) and
+ (g_mask = $7E0 ) and
+ (b_mask = $1F ) then
+ begin
+ m_specific.m_sys_format:=pix_format_rgb565;
+ m_specific.m_byte_order:=hw_byte_order;
+
+ end;
+
+ end;
+
+ 24 ,32 :
+ begin
+ m_specific.m_sys_bpp:=32;
+
+ if g_mask = $FF00 then
+ begin
+ if (r_mask = $FF ) and
+ (b_mask = $FF0000 ) then
+ case m_specific.m_format of
+ pix_format_rgba32 :
+ begin
+ m_specific.m_sys_format:=pix_format_rgba32;
+ m_specific.m_byte_order:=LSBFirst;
+
+ end;
+
+ pix_format_abgr32 :
+ begin
+ m_specific.m_sys_format:=pix_format_abgr32;
+ m_specific.m_byte_order:=MSBFirst;
+
+ end;
+
+ else
+ begin
+ m_specific.m_byte_order:=hw_byte_order;
+
+ if hw_byte_order = LSBFirst then
+ m_specific.m_sys_format:=pix_format_rgba32
+ else
+ m_specific.m_sys_format:=pix_format_abgr32;
+
+ end;
+
+ end;
+
+ if (r_mask = $FF0000 ) and
+ (b_mask = $FF ) then
+ case m_specific.m_format of
+ pix_format_argb32 :
+ begin
+ m_specific.m_sys_format:=pix_format_argb32;
+ m_specific.m_byte_order:=MSBFirst;
+
+ end;
+
+ pix_format_bgra32 :
+ begin
+ m_specific.m_sys_format:=pix_format_bgra32;
+ m_specific.m_byte_order:=LSBFirst;
+
+ end;
+
+ else
+ begin
+ m_specific.m_byte_order:=hw_byte_order;
+
+ if hw_byte_order = MSBFirst then
+ m_specific.m_sys_format:=pix_format_argb32
+ else
+ m_specific.m_sys_format:=pix_format_bgra32;
+
+ end;
+
+ end;
+
+ end;
+
+ end;
+
+ end;
+
+ if m_specific.m_sys_format = pix_format_undefined then
+ begin
+ writeln(stderr ,'RGB masks are not compatible with AGG pixel formats:' );
+ write (stderr ,'R=' ,r_mask ,'G=' ,g_mask ,'B=' ,b_mask );
+
+ XCloseDisplay(m_specific.m_display );
+
+ result:=false;
+
+ exit;
+
+ end;
+
+ fillchar(
+ m_specific.m_window_attributes ,
+ sizeof(m_specific.m_window_attributes ) ,0 );
+
+ m_specific.m_window_attributes.border_pixel:=
+ XBlackPixel(m_specific.m_display ,m_specific.m_screen );
+
+ m_specific.m_window_attributes.background_pixel:=
+ XWhitePixel(m_specific.m_display ,m_specific.m_screen );
+
+ m_specific.m_window_attributes.override_redirect:=xfalse;
+
+ window_mask:=CWBackPixel or CWBorderPixel;
+
+ m_specific.m_window:=
+ XCreateWindow(
+ m_specific.m_display ,
+ XDefaultRootWindow(m_specific.m_display ) ,
+ 0 ,0 ,
+ width_ ,height_ ,
+ 0 ,
+ m_specific.m_depth ,
+ InputOutput ,
+ CopyFromParent ,
+ window_mask ,
+ @m_specific.m_window_attributes );
+
+ m_specific.m_gc:=XCreateGC(m_specific.m_display ,m_specific.m_window ,0 ,0 );
+
+ m_specific.m_buf_alloc:=width_ * height_ * (m_bpp div 8 );
+
+ agg_getmem(m_specific.m_buf_window ,m_specific.m_buf_alloc );
+ fillchar (m_specific.m_buf_window^ ,m_specific.m_buf_alloc ,255 );
+
+ if m_flip_y then
+ m_rbuf_window.attach(
+ m_specific.m_buf_window ,
+ width_ ,height_ ,
+ -width_ * (m_bpp div 8 ) )
+ else
+ m_rbuf_window.attach(
+ m_specific.m_buf_window ,
+ width_ ,height_ ,
+ width_ * (m_bpp div 8 ) );
+
+ m_specific.m_ximg_window:=
+ XCreateImage(
+ m_specific.m_display ,
+ m_specific.m_visual , //CopyFromParent,
+ m_specific.m_depth ,
+ ZPixmap ,
+ 0 ,
+ m_specific.m_buf_window ,
+ width_ ,height_ ,
+ m_specific.m_sys_bpp ,
+ width_ * (m_specific.m_sys_bpp div 8 ) );
+
+ m_specific.m_ximg_window.byte_order:=m_specific.m_byte_order;
+
+ m_specific.caption_(PChar(@m_caption[1 ] ) );
+
+ m_initial_width :=width_;
+ m_initial_height:=height_;
+
+ if not m_specific.m_initialized then
+ begin
+ on_init;
+
+ m_specific.m_initialized:=true;
+
+ end;
+
+ trans_affine_resizing_(width_ ,height_ );
+
+ on_resize(width_ ,height_ );
+
+ m_specific.m_update_flag:=true;
+
+ hints:=XAllocSizeHints;
+
+ if hints <> NIL then
+ begin
+ if flags and window_resize <> 0 then
+ begin
+ hints.min_width :=32;
+ hints.min_height:=32;
+ hints.max_width :=4096;
+ hints.max_height:=4096;
+
+ end
+ else
+ begin
+ hints.min_width :=width_;
+ hints.min_height:=height_;
+ hints.max_width :=width_;
+ hints.max_height:=height_;
+
+ end;
+
+ hints.flags:=PMaxSize or PMinSize;
+
+ XSetWMNormalHints(m_specific.m_display ,m_specific.m_window ,hints );
+ XFree (hints );
+
+ end;
+
+ XMapWindow (m_specific.m_display ,m_specific.m_window );
+ XSelectInput(m_specific.m_display ,m_specific.m_window ,xevent_mask );
+
+ m_specific.m_close_atom:=
+ XInternAtom(m_specific.m_display ,'WM_DELETE_WINDOW' ,false );
+
+ XSetWMProtocols(
+ m_specific.m_display ,
+ m_specific.m_window ,
+ @m_specific.m_close_atom ,1 );
+
+ result:=true;
+
+end;
+
+{ RUN }
+function platform_support.run;
+var
+ flags ,i : unsigned;
+
+ cur_x ,cur_y ,width ,height : int;
+
+ x_event ,te : TXEvent;
+
+ key : TKeySym;
+
+ left ,up ,right ,down : boolean;
+
+begin
+ XFlush(m_specific.m_display );
+
+ m_quit:=false;
+
+ while not m_quit do
+ begin
+ if m_specific.m_update_flag then
+ begin
+ on_draw;
+ update_window;
+
+ m_specific.m_update_flag:=false;
+
+ end;
+
+ if not m_wait_mode then
+ if XPending(m_specific.m_display ) = 0 then
+ begin
+ on_idle;
+ continue;
+
+ end;
+
+ XNextEvent(m_specific.m_display ,@x_event );
+
+ // In the Idle mode discard all intermediate MotionNotify events
+ if not m_wait_mode and
+ (x_event._type = MotionNotify ) then
+ begin
+ te:=x_event;
+
+ repeat
+ if XPending(m_specific.m_display ) = 0 then
+ break;
+
+ XNextEvent(m_specific.m_display ,@te );
+
+ if te._type <> MotionNotify then
+ break;
+
+ until false;
+
+ x_event:=te;
+
+ end;
+
+ case x_event._type of
+ ConfigureNotify :
+ if (x_event.xconfigure.width <> trunc(m_rbuf_window._width ) ) or
+ (x_event.xconfigure.height <> trunc(m_rbuf_window._height ) ) then
+ begin
+ width :=x_event.xconfigure.width;
+ height:=x_event.xconfigure.height;
+
+ agg_freemem(m_specific.m_buf_window ,m_specific.m_buf_alloc );
+
+ m_specific.m_ximg_window.data:=0;
+
+ XDestroyImage(m_specific.m_ximg_window );
+
+ m_specific.m_buf_alloc:=width * height * (m_bpp div 8 );
+
+ agg_getmem(m_specific.m_buf_window ,m_specific.m_buf_alloc );
+
+ if m_flip_y then
+ m_rbuf_window.attach(
+ m_specific.m_buf_window ,
+ width ,height ,
+ -width * (m_bpp div 8 ) )
+ else
+ m_rbuf_window.attach(
+ m_specific.m_buf_window ,
+ width ,height ,
+ width * (m_bpp div 8 ) );
+
+ m_specific.m_ximg_window:=
+ XCreateImage(m_specific.m_display ,
+ m_specific.m_visual , //CopyFromParent,
+ m_specific.m_depth ,
+ ZPixmap ,
+ 0 ,
+ m_specific.m_buf_window ,
+ width ,height ,
+ m_specific.m_sys_bpp ,
+ width * (m_specific.m_sys_bpp div 8 ) );
+
+ m_specific.m_ximg_window.byte_order:=m_specific.m_byte_order;
+
+ trans_affine_resizing_(width ,height );
+
+ on_resize(width ,height );
+ on_draw;
+ update_window;
+
+ end;
+
+ Expose :
+ begin
+ m_specific.put_image(@m_rbuf_window );
+
+ XFlush(m_specific.m_display );
+ XSync (m_specific.m_display ,false );
+
+ end;
+
+ KeyPress :
+ begin
+ key :=XLookupKeysym(@x_event.xkey ,0 );
+ flags:=0;
+
+ if x_event.xkey.state and Button1Mask <> 0 then
+ flags:=flags or mouse_left;
+
+ if x_event.xkey.state and Button3Mask <> 0 then
+ flags:=flags or mouse_right;
+
+ if x_event.xkey.state and ShiftMask <> 0 then
+ flags:=flags or kbd_shift;
+
+ if x_event.xkey.state and ControlMask <> 0 then
+ flags:=flags or kbd_ctrl;
+
+ left :=false;
+ up :=false;
+ right:=false;
+ down :=false;
+
+ case m_specific.m_keymap[key and $FF ] of
+ key_left : left :=true;
+ key_up : up :=true;
+ key_right : right:=true;
+ key_down : down :=true;
+
+ key_f2 :
+ begin
+ copy_window_to_img(max_images - 1 );
+ save_img (max_images - 1 ,'screenshot.ppm' );
+
+ end;
+
+ end;
+
+ if m_ctrls.on_arrow_keys(left ,right ,down ,up ) then
+ begin
+ on_ctrl_change;
+ force_redraw;
+
+ end
+ else
+ if m_flip_y then
+ on_key(
+ x_event.xkey.x ,
+ trunc(m_rbuf_window._height ) - x_event.xkey.y ,
+ m_specific.m_keymap[key and $FF ] ,flags )
+ else
+ on_key(
+ x_event.xkey.x ,
+ x_event.xkey.y ,
+ m_specific.m_keymap[key and $FF ] ,flags )
+
+ end;
+
+ ButtonPress :
+ begin
+ flags:=0;
+
+ if x_event.xbutton.state and ShiftMask <> 0 then
+ flags:=flags or kbd_shift;
+
+ if x_event.xbutton.state and ControlMask <> 0 then
+ flags:=flags or kbd_ctrl;
+
+ if x_event.xbutton.button = Button1 then
+ flags:=flags or mouse_left;
+
+ if x_event.xbutton.button = Button3 then
+ flags:=flags or mouse_right;
+
+ cur_x:=x_event.xbutton.x;
+
+ if m_flip_y then
+ cur_y:=trunc(m_rbuf_window._height ) - x_event.xbutton.y
+ else
+ cur_y:=x_event.xbutton.y;
+
+ if flags and mouse_left <> 0 then
+ if m_ctrls.on_mouse_button_down(cur_x ,cur_y ) then
+ begin
+ m_ctrls.set_cur(cur_x ,cur_y );
+ on_ctrl_change;
+ force_redraw;
+
+ end
+ else
+ if m_ctrls.in_rect(cur_x ,cur_y ) then
+ if m_ctrls.set_cur(cur_x ,cur_y ) then
+ begin
+ on_ctrl_change;
+ force_redraw;
+
+ end
+ else
+ else
+ on_mouse_button_down(cur_x ,cur_y ,flags );
+
+ if flags and mouse_right <> 0 then
+ on_mouse_button_down(cur_x ,cur_y ,flags );
+
+ //m_specific.m_wait_mode:=m_wait_mode;
+ //m_wait_mode :=true;
+
+ end;
+
+ MotionNotify :
+ begin
+ flags:=0;
+
+ if x_event.xmotion.state and Button1Mask <> 0 then
+ flags:=flags or mouse_left;
+
+ if x_event.xmotion.state and Button3Mask <> 0 then
+ flags:=flags or mouse_right;
+
+ if x_event.xmotion.state and ShiftMask <> 0 then
+ flags:=flags or kbd_shift;
+
+ if x_event.xmotion.state and ControlMask <> 0 then
+ flags:=flags or kbd_ctrl;
+
+ cur_x:=x_event.xbutton.x;
+
+ if m_flip_y then
+ cur_y:=trunc(m_rbuf_window._height ) - x_event.xbutton.y
+ else
+ cur_y:=x_event.xbutton.y;
+
+ if m_ctrls.on_mouse_move(cur_x ,cur_y ,flags and mouse_left <> 0 ) then
+ begin
+ on_ctrl_change;
+ force_redraw;
+
+ end
+ else
+ if not m_ctrls.in_rect(cur_x ,cur_y ) then
+ on_mouse_move(cur_x ,cur_y ,flags );
+
+ end;
+
+ ButtonRelease :
+ begin
+ flags:=0;
+
+ if x_event.xbutton.state and ShiftMask <> 0 then
+ flags:=flags or kbd_shift;
+
+ if x_event.xbutton.state and ControlMask <> 0 then
+ flags:=flags or kbd_ctrl;
+
+ if x_event.xbutton.button = Button1 then
+ flags:=flags or mouse_left;
+
+ if x_event.xbutton.button = Button3 then
+ flags:=flags or mouse_right;
+
+ cur_x:=x_event.xbutton.x;
+
+ if m_flip_y then
+ cur_y:=trunc(m_rbuf_window._height ) - x_event.xbutton.y
+ else
+ cur_y:=x_event.xbutton.y;
+
+ if flags and mouse_left <> 0 then
+ if m_ctrls.on_mouse_button_up(cur_x ,cur_y ) then
+ begin
+ on_ctrl_change;
+ force_redraw;
+
+ end;
+
+ if flags and (mouse_left or mouse_right ) <> 0 then
+ on_mouse_button_up(cur_x ,cur_y ,flags );
+
+ //m_wait_mode:=m_specific.m_wait_mode;
+
+ end;
+
+ ClientMessage :
+ if (x_event.xclient.format = 32 ) and
+ (x_event.xclient.data.l[0 ] = int(m_specific.m_close_atom ) ) then
+ m_quit:=true;
+
+ end;
+
+ end;
+
+ i:=max_images;
+
+ while i <> 0 do
+ begin
+ dec(i );
+
+ if m_specific.m_buf_img[i ] <> NIL then
+ agg_freemem(m_specific.m_buf_img[i ] ,m_specific.m_img_alloc[i ] );
+
+ end;
+
+ agg_freemem(m_specific.m_buf_window ,m_specific.m_buf_alloc );
+
+ m_specific.m_ximg_window.data:=NIL;
+
+ XDestroyImage (m_specific.m_ximg_window );
+ XFreeGC (m_specific.m_display ,m_specific.m_gc );
+ XDestroyWindow(m_specific.m_display ,m_specific.m_window );
+ XCloseDisplay (m_specific.m_display );
+
+ result:=0;
+
+end;
+
+{ QUIT }
+procedure platform_support.quit;
+begin
+ m_quit:=true;
+
+end;
+
+{ _FORMAT }
+function platform_support._format;
+begin
+ result:=m_format;
+
+end;
+
+{ _FLIP_Y }
+function platform_support._flip_y;
+begin
+ result:=m_flip_y;
+
+end;
+
+{ _BPP }
+function platform_support._bpp;
+begin
+ result:=m_bpp;
+
+end;
+
+{ _WAIT_MODE }
+function platform_support._wait_mode;
+begin
+ result:=m_wait_mode;
+
+end;
+
+{ WAIT_MODE_ }
+procedure platform_support.wait_mode_;
+begin
+ m_wait_mode:=wait_mode;
+
+end;
+
+{ FORCE_REDRAW }
+procedure platform_support.force_redraw;
+begin
+ m_specific.m_update_flag:=true;
+
+end;
+
+{ UPDATE_WINDOW }
+procedure platform_support.update_window;
+begin
+ m_specific.put_image(@m_rbuf_window );
+
+// When m_wait_mode is true we can discard all the events
+// came while the image is being drawn. In this case
+// the X server does not accumulate mouse motion events.
+// When m_wait_mode is false, i.e. we have some idle drawing
+// we cannot afford to miss any events
+ XSync(m_specific.m_display ,m_wait_mode );
+
+end;
+
+{ RBUF_WINDOW }
+function platform_support.rbuf_window;
+begin
+ result:=@m_rbuf_window;
+
+end;
+
+{ RBUF_IMG }
+function platform_support.rbuf_img;
+begin
+ result:=@m_rbuf_img[idx ];
+
+end;
+
+{ _IMG_EXT }
+function platform_support._img_ext;
+begin
+ result:='.ppm';
+
+end;
+
+{ COPY_IMG_TO_WINDOW }
+procedure platform_support.copy_img_to_window;
+begin
+ if (idx < max_images ) and
+ (rbuf_img(idx )._buf <> NIL ) then
+ rbuf_window.copy_from(rbuf_img(idx ) );
+
+end;
+
+{ COPY_WINDOW_TO_IMG }
+procedure platform_support.copy_window_to_img;
+begin
+ if idx < max_images then
+ begin
+ create_img(idx ,rbuf_window._width ,rbuf_window._height );
+ rbuf_img (idx ).copy_from(rbuf_window );
+
+ end;
+
+end;
+
+{ COPY_IMG_TO_IMG }
+procedure platform_support.copy_img_to_img;
+begin
+ if (idx_from < max_images ) and
+ (idx_to < max_images ) and
+ (rbuf_img(idx_from )._buf <> NIL ) then
+ begin
+ create_img(
+ idx_to ,
+ rbuf_img(idx_from )._width ,
+ rbuf_img(idx_from )._height );
+
+ rbuf_img(idx_to ).copy_from(rbuf_img(idx_from ) );
+
+ end;
+
+end;
+
+{ ON_INIT }
+procedure platform_support.on_init;
+begin
+end;
+
+{ ON_RESIZE }
+procedure platform_support.on_resize;
+begin
+end;
+
+{ ON_IDLE }
+procedure platform_support.on_idle;
+begin
+end;
+
+{ ON_MOUSE_MOVE }
+procedure platform_support.on_mouse_move;
+begin
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+procedure platform_support.on_mouse_button_down;
+begin
+end;
+
+{ ON_MOUSE_BUTTON_UP }
+procedure platform_support.on_mouse_button_up;
+begin
+end;
+
+{ ON_KEY }
+procedure platform_support.on_key;
+begin
+end;
+
+{ ON_CTRL_CHANGE }
+procedure platform_support.on_ctrl_change;
+begin
+end;
+
+{ ON_DRAW }
+procedure platform_support.on_draw;
+begin
+end;
+
+{ ON_POST_DRAW }
+procedure platform_support.on_post_draw;
+begin
+end;
+
+{ ADD_CTRL }
+procedure platform_support.add_ctrl;
+begin
+ m_ctrls.add(c );
+
+ c.transform(@m_resize_mtx );
+
+end;
+
+{ TRANS_AFFINE_RESIZING_ }
+procedure platform_support.trans_affine_resizing_;
+var
+ vp : trans_viewport;
+ ts : trans_affine_scaling;
+
+begin
+ if m_window_flags and window_keep_aspect_ratio <> 0 then
+ begin
+ vp.Construct;
+ vp.preserve_aspect_ratio(0.5 ,0.5 ,aspect_ratio_meet );
+
+ vp.device_viewport(0 ,0 ,width_ ,height_ );
+ vp.world_viewport (0 ,0 ,m_initial_width ,m_initial_height );
+
+ vp.to_affine(@m_resize_mtx );
+
+ end
+ else
+ begin
+ ts.Construct(
+ width_ / m_initial_width ,
+ height_ / m_initial_height );
+
+ m_resize_mtx.assign(@ts );
+
+ end;
+
+end;
+
+{ _TRANS_AFFINE_RESIZING }
+function platform_support._trans_affine_resizing;
+begin
+ result:=@m_resize_mtx;
+
+end;
+
+{ _WIDTH }
+function platform_support._width;
+begin
+ result:=m_rbuf_window._width;
+
+end;
+
+{ _HEIGHT }
+function platform_support._height;
+begin
+ result:=m_rbuf_window._height;
+
+end;
+
+{ _INITIAL_WIDTH }
+function platform_support._initial_width;
+begin
+ result:=m_initial_width;
+
+end;
+
+{ _INITIAL_HEIGHT }
+function platform_support._initial_height;
+begin
+ result:=m_initial_height;
+
+end;
+
+{ _WINDOW_FLAGS }
+function platform_support._window_flags;
+begin
+ result:=m_window_flags;
+
+end;
+
+{ _RAW_DISPLAY_HANDLER }
+function platform_support._raw_display_handler;
+begin
+end;
+
+{ MESSAGE_ }
+procedure platform_support.message_;
+const
+ x_event_mask =
+ ExposureMask or
+ KeyPressMask;
+
+ capt = ' PRESS ANY KEY TO CONTINUE THE AGGPAS DEMO ...';
+ plus = 4;
+
+var
+ x_display : PDisplay;
+ x_window : TWindow;
+ x_event : TXEvent;
+ x_close : TAtom;
+ x_changes : TXWindowChanges;
+ x_hints : PXSizeHints;
+
+ x_gc : TGC;
+ x_tp : TXTextProperty;
+ x_tx : TXTextItem;
+
+ str ,cur : char_ptr;
+
+ y ,len ,cnt ,max ,x_dx ,x_dy : unsigned;
+
+ font_dir ,font_ascent ,font_descent : int;
+
+ font_str : TXCharStruct;
+
+procedure draw_text;
+begin
+ x_dx:=0;
+ x_dy:=0;
+
+ y :=20;
+ cur:=PChar(@msg[0 ] );
+ max:=strlen(msg );
+ len:=0;
+ cnt:=0;
+
+ while cnt < max do
+ begin
+ if len = 0 then
+ str:=cur;
+
+ case cur^ of
+ #13 :
+ begin
+ XDrawString (x_display ,x_window ,x_gc ,10 ,y ,str ,len );
+ XQueryTextExtents(
+ x_display ,XGContextFromGC(x_gc) ,
+ str ,len ,
+ @font_dir ,
+ @font_ascent ,
+ @font_descent ,
+ @font_str );
+
+ inc(y ,font_str.ascent + font_str.descent + plus );
+ inc(x_dy ,font_str.ascent + font_str.descent + plus );
+
+ if font_str.width > x_dx then
+ x_dx:=font_str.width;
+
+ len:=0;
+
+ end;
+
+ else
+ inc(len );
+
+ end;
+
+ inc(ptrcomp(cur ) );
+ inc(cnt );
+
+ end;
+
+ if len > 0 then
+ begin
+ XDrawString (x_display ,x_window ,x_gc ,10 ,y ,str ,len );
+ XQueryTextExtents(
+ x_display ,XGContextFromGC(x_gc) ,
+ str ,len ,
+ @font_dir ,
+ @font_ascent ,
+ @font_descent ,
+ @font_str );
+
+ inc(x_dy ,font_str.ascent + font_str.descent + plus );
+
+ if font_str.width > x_dx then
+ x_dx:=font_str.width;
+
+ end;
+
+end;
+
+begin
+ x_display:=XOpenDisplay(NIL );
+
+ if x_display <> NIL then
+ begin
+ x_window :=
+ XCreateSimpleWindow(
+ x_display ,
+ XDefaultRootWindow(x_display ) ,
+ 50 ,50 ,
+ 550 ,300 ,
+ 0 ,0 ,
+ 255 + (255 shl 8 ) + (255 shl 16 ) );
+
+ x_gc:=XCreateGC(x_display ,x_window ,0 ,0 );
+
+ draw_text;
+ XResizeWindow(x_display ,x_window ,x_dx + 20 ,x_dy + 40 );
+
+ x_hints:=XAllocSizeHints;
+
+ if x_hints <> NIL then
+ begin
+ x_hints.min_width :=x_dx + 20;
+ x_hints.min_height:=x_dy + 40;
+ x_hints.max_width :=x_dx + 20;
+ x_hints.max_height:=x_dy + 40;
+
+ x_hints.flags:=PMaxSize or PMinSize;
+
+ XSetWMNormalHints(x_display ,x_window ,x_hints );
+ XFree (x_hints );
+
+ end;
+
+ x_tp.value :=PCUChar(@capt[1 ] );
+ x_tp.encoding:=XA_WM_NAME;
+ x_tp.format :=8;
+ x_tp.nitems := Length(capt);
+
+ XSetWMName (x_display ,x_window ,@x_tp );
+ XStoreName (x_display ,x_window ,capt );
+ XSetIconName (x_display ,x_window ,capt );
+ XSetWMIconName(x_display ,x_window ,@x_tp );
+
+ XMapWindow (x_display ,x_window );
+ XSelectInput(x_display ,x_window ,x_event_mask );
+
+ x_close:=
+ XInternAtom(x_display ,'WM_DELETE_WINDOW' ,false );
+
+ XSetWMProtocols(
+ x_display ,
+ x_window ,
+ @x_close ,1 );
+
+ XFlush(x_display );
+
+ repeat
+ XNextEvent(x_display ,@x_event );
+
+ XFlush(x_display );
+ XSync (x_display ,true );
+
+ case x_event._type of
+ Expose :
+ draw_text;
+
+ KeyPress :
+ break;
+
+ ClientMessage :
+ if (x_event.xclient.format = 32 ) and
+ (x_event.xclient.data.l[0 ] = int(x_close ) ) then
+ break;
+
+ end;
+
+
+ until false;
+
+ while XPending(x_display ) > 0 do
+ begin
+ XNextEvent(x_display ,@x_event );
+
+ XFlush(x_display );
+ XSync (x_display ,true );
+
+ end;
+
+ XFreeGC (x_display ,x_gc );
+ XDestroyWindow(x_display ,x_window );
+ XCloseDisplay (x_display );
+
+ end
+ else
+ writeln(stderr ,msg );
+
+end;
+
+{ START_TIMER }
+procedure platform_support.start_timer;
+begin
+ m_specific.m_sw_start:=clock;
+
+end;
+
+{ ELAPSED_TIME }
+function platform_support.elapsed_time;
+var
+ stop : clock_t;
+
+begin
+ stop:=clock;
+
+ result:=(stop - m_specific.m_sw_start ) * 1000.0 / CLOCKS_PER_SEC;
+
+end;
+
+{ FULL_FILE_NAME }
+function platform_support.full_file_name;
+begin
+ result:=file_name;
+
+end;
+
+{ FILE_SOURCE }
+function platform_support.file_source;
+var
+ f : file;
+ e : integer;
+
+begin
+ result:=fname;
+
+ e:=ioresult;
+
+ AssignFile(f ,result );
+ reset (f ,1 );
+
+ if ioresult <> 0 then
+ result:=path + '/' + fname;
+
+ close(f );
+
+ e:=ioresult;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/platform/linux/file_utils_.pas b/src/corelib/render/software/platform/linux/file_utils_.pas
index ddb08187..1f6391b2 100644
--- a/src/corelib/render/software/platform/linux/file_utils_.pas
+++ b/src/corelib/render/software/platform/linux/file_utils_.pas
@@ -1,776 +1,776 @@
-//
-// AggPas 2.4 RM3 demo framework file utility library
-// Milan Marusinec alias Milano (c) 2006
-//
-unit
- file_utils_ ;
-
-INTERFACE
-
-{$I agg_mode.inc }
-{$I- }
-uses
- agg_basics ;
-
-{ TYPES DEFINITION }
-type
- api_file_ptr = ^api_file;
- api_file = record
- fileName : shortstring;
- isOpened : boolean;
-
- fSize ,
- fRead : int;
-
- // FSOpenFork parameters
- df : file;
-
- end;
-
-{ GLOBAL PROCEDURES }
- function cut_str(s : shortstring ) : shortstring;
- function up_str (s : shortstring ) : shortstring;
- function cmp_str(s : shortstring ) : shortstring;
-
- function str_dir(s : shortstring ) : shortstring;
- function dir_str(s : shortstring ) : shortstring;
-
- function str_disk(fn : shortstring ) : shortstring;
- function str_path(fn : shortstring ) : shortstring;
- function str_name(fn : shortstring ) : shortstring;
- function str_ext (fn : shortstring ) : shortstring;
-
- function fold_name (p ,n ,x : shortstring ) : shortstring;
- procedure spread_name(fn : shortstring; var p ,n ,x : shortstring );
-
- function file_exists(fn : shortstring ) : boolean;
-
- function api_open_file (var af : api_file; fname : shortstring ) : boolean;
- function api_read_file (var af : api_file; buff : pointer; aloc : int; var read : int ) : boolean;
- function api_close_file(var af : api_file ) : boolean;
-
- function param_count : int;
- function param_str(i : int ) : shortstring;
-
-
-IMPLEMENTATION
-{ LOCAL VARIABLES & CONSTANTS }
-type
- tSCAN = (
-
- SCAN_0 ,
- SCAN_1 ,SCAN_2 ,SCAN_3 ,SCAN_4 ,SCAN_5 ,SCAN_6 ,SCAN_7 ,SCAN_8 ,SCAN_9 ,
- SCAN_A ,SCAN_B ,SCAN_C ,SCAN_D ,SCAN_E ,SCAN_F ,SCAN_G ,SCAN_H ,SCAN_I ,
- SCAN_J ,SCAN_K ,SCAN_L ,SCAN_M ,SCAN_N ,SCAN_O ,SCAN_P ,SCAN_Q ,SCAN_R ,
- SCAN_S ,SCAN_T ,SCAN_U ,SCAN_V ,SCAN_W ,SCAN_X ,SCAN_Y ,SCAN_Z
-
- );
-
- tITEM = (
-
- ITEM_0 ,
- ITEM_1 ,ITEM_2 ,ITEM_3 ,ITEM_4 ,ITEM_5 ,ITEM_6 ,ITEM_7 ,ITEM_8 ,ITEM_9 ,
- ITEM_A ,ITEM_B ,ITEM_C ,ITEM_D ,ITEM_E ,ITEM_F ,ITEM_G ,ITEM_H ,ITEM_I ,
- ITEM_J ,ITEM_K ,ITEM_L ,ITEM_M ,ITEM_N ,ITEM_O ,ITEM_P ,ITEM_Q ,ITEM_R ,
- ITEM_S ,ITEM_T ,ITEM_U ,ITEM_V ,ITEM_W ,ITEM_X ,ITEM_Y ,ITEM_Z
-
- );
-
-const
- dir_slash = '/';
-
- pageEqHigh : shortstring =
- #1#2#3#4#5#6#7#8#9#10#11#12#13#14#15#16 +
- #17#18#19#20#21#22#23#24#25#26#27#28#29#30#31#32 +
- #33#34#35#36#37#38#39#40#41#42#43#44#45#46#47#48 +
- #49#50#51#52#53#54#55#56#57#58#59#60#61#62#63#64 +
- #65#66#67#68#69#70#71#72#73#74#75#76#77#78#79#80 +
- #81#82#83#84#85#86#87#88#89#90#91#92#93#94#95#96 +
- #65#66#67#68#69#70#71#72#73#74#75#76#77#78#79#80 +
- #81#82#83#84#85#86#87#88#89#90#123#124#125#126#127#128 +
- #129#130#131#132#133#134#135#136#137#138#139#140#141#142#143#144 +
- #145#146#147#148#149#150#151#152#153#154#155#156#157#158#159#160 +
- #161#162#163#164#165#166#167#168#169#170#171#172#173#174#175#176 +
- #177#178#179#180#181#182#183#184#185#186#187#188#189#190#191#192 +
- #193#194#195#196#197#198#199#200#201#202#203#204#205#206#207#208 +
- #209#210#211#212#213#214#215#216#217#218#219#220#221#222#223#224 +
- #225#226#227#228#229#230#231#232#233#234#235#236#237#238#239#240 +
- #241#242#243#244#245#246#247#248#249#250#251#252#253#254#255;
-
-{ UNIT IMPLEMENTATION }
-{ CUT_STR }
-function cut_str;
-var
- fcb : byte;
- scn : tSCAN;
-
-begin
- result:='';
-
- scn:=SCAN_1;
-
- if length(s ) > 0 then
- for fcb:=length(s ) downto 1 do
- case scn of
- SCAN_1 :
- case s[fcb ] of
- ' ' :
- else
- begin
- result:=s[fcb ];
-
- scn:=SCAN_2;
-
- end;
-
- end;
-
- SCAN_2 :
- result:=s[fcb ] + result;
-
- end;
-
-end;
-
-{ CMP_STR }
-function cmp_str;
-begin
- cmp_str:=up_str(cut_str(s ) );
-
-end;
-
-{ UP_STR }
-function up_str;
-var
- fcb : byte;
-
-begin
- if length(s ) > 0 then
- for fcb:=1 to length(s ) do
- if byte(s[fcb ] ) > 0 then
- s[fcb ]:=pageEqHigh[byte(s[fcb ] ) ];
-
- result:=s;
-
-end;
-
-{ STR_DIR }
-function str_dir;
-begin
- s:=cut_str(s );
-
- if length(s ) > 0 then
- if s[length(s ) ] <> dir_slash then
- s:=s + dir_slash;
-
- result:=s;
-
-end;
-
-{ DIR_STR }
-function dir_str;
-begin
- s:=cut_str(s );
-
- if length(s ) > 0 then
- if s[length(s ) ] = dir_slash then
- dec(byte(s[0 ] ) );
-
- result:=s;
-
-end;
-
-{ STR_DISK }
-function str_disk;
-var
- fcb : byte;
- str : shortstring;
- itm : tITEM;
-
-begin
- str:='';
- itm:=ITEM_1;
-
- if length(fn ) > 0 then
- for fcb:=1 to length(fn ) do
- case itm of
- ITEM_1 :
- case fn[fcb ] of
- 'a'..'z' ,'A'..'Z' :
- begin
- str:=fn[fcb ];
- itm:=ITEM_2;
-
- end;
-
- '\' ,'/' :
- begin
- str:=fn[fcb ];
- itm:=ITEM_3;
-
- end;
-
- else
- break;
-
- end;
-
- ITEM_2 :
- case fn[fcb ] of
- ':' :
- begin
- str:=str + fn[fcb ];
- itm:=ITEM_F;
-
- break;
-
- end;
-
- else
- break;
-
- end;
-
- ITEM_3 :
- case fn[fcb ] of
- '\' ,'/' :
- begin
- str:=str + fn[fcb ];
- itm:=ITEM_4;
-
- end;
-
- else
- break;
-
- end;
-
- ITEM_4 :
- case fn[fcb ] of
- '\' ,'/' ,':' ,'<' ,'>' ,'.' ,'"' ,'|' ,#0..#31 :
- break;
-
- else
- begin
- str:=str + fn[fcb ];
- itm:=ITEM_F;
-
- end;
-
- end;
-
- ITEM_F :
- case fn[fcb ] of
- '\' ,'/' :
- break;
-
- else
- str:=str + fn[fcb ];
-
- end;
-
- end;
-
- if itm = ITEM_F then
- result:=str
- else
- result:='';
-
-end;
-
-{ STR_PATH }
-function str_path;
-var
- fcb : byte;
- pth ,
- str : shortstring;
- itm : tITEM;
-
-begin
- pth:='';
- str:='';
- itm:=ITEM_1;
-
- if length(fn ) > 0 then
- for fcb:=1 to length(fn ) do
- case itm of
- ITEM_1 :
- case fn[fcb ] of
- '\' ,'/' :
- begin
- str:=fn[fcb ];
- itm:=ITEM_2;
-
- end;
-
- else
- begin
- str:=fn[fcb ];
- itm:=ITEM_3;
-
- end;
-
- end;
-
- ITEM_2 :
- case fn[fcb ] of
- '\' ,'/' :
- begin
- str:=str + fn[fcb ];
- itm:=ITEM_3;
-
- end;
-
- else
- begin
- pth:=str;
- str:=fn[fcb ];
- itm:=ITEM_A;
-
- end;
-
- end;
-
- ITEM_3 :
- case fn[fcb ] of
- '\' ,'/' :
- begin
- pth:=fn[fcb ];
- str:='';
- itm:=ITEM_A;
-
- end;
-
- else
- str:=str + fn[fcb ];
-
- end;
-
- ITEM_A :
- case fn[fcb ] of
- '\' ,'/' :
- begin
- pth:=pth + str + fn[fcb ];
- str:='';
-
- end;
-
- else
- str:=str + fn[fcb ];
-
- end;
-
- end;
-
- result:=pth;
-
-end;
-
-{ STR_NAME }
-function str_name;
-var
- fcb : byte;
- str ,
- ext : shortstring;
- itm : tITEM;
-
-begin
- str:='';
- ext:='';
- itm:=ITEM_1;
-
- if length(fn ) > 0 then
- for fcb:=1 to length(fn ) do
- case itm of
- ITEM_1 :
- case fn[fcb ] of
- '\' ,'/' :
- itm:=ITEM_2;
-
- 'a'..'z' ,'A'..'Z' :
- begin
- ext:=fn[fcb ];
- itm:=ITEM_4;
-
- end;
-
- '.' :
- begin
- str:='';
- ext:=fn[fcb ];
- itm:=ITEM_B;
-
- end;
-
- else
- begin
- str:=fn[fcb ];
- itm:=ITEM_A;
-
- end;
-
- end;
-
- ITEM_2 :
- case fn[fcb ] of
- '\' ,'/' :
- itm:=ITEM_3;
-
- '.' :
- begin
- str:='';
- ext:=fn[fcb ];
- itm:=ITEM_B;
-
- end;
-
- else
- begin
- str:=fn[fcb ];
- itm:=ITEM_A;
-
- end;
-
- end;
-
- ITEM_3 :
- case fn[fcb ] of
- '\' ,'/' :
- begin
- str:='';
- itm:=ITEM_A;
-
- end;
-
- end;
-
- ITEM_4 :
- case fn[fcb ] of
- '\' ,'/' :
- begin
- str:='';
- itm:=ITEM_A;
-
- end;
-
- ':' :
- itm:=ITEM_5;
-
- '.' :
- begin
- str:=ext;
- ext:=fn[fcb ];
- itm:=ITEM_B;
-
- end;
-
- else
- begin
- str:=ext + fn[fcb ];
- ext:='';
- itm:=ITEM_A;
-
- end;
-
- end;
-
- ITEM_5 :
- case fn[fcb ] of
- '\' ,'/' :
- begin
- str:='';
- itm:=ITEM_A;
-
- end;
-
- '.' :
- begin
- str:='';
- ext:=fn[fcb ];
- itm:=ITEM_B;
-
- end;
-
- else
- begin
- str:=fn[fcb ];
- itm:=ITEM_A;
-
- end;
-
- end;
-
- ITEM_A :
- case fn[fcb ] of
- '\' ,'/' :
- begin
- str:='';
- ext:='';
-
- end;
-
- '.' :
- begin
- ext:=fn[fcb ];
- itm:=ITEM_B;
-
- end;
-
- else
- str:=str + fn[fcb ];
-
- end;
-
- ITEM_B :
- case fn[fcb ] of
- '\' ,'/' :
- begin
- str:='';
- ext:='';
- itm:=ITEM_A;
-
- end;
-
- '.' :
- begin
- str:=str + ext;
- ext:=fn[fcb ];
-
- end;
-
- end;
-
- end;
-
- result:=str;
-
-end;
-
-{ STR_EXT }
-function str_ext;
-var
- fcb : byte;
- ext : shortstring;
- itm : tITEM;
-
-begin
- ext:='';
- itm:=ITEM_1;
-
- if length(fn ) > 0 then
- for fcb:=1 to length(fn ) do
- case itm of
- ITEM_1 :
- case fn[fcb ] of
- '\' ,'/' :
- itm:=ITEM_2;
-
- '.' :
- begin
- ext:=fn[fcb ];
- itm:=ITEM_B;
-
- end;
-
- else
- itm:=ITEM_A;
-
- end;
-
- ITEM_2 :
- case fn[fcb ] of
- '\' ,'/' :
- itm:=ITEM_3;
-
- '.' :
- begin
- ext:=fn[fcb ];
- itm:=ITEM_B;
-
- end;
-
- else
- itm:=ITEM_A;
-
- end;
-
- ITEM_3 :
- case fn[fcb ] of
- '\' ,'/' :
- itm:=ITEM_A;
-
- end;
-
- ITEM_A :
- case fn[fcb ] of
- '.' :
- begin
- ext:=fn[fcb ];
- itm:=ITEM_B;
-
- end;
-
- end;
-
- ITEM_B :
- case fn[fcb ] of
- '\' ,'/' :
- begin
- ext:='';
- itm:=ITEM_A;
-
- end;
-
- '.' :
- ext:=fn[fcb ];
-
- else
- ext:=ext + fn[fcb ];
-
- end;
-
- end;
-
- result:=cut_str(ext );
-
- if result = '.' then
- result:='';
-
-end;
-
-{ FOLD_NAME }
-function fold_name;
-var
- dsk ,
- nme ,
- pth ,
- ext : shortstring;
-
-begin
- dsk:=str_disk(p );
- pth:=str_dir (str_path(p ) );
- nme:=str_name(n );
- ext:=str_ext (x );
-
- result:=dsk + pth + nme + ext;
-
-end;
-
-{ SPREAD_NAME }
-procedure spread_name;
-begin
- p:=str_disk(fn ) + str_dir(str_path(fn ) );
- n:=str_name(fn );
- x:=str_ext (fn );
-
-end;
-
-{ FILE_EXISTS }
-function file_exists;
-var
- f : file;
-
-begin
- AssignFile(f ,fn );
- reset (f );
-
- if IOResult = 0 then
- begin
- close(f );
-
- result:=true;
-
- end
- else
- result:=false;
-
-end;
-
-{ API_OPEN_FILE }
-function api_open_file;
-begin
- result:=false;
-
- fillchar(af ,sizeof(api_file ) ,0 );
-
- af.fileName:=fname;
- af.isOpened:=false;
-
- IOResult;
-
- AssignFile(af.df ,fname );
- reset (af.df ,1 );
-
- if IOResult = 0 then
- begin
- af.isOpened:=true;
-
- af.fSize:=filesize(af.df );
- af.fRead:=0;
-
- end;
-
- result:=af.isOpened;
-
-end;
-
-{ API_READ_FILE }
-function api_read_file;
-begin
- result:=false;
- read :=0;
-
- if af.isOpened then
- begin
- if aloc > af.fSize - af.fRead then
- aloc:=af.fSize - af.fRead;
-
- blockread(af.df ,buff^ ,aloc ,read );
-
- if aloc = read then
- begin
- inc(af.fRead ,read );
-
- result:=true;
-
- end
- else
- read:=0;
-
- end;
-
-end;
-
-{ API_CLOSE_FILE }
-function api_close_file;
-begin
- result:=false;
-
- if af.isOpened then
- begin
- system.close(af.df );
-
- af.isOpened:=false;
-
- result:=true;
-
- end;
-
-end;
-
-{ PARAM_COUNT }
-function param_count;
-begin
- result:=ParamCount;
-
-end;
-
-{ PARAM_STR }
-function param_str;
-begin
- result:=ParamStr(i );
-
-end;
-
-END.
-
+//
+// AggPas 2.4 RM3 demo framework file utility library
+// Milan Marusinec alias Milano (c) 2006
+//
+unit
+ file_utils_ ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+{$I- }
+uses
+ agg_basics ;
+
+{ TYPES DEFINITION }
+type
+ api_file_ptr = ^api_file;
+ api_file = record
+ fileName : shortstring;
+ isOpened : boolean;
+
+ fSize ,
+ fRead : int;
+
+ // FSOpenFork parameters
+ df : file;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+ function cut_str(s : shortstring ) : shortstring;
+ function up_str (s : shortstring ) : shortstring;
+ function cmp_str(s : shortstring ) : shortstring;
+
+ function str_dir(s : shortstring ) : shortstring;
+ function dir_str(s : shortstring ) : shortstring;
+
+ function str_disk(fn : shortstring ) : shortstring;
+ function str_path(fn : shortstring ) : shortstring;
+ function str_name(fn : shortstring ) : shortstring;
+ function str_ext (fn : shortstring ) : shortstring;
+
+ function fold_name (p ,n ,x : shortstring ) : shortstring;
+ procedure spread_name(fn : shortstring; var p ,n ,x : shortstring );
+
+ function file_exists(fn : shortstring ) : boolean;
+
+ function api_open_file (var af : api_file; fname : shortstring ) : boolean;
+ function api_read_file (var af : api_file; buff : pointer; aloc : int; var read : int ) : boolean;
+ function api_close_file(var af : api_file ) : boolean;
+
+ function param_count : int;
+ function param_str(i : int ) : shortstring;
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+type
+ tSCAN = (
+
+ SCAN_0 ,
+ SCAN_1 ,SCAN_2 ,SCAN_3 ,SCAN_4 ,SCAN_5 ,SCAN_6 ,SCAN_7 ,SCAN_8 ,SCAN_9 ,
+ SCAN_A ,SCAN_B ,SCAN_C ,SCAN_D ,SCAN_E ,SCAN_F ,SCAN_G ,SCAN_H ,SCAN_I ,
+ SCAN_J ,SCAN_K ,SCAN_L ,SCAN_M ,SCAN_N ,SCAN_O ,SCAN_P ,SCAN_Q ,SCAN_R ,
+ SCAN_S ,SCAN_T ,SCAN_U ,SCAN_V ,SCAN_W ,SCAN_X ,SCAN_Y ,SCAN_Z
+
+ );
+
+ tITEM = (
+
+ ITEM_0 ,
+ ITEM_1 ,ITEM_2 ,ITEM_3 ,ITEM_4 ,ITEM_5 ,ITEM_6 ,ITEM_7 ,ITEM_8 ,ITEM_9 ,
+ ITEM_A ,ITEM_B ,ITEM_C ,ITEM_D ,ITEM_E ,ITEM_F ,ITEM_G ,ITEM_H ,ITEM_I ,
+ ITEM_J ,ITEM_K ,ITEM_L ,ITEM_M ,ITEM_N ,ITEM_O ,ITEM_P ,ITEM_Q ,ITEM_R ,
+ ITEM_S ,ITEM_T ,ITEM_U ,ITEM_V ,ITEM_W ,ITEM_X ,ITEM_Y ,ITEM_Z
+
+ );
+
+const
+ dir_slash = '/';
+
+ pageEqHigh : shortstring =
+ #1#2#3#4#5#6#7#8#9#10#11#12#13#14#15#16 +
+ #17#18#19#20#21#22#23#24#25#26#27#28#29#30#31#32 +
+ #33#34#35#36#37#38#39#40#41#42#43#44#45#46#47#48 +
+ #49#50#51#52#53#54#55#56#57#58#59#60#61#62#63#64 +
+ #65#66#67#68#69#70#71#72#73#74#75#76#77#78#79#80 +
+ #81#82#83#84#85#86#87#88#89#90#91#92#93#94#95#96 +
+ #65#66#67#68#69#70#71#72#73#74#75#76#77#78#79#80 +
+ #81#82#83#84#85#86#87#88#89#90#123#124#125#126#127#128 +
+ #129#130#131#132#133#134#135#136#137#138#139#140#141#142#143#144 +
+ #145#146#147#148#149#150#151#152#153#154#155#156#157#158#159#160 +
+ #161#162#163#164#165#166#167#168#169#170#171#172#173#174#175#176 +
+ #177#178#179#180#181#182#183#184#185#186#187#188#189#190#191#192 +
+ #193#194#195#196#197#198#199#200#201#202#203#204#205#206#207#208 +
+ #209#210#211#212#213#214#215#216#217#218#219#220#221#222#223#224 +
+ #225#226#227#228#229#230#231#232#233#234#235#236#237#238#239#240 +
+ #241#242#243#244#245#246#247#248#249#250#251#252#253#254#255;
+
+{ UNIT IMPLEMENTATION }
+{ CUT_STR }
+function cut_str;
+var
+ fcb : byte;
+ scn : tSCAN;
+
+begin
+ result:='';
+
+ scn:=SCAN_1;
+
+ if length(s ) > 0 then
+ for fcb:=length(s ) downto 1 do
+ case scn of
+ SCAN_1 :
+ case s[fcb ] of
+ ' ' :
+ else
+ begin
+ result:=s[fcb ];
+
+ scn:=SCAN_2;
+
+ end;
+
+ end;
+
+ SCAN_2 :
+ result:=s[fcb ] + result;
+
+ end;
+
+end;
+
+{ CMP_STR }
+function cmp_str;
+begin
+ cmp_str:=up_str(cut_str(s ) );
+
+end;
+
+{ UP_STR }
+function up_str;
+var
+ fcb : byte;
+
+begin
+ if length(s ) > 0 then
+ for fcb:=1 to length(s ) do
+ if byte(s[fcb ] ) > 0 then
+ s[fcb ]:=pageEqHigh[byte(s[fcb ] ) ];
+
+ result:=s;
+
+end;
+
+{ STR_DIR }
+function str_dir;
+begin
+ s:=cut_str(s );
+
+ if length(s ) > 0 then
+ if s[length(s ) ] <> dir_slash then
+ s:=s + dir_slash;
+
+ result:=s;
+
+end;
+
+{ DIR_STR }
+function dir_str;
+begin
+ s:=cut_str(s );
+
+ if length(s ) > 0 then
+ if s[length(s ) ] = dir_slash then
+ dec(byte(s[0 ] ) );
+
+ result:=s;
+
+end;
+
+{ STR_DISK }
+function str_disk;
+var
+ fcb : byte;
+ str : shortstring;
+ itm : tITEM;
+
+begin
+ str:='';
+ itm:=ITEM_1;
+
+ if length(fn ) > 0 then
+ for fcb:=1 to length(fn ) do
+ case itm of
+ ITEM_1 :
+ case fn[fcb ] of
+ 'a'..'z' ,'A'..'Z' :
+ begin
+ str:=fn[fcb ];
+ itm:=ITEM_2;
+
+ end;
+
+ '\' ,'/' :
+ begin
+ str:=fn[fcb ];
+ itm:=ITEM_3;
+
+ end;
+
+ else
+ break;
+
+ end;
+
+ ITEM_2 :
+ case fn[fcb ] of
+ ':' :
+ begin
+ str:=str + fn[fcb ];
+ itm:=ITEM_F;
+
+ break;
+
+ end;
+
+ else
+ break;
+
+ end;
+
+ ITEM_3 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ str:=str + fn[fcb ];
+ itm:=ITEM_4;
+
+ end;
+
+ else
+ break;
+
+ end;
+
+ ITEM_4 :
+ case fn[fcb ] of
+ '\' ,'/' ,':' ,'<' ,'>' ,'.' ,'"' ,'|' ,#0..#31 :
+ break;
+
+ else
+ begin
+ str:=str + fn[fcb ];
+ itm:=ITEM_F;
+
+ end;
+
+ end;
+
+ ITEM_F :
+ case fn[fcb ] of
+ '\' ,'/' :
+ break;
+
+ else
+ str:=str + fn[fcb ];
+
+ end;
+
+ end;
+
+ if itm = ITEM_F then
+ result:=str
+ else
+ result:='';
+
+end;
+
+{ STR_PATH }
+function str_path;
+var
+ fcb : byte;
+ pth ,
+ str : shortstring;
+ itm : tITEM;
+
+begin
+ pth:='';
+ str:='';
+ itm:=ITEM_1;
+
+ if length(fn ) > 0 then
+ for fcb:=1 to length(fn ) do
+ case itm of
+ ITEM_1 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ str:=fn[fcb ];
+ itm:=ITEM_2;
+
+ end;
+
+ else
+ begin
+ str:=fn[fcb ];
+ itm:=ITEM_3;
+
+ end;
+
+ end;
+
+ ITEM_2 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ str:=str + fn[fcb ];
+ itm:=ITEM_3;
+
+ end;
+
+ else
+ begin
+ pth:=str;
+ str:=fn[fcb ];
+ itm:=ITEM_A;
+
+ end;
+
+ end;
+
+ ITEM_3 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ pth:=fn[fcb ];
+ str:='';
+ itm:=ITEM_A;
+
+ end;
+
+ else
+ str:=str + fn[fcb ];
+
+ end;
+
+ ITEM_A :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ pth:=pth + str + fn[fcb ];
+ str:='';
+
+ end;
+
+ else
+ str:=str + fn[fcb ];
+
+ end;
+
+ end;
+
+ result:=pth;
+
+end;
+
+{ STR_NAME }
+function str_name;
+var
+ fcb : byte;
+ str ,
+ ext : shortstring;
+ itm : tITEM;
+
+begin
+ str:='';
+ ext:='';
+ itm:=ITEM_1;
+
+ if length(fn ) > 0 then
+ for fcb:=1 to length(fn ) do
+ case itm of
+ ITEM_1 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ itm:=ITEM_2;
+
+ 'a'..'z' ,'A'..'Z' :
+ begin
+ ext:=fn[fcb ];
+ itm:=ITEM_4;
+
+ end;
+
+ '.' :
+ begin
+ str:='';
+ ext:=fn[fcb ];
+ itm:=ITEM_B;
+
+ end;
+
+ else
+ begin
+ str:=fn[fcb ];
+ itm:=ITEM_A;
+
+ end;
+
+ end;
+
+ ITEM_2 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ itm:=ITEM_3;
+
+ '.' :
+ begin
+ str:='';
+ ext:=fn[fcb ];
+ itm:=ITEM_B;
+
+ end;
+
+ else
+ begin
+ str:=fn[fcb ];
+ itm:=ITEM_A;
+
+ end;
+
+ end;
+
+ ITEM_3 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ str:='';
+ itm:=ITEM_A;
+
+ end;
+
+ end;
+
+ ITEM_4 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ str:='';
+ itm:=ITEM_A;
+
+ end;
+
+ ':' :
+ itm:=ITEM_5;
+
+ '.' :
+ begin
+ str:=ext;
+ ext:=fn[fcb ];
+ itm:=ITEM_B;
+
+ end;
+
+ else
+ begin
+ str:=ext + fn[fcb ];
+ ext:='';
+ itm:=ITEM_A;
+
+ end;
+
+ end;
+
+ ITEM_5 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ str:='';
+ itm:=ITEM_A;
+
+ end;
+
+ '.' :
+ begin
+ str:='';
+ ext:=fn[fcb ];
+ itm:=ITEM_B;
+
+ end;
+
+ else
+ begin
+ str:=fn[fcb ];
+ itm:=ITEM_A;
+
+ end;
+
+ end;
+
+ ITEM_A :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ str:='';
+ ext:='';
+
+ end;
+
+ '.' :
+ begin
+ ext:=fn[fcb ];
+ itm:=ITEM_B;
+
+ end;
+
+ else
+ str:=str + fn[fcb ];
+
+ end;
+
+ ITEM_B :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ str:='';
+ ext:='';
+ itm:=ITEM_A;
+
+ end;
+
+ '.' :
+ begin
+ str:=str + ext;
+ ext:=fn[fcb ];
+
+ end;
+
+ end;
+
+ end;
+
+ result:=str;
+
+end;
+
+{ STR_EXT }
+function str_ext;
+var
+ fcb : byte;
+ ext : shortstring;
+ itm : tITEM;
+
+begin
+ ext:='';
+ itm:=ITEM_1;
+
+ if length(fn ) > 0 then
+ for fcb:=1 to length(fn ) do
+ case itm of
+ ITEM_1 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ itm:=ITEM_2;
+
+ '.' :
+ begin
+ ext:=fn[fcb ];
+ itm:=ITEM_B;
+
+ end;
+
+ else
+ itm:=ITEM_A;
+
+ end;
+
+ ITEM_2 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ itm:=ITEM_3;
+
+ '.' :
+ begin
+ ext:=fn[fcb ];
+ itm:=ITEM_B;
+
+ end;
+
+ else
+ itm:=ITEM_A;
+
+ end;
+
+ ITEM_3 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ itm:=ITEM_A;
+
+ end;
+
+ ITEM_A :
+ case fn[fcb ] of
+ '.' :
+ begin
+ ext:=fn[fcb ];
+ itm:=ITEM_B;
+
+ end;
+
+ end;
+
+ ITEM_B :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ ext:='';
+ itm:=ITEM_A;
+
+ end;
+
+ '.' :
+ ext:=fn[fcb ];
+
+ else
+ ext:=ext + fn[fcb ];
+
+ end;
+
+ end;
+
+ result:=cut_str(ext );
+
+ if result = '.' then
+ result:='';
+
+end;
+
+{ FOLD_NAME }
+function fold_name;
+var
+ dsk ,
+ nme ,
+ pth ,
+ ext : shortstring;
+
+begin
+ dsk:=str_disk(p );
+ pth:=str_dir (str_path(p ) );
+ nme:=str_name(n );
+ ext:=str_ext (x );
+
+ result:=dsk + pth + nme + ext;
+
+end;
+
+{ SPREAD_NAME }
+procedure spread_name;
+begin
+ p:=str_disk(fn ) + str_dir(str_path(fn ) );
+ n:=str_name(fn );
+ x:=str_ext (fn );
+
+end;
+
+{ FILE_EXISTS }
+function file_exists;
+var
+ f : file;
+
+begin
+ AssignFile(f ,fn );
+ reset (f );
+
+ if IOResult = 0 then
+ begin
+ close(f );
+
+ result:=true;
+
+ end
+ else
+ result:=false;
+
+end;
+
+{ API_OPEN_FILE }
+function api_open_file;
+begin
+ result:=false;
+
+ fillchar(af ,sizeof(api_file ) ,0 );
+
+ af.fileName:=fname;
+ af.isOpened:=false;
+
+ IOResult;
+
+ AssignFile(af.df ,fname );
+ reset (af.df ,1 );
+
+ if IOResult = 0 then
+ begin
+ af.isOpened:=true;
+
+ af.fSize:=filesize(af.df );
+ af.fRead:=0;
+
+ end;
+
+ result:=af.isOpened;
+
+end;
+
+{ API_READ_FILE }
+function api_read_file;
+begin
+ result:=false;
+ read :=0;
+
+ if af.isOpened then
+ begin
+ if aloc > af.fSize - af.fRead then
+ aloc:=af.fSize - af.fRead;
+
+ blockread(af.df ,buff^ ,aloc ,read );
+
+ if aloc = read then
+ begin
+ inc(af.fRead ,read );
+
+ result:=true;
+
+ end
+ else
+ read:=0;
+
+ end;
+
+end;
+
+{ API_CLOSE_FILE }
+function api_close_file;
+begin
+ result:=false;
+
+ if af.isOpened then
+ begin
+ system.close(af.df );
+
+ af.isOpened:=false;
+
+ result:=true;
+
+ end;
+
+end;
+
+{ PARAM_COUNT }
+function param_count;
+begin
+ result:=ParamCount;
+
+end;
+
+{ PARAM_STR }
+function param_str;
+begin
+ result:=ParamStr(i );
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/platform/mac/agg_mac_pmap.pas b/src/corelib/render/software/platform/mac/agg_mac_pmap.pas
index 7e5ad44e..98be5900 100644
--- a/src/corelib/render/software/platform/mac/agg_mac_pmap.pas
+++ b/src/corelib/render/software/platform/mac/agg_mac_pmap.pas
@@ -1,471 +1,471 @@
-//----------------------------------------------------------------------------
-// Anti-Grain Geometry - Version 2.4 (Public License)
-// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
-// Copyright (C) 2002 Hansruedi Baer (MacOS support)
-//
-// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
-// Pascal Port By: Milan Marusinec alias Milano
-// milan@marusinec.sk
-// http://www.aggpas.org
-// Copyright (c) 2005-2006
-//
-// Permission to copy, use, modify, sell and distribute this software
-// is granted provided this copyright notice appears in all copies.
-// This software is provided "as is" without express or implied
-// warranty, and with no claim as to its suitability for any purpose.
-//
-//----------------------------------------------------------------------------
-// Contact: mcseem@antigrain.com
-// mcseemagg@yahoo.com
-// http://www.antigrain.com
-// baer@karto.baug.eth.ch
-//
-// [Pascal Port History] -----------------------------------------------------
-//
-// 24.03.2006-Milano: Finished MacOS port
-// 20.03.2006-Milano: Unit port establishment
-//
-{ agg_mac_pmap.pas }
-unit
- agg_mac_pmap ;
-
-INTERFACE
-
-{$I agg_mode.inc }
-
-uses
- QuickTimeComponents ,ImageCompression ,Carbon ,
- agg_basics ;
-
-{ TYPES DEFINITION }
-const
- org_mono8 = 8;
- org_color16 = 16;
- org_color24 = 24;
- org_color32 = 32;
-
-type
- pixel_map = object
- m_pmap : ^CGrafPort;
- m_buf : pointer;
-
- m_bpp ,
- m_img_size : unsigned;
-
- constructor Construct;
- destructor Destruct;
-
- procedure destroy;
- procedure create(width ,height ,org : unsigned; clear_val : unsigned = 255 );
- procedure clear (clear_val : unsigned = 255 );
-
- function load_from_qt(filename : shortstring ) : boolean;
- function save_as_qt (filename : shortstring ) : boolean;
-
- procedure draw(window : WindowRef; device_rect : RectPtr = NIL; bmp_rect : RectPtr = NIL ); overload;
- procedure draw(window : WindowRef; x ,y : int; scale : double = 1.0 ); overload;
-
- procedure blend(window : WindowRef; device_rect : RectPtr = NIL; bmp_rect : RectPtr = NIL ); overload;
- procedure blend(window : WindowRef; x ,y : int; scale : double = 1.0 ); overload;
-
- function _buf : pointer;
- function _width : unsigned;
- function _height : unsigned;
- function _row_bytes : int;
- function _bpp : unsigned;
-
- //Auxiliary static functions
- function calc_row_len(width ,bits_per_pixel : unsigned ) : unsigned;
-
- end;
-
-{ GLOBAL PROCEDURES }
-
-
-IMPLEMENTATION
-{ LOCAL VARIABLES & CONSTANTS }
-{ UNIT IMPLEMENTATION }
-{ CONSTRUCT }
-constructor pixel_map.Construct;
-begin
- m_pmap:=NIL;
- m_buf :=NIL;
- m_bpp :=0;
-
- m_img_size:=0;
-
-end;
-
-{ DESTRUCT }
-destructor pixel_map.Destruct;
-begin
- destroy;
-
-end;
-
-{ DESTROY }
-procedure pixel_map.destroy;
-begin
- agg_freemem(m_buf ,m_img_size );
-
- m_buf:=NIL;
-
- if m_pmap <> NIL then
- begin
- DisposeGWorld(GrafPtr(m_pmap ) );
-
- m_pmap:=NIL;
-
- end;
-
-end;
-
-{ CREATE }
-procedure pixel_map.create;
-var
- r : Carbon.Rect;
-
- row_bytes : int;
-
-begin
- destroy;
-
- if width = 0 then
- width:=1;
-
- if height = 0 then
- height:=1;
-
- m_bpp :=org;
- row_bytes:=calc_row_len(width ,m_bpp );
-
- SetRect(r ,0 ,0 ,width ,height );
-
- m_img_size:=row_bytes * height;
-
- agg_getmem(m_buf ,m_img_size );
-
-// The Quicktime version for creating GWorlds is more flexible than the classical function.
- QTNewGWorldFromPtr(m_pmap ,m_bpp ,ImageCompression.Rect(r ) ,NIL ,NIL ,0 ,m_buf ,row_bytes );
-
-// create_gray_scale_palette(m_pmap); I didn't care about gray scale palettes so far.
- if clear_val <= 255 then
- fillchar(m_buf^ ,m_img_size ,clear_val );
-
-end;
-
-{ CLEAR }
-procedure pixel_map.clear;
-begin
- if m_buf <> NIL then
- fillchar(m_buf^ ,m_img_size ,clear_val );
-
-end;
-
-{ LOAD_FROM_QT }
-function pixel_map.load_from_qt;
-var
- fss : FSSpec;
- err : OSErr;
- gi : GraphicsImportComponent;
- buf : int8u_ptr;
-
- desc : ImageDescriptionHandle;
- depth : int16;
- size : unsigned;
-
-begin
-// get file specification to application directory
- err:=HGetVol(NIL ,fss.vRefNum ,fss.parID );
-
- if err = noErr then
- begin
- // CopyCStringToPascal(filename ,fss.name );
- fss.name:=filename;
-
- err:=GetGraphicsImporterForFile(ImageCompression.FSSpec(fss ) ,gi );
-
- if err = noErr then
- begin
- GraphicsImportGetImageDescription(gi ,desc );
-
- // For simplicity, all images are currently converted to 32 bit.
- // create an empty pixelmap
- depth:=24;
-
- create (desc^.width ,desc^.height ,depth ,$ff );
- DisposeHandle(Handle(desc ) );
-
- // let Quicktime draw to pixelmap
- GraphicsImportSetGWorld(gi ,m_pmap ,NIL );
- GraphicsImportDraw (gi );
-
- end;
-
- end;
-
- result:=err = noErr;
-
-end;
-
-{ SAVE_AS_QT }
-function pixel_map.save_as_qt;
-var
- fss : FSSpec;
- err : OSErr;
- ge : GraphicsExportComponent;
- cnt : UInt32;
-
-begin
-// get file specification to application directory
- err:=HGetVol(NIL ,fss.vRefNum ,fss.parID );
-
- if err = noErr then
- begin
- // CopyCStringToPascal(filename ,fss.name );
- fss.name:=filename;
-
- // I decided to use PNG as output image file type.
- // There are a number of other available formats.
- // Should I check the file suffix to choose the image file format?
- err:=
- OpenADefaultComponent(
- LongWord(int32_ptr(@GraphicsExporterComponentType[1 ] )^ ) ,
- LongWord(int32_ptr(@kQTFileTypePNG[1 ] )^ ) ,
- Carbon.ComponentInstance(ge ) );
-
- if err = noErr then
- begin
- err:=GraphicsExportSetInputGWorld(ge ,m_pmap );
-
- if err = noErr then
- begin
- err:=GraphicsExportSetOutputFile(ge ,ImageCompression.FSSpec(fss ) );
- cnt:=0;
-
- if err = noErr then
- GraphicsExportDoExport(ge ,cnt );
-
- end;
-
- CloseComponent(Carbon.ComponentInstance(ge ) );
-
- end;
-
- end;
-
- result:=err = noErr;
-
-end;
-
-{ DRAW }
-procedure pixel_map.draw(window : WindowRef; device_rect : RectPtr = NIL; bmp_rect : RectPtr = NIL );
-var
- pm : PixMapHandle;
- port : CGrafPtr;
-
- src_rect ,dest_rect : Carbon.Rect;
-
- image_description : ImageDescriptionHandle;
-
-begin
- if (m_pmap = NIL ) or
- (m_buf = NIL ) then
- exit;
-
- pm :=GetGWorldPixMap(GrafPtr(m_pmap ) );
- port:=GetWindowPort (window );
-
-// Again, I used the Quicktime version.
-// Good old 'CopyBits' does better interpolation when scaling
-// but does not support all pixel depths.
- SetRect(dest_rect ,0 ,0 ,_width ,_height );
-
- MakeImageDescriptionForPixMap(ImageCompression.PixMapHandle(pm ) ,image_description );
-
- if image_description <> NIL then
- begin
- SetRect(src_rect ,0 ,0 ,image_description^.width ,image_description^.height );
-
- DecompressImage(
- GetPixBaseAddr(pm ) ,
- image_description ,
- ImageCompression.PixMapHandle(GetPortPixMap(port ) ) ,
- ImageCompression.Rect(src_rect ) ,
- ImageCompression.Rect(dest_rect ) ,
- ditherCopy ,NIL );
-
- DisposeHandle(Handle(image_description ) );
-
- end;
-
-end;
-
-{ DRAW }
-procedure pixel_map.draw(window : WindowRef; x ,y : int; scale : double = 1.0 );
-var
- width ,height : unsigned;
-
- r : Carbon.Rect;
-
-begin
- if (m_pmap = NIL ) or
- (m_buf = NIL ) then
- exit;
-
- width :=System.Trunc(_width * scale );
- height:=System.Trunc(_height * scale );
-
- SetRect(r ,x ,y ,x + width ,y + height );
- draw (window ,@r );
-
-end;
-
-{ BLEND }
-procedure pixel_map.blend(window : WindowRef; device_rect : RectPtr = NIL; bmp_rect : RectPtr = NIL );
-begin
- draw(window ,device_rect ,bmp_rect ); // currently just mapped to drawing method
-
-end;
-
-{ BLEND }
-procedure pixel_map.blend(window : WindowRef; x ,y : int; scale : double = 1.0 );
-begin
- draw(window ,x ,y ,scale ); // currently just mapped to drawing method
-
-end;
-
-{ _BUF }
-function pixel_map._buf;
-begin
- result:=m_buf;
-
-end;
-
-{ _WIDTH }
-function pixel_map._width;
-var
- pm : PixMapHandle;
-
- bounds : Carbon.Rect;
-
-begin
- if m_pmap = NIL then
- begin
- result:=0;
-
- exit;
-
- end;
-
- pm:=GetGWorldPixMap(GrafPtr(m_pmap ) );
-
- GetPixBounds(pm ,bounds );
-
- result:=bounds.right - bounds.left;
-
-end;
-
-{ _HEIGHT }
-function pixel_map._height;
-var
- pm : PixMapHandle;
-
- bounds : Carbon.Rect;
-
-begin
- if m_pmap = NIL then
- begin
- result:=0;
-
- exit;
-
- end;
-
- pm:=GetGWorldPixMap(GrafPtr(m_pmap ) );
-
- GetPixBounds(pm ,bounds );
-
- result:=bounds.bottom - bounds.top;
-
-end;
-
-{ _ROW_BYTES }
-function pixel_map._row_bytes;
-var
- pm : PixMapHandle;
-
-begin
- if m_pmap = NIL then
- begin
- result:=0;
-
- exit;
-
- end;
-
- pm:=GetGWorldPixMap(GrafPtr(m_pmap ) );
-
- result:=calc_row_len(_width ,GetPixDepth(pm ) );
-
-end;
-
-{ _BPP }
-function pixel_map._bpp;
-begin
- result:=m_bpp;
-
-end;
-
-{ CALC_ROW_LEN }
-function pixel_map.calc_row_len;
-var
- n ,k : unsigned;
-
-begin
- n:=width;
-
- case bits_per_pixel of
- 1 :
- begin
- k:=n;
- n:=n shr 3;
-
- if k and 7 <> 0 then
- inc(n );
-
- end;
-
- 4 :
- begin
- k:=n;
- n:=n shr 1;
-
- if k and 3 <> 0 then
- inc(n );
-
- end;
-
- 8 :
- NoP;
-
- 16 :
- n:=n shl 1;
-
- 24 :
- n:=(n shl 1 ) + n;
-
- 32 :
- n:=n shl 2;
-
- else
- n:=0;
-
- end;
-
- result:=((n + 3 ) shr 2 ) shl 2;
-
-end;
-
-END.
-
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+// Copyright (C) 2002 Hansruedi Baer (MacOS support)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+// baer@karto.baug.eth.ch
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 24.03.2006-Milano: Finished MacOS port
+// 20.03.2006-Milano: Unit port establishment
+//
+{ agg_mac_pmap.pas }
+unit
+ agg_mac_pmap ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ QuickTimeComponents ,ImageCompression ,Carbon ,
+ agg_basics ;
+
+{ TYPES DEFINITION }
+const
+ org_mono8 = 8;
+ org_color16 = 16;
+ org_color24 = 24;
+ org_color32 = 32;
+
+type
+ pixel_map = object
+ m_pmap : ^CGrafPort;
+ m_buf : pointer;
+
+ m_bpp ,
+ m_img_size : unsigned;
+
+ constructor Construct;
+ destructor Destruct;
+
+ procedure destroy;
+ procedure create(width ,height ,org : unsigned; clear_val : unsigned = 255 );
+ procedure clear (clear_val : unsigned = 255 );
+
+ function load_from_qt(filename : shortstring ) : boolean;
+ function save_as_qt (filename : shortstring ) : boolean;
+
+ procedure draw(window : WindowRef; device_rect : RectPtr = NIL; bmp_rect : RectPtr = NIL ); overload;
+ procedure draw(window : WindowRef; x ,y : int; scale : double = 1.0 ); overload;
+
+ procedure blend(window : WindowRef; device_rect : RectPtr = NIL; bmp_rect : RectPtr = NIL ); overload;
+ procedure blend(window : WindowRef; x ,y : int; scale : double = 1.0 ); overload;
+
+ function _buf : pointer;
+ function _width : unsigned;
+ function _height : unsigned;
+ function _row_bytes : int;
+ function _bpp : unsigned;
+
+ //Auxiliary static functions
+ function calc_row_len(width ,bits_per_pixel : unsigned ) : unsigned;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor pixel_map.Construct;
+begin
+ m_pmap:=NIL;
+ m_buf :=NIL;
+ m_bpp :=0;
+
+ m_img_size:=0;
+
+end;
+
+{ DESTRUCT }
+destructor pixel_map.Destruct;
+begin
+ destroy;
+
+end;
+
+{ DESTROY }
+procedure pixel_map.destroy;
+begin
+ agg_freemem(m_buf ,m_img_size );
+
+ m_buf:=NIL;
+
+ if m_pmap <> NIL then
+ begin
+ DisposeGWorld(GrafPtr(m_pmap ) );
+
+ m_pmap:=NIL;
+
+ end;
+
+end;
+
+{ CREATE }
+procedure pixel_map.create;
+var
+ r : Carbon.Rect;
+
+ row_bytes : int;
+
+begin
+ destroy;
+
+ if width = 0 then
+ width:=1;
+
+ if height = 0 then
+ height:=1;
+
+ m_bpp :=org;
+ row_bytes:=calc_row_len(width ,m_bpp );
+
+ SetRect(r ,0 ,0 ,width ,height );
+
+ m_img_size:=row_bytes * height;
+
+ agg_getmem(m_buf ,m_img_size );
+
+// The Quicktime version for creating GWorlds is more flexible than the classical function.
+ QTNewGWorldFromPtr(m_pmap ,m_bpp ,ImageCompression.Rect(r ) ,NIL ,NIL ,0 ,m_buf ,row_bytes );
+
+// create_gray_scale_palette(m_pmap); I didn't care about gray scale palettes so far.
+ if clear_val <= 255 then
+ fillchar(m_buf^ ,m_img_size ,clear_val );
+
+end;
+
+{ CLEAR }
+procedure pixel_map.clear;
+begin
+ if m_buf <> NIL then
+ fillchar(m_buf^ ,m_img_size ,clear_val );
+
+end;
+
+{ LOAD_FROM_QT }
+function pixel_map.load_from_qt;
+var
+ fss : FSSpec;
+ err : OSErr;
+ gi : GraphicsImportComponent;
+ buf : int8u_ptr;
+
+ desc : ImageDescriptionHandle;
+ depth : int16;
+ size : unsigned;
+
+begin
+// get file specification to application directory
+ err:=HGetVol(NIL ,fss.vRefNum ,fss.parID );
+
+ if err = noErr then
+ begin
+ // CopyCStringToPascal(filename ,fss.name );
+ fss.name:=filename;
+
+ err:=GetGraphicsImporterForFile(ImageCompression.FSSpec(fss ) ,gi );
+
+ if err = noErr then
+ begin
+ GraphicsImportGetImageDescription(gi ,desc );
+
+ // For simplicity, all images are currently converted to 32 bit.
+ // create an empty pixelmap
+ depth:=24;
+
+ create (desc^.width ,desc^.height ,depth ,$ff );
+ DisposeHandle(Handle(desc ) );
+
+ // let Quicktime draw to pixelmap
+ GraphicsImportSetGWorld(gi ,m_pmap ,NIL );
+ GraphicsImportDraw (gi );
+
+ end;
+
+ end;
+
+ result:=err = noErr;
+
+end;
+
+{ SAVE_AS_QT }
+function pixel_map.save_as_qt;
+var
+ fss : FSSpec;
+ err : OSErr;
+ ge : GraphicsExportComponent;
+ cnt : UInt32;
+
+begin
+// get file specification to application directory
+ err:=HGetVol(NIL ,fss.vRefNum ,fss.parID );
+
+ if err = noErr then
+ begin
+ // CopyCStringToPascal(filename ,fss.name );
+ fss.name:=filename;
+
+ // I decided to use PNG as output image file type.
+ // There are a number of other available formats.
+ // Should I check the file suffix to choose the image file format?
+ err:=
+ OpenADefaultComponent(
+ LongWord(int32_ptr(@GraphicsExporterComponentType[1 ] )^ ) ,
+ LongWord(int32_ptr(@kQTFileTypePNG[1 ] )^ ) ,
+ Carbon.ComponentInstance(ge ) );
+
+ if err = noErr then
+ begin
+ err:=GraphicsExportSetInputGWorld(ge ,m_pmap );
+
+ if err = noErr then
+ begin
+ err:=GraphicsExportSetOutputFile(ge ,ImageCompression.FSSpec(fss ) );
+ cnt:=0;
+
+ if err = noErr then
+ GraphicsExportDoExport(ge ,cnt );
+
+ end;
+
+ CloseComponent(Carbon.ComponentInstance(ge ) );
+
+ end;
+
+ end;
+
+ result:=err = noErr;
+
+end;
+
+{ DRAW }
+procedure pixel_map.draw(window : WindowRef; device_rect : RectPtr = NIL; bmp_rect : RectPtr = NIL );
+var
+ pm : PixMapHandle;
+ port : CGrafPtr;
+
+ src_rect ,dest_rect : Carbon.Rect;
+
+ image_description : ImageDescriptionHandle;
+
+begin
+ if (m_pmap = NIL ) or
+ (m_buf = NIL ) then
+ exit;
+
+ pm :=GetGWorldPixMap(GrafPtr(m_pmap ) );
+ port:=GetWindowPort (window );
+
+// Again, I used the Quicktime version.
+// Good old 'CopyBits' does better interpolation when scaling
+// but does not support all pixel depths.
+ SetRect(dest_rect ,0 ,0 ,_width ,_height );
+
+ MakeImageDescriptionForPixMap(ImageCompression.PixMapHandle(pm ) ,image_description );
+
+ if image_description <> NIL then
+ begin
+ SetRect(src_rect ,0 ,0 ,image_description^.width ,image_description^.height );
+
+ DecompressImage(
+ GetPixBaseAddr(pm ) ,
+ image_description ,
+ ImageCompression.PixMapHandle(GetPortPixMap(port ) ) ,
+ ImageCompression.Rect(src_rect ) ,
+ ImageCompression.Rect(dest_rect ) ,
+ ditherCopy ,NIL );
+
+ DisposeHandle(Handle(image_description ) );
+
+ end;
+
+end;
+
+{ DRAW }
+procedure pixel_map.draw(window : WindowRef; x ,y : int; scale : double = 1.0 );
+var
+ width ,height : unsigned;
+
+ r : Carbon.Rect;
+
+begin
+ if (m_pmap = NIL ) or
+ (m_buf = NIL ) then
+ exit;
+
+ width :=System.Trunc(_width * scale );
+ height:=System.Trunc(_height * scale );
+
+ SetRect(r ,x ,y ,x + width ,y + height );
+ draw (window ,@r );
+
+end;
+
+{ BLEND }
+procedure pixel_map.blend(window : WindowRef; device_rect : RectPtr = NIL; bmp_rect : RectPtr = NIL );
+begin
+ draw(window ,device_rect ,bmp_rect ); // currently just mapped to drawing method
+
+end;
+
+{ BLEND }
+procedure pixel_map.blend(window : WindowRef; x ,y : int; scale : double = 1.0 );
+begin
+ draw(window ,x ,y ,scale ); // currently just mapped to drawing method
+
+end;
+
+{ _BUF }
+function pixel_map._buf;
+begin
+ result:=m_buf;
+
+end;
+
+{ _WIDTH }
+function pixel_map._width;
+var
+ pm : PixMapHandle;
+
+ bounds : Carbon.Rect;
+
+begin
+ if m_pmap = NIL then
+ begin
+ result:=0;
+
+ exit;
+
+ end;
+
+ pm:=GetGWorldPixMap(GrafPtr(m_pmap ) );
+
+ GetPixBounds(pm ,bounds );
+
+ result:=bounds.right - bounds.left;
+
+end;
+
+{ _HEIGHT }
+function pixel_map._height;
+var
+ pm : PixMapHandle;
+
+ bounds : Carbon.Rect;
+
+begin
+ if m_pmap = NIL then
+ begin
+ result:=0;
+
+ exit;
+
+ end;
+
+ pm:=GetGWorldPixMap(GrafPtr(m_pmap ) );
+
+ GetPixBounds(pm ,bounds );
+
+ result:=bounds.bottom - bounds.top;
+
+end;
+
+{ _ROW_BYTES }
+function pixel_map._row_bytes;
+var
+ pm : PixMapHandle;
+
+begin
+ if m_pmap = NIL then
+ begin
+ result:=0;
+
+ exit;
+
+ end;
+
+ pm:=GetGWorldPixMap(GrafPtr(m_pmap ) );
+
+ result:=calc_row_len(_width ,GetPixDepth(pm ) );
+
+end;
+
+{ _BPP }
+function pixel_map._bpp;
+begin
+ result:=m_bpp;
+
+end;
+
+{ CALC_ROW_LEN }
+function pixel_map.calc_row_len;
+var
+ n ,k : unsigned;
+
+begin
+ n:=width;
+
+ case bits_per_pixel of
+ 1 :
+ begin
+ k:=n;
+ n:=n shr 3;
+
+ if k and 7 <> 0 then
+ inc(n );
+
+ end;
+
+ 4 :
+ begin
+ k:=n;
+ n:=n shr 1;
+
+ if k and 3 <> 0 then
+ inc(n );
+
+ end;
+
+ 8 :
+ NoP;
+
+ 16 :
+ n:=n shl 1;
+
+ 24 :
+ n:=(n shl 1 ) + n;
+
+ 32 :
+ n:=n shl 2;
+
+ else
+ n:=0;
+
+ end;
+
+ result:=((n + 3 ) shr 2 ) shl 2;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/platform/mac/agg_platform_support.pas b/src/corelib/render/software/platform/mac/agg_platform_support.pas
index 9fc3fd20..608b7854 100644
--- a/src/corelib/render/software/platform/mac/agg_platform_support.pas
+++ b/src/corelib/render/software/platform/mac/agg_platform_support.pas
@@ -1,2212 +1,2212 @@
-//----------------------------------------------------------------------------
-// Anti-Grain Geometry - Version 2.4 (Public License)
-// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
-// Copyright (C) 2003 Hansruedi Baer (MacOS support)
-//
-// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
-// Pascal Port By: Milan Marusinec alias Milano
-// milan@marusinec.sk
-// http://www.aggpas.org
-// Copyright (c) 2005-2006
-//
-// Permission to copy, use, modify, sell and distribute this software
-// is granted provided this copyright notice appears in all copies.
-// This software is provided "as is" without express or implied
-// warranty, and with no claim as to its suitability for any purpose.
-//
-//----------------------------------------------------------------------------
-// Contact: mcseem@antigrain.com
-// mcseemagg@yahoo.com
-// http://www.antigrain.com
-// baer@karto.baug.eth.ch
-//
-//----------------------------------------------------------------------------
-//
-// Note:
-// I tried to retain the original structure for the Win32 platform as far
-// as possible. Currently, not all features are implemented but the examples
-// should work properly.
-// HB
-//
-//----------------------------------------------------------------------------
-//
-// class platform_support
-//
-// It's not a part of the AGG library, it's just a helper class to create
-// interactive demo examples. Since the examples should not be too complex
-// this class is provided to support some very basic interactive graphical
-// funtionality, such as putting the rendered image to the window, simple
-// keyboard and mouse input, window resizing, setting the window title,
-// and catching the "idle" events.
-//
-// The most popular platforms are:
-//
-// Windows-32 API
-// X-Window API
-// SDL library (see http://www.libsdl.org/)
-// MacOS C/C++ API
-//
-// All the system dependent stuff sits in the platform_specific class.
-// The platform_support class has just a pointer to it and it's
-// the responsibility of the implementation to create/delete it.
-// This class being defined in the implementation file can have
-// any platform dependent stuff such as HWND, X11 Window and so on.
-//
-// [Pascal Port History] -----------------------------------------------------
-//
-// 26.03.2006-Milano: Finished & tested MacOS X port
-// 20.03.2006-Milano: Unit port establishment
-//
-{ agg_platform_support.pas }
-unit
- agg_platform_support ;
-
-INTERFACE
-
-{$I agg_mode.inc }
-
-uses
- Carbon ,
- agg_basics ,
- agg_ctrl ,
- agg_rendering_buffer ,
- agg_trans_affine ,
- agg_trans_viewport ,
- agg_mac_pmap ,
- agg_color_conv ;
-
-{ TYPES DEFINITION }
-const
-//----------------------------------------------------------window_flag_e
-// These are flags used in method init(). Not all of them are
-// applicable on different platforms, for example the win32_api
-// cannot use a hardware buffer (window_hw_buffer).
-// The implementation should simply ignore unsupported flags.
- window_resize = 1;
- window_hw_buffer = 2;
- window_keep_aspect_ratio = 4;
- window_process_all_keys = 8;
-
-type
-//-----------------------------------------------------------pix_format_e
-// Possible formats of the rendering buffer. Initially I thought that it's
-// reasonable to create the buffer and the rendering functions in
-// accordance with the native pixel format of the system because it
-// would have no overhead for pixel format conersion.
-// But eventually I came to a conclusion that having a possibility to
-// convert pixel formats on demand is a good idea. First, it was X11 where
-// there lots of different formats and visuals and it would be great to
-// render everything in, say, RGB-24 and display it automatically without
-// any additional efforts. The second reason is to have a possibility to
-// debug renderers for different pixel formats and colorspaces having only
-// one computer and one system.
-//
-// This stuff is not included into the basic AGG functionality because the
-// number of supported pixel formats (and/or colorspaces) can be great and
-// if one needs to add new format it would be good only to add new
-// rendering files without having to modify any existing ones (a general
-// principle of incapsulation and isolation).
-//
-// Using a particular pixel format doesn't obligatory mean the necessity
-// of software conversion. For example, win32 API can natively display
-// gray8, 15-bit RGB, 24-bit BGR, and 32-bit BGRA formats.
-// This list can be (and will be!) extended in future.
- pix_format_e = (
-
- pix_format_undefined , // By default. No conversions are applied
- pix_format_bw, // 1 bit per color B/W
- pix_format_gray8, // Simple 256 level grayscale
- pix_format_gray16, // Simple 65535 level grayscale
- pix_format_rgb555, // 15 bit rgb. Depends on the byte ordering!
- pix_format_rgb565, // 16 bit rgb. Depends on the byte ordering!
- pix_format_rgbAAA, // 30 bit rgb. Depends on the byte ordering!
- pix_format_rgbBBA, // 32 bit rgb. Depends on the byte ordering!
- pix_format_bgrAAA, // 30 bit bgr. Depends on the byte ordering!
- pix_format_bgrABB, // 32 bit bgr. Depends on the byte ordering!
- pix_format_rgb24, // R-G-B, one byte per color component
- pix_format_bgr24, // B-G-R, native win32 BMP format.
- pix_format_rgba32, // R-G-B-A, one byte per color component
- pix_format_argb32, // A-R-G-B, native MAC format
- pix_format_abgr32, // A-B-G-R, one byte per color component
- pix_format_bgra32, // B-G-R-A, native win32 BMP format
- pix_format_rgb48, // R-G-B, 16 bits per color component
- pix_format_bgr48, // B-G-R, native win32 BMP format.
- pix_format_rgba64, // R-G-B-A, 16 bits byte per color component
- pix_format_argb64, // A-R-G-B, native MAC format
- pix_format_abgr64, // A-B-G-R, one byte per color component
- pix_format_bgra64, // B-G-R-A, native win32 BMP format
-
- end_of_pix_formats );
-
-const
-//-------------------------------------------------------------input_flag_e
-// Mouse and keyboard flags. They can be different on different platforms
-// and the ways they are obtained are also different. But in any case
-// the system dependent flags should be mapped into these ones. The meaning
-// of that is as follows. For example, if kbd_ctrl is set it means that the
-// ctrl key is pressed and being held at the moment. They are also used in
-// the overridden methods such as on_mouse_move(), on_mouse_button_down(),
-// on_mouse_button_dbl_click(), on_mouse_button_up(), on_key().
-// In the method on_mouse_button_up() the mouse flags have different
-// meaning. They mean that the respective button is being released, but
-// the meaning of the keyboard flags remains the same.
-// There's absolut minimal set of flags is used because they'll be most
-// probably supported on different platforms. Even the mouse_right flag
-// is restricted because Mac's mice have only one button, but AFAIK
-// it can be simulated with holding a special key on the keydoard.
- mouse_left = 1;
- mouse_right = 2;
- kbd_shift = 4;
- kbd_ctrl = 8;
-
-//--------------------------------------------------------------key_code_e
-// Keyboard codes. There's also a restricted set of codes that are most
-// probably supported on different platforms. Any platform dependent codes
-// should be converted into these ones. There're only those codes are
-// defined that cannot be represented as printable ASCII-characters.
-// All printable ASCII-set can be used in a regilar C/C++ manner:
-// ' ', 'A', '0' '+' and so on.
-// Since the clasas is used for creating very simple demo-applications
-// we don't need very rich possibilities here, just basic ones.
-// Actually the numeric key codes are taken from the SDL library, so,
-// the implementation of the SDL support does not require any mapping.
-// ASCII set. Should be supported everywhere
- key_backspace = 8;
- key_tab = 9;
- key_clear = 12;
- key_return = 13;
- key_pause = 19;
- key_escape = 27;
-
-// Keypad
- key_delete = 127;
- key_kp0 = 256;
- key_kp1 = 257;
- key_kp2 = 258;
- key_kp3 = 259;
- key_kp4 = 260;
- key_kp5 = 261;
- key_kp6 = 262;
- key_kp7 = 263;
- key_kp8 = 264;
- key_kp9 = 265;
- key_kp_period = 266;
- key_kp_divide = 267;
- key_kp_multiply = 268;
- key_kp_minus = 269;
- key_kp_plus = 270;
- key_kp_enter = 271;
- key_kp_equals = 272;
-
-// Arrow-keys and stuff
- key_up = 273;
- key_down = 274;
- key_right = 275;
- key_left = 276;
- key_insert = 277;
- key_home = 278;
- key_end = 279;
- key_page_up = 280;
- key_page_down = 281;
-
-// Functional keys. You'd better avoid using
-// f11...f15 in your applications if you want
-// the applications to be portable
- key_f1 = 282;
- key_f2 = 283;
- key_f3 = 284;
- key_f4 = 285;
- key_f5 = 286;
- key_f6 = 287;
- key_f7 = 288;
- key_f8 = 289;
- key_f9 = 290;
- key_f10 = 291;
- key_f11 = 292;
- key_f12 = 293;
- key_f13 = 294;
- key_f14 = 295;
- key_f15 = 296;
-
-// The possibility of using these keys is
-// very restricted. Actually it's guaranteed
-// only in win32_api and win32_sdl implementations
- key_numlock = 300;
- key_capslock = 301;
- key_scrollock = 302;
-
- max_ctrl = 128;
-
-type
-//----------------------------------------------------------ctrl_container
-// A helper class that contains pointers to a number of controls.
-// This class is used to ease the event handling with controls.
-// The implementation should simply call the appropriate methods
-// of this class when appropriate events occure.
- crtl_container_ptr = ^ctrl_container;
- ctrl_container = object
- m_ctrl : array[0..max_ctrl - 1 ] of ctrl_ptr;
-
- m_num_ctrl : unsigned;
- m_cur_ctrl : int;
-
- constructor Construct;
- destructor Destruct;
-
- procedure add(c : ctrl_ptr );
-
- function in_rect(x ,y : double ) : boolean;
-
- function on_mouse_button_down(x ,y : double ) : boolean;
- function on_mouse_button_up (x ,y : double ) : boolean;
-
- function on_mouse_move(x ,y : double; button_flag : boolean ) : boolean;
- function on_arrow_keys(left ,right ,down ,up : boolean ) : boolean;
-
- function set_cur(x ,y : double ) : boolean;
-
- end;
-
-//---------------------------------------------------------platform_support
-// This class is a base one to the apllication classes. It can be used
-// as follows:
-//
-// the_application = object(platform_support )
-//
-// constructor Construct(bpp : unsigned; flip_y : boolean );
-// . . .
-//
-// //override stuff . . .
-// procedure on_init; virtual;
-// procedure on_draw; virtual;
-// procedure on_resize(sx ,sy : int ); virtual;
-// // . . . and so on, see virtual functions
-//
-// //any your own stuff . . .
-// };
-//
-// VAR
-// app : the_application;
-//
-// BEGIN
-// app.Construct(pix_format_rgb24 ,true );
-// app.caption ("AGG Example. Lion" );
-//
-// if app.init(500 ,400 ,window_resize ) then
-// app.run;
-//
-// app.Destruct;
-//
-// END.
-//
-const
- max_images = 16;
-
-type
- platform_specific_ptr = ^platform_specific;
- platform_specific = object
- m_format ,
- m_sys_format : pix_format_e;
-
- m_flip_y : boolean;
- m_bpp ,
- m_sys_bpp : unsigned;
- m_window : WindowRef;
-
- m_pmap_window : pixel_map;
- m_pmap_img : array[0..max_images - 1 ] of pixel_map;
-
- m_keymap : array[0..255 ] of unsigned;
-
- m_last_translated_key : unsigned;
-
- m_cur_x ,
- m_cur_y : int;
-
- m_input_flags : unsigned;
- m_redraw_flag : boolean;
-
- m_sw_freq ,
- m_sw_start : UnsignedWide;
-
- constructor Construct(format : pix_format_e; flip_y : boolean );
- destructor Destruct;
-
- procedure create_pmap (width ,height : unsigned; wnd : rendering_buffer_ptr );
- procedure display_pmap(window : WindowRef; src : rendering_buffer_ptr );
-
- function load_pmap(fn : shortstring; idx : unsigned; dst : rendering_buffer_ptr ) : boolean;
- function save_pmap(fn : shortstring; idx : unsigned; src : rendering_buffer_ptr ) : boolean;
-
- function translate(keycode : unsigned ) : unsigned;
-
- end;
-
- platform_support_ptr = ^platform_support;
- platform_support = object
- m_specific : platform_specific_ptr;
- m_ctrls : ctrl_container;
-
- m_format : pix_format_e;
-
- m_bpp : unsigned;
-
- m_rbuf_window : rendering_buffer;
- m_rbuf_img : array[0..max_images - 1 ] of rendering_buffer;
-
- m_window_flags : unsigned;
- m_wait_mode ,
- m_flip_y : boolean; // flip_y - true if you want to have the Y-axis flipped vertically
- m_caption : shortstring;
- m_resize_mtx : trans_affine;
-
- m_initial_width ,
- m_initial_height : int;
-
- constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
- destructor Destruct;
-
- // Setting the windows caption (title). Should be able
- // to be called at least before calling init().
- // It's perfect if they can be called anytime.
- procedure caption_(cap : shortstring );
-
- // These 3 menthods handle working with images. The image
- // formats are the simplest ones, such as .BMP in Windows or
- // .ppm in Linux. In the applications the names of the files
- // should not have any file extensions. Method load_img() can
- // be called before init(), so, the application could be able
- // to determine the initial size of the window depending on
- // the size of the loaded image.
- // The argument "idx" is the number of the image 0...max_images-1
- function load_img (idx : unsigned; file_ : shortstring ) : boolean;
- function save_img (idx : unsigned; file_ : shortstring ) : boolean;
- function create_img(idx : unsigned; width_ : unsigned = 0; height_ : unsigned = 0 ) : boolean;
-
- // init() and run(). See description before the class for details.
- // The necessity of calling init() after creation is that it's
- // impossible to call the overridden virtual function (on_init())
- // from the constructor. On the other hand it's very useful to have
- // some on_init() event handler when the window is created but
- // not yet displayed. The rbuf_window() method (see below) is
- // accessible from on_init().
- function init(width_ ,height_ ,flags : unsigned ) : boolean;
- function run : int;
- procedure quit;
-
- // The very same parameters that were used in the constructor
- function _format : pix_format_e;
- function _flip_y : boolean;
- function _bpp : unsigned;
-
- // The following provides a very simple mechanism of doing someting
- // in background. It's not multitheading. When whait_mode is true
- // the class waits for the events and it does not ever call on_idle().
- // When it's false it calls on_idle() when the event queue is empty.
- // The mode can be changed anytime. This mechanism is satisfactory
- // for creation very simple animations.
- function _wait_mode : boolean;
- procedure wait_mode_(wait_mode : boolean );
-
- // These two functions control updating of the window.
- // force_redraw() is an analog of the Win32 InvalidateRect() function.
- // Being called it sets a flag (or sends a message) which results
- // in calling on_draw() and updating the content of the window
- // when the next event cycle comes.
- // update_window() results in just putting immediately the content
- // of the currently rendered buffer to the window without calling
- // on_draw().
- procedure force_redraw;
- procedure update_window;
-
- // So, finally, how to draw anythig with AGG? Very simple.
- // rbuf_window() returns a reference to the main rendering
- // buffer which can be attached to any rendering class.
- // rbuf_img() returns a reference to the previously created
- // or loaded image buffer (see load_img()). The image buffers
- // are not displayed directly, they should be copied to or
- // combined somehow with the rbuf_window(). rbuf_window() is
- // the only buffer that can be actually displayed.
- function rbuf_window : rendering_buffer_ptr;
- function rbuf_img(idx : unsigned ) : rendering_buffer_ptr;
-
- // Returns file extension used in the implemenation for the particular
- // system.
- function _img_ext : shortstring;
-
- //
- procedure copy_img_to_window(idx : unsigned );
- procedure copy_window_to_img(idx : unsigned );
- procedure copy_img_to_img (idx_to ,idx_from : unsigned );
-
- // Event handlers. They are not pure functions, so you don't have
- // to override them all.
- // In my demo applications these functions are defined inside
- // the the_application class
- procedure on_init; virtual;
- procedure on_resize(sx ,sy : int ); virtual;
- procedure on_idle; virtual;
-
- procedure on_mouse_move(x ,y : int; flags : unsigned ); virtual;
-
- procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual;
- procedure on_mouse_button_up (x ,y : int; flags : unsigned ); virtual;
-
- procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
- procedure on_ctrl_change; virtual;
- procedure on_draw; virtual;
- procedure on_post_draw(raw_handler : pointer ); virtual;
-
- // Adding control elements. A control element once added will be
- // working and reacting to the mouse and keyboard events. Still, you
- // will have to render them in the on_draw() using function
- // render_ctrl() because platform_support doesn't know anything about
- // renderers you use. The controls will be also scaled automatically
- // if they provide a proper scaling mechanism (all the controls
- // included into the basic AGG package do).
- // If you don't need a particular control to be scaled automatically
- // call ctrl::no_transform() after adding.
- procedure add_ctrl(c : ctrl_ptr );
-
- // Auxiliary functions. trans_affine_resizing() modifier sets up the resizing
- // matrix on the basis of the given width and height and the initial
- // width and height of the window. The implementation should simply
- // call this function every time when it catches the resizing event
- // passing in the new values of width and height of the window.
- // Nothing prevents you from "cheating" the scaling matrix if you
- // call this function from somewhere with wrong arguments.
- // trans_affine_resizing() accessor simply returns current resizing matrix
- // which can be used to apply additional scaling of any of your
- // stuff when the window is being resized.
- // width(), height(), initial_width(), and initial_height() must be
- // clear to understand with no comments :-)
- procedure trans_affine_resizing_(width_ ,height_ : int );
- function _trans_affine_resizing : trans_affine_ptr;
-
- function _width : double;
- function _height : double;
- function _initial_width : double;
- function _initial_height : double;
- function _window_flags : unsigned;
-
- // Get raw display handler depending on the system.
- // For win32 its an HDC, for other systems it can be a pointer to some
- // structure. See the implementation files for detals.
- // It's provided "as is", so, first you should check if it's not null.
- // If it's null the raw_display_handler is not supported. Also, there's
- // no guarantee that this function is implemented, so, in some
- // implementations you may have simply an unresolved symbol when linking.
- function _raw_display_handler : pointer;
-
- // display message box or print the message to the console
- // (depending on implementation)
- procedure message_(msg : PChar );
-
- // Stopwatch functions. Function elapsed_time() returns time elapsed
- // since the latest start_timer() invocation in millisecods.
- // The resolutoin depends on the implementation.
- // In Win32 it uses QueryPerformanceFrequency() / QueryPerformanceCounter().
- procedure start_timer;
- function elapsed_time : double;
-
- // Get the full file name. In most cases it simply returns
- // file_name. As it's appropriate in many systems if you open
- // a file by its name without specifying the path, it tries to
- // open it in the current directory. The demos usually expect
- // all the supplementary files to be placed in the current
- // directory, that is usually coincides with the directory where
- // the the executable is. However, in some systems (BeOS) it's not so.
- // For those kinds of systems full_file_name() can help access files
- // preserving commonly used policy.
- // So, it's a good idea to use in the demos the following:
- // FILE* fd = fopen(full_file_name("some.file"), "r");
- // instead of
- // FILE* fd = fopen("some.file", "r");
- function full_file_name(file_name : shortstring ) : shortstring;
- function file_source (path ,fname : shortstring ) : shortstring;
-
- end;
-
-{ GLOBAL PROCEDURES }
-
-
-IMPLEMENTATION
-{ LOCAL VARIABLES & CONSTANTS }
-{ UNIT IMPLEMENTATION }
-{ CONSTRUCT }
-constructor ctrl_container.Construct;
-begin
- m_num_ctrl:=0;
- m_cur_ctrl:=-1;
-
-end;
-
-{ DESTRUCT }
-destructor ctrl_container.Destruct;
-begin
-end;
-
-{ ADD }
-procedure ctrl_container.add;
-begin
- if m_num_ctrl < max_ctrl then
- begin
- m_ctrl[m_num_ctrl ]:=c;
-
- inc(m_num_ctrl );
-
- end;
-
-end;
-
-{ IN_RECT }
-function ctrl_container.in_rect;
-var
- i : unsigned;
-
-begin
- result:=false;
-
- if m_num_ctrl > 0 then
- for i:=0 to m_num_ctrl - 1 do
- if m_ctrl[i ].in_rect(x ,y ) then
- begin
- result:=true;
-
- exit;
-
- end;
-
-end;
-
-{ ON_MOUSE_BUTTON_DOWN }
-function ctrl_container.on_mouse_button_down;
-var
- i : unsigned;
-
-begin
- result:=false;
-
- if m_num_ctrl > 0 then
- for i:=0 to m_num_ctrl - 1 do
- if m_ctrl[i ].on_mouse_button_down(x ,y ) then
- begin
- result:=true;
-
- exit;
-
- end;
-
-end;
-
-{ ON_MOUSE_BUTTON_UP }
-function ctrl_container.on_mouse_button_up;
-var
- i : unsigned;
-
-begin
- result:=false;
-
- if m_num_ctrl > 0 then
- for i:=0 to m_num_ctrl - 1 do
- if m_ctrl[i ].on_mouse_button_up(x ,y ) then
- begin
- result:=true;
-
- exit;
-
- end;
-
-end;
-
-{ ON_MOUSE_MOVE }
-function ctrl_container.on_mouse_move;
-var
- i : unsigned;
-
-begin
- result:=false;
-
- if m_num_ctrl > 0 then
- for i:=0 to m_num_ctrl - 1 do
- if m_ctrl[i ].on_mouse_move(x ,y ,button_flag ) then
- begin
- result:=true;
-
- exit;
-
- end;
-
-end;
-
-{ ON_ARROW_KEYS }
-function ctrl_container.on_arrow_keys;
-begin
- result:=false;
-
- if m_cur_ctrl >= 0 then
- result:=m_ctrl[m_cur_ctrl ].on_arrow_keys(left ,right ,down ,up );
-
-end;
-
-{ SET_CUR }
-function ctrl_container.set_cur;
-var
- i : unsigned;
-
-begin
- result:=false;
-
- if m_num_ctrl > 0 then
- for i:=0 to m_num_ctrl - 1 do
- if m_ctrl[i ].in_rect(x ,y ) then
- begin
- if m_cur_ctrl <> i then
- begin
- m_cur_ctrl:=i;
-
- result:=true;
-
- end;
-
- exit;
-
- end;
-
- if m_cur_ctrl <> -1 then
- begin
- m_cur_ctrl:=-1;
-
- result:=true;
-
- end;
-
-end;
-
-{ CONSTRUCT }
-constructor platform_specific.Construct;
-var
- i : unsigned;
-
-begin
- m_pmap_window.Construct;
-
- for i:=0 to max_images - 1 do
- m_pmap_img[i ].Construct;
-
- m_format :=format;
- m_sys_format:=pix_format_undefined;
-
- m_flip_y :=flip_y;
- m_bpp :=0;
- m_sys_bpp:=0;
- m_window :=NIL;
-
- m_last_translated_key:=0;
-
- m_cur_x:=0;
- m_cur_y:=0;
-
- m_input_flags:=0;
- m_redraw_flag:=true;
-
- fillchar(m_keymap[0 ] ,sizeof(m_keymap ) ,0 );
-
-//Keyboard input is not yet fully supported nor tested
- //m_keymap[VK_PAUSE ]:=key_pause;
- m_keymap[kClearCharCode ]:=key_clear;
-
- //m_keymap[VK_NUMPAD0 ] :=key_kp0;
- //m_keymap[VK_NUMPAD1 ] :=key_kp1;
- //m_keymap[VK_NUMPAD2 ] :=key_kp2;
- //m_keymap[VK_NUMPAD3 ] :=key_kp3;
- //m_keymap[VK_NUMPAD4 ] :=key_kp4;
- //m_keymap[VK_NUMPAD5 ] :=key_kp5;
- //m_keymap[VK_NUMPAD6 ] :=key_kp6;
- //m_keymap[VK_NUMPAD7 ] :=key_kp7;
- //m_keymap[VK_NUMPAD8 ] :=key_kp8;
- //m_keymap[VK_NUMPAD9 ] :=key_kp9;
- //m_keymap[VK_DECIMAL ] :=key_kp_period;
- //m_keymap[VK_DIVIDE ] :=key_kp_divide;
- //m_keymap[VK_MULTIPLY ]:=key_kp_multiply;
- //m_keymap[VK_SUBTRACT ]:=key_kp_minus;
- //m_keymap[VK_ADD ] :=key_kp_plus;
-
- m_keymap[kUpArrowCharCode ] :=key_up;
- m_keymap[kDownArrowCharCode ] :=key_down;
- m_keymap[kRightArrowCharCode ] :=key_right;
- m_keymap[kLeftArrowCharCode ] :=key_left;
- //m_keymap[VK_INSERT ]:=key_insert;
- m_keymap[kDeleteCharCode ] :=key_delete;
- m_keymap[kHomeCharCode ] :=key_home;
- m_keymap[kEndCharCode ] :=key_end;
- m_keymap[kPageUpCharCode ] :=key_page_up;
- m_keymap[kPageDownCharCode ] :=key_page_down;
-
- //m_keymap[VK_F1 ] :=key_f1;
- //m_keymap[VK_F2 ] :=key_f2;
- //m_keymap[VK_F3 ] :=key_f3;
- //m_keymap[VK_F4 ] :=key_f4;
- //m_keymap[VK_F5 ] :=key_f5;
- //m_keymap[VK_F6 ] :=key_f6;
- //m_keymap[VK_F7 ] :=key_f7;
- //m_keymap[VK_F8 ] :=key_f8;
- //m_keymap[VK_F9 ] :=key_f9;
- //m_keymap[VK_F10 ]:=key_f10;
- //m_keymap[VK_F11 ]:=key_f11;
- //m_keymap[VK_F12 ]:=key_f12;
- //m_keymap[VK_F13 ]:=key_f13;
- //m_keymap[VK_F14 ]:=key_f14;
- //m_keymap[VK_F15 ]:=key_f15;
-
- //m_keymap[VK_NUMLOCK ]:=key_numlock;
- //m_keymap[VK_CAPITAL ]:=key_capslock;
- //m_keymap[VK_SCROLL ] :=key_scrollock;
-
- case m_format of
- pix_format_gray8 :
- begin
- m_sys_format:=pix_format_rgb24;
- m_bpp :=8;
- m_sys_bpp :=24;
-
- end;
-
- pix_format_rgb565 ,
- pix_format_rgb555 :
- begin
- m_sys_format:=pix_format_rgb555;
- m_bpp :=16;
- m_sys_bpp :=16;
-
- end;
-
- pix_format_rgb24 ,
- pix_format_bgr24 :
- begin
- m_sys_format:=pix_format_rgb24;
- m_bpp :=24;
- m_sys_bpp :=24;
-
- end;
-
- pix_format_bgra32 ,
- pix_format_abgr32 ,
- pix_format_argb32 ,
- pix_format_rgba32 :
- begin
- m_sys_format:=pix_format_argb32;
- m_bpp :=32;
- m_sys_bpp :=32;
-
- end;
-
- end;
-
- Microseconds(m_sw_freq );
- Microseconds(m_sw_start );
-
-end;
-
-{ DESTRUCT }
-destructor platform_specific.Destruct;
-var
- i : unsigned;
-
-begin
- m_pmap_window.Destruct;
-
- for i:=0 to max_images - 1 do
- m_pmap_img[i ].Destruct;
-
-end;
-
-{ CREATE_PMAP }
-procedure platform_specific.create_pmap;
-begin
- m_pmap_window.create(width ,height ,m_bpp );
-
- if m_flip_y then
- wnd.attach(
- m_pmap_window._buf ,
- m_pmap_window._width ,
- m_pmap_window._height ,
- -m_pmap_window._row_bytes )
-
- else
- wnd.attach(
- m_pmap_window._buf ,
- m_pmap_window._width ,
- m_pmap_window._height ,
- m_pmap_window._row_bytes )
-
-end;
-
-{ convert_pmap }
-procedure convert_pmap(dst ,src : rendering_buffer_ptr; format : pix_format_e );
-begin
- case format of
- pix_format_gray8 :
- color_conv(dst ,src ,color_conv_gray8_to_rgb24 );
-
- pix_format_rgb565 :
- color_conv(dst ,src ,color_conv_rgb565_to_rgb555 );
-
- pix_format_bgr24 :
- color_conv(dst ,src ,color_conv_bgr24_to_rgb24 );
-
- pix_format_abgr32 :
- color_conv(dst ,src ,color_conv_abgr32_to_argb32 );
-
- pix_format_bgra32 :
- color_conv(dst ,src ,color_conv_bgra32_to_argb32 );
-
- pix_format_rgba32 :
- color_conv(dst ,src ,color_conv_rgba32_to_argb32 );
-
- end;
-
-end;
-
-{ DISPLAY_PMAP }
-procedure platform_specific.display_pmap;
-var
- pmap_tmp : pixel_map;
- rbuf_tmp : rendering_buffer;
-
-begin
- if m_sys_format = m_format then
- m_pmap_window.draw(window )
-
- else
- begin
- pmap_tmp.Construct;
- pmap_tmp.create(m_pmap_window._width ,m_pmap_window._height ,m_sys_bpp );
-
- rbuf_tmp.Construct;
-
- if m_flip_y then
- rbuf_tmp.attach(pmap_tmp._buf ,pmap_tmp._width ,pmap_tmp._height ,-pmap_tmp._row_bytes )
- else
- rbuf_tmp.attach(pmap_tmp._buf ,pmap_tmp._width ,pmap_tmp._height ,pmap_tmp._row_bytes );
-
- convert_pmap (@rbuf_tmp ,src ,m_format );
- pmap_tmp.draw(window );
-
- rbuf_tmp.Destruct;
- pmap_tmp.Destruct;
-
- end;
-
-end;
-
-{ LOAD_PMAP }
-function platform_specific.load_pmap;
-var
- pmap_tmp : pixel_map;
- rbuf_tmp : rendering_buffer;
-
-begin
- pmap_tmp.Construct;
-
- if not pmap_tmp.load_from_qt(fn ) then
- begin
- result:=false;
-
- pmap_tmp.Destruct;
- exit;
-
- end;
-
- rbuf_tmp.Construct;
-
- if m_flip_y then
- rbuf_tmp.attach(pmap_tmp._buf ,pmap_tmp._width ,pmap_tmp._height ,-pmap_tmp._row_bytes )
- else
- rbuf_tmp.attach(pmap_tmp._buf ,pmap_tmp._width ,pmap_tmp._height ,pmap_tmp._row_bytes );
-
- m_pmap_img[idx ].create(pmap_tmp._width ,pmap_tmp._height ,m_bpp ,0 );
-
- if m_flip_y then
- dst.attach(
- m_pmap_img[idx ]._buf ,
- m_pmap_img[idx ]._width ,
- m_pmap_img[idx ]._height ,
- -m_pmap_img[idx ]._row_bytes )
- else
- dst.attach(
- m_pmap_img[idx ]._buf ,
- m_pmap_img[idx ]._width ,
- m_pmap_img[idx ]._height ,
- m_pmap_img[idx ]._row_bytes );
-
- case m_format of
- pix_format_rgb555 :
- case pmap_tmp._bpp of
- 16 : color_conv(dst ,@rbuf_tmp ,color_conv_rgb555_to_rgb555 );
- 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_rgb555 );
- 32 : color_conv(dst ,@rbuf_tmp ,color_conv_bgra32_to_rgb555 );
-
- end;
-
- pix_format_rgb565 :
- case pmap_tmp._bpp of
- 16 : color_conv(dst ,@rbuf_tmp ,color_conv_rgb555_to_rgb565 );
- 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_rgb565 );
- 32 : color_conv(dst ,@rbuf_tmp ,color_conv_bgra32_to_rgb565 );
-
- end;
-
- pix_format_rgb24 :
- case pmap_tmp._bpp of
- 16 : color_conv(dst ,@rbuf_tmp ,color_conv_rgb555_to_rgb24 );
- 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_rgb24 );
- 32 : color_conv(dst ,@rbuf_tmp ,color_conv_bgra32_to_rgb24 );
-
- end;
-
- pix_format_bgr24 :
- case pmap_tmp._bpp of
- 16 : color_conv(dst ,@rbuf_tmp ,color_conv_rgb555_to_bgr24 );
- 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_bgr24 );
- 32 : color_conv(dst ,@rbuf_tmp ,color_conv_bgra32_to_bgr24 );
-
- end;
-
- pix_format_abgr32 :
- case pmap_tmp._bpp of
- 16 : color_conv(dst ,@rbuf_tmp ,color_conv_rgb555_to_abgr32 );
- 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_abgr32 );
- 32 : color_conv(dst ,@rbuf_tmp ,color_conv_bgra32_to_abgr32 );
-
- end;
-
- pix_format_argb32 :
- case pmap_tmp._bpp of
- 16 : color_conv(dst ,@rbuf_tmp ,color_conv_rgb555_to_argb32 );
- 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_argb32 );
- 32 : color_conv(dst ,@rbuf_tmp ,color_conv_bgra32_to_argb32 );
-
- end;
-
- pix_format_bgra32 :
- case pmap_tmp._bpp of
- 16 : color_conv(dst ,@rbuf_tmp ,color_conv_rgb555_to_bgra32 );
- 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_bgra32 );
- 32 : color_conv(dst ,@rbuf_tmp ,color_conv_bgra32_to_bgra32 );
-
- end;
-
- pix_format_rgba32 :
- case pmap_tmp._bpp of
- 16 : color_conv(dst ,@rbuf_tmp ,color_conv_rgb555_to_rgba32 );
- 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_rgba32 );
- 32 : color_conv(dst ,@rbuf_tmp ,color_conv_bgra32_to_rgba32 );
-
- end;
-
- end;
-
- pmap_tmp.Destruct;
- rbuf_tmp.Destruct;
-
- result:=true;
-
-end;
-
-{ SAVE_PMAP }
-function platform_specific.save_pmap;
-var
- pmap_tmp : pixel_map;
- rbuf_tmp : rendering_buffer;
-
-begin
- if m_sys_format = m_format then
- begin
- result:=m_pmap_img[idx ].save_as_qt(fn );
-
- exit;
-
- end;
-
- pmap_tmp.Construct;
- pmap_tmp.create(
- m_pmap_img[idx ]._width ,
- m_pmap_img[idx ]._height ,
- m_sys_bpp );
-
- rbuf_tmp.Construct;
-
- if m_flip_y then
- rbuf_tmp.attach(pmap_tmp._buf ,pmap_tmp._width ,pmap_tmp._height ,-pmap_tmp._row_bytes )
- else
- rbuf_tmp.attach(pmap_tmp._buf ,pmap_tmp._width ,pmap_tmp._height ,pmap_tmp._row_bytes );
-
- convert_pmap(@rbuf_tmp ,src ,m_format );
-
- result:=pmap_tmp.save_as_qt(fn );
-
- rbuf_tmp.Destruct;
- pmap_tmp.Destruct;
-
-end;
-
-{ TRANSLATE }
-function platform_specific.translate;
-begin
- if keycode > 255 then
- m_last_translated_key:=0
- else
- m_last_translated_key:=m_keymap[keycode ];
-
-end;
-
-{ CONSTRUCT }
-constructor platform_support.Construct;
-var
- i : unsigned;
-
-begin
- new(m_specific ,Construct(format_ ,flip_y_ ) );
-
- m_ctrls.Construct;
- m_rbuf_window.Construct;
-
- for i:=0 to max_images - 1 do
- m_rbuf_img[i ].Construct;
-
- m_resize_mtx.Construct;
-
- m_format:=format_;
-
- m_bpp:=m_specific.m_bpp;
-
- m_window_flags:=0;
- m_wait_mode :=true;
- m_flip_y :=flip_y_;
-
- m_initial_width :=10;
- m_initial_height:=10;
-
- m_caption:='Anti-Grain Geometry Application'#0;
-
-end;
-
-{ DESTRUCT }
-destructor platform_support.Destruct;
-var
- i : unsigned;
-
-begin
- dispose(m_specific ,Destruct );
-
- m_ctrls.Destruct;
- m_rbuf_window.Destruct;
-
- for i:=0 to max_images - 1 do
- m_rbuf_img[i ].Destruct;
-
-end;
-
-{ CAPTION_ }
-procedure platform_support.caption_;
-begin
- m_caption:=cap + #0;
-
- dec(byte(m_caption[0 ] ) );
-
- if m_specific.m_window <> NIL then
- SetWindowTitleWithCFString(
- m_specific.m_window ,
- CFStringCreateWithPascalStringNoCopy(
- NIL ,cap ,kCFStringEncodingASCII ,NIL ) );
-
-end;
-
-{ LOAD_IMG }
-function platform_support.load_img;
-begin
- if idx < max_images then
- begin
- file_ :=file_ + _img_ext;
- result:=m_specific.load_pmap(file_ ,idx ,@m_rbuf_img[idx ] );
-
- end
- else
- result:=true;
-
-end;
-
-{ SAVE_IMG }
-function platform_support.save_img;
-begin
- if idx < max_images then
- result:=m_specific.save_pmap(file_ ,idx ,@m_rbuf_img[idx ] )
- else
- result:=true;
-
-end;
-
-{ CREATE_IMG }
-function platform_support.create_img;
-begin
- if idx < max_images then
- begin
- if width_ = 0 then
- width_:=m_specific.m_pmap_window._width;
-
- if height_ = 0 then
- height_:=m_specific.m_pmap_window._height;
-
- m_specific.m_pmap_img[idx ].create(width_ ,height_ ,m_specific.m_bpp );
-
- if m_flip_y then
- m_rbuf_img[idx ].attach(
- m_specific.m_pmap_img[idx ]._buf ,
- m_specific.m_pmap_img[idx ]._width ,
- m_specific.m_pmap_img[idx ]._height ,
- -m_specific.m_pmap_img[idx ]._row_bytes )
- else
- m_rbuf_img[idx ].attach(
- m_specific.m_pmap_img[idx ]._buf ,
- m_specific.m_pmap_img[idx ]._width ,
- m_specific.m_pmap_img[idx ]._height ,
- m_specific.m_pmap_img[idx ]._row_bytes );
-
- result:=true;
-
- end
- else
- result:=false;
-
-end;
-
-{ get_key_flags }
-function get_key_flags(wflags : int ) : unsigned;
-var
- flags : unsigned;
-
-begin
- flags:=0;
-
- if wflags and shiftKey <> 0 then
- flags:=flags or kbd_shift;
-
- if wflags and controlKey <> 0 then
- flags:=flags or kbd_ctrl;
-
- result:=flags;
-
-end;
-
-{ DOWINDOWCLOSE }
-function DoWindowClose(nextHandler : EventHandlerCallRef; theEvent : EventRef; userData : pointer ) : OSStatus;
-begin
- QuitApplicationEventLoop;
-
- result:=CallNextEventHandler(nextHandler ,theEvent );
-
-end;
-
-{ DOWINDOWDRAWCONTENT }
-function DoWindowDrawContent(nextHandler : EventHandlerCallRef; theEvent : EventRef; userData : pointer ) : OSStatus;
-var
- app : platform_support_ptr;
-
-begin
- app:=platform_support_ptr(userData );
-
- if app <> NIL then
- begin
- if app.m_specific.m_redraw_flag then
- begin
- app.on_draw;
-
- app.m_specific.m_redraw_flag:=false;
-
- end;
-
- app.m_specific.display_pmap(app.m_specific.m_window ,app.rbuf_window );
-
- end;
-
- result:=CallNextEventHandler(nextHandler ,theEvent );
-
-end;
-
-{ DOWINDOWRESIZE }
-function DoWindowResize(nextHandler : EventHandlerCallRef; theEvent : EventRef; userData : pointer ) : OSStatus;
-var
- app : platform_support_ptr;
- Rect : Carbon.Rect;
-
- width ,height : unsigned;
-
-begin
- app:=platform_support_ptr(userData );
-
- GetWindowBounds(app.m_specific.m_window ,kWindowContentRgn ,Rect );
-
- width :=Rect.Right - Rect.Left;
- height:=Rect.Bottom - Rect.Top;
-
- if (width <> app.rbuf_window._width ) or
- (height <> app.rbuf_window._height ) then
- begin
- app.m_specific.create_pmap(width ,height ,app.rbuf_window );
- app.trans_affine_resizing_(width ,height );
-
- app.on_resize(width ,height );
-
- end;
-
- app.force_redraw;
-
- result:=CallNextEventHandler(nextHandler ,theEvent );
-
-end;
-
-{ DOAPPQUIT }
-function DoAppQuit(nextHandler : EventHandlerCallRef; theEvent : EventRef; userData : pointer ) : OSStatus;
-begin
- result:=CallNextEventHandler(nextHandler ,theEvent );
-
-end;
-
-{ DOMOUSEDOWN }
-function DoMouseDown(nextHandler : EventHandlerCallRef; theEvent : EventRef; userData : pointer ) : OSStatus;
-var
- wheresMyMouse : Carbon.Point;
-
- modifier : UInt32;
- button : EventMouseButton;
-
- sz : UInt32;
- app : platform_support_ptr;
- ept : EventParamType;
-
-begin
- ept:=0;
-
- GetEventParameter(
- theEvent ,
- LongWord(int32_ptr(@kEventParamMouseLocation[1 ] )^ ) ,
- LongWord(int32_ptr(@typeQDPoint[1 ] )^ ) ,
- ept ,
- sizeof(Carbon.Point ) ,
- sz ,
- @wheresMyMouse );
-
- GlobalToLocal(wheresMyMouse );
- GetEventParameter(
- theEvent ,
- LongWord(int32_ptr(@kEventParamKeyModifiers[1 ] )^ ) ,
- LongWord(int32_ptr(@typeUInt32[1 ] )^ ) ,
- ept ,
- sizeof(UInt32 ) ,
- sz ,
- @modifier );
-
- app:=platform_support_ptr(userData );
-
- app.m_specific.m_cur_x:=wheresMyMouse.h;
-
- if app._flip_y then
- app.m_specific.m_cur_y:=app.rbuf_window._height - wheresMyMouse.v
- else
- app.m_specific.m_cur_y:=wheresMyMouse.v;
-
- GetEventParameter(
- theEvent ,
- LongWord(int32_ptr(@kEventParamMouseButton[1 ] )^ ) ,
- LongWord(int32_ptr(@typeMouseButton[1 ] )^ ) ,
- ept ,
- sizeof(EventMouseButton ) ,
- sz ,
- @button );
-
- case button of
- kEventMouseButtonSecondary :
- app.m_specific.m_input_flags:=mouse_right or get_key_flags(modifier );
-
- else
- app.m_specific.m_input_flags:=mouse_left or get_key_flags(modifier );
-
- end;
-
- app.m_ctrls.set_cur(
- app.m_specific.m_cur_x ,
- app.m_specific.m_cur_y );
-
- if app.m_ctrls.on_mouse_button_down(
- app.m_specific.m_cur_x ,
- app.m_specific.m_cur_y ) then
- begin
- app.on_ctrl_change;
- app.force_redraw;
-
- end
- else
- if app.m_ctrls.in_rect(
- app.m_specific.m_cur_x ,
- app.m_specific.m_cur_y ) then
- if app.m_ctrls.set_cur(
- app.m_specific.m_cur_x ,
- app.m_specific.m_cur_y ) then
- begin
- app.on_ctrl_change;
- app.force_redraw;
-
- end
- else
- else
- app.on_mouse_button_down(
- app.m_specific.m_cur_x ,
- app.m_specific.m_cur_y ,
- app.m_specific.m_input_flags );
-
- result:=CallNextEventHandler(nextHandler ,theEvent );
-
-end;
-
-{ DOMOUSEUP }
-function DoMouseUp(nextHandler : EventHandlerCallRef; theEvent : EventRef; userData : pointer ) : OSStatus;
-var
- wheresMyMouse : Carbon.Point;
-
- modifier : UInt32;
- button : EventMouseButton;
-
- sz : UInt32;
- app : platform_support_ptr;
- ept : EventParamType;
-
-begin
- ept:=0;
-
- GetEventParameter(
- theEvent ,
- LongWord(int32_ptr(@kEventParamMouseLocation[1 ] )^ ) ,
- LongWord(int32_ptr(@typeQDPoint[1 ] )^ ) ,
- ept ,
- sizeof(Carbon.Point ) ,
- sz ,
- @wheresMyMouse );
-
- GlobalToLocal(wheresMyMouse );
-
- GetEventParameter(
- theEvent ,
- LongWord(int32_ptr(@kEventParamKeyModifiers[1 ] )^ ) ,
- LongWord(int32_ptr(@typeUInt32[1 ] )^ ) ,
- ept ,
- sizeof(UInt32 ) ,
- sz ,
- @modifier );
-
- app:=platform_support_ptr(userData );
-
- app.m_specific.m_cur_x:=wheresMyMouse.h;
-
- if app._flip_y then
- app.m_specific.m_cur_y:=app.rbuf_window._height - wheresMyMouse.v
- else
- app.m_specific.m_cur_y:=wheresMyMouse.v;
-
- GetEventParameter(
- theEvent ,
- LongWord(int32_ptr(@kEventParamMouseButton[1 ] )^ ) ,
- LongWord(int32_ptr(@typeMouseButton[1 ] )^ ) ,
- ept ,
- sizeof(EventMouseButton ) ,
- sz ,
- @button );
-
- case button of
- kEventMouseButtonSecondary :
- app.m_specific.m_input_flags:=mouse_right or get_key_flags(modifier );
-
- else
- app.m_specific.m_input_flags:=mouse_left or get_key_flags(modifier );
-
- end;
-
- if app.m_ctrls.on_mouse_button_up(
- app.m_specific.m_cur_x ,
- app.m_specific.m_cur_y ) then
- begin
- app.on_ctrl_change;
- app.force_redraw;
-
- end;
-
- app.on_mouse_button_up(
- app.m_specific.m_cur_x ,
- app.m_specific.m_cur_y ,
- app.m_specific.m_input_flags );
-
- result:=CallNextEventHandler(nextHandler ,theEvent );
-
-end;
-
-{ DOMOUSEDRAGGED }
-function DoMouseDragged(nextHandler : EventHandlerCallRef; theEvent : EventRef; userData : pointer ) : OSStatus;
-var
- wheresMyMouse : Carbon.Point;
-
- modifier : UInt32;
- button : EventMouseButton;
-
- sz : UInt32;
- app : platform_support_ptr;
- ept : EventParamType;
-
-begin
- ept:=0;
-
- GetEventParameter(
- theEvent ,
- LongWord(int32_ptr(@kEventParamMouseLocation[1 ] )^ ) ,
- LongWord(int32_ptr(@typeQDPoint[1 ] )^ ) ,
- ept ,
- sizeof(Carbon.Point ) ,
- sz ,
- @wheresMyMouse );
-
- GlobalToLocal(wheresMyMouse );
- GetEventParameter(
- theEvent ,
- LongWord(int32_ptr(@kEventParamKeyModifiers[1 ] )^ ) ,
- LongWord(int32_ptr(@typeUInt32[1 ] )^ ) ,
- ept ,
- sizeof(UInt32 ) ,
- sz ,
- @modifier );
-
- app:=platform_support_ptr(userData );
-
- app.m_specific.m_cur_x:=wheresMyMouse.h;
-
- if app._flip_y then
- app.m_specific.m_cur_y:=app.rbuf_window._height - wheresMyMouse.v
- else
- app.m_specific.m_cur_y:=wheresMyMouse.v;
-
- GetEventParameter(
- theEvent ,
- LongWord(int32_ptr(@kEventParamMouseButton[1 ] )^ ) ,
- LongWord(int32_ptr(@typeMouseButton[1 ] )^ ) ,
- ept ,
- sizeof(EventMouseButton ) ,
- sz ,
- @button );
-
- case button of
- kEventMouseButtonSecondary :
- app.m_specific.m_input_flags:=mouse_right or get_key_flags(modifier );
-
- else
- app.m_specific.m_input_flags:=mouse_left or get_key_flags(modifier );
-
- end;
-
- if app.m_ctrls.on_mouse_move(
- app.m_specific.m_cur_x ,
- app.m_specific.m_cur_y ,
- app.m_specific.m_input_flags and mouse_left <> 0 ) then
- begin
- app.on_ctrl_change;
- app.force_redraw;
-
- end
- else
- app.on_mouse_move(
- app.m_specific.m_cur_x ,
- app.m_specific.m_cur_y ,
- app.m_specific.m_input_flags );
-
- result:=CallNextEventHandler(nextHandler ,theEvent );
-
-end;
-
-{ DOKEYDOWN }
-function DoKeyDown(nextHandler : EventHandlerCallRef; theEvent : EventRef; userData : pointer ) : OSStatus;
-var
- key_char : byte;
- key_code ,
- modifier : UInt32;
-
- sz : UInt32;
- app : platform_support_ptr;
- ept : EventParamType;
-
- left ,up ,right ,down : boolean;
-
-begin
- ept:=0;
-
- GetEventParameter(
- theEvent ,
- LongWord(int32_ptr(@kEventParamKeyMacCharCodes[1 ] )^ ) ,
- LongWord(int32_ptr(@typeChar[1 ] )^ ) ,
- ept ,
- sizeof(byte ) ,
- sz ,
- @key_char );
-
- GetEventParameter(
- theEvent ,
- LongWord(int32_ptr(@kEventParamKeyCode[1 ] )^ ) ,
- LongWord(int32_ptr(@typeUInt32[1 ] )^ ) ,
- ept ,
- sizeof(UInt32 ) ,
- sz ,
- @key_code );
-
- GetEventParameter(
- theEvent ,
- LongWord(int32_ptr(@kEventParamKeyModifiers[1 ] )^ ) ,
- LongWord(int32_ptr(@typeUInt32[1 ] )^ ) ,
- ept ,
- sizeof(UInt32 ) ,
- sz ,
- @modifier );
-
- app:=platform_support_ptr(userData );
-
- app.m_specific.m_last_translated_key:=0;
-
- case modifier of
- controlKey :
- app.m_specific.m_input_flags:=
- app.m_specific.m_input_flags or kbd_ctrl;
-
- shiftKey :
- app.m_specific.m_input_flags:=
- app.m_specific.m_input_flags or kbd_shift;
-
- else
- app.m_specific.translate(key_char );
-
- end;
-
- case key_char of
- kFunctionKeyCharCode :
- case key_code of
- 122 : app.m_specific.m_last_translated_key:=key_f1;
- 120 : app.m_specific.m_last_translated_key:=key_f2;
- 99 : app.m_specific.m_last_translated_key:=key_f3;
- 118 : app.m_specific.m_last_translated_key:=key_f4;
- 96 : app.m_specific.m_last_translated_key:=key_f5;
- 97 : app.m_specific.m_last_translated_key:=key_f6;
- 98 : app.m_specific.m_last_translated_key:=key_f7;
- 100 : app.m_specific.m_last_translated_key:=key_f8;
-
- end;
-
- end;
-
- if (app.m_specific.m_last_translated_key = 0 ) and
- (key_char > 31 ) then
- app.m_specific.m_last_translated_key:=key_char;
-
- if app.m_specific.m_last_translated_key <> 0 then
- begin
- left :=false;
- up :=false;
- right:=false;
- down :=false;
-
- case app.m_specific.m_last_translated_key of
- key_left : left :=true;
- key_up : up :=true;
- key_right : right:=true;
- key_down : down :=true;
-
- //On a Mac, screenshots are handled by the system.
- key_f2 :
- begin
- app.copy_window_to_img(max_images - 1 );
- app.save_img (max_images - 1 ,'screenshot.png' );
-
- end;
-
- key_f4 :
- if modifier = optionKey then
- app.quit;
-
- end;
-
- if app.m_ctrls.on_arrow_keys(left ,right ,down ,up ) then
- begin
- app.on_ctrl_change;
- app.force_redraw;
-
- end
- else
- app.on_key(
- app.m_specific.m_cur_x ,
- app.m_specific.m_cur_y ,
- app.m_specific.m_last_translated_key ,
- app.m_specific.m_input_flags );
-
- end;
-
- result:=CallNextEventHandler(nextHandler ,theEvent );
-
-end;
-
-{ DOKEYUP }
-function DoKeyUp(nextHandler : EventHandlerCallRef; theEvent : EventRef; userData : pointer ) : OSStatus;
-var
- key_code : byte;
- modifier : UInt32;
-
- sz : UInt32;
- app : platform_support_ptr;
- ept : EventParamType;
-
-begin
- ept:=0;
-
- GetEventParameter(
- theEvent ,
- LongWord(int32_ptr(@kEventParamKeyMacCharCodes[1 ] )^ ) ,
- LongWord(int32_ptr(@typeChar[1 ] )^ ) ,
- ept ,
- sizeof(byte ) ,
- sz ,
- @key_code );
-
- GetEventParameter(
- theEvent ,
- LongWord(int32_ptr(@kEventParamKeyModifiers[1 ] )^ ) ,
- LongWord(int32_ptr(@typeUInt32[1 ] )^ ) ,
- ept ,
- sizeof(UInt32 ) ,
- sz ,
- @modifier );
-
- app:=platform_support_ptr(userData );
-
- app.m_specific.m_last_translated_key:=0;
-
- case modifier of
- controlKey :
- app.m_specific.m_input_flags:=
- app.m_specific.m_input_flags and not kbd_ctrl;
-
- shiftKey :
- app.m_specific.m_input_flags:=
- app.m_specific.m_input_flags and not kbd_shift;
-
- end;
-
- result:=CallNextEventHandler(nextHandler ,theEvent );
-
-end;
-
-{ DOPERIODICTASK }
-procedure DoPeriodicTask(theTimer : EventLoopTimerRef; userData : pointer );
-var
- app : platform_support_ptr;
-
-begin
- app:=platform_support_ptr(userData );
-
- if not app._wait_mode then
- app.on_idle;
-
-end;
-
-{ INIT }
-function platform_support.init;
-var
- eventType : EventTypeSpec;
- handlerUPP : EventHandlerUPP;
- theTarget : CFStringRef;
- windowAttrs : WindowAttributes;
- bounds : Carbon.Rect;
- mainLoop : EventLoopRef;
- timerUPP : EventLoopTimerUPP;
- theTimer : EventLoopTimerRef;
-
-begin
- if m_specific.m_sys_format = pix_format_undefined then
- begin
- result:=false;
-
- exit;
-
- end;
-
- m_window_flags:=flags;
-
-// application
- theTarget:=GetApplicationEventTarget;
-
- eventType.eventClass:=LongWord(int32_ptr(@kEventClassApplication[1 ] )^ );
- eventType.eventKind :=kEventAppQuit;
-
- handlerUPP:=NewEventHandlerUPP(@DoAppQuit );
-
- InstallEventHandler(theTarget ,handlerUPP ,1 ,eventType ,NIL ,NIL );
-
-
- eventType.eventClass:=LongWord(int32_ptr(@kEventClassMouse[1 ] )^ );
- eventType.eventKind :=kEventMouseDown;
-
- handlerUPP:=NewEventHandlerUPP(@DoMouseDown );
-
- InstallEventHandler(theTarget ,handlerUPP ,1 ,eventType ,@self ,NIL );
-
-
- eventType.eventKind:=kEventMouseUp;
-
- handlerUPP:=NewEventHandlerUPP(@DoMouseUp );
-
- InstallEventHandler(theTarget ,handlerUPP ,1 ,eventType ,@self ,NIL );
-
-
- eventType.eventKind:=kEventMouseDragged;
-
- handlerUPP:=NewEventHandlerUPP(@DoMouseDragged );
-
- InstallEventHandler(theTarget ,handlerUPP ,1 ,eventType ,@self ,NIL );
-
-
- eventType.eventClass:=LongWord(int32_ptr(@kEventClassKeyboard[1 ] )^ );
- eventType.eventKind :=kEventRawKeyDown;
-
- handlerUPP:=NewEventHandlerUPP(@DoKeyDown );
-
- InstallEventHandler(theTarget ,handlerUPP ,1 ,eventType ,@self ,NIL );
-
-
- eventType.eventKind:=kEventRawKeyUp;
-
- handlerUPP:=NewEventHandlerUPP(@DoKeyUp );
-
- InstallEventHandler(theTarget ,handlerUPP ,1 ,eventType ,@self ,NIL );
-
-
- eventType.eventKind:=kEventRawKeyRepeat;
-
- handlerUPP:=NewEventHandlerUPP(@DoKeyDown ); // 'key repeat' is translated to 'key down'
-
- InstallEventHandler(theTarget ,handlerUPP ,1 ,eventType ,@self ,NIL );
-
-// window
- windowAttrs:=kWindowCloseBoxAttribute or kWindowCollapseBoxAttribute or kWindowStandardHandlerAttribute;
-
- if flags and window_resize <> 0 then
- windowAttrs:=
- windowAttrs or
- kWindowResizableAttribute or
- kWindowFullZoomAttribute or
- kWindowLiveResizeAttribute;
-
- SetRect (bounds ,0 ,0 ,width_ ,height_ );
- OffsetRect(bounds ,100 ,100 );
-
- CreateNewWindow(
- kDocumentWindowClass ,
- windowAttrs ,
- bounds ,
- m_specific.m_window );
-
- if m_specific.m_window = NIL then
- begin
- result:=false;
-
- exit;
-
- end;
-
-// I assume the text is ASCII.
-// Change to kCFStringEncodingMacRoman, kCFStringEncodingISOLatin1, kCFStringEncodingUTF8 or what else you need.
- SetWindowTitleWithCFString(
- m_specific.m_window ,
- CFStringCreateWithPascalStringNoCopy(
- NIL ,m_caption ,kCFStringEncodingASCII ,NIL ) );
-
- theTarget:=GetWindowEventTarget(m_specific.m_window );
-
- eventType.eventClass:=LongWord(int32_ptr(@kEventClassWindow[1 ] )^ );
- eventType.eventKind :=kEventWindowClose;
-
- handlerUPP:=NewEventHandlerUPP(@DoWindowClose );
-
- InstallEventHandler(theTarget ,handlerUPP ,1 ,eventType ,@self ,NIL );
-
-
- eventType.eventKind:=kEventWindowDrawContent;
-
- handlerUPP:=NewEventHandlerUPP(@DoWindowDrawContent );
-
- InstallEventHandler(theTarget ,handlerUPP ,1 ,eventType ,@self ,NIL );
-
-
- eventType.eventKind:=kEventWindowBoundsChanged;
-
- handlerUPP:=NewEventHandlerUPP(@DoWindowResize );
-
- InstallEventHandler(theTarget ,handlerUPP ,1 ,eventType ,@self ,NIL );
-
-// Periodic task
-// Instead of an idle function I use the Carbon event timer.
-// You may decide to change the wait value which is currently 50 milliseconds.
- mainLoop:=GetMainEventLoop;
- timerUPP:=NewEventLoopTimerUPP(@DoPeriodicTask );
-
- InstallEventLoopTimer(mainLoop ,0 ,50 * kEventDurationMillisecond ,timerUPP ,@self ,theTimer );
-
- m_specific.create_pmap(width_ ,height_ ,@m_rbuf_window );
-
- m_initial_width :=width_;
- m_initial_height:=height_;
-
- on_init;
- on_resize(width_ ,height_ );
-
- m_specific.m_redraw_flag:=true;
-
- ShowWindow (m_specific.m_window );
- SetPortWindowPort(m_specific.m_window );
-
- result:=true;
-
-end;
-
-{ RUN }
-function platform_support.run;
-begin
- RunApplicationEventLoop;
-
- result:=1;
-
-end;
-
-{ QUIT }
-procedure platform_support.quit;
-begin
- QuitApplicationEventLoop;
-
-end;
-
-{ _FORMAT }
-function platform_support._format;
-begin
- result:=m_format;
-
-end;
-
-{ _FLIP_Y }
-function platform_support._flip_y;
-begin
- result:=m_flip_y;
-
-end;
-
-{ _BPP }
-function platform_support._bpp;
-begin
- result:=m_bpp;
-
-end;
-
-{ _WAIT_MODE }
-function platform_support._wait_mode;
-begin
- result:=m_wait_mode;
-
-end;
-
-{ WAIT_MODE_ }
-procedure platform_support.wait_mode_;
-begin
- m_wait_mode:=wait_mode;
-
-end;
-
-{ FORCE_REDRAW }
-procedure platform_support.force_redraw;
-var
- bounds : Carbon.Rect;
-
-begin
- m_specific.m_redraw_flag:=true;
-
-// on_ctrl_change
- on_draw;
-
- SetRect (bounds ,0 ,0 ,m_rbuf_window._width ,m_rbuf_window._height );
- InvalWindowRect(m_specific.m_window ,bounds );
-
-end;
-
-{ UPDATE_WINDOW }
-procedure platform_support.update_window;
-begin
- m_specific.display_pmap(m_specific.m_window ,@m_rbuf_window );
-
-end;
-
-{ RBUF_WINDOW }
-function platform_support.rbuf_window;
-begin
- result:=@m_rbuf_window;
-
-end;
-
-{ RBUF_IMG }
-function platform_support.rbuf_img;
-begin
- result:=@m_rbuf_img[idx ];
-
-end;
-
-{ _IMG_EXT }
-function platform_support._img_ext;
-begin
- result:='.bmp';
-
-end;
-
-{ COPY_IMG_TO_WINDOW }
-procedure platform_support.copy_img_to_window;
-begin
- if (idx < max_images ) and
- (rbuf_img(idx )._buf <> NIL ) then
- rbuf_window.copy_from(rbuf_img(idx ) );
-
-end;
-
-{ COPY_WINDOW_TO_IMG }
-procedure platform_support.copy_window_to_img;
-begin
- if idx < max_images then
- begin
- create_img(idx ,rbuf_window._width ,rbuf_window._height );
- rbuf_img (idx ).copy_from(rbuf_window );
-
- end;
-
-end;
-
-{ COPY_IMG_TO_IMG }
-procedure platform_support.copy_img_to_img;
-begin
- if (idx_from < max_images ) and
- (idx_to < max_images ) and
- (rbuf_img(idx_from )._buf <> NIL ) then
- begin
- create_img(
- idx_to ,
- rbuf_img(idx_from )._width ,
- rbuf_img(idx_from )._height );
-
- rbuf_img(idx_to ).copy_from(rbuf_img(idx_from ) );
-
- end;
-
-end;
-
-{ ON_INIT }
-procedure platform_support.on_init;
-begin
-end;
-
-{ ON_RESIZE }
-procedure platform_support.on_resize;
-begin
-end;
-
-{ ON_IDLE }
-procedure platform_support.on_idle;
-begin
-end;
-
-{ ON_MOUSE_MOVE }
-procedure platform_support.on_mouse_move;
-begin
-end;
-
-{ ON_MOUSE_BUTTON_DOWN }
-procedure platform_support.on_mouse_button_down;
-begin
-end;
-
-{ ON_MOUSE_BUTTON_UP }
-procedure platform_support.on_mouse_button_up;
-begin
-end;
-
-{ ON_KEY }
-procedure platform_support.on_key;
-begin
-end;
-
-{ ON_CTRL_CHANGE }
-procedure platform_support.on_ctrl_change;
-begin
-end;
-
-{ ON_DRAW }
-procedure platform_support.on_draw;
-begin
-end;
-
-{ ON_POST_DRAW }
-procedure platform_support.on_post_draw;
-begin
-end;
-
-{ ADD_CTRL }
-procedure platform_support.add_ctrl;
-begin
- m_ctrls.add(c );
-
- c.transform(@m_resize_mtx );
-
-end;
-
-{ TRANS_AFFINE_RESIZING_ }
-procedure platform_support.trans_affine_resizing_;
-var
- vp : trans_viewport;
- ts : trans_affine_scaling;
-
-begin
- if m_window_flags and window_keep_aspect_ratio <> 0 then
- begin
- //double sx = double(width) / double(m_initial_width);
- //double sy = double(height) / double(m_initial_height);
- //if(sy < sx) sx = sy;
- //m_resize_mtx = trans_affine_scaling(sx, sx);
-
- vp.Construct;
- vp.preserve_aspect_ratio(0.5 ,0.5 ,aspect_ratio_meet );
-
- vp.device_viewport(0 ,0 ,width_ ,height_ );
- vp.world_viewport (0 ,0 ,m_initial_width ,m_initial_height );
-
- vp.to_affine(@m_resize_mtx );
-
- end
- else
- begin
- ts.Construct(
- width_ / m_initial_width ,
- height_ / m_initial_height );
-
- m_resize_mtx.assign(@ts );
-
- end;
-
-end;
-
-{ _TRANS_AFFINE_RESIZING }
-function platform_support._trans_affine_resizing;
-begin
- result:=@m_resize_mtx;
-
-end;
-
-{ _WIDTH }
-function platform_support._width;
-begin
- result:=m_rbuf_window._width;
-
-end;
-
-{ _HEIGHT }
-function platform_support._height;
-begin
- result:=m_rbuf_window._height;
-
-end;
-
-{ _INITIAL_WIDTH }
-function platform_support._initial_width;
-begin
- result:=m_initial_width;
-
-end;
-
-{ _INITIAL_HEIGHT }
-function platform_support._initial_height;
-begin
- result:=m_initial_height;
-
-end;
-
-{ _WINDOW_FLAGS }
-function platform_support._window_flags;
-begin
- result:=m_window_flags;
-
-end;
-
-{ _RAW_DISPLAY_HANDLER }
-function platform_support._raw_display_handler;
-begin
-end;
-
-{ MESSAGE_ }
-procedure platform_support.message_;
-var
- dlg : DialogRef;
- itm : DialogItemIndex;
-
-begin
- CreateStandardAlert(
- kAlertPlainAlert ,
- CFStringCreateWithCStringNoCopy(
- NIL ,'AGG Message' ,kCFStringEncodingASCII ,NIL ) ,
- CFStringCreateWithCStringNoCopy(
- NIL ,msg ,kCFStringEncodingASCII ,NIL ) ,
- NIL ,
- dlg );
-
- RunStandardAlert(dlg ,NIL ,itm );
-
-end;
-
-{ START_TIMER }
-procedure platform_support.start_timer;
-begin
- Microseconds(m_specific.m_sw_start );
-
-end;
-
-{ ELAPSED_TIME }
-function platform_support.elapsed_time;
-var
- stop : UnsignedWide;
-
-begin
- Microseconds(stop );
-
- result:=
- (stop.lo - m_specific.m_sw_start.lo) * 1e6 /
- m_specific.m_sw_freq.lo;
-
-end;
-
-{ FULL_FILE_NAME }
-function platform_support.full_file_name;
-begin
- result:=file_name;
-
-end;
-
-{ FILE_SOURCE }
-function platform_support.file_source;
-begin
- result:=fname;
-
-end;
-
-END.
-
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+// Copyright (C) 2003 Hansruedi Baer (MacOS support)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+// baer@karto.baug.eth.ch
+//
+//----------------------------------------------------------------------------
+//
+// Note:
+// I tried to retain the original structure for the Win32 platform as far
+// as possible. Currently, not all features are implemented but the examples
+// should work properly.
+// HB
+//
+//----------------------------------------------------------------------------
+//
+// class platform_support
+//
+// It's not a part of the AGG library, it's just a helper class to create
+// interactive demo examples. Since the examples should not be too complex
+// this class is provided to support some very basic interactive graphical
+// funtionality, such as putting the rendered image to the window, simple
+// keyboard and mouse input, window resizing, setting the window title,
+// and catching the "idle" events.
+//
+// The most popular platforms are:
+//
+// Windows-32 API
+// X-Window API
+// SDL library (see http://www.libsdl.org/)
+// MacOS C/C++ API
+//
+// All the system dependent stuff sits in the platform_specific class.
+// The platform_support class has just a pointer to it and it's
+// the responsibility of the implementation to create/delete it.
+// This class being defined in the implementation file can have
+// any platform dependent stuff such as HWND, X11 Window and so on.
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 26.03.2006-Milano: Finished & tested MacOS X port
+// 20.03.2006-Milano: Unit port establishment
+//
+{ agg_platform_support.pas }
+unit
+ agg_platform_support ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ Carbon ,
+ agg_basics ,
+ agg_ctrl ,
+ agg_rendering_buffer ,
+ agg_trans_affine ,
+ agg_trans_viewport ,
+ agg_mac_pmap ,
+ agg_color_conv ;
+
+{ TYPES DEFINITION }
+const
+//----------------------------------------------------------window_flag_e
+// These are flags used in method init(). Not all of them are
+// applicable on different platforms, for example the win32_api
+// cannot use a hardware buffer (window_hw_buffer).
+// The implementation should simply ignore unsupported flags.
+ window_resize = 1;
+ window_hw_buffer = 2;
+ window_keep_aspect_ratio = 4;
+ window_process_all_keys = 8;
+
+type
+//-----------------------------------------------------------pix_format_e
+// Possible formats of the rendering buffer. Initially I thought that it's
+// reasonable to create the buffer and the rendering functions in
+// accordance with the native pixel format of the system because it
+// would have no overhead for pixel format conersion.
+// But eventually I came to a conclusion that having a possibility to
+// convert pixel formats on demand is a good idea. First, it was X11 where
+// there lots of different formats and visuals and it would be great to
+// render everything in, say, RGB-24 and display it automatically without
+// any additional efforts. The second reason is to have a possibility to
+// debug renderers for different pixel formats and colorspaces having only
+// one computer and one system.
+//
+// This stuff is not included into the basic AGG functionality because the
+// number of supported pixel formats (and/or colorspaces) can be great and
+// if one needs to add new format it would be good only to add new
+// rendering files without having to modify any existing ones (a general
+// principle of incapsulation and isolation).
+//
+// Using a particular pixel format doesn't obligatory mean the necessity
+// of software conversion. For example, win32 API can natively display
+// gray8, 15-bit RGB, 24-bit BGR, and 32-bit BGRA formats.
+// This list can be (and will be!) extended in future.
+ pix_format_e = (
+
+ pix_format_undefined , // By default. No conversions are applied
+ pix_format_bw, // 1 bit per color B/W
+ pix_format_gray8, // Simple 256 level grayscale
+ pix_format_gray16, // Simple 65535 level grayscale
+ pix_format_rgb555, // 15 bit rgb. Depends on the byte ordering!
+ pix_format_rgb565, // 16 bit rgb. Depends on the byte ordering!
+ pix_format_rgbAAA, // 30 bit rgb. Depends on the byte ordering!
+ pix_format_rgbBBA, // 32 bit rgb. Depends on the byte ordering!
+ pix_format_bgrAAA, // 30 bit bgr. Depends on the byte ordering!
+ pix_format_bgrABB, // 32 bit bgr. Depends on the byte ordering!
+ pix_format_rgb24, // R-G-B, one byte per color component
+ pix_format_bgr24, // B-G-R, native win32 BMP format.
+ pix_format_rgba32, // R-G-B-A, one byte per color component
+ pix_format_argb32, // A-R-G-B, native MAC format
+ pix_format_abgr32, // A-B-G-R, one byte per color component
+ pix_format_bgra32, // B-G-R-A, native win32 BMP format
+ pix_format_rgb48, // R-G-B, 16 bits per color component
+ pix_format_bgr48, // B-G-R, native win32 BMP format.
+ pix_format_rgba64, // R-G-B-A, 16 bits byte per color component
+ pix_format_argb64, // A-R-G-B, native MAC format
+ pix_format_abgr64, // A-B-G-R, one byte per color component
+ pix_format_bgra64, // B-G-R-A, native win32 BMP format
+
+ end_of_pix_formats );
+
+const
+//-------------------------------------------------------------input_flag_e
+// Mouse and keyboard flags. They can be different on different platforms
+// and the ways they are obtained are also different. But in any case
+// the system dependent flags should be mapped into these ones. The meaning
+// of that is as follows. For example, if kbd_ctrl is set it means that the
+// ctrl key is pressed and being held at the moment. They are also used in
+// the overridden methods such as on_mouse_move(), on_mouse_button_down(),
+// on_mouse_button_dbl_click(), on_mouse_button_up(), on_key().
+// In the method on_mouse_button_up() the mouse flags have different
+// meaning. They mean that the respective button is being released, but
+// the meaning of the keyboard flags remains the same.
+// There's absolut minimal set of flags is used because they'll be most
+// probably supported on different platforms. Even the mouse_right flag
+// is restricted because Mac's mice have only one button, but AFAIK
+// it can be simulated with holding a special key on the keydoard.
+ mouse_left = 1;
+ mouse_right = 2;
+ kbd_shift = 4;
+ kbd_ctrl = 8;
+
+//--------------------------------------------------------------key_code_e
+// Keyboard codes. There's also a restricted set of codes that are most
+// probably supported on different platforms. Any platform dependent codes
+// should be converted into these ones. There're only those codes are
+// defined that cannot be represented as printable ASCII-characters.
+// All printable ASCII-set can be used in a regilar C/C++ manner:
+// ' ', 'A', '0' '+' and so on.
+// Since the clasas is used for creating very simple demo-applications
+// we don't need very rich possibilities here, just basic ones.
+// Actually the numeric key codes are taken from the SDL library, so,
+// the implementation of the SDL support does not require any mapping.
+// ASCII set. Should be supported everywhere
+ key_backspace = 8;
+ key_tab = 9;
+ key_clear = 12;
+ key_return = 13;
+ key_pause = 19;
+ key_escape = 27;
+
+// Keypad
+ key_delete = 127;
+ key_kp0 = 256;
+ key_kp1 = 257;
+ key_kp2 = 258;
+ key_kp3 = 259;
+ key_kp4 = 260;
+ key_kp5 = 261;
+ key_kp6 = 262;
+ key_kp7 = 263;
+ key_kp8 = 264;
+ key_kp9 = 265;
+ key_kp_period = 266;
+ key_kp_divide = 267;
+ key_kp_multiply = 268;
+ key_kp_minus = 269;
+ key_kp_plus = 270;
+ key_kp_enter = 271;
+ key_kp_equals = 272;
+
+// Arrow-keys and stuff
+ key_up = 273;
+ key_down = 274;
+ key_right = 275;
+ key_left = 276;
+ key_insert = 277;
+ key_home = 278;
+ key_end = 279;
+ key_page_up = 280;
+ key_page_down = 281;
+
+// Functional keys. You'd better avoid using
+// f11...f15 in your applications if you want
+// the applications to be portable
+ key_f1 = 282;
+ key_f2 = 283;
+ key_f3 = 284;
+ key_f4 = 285;
+ key_f5 = 286;
+ key_f6 = 287;
+ key_f7 = 288;
+ key_f8 = 289;
+ key_f9 = 290;
+ key_f10 = 291;
+ key_f11 = 292;
+ key_f12 = 293;
+ key_f13 = 294;
+ key_f14 = 295;
+ key_f15 = 296;
+
+// The possibility of using these keys is
+// very restricted. Actually it's guaranteed
+// only in win32_api and win32_sdl implementations
+ key_numlock = 300;
+ key_capslock = 301;
+ key_scrollock = 302;
+
+ max_ctrl = 128;
+
+type
+//----------------------------------------------------------ctrl_container
+// A helper class that contains pointers to a number of controls.
+// This class is used to ease the event handling with controls.
+// The implementation should simply call the appropriate methods
+// of this class when appropriate events occure.
+ crtl_container_ptr = ^ctrl_container;
+ ctrl_container = object
+ m_ctrl : array[0..max_ctrl - 1 ] of ctrl_ptr;
+
+ m_num_ctrl : unsigned;
+ m_cur_ctrl : int;
+
+ constructor Construct;
+ destructor Destruct;
+
+ procedure add(c : ctrl_ptr );
+
+ function in_rect(x ,y : double ) : boolean;
+
+ function on_mouse_button_down(x ,y : double ) : boolean;
+ function on_mouse_button_up (x ,y : double ) : boolean;
+
+ function on_mouse_move(x ,y : double; button_flag : boolean ) : boolean;
+ function on_arrow_keys(left ,right ,down ,up : boolean ) : boolean;
+
+ function set_cur(x ,y : double ) : boolean;
+
+ end;
+
+//---------------------------------------------------------platform_support
+// This class is a base one to the apllication classes. It can be used
+// as follows:
+//
+// the_application = object(platform_support )
+//
+// constructor Construct(bpp : unsigned; flip_y : boolean );
+// . . .
+//
+// //override stuff . . .
+// procedure on_init; virtual;
+// procedure on_draw; virtual;
+// procedure on_resize(sx ,sy : int ); virtual;
+// // . . . and so on, see virtual functions
+//
+// //any your own stuff . . .
+// };
+//
+// VAR
+// app : the_application;
+//
+// BEGIN
+// app.Construct(pix_format_rgb24 ,true );
+// app.caption ("AGG Example. Lion" );
+//
+// if app.init(500 ,400 ,window_resize ) then
+// app.run;
+//
+// app.Destruct;
+//
+// END.
+//
+const
+ max_images = 16;
+
+type
+ platform_specific_ptr = ^platform_specific;
+ platform_specific = object
+ m_format ,
+ m_sys_format : pix_format_e;
+
+ m_flip_y : boolean;
+ m_bpp ,
+ m_sys_bpp : unsigned;
+ m_window : WindowRef;
+
+ m_pmap_window : pixel_map;
+ m_pmap_img : array[0..max_images - 1 ] of pixel_map;
+
+ m_keymap : array[0..255 ] of unsigned;
+
+ m_last_translated_key : unsigned;
+
+ m_cur_x ,
+ m_cur_y : int;
+
+ m_input_flags : unsigned;
+ m_redraw_flag : boolean;
+
+ m_sw_freq ,
+ m_sw_start : UnsignedWide;
+
+ constructor Construct(format : pix_format_e; flip_y : boolean );
+ destructor Destruct;
+
+ procedure create_pmap (width ,height : unsigned; wnd : rendering_buffer_ptr );
+ procedure display_pmap(window : WindowRef; src : rendering_buffer_ptr );
+
+ function load_pmap(fn : shortstring; idx : unsigned; dst : rendering_buffer_ptr ) : boolean;
+ function save_pmap(fn : shortstring; idx : unsigned; src : rendering_buffer_ptr ) : boolean;
+
+ function translate(keycode : unsigned ) : unsigned;
+
+ end;
+
+ platform_support_ptr = ^platform_support;
+ platform_support = object
+ m_specific : platform_specific_ptr;
+ m_ctrls : ctrl_container;
+
+ m_format : pix_format_e;
+
+ m_bpp : unsigned;
+
+ m_rbuf_window : rendering_buffer;
+ m_rbuf_img : array[0..max_images - 1 ] of rendering_buffer;
+
+ m_window_flags : unsigned;
+ m_wait_mode ,
+ m_flip_y : boolean; // flip_y - true if you want to have the Y-axis flipped vertically
+ m_caption : shortstring;
+ m_resize_mtx : trans_affine;
+
+ m_initial_width ,
+ m_initial_height : int;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
+ destructor Destruct;
+
+ // Setting the windows caption (title). Should be able
+ // to be called at least before calling init().
+ // It's perfect if they can be called anytime.
+ procedure caption_(cap : shortstring );
+
+ // These 3 menthods handle working with images. The image
+ // formats are the simplest ones, such as .BMP in Windows or
+ // .ppm in Linux. In the applications the names of the files
+ // should not have any file extensions. Method load_img() can
+ // be called before init(), so, the application could be able
+ // to determine the initial size of the window depending on
+ // the size of the loaded image.
+ // The argument "idx" is the number of the image 0...max_images-1
+ function load_img (idx : unsigned; file_ : shortstring ) : boolean;
+ function save_img (idx : unsigned; file_ : shortstring ) : boolean;
+ function create_img(idx : unsigned; width_ : unsigned = 0; height_ : unsigned = 0 ) : boolean;
+
+ // init() and run(). See description before the class for details.
+ // The necessity of calling init() after creation is that it's
+ // impossible to call the overridden virtual function (on_init())
+ // from the constructor. On the other hand it's very useful to have
+ // some on_init() event handler when the window is created but
+ // not yet displayed. The rbuf_window() method (see below) is
+ // accessible from on_init().
+ function init(width_ ,height_ ,flags : unsigned ) : boolean;
+ function run : int;
+ procedure quit;
+
+ // The very same parameters that were used in the constructor
+ function _format : pix_format_e;
+ function _flip_y : boolean;
+ function _bpp : unsigned;
+
+ // The following provides a very simple mechanism of doing someting
+ // in background. It's not multitheading. When whait_mode is true
+ // the class waits for the events and it does not ever call on_idle().
+ // When it's false it calls on_idle() when the event queue is empty.
+ // The mode can be changed anytime. This mechanism is satisfactory
+ // for creation very simple animations.
+ function _wait_mode : boolean;
+ procedure wait_mode_(wait_mode : boolean );
+
+ // These two functions control updating of the window.
+ // force_redraw() is an analog of the Win32 InvalidateRect() function.
+ // Being called it sets a flag (or sends a message) which results
+ // in calling on_draw() and updating the content of the window
+ // when the next event cycle comes.
+ // update_window() results in just putting immediately the content
+ // of the currently rendered buffer to the window without calling
+ // on_draw().
+ procedure force_redraw;
+ procedure update_window;
+
+ // So, finally, how to draw anythig with AGG? Very simple.
+ // rbuf_window() returns a reference to the main rendering
+ // buffer which can be attached to any rendering class.
+ // rbuf_img() returns a reference to the previously created
+ // or loaded image buffer (see load_img()). The image buffers
+ // are not displayed directly, they should be copied to or
+ // combined somehow with the rbuf_window(). rbuf_window() is
+ // the only buffer that can be actually displayed.
+ function rbuf_window : rendering_buffer_ptr;
+ function rbuf_img(idx : unsigned ) : rendering_buffer_ptr;
+
+ // Returns file extension used in the implemenation for the particular
+ // system.
+ function _img_ext : shortstring;
+
+ //
+ procedure copy_img_to_window(idx : unsigned );
+ procedure copy_window_to_img(idx : unsigned );
+ procedure copy_img_to_img (idx_to ,idx_from : unsigned );
+
+ // Event handlers. They are not pure functions, so you don't have
+ // to override them all.
+ // In my demo applications these functions are defined inside
+ // the the_application class
+ procedure on_init; virtual;
+ procedure on_resize(sx ,sy : int ); virtual;
+ procedure on_idle; virtual;
+
+ procedure on_mouse_move(x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_up (x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+ procedure on_ctrl_change; virtual;
+ procedure on_draw; virtual;
+ procedure on_post_draw(raw_handler : pointer ); virtual;
+
+ // Adding control elements. A control element once added will be
+ // working and reacting to the mouse and keyboard events. Still, you
+ // will have to render them in the on_draw() using function
+ // render_ctrl() because platform_support doesn't know anything about
+ // renderers you use. The controls will be also scaled automatically
+ // if they provide a proper scaling mechanism (all the controls
+ // included into the basic AGG package do).
+ // If you don't need a particular control to be scaled automatically
+ // call ctrl::no_transform() after adding.
+ procedure add_ctrl(c : ctrl_ptr );
+
+ // Auxiliary functions. trans_affine_resizing() modifier sets up the resizing
+ // matrix on the basis of the given width and height and the initial
+ // width and height of the window. The implementation should simply
+ // call this function every time when it catches the resizing event
+ // passing in the new values of width and height of the window.
+ // Nothing prevents you from "cheating" the scaling matrix if you
+ // call this function from somewhere with wrong arguments.
+ // trans_affine_resizing() accessor simply returns current resizing matrix
+ // which can be used to apply additional scaling of any of your
+ // stuff when the window is being resized.
+ // width(), height(), initial_width(), and initial_height() must be
+ // clear to understand with no comments :-)
+ procedure trans_affine_resizing_(width_ ,height_ : int );
+ function _trans_affine_resizing : trans_affine_ptr;
+
+ function _width : double;
+ function _height : double;
+ function _initial_width : double;
+ function _initial_height : double;
+ function _window_flags : unsigned;
+
+ // Get raw display handler depending on the system.
+ // For win32 its an HDC, for other systems it can be a pointer to some
+ // structure. See the implementation files for detals.
+ // It's provided "as is", so, first you should check if it's not null.
+ // If it's null the raw_display_handler is not supported. Also, there's
+ // no guarantee that this function is implemented, so, in some
+ // implementations you may have simply an unresolved symbol when linking.
+ function _raw_display_handler : pointer;
+
+ // display message box or print the message to the console
+ // (depending on implementation)
+ procedure message_(msg : PChar );
+
+ // Stopwatch functions. Function elapsed_time() returns time elapsed
+ // since the latest start_timer() invocation in millisecods.
+ // The resolutoin depends on the implementation.
+ // In Win32 it uses QueryPerformanceFrequency() / QueryPerformanceCounter().
+ procedure start_timer;
+ function elapsed_time : double;
+
+ // Get the full file name. In most cases it simply returns
+ // file_name. As it's appropriate in many systems if you open
+ // a file by its name without specifying the path, it tries to
+ // open it in the current directory. The demos usually expect
+ // all the supplementary files to be placed in the current
+ // directory, that is usually coincides with the directory where
+ // the the executable is. However, in some systems (BeOS) it's not so.
+ // For those kinds of systems full_file_name() can help access files
+ // preserving commonly used policy.
+ // So, it's a good idea to use in the demos the following:
+ // FILE* fd = fopen(full_file_name("some.file"), "r");
+ // instead of
+ // FILE* fd = fopen("some.file", "r");
+ function full_file_name(file_name : shortstring ) : shortstring;
+ function file_source (path ,fname : shortstring ) : shortstring;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor ctrl_container.Construct;
+begin
+ m_num_ctrl:=0;
+ m_cur_ctrl:=-1;
+
+end;
+
+{ DESTRUCT }
+destructor ctrl_container.Destruct;
+begin
+end;
+
+{ ADD }
+procedure ctrl_container.add;
+begin
+ if m_num_ctrl < max_ctrl then
+ begin
+ m_ctrl[m_num_ctrl ]:=c;
+
+ inc(m_num_ctrl );
+
+ end;
+
+end;
+
+{ IN_RECT }
+function ctrl_container.in_rect;
+var
+ i : unsigned;
+
+begin
+ result:=false;
+
+ if m_num_ctrl > 0 then
+ for i:=0 to m_num_ctrl - 1 do
+ if m_ctrl[i ].in_rect(x ,y ) then
+ begin
+ result:=true;
+
+ exit;
+
+ end;
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+function ctrl_container.on_mouse_button_down;
+var
+ i : unsigned;
+
+begin
+ result:=false;
+
+ if m_num_ctrl > 0 then
+ for i:=0 to m_num_ctrl - 1 do
+ if m_ctrl[i ].on_mouse_button_down(x ,y ) then
+ begin
+ result:=true;
+
+ exit;
+
+ end;
+
+end;
+
+{ ON_MOUSE_BUTTON_UP }
+function ctrl_container.on_mouse_button_up;
+var
+ i : unsigned;
+
+begin
+ result:=false;
+
+ if m_num_ctrl > 0 then
+ for i:=0 to m_num_ctrl - 1 do
+ if m_ctrl[i ].on_mouse_button_up(x ,y ) then
+ begin
+ result:=true;
+
+ exit;
+
+ end;
+
+end;
+
+{ ON_MOUSE_MOVE }
+function ctrl_container.on_mouse_move;
+var
+ i : unsigned;
+
+begin
+ result:=false;
+
+ if m_num_ctrl > 0 then
+ for i:=0 to m_num_ctrl - 1 do
+ if m_ctrl[i ].on_mouse_move(x ,y ,button_flag ) then
+ begin
+ result:=true;
+
+ exit;
+
+ end;
+
+end;
+
+{ ON_ARROW_KEYS }
+function ctrl_container.on_arrow_keys;
+begin
+ result:=false;
+
+ if m_cur_ctrl >= 0 then
+ result:=m_ctrl[m_cur_ctrl ].on_arrow_keys(left ,right ,down ,up );
+
+end;
+
+{ SET_CUR }
+function ctrl_container.set_cur;
+var
+ i : unsigned;
+
+begin
+ result:=false;
+
+ if m_num_ctrl > 0 then
+ for i:=0 to m_num_ctrl - 1 do
+ if m_ctrl[i ].in_rect(x ,y ) then
+ begin
+ if m_cur_ctrl <> i then
+ begin
+ m_cur_ctrl:=i;
+
+ result:=true;
+
+ end;
+
+ exit;
+
+ end;
+
+ if m_cur_ctrl <> -1 then
+ begin
+ m_cur_ctrl:=-1;
+
+ result:=true;
+
+ end;
+
+end;
+
+{ CONSTRUCT }
+constructor platform_specific.Construct;
+var
+ i : unsigned;
+
+begin
+ m_pmap_window.Construct;
+
+ for i:=0 to max_images - 1 do
+ m_pmap_img[i ].Construct;
+
+ m_format :=format;
+ m_sys_format:=pix_format_undefined;
+
+ m_flip_y :=flip_y;
+ m_bpp :=0;
+ m_sys_bpp:=0;
+ m_window :=NIL;
+
+ m_last_translated_key:=0;
+
+ m_cur_x:=0;
+ m_cur_y:=0;
+
+ m_input_flags:=0;
+ m_redraw_flag:=true;
+
+ fillchar(m_keymap[0 ] ,sizeof(m_keymap ) ,0 );
+
+//Keyboard input is not yet fully supported nor tested
+ //m_keymap[VK_PAUSE ]:=key_pause;
+ m_keymap[kClearCharCode ]:=key_clear;
+
+ //m_keymap[VK_NUMPAD0 ] :=key_kp0;
+ //m_keymap[VK_NUMPAD1 ] :=key_kp1;
+ //m_keymap[VK_NUMPAD2 ] :=key_kp2;
+ //m_keymap[VK_NUMPAD3 ] :=key_kp3;
+ //m_keymap[VK_NUMPAD4 ] :=key_kp4;
+ //m_keymap[VK_NUMPAD5 ] :=key_kp5;
+ //m_keymap[VK_NUMPAD6 ] :=key_kp6;
+ //m_keymap[VK_NUMPAD7 ] :=key_kp7;
+ //m_keymap[VK_NUMPAD8 ] :=key_kp8;
+ //m_keymap[VK_NUMPAD9 ] :=key_kp9;
+ //m_keymap[VK_DECIMAL ] :=key_kp_period;
+ //m_keymap[VK_DIVIDE ] :=key_kp_divide;
+ //m_keymap[VK_MULTIPLY ]:=key_kp_multiply;
+ //m_keymap[VK_SUBTRACT ]:=key_kp_minus;
+ //m_keymap[VK_ADD ] :=key_kp_plus;
+
+ m_keymap[kUpArrowCharCode ] :=key_up;
+ m_keymap[kDownArrowCharCode ] :=key_down;
+ m_keymap[kRightArrowCharCode ] :=key_right;
+ m_keymap[kLeftArrowCharCode ] :=key_left;
+ //m_keymap[VK_INSERT ]:=key_insert;
+ m_keymap[kDeleteCharCode ] :=key_delete;
+ m_keymap[kHomeCharCode ] :=key_home;
+ m_keymap[kEndCharCode ] :=key_end;
+ m_keymap[kPageUpCharCode ] :=key_page_up;
+ m_keymap[kPageDownCharCode ] :=key_page_down;
+
+ //m_keymap[VK_F1 ] :=key_f1;
+ //m_keymap[VK_F2 ] :=key_f2;
+ //m_keymap[VK_F3 ] :=key_f3;
+ //m_keymap[VK_F4 ] :=key_f4;
+ //m_keymap[VK_F5 ] :=key_f5;
+ //m_keymap[VK_F6 ] :=key_f6;
+ //m_keymap[VK_F7 ] :=key_f7;
+ //m_keymap[VK_F8 ] :=key_f8;
+ //m_keymap[VK_F9 ] :=key_f9;
+ //m_keymap[VK_F10 ]:=key_f10;
+ //m_keymap[VK_F11 ]:=key_f11;
+ //m_keymap[VK_F12 ]:=key_f12;
+ //m_keymap[VK_F13 ]:=key_f13;
+ //m_keymap[VK_F14 ]:=key_f14;
+ //m_keymap[VK_F15 ]:=key_f15;
+
+ //m_keymap[VK_NUMLOCK ]:=key_numlock;
+ //m_keymap[VK_CAPITAL ]:=key_capslock;
+ //m_keymap[VK_SCROLL ] :=key_scrollock;
+
+ case m_format of
+ pix_format_gray8 :
+ begin
+ m_sys_format:=pix_format_rgb24;
+ m_bpp :=8;
+ m_sys_bpp :=24;
+
+ end;
+
+ pix_format_rgb565 ,
+ pix_format_rgb555 :
+ begin
+ m_sys_format:=pix_format_rgb555;
+ m_bpp :=16;
+ m_sys_bpp :=16;
+
+ end;
+
+ pix_format_rgb24 ,
+ pix_format_bgr24 :
+ begin
+ m_sys_format:=pix_format_rgb24;
+ m_bpp :=24;
+ m_sys_bpp :=24;
+
+ end;
+
+ pix_format_bgra32 ,
+ pix_format_abgr32 ,
+ pix_format_argb32 ,
+ pix_format_rgba32 :
+ begin
+ m_sys_format:=pix_format_argb32;
+ m_bpp :=32;
+ m_sys_bpp :=32;
+
+ end;
+
+ end;
+
+ Microseconds(m_sw_freq );
+ Microseconds(m_sw_start );
+
+end;
+
+{ DESTRUCT }
+destructor platform_specific.Destruct;
+var
+ i : unsigned;
+
+begin
+ m_pmap_window.Destruct;
+
+ for i:=0 to max_images - 1 do
+ m_pmap_img[i ].Destruct;
+
+end;
+
+{ CREATE_PMAP }
+procedure platform_specific.create_pmap;
+begin
+ m_pmap_window.create(width ,height ,m_bpp );
+
+ if m_flip_y then
+ wnd.attach(
+ m_pmap_window._buf ,
+ m_pmap_window._width ,
+ m_pmap_window._height ,
+ -m_pmap_window._row_bytes )
+
+ else
+ wnd.attach(
+ m_pmap_window._buf ,
+ m_pmap_window._width ,
+ m_pmap_window._height ,
+ m_pmap_window._row_bytes )
+
+end;
+
+{ convert_pmap }
+procedure convert_pmap(dst ,src : rendering_buffer_ptr; format : pix_format_e );
+begin
+ case format of
+ pix_format_gray8 :
+ color_conv(dst ,src ,color_conv_gray8_to_rgb24 );
+
+ pix_format_rgb565 :
+ color_conv(dst ,src ,color_conv_rgb565_to_rgb555 );
+
+ pix_format_bgr24 :
+ color_conv(dst ,src ,color_conv_bgr24_to_rgb24 );
+
+ pix_format_abgr32 :
+ color_conv(dst ,src ,color_conv_abgr32_to_argb32 );
+
+ pix_format_bgra32 :
+ color_conv(dst ,src ,color_conv_bgra32_to_argb32 );
+
+ pix_format_rgba32 :
+ color_conv(dst ,src ,color_conv_rgba32_to_argb32 );
+
+ end;
+
+end;
+
+{ DISPLAY_PMAP }
+procedure platform_specific.display_pmap;
+var
+ pmap_tmp : pixel_map;
+ rbuf_tmp : rendering_buffer;
+
+begin
+ if m_sys_format = m_format then
+ m_pmap_window.draw(window )
+
+ else
+ begin
+ pmap_tmp.Construct;
+ pmap_tmp.create(m_pmap_window._width ,m_pmap_window._height ,m_sys_bpp );
+
+ rbuf_tmp.Construct;
+
+ if m_flip_y then
+ rbuf_tmp.attach(pmap_tmp._buf ,pmap_tmp._width ,pmap_tmp._height ,-pmap_tmp._row_bytes )
+ else
+ rbuf_tmp.attach(pmap_tmp._buf ,pmap_tmp._width ,pmap_tmp._height ,pmap_tmp._row_bytes );
+
+ convert_pmap (@rbuf_tmp ,src ,m_format );
+ pmap_tmp.draw(window );
+
+ rbuf_tmp.Destruct;
+ pmap_tmp.Destruct;
+
+ end;
+
+end;
+
+{ LOAD_PMAP }
+function platform_specific.load_pmap;
+var
+ pmap_tmp : pixel_map;
+ rbuf_tmp : rendering_buffer;
+
+begin
+ pmap_tmp.Construct;
+
+ if not pmap_tmp.load_from_qt(fn ) then
+ begin
+ result:=false;
+
+ pmap_tmp.Destruct;
+ exit;
+
+ end;
+
+ rbuf_tmp.Construct;
+
+ if m_flip_y then
+ rbuf_tmp.attach(pmap_tmp._buf ,pmap_tmp._width ,pmap_tmp._height ,-pmap_tmp._row_bytes )
+ else
+ rbuf_tmp.attach(pmap_tmp._buf ,pmap_tmp._width ,pmap_tmp._height ,pmap_tmp._row_bytes );
+
+ m_pmap_img[idx ].create(pmap_tmp._width ,pmap_tmp._height ,m_bpp ,0 );
+
+ if m_flip_y then
+ dst.attach(
+ m_pmap_img[idx ]._buf ,
+ m_pmap_img[idx ]._width ,
+ m_pmap_img[idx ]._height ,
+ -m_pmap_img[idx ]._row_bytes )
+ else
+ dst.attach(
+ m_pmap_img[idx ]._buf ,
+ m_pmap_img[idx ]._width ,
+ m_pmap_img[idx ]._height ,
+ m_pmap_img[idx ]._row_bytes );
+
+ case m_format of
+ pix_format_rgb555 :
+ case pmap_tmp._bpp of
+ 16 : color_conv(dst ,@rbuf_tmp ,color_conv_rgb555_to_rgb555 );
+ 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_rgb555 );
+ 32 : color_conv(dst ,@rbuf_tmp ,color_conv_bgra32_to_rgb555 );
+
+ end;
+
+ pix_format_rgb565 :
+ case pmap_tmp._bpp of
+ 16 : color_conv(dst ,@rbuf_tmp ,color_conv_rgb555_to_rgb565 );
+ 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_rgb565 );
+ 32 : color_conv(dst ,@rbuf_tmp ,color_conv_bgra32_to_rgb565 );
+
+ end;
+
+ pix_format_rgb24 :
+ case pmap_tmp._bpp of
+ 16 : color_conv(dst ,@rbuf_tmp ,color_conv_rgb555_to_rgb24 );
+ 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_rgb24 );
+ 32 : color_conv(dst ,@rbuf_tmp ,color_conv_bgra32_to_rgb24 );
+
+ end;
+
+ pix_format_bgr24 :
+ case pmap_tmp._bpp of
+ 16 : color_conv(dst ,@rbuf_tmp ,color_conv_rgb555_to_bgr24 );
+ 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_bgr24 );
+ 32 : color_conv(dst ,@rbuf_tmp ,color_conv_bgra32_to_bgr24 );
+
+ end;
+
+ pix_format_abgr32 :
+ case pmap_tmp._bpp of
+ 16 : color_conv(dst ,@rbuf_tmp ,color_conv_rgb555_to_abgr32 );
+ 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_abgr32 );
+ 32 : color_conv(dst ,@rbuf_tmp ,color_conv_bgra32_to_abgr32 );
+
+ end;
+
+ pix_format_argb32 :
+ case pmap_tmp._bpp of
+ 16 : color_conv(dst ,@rbuf_tmp ,color_conv_rgb555_to_argb32 );
+ 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_argb32 );
+ 32 : color_conv(dst ,@rbuf_tmp ,color_conv_bgra32_to_argb32 );
+
+ end;
+
+ pix_format_bgra32 :
+ case pmap_tmp._bpp of
+ 16 : color_conv(dst ,@rbuf_tmp ,color_conv_rgb555_to_bgra32 );
+ 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_bgra32 );
+ 32 : color_conv(dst ,@rbuf_tmp ,color_conv_bgra32_to_bgra32 );
+
+ end;
+
+ pix_format_rgba32 :
+ case pmap_tmp._bpp of
+ 16 : color_conv(dst ,@rbuf_tmp ,color_conv_rgb555_to_rgba32 );
+ 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_rgba32 );
+ 32 : color_conv(dst ,@rbuf_tmp ,color_conv_bgra32_to_rgba32 );
+
+ end;
+
+ end;
+
+ pmap_tmp.Destruct;
+ rbuf_tmp.Destruct;
+
+ result:=true;
+
+end;
+
+{ SAVE_PMAP }
+function platform_specific.save_pmap;
+var
+ pmap_tmp : pixel_map;
+ rbuf_tmp : rendering_buffer;
+
+begin
+ if m_sys_format = m_format then
+ begin
+ result:=m_pmap_img[idx ].save_as_qt(fn );
+
+ exit;
+
+ end;
+
+ pmap_tmp.Construct;
+ pmap_tmp.create(
+ m_pmap_img[idx ]._width ,
+ m_pmap_img[idx ]._height ,
+ m_sys_bpp );
+
+ rbuf_tmp.Construct;
+
+ if m_flip_y then
+ rbuf_tmp.attach(pmap_tmp._buf ,pmap_tmp._width ,pmap_tmp._height ,-pmap_tmp._row_bytes )
+ else
+ rbuf_tmp.attach(pmap_tmp._buf ,pmap_tmp._width ,pmap_tmp._height ,pmap_tmp._row_bytes );
+
+ convert_pmap(@rbuf_tmp ,src ,m_format );
+
+ result:=pmap_tmp.save_as_qt(fn );
+
+ rbuf_tmp.Destruct;
+ pmap_tmp.Destruct;
+
+end;
+
+{ TRANSLATE }
+function platform_specific.translate;
+begin
+ if keycode > 255 then
+ m_last_translated_key:=0
+ else
+ m_last_translated_key:=m_keymap[keycode ];
+
+end;
+
+{ CONSTRUCT }
+constructor platform_support.Construct;
+var
+ i : unsigned;
+
+begin
+ new(m_specific ,Construct(format_ ,flip_y_ ) );
+
+ m_ctrls.Construct;
+ m_rbuf_window.Construct;
+
+ for i:=0 to max_images - 1 do
+ m_rbuf_img[i ].Construct;
+
+ m_resize_mtx.Construct;
+
+ m_format:=format_;
+
+ m_bpp:=m_specific.m_bpp;
+
+ m_window_flags:=0;
+ m_wait_mode :=true;
+ m_flip_y :=flip_y_;
+
+ m_initial_width :=10;
+ m_initial_height:=10;
+
+ m_caption:='Anti-Grain Geometry Application'#0;
+
+end;
+
+{ DESTRUCT }
+destructor platform_support.Destruct;
+var
+ i : unsigned;
+
+begin
+ dispose(m_specific ,Destruct );
+
+ m_ctrls.Destruct;
+ m_rbuf_window.Destruct;
+
+ for i:=0 to max_images - 1 do
+ m_rbuf_img[i ].Destruct;
+
+end;
+
+{ CAPTION_ }
+procedure platform_support.caption_;
+begin
+ m_caption:=cap + #0;
+
+ dec(byte(m_caption[0 ] ) );
+
+ if m_specific.m_window <> NIL then
+ SetWindowTitleWithCFString(
+ m_specific.m_window ,
+ CFStringCreateWithPascalStringNoCopy(
+ NIL ,cap ,kCFStringEncodingASCII ,NIL ) );
+
+end;
+
+{ LOAD_IMG }
+function platform_support.load_img;
+begin
+ if idx < max_images then
+ begin
+ file_ :=file_ + _img_ext;
+ result:=m_specific.load_pmap(file_ ,idx ,@m_rbuf_img[idx ] );
+
+ end
+ else
+ result:=true;
+
+end;
+
+{ SAVE_IMG }
+function platform_support.save_img;
+begin
+ if idx < max_images then
+ result:=m_specific.save_pmap(file_ ,idx ,@m_rbuf_img[idx ] )
+ else
+ result:=true;
+
+end;
+
+{ CREATE_IMG }
+function platform_support.create_img;
+begin
+ if idx < max_images then
+ begin
+ if width_ = 0 then
+ width_:=m_specific.m_pmap_window._width;
+
+ if height_ = 0 then
+ height_:=m_specific.m_pmap_window._height;
+
+ m_specific.m_pmap_img[idx ].create(width_ ,height_ ,m_specific.m_bpp );
+
+ if m_flip_y then
+ m_rbuf_img[idx ].attach(
+ m_specific.m_pmap_img[idx ]._buf ,
+ m_specific.m_pmap_img[idx ]._width ,
+ m_specific.m_pmap_img[idx ]._height ,
+ -m_specific.m_pmap_img[idx ]._row_bytes )
+ else
+ m_rbuf_img[idx ].attach(
+ m_specific.m_pmap_img[idx ]._buf ,
+ m_specific.m_pmap_img[idx ]._width ,
+ m_specific.m_pmap_img[idx ]._height ,
+ m_specific.m_pmap_img[idx ]._row_bytes );
+
+ result:=true;
+
+ end
+ else
+ result:=false;
+
+end;
+
+{ get_key_flags }
+function get_key_flags(wflags : int ) : unsigned;
+var
+ flags : unsigned;
+
+begin
+ flags:=0;
+
+ if wflags and shiftKey <> 0 then
+ flags:=flags or kbd_shift;
+
+ if wflags and controlKey <> 0 then
+ flags:=flags or kbd_ctrl;
+
+ result:=flags;
+
+end;
+
+{ DOWINDOWCLOSE }
+function DoWindowClose(nextHandler : EventHandlerCallRef; theEvent : EventRef; userData : pointer ) : OSStatus;
+begin
+ QuitApplicationEventLoop;
+
+ result:=CallNextEventHandler(nextHandler ,theEvent );
+
+end;
+
+{ DOWINDOWDRAWCONTENT }
+function DoWindowDrawContent(nextHandler : EventHandlerCallRef; theEvent : EventRef; userData : pointer ) : OSStatus;
+var
+ app : platform_support_ptr;
+
+begin
+ app:=platform_support_ptr(userData );
+
+ if app <> NIL then
+ begin
+ if app.m_specific.m_redraw_flag then
+ begin
+ app.on_draw;
+
+ app.m_specific.m_redraw_flag:=false;
+
+ end;
+
+ app.m_specific.display_pmap(app.m_specific.m_window ,app.rbuf_window );
+
+ end;
+
+ result:=CallNextEventHandler(nextHandler ,theEvent );
+
+end;
+
+{ DOWINDOWRESIZE }
+function DoWindowResize(nextHandler : EventHandlerCallRef; theEvent : EventRef; userData : pointer ) : OSStatus;
+var
+ app : platform_support_ptr;
+ Rect : Carbon.Rect;
+
+ width ,height : unsigned;
+
+begin
+ app:=platform_support_ptr(userData );
+
+ GetWindowBounds(app.m_specific.m_window ,kWindowContentRgn ,Rect );
+
+ width :=Rect.Right - Rect.Left;
+ height:=Rect.Bottom - Rect.Top;
+
+ if (width <> app.rbuf_window._width ) or
+ (height <> app.rbuf_window._height ) then
+ begin
+ app.m_specific.create_pmap(width ,height ,app.rbuf_window );
+ app.trans_affine_resizing_(width ,height );
+
+ app.on_resize(width ,height );
+
+ end;
+
+ app.force_redraw;
+
+ result:=CallNextEventHandler(nextHandler ,theEvent );
+
+end;
+
+{ DOAPPQUIT }
+function DoAppQuit(nextHandler : EventHandlerCallRef; theEvent : EventRef; userData : pointer ) : OSStatus;
+begin
+ result:=CallNextEventHandler(nextHandler ,theEvent );
+
+end;
+
+{ DOMOUSEDOWN }
+function DoMouseDown(nextHandler : EventHandlerCallRef; theEvent : EventRef; userData : pointer ) : OSStatus;
+var
+ wheresMyMouse : Carbon.Point;
+
+ modifier : UInt32;
+ button : EventMouseButton;
+
+ sz : UInt32;
+ app : platform_support_ptr;
+ ept : EventParamType;
+
+begin
+ ept:=0;
+
+ GetEventParameter(
+ theEvent ,
+ LongWord(int32_ptr(@kEventParamMouseLocation[1 ] )^ ) ,
+ LongWord(int32_ptr(@typeQDPoint[1 ] )^ ) ,
+ ept ,
+ sizeof(Carbon.Point ) ,
+ sz ,
+ @wheresMyMouse );
+
+ GlobalToLocal(wheresMyMouse );
+ GetEventParameter(
+ theEvent ,
+ LongWord(int32_ptr(@kEventParamKeyModifiers[1 ] )^ ) ,
+ LongWord(int32_ptr(@typeUInt32[1 ] )^ ) ,
+ ept ,
+ sizeof(UInt32 ) ,
+ sz ,
+ @modifier );
+
+ app:=platform_support_ptr(userData );
+
+ app.m_specific.m_cur_x:=wheresMyMouse.h;
+
+ if app._flip_y then
+ app.m_specific.m_cur_y:=app.rbuf_window._height - wheresMyMouse.v
+ else
+ app.m_specific.m_cur_y:=wheresMyMouse.v;
+
+ GetEventParameter(
+ theEvent ,
+ LongWord(int32_ptr(@kEventParamMouseButton[1 ] )^ ) ,
+ LongWord(int32_ptr(@typeMouseButton[1 ] )^ ) ,
+ ept ,
+ sizeof(EventMouseButton ) ,
+ sz ,
+ @button );
+
+ case button of
+ kEventMouseButtonSecondary :
+ app.m_specific.m_input_flags:=mouse_right or get_key_flags(modifier );
+
+ else
+ app.m_specific.m_input_flags:=mouse_left or get_key_flags(modifier );
+
+ end;
+
+ app.m_ctrls.set_cur(
+ app.m_specific.m_cur_x ,
+ app.m_specific.m_cur_y );
+
+ if app.m_ctrls.on_mouse_button_down(
+ app.m_specific.m_cur_x ,
+ app.m_specific.m_cur_y ) then
+ begin
+ app.on_ctrl_change;
+ app.force_redraw;
+
+ end
+ else
+ if app.m_ctrls.in_rect(
+ app.m_specific.m_cur_x ,
+ app.m_specific.m_cur_y ) then
+ if app.m_ctrls.set_cur(
+ app.m_specific.m_cur_x ,
+ app.m_specific.m_cur_y ) then
+ begin
+ app.on_ctrl_change;
+ app.force_redraw;
+
+ end
+ else
+ else
+ app.on_mouse_button_down(
+ app.m_specific.m_cur_x ,
+ app.m_specific.m_cur_y ,
+ app.m_specific.m_input_flags );
+
+ result:=CallNextEventHandler(nextHandler ,theEvent );
+
+end;
+
+{ DOMOUSEUP }
+function DoMouseUp(nextHandler : EventHandlerCallRef; theEvent : EventRef; userData : pointer ) : OSStatus;
+var
+ wheresMyMouse : Carbon.Point;
+
+ modifier : UInt32;
+ button : EventMouseButton;
+
+ sz : UInt32;
+ app : platform_support_ptr;
+ ept : EventParamType;
+
+begin
+ ept:=0;
+
+ GetEventParameter(
+ theEvent ,
+ LongWord(int32_ptr(@kEventParamMouseLocation[1 ] )^ ) ,
+ LongWord(int32_ptr(@typeQDPoint[1 ] )^ ) ,
+ ept ,
+ sizeof(Carbon.Point ) ,
+ sz ,
+ @wheresMyMouse );
+
+ GlobalToLocal(wheresMyMouse );
+
+ GetEventParameter(
+ theEvent ,
+ LongWord(int32_ptr(@kEventParamKeyModifiers[1 ] )^ ) ,
+ LongWord(int32_ptr(@typeUInt32[1 ] )^ ) ,
+ ept ,
+ sizeof(UInt32 ) ,
+ sz ,
+ @modifier );
+
+ app:=platform_support_ptr(userData );
+
+ app.m_specific.m_cur_x:=wheresMyMouse.h;
+
+ if app._flip_y then
+ app.m_specific.m_cur_y:=app.rbuf_window._height - wheresMyMouse.v
+ else
+ app.m_specific.m_cur_y:=wheresMyMouse.v;
+
+ GetEventParameter(
+ theEvent ,
+ LongWord(int32_ptr(@kEventParamMouseButton[1 ] )^ ) ,
+ LongWord(int32_ptr(@typeMouseButton[1 ] )^ ) ,
+ ept ,
+ sizeof(EventMouseButton ) ,
+ sz ,
+ @button );
+
+ case button of
+ kEventMouseButtonSecondary :
+ app.m_specific.m_input_flags:=mouse_right or get_key_flags(modifier );
+
+ else
+ app.m_specific.m_input_flags:=mouse_left or get_key_flags(modifier );
+
+ end;
+
+ if app.m_ctrls.on_mouse_button_up(
+ app.m_specific.m_cur_x ,
+ app.m_specific.m_cur_y ) then
+ begin
+ app.on_ctrl_change;
+ app.force_redraw;
+
+ end;
+
+ app.on_mouse_button_up(
+ app.m_specific.m_cur_x ,
+ app.m_specific.m_cur_y ,
+ app.m_specific.m_input_flags );
+
+ result:=CallNextEventHandler(nextHandler ,theEvent );
+
+end;
+
+{ DOMOUSEDRAGGED }
+function DoMouseDragged(nextHandler : EventHandlerCallRef; theEvent : EventRef; userData : pointer ) : OSStatus;
+var
+ wheresMyMouse : Carbon.Point;
+
+ modifier : UInt32;
+ button : EventMouseButton;
+
+ sz : UInt32;
+ app : platform_support_ptr;
+ ept : EventParamType;
+
+begin
+ ept:=0;
+
+ GetEventParameter(
+ theEvent ,
+ LongWord(int32_ptr(@kEventParamMouseLocation[1 ] )^ ) ,
+ LongWord(int32_ptr(@typeQDPoint[1 ] )^ ) ,
+ ept ,
+ sizeof(Carbon.Point ) ,
+ sz ,
+ @wheresMyMouse );
+
+ GlobalToLocal(wheresMyMouse );
+ GetEventParameter(
+ theEvent ,
+ LongWord(int32_ptr(@kEventParamKeyModifiers[1 ] )^ ) ,
+ LongWord(int32_ptr(@typeUInt32[1 ] )^ ) ,
+ ept ,
+ sizeof(UInt32 ) ,
+ sz ,
+ @modifier );
+
+ app:=platform_support_ptr(userData );
+
+ app.m_specific.m_cur_x:=wheresMyMouse.h;
+
+ if app._flip_y then
+ app.m_specific.m_cur_y:=app.rbuf_window._height - wheresMyMouse.v
+ else
+ app.m_specific.m_cur_y:=wheresMyMouse.v;
+
+ GetEventParameter(
+ theEvent ,
+ LongWord(int32_ptr(@kEventParamMouseButton[1 ] )^ ) ,
+ LongWord(int32_ptr(@typeMouseButton[1 ] )^ ) ,
+ ept ,
+ sizeof(EventMouseButton ) ,
+ sz ,
+ @button );
+
+ case button of
+ kEventMouseButtonSecondary :
+ app.m_specific.m_input_flags:=mouse_right or get_key_flags(modifier );
+
+ else
+ app.m_specific.m_input_flags:=mouse_left or get_key_flags(modifier );
+
+ end;
+
+ if app.m_ctrls.on_mouse_move(
+ app.m_specific.m_cur_x ,
+ app.m_specific.m_cur_y ,
+ app.m_specific.m_input_flags and mouse_left <> 0 ) then
+ begin
+ app.on_ctrl_change;
+ app.force_redraw;
+
+ end
+ else
+ app.on_mouse_move(
+ app.m_specific.m_cur_x ,
+ app.m_specific.m_cur_y ,
+ app.m_specific.m_input_flags );
+
+ result:=CallNextEventHandler(nextHandler ,theEvent );
+
+end;
+
+{ DOKEYDOWN }
+function DoKeyDown(nextHandler : EventHandlerCallRef; theEvent : EventRef; userData : pointer ) : OSStatus;
+var
+ key_char : byte;
+ key_code ,
+ modifier : UInt32;
+
+ sz : UInt32;
+ app : platform_support_ptr;
+ ept : EventParamType;
+
+ left ,up ,right ,down : boolean;
+
+begin
+ ept:=0;
+
+ GetEventParameter(
+ theEvent ,
+ LongWord(int32_ptr(@kEventParamKeyMacCharCodes[1 ] )^ ) ,
+ LongWord(int32_ptr(@typeChar[1 ] )^ ) ,
+ ept ,
+ sizeof(byte ) ,
+ sz ,
+ @key_char );
+
+ GetEventParameter(
+ theEvent ,
+ LongWord(int32_ptr(@kEventParamKeyCode[1 ] )^ ) ,
+ LongWord(int32_ptr(@typeUInt32[1 ] )^ ) ,
+ ept ,
+ sizeof(UInt32 ) ,
+ sz ,
+ @key_code );
+
+ GetEventParameter(
+ theEvent ,
+ LongWord(int32_ptr(@kEventParamKeyModifiers[1 ] )^ ) ,
+ LongWord(int32_ptr(@typeUInt32[1 ] )^ ) ,
+ ept ,
+ sizeof(UInt32 ) ,
+ sz ,
+ @modifier );
+
+ app:=platform_support_ptr(userData );
+
+ app.m_specific.m_last_translated_key:=0;
+
+ case modifier of
+ controlKey :
+ app.m_specific.m_input_flags:=
+ app.m_specific.m_input_flags or kbd_ctrl;
+
+ shiftKey :
+ app.m_specific.m_input_flags:=
+ app.m_specific.m_input_flags or kbd_shift;
+
+ else
+ app.m_specific.translate(key_char );
+
+ end;
+
+ case key_char of
+ kFunctionKeyCharCode :
+ case key_code of
+ 122 : app.m_specific.m_last_translated_key:=key_f1;
+ 120 : app.m_specific.m_last_translated_key:=key_f2;
+ 99 : app.m_specific.m_last_translated_key:=key_f3;
+ 118 : app.m_specific.m_last_translated_key:=key_f4;
+ 96 : app.m_specific.m_last_translated_key:=key_f5;
+ 97 : app.m_specific.m_last_translated_key:=key_f6;
+ 98 : app.m_specific.m_last_translated_key:=key_f7;
+ 100 : app.m_specific.m_last_translated_key:=key_f8;
+
+ end;
+
+ end;
+
+ if (app.m_specific.m_last_translated_key = 0 ) and
+ (key_char > 31 ) then
+ app.m_specific.m_last_translated_key:=key_char;
+
+ if app.m_specific.m_last_translated_key <> 0 then
+ begin
+ left :=false;
+ up :=false;
+ right:=false;
+ down :=false;
+
+ case app.m_specific.m_last_translated_key of
+ key_left : left :=true;
+ key_up : up :=true;
+ key_right : right:=true;
+ key_down : down :=true;
+
+ //On a Mac, screenshots are handled by the system.
+ key_f2 :
+ begin
+ app.copy_window_to_img(max_images - 1 );
+ app.save_img (max_images - 1 ,'screenshot.png' );
+
+ end;
+
+ key_f4 :
+ if modifier = optionKey then
+ app.quit;
+
+ end;
+
+ if app.m_ctrls.on_arrow_keys(left ,right ,down ,up ) then
+ begin
+ app.on_ctrl_change;
+ app.force_redraw;
+
+ end
+ else
+ app.on_key(
+ app.m_specific.m_cur_x ,
+ app.m_specific.m_cur_y ,
+ app.m_specific.m_last_translated_key ,
+ app.m_specific.m_input_flags );
+
+ end;
+
+ result:=CallNextEventHandler(nextHandler ,theEvent );
+
+end;
+
+{ DOKEYUP }
+function DoKeyUp(nextHandler : EventHandlerCallRef; theEvent : EventRef; userData : pointer ) : OSStatus;
+var
+ key_code : byte;
+ modifier : UInt32;
+
+ sz : UInt32;
+ app : platform_support_ptr;
+ ept : EventParamType;
+
+begin
+ ept:=0;
+
+ GetEventParameter(
+ theEvent ,
+ LongWord(int32_ptr(@kEventParamKeyMacCharCodes[1 ] )^ ) ,
+ LongWord(int32_ptr(@typeChar[1 ] )^ ) ,
+ ept ,
+ sizeof(byte ) ,
+ sz ,
+ @key_code );
+
+ GetEventParameter(
+ theEvent ,
+ LongWord(int32_ptr(@kEventParamKeyModifiers[1 ] )^ ) ,
+ LongWord(int32_ptr(@typeUInt32[1 ] )^ ) ,
+ ept ,
+ sizeof(UInt32 ) ,
+ sz ,
+ @modifier );
+
+ app:=platform_support_ptr(userData );
+
+ app.m_specific.m_last_translated_key:=0;
+
+ case modifier of
+ controlKey :
+ app.m_specific.m_input_flags:=
+ app.m_specific.m_input_flags and not kbd_ctrl;
+
+ shiftKey :
+ app.m_specific.m_input_flags:=
+ app.m_specific.m_input_flags and not kbd_shift;
+
+ end;
+
+ result:=CallNextEventHandler(nextHandler ,theEvent );
+
+end;
+
+{ DOPERIODICTASK }
+procedure DoPeriodicTask(theTimer : EventLoopTimerRef; userData : pointer );
+var
+ app : platform_support_ptr;
+
+begin
+ app:=platform_support_ptr(userData );
+
+ if not app._wait_mode then
+ app.on_idle;
+
+end;
+
+{ INIT }
+function platform_support.init;
+var
+ eventType : EventTypeSpec;
+ handlerUPP : EventHandlerUPP;
+ theTarget : CFStringRef;
+ windowAttrs : WindowAttributes;
+ bounds : Carbon.Rect;
+ mainLoop : EventLoopRef;
+ timerUPP : EventLoopTimerUPP;
+ theTimer : EventLoopTimerRef;
+
+begin
+ if m_specific.m_sys_format = pix_format_undefined then
+ begin
+ result:=false;
+
+ exit;
+
+ end;
+
+ m_window_flags:=flags;
+
+// application
+ theTarget:=GetApplicationEventTarget;
+
+ eventType.eventClass:=LongWord(int32_ptr(@kEventClassApplication[1 ] )^ );
+ eventType.eventKind :=kEventAppQuit;
+
+ handlerUPP:=NewEventHandlerUPP(@DoAppQuit );
+
+ InstallEventHandler(theTarget ,handlerUPP ,1 ,eventType ,NIL ,NIL );
+
+
+ eventType.eventClass:=LongWord(int32_ptr(@kEventClassMouse[1 ] )^ );
+ eventType.eventKind :=kEventMouseDown;
+
+ handlerUPP:=NewEventHandlerUPP(@DoMouseDown );
+
+ InstallEventHandler(theTarget ,handlerUPP ,1 ,eventType ,@self ,NIL );
+
+
+ eventType.eventKind:=kEventMouseUp;
+
+ handlerUPP:=NewEventHandlerUPP(@DoMouseUp );
+
+ InstallEventHandler(theTarget ,handlerUPP ,1 ,eventType ,@self ,NIL );
+
+
+ eventType.eventKind:=kEventMouseDragged;
+
+ handlerUPP:=NewEventHandlerUPP(@DoMouseDragged );
+
+ InstallEventHandler(theTarget ,handlerUPP ,1 ,eventType ,@self ,NIL );
+
+
+ eventType.eventClass:=LongWord(int32_ptr(@kEventClassKeyboard[1 ] )^ );
+ eventType.eventKind :=kEventRawKeyDown;
+
+ handlerUPP:=NewEventHandlerUPP(@DoKeyDown );
+
+ InstallEventHandler(theTarget ,handlerUPP ,1 ,eventType ,@self ,NIL );
+
+
+ eventType.eventKind:=kEventRawKeyUp;
+
+ handlerUPP:=NewEventHandlerUPP(@DoKeyUp );
+
+ InstallEventHandler(theTarget ,handlerUPP ,1 ,eventType ,@self ,NIL );
+
+
+ eventType.eventKind:=kEventRawKeyRepeat;
+
+ handlerUPP:=NewEventHandlerUPP(@DoKeyDown ); // 'key repeat' is translated to 'key down'
+
+ InstallEventHandler(theTarget ,handlerUPP ,1 ,eventType ,@self ,NIL );
+
+// window
+ windowAttrs:=kWindowCloseBoxAttribute or kWindowCollapseBoxAttribute or kWindowStandardHandlerAttribute;
+
+ if flags and window_resize <> 0 then
+ windowAttrs:=
+ windowAttrs or
+ kWindowResizableAttribute or
+ kWindowFullZoomAttribute or
+ kWindowLiveResizeAttribute;
+
+ SetRect (bounds ,0 ,0 ,width_ ,height_ );
+ OffsetRect(bounds ,100 ,100 );
+
+ CreateNewWindow(
+ kDocumentWindowClass ,
+ windowAttrs ,
+ bounds ,
+ m_specific.m_window );
+
+ if m_specific.m_window = NIL then
+ begin
+ result:=false;
+
+ exit;
+
+ end;
+
+// I assume the text is ASCII.
+// Change to kCFStringEncodingMacRoman, kCFStringEncodingISOLatin1, kCFStringEncodingUTF8 or what else you need.
+ SetWindowTitleWithCFString(
+ m_specific.m_window ,
+ CFStringCreateWithPascalStringNoCopy(
+ NIL ,m_caption ,kCFStringEncodingASCII ,NIL ) );
+
+ theTarget:=GetWindowEventTarget(m_specific.m_window );
+
+ eventType.eventClass:=LongWord(int32_ptr(@kEventClassWindow[1 ] )^ );
+ eventType.eventKind :=kEventWindowClose;
+
+ handlerUPP:=NewEventHandlerUPP(@DoWindowClose );
+
+ InstallEventHandler(theTarget ,handlerUPP ,1 ,eventType ,@self ,NIL );
+
+
+ eventType.eventKind:=kEventWindowDrawContent;
+
+ handlerUPP:=NewEventHandlerUPP(@DoWindowDrawContent );
+
+ InstallEventHandler(theTarget ,handlerUPP ,1 ,eventType ,@self ,NIL );
+
+
+ eventType.eventKind:=kEventWindowBoundsChanged;
+
+ handlerUPP:=NewEventHandlerUPP(@DoWindowResize );
+
+ InstallEventHandler(theTarget ,handlerUPP ,1 ,eventType ,@self ,NIL );
+
+// Periodic task
+// Instead of an idle function I use the Carbon event timer.
+// You may decide to change the wait value which is currently 50 milliseconds.
+ mainLoop:=GetMainEventLoop;
+ timerUPP:=NewEventLoopTimerUPP(@DoPeriodicTask );
+
+ InstallEventLoopTimer(mainLoop ,0 ,50 * kEventDurationMillisecond ,timerUPP ,@self ,theTimer );
+
+ m_specific.create_pmap(width_ ,height_ ,@m_rbuf_window );
+
+ m_initial_width :=width_;
+ m_initial_height:=height_;
+
+ on_init;
+ on_resize(width_ ,height_ );
+
+ m_specific.m_redraw_flag:=true;
+
+ ShowWindow (m_specific.m_window );
+ SetPortWindowPort(m_specific.m_window );
+
+ result:=true;
+
+end;
+
+{ RUN }
+function platform_support.run;
+begin
+ RunApplicationEventLoop;
+
+ result:=1;
+
+end;
+
+{ QUIT }
+procedure platform_support.quit;
+begin
+ QuitApplicationEventLoop;
+
+end;
+
+{ _FORMAT }
+function platform_support._format;
+begin
+ result:=m_format;
+
+end;
+
+{ _FLIP_Y }
+function platform_support._flip_y;
+begin
+ result:=m_flip_y;
+
+end;
+
+{ _BPP }
+function platform_support._bpp;
+begin
+ result:=m_bpp;
+
+end;
+
+{ _WAIT_MODE }
+function platform_support._wait_mode;
+begin
+ result:=m_wait_mode;
+
+end;
+
+{ WAIT_MODE_ }
+procedure platform_support.wait_mode_;
+begin
+ m_wait_mode:=wait_mode;
+
+end;
+
+{ FORCE_REDRAW }
+procedure platform_support.force_redraw;
+var
+ bounds : Carbon.Rect;
+
+begin
+ m_specific.m_redraw_flag:=true;
+
+// on_ctrl_change
+ on_draw;
+
+ SetRect (bounds ,0 ,0 ,m_rbuf_window._width ,m_rbuf_window._height );
+ InvalWindowRect(m_specific.m_window ,bounds );
+
+end;
+
+{ UPDATE_WINDOW }
+procedure platform_support.update_window;
+begin
+ m_specific.display_pmap(m_specific.m_window ,@m_rbuf_window );
+
+end;
+
+{ RBUF_WINDOW }
+function platform_support.rbuf_window;
+begin
+ result:=@m_rbuf_window;
+
+end;
+
+{ RBUF_IMG }
+function platform_support.rbuf_img;
+begin
+ result:=@m_rbuf_img[idx ];
+
+end;
+
+{ _IMG_EXT }
+function platform_support._img_ext;
+begin
+ result:='.bmp';
+
+end;
+
+{ COPY_IMG_TO_WINDOW }
+procedure platform_support.copy_img_to_window;
+begin
+ if (idx < max_images ) and
+ (rbuf_img(idx )._buf <> NIL ) then
+ rbuf_window.copy_from(rbuf_img(idx ) );
+
+end;
+
+{ COPY_WINDOW_TO_IMG }
+procedure platform_support.copy_window_to_img;
+begin
+ if idx < max_images then
+ begin
+ create_img(idx ,rbuf_window._width ,rbuf_window._height );
+ rbuf_img (idx ).copy_from(rbuf_window );
+
+ end;
+
+end;
+
+{ COPY_IMG_TO_IMG }
+procedure platform_support.copy_img_to_img;
+begin
+ if (idx_from < max_images ) and
+ (idx_to < max_images ) and
+ (rbuf_img(idx_from )._buf <> NIL ) then
+ begin
+ create_img(
+ idx_to ,
+ rbuf_img(idx_from )._width ,
+ rbuf_img(idx_from )._height );
+
+ rbuf_img(idx_to ).copy_from(rbuf_img(idx_from ) );
+
+ end;
+
+end;
+
+{ ON_INIT }
+procedure platform_support.on_init;
+begin
+end;
+
+{ ON_RESIZE }
+procedure platform_support.on_resize;
+begin
+end;
+
+{ ON_IDLE }
+procedure platform_support.on_idle;
+begin
+end;
+
+{ ON_MOUSE_MOVE }
+procedure platform_support.on_mouse_move;
+begin
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+procedure platform_support.on_mouse_button_down;
+begin
+end;
+
+{ ON_MOUSE_BUTTON_UP }
+procedure platform_support.on_mouse_button_up;
+begin
+end;
+
+{ ON_KEY }
+procedure platform_support.on_key;
+begin
+end;
+
+{ ON_CTRL_CHANGE }
+procedure platform_support.on_ctrl_change;
+begin
+end;
+
+{ ON_DRAW }
+procedure platform_support.on_draw;
+begin
+end;
+
+{ ON_POST_DRAW }
+procedure platform_support.on_post_draw;
+begin
+end;
+
+{ ADD_CTRL }
+procedure platform_support.add_ctrl;
+begin
+ m_ctrls.add(c );
+
+ c.transform(@m_resize_mtx );
+
+end;
+
+{ TRANS_AFFINE_RESIZING_ }
+procedure platform_support.trans_affine_resizing_;
+var
+ vp : trans_viewport;
+ ts : trans_affine_scaling;
+
+begin
+ if m_window_flags and window_keep_aspect_ratio <> 0 then
+ begin
+ //double sx = double(width) / double(m_initial_width);
+ //double sy = double(height) / double(m_initial_height);
+ //if(sy < sx) sx = sy;
+ //m_resize_mtx = trans_affine_scaling(sx, sx);
+
+ vp.Construct;
+ vp.preserve_aspect_ratio(0.5 ,0.5 ,aspect_ratio_meet );
+
+ vp.device_viewport(0 ,0 ,width_ ,height_ );
+ vp.world_viewport (0 ,0 ,m_initial_width ,m_initial_height );
+
+ vp.to_affine(@m_resize_mtx );
+
+ end
+ else
+ begin
+ ts.Construct(
+ width_ / m_initial_width ,
+ height_ / m_initial_height );
+
+ m_resize_mtx.assign(@ts );
+
+ end;
+
+end;
+
+{ _TRANS_AFFINE_RESIZING }
+function platform_support._trans_affine_resizing;
+begin
+ result:=@m_resize_mtx;
+
+end;
+
+{ _WIDTH }
+function platform_support._width;
+begin
+ result:=m_rbuf_window._width;
+
+end;
+
+{ _HEIGHT }
+function platform_support._height;
+begin
+ result:=m_rbuf_window._height;
+
+end;
+
+{ _INITIAL_WIDTH }
+function platform_support._initial_width;
+begin
+ result:=m_initial_width;
+
+end;
+
+{ _INITIAL_HEIGHT }
+function platform_support._initial_height;
+begin
+ result:=m_initial_height;
+
+end;
+
+{ _WINDOW_FLAGS }
+function platform_support._window_flags;
+begin
+ result:=m_window_flags;
+
+end;
+
+{ _RAW_DISPLAY_HANDLER }
+function platform_support._raw_display_handler;
+begin
+end;
+
+{ MESSAGE_ }
+procedure platform_support.message_;
+var
+ dlg : DialogRef;
+ itm : DialogItemIndex;
+
+begin
+ CreateStandardAlert(
+ kAlertPlainAlert ,
+ CFStringCreateWithCStringNoCopy(
+ NIL ,'AGG Message' ,kCFStringEncodingASCII ,NIL ) ,
+ CFStringCreateWithCStringNoCopy(
+ NIL ,msg ,kCFStringEncodingASCII ,NIL ) ,
+ NIL ,
+ dlg );
+
+ RunStandardAlert(dlg ,NIL ,itm );
+
+end;
+
+{ START_TIMER }
+procedure platform_support.start_timer;
+begin
+ Microseconds(m_specific.m_sw_start );
+
+end;
+
+{ ELAPSED_TIME }
+function platform_support.elapsed_time;
+var
+ stop : UnsignedWide;
+
+begin
+ Microseconds(stop );
+
+ result:=
+ (stop.lo - m_specific.m_sw_start.lo) * 1e6 /
+ m_specific.m_sw_freq.lo;
+
+end;
+
+{ FULL_FILE_NAME }
+function platform_support.full_file_name;
+begin
+ result:=file_name;
+
+end;
+
+{ FILE_SOURCE }
+function platform_support.file_source;
+begin
+ result:=fname;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/platform/mac/file_utils_.pas b/src/corelib/render/software/platform/mac/file_utils_.pas
index fc804997..051b7a6a 100644
--- a/src/corelib/render/software/platform/mac/file_utils_.pas
+++ b/src/corelib/render/software/platform/mac/file_utils_.pas
@@ -1,846 +1,846 @@
-//
-// AggPas 2.4 RM3 demo framework file utility library
-// Milan Marusinec alias Milano (c) 2006
-//
-unit
- file_utils_ ;
-
-INTERFACE
-
-{$I agg_mode.inc }
-{$I- }
-uses
- agg_basics ,
- Carbon ;
-
-{ TYPES DEFINITION }
-type
- api_file_ptr = ^api_file;
- api_file = record
- fileName : shortstring;
- isOpened : boolean;
-
- fSize ,
- fRead : SInt64;
-
- // FSOpenFork parameters
- fFSRef : FSRef;
- fName ,
- fFork : HFSUniStr255;
- fRef : SInt16;
-
- end;
-
-{ GLOBAL PROCEDURES }
- function cut_str(s : shortstring ) : shortstring;
- function up_str (s : shortstring ) : shortstring;
- function cmp_str(s : shortstring ) : shortstring;
-
- function str_dir(s : shortstring ) : shortstring;
- function dir_str(s : shortstring ) : shortstring;
-
- function str_disk(fn : shortstring ) : shortstring;
- function str_path(fn : shortstring ) : shortstring;
- function str_name(fn : shortstring ) : shortstring;
- function str_ext (fn : shortstring ) : shortstring;
-
- function fold_name (p ,n ,x : shortstring ) : shortstring;
- procedure spread_name(fn : shortstring; var p ,n ,x : shortstring );
-
- function file_exists(fn : shortstring ) : boolean;
-
- procedure display(msg : PChar );
- function pasc (msg : shortstring ) : PChar;
-
- function api_open_file (var af : api_file; fname : shortstring ) : boolean;
- function api_read_file (var af : api_file; buff : pointer; aloc : int; var read : int ) : boolean;
- function api_close_file(var af : api_file ) : boolean;
-
- function param_count : int;
- function param_str(i : int ) : shortstring;
-
-
-IMPLEMENTATION
-{ LOCAL VARIABLES & CONSTANTS }
-type
- tSCAN = (
-
- SCAN_0 ,
- SCAN_1 ,SCAN_2 ,SCAN_3 ,SCAN_4 ,SCAN_5 ,SCAN_6 ,SCAN_7 ,SCAN_8 ,SCAN_9 ,
- SCAN_A ,SCAN_B ,SCAN_C ,SCAN_D ,SCAN_E ,SCAN_F ,SCAN_G ,SCAN_H ,SCAN_I ,
- SCAN_J ,SCAN_K ,SCAN_L ,SCAN_M ,SCAN_N ,SCAN_O ,SCAN_P ,SCAN_Q ,SCAN_R ,
- SCAN_S ,SCAN_T ,SCAN_U ,SCAN_V ,SCAN_W ,SCAN_X ,SCAN_Y ,SCAN_Z
-
- );
-
- tITEM = (
-
- ITEM_0 ,
- ITEM_1 ,ITEM_2 ,ITEM_3 ,ITEM_4 ,ITEM_5 ,ITEM_6 ,ITEM_7 ,ITEM_8 ,ITEM_9 ,
- ITEM_A ,ITEM_B ,ITEM_C ,ITEM_D ,ITEM_E ,ITEM_F ,ITEM_G ,ITEM_H ,ITEM_I ,
- ITEM_J ,ITEM_K ,ITEM_L ,ITEM_M ,ITEM_N ,ITEM_O ,ITEM_P ,ITEM_Q ,ITEM_R ,
- ITEM_S ,ITEM_T ,ITEM_U ,ITEM_V ,ITEM_W ,ITEM_X ,ITEM_Y ,ITEM_Z
-
- );
-
-const
- dir_slash = '/';
-
- pageEqHigh : shortstring =
- #1#2#3#4#5#6#7#8#9#10#11#12#13#14#15#16 +
- #17#18#19#20#21#22#23#24#25#26#27#28#29#30#31#32 +
- #33#34#35#36#37#38#39#40#41#42#43#44#45#46#47#48 +
- #49#50#51#52#53#54#55#56#57#58#59#60#61#62#63#64 +
- #65#66#67#68#69#70#71#72#73#74#75#76#77#78#79#80 +
- #81#82#83#84#85#86#87#88#89#90#91#92#93#94#95#96 +
- #65#66#67#68#69#70#71#72#73#74#75#76#77#78#79#80 +
- #81#82#83#84#85#86#87#88#89#90#123#124#125#126#127#128 +
- #129#130#131#132#133#134#135#136#137#138#139#140#141#142#143#144 +
- #145#146#147#148#149#150#151#152#153#154#155#156#157#158#159#160 +
- #161#162#163#164#165#166#167#168#169#170#171#172#173#174#175#176 +
- #177#178#179#180#181#182#183#184#185#186#187#188#189#190#191#192 +
- #193#194#195#196#197#198#199#200#201#202#203#204#205#206#207#208 +
- #209#210#211#212#213#214#215#216#217#218#219#220#221#222#223#224 +
- #225#226#227#228#229#230#231#232#233#234#235#236#237#238#239#240 +
- #241#242#243#244#245#246#247#248#249#250#251#252#253#254#255;
-
-{ UNIT IMPLEMENTATION }
-{ CUT_STR }
-function cut_str;
-var
- fcb : byte;
- scn : tSCAN;
-
-begin
- result:='';
-
- scn:=SCAN_1;
-
- if length(s ) > 0 then
- for fcb:=length(s ) downto 1 do
- case scn of
- SCAN_1 :
- case s[fcb ] of
- ' ' :
- else
- begin
- result:=s[fcb ];
-
- scn:=SCAN_2;
-
- end;
-
- end;
-
- SCAN_2 :
- result:=s[fcb ] + result;
-
- end;
-
-end;
-
-{ CMP_STR }
-function cmp_str;
-begin
- cmp_str:=up_str(cut_str(s ) );
-
-end;
-
-{ UP_STR }
-function up_str;
-var
- fcb : byte;
-
-begin
- if length(s ) > 0 then
- for fcb:=1 to length(s ) do
- if byte(s[fcb ] ) > 0 then
- s[fcb ]:=pageEqHigh[byte(s[fcb ] ) ];
-
- result:=s;
-
-end;
-
-{ STR_DIR }
-function str_dir;
-begin
- s:=cut_str(s );
-
- if length(s ) > 0 then
- if s[length(s ) ] <> dir_slash then
- s:=s + dir_slash;
-
- result:=s;
-
-end;
-
-{ DIR_STR }
-function dir_str;
-begin
- s:=cut_str(s );
-
- if length(s ) > 0 then
- if s[length(s ) ] = dir_slash then
- dec(byte(s[0 ] ) );
-
- result:=s;
-
-end;
-
-{ STR_DISK }
-function str_disk;
-var
- fcb : byte;
- str : shortstring;
- itm : tITEM;
-
-begin
- str:='';
- itm:=ITEM_1;
-
- if length(fn ) > 0 then
- for fcb:=1 to length(fn ) do
- case itm of
- ITEM_1 :
- case fn[fcb ] of
- 'a'..'z' ,'A'..'Z' :
- begin
- str:=fn[fcb ];
- itm:=ITEM_2;
-
- end;
-
- '\' ,'/' :
- begin
- str:=fn[fcb ];
- itm:=ITEM_3;
-
- end;
-
- else
- break;
-
- end;
-
- ITEM_2 :
- case fn[fcb ] of
- ':' :
- begin
- str:=str + fn[fcb ];
- itm:=ITEM_F;
-
- break;
-
- end;
-
- else
- break;
-
- end;
-
- ITEM_3 :
- case fn[fcb ] of
- '\' ,'/' :
- begin
- str:=str + fn[fcb ];
- itm:=ITEM_4;
-
- end;
-
- else
- break;
-
- end;
-
- ITEM_4 :
- case fn[fcb ] of
- '\' ,'/' ,':' ,'<' ,'>' ,'.' ,'"' ,'|' ,#0..#31 :
- break;
-
- else
- begin
- str:=str + fn[fcb ];
- itm:=ITEM_F;
-
- end;
-
- end;
-
- ITEM_F :
- case fn[fcb ] of
- '\' ,'/' :
- break;
-
- else
- str:=str + fn[fcb ];
-
- end;
-
- end;
-
- if itm = ITEM_F then
- result:=str
- else
- result:='';
-
-end;
-
-{ STR_PATH }
-function str_path;
-var
- fcb : byte;
- pth ,
- str : shortstring;
- itm : tITEM;
-
-begin
- pth:='';
- str:='';
- itm:=ITEM_1;
-
- if length(fn ) > 0 then
- for fcb:=1 to length(fn ) do
- case itm of
- ITEM_1 :
- case fn[fcb ] of
- '\' ,'/' :
- begin
- str:=fn[fcb ];
- itm:=ITEM_2;
-
- end;
-
- else
- begin
- str:=fn[fcb ];
- itm:=ITEM_3;
-
- end;
-
- end;
-
- ITEM_2 :
- case fn[fcb ] of
- '\' ,'/' :
- begin
- str:=str + fn[fcb ];
- itm:=ITEM_3;
-
- end;
-
- else
- begin
- pth:=str;
- str:=fn[fcb ];
- itm:=ITEM_A;
-
- end;
-
- end;
-
- ITEM_3 :
- case fn[fcb ] of
- '\' ,'/' :
- begin
- pth:=fn[fcb ];
- str:='';
- itm:=ITEM_A;
-
- end;
-
- else
- str:=str + fn[fcb ];
-
- end;
-
- ITEM_A :
- case fn[fcb ] of
- '\' ,'/' :
- begin
- pth:=pth + str + fn[fcb ];
- str:='';
-
- end;
-
- else
- str:=str + fn[fcb ];
-
- end;
-
- end;
-
- result:=pth;
-
-end;
-
-{ STR_NAME }
-function str_name;
-var
- fcb : byte;
- str ,
- ext : shortstring;
- itm : tITEM;
-
-begin
- str:='';
- ext:='';
- itm:=ITEM_1;
-
- if length(fn ) > 0 then
- for fcb:=1 to length(fn ) do
- case itm of
- ITEM_1 :
- case fn[fcb ] of
- '\' ,'/' :
- itm:=ITEM_2;
-
- 'a'..'z' ,'A'..'Z' :
- begin
- ext:=fn[fcb ];
- itm:=ITEM_4;
-
- end;
-
- '.' :
- begin
- str:='';
- ext:=fn[fcb ];
- itm:=ITEM_B;
-
- end;
-
- else
- begin
- str:=fn[fcb ];
- itm:=ITEM_A;
-
- end;
-
- end;
-
- ITEM_2 :
- case fn[fcb ] of
- '\' ,'/' :
- itm:=ITEM_3;
-
- '.' :
- begin
- str:='';
- ext:=fn[fcb ];
- itm:=ITEM_B;
-
- end;
-
- else
- begin
- str:=fn[fcb ];
- itm:=ITEM_A;
-
- end;
-
- end;
-
- ITEM_3 :
- case fn[fcb ] of
- '\' ,'/' :
- begin
- str:='';
- itm:=ITEM_A;
-
- end;
-
- end;
-
- ITEM_4 :
- case fn[fcb ] of
- '\' ,'/' :
- begin
- str:='';
- itm:=ITEM_A;
-
- end;
-
- ':' :
- itm:=ITEM_5;
-
- '.' :
- begin
- str:=ext;
- ext:=fn[fcb ];
- itm:=ITEM_B;
-
- end;
-
- else
- begin
- str:=ext + fn[fcb ];
- ext:='';
- itm:=ITEM_A;
-
- end;
-
- end;
-
- ITEM_5 :
- case fn[fcb ] of
- '\' ,'/' :
- begin
- str:='';
- itm:=ITEM_A;
-
- end;
-
- '.' :
- begin
- str:='';
- ext:=fn[fcb ];
- itm:=ITEM_B;
-
- end;
-
- else
- begin
- str:=fn[fcb ];
- itm:=ITEM_A;
-
- end;
-
- end;
-
- ITEM_A :
- case fn[fcb ] of
- '\' ,'/' :
- begin
- str:='';
- ext:='';
-
- end;
-
- '.' :
- begin
- ext:=fn[fcb ];
- itm:=ITEM_B;
-
- end;
-
- else
- str:=str + fn[fcb ];
-
- end;
-
- ITEM_B :
- case fn[fcb ] of
- '\' ,'/' :
- begin
- str:='';
- ext:='';
- itm:=ITEM_A;
-
- end;
-
- '.' :
- begin
- str:=str + ext;
- ext:=fn[fcb ];
-
- end;
-
- end;
-
- end;
-
- result:=str;
-
-end;
-
-{ STR_EXT }
-function str_ext;
-var
- fcb : byte;
- ext : shortstring;
- itm : tITEM;
-
-begin
- ext:='';
- itm:=ITEM_1;
-
- if length(fn ) > 0 then
- for fcb:=1 to length(fn ) do
- case itm of
- ITEM_1 :
- case fn[fcb ] of
- '\' ,'/' :
- itm:=ITEM_2;
-
- '.' :
- begin
- ext:=fn[fcb ];
- itm:=ITEM_B;
-
- end;
-
- else
- itm:=ITEM_A;
-
- end;
-
- ITEM_2 :
- case fn[fcb ] of
- '\' ,'/' :
- itm:=ITEM_3;
-
- '.' :
- begin
- ext:=fn[fcb ];
- itm:=ITEM_B;
-
- end;
-
- else
- itm:=ITEM_A;
-
- end;
-
- ITEM_3 :
- case fn[fcb ] of
- '\' ,'/' :
- itm:=ITEM_A;
-
- end;
-
- ITEM_A :
- case fn[fcb ] of
- '.' :
- begin
- ext:=fn[fcb ];
- itm:=ITEM_B;
-
- end;
-
- end;
-
- ITEM_B :
- case fn[fcb ] of
- '\' ,'/' :
- begin
- ext:='';
- itm:=ITEM_A;
-
- end;
-
- '.' :
- ext:=fn[fcb ];
-
- else
- ext:=ext + fn[fcb ];
-
- end;
-
- end;
-
- result:=cut_str(ext );
-
- if result = '.' then
- result:='';
-
-end;
-
-{ FOLD_NAME }
-function fold_name;
-var
- dsk ,
- nme ,
- pth ,
- ext : shortstring;
-
-begin
- dsk:=str_disk(p );
- pth:=str_dir (str_path(p ) );
- nme:=str_name(n );
- ext:=str_ext (x );
-
- result:=dsk + pth + nme + ext;
-
-end;
-
-{ SPREAD_NAME }
-procedure spread_name;
-begin
- p:=str_disk(fn ) + str_dir(str_path(fn ) );
- n:=str_name(fn );
- x:=str_ext (fn );
-
-end;
-
-{ FILE_EXISTS }
-function file_exists;
-var
- f : file;
-
-begin
- AssignFile(f ,fn );
- reset (f );
-
- if IOResult = 0 then
- begin
- close(f );
-
- result:=true;
-
- end
- else
- result:=false;
-
-end;
-
-{ DISPLAY }
-procedure display;
-var
- dlg : DialogRef;
- itm : DialogItemIndex;
-
-begin
- CreateStandardAlert(
- kAlertPlainAlert ,
- CFStringCreateWithCStringNoCopy(
- NIL ,'AGG Message' ,kCFStringEncodingASCII ,NIL ) ,
- CFStringCreateWithCStringNoCopy(
- NIL ,msg ,kCFStringEncodingASCII ,NIL ) ,
- NIL ,
- dlg );
-
- RunStandardAlert(dlg ,NIL ,itm );
-
-end;
-
-var
- mout : shortstring;
-
-{ PASC }
-function pasc;
-begin
- if length(msg ) = 255 then
- dec(byte(msg[0 ] ) );
-
- mout :=msg + #0;
- result:=PChar(@mout[1 ] );
-
-end;
-
-{ API_OPEN_FILE }
-function api_open_file;
-var
- i : unsigned;
-
- ossError : OSErr;
- outStatus : OSStatus;
- fileSpecs : FSSpec;
-
-begin
- result:=false;
-
- fillchar(af ,sizeof(api_file ) ,0 );
-
- af.fileName:=fname;
- af.isOpened:=false;
-
-{ Fill In Unicode Name }
- for i:=1 to length(fname ) do
- af.fName.unicode[i - 1 ]:=byte(fname[i ] );
-
- af.fName.length:=length(fname );
-
-{ Create FSRef }
- outStatus:=FSMakeFSSpec(0 ,0 ,fname ,fileSpecs );
-
- if outStatus <> noErr then
- exit;
-
- outStatus:=FSpMakeFSRef(fileSpecs ,af.fFSRef );
-
- if outStatus <> noErr then
- exit;
-
-{ Open Fork }
- FSGetDataForkName(af.fFork );
-
- ossError:=FSOpenFork(af.fFSRef ,af.fFork.length ,af.fFork.unicode[0 ] ,fsRdPerm ,af.fRef );
-
- if ossError = noErr then
- begin
- af.isOpened:=true;
-
- FSGetForkSize(af.fRef ,af.fSize );
-
- af.fRead:=0;
-
- end;
-
- result:=af.isOpened;
-
-end;
-
-{ API_READ_FILE }
-function api_read_file;
-var
- ossError : OSStatus;
- forkLoad : ByteCount;
-
-begin
- result:=false;
- read :=0;
-
- if af.isOpened then
- begin
- if aloc > af.fSize - af.fRead then
- aloc:=af.fSize - af.fRead;
-
- ossError:=FSReadFork(af.fRef ,fsAtMark + noCacheMask ,af.fRead ,aloc ,buff ,forkLoad );
-
- if ossError = noErr then
- begin
- read:=forkLoad;
-
- inc(af.fRead ,read );
-
- result:=true;
-
- end;
-
- end;
-
-end;
-
-{ API_CLOSE_FILE }
-function api_close_file;
-begin
- result:=false;
-
- if af.isOpened then
- begin
- FSCloseFork(af.fRef );
-
- af.isOpened:=false;
-
- result:=true;
-
- end;
-
-end;
-
-{ PARAM_COUNT }
-function param_count;
-begin
- result:=0;
-
-end;
-
-{ PARAM_STR }
-function param_str;
-begin
- result:='';
-
-end;
-
-END.
-
+//
+// AggPas 2.4 RM3 demo framework file utility library
+// Milan Marusinec alias Milano (c) 2006
+//
+unit
+ file_utils_ ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+{$I- }
+uses
+ agg_basics ,
+ Carbon ;
+
+{ TYPES DEFINITION }
+type
+ api_file_ptr = ^api_file;
+ api_file = record
+ fileName : shortstring;
+ isOpened : boolean;
+
+ fSize ,
+ fRead : SInt64;
+
+ // FSOpenFork parameters
+ fFSRef : FSRef;
+ fName ,
+ fFork : HFSUniStr255;
+ fRef : SInt16;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+ function cut_str(s : shortstring ) : shortstring;
+ function up_str (s : shortstring ) : shortstring;
+ function cmp_str(s : shortstring ) : shortstring;
+
+ function str_dir(s : shortstring ) : shortstring;
+ function dir_str(s : shortstring ) : shortstring;
+
+ function str_disk(fn : shortstring ) : shortstring;
+ function str_path(fn : shortstring ) : shortstring;
+ function str_name(fn : shortstring ) : shortstring;
+ function str_ext (fn : shortstring ) : shortstring;
+
+ function fold_name (p ,n ,x : shortstring ) : shortstring;
+ procedure spread_name(fn : shortstring; var p ,n ,x : shortstring );
+
+ function file_exists(fn : shortstring ) : boolean;
+
+ procedure display(msg : PChar );
+ function pasc (msg : shortstring ) : PChar;
+
+ function api_open_file (var af : api_file; fname : shortstring ) : boolean;
+ function api_read_file (var af : api_file; buff : pointer; aloc : int; var read : int ) : boolean;
+ function api_close_file(var af : api_file ) : boolean;
+
+ function param_count : int;
+ function param_str(i : int ) : shortstring;
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+type
+ tSCAN = (
+
+ SCAN_0 ,
+ SCAN_1 ,SCAN_2 ,SCAN_3 ,SCAN_4 ,SCAN_5 ,SCAN_6 ,SCAN_7 ,SCAN_8 ,SCAN_9 ,
+ SCAN_A ,SCAN_B ,SCAN_C ,SCAN_D ,SCAN_E ,SCAN_F ,SCAN_G ,SCAN_H ,SCAN_I ,
+ SCAN_J ,SCAN_K ,SCAN_L ,SCAN_M ,SCAN_N ,SCAN_O ,SCAN_P ,SCAN_Q ,SCAN_R ,
+ SCAN_S ,SCAN_T ,SCAN_U ,SCAN_V ,SCAN_W ,SCAN_X ,SCAN_Y ,SCAN_Z
+
+ );
+
+ tITEM = (
+
+ ITEM_0 ,
+ ITEM_1 ,ITEM_2 ,ITEM_3 ,ITEM_4 ,ITEM_5 ,ITEM_6 ,ITEM_7 ,ITEM_8 ,ITEM_9 ,
+ ITEM_A ,ITEM_B ,ITEM_C ,ITEM_D ,ITEM_E ,ITEM_F ,ITEM_G ,ITEM_H ,ITEM_I ,
+ ITEM_J ,ITEM_K ,ITEM_L ,ITEM_M ,ITEM_N ,ITEM_O ,ITEM_P ,ITEM_Q ,ITEM_R ,
+ ITEM_S ,ITEM_T ,ITEM_U ,ITEM_V ,ITEM_W ,ITEM_X ,ITEM_Y ,ITEM_Z
+
+ );
+
+const
+ dir_slash = '/';
+
+ pageEqHigh : shortstring =
+ #1#2#3#4#5#6#7#8#9#10#11#12#13#14#15#16 +
+ #17#18#19#20#21#22#23#24#25#26#27#28#29#30#31#32 +
+ #33#34#35#36#37#38#39#40#41#42#43#44#45#46#47#48 +
+ #49#50#51#52#53#54#55#56#57#58#59#60#61#62#63#64 +
+ #65#66#67#68#69#70#71#72#73#74#75#76#77#78#79#80 +
+ #81#82#83#84#85#86#87#88#89#90#91#92#93#94#95#96 +
+ #65#66#67#68#69#70#71#72#73#74#75#76#77#78#79#80 +
+ #81#82#83#84#85#86#87#88#89#90#123#124#125#126#127#128 +
+ #129#130#131#132#133#134#135#136#137#138#139#140#141#142#143#144 +
+ #145#146#147#148#149#150#151#152#153#154#155#156#157#158#159#160 +
+ #161#162#163#164#165#166#167#168#169#170#171#172#173#174#175#176 +
+ #177#178#179#180#181#182#183#184#185#186#187#188#189#190#191#192 +
+ #193#194#195#196#197#198#199#200#201#202#203#204#205#206#207#208 +
+ #209#210#211#212#213#214#215#216#217#218#219#220#221#222#223#224 +
+ #225#226#227#228#229#230#231#232#233#234#235#236#237#238#239#240 +
+ #241#242#243#244#245#246#247#248#249#250#251#252#253#254#255;
+
+{ UNIT IMPLEMENTATION }
+{ CUT_STR }
+function cut_str;
+var
+ fcb : byte;
+ scn : tSCAN;
+
+begin
+ result:='';
+
+ scn:=SCAN_1;
+
+ if length(s ) > 0 then
+ for fcb:=length(s ) downto 1 do
+ case scn of
+ SCAN_1 :
+ case s[fcb ] of
+ ' ' :
+ else
+ begin
+ result:=s[fcb ];
+
+ scn:=SCAN_2;
+
+ end;
+
+ end;
+
+ SCAN_2 :
+ result:=s[fcb ] + result;
+
+ end;
+
+end;
+
+{ CMP_STR }
+function cmp_str;
+begin
+ cmp_str:=up_str(cut_str(s ) );
+
+end;
+
+{ UP_STR }
+function up_str;
+var
+ fcb : byte;
+
+begin
+ if length(s ) > 0 then
+ for fcb:=1 to length(s ) do
+ if byte(s[fcb ] ) > 0 then
+ s[fcb ]:=pageEqHigh[byte(s[fcb ] ) ];
+
+ result:=s;
+
+end;
+
+{ STR_DIR }
+function str_dir;
+begin
+ s:=cut_str(s );
+
+ if length(s ) > 0 then
+ if s[length(s ) ] <> dir_slash then
+ s:=s + dir_slash;
+
+ result:=s;
+
+end;
+
+{ DIR_STR }
+function dir_str;
+begin
+ s:=cut_str(s );
+
+ if length(s ) > 0 then
+ if s[length(s ) ] = dir_slash then
+ dec(byte(s[0 ] ) );
+
+ result:=s;
+
+end;
+
+{ STR_DISK }
+function str_disk;
+var
+ fcb : byte;
+ str : shortstring;
+ itm : tITEM;
+
+begin
+ str:='';
+ itm:=ITEM_1;
+
+ if length(fn ) > 0 then
+ for fcb:=1 to length(fn ) do
+ case itm of
+ ITEM_1 :
+ case fn[fcb ] of
+ 'a'..'z' ,'A'..'Z' :
+ begin
+ str:=fn[fcb ];
+ itm:=ITEM_2;
+
+ end;
+
+ '\' ,'/' :
+ begin
+ str:=fn[fcb ];
+ itm:=ITEM_3;
+
+ end;
+
+ else
+ break;
+
+ end;
+
+ ITEM_2 :
+ case fn[fcb ] of
+ ':' :
+ begin
+ str:=str + fn[fcb ];
+ itm:=ITEM_F;
+
+ break;
+
+ end;
+
+ else
+ break;
+
+ end;
+
+ ITEM_3 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ str:=str + fn[fcb ];
+ itm:=ITEM_4;
+
+ end;
+
+ else
+ break;
+
+ end;
+
+ ITEM_4 :
+ case fn[fcb ] of
+ '\' ,'/' ,':' ,'<' ,'>' ,'.' ,'"' ,'|' ,#0..#31 :
+ break;
+
+ else
+ begin
+ str:=str + fn[fcb ];
+ itm:=ITEM_F;
+
+ end;
+
+ end;
+
+ ITEM_F :
+ case fn[fcb ] of
+ '\' ,'/' :
+ break;
+
+ else
+ str:=str + fn[fcb ];
+
+ end;
+
+ end;
+
+ if itm = ITEM_F then
+ result:=str
+ else
+ result:='';
+
+end;
+
+{ STR_PATH }
+function str_path;
+var
+ fcb : byte;
+ pth ,
+ str : shortstring;
+ itm : tITEM;
+
+begin
+ pth:='';
+ str:='';
+ itm:=ITEM_1;
+
+ if length(fn ) > 0 then
+ for fcb:=1 to length(fn ) do
+ case itm of
+ ITEM_1 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ str:=fn[fcb ];
+ itm:=ITEM_2;
+
+ end;
+
+ else
+ begin
+ str:=fn[fcb ];
+ itm:=ITEM_3;
+
+ end;
+
+ end;
+
+ ITEM_2 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ str:=str + fn[fcb ];
+ itm:=ITEM_3;
+
+ end;
+
+ else
+ begin
+ pth:=str;
+ str:=fn[fcb ];
+ itm:=ITEM_A;
+
+ end;
+
+ end;
+
+ ITEM_3 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ pth:=fn[fcb ];
+ str:='';
+ itm:=ITEM_A;
+
+ end;
+
+ else
+ str:=str + fn[fcb ];
+
+ end;
+
+ ITEM_A :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ pth:=pth + str + fn[fcb ];
+ str:='';
+
+ end;
+
+ else
+ str:=str + fn[fcb ];
+
+ end;
+
+ end;
+
+ result:=pth;
+
+end;
+
+{ STR_NAME }
+function str_name;
+var
+ fcb : byte;
+ str ,
+ ext : shortstring;
+ itm : tITEM;
+
+begin
+ str:='';
+ ext:='';
+ itm:=ITEM_1;
+
+ if length(fn ) > 0 then
+ for fcb:=1 to length(fn ) do
+ case itm of
+ ITEM_1 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ itm:=ITEM_2;
+
+ 'a'..'z' ,'A'..'Z' :
+ begin
+ ext:=fn[fcb ];
+ itm:=ITEM_4;
+
+ end;
+
+ '.' :
+ begin
+ str:='';
+ ext:=fn[fcb ];
+ itm:=ITEM_B;
+
+ end;
+
+ else
+ begin
+ str:=fn[fcb ];
+ itm:=ITEM_A;
+
+ end;
+
+ end;
+
+ ITEM_2 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ itm:=ITEM_3;
+
+ '.' :
+ begin
+ str:='';
+ ext:=fn[fcb ];
+ itm:=ITEM_B;
+
+ end;
+
+ else
+ begin
+ str:=fn[fcb ];
+ itm:=ITEM_A;
+
+ end;
+
+ end;
+
+ ITEM_3 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ str:='';
+ itm:=ITEM_A;
+
+ end;
+
+ end;
+
+ ITEM_4 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ str:='';
+ itm:=ITEM_A;
+
+ end;
+
+ ':' :
+ itm:=ITEM_5;
+
+ '.' :
+ begin
+ str:=ext;
+ ext:=fn[fcb ];
+ itm:=ITEM_B;
+
+ end;
+
+ else
+ begin
+ str:=ext + fn[fcb ];
+ ext:='';
+ itm:=ITEM_A;
+
+ end;
+
+ end;
+
+ ITEM_5 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ str:='';
+ itm:=ITEM_A;
+
+ end;
+
+ '.' :
+ begin
+ str:='';
+ ext:=fn[fcb ];
+ itm:=ITEM_B;
+
+ end;
+
+ else
+ begin
+ str:=fn[fcb ];
+ itm:=ITEM_A;
+
+ end;
+
+ end;
+
+ ITEM_A :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ str:='';
+ ext:='';
+
+ end;
+
+ '.' :
+ begin
+ ext:=fn[fcb ];
+ itm:=ITEM_B;
+
+ end;
+
+ else
+ str:=str + fn[fcb ];
+
+ end;
+
+ ITEM_B :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ str:='';
+ ext:='';
+ itm:=ITEM_A;
+
+ end;
+
+ '.' :
+ begin
+ str:=str + ext;
+ ext:=fn[fcb ];
+
+ end;
+
+ end;
+
+ end;
+
+ result:=str;
+
+end;
+
+{ STR_EXT }
+function str_ext;
+var
+ fcb : byte;
+ ext : shortstring;
+ itm : tITEM;
+
+begin
+ ext:='';
+ itm:=ITEM_1;
+
+ if length(fn ) > 0 then
+ for fcb:=1 to length(fn ) do
+ case itm of
+ ITEM_1 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ itm:=ITEM_2;
+
+ '.' :
+ begin
+ ext:=fn[fcb ];
+ itm:=ITEM_B;
+
+ end;
+
+ else
+ itm:=ITEM_A;
+
+ end;
+
+ ITEM_2 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ itm:=ITEM_3;
+
+ '.' :
+ begin
+ ext:=fn[fcb ];
+ itm:=ITEM_B;
+
+ end;
+
+ else
+ itm:=ITEM_A;
+
+ end;
+
+ ITEM_3 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ itm:=ITEM_A;
+
+ end;
+
+ ITEM_A :
+ case fn[fcb ] of
+ '.' :
+ begin
+ ext:=fn[fcb ];
+ itm:=ITEM_B;
+
+ end;
+
+ end;
+
+ ITEM_B :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ ext:='';
+ itm:=ITEM_A;
+
+ end;
+
+ '.' :
+ ext:=fn[fcb ];
+
+ else
+ ext:=ext + fn[fcb ];
+
+ end;
+
+ end;
+
+ result:=cut_str(ext );
+
+ if result = '.' then
+ result:='';
+
+end;
+
+{ FOLD_NAME }
+function fold_name;
+var
+ dsk ,
+ nme ,
+ pth ,
+ ext : shortstring;
+
+begin
+ dsk:=str_disk(p );
+ pth:=str_dir (str_path(p ) );
+ nme:=str_name(n );
+ ext:=str_ext (x );
+
+ result:=dsk + pth + nme + ext;
+
+end;
+
+{ SPREAD_NAME }
+procedure spread_name;
+begin
+ p:=str_disk(fn ) + str_dir(str_path(fn ) );
+ n:=str_name(fn );
+ x:=str_ext (fn );
+
+end;
+
+{ FILE_EXISTS }
+function file_exists;
+var
+ f : file;
+
+begin
+ AssignFile(f ,fn );
+ reset (f );
+
+ if IOResult = 0 then
+ begin
+ close(f );
+
+ result:=true;
+
+ end
+ else
+ result:=false;
+
+end;
+
+{ DISPLAY }
+procedure display;
+var
+ dlg : DialogRef;
+ itm : DialogItemIndex;
+
+begin
+ CreateStandardAlert(
+ kAlertPlainAlert ,
+ CFStringCreateWithCStringNoCopy(
+ NIL ,'AGG Message' ,kCFStringEncodingASCII ,NIL ) ,
+ CFStringCreateWithCStringNoCopy(
+ NIL ,msg ,kCFStringEncodingASCII ,NIL ) ,
+ NIL ,
+ dlg );
+
+ RunStandardAlert(dlg ,NIL ,itm );
+
+end;
+
+var
+ mout : shortstring;
+
+{ PASC }
+function pasc;
+begin
+ if length(msg ) = 255 then
+ dec(byte(msg[0 ] ) );
+
+ mout :=msg + #0;
+ result:=PChar(@mout[1 ] );
+
+end;
+
+{ API_OPEN_FILE }
+function api_open_file;
+var
+ i : unsigned;
+
+ ossError : OSErr;
+ outStatus : OSStatus;
+ fileSpecs : FSSpec;
+
+begin
+ result:=false;
+
+ fillchar(af ,sizeof(api_file ) ,0 );
+
+ af.fileName:=fname;
+ af.isOpened:=false;
+
+{ Fill In Unicode Name }
+ for i:=1 to length(fname ) do
+ af.fName.unicode[i - 1 ]:=byte(fname[i ] );
+
+ af.fName.length:=length(fname );
+
+{ Create FSRef }
+ outStatus:=FSMakeFSSpec(0 ,0 ,fname ,fileSpecs );
+
+ if outStatus <> noErr then
+ exit;
+
+ outStatus:=FSpMakeFSRef(fileSpecs ,af.fFSRef );
+
+ if outStatus <> noErr then
+ exit;
+
+{ Open Fork }
+ FSGetDataForkName(af.fFork );
+
+ ossError:=FSOpenFork(af.fFSRef ,af.fFork.length ,af.fFork.unicode[0 ] ,fsRdPerm ,af.fRef );
+
+ if ossError = noErr then
+ begin
+ af.isOpened:=true;
+
+ FSGetForkSize(af.fRef ,af.fSize );
+
+ af.fRead:=0;
+
+ end;
+
+ result:=af.isOpened;
+
+end;
+
+{ API_READ_FILE }
+function api_read_file;
+var
+ ossError : OSStatus;
+ forkLoad : ByteCount;
+
+begin
+ result:=false;
+ read :=0;
+
+ if af.isOpened then
+ begin
+ if aloc > af.fSize - af.fRead then
+ aloc:=af.fSize - af.fRead;
+
+ ossError:=FSReadFork(af.fRef ,fsAtMark + noCacheMask ,af.fRead ,aloc ,buff ,forkLoad );
+
+ if ossError = noErr then
+ begin
+ read:=forkLoad;
+
+ inc(af.fRead ,read );
+
+ result:=true;
+
+ end;
+
+ end;
+
+end;
+
+{ API_CLOSE_FILE }
+function api_close_file;
+begin
+ result:=false;
+
+ if af.isOpened then
+ begin
+ FSCloseFork(af.fRef );
+
+ af.isOpened:=false;
+
+ result:=true;
+
+ end;
+
+end;
+
+{ PARAM_COUNT }
+function param_count;
+begin
+ result:=0;
+
+end;
+
+{ PARAM_STR }
+function param_str;
+begin
+ result:='';
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/platform/win/agg_platform_support.pas b/src/corelib/render/software/platform/win/agg_platform_support.pas
index 3c4c8b0a..e9680fef 100644
--- a/src/corelib/render/software/platform/win/agg_platform_support.pas
+++ b/src/corelib/render/software/platform/win/agg_platform_support.pas
@@ -1,2121 +1,2121 @@
-//----------------------------------------------------------------------------
-// Anti-Grain Geometry - Version 2.4 (Public License)
-// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
-//
-// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
-// Pascal Port By: Milan Marusinec alias Milano
-// milan@marusinec.sk
-// http://www.aggpas.org
-// Copyright (c) 2005-2006
-//
-// Permission to copy, use, modify, sell and distribute this software
-// is granted provided this copyright notice appears in all copies.
-// This software is provided "as is" without express or implied
-// warranty, and with no claim as to its suitability for any purpose.
-//
-//----------------------------------------------------------------------------
-// Contact: mcseem@antigrain.com
-// mcseemagg@yahoo.com
-// http://www.antigrain.com
-//
-//----------------------------------------------------------------------------
-//
-// class platform_support
-//
-// It's not a part of the AGG library, it's just a helper class to create
-// interactive demo examples. Since the examples should not be too complex
-// this class is provided to support some very basic interactive graphical
-// funtionality, such as putting the rendered image to the window, simple
-// keyboard and mouse input, window resizing, setting the window title,
-// and catching the "idle" events.
-//
-// The most popular platforms are:
-//
-// Windows-32 API
-// X-Window API
-// SDL library (see http://www.libsdl.org/)
-// MacOS C/C++ API
-//
-// All the system dependent stuff sits in the platform_specific class.
-// The platform_support class has just a pointer to it and it's
-// the responsibility of the implementation to create/delete it.
-// This class being defined in the implementation file can have
-// any platform dependent stuff such as HWND, X11 Window and so on.
-//
-// [Pascal Port History] -----------------------------------------------------
-//
-// 23.06.2006-Milano: ptrcomp adjustments
-// 16.12.2005-Milano: platform_specific
-// 15.12.2005-Milano: platform_support
-// 12.12.2005-Milano: Unit port establishment
-//
-{ agg_platform_support.pas }
-unit
- agg_platform_support ;
-
-INTERFACE
-
-{$I agg_mode.inc }
-{$I- }
-uses
- Windows ,Messages ,
- agg_basics ,
- agg_ctrl ,
- agg_rendering_buffer ,
- agg_trans_affine ,
- agg_trans_viewport ,
- agg_win32_bmp ,
- agg_color_conv ;
-
-{ TYPES DEFINITION }
-const
-//----------------------------------------------------------window_flag_e
-// These are flags used in method init(). Not all of them are
-// applicable on different platforms, for example the win32_api
-// cannot use a hardware buffer (window_hw_buffer).
-// The implementation should simply ignore unsupported flags.
- window_resize = 1;
- window_hw_buffer = 2;
- window_keep_aspect_ratio = 4;
- window_process_all_keys = 8;
-
-type
-//-----------------------------------------------------------pix_format_e
-// Possible formats of the rendering buffer. Initially I thought that it's
-// reasonable to create the buffer and the rendering functions in
-// accordance with the native pixel format of the system because it
-// would have no overhead for pixel format conersion.
-// But eventually I came to a conclusion that having a possibility to
-// convert pixel formats on demand is a good idea. First, it was X11 where
-// there lots of different formats and visuals and it would be great to
-// render everything in, say, RGB-24 and display it automatically without
-// any additional efforts. The second reason is to have a possibility to
-// debug renderers for different pixel formats and colorspaces having only
-// one computer and one system.
-//
-// This stuff is not included into the basic AGG functionality because the
-// number of supported pixel formats (and/or colorspaces) can be great and
-// if one needs to add new format it would be good only to add new
-// rendering files without having to modify any existing ones (a general
-// principle of incapsulation and isolation).
-//
-// Using a particular pixel format doesn't obligatory mean the necessity
-// of software conversion. For example, win32 API can natively display
-// gray8, 15-bit RGB, 24-bit BGR, and 32-bit BGRA formats.
-// This list can be (and will be!) extended in future.
- pix_format_e = (
-
- pix_format_undefined , // By default. No conversions are applied
- pix_format_bw, // 1 bit per color B/W
- pix_format_gray8, // Simple 256 level grayscale
- pix_format_gray16, // Simple 65535 level grayscale
- pix_format_rgb555, // 15 bit rgb. Depends on the byte ordering!
- pix_format_rgb565, // 16 bit rgb. Depends on the byte ordering!
- pix_format_rgbAAA, // 30 bit rgb. Depends on the byte ordering!
- pix_format_rgbBBA, // 32 bit rgb. Depends on the byte ordering!
- pix_format_bgrAAA, // 30 bit bgr. Depends on the byte ordering!
- pix_format_bgrABB, // 32 bit bgr. Depends on the byte ordering!
- pix_format_rgb24, // R-G-B, one byte per color component
- pix_format_bgr24, // B-G-R, native win32 BMP format.
- pix_format_rgba32, // R-G-B-A, one byte per color component
- pix_format_argb32, // A-R-G-B, native MAC format
- pix_format_abgr32, // A-B-G-R, one byte per color component
- pix_format_bgra32, // B-G-R-A, native win32 BMP format
- pix_format_rgb48, // R-G-B, 16 bits per color component
- pix_format_bgr48, // B-G-R, native win32 BMP format.
- pix_format_rgba64, // R-G-B-A, 16 bits byte per color component
- pix_format_argb64, // A-R-G-B, native MAC format
- pix_format_abgr64, // A-B-G-R, one byte per color component
- pix_format_bgra64, // B-G-R-A, native win32 BMP format
-
- end_of_pix_formats );
-
-const
-//-------------------------------------------------------------input_flag_e
-// Mouse and keyboard flags. They can be different on different platforms
-// and the ways they are obtained are also different. But in any case
-// the system dependent flags should be mapped into these ones. The meaning
-// of that is as follows. For example, if kbd_ctrl is set it means that the
-// ctrl key is pressed and being held at the moment. They are also used in
-// the overridden methods such as on_mouse_move(), on_mouse_button_down(),
-// on_mouse_button_dbl_click(), on_mouse_button_up(), on_key().
-// In the method on_mouse_button_up() the mouse flags have different
-// meaning. They mean that the respective button is being released, but
-// the meaning of the keyboard flags remains the same.
-// There's absolut minimal set of flags is used because they'll be most
-// probably supported on different platforms. Even the mouse_right flag
-// is restricted because Mac's mice have only one button, but AFAIK
-// it can be simulated with holding a special key on the keydoard.
- mouse_left = 1;
- mouse_right = 2;
- kbd_shift = 4;
- kbd_ctrl = 8;
-
-//--------------------------------------------------------------key_code_e
-// Keyboard codes. There's also a restricted set of codes that are most
-// probably supported on different platforms. Any platform dependent codes
-// should be converted into these ones. There're only those codes are
-// defined that cannot be represented as printable ASCII-characters.
-// All printable ASCII-set can be used in a regilar C/C++ manner:
-// ' ', 'A', '0' '+' and so on.
-// Since the clasas is used for creating very simple demo-applications
-// we don't need very rich possibilities here, just basic ones.
-// Actually the numeric key codes are taken from the SDL library, so,
-// the implementation of the SDL support does not require any mapping.
-// ASCII set. Should be supported everywhere
- key_backspace = 8;
- key_tab = 9;
- key_clear = 12;
- key_return = 13;
- key_pause = 19;
- key_escape = 27;
-
-// Keypad
- key_delete = 127;
- key_kp0 = 256;
- key_kp1 = 257;
- key_kp2 = 258;
- key_kp3 = 259;
- key_kp4 = 260;
- key_kp5 = 261;
- key_kp6 = 262;
- key_kp7 = 263;
- key_kp8 = 264;
- key_kp9 = 265;
- key_kp_period = 266;
- key_kp_divide = 267;
- key_kp_multiply = 268;
- key_kp_minus = 269;
- key_kp_plus = 270;
- key_kp_enter = 271;
- key_kp_equals = 272;
-
-// Arrow-keys and stuff
- key_up = 273;
- key_down = 274;
- key_right = 275;
- key_left = 276;
- key_insert = 277;
- key_home = 278;
- key_end = 279;
- key_page_up = 280;
- key_page_down = 281;
-
-// Functional keys. You'd better avoid using
-// f11...f15 in your applications if you want
-// the applications to be portable
- key_f1 = 282;
- key_f2 = 283;
- key_f3 = 284;
- key_f4 = 285;
- key_f5 = 286;
- key_f6 = 287;
- key_f7 = 288;
- key_f8 = 289;
- key_f9 = 290;
- key_f10 = 291;
- key_f11 = 292;
- key_f12 = 293;
- key_f13 = 294;
- key_f14 = 295;
- key_f15 = 296;
-
-// The possibility of using these keys is
-// very restricted. Actually it's guaranteed
-// only in win32_api and win32_sdl implementations
- key_numlock = 300;
- key_capslock = 301;
- key_scrollock = 302;
-
- max_ctrl = 128;
-
-type
-//----------------------------------------------------------ctrl_container
-// A helper class that contains pointers to a number of controls.
-// This class is used to ease the event handling with controls.
-// The implementation should simply call the appropriate methods
-// of this class when appropriate events occure.
- crtl_container_ptr = ^ctrl_container;
- ctrl_container = object
- m_ctrl : array[0..max_ctrl - 1 ] of ctrl_ptr;
-
- m_num_ctrl : unsigned;
- m_cur_ctrl : int;
-
- constructor Construct;
- destructor Destruct;
-
- procedure add(c : ctrl_ptr );
-
- function in_rect(x ,y : double ) : boolean;
-
- function on_mouse_button_down(x ,y : double ) : boolean;
- function on_mouse_button_up (x ,y : double ) : boolean;
-
- function on_mouse_move(x ,y : double; button_flag : boolean ) : boolean;
- function on_arrow_keys(left ,right ,down ,up : boolean ) : boolean;
-
- function set_cur(x ,y : double ) : boolean;
-
- end;
-
-//---------------------------------------------------------platform_support
-// This class is a base one to the apllication classes. It can be used
-// as follows:
-//
-// the_application = object(platform_support )
-//
-// constructor Construct(bpp : unsigned; flip_y : boolean );
-// . . .
-//
-// //override stuff . . .
-// procedure on_init; virtual;
-// procedure on_draw; virtual;
-// procedure on_resize(sx ,sy : int ); virtual;
-// // . . . and so on, see virtual functions
-//
-// //any your own stuff . . .
-// };
-//
-// VAR
-// app : the_application;
-//
-// BEGIN
-// app.Construct(pix_format_rgb24 ,true );
-// app.caption ("AGG Example. Lion" );
-//
-// if app.init(500 ,400 ,window_resize ) then
-// app.run;
-//
-// app.Destruct;
-//
-// END.
-//
-const
- max_images = 16;
-
-var
-// Hmmm, I had to rip the fields below out of the platform_specific object,
-// because being them the part of that object/class, the corresponding
-// Windows API calls QueryPerformanceXXX are working NOT!.
-// Anyway, since we use usually only one instance of platform_specific in
-// our agg demos, it's okay to do that this way. See {hack}.
- m_sw_freq ,
- m_sw_start : int64;
-
-type
- platform_specific_ptr = ^platform_specific;
- platform_specific = object
- m_format ,
- m_sys_format : pix_format_e;
-
- m_flip_y : boolean;
- m_bpp ,
- m_sys_bpp : unsigned;
- m_hwnd : HWND;
-
- m_pmap_window : pixel_map;
- m_pmap_img : array[0..max_images - 1 ] of pixel_map;
-
- m_keymap : array[0..255 ] of unsigned;
-
- m_last_translated_key : unsigned;
-
- m_cur_x ,
- m_cur_y : int;
-
- m_input_flags : unsigned;
- m_redraw_flag : boolean;
- m_current_dc : HDC;
-
- //m_sw_freq ,
- //m_sw_start : int64;{hack}
-
- constructor Construct(format : pix_format_e; flip_y : boolean );
- destructor Destruct; {OpenCPL++} virtual; {/OpenCPL++}
-
- procedure create_pmap (width ,height : unsigned; wnd : rendering_buffer_ptr ); {OpenCPL++} virtual; {/OpenCPL++}
- procedure display_pmap(dc : HDC; src : rendering_buffer_ptr ); {OpenCPL++} virtual; {/OpenCPL++}
-
- function load_pmap(fn : shortstring; idx : unsigned; dst : rendering_buffer_ptr ) : boolean;
- function save_pmap(fn : shortstring; idx : unsigned; src : rendering_buffer_ptr ) : boolean;
-
- function translate(keycode : unsigned ) : unsigned;
-
- end;
-
- platform_support_ptr = ^platform_support;
- platform_support = object
- m_specific : platform_specific_ptr;
- m_ctrls : ctrl_container;
-
- m_format : pix_format_e;
-
- m_bpp : unsigned;
-
- m_rbuf_window : rendering_buffer;
- m_rbuf_img : array[0..max_images - 1 ] of rendering_buffer;
-
- m_window_flags : unsigned;
- m_wait_mode ,
- m_flip_y : boolean; // flip_y - true if you want to have the Y-axis flipped vertically
- m_caption : shortstring;
- m_resize_mtx : trans_affine;
-
- m_initial_width ,
- m_initial_height : int;
-
- constructor Construct(format_ : pix_format_e; flip_y_ : boolean; {OpenCPL++} specific : platform_specific_ptr = NIL {/OpenCPL++} );
- destructor Destruct;
-
- // Setting the windows caption (title). Should be able
- // to be called at least before calling init().
- // It's perfect if they can be called anytime.
- procedure caption_(cap : shortstring );
-
- // These 3 menthods handle working with images. The image
- // formats are the simplest ones, such as .BMP in Windows or
- // .ppm in Linux. In the applications the names of the files
- // should not have any file extensions. Method load_img() can
- // be called before init(), so, the application could be able
- // to determine the initial size of the window depending on
- // the size of the loaded image.
- // The argument "idx" is the number of the image 0...max_images-1
- function load_img (idx : unsigned; file_ : shortstring ) : boolean;
- function save_img (idx : unsigned; file_ : shortstring ) : boolean;
- function create_img(idx : unsigned; width_ : unsigned = 0; height_ : unsigned = 0 ) : boolean;
-
- // init() and run(). See description before the class for details.
- // The necessity of calling init() after creation is that it's
- // impossible to call the overridden virtual function (on_init())
- // from the constructor. On the other hand it's very useful to have
- // some on_init() event handler when the window is created but
- // not yet displayed. The rbuf_window() method (see below) is
- // accessible from on_init().
- function init(width_ ,height_ ,flags : unsigned ) : boolean;
- function run : int;
- procedure quit;
-
- // The very same parameters that were used in the constructor
- function _format : pix_format_e;
- function _flip_y : boolean;
- function _bpp : unsigned;
-
- // The following provides a very simple mechanism of doing someting
- // in background. It's not multitheading. When whait_mode is true
- // the class waits for the events and it does not ever call on_idle().
- // When it's false it calls on_idle() when the event queue is empty.
- // The mode can be changed anytime. This mechanism is satisfactory
- // for creation very simple animations.
- function _wait_mode : boolean;
- procedure wait_mode_(wait_mode : boolean );
-
- // These two functions control updating of the window.
- // force_redraw() is an analog of the Win32 InvalidateRect() function.
- // Being called it sets a flag (or sends a message) which results
- // in calling on_draw() and updating the content of the window
- // when the next event cycle comes.
- // update_window() results in just putting immediately the content
- // of the currently rendered buffer to the window without calling
- // on_draw().
- procedure force_redraw;
- procedure update_window;
-
- // So, finally, how to draw anythig with AGG? Very simple.
- // rbuf_window() returns a reference to the main rendering
- // buffer which can be attached to any rendering class.
- // rbuf_img() returns a reference to the previously created
- // or loaded image buffer (see load_img()). The image buffers
- // are not displayed directly, they should be copied to or
- // combined somehow with the rbuf_window(). rbuf_window() is
- // the only buffer that can be actually displayed.
- function rbuf_window : rendering_buffer_ptr;
- function rbuf_img(idx : unsigned ) : rendering_buffer_ptr;
-
- // Returns file extension used in the implemenation for the particular
- // system.
- function _img_ext : shortstring;
-
- //
- procedure copy_img_to_window(idx : unsigned );
- procedure copy_window_to_img(idx : unsigned );
- procedure copy_img_to_img (idx_to ,idx_from : unsigned );
-
- // Event handlers. They are not pure functions, so you don't have
- // to override them all.
- // In my demo applications these functions are defined inside
- // the the_application class
- procedure on_init; virtual;
- procedure on_resize(sx ,sy : int ); virtual;
- procedure on_idle; virtual;
-
- procedure on_mouse_move(x ,y : int; flags : unsigned ); virtual;
-
- procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual;
- procedure on_mouse_button_up (x ,y : int; flags : unsigned ); virtual;
-
- procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
- procedure on_ctrl_change; virtual;
- procedure on_draw; virtual;
- procedure on_post_draw(raw_handler : pointer ); virtual;
-
- // Adding control elements. A control element once added will be
- // working and reacting to the mouse and keyboard events. Still, you
- // will have to render them in the on_draw() using function
- // render_ctrl() because platform_support doesn't know anything about
- // renderers you use. The controls will be also scaled automatically
- // if they provide a proper scaling mechanism (all the controls
- // included into the basic AGG package do).
- // If you don't need a particular control to be scaled automatically
- // call ctrl::no_transform() after adding.
- procedure add_ctrl(c : ctrl_ptr );
-
- // Auxiliary functions. trans_affine_resizing() modifier sets up the resizing
- // matrix on the basis of the given width and height and the initial
- // width and height of the window. The implementation should simply
- // call this function every time when it catches the resizing event
- // passing in the new values of width and height of the window.
- // Nothing prevents you from "cheating" the scaling matrix if you
- // call this function from somewhere with wrong arguments.
- // trans_affine_resizing() accessor simply returns current resizing matrix
- // which can be used to apply additional scaling of any of your
- // stuff when the window is being resized.
- // width(), height(), initial_width(), and initial_height() must be
- // clear to understand with no comments :-)
- procedure trans_affine_resizing_(width_ ,height_ : int );
- function _trans_affine_resizing : trans_affine_ptr;
-
- function _width : double;
- function _height : double;
- function _initial_width : double;
- function _initial_height : double;
- function _window_flags : unsigned;
-
- // Get raw display handler depending on the system.
- // For win32 its an HDC, for other systems it can be a pointer to some
- // structure. See the implementation files for detals.
- // It's provided "as is", so, first you should check if it's not null.
- // If it's null the raw_display_handler is not supported. Also, there's
- // no guarantee that this function is implemented, so, in some
- // implementations you may have simply an unresolved symbol when linking.
- function _raw_display_handler : pointer;
-
- // display message box or print the message to the console
- // (depending on implementation)
- procedure message_(msg : PChar );
-
- // Stopwatch functions. Function elapsed_time() returns time elapsed
- // since the latest start_timer() invocation in millisecods.
- // The resolutoin depends on the implementation.
- // In Win32 it uses QueryPerformanceFrequency() / QueryPerformanceCounter().
- procedure start_timer;
- function elapsed_time : double;
-
- // Get the full file name. In most cases it simply returns
- // file_name. As it's appropriate in many systems if you open
- // a file by its name without specifying the path, it tries to
- // open it in the current directory. The demos usually expect
- // all the supplementary files to be placed in the current
- // directory, that is usually coincides with the directory where
- // the the executable is. However, in some systems (BeOS) it's not so.
- // For those kinds of systems full_file_name() can help access files
- // preserving commonly used policy.
- // So, it's a good idea to use in the demos the following:
- // FILE* fd = fopen(full_file_name("some.file"), "r");
- // instead of
- // FILE* fd = fopen("some.file", "r");
- function full_file_name(file_name : shortstring ) : shortstring;
- function file_source (path ,fname : shortstring ) : shortstring;
-
- end;
-
-{ GLOBAL PROCEDURES }
-
-
-IMPLEMENTATION
-{ LOCAL VARIABLES & CONSTANTS }
-{ UNIT IMPLEMENTATION }
-{ CONSTRUCT }
-constructor ctrl_container.Construct;
-begin
- m_num_ctrl:=0;
- m_cur_ctrl:=-1;
-
-end;
-
-{ DESTRUCT }
-destructor ctrl_container.Destruct;
-begin
-end;
-
-{ ADD }
-procedure ctrl_container.add;
-begin
- if m_num_ctrl < max_ctrl then
- begin
- m_ctrl[m_num_ctrl ]:=c;
-
- inc(m_num_ctrl );
-
- end;
-
-end;
-
-{ IN_RECT }
-function ctrl_container.in_rect;
-var
- i : unsigned;
-
-begin
- result:=false;
-
- if m_num_ctrl > 0 then
- for i:=0 to m_num_ctrl - 1 do
- if m_ctrl[i ].in_rect(x ,y ) then
- begin
- result:=true;
-
- exit;
-
- end;
-
-end;
-
-{ ON_MOUSE_BUTTON_DOWN }
-function ctrl_container.on_mouse_button_down;
-var
- i : unsigned;
-
-begin
- result:=false;
-
- if m_num_ctrl > 0 then
- for i:=0 to m_num_ctrl - 1 do
- if m_ctrl[i ].on_mouse_button_down(x ,y ) then
- begin
- result:=true;
-
- exit;
-
- end;
-
-end;
-
-{ ON_MOUSE_BUTTON_UP }
-function ctrl_container.on_mouse_button_up;
-var
- i : unsigned;
-
-begin
- result:=false;
-
- if m_num_ctrl > 0 then
- for i:=0 to m_num_ctrl - 1 do
- if m_ctrl[i ].on_mouse_button_up(x ,y ) then
- begin
- result:=true;
-
- exit;
-
- end;
-
-end;
-
-{ ON_MOUSE_MOVE }
-function ctrl_container.on_mouse_move;
-var
- i : unsigned;
-
-begin
- result:=false;
-
- if m_num_ctrl > 0 then
- for i:=0 to m_num_ctrl - 1 do
- if m_ctrl[i ].on_mouse_move(x ,y ,button_flag ) then
- begin
- result:=true;
-
- exit;
-
- end;
-
-end;
-
-{ ON_ARROW_KEYS }
-function ctrl_container.on_arrow_keys;
-begin
- result:=false;
-
- if m_cur_ctrl >= 0 then
- result:=m_ctrl[m_cur_ctrl ].on_arrow_keys(left ,right ,down ,up );
-
-end;
-
-{ SET_CUR }
-function ctrl_container.set_cur;
-var
- i : unsigned;
-
-begin
- result:=false;
-
- if m_num_ctrl > 0 then
- for i:=0 to m_num_ctrl - 1 do
- if m_ctrl[i ].in_rect(x ,y ) then
- begin
- if m_cur_ctrl <> i then
- begin
- m_cur_ctrl:=i;
-
- result:=true;
-
- end;
-
- exit;
-
- end;
-
- if m_cur_ctrl <> -1 then
- begin
- m_cur_ctrl:=-1;
-
- result:=true;
-
- end;
-
-end;
-
-{ CONSTRUCT }
-constructor platform_specific.Construct;
-var
- i : unsigned;
-
-begin
- m_pmap_window.Construct;
-
- for i:=0 to max_images - 1 do
- m_pmap_img[i ].Construct;
-
- m_format :=format;
- m_sys_format:=pix_format_undefined;
-
- m_flip_y :=flip_y;
- m_bpp :=0;
- m_sys_bpp:=0;
- m_hwnd :=0;
-
- m_last_translated_key:=0;
-
- m_cur_x:=0;
- m_cur_y:=0;
-
- m_input_flags:=0;
- m_redraw_flag:=true;
- m_current_dc :=0;
-
- fillchar(m_keymap[0 ] ,sizeof(m_keymap ) ,0 );
-
- m_keymap[VK_PAUSE ]:=key_pause;
- m_keymap[VK_CLEAR ]:=key_clear;
-
- m_keymap[VK_NUMPAD0 ] :=key_kp0;
- m_keymap[VK_NUMPAD1 ] :=key_kp1;
- m_keymap[VK_NUMPAD2 ] :=key_kp2;
- m_keymap[VK_NUMPAD3 ] :=key_kp3;
- m_keymap[VK_NUMPAD4 ] :=key_kp4;
- m_keymap[VK_NUMPAD5 ] :=key_kp5;
- m_keymap[VK_NUMPAD6 ] :=key_kp6;
- m_keymap[VK_NUMPAD7 ] :=key_kp7;
- m_keymap[VK_NUMPAD8 ] :=key_kp8;
- m_keymap[VK_NUMPAD9 ] :=key_kp9;
- m_keymap[VK_DECIMAL ] :=key_kp_period;
- m_keymap[VK_DIVIDE ] :=key_kp_divide;
- m_keymap[VK_MULTIPLY ]:=key_kp_multiply;
- m_keymap[VK_SUBTRACT ]:=key_kp_minus;
- m_keymap[VK_ADD ] :=key_kp_plus;
-
- m_keymap[VK_UP ] :=key_up;
- m_keymap[VK_DOWN ] :=key_down;
- m_keymap[VK_RIGHT ] :=key_right;
- m_keymap[VK_LEFT ] :=key_left;
- m_keymap[VK_INSERT ]:=key_insert;
- m_keymap[VK_DELETE ]:=key_delete;
- m_keymap[VK_HOME ] :=key_home;
- m_keymap[VK_END ] :=key_end;
- m_keymap[VK_PRIOR ] :=key_page_up;
- m_keymap[VK_NEXT ] :=key_page_down;
-
- m_keymap[VK_F1 ] :=key_f1;
- m_keymap[VK_F2 ] :=key_f2;
- m_keymap[VK_F3 ] :=key_f3;
- m_keymap[VK_F4 ] :=key_f4;
- m_keymap[VK_F5 ] :=key_f5;
- m_keymap[VK_F6 ] :=key_f6;
- m_keymap[VK_F7 ] :=key_f7;
- m_keymap[VK_F8 ] :=key_f8;
- m_keymap[VK_F9 ] :=key_f9;
- m_keymap[VK_F10 ]:=key_f10;
- m_keymap[VK_F11 ]:=key_f11;
- m_keymap[VK_F12 ]:=key_f12;
- m_keymap[VK_F13 ]:=key_f13;
- m_keymap[VK_F14 ]:=key_f14;
- m_keymap[VK_F15 ]:=key_f15;
-
- m_keymap[VK_NUMLOCK ]:=key_numlock;
- m_keymap[VK_CAPITAL ]:=key_capslock;
- m_keymap[VK_SCROLL ] :=key_scrollock;
-
- case m_format of
- pix_format_bw :
- begin
- m_sys_format:=pix_format_bw;
- m_bpp :=1;
- m_sys_bpp :=1;
-
- end;
-
- pix_format_gray8 :
- begin
- m_sys_format:=pix_format_bgr24;//pix_format_gray8;{hack}
- m_bpp :=8;
- m_sys_bpp :=24;//8;
-
- end;
-
- pix_format_gray16 :
- begin
- m_sys_format:=pix_format_gray8;
- m_bpp :=16;
- m_sys_bpp :=8;
-
- end;
-
- pix_format_rgb565 ,
- pix_format_rgb555 :
- begin
- m_sys_format:=pix_format_rgb555;
- m_bpp :=16;
- m_sys_bpp :=16;
-
- end;
-
- pix_format_rgbAAA ,
- pix_format_bgrAAA ,
- pix_format_rgbBBA ,
- pix_format_bgrABB :
- begin
- m_sys_format:=pix_format_bgr24;
- m_bpp :=32;
- m_sys_bpp :=24;
-
- end;
-
- pix_format_rgb24 ,
- pix_format_bgr24 :
- begin
- m_sys_format:=pix_format_bgr24;
- m_bpp :=24;
- m_sys_bpp :=24;
-
- end;
-
- pix_format_rgb48 ,
- pix_format_bgr48 :
- begin
- m_sys_format:=pix_format_bgr24;
- m_bpp :=48;
- m_sys_bpp :=24;
-
- end;
-
- pix_format_bgra32 ,
- pix_format_abgr32 ,
- pix_format_argb32 ,
- pix_format_rgba32 :
- begin
- m_sys_format:=pix_format_bgra32;
- m_bpp :=32;
- m_sys_bpp :=32;
-
- end;
-
- pix_format_bgra64 ,
- pix_format_abgr64 ,
- pix_format_argb64 ,
- pix_format_rgba64 :
- begin
- m_sys_format:=pix_format_bgra32;
- m_bpp :=64;
- m_sys_bpp :=32;
-
- end;
-
- end;
-
- QueryPerformanceFrequency(m_sw_freq );{hack}
- QueryPerformanceCounter (m_sw_start );
-
-end;
-
-{ DESTRUCT }
-destructor platform_specific.Destruct;
-var
- i : unsigned;
-
-begin
- m_pmap_window.Destruct;
-
- for i:=0 to max_images - 1 do
- m_pmap_img[i ].Destruct;
-
-end;
-
-{ CREATE_PMAP }
-procedure platform_specific.create_pmap;
-begin
- m_pmap_window.create(width ,height ,m_bpp );
-
- if m_flip_y then
- wnd.attach(
- m_pmap_window._buf ,
- m_pmap_window._width ,
- m_pmap_window._height ,
- m_pmap_window._stride )
-
- else
- wnd.attach(
- m_pmap_window._buf ,
- m_pmap_window._width ,
- m_pmap_window._height ,
- -m_pmap_window._stride )
-
-end;
-
-{ convert_pmap }
-procedure convert_pmap(dst ,src : rendering_buffer_ptr; format : pix_format_e );
-begin
- case format of
- pix_format_gray8 :
- color_conv(dst ,src ,color_conv_gray8_to_bgr24 );
-
- pix_format_gray16 :
- color_conv(dst ,src ,color_conv_gray16_to_gray8 );
-
- pix_format_rgb565 :
- color_conv(dst ,src ,color_conv_rgb565_to_rgb555 );
-
- pix_format_rgbAAA :
- color_conv(dst ,src ,color_conv_rgbAAA_to_bgr24 );
-
- pix_format_bgrAAA :
- color_conv(dst ,src ,color_conv_bgrAAA_to_bgr24 );
-
- pix_format_rgbBBA :
- color_conv(dst ,src ,color_conv_rgbBBA_to_bgr24 );
-
- pix_format_bgrABB :
- color_conv(dst ,src ,color_conv_bgrABB_to_bgr24 );
-
- pix_format_rgb24 :
- color_conv(dst ,src ,color_conv_rgb24_to_bgr24 );
-
- pix_format_rgb48 :
- color_conv(dst ,src ,color_conv_rgb48_to_bgr24 );
-
- pix_format_bgr48 :
- color_conv(dst ,src ,color_conv_bgr48_to_bgr24 );
-
- pix_format_abgr32 :
- color_conv(dst ,src ,color_conv_abgr32_to_bgra32 );
-
- pix_format_argb32 :
- color_conv(dst ,src ,color_conv_argb32_to_bgra32 );
-
- pix_format_rgba32 :
- color_conv(dst ,src ,color_conv_rgba32_to_bgra32 );
-
- pix_format_bgra64 :
- color_conv(dst ,src ,color_conv_bgra64_to_bgra32 );
-
- pix_format_abgr64 :
- color_conv(dst ,src ,color_conv_abgr64_to_bgra32 );
-
- pix_format_argb64 :
- color_conv(dst ,src ,color_conv_argb64_to_bgra32 );
-
- pix_format_rgba64 :
- color_conv(dst ,src ,color_conv_rgba64_to_bgra32 );
-
- end;
-
-end;
-
-{ DISPLAY_PMAP }
-procedure platform_specific.display_pmap;
-var
- pmap_tmp : pixel_map;
- rbuf_tmp : rendering_buffer;
-
-begin
- if m_sys_format = m_format then
- m_pmap_window.draw(dc )
-
- else
- begin
- pmap_tmp.Construct;
- pmap_tmp.create(m_pmap_window._width ,m_pmap_window._height ,m_sys_bpp );
-
- rbuf_tmp.Construct;
-
- if m_flip_y then
- rbuf_tmp.attach(pmap_tmp._buf ,pmap_tmp._width ,pmap_tmp._height ,pmap_tmp._stride )
- else
- rbuf_tmp.attach(pmap_tmp._buf ,pmap_tmp._width ,pmap_tmp._height ,-pmap_tmp._stride );
-
- convert_pmap (@rbuf_tmp ,src ,m_format );
- pmap_tmp.draw(dc );
-
- rbuf_tmp.Destruct;
- pmap_tmp.Destruct;
-
- end;
-
-end;
-
-{ LOAD_PMAP }
-function platform_specific.load_pmap;
-var
- pmap_tmp : pixel_map;
- rbuf_tmp : rendering_buffer;
-
-begin
- pmap_tmp.Construct;
-
- if not pmap_tmp.load_from_bmp(fn ) then
- begin
- result:=false;
-
- pmap_tmp.Destruct;
- exit;
-
- end;
-
- rbuf_tmp.Construct;
-
- if m_flip_y then
- rbuf_tmp.attach(pmap_tmp._buf ,pmap_tmp._width ,pmap_tmp._height ,pmap_tmp._stride )
- else
- rbuf_tmp.attach(pmap_tmp._buf ,pmap_tmp._width ,pmap_tmp._height ,-pmap_tmp._stride );
-
- m_pmap_img[idx ].create(pmap_tmp._width ,pmap_tmp._height ,m_bpp ,0 );
-
- if m_flip_y then
- dst.attach(
- m_pmap_img[idx ]._buf ,
- m_pmap_img[idx ]._width ,
- m_pmap_img[idx ]._height ,
- m_pmap_img[idx ]._stride )
- else
- dst.attach(
- m_pmap_img[idx ]._buf ,
- m_pmap_img[idx ]._width ,
- m_pmap_img[idx ]._height ,
- -m_pmap_img[idx ]._stride );
-
- case m_format of
- pix_format_gray8 :
- case pmap_tmp._bpp of
- 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_gray8 );
-
- end;
-
- pix_format_gray16 :
- case pmap_tmp._bpp of
- 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_gray16 );
-
- end;
-
- pix_format_rgb555 :
- case pmap_tmp._bpp of
- 16 : color_conv(dst ,@rbuf_tmp ,color_conv_rgb555_to_rgb555 );
- 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_rgb555 );
- 32 : color_conv(dst ,@rbuf_tmp ,color_conv_bgra32_to_rgb555 );
-
- end;
-
- pix_format_rgb565 :
- case pmap_tmp._bpp of
- 16 : color_conv(dst ,@rbuf_tmp ,color_conv_rgb555_to_rgb565 );
- 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_rgb565 );
- 32 : color_conv(dst ,@rbuf_tmp ,color_conv_bgra32_to_rgb565 );
-
- end;
-
- pix_format_rgb24 :
- case pmap_tmp._bpp of
- 16 : color_conv(dst ,@rbuf_tmp ,color_conv_rgb555_to_rgb24 );
- 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_rgb24 );
- 32 : color_conv(dst ,@rbuf_tmp ,color_conv_bgra32_to_rgb24 );
-
- end;
-
- pix_format_bgr24 :
- case pmap_tmp._bpp of
- 16 : color_conv(dst ,@rbuf_tmp ,color_conv_rgb555_to_bgr24 );
- 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_bgr24 );
- 32 : color_conv(dst ,@rbuf_tmp ,color_conv_bgra32_to_bgr24 );
-
- end;
-
- pix_format_rgb48 :
- case pmap_tmp._bpp of
- 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_rgb48 );
-
- end;
-
- pix_format_bgr48 :
- case pmap_tmp._bpp of
- 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_bgr48 );
-
- end;
-
- pix_format_abgr32 :
- case pmap_tmp._bpp of
- 16 : color_conv(dst ,@rbuf_tmp ,color_conv_rgb555_to_abgr32 );
- 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_abgr32 );
- 32 : color_conv(dst ,@rbuf_tmp ,color_conv_bgra32_to_abgr32 );
-
- end;
-
- pix_format_argb32 :
- case pmap_tmp._bpp of
- 16 : color_conv(dst ,@rbuf_tmp ,color_conv_rgb555_to_argb32 );
- 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_argb32 );
- 32 : color_conv(dst ,@rbuf_tmp ,color_conv_bgra32_to_argb32 );
-
- end;
-
- pix_format_bgra32 :
- case pmap_tmp._bpp of
- 16 : color_conv(dst ,@rbuf_tmp ,color_conv_rgb555_to_bgra32 );
- 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_bgra32 );
- 32 : color_conv(dst ,@rbuf_tmp ,color_conv_bgra32_to_bgra32 );
-
- end;
-
- pix_format_rgba32 :
- case pmap_tmp._bpp of
- 16 : color_conv(dst ,@rbuf_tmp ,color_conv_rgb555_to_rgba32 );
- 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_rgba32 );
- 32 : color_conv(dst ,@rbuf_tmp ,color_conv_bgra32_to_rgba32 );
-
- end;
-
- pix_format_abgr64 :
- case pmap_tmp._bpp of
- 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_abgr64 );
-
- end;
-
- pix_format_argb64 :
- case pmap_tmp._bpp of
- 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_argb64 );
-
- end;
-
- pix_format_bgra64 :
- case pmap_tmp._bpp of
- 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_bgra64 );
-
- end;
-
- pix_format_rgba64 :
- case pmap_tmp._bpp of
- 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_rgba64 );
-
- end;
-
- end;
-
- pmap_tmp.Destruct;
- rbuf_tmp.Destruct;
-
- result:=true;
-
-end;
-
-{ SAVE_PMAP }
-function platform_specific.save_pmap;
-var
- pmap_tmp : pixel_map;
- rbuf_tmp : rendering_buffer;
-
-begin
- if m_sys_format = m_format then
- begin
- result:=m_pmap_img[idx ].save_as_bmp(fn );
-
- exit;
-
- end;
-
- pmap_tmp.Construct;
- pmap_tmp.create(
- m_pmap_img[idx ]._width ,
- m_pmap_img[idx ]._height ,
- m_sys_bpp );
-
- rbuf_tmp.Construct;
-
- if m_flip_y then
- rbuf_tmp.attach(pmap_tmp._buf ,pmap_tmp._width ,pmap_tmp._height ,pmap_tmp._stride )
- else
- rbuf_tmp.attach(pmap_tmp._buf ,pmap_tmp._width ,pmap_tmp._height ,-pmap_tmp._stride );
-
- convert_pmap(@rbuf_tmp ,src ,m_format );
-
- result:=pmap_tmp.save_as_bmp(fn );
-
- rbuf_tmp.Destruct;
- pmap_tmp.Destruct;
-
-end;
-
-{ TRANSLATE }
-function platform_specific.translate;
-begin
- if keycode > 255 then
- m_last_translated_key:=0
- else
- m_last_translated_key:=m_keymap[keycode ];
-
-end;
-
-{ CONSTRUCT }
-constructor platform_support.Construct;
-var
- i : unsigned;
-
-begin
-{OpenCPL++}
- if specific <> NIL then
- m_specific:=specific
-
- else
-{/OpenCPL++}
- new(m_specific ,Construct(format_ ,flip_y_ ) );
-
- m_ctrls.Construct;
- m_rbuf_window.Construct;
-
- for i:=0 to max_images - 1 do
- m_rbuf_img[i ].Construct;
-
- m_resize_mtx.Construct;
-
- m_format:=format_;
-
- m_bpp:=m_specific.m_bpp;
-
- m_window_flags:=0;
- m_wait_mode :=true;
- m_flip_y :=flip_y_;
-
- m_initial_width :=10;
- m_initial_height:=10;
-
- m_caption:='Anti-Grain Geometry Application'#0;
-
-end;
-
-{ DESTRUCT }
-destructor platform_support.Destruct;
-var
- i : unsigned;
-
-begin
- dispose(m_specific ,Destruct );
-
- m_ctrls.Destruct;
- m_rbuf_window.Destruct;
-
- for i:=0 to max_images - 1 do
- m_rbuf_img[i ].Destruct;
-
-end;
-
-{ CAPTION_ }
-procedure platform_support.caption_;
-begin
- m_caption:=cap + #0;
-
- dec(byte(m_caption[0 ] ) );
-
- if m_specific.m_hwnd <> 0 then
- SetWindowText(m_specific.m_hwnd ,@m_caption[1 ] );
-
-end;
-
-{ LOAD_IMG }
-function platform_support.load_img;
-var
- f : file;
-
-begin
- if idx < max_images then
- begin
- file_:=file_ + _img_ext;
-
- AssignFile(f ,file_ );
- reset (f ,1 );
-
- if ioresult <> 0 then
- file_:='bmp\' + file_;
-
- close(f );
-
- result:=m_specific.load_pmap(file_ ,idx ,@m_rbuf_img[idx ] );
-
- end
- else
- result:=true;
-
-end;
-
-{ SAVE_IMG }
-function platform_support.save_img;
-begin
- if idx < max_images then
- result:=m_specific.save_pmap(file_ ,idx ,@m_rbuf_img[idx ] )
- else
- result:=true;
-
-end;
-
-{ CREATE_IMG }
-function platform_support.create_img;
-begin
- if idx < max_images then
- begin
- if width_ = 0 then
- width_:=m_specific.m_pmap_window._width;
-
- if height_ = 0 then
- height_:=m_specific.m_pmap_window._height;
-
- m_specific.m_pmap_img[idx ].create(width_ ,height_ ,m_specific.m_bpp );
-
- if m_flip_y then
- m_rbuf_img[idx ].attach(
- m_specific.m_pmap_img[idx ]._buf ,
- m_specific.m_pmap_img[idx ]._width ,
- m_specific.m_pmap_img[idx ]._height ,
- m_specific.m_pmap_img[idx ]._stride )
- else
- m_rbuf_img[idx ].attach(
- m_specific.m_pmap_img[idx ]._buf ,
- m_specific.m_pmap_img[idx ]._width ,
- m_specific.m_pmap_img[idx ]._height ,
- -m_specific.m_pmap_img[idx ]._stride );
-
- result:=true;
-
- end
- else
- result:=false;
-
-end;
-
-{ get_key_flags }
-function get_key_flags(wflags : int ) : unsigned;
-var
- flags : unsigned;
-
-begin
- flags:=0;
-
- if wflags and MK_LBUTTON <> 0 then
- flags:=flags or mouse_left;
-
- if wflags and MK_RBUTTON <> 0 then
- flags:=flags or mouse_right;
-
- if wflags and MK_SHIFT <> 0 then
- flags:=flags or kbd_shift;
-
- if wflags and MK_CONTROL <> 0 then
- flags:=flags or kbd_ctrl;
-
- result:=flags;
-
-end;
-
-{ window_proc }
-function window_proc(Wnd : HWND; Msg : UINT; WPar : WParam; LPar : LParam ) : LResult; stdcall;
-var
- ps : TPaintStruct;
- app : platform_support_ptr;
- ret : LResult;
-
- dc ,paintDC : HDC;
-
- left ,up ,right ,down : boolean;
-
- ss : shortstring;
-
-begin
- app:=platform_support_ptr(GetWindowLong(Wnd ,GWL_USERDATA ) );
-
- if app = NIL then
- begin
- if Msg = WM_DESTROY then
- begin
- PostQuitMessage(0 );
-
- result:=0;
-
- exit;
-
- end;
-
- result:=DefWindowProc(Wnd ,msg ,WPar ,LPar );
-
- exit;
-
- end;
-
- dc:=GetDC(app.m_specific.m_hwnd );
-
- app.m_specific.m_current_dc:=dc;
-
- ret:=0;
-
- case Msg of
- WM_CREATE :
- NoP;
-
- WM_SIZE :
- begin
- app.m_specific.create_pmap(int16(int32u_(LPar ).low ) ,int16(int32u_(LPar ).high ) ,app.rbuf_window );
- app.trans_affine_resizing_(int16(int32u_(LPar ).low ) ,int16(int32u_(LPar ).high ) );
-
- app.on_resize(int16(int32u_(LPar ).low ) ,int16(int32u_(LPar ).high ) );
- app.force_redraw;
-
- end;
-
- WM_ERASEBKGND :
- NoP;
-
- WM_LBUTTONDOWN :
- begin
- SetCapture(app.m_specific.m_hwnd );
-
- app.m_specific.m_cur_x:=int16(int32u_(LPar ).low );
-
- if app._flip_y then
- app.m_specific.m_cur_y:=int(app.rbuf_window._height ) - int16(int32u_(LPar ).high )
- else
- app.m_specific.m_cur_y:=int16(int32u_(LPar ).high );
-
- app.m_specific.m_input_flags:=mouse_left or get_key_flags(WPar );
-
- app.m_ctrls.set_cur(app.m_specific.m_cur_x ,app.m_specific.m_cur_y );
-
- if app.m_ctrls.on_mouse_button_down(app.m_specific.m_cur_x ,app.m_specific.m_cur_y ) then
- begin
- app.on_ctrl_change;
- app.force_redraw;
-
- end
- else
- if app.m_ctrls.in_rect(app.m_specific.m_cur_x ,app.m_specific.m_cur_y ) then
- if app.m_ctrls.set_cur(app.m_specific.m_cur_x ,app.m_specific.m_cur_y ) then
- begin
- app.on_ctrl_change;
- app.force_redraw;
-
- end
- else
- else
- app.on_mouse_button_down(
- app.m_specific.m_cur_x ,
- app.m_specific.m_cur_y ,
- app.m_specific.m_input_flags );
-
- end;
-
- WM_LBUTTONUP :
- begin
- ReleaseCapture;
-
- app.m_specific.m_cur_x:=int16(int32u_(LPar ).low );
-
- if app._flip_y then
- app.m_specific.m_cur_y:=int(app.rbuf_window._height ) - int16(int32u_(LPar ).high )
- else
- app.m_specific.m_cur_y:=int16(int32u_(LPar ).high );
-
- app.m_specific.m_input_flags:=mouse_left or get_key_flags(WPar );
-
- if app.m_ctrls.on_mouse_button_up(app.m_specific.m_cur_x ,app.m_specific.m_cur_y ) then
- begin
- app.on_ctrl_change;
- app.force_redraw;
-
- end;
-
- app.on_mouse_button_up(
- app.m_specific.m_cur_x ,
- app.m_specific.m_cur_y ,
- app.m_specific.m_input_flags );
-
- end;
-
- WM_RBUTTONDOWN :
- begin
- SetCapture(app.m_specific.m_hwnd );
-
- app.m_specific.m_cur_x:=int16(int32u_(LPar ).low );
-
- if app._flip_y then
- app.m_specific.m_cur_y:=int(app.rbuf_window._height ) - int16(int32u_(LPar ).high )
- else
- app.m_specific.m_cur_y:=int16(int32u_(LPar ).high );
-
- app.m_specific.m_input_flags:=mouse_right or get_key_flags(WPar );
-
- app.on_mouse_button_down(
- app.m_specific.m_cur_x ,
- app.m_specific.m_cur_y ,
- app.m_specific.m_input_flags );
-
- end;
-
- WM_RBUTTONUP :
- begin
- ReleaseCapture;
-
- app.m_specific.m_cur_x:=int16(int32u_(LPar ).low );
-
- if app._flip_y then
- app.m_specific.m_cur_y:=int(app.rbuf_window._height ) - int16(int32u_(LPar ).high )
- else
- app.m_specific.m_cur_y:=int16(int32u_(LPar ).high );
-
- app.m_specific.m_input_flags:=mouse_right or get_key_flags(WPar );
-
- app.on_mouse_button_up(
- app.m_specific.m_cur_x ,
- app.m_specific.m_cur_y ,
- app.m_specific.m_input_flags );
-
- end;
-
- WM_MOUSEMOVE :
- begin
- app.m_specific.m_cur_x:=int16(int32u_(LPar ).low );
-
- if app._flip_y then
- app.m_specific.m_cur_y:=int(app.rbuf_window._height ) - int16(int32u_(LPar ).high )
- else
- app.m_specific.m_cur_y:=int16(int32u_(LPar ).high );
-
- app.m_specific.m_input_flags:=get_key_flags(WPar );
-
- if app.m_ctrls.on_mouse_move(
- app.m_specific.m_cur_x ,
- app.m_specific.m_cur_y ,
- ((app.m_specific.m_input_flags and mouse_left ) <> 0 ) ) then
- begin
- app.on_ctrl_change;
- app.force_redraw;
-
- end
- else
- if not app.m_ctrls.in_rect(app.m_specific.m_cur_x ,app.m_specific.m_cur_y ) then
- app.on_mouse_move(
- app.m_specific.m_cur_x ,
- app.m_specific.m_cur_y ,
- app.m_specific.m_input_flags );
-
- end;
-
- WM_SYSKEYDOWN ,WM_KEYDOWN :
- begin
- app.m_specific.m_last_translated_key:=0;
-
- case WPar of
- VK_CONTROL :
- app.m_specific.m_input_flags:=app.m_specific.m_input_flags or kbd_ctrl;
-
- VK_SHIFT :
- app.m_specific.m_input_flags:=app.m_specific.m_input_flags or kbd_shift;
-
- VK_F4 :
- if LPar and $20000000 <> 0 then
- app.quit
- else
- app.m_specific.translate(WPar );
-
- else
- app.m_specific.translate(WPar );
-
- end;
-
- if app.m_specific.m_last_translated_key <> 0 then
- begin
- left :=false;
- up :=false;
- right:=false;
- down :=false;
-
- case app.m_specific.m_last_translated_key of
- key_left :
- left:=true;
-
- key_up :
- up:=true;
-
- key_right :
- right:=true;
-
- key_down :
- down:=true;
-
- key_f2 :
- begin
- app.copy_window_to_img(max_images - 1 );
- app.save_img (max_images - 1 ,'screenshot.bmp' );
-
- end;
-
- end;
-
- if app._window_flags and window_process_all_keys <> 0 then
- app.on_key(
- app.m_specific.m_cur_x ,
- app.m_specific.m_cur_y ,
- app.m_specific.m_last_translated_key ,
- app.m_specific.m_input_flags )
-
- else
- if app.m_ctrls.on_arrow_keys(left ,right ,down ,up ) then
- begin
- app.on_ctrl_change;
- app.force_redraw;
-
- end
- else
- app.on_key(
- app.m_specific.m_cur_x ,
- app.m_specific.m_cur_y ,
- app.m_specific.m_last_translated_key ,
- app.m_specific.m_input_flags );
-
- end;
-
- end;
-
- WM_SYSKEYUP ,WM_KEYUP :
- begin
- app.m_specific.m_last_translated_key:=0;
-
- case WPar of
- VK_CONTROL :
- app.m_specific.m_input_flags:=app.m_specific.m_input_flags and (not kbd_ctrl );
-
- VK_SHIFT :
- app.m_specific.m_input_flags:=app.m_specific.m_input_flags and (not kbd_shift );
-
- end;
-
- end;
-
- WM_CHAR ,WM_SYSCHAR :
- if app.m_specific.m_last_translated_key = 0 then
- app.on_key(
- app.m_specific.m_cur_x ,
- app.m_specific.m_cur_y ,
- WPar ,
- app.m_specific.m_input_flags );
-
- WM_PAINT :
- begin
- paintDC:=BeginPaint(Wnd ,ps );
-
- app.m_specific.m_current_dc:=paintDC;
-
- if app.m_specific.m_redraw_flag then
- begin
- app.on_draw;
-
- app.m_specific.m_redraw_flag:=false;
-
- end;
-
- app.m_specific.display_pmap(paintDC ,app.rbuf_window );
- app.on_post_draw (pointer(@paintDC ) );
-
- app.m_specific.m_current_dc:=0;
-
- EndPaint(Wnd ,ps );
-
- end;
-
- WM_COMMAND :
- NoP;
-
- WM_DESTROY :
- PostQuitMessage(0 );
-
- else
- ret:=DefWindowProc(Wnd ,Msg ,WPar ,LPar );
-
- end;
-
- app.m_specific.m_current_dc:=0;
-
- ReleaseDC(app.m_specific.m_hwnd ,dc );
-
- result:=ret;
-
-end;
-
-{ INIT }
-function platform_support.init;
-var
- wc : WNDCLASS;
- rct : TRect;
-
- wflags : int;
-
-begin
- result:=false;
-
- if m_specific.m_sys_format = pix_format_undefined then
- exit;
-
- m_window_flags:=flags;
-
- wflags:=CS_OWNDC or CS_VREDRAW or CS_HREDRAW;
-
- wc.lpszClassName:='AGGAppClass';
- wc.lpfnWndProc :=@window_proc;
- wc.style :=wflags;
- wc.hInstance :=hInstance;
- wc.hIcon :=LoadIcon (0, IDI_APPLICATION);
- wc.hCursor :=LoadCursor(0, IDC_ARROW);
- wc.hbrBackground:=COLOR_WINDOW + 1;
- wc.lpszMenuName :='AGGAppMenu';
- wc.cbClsExtra :=0;
- wc.cbWndExtra :=0;
-
- RegisterClass(wc );
-
- wflags:=WS_OVERLAPPED or WS_CAPTION or WS_SYSMENU or WS_MINIMIZEBOX;
-
- if m_window_flags and window_resize <> 0 then
- wflags:=wflags or WS_THICKFRAME or WS_MAXIMIZEBOX;
-
- m_specific.m_hwnd:=
- CreateWindow(
- 'AGGAppClass' ,@m_caption[1 ] ,wflags ,
- 10 ,10 ,width_ ,height_ ,
- 0 ,0 ,hInstance ,0 );
-
- if m_specific.m_hwnd = 0 then
- exit;
-
- GetClientRect(m_specific.m_hwnd ,rct );
-
- MoveWindow(
- m_specific.m_hwnd , // handle to window
- 10 , // horizontal position
- 10 , // vertical position
- width_ + (width_ - (rct.right - rct.left ) ) ,
- height_ + (height_ - (rct.bottom - rct.top ) ) ,
- false );
-
- SetWindowLong(m_specific.m_hwnd ,GWL_USERDATA ,ptrcomp(@self ) );
-
- m_specific.create_pmap(width_ ,height_ ,@m_rbuf_window );
-
- m_initial_width :=width_;
- m_initial_height:=height_;
-
- on_init;
-
- m_specific.m_redraw_flag:=true;
-
- ShowWindow(m_specific.m_hwnd ,SW_SHOW );
-
- result:=true;
-
-end;
-
-{ RUN }
-function platform_support.run;
-var
- msg : TMsg;
-
-begin
- repeat
- if m_wait_mode then
- begin
- if not GetMessage(msg ,0 ,0 ,0 ) then
- break;
-
- TranslateMessage(msg );
- DispatchMessage (msg );
-
- end
- else
- if PeekMessage(msg ,0 ,0 ,0 ,PM_REMOVE ) then
- begin
- TranslateMessage(msg );
-
- if msg.message = WM_QUIT then
- break;
-
- DispatchMessage(msg );
-
- end
- else
- on_idle;
-
- until false;
-
- result:=msg.wParam;
-
-end;
-
-{ QUIT }
-procedure platform_support.quit;
-begin
- if m_specific.m_hwnd <> 0 then
- DestroyWindow(m_specific.m_hwnd );
-
- PostQuitMessage(0 );
-
-end;
-
-{ _FORMAT }
-function platform_support._format;
-begin
- result:=m_format;
-
-end;
-
-{ _FLIP_Y }
-function platform_support._flip_y;
-begin
- result:=m_flip_y;
-
-end;
-
-{ _BPP }
-function platform_support._bpp;
-begin
- result:=m_bpp;
-
-end;
-
-{ _WAIT_MODE }
-function platform_support._wait_mode;
-begin
- result:=m_wait_mode;
-
-end;
-
-{ WAIT_MODE_ }
-procedure platform_support.wait_mode_;
-begin
- m_wait_mode:=wait_mode;
-
-end;
-
-{ FORCE_REDRAW }
-procedure platform_support.force_redraw;
-begin
- m_specific.m_redraw_flag:=true;
-
- InvalidateRect(m_specific.m_hwnd ,0 ,false );
-
-end;
-
-{ UPDATE_WINDOW }
-procedure platform_support.update_window;
-var
- dc : HDC;
-
-begin
- dc:=GetDC(m_specific.m_hwnd );
-
- m_specific.display_pmap(dc ,@m_rbuf_window );
-
- ReleaseDC(m_specific.m_hwnd ,dc );
-
-end;
-
-{ RBUF_WINDOW }
-function platform_support.rbuf_window;
-begin
- result:=@m_rbuf_window;
-
-end;
-
-{ RBUF_IMG }
-function platform_support.rbuf_img;
-begin
- result:=@m_rbuf_img[idx ];
-
-end;
-
-{ _IMG_EXT }
-function platform_support._img_ext;
-begin
- result:='.bmp';
-
-end;
-
-{ COPY_IMG_TO_WINDOW }
-procedure platform_support.copy_img_to_window;
-begin
- if (idx < max_images ) and
- (rbuf_img(idx )._buf <> NIL ) then
- rbuf_window.copy_from(rbuf_img(idx ) );
-
-end;
-
-{ COPY_WINDOW_TO_IMG }
-procedure platform_support.copy_window_to_img;
-begin
- if idx < max_images then
- begin
- create_img(idx ,rbuf_window._width ,rbuf_window._height );
- rbuf_img (idx ).copy_from(rbuf_window );
-
- end;
-
-end;
-
-{ COPY_IMG_TO_IMG }
-procedure platform_support.copy_img_to_img;
-begin
- if (idx_from < max_images ) and
- (idx_to < max_images ) and
- (rbuf_img(idx_from )._buf <> NIL ) then
- begin
- create_img(
- idx_to ,
- rbuf_img(idx_from )._width ,
- rbuf_img(idx_from )._height );
-
- rbuf_img(idx_to ).copy_from(rbuf_img(idx_from ) );
-
- end;
-
-end;
-
-{ ON_INIT }
-procedure platform_support.on_init;
-begin
-end;
-
-{ ON_RESIZE }
-procedure platform_support.on_resize;
-begin
-end;
-
-{ ON_IDLE }
-procedure platform_support.on_idle;
-begin
-end;
-
-{ ON_MOUSE_MOVE }
-procedure platform_support.on_mouse_move;
-begin
-end;
-
-{ ON_MOUSE_BUTTON_DOWN }
-procedure platform_support.on_mouse_button_down;
-begin
-end;
-
-{ ON_MOUSE_BUTTON_UP }
-procedure platform_support.on_mouse_button_up;
-begin
-end;
-
-{ ON_KEY }
-procedure platform_support.on_key;
-begin
-end;
-
-{ ON_CTRL_CHANGE }
-procedure platform_support.on_ctrl_change;
-begin
-end;
-
-{ ON_DRAW }
-procedure platform_support.on_draw;
-begin
-end;
-
-{ ON_POST_DRAW }
-procedure platform_support.on_post_draw;
-begin
-end;
-
-{ ADD_CTRL }
-procedure platform_support.add_ctrl;
-begin
- m_ctrls.add(c );
-
- c.transform(@m_resize_mtx );
-
-end;
-
-{ TRANS_AFFINE_RESIZING_ }
-procedure platform_support.trans_affine_resizing_;
-var
- vp : trans_viewport;
- ts : trans_affine_scaling;
-
-begin
- if m_window_flags and window_keep_aspect_ratio <> 0 then
- begin
- //double sx = double(width) / double(m_initial_width);
- //double sy = double(height) / double(m_initial_height);
- //if(sy < sx) sx = sy;
- //m_resize_mtx = trans_affine_scaling(sx, sx);
-
- vp.Construct;
- vp.preserve_aspect_ratio(0.5 ,0.5 ,aspect_ratio_meet );
-
- vp.device_viewport(0 ,0 ,width_ ,height_ );
- vp.world_viewport (0 ,0 ,m_initial_width ,m_initial_height );
-
- vp.to_affine(@m_resize_mtx );
-
- end
- else
- begin
- ts.Construct(
- width_ / m_initial_width ,
- height_ / m_initial_height );
-
- m_resize_mtx.assign(@ts );
-
- end;
-
-end;
-
-{ _TRANS_AFFINE_RESIZING }
-function platform_support._trans_affine_resizing;
-begin
- result:=@m_resize_mtx;
-
-end;
-
-{ _WIDTH }
-function platform_support._width;
-begin
- result:=m_rbuf_window._width;
-
-end;
-
-{ _HEIGHT }
-function platform_support._height;
-begin
- result:=m_rbuf_window._height;
-
-end;
-
-{ _INITIAL_WIDTH }
-function platform_support._initial_width;
-begin
- result:=m_initial_width;
-
-end;
-
-{ _INITIAL_HEIGHT }
-function platform_support._initial_height;
-begin
- result:=m_initial_height;
-
-end;
-
-{ _WINDOW_FLAGS }
-function platform_support._window_flags;
-begin
- result:=m_window_flags;
-
-end;
-
-{ _RAW_DISPLAY_HANDLER }
-function platform_support._raw_display_handler;
-begin
- result:=@m_specific.m_current_dc;
-
-end;
-
-{ MESSAGE_ }
-procedure platform_support.message_;
-begin
- MessageBox(m_specific.m_hwnd ,@msg[0 ] ,'AGG Message' ,MB_OK );
-
-end;
-
-{ START_TIMER }
-procedure platform_support.start_timer;
-begin
- QueryPerformanceCounter({m_specific.}m_sw_start );{hack}
-
-end;
-
-{ ELAPSED_TIME }
-function platform_support.elapsed_time;
-var
- stop : TLargeInteger;
-
-begin
- QueryPerformanceCounter(stop );
-
- result:=(stop - {m_specific.}m_sw_start ) * 1000.0 / {m_specific.}m_sw_freq;{hack}
-
-end;
-
-{ FULL_FILE_NAME }
-function platform_support.full_file_name;
-begin
- result:=file_name;
-
-end;
-
-{ FILE_SOURCE }
-function platform_support.file_source;
-var
- f : file;
- e : integer;
-
-begin
- result:=fname;
-
- e:=ioresult;
-
- AssignFile(f ,result );
- reset (f ,1 );
-
- if ioresult <> 0 then
- result:=path + '\' + fname;
-
- close(f );
-
- e:=ioresult;
-
-end;
-
-END.
-
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// class platform_support
+//
+// It's not a part of the AGG library, it's just a helper class to create
+// interactive demo examples. Since the examples should not be too complex
+// this class is provided to support some very basic interactive graphical
+// funtionality, such as putting the rendered image to the window, simple
+// keyboard and mouse input, window resizing, setting the window title,
+// and catching the "idle" events.
+//
+// The most popular platforms are:
+//
+// Windows-32 API
+// X-Window API
+// SDL library (see http://www.libsdl.org/)
+// MacOS C/C++ API
+//
+// All the system dependent stuff sits in the platform_specific class.
+// The platform_support class has just a pointer to it and it's
+// the responsibility of the implementation to create/delete it.
+// This class being defined in the implementation file can have
+// any platform dependent stuff such as HWND, X11 Window and so on.
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 16.12.2005-Milano: platform_specific
+// 15.12.2005-Milano: platform_support
+// 12.12.2005-Milano: Unit port establishment
+//
+{ agg_platform_support.pas }
+unit
+ agg_platform_support ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+{$I- }
+uses
+ Windows ,Messages ,
+ agg_basics ,
+ agg_ctrl ,
+ agg_rendering_buffer ,
+ agg_trans_affine ,
+ agg_trans_viewport ,
+ agg_win32_bmp ,
+ agg_color_conv ;
+
+{ TYPES DEFINITION }
+const
+//----------------------------------------------------------window_flag_e
+// These are flags used in method init(). Not all of them are
+// applicable on different platforms, for example the win32_api
+// cannot use a hardware buffer (window_hw_buffer).
+// The implementation should simply ignore unsupported flags.
+ window_resize = 1;
+ window_hw_buffer = 2;
+ window_keep_aspect_ratio = 4;
+ window_process_all_keys = 8;
+
+type
+//-----------------------------------------------------------pix_format_e
+// Possible formats of the rendering buffer. Initially I thought that it's
+// reasonable to create the buffer and the rendering functions in
+// accordance with the native pixel format of the system because it
+// would have no overhead for pixel format conersion.
+// But eventually I came to a conclusion that having a possibility to
+// convert pixel formats on demand is a good idea. First, it was X11 where
+// there lots of different formats and visuals and it would be great to
+// render everything in, say, RGB-24 and display it automatically without
+// any additional efforts. The second reason is to have a possibility to
+// debug renderers for different pixel formats and colorspaces having only
+// one computer and one system.
+//
+// This stuff is not included into the basic AGG functionality because the
+// number of supported pixel formats (and/or colorspaces) can be great and
+// if one needs to add new format it would be good only to add new
+// rendering files without having to modify any existing ones (a general
+// principle of incapsulation and isolation).
+//
+// Using a particular pixel format doesn't obligatory mean the necessity
+// of software conversion. For example, win32 API can natively display
+// gray8, 15-bit RGB, 24-bit BGR, and 32-bit BGRA formats.
+// This list can be (and will be!) extended in future.
+ pix_format_e = (
+
+ pix_format_undefined , // By default. No conversions are applied
+ pix_format_bw, // 1 bit per color B/W
+ pix_format_gray8, // Simple 256 level grayscale
+ pix_format_gray16, // Simple 65535 level grayscale
+ pix_format_rgb555, // 15 bit rgb. Depends on the byte ordering!
+ pix_format_rgb565, // 16 bit rgb. Depends on the byte ordering!
+ pix_format_rgbAAA, // 30 bit rgb. Depends on the byte ordering!
+ pix_format_rgbBBA, // 32 bit rgb. Depends on the byte ordering!
+ pix_format_bgrAAA, // 30 bit bgr. Depends on the byte ordering!
+ pix_format_bgrABB, // 32 bit bgr. Depends on the byte ordering!
+ pix_format_rgb24, // R-G-B, one byte per color component
+ pix_format_bgr24, // B-G-R, native win32 BMP format.
+ pix_format_rgba32, // R-G-B-A, one byte per color component
+ pix_format_argb32, // A-R-G-B, native MAC format
+ pix_format_abgr32, // A-B-G-R, one byte per color component
+ pix_format_bgra32, // B-G-R-A, native win32 BMP format
+ pix_format_rgb48, // R-G-B, 16 bits per color component
+ pix_format_bgr48, // B-G-R, native win32 BMP format.
+ pix_format_rgba64, // R-G-B-A, 16 bits byte per color component
+ pix_format_argb64, // A-R-G-B, native MAC format
+ pix_format_abgr64, // A-B-G-R, one byte per color component
+ pix_format_bgra64, // B-G-R-A, native win32 BMP format
+
+ end_of_pix_formats );
+
+const
+//-------------------------------------------------------------input_flag_e
+// Mouse and keyboard flags. They can be different on different platforms
+// and the ways they are obtained are also different. But in any case
+// the system dependent flags should be mapped into these ones. The meaning
+// of that is as follows. For example, if kbd_ctrl is set it means that the
+// ctrl key is pressed and being held at the moment. They are also used in
+// the overridden methods such as on_mouse_move(), on_mouse_button_down(),
+// on_mouse_button_dbl_click(), on_mouse_button_up(), on_key().
+// In the method on_mouse_button_up() the mouse flags have different
+// meaning. They mean that the respective button is being released, but
+// the meaning of the keyboard flags remains the same.
+// There's absolut minimal set of flags is used because they'll be most
+// probably supported on different platforms. Even the mouse_right flag
+// is restricted because Mac's mice have only one button, but AFAIK
+// it can be simulated with holding a special key on the keydoard.
+ mouse_left = 1;
+ mouse_right = 2;
+ kbd_shift = 4;
+ kbd_ctrl = 8;
+
+//--------------------------------------------------------------key_code_e
+// Keyboard codes. There's also a restricted set of codes that are most
+// probably supported on different platforms. Any platform dependent codes
+// should be converted into these ones. There're only those codes are
+// defined that cannot be represented as printable ASCII-characters.
+// All printable ASCII-set can be used in a regilar C/C++ manner:
+// ' ', 'A', '0' '+' and so on.
+// Since the clasas is used for creating very simple demo-applications
+// we don't need very rich possibilities here, just basic ones.
+// Actually the numeric key codes are taken from the SDL library, so,
+// the implementation of the SDL support does not require any mapping.
+// ASCII set. Should be supported everywhere
+ key_backspace = 8;
+ key_tab = 9;
+ key_clear = 12;
+ key_return = 13;
+ key_pause = 19;
+ key_escape = 27;
+
+// Keypad
+ key_delete = 127;
+ key_kp0 = 256;
+ key_kp1 = 257;
+ key_kp2 = 258;
+ key_kp3 = 259;
+ key_kp4 = 260;
+ key_kp5 = 261;
+ key_kp6 = 262;
+ key_kp7 = 263;
+ key_kp8 = 264;
+ key_kp9 = 265;
+ key_kp_period = 266;
+ key_kp_divide = 267;
+ key_kp_multiply = 268;
+ key_kp_minus = 269;
+ key_kp_plus = 270;
+ key_kp_enter = 271;
+ key_kp_equals = 272;
+
+// Arrow-keys and stuff
+ key_up = 273;
+ key_down = 274;
+ key_right = 275;
+ key_left = 276;
+ key_insert = 277;
+ key_home = 278;
+ key_end = 279;
+ key_page_up = 280;
+ key_page_down = 281;
+
+// Functional keys. You'd better avoid using
+// f11...f15 in your applications if you want
+// the applications to be portable
+ key_f1 = 282;
+ key_f2 = 283;
+ key_f3 = 284;
+ key_f4 = 285;
+ key_f5 = 286;
+ key_f6 = 287;
+ key_f7 = 288;
+ key_f8 = 289;
+ key_f9 = 290;
+ key_f10 = 291;
+ key_f11 = 292;
+ key_f12 = 293;
+ key_f13 = 294;
+ key_f14 = 295;
+ key_f15 = 296;
+
+// The possibility of using these keys is
+// very restricted. Actually it's guaranteed
+// only in win32_api and win32_sdl implementations
+ key_numlock = 300;
+ key_capslock = 301;
+ key_scrollock = 302;
+
+ max_ctrl = 128;
+
+type
+//----------------------------------------------------------ctrl_container
+// A helper class that contains pointers to a number of controls.
+// This class is used to ease the event handling with controls.
+// The implementation should simply call the appropriate methods
+// of this class when appropriate events occure.
+ crtl_container_ptr = ^ctrl_container;
+ ctrl_container = object
+ m_ctrl : array[0..max_ctrl - 1 ] of ctrl_ptr;
+
+ m_num_ctrl : unsigned;
+ m_cur_ctrl : int;
+
+ constructor Construct;
+ destructor Destruct;
+
+ procedure add(c : ctrl_ptr );
+
+ function in_rect(x ,y : double ) : boolean;
+
+ function on_mouse_button_down(x ,y : double ) : boolean;
+ function on_mouse_button_up (x ,y : double ) : boolean;
+
+ function on_mouse_move(x ,y : double; button_flag : boolean ) : boolean;
+ function on_arrow_keys(left ,right ,down ,up : boolean ) : boolean;
+
+ function set_cur(x ,y : double ) : boolean;
+
+ end;
+
+//---------------------------------------------------------platform_support
+// This class is a base one to the apllication classes. It can be used
+// as follows:
+//
+// the_application = object(platform_support )
+//
+// constructor Construct(bpp : unsigned; flip_y : boolean );
+// . . .
+//
+// //override stuff . . .
+// procedure on_init; virtual;
+// procedure on_draw; virtual;
+// procedure on_resize(sx ,sy : int ); virtual;
+// // . . . and so on, see virtual functions
+//
+// //any your own stuff . . .
+// };
+//
+// VAR
+// app : the_application;
+//
+// BEGIN
+// app.Construct(pix_format_rgb24 ,true );
+// app.caption ("AGG Example. Lion" );
+//
+// if app.init(500 ,400 ,window_resize ) then
+// app.run;
+//
+// app.Destruct;
+//
+// END.
+//
+const
+ max_images = 16;
+
+var
+// Hmmm, I had to rip the fields below out of the platform_specific object,
+// because being them the part of that object/class, the corresponding
+// Windows API calls QueryPerformanceXXX are working NOT!.
+// Anyway, since we use usually only one instance of platform_specific in
+// our agg demos, it's okay to do that this way. See {hack}.
+ m_sw_freq ,
+ m_sw_start : int64;
+
+type
+ platform_specific_ptr = ^platform_specific;
+ platform_specific = object
+ m_format ,
+ m_sys_format : pix_format_e;
+
+ m_flip_y : boolean;
+ m_bpp ,
+ m_sys_bpp : unsigned;
+ m_hwnd : HWND;
+
+ m_pmap_window : pixel_map;
+ m_pmap_img : array[0..max_images - 1 ] of pixel_map;
+
+ m_keymap : array[0..255 ] of unsigned;
+
+ m_last_translated_key : unsigned;
+
+ m_cur_x ,
+ m_cur_y : int;
+
+ m_input_flags : unsigned;
+ m_redraw_flag : boolean;
+ m_current_dc : HDC;
+
+ //m_sw_freq ,
+ //m_sw_start : int64;{hack}
+
+ constructor Construct(format : pix_format_e; flip_y : boolean );
+ destructor Destruct; {OpenCPL++} virtual; {/OpenCPL++}
+
+ procedure create_pmap (width ,height : unsigned; wnd : rendering_buffer_ptr ); {OpenCPL++} virtual; {/OpenCPL++}
+ procedure display_pmap(dc : HDC; src : rendering_buffer_ptr ); {OpenCPL++} virtual; {/OpenCPL++}
+
+ function load_pmap(fn : shortstring; idx : unsigned; dst : rendering_buffer_ptr ) : boolean;
+ function save_pmap(fn : shortstring; idx : unsigned; src : rendering_buffer_ptr ) : boolean;
+
+ function translate(keycode : unsigned ) : unsigned;
+
+ end;
+
+ platform_support_ptr = ^platform_support;
+ platform_support = object
+ m_specific : platform_specific_ptr;
+ m_ctrls : ctrl_container;
+
+ m_format : pix_format_e;
+
+ m_bpp : unsigned;
+
+ m_rbuf_window : rendering_buffer;
+ m_rbuf_img : array[0..max_images - 1 ] of rendering_buffer;
+
+ m_window_flags : unsigned;
+ m_wait_mode ,
+ m_flip_y : boolean; // flip_y - true if you want to have the Y-axis flipped vertically
+ m_caption : shortstring;
+ m_resize_mtx : trans_affine;
+
+ m_initial_width ,
+ m_initial_height : int;
+
+ constructor Construct(format_ : pix_format_e; flip_y_ : boolean; {OpenCPL++} specific : platform_specific_ptr = NIL {/OpenCPL++} );
+ destructor Destruct;
+
+ // Setting the windows caption (title). Should be able
+ // to be called at least before calling init().
+ // It's perfect if they can be called anytime.
+ procedure caption_(cap : shortstring );
+
+ // These 3 menthods handle working with images. The image
+ // formats are the simplest ones, such as .BMP in Windows or
+ // .ppm in Linux. In the applications the names of the files
+ // should not have any file extensions. Method load_img() can
+ // be called before init(), so, the application could be able
+ // to determine the initial size of the window depending on
+ // the size of the loaded image.
+ // The argument "idx" is the number of the image 0...max_images-1
+ function load_img (idx : unsigned; file_ : shortstring ) : boolean;
+ function save_img (idx : unsigned; file_ : shortstring ) : boolean;
+ function create_img(idx : unsigned; width_ : unsigned = 0; height_ : unsigned = 0 ) : boolean;
+
+ // init() and run(). See description before the class for details.
+ // The necessity of calling init() after creation is that it's
+ // impossible to call the overridden virtual function (on_init())
+ // from the constructor. On the other hand it's very useful to have
+ // some on_init() event handler when the window is created but
+ // not yet displayed. The rbuf_window() method (see below) is
+ // accessible from on_init().
+ function init(width_ ,height_ ,flags : unsigned ) : boolean;
+ function run : int;
+ procedure quit;
+
+ // The very same parameters that were used in the constructor
+ function _format : pix_format_e;
+ function _flip_y : boolean;
+ function _bpp : unsigned;
+
+ // The following provides a very simple mechanism of doing someting
+ // in background. It's not multitheading. When whait_mode is true
+ // the class waits for the events and it does not ever call on_idle().
+ // When it's false it calls on_idle() when the event queue is empty.
+ // The mode can be changed anytime. This mechanism is satisfactory
+ // for creation very simple animations.
+ function _wait_mode : boolean;
+ procedure wait_mode_(wait_mode : boolean );
+
+ // These two functions control updating of the window.
+ // force_redraw() is an analog of the Win32 InvalidateRect() function.
+ // Being called it sets a flag (or sends a message) which results
+ // in calling on_draw() and updating the content of the window
+ // when the next event cycle comes.
+ // update_window() results in just putting immediately the content
+ // of the currently rendered buffer to the window without calling
+ // on_draw().
+ procedure force_redraw;
+ procedure update_window;
+
+ // So, finally, how to draw anythig with AGG? Very simple.
+ // rbuf_window() returns a reference to the main rendering
+ // buffer which can be attached to any rendering class.
+ // rbuf_img() returns a reference to the previously created
+ // or loaded image buffer (see load_img()). The image buffers
+ // are not displayed directly, they should be copied to or
+ // combined somehow with the rbuf_window(). rbuf_window() is
+ // the only buffer that can be actually displayed.
+ function rbuf_window : rendering_buffer_ptr;
+ function rbuf_img(idx : unsigned ) : rendering_buffer_ptr;
+
+ // Returns file extension used in the implemenation for the particular
+ // system.
+ function _img_ext : shortstring;
+
+ //
+ procedure copy_img_to_window(idx : unsigned );
+ procedure copy_window_to_img(idx : unsigned );
+ procedure copy_img_to_img (idx_to ,idx_from : unsigned );
+
+ // Event handlers. They are not pure functions, so you don't have
+ // to override them all.
+ // In my demo applications these functions are defined inside
+ // the the_application class
+ procedure on_init; virtual;
+ procedure on_resize(sx ,sy : int ); virtual;
+ procedure on_idle; virtual;
+
+ procedure on_mouse_move(x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual;
+ procedure on_mouse_button_up (x ,y : int; flags : unsigned ); virtual;
+
+ procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
+ procedure on_ctrl_change; virtual;
+ procedure on_draw; virtual;
+ procedure on_post_draw(raw_handler : pointer ); virtual;
+
+ // Adding control elements. A control element once added will be
+ // working and reacting to the mouse and keyboard events. Still, you
+ // will have to render them in the on_draw() using function
+ // render_ctrl() because platform_support doesn't know anything about
+ // renderers you use. The controls will be also scaled automatically
+ // if they provide a proper scaling mechanism (all the controls
+ // included into the basic AGG package do).
+ // If you don't need a particular control to be scaled automatically
+ // call ctrl::no_transform() after adding.
+ procedure add_ctrl(c : ctrl_ptr );
+
+ // Auxiliary functions. trans_affine_resizing() modifier sets up the resizing
+ // matrix on the basis of the given width and height and the initial
+ // width and height of the window. The implementation should simply
+ // call this function every time when it catches the resizing event
+ // passing in the new values of width and height of the window.
+ // Nothing prevents you from "cheating" the scaling matrix if you
+ // call this function from somewhere with wrong arguments.
+ // trans_affine_resizing() accessor simply returns current resizing matrix
+ // which can be used to apply additional scaling of any of your
+ // stuff when the window is being resized.
+ // width(), height(), initial_width(), and initial_height() must be
+ // clear to understand with no comments :-)
+ procedure trans_affine_resizing_(width_ ,height_ : int );
+ function _trans_affine_resizing : trans_affine_ptr;
+
+ function _width : double;
+ function _height : double;
+ function _initial_width : double;
+ function _initial_height : double;
+ function _window_flags : unsigned;
+
+ // Get raw display handler depending on the system.
+ // For win32 its an HDC, for other systems it can be a pointer to some
+ // structure. See the implementation files for detals.
+ // It's provided "as is", so, first you should check if it's not null.
+ // If it's null the raw_display_handler is not supported. Also, there's
+ // no guarantee that this function is implemented, so, in some
+ // implementations you may have simply an unresolved symbol when linking.
+ function _raw_display_handler : pointer;
+
+ // display message box or print the message to the console
+ // (depending on implementation)
+ procedure message_(msg : PChar );
+
+ // Stopwatch functions. Function elapsed_time() returns time elapsed
+ // since the latest start_timer() invocation in millisecods.
+ // The resolutoin depends on the implementation.
+ // In Win32 it uses QueryPerformanceFrequency() / QueryPerformanceCounter().
+ procedure start_timer;
+ function elapsed_time : double;
+
+ // Get the full file name. In most cases it simply returns
+ // file_name. As it's appropriate in many systems if you open
+ // a file by its name without specifying the path, it tries to
+ // open it in the current directory. The demos usually expect
+ // all the supplementary files to be placed in the current
+ // directory, that is usually coincides with the directory where
+ // the the executable is. However, in some systems (BeOS) it's not so.
+ // For those kinds of systems full_file_name() can help access files
+ // preserving commonly used policy.
+ // So, it's a good idea to use in the demos the following:
+ // FILE* fd = fopen(full_file_name("some.file"), "r");
+ // instead of
+ // FILE* fd = fopen("some.file", "r");
+ function full_file_name(file_name : shortstring ) : shortstring;
+ function file_source (path ,fname : shortstring ) : shortstring;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor ctrl_container.Construct;
+begin
+ m_num_ctrl:=0;
+ m_cur_ctrl:=-1;
+
+end;
+
+{ DESTRUCT }
+destructor ctrl_container.Destruct;
+begin
+end;
+
+{ ADD }
+procedure ctrl_container.add;
+begin
+ if m_num_ctrl < max_ctrl then
+ begin
+ m_ctrl[m_num_ctrl ]:=c;
+
+ inc(m_num_ctrl );
+
+ end;
+
+end;
+
+{ IN_RECT }
+function ctrl_container.in_rect;
+var
+ i : unsigned;
+
+begin
+ result:=false;
+
+ if m_num_ctrl > 0 then
+ for i:=0 to m_num_ctrl - 1 do
+ if m_ctrl[i ].in_rect(x ,y ) then
+ begin
+ result:=true;
+
+ exit;
+
+ end;
+
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+function ctrl_container.on_mouse_button_down;
+var
+ i : unsigned;
+
+begin
+ result:=false;
+
+ if m_num_ctrl > 0 then
+ for i:=0 to m_num_ctrl - 1 do
+ if m_ctrl[i ].on_mouse_button_down(x ,y ) then
+ begin
+ result:=true;
+
+ exit;
+
+ end;
+
+end;
+
+{ ON_MOUSE_BUTTON_UP }
+function ctrl_container.on_mouse_button_up;
+var
+ i : unsigned;
+
+begin
+ result:=false;
+
+ if m_num_ctrl > 0 then
+ for i:=0 to m_num_ctrl - 1 do
+ if m_ctrl[i ].on_mouse_button_up(x ,y ) then
+ begin
+ result:=true;
+
+ exit;
+
+ end;
+
+end;
+
+{ ON_MOUSE_MOVE }
+function ctrl_container.on_mouse_move;
+var
+ i : unsigned;
+
+begin
+ result:=false;
+
+ if m_num_ctrl > 0 then
+ for i:=0 to m_num_ctrl - 1 do
+ if m_ctrl[i ].on_mouse_move(x ,y ,button_flag ) then
+ begin
+ result:=true;
+
+ exit;
+
+ end;
+
+end;
+
+{ ON_ARROW_KEYS }
+function ctrl_container.on_arrow_keys;
+begin
+ result:=false;
+
+ if m_cur_ctrl >= 0 then
+ result:=m_ctrl[m_cur_ctrl ].on_arrow_keys(left ,right ,down ,up );
+
+end;
+
+{ SET_CUR }
+function ctrl_container.set_cur;
+var
+ i : unsigned;
+
+begin
+ result:=false;
+
+ if m_num_ctrl > 0 then
+ for i:=0 to m_num_ctrl - 1 do
+ if m_ctrl[i ].in_rect(x ,y ) then
+ begin
+ if m_cur_ctrl <> i then
+ begin
+ m_cur_ctrl:=i;
+
+ result:=true;
+
+ end;
+
+ exit;
+
+ end;
+
+ if m_cur_ctrl <> -1 then
+ begin
+ m_cur_ctrl:=-1;
+
+ result:=true;
+
+ end;
+
+end;
+
+{ CONSTRUCT }
+constructor platform_specific.Construct;
+var
+ i : unsigned;
+
+begin
+ m_pmap_window.Construct;
+
+ for i:=0 to max_images - 1 do
+ m_pmap_img[i ].Construct;
+
+ m_format :=format;
+ m_sys_format:=pix_format_undefined;
+
+ m_flip_y :=flip_y;
+ m_bpp :=0;
+ m_sys_bpp:=0;
+ m_hwnd :=0;
+
+ m_last_translated_key:=0;
+
+ m_cur_x:=0;
+ m_cur_y:=0;
+
+ m_input_flags:=0;
+ m_redraw_flag:=true;
+ m_current_dc :=0;
+
+ fillchar(m_keymap[0 ] ,sizeof(m_keymap ) ,0 );
+
+ m_keymap[VK_PAUSE ]:=key_pause;
+ m_keymap[VK_CLEAR ]:=key_clear;
+
+ m_keymap[VK_NUMPAD0 ] :=key_kp0;
+ m_keymap[VK_NUMPAD1 ] :=key_kp1;
+ m_keymap[VK_NUMPAD2 ] :=key_kp2;
+ m_keymap[VK_NUMPAD3 ] :=key_kp3;
+ m_keymap[VK_NUMPAD4 ] :=key_kp4;
+ m_keymap[VK_NUMPAD5 ] :=key_kp5;
+ m_keymap[VK_NUMPAD6 ] :=key_kp6;
+ m_keymap[VK_NUMPAD7 ] :=key_kp7;
+ m_keymap[VK_NUMPAD8 ] :=key_kp8;
+ m_keymap[VK_NUMPAD9 ] :=key_kp9;
+ m_keymap[VK_DECIMAL ] :=key_kp_period;
+ m_keymap[VK_DIVIDE ] :=key_kp_divide;
+ m_keymap[VK_MULTIPLY ]:=key_kp_multiply;
+ m_keymap[VK_SUBTRACT ]:=key_kp_minus;
+ m_keymap[VK_ADD ] :=key_kp_plus;
+
+ m_keymap[VK_UP ] :=key_up;
+ m_keymap[VK_DOWN ] :=key_down;
+ m_keymap[VK_RIGHT ] :=key_right;
+ m_keymap[VK_LEFT ] :=key_left;
+ m_keymap[VK_INSERT ]:=key_insert;
+ m_keymap[VK_DELETE ]:=key_delete;
+ m_keymap[VK_HOME ] :=key_home;
+ m_keymap[VK_END ] :=key_end;
+ m_keymap[VK_PRIOR ] :=key_page_up;
+ m_keymap[VK_NEXT ] :=key_page_down;
+
+ m_keymap[VK_F1 ] :=key_f1;
+ m_keymap[VK_F2 ] :=key_f2;
+ m_keymap[VK_F3 ] :=key_f3;
+ m_keymap[VK_F4 ] :=key_f4;
+ m_keymap[VK_F5 ] :=key_f5;
+ m_keymap[VK_F6 ] :=key_f6;
+ m_keymap[VK_F7 ] :=key_f7;
+ m_keymap[VK_F8 ] :=key_f8;
+ m_keymap[VK_F9 ] :=key_f9;
+ m_keymap[VK_F10 ]:=key_f10;
+ m_keymap[VK_F11 ]:=key_f11;
+ m_keymap[VK_F12 ]:=key_f12;
+ m_keymap[VK_F13 ]:=key_f13;
+ m_keymap[VK_F14 ]:=key_f14;
+ m_keymap[VK_F15 ]:=key_f15;
+
+ m_keymap[VK_NUMLOCK ]:=key_numlock;
+ m_keymap[VK_CAPITAL ]:=key_capslock;
+ m_keymap[VK_SCROLL ] :=key_scrollock;
+
+ case m_format of
+ pix_format_bw :
+ begin
+ m_sys_format:=pix_format_bw;
+ m_bpp :=1;
+ m_sys_bpp :=1;
+
+ end;
+
+ pix_format_gray8 :
+ begin
+ m_sys_format:=pix_format_bgr24;//pix_format_gray8;{hack}
+ m_bpp :=8;
+ m_sys_bpp :=24;//8;
+
+ end;
+
+ pix_format_gray16 :
+ begin
+ m_sys_format:=pix_format_gray8;
+ m_bpp :=16;
+ m_sys_bpp :=8;
+
+ end;
+
+ pix_format_rgb565 ,
+ pix_format_rgb555 :
+ begin
+ m_sys_format:=pix_format_rgb555;
+ m_bpp :=16;
+ m_sys_bpp :=16;
+
+ end;
+
+ pix_format_rgbAAA ,
+ pix_format_bgrAAA ,
+ pix_format_rgbBBA ,
+ pix_format_bgrABB :
+ begin
+ m_sys_format:=pix_format_bgr24;
+ m_bpp :=32;
+ m_sys_bpp :=24;
+
+ end;
+
+ pix_format_rgb24 ,
+ pix_format_bgr24 :
+ begin
+ m_sys_format:=pix_format_bgr24;
+ m_bpp :=24;
+ m_sys_bpp :=24;
+
+ end;
+
+ pix_format_rgb48 ,
+ pix_format_bgr48 :
+ begin
+ m_sys_format:=pix_format_bgr24;
+ m_bpp :=48;
+ m_sys_bpp :=24;
+
+ end;
+
+ pix_format_bgra32 ,
+ pix_format_abgr32 ,
+ pix_format_argb32 ,
+ pix_format_rgba32 :
+ begin
+ m_sys_format:=pix_format_bgra32;
+ m_bpp :=32;
+ m_sys_bpp :=32;
+
+ end;
+
+ pix_format_bgra64 ,
+ pix_format_abgr64 ,
+ pix_format_argb64 ,
+ pix_format_rgba64 :
+ begin
+ m_sys_format:=pix_format_bgra32;
+ m_bpp :=64;
+ m_sys_bpp :=32;
+
+ end;
+
+ end;
+
+ QueryPerformanceFrequency(m_sw_freq );{hack}
+ QueryPerformanceCounter (m_sw_start );
+
+end;
+
+{ DESTRUCT }
+destructor platform_specific.Destruct;
+var
+ i : unsigned;
+
+begin
+ m_pmap_window.Destruct;
+
+ for i:=0 to max_images - 1 do
+ m_pmap_img[i ].Destruct;
+
+end;
+
+{ CREATE_PMAP }
+procedure platform_specific.create_pmap;
+begin
+ m_pmap_window.create(width ,height ,m_bpp );
+
+ if m_flip_y then
+ wnd.attach(
+ m_pmap_window._buf ,
+ m_pmap_window._width ,
+ m_pmap_window._height ,
+ m_pmap_window._stride )
+
+ else
+ wnd.attach(
+ m_pmap_window._buf ,
+ m_pmap_window._width ,
+ m_pmap_window._height ,
+ -m_pmap_window._stride )
+
+end;
+
+{ convert_pmap }
+procedure convert_pmap(dst ,src : rendering_buffer_ptr; format : pix_format_e );
+begin
+ case format of
+ pix_format_gray8 :
+ color_conv(dst ,src ,color_conv_gray8_to_bgr24 );
+
+ pix_format_gray16 :
+ color_conv(dst ,src ,color_conv_gray16_to_gray8 );
+
+ pix_format_rgb565 :
+ color_conv(dst ,src ,color_conv_rgb565_to_rgb555 );
+
+ pix_format_rgbAAA :
+ color_conv(dst ,src ,color_conv_rgbAAA_to_bgr24 );
+
+ pix_format_bgrAAA :
+ color_conv(dst ,src ,color_conv_bgrAAA_to_bgr24 );
+
+ pix_format_rgbBBA :
+ color_conv(dst ,src ,color_conv_rgbBBA_to_bgr24 );
+
+ pix_format_bgrABB :
+ color_conv(dst ,src ,color_conv_bgrABB_to_bgr24 );
+
+ pix_format_rgb24 :
+ color_conv(dst ,src ,color_conv_rgb24_to_bgr24 );
+
+ pix_format_rgb48 :
+ color_conv(dst ,src ,color_conv_rgb48_to_bgr24 );
+
+ pix_format_bgr48 :
+ color_conv(dst ,src ,color_conv_bgr48_to_bgr24 );
+
+ pix_format_abgr32 :
+ color_conv(dst ,src ,color_conv_abgr32_to_bgra32 );
+
+ pix_format_argb32 :
+ color_conv(dst ,src ,color_conv_argb32_to_bgra32 );
+
+ pix_format_rgba32 :
+ color_conv(dst ,src ,color_conv_rgba32_to_bgra32 );
+
+ pix_format_bgra64 :
+ color_conv(dst ,src ,color_conv_bgra64_to_bgra32 );
+
+ pix_format_abgr64 :
+ color_conv(dst ,src ,color_conv_abgr64_to_bgra32 );
+
+ pix_format_argb64 :
+ color_conv(dst ,src ,color_conv_argb64_to_bgra32 );
+
+ pix_format_rgba64 :
+ color_conv(dst ,src ,color_conv_rgba64_to_bgra32 );
+
+ end;
+
+end;
+
+{ DISPLAY_PMAP }
+procedure platform_specific.display_pmap;
+var
+ pmap_tmp : pixel_map;
+ rbuf_tmp : rendering_buffer;
+
+begin
+ if m_sys_format = m_format then
+ m_pmap_window.draw(dc )
+
+ else
+ begin
+ pmap_tmp.Construct;
+ pmap_tmp.create(m_pmap_window._width ,m_pmap_window._height ,m_sys_bpp );
+
+ rbuf_tmp.Construct;
+
+ if m_flip_y then
+ rbuf_tmp.attach(pmap_tmp._buf ,pmap_tmp._width ,pmap_tmp._height ,pmap_tmp._stride )
+ else
+ rbuf_tmp.attach(pmap_tmp._buf ,pmap_tmp._width ,pmap_tmp._height ,-pmap_tmp._stride );
+
+ convert_pmap (@rbuf_tmp ,src ,m_format );
+ pmap_tmp.draw(dc );
+
+ rbuf_tmp.Destruct;
+ pmap_tmp.Destruct;
+
+ end;
+
+end;
+
+{ LOAD_PMAP }
+function platform_specific.load_pmap;
+var
+ pmap_tmp : pixel_map;
+ rbuf_tmp : rendering_buffer;
+
+begin
+ pmap_tmp.Construct;
+
+ if not pmap_tmp.load_from_bmp(fn ) then
+ begin
+ result:=false;
+
+ pmap_tmp.Destruct;
+ exit;
+
+ end;
+
+ rbuf_tmp.Construct;
+
+ if m_flip_y then
+ rbuf_tmp.attach(pmap_tmp._buf ,pmap_tmp._width ,pmap_tmp._height ,pmap_tmp._stride )
+ else
+ rbuf_tmp.attach(pmap_tmp._buf ,pmap_tmp._width ,pmap_tmp._height ,-pmap_tmp._stride );
+
+ m_pmap_img[idx ].create(pmap_tmp._width ,pmap_tmp._height ,m_bpp ,0 );
+
+ if m_flip_y then
+ dst.attach(
+ m_pmap_img[idx ]._buf ,
+ m_pmap_img[idx ]._width ,
+ m_pmap_img[idx ]._height ,
+ m_pmap_img[idx ]._stride )
+ else
+ dst.attach(
+ m_pmap_img[idx ]._buf ,
+ m_pmap_img[idx ]._width ,
+ m_pmap_img[idx ]._height ,
+ -m_pmap_img[idx ]._stride );
+
+ case m_format of
+ pix_format_gray8 :
+ case pmap_tmp._bpp of
+ 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_gray8 );
+
+ end;
+
+ pix_format_gray16 :
+ case pmap_tmp._bpp of
+ 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_gray16 );
+
+ end;
+
+ pix_format_rgb555 :
+ case pmap_tmp._bpp of
+ 16 : color_conv(dst ,@rbuf_tmp ,color_conv_rgb555_to_rgb555 );
+ 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_rgb555 );
+ 32 : color_conv(dst ,@rbuf_tmp ,color_conv_bgra32_to_rgb555 );
+
+ end;
+
+ pix_format_rgb565 :
+ case pmap_tmp._bpp of
+ 16 : color_conv(dst ,@rbuf_tmp ,color_conv_rgb555_to_rgb565 );
+ 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_rgb565 );
+ 32 : color_conv(dst ,@rbuf_tmp ,color_conv_bgra32_to_rgb565 );
+
+ end;
+
+ pix_format_rgb24 :
+ case pmap_tmp._bpp of
+ 16 : color_conv(dst ,@rbuf_tmp ,color_conv_rgb555_to_rgb24 );
+ 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_rgb24 );
+ 32 : color_conv(dst ,@rbuf_tmp ,color_conv_bgra32_to_rgb24 );
+
+ end;
+
+ pix_format_bgr24 :
+ case pmap_tmp._bpp of
+ 16 : color_conv(dst ,@rbuf_tmp ,color_conv_rgb555_to_bgr24 );
+ 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_bgr24 );
+ 32 : color_conv(dst ,@rbuf_tmp ,color_conv_bgra32_to_bgr24 );
+
+ end;
+
+ pix_format_rgb48 :
+ case pmap_tmp._bpp of
+ 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_rgb48 );
+
+ end;
+
+ pix_format_bgr48 :
+ case pmap_tmp._bpp of
+ 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_bgr48 );
+
+ end;
+
+ pix_format_abgr32 :
+ case pmap_tmp._bpp of
+ 16 : color_conv(dst ,@rbuf_tmp ,color_conv_rgb555_to_abgr32 );
+ 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_abgr32 );
+ 32 : color_conv(dst ,@rbuf_tmp ,color_conv_bgra32_to_abgr32 );
+
+ end;
+
+ pix_format_argb32 :
+ case pmap_tmp._bpp of
+ 16 : color_conv(dst ,@rbuf_tmp ,color_conv_rgb555_to_argb32 );
+ 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_argb32 );
+ 32 : color_conv(dst ,@rbuf_tmp ,color_conv_bgra32_to_argb32 );
+
+ end;
+
+ pix_format_bgra32 :
+ case pmap_tmp._bpp of
+ 16 : color_conv(dst ,@rbuf_tmp ,color_conv_rgb555_to_bgra32 );
+ 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_bgra32 );
+ 32 : color_conv(dst ,@rbuf_tmp ,color_conv_bgra32_to_bgra32 );
+
+ end;
+
+ pix_format_rgba32 :
+ case pmap_tmp._bpp of
+ 16 : color_conv(dst ,@rbuf_tmp ,color_conv_rgb555_to_rgba32 );
+ 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_rgba32 );
+ 32 : color_conv(dst ,@rbuf_tmp ,color_conv_bgra32_to_rgba32 );
+
+ end;
+
+ pix_format_abgr64 :
+ case pmap_tmp._bpp of
+ 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_abgr64 );
+
+ end;
+
+ pix_format_argb64 :
+ case pmap_tmp._bpp of
+ 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_argb64 );
+
+ end;
+
+ pix_format_bgra64 :
+ case pmap_tmp._bpp of
+ 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_bgra64 );
+
+ end;
+
+ pix_format_rgba64 :
+ case pmap_tmp._bpp of
+ 24 : color_conv(dst ,@rbuf_tmp ,color_conv_bgr24_to_rgba64 );
+
+ end;
+
+ end;
+
+ pmap_tmp.Destruct;
+ rbuf_tmp.Destruct;
+
+ result:=true;
+
+end;
+
+{ SAVE_PMAP }
+function platform_specific.save_pmap;
+var
+ pmap_tmp : pixel_map;
+ rbuf_tmp : rendering_buffer;
+
+begin
+ if m_sys_format = m_format then
+ begin
+ result:=m_pmap_img[idx ].save_as_bmp(fn );
+
+ exit;
+
+ end;
+
+ pmap_tmp.Construct;
+ pmap_tmp.create(
+ m_pmap_img[idx ]._width ,
+ m_pmap_img[idx ]._height ,
+ m_sys_bpp );
+
+ rbuf_tmp.Construct;
+
+ if m_flip_y then
+ rbuf_tmp.attach(pmap_tmp._buf ,pmap_tmp._width ,pmap_tmp._height ,pmap_tmp._stride )
+ else
+ rbuf_tmp.attach(pmap_tmp._buf ,pmap_tmp._width ,pmap_tmp._height ,-pmap_tmp._stride );
+
+ convert_pmap(@rbuf_tmp ,src ,m_format );
+
+ result:=pmap_tmp.save_as_bmp(fn );
+
+ rbuf_tmp.Destruct;
+ pmap_tmp.Destruct;
+
+end;
+
+{ TRANSLATE }
+function platform_specific.translate;
+begin
+ if keycode > 255 then
+ m_last_translated_key:=0
+ else
+ m_last_translated_key:=m_keymap[keycode ];
+
+end;
+
+{ CONSTRUCT }
+constructor platform_support.Construct;
+var
+ i : unsigned;
+
+begin
+{OpenCPL++}
+ if specific <> NIL then
+ m_specific:=specific
+
+ else
+{/OpenCPL++}
+ new(m_specific ,Construct(format_ ,flip_y_ ) );
+
+ m_ctrls.Construct;
+ m_rbuf_window.Construct;
+
+ for i:=0 to max_images - 1 do
+ m_rbuf_img[i ].Construct;
+
+ m_resize_mtx.Construct;
+
+ m_format:=format_;
+
+ m_bpp:=m_specific.m_bpp;
+
+ m_window_flags:=0;
+ m_wait_mode :=true;
+ m_flip_y :=flip_y_;
+
+ m_initial_width :=10;
+ m_initial_height:=10;
+
+ m_caption:='Anti-Grain Geometry Application'#0;
+
+end;
+
+{ DESTRUCT }
+destructor platform_support.Destruct;
+var
+ i : unsigned;
+
+begin
+ dispose(m_specific ,Destruct );
+
+ m_ctrls.Destruct;
+ m_rbuf_window.Destruct;
+
+ for i:=0 to max_images - 1 do
+ m_rbuf_img[i ].Destruct;
+
+end;
+
+{ CAPTION_ }
+procedure platform_support.caption_;
+begin
+ m_caption:=cap + #0;
+
+ dec(byte(m_caption[0 ] ) );
+
+ if m_specific.m_hwnd <> 0 then
+ SetWindowText(m_specific.m_hwnd ,@m_caption[1 ] );
+
+end;
+
+{ LOAD_IMG }
+function platform_support.load_img;
+var
+ f : file;
+
+begin
+ if idx < max_images then
+ begin
+ file_:=file_ + _img_ext;
+
+ AssignFile(f ,file_ );
+ reset (f ,1 );
+
+ if ioresult <> 0 then
+ file_:='bmp\' + file_;
+
+ close(f );
+
+ result:=m_specific.load_pmap(file_ ,idx ,@m_rbuf_img[idx ] );
+
+ end
+ else
+ result:=true;
+
+end;
+
+{ SAVE_IMG }
+function platform_support.save_img;
+begin
+ if idx < max_images then
+ result:=m_specific.save_pmap(file_ ,idx ,@m_rbuf_img[idx ] )
+ else
+ result:=true;
+
+end;
+
+{ CREATE_IMG }
+function platform_support.create_img;
+begin
+ if idx < max_images then
+ begin
+ if width_ = 0 then
+ width_:=m_specific.m_pmap_window._width;
+
+ if height_ = 0 then
+ height_:=m_specific.m_pmap_window._height;
+
+ m_specific.m_pmap_img[idx ].create(width_ ,height_ ,m_specific.m_bpp );
+
+ if m_flip_y then
+ m_rbuf_img[idx ].attach(
+ m_specific.m_pmap_img[idx ]._buf ,
+ m_specific.m_pmap_img[idx ]._width ,
+ m_specific.m_pmap_img[idx ]._height ,
+ m_specific.m_pmap_img[idx ]._stride )
+ else
+ m_rbuf_img[idx ].attach(
+ m_specific.m_pmap_img[idx ]._buf ,
+ m_specific.m_pmap_img[idx ]._width ,
+ m_specific.m_pmap_img[idx ]._height ,
+ -m_specific.m_pmap_img[idx ]._stride );
+
+ result:=true;
+
+ end
+ else
+ result:=false;
+
+end;
+
+{ get_key_flags }
+function get_key_flags(wflags : int ) : unsigned;
+var
+ flags : unsigned;
+
+begin
+ flags:=0;
+
+ if wflags and MK_LBUTTON <> 0 then
+ flags:=flags or mouse_left;
+
+ if wflags and MK_RBUTTON <> 0 then
+ flags:=flags or mouse_right;
+
+ if wflags and MK_SHIFT <> 0 then
+ flags:=flags or kbd_shift;
+
+ if wflags and MK_CONTROL <> 0 then
+ flags:=flags or kbd_ctrl;
+
+ result:=flags;
+
+end;
+
+{ window_proc }
+function window_proc(Wnd : HWND; Msg : UINT; WPar : WParam; LPar : LParam ) : LResult; stdcall;
+var
+ ps : TPaintStruct;
+ app : platform_support_ptr;
+ ret : LResult;
+
+ dc ,paintDC : HDC;
+
+ left ,up ,right ,down : boolean;
+
+ ss : shortstring;
+
+begin
+ app:=platform_support_ptr(GetWindowLong(Wnd ,GWL_USERDATA ) );
+
+ if app = NIL then
+ begin
+ if Msg = WM_DESTROY then
+ begin
+ PostQuitMessage(0 );
+
+ result:=0;
+
+ exit;
+
+ end;
+
+ result:=DefWindowProc(Wnd ,msg ,WPar ,LPar );
+
+ exit;
+
+ end;
+
+ dc:=GetDC(app.m_specific.m_hwnd );
+
+ app.m_specific.m_current_dc:=dc;
+
+ ret:=0;
+
+ case Msg of
+ WM_CREATE :
+ NoP;
+
+ WM_SIZE :
+ begin
+ app.m_specific.create_pmap(int16(int32u_(LPar ).low ) ,int16(int32u_(LPar ).high ) ,app.rbuf_window );
+ app.trans_affine_resizing_(int16(int32u_(LPar ).low ) ,int16(int32u_(LPar ).high ) );
+
+ app.on_resize(int16(int32u_(LPar ).low ) ,int16(int32u_(LPar ).high ) );
+ app.force_redraw;
+
+ end;
+
+ WM_ERASEBKGND :
+ NoP;
+
+ WM_LBUTTONDOWN :
+ begin
+ SetCapture(app.m_specific.m_hwnd );
+
+ app.m_specific.m_cur_x:=int16(int32u_(LPar ).low );
+
+ if app._flip_y then
+ app.m_specific.m_cur_y:=int(app.rbuf_window._height ) - int16(int32u_(LPar ).high )
+ else
+ app.m_specific.m_cur_y:=int16(int32u_(LPar ).high );
+
+ app.m_specific.m_input_flags:=mouse_left or get_key_flags(WPar );
+
+ app.m_ctrls.set_cur(app.m_specific.m_cur_x ,app.m_specific.m_cur_y );
+
+ if app.m_ctrls.on_mouse_button_down(app.m_specific.m_cur_x ,app.m_specific.m_cur_y ) then
+ begin
+ app.on_ctrl_change;
+ app.force_redraw;
+
+ end
+ else
+ if app.m_ctrls.in_rect(app.m_specific.m_cur_x ,app.m_specific.m_cur_y ) then
+ if app.m_ctrls.set_cur(app.m_specific.m_cur_x ,app.m_specific.m_cur_y ) then
+ begin
+ app.on_ctrl_change;
+ app.force_redraw;
+
+ end
+ else
+ else
+ app.on_mouse_button_down(
+ app.m_specific.m_cur_x ,
+ app.m_specific.m_cur_y ,
+ app.m_specific.m_input_flags );
+
+ end;
+
+ WM_LBUTTONUP :
+ begin
+ ReleaseCapture;
+
+ app.m_specific.m_cur_x:=int16(int32u_(LPar ).low );
+
+ if app._flip_y then
+ app.m_specific.m_cur_y:=int(app.rbuf_window._height ) - int16(int32u_(LPar ).high )
+ else
+ app.m_specific.m_cur_y:=int16(int32u_(LPar ).high );
+
+ app.m_specific.m_input_flags:=mouse_left or get_key_flags(WPar );
+
+ if app.m_ctrls.on_mouse_button_up(app.m_specific.m_cur_x ,app.m_specific.m_cur_y ) then
+ begin
+ app.on_ctrl_change;
+ app.force_redraw;
+
+ end;
+
+ app.on_mouse_button_up(
+ app.m_specific.m_cur_x ,
+ app.m_specific.m_cur_y ,
+ app.m_specific.m_input_flags );
+
+ end;
+
+ WM_RBUTTONDOWN :
+ begin
+ SetCapture(app.m_specific.m_hwnd );
+
+ app.m_specific.m_cur_x:=int16(int32u_(LPar ).low );
+
+ if app._flip_y then
+ app.m_specific.m_cur_y:=int(app.rbuf_window._height ) - int16(int32u_(LPar ).high )
+ else
+ app.m_specific.m_cur_y:=int16(int32u_(LPar ).high );
+
+ app.m_specific.m_input_flags:=mouse_right or get_key_flags(WPar );
+
+ app.on_mouse_button_down(
+ app.m_specific.m_cur_x ,
+ app.m_specific.m_cur_y ,
+ app.m_specific.m_input_flags );
+
+ end;
+
+ WM_RBUTTONUP :
+ begin
+ ReleaseCapture;
+
+ app.m_specific.m_cur_x:=int16(int32u_(LPar ).low );
+
+ if app._flip_y then
+ app.m_specific.m_cur_y:=int(app.rbuf_window._height ) - int16(int32u_(LPar ).high )
+ else
+ app.m_specific.m_cur_y:=int16(int32u_(LPar ).high );
+
+ app.m_specific.m_input_flags:=mouse_right or get_key_flags(WPar );
+
+ app.on_mouse_button_up(
+ app.m_specific.m_cur_x ,
+ app.m_specific.m_cur_y ,
+ app.m_specific.m_input_flags );
+
+ end;
+
+ WM_MOUSEMOVE :
+ begin
+ app.m_specific.m_cur_x:=int16(int32u_(LPar ).low );
+
+ if app._flip_y then
+ app.m_specific.m_cur_y:=int(app.rbuf_window._height ) - int16(int32u_(LPar ).high )
+ else
+ app.m_specific.m_cur_y:=int16(int32u_(LPar ).high );
+
+ app.m_specific.m_input_flags:=get_key_flags(WPar );
+
+ if app.m_ctrls.on_mouse_move(
+ app.m_specific.m_cur_x ,
+ app.m_specific.m_cur_y ,
+ ((app.m_specific.m_input_flags and mouse_left ) <> 0 ) ) then
+ begin
+ app.on_ctrl_change;
+ app.force_redraw;
+
+ end
+ else
+ if not app.m_ctrls.in_rect(app.m_specific.m_cur_x ,app.m_specific.m_cur_y ) then
+ app.on_mouse_move(
+ app.m_specific.m_cur_x ,
+ app.m_specific.m_cur_y ,
+ app.m_specific.m_input_flags );
+
+ end;
+
+ WM_SYSKEYDOWN ,WM_KEYDOWN :
+ begin
+ app.m_specific.m_last_translated_key:=0;
+
+ case WPar of
+ VK_CONTROL :
+ app.m_specific.m_input_flags:=app.m_specific.m_input_flags or kbd_ctrl;
+
+ VK_SHIFT :
+ app.m_specific.m_input_flags:=app.m_specific.m_input_flags or kbd_shift;
+
+ VK_F4 :
+ if LPar and $20000000 <> 0 then
+ app.quit
+ else
+ app.m_specific.translate(WPar );
+
+ else
+ app.m_specific.translate(WPar );
+
+ end;
+
+ if app.m_specific.m_last_translated_key <> 0 then
+ begin
+ left :=false;
+ up :=false;
+ right:=false;
+ down :=false;
+
+ case app.m_specific.m_last_translated_key of
+ key_left :
+ left:=true;
+
+ key_up :
+ up:=true;
+
+ key_right :
+ right:=true;
+
+ key_down :
+ down:=true;
+
+ key_f2 :
+ begin
+ app.copy_window_to_img(max_images - 1 );
+ app.save_img (max_images - 1 ,'screenshot.bmp' );
+
+ end;
+
+ end;
+
+ if app._window_flags and window_process_all_keys <> 0 then
+ app.on_key(
+ app.m_specific.m_cur_x ,
+ app.m_specific.m_cur_y ,
+ app.m_specific.m_last_translated_key ,
+ app.m_specific.m_input_flags )
+
+ else
+ if app.m_ctrls.on_arrow_keys(left ,right ,down ,up ) then
+ begin
+ app.on_ctrl_change;
+ app.force_redraw;
+
+ end
+ else
+ app.on_key(
+ app.m_specific.m_cur_x ,
+ app.m_specific.m_cur_y ,
+ app.m_specific.m_last_translated_key ,
+ app.m_specific.m_input_flags );
+
+ end;
+
+ end;
+
+ WM_SYSKEYUP ,WM_KEYUP :
+ begin
+ app.m_specific.m_last_translated_key:=0;
+
+ case WPar of
+ VK_CONTROL :
+ app.m_specific.m_input_flags:=app.m_specific.m_input_flags and (not kbd_ctrl );
+
+ VK_SHIFT :
+ app.m_specific.m_input_flags:=app.m_specific.m_input_flags and (not kbd_shift );
+
+ end;
+
+ end;
+
+ WM_CHAR ,WM_SYSCHAR :
+ if app.m_specific.m_last_translated_key = 0 then
+ app.on_key(
+ app.m_specific.m_cur_x ,
+ app.m_specific.m_cur_y ,
+ WPar ,
+ app.m_specific.m_input_flags );
+
+ WM_PAINT :
+ begin
+ paintDC:=BeginPaint(Wnd ,ps );
+
+ app.m_specific.m_current_dc:=paintDC;
+
+ if app.m_specific.m_redraw_flag then
+ begin
+ app.on_draw;
+
+ app.m_specific.m_redraw_flag:=false;
+
+ end;
+
+ app.m_specific.display_pmap(paintDC ,app.rbuf_window );
+ app.on_post_draw (pointer(@paintDC ) );
+
+ app.m_specific.m_current_dc:=0;
+
+ EndPaint(Wnd ,ps );
+
+ end;
+
+ WM_COMMAND :
+ NoP;
+
+ WM_DESTROY :
+ PostQuitMessage(0 );
+
+ else
+ ret:=DefWindowProc(Wnd ,Msg ,WPar ,LPar );
+
+ end;
+
+ app.m_specific.m_current_dc:=0;
+
+ ReleaseDC(app.m_specific.m_hwnd ,dc );
+
+ result:=ret;
+
+end;
+
+{ INIT }
+function platform_support.init;
+var
+ wc : WNDCLASS;
+ rct : TRect;
+
+ wflags : int;
+
+begin
+ result:=false;
+
+ if m_specific.m_sys_format = pix_format_undefined then
+ exit;
+
+ m_window_flags:=flags;
+
+ wflags:=CS_OWNDC or CS_VREDRAW or CS_HREDRAW;
+
+ wc.lpszClassName:='AGGAppClass';
+ wc.lpfnWndProc :=@window_proc;
+ wc.style :=wflags;
+ wc.hInstance :=hInstance;
+ wc.hIcon :=LoadIcon (0, IDI_APPLICATION);
+ wc.hCursor :=LoadCursor(0, IDC_ARROW);
+ wc.hbrBackground:=COLOR_WINDOW + 1;
+ wc.lpszMenuName :='AGGAppMenu';
+ wc.cbClsExtra :=0;
+ wc.cbWndExtra :=0;
+
+ RegisterClass(wc );
+
+ wflags:=WS_OVERLAPPED or WS_CAPTION or WS_SYSMENU or WS_MINIMIZEBOX;
+
+ if m_window_flags and window_resize <> 0 then
+ wflags:=wflags or WS_THICKFRAME or WS_MAXIMIZEBOX;
+
+ m_specific.m_hwnd:=
+ CreateWindow(
+ 'AGGAppClass' ,@m_caption[1 ] ,wflags ,
+ 10 ,10 ,width_ ,height_ ,
+ 0 ,0 ,hInstance ,0 );
+
+ if m_specific.m_hwnd = 0 then
+ exit;
+
+ GetClientRect(m_specific.m_hwnd ,rct );
+
+ MoveWindow(
+ m_specific.m_hwnd , // handle to window
+ 10 , // horizontal position
+ 10 , // vertical position
+ width_ + (width_ - (rct.right - rct.left ) ) ,
+ height_ + (height_ - (rct.bottom - rct.top ) ) ,
+ false );
+
+ SetWindowLong(m_specific.m_hwnd ,GWL_USERDATA ,ptrcomp(@self ) );
+
+ m_specific.create_pmap(width_ ,height_ ,@m_rbuf_window );
+
+ m_initial_width :=width_;
+ m_initial_height:=height_;
+
+ on_init;
+
+ m_specific.m_redraw_flag:=true;
+
+ ShowWindow(m_specific.m_hwnd ,SW_SHOW );
+
+ result:=true;
+
+end;
+
+{ RUN }
+function platform_support.run;
+var
+ msg : TMsg;
+
+begin
+ repeat
+ if m_wait_mode then
+ begin
+ if not GetMessage(msg ,0 ,0 ,0 ) then
+ break;
+
+ TranslateMessage(msg );
+ DispatchMessage (msg );
+
+ end
+ else
+ if PeekMessage(msg ,0 ,0 ,0 ,PM_REMOVE ) then
+ begin
+ TranslateMessage(msg );
+
+ if msg.message = WM_QUIT then
+ break;
+
+ DispatchMessage(msg );
+
+ end
+ else
+ on_idle;
+
+ until false;
+
+ result:=msg.wParam;
+
+end;
+
+{ QUIT }
+procedure platform_support.quit;
+begin
+ if m_specific.m_hwnd <> 0 then
+ DestroyWindow(m_specific.m_hwnd );
+
+ PostQuitMessage(0 );
+
+end;
+
+{ _FORMAT }
+function platform_support._format;
+begin
+ result:=m_format;
+
+end;
+
+{ _FLIP_Y }
+function platform_support._flip_y;
+begin
+ result:=m_flip_y;
+
+end;
+
+{ _BPP }
+function platform_support._bpp;
+begin
+ result:=m_bpp;
+
+end;
+
+{ _WAIT_MODE }
+function platform_support._wait_mode;
+begin
+ result:=m_wait_mode;
+
+end;
+
+{ WAIT_MODE_ }
+procedure platform_support.wait_mode_;
+begin
+ m_wait_mode:=wait_mode;
+
+end;
+
+{ FORCE_REDRAW }
+procedure platform_support.force_redraw;
+begin
+ m_specific.m_redraw_flag:=true;
+
+ InvalidateRect(m_specific.m_hwnd ,0 ,false );
+
+end;
+
+{ UPDATE_WINDOW }
+procedure platform_support.update_window;
+var
+ dc : HDC;
+
+begin
+ dc:=GetDC(m_specific.m_hwnd );
+
+ m_specific.display_pmap(dc ,@m_rbuf_window );
+
+ ReleaseDC(m_specific.m_hwnd ,dc );
+
+end;
+
+{ RBUF_WINDOW }
+function platform_support.rbuf_window;
+begin
+ result:=@m_rbuf_window;
+
+end;
+
+{ RBUF_IMG }
+function platform_support.rbuf_img;
+begin
+ result:=@m_rbuf_img[idx ];
+
+end;
+
+{ _IMG_EXT }
+function platform_support._img_ext;
+begin
+ result:='.bmp';
+
+end;
+
+{ COPY_IMG_TO_WINDOW }
+procedure platform_support.copy_img_to_window;
+begin
+ if (idx < max_images ) and
+ (rbuf_img(idx )._buf <> NIL ) then
+ rbuf_window.copy_from(rbuf_img(idx ) );
+
+end;
+
+{ COPY_WINDOW_TO_IMG }
+procedure platform_support.copy_window_to_img;
+begin
+ if idx < max_images then
+ begin
+ create_img(idx ,rbuf_window._width ,rbuf_window._height );
+ rbuf_img (idx ).copy_from(rbuf_window );
+
+ end;
+
+end;
+
+{ COPY_IMG_TO_IMG }
+procedure platform_support.copy_img_to_img;
+begin
+ if (idx_from < max_images ) and
+ (idx_to < max_images ) and
+ (rbuf_img(idx_from )._buf <> NIL ) then
+ begin
+ create_img(
+ idx_to ,
+ rbuf_img(idx_from )._width ,
+ rbuf_img(idx_from )._height );
+
+ rbuf_img(idx_to ).copy_from(rbuf_img(idx_from ) );
+
+ end;
+
+end;
+
+{ ON_INIT }
+procedure platform_support.on_init;
+begin
+end;
+
+{ ON_RESIZE }
+procedure platform_support.on_resize;
+begin
+end;
+
+{ ON_IDLE }
+procedure platform_support.on_idle;
+begin
+end;
+
+{ ON_MOUSE_MOVE }
+procedure platform_support.on_mouse_move;
+begin
+end;
+
+{ ON_MOUSE_BUTTON_DOWN }
+procedure platform_support.on_mouse_button_down;
+begin
+end;
+
+{ ON_MOUSE_BUTTON_UP }
+procedure platform_support.on_mouse_button_up;
+begin
+end;
+
+{ ON_KEY }
+procedure platform_support.on_key;
+begin
+end;
+
+{ ON_CTRL_CHANGE }
+procedure platform_support.on_ctrl_change;
+begin
+end;
+
+{ ON_DRAW }
+procedure platform_support.on_draw;
+begin
+end;
+
+{ ON_POST_DRAW }
+procedure platform_support.on_post_draw;
+begin
+end;
+
+{ ADD_CTRL }
+procedure platform_support.add_ctrl;
+begin
+ m_ctrls.add(c );
+
+ c.transform(@m_resize_mtx );
+
+end;
+
+{ TRANS_AFFINE_RESIZING_ }
+procedure platform_support.trans_affine_resizing_;
+var
+ vp : trans_viewport;
+ ts : trans_affine_scaling;
+
+begin
+ if m_window_flags and window_keep_aspect_ratio <> 0 then
+ begin
+ //double sx = double(width) / double(m_initial_width);
+ //double sy = double(height) / double(m_initial_height);
+ //if(sy < sx) sx = sy;
+ //m_resize_mtx = trans_affine_scaling(sx, sx);
+
+ vp.Construct;
+ vp.preserve_aspect_ratio(0.5 ,0.5 ,aspect_ratio_meet );
+
+ vp.device_viewport(0 ,0 ,width_ ,height_ );
+ vp.world_viewport (0 ,0 ,m_initial_width ,m_initial_height );
+
+ vp.to_affine(@m_resize_mtx );
+
+ end
+ else
+ begin
+ ts.Construct(
+ width_ / m_initial_width ,
+ height_ / m_initial_height );
+
+ m_resize_mtx.assign(@ts );
+
+ end;
+
+end;
+
+{ _TRANS_AFFINE_RESIZING }
+function platform_support._trans_affine_resizing;
+begin
+ result:=@m_resize_mtx;
+
+end;
+
+{ _WIDTH }
+function platform_support._width;
+begin
+ result:=m_rbuf_window._width;
+
+end;
+
+{ _HEIGHT }
+function platform_support._height;
+begin
+ result:=m_rbuf_window._height;
+
+end;
+
+{ _INITIAL_WIDTH }
+function platform_support._initial_width;
+begin
+ result:=m_initial_width;
+
+end;
+
+{ _INITIAL_HEIGHT }
+function platform_support._initial_height;
+begin
+ result:=m_initial_height;
+
+end;
+
+{ _WINDOW_FLAGS }
+function platform_support._window_flags;
+begin
+ result:=m_window_flags;
+
+end;
+
+{ _RAW_DISPLAY_HANDLER }
+function platform_support._raw_display_handler;
+begin
+ result:=@m_specific.m_current_dc;
+
+end;
+
+{ MESSAGE_ }
+procedure platform_support.message_;
+begin
+ MessageBox(m_specific.m_hwnd ,@msg[0 ] ,'AGG Message' ,MB_OK );
+
+end;
+
+{ START_TIMER }
+procedure platform_support.start_timer;
+begin
+ QueryPerformanceCounter({m_specific.}m_sw_start );{hack}
+
+end;
+
+{ ELAPSED_TIME }
+function platform_support.elapsed_time;
+var
+ stop : TLargeInteger;
+
+begin
+ QueryPerformanceCounter(stop );
+
+ result:=(stop - {m_specific.}m_sw_start ) * 1000.0 / {m_specific.}m_sw_freq;{hack}
+
+end;
+
+{ FULL_FILE_NAME }
+function platform_support.full_file_name;
+begin
+ result:=file_name;
+
+end;
+
+{ FILE_SOURCE }
+function platform_support.file_source;
+var
+ f : file;
+ e : integer;
+
+begin
+ result:=fname;
+
+ e:=ioresult;
+
+ AssignFile(f ,result );
+ reset (f ,1 );
+
+ if ioresult <> 0 then
+ result:=path + '\' + fname;
+
+ close(f );
+
+ e:=ioresult;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/platform/win/agg_win32_bmp.pas b/src/corelib/render/software/platform/win/agg_win32_bmp.pas
index 808cb1b6..c980eff2 100644
--- a/src/corelib/render/software/platform/win/agg_win32_bmp.pas
+++ b/src/corelib/render/software/platform/win/agg_win32_bmp.pas
@@ -1,719 +1,719 @@
-//----------------------------------------------------------------------------
-// Anti-Grain Geometry - Version 2.4 (Public License)
-// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
-//
-// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
-// Pascal Port By: Milan Marusinec alias Milano
-// milan@marusinec.sk
-// http://www.aggpas.org
-// Copyright (c) 2005-2006
-//
-// Permission to copy, use, modify, sell and distribute this software
-// is granted provided this copyright notice appears in all copies.
-// This software is provided "as is" without express or implied
-// warranty, and with no claim as to its suitability for any purpose.
-//
-//----------------------------------------------------------------------------
-// Contact: mcseem@antigrain.com
-// mcseemagg@yahoo.com
-// http://www.antigrain.com
-//
-//----------------------------------------------------------------------------
-//
-// class pixel_map
-//
-// [Pascal Port History] -----------------------------------------------------
-//
-// 23.06.2006-Milano: ptrcomp adjustments
-// 15.12.2005-Milano: Unit port establishment
-//
-{ agg_win32_bmp.pas }
-unit
- agg_win32_bmp ;
-
-INTERFACE
-
-{$I agg_mode.inc }
-
-uses
- Windows ,
- agg_basics ;
-
-{ TYPES DEFINITION }
-const
- org_mono8 = 8;
- org_color16 = 16;
- org_color24 = 24;
- org_color32 = 32;
- org_color48 = 48;
- org_color64 = 64;
-
-type
- pixel_map = object
- m_bmp : PBITMAPINFO;
- m_buf : pointer;
- m_bpp : unsigned;
-
- m_is_internal : boolean;
-
- m_img_size ,
- m_full_size : unsigned;
-
- constructor Construct;
- destructor Destruct;
-
- procedure destroy;
- procedure create(width_ ,height_ ,org : unsigned; clear_val : unsigned = 256 );
-
- function load_from_bmp(var fd : file ) : boolean; overload;
- function load_from_bmp(filename : shortstring ) : boolean; overload;
-
- function save_as_bmp(var fd : file ) : boolean; overload;
- function save_as_bmp(filename : shortstring ) : boolean; overload;
-
- procedure draw(h_dc : HDC; device_rect : PRect = NIL; bmp_rect : PRect = NIL ); overload;
- procedure draw(h_dc : HDC; x ,y : int; scale : double = 1.0 ); overload;
-
- function _buf : pointer;
- function _width : unsigned;
- function _height : unsigned;
- function _stride : int;
- function _bpp : unsigned;
-
- function create_bitmap_info (width_ ,height_ ,bits_per_pixel : unsigned ) : PBITMAPINFO;
- procedure create_gray_scale_palette(bmp : PBITMAPINFO );
-
- function calc_full_size (bmp : PBITMAPINFO ) : unsigned;
- function calc_header_size(bmp : PBITMAPINFO ) : unsigned;
- function calc_img_ptr (bmp : PBITMAPINFO ) : unsigned;
-
- function calc_palette_size(clr_used ,bits_per_pixel : unsigned ) : unsigned; overload;
- function calc_palette_size(bmp : PBITMAPINFO ) : unsigned; overload;
-
- function calc_row_len (width_ ,bits_per_pixel : unsigned ) : unsigned;
- procedure create_from_bmp(bmp : PBITMAPINFO );
-
- end;
-
-{ GLOBAL PROCEDURES }
-
-
-IMPLEMENTATION
-{ LOCAL VARIABLES & CONSTANTS }
-{ UNIT IMPLEMENTATION }
-{ CONSTRUCT }
-constructor pixel_map.Construct;
-begin
- m_bmp:=NIL;
- m_buf:=NIL;
- m_bpp:=0;
-
- m_is_internal:=false;
-
- m_img_size :=0;
- m_full_size:=0;
-
-end;
-
-{ DESTRUCT }
-destructor pixel_map.Destruct;
-begin
- destroy;
-
-end;
-
-{ DESTROY }
-procedure pixel_map.destroy;
-begin
- if (m_bmp <> NIL ) and
- m_is_internal then
- agg_freemem(pointer(m_bmp ) ,m_full_size );
-
- m_bmp:=NIL;
- m_buf:=NIL;
-
- m_is_internal:=false;
-
-end;
-
-{ CREATE }
-procedure pixel_map.create;
-begin
- destroy;
-
- if width_ = 0 then
- width_:=1;
-
- if height_ = 0 then
- height_:=1;
-
- m_bpp:=org;
-
- create_from_bmp(create_bitmap_info(width_ ,height_ ,m_bpp ) );
-
- create_gray_scale_palette(m_bmp );
-
- m_is_internal:=true;
-
- if clear_val <= 255 then
- fillchar(m_buf^ ,m_img_size ,clear_val );
-
-end;
-
-{ LOAD_FROM_BMP }
-function pixel_map.load_from_bmp(var fd : file ) : boolean;
-var
- sz : int;
-
- bmf : BITMAPFILEHEADER;
- bmi : PBITMAPINFO;
-
- bmp_size : unsigned;
-
-label
- bmperr;
-
-begin
- blockread(fd ,bmf ,sizeof(bmf ) );
-
- if bmf.bfType <> $4D42 then
- goto bmperr;
-
- bmp_size:=bmf.bfSize - sizeof(BITMAPFILEHEADER );
-
- agg_getmem(pointer(bmi ) ,bmp_size );
- blockread (fd ,bmi^ ,bmp_size ,sz );
-
- if sz <> bmp_size then
- goto bmperr;
-
- destroy;
-
- m_bpp:=bmi.bmiHeader.biBitCount;
-
- create_from_bmp(bmi );
-
- m_is_internal:=true;
-
- result:=true;
-
- exit;
-
-bmperr:
- if bmi <> NIL then
- agg_freemem(pointer(bmi ) ,bmp_size );
-
- result:=false;
-
-end;
-
-{ LOAD_FROM_BMP }
-function pixel_map.load_from_bmp(filename : shortstring ) : boolean;
-var
- fd : file;
- err : integer;
- ret : boolean;
-
-begin
-{$I- }
- err:=ioresult;
-
- assignfile(fd ,filename );
- reset (fd ,1 );
-
- err:=ioresult;
- ret:=false;
-
- if err = 0 then
- begin
- ret:=load_from_bmp(fd );
-
- close(fd );
-
- end;
-
- result:=ret;
-
-end;
-
-{ SAVE_AS_BMP }
-function pixel_map.save_as_bmp(var fd : file ) : boolean;
-var
- bmf : BITMAPFILEHEADER;
-
-begin
- if m_bmp = NIL then
- result:=false
-
- else
- begin
- bmf.bfType :=$4D42;
- bmf.bfOffBits :=calc_header_size(m_bmp ) + sizeof(bmf );
- bmf.bfSize :=bmf.bfOffBits + m_img_size;
- bmf.bfReserved1:=0;
- bmf.bfReserved2:=0;
-
- blockwrite(fd ,bmf ,sizeof(bmf ) );
- blockwrite(fd ,m_bmp^ ,m_full_size );
-
- result:=true;
-
- end;
-
-end;
-
-{ SAVE_AS_BMP }
-function pixel_map.save_as_bmp(filename : shortstring ) : boolean;
-var
- fd : file;
- err : integer;
- ret : boolean;
-
-begin
-{$I- }
- err:=ioresult;
-
- assignfile(fd ,filename );
- rewrite (fd ,1 );
-
- err:=ioresult;
- ret:=false;
-
- if err = 0 then
- begin
- ret:=save_as_bmp(fd );
-
- close(fd );
-
- end;
-
- result:=ret;
-
-end;
-
-{ DRAW }
-procedure pixel_map.draw(h_dc : HDC; device_rect : PRect = NIL; bmp_rect : PRect = NIL );
-var
- bmp_x ,
- bmp_y ,
-
- bmp_width ,
- bmp_height ,
-
- dvc_x ,
- dvc_y ,
-
- dvc_width ,
- dvc_height : unsigned;
-
- err : int;
- bok : boolean;
-
- compdc : HDC;
- handle ,
- backup : HBITMAP;
- bminfo : TBitmapInfo;
- buffer : pointer;
-
- rinc ,rgap ,size ,stride : int;
-
-begin
- if (m_bmp = NIL ) or
- (m_buf = NIL ) then
- exit;
-
- bmp_x:=0;
- bmp_y:=0;
-
- bmp_width :=m_bmp.bmiHeader.biWidth;
- bmp_height:=m_bmp.bmiHeader.biHeight;
-
- dvc_x:=0;
- dvc_y:=0;
-
- dvc_width :=m_bmp.bmiHeader.biWidth;
- dvc_height:=m_bmp.bmiHeader.biHeight;
-
- if bmp_rect <> NIL then
- begin
- bmp_x :=bmp_rect.left;
- bmp_y :=bmp_rect.top;
- bmp_width :=bmp_rect.right - bmp_rect.left;
- bmp_height:=bmp_rect.bottom - bmp_rect.top;
-
- end;
-
- dvc_x :=bmp_x;
- dvc_x :=bmp_x;
- dvc_width :=bmp_width;
- dvc_height:=bmp_height;
-
- if device_rect <> NIL then
- begin
- dvc_x :=device_rect.left;
- dvc_y :=device_rect.top;
- dvc_width :=device_rect.right - device_rect.left;
- dvc_height:=device_rect.bottom - device_rect.top;
-
- end;
-
- if (dvc_width <> bmp_width ) or
- (dvc_height <> bmp_height ) then
- begin
- SetStretchBltMode(h_dc ,COLORONCOLOR );
-
- StretchDIBits(
- h_dc , // handle of device context
- dvc_x , // x-coordinate of upper-left corner of source rect.
- dvc_y , // y-coordinate of upper-left corner of source rect.
- dvc_width , // width of source rectangle
- dvc_height , // height of source rectangle
- bmp_x ,
- bmp_y , // x, y -coordinates of upper-left corner of dest. rect.
- bmp_width , // width of destination rectangle
- bmp_height , // height of destination rectangle
- m_buf , // address of bitmap bits
- m_bmp^ , // address of bitmap data
- DIB_RGB_COLORS , // usage
- SRCCOPY ); // raster operation code
-
- end
- else
- begin
- err:=SetDIBitsToDevice(
- h_dc , // handle to device context
- dvc_x , // x-coordinate of upper-left corner of
- dvc_y , // y-coordinate of upper-left corner of
- dvc_width , // source rectangle width
- dvc_height , // source rectangle height
- bmp_x , // x-coordinate of lower-left corner of
- bmp_y , // y-coordinate of lower-left corner of
- 0 , // first scan line in array
- bmp_height , // number of scan lines
- m_buf , // address of array with DIB bits
- m_bmp^ , // address of structure with bitmap info.
- DIB_RGB_COLORS ); // RGB or palette indexes
-
- {hack}
- if err = 0 then
- begin
- compdc:=CreateCompatibleDC(h_dc );
-
- if compdc <> 0 then
- begin
- fillchar(bminfo ,sizeof(TBitmapInfoHeader ) ,0 );
-
- bminfo.bmiHeader.biSize :=m_bmp.bmiHeader.biSize;
- bminfo.bmiHeader.biCompression:=m_bmp.bmiHeader.biCompression;
-
- bminfo.bmiHeader.biPlanes :=m_bmp.bmiHeader.biPlanes;
- bminfo.bmiHeader.biBitCount:=m_bmp.bmiHeader.biBitCount;
-
- bminfo.bmiHeader.biWidth :=m_bmp.bmiHeader.biWidth;
- bminfo.bmiHeader.biHeight:=m_bmp.bmiHeader.biHeight;
-
- handle:=CreateDIBSection(compdc ,bminfo ,DIB_RGB_COLORS ,buffer ,0 ,0 );
- stride:=_stride;
-
- rinc:=((bminfo.bmiHeader.biWidth * bminfo.bmiHeader.biBitCount + 31 ) shr 5 ) shl 2;
- rgap:=bminfo.bmiHeader.biWidth mod 4;
- size:=rinc * bminfo.bmiHeader.biHeight;
-
- if handle <> 0 then
- begin
- backup:=SelectObject(compdc ,handle );
-
- if (rinc = stride ) and
- (size = m_img_size ) then
- begin
- move(m_buf^ ,buffer^ ,size );
-
- bok:=BitBlt(
- h_dc ,dvc_x ,dvc_y ,dvc_width ,dvc_height ,
- compdc ,bmp_x ,bmp_y ,
- SRCCOPY );
-
- end
- else
- MessageBox(0 ,'Cannot draw - different format !' ,'pixel_map.draw message' ,MB_OK );
-
- if backup <> 0 then
- SelectObject(compdc ,backup );
-
- DeleteObject(handle );
-
- end;
-
- DeleteDC(compdc );
-
- end;
-
- end;
-
- end;
-
-end;
-
-{ DRAW }
-procedure pixel_map.draw(h_dc : HDC; x ,y : int; scale : double = 1.0 );
-var
- rect : TRect;
-
- width_ ,
- height_ : unsigned;
-
-begin
- if (m_bmp = NIL ) or
- (m_buf = NIL ) then
- exit;
-
- width_ :=trunc(m_bmp.bmiHeader.biWidth * scale );
- height_:=trunc(m_bmp.bmiHeader.biHeight * scale );
-
- rect.left :=x;
- rect.top :=y;
- rect.right :=x + width_;
- rect.bottom:=y + height_;
-
- draw(h_dc ,@rect );
-
-end;
-
-{ _BUF }
-function pixel_map._buf;
-begin
- result:=m_buf;
-
-end;
-
-{ _WIDTH }
-function pixel_map._width;
-begin
- result:=m_bmp.bmiHeader.biWidth;
-
-end;
-
-{ _HEIGHT }
-function pixel_map._height;
-begin
- result:=m_bmp.bmiHeader.biHeight;
-
-end;
-
-{ _STRIDE }
-function pixel_map._stride;
-begin
- result:=calc_row_len(m_bmp.bmiHeader.biWidth ,m_bmp.bmiHeader.biBitCount );
-
-end;
-
-{ _BPP }
-function pixel_map._bpp;
-begin
- result:=m_bpp;
-
-end;
-
-{ CALC_FULL_SIZE }
-function pixel_map.calc_full_size;
-begin
- if bmp = NIL then
- result:=0
- else
- result:=
- sizeof(TBITMAPINFOHEADER ) +
- sizeof(RGBQUAD ) * calc_palette_size(bmp ) +
- bmp.bmiHeader.biSizeImage;
-
-end;
-
-{ CALC_HEADER_SIZE }
-function pixel_map.calc_header_size;
-begin
- if bmp = NIL then
- result:=0
- else
- result:=sizeof(TBITMAPINFOHEADER ) + sizeof(RGBQUAD ) * calc_palette_size(bmp );
-
-end;
-
-{ CALC_IMG_PTR }
-function pixel_map.calc_img_ptr;
-begin
- if bmp = NIL then
- result:=0
- else
- result:=ptrcomp(bmp ) + calc_header_size(bmp );
-
-end;
-
-{ CREATE_BITMAP_INFO }
-function pixel_map.create_bitmap_info;
-var
- bmp : PBITMAPINFO;
-
- line_len ,
- img_size ,
- rgb_size ,
- full_size : unsigned;
-
-begin
- line_len :=calc_row_len(width_ ,bits_per_pixel );
- img_size :=line_len * height_;
- rgb_size :=calc_palette_size(0 ,bits_per_pixel ) * sizeof(RGBQUAD );
- full_size:=sizeof(TBITMAPINFOHEADER ) + rgb_size + img_size;
-
- agg_getmem(pointer(bmp ) ,full_size );
- fillchar (bmp^ ,full_size ,0 );
-
- bmp.bmiHeader.biSize :=sizeof(TBITMAPINFOHEADER );
- bmp.bmiHeader.biWidth :=width_;
- bmp.bmiHeader.biHeight :=height_;
- bmp.bmiHeader.biPlanes :=1;
- bmp.bmiHeader.biBitCount :=bits_per_pixel;
- bmp.bmiHeader.biCompression :=0;
- bmp.bmiHeader.biSizeImage :=img_size;
- bmp.bmiHeader.biXPelsPerMeter:=0;
- bmp.bmiHeader.biYPelsPerMeter:=0;
- bmp.bmiHeader.biClrUsed :=0;
- bmp.bmiHeader.biClrImportant :=0;
-
- result:=bmp;
-
-end;
-
-{ CREATE_GRAY_SCALE_PALETTE }
-procedure pixel_map.create_gray_scale_palette;
-var
- rgb : PRGBQUAD;
-
- i ,rgb_size ,
- brightness : unsigned;
-
-begin
- if bmp = NIL then
- exit;
-
- rgb_size:=calc_palette_size(bmp );
-
- rgb:=PRGBQUAD(ptrcomp(bmp ) + sizeof(TBITMAPINFOHEADER ) );
-
- if rgb_size > 0 then
- for i:=0 to rgb_size - 1 do
- begin
- brightness:=trunc((255 * i ) / (rgb_size - 1 ) );
-
- rgb.rgbBlue :=brightness;
- rgb.rgbGreen:=brightness;
- rgb.rgbRed :=brightness;
-
- rgb.rgbReserved:=0;
-
- inc(ptrcomp(rgb ) ,sizeof(RGBQUAD ) );
-
- end;
-
-end;
-
-{ CALC_PALETTE_SIZE }
-function pixel_map.calc_palette_size(clr_used ,bits_per_pixel : unsigned ) : unsigned;
-var
- palette_size : int;
-
-begin
- palette_size:=0;
-
- if bits_per_pixel <= 8 then
- begin
- palette_size:=clr_used;
-
- if palette_size = 0 then
- palette_size:=1 shl bits_per_pixel;
-
- end;
-
- result:=palette_size;
-
-end;
-
-{ CALC_PALETTE_SIZE }
-function pixel_map.calc_palette_size(bmp : PBITMAPINFO ) : unsigned;
-begin
- if bmp = NIL then
- result:=0
- else
- result:=calc_palette_size(bmp.bmiHeader.biClrUsed ,bmp.bmiHeader.biBitCount );
-
-end;
-
-{ CALC_ROW_LEN }
-function pixel_map.calc_row_len;
-var
- n ,k : unsigned;
-
-begin
- n:=width_;
-
- case bits_per_pixel of
- 1 :
- begin
- k:=n;
- n:=n shr 3;
-
- if k and 7 <> 0 then
- inc(n );
-
- end;
-
- 4 :
- begin
- k:=n;
- n:=n shr 1;
-
- if k and 3 <> 0 then
- inc(n );
-
- end;
-
- 8 : NoP;
-
- 16 : n:=n * 2;
-
- 24 : n:=n * 3;
-
- 32 : n:=n * 4;
-
- 48 : n:=n * 6;
-
- 64 : n:=n * 8;
-
- else
- n:=0;
-
- end;
-
- result:=((n + 3 ) shr 2 ) shl 2;
-
-end;
-
-{ CREATE_FROM_BMP }
-procedure pixel_map.create_from_bmp;
-begin
- if bmp <> NIL then
- begin
- m_img_size:=
- calc_row_len(
- bmp.bmiHeader.biWidth ,
- bmp.bmiHeader.biBitCount ) * bmp.bmiHeader.biHeight;
-
- m_full_size:=calc_full_size(bmp );
-
- m_bmp:=bmp;
- m_buf:=pointer(calc_img_ptr(bmp ) );
-
- end;
-
-end;
-
-END.
-
+//----------------------------------------------------------------------------
+// Anti-Grain Geometry - Version 2.4 (Public License)
+// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
+//
+// Anti-Grain Geometry - Version 2.4 Release Milano 3 (AggPas 2.4 RM3)
+// Pascal Port By: Milan Marusinec alias Milano
+// milan@marusinec.sk
+// http://www.aggpas.org
+// Copyright (c) 2005-2006
+//
+// Permission to copy, use, modify, sell and distribute this software
+// is granted provided this copyright notice appears in all copies.
+// This software is provided "as is" without express or implied
+// warranty, and with no claim as to its suitability for any purpose.
+//
+//----------------------------------------------------------------------------
+// Contact: mcseem@antigrain.com
+// mcseemagg@yahoo.com
+// http://www.antigrain.com
+//
+//----------------------------------------------------------------------------
+//
+// class pixel_map
+//
+// [Pascal Port History] -----------------------------------------------------
+//
+// 23.06.2006-Milano: ptrcomp adjustments
+// 15.12.2005-Milano: Unit port establishment
+//
+{ agg_win32_bmp.pas }
+unit
+ agg_win32_bmp ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+
+uses
+ Windows ,
+ agg_basics ;
+
+{ TYPES DEFINITION }
+const
+ org_mono8 = 8;
+ org_color16 = 16;
+ org_color24 = 24;
+ org_color32 = 32;
+ org_color48 = 48;
+ org_color64 = 64;
+
+type
+ pixel_map = object
+ m_bmp : PBITMAPINFO;
+ m_buf : pointer;
+ m_bpp : unsigned;
+
+ m_is_internal : boolean;
+
+ m_img_size ,
+ m_full_size : unsigned;
+
+ constructor Construct;
+ destructor Destruct;
+
+ procedure destroy;
+ procedure create(width_ ,height_ ,org : unsigned; clear_val : unsigned = 256 );
+
+ function load_from_bmp(var fd : file ) : boolean; overload;
+ function load_from_bmp(filename : shortstring ) : boolean; overload;
+
+ function save_as_bmp(var fd : file ) : boolean; overload;
+ function save_as_bmp(filename : shortstring ) : boolean; overload;
+
+ procedure draw(h_dc : HDC; device_rect : PRect = NIL; bmp_rect : PRect = NIL ); overload;
+ procedure draw(h_dc : HDC; x ,y : int; scale : double = 1.0 ); overload;
+
+ function _buf : pointer;
+ function _width : unsigned;
+ function _height : unsigned;
+ function _stride : int;
+ function _bpp : unsigned;
+
+ function create_bitmap_info (width_ ,height_ ,bits_per_pixel : unsigned ) : PBITMAPINFO;
+ procedure create_gray_scale_palette(bmp : PBITMAPINFO );
+
+ function calc_full_size (bmp : PBITMAPINFO ) : unsigned;
+ function calc_header_size(bmp : PBITMAPINFO ) : unsigned;
+ function calc_img_ptr (bmp : PBITMAPINFO ) : unsigned;
+
+ function calc_palette_size(clr_used ,bits_per_pixel : unsigned ) : unsigned; overload;
+ function calc_palette_size(bmp : PBITMAPINFO ) : unsigned; overload;
+
+ function calc_row_len (width_ ,bits_per_pixel : unsigned ) : unsigned;
+ procedure create_from_bmp(bmp : PBITMAPINFO );
+
+ end;
+
+{ GLOBAL PROCEDURES }
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+{ UNIT IMPLEMENTATION }
+{ CONSTRUCT }
+constructor pixel_map.Construct;
+begin
+ m_bmp:=NIL;
+ m_buf:=NIL;
+ m_bpp:=0;
+
+ m_is_internal:=false;
+
+ m_img_size :=0;
+ m_full_size:=0;
+
+end;
+
+{ DESTRUCT }
+destructor pixel_map.Destruct;
+begin
+ destroy;
+
+end;
+
+{ DESTROY }
+procedure pixel_map.destroy;
+begin
+ if (m_bmp <> NIL ) and
+ m_is_internal then
+ agg_freemem(pointer(m_bmp ) ,m_full_size );
+
+ m_bmp:=NIL;
+ m_buf:=NIL;
+
+ m_is_internal:=false;
+
+end;
+
+{ CREATE }
+procedure pixel_map.create;
+begin
+ destroy;
+
+ if width_ = 0 then
+ width_:=1;
+
+ if height_ = 0 then
+ height_:=1;
+
+ m_bpp:=org;
+
+ create_from_bmp(create_bitmap_info(width_ ,height_ ,m_bpp ) );
+
+ create_gray_scale_palette(m_bmp );
+
+ m_is_internal:=true;
+
+ if clear_val <= 255 then
+ fillchar(m_buf^ ,m_img_size ,clear_val );
+
+end;
+
+{ LOAD_FROM_BMP }
+function pixel_map.load_from_bmp(var fd : file ) : boolean;
+var
+ sz : int;
+
+ bmf : BITMAPFILEHEADER;
+ bmi : PBITMAPINFO;
+
+ bmp_size : unsigned;
+
+label
+ bmperr;
+
+begin
+ blockread(fd ,bmf ,sizeof(bmf ) );
+
+ if bmf.bfType <> $4D42 then
+ goto bmperr;
+
+ bmp_size:=bmf.bfSize - sizeof(BITMAPFILEHEADER );
+
+ agg_getmem(pointer(bmi ) ,bmp_size );
+ blockread (fd ,bmi^ ,bmp_size ,sz );
+
+ if sz <> bmp_size then
+ goto bmperr;
+
+ destroy;
+
+ m_bpp:=bmi.bmiHeader.biBitCount;
+
+ create_from_bmp(bmi );
+
+ m_is_internal:=true;
+
+ result:=true;
+
+ exit;
+
+bmperr:
+ if bmi <> NIL then
+ agg_freemem(pointer(bmi ) ,bmp_size );
+
+ result:=false;
+
+end;
+
+{ LOAD_FROM_BMP }
+function pixel_map.load_from_bmp(filename : shortstring ) : boolean;
+var
+ fd : file;
+ err : integer;
+ ret : boolean;
+
+begin
+{$I- }
+ err:=ioresult;
+
+ assignfile(fd ,filename );
+ reset (fd ,1 );
+
+ err:=ioresult;
+ ret:=false;
+
+ if err = 0 then
+ begin
+ ret:=load_from_bmp(fd );
+
+ close(fd );
+
+ end;
+
+ result:=ret;
+
+end;
+
+{ SAVE_AS_BMP }
+function pixel_map.save_as_bmp(var fd : file ) : boolean;
+var
+ bmf : BITMAPFILEHEADER;
+
+begin
+ if m_bmp = NIL then
+ result:=false
+
+ else
+ begin
+ bmf.bfType :=$4D42;
+ bmf.bfOffBits :=calc_header_size(m_bmp ) + sizeof(bmf );
+ bmf.bfSize :=bmf.bfOffBits + m_img_size;
+ bmf.bfReserved1:=0;
+ bmf.bfReserved2:=0;
+
+ blockwrite(fd ,bmf ,sizeof(bmf ) );
+ blockwrite(fd ,m_bmp^ ,m_full_size );
+
+ result:=true;
+
+ end;
+
+end;
+
+{ SAVE_AS_BMP }
+function pixel_map.save_as_bmp(filename : shortstring ) : boolean;
+var
+ fd : file;
+ err : integer;
+ ret : boolean;
+
+begin
+{$I- }
+ err:=ioresult;
+
+ assignfile(fd ,filename );
+ rewrite (fd ,1 );
+
+ err:=ioresult;
+ ret:=false;
+
+ if err = 0 then
+ begin
+ ret:=save_as_bmp(fd );
+
+ close(fd );
+
+ end;
+
+ result:=ret;
+
+end;
+
+{ DRAW }
+procedure pixel_map.draw(h_dc : HDC; device_rect : PRect = NIL; bmp_rect : PRect = NIL );
+var
+ bmp_x ,
+ bmp_y ,
+
+ bmp_width ,
+ bmp_height ,
+
+ dvc_x ,
+ dvc_y ,
+
+ dvc_width ,
+ dvc_height : unsigned;
+
+ err : int;
+ bok : boolean;
+
+ compdc : HDC;
+ handle ,
+ backup : HBITMAP;
+ bminfo : TBitmapInfo;
+ buffer : pointer;
+
+ rinc ,rgap ,size ,stride : int;
+
+begin
+ if (m_bmp = NIL ) or
+ (m_buf = NIL ) then
+ exit;
+
+ bmp_x:=0;
+ bmp_y:=0;
+
+ bmp_width :=m_bmp.bmiHeader.biWidth;
+ bmp_height:=m_bmp.bmiHeader.biHeight;
+
+ dvc_x:=0;
+ dvc_y:=0;
+
+ dvc_width :=m_bmp.bmiHeader.biWidth;
+ dvc_height:=m_bmp.bmiHeader.biHeight;
+
+ if bmp_rect <> NIL then
+ begin
+ bmp_x :=bmp_rect.left;
+ bmp_y :=bmp_rect.top;
+ bmp_width :=bmp_rect.right - bmp_rect.left;
+ bmp_height:=bmp_rect.bottom - bmp_rect.top;
+
+ end;
+
+ dvc_x :=bmp_x;
+ dvc_x :=bmp_x;
+ dvc_width :=bmp_width;
+ dvc_height:=bmp_height;
+
+ if device_rect <> NIL then
+ begin
+ dvc_x :=device_rect.left;
+ dvc_y :=device_rect.top;
+ dvc_width :=device_rect.right - device_rect.left;
+ dvc_height:=device_rect.bottom - device_rect.top;
+
+ end;
+
+ if (dvc_width <> bmp_width ) or
+ (dvc_height <> bmp_height ) then
+ begin
+ SetStretchBltMode(h_dc ,COLORONCOLOR );
+
+ StretchDIBits(
+ h_dc , // handle of device context
+ dvc_x , // x-coordinate of upper-left corner of source rect.
+ dvc_y , // y-coordinate of upper-left corner of source rect.
+ dvc_width , // width of source rectangle
+ dvc_height , // height of source rectangle
+ bmp_x ,
+ bmp_y , // x, y -coordinates of upper-left corner of dest. rect.
+ bmp_width , // width of destination rectangle
+ bmp_height , // height of destination rectangle
+ m_buf , // address of bitmap bits
+ m_bmp^ , // address of bitmap data
+ DIB_RGB_COLORS , // usage
+ SRCCOPY ); // raster operation code
+
+ end
+ else
+ begin
+ err:=SetDIBitsToDevice(
+ h_dc , // handle to device context
+ dvc_x , // x-coordinate of upper-left corner of
+ dvc_y , // y-coordinate of upper-left corner of
+ dvc_width , // source rectangle width
+ dvc_height , // source rectangle height
+ bmp_x , // x-coordinate of lower-left corner of
+ bmp_y , // y-coordinate of lower-left corner of
+ 0 , // first scan line in array
+ bmp_height , // number of scan lines
+ m_buf , // address of array with DIB bits
+ m_bmp^ , // address of structure with bitmap info.
+ DIB_RGB_COLORS ); // RGB or palette indexes
+
+ {hack}
+ if err = 0 then
+ begin
+ compdc:=CreateCompatibleDC(h_dc );
+
+ if compdc <> 0 then
+ begin
+ fillchar(bminfo ,sizeof(TBitmapInfoHeader ) ,0 );
+
+ bminfo.bmiHeader.biSize :=m_bmp.bmiHeader.biSize;
+ bminfo.bmiHeader.biCompression:=m_bmp.bmiHeader.biCompression;
+
+ bminfo.bmiHeader.biPlanes :=m_bmp.bmiHeader.biPlanes;
+ bminfo.bmiHeader.biBitCount:=m_bmp.bmiHeader.biBitCount;
+
+ bminfo.bmiHeader.biWidth :=m_bmp.bmiHeader.biWidth;
+ bminfo.bmiHeader.biHeight:=m_bmp.bmiHeader.biHeight;
+
+ handle:=CreateDIBSection(compdc ,bminfo ,DIB_RGB_COLORS ,buffer ,0 ,0 );
+ stride:=_stride;
+
+ rinc:=((bminfo.bmiHeader.biWidth * bminfo.bmiHeader.biBitCount + 31 ) shr 5 ) shl 2;
+ rgap:=bminfo.bmiHeader.biWidth mod 4;
+ size:=rinc * bminfo.bmiHeader.biHeight;
+
+ if handle <> 0 then
+ begin
+ backup:=SelectObject(compdc ,handle );
+
+ if (rinc = stride ) and
+ (size = m_img_size ) then
+ begin
+ move(m_buf^ ,buffer^ ,size );
+
+ bok:=BitBlt(
+ h_dc ,dvc_x ,dvc_y ,dvc_width ,dvc_height ,
+ compdc ,bmp_x ,bmp_y ,
+ SRCCOPY );
+
+ end
+ else
+ MessageBox(0 ,'Cannot draw - different format !' ,'pixel_map.draw message' ,MB_OK );
+
+ if backup <> 0 then
+ SelectObject(compdc ,backup );
+
+ DeleteObject(handle );
+
+ end;
+
+ DeleteDC(compdc );
+
+ end;
+
+ end;
+
+ end;
+
+end;
+
+{ DRAW }
+procedure pixel_map.draw(h_dc : HDC; x ,y : int; scale : double = 1.0 );
+var
+ rect : TRect;
+
+ width_ ,
+ height_ : unsigned;
+
+begin
+ if (m_bmp = NIL ) or
+ (m_buf = NIL ) then
+ exit;
+
+ width_ :=trunc(m_bmp.bmiHeader.biWidth * scale );
+ height_:=trunc(m_bmp.bmiHeader.biHeight * scale );
+
+ rect.left :=x;
+ rect.top :=y;
+ rect.right :=x + width_;
+ rect.bottom:=y + height_;
+
+ draw(h_dc ,@rect );
+
+end;
+
+{ _BUF }
+function pixel_map._buf;
+begin
+ result:=m_buf;
+
+end;
+
+{ _WIDTH }
+function pixel_map._width;
+begin
+ result:=m_bmp.bmiHeader.biWidth;
+
+end;
+
+{ _HEIGHT }
+function pixel_map._height;
+begin
+ result:=m_bmp.bmiHeader.biHeight;
+
+end;
+
+{ _STRIDE }
+function pixel_map._stride;
+begin
+ result:=calc_row_len(m_bmp.bmiHeader.biWidth ,m_bmp.bmiHeader.biBitCount );
+
+end;
+
+{ _BPP }
+function pixel_map._bpp;
+begin
+ result:=m_bpp;
+
+end;
+
+{ CALC_FULL_SIZE }
+function pixel_map.calc_full_size;
+begin
+ if bmp = NIL then
+ result:=0
+ else
+ result:=
+ sizeof(TBITMAPINFOHEADER ) +
+ sizeof(RGBQUAD ) * calc_palette_size(bmp ) +
+ bmp.bmiHeader.biSizeImage;
+
+end;
+
+{ CALC_HEADER_SIZE }
+function pixel_map.calc_header_size;
+begin
+ if bmp = NIL then
+ result:=0
+ else
+ result:=sizeof(TBITMAPINFOHEADER ) + sizeof(RGBQUAD ) * calc_palette_size(bmp );
+
+end;
+
+{ CALC_IMG_PTR }
+function pixel_map.calc_img_ptr;
+begin
+ if bmp = NIL then
+ result:=0
+ else
+ result:=ptrcomp(bmp ) + calc_header_size(bmp );
+
+end;
+
+{ CREATE_BITMAP_INFO }
+function pixel_map.create_bitmap_info;
+var
+ bmp : PBITMAPINFO;
+
+ line_len ,
+ img_size ,
+ rgb_size ,
+ full_size : unsigned;
+
+begin
+ line_len :=calc_row_len(width_ ,bits_per_pixel );
+ img_size :=line_len * height_;
+ rgb_size :=calc_palette_size(0 ,bits_per_pixel ) * sizeof(RGBQUAD );
+ full_size:=sizeof(TBITMAPINFOHEADER ) + rgb_size + img_size;
+
+ agg_getmem(pointer(bmp ) ,full_size );
+ fillchar (bmp^ ,full_size ,0 );
+
+ bmp.bmiHeader.biSize :=sizeof(TBITMAPINFOHEADER );
+ bmp.bmiHeader.biWidth :=width_;
+ bmp.bmiHeader.biHeight :=height_;
+ bmp.bmiHeader.biPlanes :=1;
+ bmp.bmiHeader.biBitCount :=bits_per_pixel;
+ bmp.bmiHeader.biCompression :=0;
+ bmp.bmiHeader.biSizeImage :=img_size;
+ bmp.bmiHeader.biXPelsPerMeter:=0;
+ bmp.bmiHeader.biYPelsPerMeter:=0;
+ bmp.bmiHeader.biClrUsed :=0;
+ bmp.bmiHeader.biClrImportant :=0;
+
+ result:=bmp;
+
+end;
+
+{ CREATE_GRAY_SCALE_PALETTE }
+procedure pixel_map.create_gray_scale_palette;
+var
+ rgb : PRGBQUAD;
+
+ i ,rgb_size ,
+ brightness : unsigned;
+
+begin
+ if bmp = NIL then
+ exit;
+
+ rgb_size:=calc_palette_size(bmp );
+
+ rgb:=PRGBQUAD(ptrcomp(bmp ) + sizeof(TBITMAPINFOHEADER ) );
+
+ if rgb_size > 0 then
+ for i:=0 to rgb_size - 1 do
+ begin
+ brightness:=trunc((255 * i ) / (rgb_size - 1 ) );
+
+ rgb.rgbBlue :=brightness;
+ rgb.rgbGreen:=brightness;
+ rgb.rgbRed :=brightness;
+
+ rgb.rgbReserved:=0;
+
+ inc(ptrcomp(rgb ) ,sizeof(RGBQUAD ) );
+
+ end;
+
+end;
+
+{ CALC_PALETTE_SIZE }
+function pixel_map.calc_palette_size(clr_used ,bits_per_pixel : unsigned ) : unsigned;
+var
+ palette_size : int;
+
+begin
+ palette_size:=0;
+
+ if bits_per_pixel <= 8 then
+ begin
+ palette_size:=clr_used;
+
+ if palette_size = 0 then
+ palette_size:=1 shl bits_per_pixel;
+
+ end;
+
+ result:=palette_size;
+
+end;
+
+{ CALC_PALETTE_SIZE }
+function pixel_map.calc_palette_size(bmp : PBITMAPINFO ) : unsigned;
+begin
+ if bmp = NIL then
+ result:=0
+ else
+ result:=calc_palette_size(bmp.bmiHeader.biClrUsed ,bmp.bmiHeader.biBitCount );
+
+end;
+
+{ CALC_ROW_LEN }
+function pixel_map.calc_row_len;
+var
+ n ,k : unsigned;
+
+begin
+ n:=width_;
+
+ case bits_per_pixel of
+ 1 :
+ begin
+ k:=n;
+ n:=n shr 3;
+
+ if k and 7 <> 0 then
+ inc(n );
+
+ end;
+
+ 4 :
+ begin
+ k:=n;
+ n:=n shr 1;
+
+ if k and 3 <> 0 then
+ inc(n );
+
+ end;
+
+ 8 : NoP;
+
+ 16 : n:=n * 2;
+
+ 24 : n:=n * 3;
+
+ 32 : n:=n * 4;
+
+ 48 : n:=n * 6;
+
+ 64 : n:=n * 8;
+
+ else
+ n:=0;
+
+ end;
+
+ result:=((n + 3 ) shr 2 ) shl 2;
+
+end;
+
+{ CREATE_FROM_BMP }
+procedure pixel_map.create_from_bmp;
+begin
+ if bmp <> NIL then
+ begin
+ m_img_size:=
+ calc_row_len(
+ bmp.bmiHeader.biWidth ,
+ bmp.bmiHeader.biBitCount ) * bmp.bmiHeader.biHeight;
+
+ m_full_size:=calc_full_size(bmp );
+
+ m_bmp:=bmp;
+ m_buf:=pointer(calc_img_ptr(bmp ) );
+
+ end;
+
+end;
+
+END.
+
diff --git a/src/corelib/render/software/platform/win/file_utils_.pas b/src/corelib/render/software/platform/win/file_utils_.pas
index 525548e4..ef5ec27a 100644
--- a/src/corelib/render/software/platform/win/file_utils_.pas
+++ b/src/corelib/render/software/platform/win/file_utils_.pas
@@ -1,776 +1,776 @@
-//
-// AggPas 2.4 RM3 demo framework file utility library
-// Milan Marusinec alias Milano (c) 2006
-//
-unit
- file_utils_ ;
-
-INTERFACE
-
-{$I agg_mode.inc }
-{$I- }
-uses
- agg_basics ;
-
-{ TYPES DEFINITION }
-type
- api_file_ptr = ^api_file;
- api_file = record
- fileName : shortstring;
- isOpened : boolean;
-
- fSize ,
- fRead : int;
-
- // FSOpenFork parameters
- df : file;
-
- end;
-
-{ GLOBAL PROCEDURES }
- function cut_str(s : shortstring ) : shortstring;
- function up_str (s : shortstring ) : shortstring;
- function cmp_str(s : shortstring ) : shortstring;
-
- function str_dir(s : shortstring ) : shortstring;
- function dir_str(s : shortstring ) : shortstring;
-
- function str_disk(fn : shortstring ) : shortstring;
- function str_path(fn : shortstring ) : shortstring;
- function str_name(fn : shortstring ) : shortstring;
- function str_ext (fn : shortstring ) : shortstring;
-
- function fold_name (p ,n ,x : shortstring ) : shortstring;
- procedure spread_name(fn : shortstring; var p ,n ,x : shortstring );
-
- function file_exists(fn : shortstring ) : boolean;
-
- function api_open_file (var af : api_file; fname : shortstring ) : boolean;
- function api_read_file (var af : api_file; buff : pointer; aloc : int; var read : int ) : boolean;
- function api_close_file(var af : api_file ) : boolean;
-
- function param_count : int;
- function param_str(i : int ) : shortstring;
-
-
-IMPLEMENTATION
-{ LOCAL VARIABLES & CONSTANTS }
-type
- tSCAN = (
-
- SCAN_0 ,
- SCAN_1 ,SCAN_2 ,SCAN_3 ,SCAN_4 ,SCAN_5 ,SCAN_6 ,SCAN_7 ,SCAN_8 ,SCAN_9 ,
- SCAN_A ,SCAN_B ,SCAN_C ,SCAN_D ,SCAN_E ,SCAN_F ,SCAN_G ,SCAN_H ,SCAN_I ,
- SCAN_J ,SCAN_K ,SCAN_L ,SCAN_M ,SCAN_N ,SCAN_O ,SCAN_P ,SCAN_Q ,SCAN_R ,
- SCAN_S ,SCAN_T ,SCAN_U ,SCAN_V ,SCAN_W ,SCAN_X ,SCAN_Y ,SCAN_Z
-
- );
-
- tITEM = (
-
- ITEM_0 ,
- ITEM_1 ,ITEM_2 ,ITEM_3 ,ITEM_4 ,ITEM_5 ,ITEM_6 ,ITEM_7 ,ITEM_8 ,ITEM_9 ,
- ITEM_A ,ITEM_B ,ITEM_C ,ITEM_D ,ITEM_E ,ITEM_F ,ITEM_G ,ITEM_H ,ITEM_I ,
- ITEM_J ,ITEM_K ,ITEM_L ,ITEM_M ,ITEM_N ,ITEM_O ,ITEM_P ,ITEM_Q ,ITEM_R ,
- ITEM_S ,ITEM_T ,ITEM_U ,ITEM_V ,ITEM_W ,ITEM_X ,ITEM_Y ,ITEM_Z
-
- );
-
-const
- dir_slash = '\';
-
- pageEqHigh : shortstring =
- #1#2#3#4#5#6#7#8#9#10#11#12#13#14#15#16 +
- #17#18#19#20#21#22#23#24#25#26#27#28#29#30#31#32 +
- #33#34#35#36#37#38#39#40#41#42#43#44#45#46#47#48 +
- #49#50#51#52#53#54#55#56#57#58#59#60#61#62#63#64 +
- #65#66#67#68#69#70#71#72#73#74#75#76#77#78#79#80 +
- #81#82#83#84#85#86#87#88#89#90#91#92#93#94#95#96 +
- #65#66#67#68#69#70#71#72#73#74#75#76#77#78#79#80 +
- #81#82#83#84#85#86#87#88#89#90#123#124#125#126#127#128 +
- #129#130#131#132#133#134#135#136#137#138#139#140#141#142#143#144 +
- #145#146#147#148#149#150#151#152#153#154#155#156#157#158#159#160 +
- #161#162#163#164#165#166#167#168#169#170#171#172#173#174#175#176 +
- #177#178#179#180#181#182#183#184#185#186#187#188#189#190#191#192 +
- #193#194#195#196#197#198#199#200#201#202#203#204#205#206#207#208 +
- #209#210#211#212#213#214#215#216#217#218#219#220#221#222#223#224 +
- #225#226#227#228#229#230#231#232#233#234#235#236#237#238#239#240 +
- #241#242#243#244#245#246#247#248#249#250#251#252#253#254#255;
-
-{ UNIT IMPLEMENTATION }
-{ CUT_STR }
-function cut_str;
-var
- fcb : byte;
- scn : tSCAN;
-
-begin
- result:='';
-
- scn:=SCAN_1;
-
- if length(s ) > 0 then
- for fcb:=length(s ) downto 1 do
- case scn of
- SCAN_1 :
- case s[fcb ] of
- ' ' :
- else
- begin
- result:=s[fcb ];
-
- scn:=SCAN_2;
-
- end;
-
- end;
-
- SCAN_2 :
- result:=s[fcb ] + result;
-
- end;
-
-end;
-
-{ CMP_STR }
-function cmp_str;
-begin
- cmp_str:=up_str(cut_str(s ) );
-
-end;
-
-{ UP_STR }
-function up_str;
-var
- fcb : byte;
-
-begin
- if length(s ) > 0 then
- for fcb:=1 to length(s ) do
- if byte(s[fcb ] ) > 0 then
- s[fcb ]:=pageEqHigh[byte(s[fcb ] ) ];
-
- result:=s;
-
-end;
-
-{ STR_DIR }
-function str_dir;
-begin
- s:=cut_str(s );
-
- if length(s ) > 0 then
- if s[length(s ) ] <> dir_slash then
- s:=s + dir_slash;
-
- result:=s;
-
-end;
-
-{ DIR_STR }
-function dir_str;
-begin
- s:=cut_str(s );
-
- if length(s ) > 0 then
- if s[length(s ) ] = dir_slash then
- dec(byte(s[0 ] ) );
-
- result:=s;
-
-end;
-
-{ STR_DISK }
-function str_disk;
-var
- fcb : byte;
- str : shortstring;
- itm : tITEM;
-
-begin
- str:='';
- itm:=ITEM_1;
-
- if length(fn ) > 0 then
- for fcb:=1 to length(fn ) do
- case itm of
- ITEM_1 :
- case fn[fcb ] of
- 'a'..'z' ,'A'..'Z' :
- begin
- str:=fn[fcb ];
- itm:=ITEM_2;
-
- end;
-
- '\' ,'/' :
- begin
- str:=fn[fcb ];
- itm:=ITEM_3;
-
- end;
-
- else
- break;
-
- end;
-
- ITEM_2 :
- case fn[fcb ] of
- ':' :
- begin
- str:=str + fn[fcb ];
- itm:=ITEM_F;
-
- break;
-
- end;
-
- else
- break;
-
- end;
-
- ITEM_3 :
- case fn[fcb ] of
- '\' ,'/' :
- begin
- str:=str + fn[fcb ];
- itm:=ITEM_4;
-
- end;
-
- else
- break;
-
- end;
-
- ITEM_4 :
- case fn[fcb ] of
- '\' ,'/' ,':' ,'<' ,'>' ,'.' ,'"' ,'|' ,#0..#31 :
- break;
-
- else
- begin
- str:=str + fn[fcb ];
- itm:=ITEM_F;
-
- end;
-
- end;
-
- ITEM_F :
- case fn[fcb ] of
- '\' ,'/' :
- break;
-
- else
- str:=str + fn[fcb ];
-
- end;
-
- end;
-
- if itm = ITEM_F then
- result:=str
- else
- result:='';
-
-end;
-
-{ STR_PATH }
-function str_path;
-var
- fcb : byte;
- pth ,
- str : shortstring;
- itm : tITEM;
-
-begin
- pth:='';
- str:='';
- itm:=ITEM_1;
-
- if length(fn ) > 0 then
- for fcb:=1 to length(fn ) do
- case itm of
- ITEM_1 :
- case fn[fcb ] of
- '\' ,'/' :
- begin
- str:=fn[fcb ];
- itm:=ITEM_2;
-
- end;
-
- else
- begin
- str:=fn[fcb ];
- itm:=ITEM_3;
-
- end;
-
- end;
-
- ITEM_2 :
- case fn[fcb ] of
- '\' ,'/' :
- begin
- str:=str + fn[fcb ];
- itm:=ITEM_3;
-
- end;
-
- else
- begin
- pth:=str;
- str:=fn[fcb ];
- itm:=ITEM_A;
-
- end;
-
- end;
-
- ITEM_3 :
- case fn[fcb ] of
- '\' ,'/' :
- begin
- pth:=fn[fcb ];
- str:='';
- itm:=ITEM_A;
-
- end;
-
- else
- str:=str + fn[fcb ];
-
- end;
-
- ITEM_A :
- case fn[fcb ] of
- '\' ,'/' :
- begin
- pth:=pth + str + fn[fcb ];
- str:='';
-
- end;
-
- else
- str:=str + fn[fcb ];
-
- end;
-
- end;
-
- result:=pth;
-
-end;
-
-{ STR_NAME }
-function str_name;
-var
- fcb : byte;
- str ,
- ext : shortstring;
- itm : tITEM;
-
-begin
- str:='';
- ext:='';
- itm:=ITEM_1;
-
- if length(fn ) > 0 then
- for fcb:=1 to length(fn ) do
- case itm of
- ITEM_1 :
- case fn[fcb ] of
- '\' ,'/' :
- itm:=ITEM_2;
-
- 'a'..'z' ,'A'..'Z' :
- begin
- ext:=fn[fcb ];
- itm:=ITEM_4;
-
- end;
-
- '.' :
- begin
- str:='';
- ext:=fn[fcb ];
- itm:=ITEM_B;
-
- end;
-
- else
- begin
- str:=fn[fcb ];
- itm:=ITEM_A;
-
- end;
-
- end;
-
- ITEM_2 :
- case fn[fcb ] of
- '\' ,'/' :
- itm:=ITEM_3;
-
- '.' :
- begin
- str:='';
- ext:=fn[fcb ];
- itm:=ITEM_B;
-
- end;
-
- else
- begin
- str:=fn[fcb ];
- itm:=ITEM_A;
-
- end;
-
- end;
-
- ITEM_3 :
- case fn[fcb ] of
- '\' ,'/' :
- begin
- str:='';
- itm:=ITEM_A;
-
- end;
-
- end;
-
- ITEM_4 :
- case fn[fcb ] of
- '\' ,'/' :
- begin
- str:='';
- itm:=ITEM_A;
-
- end;
-
- ':' :
- itm:=ITEM_5;
-
- '.' :
- begin
- str:=ext;
- ext:=fn[fcb ];
- itm:=ITEM_B;
-
- end;
-
- else
- begin
- str:=ext + fn[fcb ];
- ext:='';
- itm:=ITEM_A;
-
- end;
-
- end;
-
- ITEM_5 :
- case fn[fcb ] of
- '\' ,'/' :
- begin
- str:='';
- itm:=ITEM_A;
-
- end;
-
- '.' :
- begin
- str:='';
- ext:=fn[fcb ];
- itm:=ITEM_B;
-
- end;
-
- else
- begin
- str:=fn[fcb ];
- itm:=ITEM_A;
-
- end;
-
- end;
-
- ITEM_A :
- case fn[fcb ] of
- '\' ,'/' :
- begin
- str:='';
- ext:='';
-
- end;
-
- '.' :
- begin
- ext:=fn[fcb ];
- itm:=ITEM_B;
-
- end;
-
- else
- str:=str + fn[fcb ];
-
- end;
-
- ITEM_B :
- case fn[fcb ] of
- '\' ,'/' :
- begin
- str:='';
- ext:='';
- itm:=ITEM_A;
-
- end;
-
- '.' :
- begin
- str:=str + ext;
- ext:=fn[fcb ];
-
- end;
-
- end;
-
- end;
-
- result:=str;
-
-end;
-
-{ STR_EXT }
-function str_ext;
-var
- fcb : byte;
- ext : shortstring;
- itm : tITEM;
-
-begin
- ext:='';
- itm:=ITEM_1;
-
- if length(fn ) > 0 then
- for fcb:=1 to length(fn ) do
- case itm of
- ITEM_1 :
- case fn[fcb ] of
- '\' ,'/' :
- itm:=ITEM_2;
-
- '.' :
- begin
- ext:=fn[fcb ];
- itm:=ITEM_B;
-
- end;
-
- else
- itm:=ITEM_A;
-
- end;
-
- ITEM_2 :
- case fn[fcb ] of
- '\' ,'/' :
- itm:=ITEM_3;
-
- '.' :
- begin
- ext:=fn[fcb ];
- itm:=ITEM_B;
-
- end;
-
- else
- itm:=ITEM_A;
-
- end;
-
- ITEM_3 :
- case fn[fcb ] of
- '\' ,'/' :
- itm:=ITEM_A;
-
- end;
-
- ITEM_A :
- case fn[fcb ] of
- '.' :
- begin
- ext:=fn[fcb ];
- itm:=ITEM_B;
-
- end;
-
- end;
-
- ITEM_B :
- case fn[fcb ] of
- '\' ,'/' :
- begin
- ext:='';
- itm:=ITEM_A;
-
- end;
-
- '.' :
- ext:=fn[fcb ];
-
- else
- ext:=ext + fn[fcb ];
-
- end;
-
- end;
-
- result:=cut_str(ext );
-
- if result = '.' then
- result:='';
-
-end;
-
-{ FOLD_NAME }
-function fold_name;
-var
- dsk ,
- nme ,
- pth ,
- ext : shortstring;
-
-begin
- dsk:=str_disk(p );
- pth:=str_dir (str_path(p ) );
- nme:=str_name(n );
- ext:=str_ext (x );
-
- result:=dsk + pth + nme + ext;
-
-end;
-
-{ SPREAD_NAME }
-procedure spread_name;
-begin
- p:=str_disk(fn ) + str_dir(str_path(fn ) );
- n:=str_name(fn );
- x:=str_ext (fn );
-
-end;
-
-{ FILE_EXISTS }
-function file_exists;
-var
- f : file;
-
-begin
- AssignFile(f ,fn );
- reset (f );
-
- if IOResult = 0 then
- begin
- close(f );
-
- result:=true;
-
- end
- else
- result:=false;
-
-end;
-
-{ API_OPEN_FILE }
-function api_open_file;
-begin
- result:=false;
-
- fillchar(af ,sizeof(api_file ) ,0 );
-
- af.fileName:=fname;
- af.isOpened:=false;
-
- IOResult;
-
- AssignFile(af.df ,fname );
- reset (af.df ,1 );
-
- if IOResult = 0 then
- begin
- af.isOpened:=true;
-
- af.fSize:=filesize(af.df );
- af.fRead:=0;
-
- end;
-
- result:=af.isOpened;
-
-end;
-
-{ API_READ_FILE }
-function api_read_file;
-begin
- result:=false;
- read :=0;
-
- if af.isOpened then
- begin
- if aloc > af.fSize - af.fRead then
- aloc:=af.fSize - af.fRead;
-
- blockread(af.df ,buff^ ,aloc ,read );
-
- if aloc = read then
- begin
- inc(af.fRead ,read );
-
- result:=true;
-
- end
- else
- read:=0;
-
- end;
-
-end;
-
-{ API_CLOSE_FILE }
-function api_close_file;
-begin
- result:=false;
-
- if af.isOpened then
- begin
- system.close(af.df );
-
- af.isOpened:=false;
-
- result:=true;
-
- end;
-
-end;
-
-{ PARAM_COUNT }
-function param_count;
-begin
- result:=ParamCount;
-
-end;
-
-{ PARAM_STR }
-function param_str;
-begin
- result:=ParamStr(i );
-
-end;
-
-END.
-
+//
+// AggPas 2.4 RM3 demo framework file utility library
+// Milan Marusinec alias Milano (c) 2006
+//
+unit
+ file_utils_ ;
+
+INTERFACE
+
+{$I agg_mode.inc }
+{$I- }
+uses
+ agg_basics ;
+
+{ TYPES DEFINITION }
+type
+ api_file_ptr = ^api_file;
+ api_file = record
+ fileName : shortstring;
+ isOpened : boolean;
+
+ fSize ,
+ fRead : int;
+
+ // FSOpenFork parameters
+ df : file;
+
+ end;
+
+{ GLOBAL PROCEDURES }
+ function cut_str(s : shortstring ) : shortstring;
+ function up_str (s : shortstring ) : shortstring;
+ function cmp_str(s : shortstring ) : shortstring;
+
+ function str_dir(s : shortstring ) : shortstring;
+ function dir_str(s : shortstring ) : shortstring;
+
+ function str_disk(fn : shortstring ) : shortstring;
+ function str_path(fn : shortstring ) : shortstring;
+ function str_name(fn : shortstring ) : shortstring;
+ function str_ext (fn : shortstring ) : shortstring;
+
+ function fold_name (p ,n ,x : shortstring ) : shortstring;
+ procedure spread_name(fn : shortstring; var p ,n ,x : shortstring );
+
+ function file_exists(fn : shortstring ) : boolean;
+
+ function api_open_file (var af : api_file; fname : shortstring ) : boolean;
+ function api_read_file (var af : api_file; buff : pointer; aloc : int; var read : int ) : boolean;
+ function api_close_file(var af : api_file ) : boolean;
+
+ function param_count : int;
+ function param_str(i : int ) : shortstring;
+
+
+IMPLEMENTATION
+{ LOCAL VARIABLES & CONSTANTS }
+type
+ tSCAN = (
+
+ SCAN_0 ,
+ SCAN_1 ,SCAN_2 ,SCAN_3 ,SCAN_4 ,SCAN_5 ,SCAN_6 ,SCAN_7 ,SCAN_8 ,SCAN_9 ,
+ SCAN_A ,SCAN_B ,SCAN_C ,SCAN_D ,SCAN_E ,SCAN_F ,SCAN_G ,SCAN_H ,SCAN_I ,
+ SCAN_J ,SCAN_K ,SCAN_L ,SCAN_M ,SCAN_N ,SCAN_O ,SCAN_P ,SCAN_Q ,SCAN_R ,
+ SCAN_S ,SCAN_T ,SCAN_U ,SCAN_V ,SCAN_W ,SCAN_X ,SCAN_Y ,SCAN_Z
+
+ );
+
+ tITEM = (
+
+ ITEM_0 ,
+ ITEM_1 ,ITEM_2 ,ITEM_3 ,ITEM_4 ,ITEM_5 ,ITEM_6 ,ITEM_7 ,ITEM_8 ,ITEM_9 ,
+ ITEM_A ,ITEM_B ,ITEM_C ,ITEM_D ,ITEM_E ,ITEM_F ,ITEM_G ,ITEM_H ,ITEM_I ,
+ ITEM_J ,ITEM_K ,ITEM_L ,ITEM_M ,ITEM_N ,ITEM_O ,ITEM_P ,ITEM_Q ,ITEM_R ,
+ ITEM_S ,ITEM_T ,ITEM_U ,ITEM_V ,ITEM_W ,ITEM_X ,ITEM_Y ,ITEM_Z
+
+ );
+
+const
+ dir_slash = '\';
+
+ pageEqHigh : shortstring =
+ #1#2#3#4#5#6#7#8#9#10#11#12#13#14#15#16 +
+ #17#18#19#20#21#22#23#24#25#26#27#28#29#30#31#32 +
+ #33#34#35#36#37#38#39#40#41#42#43#44#45#46#47#48 +
+ #49#50#51#52#53#54#55#56#57#58#59#60#61#62#63#64 +
+ #65#66#67#68#69#70#71#72#73#74#75#76#77#78#79#80 +
+ #81#82#83#84#85#86#87#88#89#90#91#92#93#94#95#96 +
+ #65#66#67#68#69#70#71#72#73#74#75#76#77#78#79#80 +
+ #81#82#83#84#85#86#87#88#89#90#123#124#125#126#127#128 +
+ #129#130#131#132#133#134#135#136#137#138#139#140#141#142#143#144 +
+ #145#146#147#148#149#150#151#152#153#154#155#156#157#158#159#160 +
+ #161#162#163#164#165#166#167#168#169#170#171#172#173#174#175#176 +
+ #177#178#179#180#181#182#183#184#185#186#187#188#189#190#191#192 +
+ #193#194#195#196#197#198#199#200#201#202#203#204#205#206#207#208 +
+ #209#210#211#212#213#214#215#216#217#218#219#220#221#222#223#224 +
+ #225#226#227#228#229#230#231#232#233#234#235#236#237#238#239#240 +
+ #241#242#243#244#245#246#247#248#249#250#251#252#253#254#255;
+
+{ UNIT IMPLEMENTATION }
+{ CUT_STR }
+function cut_str;
+var
+ fcb : byte;
+ scn : tSCAN;
+
+begin
+ result:='';
+
+ scn:=SCAN_1;
+
+ if length(s ) > 0 then
+ for fcb:=length(s ) downto 1 do
+ case scn of
+ SCAN_1 :
+ case s[fcb ] of
+ ' ' :
+ else
+ begin
+ result:=s[fcb ];
+
+ scn:=SCAN_2;
+
+ end;
+
+ end;
+
+ SCAN_2 :
+ result:=s[fcb ] + result;
+
+ end;
+
+end;
+
+{ CMP_STR }
+function cmp_str;
+begin
+ cmp_str:=up_str(cut_str(s ) );
+
+end;
+
+{ UP_STR }
+function up_str;
+var
+ fcb : byte;
+
+begin
+ if length(s ) > 0 then
+ for fcb:=1 to length(s ) do
+ if byte(s[fcb ] ) > 0 then
+ s[fcb ]:=pageEqHigh[byte(s[fcb ] ) ];
+
+ result:=s;
+
+end;
+
+{ STR_DIR }
+function str_dir;
+begin
+ s:=cut_str(s );
+
+ if length(s ) > 0 then
+ if s[length(s ) ] <> dir_slash then
+ s:=s + dir_slash;
+
+ result:=s;
+
+end;
+
+{ DIR_STR }
+function dir_str;
+begin
+ s:=cut_str(s );
+
+ if length(s ) > 0 then
+ if s[length(s ) ] = dir_slash then
+ dec(byte(s[0 ] ) );
+
+ result:=s;
+
+end;
+
+{ STR_DISK }
+function str_disk;
+var
+ fcb : byte;
+ str : shortstring;
+ itm : tITEM;
+
+begin
+ str:='';
+ itm:=ITEM_1;
+
+ if length(fn ) > 0 then
+ for fcb:=1 to length(fn ) do
+ case itm of
+ ITEM_1 :
+ case fn[fcb ] of
+ 'a'..'z' ,'A'..'Z' :
+ begin
+ str:=fn[fcb ];
+ itm:=ITEM_2;
+
+ end;
+
+ '\' ,'/' :
+ begin
+ str:=fn[fcb ];
+ itm:=ITEM_3;
+
+ end;
+
+ else
+ break;
+
+ end;
+
+ ITEM_2 :
+ case fn[fcb ] of
+ ':' :
+ begin
+ str:=str + fn[fcb ];
+ itm:=ITEM_F;
+
+ break;
+
+ end;
+
+ else
+ break;
+
+ end;
+
+ ITEM_3 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ str:=str + fn[fcb ];
+ itm:=ITEM_4;
+
+ end;
+
+ else
+ break;
+
+ end;
+
+ ITEM_4 :
+ case fn[fcb ] of
+ '\' ,'/' ,':' ,'<' ,'>' ,'.' ,'"' ,'|' ,#0..#31 :
+ break;
+
+ else
+ begin
+ str:=str + fn[fcb ];
+ itm:=ITEM_F;
+
+ end;
+
+ end;
+
+ ITEM_F :
+ case fn[fcb ] of
+ '\' ,'/' :
+ break;
+
+ else
+ str:=str + fn[fcb ];
+
+ end;
+
+ end;
+
+ if itm = ITEM_F then
+ result:=str
+ else
+ result:='';
+
+end;
+
+{ STR_PATH }
+function str_path;
+var
+ fcb : byte;
+ pth ,
+ str : shortstring;
+ itm : tITEM;
+
+begin
+ pth:='';
+ str:='';
+ itm:=ITEM_1;
+
+ if length(fn ) > 0 then
+ for fcb:=1 to length(fn ) do
+ case itm of
+ ITEM_1 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ str:=fn[fcb ];
+ itm:=ITEM_2;
+
+ end;
+
+ else
+ begin
+ str:=fn[fcb ];
+ itm:=ITEM_3;
+
+ end;
+
+ end;
+
+ ITEM_2 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ str:=str + fn[fcb ];
+ itm:=ITEM_3;
+
+ end;
+
+ else
+ begin
+ pth:=str;
+ str:=fn[fcb ];
+ itm:=ITEM_A;
+
+ end;
+
+ end;
+
+ ITEM_3 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ pth:=fn[fcb ];
+ str:='';
+ itm:=ITEM_A;
+
+ end;
+
+ else
+ str:=str + fn[fcb ];
+
+ end;
+
+ ITEM_A :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ pth:=pth + str + fn[fcb ];
+ str:='';
+
+ end;
+
+ else
+ str:=str + fn[fcb ];
+
+ end;
+
+ end;
+
+ result:=pth;
+
+end;
+
+{ STR_NAME }
+function str_name;
+var
+ fcb : byte;
+ str ,
+ ext : shortstring;
+ itm : tITEM;
+
+begin
+ str:='';
+ ext:='';
+ itm:=ITEM_1;
+
+ if length(fn ) > 0 then
+ for fcb:=1 to length(fn ) do
+ case itm of
+ ITEM_1 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ itm:=ITEM_2;
+
+ 'a'..'z' ,'A'..'Z' :
+ begin
+ ext:=fn[fcb ];
+ itm:=ITEM_4;
+
+ end;
+
+ '.' :
+ begin
+ str:='';
+ ext:=fn[fcb ];
+ itm:=ITEM_B;
+
+ end;
+
+ else
+ begin
+ str:=fn[fcb ];
+ itm:=ITEM_A;
+
+ end;
+
+ end;
+
+ ITEM_2 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ itm:=ITEM_3;
+
+ '.' :
+ begin
+ str:='';
+ ext:=fn[fcb ];
+ itm:=ITEM_B;
+
+ end;
+
+ else
+ begin
+ str:=fn[fcb ];
+ itm:=ITEM_A;
+
+ end;
+
+ end;
+
+ ITEM_3 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ str:='';
+ itm:=ITEM_A;
+
+ end;
+
+ end;
+
+ ITEM_4 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ str:='';
+ itm:=ITEM_A;
+
+ end;
+
+ ':' :
+ itm:=ITEM_5;
+
+ '.' :
+ begin
+ str:=ext;
+ ext:=fn[fcb ];
+ itm:=ITEM_B;
+
+ end;
+
+ else
+ begin
+ str:=ext + fn[fcb ];
+ ext:='';
+ itm:=ITEM_A;
+
+ end;
+
+ end;
+
+ ITEM_5 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ str:='';
+ itm:=ITEM_A;
+
+ end;
+
+ '.' :
+ begin
+ str:='';
+ ext:=fn[fcb ];
+ itm:=ITEM_B;
+
+ end;
+
+ else
+ begin
+ str:=fn[fcb ];
+ itm:=ITEM_A;
+
+ end;
+
+ end;
+
+ ITEM_A :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ str:='';
+ ext:='';
+
+ end;
+
+ '.' :
+ begin
+ ext:=fn[fcb ];
+ itm:=ITEM_B;
+
+ end;
+
+ else
+ str:=str + fn[fcb ];
+
+ end;
+
+ ITEM_B :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ str:='';
+ ext:='';
+ itm:=ITEM_A;
+
+ end;
+
+ '.' :
+ begin
+ str:=str + ext;
+ ext:=fn[fcb ];
+
+ end;
+
+ end;
+
+ end;
+
+ result:=str;
+
+end;
+
+{ STR_EXT }
+function str_ext;
+var
+ fcb : byte;
+ ext : shortstring;
+ itm : tITEM;
+
+begin
+ ext:='';
+ itm:=ITEM_1;
+
+ if length(fn ) > 0 then
+ for fcb:=1 to length(fn ) do
+ case itm of
+ ITEM_1 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ itm:=ITEM_2;
+
+ '.' :
+ begin
+ ext:=fn[fcb ];
+ itm:=ITEM_B;
+
+ end;
+
+ else
+ itm:=ITEM_A;
+
+ end;
+
+ ITEM_2 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ itm:=ITEM_3;
+
+ '.' :
+ begin
+ ext:=fn[fcb ];
+ itm:=ITEM_B;
+
+ end;
+
+ else
+ itm:=ITEM_A;
+
+ end;
+
+ ITEM_3 :
+ case fn[fcb ] of
+ '\' ,'/' :
+ itm:=ITEM_A;
+
+ end;
+
+ ITEM_A :
+ case fn[fcb ] of
+ '.' :
+ begin
+ ext:=fn[fcb ];
+ itm:=ITEM_B;
+
+ end;
+
+ end;
+
+ ITEM_B :
+ case fn[fcb ] of
+ '\' ,'/' :
+ begin
+ ext:='';
+ itm:=ITEM_A;
+
+ end;
+
+ '.' :
+ ext:=fn[fcb ];
+
+ else
+ ext:=ext + fn[fcb ];
+
+ end;
+
+ end;
+
+ result:=cut_str(ext );
+
+ if result = '.' then
+ result:='';
+
+end;
+
+{ FOLD_NAME }
+function fold_name;
+var
+ dsk ,
+ nme ,
+ pth ,
+ ext : shortstring;
+
+begin
+ dsk:=str_disk(p );
+ pth:=str_dir (str_path(p ) );
+ nme:=str_name(n );
+ ext:=str_ext (x );
+
+ result:=dsk + pth + nme + ext;
+
+end;
+
+{ SPREAD_NAME }
+procedure spread_name;
+begin
+ p:=str_disk(fn ) + str_dir(str_path(fn ) );
+ n:=str_name(fn );
+ x:=str_ext (fn );
+
+end;
+
+{ FILE_EXISTS }
+function file_exists;
+var
+ f : file;
+
+begin
+ AssignFile(f ,fn );
+ reset (f );
+
+ if IOResult = 0 then
+ begin
+ close(f );
+
+ result:=true;
+
+ end
+ else
+ result:=false;
+
+end;
+
+{ API_OPEN_FILE }
+function api_open_file;
+begin
+ result:=false;
+
+ fillchar(af ,sizeof(api_file ) ,0 );
+
+ af.fileName:=fname;
+ af.isOpened:=false;
+
+ IOResult;
+
+ AssignFile(af.df ,fname );
+ reset (af.df ,1 );
+
+ if IOResult = 0 then
+ begin
+ af.isOpened:=true;
+
+ af.fSize:=filesize(af.df );
+ af.fRead:=0;
+
+ end;
+
+ result:=af.isOpened;
+
+end;
+
+{ API_READ_FILE }
+function api_read_file;
+begin
+ result:=false;
+ read :=0;
+
+ if af.isOpened then
+ begin
+ if aloc > af.fSize - af.fRead then
+ aloc:=af.fSize - af.fRead;
+
+ blockread(af.df ,buff^ ,aloc ,read );
+
+ if aloc = read then
+ begin
+ inc(af.fRead ,read );
+
+ result:=true;
+
+ end
+ else
+ read:=0;
+
+ end;
+
+end;
+
+{ API_CLOSE_FILE }
+function api_close_file;
+begin
+ result:=false;
+
+ if af.isOpened then
+ begin
+ system.close(af.df );
+
+ af.isOpened:=false;
+
+ result:=true;
+
+ end;
+
+end;
+
+{ PARAM_COUNT }
+function param_count;
+begin
+ result:=ParamCount;
+
+end;
+
+{ PARAM_STR }
+function param_str;
+begin
+ result:=ParamStr(i );
+
+end;
+
+END.
+