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