1 /*
2  *  Copyright (c) 2016 Dmitry Kazakov <dimula73@gmail.com>
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  */
18 
19 #include "kis_colorize_mask_test.h"
20 
21 #include <QTest>
22 
23 #include "testutil.h"
24 #include "lazybrush/kis_colorize_mask.h"
25 #include "kis_paint_device_debug_utils.h"
26 #include "kis_global.h"
27 #include "lazybrush/kis_lazy_fill_tools.h"
28 #include "kundo2command.h"
29 #include "kistest.h"
30 
31 #include <KoColor.h>
32 
33 struct ColorizeMaskTester
34 {
ColorizeMaskTesterColorizeMaskTester35     ColorizeMaskTester()
36         : refRect(0,0,200,200),
37           p(refRect)
38     {
39         KisPaintDeviceSP src = p.layer->paintDevice();
40 
41         fillRect = kisGrowRect(refRect, -20);
42         internalFillRect = kisGrowRect(fillRect, -10);
43         src->fill(fillRect, KoColor(Qt::black, src->colorSpace()));
44         src->fill(internalFillRect, KoColor(Qt::transparent, src->colorSpace()));
45         src->fill(QRect(100, 10, 10, 130), KoColor(Qt::black, src->colorSpace()));
46 
47         // KIS_DUMP_DEVICE_2(src, refRect, "src", "dd");
48 
49         mask = new KisColorizeMask(p.image, "mask1");
50         p.image->addNode(mask, p.layer);
51 
52         mask->initializeCompositeOp();
53 
54         {
55             KisPaintDeviceSP key1 = new KisPaintDevice(KoColorSpaceRegistry::instance()->alpha8());
56             key1->fill(QRect(50,50,10,20), KoColor(Qt::black, key1->colorSpace()));
57             mask->testingAddKeyStroke(key1, KoColor(Qt::green, src->colorSpace()));
58             // KIS_DUMP_DEVICE_2(key1, refRect, "key1", "dd");
59         }
60 
61         {
62             KisPaintDeviceSP key2 = new KisPaintDevice(KoColorSpaceRegistry::instance()->alpha8());
63             key2->fill(QRect(150,50,10,20), KoColor(Qt::black, key2->colorSpace()));
64             mask->testingAddKeyStroke(key2, KoColor(Qt::red, src->colorSpace()));
65             // KIS_DUMP_DEVICE_2(key2, refRect, "key2", "dd");
66         }
67 
68         {
69             KisPaintDeviceSP key3 = new KisPaintDevice(KoColorSpaceRegistry::instance()->alpha8());
70             key3->fill(QRect(0,0,10,10), KoColor(Qt::black, key3->colorSpace()));
71             mask->testingAddKeyStroke(key3, KoColor(Qt::blue, src->colorSpace()), true);
72             // KIS_DUMP_DEVICE_2(key3, refRect, "key3", "dd");
73         }
74 
75         mask->resetCache();
76 
77         mask->testingRegenerateMask();
78         p.image->waitForDone();
79 
80         // KIS_DUMP_DEVICE_2(mask->coloringProjection(), refRect, "coloring", "dd");
81         // KIS_DUMP_DEVICE_2(mask->paintDevice(), refRect, "paintDevice", "dd");
82         // KIS_DUMP_DEVICE_2(mask->testingFilteredSource(), refRect, "filteredSource", "dd");
83     }
84 
85     QRect refRect;
86     TestUtil::MaskParent p;
87     KisColorizeMaskSP mask;
88 
89     QRect fillRect;
90     QRect internalFillRect;
91 };
92 
93 
test()94 void KisColorizeMaskTest::test()
95 {
96     ColorizeMaskTester t;
97 
98     QList<KisLazyFillTools::KeyStroke> strokes;
99 
100     strokes = t.mask->fetchKeyStrokesDirect();
101 
102     const QRect expectedFillRect(25,25,145,150);
103 
104     // Check initial bounding rects
105 
106     QCOMPARE(t.mask->paintDevice()->exactBounds(), QRect(0,0,160,70));
107     QCOMPARE(t.mask->coloringProjection()->exactBounds(), expectedFillRect);
108     QCOMPARE(t.mask->testingFilteredSource()->exactBounds(), t.refRect);
109 
110     QCOMPARE(strokes[0].dev->exactBounds(), QRect(50,50,10,20));
111     QCOMPARE(strokes[1].dev->exactBounds(), QRect(150,50,10,20));
112     QCOMPARE(strokes[2].dev->exactBounds(), QRect(0,0,10,10));
113 
114     // Move the t.mask: the filled area is also expected to be moved!
115     t.mask->setX(5);
116     t.mask->setY(7);
117 
118     // KIS_DUMP_DEVICE_2(t.mask->coloringProjection(), t.refRect, "coloring2", "dd");
119     // KIS_DUMP_DEVICE_2(t.mask->paintDevice(), t.refRect, "paintDevice2", "dd");
120     // KIS_DUMP_DEVICE_2(t.mask->testingFilteredSource(), t.refRect, "filteredSource2", "dd");
121 
122     QCOMPARE(t.mask->paintDevice()->exactBounds(), QRect(5,7,160,70));
123     QCOMPARE(t.mask->coloringProjection()->exactBounds(), expectedFillRect.translated(5, 7));
124     QCOMPARE(t.mask->testingFilteredSource()->exactBounds(), t.refRect);
125 
126     QCOMPARE(strokes[0].dev->exactBounds(), QRect(55,57,10,20));
127     QCOMPARE(strokes[1].dev->exactBounds(), QRect(155,57,10,20));
128     QCOMPARE(strokes[2].dev->exactBounds(), QRect(5,7,10,10));
129 
130     // Test changing t.mask color space
131 
132     const KoColorSpace *oldCS = KoColorSpaceRegistry::instance()->rgb8();
133     const KoColorSpace *newCS = KoColorSpaceRegistry::instance()->lab16();
134 
135     QCOMPARE(t.mask->colorSpace(), oldCS);
136     QCOMPARE(t.mask->paintDevice()->colorSpace(), oldCS);
137     QCOMPARE(t.mask->coloringProjection()->colorSpace(), oldCS);
138 
139     QCOMPARE(strokes[0].color.colorSpace(), oldCS);
140     QCOMPARE(strokes[1].color.colorSpace(), oldCS);
141     QCOMPARE(strokes[2].color.colorSpace(), oldCS);
142 
143     QScopedPointer<KUndo2Command> cmd(t.mask->setColorSpace(newCS));
144     cmd->redo();
145     strokes = t.mask->fetchKeyStrokesDirect();
146 
147     QCOMPARE(t.mask->colorSpace(), newCS);
148     QCOMPARE(t.mask->paintDevice()->colorSpace(), newCS);
149     QCOMPARE(t.mask->coloringProjection()->colorSpace(), newCS);
150 
151     QCOMPARE(strokes[0].color.colorSpace(), newCS);
152     QCOMPARE(strokes[1].color.colorSpace(), newCS);
153     QCOMPARE(strokes[2].color.colorSpace(), newCS);
154 
155     cmd->undo();
156     strokes = t.mask->fetchKeyStrokesDirect();
157 
158     QCOMPARE(t.mask->colorSpace(), oldCS);
159     QCOMPARE(t.mask->paintDevice()->colorSpace(), oldCS);
160     QCOMPARE(t.mask->coloringProjection()->colorSpace(), oldCS);
161 
162     QCOMPARE(strokes[0].color.colorSpace(), oldCS);
163     QCOMPARE(strokes[1].color.colorSpace(), oldCS);
164     QCOMPARE(strokes[2].color.colorSpace(), oldCS);
165 
166     cmd->redo();
167     strokes = t.mask->fetchKeyStrokesDirect();
168 
169     QCOMPARE(t.mask->colorSpace(), newCS);
170     QCOMPARE(t.mask->paintDevice()->colorSpace(), newCS);
171     QCOMPARE(t.mask->coloringProjection()->colorSpace(), newCS);
172 
173     QCOMPARE(strokes[0].color.colorSpace(), newCS);
174     QCOMPARE(strokes[1].color.colorSpace(), newCS);
175     QCOMPARE(strokes[2].color.colorSpace(), newCS);
176 }
177 
178 #include "processing/kis_crop_processing_visitor.h"
179 
testCrop()180 void KisColorizeMaskTest::testCrop()
181 {
182     ColorizeMaskTester t;
183     QList<KisLazyFillTools::KeyStroke> strokes;
184     strokes = t.mask->fetchKeyStrokesDirect();
185 
186     const QRect expectedFillRect(25,25,145,150);
187 
188     // Check initial bounding rects
189 
190     QCOMPARE(t.mask->paintDevice()->exactBounds(), QRect(0,0,160,70));
191     QCOMPARE(t.mask->coloringProjection()->exactBounds(), expectedFillRect);
192     QCOMPARE(t.mask->testingFilteredSource()->exactBounds(), t.refRect);
193 
194     // KIS_DUMP_DEVICE_2(t.mask->coloringProjection(), t.refRect, "coloring3", "dd");
195     // KIS_DUMP_DEVICE_2(t.mask->paintDevice(), t.refRect, "paintDevice3", "dd");
196     // KIS_DUMP_DEVICE_2(t.mask->testingFilteredSource(), t.refRect, "filteredSource3", "dd");
197 
198     QCOMPARE(strokes[0].dev->exactBounds(), QRect(50,50,10,20));
199     QCOMPARE(strokes[1].dev->exactBounds(), QRect(150,50,10,20));
200     QCOMPARE(strokes[2].dev->exactBounds(), QRect(0,0,10,10));
201 
202     QRect cropRect(5,5,150,55);
203     KisCropProcessingVisitor visitor(cropRect, true, true);
204     t.mask->accept(visitor, t.p.image->undoAdapter());
205 
206     // KIS_DUMP_DEVICE_2(t.mask->coloringProjection(), t.refRect, "coloring4", "dd");
207     // KIS_DUMP_DEVICE_2(t.mask->paintDevice(), t.refRect, "paintDevice4", "dd");
208     // KIS_DUMP_DEVICE_2(t.mask->testingFilteredSource(), t.refRect, "filteredSource4", "dd");
209 
210     QCOMPARE(t.mask->paintDevice()->exactBounds(), QRect(0,0,150,55));
211     QCOMPARE(t.mask->coloringProjection()->exactBounds(), (expectedFillRect & cropRect).translated(-cropRect.topLeft()));
212     QCOMPARE(t.mask->testingFilteredSource()->exactBounds(), t.refRect);
213 
214     QCOMPARE(strokes[0].dev->exactBounds(), QRect(45,45,10,10));
215     QCOMPARE(strokes[1].dev->exactBounds(), QRect(145,45,5,10));
216     QCOMPARE(strokes[2].dev->exactBounds(), QRect(0,0,5,5));
217 }
218 
219 KISTEST_MAIN(KisColorizeMaskTest)
220