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.