#include #include #include "pbd/stacktrace.h" #include "pbd/xml++.h" #include "pbd/compose.h" #include "canvas/rectangle.h" #include "canvas/debug.h" #include "canvas/utils.h" using namespace std; using namespace ArdourCanvas; Rectangle::Rectangle (Group* parent) : Item (parent) , Outline (parent) , Fill (parent) , _outline_what ((What) (LEFT | RIGHT | TOP | BOTTOM)) { } Rectangle::Rectangle (Group* parent, Rect const & rect) : Item (parent) , Outline (parent) , Fill (parent) , _rect (rect) , _outline_what ((What) (LEFT | RIGHT | TOP | BOTTOM)) { } void Rectangle::render (Rect const & /*area*/, Cairo::RefPtr context) const { Rect plot = _rect; plot.x1 = min (plot.x1, CAIRO_MAX); plot.y1 = min (plot.y1, CAIRO_MAX); if (_fill) { setup_fill_context (context); context->rectangle (plot.x0, plot.y0, plot.width(), plot.height()); if (!_outline) { context->fill (); } 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 (); } } } if (_outline) { if (_outline_what == What (LEFT|RIGHT|BOTTOM|TOP)) { /* if we filled and use full outline, we are already done */ if (!_fill) { context->rectangle (plot.x0, plot.y0, plot.width(), plot.height()); setup_outline_context (context); context->stroke (); } } else { if (_outline_what & LEFT) { context->move_to (plot.x0, plot.y0); context->line_to (plot.x0, plot.y1); } if (_outline_what & BOTTOM) { context->move_to (plot.x0, plot.y1); context->line_to (plot.x1, plot.y1); } if (_outline_what & RIGHT) { context->move_to (plot.x1, plot.y0); context->line_to (plot.x1, plot.y1); } if (_outline_what & TOP) { context->move_to (plot.x0, plot.y0); context->line_to (plot.x1, plot.y0); } setup_outline_context (context); context->stroke (); } } } void Rectangle::compute_bounding_box () const { Rect r = _rect.fix (); _bounding_box = boost::optional (r.expand (_outline_width / 2)); _bounding_box_dirty = false; } void Rectangle::set (Rect const & r) { /* We don't update the bounding box here; it's just as cheap to do it when asked. */ begin_change (); _rect = r; _bounding_box_dirty = true; end_change (); DEBUG_TRACE (PBD::DEBUG::CanvasItemsDirtied, "canvas item dirty: rectangle change (set)\n"); } void Rectangle::set_x0 (Coord x0) { begin_change (); _rect.x0 = x0; _bounding_box_dirty = true; end_change (); DEBUG_TRACE (PBD::DEBUG::CanvasItemsDirtied, "canvas item dirty: rectangle change (x0)\n"); } void Rectangle::set_y0 (Coord y0) { begin_change (); _rect.y0 = y0; _bounding_box_dirty = true; end_change(); DEBUG_TRACE (PBD::DEBUG::CanvasItemsDirtied, "canvas item dirty: rectangle change (y0)\n"); } void Rectangle::set_x1 (Coord x1) { begin_change (); _rect.x1 = x1; _bounding_box_dirty = true; end_change (); DEBUG_TRACE (PBD::DEBUG::CanvasItemsDirtied, "canvas item dirty: rectangle change (x1)\n"); } void Rectangle::set_y1 (Coord y1) { begin_change (); _rect.y1 = y1; _bounding_box_dirty = true; end_change (); DEBUG_TRACE (PBD::DEBUG::CanvasItemsDirtied, "canvas item dirty: rectangle change (y1)\n"); } void Rectangle::set_outline_what (What what) { begin_change (); _outline_what = what; end_change (); } void Rectangle::set_outline_what (int what) { set_outline_what ((What) what); }