Basic high-dpi "retina" support for Qt 5.

Bring Qt 5 on par with Qt 4, prepare for more comprehensive
support later on.

Introduce device independent pixels (dips), device pixels,
and devicePixelRatio. Add high-dpi support to QPainter,
QGLWidget, the cocoa platform plugin, mac and fusion styles.

Dips are similar to CSS pixels, Apple points and
Android density-independent pixels. Device pixels
are pixels in the backing store/physical pixels on screen.
devicePixelRatio is the ratio between them, which is
1.0 on standard displays and 2.0 on "retina" displays.

New API:
QImage::devicePixelRatio() and setDevicePixelRatio()
QPixmap::devicePixelRatio() and setDevicePixelRatio()
QWindow::devicePixelRatio()
QScreen::devicePixelRatio()
QGuiApplicaiton::devicePixelRatio()

Change-Id: If98c3ca9bfdf0e1bdbcf7574cd5b912c9ff63856
Reviewed-by: Morten Johan Sørvig <morten.sorvig@digia.com>
Reviewed-by: Gunnar Sletta <gunnar.sletta@digia.com>
This commit is contained in:
Morten Johan Sørvig 2012-11-20 11:34:52 +01:00 committed by The Qt Project
parent c8dc41bacd
commit 5e61bbe586
50 changed files with 934 additions and 119 deletions

View File

