X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fcanvas%2Frectangle.cc;h=06a41e074c0fe6514c58b40ca12b7cdfc4778bb3;hb=6d4c0baad3a09d43b5eacb37ea2a2e4c31afcec6;hp=bb1198c1bb1c1c7b9ce394497b867a80eff7cfa8;hpb=ce8731b32d5e91f56396cb5f6ca0798bc7fed48a;p=ardour.git diff --git a/libs/canvas/rectangle.cc b/libs/canvas/rectangle.cc index bb1198c1bb..06a41e074c 100644 --- a/libs/canvas/rectangle.cc +++ b/libs/canvas/rectangle.cc @@ -36,7 +36,6 @@ Rectangle::Rectangle (Group* parent) , Fill (parent) , _outline_what ((What) (LEFT | RIGHT | TOP | BOTTOM)) { - } Rectangle::Rectangle (Group* parent, Rect const & rect) @@ -50,93 +49,89 @@ Rectangle::Rectangle (Group* parent, Rect const & rect) } void -Rectangle::render (Rect const & /*area*/, Cairo::RefPtr context) const +Rectangle::render (Rect const & area, Cairo::RefPtr context) const { - /* Cairo goes a little (!) wrong when asked to fill/stroke rectangles that - * extend way beyond the surface boundaries. To avoid this issue, - * clamp what we are drawing using the absolute end of the visible - * canvas, converting to item-space coordinates, of course. - */ + Rect self = item_to_window (_rect); + boost::optional r = self.intersection (area); - Rect plot = _rect; - Rect visible = _canvas->visible_area(); - Duple visible_end = canvas_to_item (Duple (visible.x1, visible.y1)); + if (!r) { + std::cerr << whatami() << '/' << name << " not covered by render area! ... " << self << " vs. " << area << std::endl; + return; + } - plot.x1 = min (plot.x1, visible_end.x); - plot.y1 = min (plot.y1, visible_end.y); + Rect draw = r.get (); if (_fill) { - setup_fill_context (context); - cerr << "Fill rect: " << plot << endl; - context->rectangle (plot.x0, plot.y0, plot.width(), plot.height()); - - if (!_outline) { - context->fill (); + if (_stops.empty()) { + setup_fill_context (context); } else { - - /* special/common case: outline the entire rectangle is - * requested, so just use the same path for the fill - * and stroke. - */ - - if (_outline_what == What (LEFT|RIGHT|BOTTOM|TOP)) { - context->fill_preserve(); - setup_outline_context (context); - context->stroke (); - } else { - context->fill (); - } + setup_gradient_context (context, self, Duple (draw.x0, draw.y0)); } - } + context->rectangle (draw.x0, draw.y0, draw.width(), draw.height()); + context->fill (); + } if (_outline) { - + setup_outline_context (context); if (_outline_what == What (LEFT|RIGHT|BOTTOM|TOP)) { - - /* if we filled and use full outline, we are already - * done. otherwise, draw the frame here. - */ - - if (!_fill) { - context->rectangle (plot.x0, plot.y0, plot.width(), plot.height()); - context->stroke (); - } + context->rectangle (self.x0 + 0.5, self.y0 + 0.5, self.width(), self.height()); + } else { + + context->set_line_cap (Cairo::LINE_CAP_SQUARE); + /* see the cairo FAQ on single pixel lines to see why we do + * this expansion of the perimeter. + */ + if (_outline_what & LEFT) { - context->move_to (plot.x0, plot.y0); - context->line_to (plot.x0, plot.y1); + /* 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); } if (_outline_what & BOTTOM) { - context->move_to (plot.x0, plot.y1); - context->line_to (plot.x1, plot.y1); + /* 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); } if (_outline_what & RIGHT) { - context->move_to (plot.x1, plot.y0); - context->line_to (plot.x1, plot.y1); + /* 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); } if (_outline_what & TOP) { - context->move_to (plot.x0, plot.y0); - context->line_to (plot.x1, plot.y0); + /* 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->stroke (); } + + context->stroke (); } } void Rectangle::compute_bounding_box () const { - Rect r = _rect.fix (); - _bounding_box = boost::optional (r.expand (_outline_width / 2)); - + if (!_rect.empty()) { + Rect r = _rect.fix (); + + /* our outlines are always inside our coordinates, but we have + * to ensure that our bounding box fully *contains* the + * rectangle + * + * XXX: or something like that, waffle. + * + */ + _bounding_box = r.expand (1.0); + } + _bounding_box_dirty = false; }