From b350aa5a1ccbadcb5f794183c443c0738cd1e9ab Mon Sep 17 00:00:00 2001
From: Good Guy <good1.2guy@gmail.com>
Date: Sun, 4 Aug 2019 18:59:22 -0600
Subject: [PATCH] feather expandable limits, feather gausian taper, clear
 canvas tweaks

---
 cinelerra-5.1/cinelerra/canvas.C      |  7 ++--
 cinelerra-5.1/cinelerra/canvas.h      |  1 +
 cinelerra-5.1/cinelerra/cwindowgui.C  |  7 +++-
 cinelerra-5.1/cinelerra/cwindowgui.h  |  1 +
 cinelerra-5.1/cinelerra/cwindowtool.C | 47 ++++++++++++++++-----------
 cinelerra-5.1/cinelerra/cwindowtool.h |  2 ++
 cinelerra-5.1/cinelerra/maskengine.C  |  6 ++--
 cinelerra-5.1/cinelerra/playback3d.C  |  6 ++--
 8 files changed, 48 insertions(+), 29 deletions(-)

diff --git a/cinelerra-5.1/cinelerra/canvas.C b/cinelerra-5.1/cinelerra/canvas.C
index f0ea0a12..be0a2af0 100644
--- a/cinelerra-5.1/cinelerra/canvas.C
+++ b/cinelerra-5.1/cinelerra/canvas.C
@@ -905,17 +905,14 @@ void Canvas::clear(int flash)
 {
 	BC_WindowBase *cwdw = get_canvas();
 	if( !cwdw )  return;
-	cwdw->set_bg_color(BLACK);
+	cwdw->set_bg_color(get_clear_color());
 	cwdw->clear_box(0,0, cwdw->get_w(), cwdw->get_h());
 	if( flash ) cwdw->flash();
 }
 
 
 CanvasOutput::CanvasOutput(Canvas *canvas,
-    int x,
-    int y,
-    int w,
-    int h)
+    int x, int y, int w, int h)
  : BC_SubWindow(x, y, w, h, BLACK)
 {
 	this->canvas = canvas;
diff --git a/cinelerra-5.1/cinelerra/canvas.h b/cinelerra-5.1/cinelerra/canvas.h
index 775df7d0..53f6ee8b 100644
--- a/cinelerra-5.1/cinelerra/canvas.h
+++ b/cinelerra-5.1/cinelerra/canvas.h
@@ -86,6 +86,7 @@ public:
 	virtual void toggle_controls() {}
 	virtual int get_cwindow_controls() { return 0; }
 	virtual int get_fullscreen();
+	virtual int get_clear_color() { return 0; }
 	virtual void set_fullscreen(int value);
 
 	int cursor_leave_event_base(BC_WindowBase *caller);
diff --git a/cinelerra-5.1/cinelerra/cwindowgui.C b/cinelerra-5.1/cinelerra/cwindowgui.C
index 3493bd3b..50938bd3 100644
--- a/cinelerra-5.1/cinelerra/cwindowgui.C
+++ b/cinelerra-5.1/cinelerra/cwindowgui.C
@@ -3552,5 +3552,10 @@ int CWindowCanvas::get_cwindow_controls()
 	return mwindow->session->cwindow_controls;
 }
 
-
+int CWindowCanvas::get_clear_color()
+{
+	int color = mwindow->edl->session->cwindow_clear_color;
+	if( color < 0 ) color = get_canvas()->get_bg_color();
+	return color;
+}
 
diff --git a/cinelerra-5.1/cinelerra/cwindowgui.h b/cinelerra-5.1/cinelerra/cwindowgui.h
index af847454..b346885a 100644
--- a/cinelerra-5.1/cinelerra/cwindowgui.h
+++ b/cinelerra-5.1/cinelerra/cwindowgui.h
@@ -320,6 +320,7 @@ public:
 	void calculate_origin();
 	void toggle_controls();
 	int get_cwindow_controls();
+	int get_clear_color();
 
 	MWindow *mwindow;
 	CWindowGUI *gui;
diff --git a/cinelerra-5.1/cinelerra/cwindowtool.C b/cinelerra-5.1/cinelerra/cwindowtool.C
index 0b0b6069..44daadd1 100644
--- a/cinelerra-5.1/cinelerra/cwindowtool.C
+++ b/cinelerra-5.1/cinelerra/cwindowtool.C
@@ -2077,7 +2077,7 @@ int CWindowMaskDrawBoundary::handle_event()
 
 
 CWindowMaskFeather::CWindowMaskFeather(MWindow *mwindow, CWindowMaskGUI *gui, int x, int y)
- : BC_TumbleTextBox(gui, 0, -FEATHER_MAX, FEATHER_MAX, x, y, 64, 2)
+ : BC_TumbleTextBox(gui, 0, INT_MIN, INT_MAX, x, y, 64, 2)
 {
 	this->mwindow = mwindow;
 	this->gui = gui;
@@ -2124,7 +2124,6 @@ int CWindowMaskFeather::update_value(float v)
 			if( !gui->mask_enables[i]->get_value() ) continue;
 			SubMask *sub_mask = keyframe->get_submask(i);
 			float feather = sub_mask->feather + change;
-			bclamp(feather, -FEATHER_MAX, FEATHER_MAX);
 			sub_mask->feather = feather;
 		}
 #ifdef USE_KEYFRAME_SPANNING
