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 perspective ; 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_rbox_ctrl , 26 27 agg_rasterizer_scanline_aa , 28 agg_scanline , 29 agg_scanline_p , 30 31 agg_renderer_base , 32 agg_renderer_scanline , 33 agg_render_scanlines , 34 35 agg_path_storage , 36 agg_bounding_rect , 37 agg_trans_affine , 38 agg_trans_bilinear , 39 agg_trans_perspective , 40 agg_conv_transform , 41 agg_conv_stroke , 42 agg_conv_clip_polygon , 43 agg_ellipse , 44 interactive_polygon_ , 45 parse_lion_ 46 47{$I pixel_formats.inc } 48{$I agg_mode.inc } 49 50const 51 flip_y = true; 52 53var 54 g_rasterizer : rasterizer_scanline_aa; 55 g_scanline : scanline_p8; 56 57 g_path : path_storage; 58 g_colors : array[0..99 ] of aggclr; 59 g_path_idx : array[0..99 ] of unsigned; 60 61 g_npaths : unsigned; 62 63 g_x1 ,g_y1 ,g_x2 ,g_y2 , 64 g_base_dx ,g_base_dy , 65 g_angle ,g_scale , 66 g_skew_x ,g_skew_y : double; 67 68 g_nclick : int; 69 70type 71 the_application = object(platform_support ) 72 m_quad : interactive_polygon; 73 m_trans_type : rbox_ctrl; 74 75 constructor Construct(format_ : pix_format_e; flip_y_ : boolean ); 76 destructor Destruct; 77 78 procedure on_init; virtual; 79 procedure on_draw; virtual; 80 81 procedure on_mouse_move (x ,y : int; flags : unsigned ); virtual; 82 procedure on_mouse_button_down(x ,y : int; flags : unsigned ); virtual; 83 procedure on_mouse_button_up (x ,y : int; flags : unsigned ); virtual; 84 85 procedure on_key(x ,y : int; key ,flags : unsigned ); virtual; 86 87 end; 88 89{ _PARSE_LION_ } 90procedure _parse_lion_; 91begin 92 g_npaths:=parse_lion(@g_path ,@g_colors ,@g_path_idx ); 93 94 bounding_rect(@g_path ,@g_path_idx ,0 ,g_npaths ,@g_x1 ,@g_y1 ,@g_x2 ,@g_y2 ); 95 96 g_base_dx:=(g_x2 - g_x1 ) / 2.0; 97 g_base_dy:=(g_y2 - g_y1 ) / 2.0; 98 99 g_path.flip_x(g_x1 ,g_x2 ); 100 g_path.flip_y(g_y1 ,g_y2 ); 101 102end; 103 104{ CONSTRUCT } 105constructor the_application.Construct; 106begin 107 inherited Construct(format_ ,flip_y_ ); 108 109 m_quad.Construct (4 ,5.0 ); 110 m_trans_type.Construct(420 ,5.0 ,420 + 130.0 ,55.0 ,not flip_y_ ); 111 112 _parse_lion_; 113 114 m_quad.xn_ptr(0 )^:=g_x1; 115 m_quad.yn_ptr(0 )^:=g_y1; 116 m_quad.xn_ptr(1 )^:=g_x2; 117 m_quad.yn_ptr(1 )^:=g_y1; 118 m_quad.xn_ptr(2 )^:=g_x2; 119 m_quad.yn_ptr(2 )^:=g_y2; 120 m_quad.xn_ptr(3 )^:=g_x1; 121 m_quad.yn_ptr(3 )^:=g_y2; 122 123 m_trans_type.add_item ('Bilinear' ); 124 m_trans_type.add_item ('Perspective' ); 125 m_trans_type.cur_item_(0 ); 126 127 add_ctrl(@m_trans_type ); 128 129end; 130 131{ DESTRUCT } 132destructor the_application.Destruct; 133begin 134 inherited Destruct; 135 136 m_quad.Destruct; 137 m_trans_type.Destruct; 138 139end; 140 141{ ON_INIT } 142procedure the_application.on_init; 143var 144 dx ,dy : double; 145 146begin 147 dx:=_width / 2.0 - (m_quad.xn_ptr(1 )^ - m_quad.xn_ptr(0 )^ ) / 2.0; 148 dy:=_height / 2.0 - (m_quad.yn_ptr(2 )^ - m_quad.yn_ptr(0 )^ ) / 2.0; 149 150 m_quad.xn_ptr(0 )^:=m_quad.xn_ptr(0 )^ + dx; 151 m_quad.yn_ptr(0 )^:=m_quad.yn_ptr(0 )^ + dy; 152 m_quad.xn_ptr(1 )^:=m_quad.xn_ptr(1 )^ + dx; 153 m_quad.yn_ptr(1 )^:=m_quad.yn_ptr(1 )^ + dy; 154 m_quad.xn_ptr(2 )^:=m_quad.xn_ptr(2 )^ + dx; 155 m_quad.yn_ptr(2 )^:=m_quad.yn_ptr(2 )^ + dy; 156 m_quad.xn_ptr(3 )^:=m_quad.xn_ptr(3 )^ + dx; 157 m_quad.yn_ptr(3 )^:=m_quad.yn_ptr(3 )^ + dy; 158 159end; 160 161{ ON_DRAW } 162procedure the_application.on_draw; 163var 164 pixf : pixel_formats; 165 166 rb : renderer_base; 167 r : renderer_scanline_aa_solid; 168 169 rgba : aggclr; 170 171 tr_bi : trans_bilinear; 172 tr_pe , 173 tr2 : trans_perspective23; 174 175 trans : conv_transform; 176 177 ell : ellipse; 178 ell_stroke : conv_stroke; 179 trans_ell , 180 trans_ell_stroke : conv_transform; 181 182 x ,y : double; 183 184begin 185// Initialize structures 186 pixfmt(pixf ,rbuf_window ); 187 188 rb.Construct(@pixf ); 189 r.Construct (@rb ); 190 191 rgba.ConstrDbl(1 ,1 ,1 ); 192 rb.clear (@rgba ); 193 194 g_rasterizer.clip_box(0 ,0 ,_width ,_height ); 195 196// Perspective rendering 197 if m_trans_type._cur_item = 0 then 198 begin 199 tr_bi.Construct(g_x1 ,g_y1 ,g_x2 ,g_y2 ,m_quad.polygon ); 200 201 if tr_bi.is_valid then 202 begin 203 // Render transformed lion 204 trans.Construct (@g_path ,@tr_bi ); 205 render_all_paths(@g_rasterizer ,@g_scanline ,@r ,@trans ,@g_colors ,@g_path_idx ,g_npaths ); 206 207 // Render transformed ellipse 208 ell.Construct( 209 (g_x1 + g_x2 ) * 0.5 ,(g_y1 + g_y2 ) * 0.5 , 210 (g_x2 - g_x1 ) * 0.5 ,(g_y2 - g_y1 ) * 0.5 ,200 ); 211 212 ell_stroke.Construct(@ell ); 213 ell_stroke.width_ (3.0 ); 214 trans_ell.Construct (@ell ,@tr_bi ); 215 216 trans_ell_stroke.Construct(@ell_stroke ,@tr_bi ); 217 218 g_rasterizer.add_path(@trans_ell ); 219 220 rgba.ConstrDbl(0.5 ,0.3 ,0.0 ,0.3 ); 221 r.color_ (@rgba ); 222 223 render_scanlines(@g_rasterizer ,@g_scanline ,@r ); 224 225 g_rasterizer.add_path(@trans_ell_stroke ); 226 227 rgba.ConstrDbl(0.0 ,0.3 ,0.2 ,1.0 ); 228 r.color_ (@rgba ); 229 230 render_scanlines(@g_rasterizer ,@g_scanline ,@r ); 231 232 // Free 233 ell_stroke.Destruct; 234 235 end; 236 237 end 238 else 239 begin 240 tr_pe.Construct(g_x1 ,g_y1 ,g_x2 ,g_y2 ,m_quad.polygon ); 241 242 if tr_pe.is_valid then 243 begin 244 // Render transformed lion 245 trans.Construct(@g_path ,@tr_pe ); 246 247 render_all_paths(@g_rasterizer ,@g_scanline ,@r ,@trans ,@g_colors ,@g_path_idx ,g_npaths ); 248 249 // Render transformed ellipse 250 ell.Construct( 251 (g_x1 + g_x2 ) * 0.5 ,(g_y1 + g_y2 ) * 0.5 , 252 (g_x2 - g_x1 ) * 0.5 ,(g_y2 - g_y1 ) * 0.5 ,200 ); 253 254 ell_stroke.Construct(@ell ); 255 ell_stroke.width_ (3.0 ); 256 257 trans_ell.Construct (@ell ,@tr_pe ); 258 trans_ell_stroke.Construct(@ell_stroke ,@tr_pe ); 259 260 g_rasterizer.add_path(@trans_ell ); 261 262 rgba.ConstrDbl(0.5 ,0.3 ,0.0 ,0.3 ); 263 r.color_ (@rgba ); 264 265 render_scanlines(@g_rasterizer ,@g_scanline ,@r ); 266 267 g_rasterizer.add_path(@trans_ell_stroke ); 268 269 rgba.ConstrDbl(0.0 ,0.3 ,0.2 ,1.0 ); 270 r.color_ (@rgba ); 271 272 render_scanlines(@g_rasterizer ,@g_scanline ,@r ); 273 274 // Free 275 ell_stroke.Destruct; 276 277 // Testing the reverse transformations 278 { tr2.Construct(m_quad.polygon ,g_x1 ,g_y1 ,g_x2 ,g_y2 ); 279 280 if tr2.is_valid then 281 begin 282 x:=m_quad.xn_ptr(0 )^; 283 y:=m_quad.yn_ptr(0 )^; 284 285 tr2.transform (@tr2 ,@x ,@y ); 286 g_rasterizer.move_to_d(x ,y ); 287 288 x:=m_quad.xn_ptr(1 )^; 289 y:=m_quad.yn_ptr(1 )^; 290 291 tr2.transform (@tr2 ,@x ,@y ); 292 g_rasterizer.line_to_d(x ,y ); 293 294 x:=m_quad.xn_ptr(2 )^; 295 y:=m_quad.yn_ptr(2 )^; 296 297 tr2.transform (@tr2 ,@x ,@y ); 298 g_rasterizer.line_to_d(x ,y ); 299 300 x:=m_quad.xn_ptr(3 )^; 301 y:=m_quad.yn_ptr(3 )^; 302 303 tr2.transform (@tr2 ,@x ,@y ); 304 g_rasterizer.line_to_d(x ,y ); 305 306 rgba.ConstrDbl(0.5 ,0.0 ,0.0 ,0.5 ); 307 r.color_ (@rgba ); 308 309 render_scanlines(@g_rasterizer ,@g_scanline ,@r ); 310 311 end 312 else 313 message_('Singularity...' );{} 314 315 end; 316 317 end; 318 319// Render the "quad" tool and controls 320 g_rasterizer.add_path(@m_quad ); 321 322 rgba.ConstrDbl(0 ,0.3 ,0.5 ,0.6 ); 323 r.color_ (@rgba ); 324 325 render_scanlines(@g_rasterizer ,@g_scanline ,@r ); 326 render_ctrl (@g_rasterizer ,@g_scanline ,@r ,@m_trans_type ); 327 328end; 329 330{ ON_MOUSE_MOVE } 331procedure the_application.on_mouse_move; 332begin 333 if flags and mouse_left <> 0 then 334 if m_quad.on_mouse_move(x ,y ) then 335 force_redraw; 336 337 if flags and mouse_left = 0 then 338 on_mouse_button_up(x ,y ,flags ); 339 340end; 341 342{ ON_MOUSE_BUTTON_DOWN } 343procedure the_application.on_mouse_button_down; 344begin 345 if flags and mouse_left <> 0 then 346 if m_quad.on_mouse_button_down(x ,y ) then 347 force_redraw; 348 349end; 350 351{ ON_MOUSE_BUTTON_UP } 352procedure the_application.on_mouse_button_up; 353begin 354 if m_quad.on_mouse_button_up(x ,y ) then 355 force_redraw; 356 357end; 358 359{ ON_KEY } 360procedure the_application.on_key; 361begin 362 if key = key_f1 then 363 message_( 364 'Perspective and bilinear transformations. In general, these classes can transform '#13 + 365 'an arbitrary quadrangle to another arbitrary quadrangle (with some restrictions). '#13 + 366 'The example demonstrates how to transform a rectangle to a quadrangle defined by '#13 + 367 '4 vertices. Note, that the perspective transformations don''t work correctly if '#13 + 368 'the destination quadrangle is concave. Bilinear thansformations give a different '#13 + 369 'result, but remain valid with any shape of the destination quadrangle.'#13#13 + 370 'How to play with:'#13#13 + 371 'You can drag the 4 corners of the quadrangle, as well as its boundaries.' + 372 #13#13'Note: F2 key saves current "screenshot" file in this demo''s directory. ' ); 373 374end; 375 376VAR 377 app : the_application; 378 379BEGIN 380// Rendering 381 g_rasterizer.Construct; 382 g_scanline.Construct; 383 g_path.Construct; 384 385 g_npaths:=0; 386 387 g_x1:=0; 388 g_y1:=0; 389 g_x2:=0; 390 g_y2:=0; 391 392 g_base_dx:=0; 393 g_base_dy:=0; 394 395 g_angle:=0; 396 g_scale:=1.0; 397 398 g_skew_x:=0; 399 g_skew_y:=0; 400 g_nclick:=0; 401 402// App 403 app.Construct(pix_format ,flip_y ); 404 app.caption_ ('AGG Example. Perspective Transformations (F1-Help)' ); 405 406 if app.init(600 ,600 ,window_resize ) then 407 app.run; 408 409 app.Destruct; 410 411// Free 412 g_rasterizer.Destruct; 413 g_scanline.Destruct; 414 g_path.Destruct; 415 416END.