}
+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.
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.
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 *);
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 */
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;
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;
}
{
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 ();
}
#ifndef __gtk2_ardour_cairo_widget_h__
#define __gtk2_ardour_cairo_widget_h__
+#include <cairomm/surface.h>
#include <gtkmm/eventbox.h>
#include "gtkmm2ext/visibility.h"
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;
# 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')