Skip to content

Commit

Permalink
Merge pull request #1267 from scribblemaniac/painter-improvements
Browse files Browse the repository at this point in the history
Painting improvements
  • Loading branch information
candyface authored Dec 1, 2019
2 parents 22b982d + 77d96c3 commit 91951c5
Show file tree
Hide file tree
Showing 5 changed files with 215 additions and 82 deletions.
180 changes: 146 additions & 34 deletions core_lib/src/canvaspainter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,28 +69,103 @@ void CanvasPainter::ignoreTransformedSelection()
mRenderTransform = false;
}

void CanvasPainter::paint(const Object* object, int layer, int frame, QRect rect)
void CanvasPainter::paintCached()
{
Q_ASSERT(object);
mObject = object;
QPixmap tempPixmap(mCanvas->size());
tempPixmap.fill(Qt::transparent);
mCanvas->fill(Qt::transparent);
QPainter tempPainter;
QPainter painter;
initializePainter(tempPainter, tempPixmap);
initializePainter(painter, *mCanvas);

mCurrentLayerIndex = layer;
mFrameNumber = frame;
if (!mPreLayersCache)
{
renderPreLayers(painter);
mPreLayersCache.reset(new QPixmap(*mCanvas));
}
else
{
painter.setWorldMatrixEnabled(false);
painter.drawPixmap(0, 0, *(mPreLayersCache.get()));
painter.setWorldMatrixEnabled(true);
}

renderCurLayer(painter);

if (!mPostLayersCache)
{
renderPostLayers(tempPainter);
mPostLayersCache.reset(new QPixmap(tempPixmap));
painter.setWorldMatrixEnabled(false);
painter.drawPixmap(0, 0, tempPixmap);
painter.setWorldMatrixEnabled(true);
}
else
{
painter.setWorldMatrixEnabled(false);
painter.drawPixmap(0, 0, *(mPostLayersCache.get()));
painter.setWorldMatrixEnabled(true);
}
}

//QRectF mappedInvCanvas = mViewInverse.mapRect(QRectF(mCanvas->rect()));
//QSizeF croppedPainter = QSizeF(mappedInvCanvas.size());
//QRectF aligned = QRectF(QPointF(mappedInvCanvas.topLeft()), croppedPainter);
QPainter painter(mCanvas);
void CanvasPainter::resetLayerCache()
{
mPreLayersCache.reset();
mPostLayersCache.reset();
}

void CanvasPainter::initializePainter(QPainter& painter, QPixmap& pixmap)
{
painter.begin(&pixmap);
painter.setWorldMatrixEnabled(true);
painter.setWorldTransform(mViewTransform);
}

Q_UNUSED(rect);
void CanvasPainter::renderPreLayers(QPixmap *pixmap)
{
QPainter painter;
initializePainter(painter, *pixmap);
renderPreLayers(painter);
}

paintBackground();
void CanvasPainter::renderPreLayers(QPainter& painter)
{
if (mOptions.nShowAllLayers > 0)
{
paintCurrentFrame(painter, 0, mCurrentLayerIndex-1);
}

paintOnionSkin(painter);
painter.setOpacity(1.0);
}

void CanvasPainter::renderCurLayer(QPixmap *pixmap)
{
QPainter painter;
initializePainter(painter, *pixmap);
renderCurLayer(painter);
}

void CanvasPainter::renderCurLayer(QPainter& painter)
{
paintCurrentFrame(painter, mCurrentLayerIndex, mCurrentLayerIndex);
}

void CanvasPainter::renderPostLayers(QPixmap *pixmap)
{
QPainter painter;
initializePainter(painter, *pixmap);
renderPostLayers(painter);
}

void CanvasPainter::renderPostLayers(QPainter& painter)
{
if (mOptions.nShowAllLayers > 0)
{
paintCurrentFrame(painter, mCurrentLayerIndex+1, mObject->getLayerCount()-1);
}

//painter.setClipRect(aligned); // this aligned rect is valid only for bitmap images.
paintCurrentFrame(painter);
paintCameraBorder(painter);

// post effects
Expand All @@ -100,6 +175,27 @@ void CanvasPainter::paint(const Object* object, int layer, int frame, QRect rect
}
}

void CanvasPainter::setPaintSettings(const Object* object, int currentLayer, int frame, QRect rect, BitmapImage *buffer)
{
Q_UNUSED(rect)
Q_ASSERT(object);
mObject = object;

mCurrentLayerIndex = currentLayer;
mFrameNumber = frame;
mBuffer = buffer;
}

