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

489 lines
15 KiB
ObjectPascal
Raw Blame History

{mac_copy:1.bmp}
{mac_copy:2.bmp}
{mac_copy:3.bmp}
{mac_copy:4.bmp}
{mac_copy:5.bmp}
{mac_copy:6.bmp}
{mac_copy:7.bmp}
{mac_copy:8.bmp}
{mac_copy:9.bmp}
//
// 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
line_patterns ;
uses
SysUtils ,
agg_basics ,
agg_platform_support ,
agg_color ,
agg_pixfmt ,
agg_pixfmt_rgb ,
agg_ctrl ,
agg_slider_ctrl ,
agg_bezier_ctrl ,
agg_rendering_buffer ,
agg_renderer_base ,
agg_renderer_scanline ,
agg_renderer_outline_aa ,
agg_renderer_outline_image ,
agg_rasterizer_scanline_aa ,
agg_rasterizer_outline_aa ,
agg_scanline ,
agg_scanline_p ,
agg_render_scanlines ,
agg_pattern_filters_rgba ,
agg_conv_stroke ,
agg_conv_transform ,
agg_conv_clip_polyline ,
agg_vertex_source ;
{$I agg_mode.inc }
{$I- }
const
flip_y = true;
brightness_to_alpha : array[0..256 * 3 - 1 ] of int8u = (
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 254, 254, 254, 254, 254,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 254, 253, 253,
253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 252,
252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 251, 251, 251, 251, 251,
251, 251, 251, 251, 250, 250, 250, 250, 250, 250, 250, 250, 249, 249, 249, 249,
249, 249, 249, 248, 248, 248, 248, 248, 248, 248, 247, 247, 247, 247, 247, 246,
246, 246, 246, 246, 246, 245, 245, 245, 245, 245, 244, 244, 244, 244, 243, 243,
243, 243, 243, 242, 242, 242, 242, 241, 241, 241, 241, 240, 240, 240, 239, 239,
239, 239, 238, 238, 238, 238, 237, 237, 237, 236, 236, 236, 235, 235, 235, 234,
234, 234, 233, 233, 233, 232, 232, 232, 231, 231, 230, 230, 230, 229, 229, 229,
228, 228, 227, 227, 227, 226, 226, 225, 225, 224, 224, 224, 223, 223, 222, 222,
221, 221, 220, 220, 219, 219, 219, 218, 218, 217, 217, 216, 216, 215, 214, 214,
213, 213, 212, 212, 211, 211, 210, 210, 209, 209, 208, 207, 207, 206, 206, 205,
204, 204, 203, 203, 202, 201, 201, 200, 200, 199, 198, 198, 197, 196, 196, 195,
194, 194, 193, 192, 192, 191, 190, 190, 189, 188, 188, 187, 186, 186, 185, 184,
183, 183, 182, 181, 180, 180, 179, 178, 177, 177, 176, 175, 174, 174, 173, 172,
171, 171, 170, 169, 168, 167, 166, 166, 165, 164, 163, 162, 162, 161, 160, 159,
158, 157, 156, 156, 155, 154, 153, 152, 151, 150, 149, 148, 148, 147, 146, 145,
144, 143, 142, 141, 140, 139, 138, 137, 136, 135, 134, 133, 132, 131, 130, 129,
128, 128, 127, 125, 124, 123, 122, 121, 120, 119, 118, 117, 116, 115, 114, 113,
112, 111, 110, 109, 108, 107, 106, 105, 104, 102, 101, 100, 99, 98, 97, 96,
95, 94, 93, 91, 90, 89, 88, 87, 86, 85, 84, 82, 81, 80, 79, 78,
77, 75, 74, 73, 72, 71, 70, 69, 67, 66, 65, 64, 63, 61, 60, 59,
58, 57, 56, 54, 53, 52, 51, 50, 48, 47, 46, 45, 44, 42, 41, 40,
39, 37, 36, 35, 34, 33, 31, 30, 29, 28, 27, 25, 24, 23, 22, 20,
19, 18, 17, 15, 14, 13, 12, 11, 9, 8, 7, 6, 4, 3, 2, 1 );
type
pattern_src_brightness_to_alpha_rgba8 = object(pixel_source )
m_rb : rendering_buffer_ptr;
m_pf : pixel_formats;
constructor Construct(rb : rendering_buffer_ptr );
function _width : unsigned; virtual;
function _height : unsigned; virtual;
function pixel(x ,y : int ) : rgba8; virtual;
end;
the_application = object(platform_support )
m_ctrl_color : aggclr;
m_curve1 ,
m_curve2 ,
m_curve3 ,
m_curve4 ,
m_curve5 ,
m_curve6 ,
m_curve7 ,
m_curve8 ,
m_curve9 : bezier_ctrl;
m_scale_x ,
m_start_x : slider_ctrl;
constructor Construct(format_ : pix_format_e; flip_y_ : boolean );
destructor Destruct;
procedure draw_curve(
patt : line_image_pattern_ptr;
ras : rasterizer_outline_aa_ptr;
ren : renderer_outline_image_ptr;
src : pixel_source_ptr;
vs : vertex_source_ptr );
procedure on_draw; virtual;
procedure on_key(x ,y : int; key ,flags : unsigned ); virtual;
procedure on_ctrl_change; virtual;
end;
{ CONSTRUCT }
constructor pattern_src_brightness_to_alpha_rgba8.Construct;
begin
m_rb:=rb;
pixfmt_bgr24(m_pf ,m_rb );
end;
{ _WIDTH }
function pattern_src_brightness_to_alpha_rgba8._width;
begin
result:=m_pf._width;
end;
{ _HEIGHT }
function pattern_src_brightness_to_alpha_rgba8._height;
begin
result:=m_pf._height;
end;
{ PIXEL }
function pattern_src_brightness_to_alpha_rgba8.pixel;
var
c : aggclr;
begin
c :=m_pf.pixel(@m_pf ,x ,y );
c.a:=brightness_to_alpha[c.r + c.g + c.b ];
result.r:=c.r;
result.g:=c.g;
result.b:=c.b;
result.a:=c.a;
end;
{ CONSTRUCT }
constructor the_application.Construct;
begin
inherited Construct(format_ ,flip_y_ );
m_ctrl_color.ConstrDbl(0 ,0.3 ,0.5 ,0.3 );
m_scale_x.Construct(5.0 ,5.0 ,240.0 ,12.0 ,not flip_y_ );
m_start_x.Construct(250.0 ,5.0 ,495.0 ,12.0 ,not flip_y_ );
m_curve1.Construct;
m_curve2.Construct;
m_curve3.Construct;
m_curve4.Construct;
m_curve5.Construct;
m_curve6.Construct;
m_curve7.Construct;
m_curve8.Construct;
m_curve9.Construct;
m_curve1.line_color_(@m_ctrl_color );
m_curve2.line_color_(@m_ctrl_color );
m_curve3.line_color_(@m_ctrl_color );
m_curve4.line_color_(@m_ctrl_color );
m_curve5.line_color_(@m_ctrl_color );
m_curve6.line_color_(@m_ctrl_color );
m_curve7.line_color_(@m_ctrl_color );
m_curve8.line_color_(@m_ctrl_color );
m_curve9.line_color_(@m_ctrl_color );
m_curve1.curve_(64 ,19 ,14 ,126 ,118 ,266 ,19 ,265 );
m_curve2.curve_(112 ,113 ,178 ,32 ,200 ,132 ,125 ,438 );
m_curve3.curve_(401 ,24 ,326 ,149 ,285 ,11 ,177 ,77 );
m_curve4.curve_(188 ,427 ,129 ,295 ,19 ,283 ,25 ,410 );
m_curve5.curve_(451 ,346 ,302 ,218 ,265 ,441 ,459 ,400 );
m_curve6.curve_(454 ,198 ,14 ,13 ,220 ,291 ,483 ,283 );
m_curve7.curve_(301 ,398 ,355 ,231 ,209 ,211 ,170 ,353 );
m_curve8.curve_(484 ,101 ,222 ,33 ,486 ,435 ,487 ,138 );
m_curve9.curve_(143 ,147 ,11 ,45 ,83 ,427 ,132 ,197 );
add_ctrl(@m_curve1 );
add_ctrl(@m_curve2 );
add_ctrl(@m_curve3 );
add_ctrl(@m_curve4 );
add_ctrl(@m_curve5 );
add_ctrl(@m_curve6 );
add_ctrl(@m_curve7 );
add_ctrl(@m_curve8 );
add_ctrl(@m_curve9 );
m_curve1.no_transform;
m_curve2.no_transform;
m_curve3.no_transform;
m_curve4.no_transform;
m_curve5.no_transform;
m_curve6.no_transform;
m_curve7.no_transform;
m_curve8.no_transform;
m_curve9.no_transform;
m_scale_x.label_('Scale X=%.2f' );
m_scale_x.range_(0.2 ,3.0 );
m_scale_x.value_(1.0 );
m_scale_x.no_transform;
add_ctrl(@m_scale_x );
m_start_x.label_('Start X=%.2f' );
m_start_x.range_(0.0 ,10.0 );
m_start_x.value_(0.0 );
m_start_x.no_transform;
add_ctrl(@m_start_x );
end;
{ DESTRUCT }
destructor the_application.Destruct;
begin
inherited Destruct;
m_scale_x.Destruct;
m_start_x.Destruct;
m_curve1.Destruct;
m_curve2.Destruct;
m_curve3.Destruct;
m_curve4.Destruct;
m_curve5.Destruct;
m_curve6.Destruct;
m_curve7.Destruct;
m_curve8.Destruct;
m_curve9.Destruct;
end;
{ DRAW_CURVE }
procedure the_application.draw_curve;
begin
patt.create (src );
ren.scale_x_(m_scale_x._value );
ren.start_x_(m_start_x._value );
ras.add_path(vs );
end;
{ ON_DRAW }
procedure the_application.on_draw;
var
pf : pixel_formats;
ren : renderer_scanline_aa_solid;
ras : rasterizer_scanline_aa;
sl : scanline_p8;
rgba : aggclr;
ren_base : renderer_base;
p1 ,p2 ,p3 ,p4 ,p5 ,p6 ,p7 ,p8 ,p9 : pattern_src_brightness_to_alpha_rgba8;
fltr : pattern_filter_bilinear_rgba{};
patt : line_image_pattern;
ren_img : renderer_outline_image;
ras_img : rasterizer_outline_aa;
begin
// Initialize structures
pixfmt_bgr24(pf ,rbuf_window );
ren_base.Construct(@pf );
ren.Construct (@ren_base );
rgba.ConstrDbl(1.0 ,1.0 ,0.95 );
ren_base.clear(@rgba );
ras.Construct;
sl.Construct;
// Pattern source. Must have an interface:
// width() const
// height() const
// pixel(int x, int y) const
// Any agg::renderer_base<> or derived
// is good for the use as a source.
p1.Construct(rbuf_img(0 ) );
p2.Construct(rbuf_img(1 ) );
p3.Construct(rbuf_img(2 ) );
p4.Construct(rbuf_img(3 ) );
p5.Construct(rbuf_img(4 ) );
p6.Construct(rbuf_img(5 ) );
p7.Construct(rbuf_img(6 ) );
p8.Construct(rbuf_img(7 ) );
p9.Construct(rbuf_img(8 ) );
fltr.Construct; // Filtering functor
// agg::line_image_pattern is the main container for the patterns. It creates
// a copy of the patterns extended according to the needs of the filter.
// agg::line_image_pattern can operate with arbitrary image width, but if the
// width of the pattern is power of 2, it's better to use the modified
// version agg::line_image_pattern_pow2 because it works about 15-25 percent
// faster than agg::line_image_pattern (because of using simple masking instead
// of expensive '%' operation).
//-- Create with specifying the source
// patt.Construct(@fltr ,@src );
//-- Create uninitialized and set the source
patt.Construct (@fltr );
ren_img.Construct(@ren_base ,@patt );
ras_img.Construct(@ren_img );
draw_curve(@patt ,@ras_img ,@ren_img ,@p1 ,m_curve1._curve );
draw_curve(@patt ,@ras_img ,@ren_img ,@p2 ,m_curve2._curve );
draw_curve(@patt ,@ras_img ,@ren_img ,@p3 ,m_curve3._curve );
draw_curve(@patt ,@ras_img ,@ren_img ,@p4 ,m_curve4._curve );
draw_curve(@patt ,@ras_img ,@ren_img ,@p5 ,m_curve5._curve );
draw_curve(@patt ,@ras_img ,@ren_img ,@p6 ,m_curve6._curve );
draw_curve(@patt ,@ras_img ,@ren_img ,@p7 ,m_curve7._curve );
draw_curve(@patt ,@ras_img ,@ren_img ,@p8 ,m_curve8._curve );
draw_curve(@patt ,@ras_img ,@ren_img ,@p9 ,m_curve9._curve );
// Render the controls
render_ctrl(@ras ,@sl ,@ren ,@m_curve1 );
render_ctrl(@ras ,@sl ,@ren ,@m_curve2 );
render_ctrl(@ras ,@sl ,@ren ,@m_curve3 );
render_ctrl(@ras ,@sl ,@ren ,@m_curve4 );
render_ctrl(@ras ,@sl ,@ren ,@m_curve5 );
render_ctrl(@ras ,@sl ,@ren ,@m_curve6 );
render_ctrl(@ras ,@sl ,@ren ,@m_curve7 );
render_ctrl(@ras ,@sl ,@ren ,@m_curve8 );
render_ctrl(@ras ,@sl ,@ren ,@m_curve9 );
render_ctrl(@ras ,@sl ,@ren ,@m_scale_x );
render_ctrl(@ras ,@sl ,@ren ,@m_start_x );
// Free AGG resources
ras.Destruct;
sl.Destruct;
patt.Destruct;
ras_img.Destruct;
end;
{ ON_KEY }
procedure the_application.on_key;
var
fd : text;
buf : array[0..255 ] of char;
begin
if key = byte(' ' ) then
begin
AssignFile(fd ,'coord' );
rewrite (fd );
sprintf(@buf[0 ] ,'%.0f, ' ,m_curve1._x1 );
sprintf(@buf[StrLen(@buf ) ] ,'%.0f, ' ,m_curve1._y1 );
sprintf(@buf[StrLen(@buf ) ] ,'%.0f, ' ,m_curve1._x2 );
sprintf(@buf[StrLen(@buf ) ] ,'%.0f, ' ,m_curve1._y2 );
sprintf(@buf[StrLen(@buf ) ] ,'%.0f, ' ,m_curve1._x3 );
sprintf(@buf[StrLen(@buf ) ] ,'%.0f, ' ,m_curve1._y3 );
sprintf(@buf[StrLen(@buf ) ] ,'%.0f, ' ,m_curve1._x4 );
sprintf(@buf[StrLen(@buf ) ] ,'%.0f' ,m_curve1._y4 );
write(fd ,PChar(@buf[0 ] ) );
close(fd );
end;
if key = key_f1 then
message_(
'The demo shows a very powerful mechanism of using arbitrary images as line patterns. '#13 +
'The main point of it is that the images are drawn along the path. It allows you to '#13 +
'draw very fancy looking lines quite easily and very useful in GIS/cartography applications. '#13 +
'There the bilinear filtering is used, but it''s also possible to add any other filtering '#13 +
'methods, or just use the nearest neighbour one for the sake of speed. '#13 +
'Actually, the algorithm uses 32bit images with alpha channel, but in this demo alpha is '#13 +
'simulated in such a way that wite is transparent, black is opaque. The intermediate colors '#13 +
'have intermediate opacity that is defined by the brightness_to_alpha array.'#13#13 +
'How to play with:'#13#13 +
'In the demo you can drag the control points of the curves and observe that the images '#13 +
'are transformed quite consistently and smoothly. You can also try to replace the image '#13 +
'files (1<>9) with your own. The BMP files must have 24bit colors (TrueColor), the PPM '#13 +
'ones must be of type "P6". Also, the heigh should not exceed 64 pixels, and the background '#13 +
'should be white or very close to white.'#13 +
'Press the spacebar to write down the "coord" file of the curve 1 (of 1.bmp).' +
#13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' );
end;
{ ON_CTRL_CHANGE }
procedure the_application.on_ctrl_change;
begin
end;
VAR
app : the_application;
buf : array [0..255 ] of char;
ext : string[10 ];
BEGIN
app.Construct(pix_format_bgr24 ,flip_y );
app.caption_ ('AGG Example. Drawing Lines with Image Patterns (F1-Help)' );
if not app.load_img(0 ,'1' ) or
not app.load_img(1 ,'2' ) or
not app.load_img(2 ,'3' ) or
not app.load_img(3 ,'4' ) or
not app.load_img(4 ,'5' ) or
not app.load_img(5 ,'6' ) or
not app.load_img(6 ,'7' ) or
not app.load_img(7 ,'8' ) or
not app.load_img(8 ,'9' ) then
begin
ext:=app._img_ext;
sprintf(@buf[0 ] ,'There must be files 1%s' ,ptrcomp(@ext[1 ] ) );
sprintf(
@buf[StrLen(@buf ) ] ,
'...9%s'#13 +
'Download and unzip:'#13 +
'http://www.antigrain.com/line_patterns.bmp.zip'#13 +
'or'#13 +
'http://www.antigrain.com/line_patterns.ppm.tar.gz'#13 ,
ptrcomp(@ext[1 ] ) );
app.message_(@buf[0 ] );
end
else
if app.init(500 ,450 ,window_resize ) then
app.run;
app.Destruct;
END.