00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef KIS_MERGE_H_
00021 #define KIS_MERGE_H_
00022
00023 #include <qrect.h>
00024
00025 #include "kis_types.h"
00026 #include "kis_paint_device.h"
00027 #include "kis_layer_visitor.h"
00028 #include "kis_painter.h"
00029 #include "kis_image.h"
00030 #include "kis_layer.h"
00031 #include "kis_group_layer.h"
00032 #include "kis_adjustment_layer.h"
00033 #include "kis_paint_layer.h"
00034 #include "kis_part_layer_iface.h"
00035 #include "kis_filter.h"
00036 #include "kis_filter_configuration.h"
00037 #include "kis_filter_registry.h"
00038 #include "kis_selection.h"
00039 #include "kis_transaction.h"
00040 #include "kis_iterators_pixel.h"
00041
00042 class KisMergeVisitor : public KisLayerVisitor {
00043 public:
00048 KisMergeVisitor(KisPaintDeviceSP projection, const QRect& rc) :
00049 KisLayerVisitor()
00050 {
00051 Q_ASSERT(projection);
00052
00053 m_projection = projection;
00054 m_rc = rc;
00055 }
00056
00057 private:
00058
00059 template<class Target>
00060 KSharedPtr<Target> paintIndirect(KisPaintDeviceSP source,
00061 KSharedPtr<Target> target,
00062 KisLayerSupportsIndirectPainting* layer,
00063 Q_INT32 sx, Q_INT32 sy, Q_INT32 dx, Q_INT32 dy,
00064 Q_INT32 w, Q_INT32 h) {
00065 KisPainter gc2(target.data());
00066 gc2.bitBlt(dx, dy, COMPOSITE_COPY, source,
00067 OPACITY_OPAQUE, sx, sy, w, h);
00068 gc2.bitBlt(dx, dy, layer->temporaryCompositeOp(), layer->temporaryTarget(),
00069 layer->temporaryOpacity(), sx, sy, w, h);
00070 gc2.end();
00071 return target;
00072 }
00073
00074 public:
00075 virtual bool visit(KisPaintLayer *layer)
00076 {
00077
00078 if (m_projection == 0) {
00079 return false;
00080 }
00081
00082 kdDebug(41010) << "Visiting on paint layer " << layer->name() << ", visible: " << layer->visible()
00083 << ", temporary: " << layer->temporary() << ", extent: "
00084 << layer->extent() << ", dirty: " << layer->dirtyRect() << ", paint rect: " << m_rc << endl;
00085 if (!layer->visible())
00086 return true;
00087
00088 Q_INT32 sx, sy, dx, dy, w, h;
00089
00090 QRect rc = layer->paintDevice()->extent() & m_rc;
00091
00092
00093 KisPaintDeviceSP tempTarget = layer->temporaryTarget();
00094 if (tempTarget) {
00095 rc = (layer->paintDevice()->extent() | tempTarget->extent()) & m_rc;
00096 }
00097
00098 sx = rc.left();
00099 sy = rc.top();
00100 w = rc.width();
00101 h = rc.height();
00102 dx = sx;
00103 dy = sy;
00104
00105 KisPainter gc(m_projection);
00106 KisPaintDeviceSP source = layer->paintDevice();
00107
00108 if (!layer->hasMask()) {
00109 if (tempTarget) {
00110 KisPaintDeviceSP temp = new KisPaintDevice(source->colorSpace());
00111 source = paintIndirect(source, temp, layer, sx, sy, dx, dy, w, h);
00112 }
00113
00114 gc.bitBlt(dx, dy, layer->compositeOp(), source, layer->opacity(), sx, sy, w, h);
00115 } else {
00116 if (layer->renderMask()) {
00117
00118
00119
00120
00121
00122
00123
00124
00125 sx = m_rc.left();
00126 sy = m_rc.top();
00127 w = m_rc.width();
00128 h = m_rc.height();
00129 dx = sx;
00130 dy = sy;
00131
00132
00133
00134 KisPaintDeviceSP mask = layer->getMask();
00135 QRect mextent = mask->extent();
00136 if ((mextent & m_rc) != m_rc) {
00137
00138
00139
00140
00141
00142 KisRectIteratorPixel it = mask->createRectIterator(sx, sy, w, h, true);
00143 while (!it.isDone())
00144 ++it;
00145 }
00146 if (tempTarget) {
00147 KisPaintDeviceSP temp = new KisPaintDevice(source->colorSpace());
00148 mask = paintIndirect(mask, temp, layer, sx, sy, dx, dy, w, h);
00149 }
00150
00151 gc.bitBlt(dx, dy, COMPOSITE_OVER, mask, OPACITY_OPAQUE, sx, sy, w, h);
00152 } else {
00153 KisSelectionSP mask = layer->getMaskAsSelection();
00154
00155 if (tempTarget && layer->editMask()) {
00156 KisPaintDeviceSP maskSrc = layer->getMask();
00157 KisPaintDeviceSP temp = new KisPaintDevice(maskSrc->colorSpace());
00158 temp = paintIndirect(maskSrc, temp, layer, sx, sy, dx, dy, w, h);
00159
00160 KisRectIteratorPixel srcIt = temp->createRectIterator(sx, sy, w, h, false);
00161 KisRectIteratorPixel dstIt = mask->createRectIterator(sx, sy, w, h, true);
00162
00163 while(!dstIt.isDone()) {
00164
00165 *dstIt.rawData() = *srcIt.rawData();
00166 ++srcIt;
00167 ++dstIt;
00168 }
00169 } else if (tempTarget) {
00170
00171 KisPaintDeviceSP temp = new KisPaintDevice(source->colorSpace());
00172 source = paintIndirect(source, temp, layer, sx, sy, dx, dy, w, h);
00173 }
00174
00175 gc.bltSelection(dx, dy,
00176 layer->compositeOp(),
00177 source,
00178 mask,
00179 layer->opacity(), sx, sy, w, h);
00180 }
00181 }
00182
00183 layer->setClean( rc );
00184 return true;
00185 }
00186
00187 virtual bool visit(KisGroupLayer *layer)
00188 {
00189
00190 if (m_projection == 0) {
00191 return false;
00192 }
00193
00194 kdDebug(41010) << "Visiting on group layer " << layer->name() << ", visible: " << layer->visible() << ", extent: "
00195 << layer->extent() << ", dirty: " << layer->dirtyRect() << ", paint rect: " << m_rc << endl;
00196
00197 if (!layer->visible())
00198 return true;
00199
00200 Q_INT32 sx, sy, dx, dy, w, h;
00201
00202
00203 KisPaintDeviceSP dev = layer->projection(m_rc);
00204 QRect rc = dev->extent() & m_rc;
00205
00206 sx = rc.left();
00207 sy = rc.top();
00208 w = rc.width();
00209 h = rc.height();
00210 dx = sx;
00211 dy = sy;
00212
00213 KisPainter gc(m_projection);
00214 gc.bitBlt(dx, dy, layer->compositeOp(), dev, layer->opacity(), sx, sy, w, h);
00215
00216 return true;
00217 }
00218
00219 virtual bool visit(KisPartLayer* layer)
00220 {
00221
00222 kdDebug(41010) << "Visiting on part layer " << layer->name() << ", visible: " << layer->visible() << ", extent: "
00223 << layer->extent() << ", dirty: " << layer->dirtyRect() << ", paint rect: " << m_rc << endl;
00224
00225 if (m_projection == 0) {
00226 return false;
00227 }
00228 if (!layer->visible())
00229 return true;
00230
00231 KisPaintDeviceSP dev(layer->prepareProjection(m_projection, m_rc));
00232 if (!dev)
00233 return true;
00234
00235 Q_INT32 sx, sy, dx, dy, w, h;
00236
00237 QRect rc = dev->extent() & m_rc;
00238
00239 sx= rc.left();
00240 sy = rc.top();
00241 w = rc.width();
00242 h = rc.height();
00243 dx = sx;
00244 dy = sy;
00245
00246 KisPainter gc(m_projection);
00247 gc.bitBlt(dx, dy, layer->compositeOp() , dev, layer->opacity(), sx, sy, w, h);
00248
00249 layer->setClean(rc);
00250 return true;
00251 }
00252
00253 virtual bool visit(KisAdjustmentLayer* layer)
00254 {
00255 kdDebug(41010) << "Visiting on adjustment layer " << layer->name() << ", visible: " << layer->visible() << ", extent: "
00256 << layer->extent() << ", dirty: " << layer->dirtyRect() << ", paint rect: " << m_rc << endl;
00257
00258 if (m_projection == 0) {
00259 return true;
00260 }
00261
00262 if (!layer->visible())
00263 return true;
00264
00265 KisPaintDeviceSP tempTarget = layer->temporaryTarget();
00266 if (tempTarget) {
00267 m_rc = (layer->extent() | tempTarget->extent()) & m_rc;
00268 }
00269
00270 if (m_rc.width() == 0 || m_rc.height() == 0)
00271 return true;
00272
00273 KisFilterConfiguration * cfg = layer->filter();
00274 if (!cfg) return false;
00275
00276
00277 KisFilter * f = KisFilterRegistry::instance()->get( cfg->name() );
00278 if (!f) return false;
00279
00280
00281
00282 KisSelectionSP selection = layer->selection();
00283
00284
00285
00286 KisPaintDeviceSP tmp = 0;
00287 KisSelectionSP sel = selection;
00288
00289 if (selection != 0) {
00290 tmp = new KisPaintDevice(m_projection->colorSpace());
00291
00292 KisPainter gc(tmp);
00293 QRect selectedRect = selection->selectedRect();
00294 selectedRect &= m_rc;
00295
00296 if (selectedRect.width() == 0 || selectedRect.height() == 0)
00297 return true;
00298
00299
00300
00301
00302
00303 tmp->setX(selection->getX());
00304 tmp->setY(selection->getY());
00305
00306
00307 if (tempTarget) {
00308 sel = new KisSelection();
00309 sel = paintIndirect(selection.data(), sel, layer, m_rc.left(), m_rc.top(),
00310 m_rc.left(), m_rc.top(), m_rc.width(), m_rc.height());
00311 }
00312
00313 gc.bitBlt(selectedRect.x(), selectedRect.y(), COMPOSITE_COPY, m_projection,
00314 selectedRect.x(), selectedRect.y(),
00315 selectedRect.width(), selectedRect.height());
00316 gc.end();
00317 } else {
00318 tmp = new KisPaintDevice(*m_projection);
00319 }
00320
00321
00322
00323 KisTransaction* cmd = new KisTransaction("", tmp);
00324
00325
00326
00327 f->process(tmp, tmp, cfg, m_rc);
00328
00329 delete cmd;
00330
00331
00332 KisPainter gc(m_projection);
00333 if (selection)
00334 gc.bltSelection(m_rc.left(), m_rc.top(),
00335 COMPOSITE_OVER, tmp, sel, layer->opacity(),
00336 m_rc.left(), m_rc.top(), m_rc.width(), m_rc.height());
00337 else
00338 gc.bitBlt(m_rc.left(), m_rc.top(),
00339 COMPOSITE_OVER, tmp, layer->opacity(),
00340 m_rc.left(), m_rc.top(), m_rc.width(), m_rc.height());
00341 gc.end();
00342
00343
00344 gc.begin(layer->cachedPaintDevice());
00345 gc.bitBlt(m_rc.left(), m_rc.top(),
00346 COMPOSITE_COPY, m_projection, OPACITY_OPAQUE,
00347 m_rc.left(), m_rc.top(), m_rc.width(), m_rc.height());
00348 layer->setClean(m_rc);
00349 return true;
00350 }
00351
00352 private:
00353 KisPaintDeviceSP m_projection;
00354 QRect m_rc;
00355 };
00356
00357 #endif // KIS_MERGE_H_
00358