add new canvas Image item, with somewhat optimized API for asynchronous, threaded...
authorPaul Davis <paul@linuxaudiosystems.com>
Tue, 16 Apr 2013 01:40:15 +0000 (21:40 -0400)
committerPaul Davis <paul@linuxaudiosystems.com>
Tue, 16 Apr 2013 01:40:15 +0000 (21:40 -0400)
libs/canvas/canvas/image.h [new file with mode: 0644]
libs/canvas/image.cc [new file with mode: 0644]
libs/canvas/wscript

diff --git a/libs/canvas/canvas/image.h b/libs/canvas/canvas/image.h
new file mode 100644 (file)
index 0000000..e23e922
--- /dev/null
@@ -0,0 +1,57 @@
+#ifndef __CANVAS_IMAGE__
+#define __CANVAS_IMAGE__
+
+#include <stdint.h>
+#include <boost/shared_ptr.hpp>
+#include <boost/shared_array.hpp>
+
+#include "canvas/item.h"
+
+namespace ArdourCanvas {
+
+class Image : public Item
+{
+public:
+    Image (Group *, Cairo::Format, int width, int height);
+    
+    struct Data {
+       Data (boost::shared_array<uint8_t> d, int w, int h, int s, Cairo::Format fmt)
+               : data (d)
+               , width (w)
+               , height (h)
+               , stride (s)
+               , format (fmt)
+       {}
+
+       boost::shared_array<uint8_t> data;
+       int width;
+       int height;
+       int stride;
+       Cairo::Format format;
+    };
+
+    boost::shared_ptr<Data> get_image ();
+    void put_image (boost::shared_ptr<Data>);
+
+    void render (Rect const &, Cairo::RefPtr<Cairo::Context>) const;
+    void compute_bounding_box () const;
+    XMLNode* get_state () const;
+    void set_state (XMLNode const *);
+    
+private:
+    Cairo::Format            _format;
+    int                      _width;
+    int                      _height;
+    int                      _data;
+    mutable boost::shared_ptr<Data>  _current;
+    boost::shared_ptr<Data>  _pending;
+    mutable bool             _need_render;
+    mutable Cairo::RefPtr<Cairo::Surface> _surface;
+
+    void accept_data ();
+    PBD::Signal0<void> DataReady;
+    PBD::ScopedConnectionList data_connections;
+};
+
+}
+#endif
diff --git a/libs/canvas/image.cc b/libs/canvas/image.cc
new file mode 100644 (file)
index 0000000..0c7ce6e
--- /dev/null
@@ -0,0 +1,80 @@
+#include "canvas/image.h"
+
+#include "gtkmm2ext/gui_thread.h"
+
+#include "pbd/xml++.h"
+
+using namespace ArdourCanvas;
+
+Image::Image (Group* group, Cairo::Format fmt, int width, int height)
+       : Item (group)
+       , _format (fmt)
+       , _width (width)
+       , _height (height)
+       , _need_render (false)
+{
+       DataReady.connect (data_connections, MISSING_INVALIDATOR, boost::bind (&Image::accept_data, this), gui_context());
+}
+
+void 
+Image::render (Rect const& area, Cairo::RefPtr<Cairo::Context> context) const
+{
+       if (_current) {
+               _surface = Cairo::ImageSurface::create (_current->data.get(),
+                                                       _current->format,
+                                                       _current->width,
+                                                       _current->height,
+                                                       _current->stride);
+       }
+
+       _current.reset ();
+
+       context->set_source (_surface, 0, 0);
+       context->rectangle (area.x0, area.y0, area.width(), area.height());
+       context->fill ();
+}
+
+void
+Image::compute_bounding_box () const
+{
+       _bounding_box = boost::optional<Rect> (Rect (0, 0, _width, _height));
+       _bounding_box_dirty = false;
+}
+
+boost::shared_ptr<Image::Data>
+Image::get_image ()
+{
+       int stride = Cairo::ImageSurface::format_stride_for_width (_format, _width);
+       boost::shared_ptr<Data> d (new Data (boost::shared_array<uint8_t> (new uint8_t[stride*_height]), _width, _height, stride, _format));
+
+       return d;
+}
+
+void
+Image::put_image (boost::shared_ptr<Data> d)
+{
+       _pending = d;
+       DataReady (); /* EMIT SIGNAL */
+}
+
+void
+Image::accept_data () 
+{
+       /* must be executed in gui thread */
+       _current = _pending;
+       _pending.reset ();
+       _need_render = true;
+}           
+
+XMLNode *
+Image::get_state () const
+{
+       /* XXX */
+       return new XMLNode ("Image");
+}
+
+void
+Image::set_state (XMLNode const * /*node*/)
+{
+       /* XXX */
+}
index 5b36edcb038892e102c9c342c232cc855f29efc0..eb1613c1176c9c41e10280bf106a2507c1e2d079 100644 (file)
@@ -36,6 +36,7 @@ canvas_sources = [
        'fill.cc',
         'flag.cc',
        'group.cc',
+        'image.cc',
        'item_factory.cc',
        'line.cc',
         'line_set.cc',
@@ -72,7 +73,7 @@ def build(bld):
 
     obj.export_includes = ['.']
     obj.includes     = ['.']
-    obj.uselib       = 'SIGCPP CAIROMM GTKMM'
+    obj.uselib       = 'SIGCPP CAIROMM GTKMM BOOST'
     obj.use          = [ 'libpbd', 'libevoral', 'libardour', 'libgtkmm2ext' ]
     obj.name         = 'libcanvas'
     obj.target       = 'canvas'