Add devicePixelRatio metric to QPaintDevice.

Previously QPainter computed the devicePixelRatio
based on the physical and logical dpi, and expected
that the ratio between them would be either 1x or
2x.

This was problematic for paint devices like printers
where the physical dpi can be much higher than the
logical dpi, and also for QScreen where the physical
dpi would have to be defined as a multiple of the
logical dpi.

Add QPaintDevice::PdmDevicePixelRatio and QPaintDevice::
devicePixelRatio() getter and implement it for the
QPaintDevice subclasses. Use it when calculating the
highdpi scale transform in qpainter.cpp and when scaling
the clip rect in qwidget.cpp.

Remove physical dpi scaling for QImage, QPixmap and
QOpenGLPaintDevice, reverting to the old behavior.

Change-Id: I6c97510613196d4536ff39d08e9750b8782283d4
Reviewed-by: Samuel Rødal <samuel.rodal@digia.com>
Reviewed-by: Gunnar Sletta <gunnar.sletta@digia.com>
This commit is contained in:
Morten Johan Sørvig 2013-01-24 09:26:45 +01:00 committed by The Qt Project
parent 1f3a67e870
commit cea58f4b77
17 changed files with 73 additions and 26 deletions

View File

@ -4994,12 +4994,17 @@ int QImage::metric(PaintDeviceMetric metric) const
break;
case PdmPhysicalDpiX:
return qRound(d->dpmx * 0.0254 * d->devicePixelRatio);
return qRound(d->dpmx * 0.0254);
break;
case PdmPhysicalDpiY:
return qRound(d->dpmy * 0.0254 * d->devicePixelRatio);
return qRound(d->dpmy * 0.0254);
break;
case PdmDevicePixelRatio:
return d->devicePixelRatio;
break;
default:
qWarning("QImage::metric(): Unhandled metric type %d", metric);
break;

View File

@ -956,6 +956,9 @@ int QPicture::metric(PaintDeviceMetric m) const
case PdmDepth:
val = 24;
break;
case PdmDevicePixelRatio:
val = 1;
break;
default:
val = 0;
qWarning("QPicture::metric: Invalid metric command");

View File

@ -120,6 +120,8 @@ int QBlittablePlatformPixmap::metric(QPaintDevice::PaintDeviceMetric metric) con
case QPaintDevice::PdmDpiY: // fall-through
case QPaintDevice::PdmPhysicalDpiY:
return qt_defaultDpiY();
case QPaintDevice::PdmDevicePixelRatio:
return 1;
default:
qWarning("QRasterPlatformPixmap::metric(): Unhandled metric type %d", metric);
break;

View File

@ -278,11 +278,13 @@ int QRasterPlatformPixmap::metric(QPaintDevice::PaintDeviceMetric metric) const
case QPaintDevice::PdmDpiX:
return qt_defaultDpiX();
case QPaintDevice::PdmPhysicalDpiX:
return qt_defaultDpiX() * image.devicePixelRatio();
return qt_defaultDpiX();
case QPaintDevice::PdmDpiY:
return qt_defaultDpiX();
case QPaintDevice::PdmPhysicalDpiY:
return qt_defaultDpiY() * image.devicePixelRatio();
return qt_defaultDpiY();
case QPaintDevice::PdmDevicePixelRatio:
return image.devicePixelRatio();
default:
qWarning("QRasterPlatformPixmap::metric(): Unhandled metric type %d", metric);
break;

View File

@ -282,9 +282,11 @@ int QOpenGLPaintDevice::metric(QPaintDevice::PaintDeviceMetric metric) const
case PdmDpiY:
return qRound(d_ptr->dpmy * 0.0254);
case PdmPhysicalDpiX:
return qRound(d_ptr->dpmx * 0.0254 * d_ptr->devicePixelRatio);
return qRound(d_ptr->dpmx * 0.0254);
case PdmPhysicalDpiY:
return qRound(d_ptr->dpmy * 0.0254 * d_ptr->devicePixelRatio);
return qRound(d_ptr->dpmy * 0.0254);
case PdmDevicePixelRatio:
return 1;
default:
qWarning("QOpenGLPaintDevice::metric() - metric %d not known", metric);
return 0;

View File

@ -95,6 +95,8 @@ int QPaintDevice::metric(PaintDeviceMetric m) const
} else if (m == PdmNumColors) {
// FIXME: does this need to be a real value?
return 256;
} else if (m == PdmDevicePixelRatio) {
return 1;
} else {
qDebug("Unrecognised metric %d!",m);
return 0;

View File

@ -65,7 +65,8 @@ public:
PdmDpiX,
PdmDpiY,
PdmPhysicalDpiX,
PdmPhysicalDpiY
PdmPhysicalDpiY,
PdmDevicePixelRatio
};
virtual ~QPaintDevice();
@ -82,6 +83,7 @@ public:
int logicalDpiY() const { return metric(PdmDpiY); }
int physicalDpiX() const { return metric(PdmPhysicalDpiX); }
int physicalDpiY() const { return metric(PdmPhysicalDpiY); }
int devicePixelRatio() const { return metric(PdmDevicePixelRatio); }
int colorCount() const { return metric(PdmNumColors); }
int depth() const { return metric(PdmDepth); }

View File

@ -114,6 +114,10 @@
\value PdmPhysicalDpiY The vertical resolution of the device in
dots per inch. See also physicalDpiY().
\value PdmDevicePixelRatio The device pixel ratio for device. Common
values are 1 for normal-dpi displays and 2 for high-dpi "retina"
displays.
\sa metric()
*/
@ -273,3 +277,12 @@
\sa physicalDpiX(), logicalDpiY()
*/
/*!
\fn int QPaintDevice::devicePixelRatio() const
Returns the device pixel ratio for device.
Common values are 1 for normal-dpi displays and 2 for high-dpi
"retina" displays.
*/

