Commit 4bab45a2 authored by Dmitry Kazakov's avatar Dmitry Kazakov

Fix memory leaks caused by KisPaintDevice::convertTo()

For years this method returned KUndoCommand and for years we
forgot to delete this command, causing memory leaks.

This patch refactors convertTo() call to not return anythingon heap,
but just accepting optional parent command.
parent 214d419c
......@@ -191,12 +191,14 @@ namespace KisCommandUtils
}
void CompositeCommand::redo() {
KUndo2Command::redo();
Q_FOREACH (KUndo2Command *cmd, m_commands) {
cmd->redo();
}
}
void CompositeCommand::undo() {
KUndo2Command::undo();
Q_FOREACH (KUndo2Command *cmd, m_commands) {
cmd->undo();
}
......
......@@ -114,27 +114,22 @@ bool KisColorSpaceConvertVisitor::convertPaintDevice(KisLayer* layer)
return false;
}
KUndo2Command *parentConversionCommand = new KUndo2Command();
if (layer->original()) {
KUndo2Command* cmd = layer->original()->convertTo(m_dstColorSpace, m_renderingIntent, m_conversionFlags);
if (cmd) {
image->undoAdapter()->addCommand(cmd);
}
layer->original()->convertTo(m_dstColorSpace, m_renderingIntent, m_conversionFlags, parentConversionCommand);
}
if (layer->paintDevice()) {
KUndo2Command* cmd = layer->paintDevice()->convertTo(m_dstColorSpace, m_renderingIntent, m_conversionFlags);
if (cmd) {
image->undoAdapter()->addCommand(cmd);
}
layer->paintDevice()->convertTo(m_dstColorSpace, m_renderingIntent, m_conversionFlags, parentConversionCommand);
}
if (layer->projection()) {
KUndo2Command* cmd = layer->projection()->convertTo(m_dstColorSpace, m_renderingIntent, m_conversionFlags);
if (cmd) {
image->undoAdapter()->addCommand(cmd);
}
layer->projection()->convertTo(m_dstColorSpace, m_renderingIntent, m_conversionFlags, parentConversionCommand);
}
image->undoAdapter()->addCommand(parentConversionCommand);
KisPaintLayer *paintLayer = 0;
if ((paintLayer = dynamic_cast<KisPaintLayer*>(layer))) {
paintLayer->setAlphaLocked(alphaLock);
......
......@@ -108,7 +108,7 @@ public:
KisPaintDeviceStrategy* currentStrategy();
void init(const KoColorSpace *cs, const quint8 *defaultPixel);
KUndo2Command* convertColorSpace(const KoColorSpace * dstColorSpace, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags);
void convertColorSpace(const KoColorSpace * dstColorSpace, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags, KUndo2Command *parentCommand);
bool assignProfile(const KoColorProfile * profile);
inline const KoColorSpace* colorSpace() const
......@@ -895,14 +895,15 @@ void KisPaintDevice::Private::tesingFetchLodDevice(KisPaintDeviceSP targetDevice
transferFromData(data, targetDevice);
}
KUndo2Command* KisPaintDevice::Private::convertColorSpace(const KoColorSpace * dstColorSpace, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags)
void KisPaintDevice::Private::convertColorSpace(const KoColorSpace * dstColorSpace, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags, KUndo2Command *parentCommand)
{
class DeviceChangeColorSpaceCommand : public KUndo2Command
{
public:
DeviceChangeColorSpaceCommand(KisPaintDeviceSP device)
: m_firstRun(true),
DeviceChangeColorSpaceCommand(KisPaintDeviceSP device, KUndo2Command *parent = 0)
: KUndo2Command(parent),
m_firstRun(true),
m_device(device)
{
}
......@@ -937,25 +938,19 @@ KUndo2Command* KisPaintDevice::Private::convertColorSpace(const KoColorSpace * d
};
KUndo2Command *parentCommand = new DeviceChangeColorSpaceCommand(q);
QList<Data*> dataObjects = allDataObjects();
if (dataObjects.isEmpty()) return;
KUndo2Command *mainCommand =
parentCommand ? new DeviceChangeColorSpaceCommand(q, parentCommand) : 0;
Q_FOREACH (Data *data, dataObjects) {
if (!data) continue;
data->convertDataColorSpace(dstColorSpace, renderingIntent, conversionFlags, parentCommand);
}
if (!parentCommand->childCount()) {
delete parentCommand;
parentCommand = 0;
} else {
q->emitColorSpaceChanged();
data->convertDataColorSpace(dstColorSpace, renderingIntent, conversionFlags, mainCommand);
}
return parentCommand;
q->emitColorSpaceChanged();
}
bool KisPaintDevice::Private::assignProfile(const KoColorProfile * profile)
......@@ -1516,10 +1511,9 @@ void KisPaintDevice::emitProfileChanged()
emit profileChanged(m_d->colorSpace()->profile());
}
KUndo2Command* KisPaintDevice::convertTo(const KoColorSpace * dstColorSpace, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags)
void KisPaintDevice::convertTo(const KoColorSpace * dstColorSpace, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags, KUndo2Command *parentCommand)
{
KUndo2Command *command = m_d->convertColorSpace(dstColorSpace, renderingIntent, conversionFlags);
return command;
m_d->convertColorSpace(dstColorSpace, renderingIntent, conversionFlags, parentCommand);
}
bool KisPaintDevice::setProfile(const KoColorProfile * profile)
......
......@@ -482,12 +482,11 @@ public:
/**
* Converts the paint device to a different colorspace
*
* @return a command that can be used to undo the conversion.
*/
KUndo2Command* convertTo(const KoColorSpace * dstColorSpace,
KoColorConversionTransformation::Intent renderingIntent = KoColorConversionTransformation::internalRenderingIntent(),
KoColorConversionTransformation::ConversionFlags conversionFlags = KoColorConversionTransformation::internalConversionFlags());
void convertTo(const KoColorSpace * dstColorSpace,
KoColorConversionTransformation::Intent renderingIntent = KoColorConversionTransformation::internalRenderingIntent(),
KoColorConversionTransformation::ConversionFlags conversionFlags = KoColorConversionTransformation::internalConversionFlags(),
KUndo2Command *parentCommand = 0);
/**
* Changes the profile of the colorspace of this paint device to the given
......
......@@ -188,6 +188,9 @@ public:
m_colorSpace, dstColorSpace,
parentCommand);
cmd->forcedRedo();
if (!parentCommand) {
delete cmd;
}
}
void prepareClone(const KisPaintDeviceData *srcData, bool copyContent = false) {
......
......@@ -92,7 +92,7 @@ KisPixelSelection::KisPixelSelection(const KisPaintDeviceSP copySource, KritaUti
, m_d(new Private)
{
KisPaintDeviceSP tmpDevice = new KisPaintDevice(*copySource, copyMode, 0);
delete tmpDevice->convertTo(this->colorSpace());
tmpDevice->convertTo(this->colorSpace());
this->makeFullCopyFrom(*tmpDevice, copyMode, 0);
......
......@@ -276,8 +276,8 @@ KUndo2Command* KisColorizeMask::setColorSpace(const KoColorSpace * dstColorSpace
CompositeCommand *composite = new CompositeCommand();
composite->addCommand(m_d->fakePaintDevice->convertTo(dstColorSpace, renderingIntent, conversionFlags));
composite->addCommand(m_d->coloringProjection->convertTo(dstColorSpace, renderingIntent, conversionFlags));
m_d->fakePaintDevice->convertTo(dstColorSpace, renderingIntent, conversionFlags, composite);
m_d->coloringProjection->convertTo(dstColorSpace, renderingIntent, conversionFlags, composite);
KUndo2Command *strokesConversionCommand =
new SetKeyStrokesColorSpaceCommand(
......
......@@ -72,7 +72,7 @@ void KisCsConversionTest::testColorSpaceConversion()
dev->convertFromQImage(image, 0);
dev->moveTo(10, 10); // Unalign with tile boundaries
dev->setDefaultBounds(new TestUtil::TestingTimedDefaultBounds(dev->exactBounds()));
delete dev->convertTo(dstCs);
dev->convertTo(dstCs);
if (dev->exactBounds() != QRect(10, 10, image.width(), image.height())) {
logFailure("bounds", srcCs, dstCs);
......
......@@ -274,7 +274,11 @@ void KisPaintDeviceTest::testColorSpaceConversion()
KisPaintDeviceSP dev = new KisPaintDevice(srcCs);
dev->convertFromQImage(image, 0);
dev->moveTo(10, 10); // Unalign with tile boundaries
KUndo2Command* cmd = dev->convertTo(dstCs);
KUndo2Command* cmd = new KUndo2Command();
dev->convertTo(dstCs,
KoColorConversionTransformation::internalRenderingIntent(),
KoColorConversionTransformation::internalConversionFlags(),
cmd);
QCOMPARE(dev->exactBounds(), QRect(10, 10, image.width(), image.height()));
QCOMPARE(dev->pixelSize(), dstCs->pixelSize());
......
......@@ -143,8 +143,7 @@ void KisImportCatcher::adaptClipToImageColorSpace(KisPaintDeviceSP dev, KisImage
KisConfig cfg(true);
if (cfg.convertToImageColorspaceOnImport() && *dev->colorSpace() != *image->colorSpace()) {
/// XXX: do we need intent here?
KUndo2Command* cmd = dev->convertTo(image->colorSpace());
delete cmd;
dev->convertTo(image->colorSpace());
}
}
......@@ -861,8 +861,7 @@ bool KisPNGConverter::saveDeviceToStore(const QString &filename, const QRect &im
if (dev->colorSpace()->id() != "RGBA") {
dev = new KisPaintDevice(*dev.data());
KUndo2Command *cmd = dev->convertTo(KoColorSpaceRegistry::instance()->rgb8());
delete cmd;
dev->convertTo(KoColorSpaceRegistry::instance()->rgb8());
}
bool success = pngconv.buildFile(&io, imageRect, xRes, yRes, dev, annotIt, annotIt, options, metaDataStore);
......@@ -936,7 +935,7 @@ KisImageBuilder_Result KisPNGConverter::buildFile(QIODevice* iodevice, const QRe
KisPaintDeviceSP tmp = new KisPaintDevice(device->colorSpace());
tmp->makeCloneFromRough(device, imageRect);
delete tmp->convertTo(dstCS);
tmp->convertTo(dstCS);
device = tmp;
......@@ -954,8 +953,7 @@ KisImageBuilder_Result KisPNGConverter::buildFile(QIODevice* iodevice, const QRe
if (options.forceSRGB || !colormodels.contains(device->colorSpace()->colorModelId().id())) {
const KoColorSpace* cs = KoColorSpaceRegistry::instance()->colorSpace(RGBAColorModelID.id(), device->colorSpace()->colorDepthId().id(), "sRGB built-in - (lcms internal)");
device = new KisPaintDevice(*device);
KUndo2Command *cmd = device->convertTo(cs);
delete cmd;
device->convertTo(cs);
}
// Initialize structures
......
......@@ -101,9 +101,7 @@ void KisFilterFastColorTransfer::processImpl(KisPaintDeviceSP device,
const KoColorSpace* oldCS = device->colorSpace();
KisPaintDeviceSP srcLAB = new KisPaintDevice(*device.data());
dbgPlugins << "srcLab : " << srcLAB->extent();
KUndo2Command* cmd = srcLAB->convertTo(labCS, KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::internalConversionFlags());
delete cmd;
srcLAB->convertTo(labCS, KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::internalConversionFlags());
KoProgressUpdater compositeUpdater(progressUpdater, KoProgressUpdater::Unthreaded);
KoUpdater *updaterStats = compositeUpdater.startSubtask(1);
......
......@@ -95,8 +95,7 @@ KisPropertiesConfigurationSP KisWdgFastColorTransfer::configuration() const
}
dbgPlugins << "convert ref to lab";
KUndo2Command* cmd = ref->convertTo(labCS, KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::internalConversionFlags());
delete cmd;
ref->convertTo(labCS, KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::internalConversionFlags());
// Compute the means and sigmas of ref
double meanL_ref = 0., meanA_ref = 0., meanB_ref = 0.;
......
......@@ -179,14 +179,13 @@ void KisFilterPhongBumpmap::processImpl(KisPaintDeviceSP device,
KisPaintDeviceSP bumpmapPaintDevice = new KisPaintDevice(KoColorSpaceRegistry::instance()->rgb16());
bumpmapPaintDevice->writeBytes(bumpmap.data(), outputArea.x(), outputArea.y(), outputArea.width(), outputArea.height());
KUndo2Command *leaker = bumpmapPaintDevice->convertTo(device->colorSpace(), KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::internalConversionFlags());
bumpmapPaintDevice->convertTo(device->colorSpace(), KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::internalConversionFlags());
KisPainter copier(device);
copier.bitBlt(outputArea.x(), outputArea.y(), bumpmapPaintDevice,
outputArea.x(), outputArea.y(), outputArea.width(), outputArea.height());
//device->prepareClone(bumpmapPaintDevice);
//device->makeCloneFrom(bumpmapPaintDevice, bumpmapPaintDevice->extent()); // THIS COULD BE BUG GY
delete leaker;
if (progressUpdater) progressUpdater->setProgress(100);
}
......
......@@ -425,8 +425,7 @@ KisImageBuilder_Result CSVSaver::getLayer(CSVLayerRecord* layer, KisDocument* ex
if (!KisPNGConverter::isColorSpaceSupported(cs)) {
device = new KisPaintDevice(*device.data());
KUndo2Command *cmd= device->convertTo(KoColorSpaceRegistry::instance()->rgb8());
delete cmd;
device->convertTo(KoColorSpaceRegistry::instance()->rgb8());
}
KisPNGOptions options;
......
......@@ -127,8 +127,7 @@ KisImportExportFilter::ConversionStatus KisHeightMapExport::convert(KisDocument
if (pd->colorSpace()->colorModelId() != target_co_model || pd->colorSpace()->colorDepthId() != target_co_depth) {
pd = new KisPaintDevice(*pd.data());
KUndo2Command *cmd = pd->convertTo(KoColorSpaceRegistry::instance()->colorSpace(target_co_model.id(), target_co_depth.id()));
delete cmd;
pd->convertTo(KoColorSpaceRegistry::instance()->colorSpace(target_co_model.id(), target_co_depth.id()));
}
if (target_co_depth == Float32BitsColorDepthID) {
......
......@@ -470,16 +470,14 @@ KisImageBuilder_Result KisJPEGConverter::buildFile(QIODevice *io, KisPaintLayerS
J_COLOR_SPACE color_type = getColorTypeforColorSpace(cs);
if (color_type == JCS_UNKNOWN) {
KUndo2Command *tmp = layer->paintDevice()->convertTo(KoColorSpaceRegistry::instance()->rgb8(), KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::internalConversionFlags());
delete tmp;
layer->paintDevice()->convertTo(KoColorSpaceRegistry::instance()->rgb8(), KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::internalConversionFlags());
cs = KoColorSpaceRegistry::instance()->rgb8();
color_type = JCS_RGB;
}
if (options.forceSRGB) {
const KoColorSpace* dst = KoColorSpaceRegistry::instance()->colorSpace(RGBAColorModelID.id(), layer->colorSpace()->colorDepthId().id(), "sRGB built-in - (lcms internal)");
KUndo2Command *tmp = layer->paintDevice()->convertTo(dst);
delete tmp;
layer->paintDevice()->convertTo(dst);
cs = dst;
color_type = JCS_RGB;
}
......
......@@ -585,10 +585,10 @@ KisPaintDeviceSP PSDLayerRecord::convertMaskDeviceIfNeeded(KisPaintDeviceSP dev)
if (m_header.channelDepth == 16) {
result = new KisPaintDevice(*dev);
delete result->convertTo(KoColorSpaceRegistry::instance()->alpha16());
result->convertTo(KoColorSpaceRegistry::instance()->alpha16());
} else if (m_header.channelDepth == 32) {
result = new KisPaintDevice(*dev);
delete result->convertTo(KoColorSpaceRegistry::instance()->alpha32f());
result->convertTo(KoColorSpaceRegistry::instance()->alpha32f());
}
return result;
}
......
......@@ -74,8 +74,7 @@ bool KisSpriterExport::savePaintDevice(KisPaintDeviceSP dev, const QString &file
if (!KisPNGConverter::isColorSpaceSupported(dev->colorSpace())) {
dev = new KisPaintDevice(*dev.data());
KUndo2Command *cmd = dev->convertTo(KoColorSpaceRegistry::instance()->rgb8());
delete cmd;
dev->convertTo(KoColorSpaceRegistry::instance()->rgb8());
}
KisPNGOptions options;
......
......@@ -85,7 +85,7 @@ void generateDab(const DabGenerationInfo &di, DabRenderingResources *resources,
QRect maskRect(QPoint(), di.dstDabRect.size());
resources->colorSource->colorize(resources->colorSourceDevice, maskRect, di.info.pos().toPoint());
delete resources->colorSourceDevice->convertTo(cs);
resources->colorSourceDevice->convertTo(cs);
resources->brush->mask(*dab, resources->colorSourceDevice,
di.shape,
......
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