Commit 3dffd58b authored by Dmitry Kazakov's avatar Dmitry Kazakov

Fix for a crash when saving a document after adding a text shape

Summary:
This patch should fix a crash that happens after
KisShapeLayerCanvas::repaint() is called on a cloned image. Actually,
KisShapeLayer::setImage() was implemented incorrectly. It deleted
m_d->converter and m_d->paintDevice, although canvas still owned a link
to them. Therefore the next coming update crashed the application.

BUG:372357

Test Plan:
I could never reproduce the original bug, I only used the results of
Boud's valgrind output. So please test the original bug with the patch
before I push it into 3.1 and impex.

Reviewers: #krita, rempt

Differential Revision: https://phabricator.kde.org/D3452
parent 2f8de900
......@@ -114,14 +114,12 @@ struct KisShapeLayer::Private
{
public:
Private()
: converter(0)
, canvas(0)
: canvas(0)
, controller(0)
, x(0)
, y(0)
{}
KoViewConverter * converter;
KisPaintDeviceSP paintDevice;
KisShapeLayerCanvas * canvas;
KoShapeBasedDocumentBase* controller;
......@@ -222,7 +220,6 @@ KisShapeLayer::~KisShapeLayer()
delete shape;
}
delete m_d->converter;
delete m_d->canvas;
delete m_d;
}
......@@ -232,14 +229,12 @@ void KisShapeLayer::initShapeLayer(KoShapeBasedDocumentBase* controller)
setSupportsLodMoves(false);
setShapeId(KIS_SHAPE_LAYER_ID);
m_d->converter = new KisImageViewConverter(image());
KIS_ASSERT_RECOVER_NOOP(this->image());
m_d->paintDevice = new KisPaintDevice(image()->colorSpace());
m_d->paintDevice->setDefaultBounds(new KisDefaultBounds(this->image()));
m_d->paintDevice->setParentNode(this);
m_d->canvas = new KisShapeLayerCanvas(this, m_d->converter);
m_d->canvas = new KisShapeLayerCanvas(this, image());
m_d->canvas->setProjection(m_d->paintDevice);
m_d->canvas->moveToThread(this->thread());
m_d->controller = controller;
......@@ -261,9 +256,9 @@ bool KisShapeLayer::allowAsChild(KisNodeSP node) const
void KisShapeLayer::setImage(KisImageWSP _image)
{
KisLayer::setImage(_image);
delete m_d->converter;
m_d->converter = new KisImageViewConverter(image());
m_d->paintDevice = new KisPaintDevice(image()->colorSpace());
m_d->canvas->setImage(_image);
m_d->paintDevice->convertTo(_image->colorSpace());
m_d->paintDevice->setDefaultBounds(new KisDefaultBounds(_image));
}
KisLayerSP KisShapeLayer::createMergedLayerTemplate(KisLayerSP prevLayer)
......@@ -317,7 +312,7 @@ qint32 KisShapeLayer::y() const
void KisShapeLayer::setX(qint32 x)
{
qint32 delta = x - this->x();
QPointF diff = QPointF(m_d->converter->viewToDocumentX(delta), 0);
QPointF diff = QPointF(m_d->canvas->viewConverter()->viewToDocumentX(delta), 0);
emit sigMoveShapes(diff);
// Save new value to satisfy LSP
......@@ -327,7 +322,7 @@ void KisShapeLayer::setX(qint32 x)
void KisShapeLayer::setY(qint32 y)
{
qint32 delta = y - this->y();
QPointF diff = QPointF(0, m_d->converter->viewToDocumentY(delta));
QPointF diff = QPointF(0, m_d->canvas->viewConverter()->viewToDocumentY(delta));
emit sigMoveShapes(diff);
// Save new value to satisfy LSP
......@@ -372,7 +367,7 @@ KoShapeManager* KisShapeLayer::shapeManager() const
KoViewConverter* KisShapeLayer::converter() const
{
return m_d->converter;
return m_d->canvas->viewConverter();
}
bool KisShapeLayer::visible(bool recursive) const
......@@ -585,7 +580,7 @@ KUndo2Command* KisShapeLayer::transform(const QTransform &transform) {
QList<KoShape*> shapes = m_d->canvas->shapeManager()->shapes();
if(shapes.isEmpty()) return 0;
KisImageViewConverter *converter = dynamic_cast<KisImageViewConverter*>(m_d->converter);
KisImageViewConverter *converter = dynamic_cast<KisImageViewConverter*>(this->converter());
QTransform realTransform = converter->documentToView() *
transform * converter->viewToDocument();
......
......@@ -33,16 +33,17 @@
#include <KoCompositeOpRegistry.h>
#include <KoSelection.h>
#include <KoUnit.h>
#include "kis_image_view_converter.h"
#include <kis_debug.h>
//#define DEBUG_REPAINT
KisShapeLayerCanvas::KisShapeLayerCanvas(KisShapeLayer *parent, KoViewConverter * viewConverter)
KisShapeLayerCanvas::KisShapeLayerCanvas(KisShapeLayer *parent, KisImageWSP image)
: QObject()
, KoCanvasBase(0)
, m_isDestroying(false)
, m_viewConverter(viewConverter)
, m_viewConverter(new KisImageViewConverter(image))
, m_shapeManager(new KoShapeManager(this))
, m_projection(0)
, m_parentLayer(parent)
......@@ -56,6 +57,11 @@ KisShapeLayerCanvas::~KisShapeLayerCanvas()
delete m_shapeManager;
}
void KisShapeLayerCanvas::setImage(KisImageWSP image)
{
m_viewConverter->setImage(image);
}
void KisShapeLayerCanvas::prepareForDestroying()
{
m_isDestroying = true;
......@@ -152,9 +158,9 @@ KoToolProxy * KisShapeLayerCanvas::toolProxy() const
return 0;
}
KoViewConverter *KisShapeLayerCanvas::viewConverter() const
KoViewConverter* KisShapeLayerCanvas::viewConverter() const
{
return m_viewConverter;
return m_viewConverter.data();
}
QWidget* KisShapeLayerCanvas::canvasWidget()
......
......@@ -30,6 +30,7 @@ class KoViewConverter;
class KUndo2Command;
class QWidget;
class KoUnit;
class KisImageViewConverter;
/**
* KisShapeLayerCanvas is a special canvas implementation that Krita
......@@ -43,7 +44,7 @@ class KisShapeLayerCanvas : public QObject, public KoCanvasBase
Q_OBJECT
public:
KisShapeLayerCanvas(KisShapeLayer *parent, KoViewConverter * viewConverter);
KisShapeLayerCanvas(KisShapeLayer *parent, KisImageWSP image);
virtual ~KisShapeLayerCanvas();
/// This canvas won't render onto a widget, but a projection
......@@ -51,6 +52,8 @@ public:
m_projection = projection;
}
void setImage(KisImageWSP image);
void prepareForDestroying();
void gridSize(QPointF *offset, QSizeF *spacing) const;
bool snapToGrid() const;
......@@ -58,7 +61,7 @@ public:
KoShapeManager *shapeManager() const;
void updateCanvas(const QRectF& rc);
KoToolProxy * toolProxy() const;
KoViewConverter *viewConverter() const;
KoViewConverter* viewConverter() const;
QWidget* canvasWidget();
const QWidget* canvasWidget() const;
KoUnit unit() const;
......@@ -72,7 +75,7 @@ Q_SIGNALS:
private:
bool m_isDestroying;
KoViewConverter * m_viewConverter;
QScopedPointer<KisImageViewConverter> m_viewConverter;
KoShapeManager * m_shapeManager;
KisPaintDeviceSP m_projection;
KisShapeLayer *m_parentLayer;
......
......@@ -28,6 +28,11 @@ KisImageViewConverter::KisImageViewConverter(const KisImageWSP image)
setZoom(0.1); // set the superclass to not hit the optimization of zoom=100%
}
void KisImageViewConverter::setImage(KisImageWSP image)
{
m_image = image;
}
QTransform KisImageViewConverter::documentToView() const
{
return QTransform::fromScale(m_image->xRes(), m_image->yRes());
......
......@@ -45,6 +45,8 @@ public:
*/
KisImageViewConverter(const KisImageWSP image);
void setImage(KisImageWSP image);
QTransform documentToView() const;
QTransform viewToDocument() const;
......@@ -63,7 +65,7 @@ public:
qreal zoom() const;
private:
const KisImageWSP m_image;
KisImageWSP m_image;
};
#endif
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