diff --git a/src/declarativeimports/core/framesvgitem.cpp b/src/declarativeimports/core/framesvgitem.cpp index dae8a4f9d..e2a078903 100644 --- a/src/declarativeimports/core/framesvgitem.cpp +++ b/src/declarativeimports/core/framesvgitem.cpp @@ -492,7 +492,12 @@ void FrameSvgItem::updateDevicePixelRatio() { //devicepixelratio is always set integer in the svg, so needs at least 192dpi to double up. //(it needs to be integer to have lines contained inside a svg piece to keep being pixel aligned) - m_frameSvg->setDevicePixelRatio(qMax(1.0, floor(m_units.devicePixelRatio()))); + if (window()) { + m_frameSvg->setDevicePixelRatio(qMax(1.0, floor(window()->devicePixelRatio()))); + } else { + m_frameSvg->setDevicePixelRatio(qMax(1.0, floor(qApp->devicePixelRatio()))); + } + m_frameSvg->setScaleFactor(qMax(1.0, floor(m_units.devicePixelRatio()))); m_textureChanged = true; } diff --git a/src/declarativeimports/core/iconitem.cpp b/src/declarativeimports/core/iconitem.cpp index d653bf382..42f4bc8d4 100644 --- a/src/declarativeimports/core/iconitem.cpp +++ b/src/declarativeimports/core/iconitem.cpp @@ -115,6 +115,7 @@ void IconItem::setSource(const QVariant &source) if (!m_svgIcon) { m_svgIcon = new Plasma::Svg(this); m_svgIcon->setColorGroup(m_colorGroup); + m_svgIcon->setDevicePixelRatio((window() ? window()->devicePixelRatio() : qApp->devicePixelRatio())); } //try as a svg icon m_svgIcon->setImagePath("icons/" + source.toString().split("-").first()); @@ -322,7 +323,7 @@ void IconItem::loadPixmap() m_svgIcon->resize(size, size); result = m_svgIcon->pixmap(m_source.toString()); } else if (!m_icon.isNull()) { - result = m_icon.pixmap(QSize(size, size)); + result = m_icon.pixmap(QSize(size, size) * (window() ? window()->devicePixelRatio() : qApp->devicePixelRatio())); } else if (!m_pixmapIcon.isNull()) { result = m_pixmapIcon; } else if (!m_imageIcon.isNull()) { diff --git a/src/declarativeimports/core/svgitem.cpp b/src/declarativeimports/core/svgitem.cpp index 570c1c370..849c85f39 100644 --- a/src/declarativeimports/core/svgitem.cpp +++ b/src/declarativeimports/core/svgitem.cpp @@ -198,7 +198,12 @@ void SvgItem::updateDevicePixelRatio() if (m_svg) { //devicepixelratio is always set integer in the svg, so needs at least 192dpi to double up. //(it needs to be integer to have lines contained inside a svg piece to keep being pixel aligned) - m_svg.data()->setDevicePixelRatio(qMax(1.0, floor(m_units.devicePixelRatio()))); + if (window()) { + m_svg.data()->setDevicePixelRatio(qMax(1.0, floor(window()->devicePixelRatio()))); + } else { + m_svg.data()->setDevicePixelRatio(qMax(1.0, floor(qApp->devicePixelRatio()))); + } + m_svg.data()->setScaleFactor(qMax(1.0, floor(m_units.devicePixelRatio()))); } } diff --git a/src/declarativeimports/core/units.cpp b/src/declarativeimports/core/units.cpp index 6cad17acf..84afccdbe 100644 --- a/src/declarativeimports/core/units.cpp +++ b/src/declarativeimports/core/units.cpp @@ -206,6 +206,7 @@ int Units::largeSpacing() const void Units::updateSpacing() { int gridUnit = QFontMetrics(QGuiApplication::font()).boundingRect("M").height(); + if (gridUnit % 2 != 0) { gridUnit++; } diff --git a/src/plasma/framesvg.cpp b/src/plasma/framesvg.cpp index 1bb3510bb..e4093d7e3 100644 --- a/src/plasma/framesvg.cpp +++ b/src/plasma/framesvg.cpp @@ -791,7 +791,7 @@ void FrameSvgPrivate::generateBackground(FrameData *frame) void FrameSvgPrivate::generateFrameBackground(FrameData *frame) { //qDebug() << "generating background"; - const QSize size = frameSize(frame).toSize(); + const QSize size = frameSize(frame).toSize() * q->devicePixelRatio(); if (!size.isValid()) { #ifndef NDEBUG @@ -820,25 +820,29 @@ void FrameSvgPrivate::generateFrameBackground(FrameData *frame) // Sides const int leftHeight = q->elementSize(prefix % "left").height(); - paintBorder(p, frame, FrameSvg::LeftBorder, QSize(frame->leftWidth, leftHeight), contentRect); - paintBorder(p, frame, FrameSvg::RightBorder, QSize(frame->rightWidth, leftHeight), contentRect); + paintBorder(p, frame, FrameSvg::LeftBorder, QSize(frame->leftWidth, leftHeight) * q->devicePixelRatio(), contentRect); + paintBorder(p, frame, FrameSvg::RightBorder, QSize(frame->rightWidth, leftHeight) * q->devicePixelRatio(), contentRect); const int topWidth = q->elementSize(prefix % "top").width(); - paintBorder(p, frame, FrameSvg::TopBorder, QSize(topWidth, frame->topHeight), contentRect); - paintBorder(p, frame, FrameSvg::BottomBorder, QSize(topWidth, frame->bottomHeight), contentRect); + paintBorder(p, frame, FrameSvg::TopBorder, QSize(topWidth, frame->topHeight) * q->devicePixelRatio(), contentRect); + paintBorder(p, frame, FrameSvg::BottomBorder, QSize(topWidth, frame->bottomHeight) * q->devicePixelRatio(), contentRect); + p.end(); + + frame->cachedBackground.setDevicePixelRatio(q->devicePixelRatio()); } QRect FrameSvgPrivate::contentGeometry(FrameData* frame, const QSize& size) const { - const QSize contentSize(size.width() - frame->leftWidth - frame->rightWidth, size.height() - frame->topHeight - frame->bottomHeight); + const QSize contentSize(size.width() - frame->leftWidth * q->devicePixelRatio() - frame->rightWidth * q->devicePixelRatio(), + size.height() - frame->topHeight * q->devicePixelRatio() - frame->bottomHeight * q->devicePixelRatio()); QRect contentRect(QPoint(0,0), contentSize); if (frame->enabledBorders & FrameSvg::LeftBorder && q->hasElement(prefix % "left")) { - contentRect.translate(frame->leftWidth, 0); + contentRect.translate(frame->leftWidth * q->devicePixelRatio(), 0); } // Corners if (frame->enabledBorders & FrameSvg::TopBorder && q->hasElement(prefix % "top")) { - contentRect.translate(0, frame->topHeight); + contentRect.translate(0, frame->topHeight * q->devicePixelRatio()); } return contentRect; } @@ -859,14 +863,14 @@ void FrameSvgPrivate::paintCenter(QPainter& p, FrameData* frame, const QRect& co if (frame->composeOverBorder) { p.drawTiledPixmap(QRect(QPoint(0, 0), fullSize), center); } else { - p.drawTiledPixmap(FrameSvgHelpers::sectionRect(FrameSvg::NoBorder, contentRect, fullSize), center); + p.drawTiledPixmap(FrameSvgHelpers::sectionRect(FrameSvg::NoBorder, contentRect, fullSize * q->devicePixelRatio()), center); } } else { if (frame->composeOverBorder) { q->paint(&p, QRect(QPoint(0, 0), fullSize), centerElementId); } else { - q->paint(&p, FrameSvgHelpers::sectionRect(FrameSvg::NoBorder, contentRect, fullSize), centerElementId); + q->paint(&p, FrameSvgHelpers::sectionRect(FrameSvg::NoBorder, contentRect, fullSize * q->devicePixelRatio()), centerElementId); } } } @@ -883,7 +887,7 @@ void FrameSvgPrivate::paintBorder(QPainter& p, FrameData* frame, const FrameSvg: QString side = prefix % FrameSvgHelpers::borderToElementId(borders); if (frame->enabledBorders & borders && q->hasElement(side) && !size.isEmpty()) { if (frame->stretchBorders) { - q->paint(&p, FrameSvgHelpers::sectionRect(borders, contentRect, frame->frameSize), side); + q->paint(&p, FrameSvgHelpers::sectionRect(borders, contentRect, frame->frameSize * q->devicePixelRatio()), side); } else { QPixmap px(size); px.fill(Qt::transparent); @@ -892,7 +896,7 @@ void FrameSvgPrivate::paintBorder(QPainter& p, FrameData* frame, const FrameSvg: sidePainter.setCompositionMode(QPainter::CompositionMode_Source); q->paint(&sidePainter, QRect(QPoint(0, 0), size), side); - p.drawTiledPixmap(FrameSvgHelpers::sectionRect(borders, contentRect, frame->frameSize), px); + p.drawTiledPixmap(FrameSvgHelpers::sectionRect(borders, contentRect, frame->frameSize * q->devicePixelRatio()), px); } } } @@ -901,7 +905,7 @@ void FrameSvgPrivate::paintCorner(QPainter& p, FrameData* frame, Plasma::FrameSv { QString corner = prefix % FrameSvgHelpers::borderToElementId(border); if (frame->enabledBorders & border && q->hasElement(corner)) { - q->paint(&p, FrameSvgHelpers::sectionRect(border, contentRect, frame->frameSize), corner); + q->paint(&p, FrameSvgHelpers::sectionRect(border, contentRect, frame->frameSize * q->devicePixelRatio()), corner); } } @@ -909,7 +913,7 @@ QString FrameSvgPrivate::cacheId(FrameData *frame, const QString &prefixToSave) { const QSize size = frameSize(frame).toSize(); const QLatin1Char s('_'); - return QString::number(frame->enabledBorders) % s % QString::number(size.width()) % s % QString::number(size.height()) % s % prefixToSave % s % q->imagePath(); + return QString::number(frame->enabledBorders) % s % QString::number(size.width()) % s % QString::number(size.height()) % s % QString::number(q->scaleFactor()) % s % QString::number(q->devicePixelRatio()) % s % prefixToSave % s % q->imagePath(); } void FrameSvgPrivate::cacheFrame(const QString &prefixToSave, const QPixmap &background, const QPixmap &overlay) diff --git a/src/plasma/private/svg_p.h b/src/plasma/private/svg_p.h index a31d0acd1..ab91c42fd 100644 --- a/src/plasma/private/svg_p.h +++ b/src/plasma/private/svg_p.h @@ -72,7 +72,7 @@ public: Theme *actualTheme(); Theme *cacheAndColorsTheme(); - QPixmap findInCache(const QString &elementId, const QSizeF &s = QSizeF()); + QPixmap findInCache(const QString &elementId, qreal ratio, const QSizeF &s = QSizeF()); void createRenderer(); void eraseRenderer(); @@ -109,6 +109,7 @@ public: Theme::ColorGroup colorGroup; unsigned int lastModified; qreal devicePixelRatio; + qreal scaleFactor; bool multipleImages : 1; bool themed : 1; bool fromCurrentTheme : 1; diff --git a/src/plasma/svg.cpp b/src/plasma/svg.cpp index 0a0db5e80..2cb6472d2 100644 --- a/src/plasma/svg.cpp +++ b/src/plasma/svg.cpp @@ -129,8 +129,8 @@ bool SharedSvgRenderer::load( } #define QLSEP QLatin1Char('_') -#define CACHE_ID_WITH_SIZE(size, id, devicePixelRatio) QString::number(int(size.width())) % QLSEP % QString::number(int(size.height())) % QLSEP % id % QLSEP % QString::number(int(devicePixelRatio)) -#define CACHE_ID_NATURAL_SIZE(id, devicePixelRatio) QLatin1Literal("Natural") % QLSEP % id % QLSEP % QString::number(int(devicePixelRatio)) +#define CACHE_ID_WITH_SIZE(size, id, devicePixelRatio) QString::number(int(size.width())) % QLSEP % QString::number(int(size.height())) % QLSEP % id % QLSEP % QLSEP % QString::number(int(devicePixelRatio)) +#define CACHE_ID_NATURAL_SIZE(id, devicePixelRatio) QLatin1Literal("Natural") % QLSEP % id % QLSEP % QLSEP % QString::number(int(devicePixelRatio)) SvgPrivate::SvgPrivate(Svg *svg) : q(svg), @@ -139,6 +139,7 @@ SvgPrivate::SvgPrivate(Svg *svg) colorGroup(Plasma::Theme::NormalColorGroup), lastModified(0), devicePixelRatio(1.0), + scaleFactor(1.0), multipleImages(false), themed(false), fromCurrentTheme(false), @@ -237,7 +238,7 @@ bool SvgPrivate::setImagePath(const QString &imagePath) naturalSize = rect.size(); } else { createRenderer(); - naturalSize = renderer->defaultSize() * devicePixelRatio; + naturalSize = renderer->defaultSize() * scaleFactor; //qDebug() << "natural size for" << path << "from renderer is" << naturalSize; cacheAndColorsTheme()->insertIntoRectsCache(path, "_Natural", QRectF(QPointF(0, 0), naturalSize)); //qDebug() << "natural size for" << path << "from cache is" << naturalSize; @@ -279,7 +280,7 @@ Theme *SvgPrivate::cacheAndColorsTheme() } } -QPixmap SvgPrivate::findInCache(const QString &elementId, const QSizeF &s) +QPixmap SvgPrivate::findInCache(const QString &elementId, qreal ratio, const QSizeF &s) { QSize size; QString actualElementId; @@ -287,7 +288,7 @@ QPixmap SvgPrivate::findInCache(const QString &elementId, const QSizeF &s) if (elementsWithSizeHints.isEmpty()) { // Fetch all size hinted element ids from the theme's rect cache // and store them locally. - QRegExp sizeHintedKeyExpr(CACHE_ID_NATURAL_SIZE("(\\d+)-(\\d+)-(.+)", devicePixelRatio)); + QRegExp sizeHintedKeyExpr(CACHE_ID_NATURAL_SIZE("(\\d+)-(\\d+)-(.+)", ratio)); foreach (const QString &key, cacheAndColorsTheme()->listCachedRectKeys(path)) { if (sizeHintedKeyExpr.exactMatch(key)) { @@ -317,7 +318,7 @@ QPixmap SvgPrivate::findInCache(const QString &elementId, const QSizeF &s) Q_FOREACH (const QSize &hint, elementSizeHints) { - if (hint.width() >= s.width() && hint.height() >= s.height() && + if (hint.width() >= s.width() * ratio && hint.height() >= s.height() * ratio && (!bestFit.isValid() || (bestFit.width() * bestFit.height()) > (hint.width() * hint.height()))) { bestFit = hint; @@ -336,9 +337,9 @@ QPixmap SvgPrivate::findInCache(const QString &elementId, const QSizeF &s) } if (elementId.isEmpty() || (multipleImages && s.isValid())) { - size = s.toSize(); + size = s.toSize() * ratio; } else { - size = elementRect(actualElementId).size().toSize(); + size = elementRect(actualElementId).size().toSize() * ratio; } if (size.isEmpty()) { @@ -355,6 +356,7 @@ QPixmap SvgPrivate::findInCache(const QString &elementId, const QSizeF &s) QPixmap p; if (cacheRendering && cacheAndColorsTheme()->findInCache(id, p, lastModified)) { + p.setDevicePixelRatio(ratio); //qDebug() << "found cached version of " << id << p.size(); return p; } @@ -382,6 +384,7 @@ QPixmap SvgPrivate::findInCache(const QString &elementId, const QSizeF &s) } renderPainter.end(); + p.setDevicePixelRatio(ratio); // Apply current color scheme if the svg asks for it if (applyColors) { @@ -543,7 +546,7 @@ QRectF SvgPrivate::findAndCacheElementRect(const QString &elementId) qreal dy = size.height() / naturalSize.height(); elementRect = QRectF(elementRect.x() * dx, elementRect.y() * dy, - elementRect.width() * dx * devicePixelRatio, elementRect.height() * dy * devicePixelRatio); + elementRect.width() * dx * scaleFactor, elementRect.height() * dy * scaleFactor); cacheAndColorsTheme()->insertIntoRectsCache(path, id, elementRect); @@ -707,8 +710,8 @@ void Svg::setDevicePixelRatio(qreal ratio) } d->devicePixelRatio = floor(ratio); + emit repaintNeeded(); - emit sizeChanged(); } qreal Svg::devicePixelRatio() @@ -716,6 +719,27 @@ qreal Svg::devicePixelRatio() return d->devicePixelRatio; } + +void Svg::setScaleFactor(qreal ratio) +{ + //be completely integer for now + //devicepixelratio is always set integer in the svg, so needs at least 192dpi to double up. + //(it needs to be integer to have lines contained inside a svg piece to keep being pixel aligned) + if (floor(d->scaleFactor) == floor(ratio)) { + return; + } + + d->scaleFactor = floor(ratio); + + emit repaintNeeded(); + emit sizeChanged(); +} + +qreal Svg::scaleFactor() const +{ + return d->scaleFactor; +} + void Svg::setColorGroup(Plasma::Theme::ColorGroup group) { if (d->colorGroup == group) { @@ -736,28 +760,30 @@ Plasma::Theme::ColorGroup Svg::colorGroup() const QPixmap Svg::pixmap(const QString &elementID) { if (elementID.isNull() || d->multipleImages) { - return d->findInCache(elementID, size()); + return d->findInCache(elementID, d->devicePixelRatio, size()); } else { - return d->findInCache(elementID); + return d->findInCache(elementID, d->devicePixelRatio); } } QImage Svg::image(const QSize &size, const QString &elementID) { - QPixmap pix(d->findInCache(elementID, size)); + QPixmap pix(d->findInCache(elementID, d->devicePixelRatio, size)); return pix.toImage(); } void Svg::paint(QPainter *painter, const QPointF &point, const QString &elementID) { - QPixmap pix((elementID.isNull() || d->multipleImages) ? d->findInCache(elementID, size()) : - d->findInCache(elementID)); + Q_ASSERT(painter->device()); + const int ratio = painter->device()->devicePixelRatio(); + QPixmap pix((elementID.isNull() || d->multipleImages) ? d->findInCache(elementID, ratio, size()) : + d->findInCache(elementID, ratio)); if (pix.isNull()) { return; } - painter->drawPixmap(QRectF(point, pix.size()), pix, QRectF(QPointF(0, 0), pix.size())); + painter->drawPixmap(QRectF(point, size()), pix, QRectF(QPointF(0, 0), pix.size())); } void Svg::paint(QPainter *painter, int x, int y, const QString &elementID) @@ -767,13 +793,18 @@ void Svg::paint(QPainter *painter, int x, int y, const QString &elementID) void Svg::paint(QPainter *painter, const QRectF &rect, const QString &elementID) { - QPixmap pix(d->findInCache(elementID, rect.size())); - painter->drawPixmap(QRectF(rect.topLeft(), pix.size()), pix, QRectF(QPointF(0, 0), pix.size())); + Q_ASSERT(painter->device()); + const int ratio = painter->device()->devicePixelRatio(); + QPixmap pix(d->findInCache(elementID, ratio, rect.size())); + + painter->drawPixmap(QRectF(rect.topLeft(), rect.size()), pix, QRectF(QPointF(0, 0), pix.size())); } void Svg::paint(QPainter *painter, int x, int y, int width, int height, const QString &elementID) { - QPixmap pix(d->findInCache(elementID, QSizeF(width, height))); + Q_ASSERT(painter->device()); + const int ratio = painter->device()->devicePixelRatio(); + QPixmap pix(d->findInCache(elementID, ratio, QSizeF(width, height))); painter->drawPixmap(x, y, pix, 0, 0, pix.size().width(), pix.size().height()); } diff --git a/src/plasma/svg.h b/src/plasma/svg.h index 0bcbd7a3d..92696b990 100644 --- a/src/plasma/svg.h +++ b/src/plasma/svg.h @@ -85,7 +85,9 @@ public: /** * Set the device pixel ratio for the Svg. This is the ratio between * image pixels and device-independent pixels. - * The default value is 1.0. + * The Svg will produce pixmaps scaled by devicePixelRatio, but all the sizes and element + * rects will not be altered. + * The default value is 1.0 and the scale will be done rounded to the floor integer * Setting it to something more, will make all the elements of this svg appear bigger. */ void setDevicePixelRatio(qreal ratio); @@ -95,6 +97,21 @@ public: */ qreal devicePixelRatio(); + /** + * Settng a scale factor greater than one it will result in final images scaled by it. + * Unlike devicePixelRatio, every size and element rect will be scaled accordingly. + * @return how much to scale the rendered image. + */ + qreal scaleFactor() const; + + /** + * Settng a scale factor greater than one it will result in final images scaled by it. + * Unlike devicePixelRatio, every size and element rect will be scaled accordingly. + * The default value is 1.0 and the scale will be done rounded to the floor integer. + * @param how much to scale the Svg + */ + void setScaleFactor(qreal factor); + /** * Set a color group for the Svg. * if the Svg uses stylesheets and has elements