mirror of
				https://gitlab.com/freepascal.org/lazarus/lazarus.git
				synced 2025-10-31 21:09:28 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			450 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
			
		
		
	
	
			450 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
| //
 | ||
| // 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
 | ||
|  rasterizers ;
 | ||
| 
 | ||
| {$DEFINE AGG_BGR24 }
 | ||
| 
 | ||
| uses
 | ||
|  SysUtils ,
 | ||
| 
 | ||
|  agg_basics ,
 | ||
|  agg_platform_support ,
 | ||
|  agg_math ,
 | ||
| 
 | ||
|  agg_ctrl ,
 | ||
|  agg_slider_ctrl ,
 | ||
|  agg_cbox_ctrl ,
 | ||
| 
 | ||
|  agg_rasterizer_scanline_aa ,
 | ||
|  agg_rasterizer_outline ,
 | ||
|  agg_scanline ,
 | ||
|  agg_scanline_p ,
 | ||
|  agg_scanline_bin ,
 | ||
| 
 | ||
|  agg_renderer_base ,
 | ||
|  agg_renderer_scanline ,
 | ||
|  agg_renderer_primitives ,
 | ||
|  agg_render_scanlines ,
 | ||
| 
 | ||
|  agg_path_storage ,
 | ||
|  agg_gamma_functions
 | ||
| 
 | ||
| {$I pixel_formats.inc }
 | ||
| {$I agg_mode.inc }
 | ||
| 
 | ||
| const
 | ||
|  flip_y = true;
 | ||
| 
 | ||
| type
 | ||
|  the_application = object(platform_support )
 | ||
|    m_x ,
 | ||
|    m_y : array[0..2 ] of double;
 | ||
| 
 | ||
|    m_dx ,
 | ||
|    m_dy : double;
 | ||
| 
 | ||
|    m_idx : int;
 | ||
| 
 | ||
|    m_gamma ,
 | ||
|    m_alpha : slider_ctrl;
 | ||
|    m_test  : cbox_ctrl;
 | ||
| 
 | ||
|    m_ras    : rasterizer_scanline_aa;
 | ||
|    m_sl_p8  : scanline_p8;
 | ||
|    m_sl_bin : scanline_bin;
 | ||
| 
 | ||
|    constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
 | ||
|    destructor  Destruct;
 | ||
| 
 | ||
|    procedure draw_anti_aliased;
 | ||
|    procedure draw_aliased;
 | ||
| 
 | ||
|    procedure on_draw; 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;
 | ||
| 
 | ||
|   end;
 | ||
| 
 | ||
| { CONSTRUCT }
 | ||
| constructor the_application.Construct;
 | ||
| begin
 | ||
|  inherited Construct(format_ ,flip_y_ );
 | ||
| 
 | ||
|  m_ras.Construct;
 | ||
|  m_sl_p8.Construct;
 | ||
|  m_sl_bin.Construct;
 | ||
| 
 | ||
|  m_idx:=-1;
 | ||
| 
 | ||
|  m_x[0 ]:=100 + 120; m_y[0 ]:=60;
 | ||
|  m_x[1 ]:=369 + 120; m_y[1 ]:=170;
 | ||
|  m_x[2 ]:=143 + 120; m_y[2 ]:=310;
 | ||
| 
 | ||
|  m_gamma.Construct(130 + 10 ,10 + 4 ,130 + 150 ,10 + 8 + 4 ,not flip_y );
 | ||
| 
 | ||
|  add_ctrl(@m_gamma );
 | ||
| 
 | ||
|  m_gamma.range_(0 ,1 );
 | ||
|  m_gamma.value_(0.5 );
 | ||
|  m_gamma.label_('Gamma=%1.2f' );
 | ||
|  m_gamma.no_transform;
 | ||
| 
 | ||
|  m_alpha.Construct(130 + 150 + 10 ,10 + 4 ,500 - 10 ,10 + 8 + 4 ,not flip_y );
 | ||
| 
 | ||
|  add_ctrl(@m_alpha );
 | ||
| 
 | ||
|  m_alpha.range_(0 ,1 );
 | ||
|  m_alpha.value_(1 );
 | ||
|  m_alpha.label_('Alpha=%1.2f' );
 | ||
|  m_alpha.no_transform;
 | ||
| 
 | ||
|  m_test.Construct(130 + 10.0 ,10.0 + 4.0 + 16.0 ,'Test Performance' ,not flip_y );
 | ||
| 
 | ||
|  add_ctrl(@m_test );
 | ||
| 
 | ||
|  m_test.no_transform;
 | ||
| 
 | ||
| end;
 | ||
| 
 | ||
| { DESTRUCT }
 | ||
| destructor the_application.Destruct;
 | ||
| begin
 | ||
|  inherited Destruct;
 | ||
