Skip to content

Commit

Permalink
Check for null pointer returned by getLastVectorImageAtFrame where re…
Browse files Browse the repository at this point in the history
…levant

There are places that only have a Q_CHECK_PTR because they
follow a call to ScribbleArea::handleDrawingOnEmptyFrame which
should guarantee a frame after invocation. However this is called only
at the start of a stroke typically, which means that if the frame is
deleted while the stroke is in progress (ex. with a shortcut), then
it will still crash without a check. Users who aren't trying to break
the program will likely never do this, but we might as well add the
checks if we know the issue is there.
  • Loading branch information
scribblemaniac authored and chchwy committed Jun 19, 2020
1 parent 9ab84e4 commit d4c7bc6
Show file tree
Hide file tree
Showing 11 changed files with 137 additions and 82 deletions.
25 changes: 16 additions & 9 deletions core_lib/src/interface/editor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -556,7 +556,11 @@ void Editor::copy()
if (layer->type() == Layer::VECTOR)
{
clipboardVectorOk = true;
g_clipboardVectorImage = *((static_cast<LayerVector*>(layer))->getLastVectorImageAtFrame(currentFrame(), 0)); // copy the image
VectorImage *vectorImage = static_cast<LayerVector*>(layer)->getLastVectorImageAtFrame(currentFrame(), 0);
if (vectorImage != nullptr)
{
g_clipboardVectorImage = *vectorImage; // copy the image
}
}
}

Expand Down Expand Up @@ -592,7 +596,8 @@ void Editor::paste()
backup(tr("Paste"));
deselectAll();
mScribbleArea->handleDrawingOnEmptyFrame();
VectorImage* vectorImage = (static_cast<LayerVector*>(layer))->getLastVectorImageAtFrame(currentFrame(), 0);
VectorImage* vectorImage = static_cast<LayerVector*>(layer)->getLastVectorImageAtFrame(currentFrame(), 0);
Q_CHECK_PTR(vectorImage);
vectorImage->paste(g_clipboardVectorImage); // paste the clipboard
select()->setSelection(vectorImage->getSelectionRect(), false);
}
Expand Down Expand Up @@ -967,10 +972,11 @@ void Editor::selectAll()
else if (layer->type() == Layer::VECTOR)
{
VectorImage *vectorImage = static_cast<LayerVector*>(layer)->getLastVectorImageAtFrame(mFrame,0);
if (vectorImage == nullptr) { return; }

vectorImage->selectAll();
rect = vectorImage->getSelectionRect();
if (vectorImage != nullptr)
{
vectorImage->selectAll();
rect = vectorImage->getSelectionRect();
}
}
select()->setSelection(rect, false);
}
Expand All @@ -983,9 +989,10 @@ void Editor::deselectAll()
if (layer->type() == Layer::VECTOR)
{
VectorImage *vectorImage = static_cast<LayerVector*>(layer)->getLastVectorImageAtFrame(mFrame,0);
if (vectorImage == nullptr) { return; }

vectorImage->deselectAll();
if (vectorImage != nullptr)
{
vectorImage->deselectAll();
}
}

select()->resetSelectionProperties();
Expand Down
148 changes: 88 additions & 60 deletions core_lib/src/interface/scribblearea.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,11 @@ void ScribbleArea::updateAllVectorLayersAt(int frameNumber)
Layer* layer = mEditor->object()->getLayer(i);
if (layer->type() == Layer::VECTOR)
{
currentVectorImage(layer)->modification();
VectorImage* vectorImage = currentVectorImage(layer);
if (vectorImage != nullptr)
{
vectorImage->modification();
}
}
}
updateFrame(frameNumber);
Expand Down Expand Up @@ -960,7 +964,11 @@ void ScribbleArea::paintEvent(QPaintEvent* event)
Q_CHECK_PTR(layer);
if (layer->type() == Layer::VECTOR)
{
currentVectorImage(layer)->setModified(true);
VectorImage* vectorImage = currentVectorImage(layer);
if (vectorImage != nullptr)
{
vectorImage->setModified(true);
}
}
}

