[Summary] To have USE_CAIRO_IMAGE_SURFACE working -- clean up and fixing cairo_widget. With occasion: eliminating _current_event_expose as Robin has introduced expose_area which plays similar role. Now WINDOW works under USE_CAIRO_IMAGE_SURFACE condition.

WARNING: we should assure that cairo's clip() serves well in Ardour as we stopped using clip_preserve().
This commit is contained in:
VKamyshniy 2014-11-17 17:55:47 +02:00
parent c4f1d74ebc
commit 96b8486ceb
4 changed files with 86 additions and 83 deletions

View file

@ -285,7 +285,7 @@ AudioClock::set_colors ()
}
void
AudioClock::render (cairo_t* cr, cairo_rectangle_t*)
AudioClock::render (cairo_t* cr, cairo_rectangle_t* expose_area)
{
/* main layout: rounded rect, plus the text */
@ -293,19 +293,19 @@ AudioClock::render (cairo_t* cr, cairo_rectangle_t*)
cairo_set_source_rgba (cr, bg_r, bg_g, bg_b, bg_a);
if (corner_radius) {
if (_left_layout) {
Gtkmm2ext::rounded_top_half_rectangle (cr, _current_event_expose->area.x, _current_event_expose->area.y, get_width(), upper_height, corner_radius);
Gtkmm2ext::rounded_top_half_rectangle (cr, expose_area->x, expose_area->y, get_width(), upper_height, corner_radius);
} else {
Gtkmm2ext::rounded_rectangle (cr, _current_event_expose->area.x, _current_event_expose->area.y, get_width(), upper_height, corner_radius);
Gtkmm2ext::rounded_rectangle (cr, expose_area->x, expose_area->y, get_width(), upper_height, corner_radius);
}
} else {
cairo_rectangle (cr, _current_event_expose->area.x, _current_event_expose->area.y, get_width(), upper_height);
cairo_rectangle (cr, expose_area->x, expose_area->y, get_width(), upper_height);
}
cairo_fill (cr);
}
cairo_move_to (cr,
(get_width() - layout_width) / 2.0 + _current_event_expose->area.x,
(upper_height - layout_height) / 2.0 + _current_event_expose->area.y);
(get_width() - layout_width) / 2.0 + expose_area->x,
(upper_height - layout_height) / 2.0 + expose_area->y);
pango_cairo_show_layout (cr, _layout->gobj());
@ -324,15 +324,15 @@ AudioClock::render (cairo_t* cr, cairo_rectangle_t*)
if (_need_bg) {
if (corner_radius) {
Gtkmm2ext::rounded_bottom_half_rectangle (cr,
_current_event_expose->area.x,
_current_event_expose->area.y + upper_height + separator_height,
expose_area->x,
expose_area->y + upper_height + separator_height,
left_rect_width + (separator_height == 0 ? corner_radius : 0),
h,
corner_radius);
} else {
cairo_rectangle (cr,
_current_event_expose->area.x,
_current_event_expose->area.y + upper_height + separator_height,
expose_area->x,
expose_area->y + upper_height + separator_height,
left_rect_width,
h);
}
@ -340,22 +340,22 @@ AudioClock::render (cairo_t* cr, cairo_rectangle_t*)
}
cairo_move_to (cr,
_current_event_expose->area.x + x_leading_padding,
_current_event_expose->area.y + upper_height + separator_height + ((h - info_height)/2.0));
expose_area->x + x_leading_padding,
expose_area->y + upper_height + separator_height + ((h - info_height)/2.0));
pango_cairo_show_layout (cr, _left_layout->gobj());
if (_need_bg) {
if (corner_radius) {
Gtkmm2ext::rounded_bottom_half_rectangle (cr,
_current_event_expose->area.x + left_rect_width + separator_height,
_current_event_expose->area.y + upper_height + separator_height,
expose_area->x + left_rect_width + separator_height,
expose_area->y + upper_height + separator_height,
get_width() - separator_height - left_rect_width,
h,
corner_radius);
} else {
cairo_rectangle (cr,
_current_event_expose->area.x + left_rect_width + separator_height,
_current_event_expose->area.y + upper_height + separator_height,
expose_area->x + left_rect_width + separator_height,
expose_area->y + upper_height + separator_height,
get_width() - separator_height - left_rect_width,
h);
}
@ -379,12 +379,12 @@ AudioClock::render (cairo_t* cr, cairo_rectangle_t*)
x = x_leading_padding + left_rect_width + separator_height;
}
cairo_move_to (cr,
_current_event_expose->area.x + x,
_current_event_expose->area.y + upper_height + separator_height + ((h - info_height)/2.0));
expose_area->x + x,
expose_area->y + upper_height + separator_height + ((h - info_height)/2.0));
} else {
cairo_move_to (cr,
_current_event_expose->area.x + x_leading_padding + left_rect_width + separator_height,
_current_event_expose->area.y + upper_height + separator_height + ((h - info_height)/2.0));
expose_area->x + x_leading_padding + left_rect_width + separator_height,
expose_area->y + upper_height + separator_height + ((h - info_height)/2.0));
}
pango_cairo_show_layout (cr, _right_layout->gobj());
@ -394,15 +394,15 @@ AudioClock::render (cairo_t* cr, cairo_rectangle_t*)
if (_need_bg) {
if (corner_radius) {
Gtkmm2ext::rounded_bottom_half_rectangle (cr,
_current_event_expose->area.x,
_current_event_expose->area.y + upper_height + separator_height,
expose_area->x,
expose_area->y + upper_height + separator_height,
get_width(),
h,
corner_radius);
} else {
cairo_rectangle (cr,
_current_event_expose->area.x,
_current_event_expose->area.y + upper_height + separator_height,
expose_area->x,
expose_area->y + upper_height + separator_height,
get_width(),
h);
}
@ -430,8 +430,8 @@ AudioClock::render (cairo_t* cr, cairo_rectangle_t*)
cairo_set_source_rgba (cr, cursor_r, cursor_g, cursor_b, cursor_a);
cairo_rectangle (cr,
_current_event_expose->area.x + min (get_width() - 2.0, (double) xcenter + cursor.get_x()/PANGO_SCALE + em_width),
_current_event_expose->area.y + (upper_height - layout_height)/2.0,
expose_area->x + min (get_width() - 2.0, (double) xcenter + cursor.get_x()/PANGO_SCALE + em_width),
expose_area->y + (upper_height - layout_height)/2.0,
2.0,
cursor.get_height()/PANGO_SCALE);
cairo_fill (cr);
@ -442,8 +442,8 @@ AudioClock::render (cairo_t* cr, cairo_rectangle_t*)
if (input_string.empty()) {
cairo_set_source_rgba (cr, cursor_r, cursor_g, cursor_b, cursor_a);
cairo_rectangle (cr,
_current_event_expose->area.x + (get_width()/2.0),
_current_event_expose->area.y + (upper_height - layout_height)/2.0,
expose_area->x + (get_width()/2.0),
expose_area->y + (upper_height - layout_height)/2.0,
2.0,
upper_height);
cairo_fill (cr);

View file

@ -723,7 +723,7 @@ void
GtkCanvas::on_size_allocate (Gtk::Allocation& a)
{
EventBox::on_size_allocate (a);
#ifdef USE_CAIRO_IMAGE_SURFACE_FOR_GTK_CANVAS
#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());
@ -737,7 +737,7 @@ GtkCanvas::on_size_allocate (Gtk::Allocation& a)
bool
GtkCanvas::on_expose_event (GdkEventExpose* ev)
{
#ifdef USE_CAIRO_IMAGE_SURFACE_FOR_GTK_CANVAS
#ifdef USE_CAIRO_IMAGE_SURFACE
if (!canvas_image) {
canvas_image = Cairo::ImageSurface::create (Cairo::FORMAT_ARGB32, get_width(), get_height());
}
@ -764,7 +764,7 @@ GtkCanvas::on_expose_event (GdkEventExpose* ev)
render (Rect (ev->area.x, ev->area.y, ev->area.x + ev->area.width, ev->area.y + ev->area.height), draw_context);
#ifdef USE_CAIRO_IMAGE_SURFACE_FOR_GTK_CANVAS
#ifdef USE_CAIRO_IMAGE_SURFACE
/* now blit our private surface back to the GDK one */
window_context->rectangle (ev->area.x, ev->area.y, ev->area.width, ev->area.height);

View file

@ -33,7 +33,6 @@ CairoWidget::CairoWidget ()
, _visual_state (Gtkmm2ext::NoVisualState)
, _need_bg (true)
, _name_proxy (this, X_("name"))
, _current_event_expose (0)
{
_name_proxy.connect (sigc::mem_fun (*this, &CairoWidget::on_name_changed));
}
@ -52,63 +51,66 @@ CairoWidget::on_button_press_event (GdkEventButton*)
bool
CairoWidget::on_expose_event (GdkEventExpose *ev)
{
_current_event_expose = ev;
#ifdef USE_CAIRO_IMAGE_SURFACE_FOR_CAIRO_WIDGET
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);
#ifdef USE_CAIRO_IMAGE_SURFACE_FOR_CAIRO_WIDGET
cr->clip_preserve ();
#else
cr->clip ();
#endif
/* paint expose area the color of the parent window bg
*/
if (get_visible_window ()) {
Gdk::Color bg (get_parent_bg());
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.y = ev->area.y;
expose_area.width = ev->area.width;
expose_area.height = ev->area.height;
#ifdef USE_CAIRO_IMAGE_SURFACE
Cairo::RefPtr<Cairo::Context> cr;
if (get_visible_window ()) {
expose_area.x = 0;
expose_area.y = 0;
if (!_image_surface) {
_image_surface = Cairo::ImageSurface::create (Cairo::FORMAT_ARGB32, get_width(), get_height());
}
cr = Cairo::Context::create (_image_surface);
} else {
expose_area.x = ev->area.x;
expose_area.y = ev->area.y;
cr = get_window()->create_cairo_context ();
}
#else
expose_area.x = ev->area.x;
expose_area.y = ev->area.y;
Cairo::RefPtr<Cairo::Context> cr = get_window()->create_cairo_context ();
#endif
cr->rectangle (expose_area.x, ev->area.y, expose_area.width, expose_area.height);
cr->clip ();
/* paint expose area the color of the parent window bg
*/
if (get_visible_window ()) {
Gdk::Color bg (get_parent_bg());
cr->rectangle (expose_area.x, ev->area.y, expose_area.width, expose_area.height);
cr->set_source_rgb (bg.get_red_p(), bg.get_green_p(), bg.get_blue_p());
cr->fill ();
}
render (cr->cobj(), &expose_area);
Gtk::Widget* child = get_child ();
if (child) {
propagate_expose (*child, ev);
}
#ifdef USE_CAIRO_IMAGE_SURFACE_FOR_CAIRO_WIDGET
image_surface->flush();
/* now blit our private surface back to the GDK one */
#ifdef USE_CAIRO_IMAGE_SURFACE
if(get_visible_window ()) {
_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::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 ();
cairo_context->rectangle (ev->area.x, ev->area.y, ev->area.width, ev->area.height);
cairo_context->clip ();
cairo_context->set_source (_image_surface, ev->area.x, ev->area.y);
cairo_context->set_operator (Cairo::OPERATOR_OVER);
cairo_context->paint ();
}
#endif
Gtk::Widget* child = get_child ();
if (child) {
propagate_expose (*child, ev);
}
return true;
}
@ -131,8 +133,8 @@ CairoWidget::on_size_allocate (Gtk::Allocation& alloc)
{
Gtk::EventBox::on_size_allocate (alloc);
#ifdef USE_CAIRO_IMAGE_SURFACE_FOR_CAIRO_WIDGET
image_surface = Cairo::ImageSurface::create (Cairo::FORMAT_ARGB32, alloc.get_width(), alloc.get_height());
#ifdef USE_CAIRO_IMAGE_SURFACE
_image_surface = Cairo::ImageSurface::create (Cairo::FORMAT_ARGB32, alloc.get_width(), alloc.get_height());
#endif
set_dirty ();

View file

@ -105,12 +105,13 @@ protected:
Gtkmm2ext::ActiveState _active_state;
Gtkmm2ext::VisualState _visual_state;
bool _need_bg;
GdkEventExpose* _current_event_expose; // Valid only when on_expose_event
static sigc::slot<void> focus_handler;
private:
Cairo::RefPtr<Cairo::Surface> image_surface;
#ifdef USE_CAIRO_IMAGE_SURFACE
Cairo::RefPtr<Cairo::Surface> _image_surface;
#endif
Glib::SignalProxyProperty _name_proxy;
};