| 
 | ||
|  m_alpha.Destruct;
 | ||
|  m_gamma.Destruct;
 | ||
|  m_test.Destruct;
 | ||
| 
 | ||
|  m_ras.Destruct;
 | ||
|  m_sl_p8.Destruct;
 | ||
|  m_sl_bin.Destruct;
 | ||
| 
 | ||
| end;
 | ||
| 
 | ||
| { DRAW_ANTI_ALIASED }
 | ||
| procedure the_application.draw_anti_aliased;
 | ||
| var
 | ||
|  pixf   : pixel_formats;
 | ||
|  rb     : renderer_base;
 | ||
|  ren_aa : renderer_scanline_aa_solid;
 | ||
| 
 | ||
|  path : path_storage;
 | ||
|  rgba : aggclr;
 | ||
| 
 | ||
|  gamma : gamma_power;
 | ||
| 
 | ||
| begin
 | ||
|  pixfmt(pixf ,rbuf_window );
 | ||
| 
 | ||
|  rb.Construct    (@pixf );
 | ||
|  ren_aa.Construct(@rb );
 | ||
| 
 | ||
| // Path & Color
 | ||
|  path.Construct;
 | ||
| 
 | ||
|  path.move_to(m_x[0 ] ,m_y[0 ] );
 | ||
|  path.line_to(m_x[1 ] ,m_y[1 ] );
 | ||
|  path.line_to(m_x[2 ] ,m_y[2 ] );
 | ||
|  path.close_polygon;
 | ||
| 
 | ||
|  rgba.ConstrDbl(0.7 ,0.5 ,0.1 ,m_alpha._value );
 | ||
|  ren_aa.color_ (@rgba );
 | ||
| 
 | ||
| // Draw
 | ||
|  gamma.Construct(m_gamma._value * 2.0 );
 | ||
| 
 | ||
|  m_ras.gamma   (@gamma );
 | ||
|  m_ras.add_path(@path );
 | ||
| 
 | ||
|  render_scanlines(@m_ras ,@m_sl_p8 ,@ren_aa );
 | ||
| 
 | ||
| // Free
 | ||
|  path.Destruct;
 | ||
| 
 | ||
| end;
 | ||
| 
 | ||
| { DRAW_ALIASED }
 | ||
| procedure the_application.draw_aliased;
 | ||
| var
 | ||
|  pixf    : pixel_formats;
 | ||
|  rb      : renderer_base;
 | ||
|  ren_bin : renderer_scanline_bin_solid;
 | ||
| 
 | ||
|  path : path_storage;
 | ||
|  rgba : aggclr;
 | ||
| 
 | ||
|  gamma : gamma_threshold;
 | ||
| 
 | ||
|  ren_pr   : renderer_primitives;
 | ||
|  ras_line : rasterizer_outline;
 | ||
| 
 | ||
| begin
 | ||
|  pixfmt(pixf ,rbuf_window );
 | ||
| 
 | ||
|  rb.Construct     (@pixf );
 | ||
|  ren_bin.Construct(@rb );
 | ||
| 
 | ||
| // Path & Color
 | ||
|  path.Construct;
 | ||
| 
 | ||
|  path.move_to(m_x[0 ] - 200 ,m_y[0 ] );
 | ||
|  path.line_to(m_x[1 ] - 200 ,m_y[1 ] );
 | ||
|  path.line_to(m_x[2 ] - 200 ,m_y[2 ] );
 | ||
|  path.close_polygon;
 | ||
| 
 | ||
|  rgba.ConstrDbl(0.1 ,0.5 ,0.7 ,m_alpha._value );
 | ||
|  ren_bin.color_(@rgba );
 | ||
| 
 | ||
| // Draw
 | ||
|  gamma.Construct(m_gamma._value );
 | ||
| 
 | ||
|  m_ras.gamma   (@gamma );
 | ||
|  m_ras.add_path(@path );
 | ||
| 
 | ||
|  render_scanlines(@m_ras ,@m_sl_bin ,@ren_bin );
 | ||
| 
 | ||
| //-- Drawing an outline with subpixel accuracy (aliased)
 | ||
