-rw-r--r-- | agg-plot/plot.h | 15 | ||||
-rw-r--r-- | agg-plot/rect.h | 16 | ||||
-rw-r--r-- | fox-gui/Makefile | 2 | ||||
-rw-r--r-- | fox-gui/fx_plot_canvas.cpp | 248 | ||||
-rw-r--r-- | fox-gui/fx_plot_canvas.h | 77 | ||||
-rw-r--r-- | fox-gui/image_buf.h | 16 | ||||
-rw-r--r-- | fox-gui/lua_plot_window.cpp | 58 | ||||
-rw-r--r-- | fox-gui/window_part.cpp | 5 | ||||
-rw-r--r-- | fox-gui/window_part.h | 2 | ||||
-rw-r--r-- | fox-gui/window_surface.cpp | 142 | ||||
-rw-r--r-- | fox-gui/window_surface.h | 91 |
diff --git a/agg-plot/plot.h b/agg-plot/plot.h index 0ab76a89..06d0d35a 100644 --- a/agg-plot/plot.h +++ b/agg-plot/plot.h @@ -466,6 +466,11 @@ protected: bool m_need_redraw; opt_rect<double> m_rect; + // keep trace of the region where changes happened since + // the last pushlayer or clear + opt_rect<double> m_changes_accu; + opt_rect<double> m_changes_pending; + bool m_use_units; units m_ux, m_uy; @@ -505,6 +510,7 @@ void plot<RM>::commit_pending_draw() { push_drawing_queue(); m_need_redraw = false; + m_changes_pending.clear(); } template <class RM> @@ -642,6 +648,13 @@ template <class Canvas> void plot<RM>::draw_queue(Canvas& _canvas, const agg::tr bb.add<rect_union>(ebb); } + m_changes_accu.add<rect_union>(bb); + + if (m_changes_pending.is_defined()) + { + bb.add<rect_union>(m_changes_pending); + } + canvas.reset_clipping(); } @@ -1114,6 +1127,8 @@ void plot<RM>::clear_current_layer() clear_drawing_queue(); layer_dispose_elements(current); current->clear(); + m_changes_pending = m_changes_accu; + m_changes_accu.clear(); } template <class RM> diff --git a/agg-plot/rect.h b/agg-plot/rect.h index 3205da6c..d768d0dd 100644 --- a/agg-plot/rect.h +++ b/agg-plot/rect.h @@ -20,10 +20,20 @@ public: void clear() { m_defined = false; }; + void set(const rect_type& r) { m_defined = true; m_rect = r; }; + + void set(T x1, T y1, T x2, T y2) { + m_defined = true; + m_rect.x1 = x1; + m_rect.y1 = y1; + m_rect.x2 = x2; + m_rect.y2 = y2; + }; + bool is_defined() const { return m_defined; }; @@ -41,6 +51,12 @@ public: m_rect = src.m_rect; } + void operator = (const rect_type& src) + { + m_defined = true; + m_rect = src; + } + template <set_oper_e op> void add(const rect_type& r) { diff --git a/fox-gui/Makefile b/fox-gui/Makefile index c3d99526..0d793220 100644 --- a/fox-gui/Makefile +++ b/fox-gui/Makefile @@ -36,7 +36,7 @@ INCLUDES += -I$(GSH_BASE_DIR) -I$(GSH_BASE_DIR)/lua-gsl -I$(GSH_BASE_DIR)/agg-pl INCLUDES += $(AGG_INCLUDES) $(FOX_INCLUDES) $(FREETYPE_INCLUDES) $(PTHREADS_CFLAGS) LIBS += $(GSL_SHELL_LIBS) $(FOX_LIBS) $(AGG_LIBS) $(FREETYPE_LIBS) $(PTHREADS_LIBS) $(GSL_LIBS) -lsupc++ -lm -FOXGUI_SRC_FILES = io_thread.cpp fx_console.cpp redirect.cpp gsl_shell_interp.cpp gsl_shell_thread.cpp fox_gsl_shell.cpp gsl_shell_window.cpp window_part.cpp fx_plot_canvas.cpp fx_plot_window.cpp lua_plot_window.cpp gsl_shell_app.cpp gsl-shell-fox.cpp +FOXGUI_SRC_FILES = io_thread.cpp window_surface.cpp fx_console.cpp redirect.cpp gsl_shell_interp.cpp gsl_shell_thread.cpp fox_gsl_shell.cpp gsl_shell_window.cpp window_part.cpp fx_plot_canvas.cpp fx_plot_window.cpp lua_plot_window.cpp gsl_shell_app.cpp gsl-shell-fox.cpp FOXGUI_OBJ_FILES := $(FOXGUI_SRC_FILES:%.cpp=%.o) DEP_FILES := $(FOXGUI_SRC_FILES:%.cpp=.deps/%.P) diff --git a/fox-gui/fx_plot_canvas.cpp b/fox-gui/fx_plot_canvas.cpp index d96a0943..879a2135 100644 --- a/fox-gui/fx_plot_canvas.cpp +++ b/fox-gui/fx_plot_canvas.cpp @@ -8,91 +8,22 @@ FXDEFMAP(fx_plot_canvas) fx_plot_canvas_map[]= { FXMAPFUNC(SEL_PAINT, 0, fx_plot_canvas::on_cmd_paint), - FXMAPFUNC(SEL_UPDATE, 0, fx_plot_canvas::on_update), }; FXIMPLEMENT(fx_plot_canvas,FXCanvas,fx_plot_canvas_map,ARRAYNUMBER(fx_plot_canvas_map)); fx_plot_canvas::fx_plot_canvas(FXComposite* p, const char* split_str, FXObject* tgt, FXSelector sel, FXuint opts, FXint x, FXint y, FXint w, FXint h): - FXCanvas(p, tgt, sel, opts, x, y, w, h), - m_img(), m_save_img(), m_canvas(0) + FXCanvas(p, tgt, sel, opts, x, y, w, h), m_surface(split_str) { - split(split_str ? split_str : "."); -} - -fx_plot_canvas::~fx_plot_canvas() -{ - delete m_canvas; -} - -void fx_plot_canvas::split(const char* split_str) -{ - m_part.parse(split_str); - m_part.split(); - - m_plots.clear(); - plot_ref empty; - for (unsigned k = 0; k < m_part.get_slot_number(); k++) - m_plots.add(empty); -} - -bool fx_plot_canvas::prepare_image_buffer(unsigned ww, unsigned hh) -{ - if (likely(m_img.resize(ww, hh))) - { - m_canvas = new(std::nothrow) canvas(m_img, ww, hh, colors::white); - plots_set_to_dirty(); - return (m_canvas != NULL); - } - return false; -} - -bool fx_plot_canvas::ensure_canvas_size(unsigned ww, unsigned hh) -{ - if (unlikely(m_img.width() != ww || m_img.height() != hh)) - { - return prepare_image_buffer(ww, hh); - } - return true; -} - -void fx_plot_canvas::plot_render(plot_ref& ref, const agg::rect_i& r) -{ - m_canvas->clear_box(r); - if (ref.plot) - { - AGG_LOCK(); - ref.plot->draw(*m_canvas, r, &ref.inf); - AGG_UNLOCK(); - } - ref.is_image_dirty = false; -} - -void fx_plot_canvas::plot_render(unsigned index) -{ - plot_ref& ref = m_plots[index]; - int ww = getWidth(), hh = getHeight(); - agg::rect_i r = m_part.rect(index, ww, hh); - plot_render(ref, r); -} - -opt_rect<double> -fx_plot_canvas::plot_render_queue(plot_ref& ref, const agg::rect_i& box) -{ - const agg::trans_affine m = affine_matrix(box); - opt_rect<double> r, draw_rect; - AGG_LOCK(); - ref.plot->draw_queue(*m_canvas, m, ref.inf, draw_rect); - AGG_UNLOCK(); - r.add<rect_union>(draw_rect); - r.add<rect_union>(ref.dirty_rect); - ref.dirty_rect = draw_rect; - return r; } void fx_plot_canvas::update_region(const agg::rect_i& r) { FXshort ww = r.x2 - r.x1, hh= r.y2 - r.y1; + if (ww <= 0 || hh <= 0) return; + + const image& src_img = m_surface.get_image(); + FXImage img(getApp(), NULL, IMAGE_OWNED|IMAGE_SHMI|IMAGE_SHMP, ww, hh); const unsigned fox_pixel_size = 4; @@ -101,7 +32,7 @@ void fx_plot_canvas::update_region(const agg::rect_i& r) dest.attach((agg::int8u*) img.getData(), ww, hh, -ww * fox_pixel_size); rendering_buffer_ro src; - rendering_buffer_get_const_view(src, m_img, r, image_pixel_width); + rendering_buffer_get_const_view(src, src_img, r, window_surface::image_pixel_width); my_color_conv(&dest, &src, color_conv_rgb24_to_rgba32()); @@ -111,151 +42,82 @@ void fx_plot_canvas::update_region(const agg::rect_i& r) dc.drawImage(&img, r.x1, getHeight() - r.y2); } -void fx_plot_canvas::plot_draw(unsigned index, int canvas_width, int canvas_height) -{ - plot_ref& ref = m_plots[index]; - agg::rect_i r = m_part.rect(index, canvas_width, canvas_height); - if (ref.is_image_dirty) - plot_render(ref, r); - update_region(r); - ref.is_dirty = false; -} - -sg_plot* fx_plot_canvas::get_plot(unsigned index, int canvas_width, int canvas_height, agg::rect_i& area) +void fx_plot_canvas::update_plot_region(unsigned index) { - plot_ref& ref = m_plots[index]; - if (ref.plot) - area = m_part.rect(index, canvas_width, canvas_height); - return ref.plot; + agg::rect_i area = m_surface.get_plot_area(index); + update_region(area); } -void fx_plot_canvas::plot_draw(unsigned index) +int fx_plot_canvas::attach(sg_plot* p, const char* slot_str) { - int ww = getWidth(), hh = getHeight(); - plot_draw(index, ww, hh); + return m_surface.attach(p, slot_str); } -void -fx_plot_canvas::plot_draw_queue(unsigned index, int canvas_width, int canvas_height, bool draw_all) +void fx_plot_canvas::slot_refresh(unsigned index) { - plot_ref& ref = m_plots[index]; - - if (!ref.plot) return; - - agg::rect_i r = m_part.rect(index, canvas_width, canvas_height); - opt_rect<double> rect = plot_render_queue(ref, r); + bool redraw = m_surface.plot(index)->need_redraw(); + if (redraw) + { + m_surface.render(index); + } - if (draw_all) + opt_rect<int> r = m_surface.render_drawing_queue(index); + agg::rect_i area = m_surface.get_plot_area(index); + if (redraw) { - update_region(r); + update_region(area); } - else if (rect.is_defined()) + else { - const int pd = 4; - const agg::rect_d& ur = rect.rect(); - const agg::rect_i box(0, 0, canvas_width, canvas_height); - agg::rect_i ri(ur.x1 - pd, ur.y1 - pd, ur.x2 + pd, ur.y2 + pd); - ri.clip(box); - update_region(ri); + if (r.is_defined()) + { + const int pad = 4; + const agg::rect_i& ri = r.rect(); + agg::rect_i r_pad(ri.x1 - pad, ri.y1 - pad, ri.x2 + pad, ri.y2 + pad); + r_pad.clip(area); + update_region(r_pad); + } } } - -void fx_plot_canvas::plot_draw_queue(unsigned index, bool draw_all) -{ - int ww = getWidth(), hh = getHeight(); - plot_draw_queue(index, ww, hh, draw_all); -} - -void plot_ref::attach(sg_plot* p) +void +fx_plot_canvas::slot_update(unsigned index) { - plot = p; - is_dirty = true; - is_image_dirty = true; - dirty_rect.clear(); + m_surface.render(index); + m_surface.render_drawing_queue(index); + update_plot_region(index); } -int fx_plot_canvas::attach(sg_plot* p, const char* slot_str) +void +fx_plot_canvas::save_slot_image(unsigned index) { - int index = m_part.get_slot_index(slot_str); - if (index >= 0) - m_plots[index].attach(p); - return index; + m_surface.save_plot_image(index); } -bool fx_plot_canvas::save_plot_image(unsigned index) -{ - int ww = getWidth(), hh = getHeight(); - - if (!m_save_img.ensure_size(ww, hh)) return false; - - plot_ref& ref = m_plots[index]; - agg::rect_i r = m_part.rect(index, ww, hh); - - if (ref.is_image_dirty) - plot_render(ref, r); - - rendering_buffer_ro src; - rendering_buffer_get_const_view(src, m_img, r, image_pixel_width); - - agg::rendering_buffer dest; - rendering_buffer_get_view(dest, m_save_img, r, image_pixel_width); - - dest.copy_from(src); - return true; -} - -bool fx_plot_canvas::restore_plot_image(unsigned index) -{ - int ww = getWidth(), hh = getHeight(); - - if (!image::match(m_img, m_save_img)) - return false; - - agg::rect_i r = m_part.rect(index, ww, hh); - - rendering_buffer_ro src; - rendering_buffer_get_const_view(src, m_save_img, r, image_pixel_width); - - agg::rendering_buffer dest; - rendering_buffer_get_view(dest, m_img, r, image_pixel_width); - - dest.copy_from(src); - return true; -} - -long fx_plot_canvas::on_cmd_paint(FXObject *, FXSelector, void *ptr) +void +fx_plot_canvas::restore_slot_image(unsigned index) { - int ww = getWidth(), hh = getHeight(); - if (unlikely(!ensure_canvas_size(ww, hh))) - return 1; - for (unsigned k = 0; k < m_plots.size(); k++) + if (m_surface.have_saved_image(index)) { - plot_draw(k, ww, hh); + m_surface.restore_plot_image(index); + } + else + { + m_surface.render(index); + m_surface.save_plot_image(index); } - return 1; } -long fx_plot_canvas::on_update(FXObject *, FXSelector, void *) +long fx_plot_canvas::on_cmd_paint(FXObject *, FXSelector, void *ptr) { int ww = getWidth(), hh = getHeight(); - if (unlikely(!ensure_canvas_size(ww, hh))) - return 1; - for (unsigned k = 0; k < m_plots.size(); k++) + + if (!m_surface.canvas_size_match(ww, hh)) { - plot_ref& ref = m_plots[k]; - if (ref.is_dirty) - { - plot_draw(k, ww, hh); - } + m_surface.resize(ww, hh); + m_surface.draw_image_buffer(); } - return 1; -} -void fx_plot_canvas::plots_set_to_dirty() -{ - for (unsigned k = 0; k < m_plots.size(); k++) - { - plot_ref& ref = m_plots[k]; - ref.is_image_dirty = true; - } + agg::rect_i r(0, 0, ww, hh); + update_region(r); + return 1; } diff --git a/fox-gui/fx_plot_canvas.h b/fox-gui/fx_plot_canvas.h index de54e63d..3609c968 100644 --- a/fox-gui/fx_plot_canvas.h +++ b/fox-gui/fx_plot_canvas.h @@ -1,95 +1,50 @@ #ifndef FOXGUI_FX_PLOT_CANVAS_H #define FOXGUI_FX_PLOT_CANVAS_H -#include <new> #include <fx.h> #include <agg_basics.h> #include <agg_rendering_buffer.h> #include <agg_trans_affine.h> -#include "image_buf.h" -#include "window_part.h" -#include "sg_object.h" -#include "lua-plot-cpp.h" -#include "canvas.h" -#include "rect.h" - -struct plot_ref { - plot_ref(): plot(NULL) {} - - void attach(sg_plot* p); - - sg_plot* plot; - plot_render_info inf; - bool is_dirty; - bool is_image_dirty; - opt_rect<double> dirty_rect; -}; +#include "window_surface.h" class fx_plot_canvas : public FXCanvas { FXDECLARE(fx_plot_canvas) - enum { image_pixel_width = 3 }; - - typedef image_gen<image_pixel_width, true> image; + typedef window_surface::image image; public: fx_plot_canvas(FXComposite* p, const char* split, FXObject* tgt=NULL, FXSelector sel=0, FXuint opts=FRAME_NORMAL, FXint x=0, FXint y=0, FXint w=0, FXint h=0); - ~fx_plot_canvas(); - int attach(sg_plot* p, const char* slot_str); - void split(const char* split_str); - - void update_region(const agg::rect_base<int>& r); - void plot_draw(unsigned index); - void plot_draw_queue(unsigned index, bool draw_all); - void plot_render(unsigned index); + bool is_ready() const { return m_surface.is_ready(); } - sg_plot* get_plot(unsigned index, int canvas_width, int canvas_height, agg::rect_i& area); - unsigned get_plot_number() const { return m_plots.size(); } + sg_plot* get_plot(unsigned index) const { return m_surface.plot(index); } + unsigned get_plot_number() const { return m_surface.plot_number(); } + agg::rect_i get_plot_area(unsigned index, int w, int h) const { return m_surface.get_plot_area(index, w, h); } - bool need_redraw(unsigned index) - { - return m_plots[index].plot->need_redraw(); - } + void draw(unsigned index); - bool is_ready() const { return (m_canvas != 0); } - - bool save_plot_image(unsigned index); - bool restore_plot_image(unsigned index); + void slot_refresh(unsigned index); + void slot_update(unsigned index); + void save_slot_image(unsigned index); + void restore_slot_image(unsigned index); long on_cmd_paint(FXObject *, FXSelector, void *); - long on_update(FXObject *, FXSelector, void *); protected: - fx_plot_canvas() {} + fx_plot_canvas(): m_surface(NULL) {} private: - bool prepare_image_buffer(unsigned ww, unsigned hh); - bool ensure_canvas_size(unsigned ww, unsigned hh); - void plots_set_to_dirty(); - - void plot_render(plot_ref& ref, const agg::rect_i& r); - void plot_draw(unsigned index, int canvas_width, int canvas_height); - opt_rect<double> plot_render_queue(plot_ref& ref, const agg::rect_i& r); - void plot_draw_queue(unsigned index, int canvas_width, int canvas_height, bool draw_all); - - bool plot_is_defined(unsigned index) - { - return (m_plots[index].plot != NULL); - } - - image m_img; - image m_save_img; - window_part m_part; - agg::pod_bvector<plot_ref> m_plots; - canvas* m_canvas; + void update_region(const agg::rect_i& r); + void update_plot_region(unsigned index); + + window_surface m_surface; }; #endif diff --git a/fox-gui/image_buf.h b/fox-gui/image_buf.h index 9136d8f7..2d36153c 100644 --- a/fox-gui/image_buf.h +++ b/fox-gui/image_buf.h @@ -1,9 +1,12 @@ #ifndef FOXGUI_IMAGE_BUF_H #define FOXGUI_IMAGE_BUF_H +#include <new> + #include "defs.h" -#include <agg_rendering_buffer.h> +#include "agg_rendering_buffer.h" +#include "rendering_buffer_utils.h" template <unsigned PixelSize, bool FlipY> struct image_gen : agg::rendering_buffer @@ -50,6 +53,17 @@ struct image_gen : agg::rendering_buffer return (a.width() == b.width() && a.height() == b.height()); } + static void copy_region(image_gen& dest_img, const image_gen& src_img, const agg::rect_i r) + { + rendering_buffer_ro src; + rendering_buffer_get_const_view(src, src_img, r, PixelSize); + + agg::rendering_buffer dest; + rendering_buffer_get_view(dest, dest_img, r, PixelSize); + + dest.copy_from(src); + } + private: bool init(unsigned w, unsigned h) { diff --git a/fox-gui/lua_plot_window.cpp b/fox-gui/lua_plot_window.cpp index 945ac09f..02acc1a9 100644 --- a/fox-gui/lua_plot_window.cpp +++ b/fox-gui/lua_plot_window.cpp @@ -147,7 +147,8 @@ fox_window_attach_try(lua_State *L) if (index < 0) return error_return(L, "invalid slot specification"); - canvas->plot_draw(index); + if (canvas->is_ready()) + canvas->slot_update(index); window_refs_add (L, index + 1, 1, 2); return 0; @@ -189,8 +190,8 @@ fox_window_close(lua_State* L) return nret; } -static int -fox_window_slot_generic_try(lua_State *L, void (*slot_func)(fx_plot_canvas*, unsigned)) +int +fx_canvas_slot_operation(lua_State *L, void (fx_plot_canvas::*method_ptr)(unsigned)) { window_mutex wm(L, 1); @@ -207,72 +208,40 @@ fox_window_slot_generic_try(lua_State *L, void (*slot_func)(fx_plot_canvas*, uns if (canvas->is_ready()) { - slot_func(canvas, slot_id - 1); + (canvas->*method_ptr)(slot_id - 1); } return 0; } -static void -slot_refresh(fx_plot_canvas* canvas, unsigned index) -{ - bool redraw = canvas->need_redraw(index); - if (redraw) - canvas->plot_render(index); - canvas->plot_draw_queue(index, redraw); -} - int fox_window_slot_refresh(lua_State* L) { - int nret = fox_window_slot_generic_try(L, slot_refresh); + int nret = fx_canvas_slot_operation(L, &fx_plot_canvas::slot_refresh); if (nret < 0) lua_error(L); return nret; } -static void -slot_update(fx_plot_canvas* canvas, unsigned index) -{ - canvas->plot_render(index); - canvas->plot_draw_queue(index, true); -} - int fox_window_slot_update(lua_State* L) { - int nret = fox_window_slot_generic_try(L, slot_update); + int nret = fx_canvas_slot_operation(L, &fx_plot_canvas::slot_update); if (nret < 0) lua_error(L); return nret; } -static void -save_slot_image(fx_plot_canvas* canvas, unsigned index) -{ - canvas->save_plot_image(index); -} - int fox_window_save_slot_image (lua_State *L) { - int nret = fox_window_slot_generic_try(L, save_slot_image); + int nret = fx_canvas_slot_operation(L, &fx_plot_canvas::save_slot_image); if (nret < 0) lua_error(L); return nret; } -static void -restore_slot_image(fx_plot_canvas* canvas, unsigned index) -{ - if (!canvas->restore_plot_image(index)) - { - canvas->plot_render(index); - canvas->save_plot_image(index); - } -} - int fox_window_restore_slot_image (lua_State *L) { - int nret = fox_window_slot_generic_try(L, restore_slot_image); + int nret = fx_canvas_slot_operation(L, &fx_plot_canvas::restore_slot_image); if (nret < 0) lua_error(L); return nret; } @@ -315,14 +284,14 @@ fox_window_export_svg_try(lua_State *L) unsigned n = fxcanvas->get_plot_number(); for (unsigned k = 0; k < n; k++) { - agg::rect_i box; char plot_name[64]; - sg_plot* p = fxcanvas->get_plot(k, int(w), int(h), box); + sg_plot* p = fxcanvas->get_plot(k); if (p) { + agg::rect_i area = fxcanvas->get_plot_area(k, int(w), int(h)); sprintf(plot_name, "plot%u", k + 1); canvas.write_group_header(plot_name); - p->draw(canvas, box, NULL); + p->draw(canvas, area, NULL); canvas.write_group_end(plot_name); } } @@ -337,8 +306,7 @@ int fox_window_export_svg(lua_State *L) { int nret = fox_window_export_svg_try(L); - if (unlikely(nret < 0)) - return lua_error(L); + if (nret < 0) return lua_error(L); return nret; } diff --git a/fox-gui/window_part.cpp b/fox-gui/window_part.cpp index 1f487c21..89d9b84c 100644 --- a/fox-gui/window_part.cpp +++ b/fox-gui/window_part.cpp @@ -175,10 +175,9 @@ window_part::get_slot_index(const char* str) } agg::rect_i -window_part::rect(unsigned index, int w, int h) +window_part::rect(unsigned index, int w, int h) const { -#warning TODO: enforce that rect is never bigger than canvas - rect_type& r = m_rect[index]; + const rect_type& r = m_rect[index]; return agg::rect_i(w * r.x1, h * r.y1, w * r.x2, h * r.y2); } diff --git a/fox-gui/window_part.h b/fox-gui/window_part.h index 99039cf0..d01b724d 100644 --- a/fox-gui/window_part.h +++ b/fox-gui/window_part.h @@ -23,7 +23,7 @@ public: int get_slot_index(const char* str); unsigned get_slot_number() const; - agg::rect_i rect(unsigned index, int canvas_width, int canvas_height); + agg::rect_i rect(unsigned index, int canvas_width, int canvas_height) const; private: int skip_node(int index, int& leaf_count); diff --git a/fox-gui/window_surface.cpp b/fox-gui/window_surface.cpp new file mode 100644 index 00000000..b44bb01d --- /dev/null +++ b/fox-gui/window_surface.cpp @@ -0,0 +1,142 @@ +#include "window_surface.h" + +#include "util/agg_color_conv_rgb8.h" + +#include "fatal.h" +#include "lua-graph.h" + +window_surface::window_surface(const char* split_str): +m_img(), m_save_img(), m_canvas(0) +{ + split(split_str ? split_str : "."); +} + +window_surface::~window_surface() +{ + delete m_canvas; +} + +void window_surface::split(const char* split_str) +{ + m_part.parse(split_str); + m_part.split(); + + m_plots.clear(); + plot_ref empty; + for (unsigned k = 0; k < m_part.get_slot_number(); k++) + m_plots.add(empty); +} + +bool window_surface::resize(unsigned ww, unsigned hh) +{ + m_save_img.clear(); + + for (unsigned k = 0; k < plot_number(); k++) + m_plots[k].have_save_img = false; + + if (likely(m_img.resize(ww, hh))) + { + m_canvas = new(std::nothrow) canvas(m_img, ww, hh, colors::white); + return (m_canvas != NULL); + } + return false; +} + +void window_surface::draw_image_buffer() +{ + for (unsigned k = 0; k < plot_number(); k++) + render(k); +} + +void window_surface::render(plot_ref& ref, const agg::rect_i& r) +{ + m_canvas->clear_box(r); + if (ref.plot) + { + graph_mutex::lock(); + ref.plot->draw(*m_canvas, r, &ref.inf); + graph_mutex::unlock(); + } +} + +void window_surface::render(unsigned index) +{ + int canvas_width = get_width(), canvas_height = get_height(); + plot_ref& ref = m_plots[index]; + agg::rect_i area = m_part.rect(index, canvas_width, canvas_height); + render(ref, area); +} + +opt_rect<int> +window_surface::render_drawing_queue(plot_ref& ref, const agg::rect_i& box) +{ + const agg::trans_affine m = affine_matrix(box); + opt_rect<double> r; + + graph_mutex::lock(); + ref.plot->draw_queue(*m_canvas, m, ref.inf, r); + graph_mutex::unlock(); + + opt_rect<int> ri; + if (r.is_defined()) + { + const agg::rect_d& rx = r.rect(); + ri.set(rx.x1, rx.y1, rx.x2, rx.y2); + } + + return ri; +} + +opt_rect<int> +window_surface::render_drawing_queue(unsigned index) +{ + int canvas_width = get_width(), canvas_height = get_height(); + plot_ref& ref = m_plots[index]; + + if (unlikely(!ref.plot)) + fatal_exception("call to plot_draw_queue for undefined plot"); + + agg::rect_i area = m_part.rect(index, canvas_width, canvas_height); + return render_drawing_queue(ref, area); +} + +int window_surface::attach(sg_plot* p, const char* slot_str) +{ + int index = m_part.get_slot_index(slot_str); + if (index >= 0) + m_plots[index].plot = p; + return index; +} + +bool window_surface::save_plot_image(unsigned index) +{ + int ww = get_width(), hh = get_height(); + if (unlikely(!m_save_img.ensure_size(ww, hh))) return false; + + agg::rect_i r = m_part.rect(index, ww, hh); + image::copy_region(m_save_img, m_img, r); + m_plots[index].have_save_img = true; + return true; +} + +bool window_surface::restore_plot_image(unsigned index) +{ + if (unlikely(!m_plots[index].have_save_img)) + fatal_exception("window_surface::restore_slot_image invalid restore image"); + + int ww = get_width(), hh = get_height(); + agg::rect_i r = m_part.rect(index, ww, hh); + image::copy_region(m_img, m_save_img, r); + return true; +} + +agg::rect_i window_surface::get_plot_area(unsigned index) const +{ + int canvas_width = get_width(), canvas_height = get_height(); + return m_part.rect(index, canvas_width, canvas_height); +} + +agg::rect_i window_surface::get_plot_area(unsigned index, int width, int height) const +{ + return m_part.rect(index, width, height); +} diff --git a/fox-gui/window_surface.h b/fox-gui/window_surface.h new file mode 100644 index 00000000..c92cbde0 --- /dev/null +++ b/fox-gui/window_surface.h @@ -0,0 +1,91 @@ +#ifndef FOXGUI_WINDOW_SURFACE_H +#define FOXGUI_WINDOW_SURFACE_H + +#include <fx.h> + +#include <agg_basics.h> +#include <agg_rendering_buffer.h> +#include <agg_trans_affine.h> + +#include "lua-graph.h" +#include "image_buf.h" +#include "window_part.h" +#include "sg_object.h" +#include "lua-plot-cpp.h" +#include "canvas.h" +#include "rect.h" + +struct plot_ref { + plot_ref(): plot(NULL), have_save_img(false) {} + + sg_plot* plot; + plot_render_info inf; + bool have_save_img; +}; + +struct graph_mutex { + static void lock() { AGG_LOCK(); } + static void unlock() { AGG_UNLOCK(); } +}; + +class window_surface +{ +public: + enum { image_pixel_width = 3 }; + typedef image_gen<image_pixel_width, true> image; + + window_surface(const char* split); + ~window_surface(); + + int attach(sg_plot* p, const char* slot_str); + void split(const char* split_str); + + bool canvas_size_match(unsigned ww, unsigned hh) + { + return (m_img.width() == ww && m_img.height() == hh); + } + + bool resize(unsigned ww, unsigned hh); + + // redraw all the image buffer for the current plots + void draw_image_buffer(); + + int get_width() const { return m_img.width(); } + int get_height() const { return m_img.height(); } + + void render(unsigned index); + opt_rect<int> render_drawing_queue(unsigned index); + + sg_plot* plot(unsigned index) const { return m_plots[index].plot; } + + agg::rect_i get_plot_area(unsigned index) const; + agg::rect_i get_plot_area(unsigned index, int width, int height) const; + unsigned plot_number() const { return m_plots.size(); } + + bool is_ready() const { return (m_canvas != 0); } + + bool save_plot_image(unsigned index); + bool restore_plot_image(unsigned index); + + const image& get_image() { return m_img; } + + bool have_saved_image(unsigned k) const { return m_plots[k].have_save_img; } + +private: + void render(plot_ref& ref, const agg::rect_i& r); + + opt_rect<int> render_drawing_queue(plot_ref& ref, const agg::rect_i& r); + + bool plot_is_defined(unsigned index) const + { + return (m_plots[index].plot != NULL); + } + + image m_img; + image m_save_img; + window_part m_part; + agg::pod_bvector<plot_ref> m_plots; + canvas* m_canvas; +}; + +#endif |