krita

kis_layer.cc

00001 /*
00002  *  Copyright (c) 2002 Patrick Julien <freak@codepimps.org>
00003  *  Copyright (c) 2005 Casper Boemann <cbr@boemann.dk>
00004  *
00005  *  this program is free software; you can redistribute it and/or modify
00006  *  it under the terms of the gnu general public license as published by
00007  *  the free software foundation; either version 2 of the license, or
00008  *  (at your option) any later version.
00009  *
00010  *  this program is distributed in the hope that it will be useful,
00011  *  but without any warranty; without even the implied warranty of
00012  *  merchantability or fitness for a particular purpose.  see the
00013  *  gnu general public license for more details.
00014  *
00015  *  you should have received a copy of the gnu general public license
00016  *  along with this program; if not, write to the free software
00017  *  foundation, inc., 675 mass ave, cambridge, ma 02139, usa.
00018  */
00019 
00020 #include <kdebug.h>
00021 #include <qimage.h>
00022 
00023 #include "kis_debug_areas.h"
00024 #include "kis_group_layer.h"
00025 #include "kis_image.h"
00026 #include "kis_layer.h"
00027 #include "kis_painter.h"
00028 #include "kis_undo_adapter.h"
00029 
00030 namespace {
00031 
00032     class KisLayerCommand : public KNamedCommand {
00033         typedef KNamedCommand super;
00034 
00035     public:
00036         KisLayerCommand(const QString& name, KisLayerSP layer);
00037         virtual ~KisLayerCommand() {}
00038 
00039         virtual void execute() = 0;
00040         virtual void unexecute() = 0;
00041 
00042     protected:
00043         void setUndo(bool undo);
00044 
00045         KisLayerSP m_layer;
00046     };
00047 
00048     KisLayerCommand::KisLayerCommand(const QString& name, KisLayerSP layer) :
00049         super(name), m_layer(layer)
00050     {
00051     }
00052 
00053     void KisLayerCommand::setUndo(bool undo)
00054     {
00055         if (m_layer->undoAdapter()) {
00056             m_layer->undoAdapter()->setUndo(undo);
00057         }
00058     }
00059 
00060     class KisLayerLockedCommand : public KisLayerCommand {
00061         typedef KisLayerCommand super;
00062 
00063     public:
00064         KisLayerLockedCommand(KisLayerSP layer, bool newLocked);
00065 
00066         virtual void execute();
00067         virtual void unexecute();
00068 
00069     private:
00070         bool m_newLocked;
00071     };
00072 
00073     KisLayerLockedCommand::KisLayerLockedCommand(KisLayerSP layer, bool newLocked) :
00074         super(i18n("Lock Layer"), layer)
00075     {
00076         m_newLocked = newLocked;
00077     }
00078 
00079     void KisLayerLockedCommand::execute()
00080     {
00081         setUndo(false);
00082         m_layer->setLocked(m_newLocked);
00083         setUndo(true);
00084     }
00085 
00086     void KisLayerLockedCommand::unexecute()
00087     {
00088         setUndo(false);
00089         m_layer->setLocked(!m_newLocked);
00090         setUndo(true);
00091     }
00092 
00093     class KisLayerOpacityCommand : public KisLayerCommand {
00094         typedef KisLayerCommand super;
00095 
00096     public:
00097         KisLayerOpacityCommand(KisLayerSP layer, Q_UINT8 oldOpacity, Q_UINT8 newOpacity);
00098 
00099         virtual void execute();
00100         virtual void unexecute();
00101 
00102     private:
00103         Q_UINT8 m_oldOpacity;
00104         Q_UINT8 m_newOpacity;
00105     };
00106 
00107     KisLayerOpacityCommand::KisLayerOpacityCommand(KisLayerSP layer, Q_UINT8 oldOpacity, Q_UINT8 newOpacity) :
00108         super(i18n("Layer Opacity"), layer)
00109     {
00110         m_oldOpacity = oldOpacity;
00111         m_newOpacity = newOpacity;
00112     }
00113 
00114     void KisLayerOpacityCommand::execute()
00115     {
00116         setUndo(false);
00117         m_layer->setOpacity(m_newOpacity);
00118         setUndo(true);
00119     }
00120 
00121     void KisLayerOpacityCommand::unexecute()
00122     {
00123         setUndo(false);
00124         m_layer->setOpacity(m_oldOpacity);
00125         setUndo(true);
00126     }
00127 
00128     class KisLayerVisibilityCommand : public KisLayerCommand {
00129         typedef KisLayerCommand super;
00130 
00131     public:
00132         KisLayerVisibilityCommand(KisLayerSP layer, bool newVisibility);
00133 
00134         virtual void execute();
00135         virtual void unexecute();
00136 
00137     private:
00138         bool m_newVisibility;
00139     };
00140 
00141     KisLayerVisibilityCommand::KisLayerVisibilityCommand(KisLayerSP layer, bool newVisibility) :
00142         super(i18n("Layer Visibility"), layer)
00143     {
00144         m_newVisibility = newVisibility;
00145     }
00146 
00147     void KisLayerVisibilityCommand::execute()
00148     {
00149         setUndo(false);
00150         m_layer->setVisible(m_newVisibility);
00151         setUndo(true);
00152     }
00153 
00154     void KisLayerVisibilityCommand::unexecute()
00155     {
00156         setUndo(false);
00157         m_layer->setVisible(!m_newVisibility);
00158         setUndo(true);
00159     }
00160 
00161     class KisLayerCompositeOpCommand : public KisLayerCommand {
00162         typedef KisLayerCommand super;
00163 
00164     public:
00165         KisLayerCompositeOpCommand(KisLayerSP layer, const KisCompositeOp& oldCompositeOp, const KisCompositeOp& newCompositeOp);
00166 
00167         virtual void execute();
00168         virtual void unexecute();
00169 
00170     private:
00171         KisCompositeOp m_oldCompositeOp;
00172         KisCompositeOp m_newCompositeOp;
00173     };
00174 
00175     KisLayerCompositeOpCommand::KisLayerCompositeOpCommand(KisLayerSP layer, const KisCompositeOp& oldCompositeOp,
00176                                        const KisCompositeOp& newCompositeOp) :
00177         super(i18n("Layer Composite Mode"), layer)
00178     {
00179         m_oldCompositeOp = oldCompositeOp;
00180         m_newCompositeOp = newCompositeOp;
00181     }
00182 
00183     void KisLayerCompositeOpCommand::execute()
00184     {
00185         setUndo(false);
00186         m_layer->setCompositeOp(m_newCompositeOp);
00187         setUndo(true);
00188     }
00189 
00190     void KisLayerCompositeOpCommand::unexecute()
00191     {
00192         setUndo(false);
00193         m_layer->setCompositeOp(m_oldCompositeOp);
00194         setUndo(true);
00195     }
00196 
00197     class KisLayerOffsetCommand : public KNamedCommand {
00198         typedef KNamedCommand super;
00199 
00200     public:
00201         KisLayerOffsetCommand(KisLayerSP layer, const QPoint& oldpos, const QPoint& newpos);
00202         virtual ~KisLayerOffsetCommand();
00203 
00204         virtual void execute();
00205         virtual void unexecute();
00206 
00207     private:
00208         void moveTo(const QPoint& pos);
00209 
00210     private:
00211         KisLayerSP m_layer;
00212         QRect m_updateRect;
00213         QPoint m_oldPos;
00214         QPoint m_newPos;
00215     };
00216 
00217     KisLayerOffsetCommand::KisLayerOffsetCommand(KisLayerSP layer, const QPoint& oldpos, const QPoint& newpos) :
00218         super(i18n("Move Layer"))
00219     {
00220         m_layer = layer;
00221         m_oldPos = oldpos;
00222         m_newPos = newpos;
00223 
00224         QRect currentBounds = m_layer->exactBounds();
00225         QRect oldBounds = currentBounds;
00226         oldBounds.moveBy(oldpos.x() - newpos.x(), oldpos.y() - newpos.y());
00227 
00228         m_updateRect = currentBounds | oldBounds;
00229     }
00230 
00231     KisLayerOffsetCommand::~KisLayerOffsetCommand()
00232     {
00233     }
00234 
00235     void KisLayerOffsetCommand::execute()
00236     {
00237         moveTo(m_newPos);
00238     }
00239 
00240     void KisLayerOffsetCommand::unexecute()
00241     {
00242         moveTo(m_oldPos);
00243     }
00244 
00245     void KisLayerOffsetCommand::moveTo(const QPoint& pos)
00246     {
00247         if (m_layer->undoAdapter()) {
00248             m_layer->undoAdapter()->setUndo(false);
00249         }
00250 
00251         m_layer->setX(pos.x());
00252         m_layer->setY(pos.y());
00253 
00254         m_layer->setDirty(m_updateRect);
00255 
00256         if (m_layer->undoAdapter()) {
00257             m_layer->undoAdapter()->setUndo(true);
00258         }
00259     }
00260 }
00261 
00262 static int getID()
00263 {
00264     static int id = 1;
00265     return id++;
00266 }
00267 
00268 
00269 KisLayer::KisLayer(KisImage *img, const QString &name, Q_UINT8 opacity) :
00270     QObject(0, name.latin1()),
00271     KShared(),
00272     m_id(getID()),
00273     m_index(-1),
00274     m_opacity(opacity),
00275     m_locked(false),
00276     m_visible(true),
00277     m_temporary(false),
00278     m_name(name),
00279     m_parent(0),
00280     m_image(img),
00281     m_compositeOp(COMPOSITE_OVER)
00282 {
00283 }
00284 
00285 KisLayer::KisLayer(const KisLayer& rhs) :
00286     QObject(),
00287     KShared(rhs)
00288 {
00289     if (this != &rhs) {
00290         m_id = getID();
00291         m_index = -1;
00292         m_opacity = rhs.m_opacity;
00293         m_locked = rhs.m_locked;
00294         m_visible = rhs.m_visible;
00295         m_temporary = rhs.m_temporary;
00296         m_dirtyRect = rhs.m_dirtyRect;
00297         m_name = rhs.m_name;
00298         m_image = rhs.m_image;
00299         m_parent = 0;
00300         m_compositeOp = rhs.m_compositeOp;
00301     }
00302 }
00303 
00304 KisLayer::~KisLayer()
00305 {
00306 }
00307 
00308 void KisLayer::setClean(const QRect & rect)
00309 {
00310     if (m_dirtyRect.isValid() && rect.isValid()) {
00311 
00312         // XXX: We should only set the parts clean that were actually cleaned. However, extent and exactBounds conspire
00313         // to make that very hard atm.
00314         //if (rect.contains(m_dirtyRect)) m_dirtyRect = QRect();
00315         m_dirtyRect = QRect();
00316     }
00317 
00318 }
00319 
00320 bool KisLayer::dirty()
00321 {
00322     return m_dirtyRect.isValid();
00323 }
00324 
00325 
00326 bool KisLayer::dirty(const QRect & rc)
00327 {
00328     if (!m_dirtyRect.isValid() || !rc.isValid()) return false;
00329 
00330     return rc.intersects(m_dirtyRect);
00331 }
00332 
00333 QRect KisLayer::dirtyRect() const
00334 {
00335     return m_dirtyRect;
00336 }
00337 
00338 void KisLayer::setDirty(bool propagate)
00339 {
00340     QRect rc = extent();
00341 
00342     if (rc.isValid()) m_dirtyRect = rc;
00343 
00344     // If we're dirty, our parent is dirty, if we've got a parent
00345     if (propagate && m_parent && rc.isValid()) m_parent->setDirty(m_dirtyRect);
00346 
00347     if (m_image && rc.isValid()) {
00348         m_image->notifyLayerUpdated(this, rc);
00349     }
00350 }
00351 
00352 void KisLayer::setDirty(const QRect & rc, bool propagate)
00353 {
00354     // If we're dirty, our parent is dirty, if we've got a parent
00355 
00356     if (rc.isValid())
00357         m_dirtyRect |= rc;
00358 
00359     if (propagate && m_parent && m_dirtyRect.isValid())
00360         m_parent->setDirty(m_dirtyRect);
00361 
00362     if (m_image && rc.isValid()) {
00363         m_image->notifyLayerUpdated(this, rc);
00364     }
00365 }
00366 
00367 KisGroupLayerSP KisLayer::parent() const
00368 {
00369     return m_parent;
00370 }
00371 
00372 KisLayerSP KisLayer::prevSibling() const
00373 {
00374     if (!parent())
00375         return 0;
00376     return parent()->at(index() - 1);
00377 }
00378 
00379 KisLayerSP KisLayer::nextSibling() const
00380 {
00381     if (!parent())
00382         return 0;
00383     return parent()->at(index() + 1);
00384 }
00385 
00386 int KisLayer::index() const
00387 {
00388     return m_index;
00389 }
00390 
00391 void KisLayer::setIndex(int i)
00392 {
00393     if (!parent())
00394         return;
00395     parent()->setIndex(this, i);
00396 }
00397 
00398 KisLayerSP KisLayer::findLayer(const QString& n) const
00399 {
00400     if (name() == n)
00401         return const_cast<KisLayer*>(this); //HACK any less ugly way? findLayer() is conceptually const...
00402     for (KisLayerSP layer = firstChild(); layer; layer = layer->nextSibling())
00403         if (KisLayerSP found = layer->findLayer(n))
00404             return found;
00405     return 0;
00406 }
00407 
00408 KisLayerSP KisLayer::findLayer(int i) const
00409 {
00410     if (id() == i)
00411         return const_cast<KisLayer*>(this); //HACK
00412     for (KisLayerSP layer = firstChild(); layer; layer = layer->nextSibling())
00413         if (KisLayerSP found = layer->findLayer(i))
00414             return found;
00415     return 0;
00416 }
00417 
00418 int KisLayer::numLayers(int flags) const
00419 {
00420     int num = 0;
00421     if (matchesFlags(flags)) num++;
00422     for (KisLayerSP layer = firstChild(); layer; layer = layer->nextSibling())
00423         num += layer->numLayers(flags);
00424     return num;
00425 }
00426 
00427 bool KisLayer::matchesFlags(int flags) const
00428 {
00429     if ((flags & Visible) && !visible())
00430         return false;
00431     if ((flags & Hidden) && visible())
00432         return false;
00433     if ((flags & Locked) && !locked())
00434         return false;
00435     if ((flags & Unlocked) && locked())
00436         return false;
00437     return true;
00438 }
00439 
00440 Q_UINT8 KisLayer::opacity() const
00441 {
00442     return m_opacity;
00443 }
00444 
00445 void KisLayer::setOpacity(Q_UINT8 val)
00446 {
00447     if (m_opacity != val)
00448     {
00449         m_opacity = val;
00450         setDirty();
00451         notifyPropertyChanged();
00452     }
00453 }
00454 
00455 KNamedCommand *KisLayer::setOpacityCommand(Q_UINT8 newOpacity)
00456 {
00457     return new KisLayerOpacityCommand(this, opacity(), newOpacity);
00458 }
00459 
00460 KNamedCommand *KisLayer::setOpacityCommand(Q_UINT8 prevOpacity, Q_UINT8 newOpacity)
00461 {
00462     return new KisLayerOpacityCommand(this, prevOpacity, newOpacity);
00463 }
00464 
00465 const bool KisLayer::visible() const
00466 {
00467     return m_visible;
00468 }
00469 
00470 void KisLayer::setVisible(bool v)
00471 {
00472     if (m_visible != v) {
00473 
00474         m_visible = v;
00475         notifyPropertyChanged();
00476         setDirty();
00477 
00478         if (undoAdapter() && undoAdapter()->undo()) {
00479             undoAdapter()->addCommand(setVisibleCommand(v));
00480         }
00481     }
00482 }
00483 
00484 KNamedCommand *KisLayer::setVisibleCommand(bool newVisibility)
00485 {
00486     return new KisLayerVisibilityCommand(this, newVisibility);
00487 }
00488 
00489 bool KisLayer::locked() const
00490 {
00491     return m_locked;
00492 }
00493 
00494 void KisLayer::setLocked(bool l)
00495 {
00496     if (m_locked != l) {
00497         m_locked = l;
00498         notifyPropertyChanged();
00499 
00500         if (undoAdapter() && undoAdapter()->undo()) {
00501             undoAdapter()->addCommand(setLockedCommand(l));
00502         }
00503     }
00504 }
00505 
00506 bool KisLayer::temporary() const
00507 {
00508     return m_temporary;
00509 }
00510 
00511 void KisLayer::setTemporary(bool t)
00512 {
00513     m_temporary = t;
00514 }
00515 
00516 KNamedCommand *KisLayer::setLockedCommand(bool newLocked)
00517 {
00518     return new KisLayerLockedCommand(this, newLocked);
00519 }
00520 
00521 QString KisLayer::name() const
00522 {
00523         return m_name;
00524 }
00525 
00526 void KisLayer::setName(const QString& name)
00527 {
00528     if (!name.isEmpty() && m_name != name)
00529     {
00530         m_name = name;
00531         notifyPropertyChanged();
00532     }
00533 }
00534 
00535 void KisLayer::setCompositeOp(const KisCompositeOp& compositeOp)
00536 {
00537     if (m_compositeOp != compositeOp)
00538     {
00539        m_compositeOp = compositeOp;
00540        notifyPropertyChanged();
00541        setDirty();
00542 
00543     }
00544 }
00545 
00546 KNamedCommand *KisLayer::setCompositeOpCommand(const KisCompositeOp& newCompositeOp)
00547 {
00548     return new KisLayerCompositeOpCommand(this, compositeOp(), newCompositeOp);
00549 }
00550 
00551 KNamedCommand *KisLayer::moveCommand(QPoint oldPosition, QPoint newPosition)
00552 {
00553     return new KisLayerOffsetCommand(this, oldPosition, newPosition);
00554 }
00555 
00556 KisUndoAdapter *KisLayer::undoAdapter() const
00557 {
00558     if (m_image) {
00559         return m_image->undoAdapter();
00560     }
00561     return 0;
00562 }
00563 
00564 void KisLayer::paintMaskInactiveLayers(QImage &, Q_INT32, Q_INT32, Q_INT32, Q_INT32)
00565 {
00566 }
00567 
00568 void KisLayer::paintSelection(QImage &, Q_INT32, Q_INT32, Q_INT32, Q_INT32)
00569 {
00570 }
00571 
00572 void KisLayer::paintSelection(QImage &, const QRect&, const QSize&, const QSize&)
00573 {
00574 }
00575 
00576 QImage KisLayer::createThumbnail(Q_INT32, Q_INT32)
00577 {
00578     return 0;
00579 }
00580 
00581 void KisLayer::notifyPropertyChanged()
00582 {
00583     if(image() && !signalsBlocked())
00584         image()->notifyPropertyChanged(this);
00585 }
00586 
00587 #include "kis_layer.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys