a069e79b337ada142bb4342be7c73a7e701b59cc
[blender.git] / source / blender / imbuf / intern / rectop.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
17  * All rights reserved.
18  * allocimbuf.c
19  */
20
21 /** \file
22  * \ingroup imbuf
23  */
24
25 #include <stdlib.h>
26
27 #include "BLI_utildefines.h"
28 #include "BLI_math_base.h"
29 #include "BLI_math_color.h"
30 #include "BLI_math_color_blend.h"
31 #include "BLI_math_vector.h"
32
33 #include "IMB_imbuf_types.h"
34 #include "IMB_imbuf.h"
35
36 #include "IMB_colormanagement.h"
37
38 void IMB_blend_color_byte(unsigned char dst[4],
39                           unsigned char src1[4],
40                           unsigned char src2[4],
41                           IMB_BlendMode mode)
42 {
43   switch (mode) {
44     case IMB_BLEND_MIX:
45       blend_color_mix_byte(dst, src1, src2);
46       break;
47     case IMB_BLEND_ADD:
48       blend_color_add_byte(dst, src1, src2);
49       break;
50     case IMB_BLEND_SUB:
51       blend_color_sub_byte(dst, src1, src2);
52       break;
53     case IMB_BLEND_MUL:
54       blend_color_mul_byte(dst, src1, src2);
55       break;
56     case IMB_BLEND_LIGHTEN:
57       blend_color_lighten_byte(dst, src1, src2);
58       break;
59     case IMB_BLEND_DARKEN:
60       blend_color_darken_byte(dst, src1, src2);
61       break;
62     case IMB_BLEND_ERASE_ALPHA:
63       blend_color_erase_alpha_byte(dst, src1, src2);
64       break;
65     case IMB_BLEND_ADD_ALPHA:
66       blend_color_add_alpha_byte(dst, src1, src2);
67       break;
68     case IMB_BLEND_OVERLAY:
69       blend_color_overlay_byte(dst, src1, src2);
70       break;
71     case IMB_BLEND_HARDLIGHT:
72       blend_color_hardlight_byte(dst, src1, src2);
73       break;
74     case IMB_BLEND_COLORBURN:
75       blend_color_burn_byte(dst, src1, src2);
76       break;
77     case IMB_BLEND_LINEARBURN:
78       blend_color_linearburn_byte(dst, src1, src2);
79       break;
80     case IMB_BLEND_COLORDODGE:
81       blend_color_dodge_byte(dst, src1, src2);
82       break;
83     case IMB_BLEND_SCREEN:
84       blend_color_screen_byte(dst, src1, src2);
85       break;
86     case IMB_BLEND_SOFTLIGHT:
87       blend_color_softlight_byte(dst, src1, src2);
88       break;
89     case IMB_BLEND_PINLIGHT:
90       blend_color_pinlight_byte(dst, src1, src2);
91       break;
92     case IMB_BLEND_LINEARLIGHT:
93       blend_color_linearlight_byte(dst, src1, src2);
94       break;
95     case IMB_BLEND_VIVIDLIGHT:
96       blend_color_vividlight_byte(dst, src1, src2);
97       break;
98     case IMB_BLEND_DIFFERENCE:
99       blend_color_difference_byte(dst, src1, src2);
100       break;
101     case IMB_BLEND_EXCLUSION:
102       blend_color_exclusion_byte(dst, src1, src2);
103       break;
104     case IMB_BLEND_COLOR:
105       blend_color_color_byte(dst, src1, src2);
106       break;
107     case IMB_BLEND_HUE:
108       blend_color_hue_byte(dst, src1, src2);
109       break;
110     case IMB_BLEND_SATURATION:
111       blend_color_saturation_byte(dst, src1, src2);
112       break;
113     case IMB_BLEND_LUMINOSITY:
114       blend_color_luminosity_byte(dst, src1, src2);
115       break;
116
117     default:
118       dst[0] = src1[0];
119       dst[1] = src1[1];
120       dst[2] = src1[2];
121       dst[3] = src1[3];
122       break;
123   }
124 }
125
126 void IMB_blend_color_float(float dst[4], float src1[4], float src2[4], IMB_BlendMode mode)
127 {
128   switch (mode) {
129     case IMB_BLEND_MIX:
130       blend_color_mix_float(dst, src1, src2);
131       break;
132     case IMB_BLEND_ADD:
133       blend_color_add_float(dst, src1, src2);
134       break;
135     case IMB_BLEND_SUB:
136       blend_color_sub_float(dst, src1, src2);
137       break;
138     case IMB_BLEND_MUL:
139       blend_color_mul_float(dst, src1, src2);
140       break;
141     case IMB_BLEND_LIGHTEN:
142       blend_color_lighten_float(dst, src1, src2);
143       break;
144     case IMB_BLEND_DARKEN:
145       blend_color_darken_float(dst, src1, src2);
146       break;
147     case IMB_BLEND_ERASE_ALPHA:
148       blend_color_erase_alpha_float(dst, src1, src2);
149       break;
150     case IMB_BLEND_ADD_ALPHA:
151       blend_color_add_alpha_float(dst, src1, src2);
152       break;
153     case IMB_BLEND_OVERLAY:
154       blend_color_overlay_float(dst, src1, src2);
155       break;
156     case IMB_BLEND_HARDLIGHT:
157       blend_color_hardlight_float(dst, src1, src2);
158       break;
159     case IMB_BLEND_COLORBURN:
160       blend_color_burn_float(dst, src1, src2);
161       break;
162     case IMB_BLEND_LINEARBURN:
163       blend_color_linearburn_float(dst, src1, src2);
164       break;
165     case IMB_BLEND_COLORDODGE:
166       blend_color_dodge_float(dst, src1, src2);
167       break;
168     case IMB_BLEND_SCREEN:
169       blend_color_screen_float(dst, src1, src2);
170       break;
171     case IMB_BLEND_SOFTLIGHT:
172       blend_color_softlight_float(dst, src1, src2);
173       break;
174     case IMB_BLEND_PINLIGHT:
175       blend_color_pinlight_float(dst, src1, src2);
176       break;
177     case IMB_BLEND_LINEARLIGHT:
178       blend_color_linearlight_float(dst, src1, src2);
179       break;
180     case IMB_BLEND_VIVIDLIGHT:
181       blend_color_vividlight_float(dst, src1, src2);
182       break;
183     case IMB_BLEND_DIFFERENCE:
184       blend_color_difference_float(dst, src1, src2);
185       break;
186     case IMB_BLEND_EXCLUSION:
187       blend_color_exclusion_float(dst, src1, src2);
188       break;
189     case IMB_BLEND_COLOR:
190       blend_color_color_float(dst, src1, src2);
191       break;
192     case IMB_BLEND_HUE:
193       blend_color_hue_float(dst, src1, src2);
194       break;
195     case IMB_BLEND_SATURATION:
196       blend_color_saturation_float(dst, src1, src2);
197       break;
198     case IMB_BLEND_LUMINOSITY:
199       blend_color_luminosity_float(dst, src1, src2);
200       break;
201     default:
202       dst[0] = src1[0];
203       dst[1] = src1[1];
204       dst[2] = src1[2];
205       dst[3] = src1[3];
206       break;
207   }
208 }
209
210 /* clipping */
211
212 void IMB_rectclip(ImBuf *dbuf,
213                   ImBuf *sbuf,
214                   int *destx,
215                   int *desty,
216                   int *srcx,
217                   int *srcy,
218                   int *width,
219                   int *height)
220 {
221   int tmp;
222
223   if (dbuf == NULL)
224     return;
225
226   if (*destx < 0) {
227     *srcx -= *destx;
228     *width += *destx;
229     *destx = 0;
230   }
231   if (*srcx < 0) {
232     *destx -= *srcx;
233     *width += *srcx;
234     *srcx = 0;
235   }
236   if (*desty < 0) {
237     *srcy -= *desty;
238     *height += *desty;
239     *desty = 0;
240   }
241   if (*srcy < 0) {
242     *desty -= *srcy;
243     *height += *srcy;
244     *srcy = 0;
245   }
246
247   tmp = dbuf->x - *destx;
248   if (*width > tmp)
249     *width = tmp;
250   tmp = dbuf->y - *desty;
251   if (*height > tmp)
252     *height = tmp;
253
254   if (sbuf) {
255     tmp = sbuf->x - *srcx;
256     if (*width > tmp)
257       *width = tmp;
258     tmp = sbuf->y - *srcy;
259     if (*height > tmp)
260       *height = tmp;
261   }
262
263   if ((*height <= 0) || (*width <= 0)) {
264     *width = 0;
265     *height = 0;
266   }
267 }
268
269 static void imb_rectclip3(ImBuf *dbuf,
270                           ImBuf *obuf,
271                           ImBuf *sbuf,
272                           int *destx,
273                           int *desty,
274                           int *origx,
275                           int *origy,
276                           int *srcx,
277                           int *srcy,
278                           int *width,
279                           int *height)
280 {
281   int tmp;
282
283   if (dbuf == NULL)
284     return;
285
286   if (*destx < 0) {
287     *srcx -= *destx;
288     *origx -= *destx;
289     *width += *destx;
290     *destx = 0;
291   }
292   if (*origx < 0) {
293     *destx -= *origx;
294     *srcx -= *origx;
295     *width += *origx;
296     *origx = 0;
297   }
298   if (*srcx < 0) {
299     *destx -= *srcx;
300     *origx -= *srcx;
301     *width += *srcx;
302     *srcx = 0;
303   }
304
305   if (*desty < 0) {
306     *srcy -= *desty;
307     *origy -= *desty;
308     *height += *desty;
309     *desty = 0;
310   }
311   if (*origy < 0) {
312     *desty -= *origy;
313     *srcy -= *origy;
314     *height += *origy;
315     *origy = 0;
316   }
317   if (*srcy < 0) {
318     *desty -= *srcy;
319     *origy -= *srcy;
320     *height += *srcy;
321     *srcy = 0;
322   }
323
324   tmp = dbuf->x - *destx;
325   if (*width > tmp)
326     *width = tmp;
327   tmp = dbuf->y - *desty;
328   if (*height > tmp)
329     *height = tmp;
330
331   if (obuf) {
332     tmp = obuf->x - *origx;
333     if (*width > tmp)
334       *width = tmp;
335     tmp = obuf->y - *origy;
336     if (*height > tmp)
337       *height = tmp;
338   }
339
340   if (sbuf) {
341     tmp = sbuf->x - *srcx;
342     if (*width > tmp)
343       *width = tmp;
344     tmp = sbuf->y - *srcy;
345     if (*height > tmp)
346       *height = tmp;
347   }
348
349   if ((*height <= 0) || (*width <= 0)) {
350     *width = 0;
351     *height = 0;
352   }
353 }
354
355 /* copy and blend */
356
357 void IMB_rectcpy(
358     ImBuf *dbuf, ImBuf *sbuf, int destx, int desty, int srcx, int srcy, int width, int height)
359 {
360   IMB_rectblend(dbuf,
361                 dbuf,
362                 sbuf,
363                 NULL,
364                 NULL,
365                 NULL,
366                 0,
367                 destx,
368                 desty,
369                 destx,
370                 desty,
371                 srcx,
372                 srcy,
373                 width,
374                 height,
375                 IMB_BLEND_COPY,
376                 false);
377 }
378
379 typedef void (*IMB_blend_func)(unsigned char *dst,
380                                const unsigned char *src1,
381                                const unsigned char *src2);
382 typedef void (*IMB_blend_func_float)(float *dst, const float *src1, const float *src2);
383
384 void IMB_rectblend(ImBuf *dbuf,
385                    ImBuf *obuf,
386                    ImBuf *sbuf,
387                    unsigned short *dmask,
388                    unsigned short *curvemask,
389                    unsigned short *texmask,
390                    float mask_max,
391                    int destx,
392                    int desty,
393                    int origx,
394                    int origy,
395                    int srcx,
396                    int srcy,
397                    int width,
398                    int height,
399                    IMB_BlendMode mode,
400                    bool accumulate)
401 {
402   unsigned int *drect = NULL, *orect = NULL, *srect = NULL, *dr, * or, *sr;
403   float *drectf = NULL, *orectf = NULL, *srectf = NULL, *drf, *orf, *srf;
404   unsigned short *cmaskrect = curvemask, *cmr;
405   unsigned short *dmaskrect = dmask, *dmr;
406   unsigned short *texmaskrect = texmask, *tmr;
407   int do_float, do_char, srcskip, destskip, origskip, x;
408   IMB_blend_func func = NULL;
409   IMB_blend_func_float func_float = NULL;
410
411   if (dbuf == NULL || obuf == NULL)
412     return;
413
414   imb_rectclip3(dbuf, obuf, sbuf, &destx, &desty, &origx, &origy, &srcx, &srcy, &width, &height);
415
416   if (width == 0 || height == 0)
417     return;
418   if (sbuf && sbuf->channels != 4)
419     return;
420   if (dbuf->channels != 4)
421     return;
422
423   do_char = (sbuf && sbuf->rect && dbuf->rect && obuf->rect);
424   do_float = (sbuf && sbuf->rect_float && dbuf->rect_float && obuf->rect_float);
425
426   if (do_char) {
427     drect = dbuf->rect + ((size_t)desty) * dbuf->x + destx;
428     orect = obuf->rect + ((size_t)origy) * obuf->x + origx;
429   }
430   if (do_float) {
431     drectf = dbuf->rect_float + (((size_t)desty) * dbuf->x + destx) * 4;
432     orectf = obuf->rect_float + (((size_t)origy) * obuf->x + origx) * 4;
433   }
434
435   if (dmaskrect)
436     dmaskrect += ((size_t)origy) * obuf->x + origx;
437
438   destskip = dbuf->x;
439   origskip = obuf->x;
440
441   if (sbuf) {
442     if (do_char)
443       srect = sbuf->rect + ((size_t)srcy) * sbuf->x + srcx;
444     if (do_float)
445       srectf = sbuf->rect_float + (((size_t)srcy) * sbuf->x + srcx) * 4;
446     srcskip = sbuf->x;
447
448     if (cmaskrect)
449       cmaskrect += ((size_t)srcy) * sbuf->x + srcx;
450
451     if (texmaskrect)
452       texmaskrect += ((size_t)srcy) * sbuf->x + srcx;
453   }
454   else {
455     srect = drect;
456     srectf = drectf;
457     srcskip = destskip;
458   }
459
460   if (mode == IMB_BLEND_COPY) {
461     /* copy */
462     for (; height > 0; height--) {
463       if (do_char) {
464         memcpy(drect, srect, width * sizeof(int));
465         drect += destskip;
466         srect += srcskip;
467       }
468
469       if (do_float) {
470         memcpy(drectf, srectf, width * sizeof(float) * 4);
471         drectf += destskip * 4;
472         srectf += srcskip * 4;
473       }
474     }
475   }
476   else if (mode == IMB_BLEND_COPY_RGB) {
477     /* copy rgb only */
478     for (; height > 0; height--) {
479       if (do_char) {
480         dr = drect;
481         sr = srect;
482         for (x = width; x > 0; x--, dr++, sr++) {
483           ((char *)dr)[0] = ((char *)sr)[0];
484           ((char *)dr)[1] = ((char *)sr)[1];
485           ((char *)dr)[2] = ((char *)sr)[2];
486         }
487         drect += destskip;
488         srect += srcskip;
489       }
490
491       if (do_float) {
492         drf = drectf;
493         srf = srectf;
494         for (x = width; x > 0; x--, drf += 4, srf += 4) {
495           float map_alpha = (srf[3] == 0.0f) ? drf[3] : drf[3] / srf[3];
496
497           drf[0] = srf[0] * map_alpha;
498           drf[1] = srf[1] * map_alpha;
499           drf[2] = srf[2] * map_alpha;
500         }
501         drectf += destskip * 4;
502         srectf += srcskip * 4;
503       }
504     }
505   }
506   else if (mode == IMB_BLEND_COPY_ALPHA) {
507     /* copy alpha only */
508     for (; height > 0; height--) {
509       if (do_char) {
510         dr = drect;
511         sr = srect;
512         for (x = width; x > 0; x--, dr++, sr++)
513           ((char *)dr)[3] = ((char *)sr)[3];
514         drect += destskip;
515         srect += srcskip;
516       }
517
518       if (do_float) {
519         drf = drectf;
520         srf = srectf;
521         for (x = width; x > 0; x--, drf += 4, srf += 4)
522           drf[3] = srf[3];
523         drectf += destskip * 4;
524         srectf += srcskip * 4;
525       }
526     }
527   }
528   else {
529     switch (mode) {
530       case IMB_BLEND_MIX:
531       case IMB_BLEND_INTERPOLATE:
532         func = blend_color_mix_byte;
533         func_float = blend_color_mix_float;
534         break;
535       case IMB_BLEND_ADD:
536         func = blend_color_add_byte;
537         func_float = blend_color_add_float;
538         break;
539       case IMB_BLEND_SUB:
540         func = blend_color_sub_byte;
541         func_float = blend_color_sub_float;
542         break;
543       case IMB_BLEND_MUL:
544         func = blend_color_mul_byte;
545         func_float = blend_color_mul_float;
546         break;
547       case IMB_BLEND_LIGHTEN:
548         func = blend_color_lighten_byte;
549         func_float = blend_color_lighten_float;
550         break;
551       case IMB_BLEND_DARKEN:
552         func = blend_color_darken_byte;
553         func_float = blend_color_darken_float;
554         break;
555       case IMB_BLEND_ERASE_ALPHA:
556         func = blend_color_erase_alpha_byte;
557         func_float = blend_color_erase_alpha_float;
558         break;
559       case IMB_BLEND_ADD_ALPHA:
560         func = blend_color_add_alpha_byte;
561         func_float = blend_color_add_alpha_float;
562         break;
563       case IMB_BLEND_OVERLAY:
564         func = blend_color_overlay_byte;
565         func_float = blend_color_overlay_float;
566         break;
567       case IMB_BLEND_HARDLIGHT:
568         func = blend_color_hardlight_byte;
569         func_float = blend_color_hardlight_float;
570         break;
571       case IMB_BLEND_COLORBURN:
572         func = blend_color_burn_byte;
573         func_float = blend_color_burn_float;
574         break;
575       case IMB_BLEND_LINEARBURN:
576         func = blend_color_linearburn_byte;
577         func_float = blend_color_linearburn_float;
578         break;
579       case IMB_BLEND_COLORDODGE:
580         func = blend_color_dodge_byte;
581         func_float = blend_color_dodge_float;
582         break;
583       case IMB_BLEND_SCREEN:
584         func = blend_color_screen_byte;
585         func_float = blend_color_screen_float;
586         break;
587       case IMB_BLEND_SOFTLIGHT:
588         func = blend_color_softlight_byte;
589         func_float = blend_color_softlight_float;
590         break;
591       case IMB_BLEND_PINLIGHT:
592         func = blend_color_pinlight_byte;
593         func_float = blend_color_pinlight_float;
594         break;
595       case IMB_BLEND_LINEARLIGHT:
596         func = blend_color_linearlight_byte;
597         func_float = blend_color_linearlight_float;
598         break;
599       case IMB_BLEND_VIVIDLIGHT:
600         func = blend_color_vividlight_byte;
601         func_float = blend_color_vividlight_float;
602         break;
603       case IMB_BLEND_DIFFERENCE:
604         func = blend_color_difference_byte;
605         func_float = blend_color_difference_float;
606         break;
607       case IMB_BLEND_EXCLUSION:
608         func = blend_color_exclusion_byte;
609         func_float = blend_color_exclusion_float;
610         break;
611       case IMB_BLEND_COLOR:
612         func = blend_color_color_byte;
613         func_float = blend_color_color_float;
614         break;
615       case IMB_BLEND_HUE:
616         func = blend_color_hue_byte;
617         func_float = blend_color_hue_float;
618         break;
619       case IMB_BLEND_SATURATION:
620         func = blend_color_saturation_byte;
621         func_float = blend_color_saturation_float;
622         break;
623       case IMB_BLEND_LUMINOSITY:
624         func = blend_color_luminosity_byte;
625         func_float = blend_color_luminosity_float;
626         break;
627       default:
628         break;
629     }
630
631     /* blend */
632     for (; height > 0; height--) {
633       if (do_char) {
634         dr = drect;
635         or = orect;
636         sr = srect;
637
638         if (cmaskrect) {
639           /* mask accumulation for painting */
640           cmr = cmaskrect;
641           tmr = texmaskrect;
642
643           /* destination mask present, do max alpha masking */
644           if (dmaskrect) {
645             dmr = dmaskrect;
646             for (x = width; x > 0; x--, dr++, or ++, sr++, dmr++, cmr++) {
647               unsigned char *src = (unsigned char *)sr;
648               float mask_lim = mask_max * (*cmr);
649
650               if (texmaskrect)
651                 mask_lim *= ((*tmr++) / 65535.0f);
652
653               if (src[3] && mask_lim) {
654                 float mask;
655
656                 if (accumulate)
657                   mask = *dmr + mask_lim;
658                 else
659                   mask = *dmr + mask_lim - (*dmr * (*cmr / 65535.0f));
660
661                 mask = min_ff(mask, 65535.0);
662
663                 if (mask > *dmr) {
664                   unsigned char mask_src[4];
665
666                   *dmr = mask;
667
668                   mask_src[0] = src[0];
669                   mask_src[1] = src[1];
670                   mask_src[2] = src[2];
671
672                   if (mode == IMB_BLEND_INTERPOLATE) {
673                     mask_src[3] = src[3];
674                     blend_color_interpolate_byte(
675                         (unsigned char *)dr, (unsigned char *) or, mask_src, mask / 65535.0f);
676                   }
677                   else {
678                     mask_src[3] = divide_round_i(src[3] * mask, 65535);
679                     func((unsigned char *)dr, (unsigned char *) or, mask_src);
680                   }
681                 }
682               }
683             }
684             dmaskrect += origskip;
685           }
686           /* no destination mask buffer, do regular blend with masktexture if present */
687           else {
688             for (x = width; x > 0; x--, dr++, or ++, sr++, cmr++) {
689               unsigned char *src = (unsigned char *)sr;
690               float mask = (float)mask_max * ((float)(*cmr));
691
692               if (texmaskrect)
693                 mask *= ((float)(*tmr++) / 65535.0f);
694
695               mask = min_ff(mask, 65535.0);
696
697               if (src[3] && (mask > 0.0f)) {
698                 unsigned char mask_src[4];
699
700                 mask_src[0] = src[0];
701                 mask_src[1] = src[1];
702                 mask_src[2] = src[2];
703
704                 if (mode == IMB_BLEND_INTERPOLATE) {
705                   mask_src[3] = src[3];
706                   blend_color_interpolate_byte(
707                       (unsigned char *)dr, (unsigned char *) or, mask_src, mask / 65535.0f);
708                 }
709                 else {
710                   mask_src[3] = divide_round_i(src[3] * mask, 65535);
711                   func((unsigned char *)dr, (unsigned char *) or, mask_src);
712                 }
713               }
714             }
715           }
716
717           cmaskrect += srcskip;
718           if (texmaskrect)
719             texmaskrect += srcskip;
720         }
721         else {
722           /* regular blending */
723           for (x = width; x > 0; x--, dr++, or ++, sr++) {
724             if (((unsigned char *)sr)[3])
725               func((unsigned char *)dr, (unsigned char *) or, (unsigned char *)sr);
726           }
727         }
728
729         drect += destskip;
730         orect += origskip;
731         srect += srcskip;
732       }
733
734       if (do_float) {
735         drf = drectf;
736         orf = orectf;
737         srf = srectf;
738
739         if (cmaskrect) {
740           /* mask accumulation for painting */
741           cmr = cmaskrect;
742           tmr = texmaskrect;
743
744           /* destination mask present, do max alpha masking */
745           if (dmaskrect) {
746             dmr = dmaskrect;
747             for (x = width; x > 0; x--, drf += 4, orf += 4, srf += 4, dmr++, cmr++) {
748               float mask_lim = mask_max * (*cmr);
749
750               if (texmaskrect)
751                 mask_lim *= ((*tmr++) / 65535.0f);
752
753               if (srf[3] && mask_lim) {
754                 float mask;
755
756                 if (accumulate)
757                   mask = min_ff(*dmr + mask_lim, 65535.0);
758                 else
759                   mask = *dmr + mask_lim - (*dmr * (*cmr / 65535.0f));
760
761                 mask = min_ff(mask, 65535.0);
762
763                 if (mask > *dmr) {
764                   *dmr = mask;
765
766                   if (mode == IMB_BLEND_INTERPOLATE) {
767                     blend_color_interpolate_float(drf, orf, srf, mask / 65535.0f);
768                   }
769                   else {
770                     float mask_srf[4];
771                     mul_v4_v4fl(mask_srf, srf, mask / 65535.0f);
772                     func_float(drf, orf, mask_srf);
773                   }
774                 }
775               }
776             }
777             dmaskrect += origskip;
778           }
779           /* no destination mask buffer, do regular blend with masktexture if present */
780           else {
781             for (x = width; x > 0; x--, drf += 4, orf += 4, srf += 4, cmr++) {
782               float mask = (float)mask_max * ((float)(*cmr));
783
784               if (texmaskrect)
785                 mask *= ((float)(*tmr++) / 65535.0f);
786
787               mask = min_ff(mask, 65535.0);
788
789               if (srf[3] && (mask > 0.0f)) {
790                 if (mode == IMB_BLEND_INTERPOLATE) {
791                   blend_color_interpolate_float(drf, orf, srf, mask / 65535.0f);
792                 }
793                 else {
794                   float mask_srf[4];
795                   mul_v4_v4fl(mask_srf, srf, mask / 65535.0f);
796                   func_float(drf, orf, mask_srf);
797                 }
798               }
799             }
800           }
801
802           cmaskrect += srcskip;
803           if (texmaskrect)
804             texmaskrect += srcskip;
805         }
806         else {
807           /* regular blending */
808           for (x = width; x > 0; x--, drf += 4, orf += 4, srf += 4) {
809             if (srf[3] != 0)
810               func_float(drf, orf, srf);
811           }
812         }
813
814         drectf += destskip * 4;
815         orectf += origskip * 4;
816         srectf += srcskip * 4;
817       }
818     }
819   }
820 }
821
822 typedef struct RectBlendThreadData {
823   ImBuf *dbuf, *obuf, *sbuf;
824   unsigned short *dmask, *curvemask, *texmask;
825   float mask_max;
826   int destx, desty, origx, origy;
827   int srcx, srcy, width;
828   IMB_BlendMode mode;
829   bool accumulate;
830 } RectBlendThreadData;
831
832 static void rectblend_thread_do(void *data_v, int start_scanline, int num_scanlines)
833 {
834   RectBlendThreadData *data = (RectBlendThreadData *)data_v;
835   IMB_rectblend(data->dbuf,
836                 data->obuf,
837                 data->sbuf,
838                 data->dmask,
839                 data->curvemask,
840                 data->texmask,
841                 data->mask_max,
842                 data->destx,
843                 data->desty + start_scanline,
844                 data->origx,
845                 data->origy + start_scanline,
846                 data->srcx,
847                 data->srcy + start_scanline,
848                 data->width,
849                 num_scanlines,
850                 data->mode,
851                 data->accumulate);
852 }
853
854 void IMB_rectblend_threaded(ImBuf *dbuf,
855                             ImBuf *obuf,
856                             ImBuf *sbuf,
857                             unsigned short *dmask,
858                             unsigned short *curvemask,
859                             unsigned short *texmask,
860                             float mask_max,
861                             int destx,
862                             int desty,
863                             int origx,
864                             int origy,
865                             int srcx,
866                             int srcy,
867                             int width,
868                             int height,
869                             IMB_BlendMode mode,
870                             bool accumulate)
871 {
872   if (((size_t)width) * height < 64 * 64) {
873     IMB_rectblend(dbuf,
874                   obuf,
875                   sbuf,
876                   dmask,
877                   curvemask,
878                   texmask,
879                   mask_max,
880                   destx,
881                   desty,
882                   origx,
883                   origy,
884                   srcx,
885                   srcy,
886                   width,
887                   height,
888                   mode,
889                   accumulate);
890   }
891   else {
892     RectBlendThreadData data;
893     data.dbuf = dbuf;
894     data.obuf = obuf;
895     data.sbuf = sbuf;
896     data.dmask = dmask;
897     data.curvemask = curvemask;
898     data.texmask = texmask;
899     data.mask_max = mask_max;
900     data.destx = destx;
901     data.desty = desty;
902     data.origx = origx;
903     data.origy = origy;
904     data.srcx = srcx;
905     data.srcy = srcy;
906     data.width = width;
907     data.mode = mode;
908     data.accumulate = accumulate;
909     IMB_processor_apply_threaded_scanlines(height, rectblend_thread_do, &data);
910   }
911 }
912
913 /* fill */
914
915 void IMB_rectfill(ImBuf *drect, const float col[4])
916 {
917   int num;
918
919   if (drect->rect) {
920     unsigned int *rrect = drect->rect;
921     char ccol[4];
922
923     ccol[0] = (int)(col[0] * 255);
924     ccol[1] = (int)(col[1] * 255);
925     ccol[2] = (int)(col[2] * 255);
926     ccol[3] = (int)(col[3] * 255);
927
928     num = drect->x * drect->y;
929     for (; num > 0; num--)
930       *rrect++ = *((unsigned int *)ccol);
931   }
932
933   if (drect->rect_float) {
934     float *rrectf = drect->rect_float;
935
936     num = drect->x * drect->y;
937     for (; num > 0; num--) {
938       *rrectf++ = col[0];
939       *rrectf++ = col[1];
940       *rrectf++ = col[2];
941       *rrectf++ = col[3];
942     }
943   }
944 }
945
946 void buf_rectfill_area(unsigned char *rect,
947                        float *rectf,
948                        int width,
949                        int height,
950                        const float col[4],
951                        struct ColorManagedDisplay *display,
952                        int x1,
953                        int y1,
954                        int x2,
955                        int y2)
956 {
957   int i, j;
958   float a;    /* alpha */
959   float ai;   /* alpha inverted */
960   float aich; /* alpha, inverted, ai/255.0 - Convert char to float at the same time */
961   if ((!rect && !rectf) || (!col) || col[3] == 0.0f)
962     return;
963
964   /* sanity checks for coords */
965   CLAMP(x1, 0, width);
966   CLAMP(x2, 0, width);
967   CLAMP(y1, 0, height);
968   CLAMP(y2, 0, height);
969
970   if (x1 > x2)
971     SWAP(int, x1, x2);
972   if (y1 > y2)
973     SWAP(int, y1, y2);
974   if (x1 == x2 || y1 == y2)
975     return;
976
977   a = col[3];
978   ai = 1 - a;
979   aich = ai / 255.0f;
980
981   if (rect) {
982     unsigned char *pixel;
983     unsigned char chr = 0, chg = 0, chb = 0;
984     float fr = 0, fg = 0, fb = 0;
985
986     const int alphaint = unit_float_to_uchar_clamp(a);
987
988     if (a == 1.0f) {
989       chr = unit_float_to_uchar_clamp(col[0]);
990       chg = unit_float_to_uchar_clamp(col[1]);
991       chb = unit_float_to_uchar_clamp(col[2]);
992     }
993     else {
994       fr = col[0] * a;
995       fg = col[1] * a;
996       fb = col[2] * a;
997     }
998     for (j = 0; j < y2 - y1; j++) {
999       for (i = 0; i < x2 - x1; i++) {
1000         pixel = rect + 4 * (((y1 + j) * width) + (x1 + i));
1001         if (pixel >= rect && pixel < rect + (4 * (width * height))) {
1002           if (a == 1.0f) {
1003             pixel[0] = chr;
1004             pixel[1] = chg;
1005             pixel[2] = chb;
1006             pixel[3] = 255;
1007           }
1008           else {
1009             int alphatest;
1010             pixel[0] = (char)((fr + ((float)pixel[0] * aich)) * 255.0f);
1011             pixel[1] = (char)((fg + ((float)pixel[1] * aich)) * 255.0f);
1012             pixel[2] = (char)((fb + ((float)pixel[2] * aich)) * 255.0f);
1013             pixel[3] = (char)((alphatest = ((int)pixel[3] + alphaint)) < 255 ? alphatest : 255);
1014           }
1015         }
1016       }
1017     }
1018   }
1019
1020   if (rectf) {
1021     float col_conv[4];
1022     float *pixel;
1023
1024     if (display) {
1025       copy_v4_v4(col_conv, col);
1026       IMB_colormanagement_display_to_scene_linear_v3(col_conv, display);
1027     }
1028     else {
1029       srgb_to_linearrgb_v4(col_conv, col);
1030     }
1031
1032     for (j = 0; j < y2 - y1; j++) {
1033       for (i = 0; i < x2 - x1; i++) {
1034         pixel = rectf + 4 * (((y1 + j) * width) + (x1 + i));
1035         if (a == 1.0f) {
1036           pixel[0] = col_conv[0];
1037           pixel[1] = col_conv[1];
1038           pixel[2] = col_conv[2];
1039           pixel[3] = 1.0f;
1040         }
1041         else {
1042           float alphatest;
1043           pixel[0] = (col_conv[0] * a) + (pixel[0] * ai);
1044           pixel[1] = (col_conv[1] * a) + (pixel[1] * ai);
1045           pixel[2] = (col_conv[2] * a) + (pixel[2] * ai);
1046           pixel[3] = (alphatest = (pixel[3] + a)) < 1.0f ? alphatest : 1.0f;
1047         }
1048       }
1049     }
1050   }
1051 }
1052
1053 void IMB_rectfill_area(ImBuf *ibuf,
1054                        const float col[4],
1055                        int x1,
1056                        int y1,
1057                        int x2,
1058                        int y2,
1059                        struct ColorManagedDisplay *display)
1060 {
1061   if (!ibuf)
1062     return;
1063   buf_rectfill_area((unsigned char *)ibuf->rect,
1064                     ibuf->rect_float,
1065                     ibuf->x,
1066                     ibuf->y,
1067                     col,
1068                     display,
1069                     x1,
1070                     y1,
1071                     x2,
1072                     y2);
1073 }
1074
1075 void IMB_rectfill_alpha(ImBuf *ibuf, const float value)
1076 {
1077   int i;
1078
1079   if (ibuf->rect_float && (ibuf->channels == 4)) {
1080     float *fbuf = ibuf->rect_float + 3;
1081     for (i = ibuf->x * ibuf->y; i > 0; i--, fbuf += 4) {
1082       *fbuf = value;
1083     }
1084   }
1085
1086   if (ibuf->rect) {
1087     const unsigned char cvalue = value * 255;
1088     unsigned char *cbuf = ((unsigned char *)ibuf->rect) + 3;
1089     for (i = ibuf->x * ibuf->y; i > 0; i--, cbuf += 4) {
1090       *cbuf = cvalue;
1091     }
1092   }
1093 }