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.