koffice/krita/image

Dmitry Kazakov dimula73 at gmail.com
Sun Nov 21 23:05:03 CET 2010


SVN commit 1199447 by dkazakov:

Fixed a full refresh for Clone layers

Now the Async Merger knows about one more type of layer position:
N_EXTRA. Such layer will be counted in a need rect chain and will be
updated (original+projection), but it will not be merged into  the
final projection of the image. This is done for preliminary updates of
the sources of Clone layers.

Btw, i would suggest everyone to perform 'make clean' in
./krita/image/ folder, because many parts of walkers are
inlined. There is no need to do a full clean, just in ./image/
directory.

CCMAIL:kimageshop at kde.org
BUG:257532


 M  +13 -0     kis_async_merger.h  
 M  +8 -7      kis_base_rects_walker.h  
 M  +27 -0     kis_full_refresh_walker.h  
 M  +4 -4      kis_node.h  
 M  +70 -0     tests/kis_async_merger_test.cpp  
 M  +1 -0      tests/kis_async_merger_test.h  


--- trunk/koffice/krita/image/kis_async_merger.h #1199446:1199447
@@ -189,6 +189,19 @@
 
             QRect applyRect = item.m_applyRect;
 
+            if(item.m_position & KisMergeWalker::N_EXTRA) {
+                // The type of layers that will not go to projection.
+
+                DEBUG_NODE_ACTION("Updating", "N_EXTRA", currentNode, applyRect);
+                KisUpdateOriginalVisitor originalVisitor(applyRect,
+                                                         m_currentProjection);
+                currentNode->accept(originalVisitor);
+                currentNode->updateProjection(applyRect);
+
+                continue;
+            }
+
+
             if(!m_currentProjection)
                 setupProjection(currentNode, applyRect, useTempProjections);
 
--- trunk/koffice/krita/image/kis_base_rects_walker.h #1199446:1199447
@@ -41,16 +41,17 @@
         N_NORMAL     = 0x00,
         N_TOPMOST    = 0x01,
         N_BOTTOMMOST = 0x02,
+        N_EXTRA      = 0x04,
 
-        N_ABOVE_FILTHY = 0x04,
-        N_FILTHY_ORIGINAL   = 0x08, // not used actually
-        N_FILTHY_PROJECTION = 0x10,
-        N_FILTHY = 0x20,
-        N_BELOW_FILTHY = 0x40
+        N_ABOVE_FILTHY = 0x08,
+        N_FILTHY_ORIGINAL   = 0x10, // not used actually
+        N_FILTHY_PROJECTION = 0x20,
+        N_FILTHY = 0x40,
+        N_BELOW_FILTHY = 0x80
     };
 
-    #define GRAPH_POSITION_MASK     0x03
-    #define POSITION_TO_FILTHY_MASK 0x7C
+    #define GRAPH_POSITION_MASK     0x07
+    #define POSITION_TO_FILTHY_MASK 0xF8
 
     struct JobItem {
         KisNodeSP m_node;
--- trunk/koffice/krita/image/kis_full_refresh_walker.h #1199446:1199447
@@ -21,8 +21,10 @@
 
 #include "kis_node.h"
 #include "kis_types.h"
+#include "kis_clone_layer.h"
 #include "kis_base_rects_walker.h"
 
+
 class KRITAIMAGE_EXPORT KisFullRefreshWalker : public KisBaseRectsWalker
 {
 
@@ -116,6 +118,31 @@
                 startTrip(currentNode);
         } while ((currentNode = currentNode->prevSibling()));
     }
+
+    void registerNeedRect(KisNodeSP node, NodePosition position) {
+        KisBaseRectsWalker::registerNeedRect(node, position);
+
+        KisCloneLayerSP cloneLayer = qobject_cast<KisCloneLayer*>(node.data());
+        if(cloneLayer) {
+            /**
+             * We need to check whether the source of the clone is going
+             * to be updated after the clone itself. If so we need to
+             * pre-update it manually. This can be checked by the precedence
+             * of the source in the nodes stack
+             */
+            if(isRegistered(cloneLayer->copyFrom())) {
+                registerNeedRect(cloneLayer->copyFrom(), N_EXTRA | N_FILTHY);
+            }
+        }
+    }
+
+    bool isRegistered(KisNodeSP node) {
+        foreach(const JobItem &item, nodeStack()) {
+            if(item.m_node == node)
+                return true;
+        }
+        return false;
+    }
 };
 
 
