changeset 1401:28075cc658c9

Scale pen for retina display on macOS as well as for hidpi display elsewhere
author Chris Cannam
date Thu, 15 Nov 2018 14:04:32 +0000
parents decb7741d036
children b0eeec95ab5b
files layer/LayerGeometryProvider.h layer/PaintAssistant.cpp layer/PaintAssistant.h layer/SliceLayer.cpp layer/TimeValueLayer.cpp layer/WaveformLayer.cpp view/Pane.cpp view/View.cpp view/View.h view/ViewProxy.h
diffstat 10 files changed, 101 insertions(+), 84 deletions(-) [+]
line wrap: on
line diff
--- a/layer/LayerGeometryProvider.h	Thu Nov 15 13:06:38 2018 +0000
+++ b/layer/LayerGeometryProvider.h	Thu Nov 15 14:04:32 2018 +0000
@@ -178,6 +178,10 @@
                                      QRect rect, bool focus) const = 0;
 
     virtual void updatePaintRect(QRect r) = 0;
+
+    virtual double scaleSize(double size) const = 0;
+    virtual double scalePenWidth(double width) const = 0;
+    virtual QPen scalePen(QPen pen) const = 0;
     
     virtual View *getView() = 0;
     virtual const View *getView() const = 0;
--- a/layer/PaintAssistant.cpp	Thu Nov 15 13:06:38 2018 +0000
+++ b/layer/PaintAssistant.cpp	Thu Nov 15 14:04:32 2018 +0000
@@ -241,48 +241,4 @@
     }
 }
 
-double
-PaintAssistant::scaleSize(double size)
-{
-    static double ratio = 0.0;
-    if (ratio == 0.0) {
-        double baseEm;
-#ifdef Q_OS_MAC
-        baseEm = 17.0;
-#else
-        baseEm = 15.0;
-#endif
-        double em = QFontMetrics(QFont()).height();
-        ratio = em / baseEm;
 
-        SVDEBUG << "PaintAssistant::scaleSize: ratio is " << ratio
-                << " (em = " << em << ")" << endl;
-
-        if (ratio < 1.0) {
-            SVDEBUG << "PaintAssistant::scaleSize: rounding ratio up to 1.0"
-                    << endl;
-            ratio = 1.0;
-        }
-    }
-
-    return size * ratio;
-}
-
-double
-PaintAssistant::scalePenWidth(double width)
-{
-    if (width <= 0) {
-        // zero-width pen, produce a scaled one-pixel pen
-        width = 1;
-    }
-
-    return scaleSize(width);
-}
-
-QPen
-PaintAssistant::scalePen(QPen pen)
-{
-    return QPen(pen.color(), scalePenWidth(pen.width()));
-}
-
-
--- a/layer/PaintAssistant.h	Thu Nov 15 13:06:38 2018 +0000
+++ b/layer/PaintAssistant.h	Thu Nov 15 14:04:32 2018 +0000
@@ -47,27 +47,6 @@
     static void drawVisibleText(const LayerGeometryProvider *,
                                 QPainter &p, int x, int y,
                                 QString text, TextStyle style);
-
-    /**
-     * Scale up a size in pixels for a hi-dpi display without pixel
-     * doubling. This is like ViewManager::scalePixelSize, but taking
-     * and returning floating-point values rather than integer
-     * pixels. It is also a little more conservative - it never
-     * shrinks the size, it can only increase or leave it unchanged.
-     */
-    static double scaleSize(double size);
-
-    /**
-     * Scale up pen width for a hi-dpi display without pixel doubling.
-     * This is like scaleSize except that it also scales the
-     * zero-width case.
-     */
-    static double scalePenWidth(double width);
-
-    /**
-     * Apply scalePenWidth to a pen.
-     */
-    static QPen scalePen(QPen pen);
 };
 
 #endif
--- a/layer/SliceLayer.cpp	Thu Nov 15 13:06:38 2018 +0000
+++ b/layer/SliceLayer.cpp	Thu Nov 15 14:04:32 2018 +0000
@@ -457,7 +457,7 @@
         // thinner pen
         QPen pen;
         if (mh < 10000) {
-            pen = PaintAssistant::scalePen(QPen(getBaseQColor(), 0.8));
+            pen = v->scalePen(QPen(getBaseQColor(), 0.8));
         } else {
             pen = QPen(getBaseQColor(), 1);
         }
