fix crash when copy'ing latent plugins
[ardour.git] / libs / canvas / xfade_curve.cc
index 0fff4aa03e5b213eb4a4e83a92fb352071787dfb..e93331e7f987ce8430fb8e5af573d7a137a48e8d 100644 (file)
@@ -1,20 +1,20 @@
 /*
-    Copyright (C) 2013 Paul Davis
-    Copyright (C) 2014 Robin Gareus <robin@gareus.org>
+  Copyright (C) 2013 Paul Davis
+  Copyright (C) 2014 Robin Gareus <robin@gareus.org>
 
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
 
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
 
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
 */
 
 #include <exception>
 #include <algorithm>
 
-#include "canvas/utils.h"
 #include "canvas/xfade_curve.h"
 #include "canvas/interpolated_curve.h"
+#include "canvas/utils.h"
 
 using namespace ArdourCanvas;
 using std::min;
 using std::max;
 
-XFadeCurve::XFadeCurve (Group* parent)
+#ifdef USE_TRACKS_CODE_FEATURES
+static const bool show_bg_fades = false;
+#else
+static const bool show_bg_fades = true;
+#endif
+
+XFadeCurve::XFadeCurve (Canvas* c)
+       : Item (c)
+       , points_per_segment (32)
+       , _xfadeposition (Start)
+       , _outline_color (0x000000ff)
+       , _fill_color (0x22448880)
+       , show_background_fade (show_bg_fades)
+{
+}
+
+XFadeCurve::XFadeCurve (Canvas* c, XFadePosition pos)
+       : Item (c)
+       , points_per_segment (32)
+       , _xfadeposition (pos)
+       , _outline_color (0x000000ff)
+       , _fill_color (0x22448880)
+       , show_background_fade (show_bg_fades)
+{
+}
+
+XFadeCurve::XFadeCurve (Item* parent)
        : Item (parent)
-       , points_per_segment (24)
+       , points_per_segment (32)
        , _xfadeposition (Start)
        , _outline_color (0x000000ff)
        , _fill_color (0x22448880)
+       , show_background_fade (show_bg_fades)
 {
 }
 
-XFadeCurve::XFadeCurve (Group* parent, XFadePosition pos)
+XFadeCurve::XFadeCurve (Item* parent, XFadePosition pos)
        : Item (parent)
-       , points_per_segment (24)
+       , points_per_segment (32)
        , _xfadeposition (pos)
        , _outline_color (0x000000ff)
        , _fill_color (0x22448880)
+       , show_background_fade (show_bg_fades)
 {
 }
 
