diff --git a/libs/canvas/canvas/container.h b/libs/canvas/canvas/container.h index 3d01056a06..c63d1a4f4d 100644 --- a/libs/canvas/canvas/container.h +++ b/libs/canvas/canvas/container.h @@ -59,6 +59,25 @@ public: * overridden as necessary. */ void prepare_for_render (Rect const & area) const; + + /** Render all children of this container as group, + * so that they occlude each other. Then blend the result + * onto the destination with the given alpha level. + * + * @param alpha + * - alpha < 0 render normally, do not group rendering. This is the default. + * - alpha == 0 do not render at all. rendered items would be invisible. + * - alpha < 1.0 use a group to render objects, blend flattened result with the given transparency. + * - alpha >= 1.0 simply blit the result of the grouped render operation. + */ + void set_render_with_alpha (double alpha); + + double render_with_alpha () const { + return _render_with_alpha; + } + +private: + double _render_with_alpha; }; } diff --git a/libs/canvas/container.cc b/libs/canvas/container.cc index 95efc97f8a..249df83b96 100644 --- a/libs/canvas/container.cc +++ b/libs/canvas/container.cc @@ -23,17 +23,20 @@ using namespace ArdourCanvas; Container::Container (Canvas* canvas) : Item (canvas) + , _render_with_alpha (-1) { } Container::Container (Item* parent) : Item (parent) + , _render_with_alpha (-1) { } Container::Container (Item* parent, Duple const & p) : Item (parent, p) + , _render_with_alpha (-1) { } @@ -46,7 +49,20 @@ Container::prepare_for_render (Rect const & area) const void Container::render (Rect const & area, Cairo::RefPtr context) const { + if (_render_with_alpha == 0) { + return; + } else if (_render_with_alpha > 0) { + context->push_group (); + } + Item::render_children (area, context); + + if (_render_with_alpha >= 1.0) { + context->pop_group (); + } else if (_render_with_alpha > 0) { + context->pop_group_to_source (); + context->paint_with_alpha (_render_with_alpha); + } } void @@ -56,3 +72,13 @@ Container::compute_bounding_box () const /* nothing to do here; Item::bounding_box() will add all children for us */ set_bbox_clean (); } + +void +Container::set_render_with_alpha (double alpha) +{ + if (_render_with_alpha == alpha) { + return; + } + _render_with_alpha = alpha; + redraw (); +}