1{target:win} 2// 3// AggPas 2.4 RM3 Demo application 4// Note: Press F1 key on run to see more info about this demo 5// 6// Paths: src;src\ctrl;src\svg;src\util;src\platform\win;expat-wrap 7// 8program 9 trans_curve2 ; 10 11{DEFINE AGG_GRAY8 } 12{$DEFINE AGG_BGR24 } 13{DEFINE AGG_RGB24 } 14{DEFINE AGG_BGRA32 } 15{DEFINE AGG_RGBA32 } 16{DEFINE AGG_ARGB32 } 17{DEFINE AGG_ABGR32 } 18{DEFINE AGG_RGB565 } 19{DEFINE AGG_RGB555 } 20 21uses 22 Windows , 23 24 agg_basics , 25 agg_platform_support , 26 27 agg_ctrl , 28 agg_cbox_ctrl , 29 agg_slider_ctrl , 30 31 agg_rasterizer_scanline_aa , 32 agg_scanline , 33 agg_scanline_p , 34 35 agg_rendering_buffer , 36 agg_renderer_base , 37 agg_renderer_scanline , 38 agg_render_scanlines , 39 40 agg_math , 41 agg_conv_curve , 42 agg_conv_transform , 43 agg_trans_double_path , 44 agg_conv_bspline , 45 agg_conv_segmentator , 46 agg_conv_stroke , 47 agg_font_win32_tt , 48 agg_font_cache_manager , 49 interactive_polygon_ 50 51{$I pixel_formats.inc } 52{$I agg_mode.inc } 53 54const 55 flip_y = true; 56 57 text_ : PChar = 58 'Anti-Grain Geometry is designed as a set of loosely coupled ' + 59 'algorithms and class templates united with a common idea, ' + 60 'so that all the components can be easily combined. Also, ' + 61 'the template based design allows you to replace any part of ' + 62 'the library without the necessity to modify a single byte in ' + 63 'the existing code. '; 64 65type 66 the_application = object(platform_support ) 67 m_feng : font_engine_win32_tt_int16; 68 m_fman : font_cache_manager; 69 m_poly1 , 70 m_poly2 : interactive_polygon; 71 72 m_num_points : slider_ctrl; 73 m_fixed_len , 74 m_preserve_x_scale , 75 m_animate : cbox_ctrl; 76 77 m_dx1 , 78 m_dy1 , 79 m_dx2 , 80 m_dy2 : array[0..5 ] of double; 81 82 m_prev_animate : boolean; 83 84 constructor Construct(dc : HDC; format_ : pix_format_e; flip_y_ : boolean ); 85 destructor Destruct; 86 87 procedure on_init; virtual; 88 procedure on_draw; virtual; 89 90 procedure on_mouse_move (x ,y : int; flags : unsigned ); virtual; 91 procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual; 92 procedure on_mouse_button_up (x ,y : int; flags : unsigned ); virtual; 93 94 procedure on_key(x ,y : int; key ,flags : unsigned ); virtual; 95 procedure on_ctrl_change; virtual; 96 97 procedure move_point (x ,y ,dx ,dy : double_ptr ); 98 procedure normalize_point(i : unsigned ); 99 100 procedure on_idle; virtual; 101 102 end; 103 104{ CONSTRUCT } 105constructor the_application.Construct; 106begin 107 inherited Construct(format_ ,flip_y_ ); 108 109 m_feng.Construct (dc ); 110 m_fman.Construct (@m_feng ); 111 m_poly1.Construct(6 ,5.0 ); 112 m_poly2.Construct(6 ,5.0 ); 113 114 m_num_points.Construct (5.0 ,5.0 ,340.0 ,12.0 ,not flip_y_ ); 115 m_fixed_len.Construct (350 ,5.0 ,'Fixed Length' ,not flip_y_ ); 116 m_preserve_x_scale.Construct(465 ,5.0 ,'Preserve X scale' ,not flip_y_ ); 117 m_animate.Construct (350 ,25.0 ,'Animate' ,not flip_y_ ); 118 119 m_prev_animate:=false; 120 121 add_ctrl(@m_fixed_len ); 122 add_ctrl(@m_preserve_x_scale ); 123 add_ctrl(@m_animate ); 124 125 m_fixed_len.status_ (true ); 126 m_preserve_x_scale.status_(true ); 127 128 m_num_points.range_(10.0 ,400.0 ); 129 m_num_points.value_(200.0 ); 130 m_num_points.label_('Number of intermediate Points = %.3f' ); 131 132 add_ctrl(@m_num_points ); 133 134 m_poly1.close_(false ); 135 m_poly2.close_(false ); 136 137end; 138 139{ DESTRUCT } 140destructor the_application.Destruct; 141begin 142 inherited Destruct; 143 144 m_num_points.Destruct; 145 m_fixed_len.Destruct; 146 m_preserve_x_scale.Destruct; 147 m_animate.Destruct; 148 149 m_poly1.Destruct; 150 m_poly2.Destruct; 151 152 m_feng.Destruct; 153 m_fman.Destruct; 154 155end; 156 157{ ON_INIT } 158procedure the_application.on_init; 159begin 160 m_poly1.xn_ptr(0 )^:= 10 + 50; 161 m_poly1.yn_ptr(0 )^:=-10 + 50; 162 m_poly1.xn_ptr(1 )^:= 10 + 150 + 20; 163 m_poly1.yn_ptr(1 )^:=-10 + 150 - 20; 164 m_poly1.xn_ptr(2 )^:= 10 + 250 - 20; 165 m_poly1.yn_ptr(2 )^:=-10 + 250 + 20; 166 m_poly1.xn_ptr(3 )^:= 10 + 350 + 20; 167 m_poly1.yn_ptr(3 )^:=-10 + 350 - 20; 168 m_poly1.xn_ptr(4 )^:= 10 + 450 - 20; 169 m_poly1.yn_ptr(4 )^:=-10 + 450 + 20; 170 m_poly1.xn_ptr(5 )^:= 10 + 550; 171 m_poly1.yn_ptr(5 )^:=-10 + 550; 172 173 m_poly2.xn_ptr(0 )^:=-10 + 50; 174 m_poly2.yn_ptr(0 )^:= 10 + 50; 175 m_poly2.xn_ptr(1 )^:=-10 + 150 + 20; 176 m_poly2.yn_ptr(1 )^:= 10 + 150 - 20; 177 m_poly2.xn_ptr(2 )^:=-10 + 250 - 20; 178 m_poly2.yn_ptr(2 )^:= 10 + 250 + 20; 179 m_poly2.xn_ptr(3 )^:=-10 + 350 + 20; 180 m_poly2.yn_ptr(3 )^:= 10 + 350 - 20; 181 m_poly2.xn_ptr(4 )^:=-10 + 450 - 20; 182 m_poly2.yn_ptr(4 )^:= 10 + 450 + 20; 183 m_poly2.xn_ptr(5 )^:=-10 + 550; 184 m_poly2.yn_ptr(5 )^:= 10 + 550; 185 186end; 187 188{ ON_DRAW } 189procedure the_application.on_draw; 190var 191 pixf : pixel_formats; 192 rgba : aggclr; 193 194 rb : renderer_base; 195 r : renderer_scanline_aa_solid; 196 sl : scanline_p8; 197 198 ras : rasterizer_scanline_aa; 199 200 path1 , 201 path2 : simple_polygon_vertex_source; 202 203 bspline1 , 204 bspline2 : conv_bspline; 205 206 tcurve : trans_double_path; 207 fcurves : conv_curve; 208 fsegm : conv_segmentator; 209 ftrans : conv_transform; 210 211 x ,y : double; 212 213 p : int8u_ptr; 214 215 glyph : glyph_cache_ptr; 216 217 stroke1 , 218 stroke2 : conv_stroke; 219 220begin 221// Initialize structures 222 pixfmt(pixf ,rbuf_window ); 223 224 rb.Construct(@pixf ); 225 r.Construct (@rb ); 226 227 rgba.ConstrDbl(1 ,1 ,1 ); 228 rb.clear (@rgba ); 229 230 sl.Construct; 231 ras.Construct; 232 233// Render the text 234 path1.Construct(m_poly1.polygon ,m_poly1.num_points ,false ,false ); 235 path2.Construct(m_poly2.polygon ,m_poly2.num_points ,false ,false ); 236 237 bspline1.Construct(@path1 ); 238 bspline2.Construct(@path2 ); 239 240 bspline1.interpolation_step_(1.0 / m_num_points._value ); 241 bspline2.interpolation_step_(1.0 / m_num_points._value ); 242 243 tcurve.Construct; 244 fcurves.Construct(m_fman.path_adaptor ); 245 fsegm.Construct (@fcurves); 246 ftrans.Construct (@fsegm ,@tcurve ); 247 248 tcurve.preserve_x_scale_(m_preserve_x_scale._status ); 249 250 if m_fixed_len._status then 251 tcurve.base_length_(1140.0 ); 252 253 tcurve.base_height_(30.0 ); 254 tcurve.add_paths (@bspline1 ,@bspline2 ); 255 256 fsegm.approximation_scale_ (3.0 ); 257 fcurves.approximation_scale_(5.0 ); 258 259 m_feng.height_ (40.0 ); 260 m_feng.hinting_(false ); 261 m_feng.italic_ (true ); 262 263 if m_feng.create_font('Times New Roman' ,glyph_ren_outline ) then 264 begin 265 x:=0.0; 266 y:=3.0; 267 p:=@text_[0 ]; 268 269 while p^ <> 0 do 270 begin 271 glyph:=m_fman.glyph(p^ ); 272 273 if glyph <> NIL then 274 begin 275 if x > tcurve.total_length1 then 276 break; 277 278 m_fman.add_kerning (@x ,@y ); 279 m_fman.init_embedded_adaptors(glyph ,x ,y ); 280 281 if glyph.data_type = glyph_data_outline then 282 begin 283 ras.reset; 284 ras.add_path(@ftrans ); 285 286 rgba.ConstrInt(0 ,0 ,0 ); 287 r.color_ (@rgba ); 288 289 render_scanlines(@ras ,@sl ,@r ); 290 291 end; 292 293 // increment pen position 294 x:=x + glyph.advance_x; 295 y:=y + glyph.advance_y; 296 297 end; 298 299 inc(ptrcomp(p ) ,sizeof(int8u ) ); 300 301 end; 302 303 end; 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 dc : HDC; 527 528BEGIN 529 dc:=GetDC(0 ); 530 531 app.Construct(dc ,pix_format ,flip_y ); 532 app.caption_ ('AGG Example. Non-linear "Along-A-Curve" Transformer - Win32 (F1-Help)' ); 533 534 if app.init(600 ,600 ,window_resize ) then 535 app.run; 536 537 app.Destruct; 538 539 ReleaseDC(0 ,dc ); 540 541END.