feather expandable limits, feather gausian taper, clear canvas tweaks
[goodguy/cinelerra.git] / cinelerra-5.1 / cinelerra / maskengine.C
index 467ffa0b225c5d27a73b1dec9024bee6802fc21f..8f6541ae6338bafd4191a32cffc7ad71514fe325 100644 (file)
@@ -26,6 +26,7 @@
 #include "maskautos.h"
 #include "maskengine.h"
 #include "mutex.h"
+#include "track.h"
 #include "transportque.inc"
 #include "vframe.h"
 
@@ -219,10 +220,12 @@ void MaskUnit::process_package(LoadPackage *package)
                        int fg = 0xffff * (rv >= 0 ? vv : 0);
                        int bg = 0xffff * (rv >= 0 ? 0 : vv);
                        int rr = r*r;  double dr = 1./rr;
+                       // gausian, rr is x**2, limit 1/255
+                       double sig2 = -log(255.0);
                        temp_t psf[rr+1];  spot = psf;
                        for( int i=0; i<=rr; ++i ) {
-                               double d = i*dr;
-                               psf[i] = (1-d)*fg + d*bg;
+                               double d = exp(i*dr * sig2);
+                               psf[i] = d*fg + (1-d)*bg;
                        }
                        int n = edge.size();
                        for( int i=0; i<n; ++i ) {
@@ -311,8 +314,8 @@ MaskEngine::~MaskEngine()
        point_sets.remove_all_objects();
 }
 
-int MaskEngine::points_equivalent(ArrayList<MaskPoint*> *new_points,
-       ArrayList<MaskPoint*> *points)
+int MaskEngine::points_equivalent(MaskPoints *new_points,
+       MaskPoints *points)
 {
 //printf("MaskEngine::points_equivalent %d %d\n", new_points->total, points->total);
        if( new_points->total != points->total ) return 0;
@@ -324,48 +327,6 @@ int MaskEngine::points_equivalent(ArrayList<MaskPoint*> *new_points,
        return 1;
 }
 
-void MaskEngine::draw_edge(MaskEdge &edge, MaskPointSet &points)
-{
-       if( points.size() < 2 ) return;
-       edge.remove_all();
-       for( int i=0; i<points.size(); ++i ) {
-               MaskPoint *ap = points[i];
-               MaskPoint *bp = (i>=points.size()-1) ?
-                               points[0] : points[i+1];
-               int dx = ap->x - bp->x, dy = ap->y - bp->y;
-               int segments = (int)(sqrt(dx*dx + dy*dy));
-               if( !segments ) continue;
-               if( ap->control_x2 == 0 && ap->control_y2 == 0 &&
-                   bp->control_x1 == 0 && bp->control_y1 == 0 )
-                       segments = 1;
-               float x0 = ap->x, y0 = ap->y;
-               float x1 = ap->x + ap->control_x2;
-               float y1 = ap->y + ap->control_y2;
-               float x2 = bp->x + bp->control_x1;
-               float y2 = bp->y + bp->control_y1;
-               float x3 = bp->x, y3 = bp->y;
-
-               for( int j = 0; j <= segments; ++j ) {
-                       float t = (float)j / segments;
-                       float tpow2 = t * t;
-                       float tpow3 = t * t * t;
-                       float invt = 1 - t;
-                       float invtpow2 = invt * invt;
-                       float invtpow3 = invt * invt * invt;
-
-                       int x = (invtpow3 * x0
-                               + 3 * t     * invtpow2 * x1
-                               + 3 * tpow2 * invt     * x2
-                               +     tpow3         * x3);
-                       int y = (invtpow3 * y0
-                               + 3 * t     * invtpow2 * y1
-                               + 3 * tpow2 * invt     * y2
-                               +     tpow3         * y3);
-                       edge.append(x, y);
-               }
-       }
-}
-
 void MaskEngine::do_mask(VFrame *output,
        int64_t start_position_project,
        MaskAutos *keyframe_set,
@@ -419,17 +380,16 @@ SET_TRACE
                if( new_fader != faders[i] ) { recalculate = 1;  break; }
                float new_feather = keyframe_set->get_feather(start_position_project, i, PLAY_FORWARD);
                if( new_feather != feathers[i] ) { recalculate = 1;  break; }
-               ArrayList<MaskPoint*> new_points;
+               MaskPoints new_points;
                keyframe_set->get_points(&new_points, i,
                                start_position_project, PLAY_FORWARD);
                if( !points_equivalent(&new_points, point_sets[i]) )
                        recalculate = 1;
-               new_points.remove_all_objects();
        }
 
        if( recalculate ) {
                for( int i = 0; i < point_sets.total; i++ ) {
-                       ArrayList<MaskPoint*> *points = point_sets[i];
+                       MaskPoints *points = point_sets[i];
                        points->remove_all_objects();
                }
                point_sets.remove_all_objects();
@@ -438,6 +398,7 @@ SET_TRACE
                feathers.remove_all();
                fade[0] = 0;
 
+               int show_mask = keyframe_set->track->masks;
                for( int i=0; i<total_submasks; ++i ) {
                        float fader = keyframe_set->get_fader(start_position_project, i, PLAY_FORWARD);
                        float v = fader / 100;
@@ -450,10 +411,12 @@ SET_TRACE
                        fade[i+1] = t;
                        float feather = keyframe_set->get_feather(start_position_project, i, PLAY_FORWARD);
                        feathers.append(feather);
-                       MaskPointSet *new_points = new MaskPointSet();
+                       MaskPoints *new_points = new MaskPoints();
                        keyframe_set->get_points(new_points, i, start_position_project, PLAY_FORWARD);
                        point_sets.append(new_points);
-                       draw_edge(*edges.append(new MaskEdge()), *new_points);
+                       MaskEdge *edge = edges.append(new MaskEdge());
+                       if( !((show_mask>>i) & 1) ) continue;
+                       edge->load(*new_points, 0);
                }
 // draw mask
                if( !mask ) mask = new VFrame(mask_w, mask_h, mask_model, 0);