changeset 1327:646e713a4632 zoom

Further ZoomLevel fixes
author Chris Cannam
date Thu, 20 Sep 2018 11:45:26 +0100
parents 97c68bffbda6
children b39cd8fb309f
files view/View.cpp view/ViewManager.cpp view/ViewManager.h
diffstat 3 files changed, 99 insertions(+), 57 deletions(-) [+]
line wrap: on
line diff
--- a/view/View.cpp	Thu Sep 20 10:45:24 2018 +0100
+++ b/view/View.cpp	Thu Sep 20 11:45:26 2018 +0100
@@ -330,20 +330,30 @@
 
     if (m_centreFrame != f) {
 
-        int formerPixel = int(m_centreFrame / m_zoomLevel);
-
+        sv_frame_t formerCentre = m_centreFrame;
         m_centreFrame = f;
-
-        int newPixel = int(m_centreFrame / m_zoomLevel);
         
-        if (newPixel != formerPixel) {
+        if (m_zoomLevel.zone == ZoomLevel::PixelsPerFrame) {
 
 #ifdef DEBUG_VIEW_WIDGET_PAINT
-            cout << "View(" << this << ")::setCentreFrame: newPixel " << newPixel << ", formerPixel " << formerPixel << endl;
+            SVCERR << "View(" << this << ")::setCentreFrame: in PixelsPerFrame zone, so change must be visible" << endl;
 #endif
             update();
-
             changeVisible = true;
+
+        } else {
+        
+            int formerPixel = int(formerCentre / m_zoomLevel.level);
+            int newPixel = int(m_centreFrame / m_zoomLevel.level);
+        
+            if (newPixel != formerPixel) {
+
+#ifdef DEBUG_VIEW_WIDGET_PAINT
+                SVCERR << "View(" << this << ")::setCentreFrame: newPixel " << newPixel << ", formerPixel " << formerPixel << endl;
+#endif
+                update();
+                changeVisible = true;
+            }
         }
 
         if (e) {
@@ -363,23 +373,30 @@
 int
 View::getXForFrame(sv_frame_t frame) const
 {
-    return int((frame - getStartFrame()) / m_zoomLevel);
+    sv_frame_t fdiff = frame - getCentreFrame();
+
+    if (m_zoomLevel.zone == ZoomLevel::FramesPerPixel) {
+        fdiff /= m_zoomLevel.level;
+    } else {
+        fdiff *= m_zoomLevel.level;
+    }
+
+    return int(fdiff + (width()/2));
 }
 
 sv_frame_t
 View::getFrameForX(int x) const
 {
-    sv_frame_t z = m_zoomLevel; // nb not just int, or multiplication may overflow
-    sv_frame_t frame = m_centreFrame - (width()/2) * z;
-
-    frame = (frame / z) * z; // this is start frame
-    frame = frame + x * z;
-
-#ifdef DEBUG_VIEW_WIDGET_PAINT
-    cerr << "View::getFrameForX(" << x << "): z = " << z << ", m_centreFrame = " << m_centreFrame << ", width() = " << width() << ", frame = " << frame << endl;
-#endif
-
-    return frame;
+    int diff = x - (width()/2);
+    sv_frame_t fdiff = diff;
+
+    if (m_zoomLevel.zone == ZoomLevel::FramesPerPixel) {
+        fdiff *= m_zoomLevel.level;
+    } else {
+        fdiff /= m_zoomLevel.level;
+    }
+
+    return fdiff + m_centreFrame;
 }
 
 double
@@ -479,14 +496,15 @@
 void
 View::setZoomLevel(ZoomLevel z)
 {
-    int dpratio = effectiveDevicePixelRatio();
-    if (z < dpratio) return;
-    if (z < 1) z = 1;
-    if (m_zoomLevel != int(z)) {
-        m_zoomLevel = z;
-        emit zoomLevelChanged(z, m_followZoom);
-        update();
+//!!!    int dpratio = effectiveDevicePixelRatio();
+//    if (z < dpratio) return;
+//    if (z < 1) z = 1;
+    if (m_zoomLevel == z) {
+        return;
     }
+    m_zoomLevel = z;
+    emit zoomLevelChanged(z, m_followZoom);
+    update();
 }
 
 bool
@@ -1400,30 +1418,32 @@
     return nonScrollables;
 }
 
-int
-View::getZoomConstraintBlockSize(int blockSize,
-                                 ZoomConstraint::RoundingDirection dir)
+ZoomLevel
+View::getZoomConstraintLevel(ZoomLevel zoomLevel,
+                             ZoomConstraint::RoundingDirection dir)
     const
 {
-    int candidate = blockSize;
+    using namespace std::rel_ops;
+    
+    ZoomLevel candidate = zoomLevel;
     bool haveCandidate = false;
 
     PowerOfSqrtTwoZoomConstraint defaultZoomConstraint;
 
-    for (LayerList::const_iterator i = m_layerStack.begin(); i != m_layerStack.end(); ++i) {
+    for (auto i = m_layerStack.begin(); i != m_layerStack.end(); ++i) {
 
         const ZoomConstraint *zoomConstraint = (*i)->getZoomConstraint();
         if (!zoomConstraint) zoomConstraint = &defaultZoomConstraint;
 
-        int thisBlockSize =
-            zoomConstraint->getNearestBlockSize(blockSize, dir);
+        ZoomLevel thisLevel =
+            zoomConstraint->getNearestZoomLevel(zoomLevel, dir);
 
         // Go for the block size that's furthest from the one
         // passed in.  Most of the time, that's what we want.
         if (!haveCandidate ||
-            (thisBlockSize > blockSize && thisBlockSize > candidate) ||
-            (thisBlockSize < blockSize && thisBlockSize < candidate)) {
-            candidate = thisBlockSize;
+            (thisLevel > zoomLevel && thisLevel > candidate) ||
+            (thisLevel < zoomLevel && thisLevel < candidate)) {
+            candidate = thisLevel;
             haveCandidate = true;
         }
     }
@@ -1464,6 +1484,8 @@
                                               ZoomConstraint::RoundUp);
     }
 
+    using namespace std::rel_ops;
+    
     if (newZoomLevel != m_zoomLevel) {
         setZoomLevel(newZoomLevel);
     }
@@ -1763,6 +1785,8 @@
                   << m_cacheZoomLevel << ", zoom " << m_zoomLevel << endl;
 #endif
 
+        using namespace std::rel_ops;
+    
         if (!m_cache ||
             m_cacheZoomLevel != m_zoomLevel ||
             scaledCacheSize != m_cache->size()) {
@@ -2368,8 +2392,8 @@
 bool
 View::render(QPainter &paint, int xorigin, sv_frame_t f0, sv_frame_t f1)
 {
-    int x0 = int(f0 / m_zoomLevel);
-    int x1 = int(f1 / m_zoomLevel);
+    int x0 = int(round(m_zoomLevel.framesToPixels(double(f0))));
+    int x1 = int(round(m_zoomLevel.framesToPixels(double(f1))));
 
     int w = x1 - x0;
 
@@ -2431,7 +2455,8 @@
             return false;
         }
 
-        m_centreFrame = f0 + (x + width()/2) * m_zoomLevel;
+        m_centreFrame = f0 + sv_frame_t(round(m_zoomLevel.pixelsToFrames
+                                              (x + width()/2)));
         
         QRect chunk(0, 0, width(), height());
 
@@ -2482,8 +2507,8 @@
 QImage *
 View::renderPartToNewImage(sv_frame_t f0, sv_frame_t f1)
 {
-    int x0 = int(f0 / getZoomLevel());
-    int x1 = int(f1 / getZoomLevel());
+    int x0 = int(round(getZoomLevel().framesToPixels(double(f0))));
+    int x1 = int(round(getZoomLevel().framesToPixels(double(f1))));
     
     QImage *image = new QImage(x1 - x0, height(), QImage::Format_RGB32);
 
@@ -2510,8 +2535,8 @@
 QSize
 View::getRenderedPartImageSize(sv_frame_t f0, sv_frame_t f1)
 {
-    int x0 = int(f0 / getZoomLevel());
-    int x1 = int(f1 / getZoomLevel());
+    int x0 = int(round(getZoomLevel().framesToPixels(double(f0))));
+    int x1 = int(round(getZoomLevel().framesToPixels(double(f1))));
 
     return QSize(x1 - x0, height());
 }
@@ -2528,8 +2553,8 @@
 bool
 View::renderPartToSvgFile(QString filename, sv_frame_t f0, sv_frame_t f1)
 {
-    int x0 = int(f0 / getZoomLevel());
-    int x1 = int(f1 / getZoomLevel());
+    int x0 = int(round(getZoomLevel().framesToPixels(double(f0))));
+    int x1 = int(round(getZoomLevel().framesToPixels(double(f1))));
 
     QSvgGenerator generator;
     generator.setFileName(filename);
@@ -2551,15 +2576,27 @@
 {
     stream << indent;
 
+    int classicZoomValue, deepZoomValue;
+
+    if (m_zoomLevel.zone == ZoomLevel::FramesPerPixel) {
+        classicZoomValue = m_zoomLevel.level;
+        deepZoomValue = 1;
+    } else {
+        classicZoomValue = 1;
+        deepZoomValue = m_zoomLevel.level;
+    }
+
     stream << QString("<view "
                       "centre=\"%1\" "
                       "zoom=\"%2\" "
-                      "followPan=\"%3\" "
-                      "followZoom=\"%4\" "
-                      "tracking=\"%5\" "
+                      "deepZoom=\"%3\" "
+                      "followPan=\"%4\" "
+                      "followZoom=\"%5\" "
+                      "tracking=\"%6\" "
                       " %6>\n")
         .arg(m_centreFrame)
-        .arg(m_zoomLevel)
+        .arg(classicZoomValue)
+        .arg(deepZoomValue)
         .arg(m_followPan)
         .arg(m_followZoom)
         .arg(m_followPlay == PlaybackScrollContinuous ? "scroll" :
--- a/view/ViewManager.cpp	Thu Sep 20 10:45:24 2018 +0100
+++ b/view/ViewManager.cpp	Thu Sep 20 11:45:26 2018 +0100
@@ -33,7 +33,7 @@
     m_playSource(0),
     m_recordTarget(0),
     m_globalCentreFrame(0),
-    m_globalZoom(1024),
+    m_globalZoom(ZoomLevel::FramesPerPixel, 1024),
     m_playbackFrame(0),
     m_playbackModel(0),
     m_mainModelSampleRate(0),
@@ -147,7 +147,7 @@
     emit globalCentreFrameChanged(f);
 }
 
-int
+ZoomLevel
 ViewManager::getGlobalZoom() const
 {
 #ifdef DEBUG_VIEW_MANAGER
@@ -687,7 +687,7 @@
 }
 
 void
-ViewManager::viewZoomLevelChanged(int z, bool locked)
+ViewManager::viewZoomLevelChanged(ZoomLevel z, bool locked)
 {
     View *v = dynamic_cast<View *>(sender());
 
@@ -709,7 +709,11 @@
     emit viewZoomLevelChanged(v, z, locked);
 
     if (!dynamic_cast<Overview *>(v)) {
-        emit activity(tr("Zoom to %n sample(s) per pixel", "", z));
+        if (z.zone == ZoomLevel::FramesPerPixel) {
+            emit activity(tr("Zoom to %n sample(s) per pixel", "", z.level));
+        } else {
+            emit activity(tr("Zoom to %n pixels per sample", "", z.level));
+        }
     }
 }
 
--- a/view/ViewManager.h	Thu Sep 20 10:45:24 2018 +0100
+++ b/view/ViewManager.h	Thu Sep 20 11:45:26 2018 +0100
@@ -27,6 +27,7 @@
 #include "base/Command.h"
 #include "base/Clipboard.h"
 #include "base/BaseTypes.h"
+#include "base/ZoomLevel.h"
 
 class AudioPlaySource;
 class AudioRecordTarget;
@@ -87,7 +88,7 @@
     bool isRecording() const;
 
     sv_frame_t getGlobalCentreFrame() const; // the set method is a slot
-    int getGlobalZoom() const;
+    ZoomLevel getGlobalZoom() const;
 
     sv_frame_t getPlaybackFrame() const; // the set method is a slot
 
@@ -255,7 +256,7 @@
     void viewCentreFrameChanged(View *v, sv_frame_t frame);
 
     /** Emitted when a view zooms. */
-    void viewZoomLevelChanged(View *v, int zoom, bool locked);
+    void viewZoomLevelChanged(View *v, ZoomLevel zoom, bool locked);
 
     /** Emitted when the playback frame changes. */
     void playbackFrameChanged(sv_frame_t frame);
@@ -307,7 +308,7 @@
 
 public slots:
     void viewCentreFrameChanged(sv_frame_t, bool, PlaybackFollowMode);
-    void viewZoomLevelChanged(int, bool);
+    void viewZoomLevelChanged(ZoomLevel, bool);
     void setGlobalCentreFrame(sv_frame_t);
     void setPlaybackFrame(sv_frame_t);
     void playStatusChanged(bool playing);
@@ -323,7 +324,7 @@
     AudioRecordTarget *m_recordTarget;
     
     sv_frame_t m_globalCentreFrame;
-    int m_globalZoom;
+    ZoomLevel m_globalZoom;
     mutable sv_frame_t m_playbackFrame;
     Model *m_playbackModel; //!!!
     sv_samplerate_t m_mainModelSampleRate;