X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fcanvas%2Fline_set.cc;h=03f2f0abf1a50b89d29d70208b12b36defbc464a;hb=c8c6bca6587450ff64303dbc994a4cd28d6ce7aa;hp=5aefe1bf47f76cff8c2428ab4686a79b7450a576;hpb=300b484cf6ac14c15e365c4062345d64a61c4b18;p=ardour.git diff --git a/libs/canvas/line_set.cc b/libs/canvas/line_set.cc index 5aefe1bf47..03f2f0abf1 100644 --- a/libs/canvas/line_set.cc +++ b/libs/canvas/line_set.cc @@ -23,62 +23,110 @@ using namespace std; using namespace ArdourCanvas; -/* XXX: hard-wired to horizontal only */ - class LineSorter { public: - bool operator() (LineSet::Line& a, LineSet::Line& b) { - return a.y < b.y; + bool operator() (LineSet::Line const & a, LineSet::Line const & b) { + return a.pos < b.pos; } }; -LineSet::LineSet (Group* parent) - : Item (parent) - , _height (0) +LineSet::LineSet (Canvas* c, Orientation o) + : Item (c) + , _extent (0) + , _orientation (o) { } +LineSet::LineSet (Item* parent, Orientation o) + : Item (parent) + , _extent (0) + , _orientation (o) +{ + +} void LineSet::compute_bounding_box () const { if (_lines.empty ()) { _bounding_box = boost::optional (); - _bounding_box_dirty = false; - return; + } else { + + if (_orientation == Horizontal) { + + _bounding_box = Rect (0, /* x0 */ + _lines.front().pos - (_lines.front().width/2.0), /* y0 */ + _extent, /* x1 */ + _lines.back().pos - (_lines.back().width/2.0) /* y1 */ + ); + + } else { + + _bounding_box = Rect (_lines.front().pos - _lines.front().width/2.0, /* x0 */ + 0, /* y0 */ + _lines.back().pos + _lines.back().width/2.0, /* x1 */ + _extent /* y1 */ + ); + } } - - _bounding_box = Rect (0, _lines.front().y, COORD_MAX, min (_height, _lines.back().y)); + _bounding_box_dirty = false; } void -LineSet::set_height (Distance height) +LineSet::set_extent (Distance e) { begin_change (); - _height = height; - + _extent = e; _bounding_box_dirty = true; + end_change (); } void LineSet::render (Rect const & area, Cairo::RefPtr context) const { - for (list::const_iterator i = _lines.begin(); i != _lines.end(); ++i) { - if (i->y > area.y1) { - break; - } else if (i->y > area.y0) { - set_source_rgba (context, i->color); - context->set_line_width (i->width); - Duple p0 = item_to_window (Duple (area.x0, i->y)); - Duple p1 = item_to_window (Duple (area.x1, i->y)); - context->move_to (p0.x, p0.y); - context->line_to (p1.x, p1.y); - context->stroke (); + /* area is in window coordinates */ + + for (vector::const_iterator i = _lines.begin(); i != _lines.end(); ++i) { + + Rect self; + + if (_orientation == Horizontal) { + self = item_to_window (Rect (0, i->pos - (i->width/2.0), _extent, i->pos + (i->width/2.0))); + } else { + self = item_to_window (Rect (i->pos - (i->width/2.0), 0, i->pos + (i->width/2.0), _extent)); + } + + boost::optional isect = self.intersection (area); + + if (!isect) { + continue; } + + Rect intersection (isect.get()); + + set_source_rgba (context, i->color); + context->set_line_width (i->width); + + /* Not 100% sure that the computation of the invariant + * positions (y and x) below work correctly if the line width + * is not 1.0, but visual inspection suggests it is OK. + */ + + if (_orientation == Horizontal) { + double y = self.y0 + ((self.y1 - self.y0)/2.0); + context->move_to (intersection.x0, y); + context->line_to (intersection.x1, y); + } else { + double x = self.x0 + ((self.x1 - self.x0)/2.0); + context->move_to (x, intersection.y0); + context->line_to (x, intersection.y1); + } + + context->stroke (); } } @@ -86,9 +134,9 @@ void LineSet::add (Coord y, Distance width, Color color) { begin_change (); - + _lines.push_back (Line (y, width, color)); - _lines.sort (LineSorter ()); + sort (_lines.begin(), _lines.end(), LineSorter()); _bounding_box_dirty = true; end_change (); @@ -102,3 +150,15 @@ LineSet::clear () _bounding_box_dirty = true; end_change (); } + +bool +LineSet::covers (Duple const & /*point*/) const +{ + /* lines are ordered by position along primary axis, so binary search + * to find the place to start looking. + * + * XXX but not yet. + */ + + return false; +}