Add an optional ArdourCanvas::Item::prepare_for_render interface
Called when an item has requested a redraw and intersects with visible canvas area. Also add Canvas::prepare_for_render that will call Item::prepare_for_render for items visible on the canvas.
This commit is contained in:
parent
265f52535a
commit
c4e31fc322
|
@ -144,6 +144,22 @@ Canvas::render (Rect const & area, Cairo::RefPtr<Cairo::Context> const & context
|
|||
|
||||
}
|
||||
|
||||
void
|
||||
Canvas::prepare_for_render (Rect const & area) const
|
||||
{
|
||||
Rect root_bbox = _root.bounding_box();
|
||||
if (!root_bbox) {
|
||||
/* the root has no bounding box, so there's nothing to render */
|
||||
return;
|
||||
}
|
||||
|
||||
Rect draw = root_bbox.intersection (area);
|
||||
|
||||
if (draw) {
|
||||
_root.prepare_for_render (draw);
|
||||
}
|
||||
}
|
||||
|
||||
ostream&
|
||||
operator<< (ostream& o, Canvas& c)
|
||||
{
|
||||
|
@ -231,9 +247,17 @@ Canvas::item_changed (Item* item, Rect pre_change_bounding_box)
|
|||
Rect post_change_bounding_box = item->bounding_box ();
|
||||
|
||||
if (post_change_bounding_box) {
|
||||
if (item->item_to_window (post_change_bounding_box).intersection (window_bbox)) {
|
||||
Rect const window_intersection =
|
||||
item->item_to_window (post_change_bounding_box).intersection (window_bbox);
|
||||
|
||||
if (window_intersection) {
|
||||
/* request a redraw of the item's new bounding box */
|
||||
queue_draw_item_area (item, post_change_bounding_box);
|
||||
|
||||
// Allow item to do any work necessary to prepare for being rendered.
|
||||
item->prepare_for_render (window_intersection);
|
||||
} else {
|
||||
// No intersection with visible window area
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -937,6 +961,13 @@ GtkCanvas::on_expose_event (GdkEventExpose* ev)
|
|||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
GtkCanvas::prepare_for_render () const
|
||||
{
|
||||
Rect window_bbox = visible_area ();
|
||||
Canvas::prepare_for_render (window_bbox);
|
||||
}
|
||||
|
||||
/** Handler for GDK scroll events.
|
||||
* @param ev Event.
|
||||
* @return true if the event was handled.
|
||||
|
|
|
@ -87,6 +87,8 @@ public:
|
|||
|
||||
void render (Rect const &, Cairo::RefPtr<Cairo::Context> const &) const;
|
||||
|
||||
void prepare_for_render (Rect const &) const;
|
||||
|
||||
/** @return root group */
|
||||
Item* root () {
|
||||
return &_root;
|
||||
|
@ -214,6 +216,8 @@ public:
|
|||
Canvas::render (rect, ctx);
|
||||
}
|
||||
|
||||
void prepare_for_render () const;
|
||||
|
||||
uint32_t background_color() { return Canvas::background_color (); }
|
||||
|
||||
protected:
|
||||
|
|
|
@ -53,6 +53,12 @@ public:
|
|||
* (just call Item::render_children()). It can be overridden as necessary.
|
||||
*/
|
||||
void render (Rect const & area, Cairo::RefPtr<Cairo::Context> context) const;
|
||||
|
||||
/** The prepare_for_render() method is likely to be identical in all
|
||||
* containers (just call Item::prepare_for_render_children()). It can be
|
||||
* overridden as necessary.
|
||||
*/
|
||||
void prepare_for_render (Rect const & area) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -75,6 +75,13 @@ public:
|
|||
*/
|
||||
virtual void render (Rect const & area, Cairo::RefPtr<Cairo::Context>) const = 0;
|
||||
|
||||
/** Item has changed will be rendered in next render pass so give item a
|
||||
* chance to perhaps schedule work in another thread etc.
|
||||
*
|
||||
* @param area Area to draw, in **window** coordinates
|
||||
*/
|
||||
virtual void prepare_for_render (Rect const & area) const { }
|
||||
|
||||
/** Adds one or more items to the vector @param items based on their
|
||||
* covering @param point which is in **window** coordinates
|
||||
*
|
||||
|
@ -309,6 +316,7 @@ protected:
|
|||
|
||||
void add_child_bounding_boxes (bool include_hidden = false) const;
|
||||
void render_children (Rect const & area, Cairo::RefPtr<Cairo::Context> context) const;
|
||||
void prepare_for_render_children (Rect const & area) const;
|
||||
|
||||
Duple scroll_offset() const;
|
||||
Duple position_offset() const;
|
||||
|
|
|
@ -37,6 +37,12 @@ Container::Container (Item* parent, Duple const & p)
|
|||
{
|
||||
}
|
||||
|
||||
void
|
||||
Container::prepare_for_render (Rect const & area) const
|
||||
{
|
||||
Item::prepare_for_render_children (area);
|
||||
}
|
||||
|
||||
void
|
||||
Container::render (Rect const & area, Cairo::RefPtr<Cairo::Context> context) const
|
||||
{
|
||||
|
|
|
@ -830,6 +830,43 @@ Item::render_children (Rect const & area, Cairo::RefPtr<Cairo::Context> context)
|
|||
--render_depth;
|
||||
}
|
||||
|
||||
void
|
||||
Item::prepare_for_render_children (Rect const & area) const
|
||||
{
|
||||
if (_items.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ensure_lut ();
|
||||
std::vector<Item*> items = _lut->get (area);
|
||||
|
||||
for (std::vector<Item*>::const_iterator i = items.begin(); i != items.end(); ++i) {
|
||||
|
||||
if (!(*i)->visible ()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Rect item_bbox = (*i)->bounding_box ();
|
||||
|
||||
if (!item_bbox) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Rect item = (*i)->item_to_window (item_bbox, false);
|
||||
Rect d = item.intersection (area);
|
||||
|
||||
if (d) {
|
||||
Rect draw = d;
|
||||
if (draw.width() && draw.height()) {
|
||||
(*i)->prepare_for_render (area);
|
||||
}
|
||||
|
||||
} else {
|
||||
// Item does not intersect with visible canvas area
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Item::add_child_bounding_boxes (bool include_hidden) const
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue
Block a user