From 911399f8b38fb3b9b99aa5e4497ccb37dae0192d Mon Sep 17 00:00:00 2001 From: Robin Gareus Date: Thu, 28 Nov 2024 14:50:34 +0100 Subject: [PATCH] Use same rounding for wave-view rectangle as TAV Previously the waveform could exceed the AudioRegionView's Rectangle on either side due to rounding. ``` round ((start - end) / spp) != round (start/spp) - round (end/spp) ``` --- libs/waveview/wave_view.cc | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/libs/waveview/wave_view.cc b/libs/waveview/wave_view.cc index e2c6523fa1..fbdd2e0756 100644 --- a/libs/waveview/wave_view.cc +++ b/libs/waveview/wave_view.cc @@ -302,11 +302,24 @@ WaveView::get_item_and_draw_rect_in_window_coords (Rect const& canvas_rect, Rect * So let's start by determining the area covered by the region, in * window coordinates. It begins at zero (in item coordinates for this * waveview, and extends to region_length() / _samples_per_pixel. + * + * Use same rounding as UI's TimeAxisViewItem::set_samples_per_pixel, + * TimeAxisViewItem::reset_width_dependent_items */ + double spp = _props->samples_per_pixel; + double end_pixel = round ((_region->position () + _region->length ()).samples () / spp); + double start_pixel = round (_region->position ().samples () / spp); + double const width = end_pixel - start_pixel; - double const width = region_length() / _props->samples_per_pixel; item_rect = item_to_window (Rect (0.0, 0.0, width, _props->height), false); + /* do round actual start/end clip-mask, to match TimeAxisViewItem frame */ + double rx0 = round (item_rect.x0); + double rx1 = round (item_rect.x1); + + /* don't round item, this way sample-positions from pixels remain consistent + * (waveform does not jitter when region is split) + */ item_rect.x0 = floor (item_rect.x0); item_rect.x1 = ceil (item_rect.x1); item_rect.y0 = round (item_rect.y0); @@ -326,8 +339,8 @@ WaveView::get_item_and_draw_rect_in_window_coords (Rect const& canvas_rect, Rect * We round down in case we were asked to draw "between" pixels at the start * and/or end. */ - draw_rect.x0 = floor (draw_rect.x0); - draw_rect.x1 = ceil (draw_rect.x1); + draw_rect.x0 = max (floor (draw_rect.x0), rx0); + draw_rect.x1 = min (ceil (draw_rect.x1), rx1); return true; } @@ -1153,7 +1166,10 @@ void WaveView::compute_bounding_box () const { if (_region) { - _bounding_box = Rect (0.0, 0.0, region_length() / _props->samples_per_pixel, _props->height); + double spp = _props->samples_per_pixel; + double end_pixel = round ((_region->position () + _region->length ()).samples () / spp); + double start_start = round (_region->position ().samples () / spp); + _bounding_box = Rect (0.0, 0.0, end_pixel - start_start, _props->height); } else { _bounding_box = Rect (); }