fix clamping of line and rect coordinates to avoid issues with cairo when drawing...
authorPaul Davis <paul@linuxaudiosystems.com>
Wed, 17 Apr 2013 14:53:17 +0000 (10:53 -0400)
committerPaul Davis <paul@linuxaudiosystems.com>
Wed, 17 Apr 2013 14:53:17 +0000 (10:53 -0400)
17 files changed:
gtk2_ardour/editor_canvas.cc
gtk2_ardour/editor_cursors.cc
gtk2_ardour/editor_markers.cc
gtk2_ardour/editor_mouse.cc
gtk2_ardour/editor_ops.cc
gtk2_ardour/editor_tempodisplay.cc
gtk2_ardour/tempo_lines.cc
gtk2_ardour/tempo_lines.h
gtk2_ardour/time_axis_view.cc
gtk2_ardour/time_axis_view_item.cc
libs/canvas/canvas.cc
libs/canvas/canvas/canvas.h
libs/canvas/canvas/types.h
libs/canvas/item.cc
libs/canvas/line.cc
libs/canvas/rectangle.cc
libs/canvas/types.cc

index 1b9795bde4319c202e2ed3b9512b92bc33fbb601..bf195525b94991fd141570faebe01c846a59dbb6 100644 (file)
@@ -107,31 +107,37 @@ Editor::initialize_canvas ()
 
        meter_bar_group = new ArdourCanvas::Group (_time_bars_canvas->root ());
        meter_bar = new ArdourCanvas::Rectangle (meter_bar_group, ArdourCanvas::Rect (0.0, 0.0, ArdourCanvas::COORD_MAX, timebar_height - 1));
+       CANVAS_DEBUG_NAME (meter_bar, "meter Bar");
        meter_bar->set_outline_width (1);
        meter_bar->set_outline_what (0x8);
 
        tempo_bar_group = new ArdourCanvas::Group (_time_bars_canvas->root ());
        tempo_bar = new ArdourCanvas::Rectangle (tempo_bar_group, ArdourCanvas::Rect (0.0, 0.0, ArdourCanvas::COORD_MAX, timebar_height - 1));
+       CANVAS_DEBUG_NAME (tempo_bar, "Tempo  Bar");
        tempo_bar->set_outline_width (1);
        tempo_bar->set_outline_what (0x8);
 
        range_marker_bar_group = new ArdourCanvas::Group (_time_bars_canvas->root ());
        range_marker_bar = new ArdourCanvas::Rectangle (range_marker_bar_group, ArdourCanvas::Rect (0.0, 0.0, ArdourCanvas::COORD_MAX, timebar_height - 1));
+       CANVAS_DEBUG_NAME (range_marker_bar, "Range Marker Bar");
        range_marker_bar->set_outline_width (1);
        range_marker_bar->set_outline_what (0x8);
 
        transport_marker_bar_group = new ArdourCanvas::Group (_time_bars_canvas->root ());
        transport_marker_bar = new ArdourCanvas::Rectangle (transport_marker_bar_group, ArdourCanvas::Rect (0.0, 0.0, ArdourCanvas::COORD_MAX, timebar_height - 1));
+       CANVAS_DEBUG_NAME (transport_marker_bar, "transport Marker Bar");
        transport_marker_bar->set_outline_width (1);
        transport_marker_bar->set_outline_what (0x8);
 
        marker_bar_group = new ArdourCanvas::Group (_time_bars_canvas->root ());
        marker_bar = new ArdourCanvas::Rectangle (marker_bar_group, ArdourCanvas::Rect (0.0, 0.0, ArdourCanvas::COORD_MAX, timebar_height - 1));
+       CANVAS_DEBUG_NAME (marker_bar, "Marker Bar");
        marker_bar->set_outline_width (1);
        marker_bar->set_outline_what (0x8);
 
        cd_marker_bar_group = new ArdourCanvas::Group (_time_bars_canvas->root ());
        cd_marker_bar = new ArdourCanvas::Rectangle (cd_marker_bar_group, ArdourCanvas::Rect (0.0, 0.0, ArdourCanvas::COORD_MAX, timebar_height - 1));
+       CANVAS_DEBUG_NAME (cd_marker_bar, "CD Marker Bar");
        cd_marker_bar->set_outline_width (1);
        cd_marker_bar->set_outline_what (0x8);
 
