00001 #include <stdio.h>
00002 #include "agg_rendering_buffer.h"
00003 #include "agg_renderer_base.h"
00004 #include "agg_rasterizer_scanline_aa.h"
00005 #include "agg_scanline_u.h"
00006 #include "agg_renderer_scanline.h"
00007 #include "agg_rounded_rect.h"
00008 #include "agg_pixfmt_rgba.h"
00009 #include "agg_span_allocator.h"
00010 #include "agg_span_gradient.h"
00011 #include "agg_gsv_text.h"
00012 #include "agg_span_interpolator_linear.h"
00013 #include "platform/agg_platform_support.h"
00014 #include "ctrl/agg_slider_ctrl.h"
00015 #include "ctrl/agg_rbox_ctrl.h"
00016
00017
00018 enum flip_y_e { flip_y = true };
00019
00020 typedef agg::rgba8 color;
00021 typedef agg::order_bgra order;
00022 typedef agg::int32u pixel_type;
00023 typedef agg::rendering_buffer rbuf_type;
00024 #define pix_format agg::pix_format_bgra32
00025
00026 typedef agg::blender_rgba<color, order> prim_blender_type;
00027 typedef agg::pixfmt_alpha_blend_rgba<prim_blender_type, rbuf_type> prim_pixfmt_type;
00028 typedef agg::renderer_base<prim_pixfmt_type> prim_ren_base_type;
00029
00030 void force_comp_op_link()
00031 {
00032
00033
00034 agg::int8u p[4] = {0};
00035 agg::comp_op_rgba_contrast <color, order>::blend_pix(p,0,0,0,0,0);
00036 agg::comp_op_rgba_darken <color, order>::blend_pix(p,0,0,0,0,0);
00037 agg::comp_op_rgba_lighten <color, order>::blend_pix(p,0,0,0,0,0);
00038 agg::comp_op_rgba_color_dodge<color, order>::blend_pix(p,0,0,0,0,0);
00039 agg::comp_op_rgba_color_burn <color, order>::blend_pix(p,0,0,0,0,0);
00040 agg::comp_op_rgba_hard_light <color, order>::blend_pix(p,0,0,0,0,0);
00041 agg::comp_op_rgba_soft_light <color, order>::blend_pix(p,0,0,0,0,0);
00042 agg::comp_op_rgba_difference <color, order>::blend_pix(p,0,0,0,0,0);
00043 agg::comp_op_rgba_exclusion <color, order>::blend_pix(p,0,0,0,0,0);
00044 agg::comp_op_rgba_src_atop <color, order>::blend_pix(p,0,0,0,0,0);
00045 agg::comp_op_rgba_dst_atop <color, order>::blend_pix(p,0,0,0,0,0);
00046 agg::comp_op_rgba_xor <color, order>::blend_pix(p,0,0,0,0,0);
00047 agg::comp_op_rgba_plus <color, order>::blend_pix(p,0,0,0,0,0);
00048 agg::comp_op_rgba_minus <color, order>::blend_pix(p,0,0,0,0,0);
00049 agg::comp_op_rgba_multiply <color, order>::blend_pix(p,0,0,0,0,0);
00050 agg::comp_op_rgba_screen <color, order>::blend_pix(p,0,0,0,0,0);
00051 agg::comp_op_rgba_overlay <color, order>::blend_pix(p,0,0,0,0,0);
00052 agg::comp_op_rgba_src <color, order>::blend_pix(p,0,0,0,0,0);
00053 agg::comp_op_rgba_dst <color, order>::blend_pix(p,0,0,0,0,0);
00054 agg::comp_op_rgba_src_over <color, order>::blend_pix(p,0,0,0,0,0);
00055 agg::comp_op_rgba_dst_over <color, order>::blend_pix(p,0,0,0,0,0);
00056 agg::comp_op_rgba_src_in <color, order>::blend_pix(p,0,0,0,0,0);
00057 agg::comp_op_rgba_dst_in <color, order>::blend_pix(p,0,0,0,0,0);
00058 agg::comp_op_rgba_src_out <color, order>::blend_pix(p,0,0,0,0,0);
00059 agg::comp_op_rgba_dst_out <color, order>::blend_pix(p,0,0,0,0,0);
00060 agg::comp_op_rgba_clear <color, order>::blend_pix(p,0,0,0,0,0);
00061 }
00062
00063 namespace agg
00064 {
00065
00066
00067 template<> struct gradient_linear_color<color>
00068 {
00069 typedef color color_type;
00070 enum base_scale_e { base_shift = color_type::base_shift };
00071
00072 gradient_linear_color() {}
00073 gradient_linear_color(const color_type& c1, const color_type& c2) :
00074 m_c1(c1), m_c2(c2) {}
00075
00076 static unsigned size() { return 256; }
00077 color_type operator [] (unsigned v) const
00078 {
00079 color_type c;
00080 typedef color_type::value_type value_type;
00081 v <<= base_shift - 8;
00082 c.r = (value_type)((((m_c2.r - m_c1.r) * v) + (m_c1.r << base_shift)) >> base_shift);
00083 c.g = (value_type)((((m_c2.g - m_c1.g) * v) + (m_c1.g << base_shift)) >> base_shift);
00084 c.b = (value_type)((((m_c2.b - m_c1.b) * v) + (m_c1.b << base_shift)) >> base_shift);
00085 c.a = (value_type)((((m_c2.a - m_c1.a) * v) + (m_c1.a << base_shift)) >> base_shift);
00086 return c;
00087 }
00088
00089 void colors(const color_type& c1, const color_type& c2)
00090 {
00091 m_c1 = c1;
00092 m_c2 = c2;
00093 }
00094
00095 color_type m_c1;
00096 color_type m_c2;
00097 };
00098
00099 }
00100
00101
00102
00103
00104 agg::trans_affine gradient_affine(double x1, double y1, double x2, double y2,
00105 double gradient_d2 = 100.0)
00106 {
00107 agg::trans_affine mtx;
00108 double dx = x2 - x1;
00109 double dy = y2 - y1;
00110 mtx.reset();
00111 mtx *= agg::trans_affine_scaling(sqrt(dx * dx + dy * dy) / gradient_d2);
00112 mtx *= agg::trans_affine_rotation(atan2(dy, dx));
00113 mtx *= agg::trans_affine_translation(x1, y1);
00114 mtx.invert();
00115 return mtx;
00116 }
00117
00118
00119
00120 template<class RenBase>
00121 void circle(RenBase& rbase, color c1, color c2,
00122 double x1, double y1, double x2, double y2,
00123 double shadow_alpha)
00124 {
00125 typedef RenBase renderer_base_type;
00126 typedef agg::gradient_x gradient_func_type;
00127 typedef agg::gradient_linear_color<color> color_func_type;
00128 typedef agg::span_interpolator_linear<> interpolator_type;
00129 typedef agg::span_allocator<color> span_allocator_type;
00130 typedef agg::span_gradient<color,
00131 interpolator_type,
00132 gradient_func_type,
00133 color_func_type> span_gradient_type;
00134
00135 gradient_func_type gradient_func;
00136 agg::trans_affine gradient_mtx = gradient_affine(x1, y1, x2, y2, 100);
00137 interpolator_type span_interpolator(gradient_mtx);
00138 span_allocator_type span_allocator;
00139 color_func_type color_func(c1, c2);
00140 span_gradient_type span_gradient(span_interpolator,
00141 gradient_func,
00142 color_func,
00143 0, 100);
00144 agg::rasterizer_scanline_aa<> ras;
00145 agg::scanline_u8 sl;
00146
00147 double r = agg::calc_distance(x1, y1, x2, y2) / 2;
00148 agg::ellipse ell((x1+x2)/2+5, (y1+y2)/2-3, r, r, 100);
00149
00150 ras.add_path(ell);
00151 agg::render_scanlines_aa_solid(ras, sl, rbase,
00152 agg::rgba(0.6, 0.6, 0.6, 0.7*shadow_alpha));
00153
00154 ell.init((x1+x2)/2, (y1+y2)/2, r, r, 100);
00155 ras.add_path(ell);
00156 agg::render_scanlines_aa(ras, sl, rbase, span_allocator, span_gradient);
00157 }
00158
00159
00160
00161 template<class RenBase>
00162 void dst_shape(RenBase& rbase, color c1, color c2,
00163 double x1, double y1, double x2, double y2)
00164 {
00165 typedef RenBase renderer_base_type;
00166 typedef agg::gradient_x gradient_func_type;
00167 typedef agg::gradient_linear_color<color> color_func_type;
00168 typedef agg::span_interpolator_linear<> interpolator_type;
00169 typedef agg::span_allocator<color> span_allocator_type;
00170 typedef agg::span_gradient<color,
00171 interpolator_type,
00172 gradient_func_type,
00173 color_func_type> span_gradient_type;
00174
00175 gradient_func_type gradient_func;
00176 agg::trans_affine gradient_mtx = gradient_affine(x1, y1, x2, y2, 100);
00177 interpolator_type span_interpolator(gradient_mtx);
00178 span_allocator_type span_allocator;
00179 color_func_type color_func(c1, c2);
00180 span_gradient_type span_gradient(span_interpolator,
00181 gradient_func,
00182 color_func,
00183 0, 100);
00184 agg::rasterizer_scanline_aa<> ras;
00185 agg::scanline_u8 sl;
00186
00187 agg::rounded_rect shape(x1, y1, x2, y2, 40);
00188
00189
00190 ras.add_path(shape);
00191 agg::render_scanlines_aa(ras, sl, rbase, span_allocator, span_gradient);
00192 }
00193
00194
00195
00196
00197
00198
00199
00200 class the_application : public agg::platform_support
00201 {
00202 agg::slider_ctrl<color> m_alpha_src;
00203 agg::slider_ctrl<color> m_alpha_dst;
00204 agg::rbox_ctrl<agg::rgba8> m_comp_op;
00205
00206 public:
00207 the_application(agg::pix_format_e format, bool flip_y) :
00208 agg::platform_support(format, flip_y),
00209 m_alpha_src(5, 5, 400, 11, !flip_y),
00210 m_alpha_dst(5, 5+15, 400, 11+15, !flip_y),
00211 m_comp_op(420, 5.0, 420+170.0, 395.0, !flip_y)
00212 {
00213 m_alpha_src.label("Src Alpha=%.2f");
00214 m_alpha_src.value(1.0);
00215 add_ctrl(m_alpha_src);
00216
00217 m_alpha_dst.label("Dst Alpha=%.2f");
00218 m_alpha_dst.value(0.75);
00219 add_ctrl(m_alpha_dst);
00220
00221 m_comp_op.text_size(7);
00222 m_comp_op.add_item("clear");
00223 m_comp_op.add_item("src");
00224 m_comp_op.add_item("dst");
00225 m_comp_op.add_item("src-over");
00226 m_comp_op.add_item("dst-over");
00227 m_comp_op.add_item("src-in");
00228 m_comp_op.add_item("dst-in");
00229 m_comp_op.add_item("src-out");
00230 m_comp_op.add_item("dst-out");
00231 m_comp_op.add_item("src-atop");
00232 m_comp_op.add_item("dst-atop");
00233 m_comp_op.add_item("xor");
00234 m_comp_op.add_item("plus");
00235 m_comp_op.add_item("minus");
00236 m_comp_op.add_item("multiply");
00237 m_comp_op.add_item("screen");
00238 m_comp_op.add_item("overlay");
00239 m_comp_op.add_item("darken");
00240 m_comp_op.add_item("lighten");
00241 m_comp_op.add_item("color-dodge");
00242 m_comp_op.add_item("color-burn");
00243 m_comp_op.add_item("hard-light");
00244 m_comp_op.add_item("soft-light");
00245 m_comp_op.add_item("difference");
00246 m_comp_op.add_item("exclusion");
00247 m_comp_op.add_item("contrast");
00248 m_comp_op.cur_item(3);
00249 add_ctrl(m_comp_op);
00250 }
00251
00252 virtual ~the_application()
00253 {
00254 }
00255
00256 virtual void on_init()
00257 {
00258 }
00259
00260
00261 void render_scene(rbuf_type& rbuf, prim_pixfmt_type& pixf)
00262 {
00263 typedef agg::comp_op_adaptor_rgba<color, order> blender_type;
00264 typedef agg::pixfmt_custom_blend_rgba<blender_type, rbuf_type> pixfmt_type;
00265 typedef agg::renderer_base<pixfmt_type> renderer_type;
00266
00267 pixfmt_type ren_pixf(rbuf);
00268 renderer_type renderer(ren_pixf);
00269
00270 agg::renderer_base<prim_pixfmt_type> rb(pixf);
00271
00272 rb.blend_from(prim_pixfmt_type(rbuf_img(1)),
00273 0, 250, 180,
00274 unsigned(m_alpha_src.value() * 255));
00275
00276 circle(rb,
00277 agg::rgba8(0xFD, 0xF0, 0x6F, unsigned(m_alpha_src.value() * 255)),
00278 agg::rgba8(0xFE, 0x9F, 0x34, unsigned(m_alpha_src.value() * 255)),
00279 70*3, 100+24*3, 37*3, 100+79*3,
00280 m_alpha_src.value());
00281
00282 ren_pixf.comp_op(m_comp_op.cur_item());
00283
00284 if(m_comp_op.cur_item() == 25)
00285 {
00286 double v = m_alpha_dst.value();
00287 dst_shape(renderer,
00288 agg::rgba(v, v, v),
00289 agg::rgba(v, v, v),
00290 300+50, 100+24*3, 107+50, 100+79*3);
00291 }
00292 else
00293 {
00294 dst_shape(renderer,
00295 agg::rgba8(0x7F, 0xC1, 0xFF, unsigned(m_alpha_dst.value() * 255)),
00296 agg::rgba8(0x05, 0x00, 0x5F, unsigned(m_alpha_dst.value() * 255)),
00297 300+50, 100+24*3, 107+50, 100+79*3);
00298 }
00299 }
00300
00301
00302 virtual void on_draw()
00303 {
00304 prim_pixfmt_type pixf(rbuf_window());
00305 prim_ren_base_type rb(pixf);
00306 rb.clear(agg::rgba8(255, 255, 255));
00307
00308 unsigned y;
00309 for(y = 0; y < rb.height(); y += 8)
00310 {
00311 unsigned x;
00312 for(x = ((y >> 3) & 1) << 3; x < rb.width(); x += 16)
00313 {
00314 rb.copy_bar(x, y, x+7, y+7, agg::rgba8(0xdf, 0xdf, 0xdf));
00315 }
00316 }
00317
00318 create_img(0, rbuf_window().width(), rbuf_window().height());
00319
00320 prim_pixfmt_type pixf2(rbuf_img(0));
00321 prim_ren_base_type rb2(pixf2);
00322 rb2.clear(agg::rgba8(0,0,0,0));
00323
00324 typedef agg::blender_rgba_pre<color, order> blender_type_pre;
00325 typedef agg::pixfmt_alpha_blend_rgba<blender_type_pre, rbuf_type, pixel_type> pixfmt_pre;
00326 typedef agg::renderer_base<pixfmt_pre> ren_base_pre;
00327
00328 pixfmt_pre pixf_pre(rbuf_window());
00329 ren_base_pre rb_pre(pixf_pre);
00330
00331
00332 start_timer();
00333 render_scene(rbuf_img(0), pixf2);
00334 double tm = elapsed_time();
00335
00336 rb_pre.blend_from(pixf2);
00337
00338 agg::rasterizer_scanline_aa<> ras;
00339 agg::scanline_u8 sl;
00340 agg::renderer_scanline_aa_solid<prim_ren_base_type> ren(rb);
00341
00342 char buf[64];
00343 agg::gsv_text t;
00344 t.size(10.0);
00345
00346 agg::conv_stroke<agg::gsv_text> pt(t);
00347 pt.width(1.5);
00348
00349 sprintf(buf, "%3.2f ms", tm);
00350 t.start_point(10.0, 35.0);
00351 t.text(buf);
00352
00353 ras.add_path(pt);
00354 ren.color(agg::rgba(0,0,0));
00355 agg::render_scanlines(ras, sl, ren);
00356
00357 agg::render_ctrl_rs(ras, sl, ren, m_alpha_src);
00358 agg::render_ctrl_rs(ras, sl, ren, m_alpha_dst);
00359 agg::render_ctrl_rs(ras, sl, ren, m_comp_op);
00360 }
00361
00362
00363 virtual void on_mouse_button_down(int x, int y, unsigned flags)
00364 {
00365 }
00366
00367 virtual void on_mouse_move(int x, int y, unsigned flags)
00368 {
00369 }
00370
00371 virtual void on_mouse_button_up(int x, int y, unsigned flags)
00372 {
00373 }
00374 };
00375
00376
00377 int agg_main(int argc, char* argv[])
00378 {
00379 force_comp_op_link();
00380 the_application app(pix_format, flip_y);
00381 app.caption("AGG Example. Compositing Modes");
00382
00383 const char* img_name = "compositing";
00384 if(argc >= 2) img_name = argv[1];
00385 if(!app.load_img(1, img_name))
00386 {
00387 char buf[256];
00388 if(strcmp(img_name, "compositing") == 0)
00389 {
00390 sprintf(buf, "File not found: %s%s. Download http://www.antigrain.com/%s%s\n"
00391 "or copy it from another directory if available.",
00392 img_name, app.img_ext(), img_name, app.img_ext());
00393 }
00394 else
00395 {
00396 sprintf(buf, "File not found: %s%s", img_name, app.img_ext());
00397 }
00398 app.message(buf);
00399 return 1;
00400 }
00401
00402
00403 if(app.init(600, 400, agg::window_resize))
00404 {
00405 return app.run();
00406 }
00407 return 1;
00408 }
00409
00410