X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fcanvas%2Fframed_curve.cc;h=66145f718323b691c856e2e39dc9f31fc249c6fe;hb=e157a84c2b6cb27ef22134c11fde5f277a87e8c7;hp=c5b2d6de22c3b4d476c4d5ef5a547a01848c24b8;hpb=8f88f42ba997d816682cf1c1cfa9b9c3306ad2a8;p=ardour.git diff --git a/libs/canvas/framed_curve.cc b/libs/canvas/framed_curve.cc index c5b2d6de22..66145f7183 100644 --- a/libs/canvas/framed_curve.cc +++ b/libs/canvas/framed_curve.cc @@ -31,7 +31,7 @@ FramedCurve::FramedCurve (Canvas* c) : PolyItem (c) , n_samples (0) , points_per_segment (16) - , curve_fill (None) + , curve_fill (Inside) { } @@ -39,7 +39,7 @@ FramedCurve::FramedCurve (Item* parent) : PolyItem (parent) , n_samples (0) , points_per_segment (16) - , curve_fill (None) + , curve_fill (Inside) { } @@ -85,8 +85,14 @@ FramedCurve::interpolate () } samples.clear (); - InterpolatedCurve::interpolate (curve_points, points_per_segment, CatmullRomCentripetal, false, samples); - n_samples = samples.size(); + if (_points.size() == 3) { + samples.push_back (curve_points.front()); + samples.push_back (curve_points.back()); + n_samples = 2; + } else { + InterpolatedCurve::interpolate (curve_points, points_per_segment, CatmullRomCentripetal, false, samples); + n_samples = samples.size(); + } } void @@ -96,10 +102,10 @@ FramedCurve::render (Rect const & area, Cairo::RefPtr context) c return; } - Rect self = item_to_window (_bounding_box.get()); - boost::optional d = self.intersection (area); + Rect self = item_to_window (_bounding_box); + Rect d = self.intersection (area); assert (d); - Rect draw = d.get (); + Rect draw = d; /* Our approach is to always draw n_segments across our total size. * @@ -136,20 +142,40 @@ FramedCurve::render (Rect const & area, Cairo::RefPtr context) c } setup_outline_context (context); - if (_points.size() == 3) { /* straight line */ Duple window_space; Points::const_iterator it = _points.begin(); + + Duple first_point = Duple (0.0, 0.0); + Duple last_point = Duple (0.0, 0.0); + window_space = item_to_window (*it); - context->move_to (window_space.x, window_space.y); + if (window_space.x <= draw.x0) { + first_point = Duple (draw.x0, window_space.y); + } else { + first_point = Duple (window_space.x, window_space.y); + } + context->move_to (first_point.x, first_point.y); + ++it; window_space = item_to_window (*it, false); - context->line_to (window_space.x, window_space.y); + if (window_space.x <= draw.x0) { + context->line_to (draw.x0, window_space.y); + } else { + context->line_to (window_space.x, window_space.y); + } + window_space = item_to_window (_points.back(), false); - context->line_to (window_space.x, window_space.y); + if (window_space.x >= draw.x1) { + last_point = Duple (draw.x1, window_space.y); + } else { + last_point = Duple (window_space.x, window_space.y); + } + + context->line_to (last_point.x, last_point.y); switch (curve_fill) { case None: @@ -157,10 +183,10 @@ FramedCurve::render (Rect const & area, Cairo::RefPtr context) c break; case Inside: context->stroke_preserve (); - window_space = item_to_window (Duple(_points.back().x, draw.height())); - context->line_to (window_space.x, window_space.y); - window_space = item_to_window (Duple(_points.front().x, draw.height())); - context->line_to (window_space.x, window_space.y); + window_space = item_to_window (Duple(0.0, draw.height())); + context->line_to (last_point.x, window_space.y); + window_space = item_to_window (Duple(0.0, draw.height())); + context->line_to (first_point.x, window_space.y); context->close_path(); setup_fill_context(context); context->fill (); @@ -168,18 +194,15 @@ FramedCurve::render (Rect const & area, Cairo::RefPtr context) c case Outside: context->stroke_preserve (); window_space = item_to_window (Duple(_points.back().x, 0.0)); - context->line_to (window_space.x, window_space.y); + context->line_to (last_point.x, window_space.y); window_space = item_to_window (Duple(_points.front().x, 0.0)); - context->line_to (window_space.x, window_space.y); + context->line_to (first_point.x, window_space.y); context->close_path(); setup_fill_context(context); context->fill (); break; } - context->restore (); - } else { - /* curve of at least 3 points */ /* find left and right-most sample */ @@ -203,24 +226,26 @@ FramedCurve::render (Rect const & area, Cairo::RefPtr context) c } } - /* a redraw may have been requested between the last sample and the last point.*/ + const Duple first_sample = Duple (samples[left].x, samples[left].y); - Duple last_point = Duple (samples[right].x, samples[right].y); - Duple first_point = Duple (samples[left].x, samples[left].y); + /* move to the first sample's x and the draw height */ + window_space = item_to_window (Duple (first_sample.x, draw.height())); + context->move_to (window_space.x, window_space.y); - if (draw.x1 > last_point.x) { - last_point = Duple (_points.back().x, _points.back().y); - } - if (draw.x0 < first_point.x) { - first_point = Duple (_points.front().x, _points.front().y); + /* draw line to first sample and then between samples */ + for (uint32_t idx = left; idx <= right; ++idx) { + window_space = item_to_window (Duple (samples[idx].x, samples[idx].y), false); + context->line_to (window_space.x, window_space.y); } - window_space = item_to_window (first_point); - context->move_to (window_space.x, window_space.y); + /* a redraw may have been requested between the last sample and the last point. + if so, draw a line to the last _point. + */ + Duple last_sample = Duple (samples[right].x, samples[right].y); - /* draw line between samples */ - for (uint32_t idx = left + 1; idx <= right; ++idx) { - window_space = item_to_window (Duple (samples[idx].x, samples[idx].y), false); + if (draw.x1 > last_sample.x) { + last_sample = Duple (_points.back().x, _points.back().y); + window_space = item_to_window (last_sample, false); context->line_to (window_space.x, window_space.y); } @@ -230,29 +255,28 @@ FramedCurve::render (Rect const & area, Cairo::RefPtr context) c break; case Inside: context->stroke_preserve (); - - window_space = item_to_window (Duple (last_point.x, draw.height())); + /* close the frame, possibly using the last _point's x rather than samples[right].x */ + window_space = item_to_window (Duple (last_sample.x, draw.height())); context->line_to (window_space.x, window_space.y); - window_space = item_to_window (Duple (first_point.x, draw.height())); + window_space = item_to_window (Duple (first_sample.x, draw.height())); context->line_to (window_space.x, window_space.y); - context->close_path(); setup_fill_context(context); context->fill (); break; case Outside: context->stroke_preserve (); - window_space = item_to_window (last_point); + window_space = item_to_window (Duple (last_sample.x, 0.0)); context->line_to (window_space.x, window_space.y); - window_space = item_to_window (first_point); + window_space = item_to_window (Duple (first_sample.x, 0.0)); context->line_to (window_space.x, window_space.y); context->close_path(); setup_fill_context(context); context->fill (); break; } - context->restore (); } + context->restore (); #if 0 /* add points */