]> git.lyx.org Git - lyx.git/commitdiff
#9130 Text in main work area isn't rendered with high resolution
authorStephan Witt <switt@lyx.org>
Sun, 12 Oct 2014 17:23:13 +0000 (19:23 +0200)
committerStephan Witt <switt@lyx.org>
Sat, 18 Oct 2014 09:53:16 +0000 (11:53 +0200)
Introduce the concept of pixel ratio: the ratio of physical and device independent pixels.
This is useful for rendering of content on Retina-displays of Mac hardware with high resolution.
Qt has real support for this starting with Qt5 - therefore it has to be compiled conditionally.
This change uses some work of Marcelo Galvão Póvoa, thank you.

src/frontends/Painter.h
src/frontends/qt4/GuiApplication.cpp
src/frontends/qt4/GuiApplication.h
src/frontends/qt4/GuiPainter.cpp
src/frontends/qt4/GuiPainter.h
src/frontends/qt4/GuiView.cpp
src/frontends/qt4/GuiView.h
src/frontends/qt4/GuiWorkArea.cpp
src/frontends/qt4/GuiWorkArea.h
src/frontends/qt4/GuiWorkArea_Private.h

index 78ec6e5715a69400a57868e68a1fecad8d9473c5..221da4ada72bb5e30375d54dd640fdefece8772e 100644 (file)
@@ -54,7 +54,7 @@ namespace frontend {
  */
 class Painter {
 public:
-       Painter() : drawing_enabled_(true) {}
+       Painter(double pixel_ratio) : drawing_enabled_(true), pixel_ratio_(pixel_ratio) {}
 
        static const float thin_line;
 
@@ -134,6 +134,8 @@ public:
        /// Indicate wether real screen drawing shall be done or not.
        bool isDrawingEnabled() const { return drawing_enabled_; }
 
+       double pixelRatio() const { return pixel_ratio_; }
+
        /// draw a char at position x, y (y is the baseline)
        /**
        * \return the width of the drawn text.
@@ -170,6 +172,8 @@ public:
 private:
        ///
        bool drawing_enabled_;
+       /// Ratio between physical pixels and device-independent pixels
+       double pixel_ratio_;
 };
 
 } // namespace frontend
index d09bcdbb5f76201b8ad0bbf0e73cb9888e79d112..2697abeb6146025401edcdb6ed372e02a6b47067 100644 (file)
@@ -17,7 +17,6 @@
 #include "ColorCache.h"
 #include "ColorSet.h"
 #include "GuiClipboard.h"
-#include "GuiImage.h"
 #include "GuiKeySymbol.h"
 #include "GuiSelection.h"
 #include "GuiView.h"
@@ -1039,6 +1038,16 @@ GuiApplication * theGuiApp()
 }
 
 
+double GuiApplication::pixelRatio() const
+{
+#if QT_VERSION > 0x050000
+       return devicePixelRatio();
+#else
+       return 1.0;
+#endif
+}
+       
+       
 void GuiApplication::clearSession()
 {
        QSettings settings;
index 5e4cda2e8ca7353e5200c792e9d75f55cba315b0..410ccc4426384ff33654b3254b72952af684d459 100644 (file)
@@ -139,7 +139,10 @@ public:
        void unregisterView(GuiView * gv);
        ///
        GuiView & view(int id) const;
-       ///
+
+       /// Current ratio between physical pixels and device-independent pixels
+       double pixelRatio() const;
+       
        void processKeySym(KeySymbol const & key, KeyModifier state);
        /// return the status bar state string
        docstring viewStatusMessage();
index c7d56c8b71f27701e4eb89c68ac27eb115b6c2b9..986ac4672aecc499126d535006166ae84bd9a447 100644 (file)
@@ -52,8 +52,8 @@ namespace frontend {
   
 const float Painter::thin_line = 0.0;
 
-GuiPainter::GuiPainter(QPaintDevice * device)
-       : QPainter(device), Painter(),
+GuiPainter::GuiPainter(QPaintDevice * device, double pixel_ratio)
+       : QPainter(device), Painter(pixel_ratio),
          use_pixmap_cache_(lyxrc.use_pixmap_cache && USE_PIXMAP_CACHE)
 {
        // new QPainter has default QPen:
@@ -270,7 +270,10 @@ void GuiPainter::image(int x, int y, int w, int h, graphics::Image const & i)
        if (!isDrawingEnabled())
                return;
 
-       drawImage(x, y, qlimage.image(), 0, 0, w, h);
+       QImage const image = qlimage.image();
+       QRectF const drect = QRectF(x, y, w, h);
+       QRectF const srect = QRectF(0, 0, image.width(), image.height());
+       drawImage(drect, image, srect);
 }
 
 
@@ -367,9 +370,12 @@ int GuiPainter::text(int x, int y, docstring const & s,
                int const mD = fm.maxDescent();
                int const h = mA + mD;
                if (w > 0 && h > 0) {
-                       pm = QPixmap(w, h);
+                       pm = QPixmap(pixelRatio() * w , pixelRatio() * h);
+#if QT_VERSION > 0x050000
+                       pm.setDevicePixelRatio(pixelRatio());
+#endif
                        pm.fill(Qt::transparent);
-                       GuiPainter p(&pm);
+                       GuiPainter p(&pm, pixelRatio());
                        p.setQPainterPen(computeColor(f.realColor()));
                        if (p.font() != ff)
                                p.setFont(ff);
index 3af51750fd9719919e2108d5bf88a6d820252035..e9c6fdf8b96b62db596bb329de55e716ee575416 100644 (file)
@@ -29,11 +29,11 @@ class FontInfo;
 namespace frontend {
 
 /**
- * GuiPainter - a painter implementation for Qt4
+ * GuiPainter - a painter implementation for Qt
  */
 class GuiPainter : public QPainter, public Painter {
 public:
-       GuiPainter(QPaintDevice *);
+       GuiPainter(QPaintDevice *, double pixel_ratio);
        virtual ~GuiPainter();
 
        /// draw a line from point to point
index cba88ee21d461072c1a74ab007ac0de1492bc7e7..8c5080763f083cf843a549df18e43b88cc65481a 100644 (file)
@@ -172,8 +172,13 @@ public:
 
        void paintEvent(QPaintEvent *)
        {
-               int x = (width() - splash_.width()) / 2;
-               int y = (height() - splash_.height()) / 2;
+               QRectF r = splash_.rect();
+#if QT_VERSION > 0x050000
+               r.setWidth(r.width() / splash_.devicePixelRatio());
+               r.setHeight(r.height() / splash_.devicePixelRatio());
+#endif
+               int x = (width() - r.width()) / 2;
+               int y = (height() - r.height()) / 2;
                QPainter pain(this);
                pain.drawPixmap(x, y, splash_);
        }
@@ -1204,6 +1209,16 @@ void GuiView::setBusy(bool busy)
 }
 
 
+double GuiView::pixelRatio() const
+{
+#if QT_VERSION > 0x050000
+       return devicePixelRatio();
+#else
+       return 1.0;
+#endif
+}
+       
+       
 GuiWorkArea * GuiView::workArea(int index)
 {
        if (TabWorkArea * twa = d.currentTabWorkArea())
index 9b7ee2e953357c469b98d1b45cc564af06f63b57..b10548d89eb78f9ed78b12a5a12d759f1d960c94 100644 (file)
@@ -199,6 +199,9 @@ public:
        GuiWorkArea const * currentMainWorkArea() const;
        /// return the current document WorkArea (it may not have the focus).
        GuiWorkArea * currentMainWorkArea();
+       
+       /// Current ratio between physical pixels and device-independent pixels
+       double pixelRatio() const;
 
 Q_SIGNALS:
        void closing(int);
index e5b2cf57c950cbdd4651a6038f3a75e475123659..fbc2eca088e9c44d125c4fac203ada58d488356c 100644 (file)
@@ -246,6 +246,7 @@ SyntheticMouseEvent::SyntheticMouseEvent()
 GuiWorkArea::Private::Private(GuiWorkArea * parent)
 : p(parent), screen_(0), buffer_view_(0), lyx_view_(0), cursor_visible_(false),
 need_resize_(false), schedule_redraw_(false), preedit_lines_(1),
+pixel_ratio_(1.0),
 completer_(new GuiCompleter(p, p))
 {
 }
@@ -266,6 +267,16 @@ GuiWorkArea::GuiWorkArea(Buffer & buffer, GuiView & gv)
 }
 
 
+double GuiWorkArea::pixelRatio() const
+{
+#if QT_VERSION > 0x050000
+       return devicePixelRatio();
+#else
+       return 1.0;
+#endif
+}
+
+
 void GuiWorkArea::init()
 {
        // Setup the signals
@@ -1120,11 +1131,11 @@ void GuiWorkArea::Private::update(int x, int y, int w, int h)
 
 void GuiWorkArea::paintEvent(QPaintEvent * ev)
 {
-       QRect const rc = ev->rect();
+       QRectF const rc = ev->rect();
        // LYXERR(Debug::PAINTING, "paintEvent begin: x: " << rc.x()
        //      << " y: " << rc.y() << " w: " << rc.width() << " h: " << rc.height());
 
-       if (d->need_resize_) {
+       if (d->needResize()) {
                d->resetScreen();
                d->resizeBufferView();
                if (d->cursor_visible_) {
@@ -1134,10 +1145,15 @@ void GuiWorkArea::paintEvent(QPaintEvent * ev)
        }
 
        QPainter pain(viewport());
+       double const pr = pixelRatio();
+       QRectF const rcs = QRectF(rc.x() * pr, rc.y() * pr, rc.width() * pr, rc.height() * pr);
+
        if (lyxrc.use_qimage) {
-               pain.drawImage(rc, static_cast<QImage const &>(*d->screen_), rc);
+               QImage const & image = static_cast<QImage const &>(*d->screen_);
+               pain.drawImage(rc, image, rcs);
        } else {
-               pain.drawPixmap(rc, static_cast<QPixmap const &>(*d->screen_), rc);
+               QPixmap const & pixmap = static_cast<QPixmap const &>(*d->screen_);
+               pain.drawPixmap(rc, pixmap, rcs);
        }
        d->cursor_->draw(pain);
        ev->accept();
@@ -1146,7 +1162,7 @@ void GuiWorkArea::paintEvent(QPaintEvent * ev)
 
 void GuiWorkArea::Private::updateScreen()
 {
-       GuiPainter pain(screen_);
+       GuiPainter pain(screen_, p->pixelRatio());
        buffer_view_->draw(pain);
 }
 
@@ -1220,7 +1236,7 @@ void GuiWorkArea::inputMethodEvent(QInputMethodEvent * e)
                return;
        }
 
-       GuiPainter pain(d->screen_);
+       GuiPainter pain(d->screen_, pixelRatio());
        d->buffer_view_->updateMetrics();
        d->buffer_view_->draw(pain);
        FontInfo font = d->buffer_view_->cursor().getFont().fontInfo();
index e5c488f6a8ae1fa473e36a7135da8b37e40b8ad5..fb6341b1a0789776acbf358eb676256e9357fc87 100644 (file)
@@ -84,6 +84,9 @@ public:
        GuiView const & view() const;
        GuiView & view();
 
+       /// Current ratio between physical pixels and device-independent pixels
+       double pixelRatio() const;
+
 public Q_SLOTS:
        ///
        void stopBlinkingCursor();
index 6d180dd175d8cd65036a1908111c2af573a716e4..0915b64d4c2d87b0c2bb456bacb65269225275f6 100644 (file)
@@ -117,14 +117,28 @@ struct GuiWorkArea::Private
        ///
        void setCursorShape(Qt::CursorShape shape);
 
+       bool needResize() const {
+               return need_resize_ || p->pixelRatio() != pixel_ratio_;
+       }
+
        void resetScreen()
        {
                delete screen_;
+               pixel_ratio_ = p->pixelRatio();
                if (lyxrc.use_qimage) {
-                       screen_ = new QImage(p->viewport()->width(), p->viewport()->height(),
-                               QImage::Format_ARGB32_Premultiplied);
+                       QImage *x = new QImage(pixel_ratio_ * p->viewport()->width(),
+                               pixel_ratio_ * p->viewport()->height(), QImage::Format_ARGB32_Premultiplied);
+#if QT_VERSION > 0x050000
+                       x->setDevicePixelRatio(pixel_ratio_);
+#endif
+                       screen_ = x;
                } else {
-                       screen_ = new QPixmap(p->viewport()->width(), p->viewport()->height());
+                       QPixmap *x = new QPixmap(pixel_ratio_ * p->viewport()->width(),
+                               pixel_ratio_ * p->viewport()->height());
+#if QT_VERSION > 0x050000
+                       x->setDevicePixelRatio(pixel_ratio_);
+#endif
+                       screen_ = x;
                }
        }
        ///
@@ -155,7 +169,10 @@ struct GuiWorkArea::Private
        bool schedule_redraw_;
        ///
        int preedit_lines_;
-
+       /// Ratio between physical pixels and device-independent pixels
+       /// We save the last used value to detect changes of the
+       /// current pixel_ratio of the viewport.
+       double pixel_ratio_;
        ///
        GuiCompleter * completer_;