@@ -139,37 +167,41 @@ XFadeCurve::get_path(Rect const & area, Cairo::RefPtr<Cairo::Context> context, C
 
        if (c.points.size () == 2) {
 
-               window_space = item_to_window (c.points.front());
+               window_space = item_to_window (c.points.front(), false);
                context->move_to (window_space.x, window_space.y);
-               window_space = item_to_window (c.points.back());
+               window_space = item_to_window (c.points.back(), false);
                context->line_to (window_space.x, window_space.y);
 
        } else {
 
                /* find left and right-most sample */
                Points::size_type left = 0;
-               Points::size_type right = c.n_samples;
+               Points::size_type right = c.n_samples - 1;
 
+               assert (left < right);
+               // we should really really do a binary search rather than iterate
                for (Points::size_type idx = 0; idx < c.n_samples - 1; ++idx) {
                        left = idx;
-                       window_space = item_to_window (Duple (c.samples[idx].x, 0.0));
+                       window_space = item_to_window (Duple (c.samples[idx].x, 0.0), false);
                        if (window_space.x >= area.x0) break;
                }
-               for (Points::size_type idx = c.n_samples; idx > left + 1; --idx) {
-                       window_space = item_to_window (Duple (c.samples[idx].x, 0.0));
+               for (Points::size_type idx = c.n_samples - 1; right > left;) {
+                       if (--idx <= left) break;
+                       window_space = item_to_window (Duple (c.samples[idx].x, 0.0), false);
                        if (window_space.x <= area.x1) break;
                        right = idx;
                }
 
+               assert(left < right);
+               assert(left < c.n_samples);
+               assert(right < c.n_samples);
+
                /* draw line between samples */
-               window_space = item_to_window (Duple (c.samples[left].x, c.samples[left].y));
+               window_space = item_to_window (Duple (c.samples[left].x, c.samples[left].y), false);
                context->move_to (window_space.x, window_space.y);
-               Coord last_x = round(window_space.x);
-               for (uint32_t idx = left + 1; idx < right; ++idx) {
-                       window_space = item_to_window (Duple (c.samples[idx].x, c.samples[idx].y));
-                       if (last_x == round(window_space.x)) continue;
-                       last_x = round(window_space.x);
-                       context->line_to (last_x - .5 , window_space.y);
+               for (uint32_t idx = left + 1; idx <= right; ++idx) {
+                       window_space = item_to_window (Duple (c.samples[idx].x, c.samples[idx].y), false);
+                       context->line_to (window_space.x, window_space.y);
                }
        }
        return context->copy_path ();
@@ -180,15 +212,15 @@ XFadeCurve::close_path(Rect const & area, Cairo::RefPtr<Cairo::Context> context,
 {
        Duple window_space;
        if (inside) {
-               window_space = item_to_window (Duple(c.points.back().x, area.height()));
+               window_space = item_to_window (Duple(c.points.back().x, area.height()), false);
                context->line_to (window_space.x, window_space.y);
-               window_space = item_to_window (Duple(c.points.front().x, area.height()));
+               window_space = item_to_window (Duple(c.points.front().x, area.height()), false);
                context->line_to (window_space.x, window_space.y);
                context->close_path();
        } else {
-               window_space = item_to_window (Duple(c.points.back().x, 0.0));
+               window_space = item_to_window (Duple(c.points.back().x, 0.0), false);
                context->line_to (window_space.x, window_space.y);
-               window_space = item_to_window (Duple(c.points.front().x, 0.0));
+               window_space = item_to_window (Duple(c.points.front().x, 0.0), false);
                context->line_to (window_space.x, window_space.y);
                context->close_path();
        }
@@ -224,44 +256,52 @@ XFadeCurve::render (Rect const & area, Cairo::RefPtr<Cairo::Context> context) co
        Color fill_shaded = _fill_color;
        fill_shaded = 0.5 * (fill_shaded & 0xff) + (fill_shaded & ~0xff);
 
-#define IS (_xfadeposition == Start)
+#define IS_START (_xfadeposition == Start)
 
        /* fill primary fade */
        context->begin_new_path ();
-       context->append_path (IS ? *path_in : *path_out);
-       close_path(draw, context, IS ?_in : _out, false);
+       context->append_path (IS_START ? *path_in : *path_out);
+       close_path(draw, context, IS_START ?_in : _out, false);
        set_source_rgba (context, _fill_color);
        context->fill ();
 
-       /* fill background fade */
-       context->save ();
-       context->begin_new_path ();
-       context->append_path (IS ? *path_in : *path_out);
-       close_path(draw, context, IS ? _in : _out, true);
-       //context->set_fill_rule (Cairo::FILL_RULE_EVEN_ODD);
-       context->clip ();
-       context->begin_new_path ();
-       context->append_path (IS ? *path_out: *path_in);
-       close_path(draw, context, IS ? _out : _in, true);
-       set_source_rgba (context, fill_shaded);
-       //context->set_fill_rule (Cairo::FILL_RULE_WINDING);
-       context->fill ();
-       context->restore ();
+       if (show_background_fade) {
+               /* fill background fade */
+               context->save ();
+               context->begin_new_path ();
+               context->append_path (IS_START ? *path_in : *path_out);
+               close_path(draw, context, IS_START ? _in : _out, true);
+               context->set_fill_rule (Cairo::FILL_RULE_EVEN_ODD);
+               context->clip ();
+               context->begin_new_path ();
+               context->append_path (IS_START ? *path_out: *path_in);
+               close_path(draw, context, IS_START ? _out : _in, true);
+               set_source_rgba (context, fill_shaded);
+               context->set_fill_rule (Cairo::FILL_RULE_WINDING);
+               context->fill ();
+               context->restore ();
+       }
 
        /* draw lines over fills */
-       set_source_rgba (context, IS ? _outline_color : outline_shaded);
-       context->set_line_width (IS ? 1.0 : .5);
-
-       context->begin_new_path ();
-       context->append_path (*path_in);
-       context->stroke();
+       /* fade in line */
+       if (IS_START || show_background_fade) {
+               set_source_rgba (context, IS_START ? _outline_color : outline_shaded);
+               context->set_line_width (IS_START ? 1.0 : .5);
+
+               context->begin_new_path ();
+               context->append_path (*path_in);
+               context->stroke();
+       }
 
-       set_source_rgba (context, IS ? outline_shaded :_outline_color);
-       context->set_line_width (IS ? .5 : 1.0);
+       /* fade out line */
+       if (!IS_START || show_background_fade) {
+               set_source_rgba (context, IS_START ? outline_shaded :_outline_color);
+               context->set_line_width (IS_START ? .5 : 1.0);
 
-       context->begin_new_path ();
-       context->append_path (*path_out);
-       context->stroke();
+               context->begin_new_path ();
+               context->append_path (*path_out);
+               context->stroke();
+       }
 
        context->restore ();