krita

kis_group_layer.cc

00001 /*
00002  *  Copyright (c) 2005 Casper Boemann <cbr@boemann.dk>
00003  *
00004  *  this program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the gnu general public license as published by
00006  *  the free software foundation; either version 2 of the license, or
00007  *  (at your option) any later version.
00008  *
00009  *  this program is distributed in the hope that it will be useful,
00010  *  but without any warranty; without even the implied warranty of
00011  *  merchantability or fitness for a particular purpose.  see the
00012  *  gnu general public license for more details.
00013  *
00014  *  you should have received a copy of the gnu general public license
00015  *  along with this program; if not, write to the free software
00016  *  foundation, inc., 675 mass ave, cambridge, ma 02139, usa.
00017  */
00018 
00019 #include <kdebug.h>
00020 #include <kglobal.h>
00021 #include <qimage.h>
00022 #include <qdatetime.h>
00023 
00024 #include "kis_types.h"
00025 #include "kis_layer.h"
00026 #include "kis_group_layer.h"
00027 #include "kis_layer_visitor.h"
00028 #include "kis_debug_areas.h"
00029 #include "kis_image.h"
00030 #include "kis_paint_device.h"
00031 #include "kis_merge_visitor.h"
00032 #include "kis_fill_painter.h"
00033 
00034 KisGroupLayer::KisGroupLayer(KisImage *img, const QString &name, Q_UINT8 opacity) :
00035     super(img, name, opacity),
00036     m_x(0),
00037     m_y(0)
00038 {
00039     m_projection = new KisPaintDevice(this, img->colorSpace(), name.latin1());
00040 }
00041 
00042 KisGroupLayer::KisGroupLayer(const KisGroupLayer &rhs) :
00043     super(rhs),
00044     m_x(rhs.m_x),
00045     m_y(rhs.m_y)
00046 {
00047     for(vKisLayerSP_cit it = rhs.m_layers.begin(); it != rhs.m_layers.end(); ++it)
00048     {
00049         m_layers.push_back( it->data()->clone() );
00050     }
00051     m_projection = new KisPaintDevice(*rhs.m_projection.data());
00052     m_projection->setParentLayer(this);
00053 }
00054 
00055 KisLayerSP KisGroupLayer::clone() const
00056 {
00057     return new KisGroupLayer(*this);
00058 }
00059 
00060 KisGroupLayer::~KisGroupLayer()
00061 {
00062     m_layers.clear();
00063 }
00064 
00065 
00066 void KisGroupLayer::setDirty(bool propagate)
00067 {
00068     KisLayer::setDirty(propagate);
00069     if (propagate) emit (sigDirty(m_dirtyRect));
00070 }
00071 
00072 void KisGroupLayer::setDirty(const QRect & rc, bool propagate)
00073 {
00074     KisLayer::setDirty(rc, propagate);
00075     if (propagate) emit sigDirty(rc);
00076 }
00077 
00078 void KisGroupLayer::resetProjection(KisPaintDevice* to)
00079 {
00080     if (to)
00081         m_projection = new KisPaintDevice(*to); 
00082     else
00083         m_projection = new KisPaintDevice(this, image()->colorSpace(), name().latin1());
00084 }
00085 
00086 bool KisGroupLayer::paintLayerInducesProjectionOptimization(KisPaintLayer* l) {
00087     return l && l->paintDevice()->colorSpace() == m_image->colorSpace() && l->visible()
00088              && l->opacity() == OPACITY_OPAQUE && !l->temporaryTarget() && !l->hasMask();
00089 }
00090 
00091 KisPaintDeviceSP KisGroupLayer::projection(const QRect & rect)
00092 {
00093     // We don't have a parent, and we've got only one child: abuse the child's
00094     // paint device as the projection if the child is visible and 100% opaque
00095     if (parent() == 0 && childCount() == 1) {
00096         KisPaintLayerSP l = dynamic_cast<KisPaintLayer*>(firstChild().data());
00097         if (paintLayerInducesProjectionOptimization(l)) {
00098             l->setClean(rect);
00099             setClean(rect);
00100             return l->paintDevice();
00101         }
00102     }
00103     // No need for updates, we're clean
00104     if (!dirty()) {
00105         return m_projection;
00106     }
00107     // No need for updates -- the desired area wasn't dirty
00108     if (!rect.intersects(m_dirtyRect)) {
00109         return m_projection;
00110     }
00111 
00112 
00113     // Okay, we need to update the intersection between
00114     // what's dirty and what's asked us to be updated.
00115     // XXX Nooo, that doesn't work, since the call to setClean following this, is actually:
00116     // m_dirtyRect = QRect(); So the non-intersecting part gets brilliantly lost otherwise.
00117     const QRect rc = m_dirtyRect;//rect.intersect(m_dirtyRect);
00118 
00119     updateProjection(rc);
00120     setClean(rect);
00121 
00122     return m_projection;
00123 }
00124 
00125 uint KisGroupLayer::childCount() const
00126 {
00127     return m_layers.count();
00128 }
00129 
00130 KisLayerSP KisGroupLayer::firstChild() const
00131 {
00132     return at(0);
00133 }
00134 
00135 KisLayerSP KisGroupLayer::lastChild() const
00136 {
00137     return at(childCount() - 1);
00138 }
00139 
00140 KisLayerSP KisGroupLayer::at(int index) const
00141 {
00142     if (childCount() && index >= 0 && kClamp(uint(index), uint(0), childCount() - 1) == uint(index))
00143         return m_layers.at(reverseIndex(index));
00144     return 0;
00145 }
00146 
00147 int KisGroupLayer::index(KisLayerSP layer) const
00148 {
00149     if (layer->parent().data() == this)
00150         return layer->index();
00151     return -1;
00152 }
00153 
00154 void KisGroupLayer::setIndex(KisLayerSP layer, int index)
00155 {
00156     if (layer->parent().data() != this)
00157         return;
00158     //TODO optimize
00159     removeLayer(layer);
00160     addLayer(layer, index);
00161 }
00162 
00163 bool KisGroupLayer::addLayer(KisLayerSP newLayer, int x)
00164 {
00165     if (x < 0 || kClamp(uint(x), uint(0), childCount()) != uint(x) ||
00166         newLayer->parent() || m_layers.contains(newLayer))
00167     {
00168         kdWarning() << "invalid input to KisGroupLayer::addLayer(KisLayerSP newLayer, int x)!" << endl;
00169         return false;
00170     }
00171     uint index(x);
00172     if (index == 0)
00173         m_layers.append(newLayer);
00174     else
00175         m_layers.insert(m_layers.begin() + reverseIndex(index) + 1, newLayer);
00176     for (uint i = childCount() - 1; i > index; i--)
00177         at(i)->m_index++;
00178     newLayer->m_parent = this;
00179     newLayer->m_index = index;
00180     newLayer->setImage(image());
00181     newLayer->setDirty(newLayer->extent());
00182     setDirty();
00183     return true;
00184 }
00185 
00186 bool KisGroupLayer::addLayer(KisLayerSP newLayer, KisLayerSP aboveThis)
00187 {
00188     if (aboveThis && aboveThis->parent().data() != this)
00189     {
00190         kdWarning() << "invalid input to KisGroupLayer::addLayer(KisLayerSP newLayer, KisLayerSP aboveThis)!" << endl;
00191         return false;
00192     }
00193     return addLayer(newLayer, aboveThis ? aboveThis->index() : childCount());
00194 }
00195 
00196 bool KisGroupLayer::removeLayer(int x)
00197 {
00198     if (x >= 0 && kClamp(uint(x), uint(0), childCount() - 1) == uint(x))
00199     {
00200         uint index(x);
00201         for (uint i = childCount() - 1; i > index; i--)
00202             at(i)->m_index--;
00203         KisLayerSP removedLayer = at(index);
00204 
00205         removedLayer->m_parent = 0;
00206         removedLayer->m_index = -1;
00207         m_layers.erase(m_layers.begin() + reverseIndex(index));
00208         setDirty(removedLayer->extent());
00209         if (childCount() < 1) {
00210             // No children, nothing to show for it.
00211             m_projection->clear();
00212             setDirty();
00213         }
00214         return true;
00215     }
00216     kdWarning() << "invalid input to KisGroupLayer::removeLayer()!" << endl;
00217     return false;
00218 }
00219 
00220 bool KisGroupLayer::removeLayer(KisLayerSP layer)
00221 {
00222     if (layer->parent().data() != this)
00223     {
00224         kdWarning() << "invalid input to KisGroupLayer::removeLayer()!" << endl;
00225         return false;
00226     }
00227 
00228     return removeLayer(layer->index());
00229 }
00230 
00231 void KisGroupLayer::setImage(KisImage *image)
00232 {
00233     super::setImage(image);
00234     for (vKisLayerSP_it it = m_layers.begin(); it != m_layers.end(); ++it)
00235     {
00236         (*it)->setImage(image);
00237     }
00238 }
00239 
00240 QRect KisGroupLayer::extent() const
00241 {
00242     QRect groupExtent;
00243 
00244     for (vKisLayerSP_cit it = m_layers.begin(); it != m_layers.end(); ++it)
00245     {
00246         groupExtent |= (*it)->extent();
00247     }
00248 
00249     return groupExtent;
00250 }
00251 
00252 QRect KisGroupLayer::exactBounds() const
00253 {
00254     QRect groupExactBounds;
00255 
00256     for (vKisLayerSP_cit it = m_layers.begin(); it != m_layers.end(); ++it)
00257     {
00258         groupExactBounds |= (*it)->exactBounds();
00259     }
00260 
00261     return groupExactBounds;
00262 }
00263 
00264 Q_INT32 KisGroupLayer::x() const
00265 {
00266     return m_x;
00267 }
00268 
00269 void KisGroupLayer::setX(Q_INT32 x)
00270 {
00271     Q_INT32 delta = x - m_x;
00272 
00273     for (vKisLayerSP_cit it = m_layers.begin(); it != m_layers.end(); ++it)
00274     {
00275         KisLayerSP layer = *it;
00276         layer->setX(layer->x() + delta);
00277     }
00278     m_x = x;
00279 }
00280 
00281 Q_INT32 KisGroupLayer::y() const
00282 {
00283     return m_y;
00284 }
00285 
00286 void KisGroupLayer::setY(Q_INT32 y)
00287 {
00288     Q_INT32 delta = y - m_y;
00289 
00290     for (vKisLayerSP_cit it = m_layers.begin(); it != m_layers.end(); ++it)
00291     {
00292         KisLayerSP layer = *it;
00293         layer->setY(layer->y() + delta);
00294     }
00295 
00296     m_y = y;
00297 }
00298 
00299 QImage KisGroupLayer::createThumbnail(Q_INT32 w, Q_INT32 h)
00300 {
00301     return m_projection->createThumbnail(w, h);
00302 }
00303 
00304 void KisGroupLayer::updateProjection(const QRect & rc)
00305 {
00306     if (!m_dirtyRect.isValid()) return;
00307 
00308     // Get the first layer in this group to start compositing with
00309     KisLayerSP child = lastChild();
00310 
00311     // No child -- clear the projection. Without children, a group layer is empty.
00312     if (!child) m_projection->clear();
00313 
00314     KisLayerSP startWith = 0;
00315     KisAdjustmentLayerSP adjLayer = 0;
00316     KisLayerSP tmpPaintLayer = 0;
00317 
00318     // If this is the rootlayer, don't do anything with adj. layers that are below the
00319     // first paintlayer
00320     bool gotPaintLayer = (parent() != 0);
00321 
00322     // Look through all the child layers, searching for the first dirty layer
00323     // if it's found, and if we have found an adj. layer before the the dirty layer,
00324     // composite from the first adjustment layer searching back from the first dirty layer
00325     while (child) {
00326         KisAdjustmentLayerSP tmpAdjLayer = dynamic_cast<KisAdjustmentLayer*>(child.data());
00327         if (tmpAdjLayer) {
00328             if (gotPaintLayer) {
00329                 // If this adjustment layer is dirty, start compositing with the
00330                 // previous layer, if there's one.
00331                 if (tmpAdjLayer->dirty(rc) && adjLayer != 0 && adjLayer->visible()) {
00332                     startWith = adjLayer->prevSibling();
00333                     break;
00334                 }
00335                 else if (tmpAdjLayer->visible() && !tmpAdjLayer->dirty(rc)) {
00336                     // This is the first adj. layer that is not dirty -- the perfect starting point
00337                     adjLayer = tmpAdjLayer;
00338                 }
00339                 else {
00340                     startWith = tmpPaintLayer;
00341                 }
00342             }
00343         }
00344         else {
00345             tmpPaintLayer = child;
00346             gotPaintLayer = true;
00347             // A non-adjustmentlayer that's dirty; if there's an adjustmentlayer
00348             // with a cache, we'll start from there.
00349             if (child->dirty(rc)) {
00350                 if (adjLayer != 0 && adjLayer->visible()) {
00351                     // the first layer on top of the adj. layer
00352                     startWith = adjLayer->prevSibling();
00353                 }
00354                 else {
00355                     startWith = child;
00356                 }
00357                 // break here: if there's no adj layer, we'll start with the layer->lastChild
00358                 break;
00359             }
00360         }
00361         child = child->prevSibling();
00362     }
00363 
00364     if (adjLayer != 0 && startWith == 0 && gotPaintLayer && adjLayer->prevSibling()) {
00365         startWith = adjLayer->prevSibling();
00366     }
00367 
00368     // No adj layer -- all layers inside the group must be recomposited
00369     if (adjLayer == 0) {
00370         startWith = lastChild();
00371     }
00372 
00373     if (startWith == 0) {
00374         return;
00375     }
00376 
00377     bool first = true; // The first layer in a stack needs special compositing
00378 
00379     // Fill the projection either with the cached data, or erase it.
00380     KisFillPainter gc(m_projection);
00381     if (adjLayer != 0) {
00382         gc.bitBlt(rc.left(), rc.top(),
00383                   COMPOSITE_COPY, adjLayer->cachedPaintDevice(), OPACITY_OPAQUE,
00384                   rc.left(), rc.top(), rc.width(), rc.height());
00385         first = false;
00386     }
00387     else {
00388         gc.eraseRect(rc);
00389         first = true;
00390     }
00391     gc.end();
00392 
00393     KisMergeVisitor visitor(m_projection, rc);
00394 
00395     child = startWith;
00396 
00397     while(child)
00398     {
00399         if(first)
00400         {
00401             // Copy the lowest layer rather than compositing it with the background
00402             // or an empty image. This means the layer's composite op is ignored,
00403             // which is consistent with Photoshop and gimp.
00404             const KisCompositeOp cop = child->compositeOp();
00405             const bool block = child->signalsBlocked();
00406             child->blockSignals(true);
00407             // Composite op copy doesn't take a mask/selection into account, so we need
00408             // to make a difference between a paintlayer with a mask, and one without
00409             KisPaintLayer* l = dynamic_cast<KisPaintLayer*>(child.data());
00410             if (l && l->hasMask())
00411                 child->m_compositeOp = COMPOSITE_OVER;
00412             else
00413                 child->m_compositeOp = COMPOSITE_COPY;
00414             child->blockSignals(block);
00415             child->accept(visitor);
00416             child->blockSignals(true);
00417             child->m_compositeOp = cop;
00418             child->blockSignals(block);
00419             first = false;
00420         }
00421         else
00422             child->accept(visitor);
00423 
00424         child = child->prevSibling();
00425     }
00426 }
00427 
00428 #include "kis_group_layer.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys