// // AggPas 2.4 RM3 Demo application // Note: Press F1 key on run to see more info about this demo // // Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap // program idea ; {DEFINE AGG_GRAY8 } {$DEFINE AGG_BGR24 } {DEFINE AGG_RGB24 } {DEFINE AGG_BGRA32 } {DEFINE AGG_RGBA32 } {DEFINE AGG_ARGB32 } {DEFINE AGG_ABGR32 } {DEFINE AGG_RGB565 } {DEFINE AGG_RGB555 } uses Math , agg_basics , agg_platform_support , agg_ctrl , agg_slider_ctrl , agg_cbox_ctrl , agg_rasterizer_scanline_aa , agg_scanline , agg_scanline_p , agg_renderer_base , agg_renderer_scanline , agg_render_scanlines , agg_gamma_functions , agg_path_storage , agg_trans_affine , agg_conv_stroke , agg_conv_transform , agg_vertex_source {$I pixel_formats.inc } {$I agg_mode.inc } const flip_y = false; type path_attributes = object index : unsigned; fill_color , stroke_color : aggclr; stroke_width : double; constructor Construct; overload; constructor Construct(idx : unsigned; fill ,stroke : aggclr_ptr; width : double ); overload; end; const g_poly_bulb : array[0..39 ] of double = ( -6 ,-67 ,-6 ,-71 ,-7 ,-74 ,-8 ,-76 ,-10 ,-79 , -10 ,-82 ,-9 ,-84 ,-6 ,-86 ,-4 ,-87 ,-2 ,-86 , -1 ,-86 ,1 ,-84 ,2 ,-82 ,2 ,-79 ,0 ,-77 , -2 ,-73 ,-2 ,-71 ,-2 ,-69 ,-3 ,-67 ,-4 ,-65 ); g_poly_beam1 : array[0..9 ] of double = ( -14 ,-84 ,-22 ,-85 ,-23 ,-87 ,-22 ,-88 ,-21 ,-88 ); g_poly_beam2 : array[0..9 ] of double = ( -10 ,-92 ,-14 ,-96 ,-14 ,-98 ,-12 ,-99 ,-11 ,-97 ); g_poly_beam3 : array[0..9 ] of double = ( -1 ,-92 ,-2 ,-98 ,0 ,-100 ,2 ,-100 ,1 ,-98 ); g_poly_beam4 : array[0..9 ] of double = ( 5 ,-89 ,11 ,-94 ,13 ,-93 ,13 ,-92 ,12 ,-91 ); g_poly_fig1 : array[0..41 ] of double = ( 1 ,-48 ,-3 ,-54 ,-7 ,-58 ,-12 ,-58 ,-17 ,-55 , -20 ,-52 ,-21 ,-47 ,-20 ,-40 ,-17 ,-33 ,-11 ,-28 , -6 ,-26 ,-2 ,-25 ,2 ,-26 ,4 ,-28 ,5 ,-33 , 5 ,-39 ,3 ,-44 ,12 ,-48 ,12 ,-50 ,12 ,-51 , 3 ,-46 ); g_poly_fig2 : array[0..75 ] of double = ( 11 ,-27 ,6 ,-23 ,4 ,-22 ,3 ,-19 ,5 ,-16 , 6 ,-15 ,11 ,-17 ,19 ,-23 ,25 ,-30 ,32 ,-38 , 32 ,-41 ,32 ,-50 ,30 ,-64 ,32 ,-72 ,32 ,-75 , 31 ,-77 ,28 ,-78 ,26 ,-80 ,28 ,-87 ,27 ,-89 , 25 ,-88 ,24 ,-79 ,24 ,-76 ,23 ,-75 ,20 ,-76 , 17 ,-76 ,17 ,-74 ,19 ,-73 ,22 ,-73 ,24 ,-71 , 26 ,-69 ,27 ,-64 ,28 ,-55 ,28 ,-47 ,28 ,-40 , 26 ,-38 ,20 ,-33 ,14 ,-30 ); g_poly_fig3 : array[0..69 ] of double = ( -6 ,-20 ,-9 ,-21 ,-15 ,-21 ,-20 ,-17 ,-28 ,-8 , -32 ,-1 ,-32 ,1 ,-30 ,6 ,-26 ,8 ,-20 ,10 , -16 ,12 ,-14 ,14 ,-15 ,16 ,-18 ,20 ,-22 ,20 , -25 ,19 ,-27 ,20 ,-26 ,22 ,-23 ,23 ,-18 ,23 , -14 ,22 ,-11 ,20 ,-10 ,17 ,-9 ,14 ,-11 ,11 , -16 ,9 ,-22 ,8 ,-26 ,5 ,-28 ,2 ,-27 ,-2 , -23 ,-8 ,-19 ,-11 ,-12 ,-14 ,-6 ,-15 ,-6 ,-18 ); g_poly_fig4 : array[0..39 ] of double = ( 11 ,-6 ,8 ,-16 ,5 ,-21 ,-1 ,-23 ,-7 ,-22 , -10 ,-17 ,-9 ,-10 ,-8 ,0 ,-8 ,10 ,-10 ,18 , -11 ,22 ,-10 ,26 ,-7 ,28 ,-3 ,30 ,0 ,31 , 5 ,31 ,10 ,27 ,14 ,18 ,14 ,11 ,11 ,2 ); g_poly_fig5 : array[0..55 ] of double = ( 0 ,22 ,-5 ,21 ,-8 ,22 ,-9 ,26 ,-8 ,49 , -8 ,54 ,-10 ,64 ,-10 ,75 ,-9 ,81 ,-10 ,84 , -16 ,89 ,-18 ,95 ,-18 ,97 ,-13 ,100 ,-12 ,99 , -12 ,95 ,-10 ,90 ,-8 ,87 ,-6 ,86 ,-4 ,83 , -3 ,82 ,-5 ,80 ,-6 ,79 ,-7 ,74 ,-6 ,63 , -3 ,52 ,0 ,42 ,1 ,31 ); g_poly_fig6 : array[0..61 ] of double = ( 12 ,31 ,12 ,24 ,8 ,21 ,3 ,21 ,2 ,24 , 3 ,30 ,5 ,40 ,8 ,47 ,10 ,56 ,11 ,64 , 11 ,71 ,10 ,76 ,8 ,77 ,8 ,79 ,10 ,81 , 13 ,82 ,17 ,82 ,26 ,84 ,28 ,87 ,32 ,86 , 33 ,81 ,32 ,80 ,25 ,79 ,17 ,79 ,14 ,79 , 13 ,76 ,14 ,72 ,14 ,64 ,13 ,55 ,12 ,44 , 12 ,34 ); var g_npaths : unsigned; g_pflag : filling_rule_e; g_angle : double; g_attr : array[0..2 ] of path_attributes; g_path : path_storage; g_rasterizer : rasterizer_scanline_aa; g_scanline : scanline_p8; //AGG_POLY_SIZE: sizeof(p ) / (sizeof(double ) * 2 type the_application = object(platform_support ) m_dx , m_dy : double; m_rotate , m_even_odd , m_draft , m_roundoff : cbox_ctrl; m_angle_delta : slider_ctrl; m_redraw_flag : boolean; constructor Construct(format_ : pix_format_e; flip_y_ : boolean ); destructor Destruct; procedure on_init; virtual; procedure on_resize(sx ,sy : int ); virtual; procedure on_draw; virtual; procedure on_idle; virtual; procedure on_ctrl_change; virtual; procedure on_key(x ,y : int; key ,flags : unsigned ); virtual; end; { trans_roundoff } procedure trans_roundoff(this : trans_affine_ptr; x ,y : double_ptr ); begin x^:=Floor(x^ + 0.5 ); y^:=Floor(y^ + 0.5 ); end; { CONSTRUCT } constructor path_attributes.Construct; begin fill_color.Construct; stroke_color.Construct; index :=0; stroke_width:=0; end; { CONSTRUCT } constructor path_attributes.Construct(idx : unsigned; fill ,stroke : aggclr_ptr; width : double ); begin index :=idx; fill_color :=fill^; stroke_color:=stroke^; stroke_width:=width; end; { CONSTRUCT } constructor the_application.Construct; var rgbs , rgbf : aggclr; begin inherited Construct(format_ ,flip_y_ ); // Controls m_rotate.Construct (10 ,3 ,'Rotate' ,not flip_y_ ); m_even_odd.Construct(60 ,3 ,'Even-Odd' ,not flip_y_ ); m_draft.Construct (130 ,3 ,'Draft' ,not flip_y_ ); m_roundoff.Construct(175 ,3 ,'Roundoff' ,not flip_y_ ); m_angle_delta.Construct(10 ,21 ,250-10 ,27 ,not flip_y_ ); m_angle_delta.label_ ('Step=%4.3f degree' ); m_redraw_flag:=true; m_rotate.text_size_ (7 ); m_even_odd.text_size_(7 ); m_draft.text_size_ (7 ); m_roundoff.text_size_(7 ); add_ctrl(@m_rotate ); add_ctrl(@m_even_odd ); add_ctrl(@m_draft ); add_ctrl(@m_roundoff ); add_ctrl(@m_angle_delta ); m_angle_delta.value_(0.01 ); // Polygon rgbf.ConstrInt(255 ,255 ,0 ); rgbs.ConstrInt(0 ,0 ,0 ); g_attr[g_npaths ].Construct( g_path.start_new_path , @rgbf ,@rgbs ,1.0 ); inc(g_npaths ); g_path.add_poly(@g_poly_bulb[0 ] ,sizeof(g_poly_bulb ) div (sizeof(double ) * 2 ) ,false ,path_flags_close ); rgbf.ConstrInt(255 ,255 ,200 ); rgbs.ConstrInt(90 ,0 ,0 ); g_attr[g_npaths ].Construct( g_path.start_new_path , @rgbf ,@rgbs ,0.7 ); inc(g_npaths ); g_path.add_poly(@g_poly_beam1[0 ] ,sizeof(g_poly_beam1 ) div (sizeof(double ) * 2 ) ,false ,path_flags_close ); g_path.add_poly(@g_poly_beam2[0 ] ,sizeof(g_poly_beam2 ) div (sizeof(double ) * 2 ) ,false ,path_flags_close ); g_path.add_poly(@g_poly_beam3[0 ] ,sizeof(g_poly_beam3 ) div (sizeof(double ) * 2 ) ,false ,path_flags_close ); g_path.add_poly(@g_poly_beam4[0 ] ,sizeof(g_poly_beam4 ) div (sizeof(double ) * 2 ) ,false ,path_flags_close ); rgbf.ConstrInt(0 ,0 ,0 ); rgbs.ConstrInt(0 ,0 ,0 ); g_attr[g_npaths ].Construct( g_path.start_new_path , @rgbf ,@rgbs ,0.0 ); inc(g_npaths ); g_path.add_poly(@g_poly_fig1[0 ] ,sizeof(g_poly_fig1 ) div (sizeof(double ) * 2 ) ); g_path.add_poly(@g_poly_fig2[0 ] ,sizeof(g_poly_fig2 ) div (sizeof(double ) * 2 ) ); g_path.add_poly(@g_poly_fig3[0 ] ,sizeof(g_poly_fig3 ) div (sizeof(double ) * 2 ) ); g_path.add_poly(@g_poly_fig4[0 ] ,sizeof(g_poly_fig4 ) div (sizeof(double ) * 2 ) ); g_path.add_poly(@g_poly_fig5[0 ] ,sizeof(g_poly_fig5 ) div (sizeof(double ) * 2 ) ); g_path.add_poly(@g_poly_fig6[0 ] ,sizeof(g_poly_fig6 ) div (sizeof(double ) * 2 ) ); end; { DESTRUCT } destructor the_application.Destruct; begin inherited Destruct; m_rotate.Destruct; m_even_odd.Destruct; m_draft.Destruct; m_roundoff.Destruct; m_angle_delta.Destruct; end; { ON_INIT } procedure the_application.on_init; begin m_dx:=rbuf_window._width; m_dy:=rbuf_window._height; end; { ON_RESIZE } procedure the_application.on_resize; begin m_redraw_flag:=true; end; { ON_DRAW } procedure the_application.on_draw; var pixf : pixel_formats; rbase : renderer_base; r : renderer_scanline_aa_solid; rb : renderer_scanline_bin_solid; rgba : aggclr; gm_no : vertex_source; gm_th : gamma_threshold; mtx : trans_affine; tar : trans_affine_rotation; tat : trans_affine_translation; tas : trans_affine_scaling; roundoff : trans_affine; fill ,fill_roundoff : conv_transform; stroke ,stroke_roundoff : conv_stroke; i : unsigned; begin // Initialize structures pixfmt(pixf ,rbuf_window ); rbase.Construct(@pixf ); r.Construct (@rbase ); rb.Construct (@rbase ); roundoff.Construct(@trans_roundoff ); // Render the controls if m_redraw_flag then begin gm_no.Construct; g_rasterizer.gamma(@gm_no ); rgba.ConstrInt(255 ,255 ,255 ); rbase.clear (@rgba ); g_rasterizer.filling_rule(fill_non_zero ); render_ctrl(@g_rasterizer ,@g_scanline ,@r ,@m_rotate ); render_ctrl(@g_rasterizer ,@g_scanline ,@r ,@m_even_odd ); render_ctrl(@g_rasterizer ,@g_scanline ,@r ,@m_draft ); render_ctrl(@g_rasterizer ,@g_scanline ,@r ,@m_roundoff ); render_ctrl(@g_rasterizer ,@g_scanline ,@r ,@m_angle_delta ); m_redraw_flag:=false; end else begin rgba.ConstrInt(255 ,255 ,255 ); rbase.copy_bar( 0 ,trunc(32.0 * rbuf_window._height / m_dy ) , rbuf_window._width ,rbuf_window._height , @rgba ); end; // Draft mode if m_draft._status then begin gm_th.Construct (0.4 ); g_rasterizer.gamma(@gm_th ); end; // Rotate polygon tar.Construct(g_angle * pi / 180.0 ); tat.Construct(m_dx / 2 ,m_dy / 2 + 10 ); tas.Construct(rbuf_window._width / m_dx ,rbuf_window._height / m_dy ); mtx.Construct; mtx.reset; mtx.multiply(@tar ); mtx.multiply(@tat ); mtx.multiply(@tas ); fill.Construct (@g_path ,@mtx ); fill_roundoff.Construct(@fill ,@roundoff ); stroke.Construct (@fill ); stroke_roundoff.Construct(@fill_roundoff ); if m_even_odd._status then g_pflag:=fill_even_odd else g_pflag:=fill_non_zero; // Render polygon for i:=0 to g_npaths - 1 do begin g_rasterizer.filling_rule(g_pflag ); r.color_ (@g_attr[i ].fill_color ); rb.color_(@g_attr[i ].fill_color ); if m_roundoff._status then g_rasterizer.add_path(@fill_roundoff ,g_attr[i ].index ) else g_rasterizer.add_path(@fill ,g_attr[i ].index ); if m_draft._status then render_scanlines(@g_rasterizer ,@g_scanline ,@rb ) else render_scanlines(@g_rasterizer ,@g_scanline ,@r ); if g_attr[i ].stroke_width > 0.001 then begin r.color_ (@g_attr[i ].stroke_color ); rb.color_(@g_attr[i ].stroke_color ); stroke.width_ (g_attr[i ].stroke_width * mtx.scale ); stroke_roundoff.width_(g_attr[i ].stroke_width * mtx.scale ); if m_roundoff._status then g_rasterizer.add_path(@stroke_roundoff ,g_attr[i ].index ) else g_rasterizer.add_path(@stroke ,g_attr[i ].index ); if m_draft._status then render_scanlines(@g_rasterizer ,@g_scanline ,@rb ) else render_scanlines(@g_rasterizer ,@g_scanline ,@r ); end; end; // Free AGG resources stroke.Destruct; stroke_roundoff.Destruct; end; { ON_IDLE } procedure the_application.on_idle; begin g_angle:=g_angle + m_angle_delta._value; if g_angle > 360.0 then g_angle:=g_angle - 360.0; force_redraw; end; { ON_CTRL_CHANGE } procedure the_application.on_ctrl_change; begin wait_mode_(not m_rotate._status ); m_redraw_flag:=true; end; { ON_KEY } procedure the_application.on_key; begin if key = key_f1 then message_( 'The polygons for this "idea" were taken from the book "Dynamic HTML in Action" '#13 + 'by Eric Schurman. An example of using Microsoft Direct Animation can be found here: '#13 + '"http://www.antigrain.com/demo/ideaDA.html." If you use Microsoft Internet Explorer '#13 + 'you can compare the quality of rendering in AGG and Microsoft Direct Animation. '#13 + 'Note that even when you click "Rotate with High Quality", you will see it "jitters". '#13 + 'It''s because there are actually no Subpixel Accuracy used in the Microsoft Direct '#13 + 'Animation.In the AGG example, there''s no jitter even in the "Draft" (low quality) '#13 + 'mode. You can see the simulated jittering if you turn on the "Roundoff" mode, in which '#13 + 'there integer pixel coordinated are used. As for the performance, note, that the image '#13 + 'in AGG is rotated with step of 0.01 degree (initially), while in the Direct Animation '#13 + 'Example the angle step is 0.1 degree.' + #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' ); end; VAR app : the_application; BEGIN g_npaths:=0; g_pflag :=fill_non_zero; g_angle :=0.0; g_path.Construct; g_rasterizer.Construct; g_scanline.Construct; app.Construct(pix_format ,flip_y ); app.caption_ ('AGG Example. Idea (F1-Help)' ); if app.init(250 ,280 ,window_resize ) then app.run; app.Destruct; g_rasterizer.Destruct; g_scanline.Destruct; g_path.Destruct; END.