From 061e0852fc4aeb320bd4840cac2231f0280970c8 Mon Sep 17 00:00:00 2001 From: MrStevns Date: Sun, 10 Dec 2023 10:30:42 +0100 Subject: [PATCH] Regression - #1799: Fix pen dabs being added to each other Actually the first check in canvas painter would always return true because the blitRect and mTilledBuffer rect are in different coordinate spaces. --- core_lib/src/canvaspainter.cpp | 11 ++------- core_lib/src/canvaspainter.h | 3 --- core_lib/src/interface/scribblearea.cpp | 33 +++++++++++++++---------- core_lib/src/tool/erasertool.cpp | 4 +-- 4 files changed, 24 insertions(+), 27 deletions(-) diff --git a/core_lib/src/canvaspainter.cpp b/core_lib/src/canvaspainter.cpp index 24529ec38..3990e3920 100644 --- a/core_lib/src/canvaspainter.cpp +++ b/core_lib/src/canvaspainter.cpp @@ -300,16 +300,9 @@ void CanvasPainter::paintCurrentBitmapFrame(QPainter& painter, const QRect& blit if (isCurrentLayer && isDrawing) { - // Certain tools require being painted continuously, for example, the Polyline tool. - // The tiled buffer does not update the area outside which it paints, - // so in that case, in order to see the previously laid-down polyline stroke, - // the surrounding area must be drawn again before - // applying the new tiled output on top - if (!blitRect.contains(mTiledBuffer->bounds()) || mOptions.bIgnoreCanvasBuffer) { - currentBitmapPainter.setCompositionMode(QPainter::CompositionMode_Source); - currentBitmapPainter.drawImage(paintedImage->topLeft(), *paintedImage->image()); - } + currentBitmapPainter.drawImage(paintedImage->topLeft(), *paintedImage->image()); + currentBitmapPainter.setCompositionMode(mOptions.cmBufferBlendMode); const auto tiles = mTiledBuffer->tiles(); for (const Tile* tile : tiles) { currentBitmapPainter.drawPixmap(tile->posF(), tile->pixmap()); diff --git a/core_lib/src/canvaspainter.h b/core_lib/src/canvaspainter.h index 99b90c6be..7f1d3c285 100644 --- a/core_lib/src/canvaspainter.h +++ b/core_lib/src/canvaspainter.h @@ -42,9 +42,6 @@ struct CanvasPainterOptions bool bThinLines = false; bool bOutlines = false; - /// When using a tool that can't rely on canvas buffer, - /// for example Polyline because we're continously clearing the surface - bool bIgnoreCanvasBuffer = false; LayerVisibility eLayerVisibility = LayerVisibility::RELATED; float fLayerVisibilityThreshold = 0.f; float scaling = 1.0f; diff --git a/core_lib/src/interface/scribblearea.cpp b/core_lib/src/interface/scribblearea.cpp index 4e8d5e319..d39359c02 100644 --- a/core_lib/src/interface/scribblearea.cpp +++ b/core_lib/src/interface/scribblearea.cpp @@ -202,16 +202,6 @@ void ScribbleArea::onTileUpdated(TiledBuffer* tiledBuffer, Tile* tile) void ScribbleArea::onTileCreated(TiledBuffer* tiledBuffer, Tile* tile) { Q_UNUSED(tiledBuffer) - Layer::LAYER_TYPE layerType = mEditor->layers()->currentLayer()->type(); - if (layerType == Layer::BITMAP) { - const auto& bitmapImage = currentBitmapImage(mEditor->layers()->currentLayer()); - const QImage& image = *bitmapImage->image(); - tile->load(image, bitmapImage->topLeft()); - } else if (layerType == Layer::VECTOR) { - - // Not used, we only use the buffer to paint the stroke before painting the real vector stroke - } - const QRectF& mappedRect = mEditor->view()->getView().mapRect(QRectF(tile->bounds())); update(mappedRect.toAlignedRect()); } @@ -855,7 +845,24 @@ void ScribbleArea::paintBitmapBuffer() BitmapImage* targetImage = currentBitmapImage(layer); if (targetImage != nullptr) { - targetImage->paste(&mTiledBuffer, QPainter::CompositionMode_Source); + QPainter::CompositionMode cm = QPainter::CompositionMode_SourceOver; + switch (currentTool()->type()) + { + case ERASER: + cm = QPainter::CompositionMode_DestinationOut; + break; + case BRUSH: + case PEN: + case PENCIL: + if (currentTool()->properties.preserveAlpha) + { + cm = QPainter::CompositionMode_SourceOver; + } + break; + default: //nothing + break; + } + targetImage->paste(&mTiledBuffer, cm); } QRect rect = mEditor->view()->mapCanvasToScreen(mTiledBuffer.bounds()).toRect(); @@ -1208,7 +1215,6 @@ void ScribbleArea::prepCanvas(int frame) o.fLayerVisibilityThreshold = mPrefs->getFloat(SETTING::LAYER_VISIBILITY_THRESHOLD); o.scaling = mEditor->view()->scaling(); o.cmBufferBlendMode = mEditor->tools()->currentTool()->type() == ToolType::ERASER ? QPainter::CompositionMode_DestinationOut : QPainter::CompositionMode_SourceOver; - o.bIgnoreCanvasBuffer = currentTool()->type() == POLYLINE; OnionSkinPainterOptions onionSkinOptions; onionSkinOptions.enabledWhilePlaying = mPrefs->getInt(SETTING::ONION_WHILE_PLAYBACK); @@ -1270,7 +1276,8 @@ void ScribbleArea::drawPath(QPainterPath path, QPen pen, QBrush brush, QPainter: void ScribbleArea::drawPen(QPointF thePoint, qreal brushWidth, QColor fillColor, bool useAA) { - mTiledBuffer.drawBrush(thePoint, brushWidth, mEditor->view()->mapScreenToCanvas(mCursorImg.rect()).width(), Qt::NoPen, QBrush(fillColor, Qt::SolidPattern), QPainter::CompositionMode_SourceOver, useAA); + // We use Source as opposed to SourceOver here to avoid the dabs being added on top of each other + mTiledBuffer.drawBrush(thePoint, brushWidth, mEditor->view()->mapScreenToCanvas(mCursorImg.rect()).width(), Qt::NoPen, QBrush(fillColor, Qt::SolidPattern), QPainter::CompositionMode_Source, useAA); } void ScribbleArea::drawPencil(QPointF thePoint, qreal brushWidth, qreal fixedBrushFeather, QColor fillColor, qreal opacity) diff --git a/core_lib/src/tool/erasertool.cpp b/core_lib/src/tool/erasertool.cpp index 405a6498c..7d57ade7e 100644 --- a/core_lib/src/tool/erasertool.cpp +++ b/core_lib/src/tool/erasertool.cpp @@ -200,7 +200,7 @@ void EraserTool::paintAt(QPointF point) brushWidth, properties.feather, QColor(255, 255, 255, 255), - QPainter::CompositionMode_DestinationOut, + QPainter::CompositionMode_SourceOver, opacity, properties.useFeather, properties.useAA == ON); @@ -240,7 +240,7 @@ void EraserTool::drawStroke() brushWidth, properties.feather, Qt::white, - QPainter::CompositionMode_DestinationOut, + QPainter::CompositionMode_SourceOver, opacity, properties.useFeather, properties.useAA == ON);