index c5e6b6d5d6d251b3e37d8880a5bd48bb31babd07..b012b97fe983a8976ba5aadd91f40ae30fd070dd 100644 (file)
@@ -21,6 +21,7 @@
 #include <cmath>
 
 #include "canvas/canvas.h"
+#include "canvas/debug.h"
 
 #include "utils.h"
 #include "editor_cursors.h"
@@ -36,6 +37,9 @@ EditorCursor::EditorCursor (Editor& ed, bool (Editor::*callbck)(GdkEvent*,Ardour
        , _track_canvas_item (_editor._track_canvas->root ())
        , _length (1.0)
 {
+       CANVAS_DEBUG_NAME ((&_time_bars_canvas_item), "timebars editor cursor");
+       CANVAS_DEBUG_NAME ((&_track_canvas_item), "track canvas editor cursor");
+
        _time_bars_canvas_item.set_outline_width (1);
        _track_canvas_item.set_outline_width (1);
 
index 04cea1bc04e72e2031013cabde827e3a97428ab7..ff28f7b56a1c65c7e969ab6b8aa3cd42be1dca90 100644 (file)
@@ -1444,7 +1444,7 @@ Editor::update_punch_range_view (bool visibility)
        Location* tpl;
 
        if ((_session->config.get_punch_in() || _session->config.get_punch_out()) && ((tpl = transport_punch_location()) != 0)) {
-               ArdourCanvas::Rect const v = _track_canvas_viewport->visible_area ();
+               ArdourCanvas::Rect const v = _track_canvas->visible_area ();
                if (_session->config.get_punch_in()) {
                        transport_punch_range_rect->set_x0 (sample_to_pixel (tpl->start()));
                        transport_punch_range_rect->set_x1 (_session->config.get_punch_out() ? sample_to_pixel (tpl->end()) : sample_to_pixel (JACK_MAX_FRAMES));
index 137c3e2c375eecbaa94af71de52c5b2211a5c286..efb4c1d5aeadc75ef83fbe11d26a418d41b47f9f 100644 (file)
@@ -1343,7 +1343,7 @@ Editor::button_press_handler (ArdourCanvas::Item* item, GdkEvent* event, ItemTyp
                pointer_window = canvas_window->get_pointer (x, y, mask);
 
                if (pointer_window == _track_canvas->get_window()) {
-                       _track_canvas_viewport->window_to_canvas (x, y, wx, wy);
+                       _track_canvas->window_to_canvas (x, y, wx, wy);
                }
        }
 
@@ -2942,5 +2942,5 @@ Editor::get_pointer_position (double& x, double& y) const
 {
        int px, py;
        _track_canvas->get_pointer (px, py);
-       _track_canvas_viewport->window_to_canvas (px, py, x, y);
+       _track_canvas->window_to_canvas (px, py, x, y);
 }
index 157a034ea51a4f9edf801ee5b6a4937c823f8b22..1bd1a5c82eb3fa408bbbc1f6aabb5b22ec097af6 100644 (file)
@@ -1335,8 +1335,8 @@ Editor::clamp_samples_per_pixel (double& fpp) const
 {
        bool clamped = false;
        
-       if (fpp < 2.0) {
-               fpp = 2.0;
+       if (fpp < 1.0) {
+               fpp = 1.0;
                clamped = true;
        }
 
index 7421ebee47865b09dc37d11b13e806d0e06efe0b..4eb43ad53b42cd6a4369844c8a0319f27c69a180 100644 (file)
@@ -191,7 +191,7 @@ Editor::draw_measures (ARDOUR::TempoMap::BBTPointList::const_iterator& begin,
        }
 
        if (tempo_lines == 0) {
-               tempo_lines = new TempoLines (*_track_canvas_viewport, time_line_group, physical_screen_height(get_window()));
+               tempo_lines = new TempoLines (*_track_canvas, time_line_group, physical_screen_height(get_window()));
        }
        
        tempo_lines->draw (begin, end, samples_per_pixel);
index 282d8f62dd2d0cf5bd06fded69872a27f6ccdfb8..dddb1ee426a09c8b281de5c05529605bac582de4 100644 (file)
@@ -27,8 +27,8 @@ using namespace std;
 
 #define MAX_CACHED_LINES 128
 
-TempoLines::TempoLines (ArdourCanvas::GtkCanvasViewport& canvas_viewport, ArdourCanvas::Group* group, double screen_height)
-       : _canvas_viewport (canvas_viewport)
+TempoLines::TempoLines (ArdourCanvas::Canvas& canvas, ArdourCanvas::Group* group, double screen_height)
+       : _canvas (canvas)
        , _group(group)
        , _clean_left(DBL_MAX)
        , _clean_right(0.0)
@@ -88,7 +88,7 @@ TempoLines::draw (const ARDOUR::TempoMap::BBTPointList::const_iterator& begin,
 
        const size_t needed = distance (begin, end);
 
-       ArdourCanvas::Rect const visible = _canvas_viewport.visible_area ();
+       ArdourCanvas::Rect const visible = _canvas.visible_area ();
 
        /* get the first bar spacing */
 
index defe07226c0c8a4016816f1efb0555f4fe778db8..a0c76505162f9a2170b924d5cc57093f09dc86d3 100644 (file)
@@ -33,7 +33,7 @@ typedef boost::fast_pool_allocator<
 
 class TempoLines {
 public:
-       TempoLines(ArdourCanvas::GtkCanvasViewport& canvas, ArdourCanvas::Group* group, double screen_height);
+       TempoLines(ArdourCanvas::Canvas& canvas, ArdourCanvas::Group* group, double screen_height);
 
        void tempo_map_changed();
 
@@ -48,7 +48,7 @@ private:
        typedef std::map<double, ArdourCanvas::Line*, std::less<double>, MapAllocator> Lines;
        Lines _lines;
 
-        ArdourCanvas::GtkCanvasViewport& _canvas_viewport;
+        ArdourCanvas::Canvas& _canvas;
        ArdourCanvas::Group*  _group;
        double                _clean_left;
        double                _clean_right;
index c54b26a1ea67b1cb6d8f8d6593770b718835a6f1..cfa22ae805fdd9f040d85193d51049eda3e667c9 100644 (file)
@@ -780,9 +780,6 @@ TimeAxisView::set_samples_per_pixel (double fpp)
        for (Children::iterator i = children.begin(); i != children.end(); ++i) {
                (*i)->set_samples_per_pixel (fpp);
        }
-
-       AnalysisFeatureList::const_iterator i;
-       list<ArdourCanvas::Line*>::iterator l;
 }
 
 void
index 0a20cea3dd4112751e04a8e2d793c8e2e9082b24..57bda5fa26b34a93b9c92c3bf07567deecdc0fae 100644 (file)
@@ -849,7 +849,6 @@ TimeAxisViewItem::set_samples_per_pixel (double fpp)
 void
 TimeAxisViewItem::reset_width_dependent_items (double pixel_width)
 {
-
        if (pixel_width < 2.0) {
 
                if (show_vestigial) {
index 726e4fb2fc5b552317d9806550659c59edf4cc77..ff624be8fbd7cf80ee6738f0ef341ed5ac567f0b 100644 (file)
@@ -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 ());
-}
index 9b31844e7e4632a884884a3be232fb97668e7b36..8b8ed37cd48d469cd2c55920cc8897ea7a6889e5 100644 (file)
@@ -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 *);
 
index 606c832ba5ea0b9b9acb4edb0ce8a78dbc821ed0..37c0c213ea3b48669dc85e20872057e69908a901 100644 (file)
@@ -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 &);
index da551fade6e5609b930d6f11bfd666cf5a7c04e0..f5aa39d20df6292decea44e107e7f774d4e3790c 100644 (file)
@@ -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
index 7baa0e1e73657b5560f555b0bc8405ec7651a47a..2894a80a894323b51c1ad28ed1d233816933505c 100644 (file)
@@ -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 ();
 }
 
index 8aa8b6161c2ba9c4bf0fd56a7c938e342e2f1abb..38106a65506d1a358757e8048c0b24281a8a1424 100644 (file)
@@ -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);
index c2612a0b2b9b34418817e4f6f650ec79959a9b69..dfd934b126f7bbfd47d13bd11dbb9edfd31f3868 100644 (file)
@@ -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)
 {