From 0e4ddcf50679d136ab8fe2356d5a7921f91aa0cb Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Sun, 14 May 2017 20:37:58 +0200 Subject: Fix out-of-bounds waveform image rendering. With large sample-rates and high-zoom-level the minimal request-size or at least 1/10sed can exceed the max image size supported by cairo. e.g. @192kSPS; 100ms = 19200 samples. * 1 sample/pixel, * 2 (left/right) = 38400px > 2^15px. --- libs/canvas/wave_view.cc | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/libs/canvas/wave_view.cc b/libs/canvas/wave_view.cc index 94821c48dd..039979c3a9 100644 --- a/libs/canvas/wave_view.cc +++ b/libs/canvas/wave_view.cc @@ -912,10 +912,15 @@ WaveView::desired_image_width () const * We want at least 1 canvas width's worth, but if that * represents less than 1/10th of a second, use 1/10th of * a second instead. + * + * ..unless at high-zoom level 100ms would be more than 2^15px + * (cairo image limit), note that generate_image() uses twice this + * width (left/right of the center of the request range. */ framecnt_t canvas_width_samples = _canvas->visible_area().width() * _samples_per_pixel; - const framecnt_t one_tenth_of_second = _region->session().frame_rate() / 10; + const framecnt_t one_tenth_of_second = std::min (_region->session().frame_rate() / 10, (framecnt_t)floor (16383.0 / _samples_per_pixel)); + if (canvas_width_samples > one_tenth_of_second) { return canvas_width_samples; @@ -927,6 +932,7 @@ WaveView::desired_image_width () const void WaveView::queue_get_image (boost::shared_ptr region, framepos_t start, framepos_t end) const { + DEBUG_TRACE (DEBUG::WaveView, string_compose ("%1: queue image from %2 .. %3\n", name, start, end)); boost::shared_ptr req (new WaveViewThreadRequest); req->type = WaveViewThreadRequest::Draw; @@ -983,13 +989,14 @@ WaveView::generate_image (boost::shared_ptr req, bool in_ const framepos_t center = req->start + ((req->end - req->start) / 2); const framecnt_t image_samples = req->width; - /* we can request data from anywhere in the Source, between 0 and its length - */ + /* we can request data from anywhere in the Source, between 0 and its length */ framepos_t sample_start = max (_region_start, (center - image_samples)); framepos_t sample_end = min (center + image_samples, region_end()); const int n_peaks = std::max (1LL, llrint (ceil ((sample_end - sample_start) / (req->samples_per_pixel)))); + DEBUG_TRACE (DEBUG::WaveView, string_compose ("%1: request %2 .. %3 width: %4; render %5 .. %6 (%7)\n", name, req->start, req->end, req->width, sample_start, sample_end, n_peaks)); + assert (n_peaks > 0 && n_peaks < 32767); boost::scoped_array peaks (new PeakData[n_peaks]); -- cgit v1.2.3