summaryrefslogtreecommitdiffstats
path: root/chalk/core/kis_image.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'chalk/core/kis_image.cpp')
-rw-r--r--chalk/core/kis_image.cpp1702
1 files changed, 1702 insertions, 0 deletions
diff --git a/chalk/core/kis_image.cpp b/chalk/core/kis_image.cpp
new file mode 100644
index 000000000..1180bf4cf
--- /dev/null
+++ b/chalk/core/kis_image.cpp
@@ -0,0 +1,1702 @@
+/*
+ * Copyright (c) 2002 Patrick Julien <freak@codepimps.org>
+ * Copyright (c) 2007 Benjamin Schleimer <bensch128@yahoo.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+#include <stdlib.h>
+#include <math.h>
+
+#include <config.h>
+#include LCMS_HEADER
+
+#include <tqimage.h>
+#include <tqpainter.h>
+#include <tqsize.h>
+#include <tqtl.h>
+#include <tqapplication.h>
+#include <tqthread.h>
+#include <tqdatetime.h>
+
+#include <kcommand.h>
+#include <kdebug.h>
+#include <tdelocale.h>
+
+#include "kis_image_iface.h"
+
+#include "kis_annotation.h"
+#include "kis_colorspace_factory_registry.h"
+#include "kis_color.h"
+#include "kis_command.h"
+#include "kis_types.h"
+//#include "kis_guide.h"
+#include "kis_image.h"
+#include "kis_paint_device.h"
+#include "kis_paint_device_action.h"
+#include "kis_selection.h"
+#include "kis_painter.h"
+#include "kis_fill_painter.h"
+#include "kis_layer.h"
+#include "kis_group_layer.h"
+#include "kis_adjustment_layer.h"
+#include "kis_paint_layer.h"
+#include "kis_colorspace_convert_visitor.h"
+#include "kis_background.h"
+#include "kis_substrate.h"
+#include "kis_scale_visitor.h"
+#include "kis_nameserver.h"
+#include "kis_undo_adapter.h"
+#include "kis_merge_visitor.h"
+#include "kis_transaction.h"
+#include "kis_crop_visitor.h"
+#include "kis_transform_visitor.h"
+#include "kis_filter_strategy.h"
+#include "kis_profile.h"
+#include "kis_paint_layer.h"
+#include "kis_perspective_grid.h"
+#include "kis_change_profile_visitor.h"
+#include "kis_group_layer.h"
+#include "kis_iterators_pixel.h"
+#include "kis_shear_visitor.h"
+
+class KisImage::KisImagePrivate {
+public:
+ KisColor backgroundColor;
+ TQ_UINT32 lockCount;
+ bool sizeChangedWhileLocked;
+ bool selectionChangedWhileLocked;
+ KisSubstrateSP substrate;
+ KisPerspectiveGrid* perspectiveGrid;
+};
+
+
+namespace {
+
+ class KisResizeImageCmd : public KNamedCommand {
+ typedef KNamedCommand super;
+
+ public:
+ KisResizeImageCmd(KisUndoAdapter *adapter,
+ KisImageSP img,
+ TQ_INT32 width,
+ TQ_INT32 height,
+ TQ_INT32 oldWidth,
+ TQ_INT32 oldHeight) : super(i18n("Resize Image"))
+ {
+ m_adapter = adapter;
+ m_img = img;
+ m_before = TQSize(oldWidth, oldHeight);
+ m_after = TQSize(width, height);
+ }
+
+ virtual ~KisResizeImageCmd()
+ {
+ }
+
+ public:
+ virtual void execute()
+ {
+ m_adapter->setUndo(false);
+ m_img->resize(m_after.width(), m_after.height());
+ m_adapter->setUndo(true);
+ }
+
+ virtual void unexecute()
+ {
+ m_adapter->setUndo(false);
+ m_img->resize(m_before.width(), m_before.height());
+ m_adapter->setUndo(true);
+ }
+
+ private:
+ KisUndoAdapter *m_adapter;
+ KisImageSP m_img;
+ TQSize m_before;
+ TQSize m_after;
+ };
+
+ // -------------------------------------------------------
+
+ class KisChangeLayersCmd : public KNamedCommand {
+ typedef KNamedCommand super;
+
+ public:
+ KisChangeLayersCmd(KisUndoAdapter *adapter, KisImageSP img,
+ KisGroupLayerSP oldRootLayer, KisGroupLayerSP newRootLayer, const TQString& name)
+ : super(name)
+ {
+ m_adapter = adapter;
+ m_img = img;
+ m_oldRootLayer = oldRootLayer;
+ m_newRootLayer = newRootLayer;
+ }
+
+ virtual ~KisChangeLayersCmd()
+ {
+ }
+
+ public:
+ virtual void execute()
+ {
+ m_adapter->setUndo(false);
+ m_img->setRootLayer(m_newRootLayer);
+ m_adapter->setUndo(true);
+ m_img->notifyLayersChanged();
+ }
+
+ virtual void unexecute()
+ {
+ m_adapter->setUndo(false);
+ m_img->setRootLayer(m_oldRootLayer);
+ m_adapter->setUndo(true);
+ m_img->notifyLayersChanged();
+ }
+
+ private:
+ KisUndoAdapter *m_adapter;
+ KisImageSP m_img;
+ KisGroupLayerSP m_oldRootLayer;
+ KisGroupLayerSP m_newRootLayer;
+ };
+
+
+ // -------------------------------------------------------
+
+ class KisConvertImageTypeCmd : public KNamedCommand {
+ typedef KNamedCommand super;
+
+ public:
+ KisConvertImageTypeCmd(KisUndoAdapter *adapter, KisImageSP img,
+ KisColorSpace * beforeColorSpace, KisColorSpace * afterColorSpace
+ ) : super(i18n("Convert Image Type"))
+ {
+ m_adapter = adapter;
+ m_img = img;
+ m_beforeColorSpace = beforeColorSpace;
+ m_afterColorSpace = afterColorSpace;
+ }
+
+ virtual ~KisConvertImageTypeCmd()
+ {
+ }
+
+ public:
+ virtual void execute()
+ {
+ m_adapter->setUndo(false);
+
+ m_img->setColorSpace(m_afterColorSpace);
+ m_img->setProfile(m_afterColorSpace->getProfile());
+
+ m_adapter->setUndo(true);
+ }
+
+ virtual void unexecute()
+ {
+ m_adapter->setUndo(false);
+
+ m_img->setColorSpace(m_beforeColorSpace);
+ m_img->setProfile(m_beforeColorSpace->getProfile());
+
+ m_adapter->setUndo(true);
+ }
+
+ private:
+ KisUndoAdapter *m_adapter;
+ KisImageSP m_img;
+ KisColorSpace * m_beforeColorSpace;
+ KisColorSpace * m_afterColorSpace;
+ };
+
+
+ // -------------------------------------------------------
+
+ class KisImageCommand : public KNamedCommand {
+ typedef KNamedCommand super;
+
+ public:
+ KisImageCommand(const TQString& name, KisImageSP image);
+ virtual ~KisImageCommand() {}
+
+ virtual void execute() = 0;
+ virtual void unexecute() = 0;
+
+ protected:
+ void setUndo(bool undo);
+
+ KisImageSP m_image;
+ };
+
+ KisImageCommand::KisImageCommand(const TQString& name, KisImageSP image) :
+ super(name), m_image(image)
+ {
+ }
+
+ void KisImageCommand::setUndo(bool undo)
+ {
+ if (m_image->undoAdapter()) {
+ m_image->undoAdapter()->setUndo(undo);
+ }
+ }
+
+
+ // -------------------------------------------------------
+
+ class KisLayerPositionCommand : public KisImageCommand {
+ typedef KisImageCommand super;
+
+ public:
+ KisLayerPositionCommand(const TQString& name, KisImageSP image, KisLayerSP layer, KisGroupLayerSP parent, KisLayerSP aboveThis) : super(name, image)
+ {
+ m_layer = layer;
+ m_oldParent = layer->parent();
+ m_oldAboveThis = layer->nextSibling();
+ m_newParent = parent;
+ m_newAboveThis = aboveThis;
+ }
+
+ virtual void execute()
+ {
+ setUndo(false);
+ m_image->moveLayer(m_layer, m_newParent, m_newAboveThis);
+ setUndo(true);
+ }
+
+ virtual void unexecute()
+ {
+ setUndo(false);
+ m_image->moveLayer(m_layer, m_oldParent, m_oldAboveThis);
+ setUndo(true);
+ }
+
+ private:
+ KisLayerSP m_layer;
+ KisGroupLayerSP m_oldParent;
+ KisLayerSP m_oldAboveThis;
+ KisGroupLayerSP m_newParent;
+ KisLayerSP m_newAboveThis;
+ };
+
+
+ // -------------------------------------------------------
+
+ class LayerAddCmd : public KisCommand {
+ typedef KisCommand super;
+
+ public:
+ LayerAddCmd(KisUndoAdapter *adapter, KisImageSP img, KisLayerSP layer) : super(i18n("Add Layer"), adapter)
+ {
+ m_img = img;
+ m_layer = layer;
+ m_parent = layer->parent();
+ m_aboveThis = layer->nextSibling();
+ }
+
+ virtual ~LayerAddCmd()
+ {
+ }
+
+ virtual void execute()
+ {
+ adapter()->setUndo(false);
+ m_img->addLayer(m_layer, m_parent.data(), m_aboveThis);
+ adapter()->setUndo(true);
+ }
+
+ virtual void unexecute()
+ {
+ adapter()->setUndo(false);
+ m_img->removeLayer(m_layer);
+ adapter()->setUndo(true);
+ }
+
+ private:
+ KisImageSP m_img;
+ KisLayerSP m_layer;
+ KisGroupLayerSP m_parent;
+ KisLayerSP m_aboveThis;
+ };
+
+ // -------------------------------------------------------
+
+ class LayerRmCmd : public KNamedCommand {
+ typedef KNamedCommand super;
+
+ public:
+ LayerRmCmd(KisUndoAdapter *adapter, KisImageSP img,
+ KisLayerSP layer, KisGroupLayerSP wasParent, KisLayerSP wasAbove)
+ : super(i18n("Remove Layer"))
+ {
+ m_adapter = adapter;
+ m_img = img;
+ m_layer = layer;
+ m_prevParent = wasParent;
+ m_prevAbove = wasAbove;
+ }
+
+ virtual ~LayerRmCmd()
+ {
+ }
+
+ virtual void execute()
+ {
+ m_adapter->setUndo(false);
+ m_img->removeLayer(m_layer);
+ m_adapter->setUndo(true);
+ }
+
+ virtual void unexecute()
+ {
+ m_adapter->setUndo(false);
+ m_img->addLayer(m_layer, m_prevParent.data(), m_prevAbove);
+ m_adapter->setUndo(true);
+ }
+
+ private:
+ KisUndoAdapter *m_adapter;
+ KisImageSP m_img;
+ KisLayerSP m_layer;
+ KisGroupLayerSP m_prevParent;
+ KisLayerSP m_prevAbove;
+ };
+
+ class LayerMoveCmd: public KNamedCommand {
+ typedef KNamedCommand super;
+
+ public:
+ LayerMoveCmd(KisUndoAdapter *adapter, KisImageSP img,
+ KisLayerSP layer, KisGroupLayerSP wasParent, KisLayerSP wasAbove)
+ : super(i18n("Move Layer"))
+ {
+ m_adapter = adapter;
+ m_img = img;
+ m_layer = layer;
+ m_prevParent = wasParent;
+ m_prevAbove = wasAbove;
+ m_newParent = layer->parent();
+ m_newAbove = layer->nextSibling();
+ }
+
+ virtual ~LayerMoveCmd()
+ {
+ }
+
+ virtual void execute()
+ {
+ m_adapter->setUndo(false);
+ m_img->moveLayer(m_layer, m_newParent.data(), m_newAbove);
+ m_adapter->setUndo(true);
+ }
+
+ virtual void unexecute()
+ {
+ m_adapter->setUndo(false);
+ m_img->moveLayer(m_layer, m_prevParent.data(), m_prevAbove);
+ m_adapter->setUndo(true);
+ }
+
+ private:
+ KisUndoAdapter *m_adapter;
+ KisImageSP m_img;
+ KisLayerSP m_layer;
+ KisGroupLayerSP m_prevParent;
+ KisLayerSP m_prevAbove;
+ KisGroupLayerSP m_newParent;
+ KisLayerSP m_newAbove;
+ };
+
+
+ // -------------------------------------------------------
+
+ class LayerPropsCmd : public KNamedCommand {
+ typedef KNamedCommand super;
+
+ public:
+ LayerPropsCmd(KisLayerSP layer,
+ KisImageSP img,
+ KisUndoAdapter *adapter,
+ const TQString& name,
+ TQ_INT32 opacity,
+ const KisCompositeOp& compositeOp) : super(i18n("Layer Property Changes"))
+ {
+ m_layer = layer;
+ m_img = img;
+ m_adapter = adapter;
+ m_name = name;
+ m_opacity = opacity;
+ m_compositeOp = compositeOp;
+ }
+
+ virtual ~LayerPropsCmd()
+ {
+ }
+
+ public:
+ virtual void execute()
+ {
+ TQString name = m_layer->name();
+ TQ_INT32 opacity = m_layer->opacity();
+ KisCompositeOp compositeOp = m_layer->compositeOp();
+
+ m_adapter->setUndo(false);
+ m_img->setLayerProperties(m_layer,
+ m_opacity,
+ m_compositeOp,
+ m_name);
+ m_adapter->setUndo(true);
+ m_name = name;
+ m_opacity = opacity;
+ m_compositeOp = compositeOp;
+ m_layer->setDirty();
+ }
+
+ virtual void unexecute()
+ {
+ execute();
+ }
+
+ private:
+ KisUndoAdapter *m_adapter;
+ KisLayerSP m_layer;
+ KisImageSP m_img;
+ TQString m_name;
+ TQ_INT32 m_opacity;
+ KisCompositeOp m_compositeOp;
+ };
+
+ // -------------------------------------------------------
+
+ class LockImageCommand : public KNamedCommand {
+ typedef KNamedCommand super;
+
+ public:
+ LockImageCommand(KisImageSP img, bool lockImage) : super("lock image") // Not for translation, this
+ { // is only ever used inside a macro command.
+ m_img = img;
+ m_lockImage = lockImage;
+ }
+
+ virtual ~LockImageCommand()
+ {
+ }
+
+ virtual void execute()
+ {
+ if (m_lockImage) {
+ m_img->lock();
+ } else {
+ m_img->unlock();
+ }
+ }
+
+ virtual void unexecute()
+ {
+ if (m_lockImage) {
+ m_img->unlock();
+ } else {
+ m_img->lock();
+ }
+ }
+
+ private:
+ KisImageSP m_img;
+ bool m_lockImage;
+ };
+}
+
+KisImage::KisImage(KisUndoAdapter *adapter, TQ_INT32 width, TQ_INT32 height, KisColorSpace * colorSpace, const TQString& name)
+ : TQObject(0, name.latin1()), TDEShared()
+{
+ init(adapter, width, height, colorSpace, name);
+ setName(name);
+ m_dcop = 0L;
+}
+
+KisImage::KisImage(const KisImage& rhs) : TQObject(), TDEShared(rhs)
+{
+ m_dcop = 0L;
+ if (this != &rhs) {
+ m_private = new KisImagePrivate(*rhs.m_private);
+ m_private->perspectiveGrid = new KisPerspectiveGrid(*rhs.m_private->perspectiveGrid);
+ m_uri = rhs.m_uri;
+ m_name = TQString();
+ m_width = rhs.m_width;
+ m_height = rhs.m_height;
+ m_xres = rhs.m_xres;
+ m_yres = rhs.m_yres;
+ m_unit = rhs.m_unit;
+ m_colorSpace = rhs.m_colorSpace;
+ m_dirty = rhs.m_dirty;
+ m_adapter = rhs.m_adapter;
+
+ m_bkg = new KisBackground();
+ TQ_CHECK_PTR(m_bkg);
+
+ m_rootLayer = static_cast<KisGroupLayer*>(rhs.m_rootLayer->clone().data());
+ connect(m_rootLayer, TQT_SIGNAL(sigDirty(TQRect)), this, TQT_SIGNAL(sigImageUpdated(TQRect)));
+
+ m_annotations = rhs.m_annotations; // XXX the annotations would probably need to be deep-copied
+
+ m_nserver = new KisNameServer(i18n("Layer %1"), rhs.m_nserver->currentSeed() + 1);
+ TQ_CHECK_PTR(m_nserver);
+
+ //m_guides = rhs.m_guides;
+
+ // Set this as the current image for the layers
+ m_rootLayer->setImage(this);
+ // Set the active paint layer
+ if(rhs.activeLayer() != NULL) {
+ TQString layerName = rhs.activeLayer()->name();
+ // kdDebug(12345) << "KisImage::KisImage: active layer = " << layerName << "\n";
+ KisLayerSP activeLayer = rootLayer()->findLayer(layerName);
+ Q_ASSERT(activeLayer);
+ activate(activeLayer);
+ } else {
+ activate(NULL);
+ }
+ }
+}
+
+
+
+DCOPObject * KisImage::dcopObject()
+{
+ if (!m_dcop) {
+ m_dcop = new KisImageIface(this);
+ TQ_CHECK_PTR(m_dcop);
+ }
+ return m_dcop;
+}
+
+KisImage::~KisImage()
+{
+ delete m_private->perspectiveGrid;
+ delete m_private;
+ delete m_nserver;
+ delete m_dcop;
+}
+
+TQString KisImage::name() const
+{
+ return m_name;
+}
+
+void KisImage::setName(const TQString& name)
+{
+ if (!name.isEmpty())
+ m_name = name;
+}
+
+TQString KisImage::description() const
+{
+ return m_description;
+}
+
+void KisImage::setDescription(const TQString& description)
+{
+ if (!description.isEmpty())
+ m_description = description;
+}
+
+
+KisColor KisImage::backgroundColor() const
+{
+ return m_private->backgroundColor;
+}
+
+void KisImage::setBackgroundColor(const KisColor & color)
+{
+ m_private->backgroundColor = color;
+}
+
+
+TQString KisImage::nextLayerName() const
+{
+ if (m_nserver->currentSeed() == 0) {
+ m_nserver->number();
+ return i18n("background");
+ }
+
+ return m_nserver->name();
+}
+
+void KisImage::rollBackLayerName()
+{
+ m_nserver->rollback();
+}
+
+void KisImage::init(KisUndoAdapter *adapter, TQ_INT32 width, TQ_INT32 height, KisColorSpace * colorSpace, const TQString& name)
+{
+ Q_ASSERT(colorSpace);
+
+ if (colorSpace == 0) {
+ colorSpace = KisMetaRegistry::instance()->csRegistry()->getRGB8();
+ kdWarning(41010) << "No colorspace specified: using RGBA\n";
+ }
+
+ m_private = new KisImagePrivate();
+ m_private->backgroundColor = KisColor(TQt::white, colorSpace);
+ m_private->lockCount = 0;
+ m_private->sizeChangedWhileLocked = false;
+ m_private->selectionChangedWhileLocked = false;
+ m_private->substrate = 0;
+ m_private->perspectiveGrid = new KisPerspectiveGrid();
+
+ m_adapter = adapter;
+
+ m_nserver = new KisNameServer(i18n("Layer %1"), 1);
+ m_name = name;
+
+ m_colorSpace = colorSpace;
+ m_bkg = new KisBackground();
+
+ m_rootLayer = new KisGroupLayer(this,"root", OPACITY_OPAQUE);
+ connect(m_rootLayer, TQT_SIGNAL(sigDirty(TQRect)), this, TQT_SIGNAL(sigImageUpdated(TQRect)));
+
+ m_xres = 1.0;
+ m_yres = 1.0;
+ m_unit = KoUnit::U_PT;
+ m_dirty = false;
+ m_width = width;
+ m_height = height;
+}
+
+bool KisImage::locked() const
+{
+ return m_private->lockCount != 0;
+}
+
+void KisImage::lock()
+{
+ if (!locked()) {
+ if (m_rootLayer) disconnect(m_rootLayer, TQT_SIGNAL(sigDirty(TQRect)), this, TQT_SIGNAL(sigImageUpdated(TQRect)));
+ m_private->sizeChangedWhileLocked = false;
+ m_private->selectionChangedWhileLocked = false;
+ }
+ m_private->lockCount++;
+}
+
+void KisImage::unlock()
+{
+ Q_ASSERT(locked());
+
+ if (locked()) {
+ m_private->lockCount--;
+
+ if (m_private->lockCount == 0) {
+ if (m_private->sizeChangedWhileLocked) {
+ // A size change implies a full image update so only send this.
+ emit sigSizeChanged(m_width, m_height);
+ } else {
+ if (m_rootLayer->dirty()) emit sigImageUpdated( m_rootLayer->dirtyRect() );
+ }
+
+ if (m_private->selectionChangedWhileLocked) {
+ emit sigActiveSelectionChanged(this);
+ }
+
+ if (m_rootLayer) connect(m_rootLayer, TQT_SIGNAL(sigDirty(TQRect)), this, TQT_SIGNAL(sigImageUpdated(TQRect)));
+ }
+ }
+}
+
+void KisImage::emitSizeChanged()
+{
+ if (!locked()) {
+ emit sigSizeChanged(m_width, m_height);
+ } else {
+ m_private->sizeChangedWhileLocked = true;
+ }
+}
+
+void KisImage::notifyLayerUpdated(KisLayerSP layer, TQRect rc)
+{
+ emit sigLayerUpdated(layer, rc);
+}
+
+void KisImage::resize(TQ_INT32 w, TQ_INT32 h, TQ_INT32 x, TQ_INT32 y, bool cropLayers)
+{
+ if (w != width() || h != height()) {
+
+ lock();
+
+ if (undo()) {
+ if (cropLayers)
+ m_adapter->beginMacro(i18n("Crop Image"));
+ else
+ m_adapter->beginMacro(i18n("Resize Image"));
+
+ m_adapter->addCommand(new LockImageCommand(this, true));
+ m_adapter->addCommand(new KisResizeImageCmd(m_adapter, this, w, h, width(), height()));
+ }
+
+ m_width = w;
+ m_height = h;
+
+ if (cropLayers) {
+ KisCropVisitor v(TQRect(x, y, w, h));
+ m_rootLayer->accept(v);
+ }
+
+ emitSizeChanged();
+
+ unlock();
+
+ if (undo()) {
+ m_adapter->addCommand(new LockImageCommand(this, false));
+ m_adapter->endMacro();
+ }
+ }
+}
+
+void KisImage::resize(const TQRect& rc, bool cropLayers)
+{
+ resize(rc.width(), rc.height(), rc.x(), rc.y(), cropLayers);
+}
+
+
+void KisImage::scale(double sx, double sy, KisProgressDisplayInterface *progress, KisFilterStrategy *filterStrategy)
+{
+ if (nlayers() == 0) return; // Nothing to scale
+
+ // New image size. XXX: Pass along to discourage rounding errors?
+ TQ_INT32 w, h;
+ w = (TQ_INT32)(( width() * sx) + 0.5);
+ h = (TQ_INT32)(( height() * sy) + 0.5);
+
+ if (w != width() || h != height()) {
+
+ lock();
+
+ if (undo()) {
+ m_adapter->beginMacro(i18n("Scale Image"));
+ m_adapter->addCommand(new LockImageCommand(this, true));
+ }
+#if 0
+ if ( colorSpace()->id() == KisID("RGBA") || colorSpace()->id() == KisID("CMYK") || colorSpace()->id() == KisID("GRAYA")) {
+ KisScaleVisitor v (this, sx, sy, progress, filterStrategy);
+ m_rootLayer->accept( v );
+ }
+ else {
+#endif
+ KisTransformVisitor visitor (this, sx, sy, 0.0, 0.0, 0.0, 0, 0, progress, filterStrategy);
+ m_rootLayer->accept(visitor);
+// }
+
+ if (undo()) {
+ m_adapter->addCommand(new KisResizeImageCmd(m_adapter, this, w, h, width(), height()));
+ }
+
+ m_width = w;
+ m_height = h;
+
+ emitSizeChanged();
+
+ unlock();
+
+ if (undo()) {
+ m_adapter->addCommand(new LockImageCommand(this, false));
+ m_adapter->endMacro();
+ }
+ }
+}
+
+
+
+void KisImage::rotate(double radians, KisProgressDisplayInterface *progress)
+{
+ lock();
+
+ TQ_INT32 w = width();
+ TQ_INT32 h = height();
+ TQ_INT32 tx = TQ_INT32((w*cos(radians) - h*sin(radians) - w) / 2 + 0.5);
+ TQ_INT32 ty = TQ_INT32((h*cos(radians) + w*sin(radians) - h) / 2 + 0.5);
+ w = (TQ_INT32)(width()*TQABS(cos(radians)) + height()*TQABS(sin(radians)) + 0.5);
+ h = (TQ_INT32)(height()*TQABS(cos(radians)) + width()*TQABS(sin(radians)) + 0.5);
+
+ tx -= (w - width()) / 2;
+ ty -= (h - height()) / 2;
+
+ if (undo()) {
+ m_adapter->beginMacro(i18n("Rotate Image"));
+ m_adapter->addCommand(new LockImageCommand(this, true));
+ }
+
+ KisFilterStrategy *filter = KisFilterStrategyRegistry::instance()->get(KisID("Triangle"));
+ KisTransformVisitor visitor (this, 1.0, 1.0, 0, 0, radians, -tx, -ty, progress, filter);
+ m_rootLayer->accept(visitor);
+
+ if (undo()) m_adapter->addCommand(new KisResizeImageCmd(undoAdapter(), this, w, h, width(), height()));
+
+ m_width = w;
+ m_height = h;
+
+ emitSizeChanged();
+
+ unlock();
+
+ if (undo()) {
+ m_adapter->addCommand(new LockImageCommand(this, false));
+ m_adapter->endMacro();
+ }
+}
+
+void KisImage::shear(double angleX, double angleY, KisProgressDisplayInterface *m_progress)
+{
+ const double pi=3.1415926535897932385;
+
+ //new image size
+ TQ_INT32 w=width();
+ TQ_INT32 h=height();
+
+
+ if(angleX != 0 || angleY != 0){
+ double deltaY=height()*TQABS(tan(angleX*pi/180)*tan(angleY*pi/180));
+ w = (TQ_INT32) ( width() + TQABS(height()*tan(angleX*pi/180)) );
+ //ugly fix for the problem of having two extra pixels if only a shear along one
+ //axis is done. This has to be fixed in the cropping code in KisRotateVisitor!
+ if (angleX == 0 || angleY == 0)
+ h = (TQ_INT32) ( height() + TQABS(w*tan(angleY*pi/180)) );
+ else if (angleX > 0 && angleY > 0)
+ h = (TQ_INT32) ( height() + TQABS(w*tan(angleY*pi/180))- 2 * deltaY + 2 );
+ else if (angleX < 0 && angleY < 0)
+ h = (TQ_INT32) ( height() + TQABS(w*tan(angleY*pi/180))- 2 * deltaY + 2 );
+ else
+ h = (TQ_INT32) ( height() + TQABS(w*tan(angleY*pi/180)) );
+ }
+
+ if (w != width() || h != height()) {
+
+ lock();
+
+ if (undo()) {
+ m_adapter->beginMacro(i18n("Shear Image"));
+ m_adapter->addCommand(new LockImageCommand(this, true));
+ }
+
+ KisShearVisitor v(angleX, angleY, m_progress);
+ v.setUndoAdapter(undoAdapter());
+ rootLayer()->accept(v);
+
+ if (undo()) m_adapter->addCommand(new KisResizeImageCmd(m_adapter, this, w, h, width(), height()));
+
+ m_width = w;
+ m_height = h;
+
+ emitSizeChanged();
+
+ unlock();
+
+ if (undo()) {
+ m_adapter->addCommand(new LockImageCommand(this, false));
+ m_adapter->endMacro();
+ }
+ }
+}
+
+void KisImage::convertTo(KisColorSpace * dstColorSpace, TQ_INT32 renderingIntent)
+{
+ if ( m_colorSpace == dstColorSpace )
+ {
+ return;
+ }
+
+ lock();
+
+ KisColorSpace * oldCs = m_colorSpace;
+
+ if (undo()) {
+ m_adapter->beginMacro(i18n("Convert Image Type"));
+ m_adapter->addCommand(new LockImageCommand(this, true));
+ }
+
+ setColorSpace(dstColorSpace);
+
+ KisColorSpaceConvertVisitor visitor(dstColorSpace, renderingIntent);
+ m_rootLayer->accept(visitor);
+
+ unlock();
+
+ emit sigLayerPropertiesChanged( m_activeLayer );
+
+ if (undo()) {
+
+ m_adapter->addCommand(new KisConvertImageTypeCmd(undoAdapter(), this,
+ oldCs, dstColorSpace));
+ m_adapter->addCommand(new LockImageCommand(this, false));
+ m_adapter->endMacro();
+ }
+}
+
+KisProfile * KisImage::getProfile() const
+{
+ return colorSpace()->getProfile();
+}
+
+void KisImage::setProfile(const KisProfile * profile)
+{
+ if (profile == 0) return;
+
+ KisColorSpace * dstCs= KisMetaRegistry::instance()->csRegistry()->getColorSpace( colorSpace()->id(),
+ profile);
+ if (dstCs) {
+
+ lock();
+
+ KisColorSpace * oldCs = colorSpace();
+ setColorSpace(dstCs);
+ emit(sigProfileChanged(const_cast<KisProfile *>(profile)));
+
+ KisChangeProfileVisitor visitor(oldCs, dstCs);
+ m_rootLayer->accept(visitor);
+
+ unlock();
+ }
+}
+
+double KisImage::xRes()
+{
+ return m_xres;
+}
+
+double KisImage::yRes()
+{
+ return m_yres;
+}
+
+void KisImage::setResolution(double xres, double yres)
+{
+ m_xres = xres;
+ m_yres = yres;
+}
+
+TQ_INT32 KisImage::width() const
+{
+ return m_width;
+}
+
+TQ_INT32 KisImage::height() const
+{
+ return m_height;
+}
+
+KisPaintDeviceSP KisImage::activeDevice()
+{
+ if (KisPaintLayer* layer = dynamic_cast<KisPaintLayer*>(m_activeLayer.data())) {
+ return layer->paintDeviceOrMask();
+ }
+ else if (KisAdjustmentLayer* layer = dynamic_cast<KisAdjustmentLayer*>(m_activeLayer.data())) {
+ if (layer->selection()) {
+ return layer->selection().data();
+ }
+ }
+ else if (KisGroupLayer * layer = dynamic_cast<KisGroupLayer*>(m_activeLayer.data())) {
+ // Find first child
+ KisLayerSP child = layer->lastChild();
+ while(child)
+ {
+ if (KisPaintLayer* layer = dynamic_cast<KisPaintLayer*>(child.data())) {
+ return layer->paintDevice();
+ }
+ child = child->prevSibling();
+ }
+ KisLayerSP sibling = layer->nextSibling();
+ while (sibling) {
+ if (KisPaintLayer* layer = dynamic_cast<KisPaintLayer*>(sibling.data())) {
+ return layer->paintDevice();
+ }
+ sibling = sibling->nextSibling();
+ }
+ }
+ else if (KisLayerSP layer = m_activeLayer) {
+ // A weird layer -- let's not return it, but a sibling
+ KisLayerSP sibling = layer->nextSibling();
+ while (sibling) {
+ if (KisPaintLayer* layer = dynamic_cast<KisPaintLayer*>(sibling.data())) {
+ return layer->paintDevice();
+ }
+ sibling = sibling->nextSibling();
+ }
+ }
+ // XXX: We're buggered!
+ return 0;
+}
+
+KisLayerSP KisImage::newLayer(const TQString& name, TQ_UINT8 opacity, const KisCompositeOp& compositeOp, KisColorSpace * colorstrategy)
+{
+ KisPaintLayer * layer;
+ if (colorstrategy)
+ layer = new KisPaintLayer(this, name, opacity, colorstrategy);
+ else
+ layer = new KisPaintLayer(this, name, opacity);
+ TQ_CHECK_PTR(layer);
+
+ if (compositeOp.isValid())
+ layer->setCompositeOp(compositeOp);
+ layer->setVisible(true);
+
+ if (m_activeLayer != 0) {
+ addLayer(layer, m_activeLayer->parent().data(), m_activeLayer->nextSibling());
+ }
+ else {
+ addLayer(layer, m_rootLayer, 0);
+ }
+ activate(layer);
+
+ return layer;
+}
+
+void KisImage::setLayerProperties(KisLayerSP layer, TQ_UINT8 opacity, const KisCompositeOp& compositeOp, const TQString& name)
+{
+ if (layer && (layer->opacity() != opacity || layer->compositeOp() != compositeOp || layer->name() != name)) {
+ if (undo()) {
+ TQString oldname = layer->name();
+ TQ_INT32 oldopacity = layer->opacity();
+ KisCompositeOp oldCompositeOp = layer->compositeOp();
+ layer->setName(name);
+ layer->setOpacity(opacity);
+ layer->setCompositeOp(compositeOp);
+ m_adapter->addCommand(new LayerPropsCmd(layer, this, m_adapter, oldname, oldopacity, oldCompositeOp));
+ } else {
+ layer->setName(name);
+ layer->setOpacity(opacity);
+ layer->setCompositeOp(compositeOp);
+ }
+ }
+}
+
+KisGroupLayerSP KisImage::rootLayer() const
+{
+ return m_rootLayer;
+}
+
+KisLayerSP KisImage::activeLayer() const
+{
+ return m_activeLayer;
+}
+
+KisPaintDeviceSP KisImage::projection()
+{
+ return m_rootLayer->projection(TQRect(0, 0, m_width, m_height));
+}
+
+KisLayerSP KisImage::activate(KisLayerSP layer)
+{
+ if (layer != m_activeLayer) {
+ if (m_activeLayer) m_activeLayer->deactivate();
+ m_activeLayer = layer;
+ if (m_activeLayer) m_activeLayer->activate();
+ emit sigLayerActivated(m_activeLayer);
+ emit sigMaskInfoChanged();
+ }
+
+ return layer;
+}
+
+KisLayerSP KisImage::findLayer(const TQString& name) const
+{
+ return rootLayer()->findLayer(name);
+}
+
+KisLayerSP KisImage::findLayer(int id) const
+{
+ return rootLayer()->findLayer(id);
+}
+
+
+bool KisImage::addLayer(KisLayerSP layer, KisGroupLayerSP parent)
+{
+ return addLayer(layer, parent, parent->firstChild());
+}
+
+bool KisImage::addLayer(KisLayerSP layer, KisGroupLayerSP parent, KisLayerSP aboveThis)
+{
+ if (!parent)
+ return false;
+
+ const bool success = parent->addLayer(layer, aboveThis);
+ if (success)
+ {
+ KisPaintLayerSP player = dynamic_cast<KisPaintLayer*>(layer.data());
+ if (player != 0) {
+
+ // XXX: This should also be done whenever a layer grows!
+ TQValueVector<KisPaintDeviceAction *> actions = KisMetaRegistry::instance() ->
+ csRegistry()->paintDeviceActionsFor(player->paintDevice()->colorSpace());
+ for (uint i = 0; i < actions.count(); i++) {
+ actions.at(i)->act(player.data()->paintDevice(), width(), height());
+ }
+
+ connect(player, TQT_SIGNAL(sigMaskInfoChanged()), this, TQT_SIGNAL(sigMaskInfoChanged()));
+ }
+
+ if (layer->extent().isValid()) layer->setDirty();
+
+ if (!layer->temporary()) {
+ emit sigLayerAdded(layer);
+ activate(layer);
+ }
+
+
+ if (!layer->temporary() && undo()) {
+ m_adapter->addCommand(new LayerAddCmd(m_adapter, this, layer));
+ }
+ }
+
+ return success;
+}
+
+bool KisImage::removeLayer(KisLayerSP layer)
+{
+ if (!layer || layer->image() != this)
+ return false;
+
+ if (KisGroupLayerSP parent = layer->parent()) {
+ // Adjustment layers should mark the layers underneath them, whose rendering
+ // they have cached, diryt on removal. Otherwise, the group won't be re-rendered.
+ KisAdjustmentLayer * al = dynamic_cast<KisAdjustmentLayer*>(layer.data());
+ if (al) {
+ TQRect r = al->extent();
+ lock(); // Lock the image, because we are going to dirty a lot of layers
+ KisLayerSP l = layer->nextSibling();
+ while (l) {
+ KisAdjustmentLayer * al2 = dynamic_cast<KisAdjustmentLayer*>(l.data());
+ l->setDirty(r, false);
+ if (al2 != 0) break;
+ l = l->nextSibling();
+ }
+ unlock();
+ }
+ KisPaintLayerSP player = dynamic_cast<KisPaintLayer*>(layer.data());
+ if (player != 0) {
+ disconnect(player, TQT_SIGNAL(sigMaskInfoChanged()),
+ this, TQT_SIGNAL(sigMaskInfoChanged()));
+ }
+ KisLayerSP l = layer->prevSibling();
+ TQRect r = layer->extent();
+ while (l) {
+ l->setDirty(r, false);
+ l = l->prevSibling();
+ }
+
+ KisLayerSP wasAbove = layer->nextSibling();
+ KisLayerSP wasBelow = layer->prevSibling();
+ const bool wasActive = layer == activeLayer();
+ // sigLayerRemoved can set it to 0, we don't want that in the else of wasActive!
+ KisLayerSP actLayer = activeLayer();
+ const bool success = parent->removeLayer(layer);
+ if (success) {
+ layer->setImage(0);
+ if (!layer->temporary() && undo()) {
+ m_adapter->addCommand(new LayerRmCmd(m_adapter, this, layer, parent, wasAbove));
+ }
+ if (!layer->temporary()) {
+ emit sigLayerRemoved(layer, parent, wasAbove);
+ if (wasActive) {
+ if (wasBelow)
+ activate(wasBelow);
+ else if (wasAbove)
+ activate(wasAbove);
+ else if (parent != rootLayer())
+ activate(parent.data());
+ else
+ activate(rootLayer()->firstChild());
+ } else {
+ activate(actLayer);
+ }
+ }
+ }
+ return success;
+ }
+
+ return false;
+}
+
+bool KisImage::raiseLayer(KisLayerSP layer)
+{
+ if (!layer)
+ return false;
+ return moveLayer(layer, layer->parent().data(), layer->prevSibling());
+}
+
+bool KisImage::lowerLayer(KisLayerSP layer)
+{
+ if (!layer)
+ return false;
+ if (KisLayerSP next = layer->nextSibling())
+ return moveLayer(layer, layer->parent().data(), next->nextSibling());
+ return false;
+}
+
+bool KisImage::toTop(KisLayerSP layer)
+{
+ if (!layer)
+ return false;
+ return moveLayer(layer, rootLayer(), rootLayer()->firstChild());
+}
+
+bool KisImage::toBottom(KisLayerSP layer)
+{
+ if (!layer)
+ return false;
+ return moveLayer(layer, rootLayer(), 0);
+}
+
+bool KisImage::moveLayer(KisLayerSP layer, KisGroupLayerSP parent, KisLayerSP aboveThis)
+{
+ if (!parent)
+ return false;
+
+ KisGroupLayerSP wasParent = layer->parent();
+ KisLayerSP wasAbove = layer->nextSibling();
+
+ if (wasParent.data() == parent.data() && wasAbove.data() == aboveThis.data())
+ return false;
+
+ lock();
+
+ if (!wasParent->removeLayer(layer)) {
+ unlock();
+ return false;
+ }
+
+ const bool success = parent->addLayer(layer, aboveThis);
+
+ layer->setDirty();
+
+ unlock();
+
+ if (success)
+ {
+ emit sigLayerMoved(layer, wasParent, wasAbove);
+ if (undo())
+ m_adapter->addCommand(new LayerMoveCmd(m_adapter, this, layer, wasParent, wasAbove));
+ }
+ else //we already removed the layer above, but re-adding it failed, so...
+ {
+ emit sigLayerRemoved(layer, wasParent, wasAbove);
+ if (undo())
+ m_adapter->addCommand(new LayerRmCmd(m_adapter, this, layer, wasParent, wasAbove));
+ }
+
+ return success;
+}
+
+TQ_INT32 KisImage::nlayers() const
+{
+ return rootLayer()->numLayers() - 1;
+}
+
+TQ_INT32 KisImage::nHiddenLayers() const
+{
+ return rootLayer()->numLayers(KisLayer::Hidden);
+}
+
+void KisImage::flatten()
+{
+ KisGroupLayerSP oldRootLayer = m_rootLayer;
+ disconnect(oldRootLayer, TQT_SIGNAL(sigDirty(TQRect)), this, TQT_SIGNAL(sigImageUpdated(TQRect)));
+
+ KisPaintLayer *dst = new KisPaintLayer(this, nextLayerName(), OPACITY_OPAQUE, colorSpace());
+ TQ_CHECK_PTR(dst);
+
+ TQRect rc = mergedImage()->extent();
+
+ KisPainter gc(dst->paintDevice());
+ gc.bitBlt(rc.x(), rc.y(), COMPOSITE_COPY, mergedImage(), OPACITY_OPAQUE, rc.left(), rc.top(), rc.width(), rc.height());
+
+ m_rootLayer = new KisGroupLayer(this, "", OPACITY_OPAQUE);
+ connect(m_rootLayer, TQT_SIGNAL(sigDirty(TQRect)), this, TQT_SIGNAL(sigImageUpdated(TQRect)));
+
+ if (undo()) {
+ m_adapter->beginMacro(i18n("Flatten Image"));
+ m_adapter->addCommand(new LockImageCommand(this, true));
+ m_adapter->addCommand(new KisChangeLayersCmd(m_adapter, this, oldRootLayer, m_rootLayer, ""));
+ }
+
+ lock();
+
+ addLayer(dst, m_rootLayer, 0);
+ activate(dst);
+
+ unlock();
+
+ notifyLayersChanged();
+
+ if (undo()) {
+ m_adapter->addCommand(new LockImageCommand(this, false));
+ m_adapter->endMacro();
+ }
+}
+
+
+void KisImage::mergeLayer(KisLayerSP layer)
+{
+ KisPaintLayer *player = new KisPaintLayer(this, layer->name(), OPACITY_OPAQUE, colorSpace());
+ TQ_CHECK_PTR(player);
+
+ TQRect rc = layer->extent() | layer->nextSibling()->extent();
+
+ undoAdapter()->beginMacro(i18n("Merge with Layer Below"));
+
+ //Abuse the merge visitor to only merge two layers (if either are groups they'll recursively merge)
+ KisMergeVisitor visitor(player->paintDevice(), rc);
+ layer->nextSibling()->accept(visitor);
+ layer->accept(visitor);
+
+ removeLayer(layer->nextSibling());
+ addLayer(player, layer->parent(), layer);
+ removeLayer(layer);
+
+ undoAdapter()->endMacro();
+}
+
+
+void KisImage::setModified()
+{
+ emit sigImageModified();
+}
+
+void KisImage::renderToPainter(TQ_INT32 x1,
+ TQ_INT32 y1,
+ TQ_INT32 x2,
+ TQ_INT32 y2,
+ TQPainter &painter,
+ KisProfile * monitorProfile,
+ PaintFlags paintFlags,
+ float exposure)
+{
+
+ TQImage img = convertToTQImage(x1, y1, x2, y2, monitorProfile, exposure);
+
+ TQ_INT32 w = x2 - x1 + 1;
+ TQ_INT32 h = y2 - y1 + 1;
+
+
+ if (paintFlags & PAINT_BACKGROUND) {
+ m_bkg->paintBackground(img, x1, y1);
+ img.setAlphaBuffer(false);
+ }
+
+ if (paintFlags & PAINT_SELECTION) {
+ if (m_activeLayer != 0) {
+ m_activeLayer->paintSelection(img, x1, y1, w, h);
+ }
+ }
+
+ if (paintFlags & PAINT_MASKINACTIVELAYERS) {
+ if (m_activeLayer != 0) {
+ m_activeLayer->paintMaskInactiveLayers(img, x1, y1, w, h);
+ }
+ }
+
+ painter.drawImage(x1, y1, img, 0, 0, w, h);
+}
+
+TQImage KisImage::convertToTQImage(TQ_INT32 x1,
+ TQ_INT32 y1,
+ TQ_INT32 x2,
+ TQ_INT32 y2,
+ KisProfile * profile,
+ float exposure)
+{
+ TQ_INT32 w = x2 - x1 + 1;
+ TQ_INT32 h = y2 - y1 + 1;
+
+ KisPaintDeviceSP dev = m_rootLayer->projection(TQRect(x1, y1, w, h));
+ TQImage img = dev->convertToTQImage(profile, x1, y1, w, h, exposure);
+
+ if (!img.isNull()) {
+
+#ifdef __BIG_ENDIAN__
+ uchar * data = img.bits();
+ for (int i = 0; i < w * h; ++i) {
+ uchar r, g, b, a;
+ a = data[0];
+ b = data[1];
+ g = data[2];
+ r = data[3];
+ data[0] = r;
+ data[1] = g;
+ data[2] = b;
+ data[3] = a;
+ data += 4;
+ }
+#endif
+
+ return img;
+ }
+
+ return TQImage();
+}
+
+TQImage KisImage::convertToTQImage(const TQRect& r, const TQSize& scaledImageSize, KisProfile *profile, PaintFlags paintFlags, float exposure)
+{
+
+ if (r.isEmpty() || scaledImageSize.isEmpty()) {
+ return TQImage();
+ }
+
+ TQ_INT32 imageWidth = width();
+ TQ_INT32 imageHeight = height();
+ TQ_UINT32 pixelSize = colorSpace()->pixelSize();
+
+ double xScale = static_cast<double>(imageWidth) / scaledImageSize.width();
+ double yScale = static_cast<double>(imageHeight) / scaledImageSize.height();
+
+ TQRect srcRect;
+
+ srcRect.setLeft(static_cast<int>(r.left() * xScale));
+ srcRect.setRight(static_cast<int>(ceil((r.right() + 1) * xScale)) - 1);
+ srcRect.setTop(static_cast<int>(r.top() * yScale));
+ srcRect.setBottom(static_cast<int>(ceil((r.bottom() + 1) * yScale)) - 1);
+
+ KisPaintDeviceSP mergedImage = m_rootLayer->projection(srcRect);
+ TQTime t;
+ t.start();
+
+ TQ_UINT8 *scaledImageData = new TQ_UINT8[r.width() * r.height() * pixelSize];
+
+ TQ_UINT8 *imageRow = new TQ_UINT8[srcRect.width() * pixelSize];
+ const TQ_INT32 imageRowX = srcRect.x();
+
+ for (TQ_INT32 y = 0; y < r.height(); ++y) {
+
+ TQ_INT32 dstY = r.y() + y;
+ TQ_INT32 dstX = r.x();
+ TQ_INT32 srcY = (dstY * imageHeight) / scaledImageSize.height();
+
+ mergedImage->readBytes(imageRow, imageRowX, srcY, srcRect.width(), 1);
+
+ TQ_UINT8 *dstPixel = scaledImageData + (y * r.width() * pixelSize);
+ TQ_UINT32 columnsRemaining = r.width();
+
+ while (columnsRemaining > 0) {
+
+ TQ_INT32 srcX = (dstX * imageWidth) / scaledImageSize.width();
+
+ memcpy(dstPixel, imageRow + ((srcX - imageRowX) * pixelSize), pixelSize);
+
+ ++dstX;
+ dstPixel += pixelSize;
+ --columnsRemaining;
+ }
+ }
+ kdDebug() << "Time elapsed scaling image: " << t.elapsed() << endl;
+
+ delete [] imageRow;
+
+ TQImage image = colorSpace()->convertToTQImage(scaledImageData, r.width(), r.height(), profile, INTENT_PERCEPTUAL, exposure);
+ delete [] scaledImageData;
+
+#ifdef __BIG_ENDIAN__
+ uchar * data = image.bits();
+ for (int i = 0; i < image.width() * image.height(); ++i) {
+ uchar r, g, b, a;
+ a = data[0];
+ b = data[1];
+ g = data[2];
+ r = data[3];
+ data[0] = r;
+ data[1] = g;
+ data[2] = b;
+ data[3] = a;
+ data += 4;
+ }
+#endif
+
+ if (paintFlags & PAINT_BACKGROUND) {
+ m_bkg->paintBackground(image, r, scaledImageSize, TQSize(imageWidth, imageHeight));
+ image.setAlphaBuffer(false);
+ }
+
+ if (paintFlags & PAINT_SELECTION) {
+ if (m_activeLayer != 0) {
+ m_activeLayer->paintSelection(image, r, scaledImageSize, TQSize(imageWidth, imageHeight));
+ }
+ }
+
+ /*if (paintFlags & PAINT_MASKINACTIVELAYERS) {
+ if (m_activeLayer != 0) {
+ m_activeLayer->paintMaskInactiveLayers(img, x1, y1, w, h);
+ }
+ }*/
+
+ return image;
+}
+
+KisPaintDeviceSP KisImage::mergedImage()
+{
+ return m_rootLayer->projection(TQRect(0, 0, m_width, m_height));
+}
+
+KisColor KisImage::mergedPixel(TQ_INT32 x, TQ_INT32 y)
+{
+ return m_rootLayer->projection(TQRect(x, y, 1, 1))->colorAt(x, y);
+}
+
+void KisImage::notifyLayersChanged()
+{
+ emit sigLayersChanged(rootLayer());
+}
+
+void KisImage::notifyPropertyChanged(KisLayerSP layer)
+{
+ emit sigLayerPropertiesChanged(layer);
+}
+
+void KisImage::notifyImageLoaded()
+{
+}
+
+TQRect KisImage::bounds() const
+{
+ return TQRect(0, 0, width(), height());
+}
+
+
+void KisImage::setUndoAdapter(KisUndoAdapter * adapter)
+{
+ m_adapter = adapter;
+}
+
+
+KisUndoAdapter* KisImage::undoAdapter() const
+{
+ return m_adapter;
+}
+
+bool KisImage::undo() const
+{
+ return (m_adapter && m_adapter->undo());
+}
+
+//KisGuideMgr *KisImage::guides() const
+//{
+// return const_cast<KisGuideMgr*>(&m_guides);
+//}
+
+void KisImage::slotSelectionChanged()
+{
+ slotSelectionChanged(bounds());
+}
+
+void KisImage::slotSelectionChanged(const TQRect& r)
+{
+ TQRect r2(r.x() - 1, r.y() - 1, r.width() + 2, r.height() + 2);
+
+ if (!locked()) {
+ emit sigActiveSelectionChanged(this);
+ emit sigSelectionChanged(this);
+ } else {
+ m_private->selectionChangedWhileLocked = true;
+ }
+}
+
+KisColorSpace * KisImage::colorSpace() const
+{
+ return m_colorSpace;
+}
+
+void KisImage::setColorSpace(KisColorSpace * colorSpace)
+{
+ m_colorSpace = colorSpace;
+ m_rootLayer->resetProjection();
+ emit sigColorSpaceChanged(colorSpace);
+}
+
+void KisImage::setRootLayer(KisGroupLayerSP rootLayer)
+{
+ disconnect(m_rootLayer, TQT_SIGNAL(sigDirty(TQRect)), this, TQT_SIGNAL(sigImageUpdated(TQRect)));
+
+ m_rootLayer = rootLayer;
+
+ if (!locked()) {
+ connect(m_rootLayer, TQT_SIGNAL(sigDirty(TQRect)), this, TQT_SIGNAL(sigImageUpdated(TQRect)));
+ }
+ activate(m_rootLayer->firstChild());
+}
+
+void KisImage::addAnnotation(KisAnnotationSP annotation)
+{
+ // Find the icc annotation, if there is one
+ vKisAnnotationSP_it it = m_annotations.begin();
+ while (it != m_annotations.end()) {
+ if ((*it)->type() == annotation->type()) {
+ *it = annotation;
+ return;
+ }
+ ++it;
+ }
+ m_annotations.push_back(annotation);
+}
+
+KisAnnotationSP KisImage::annotation(TQString type)
+{
+ vKisAnnotationSP_it it = m_annotations.begin();
+ while (it != m_annotations.end()) {
+ if ((*it)->type() == type) {
+ return *it;
+ }
+ ++it;
+ }
+ return 0;
+}
+
+void KisImage::removeAnnotation(TQString type)
+{
+ vKisAnnotationSP_it it = m_annotations.begin();
+ while (it != m_annotations.end()) {
+ if ((*it)->type() == type) {
+ m_annotations.erase(it);
+ return;
+ }
+ ++it;
+ }
+}
+
+vKisAnnotationSP_it KisImage::beginAnnotations()
+{
+ KisProfile * profile = colorSpace()->getProfile();
+ KisAnnotationSP annotation;
+
+ if (profile)
+ annotation = profile->annotation();
+
+ if (annotation)
+ addAnnotation(annotation);
+ else
+ removeAnnotation("icc");
+
+ return m_annotations.begin();
+}
+
+vKisAnnotationSP_it KisImage::endAnnotations()
+{
+ return m_annotations.end();
+}
+
+KisBackgroundSP KisImage::background() const
+{
+ return m_bkg;
+}
+
+KisPerspectiveGrid* KisImage::perspectiveGrid()
+{
+ return m_private->perspectiveGrid;
+}
+
+#include "kis_image.moc"
+