#include #include #include "agg_scanline_p.h" #include "platform/agg_platform_support.h" #include "ctrl/agg_slider_ctrl.h" #include "agg_svg_exception.h" #include "agg_svg_parser.h" #include "agg_svg_indexation_interpreter.h" #include "agg_svg_rendering_interpreter.h" #include "agg_svg_attributes_map.h" #include "agg_svg_rasterizer.h" enum { flip_y_e = false }; class the_application : public agg::platform_support { agg::svg::dom_storage m_storage; agg::svg::dom_storage::map_type m_id2elem_map; agg::svg::attributes_map m_attr_map; agg::svg::global_settings m_settings; agg::svg::attributes m_attributes; agg::svg::frame_buffer_rgba m_frame_buffer; agg::svg::rasterizer m_rasterizer; agg::svg::renderer_rgba m_renderer; agg::svg::pipeline m_pipeline; agg::svg::gradient_lut_cache m_gradient_lut_cache; //agg::slider_ctrl m_expand; agg::slider_ctrl m_gamma; //agg::slider_ctrl m_scale; //agg::slider_ctrl m_rotate; enum tool_type_e {tool_none, tool_zoom, tool_pan}; tool_type_e m_current_tool; int m_x1; int m_y1; int m_x2; int m_y2; bool m_drag_flag; public: the_application(agg::pix_format_e format, bool flip_y) : agg::platform_support(format, flip_y), //m_expand(5, 5, 256-5, 11, !flip_y), m_gamma (5, 5, 256-5, 20, !flip_y), //m_scale (256+5, 5, 512-5, 11, !flip_y), //m_rotate(256+5, 5+15, 512-5, 11+15, !flip_y), m_x1(0), m_y1(0), m_x2(0), m_y2(0), m_drag_flag(false), m_attributes(m_settings), m_renderer(m_rasterizer, m_frame_buffer), m_current_tool(tool_none) { //add_ctrl(m_expand); add_ctrl(m_gamma); //add_ctrl(m_scale); //add_ctrl(m_rotate); //m_expand.label("Expand=%3.2f"); //m_expand.range(-1, 1.2); //m_expand.value(0.0); m_gamma.label("Gamma=%3.2f"); m_gamma.range(0.0, 3.0); m_gamma.value(1.0); //m_scale.label("Scale=%3.2f"); //m_scale.range(0.2, 10.0); //m_scale.value(1.0); //m_rotate.label("Rotate=%3.2f"); //m_rotate.range(-180.0, 180.0); //m_rotate.value(0.0); } void swap_int(int* n1, int* n2) { int temp; temp = *n1; *n1 = *n2; *n2 = temp; } void normalize_rect(int* x1, int* y1, int* x2, int* y2) { if (*x1 > *x2) { swap_int(x1, x2); } if (*y1 > *y2) { swap_int(y1, y2); } } void update_zoom() { if (m_current_tool == tool_zoom) { int x1 = m_x1; int y1 = m_y1; int x2 = m_x2; int y2 = m_y2; normalize_rect(&x1, &y1, &x2, &y2); m_attributes.set_zoom(x1, y1, x2, y2); } else if (m_current_tool == tool_pan) { int offset_x = m_x2 - m_x1; int offset_y = m_y2 - m_y1; int x1 = -offset_x; int y1 = -offset_y; int x2 = rbuf_window().width() - offset_x; int y2 = rbuf_window().height() - offset_y; m_attributes.set_zoom(x1, y1, x2, y2); } } void indexation() { agg::svg::indexation_interpreter consumer(m_id2elem_map); m_storage.traverse(consumer); m_id2elem_map.sort_state(agg::svg::on); } void reset() { m_id2elem_map.clear(); m_attributes.clear(); m_renderer.reset(); } void parse_svg(const char* fname) { if(!fname) return; m_attributes.initial_zoom(); m_storage.clear(); reset(); agg::svg::parser p(m_storage, m_attr_map); p.parse(fname); indexation(); } void on_resize(int sx, int sy) { m_frame_buffer.create(sx, sy, flip_y_e); } void draw(agg::rendering_buffer& rbuf, double expand, double gamma) { agg::svg::renderer_rgba::pixfmt_type pixfmt(rbuf); agg::svg::renderer_rgba::renderer_base_type rbase(pixfmt); m_rasterizer.gamma(gamma); m_settings.gamma(gamma); m_attributes.window(0, 0, rbuf.width(), rbuf.height()); m_frame_buffer.clear(agg::svg::color_type(255, 255, 255)); m_renderer.attach(m_frame_buffer); agg::svg::rendering_interpreter rin( m_pipeline, m_attributes, m_renderer, m_id2elem_map, m_gradient_lut_cache ); #ifdef EXPAND_PATHS rin.expand(expand); #endif m_storage.traverse(rin); assert(0 == m_attributes.num_sessions()); if (m_settings.gamma() != 1.0) { m_frame_buffer.pixfmt().apply_gamma_inv(m_settings.gamma_lut()); } if(m_frame_buffer.is_valid()) { rbase.copy_from(m_frame_buffer.ren_buf()); if (m_current_tool == tool_zoom) { agg::rgba8 color(0, 0, 0, 255); rbase.blend_hline(m_x1, m_y1, m_x2, color, agg::cover_full); rbase.blend_hline(m_x1, m_y2, m_x2, color, agg::cover_full); rbase.blend_vline(m_x1, m_y1, m_y2, color, agg::cover_full); rbase.blend_vline(m_x2, m_y1, m_y2, color, agg::cover_full); } } else { rbase.clear(agg::svg::color_type(255, 255, 255)); } } virtual void on_draw() { try { typedef agg::pixfmt_bgra32 pixfmt; typedef agg::renderer_base renderer_base; typedef agg::renderer_scanline_aa_solid renderer_solid; pixfmt pixf(rbuf_window()); renderer_base rb(pixf); renderer_solid ren(rb); rb.clear(agg::rgba(1,1,1)); agg::rasterizer_scanline_aa<> ras; agg::scanline_p8 sl; //ras.gamma(agg::gamma_power(m_gamma.value())); start_timer(); draw(rbuf_window(), 0.0/*m_expand.value()*/, m_gamma.value()); double tm = elapsed_time(); ras.gamma(agg::gamma_none()); //agg::render_ctrl(ras, sl, rb, m_expand); agg::render_ctrl(ras, sl, rb, m_gamma); //agg::render_ctrl(ras, sl, rb, m_scale); //agg::render_ctrl(ras, sl, rb, m_rotate); char buf[128]; agg::gsv_text t; t.size(10.0); t.flip(true); agg::conv_stroke pt(t); pt.width(1.5); //sprintf(buf, "Vertices=%d Time=%.3f ms", vertex_count, tm); sprintf(buf, "Time=%.3f ms", tm); t.start_point(4.0, 40.0); t.text(buf); ras.add_path(pt); ren.color(agg::rgba(0,0,0)); agg::render_scanlines(ras, sl, ren); } catch (agg::svg::exception&) { } } virtual void on_mouse_button_down(int x, int y, unsigned flags) { if (flags & agg::mouse_left) m_current_tool = tool_zoom; if (flags & agg::mouse_right) m_current_tool = tool_pan; m_x1 = x; m_y1 = y; m_x2 = x; m_y2 = y; m_drag_flag = true; } virtual void on_mouse_move(int x, int y, unsigned flags) { if(flags == 0) { m_drag_flag = false; } if (m_drag_flag) { m_x2 = x; m_y2 = y; if (m_current_tool == tool_zoom) { force_redraw(); } else if (m_current_tool == tool_pan) { update_zoom(); m_x1 = x; m_y1 = y; force_redraw(); } } } void zoom_out(int x, int y) { int d = 100; int x1 = -d; int y1 = -d; int x2 = rbuf_window().width() + d; int y2 = rbuf_window().height() + d; int w = x2 - x1; int h = y2 - y1; int cx = x1 + w/2; int cy = y1 + h/2; int dx = x - cx; int dy = y - cy; m_attributes.set_zoom(x1 + dx, y1 + dy, x2 + dx, y2 + dy); force_redraw(); } virtual void on_mouse_button_up(int x, int y, unsigned flags) { if ((flags & agg::kbd_shift) && m_x1 == x && m_y1 == y) { zoom_out(x,y); m_drag_flag = false; m_current_tool = tool_none; } if (m_drag_flag) { if (m_current_tool == tool_zoom) { if(x != m_x1 && y != m_y1) { m_x2 = x; m_y2 = y; update_zoom(); } force_redraw(); } m_drag_flag = false; } m_current_tool = tool_none; } virtual void on_key(int x, int y, unsigned key, unsigned flags) { if(key == agg::key_home) { m_attributes.initial_zoom(); force_redraw(); } } }; int agg_main(int argc, char* argv[]) { the_application app(agg::svg::pix_format, flip_y_e); const char* fname = "tiger.svg"; if(argc <= 1) { FILE* fd = fopen(app.full_file_name(fname), "r"); if(fd == 0) { app.message("Usage: svg_test \n" "Download http://antigrain.com/svg/tiger.svg"); return 1; } fclose(fd); } else { fname = argv[1]; } try { app.parse_svg(app.full_file_name(fname)); } catch (agg::svg::exception& e) { app.message(e.msg()); return 1; } if(app.init(512, 600, agg::window_resize)) { return app.run(); } return 1; }