diff options
author | Robin Gareus <robin@gareus.org> | 2014-05-26 17:02:21 +0200 |
---|---|---|
committer | Robin Gareus <robin@gareus.org> | 2014-05-26 17:02:21 +0200 |
commit | 791c668756786e570c124dfa778234676a0a76a6 (patch) | |
tree | a5b84daf00477591f27e3ed294fe1cc96671d1db /libs/canvas/curve.cc | |
parent | a0037ee2d8a1a100e1528bcc4fb78fab048957fc (diff) |
fix x-fade drawing
Catmull-Rom curve samples are not equally spaced on the x-axis.
Furthermore, Curve::map_value() is not needed, cairo line_to
already interpolates.
Diffstat (limited to 'libs/canvas/curve.cc')
-rw-r--r-- | libs/canvas/curve.cc | 76 |
1 files changed, 19 insertions, 57 deletions
diff --git a/libs/canvas/curve.cc b/libs/canvas/curve.cc index af7e3c110a..b5bab9c867 100644 --- a/libs/canvas/curve.cc +++ b/libs/canvas/curve.cc @@ -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 (); |