1 #include <math.h>
2 #include <stdio.h>
3 #include <time.h>
4 #include "agg_basics.h"
5 #include "agg_rendering_buffer.h"
6 #include "agg_rasterizer_scanline_aa.h"
7 #include "agg_rasterizer_outline.h"
8 #include "agg_conv_transform.h"
9 #include "agg_conv_stroke.h"
10 #include "agg_scanline_p.h"
11 #include "agg_renderer_scanline.h"
12 #include "agg_renderer_primitives.h"
13 #include "agg_rasterizer_outline.h"
14 #include "agg_rasterizer_outline_aa.h"
15 #include "agg_pattern_filters_rgba.h"
16 #include "agg_renderer_outline_aa.h"
17 #include "agg_renderer_outline_image.h"
18 #include "ctrl/agg_slider_ctrl.h"
19 #include "ctrl/agg_cbox_ctrl.h"
20 #include "platform/agg_platform_support.h"
21 
22 #define AGG_BGR24
23 //#define AGG_RGB24
24 //#define AGG_BGRA32
25 //#define AGG_RGBA32
26 //#define AGG_ARGB32
27 //#define AGG_ABGR32
28 //#define AGG_RGB565
29 //#define AGG_RGB555
30 #include "pixel_formats.h"
31 
32 
33 enum flip_y_e { flip_y = true };
34 
35 static const agg::int32u pixmap_chain[] =
36 {
37     16, 7,
38     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0xb4c29999, 0xff9a5757, 0xff9a5757, 0xff9a5757, 0xff9a5757, 0xff9a5757, 0xff9a5757, 0xb4c29999, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff,
39     0x00ffffff, 0x00ffffff, 0x0cfbf9f9, 0xff9a5757, 0xff660000, 0xff660000, 0xff660000, 0xff660000, 0xff660000, 0xff660000, 0xff660000, 0xff660000, 0xb4c29999, 0x00ffffff, 0x00ffffff, 0x00ffffff,
40     0x00ffffff, 0x5ae0cccc, 0xffa46767, 0xff660000, 0xff975252, 0x7ed4b8b8, 0x5ae0cccc, 0x5ae0cccc, 0x5ae0cccc, 0x5ae0cccc, 0xa8c6a0a0, 0xff7f2929, 0xff670202, 0x9ecaa6a6, 0x5ae0cccc, 0x00ffffff,
41     0xff660000, 0xff660000, 0xff660000, 0xff660000, 0xff660000, 0xff660000, 0xa4c7a2a2, 0x3affff00, 0x3affff00, 0xff975151, 0xff660000, 0xff660000, 0xff660000, 0xff660000, 0xff660000, 0xff660000,
42     0x00ffffff, 0x5ae0cccc, 0xffa46767, 0xff660000, 0xff954f4f, 0x7ed4b8b8, 0x5ae0cccc, 0x5ae0cccc, 0x5ae0cccc, 0x5ae0cccc, 0xa8c6a0a0, 0xff7f2929, 0xff670202, 0x9ecaa6a6, 0x5ae0cccc, 0x00ffffff,
43     0x00ffffff, 0x00ffffff, 0x0cfbf9f9, 0xff9a5757, 0xff660000, 0xff660000, 0xff660000, 0xff660000, 0xff660000, 0xff660000, 0xff660000, 0xff660000, 0xb4c29999, 0x00ffffff, 0x00ffffff, 0x00ffffff,
44     0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0xb4c29999, 0xff9a5757, 0xff9a5757, 0xff9a5757, 0xff9a5757, 0xff9a5757, 0xff9a5757, 0xb4c29999, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff
45 };
46 
47 
48 
49 namespace agg
50 {
51     class pattern_pixmap_argb32
52     {
53     public:
54         typedef rgba8 color_type;
55 
pattern_pixmap_argb32(const int32u * pixmap)56         pattern_pixmap_argb32(const int32u* pixmap) : m_pixmap(pixmap) {}
57 
width() const58         unsigned width()  const { return m_pixmap[0]; }
height() const59         unsigned height() const { return m_pixmap[1]; }
60 
pixel(int x,int y) const61         rgba8 pixel(int x, int y) const
62         {
63             int32u p = m_pixmap[y * width() + x + 2];
64             return rgba8((p >> 16) & 0xFF, (p >> 8) & 0xFF, p & 0xFF, p >> 24);
65         }
66     private:
67         const int32u* m_pixmap;
68     };
69 }
70 
71 
72 
73 class spiral
74 {
75 public:
spiral(double x,double y,double r1,double r2,double step,double start_angle=0)76     spiral(double x, double y, double r1, double r2, double step, double start_angle=0) :
77         m_x(x),
78         m_y(y),
79         m_r1(r1),
80         m_r2(r2),
81         m_step(step),
82         m_start_angle(start_angle),
83         m_angle(start_angle),
84         m_da(agg::deg2rad(8.0)),
85         m_dr(m_step / 45.0)
86     {
87     }
88 
rewind(unsigned)89     void rewind(unsigned)
90     {
91         m_angle = m_start_angle;
92         m_curr_r = m_r1;
93         m_start = true;
94     }
95 
vertex(double * x,double * y)96     unsigned vertex(double* x, double* y)
97     {
98         if(m_curr_r > m_r2) return agg::path_cmd_stop;
99 
100         *x = m_x + cos(m_angle) * m_curr_r;
101         *y = m_y + sin(m_angle) * m_curr_r;
102         m_curr_r += m_dr;
103         m_angle += m_da;
104         if(m_start)
105         {
106             m_start = false;
107             return agg::path_cmd_move_to;
108         }
109         return agg::path_cmd_line_to;
110     }
111 
112 private:
113     double m_x;
114     double m_y;
115     double m_r1;
116     double m_r2;
117     double m_step;
118     double m_start_angle;
119 
120     double m_angle;
121     double m_curr_r;
122     double m_da;
123     double m_dr;
124     bool   m_start;
125 };
126 
127 
128 struct roundoff
129 {
transformroundoff130     void transform(double* x, double* y) const
131     {
132         *x = floor(*x);
133         *y = floor(*y);
134     }
135 };
136 
137 
138 class the_application : public agg::platform_support
139 {
140     agg::slider_ctrl<agg::rgba8> m_step;
141     agg::slider_ctrl<agg::rgba8> m_width;
142     agg::cbox_ctrl<agg::rgba8>   m_test;
143     agg::cbox_ctrl<agg::rgba8>   m_rotate;
144     agg::cbox_ctrl<agg::rgba8>   m_accurate_joins;
145     agg::cbox_ctrl<agg::rgba8>   m_scale_pattern;
146     double m_start_angle;
147 
148 
149 public:
150     typedef agg::renderer_base<pixfmt> renderer_base;
151     typedef agg::renderer_scanline_aa_solid<renderer_base> renderer_aa;
152     typedef agg::renderer_primitives<renderer_base> renderer_prim;
153     typedef agg::rasterizer_outline<renderer_prim> rasterizer_outline;
154     typedef agg::rasterizer_scanline_aa<> rasterizer_scanline;
155     typedef agg::scanline_p8 scanline;
156     typedef agg::renderer_outline_aa<renderer_base> renderer_oaa;
157     typedef agg::pattern_filter_bilinear_rgba8 pattern_filter;
158     typedef agg::line_image_pattern_pow2<pattern_filter> image_pattern;
159     typedef agg::renderer_outline_image<renderer_base, image_pattern> renderer_img;
160     typedef agg::rasterizer_outline_aa<renderer_oaa> rasterizer_outline_aa;
161     typedef agg::rasterizer_outline_aa<renderer_img> rasterizer_outline_img;
162 
163 
164 
the_application(agg::pix_format_e format,bool flip_y)165     the_application(agg::pix_format_e format, bool flip_y) :
166         agg::platform_support(format, flip_y),
167         m_step(10.0, 10.0 + 4.0, 150.0, 10.0 + 8.0 + 4.0, !flip_y),
168         m_width(150.0 + 10.0, 10.0 + 4.0, 400 - 10.0, 10.0 + 8.0 + 4.0, !flip_y),
169         m_test(10.0, 10.0 + 4.0 + 16.0,    "Test Performance", !flip_y),
170         m_rotate(130 + 10.0, 10.0 + 4.0 + 16.0,    "Rotate", !flip_y),
171         m_accurate_joins(200 + 10.0, 10.0 + 4.0 + 16.0, "Accurate Joins", !flip_y),
172         m_scale_pattern(310 + 10.0, 10.0 + 4.0 + 16.0, "Scale Pattern", !flip_y),
173         m_start_angle(0.0)
174     {
175         add_ctrl(m_step);
176         m_step.range(0.0, 2.0);
177         m_step.value(0.1);
178         m_step.label("Step=%1.2f");
179         m_step.no_transform();
180 
181         add_ctrl(m_width);
182         m_width.range(0.0, 7.0);
183         m_width.value(3.0);
184         m_width.label("Width=%1.2f");
185         m_width.no_transform();
186 
187         add_ctrl(m_test);
188         m_test.text_size(9.0, 7.0);
189         m_test.no_transform();
190 
191         add_ctrl(m_rotate);
192         m_rotate.text_size(9.0, 7.0);
193         m_rotate.no_transform();
194 
195         add_ctrl(m_accurate_joins);
196         m_accurate_joins.text_size(9.0, 7.0);
197         m_accurate_joins.no_transform();
198 
199         add_ctrl(m_scale_pattern);
200         m_scale_pattern.text_size(9.0, 7.0);
201         m_scale_pattern.no_transform();
202         m_scale_pattern.status(true);
203     }
204 
205 
206 
draw_aliased_pix_accuracy(rasterizer_outline & ras,renderer_prim & prim)207     void draw_aliased_pix_accuracy(rasterizer_outline& ras, renderer_prim& prim)
208     {
209         spiral s1(width()/5, height()/4+50, 5, 70, 8, m_start_angle);
210         roundoff rn;
211         agg::conv_transform<spiral, roundoff> trans(s1, rn);
212         prim.line_color(agg::rgba(0.4, 0.3, 0.1));
213         ras.add_path(trans);
214     }
215 
draw_aliased_subpix_accuracy(rasterizer_outline & ras,renderer_prim & prim)216     void draw_aliased_subpix_accuracy(rasterizer_outline& ras, renderer_prim& prim)
217     {
218         spiral s2(width()/2, height()/4+50, 5, 70, 8, m_start_angle);
219         prim.line_color(agg::rgba(0.4, 0.3, 0.1));
220         ras.add_path(s2);
221     }
222 
draw_anti_aliased_outline(rasterizer_outline_aa & ras,renderer_oaa & ren)223     void draw_anti_aliased_outline(rasterizer_outline_aa& ras, renderer_oaa& ren)
224     {
225         spiral s3(width()/5, height() - height()/4 + 20, 5, 70, 8, m_start_angle);
226         ren.color(agg::rgba(0.4, 0.3, 0.1));
227         ras.add_path(s3);
228     }
229 
draw_anti_aliased_scanline(rasterizer_scanline & ras,scanline & sl,renderer_aa & ren)230     void draw_anti_aliased_scanline(rasterizer_scanline& ras, scanline& sl, renderer_aa& ren)
231     {
232         spiral s4(width()/2, height() - height()/4 + 20, 5, 70, 8, m_start_angle);
233         agg::conv_stroke<spiral> stroke(s4);
234         stroke.width(m_width.value());
235         stroke.line_cap(agg::round_cap);
236         ren.color(agg::rgba(0.4, 0.3, 0.1));
237         ras.add_path(stroke);
238         agg::render_scanlines(ras, sl, ren);
239     }
240 
draw_anti_aliased_outline_img(rasterizer_outline_img & ras,renderer_img & ren)241     void draw_anti_aliased_outline_img(rasterizer_outline_img& ras, renderer_img& ren)
242     {
243         spiral s5(width() - width()/5, height() - height()/4 + 20, 5, 70, 8, m_start_angle);
244         ras.add_path(s5);
245     }
246 
247 
248 
text(rasterizer_scanline & ras,scanline & sl,renderer_aa & ren,double x,double y,const char * txt)249     void text(rasterizer_scanline& ras,
250               scanline& sl,
251               renderer_aa& ren,
252               double x, double y, const char* txt)
253     {
254         agg::gsv_text t;
255         t.size(8);
256         t.text(txt);
257         t.start_point(x, y);
258         agg::conv_stroke<agg::gsv_text> stroke(t);
259         stroke.width(0.7);
260         ras.add_path(stroke);
261         ren.color(agg::rgba(0,0,0));
262         agg::render_scanlines(ras, sl, ren);
263     }
264 
265 
266 
267 
on_draw()268     virtual void on_draw()
269     {
270         pixfmt pf(rbuf_window());
271         renderer_base ren_base(pf);
272         renderer_aa ren_aa(ren_base);
273         renderer_prim ren_prim(ren_base);
274         rasterizer_scanline ras_aa;
275         scanline sl;
276         rasterizer_outline ras_al(ren_prim);
277         agg::line_profile_aa prof;
278         prof.width(m_width.value());
279         renderer_oaa ren_oaa(ren_base, prof);
280         rasterizer_outline_aa ras_oaa(ren_oaa);
281         ras_oaa.line_join(m_accurate_joins.status() ?
282                               agg::outline_miter_accurate_join :
283                               agg::outline_round_join);
284         ras_oaa.round_cap(true);
285 
286         pattern_filter filter;
287         agg::pattern_pixmap_argb32 src(pixmap_chain);
288         agg::line_image_scale<agg::pattern_pixmap_argb32> src_scaled(src, m_width.value());
289         image_pattern pattern(filter);
290         if(m_scale_pattern.status())
291         {
292             pattern.create(src_scaled);
293         }
294         else
295         {
296             pattern.create(src);
297         }
298         renderer_img ren_img(ren_base, pattern);
299         if(m_scale_pattern.status())
300         {
301             ren_img.scale_x(m_width.value() / src.height());
302         }
303         rasterizer_outline_img ras_img(ren_img);
304 
305         ren_base.clear(agg::rgba(1.0, 1.0, 0.95));
306 
307         draw_aliased_pix_accuracy(ras_al, ren_prim);
308         draw_aliased_subpix_accuracy(ras_al, ren_prim);
309         draw_anti_aliased_outline(ras_oaa, ren_oaa);
310         draw_anti_aliased_scanline(ras_aa, sl, ren_aa);
311         draw_anti_aliased_outline_img(ras_img, ren_img);
312 
313         text(ras_aa, sl, ren_aa, 50, 80, "Bresenham lines,\n\nregular accuracy");
314         text(ras_aa, sl, ren_aa, width()/2-50, 80, "Bresenham lines,\n\nsubpixel accuracy");
315         text(ras_aa, sl, ren_aa, 50, height()/2+50, "Anti-aliased lines");
316         text(ras_aa, sl, ren_aa, width()/2-50, height()/2+50, "Scanline rasterizer");
317         text(ras_aa, sl, ren_aa, width() - width()/5 - 50, height()/2+50, "Arbitrary Image Pattern");
318 
319 
320         agg::render_ctrl(ras_aa, sl, ren_base, m_step);
321         agg::render_ctrl(ras_aa, sl, ren_base, m_width);
322         agg::render_ctrl(ras_aa, sl, ren_base, m_test);
323         agg::render_ctrl(ras_aa, sl, ren_base, m_rotate);
324         agg::render_ctrl(ras_aa, sl, ren_base, m_accurate_joins);
325         agg::render_ctrl(ras_aa, sl, ren_base, m_scale_pattern);
326 
327 
328 
329 /*
330 // An example of using anti-aliased outline rasterizer.
331 // Uncomment it to see the result
332 //
333 
334 // Includes:
335 //#include "agg_pixfmt_rgb.h"           // or another
336 //#include "agg_renderer_outline_aa.h"
337 //#include "agg_rasterizer_outline_aa.h"
338 
339 typedef agg::renderer_base<agg::pixfmt_bgr24> base_ren_type;
340 typedef agg::renderer_outline_aa<base_ren_type> renderer_type;
341 typedef agg::rasterizer_outline_aa<renderer_type> rasterizer_type;
342 
343 double width = 5.0;
344 //-- create with specifying width
345 //-- min_width=1.0, smoother_width=1.0
346 //agg::line_profile_aa(width, agg::gamma_none());
347 
348 //-- create uninitialized and set parameters
349 agg::line_profile_aa profile;
350 profile.gamma(agg::gamma_power(1.2));  //optional
351 profile.min_width(0.75);               //optional
352 profile.smoother_width(3.0);           //optional
353 profile.width(width);                  //mandatory!
354 
355 agg::pixfmt_bgr24 pixf(rbuf_window()); //or another
356 base_ren_type base_ren(pixf);
357 renderer_type ren(base_ren, profile);
358 ren.color(agg::rgba8(0,0,0));          //mandatory!
359 rasterizer_type ras(ren);
360 ras.round_cap(true);                   //optional
361 ras.accurate_join(true);               //optional
362 
363 //-- move_to/line_to interface
364 ras.move_to_d(100, 100);
365 ras.line_to_d(150, 200);
366 ras.render(false);     //false means "don't close
367                        //the polygon", i.e. polyline
368 
369 //-- add_path interface
370 //-- doesn't require invoking render()
371 //ras.add_path(some_path);
372 */
373 
374 
375 
376 
377 /*
378 // An example of using image pattern outline rasterizer
379 // Uncomment it to see the result
380 //
381 
382 // Includes:
383 //#include "agg_pixfmt_rgb.h"           // or another
384 //#include "agg_pattern_filters_rgba.h"  // for all rgba-8-bit color formats
385 //#include "agg_renderer_outline_image.h"
386 //#include "agg_rasterizer_outline_aa.h"
387 
388 
389 agg::pattern_filter_bilinear_rgba8 fltr;          // Filtering functor
390 
391 agg::pattern_pixmap_argb32 patt_src(pixmap_chain); // Source. Must have an interface:
392                                                    // width() const
393                                                    // height() const
394                                                    // pixel(int x, int y) const
395                                                    // Any agg::renderer_base<> or derived
396                                                    // is good for the use as a source.
397 
398 // agg::line_image_pattern is the main container for the patterns. It creates
399 // a copy of the patterns extended according to the needs of the filter.
400 // agg::line_image_pattern can operate with arbitrary image width, but if the
401 // width of the pattern is power of 2, it's better to use the modified
402 // version agg::line_image_pattern_pow2 because it works about 15-25 percent
403 // faster than agg::line_image_pattern (because of using simple masking instead
404 // of expensive '%' operation).
405 typedef agg::line_image_pattern_pow2<agg::pattern_filter_bilinear_rgba8> pattern_type;
406 
407 typedef agg::renderer_base<agg::pixfmt_bgr24> base_ren_type;
408 typedef agg::renderer_outline_image<base_ren_type, pattern_type> renderer_type;
409 typedef agg::rasterizer_outline_aa<renderer_type>                rasterizer_type;
410 
411 //-- Create with specifying the source
412 pattern_type patt(fltr, src);
413 
414 //-- Create uninitialized and set the source
415 //pattern_type patt(fltr);
416 //patt.create(src);
417 
418 agg::pixfmt_bgr24 pixf(rbuf_window()); //or another
419 base_ren_type base_ren(pixf);
420 renderer_type ren(base_ren, patt);
421 //ren.scale_x(1.3);                    // Optional
422 rasterizer_type ras(ren);
423 
424 //-- move_to/line_to interface
425 ras.move_to_d(100, 150);
426 ras.line_to_d(0, 0);
427 ras.line_to_d(300, 200);
428 //ras.line_to_d(10, 10);
429 ras.render(false);     //false means "don't close
430                        //the polygon", i.e. polyline
431 
432 //-- add_path interface
433 //-- doesn't require invoking render()
434 //ras.add_path(some_path);
435 */
436 
437     }
438 
439 
on_idle()440     virtual void on_idle()
441     {
442         m_start_angle += agg::deg2rad(m_step.value());
443         if(m_start_angle > agg::deg2rad(360.0)) m_start_angle -= agg::deg2rad(360.0);
444         force_redraw();
445     }
446 
on_ctrl_change()447     virtual void on_ctrl_change()
448     {
449         wait_mode(!m_rotate.status());
450 
451         if(m_test.status())
452         {
453             on_draw();
454             update_window();
455 
456             pixfmt pf(rbuf_window());
457             renderer_base ren_base(pf);
458             renderer_aa ren_aa(ren_base);
459             renderer_prim ren_prim(ren_base);
460             rasterizer_scanline ras_aa;
461             scanline sl;
462             rasterizer_outline ras_al(ren_prim);
463             agg::line_profile_aa prof;
464             prof.width(m_width.value());
465             renderer_oaa ren_oaa(ren_base, prof);
466             rasterizer_outline_aa ras_oaa(ren_oaa);
467             ras_oaa.line_join(m_accurate_joins.status() ?
468                                   agg::outline_miter_accurate_join :
469                                   agg::outline_round_join);
470             ras_oaa.round_cap(true);
471 
472             pattern_filter filter;
473             agg::pattern_pixmap_argb32 src(pixmap_chain);
474             agg::line_image_scale<agg::pattern_pixmap_argb32> src_scaled(src, m_width.value());
475             image_pattern pattern(filter);
476             if(m_scale_pattern.status())
477             {
478                 pattern.create(src_scaled);
479             }
480             else
481             {
482                 pattern.create(src);
483             }
484             renderer_img ren_img(ren_base, pattern);
485             if(m_scale_pattern.status())
486             {
487                 ren_img.scale_x(src.height() / m_width.value());
488             }
489             rasterizer_outline_img ras_img(ren_img);
490 
491             unsigned i;
492 
493             start_timer();
494             for(i = 0; i < 200; i++)
495             {
496                 draw_aliased_subpix_accuracy(ras_al, ren_prim);
497                 m_start_angle += agg::deg2rad(m_step.value());
498             }
499             double t2 = elapsed_time();
500 
501             start_timer();
502             for(i = 0; i < 200; i++)
503             {
504                 draw_anti_aliased_outline(ras_oaa, ren_oaa);
505                 m_start_angle += agg::deg2rad(m_step.value());
506             }
507             double t3 = elapsed_time();
508 
509             start_timer();
510             for(i = 0; i < 200; i++)
511             {
512                 draw_anti_aliased_scanline(ras_aa, sl, ren_aa);
513                 m_start_angle += agg::deg2rad(m_step.value());
514             }
515             double t4 = elapsed_time();
516 
517             start_timer();
518             for(i = 0; i < 200; i++)
519             {
520                 draw_anti_aliased_outline_img(ras_img, ren_img);
521                 m_start_angle += agg::deg2rad(m_step.value());
522             }
523             double t5 = elapsed_time();
524 
525             m_test.status(false);
526             force_redraw();
527             char buf[256];
528             sprintf(buf, "Aliased=%1.2fms, Anti-Aliased=%1.2fms, Scanline=%1.2fms, Image-Pattern=%1.2fms",
529                           t2, t3, t4, t5);
530             message(buf);
531         }
532     }
533 };
534 
535 
agg_main(int argc,char * argv[])536 int agg_main(int argc, char* argv[])
537 {
538     the_application app(pix_format, flip_y);
539     app.caption("AGG Example. Line Join");
540 
541     if(app.init(500, 450, 0))
542     {
543         return app.run();
544     }
545 
546     return 1;
547 }
548 
549 
550