krita

kis_merge_visitor.h

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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00018  */
00019 #ifndef KIS_MERGE_H_
00020 #define KIS_MERGE_H_
00021 
00022 #include <qrect.h>
00023 
00024 #include "kis_types.h"
00025 #include "kis_paint_device.h"
00026 #include "kis_layer_visitor.h"
00027 #include "kis_painter.h"
00028 #include "kis_image.h"
00029 #include "kis_layer.h"
00030 #include "kis_group_layer.h"
00031 #include "kis_adjustment_layer.h"
00032 #include "kis_paint_layer.h"
00033 #include "kis_part_layer_iface.h"
00034 #include "kis_filter.h"
00035 #include "kis_filter_configuration.h"
00036 #include "kis_filter_registry.h"
00037 #include "kis_selection.h"
00038 
00039 class KisMergeVisitor : public KisLayerVisitor {
00040 public:
00045     KisMergeVisitor(KisPaintDeviceSP projection, const QRect& rc) :
00046         KisLayerVisitor()
00047     {
00048         Q_ASSERT(projection);
00049 
00050         m_projection = projection;
00051         m_rc = rc;
00052     }
00053 
00054 public:
00055     virtual bool visit(KisPaintLayer *layer)
00056     {
00057         
00058         if (m_projection == 0) {
00059             return false;
00060         }
00061         
00062         kdDebug(41010) << "Visiting on paint layer " << layer->name() << ", visible: " << layer->visible()
00063                 << ", temporary: " << layer->temporary() << ", extent: "
00064                 << layer->extent() << ", dirty: " << layer->dirtyRect() << ", paint rect: " << m_rc << endl;
00065         if (!layer->visible())
00066             return true;
00067 
00068         Q_INT32 sx, sy, dx, dy, w, h;
00069 
00070         QRect rc = layer->paintDevice()->extent() & m_rc;
00071 
00072         sx = rc.left();
00073         sy = rc.top();
00074         w  = rc.width();
00075         h  = rc.height();
00076         dx = sx;
00077         dy = sy;
00078 
00079         KisPainter gc(m_projection);
00080         gc.bitBlt(dx, dy, layer->compositeOp(), layer->paintDevice(), layer->opacity(), sx, sy, w, h);
00081 
00082         layer->setClean( rc );
00083         return true;
00084     }
00085 
00086     virtual bool visit(KisGroupLayer *layer)
00087     {
00088         
00089         if (m_projection == 0) {
00090             return false;
00091         }
00092         
00093         kdDebug(41010) << "Visiting on group layer " << layer->name() << ", visible: " << layer->visible() << ", extent: "
00094                 << layer->extent() << ", dirty: " << layer->dirtyRect() << ", paint rect: " << m_rc << endl;
00095                 
00096         if (!layer->visible())
00097             return true;
00098         
00099         Q_INT32 sx, sy, dx, dy, w, h;
00100 
00101         // This automatically makes sure the projection is up-to-date for the specified rect.
00102         KisPaintDeviceSP dev = layer->projection(m_rc);
00103         QRect rc = dev->extent() & m_rc;
00104 
00105         sx = rc.left();
00106         sy = rc.top();
00107         w  = rc.width();
00108         h  = rc.height();
00109         dx = sx;
00110         dy = sy;
00111 
00112         KisPainter gc(m_projection);
00113         gc.bitBlt(dx, dy, layer->compositeOp(), dev, layer->opacity(), sx, sy, w, h);
00114 
00115         return true;
00116     }
00117 
00118     virtual bool visit(KisPartLayer* layer)
00119     {
00120 
00121         kdDebug(41010) << "Visiting on part layer " << layer->name() << ", visible: " << layer->visible() << ", extent: "
00122                 << layer->extent() << ", dirty: " << layer->dirtyRect() << ", paint rect: " << m_rc << endl;
00123         
00124         if (m_projection == 0) {
00125             return false;
00126         }
00127         if (!layer->visible())
00128             return true;
00129 
00130         KisPaintDeviceSP dev(layer->prepareProjection(m_projection, m_rc));
00131         if (!dev)
00132             return true;
00133 
00134         Q_INT32 sx, sy, dx, dy, w, h;
00135 
00136         QRect rc = dev->extent() & m_rc;
00137 
00138         sx= rc.left();
00139         sy = rc.top();
00140         w = rc.width();
00141         h = rc.height();
00142         dx = sx;
00143         dy = sy;
00144 
00145         KisPainter gc(m_projection);
00146         gc.bitBlt(dx, dy, layer->compositeOp() , dev, layer->opacity(), sx, sy, w, h);
00147 
00148         layer->setClean(rc);
00149         return true;
00150     }
00151 
00152     virtual bool visit(KisAdjustmentLayer* layer)
00153     {
00154         kdDebug(41010) << "Visiting on adjustment layer " << layer->name() << ", visible: " << layer->visible() << ", extent: "
00155                 << layer->extent() << ", dirty: " << layer->dirtyRect() << ", paint rect: " << m_rc << endl;
00156         
00157         if (m_projection == 0) {
00158             return true;
00159         }
00160         
00161         if (!layer->visible())
00162             return true;
00163 
00164         KisFilterConfiguration * cfg = layer->filter();
00165         if (!cfg) return false;
00166 
00167         
00168         KisFilter * f = KisFilterRegistry::instance()->get( cfg->name() );
00169         if (!f) return false;
00170         
00171         KisSelectionSP selection = layer->selection();
00172 
00173         // Copy of the projection -- use the copy-on-write trick.
00174         KisPaintDeviceSP tmp = new KisPaintDevice(*m_projection);
00175 
00176         // If there's a selection, only keep the selected bits
00177         if (selection != 0) {
00178             tmp->setSelection(selection);
00179         }
00180         
00181         // Filter the temporary paint device -- remember, these are only the selected bits,
00182         // if there was a selection.
00183         f->process(tmp, tmp, cfg, m_rc);
00184 
00185         // Copy the filtered bits onto the projection 
00186         KisPainter gc(m_projection);
00187         if (selection)
00188             gc.bltSelection(m_rc.left(), m_rc.top(),
00189                             COMPOSITE_OVER, tmp, selection, layer->opacity(),
00190                             m_rc.left(), m_rc.top(), m_rc.width(), m_rc.height());
00191         else
00192             gc.bitBlt(m_rc.left(), m_rc.top(),
00193                       COMPOSITE_OVER, tmp, layer->opacity(),
00194                       m_rc.left(), m_rc.top(), m_rc.width(), m_rc.height());
00195         gc.end();
00196 
00197         // Copy the finished projection onto the cache
00198         gc.begin(layer->cachedPaintDevice());
00199         gc.bitBlt(m_rc.left(), m_rc.top(),
00200                   COMPOSITE_COPY, m_projection, OPACITY_OPAQUE,
00201                   m_rc.left(), m_rc.top(), m_rc.width(), m_rc.height());
00202 
00203         layer->setClean(m_rc);
00204 
00205         return true;
00206     }
00207 
00208 private:
00209     KisPaintDeviceSP m_projection;
00210     QRect m_rc;
00211 };
00212 
00213 #endif // KIS_MERGE_H_
00214 
KDE Home | KDE Accessibility Home | Description of Access Keys