summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libs/canvas/canvas/surface_group.h48
-rw-r--r--libs/canvas/surface_group.cc114
-rw-r--r--libs/canvas/wscript1
3 files changed, 163 insertions, 0 deletions
diff --git a/libs/canvas/canvas/surface_group.h b/libs/canvas/canvas/surface_group.h
new file mode 100644
index 0000000000..620038a802
--- /dev/null
+++ b/libs/canvas/canvas/surface_group.h
@@ -0,0 +1,48 @@
+/*
+ Copyright (C) 2011-2013 Paul Davis
+ Author: Robin Gareus <robin@gareus.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#ifndef __CANVAS_SURFACE_GROUP_H__
+#define __CANVAS_SURFACE_GROUP_H__
+
+#include <list>
+#include <vector>
+
+#include "canvas/visibility.h"
+#include "canvas/group.h"
+
+namespace ArdourCanvas {
+
+class LIBCANVAS_API SurfaceGroup : public Group
+{
+public:
+ explicit SurfaceGroup (Group *);
+ explicit SurfaceGroup (Group *, Duple);
+ ~SurfaceGroup ();
+
+ void render (Rect const &, Cairo::RefPtr<Cairo::Context>) const;
+
+private:
+ mutable Duple _surface_position;
+ mutable Duple _surface_geometry;
+ mutable Cairo::RefPtr<Cairo::ImageSurface> _surface;
+};
+
+}
+
+#endif
diff --git a/libs/canvas/surface_group.cc b/libs/canvas/surface_group.cc
new file mode 100644
index 0000000000..517e8ab1b3
--- /dev/null
+++ b/libs/canvas/surface_group.cc
@@ -0,0 +1,114 @@
+/*
+ Copyright (C) 2011-2013 Paul Davis
+ Author: Robin Gareus <robin@gareus.org>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <iostream>
+#include <cairomm/context.h>
+
+#include "canvas/surface_group.h"
+
+using namespace std;
+using namespace ArdourCanvas;
+
+SurfaceGroup::SurfaceGroup (Group* parent)
+ : Group (parent)
+ , _surface_position (0,0)
+ , _surface_geometry (0,0)
+ , _surface (0)
+{
+
+}
+
+SurfaceGroup::SurfaceGroup (Group* parent, Duple position)
+ : Group (parent, position)
+ , _surface_geometry (0,0)
+ , _surface (0)
+{
+
+}
+
+SurfaceGroup::~SurfaceGroup ()
+{
+
+}
+
+void
+SurfaceGroup::render (Rect const & area, Cairo::RefPtr<Cairo::Context> context) const
+{
+ bool re_expose = false;
+ boost::optional<Rect> bb = bounding_box ();
+
+ if (bb) {
+ Duple geo = Duple (bb->width (), bb->height ());
+ if (geo != _surface_geometry) {
+ re_expose = true;
+#if 0 // DEBUG
+ printf ("re allocate surface group %1.f x %.1f @ %1.f x %.1f self: %1.f x %.1f\n",
+ geo.x, geo.y, bb->x0, bb->y0, _position.x, _position.y);
+#endif
+ if (geo.x > 32768 || geo.y > 32768) {
+ // TODO allocate N surfaces, render at offset and stitch them together.
+ // OR use one surfacen and re-expose child items when offset changes
+ return;
+ }
+
+ _surface = Cairo::ImageSurface::create (Cairo::FORMAT_ARGB32, geo.x, geo.y);
+ _surface_geometry = geo;
+ _surface_position = Duple (bb->x0, bb->y0);
+ }
+ }
+
+ if (!_surface) return;
+
+ Rect a (0, 0, _surface_geometry.x, _surface_geometry.y);
+
+ if (!re_expose) {
+ Duple tmp_p0 = window_to_item (Duple (area.x0, area.y0));
+ Duple tmp_p1 = window_to_item (Duple (area.x1, area.y1));
+ Rect wa (tmp_p0.x, tmp_p0.y, tmp_p1.x, tmp_p1.y);
+ boost::optional<Rect> d = a.intersection (wa);
+ assert (d);
+ a = d.get ();
+ }
+
+ Duple window_space;
+ window_space = item_to_window (Duple (_position.x + _surface_position.x, _position.y + _surface_position.y));
+ Cairo::RefPtr<Cairo::Context> cr = Cairo::Context::create (_surface);
+
+#if 1 // clear surface, needed if any content is semi-transparent
+ cr->save ();
+ cr->set_operator (Cairo::OPERATOR_CLEAR);
+ cr->rectangle (a.x0, a.y0, a.x1, a.y1);
+ cr->fill ();
+ cr->restore ();
+#endif
+
+#if 0 // DEBUG
+ printf ("EXPOSE: %1.f x %.1f -> %1.f x %.1f\n", a.x0, a.y0, a.x1, a.y1);
+ Rect dbg = item_to_window (a);
+ printf ("RENDER: %1.f x %.1f -> %1.f x %.1f WS: %1.f x %.1f \n",
+ dbg.x0, dbg.y0, dbg.x1, dbg.y1, window_space.x, -window_space.y);
+#endif
+
+ cr->translate (-window_space.x, -window_space.y);
+
+ Group::render (item_to_window (a), cr);
+
+ context->set_source (_surface, window_space.x, window_space.y);
+ context->paint ();
+}
diff --git a/libs/canvas/wscript b/libs/canvas/wscript
index 0c5192645c..3121cc4657 100644
--- a/libs/canvas/wscript
+++ b/libs/canvas/wscript
@@ -51,6 +51,7 @@ canvas_sources = [
'rectangle.cc',
'root_group.cc',
'stateful_image.cc',
+ 'surface_group.cc',
'text.cc',
'types.cc',
'utils.cc',