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()
00079 {
00080     m_projection = new KisPaintDevice(this, image()->colorSpace(), name().latin1());
00081 }
00082 
00083 KisPaintDeviceSP KisGroupLayer::projection(const QRect & rect)
00084 {
00085     // We don't have a parent, and we've got only one child: abuse the child's
00086     // paint device as the projection if the child is visible and 100% opaque
00087     if (parent() == 0 && childCount() == 1) {
00088         KisPaintLayerSP l = dynamic_cast<KisPaintLayer*>(firstChild().data());
00089         if (l && l->paintDevice()->colorSpace() == m_image->colorSpace() && l->visible() && l->opacity() == OPACITY_OPAQUE) {
00090             l->setClean(rect);
00091             setClean(rect);
00092             return l->paintDevice();
00093         }
00094     }
00095     // No need for updates, we're clean
00096     if (!dirty()) {
00097         return m_projection;
00098     }
00099     // No need for updates -- the desired area wasn't dirty
00100     if (!rect.intersects(m_dirtyRect)) {
00101         return m_projection;
00102     }
00103 
00104 
00105     // Okay, we need to update the intersection between
00106     // what's dirty and what's asked us to be updated.
00107     // XXX Nooo, that doesn't work, since the call to setClean following this, is actually:
00108     // m_dirtyRect = QRect(); So the non-intersecting part gets brilliantly lost otherwise.
00109     const QRect rc = m_dirtyRect;//rect.intersect(m_dirtyRect);
00110 
00111     QTime t;
00112     t.start();
00113     updateProjection(rc);
00114     setClean(rect);
00115 
00116     return m_projection;
00117 }
00118 
00119 uint KisGroupLayer::childCount() const
00120 {
00121     return m_layers.count();
00122 }
00123 
00124 KisLayerSP KisGroupLayer::firstChild() const
00125 {
00126     return at(0);
00127 }
00128 
00129 KisLayerSP KisGroupLayer::lastChild() const
00130 {
00131     return at(childCount() - 1);
00132 }
00133 
00134 KisLayerSP KisGroupLayer::at(int index) const
00135 {
00136     if (childCount() && index >= 0 && kClamp(uint(index), uint(0), childCount() - 1) == uint(index))
00137         return m_layers.at(reverseIndex(index));
00138     return 0;
00139 }
00140 
00141 int KisGroupLayer::index(KisLayerSP layer) const
00142 {
00143     if (layer->parent().data() == this)
00144         return layer->index();
00145     return -1;
00146 }
00147 
00148 void KisGroupLayer::setIndex(KisLayerSP layer, int index)
00149 {
00150     if (layer->parent().data() != this)
00151         return;
00152     //TODO optimize
00153     removeLayer(layer);
00154     addLayer(layer, index);
00155 }
00156 
00157 bool KisGroupLayer::addLayer(KisLayerSP newLayer, int x)
00158 {
00159     if (x < 0 || kClamp(uint(x), uint(0), childCount()) != uint(x) ||
00160         newLayer->parent() || m_layers.contains(newLayer))
00161     {
00162         kdWarning() << "invalid input to KisGroupLayer::addLayer(KisLayerSP newLayer, int x)!" << endl;
00163         return false;
00164     }
00165     uint index(x);
00166     if (index == 0)
00167         m_layers.append(newLayer);
00168     else
00169         m_layers.insert(m_layers.begin() + reverseIndex(index) + 1, newLayer);
00170     for (uint i = childCount() - 1; i > index; i--)
00171         at(i)->m_index++;
00172     newLayer->m_parent = this;
00173     newLayer->m_index = index;
00174     newLayer->setImage(image());
00175     newLayer->setDirty(newLayer->extent());
00176     setDirty();
00177     return true;
00178 }
00179 
00180 bool KisGroupLayer::addLayer(KisLayerSP newLayer, KisLayerSP aboveThis)
00181 {
00182     if (aboveThis && aboveThis->parent().data() != this)
00183     {
00184         kdWarning() << "invalid input to KisGroupLayer::addLayer(KisLayerSP newLayer, KisLayerSP aboveThis)!" << endl;
00185         return false;
00186     }
00187     return addLayer(newLayer, aboveThis ? aboveThis->index() : childCount());
00188 }
00189 
00190 bool KisGroupLayer::removeLayer(int x)
00191 {
00192     if (x >= 0 && kClamp(uint(x), uint(0), childCount() - 1) == uint(x))
00193     {
00194         uint index(x);
00195         for (uint i = childCount() - 1; i > index; i--)
00196             at(i)->m_index--;
00197         KisLayerSP removedLayer = at(index);
00198 
00199         removedLayer->m_parent = 0;
00200         removedLayer->m_index = -1;
00201         m_layers.erase(m_layers.begin() + reverseIndex(index));
00202         setDirty(removedLayer->extent());
00203         if (childCount() < 1) {
00204             // No children, nothing to show for it.
00205             m_projection->clear();
00206             setDirty();
00207         }
00208         return true;
00209     }
00210     kdWarning() << "invalid input to KisGroupLayer::removeLayer()!" << endl;
00211     return false;
00212 }
00213 
00214 bool KisGroupLayer::removeLayer(KisLayerSP layer)
00215 {
00216     if (layer->parent().data() != this)
00217     {
00218         kdWarning() << "invalid input to KisGroupLayer::removeLayer()!" << endl;
00219         return false;
00220     }
00221 
00222     return removeLayer(layer->index());
00223 }
00224 
00225 void KisGroupLayer::setImage(KisImage *image)
00226 {
00227     super::setImage(image);
00228     for (vKisLayerSP_it it = m_layers.begin(); it != m_layers.end(); ++it)
00229     {
00230         (*it)->setImage(image);
00231     }
00232 }
00233 
00234 QRect KisGroupLayer::extent() const
00235 {
00236     QRect groupExtent;
00237 
00238     for (vKisLayerSP_cit it = m_layers.begin(); it != m_layers.end(); ++it)
00239     {
00240         groupExtent |= (*it)->extent();
00241     }
00242 
00243     return groupExtent;
00244 }
00245 
00246 QRect KisGroupLayer::exactBounds() const
00247 {
00248     QRect groupExactBounds;
00249 
00250     for (vKisLayerSP_cit it = m_layers.begin(); it != m_layers.end(); ++it)
00251     {
00252         groupExactBounds |= (*it)->exactBounds();
00253     }
00254 
00255     return groupExactBounds;
00256 }
00257 
00258 Q_INT32 KisGroupLayer::x() const
00259 {
00260     return m_x;
00261 }
00262 
00263 void KisGroupLayer::setX(Q_INT32 x)
00264 {
00265     Q_INT32 delta = x - m_x;
00266 
00267     for (vKisLayerSP_cit it = m_layers.begin(); it != m_layers.end(); ++it)
00268     {
00269         KisLayerSP layer = *it;
00270         layer->setX(layer->x() + delta);
00271     }
00272     m_x = x;
00273 }
00274 
00275 Q_INT32 KisGroupLayer::y() const
00276 {
00277     return m_y;
00278 }
00279 
00280 void KisGroupLayer::setY(Q_INT32 y)
00281 {
00282     Q_INT32 delta = y - m_y;
00283 
00284     for (vKisLayerSP_cit it = m_layers.begin(); it != m_layers.end(); ++it)
00285     {
00286         KisLayerSP layer = *it;
00287         layer->setY(layer->y() + delta);
00288     }
00289 
00290     m_y = y;
00291 }
00292 
00293 QImage KisGroupLayer::createThumbnail(Q_INT32 w, Q_INT32 h)
00294 {
00295     return m_projection->createThumbnail(w, h);
00296 }
00297 
00298 void KisGroupLayer::updateProjection(const QRect & rc)
00299 {
00300     if (!m_dirtyRect.isValid()) return;
00301 
00302     // Get the first layer in this group to start compositing with
00303     KisLayerSP child = lastChild();
00304 
00305     // No child -- clear the projection. Without children, a group layer is empty.
00306     if (!child) m_projection->clear();
00307 
00308     KisLayerSP startWith = 0;
00309     KisAdjustmentLayerSP adjLayer = 0;
00310     KisLayerSP tmpPaintLayer = 0;
00311 
00312     // If this is the rootlayer, don't do anything with adj. layers that are below the
00313     // first paintlayer
00314     bool gotPaintLayer = (parent() != 0);
00315 
00316     // Look through all the child layers, searching for the first dirty layer
00317     // if it's found, and if we have found an adj. layer before the the dirty layer,
00318     // composite from the first adjustment layer searching back from the first dirty layer
00319     while (child) {
00320         KisAdjustmentLayerSP tmpAdjLayer = dynamic_cast<KisAdjustmentLayer*>(child.data());
00321         if (tmpAdjLayer) {
00322             if (gotPaintLayer) {
00323                 // If this adjustment layer is dirty, start compositing with the
00324                 // previous layer, if there's one.
00325                 if (tmpAdjLayer->dirty(rc) && adjLayer != 0 && adjLayer->visible()) {
00326                     startWith = adjLayer->prevSibling();
00327                     break;
00328                 }
00329                 else if (tmpAdjLayer->visible() && !tmpAdjLayer->dirty(rc)) {
00330                     // This is the first adj. layer that is not dirty -- the perfect starting point
00331                     adjLayer = tmpAdjLayer;
00332                 }
00333                 else {
00334                     startWith = tmpPaintLayer;
00335                 }
00336             }
00337         }
00338         else {
00339             tmpPaintLayer = child;
00340             gotPaintLayer = true;
00341             // A non-adjustmentlayer that's dirty; if there's an adjustmentlayer
00342             // with a cache, we'll start from there.
00343             if (child->dirty(rc)) {
00344                 if (adjLayer != 0 && adjLayer->visible()) {
00345                     // the first layer on top of the adj. layer
00346                     startWith = adjLayer->prevSibling();
00347                 }
00348                 else {
00349                     startWith = child;
00350                 }
00351                 // break here: if there's no adj layer, we'll start with the layer->lastChild
00352                 break;
00353             }
00354         }
00355         child = child->prevSibling();
00356     }
00357 
00358     if (adjLayer != 0 && startWith == 0 && gotPaintLayer && adjLayer->prevSibling()) {
00359         startWith = adjLayer->prevSibling();
00360     }
00361 
00362     // No adj layer -- all layers inside the group must be recomposited
00363     if (adjLayer == 0) {
00364         startWith = lastChild();
00365     }
00366 
00367     if (startWith == 0) {
00368         return;
00369     }
00370 
00371     bool first = true; // The first layer in a stack needs special compositing
00372 
00373     // Fill the projection either with the cached data, or erase it.
00374     KisFillPainter gc(m_projection);
00375     if (adjLayer != 0) {
00376         gc.bitBlt(rc.left(), rc.top(),
00377                   COMPOSITE_COPY, adjLayer->cachedPaintDevice(), OPACITY_OPAQUE,
00378                   rc.left(), rc.top(), rc.width(), rc.height());
00379         first = false;
00380     }
00381     else {
00382         gc.eraseRect(rc);
00383         first = true;
00384     }
00385     gc.end();
00386 
00387     KisMergeVisitor visitor(m_projection, rc);
00388 
00389     child = startWith;
00390 
00391     while(child)
00392     {
00393         if(first)
00394         {
00395             // Copy the lowest layer rather than compositing it with the background
00396             // or an empty image. This means the layer's composite op is ignored,
00397             // which is consistent with Photoshop and gimp.
00398             const KisCompositeOp cop = child->compositeOp();
00399             const bool block = child->signalsBlocked();
00400             child->blockSignals(true);
00401             child->m_compositeOp = COMPOSITE_COPY;
00402             child->blockSignals(block);
00403             child->accept(visitor);
00404             child->blockSignals(true);
00405             child->m_compositeOp = cop;
00406             child->blockSignals(block);
00407             first = false;
00408         }
00409         else
00410             child->accept(visitor);
00411 
00412         child = child->prevSibling();
00413     }
00414 }
00415 
00416 #include "kis_group_layer.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys