Improved logical and physical DPI APIs.

Made physicalSize() return QSizeF instead, to prevent rounding errors.
Added logicalSize() as the base to compute font pixel sizes instead, and
added convenience functions in QScreen to access the logical and
physical sizes and DPI metrics.

Task-number: QTBUG-21736
Task-number: QTBUG-21737
Change-Id: Ic705dc98eb3632617659e65a0c9a552673dc0c65
Reviewed-on: http://codereview.qt-project.org/5888
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@nokia.com>
This commit is contained in:
Samuel Rødal 2011-09-30 14:25:43 +02:00 committed by Qt by Nokia
parent 29948e6665
commit 7d2cfbe5aa
24 changed files with 165 additions and 59 deletions

View File

@ -127,20 +127,41 @@ QScreen *QPlatformScreen::screen() const
/*!
Reimplement this function in subclass to return the physical size of the
screen. This function is used by QFont to convert point sizes to pixel
sizes.
screen. The physical size represents the actual physical dimensions of
the display.
The default implementation takes the pixel size of the screen, considers a
resolution of 100 dots per inch, and returns the calculated physical size.
A device with a screen that has different resolutions will need to be
supported by a suitable reimplementation of this function.
\sa logcalDpi
*/
QSize QPlatformScreen::physicalSize() const
QSizeF QPlatformScreen::physicalSize() const
{
static const int dpi = 100;
int width = geometry().width() / dpi * qreal(25.4) ;
int height = geometry().height() / dpi * qreal(25.4) ;
return QSize(width,height);
return QSizeF(geometry().size()) / dpi * qreal(25.4);
}
/*!
Reimplement this function in subclass to return the logical horizontal
and vertical dots per inch metrics of the screen.
The logical dots per inch metrics are used by QFont to convert point sizes
to pixel sizes.
The default implementation uses the screen pixel size and physical size to
compute the metrics.
\sa physicalSize
*/
QDpi QPlatformScreen::logicalDpi() const
{
QSizeF ps = physicalSize();
QSize s = geometry().size();
return QDpi(25.4 * s.width() / ps.width(),
25.4 * s.height() / ps.height());
}
QPlatformScreen * QPlatformScreen::platformScreenForWindow(const QWindow *window)

View File

