Navigation Menu

Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Painting improvements #1267

Merged
merged 5 commits into from Dec 1, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
180 changes: 146 additions & 34 deletions core_lib/src/canvaspainter.cpp
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
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