void CanvasPainter::paint()
{
QPainter painter;
initializePainter(painter, *mCanvas);

renderPreLayers(painter);
renderCurLayer(painter);
renderPostLayers(painter);
}

void CanvasPainter::paintBackground()
{
mCanvas->fill(Qt::transparent);
Expand Down Expand Up @@ -141,8 +237,8 @@ void CanvasPainter::paintOnionSkin(QPainter& painter)

switch (layer->type())
{
case Layer::BITMAP: { paintBitmapFrame(painter, layer, onionFrameNumber, mOptions.bColorizePrevOnion, false); break; }
case Layer::VECTOR: { paintVectorFrame(painter, layer, onionFrameNumber, mOptions.bColorizePrevOnion, false); break; }
case Layer::BITMAP: { paintBitmapFrame(painter, layer, onionFrameNumber, mOptions.bColorizePrevOnion, false, false); break; }
case Layer::VECTOR: { paintVectorFrame(painter, layer, onionFrameNumber, mOptions.bColorizePrevOnion, false, false); break; }
default: break;
}
opacity = opacity - prevOpacityIncrement;
Expand All @@ -167,8 +263,8 @@ void CanvasPainter::paintOnionSkin(QPainter& painter)

switch (layer->type())
{
case Layer::BITMAP: { paintBitmapFrame(painter, layer, onionFrameNumber, mOptions.bColorizeNextOnion, false); break; }
case Layer::VECTOR: { paintVectorFrame(painter, layer, onionFrameNumber, mOptions.bColorizeNextOnion, false); break; }
case Layer::BITMAP: { paintBitmapFrame(painter, layer, onionFrameNumber, mOptions.bColorizeNextOnion, false, false); break; }
case Layer::VECTOR: { paintVectorFrame(painter, layer, onionFrameNumber, mOptions.bColorizeNextOnion, false, false); break; }
default: break;
}
opacity = opacity - nextOpacityIncrement;
Expand All @@ -183,7 +279,8 @@ void CanvasPainter::paintBitmapFrame(QPainter& painter,
Layer* layer,
int nFrame,
bool colorize,
bool useLastKeyFrame)
bool useLastKeyFrame,
bool isCurrentFrame)
{
#ifdef _DEBUG
LayerBitmap* bitmapLayer = dynamic_cast<LayerBitmap*>(layer);
Expand All @@ -207,17 +304,28 @@ void CanvasPainter::paintBitmapFrame(QPainter& painter,
paintedImage = bitmapLayer->getBitmapImageAtFrame(nFrame);
}

if (paintedImage == nullptr || paintedImage->bounds().isEmpty())
if ((paintedImage == nullptr || paintedImage->bounds().isEmpty())
&& !(isCurrentFrame && mBuffer != nullptr && !mBuffer->bounds().isEmpty()))
{
return;
}

if (paintedImage == nullptr)
{
paintedImage = new BitmapImage();
}

paintedImage->loadFile(); // Critical! force the BitmapImage to load the image
//qCDebug(mLog) << "Paint Image Size:" << paintedImage->image()->size();

BitmapImage paintToImage;
paintToImage.paste(paintedImage);

if (isCurrentFrame)
{
paintToImage.paste(mBuffer, mOptions.cmBufferBlendMode);
}

if (colorize)
{
QBrush colorBrush = QBrush(Qt::transparent); //no color for the current frame
Expand Down Expand Up @@ -277,7 +385,8 @@ void CanvasPainter::paintVectorFrame(QPainter& painter,
Layer* layer,
int nFrame,
bool colorize,
bool useLastKeyFrame)
bool useLastKeyFrame,
bool isCurrentFrame)
{
#ifdef _DEBUG
LayerVector* vectorLayer = dynamic_cast<LayerVector*>(layer);
Expand Down Expand Up @@ -313,6 +422,11 @@ void CanvasPainter::paintVectorFrame(QPainter& painter,
BitmapImage tempBitmapImage;
tempBitmapImage.setImage(pImage);

if (isCurrentFrame)
{
tempBitmapImage.paste(mBuffer, mOptions.cmBufferBlendMode);
}

if (colorize)
{
QBrush colorBrush = QBrush(Qt::transparent); //no color for the current frame
Expand Down Expand Up @@ -354,31 +468,29 @@ void CanvasPainter::paintTransformedSelection(QPainter& painter)
}
}

void CanvasPainter::paintCurrentFrame(QPainter& painter)
/** Paints layers within the specified range for the current frame.
*
* @param painter The painter to paint to
* @param startLayer The first layer to paint (inclusive)
* @param endLayer The last layer to paint (inclusive)
*/
void CanvasPainter::paintCurrentFrame(QPainter& painter, int startLayer, int endLayer)
{
//bool isCamera = mObject->getLayer(mCurrentLayerIndex)->type() == Layer::CAMERA;
painter.setOpacity(1.0);

for (int i = 0; i < mObject->getLayerCount(); ++i)
for (int i = startLayer; i <= endLayer; ++i)
{
Layer* layer = mObject->getLayer(i);

if (layer->visible() == false)
continue;

if (i == mCurrentLayerIndex) {
paintOnionSkin(painter);
painter.setOpacity(1.0);
}

if (i == mCurrentLayerIndex || mOptions.nShowAllLayers > 0)
switch (layer->type())
{
switch (layer->type())
{
case Layer::BITMAP: { paintBitmapFrame(painter, layer, mFrameNumber, false, true); break; }
case Layer::VECTOR: { paintVectorFrame(painter, layer, mFrameNumber, false, true); break; }
default: break;
}
case Layer::BITMAP: { paintBitmapFrame(painter, layer, mFrameNumber, false, true, i == mCurrentLayerIndex); break; }
case Layer::VECTOR: { paintVectorFrame(painter, layer, mFrameNumber, false, true, i == mCurrentLayerIndex); break; }
default: break;
}
}
}
Expand Down
37 changes: 31 additions & 6 deletions core_lib/src/canvaspainter.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ GNU General Public License for more details.
#include <QPainter>
#include "log.h"

#include "layer.h"

class Object;
class Layer;
class BitmapImage;
class ViewManager;

Expand All @@ -51,6 +51,7 @@ struct CanvasPainterOptions
float scaling = 1.0f;
bool isPlaying = false;
bool onionWhilePlayback = false;
QPainter::CompositionMode cmBufferBlendMode = QPainter::CompositionMode_SourceOver;
};


Expand All @@ -59,7 +60,7 @@ class CanvasPainter : public QObject
Q_OBJECT

public:
explicit CanvasPainter(QObject* parent = 0);
explicit CanvasPainter(QObject* parent = nullptr);
virtual ~CanvasPainter();

void setCanvas(QPixmap* canvas);
Expand All @@ -69,17 +70,37 @@ class CanvasPainter : public QObject
void ignoreTransformedSelection();
QRect getCameraRect();

void paint(const Object* object, int layer, int frame, QRect rect);
void setPaintSettings(const Object* object, int currentLayer, int frame, QRect rect, BitmapImage* buffer);
void paint();
void paintCached();
void renderGrid(QPainter& painter);
void resetLayerCache();

private:

/**
* @brief CanvasPainter::initializePainter
* Enriches the painter with a context and sets it's initial matrix.
* @param The in/out painter
* @param The paint device ie. a pixmap
*/
void initializePainter(QPainter& painter, QPixmap& pixmap);

void renderPreLayers(QPainter& painter);
void renderCurLayer(QPainter& painter);
void renderPostLayers(QPainter& painter);

void paintBackground();
void paintOnionSkin(QPainter& painter);

void paintCurrentFrame(QPainter& painter);
void renderPostLayers(QPixmap *pixmap);
void renderCurLayer(QPixmap *pixmap);
void renderPreLayers(QPixmap *pixmap);

void paintBitmapFrame(QPainter&, Layer* layer, int nFrame, bool colorize, bool useLastKeyFrame);
void paintVectorFrame(QPainter&, Layer* layer, int nFrame, bool colorize, bool useLastKeyFrame);
void paintCurrentFrame(QPainter& painter, int startLayer, int endLayer);

void paintBitmapFrame(QPainter&, Layer* layer, int nFrame, bool colorize, bool useLastKeyFrame, bool isCurrentFrame);
void paintVectorFrame(QPainter&, Layer* layer, int nFrame, bool colorize, bool useLastKeyFrame, bool isCurrentFrame);

void paintTransformedSelection(QPainter& painter);
void paintGrid(QPainter& painter);
Expand All @@ -99,6 +120,7 @@ class CanvasPainter : public QObject

int mCurrentLayerIndex = 0;
int mFrameNumber = 0;
BitmapImage* mBuffer = nullptr;

QImage mScaledBitmap;

Expand All @@ -110,6 +132,9 @@ class CanvasPainter : public QObject
QTransform mSelectionTransform;

QLoggingCategory mLog;

// Caches specificially for when drawing on the canvas
std::unique_ptr<QPixmap> mPreLayersCache, mPostLayersCache;
};

#endif // CANVASRENDERER_H
Loading

0 comments on commit 91951c5

Please sign in to comment.