-rw-r--r-- | agg-plot/lua-plot.cpp | 44 | ||||
-rw-r--r-- | agg-plot/plot-auto.h | 44 | ||||
-rw-r--r-- | agg-plot/plot.h | 124 |
diff --git a/agg-plot/lua-plot.cpp b/agg-plot/lua-plot.cpp index 68474f13..a09b7ac0 100644 --- a/agg-plot/lua-plot.cpp +++ b/agg-plot/lua-plot.cpp @@ -54,6 +54,9 @@ static int plot_title_get (lua_State *L); static int plot_units_set (lua_State *L); static int plot_units_get (lua_State *L); static int plot_set_limits (lua_State *L); +static int plot_push_layer (lua_State *L); +static int plot_pop_layer (lua_State *L); +static int plot_clear (lua_State *L); static int canvas_new (lua_State *L); @@ -72,6 +75,9 @@ static const struct luaL_Reg plot_methods[] = { {"update", plot_update }, {"show", plot_show }, {"limits", plot_set_limits }, + {"pushlayer", plot_push_layer }, + {"poplayer", plot_pop_layer }, + {"clear", plot_clear }, {"__index", plot_index }, {"__newindex", plot_newindex }, {"__gc", plot_free }, @@ -246,7 +252,7 @@ void plot_update_raw (lua_State *L, lua_plot *p, int plot_index) { window_plot_rev_lookup_apply (L, plot_index, window_slot_update); - p->redraw_done(); + p->commit_pending_draw(); } int @@ -262,7 +268,7 @@ plot_flush (lua_State *L) { lua_plot *p = object_check<lua_plot>(L, 1, GS_PLOT); window_plot_rev_lookup_apply (L, 1, window_slot_refresh); - p->redraw_done(); + p->commit_pending_draw(); return 0; } @@ -288,7 +294,41 @@ plot_set_limits (lua_State *L) r.x2 = gs_check_number (L, 4, true); r.y2 = gs_check_number (L, 5, true); + AGG_LOCK(); p->set_limits(r); + AGG_UNLOCK(); + plot_update_raw (L, p, 1); + return 0; +} + +int +plot_push_layer (lua_State *L) +{ + lua_plot *p = object_check<lua_plot>(L, 1, GS_PLOT); + AGG_LOCK(); + p->push_layer(); + AGG_UNLOCK(); + return 0; +} + +int +plot_pop_layer (lua_State *L) +{ + lua_plot *p = object_check<lua_plot>(L, 1, GS_PLOT); + AGG_LOCK(); + p->pop_layer(); + AGG_UNLOCK(); + plot_update_raw (L, p, 1); + return 0; +} + +int +plot_clear (lua_State *L) +{ + lua_plot *p = object_check<lua_plot>(L, 1, GS_PLOT); + AGG_LOCK(); + p->clear_current_layer(); + AGG_UNLOCK(); plot_update_raw (L, p, 1); return 0; } diff --git a/agg-plot/plot-auto.h b/agg-plot/plot-auto.h index 2d11bee6..16667781 100644 --- a/agg-plot/plot-auto.h +++ b/agg-plot/plot-auto.h @@ -29,6 +29,7 @@ template<class VertexSource, class resource_manager = no_management> class plot_auto : public plot<VertexSource, resource_manager> { typedef plot_item<VertexSource> item; + typedef agg::pod_bvector<item> item_list; public: plot_auto() : @@ -42,6 +43,10 @@ public: virtual void on_draw() { check_bounding_box(); }; private: + void calc_layer_bounding_box(item_list& layer, + agg::rect_base<double>& prect, + bool is_initialized); + void check_bounding_box(); void calc_bounding_box(); bool fit_inside(VertexSource *obj) const; @@ -60,7 +65,7 @@ void plot_auto<VS,RM>::add(VS* vs, agg::rgba8 *color, bool outline) { this->m_bbox_updated = false; this->m_need_redraw = true; - this->m_elements.add(d); + this->current_layer().add(d); } else { @@ -89,20 +94,35 @@ void plot_auto<VS,RM>::check_bounding_box() } template<class VS, class RM> -void plot_auto<VS,RM>::calc_bounding_box() +void plot_auto<VS,RM>::calc_layer_bounding_box(plot_auto<VS,RM>::item_list& layer, agg::rect_base<double>& prect, bool is_initialized) { - for (unsigned j = 0; j < this->m_elements.size(); j++) - { - item& d = this->m_elements[j]; - agg::rect_base<double> r; + for (unsigned j = 0; j < layer.size(); j++) + { + item& d = layer[j]; + agg::rect_base<double> r; - d.vs->bounding_box(&r.x1, &r.y1, &r.x2, &r.y2); + d.vs->bounding_box(&r.x1, &r.y1, &r.x2, &r.y2); - if (j == 0) - this->m_rect = r; - else - this->m_rect = agg::unite_rectangles(this->m_rect, r); - } + if (! is_initialized) + { + prect = r; + is_initialized = true; + } + else + { + prect = agg::unite_rectangles(prect, r); + } + } +} + +template<class VS, class RM> +void plot_auto<VS,RM>::calc_bounding_box() +{ + calc_layer_bounding_box(this->m_root_layer, this->m_rect, false); + for (unsigned j = 0; j < this->m_layers.size(); j++) + { + calc_layer_bounding_box(*(this->m_layers[j]), this->m_rect, true); + } } template<class VS, class RM> diff --git a/agg-plot/plot.h b/agg-plot/plot.h index 275b2898..5d051a86 100644 --- a/agg-plot/plot.h +++ b/agg-plot/plot.h @@ -56,15 +56,19 @@ struct plot_item { VertexSource& vertex_source() { return *vs; }; }; -template<class VertexSource, class resource_manager = no_management> +template<class vertex_source, class resource_manager> class plot { - typedef plot_item<VertexSource> item; + typedef plot_item<vertex_source> item; + typedef agg::pod_bvector<item> item_list; + + static const unsigned max_layers = 8; public: typedef pod_list<item> iterator; plot(bool use_units = true) : - m_elements(), m_drawing_queue(0), + m_root_layer(), m_layers(), m_current_layer(&m_root_layer), + m_drawing_queue(0), m_need_redraw(true), m_rect(), m_use_units(use_units), m_title_buf() { @@ -77,10 +81,12 @@ public: virtual ~plot() { - for (unsigned j = 0; j < m_elements.size(); j++) + layer_dispose_elements(m_root_layer); + for (unsigned k = 0; k < m_layers.size(); k++) { - item& d = m_elements[j]; - resource_manager::dispose(d.vs); + item_list *layer = m_layers[k]; + layer_dispose_elements(*layer); + delete layer; } }; @@ -92,16 +98,21 @@ public: void set_limits(const agg::rect_base<double>& r); - virtual void add(VertexSource* vs, agg::rgba8 *color, bool outline); + virtual void add(vertex_source* vs, agg::rgba8 *color, bool outline); virtual void on_draw() { }; void draw(canvas &canvas, agg::trans_affine& m); + bool push_layer(); + bool pop_layer(); + /* drawing queue related methods */ void push_drawing_queue(); + void clear_drawing_queue(); + void clear_current_layer(); bool need_redraw() const { return m_need_redraw; }; - void redraw_done(); + void commit_pending_draw(); bool draw_queue(canvas &canvas, agg::trans_affine& m, @@ -122,11 +133,18 @@ protected: static void viewport_scale(agg::trans_affine& trans); - bool fit_inside(VertexSource *obj) const; + bool fit_inside(vertex_source *obj) const; void push_drawing_rev(pod_list<item> *c); + void layer_dispose_elements (item_list& layer); + + item_list& current_layer() { return *m_current_layer; }; + + item_list m_root_layer; + agg::pod_auto_vector<item_list*, max_layers> m_layers; + item_list *m_current_layer; + // agg::pod_bvector<item> m_elements; - agg::pod_bvector<item> m_elements; agg::trans_affine m_trans; pod_list<item> *m_drawing_queue; @@ -147,12 +165,12 @@ void plot<VS,RM>::push_drawing_rev(pod_list<item> *c) if (c) { push_drawing_rev (c->next()); - m_elements.add(c->content()); + m_current_layer->add(c->content()); } } template <class VS, class RM> -void plot<VS,RM>::redraw_done() +void plot<VS,RM>::commit_pending_draw() { push_drawing_queue(); m_need_redraw = false; @@ -185,6 +203,17 @@ void plot<VS,RM>::push_drawing_queue() } template <class VS, class RM> +void plot<VS,RM>::clear_drawing_queue() +{ + while (m_drawing_queue) + { + item& d = m_drawing_queue->content(); + RM::dispose(d.vs); + m_drawing_queue = list::pop(m_drawing_queue); + } +} + +template <class VS, class RM> void plot<VS,RM>::draw(canvas &canvas, agg::trans_affine& canvas_mtx) { on_draw(); @@ -248,9 +277,18 @@ void plot<VS,RM>::draw_elements(canvas &canvas, agg::trans_affine& canvas_mtx) { agg::trans_affine m = get_scaled_matrix(canvas_mtx); - for (unsigned j = 0; j < m_elements.size(); j++) + for (unsigned j = 0; j < m_root_layer.size(); j++) + { + draw_element(m_root_layer[j], canvas, m); + } + + for (unsigned k = 0; k < m_layers.size(); k++) { - draw_element(m_elements[j], canvas, m); + item_list& layer = *(m_layers[k]); + for (unsigned j = 0; j < layer.size(); j++) + { + draw_element(layer[j], canvas, m); + } } } @@ -437,4 +475,62 @@ void plot<VS,RM>::set_limits(const agg::rect_base<double>& r) compute_user_trans(); } +template<class VS, class RM> +void plot<VS,RM>::layer_dispose_elements(plot<VS,RM>::item_list& layer) +{ + unsigned n = layer.size(); + for (unsigned k = 0; k < n; k++) + { + RM::dispose(layer[k].vs); + } +} + +template<class VS, class RM> +bool plot<VS,RM>::push_layer() +{ + if (m_layers.size() >= max_layers) + return false; + + item_list *new_layer = new(std::nothrow) item_list(); + if (new_layer == 0) + return false; + + commit_pending_draw(); + m_layers.add(new_layer); + m_current_layer = new_layer; + + return true; +} + +template<class VS, class RM> +bool plot<VS,RM>::pop_layer() +{ + unsigned n = m_layers.size(); + + if (n == 0) + return false; + + item_list *layer = m_layers[n-1]; + layer_dispose_elements (*layer); + delete layer; + + m_layers.inc_size(-1); + n--; + + clear_drawing_queue(); + m_need_redraw = true; + m_current_layer = (n > 0 ? m_layers[n-1] : &m_root_layer); + + return true; +} + +template <class VS, class RM> +void plot<VS,RM>::clear_current_layer() +{ + clear_drawing_queue(); + layer_dispose_elements (current_layer()); + m_current_layer->clear(); + m_need_redraw = true; +} + #endif |