--- a/layer/TimeValueLayer.cpp	Thu Nov 15 13:06:38 2018 +0000
+++ b/layer/TimeValueLayer.cpp	Thu Nov 15 14:04:32 2018 +0000
@@ -565,7 +565,7 @@
     }
 
     if (!usePoints.empty()) {
-        int fuzz = ViewManager::scalePixelSize(2);
+        int fuzz = v->scaleSize(2);
         int px = v->getXForFrame(usePoints.begin()->frame);
         if ((px > x && px - x > fuzz) ||
             (px < x && x - px > fuzz + 3)) {
@@ -1061,7 +1061,7 @@
             brush = QBrush(Qt::NoBrush);
         }
         
-        paint.setPen(PaintAssistant::scalePen(pen));
+        paint.setPen(v->scalePen(pen));
         paint.setBrush(brush);
         
         if (m_plotStyle == PlotStems) {
@@ -1092,7 +1092,7 @@
             m_plotStyle != PlotSegmentation) {
             if (illuminate) {
                 paint.save();
-                paint.setPen(PaintAssistant::scalePen(getForegroundQColor(v)));
+                paint.setPen(v->scalePen(getForegroundQColor(v)));
                 paint.setBrush(getForegroundQColor(v));
             }
             if (m_plotStyle != PlotStems ||
@@ -1114,7 +1114,7 @@
                 if (m_plotStyle == PlotConnectedPoints) {
                     
                     paint.save();
-                    paint.setPen(PaintAssistant::scalePen(brushColour));
+                    paint.setPen(v->scalePen(brushColour));
                     paint.drawLine(x + w, y, nx, ny);
                     paint.restore();
 
@@ -1173,7 +1173,7 @@
             
             if (nx <= x) continue;
 
-            paint.setPen(PaintAssistant::scalePen(QPen(getForegroundQColor(v), 2)));
+            paint.setPen(v->scalePen(QPen(getForegroundQColor(v), 2)));
 
             if (!illuminate) {
                 if (!m_drawSegmentDivisions ||
--- a/layer/WaveformLayer.cpp	Thu Nov 15 13:06:38 2018 +0000
+++ b/layer/WaveformLayer.cpp	Thu Nov 15 14:04:32 2018 +0000
@@ -1053,10 +1053,10 @@
     }
     
     if (!individualSamplePoints.empty()) {
-        double sz = PaintAssistant::scaleSize(2.0);
+        double sz = v->scaleSize(2.0);
         if (v->getZoomLevel().zone == ZoomLevel::PixelsPerFrame) {
             if (v->getZoomLevel().level < 10) {
-                sz = PaintAssistant::scaleSize(1.2);
+                sz = v->scaleSize(1.2);
             }
         }
         paint->save();
--- a/view/Pane.cpp	Thu Nov 15 13:06:38 2018 +0000
+++ b/view/Pane.cpp	Thu Nov 15 14:04:32 2018 +0000
@@ -688,7 +688,7 @@
         c = QColor(240, 240, 240);
     }
 
-    paint.setPen(PaintAssistant::scalePen(c));
+    paint.setPen(scalePen(c));
     int x = width() / 2;
 
     if (!omitLine) {
@@ -1173,7 +1173,7 @@
 
     if (!m_manager) return Selection();
 
-    sv_frame_t testFrame = getFrameForX(x - ViewManager::scalePixelSize(5));
+    sv_frame_t testFrame = getFrameForX(x - scaleSize(5));
     if (testFrame < 0) {
         testFrame = getFrameForX(x);
         if (testFrame < 0) return Selection();
@@ -1185,14 +1185,14 @@
     int lx = getXForFrame(selection.getStartFrame());
     int rx = getXForFrame(selection.getEndFrame());
     
-    int fuzz = ViewManager::scalePixelSize(2);
+    int fuzz = scaleSize(2);
     if (x < lx - fuzz || x > rx + fuzz) return Selection();
 
     int width = rx - lx;
-    fuzz = ViewManager::scalePixelSize(3);
+    fuzz = scaleSize(3);
     if (width < 12) fuzz = width / 4;
-    if (fuzz < ViewManager::scalePixelSize(1)) {
-        fuzz = ViewManager::scalePixelSize(1);
+    if (fuzz < scaleSize(1)) {
+        fuzz = scaleSize(1);
     }
 
     if (x < lx + fuzz) closeToLeftEdge = true;
--- a/view/View.cpp	Thu Nov 15 13:06:38 2018 +0000
+++ b/view/View.cpp	Thu Nov 15 14:04:32 2018 +0000
@@ -238,7 +238,7 @@
         }
     }
 
-    int y = ViewManager::scalePixelSize(15) + paint.fontMetrics().ascent();
+    int y = scaleSize(15) + paint.fontMetrics().ascent();
 
     for (std::map<int, Layer *>::const_iterator i = sortedLayers.begin();
          i != sortedLayers.end(); ++i) {
@@ -674,7 +674,7 @@
     QPushButton *cancel = new QPushButton(this);
     cancel->setIcon(IconLoader().load("cancel"));
     cancel->setFlat(true);
-    int scaled20 = ViewManager::scalePixelSize(20);
+    int scaled20 = scaleSize(20);
     cancel->setFixedSize(QSize(scaled20, scaled20));
     connect(cancel, SIGNAL(clicked()), this, SLOT(cancelClicked()));
     
@@ -1593,6 +1593,49 @@
     return n;
 }
 
+double
+View::scaleSize(double size) const
+{
+    static double ratio = 0.0;
+
+    if (ratio == 0.0) {
+        double baseEm;
+#ifdef Q_OS_MAC
+        baseEm = 17.0;
+#else
+        baseEm = 15.0;
+#endif
+        double em = QFontMetrics(QFont()).height();
+        ratio = em / baseEm;
+
+        SVDEBUG << "View::scaleSize: ratio is " << ratio
+                << " (em = " << em << ")" << endl;
+
+        if (ratio < 1.0) {
+            SVDEBUG << "View::scaleSize: rounding ratio up to 1.0" << endl;
+            ratio = 1.0;
+        }
+    }
+
+    return size * ratio;
+}
+
+double
+View::scalePenWidth(double width) const 
+{
+    if (width <= 0) { // zero-width pen, produce a scaled one-pixel pen
+        width = 1;
+    }
+    double ratio = scaleSize(1.0);
+    return width * sqrt(ratio);
+}
+
+QPen
+View::scalePen(QPen pen) const 
+{
+    return QPen(pen.color(), scalePenWidth(pen.width()));
+}
+
 bool
 View::areLayerColoursSignificant() const
 {
@@ -1749,7 +1792,7 @@
                     timer->start();
                 }
 
-                int scaled20 = ViewManager::scalePixelSize(20);
+                int scaled20 = scaleSize(20);
 
                 cancel->move(0, ph - pb->height()/2 - scaled20/2);
                 cancel->show();
@@ -2170,7 +2213,7 @@
             (illuminateFrame >= 0 && i->contains(illuminateFrame));
 
         double h = height();
-        double penWidth = PaintAssistant::scalePenWidth(1.0);
+        double penWidth = scalePenWidth(1.0);
         double half = penWidth/2.0;
 
         paint.setPen(QPen(QColor(150, 150, 255), penWidth));
@@ -2187,7 +2230,7 @@
 
         if (illuminateThis) {
             paint.save();
-            penWidth = PaintAssistant::scalePenWidth(2.0);
+            penWidth = scalePenWidth(2.0);
             half = penWidth/2.0;
             paint.setPen(QPen(getForeground(), penWidth));
             if (closeToLeft) {
--- a/view/View.h	Thu Nov 15 13:06:38 2018 +0000
+++ b/view/View.h	Thu Nov 15 14:04:32 2018 +0000
@@ -376,6 +376,10 @@
     int getPaintWidth() const { return getPaintRect().width(); }
     int getPaintHeight() const { return getPaintRect().height(); }
 
+    double scaleSize(double size) const;
+    double scalePenWidth(double width) const;
+    QPen scalePen(QPen pen) const;
+
     typedef std::set<Model *> ModelSet;
     ModelSet getModels();
 
--- a/view/ViewProxy.h	Thu Nov 15 13:06:38 2018 +0000
+++ b/view/ViewProxy.h	Thu Nov 15 14:04:32 2018 +0000
@@ -143,6 +143,37 @@
                        r.width() / m_scaleFactor,
                        r.height() / m_scaleFactor);
     }
+
+    /**
+     * Scale up a size in pixels for a hi-dpi display without pixel
+     * doubling. This is like ViewManager::scalePixelSize, but taking
+     * and returning floating-point values rather than integer
+     * pixels. It is also a little more conservative - it never
+     * shrinks the size, it can only increase or leave it unchanged.
+     */
+    virtual double scaleSize(double size) const {
+        return m_view->scaleSize(size * m_scaleFactor);
+    }
+
+    /**
+     * Scale up pen width for a hi-dpi display without pixel doubling.
+     * This is like scaleSize except that it also scales the
+     * zero-width case.
+     */
+    virtual double scalePenWidth(double width) const {
+        if (width <= 0) { // zero-width pen, produce a scaled one-pixel pen
+            width = 1;
+        }
+        width *= sqrt(double(m_scaleFactor));
+        return m_view->scalePenWidth(width);
+    }
+
+    /**
+     * Apply scalePenWidth to a pen.
+     */
+    virtual QPen scalePen(QPen pen) const {
+        return QPen(pen.color(), scalePenWidth(pen.width()));
+    }
     
     virtual View *getView() { return m_view; }
     virtual const View *getView() const { return m_view; }