allow to use cairo-image/software surface for canvas & cairowidgets
This commit is contained in:
parent
6dc3a4bf61
commit
b04414d170
@ -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);
|
||||
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
||||
|
||||
}
|
||||
|
||||
/** Handler for GDK scroll events.
|
||||
|
@ -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 */
|
||||
|
@ -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 ();
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
5
wscript
5
wscript
@ -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')
|
||||
|
Loading…
Reference in New Issue
Block a user