41 using float_m =
typename float_v::batch_bool_type;
49 dataWrapper.read(src, src_c1, src_c2, src_c3, src_alpha);
51 const float_v opacity_norm_vec = [&]() {
54 const float_v uint8MaxRec1(1.0f / 255.0f);
56 o *= mask_vec * uint8MaxRec1;
61 const float_v zeroValue(0.0f);
62 const float_v oneValue(1.0f);
64 const float_m opacity_is_null_mask = opacity_norm_vec == zeroValue;
68 if (xsimd::all(opacity_is_null_mask)) {
70 }
else if (xsimd::all(opacity_norm_vec == oneValue)) {
71 if (xsimd::all(src_alpha == zeroValue)) {
72 dataWrapper.clearPixels(dst);
74 dataWrapper.copyPixels(src, dst);
83 dataWrapper.read(dst, dst_c1, dst_c2, dst_c3, dst_alpha);
85 const float_v newAlpha = dst_alpha + opacity_norm_vec * (src_alpha - dst_alpha);
87 if (xsimd::all(newAlpha == zeroValue)) {
88 dataWrapper.clearPixels(dst);
100 dst_c1 += opacity_norm_vec * (src_c1 - dst_c1);
101 dst_c2 += opacity_norm_vec * (src_c2 - dst_c2);
102 dst_c3 += opacity_norm_vec * (src_c3 - dst_c3);
104 if (!xsimd::all(newAlpha == oneValue)) {
120 dst_c1 = xsimd::select(xsimd::isnan(dst_c1), unitValue, dst_c1);
121 dst_c2 = xsimd::select(xsimd::isnan(dst_c2), unitValue, dst_c2);
122 dst_c3 = xsimd::select(xsimd::isnan(dst_c3), unitValue, dst_c3);
123 dst_c1 = xsimd::min(dst_c1, unitValue);
124 dst_c2 = xsimd::min(dst_c2, unitValue);
125 dst_c3 = xsimd::min(dst_c3, unitValue);
134 pixelRecoverHelper.
recoverPixels(opacity_is_null_mask, dst_c1, dst_c2, dst_c3);
136 dataWrapper.write(dst, dst_c1, dst_c2, dst_c3, newAlpha);
145 const qint32 alpha_pos = 3;
147 const auto *s =
reinterpret_cast<const channels_type*
>(src);
148 auto *d =
reinterpret_cast<channels_type*
>(dst);
150 const channels_type nativeOriginalSrcAlpha = s[alpha_pos];
160 float srcAlpha = nativeOriginalSrcAlpha;
164 const float uint8Rec1 = 1.0f / 255.0f;
165 opacity *= float(*mask) * uint8Rec1;
168 if (opacity == 0.0f) {
170 }
else if (opacity == 1.0f) {
171 if (allChannelsFlag && !alphaLocked) {
172 if (srcAlpha == 0.0f) {
173 KoStreamedMathFunctions::clearPixel<sizeof(Pixel)>(dst);
175 KoStreamedMathFunctions::copyPixel<sizeof(Pixel)>(src, dst);
182 if (channelFlags.at(0)) d[0] = s[0];
183 if (channelFlags.at(1)) d[1] = s[1];
184 if (channelFlags.at(2)) d[2] = s[2];
185 if (!alphaLocked) d[3] = s[3];
198 float dstAlpha = d[alpha_pos];
201 float newAlpha = dstAlpha + opacity * (srcAlpha - dstAlpha);
203 if (newAlpha == 0.0f) {
204 if ((allChannelsFlag && !alphaLocked) || dstAlpha == 0.0f) {
205 KoStreamedMathFunctions::clearPixel<sizeof(Pixel)>(dst);
230 dst_c1 += opacity * (src_c1 - dst_c1);
231 dst_c2 += opacity * (src_c2 - dst_c2);
232 dst_c3 += opacity * (src_c3 - dst_c3);
234 if (newAlpha != 1.0f) {
241 dst_c1 = std::isnan(dst_c1) ? unitValue : dst_c1;
242 dst_c2 = std::isnan(dst_c2) ? unitValue : dst_c2;
243 dst_c3 = std::isnan(dst_c3) ? unitValue : dst_c3;
245 dst_c1 = std::min(dst_c1, unitValue);
246 dst_c2 = std::min(dst_c2, unitValue);
247 dst_c3 = std::min(dst_c3, unitValue);
250 if (allChannelsFlag) {
255 if (dstAlpha != 0.0f || alphaLocked) {