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