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 multi_clip ; 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 Math , 22 23 agg_basics , 24 agg_array , 25 agg_platform_support , 26 27 agg_ctrl , 28 agg_slider_ctrl , 29 30 agg_rasterizer_scanline_aa , 31 agg_rasterizer_outline_aa , 32 agg_scanline , 33 agg_scanline_u , 34 35 agg_rendering_buffer , 36 agg_renderer_base , 37 agg_renderer_scanline , 38 agg_renderer_outline_aa , 39 agg_renderer_primitives , 40 agg_renderer_markers , 41 agg_renderer_mclip , 42 agg_render_scanlines , 43 44 agg_path_storage , 45 agg_bounding_rect , 46 agg_trans_affine , 47 agg_conv_transform , 48 agg_ellipse , 49 agg_span_gradient , 50 agg_span_allocator , 51 agg_span_interpolator_linear , 52 parse_lion_ 53 54{$I pixel_formats.inc } 55{$I agg_mode.inc } 56 57const 58 flip_y = true; 59 60var 61 g_rasterizer : rasterizer_scanline_aa; 62 g_scanline : scanline_u8; 63 64 g_path : path_storage; 65 g_colors : array[0..99 ] of aggclr; 66 g_path_idx : array[0..99 ] of unsigned; 67 68 g_npaths : unsigned; 69 70 g_x1 ,g_y1 ,g_x2 ,g_y2 , 71 g_base_dx ,g_base_dy , 72 g_angle ,g_scale , 73 g_skew_x ,g_skew_y : double; 74 75 g_nclick : int; 76 77type 78 gradient_linear_color = object(pod_auto_array ) 79 m_c1 ,m_c2 ,c : aggclr; 80 81 constructor Construct(c1 ,c2 : aggclr_ptr ); 82 83 function size : unsigned; virtual; 84 function array_operator(i : unsigned ) : pointer; virtual; 85 86 procedure colors(c1 ,c2 : aggclr_ptr ); 87 88 end; 89 90 the_application = object(platform_support ) 91 m_num_cb : slider_ctrl; 92 93 constructor Construct(format_ : pix_format_e; flip_y_ : boolean ); 94 destructor Destruct; 95 96 procedure on_draw; virtual; 97 98 procedure transform(width_ ,height_ ,x ,y : double ); 99 100 procedure on_mouse_move (x ,y : int; flags : unsigned ); virtual; 101 procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual; 102 103 procedure on_key(x ,y : int; key ,flags : unsigned ); virtual; 104 105 end; 106 107{ CONSTRUCT } 108constructor gradient_linear_color.Construct; 109begin 110 m_c1:=c1^; 111 m_c2:=c2^; 112 113end; 114 115{ SIZE } 116function gradient_linear_color.size; 117begin 118 result:=256; 119 120end; 121 122{ ARRAY_OPERATOR } 123function gradient_linear_color.array_operator; 124begin 125 c.v:=int8u((((m_c2.v - m_c1.v ) * i ) + (m_c1.v shl 8 ) ) shr 8 ); 126 c.r:=int8u((((m_c2.r - m_c1.r ) * i ) + (m_c1.r shl 8 ) ) shr 8 ); 127 c.g:=int8u((((m_c2.g - m_c1.g ) * i ) + (m_c1.g shl 8 ) ) shr 8 ); 128 c.b:=int8u((((m_c2.b - m_c1.b ) * i ) + (m_c1.b shl 8 ) ) shr 8 ); 129 c.a:=int8u((((m_c2.a - m_c1.a ) * i ) + (m_c1.a shl 8 ) ) shr 8 ); 130 131 result:=@c; 132 133end; 134 135{ COLORS } 136procedure gradient_linear_color.colors; 137begin 138 m_c1:=c1^; 139 m_c2:=c2^; 140 141end; 142 143{ _PARSE_LION_ } 144procedure _parse_lion_; 145begin 146 g_npaths:=parse_lion(@g_path ,@g_colors ,@g_path_idx ); 147 148 bounding_rect(@g_path ,@g_path_idx ,0 ,g_npaths ,@g_x1 ,@g_y1 ,@g_x2 ,@g_y2 ); 149 150 g_base_dx:=(g_x2 - g_x1 ) / 2.0; 151 g_base_dy:=(g_y2 - g_y1 ) / 2.0; 152 153end; 154 155{ CONSTRUCT } 156constructor the_application.Construct; 157begin 158 inherited Construct(format_ ,flip_y_ ); 159 160 m_num_cb.Construct(5 ,5 ,150 ,12 ,not flip_y_ ); 161 162 _parse_lion_; 163 164 add_ctrl(@m_num_cb ); 165 166 m_num_cb.range_ (2 ,10 ); 167 //m_num_cb.num_steps_(8 ); 168 m_num_cb.label_ ('N=%.2f' ); 169 m_num_cb.no_transform; 170 171end; 172 173{ DESTRUCT } 174destructor the_application.Destruct; 175begin 176 inherited Destruct; 177 178 m_num_cb.Destruct; 179 180end; 181 182{ ON_DRAW } 183procedure the_application.on_draw; 184var 185 i : unsigned; 186 187 width_ ,height_ ,x ,y ,x1 ,y1 ,x2 ,y2 : int; 188 189 pf : pixel_formats; 190 r : renderer_mclip; 191 rs : renderer_scanline_aa_solid; 192 193 rgba , 194 rgbb : aggclr; 195 196 mtx : trans_affine; 197 tat : trans_affine_translation; 198 tas : trans_affine_scaling; 199 tar : trans_affine_rotation; 200 taw : trans_affine_skewing; 201 202 trans : conv_transform; 203 204 m : renderer_markers; 205 w , 206 n : double; 207 208 profile : line_profile_aa; 209 210 ren : renderer_outline_aa; 211 ras : rasterizer_outline_aa; 212 grm : trans_affine; 213 grf : gradient_circle; 214 grc : gradient_linear_color; 215 ell : ellipse; 216 217 sa : span_allocator; 218 sg : span_gradient; 219 rg : renderer_scanline_aa; 220 221 inter : span_interpolator_linear; 222 223begin 224 width_ :=rbuf_window._width; 225 height_:=rbuf_window._height; 226 227// Initialize structures 228 pixfmt(pf ,rbuf_window ); 229 230 r.Construct (@pf ); 231 rs.Construct(@r ); 232 233// Transform lion 234 mtx.Construct; 235 236 tat.Construct(-g_base_dx ,-g_base_dy ); 237 mtx.multiply (@tat ); 238 239 tas.Construct(g_scale ,g_scale ); 240 mtx.multiply (@tas ); 241 242 tar.Construct(g_angle + pi ); 243 mtx.multiply (@tar ); 244 245 taw.Construct(g_skew_x / 1000.0 ,g_skew_y / 1000.0 ); 246 mtx.multiply (@taw ); 247 248 tat.Construct(_width / 2 ,_height / 2 ); 249 mtx.multiply (@tat ); 250 251 rgba.ConstrDbl(1 ,1 ,1 ); 252 r.clear (@rgba ); 253 254// Custom Clip Renderer Base 255 r.reset_clipping(false ); // Visibility: "false" means "no visible regions" 256 257 n:=m_num_cb._value; 258 x:=0; 259 260 while x < n do 261 begin 262 y:=0; 263 264 while y < n do 265 begin 266 x1:=trunc(width_ * x / n ); 267 y1:=trunc(height_ * y / n ); 268 x2:=trunc(width_ * (x + 1 ) / n ); 269 y2:=trunc(height_ * (y + 1 ) / n ); 270 271 r.add_clip_box(x1 + 5 ,y1 + 5 ,x2 - 5 ,y2 - 5 ); 272 273 inc(y ); 274 275 end; 276 277 inc(x ); 278 279 end;{} 280 281// Render the lion 282 trans.Construct (@g_path ,@mtx ); 283 render_all_paths(@g_rasterizer ,@g_scanline ,@rs ,@trans ,@g_colors ,@g_path_idx ,g_npaths );{} 284 285// The scanline rasterizer allows you to perform clipping to multiple 286// regions "manually", like in the following code, but the "embedded" method 287// shows much better performance. 288{ for i:=0 to g_npaths - 1 do 289 begin 290 g_rasterizer.reset; 291 g_rasterizer.add_path(@trans ,g_path_idx[i ] ); 292 293 rs.color_(@g_colors[i ] ); 294 295 n:=m_num_cb._value; 296 x:=0; 297 298 while x < n do 299 begin 300 y:=0; 301 302 while y < n do 303 begin 304 x1:=trunc(width_ * x / n ); 305 y1:=trunc(height_ * y / n ); 306 x2:=trunc(width_ * (x + 1 ) / n ); 307 y2:=trunc(height_ * (y + 1 ) / n ); 308 309 // r should be of type renderer_base 310 r.clip_box_(x1 + 5 ,y1 + 5 ,x2 - 5 ,y2 - 5 ); 311 312 render_scanlines(@g_rasterizer ,@g_scanline ,@rs ); 313 314 inc(y ); 315 316 end; 317 318 inc(x ); 319 320 end; 321 322 end;{} 323 324// Render random Bresenham lines and markers 325 m.Construct(@r ); 326 327 for i:=0 to 49 do 328 begin 329 rgba.ConstrInt( 330 Random($7fff ) and $7F , 331 Random($7fff ) and $7F , 332 Random($7fff ) and $7F , 333 (Random($7fff ) and $7F ) + $7F ); 334 335 m.line_color_(@rgba ); 336 337 rgba.ConstrInt( 338 Random($7fff ) and $7F , 339 Random($7fff ) and $7F , 340 Random($7fff ) and $7F , 341 (Random($7fff ) and $7F ) + $7F ); 342 343 m.fill_color_(@rgba ); 344 345 m.line( 346 m.coord(Random($7fff ) mod width_ ) ,m.coord(Random($7fff ) mod height_ ) , 347 m.coord(Random($7fff ) mod width_ ) ,m.coord(Random($7fff ) mod height_ ) ); 348 349 m.marker( 350 Random($7fff ) mod width_ ,Random($7fff ) mod height_ ,Random($7fff ) mod 10 + 5 , 351 marker_e(Random($7fff ) mod int(end_of_markers ) ) ); 352 353 end; 354 355// Render random anti-aliased lines 356 w:=5.0; 357 358 profile.Construct; 359 profile.width_(w ); 360 361 ren.Construct (@r ,@profile ); 362 ras.Construct (@ren ); 363 ras.round_cap_(true ); 364 365 for i:=0 to 49 do 366 begin 367 rgba.ConstrInt( 368 Random($7fff ) and $7F , 369 Random($7fff ) and $7F , 370 Random($7fff ) and $7F , 371 (Random($7fff ) and $7F ) + $7F ); 372 373 ren.color_(@rgba ); 374 375 ras.move_to_d(Random($7fff ) mod width_ ,Random($7fff ) mod height_ ); 376 ras.line_to_d(Random($7fff ) mod width_ ,Random($7fff ) mod height_ ); 377 ras.render (false ); 378 379 end; 380 381// Render random circles with gradient 382 grm.Construct; 383 grf.Construct; 384 rgba.ConstrInt(0 ,0 ,0 ); 385 rgbb.ConstrInt(0 ,0 ,0 ); 386 grc.Construct (@rgba ,@rgbb ); 387 ell.Construct; 388 sa.Construct; 389 inter.Construct(@grm ); 390 391 sg.Construct(@sa ,@inter ,@grf ,@grc ,0 ,10 ); 392 rg.Construct(@r ,@sg ); 393 394 for i:=0 to 49 do 395 begin 396 x:=Random($7fff ) mod width_; 397 y:=Random($7fff ) mod height_; 398 w:=Random($7fff ) mod 10 + 5; 399 400 grm.reset; 401 402 tas.Construct(w / 10.0 ); 403 grm.multiply (@tas ); 404 405 tat.Construct(x ,y ); 406 grm.multiply (@tat ); 407 408 grm.invert; 409 410 rgba.ConstrInt(255 ,255 ,255 ,0 ); 411 rgbb.ConstrInt( 412 Random($7fff ) and $7F , 413 Random($7fff ) and $7F , 414 Random($7fff ) and $7F ,255 ); 415 416 grc.colors(@rgba ,@rgbb ); 417 sg.color_function_(@grc ); 418 419 ell.init(x ,y ,w ,w ,32 ); 420 421 g_rasterizer.add_path(@ell ); 422 render_scanlines (@g_rasterizer ,@g_scanline ,@rg ); 423 424 end; 425 426// Render the controls 427 r.reset_clipping(true ); // "true" means "all rendering buffer is visible". 428 429 render_ctrl(@g_rasterizer ,@g_scanline ,@rs ,@m_num_cb ); 430 431// Free AGG resources 432 profile.Destruct; 433 ras.Destruct; 434 sa.Destruct; 435 r.Destruct; 436 437end; 438 439{ TRANSFORM } 440procedure the_application.transform; 441begin 442 x:=x - width_ / 2; 443 y:=y - height_ / 2; 444 445 g_angle:=ArcTan2(y ,x ); 446 g_scale:=Sqrt(y * y + x * x ) / 100.0; 447 448end; 449 450{ ON_MOUSE_MOVE } 451procedure the_application.on_mouse_move; 452begin 453 on_mouse_button_down(x ,y ,flags ); 454 455end; 456 457{ ON_MOUSE_BUTTON_DOWN } 458procedure the_application.on_mouse_button_down; 459var 460 width_ ,height_ : int; 461 462begin 463 if flags and mouse_left <> 0 then 464 begin 465 width_ :=rbuf_window._width; 466 height_:=rbuf_window._height; 467 468 transform(width_ ,height_ ,x ,y ); 469 470 force_redraw; 471 472 end; 473 474 if flags and mouse_right <> 0 then 475 begin 476 g_skew_x:=x; 477 g_skew_y:=y; 478 479 force_redraw; 480 481 end; 482 483end; 484 485{ ON_KEY } 486procedure the_application.on_key; 487begin 488 if key = key_f1 then 489 message_( 490 'A testing example that demonstrates clipping to multiple rectangular regions. '#13 + 491 'It''s a low-level (pixel) clipping that can be useful to draw images clipped '#13 + 492 'to a complex region with orthogonal boundaries. It can be useful in some window '#13 + 493 'interfaces that use a custom mechanism to draw window content. The example '#13 + 494 'uses all possible rendering mechanisms.'#13#13 + 495 'How to play with:'#13#13 + 496 'Use the left mouse button to rotate and resize the lion.'#13 + 497 'Use the right mouse button to skew the lion.' + 498 #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' ); 499 500end; 501 502VAR 503 app : the_application; 504 505BEGIN 506// Rendering 507 g_rasterizer.Construct; 508 g_scanline.Construct; 509 g_path.Construct; 510 511 g_npaths:=0; 512 513 g_x1:=0; 514 g_y1:=0; 515 g_x2:=0; 516 g_y2:=0; 517 518 g_base_dx:=0; 519 g_base_dy:=0; 520 521 g_angle:=0; 522 g_scale:=1.0; 523 524 g_skew_x:=0; 525 g_skew_y:=0; 526 g_nclick:=0; 527 528// App 529 app.Construct(pix_format ,flip_y ); 530 app.caption_ ('AGG Example. Clipping to multiple rectangle regions (F1-Help)' ); 531 532 if app.init(512 ,400 ,window_resize ) then 533 app.run; 534 535 app.Destruct; 536 537// Free 538 g_rasterizer.Destruct; 539 g_scanline.Destruct; 540 g_path.Destruct; 541 542END.