X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fcanvas%2Frectangle.cc;h=232da178935b083720b8db64d2334087ee993eff;hb=f1e6b28ab7759f9bc93eb965cbe7740f1bafb2d3;hp=ac05003693970325153322f44ce843049ea8e30f;hpb=590882f3c8e063528452d71daffb36d3151da05e;p=ardour.git diff --git a/libs/canvas/rectangle.cc b/libs/canvas/rectangle.cc index ac05003693..232da17893 100644 --- a/libs/canvas/rectangle.cc +++ b/libs/canvas/rectangle.cc @@ -43,28 +43,34 @@ Rectangle::Rectangle (Canvas* c, Rect const & rect) { } -Rectangle::Rectangle (Group* g) - : Item (g) +Rectangle::Rectangle (Item* parent) + : Item (parent) , _outline_what ((What) (LEFT | RIGHT | TOP | BOTTOM)) { } -Rectangle::Rectangle (Group* g, Rect const & rect) - : Item (g) +Rectangle::Rectangle (Item* parent, Rect const & rect) + : Item (parent) , _rect (rect) , _outline_what ((What) (LEFT | RIGHT | TOP | BOTTOM)) { } -void -Rectangle::render (Rect const & area, Cairo::RefPtr context) const +Rect +Rectangle::get_self_for_render () const { /* In general, a Rectangle will have a _position of (0,0) within its parent, and its extent is actually defined by _rect. But in the unusual case that _position is set to something other than (0,0), we should take that into account when rendering. */ - Rect self = item_to_window (_rect.translate (_position)); + + return item_to_window (_rect.translate (_position)); +} + +void +Rectangle::render_self (Rect const & area, Cairo::RefPtr context, Rect self) const +{ boost::optional r = self.intersection (area); if (!r) { @@ -88,57 +94,73 @@ Rectangle::render (Rect const & area, Cairo::RefPtr context) con setup_outline_context (context); - /* see the cairo FAQ on single pixel lines to see why we do + /* the goal here is that if the border is 1 pixel + * thick, it will precisely align with the corner + * coordinates of the rectangle. So if the rectangle + * has a left edge at 0 and a right edge at 10, then + * the left edge must span -0.5..+0.5, the right edge + * must span 9.5..10.5 (i.e. the single full color + * pixel is precisely aligned with 0 and 10 + * respectively). + * + * we have to shift left/up in all cases, which means + * subtraction along both axes (i.e. edge at + * N, outline must start at N-0.5). + * + * see the cairo FAQ on single pixel lines to see why we do * the 0.5 pixel additions. */ + self = self.translate (Duple (0.5, 0.5)); + if (_outline_what == What (LEFT|RIGHT|BOTTOM|TOP)) { - context->rectangle (self.x0 + 0.5, self.y0 + 0.5, self.width() - 1.0, self.height() - 1.0); + context->rectangle (self.x0, self.y0, self.width(), self.height()); } else { if (_outline_what & LEFT) { - /* vertical line: move x-coordinate by 0.5 pixels */ - context->move_to (self.x0 + 0.5, self.y0); - context->line_to (self.x0 + 0.5, self.y1); + context->move_to (self.x0, self.y0); + context->line_to (self.x0, self.y1); } if (_outline_what & TOP) { - /* horizontal line: move y-coordinate by 0.5 pixels */ - context->move_to (self.x0, self.y0 + 0.5); - context->line_to (self.x1, self.y0 + 0.5); + context->move_to (self.x0, self.y0); + context->line_to (self.x1, self.y0); } if (_outline_what & BOTTOM) { - /* horizontal line: move y-coordinate by 0.5 pixels */ - context->move_to (self.x0, self.y1 - 0.5); - context->line_to (self.x1, self.y1 - 0.5); + context->move_to (self.x0, self.y1); + context->line_to (self.x1, self.y1); } if (_outline_what & RIGHT) { - /* vertical line: move x-coordinate by 0.5 pixels */ - context->move_to (self.x1 + 0.5, self.y0); - context->line_to (self.x1 + 0.5, self.y1); + context->move_to (self.x1, self.y0); + context->line_to (self.x1, self.y1); } - } context->stroke (); } } +void +Rectangle::render (Rect const & area, Cairo::RefPtr context) const +{ + render_self (area, context, get_self_for_render ()); +} + void Rectangle::compute_bounding_box () const { if (!_rect.empty()) { Rect r = _rect.fix (); + /* take into acount the 0.5 addition to the bounding box for the right and bottom edges, see ::render() above */ - r.x1 += 1.0; // XXX this makes no sense but is necessary - r.y1 += 0.5; + r = r.expand (1.0); _bounding_box = r; } @@ -226,3 +248,37 @@ Rectangle::set_outline_what (What what) } } + +/*-------------------*/ + +void +TimeRectangle::compute_bounding_box () const +{ + Rectangle::compute_bounding_box (); + + if (_bounding_box) { + Rect r = _bounding_box.get (); + + /* This is a TimeRectangle, so its right edge is drawn 1 pixel beyond + * (larger x-axis coordinates) than a normal Rectangle. + */ + + r.x1 += 1.0; /* this should be using safe_add() */ + + _bounding_box = r; + } +} + +void +TimeRectangle::render (Rect const & area, Cairo::RefPtr context) const +{ + Rect self = get_self_for_render (); + + + /* This is a TimeRectangle, so its right edge is drawn 1 pixel beyond + * (larger x-axis coordinates) than a normal Rectangle. + */ + + self.x1 += 1.0; /* this should be using safe_add() */ + render_self (area, context, self); +}