@@ -2146,7 +2145,7 @@ int CWindowMaskFeather::handle_event()
 
 CWindowMaskFeatherSlider::CWindowMaskFeatherSlider(MWindow *mwindow,
 		CWindowMaskGUI *gui, int x, int y, int w, float v)
- : BC_FSlider(x, y, 0, w, w, -FEATHER_MAX, FEATHER_MAX, v)
+ : BC_FSlider(x, y, 0, w, w, -FEATHER_MAX-5, FEATHER_MAX+5, v)
 {
 	this->mwindow = mwindow;
 	this->gui = gui;
@@ -2154,6 +2153,7 @@ CWindowMaskFeatherSlider::CWindowMaskFeatherSlider(MWindow *mwindow,
 	timer = new Timer();
 	stick = 0;
 	last_v = 0;
+	max = FEATHER_MAX;
 }
 
 CWindowMaskFeatherSlider::~CWindowMaskFeatherSlider()
@@ -2163,32 +2163,41 @@ CWindowMaskFeatherSlider::~CWindowMaskFeatherSlider()
 
 int CWindowMaskFeatherSlider::handle_event()
 {
+	int sticky = 0;
 	float v = get_value();
-	if( stick > 0 ) {
-		int64_t ms = timer->get_difference();
-		if( ms < 250 && --stick > 0 ) {
-			if( get_value() == 0 ) return 1;
-			update(v = 0);
+	if( stick && timer->get_difference() >= 250 )
+		stick = 0; // no events for .25 sec
+	if( stick && (last_v * (v-last_v)) < 0 )
+		stick = 0; // dv changed direction
+	if( stick ) {
+		if( --stick > 0 ) {
+			timer->update();
+			update(last_v);
+			return 1;
 		}
-		else {
-			stick = 0;
-			last_v = v;
+		if( last_v ) {
+			max *= 1.25;
+			update(get_w(), v=last_v, -max-5, max+5);
+			button_release_event();
 		}
 	}
-	else if( (last_v>=0 && v<0) || (last_v<0 && v>=0) ) {
-		stick = 16;
-		v = 0;
-	}
-	else
-		last_v = v;
-	timer->update();
+	else if( v > max ) { v = max;  sticky = 24; }
+	else if( v < -max ) { v = -max; sticky = 24; }
+	else if( v>=0 ? last_v<0 : last_v>=0 ) { v = 0;  sticky = 16; }
+	if( sticky ) { update(v);  stick = sticky;  timer->update(); }
+	last_v = v;
 	gui->feather->BC_TumbleTextBox::update(v);
 	return gui->feather->update_value(v);
 }
 
 int CWindowMaskFeatherSlider::update(float v)
 {
-	return BC_FSlider::update(v);
+	while( max < v ) max *= 1.25;
+	return update(get_w(), v, -max-5, max+5);
+}
+int CWindowMaskFeatherSlider::update(int r, float v, float mn, float mx)
+{
+	return BC_FSlider::update(r, v, mn, mx);
 }
 
 CWindowMaskFade::CWindowMaskFade(MWindow *mwindow, CWindowMaskGUI *gui, int x, int y)
diff --git a/cinelerra-5.1/cinelerra/cwindowtool.h b/cinelerra-5.1/cinelerra/cwindowtool.h
index 3d05d38a..c8918071 100644
--- a/cinelerra-5.1/cinelerra/cwindowtool.h
+++ b/cinelerra-5.1/cinelerra/cwindowtool.h
@@ -456,11 +456,13 @@ public:
 	~CWindowMaskFeatherSlider();
 	int handle_event();
 	int update(float v);
+	int update(int r, float v, float mn, float mx);
 	char *get_caption() { return 0; }
 	MWindow *mwindow;
 	CWindowMaskGUI *gui;
 	int stick;
 	float last_v;
+	float max;
 	Timer *timer;
 };
 
diff --git a/cinelerra-5.1/cinelerra/maskengine.C b/cinelerra-5.1/cinelerra/maskengine.C
index e369d77c..8f6541ae 100644
--- a/cinelerra-5.1/cinelerra/maskengine.C
+++ b/cinelerra-5.1/cinelerra/maskengine.C
@@ -220,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 ) {
diff --git a/cinelerra-5.1/cinelerra/playback3d.C b/cinelerra-5.1/cinelerra/playback3d.C
index 53f6c9e6..f5ef5c4f 100644
--- a/cinelerra-5.1/cinelerra/playback3d.C
+++ b/cinelerra-5.1/cinelerra/playback3d.C
@@ -285,13 +285,15 @@ static const char *feather_frag =
 	"	float fg = rv>=0 ? vv : 1.;\n"
 	"	float bg = rv>=0 ? 1. : vv;\n"
 	"	int len = points.length();\n"
+	"	float sig2 = -log(255.0);\n"
 	"	for( int i=0; i<len; ++i ) {\n"
 	"		float dx = float(points[i].x) - gl_FragCoord.x;\n"
 	"		float dy = float(points[i].y) - gl_FragCoord.y;\n"
 	"		float dd = dx*dx + dy*dy;\n"
 	"		if( dd >= rr ) continue;\n"
-	"		float d = dd*dr;\n"
-	"		float a = (1.-d)*fg + d*bg;\n"
+	"		float ss = dd / rr;\n"
+	"		float d = exp(ss * sig2);\n"
+	"		float a = d*fg + (1.-d)*bg;\n"
 	"		if( rv*(color.a-a) > 0 ) color = vec4(a);\n"
 	"	}\n"
 	"}\n";
-- 
2.26.2