1 #include <math.h>
2 #include <stdio.h>
3 #include "agg_basics.h"
4 #include "agg_rendering_buffer.h"
5 #include "agg_rasterizer_scanline_aa.h"
6 #include "agg_rasterizer_outline.h"
7 #include "agg_conv_stroke.h"
8 #include "agg_conv_dash.h"
9 #include "agg_conv_curve.h"
10 #include "agg_conv_contour.h"
11 #include "agg_conv_marker.h"
12 #include "agg_conv_shorten_path.h"
13 #include "agg_conv_marker_adaptor.h"
14 #include "agg_conv_concat.h"
15 #include "agg_arrowhead.h"
16 #include "agg_vcgen_markers_term.h"
17 #include "agg_scanline_p.h"
18 #include "agg_scanline_u.h"
19 #include "agg_renderer_scanline.h"
20 #include "agg_renderer_primitives.h"
21 #include "agg_span_allocator.h"
22 #include "agg_span_gradient.h"
23 #include "agg_span_interpolator_linear.h"
24 #include "agg_pixfmt_rgb.h"
25 #include "ctrl/agg_slider_ctrl.h"
26 #include "ctrl/agg_rbox_ctrl.h"
27 #include "ctrl/agg_cbox_ctrl.h"
28 #include "platform/agg_platform_support.h"
29 
30 enum flip_y_e { flip_y = true };
31 
32 
33 typedef agg::pixfmt_bgr24 pixfmt;
34 typedef pixfmt::color_type color_type;
35 typedef agg::renderer_base<pixfmt> base_renderer;
36 typedef agg::renderer_primitives<base_renderer> primitives_renderer;
37 
38 typedef agg::renderer_scanline_aa_solid<base_renderer>  solid_renderer;
39 typedef agg::renderer_scanline_bin_solid<base_renderer> draft_renderer;
40 
41 typedef agg::gradient_radial_d gradient_function;
42 typedef agg::span_interpolator_linear<> interpolator;
43 typedef agg::pod_auto_array<color_type, 256> color_array_type;
44 typedef agg::span_gradient<color_type,
45                            interpolator,
46                            gradient_function,
47                            color_array_type> gradient_span_gen;
48 typedef agg::span_allocator<color_type> gradient_span_alloc;
49 
50 typedef agg::renderer_scanline_aa<base_renderer,
51                                   gradient_span_alloc,
52                                   gradient_span_gen> gradient_renderer;
53 
54 typedef agg::rasterizer_scanline_aa<> scanline_rasterizer;
55 typedef agg::rasterizer_outline<primitives_renderer> outline_rasterizer;
56 
57 
58 
59 //============================================================================
60 class graph
61 {
62 public:
63     struct node
64     {
65         double x, y;
nodegraph::node66         node() {}
nodegraph::node67         node(double x_, double y_) : x(x_), y(y_) {}
68     };
69 
70     struct edge
71     {
72         int node1;
73         int node2;
edgegraph::edge74         edge() {}
edgegraph::edge75         edge(int n1, int n2) : node1(n1), node2(n2) {}
76     };
77 
~graph()78 	~graph()
79     {
80         delete [] m_edges;
81         delete [] m_nodes;
82     }
83 
graph(int num_nodes,int num_edges)84     graph(int num_nodes, int num_edges) :
85         m_num_nodes(num_nodes),
86         m_num_edges(num_edges),
87         m_nodes(new node[num_nodes]),
88         m_edges(new edge[num_edges])
89     {
90         int i;
91 
92 	    srand(100);
93 
94 	    for(i = 0; i < m_num_nodes; i++)
95         {
96             m_nodes[i].x = (double(rand()) / RAND_MAX) * 0.75 + 0.2;
97             m_nodes[i].y = (double(rand()) / RAND_MAX) * 0.85 + 0.1;
98         }
99 
100 	    for(i = 0; i < m_num_edges; i++)
101         {
102             m_edges[i].node1 = rand() % m_num_nodes;
103             m_edges[i].node2 = rand() % m_num_nodes;
104             if(m_edges[i].node1 == m_edges[i].node2) i--;
105         }
106     }
107 
get_num_nodes() const108     int get_num_nodes() const { return m_num_nodes; }
get_num_edges() const109     int get_num_edges() const { return m_num_edges; }
110 
get_node(int idx,double w,double h) const111 	node get_node(int idx, double w, double h) const
112     {
113         node p(0.0, 0.0);
114         if(idx < m_num_nodes)
115         {
116             p = m_nodes[idx];
117             p.x = p.x * w;
118             p.y = p.y * h;
119         }
120         return p;
121     }
122 
get_edge(int idx) const123 	edge get_edge(int idx) const
124     {
125         edge b(0,0);
126         if(idx < m_num_edges)
127         {
128             b = m_edges[idx];
129         }
130         return b;
131     }
132 
133 private:
134     graph(const graph&);
135     const graph& operator = (const graph&);
136 
137     int m_num_nodes;
138     int m_num_edges;
139     node* m_nodes;
140     edge* m_edges;
141 };
142 
143 
144 
145 
146 
147 
148 
149 
150 
151 //============================================================================
152 struct line
153 {
154     double x1, y1, x2, y2;
155     int f;
156 
lineline157     line(double x1_, double y1_, double x2_, double y2_) :
158         x1(x1_), y1(y1_), x2(x2_), y2(y2_), f(0) {}
159 
rewindline160     void rewind(unsigned) { f = 0; }
vertexline161     unsigned vertex(double* x, double* y)
162     {
163         if(f == 0) { ++f; *x = x1; *y = y1; return agg::path_cmd_move_to; }
164         if(f == 1) { ++f; *x = x2; *y = y2; return agg::path_cmd_line_to; }
165         return agg::path_cmd_stop;
166     }
167 };
168 
169 
170 
171 
172 //============================================================================
173 struct curve
174 {
175     agg::curve4 c;
176 
curvecurve177     curve(double x1, double y1, double x2, double y2, double k=0.5)
178     {
179         c.init(x1, y1,
180                x1 - (y2 - y1) * k,
181                y1 + (x2 - x1) * k,
182                x2 + (y2 - y1) * k,
183                y2 - (x2 - x1) * k,
184                x2, y2);
185     }
186 
rewindcurve187     void rewind(unsigned path_id) { c.rewind(path_id); }
vertexcurve188     unsigned vertex(double* x, double* y) { return c.vertex(x, y); }
189 };
190 
191 
192 
193 //============================================================================
194 template<class Source> struct stroke_draft_simple
195 {
196     Source& s;
stroke_draft_simplestroke_draft_simple197     stroke_draft_simple(Source& src, double w) :
198         s(src)
199     {
200     }
201 
rewindstroke_draft_simple202     void rewind(unsigned path_id) { s.rewind(path_id); }
vertexstroke_draft_simple203     unsigned vertex(double* x, double* y) { return s.vertex(x, y); }
204 };
205 
206 
207 //============================================================================
208 template<class Source> struct stroke_draft_arrow
209 {
210     typedef agg::conv_marker_adaptor<Source, agg::vcgen_markers_term>           stroke_type;
211     typedef agg::conv_marker<typename stroke_type::marker_type, agg::arrowhead> marker_type;
212     typedef agg::conv_concat<stroke_type, marker_type>                          concat_type;
213 
214     stroke_type    s;
215     agg::arrowhead ah;
216     marker_type    m;
217     concat_type    c;
218 
stroke_draft_arrowstroke_draft_arrow219     stroke_draft_arrow(Source& src, double w) :
220         s(src),
221         ah(),
222         m(s.markers(), ah),
223         c(s, m)
224     {
225         ah.head(0, 10, 5, 0);
226         s.shorten(10.0);
227     }
228 
rewindstroke_draft_arrow229     void rewind(unsigned path_id) { c.rewind(path_id); }
vertexstroke_draft_arrow230     unsigned vertex(double* x, double* y) { return c.vertex(x, y); }
231 };
232 
233 
234 
235 //============================================================================
236 template<class Source> struct stroke_fine_simple
237 {
238     typedef agg::conv_stroke<Source> stroke_type;
239 
240     stroke_type    s;
241 
stroke_fine_simplestroke_fine_simple242     stroke_fine_simple(Source& src, double w) :
243         s(src)
244     {
245         s.width(w);
246     }
rewindstroke_fine_simple247     void rewind(unsigned path_id) { s.rewind(path_id); }
vertexstroke_fine_simple248     unsigned vertex(double* x, double* y) { return s.vertex(x, y); }
249 };
250 
251 
252 
253 //============================================================================
254 template<class Source> struct stroke_fine_arrow
255 {
256     typedef agg::conv_stroke<Source, agg::vcgen_markers_term>                   stroke_type;
257     typedef agg::conv_marker<typename stroke_type::marker_type, agg::arrowhead> marker_type;
258     typedef agg::conv_concat<stroke_type, marker_type>                          concat_type;
259 
260     stroke_type    s;
261     agg::arrowhead ah;
262     marker_type    m;
263     concat_type    c;
264 
stroke_fine_arrowstroke_fine_arrow265     stroke_fine_arrow(Source& src, double w) :
266         s(src),
267         ah(),
268         m(s.markers(), ah),
269         c(s, m)
270     {
271         s.width(w);
272         ah.head(0, 10, 5, 0);
273         s.shorten(w * 2.0);
274     }
275 
rewindstroke_fine_arrow276     void rewind(unsigned path_id) { c.rewind(path_id); }
vertexstroke_fine_arrow277     unsigned vertex(double* x, double* y) { return c.vertex(x, y); }
278 };
279 
280 
281 
282 //============================================================================
283 template<class Source> struct dash_stroke_draft_simple
284 {
285     typedef agg::conv_dash<Source, agg::vcgen_markers_term> dash_type;
286 
287     dash_type d;
288 
dash_stroke_draft_simpledash_stroke_draft_simple289     dash_stroke_draft_simple(Source& src,
290                              double dash_len,
291                              double gap_len,
292                              double w) :
293         d(src)
294     {
295         d.add_dash(dash_len, gap_len);
296     }
297 
rewinddash_stroke_draft_simple298     void rewind(unsigned path_id) { d.rewind(path_id); }
vertexdash_stroke_draft_simple299     unsigned vertex(double* x, double* y) { return d.vertex(x, y); }
300 };
301 
302 
303 //============================================================================
304 template<class Source> struct dash_stroke_draft_arrow
305 {
306     typedef agg::conv_dash<Source, agg::vcgen_markers_term>                   dash_type;
307     typedef agg::conv_marker<typename dash_type::marker_type, agg::arrowhead> marker_type;
308     typedef agg::conv_concat<dash_type, marker_type>                          concat_type;
309 
310     dash_type      d;
311     agg::arrowhead ah;
312     marker_type    m;
313     concat_type    c;
314 
dash_stroke_draft_arrowdash_stroke_draft_arrow315     dash_stroke_draft_arrow(Source& src,
316                             double dash_len, double gap_len, double w) :
317         d(src),
318         ah(),
319         m(d.markers(), ah),
320         c(d, m)
321     {
322         d.add_dash(dash_len, gap_len);
323         ah.head(0, 10, 5, 0);
324         d.shorten(10.0);
325     }
326 
rewinddash_stroke_draft_arrow327     void rewind(unsigned path_id) { c.rewind(path_id); }
vertexdash_stroke_draft_arrow328     unsigned vertex(double* x, double* y) { return c.vertex(x, y); }
329 };
330 
331 
332 
333 
334 //============================================================================
335 template<class Source> struct dash_stroke_fine_simple
336 {
337     typedef agg::conv_dash<Source>       dash_type;
338     typedef agg::conv_stroke<dash_type>  stroke_type;
339 
340     dash_type      d;
341     stroke_type    s;
342 
dash_stroke_fine_simpledash_stroke_fine_simple343     dash_stroke_fine_simple(Source& src,
344                            double dash_len, double gap_len, double w) :
345         d(src),
346         s(d)
347     {
348         d.add_dash(dash_len, gap_len);
349         s.width(w);
350     }
351 
rewinddash_stroke_fine_simple352     void rewind(unsigned path_id) { s.rewind(path_id); }
vertexdash_stroke_fine_simple353     unsigned vertex(double* x, double* y) { return s.vertex(x, y); }
354 };
355 
356 
357 
358 
359 
360 
361 //============================================================================
362 template<class Source> struct dash_stroke_fine_arrow
363 {
364     typedef agg::conv_dash<Source, agg::vcgen_markers_term>                   dash_type;
365     typedef agg::conv_stroke<dash_type>                                       stroke_type;
366     typedef agg::conv_marker<typename dash_type::marker_type, agg::arrowhead> marker_type;
367     typedef agg::conv_concat<stroke_type, marker_type>                        concat_type;
368 
369     dash_type      d;
370     stroke_type    s;
371     agg::arrowhead ah;
372     marker_type    m;
373     concat_type    c;
374 
dash_stroke_fine_arrowdash_stroke_fine_arrow375     dash_stroke_fine_arrow(Source& src,
376                            double dash_len, double gap_len, double w) :
377         d(src),
378         s(d),
379         ah(),
380         m(d.markers(), ah),
381         c(s, m)
382     {
383         d.add_dash(dash_len, gap_len);
384         s.width(w);
385         ah.head(0, 10, 5, 0);
386         d.shorten(w * 2.0);
387     }
388 
rewinddash_stroke_fine_arrow389     void rewind(unsigned path_id) { c.rewind(path_id); }
vertexdash_stroke_fine_arrow390     unsigned vertex(double* x, double* y) { return c.vertex(x, y); }
391 };
392 
393 
394 
395 //#define stroke_draft      stroke_draft_simple
396 //#define dash_stroke_draft dash_stroke_draft_simple
397 //#define stroke_fine       stroke_fine_simple
398 //#define dash_stroke_fine  dash_stroke_fine_simple
399 
400 #define stroke_draft      stroke_draft_arrow
401 #define dash_stroke_draft dash_stroke_draft_arrow
402 #define stroke_fine       stroke_fine_arrow
403 #define dash_stroke_fine  dash_stroke_fine_arrow
404 
405 
406 
407 
408 
409 class the_application : public agg::platform_support
410 {
411     agg::rbox_ctrl<agg::rgba>   m_type;
412     agg::slider_ctrl<agg::rgba> m_width;
413     agg::cbox_ctrl<agg::rgba>   m_benchmark;
414     agg::cbox_ctrl<agg::rgba>   m_draw_nodes;
415     agg::cbox_ctrl<agg::rgba>   m_draw_edges;
416     agg::cbox_ctrl<agg::rgba>   m_draft;
417     agg::cbox_ctrl<agg::rgba>   m_translucent;
418     graph                       m_graph;
419     color_array_type            m_gradient_colors;
420     int                         m_draw;
421     agg::scanline_u8            m_sl;
422 
423 
424 public:
the_application(agg::pix_format_e format,bool flip_y)425     the_application(agg::pix_format_e format, bool flip_y) :
426         agg::platform_support(format, flip_y),
427         m_type(-1, -1, -1, -1, !flip_y),
428         m_width(110+80, 8.0, 110+200.0+80, 8.0 + 7.0, !flip_y),
429         m_benchmark(110+200+80+8, 8.0-2.0, "Benchmark", !flip_y),
430         m_draw_nodes(110+200+80+8, 8.0-2.0+15.0, "Draw Nodes", !flip_y),
431         m_draw_edges(200+200+80+8, 8.0-2.0+15.0, "Draw Edges", !flip_y),
432         m_draft(200+200+80+8, 8.0-2.0, "Draft Mode", !flip_y),
433         m_translucent(110+80, 8.0-2.0+15.0, "Translucent Mode", !flip_y),
434         m_graph(200, 100),
435         m_gradient_colors(),
436         m_draw(3)
437     {
438         add_ctrl(m_type);
439         m_type.text_size(8.0);
440         m_type.add_item("Solid lines");
441         m_type.add_item("Bezier curves");
442         m_type.add_item("Dashed curves");
443         m_type.add_item("Poygons AA");
444         m_type.add_item("Poygons Bin");
445         m_type.cur_item(0);
446 
447         add_ctrl(m_width);
448         m_width.num_steps(20);
449         m_width.range(0.0, 5.0);
450         m_width.value(2.0);
451         m_width.label("Width=%1.2f");
452 
453         m_benchmark.text_size(8.0);
454         m_draw_nodes.text_size(8.0);
455         m_draft.text_size(8.0);
456         m_draw_nodes.status(true);
457         m_draw_edges.status(true);
458         add_ctrl(m_benchmark);
459         add_ctrl(m_draw_nodes);
460         add_ctrl(m_draw_edges);
461         add_ctrl(m_draft);
462         add_ctrl(m_translucent);
463 
464         agg::rgba c1(1, 1, 0, 0.25);
465         agg::rgba c2(0, 0, 1);
466 
467         int i;
468         for(i = 0; i < 256; i++)
469         {
470             m_gradient_colors[i] = c1.gradient(c2, double(i) / 255.0);
471         }
472     }
473 
474 
475 
476 
477 
478 
479     //------------------------------------------------------------------------
draw_nodes_draft()480     void draw_nodes_draft()
481     {
482         pixfmt pixf(rbuf_window());
483         base_renderer rb(pixf);
484         primitives_renderer prim(rb);
485         int i;
486         for(i = 0; i < m_graph.get_num_nodes(); i++)
487         {
488             graph::node n = m_graph.get_node(i, width(), height());
489             prim.fill_color(m_gradient_colors[147]);
490             prim.line_color(m_gradient_colors[255]);
491             prim.outlined_ellipse(int(n.x), int(n.y), 10, 10);
492             prim.fill_color(m_gradient_colors[50]);
493             prim.solid_ellipse(int(n.x), int(n.y), 4, 4);
494         }
495     }
496 
497 
498 
499     //------------------------------------------------------------------------
draw_nodes_fine(scanline_rasterizer & ras)500     void draw_nodes_fine(scanline_rasterizer& ras)
501     {
502         gradient_span_alloc sa;
503         pixfmt pixf(rbuf_window());
504         base_renderer rb(pixf);
505         int i;
506         for(i = 0; i < m_graph.get_num_nodes(); i++)
507         {
508             graph::node n = m_graph.get_node(i, width(), height());
509             agg::ellipse ell(n.x, n.y, 5.0 * m_width.value(), 5.0 * m_width.value());
510 
511             double x, y;
512             switch(m_draw)
513             {
514                 case 0:
515                     ell.rewind(0);
516                     while(!agg::is_stop(ell.vertex(&x, &y)));
517                     break;
518 
519                 case 1:
520                     ras.reset();
521                     ras.add_path(ell);
522                     break;
523 
524                 case 2:
525                     ras.reset();
526                     ras.add_path(ell);
527                     ras.sort();
528                     break;
529 
530                 case 3:
531                 {
532                     gradient_function gf;
533                     agg::trans_affine mtx;
534                     mtx *= agg::trans_affine_scaling(m_width.value() / 2.0);
535                     mtx *= agg::trans_affine_translation(n.x, n.y);
536                     mtx.invert();
537                     interpolator inter(mtx);
538                     gradient_span_gen sg(inter, gf, m_gradient_colors, 0.0, 10.0);
539                     gradient_renderer ren(rb, sa, sg);
540                     ras.add_path(ell);
541                     agg::render_scanlines(ras, m_sl, ren);
542                 }
543                 break;
544             }
545         }
546     }
547 
548 
549 
550 
551 
552     //------------------------------------------------------------------------
553     template<class Source>
render_edge_fine(scanline_rasterizer & ras,solid_renderer & ren_fine,draft_renderer & ren_draft,Source & src)554     void render_edge_fine(scanline_rasterizer& ras,
555                           solid_renderer& ren_fine,
556                           draft_renderer& ren_draft,
557                           Source& src)
558     {
559         double x, y;
560         switch(m_draw)
561         {
562             case 0:
563                 src.rewind(0);
564                 while(!agg::is_stop(src.vertex(&x, &y)));
565             break;
566 
567             case 1:
568                 ras.reset();
569                 ras.add_path(src);
570             break;
571 
572             case 2:
573                 ras.reset();
574                 ras.add_path(src);
575                 ras.sort();
576             break;
577 
578             case 3:
579             {
580                 int r = rand() & 0x7F;
581                 int g = rand() & 0x7F;
582                 int b = rand() & 0x7F;
583                 int a = 255;
584                 if(m_translucent.status()) a = 80;
585                 ras.add_path(src);
586 
587                 if(m_type.cur_item() < 4)
588                 {
589                     ren_fine.color(agg::rgba8(r, g, b, a));
590                     agg::render_scanlines(ras, m_sl, ren_fine);
591                 }
592                 else
593                 {
594                     ren_draft.color(agg::rgba8(r, g, b, a));
595                     agg::render_scanlines(ras, m_sl, ren_draft);
596                 }
597             }
598             break;
599         }
600     }
601 
602 
603 
604     //------------------------------------------------------------------------
draw_lines_draft()605     void draw_lines_draft()
606     {
607         pixfmt pixf(rbuf_window());
608         base_renderer rb(pixf);
609         primitives_renderer prim(rb);
610         outline_rasterizer ras(prim);
611 
612         int i;
613         for(i = 0; i < m_graph.get_num_edges(); i++)
614         {
615             graph::edge e  = m_graph.get_edge(i);
616             graph::node n1 = m_graph.get_node(e.node1, width(), height());
617             graph::node n2 = m_graph.get_node(e.node2, width(), height());
618             line l(n1.x, n1.y, n2.x, n2.y);
619             stroke_draft<line> s(l, m_width.value());
620 
621             int r = rand() & 0x7F;
622             int g = rand() & 0x7F;
623             int b = rand() & 0x7F;
624             int a = 255;
625             if(m_translucent.status()) a = 80;
626             prim.line_color(agg::rgba8(r, g, b, a));
627             ras.add_path(s);
628         }
629     }
630 
631 
632     //------------------------------------------------------------------------
draw_curves_draft()633     void draw_curves_draft()
634     {
635         pixfmt pixf(rbuf_window());
636         base_renderer rb(pixf);
637         primitives_renderer prim(rb);
638         outline_rasterizer ras(prim);
639 
640         int i;
641         for(i = 0; i < m_graph.get_num_edges(); i++)
642         {
643             graph::edge e  = m_graph.get_edge(i);
644             graph::node n1 = m_graph.get_node(e.node1, width(), height());
645             graph::node n2 = m_graph.get_node(e.node2, width(), height());
646             curve c(n1.x, n1.y, n2.x, n2.y);
647             stroke_draft<curve> s(c, m_width.value());
648 
649             int r = rand() & 0x7F;
650             int g = rand() & 0x7F;
651             int b = rand() & 0x7F;
652             int a = 255;
653             if(m_translucent.status()) a = 80;
654             prim.line_color(agg::rgba8(r, g, b, a));
655             ras.add_path(s);
656         }
657     }
658 
659 
660     //------------------------------------------------------------------------
draw_dashes_draft()661     void draw_dashes_draft()
662     {
663         pixfmt pixf(rbuf_window());
664         base_renderer rb(pixf);
665         primitives_renderer prim(rb);
666         outline_rasterizer ras(prim);
667 
668         int i;
669         for(i = 0; i < m_graph.get_num_edges(); i++)
670         {
671             graph::edge e  = m_graph.get_edge(i);
672             graph::node n1 = m_graph.get_node(e.node1, width(), height());
673             graph::node n2 = m_graph.get_node(e.node2, width(), height());
674             curve c(n1.x, n1.y, n2.x, n2.y);
675             dash_stroke_draft<curve> s(c, 6.0, 3.0, m_width.value());
676 
677             int r = rand() & 0x7F;
678             int g = rand() & 0x7F;
679             int b = rand() & 0x7F;
680             int a = 255;
681             if(m_translucent.status()) a = 80;
682             prim.line_color(agg::rgba8(r, g, b, a));
683             ras.add_path(s);
684         }
685     }
686 
687 
688     //------------------------------------------------------------------------
draw_lines_fine(scanline_rasterizer & ras,solid_renderer & solid,draft_renderer & draft)689     void draw_lines_fine(scanline_rasterizer& ras,
690                          solid_renderer& solid,
691                          draft_renderer& draft)
692     {
693         int i;
694         for(i = 0; i < m_graph.get_num_edges(); i++)
695         {
696             graph::edge b  = m_graph.get_edge(i);
697             graph::node n1 = m_graph.get_node(b.node1, width(), height());
698             graph::node n2 = m_graph.get_node(b.node2, width(), height());
699             line l(n1.x, n1.y, n2.x, n2.y);
700             stroke_fine<line> s(l, m_width.value());
701             render_edge_fine(ras, solid, draft, s);
702         }
703     }
704 
705 
706     //------------------------------------------------------------------------
draw_curves_fine(scanline_rasterizer & ras,solid_renderer & solid,draft_renderer & draft)707     void draw_curves_fine(scanline_rasterizer& ras,
708                           solid_renderer& solid,
709                           draft_renderer& draft)
710 
711     {
712         int i;
713         for(i = 0; i < m_graph.get_num_edges(); i++)
714         {
715             graph::edge b  = m_graph.get_edge(i);
716             graph::node n1 = m_graph.get_node(b.node1, width(), height());
717             graph::node n2 = m_graph.get_node(b.node2, width(), height());
718             curve c(n1.x, n1.y, n2.x, n2.y);
719             stroke_fine<curve> s(c, m_width.value());
720             render_edge_fine(ras, solid, draft, s);
721         }
722     }
723 
724 
725     //------------------------------------------------------------------------
draw_dashes_fine(scanline_rasterizer & ras,solid_renderer & solid,draft_renderer & draft)726     void draw_dashes_fine(scanline_rasterizer& ras,
727                           solid_renderer& solid,
728                           draft_renderer& draft)
729     {
730         int i;
731         for(i = 0; i < m_graph.get_num_edges(); i++)
732         {
733             graph::edge b  = m_graph.get_edge(i);
734             graph::node n1 = m_graph.get_node(b.node1, width(), height());
735             graph::node n2 = m_graph.get_node(b.node2, width(), height());
736             curve c(n1.x, n1.y, n2.x, n2.y);
737             dash_stroke_fine<curve> s(c, 6.0, 3.0, m_width.value());
738             render_edge_fine(ras, solid, draft, s);
739         }
740     }
741 
742 
743     //------------------------------------------------------------------------
draw_polygons(scanline_rasterizer & ras,solid_renderer & solid,draft_renderer & draft)744     void draw_polygons(scanline_rasterizer& ras,
745                        solid_renderer& solid,
746                        draft_renderer& draft)
747     {
748         int i;
749         if(m_type.cur_item() == 4)
750         {
751             ras.gamma(agg::gamma_threshold(0.5));
752         }
753         for(i = 0; i < m_graph.get_num_edges(); i++)
754         {
755             graph::edge b  = m_graph.get_edge(i);
756             graph::node n1 = m_graph.get_node(b.node1, width(), height());
757             graph::node n2 = m_graph.get_node(b.node2, width(), height());
758             curve c(n1.x, n1.y, n2.x, n2.y);
759             render_edge_fine(ras, solid, draft, c);
760         }
761         ras.gamma(agg::gamma_none());
762     }
763 
764 
765 
766     //------------------------------------------------------------------------
draw_scene(scanline_rasterizer & ras,solid_renderer & solid,draft_renderer & draft)767     void draw_scene(scanline_rasterizer& ras,
768                     solid_renderer& solid,
769                     draft_renderer& draft)
770     {
771         ras.gamma(agg::gamma_none());
772         srand(100);
773         if(m_draw_nodes.status())
774         {
775             if(m_draft.status())
776             {
777                 draw_nodes_draft();
778             }
779             else
780             {
781                 draw_nodes_fine(ras);
782             }
783         }
784 
785         if(m_draw_edges.status())
786         {
787             if(m_draft.status())
788             {
789                 switch(m_type.cur_item())
790                 {
791                 case 0: draw_lines_draft();    break;
792                 case 1: draw_curves_draft();   break;
793                 case 2: draw_dashes_draft();   break;
794                 }
795             }
796             else
797             {
798                 switch(m_type.cur_item())
799                 {
800                 case 0: draw_lines_fine(ras, solid, draft);  break;
801                 case 1: draw_curves_fine(ras, solid, draft); break;
802                 case 2: draw_dashes_fine(ras, solid, draft); break;
803                 case 3:
804                 case 4: draw_polygons(ras, solid, draft);    break;
805                 }
806             }
807         }
808     }
809 
810 
811 
812 
813 
814 
815 
816 
817 
818 
819 
820 
821     //------------------------------------------------------------------------
on_draw()822     virtual void on_draw()
823     {
824         scanline_rasterizer ras;
825 
826         pixfmt pixf(rbuf_window());
827         base_renderer rb(pixf);
828         solid_renderer solid(rb);
829         draft_renderer draft(rb);
830 
831         rb.clear(agg::rgba(1, 1, 1));
832         draw_scene(ras, solid, draft);
833 
834         ras.filling_rule(agg::fill_non_zero);
835         agg::render_ctrl(ras, m_sl, rb, m_type);
836         agg::render_ctrl(ras, m_sl, rb, m_width);
837         agg::render_ctrl(ras, m_sl, rb, m_benchmark);
838         agg::render_ctrl(ras, m_sl, rb, m_draw_nodes);
839         agg::render_ctrl(ras, m_sl, rb, m_draw_edges);
840         agg::render_ctrl(ras, m_sl, rb, m_draft);
841         agg::render_ctrl(ras, m_sl, rb, m_translucent);
842     }
843 
844 
845 
846 
on_ctrl_change()847     virtual void on_ctrl_change()
848     {
849         if(m_benchmark.status())
850         {
851             int i;
852             on_draw();
853             update_window();
854 
855             scanline_rasterizer ras;
856 
857             pixfmt pixf(rbuf_window());
858             base_renderer rb(pixf);
859             solid_renderer solid(rb);
860             draft_renderer draft(rb);
861 
862             char buf[256];
863             if(m_draft.status())
864             {
865                 start_timer();
866                 for(i = 0; i < 10; i++)
867                 {
868                     draw_scene(ras, solid, draft);
869                 }
870                 sprintf(buf, "%3.3f milliseconds", elapsed_time());
871             }
872             else
873             {
874                 double times[5];
875                 for(m_draw = 0; m_draw < 4; m_draw++)
876                 {
877                     start_timer();
878                     for(i = 0; i < 10; i++)
879                     {
880                         draw_scene(ras, solid, draft);
881                     }
882                     times[m_draw] = elapsed_time();
883                 }
884                 m_draw = 3;
885 
886                 times[4]  = times[3];
887                 times[3] -= times[2];
888                 times[2] -= times[1];
889                 times[1] -= times[0];
890 
891                 FILE* fd = fopen(full_file_name("benchmark"), "a");
892                 fprintf(fd, "%10.3f %10.3f %10.3f %10.3f %10.3f\n",
893                             times[0], times[1], times[2], times[3], times[4]);
894                 fclose(fd);
895 
896 
897                 sprintf(buf, "  pipeline  add_path         sort       render       total\n"
898                              "%10.3f %10.3f %10.3f %10.3f %10.3f",
899                         times[0], times[1], times[2], times[3], times[4]);
900             }
901             message(buf);
902 
903             m_benchmark.status(false);
904             force_redraw();
905         }
906     }
907 };
908 
909 
910 
agg_main(int argc,char * argv[])911 int agg_main(int argc, char* argv[])
912 {
913     the_application app(agg::pix_format_bgr24, flip_y);
914     app.caption("AGG Example. Line Join");
915 
916     if(app.init(600+100, 500+30, agg::window_resize))
917     {
918         return app.run();
919     }
920     return 1;
921 }
922 
923 
924