krita

kis_paint_layer.cc

00001 /*
00002  *  Copyright (c) 2005 Casper Boemann <cbr@boemann.dk>
00003  *  Copyright (c) 2006 Bart Coppens <kde@bartcoppens.be>
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_image.h"
00025 #include "kis_paint_layer.h"
00026 #include "kis_selection.h"
00027 #include "kis_painter.h"
00028 #include "kis_undo_adapter.h"
00029 #include "kis_iterators_pixel.h"
00030 #include "kis_paint_device.h"
00031 #include "kis_meta_registry.h"
00032 #include "kis_colorspace_factory_registry.h"
00033 #include "kis_datamanager.h"
00034 #include "kis_undo_adapter.h"
00035 
00036 KisPaintLayer::KisPaintLayer(KisImage *img, const QString& name, Q_UINT8 opacity, KisPaintDeviceSP dev)
00037     : super(img, name, opacity)
00038 {
00039     Q_ASSERT(img);
00040     Q_ASSERT(dev);
00041     m_paintdev = dev;
00042     m_mask = 0;
00043     m_maskAsSelection = 0;
00044     m_paintdev->setParentLayer(this);
00045     m_renderMask = false;
00046     m_editMask = true;
00047 }
00048 
00049 
00050 KisPaintLayer::KisPaintLayer(KisImage *img, const QString& name, Q_UINT8 opacity)
00051     : super(img, name, opacity)
00052 {
00053     Q_ASSERT(img);
00054     m_paintdev = new KisPaintDevice(this, img->colorSpace(), name.latin1());
00055     m_mask = 0;
00056     m_maskAsSelection = 0;
00057     m_renderMask = false;
00058     m_editMask = true;
00059 }
00060 
00061 KisPaintLayer::KisPaintLayer(KisImage *img, const QString& name, Q_UINT8 opacity, KisColorSpace * colorSpace)
00062     : super(img, name, opacity)
00063 {
00064     Q_ASSERT(img);
00065     Q_ASSERT(colorSpace);
00066     m_paintdev = new KisPaintDevice(this, colorSpace,  name.latin1());
00067     m_mask = 0;
00068     m_maskAsSelection = 0;
00069     m_renderMask = false;
00070     m_editMask = true;
00071 }
00072 
00073 KisPaintLayer::KisPaintLayer(const KisPaintLayer& rhs) :
00074         KisLayer(rhs), KisLayerSupportsIndirectPainting(rhs)
00075 {
00076     m_paintdev = new KisPaintDevice( *rhs.m_paintdev.data() );
00077     m_paintdev->setParentLayer(this);
00078     if (rhs.hasMask()) {
00079         m_mask = new KisPaintDevice(*rhs.m_mask.data());
00080         m_mask->setParentLayer(this);
00081     }
00082     m_renderMask = rhs.m_renderMask;
00083     m_editMask = rhs.m_editMask;
00084 }
00085 
00086 KisLayerSP KisPaintLayer::clone() const
00087 {
00088     return new KisPaintLayer(*this);
00089 }
00090 
00091 KisPaintLayer::~KisPaintLayer()
00092 {
00093     if (m_paintdev != 0) {
00094         m_paintdev->setParentLayer(0);
00095     }
00096     if (m_mask != 0) {
00097         m_mask->setParentLayer(0);
00098     }
00099 }
00100 
00101 void KisPaintLayer::paintSelection(QImage &img, Q_INT32 x, Q_INT32 y, Q_INT32 w, Q_INT32 h)
00102 {
00103     if (m_paintdev && m_paintdev->hasSelection()) {
00104         m_paintdev->selection()->paintSelection(img, x, y, w, h);
00105     } else if (m_mask && m_editMask && m_mask->hasSelection()) {
00106         m_mask->selection()->paintSelection(img, x, y, w, h);
00107     }
00108 }
00109 
00110 void KisPaintLayer::paintSelection(QImage &img, const QRect& scaledImageRect, const QSize& scaledImageSize, const QSize& imageSize)
00111 {
00112     if (m_paintdev && m_paintdev->hasSelection()) {
00113         m_paintdev->selection()->paintSelection(img, scaledImageRect, scaledImageSize, imageSize);
00114     } else if (m_mask && m_editMask && m_mask->hasSelection()) {
00115         m_mask->selection()->paintSelection(img, scaledImageRect, scaledImageSize, imageSize);
00116     }
00117 }
00118 
00119 void KisPaintLayer::paintMaskInactiveLayers(QImage &img, Q_INT32 x, Q_INT32 y, Q_INT32 w, Q_INT32 h)
00120 {
00121     uchar *j = img.bits();
00122 
00123     KisColorSpace *cs = m_paintdev->colorSpace();
00124 
00125     for (Q_INT32 y2 = y; y2 < h + y; ++y2) {
00126         KisHLineIteratorPixel it = m_paintdev->createHLineIterator(x, y2, w, false);
00127         while ( ! it.isDone()) {
00128             Q_UINT8 s = cs->getAlpha(it.rawData());
00129             if(s==0)
00130             {
00131                 Q_UINT8 g = (*(j + 0)  + *(j + 1 ) + *(j + 2 )) / 9;
00132 
00133                 *(j+0) = 128+g ;
00134                 *(j+1) = 165+g;
00135                 *(j+2) = 128+g;
00136             }
00137             j+=4;
00138             ++it;
00139         }
00140     }
00141 }
00142 
00143 QImage KisPaintLayer::createThumbnail(Q_INT32 w, Q_INT32 h)
00144 {
00145     if (m_paintdev)
00146         return m_paintdev->createThumbnail(w, h);
00147     else
00148         return QImage();
00149 }
00150 
00151 
00152 Q_INT32 KisPaintLayer::x() const {
00153     if (m_paintdev)
00154         return m_paintdev->getX();
00155     else return 0;
00156 }
00157 
00158 void KisPaintLayer::setX(Q_INT32 x)
00159 {
00160     if (m_paintdev)
00161         m_paintdev->setX(x);
00162 }
00163 
00164 Q_INT32 KisPaintLayer::y() const {
00165     if (m_paintdev)
00166         return m_paintdev->getY();
00167     else
00168         return 0;
00169 }
00170 
00171 void KisPaintLayer::setY(Q_INT32 y) {
00172     if (m_paintdev)
00173         m_paintdev->setY(y);
00174 }
00175 
00176 QRect KisPaintLayer::extent() const {
00177     if (m_paintdev)
00178         return m_paintdev->extent();
00179     else
00180         return QRect();
00181 }
00182 
00183 QRect KisPaintLayer::exactBounds() const {
00184     if (m_paintdev)
00185         return m_paintdev->exactBounds();
00186     else
00187         return QRect();
00188 }
00189 
00190 void KisPaintLayer::removeMask() {
00191     if (!hasMask())
00192         return;
00193 
00194     m_mask->setParentLayer(0);
00195     m_mask = 0;
00196     m_maskAsSelection = 0;
00197     setDirty();
00198 
00199     emit sigMaskInfoChanged();
00200 }
00201 
00202 // ### XXX Do we apply the mask outside the image boundaries too? I'd say no, but I'm not sure
00203 void KisPaintLayer::applyMask() {
00204     if (!hasMask())
00205         return;
00206 
00207     int x, y, w, h;
00208     m_paintdev->extent(x, y, w, h);
00209 
00210     // A bit slow; but it works
00211     KisPaintDeviceSP temp = new KisPaintDevice(m_paintdev->colorSpace());
00212     KisPainter gc(temp);
00213     gc.bltSelection(x, y, COMPOSITE_OVER, m_paintdev, m_maskAsSelection, OPACITY_OPAQUE, x, y, w, h);
00214     gc.end();
00215     gc.begin(m_paintdev);
00216     gc.bitBlt(x, y, COMPOSITE_COPY, temp, OPACITY_OPAQUE, x, y, w, h);
00217     gc.end();
00218 
00219     removeMask();
00220 }
00221 
00222 KisPaintDeviceSP KisPaintLayer::createMask() {
00223     if (hasMask())
00224         return m_mask;
00225 
00226     kdDebug() << k_funcinfo << endl;
00227     // Grey8 nicely fits our needs of being intuitively comparable to other apps'
00228     // mask layer interfaces. It does have an alpha component though, which is a bit
00229     // less appropriate in this context.
00230     m_mask = new KisPaintDevice(KisMetaRegistry::instance()->csRegistry()
00231             ->getColorSpace(KisID("GRAYA"), 0));
00232 
00233     genericMaskCreationHelper();
00234 
00235     return m_mask;
00236 }
00237 
00238 // FIXME If from is a paint device is not grey8!!
00239 void KisPaintLayer::createMaskFromPaintDevice(KisPaintDeviceSP from) {
00240     if (hasMask())
00241         return; // Or overwrite? XXX
00242 
00243     kdDebug() << k_funcinfo << endl;
00244     m_mask = from; // KisPaintDevice(*from); XXX
00245 
00246     genericMaskCreationHelper();
00247 }
00248 
00249 void KisPaintLayer::createMaskFromSelection(KisSelectionSP from) {
00250     kdDebug() << k_funcinfo << endl;
00251     m_mask = new KisPaintDevice(KisMetaRegistry::instance()->csRegistry()
00252             ->getColorSpace(KisID("GRAYA"), 0));
00253     m_mask->setParentLayer(this);
00254 
00255     m_maskAsSelection = new KisSelection(); // Anonymous selection is good enough
00256 
00257     // Default pixel is opaque white == don't mask?
00258     Q_UINT8 const defPixel[] = { 255, 255 };
00259     m_mask->dataManager()->setDefaultPixel(defPixel);
00260 
00261     if (from) {
00262         QRect r(extent());
00263 
00264         int w = r.width();
00265         int h = r.height();
00266         for (int y = r.y(); y < h; y++) {
00267             KisHLineIteratorPixel srcIt = from->createHLineIterator(r.x(), y, w, false);
00268             KisHLineIteratorPixel dstIt = m_mask->createHLineIterator(r.x(), y, w, true);
00269 
00270             while(!dstIt.isDone()) {
00271                 // XXX same remark as in convertMaskToSelection
00272                 *dstIt.rawData() = *srcIt.rawData();
00273                 ++srcIt;
00274                 ++dstIt;
00275             }
00276         }
00277     }
00278 
00279     convertMaskToSelection(extent());
00280     m_paintdev->deselect();
00281 
00282     setDirty();
00283     emit sigMaskInfoChanged();
00284 }
00285 
00286 KisPaintDeviceSP KisPaintLayer::getMask() {
00287     createMask();
00288     kdDebug() << k_funcinfo << endl;
00289     return m_mask;
00290 }
00291 
00292 KisSelectionSP KisPaintLayer::getMaskAsSelection() {
00293     createMask();
00294     kdDebug() << k_funcinfo << endl;
00295     return m_maskAsSelection;
00296 }
00297 
00298 void KisPaintLayer::setEditMask(bool b) {
00299     m_editMask = b;
00300     emit sigMaskInfoChanged();
00301 }
00302 
00303 void KisPaintLayer::setRenderMask(bool b) {
00304     m_renderMask = b;
00305 
00306     if (hasMask())
00307         setDirty();
00308 
00309     emit sigMaskInfoChanged();
00310 }
00311 
00312 void KisPaintLayer::convertMaskToSelection(const QRect& r) {
00313     KisRectIteratorPixel srcIt = m_mask->createRectIterator(r.x(), r.y(),
00314             r.width(), r.height(), false);
00315     KisRectIteratorPixel dstIt = m_maskAsSelection->createRectIterator(r.x(), r.y(),
00316             r.width(), r.height(), true);
00317 
00318     while(!dstIt.isDone()) {
00319         // src is grey8 (grey + alpha), dst is alpha8. We convert the grey value to
00320         // alpha8 manually and ignore the alpha (that's why we don't convert using default
00321         // functions, and interpret the data raw!) [ XXX ]
00322         *dstIt.rawData() = *srcIt.rawData();
00323         ++srcIt;
00324         ++dstIt;
00325     }
00326 }
00327 
00328 void KisPaintLayer::genericMaskCreationHelper() {
00329     m_mask->setParentLayer(this);
00330 
00331     m_maskAsSelection = new KisSelection(); // Anonymous selection is good enough
00332 
00333     // Default pixel is opaque white == don't mask?
00334     Q_UINT8 const defPixel[] = { 255, 255 };
00335     m_mask->dataManager()->setDefaultPixel(defPixel);
00336 
00337     setDirty();
00338     emit sigMaskInfoChanged();
00339 }
00340 
00341 void KisPaintLayer::setDirty(bool propagate) {
00342     if (hasMask())
00343         convertMaskToSelection(extent());
00344     super::setDirty(propagate);
00345 }
00346 
00347 void KisPaintLayer::setDirty(const QRect & rect, bool propagate) {
00348     if (hasMask())
00349         convertMaskToSelection(rect);
00350     super::setDirty(rect, propagate);
00351 }
00352 
00353 // Undoable versions code
00354 namespace {
00355     class KisCreateMaskCommand : public KNamedCommand {
00356         typedef KNamedCommand super;
00357         KisPaintLayerSP m_layer;
00358         KisPaintDeviceSP m_mask;
00359     public:
00360         KisCreateMaskCommand(const QString& name, KisPaintLayer* layer)
00361             : super(name), m_layer(layer) {}
00362         virtual void execute() {
00363             kdDebug() << k_funcinfo << endl;
00364             if (!m_mask)
00365                 m_mask = m_layer->createMask();
00366             else
00367                 m_layer->createMaskFromPaintDevice(m_mask);
00368         }
00369         virtual void unexecute() {
00370             m_layer->removeMask();
00371         }
00372     };
00373 
00374     class KisMaskFromSelectionCommand : public KNamedCommand {
00375         typedef KNamedCommand super;
00376         KisPaintLayerSP m_layer;
00377         KisPaintDeviceSP m_maskBefore;
00378         KisPaintDeviceSP m_maskAfter;
00379         KisSelectionSP m_selection;
00380     public:
00381         KisMaskFromSelectionCommand(const QString& name, KisPaintLayer* layer)
00382             : super(name), m_layer(layer) {
00383             if (m_layer->hasMask())
00384                 m_maskBefore = m_layer->getMask();
00385             else
00386                 m_maskBefore = 0;
00387             m_maskAfter = 0;
00388             if (m_layer->paintDevice()->hasSelection())
00389                 m_selection = m_layer->paintDevice()->selection();
00390             else
00391                 m_selection = 0;
00392         }
00393         virtual void execute() {
00394             if (!m_maskAfter) {
00395                 m_layer->createMaskFromSelection(m_selection);
00396                 m_maskAfter = m_layer->getMask();
00397             } else {
00398                 m_layer->paintDevice()->deselect();
00399                 m_layer->createMaskFromPaintDevice(m_maskAfter);
00400             }
00401         }
00402         virtual void unexecute() {
00403             m_layer->paintDevice()->setSelection(m_selection);
00404             if (m_maskBefore)
00405                 m_layer->createMaskFromPaintDevice(m_maskBefore);
00406             else
00407                 m_layer->removeMask();
00408         }
00409     };
00410 
00411     class KisMaskToSelectionCommand : public KNamedCommand {
00412         typedef KNamedCommand super;
00413         KisPaintLayerSP m_layer;
00414         KisPaintDeviceSP m_mask;
00415         KisSelectionSP m_selection;
00416     public:
00417         KisMaskToSelectionCommand(const QString& name, KisPaintLayer* layer)
00418             : super(name), m_layer(layer) {
00419             m_mask = m_layer->getMask();
00420             if (m_layer->paintDevice()->hasSelection())
00421                 m_selection = m_layer->paintDevice()->selection();
00422             else
00423                 m_selection = 0;
00424         }
00425         virtual void execute() {
00426             m_layer->paintDevice()->setSelection(m_layer->getMaskAsSelection());
00427             m_layer->removeMask();
00428         }
00429         virtual void unexecute() {
00430             if (m_selection)
00431                 m_layer->paintDevice()->setSelection(m_selection);
00432             else
00433                 m_layer->paintDevice()->deselect();
00434             m_layer->createMaskFromPaintDevice(m_mask);
00435         }
00436     };
00437 
00438     class KisRemoveMaskCommand : public KNamedCommand {
00439         typedef KNamedCommand super;
00440         KisPaintLayerSP m_layer;
00441         KisPaintDeviceSP m_mask;
00442     public:
00443         KisRemoveMaskCommand(const QString& name, KisPaintLayer* layer)
00444             : super(name), m_layer(layer) {
00445             m_mask = m_layer->getMask();
00446         }
00447         virtual void execute() {
00448             kdDebug() << k_funcinfo << endl;
00449             m_layer->removeMask();
00450         }
00451         virtual void unexecute() {
00452             // I hope that if the undo stack unwinds, it will end up here in the right
00453             // state again; taking a deep-copy sounds like wasteful to me
00454             m_layer->createMaskFromPaintDevice(m_mask);
00455         }
00456     };
00457 
00458     class KisApplyMaskCommand : public KNamedCommand {
00459         typedef KNamedCommand super;
00460         KisPaintLayerSP m_layer;
00461         KisPaintDeviceSP m_mask;
00462         KisPaintDeviceSP m_original;
00463     public:
00464         KisApplyMaskCommand(const QString& name, KisPaintLayer* layer)
00465             : super(name), m_layer(layer) {
00466             m_mask = m_layer->getMask();
00467             m_original = new KisPaintDevice(*m_layer->paintDevice());
00468         }
00469         virtual void execute() {
00470             m_layer->applyMask();
00471         }
00472         virtual void unexecute() {
00473                 // I hope that if the undo stack unwinds, it will end up here in the right
00474                 // state again; taking a deep-copy sounds like wasteful to me
00475             KisPainter gc(m_layer->paintDevice());
00476             int x, y, w, h;
00477             m_layer->paintDevice()->extent(x, y, w, h);
00478 
00479             gc.bitBlt(x, y, COMPOSITE_COPY, m_original, OPACITY_OPAQUE, x, y, w, h);
00480             gc.end();
00481 
00482             m_layer->createMaskFromPaintDevice(m_mask);
00483         }
00484     };
00485 }
00486 
00487 KNamedCommand* KisPaintLayer::createMaskCommand() {
00488     return new KisCreateMaskCommand(i18n("Create Layer Mask"), this);
00489 }
00490 
00491 KNamedCommand* KisPaintLayer::maskFromSelectionCommand() {
00492     return new KisMaskFromSelectionCommand(i18n("Mask From Selection"), this);
00493 }
00494 
00495 KNamedCommand* KisPaintLayer::maskToSelectionCommand() {
00496     return new KisMaskToSelectionCommand(i18n("Mask to Selection"), this);
00497 }
00498 
00499 
00500 KNamedCommand* KisPaintLayer::removeMaskCommand() {
00501     return new KisRemoveMaskCommand(i18n("Remove Layer Mask"), this);
00502 }
00503 
00504 KNamedCommand* KisPaintLayer::applyMaskCommand() {
00505     return new KisApplyMaskCommand(i18n("Apply Layer Mask"), this);
00506 }
00507 
00508 
00509 #include "kis_paint_layer.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys