using namespace std;
using namespace ArdourCanvas;
-Rectangle::Rectangle (Group* parent)
+Rectangle::Rectangle (Canvas* c)
+ : Item (c)
+ , _outline_what ((What) (LEFT | RIGHT | TOP | BOTTOM))
+{
+}
+
+Rectangle::Rectangle (Canvas* c, Rect const & rect)
+ : Item (c)
+ , _rect (rect)
+ , _outline_what ((What) (LEFT | RIGHT | TOP | BOTTOM))
+{
+}
+
+Rectangle::Rectangle (Item* parent)
: Item (parent)
- , Outline (parent)
- , Fill (parent)
, _outline_what ((What) (LEFT | RIGHT | TOP | BOTTOM))
{
}
-Rectangle::Rectangle (Group* parent, Rect const & rect)
+Rectangle::Rectangle (Item* parent, Rect const & rect)
: Item (parent)
- , Outline (parent)
- , Fill (parent)
, _rect (rect)
, _outline_what ((What) (LEFT | RIGHT | TOP | BOTTOM))
{
-
+}
+
+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.
+ */
+
+ return item_to_window (_rect.translate (_position));
}
void
-Rectangle::render (Rect const & area, Cairo::RefPtr<Cairo::Context> context) const
+Rectangle::render_self (Rect const & area, Cairo::RefPtr<Cairo::Context> context, Rect self) const
{
- Rect self = item_to_window (_rect);
boost::optional<Rect> r = self.intersection (area);
if (!r) {
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<Cairo::Context> 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;
}
}
}
+
+/*-------------------*/
+
+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<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);
+}