summaryrefslogtreecommitdiff
path: root/libs/canvas
diff options
context:
space:
mode:
authorRobin Gareus <robin@gareus.org>2014-10-28 02:15:10 +0100
committerRobin Gareus <robin@gareus.org>2014-10-28 02:15:10 +0100
commitb04414d170bff6d3d7cbfdcedd2dcab917fa3e18 (patch)
treec373438261496bd18f87b85ef1277b9c593cb9d3 /libs/canvas
parent6dc3a4bf61b0b5cd7947af6c5c9099f09c32b934 (diff)
allow to use cairo-image/software surface for canvas & cairowidgets
Diffstat (limited to 'libs/canvas')
-rw-r--r--libs/canvas/canvas.cc52
-rw-r--r--libs/canvas/canvas/canvas.h3
2 files changed, 54 insertions, 1 deletions
diff --git a/libs/canvas/canvas.cc b/libs/canvas/canvas.cc
index 02127da36a..9d1d9f3ad9 100644
--- a/libs/canvas/canvas.cc
+++ b/libs/canvas/canvas.cc
@@ -720,6 +720,18 @@ GtkCanvas::item_going_away (Item* item, boost::optional<Rect> bounding_box)
}
+void
+GtkCanvas::on_size_allocate (Gtk::Allocation& a)
+{
+ EventBox::on_size_allocate (a);
+#ifdef USE_CAIRO_IMAGE_SURFACE
+ /* allocate an image surface as large as the canvas itself */
+
+ canvas_image.clear ();
+ canvas_image = Cairo::ImageSurface::create (Cairo::FORMAT_ARGB32, a.get_width(), a.get_height());
+#endif
+}
+
/** Handler for GDK expose events.
* @param ev Event.
* @return true if the event was handled.
@@ -727,11 +739,49 @@ GtkCanvas::item_going_away (Item* item, boost::optional<Rect> bounding_box)
bool
GtkCanvas::on_expose_event (GdkEventExpose* ev)
{
+#ifdef USE_CAIRO_IMAGE_SURFACE
+ if (!canvas_image) {
+ canvas_image = Cairo::ImageSurface::create (Cairo::FORMAT_ARGB32, get_width(), get_height());
+ }
+
+ {
+ /* scope for image_context */
+ Cairo::RefPtr<Cairo::Context> image_context = Cairo::Context::create (canvas_image);
+
+ /* clear expose area to transparent */
+
+ image_context->save ();
+ image_context->rectangle (ev->area.x, ev->area.y, ev->area.width, ev->area.height);
+ image_context->clip ();
+ image_context->set_operator (Cairo::OPERATOR_CLEAR);
+ image_context->paint ();
+ image_context->restore ();
+
+ /* render into image surface */
+
+ render (Rect (ev->area.x, ev->area.y, ev->area.x + ev->area.width, ev->area.y + ev->area.height), image_context);
+
+ /* image surface is flushed when image_context goes out of scope */
+ }
+
+ /* now blit our private surface back to the GDK one */
+
+ Cairo::RefPtr<Cairo::Context> cairo_context = get_window()->create_cairo_context ();
+
+ cairo_context->rectangle (ev->area.x, ev->area.y, ev->area.width, ev->area.height);
+ cairo_context->clip ();
+ cairo_context->set_source (canvas_image, 0, 0);
+ cairo_context->set_operator (Cairo::OPERATOR_SOURCE);
+ cairo_context->paint ();
+
+#else
+
Cairo::RefPtr<Cairo::Context> cairo_context = get_window()->create_cairo_context ();
render (Rect (ev->area.x, ev->area.y, ev->area.x + ev->area.width, ev->area.y + ev->area.height), cairo_context);
- return true;
+#endif
+ return true;
}
/** Handler for GDK scroll events.
diff --git a/libs/canvas/canvas/canvas.h b/libs/canvas/canvas/canvas.h
index c45908f0b3..107ea0d7b2 100644
--- a/libs/canvas/canvas/canvas.h
+++ b/libs/canvas/canvas/canvas.h
@@ -190,6 +190,7 @@ public:
void stop_tooltip_timeout ();
protected:
+ void on_size_allocate (Gtk::Allocation&);
bool on_scroll_event (GdkEventScroll *);
bool on_expose_event (GdkEventExpose *);
bool on_button_press_event (GdkEventButton *);
@@ -210,6 +211,8 @@ private:
void item_going_away (Item *, boost::optional<Rect>);
bool send_leave_event (Item const *, double, double) const;
+ Cairo::RefPtr<Cairo::Surface> canvas_image;
+
/** Item currently chosen for event delivery based on pointer position */
Item * _current_item;
/** Item pending as _current_item */