summaryrefslogtreecommitdiff
path: root/libs/canvas
diff options
context:
space:
mode:
authorTim Mayberry <mojofunk@gmail.com>2017-04-01 23:02:49 +1000
committerTim Mayberry <mojofunk@gmail.com>2017-06-26 08:40:47 +1000
commitc4e31fc32273a84c0436f32fce742ae21718b03c (patch)
tree3fac41d0063c4dc43112e1a65b43ede9b03f72aa /libs/canvas
parent265f52535a73d996de0e6a61a5b30070c6226cf8 (diff)
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.
Diffstat (limited to 'libs/canvas')
-rw-r--r--libs/canvas/canvas.cc33
-rw-r--r--libs/canvas/canvas/canvas.h4
-rw-r--r--libs/canvas/canvas/container.h6
-rw-r--r--libs/canvas/canvas/item.h8
-rw-r--r--libs/canvas/container.cc6
-rw-r--r--libs/canvas/item.cc37
6 files changed, 93 insertions, 1 deletions
diff --git a/libs/canvas/canvas.cc b/libs/canvas/canvas.cc
index be61b6cb84..baa10f9cf7 100644
--- a/libs/canvas/canvas.cc
+++ b/libs/canvas/canvas.cc
@@ -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.
diff --git a/libs/canvas/canvas/canvas.h b/libs/canvas/canvas/canvas.h
index 2f506fc3c0..cb4f6dd70c 100644
--- a/libs/canvas/canvas/canvas.h
+++ b/libs/canvas/canvas/canvas.h
@@ -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:
diff --git a/libs/canvas/canvas/container.h b/libs/canvas/canvas/container.h
index f95f2f9e2b..4f2fad8f60 100644
--- a/libs/canvas/canvas/container.h
+++ b/libs/canvas/canvas/container.h
@@ -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;
};
}
diff --git a/libs/canvas/canvas/item.h b/libs/canvas/canvas/item.h
index 02f84a62ee..4088011a01 100644
--- a/libs/canvas/canvas/item.h
+++ b/libs/canvas/canvas/item.h
@@ -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;
diff --git a/libs/canvas/container.cc b/libs/canvas/container.cc
index 78598d5118..71085a8257 100644
--- a/libs/canvas/container.cc
+++ b/libs/canvas/container.cc
@@ -38,6 +38,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
{
Item::render_children (area, context);
diff --git a/libs/canvas/item.cc b/libs/canvas/item.cc
index 589f1214b7..98fe6362db 100644
--- a/libs/canvas/item.cc
+++ b/libs/canvas/item.cc
@@ -831,6 +831,43 @@ Item::render_children (Rect const & area, Cairo::RefPtr<Cairo::Context> context)
}
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
{
Rect self;