mirror of
				https://gitlab.com/freepascal.org/lazarus/lazarus.git
				synced 2025-11-04 08:19:53 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			503 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			ObjectPascal
		
	
	
	
	
	
			
		
		
	
	
			503 lines
		
	
	
		
			11 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
 | 
						|
 alpha_gradient ;
 | 
						|
 | 
						|
uses
 | 
						|
 agg_basics ,
 | 
						|
 agg_platform_support ,
 | 
						|
 | 
						|
 agg_color ,
 | 
						|
 agg_pixfmt ,
 | 
						|
 agg_pixfmt_rgb ,
 | 
						|
 | 
						|
 agg_ctrl ,
 | 
						|
 agg_spline_ctrl ,
 | 
						|
 | 
						|
 agg_renderer_base ,
 | 
						|
 agg_renderer_scanline ,
 | 
						|
 agg_rasterizer_scanline_aa ,
 | 
						|
 agg_scanline ,
 | 
						|
 agg_scanline_u ,
 | 
						|
 agg_render_scanlines ,
 | 
						|
 | 
						|
 agg_array ,
 | 
						|
 agg_span_gradient ,
 | 
						|
 agg_span_gradient_alpha ,
 | 
						|
 agg_span_interpolator_linear ,
 | 
						|
 agg_span_converter ,
 | 
						|
 agg_span_allocator ,
 | 
						|
 agg_ellipse ,
 | 
						|
 agg_vcgen_stroke ,
 | 
						|
 agg_trans_affine ,
 | 
						|
 agg_math ;
 | 
						|
 | 
						|
{$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_alpha : spline_ctrl;
 | 
						|
 | 
						|
   constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
 | 
						|
   destructor  Destruct;
 | 
						|
 | 
						|
   procedure fill_color_array(array_ : pod_auto_array_ptr; begin_ ,middle_ ,end_ : aggclr_ptr );
 | 
						|
 | 
						|
   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;
 | 
						|
 | 
						|
  end;
 | 
						|
 | 
						|
{ CONSTRUCT }
 | 
						|
constructor the_application.Construct;
 | 
						|
begin
 | 
						|
 inherited Construct(format_ ,flip_y_ );
 | 
						|
 | 
						|
 m_alpha.Construct(2 ,2 ,200 ,30 ,6 ,not flip_y_ );
 | 
						|
 | 
						|
 m_idx:=-1;
 | 
						|
 | 
						|
 m_x[0 ]:=257;
 | 
						|
 m_y[0 ]:=60;
 | 
						|
 m_x[1 ]:=369;
 | 
						|
 m_y[1 ]:=170;
 | 
						|
 m_x[2 ]:=143;
 | 
						|
 m_y[2 ]:=310;
 | 
						|
 | 
						|
 m_alpha.point_(0 ,0.0       ,0.0);
 | 
						|
 m_alpha.point_(1 ,1.0 / 5.0 ,1.0 - 4.0 / 5.0 );
 | 
						|
 m_alpha.point_(2 ,2.0 / 5.0 ,1.0 - 3.0 / 5.0 );
 | 
						|
 m_alpha.point_(3 ,3.0 / 5.0 ,1.0 - 2.0 / 5.0 );
 | 
						|
 m_alpha.point_(4 ,4.0 / 5.0 ,1.0 - 1.0 / 5.0 );
 | 
						|
 m_alpha.point_(5 ,1.0       ,1.0 );
 | 
						|
 | 
						|
 m_alpha.update_spline;
 | 
						|
 | 
						|
 add_ctrl(@m_alpha );
 | 
						|
 | 
						|
end;
 | 
						|
 | 
						|
{ DESTRUCT }
 | 
						|
destructor the_application.Destruct;
 | 
						|
begin
 | 
						|
 inherited Destruct;
 | 
						|
 | 
						|
 m_alpha.Destruct;
 | 
						|
 | 
						|
end;
 | 
						|
 | 
						|
{ FILL_COLOR_ARRAY }
 | 
						|
procedure the_application.fill_color_array;
 | 
						|
var
 | 
						|
 i : unsigned;
 | 
						|
 | 
						|
begin
 | 
						|
 i:=0;
 | 
						|
 | 
						|
 while i < 128 do
 | 
						|
  begin
 | 
						|
   aggclr_ptr(array_.array_operator(i ) )^:=
 | 
						|
    begin_.gradient(middle_ ,i / 128.0 );
 | 
						|
 | 
						|
   inc(i );
 | 
						|
 | 
						|
  end;
 | 
						|
 | 
						|
 while i < 256 do
 | 
						|
  begin
 | 
						|
   aggclr_ptr(array_.array_operator(i ) )^:=
 | 
						|
    middle_.gradient(end_ ,(i - 128 ) / 128.0 );
 | 
						|
 | 
						|
   inc(i );
 | 
						|
 | 
						|
  end;
 | 
						|
 | 
						|
end;
 | 
						|
 | 
						|
{ ON_DRAW }
 | 
						|
procedure the_application.on_draw;
 | 
						|
type
 | 
						|
// Gradient shape function (linear, radial, custom, etc)
 | 
						|
 gradient_func_type = gradient_circle;
 | 
						|
 | 
						|
// Alpha gradient shape function (linear, radial, custom, etc)
 | 
						|
 gradient_alpha_func_type = gradient_xy;
 | 
						|
 | 
						|
// Span interpolator. This object is used in all span generators 
 | 
						|
// that operate with transformations during iterating of the spans,
 | 
						|
// for example, image transformers use the interpolator too.
 | 
						|
 interpolator_type = span_interpolator_linear;
 | 
						|
 | 
						|
// Span allocator is an object that allocates memory for
 | 
						|
// the array of colors that will be used to render the
 | 
						|
// color spans. One object can be shared between different
 | 
						|
// span generators.
 | 
						|
 span_allocator_type = span_allocator;
 | 
						|
 | 
						|
// Gradient colors array adaptor
 | 
						|
 gradient_colors_type = pod_auto_array;
 | 
						|
 | 
						|
// Finally, the gradient span generator working with the color_type
 | 
						|
// color type.
 | 
						|
 span_gradient_type = span_gradient;
 | 
						|
 | 
						|
// Gradient alpha array adaptor
 | 
						|
 gradient_alpha_type = pod_auto_array;
 | 
						|
 | 
						|
// The alpha gradient span converter working with the color_type
 | 
						|
// color type.
 | 
						|
 span_gradient_alpha_type = span_gradient_alpha;
 | 
						|
 | 
						|
// Span converter type
 | 
						|
 span_conv_type = span_converter;
 | 
						|
 | 
						|
// The gradient (plus span converter) renderer type
 | 
						|
 renderer_gradient_type = renderer_scanline_aa;
 | 
						|
 | 
						|
var
 | 
						|
 pf : pixel_formats;
 | 
						|
 | 
						|
 rgba ,
 | 
						|
 rgbb ,
 | 
						|
 rgbc : aggclr;
 | 
						|
 | 
						|
 ren_base  : renderer_base;
 | 
						|
 ren_solid : renderer_scanline_aa_solid;
 | 
						|
 | 
						|
 sl  : scanline_u8;
 | 
						|
 ras : rasterizer_scanline_aa;
 | 
						|
 | 
						|
 ell : ellipse;
 | 
						|
 | 
						|
 i ,w ,h : unsigned;
 | 
						|
 | 
						|
 parallelogram : array[0..5 ] of double;
 | 
						|
 | 
						|
 tas : trans_affine_scaling;
 | 
						|
 tar : trans_affine_rotation;
 | 
						|
 tat : trans_affine_translation;
 | 
						|
 | 
						|
 stroke : vcgen_stroke;
 | 
						|
 | 
						|
// The gradient objects declarations
 | 
						|
 gradient_func           : gradient_func_type;       // The gradient function
 | 
						|
 alpha_func              : gradient_alpha_func_type; // The gradient function
 | 
						|
 gradient_mtx            ,                           // Gradient affine transformer
 | 
						|
 alpha_mtx               : trans_affine;             // Alpha affine transformer
 | 
						|
 span_interpolator       ,                           // Span gradient interpolator
 | 
						|
 span_interpolator_alpha : interpolator_type;        // Span alpha interpolator
 | 
						|
 span_allocator          : span_allocator_type;      // Span Allocator
 | 
						|
 color_array             : gradient_colors_type;     // The gradient colors
 | 
						|
 | 
						|
 span_gradient       : span_gradient_type;
 | 
						|
 alpha_array         : gradient_alpha_type;
 | 
						|
 span_gradient_alpha : span_gradient_alpha_type;
 | 
						|
 span_conv           : span_conv_type;
 | 
						|
 ren_gradient        : renderer_gradient_type;
 | 
						|
 | 
						|
begin
 | 
						|
// Initialize structures
 | 
						|
 pixfmt_bgr24(pf ,rbuf_window );
 | 
						|
 | 
						|
 ren_base.Construct (@pf );
 | 
						|
 ren_solid.Construct(@ren_base );
 | 
						|
 | 
						|
 rgba.ConstrDbl(1 ,1 ,1 );
 | 
						|
 ren_base.clear(@rgba );
 | 
						|
 | 
						|
 sl.Construct;
 | 
						|
 ras.Construct;
 | 
						|
 | 
						|
// Draw some background
 | 
						|
 ell.Construct;
 | 
						|
 | 
						|
 RandSeed:=1234;
 | 
						|
 | 
						|
 w:=trunc(_width );
 | 
						|
 h:=trunc(_height );
 | 
						|
 | 
						|
 for i:=0 to 99 do
 | 
						|
  begin
 | 
						|
   ell.init(
 | 
						|
    Random($7fff ) mod w ,Random($7fff ) mod h ,
 | 
						|
    Random($7fff ) mod 60 + 5 ,Random($7fff ) mod 60 + 5 ,50 );
 | 
						|
 | 
						|
   rgba.ConstrDbl(
 | 
						|
    Random($7fff ) / $7fff ,
 | 
						|
    Random($7fff ) / $7fff ,
 | 
						|
    Random($7fff ) / $7fff ,
 | 
						|
    Random($7fff ) / $7fff / 2.0 );
 | 
						|
 | 
						|
   ren_solid.color_(@rgba );
 | 
						|
   ras.add_path    (@ell);
 | 
						|
   render_scanlines(@ras ,@sl ,@ren_solid );
 | 
						|
 | 
						|
  end;
 | 
						|
 | 
						|
 parallelogram[0 ]:=m_x[0 ];
 | 
						|
 parallelogram[1 ]:=m_y[0 ];
 | 
						|
 parallelogram[2 ]:=m_x[1 ];
 | 
						|
 parallelogram[3 ]:=m_y[1 ];
 | 
						|
 parallelogram[4 ]:=m_x[2 ];
 | 
						|
 parallelogram[5 ]:=m_y[2 ];
 | 
						|
 | 
						|
// The gradient objects initializations
 | 
						|
 gradient_func.Construct;
 | 
						|
 alpha_func.Construct;
 | 
						|
 gradient_mtx.Construct;
 | 
						|
 alpha_mtx.Construct;
 | 
						|
 span_interpolator.Construct      (@gradient_mtx );
 | 
						|
 span_interpolator_alpha.Construct(@alpha_mtx );
 | 
						|
 span_allocator.Construct;
 | 
						|
 color_array.Construct(256 ,sizeof(aggclr ) );
 | 
						|
 | 
						|
// Initialize the gradient span itself.
 | 
						|
// The last two arguments are so called "d1" and "d2"
 | 
						|
// defining two distances in pixels, where the gradient starts
 | 
						|
// and where it ends. The actual meaning of "d1" and "d2" depands
 | 
						|
// on the gradient function.
 | 
						|
 span_gradient.Construct(
 | 
						|
  @span_allocator ,
 | 
						|
  @span_interpolator ,
 | 
						|
  @gradient_func ,
 | 
						|
  @color_array ,0 ,150 );
 | 
						|
 | 
						|
 alpha_array.Construct(256 ,sizeof(int8u ) );
 | 
						|
 | 
						|
 span_gradient_alpha.Construct(
 | 
						|
  @span_interpolator_alpha ,
 | 
						|
  @alpha_func ,
 | 
						|
  @alpha_array ,0 ,100 );
 | 
						|
 | 
						|
// Span converter initialization
 | 
						|
 span_conv.Construct(@span_gradient ,@span_gradient_alpha );
 | 
						|
 | 
						|
// The gradient renderer
 | 
						|
 ren_gradient.Construct(@ren_base ,@span_conv );
 | 
						|
 | 
						|
// Finally we can draw a circle
 | 
						|
 tas.Construct(0.75 ,1.2 );
 | 
						|
 tar.Construct(pi / 3.0 );
 | 
						|
 tat.Construct(_width / 2 ,_height / 2 );
 | 
						|
 | 
						|
 gradient_mtx.multiply(@tas );
 | 
						|
 gradient_mtx.multiply(@tar );
 | 
						|
 gradient_mtx.multiply(@tat );
 | 
						|
 gradient_mtx.invert;
 | 
						|
 | 
						|
 alpha_mtx.parl_to_rect(@parallelogram ,-100 ,-100 ,100 ,100 );
 | 
						|
 | 
						|
 rgba.ConstrDbl(0    ,0.19 ,0.19 );
 | 
						|
 rgbb.ConstrDbl(0.7  ,0.7  ,0.19 );
 | 
						|
 rgbc.ConstrDbl(0.31 ,0    ,0 );
 | 
						|
 | 
						|
 fill_color_array(@color_array ,@rgba ,@rgbb ,@rgbc );
 | 
						|
 | 
						|
// Fill Alpha array
 | 
						|
 for i:=0 to 255 do
 | 
						|
  int8u_ptr(alpha_array.array_operator(i ) )^:=
 | 
						|
   int8u(trunc(m_alpha._value(i / 255.0 ) * base_mask ) );
 | 
						|
 | 
						|
 ell.init(_width / 2 ,_height / 2 ,150 ,150 ,100 );
 | 
						|
 | 
						|
 ras.add_path    (@ell);
 | 
						|
 render_scanlines(@ras ,@sl ,@ren_gradient );
 | 
						|
 | 
						|
// Draw the control points and the parallelogram
 | 
						|
 rgba.ConstrDbl  (0 ,0.4 ,0.4 ,0.31 );
 | 
						|
 ren_solid.color_(@rgba );
 | 
						|
 | 
						|
 ell.init        (m_x[0 ] ,m_y[0 ] ,5 ,5 ,20 );
 | 
						|
 ras.add_path    (@ell);
 | 
						|
 render_scanlines(@ras ,@sl ,@ren_solid );
 | 
						|
 | 
						|
 ell.init        (m_x[1 ] ,m_y[1 ] ,5 ,5 ,20 );
 | 
						|
 ras.add_path    (@ell );
 | 
						|
 render_scanlines(@ras ,@sl ,@ren_solid );
 | 
						|
 | 
						|
 ell.init        (m_x[2 ] ,m_y[2 ] ,5 ,5 ,20 );
 | 
						|
 ras.add_path    (@ell );
 | 
						|
 render_scanlines(@ras ,@sl ,@ren_solid );
 | 
						|
 | 
						|
 stroke.Construct;
 | 
						|
 stroke.add_vertex(m_x[0 ] ,m_y[0 ] ,path_cmd_move_to );
 | 
						|
 stroke.add_vertex(m_x[1 ] ,m_y[1 ] ,path_cmd_line_to );
 | 
						|
 stroke.add_vertex(m_x[2 ] ,m_y[2 ] ,path_cmd_line_to );
 | 
						|
 stroke.add_vertex(m_x[0 ] + m_x[2 ] - m_x[1 ] ,m_y[0 ] + m_y[2 ] - m_y[1 ] ,path_cmd_line_to );
 | 
						|
 stroke.add_vertex(0 ,0 ,path_cmd_end_poly or path_flags_close );
 | 
						|
 | 
						|
 rgba.ConstrDbl  (0 ,0 ,0 );
 | 
						|
 ren_solid.color_(@rgba );
 | 
						|
 ras.add_path    (@stroke);
 | 
						|
 render_scanlines(@ras ,@sl ,@ren_solid );
 | 
						|
 | 
						|
// Render the controls
 | 
						|
 render_ctrl(@ras ,@sl ,@ren_solid ,@m_alpha );
 | 
						|
 | 
						|
// Free AGG resources
 | 
						|
 sl.Destruct;
 | 
						|
 ras.Destruct;
 | 
						|
 | 
						|
 span_allocator.Destruct;
 | 
						|
 color_array.Destruct;
 | 
						|
 alpha_array.Destruct;
 | 
						|
 | 
						|
 stroke.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
 | 
						|
 else
 | 
						|
  on_mouse_button_up(x ,y ,flags );
 | 
						|
 | 
						|
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 ] ) ) < 10.0 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 ) 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_(
 | 
						|
   'The demo shows how to combine any span generator with alpha-channel gradient.'#13#13 +
 | 
						|
   'How to play with:'#13#13 +
 | 
						|
   'Use the mouse to move the parallelogram around.'#13 +
 | 
						|
   'Use the arrow keys to move the parallelogram very precisely.' +
 | 
						|
   #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory.  ' );
 | 
						|
 | 
						|
end;
 | 
						|
 | 
						|
VAR
 | 
						|
 app : the_application;
 | 
						|
 | 
						|
BEGIN
 | 
						|
 app.Construct(pix_format_bgr24 ,flip_y );
 | 
						|
 app.caption_ ('AGG Example. Alpha channel gradient (F1-Help)' );
 | 
						|
 | 
						|
 if app.init(400 ,320 ,window_resize ) then
 | 
						|
  app.run;
 | 
						|
 | 
						|
 app.Destruct;
 | 
						|
 | 
						|
END. |