| (* ren_pr.Construct  (@rb );
 | ||
|  ras_line.Construct(@ren_pr );
 | ||
| 
 | ||
|  rgba.ConstrDbl(0.0 ,0.0 ,0.0 );
 | ||
| 
 | ||
|  ren_pr._line_color(@rgba );
 | ||
|  ras_line.add_path (@path );(**)
 | ||
| 
 | ||
| // Free
 | ||
|  path.Destruct;
 | ||
| 
 | ||
| end;
 | ||
| 
 | ||
| { ON_DRAW }
 | ||
| procedure the_application.on_draw;
 | ||
| var
 | ||
|  pixf   : pixel_formats;
 | ||
|  rb     : renderer_base;
 | ||
|  ren_aa : renderer_scanline_aa_solid;
 | ||
| 
 | ||
|  ras_aa : rasterizer_scanline_aa;
 | ||
| 
 | ||
|  rgba : aggclr;
 | ||
| 
 | ||
| begin
 | ||
| // Initialize structures
 | ||
|  pixfmt(pixf ,rbuf_window );
 | ||
| 
 | ||
|  rb.Construct    (@pixf );
 | ||
|  ren_aa.Construct(@rb );
 | ||
| 
 | ||
|  ras_aa.Construct;
 | ||
| 
 | ||
| // Setup colors & background
 | ||
|  rgba.ConstrDbl(1 ,1 ,1 );
 | ||
| 
 | ||
|  rb.clear(@rgba );
 | ||
| 
 | ||
| // Draw
 | ||
|  draw_anti_aliased;
 | ||
|  draw_aliased;
 | ||
| 
 | ||
| // Render controls
 | ||
|  render_ctrl(@ras_aa ,@m_sl_p8 ,@ren_aa ,@m_gamma );
 | ||
|  render_ctrl(@ras_aa ,@m_sl_p8 ,@ren_aa ,@m_alpha );
 | ||
|  render_ctrl(@ras_aa ,@m_sl_p8 ,@ren_aa ,@m_test );
 | ||
| 
 | ||
| // Free AGG resources
 | ||
|  ras_aa.Destruct;
 | ||
| 
 | ||
| end;
 | ||
| 
 | ||
| { ON_MOUSE_MOVE }
 | ||
| procedure the_application.on_mouse_move;
 | ||
| var
 | ||
|  dx ,dy : double;
 | ||
| 
 | ||
| begin
 | ||
|  if flags and mouse_left <> 0 then
 | ||
|   begin
 | ||
|    if m_idx = 3 then
 | ||
|     begin
 | ||
|      dx:=x - m_dx;
 | ||
|      dy:=y - m_dy;
 | ||
| 
 | ||
|      m_x[1 ]:=m_x[1 ] - (m_x[0 ] - dx );
 | ||
|      m_y[1 ]:=m_y[1 ] - (m_y[0 ] - dy );
 | ||
|      m_x[2 ]:=m_x[2 ] - (m_x[0 ] - dx );
 | ||
|      m_y[2 ]:=m_y[2 ] - (m_y[0 ] - dy );
 | ||
|      m_x[0 ]:= dx;
 | ||
|      m_y[0 ]:= dy;
 | ||
| 
 | ||
|      force_redraw;
 | ||
|      exit;
 | ||
| 
 | ||
|     end;
 | ||
| 
 | ||
|    if m_idx >= 0 then
 | ||
|     begin
 | ||
|      m_x[m_idx ]:=x - m_dx;
 | ||
|      m_y[m_idx ]:=y - m_dy;
 | ||
| 
 | ||
|      force_redraw;
 | ||
| 
 | ||
|     end;
 | ||
| 
 | ||
|   end;
 | ||
| 
 | ||
| end;
 | ||
| 
 | ||
| { ON_MOUSE_BUTTON_DOWN }
 | ||
| procedure the_application.on_mouse_button_down;
 | ||
| var
 | ||
|  i : unsigned;
 | ||
| 
 | ||
| begin
 | ||
|  if flags and mouse_left <> 0 then
 | ||
|   begin
 | ||
|    i:=0;
 | ||
| 
 | ||
|    while i < 3 do
 | ||
|     begin
 | ||
|      if (Sqrt((x - m_x[i ] ) * (x - m_x[i ] ) + (y - m_y[i ] ) * (y - m_y[i ] ) ) < 20 ) or
 | ||
|         (Sqrt((x - m_x[i ] + 200 ) * (x - m_x[i ] + 200 ) + (y - m_y[i ] ) * (y - m_y[i ] ) ) < 20 ) then
 | ||
|       begin
 | ||
|        m_dx :=x - m_x[i ];
 | ||
|        m_dy :=y - m_y[i ];
 | ||
|        m_idx:=i;
 | ||
| 
 | ||
|        break;
 | ||
| 
 | ||
|       end;
 | ||
| 
 | ||
|      inc(i );
 | ||
| 
 | ||
|     end;
 | ||
| 
 | ||
|    if i = 3 then
 | ||
|     if point_in_triangle(m_x[0 ] ,m_y[0 ] ,m_x[1 ] ,m_y[1 ] ,m_x[2 ] ,m_y[2 ] ,x ,y ) or
 | ||
|        point_in_triangle(m_x[0 ] - 200 ,m_y[0 ] ,m_x[1 ] - 200 ,m_y[1 ] ,m_x[2 ] - 200 ,m_y[2 ] ,x ,y ) then
 | ||
|      begin
 | ||
|       m_dx :=x - m_x[0 ];
 | ||
|       m_dy :=y - m_y[0 ];
 | ||
|       m_idx:= 3;
 | ||
| 
 | ||
|      end;
 | ||
| 
 | ||
|   end;
 | ||
| 
 | ||
| end;
 | ||
| 
 | ||
| { ON_MOUSE_BUTTON_UP }
 | ||
| procedure the_application.on_mouse_button_up;
 | ||
| begin
 | ||
|  m_idx:=-1;
 | ||
| 
 | ||
| end;
 | ||
| 
 | ||
| { ON_KEY }
 | ||
| procedure the_application.on_key;
 | ||
| var
 | ||
|  dx ,dy : double;
 | ||
| 
 | ||
| begin
 | ||
|  dx:=0;
 | ||
|  dy:=0;
 | ||
| 
 | ||
|  case key of
 | ||
|   key_left  : dx:=-0.1;
 | ||
|   key_right : dx:= 0.1;
 | ||
|   key_up    : dy:= 0.1;
 | ||
|   key_down  : dy:=-0.1;
 | ||
| 
 | ||
|  end;
 | ||
| 
 | ||
|  m_x[0 ]:=m_x[0 ] + dx;
 | ||
|  m_y[0 ]:=m_y[0 ] + dy;
 | ||
|  m_x[1 ]:=m_x[1 ] + dx;
 | ||
|  m_y[1 ]:=m_y[1 ] + dy;
 | ||
| 
 | ||
|  force_redraw;
 | ||
| 
 | ||
|  if key = key_f1 then
 | ||
|   message_(
 | ||
|    'It''s a very simple example that was written to compare the performance between '#13 +
 | ||
|    'Anti-Aliased and regular polygon filling. It appears that the most expensive '#13 +
 | ||
|    'operation is rendering of horizontal scanlines. So that, we can use the very '#13 +
 | ||
|    'same rasterization algorithm to draw regular, aliased polygons. Of course, it''s '#13 +
 | ||
|    'possible to write a special version of the rasterizer that will work faster, but '#13 +
 | ||
|    'won''t calculate the pixel coverage values. But on the other hand, the existing '#13 +
 | ||
|    'version of the rasterizer_scanline_aa allows you to change gamma, and to "dilate" '#13 +
 | ||
|    'or "shrink" the polygons in range of <20> 1 pixel.'#13#13 +
 | ||
|    'How to play with:'#13#13 +
 | ||
|    'As usual, you can drag the triangles as well as the vertices of them. '#13 +
 | ||
|    'Compare the performance with different shapes and opacity.' +
 | ||
|    #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory.  ' );
 | ||
| 
 | ||
| end;
 | ||
| 
 | ||
| { ON_CTRL_CHANGE }
 | ||
| procedure the_application.on_ctrl_change;
 | ||
| var
 | ||
|  i : int;
 | ||
| 
 | ||
|  t1 ,t2 : double;
 | ||
| 
 | ||
|  buf : array[0..99 ] of char;
 | ||
| 
 | ||
| begin
 | ||
|  if m_test._status then
 | ||
|   begin
 | ||
|    on_draw;
 | ||
|    update_window;
 | ||
|    m_test.status_(false );
 | ||
| 
 | ||
|    start_timer;
 | ||
| 
 | ||
|    for i:=0 to 999 do
 | ||
|     draw_aliased;
 | ||
| 
 | ||
|    t1:=elapsed_time;
 | ||
| 
 | ||
|    start_timer;
 | ||
| 
 | ||
|    for i:=0 to 999 do
 | ||
|     draw_anti_aliased;
 | ||
| 
 | ||
|    t2:=elapsed_time;
 | ||
| 
 | ||
|    update_window;
 | ||
| 
 | ||
|    sprintf (@buf[0 ] ,'Time Aliased=%.2fms '#0 ,t1 );
 | ||
|    sprintf (@buf[StrLen(@buf[0 ] ) ] ,'Time Anti-Aliased=%.2fms'#0 ,t2 );
 | ||
|    message_(@buf[0 ] );
 | ||
| 
 | ||
|   end;
 | ||
| 
 | ||
| end;
 | ||
| 
 | ||
| VAR
 | ||
|  app : the_application;
 | ||
| 
 | ||
| BEGIN
 | ||
|  app.Construct(pix_format ,flip_y );
 | ||
|  app.caption_ ('AGG Example. Line Join (F1-Help)' );
 | ||
| 
 | ||
|  if app.init(500 ,330 ,window_resize ) then
 | ||
|   app.run;
 | ||
| 
 | ||
|  app.Destruct;
 | ||
| 
 | ||
| END.
 | 
