X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fcanvas%2Fline_set.cc;h=03f2f0abf1a50b89d29d70208b12b36defbc464a;hb=c8c6bca6587450ff64303dbc994a4cd28d6ce7aa;hp=1625e0478dd80cee7fe0e9f15b41664330242648;hpb=86343b6c15a3a43f082802484d2bc813d34db821;p=ardour.git diff --git a/libs/canvas/line_set.cc b/libs/canvas/line_set.cc index 1625e0478d..03f2f0abf1 100644 --- a/libs/canvas/line_set.cc +++ b/libs/canvas/line_set.cc @@ -23,22 +23,28 @@ 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 @@ -46,19 +52,36 @@ LineSet::compute_bounding_box () const if (_lines.empty ()) { _bounding_box = boost::optional (); } else { - _bounding_box = Rect (0, _lines.front().y - (_lines.front().width/2.0), COORD_MAX, min (_height, _lines.back().y - (_lines.back().width/2.0))); + + 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_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 (); } @@ -67,19 +90,42 @@ LineSet::render (Rect const & area, Cairo::RefPtr context) const { /* area is in window coordinates */ - for (list::const_iterator i = _lines.begin(); i != _lines.end(); ++i) { + 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); - Rect self = item_to_window (Rect (0, i->y - (i->width/2.0), COORD_MAX, i->y + (i->width/2.0))); - boost::optional intersect = self.intersection (area); - - if (!intersect) { - continue; + if (!isect) { + continue; } + Rect intersection (isect.get()); + set_source_rgba (context, i->color); context->set_line_width (i->width); - context->move_to (intersect->x0, self.y0 + ((self.y1 - self.y0)/2.0)); - context->line_to (intersect->x1, self.y0 + ((self.y1 - self.y0)/2.0)); + + /* 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 (); } } @@ -88,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 (); @@ -108,5 +154,11 @@ LineSet::clear () 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; }