changeset 1375:694004228ab7 zoom

Fix incorrect start/end overlay drawing when zoomed far in
author Chris Cannam
date Tue, 06 Nov 2018 10:51:46 +0000
parents 631897ba9fca
children 5a051ca3170e
files layer/WaveformLayer.cpp layer/WaveformLayer.h view/Pane.cpp view/View.cpp view/View.h
diffstat 5 files changed, 66 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/layer/WaveformLayer.cpp	Tue Nov 06 08:59:03 2018 +0000
+++ b/layer/WaveformLayer.cpp	Tue Nov 06 10:51:46 2018 +0000
@@ -826,7 +826,8 @@
         }
 
         if (f0 < frame0) {
-            SVCERR << "ERROR: WaveformLayer::paint: pixel " << x << " has f0 = " << f0 << " which is less than range frame0 " << frame0 << " for x0 = " << x0 << endl;
+            // Not an error, this simply occurs when painting the
+            // start of a signal in PixelsPerFrame zone
             continue;
         }
 
--- a/layer/WaveformLayer.h	Tue Nov 06 08:59:03 2018 +0000
+++ b/layer/WaveformLayer.h	Tue Nov 06 10:51:46 2018 +0000
@@ -20,6 +20,8 @@
 
 #include "SingleColourLayer.h"
 
+#include "base/ZoomLevel.h"
+
 #include "data/model/RangeSummarisableTimeValueModel.h"
 
 class View;
--- a/view/Pane.cpp	Tue Nov 06 08:59:03 2018 +0000
+++ b/view/Pane.cpp	Tue Nov 06 10:51:46 2018 +0000
@@ -750,11 +750,8 @@
 void
 Pane::drawModelTimeExtents(QRect r, QPainter &paint, const Model *model)
 {
-    int x0 = getXForFrame(model->getStartFrame());
-    int x1 = getXForFrame(model->getEndFrame());
-
     paint.save();
-
+    
     QBrush brush;
 
     if (hasLightBackground()) {
@@ -765,14 +762,24 @@
         paint.setPen(Qt::white);
     }
 
-    if (x0 > r.x()) {
-        paint.fillRect(0, 0, x0, height(), brush);
-        paint.drawLine(x0, 0, x0, height());
+    sv_frame_t f0 = model->getStartFrame();
+
+    if (f0 > getStartFrame() && f0 < getEndFrame()) {
+        int x0 = getXForFrame(f0);
+        if (x0 > r.x()) {
+            paint.fillRect(0, 0, x0, height(), brush);
+            paint.drawLine(x0, 0, x0, height());
+        }
     }
 
-    if (x1 < r.x() + r.width()) {
-        paint.fillRect(x1, 0, width() - x1, height(), brush);
-        paint.drawLine(x1, 0, x1, height());
+    sv_frame_t f1 = model->getEndFrame();
+    
+    if (f1 > getStartFrame() && f1 < getEndFrame()) {
+        int x1 = getXForFrame(f1);
+        if (x1 < r.x() + r.width()) {
+            paint.fillRect(x1, 0, width() - x1, height(), brush);
+            paint.drawLine(x1, 0, x1, height());
+        }
     }
 
     paint.restore();
--- a/view/View.cpp	Tue Nov 06 08:59:03 2018 +0000
+++ b/view/View.cpp	Tue Nov 06 10:51:46 2018 +0000
@@ -395,18 +395,50 @@
     
     sv_frame_t level = m_zoomLevel.level;
     sv_frame_t fdiff = frame - getCentreFrame();
-    int diff, result;
-
+    int result = 0;
+
+    bool inRange = false;
     if (m_zoomLevel.zone == ZoomLevel::FramesPerPixel) {
-        diff = int(fdiff / level);
-        if ((fdiff < 0) && ((fdiff % level) != 0)) {
-            --diff; // round to the left
+        inRange = ((fdiff / level) < sv_frame_t(INT_MAX) &&
+                   (fdiff / level) > sv_frame_t(INT_MIN));
+    } else {
+        inRange = (fdiff < sv_frame_t(INT_MAX) / level &&
+                   fdiff > sv_frame_t(INT_MIN) / level);
+    }
+
+    if (inRange) {
+        
+        sv_frame_t adjusted;
+
+        if (m_zoomLevel.zone == ZoomLevel::FramesPerPixel) {
+            adjusted = fdiff / level;
+            if ((fdiff < 0) && ((fdiff % level) != 0)) {
+                --adjusted; // round to the left
+            }
+        } else {
+            adjusted = fdiff * level;
         }
-    } else {
-        diff = int(fdiff * level);
+
+        adjusted = adjusted + (width()/2);
+
+        if (adjusted > INT_MAX || adjusted < INT_MIN) {
+            inRange = false;
+        } else {
+            result = int(adjusted);
+        }
     }
 
-    result = int(diff + (width()/2));
+    if (!inRange) {
+        SVCERR << "ERROR: Frame " << frame
+               << " is out of range in View::getXForFrame" << endl;
+        SVCERR << "ERROR: (centre frame = " << getCentreFrame() << ", fdiff = "
+               << fdiff << ", zoom level = " << m_zoomLevel << ")" << endl;
+        SVCERR << "ERROR: This is a logic error: getXForFrame should not be "
+               << "called for locations unadjacent to the current view"
+               << endl;
+        return 0;
+    }
+
     return result;
 }
 
--- a/view/View.h	Tue Nov 06 08:59:03 2018 +0000
+++ b/view/View.h	Tue Nov 06 10:51:46 2018 +0000
@@ -104,7 +104,11 @@
 
     /**
      * Return the pixel x-coordinate corresponding to a given sample
-     * frame (which may be negative).
+     * frame. The frame is permitted to be negative, and the result
+     * may be outside the currently visible area. But this should not
+     * be called with frame values very far away from the currently
+     * visible area, as that could lead to overflow. In that situation
+     * an error will be logged and 0 returned.
      */
     int getXForFrame(sv_frame_t frame) const;