since we now expand rectangles to the right always, adjust the bounding box computation
[ardour.git] / libs / canvas / rectangle.cc
index d90fd3a94335b61233b70aeb5a6751c3b434f41d..57aa92d040ae2b6b3bd6825613252430c9104f22 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)
@@ -56,7 +55,6 @@ Rectangle::render (Rect const & area, Cairo::RefPtr<Cairo::Context> context) con
        boost::optional<Rect> r = self.intersection (area);
 
        if (!r) {
-               std::cerr << whatami() << '/' << name << " not covered by render area! ... " << self << " vs. " << area << std::endl;
                return;
        }
 
@@ -68,48 +66,76 @@ Rectangle::render (Rect const & area, Cairo::RefPtr<Cairo::Context> context) con
                } else {
                        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);
+               
+               /* see the cairo FAQ on single pixel lines to see why we do
+                * the 0.5 pixel additions.
+                */
 
-               context->save ();
-               context->rectangle (draw.x0, draw.y0, draw.width(), draw.height());
-               context->clip ();
+               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);
 
-               if (_outline_what & LEFT) {
-                       context->move_to (self.x0, self.y0);
-                       context->line_to (self.x0, self.y1);
-               }
-               
-               if (_outline_what & BOTTOM) {
-                       context->move_to (self.x0, self.y1);
-                       context->line_to (self.x1, self.y1);
-               }
-               
-               if (_outline_what & RIGHT) {
-                       context->move_to (self.x1, self.y0);
-                       context->line_to (self.x1, self.y1);
-               }
-               
-               if (_outline_what & TOP) {
-                       context->move_to (self.x0, self.y0);
-                       context->line_to (self.x1, self.y0);
+               } 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);
+                       }
+                       
+                       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);
+                       }
+
+                       /* in theory, you'd expect us to adjust these two by
+                        * MINUS 0.5 pixels. But the way that Cairo apparently
+                        * does rounding can lead that approach to draw on the
+                        * wrong pixel coordinate. So we add 0.5 even here.
+                        */
+
+                       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);
+                       }
+                       
                }
                
                context->stroke ();
-               context->restore ();
        }
 }
 
 void
 Rectangle::compute_bounding_box () const
 {
-       Rect r = _rect.fix ();
-       _bounding_box = boost::optional<Rect> (r.expand (_outline_width/2.0));
+       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 += 0.5;
+               r.y1 += 0.5;
+
+               _bounding_box = r;
+       }
+
        _bounding_box_dirty = false;
 }