View File

@ -225,17 +225,24 @@ QTransform QPainterPrivate::viewTransform() const
return QTransform();
}
int QPainterPrivate::effectiveDevicePixelRatio() const
{
// Limited feature introduction for Qt 5.0.0, remove ifdef in a later release.
#ifdef Q_OS_MAC
// Special cases for devices that does not support PdmDevicePixelRatio go here:
if (device->devType() == QInternal::Printer)
return 1;
return qMax(1, device->metric(QPaintDevice::PdmDevicePixelRatio));
#else
return 1;
#endif
}
QTransform QPainterPrivate::hidpiScaleTransform() const
{
#ifdef Q_OS_MAC
// Limited feature introduction for Qt 5.0.0, remove ifdef in a later release.
if (device->devType() == QInternal::Printer || device->physicalDpiX() == 0 || device->logicalDpiX() == 0)
return QTransform();
const qreal deviceScale = (device->physicalDpiX() / device->logicalDpiX());
if (deviceScale > 1.0)
return QTransform::fromScale(deviceScale, deviceScale);
#endif
return QTransform();
int devicePixelRatio = effectiveDevicePixelRatio();
return QTransform::fromScale(devicePixelRatio, devicePixelRatio);
}
/*
@ -1837,14 +1844,7 @@ bool QPainter::begin(QPaintDevice *pd)
Q_ASSERT(d->engine->isActive());
#ifdef Q_OS_MAC
// Limited feature introduction for Qt 5.0.0, remove ifdef in a later release.
const bool isHighDpi = (pd->devType() == QInternal::Printer || d->device->physicalDpiX() == 0 || d->device->logicalDpiX() == 0) ?
false : (d->device->physicalDpiX() / d->device->logicalDpiX() > 1);
#else
const bool isHighDpi = false;
#endif
if (!d->state->redirectionMatrix.isIdentity() || isHighDpi)
if (!d->state->redirectionMatrix.isIdentity() || d->effectiveDevicePixelRatio() > 1)
d->updateMatrix();
Q_ASSERT(d->engine->isActive());

View File

@ -249,6 +249,7 @@ public:
}
QTransform viewTransform() const;
int effectiveDevicePixelRatio() const;
QTransform hidpiScaleTransform() const;
static bool attachPainterPrivate(QPainter *q, QPaintDevice *pdev);
void detachPainterPrivate(QPainter *q);

View File

@ -1455,6 +1455,9 @@ int QPdfEngine::metric(QPaintDevice::PaintDeviceMetric metricType) const
case QPaintDevice::PdmDepth:
val = 32;
break;
case QPaintDevice::PdmDevicePixelRatio:
val = 1;
break;
default:
qWarning("QPdfWriter::metric: Invalid metric command");
return 0;

View File

@ -1232,6 +1232,9 @@ int QGLFramebufferObject::metric(PaintDeviceMetric metric) const
case PdmPhysicalDpiY:
return qRound(dpmy * 0.0254);
case QPaintDevice::PdmDevicePixelRatio:
return 1;
default:
qWarning("QGLFramebufferObject::metric(), Unhandled metric type: %d.\n", metric);
break;

View File

@ -67,6 +67,8 @@ int QGLPaintDevice::metric(QPaintDevice::PaintDeviceMetric metric) const
const QGLFormat f = format();
return f.redBufferSize() + f.greenBufferSize() + f.blueBufferSize() + f.alphaBufferSize();
}
case PdmDevicePixelRatio:
return 1;
default:
qWarning("QGLPaintDevice::metric() - metric %d not known", metric);
return 0;

View File

@ -462,6 +462,9 @@ int QGLPixelBuffer::metric(PaintDeviceMetric metric) const
case PdmPhysicalDpiY:
return qRound(dpmy * 0.0254);
case QPaintDevice::PdmDevicePixelRatio:
return 1;
default:
qWarning("QGLPixelBuffer::metric(), Unhandled metric type: %d\n", metric);
break;

View File

@ -364,6 +364,9 @@ int QMacPrintEngine::metric(QPaintDevice::PaintDeviceMetric m) const
case QPaintDevice::PdmDepth:
val = 24;
break;
case QPaintDevice::PdmDevicePixelRatio:
val = 1;
break;
default:
val = 0;
qWarning("QPrinter::metric: Invalid metric command");

View File

@ -1811,9 +1811,8 @@ void QWidgetPrivate::setSystemClip(QPaintDevice *paintDevice, const QRegion &reg
// it has been tested.
QPaintEngine *paintEngine = paintDevice->paintEngine();
#ifdef Q_OS_MAC
const qreal devicePixelRatio = (paintDevice->physicalDpiX() == 0 || paintDevice->logicalDpiX() == 0) ?
1.0 : (paintDevice->physicalDpiX() / paintDevice->logicalDpiX());
QTransform scaleTransform;
const qreal devicePixelRatio = paintDevice->devicePixelRatio();
scaleTransform.scale(devicePixelRatio, devicePixelRatio);
paintEngine->d_func()->systemClip = scaleTransform.map(region);
#else

View File

@ -836,6 +836,8 @@ int QWidget::metric(PaintDeviceMetric m) const
return qRound(screen->physicalDotsPerInchX());
} else if (m == PdmPhysicalDpiY) {
return qRound(screen->physicalDotsPerInchY());
} else if (m == PdmDevicePixelRatio) {
return screen->devicePixelRatio();
} else {
val = QPaintDevice::metric(m);// XXX
}