@ -95,10 +95,12 @@ static QImage rotated270(const QImage &src);
QBasicAtomicInt qimage_serial_number = Q_BASIC_ATOMIC_INITIALIZER(1);
QImageData::QImageData()
: ref(0), width(0), height(0), depth(0), nbytes(0), data(0),
: ref(0), width(0), height(0), depth(0), nbytes(0), devicePixelRatio(1.0), data(0),
format(QImage::Format_ARGB32), bytes_per_line(0),
ser_no(qimage_serial_number.fetchAndAddRelaxed(1)),
detach_no(0),
ldpmx(qt_defaultDpiX() * 100 / qreal(2.54)),
ldpmy(qt_defaultDpiY() * 100 / qreal(2.54)),
dpmx(qt_defaultDpiX() * 100 / qreal(2.54)),
dpmy(qt_defaultDpiY() * 100 / qreal(2.54)),
offset(0, 0), own_data(true), ro_data(false), has_alpha_clut(false),
@ -1216,6 +1218,7 @@ QImage QImage::copy(const QRect& r) const
image.d->dpmx = dotsPerMeterX();
image.d->dpmy = dotsPerMeterY();
image.d->devicePixelRatio = devicePixelRatio();
image.d->offset = offset();
image.d->has_alpha_clut = d->has_alpha_clut;
image.d->text = d->text;
@ -1369,6 +1372,52 @@ QVector<QRgb> QImage::colorTable() const
return d ? d->colortable : QVector<QRgb>();
}
/*!
Returns the device pixel ratio for the image. This is the
ratio between image pixels and device-independent pixels.
Use this function when calculating layout geometry based on
the image size: QSize layoutSize = image.size() / image.devicePixelRatio()
The default value is 1.0.
\sa setDevicePixelRatio()
*/
qreal QImage::devicePixelRatio() const
{
if (!d)
return 1.0;
return d->devicePixelRatio;
}
/*!
Sets the the device pixel ratio for the image. This is the
ratio between image pixels and device-independent pixels.
The default value is 1.0. Setting it to something else has
two effects:
QPainters that are opened on the image will be scaled. For
example, painting on a 200x200 image if with a ratio of 2.0
will result in effective (device-independent) painting bounds
of 100x100.
Code paths in Qt that calculate layout geometry based on the
image size will take the ratio into account:
QSize layoutSize = image.size() / image.devicePixelRatio()
The net effect of this is that the image is displayed as
high-dpi image rather than a large image.
\sa devicePixelRatio()
*/
void QImage::setDevicePixelRatio(qreal scaleFactor)
{
if (!d)
return;
detach();
d->devicePixelRatio = scaleFactor;
}
/*!
\since 4.6
Returns the number of bytes occupied by the image data.
@ -3359,6 +3408,7 @@ QImage QImage::convertToFormat(Format format, Qt::ImageConversionFlags flags) co
image.setDotsPerMeterY(dotsPerMeterY());
image.setDotsPerMeterX(dotsPerMeterX());
image.setDevicePixelRatio(devicePixelRatio());
image.d->text = d->text;
@ -3479,6 +3529,7 @@ QImage QImage::convertToFormat(Format format, const QVector<QRgb> &colorTable, Q
QImage image(d->width, d->height, format);
QIMAGE_SANITYCHECK_MEMORY(image);
image.setDevicePixelRatio(devicePixelRatio());
image.d->text = d->text;
@ -4932,17 +4983,20 @@ int QImage::metric(PaintDeviceMetric metric) const
return d->depth;
case PdmDpiX:
return qRound(d->dpmx * 0.0254);
return qRound(d->ldpmx * 0.0254);
break;
case PdmDpiY:
return qRound(d->dpmy * 0.0254);
return qRound(d->ldpmy * 0.0254);
break;
case PdmPhysicalDpiX:
return qRound(d->dpmx * 0.0254);
return qRound(d->dpmx * 0.0254 * d->devicePixelRatio);
break;
case PdmPhysicalDpiY:
return qRound(d->dpmy * 0.0254);
return qRound(d->dpmy * 0.0254 * d->devicePixelRatio);
break;
default:
qWarning("QImage::metric(): Unhandled metric type %d", metric);
break;
@ -5641,6 +5695,7 @@ QImage QImage::transformed(const QTransform &matrix, Qt::TransformationMode mode
dImage.d->dpmx = dotsPerMeterX();
dImage.d->dpmy = dotsPerMeterY();
dImage.d->devicePixelRatio = devicePixelRatio();
switch (bpp) {
// initizialize the data

View File

@ -211,6 +211,9 @@ public:
QVector<QRgb> colorTable() const;
void setColorTable(const QVector<QRgb> colors);
qreal devicePixelRatio() const;
void setDevicePixelRatio(qreal scaleFactor);
void fill(uint pixel);
void fill(const QColor &color);
void fill(Qt::GlobalColor color);

View File

@ -74,6 +74,7 @@ struct Q_GUI_EXPORT QImageData { // internal image data
int height;
int depth;
int nbytes; // number of bytes data
qreal devicePixelRatio;
QVector<QRgb> colortable;
uchar *data;
QImage::Format format;
@ -81,8 +82,10 @@ struct Q_GUI_EXPORT QImageData { // internal image data
int ser_no; // serial number
int detach_no;
qreal dpmx; // dots per meter X (or 0)
qreal dpmy; // dots per meter Y (or 0)
qreal ldpmx; // logical dots per meter X (or 0)
qreal ldpmy; // logical dots per meter Y (or 0)
qreal dpmx; // device dots per meter X (or 0)
qreal dpmy; // device dots per meter Y (or 0)
QPoint offset; // offset in pixels
uint own_data : 1;

View File

@ -1234,6 +1234,11 @@ bool QImageReader::read(QImage *image)
}
}
// successful read; check for "@2x" file name suffix and set device pixel ratio.
if (QFileInfo(fileName()).baseName().endsWith("@2x")) {
image->setDevicePixelRatio(2.0);
}
return true;
}

View File

@ -638,6 +638,50 @@ void QPixmap::setMask(const QBitmap &mask)
data->fromImage(image, Qt::AutoColor);
}
/*!
Returns the device pixel ratio for the pixmap. This is the
ratio between pixmap pixels and device-independent pixels.
Use this function when calculating layout geometry based on
the pixmap size: QSize layoutSize = image.size() / image.devicePixelRatio()
The default value is 1.0.
\sa setDevicePixelRatio()
*/
qreal QPixmap::devicePixelRatio() const
{
if (!data)
return qreal(1.0);
return data->devicePixelRatio();
}
/*!
Sets the the device pixel ratio for the pixmap. This is the
ratio between image pixels and device-independent pixels.
The default value is 1.0. Setting it to something else has
two effects:
QPainters that are opened on the pixmap will be scaled. For
example, painting on a 200x200 image if with a ratio of 2.0
will result in effective (device-independent) painting bounds
of 100x100.
Code paths in Qt that calculate layout geometry based on the
pixmap size will take the ratio into account:
QSize layoutSize = pixmap.size() / pixmap.devicePixelRatio()
The net effect of this is that the pixmap is displayed as
high-dpi pixmap rather than a large pixmap.
\sa devicePixelRatio()
*/
void QPixmap::setDevicePixelRatio(qreal scaleFactor)
{
detach();
data->setDevicePixelRatio(scaleFactor);
}
#ifndef QT_NO_IMAGE_HEURISTIC_MASK
/*!
Creates and returns a heuristic mask for this pixmap.

View File

@ -102,6 +102,9 @@ public:
QBitmap mask() const;
void setMask(const QBitmap &);
qreal devicePixelRatio() const;
void setDevicePixelRatio(qreal scaleFactor);
bool hasAlpha() const;
bool hasAlphaChannel() const;

View File

@ -195,6 +195,16 @@ void QBlittablePlatformPixmap::fromImage(const QImage &image,
}
}
qreal QBlittablePlatformPixmap::devicePixelRatio() const
{
return m_devicePixelRatio;
}
void QBlittablePlatformPixmap::setDevicePixelRatio(qreal scaleFactor)
{
m_devicePixelRatio = scaleFactor;
}
QPaintEngine *QBlittablePlatformPixmap::paintEngine() const
{
if (!m_engine) {

View File

@ -66,6 +66,8 @@ public:
QImage toImage() const;
bool hasAlphaChannel() const;
void fromImage(const QImage &image, Qt::ImageConversionFlags flags);
qreal devicePixelRatio() const;
void setDevicePixelRatio(qreal scaleFactor);
QPaintEngine *paintEngine() const;
@ -89,6 +91,7 @@ protected:
QScopedPointer<QBlitterPaintEngine> m_engine;
QScopedPointer<QBlittable> m_blittable;
bool m_alpha;
qreal m_devicePixelRatio;
#ifdef QT_BLITTER_RASTEROVERLAY
QImage *m_rasterOverlay;

View File

@ -272,12 +272,14 @@ int QRasterPlatformPixmap::metric(QPaintDevice::PaintDeviceMetric metric) const
return d->colortable.size();
case QPaintDevice::PdmDepth:
return this->d;
case QPaintDevice::PdmDpiX: // fall-through
case QPaintDevice::PdmPhysicalDpiX:
case QPaintDevice::PdmDpiX:
return qt_defaultDpiX();
case QPaintDevice::PdmPhysicalDpiX:
return qt_defaultDpiX() * image.devicePixelRatio();
case QPaintDevice::PdmDpiY:
return qt_defaultDpiX();
case QPaintDevice::PdmDpiY: // fall-through
case QPaintDevice::PdmPhysicalDpiY:
return qt_defaultDpiY();
return qt_defaultDpiY() * image.devicePixelRatio();
default:
qWarning("QRasterPlatformPixmap::metric(): Unhandled metric type %d", metric);
break;
@ -350,6 +352,7 @@ void QRasterPlatformPixmap::createPixmapForImage(QImage &sourceImage, Qt::ImageC
}
is_null = (w <= 0 || h <= 0);
image.d->devicePixelRatio = sourceImage.devicePixelRatio();
setSerialNumber(image.cacheKey() >> 32);
}
@ -358,4 +361,14 @@ QImage* QRasterPlatformPixmap::buffer()
return &image;
}
qreal QRasterPlatformPixmap::devicePixelRatio() const
{
return image.devicePixelRatio();
}
void QRasterPlatformPixmap::setDevicePixelRatio(qreal scaleFactor)
{
image.setDevicePixelRatio(scaleFactor);
}
QT_END_NAMESPACE

View File

@ -79,6 +79,9 @@ public:
QImage toImage(const QRect &rect) const;
QPaintEngine* paintEngine() const;
QImage* buffer();
qreal devicePixelRatio() const;
void setDevicePixelRatio(qreal scaleFactor);
protected:
int metric(QPaintDevice::PaintDeviceMetric metric) const;

View File

@ -108,6 +108,9 @@ public:
inline PixelType pixelType() const { return type; }
inline ClassId classId() const { return static_cast<ClassId>(id); }
virtual qreal devicePixelRatio() const = 0;
virtual void setDevicePixelRatio(qreal scaleFactor) = 0;
virtual QImage* buffer();
inline int width() const { return w; }

View File

@ -703,7 +703,34 @@ QList<QScreen *> QGuiApplication::screens()
/*!
Returns the top level window at the given position \a pos, if any.
Returns the highest screen device pixel ratio found on
the system. This is the ratio between physical pixels and
device-independent pixels.
Use this function only when you don't know which window you are targeting.
If you do know the target window use QWindow::devicePixelRatio() instead.
\sa QWindow::devicePixelRatio();
\sa QGuiApplicaiton::devicePixelRatio();
*/
qreal QGuiApplication::devicePixelRatio() const
{
// Cache topDevicePixelRatio, iterate through the screen list once only.
static qreal topDevicePixelRatio = 0.0;
if (!qFuzzyIsNull(topDevicePixelRatio)) {
return topDevicePixelRatio;
}
topDevicePixelRatio = 1.0; // make sure we never return 0.
foreach (QScreen *screen, QGuiApplicationPrivate::screen_list) {
topDevicePixelRatio = qMax(topDevicePixelRatio, screen->devicePixelRatio());
}
return topDevicePixelRatio;
}
/*!
Returns the top level window at the given position, if any.
*/
QWindow *QGuiApplication::topLevelAt(const QPoint &pos)
{

View File

@ -104,6 +104,7 @@ public:
static QScreen *primaryScreen();
static QList<QScreen *> screens();
qreal devicePixelRatio() const;
#ifndef QT_NO_CURSOR
static QCursor *overrideCursor();

View File

@ -160,6 +160,18 @@ QDpi QPlatformScreen::logicalDpi() const
25.4 * s.height() / ps.height());
}
/*!
Reimplement this function in subclass to return the device pixel
ratio for the screen. This is the ratio between physical pixels
and device-independent pixels.
\sa QPlatformWindow::devicePixelRatio();
*/
qreal QPlatformScreen::devicePixelRatio() const
{
return 1.0;
}
/*!
Reimplement this function in subclass to return the vertical refresh rate
of the screen, in Hz.

View File

@ -98,6 +98,7 @@ public:
virtual QSizeF physicalSize() const;
virtual QDpi logicalDpi() const;
virtual qreal devicePixelRatio() const;
virtual qreal refreshRate() const;

View File

@ -355,6 +355,18 @@ Qt::ScreenOrientation QPlatformWindow::requestWindowOrientation(Qt::ScreenOrient
return Qt::PrimaryOrientation;
}
/*!
Reimplement this function in subclass to return the device pixel ratio
for the window. This is the ratio between physical pixels
and device-independent pixels.
\sa QPlatformWindow::devicePixelRatio();
*/
qreal QPlatformWindow::devicePixelRatio() const
{
return 1.0;
}
bool QPlatformWindow::setKeyboardGrabEnabled(bool grab)
{
Q_UNUSED(grab);

View File

@ -117,6 +117,8 @@ public:
virtual void handleContentOrientationChange(Qt::ScreenOrientation orientation);
virtual Qt::ScreenOrientation requestWindowOrientation(Qt::ScreenOrientation orientation);
virtual qreal devicePixelRatio() const;
virtual bool setKeyboardGrabEnabled(bool grab);
virtual bool setMouseGrabEnabled(bool grab);

View File

@ -214,6 +214,20 @@ qreal QScreen::logicalDotsPerInch() const
return (dpi.first + dpi.second) * qreal(0.5);
}
/*
Returns the ratio between physical pixels and device-independent pixels for the screen.
Common values are 1.0 on normal displays and 2.0 on Apple retina displays.
\sa QWindow::devicePixelRatio();
\sa QGuiApplicaiton::devicePixelRatio();
*/
qreal QScreen::devicePixelRatio() const
{
Q_D(const QScreen);
return d->platformScreen->devicePixelRatio();
}
/*!
\property QScreen::physicalSize
\brief the screen's physical size (in millimeters)

View File

@ -109,6 +109,8 @@ public:
qreal logicalDotsPerInchY() const;
qreal logicalDotsPerInch() const;
qreal devicePixelRatio() const;
QSize availableSize() const;
QRect availableGeometry() const;

View File

@ -805,6 +805,24 @@ Qt::ScreenOrientation QWindow::orientation() const
return d->windowOrientation;
}
/*!
Returns the ratio between physical pixels and device-independent pixels
for the window. This value is dependent on the screen the window is on,
and may change when the window is moved.
Common values are 1.0 on normal displays and 2.0 on Apple "retina" displays.
\sa QWindow::devicePixelRatio();
\sa QGuiApplicaiton::devicePixelRatio();
*/
qreal QWindow::devicePixelRatio() const
{
Q_D(const QWindow);
if (!d->platformWindow)
return 1.0;
return d->platformWindow->devicePixelRatio();
}
/*!
\brief set the screen-occupation state of the window

View File

@ -184,6 +184,8 @@ public:
void reportContentOrientationChange(Qt::ScreenOrientation orientation);
Qt::ScreenOrientation contentOrientation() const;
qreal devicePixelRatio() const;
bool requestOrientation(Qt::ScreenOrientation orientation);
Qt::ScreenOrientation orientation() const;

View File

@ -1072,9 +1072,11 @@ void QRasterPaintEnginePrivate::systemStateChanged()
exDeviceRect = deviceRect;
Q_Q(QRasterPaintEngine);
q->state()->strokeFlags |= QPaintEngine::DirtyClipRegion;
q->state()->fillFlags |= QPaintEngine::DirtyClipRegion;
q->state()->pixmapFlags |= QPaintEngine::DirtyClipRegion;
if (q->state()) {
q->state()->strokeFlags |= QPaintEngine::DirtyClipRegion;
q->state()->fillFlags |= QPaintEngine::DirtyClipRegion;
q->state()->pixmapFlags |= QPaintEngine::DirtyClipRegion;
}
}
void QRasterPaintEnginePrivate::updateMatrixData(QSpanData *spanData, const QBrush &b, const QTransform &m)
@ -2143,9 +2145,10 @@ void QRasterPaintEngine::drawImage(const QPointF &p, const QImage &img)
Q_D(QRasterPaintEngine);
QRasterPaintEngineState *s = state();
qreal scale = img.devicePixelRatio();
if (s->matrix.type() > QTransform::TxTranslate) {
drawImage(QRectF(p.x(), p.y(), img.width(), img.height()),
if (scale > 1.0 || s->matrix.type() > QTransform::TxTranslate) {
drawImage(QRectF(p.x(), p.y(), img.width() / scale, img.height() / scale),
img,
QRectF(0, 0, img.width(), img.height()));
} else {
@ -2349,6 +2352,22 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe
return;
}
} else {
// Test for optimized high-dpi case: 2x source on 2x target. (Could be generalized to nX.)
bool sourceRect2x = r.width() * 2 == sr.width() && r.height() * 2 == sr.height();
bool scale2x = (s->matrix.m11() == qreal(2)) && (s->matrix.m22() == qreal(2));
if (s->matrix.type() == QTransform::TxScale && sourceRect2x && scale2x) {
SrcOverBlendFunc func = qBlendFunctions[d->rasterBuffer->format][img.format()];
if (func) {
QPointF pt(r.x() * 2 + s->matrix.dx(), r.y() * 2 + s->matrix.dy());
if (!clip) {
d->drawImage(pt, img, func, d->deviceRect, s->intOpacity, sr.toRect());
return;
} else if (clip->hasRectClip) {
d->drawImage(pt, img, func, clip->clipRect, s->intOpacity, sr.toRect());
return;
}
}
}
SrcOverScaleFunc func = qScaleFunctions[d->rasterBuffer->format][img.format()];
if (func && (!clip || clip->hasRectClip)) {
func(d->rasterBuffer->buffer(), d->rasterBuffer->bytesPerLine(),

View File

@ -939,12 +939,12 @@ void QPaintEngineEx::drawPolygon(const QPoint *points, int pointCount, PolygonDr
void QPaintEngineEx::drawPixmap(const QPointF &pos, const QPixmap &pm)
{
drawPixmap(QRectF(pos, pm.size()), pm, pm.rect());
drawPixmap(QRectF(pos, pm.size() / pm.devicePixelRatio()), pm, pm.rect());
}
void QPaintEngineEx::drawImage(const QPointF &pos, const QImage &image)
{
drawImage(QRectF(pos, image.size()), image, image.rect());
drawImage(QRectF(pos, image.size() / image.devicePixelRatio()), image, image.rect());
}
void QPaintEngineEx::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &s)

View File

@ -225,6 +225,18 @@ QTransform QPainterPrivate::viewTransform() const
return QTransform();
}
QTransform QPainterPrivate::hidpiScaleTransform() const
{
#ifdef Q_OS_MAC
// Limited feature introduction for Qt 5.0.0, remove ifdef in a later release.
if (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();
}
/*
\internal
@ -641,6 +653,8 @@ void QPainterPrivate::updateMatrix()
else
state->dirtyFlags |= QPaintEngine::DirtyTransform;
state->matrix *= hidpiScaleTransform();
// printf("VxF=%d, WxF=%d\n", state->VxF, state->WxF);
// qDebug() << " --- using matrix" << state->matrix << redirection_offset;
}
@ -1827,7 +1841,14 @@ bool QPainter::begin(QPaintDevice *pd)
Q_ASSERT(d->engine->isActive());
if (!d->state->redirectionMatrix.isIdentity())
#ifdef Q_OS_MAC
// Limited feature introduction for Qt 5.0.0, remove ifdef in a later release.
const bool isHighDpi = (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)
d->updateMatrix();
Q_ASSERT(d->engine->isActive());
@ -5092,7 +5113,8 @@ void QPainter::drawPixmap(const QPointF &p, const QPixmap &pm)
x += d->state->matrix.dx();
y += d->state->matrix.dy();
}
d->engine->drawPixmap(QRectF(x, y, w, h), pm, QRectF(0, 0, w, h));
int scale = pm.devicePixelRatio();
d->engine->drawPixmap(QRectF(x, y, w / scale, h / scale), pm, QRectF(0, 0, w, h));
}
}
@ -5122,6 +5144,11 @@ void QPainter::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr)
qreal sw = sr.width();
qreal sh = sr.height();
// Get pixmap scale. Use it when calculating the target
// rect size from pixmap size. For example, a 2X 64x64 pixel
// pixmap should result in a 32x32 point target rect.
const qreal pmscale = pm.devicePixelRatio();
// Sanity-check clipping
if (sw <= 0)
sw = pm.width() - sx;
@ -5130,9 +5157,9 @@ void QPainter::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr)
sh = pm.height() - sy;
if (w < 0)
w = sw;
w = sw / pmscale;
if (h < 0)
h = sh;
h = sh / pmscale;
if (sx < 0) {
qreal w_ratio = sx * w/sw;
@ -5345,6 +5372,7 @@ void QPainter::drawImage(const QPointF &p, const QImage &image)
int w = image.width();
int h = image.height();
qreal scale = image.devicePixelRatio();
d->updateState(d->state);
@ -5368,8 +5396,7 @@ void QPainter::drawImage(const QPointF &p, const QImage &image)
setBrush(brush);
setPen(Qt::NoPen);
setBrushOrigin(QPointF(0, 0));
drawRect(image.rect());
drawRect(QRect(QPoint(0, 0), image.size() / scale));
restore();
return;
}
@ -5380,7 +5407,7 @@ void QPainter::drawImage(const QPointF &p, const QImage &image)
y += d->state->matrix.dy();
}
d->engine->drawImage(QRectF(x, y, w, h), image, QRectF(0, 0, w, h), Qt::AutoColor);
d->engine->drawImage(QRectF(x, y, w / scale, h / scale), image, QRectF(0, 0, w, h), Qt::AutoColor);
}
void QPainter::drawImage(const QRectF &targetRect, const QImage &image, const QRectF &sourceRect,
@ -5399,6 +5426,7 @@ void QPainter::drawImage(const QRectF &targetRect, const QImage &image, const QR
qreal sy = sourceRect.y();
qreal sw = sourceRect.width();
qreal sh = sourceRect.height();
qreal imageScale = image.devicePixelRatio();
// Sanity-check clipping
if (sw <= 0)
@ -5408,9 +5436,9 @@ void QPainter::drawImage(const QRectF &targetRect, const QImage &image, const QR
sh = image.height() - sy;
if (w < 0)
w = sw;
w = sw / imageScale;
if (h < 0)
h = sh;
h = sh / imageScale;
if (sx < 0) {
qreal w_ratio = sx * w/sw;
@ -8235,7 +8263,7 @@ QTransform QPainter::combinedTransform() const
qWarning("QPainter::combinedTransform: Painter not active");
return QTransform();
}
return d->state->worldMatrix * d->viewTransform();
return d->state->worldMatrix * d->viewTransform() * d->hidpiScaleTransform();
}
/*!

View File

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

View File

@ -4100,7 +4100,9 @@ void QGLWidget::glDraw()
#endif
if (!d->glcx->initialized()) {
glInit();
resizeGL(d->glcx->device()->width(), d->glcx->device()->height()); // New context needs this "resize"
const qreal scaleFactor = (window() && window()->windowHandle()) ?
window()->windowHandle()->devicePixelRatio() : 1.0;
resizeGL(d->glcx->device()->width() * scaleFactor, d->glcx->device()->height() * scaleFactor); // New context needs this "resize"
}
paintGL();
if (doubleBuffer()) {

View File

@ -370,7 +370,10 @@ void QGLWidget::resizeEvent(QResizeEvent *e)
makeCurrent();
if (!d->glcx->initialized())
glInit();
resizeGL(width(), height());
const qreal scaleFactor = (window() && window()->windowHandle()) ?
window()->windowHandle()->devicePixelRatio() : 1.0;
resizeGL(width() * scaleFactor, height() * scaleFactor);
}

View File

@ -62,6 +62,7 @@ public:
void resize (const QSize &size, const QRegion &);
bool scroll(const QRegion &area, int dx, int dy);
CGImageRef getBackingStoreCGImage();
qreal getBackingStoreDevicePixelRatio();
private:
QImage m_qImage;

View File

@ -59,10 +59,22 @@ QCocoaBackingStore::~QCocoaBackingStore()
QPaintDevice *QCocoaBackingStore::paintDevice()
{
if (m_qImage.size() != m_requestedSize) {
if (m_qImage.size() / m_qImage.devicePixelRatio() != m_requestedSize) {
CGImageRelease(m_cgImage);
m_cgImage = 0;
m_qImage = QImage(m_requestedSize, QImage::Format_ARGB32_Premultiplied);
int scaleFactor = 1;
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_7) {
QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(window()->handle());
if (cocoaWindow && cocoaWindow->m_contentView) {
scaleFactor = int([[cocoaWindow->m_contentView window] backingScaleFactor]);
}
}
#endif
m_qImage = QImage(m_requestedSize * scaleFactor, QImage::Format_ARGB32_Premultiplied);
m_qImage.setDevicePixelRatio(scaleFactor);
}
return &m_qImage;
}
@ -90,10 +102,11 @@ void QCocoaBackingStore::resize(const QSize &size, const QRegion &)
bool QCocoaBackingStore::scroll(const QRegion &area, int dx, int dy)
{
extern void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset);
QPoint qpoint(dx, dy);
const qreal devicePixelRatio = m_qImage.devicePixelRatio();
QPoint qpoint(dx * devicePixelRatio, dy * devicePixelRatio);
const QVector<QRect> qrects = area.rects();
for (int i = 0; i < qrects.count(); ++i) {
const QRect &qrect = qrects.at(i);
const QRect &qrect = QRect(qrects.at(i).topLeft() * devicePixelRatio, qrects.at(i).size() * devicePixelRatio);
qt_scrollRectInImage(m_qImage, qrect, qpoint);
}
return true;
@ -110,4 +123,9 @@ CGImageRef QCocoaBackingStore::getBackingStoreCGImage()
return m_cgImage;
}
qreal QCocoaBackingStore::getBackingStoreDevicePixelRatio()
{
return m_qImage.devicePixelRatio();
}
QT_END_NAMESPACE

View File

@ -114,6 +114,18 @@ void QCocoaGLContext::setActiveWindow(QWindow *window)
cocoaWindow->setCurrentContext(this);
[(QNSView *) cocoaWindow->contentView() setQCocoaGLContext:this];
// Enable high-dpi OpenGL for retina displays. Enabling has the side
// effect that Cooca will start calling glViewport(0, 0, width, height),
// overriding any glViewport calls in application code. This is usually not a
// problem, except if the applcation wants to have a "custom" viewport.
// (like the hellogl example)
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_7) {
if (cocoaWindow->devicePixelRatio() > 1)
[cocoaWindow->contentView() setWantsBestResolutionOpenGLSurface:YES];
}
#endif
}
void QCocoaGLContext::doneCurrent()

View File

@ -68,6 +68,7 @@ public:
QRect availableGeometry() const { return m_availableGeometry; }
int depth() const { return m_depth; }
QImage::Format format() const { return m_format; }
qreal devicePixelRatio() const;
QSizeF physicalSize() const { return m_physicalSize; }
QDpi logicalDpi() const { return m_logicalDpi; }
qreal refreshRate() const { return m_refreshRate; }

View File

@ -115,6 +115,18 @@ void QCocoaScreen::updateGeometry()
QWindowSystemInterface::handleScreenAvailableGeometryChange(screen(), availableGeometry());
}
qreal QCocoaScreen::devicePixelRatio() const
{
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_7) {
return qreal([m_screen backingScaleFactor]);
} else
#endif
{
return 1.0;
}
}
extern CGContextRef qt_mac_cg_context(const QPaintDevice *pdev);
QPixmap QCocoaScreen::grabWindow(WId window, int x, int y, int width, int height) const

View File

@ -140,6 +140,8 @@ public:
void setMenubar(QCocoaMenuBar *mb);
QCocoaMenuBar *menubar() const;
qreal devicePixelRatio() const;
protected:
// NSWindow handling. The QCocoaWindow/QNSView can either be displayed
// in an existing NSWindow or in one created by Qt.

View File

@ -39,6 +39,7 @@
**
****************************************************************************/
#include "qcocoawindow.h"
#include "qcocoaintegration.h"
#include "qnswindowdelegate.h"
#include "qcocoaautoreleasepool.h"
#include "qcocoaeventdispatcher.h"
@ -820,6 +821,20 @@ QCocoaMenuBar *QCocoaWindow::menubar() const
return m_menubar;
}
qreal QCocoaWindow::devicePixelRatio() const
{
if (!m_nsWindow)
return 1.0;
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_7) {
return qreal([m_nsWindow backingScaleFactor]);
} else
#endif
{
return 1.0;
}
}
QMargins QCocoaWindow::frameMargins() const
{
NSRect frameW = [m_nsWindow frame];

View File

@ -244,7 +244,7 @@ static QTouchDevice *touchDevice = 0;
- (void) flushBackingStore:(QCocoaBackingStore *)backingStore region:(const QRegion &)region offset:(QPoint)offset
{
m_backingStore = backingStore;
m_backingStoreOffset = offset;
m_backingStoreOffset = offset * m_backingStore->getBackingStoreDevicePixelRatio();
QRect br = region.boundingRect();
[self setNeedsDisplayInRect:NSMakeRect(br.x(), br.y(), br.width(), br.height())];
}
@ -275,33 +275,44 @@ static QTouchDevice *touchDevice = 0;
if (!m_backingStore)
return;
CGRect dirtyCGRect = NSRectToCGRect(dirtyRect);
// Calculate source and target rects. The target rect is the dirtyRect:
CGRect dirtyWindowRect = NSRectToCGRect(dirtyRect);
// The backing store source rect will be larger on retina displays.
// Scale dirtyRect by the device pixel ratio:
const qreal devicePixelRatio = m_backingStore->getBackingStoreDevicePixelRatio();
CGRect dirtyBackingRect = CGRectMake(dirtyRect.origin.x * devicePixelRatio,
dirtyRect.origin.y * devicePixelRatio,
dirtyRect.size.width * devicePixelRatio,
dirtyRect.size.height * devicePixelRatio);
NSGraphicsContext *nsGraphicsContext = [NSGraphicsContext currentContext];
CGContextRef cgContext = (CGContextRef) [nsGraphicsContext graphicsPort];
// Translate coordiate system from CoreGraphics (bottom-left) to NSView (top-left):
CGContextSaveGState(cgContext);
int dy = dirtyCGRect.origin.y + CGRectGetMaxY(dirtyCGRect);
int dy = dirtyWindowRect.origin.y + CGRectGetMaxY(dirtyWindowRect);
CGContextTranslateCTM(cgContext, 0, dy);
CGContextScaleCTM(cgContext, 1, -1);
// If a mask is set, modify the sub image accordingly:
CGImageRef subMask = 0;
if (m_maskImage) {
subMask = CGImageCreateWithImageInRect(m_maskImage, dirtyCGRect);
CGContextClipToMask(cgContext, dirtyCGRect, subMask);
subMask = CGImageCreateWithImageInRect(m_maskImage, dirtyWindowRect);
CGContextClipToMask(cgContext, dirtyWindowRect, subMask);
}
// Clip out and draw the correct sub image from the (shared) backingstore:
CGRect backingStoreRect = CGRectMake(
dirtyRect.origin.x + m_backingStoreOffset.x(),
dirtyRect.origin.y + m_backingStoreOffset.y(),
dirtyRect.size.width,
dirtyRect.size.height
dirtyBackingRect.origin.x + m_backingStoreOffset.x(),
dirtyBackingRect.origin.y + m_backingStoreOffset.y(),
dirtyBackingRect.size.width,
dirtyBackingRect.size.height
);
CGImageRef bsCGImage = m_backingStore->getBackingStoreCGImage();
CGImageRef cleanImg = CGImageCreateWithImageInRect(bsCGImage, backingStoreRect);
CGContextDrawImage(cgContext, dirtyCGRect, cleanImg);
CGContextDrawImage(cgContext, dirtyWindowRect, cleanImg);
// Clean-up:
CGContextRestoreGState(cgContext);

View File

@ -1060,10 +1060,12 @@ QRect QItemDelegate::rect(const QStyleOptionViewItem &option,
switch (value.type()) {
case QVariant::Invalid:
break;
case QVariant::Pixmap:
return QRect(QPoint(0, 0), qvariant_cast<QPixmap>(value).size());
case QVariant::Image:
return QRect(QPoint(0, 0), qvariant_cast<QImage>(value).size());
case QVariant::Pixmap: {
const QPixmap &pixmap = qvariant_cast<QPixmap>(value);
return QRect(QPoint(0, 0), pixmap.size() / pixmap.devicePixelRatio() ); }
case QVariant::Image: {
const QImage &image = qvariant_cast<QImage>(value);
return QRect(QPoint(0, 0), image.size() / image.devicePixelRatio() ); }
case QVariant::Icon: {
QIcon::Mode mode = d->iconMode(option.state);
QIcon::State state = d->iconState(option.state);

View File

@ -1794,6 +1794,23 @@ QRegion QWidgetPrivate::clipRegion() const
return r;
}
void QWidgetPrivate::setSystemClip(QPaintDevice *paintDevice, const QRegion &region)
{
// Transform the system clip region from device-independent pixels to device pixels
// Qt 5.0.0: This is a Mac-only code path for now, can be made cross-platform once
// 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;
scaleTransform.scale(devicePixelRatio, devicePixelRatio);
paintEngine->d_func()->systemClip = scaleTransform.map(region);
#else
paintEngine->d_func()->systemClip = region;
#endif
}
#ifndef QT_NO_GRAPHICSEFFECT
void QWidgetPrivate::invalidateGraphicsEffectsRecursively()
{
@ -4998,13 +5015,12 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
QWidgetPaintContext context(pdev, rgn, offset, flags, sharedPainter, backingStore);
sourced->context = &context;
if (!sharedPainter) {
QPaintEngine *paintEngine = pdev->paintEngine();
paintEngine->d_func()->systemClip = rgn.translated(offset);
setSystemClip(pdev, rgn.translated(offset));
QPainter p(pdev);
p.translate(offset);
context.painter = &p;
graphicsEffect->draw(&p);
paintEngine->d_func()->systemClip = QRegion();
setSystemClip(pdev, QRegion());
} else {
context.painter = sharedPainter;
if (sharedPainter->worldTransform() != sourced->lastEffectTransform) {
@ -5061,7 +5077,7 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
#endif
if (sharedPainter)
paintEngine->d_func()->systemClip = toBePainted;
setSystemClip(pdev, toBePainted);
else
paintEngine->d_func()->systemRect = q->data->crect;
@ -5073,7 +5089,7 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
}
if (!sharedPainter)
paintEngine->d_func()->systemClip = toBePainted.translated(offset);
setSystemClip(pdev, toBePainted.translated(offset));
if (!onScreen && !asRoot && !isOpaque && q->testAttribute(Qt::WA_TintedBackground)) {
QPainter p(q);
@ -5108,7 +5124,8 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
paintEngine->d_func()->systemRect = QRect();
else
paintEngine->d_func()->currentClipDevice = 0;
paintEngine->d_func()->systemClip = QRegion();
setSystemClip(pdev, QRegion());
}
q->setAttribute(Qt::WA_WState_InPaintEvent, false);
if (q->paintingActive())

View File

@ -402,6 +402,7 @@ public:
QRect clipRect() const;
QRegion clipRegion() const;
void setSystemClip(QPaintDevice *paintDevice, const QRegion &region);
void subtractOpaqueChildren(QRegion &rgn, const QRect &clipRect) const;
void subtractOpaqueSiblings(QRegion &source, bool *hasDirtySiblingsAbove = 0,
bool alsoNonOpaque = false) const;

View File

@ -303,7 +303,7 @@ static void qt_fusion_draw_mdibutton(QPainter *painter, const QStyleOptionTitleB
gradient.setColorAt(1, mdiButtonGradientStopColor);
QColor mdiButtonBorderColor(active ? option->palette.highlight().color().darker(180): dark.darker(110));
painter->setPen(QPen(mdiButtonBorderColor, 1));
painter->setPen(QPen(mdiButtonBorderColor));
const QLine lines[4] = {
QLine(tmp.left() + 2, tmp.top(), tmp.right() - 2, tmp.top()),
QLine(tmp.left() + 2, tmp.bottom(), tmp.right() - 2, tmp.bottom()),
@ -457,7 +457,7 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem,
if (const QStyleOptionTabBarBase *tbb
= qstyleoption_cast<const QStyleOptionTabBarBase *>(option)) {
painter->save();
painter->setPen(QPen(outline.lighter(110), 0));
painter->setPen(QPen(outline.lighter(110)));
switch (tbb->shape) {
case QTabBar::RoundedNorth: {
QRegion region(tbb->rect);
@ -603,7 +603,7 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem,
}
}
break;
case PE_Frame:
case PE_Frame: {
if (widget && widget->inherits("QComboBoxPrivateContainer")){
QStyleOption copy = *option;
copy.state |= State_Raised;
@ -611,14 +611,16 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem,
break;
}
painter->save();
painter->setPen(outline.lighter(108));
QPen thePen(outline.lighter(108));
thePen.setCosmetic(false);
painter->setPen(thePen);
painter->drawRect(option->rect.adjusted(0, 0, -1, -1));
painter->restore();
painter->restore(); }
break;
case PE_FrameMenu:
painter->save();
{
painter->setPen(QPen(outline, 1));
painter->setPen(QPen(outline));
painter->drawRect(option->rect.adjusted(0, 0, -1, -1));
QColor frameLight = option->palette.background().color().lighter(160);
QColor frameShadow = option->palette.background().color().darker(110);
@ -644,9 +646,9 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem,
QRect rect= option->rect;
painter->setPen(softshadow);
painter->drawRect(option->rect.adjusted(0, 0, -1, -1));
painter->setPen(QPen(option->palette.light(), 0));
painter->setPen(QPen(option->palette.light(), 1));
painter->drawLine(QPoint(rect.left() + 1, rect.top() + 1), QPoint(rect.left() + 1, rect.bottom() - 1));
painter->setPen(QPen(option->palette.background().color().darker(120), 0));
painter->setPen(QPen(option->palette.background().color().darker(120)));
painter->drawLine(QPoint(rect.left() + 1, rect.bottom() - 1), QPoint(rect.right() - 2, rect.bottom() - 1));
painter->drawLine(QPoint(rect.right() - 1, rect.top() + 1), QPoint(rect.right() - 1, rect.bottom() - 1));
@ -680,12 +682,12 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem,
painter->save();
{
QRect rect= option->rect;
painter->setPen(QPen(outline.darker(150), 0));
painter->setPen(QPen(outline.darker(150)));
painter->drawRect(option->rect.adjusted(0, 0, -1, -1));
painter->setPen(QPen(option->palette.light(), 0));
painter->setPen(QPen(option->palette.light(), 1));
painter->drawLine(QPoint(rect.left() + 1, rect.top() + 1),
QPoint(rect.left() + 1, rect.bottom() - 1));
painter->setPen(QPen(option->palette.background().color().darker(120), 0));
painter->setPen(QPen(option->palette.background().color().darker(120)));
painter->drawLine(QPoint(rect.left() + 1, rect.bottom() - 1),
QPoint(rect.right() - 2, rect.bottom() - 1));
painter->drawLine(QPoint(rect.right() - 1, rect.top() + 1),
@ -705,7 +707,7 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem,
painter->translate(0.5, 0.5);
// Draw Outline
painter->setPen( QPen(hasFocus ? highlightedOutline : outline, 0));
painter->setPen( QPen(hasFocus ? highlightedOutline : outline));
painter->setBrush(option->palette.base());
painter->drawRoundedRect(r.adjusted(0, 0, -1, -1), 2, 2);
@ -740,10 +742,10 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem,
gradient.setColorAt(1, (state & State_Sunken) ? pressedColor : option->palette.base().color());
painter->setBrush((state & State_Sunken) ? QBrush(pressedColor) : gradient);
painter->setPen(QPen(outline.lighter(110), 1));
painter->setPen(QPen(outline.lighter(110)));
if (option->state & State_HasFocus && option->state & State_KeyboardFocusChange)
painter->setPen(QPen(highlightedOutline, 1));
painter->setPen(QPen(highlightedOutline));
painter->drawRect(rect);
QColor checkMarkColor = option->palette.text().color().darker(120);
@ -785,9 +787,9 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem,
painter->setRenderHint(QPainter::Antialiasing, true);
QPainterPath circle;
circle.addEllipse(rect.center() + QPoint(1.0, 1.0), 6.5, 6.5);
painter->setPen(QPen(option->palette.background().color().darker(150), 1));
painter->setPen(QPen(option->palette.background().color().darker(150)));
if (option->state & State_HasFocus && option->state & State_KeyboardFocusChange)
painter->setPen(QPen(highlightedOutline, 1));
painter->setPen(QPen(highlightedOutline));
painter->drawPath(circle);
if (state & (State_On )) {
@ -862,7 +864,7 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem,
if (isFlat && !isDown) {
if (isDefault) {
r = option->rect.adjusted(0, 1, 0, -1);
painter->setPen(QPen(Qt::black, 0));
painter->setPen(QPen(Qt::black));
const QLine lines[4] = {
QLine(QPoint(r.left() + 2, r.top()),
QPoint(r.right() - 2, r.top())),
@ -910,7 +912,7 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem,
p->setBrush(Qt::NoBrush);
// Outline
p->setPen(!isEnabled ? QPen(darkOutline.lighter(115)) : QPen(darkOutline, 1));
p->setPen(!isEnabled ? QPen(darkOutline.lighter(115)) : QPen(darkOutline));
p->drawRoundedRect(r, 2.0, 2.0);
p->setPen(d->innerContrastLine());
@ -1300,7 +1302,7 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio
painter->drawLine(rect.topLeft() - QPoint(0, 1), rect.topRight() - QPoint(0, 1));
painter->setBrush(option->palette.base());
painter->setPen(QPen(outline, 0));
painter->setPen(QPen(outline));
painter->drawRoundedRect(rect.adjusted(0, 0, -1, -1), 2, 2);
// Inner shadow
@ -1359,14 +1361,14 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio
progressBar.setRect(rect.left(), rect.top(), width - 1, rect.height() - 1);
if (!complete) {
painter->drawLine(progressBar.topRight() + QPoint(2, 1), progressBar.bottomRight() + QPoint(2, 0));
painter->setPen(QPen(highlight.darker(140), 0));
painter->setPen(QPen(highlight.darker(140)));
painter->drawLine(progressBar.topRight() + QPoint(1, 1), progressBar.bottomRight() + QPoint(1, 0));
}
} else {
progressBar.setRect(rect.right() - width - 1, rect.top(), width + 2, rect.height() - 1);
if (!complete) {
painter->drawLine(progressBar.topLeft() + QPoint(-2, 1), progressBar.bottomLeft() + QPoint(-2, 0));
painter->setPen(QPen(highlight.darker(140), 0));
painter->setPen(QPen(highlight.darker(140)));
painter->drawLine(progressBar.topLeft() + QPoint(-1, 1), progressBar.bottomLeft() + QPoint(-1, 0));
}
}
@ -1376,7 +1378,7 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio
if (indeterminate || bar->progress > bar->minimum) {
painter->setPen(QPen(outline, 0));
painter->setPen(QPen(outline));
QColor highlightedGradientStartColor = highlight.lighter(120);
QColor highlightedGradientStopColor = highlight;
@ -1471,7 +1473,7 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio
QRect r = option->rect;
if (act) {
painter->setBrush(option->palette.highlight().color());
painter->setPen(QPen(highlightOutline, 0));
painter->setPen(QPen(highlightOutline));
painter->drawRect(r.adjusted(0, 0, -1, -1));
// painter->drawRoundedRect(r.adjusted(1, 1, -1, -1), 2, 2);
@ -1518,7 +1520,7 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio
if (selected) {
QRect r = option->rect;
painter->fillRect(r, highlight);
painter->setPen(QPen(highlightOutline, 0));
painter->setPen(QPen(highlightOutline));
const QLine lines[4] = {
QLine(QPoint(r.left() + 1, r.bottom()), QPoint(r.right() - 1, r.bottom())),
QLine(QPoint(r.left() + 1, r.top()), QPoint(r.right() - 1, r.top())),
@ -2141,15 +2143,18 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption
QPixmap upArrow = colorizedImage(QLatin1String(":/qt-project.org/styles/commonstyle/images/fusion_arrow.png"),
(spinBox->stepEnabled & QAbstractSpinBox::StepUpEnabled) ? arrowColor : disabledColor);
cachePainter.drawPixmap(QRect(upRect.center().x() - upArrow.width() / 4 + 1,
upRect.center().y() - upArrow.height() / 4 + 1,
upArrow.width()/2, upArrow.height()/2), upArrow);
QRectF upArrowRect = QRectF(upRect.center().x() - upArrow.width() / 4.0 + 1.0,
upRect.center().y() - upArrow.height() / 4.0 + 1.0,
upArrow.width() / 2.0, upArrow.height() / 2.0);
cachePainter.drawPixmap(upArrowRect, upArrow, QRectF(QPointF(0.0, 0.0), upArrow.size()));
QPixmap downArrow = colorizedImage(QLatin1String(":/qt-project.org/styles/commonstyle/images/fusion_arrow.png"),
(spinBox->stepEnabled & QAbstractSpinBox::StepDownEnabled) ? arrowColor : disabledColor, 180);
cachePainter.drawPixmap(QRect(downRect.center().x() - downArrow.width() / 4 + 1,
downRect.center().y() - downArrow.height() / 4 + 1,
downArrow.width()/2, downArrow.height()/2), downArrow);
QRectF downArrowRect = QRectF(downRect.center().x() - downArrow.width() / 4.0 + 1.0,
downRect.center().y() - downArrow.height() / 4.0 + 1.0,
downArrow.width() / 2.0, downArrow.height() / 2.0);
cachePainter.drawPixmap(downArrowRect, downArrow, QRectF(QPointF(0.0, 0.0), downArrow.size()));
}
cachePainter.end();
@ -2486,7 +2491,7 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption
// Paint slider
if (scrollBar->subControls & SC_ScrollBarSlider) {
QRect pixmapRect = scrollBarSlider;
painter->setPen(QPen(alphaOutline, 0));
painter->setPen(QPen(alphaOutline));
if (option->state & State_Sunken && scrollBar->activeSubControls & SC_ScrollBarSlider)
painter->setBrush(midColor2);
else if (option->state & State_MouseOver && scrollBar->activeSubControls & SC_ScrollBarSlider)
@ -2521,7 +2526,7 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption
painter->setPen(Qt::NoPen);
painter->drawRect(scrollBarSubLine.adjusted(horizontal ? 0 : 1, horizontal ? 1 : 0, 0, 0));
painter->setPen(QPen(alphaOutline, 1));
painter->setPen(QPen(alphaOutline));
if (option->state & State_Horizontal) {
if (option->direction == Qt::RightToLeft) {
pixmapRect.setLeft(scrollBarSubLine.left());
@ -2545,9 +2550,10 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption
rotation = option->direction == Qt::LeftToRight ? -90 : 90;
QRect upRect = scrollBarSubLine.translated(horizontal ? -2 : -1, 0);
QPixmap arrowPixmap = colorizedImage(QLatin1String(":/qt-project.org/styles/commonstyle/images/fusion_arrow.png"), arrowColor, rotation);
painter->drawPixmap(QRect(upRect.center().x() - arrowPixmap.width() / 4 + 2,
upRect.center().y() - arrowPixmap.height() / 4 + 1,
arrowPixmap.width()/2, arrowPixmap.height()/2), arrowPixmap);
painter->drawPixmap(QRectF(upRect.center().x() - arrowPixmap.width() / 4.0 + 2.0,
upRect.center().y() - arrowPixmap.height() / 4.0 + 1.0,
arrowPixmap.width() / 2.0, arrowPixmap.height() / 2.0),
arrowPixmap, QRectF(QPoint(0.0, 0.0), arrowPixmap.size()));
}
// The AddLine (down/right) button
@ -2584,9 +2590,10 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption
rotation = option->direction == Qt::LeftToRight ? 90 : -90;
QRect downRect = scrollBarAddLine.translated(-1, 1);
QPixmap arrowPixmap = colorizedImage(QLatin1String(":/qt-project.org/styles/commonstyle/images/fusion_arrow.png"), arrowColor, rotation);
painter->drawPixmap(QRect(downRect.center().x() - arrowPixmap.width() / 4 + 2,
downRect.center().y() - arrowPixmap.height() / 4,
arrowPixmap.width()/2, arrowPixmap.height()/2), arrowPixmap);
painter->drawPixmap(QRectF(downRect.center().x() - arrowPixmap.width() / 4.0 + 2.0,
downRect.center().y() - arrowPixmap.height() / 4.0,
arrowPixmap.width() / 2.0, arrowPixmap.height() / 2.0),
arrowPixmap, QRectF(QPoint(0.0, 0.0), arrowPixmap.size()));
}
}
@ -2640,7 +2647,7 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption
downArrowRect.left() - 6: downArrowRect.right() + 6);
proxy()->drawPrimitive(PE_PanelButtonCommand, &buttonOption, &cachePainter, widget);
cachePainter.restore();
cachePainter.setPen( QPen(hasFocus ? option->palette.highlight() : outline.lighter(110), 0));
cachePainter.setPen( QPen(hasFocus ? option->palette.highlight() : outline.lighter(110), 1));
if (!sunken) {
int borderSize = 1;
@ -2677,9 +2684,10 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption
QColor arrowColor = option->palette.buttonText().color();
arrowColor.setAlpha(220);
QPixmap downArrow = colorizedImage(QLatin1String(":/qt-project.org/styles/commonstyle/images/fusion_arrow.png"), arrowColor, 180);
cachePainter.drawPixmap(QRect(downArrowRect.center().x() - downArrow.width() / 4 + 1,
downArrowRect.center().y() - downArrow.height() / 4 + 1,
downArrow.width()/2, downArrow.height()/2), downArrow);
cachePainter.drawPixmap(QRectF(downArrowRect.center().x() - downArrow.width() / 4.0 + 1.0,
downArrowRect.center().y() - downArrow.height() / 4.0 + 1.0,
downArrow.width() / 2.0, downArrow.height() / 2.0),
downArrow, QRectF(QPointF(0.0, 0.0), downArrow.size()));
}
cachePainter.end();
QPixmapCache::insert(pixmapName, cache);
@ -2730,7 +2738,7 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption
gradient.setStart(pixmapRect.left(), pixmapRect.center().y());
gradient.setFinalStop(pixmapRect.right(), pixmapRect.center().y());
}
groovePainter.setPen(QPen(outline, 0));
groovePainter.setPen(QPen(outline));
gradient.setColorAt(0, grooveColor.darker(110));
gradient.setColorAt(1, grooveColor.lighter(110));//palette.button().color().darker(115));
groovePainter.setBrush(gradient);
@ -2764,7 +2772,7 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption
groovePainter.setRenderHint(QPainter::Antialiasing, true);
groovePainter.translate(0.5, 0.5);
groovePainter.setPen(QPen(outline, 0));
groovePainter.setPen(QPen(outline));
gradient.setColorAt(0, activeHighlight);
gradient.setColorAt(1, activeHighlight.lighter(130));
groovePainter.setBrush(gradient);
@ -2813,9 +2821,9 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption
handlePainter.setBrush(QColor(0, 0, 0, 40));
handlePainter.drawRect(r.adjusted(-1, 2, 1, -2));
handlePainter.setPen(QPen(d->outline(option->palette), 1));
handlePainter.setPen(QPen(d->outline(option->palette)));
if (option->state & State_HasFocus && option->state & State_KeyboardFocusChange)
handlePainter.setPen(QPen(d->highlightedOutline(option->palette), 1));
handlePainter.setPen(QPen(d->highlightedOutline(option->palette)));
handlePainter.setBrush(gradient);
handlePainter.drawRoundedRect(r, 2, 2);

View File

@ -462,7 +462,7 @@ class QMacCGContext
{
CGContextRef context;
public:
QMacCGContext(QPainter *p); //qpaintengine_mac.cpp
QMacCGContext(QPainter *p);
inline QMacCGContext() { context = 0; }
inline QMacCGContext(const QPaintDevice *pdev) {
extern CGContextRef qt_mac_cg_context(const QPaintDevice *);
@ -6476,6 +6476,18 @@ void qt_mac_clip_cg(CGContextRef hd, const QRegion &rgn, CGAffineTransform *orig
}
}
// move to QRegion?
void qt_mac_scale_region(QRegion *region, qreal scaleFactor)
{
QVector<QRect> scaledRects;
scaledRects.reserve(region->rects().count());
foreach (const QRect &rect, region->rects()) {
scaledRects.append(QRect(rect.topLeft(), rect.size() * scaleFactor));
}
region->setRects(&scaledRects[0], scaledRects.count());
}
QMacCGContext::QMacCGContext(QPainter *p)
{
QPaintEngine *pe = p->paintEngine();
@ -6502,20 +6514,28 @@ QMacCGContext::QMacCGContext(QPainter *p)
CGContextScaleCTM(context, 1, -1);
if (devType == QInternal::Widget) {
QRegion clip = p->paintEngine()->systemClip();
QTransform native = p->deviceTransform();
// Set the clip rect which is an intersection of the system clip
// and the painter clip. To make matters more interesting these
// are in device pixels and device-independent pixels, respectively.
const qreal devicePixelRatio = image->devicePixelRatio();
QRegion clip = p->paintEngine()->systemClip(); // get system clip in device pixels
QTransform native = p->deviceTransform(); // get device transform. dx/dy is in device pixels
if (p->hasClipping()) {
QRegion r = p->clipRegion();
QRegion r = p->clipRegion(); // get painter clip, which is in device-independent pixels
qt_mac_scale_region(&r, devicePixelRatio); // scale painter clip to device pixels
r.translate(native.dx(), native.dy());
if (clip.isEmpty())
clip = r;
else
clip &= r;
}
qt_mac_clip_cg(context, clip, 0);
qt_mac_clip_cg(context, clip, 0); // clip in device pixels
CGContextTranslateCTM(context, native.dx(), native.dy());
// Scale the context so that painting happens in device-independet pixels.
CGContextScaleCTM(context, devicePixelRatio, devicePixelRatio);
CGContextTranslateCTM(context, native.dx() / devicePixelRatio, native.dy() / devicePixelRatio);
}
} else {
qDebug() << "QMacCGContext:: Unsupported painter devtype type" << devType;

View File

@ -618,10 +618,11 @@ void QStyle::drawItemText(QPainter *painter, const QRect &rect, int alignment, c
void QStyle::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment,
const QPixmap &pixmap) const
{
QRect aligned = alignedRect(QApplication::layoutDirection(), QFlag(alignment), pixmap.size(), rect);
int scale = pixmap.devicePixelRatio();
QRect aligned = alignedRect(QApplication::layoutDirection(), QFlag(alignment), pixmap.size() / scale, rect);
QRect inter = aligned.intersected(rect);
painter->drawPixmap(inter.x(), inter.y(), pixmap, inter.x() - aligned.x(), inter.y() - aligned.y(), inter.width(), inter.height());
painter->drawPixmap(inter.x(), inter.y(), pixmap, inter.x() - aligned.x(), inter.y() - aligned.y(), inter.width() * scale, inter.height() *scale);
}
/*!

View File

@ -43,6 +43,7 @@
#define QSTYLE_P_H
#include "private/qobject_p.h"
#include <QtGui/qguiapplication.h>
#include <QtWidgets/qstyle.h>
QT_BEGIN_NAMESPACE
@ -74,12 +75,18 @@ public:
inline QImage styleCacheImage(const QSize &size)
{
return QImage(size, QImage::Format_ARGB32_Premultiplied);
const qreal pixelRatio = qApp->devicePixelRatio();
QImage cacheImage = QImage(size * pixelRatio, QImage::Format_ARGB32_Premultiplied);
cacheImage.setDevicePixelRatio(pixelRatio);
return cacheImage;
}
inline QPixmap styleCachePixmap(const QSize &size)
{
return QPixmap(size);
const qreal pixelRatio = qApp->devicePixelRatio();
QPixmap cachePixmap = QPixmap(size * pixelRatio);
cachePixmap.setDevicePixelRatio(pixelRatio);
return cachePixmap;
}
#define BEGIN_STYLE_PIXMAPCACHE(a) \

View File

@ -562,17 +562,18 @@ QSize QLabelPrivate::sizeForWidth(int w) const
int vextra = hextra;
QFontMetrics fm = q->fontMetrics();
if (pixmap && !pixmap->isNull())
if (pixmap && !pixmap->isNull()) {
br = pixmap->rect();
br.setSize(br.size() / pixmap->devicePixelRatio());
#ifndef QT_NO_PICTURE
else if (picture && !picture->isNull())
} else if (picture && !picture->isNull()) {
br = picture->boundingRect();
#endif
#ifndef QT_NO_MOVIE
else if (movie && !movie->currentPixmap().isNull())
} else if (movie && !movie->currentPixmap().isNull()) {
br = movie->currentPixmap().rect();
#endif
else if (isTextLabel) {
} else if (isTextLabel) {
int align = QStyle::visualAlignment(textDirection(), QFlag(this->align));
// Add indentation
int m = indent;

View File

@ -0,0 +1,12 @@
TEMPLATE = app
TARGET = highdpi
DEPENDPATH += .
INCLUDEPATH += .
QT += widgets
# Input
SOURCES += main.cpp
RESOURCES += \
highdpi.qrc

View File

@ -0,0 +1,7 @@
<RCC>
<qresource prefix="/">
<file>qticon.png</file>
<file>qticon@2x.png</file>
<file>qticon_large.png</file>
</qresource>
</RCC>

View File

@ -0,0 +1,366 @@
/****************************************************************************
**
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtCore>
#include <QtGui>
#include <QtWidgets>
class PixmapPainter : public QWidget
{
public:
PixmapPainter();
void paintEvent(QPaintEvent *event);
QPixmap pixmap1X;
QPixmap pixmap2X;
QPixmap pixmapLarge;
QImage image1X;
QImage image2X;
QImage imageLarge;
QIcon qtIcon;
};
PixmapPainter::PixmapPainter()
{
pixmap1X = QPixmap(":/qticon.png");
pixmap2X = QPixmap(":/qticon@2x.png");
pixmapLarge = QPixmap(":/qticon_large.png");
image1X = QImage(":/qticon.png");
image2X = QImage(":/qticon@2x.png");
imageLarge = QImage(":/qticon_large.png");
qtIcon.addFile(":/qticon.png");
qtIcon.addFile(":/qticon@2x.png");
}
void PixmapPainter::paintEvent(QPaintEvent *event)
{
QPainter p(this);
p.fillRect(QRect(QPoint(0, 0), size()), QBrush(Qt::gray));
int pixmapPointSize = 64;
int y = 30;
int dy = 150;
int x = 10;
int dx = 80;
// draw at point
// qDebug() << "paint pixmap" << pixmap1X.devicePixelRatio();
p.drawPixmap(x, y, pixmap1X);
x+=dx;p.drawPixmap(x, y, pixmap2X);
x+=dx;p.drawPixmap(x, y, pixmapLarge);
x+=dx*2;p.drawPixmap(x, y, qtIcon.pixmap(QSize(pixmapPointSize, pixmapPointSize)));
x+=dx;p.drawImage(x, y, image1X);
x+=dx;p.drawImage(x, y, image2X);
x+=dx;p.drawImage(x, y, imageLarge);
// draw at 64x64 rect
y+=dy;
x = 10;
p.drawPixmap(QRect(x, y, pixmapPointSize, pixmapPointSize), pixmap1X);
x+=dx;p.drawPixmap(QRect(x, y, pixmapPointSize, pixmapPointSize), pixmap2X);
x+=dx;p.drawPixmap(QRect(x, y, pixmapPointSize, pixmapPointSize), pixmapLarge);
x+=dx;p.drawPixmap(QRect(x, y, pixmapPointSize, pixmapPointSize), qtIcon.pixmap(QSize(pixmapPointSize, pixmapPointSize)));
x+=dx;p.drawImage(QRect(x, y, pixmapPointSize, pixmapPointSize), image1X);
x+=dx;p.drawImage(QRect(x, y, pixmapPointSize, pixmapPointSize), image2X);
x+=dx;p.drawImage(QRect(x, y, pixmapPointSize, pixmapPointSize), imageLarge);
// draw at 128x128 rect
y+=dy - 50;
x = 10;
p.drawPixmap(QRect(x, y, pixmapPointSize * 2, pixmapPointSize * 2), pixmap1X);
x+=dx * 2; p.drawPixmap(QRect(x, y, pixmapPointSize * 2, pixmapPointSize * 2), pixmap2X);
x+=dx * 2; p.drawPixmap(QRect(x, y, pixmapPointSize * 2, pixmapPointSize * 2), pixmapLarge);
x+=dx * 2; p.drawPixmap(QRect(x, y, pixmapPointSize * 2, pixmapPointSize * 2), qtIcon.pixmap(QSize(pixmapPointSize, pixmapPointSize)));
x+=dx * 2; p.drawImage(QRect(x, y, pixmapPointSize * 2, pixmapPointSize * 2), image1X);
x+=dx * 2; p.drawImage(QRect(x, y, pixmapPointSize * 2, pixmapPointSize * 2), image2X);
x+=dx * 2; p.drawImage(QRect(x, y, pixmapPointSize * 2, pixmapPointSize * 2), imageLarge);
}
class Labels : public QWidget
{
public:
Labels();
QPixmap pixmap1X;
QPixmap pixmap2X;
QPixmap pixmapLarge;
QIcon qtIcon;
};
Labels::Labels()
{
pixmap1X = QPixmap(":/qticon.png");
pixmap2X = QPixmap(":/qticon@2x.png");
pixmapLarge = QPixmap(":/qticon_large.png");
qtIcon.addFile(":/qticon.png");
qtIcon.addFile(":/qticon@2x.png");
setWindowIcon(qtIcon);
setWindowTitle("Labels");
QLabel *label1x = new QLabel();
label1x->setPixmap(pixmap1X);
QLabel *label2x = new QLabel();
label2x->setPixmap(pixmap2X);
QLabel *labelIcon = new QLabel();
labelIcon->setPixmap(qtIcon.pixmap(QSize(64,64)));
QLabel *labelLarge = new QLabel();
labelLarge->setPixmap(pixmapLarge);
QHBoxLayout *layout = new QHBoxLayout(this);
// layout->addWidget(label1x); //expected low-res on high-dpi displays
layout->addWidget(label2x);
// layout->addWidget(labelIcon);
// layout->addWidget(labelLarge); // expected large size and low-res
setLayout(layout);
}
class MainWindow : public QMainWindow
{
public:
MainWindow();
QIcon qtIcon;
QIcon qtIcon1x;
QIcon qtIcon2x;
QToolBar *fileToolBar;
};
MainWindow::MainWindow()
{
qtIcon.addFile(":/qticon.png");
qtIcon.addFile(":/qticon@2x.png");
qtIcon1x.addFile(":/qticon.png");
qtIcon2x.addFile(":/qticon@2x.png");
setWindowIcon(qtIcon);
setWindowTitle("MainWindow");
fileToolBar = addToolBar(tr("File"));
// fileToolBar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
fileToolBar->addAction(new QAction(qtIcon, QString("1x and 2x"), this));
fileToolBar->addAction(new QAction(qtIcon1x, QString("1x"), this));
fileToolBar->addAction(new QAction(qtIcon2x, QString("2x"), this));
}
class StandardIcons : public QWidget
{
public:
void paintEvent(QPaintEvent *event)
{
int x = 10;
int y = 10;
int dx = 50;
int dy = 50;
int maxX = 500;
for (int iconIndex = QStyle::SP_TitleBarMenuButton; iconIndex < QStyle::SP_MediaVolumeMuted; ++iconIndex) {
QIcon icon = qApp->style()->standardIcon(QStyle::StandardPixmap(iconIndex));
QPainter p(this);
p.drawPixmap(x, y, icon.pixmap(dx - 5, dy - 5));
if (x + dx > maxX)
y+=dy;
x = ((x + dx) % maxX);
}
};
};
class Caching : public QWidget
{
public:
void paintEvent(QPaintEvent *event)
{
QSize layoutSize(75, 75);
QPainter widgetPainter(this);
widgetPainter.fillRect(QRect(QPoint(0, 0), this->size()), Qt::gray);
{
const qreal devicePixelRatio = this->windowHandle()->devicePixelRatio();
QPixmap cache(layoutSize * devicePixelRatio);
cache.setDevicePixelRatio(devicePixelRatio);
QPainter cachedPainter(&cache);
cachedPainter.fillRect(QRect(0,0, 75, 75), Qt::blue);
cachedPainter.fillRect(QRect(10,10, 55, 55), Qt::red);
cachedPainter.drawEllipse(QRect(10,10, 55, 55));
QPainter widgetPainter(this);
widgetPainter.drawPixmap(QPoint(10, 10), cache);
}
{
const qreal devicePixelRatio = this->windowHandle()->devicePixelRatio();
QImage cache = QImage(layoutSize * devicePixelRatio, QImage::QImage::Format_ARGB32_Premultiplied);
cache.setDevicePixelRatio(devicePixelRatio);
QPainter cachedPainter(&cache);
cachedPainter.fillRect(QRect(0,0, 75, 75), Qt::blue);
cachedPainter.fillRect(QRect(10,10, 55, 55), Qt::red);
cachedPainter.drawEllipse(QRect(10,10, 55, 55));
QPainter widgetPainter(this);
widgetPainter.drawImage(QPoint(95, 10), cache);
}
}
};
class Style : public QWidget {
public:
QPushButton *button;
QLineEdit *lineEdit;
QSlider *slider;
QHBoxLayout *row1;
Style() {
row1 = new QHBoxLayout();
setLayout(row1);
button = new QPushButton();
button->setText("Test Button");
row1->addWidget(button);
lineEdit = new QLineEdit();
lineEdit->setText("Test Lineedit");
row1->addWidget(lineEdit);
slider = new QSlider();
row1->addWidget(slider);
row1->addWidget(new QSpinBox);
row1->addWidget(new QScrollBar);
QTabBar *tab = new QTabBar();
tab->addTab("Foo");
tab->addTab("Bar");
row1->addWidget(tab);
}
};
class Fonts : public QWidget
{
public:
void paintEvent(QPaintEvent *event)
{
QPainter painter(this);
int y = 40;
for (int fontSize = 2; fontSize < 18; fontSize += 2) {
QFont font;
font.setPointSize(fontSize);
QString string = QString(QStringLiteral("%1 The quick brown fox jumped over the lazy Doug.")).arg(fontSize);
painter.setFont(font);
painter.drawText(10, y, string);
y += (fontSize * 2.5);
}
}
};
template <typename T>
void apiTestdevicePixelRatioGetter()
{
if (0) {
T *t = 0;
t->devicePixelRatio();
}
}
template <typename T>
void apiTestdevicePixelRatioSetter()
{
if (0) {
T *t = 0;
t->setDevicePixelRatio(2.0);
}
}
void apiTest()
{
// compile call to devicePixelRatio getter and setter (verify spelling)
apiTestdevicePixelRatioGetter<QWindow>();
apiTestdevicePixelRatioGetter<QScreen>();
apiTestdevicePixelRatioGetter<QGuiApplication>();
apiTestdevicePixelRatioGetter<QImage>();
apiTestdevicePixelRatioSetter<QImage>();
apiTestdevicePixelRatioGetter<QPixmap>();
apiTestdevicePixelRatioSetter<QPixmap>();
}
int main(int argc, char **argv)
{
qputenv("QT_HIGHDPI_AWARE", "1");
QApplication app(argc, argv);
PixmapPainter pixmapPainter;
// Enable for lots of pixmap drawing
pixmapPainter.show();
Labels label;
label.resize(200, 200);
label.show();
MainWindow mainWindow;
mainWindow.show();
StandardIcons icons;
icons.resize(510, 510);
icons.show();
Caching caching;
caching.resize(300, 300);
caching.show();
Style style;
style.show();
Fonts fonts;
fonts.show();
return app.exec();
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -121,6 +121,7 @@ static void printHelp()
" -commands Displays all available commands\n"
" -w Width of the paintdevice\n"
" -h Height of the paintdevice\n"
" -scalefactor Scale factor (device pixel ratio) of the paintdevice\n"
" -cmp Show the reference picture\n"
" -bg-white No checkers background\n");
}
@ -238,6 +239,8 @@ int main(int argc, char **argv)
bool highres = false;
bool show_cmp = false;
int width = 800, height = 800;
int scaledWidth = width, scaledHeight = height;
qreal scalefactor = 1.0;
bool verboseMode = false;
#ifndef QT_NO_OPENGL
@ -328,6 +331,9 @@ int main(int argc, char **argv)
} else if (option == "h") {
Q_ASSERT_X(i + 1 < argc, "main", "-h must be followed by a value");
height = atoi(argv[++i]);
} else if (option == "scalefactor") {
Q_ASSERT_X(i + 1 < argc, "main", "-scalefactor must be followed by a value");
scalefactor = atof(argv[++i]);
} else if (option == "cmp") {
show_cmp = true;
} else if (option == "bg-white") {
@ -350,6 +356,8 @@ int main(int argc, char **argv)
#endif
}
}
scaledWidth = width * scalefactor;
scaledHeight = height * scalefactor;
PaintCommands pcmd(QStringList(), 800, 800);
pcmd.setVerboseMode(verboseMode);
@ -514,7 +522,8 @@ int main(int argc, char **argv)
#endif
case PixmapType:
{
QPixmap pixmap(width, height);
QPixmap pixmap(scaledWidth, scaledHeight);
pixmap.setDevicePixelRatio(scalefactor);
pixmap.fill(Qt::white);
QPainter pt(&pixmap);
pcmd.setPainter(&pt);
@ -527,7 +536,8 @@ int main(int argc, char **argv)
case BitmapType:
{
QBitmap bitmap(width, height);
QBitmap bitmap(scaledWidth, scaledHeight);
bitmap.setDevicePixelRatio(scalefactor);
QPainter pt(&bitmap);
pcmd.setPainter(&pt);
pcmd.setFilePath(fileinfo.absolutePath());
@ -547,9 +557,10 @@ int main(int argc, char **argv)
case ImageType:
{
qDebug() << "Creating image";
QImage image(width, height, type == ImageMonoType
QImage image(scaledWidth, scaledHeight, type == ImageMonoType
? QImage::Format_MonoLSB
: imageFormat);
image.setDevicePixelRatio(scalefactor);
image.fill(0);
QPainter pt(&image);
pcmd.setPainter(&pt);
@ -557,6 +568,7 @@ int main(int argc, char **argv)
pcmd.runCommands();
pt.end();
image.convertToFormat(QImage::Format_ARGB32).save("output_image.png", "PNG");
image.setDevicePixelRatio(1.0); // reset scale factor: display "large" image.
#ifndef CONSOLE_APPLICATION
QLabel *label = createLabel();
label->setPixmap(QPixmap::fromImage(image));