Commit c7c3310f authored by Dmitry Kazakov's avatar Dmitry Kazakov

Fix crash when closing images with shape layer + mask

We shouldn't call any node's method that accesses parent() or
next/prevSibling() in ctor and dtor. It is just unsafe.

BUG:372184

# Conflicts:
#	libs/ui/flake/kis_shape_layer.cc
parent 2ca21b7e
......@@ -213,10 +213,9 @@ KisShapeLayer::KisShapeLayer(const KisShapeLayer& _rhs, const KisShapeLayer &_ad
KisShapeLayer::~KisShapeLayer()
{
/**
* Small hack alert: we set the image to null to disable
* updates those will be emitted on shape deletion
* Small hack alert: we should avoid updates on shape deletion
*/
KisLayer::setImage(0);
m_d->canvas->prepareForDestroying();
Q_FOREACH (KoShape *shape, shapes()) {
shape->setParent(0);
......
......@@ -41,6 +41,7 @@
KisShapeLayerCanvas::KisShapeLayerCanvas(KisShapeLayer *parent, KoViewConverter * viewConverter)
: QObject()
, KoCanvasBase(0)
, m_isDestroying(false)
, m_viewConverter(viewConverter)
, m_shapeManager(new KoShapeManager(this))
, m_projection(0)
......@@ -55,6 +56,11 @@ KisShapeLayerCanvas::~KisShapeLayerCanvas()
delete m_shapeManager;
}
void KisShapeLayerCanvas::prepareForDestroying()
{
m_isDestroying = true;
}
void KisShapeLayerCanvas::gridSize(QPointF *offset, QSizeF *spacing) const
{
Q_ASSERT(false); // This should never be called as this canvas should have no tools.
......@@ -86,7 +92,7 @@ void KisShapeLayerCanvas::updateCanvas(const QRectF& rc)
{
dbgUI << "KisShapeLayerCanvas::updateCanvas()" << rc;
//image is 0, if parentLayer is being deleted so don't update
if (!m_parentLayer->image()) {
if (!m_parentLayer->image() || m_isDestroying) {
return;
}
......
......@@ -51,6 +51,7 @@ public:
m_projection = projection;
}
void prepareForDestroying();
void gridSize(QPointF *offset, QSizeF *spacing) const;
bool snapToGrid() const;
void addCommand(KUndo2Command *command);
......@@ -70,6 +71,7 @@ Q_SIGNALS:
void forwardRepaint();
private:
bool m_isDestroying;
KoViewConverter * m_viewConverter;
KoShapeManager * m_shapeManager;
KisPaintDeviceSP m_projection;
......
......@@ -87,7 +87,7 @@ QTransform createTestingTransform() {
return QTransform(1,2,3,4,5,6,7,8,9);
}
KisDocument* createCompleteDocument()
KisDocument* createCompleteDocument(bool shouldMaskToShapeLayer = false)
{
KisImageWSP image = new KisImage(0, 1024, 1024, KoColorSpaceRegistry::instance()->rgb8(), "test for roundtrip");
......@@ -207,6 +207,14 @@ KisDocument* createCompleteDocument()
image->addNode(transformMask, paintLayer2);
if (shouldMaskToShapeLayer) {
// add all-visible transparency mask to crash a shape layer
KisTransparencyMaskSP transparencyMask3 = new KisTransparencyMask();
transparencyMask3->setName("crashy-transparency-mask");
transparencyMask3->initSelection(shapeLayer);
image->addNode(transparencyMask3, shapeLayer);
}
return doc;
}
......
......@@ -61,6 +61,17 @@ void KisKraSaverTest::initTestCase()
KisGeneratorRegistry::instance();
}
void KisKraSaverTest::testCrashyShapeLayer()
{
/**
* KisShapeLayer used to call setImage from its destructor and
* therefore causing an infinite recursion (when at least one transparency
* mask was preset. This testcase just checks that.
*/
QScopedPointer<KisDocument> doc(createCompleteDocument(true));
Q_UNUSED(doc);
}
void KisKraSaverTest::testRoundTrip()
{
......
......@@ -28,6 +28,8 @@ private Q_SLOTS:
void initTestCase();
void testCrashyShapeLayer();
// XXX: Also test roundtripping of metadata
void testRoundTrip();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment