1// 2// AggPas 2.4 RM3 Demo application 3// Note: Press F1 key on run to see more info about this demo 4// 5// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap 6// 7program 8 trans_curve2_ft ; 9 10{DEFINE AGG_GRAY8 } 11{$DEFINE AGG_BGR24 } 12{DEFINE AGG_RGB24 } 13{DEFINE AGG_BGRA32 } 14{DEFINE AGG_RGBA32 } 15{DEFINE AGG_ARGB32 } 16{DEFINE AGG_ABGR32 } 17{DEFINE AGG_RGB565 } 18{DEFINE AGG_RGB555 } 19 20uses 21 agg_basics , 22 agg_platform_support , 23 24 agg_ctrl , 25 agg_cbox_ctrl , 26 agg_slider_ctrl , 27 28 agg_rasterizer_scanline_aa , 29 agg_scanline , 30 agg_scanline_p , 31 32 agg_rendering_buffer , 33 agg_renderer_base , 34 agg_renderer_scanline , 35 agg_render_scanlines , 36 37 agg_math , 38 agg_conv_curve , 39 agg_conv_transform , 40 agg_trans_double_path , 41 agg_conv_bspline , 42 agg_conv_segmentator , 43 agg_conv_stroke , 44 agg_font_freetype , 45 agg_font_cache_manager , 46 interactive_polygon_ 47 48{$I pixel_formats.inc } 49{$I agg_mode.inc } 50 51const 52 flip_y = true; 53 54 text_ : PChar = 55 'Anti-Grain Geometry is designed as a set of loosely coupled ' + 56 'algorithms and class templates united with a common idea, ' + 57 'so that all the components can be easily combined. Also, ' + 58 'the template based design allows you to replace any part of ' + 59 'the library without the necessity to modify a single byte in ' + 60 'the existing code. '; 61 62type 63 the_application = object(platform_support ) 64 m_feng : font_engine_freetype_int16; 65 m_fman : font_cache_manager; 66 m_poly1 , 67 m_poly2 : interactive_polygon; 68 69 m_num_points : slider_ctrl; 70 m_fixed_len , 71 m_preserve_x_scale , 72 m_animate : cbox_ctrl; 73 74 m_dx1 , 75 m_dy1 , 76 m_dx2 , 77 m_dy2 : array[0..5 ] of double; 78 79 m_prev_animate : boolean; 80 81 constructor Construct(format_ : pix_format_e; flip_y_ : boolean ); 82 destructor Destruct; 83 84 procedure on_init; virtual; 85 procedure on_draw; virtual; 86 87 procedure on_mouse_move (x ,y : int; flags : unsigned ); virtual; 88 procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual; 89 procedure on_mouse_button_up (x ,y : int; flags : unsigned ); virtual; 90 91 procedure on_key(x ,y : int; key ,flags : unsigned ); virtual; 92 procedure on_ctrl_change; virtual; 93 94 procedure move_point (x ,y ,dx ,dy : double_ptr ); 95 procedure normalize_point(i : unsigned ); 96 97 procedure on_idle; virtual; 98 99 end; 100 101{ CONSTRUCT } 102constructor the_application.Construct; 103begin 104 inherited Construct(format_ ,flip_y_ ); 105 106 m_feng.Construct; 107 m_fman.Construct (@m_feng ); 108 m_poly1.Construct(6 ,5.0 ); 109 m_poly2.Construct(6 ,5.0 ); 110 111 m_num_points.Construct (5.0 ,5.0 ,340.0 ,12.0 ,not flip_y_ ); 112 m_fixed_len.Construct (350 ,5.0 ,'Fixed Length' ,not flip_y_ ); 113 m_preserve_x_scale.Construct(465 ,5.0 ,'Preserve X scale' ,not flip_y_ ); 114 m_animate.Construct (350 ,25.0 ,'Animate' ,not flip_y_ ); 115 116 m_prev_animate:=false; 117 118 add_ctrl(@m_fixed_len ); 119 add_ctrl(@m_preserve_x_scale ); 120 add_ctrl(@m_animate ); 121 122 m_fixed_len.status_ (true ); 123 m_preserve_x_scale.status_(true ); 124 125 m_num_points.range_(10.0 ,400.0 ); 126 m_num_points.value_(200.0 ); 127 m_num_points.label_('Number of intermediate Points = %.3f' ); 128 129 add_ctrl(@m_num_points ); 130 131 m_poly1.close_(false ); 132 m_poly2.close_(false ); 133 134end; 135 136{ DESTRUCT } 137destructor the_application.Destruct; 138begin 139 inherited Destruct; 140 141 m_num_points.Destruct; 142 m_fixed_len.Destruct; 143 m_preserve_x_scale.Destruct; 144 m_animate.Destruct; 145 146 m_poly1.Destruct; 147 m_poly2.Destruct; 148 149 m_feng.Destruct; 150 m_fman.Destruct; 151 152end; 153 154{ ON_INIT } 155procedure the_application.on_init; 156begin 157 m_poly1.xn_ptr(0 )^:= 10 + 50; 158 m_poly1.yn_ptr(0 )^:=-10 + 50; 159 m_poly1.xn_ptr(1 )^:= 10 + 150 + 20; 160 m_poly1.yn_ptr(1 )^:=-10 + 150 - 20; 161 m_poly1.xn_ptr(2 )^:= 10 + 250 - 20; 162 m_poly1.yn_ptr(2 )^:=-10 + 250 + 20; 163 m_poly1.xn_ptr(3 )^:= 10 + 350 + 20; 164 m_poly1.yn_ptr(3 )^:=-10 + 350 - 20; 165 m_poly1.xn_ptr(4 )^:= 10 + 450 - 20; 166 m_poly1.yn_ptr(4 )^:=-10 + 450 + 20; 167 m_poly1.xn_ptr(5 )^:= 10 + 550; 168 m_poly1.yn_ptr(5 )^:=-10 + 550; 169 170 m_poly2.xn_ptr(0 )^:=-10 + 50; 171 m_poly2.yn_ptr(0 )^:= 10 + 50; 172 m_poly2.xn_ptr(1 )^:=-10 + 150 + 20; 173 m_poly2.yn_ptr(1 )^:= 10 + 150 - 20; 174 m_poly2.xn_ptr(2 )^:=-10 + 250 - 20; 175 m_poly2.yn_ptr(2 )^:= 10 + 250 + 20; 176 m_poly2.xn_ptr(3 )^:=-10 + 350 + 20; 177 m_poly2.yn_ptr(3 )^:= 10 + 350 - 20; 178 m_poly2.xn_ptr(4 )^:=-10 + 450 - 20; 179 m_poly2.yn_ptr(4 )^:= 10 + 450 + 20; 180 m_poly2.xn_ptr(5 )^:=-10 + 550; 181 m_poly2.yn_ptr(5 )^:= 10 + 550; 182 183end; 184 185{ ON_DRAW } 186procedure the_application.on_draw; 187var 188 pixf : pixel_formats; 189 rgba : aggclr; 190 191 rb : renderer_base; 192 r : renderer_scanline_aa_solid; 193 sl : scanline_p8; 194 195 ras : rasterizer_scanline_aa; 196 197 path1 , 198 path2 : simple_polygon_vertex_source; 199 200 bspline1 , 201 bspline2 : conv_bspline; 202 203 tcurve : trans_double_path; 204 fcurves : conv_curve; 205 fsegm : conv_segmentator; 206 ftrans : conv_transform; 207 208 x ,y : double; 209 210 p : int8u_ptr; 211 212 glyph : glyph_cache_ptr; 213 214 stroke1 , 215 stroke2 : conv_stroke; 216 217begin 218// Initialize structures 219 pixfmt(pixf ,rbuf_window ); 220 221 rb.Construct(@pixf ); 222 r.Construct (@rb ); 223 224 rgba.ConstrDbl(1 ,1 ,1 ); 225 rb.clear (@rgba ); 226 227 sl.Construct; 228 ras.Construct; 229 230// Render the text 231 path1.Construct(m_poly1.polygon ,m_poly1.num_points ,false ,false ); 232 path2.Construct(m_poly2.polygon ,m_poly2.num_points ,false ,false ); 233 234 bspline1.Construct(@path1 ); 235 bspline2.Construct(@path2 ); 236 237 bspline1.interpolation_step_(1.0 / m_num_points._value ); 238 bspline2.interpolation_step_(1.0 / m_num_points._value ); 239 240 tcurve.Construct; 241 fcurves.Construct(m_fman.path_adaptor ); 242 fsegm.Construct (@fcurves); 243 ftrans.Construct (@fsegm ,@tcurve ); 244 245 tcurve.preserve_x_scale_(m_preserve_x_scale._status ); 246 247 if m_fixed_len._status then 248 tcurve.base_length_(1140.0 ); 249 250 tcurve.base_height_(30.0 ); 251 tcurve.add_paths (@bspline1 ,@bspline2 ); 252 253 fsegm.approximation_scale_ (3.0 ); 254 fcurves.approximation_scale_(5.0 ); 255 256 if m_feng.load_font('timesi.ttf' ,0 ,glyph_ren_outline ) then 257 begin 258 x:=0.0; 259 y:=3.0; 260 p:=@text_[0 ]; 261 262 m_feng.hinting_(false ); 263 m_feng.height_ (40.0 ); 264 265 while p^ <> 0 do 266 begin 267 glyph:=m_fman.glyph(p^ ); 268 269 if glyph <> NIL then 270 begin 271 if x > tcurve.total_length1 then 272 break; 273 274 m_fman.add_kerning (@x ,@y ); 275 m_fman.init_embedded_adaptors(glyph ,x ,y ); 276 277 if glyph.data_type = glyph_data_outline then 278 begin 279 ras.reset; 280 ras.add_path(@ftrans ); 281 282 rgba.ConstrInt(0 ,0 ,0 ); 283 r.color_ (@rgba ); 284 285 render_scanlines(@ras ,@sl ,@r ); 286 287 end; 288 289 // increment pen position 290 x:=x + glyph.advance_x; 291 y:=y + glyph.advance_y; 292 293 end; 294 295 inc(ptrcomp(p ) ,sizeof(int8u ) ); 296 297 end; 298 299 end 300 else 301 message_( 302 'Please copy file timesi.ttf to the current directory'#13 + 303 'or download it from http://www.antigrain.com/timesi.zip' ); 304 305// Render the path curve 306 stroke1.Construct(@bspline1 ); 307 stroke2.Construct(@bspline2 ); 308 309 stroke1.width_(2.0 ); 310 stroke2.width_(2.0 ); 311 312 rgba.ConstrInt(170 ,50 ,20 ,100 ); 313 r.color_ (@rgba ); 314 315 ras.add_path (@stroke1 ); 316 render_scanlines(@ras ,@sl ,@r ); 317 318 ras.add_path (@stroke2); 319 render_scanlines(@ras ,@sl ,@r ); 320 321// Render the "poly" tool 322 rgba.ConstrDbl(0 ,0.3 ,0.5 ,0.2 ); 323 r.color_ (@rgba ); 324 325 ras.add_path (@m_poly1 ); 326 render_scanlines(@ras ,@sl ,@r ); 327 328 ras.add_path (@m_poly2 ); 329 render_scanlines(@ras ,@sl ,@r ); 330 331// Render the controls 332 render_ctrl(@ras ,@sl ,@r ,@m_fixed_len ); 333 render_ctrl(@ras ,@sl ,@r ,@m_preserve_x_scale ); 334 render_ctrl(@ras ,@sl ,@r ,@m_animate ); 335 render_ctrl(@ras ,@sl ,@r ,@m_num_points ); 336 337// Free AGG resources 338 sl.Destruct; 339 ras.Destruct; 340 341 bspline1.Destruct; 342 bspline2.Destruct; 343 tcurve.Destruct; 344 fcurves.Destruct; 345 fsegm.Destruct; 346 347 stroke1.Destruct; 348 stroke2.Destruct; 349 350end; 351 352{ ON_MOUSE_MOVE } 353procedure the_application.on_mouse_move; 354begin 355 if flags and mouse_left <> 0 then 356 begin 357 if m_poly1.on_mouse_move(x ,y ) then 358 force_redraw; 359 360 if m_poly2.on_mouse_move(x ,y ) then 361 force_redraw; 362 363 end; 364 365 if flags and mouse_left = 0 then 366 on_mouse_button_up(x ,y ,flags ); 367 368end; 369 370{ ON_MOUSE_BUTTON_DOWN } 371procedure the_application.on_mouse_button_down; 372begin 373 if flags and mouse_left <> 0 then 374 begin 375 if m_poly1.on_mouse_button_down(x ,y ) then 376 force_redraw; 377 378 if m_poly2.on_mouse_button_down(x ,y ) then 379 force_redraw; 380 381 end; 382 383end; 384 385{ ON_MOUSE_BUTTON_UP } 386procedure the_application.on_mouse_button_up; 387begin 388 if m_poly1.on_mouse_button_up(x ,y ) then 389 force_redraw; 390 391 if m_poly2.on_mouse_button_up(x ,y ) then 392 force_redraw; 393 394end; 395 396{ ON_KEY } 397procedure the_application.on_key; 398begin 399 if key = key_f1 then 400 message_( 401 'Similar to the "trans_curve1" demo, but here the transformer operates with two '#13 + 402 'arbitrary curves. It requires more calculations, but gives you more freedom. '#13 + 403 'In other words you will see :-).' + 404 #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' ); 405 406end; 407 408{ ON_CTRL_CHANGE } 409procedure the_application.on_ctrl_change; 410var 411 i : int; 412 413begin 414 if m_animate._status <> m_prev_animate then 415 begin 416 if m_animate._status then 417 begin 418 on_init; 419 420 for i:=0 to 5 do 421 begin 422 m_dx1[i ]:=((Random($7fff ) mod 1000 ) - 500 ) * 0.01; 423 m_dy1[i ]:=((Random($7fff ) mod 1000 ) - 500 ) * 0.01; 424 m_dx2[i ]:=((Random($7fff ) mod 1000 ) - 500 ) * 0.01; 425 m_dy2[i ]:=((Random($7fff ) mod 1000 ) - 500 ) * 0.01; 426 427 end; 428 429 wait_mode_(false ); 430 431 end 432 else 433 wait_mode_(true ); 434 435 m_prev_animate:=m_animate._status; 436 437 end; 438 439end; 440 441{ MOVE_POINT } 442procedure the_application.move_point; 443begin 444 if x^ < 0.0 then 445 begin 446 x^ :=0.0; 447 dx^:=-dx^; 448 449 end; 450 451 if x^ > _width then 452 begin 453 x^ :=_width; 454 dx^:=-dx^; 455 456 end; 457 458 if y^ < 0.0 then 459 begin 460 y^ :=0.0; 461 dy^:=-dy^; 462 463 end; 464 465 if y^ > _height then 466 begin 467 y^ :=_height; 468 dy^:=-dy^; 469 470 end; 471 472 x^:=x^ + dx^; 473 y^:=y^ + dy^; 474 475end; 476 477{ NORMALIZE_POINT } 478procedure the_application.normalize_point; 479var 480 d : double; 481 482begin 483 d:= 484 calc_distance( 485 m_poly1.xn_ptr(i )^ ,m_poly1.yn_ptr(i )^ , 486 m_poly2.xn_ptr(i )^ ,m_poly2.yn_ptr(i )^ ); 487 488// 28.8 is 20 * sqrt(2) 489 if d > 28.28 then 490 begin 491 m_poly2.xn_ptr(i )^:= 492 m_poly1.xn_ptr(i )^ + 493 (m_poly2.xn_ptr(i )^ - 494 m_poly1.xn_ptr(i )^ ) * 28.28 / d; 495 496 m_poly2.yn_ptr(i )^:= 497 m_poly1.yn_ptr(i )^ + 498 (m_poly2.yn_ptr(i )^ - 499 m_poly1.yn_ptr(i )^ ) * 28.28 / d; 500 501 end; 502 503end; 504 505{ ON_IDLE } 506procedure the_application.on_idle; 507var 508 i : int; 509 510begin 511 for i:=0 to 5 do 512 begin 513 move_point(m_poly1.xn_ptr(i ) ,m_poly1.yn_ptr(i ) ,@m_dx1[i ] ,@m_dy1[i ] ); 514 move_point(m_poly2.xn_ptr(i ) ,m_poly2.yn_ptr(i ) ,@m_dx2[i ] ,@m_dy2[i ] ); 515 516 normalize_point(i); 517 518 end; 519 520 force_redraw; 521 522end; 523 524VAR 525 app : the_application; 526 527BEGIN 528 app.Construct(pix_format ,flip_y ); 529 app.caption_ ('AGG Example. Non-linear "Along-A-Curve" Transformer - FreeType (F1-Help)' ); 530 531 if app.init(600 ,600 ,window_resize ) then 532 app.run; 533 534 app.Destruct; 535 536END. 537