diff options
-rw-r--r-- | libs/canvas/canvas.cc | 52 | ||||
-rw-r--r-- | libs/canvas/canvas/canvas.h | 3 | ||||
-rw-r--r-- | libs/gtkmm2ext/cairo_widget.cc | 39 | ||||
-rw-r--r-- | libs/gtkmm2ext/gtkmm2ext/cairo_widget.h | 2 | ||||
-rw-r--r-- | wscript | 5 |
5 files changed, 93 insertions, 8 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 */ diff --git a/libs/gtkmm2ext/cairo_widget.cc b/libs/gtkmm2ext/cairo_widget.cc index 03c23000a2..5180c2e8d0 100644 --- a/libs/gtkmm2ext/cairo_widget.cc +++ b/libs/gtkmm2ext/cairo_widget.cc @@ -64,17 +64,27 @@ CairoWidget::on_button_press_event (GdkEventButton*) bool CairoWidget::on_expose_event (GdkEventExpose *ev) { - cairo_t* cr = gdk_cairo_create (get_window ()->gobj()); - cairo_rectangle (cr, ev->area.x, ev->area.y, ev->area.width, ev->area.height); - cairo_clip_preserve (cr); +#ifdef USE_CAIRO_IMAGE_SURFACE + + if (!image_surface) { + image_surface = Cairo::ImageSurface::create (Cairo::FORMAT_ARGB32, get_width(), get_height()); + } + + Cairo::RefPtr<Cairo::Context> cr = Cairo::Context::create (image_surface); +#else + Cairo::RefPtr<Cairo::Context> cr = get_window()->create_cairo_context (); +#endif + + cr->rectangle (ev->area.x, ev->area.y, ev->area.width, ev->area.height); + cr->clip_preserve (); /* paint expose area the color of the parent window bg */ Gdk::Color bg (get_parent_bg()); - cairo_set_source_rgb (cr, bg.get_red_p(), bg.get_green_p(), bg.get_blue_p()); - cairo_fill (cr); + cr->set_source_rgb (bg.get_red_p(), bg.get_green_p(), bg.get_blue_p()); + cr->fill (); cairo_rectangle_t expose_area; expose_area.x = ev->area.x; @@ -82,9 +92,20 @@ CairoWidget::on_expose_event (GdkEventExpose *ev) expose_area.width = ev->area.width; expose_area.height = ev->area.height; - render (cr, &expose_area); + render (cr->cobj(), &expose_area); - cairo_destroy (cr); +#ifdef USE_CAIRO_IMAGE_SURFACE + image_surface->flush(); + /* 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 (image_surface, 0, 0); + cairo_context->set_operator (Cairo::OPERATOR_SOURCE); + cairo_context->paint (); +#endif return true; } @@ -108,6 +129,10 @@ CairoWidget::on_size_allocate (Gtk::Allocation& alloc) { Gtk::EventBox::on_size_allocate (alloc); +#ifdef USE_CAIRO_IMAGE_SURFACE + image_surface = Cairo::ImageSurface::create (Cairo::FORMAT_ARGB32, alloc.get_width(), alloc.get_height()); +#endif + set_dirty (); } diff --git a/libs/gtkmm2ext/gtkmm2ext/cairo_widget.h b/libs/gtkmm2ext/gtkmm2ext/cairo_widget.h index 87002101bd..038198ab57 100644 --- a/libs/gtkmm2ext/gtkmm2ext/cairo_widget.h +++ b/libs/gtkmm2ext/gtkmm2ext/cairo_widget.h @@ -20,6 +20,7 @@ #ifndef __gtk2_ardour_cairo_widget_h__ #define __gtk2_ardour_cairo_widget_h__ +#include <cairomm/surface.h> #include <gtkmm/eventbox.h> #include "gtkmm2ext/visibility.h" @@ -116,6 +117,7 @@ protected: static sigc::slot<void> focus_handler; private: + Cairo::RefPtr<Cairo::Surface> image_surface; Glib::SignalProxyProperty _name_proxy; sigc::connection _parent_style_change; Widget * _current_parent; @@ -716,6 +716,11 @@ def configure(conf): # TODO put this only where it is needed conf.env.append_value('LIB', 'regex') + # work around GdkDrawable BitBlt performance issue on windows + # see http://gareus.org/wiki/ardour_windows_gdk_and_cairo + conf.env.append_value('CFLAGS', '-DUSE_CAIRO_IMAGE_SURFACE') + conf.env.append_value('CXXFLAGS', '-DUSE_CAIRO_IMAGE_SURFACE') + # Tell everyone that this is a waf build conf.env.append_value('CFLAGS', '-DWAF_BUILD') |