fix up thinko in recent raise_to_top/lower_to_bottom optimization
[ardour.git] / libs / canvas / rectangle.cc
index a5aa0a2895852dc4b46c4a9988a0e21254627ea2..06a41e074c0fe6514c58b40ca12b7cdfc4778bb3 100644 (file)
@@ -36,7 +36,6 @@ Rectangle::Rectangle (Group* parent)
        , Fill (parent)
        , _outline_what ((What) (LEFT | RIGHT | TOP | BOTTOM))
 {
-
 }
 
 Rectangle::Rectangle (Group* parent, Rect const & rect)
@@ -53,24 +52,14 @@ void
 Rectangle::render (Rect const & area, Cairo::RefPtr<Cairo::Context> context) const
 {
        Rect self = item_to_window (_rect);
-       boost::optional<Rect> d = self.intersection (area);
+       boost::optional<Rect> r = self.intersection (area);
 
-       if (!d) {
+       if (!r) {
+               std::cerr << whatami() << '/' << name << " not covered by render area! ... " << self << " vs. " << area << std::endl;
                return;
        }
-       
-       Rect draw = d.get();
-       static const double boundary = 0.5;
-       const double x_limit = _canvas->visible_area().width();
-
-       draw.x0 = max (self.x0, max (0.0, draw.x0 - boundary));
-       draw.x1 = min (self.x1, min (x_limit, draw.x1 + boundary));
-
-       draw.y0 = max (self.y0, max (0.0, draw.y0 - boundary));
-       draw.y1 = min (self.y1, min (x_limit, draw.y1 + boundary));
 
-       Rect fill_rect = draw;
-       Rect stroke_rect = fill_rect.expand (0.5);
+       Rect draw = r.get ();
 
        if (_fill) {
                if (_stops.empty()) {
@@ -78,7 +67,7 @@ Rectangle::render (Rect const & area, Cairo::RefPtr<Cairo::Context> context) con
                } else {
                        setup_gradient_context (context, self, Duple (draw.x0, draw.y0));
                }
-               context->rectangle (fill_rect.x0, fill_rect.y0, fill_rect.width(), fill_rect.height());
+               context->rectangle (draw.x0, draw.y0, draw.width(), draw.height());
                context->fill ();
        }
        
@@ -86,24 +75,41 @@ Rectangle::render (Rect const & area, Cairo::RefPtr<Cairo::Context> context) con
 
                setup_outline_context (context);
 
-               if (_outline_what & LEFT) {
-                       context->move_to (stroke_rect.x0, stroke_rect.y0);
-                       context->line_to (stroke_rect.x0, stroke_rect.y1);
-               }
-               
-               if (_outline_what & BOTTOM) {
-                       context->move_to (stroke_rect.x0, stroke_rect.y1);
-                       context->line_to (stroke_rect.x1, stroke_rect.y1);
-               }
-               
-               if (_outline_what & RIGHT) {
-                       context->move_to (stroke_rect.x1, stroke_rect.y0);
-                       context->line_to (stroke_rect.x1, stroke_rect.y1);
-               }
-               
-               if (_outline_what & TOP) {
-                       context->move_to (stroke_rect.x0, stroke_rect.y0);
-                       context->line_to (stroke_rect.x1, stroke_rect.y0);
+               if (_outline_what == What (LEFT|RIGHT|BOTTOM|TOP)) {
+                       
+                       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) {
+                               /* 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) {
+                               /* 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) {
+                               /* 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) {
+                               /* 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 ();
@@ -113,9 +119,19 @@ Rectangle::render (Rect const & area, Cairo::RefPtr<Cairo::Context> context) con
 void
 Rectangle::compute_bounding_box () const
 {
-       Rect r = _rect.fix ();
-       _bounding_box = boost::optional<Rect> (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;
 }