commit 9135dcee0743538db730cd05b3daff029d50119f
Author: Stephan Witt <[email protected]>
Date: Sun Oct 12 19:23:13 2014 +0200
#9130 Text in main work area isn't rendered with high resolution
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.
diff --git a/src/frontends/Painter.h b/src/frontends/Painter.h
index 78ec6e5..221da4a 100644
--- a/src/frontends/Painter.h
+++ b/src/frontends/Painter.h
@@ -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
diff --git a/src/frontends/qt4/GuiApplication.cpp
b/src/frontends/qt4/GuiApplication.cpp
index d09bcdb..2697abe 100644
--- a/src/frontends/qt4/GuiApplication.cpp
+++ b/src/frontends/qt4/GuiApplication.cpp
@@ -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;
diff --git a/src/frontends/qt4/GuiApplication.h
b/src/frontends/qt4/GuiApplication.h
index 5e4cda2..410ccc4 100644
--- a/src/frontends/qt4/GuiApplication.h
+++ b/src/frontends/qt4/GuiApplication.h
@@ -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();
diff --git a/src/frontends/qt4/GuiPainter.cpp b/src/frontends/qt4/GuiPainter.cpp
index c7d56c8..986ac46 100644
--- a/src/frontends/qt4/GuiPainter.cpp
+++ b/src/frontends/qt4/GuiPainter.cpp
@@ -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);
diff --git a/src/frontends/qt4/GuiPainter.h b/src/frontends/qt4/GuiPainter.h
index 3af5175..e9c6fdf 100644
--- a/src/frontends/qt4/GuiPainter.h
+++ b/src/frontends/qt4/GuiPainter.h
@@ -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
diff --git a/src/frontends/qt4/GuiView.cpp b/src/frontends/qt4/GuiView.cpp
index cba88ee..8c50807 100644
--- a/src/frontends/qt4/GuiView.cpp
+++ b/src/frontends/qt4/GuiView.cpp
@@ -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())
diff --git a/src/frontends/qt4/GuiView.h b/src/frontends/qt4/GuiView.h
index 9b7ee2e..b10548d 100644
--- a/src/frontends/qt4/GuiView.h
+++ b/src/frontends/qt4/GuiView.h
@@ -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);
diff --git a/src/frontends/qt4/GuiWorkArea.cpp
b/src/frontends/qt4/GuiWorkArea.cpp
index e5b2cf5..fbc2eca 100644
--- a/src/frontends/qt4/GuiWorkArea.cpp
+++ b/src/frontends/qt4/GuiWorkArea.cpp
@@ -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();
diff --git a/src/frontends/qt4/GuiWorkArea.h b/src/frontends/qt4/GuiWorkArea.h
index e5c488f..fb6341b 100644
--- a/src/frontends/qt4/GuiWorkArea.h
+++ b/src/frontends/qt4/GuiWorkArea.h
@@ -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();
diff --git a/src/frontends/qt4/GuiWorkArea_Private.h
b/src/frontends/qt4/GuiWorkArea_Private.h
index 6d180dd..0915b64 100644
--- a/src/frontends/qt4/GuiWorkArea_Private.h
+++ b/src/frontends/qt4/GuiWorkArea_Private.h
@@ -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_;