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  *
19  * - Blender Foundation, 2003-2009
20  * - Peter Schlaile <peter [at] schlaile [dot] de> 2005/2006
21  */
22 
23 /** \file
24  * \ingroup bke
25  */
26 
27 #include <math.h>
28 #include <stdlib.h>
29 #include <string.h>
30 
31 #include "MEM_guardedalloc.h"
32 
33 #include "BLI_listbase.h"
34 #include "BLI_math.h" /* windows needs for M_PI */
35 #include "BLI_path_util.h"
36 #include "BLI_rect.h"
37 #include "BLI_string.h"
38 #include "BLI_threads.h"
39 #include "BLI_utildefines.h"
40 
41 #include "DNA_anim_types.h"
42 #include "DNA_scene_types.h"
43 #include "DNA_sequence_types.h"
44 #include "DNA_space_types.h"
45 
46 #include "BKE_fcurve.h"
47 #include "BKE_lib_id.h"
48 #include "BKE_main.h"
49 #include "BKE_sequencer.h"
50 
51 #include "IMB_colormanagement.h"
52 #include "IMB_imbuf.h"
53 #include "IMB_imbuf_types.h"
54 #include "IMB_metadata.h"
55 
56 #include "BLI_math_color_blend.h"
57 
58 #include "RNA_access.h"
59 
60 #include "RE_pipeline.h"
61 
62 #include "BLF_api.h"
63 
64 static struct SeqEffectHandle get_sequence_effect_impl(int seq_type);
65 
slice_get_byte_buffers(const SeqRenderData * context,const ImBuf * ibuf1,const ImBuf * ibuf2,const ImBuf * ibuf3,const ImBuf * out,int start_line,unsigned char ** rect1,unsigned char ** rect2,unsigned char ** rect3,unsigned char ** rect_out)66 static void slice_get_byte_buffers(const SeqRenderData *context,
67                                    const ImBuf *ibuf1,
68                                    const ImBuf *ibuf2,
69                                    const ImBuf *ibuf3,
70                                    const ImBuf *out,
71                                    int start_line,
72                                    unsigned char **rect1,
73                                    unsigned char **rect2,
74                                    unsigned char **rect3,
75                                    unsigned char **rect_out)
76 {
77   int offset = 4 * start_line * context->rectx;
78 
79   *rect1 = (unsigned char *)ibuf1->rect + offset;
80   *rect_out = (unsigned char *)out->rect + offset;
81 
82   if (ibuf2) {
83     *rect2 = (unsigned char *)ibuf2->rect + offset;
84   }
85 
86   if (ibuf3) {
87     *rect3 = (unsigned char *)ibuf3->rect + offset;
88   }
89 }
90 
slice_get_float_buffers(const SeqRenderData * context,const ImBuf * ibuf1,const ImBuf * ibuf2,const ImBuf * ibuf3,const ImBuf * out,int start_line,float ** rect1,float ** rect2,float ** rect3,float ** rect_out)91 static void slice_get_float_buffers(const SeqRenderData *context,
92                                     const ImBuf *ibuf1,
93                                     const ImBuf *ibuf2,
94                                     const ImBuf *ibuf3,
95                                     const ImBuf *out,
96                                     int start_line,
97                                     float **rect1,
98                                     float **rect2,
99                                     float **rect3,
100                                     float **rect_out)
101 {
102   int offset = 4 * start_line * context->rectx;
103 
104   *rect1 = ibuf1->rect_float + offset;
105   *rect_out = out->rect_float + offset;
106 
107   if (ibuf2) {
108     *rect2 = ibuf2->rect_float + offset;
109   }
110 
111   if (ibuf3) {
112     *rect3 = ibuf3->rect_float + offset;
113   }
114 }
115 
116 /*********************** Glow effect *************************/
117 
118 enum {
119   GlowR = 0,
120   GlowG = 1,
121   GlowB = 2,
122   GlowA = 3,
123 };
124 
prepare_effect_imbufs(const SeqRenderData * context,ImBuf * ibuf1,ImBuf * ibuf2,ImBuf * ibuf3)125 static ImBuf *prepare_effect_imbufs(const SeqRenderData *context,
126                                     ImBuf *ibuf1,
127                                     ImBuf *ibuf2,
128                                     ImBuf *ibuf3)
129 {
130   ImBuf *out;
131   Scene *scene = context->scene;
132   int x = context->rectx;
133   int y = context->recty;
134 
135   if (!ibuf1 && !ibuf2 && !ibuf3) {
136     /* hmmm, global float option ? */
137     out = IMB_allocImBuf(x, y, 32, IB_rect);
138   }
139   else if ((ibuf1 && ibuf1->rect_float) || (ibuf2 && ibuf2->rect_float) ||
140            (ibuf3 && ibuf3->rect_float)) {
141     /* if any inputs are rectfloat, output is float too */
142 
143     out = IMB_allocImBuf(x, y, 32, IB_rectfloat);
144   }
145   else {
146     out = IMB_allocImBuf(x, y, 32, IB_rect);
147   }
148 
149   if (out->rect_float) {
150     if (ibuf1 && !ibuf1->rect_float) {
151       BKE_sequencer_imbuf_to_sequencer_space(scene, ibuf1, true);
152     }
153 
154     if (ibuf2 && !ibuf2->rect_float) {
155       BKE_sequencer_imbuf_to_sequencer_space(scene, ibuf2, true);
156     }
157 
158     if (ibuf3 && !ibuf3->rect_float) {
159       BKE_sequencer_imbuf_to_sequencer_space(scene, ibuf3, true);
160     }
161 
162     IMB_colormanagement_assign_float_colorspace(out, scene->sequencer_colorspace_settings.name);
163   }
164   else {
165     if (ibuf1 && !ibuf1->rect) {
166       IMB_rect_from_float(ibuf1);
167     }
168 
169     if (ibuf2 && !ibuf2->rect) {
170       IMB_rect_from_float(ibuf2);
171     }
172 
173     if (ibuf3 && !ibuf3->rect) {
174       IMB_rect_from_float(ibuf3);
175     }
176   }
177 
178   /* If effect only affecting a single channel, forward input's metadata to the output. */
179   if (ibuf1 != NULL && ibuf1 == ibuf2 && ibuf2 == ibuf3) {
180     IMB_metadata_copy(out, ibuf1);
181   }
182 
183   return out;
184 }
185 
186 /*********************** Alpha Over *************************/
187 
init_alpha_over_or_under(Sequence * seq)188 static void init_alpha_over_or_under(Sequence *seq)
189 {
190   Sequence *seq1 = seq->seq1;
191   Sequence *seq2 = seq->seq2;
192 
193   seq->seq2 = seq1;
194   seq->seq1 = seq2;
195 }
196 
do_alphaover_effect_byte(float facf0,float facf1,int x,int y,unsigned char * rect1,unsigned char * rect2,unsigned char * out)197 static void do_alphaover_effect_byte(float facf0,
198                                      float facf1,
199                                      int x,
200                                      int y,
201                                      unsigned char *rect1,
202                                      unsigned char *rect2,
203                                      unsigned char *out)
204 {
205   float fac2, mfac, fac, fac4;
206   int xo;
207   unsigned char *cp1, *cp2, *rt;
208   float tempc[4], rt1[4], rt2[4];
209 
210   xo = x;
211   cp1 = rect1;
212   cp2 = rect2;
213   rt = out;
214 
215   fac2 = facf0;
216   fac4 = facf1;
217 
218   while (y--) {
219     x = xo;
220     while (x--) {
221       /* rt = rt1 over rt2  (alpha from rt1) */
222 
223       straight_uchar_to_premul_float(rt1, cp1);
224       straight_uchar_to_premul_float(rt2, cp2);
225 
226       fac = fac2;
227       mfac = 1.0f - fac2 * rt1[3];
228 
229       if (fac <= 0.0f) {
230         *((unsigned int *)rt) = *((unsigned int *)cp2);
231       }
232       else if (mfac <= 0.0f) {
233         *((unsigned int *)rt) = *((unsigned int *)cp1);
234       }
235       else {
236         tempc[0] = fac * rt1[0] + mfac * rt2[0];
237         tempc[1] = fac * rt1[1] + mfac * rt2[1];
238         tempc[2] = fac * rt1[2] + mfac * rt2[2];
239         tempc[3] = fac * rt1[3] + mfac * rt2[3];
240 
241         premul_float_to_straight_uchar(rt, tempc);
242       }
243       cp1 += 4;
244       cp2 += 4;
245       rt += 4;
246     }
247 
248     if (y == 0) {
249       break;
250     }
251     y--;
252 
253     x = xo;
254     while (x--) {
255       straight_uchar_to_premul_float(rt1, cp1);
256       straight_uchar_to_premul_float(rt2, cp2);
257 
258       fac = fac4;
259       mfac = 1.0f - (fac4 * rt1[3]);
260 
261       if (fac <= 0.0f) {
262         *((unsigned int *)rt) = *((unsigned int *)cp2);
263       }
264       else if (mfac <= 0.0f) {
265         *((unsigned int *)rt) = *((unsigned int *)cp1);
266       }
267       else {
268         tempc[0] = fac * rt1[0] + mfac * rt2[0];
269         tempc[1] = fac * rt1[1] + mfac * rt2[1];
270         tempc[2] = fac * rt1[2] + mfac * rt2[2];
271         tempc[3] = fac * rt1[3] + mfac * rt2[3];
272 
273         premul_float_to_straight_uchar(rt, tempc);
274       }
275       cp1 += 4;
276       cp2 += 4;
277       rt += 4;
278     }
279   }
280 }
281 
do_alphaover_effect_float(float facf0,float facf1,int x,int y,float * rect1,float * rect2,float * out)282 static void do_alphaover_effect_float(
283     float facf0, float facf1, int x, int y, float *rect1, float *rect2, float *out)
284 {
285   float fac2, mfac, fac, fac4;
286   int xo;
287   float *rt1, *rt2, *rt;
288 
289   xo = x;
290   rt1 = rect1;
291   rt2 = rect2;
292   rt = out;
293 
294   fac2 = facf0;
295   fac4 = facf1;
296 
297   while (y--) {
298     x = xo;
299     while (x--) {
300       /* rt = rt1 over rt2  (alpha from rt1) */
301 
302       fac = fac2;
303       mfac = 1.0f - (fac2 * rt1[3]);
304 
305       if (fac <= 0.0f) {
306         memcpy(rt, rt2, sizeof(float[4]));
307       }
308       else if (mfac <= 0) {
309         memcpy(rt, rt1, sizeof(float[4]));
310       }
311       else {
312         rt[0] = fac * rt1[0] + mfac * rt2[0];
313         rt[1] = fac * rt1[1] + mfac * rt2[1];
314         rt[2] = fac * rt1[2] + mfac * rt2[2];
315         rt[3] = fac * rt1[3] + mfac * rt2[3];
316       }
317       rt1 += 4;
318       rt2 += 4;
319       rt += 4;
320     }
321 
322     if (y == 0) {
323       break;
324     }
325     y--;
326 
327     x = xo;
328     while (x--) {
329       fac = fac4;
330       mfac = 1.0f - (fac4 * rt1[3]);
331 
332       if (fac <= 0.0f) {
333         memcpy(rt, rt2, sizeof(float[4]));
334       }
335       else if (mfac <= 0.0f) {
336         memcpy(rt, rt1, sizeof(float[4]));
337       }
338       else {
339         rt[0] = fac * rt1[0] + mfac * rt2[0];
340         rt[1] = fac * rt1[1] + mfac * rt2[1];
341         rt[2] = fac * rt1[2] + mfac * rt2[2];
342         rt[3] = fac * rt1[3] + mfac * rt2[3];
343       }
344       rt1 += 4;
345       rt2 += 4;
346       rt += 4;
347     }
348   }
349 }
350 
do_alphaover_effect(const SeqRenderData * context,Sequence * UNUSED (seq),float UNUSED (cfra),float facf0,float facf1,ImBuf * ibuf1,ImBuf * ibuf2,ImBuf * UNUSED (ibuf3),int start_line,int total_lines,ImBuf * out)351 static void do_alphaover_effect(const SeqRenderData *context,
352                                 Sequence *UNUSED(seq),
353                                 float UNUSED(cfra),
354                                 float facf0,
355                                 float facf1,
356                                 ImBuf *ibuf1,
357                                 ImBuf *ibuf2,
358                                 ImBuf *UNUSED(ibuf3),
359                                 int start_line,
360                                 int total_lines,
361                                 ImBuf *out)
362 {
363   if (out->rect_float) {
364     float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
365 
366     slice_get_float_buffers(
367         context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
368 
369     do_alphaover_effect_float(facf0, facf1, context->rectx, total_lines, rect1, rect2, rect_out);
370   }
371   else {
372     unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
373 
374     slice_get_byte_buffers(
375         context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
376 
377     do_alphaover_effect_byte(facf0, facf1, context->rectx, total_lines, rect1, rect2, rect_out);
378   }
379 }
380 
381 /*********************** Alpha Under *************************/
382 
do_alphaunder_effect_byte(float facf0,float facf1,int x,int y,unsigned char * rect1,unsigned char * rect2,unsigned char * out)383 static void do_alphaunder_effect_byte(float facf0,
384                                       float facf1,
385                                       int x,
386                                       int y,
387                                       unsigned char *rect1,
388                                       unsigned char *rect2,
389                                       unsigned char *out)
390 {
391   float fac2, fac, fac4;
392   int xo;
393   unsigned char *cp1, *cp2, *rt;
394   float tempc[4], rt1[4], rt2[4];
395 
396   xo = x;
397   cp1 = rect1;
398   cp2 = rect2;
399   rt = out;
400 
401   fac2 = facf0;
402   fac4 = facf1;
403 
404   while (y--) {
405     x = xo;
406     while (x--) {
407       /* rt = rt1 under rt2  (alpha from rt2) */
408       straight_uchar_to_premul_float(rt1, cp1);
409       straight_uchar_to_premul_float(rt2, cp2);
410 
411       /* this complex optimization is because the
412        * 'skybuf' can be crossed in
413        */
414       if (rt2[3] <= 0.0f && fac2 >= 1.0f) {
415         *((unsigned int *)rt) = *((unsigned int *)cp1);
416       }
417       else if (rt2[3] >= 1.0f) {
418         *((unsigned int *)rt) = *((unsigned int *)cp2);
419       }
420       else {
421         fac = (fac2 * (1.0f - rt2[3]));
422 
423         if (fac <= 0) {
424           *((unsigned int *)rt) = *((unsigned int *)cp2);
425         }
426         else {
427           tempc[0] = (fac * rt1[0] + rt2[0]);
428           tempc[1] = (fac * rt1[1] + rt2[1]);
429           tempc[2] = (fac * rt1[2] + rt2[2]);
430           tempc[3] = (fac * rt1[3] + rt2[3]);
431 
432           premul_float_to_straight_uchar(rt, tempc);
433         }
434       }
435       cp1 += 4;
436       cp2 += 4;
437       rt += 4;
438     }
439 
440     if (y == 0) {
441       break;
442     }
443     y--;
444 
445     x = xo;
446     while (x--) {
447       straight_uchar_to_premul_float(rt1, cp1);
448       straight_uchar_to_premul_float(rt2, cp2);
449 
450       if (rt2[3] <= 0.0f && fac4 >= 1.0f) {
451         *((unsigned int *)rt) = *((unsigned int *)cp1);
452       }
453       else if (rt2[3] >= 1.0f) {
454         *((unsigned int *)rt) = *((unsigned int *)cp2);
455       }
456       else {
457         fac = (fac4 * (1.0f - rt2[3]));
458 
459         if (fac <= 0) {
460           *((unsigned int *)rt) = *((unsigned int *)cp2);
461         }
462         else {
463           tempc[0] = (fac * rt1[0] + rt2[0]);
464           tempc[1] = (fac * rt1[1] + rt2[1]);
465           tempc[2] = (fac * rt1[2] + rt2[2]);
466           tempc[3] = (fac * rt1[3] + rt2[3]);
467 
468           premul_float_to_straight_uchar(rt, tempc);
469         }
470       }
471       cp1 += 4;
472       cp2 += 4;
473       rt += 4;
474     }
475   }
476 }
477 
do_alphaunder_effect_float(float facf0,float facf1,int x,int y,float * rect1,float * rect2,float * out)478 static void do_alphaunder_effect_float(
479     float facf0, float facf1, int x, int y, float *rect1, float *rect2, float *out)
480 {
481   float fac2, fac, fac4;
482   int xo;
483   float *rt1, *rt2, *rt;
484 
485   xo = x;
486   rt1 = rect1;
487   rt2 = rect2;
488   rt = out;
489 
490   fac2 = facf0;
491   fac4 = facf1;
492 
493   while (y--) {
494     x = xo;
495     while (x--) {
496       /* rt = rt1 under rt2  (alpha from rt2) */
497 
498       /* this complex optimization is because the
499        * 'skybuf' can be crossed in
500        */
501       if (rt2[3] <= 0 && fac2 >= 1.0f) {
502         memcpy(rt, rt1, sizeof(float[4]));
503       }
504       else if (rt2[3] >= 1.0f) {
505         memcpy(rt, rt2, sizeof(float[4]));
506       }
507       else {
508         fac = fac2 * (1.0f - rt2[3]);
509 
510         if (fac == 0) {
511           memcpy(rt, rt2, sizeof(float[4]));
512         }
513         else {
514           rt[0] = fac * rt1[0] + rt2[0];
515           rt[1] = fac * rt1[1] + rt2[1];
516           rt[2] = fac * rt1[2] + rt2[2];
517           rt[3] = fac * rt1[3] + rt2[3];
518         }
519       }
520       rt1 += 4;
521       rt2 += 4;
522       rt += 4;
523     }
524 
525     if (y == 0) {
526       break;
527     }
528     y--;
529 
530     x = xo;
531     while (x--) {
532       if (rt2[3] <= 0 && fac4 >= 1.0f) {
533         memcpy(rt, rt1, sizeof(float[4]));
534       }
535       else if (rt2[3] >= 1.0f) {
536         memcpy(rt, rt2, sizeof(float[4]));
537       }
538       else {
539         fac = fac4 * (1.0f - rt2[3]);
540 
541         if (fac == 0) {
542           memcpy(rt, rt2, sizeof(float[4]));
543         }
544         else {
545           rt[0] = fac * rt1[0] + rt2[0];
546           rt[1] = fac * rt1[1] + rt2[1];
547           rt[2] = fac * rt1[2] + rt2[2];
548           rt[3] = fac * rt1[3] + rt2[3];
549         }
550       }
551       rt1 += 4;
552       rt2 += 4;
553       rt += 4;
554     }
555   }
556 }
557 
do_alphaunder_effect(const SeqRenderData * context,Sequence * UNUSED (seq),float UNUSED (cfra),float facf0,float facf1,ImBuf * ibuf1,ImBuf * ibuf2,ImBuf * UNUSED (ibuf3),int start_line,int total_lines,ImBuf * out)558 static void do_alphaunder_effect(const SeqRenderData *context,
559                                  Sequence *UNUSED(seq),
560                                  float UNUSED(cfra),
561                                  float facf0,
562                                  float facf1,
563                                  ImBuf *ibuf1,
564                                  ImBuf *ibuf2,
565                                  ImBuf *UNUSED(ibuf3),
566                                  int start_line,
567                                  int total_lines,
568                                  ImBuf *out)
569 {
570   if (out->rect_float) {
571     float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
572 
573     slice_get_float_buffers(
574         context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
575 
576     do_alphaunder_effect_float(facf0, facf1, context->rectx, total_lines, rect1, rect2, rect_out);
577   }
578   else {
579     unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
580 
581     slice_get_byte_buffers(
582         context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
583 
584     do_alphaunder_effect_byte(facf0, facf1, context->rectx, total_lines, rect1, rect2, rect_out);
585   }
586 }
587 
588 /*********************** Cross *************************/
589 
do_cross_effect_byte(float facf0,float facf1,int x,int y,unsigned char * rect1,unsigned char * rect2,unsigned char * out)590 static void do_cross_effect_byte(float facf0,
591                                  float facf1,
592                                  int x,
593                                  int y,
594                                  unsigned char *rect1,
595                                  unsigned char *rect2,
596                                  unsigned char *out)
597 {
598   int fac1, fac2, fac3, fac4;
599   int xo;
600   unsigned char *rt1, *rt2, *rt;
601 
602   xo = x;
603   rt1 = rect1;
604   rt2 = rect2;
605   rt = out;
606 
607   fac2 = (int)(256.0f * facf0);
608   fac1 = 256 - fac2;
609   fac4 = (int)(256.0f * facf1);
610   fac3 = 256 - fac4;
611 
612   while (y--) {
613     x = xo;
614     while (x--) {
615       rt[0] = (fac1 * rt1[0] + fac2 * rt2[0]) >> 8;
616       rt[1] = (fac1 * rt1[1] + fac2 * rt2[1]) >> 8;
617       rt[2] = (fac1 * rt1[2] + fac2 * rt2[2]) >> 8;
618       rt[3] = (fac1 * rt1[3] + fac2 * rt2[3]) >> 8;
619 
620       rt1 += 4;
621       rt2 += 4;
622       rt += 4;
623     }
624 
625     if (y == 0) {
626       break;
627     }
628     y--;
629 
630     x = xo;
631     while (x--) {
632       rt[0] = (fac3 * rt1[0] + fac4 * rt2[0]) >> 8;
633       rt[1] = (fac3 * rt1[1] + fac4 * rt2[1]) >> 8;
634       rt[2] = (fac3 * rt1[2] + fac4 * rt2[2]) >> 8;
635       rt[3] = (fac3 * rt1[3] + fac4 * rt2[3]) >> 8;
636 
637       rt1 += 4;
638       rt2 += 4;
639       rt += 4;
640     }
641   }
642 }
643 
do_cross_effect_float(float facf0,float facf1,int x,int y,float * rect1,float * rect2,float * out)644 static void do_cross_effect_float(
645     float facf0, float facf1, int x, int y, float *rect1, float *rect2, float *out)
646 {
647   float fac1, fac2, fac3, fac4;
648   int xo;
649   float *rt1, *rt2, *rt;
650 
651   xo = x;
652   rt1 = rect1;
653   rt2 = rect2;
654   rt = out;
655 
656   fac2 = facf0;
657   fac1 = 1.0f - fac2;
658   fac4 = facf1;
659   fac3 = 1.0f - fac4;
660 
661   while (y--) {
662     x = xo;
663     while (x--) {
664       rt[0] = fac1 * rt1[0] + fac2 * rt2[0];
665       rt[1] = fac1 * rt1[1] + fac2 * rt2[1];
666       rt[2] = fac1 * rt1[2] + fac2 * rt2[2];
667       rt[3] = fac1 * rt1[3] + fac2 * rt2[3];
668 
669       rt1 += 4;
670       rt2 += 4;
671       rt += 4;
672     }
673 
674     if (y == 0) {
675       break;
676     }
677     y--;
678 
679     x = xo;
680     while (x--) {
681       rt[0] = fac3 * rt1[0] + fac4 * rt2[0];
682       rt[1] = fac3 * rt1[1] + fac4 * rt2[1];
683       rt[2] = fac3 * rt1[2] + fac4 * rt2[2];
684       rt[3] = fac3 * rt1[3] + fac4 * rt2[3];
685 
686       rt1 += 4;
687       rt2 += 4;
688       rt += 4;
689     }
690   }
691 }
692 
do_cross_effect(const SeqRenderData * context,Sequence * UNUSED (seq),float UNUSED (cfra),float facf0,float facf1,ImBuf * ibuf1,ImBuf * ibuf2,ImBuf * UNUSED (ibuf3),int start_line,int total_lines,ImBuf * out)693 static void do_cross_effect(const SeqRenderData *context,
694                             Sequence *UNUSED(seq),
695                             float UNUSED(cfra),
696                             float facf0,
697                             float facf1,
698                             ImBuf *ibuf1,
699                             ImBuf *ibuf2,
700                             ImBuf *UNUSED(ibuf3),
701                             int start_line,
702                             int total_lines,
703                             ImBuf *out)
704 {
705   if (out->rect_float) {
706     float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
707 
708     slice_get_float_buffers(
709         context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
710 
711     do_cross_effect_float(facf0, facf1, context->rectx, total_lines, rect1, rect2, rect_out);
712   }
713   else {
714     unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
715 
716     slice_get_byte_buffers(
717         context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
718 
719     do_cross_effect_byte(facf0, facf1, context->rectx, total_lines, rect1, rect2, rect_out);
720   }
721 }
722 
723 /*********************** Gamma Cross *************************/
724 
725 /* copied code from initrender.c */
726 static unsigned short gamtab[65536];
727 static unsigned short igamtab1[256];
728 static bool gamma_tabs_init = false;
729 
730 #define RE_GAMMA_TABLE_SIZE 400
731 
732 static float gamma_range_table[RE_GAMMA_TABLE_SIZE + 1];
733 static float gamfactor_table[RE_GAMMA_TABLE_SIZE];
734 static float inv_gamma_range_table[RE_GAMMA_TABLE_SIZE + 1];
735 static float inv_gamfactor_table[RE_GAMMA_TABLE_SIZE];
736 static float color_domain_table[RE_GAMMA_TABLE_SIZE + 1];
737 static float color_step;
738 static float inv_color_step;
739 static float valid_gamma;
740 static float valid_inv_gamma;
741 
makeGammaTables(float gamma)742 static void makeGammaTables(float gamma)
743 {
744   /* we need two tables: one forward, one backward */
745   int i;
746 
747   valid_gamma = gamma;
748   valid_inv_gamma = 1.0f / gamma;
749   color_step = 1.0f / RE_GAMMA_TABLE_SIZE;
750   inv_color_step = (float)RE_GAMMA_TABLE_SIZE;
751 
752   /* We could squeeze out the two range tables to gain some memory */
753   for (i = 0; i < RE_GAMMA_TABLE_SIZE; i++) {
754     color_domain_table[i] = i * color_step;
755     gamma_range_table[i] = pow(color_domain_table[i], valid_gamma);
756     inv_gamma_range_table[i] = pow(color_domain_table[i], valid_inv_gamma);
757   }
758 
759   /* The end of the table should match 1.0 carefully. In order to avoid
760    * rounding errors, we just set this explicitly. The last segment may
761    * have a different length than the other segments, but our
762    * interpolation is insensitive to that
763    */
764   color_domain_table[RE_GAMMA_TABLE_SIZE] = 1.0;
765   gamma_range_table[RE_GAMMA_TABLE_SIZE] = 1.0;
766   inv_gamma_range_table[RE_GAMMA_TABLE_SIZE] = 1.0;
767 
768   /* To speed up calculations, we make these calc factor tables. They are
769    * multiplication factors used in scaling the interpolation
770    */
771   for (i = 0; i < RE_GAMMA_TABLE_SIZE; i++) {
772     gamfactor_table[i] = inv_color_step * (gamma_range_table[i + 1] - gamma_range_table[i]);
773     inv_gamfactor_table[i] = inv_color_step *
774                              (inv_gamma_range_table[i + 1] - inv_gamma_range_table[i]);
775   }
776 }
777 
gammaCorrect(float c)778 static float gammaCorrect(float c)
779 {
780   int i;
781   float res;
782 
783   i = floorf(c * inv_color_step);
784   /* Clip to range [0, 1]: outside, just do the complete calculation.
785    * We may have some performance problems here. Stretching up the LUT
786    * may help solve that, by exchanging LUT size for the interpolation.
787    * Negative colors are explicitly handled.
788    */
789   if (UNLIKELY(i < 0)) {
790     res = -powf(-c, valid_gamma);
791   }
792   else if (i >= RE_GAMMA_TABLE_SIZE) {
793     res = powf(c, valid_gamma);
794   }
795   else {
796     res = gamma_range_table[i] + ((c - color_domain_table[i]) * gamfactor_table[i]);
797   }
798 
799   return res;
800 }
801 
802 /* ------------------------------------------------------------------------- */
803 
invGammaCorrect(float c)804 static float invGammaCorrect(float c)
805 {
806   int i;
807   float res = 0.0;
808 
809   i = floorf(c * inv_color_step);
810   /* Negative colors are explicitly handled */
811   if (UNLIKELY(i < 0)) {
812     res = -powf(-c, valid_inv_gamma);
813   }
814   else if (i >= RE_GAMMA_TABLE_SIZE) {
815     res = powf(c, valid_inv_gamma);
816   }
817   else {
818     res = inv_gamma_range_table[i] + ((c - color_domain_table[i]) * inv_gamfactor_table[i]);
819   }
820 
821   return res;
822 }
823 
gamtabs(float gamma)824 static void gamtabs(float gamma)
825 {
826   float val, igamma = 1.0f / gamma;
827   int a;
828 
829   /* gamtab: in short, out short */
830   for (a = 0; a < 65536; a++) {
831     val = a;
832     val /= 65535.0f;
833 
834     if (gamma == 2.0f) {
835       val = sqrtf(val);
836     }
837     else if (gamma != 1.0f) {
838       val = powf(val, igamma);
839     }
840 
841     gamtab[a] = (65535.99f * val);
842   }
843   /* inverse gamtab1 : in byte, out short */
844   for (a = 1; a <= 256; a++) {
845     if (gamma == 2.0f) {
846       igamtab1[a - 1] = a * a - 1;
847     }
848     else if (gamma == 1.0f) {
849       igamtab1[a - 1] = 256 * a - 1;
850     }
851     else {
852       val = a / 256.0f;
853       igamtab1[a - 1] = (65535.0 * pow(val, gamma)) - 1;
854     }
855   }
856 }
857 
build_gammatabs(void)858 static void build_gammatabs(void)
859 {
860   if (gamma_tabs_init == false) {
861     gamtabs(2.0f);
862     makeGammaTables(2.0f);
863     gamma_tabs_init = true;
864   }
865 }
866 
init_gammacross(Sequence * UNUSED (seq))867 static void init_gammacross(Sequence *UNUSED(seq))
868 {
869 }
870 
load_gammacross(Sequence * UNUSED (seq))871 static void load_gammacross(Sequence *UNUSED(seq))
872 {
873 }
874 
free_gammacross(Sequence * UNUSED (seq),const bool UNUSED (do_id_user))875 static void free_gammacross(Sequence *UNUSED(seq), const bool UNUSED(do_id_user))
876 {
877 }
878 
do_gammacross_effect_byte(float facf0,float UNUSED (facf1),int x,int y,unsigned char * rect1,unsigned char * rect2,unsigned char * out)879 static void do_gammacross_effect_byte(float facf0,
880                                       float UNUSED(facf1),
881                                       int x,
882                                       int y,
883                                       unsigned char *rect1,
884                                       unsigned char *rect2,
885                                       unsigned char *out)
886 {
887   float fac1, fac2;
888   int xo;
889   unsigned char *cp1, *cp2, *rt;
890   float rt1[4], rt2[4], tempc[4];
891 
892   xo = x;
893   cp1 = rect1;
894   cp2 = rect2;
895   rt = out;
896 
897   fac2 = facf0;
898   fac1 = 1.0f - fac2;
899 
900   while (y--) {
901     x = xo;
902     while (x--) {
903       straight_uchar_to_premul_float(rt1, cp1);
904       straight_uchar_to_premul_float(rt2, cp2);
905 
906       tempc[0] = gammaCorrect(fac1 * invGammaCorrect(rt1[0]) + fac2 * invGammaCorrect(rt2[0]));
907       tempc[1] = gammaCorrect(fac1 * invGammaCorrect(rt1[1]) + fac2 * invGammaCorrect(rt2[1]));
908       tempc[2] = gammaCorrect(fac1 * invGammaCorrect(rt1[2]) + fac2 * invGammaCorrect(rt2[2]));
909       tempc[3] = gammaCorrect(fac1 * invGammaCorrect(rt1[3]) + fac2 * invGammaCorrect(rt2[3]));
910 
911       premul_float_to_straight_uchar(rt, tempc);
912       cp1 += 4;
913       cp2 += 4;
914       rt += 4;
915     }
916 
917     if (y == 0) {
918       break;
919     }
920     y--;
921 
922     x = xo;
923     while (x--) {
924       straight_uchar_to_premul_float(rt1, cp1);
925       straight_uchar_to_premul_float(rt2, cp2);
926 
927       tempc[0] = gammaCorrect(fac1 * invGammaCorrect(rt1[0]) + fac2 * invGammaCorrect(rt2[0]));
928       tempc[1] = gammaCorrect(fac1 * invGammaCorrect(rt1[1]) + fac2 * invGammaCorrect(rt2[1]));
929       tempc[2] = gammaCorrect(fac1 * invGammaCorrect(rt1[2]) + fac2 * invGammaCorrect(rt2[2]));
930       tempc[3] = gammaCorrect(fac1 * invGammaCorrect(rt1[3]) + fac2 * invGammaCorrect(rt2[3]));
931 
932       premul_float_to_straight_uchar(rt, tempc);
933       cp1 += 4;
934       cp2 += 4;
935       rt += 4;
936     }
937   }
938 }
939 
do_gammacross_effect_float(float facf0,float UNUSED (facf1),int x,int y,float * rect1,float * rect2,float * out)940 static void do_gammacross_effect_float(
941     float facf0, float UNUSED(facf1), int x, int y, float *rect1, float *rect2, float *out)
942 {
943   float fac1, fac2;
944   int xo;
945   float *rt1, *rt2, *rt;
946 
947   xo = x;
948   rt1 = rect1;
949   rt2 = rect2;
950   rt = out;
951 
952   fac2 = facf0;
953   fac1 = 1.0f - fac2;
954 
955   while (y--) {
956     x = xo * 4;
957     while (x--) {
958       *rt = gammaCorrect(fac1 * invGammaCorrect(*rt1) + fac2 * invGammaCorrect(*rt2));
959       rt1++;
960       rt2++;
961       rt++;
962     }
963 
964     if (y == 0) {
965       break;
966     }
967     y--;
968 
969     x = xo * 4;
970     while (x--) {
971       *rt = gammaCorrect(fac1 * invGammaCorrect(*rt1) + fac2 * invGammaCorrect(*rt2));
972 
973       rt1++;
974       rt2++;
975       rt++;
976     }
977   }
978 }
979 
gammacross_init_execution(const SeqRenderData * context,ImBuf * ibuf1,ImBuf * ibuf2,ImBuf * ibuf3)980 static struct ImBuf *gammacross_init_execution(const SeqRenderData *context,
981                                                ImBuf *ibuf1,
982                                                ImBuf *ibuf2,
983                                                ImBuf *ibuf3)
984 {
985   ImBuf *out = prepare_effect_imbufs(context, ibuf1, ibuf2, ibuf3);
986   build_gammatabs();
987 
988   return out;
989 }
990 
do_gammacross_effect(const SeqRenderData * context,Sequence * UNUSED (seq),float UNUSED (cfra),float facf0,float facf1,ImBuf * ibuf1,ImBuf * ibuf2,ImBuf * UNUSED (ibuf3),int start_line,int total_lines,ImBuf * out)991 static void do_gammacross_effect(const SeqRenderData *context,
992                                  Sequence *UNUSED(seq),
993                                  float UNUSED(cfra),
994                                  float facf0,
995                                  float facf1,
996                                  ImBuf *ibuf1,
997                                  ImBuf *ibuf2,
998                                  ImBuf *UNUSED(ibuf3),
999                                  int start_line,
1000                                  int total_lines,
1001                                  ImBuf *out)
1002 {
1003   if (out->rect_float) {
1004     float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
1005 
1006     slice_get_float_buffers(
1007         context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
1008 
1009     do_gammacross_effect_float(facf0, facf1, context->rectx, total_lines, rect1, rect2, rect_out);
1010   }
1011   else {
1012     unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
1013 
1014     slice_get_byte_buffers(
1015         context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
1016 
1017     do_gammacross_effect_byte(facf0, facf1, context->rectx, total_lines, rect1, rect2, rect_out);
1018   }
1019 }
1020 
1021 /*********************** Add *************************/
1022 
do_add_effect_byte(float facf0,float facf1,int x,int y,unsigned char * rect1,unsigned char * rect2,unsigned char * out)1023 static void do_add_effect_byte(float facf0,
1024                                float facf1,
1025                                int x,
1026                                int y,
1027                                unsigned char *rect1,
1028                                unsigned char *rect2,
1029                                unsigned char *out)
1030 {
1031   int xo, fac1, fac3;
1032   unsigned char *cp1, *cp2, *rt;
1033 
1034   xo = x;
1035   cp1 = rect1;
1036   cp2 = rect2;
1037   rt = out;
1038 
1039   fac1 = (int)(256.0f * facf0);
1040   fac3 = (int)(256.0f * facf1);
1041 
1042   while (y--) {
1043     x = xo;
1044 
1045     while (x--) {
1046       const int m = fac1 * (int)cp2[3];
1047       rt[0] = min_ii(cp1[0] + ((m * cp2[0]) >> 16), 255);
1048       rt[1] = min_ii(cp1[1] + ((m * cp2[1]) >> 16), 255);
1049       rt[2] = min_ii(cp1[2] + ((m * cp2[2]) >> 16), 255);
1050       rt[3] = cp1[3];
1051 
1052       cp1 += 4;
1053       cp2 += 4;
1054       rt += 4;
1055     }
1056 
1057     if (y == 0) {
1058       break;
1059     }
1060     y--;
1061 
1062     x = xo;
1063     while (x--) {
1064       const int m = fac3 * (int)cp2[3];
1065       rt[0] = min_ii(cp1[0] + ((m * cp2[0]) >> 16), 255);
1066       rt[1] = min_ii(cp1[1] + ((m * cp2[1]) >> 16), 255);
1067       rt[2] = min_ii(cp1[2] + ((m * cp2[2]) >> 16), 255);
1068       rt[3] = cp1[3];
1069 
1070       cp1 += 4;
1071       cp2 += 4;
1072       rt += 4;
1073     }
1074   }
1075 }
1076 
do_add_effect_float(float facf0,float facf1,int x,int y,float * rect1,float * rect2,float * out)1077 static void do_add_effect_float(
1078     float facf0, float facf1, int x, int y, float *rect1, float *rect2, float *out)
1079 {
1080   int xo;
1081   float fac1, fac3;
1082   float *rt1, *rt2, *rt;
1083 
1084   xo = x;
1085   rt1 = rect1;
1086   rt2 = rect2;
1087   rt = out;
1088 
1089   fac1 = facf0;
1090   fac3 = facf1;
1091 
1092   while (y--) {
1093     x = xo;
1094     while (x--) {
1095       const float m = (1.0f - (rt1[3] * (1.0f - fac1))) * rt2[3];
1096       rt[0] = rt1[0] + m * rt2[0];
1097       rt[1] = rt1[1] + m * rt2[1];
1098       rt[2] = rt1[2] + m * rt2[2];
1099       rt[3] = rt1[3];
1100 
1101       rt1 += 4;
1102       rt2 += 4;
1103       rt += 4;
1104     }
1105 
1106     if (y == 0) {
1107       break;
1108     }
1109     y--;
1110 
1111     x = xo;
1112     while (x--) {
1113       const float m = (1.0f - (rt1[3] * (1.0f - fac3))) * rt2[3];
1114       rt[0] = rt1[0] + m * rt2[0];
1115       rt[1] = rt1[1] + m * rt2[1];
1116       rt[2] = rt1[2] + m * rt2[2];
1117       rt[3] = rt1[3];
1118 
1119       rt1 += 4;
1120       rt2 += 4;
1121       rt += 4;
1122     }
1123   }
1124 }
1125 
do_add_effect(const SeqRenderData * context,Sequence * UNUSED (seq),float UNUSED (cfra),float facf0,float facf1,ImBuf * ibuf1,ImBuf * ibuf2,ImBuf * UNUSED (ibuf3),int start_line,int total_lines,ImBuf * out)1126 static void do_add_effect(const SeqRenderData *context,
1127                           Sequence *UNUSED(seq),
1128                           float UNUSED(cfra),
1129                           float facf0,
1130                           float facf1,
1131                           ImBuf *ibuf1,
1132                           ImBuf *ibuf2,
1133                           ImBuf *UNUSED(ibuf3),
1134                           int start_line,
1135                           int total_lines,
1136                           ImBuf *out)
1137 {
1138   if (out->rect_float) {
1139     float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
1140 
1141     slice_get_float_buffers(
1142         context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
1143 
1144     do_add_effect_float(facf0, facf1, context->rectx, total_lines, rect1, rect2, rect_out);
1145   }
1146   else {
1147     unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
1148 
1149     slice_get_byte_buffers(
1150         context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
1151 
1152     do_add_effect_byte(facf0, facf1, context->rectx, total_lines, rect1, rect2, rect_out);
1153   }
1154 }
1155 
1156 /*********************** Sub *************************/
1157 
do_sub_effect_byte(float facf0,float facf1,int x,int y,unsigned char * rect1,unsigned char * rect2,unsigned char * out)1158 static void do_sub_effect_byte(float facf0,
1159                                float facf1,
1160                                int x,
1161                                int y,
1162                                unsigned char *rect1,
1163                                unsigned char *rect2,
1164                                unsigned char *out)
1165 {
1166   int xo, fac1, fac3;
1167   unsigned char *cp1, *cp2, *rt;
1168 
1169   xo = x;
1170   cp1 = rect1;
1171   cp2 = rect2;
1172   rt = out;
1173 
1174   fac1 = (int)(256.0f * facf0);
1175   fac3 = (int)(256.0f * facf1);
1176 
1177   while (y--) {
1178     x = xo;
1179     while (x--) {
1180       const int m = fac1 * (int)cp2[3];
1181       rt[0] = max_ii(cp1[0] - ((m * cp2[0]) >> 16), 0);
1182       rt[1] = max_ii(cp1[1] - ((m * cp2[1]) >> 16), 0);
1183       rt[2] = max_ii(cp1[2] - ((m * cp2[2]) >> 16), 0);
1184       rt[3] = cp1[3];
1185 
1186       cp1 += 4;
1187       cp2 += 4;
1188       rt += 4;
1189     }
1190 
1191     if (y == 0) {
1192       break;
1193     }
1194     y--;
1195 
1196     x = xo;
1197     while (x--) {
1198       const int m = fac3 * (int)cp2[3];
1199       rt[0] = max_ii(cp1[0] - ((m * cp2[0]) >> 16), 0);
1200       rt[1] = max_ii(cp1[1] - ((m * cp2[1]) >> 16), 0);
1201       rt[2] = max_ii(cp1[2] - ((m * cp2[2]) >> 16), 0);
1202       rt[3] = cp1[3];
1203 
1204       cp1 += 4;
1205       cp2 += 4;
1206       rt += 4;
1207     }
1208   }
1209 }
1210 
do_sub_effect_float(float UNUSED (facf0),float facf1,int x,int y,float * rect1,float * rect2,float * out)1211 static void do_sub_effect_float(
1212     float UNUSED(facf0), float facf1, int x, int y, float *rect1, float *rect2, float *out)
1213 {
1214   int xo;
1215   float /* fac1, */ fac3_inv;
1216   float *rt1, *rt2, *rt;
1217 
1218   xo = x;
1219   rt1 = rect1;
1220   rt2 = rect2;
1221   rt = out;
1222 
1223   /* UNUSED */
1224   // fac1 = facf0;
1225   fac3_inv = 1.0f - facf1;
1226 
1227   while (y--) {
1228     x = xo;
1229     while (x--) {
1230       const float m = (1.0f - (rt1[3] * fac3_inv)) * rt2[3];
1231       rt[0] = max_ff(rt1[0] - m * rt2[0], 0.0f);
1232       rt[1] = max_ff(rt1[1] - m * rt2[1], 0.0f);
1233       rt[2] = max_ff(rt1[2] - m * rt2[2], 0.0f);
1234       rt[3] = rt1[3];
1235 
1236       rt1 += 4;
1237       rt2 += 4;
1238       rt += 4;
1239     }
1240 
1241     if (y == 0) {
1242       break;
1243     }
1244     y--;
1245 
1246     x = xo;
1247     while (x--) {
1248       const float m = (1.0f - (rt1[3] * fac3_inv)) * rt2[3];
1249       rt[0] = max_ff(rt1[0] - m * rt2[0], 0.0f);
1250       rt[1] = max_ff(rt1[1] - m * rt2[1], 0.0f);
1251       rt[2] = max_ff(rt1[2] - m * rt2[2], 0.0f);
1252       rt[3] = rt1[3];
1253 
1254       rt1 += 4;
1255       rt2 += 4;
1256       rt += 4;
1257     }
1258   }
1259 }
1260 
do_sub_effect(const SeqRenderData * context,Sequence * UNUSED (seq),float UNUSED (cfra),float facf0,float facf1,ImBuf * ibuf1,ImBuf * ibuf2,ImBuf * UNUSED (ibuf3),int start_line,int total_lines,ImBuf * out)1261 static void do_sub_effect(const SeqRenderData *context,
1262                           Sequence *UNUSED(seq),
1263                           float UNUSED(cfra),
1264                           float facf0,
1265                           float facf1,
1266                           ImBuf *ibuf1,
1267                           ImBuf *ibuf2,
1268                           ImBuf *UNUSED(ibuf3),
1269                           int start_line,
1270                           int total_lines,
1271                           ImBuf *out)
1272 {
1273   if (out->rect_float) {
1274     float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
1275 
1276     slice_get_float_buffers(
1277         context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
1278 
1279     do_sub_effect_float(facf0, facf1, context->rectx, total_lines, rect1, rect2, rect_out);
1280   }
1281   else {
1282     unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
1283 
1284     slice_get_byte_buffers(
1285         context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
1286 
1287     do_sub_effect_byte(facf0, facf1, context->rectx, total_lines, rect1, rect2, rect_out);
1288   }
1289 }
1290 
1291 /*********************** Drop *************************/
1292 
1293 /* Must be > 0 or add precopy, etc to the function */
1294 #define XOFF 8
1295 #define YOFF 8
1296 
do_drop_effect_byte(float facf0,float facf1,int x,int y,unsigned char * rect2i,unsigned char * rect1i,unsigned char * outi)1297 static void do_drop_effect_byte(float facf0,
1298                                 float facf1,
1299                                 int x,
1300                                 int y,
1301                                 unsigned char *rect2i,
1302                                 unsigned char *rect1i,
1303                                 unsigned char *outi)
1304 {
1305   int temp, fac, fac1, fac2;
1306   unsigned char *rt1, *rt2, *out;
1307   int field = 1;
1308 
1309   const int width = x;
1310   const int height = y;
1311   const int xoff = min_ii(XOFF, width);
1312   const int yoff = min_ii(YOFF, height);
1313 
1314   fac1 = (int)(70.0f * facf0);
1315   fac2 = (int)(70.0f * facf1);
1316 
1317   rt2 = rect2i + yoff * 4 * width;
1318   rt1 = rect1i;
1319   out = outi;
1320   for (y = 0; y < height - yoff; y++) {
1321     if (field) {
1322       fac = fac1;
1323     }
1324     else {
1325       fac = fac2;
1326     }
1327     field = !field;
1328 
1329     memcpy(out, rt1, sizeof(*out) * xoff * 4);
1330     rt1 += xoff * 4;
1331     out += xoff * 4;
1332 
1333     for (x = xoff; x < width; x++) {
1334       temp = ((fac * rt2[3]) >> 8);
1335 
1336       *(out++) = MAX2(0, *rt1 - temp);
1337       rt1++;
1338       *(out++) = MAX2(0, *rt1 - temp);
1339       rt1++;
1340       *(out++) = MAX2(0, *rt1 - temp);
1341       rt1++;
1342       *(out++) = MAX2(0, *rt1 - temp);
1343       rt1++;
1344       rt2 += 4;
1345     }
1346     rt2 += xoff * 4;
1347   }
1348   memcpy(out, rt1, sizeof(*out) * yoff * 4 * width);
1349 }
1350 
do_drop_effect_float(float facf0,float facf1,int x,int y,float * rect2i,float * rect1i,float * outi)1351 static void do_drop_effect_float(
1352     float facf0, float facf1, int x, int y, float *rect2i, float *rect1i, float *outi)
1353 {
1354   float temp, fac, fac1, fac2;
1355   float *rt1, *rt2, *out;
1356   int field = 1;
1357 
1358   const int width = x;
1359   const int height = y;
1360   const int xoff = min_ii(XOFF, width);
1361   const int yoff = min_ii(YOFF, height);
1362 
1363   fac1 = 70.0f * facf0;
1364   fac2 = 70.0f * facf1;
1365 
1366   rt2 = rect2i + yoff * 4 * width;
1367   rt1 = rect1i;
1368   out = outi;
1369   for (y = 0; y < height - yoff; y++) {
1370     if (field) {
1371       fac = fac1;
1372     }
1373     else {
1374       fac = fac2;
1375     }
1376     field = !field;
1377 
1378     memcpy(out, rt1, sizeof(*out) * xoff * 4);
1379     rt1 += xoff * 4;
1380     out += xoff * 4;
1381 
1382     for (x = xoff; x < width; x++) {
1383       temp = fac * rt2[3];
1384 
1385       *(out++) = MAX2(0.0f, *rt1 - temp);
1386       rt1++;
1387       *(out++) = MAX2(0.0f, *rt1 - temp);
1388       rt1++;
1389       *(out++) = MAX2(0.0f, *rt1 - temp);
1390       rt1++;
1391       *(out++) = MAX2(0.0f, *rt1 - temp);
1392       rt1++;
1393       rt2 += 4;
1394     }
1395     rt2 += xoff * 4;
1396   }
1397   memcpy(out, rt1, sizeof(*out) * yoff * 4 * width);
1398 }
1399 
1400 /*********************** Mul *************************/
1401 
do_mul_effect_byte(float facf0,float facf1,int x,int y,unsigned char * rect1,unsigned char * rect2,unsigned char * out)1402 static void do_mul_effect_byte(float facf0,
1403                                float facf1,
1404                                int x,
1405                                int y,
1406                                unsigned char *rect1,
1407                                unsigned char *rect2,
1408                                unsigned char *out)
1409 {
1410   int xo, fac1, fac3;
1411   unsigned char *rt1, *rt2, *rt;
1412 
1413   xo = x;
1414   rt1 = rect1;
1415   rt2 = rect2;
1416   rt = out;
1417 
1418   fac1 = (int)(256.0f * facf0);
1419   fac3 = (int)(256.0f * facf1);
1420 
1421   /* formula:
1422    * fac * (a * b) + (1 - fac) * a  => fac * a * (b - 1) + axaux = c * px + py * s; //+centx
1423    * yaux = -s * px + c * py; //+centy
1424    */
1425 
1426   while (y--) {
1427 
1428     x = xo;
1429     while (x--) {
1430 
1431       rt[0] = rt1[0] + ((fac1 * rt1[0] * (rt2[0] - 255)) >> 16);
1432       rt[1] = rt1[1] + ((fac1 * rt1[1] * (rt2[1] - 255)) >> 16);
1433       rt[2] = rt1[2] + ((fac1 * rt1[2] * (rt2[2] - 255)) >> 16);
1434       rt[3] = rt1[3] + ((fac1 * rt1[3] * (rt2[3] - 255)) >> 16);
1435 
1436       rt1 += 4;
1437       rt2 += 4;
1438       rt += 4;
1439     }
1440 
1441     if (y == 0) {
1442       break;
1443     }
1444     y--;
1445 
1446     x = xo;
1447     while (x--) {
1448 
1449       rt[0] = rt1[0] + ((fac3 * rt1[0] * (rt2[0] - 255)) >> 16);
1450       rt[1] = rt1[1] + ((fac3 * rt1[1] * (rt2[1] - 255)) >> 16);
1451       rt[2] = rt1[2] + ((fac3 * rt1[2] * (rt2[2] - 255)) >> 16);
1452       rt[3] = rt1[3] + ((fac3 * rt1[3] * (rt2[3] - 255)) >> 16);
1453 
1454       rt1 += 4;
1455       rt2 += 4;
1456       rt += 4;
1457     }
1458   }
1459 }
1460 
do_mul_effect_float(float facf0,float facf1,int x,int y,float * rect1,float * rect2,float * out)1461 static void do_mul_effect_float(
1462     float facf0, float facf1, int x, int y, float *rect1, float *rect2, float *out)
1463 {
1464   int xo;
1465   float fac1, fac3;
1466   float *rt1, *rt2, *rt;
1467 
1468   xo = x;
1469   rt1 = rect1;
1470   rt2 = rect2;
1471   rt = out;
1472 
1473   fac1 = facf0;
1474   fac3 = facf1;
1475 
1476   /* formula:
1477    * fac * (a * b) + (1 - fac) * a  =>  fac * a * (b - 1) + a
1478    */
1479 
1480   while (y--) {
1481     x = xo;
1482     while (x--) {
1483       rt[0] = rt1[0] + fac1 * rt1[0] * (rt2[0] - 1.0f);
1484       rt[1] = rt1[1] + fac1 * rt1[1] * (rt2[1] - 1.0f);
1485       rt[2] = rt1[2] + fac1 * rt1[2] * (rt2[2] - 1.0f);
1486       rt[3] = rt1[3] + fac1 * rt1[3] * (rt2[3] - 1.0f);
1487 
1488       rt1 += 4;
1489       rt2 += 4;
1490       rt += 4;
1491     }
1492 
1493     if (y == 0) {
1494       break;
1495     }
1496     y--;
1497 
1498     x = xo;
1499     while (x--) {
1500       rt[0] = rt1[0] + fac3 * rt1[0] * (rt2[0] - 1.0f);
1501       rt[1] = rt1[1] + fac3 * rt1[1] * (rt2[1] - 1.0f);
1502       rt[2] = rt1[2] + fac3 * rt1[2] * (rt2[2] - 1.0f);
1503       rt[3] = rt1[3] + fac3 * rt1[3] * (rt2[3] - 1.0f);
1504 
1505       rt1 += 4;
1506       rt2 += 4;
1507       rt += 4;
1508     }
1509   }
1510 }
1511 
do_mul_effect(const SeqRenderData * context,Sequence * UNUSED (seq),float UNUSED (cfra),float facf0,float facf1,ImBuf * ibuf1,ImBuf * ibuf2,ImBuf * UNUSED (ibuf3),int start_line,int total_lines,ImBuf * out)1512 static void do_mul_effect(const SeqRenderData *context,
1513                           Sequence *UNUSED(seq),
1514                           float UNUSED(cfra),
1515                           float facf0,
1516                           float facf1,
1517                           ImBuf *ibuf1,
1518                           ImBuf *ibuf2,
1519                           ImBuf *UNUSED(ibuf3),
1520                           int start_line,
1521                           int total_lines,
1522                           ImBuf *out)
1523 {
1524   if (out->rect_float) {
1525     float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
1526 
1527     slice_get_float_buffers(
1528         context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
1529 
1530     do_mul_effect_float(facf0, facf1, context->rectx, total_lines, rect1, rect2, rect_out);
1531   }
1532   else {
1533     unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
1534 
1535     slice_get_byte_buffers(
1536         context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
1537 
1538     do_mul_effect_byte(facf0, facf1, context->rectx, total_lines, rect1, rect2, rect_out);
1539   }
1540 }
1541 
1542 /*********************** Blend Mode ***************************************/
1543 typedef void (*IMB_blend_func_byte)(unsigned char *dst,
1544                                     const unsigned char *src1,
1545                                     const unsigned char *src2);
1546 typedef void (*IMB_blend_func_float)(float *dst, const float *src1, const float *src2);
1547 
apply_blend_function_byte(float facf0,float facf1,int x,int y,unsigned char * rect1,unsigned char * rect2,unsigned char * out,IMB_blend_func_byte blend_function)1548 BLI_INLINE void apply_blend_function_byte(float facf0,
1549                                           float facf1,
1550                                           int x,
1551                                           int y,
1552                                           unsigned char *rect1,
1553                                           unsigned char *rect2,
1554                                           unsigned char *out,
1555                                           IMB_blend_func_byte blend_function)
1556 {
1557   int xo;
1558   unsigned char *rt1, *rt2, *rt;
1559   unsigned int achannel;
1560   xo = x;
1561   rt1 = rect1;
1562   rt2 = rect2;
1563   rt = out;
1564   while (y--) {
1565     for (x = xo; x > 0; x--) {
1566       achannel = rt1[3];
1567       rt1[3] = (unsigned int)achannel * facf0;
1568       blend_function(rt, rt1, rt2);
1569       rt1[3] = achannel;
1570       rt[3] = rt1[3];
1571       rt1 += 4;
1572       rt2 += 4;
1573       rt += 4;
1574     }
1575     if (y == 0) {
1576       break;
1577     }
1578     y--;
1579     for (x = xo; x > 0; x--) {
1580       achannel = rt1[3];
1581       rt1[3] = (unsigned int)achannel * facf1;
1582       blend_function(rt, rt1, rt2);
1583       rt1[3] = achannel;
1584       rt[3] = rt1[3];
1585       rt1 += 4;
1586       rt2 += 4;
1587       rt += 4;
1588     }
1589   }
1590 }
1591 
apply_blend_function_float(float facf0,float facf1,int x,int y,float * rect1,float * rect2,float * out,IMB_blend_func_float blend_function)1592 BLI_INLINE void apply_blend_function_float(float facf0,
1593                                            float facf1,
1594                                            int x,
1595                                            int y,
1596                                            float *rect1,
1597                                            float *rect2,
1598                                            float *out,
1599                                            IMB_blend_func_float blend_function)
1600 {
1601   int xo;
1602   float *rt1, *rt2, *rt;
1603   float achannel;
1604   xo = x;
1605   rt1 = rect1;
1606   rt2 = rect2;
1607   rt = out;
1608   while (y--) {
1609     for (x = xo; x > 0; x--) {
1610       achannel = rt1[3];
1611       rt1[3] = achannel * facf0;
1612       blend_function(rt, rt1, rt2);
1613       rt1[3] = achannel;
1614       rt[3] = rt1[3];
1615       rt1 += 4;
1616       rt2 += 4;
1617       rt += 4;
1618     }
1619     if (y == 0) {
1620       break;
1621     }
1622     y--;
1623     for (x = xo; x > 0; x--) {
1624       achannel = rt1[3];
1625       rt1[3] = achannel * facf1;
1626       blend_function(rt, rt1, rt2);
1627       rt1[3] = achannel;
1628       rt[3] = rt1[3];
1629       rt1 += 4;
1630       rt2 += 4;
1631       rt += 4;
1632     }
1633   }
1634 }
1635 
do_blend_effect_float(float facf0,float facf1,int x,int y,float * rect1,float * rect2,int btype,float * out)1636 static void do_blend_effect_float(
1637     float facf0, float facf1, int x, int y, float *rect1, float *rect2, int btype, float *out)
1638 {
1639   switch (btype) {
1640     case SEQ_TYPE_ADD:
1641       apply_blend_function_float(facf0, facf1, x, y, rect1, rect2, out, blend_color_add_float);
1642       break;
1643     case SEQ_TYPE_SUB:
1644       apply_blend_function_float(facf0, facf1, x, y, rect1, rect2, out, blend_color_sub_float);
1645       break;
1646     case SEQ_TYPE_MUL:
1647       apply_blend_function_float(facf0, facf1, x, y, rect1, rect2, out, blend_color_mul_float);
1648       break;
1649     case SEQ_TYPE_DARKEN:
1650       apply_blend_function_float(facf0, facf1, x, y, rect1, rect2, out, blend_color_darken_float);
1651       break;
1652     case SEQ_TYPE_COLOR_BURN:
1653       apply_blend_function_float(facf0, facf1, x, y, rect1, rect2, out, blend_color_burn_float);
1654       break;
1655     case SEQ_TYPE_LINEAR_BURN:
1656       apply_blend_function_float(
1657           facf0, facf1, x, y, rect1, rect2, out, blend_color_linearburn_float);
1658       break;
1659     case SEQ_TYPE_SCREEN:
1660       apply_blend_function_float(facf0, facf1, x, y, rect1, rect2, out, blend_color_screen_float);
1661       break;
1662     case SEQ_TYPE_LIGHTEN:
1663       apply_blend_function_float(facf0, facf1, x, y, rect1, rect2, out, blend_color_lighten_float);
1664       break;
1665     case SEQ_TYPE_DODGE:
1666       apply_blend_function_float(facf0, facf1, x, y, rect1, rect2, out, blend_color_dodge_float);
1667       break;
1668     case SEQ_TYPE_OVERLAY:
1669       apply_blend_function_float(facf0, facf1, x, y, rect1, rect2, out, blend_color_overlay_float);
1670       break;
1671     case SEQ_TYPE_SOFT_LIGHT:
1672       apply_blend_function_float(
1673           facf0, facf1, x, y, rect1, rect2, out, blend_color_softlight_float);
1674       break;
1675     case SEQ_TYPE_HARD_LIGHT:
1676       apply_blend_function_float(
1677           facf0, facf1, x, y, rect1, rect2, out, blend_color_hardlight_float);
1678       break;
1679     case SEQ_TYPE_PIN_LIGHT:
1680       apply_blend_function_float(
1681           facf0, facf1, x, y, rect1, rect2, out, blend_color_pinlight_float);
1682       break;
1683     case SEQ_TYPE_LIN_LIGHT:
1684       apply_blend_function_float(
1685           facf0, facf1, x, y, rect1, rect2, out, blend_color_linearlight_float);
1686       break;
1687     case SEQ_TYPE_VIVID_LIGHT:
1688       apply_blend_function_float(
1689           facf0, facf1, x, y, rect1, rect2, out, blend_color_vividlight_float);
1690       break;
1691     case SEQ_TYPE_BLEND_COLOR:
1692       apply_blend_function_float(facf0, facf1, x, y, rect1, rect2, out, blend_color_color_float);
1693       break;
1694     case SEQ_TYPE_HUE:
1695       apply_blend_function_float(facf0, facf1, x, y, rect1, rect2, out, blend_color_hue_float);
1696       break;
1697     case SEQ_TYPE_SATURATION:
1698       apply_blend_function_float(
1699           facf0, facf1, x, y, rect1, rect2, out, blend_color_saturation_float);
1700       break;
1701     case SEQ_TYPE_VALUE:
1702       apply_blend_function_float(
1703           facf0, facf1, x, y, rect1, rect2, out, blend_color_luminosity_float);
1704       break;
1705     case SEQ_TYPE_DIFFERENCE:
1706       apply_blend_function_float(
1707           facf0, facf1, x, y, rect1, rect2, out, blend_color_difference_float);
1708       break;
1709     case SEQ_TYPE_EXCLUSION:
1710       apply_blend_function_float(
1711           facf0, facf1, x, y, rect1, rect2, out, blend_color_exclusion_float);
1712       break;
1713     default:
1714       break;
1715   }
1716 }
1717 
do_blend_effect_byte(float facf0,float facf1,int x,int y,unsigned char * rect1,unsigned char * rect2,int btype,unsigned char * out)1718 static void do_blend_effect_byte(float facf0,
1719                                  float facf1,
1720                                  int x,
1721                                  int y,
1722                                  unsigned char *rect1,
1723                                  unsigned char *rect2,
1724                                  int btype,
1725                                  unsigned char *out)
1726 {
1727   switch (btype) {
1728     case SEQ_TYPE_ADD:
1729       apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_add_byte);
1730       break;
1731     case SEQ_TYPE_SUB:
1732       apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_sub_byte);
1733       break;
1734     case SEQ_TYPE_MUL:
1735       apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_mul_byte);
1736       break;
1737     case SEQ_TYPE_DARKEN:
1738       apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_darken_byte);
1739       break;
1740     case SEQ_TYPE_COLOR_BURN:
1741       apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_burn_byte);
1742       break;
1743     case SEQ_TYPE_LINEAR_BURN:
1744       apply_blend_function_byte(
1745           facf0, facf1, x, y, rect1, rect2, out, blend_color_linearburn_byte);
1746       break;
1747     case SEQ_TYPE_SCREEN:
1748       apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_screen_byte);
1749       break;
1750     case SEQ_TYPE_LIGHTEN:
1751       apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_lighten_byte);
1752       break;
1753     case SEQ_TYPE_DODGE:
1754       apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_dodge_byte);
1755       break;
1756     case SEQ_TYPE_OVERLAY:
1757       apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_overlay_byte);
1758       break;
1759     case SEQ_TYPE_SOFT_LIGHT:
1760       apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_softlight_byte);
1761       break;
1762     case SEQ_TYPE_HARD_LIGHT:
1763       apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_hardlight_byte);
1764       break;
1765     case SEQ_TYPE_PIN_LIGHT:
1766       apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_pinlight_byte);
1767       break;
1768     case SEQ_TYPE_LIN_LIGHT:
1769       apply_blend_function_byte(
1770           facf0, facf1, x, y, rect1, rect2, out, blend_color_linearlight_byte);
1771       break;
1772     case SEQ_TYPE_VIVID_LIGHT:
1773       apply_blend_function_byte(
1774           facf0, facf1, x, y, rect1, rect2, out, blend_color_vividlight_byte);
1775       break;
1776     case SEQ_TYPE_BLEND_COLOR:
1777       apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_color_byte);
1778       break;
1779     case SEQ_TYPE_HUE:
1780       apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_hue_byte);
1781       break;
1782     case SEQ_TYPE_SATURATION:
1783       apply_blend_function_byte(
1784           facf0, facf1, x, y, rect1, rect2, out, blend_color_saturation_byte);
1785       break;
1786     case SEQ_TYPE_VALUE:
1787       apply_blend_function_byte(
1788           facf0, facf1, x, y, rect1, rect2, out, blend_color_luminosity_byte);
1789       break;
1790     case SEQ_TYPE_DIFFERENCE:
1791       apply_blend_function_byte(
1792           facf0, facf1, x, y, rect1, rect2, out, blend_color_difference_byte);
1793       break;
1794     case SEQ_TYPE_EXCLUSION:
1795       apply_blend_function_byte(facf0, facf1, x, y, rect1, rect2, out, blend_color_exclusion_byte);
1796       break;
1797     default:
1798       break;
1799   }
1800 }
1801 
do_blend_mode_effect(const SeqRenderData * context,Sequence * seq,float UNUSED (cfra),float facf0,float facf1,ImBuf * ibuf1,ImBuf * ibuf2,ImBuf * UNUSED (ibuf3),int start_line,int total_lines,ImBuf * out)1802 static void do_blend_mode_effect(const SeqRenderData *context,
1803                                  Sequence *seq,
1804                                  float UNUSED(cfra),
1805                                  float facf0,
1806                                  float facf1,
1807                                  ImBuf *ibuf1,
1808                                  ImBuf *ibuf2,
1809                                  ImBuf *UNUSED(ibuf3),
1810                                  int start_line,
1811                                  int total_lines,
1812                                  ImBuf *out)
1813 {
1814   if (out->rect_float) {
1815     float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
1816     slice_get_float_buffers(
1817         context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
1818     do_blend_effect_float(
1819         facf0, facf1, context->rectx, total_lines, rect1, rect2, seq->blend_mode, rect_out);
1820   }
1821   else {
1822     unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
1823     slice_get_byte_buffers(
1824         context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
1825     do_blend_effect_byte(
1826         facf0, facf1, context->rectx, total_lines, rect1, rect2, seq->blend_mode, rect_out);
1827   }
1828 }
1829 /*********************** Color Mix Effect  *************************/
init_colormix_effect(Sequence * seq)1830 static void init_colormix_effect(Sequence *seq)
1831 {
1832   ColorMixVars *data;
1833 
1834   if (seq->effectdata) {
1835     MEM_freeN(seq->effectdata);
1836   }
1837   seq->effectdata = MEM_callocN(sizeof(ColorMixVars), "colormixvars");
1838   data = (ColorMixVars *)seq->effectdata;
1839   data->blend_effect = SEQ_TYPE_OVERLAY;
1840   data->factor = 1.0f;
1841 }
1842 
do_colormix_effect(const SeqRenderData * context,Sequence * seq,float UNUSED (cfra),float UNUSED (facf0),float UNUSED (facf1),ImBuf * ibuf1,ImBuf * ibuf2,ImBuf * UNUSED (ibuf3),int start_line,int total_lines,ImBuf * out)1843 static void do_colormix_effect(const SeqRenderData *context,
1844                                Sequence *seq,
1845                                float UNUSED(cfra),
1846                                float UNUSED(facf0),
1847                                float UNUSED(facf1),
1848                                ImBuf *ibuf1,
1849                                ImBuf *ibuf2,
1850                                ImBuf *UNUSED(ibuf3),
1851                                int start_line,
1852                                int total_lines,
1853                                ImBuf *out)
1854 {
1855   float facf;
1856 
1857   ColorMixVars *data = seq->effectdata;
1858   facf = data->factor;
1859 
1860   if (out->rect_float) {
1861     float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
1862     slice_get_float_buffers(
1863         context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
1864     do_blend_effect_float(
1865         facf, facf, context->rectx, total_lines, rect1, rect2, data->blend_effect, rect_out);
1866   }
1867   else {
1868     unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
1869     slice_get_byte_buffers(
1870         context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
1871     do_blend_effect_byte(
1872         facf, facf, context->rectx, total_lines, rect1, rect2, data->blend_effect, rect_out);
1873   }
1874 }
1875 
1876 /*********************** Wipe *************************/
1877 
1878 typedef struct WipeZone {
1879   float angle;
1880   int flip;
1881   int xo, yo;
1882   int width;
1883   float pythangle;
1884 } WipeZone;
1885 
precalc_wipe_zone(WipeZone * wipezone,WipeVars * wipe,int xo,int yo)1886 static void precalc_wipe_zone(WipeZone *wipezone, WipeVars *wipe, int xo, int yo)
1887 {
1888   wipezone->flip = (wipe->angle < 0.0f);
1889   wipezone->angle = tanf(fabsf(wipe->angle));
1890   wipezone->xo = xo;
1891   wipezone->yo = yo;
1892   wipezone->width = (int)(wipe->edgeWidth * ((xo + yo) / 2.0f));
1893   wipezone->pythangle = 1.0f / sqrtf(wipezone->angle * wipezone->angle + 1.0f);
1894 }
1895 
1896 /* This function calculates the blur band for the wipe effects */
in_band(float width,float dist,int side,int dir)1897 static float in_band(float width, float dist, int side, int dir)
1898 {
1899   float alpha;
1900 
1901   if (width == 0) {
1902     return (float)side;
1903   }
1904 
1905   if (width < dist) {
1906     return (float)side;
1907   }
1908 
1909   if (side == 1) {
1910     alpha = (dist + 0.5f * width) / (width);
1911   }
1912   else {
1913     alpha = (0.5f * width - dist) / (width);
1914   }
1915 
1916   if (dir == 0) {
1917     alpha = 1 - alpha;
1918   }
1919 
1920   return alpha;
1921 }
1922 
check_zone(WipeZone * wipezone,int x,int y,Sequence * seq,float facf0)1923 static float check_zone(WipeZone *wipezone, int x, int y, Sequence *seq, float facf0)
1924 {
1925   float posx, posy, hyp, hyp2, angle, hwidth, b1, b2, b3, pointdist;
1926   /* some future stuff */
1927   /* float hyp3, hyp4, b4, b5 */
1928   float temp1, temp2, temp3, temp4; /* some placeholder variables */
1929   int xo = wipezone->xo;
1930   int yo = wipezone->yo;
1931   float halfx = xo * 0.5f;
1932   float halfy = yo * 0.5f;
1933   float widthf, output = 0;
1934   WipeVars *wipe = (WipeVars *)seq->effectdata;
1935   int width;
1936 
1937   if (wipezone->flip) {
1938     x = xo - x;
1939   }
1940   angle = wipezone->angle;
1941 
1942   if (wipe->forward) {
1943     posx = facf0 * xo;
1944     posy = facf0 * yo;
1945   }
1946   else {
1947     posx = xo - facf0 * xo;
1948     posy = yo - facf0 * yo;
1949   }
1950 
1951   switch (wipe->wipetype) {
1952     case DO_SINGLE_WIPE:
1953       width = min_ii(wipezone->width, facf0 * yo);
1954       width = min_ii(width, yo - facf0 * yo);
1955 
1956       if (angle == 0.0f) {
1957         b1 = posy;
1958         b2 = y;
1959         hyp = fabsf(y - posy);
1960       }
1961       else {
1962         b1 = posy - (-angle) * posx;
1963         b2 = y - (-angle) * x;
1964         hyp = fabsf(angle * x + y + (-posy - angle * posx)) * wipezone->pythangle;
1965       }
1966 
1967       if (angle < 0) {
1968         temp1 = b1;
1969         b1 = b2;
1970         b2 = temp1;
1971       }
1972 
1973       if (wipe->forward) {
1974         if (b1 < b2) {
1975           output = in_band(width, hyp, 1, 1);
1976         }
1977         else {
1978           output = in_band(width, hyp, 0, 1);
1979         }
1980       }
1981       else {
1982         if (b1 < b2) {
1983           output = in_band(width, hyp, 0, 1);
1984         }
1985         else {
1986           output = in_band(width, hyp, 1, 1);
1987         }
1988       }
1989       break;
1990 
1991     case DO_DOUBLE_WIPE:
1992       if (!wipe->forward) {
1993         facf0 = 1.0f - facf0; /* Go the other direction */
1994       }
1995 
1996       width = wipezone->width; /* calculate the blur width */
1997       hwidth = width * 0.5f;
1998       if (angle == 0) {
1999         b1 = posy * 0.5f;
2000         b3 = yo - posy * 0.5f;
2001         b2 = y;
2002 
2003         hyp = fabsf(y - posy * 0.5f);
2004         hyp2 = fabsf(y - (yo - posy * 0.5f));
2005       }
2006       else {
2007         b1 = posy * 0.5f - (-angle) * posx * 0.5f;
2008         b3 = (yo - posy * 0.5f) - (-angle) * (xo - posx * 0.5f);
2009         b2 = y - (-angle) * x;
2010 
2011         hyp = fabsf(angle * x + y + (-posy * 0.5f - angle * posx * 0.5f)) * wipezone->pythangle;
2012         hyp2 = fabsf(angle * x + y + (-(yo - posy * 0.5f) - angle * (xo - posx * 0.5f))) *
2013                wipezone->pythangle;
2014       }
2015 
2016       hwidth = min_ff(hwidth, fabsf(b3 - b1) / 2.0f);
2017 
2018       if (b2 < b1 && b2 < b3) {
2019         output = in_band(hwidth, hyp, 0, 1);
2020       }
2021       else if (b2 > b1 && b2 > b3) {
2022         output = in_band(hwidth, hyp2, 0, 1);
2023       }
2024       else {
2025         if (hyp < hwidth && hyp2 > hwidth) {
2026           output = in_band(hwidth, hyp, 1, 1);
2027         }
2028         else if (hyp > hwidth && hyp2 < hwidth) {
2029           output = in_band(hwidth, hyp2, 1, 1);
2030         }
2031         else {
2032           output = in_band(hwidth, hyp2, 1, 1) * in_band(hwidth, hyp, 1, 1);
2033         }
2034       }
2035       if (!wipe->forward) {
2036         output = 1 - output;
2037       }
2038       break;
2039     case DO_CLOCK_WIPE:
2040       /*
2041        * temp1: angle of effect center in rads
2042        * temp2: angle of line through (halfx, halfy) and (x, y) in rads
2043        * temp3: angle of low side of blur
2044        * temp4: angle of high side of blur
2045        */
2046       output = 1.0f - facf0;
2047       widthf = wipe->edgeWidth * 2.0f * (float)M_PI;
2048       temp1 = 2.0f * (float)M_PI * facf0;
2049 
2050       if (wipe->forward) {
2051         temp1 = 2.0f * (float)M_PI - temp1;
2052       }
2053 
2054       x = x - halfx;
2055       y = y - halfy;
2056 
2057       temp2 = asin(abs(y) / hypot(x, y));
2058       if (x <= 0 && y >= 0) {
2059         temp2 = (float)M_PI - temp2;
2060       }
2061       else if (x <= 0 && y <= 0) {
2062         temp2 += (float)M_PI;
2063       }
2064       else if (x >= 0 && y <= 0) {
2065         temp2 = 2.0f * (float)M_PI - temp2;
2066       }
2067 
2068       if (wipe->forward) {
2069         temp3 = temp1 - (widthf * 0.5f) * facf0;
2070         temp4 = temp1 + (widthf * 0.5f) * (1 - facf0);
2071       }
2072       else {
2073         temp3 = temp1 - (widthf * 0.5f) * (1 - facf0);
2074         temp4 = temp1 + (widthf * 0.5f) * facf0;
2075       }
2076       if (temp3 < 0) {
2077         temp3 = 0;
2078       }
2079       if (temp4 > 2.0f * (float)M_PI) {
2080         temp4 = 2.0f * (float)M_PI;
2081       }
2082 
2083       if (temp2 < temp3) {
2084         output = 0;
2085       }
2086       else if (temp2 > temp4) {
2087         output = 1;
2088       }
2089       else {
2090         output = (temp2 - temp3) / (temp4 - temp3);
2091       }
2092       if (x == 0 && y == 0) {
2093         output = 1;
2094       }
2095       if (output != output) {
2096         output = 1;
2097       }
2098       if (wipe->forward) {
2099         output = 1 - output;
2100       }
2101       break;
2102     case DO_IRIS_WIPE:
2103       if (xo > yo) {
2104         yo = xo;
2105       }
2106       else {
2107         xo = yo;
2108       }
2109 
2110       if (!wipe->forward) {
2111         facf0 = 1 - facf0;
2112       }
2113 
2114       width = wipezone->width;
2115       hwidth = width * 0.5f;
2116 
2117       temp1 = (halfx - (halfx)*facf0);
2118       pointdist = hypotf(temp1, temp1);
2119 
2120       temp2 = hypotf(halfx - x, halfy - y);
2121       if (temp2 > pointdist) {
2122         output = in_band(hwidth, fabsf(temp2 - pointdist), 0, 1);
2123       }
2124       else {
2125         output = in_band(hwidth, fabsf(temp2 - pointdist), 1, 1);
2126       }
2127 
2128       if (!wipe->forward) {
2129         output = 1 - output;
2130       }
2131 
2132       break;
2133   }
2134   if (output < 0) {
2135     output = 0;
2136   }
2137   else if (output > 1) {
2138     output = 1;
2139   }
2140   return output;
2141 }
2142 
init_wipe_effect(Sequence * seq)2143 static void init_wipe_effect(Sequence *seq)
2144 {
2145   if (seq->effectdata) {
2146     MEM_freeN(seq->effectdata);
2147   }
2148 
2149   seq->effectdata = MEM_callocN(sizeof(WipeVars), "wipevars");
2150 }
2151 
num_inputs_wipe(void)2152 static int num_inputs_wipe(void)
2153 {
2154   return 2;
2155 }
2156 
free_wipe_effect(Sequence * seq,const bool UNUSED (do_id_user))2157 static void free_wipe_effect(Sequence *seq, const bool UNUSED(do_id_user))
2158 {
2159   if (seq->effectdata) {
2160     MEM_freeN(seq->effectdata);
2161   }
2162 
2163   seq->effectdata = NULL;
2164 }
2165 
copy_wipe_effect(Sequence * dst,Sequence * src,const int UNUSED (flag))2166 static void copy_wipe_effect(Sequence *dst, Sequence *src, const int UNUSED(flag))
2167 {
2168   dst->effectdata = MEM_dupallocN(src->effectdata);
2169 }
2170 
do_wipe_effect_byte(Sequence * seq,float facf0,float UNUSED (facf1),int x,int y,unsigned char * rect1,unsigned char * rect2,unsigned char * out)2171 static void do_wipe_effect_byte(Sequence *seq,
2172                                 float facf0,
2173                                 float UNUSED(facf1),
2174                                 int x,
2175                                 int y,
2176                                 unsigned char *rect1,
2177                                 unsigned char *rect2,
2178                                 unsigned char *out)
2179 {
2180   WipeZone wipezone;
2181   WipeVars *wipe = (WipeVars *)seq->effectdata;
2182   int xo, yo;
2183   unsigned char *cp1, *cp2, *rt;
2184 
2185   precalc_wipe_zone(&wipezone, wipe, x, y);
2186 
2187   cp1 = rect1;
2188   cp2 = rect2;
2189   rt = out;
2190 
2191   xo = x;
2192   yo = y;
2193   for (y = 0; y < yo; y++) {
2194     for (x = 0; x < xo; x++) {
2195       float check = check_zone(&wipezone, x, y, seq, facf0);
2196       if (check) {
2197         if (cp1) {
2198           float rt1[4], rt2[4], tempc[4];
2199 
2200           straight_uchar_to_premul_float(rt1, cp1);
2201           straight_uchar_to_premul_float(rt2, cp2);
2202 
2203           tempc[0] = rt1[0] * check + rt2[0] * (1 - check);
2204           tempc[1] = rt1[1] * check + rt2[1] * (1 - check);
2205           tempc[2] = rt1[2] * check + rt2[2] * (1 - check);
2206           tempc[3] = rt1[3] * check + rt2[3] * (1 - check);
2207 
2208           premul_float_to_straight_uchar(rt, tempc);
2209         }
2210         else {
2211           rt[0] = 0;
2212           rt[1] = 0;
2213           rt[2] = 0;
2214           rt[3] = 255;
2215         }
2216       }
2217       else {
2218         if (cp2) {
2219           rt[0] = cp2[0];
2220           rt[1] = cp2[1];
2221           rt[2] = cp2[2];
2222           rt[3] = cp2[3];
2223         }
2224         else {
2225           rt[0] = 0;
2226           rt[1] = 0;
2227           rt[2] = 0;
2228           rt[3] = 255;
2229         }
2230       }
2231 
2232       rt += 4;
2233       if (cp1 != NULL) {
2234         cp1 += 4;
2235       }
2236       if (cp2 != NULL) {
2237         cp2 += 4;
2238       }
2239     }
2240   }
2241 }
2242 
do_wipe_effect_float(Sequence * seq,float facf0,float UNUSED (facf1),int x,int y,float * rect1,float * rect2,float * out)2243 static void do_wipe_effect_float(Sequence *seq,
2244                                  float facf0,
2245                                  float UNUSED(facf1),
2246                                  int x,
2247                                  int y,
2248                                  float *rect1,
2249                                  float *rect2,
2250                                  float *out)
2251 {
2252   WipeZone wipezone;
2253   WipeVars *wipe = (WipeVars *)seq->effectdata;
2254   int xo, yo;
2255   float *rt1, *rt2, *rt;
2256 
2257   precalc_wipe_zone(&wipezone, wipe, x, y);
2258 
2259   rt1 = rect1;
2260   rt2 = rect2;
2261   rt = out;
2262 
2263   xo = x;
2264   yo = y;
2265   for (y = 0; y < yo; y++) {
2266     for (x = 0; x < xo; x++) {
2267       float check = check_zone(&wipezone, x, y, seq, facf0);
2268       if (check) {
2269         if (rt1) {
2270           rt[0] = rt1[0] * check + rt2[0] * (1 - check);
2271           rt[1] = rt1[1] * check + rt2[1] * (1 - check);
2272           rt[2] = rt1[2] * check + rt2[2] * (1 - check);
2273           rt[3] = rt1[3] * check + rt2[3] * (1 - check);
2274         }
2275         else {
2276           rt[0] = 0;
2277           rt[1] = 0;
2278           rt[2] = 0;
2279           rt[3] = 1.0;
2280         }
2281       }
2282       else {
2283         if (rt2) {
2284           rt[0] = rt2[0];
2285           rt[1] = rt2[1];
2286           rt[2] = rt2[2];
2287           rt[3] = rt2[3];
2288         }
2289         else {
2290           rt[0] = 0;
2291           rt[1] = 0;
2292           rt[2] = 0;
2293           rt[3] = 1.0;
2294         }
2295       }
2296 
2297       rt += 4;
2298       if (rt1 != NULL) {
2299         rt1 += 4;
2300       }
2301       if (rt2 != NULL) {
2302         rt2 += 4;
2303       }
2304     }
2305   }
2306 }
2307 
do_wipe_effect(const SeqRenderData * context,Sequence * seq,float UNUSED (cfra),float facf0,float facf1,ImBuf * ibuf1,ImBuf * ibuf2,ImBuf * ibuf3)2308 static ImBuf *do_wipe_effect(const SeqRenderData *context,
2309                              Sequence *seq,
2310                              float UNUSED(cfra),
2311                              float facf0,
2312                              float facf1,
2313                              ImBuf *ibuf1,
2314                              ImBuf *ibuf2,
2315                              ImBuf *ibuf3)
2316 {
2317   ImBuf *out = prepare_effect_imbufs(context, ibuf1, ibuf2, ibuf3);
2318 
2319   if (out->rect_float) {
2320     do_wipe_effect_float(seq,
2321                          facf0,
2322                          facf1,
2323                          context->rectx,
2324                          context->recty,
2325                          ibuf1->rect_float,
2326                          ibuf2->rect_float,
2327                          out->rect_float);
2328   }
2329   else {
2330     do_wipe_effect_byte(seq,
2331                         facf0,
2332                         facf1,
2333                         context->rectx,
2334                         context->recty,
2335                         (unsigned char *)ibuf1->rect,
2336                         (unsigned char *)ibuf2->rect,
2337                         (unsigned char *)out->rect);
2338   }
2339 
2340   return out;
2341 }
2342 
2343 /*********************** Transform *************************/
2344 
init_transform_effect(Sequence * seq)2345 static void init_transform_effect(Sequence *seq)
2346 {
2347   TransformVars *transform;
2348 
2349   if (seq->effectdata) {
2350     MEM_freeN(seq->effectdata);
2351   }
2352 
2353   seq->effectdata = MEM_callocN(sizeof(TransformVars), "transformvars");
2354 
2355   transform = (TransformVars *)seq->effectdata;
2356 
2357   transform->ScalexIni = 1.0f;
2358   transform->ScaleyIni = 1.0f;
2359 
2360   transform->xIni = 0.0f;
2361   transform->yIni = 0.0f;
2362 
2363   transform->rotIni = 0.0f;
2364 
2365   transform->interpolation = 1;
2366   transform->percent = 1;
2367   transform->uniform_scale = 0;
2368 }
2369 
num_inputs_transform(void)2370 static int num_inputs_transform(void)
2371 {
2372   return 1;
2373 }
2374 
free_transform_effect(Sequence * seq,const bool UNUSED (do_id_user))2375 static void free_transform_effect(Sequence *seq, const bool UNUSED(do_id_user))
2376 {
2377   if (seq->effectdata) {
2378     MEM_freeN(seq->effectdata);
2379   }
2380   seq->effectdata = NULL;
2381 }
2382 
copy_transform_effect(Sequence * dst,Sequence * src,const int UNUSED (flag))2383 static void copy_transform_effect(Sequence *dst, Sequence *src, const int UNUSED(flag))
2384 {
2385   dst->effectdata = MEM_dupallocN(src->effectdata);
2386 }
2387 
transform_image(int x,int y,int start_line,int total_lines,ImBuf * ibuf1,ImBuf * out,float scale_x,float scale_y,float translate_x,float translate_y,float rotate,int interpolation)2388 static void transform_image(int x,
2389                             int y,
2390                             int start_line,
2391                             int total_lines,
2392                             ImBuf *ibuf1,
2393                             ImBuf *out,
2394                             float scale_x,
2395                             float scale_y,
2396                             float translate_x,
2397                             float translate_y,
2398                             float rotate,
2399                             int interpolation)
2400 {
2401   /* Rotate */
2402   float s = sinf(rotate);
2403   float c = cosf(rotate);
2404 
2405   for (int yi = start_line; yi < start_line + total_lines; yi++) {
2406     for (int xi = 0; xi < x; xi++) {
2407       /* translate point */
2408       float xt = xi - translate_x;
2409       float yt = yi - translate_y;
2410 
2411       /* rotate point with center ref */
2412       float xr = c * xt + s * yt;
2413       float yr = -s * xt + c * yt;
2414 
2415       /* scale point with center ref */
2416       xt = xr / scale_x;
2417       yt = yr / scale_y;
2418 
2419       /* undo reference center point  */
2420       xt += (x / 2.0f);
2421       yt += (y / 2.0f);
2422 
2423       /* interpolate */
2424       switch (interpolation) {
2425         case 0:
2426           nearest_interpolation(ibuf1, out, xt, yt, xi, yi);
2427           break;
2428         case 1:
2429           bilinear_interpolation(ibuf1, out, xt, yt, xi, yi);
2430           break;
2431         case 2:
2432           bicubic_interpolation(ibuf1, out, xt, yt, xi, yi);
2433           break;
2434       }
2435     }
2436   }
2437 }
2438 
do_transform_effect(const SeqRenderData * context,Sequence * seq,float UNUSED (cfra),float UNUSED (facf0),float UNUSED (facf1),ImBuf * ibuf1,ImBuf * UNUSED (ibuf2),ImBuf * UNUSED (ibuf3),int start_line,int total_lines,ImBuf * out)2439 static void do_transform_effect(const SeqRenderData *context,
2440                                 Sequence *seq,
2441                                 float UNUSED(cfra),
2442                                 float UNUSED(facf0),
2443                                 float UNUSED(facf1),
2444                                 ImBuf *ibuf1,
2445                                 ImBuf *UNUSED(ibuf2),
2446                                 ImBuf *UNUSED(ibuf3),
2447                                 int start_line,
2448                                 int total_lines,
2449                                 ImBuf *out)
2450 {
2451   Scene *scene = context->scene;
2452   TransformVars *transform = (TransformVars *)seq->effectdata;
2453   float scale_x, scale_y, translate_x, translate_y, rotate_radians;
2454 
2455   /* Scale */
2456   if (transform->uniform_scale) {
2457     scale_x = scale_y = transform->ScalexIni;
2458   }
2459   else {
2460     scale_x = transform->ScalexIni;
2461     scale_y = transform->ScaleyIni;
2462   }
2463 
2464   int x = context->rectx;
2465   int y = context->recty;
2466 
2467   /* Translate */
2468   if (!transform->percent) {
2469     float rd_s = (scene->r.size / 100.0f);
2470 
2471     translate_x = transform->xIni * rd_s + (x / 2.0f);
2472     translate_y = transform->yIni * rd_s + (y / 2.0f);
2473   }
2474   else {
2475     translate_x = x * (transform->xIni / 100.0f) + (x / 2.0f);
2476     translate_y = y * (transform->yIni / 100.0f) + (y / 2.0f);
2477   }
2478 
2479   /* Rotate */
2480   rotate_radians = DEG2RADF(transform->rotIni);
2481 
2482   transform_image(x,
2483                   y,
2484                   start_line,
2485                   total_lines,
2486                   ibuf1,
2487                   out,
2488                   scale_x,
2489                   scale_y,
2490                   translate_x,
2491                   translate_y,
2492                   rotate_radians,
2493                   transform->interpolation);
2494 }
2495 
2496 /*********************** Glow *************************/
2497 
RVBlurBitmap2_float(float * map,int width,int height,float blur,int quality)2498 static void RVBlurBitmap2_float(float *map, int width, int height, float blur, int quality)
2499 {
2500   /* Much better than the previous blur!
2501    * We do the blurring in two passes which is a whole lot faster.
2502    * I changed the math around to implement an actual Gaussian distribution.
2503    *
2504    * Watch out though, it tends to misbehave with large blur values on
2505    * a small bitmap. Avoid avoid! */
2506 
2507   float *temp = NULL, *swap;
2508   float *filter = NULL;
2509   int x, y, i, fx, fy;
2510   int index, ix, halfWidth;
2511   float fval, k, curColor[4], curColor2[4], weight = 0;
2512 
2513   /* If we're not really blurring, bail out */
2514   if (blur <= 0) {
2515     return;
2516   }
2517 
2518   /* Allocate memory for the tempmap and the blur filter matrix */
2519   temp = MEM_mallocN(sizeof(float[4]) * width * height, "blurbitmaptemp");
2520   if (!temp) {
2521     return;
2522   }
2523 
2524   /* Allocate memory for the filter elements */
2525   halfWidth = ((quality + 1) * blur);
2526   filter = (float *)MEM_mallocN(sizeof(float) * halfWidth * 2, "blurbitmapfilter");
2527   if (!filter) {
2528     MEM_freeN(temp);
2529     return;
2530   }
2531 
2532   /* Apparently we're calculating a bell curve based on the standard deviation (or radius)
2533    * This code is based on an example posted to comp.graphics.algorithms by
2534    * Blancmange <bmange@airdmhor.gen.nz>
2535    */
2536 
2537   k = -1.0f / (2.0f * (float)M_PI * blur * blur);
2538 
2539   for (ix = 0; ix < halfWidth; ix++) {
2540     weight = (float)exp(k * (ix * ix));
2541     filter[halfWidth - ix] = weight;
2542     filter[halfWidth + ix] = weight;
2543   }
2544   filter[0] = weight;
2545 
2546   /* Normalize the array */
2547   fval = 0;
2548   for (ix = 0; ix < halfWidth * 2; ix++) {
2549     fval += filter[ix];
2550   }
2551 
2552   for (ix = 0; ix < halfWidth * 2; ix++) {
2553     filter[ix] /= fval;
2554   }
2555 
2556   /* Blur the rows */
2557   for (y = 0; y < height; y++) {
2558     /* Do the left & right strips */
2559     for (x = 0; x < halfWidth; x++) {
2560       fx = 0;
2561       zero_v4(curColor);
2562       zero_v4(curColor2);
2563 
2564       for (i = x - halfWidth; i < x + halfWidth; i++) {
2565         if ((i >= 0) && (i < width)) {
2566           index = (i + y * width) * 4;
2567           madd_v4_v4fl(curColor, map + index, filter[fx]);
2568 
2569           index = (width - 1 - i + y * width) * 4;
2570           madd_v4_v4fl(curColor2, map + index, filter[fx]);
2571         }
2572         fx++;
2573       }
2574       index = (x + y * width) * 4;
2575       copy_v4_v4(temp + index, curColor);
2576 
2577       index = (width - 1 - x + y * width) * 4;
2578       copy_v4_v4(temp + index, curColor2);
2579     }
2580 
2581     /* Do the main body */
2582     for (x = halfWidth; x < width - halfWidth; x++) {
2583       fx = 0;
2584       zero_v4(curColor);
2585       for (i = x - halfWidth; i < x + halfWidth; i++) {
2586         index = (i + y * width) * 4;
2587         madd_v4_v4fl(curColor, map + index, filter[fx]);
2588         fx++;
2589       }
2590       index = (x + y * width) * 4;
2591       copy_v4_v4(temp + index, curColor);
2592     }
2593   }
2594 
2595   /* Swap buffers */
2596   swap = temp;
2597   temp = map;
2598   map = swap;
2599 
2600   /* Blur the columns */
2601   for (x = 0; x < width; x++) {
2602     /* Do the top & bottom strips */
2603     for (y = 0; y < halfWidth; y++) {
2604       fy = 0;
2605       zero_v4(curColor);
2606       zero_v4(curColor2);
2607       for (i = y - halfWidth; i < y + halfWidth; i++) {
2608         if ((i >= 0) && (i < height)) {
2609           /* Bottom */
2610           index = (x + i * width) * 4;
2611           madd_v4_v4fl(curColor, map + index, filter[fy]);
2612 
2613           /* Top */
2614           index = (x + (height - 1 - i) * width) * 4;
2615           madd_v4_v4fl(curColor2, map + index, filter[fy]);
2616         }
2617         fy++;
2618       }
2619       index = (x + y * width) * 4;
2620       copy_v4_v4(temp + index, curColor);
2621 
2622       index = (x + (height - 1 - y) * width) * 4;
2623       copy_v4_v4(temp + index, curColor2);
2624     }
2625 
2626     /* Do the main body */
2627     for (y = halfWidth; y < height - halfWidth; y++) {
2628       fy = 0;
2629       zero_v4(curColor);
2630       for (i = y - halfWidth; i < y + halfWidth; i++) {
2631         index = (x + i * width) * 4;
2632         madd_v4_v4fl(curColor, map + index, filter[fy]);
2633         fy++;
2634       }
2635       index = (x + y * width) * 4;
2636       copy_v4_v4(temp + index, curColor);
2637     }
2638   }
2639 
2640   /* Swap buffers */
2641   swap = temp;
2642   temp = map; /* map = swap; */ /* UNUSED */
2643 
2644   /* Tidy up   */
2645   MEM_freeN(filter);
2646   MEM_freeN(temp);
2647 }
2648 
RVAddBitmaps_float(float * a,float * b,float * c,int width,int height)2649 static void RVAddBitmaps_float(float *a, float *b, float *c, int width, int height)
2650 {
2651   int x, y, index;
2652 
2653   for (y = 0; y < height; y++) {
2654     for (x = 0; x < width; x++) {
2655       index = (x + y * width) * 4;
2656       c[index + GlowR] = min_ff(1.0f, a[index + GlowR] + b[index + GlowR]);
2657       c[index + GlowG] = min_ff(1.0f, a[index + GlowG] + b[index + GlowG]);
2658       c[index + GlowB] = min_ff(1.0f, a[index + GlowB] + b[index + GlowB]);
2659       c[index + GlowA] = min_ff(1.0f, a[index + GlowA] + b[index + GlowA]);
2660     }
2661   }
2662 }
2663 
RVIsolateHighlights_float(const float * in,float * out,int width,int height,float threshold,float boost,float clamp)2664 static void RVIsolateHighlights_float(
2665     const float *in, float *out, int width, int height, float threshold, float boost, float clamp)
2666 {
2667   int x, y, index;
2668   float intensity;
2669 
2670   for (y = 0; y < height; y++) {
2671     for (x = 0; x < width; x++) {
2672       index = (x + y * width) * 4;
2673 
2674       /* Isolate the intensity */
2675       intensity = (in[index + GlowR] + in[index + GlowG] + in[index + GlowB] - threshold);
2676       if (intensity > 0) {
2677         out[index + GlowR] = min_ff(clamp, (in[index + GlowR] * boost * intensity));
2678         out[index + GlowG] = min_ff(clamp, (in[index + GlowG] * boost * intensity));
2679         out[index + GlowB] = min_ff(clamp, (in[index + GlowB] * boost * intensity));
2680         out[index + GlowA] = min_ff(clamp, (in[index + GlowA] * boost * intensity));
2681       }
2682       else {
2683         out[index + GlowR] = 0;
2684         out[index + GlowG] = 0;
2685         out[index + GlowB] = 0;
2686         out[index + GlowA] = 0;
2687       }
2688     }
2689   }
2690 }
2691 
init_glow_effect(Sequence * seq)2692 static void init_glow_effect(Sequence *seq)
2693 {
2694   GlowVars *glow;
2695 
2696   if (seq->effectdata) {
2697     MEM_freeN(seq->effectdata);
2698   }
2699 
2700   seq->effectdata = MEM_callocN(sizeof(GlowVars), "glowvars");
2701 
2702   glow = (GlowVars *)seq->effectdata;
2703   glow->fMini = 0.25;
2704   glow->fClamp = 1.0;
2705   glow->fBoost = 0.5;
2706   glow->dDist = 3.0;
2707   glow->dQuality = 3;
2708   glow->bNoComp = 0;
2709 }
2710 
num_inputs_glow(void)2711 static int num_inputs_glow(void)
2712 {
2713   return 1;
2714 }
2715 
free_glow_effect(Sequence * seq,const bool UNUSED (do_id_user))2716 static void free_glow_effect(Sequence *seq, const bool UNUSED(do_id_user))
2717 {
2718   if (seq->effectdata) {
2719     MEM_freeN(seq->effectdata);
2720   }
2721 
2722   seq->effectdata = NULL;
2723 }
2724 
copy_glow_effect(Sequence * dst,Sequence * src,const int UNUSED (flag))2725 static void copy_glow_effect(Sequence *dst, Sequence *src, const int UNUSED(flag))
2726 {
2727   dst->effectdata = MEM_dupallocN(src->effectdata);
2728 }
2729 
do_glow_effect_byte(Sequence * seq,int render_size,float facf0,float UNUSED (facf1),int x,int y,unsigned char * rect1,unsigned char * UNUSED (rect2),unsigned char * out)2730 static void do_glow_effect_byte(Sequence *seq,
2731                                 int render_size,
2732                                 float facf0,
2733                                 float UNUSED(facf1),
2734                                 int x,
2735                                 int y,
2736                                 unsigned char *rect1,
2737                                 unsigned char *UNUSED(rect2),
2738                                 unsigned char *out)
2739 {
2740   float *outbuf, *inbuf;
2741   GlowVars *glow = (GlowVars *)seq->effectdata;
2742 
2743   inbuf = MEM_mallocN(sizeof(float[4]) * x * y, "glow effect input");
2744   outbuf = MEM_mallocN(sizeof(float[4]) * x * y, "glow effect output");
2745 
2746   IMB_buffer_float_from_byte(inbuf, rect1, IB_PROFILE_SRGB, IB_PROFILE_SRGB, false, x, y, x, x);
2747   IMB_buffer_float_premultiply(inbuf, x, y);
2748 
2749   RVIsolateHighlights_float(
2750       inbuf, outbuf, x, y, glow->fMini * 3.0f, glow->fBoost * facf0, glow->fClamp);
2751   RVBlurBitmap2_float(outbuf, x, y, glow->dDist * (render_size / 100.0f), glow->dQuality);
2752   if (!glow->bNoComp) {
2753     RVAddBitmaps_float(inbuf, outbuf, outbuf, x, y);
2754   }
2755 
2756   IMB_buffer_float_unpremultiply(outbuf, x, y);
2757   IMB_buffer_byte_from_float(
2758       out, outbuf, 4, 0.0f, IB_PROFILE_SRGB, IB_PROFILE_SRGB, false, x, y, x, x);
2759 
2760   MEM_freeN(inbuf);
2761   MEM_freeN(outbuf);
2762 }
2763 
do_glow_effect_float(Sequence * seq,int render_size,float facf0,float UNUSED (facf1),int x,int y,float * rect1,float * UNUSED (rect2),float * out)2764 static void do_glow_effect_float(Sequence *seq,
2765                                  int render_size,
2766                                  float facf0,
2767                                  float UNUSED(facf1),
2768                                  int x,
2769                                  int y,
2770                                  float *rect1,
2771                                  float *UNUSED(rect2),
2772                                  float *out)
2773 {
2774   float *outbuf = out;
2775   float *inbuf = rect1;
2776   GlowVars *glow = (GlowVars *)seq->effectdata;
2777 
2778   RVIsolateHighlights_float(
2779       inbuf, outbuf, x, y, glow->fMini * 3.0f, glow->fBoost * facf0, glow->fClamp);
2780   RVBlurBitmap2_float(outbuf, x, y, glow->dDist * (render_size / 100.0f), glow->dQuality);
2781   if (!glow->bNoComp) {
2782     RVAddBitmaps_float(inbuf, outbuf, outbuf, x, y);
2783   }
2784 }
2785 
do_glow_effect(const SeqRenderData * context,Sequence * seq,float UNUSED (cfra),float facf0,float facf1,ImBuf * ibuf1,ImBuf * ibuf2,ImBuf * ibuf3)2786 static ImBuf *do_glow_effect(const SeqRenderData *context,
2787                              Sequence *seq,
2788                              float UNUSED(cfra),
2789                              float facf0,
2790                              float facf1,
2791                              ImBuf *ibuf1,
2792                              ImBuf *ibuf2,
2793                              ImBuf *ibuf3)
2794 {
2795   ImBuf *out = prepare_effect_imbufs(context, ibuf1, ibuf2, ibuf3);
2796 
2797   int render_size = 100 * context->rectx / context->scene->r.xsch;
2798 
2799   if (out->rect_float) {
2800     do_glow_effect_float(seq,
2801                          render_size,
2802                          facf0,
2803                          facf1,
2804                          context->rectx,
2805                          context->recty,
2806                          ibuf1->rect_float,
2807                          NULL,
2808                          out->rect_float);
2809   }
2810   else {
2811     do_glow_effect_byte(seq,
2812                         render_size,
2813                         facf0,
2814                         facf1,
2815                         context->rectx,
2816                         context->recty,
2817                         (unsigned char *)ibuf1->rect,
2818                         NULL,
2819                         (unsigned char *)out->rect);
2820   }
2821 
2822   return out;
2823 }
2824 
2825 /*********************** Solid color *************************/
2826 
init_solid_color(Sequence * seq)2827 static void init_solid_color(Sequence *seq)
2828 {
2829   SolidColorVars *cv;
2830 
2831   if (seq->effectdata) {
2832     MEM_freeN(seq->effectdata);
2833   }
2834 
2835   seq->effectdata = MEM_callocN(sizeof(SolidColorVars), "solidcolor");
2836 
2837   cv = (SolidColorVars *)seq->effectdata;
2838   cv->col[0] = cv->col[1] = cv->col[2] = 0.5;
2839 }
2840 
num_inputs_color(void)2841 static int num_inputs_color(void)
2842 {
2843   return 0;
2844 }
2845 
free_solid_color(Sequence * seq,const bool UNUSED (do_id_user))2846 static void free_solid_color(Sequence *seq, const bool UNUSED(do_id_user))
2847 {
2848   if (seq->effectdata) {
2849     MEM_freeN(seq->effectdata);
2850   }
2851 
2852   seq->effectdata = NULL;
2853 }
2854 
copy_solid_color(Sequence * dst,Sequence * src,const int UNUSED (flag))2855 static void copy_solid_color(Sequence *dst, Sequence *src, const int UNUSED(flag))
2856 {
2857   dst->effectdata = MEM_dupallocN(src->effectdata);
2858 }
2859 
early_out_color(Sequence * UNUSED (seq),float UNUSED (facf0),float UNUSED (facf1))2860 static int early_out_color(Sequence *UNUSED(seq), float UNUSED(facf0), float UNUSED(facf1))
2861 {
2862   return EARLY_NO_INPUT;
2863 }
2864 
do_solid_color(const SeqRenderData * context,Sequence * seq,float UNUSED (cfra),float facf0,float facf1,ImBuf * ibuf1,ImBuf * ibuf2,ImBuf * ibuf3)2865 static ImBuf *do_solid_color(const SeqRenderData *context,
2866                              Sequence *seq,
2867                              float UNUSED(cfra),
2868                              float facf0,
2869                              float facf1,
2870                              ImBuf *ibuf1,
2871                              ImBuf *ibuf2,
2872                              ImBuf *ibuf3)
2873 {
2874   ImBuf *out = prepare_effect_imbufs(context, ibuf1, ibuf2, ibuf3);
2875 
2876   SolidColorVars *cv = (SolidColorVars *)seq->effectdata;
2877 
2878   unsigned char *rect;
2879   float *rect_float;
2880   int x; /*= context->rectx;*/ /*UNUSED*/
2881   int y; /*= context->recty;*/ /*UNUSED*/
2882 
2883   if (out->rect) {
2884     unsigned char col0[3];
2885     unsigned char col1[3];
2886 
2887     col0[0] = facf0 * cv->col[0] * 255;
2888     col0[1] = facf0 * cv->col[1] * 255;
2889     col0[2] = facf0 * cv->col[2] * 255;
2890 
2891     col1[0] = facf1 * cv->col[0] * 255;
2892     col1[1] = facf1 * cv->col[1] * 255;
2893     col1[2] = facf1 * cv->col[2] * 255;
2894 
2895     rect = (unsigned char *)out->rect;
2896 
2897     for (y = 0; y < out->y; y++) {
2898       for (x = 0; x < out->x; x++, rect += 4) {
2899         rect[0] = col0[0];
2900         rect[1] = col0[1];
2901         rect[2] = col0[2];
2902         rect[3] = 255;
2903       }
2904       y++;
2905       if (y < out->y) {
2906         for (x = 0; x < out->x; x++, rect += 4) {
2907           rect[0] = col1[0];
2908           rect[1] = col1[1];
2909           rect[2] = col1[2];
2910           rect[3] = 255;
2911         }
2912       }
2913     }
2914   }
2915   else if (out->rect_float) {
2916     float col0[3];
2917     float col1[3];
2918 
2919     col0[0] = facf0 * cv->col[0];
2920     col0[1] = facf0 * cv->col[1];
2921     col0[2] = facf0 * cv->col[2];
2922 
2923     col1[0] = facf1 * cv->col[0];
2924     col1[1] = facf1 * cv->col[1];
2925     col1[2] = facf1 * cv->col[2];
2926 
2927     rect_float = out->rect_float;
2928 
2929     for (y = 0; y < out->y; y++) {
2930       for (x = 0; x < out->x; x++, rect_float += 4) {
2931         rect_float[0] = col0[0];
2932         rect_float[1] = col0[1];
2933         rect_float[2] = col0[2];
2934         rect_float[3] = 1.0;
2935       }
2936       y++;
2937       if (y < out->y) {
2938         for (x = 0; x < out->x; x++, rect_float += 4) {
2939           rect_float[0] = col1[0];
2940           rect_float[1] = col1[1];
2941           rect_float[2] = col1[2];
2942           rect_float[3] = 1.0;
2943         }
2944       }
2945     }
2946   }
2947   return out;
2948 }
2949 
2950 /*********************** Mulitcam *************************/
2951 
2952 /* no effect inputs for multicam, we use give_ibuf_seq */
num_inputs_multicam(void)2953 static int num_inputs_multicam(void)
2954 {
2955   return 0;
2956 }
2957 
early_out_multicam(Sequence * UNUSED (seq),float UNUSED (facf0),float UNUSED (facf1))2958 static int early_out_multicam(Sequence *UNUSED(seq), float UNUSED(facf0), float UNUSED(facf1))
2959 {
2960   return EARLY_NO_INPUT;
2961 }
2962 
do_multicam(const SeqRenderData * context,Sequence * seq,float cfra,float UNUSED (facf0),float UNUSED (facf1),ImBuf * UNUSED (ibuf1),ImBuf * UNUSED (ibuf2),ImBuf * UNUSED (ibuf3))2963 static ImBuf *do_multicam(const SeqRenderData *context,
2964                           Sequence *seq,
2965                           float cfra,
2966                           float UNUSED(facf0),
2967                           float UNUSED(facf1),
2968                           ImBuf *UNUSED(ibuf1),
2969                           ImBuf *UNUSED(ibuf2),
2970                           ImBuf *UNUSED(ibuf3))
2971 {
2972   ImBuf *out;
2973   Editing *ed;
2974   ListBase *seqbasep;
2975 
2976   if (seq->multicam_source == 0 || seq->multicam_source >= seq->machine) {
2977     return NULL;
2978   }
2979 
2980   ed = context->scene->ed;
2981   if (!ed) {
2982     return NULL;
2983   }
2984   seqbasep = BKE_sequence_seqbase(&ed->seqbase, seq);
2985   if (!seqbasep) {
2986     return NULL;
2987   }
2988 
2989   out = BKE_sequencer_give_ibuf_seqbase(context, cfra, seq->multicam_source, seqbasep);
2990 
2991   return out;
2992 }
2993 
2994 /*********************** Adjustment *************************/
2995 
2996 /* no effect inputs for adjustment, we use give_ibuf_seq */
num_inputs_adjustment(void)2997 static int num_inputs_adjustment(void)
2998 {
2999   return 0;
3000 }
3001 
early_out_adjustment(Sequence * UNUSED (seq),float UNUSED (facf0),float UNUSED (facf1))3002 static int early_out_adjustment(Sequence *UNUSED(seq), float UNUSED(facf0), float UNUSED(facf1))
3003 {
3004   return EARLY_NO_INPUT;
3005 }
3006 
do_adjustment_impl(const SeqRenderData * context,Sequence * seq,float cfra)3007 static ImBuf *do_adjustment_impl(const SeqRenderData *context, Sequence *seq, float cfra)
3008 {
3009   Editing *ed;
3010   ListBase *seqbasep;
3011   ImBuf *i = NULL;
3012 
3013   ed = context->scene->ed;
3014 
3015   seqbasep = BKE_sequence_seqbase(&ed->seqbase, seq);
3016 
3017   if (seq->machine > 1) {
3018     i = BKE_sequencer_give_ibuf_seqbase(context, cfra, seq->machine - 1, seqbasep);
3019   }
3020 
3021   /* found nothing? so let's work the way up the metastrip stack, so
3022    * that it is possible to group a bunch of adjustment strips into
3023    * a metastrip and have that work on everything below the metastrip
3024    */
3025 
3026   if (!i) {
3027     Sequence *meta;
3028 
3029     meta = BKE_sequence_metastrip(&ed->seqbase, NULL, seq);
3030 
3031     if (meta) {
3032       i = do_adjustment_impl(context, meta, cfra);
3033     }
3034   }
3035 
3036   return i;
3037 }
3038 
do_adjustment(const SeqRenderData * context,Sequence * seq,float cfra,float UNUSED (facf0),float UNUSED (facf1),ImBuf * UNUSED (ibuf1),ImBuf * UNUSED (ibuf2),ImBuf * UNUSED (ibuf3))3039 static ImBuf *do_adjustment(const SeqRenderData *context,
3040                             Sequence *seq,
3041                             float cfra,
3042                             float UNUSED(facf0),
3043                             float UNUSED(facf1),
3044                             ImBuf *UNUSED(ibuf1),
3045                             ImBuf *UNUSED(ibuf2),
3046                             ImBuf *UNUSED(ibuf3))
3047 {
3048   ImBuf *out;
3049   Editing *ed;
3050 
3051   ed = context->scene->ed;
3052 
3053   if (!ed) {
3054     return NULL;
3055   }
3056 
3057   out = do_adjustment_impl(context, seq, cfra);
3058 
3059   return out;
3060 }
3061 
3062 /*********************** Speed *************************/
3063 
init_speed_effect(Sequence * seq)3064 static void init_speed_effect(Sequence *seq)
3065 {
3066   SpeedControlVars *v;
3067 
3068   if (seq->effectdata) {
3069     MEM_freeN(seq->effectdata);
3070   }
3071 
3072   seq->effectdata = MEM_callocN(sizeof(SpeedControlVars), "speedcontrolvars");
3073 
3074   v = (SpeedControlVars *)seq->effectdata;
3075   v->globalSpeed = 1.0;
3076   v->frameMap = NULL;
3077   v->flags |= SEQ_SPEED_INTEGRATE; /* should be default behavior */
3078   v->length = 0;
3079 }
3080 
load_speed_effect(Sequence * seq)3081 static void load_speed_effect(Sequence *seq)
3082 {
3083   SpeedControlVars *v = (SpeedControlVars *)seq->effectdata;
3084 
3085   v->frameMap = NULL;
3086   v->length = 0;
3087 }
3088 
num_inputs_speed(void)3089 static int num_inputs_speed(void)
3090 {
3091   return 1;
3092 }
3093 
free_speed_effect(Sequence * seq,const bool UNUSED (do_id_user))3094 static void free_speed_effect(Sequence *seq, const bool UNUSED(do_id_user))
3095 {
3096   SpeedControlVars *v = (SpeedControlVars *)seq->effectdata;
3097   if (v->frameMap) {
3098     MEM_freeN(v->frameMap);
3099   }
3100   if (seq->effectdata) {
3101     MEM_freeN(seq->effectdata);
3102   }
3103   seq->effectdata = NULL;
3104 }
3105 
copy_speed_effect(Sequence * dst,Sequence * src,const int UNUSED (flag))3106 static void copy_speed_effect(Sequence *dst, Sequence *src, const int UNUSED(flag))
3107 {
3108   SpeedControlVars *v;
3109   dst->effectdata = MEM_dupallocN(src->effectdata);
3110   v = (SpeedControlVars *)dst->effectdata;
3111   v->frameMap = NULL;
3112   v->length = 0;
3113 }
3114 
early_out_speed(Sequence * UNUSED (seq),float UNUSED (facf0),float UNUSED (facf1))3115 static int early_out_speed(Sequence *UNUSED(seq), float UNUSED(facf0), float UNUSED(facf1))
3116 {
3117   return EARLY_DO_EFFECT;
3118 }
3119 
store_icu_yrange_speed(Sequence * seq,short UNUSED (adrcode),float * ymin,float * ymax)3120 static void store_icu_yrange_speed(Sequence *seq, short UNUSED(adrcode), float *ymin, float *ymax)
3121 {
3122   SpeedControlVars *v = (SpeedControlVars *)seq->effectdata;
3123 
3124   /* if not already done, load / initialize data */
3125   BKE_sequence_get_effect(seq);
3126 
3127   if ((v->flags & SEQ_SPEED_INTEGRATE) != 0) {
3128     *ymin = -100.0;
3129     *ymax = 100.0;
3130   }
3131   else {
3132     if (v->flags & SEQ_SPEED_COMPRESS_IPO_Y) {
3133       *ymin = 0.0;
3134       *ymax = 1.0;
3135     }
3136     else {
3137       *ymin = 0.0;
3138       *ymax = seq->len;
3139     }
3140   }
3141 }
3142 
BKE_sequence_effect_speed_rebuild_map(Scene * scene,Sequence * seq,bool force)3143 void BKE_sequence_effect_speed_rebuild_map(Scene *scene, Sequence *seq, bool force)
3144 {
3145   int cfra;
3146   float fallback_fac = 1.0f;
3147   SpeedControlVars *v = (SpeedControlVars *)seq->effectdata;
3148   FCurve *fcu = NULL;
3149   int flags = v->flags;
3150 
3151   /* if not already done, load / initialize data */
3152   BKE_sequence_get_effect(seq);
3153 
3154   if ((force == false) && (seq->len == v->length) && (v->frameMap != NULL)) {
3155     return;
3156   }
3157   if ((seq->seq1 == NULL) || (seq->len < 1)) {
3158     /* make coverity happy and check for (CID 598) input strip ... */
3159     return;
3160   }
3161 
3162   /* XXX - new in 2.5x. should we use the animation system this way?
3163    * The fcurve is needed because many frames need evaluating at once - campbell */
3164   fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "speed_factor", 0, NULL);
3165   if (!v->frameMap || v->length != seq->len) {
3166     if (v->frameMap) {
3167       MEM_freeN(v->frameMap);
3168     }
3169 
3170     v->length = seq->len;
3171 
3172     v->frameMap = MEM_callocN(sizeof(float) * v->length, "speedcontrol frameMap");
3173   }
3174 
3175   fallback_fac = 1.0;
3176 
3177   if (seq->flag & SEQ_USE_EFFECT_DEFAULT_FADE) {
3178     if ((seq->seq1->enddisp != seq->seq1->start) && (seq->seq1->len != 0)) {
3179       fallback_fac = (float)seq->seq1->len / (float)(seq->seq1->enddisp - seq->seq1->start);
3180       flags = SEQ_SPEED_INTEGRATE;
3181       fcu = NULL;
3182     }
3183   }
3184   else {
3185     /* if there is no fcurve, use value as simple multiplier */
3186     if (!fcu) {
3187       fallback_fac = seq->speed_fader; /* same as speed_factor in rna*/
3188     }
3189   }
3190 
3191   if (flags & SEQ_SPEED_INTEGRATE) {
3192     float cursor = 0;
3193     float facf;
3194 
3195     v->frameMap[0] = 0;
3196     v->lastValidFrame = 0;
3197 
3198     for (cfra = 1; cfra < v->length; cfra++) {
3199       if (fcu) {
3200         facf = evaluate_fcurve(fcu, seq->startdisp + cfra);
3201       }
3202       else {
3203         facf = fallback_fac;
3204       }
3205       facf *= v->globalSpeed;
3206 
3207       cursor += facf;
3208 
3209       if (cursor >= seq->seq1->len) {
3210         v->frameMap[cfra] = seq->seq1->len - 1;
3211       }
3212       else {
3213         v->frameMap[cfra] = cursor;
3214         v->lastValidFrame = cfra;
3215       }
3216     }
3217   }
3218   else {
3219     float facf;
3220 
3221     v->lastValidFrame = 0;
3222     for (cfra = 0; cfra < v->length; cfra++) {
3223 
3224       if (fcu) {
3225         facf = evaluate_fcurve(fcu, seq->startdisp + cfra);
3226       }
3227       else {
3228         facf = fallback_fac;
3229       }
3230 
3231       if (flags & SEQ_SPEED_COMPRESS_IPO_Y) {
3232         facf *= seq->seq1->len;
3233       }
3234       facf *= v->globalSpeed;
3235 
3236       if (facf >= seq->seq1->len) {
3237         facf = seq->seq1->len - 1;
3238       }
3239       else {
3240         v->lastValidFrame = cfra;
3241       }
3242       v->frameMap[cfra] = facf;
3243     }
3244   }
3245 }
3246 
3247 /* Override cfra when rendering speed effect input. */
BKE_sequencer_speed_effect_target_frame_get(const SeqRenderData * context,Sequence * seq,float cfra,int input)3248 float BKE_sequencer_speed_effect_target_frame_get(const SeqRenderData *context,
3249                                                   Sequence *seq,
3250                                                   float cfra,
3251                                                   int input)
3252 {
3253   int nr = BKE_sequencer_give_stripelem_index(seq, cfra);
3254   SpeedControlVars *s = (SpeedControlVars *)seq->effectdata;
3255   BKE_sequence_effect_speed_rebuild_map(context->scene, seq, false);
3256 
3257   /* No interpolation. */
3258   if ((s->flags & SEQ_SPEED_USE_INTERPOLATION) == 0) {
3259     return seq->start + s->frameMap[nr];
3260   }
3261 
3262   /* We need to provide current and next image for interpolation. */
3263   if (input == 0) { /* Current frame. */
3264     return floor(seq->start + s->frameMap[nr]);
3265   }
3266   /* Next frame. */
3267   return ceil(seq->start + s->frameMap[nr]);
3268 }
3269 
speed_effect_interpolation_ratio_get(SpeedControlVars * s,Sequence * seq,float cfra)3270 static float speed_effect_interpolation_ratio_get(SpeedControlVars *s, Sequence *seq, float cfra)
3271 {
3272   int nr = BKE_sequencer_give_stripelem_index(seq, cfra);
3273   return s->frameMap[nr] - floor(s->frameMap[nr]);
3274 }
3275 
do_speed_effect(const SeqRenderData * context,Sequence * seq,float cfra,float facf0,float facf1,ImBuf * ibuf1,ImBuf * ibuf2,ImBuf * ibuf3)3276 static ImBuf *do_speed_effect(const SeqRenderData *context,
3277                               Sequence *seq,
3278                               float cfra,
3279                               float facf0,
3280                               float facf1,
3281                               ImBuf *ibuf1,
3282                               ImBuf *ibuf2,
3283                               ImBuf *ibuf3)
3284 {
3285   SpeedControlVars *s = (SpeedControlVars *)seq->effectdata;
3286   struct SeqEffectHandle cross_effect = get_sequence_effect_impl(SEQ_TYPE_CROSS);
3287   ImBuf *out;
3288 
3289   if (s->flags & SEQ_SPEED_USE_INTERPOLATION) {
3290     out = prepare_effect_imbufs(context, ibuf1, ibuf2, ibuf3);
3291     facf0 = facf1 = speed_effect_interpolation_ratio_get(s, seq, cfra);
3292     /* Current frame is ibuf1, next frame is ibuf2. */
3293     out = BKE_sequencer_effect_execute_threaded(
3294         &cross_effect, context, NULL, cfra, facf0, facf1, ibuf1, ibuf2, ibuf3);
3295     return out;
3296   }
3297 
3298   /* No interpolation. */
3299   return IMB_dupImBuf(ibuf1);
3300 }
3301 
3302 /*********************** overdrop *************************/
3303 
do_overdrop_effect(const SeqRenderData * context,Sequence * UNUSED (seq),float UNUSED (cfra),float facf0,float facf1,ImBuf * ibuf1,ImBuf * ibuf2,ImBuf * UNUSED (ibuf3),int start_line,int total_lines,ImBuf * out)3304 static void do_overdrop_effect(const SeqRenderData *context,
3305                                Sequence *UNUSED(seq),
3306                                float UNUSED(cfra),
3307                                float facf0,
3308                                float facf1,
3309                                ImBuf *ibuf1,
3310                                ImBuf *ibuf2,
3311                                ImBuf *UNUSED(ibuf3),
3312                                int start_line,
3313                                int total_lines,
3314                                ImBuf *out)
3315 {
3316   int x = context->rectx;
3317   int y = total_lines;
3318 
3319   if (out->rect_float) {
3320     float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
3321 
3322     slice_get_float_buffers(
3323         context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
3324 
3325     do_drop_effect_float(facf0, facf1, x, y, rect1, rect2, rect_out);
3326     do_alphaover_effect_float(facf0, facf1, x, y, rect1, rect2, rect_out);
3327   }
3328   else {
3329     unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
3330 
3331     slice_get_byte_buffers(
3332         context, ibuf1, ibuf2, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
3333 
3334     do_drop_effect_byte(facf0, facf1, x, y, rect1, rect2, rect_out);
3335     do_alphaover_effect_byte(facf0, facf1, x, y, rect1, rect2, rect_out);
3336   }
3337 }
3338 
3339 /*********************** Gaussian Blur *************************/
3340 
3341 /* NOTE: This gaussian blur implementation accumulates values in the square
3342  * kernel rather that doing X direction and then Y direction because of the
3343  * lack of using multiple-staged filters.
3344  *
3345  * Once we can we'll implement a way to apply filter as multiple stages we
3346  * can optimize hell of a lot in here.
3347  */
3348 
init_gaussian_blur_effect(Sequence * seq)3349 static void init_gaussian_blur_effect(Sequence *seq)
3350 {
3351   if (seq->effectdata) {
3352     MEM_freeN(seq->effectdata);
3353   }
3354 
3355   seq->effectdata = MEM_callocN(sizeof(WipeVars), "wipevars");
3356 }
3357 
num_inputs_gaussian_blur(void)3358 static int num_inputs_gaussian_blur(void)
3359 {
3360   return 1;
3361 }
3362 
free_gaussian_blur_effect(Sequence * seq,const bool UNUSED (do_id_user))3363 static void free_gaussian_blur_effect(Sequence *seq, const bool UNUSED(do_id_user))
3364 {
3365   if (seq->effectdata) {
3366     MEM_freeN(seq->effectdata);
3367   }
3368 
3369   seq->effectdata = NULL;
3370 }
3371 
copy_gaussian_blur_effect(Sequence * dst,Sequence * src,const int UNUSED (flag))3372 static void copy_gaussian_blur_effect(Sequence *dst, Sequence *src, const int UNUSED(flag))
3373 {
3374   dst->effectdata = MEM_dupallocN(src->effectdata);
3375 }
3376 
early_out_gaussian_blur(Sequence * seq,float UNUSED (facf0),float UNUSED (facf1))3377 static int early_out_gaussian_blur(Sequence *seq, float UNUSED(facf0), float UNUSED(facf1))
3378 {
3379   GaussianBlurVars *data = seq->effectdata;
3380   if (data->size_x == 0.0f && data->size_y == 0) {
3381     return EARLY_USE_INPUT_1;
3382   }
3383   return EARLY_DO_EFFECT;
3384 }
3385 
3386 /* TODO(sergey): De-duplicate with compositor. */
make_gaussian_blur_kernel(float rad,int size)3387 static float *make_gaussian_blur_kernel(float rad, int size)
3388 {
3389   float *gausstab, sum, val;
3390   float fac;
3391   int i, n;
3392 
3393   n = 2 * size + 1;
3394 
3395   gausstab = (float *)MEM_mallocN(sizeof(float) * n, __func__);
3396 
3397   sum = 0.0f;
3398   fac = (rad > 0.0f ? 1.0f / rad : 0.0f);
3399   for (i = -size; i <= size; i++) {
3400     val = RE_filter_value(R_FILTER_GAUSS, (float)i * fac);
3401     sum += val;
3402     gausstab[i + size] = val;
3403   }
3404 
3405   sum = 1.0f / sum;
3406   for (i = 0; i < n; i++) {
3407     gausstab[i] *= sum;
3408   }
3409 
3410   return gausstab;
3411 }
3412 
do_gaussian_blur_effect_byte_x(Sequence * seq,int start_line,int x,int y,int frame_width,int UNUSED (frame_height),const unsigned char * rect,unsigned char * out)3413 static void do_gaussian_blur_effect_byte_x(Sequence *seq,
3414                                            int start_line,
3415                                            int x,
3416                                            int y,
3417                                            int frame_width,
3418                                            int UNUSED(frame_height),
3419                                            const unsigned char *rect,
3420                                            unsigned char *out)
3421 {
3422 #define INDEX(_x, _y) (((_y) * (x) + (_x)) * 4)
3423   GaussianBlurVars *data = seq->effectdata;
3424   const int size_x = (int)(data->size_x + 0.5f);
3425   int i, j;
3426 
3427   /* Make gaussian weight table. */
3428   float *gausstab_x;
3429   gausstab_x = make_gaussian_blur_kernel(data->size_x, size_x);
3430 
3431   for (i = 0; i < y; i++) {
3432     for (j = 0; j < x; j++) {
3433       int out_index = INDEX(j, i);
3434       float accum[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3435       float accum_weight = 0.0f;
3436 
3437       for (int current_x = j - size_x; current_x <= j + size_x; current_x++) {
3438         if (current_x < 0 || current_x >= frame_width) {
3439           /* Out of bounds. */
3440           continue;
3441         }
3442         int index = INDEX(current_x, i + start_line);
3443         float weight = gausstab_x[current_x - j + size_x];
3444         accum[0] += rect[index] * weight;
3445         accum[1] += rect[index + 1] * weight;
3446         accum[2] += rect[index + 2] * weight;
3447         accum[3] += rect[index + 3] * weight;
3448         accum_weight += weight;
3449       }
3450 
3451       float inv_accum_weight = 1.0f / accum_weight;
3452       out[out_index + 0] = accum[0] * inv_accum_weight;
3453       out[out_index + 1] = accum[1] * inv_accum_weight;
3454       out[out_index + 2] = accum[2] * inv_accum_weight;
3455       out[out_index + 3] = accum[3] * inv_accum_weight;
3456     }
3457   }
3458 
3459   MEM_freeN(gausstab_x);
3460 #undef INDEX
3461 }
3462 
do_gaussian_blur_effect_byte_y(Sequence * seq,int start_line,int x,int y,int UNUSED (frame_width),int frame_height,const unsigned char * rect,unsigned char * out)3463 static void do_gaussian_blur_effect_byte_y(Sequence *seq,
3464                                            int start_line,
3465                                            int x,
3466                                            int y,
3467                                            int UNUSED(frame_width),
3468                                            int frame_height,
3469                                            const unsigned char *rect,
3470                                            unsigned char *out)
3471 {
3472 #define INDEX(_x, _y) (((_y) * (x) + (_x)) * 4)
3473   GaussianBlurVars *data = seq->effectdata;
3474   const int size_y = (int)(data->size_y + 0.5f);
3475   int i, j;
3476 
3477   /* Make gaussian weight table. */
3478   float *gausstab_y;
3479   gausstab_y = make_gaussian_blur_kernel(data->size_y, size_y);
3480 
3481   for (i = 0; i < y; i++) {
3482     for (j = 0; j < x; j++) {
3483       int out_index = INDEX(j, i);
3484       float accum[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3485       float accum_weight = 0.0f;
3486       for (int current_y = i - size_y; current_y <= i + size_y; current_y++) {
3487         if (current_y < -start_line || current_y + start_line >= frame_height) {
3488           /* Out of bounds. */
3489           continue;
3490         }
3491         int index = INDEX(j, current_y + start_line);
3492         float weight = gausstab_y[current_y - i + size_y];
3493         accum[0] += rect[index] * weight;
3494         accum[1] += rect[index + 1] * weight;
3495         accum[2] += rect[index + 2] * weight;
3496         accum[3] += rect[index + 3] * weight;
3497         accum_weight += weight;
3498       }
3499       float inv_accum_weight = 1.0f / accum_weight;
3500       out[out_index + 0] = accum[0] * inv_accum_weight;
3501       out[out_index + 1] = accum[1] * inv_accum_weight;
3502       out[out_index + 2] = accum[2] * inv_accum_weight;
3503       out[out_index + 3] = accum[3] * inv_accum_weight;
3504     }
3505   }
3506 
3507   MEM_freeN(gausstab_y);
3508 #undef INDEX
3509 }
3510 
do_gaussian_blur_effect_float_x(Sequence * seq,int start_line,int x,int y,int frame_width,int UNUSED (frame_height),float * rect,float * out)3511 static void do_gaussian_blur_effect_float_x(Sequence *seq,
3512                                             int start_line,
3513                                             int x,
3514                                             int y,
3515                                             int frame_width,
3516                                             int UNUSED(frame_height),
3517                                             float *rect,
3518                                             float *out)
3519 {
3520 #define INDEX(_x, _y) (((_y) * (x) + (_x)) * 4)
3521   GaussianBlurVars *data = seq->effectdata;
3522   const int size_x = (int)(data->size_x + 0.5f);
3523   int i, j;
3524 
3525   /* Make gaussian weight table. */
3526   float *gausstab_x;
3527   gausstab_x = make_gaussian_blur_kernel(data->size_x, size_x);
3528 
3529   for (i = 0; i < y; i++) {
3530     for (j = 0; j < x; j++) {
3531       int out_index = INDEX(j, i);
3532       float accum[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3533       float accum_weight = 0.0f;
3534       for (int current_x = j - size_x; current_x <= j + size_x; current_x++) {
3535         if (current_x < 0 || current_x >= frame_width) {
3536           /* Out of bounds. */
3537           continue;
3538         }
3539         int index = INDEX(current_x, i + start_line);
3540         float weight = gausstab_x[current_x - j + size_x];
3541         madd_v4_v4fl(accum, &rect[index], weight);
3542         accum_weight += weight;
3543       }
3544       mul_v4_v4fl(&out[out_index], accum, 1.0f / accum_weight);
3545     }
3546   }
3547 
3548   MEM_freeN(gausstab_x);
3549 #undef INDEX
3550 }
3551 
do_gaussian_blur_effect_float_y(Sequence * seq,int start_line,int x,int y,int UNUSED (frame_width),int frame_height,float * rect,float * out)3552 static void do_gaussian_blur_effect_float_y(Sequence *seq,
3553                                             int start_line,
3554                                             int x,
3555                                             int y,
3556                                             int UNUSED(frame_width),
3557                                             int frame_height,
3558                                             float *rect,
3559                                             float *out)
3560 {
3561 #define INDEX(_x, _y) (((_y) * (x) + (_x)) * 4)
3562   GaussianBlurVars *data = seq->effectdata;
3563   const int size_y = (int)(data->size_y + 0.5f);
3564   int i, j;
3565 
3566   /* Make gaussian weight table. */
3567   float *gausstab_y;
3568   gausstab_y = make_gaussian_blur_kernel(data->size_y, size_y);
3569 
3570   for (i = 0; i < y; i++) {
3571     for (j = 0; j < x; j++) {
3572       int out_index = INDEX(j, i);
3573       float accum[4] = {0.0f, 0.0f, 0.0f, 0.0f};
3574       float accum_weight = 0.0f;
3575       for (int current_y = i - size_y; current_y <= i + size_y; current_y++) {
3576         if (current_y < -start_line || current_y + start_line >= frame_height) {
3577           /* Out of bounds. */
3578           continue;
3579         }
3580         int index = INDEX(j, current_y + start_line);
3581         float weight = gausstab_y[current_y - i + size_y];
3582         madd_v4_v4fl(accum, &rect[index], weight);
3583         accum_weight += weight;
3584       }
3585       mul_v4_v4fl(&out[out_index], accum, 1.0f / accum_weight);
3586     }
3587   }
3588 
3589   MEM_freeN(gausstab_y);
3590 #undef INDEX
3591 }
3592 
do_gaussian_blur_effect_x_cb(const SeqRenderData * context,Sequence * seq,ImBuf * ibuf,int start_line,int total_lines,ImBuf * out)3593 static void do_gaussian_blur_effect_x_cb(const SeqRenderData *context,
3594                                          Sequence *seq,
3595                                          ImBuf *ibuf,
3596                                          int start_line,
3597                                          int total_lines,
3598                                          ImBuf *out)
3599 {
3600   if (out->rect_float) {
3601     float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
3602 
3603     slice_get_float_buffers(
3604         context, ibuf, NULL, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
3605 
3606     do_gaussian_blur_effect_float_x(seq,
3607                                     start_line,
3608                                     context->rectx,
3609                                     total_lines,
3610                                     context->rectx,
3611                                     context->recty,
3612                                     ibuf->rect_float,
3613                                     rect_out);
3614   }
3615   else {
3616     unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
3617 
3618     slice_get_byte_buffers(
3619         context, ibuf, NULL, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
3620 
3621     do_gaussian_blur_effect_byte_x(seq,
3622                                    start_line,
3623                                    context->rectx,
3624                                    total_lines,
3625                                    context->rectx,
3626                                    context->recty,
3627                                    (unsigned char *)ibuf->rect,
3628                                    rect_out);
3629   }
3630 }
3631 
do_gaussian_blur_effect_y_cb(const SeqRenderData * context,Sequence * seq,ImBuf * ibuf,int start_line,int total_lines,ImBuf * out)3632 static void do_gaussian_blur_effect_y_cb(const SeqRenderData *context,
3633                                          Sequence *seq,
3634                                          ImBuf *ibuf,
3635                                          int start_line,
3636                                          int total_lines,
3637                                          ImBuf *out)
3638 {
3639   if (out->rect_float) {
3640     float *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
3641 
3642     slice_get_float_buffers(
3643         context, ibuf, NULL, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
3644 
3645     do_gaussian_blur_effect_float_y(seq,
3646                                     start_line,
3647                                     context->rectx,
3648                                     total_lines,
3649                                     context->rectx,
3650                                     context->recty,
3651                                     ibuf->rect_float,
3652                                     rect_out);
3653   }
3654   else {
3655     unsigned char *rect1 = NULL, *rect2 = NULL, *rect_out = NULL;
3656 
3657     slice_get_byte_buffers(
3658         context, ibuf, NULL, NULL, out, start_line, &rect1, &rect2, NULL, &rect_out);
3659 
3660     do_gaussian_blur_effect_byte_y(seq,
3661                                    start_line,
3662                                    context->rectx,
3663                                    total_lines,
3664                                    context->rectx,
3665                                    context->recty,
3666                                    (unsigned char *)ibuf->rect,
3667                                    rect_out);
3668   }
3669 }
3670 
3671 typedef struct RenderGaussianBlurEffectInitData {
3672   const SeqRenderData *context;
3673   Sequence *seq;
3674   ImBuf *ibuf;
3675   ImBuf *out;
3676 } RenderGaussianBlurEffectInitData;
3677 
3678 typedef struct RenderGaussianBlurEffectThread {
3679   const SeqRenderData *context;
3680   Sequence *seq;
3681   ImBuf *ibuf;
3682   ImBuf *out;
3683   int start_line, tot_line;
3684 } RenderGaussianBlurEffectThread;
3685 
render_effect_execute_init_handle(void * handle_v,int start_line,int tot_line,void * init_data_v)3686 static void render_effect_execute_init_handle(void *handle_v,
3687                                               int start_line,
3688                                               int tot_line,
3689                                               void *init_data_v)
3690 {
3691   RenderGaussianBlurEffectThread *handle = (RenderGaussianBlurEffectThread *)handle_v;
3692   RenderGaussianBlurEffectInitData *init_data = (RenderGaussianBlurEffectInitData *)init_data_v;
3693 
3694   handle->context = init_data->context;
3695   handle->seq = init_data->seq;
3696   handle->ibuf = init_data->ibuf;
3697   handle->out = init_data->out;
3698 
3699   handle->start_line = start_line;
3700   handle->tot_line = tot_line;
3701 }
3702 
render_effect_execute_do_x_thread(void * thread_data_v)3703 static void *render_effect_execute_do_x_thread(void *thread_data_v)
3704 {
3705   RenderGaussianBlurEffectThread *thread_data = (RenderGaussianBlurEffectThread *)thread_data_v;
3706   do_gaussian_blur_effect_x_cb(thread_data->context,
3707                                thread_data->seq,
3708                                thread_data->ibuf,
3709                                thread_data->start_line,
3710                                thread_data->tot_line,
3711                                thread_data->out);
3712   return NULL;
3713 }
3714 
render_effect_execute_do_y_thread(void * thread_data_v)3715 static void *render_effect_execute_do_y_thread(void *thread_data_v)
3716 {
3717   RenderGaussianBlurEffectThread *thread_data = (RenderGaussianBlurEffectThread *)thread_data_v;
3718   do_gaussian_blur_effect_y_cb(thread_data->context,
3719                                thread_data->seq,
3720                                thread_data->ibuf,
3721                                thread_data->start_line,
3722                                thread_data->tot_line,
3723                                thread_data->out);
3724 
3725   return NULL;
3726 }
3727 
do_gaussian_blur_effect(const SeqRenderData * context,Sequence * seq,float UNUSED (cfra),float UNUSED (facf0),float UNUSED (facf1),ImBuf * ibuf1,ImBuf * UNUSED (ibuf2),ImBuf * UNUSED (ibuf3))3728 static ImBuf *do_gaussian_blur_effect(const SeqRenderData *context,
3729                                       Sequence *seq,
3730                                       float UNUSED(cfra),
3731                                       float UNUSED(facf0),
3732                                       float UNUSED(facf1),
3733                                       ImBuf *ibuf1,
3734                                       ImBuf *UNUSED(ibuf2),
3735                                       ImBuf *UNUSED(ibuf3))
3736 {
3737   ImBuf *out = prepare_effect_imbufs(context, ibuf1, NULL, NULL);
3738 
3739   RenderGaussianBlurEffectInitData init_data;
3740 
3741   init_data.context = context;
3742   init_data.seq = seq;
3743   init_data.ibuf = ibuf1;
3744   init_data.out = out;
3745 
3746   IMB_processor_apply_threaded(out->y,
3747                                sizeof(RenderGaussianBlurEffectThread),
3748                                &init_data,
3749                                render_effect_execute_init_handle,
3750                                render_effect_execute_do_x_thread);
3751 
3752   ibuf1 = out;
3753   init_data.ibuf = ibuf1;
3754   out = prepare_effect_imbufs(context, ibuf1, NULL, NULL);
3755   init_data.out = out;
3756 
3757   IMB_processor_apply_threaded(out->y,
3758                                sizeof(RenderGaussianBlurEffectThread),
3759                                &init_data,
3760                                render_effect_execute_init_handle,
3761                                render_effect_execute_do_y_thread);
3762 
3763   IMB_freeImBuf(ibuf1);
3764 
3765   return out;
3766 }
3767 
3768 /*********************** text *************************/
3769 
init_text_effect(Sequence * seq)3770 static void init_text_effect(Sequence *seq)
3771 {
3772   TextVars *data;
3773 
3774   if (seq->effectdata) {
3775     MEM_freeN(seq->effectdata);
3776   }
3777 
3778   data = seq->effectdata = MEM_callocN(sizeof(TextVars), "textvars");
3779   data->text_font = NULL;
3780   data->text_blf_id = -1;
3781   data->text_size = 30;
3782 
3783   copy_v4_fl(data->color, 1.0f);
3784   data->shadow_color[3] = 1.0f;
3785 
3786   BLI_strncpy(data->text, "Text", sizeof(data->text));
3787 
3788   data->loc[0] = 0.5f;
3789   data->align = SEQ_TEXT_ALIGN_X_CENTER;
3790   data->align_y = SEQ_TEXT_ALIGN_Y_BOTTOM;
3791 }
3792 
BKE_sequencer_text_font_unload(TextVars * data,const bool do_id_user)3793 void BKE_sequencer_text_font_unload(TextVars *data, const bool do_id_user)
3794 {
3795   if (data) {
3796     /* Unlink the VFont */
3797     if (do_id_user && data->text_font != NULL) {
3798       id_us_min(&data->text_font->id);
3799       data->text_font = NULL;
3800     }
3801 
3802     /* Unload the BLF font. */
3803     if (data->text_blf_id >= 0) {
3804       BLF_unload_id(data->text_blf_id);
3805     }
3806   }
3807 }
3808 
BKE_sequencer_text_font_load(TextVars * data,const bool do_id_user)3809 void BKE_sequencer_text_font_load(TextVars *data, const bool do_id_user)
3810 {
3811   if (data->text_font != NULL) {
3812     if (do_id_user) {
3813       id_us_plus(&data->text_font->id);
3814     }
3815 
3816     char path[FILE_MAX];
3817     STRNCPY(path, data->text_font->filepath);
3818     BLI_assert(BLI_thread_is_main());
3819     BLI_path_abs(path, ID_BLEND_PATH_FROM_GLOBAL(&data->text_font->id));
3820 
3821     data->text_blf_id = BLF_load(path);
3822   }
3823 }
3824 
free_text_effect(Sequence * seq,const bool do_id_user)3825 static void free_text_effect(Sequence *seq, const bool do_id_user)
3826 {
3827   TextVars *data = seq->effectdata;
3828   BKE_sequencer_text_font_unload(data, do_id_user);
3829 
3830   if (data) {
3831     MEM_freeN(data);
3832     seq->effectdata = NULL;
3833   }
3834 }
3835 
load_text_effect(Sequence * seq)3836 static void load_text_effect(Sequence *seq)
3837 {
3838   TextVars *data = seq->effectdata;
3839   BKE_sequencer_text_font_load(data, false);
3840 }
3841 
copy_text_effect(Sequence * dst,Sequence * src,const int flag)3842 static void copy_text_effect(Sequence *dst, Sequence *src, const int flag)
3843 {
3844   dst->effectdata = MEM_dupallocN(src->effectdata);
3845   TextVars *data = dst->effectdata;
3846 
3847   data->text_blf_id = -1;
3848   BKE_sequencer_text_font_load(data, (flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0);
3849 }
3850 
num_inputs_text(void)3851 static int num_inputs_text(void)
3852 {
3853   return 0;
3854 }
3855 
early_out_text(Sequence * seq,float UNUSED (facf0),float UNUSED (facf1))3856 static int early_out_text(Sequence *seq, float UNUSED(facf0), float UNUSED(facf1))
3857 {
3858   TextVars *data = seq->effectdata;
3859   if (data->text[0] == 0 || data->text_size < 1 ||
3860       ((data->color[3] == 0.0f) &&
3861        (data->shadow_color[3] == 0.0f || (data->flag & SEQ_TEXT_SHADOW) == 0))) {
3862     return EARLY_USE_INPUT_1;
3863   }
3864   return EARLY_NO_INPUT;
3865 }
3866 
do_text_effect(const SeqRenderData * context,Sequence * seq,float UNUSED (cfra),float UNUSED (facf0),float UNUSED (facf1),ImBuf * ibuf1,ImBuf * ibuf2,ImBuf * ibuf3)3867 static ImBuf *do_text_effect(const SeqRenderData *context,
3868                              Sequence *seq,
3869                              float UNUSED(cfra),
3870                              float UNUSED(facf0),
3871                              float UNUSED(facf1),
3872                              ImBuf *ibuf1,
3873                              ImBuf *ibuf2,
3874                              ImBuf *ibuf3)
3875 {
3876   ImBuf *out = prepare_effect_imbufs(context, ibuf1, ibuf2, ibuf3);
3877   TextVars *data = seq->effectdata;
3878   int width = out->x;
3879   int height = out->y;
3880   struct ColorManagedDisplay *display;
3881   const char *display_device;
3882   int font = blf_mono_font_render;
3883   int line_height;
3884   int y_ofs, x, y;
3885   double proxy_size_comp;
3886 
3887   if (data->text_blf_id == SEQ_FONT_NOT_LOADED) {
3888     data->text_blf_id = -1;
3889 
3890     if (data->text_font) {
3891       data->text_blf_id = BLF_load(data->text_font->filepath);
3892     }
3893   }
3894 
3895   if (data->text_blf_id >= 0) {
3896     font = data->text_blf_id;
3897   }
3898 
3899   display_device = context->scene->display_settings.display_device;
3900   display = IMB_colormanagement_display_get_named(display_device);
3901 
3902   /* Compensate text size for preview render size. */
3903   proxy_size_comp = context->scene->r.size / 100.0;
3904   if (context->preview_render_size != SEQ_RENDER_SIZE_SCENE) {
3905     proxy_size_comp = BKE_sequencer_rendersize_to_scale_factor(context->preview_render_size);
3906   }
3907 
3908   /* set before return */
3909   BLF_size(font, proxy_size_comp * data->text_size, 72);
3910 
3911   BLF_enable(font, BLF_WORD_WRAP);
3912 
3913   /* use max width to enable newlines only */
3914   BLF_wordwrap(font, (data->wrap_width != 0.0f) ? data->wrap_width * width : -1);
3915 
3916   BLF_buffer(
3917       font, out->rect_float, (unsigned char *)out->rect, width, height, out->channels, display);
3918 
3919   line_height = BLF_height_max(font);
3920 
3921   y_ofs = -BLF_descender(font);
3922 
3923   x = (data->loc[0] * width);
3924   y = (data->loc[1] * height) + y_ofs;
3925 
3926   if ((data->align == SEQ_TEXT_ALIGN_X_LEFT) && (data->align_y == SEQ_TEXT_ALIGN_Y_TOP)) {
3927     y -= line_height;
3928   }
3929   else {
3930     /* vars for calculating wordwrap */
3931     struct {
3932       struct ResultBLF info;
3933       rctf rect;
3934     } wrap;
3935 
3936     BLF_boundbox_ex(font, data->text, sizeof(data->text), &wrap.rect, &wrap.info);
3937 
3938     if (data->align == SEQ_TEXT_ALIGN_X_RIGHT) {
3939       x -= BLI_rctf_size_x(&wrap.rect);
3940     }
3941     else if (data->align == SEQ_TEXT_ALIGN_X_CENTER) {
3942       x -= BLI_rctf_size_x(&wrap.rect) / 2;
3943     }
3944 
3945     if (data->align_y == SEQ_TEXT_ALIGN_Y_TOP) {
3946       y -= line_height;
3947     }
3948     else if (data->align_y == SEQ_TEXT_ALIGN_Y_BOTTOM) {
3949       y += (wrap.info.lines - 1) * line_height;
3950     }
3951     else if (data->align_y == SEQ_TEXT_ALIGN_Y_CENTER) {
3952       y += (((wrap.info.lines - 1) / 2) * line_height) - (line_height / 2);
3953     }
3954   }
3955 
3956   /* BLF_SHADOW won't work with buffers, instead use cheap shadow trick */
3957   if (data->flag & SEQ_TEXT_SHADOW) {
3958     int fontx, fonty;
3959     fontx = BLF_width_max(font);
3960     fonty = line_height;
3961     BLF_position(font, x + max_ii(fontx / 25, 1), y + max_ii(fonty / 25, 1), 0.0f);
3962     BLF_buffer_col(font, data->shadow_color);
3963     BLF_draw_buffer(font, data->text, BLF_DRAW_STR_DUMMY_MAX);
3964   }
3965 
3966   BLF_position(font, x, y, 0.0f);
3967   BLF_buffer_col(font, data->color);
3968   BLF_draw_buffer(font, data->text, BLF_DRAW_STR_DUMMY_MAX);
3969 
3970   BLF_buffer(font, NULL, NULL, 0, 0, 0, NULL);
3971 
3972   BLF_disable(font, BLF_WORD_WRAP);
3973 
3974   return out;
3975 }
3976 
3977 /*********************** sequence effect factory *************************/
3978 
init_noop(Sequence * UNUSED (seq))3979 static void init_noop(Sequence *UNUSED(seq))
3980 {
3981 }
3982 
load_noop(Sequence * UNUSED (seq))3983 static void load_noop(Sequence *UNUSED(seq))
3984 {
3985 }
3986 
free_noop(Sequence * UNUSED (seq),const bool UNUSED (do_id_user))3987 static void free_noop(Sequence *UNUSED(seq), const bool UNUSED(do_id_user))
3988 {
3989 }
3990 
num_inputs_default(void)3991 static int num_inputs_default(void)
3992 {
3993   return 2;
3994 }
3995 
copy_effect_default(Sequence * dst,Sequence * src,const int UNUSED (flag))3996 static void copy_effect_default(Sequence *dst, Sequence *src, const int UNUSED(flag))
3997 {
3998   dst->effectdata = MEM_dupallocN(src->effectdata);
3999 }
4000 
free_effect_default(Sequence * seq,const bool UNUSED (do_id_user))4001 static void free_effect_default(Sequence *seq, const bool UNUSED(do_id_user))
4002 {
4003   if (seq->effectdata) {
4004     MEM_freeN(seq->effectdata);
4005   }
4006 
4007   seq->effectdata = NULL;
4008 }
4009 
early_out_noop(Sequence * UNUSED (seq),float UNUSED (facf0),float UNUSED (facf1))4010 static int early_out_noop(Sequence *UNUSED(seq), float UNUSED(facf0), float UNUSED(facf1))
4011 {
4012   return EARLY_DO_EFFECT;
4013 }
4014 
early_out_fade(Sequence * UNUSED (seq),float facf0,float facf1)4015 static int early_out_fade(Sequence *UNUSED(seq), float facf0, float facf1)
4016 {
4017   if (facf0 == 0.0f && facf1 == 0.0f) {
4018     return EARLY_USE_INPUT_1;
4019   }
4020   if (facf0 == 1.0f && facf1 == 1.0f) {
4021     return EARLY_USE_INPUT_2;
4022   }
4023   return EARLY_DO_EFFECT;
4024 }
4025 
early_out_mul_input2(Sequence * UNUSED (seq),float facf0,float facf1)4026 static int early_out_mul_input2(Sequence *UNUSED(seq), float facf0, float facf1)
4027 {
4028   if (facf0 == 0.0f && facf1 == 0.0f) {
4029     return EARLY_USE_INPUT_1;
4030   }
4031   return EARLY_DO_EFFECT;
4032 }
4033 
store_icu_yrange_noop(Sequence * UNUSED (seq),short UNUSED (adrcode),float * UNUSED (ymin),float * UNUSED (ymax))4034 static void store_icu_yrange_noop(Sequence *UNUSED(seq),
4035                                   short UNUSED(adrcode),
4036                                   float *UNUSED(ymin),
4037                                   float *UNUSED(ymax))
4038 {
4039   /* defaults are fine */
4040 }
4041 
get_default_fac_noop(Sequence * UNUSED (seq),float UNUSED (cfra),float * facf0,float * facf1)4042 static void get_default_fac_noop(Sequence *UNUSED(seq),
4043                                  float UNUSED(cfra),
4044                                  float *facf0,
4045                                  float *facf1)
4046 {
4047   *facf0 = *facf1 = 1.0;
4048 }
4049 
get_default_fac_fade(Sequence * seq,float cfra,float * facf0,float * facf1)4050 static void get_default_fac_fade(Sequence *seq, float cfra, float *facf0, float *facf1)
4051 {
4052   *facf0 = (float)(cfra - seq->startdisp);
4053   *facf1 = (float)(*facf0 + 0.5f);
4054   *facf0 /= seq->len;
4055   *facf1 /= seq->len;
4056 }
4057 
init_execution(const SeqRenderData * context,ImBuf * ibuf1,ImBuf * ibuf2,ImBuf * ibuf3)4058 static struct ImBuf *init_execution(const SeqRenderData *context,
4059                                     ImBuf *ibuf1,
4060                                     ImBuf *ibuf2,
4061                                     ImBuf *ibuf3)
4062 {
4063   ImBuf *out = prepare_effect_imbufs(context, ibuf1, ibuf2, ibuf3);
4064 
4065   return out;
4066 }
4067 
get_sequence_effect_impl(int seq_type)4068 static struct SeqEffectHandle get_sequence_effect_impl(int seq_type)
4069 {
4070   struct SeqEffectHandle rval;
4071   int sequence_type = seq_type;
4072 
4073   rval.multithreaded = false;
4074   rval.supports_mask = false;
4075   rval.init = init_noop;
4076   rval.num_inputs = num_inputs_default;
4077   rval.load = load_noop;
4078   rval.free = free_noop;
4079   rval.early_out = early_out_noop;
4080   rval.get_default_fac = get_default_fac_noop;
4081   rval.store_icu_yrange = store_icu_yrange_noop;
4082   rval.execute = NULL;
4083   rval.init_execution = init_execution;
4084   rval.execute_slice = NULL;
4085   rval.copy = NULL;
4086 
4087   switch (sequence_type) {
4088     case SEQ_TYPE_CROSS:
4089       rval.multithreaded = true;
4090       rval.execute_slice = do_cross_effect;
4091       rval.early_out = early_out_fade;
4092       rval.get_default_fac = get_default_fac_fade;
4093       break;
4094     case SEQ_TYPE_GAMCROSS:
4095       rval.multithreaded = true;
4096       rval.init = init_gammacross;
4097       rval.load = load_gammacross;
4098       rval.free = free_gammacross;
4099       rval.early_out = early_out_fade;
4100       rval.get_default_fac = get_default_fac_fade;
4101       rval.init_execution = gammacross_init_execution;
4102       rval.execute_slice = do_gammacross_effect;
4103       break;
4104     case SEQ_TYPE_ADD:
4105       rval.multithreaded = true;
4106       rval.execute_slice = do_add_effect;
4107       rval.early_out = early_out_mul_input2;
4108       break;
4109     case SEQ_TYPE_SUB:
4110       rval.multithreaded = true;
4111       rval.execute_slice = do_sub_effect;
4112       rval.early_out = early_out_mul_input2;
4113       break;
4114     case SEQ_TYPE_MUL:
4115       rval.multithreaded = true;
4116       rval.execute_slice = do_mul_effect;
4117       rval.early_out = early_out_mul_input2;
4118       break;
4119     case SEQ_TYPE_SCREEN:
4120     case SEQ_TYPE_OVERLAY:
4121     case SEQ_TYPE_COLOR_BURN:
4122     case SEQ_TYPE_LINEAR_BURN:
4123     case SEQ_TYPE_DARKEN:
4124     case SEQ_TYPE_LIGHTEN:
4125     case SEQ_TYPE_DODGE:
4126     case SEQ_TYPE_SOFT_LIGHT:
4127     case SEQ_TYPE_HARD_LIGHT:
4128     case SEQ_TYPE_PIN_LIGHT:
4129     case SEQ_TYPE_LIN_LIGHT:
4130     case SEQ_TYPE_VIVID_LIGHT:
4131     case SEQ_TYPE_BLEND_COLOR:
4132     case SEQ_TYPE_HUE:
4133     case SEQ_TYPE_SATURATION:
4134     case SEQ_TYPE_VALUE:
4135     case SEQ_TYPE_DIFFERENCE:
4136     case SEQ_TYPE_EXCLUSION:
4137       rval.multithreaded = true;
4138       rval.execute_slice = do_blend_mode_effect;
4139       rval.early_out = early_out_mul_input2;
4140       break;
4141     case SEQ_TYPE_COLORMIX:
4142       rval.multithreaded = true;
4143       rval.init = init_colormix_effect;
4144       rval.free = free_effect_default;
4145       rval.copy = copy_effect_default;
4146       rval.execute_slice = do_colormix_effect;
4147       rval.early_out = early_out_mul_input2;
4148       break;
4149     case SEQ_TYPE_ALPHAOVER:
4150       rval.multithreaded = true;
4151       rval.init = init_alpha_over_or_under;
4152       rval.execute_slice = do_alphaover_effect;
4153       break;
4154     case SEQ_TYPE_OVERDROP:
4155       rval.multithreaded = true;
4156       rval.execute_slice = do_overdrop_effect;
4157       break;
4158     case SEQ_TYPE_ALPHAUNDER:
4159       rval.multithreaded = true;
4160       rval.init = init_alpha_over_or_under;
4161       rval.execute_slice = do_alphaunder_effect;
4162       break;
4163     case SEQ_TYPE_WIPE:
4164       rval.init = init_wipe_effect;
4165       rval.num_inputs = num_inputs_wipe;
4166       rval.free = free_wipe_effect;
4167       rval.copy = copy_wipe_effect;
4168       rval.early_out = early_out_fade;
4169       rval.get_default_fac = get_default_fac_fade;
4170       rval.execute = do_wipe_effect;
4171       break;
4172     case SEQ_TYPE_GLOW:
4173       rval.init = init_glow_effect;
4174       rval.num_inputs = num_inputs_glow;
4175       rval.free = free_glow_effect;
4176       rval.copy = copy_glow_effect;
4177       rval.execute = do_glow_effect;
4178       break;
4179     case SEQ_TYPE_TRANSFORM:
4180       rval.multithreaded = true;
4181       rval.init = init_transform_effect;
4182       rval.num_inputs = num_inputs_transform;
4183       rval.free = free_transform_effect;
4184       rval.copy = copy_transform_effect;
4185       rval.execute_slice = do_transform_effect;
4186       break;
4187     case SEQ_TYPE_SPEED:
4188       rval.init = init_speed_effect;
4189       rval.num_inputs = num_inputs_speed;
4190       rval.load = load_speed_effect;
4191       rval.free = free_speed_effect;
4192       rval.copy = copy_speed_effect;
4193       rval.execute = do_speed_effect;
4194       rval.early_out = early_out_speed;
4195       rval.store_icu_yrange = store_icu_yrange_speed;
4196       break;
4197     case SEQ_TYPE_COLOR:
4198       rval.init = init_solid_color;
4199       rval.num_inputs = num_inputs_color;
4200       rval.early_out = early_out_color;
4201       rval.free = free_solid_color;
4202       rval.copy = copy_solid_color;
4203       rval.execute = do_solid_color;
4204       break;
4205     case SEQ_TYPE_MULTICAM:
4206       rval.num_inputs = num_inputs_multicam;
4207       rval.early_out = early_out_multicam;
4208       rval.execute = do_multicam;
4209       break;
4210     case SEQ_TYPE_ADJUSTMENT:
4211       rval.supports_mask = true;
4212       rval.num_inputs = num_inputs_adjustment;
4213       rval.early_out = early_out_adjustment;
4214       rval.execute = do_adjustment;
4215       break;
4216     case SEQ_TYPE_GAUSSIAN_BLUR:
4217       rval.init = init_gaussian_blur_effect;
4218       rval.num_inputs = num_inputs_gaussian_blur;
4219       rval.free = free_gaussian_blur_effect;
4220       rval.copy = copy_gaussian_blur_effect;
4221       rval.early_out = early_out_gaussian_blur;
4222       rval.execute = do_gaussian_blur_effect;
4223       break;
4224     case SEQ_TYPE_TEXT:
4225       rval.num_inputs = num_inputs_text;
4226       rval.init = init_text_effect;
4227       rval.free = free_text_effect;
4228       rval.load = load_text_effect;
4229       rval.copy = copy_text_effect;
4230       rval.early_out = early_out_text;
4231       rval.execute = do_text_effect;
4232       break;
4233   }
4234 
4235   return rval;
4236 }
4237 
BKE_sequence_get_effect(Sequence * seq)4238 struct SeqEffectHandle BKE_sequence_get_effect(Sequence *seq)
4239 {
4240   struct SeqEffectHandle rval = {false, false, NULL};
4241 
4242   if (seq->type & SEQ_TYPE_EFFECT) {
4243     rval = get_sequence_effect_impl(seq->type);
4244     if ((seq->flag & SEQ_EFFECT_NOT_LOADED) != 0) {
4245       rval.load(seq);
4246       seq->flag &= ~SEQ_EFFECT_NOT_LOADED;
4247     }
4248   }
4249 
4250   return rval;
4251 }
4252 
BKE_sequence_get_blend(Sequence * seq)4253 struct SeqEffectHandle BKE_sequence_get_blend(Sequence *seq)
4254 {
4255   struct SeqEffectHandle rval = {false, false, NULL};
4256 
4257   if (seq->blend_mode != 0) {
4258     if ((seq->flag & SEQ_EFFECT_NOT_LOADED) != 0) {
4259       /* load the effect first */
4260       rval = get_sequence_effect_impl(seq->type);
4261       rval.load(seq);
4262     }
4263 
4264     rval = get_sequence_effect_impl(seq->blend_mode);
4265     if ((seq->flag & SEQ_EFFECT_NOT_LOADED) != 0) {
4266       /* now load the blend and unset unloaded flag */
4267       rval.load(seq);
4268       seq->flag &= ~SEQ_EFFECT_NOT_LOADED;
4269     }
4270   }
4271 
4272   return rval;
4273 }
4274 
BKE_sequence_effect_get_num_inputs(int seq_type)4275 int BKE_sequence_effect_get_num_inputs(int seq_type)
4276 {
4277   struct SeqEffectHandle rval = get_sequence_effect_impl(seq_type);
4278 
4279   int cnt = rval.num_inputs();
4280   if (rval.execute || (rval.execute_slice && rval.init_execution)) {
4281     return cnt;
4282   }
4283   return 0;
4284 }
4285 
BKE_sequence_effect_get_supports_mask(int seq_type)4286 int BKE_sequence_effect_get_supports_mask(int seq_type)
4287 {
4288   struct SeqEffectHandle rval = get_sequence_effect_impl(seq_type);
4289 
4290   return rval.supports_mask;
4291 }
4292