lazarus/components/aggpas/graph_test.dpr
mattias 36a2b1ea07 added aggpas
git-svn-id: trunk@21942 -
2009-10-01 12:24:32 +00:00

1591 lines
28 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
graph_test ;
uses
SysUtils ,
agg_basics ,
agg_platform_support ,
agg_color ,
agg_pixfmt ,
agg_pixfmt_rgb ,
agg_ctrl ,
agg_slider_ctrl ,
agg_cbox_ctrl ,
agg_rbox_ctrl ,
agg_renderer_base ,
agg_renderer_scanline ,
agg_renderer_primitives ,
agg_rasterizer_scanline_aa ,
agg_rasterizer_outline ,
agg_scanline ,
agg_scanline_p ,
agg_scanline_u ,
agg_render_scanlines ,
agg_array ,
agg_curves ,
agg_ellipse ,
agg_vertex_source ,
agg_conv_stroke ,
agg_conv_dash ,
agg_conv_curve ,
agg_conv_contour ,
agg_conv_marker ,
agg_conv_shorten_path ,
agg_conv_marker_adaptor ,
agg_conv_concat ,
agg_arrowhead ,
agg_vcgen_markers_term ,
agg_span_allocator ,
agg_span_gradient ,
agg_span_interpolator_linear ,
agg_gamma_functions ,
agg_trans_affine ;
{$I agg_mode.inc }
{$I- }
const
flip_y = true;
type
base_renderer = renderer_base;
primitives_renderer = renderer_primitives;
solid_renderer = renderer_scanline_aa_solid;
draft_renderer = renderer_scanline_bin_solid;
gradient_function = gradient_radial_d;
interpolator = span_interpolator_linear;
gradient_span_gen = span_gradient;
gradient_span_alloc = span_allocator;
gradient_renderer = renderer_scanline_aa;
scanline_rasterizer = rasterizer_scanline_aa;
outline_rasterizer = rasterizer_outline;
node_ptr = ^node;
node = object
x ,y : double;
constructor Construct; overload;
constructor Construct(x_ ,y_ : double ); overload;
end;
edge_ptr = ^edge;
edge = object
node1 ,node2 : int;
constructor Construct; overload;
constructor Construct(n1 ,n2 : int ); overload;
end;
graph = object
m_num_nodes ,
m_num_edges : int;
m_nodes : node_ptr;
m_edges : edge_ptr;
constructor Construct(num_nodes ,num_edges : int );
destructor Destruct;
function get_num_nodes : int;
function get_num_edges : int;
function get_node(idx : int; w ,h : double ) : node;
function get_edge(idx : int ) : edge;
end;
line = object(vertex_source )
x1 ,y1 ,x2 ,y2 : double;
f : int;
constructor Construct(x1_ ,y1_ ,x2_ ,y2_ : double );
procedure rewind(path_id : unsigned ); virtual;
function vertex(x ,y : double_ptr ) : unsigned; virtual;
end;
curve = object(vertex_source )
c : curve4;
constructor Construct(x1 ,y1 ,x2 ,y2 : double; k : double = 0.5 );
destructor Destruct; virtual;
procedure rewind(path_id : unsigned ); virtual;
function vertex(x ,y : double_ptr ) : unsigned; virtual;
end;
stroke_draft_simple = object(vertex_source )
s : vertex_source_ptr;
constructor Construct(src : vertex_source_ptr );
procedure rewind(path_id : unsigned ); virtual;
function vertex(x ,y : double_ptr ) : unsigned; virtual;
end;
stroke_draft_arrow = object(vertex_source )
s : conv_marker_adaptor;
ah : arrowhead;
m : conv_marker;
ma : vcgen_markers_term;
c : conv_concat;
constructor Construct(src : vertex_source_ptr; w : double );
destructor Destruct; virtual;
procedure rewind(path_id : unsigned ); virtual;
function vertex(x ,y : double_ptr ) : unsigned; virtual;
end;
stroke_fine_simple = object(vertex_source )
s : conv_stroke;
constructor Construct(src : vertex_source_ptr; w : double );
destructor Destruct; virtual;
procedure rewind(path_id : unsigned ); virtual;
function vertex(x ,y : double_ptr ) : unsigned; virtual;
end;
stroke_fine_arrow = object(vertex_source )
s : conv_stroke;
ah : arrowhead;
m : conv_marker;
ma : vcgen_markers_term;
c : conv_concat;
constructor Construct(src : vertex_source_ptr; w : double );
destructor Destruct; virtual;
procedure rewind(path_id : unsigned ); virtual;
function vertex(x ,y : double_ptr ) : unsigned; virtual;
end;
dash_stroke_draft_simple = object(vertex_source )
d : conv_dash;
constructor Construct(src : vertex_source_ptr; dash_len ,gap_len ,w : double );
destructor Destruct; virtual;
procedure rewind(path_id : unsigned ); virtual;
function vertex(x ,y : double_ptr ) : unsigned; virtual;
end;
dash_stroke_draft_arrow = object(vertex_source )
d : conv_dash;
ah : arrowhead;
m : conv_marker;
ma : vcgen_markers_term;
c : conv_concat;
constructor Construct(src : vertex_source_ptr; dash_len ,gap_len ,w : double );
destructor Destruct; virtual;
procedure rewind(path_id : unsigned ); virtual;
function vertex(x ,y : double_ptr ) : unsigned; virtual;
end;
dash_stroke_fine_simple = object(vertex_source )
d : conv_dash;
s : conv_stroke;
constructor Construct(src : vertex_source_ptr; dash_len ,gap_len ,w : double );
destructor Destruct; virtual;
procedure rewind(path_id : unsigned ); virtual;
function vertex(x ,y : double_ptr ) : unsigned; virtual;
end;
dash_stroke_fine_arrow = object(vertex_source )
d : conv_dash;
s : conv_stroke;
ah : arrowhead;
m : conv_marker;
ma : vcgen_markers_term;
c : conv_concat;
constructor Construct(src : vertex_source_ptr; dash_len ,gap_len ,w : double );
destructor Destruct; virtual;
procedure rewind(path_id : unsigned ); virtual;
function vertex(x ,y : double_ptr ) : unsigned; virtual;
end;
{ stroke_draft = stroke_draft_simple;
dash_stroke_draft = dash_stroke_draft_simple;
stroke_fine = stroke_fine_simple;
dash_stroke_fine = dash_stroke_fine_simple;{}
stroke_draft = stroke_draft_arrow;
dash_stroke_draft = dash_stroke_draft_arrow;
stroke_fine = stroke_fine_arrow;
dash_stroke_fine = dash_stroke_fine_arrow;{}
the_application = object(platform_support )
m_type : rbox_ctrl;
m_width : slider_ctrl;
m_benchmark ,
m_draw_nodes ,
m_draw_edges ,
m_draft ,
m_translucent : cbox_ctrl;
m_gradient_colors : pod_auto_array;
m_graph : graph;
m_draw : int;
m_sl : scanline_u8;
constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
destructor Destruct;
procedure draw_nodes_draft;
procedure draw_nodes_fine(ras : rasterizer_scanline_ptr );
procedure render_edge_fine(
ras : rasterizer_scanline_ptr;
ren_fine ,
ren_draft : renderer_scanline_ptr;
src : vertex_source_ptr );
procedure draw_lines_draft;
procedure draw_curves_draft;
procedure draw_dashes_draft;
procedure draw_lines_fine(
ras : rasterizer_scanline_ptr;
solid ,
draft : renderer_scanline_ptr );
procedure draw_curves_fine(
ras : rasterizer_scanline_ptr;
solid ,
draft : renderer_scanline_ptr );
procedure draw_dashes_fine(
ras : rasterizer_scanline_ptr;
solid ,
draft : renderer_scanline_ptr );
procedure draw_polygons(
ras : rasterizer_scanline_ptr;
solid ,
draft : renderer_scanline_ptr );
procedure draw_scene(
ras : rasterizer_scanline_ptr;
solid ,
draft : renderer_scanline_ptr );
procedure on_draw; virtual;
procedure on_ctrl_change; virtual;
procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
end;
{ CONSTRUCT }
constructor node.Construct;
begin
x:=0;
y:=0;
end;
{ CONSTRUCT }
constructor node.Construct(x_ ,y_ : double );
begin
x:=x_;
y:=y_;
end;
{ CONSTRUCT }
constructor edge.Construct;
begin
node1:=0;
node2:=0;
end;
{ CONSTRUCT }
constructor edge.Construct(n1 ,n2 : int );
begin
node1:=n1;
node2:=n2;
end;
{ CONSTRUCT }
constructor graph.Construct;
var
i : int;
n : node_ptr;
e : edge_ptr;
begin
m_num_nodes:=num_nodes;
m_num_edges:=num_edges;
agg_getmem(pointer(m_nodes ) ,m_num_nodes * sizeof(node ) );
agg_getmem(pointer(m_edges ) ,m_num_edges * sizeof(edge ) );
RandSeed:=100;
for i:=0 to m_num_nodes - 1 do
begin
n:=node_ptr(ptrcomp(m_nodes ) + i * sizeof(node ) );
n.x:=(Random($7fff ) / $7fff ) * 0.75 + 0.2;
n.y:=(Random($7fff ) / $7fff ) * 0.85 + 0.1;
end;
i:=0;
while i < m_num_edges do
begin
e:=edge_ptr(ptrcomp(m_edges ) + i * sizeof(edge ) );
e.node1:=Random($7fff ) mod m_num_nodes;
e.node2:=Random($7fff ) mod m_num_nodes;
if e.node1 = e.node2 then
dec(i );
inc(i );
end;
end;
{ DESTRUCT }
destructor graph.Destruct;
begin
agg_freemem(pointer(m_nodes ) ,m_num_nodes * sizeof(node ) );
agg_freemem(pointer(m_edges ) ,m_num_edges * sizeof(edge ) );
end;
{ GET_NUM_NODES }
function graph.get_num_nodes;
begin
result:=m_num_nodes;
end;
{ GET_NUM_EDGES }
function graph.get_num_edges;
begin
result:=m_num_edges;
end;
{ GET_NODE }
function graph.get_node;
var
p : node;
begin
p.Construct;
if idx < m_num_nodes then
begin
p:=node_ptr(ptrcomp(m_nodes ) + idx * sizeof(node ) )^;
p.x:=p.x * w;
p.y:=p.y * h;
end;
result:=p;
end;
{ GET_EDGE }
function graph.get_edge;
var
b : edge;
begin
b.Construct;
if idx < m_num_edges then
b:=edge_ptr(ptrcomp(m_edges ) + idx * sizeof(edge ) )^;
result:=b;
end;
{ CONSTRUCT }
constructor line.Construct;
begin
x1:=x1_;
y1:=y1_;
x2:=x2_;
y2:=y2_;
f :=0;
end;
{ REWIND }
procedure line.rewind;
begin
f:=0;
end;
{ VERTEX }
function line.vertex;
begin
if f = 0 then
begin
inc(f );
x^:=x1;
y^:=y1;
result:=path_cmd_move_to;
exit;
end;
if f = 1 then
begin
inc(f );
x^:=x2;
y^:=y2;
result:=path_cmd_line_to;
exit;
end;
result:=path_cmd_stop;
end;
{ CONSTRUCT }
constructor curve.Construct;
begin
c.Construct;
c.init4(
x1 ,y1 ,
x1 - (y2 - y1 ) * k ,
y1 + (x2 - x1 ) * k ,
x2 + (y2 - y1 ) * k ,
y2 - (x2 - x1 ) * k ,
x2 ,y2 );
end;
{ DESTRUCT }
destructor curve.Destruct;
begin
c.Destruct;
end;
{ REWIND }
procedure curve.rewind;
begin
c.rewind(path_id );
end;
{ VERTEX }
function curve.vertex;
begin
result:=c.vertex(x ,y );
end;
{ CONSTRUCT }
constructor stroke_draft_simple.Construct;
begin
s:=src;
end;
{ REWIND }
procedure stroke_draft_simple.rewind;
begin
s.rewind(path_id );
end;
{ VERTEX }
function stroke_draft_simple.vertex;
begin
s.vertex(x ,y );
end;
{ CONSTRUCT }
constructor stroke_draft_arrow.Construct;
begin
s.Construct(src );
ma.Construct;
s.set_markers(@ma );
ah.Construct;
m.Construct(s.markers ,@ah );
c.Construct(@s ,@m );
ah.head_ (0 ,10 ,5 ,0 );
s.shorten_(10.0 );
end;
{ DESTRUCT }
destructor stroke_draft_arrow.Destruct;
begin
s.Destruct;
ma.Destruct;
end;
{ REWIND }
procedure stroke_draft_arrow.rewind;
begin
c.rewind(path_id );
end;
{ VERTEX }
function stroke_draft_arrow.vertex;
begin
result:=c.vertex(x ,y );
end;
{ CONSTRUCT }
constructor stroke_fine_simple.Construct;
begin
s.Construct(src );
s.width_ (w );
end;
{ DESTRUCT }
destructor stroke_fine_simple.Destruct;
begin
s.Destruct;
end;
{ REWIND }
procedure stroke_fine_simple.rewind;
begin
s.rewind(path_id );
end;
{ VERTEX }
function stroke_fine_simple.vertex;
begin
result:=s.vertex(x ,y );
end;
{ CONSTRUCT }
constructor stroke_fine_arrow.Construct;
begin
s.Construct(src );
ma.Construct;
s.set_markers(@ma );
ah.Construct;
m.Construct(s.markers ,@ah );
c.Construct(@s ,@m );
s.width_ (w );
ah.head_ (0 ,10 ,5 ,0 );
s.shorten_(w * 2.0 );
end;
{ DESTRUCT }
destructor stroke_fine_arrow.Destruct;
begin
s.Destruct;
ma.Destruct;
end;
{ REWIND }
procedure stroke_fine_arrow.rewind;
begin
c.rewind(path_id );
end;
{ VERTEX }
function stroke_fine_arrow.vertex;
begin
result:=c.vertex(x ,y );
end;
{ CONSTRUCT }
constructor dash_stroke_draft_simple.Construct;
begin
d.Construct(src );
d.add_dash (dash_len ,gap_len );
end;
{ DESTRUCT }
destructor dash_stroke_draft_simple.Destruct;
begin
d.Destruct;
end;
{ REWIND }
procedure dash_stroke_draft_simple.rewind;
begin
d.rewind(path_id );
end;
{ VERTEX }
function dash_stroke_draft_simple.vertex;
begin
result:=d.vertex(x ,y );
end;
{ CONSTRUCT }
constructor dash_stroke_draft_arrow.Construct;
begin
d.Construct(src );
ma.Construct;
d.set_markers(@ma );
ah.Construct;
m.Construct(d.markers ,@ah );
c.Construct(@d ,@m );
d.add_dash(dash_len ,gap_len );
ah.head_ (0 ,10 ,5 ,0 );
d.shorten_(10.0 );
end;
{ DESTRUCT }
destructor dash_stroke_draft_arrow.Destruct;
begin
d.Destruct;
ma.Destruct;
end;
{ REWIND }
procedure dash_stroke_draft_arrow.rewind;
begin
c.rewind(path_id );
end;
{ VERTEX }
function dash_stroke_draft_arrow.vertex;
begin
result:=c.vertex(x ,y );
end;
{ CONSTRUCT }
constructor dash_stroke_fine_simple.Construct;
begin
d.Construct(src );
s.Construct(@d );
d.add_dash(dash_len ,gap_len );
s.width_ (w );
end;
{ DESTRUCT }
destructor dash_stroke_fine_simple.Destruct;
begin
d.Destruct;
s.Destruct;
end;
{ REWIND }
procedure dash_stroke_fine_simple.rewind;
begin
s.rewind(path_id );
end;
{ VERTEX }
function dash_stroke_fine_simple.vertex;
begin
result:=s.vertex(x ,y );
end;
{ CONSTRUCT }
constructor dash_stroke_fine_arrow.Construct;
begin
d.Construct(src );
ma.Construct;
d.set_markers(@ma );
s.Construct(@d );
ah.Construct;
m.Construct(d.markers ,@ah );
c.Construct(@s ,@m );
d.add_dash(dash_len ,gap_len );
s.width_ (w );
ah.head_ (0 ,10 ,5 ,0 );
d.shorten_(w * 2.0 );
end;
{ DESTRUCT }
destructor dash_stroke_fine_arrow.Destruct;
begin
d.Destruct;
s.Destruct;
ma.Destruct;
end;
{ REWIND }
procedure dash_stroke_fine_arrow.rewind;
begin
c.rewind(path_id );
end;
{ VERTEX }
function dash_stroke_fine_arrow.vertex;
begin
result:=c.vertex(x ,y );
end;
{ CONSTRUCT }
constructor the_application.Construct;
var
i : int;
c1 ,c2 : aggclr;
begin
inherited Construct(format_ ,flip_y_ );
m_type.Construct (-1 ,-1 ,-1 ,-1 ,not flip_y_ );
m_width.Construct(110 + 80 ,8.0 ,110 + 200.0 + 80 ,8.0 + 7.0 ,not flip_y_ );
m_benchmark.Construct (110 + 200 + 80 + 8 ,8.0 - 2.0 ,'Benchmark' ,not flip_y_ );
m_draw_nodes.Construct (110 + 200 + 80 + 8 ,8.0 - 2.0 + 15.0 ,'Draw Nodes' ,not flip_y_ );
m_draw_edges.Construct (200 + 200 + 80 + 8 ,8.0 - 2.0 + 15.0 ,'Draw Edges' ,not flip_y_ );
m_draft.Construct (200 + 200 + 80 + 8 ,8.0 - 2.0 ,'Draft Mode' ,not flip_y_ );
m_translucent.Construct(110 + 80 ,8.0 - 2.0 + 15.0 ,'Translucent Mode' ,not flip_y_ );
m_graph.Construct(200 ,100 );
m_sl.Construct;
m_draw:=3;
m_gradient_colors.Construct(256 ,sizeof(aggclr ) );
add_ctrl(@m_type );
m_type.text_size_(8.0 );
m_type.add_item ('Solid lines' );
m_type.add_item ('Bezier curves' );
m_type.add_item ('Dashed curves' );
m_type.add_item ('Poygons AA' );
m_type.add_item ('Poygons Bin' );
m_type.cur_item_ (0 );
add_ctrl(@m_width );
m_width.num_steps_(20 );
m_width.range_ (0.0 ,5.0 );
m_width.value_ (2.0 );
m_width.label_ ('Width=%1.2f' );
m_benchmark.text_size_ (8.0 );
m_draw_nodes.text_size_(8.0 );
m_draft.text_size_ (8.0 );
m_draw_nodes.status_ (true );
m_draw_edges.status_ (true );
add_ctrl(@m_benchmark );
add_ctrl(@m_draw_nodes );
add_ctrl(@m_draw_edges );
add_ctrl(@m_draft );
add_ctrl(@m_translucent );
c1.ConstrDbl(1 ,1 ,0 ,0.25 );
c2.ConstrDbl(0 ,0 ,1 );
for i:=0 to 255 do
aggclr_ptr(
m_gradient_colors.array_operator(i ) )^:=c1.gradient(@c2 ,i / 255.0 );
end;
{ DESTRUCT }
destructor the_application.Destruct;
begin
inherited Destruct;
m_type.Destruct;
m_width.Destruct;
m_benchmark.Destruct;
m_draw_nodes.Destruct;
m_draw_edges.Destruct;
m_draft.Destruct;
m_translucent.Destruct;
m_graph.Destruct;
m_sl.Destruct;
m_gradient_colors.Destruct;
end;
{ DRAW_NODES_DRAFT }
procedure the_application.draw_nodes_draft;
var
pixf : pixel_formats;
rb : base_renderer;
prim : primitives_renderer;
i : int;
n : node;
begin
pixfmt_bgr24 (pixf ,rbuf_window );
rb.Construct (@pixf );
prim.Construct(@rb );
i:=0;
while i < m_graph.get_num_nodes do
begin
n:=m_graph.get_node(i ,_width ,_height );
prim.fill_color_ (aggclr_ptr(m_gradient_colors.array_operator(147 ) ) );
prim.line_color_ (aggclr_ptr(m_gradient_colors.array_operator(255 ) ) );
prim.outlined_ellipse(trunc(n.x ) ,trunc(n.y ) ,10 ,10 );
prim.fill_color_ (aggclr_ptr(m_gradient_colors.array_operator(50 ) ) );
prim.solid_ellipse (trunc(n.x ) ,trunc(n.y ) ,4 ,4 );
inc(i );
end;
end;
{ DRAW_NODES_FINE }
procedure the_application.draw_nodes_fine;
var
pixf : pixel_formats;
sa : gradient_span_alloc;
rb : base_renderer;
gf : gradient_function;
sg : gradient_span_gen;
i : int;
n : node;
ell : ellipse;
mtx : trans_affine;
tas : trans_affine_scaling;
tat : trans_affine_translation;
ren : gradient_renderer;
inter : interpolator;
x ,y : double;
begin
sa.Construct;
pixfmt_bgr24(pixf ,rbuf_window );
rb.Construct(@pixf );
i:=0;
while i < m_graph.get_num_nodes do
begin
n:=m_graph.get_node(i ,_width ,_height );
ell.Construct(n.x ,n.y ,5.0 * m_width._value ,5.0 * m_width._value );
case m_draw of
0 :
begin
ell.rewind(0);
while not is_stop(ell.vertex(@x ,@y ) ) do;
end;
1 :
begin
ras.reset;
ras.add_path(@ell );
end;
2 :
begin
ras.reset;
ras.add_path(@ell );
ras.sort;
end;
3 :
begin
gf.Construct;
mtx.Construct;
tas.Construct(m_width._value / 2.0 ); mtx.multiply(@tas );
tat.Construct(n.x ,n.y ); mtx.multiply(@tat );
mtx.invert;
inter.Construct(@mtx );
sg.Construct (@sa ,@inter ,@gf ,@m_gradient_colors ,0.0 ,10.0 );
ren.Construct(@rb ,@sg );
ras.add_path (@ell);
render_scanlines(ras ,@m_sl ,@ren );
end;
end;
inc(i );
end;
sa.Destruct;
end;
{ RENDER_EDGE_FINE }
procedure the_application.render_edge_fine;
var
rgba : aggclr;
x ,y : double;
r ,g ,b ,a : int;
begin
case m_draw of
0 :
begin
src.rewind(0 );
while not is_stop(src.vertex(@x ,@y ) ) do;
end;
1 :
begin
ras.reset;
ras.add_path(src );
end;
2 :
begin
ras.reset;
ras.add_path(src );
ras.sort;
end;
3 :
begin
r:=Random($7fff ) and $7F;
g:=Random($7fff ) and $7F;
b:=Random($7fff ) and $7F;
a:=255;
if m_translucent._status then
a:=80;
ras.add_path(src );
if m_type._cur_item < 4 then
begin
rgba.ConstrInt (r ,g ,b ,a );
ren_fine.color_ (@rgba );
render_scanlines(ras ,@m_sl ,ren_fine );
end
else
begin
rgba.ConstrInt (r ,g ,b ,a );
ren_draft.color_(@rgba );
render_scanlines(ras ,@m_sl ,ren_draft );
end;
end;
end;
end;
{ DRAW_LINES_DRAFT }
procedure the_application.draw_lines_draft;
var
pixf : pixel_formats;
prim : primitives_renderer;
rgba : aggclr;
rb : base_renderer;
ras : outline_rasterizer;
i ,r ,g ,b ,a : int;
l : line;
s : stroke_draft;
e : edge;
n1 ,
n2 : node;
begin
pixfmt_bgr24(pixf ,rbuf_window );
rb.Construct (@pixf );
prim.Construct(@rb );
ras.Construct (@prim );
i:=0;
while i < m_graph.get_num_edges do
begin
e :=m_graph.get_edge(i );
n1:=m_graph.get_node(e.node1 ,_width ,_height );
n2:=m_graph.get_node(e.node2 ,_width ,_height );
l.Construct(n1.x ,n1.y ,n2.x ,n2.y );
s.Construct(@l ,m_width._value );
r:=Random($7fff ) and $7F;
g:=Random($7fff ) and $7F;
b:=Random($7fff ) and $7F;
a:=255;
if m_translucent._status then
a:=80;
rgba.ConstrInt (r ,g ,b ,a );
prim.line_color_(@rgba );
ras.add_path (@s );
s.Destruct;
inc(i );
end;
end;
{ DRAW_CURVES_DRAFT }
procedure the_application.draw_curves_draft;
var
pixf : pixel_formats;
prim : primitives_renderer;
rgba : aggclr;
rb : base_renderer;
ras : outline_rasterizer;
i ,r ,g ,b ,a : int;
c : curve;
s : stroke_draft;
e : edge;
n1 ,
n2 : node;
begin
pixfmt_bgr24(pixf ,rbuf_window );
rb.Construct (@pixf );
prim.Construct(@rb );
ras.Construct (@prim );
i:=0;
while i < m_graph.get_num_edges do
begin
e :=m_graph.get_edge(i );
n1:=m_graph.get_node(e.node1 ,_width ,_height );
n2:=m_graph.get_node(e.node2 ,_width ,_height );
c.Construct(n1.x ,n1.y ,n2.x ,n2.y );
s.Construct(@c ,m_width._value );
r:=Random($7fff ) and $7F;
g:=Random($7fff ) and $7F;
b:=Random($7fff ) and $7F;
a:=255;
if m_translucent._status then
a:=80;
rgba.ConstrInt (r ,g ,b ,a );
prim.line_color_(@rgba );
ras.add_path (@s );
c.Destruct;
s.Destruct;
inc(i );
end;
end;
{ DRAW_DASHES_DRAFT }
procedure the_application.draw_dashes_draft;
var
pixf : pixel_formats;
prim : primitives_renderer;
rgba : aggclr;
rb : base_renderer;
ras : outline_rasterizer;
i ,r ,g ,b ,a : int;
c : curve;
s : dash_stroke_draft;
e : edge;
n1 ,
n2 : node;
begin
pixfmt_bgr24(pixf ,rbuf_window );
rb.Construct (@pixf );
prim.Construct(@rb );
ras.Construct (@prim );
i:=0;
while i < m_graph.get_num_edges do
begin
e :=m_graph.get_edge(i );
n1:=m_graph.get_node(e.node1 ,_width ,_height );
n2:=m_graph.get_node(e.node2 ,_width ,_height );
c.Construct(n1.x ,n1.y ,n2.x ,n2.y );
s.Construct(@c ,6.0 ,3.0 ,m_width._value );
r:=Random($7fff ) and $7F;
g:=Random($7fff ) and $7F;
b:=Random($7fff ) and $7F;
a:=255;
if m_translucent._status then
a:=80;
rgba.ConstrInt (r ,g ,b ,a );
prim.line_color_(@rgba );
ras.add_path (@s );
c.Destruct;
s.Destruct;
inc(i );
end;
end;
{ DRAW_LINES_FINE }
procedure the_application.draw_lines_fine;
var
i : int;
b : edge;
l : line;
s : stroke_fine;
n1 ,n2 : node;
begin
i:=0;
while i < m_graph.get_num_edges do
begin
b :=m_graph.get_edge(i );
n1:=m_graph.get_node(b.node1 ,_width ,_height );
n2:=m_graph.get_node(b.node2 ,_width ,_height );
l.Construct(n1.x ,n1.y ,n2.x ,n2.y );
s.Construct(@l ,m_width._value );
render_edge_fine(ras ,solid ,draft ,@s );
s.Destruct;
inc(i );
end;
end;
{ DRAW_CURVES_FINE }
procedure the_application.draw_curves_fine;
var
i : int;
b : edge;
c : curve;
s : stroke_fine;
n1 ,n2 : node;
begin
i:=0;
while i < m_graph.get_num_edges do
begin
b :=m_graph.get_edge(i );
n1:=m_graph.get_node(b.node1 ,_width ,_height );
n2:=m_graph.get_node(b.node2 ,_width ,_height );
c.Construct(n1.x ,n1.y ,n2.x ,n2.y );
s.Construct(@c ,m_width._value );
render_edge_fine(ras ,solid ,draft ,@s );
c.Destruct;
s.Destruct;
inc(i );
end;
end;
{ DRAW_DASHES_FINE }
procedure the_application.draw_dashes_fine;
var
i : int;
b : edge;
c : curve;
s : dash_stroke_fine;
n1 ,n2 : node;
begin
i:=0;
while i < m_graph.get_num_edges do
begin
b :=m_graph.get_edge(i );
n1:=m_graph.get_node(b.node1 ,_width ,_height );
n2:=m_graph.get_node(b.node2 ,_width ,_height );
c.Construct(n1.x ,n1.y ,n2.x ,n2.y );
s.Construct(@c ,6.0 ,3.0 ,m_width._value );
render_edge_fine(ras ,solid ,draft ,@s );
c.Destruct;
s.Destruct;
inc(i );
end;
end;
{ DRAW_POLYGONS }
procedure the_application.draw_polygons;
var
i : int;
b : edge;
c : curve;
n1 ,n2 : node;
gm_no : gamma_none;
gm_th : gamma_threshold;
begin
if m_type._cur_item = 4 then
begin
gm_th.Construct(0.5 );
ras.gamma (@gm_th );
end;
i:=0;
while i < m_graph.get_num_edges do
begin
b :=m_graph.get_edge(i );
n1:=m_graph.get_node(b.node1 ,_width ,_height );
n2:=m_graph.get_node(b.node2 ,_width ,_height );
c.Construct(n1.x ,n1.y ,n2.x ,n2.y );
render_edge_fine(ras ,solid ,draft ,@c );
c.Destruct;
inc(i );
end;
gm_no.Construct;
ras.gamma(@gm_no );
end;
{ DRAW_SCENE }
procedure the_application.draw_scene;
var
gm_no : gamma_none;
begin
gm_no.Construct;
ras.gamma(@gm_no );
RandSeed:=100;
if m_draw_nodes._status then
if m_draft._status then
draw_nodes_draft
else
draw_nodes_fine(ras );
if m_draw_edges._status then
if m_draft._status then
case m_type._cur_item of
0 : draw_lines_draft;
1 : draw_curves_draft;
2 : draw_dashes_draft;
end
else
case m_type._cur_item of
0 :
draw_lines_fine(ras ,solid ,draft );
1 :
draw_curves_fine(ras ,solid ,draft );
2 :
draw_dashes_fine(ras ,solid ,draft );
3 ,4 :
draw_polygons(ras ,solid ,draft );
end;
end;
{ ON_DRAW }
procedure the_application.on_draw;
var
pixf : pixel_formats;
rgba : aggclr;
ras : scanline_rasterizer;
rb : base_renderer;
solid : solid_renderer;
draft : draft_renderer;
begin
// Initialize structures
ras.Construct;
pixfmt_bgr24(pixf ,rbuf_window );
rb.Construct (@pixf );
solid.Construct(@rb );
draft.Construct(@rb );
rgba.ConstrDbl(1 ,1 ,1 );
rb.clear (@rgba );
// Render
draw_scene(@ras ,@solid ,@draft );
// Render the controls
ras.filling_rule(fill_non_zero );
render_ctrl(@ras ,@m_sl ,@solid ,@m_type );
render_ctrl(@ras ,@m_sl ,@solid ,@m_width );
render_ctrl(@ras ,@m_sl ,@solid ,@m_benchmark );
render_ctrl(@ras ,@m_sl ,@solid ,@m_draw_nodes );
render_ctrl(@ras ,@m_sl ,@solid ,@m_draw_edges );
render_ctrl(@ras ,@m_sl ,@solid ,@m_draft );
render_ctrl(@ras ,@m_sl ,@solid ,@m_translucent );
// Free AGG resources
ras.Destruct;
end;
{ ON_CTRL_CHANGE }
procedure the_application.on_ctrl_change;
var
pixf : pixel_formats;
i : int;
fd : text;
ras : scanline_rasterizer;
rb : base_renderer;
solid : solid_renderer;
draft : draft_renderer;
buf : array[0..255 ] of char;
times : array[0..4 ] of double;
begin
if m_benchmark._status then
begin
on_draw;
update_window;
ras.Construct;
pixfmt_bgr24(pixf ,rbuf_window );
rb.Construct (@pixf );
solid.Construct(@rb );
draft.Construct(@rb );
if m_draft._status then
begin
start_timer;
for i:=0 to 9 do
draw_scene(@ras ,@solid ,@draft );
sprintf(@buf[0 ] ,'%3.3f milliseconds' ,elapsed_time );
end
else
begin
m_draw:=0;
while m_draw < 4 do
begin
start_timer;
for i:=0 to 9 do
draw_scene(@ras ,@solid ,@draft );
times[m_draw ]:=elapsed_time;
inc(m_draw );
end;
m_draw:=3;
times[4 ]:=times[3 ];
times[3 ]:=times[3 ] - times[2 ];
times[2 ]:=times[2 ] - times[1 ];
times[1 ]:=times[1 ] - times[0 ];
AssignFile(fd ,'benchmark' );
rewrite (fd );
sprintf(@buf[0 ] ,'%10.3f ' ,times[0 ] );
sprintf(@buf[StrLen(@buf ) ] ,'%10.3f ' ,times[1 ] );
sprintf(@buf[StrLen(@buf ) ] ,'%10.3f ' ,times[2 ] );
sprintf(@buf[StrLen(@buf ) ] ,'%10.3f ' ,times[3 ] );
sprintf(@buf[StrLen(@buf ) ] ,'%10.3f' ,times[4 ] );
writeln(fd ,PChar(@buf[0 ] ) );
close (fd );
sprintf(@buf[0 ] ,' pipeline add_path sort render total'#13'%10.3f ' ,times[0 ] );
sprintf(@buf[StrLen(@buf ) ] ,'%10.3f ' ,times[1 ] );
sprintf(@buf[StrLen(@buf ) ] ,'%10.3f ' ,times[2 ] );
sprintf(@buf[StrLen(@buf ) ] ,'%10.3f ' ,times[3 ] );
sprintf(@buf[StrLen(@buf ) ] ,'%10.3f' ,times[4 ] );
end;
message_(@buf[0 ] );
m_benchmark.status_(false );
force_redraw;
ras.Destruct;
end;
end;
{ ON_KEY }
procedure the_application.on_key;
begin
if key = key_f1 then
message_(
'Yet another example of the "general" kind. It was used mostly to compare '#13 +
'the performance of different steps of rendering in order to see the weaknesses. '#13 +
'The WIn GDI+ analog of it looks worse and works slower. Try "GDI_graph_test.zip"'#13 +
'(from www.antigrain.com/demo) and compare it with the AGG one. '#13 +
'The most disappointing thing in GDI+ is that it cannot draw Bezier curves correctly. '#13#13 +
'How to play with:'#13#13 +
'Run the GDI+ example, choose menu Image/Bezier curves, expand the window to '#13 +
'about 1000x1000 pixels, and then gradually change the size of the window. You will '#13 +
'see that some curves miss the destination points (the centers of the node circles).' +
#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. Line Join (F1-Help)' );
if app.init(600 + 100 ,500 + 30 ,window_resize ) then
app.run;
app.Destruct;
END.