1 /*
2  *  Copyright (c) 2010 Cyrille Berger <cberger@cberger.net>
3  *  Copyright (c) 2010 Lukáš Tvrdý <lukast.dev@gmail.com>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with this library; see the file COPYING.LIB.  If not, write to
17  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19 */
20 
21 #include "TestKoCompositeOps.h"
22 
23 #include <QTest>
24 
25 #include <KoColorSpace.h>
26 
27 #include "../compositeops/KoCompositeOpAlphaDarken.h"
28 #include "../compositeops/KoCompositeOpOver.h"
29 
30 #include <KoColorSpaceTraits.h>
31 
32 #define FULL_OPACITY KoColorSpaceMathsTraits<quint16>::unitValue
33 #define HALF_OPACITY (FULL_OPACITY/2)
34 #define QUARTER_OPACITY (FULL_OPACITY/4)
35 
36 #define QCOMPAREui(a,b) QCOMPARE(a, (quint16)b)
37 
38 #include <KoCompositeOpDivide.h>
39 #include <KoCompositeOpDodge.h>
40 #include <KoCompositeOpInversedSubtract.h>
41 #include <KoCompositeOpMultiply.h>
42 #include <KoCompositeOpOverlay.h>
43 #include <KoCompositeOpScreen.h>
44 #include <KoCompositeOpSubtract.h>
45 #include <KoCompositeOpCopy.h>
46 #include <KoCompositeOpCopy2.h>
47 
48 #include <KoColorSpaceRegistry.h>
49 #include <KoColor.h>
50 
testCompositeOver()51 void TestKoCompositeOps::testCompositeOver()
52 {
53     KoBgrU16Traits::Pixel p16f;
54     KoBgrU16Traits::Pixel p16f1;
55     quint8 *p16fPtr = reinterpret_cast<quint8 *>(&p16f);
56     quint8 *p16fPtr1 = reinterpret_cast<quint8 *>(&p16f1);
57 
58     KoCompositeOpOver<KoBgrU16Traits> over(0);
59     // Test no mask, full opacity
60     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
61     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
62     over.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
63     QCOMPAREui(p16f1.red, 10000);
64     QCOMPAREui(p16f1.green, 15000);
65     QCOMPAREui(p16f1.blue, 20000);
66     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
67 
68     // Test no mask, half opacity
69     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
70     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
71     over.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 127);
72     QCOMPAREui(p16f1.red, 12510);
73     QCOMPAREui(p16f1.green, 7972);
74     QCOMPAREui(p16f1.blue, 17992);
75     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
76 
77     // Test mask, full opacity
78     quint8 mask; mask = 127;
79     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
80     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
81     over.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, &mask, 1, 1, 1, 255);
82     QCOMPAREui(p16f1.red, 12510);
83     QCOMPAREui(p16f1.green, 7972);
84     QCOMPAREui(p16f1.blue, 17992);
85     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
86 
87     // Test mask, half opacity
88     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
89     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
90     over.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, &mask, 1, 1, 1, 127);
91     QCOMPAREui(p16f1.red, 13760);
92     QCOMPAREui(p16f1.green, 4472);
93     QCOMPAREui(p16f1.blue, 16992);
94     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
95 
96     // Test no mask, full opacity, transparent source
97     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = 0;
98     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
99     over.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
100     QCOMPAREui(p16f1.red, 15000);
101     QCOMPAREui(p16f1.green, 1000);
102     QCOMPAREui(p16f1.blue, 16000);
103     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
104 
105     // Test no mask, full opacity, transparent dst
106     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
107     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = 0;
108     over.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
109     QCOMPAREui(p16f1.red, 10000);
110     QCOMPAREui(p16f1.green, 15000);
111     QCOMPAREui(p16f1.blue, 20000);
112     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
113 
114     // Test no mask, full opacity, half-transparent dst
115     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
116     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = HALF_OPACITY;
117     over.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
118     QCOMPAREui(p16f1.red, 10000);
119     QCOMPAREui(p16f1.green, 15000);
120     QCOMPAREui(p16f1.blue, 20000);
121     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
122 
123     // Test no mask, full opacity, half-transparent src
124     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = HALF_OPACITY;
125     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
126     over.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
127     QCOMPAREui(p16f1.red, 12501);
128     QCOMPAREui(p16f1.green, 7999);
129     QCOMPAREui(p16f1.blue, 17999);
130     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
131 
132     // Test no mask, full opacity, half-transparent src, dst
133     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = HALF_OPACITY;
134     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = HALF_OPACITY;
135     over.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
136     QCOMPAREui(p16f1.red, 11667);
137     QCOMPAREui(p16f1.green, 10333);
138     QCOMPAREui(p16f1.blue, 18666);
139     QCOMPAREui(p16f1.alpha, 49151);
140 
141     // Test no mask, full opacity, quarter-transparent src, half-transparent dst
142     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = QUARTER_OPACITY;
143     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = HALF_OPACITY;
144     over.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
145     QCOMPAREui(p16f1.red, 13001);
146     QCOMPAREui(p16f1.green, 6599);
147     QCOMPAREui(p16f1.blue, 17599);
148     QCOMPAREui(p16f1.alpha, 40959);
149 
150     // Test no mask, full opacity, quarter-transparent dst, half-transparent src
151     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = HALF_OPACITY;
152     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = QUARTER_OPACITY;
153     over.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
154     QCOMPAREui(p16f1.red, 11000);
155     QCOMPAREui(p16f1.green, 12200);
156     QCOMPAREui(p16f1.blue, 19200);
157     QCOMPAREui(p16f1.alpha, 40959);
158 }
159 
testCompositeAlphaDarken()160 void TestKoCompositeOps::testCompositeAlphaDarken()
161 {
162     KoBgrU16Traits::Pixel p16f;
163     KoBgrU16Traits::Pixel p16f1;
164     quint8 *p16fPtr = reinterpret_cast<quint8 *>(&p16f);
165     quint8 *p16fPtr1 = reinterpret_cast<quint8 *>(&p16f1);
166 
167     KoCompositeOpAlphaDarken<KoBgrU16Traits> alphaDarken(0);
168     // Test no mask, full opacity
169     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
170     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
171     alphaDarken.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
172     QCOMPAREui(p16f1.red, 10000);
173     QCOMPAREui(p16f1.green, 15000);
174     QCOMPAREui(p16f1.blue, 20000);
175     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
176 
177     // Test no mask, half opacity
178     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
179     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
180     alphaDarken.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 127);
181     QCOMPAREui(p16f1.red, 12510);
182     QCOMPAREui(p16f1.green, 7972);
183     QCOMPAREui(p16f1.blue, 17992);
184     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
185 
186     // Test mask, full opacity
187     quint8 mask; mask = 127;
188     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
189     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
190     alphaDarken.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, &mask, 1, 1, 1, 255);
191     QCOMPAREui(p16f1.red, 12510);
192     QCOMPAREui(p16f1.green, 7972);
193     QCOMPAREui(p16f1.blue, 17992);
194     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
195 
196     // Test mask, half opacity
197     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
198     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
199     alphaDarken.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, &mask, 1, 1, 1, 127);
200     QCOMPAREui(p16f1.red, 13760);
201     QCOMPAREui(p16f1.green, 4472);
202     QCOMPAREui(p16f1.blue, 16992);
203     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
204 
205     // Test no mask, full opacity, transparent source
206     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = 0;
207     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
208     alphaDarken.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
209     QCOMPAREui(p16f1.red, 15000);
210     QCOMPAREui(p16f1.green, 1000);
211     QCOMPAREui(p16f1.blue, 16000);
212     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
213 
214     // Test no mask, full opacity, transparent dst
215     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
216     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = 0;
217     alphaDarken.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
218     QCOMPAREui(p16f1.red, 10000);
219     QCOMPAREui(p16f1.green, 15000);
220     QCOMPAREui(p16f1.blue, 20000);
221     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
222 
223     // Test no mask, full opacity, half-transparent dst
224     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
225     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = HALF_OPACITY;
226     alphaDarken.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
227     QCOMPAREui(p16f1.red, 10000);
228     QCOMPAREui(p16f1.green, 15000);
229     QCOMPAREui(p16f1.blue, 20000);
230     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
231 
232     // Test no mask, full opacity, half-transparent src
233     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = HALF_OPACITY;
234     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
235     alphaDarken.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
236     QCOMPAREui(p16f1.red, 12501);
237     QCOMPAREui(p16f1.green, 7999);
238     QCOMPAREui(p16f1.blue, 17999);
239     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
240 
241     // Test no mask, full opacity, half-transparent src
242     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = HALF_OPACITY;
243     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = HALF_OPACITY;
244     alphaDarken.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
245     QCOMPAREui(p16f1.red, 12501);
246     QCOMPAREui(p16f1.green, 7999);
247     QCOMPAREui(p16f1.blue, 17999);
248     QCOMPAREui(p16f1.alpha, 49150);
249 
250     // Test no mask, full opacity, quarter-transparent src, half-transparent dst
251     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = QUARTER_OPACITY;
252     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = HALF_OPACITY;
253     alphaDarken.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
254     QCOMPAREui(p16f1.red, 13751);
255     QCOMPAREui(p16f1.green, 4499);
256     QCOMPAREui(p16f1.blue, 16999);
257     QCOMPAREui(p16f1.alpha, 40958);
258 
259     // Test no mask, full opacity, quarter-transparent dst, half-transparent src
260     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = HALF_OPACITY;
261     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = QUARTER_OPACITY;
262     alphaDarken.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
263     QCOMPAREui(p16f1.red, 12501);
264     QCOMPAREui(p16f1.green, 7999);
265     QCOMPAREui(p16f1.blue, 17999);
266     QCOMPAREui(p16f1.alpha, 40958);
267 }
268 
testCompositeDivide()269 void TestKoCompositeOps::testCompositeDivide()
270 {
271     KoBgrU16Traits::Pixel p16f;
272     KoBgrU16Traits::Pixel p16f1;
273     quint8 *p16fPtr = reinterpret_cast<quint8 *>(&p16f);
274     quint8 *p16fPtr1 = reinterpret_cast<quint8 *>(&p16f1);
275 
276     KoCompositeOpDivide<KoBgrU16Traits> divide(0);
277     // Test no mask, full opacity
278     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
279     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
280     divide.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
281     QCOMPAREui(p16f1.red, 65535);
282     QCOMPAREui(p16f1.green, 4369);
283     QCOMPAREui(p16f1.blue, 52426);
284     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
285 
286     // Test no mask, half opacity
287     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
288     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
289     divide.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 127);
290     QCOMPAREui(p16f1.red, 40168);
291     QCOMPAREui(p16f1.green, 2677);
292     QCOMPAREui(p16f1.blue, 34141);
293     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
294 
295     // Test mask, full opacity
296     quint8 mask; mask = 127;
297     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
298     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
299     divide.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, &mask, 1, 1, 1, 255);
300     QCOMPAREui(p16f1.red, 40168);
301     QCOMPAREui(p16f1.green, 2677);
302     QCOMPAREui(p16f1.blue, 34141);
303     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
304 
305     // Test mask, half opacity
306     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
307     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
308     divide.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, &mask, 1, 1, 1, 127);
309     QCOMPAREui(p16f1.red, 27534);
310     QCOMPAREui(p16f1.green, 1835);
311     QCOMPAREui(p16f1.blue, 25034);
312     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
313 
314     // Test no mask, full opacity, transparent source
315     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = 0;
316     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
317     divide.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
318     QCOMPAREui(p16f1.red, 15000);
319     QCOMPAREui(p16f1.green, 1000);
320     QCOMPAREui(p16f1.blue, 16000);
321     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
322 
323     // Test no mask, full opacity, transparent dst
324     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
325     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = 0;
326     divide.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
327     QCOMPAREui(p16f1.red, 15000);
328     QCOMPAREui(p16f1.green, 1000);
329     QCOMPAREui(p16f1.blue, 16000);
330     QCOMPAREui(p16f1.alpha, 0);
331 
332     // Test no mask, full opacity, half-transparent dst
333     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
334     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = HALF_OPACITY;
335     divide.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
336     QCOMPAREui(p16f1.red, 48690);
337     QCOMPAREui(p16f1.green, 3246);
338     QCOMPAREui(p16f1.blue, 40284);
339     QCOMPAREui(p16f1.alpha, HALF_OPACITY);
340 
341     // Test no mask, full opacity, half-transparent src
342     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = HALF_OPACITY;
343     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
344     divide.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
345     QCOMPAREui(p16f1.red, 40267);
346     QCOMPAREui(p16f1.green, 2684);
347     QCOMPAREui(p16f1.blue, 34212);
348     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
349 
350     // Test no mask, full opacity, half-transparent src
351     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = HALF_OPACITY;
352     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = HALF_OPACITY;
353     divide.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
354     QCOMPAREui(p16f1.red, 48690);
355     QCOMPAREui(p16f1.green, 3246);
356     QCOMPAREui(p16f1.blue, 40284);
357     QCOMPAREui(p16f1.alpha, HALF_OPACITY);
358 
359     // Test no mask, full opacity, quarter-transparent src, half-transparent dst
360     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = QUARTER_OPACITY;
361     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = HALF_OPACITY;
362     divide.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
363     QCOMPAREui(p16f1.red, 35213);
364     QCOMPAREui(p16f1.green, 2347);
365     QCOMPAREui(p16f1.blue, 30569);
366     QCOMPAREui(p16f1.alpha, HALF_OPACITY);
367 
368     // Test no mask, full opacity, quarter-transparent dst, half-transparent src
369     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = HALF_OPACITY;
370     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = QUARTER_OPACITY;
371     divide.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
372     QCOMPAREui(p16f1.red, 43877);
373     QCOMPAREui(p16f1.green, 2925);
374     QCOMPAREui(p16f1.blue, 36815);
375     QCOMPAREui(p16f1.alpha, QUARTER_OPACITY);
376 }
377 
testCompositeDodge()378 void TestKoCompositeOps::testCompositeDodge()
379 {
380     KoBgrU16Traits::Pixel p16f;
381     KoBgrU16Traits::Pixel p16f1;
382     quint8 *p16fPtr = reinterpret_cast<quint8 *>(&p16f);
383     quint8 *p16fPtr1 = reinterpret_cast<quint8 *>(&p16f1);
384 
385     KoCompositeOpDodge<KoBgrU16Traits> dodge(0);
386     // Test no mask, full opacity
387     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
388     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
389     dodge.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
390     QCOMPAREui(p16f1.red, 17700);
391     QCOMPAREui(p16f1.green, 1296);
392     QCOMPAREui(p16f1.blue, 23027);
393     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
394 
395     // Test no mask, half opacity
396     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
397     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
398     dodge.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 127);
399     QCOMPAREui(p16f1.red, 16344);
400     QCOMPAREui(p16f1.green, 1147);
401     QCOMPAREui(p16f1.blue, 19499);
402     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
403 
404     // Test mask, full opacity
405     quint8 mask; mask = 127;
406     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
407     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
408     dodge.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, &mask, 1, 1, 1, 255);
409     QCOMPAREui(p16f1.red, 16344);
410     QCOMPAREui(p16f1.green, 1147);
411     QCOMPAREui(p16f1.blue, 19499);
412     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
413 
414     // Test mask, half opacity
415     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
416     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
417     dodge.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, &mask, 1, 1, 1, 127);
418     QCOMPAREui(p16f1.red, 15669);
419     QCOMPAREui(p16f1.green, 1073);
420     QCOMPAREui(p16f1.blue, 17742);
421     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
422 
423     // Test no mask, full opacity, transparent source
424     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = 0;
425     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
426     dodge.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
427     QCOMPAREui(p16f1.red, 15000);
428     QCOMPAREui(p16f1.green, 1000);
429     QCOMPAREui(p16f1.blue, 16000);
430     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
431 
432     // Test no mask, full opacity, transparent dst
433     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
434     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = 0;
435     dodge.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
436     QCOMPAREui(p16f1.red, 15000);
437     QCOMPAREui(p16f1.green, 1000);
438     QCOMPAREui(p16f1.blue, 16000);
439     QCOMPAREui(p16f1.alpha, 0);
440 
441     // Test no mask, full opacity, half-transparent dst
442     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
443     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = HALF_OPACITY;
444     dodge.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
445     QCOMPAREui(p16f1.red, 16800);
446     QCOMPAREui(p16f1.green, 1197);
447     QCOMPAREui(p16f1.blue, 20684);
448     QCOMPAREui(p16f1.alpha, HALF_OPACITY);
449 
450     // Test no mask, full opacity, half-transparent src
451     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = HALF_OPACITY;
452     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
453     dodge.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
454     QCOMPAREui(p16f1.red, 16349);
455     QCOMPAREui(p16f1.green, 1147);
456     QCOMPAREui(p16f1.blue, 19513);
457     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
458 
459     // Test no mask, full opacity, half-transparent src
460     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = HALF_OPACITY;
461     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = HALF_OPACITY;
462     dodge.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
463     QCOMPAREui(p16f1.red, 16800);
464     QCOMPAREui(p16f1.green, 1197);
465     QCOMPAREui(p16f1.blue, 20684);
466     QCOMPAREui(p16f1.alpha, HALF_OPACITY);
467 
468     // Test no mask, full opacity, quarter-transparent src, half-transparent dst
469     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = QUARTER_OPACITY;
470     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = HALF_OPACITY;
471     dodge.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
472     QCOMPAREui(p16f1.red, 16079);
473     QCOMPAREui(p16f1.green, 1118);
474     QCOMPAREui(p16f1.blue, 18810);
475     QCOMPAREui(p16f1.alpha, HALF_OPACITY);
476 
477     // Test no mask, full opacity, quarter-transparent dst, half-transparent src
478     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = HALF_OPACITY;
479     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = QUARTER_OPACITY;
480     dodge.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
481     QCOMPAREui(p16f1.red, 16542);
482     QCOMPAREui(p16f1.green, 1169);
483     QCOMPAREui(p16f1.blue, 20015);
484     QCOMPAREui(p16f1.alpha, QUARTER_OPACITY);
485 }
486 
testCompositeInversedSubtract()487 void TestKoCompositeOps::testCompositeInversedSubtract()
488 {
489     KoBgrU16Traits::Pixel p16f;
490     KoBgrU16Traits::Pixel p16f1;
491     quint8 *p16fPtr = reinterpret_cast<quint8 *>(&p16f);
492     quint8 *p16fPtr1 = reinterpret_cast<quint8 *>(&p16f1);
493 
494     KoCompositeOpInversedSubtract<KoBgrU16Traits> inversedSubtract(0);
495     // Test no mask, full opacity
496     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
497     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
498     inversedSubtract.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
499     QCOMPAREui(p16f1.red, 0);
500     QCOMPAREui(p16f1.green, 14000);
501     QCOMPAREui(p16f1.blue, 4000);
502     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
503 
504     // Test no mask, half opacity
505     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
506     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
507     inversedSubtract.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 127);
508     QCOMPAREui(p16f1.red, 7530);
509     QCOMPAREui(p16f1.green, 7474);
510     QCOMPAREui(p16f1.blue, 10024);
511     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
512 
513     // Test mask, full opacity
514     quint8 mask; mask = 127;
515     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
516     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
517     inversedSubtract.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, &mask, 1, 1, 1, 255);
518     QCOMPAREui(p16f1.red, 7530);
519     QCOMPAREui(p16f1.green, 7474);
520     QCOMPAREui(p16f1.blue, 10024);
521     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
522 
523     // Test mask, half opacity
524     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
525     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
526     inversedSubtract.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, &mask, 1, 1, 1, 127);
527     QCOMPAREui(p16f1.red, 11280);
528     QCOMPAREui(p16f1.green, 4224);
529     QCOMPAREui(p16f1.blue, 13024);
530     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
531 
532     // Test no mask, full opacity, transparent source
533     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = 0;
534     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
535     inversedSubtract.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
536     QCOMPAREui(p16f1.red, 15000);
537     QCOMPAREui(p16f1.green, 1000);
538     QCOMPAREui(p16f1.blue, 16000);
539     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
540 
541     // Test no mask, full opacity, transparent dst
542     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
543     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = 0;
544     inversedSubtract.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
545     QCOMPAREui(p16f1.red, 15000);
546     QCOMPAREui(p16f1.green, 1000);
547     QCOMPAREui(p16f1.blue, 16000);
548     QCOMPAREui(p16f1.alpha, 0);
549 
550     // Test no mask, full opacity, half-transparent dst
551     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
552     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = HALF_OPACITY;
553     inversedSubtract.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
554     QCOMPAREui(p16f1.red, 5000);
555     QCOMPAREui(p16f1.green, 9666);
556     QCOMPAREui(p16f1.blue, 8000);
557     QCOMPAREui(p16f1.alpha, HALF_OPACITY);
558 
559     // Test no mask, full opacity, half-transparent src
560     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = HALF_OPACITY;
561     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
562     inversedSubtract.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
563     QCOMPAREui(p16f1.red, 7501);
564     QCOMPAREui(p16f1.green, 7499);
565     QCOMPAREui(p16f1.blue, 10001);
566     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
567 
568     // Test no mask, full opacity, half-transparent src
569     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = HALF_OPACITY;
570     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = HALF_OPACITY;
571     inversedSubtract.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
572     QCOMPAREui(p16f1.red, 5000);
573     QCOMPAREui(p16f1.green, 9666);
574     QCOMPAREui(p16f1.blue, 8000);
575     QCOMPAREui(p16f1.alpha, HALF_OPACITY);
576 
577     // Test no mask, full opacity, quarter-transparent src, half-transparent dst
578     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = QUARTER_OPACITY;
579     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = HALF_OPACITY;
580     inversedSubtract.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
581     QCOMPAREui(p16f1.red, 9001);
582     QCOMPAREui(p16f1.green, 6199);
583     QCOMPAREui(p16f1.blue, 11201);
584     QCOMPAREui(p16f1.alpha, HALF_OPACITY);
585 
586     // Test no mask, full opacity, quarter-transparent dst, half-transparent src
587     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = HALF_OPACITY;
588     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = QUARTER_OPACITY;
589     inversedSubtract.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
590     QCOMPAREui(p16f1.red, 6429);
591     QCOMPAREui(p16f1.green, 8428);
592     QCOMPAREui(p16f1.blue, 9143);
593     QCOMPAREui(p16f1.alpha, QUARTER_OPACITY);
594 }
595 
testCompositeMulitply()596 void TestKoCompositeOps::testCompositeMulitply()
597 {
598     KoBgrU16Traits::Pixel p16f;
599     KoBgrU16Traits::Pixel p16f1;
600     quint8 *p16fPtr = reinterpret_cast<quint8 *>(&p16f);
601     quint8 *p16fPtr1 = reinterpret_cast<quint8 *>(&p16f1);
602 
603     KoCompositeOpMultiply<KoBgrU16Traits> mulitply(0);
604     // Test no mask, full opacity
605     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
606     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
607     mulitply.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
608     QCOMPAREui(p16f1.red, 2289);
609     QCOMPAREui(p16f1.green, 229);
610     QCOMPAREui(p16f1.blue, 4883);
611     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
612 
613     // Test no mask, half opacity
614     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
615     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
616     mulitply.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 127);
617     QCOMPAREui(p16f1.red, 8670);
618     QCOMPAREui(p16f1.green, 617);
619     QCOMPAREui(p16f1.blue, 10464);
620     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
621 
622     // Test mask, full opacity
623     quint8 mask; mask = 127;
624     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
625     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
626     mulitply.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, &mask, 1, 1, 1, 255);
627     QCOMPAREui(p16f1.red, 8670);
628     QCOMPAREui(p16f1.green, 617);
629     QCOMPAREui(p16f1.blue, 10464);
630     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
631 
632     // Test mask, half opacity
633     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
634     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
635     mulitply.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, &mask, 1, 1, 1, 127);
636     QCOMPAREui(p16f1.red, 11848);
637     QCOMPAREui(p16f1.green, 809);
638     QCOMPAREui(p16f1.blue, 13243);
639     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
640 
641     // Test no mask, full opacity, transparent source
642     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = 0;
643     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
644     mulitply.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
645     QCOMPAREui(p16f1.red, 15000);
646     QCOMPAREui(p16f1.green, 1000);
647     QCOMPAREui(p16f1.blue, 16000);
648     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
649 
650     // Test no mask, full opacity, transparent dst
651     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
652     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = 0;
653     mulitply.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
654     QCOMPAREui(p16f1.red, 15000);
655     QCOMPAREui(p16f1.green, 1000);
656     QCOMPAREui(p16f1.blue, 16000);
657     QCOMPAREui(p16f1.alpha, 0);
658 
659     // Test no mask, full opacity, half-transparent dst
660     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
661     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = HALF_OPACITY;
662     mulitply.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
663     QCOMPAREui(p16f1.red, 6526);
664     QCOMPAREui(p16f1.green, 486);
665     QCOMPAREui(p16f1.blue, 8589);
666     QCOMPAREui(p16f1.alpha, HALF_OPACITY);
667 
668     // Test no mask, full opacity, half-transparent src
669     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = HALF_OPACITY;
670     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
671     mulitply.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
672     QCOMPAREui(p16f1.red, 8645);
673     QCOMPAREui(p16f1.green, 615);
674     QCOMPAREui(p16f1.blue, 10442);
675     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
676 
677     // Test no mask, full opacity, half-transparent src
678     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = HALF_OPACITY;
679     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = HALF_OPACITY;
680     mulitply.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
681     QCOMPAREui(p16f1.red, 6526);
682     QCOMPAREui(p16f1.green, 486);
683     QCOMPAREui(p16f1.blue, 8589);
684     QCOMPAREui(p16f1.alpha, HALF_OPACITY);
685 
686     // Test no mask, full opacity, quarter-transparent src, half-transparent dst
687     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = QUARTER_OPACITY;
688     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = HALF_OPACITY;
689     mulitply.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
690     QCOMPAREui(p16f1.red, 9916);
691     QCOMPAREui(p16f1.green, 692);
692     QCOMPAREui(p16f1.blue, 11554);
693     QCOMPAREui(p16f1.alpha, HALF_OPACITY);
694 
695     // Test no mask, full opacity, quarter-transparent dst, half-transparent src
696     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = HALF_OPACITY;
697     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = QUARTER_OPACITY;
698     mulitply.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
699     QCOMPAREui(p16f1.red, 7737);
700     QCOMPAREui(p16f1.green, 560);
701     QCOMPAREui(p16f1.blue, 9648);
702     QCOMPAREui(p16f1.alpha, QUARTER_OPACITY);
703 }
704 
testCompositeOverlay()705 void TestKoCompositeOps::testCompositeOverlay()
706 {
707     KoBgrU16Traits::Pixel p16f;
708     KoBgrU16Traits::Pixel p16f1;
709     quint8 *p16fPtr = reinterpret_cast<quint8 *>(&p16f);
710     quint8 *p16fPtr1 = reinterpret_cast<quint8 *>(&p16f1);
711 
712     KoCompositeOpOverlay<KoBgrU16Traits> overlay(0);
713     // Test no mask, full opacity
714     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
715     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
716     overlay.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
717     QCOMPAREui(p16f1.red, 6963);
718     QCOMPAREui(p16f1.green, 466);
719     QCOMPAREui(p16f1.blue, 11288);
720     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
721 
722     // Test no mask, half opacity
723     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
724     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
725     overlay.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 127);
726     QCOMPAREui(p16f1.red, 10998);
727     QCOMPAREui(p16f1.green, 735);
728     QCOMPAREui(p16f1.blue, 13654);
729     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
730 
731     // Test mask, full opacity
732     quint8 mask; mask = 127;
733     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
734     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
735     overlay.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, &mask, 1, 1, 1, 255);
736     QCOMPAREui(p16f1.red, 10998);
737     QCOMPAREui(p16f1.green, 735);
738     QCOMPAREui(p16f1.blue, 13654);
739     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
740 
741     // Test mask, half opacity
742     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
743     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
744     overlay.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, &mask, 1, 1, 1, 127);
745     QCOMPAREui(p16f1.red, 13007);
746     QCOMPAREui(p16f1.green, 868);
747     QCOMPAREui(p16f1.blue, 14832);
748     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
749 
750     // Test no mask, full opacity, transparent source
751     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = 0;
752     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
753     overlay.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
754     QCOMPAREui(p16f1.red, 15000);
755     QCOMPAREui(p16f1.green, 1000);
756     QCOMPAREui(p16f1.blue, 16000);
757     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
758 
759     // Test no mask, full opacity, transparent dst
760     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
761     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = 0;
762     overlay.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
763     QCOMPAREui(p16f1.red, 15000);
764     QCOMPAREui(p16f1.green, 1000);
765     QCOMPAREui(p16f1.blue, 16000);
766     QCOMPAREui(p16f1.alpha, 0);
767 
768     // Test no mask, full opacity, half-transparent dst
769     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
770     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = HALF_OPACITY;
771     overlay.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
772     QCOMPAREui(p16f1.red, 9642);
773     QCOMPAREui(p16f1.green, 644);
774     QCOMPAREui(p16f1.blue, 12859);
775     QCOMPAREui(p16f1.alpha, HALF_OPACITY);
776 
777     // Test no mask, full opacity, half-transparent src
778     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = HALF_OPACITY;
779     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
780     overlay.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
781     QCOMPAREui(p16f1.red, 10982);
782     QCOMPAREui(p16f1.green, 734);
783     QCOMPAREui(p16f1.blue, 13645);
784     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
785 
786     // Test no mask, full opacity, half-transparent src
787     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = HALF_OPACITY;
788     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = HALF_OPACITY;
789     overlay.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
790     QCOMPAREui(p16f1.red, 9642);
791     QCOMPAREui(p16f1.green, 644);
792     QCOMPAREui(p16f1.blue, 12859);
793     QCOMPAREui(p16f1.alpha, HALF_OPACITY);
794 
795     // Test no mask, full opacity, quarter-transparent src, half-transparent dst
796     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = QUARTER_OPACITY;
797     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = HALF_OPACITY;
798     overlay.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
799     QCOMPAREui(p16f1.red, 11786);
800     QCOMPAREui(p16f1.green, 787);
801     QCOMPAREui(p16f1.blue, 14116);
802     QCOMPAREui(p16f1.alpha, HALF_OPACITY);
803 
804     // Test no mask, full opacity, quarter-transparent dst, half-transparent src
805     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = HALF_OPACITY;
806     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = QUARTER_OPACITY;
807     overlay.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
808     QCOMPAREui(p16f1.red, 10408);
809     QCOMPAREui(p16f1.green, 695);
810     QCOMPAREui(p16f1.blue, 13308);
811     QCOMPAREui(p16f1.alpha, QUARTER_OPACITY);
812 }
813 
testCompositeScreen()814 void TestKoCompositeOps::testCompositeScreen()
815 {
816     KoBgrU16Traits::Pixel p16f;
817     KoBgrU16Traits::Pixel p16f1;
818     quint8 *p16fPtr = reinterpret_cast<quint8 *>(&p16f);
819     quint8 *p16fPtr1 = reinterpret_cast<quint8 *>(&p16f1);
820 
821     KoCompositeOpScreen<KoBgrU16Traits> screen(0);
822     // Test no mask, full opacity
823     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
824     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
825     screen.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
826     QCOMPAREui(p16f1.red, 22711);
827     QCOMPAREui(p16f1.green, 15771);
828     QCOMPAREui(p16f1.blue, 31117);
829     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
830 
831     // Test no mask, half opacity
832     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
833     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
834     screen.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 127);
835     QCOMPAREui(p16f1.red, 18840);
836     QCOMPAREui(p16f1.green, 8356);
837     QCOMPAREui(p16f1.blue, 23528);
838     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
839 
840     // Test mask, full opacity
841     quint8 mask; mask = 127;
842     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
843     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
844     screen.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, &mask, 1, 1, 1, 255);
845     QCOMPAREui(p16f1.red, 18840);
846     QCOMPAREui(p16f1.green, 8356);
847     QCOMPAREui(p16f1.blue, 23528);
848     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
849 
850     // Test mask, half opacity
851     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
852     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
853     screen.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, &mask, 1, 1, 1, 127);
854     QCOMPAREui(p16f1.red, 16912);
855     QCOMPAREui(p16f1.green, 4663);
856     QCOMPAREui(p16f1.blue, 19749);
857     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
858 
859     // Test no mask, full opacity, transparent source
860     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = 0;
861     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
862     screen.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
863     QCOMPAREui(p16f1.red, 15000);
864     QCOMPAREui(p16f1.green, 1000);
865     QCOMPAREui(p16f1.blue, 16000);
866     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
867 
868     // Test no mask, full opacity, transparent dst
869     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
870     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = 0;
871     screen.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
872     QCOMPAREui(p16f1.red, 15000);
873     QCOMPAREui(p16f1.green, 1000);
874     QCOMPAREui(p16f1.blue, 16000);
875     QCOMPAREui(p16f1.alpha, 0);
876 
877     // Test no mask, full opacity, half-transparent dst
878     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
879     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = HALF_OPACITY;
880     screen.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
881     QCOMPAREui(p16f1.red, 20140);
882     QCOMPAREui(p16f1.green, 10847);
883     QCOMPAREui(p16f1.blue, 26078);
884     QCOMPAREui(p16f1.alpha, HALF_OPACITY);
885 
886     // Test no mask, full opacity, half-transparent src
887     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = HALF_OPACITY;
888     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
889     screen.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
890     QCOMPAREui(p16f1.red, 18855);
891     QCOMPAREui(p16f1.green, 8385);
892     QCOMPAREui(p16f1.blue, 23558);
893     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
894 
895     // Test no mask, full opacity, half-transparent src
896     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = HALF_OPACITY;
897     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = HALF_OPACITY;
898     screen.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
899     QCOMPAREui(p16f1.red, 20140);
900     QCOMPAREui(p16f1.green, 10847);
901     QCOMPAREui(p16f1.blue, 26078);
902     QCOMPAREui(p16f1.alpha, HALF_OPACITY);
903 
904     // Test no mask, full opacity, quarter-transparent src, half-transparent dst
905     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = QUARTER_OPACITY;
906     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = HALF_OPACITY;
907     screen.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
908     QCOMPAREui(p16f1.red, 18084);
909     QCOMPAREui(p16f1.green, 6908);
910     QCOMPAREui(p16f1.blue, 22046);
911     QCOMPAREui(p16f1.alpha, HALF_OPACITY);
912 
913     // Test no mask, full opacity, quarter-transparent dst, half-transparent src
914     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = HALF_OPACITY;
915     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = QUARTER_OPACITY;
916     screen.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
917     QCOMPAREui(p16f1.red, 19406);
918     QCOMPAREui(p16f1.green, 9440);
919     QCOMPAREui(p16f1.blue, 24638);
920     QCOMPAREui(p16f1.alpha, QUARTER_OPACITY);
921 }
922 
testCompositeSubtract()923 void TestKoCompositeOps::testCompositeSubtract()
924 {
925     KoBgrU16Traits::Pixel p16f;
926     KoBgrU16Traits::Pixel p16f1;
927     quint8 *p16fPtr = reinterpret_cast<quint8 *>(&p16f);
928     quint8 *p16fPtr1 = reinterpret_cast<quint8 *>(&p16f1);
929 
930     KoCompositeOpSubtract<KoBgrU16Traits> subtract(0);
931     // Test no mask, full opacity
932     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
933     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
934     subtract.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
935     QCOMPAREui(p16f1.red, 5000);
936     QCOMPAREui(p16f1.green, 0);
937     QCOMPAREui(p16f1.blue, 0);
938     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
939 
940     // Test no mask, half opacity
941     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
942     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
943     subtract.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 127);
944     QCOMPAREui(p16f1.red, 10020);
945     QCOMPAREui(p16f1.green, 502);
946     QCOMPAREui(p16f1.blue, 8032);
947     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
948 
949     // Test mask, full opacity
950     quint8 mask; mask = 127;
951     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
952     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
953     subtract.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, &mask, 1, 1, 1, 255);
954     QCOMPAREui(p16f1.red, 10020);
955     QCOMPAREui(p16f1.green, 502);
956     QCOMPAREui(p16f1.blue, 8032);
957     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
958 
959     // Test mask, half opacity
960     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
961     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
962     subtract.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, &mask, 1, 1, 1, 127);
963     QCOMPAREui(p16f1.red, 12520);
964     QCOMPAREui(p16f1.green, 752);
965     QCOMPAREui(p16f1.blue, 12032);
966     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
967 
968     // Test no mask, full opacity, transparent source
969     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = 0;
970     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
971     subtract.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
972     QCOMPAREui(p16f1.red, 15000);
973     QCOMPAREui(p16f1.green, 1000);
974     QCOMPAREui(p16f1.blue, 16000);
975     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
976 
977     // Test no mask, full opacity, transparent dst
978     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
979     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = 0;
980     subtract.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
981     QCOMPAREui(p16f1.red, 15000);
982     QCOMPAREui(p16f1.green, 1000);
983     QCOMPAREui(p16f1.blue, 16000);
984     QCOMPAREui(p16f1.alpha, 0);
985 
986     // Test no mask, full opacity, half-transparent dst
987     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
988     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = HALF_OPACITY;
989     subtract.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
990     QCOMPAREui(p16f1.red, 8334);
991     QCOMPAREui(p16f1.green, 334);
992     QCOMPAREui(p16f1.blue, 5334);
993     QCOMPAREui(p16f1.alpha, HALF_OPACITY);
994 
995     // Test no mask, full opacity, half-transparent src
996     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = HALF_OPACITY;
997     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
998     subtract.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
999     QCOMPAREui(p16f1.red, 10001);
1000     QCOMPAREui(p16f1.green, 501);
1001     QCOMPAREui(p16f1.blue, 8001);
1002     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
1003 
1004     // Test no mask, full opacity, half-transparent src
1005     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = HALF_OPACITY;
1006     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = HALF_OPACITY;
1007     subtract.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
1008     QCOMPAREui(p16f1.red, 8334);
1009     QCOMPAREui(p16f1.green, 334);
1010     QCOMPAREui(p16f1.blue, 5334);
1011     QCOMPAREui(p16f1.alpha, HALF_OPACITY);
1012 
1013     // Test no mask, full opacity, quarter-transparent src, half-transparent dst
1014     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = QUARTER_OPACITY;
1015     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = HALF_OPACITY;
1016     subtract.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
1017     QCOMPAREui(p16f1.red, 11001);
1018     QCOMPAREui(p16f1.green, 601);
1019     QCOMPAREui(p16f1.blue, 9601);
1020     QCOMPAREui(p16f1.alpha, HALF_OPACITY);
1021 
1022     // Test no mask, full opacity, quarter-transparent dst, half-transparent src
1023     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = HALF_OPACITY;
1024     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = QUARTER_OPACITY;
1025     subtract.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
1026     QCOMPAREui(p16f1.red, 9286);
1027     QCOMPAREui(p16f1.green, 429);
1028     QCOMPAREui(p16f1.blue, 6858);
1029     QCOMPAREui(p16f1.alpha, QUARTER_OPACITY);
1030 }
1031 
testCompositeCopy2()1032 void TestKoCompositeOps::testCompositeCopy2()
1033 {
1034     KoBgrU16Traits::Pixel p16f;
1035     KoBgrU16Traits::Pixel p16f1;
1036     quint8 *p16fPtr = reinterpret_cast<quint8 *>(&p16f);
1037     quint8 *p16fPtr1 = reinterpret_cast<quint8 *>(&p16f1);
1038 
1039     KoCompositeOpCopy2<KoBgrU16Traits> copy(0);
1040     // Test no mask, full opacity
1041     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
1042     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
1043     copy.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
1044     QCOMPAREui(p16f1.red, 10000);
1045     QCOMPAREui(p16f1.green, 15000);
1046     QCOMPAREui(p16f1.blue, 20000);
1047     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
1048 
1049     // Test no mask, half opacity
1050     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
1051     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
1052     copy.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 127);
1053     QCOMPAREui(p16f1.red, 12510);
1054     QCOMPAREui(p16f1.green, 7972);
1055     QCOMPAREui(p16f1.blue, 17992);
1056     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
1057 
1058     // Test mask, full opacity
1059     quint8 mask; mask = 127;
1060     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
1061     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
1062     copy.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, &mask, 1, 1, 1, 255);
1063     QCOMPAREui(p16f1.red, 12510);
1064     QCOMPAREui(p16f1.green, 7972);
1065     QCOMPAREui(p16f1.blue, 17992);
1066     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
1067 
1068     // Test mask, half opacity
1069     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
1070     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
1071     copy.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, &mask, 1, 1, 1, 127);
1072     QCOMPAREui(p16f1.red, 13760);
1073     QCOMPAREui(p16f1.green, 4472);
1074     QCOMPAREui(p16f1.blue, 16992);
1075     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
1076 
1077     // Test no mask, full opacity, transparent source
1078     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = 0;
1079     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
1080     copy.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
1081     QCOMPAREui(p16f1.red, 10000);
1082     QCOMPAREui(p16f1.green, 15000);
1083     QCOMPAREui(p16f1.blue, 20000);
1084     QCOMPAREui(p16f1.alpha, 0);
1085 
1086     // Test no mask, full opacity, transparent dst
1087     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
1088     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = 0;
1089     copy.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
1090     QCOMPAREui(p16f1.red, 10000);
1091     QCOMPAREui(p16f1.green, 15000);
1092     QCOMPAREui(p16f1.blue, 20000);
1093     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
1094 
1095     // Test no mask, full opacity, half-transparent dst
1096     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = FULL_OPACITY;
1097     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = HALF_OPACITY;
1098     copy.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
1099     QCOMPAREui(p16f1.red, 10000);
1100     QCOMPAREui(p16f1.green, 15000);
1101     QCOMPAREui(p16f1.blue, 20000);
1102     QCOMPAREui(p16f1.alpha, FULL_OPACITY);
1103 
1104     // Test no mask, full opacity, half-transparent src
1105     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = HALF_OPACITY;
1106     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = FULL_OPACITY;
1107     copy.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
1108     QCOMPAREui(p16f1.red, 10000);
1109     QCOMPAREui(p16f1.green, 15000);
1110     QCOMPAREui(p16f1.blue, 20000);
1111     QCOMPAREui(p16f1.alpha, HALF_OPACITY);
1112 
1113     // Test no mask, full opacity, half-transparent src
1114     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = HALF_OPACITY;
1115     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = HALF_OPACITY;
1116     copy.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
1117     QCOMPAREui(p16f1.red, 10000);
1118     QCOMPAREui(p16f1.green, 15000);
1119     QCOMPAREui(p16f1.blue, 20000);
1120     QCOMPAREui(p16f1.alpha, HALF_OPACITY);
1121 
1122     // Test no mask, full opacity, quarter-transparent src, half-transparent dst
1123     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = QUARTER_OPACITY;
1124     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = HALF_OPACITY;
1125     copy.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
1126     QCOMPAREui(p16f1.red, 10000);
1127     QCOMPAREui(p16f1.green, 15000);
1128     QCOMPAREui(p16f1.blue, 20000);
1129     QCOMPAREui(p16f1.alpha, QUARTER_OPACITY);
1130 
1131     // Test no mask, full opacity, quarter-transparent dst, half-transparent src
1132     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = HALF_OPACITY;
1133     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = QUARTER_OPACITY;
1134     copy.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 255);
1135     QCOMPAREui(p16f1.red, 10000);
1136     QCOMPAREui(p16f1.green, 15000);
1137     QCOMPAREui(p16f1.blue, 20000);
1138     QCOMPAREui(p16f1.alpha, HALF_OPACITY);
1139 
1140     // Test no mask, half opacity, quarter-transparent dst, half-transparent src
1141     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = HALF_OPACITY;
1142     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = QUARTER_OPACITY;
1143     copy.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, 0, 0, 1, 1, 127);
1144     QCOMPAREui(p16f1.red, 12510);
1145     QCOMPAREui(p16f1.green, 7972);
1146     QCOMPAREui(p16f1.blue, 17992);
1147     QCOMPAREui(p16f1.alpha, 24542);
1148 
1149     // Test mask, half opacity, quarter-transparent dst, half-transparent src
1150     p16f.red = 10000; p16f.green = 15000; p16f.blue = 20000; p16f.alpha = HALF_OPACITY;
1151     p16f1.red = 15000; p16f1.green = 1000; p16f1.blue = 16000; p16f1.alpha = QUARTER_OPACITY;
1152     copy.composite(p16fPtr1, KoBgrU16Traits::pixelSize, p16fPtr, KoBgrU16Traits::pixelSize, &mask, 0, 1, 1, 127);
1153     QCOMPAREui(p16f1.red, 13760);
1154     QCOMPAREui(p16f1.green, 4472);
1155     QCOMPAREui(p16f1.blue, 16992);
1156     QCOMPAREui(p16f1.alpha, 20447);
1157 }
1158 
testCompositeCopy()1159 void TestKoCompositeOps::testCompositeCopy()
1160 {
1161     const KoColorSpace *cs = KoColorSpaceRegistry::instance()->rgb8();
1162     const KoCompositeOp *copy = cs->compositeOp(COMPOSITE_COPY);
1163 
1164     KoColor black(Qt::black, cs);
1165     KoColor white(Qt::white, cs);
1166     KoColor opaque(QColor(0, 0, 0, 0), cs);
1167 
1168     int w = 512;
1169     int h = 512;
1170 
1171     int pixelCount = w * h;
1172     quint32 pixelSize = cs->pixelSize();
1173     // dst
1174     quint8 *layer = new quint8[pixelCount * pixelSize];
1175     quint8 *iter = layer;
1176     for (int i = 0; i < pixelCount; i++) {
1177         memcpy(iter, white.data(), pixelSize);
1178         iter += pixelSize;
1179     }
1180 
1181     // full white image
1182     //cs->convertToQImage(layer, w, h, 0,KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::internalConversionFlags()).save("0dst.png");
1183 
1184     // src
1185     quint8 *dab = new quint8[pixelCount * pixelSize];
1186     iter = dab;
1187     for (int i = 0; i < pixelCount; i++) {
1188         memcpy(iter, black.data(), pixelSize);
1189         iter += pixelSize;
1190     }
1191 
1192     // full black image
1193     //cs->convertToQImage(dab, w, h, 0,KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::internalConversionFlags()).save("1src.png");
1194 
1195     // selection
1196     quint32 selectionPixelSize = KoColorSpaceRegistry::instance()->alpha8()->pixelSize();
1197     quint8 *selection = new quint8[pixelCount * selectionPixelSize];
1198     iter = selection;
1199     for (int height = 0; height < h; height++) {
1200         for (int width = 0; width < w; width++) {
1201             if ((height > 128) && (height < 256) && (width > 128) && (width < 256)) {
1202                 *iter = 255;
1203             } else {
1204                 *iter = 0;
1205             }
1206             iter += selectionPixelSize;
1207         }
1208     }
1209 
1210     // white rectangle at 128,128
1211     //KoColorSpaceRegistry::instance()->alpha8()->convertToQImage(selection, w, h, 0, KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::internalConversionFlags()).save("1mask.png");
1212 
1213     copy->composite(layer, w * pixelSize,
1214                     dab, w * pixelSize,
1215                     0, 0,
1216                     h, w,
1217                     255,
1218                     QBitArray());
1219 
1220     // full black image
1221     //cs->convertToQImage(layer, w, h, 0,KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::internalConversionFlags()).save("2result.png");
1222 
1223     copy->composite(layer, w * pixelSize,
1224                     opaque.data(), 0,
1225                     0, 0,
1226                     h, w,
1227                     255,
1228                     QBitArray()
1229                    );
1230 
1231     // full opaque image
1232     //cs->convertToQImage(layer, w, h, 0,KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::internalConversionFlags()).save("3result.png");
1233 
1234     copy->composite(layer, w * pixelSize,
1235                     dab, w * pixelSize,
1236                     selection, w * selectionPixelSize,
1237                     h, w,
1238                     255,
1239                     QBitArray()
1240                    );
1241 
1242     // black rectangle on opaque background
1243     QImage result = cs->convertToQImage(layer, w, h, 0, KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::internalConversionFlags());
1244     QImage expectedResult(QString(FILES_DATA_DIR) + QDir::separator() + "CopyWithSelectionExpectedResult.png");
1245 
1246     bool testOk = (result == expectedResult);
1247     if (!testOk) {
1248         qDebug() << "Saving the result";
1249         result.save("CopyWithSelection.png");
1250     }
1251 
1252     QVERIFY2(testOk, "Images are not equal");
1253 
1254     copy->composite(layer, w * pixelSize,
1255                     white.data(), 0,
1256                     selection, w * selectionPixelSize,
1257                     h, w,
1258                     255,
1259                     QBitArray());
1260 
1261     result = cs->convertToQImage(layer, w, h, 0, KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::internalConversionFlags());
1262     expectedResult = QImage(QString(FILES_DATA_DIR) + QDir::separator() + "CopySingleWithSelectionExpectedResult.png");
1263 
1264     testOk = (result == expectedResult);
1265     if (!testOk) {
1266         qDebug() << expectedResult.size() << result.size();
1267         for (int row = 0; row < expectedResult.size().height(); ++row) {
1268             for (int col = 0; col < expectedResult.size().width(); ++ col) {
1269                 QRgb res = result.pixel(col, row);
1270                 QRgb exp = expectedResult.pixel(col, row);
1271                 if (res != exp) {
1272                     qDebug() << "wrong pixel:" << col << "," << row
1273                              << "result:" << qRed(res) << qGreen(res) << qBlue(res) << qAlpha(res)
1274                              << "expected" << qRed(exp) << qGreen(exp) << qBlue(exp) << qAlpha(exp);
1275                 }
1276             }
1277         }
1278         expectedResult.save("expected result.png");
1279         result.save("CopySingleWithSelection.png");
1280         QFAIL("Images with single pixel and selection are not equal");
1281 
1282     }
1283 
1284 }
1285 
1286 QTEST_GUILESS_MAIN(TestKoCompositeOps)
1287