Cleanup: style, use braces for imbuf
[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
227   if (*destx < 0) {
228     *srcx -= *destx;
229     *width += *destx;
230     *destx = 0;
231   }
232   if (*srcx < 0) {
233     *destx -= *srcx;
234     *width += *srcx;
235     *srcx = 0;
236   }
237   if (*desty < 0) {
238     *srcy -= *desty;
239     *height += *desty;
240     *desty = 0;
241   }
242   if (*srcy < 0) {
243     *desty -= *srcy;
244     *height += *srcy;
245     *srcy = 0;
246   }
247
248   tmp = dbuf->x - *destx;
249   if (*width > tmp) {
250     *width = tmp;
251   }
252   tmp = dbuf->y - *desty;
253   if (*height > tmp) {
254     *height = tmp;
255   }
256
257   if (sbuf) {
258     tmp = sbuf->x - *srcx;
259     if (*width > tmp) {
260       *width = tmp;
261     }
262     tmp = sbuf->y - *srcy;
263     if (*height > tmp) {
264       *height = tmp;
265     }
266   }
267
268   if ((*height <= 0) || (*width <= 0)) {
269     *width = 0;
270     *height = 0;
271   }
272 }
273
274 static void imb_rectclip3(ImBuf *dbuf,
275                           ImBuf *obuf,
276                           ImBuf *sbuf,
277                           int *destx,
278                           int *desty,
279                           int *origx,
280                           int *origy,
281                           int *srcx,
282                           int *srcy,
283                           int *width,
284                           int *height)
285 {
286   int tmp;
287
288   if (dbuf == NULL) {
289     return;
290   }
291
292   if (*destx < 0) {
293     *srcx -= *destx;
294     *origx -= *destx;
295     *width += *destx;
296     *destx = 0;
297   }
298   if (*origx < 0) {
299     *destx -= *origx;
300     *srcx -= *origx;
301     *width += *origx;
302     *origx = 0;
303   }
304   if (*srcx < 0) {
305     *destx -= *srcx;
306     *origx -= *srcx;
307     *width += *srcx;
308     *srcx = 0;
309   }
310
311   if (*desty < 0) {
312     *srcy -= *desty;
313     *origy -= *desty;
314     *height += *desty;
315     *desty = 0;
316   }
317   if (*origy < 0) {
318     *desty -= *origy;
319     *srcy -= *origy;
320     *height += *origy;
321     *origy = 0;
322   }
323   if (*srcy < 0) {
324     *desty -= *srcy;
325     *origy -= *srcy;
326     *height += *srcy;
327     *srcy = 0;
328   }
329
330   tmp = dbuf->x - *destx;
331   if (*width > tmp) {
332     *width = tmp;
333   }
334   tmp = dbuf->y - *desty;
335   if (*height > tmp) {
336     *height = tmp;
337   }
338
339   if (obuf) {
340     tmp = obuf->x - *origx;
341     if (*width > tmp) {
342       *width = tmp;
343     }
344     tmp = obuf->y - *origy;
345     if (*height > tmp) {
346       *height = tmp;
347     }
348   }
349
350   if (sbuf) {
351     tmp = sbuf->x - *srcx;
352     if (*width > tmp) {
353       *width = tmp;
354     }
355     tmp = sbuf->y - *srcy;
356     if (*height > tmp) {
357       *height = tmp;
358     }
359   }
360
361   if ((*height <= 0) || (*width <= 0)) {
362     *width = 0;
363     *height = 0;
364   }
365 }
366
367 /* copy and blend */
368
369 void IMB_rectcpy(
370     ImBuf *dbuf, ImBuf *sbuf, int destx, int desty, int srcx, int srcy, int width, int height)
371 {
372   IMB_rectblend(dbuf,
373                 dbuf,
374                 sbuf,
375                 NULL,
376                 NULL,
377                 NULL,
378                 0,
379                 destx,
380                 desty,
381                 destx,
382                 desty,
383                 srcx,
384                 srcy,
385                 width,
386                 height,
387                 IMB_BLEND_COPY,
388                 false);
389 }
390
391 typedef void (*IMB_blend_func)(unsigned char *dst,
392                                const unsigned char *src1,
393                                const unsigned char *src2);
394 typedef void (*IMB_blend_func_float)(float *dst, const float *src1, const float *src2);
395
396 void IMB_rectblend(ImBuf *dbuf,
397                    ImBuf *obuf,
398                    ImBuf *sbuf,
399                    unsigned short *dmask,
400                    unsigned short *curvemask,
401                    unsigned short *texmask,
402                    float mask_max,
403                    int destx,
404                    int desty,
405                    int origx,
406                    int origy,
407                    int srcx,
408                    int srcy,
409                    int width,
410                    int height,
411                    IMB_BlendMode mode,
412                    bool accumulate)
413 {
414   unsigned int *drect = NULL, *orect = NULL, *srect = NULL, *dr, * or, *sr;
415   float *drectf = NULL, *orectf = NULL, *srectf = NULL, *drf, *orf, *srf;
416   unsigned short *cmaskrect = curvemask, *cmr;
417   unsigned short *dmaskrect = dmask, *dmr;
418   unsigned short *texmaskrect = texmask, *tmr;
419   int do_float, do_char, srcskip, destskip, origskip, x;
420   IMB_blend_func func = NULL;
421   IMB_blend_func_float func_float = NULL;
422
423   if (dbuf == NULL || obuf == NULL) {
424     return;
425   }
426
427   imb_rectclip3(dbuf, obuf, sbuf, &destx, &desty, &origx, &origy, &srcx, &srcy, &width, &height);
428
429   if (width == 0 || height == 0) {
430     return;
431   }
432   if (sbuf && sbuf->channels != 4) {
433     return;
434   }
435   if (dbuf->channels != 4) {
436     return;
437   }
438
439   do_char = (sbuf && sbuf->rect && dbuf->rect && obuf->rect);
440   do_float = (sbuf && sbuf->rect_float && dbuf->rect_float && obuf->rect_float);
441
442   if (do_char) {
443     drect = dbuf->rect + ((size_t)desty) * dbuf->x + destx;
444     orect = obuf->rect + ((size_t)origy) * obuf->x + origx;
445   }
446   if (do_float) {
447     drectf = dbuf->rect_float + (((size_t)desty) * dbuf->x + destx) * 4;
448     orectf = obuf->rect_float + (((size_t)origy) * obuf->x + origx) * 4;
449   }
450
451   if (dmaskrect) {
452     dmaskrect += ((size_t)origy) * obuf->x + origx;
453   }
454
455   destskip = dbuf->x;
456   origskip = obuf->x;
457
458   if (sbuf) {
459     if (do_char) {
460       srect = sbuf->rect + ((size_t)srcy) * sbuf->x + srcx;
461     }
462     if (do_float) {
463       srectf = sbuf->rect_float + (((size_t)srcy) * sbuf->x + srcx) * 4;
464     }
465     srcskip = sbuf->x;
466
467     if (cmaskrect) {
468       cmaskrect += ((size_t)srcy) * sbuf->x + srcx;
469     }
470
471     if (texmaskrect) {
472       texmaskrect += ((size_t)srcy) * sbuf->x + srcx;
473     }
474   }
475   else {
476     srect = drect;
477     srectf = drectf;
478     srcskip = destskip;
479   }
480
481   if (mode == IMB_BLEND_COPY) {
482     /* copy */
483     for (; height > 0; height--) {
484       if (do_char) {
485         memcpy(drect, srect, width * sizeof(int));
486         drect += destskip;
487         srect += srcskip;
488       }
489
490       if (do_float) {
491         memcpy(drectf, srectf, width * sizeof(float) * 4);
492         drectf += destskip * 4;
493         srectf += srcskip * 4;
494       }
495     }
496   }
497   else if (mode == IMB_BLEND_COPY_RGB) {
498     /* copy rgb only */
499     for (; height > 0; height--) {
500       if (do_char) {
501         dr = drect;
502         sr = srect;
503         for (x = width; x > 0; x--, dr++, sr++) {
504           ((char *)dr)[0] = ((char *)sr)[0];
505           ((char *)dr)[1] = ((char *)sr)[1];
506           ((char *)dr)[2] = ((char *)sr)[2];
507         }
508         drect += destskip;
509         srect += srcskip;
510       }
511
512       if (do_float) {
513         drf = drectf;
514         srf = srectf;
515         for (x = width; x > 0; x--, drf += 4, srf += 4) {
516           float map_alpha = (srf[3] == 0.0f) ? drf[3] : drf[3] / srf[3];
517
518           drf[0] = srf[0] * map_alpha;
519           drf[1] = srf[1] * map_alpha;
520           drf[2] = srf[2] * map_alpha;
521         }
522         drectf += destskip * 4;
523         srectf += srcskip * 4;
524       }
525     }
526   }
527   else if (mode == IMB_BLEND_COPY_ALPHA) {
528     /* copy alpha only */
529     for (; height > 0; height--) {
530       if (do_char) {
531         dr = drect;
532         sr = srect;
533         for (x = width; x > 0; x--, dr++, sr++) {
534           ((char *)dr)[3] = ((char *)sr)[3];
535         }
536         drect += destskip;
537         srect += srcskip;
538       }
539
540       if (do_float) {
541         drf = drectf;
542         srf = srectf;
543         for (x = width; x > 0; x--, drf += 4, srf += 4) {
544           drf[3] = srf[3];
545         }
546         drectf += destskip * 4;
547         srectf += srcskip * 4;
548       }
549     }
550   }
551   else {
552     switch (mode) {
553       case IMB_BLEND_MIX:
554       case IMB_BLEND_INTERPOLATE:
555         func = blend_color_mix_byte;
556         func_float = blend_color_mix_float;
557         break;
558       case IMB_BLEND_ADD:
559         func = blend_color_add_byte;
560         func_float = blend_color_add_float;
561         break;
562       case IMB_BLEND_SUB:
563         func = blend_color_sub_byte;
564         func_float = blend_color_sub_float;
565         break;
566       case IMB_BLEND_MUL:
567         func = blend_color_mul_byte;
568         func_float = blend_color_mul_float;
569         break;
570       case IMB_BLEND_LIGHTEN:
571         func = blend_color_lighten_byte;
572         func_float = blend_color_lighten_float;
573         break;
574       case IMB_BLEND_DARKEN:
575         func = blend_color_darken_byte;
576         func_float = blend_color_darken_float;
577         break;
578       case IMB_BLEND_ERASE_ALPHA:
579         func = blend_color_erase_alpha_byte;
580         func_float = blend_color_erase_alpha_float;
581         break;
582       case IMB_BLEND_ADD_ALPHA:
583         func = blend_color_add_alpha_byte;
584         func_float = blend_color_add_alpha_float;
585         break;
586       case IMB_BLEND_OVERLAY:
587         func = blend_color_overlay_byte;
588         func_float = blend_color_overlay_float;
589         break;
590       case IMB_BLEND_HARDLIGHT:
591         func = blend_color_hardlight_byte;
592         func_float = blend_color_hardlight_float;
593         break;
594       case IMB_BLEND_COLORBURN:
595         func = blend_color_burn_byte;
596         func_float = blend_color_burn_float;
597         break;
598       case IMB_BLEND_LINEARBURN:
599         func = blend_color_linearburn_byte;
600         func_float = blend_color_linearburn_float;
601         break;
602       case IMB_BLEND_COLORDODGE:
603         func = blend_color_dodge_byte;
604         func_float = blend_color_dodge_float;
605         break;
606       case IMB_BLEND_SCREEN:
607         func = blend_color_screen_byte;
608         func_float = blend_color_screen_float;
609         break;
610       case IMB_BLEND_SOFTLIGHT:
611         func = blend_color_softlight_byte;
612         func_float = blend_color_softlight_float;
613         break;
614       case IMB_BLEND_PINLIGHT:
615         func = blend_color_pinlight_byte;
616         func_float = blend_color_pinlight_float;
617         break;
618       case IMB_BLEND_LINEARLIGHT:
619         func = blend_color_linearlight_byte;
620         func_float = blend_color_linearlight_float;
621         break;
622       case IMB_BLEND_VIVIDLIGHT:
623         func = blend_color_vividlight_byte;
624         func_float = blend_color_vividlight_float;
625         break;
626       case IMB_BLEND_DIFFERENCE:
627         func = blend_color_difference_byte;
628         func_float = blend_color_difference_float;
629         break;
630       case IMB_BLEND_EXCLUSION:
631         func = blend_color_exclusion_byte;
632         func_float = blend_color_exclusion_float;
633         break;
634       case IMB_BLEND_COLOR:
635         func = blend_color_color_byte;
636         func_float = blend_color_color_float;
637         break;
638       case IMB_BLEND_HUE:
639         func = blend_color_hue_byte;
640         func_float = blend_color_hue_float;
641         break;
642       case IMB_BLEND_SATURATION:
643         func = blend_color_saturation_byte;
644         func_float = blend_color_saturation_float;
645         break;
646       case IMB_BLEND_LUMINOSITY:
647         func = blend_color_luminosity_byte;
648         func_float = blend_color_luminosity_float;
649         break;
650       default:
651         break;
652     }
653
654     /* blend */
655     for (; height > 0; height--) {
656       if (do_char) {
657         dr = drect;
658         or = orect;
659         sr = srect;
660
661         if (cmaskrect) {
662           /* mask accumulation for painting */
663           cmr = cmaskrect;
664           tmr = texmaskrect;
665
666           /* destination mask present, do max alpha masking */
667           if (dmaskrect) {
668             dmr = dmaskrect;
669             for (x = width; x > 0; x--, dr++, or ++, sr++, dmr++, cmr++) {
670               unsigned char *src = (unsigned char *)sr;
671               float mask_lim = mask_max * (*cmr);
672
673               if (texmaskrect) {
674                 mask_lim *= ((*tmr++) / 65535.0f);
675               }
676
677               if (src[3] && mask_lim) {
678                 float mask;
679
680                 if (accumulate) {
681                   mask = *dmr + mask_lim;
682                 }
683                 else {
684                   mask = *dmr + mask_lim - (*dmr * (*cmr / 65535.0f));
685                 }
686
687                 mask = min_ff(mask, 65535.0);
688
689                 if (mask > *dmr) {
690                   unsigned char mask_src[4];
691
692                   *dmr = mask;
693
694                   mask_src[0] = src[0];
695                   mask_src[1] = src[1];
696                   mask_src[2] = src[2];
697
698                   if (mode == IMB_BLEND_INTERPOLATE) {
699                     mask_src[3] = src[3];
700                     blend_color_interpolate_byte(
701                         (unsigned char *)dr, (unsigned char *) or, mask_src, mask / 65535.0f);
702                   }
703                   else {
704                     mask_src[3] = divide_round_i(src[3] * mask, 65535);
705                     func((unsigned char *)dr, (unsigned char *) or, mask_src);
706                   }
707                 }
708               }
709             }
710             dmaskrect += origskip;
711           }
712           /* no destination mask buffer, do regular blend with masktexture if present */
713           else {
714             for (x = width; x > 0; x--, dr++, or ++, sr++, cmr++) {
715               unsigned char *src = (unsigned char *)sr;
716               float mask = (float)mask_max * ((float)(*cmr));
717
718               if (texmaskrect) {
719                 mask *= ((float)(*tmr++) / 65535.0f);
720               }
721
722               mask = min_ff(mask, 65535.0);
723
724               if (src[3] && (mask > 0.0f)) {
725                 unsigned char mask_src[4];
726
727                 mask_src[0] = src[0];
728                 mask_src[1] = src[1];
729                 mask_src[2] = src[2];
730
731                 if (mode == IMB_BLEND_INTERPOLATE) {
732                   mask_src[3] = src[3];
733                   blend_color_interpolate_byte(
734                       (unsigned char *)dr, (unsigned char *) or, mask_src, mask / 65535.0f);
735                 }
736                 else {
737                   mask_src[3] = divide_round_i(src[3] * mask, 65535);
738                   func((unsigned char *)dr, (unsigned char *) or, mask_src);
739                 }
740               }
741             }
742           }
743
744           cmaskrect += srcskip;
745           if (texmaskrect) {
746             texmaskrect += srcskip;
747           }
748         }
749         else {
750           /* regular blending */
751           for (x = width; x > 0; x--, dr++, or ++, sr++) {
752             if (((unsigned char *)sr)[3]) {
753               func((unsigned char *)dr, (unsigned char *) or, (unsigned char *)sr);
754             }
755           }
756         }
757
758         drect += destskip;
759         orect += origskip;
760         srect += srcskip;
761       }
762
763       if (do_float) {
764         drf = drectf;
765         orf = orectf;
766         srf = srectf;
767
768         if (cmaskrect) {
769           /* mask accumulation for painting */
770           cmr = cmaskrect;
771           tmr = texmaskrect;
772
773           /* destination mask present, do max alpha masking */
774           if (dmaskrect) {
775             dmr = dmaskrect;
776             for (x = width; x > 0; x--, drf += 4, orf += 4, srf += 4, dmr++, cmr++) {
777               float mask_lim = mask_max * (*cmr);
778
779               if (texmaskrect) {
780                 mask_lim *= ((*tmr++) / 65535.0f);
781               }
782
783               if (srf[3] && mask_lim) {
784                 float mask;
785
786                 if (accumulate) {
787                   mask = min_ff(*dmr + mask_lim, 65535.0);
788                 }
789                 else {
790                   mask = *dmr + mask_lim - (*dmr * (*cmr / 65535.0f));
791                 }
792
793                 mask = min_ff(mask, 65535.0);
794
795                 if (mask > *dmr) {
796                   *dmr = mask;
797
798                   if (mode == IMB_BLEND_INTERPOLATE) {
799                     blend_color_interpolate_float(drf, orf, srf, mask / 65535.0f);
800                   }
801                   else {
802                     float mask_srf[4];
803                     mul_v4_v4fl(mask_srf, srf, mask / 65535.0f);
804                     func_float(drf, orf, mask_srf);
805                   }
806                 }
807               }
808             }
809             dmaskrect += origskip;
810           }
811           /* no destination mask buffer, do regular blend with masktexture if present */
812           else {
813             for (x = width; x > 0; x--, drf += 4, orf += 4, srf += 4, cmr++) {
814               float mask = (float)mask_max * ((float)(*cmr));
815
816               if (texmaskrect) {
817                 mask *= ((float)(*tmr++) / 65535.0f);
818               }
819
820               mask = min_ff(mask, 65535.0);
821
822               if (srf[3] && (mask > 0.0f)) {
823                 if (mode == IMB_BLEND_INTERPOLATE) {
824                   blend_color_interpolate_float(drf, orf, srf, mask / 65535.0f);
825                 }
826                 else {
827                   float mask_srf[4];
828                   mul_v4_v4fl(mask_srf, srf, mask / 65535.0f);
829                   func_float(drf, orf, mask_srf);
830                 }
831               }
832             }
833           }
834
835           cmaskrect += srcskip;
836           if (texmaskrect) {
837             texmaskrect += srcskip;
838           }
839         }
840         else {
841           /* regular blending */
842           for (x = width; x > 0; x--, drf += 4, orf += 4, srf += 4) {
843             if (srf[3] != 0) {
844               func_float(drf, orf, srf);
845             }
846           }
847         }
848
849         drectf += destskip * 4;
850         orectf += origskip * 4;
851         srectf += srcskip * 4;
852       }
853     }
854   }
855 }
856
857 typedef struct RectBlendThreadData {
858   ImBuf *dbuf, *obuf, *sbuf;
859   unsigned short *dmask, *curvemask, *texmask;
860   float mask_max;
861   int destx, desty, origx, origy;
862   int srcx, srcy, width;
863   IMB_BlendMode mode;
864   bool accumulate;
865 } RectBlendThreadData;
866
867 static void rectblend_thread_do(void *data_v, int start_scanline, int num_scanlines)
868 {
869   RectBlendThreadData *data = (RectBlendThreadData *)data_v;
870   IMB_rectblend(data->dbuf,
871                 data->obuf,
872                 data->sbuf,
873                 data->dmask,
874                 data->curvemask,
875                 data->texmask,
876                 data->mask_max,
877                 data->destx,
878                 data->desty + start_scanline,
879                 data->origx,
880                 data->origy + start_scanline,
881                 data->srcx,
882                 data->srcy + start_scanline,
883                 data->width,
884                 num_scanlines,
885                 data->mode,
886                 data->accumulate);
887 }
888
889 void IMB_rectblend_threaded(ImBuf *dbuf,
890                             ImBuf *obuf,
891                             ImBuf *sbuf,
892                             unsigned short *dmask,
893                             unsigned short *curvemask,
894                             unsigned short *texmask,
895                             float mask_max,
896                             int destx,
897                             int desty,
898                             int origx,
899                             int origy,
900                             int srcx,
901                             int srcy,
902                             int width,
903                             int height,
904                             IMB_BlendMode mode,
905                             bool accumulate)
906 {
907   if (((size_t)width) * height < 64 * 64) {
908     IMB_rectblend(dbuf,
909                   obuf,
910                   sbuf,
911                   dmask,
912                   curvemask,
913                   texmask,
914                   mask_max,
915                   destx,
916                   desty,
917                   origx,
918                   origy,
919                   srcx,
920                   srcy,
921                   width,
922                   height,
923                   mode,
924                   accumulate);
925   }
926   else {
927     RectBlendThreadData data;
928     data.dbuf = dbuf;
929     data.obuf = obuf;
930     data.sbuf = sbuf;
931     data.dmask = dmask;
932     data.curvemask = curvemask;
933     data.texmask = texmask;
934     data.mask_max = mask_max;
935     data.destx = destx;
936     data.desty = desty;
937     data.origx = origx;
938     data.origy = origy;
939     data.srcx = srcx;
940     data.srcy = srcy;
941     data.width = width;
942     data.mode = mode;
943     data.accumulate = accumulate;
944     IMB_processor_apply_threaded_scanlines(height, rectblend_thread_do, &data);
945   }
946 }
947
948 /* fill */
949
950 void IMB_rectfill(ImBuf *drect, const float col[4])
951 {
952   int num;
953
954   if (drect->rect) {
955     unsigned int *rrect = drect->rect;
956     char ccol[4];
957
958     ccol[0] = (int)(col[0] * 255);
959     ccol[1] = (int)(col[1] * 255);
960     ccol[2] = (int)(col[2] * 255);
961     ccol[3] = (int)(col[3] * 255);
962
963     num = drect->x * drect->y;
964     for (; num > 0; num--) {
965       *rrect++ = *((unsigned int *)ccol);
966     }
967   }
968
969   if (drect->rect_float) {
970     float *rrectf = drect->rect_float;
971
972     num = drect->x * drect->y;
973     for (; num > 0; num--) {
974       *rrectf++ = col[0];
975       *rrectf++ = col[1];
976       *rrectf++ = col[2];
977       *rrectf++ = col[3];
978     }
979   }
980 }
981
982 void buf_rectfill_area(unsigned char *rect,
983                        float *rectf,
984                        int width,
985                        int height,
986                        const float col[4],
987                        struct ColorManagedDisplay *display,
988                        int x1,
989                        int y1,
990                        int x2,
991                        int y2)
992 {
993   int i, j;
994   float a;    /* alpha */
995   float ai;   /* alpha inverted */
996   float aich; /* alpha, inverted, ai/255.0 - Convert char to float at the same time */
997   if ((!rect && !rectf) || (!col) || col[3] == 0.0f) {
998     return;
999   }
1000
1001   /* sanity checks for coords */
1002   CLAMP(x1, 0, width);
1003   CLAMP(x2, 0, width);
1004   CLAMP(y1, 0, height);
1005   CLAMP(y2, 0, height);
1006
1007   if (x1 > x2) {
1008     SWAP(int, x1, x2);
1009   }
1010   if (y1 > y2) {
1011     SWAP(int, y1, y2);
1012   }
1013   if (x1 == x2 || y1 == y2) {
1014     return;
1015   }
1016
1017   a = col[3];
1018   ai = 1 - a;
1019   aich = ai / 255.0f;
1020
1021   if (rect) {
1022     unsigned char *pixel;
1023     unsigned char chr = 0, chg = 0, chb = 0;
1024     float fr = 0, fg = 0, fb = 0;
1025
1026     const int alphaint = unit_float_to_uchar_clamp(a);
1027
1028     if (a == 1.0f) {
1029       chr = unit_float_to_uchar_clamp(col[0]);
1030       chg = unit_float_to_uchar_clamp(col[1]);
1031       chb = unit_float_to_uchar_clamp(col[2]);
1032     }
1033     else {
1034       fr = col[0] * a;
1035       fg = col[1] * a;
1036       fb = col[2] * a;
1037     }
1038     for (j = 0; j < y2 - y1; j++) {
1039       for (i = 0; i < x2 - x1; i++) {
1040         pixel = rect + 4 * (((y1 + j) * width) + (x1 + i));
1041         if (pixel >= rect && pixel < rect + (4 * (width * height))) {
1042           if (a == 1.0f) {
1043             pixel[0] = chr;
1044             pixel[1] = chg;
1045             pixel[2] = chb;
1046             pixel[3] = 255;
1047           }
1048           else {
1049             int alphatest;
1050             pixel[0] = (char)((fr + ((float)pixel[0] * aich)) * 255.0f);
1051             pixel[1] = (char)((fg + ((float)pixel[1] * aich)) * 255.0f);
1052             pixel[2] = (char)((fb + ((float)pixel[2] * aich)) * 255.0f);
1053             pixel[3] = (char)((alphatest = ((int)pixel[3] + alphaint)) < 255 ? alphatest : 255);
1054           }
1055         }
1056       }
1057     }
1058   }
1059
1060   if (rectf) {
1061     float col_conv[4];
1062     float *pixel;
1063
1064     if (display) {
1065       copy_v4_v4(col_conv, col);
1066       IMB_colormanagement_display_to_scene_linear_v3(col_conv, display);
1067     }
1068     else {
1069       srgb_to_linearrgb_v4(col_conv, col);
1070     }
1071
1072     for (j = 0; j < y2 - y1; j++) {
1073       for (i = 0; i < x2 - x1; i++) {
1074         pixel = rectf + 4 * (((y1 + j) * width) + (x1 + i));
1075         if (a == 1.0f) {
1076           pixel[0] = col_conv[0];
1077           pixel[1] = col_conv[1];
1078           pixel[2] = col_conv[2];
1079           pixel[3] = 1.0f;
1080         }
1081         else {
1082           float alphatest;
1083           pixel[0] = (col_conv[0] * a) + (pixel[0] * ai);
1084           pixel[1] = (col_conv[1] * a) + (pixel[1] * ai);
1085           pixel[2] = (col_conv[2] * a) + (pixel[2] * ai);
1086           pixel[3] = (alphatest = (pixel[3] + a)) < 1.0f ? alphatest : 1.0f;
1087         }
1088       }
1089     }
1090   }
1091 }
1092
1093 void IMB_rectfill_area(ImBuf *ibuf,
1094                        const float col[4],
1095                        int x1,
1096                        int y1,
1097                        int x2,
1098                        int y2,
1099                        struct ColorManagedDisplay *display)
1100 {
1101   if (!ibuf) {
1102     return;
1103   }
1104   buf_rectfill_area((unsigned char *)ibuf->rect,
1105                     ibuf->rect_float,
1106                     ibuf->x,
1107                     ibuf->y,
1108                     col,
1109                     display,
1110                     x1,
1111                     y1,
1112                     x2,
1113                     y2);
1114 }
1115
1116 void IMB_rectfill_alpha(ImBuf *ibuf, const float value)
1117 {
1118   int i;
1119
1120   if (ibuf->rect_float && (ibuf->channels == 4)) {
1121     float *fbuf = ibuf->rect_float + 3;
1122     for (i = ibuf->x * ibuf->y; i > 0; i--, fbuf += 4) {
1123       *fbuf = value;
1124     }
1125   }
1126
1127   if (ibuf->rect) {
1128     const unsigned char cvalue = value * 255;
1129     unsigned char *cbuf = ((unsigned char *)ibuf->rect) + 3;
1130     for (i = ibuf->x * ibuf->y; i > 0; i--, cbuf += 4) {
1131       *cbuf = cvalue;
1132     }
1133   }
1134 }