diff --git a/core_lib/src/camerapainter.cpp b/core_lib/src/camerapainter.cpp index e33c0ebbcd..ca4a40993f 100644 --- a/core_lib/src/camerapainter.cpp +++ b/core_lib/src/camerapainter.cpp @@ -28,9 +28,21 @@ GNU General Public License for more details. #include "painterutils.h" -CameraPainter::CameraPainter() +CameraPainter::CameraPainter(QPixmap& canvas) : mCanvas(canvas) { + reset(); +} +void CameraPainter::reset() +{ + mCameraPixmap = QPixmap(mCanvas.size()); + mCameraPixmap.setDevicePixelRatio(mCanvas.devicePixelRatioF()); + mCameraPixmap.fill(Qt::transparent); +} + +void CameraPainter::resetCache() +{ + mCameraCacheValid = false; } void CameraPainter::preparePainter(const Object* object, @@ -52,50 +64,51 @@ void CameraPainter::preparePainter(const Object* object, mViewScale = viewScale; } -void CameraPainter::paint() const +void CameraPainter::paint(const QRect& blitRect) { QPainter painter; - initializePainter(painter, *mCanvas); - paintVisuals(painter); + initializePainter(painter, mCanvas, blitRect, false); + paintVisuals(painter, blitRect); + + mCameraCacheValid = true; } -void CameraPainter::paintCached() +void CameraPainter::paintCached(const QRect& blitRect) { - if (!mCachedPaint) { - QPainter tempPainter; - QPixmap cachedPixmap(mCanvas->size()); - cachedPixmap.fill(Qt::transparent); - initializePainter(tempPainter, cachedPixmap); - - paintVisuals(tempPainter); - mCachedPaint.reset(new QPixmap(cachedPixmap)); - tempPainter.end(); - } - QPainter painter; - initializePainter(painter, *mCanvas); - painter.drawPixmap(0, 0, *mCachedPaint.get()); - painter.end(); + // As always, initialize the painter with the canvas image, as this is what we'll paint on + // In this case though because the canvas has already been painted, we're not interested in + // having the blitter clear the image again, as that would remove our previous painted data, ie. strokes... + initializePainter(painter, mCanvas, blitRect, false); + if (!mCameraCacheValid) { + paintVisuals(painter, blitRect); + painter.end(); + mCameraCacheValid = true; + } else { + painter.setWorldMatrixEnabled(false); + painter.drawPixmap(mZeroPoint, mCameraPixmap); + painter.setWorldMatrixEnabled(true); + painter.end(); + } } -void CameraPainter::setCanvas(QPixmap* canvas) +void CameraPainter::initializePainter(QPainter& painter, QPixmap& pixmap, const QRect& blitRect, bool blitEnabled) { - mCanvas = canvas; -} + painter.begin(&pixmap); -void CameraPainter::resetCache() -{ - mCachedPaint.reset(); -} + if (blitEnabled) { + painter.setCompositionMode(QPainter::CompositionMode_Clear); + painter.fillRect(blitRect, Qt::transparent); + // Surface has been cleared and is ready to be painted on + painter.setCompositionMode(QPainter::CompositionMode_SourceOver); + } -void CameraPainter::initializePainter(QPainter& painter, QPixmap& pixmap) const -{ - painter.begin(&pixmap); + painter.setClipRect(blitRect); + painter.setWorldMatrixEnabled(true); painter.setWorldTransform(mViewTransform); - painter.setWorldMatrixEnabled(false); } -void CameraPainter::paintVisuals(QPainter& painter) const +void CameraPainter::paintVisuals(QPainter& painter, const QRect& blitRect) { LayerCamera* cameraLayerBelow = static_cast(mObject->getLayerBelow(mCurrentLayerIndex, Layer::CAMERA)); @@ -105,6 +118,9 @@ void CameraPainter::paintVisuals(QPainter& painter) const if (mLayerVisibility == LayerVisibility::CURRENTONLY && currentLayer->type() != Layer::CAMERA) { return; } + QPainter visualsPainter; + initializePainter(visualsPainter, mCameraPixmap, blitRect, true); + if (!mIsPlaying || mOnionSkinOptions.enabledWhilePlaying) { int startLayerI = 0; @@ -117,15 +133,15 @@ void CameraPainter::paintVisuals(QPainter& painter) const bool isCurrentLayer = cameraLayer == cameraLayerBelow; - painter.save(); - painter.setOpacity(1); + visualsPainter.save(); + visualsPainter.setOpacity(1); if (mLayerVisibility == LayerVisibility::RELATED && !isCurrentLayer) { - painter.setOpacity(calculateRelativeOpacityForLayer(mCurrentLayerIndex, i, mRelativeLayerOpacityThreshold)); + visualsPainter.setOpacity(calculateRelativeOpacityForLayer(mCurrentLayerIndex, i, mRelativeLayerOpacityThreshold)); } - paintOnionSkinning(painter, cameraLayer); + paintOnionSkinning(visualsPainter, cameraLayer); - painter.restore(); + visualsPainter.restore(); } } @@ -133,10 +149,13 @@ void CameraPainter::paintVisuals(QPainter& painter) const QTransform camTransform = cameraLayerBelow->getViewAtFrame(mFrameIndex); QRect cameraRect = cameraLayerBelow->getViewRect(); - paintBorder(painter, camTransform, cameraRect); + paintBorder(visualsPainter, camTransform, cameraRect); + + painter.setWorldMatrixEnabled(false); + painter.drawPixmap(mZeroPoint, mCameraPixmap); } -void CameraPainter::paintBorder(QPainter& painter, const QTransform& camTransform, const QRect& camRect) const +void CameraPainter::paintBorder(QPainter& painter, const QTransform& camTransform, const QRect& camRect) { painter.save(); QRect viewRect = painter.viewport(); @@ -159,12 +178,13 @@ void CameraPainter::paintBorder(QPainter& painter, const QTransform& camTransfor painter.restore(); } -void CameraPainter::paintOnionSkinning(QPainter& painter, const LayerCamera* cameraLayer) const +void CameraPainter::paintOnionSkinning(QPainter& painter, const LayerCamera* cameraLayer) { QPen onionSkinPen; painter.save(); painter.setBrush(Qt::NoBrush); + painter.setWorldMatrixEnabled(false); onionSkinPen.setStyle(Qt::PenStyle::DashLine); mOnionSkinPainter.paint(painter, cameraLayer, mOnionSkinOptions, mFrameIndex, [&] (OnionSkinPaintState state, int onionSkinNumber) { diff --git a/core_lib/src/camerapainter.h b/core_lib/src/camerapainter.h index 1bfa1a9c24..45dcac50f4 100644 --- a/core_lib/src/camerapainter.h +++ b/core_lib/src/camerapainter.h @@ -37,28 +37,31 @@ class KeyFrame; class CameraPainter { public: - explicit CameraPainter(); + explicit CameraPainter(QPixmap& canvas); - void paint() const; - void paintCached(); + void paint(const QRect& blitRect); + void paintCached(const QRect& blitRect); void setOnionSkinPainterOptions(const OnionSkinPainterOptions& options) { mOnionSkinOptions = options; } - void setCanvas(QPixmap* canvas); void preparePainter(const Object* object, int layerIndex, int frameIndex, const QTransform& transform, bool isPlaying, LayerVisibility layerVisibility, float relativeLayerOpacityThreshold, qreal viewScale); + void reset(); + void resetCache(); private: - void initializePainter(QPainter& painter, QPixmap& pixmap) const; - void paintVisuals(QPainter& painter) const; - void paintBorder(QPainter& painter, const QTransform& camTransform, const QRect& camRect) const; - void paintOnionSkinning(QPainter& painter, const LayerCamera* cameraLayer) const; + void initializePainter(QPainter& painter, QPixmap& pixmap, const QRect& blitRect, bool blitEnabled); + void paintVisuals(QPainter& painter, const QRect& blitRect); + void paintBorder(QPainter& painter, const QTransform& camTransform, const QRect& camRect); + void paintOnionSkinning(QPainter& painter, const LayerCamera* cameraLayer); const Object* mObject = nullptr; - QPixmap* mCanvas = nullptr; + QPixmap& mCanvas; - std::unique_ptr mCachedPaint = nullptr; + QPixmap mCameraPixmap; QTransform mViewTransform; + const QPointF mZeroPoint; + OnionSkinSubPainter mOnionSkinPainter; OnionSkinPainterOptions mOnionSkinOptions; @@ -69,6 +72,7 @@ class CameraPainter qreal mViewScale = 0; bool mIsPlaying = false; + bool mCameraCacheValid = false; }; #endif // CAMERAPAINTER_H diff --git a/core_lib/src/interface/backgroundwidget.cpp b/core_lib/src/interface/backgroundwidget.cpp index ebee13a2b6..b51aad4127 100644 --- a/core_lib/src/interface/backgroundwidget.cpp +++ b/core_lib/src/interface/backgroundwidget.cpp @@ -19,6 +19,7 @@ GNU General Public License for more details. #include #include +#include BackgroundWidget::BackgroundWidget(QWidget* parent) : QWidget(parent) @@ -66,11 +67,13 @@ void BackgroundWidget::settingUpdated(SETTING setting) } } -void BackgroundWidget::paintEvent(QPaintEvent *) +void BackgroundWidget::paintEvent(QPaintEvent* event) { QStyleOption opt; opt.initFrom(this); QPainter painter(this); + painter.setClipRect(event->rect()); + style()->drawPrimitive(QStyle::PE_Widget, &opt, &painter, this); if (mHasShadow) @@ -112,7 +115,7 @@ void BackgroundWidget::loadBackgroundStyle() setStyleSheet(mStyle); } -void BackgroundWidget::drawShadow( QPainter& painter ) +void BackgroundWidget::drawShadow(QPainter& painter) { int radius1 = 12; int radius2 = 8; diff --git a/core_lib/src/interface/backgroundwidget.h b/core_lib/src/interface/backgroundwidget.h index 881a41a397..9c58fc11ff 100644 --- a/core_lib/src/interface/backgroundwidget.h +++ b/core_lib/src/interface/backgroundwidget.h @@ -35,7 +35,7 @@ public slots: protected: - void paintEvent( QPaintEvent* ) override; + void paintEvent(QPaintEvent* event) override; private slots: diff --git a/core_lib/src/interface/scribblearea.cpp b/core_lib/src/interface/scribblearea.cpp index 028068eda7..7e6d58ede8 100644 --- a/core_lib/src/interface/scribblearea.cpp +++ b/core_lib/src/interface/scribblearea.cpp @@ -45,7 +45,7 @@ GNU General Public License for more details. #include "selectionmanager.h" #include "overlaymanager.h" -ScribbleArea::ScribbleArea(QWidget* parent) : QWidget(parent), mCanvasPainter(mCanvas) +ScribbleArea::ScribbleArea(QWidget* parent) : QWidget(parent), mCanvasPainter(mCanvas), mCameraPainter(mCanvas) { setObjectName("ScribbleArea"); @@ -825,6 +825,7 @@ void ScribbleArea::resizeEvent(QResizeEvent* event) invalidateCacheForFrame(mEditor->currentFrame()); invalidatePainterCaches(); mCanvasPainter.reset(); + mCameraPainter.reset(); } void ScribbleArea::showLayerNotVisibleWarning() @@ -1010,7 +1011,7 @@ void ScribbleArea::paintEvent(QPaintEvent* event) prepOverlays(currentFrame); mCanvasPainter.paintCached(event->rect()); - mCameraPainter.paintCached(); + mCameraPainter.paintCached(event->rect()); } if (currentTool()->type() == MOVE) @@ -1193,7 +1194,6 @@ void ScribbleArea::prepCameraPainter(int frame) onionSkinOptions.minOpacity = mPrefs->getInt(SETTING::ONION_MIN_OPACITY); mCameraPainter.setOnionSkinPainterOptions(onionSkinOptions); - mCameraPainter.setCanvas(&mCanvas); } void ScribbleArea::prepCanvas(int frame, QRect rect) @@ -1240,7 +1240,7 @@ void ScribbleArea::drawCanvas(int frame, QRect rect) prepCameraPainter(frame); prepOverlays(frame); mCanvasPainter.paint(rect); - mCameraPainter.paint(); + mCameraPainter.paint(rect); } void ScribbleArea::setGaussianGradient(QGradient &gradient, QColor color, qreal opacity, qreal offset)