Give the Windows MMTimer test a better chance of passing
[ardour.git] / libs / canvas / rectangle.cc
index 7a4129d30a6d1647257e91fc6cc6bf72e081d689..64cdd3af8acedb78c52ee04cb744d03152bf2071 100644 (file)
@@ -72,7 +72,7 @@ void
 Rectangle::render_self (Rect const & area, Cairo::RefPtr<Cairo::Context> context, Rect self) const
 {
        boost::optional<Rect> r = self.intersection (area);
-       
+
        if (!r) {
                return;
        }
@@ -88,50 +88,57 @@ Rectangle::render_self (Rect const & area, Cairo::RefPtr<Cairo::Context> context
 
                context->rectangle (draw.x0, draw.y0, draw.width(), draw.height());
                context->fill ();
-       } 
-       
+       }
+
        if (_outline) {
 
                setup_outline_context (context);
-               
+
                /* 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..1, the right edge
-                * must span 9..10 because the first and final pixels
-                * to be colored are actually "at" 0.5 and 9.5 (midway
-                * between the integer coordinates.
+                * must span 10..11 because the first and final pixels
+                * to be colored are actually "at" 0.5 and 10.5 (midway
+                * between the integer coordinates).
+                *
+                * See the Cairo FAQ on single pixel lines for more
+                * detail.
                 */
 
+               if (fmod (_outline_width, 2.0)  != 0.0) {
+                       const double shift = _outline_width * 0.5;
+                       self = self.translate (Duple (shift, shift));
+               }
+
                if (_outline_what == What (LEFT|RIGHT|BOTTOM|TOP)) {
-                       
-                       self = self.shrink (0.5);
+
                        context->rectangle (self.x0, self.y0, self.width(), self.height());
 
                } else {
 
                        if (_outline_what & LEFT) {
-                               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) {
-                               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) {
-                               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) {
-                               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 ();
        }
 }
@@ -156,7 +163,7 @@ Rectangle::compute_bounding_box () const
                   bounding box is 1.0 pixels outside the stated
                   corners of the rectangle (so that the middle
                   of the 2 pixel wide border passes through
-                  the corners, alternatively described as 1 row 
+                  the corners, alternatively described as 1 row
                   of pixels outside of the corners, and 1 row
                   inside).
 
@@ -174,7 +181,7 @@ Rectangle::compute_bounding_box () const
                   than the rectangle itself.
                */
 
-               _bounding_box = r.expand (_outline_width * 0.5);
+               _bounding_box = r.expand (1.0 + _outline_width * 0.5);
        }
 
        _bounding_box_dirty = false;
@@ -188,11 +195,11 @@ Rectangle::set (Rect const & r)
        */
 
        if (r != _rect) {
-               
+
                begin_change ();
-               
+
                _rect = r;
-               
+
                _bounding_box_dirty = true;
                end_change ();
        }
@@ -203,9 +210,9 @@ Rectangle::set_x0 (Coord x0)
 {
        if (x0 != _rect.x0) {
                begin_change ();
-               
+
                _rect.x0 = x0;
-               
+
                _bounding_box_dirty = true;
                end_change ();
        }
@@ -216,9 +223,9 @@ Rectangle::set_y0 (Coord y0)
 {
        if (y0 != _rect.y0) {
                begin_change ();
-               
+
                _rect.y0 = y0;
-               
+
                _bounding_box_dirty = true;
                end_change();
        }
@@ -229,9 +236,9 @@ Rectangle::set_x1 (Coord x1)
 {
        if (x1 != _rect.x1) {
                begin_change ();
-               
+
                _rect.x1 = x1;
-               
+
                _bounding_box_dirty = true;
                end_change ();
        }
@@ -242,9 +249,9 @@ Rectangle::set_y1 (Coord y1)
 {
        if (y1 != _rect.y1) {
                begin_change ();
-               
+
                _rect.y1 = y1;
-               
+
                _bounding_box_dirty = true;
                end_change ();
        }
@@ -260,36 +267,25 @@ Rectangle::set_outline_what (What what)
        }
 }
 
+double
+Rectangle::vertical_fraction (double y) const
+{
+        /* y is in canvas coordinates */
+
+        Duple i (canvas_to_item (Duple (0, y)));
+        boost::optional<Rect> r = bounding_box();
+        if (!r) {
+                return 0; /* not really correct, but what else can we do? */
+        }
 
-/*-------------------*/
+        Rect bbox (r.get());
 
-void
-TimeRectangle::compute_bounding_box () const
-{
-       Rectangle::compute_bounding_box ();
+        if (i.y < bbox.y0 || i.y >= bbox.y1) {
+                return 0;
+        }
 
-       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;
-       }
-}
+        /* convert to fit Cairo origin model (origin at upper left)
+         */
 
-void 
-TimeRectangle::render (Rect const & area, Cairo::RefPtr<Cairo::Context> 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);
+        return 1.0 - ((i.y - bbox.y0) / bbox.height());
 }