Expand All @@ -977,70 +985,73 @@ void ScribbleArea::paintEvent(QPaintEvent* event)
if (layer->type() == Layer::VECTOR)
{
VectorImage* vectorImage = currentVectorImage(layer);
switch (currentTool()->type())
{
case SMUDGE:
case HAND:
if (vectorImage != nullptr)
{
auto selectMan = mEditor->select();
painter.save();
painter.setWorldMatrixEnabled(false);
painter.setRenderHint(QPainter::Antialiasing, false);
// ----- paints the edited elements
QPen pen2(Qt::black, 0.5, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
painter.setPen(pen2);
QColor color;
// ------------ vertices of the edited curves
color = QColor(200, 200, 200);
painter.setBrush(color);
VectorSelection vectorSelection = selectMan->vectorSelection;
for (int k = 0; k < vectorSelection.curve.size(); k++)
switch (currentTool()->type())
{
int curveNumber = vectorSelection.curve.at(k);

for (int vertexNumber = -1; vertexNumber < vectorImage->getCurveSize(curveNumber); vertexNumber++)
case SMUDGE:
case HAND:
{
auto selectMan = mEditor->select();
painter.save();
painter.setWorldMatrixEnabled(false);
painter.setRenderHint(QPainter::Antialiasing, false);
// ----- paints the edited elements
QPen pen2(Qt::black, 0.5, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
painter.setPen(pen2);
QColor color;
// ------------ vertices of the edited curves
color = QColor(200, 200, 200);
painter.setBrush(color);
VectorSelection vectorSelection = selectMan->vectorSelection;
for (int k = 0; k < vectorSelection.curve.size(); k++)
{
QPointF vertexPoint = vectorImage->getVertex(curveNumber, vertexNumber);
QRectF rectangle(mEditor->view()->mapCanvasToScreen(vertexPoint) - QPointF(3.0, 3.0), QSizeF(7, 7));
if (rect().contains(mEditor->view()->mapCanvasToScreen(vertexPoint).toPoint()))
int curveNumber = vectorSelection.curve.at(k);

for (int vertexNumber = -1; vertexNumber < vectorImage->getCurveSize(curveNumber); vertexNumber++)
{
painter.drawRect(rectangle);
QPointF vertexPoint = vectorImage->getVertex(curveNumber, vertexNumber);
QRectF rectangle(mEditor->view()->mapCanvasToScreen(vertexPoint) - QPointF(3.0, 3.0), QSizeF(7, 7));
if (rect().contains(mEditor->view()->mapCanvasToScreen(vertexPoint).toPoint()))
{
painter.drawRect(rectangle);
}
}
}
}
// ------------ selected vertices of the edited curves
color = QColor(100, 100, 255);
painter.setBrush(color);
for (int k = 0; k < vectorSelection.vertex.size(); k++)
{
VertexRef vertexRef = vectorSelection.vertex.at(k);
QPointF vertexPoint = vectorImage->getVertex(vertexRef);
QRectF rectangle0 = QRectF(mEditor->view()->mapCanvasToScreen(vertexPoint) - QPointF(3.0, 3.0), QSizeF(7, 7));
painter.drawRect(rectangle0);
}
// ----- paints the closest vertices
color = QColor(255, 0, 0);
painter.setBrush(color);
QList<VertexRef> closestVertices = selectMan->closestVertices();
if (vectorSelection.curve.size() > 0)
{
for (int k = 0; k < closestVertices.size(); k++)
// ------------ selected vertices of the edited curves
color = QColor(100, 100, 255);
painter.setBrush(color);
for (int k = 0; k < vectorSelection.vertex.size(); k++)
{
VertexRef vertexRef = closestVertices.at(k);
VertexRef vertexRef = vectorSelection.vertex.at(k);
QPointF vertexPoint = vectorImage->getVertex(vertexRef);
QRectF rectangle0 = QRectF(mEditor->view()->mapCanvasToScreen(vertexPoint) - QPointF(3.0, 3.0), QSizeF(7, 7));
painter.drawRect(rectangle0);
}
// ----- paints the closest vertices
color = QColor(255, 0, 0);
painter.setBrush(color);
QList<VertexRef> closestVertices = selectMan->closestVertices();
if (vectorSelection.curve.size() > 0)
{
for (int k = 0; k < closestVertices.size(); k++)
{
VertexRef vertexRef = closestVertices.at(k);
QPointF vertexPoint = vectorImage->getVertex(vertexRef);

QRectF rectangle = QRectF(mEditor->view()->mapCanvasToScreen(vertexPoint) - QPointF(3.0, 3.0), QSizeF(7, 7));
painter.drawRect(rectangle);
QRectF rectangle = QRectF(mEditor->view()->mapCanvasToScreen(vertexPoint) - QPointF(3.0, 3.0), QSizeF(7, 7));
painter.drawRect(rectangle);
}
}
painter.restore();
break;
}
painter.restore();
break;
}
default:
{
break;
default:
{
break;
}
} // end switch
}
} // end switch
}

paintCanvasCursor(painter);
Expand Down Expand Up @@ -1100,7 +1111,7 @@ BitmapImage* ScribbleArea::currentBitmapImage(Layer* layer) const
VectorImage* ScribbleArea::currentVectorImage(Layer* layer) const
{
Q_ASSERT(layer->type() == Layer::VECTOR);
auto vectorLayer = (static_cast<LayerVector*>(layer));
auto vectorLayer = static_cast<LayerVector*>(layer);
return vectorLayer->getLastVectorImageAtFrame(mEditor->currentFrame(), 0);
}

Expand Down Expand Up @@ -1328,6 +1339,7 @@ void ScribbleArea::paintTransformedSelection()
{
// vector transformation
VectorImage* vectorImage = currentVectorImage(layer);
if (vectorImage == nullptr) { return; }
vectorImage->setSelectionTransformation(selectMan->selectionTransform());

}
Expand Down Expand Up @@ -1390,8 +1402,8 @@ void ScribbleArea::applyTransformedSelection()
// will always be applied on the previous keyframe when on an empty frame
//handleDrawingOnEmptyFrame();
VectorImage* vectorImage = currentVectorImage(layer);
if (vectorImage == nullptr) { return; }
vectorImage->applySelectionTransformation();

}

setModified(mEditor->layers()->currentLayerIndex(), mEditor->currentFrame());
Expand All @@ -1413,7 +1425,10 @@ void ScribbleArea::cancelTransformedSelection()
if (layer->type() == Layer::VECTOR) {

VectorImage* vectorImage = currentVectorImage(layer);
vectorImage->setSelectionTransformation(QTransform());
if (vectorImage != nullptr)
{
vectorImage->setSelectionTransformation(QTransform());
}
}

mEditor->select()->setSelection(selectMan->mySelectionRect(), false);
Expand All @@ -1429,6 +1444,7 @@ void ScribbleArea::displaySelectionProperties()
if (layer->type() == Layer::VECTOR)
{
VectorImage* vectorImage = currentVectorImage(layer);
if (vectorImage == nullptr) { return; }
//vectorImage->applySelectionTransformation();
if (currentTool()->type() == MOVE)
{
Expand Down Expand Up @@ -1553,8 +1569,16 @@ void ScribbleArea::deleteSelection()
mEditor->backup(tr("Delete Selection", "Undo Step: clear the selection area."));

selectMan->clearCurves();
if (layer->type() == Layer::VECTOR) { currentVectorImage(layer)->deleteSelection(); }
if (layer->type() == Layer::BITMAP) { currentBitmapImage(layer)->clear(selectMan->mySelectionRect()); }
if (layer->type() == Layer::VECTOR)
{
VectorImage* vectorImage = currentVectorImage(layer);
Q_CHECK_PTR(vectorImage);
vectorImage->deleteSelection();
}
else if (layer->type() == Layer::BITMAP)
{
currentBitmapImage(layer)->clear(selectMan->mySelectionRect());
}
updateAllFrames();
}
}
Expand All @@ -1568,7 +1592,11 @@ void ScribbleArea::clearImage()
{
mEditor->backup(tr("Clear Image", "Undo step text"));

currentVectorImage(layer)->clear();
VectorImage* vectorImage = currentVectorImage(layer);
if (vectorImage != nullptr)
{
vectorImage->clear();
}
mEditor->select()->clearCurves();
mEditor->select()->clearVertices();
}
Expand Down
4 changes: 3 additions & 1 deletion core_lib/src/structure/object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -668,8 +668,10 @@ void Object::paintImage(QPainter& painter,int frameNumber,
{
LayerVector* layerVector = static_cast<LayerVector*>(layer);
VectorImage* vec = layerVector->getLastVectorImageAtFrame(frameNumber, 0);
if (vec)
if (vec != nullptr)
{
vec->paintImage(painter, false, false, antialiasing);
}
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion core_lib/src/tool/buckettool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,8 @@ void BucketTool::paintVector(Layer* layer)
{
mScribbleArea->clearBitmapBuffer();

VectorImage* vectorImage = ((LayerVector *)layer)->getLastVectorImageAtFrame(mEditor->currentFrame(), 0);
VectorImage* vectorImage = static_cast<LayerVector*>(layer)->getLastVectorImageAtFrame(mEditor->currentFrame(), 0);
if (vectorImage == nullptr) { return; } // Can happen if the first frame is deleted while drawing

if (!vectorImage->isPathFilled())
{
Expand Down
5 changes: 3 additions & 2 deletions core_lib/src/tool/erasertool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -302,11 +302,12 @@ void EraserTool::removeVectorPaint()
}
else if (layer->type() == Layer::VECTOR)
{
VectorImage*vectorImage = ((LayerVector*)layer)->getLastVectorImageAtFrame(mEditor->currentFrame(), 0);
mScribbleArea->clearBitmapBuffer();
VectorImage* vectorImage = static_cast<LayerVector*>(layer)->getLastVectorImageAtFrame(mEditor->currentFrame(), 0);
if (vectorImage == nullptr) { return; } // Can happen if the first frame is deleted while drawing
// Clear the area containing the last point
//vectorImage->removeArea(lastPoint);
// Clear the temporary pixel path
mScribbleArea->clearBitmapBuffer();
vectorImage->deleteSelectedPoints();

mScribbleArea->setModified(mEditor->layers()->currentLayerIndex(), mEditor->currentFrame());
Expand Down
2 changes: 2 additions & 0 deletions core_lib/src/tool/movetool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ void MoveTool::createVectorSelection(Qt::KeyboardModifiers keyMod, Layer* layer)
assert(layer->type() == Layer::VECTOR);
LayerVector* vecLayer = static_cast<LayerVector*>(layer);
VectorImage* vectorImage = vecLayer->getLastVectorImageAtFrame(mEditor->currentFrame(), 0);
if (vectorImage == nullptr) { return; }

if (!mEditor->select()->closestCurves().empty()) // the user clicks near a curve
{
Expand Down Expand Up @@ -277,6 +278,7 @@ void MoveTool::storeClosestVectorCurve(Layer* layer)
auto selectMan = mEditor->select();
auto layerVector = static_cast<LayerVector*>(layer);
VectorImage* pVecImg = layerVector->getLastVectorImageAtFrame(mEditor->currentFrame(), 0);
if (pVecImg == nullptr) { return; }
selectMan->setCurves(pVecImg->getCurvesCloseTo(getCurrentPoint(), selectMan->selectionTolerance()));
}

Expand Down
4 changes: 2 additions & 2 deletions core_lib/src/tool/penciltool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -315,8 +315,8 @@ void PencilTool::paintVectorStroke(Layer* layer)
curve.setInvisibility(true);
curve.setVariableWidth(false);
curve.setColorNumber(mEditor->color()->frontColorNumber());
VectorImage* vectorImage = ((LayerVector *)layer)->getLastVectorImageAtFrame(mEditor->currentFrame(), 0);

VectorImage* vectorImage = static_cast<LayerVector*>(layer)->getLastVectorImageAtFrame(mEditor->currentFrame(), 0);
if (vectorImage == nullptr) { return; } // Can happen if the first frame is deleted while drawing
vectorImage->addCurve(curve, qAbs(mEditor->view()->scaling()), properties.vectorMergeEnabled);

if (properties.useFillContour)
Expand Down
1 change: 1 addition & 0 deletions core_lib/src/tool/pentool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,7 @@ void PenTool::paintVectorStroke(Layer* layer)

auto pLayerVector = static_cast<LayerVector*>(layer);
VectorImage* vectorImage = pLayerVector->getLastVectorImageAtFrame(mEditor->currentFrame(), 0);
if (vectorImage == nullptr) { return; } // Can happen if the first frame is deleted while drawing
vectorImage->addCurve(curve, mEditor->view()->scaling(), false);

if (vectorImage->isAnyCurveSelected() || mEditor->select()->somethingSelected())
Expand Down
10 changes: 7 additions & 3 deletions core_lib/src/tool/polylinetool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,9 @@ void PolylineTool::pointerPressEvent(PointerEvent* event)

if (layer->type() == Layer::VECTOR)
{
((LayerVector *)layer)->getLastVectorImageAtFrame(mEditor->currentFrame(), 0)->deselectAll();
VectorImage* vectorImage = static_cast<LayerVector*>(layer)->getLastVectorImageAtFrame(mEditor->currentFrame(), 0);
Q_CHECK_PTR(vectorImage);
vectorImage->deselectAll();
if (mScribbleArea->makeInvisible() && !mEditor->preference()->isOn(SETTING::INVISIBLE_LINES))
{
mScribbleArea->toggleThinLines();
Expand Down Expand Up @@ -239,6 +241,7 @@ void PolylineTool::cancelPolyline()
void PolylineTool::endPolyline(QList<QPointF> points)
{
Layer* layer = mEditor->layers()->currentLayer();
mScribbleArea->clearBitmapBuffer();

if (layer->type() == Layer::VECTOR)
{
Expand All @@ -255,14 +258,15 @@ void PolylineTool::endPolyline(QList<QPointF> points)
curve.setVariableWidth(false);
curve.setInvisibility(mScribbleArea->makeInvisible());

((LayerVector *)layer)->getLastVectorImageAtFrame(mEditor->currentFrame(), 0)->addCurve(curve, mEditor->view()->scaling());
VectorImage* vectorImage = static_cast<LayerVector*>(layer)->getLastVectorImageAtFrame(mEditor->currentFrame(), 0);
if (vectorImage == nullptr) { return; } // Can happen if the first frame is deleted while drawing
vectorImage->addCurve(curve, mEditor->view()->scaling());
}
if (layer->type() == Layer::BITMAP)
{
drawPolyline(points, points.last());
BitmapImage *bitmapImage = ((LayerBitmap *)layer)->getLastBitmapImageAtFrame(mEditor->currentFrame(), 0);
bitmapImage->paste(mScribbleArea->mBufferImg);
}
mScribbleArea->mBufferImg->clear();
mScribbleArea->setModified(mEditor->layers()->currentLayerIndex(), mEditor->currentFrame());
}
Loading

0 comments on commit d4c7bc6

Please sign in to comment.