@ -67,6 +67,8 @@ class QPlatformWindow;
class QScreen;
class QSurfaceFormat;
typedef QPair<qreal, qreal> QDpi;
class Q_GUI_EXPORT QPlatformScreenPageFlipper : public QObject
{
Q_OBJECT
@ -93,7 +95,9 @@ public:
virtual int depth() const = 0;
virtual QImage::Format format() const = 0;
virtual QSize physicalSize() const;
virtual QSizeF physicalSize() const;
virtual QDpi logicalDpi() const;
virtual QWindow *topLevelAt(const QPoint &point) const;
virtual QList<QPlatformScreen *> virtualSiblings() const;

View File

@ -101,6 +101,75 @@ QSize QScreen::size() const
return d->platformScreen->geometry().size();
}
/*!
Gets the number of physical dots or pixels per inch in the horizontal direction.
This value represents the actual horizontal pixel density on the screen's display.
Depending on what information the underlying system provides the value might not be
entirely accurate.
\sa physicalDotsPerInchY()
*/
qreal QScreen::physicalDotsPerInchX() const
{
return size().width() / physicalSize().width() * 25.4;
}
/*!
Gets the number of physical dots or pixels per inch in the vertical direction.
This value represents the actual vertical pixel density on the screen's display.
Depending on what information the underlying system provides the value might not be
entirely accurate.
\sa physicalDotsPerInchX()
*/
qreal QScreen::physicalDotsPerInchY() const
{
return size().height() / physicalSize().height() * 25.4;
}
/*!
Gets the number of logical dots or pixels per inch in the horizontal direction.
This value is used to convert font point sizes to pixel sizes.
\sa logicalDotsPerInchY()
*/
qreal QScreen::logicalDotsPerInchX() const
{
Q_D(const QScreen);
return d->platformScreen->logicalDpi().first;
}
/*!
Gets the number of logical dots or pixels per inch in the vertical direction.
This value is used to convert font point sizes to pixel sizes.
\sa logicalDotsPerInchX()
*/
qreal QScreen::logicalDotsPerInchY() const
{
Q_D(const QScreen);
return d->platformScreen->logicalDpi().second;
}
/*!
Get the screen's physical size (in millimeters).
The physical size represents the actual physical dimensions of the
screen's display.
Depending on what information the underlying system provides the value
might not be entirely accurate.
*/
QSizeF QScreen::physicalSize() const
{
Q_D(const QScreen);
return d->platformScreen->physicalSize();
}
/*!
Get the screen's available size.

View File

@ -44,6 +44,9 @@
#include <QtCore/QList>
#include <QtCore/QObject>
#include <QtCore/QRect>
#include <QtCore/QSize>
#include <QtCore/QSizeF>
QT_BEGIN_HEADER
@ -54,7 +57,6 @@ QT_MODULE(Gui)
class QPlatformScreen;
class QScreenPrivate;
class QWindow;
class QSize;
class QRect;
class Q_GUI_EXPORT QScreen : public QObject
@ -72,6 +74,14 @@ public:
QSize size() const;
QRect geometry() const;
QSizeF physicalSize() const;
qreal physicalDotsPerInchX() const;
qreal physicalDotsPerInchY() const;
qreal logicalDotsPerInchX() const;
qreal logicalDotsPerInchY() const;
QSize availableSize() const;
QRect availableGeometry() const;

View File

@ -170,9 +170,7 @@ Q_GUI_EXPORT int qt_defaultDpiX()
#elif defined(Q_WS_QPA)
QScreen *screen = QGuiApplication::primaryScreen();
if (screen) {
const QSize screenSize = screen->geometry().size();
const QSize physicalSize = screen->handle()->physicalSize();
dpi = qRound(screenSize.width() / (physicalSize.width() / qreal(25.4)));
dpi = qRound(screen->logicalDotsPerInchX());
} else {
//PI has not been initialised, or it is being initialised. Give a default dpi
dpi = 100;
@ -200,9 +198,7 @@ Q_GUI_EXPORT int qt_defaultDpiY()
#elif defined(Q_WS_QPA)
QScreen *screen = QGuiApplication::primaryScreen();
if (screen) {
const QSize screenSize = screen->geometry().size();
const QSize physicalSize = screen->handle()->physicalSize();
dpi = qRound(screenSize.height() / (physicalSize.height() / qreal(25.4)));
dpi = qRound(screen->logicalDotsPerInchY());
} else {
//PI has not been initialised, or it is being initialised. Give a default dpi
dpi = 100;

View File

@ -59,14 +59,14 @@ public:
QRect geometry() const { return m_geometry; }
int depth() const { return m_depth; }
QImage::Format format() const { return m_format; }
QSize physicalSize() const { return m_physicalSize; }
QSizeF physicalSize() const { return m_physicalSize; }
public:
NSScreen *m_screen;
QRect m_geometry;
int m_depth;
QImage::Format m_format;
QSize m_physicalSize;
QSizeF m_physicalSize;
};
class QCocoaIntegration : public QPlatformIntegration

View File

@ -70,7 +70,7 @@ QCocoaScreen::QCocoaScreen(int screenIndex)
const int dpi = 72;
const qreal inch = 25.4;
m_physicalSize = QSize(qRound(m_geometry.width() * inch / dpi), qRound(m_geometry.height() *inch / dpi));
m_physicalSize = QSizeF(m_geometry.size()) * inch / dpi;
}
QCocoaScreen::~QCocoaScreen()

View File

@ -73,7 +73,7 @@ QDirectFbScreen::QDirectFbScreen(int display)
const int dpi = 72;
const qreal inch = 25.4;
m_depth = QDirectFbConvenience::colorDepthForSurface(config.pixelformat);
m_physicalSize = QSize(qRound(config.width * inch / dpi), qRound(config.height *inch / dpi));
m_physicalSize = QSizeF(config.width, config.height) * inch / dpi;
m_cursor = new QDirectFBCursor(this);
}

View File

@ -63,13 +63,13 @@ public:
QRect geometry() const { return m_geometry; }
int depth() const { return m_depth; }
QImage::Format format() const { return m_format; }
QSize physicalSize() const { return m_physicalSize; }
QSizeF physicalSize() const { return m_physicalSize; }
public:
QRect m_geometry;
int m_depth;
QImage::Format m_format;
QSize m_physicalSize;
QSizeF m_physicalSize;
IDirectFBDisplayLayer *m_layer;

View File

@ -91,7 +91,7 @@ QImage::Format QKmsScreen::format() const
return m_format;
}
QSize QKmsScreen::physicalSize() const
QSizeF QKmsScreen::physicalSize() const
{
return m_physicalSize;
}
@ -132,7 +132,7 @@ void QKmsScreen::initializeScreenMode()
m_geometry = QRect(0, 0, m_mode.hdisplay, m_mode.vdisplay);
m_depth = 32;
m_format = QImage::Format_RGB32;
m_physicalSize = QSize(connector->mmWidth, connector->mmHeight);
m_physicalSize = QSizeF(connector->mmWidth, connector->mmHeight);
//Setup three buffers for current mode
m_bufferManager.setupBuffersForMode(m_mode, 3);

View File

@ -60,7 +60,7 @@ public:
QRect geometry() const;
int depth() const;
QImage::Format format() const;
QSize physicalSize() const;
QSizeF physicalSize() const;
GLuint framebufferObject() const;
quint32 crtcId() const { return m_crtcId; }
@ -83,7 +83,7 @@ private:
quint32 m_crtcId;
drmModeModeInfo m_mode;
QRect m_geometry;
QSize m_physicalSize;
QSizeF m_physicalSize;
int m_depth;
QImage::Format m_format;

View File

@ -112,9 +112,9 @@ QImage::Format QOpenWFDScreen::format() const
return QImage::Format_RGB32;
}
QSize QOpenWFDScreen::physicalSize() const
QSizeF QOpenWFDScreen::physicalSize() const
{
return mPort->physicalSize().toSize();
return mPort->physicalSize();
}
QOpenWFDPort * QOpenWFDScreen::port() const

View File

@ -64,7 +64,7 @@ public:
QRect geometry() const;
int depth() const;
QImage::Format format() const;
QSize physicalSize() const;
QSizeF physicalSize() const;
QOpenWFDPort *port() const;

View File

@ -392,8 +392,8 @@ QImage::Format QVFbScreen::format() const
return d_ptr->format();
}
QSize QVFbScreen::physicalSize() const {
return (d_ptr->screenSize()*254)/720;
QSizeF QVFbScreen::physicalSize() const {
return (QSizeF(d_ptr->screenSize())*254)/720.;
}
#if 0

View File

@ -60,7 +60,7 @@ public:
QRect geometry() const;
int depth() const;
QImage::Format format() const;
QSize physicalSize() const;
QSizeF physicalSize() const;
QImage *screenImage();

View File

@ -57,7 +57,7 @@ public:
QRect geometry() const { return m_geometry; }
int depth() const { return m_depth; }
QImage::Format format() const { return m_format; }
QSize physicalSize() const { return m_physicalSize; }
QSizeF physicalSize() const { return m_physicalSize; }
UIScreen *uiScreen() const;
@ -65,7 +65,7 @@ private:
QRect m_geometry;
int m_depth;
QImage::Format m_format;
QSize m_physicalSize;
QSizeF m_physicalSize;
int m_index;
};

View File

@ -67,7 +67,7 @@ QUIKitScreen::QUIKitScreen(int screenIndex)
dpi = 132.;
dragDistance = 10;
}
m_physicalSize = QSize(qRound(bounds.size.width * inch / dpi), qRound(bounds.size.height * inch / dpi));
m_physicalSize = QSizeF(bounds.size.width, bounds.size.height) * inch / dpi;
qApp->setStartDragDistance(dragDistance);
[pool release];
}

View File

@ -55,8 +55,6 @@
QT_BEGIN_NAMESPACE
typedef QPair<int, int> DPI;
QWindowsScreenData::QWindowsScreenData() :
dpi(96, 96),
depth(32),
@ -64,25 +62,25 @@ QWindowsScreenData::QWindowsScreenData() :
{
}
static inline DPI deviceDPI(HDC hdc)
static inline QDpi deviceDPI(HDC hdc)
{
return DPI(GetDeviceCaps(hdc, LOGPIXELSX), GetDeviceCaps(hdc, LOGPIXELSY));
return QDpi(GetDeviceCaps(hdc, LOGPIXELSX), GetDeviceCaps(hdc, LOGPIXELSY));
}
static inline QSize deviceSizeMM(const QSize &pixels, const DPI &dpi)
static inline QSizeF deviceSizeMM(const QSize &pixels, const QDpi &dpi)
{
const qreal inchToMM = 25.4;
const qreal h = qreal(pixels.width()) / qreal(dpi.first) * inchToMM;
const qreal v = qreal(pixels.height()) / qreal(dpi.second) * inchToMM;
return QSize(qRound(h), qRound(v));
return QSizeF(h, v);
}
static inline DPI deviceDPI(const QSize &pixels, const QSize &physicalSizeMM)
static inline QDpi deviceDPI(const QSize &pixels, const QSizeF &physicalSizeMM)
{
const qreal inchToMM = 25.4;
const qreal h = qreal(pixels.width()) / (qreal(physicalSizeMM.width()) / inchToMM);
const qreal v = qreal(pixels.height()) / (qreal(physicalSizeMM.height()) / inchToMM);
return DPI(qRound(v), qRound(h));
return QDpi(h, v);
}
typedef QList<QWindowsScreenData> WindowsScreenDataList;
@ -101,13 +99,13 @@ BOOL QT_WIN_CALLBACK monitorEnumCallback(HMONITOR hMonitor, HDC, LPRECT, LPARAM
data.geometry = QRect(QPoint(info.rcMonitor.left, info.rcMonitor.top), QPoint(info.rcMonitor.right - 1, info.rcMonitor.bottom - 1));
if (HDC hdc = CreateDC(info.szDevice, NULL, NULL, NULL)) {
data.dpi = deviceDPI(hdc);
data.physicalSizeMM = QSizeF(GetDeviceCaps(hdc, HORZSIZE), GetDeviceCaps(hdc, VERTSIZE));
DeleteDC(hdc);
} else {
qWarning("%s: Unable to obtain handle for monitor '%s', defaulting to %d DPI.",
__FUNCTION__, qPrintable(QString::fromWCharArray(info.szDevice)),
data.dpi.first);
}
data.physicalSizeMM = deviceSizeMM(data.geometry.size(), data.dpi);
data.geometry = QRect(QPoint(info.rcMonitor.left, info.rcMonitor.top), QPoint(info.rcMonitor.right - 1, info.rcMonitor.bottom - 1));
data.availableGeometry = QRect(QPoint(info.rcWork.left, info.rcWork.top), QPoint(info.rcWork.right - 1, info.rcWork.bottom - 1));
data.primary = (info.dwFlags & MONITORINFOF_PRIMARY) != 0;

View File

@ -56,8 +56,8 @@ struct QWindowsScreenData
QRect geometry;
QRect availableGeometry;
QPair<int, int> dpi;
QSize physicalSizeMM;
QDpi dpi;
QSizeF physicalSizeMM;
int depth;
QImage::Format format;
bool primary;
@ -74,7 +74,8 @@ public:
virtual QRect availableGeometry() const { return m_data.availableGeometry; }
virtual int depth() const { return m_data.depth; }
virtual QImage::Format format() const { return m_data.format; }
virtual QSize physicalSize() const { return m_data.physicalSizeMM; }
virtual QSizeF physicalSize() const { return m_data.physicalSizeMM; }
virtual QDpi logicalDpi() const { return m_data.dpi; }
virtual QWindow *topLevelAt(const QPoint &point) const
{ return QWindowsScreen::findTopLevelAt(point, CWP_SKIPINVISIBLE); }

View File

@ -222,9 +222,9 @@ QImage::Format QXcbScreen::format() const
return QImage::Format_RGB32;
}
QSize QXcbScreen::physicalSize() const
QSizeF QXcbScreen::physicalSize() const
{
return QSize(m_screen->width_in_millimeters, m_screen->height_in_millimeters);
return QSizeF(m_screen->width_in_millimeters, m_screen->height_in_millimeters);
}
int QXcbScreen::screenNumber() const

View File

@ -67,7 +67,7 @@ public:
QRect geometry() const;
int depth() const;
QImage::Format format() const;
QSize physicalSize() const;
QSizeF physicalSize() const;
int screenNumber() const;

View File

@ -218,7 +218,7 @@ QXlibScreen::QXlibScreen()
int physicalWidth = DisplayWidthMM(mDisplay->nativeDisplay(), mScreen);
int physicalHeight = DisplayHeightMM(mDisplay->nativeDisplay(), mScreen);
mPhysicalSize = QSize(physicalWidth,physicalHeight);
mPhysicalSize = QSizeF(physicalWidth, physicalHeight);
int xSocketNumber = XConnectionNumber(mDisplay->nativeDisplay());

View File

@ -62,7 +62,7 @@ public:
QRect geometry() const { return mGeometry; }
int depth() const { return mDepth; }
QImage::Format format() const { return mFormat; }
QSize physicalSize() const { return mPhysicalSize; }
QSizeF physicalSize() const { return mPhysicalSize; }
Window rootWindow();
unsigned long blackPixel();
@ -94,7 +94,7 @@ private:
void handleSelectionRequest(XEvent *event);
QRect mGeometry;
QSize mPhysicalSize;
QSizeF mPhysicalSize;
int mDepth;
QImage::Format mFormat;
QXlibCursor *mCursor;

View File

@ -739,12 +739,15 @@ int QWidget::metric(PaintDeviceMetric m) const
{
Q_D(const QWidget);
QPlatformScreen *screen = 0;
QScreen *screen = 0;
if (QWidget *topLevel = window())
if (QWindow *topLevelWindow = topLevel->windowHandle())
screen = QPlatformScreen::platformScreenForWindow(topLevelWindow);
if (QWindow *topLevelWindow = topLevel->windowHandle()) {
QPlatformScreen *platformScreen = QPlatformScreen::platformScreenForWindow(topLevelWindow);
if (platformScreen)
screen = platformScreen->screen();
}
if (!screen && QGuiApplication::primaryScreen())
screen = QGuiApplication::primaryScreen()->handle();
screen = QGuiApplication::primaryScreen();
if (!screen) {
if (m == PdmDpiX || m == PdmDpiY)
@ -762,18 +765,22 @@ int QWidget::metric(PaintDeviceMetric m) const
val = data->crect.height() * screen->physicalSize().height() / screen->geometry().height();
} else if (m == PdmDepth) {
return screen->depth();
} else if (m == PdmDpiX || m == PdmPhysicalDpiX) {
} else if (m == PdmDpiX) {
if (d->extra && d->extra->customDpiX)
return d->extra->customDpiX;
else if (d->parent)
return static_cast<QWidget *>(d->parent)->metric(m);
return qRound(screen->geometry().width() / double(screen->physicalSize().width() / 25.4));
} else if (m == PdmDpiY || m == PdmPhysicalDpiY) {
return qRound(screen->logicalDotsPerInchX());
} else if (m == PdmDpiY) {
if (d->extra && d->extra->customDpiY)
return d->extra->customDpiY;
else if (d->parent)
return static_cast<QWidget *>(d->parent)->metric(m);
return qRound(screen->geometry().height() / double(screen->physicalSize().height() / 25.4));
return qRound(screen->logicalDotsPerInchY());
} else if (m == PdmPhysicalDpiX) {
return qRound(screen->physicalDotsPerInchX());
} else if (m == PdmPhysicalDpiY) {
return qRound(screen->physicalDotsPerInchY());
} else {
val = QPaintDevice::metric(m);// XXX
}