diff options
author | Robin Gareus <robin@gareus.org> | 2014-10-28 02:15:10 +0100 |
---|---|---|
committer | Robin Gareus <robin@gareus.org> | 2014-10-28 02:15:10 +0100 |
commit | b04414d170bff6d3d7cbfdcedd2dcab917fa3e18 (patch) | |
tree | c373438261496bd18f87b85ef1277b9c593cb9d3 /libs/canvas/canvas.cc | |
parent | 6dc3a4bf61b0b5cd7947af6c5c9099f09c32b934 (diff) |
allow to use cairo-image/software surface for canvas & cairowidgets
Diffstat (limited to 'libs/canvas/canvas.cc')
-rw-r--r-- | libs/canvas/canvas.cc | 52 |
1 files changed, 51 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. |