--- trunk/koffice/krita/image/kis_node.h #1199446:1199447
@@ -49,10 +49,10 @@
      *       when changing this struct
      */
     enum PositionToFilthy {
-        N_ABOVE_FILTHY = 0x04,
-        N_FILTHY_PROJECTION = 0x10,
-        N_FILTHY = 0x20,
-        N_BELOW_FILTHY = 0x40
+        N_ABOVE_FILTHY = 0x08,
+        N_FILTHY_PROJECTION = 0x20,
+        N_FILTHY = 0x40,
+        N_BELOW_FILTHY = 0x80
     };
 
     /**
--- trunk/koffice/krita/image/tests/kis_async_merger_test.cpp #1199446:1199447
@@ -19,6 +19,7 @@
 #include "kis_async_merger_test.h"
 
 #include "kis_merge_walker.h"
+#include "kis_full_refresh_walker.h"
 #include "kis_async_merger.h"
 
 #include <qtest_kde.h>
@@ -28,6 +29,7 @@
 #include "kis_paint_layer.h"
 #include "kis_group_layer.h"
 #include "kis_adjustment_layer.h"
+#include "kis_filter_mask.h"
 #include "kis_selection.h"
 
 #include "filter/kis_filter.h"
@@ -164,7 +166,75 @@
     QVERIFY(groupLayer->original() == paintLayer1->projection());
 }
 
+    /*
+      +--------------+
+      |root          |
+      | paint 1      |
+      |  invert_mask |
+      | clone_of_1   |
+      +--------------+
+     */
 
+void KisAsyncMergerTest::testFullRefreshWithClones()
+{
+    const KoColorSpace *colorSpace = KoColorSpaceRegistry::instance()->rgb8();
+    KisImageSP image = new KisImage(0, 128, 128, colorSpace, "clones test");
+
+    KisPaintDeviceSP device1 = new KisPaintDevice(colorSpace);
+    device1->fill(image->bounds(), KoColor( Qt::white, colorSpace));
+
+    KisFilterSP filter = KisFilterRegistry::instance()->value("invert");
+    Q_ASSERT(filter);
+    KisFilterConfiguration *configuration = filter->defaultConfiguration(0);
+    Q_ASSERT(configuration);
+
+    KisLayerSP paintLayer1 = new KisPaintLayer(image, "paint1", OPACITY_OPAQUE_U8, device1);
+    KisFilterMaskSP invertMask1 = new KisFilterMask();
+    invertMask1->setFilter(configuration);
+
+    KisLayerSP cloneLayer1 = new KisCloneLayer(paintLayer1, image, "clone_of_1", OPACITY_OPAQUE_U8);
+    /**
+     * The clone layer must have a projection to allow us
+     * to read what it got from its source. Just shift it.
+     */
+    cloneLayer1->setX(10);
+    cloneLayer1->setY(10);
+
+    image->addNode(cloneLayer1, image->rootLayer());
+    image->addNode(paintLayer1, image->rootLayer());
+    image->addNode(invertMask1, paintLayer1);
+
+    QRect cropRect(image->bounds());
+
+    KisFullRefreshWalker walker(cropRect);
+    KisAsyncMerger merger;
+
+    walker.collectRects(image->rootLayer(), image->bounds());
+    merger.startMerge(walker);
+
+    QRect filledRect(10, 10,
+                     image->width() - cloneLayer1->x(),
+                     image->height() - cloneLayer1->y());
+
+    const int pixelSize = device1->pixelSize();
+    const int numPixels = filledRect.width() * filledRect.height();
+
+    QByteArray bytes(numPixels * pixelSize, 13);
+    cloneLayer1->projection()->readBytes((quint8*)bytes.data(), filledRect);
+
+    KoColor desiredPixel(Qt::black, colorSpace);
+    quint8 *srcPtr = (quint8*)bytes.data();
+    quint8 *dstPtr = desiredPixel.data();
+    for(int i = 0; i < numPixels; i++) {
+        if(memcmp(srcPtr, dstPtr, pixelSize)) {
+            qDebug() << "expected:" << dstPtr[0] << dstPtr[1] << dstPtr[2] << dstPtr[3];
+            qDebug() << "result:  " << srcPtr[0] << srcPtr[1] << srcPtr[2] << srcPtr[3];
+            QFAIL("Failed to compare pixels");
+        }
+        srcPtr += pixelSize;
+    }
+}
+
 QTEST_KDEMAIN(KisAsyncMergerTest, NoGUI)
 #include "kis_async_merger_test.moc"
 
--- trunk/koffice/krita/image/tests/kis_async_merger_test.h #1199446:1199447
@@ -28,6 +28,7 @@
 private slots:
     void testMerger();
     void debugObligeChild();
+    void testFullRefreshWithClones();
 private:
 };
 


More information about the kimageshop mailing list