author | Francesco Abbate <francesco.bbt@gmail.com> | 2012年01月11日 16:41:22 +0100 |
---|---|---|
committer | Francesco Abbate <francesco.bbt@gmail.com> | 2012年01月30日 21:26:02 +0100 |
commit | 3835be08da347dcaf854d61dc21f0cb52164ef8a (patch) | |
tree | c2a6772c5dc17fbfb551fbdb36e4d4617a82dd31 /agg-plot | |
parent | 900c2a906c1a7ec8043b3f6eb9e74ec1c8f05063 (diff) | |
download | gsl-shell-3835be08da347dcaf854d61dc21f0cb52164ef8a.tar.gz |
-rw-r--r-- | agg-plot/lua-draw.cpp | 31 | ||||
-rw-r--r-- | agg-plot/lua-plot.cpp | 34 | ||||
-rw-r--r-- | agg-plot/plot-auto.h | 6 | ||||
-rw-r--r-- | agg-plot/plot.h | 97 | ||||
-rw-r--r-- | agg-plot/rect.h | 3 | ||||
-rw-r--r-- | agg-plot/text-shape.h | 100 | ||||
-rw-r--r-- | agg-plot/text.cpp | 3 | ||||
-rw-r--r-- | agg-plot/utils.h | 6 |
diff --git a/agg-plot/lua-draw.cpp b/agg-plot/lua-draw.cpp index 932d9c26..b9a3a13e 100644 --- a/agg-plot/lua-draw.cpp +++ b/agg-plot/lua-draw.cpp @@ -26,6 +26,7 @@ extern "C" { } #include "lua-draw.h" +#include "text-shape.h" #include "gsl-shell.h" #include "lua-cpp-utils.h" #include "gs-types.h" @@ -62,6 +63,9 @@ static int agg_ellipse_new (lua_State *L); static int agg_circle_new (lua_State *L); static int agg_ellipse_free (lua_State *L); +static int textshape_new (lua_State *L); +static int textshape_free (lua_State *L); + static void path_cmd (draw::path *p, int cmd, struct cmd_call_stack *stack); static struct path_cmd_reg cmd_table[] = { @@ -78,6 +82,7 @@ static const struct luaL_Reg draw_functions[] = { {"path", agg_path_new}, {"ellipse", agg_ellipse_new}, {"circle", agg_circle_new}, + {"textshape", textshape_new}, {NULL, NULL} }; @@ -87,6 +92,11 @@ static const struct luaL_Reg agg_path_methods[] = { {NULL, NULL} }; +static const struct luaL_Reg textshape_methods[] = { + {"__gc", textshape_free}, + {NULL, NULL} +}; + static const struct luaL_Reg agg_ellipse_methods[] = { {"__gc", agg_ellipse_free}, @@ -243,6 +253,23 @@ agg_ellipse_free (lua_State *L) return object_free<draw::ellipse>(L, 1, GS_DRAW_ELLIPSE); } +int +textshape_new (lua_State *L) +{ + double x = luaL_checknumber(L, 1); + double y = luaL_checknumber(L, 2); + const char* text = luaL_checkstring(L, 3); + double ts = luaL_checknumber(L, 4); + new(L, GS_DRAW_TEXTSHAPE) draw::text_shape(x, y, text, ts); + return 1; +} + +int +textshape_free (lua_State *L) +{ + return object_free<draw::text_shape>(L, 1, GS_DRAW_TEXTSHAPE); +} + void draw_register (lua_State *L) { @@ -256,6 +283,10 @@ draw_register (lua_State *L) luaL_register (L, NULL, agg_ellipse_methods); lua_pop (L, 1); + luaL_newmetatable (L, GS_METATABLE(GS_DRAW_TEXTSHAPE)); + luaL_register (L, NULL, textshape_methods); + lua_pop (L, 1); + /* gsl module registration */ luaL_register (L, NULL, draw_functions); } diff --git a/agg-plot/lua-plot.cpp b/agg-plot/lua-plot.cpp index 01f3e887..59df3300 100644 --- a/agg-plot/lua-plot.cpp +++ b/agg-plot/lua-plot.cpp @@ -67,6 +67,7 @@ static int plot_xlab_angle_get (lua_State *L); static int plot_ylab_angle_set (lua_State *L); static int plot_ylab_angle_get (lua_State *L); static int plot_set_categories (lua_State *L); +static int plot_set_mini (lua_State *L); static int plot_sync_mode_get (lua_State *L); static int plot_sync_mode_set (lua_State *L); @@ -106,6 +107,7 @@ static const struct luaL_Reg plot_methods[] = { {"save", bitmap_save_image }, {"save_svg", plot_save_svg }, {"set_categories", plot_set_categories}, + {"set_mini", plot_set_mini}, {NULL, NULL} }; @@ -649,6 +651,38 @@ plot_set_categories (lua_State *L) return 0; } +int +plot_set_mini(lua_State *L) +{ + sg_plot* p = object_check<sg_plot>(L, 1, GS_PLOT); + const char* placement = luaL_checkstring(L, 2); + sg_plot* mp = object_check<sg_plot>(L, 3, GS_PLOT); + sg_plot::placement_e pos; + + char letter = placement[0]; + if (letter == 'r') + pos = sg_plot::right; + else if (letter == 'l') + pos = sg_plot::left; + else if (letter == 'b') + pos = sg_plot::bottom; + else if (letter == 't') + pos = sg_plot::top; + else + return luaL_error (L, "invalid mini plot placement specification."); + + lua_getfenv (L, 1); + objref_mref_add (L, -1, (int)pos, 3); + + AGG_LOCK(); + p->add_mini_plot(mp, pos); + AGG_UNLOCK(); + + plot_update_raw (L, p, 1); + + return 0; +} + void plot_register (lua_State *L) { diff --git a/agg-plot/plot-auto.h b/agg-plot/plot-auto.h index 027c0975..17b83c1c 100644 --- a/agg-plot/plot-auto.h +++ b/agg-plot/plot-auto.h @@ -41,7 +41,11 @@ public: virtual ~plot_auto() { }; virtual void add(VertexSource* vs, agg::rgba8& color, bool outline); - virtual void before_draw() { check_bounding_box(); }; + virtual void before_draw() + { + plot<VertexSource, resource_manager>::before_draw(); + check_bounding_box(); + }; virtual bool pop_layer(); diff --git a/agg-plot/plot.h b/agg-plot/plot.h index bc46a9eb..07025ce5 100644 --- a/agg-plot/plot.h +++ b/agg-plot/plot.h @@ -89,6 +89,7 @@ public: typedef virtual_canvas<VertexSource> canvas_type; enum axis_e { x_axis, y_axis }; + enum placement_e { right = 0, left = 1, bottom = 2, top = 3 }; struct axis { str title; @@ -129,6 +130,8 @@ public: m_sync_mode(true), m_x_axis(x_axis), m_y_axis(y_axis) { compute_user_trans(); + for (unsigned k = 0; k < 4; k++) + m_mini_plot[k] = 0; }; virtual ~plot() @@ -146,6 +149,11 @@ public: str& x_axis_title() { return m_x_axis.title; } str& y_axis_title() { return m_y_axis.title; } + void add_mini_plot(plot* p, placement_e where) + { + m_mini_plot[where] = p; + } + axis& get_axis(axis_e axis_dir) { return (axis_dir == x_axis ? m_x_axis : m_y_axis); @@ -169,7 +177,17 @@ public: void set_limits(const agg::rect_base<double>& r); virtual void add(VertexSource* vs, agg::rgba8& color, bool outline); - virtual void before_draw() { }; + virtual void before_draw() { } + + void get_bounding_rect(agg::rect_base<double>& bb) + { + before_draw(); + + if (m_rect.is_defined()) + bb = m_rect.rect(); + else + bb = agg::rect_base<double>(0.0, 0.0, 0.0, 0.0); + } template <class Canvas> void draw(Canvas& canvas, agg::trans_affine& m); @@ -231,6 +249,9 @@ protected: void draw_element(item& c, canvas_type &canvas, agg::trans_affine& m); void draw_axis(canvas_type& can, agg::trans_affine& m); + agg::trans_affine draw_mini_plots(canvas_type& canvas, + agg::trans_affine& canvas_mtx); + agg::trans_affine get_scaled_matrix(agg::trans_affine& canvas_mtx); void clip_plot_area(canvas_type& canvas, agg::trans_affine& canvas_mtx); @@ -270,6 +291,7 @@ private: bool m_sync_mode; axis m_x_axis, m_y_axis; + plot* m_mini_plot[4]; }; static double compute_scale(agg::trans_affine& m) @@ -333,8 +355,10 @@ template <class Canvas> void plot<VS,RM>::draw(Canvas& _canvas, agg::trans_affin { canvas_adapter<Canvas, VS> canvas(&_canvas); before_draw(); - draw_axis(canvas, canvas_mtx); - draw_elements(canvas, canvas_mtx); + + agg::trans_affine area_mtx = draw_mini_plots(canvas, canvas_mtx); + draw_axis(canvas, area_mtx); + draw_elements(canvas, area_mtx); }; template <class VS, class RM> @@ -529,11 +553,71 @@ double plot<VS,RM>::draw_axis_m(axis_e dir, units& u, } template <class VS, class RM> +agg::trans_affine plot<VS,RM>::draw_mini_plots(canvas_type& canvas, + agg::trans_affine& canvas_mtx) +{ + const double sx = canvas_mtx.sx, sy = canvas_mtx.sy; + const double pad = 2.0; + + double dxl = 0.0, dxr = 0.0, dyb = 0.0, dyt = 0.0; + + for (int k = 0; k < 4; k++) + { + plot* mp = m_mini_plot[k]; + + if (mp) + { + agg::rect_base<double> bb; + mp->get_bounding_rect(bb); + + double dx = bb.x2 - bb.x1, dy = bb.y2 - bb.y1; + double px, py; + switch (k) + { + case right: + px = sx - dx + pad; + dxr = dx + 2*pad; + py = (sy - dy) / 2 + pad; + break; + case left: + px = pad; + dxl = dx + 2*pad; + py = (sy - dy) / 2 + pad; + break; + case bottom: + py = pad; + dyb = dy + 2*pad; + px = (sx - dx) / 2 + pad; + break; + case top: + py = sy - dy + pad; + dyt = dy + 2*pad; + px = (sx - dx) / 2 + pad; + break; + default: + /* */; + } + + agg::trans_affine mtx(dx + 2*pad, 0.0, 0.0, dy + 2*pad, px, py); + + mp->before_draw(); + mp->draw_axis(canvas, mtx); + mp->draw_elements(canvas, mtx); + } + } + + double cpx = canvas_mtx.tx, cpy = canvas_mtx.ty; + + double ssx = sx - (dxl + dxr), ssy = sy - (dyb + dyt); + return agg::trans_affine(ssx, 0.0, 0.0, ssy, cpx + dxl, cpy + dyb); +} + +template <class VS, class RM> void plot<VS,RM>::draw_axis(canvas_type& canvas, agg::trans_affine& canvas_mtx) { if (!m_use_units) { - const double pad = 4.0; + const double pad = 2.0; m_left_margin = pad; m_right_margin = pad; m_bottom_margin = pad; @@ -573,10 +657,9 @@ void plot<VS,RM>::draw_axis(canvas_type& canvas, agg::trans_affine& canvas_mtx) const double ppad = 0.02, fpad = 4; ptr_list<draw::text> labels; - double dx_label, dy_label; - dy_label = draw_axis_m(x_axis, m_ux, m_trans, labels, scale, mark, ln); - dx_label = draw_axis_m(y_axis, m_uy, m_trans, labels, scale, mark, ln); + double dy_label = draw_axis_m(x_axis, m_ux, m_trans, labels, scale, mark, ln); + double dx_label = draw_axis_m(y_axis, m_uy, m_trans, labels, scale, mark, ln); const double sx = canvas_mtx.sx, sy = canvas_mtx.sy; const double lsx = (dx_label + 4 * ppad * sx + 2 * fpad) / (1 + 4 * ppad); diff --git a/agg-plot/rect.h b/agg-plot/rect.h index 4a5592ba..5faedd7f 100644 --- a/agg-plot/rect.h +++ b/agg-plot/rect.h @@ -56,7 +56,8 @@ public: template <typename T> agg::rect_base<T> rect_of_slot_matrix (const agg::trans_affine& mtx) { - return agg::rect_base<T>(T(mtx.tx), T(mtx.ty), T(mtx.sx + mtx.tx), T(mtx.sy + mtx.ty)); + T dx = T(mtx.sx + mtx.tx), dy = T(mtx.sy + mtx.ty); + return agg::rect_base<T>(T(mtx.tx), T(mtx.ty), dx, dy); } #endif diff --git a/agg-plot/text-shape.h b/agg-plot/text-shape.h new file mode 100644 index 00000000..326ca9b8 --- /dev/null +++ b/agg-plot/text-shape.h @@ -0,0 +1,100 @@ +#ifndef AGGPLOT_TEXT_SHAPE_H +#define AGGPLOT_TEXT_SHAPE_H + +#include "agg_gsv_text.h" + +#include "sg_object.h" + +typedef sg_object_gen<agg::gsv_text> sg_text_base; + +namespace draw { + + class text_shape : public sg_object { + public: + text_shape(double x, double y, const char* text, + double _size = 10.0, double hjustif = 0.0, double vjustif = 0.0): + m_sg_text(), m_x(x), m_y(y), m_text(text), m_size(_size), + m_scaling(0), m_trans(m_sg_text, identity_matrix), m_stroke(m_trans) + { + agg::gsv_text& t = m_sg_text.self(); + t.text(text); + t.size(_size); + + const double text_width = t.text_width(), text_height = _size; + m_x -= hjustif * text_width; + m_y -= vjustif * text_height; + + t.start_point(m_x, m_y); + + m_stroke.line_cap(agg::round_cap); + m_stroke.line_join(agg::round_join); + } + + virtual void rewind(unsigned path_id) + { + m_sg_text.self().start_point(m_x, m_y); + m_stroke.rewind(path_id); + } + + virtual unsigned vertex(double* x, double* y) + { + return m_stroke.vertex(x, y); + } + + virtual void bounding_box(double *x1, double *y1, double *x2, double *y2) + { + agg::bounding_rect_single(m_sg_text, 0, x1, y1, x2, y2); + } + + virtual str write_svg(int id, agg::rgba8 c, double h) + { + const char* text = m_text.cstr(); + int txt_size = (int)(m_size * 1.5); + + const agg::trans_affine& m = *m_scaling; + + double x = m_x, y = -m_y; + const double dx = m.tx, dy = svg_y_coord(m.ty, h); + + if (is_unit_matrix(m)) + { + x += dx; + y += dy; + } + + str svgtext = str::print("<text x=\"%g\" y=\"%g\" id=\"text%i\"" \ + " style=\"font-size:%i\">" \ + " <tspan id=\"tspan%i\">%s</tspan>" \ + "</text>", + x, y, id, txt_size, id, text); + + str s; + if (is_unit_matrix(m)) + s = svgtext; + else + s = str::print("<g transform=\"matrix(%g,%g,%g,%g,%g,%g)\">%s</g>", + m.sx, m.shx, m.shy, m.sy, dx, dy, svgtext.cstr()); + + return s; + } + + virtual void apply_transform(const agg::trans_affine& m, double as) + { + m_stroke.width(1.5 * m.scale()); + m_trans.transformer(m); + m_scaling = &m; + } + + private: + sg_text_base m_sg_text; + double m_x, m_y; + str m_text; + double m_size; + + const agg::trans_affine* m_scaling; + agg::conv_transform<sg_object> m_trans; + agg::conv_stroke<agg::conv_transform<sg_object> > m_stroke; + }; +} + +#endif diff --git a/agg-plot/text.cpp b/agg-plot/text.cpp index ad6bd021..1aa63ba6 100644 --- a/agg-plot/text.cpp +++ b/agg-plot/text.cpp @@ -62,8 +62,7 @@ namespace draw { style.printf_add(";fill:%s", rgbstr); } - bool need_rotate = (fabs(m.sx - 1.0) > eps || fabs(m.shx) > eps || \ - fabs(m.shy) > eps || fabs(m.sy - 1.0) > eps); + bool need_rotate = !is_unit_matrix(m, eps); int txt_size = (int)(m_text_height * 1.5); diff --git a/agg-plot/utils.h b/agg-plot/utils.h index d90febf6..a6a0a5df 100644 --- a/agg-plot/utils.h +++ b/agg-plot/utils.h @@ -48,6 +48,12 @@ private: agg::pod_bvector<T*> m_list; }; +inline bool is_unit_matrix(const agg::trans_affine& m, double eps = 1.0e-5) +{ + return (fabs(m.sx - 1.0) < eps && fabs(m.shx) < eps && \ + fabs(m.shy) < eps && fabs(m.sy - 1.0) < eps); +} + extern void trans_affine_compose (agg::trans_affine& a, const agg::trans_affine& b); |