diff options
Diffstat (limited to 'src')
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. + |