// // 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 trans_curve1_ft ; {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 agg_basics , agg_platform_support , agg_ctrl , agg_cbox_ctrl , agg_slider_ctrl , agg_rasterizer_scanline_aa , agg_scanline , agg_scanline_p , agg_rendering_buffer , agg_renderer_base , agg_renderer_scanline , agg_render_scanlines , agg_conv_curve , agg_conv_transform , agg_conv_bspline , agg_conv_segmentator , agg_conv_stroke , agg_font_freetype , agg_font_cache_manager , agg_trans_single_path , interactive_polygon_ {$I pixel_formats.inc } {$I agg_mode.inc } const flip_y = true; text_ : PChar = 'Anti-Grain Geometry is designed as a set of loosely coupled ' + 'algorithms and class templates united with a common idea, ' + 'so that all the components can be easily combined. Also, ' + 'the template based design allows you to replace any part of ' + 'the library without the necessity to modify a single byte in ' + 'the existing code. '; type the_application = object(platform_support ) m_feng : font_engine_freetype_int16; m_fman : font_cache_manager; m_poly : interactive_polygon; m_num_points : slider_ctrl; m_close , m_preserve_x_scale , m_fixed_len , m_animate : cbox_ctrl; m_dx , m_dy : array[0..5 ] of double; m_prev_animate : boolean; constructor Construct(format_ : pix_format_e; flip_y_ : boolean ); destructor Destruct; procedure on_init; virtual; 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; procedure move_point(x ,y ,dx ,dy : double_ptr ); procedure on_idle; virtual; end; { CONSTRUCT } constructor the_application.Construct; begin inherited Construct(format_ ,flip_y_ ); m_feng.Construct; m_fman.Construct(@m_feng ); m_poly.Construct(6 ,5.0 ); m_num_points.Construct (5.0 ,5.0 ,340.0 ,12.0 ,not flip_y_ ); m_close.Construct (350 ,5.0 ,'Close' ,not flip_y_ ); m_preserve_x_scale.Construct(460 ,5.0 ,'Preserve X scale' ,not flip_y_ ); m_fixed_len.Construct (350 ,25.0 ,'Fixed Length' ,not flip_y_ ); m_animate.Construct (460 ,25.0 ,'Animate' ,not flip_y_ ); m_prev_animate:=false; add_ctrl(@m_close ); add_ctrl(@m_preserve_x_scale ); add_ctrl(@m_fixed_len ); add_ctrl(@m_animate ); m_preserve_x_scale.status_(true ); m_fixed_len.status_ (true ); m_num_points.range_(10.0 ,400.0 ); m_num_points.value_(200.0 ); m_num_points.label_('Number of intermediate Points = %.3f' ); add_ctrl(@m_num_points ); end; { DESTRUCT } destructor the_application.Destruct; begin inherited Destruct; m_poly.Destruct; m_num_points.Destruct; m_close.Destruct; m_preserve_x_scale.Destruct; m_fixed_len.Destruct; m_animate.Destruct; m_feng.Destruct; m_fman.Destruct; end; { ON_INIT } procedure the_application.on_init; begin m_poly.xn_ptr(0 )^:=50; m_poly.yn_ptr(0 )^:=50; m_poly.xn_ptr(1 )^:=150 + 20; m_poly.yn_ptr(1 )^:=150 - 20; m_poly.xn_ptr(2 )^:=250 - 20; m_poly.yn_ptr(2 )^:=250 + 20; m_poly.xn_ptr(3 )^:=350 + 20; m_poly.yn_ptr(3 )^:=350 - 20; m_poly.xn_ptr(4 )^:=450 - 20; m_poly.yn_ptr(4 )^:=450 + 20; m_poly.xn_ptr(5 )^:=550; m_poly.yn_ptr(5 )^:=550; end; { ON_DRAW } procedure the_application.on_draw; var pixf : pixel_formats; rgba : aggclr; rb : renderer_base; r : renderer_scanline_aa_solid; sl : scanline_p8; ras : rasterizer_scanline_aa; path : simple_polygon_vertex_source; bspline : conv_bspline; tcurve : trans_single_path; fcurves : conv_curve; fsegm : conv_segmentator; ftrans : conv_transform; x ,y : double; p : int8u_ptr; glyph : glyph_cache_ptr; stroke : conv_stroke; begin // Initialize structures pixfmt(pixf ,rbuf_window ); rb.Construct(@pixf ); r.Construct (@rb ); rgba.ConstrDbl(1 ,1 ,1 ); rb.clear (@rgba ); sl.Construct; ras.Construct; m_poly.close_(m_close._status ); // Render the text path.Construct (m_poly.polygon ,m_poly.num_points ,false ,m_close._status ); bspline.Construct(@path ); bspline.interpolation_step_(1.0 / m_num_points._value ); tcurve.Construct; tcurve.add_path (@bspline ); tcurve.preserve_x_scale_(m_preserve_x_scale._status ); if m_fixed_len._status then tcurve.base_length_(1120 ); fcurves.Construct(m_fman.path_adaptor ); fsegm.Construct (@fcurves ); ftrans.Construct (@fsegm ,@tcurve ); fsegm.approximation_scale_ (3.0 ); fcurves.approximation_scale_(2.0 ); if m_feng.load_font('timesi.ttf' ,0 ,glyph_ren_outline ) then begin x:=0.0; y:=3.0; p:=@text_[0 ]; m_feng.hinting_(false ); m_feng.height_ (40.0 ); while p^ <> 0 do begin glyph:=m_fman.glyph(p^ ); if glyph <> NIL then begin if x > tcurve.total_length then break; m_fman.add_kerning (@x ,@y ); m_fman.init_embedded_adaptors(glyph ,x ,y ); if glyph.data_type = glyph_data_outline then begin ras.reset; ras.add_path(@ftrans ); rgba.ConstrInt(0 ,0 ,0 ); r.color_ (@rgba ); render_scanlines(@ras ,@sl ,@r ); end; // increment pen position x:=x + glyph.advance_x; y:=y + glyph.advance_y; end; inc(ptrcomp(p ) ,sizeof(int8u ) ); end; end else message_( 'Please copy file timesi.ttf to the current directory'#13 + 'or download it from http://www.antigrain.com/timesi.zip' ); // Render the path curve stroke.Construct(@bspline ); stroke.width_ (2.0 ); rgba.ConstrInt(170 ,50 ,20 ,100 ); r.color_ (@rgba ); ras.add_path (@stroke ); render_scanlines(@ras ,@sl ,@r ); // Render the "poly" tool rgba.ConstrDbl(0 ,0.3 ,0.5 ,0.3 ); r.color_ (@rgba ); ras.add_path (@m_poly ); render_scanlines(@ras ,@sl ,@r ); // Render the controls render_ctrl(@ras ,@sl ,@r ,@m_close ); render_ctrl(@ras ,@sl ,@r ,@m_preserve_x_scale ); render_ctrl(@ras ,@sl ,@r ,@m_fixed_len ); render_ctrl(@ras ,@sl ,@r ,@m_animate ); render_ctrl(@ras ,@sl ,@r ,@m_num_points ); // Free AGG resources sl.Destruct; ras.Destruct; bspline.Destruct; tcurve.Destruct; fcurves.Destruct; fsegm.Destruct; stroke.Destruct; end; { ON_MOUSE_MOVE } procedure the_application.on_mouse_move; begin if flags and mouse_left <> 0 then if m_poly.on_mouse_move(x ,y ) then force_redraw; if flags and mouse_left = 0 then on_mouse_button_up(x ,y ,flags ); end; { ON_MOUSE_BUTTON_DOWN } procedure the_application.on_mouse_button_down; begin if flags and mouse_left <> 0 then if m_poly.on_mouse_button_down(x ,y ) then force_redraw; end; { ON_MOUSE_BUTTON_UP } procedure the_application.on_mouse_button_up; begin if m_poly.on_mouse_button_up(x ,y ) then force_redraw; end; { ON_KEY } procedure the_application.on_key; begin if key = key_f1 then message_( 'This is a "kinda-cool-stuff" demo that performs non-linear transformations and '#13 + 'draws vector text along a curve. Note that it''s not just calculating of the glyph '#13 + 'angles and positions, they are transformed as if they were elastic. The curve is '#13 + 'calculated as a bicubic spline. The option "Preserve X scale" makes the converter '#13 + 'distribute all the points uniformly along the curve. If it''s unchechked, the scale '#13 + 'will be proportional to the distance between the control points.' + #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; begin if m_animate._status <> m_prev_animate then begin if m_animate._status then begin on_init; for i:=0 to 5 do begin m_dx[i ]:=((Random($7fff ) mod 1000 ) - 500 ) * 0.01; m_dy[i ]:=((Random($7fff ) mod 1000 ) - 500 ) * 0.01; end; wait_mode_(false ); end else wait_mode_(true ); m_prev_animate:=m_animate._status; end; end; { MOVE_POINT } procedure the_application.move_point; begin if x^ < 0.0 then begin x^ :=0.0; dx^:=-dx^; end; if x^ > _width then begin x^ :=_width; dx^:=-dx^; end; if y^ < 0.0 then begin y^ :=0.0; dy^:=-dy^; end; if y^ > _height then begin y^ :=_height; dy^:=-dy^; end; x^:=x^ + dx^; y^:=y^ + dy^; end; { ON_IDLE } procedure the_application.on_idle; var i : int; begin for i:=0 to 5 do move_point(m_poly.xn_ptr(i ) ,m_poly.yn_ptr(i ) ,@m_dx[i ] ,@m_dy[i ] ); force_redraw; end; VAR app : the_application; BEGIN app.Construct(pix_format ,flip_y ); app.caption_ ('AGG Example. Non-linear "Along-A-Curve" Transformer - FreeType (F1-Help)' ); if app.init(600 ,600 ,window_resize ) then app.run; app.Destruct; END.