commit bf2e8f975ee2c2f9d80895cb4cca241b275013c6
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Thu Jul 30 11:38:42 2020 +0100

    Improve the Blur App to catch the bug where a small part of the Blur (and Glow) halo gets displayed on the other edge of the surface.

diff --git a/src/main/java/org/distorted/examples/blur/BlurActivity.java b/src/main/java/org/distorted/examples/blur/BlurActivity.java
index f2b7033..b412273 100644
--- a/src/main/java/org/distorted/examples/blur/BlurActivity.java
+++ b/src/main/java/org/distorted/examples/blur/BlurActivity.java
@@ -33,7 +33,7 @@ import org.distorted.library.main.DistortedLibrary;
 
 public class BlurActivity extends Activity  implements OnSeekBarChangeListener
 {
-    private TextView textBlur;
+    private TextView textBlur, textHalo, textMove;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
     
@@ -42,10 +42,22 @@ public class BlurActivity extends Activity  implements OnSeekBarChangeListener
       {
       super.onCreate(icicle);
       setContentView(R.layout.blurlayout);
+
       textBlur = findViewById(R.id.blurText);
-      SeekBar bar = findViewById(R.id.blurSeek);
-      bar.setOnSeekBarChangeListener(this);
-      bar.setProgress(50);
+      textHalo = findViewById(R.id.haloText);
+      textMove = findViewById(R.id.moveText);
+
+      SeekBar barB = findViewById(R.id.blurSeek);
+      barB.setOnSeekBarChangeListener(this);
+      barB.setProgress(50);
+
+      SeekBar barH = findViewById(R.id.haloSeek);
+      barH.setOnSeekBarChangeListener(this);
+      barH.setProgress(50);
+
+      SeekBar barM = findViewById(R.id.moveSeek);
+      barM.setOnSeekBarChangeListener(this);
+      barM.setProgress(50);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -84,10 +96,17 @@ public class BlurActivity extends Activity  implements OnSeekBarChangeListener
       {
       BlurSurfaceView view = findViewById(R.id.blurSurfaceView);
 
-      if (bar.getId() == R.id.blurSeek)
+      switch( bar.getId() )
         {
-        int level = view.getRenderer().setBlur(progress);
-        textBlur.setText(getString(R.string.blur_placeholder,level));
+        case R.id.blurSeek: int l1 = view.getRenderer().setBlur(progress);
+                            textBlur.setText(getString(R.string.blur_placeholder,l1));
+                            break;
+        case R.id.haloSeek: int l2 = view.getRenderer().setHalo(progress);
+                            textHalo.setText(getString(R.string.halo_placeholder,l2));
+                            break;
+        case R.id.moveSeek: int l3 = view.getRenderer().setMove(progress);
+                            textMove.setText(getString(R.string.move_placeholder,l3));
+                            break;
         }
       }
 
diff --git a/src/main/java/org/distorted/examples/blur/BlurRenderer.java b/src/main/java/org/distorted/examples/blur/BlurRenderer.java
index 9baf6fe..2552d09 100644
--- a/src/main/java/org/distorted/examples/blur/BlurRenderer.java
+++ b/src/main/java/org/distorted/examples/blur/BlurRenderer.java
@@ -24,12 +24,12 @@ import android.graphics.BitmapFactory;
 import android.opengl.GLSurfaceView;
 
 import org.distorted.examples.R;
+import org.distorted.library.effect.MatrixEffectMove;
 import org.distorted.library.effect.MatrixEffectScale;
 import org.distorted.library.effect.PostprocessEffectBlur;
 import org.distorted.library.main.DistortedLibrary;
 import org.distorted.library.main.DistortedEffects;
 import org.distorted.library.main.DistortedFramebuffer;
-import org.distorted.library.main.DistortedNode;
 import org.distorted.library.main.DistortedScreen;
 import org.distorted.library.main.DistortedTexture;
 import org.distorted.library.mesh.MeshRectangles;
@@ -48,6 +48,7 @@ import javax.microedition.khronos.opengles.GL10;
 class BlurRenderer implements GLSurfaceView.Renderer, DistortedLibrary.ExceptionListener
 {
     private final static int SIZE = 500;
+    private final static float PART = 0.5f;
 
     private GLSurfaceView mView;
     private DistortedTexture mTexture;
@@ -56,7 +57,7 @@ class BlurRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exception
     private DistortedFramebuffer mBuffer;
     private MeshRectangles mMesh, mMeshBuffer;
     private Static2D mHaloRadiusSta;
-    private Static3D mScale, mBufferScale;
+    private Static3D mMove, mScale, mBufferScale;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
@@ -72,17 +73,40 @@ class BlurRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exception
       Dynamic2D haloAndRadiusDyn = new Dynamic2D();
       haloAndRadiusDyn.add(mHaloRadiusSta);
 
+      mMove = new Static3D(0,0,0);
       mScale= new Static3D(1,1,1);
       mBufferScale= new Static3D(1,1,1);
 
       mBufferEffects = new DistortedEffects();
       mBufferEffects.apply(new MatrixEffectScale(mBufferScale));
+      mBufferEffects.apply(new PostprocessEffectBlur(haloAndRadiusDyn));
 
       mEffects = new DistortedEffects();
-      mEffects.apply( new PostprocessEffectBlur(haloAndRadiusDyn) );
       mEffects.apply(new MatrixEffectScale(mScale));
+      mEffects.apply(new MatrixEffectMove(mMove));
       }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+//   0 --> (SIZE-factor2) * -0.5
+//  50 --> (SIZE-factor2) *  0.0
+// 100 --> (SIZE-factor2) * +0.5
+
+   int setMove(int move)
+     {
+     float xmove = (1-PART)*SIZE*(move-50)*0.01f;
+     mMove.set0(xmove);
+     return (int)xmove;
+     }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   int setHalo(int halo)
+     {
+     int radius = halo;
+     mHaloRadiusSta.set0(radius);
+     return radius;
+     }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
    int setBlur(int blur)
@@ -106,12 +130,10 @@ class BlurRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exception
     
    public void onSurfaceChanged(GL10 glUnused, int width, int height)
      {
-     float factor1 = 0.8f* (Math.min(width, height));
-
+     float factor1 = Math.min(width, height);
      mBufferScale.set( factor1,factor1,factor1 );
 
-     float factor2 = 0.9f*SIZE;
-
+     float factor2 = PART*SIZE;
      mScale.set( factor2,factor2,factor2 );
 
      mScreen.resize(width, height);
@@ -141,8 +163,10 @@ class BlurRenderer implements GLSurfaceView.Renderer, DistortedLibrary.Exception
      mTexture.setTexture(bitmap);
 
      mScreen.detachAll();
+     mBuffer.detachAll();
+
      mScreen.attach(mBuffer, mBufferEffects, mMeshBuffer);
-     mBuffer.attach(new DistortedNode(mTexture,mEffects,mMesh));
+     mBuffer.attach(mTexture,mEffects,mMesh);
 
      PostprocessEffectBlur.enable();
 
diff --git a/src/main/res/layout/blurlayout.xml b/src/main/res/layout/blurlayout.xml
index 4231ca3..a89ba0a 100644
--- a/src/main/res/layout/blurlayout.xml
+++ b/src/main/res/layout/blurlayout.xml
@@ -11,7 +11,31 @@
         android:layout_weight="1" />
 
     <LinearLayout
-        android:id="@+id/linearLayout1"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:gravity="center|fill_horizontal"
+        android:orientation="horizontal" >
+
+        <TextView
+                android:id="@+id/haloText"
+                android:layout_width="150dp"
+                android:layout_height="wrap_content"
+                android:layout_weight="0.5"
+                android:gravity="center_vertical|center"
+                android:text="@string/blur"
+                android:textAppearance="?android:attr/textAppearanceMedium" />
+
+        <SeekBar
+                android:id="@+id/haloSeek"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:paddingLeft="15dp"
+                android:paddingRight="10dp" />
+
+    </LinearLayout>
+
+    <LinearLayout
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
         android:gravity="center|fill_horizontal"
@@ -36,4 +60,29 @@
 
     </LinearLayout>
 
+    <LinearLayout
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:gravity="center|fill_horizontal"
+        android:orientation="horizontal" >
+
+        <TextView
+                android:id="@+id/moveText"
+                android:layout_width="150dp"
+                android:layout_height="wrap_content"
+                android:layout_weight="0.5"
+                android:gravity="center_vertical|center"
+                android:text="@string/blur"
+                android:textAppearance="?android:attr/textAppearanceMedium" />
+
+        <SeekBar
+                android:id="@+id/moveSeek"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:paddingLeft="15dp"
+                android:paddingRight="10dp" />
+
+    </LinearLayout>
+
 </LinearLayout>
diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml
index 735734c..6cbf5a2 100644
--- a/src/main/res/values/strings.xml
+++ b/src/main/res/values/strings.xml
@@ -117,6 +117,8 @@
     <string name="near_placeholder">Near: %1$.2f</string>
     <string name="wind_placeholder">Wind: %1$d</string>
     <string name="blur_placeholder">Blur: %1$d</string>
+    <string name="halo_placeholder">Halo: %1$d</string>
+    <string name="move_placeholder">Move: %1$d</string>
     <string name="glow_radius_placeholder">Radius: %1$d</string>
     <string name="glow_alpha_placeholder">Alpha: %1$.2f</string>
     <string name="inflate_placeholder">Inflate: %1$.2f</string>
