fix x-fade drawing
authorRobin Gareus <robin@gareus.org>
Mon, 26 May 2014 15:02:21 +0000 (17:02 +0200)
committerRobin Gareus <robin@gareus.org>
Mon, 26 May 2014 15:02:21 +0000 (17:02 +0200)
Catmull-Rom curve samples are not equally spaced on the x-axis.
Furthermore, Curve::map_value() is not needed, cairo line_to
already interpolates.

libs/canvas/canvas/curve.h
libs/canvas/curve.cc

index d05107640cc2a2efea17d8b11663de62016e665b..1fe21c3307220c49d2db4c03fe140908ea52a983 100644 (file)
@@ -50,7 +50,6 @@ public:
     uint32_t points_per_segment;
     SplineType curve_type;
 
-    double map_value (double) const;
     void interpolate ();
 
     static void interpolate (const Points& coordinates, uint32_t points_per_segment, SplineType, bool closed, Points& results);
index af7e3c110a1d94e3886f2fc27072baa7193f82fe..b5bab9c8677b181ce320e66cea702623a5cc8ac7 100644 (file)
@@ -272,34 +272,6 @@ Curve::interpolate (const Points& coordinates, uint32_t points_per_segment, Spli
         }
 }
 
-/** Given a fractional position within the x-axis range of the
- * curve, return the corresponding y-axis value
- */
-
-double
-Curve::map_value (double x) const
-{
-       if (x > 0.0 && x < 1.0) {
-
-               double f;
-               Points::size_type index;
-               
-               /* linearly interpolate between two of our smoothed "samples"
-                */
-               
-               x = x * (n_samples - 1);
-               index = (Points::size_type) x; // XXX: should we explicitly use floor()?
-               f = x - index;
-
-               return (1.0 - f) * samples[index].y + f * samples[index+1].y;
-               
-       } else if (x >= 1.0) {
-               return samples.back().y;
-       } else {
-               return samples.front().y;
-       }
-}
-
 void
 Curve::render (Rect const & area, Cairo::RefPtr<Cairo::Context> context) const
 {
@@ -366,36 +338,26 @@ Curve::render (Rect const & area, Cairo::RefPtr<Cairo::Context> context) const
                        draw.x1 = w2.x;
                }
 
-               /* full width of the curve */
-               const double xextent = _points.back().x - _points.front().x;
-               /* Determine where the first drawn point will be */
-               Duple item_space = window_to_item (Duple (draw.x0, 0)); /* y value is irrelevant */
-               /* determine the fractional offset of this location into the overall extent of the curve */
-               const double xfract_offset = (item_space.x - _points.front().x)/xextent;
-               const uint32_t pixels = draw.width ();
-               Duple window_space;
+               /* find left and right-most sample */
+               Points::size_type left = 0;
+               Points::size_type right = n_samples;
 
-               /* draw the first point */
-
-               for (uint32_t pixel = 0; pixel < pixels; ++pixel) {
-
-                       /* fractional distance into the total horizontal extent of the curve */
-                       double xfract = xfract_offset + (pixel / xextent);
-                       /* compute vertical coordinate (item-space) at that location */
-                       double y = map_value (xfract);
-                       
-                       /* convert to window space for drawing */
-                       window_space = item_to_window (Duple (0.0, y)); /* x-value is irrelevant */
-
-                       /* we are moving across the draw area pixel-by-pixel */
-                       window_space.x = draw.x0 + pixel;
-                       
-                       /* plot this point */
-                       if (pixel == 0) {
-                               context->move_to (window_space.x, window_space.y);
-                       } else {
-                               context->line_to (window_space.x, window_space.y);
-                       }
+               for (Points::size_type idx = 0; idx < n_samples - 1; ++idx) {
+                       left = idx;
+                       if (samples[idx].x >= draw.x0) break;
+               }
+               for (Points::size_type idx = n_samples; idx > left + 1; --idx) {
+                       if (samples[idx].x <= draw.x1) break;
+                       right = idx;
+               }
+
+               /* draw line between samples */
+               Duple window_space;
+               window_space = item_to_window (Duple (samples[left].x, samples[left].y));
+               context->move_to (window_space.x, window_space.y);
+               for (uint32_t idx = left + 1; idx < right; ++idx) {
+                       window_space = item_to_window (Duple (samples[idx].x, samples[idx].y));
+                       context->line_to (window_space.x, window_space.y);
                }
 
                context->stroke ();