Skip to content

Commit

Permalink
Paintable: caching the rendered SVG.
Browse files Browse the repository at this point in the history
  • Loading branch information
daschuer committed Sep 21, 2024
1 parent 5458b4b commit a248708
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 25 deletions.
61 changes: 36 additions & 25 deletions src/widget/paintable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,39 +100,43 @@ bool Paintable::isNull() const {
}

QSize Paintable::size() const {
if (m_pSvg) {
return m_pSvg->defaultSize();
}
if (m_pPixmap) {
return m_pPixmap->size();
} else if (m_pSvg) {
return m_pSvg->defaultSize();
}
return QSize();
}

int Paintable::width() const {
if (m_pPixmap) {
return m_pPixmap->width();
} else if (m_pSvg) {
if (m_pSvg) {
QSize size = m_pSvg->defaultSize();
return size.width();
}
if (m_pPixmap) {
return m_pPixmap->width();
}
return 0;
}

int Paintable::height() const {
if (m_pPixmap) {
return m_pPixmap->height();
} else if (m_pSvg) {
if (m_pSvg) {
QSize size = m_pSvg->defaultSize();
return size.height();
}
if (m_pPixmap) {
return m_pPixmap->height();
}
return 0;
}

QRectF Paintable::rect() const {
if (m_pSvg) {
return QRectF(QPointF(0, 0), m_pSvg->defaultSize());
}
if (m_pPixmap) {
return m_pPixmap->rect();
} else if (m_pSvg) {
return QRectF(QPointF(0, 0), m_pSvg->defaultSize());
}
return QRectF();
}
Expand Down Expand Up @@ -247,6 +251,27 @@ void Paintable::drawInternal(const QRectF& targetRect, QPainter* pPainter,
const QRectF& sourceRect) {
// qDebug() << "Paintable::drawInternal" << DrawModeToString(m_drawMode)
// << targetRect << sourceRect;
if (m_pSvg) {
if (m_drawMode == TILE) {
qWarning() << "Tiled SVG should have been rendered to pixmap!";
} else {
if (!m_pPixmap ||
m_pPixmap->size() != targetRect.size().toSize() ||
m_lastSourceRect != sourceRect) {
// qDebug() << "Paintable cache miss";
qreal devicePixelRatio = pPainter->device()->devicePixelRatio();
m_pPixmap = std::make_unique<QPixmap>(targetRect.size().toSize());
m_pPixmap->setDevicePixelRatio(devicePixelRatio);
m_pPixmap->fill(Qt::transparent);
auto pixmapPainter = QPainter(m_pPixmap.get());
m_pSvg->setViewBox(sourceRect);
m_pSvg->render(&pixmapPainter);
m_lastSourceRect = sourceRect;
}
pPainter->drawPixmap(targetRect.topLeft(), *m_pPixmap);
}
return;
}
if (m_pPixmap) {
// Note: Qt rounds the target rect to device pixels internally
// using roundInDeviceCoordinates()
Expand All @@ -263,21 +288,7 @@ void Paintable::drawInternal(const QRectF& targetRect, QPainter* pPainter,
pPainter->drawPixmap(targetRect, *m_pPixmap, sourceRect);
}
}
} else if (m_pSvg) {
if (m_drawMode == TILE) {
qWarning() << "Tiled SVG should have been rendered to pixmap!";
} else {
// NOTE(rryan): QSvgRenderer render does not clip for us -- it
// applies a world transformation using viewBox and renders the
// entire SVG to the painter. We save/restore the QPainter in case
// there is an existing clip region (I don't know of any Mixxx code
// that uses one but we may in the future).
PainterScope PainterScope(pPainter);
pPainter->setClipping(true);
pPainter->setClipRect(targetRect);
m_pSvg->setViewBox(sourceRect);
m_pSvg->render(pPainter, targetRect);
}
return;
}
}

Expand Down
1 change: 1 addition & 0 deletions src/widget/paintable.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,5 @@ class Paintable {
std::unique_ptr<QPixmap> m_pPixmap;
std::unique_ptr<QSvgRenderer> m_pSvg;
DrawMode m_drawMode;
QRectF m_lastSourceRect;
};

0 comments on commit a248708

Please sign in to comment.