summaryrefslogtreecommitdiff
path: root/libs/canvas
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2013-04-17 10:53:17 -0400
committerPaul Davis <paul@linuxaudiosystems.com>2013-04-17 10:53:17 -0400
commitd1a05240efc9816b4358cdeab458a54048abf9be (patch)
treefa45892d3971951ec5a51d6a0526271940cb6de3 /libs/canvas
parent96eee9e7a162e3e26dd9c1ea4d8fc1ad02a3dda9 (diff)
fix clamping of line and rect coordinates to avoid issues with cairo when drawing way outside a surface's dimensions; move various coordinate methods down to Canvas, because they don't require GTK information; make visible_area() a Canvas virtual method so that we don't have to cast to call it
Diffstat (limited to 'libs/canvas')
-rw-r--r--libs/canvas/canvas.cc80
-rw-r--r--libs/canvas/canvas/canvas.h27
-rw-r--r--libs/canvas/canvas/types.h1
-rw-r--r--libs/canvas/item.cc2
-rw-r--r--libs/canvas/line.cc11
-rw-r--r--libs/canvas/rectangle.cc14
-rw-r--r--libs/canvas/types.cc10
7 files changed, 76 insertions, 69 deletions
diff --git a/libs/canvas/canvas.cc b/libs/canvas/canvas.cc
index 726e4fb2fc..ff624be8fb 100644
--- a/libs/canvas/canvas.cc
+++ b/libs/canvas/canvas.cc
@@ -198,6 +198,30 @@ Canvas::item_changed (Item* item, boost::optional<Rect> pre_change_bounding_box)
}
}
+Duple
+Canvas::window_to_canvas (Duple const & d) const
+{
+ return d.translate (Duple (_scroll_offset_x, _scroll_offset_y));
+}
+
+Duple
+Canvas::canvas_to_window (Duple const & d) const
+{
+ return d.translate (Duple (-_scroll_offset_x, -_scroll_offset_y));
+}
+
+Rect
+Canvas::window_to_canvas (Rect const & r) const
+{
+ return r.translate (Duple (_scroll_offset_x, _scroll_offset_y));
+}
+
+Rect
+Canvas::canvas_to_window (Rect const & r) const
+{
+ return r.translate (Duple (-_scroll_offset_x, -_scroll_offset_y));
+}
+
/** Called when an item has moved.
* @param item Item that has moved.
* @param pre_change_parent_bounding_box The bounding box of the item before
@@ -553,6 +577,15 @@ GtkCanvas::ungrab ()
_grabbed_item = 0;
}
+/** @return The visible area of the canvas, in canvas coordinates */
+Rect
+GtkCanvas::visible_area () const
+{
+ Distance const xo = _scroll_offset_x;
+ Distance const yo = _scroll_offset_y;
+ return Rect (xo, yo, xo + get_allocation().get_width (), yo + get_allocation().get_height ());
+}
+
/** Create a GtkCanvaSViewport.
* @param hadj Adjustment to use for horizontal scrolling.
* @param vadj Adjustment to use for vertica scrolling.
@@ -575,30 +608,6 @@ GtkCanvasViewport::scrolled ()
queue_draw ();
}
-Duple
-GtkCanvas::window_to_canvas (Duple const & d) const
-{
- return d.translate (Duple (_scroll_offset_x, _scroll_offset_y));
-}
-
-Duple
-GtkCanvas::canvas_to_window (Duple const & d) const
-{
- return d.translate (Duple (-_scroll_offset_x, -_scroll_offset_y));
-}
-
-Rect
-GtkCanvas::window_to_canvas (Rect const & r) const
-{
- return r.translate (Duple (_scroll_offset_x, _scroll_offset_y));
-}
-
-Rect
-GtkCanvas::canvas_to_window (Rect const & r) const
-{
- return r.translate (Duple (-_scroll_offset_x, -_scroll_offset_y));
-}
-
/** Handler for when GTK asks us what minimum size we want.
* @param req Requsition to fill in.
*/
@@ -612,26 +621,3 @@ GtkCanvasViewport::on_size_request (Gtk::Requisition* req)
req->height = 16;
}
-/** Convert window coordinates to canvas coordinates by taking into account
- * where we are scrolled to.
- * @param wx Window x.
- * @param wy Window y.
- * @param cx Filled in with canvas x.
- * @param cy Filled in with canvas y.
- */
-void
-GtkCanvasViewport::window_to_canvas (int wx, int wy, Coord& cx, Coord& cy) const
-{
- Duple d = _canvas.window_to_canvas (Duple (wx, wy));
- cx = d.x;
- cy = d.y;
-}
-
-/** @return The visible area of the canvas, in canvas coordinates */
-Rect
-GtkCanvasViewport::visible_area () const
-{
- Distance const xo = hadjustment.get_value ();
- Distance const yo = vadjustment.get_value ();
- return Rect (xo, yo, xo + get_allocation().get_width (), yo + get_allocation().get_height ());
-}
diff --git a/libs/canvas/canvas/canvas.h b/libs/canvas/canvas/canvas.h
index 9b31844e7e..8b8ed37cd4 100644
--- a/libs/canvas/canvas/canvas.h
+++ b/libs/canvas/canvas/canvas.h
@@ -87,7 +87,25 @@ public:
_log_renders = log;
}
+ Rect canvas_to_window (Rect const&) const;
+ Rect window_to_canvas (Rect const&) const;
+ Duple canvas_to_window (Duple const&) const;
+ Duple window_to_canvas (Duple const&) const;
+
+ void canvas_to_window (Coord cx, Coord cy, Coord& wx, Coord& wy) {
+ Duple d = canvas_to_window (Duple (cx, cy));
+ wx = d.x;
+ wy = d.y;
+ }
+
+ void window_to_canvas (Coord wx, Coord wy, Coord& cx, Coord& cy) {
+ Duple d = window_to_canvas (Duple (wx, wy));
+ cx = d.x;
+ cy = d.y;
+ }
+
void scroll_to (Coord x, Coord y);
+ virtual Rect visible_area () const = 0;
std::string indent() const;
std::string render_indent() const;
@@ -119,11 +137,7 @@ public:
Cairo::RefPtr<Cairo::Context> context ();
- Rect canvas_to_window (Rect const&) const;
- Rect window_to_canvas (Rect const&) const;
-
- Duple canvas_to_window (Duple const&) const;
- Duple window_to_canvas (Duple const&) const;
+ Rect visible_area () const;
protected:
bool on_expose_event (GdkEventExpose *);
@@ -162,9 +176,6 @@ public:
return &_canvas;
}
- void window_to_canvas (int, int, Coord &, Coord &) const;
- Rect visible_area () const;
-
protected:
void on_size_request (Gtk::Requisition *);
diff --git a/libs/canvas/canvas/types.h b/libs/canvas/canvas/types.h
index 606c832ba5..37c0c213ea 100644
--- a/libs/canvas/canvas/types.h
+++ b/libs/canvas/canvas/types.h
@@ -56,6 +56,7 @@ struct Duple
extern Duple operator- (Duple const &);
extern Duple operator+ (Duple const &, Duple const &);
+extern bool operator== (Duple const &, Duple const &);
extern Duple operator- (Duple const &, Duple const &);
extern Duple operator/ (Duple const &, double);
extern std::ostream & operator<< (std::ostream &, Duple const &);
diff --git a/libs/canvas/item.cc b/libs/canvas/item.cc
index da551fade6..f5aa39d20d 100644
--- a/libs/canvas/item.cc
+++ b/libs/canvas/item.cc
@@ -370,7 +370,7 @@ Item::dump (ostream& o) const
{
boost::optional<ArdourCanvas::Rect> bb = bounding_box();
- o << _canvas->indent() << whatami() << ' ' << this;
+ o << _canvas->indent() << whatami() << ' ' << this << " Visible ? " << _visible;
o << " @ " << position();
#ifdef CANVAS_DEBUG
diff --git a/libs/canvas/line.cc b/libs/canvas/line.cc
index 7baa0e1e73..2894a80a89 100644
--- a/libs/canvas/line.cc
+++ b/libs/canvas/line.cc
@@ -24,6 +24,7 @@
#include "canvas/types.h"
#include "canvas/debug.h"
#include "canvas/utils.h"
+#include "canvas/canvas.h"
using namespace std;
using namespace ArdourCanvas;
@@ -55,14 +56,8 @@ void
Line::render (Rect const & /*area*/, Cairo::RefPtr<Cairo::Context> context) const
{
setup_outline_context (context);
-
- Duple plot[2] = {
- Duple (min (_points[0].x, CAIRO_MAX), min (_points[0].y, CAIRO_MAX)),
- Duple (min (_points[1].x, CAIRO_MAX), min (_points[1].y, CAIRO_MAX))
- };
-
- context->move_to (plot[0].x, plot[0].y);
- context->line_to (plot[1].x, plot[1].y);
+ context->move_to (_points[0].x, _points[0].y);
+ context->line_to (_points[1].x, _points[1].y);
context->stroke ();
}
diff --git a/libs/canvas/rectangle.cc b/libs/canvas/rectangle.cc
index 8aa8b6161c..38106a6550 100644
--- a/libs/canvas/rectangle.cc
+++ b/libs/canvas/rectangle.cc
@@ -21,6 +21,8 @@
#include <cairomm/context.h>
#include "pbd/stacktrace.h"
#include "pbd/compose.h"
+
+#include "canvas/canvas.h"
#include "canvas/rectangle.h"
#include "canvas/debug.h"
#include "canvas/utils.h"
@@ -50,10 +52,18 @@ Rectangle::Rectangle (Group* parent, Rect const & rect)
void
Rectangle::render (Rect const & /*area*/, Cairo::RefPtr<Cairo::Context> context) const
{
+ /* Cairo goes a little (!) wrong when asked to fill/stroke rectangles that
+ * extend way beyond the surface boundaries. To avoid this issue,
+ * clamp what we are drawing using the absolute end of the visible
+ * canvas, converting to item-space coordinates, of course.
+ */
+
Rect plot = _rect;
+ Rect visible = _canvas->visible_area();
+ Duple visible_end = canvas_to_item (Duple (visible.x1, visible.y1));
- plot.x1 = min (plot.x1, CAIRO_MAX);
- plot.y1 = min (plot.y1, CAIRO_MAX);
+ plot.x1 = min (plot.x1, visible_end.x);
+ plot.y1 = min (plot.y1, visible_end.y);
if (_fill) {
setup_fill_context (context);
diff --git a/libs/canvas/types.cc b/libs/canvas/types.cc
index c2612a0b2b..dfd934b126 100644
--- a/libs/canvas/types.cc
+++ b/libs/canvas/types.cc
@@ -25,9 +25,7 @@
using namespace std;
using namespace ArdourCanvas;
-Coord const ArdourCanvas::COORD_MAX = DBL_MAX;
-/* XXX: empirically arrived at */
-Coord const ArdourCanvas::CAIRO_MAX = 65536;
+Coord const ArdourCanvas::COORD_MAX = 1.7e307;
static inline Coord
safe_add (Coord a, Coord b)
@@ -132,6 +130,12 @@ ArdourCanvas::operator+ (Duple const & a, Duple const & b)
return Duple (safe_add (a.x, b.x), safe_add (a.y, b.y));
}
+bool
+ArdourCanvas::operator== (Duple const & a, Duple const & b)
+{
+ return a.x == b.x && a.y == b.y;
+}
+
Duple
ArdourCanvas::operator- (Duple const & a, Duple const & b)
{