4a8601df0b8b314e7c5be73c4234f92c409efd83
[blender.git] / source / blender / blenkernel / intern / mask_evaluate.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2012 Blender Foundation.
19  * All rights reserved.
20  *
21  * Contributor(s): Blender Foundation,
22  *                 Sergey Sharybin,
23  *                 Campbell Barton
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/blenkernel/intern/mask_evaluate.c
29  *  \ingroup bke
30  *
31  * Functions for evaluating the mask beziers into points for the outline and feather.
32  */
33
34 #include <stddef.h>
35 #include <string.h>
36
37 #include "MEM_guardedalloc.h"
38
39 #include "BLI_utildefines.h"
40 #include "BLI_path_util.h"
41 #include "BLI_string.h"
42 #include "BLI_listbase.h"
43 #include "BLI_math.h"
44
45 #include "DNA_mask_types.h"
46 #include "DNA_node_types.h"
47 #include "DNA_scene_types.h"
48 #include "DNA_object_types.h"
49 #include "DNA_screen_types.h"
50 #include "DNA_space_types.h"
51 #include "DNA_movieclip_types.h"
52 #include "DNA_tracking_types.h"
53 #include "DNA_sequence_types.h"
54
55 #include "BKE_curve.h"
56 #include "BKE_global.h"
57 #include "BKE_library.h"
58 #include "BKE_main.h"
59 #include "BKE_mask.h"
60 #include "BKE_node.h"
61 #include "BKE_sequencer.h"
62 #include "BKE_tracking.h"
63 #include "BKE_movieclip.h"
64
65
66 unsigned int BKE_mask_spline_resolution(MaskSpline *spline, int width, int height)
67 {
68         float max_segment = 0.01f;
69         unsigned int i, resol = 1;
70
71         if (width != 0 && height != 0) {
72                 max_segment = 1.0f / (float)maxi(width, height);
73         }
74
75         for (i = 0; i < spline->tot_point; i++) {
76                 MaskSplinePoint *point = &spline->points[i];
77                 BezTriple *bezt_curr, *bezt_next;
78                 float a, b, c, len;
79                 unsigned int cur_resol;
80
81                 bezt_curr = &point->bezt;
82                 bezt_next = BKE_mask_spline_point_next_bezt(spline, spline->points, point);
83
84                 if (bezt_next == NULL) {
85                         break;
86                 }
87
88                 a = len_v3v3(bezt_curr->vec[1], bezt_curr->vec[2]);
89                 b = len_v3v3(bezt_curr->vec[2], bezt_next->vec[0]);
90                 c = len_v3v3(bezt_next->vec[0], bezt_next->vec[1]);
91
92                 len = a + b + c;
93                 cur_resol = len / max_segment;
94
95                 resol = MAX2(resol, cur_resol);
96
97                 if (resol >= MASK_RESOL_MAX) {
98                         break;
99                 }
100         }
101
102         return CLAMPIS(resol, 1, MASK_RESOL_MAX);
103 }
104
105 unsigned int BKE_mask_spline_feather_resolution(MaskSpline *spline, int width, int height)
106 {
107         const float max_segment = 0.005;
108         unsigned int resol = BKE_mask_spline_resolution(spline, width, height);
109         float max_jump = 0.0f;
110         int i;
111
112         /* avoid checking the featrher if we already hit the maximum value */
113         if (resol >= MASK_RESOL_MAX) {
114                 return MASK_RESOL_MAX;
115         }
116
117         for (i = 0; i < spline->tot_point; i++) {
118                 MaskSplinePoint *point = &spline->points[i];
119                 float prev_u, prev_w;
120                 int j;
121
122                 prev_u = 0.0f;
123                 prev_w = point->bezt.weight;
124
125                 for (j = 0; j < point->tot_uw; j++) {
126                         const float w_diff = (point->uw[j].w - prev_w);
127                         const float u_diff = (point->uw[j].u - prev_u);
128
129                         /* avoid divide by zero and very high values,
130                          * though these get clamped eventually */
131                         if (u_diff > FLT_EPSILON) {
132                                 float jump = fabsf(w_diff / u_diff);
133
134                                 max_jump = MAX2(max_jump, jump);
135                         }
136
137                         prev_u = point->uw[j].u;
138                         prev_w = point->uw[j].w;
139                 }
140         }
141
142         resol += max_jump / max_segment;
143
144         return CLAMPIS(resol, 1, MASK_RESOL_MAX);
145 }
146
147 int BKE_mask_spline_differentiate_calc_total(const MaskSpline *spline, const unsigned int resol)
148 {
149         if (spline->flag & MASK_SPLINE_CYCLIC) {
150                 return spline->tot_point * resol;
151         }
152         else {
153                 return ((spline->tot_point - 1) * resol) + 1;
154         }
155 }
156
157 float (*BKE_mask_spline_differentiate_with_resolution_ex(MaskSpline *spline,
158                                                          int *tot_diff_point,
159                                                          const unsigned int resol
160                                                          ))[2]
161 {
162         MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
163
164         MaskSplinePoint *point_curr, *point_prev;
165         float (*diff_points)[2], (*fp)[2];
166         const int tot = BKE_mask_spline_differentiate_calc_total(spline, resol);
167         int a;
168
169         if (spline->tot_point <= 1) {
170                 /* nothing to differentiate */
171                 *tot_diff_point = 0;
172                 return NULL;
173         }
174
175         /* len+1 because of 'forward_diff_bezier' function */
176         *tot_diff_point = tot;
177         diff_points = fp = MEM_mallocN((tot + 1) * sizeof(*diff_points), "mask spline vets");
178
179         a = spline->tot_point - 1;
180         if (spline->flag & MASK_SPLINE_CYCLIC)
181                 a++;
182
183         point_prev = points_array;
184         point_curr = point_prev + 1;
185
186         while (a--) {
187                 BezTriple *bezt_prev;
188                 BezTriple *bezt_curr;
189                 int j;
190
191                 if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC))
192                         point_curr = points_array;
193
194                 bezt_prev = &point_prev->bezt;
195                 bezt_curr = &point_curr->bezt;
196
197                 for (j = 0; j < 2; j++) {
198                         BKE_curve_forward_diff_bezier(bezt_prev->vec[1][j], bezt_prev->vec[2][j],
199                                                       bezt_curr->vec[0][j], bezt_curr->vec[1][j],
200                                                       &(*fp)[j], resol, 2 * sizeof(float));
201                 }
202
203                 fp += resol;
204
205                 if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC) == 0) {
206                         copy_v2_v2(*fp, bezt_curr->vec[1]);
207                 }
208
209                 point_prev = point_curr;
210                 point_curr++;
211         }
212
213         return diff_points;
214 }
215
216 float (*BKE_mask_spline_differentiate_with_resolution(MaskSpline *spline, int width, int height,
217                                                       int *tot_diff_point
218                                                       ))[2]
219 {
220         int unsigned resol = BKE_mask_spline_resolution(spline, width, height);
221
222         return BKE_mask_spline_differentiate_with_resolution_ex(spline, tot_diff_point, resol);
223 }
224
225 float (*BKE_mask_spline_differentiate(MaskSpline *spline, int *tot_diff_point))[2]
226 {
227         return BKE_mask_spline_differentiate_with_resolution(spline, 0, 0, tot_diff_point);
228 }
229
230 /* ** feather points self-intersection collapse routine ** */
231
232 typedef struct FeatherEdgesBucket {
233         int tot_segment;
234         int (*segments)[2];
235         int alloc_segment;
236 } FeatherEdgesBucket;
237
238 static void feather_bucket_add_edge(FeatherEdgesBucket *bucket, int start, int end)
239 {
240         const int alloc_delta = 256;
241
242         if (bucket->tot_segment >= bucket->alloc_segment) {
243                 if (!bucket->segments) {
244                         bucket->segments = MEM_callocN(alloc_delta * sizeof(*bucket->segments), "feather bucket segments");
245                 }
246                 else {
247                         bucket->segments = MEM_reallocN(bucket->segments,
248                                         (alloc_delta + bucket->tot_segment) * sizeof(*bucket->segments));
249                 }
250
251                 bucket->alloc_segment += alloc_delta;
252         }
253
254         bucket->segments[bucket->tot_segment][0] = start;
255         bucket->segments[bucket->tot_segment][1] = end;
256
257         bucket->tot_segment++;
258 }
259
260 static void feather_bucket_check_intersect(float (*feather_points)[2], int tot_feather_point, FeatherEdgesBucket *bucket,
261                                            int cur_a, int cur_b)
262 {
263         int i;
264
265         float *v1 = (float *) feather_points[cur_a];
266         float *v2 = (float *) feather_points[cur_b];
267
268         for (i = 0; i < bucket->tot_segment; i++) {
269                 int check_a = bucket->segments[i][0];
270                 int check_b = bucket->segments[i][1];
271
272                 float *v3 = (float *) feather_points[check_a];
273                 float *v4 = (float *) feather_points[check_b];
274
275                 if (check_a >= cur_a - 1 || cur_b == check_a)
276                         continue;
277
278                 if (isect_seg_seg_v2(v1, v2, v3, v4)) {
279                         int k;
280                         float p[2];
281                         float min_a[2], max_a[2];
282                         float min_b[2], max_b[2];
283
284                         isect_seg_seg_v2_point(v1, v2, v3, v4, p);
285
286                         INIT_MINMAX2(min_a, max_a);
287                         INIT_MINMAX2(min_b, max_b);
288
289                         /* collapse loop with smaller AABB */
290                         for (k = 0; k < tot_feather_point; k++) {
291                                 if (k >= check_b && k <= cur_a) {
292                                         DO_MINMAX2(feather_points[k], min_a, max_a);
293                                 }
294                                 else {
295                                         DO_MINMAX2(feather_points[k], min_b, max_b);
296                                 }
297                         }
298
299                         if (max_a[0] - min_a[0] < max_b[0] - min_b[0] ||
300                             max_a[1] - min_a[1] < max_b[1] - min_b[1])
301                         {
302                                 for (k = check_b; k <= cur_a; k++) {
303                                         copy_v2_v2(feather_points[k], p);
304                                 }
305                         }
306                         else {
307                                 for (k = 0; k <= check_a; k++) {
308                                         copy_v2_v2(feather_points[k], p);
309                                 }
310
311                                 if (cur_b != 0) {
312                                         for (k = cur_b; k < tot_feather_point; k++) {
313                                                 copy_v2_v2(feather_points[k], p);
314                                         }
315                                 }
316                         }
317                 }
318         }
319 }
320
321 static int feather_bucket_index_from_coord(float co[2], const float min[2], const float bucket_scale[2],
322                                            const int buckets_per_side)
323 {
324         int x = (int) ((co[0] - min[0]) * bucket_scale[0]);
325         int y = (int) ((co[1] - min[1]) * bucket_scale[1]);
326
327         if (x == buckets_per_side)
328                 x--;
329
330         if (y == buckets_per_side)
331                 y--;
332
333         return y * buckets_per_side + x;
334 }
335
336 static void feather_bucket_get_diagonal(FeatherEdgesBucket *buckets, int start_bucket_index, int end_bucket_index,
337                                         int buckets_per_side, FeatherEdgesBucket **diagonal_bucket_a_r,
338                                         FeatherEdgesBucket **diagonal_bucket_b_r)
339 {
340         int start_bucket_x = start_bucket_index % buckets_per_side;
341         int start_bucket_y = start_bucket_index / buckets_per_side;
342
343         int end_bucket_x = end_bucket_index % buckets_per_side;
344         int end_bucket_y = end_bucket_index / buckets_per_side;
345
346         int diagonal_bucket_a_index = start_bucket_y * buckets_per_side + end_bucket_x;
347         int diagonal_bucket_b_index = end_bucket_y * buckets_per_side + start_bucket_x;
348
349         *diagonal_bucket_a_r = &buckets[diagonal_bucket_a_index];
350         *diagonal_bucket_b_r = &buckets[diagonal_bucket_b_index];
351 }
352
353 void BKE_mask_spline_feather_collapse_inner_loops(MaskSpline *spline, float (*feather_points)[2], const int tot_feather_point)
354 {
355 #define BUCKET_INDEX(co) \
356         feather_bucket_index_from_coord(co, min, bucket_scale, buckets_per_side)
357
358         int buckets_per_side, tot_bucket;
359         float bucket_size, bucket_scale[2];
360
361         FeatherEdgesBucket *buckets;
362
363         int i;
364         float min[2], max[2];
365         float max_delta_x = -1.0f, max_delta_y = -1.0f, max_delta;
366
367         if (tot_feather_point < 4) {
368                 /* self-intersection works only for quads at least,
369                  * in other cases polygon can't be self-intersecting anyway
370                  */
371
372                 return;
373         }
374
375         /* find min/max corners of mask to build buckets in that space */
376         INIT_MINMAX2(min, max);
377
378         for (i = 0; i < tot_feather_point; i++) {
379                 int next = i + 1;
380                 float delta;
381
382                 DO_MINMAX2(feather_points[i], min, max);
383
384                 if (next == tot_feather_point) {
385                         if (spline->flag & MASK_SPLINE_CYCLIC)
386                                 next = 0;
387                         else
388                                 break;
389                 }
390
391                 delta = fabsf(feather_points[i][0] - feather_points[next][0]);
392                 if (delta > max_delta_x)
393                         max_delta_x = delta;
394
395                 delta = fabsf(feather_points[i][1] - feather_points[next][1]);
396                 if (delta > max_delta_y)
397                         max_delta_y = delta;
398         }
399
400         /* prevent divisionsby zero by ensuring bounding box is not collapsed */
401         if (max[0] - min[0] < FLT_EPSILON) {
402                 max[0] += 0.01f;
403                 min[0] -= 0.01f;
404         }
405
406         if (max[1] - min[1] < FLT_EPSILON) {
407                 max[1] += 0.01f;
408                 min[1] -= 0.01f;
409         }
410
411         /* use dynamically calculated buckets per side, so we likely wouldn't
412          * run into a situation when segment doesn't fit two buckets which is
413          * pain collecting candidates for intersection
414          */
415
416         max_delta_x /= max[0] - min[0];
417         max_delta_y /= max[1] - min[1];
418
419         max_delta = MAX2(max_delta_x, max_delta_y);
420
421         buckets_per_side = MIN2(512, 0.9f / max_delta);
422
423         if (buckets_per_side == 0) {
424                 /* happens when some segment fills the whole bounding box across some of dimension */
425
426                 buckets_per_side = 1;
427         }
428
429         tot_bucket = buckets_per_side * buckets_per_side;
430         bucket_size = 1.0f / buckets_per_side;
431
432         /* pre-compute multipliers, to save mathematical operations in loops */
433         bucket_scale[0] = 1.0f / ((max[0] - min[0]) * bucket_size);
434         bucket_scale[1] = 1.0f / ((max[1] - min[1]) * bucket_size);
435
436         /* fill in buckets' edges */
437         buckets = MEM_callocN(sizeof(FeatherEdgesBucket) * tot_bucket, "feather buckets");
438
439         for (i = 0; i < tot_feather_point; i++) {
440                 int start = i, end = i + 1;
441                 int start_bucket_index, end_bucket_index;
442
443                 if (end == tot_feather_point) {
444                         if (spline->flag & MASK_SPLINE_CYCLIC)
445                                 end = 0;
446                         else
447                                 break;
448                 }
449
450                 start_bucket_index = BUCKET_INDEX(feather_points[start]);
451                 end_bucket_index = BUCKET_INDEX(feather_points[end]);
452
453                 feather_bucket_add_edge(&buckets[start_bucket_index], start, end);
454
455                 if (start_bucket_index != end_bucket_index) {
456                         FeatherEdgesBucket *end_bucket = &buckets[end_bucket_index];
457                         FeatherEdgesBucket *diagonal_bucket_a, *diagonal_bucket_b;
458
459                         feather_bucket_get_diagonal(buckets, start_bucket_index, end_bucket_index, buckets_per_side,
460                                                     &diagonal_bucket_a, &diagonal_bucket_b);
461
462                         feather_bucket_add_edge(end_bucket, start, end);
463                         feather_bucket_add_edge(diagonal_bucket_a, start, end);
464                         feather_bucket_add_edge(diagonal_bucket_a, start, end);
465                 }
466         }
467
468         /* check all edges for intersection with edges from their buckets */
469         for (i = 0; i < tot_feather_point; i++) {
470                 int cur_a = i, cur_b = i + 1;
471                 int start_bucket_index, end_bucket_index;
472
473                 FeatherEdgesBucket *start_bucket;
474
475                 if (cur_b == tot_feather_point)
476                         cur_b = 0;
477
478                 start_bucket_index = BUCKET_INDEX(feather_points[cur_a]);
479                 end_bucket_index = BUCKET_INDEX(feather_points[cur_b]);
480
481                 start_bucket = &buckets[start_bucket_index];
482
483                 feather_bucket_check_intersect(feather_points, tot_feather_point, start_bucket, cur_a, cur_b);
484
485                 if (start_bucket_index != end_bucket_index) {
486                         FeatherEdgesBucket *end_bucket = &buckets[end_bucket_index];
487                         FeatherEdgesBucket *diagonal_bucket_a, *diagonal_bucket_b;
488
489                         feather_bucket_get_diagonal(buckets, start_bucket_index, end_bucket_index, buckets_per_side,
490                                                     &diagonal_bucket_a, &diagonal_bucket_b);
491
492                         feather_bucket_check_intersect(feather_points, tot_feather_point, end_bucket, cur_a, cur_b);
493                         feather_bucket_check_intersect(feather_points, tot_feather_point, diagonal_bucket_a, cur_a, cur_b);
494                         feather_bucket_check_intersect(feather_points, tot_feather_point, diagonal_bucket_b, cur_a, cur_b);
495                 }
496         }
497
498         /* free buckets */
499         for (i = 0; i < tot_bucket; i++) {
500                 if (buckets[i].segments)
501                         MEM_freeN(buckets[i].segments);
502         }
503
504         MEM_freeN(buckets);
505
506 #undef BUCKET_INDEX
507 }
508
509 /** only called from #BKE_mask_spline_feather_differentiated_points_with_resolution_ex() ! */
510 static float (*mask_spline_feather_differentiated_points_with_resolution_ex__even(MaskSpline *spline,
511                                                                                   int *tot_feather_point,
512                                                                                   const unsigned int resol,
513                                                                                   const int do_feather_isect
514                                                                                   ))[2]
515 {
516         MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
517         MaskSplinePoint *point_curr, *point_prev;
518         float (*feather)[2], (*fp)[2];
519
520         const int tot = BKE_mask_spline_differentiate_calc_total(spline, resol);
521         int a;
522
523         /* tot+1 because of 'forward_diff_bezier' function */
524         feather = fp = MEM_mallocN((tot + 1) * sizeof(*feather), "mask spline feather diff points");
525
526         a = spline->tot_point - 1;
527         if (spline->flag & MASK_SPLINE_CYCLIC)
528                 a++;
529
530         point_prev = points_array;
531         point_curr = point_prev + 1;
532
533         while (a--) {
534                 /* BezTriple *bezt_prev; */  /* UNUSED */
535                 /* BezTriple *bezt_curr; */      /* UNUSED */
536                 int j;
537
538                 if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC))
539                         point_curr = points_array;
540
541
542                 /* bezt_prev = &point_prev->bezt; */
543                 /* bezt_curr = &point_curr->bezt; */
544
545                 for (j = 0; j < resol; j++, fp++) {
546                         float u = (float) j / resol, weight;
547                         float co[2], n[2];
548
549                         /* TODO - these calls all calculate similar things
550                          * could be unified for some speed */
551                         BKE_mask_point_segment_co(spline, point_prev, u, co);
552                         BKE_mask_point_normal(spline, point_prev, u, n);
553                         weight = BKE_mask_point_weight(spline, point_prev, u);
554
555                         madd_v2_v2v2fl(*fp, co, n, weight);
556                 }
557
558                 if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC) == 0) {
559                         float u = 1.0f, weight;
560                         float co[2], n[2];
561
562                         BKE_mask_point_segment_co(spline, point_prev, u, co);
563                         BKE_mask_point_normal(spline, point_prev, u, n);
564                         weight = BKE_mask_point_weight(spline, point_prev, u);
565
566                         madd_v2_v2v2fl(*fp, co, n, weight);
567                 }
568
569                 point_prev = point_curr;
570                 point_curr++;
571         }
572
573         *tot_feather_point = tot;
574
575         if ((spline->flag & MASK_SPLINE_NOINTERSECT) && do_feather_isect) {
576                 BKE_mask_spline_feather_collapse_inner_loops(spline, feather, tot);
577         }
578
579         return feather;
580 }
581
582 /** only called from #BKE_mask_spline_feather_differentiated_points_with_resolution_ex() ! */
583 static float (*mask_spline_feather_differentiated_points_with_resolution_ex__double(MaskSpline *spline,
584                                                                                     int *tot_feather_point,
585                                                                                     const unsigned int resol,
586                                                                                     const int do_feather_isect
587                                                                                     ))[2]
588 {
589         MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
590
591         MaskSplinePoint *point_curr, *point_prev;
592         float (*feather)[2], (*fp)[2];
593         const int tot = BKE_mask_spline_differentiate_calc_total(spline, resol);
594         int a;
595
596         if (spline->tot_point <= 1) {
597                 /* nothing to differentiate */
598                 *tot_feather_point = 0;
599                 return NULL;
600         }
601
602         /* len+1 because of 'forward_diff_bezier' function */
603         *tot_feather_point = tot;
604         feather = fp = MEM_mallocN((tot + 1) * sizeof(*feather), "mask spline vets");
605
606         a = spline->tot_point - 1;
607         if (spline->flag & MASK_SPLINE_CYCLIC)
608                 a++;
609
610         point_prev = points_array;
611         point_curr = point_prev + 1;
612
613         while (a--) {
614                 BezTriple local_prevbezt;
615                 BezTriple local_bezt;
616                 float point_prev_n[2], point_curr_n[2], tvec[2];
617                 float weight_prev, weight_curr;
618                 float len_base, len_feather, len_scalar;
619
620                 BezTriple *bezt_prev;
621                 BezTriple *bezt_curr;
622                 int j;
623
624                 if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC))
625                         point_curr = points_array;
626
627                 bezt_prev = &point_prev->bezt;
628                 bezt_curr = &point_curr->bezt;
629
630                 /* modified copy for feather */
631                 local_prevbezt = *bezt_prev;
632                 local_bezt     = *bezt_curr;
633
634                 bezt_prev = &local_prevbezt;
635                 bezt_curr = &local_bezt;
636
637                 /* calc the normals */
638                 sub_v2_v2v2(tvec, bezt_prev->vec[1], bezt_prev->vec[0]);
639                 normalize_v2(tvec);
640                 point_prev_n[0] = -tvec[1];
641                 point_prev_n[1] =  tvec[0];
642
643                 sub_v2_v2v2(tvec, bezt_curr->vec[1], bezt_curr->vec[0]);
644                 normalize_v2(tvec);
645                 point_curr_n[0] = -tvec[1];
646                 point_curr_n[1] =  tvec[0];
647
648                 weight_prev = bezt_prev->weight;
649                 weight_curr = bezt_curr->weight;
650
651                 mul_v2_fl(point_prev_n, weight_prev);
652                 mul_v2_fl(point_curr_n, weight_curr);
653
654                 /* before we transform verts */
655                 len_base = len_v2v2(bezt_prev->vec[1], bezt_curr->vec[1]);
656
657                 // add_v2_v2(bezt_prev->vec[0], point_prev_n);  // not needed
658                 add_v2_v2(bezt_prev->vec[1], point_prev_n);
659                 add_v2_v2(bezt_prev->vec[2], point_prev_n);
660
661                 add_v2_v2(bezt_curr->vec[0], point_curr_n);
662                 add_v2_v2(bezt_curr->vec[1], point_curr_n);
663                 // add_v2_v2(bezt_curr->vec[2], point_curr_n); // not needed
664
665                 len_feather = len_v2v2(bezt_prev->vec[1], bezt_curr->vec[1]);
666
667                 /* scale by chane in length */
668                 len_scalar = len_feather / len_base;
669                 dist_ensure_v2_v2fl(bezt_prev->vec[2], bezt_prev->vec[1], len_scalar * len_v2v2(bezt_prev->vec[2], bezt_prev->vec[1]));
670                 dist_ensure_v2_v2fl(bezt_curr->vec[0], bezt_curr->vec[1], len_scalar * len_v2v2(bezt_curr->vec[0], bezt_curr->vec[1]));
671
672
673                 for (j = 0; j < 2; j++) {
674                         BKE_curve_forward_diff_bezier(bezt_prev->vec[1][j], bezt_prev->vec[2][j],
675                                                       bezt_curr->vec[0][j], bezt_curr->vec[1][j],
676                                                       &(*fp)[j], resol, 2 * sizeof(float));
677                 }
678
679
680                 /* scale by the uw's */
681                 if (point_prev->tot_uw) {
682                         for (j = 0; j < resol; j++, fp++) {
683                                 float u = (float) j / resol;
684                                 float weight_uw, weight_scalar;
685                                 float co[2];
686
687                                 /* TODO - these calls all calculate similar things
688                                  * could be unified for some speed */
689                                 BKE_mask_point_segment_co(spline, point_prev, u, co);
690
691                                 weight_uw     = BKE_mask_point_weight(spline, point_prev, u);
692                                 weight_scalar = BKE_mask_point_weight_scalar(spline, point_prev, u);
693
694                                 dist_ensure_v2_v2fl(*fp, co, len_v2v2(*fp, co) * (weight_uw / weight_scalar));
695                         }
696                 }
697                 else {
698                         fp += resol;
699                 }
700
701                 if (a == 0 && (spline->flag & MASK_SPLINE_CYCLIC) == 0) {
702                         copy_v2_v2(*fp, bezt_curr->vec[1]);
703                 }
704
705                 point_prev = point_curr;
706                 point_curr++;
707         }
708
709         if ((spline->flag & MASK_SPLINE_NOINTERSECT) && do_feather_isect) {
710                 BKE_mask_spline_feather_collapse_inner_loops(spline, feather, tot);
711         }
712
713         return feather;
714 }
715
716 /**
717  * values align with #BKE_mask_spline_differentiate_with_resolution_ex
718  * when \a resol arguments match.
719  */
720 float (*BKE_mask_spline_feather_differentiated_points_with_resolution_ex(MaskSpline *spline,
721                                                                          int *tot_feather_point,
722                                                                          const unsigned int resol,
723                                                                          const int do_feather_isect
724                                                                          ))[2]
725 {
726         switch (spline->offset_mode) {
727                 case MASK_SPLINE_OFFSET_EVEN:
728                         return mask_spline_feather_differentiated_points_with_resolution_ex__even(spline, tot_feather_point, resol, do_feather_isect);
729                         break;
730                 case MASK_SPLINE_OFFSET_SMOOTH:
731                 default:
732                         return mask_spline_feather_differentiated_points_with_resolution_ex__double(spline, tot_feather_point, resol, do_feather_isect);
733                         break;
734         }
735 }
736
737 float (*BKE_mask_spline_feather_differentiated_points_with_resolution(MaskSpline *spline, int width, int height,
738                                                                       int *tot_feather_point, const int do_feather_isect))[2]
739 {
740         unsigned int resol = BKE_mask_spline_feather_resolution(spline, width, height);
741
742         return BKE_mask_spline_feather_differentiated_points_with_resolution_ex(spline, tot_feather_point, resol, do_feather_isect);
743 }
744
745 float (*BKE_mask_spline_feather_differentiated_points(MaskSpline *spline, int *tot_feather_point))[2]
746 {
747         return BKE_mask_spline_feather_differentiated_points_with_resolution(spline, 0, 0, tot_feather_point, TRUE);
748 }
749
750 float (*BKE_mask_spline_feather_points(MaskSpline *spline, int *tot_feather_point))[2]
751 {
752         MaskSplinePoint *points_array = BKE_mask_spline_point_array(spline);
753
754         int i, tot = 0;
755         float (*feather)[2], (*fp)[2];
756
757         /* count */
758         for (i = 0; i < spline->tot_point; i++) {
759                 MaskSplinePoint *point = &points_array[i];
760
761                 tot += point->tot_uw + 1;
762         }
763
764         /* create data */
765         feather = fp = MEM_mallocN(tot * sizeof(*feather), "mask spline feather points");
766
767         for (i = 0; i < spline->tot_point; i++) {
768                 MaskSplinePoint *point = &points_array[i];
769                 BezTriple *bezt = &point->bezt;
770                 float weight, n[2];
771                 int j;
772
773                 BKE_mask_point_normal(spline, point, 0.0f, n);
774                 weight = BKE_mask_point_weight(spline, point, 0.0f);
775
776                 madd_v2_v2v2fl(*fp, bezt->vec[1], n, weight);
777                 fp++;
778
779                 for (j = 0; j < point->tot_uw; j++) {
780                         float u = point->uw[j].u;
781                         float co[2];
782
783                         BKE_mask_point_segment_co(spline, point, u, co);
784                         BKE_mask_point_normal(spline, point, u, n);
785                         weight = BKE_mask_point_weight(spline, point, u);
786
787                         madd_v2_v2v2fl(*fp, co, n, weight);
788                         fp++;
789                 }
790         }
791
792         *tot_feather_point = tot;
793
794         return feather;
795 }
796
797 /* *** mask point functions which involve evaluation *** */
798 float *BKE_mask_point_segment_feather_diff_with_resolution(MaskSpline *spline, MaskSplinePoint *point,
799                                                            int width, int height,
800                                                            unsigned int *tot_feather_point)
801 {
802         float *feather, *fp;
803         unsigned int resol = BKE_mask_spline_feather_resolution(spline, width, height);
804         unsigned int i;
805
806         feather = fp = MEM_callocN(2 * resol * sizeof(float), "mask point spline feather diff points");
807
808         for (i = 0; i < resol; i++, fp += 2) {
809                 float u = (float)(i % resol) / resol, weight;
810                 float co[2], n[2];
811
812                 BKE_mask_point_segment_co(spline, point, u, co);
813                 BKE_mask_point_normal(spline, point, u, n);
814                 weight = BKE_mask_point_weight(spline, point, u);
815
816                 fp[0] = co[0] + n[0] * weight;
817                 fp[1] = co[1] + n[1] * weight;
818         }
819
820         *tot_feather_point = resol;
821
822         return feather;
823 }
824
825 float *BKE_mask_point_segment_feather_diff(MaskSpline *spline, MaskSplinePoint *point, unsigned int *tot_feather_point)
826 {
827         return BKE_mask_point_segment_feather_diff_with_resolution(spline, point, 0, 0, tot_feather_point);
828 }
829
830 float *BKE_mask_point_segment_diff_with_resolution(MaskSpline *spline, MaskSplinePoint *point,
831                                                    int width, int height, unsigned int *tot_diff_point)
832 {
833         MaskSplinePoint *points_array = BKE_mask_spline_point_array_from_point(spline, point);
834
835         BezTriple *bezt, *bezt_next;
836         float *diff_points, *fp;
837         int j, resol = BKE_mask_spline_resolution(spline, width, height);
838
839         bezt = &point->bezt;
840         bezt_next = BKE_mask_spline_point_next_bezt(spline, points_array, point);
841
842         if (!bezt_next)
843                 return NULL;
844
845         /* resol+1 because of 'forward_diff_bezier' function */
846         *tot_diff_point = resol + 1;
847         diff_points = fp = MEM_callocN((resol + 1) * 2 * sizeof(float), "mask segment vets");
848
849         for (j = 0; j < 2; j++) {
850                 BKE_curve_forward_diff_bezier(bezt->vec[1][j], bezt->vec[2][j],
851                                               bezt_next->vec[0][j], bezt_next->vec[1][j],
852                                               fp + j, resol, 2 * sizeof(float));
853         }
854
855         copy_v2_v2(fp + 2 * resol, bezt_next->vec[1]);
856
857         return diff_points;
858 }
859
860 float *BKE_mask_point_segment_diff(MaskSpline *spline, MaskSplinePoint *point, unsigned int *tot_diff_point)
861 {
862         return BKE_mask_point_segment_diff_with_resolution(spline, point, 0, 0, tot_diff_point);
863 }