Add Background Support

Change-Id: I0bc0566f2bcc7ad68c93a4cefa07c320f1757d35
diff --git a/new3d/src/com/android/gallery3d/anim/FloatAnimation.java b/new3d/src/com/android/gallery3d/anim/FloatAnimation.java
new file mode 100644
index 0000000..c8d1dd9
--- /dev/null
+++ b/new3d/src/com/android/gallery3d/anim/FloatAnimation.java
@@ -0,0 +1,45 @@
+package com.android.gallery3d.anim;
+
+public class FloatAnimation {
+    private static final long ANIMATION_START = 0;
+    private static final long NO_ANIMATION = -1;
+
+    private long mStartTime = NO_ANIMATION;
+    private final int mDuration;
+
+    private final float mFrom;
+    private final float mTo;
+    private float mCurrent;
+
+    public FloatAnimation(float from, float to, int duration) {
+        mFrom = from;
+        mTo = to;
+        mDuration = duration;
+    }
+
+    public void start() {
+        mStartTime = ANIMATION_START;
+    }
+
+    public boolean calculate(long currentTimeMillis) {
+        if (mStartTime == NO_ANIMATION) return false;
+        if (mStartTime == ANIMATION_START) mStartTime = currentTimeMillis;
+        int elapse = (int) (currentTimeMillis - mStartTime);
+        if (elapse < mDuration) {
+            float x = (float) elapse / mDuration;
+            mCurrent = mFrom + (mTo - mFrom) * x;
+        } else {
+            mCurrent = mTo;
+            mStartTime = NO_ANIMATION;
+        }
+        return true;
+    }
+
+    public boolean isActive() {
+        return mStartTime != NO_ANIMATION;
+    }
+
+    public float get() {
+        return mCurrent;
+    }
+}
diff --git a/new3d/src/com/android/gallery3d/app/Gallery.java b/new3d/src/com/android/gallery3d/app/Gallery.java
index 7870d69..45c95fd 100644
--- a/new3d/src/com/android/gallery3d/app/Gallery.java
+++ b/new3d/src/com/android/gallery3d/app/Gallery.java
@@ -18,23 +18,38 @@
 
 import android.app.Activity;
 import android.content.Intent;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
 import android.os.Bundle;
+import android.os.Message;
 import android.util.Log;
 
 import com.android.gallery3d.R;
 import com.android.gallery3d.data.LocalMediaSet;
 import com.android.gallery3d.data.MediaDbAccessor;
 import com.android.gallery3d.data.MediaSet;
+import com.android.gallery3d.ui.AdaptiveBackground;
+import com.android.gallery3d.ui.GLHandler;
 import com.android.gallery3d.ui.GLRootView;
-import com.android.gallery3d.ui.SlotView;
+import com.android.gallery3d.ui.GLView;
 import com.android.gallery3d.ui.MediaSetSlotAdapter;
+import com.android.gallery3d.ui.OverlayLayout;
+import com.android.gallery3d.ui.SlotView;
 
 public final class Gallery extends Activity {
     public static final String REVIEW_ACTION = "com.android.gallery3d.app.REVIEW";
 
+    private static final int CHANGE_BACKGROUND = 1;
+
     private static final String TAG = "Gallery";
     private GLRootView mGLRootView;
     private SlotView mSlotView;
+    private GLHandler mHandler;
+    private AdaptiveBackground mBackground;
+
+    private Bitmap mBgImages[];
+    private int mBgIndex = 0;
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
@@ -43,10 +58,49 @@
         mGLRootView = (GLRootView) findViewById(R.id.gl_root_view);
 
         mSlotView = new SlotView(this);
-        mGLRootView.setContentPane(mSlotView);
         MediaSet rootSet = MediaDbAccessor.getMediaSets(this);
         ((LocalMediaSet) rootSet).printOut();
         mSlotView.setModel(new MediaSetSlotAdapter(this, rootSet));
+
+        mBackground = new AdaptiveBackground();
+
+        GLView overlay = new OverlayLayout();
+        overlay.addComponent(mBackground);
+        overlay.addComponent(mSlotView);
+        mGLRootView.setContentPane(overlay);
+
+        mHandler = new GLHandler(mGLRootView) {
+            @Override
+            public void handleMessage(Message message) {
+                switch (message.what) {
+                    case CHANGE_BACKGROUND:
+                        changeBackground();
+                        break;
+                }
+            }
+        };
+
+        loadBackgroundBitmap(R.drawable.square,
+                R.drawable.potrait, R.drawable.landscape);
+        mBackground.setImage(mBgImages[mBgIndex]);
+    }
+
+    private void changeBackground() {
+        mBackground.setImage(mBgImages[mBgIndex]);
+        if (++mBgIndex == mBgImages.length) mBgIndex = 0;
+        mHandler.sendEmptyMessageDelayed(CHANGE_BACKGROUND, 3000);
+    }
+
+    private void loadBackgroundBitmap(int ... ids) {
+        BitmapFactory.Options options = new BitmapFactory.Options();
+        options.inPreferredConfig = Bitmap.Config.ARGB_8888;
+        mBgImages = new Bitmap[ids.length];
+        Resources res = getResources();
+        for (int i = 0, n = ids.length; i < n; ++i) {
+            Bitmap bitmap = BitmapFactory.decodeResource(res, ids[i], options);
+            mBgImages[i] = mBackground.getAdaptiveBitmap(bitmap);
+            bitmap.recycle();
+        }
     }
 
     @Override
@@ -63,12 +117,14 @@
     public void onResume() {
         super.onResume();
         mGLRootView.onResume();
+        mHandler.sendEmptyMessageDelayed(CHANGE_BACKGROUND, 3000);
     }
 
     @Override
     public void onPause() {
         super.onPause();
         mGLRootView.onPause();
+        mHandler.removeMessages(CHANGE_BACKGROUND);
     }
 
     @Override
diff --git a/new3d/src/com/android/gallery3d/ui/AdaptiveBackground.java b/new3d/src/com/android/gallery3d/ui/AdaptiveBackground.java
new file mode 100644
index 0000000..7b8adbe
--- /dev/null
+++ b/new3d/src/com/android/gallery3d/ui/AdaptiveBackground.java
@@ -0,0 +1,104 @@
+package com.android.gallery3d.ui;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.LightingColorFilter;
+import android.graphics.Paint;
+
+import com.android.gallery3d.anim.FloatAnimation;
+
+import javax.microedition.khronos.opengles.GL11;
+
+public class AdaptiveBackground extends GLView {
+
+    private static final int BACKGROUND_WIDTH = 128;
+    private static final int BACKGROUND_HEIGHT = 64;
+    private static final int FILTERED_COLOR = 0xffaaaaaa;
+    private static final int ANIMATION_DURATION = 500;
+
+    private MixedTexture mMixedTexture;
+    private final Paint mPaint;
+    private Bitmap mPendingBitmap;
+    private final FloatAnimation mAnimation =
+            new FloatAnimation(0, 1, ANIMATION_DURATION);
+
+    public AdaptiveBackground() {
+        Paint paint = new Paint();
+        paint.setFilterBitmap(true);
+        paint.setColorFilter(new LightingColorFilter(FILTERED_COLOR, 0));
+        mPaint = paint;
+    }
+
+    public Bitmap getAdaptiveBitmap(Bitmap bitmap) {
+        Bitmap target = Bitmap.createBitmap(
+                BACKGROUND_WIDTH, BACKGROUND_HEIGHT, Bitmap.Config.ARGB_8888);
+        Canvas canvas = new Canvas(target);
+        int width = bitmap.getWidth();
+        int height = bitmap.getHeight();
+        int left = 0;
+        int top = 0;
+        if (width * BACKGROUND_HEIGHT > height * BACKGROUND_WIDTH) {
+            float scale = (float) BACKGROUND_HEIGHT / height;
+            canvas.scale(scale, scale);
+            left = (BACKGROUND_WIDTH - (int) (width * scale + 0.5)) / 2;
+        } else {
+            float scale = (float) BACKGROUND_WIDTH / width;
+            canvas.scale(scale, scale);
+            top = (BACKGROUND_HEIGHT - (int) (height * scale + 0.5)) / 2;
+        }
+        canvas.drawBitmap(bitmap, left, top, mPaint);
+        BoxBlurFilter.apply(target,
+                BoxBlurFilter.MODE_REPEAT, BoxBlurFilter.MODE_CLAMP);
+        return target;
+    }
+
+    private void startTransition(Bitmap bitmap) {
+        BitmapTexture texture = new BitmapTexture(bitmap);
+        if (mMixedTexture == null) {
+            mMixedTexture = new MixedTexture(texture);
+        } else {
+            mMixedTexture.setNewDestination(texture);
+        }
+        mMixedTexture.setMixtureRatio(0);
+        mAnimation.start();
+        invalidate();
+    }
+
+    public void setImage(Bitmap bitmap) {
+        if (mAnimation.isActive()) {
+            mPendingBitmap = bitmap;
+        } else {
+            startTransition(bitmap);
+        }
+    }
+
+    public void setScrollPosition(int position) {
+        if (mScrollX == position) return;
+        mScrollX = position;
+        invalidate();
+    }
+
+    @Override
+    protected void render(GLRootView root, GL11 gl) {
+        if (mMixedTexture == null) return;
+
+        if (mAnimation.calculate(root.currentAnimationTimeMillis())) {
+            mMixedTexture.setMixtureRatio(mAnimation.get());
+            invalidate();
+        } else if (mPendingBitmap != null) {
+            startTransition(mPendingBitmap);
+            mPendingBitmap = null;
+        }
+
+        int height = getHeight();
+        float scale = (float) height / BACKGROUND_HEIGHT;
+        int width = (int) (BACKGROUND_WIDTH * scale + 0.5f);
+        int scroll = mScrollX;
+        int start = (scroll / width) * width;
+
+        MixedTexture mixed = mMixedTexture;
+        for (int i = start, n = scroll + getWidth(); i < n; i += width) {
+            mMixedTexture.draw(root, i - scroll, 0, width, height);
+        }
+    }
+}
diff --git a/new3d/src/com/android/gallery3d/ui/BoxBlurFilter.java b/new3d/src/com/android/gallery3d/ui/BoxBlurFilter.java
new file mode 100644
index 0000000..a256ea9
--- /dev/null
+++ b/new3d/src/com/android/gallery3d/ui/BoxBlurFilter.java
@@ -0,0 +1,84 @@
+package com.android.gallery3d.ui;
+
+import android.graphics.Bitmap;
+
+
+public class BoxBlurFilter {
+    private static final int RED_MASK = 0xff0000;
+    private static final int RED_MASK_SHIFT = 16;
+    private static final int GREEN_MASK = 0x00ff00;
+    private static final int GREEN_MASK_SHIFT = 8;
+    private static final int BLUE_MASK = 0x0000ff;
+    private static final int RADIUS = 4;
+    private static final int KERNEL_SIZE = RADIUS * 2 + 1;
+    private static final int NUM_COLORS = 256;
+    private static final int[] KERNEL_NORM = new int[KERNEL_SIZE * NUM_COLORS];
+
+    public static final int MODE_REPEAT = 1;
+    public static final int MODE_CLAMP = 2;
+
+    static {
+        int index = 0;
+        // Build a lookup table from summed to normalized kernel values.
+        // The formula: KERNAL_NORM[value] = value / KERNEL_SIZE
+        for (int i = 0; i < NUM_COLORS; ++i) {
+            for (int j = 0; j < KERNEL_SIZE; ++j) {
+                KERNEL_NORM[index++] = i;
+            }
+        }
+    }
+
+    private BoxBlurFilter() {
+    }
+
+    private static int sample(int x, int width, int mode) {
+        if (x >= 0 && x < width) return x;
+        return mode == MODE_REPEAT
+                ? x < 0 ? x + width : x - width
+                : x < 0 ? 0 : width - 1;
+    }
+
+    public static void apply(
+            Bitmap bitmap, int horizontalMode, int verticalMode) {
+
+        int width = bitmap.getWidth();
+        int height = bitmap.getHeight();
+        int data[] = new int[width * height];
+        bitmap.getPixels(data, 0, width, 0, 0, width, height);
+        int temp[] = new int[width * height];
+        applyOneDimension(data, temp, width, height, horizontalMode);
+        applyOneDimension(temp, data, height, width, verticalMode);
+        bitmap.setPixels(data, 0, width, 0, 0, width, height);
+    }
+
+    private static void applyOneDimension(
+            int[] in, int[] out, int width, int height, int mode) {
+        for (int y = 0, read = 0; y < height; ++y, read += width) {
+            // Evaluate the kernel for the first pixel in the row.
+            int red = 0;
+            int green = 0;
+            int blue = 0;
+            for (int i = -RADIUS; i <= RADIUS; ++i) {
+                int argb = in[read + sample(i, width, mode)];
+                red += (argb & RED_MASK) >> RED_MASK_SHIFT;
+                green += (argb & GREEN_MASK) >> GREEN_MASK_SHIFT;
+                blue += argb & BLUE_MASK;
+            }
+            for (int x = 0, write = y; x < width; ++x, write += height) {
+                // Output the current pixel.
+                out[write] = 0xFF000000
+                        | (KERNEL_NORM[red] << RED_MASK_SHIFT)
+                        | (KERNEL_NORM[green] << GREEN_MASK_SHIFT)
+                        | KERNEL_NORM[blue];
+
+                // Slide to the next pixel, adding the new rightmost pixel and
+                // subtracting the former leftmost.
+                int prev = in[read + sample(x - RADIUS, width, mode)];
+                int next = in[read + sample(x + RADIUS + 1, width, mode)];
+                red += ((next & RED_MASK) - (prev & RED_MASK)) >> RED_MASK_SHIFT;
+                green += ((next & GREEN_MASK) - (prev & GREEN_MASK)) >> GREEN_MASK_SHIFT;
+                blue += (next & BLUE_MASK) - (prev & BLUE_MASK);
+            }
+        }
+    }
+}
diff --git a/new3d/src/com/android/gallery3d/ui/GLHandler.java b/new3d/src/com/android/gallery3d/ui/GLHandler.java
new file mode 100644
index 0000000..d59f9ef
--- /dev/null
+++ b/new3d/src/com/android/gallery3d/ui/GLHandler.java
@@ -0,0 +1,20 @@
+package com.android.gallery3d.ui;
+
+import android.os.Handler;
+import android.os.Message;
+
+public class GLHandler extends Handler {
+
+    private final GLRootView mRootView;
+
+    public GLHandler(GLRootView rootView) {
+        mRootView = rootView;
+    }
+
+    @Override
+    public void dispatchMessage(Message message) {
+        synchronized (mRootView) {
+            super.dispatchMessage(message);
+        }
+    }
+}
diff --git a/new3d/src/com/android/gallery3d/ui/GLRootView.java b/new3d/src/com/android/gallery3d/ui/GLRootView.java
index 98d850f..b2afc67 100644
--- a/new3d/src/com/android/gallery3d/ui/GLRootView.java
+++ b/new3d/src/com/android/gallery3d/ui/GLRootView.java
@@ -91,6 +91,7 @@
     private final int mNinePatchY[] = new int[4];
     private final float mNinePatchU[] = new float[4];
     private final float mNinePatchV[] = new float[4];
+    private final float mTextureColor[] = new float[4];
 
     private FloatBuffer mXyPointer;
     private FloatBuffer mUvPointer;
@@ -244,6 +245,10 @@
         gl.glVertexPointer(2, GL11.GL_FLOAT, 0, mXyPointer);
         gl.glTexCoordPointer(2, GL11.GL_FLOAT, 0, mUvPointer);
 
+        // Enable the texture coordinate array for Texture 1
+        gl.glClientActiveTexture(GL11.GL_TEXTURE1);
+        gl.glTexCoordPointer(2, GL11.GL_FLOAT, 0, mUvPointer);
+        gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
     }
 
     /**
@@ -527,21 +532,8 @@
         drawRect(x, y, width, height);
     }
 
-    public void drawTexture(
+    private void drawBoundTexture(
             BasicTexture texture, int x, int y, int width, int height) {
-        drawTexture(texture, x, y, width, height, mTransformation.getAlpha());
-    }
-
-    public void drawTexture(BasicTexture texture,
-            int x, int y, int width, int height, float alpha) {
-        mGLState.setBlendEnabled(!texture.isOpaque() || alpha < OPAQUE_ALPHA);
-        mGLState.setTexture2DEnabled(true);
-
-        if (!texture.bind(this, mGL)) {
-            throw new RuntimeException("cannot bind" + texture.toString());
-        }
-        if (width <= 0 || height <= 0) return ;
-
         Matrix matrix = mTransformation.getMatrix();
         matrix.getValues(mMatrixValues);
 
@@ -552,7 +544,6 @@
                     (texture.mWidth - 0.5f) / texture.mTextureWidth,
                     (texture.mHeight - 0.5f) / texture.mTextureHeight,
                     mUvBuffer, mUvPointer);
-            mGLState.setTextureAlpha(alpha);
             drawRect(x, y, width, height, mMatrixValues);
         } else {
             // draw the rect from bottom-left to top-right
@@ -562,10 +553,89 @@
             width = (int) points[2] - x;
             height = (int) points[3] - y;
             if (width > 0 && height > 0) {
-                mGLState.setTextureAlpha(alpha);
                 ((GL11Ext) mGL).glDrawTexiOES(x, y, 0, width, height);
             }
         }
+
+    }
+
+    public void drawTexture(
+            BasicTexture texture, int x, int y, int width, int height) {
+        drawTexture(texture, x, y, width, height, mTransformation.getAlpha());
+    }
+
+    public void drawTexture(BasicTexture texture,
+            int x, int y, int width, int height, float alpha) {
+        if (width <= 0 || height <= 0) return ;
+
+        mGLState.setBlendEnabled(!texture.isOpaque() || alpha < OPAQUE_ALPHA);
+        mGLState.setTexture2DEnabled(true);
+
+        if (!texture.bind(this, mGL)) {
+            throw new RuntimeException("cannot bind" + texture.toString());
+        }
+        mGLState.setTextureAlpha(alpha);
+        drawBoundTexture(texture, x, y, width, height);
+    }
+
+    public void drawMixed(BasicTexture from, BasicTexture to,
+            float ratio, int x, int y, int w, int h) {
+        drawMixed(from, to, ratio, x, y, w, h, mTransformation.getAlpha());
+    }
+
+    private void setTextureColor(float r, float g, float b, float alpha) {
+        float[] color = mTextureColor;
+        color[0] = r;
+        color[1] = g;
+        color[2] = b;
+        color[3] = alpha;
+    }
+
+    public void drawMixed(BasicTexture from, BasicTexture to,
+            float ratio, int x, int y, int width, int height, float alpha) {
+        if (alpha < OPAQUE_ALPHA) {
+            throw new RuntimeException("Cannot support alpha value");
+        }
+        mGLState.setBlendEnabled(!from.isOpaque() || !to.isOpaque());
+        mGLState.setTexture2DEnabled(true);
+
+        final GL11 gl = mGL;
+        if (!from.bind(this, gl)) {
+            throw new RuntimeException("fail to bind texture");
+        }
+
+        gl.glActiveTexture(GL11.GL_TEXTURE1);
+        if (!to.bind(this, gl)) {
+            gl.glActiveTexture(GL11.GL_TEXTURE0);
+            throw new RuntimeException("fail to bind texture");
+        }
+        gl.glEnable(GL11.GL_TEXTURE_2D);
+
+        // Interpolate the RGB and alpha values between both textures.
+        mGLState.setTexEnvMode(GL11.GL_COMBINE);
+        gl.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_COMBINE_RGB, GL11.GL_INTERPOLATE);
+        gl.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_COMBINE_ALPHA, GL11.GL_INTERPOLATE);
+
+        // Specify the interpolation factor via the alpha component of
+        // GL_TEXTURE_ENV_COLORes.
+        setTextureColor(ratio, ratio, ratio, ratio);
+        gl.glTexEnvfv(GL11.GL_TEXTURE_ENV, GL11.GL_TEXTURE_ENV_COLOR, mTextureColor, 0);
+
+        // Wire up the interpolation factor for RGB.
+        gl.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_SRC2_RGB, GL11.GL_CONSTANT);
+        gl.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_OPERAND2_RGB, GL11.GL_SRC_ALPHA);
+
+        // Wire up the interpolation factor for alpha.
+        gl.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_SRC2_ALPHA, GL11.GL_CONSTANT);
+        gl.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_OPERAND2_ALPHA, GL11.GL_SRC_ALPHA);
+
+        // Draw the combined texture.
+        drawBoundTexture(to, x, y, width, height);
+
+        // Disable TEXTURE1.
+        gl.glDisable(GL11.GL_TEXTURE_2D);
+        // Switch back to the default texture unit.
+        gl.glActiveTexture(GL11.GL_TEXTURE0);
     }
 
     private static boolean isMatrixRotatedOrFlipped(float matrix[]) {
diff --git a/new3d/src/com/android/gallery3d/ui/MixedTexture.java b/new3d/src/com/android/gallery3d/ui/MixedTexture.java
new file mode 100644
index 0000000..7092437
--- /dev/null
+++ b/new3d/src/com/android/gallery3d/ui/MixedTexture.java
@@ -0,0 +1,55 @@
+package com.android.gallery3d.ui;
+
+import android.util.Log;
+
+
+public class MixedTexture implements Texture {
+    private BasicTexture mSource;
+    private BasicTexture mDestination;
+    private float mMixRatio = 1.0f;
+    private final int mWidth;
+    private final int mHeight;
+
+    public MixedTexture(BasicTexture texture) {
+        mDestination = texture;
+        mWidth = texture.getWidth();
+        mHeight = texture.getHeight();
+    }
+
+    public BasicTexture setNewDestination(BasicTexture texture) {
+        if (texture.getWidth() != mWidth || texture.getHeight() != mHeight) {
+            throw new IllegalArgumentException();
+        }
+        mMixRatio = 0f;
+        BasicTexture result = mSource;
+        mSource = mDestination;
+        mDestination = texture;
+        return result;
+    }
+
+    public void setMixtureRatio(float ratio) {
+        if (ratio > 1 || ratio < 0) {
+            throw new IllegalArgumentException();
+        }
+        mMixRatio = ratio;
+    }
+
+    public void draw(GLRootView root, int x, int y) {
+        draw(root, x, y, mWidth, mHeight);
+    }
+
+    public void draw(GLRootView root, int x, int y, int w, int h) {
+        Log.v("MixedTexture", "ratio  = " + mMixRatio);
+        if (mMixRatio >= 1 || mSource == null) {
+            mDestination.draw(root, x, y, w, h);
+        } else if (mMixRatio <= 0) {
+            mSource.draw(root, x, y, w, h);
+        } else {
+            root.drawMixed(mSource, mDestination, mMixRatio, x, y, w, h);
+        }
+    }
+
+    public boolean isOpaque() {
+        return true;
+    }
+}
\ No newline at end of file
diff --git a/new3d/src/com/android/gallery3d/ui/OverlayLayout.java b/new3d/src/com/android/gallery3d/ui/OverlayLayout.java
new file mode 100644
index 0000000..d7c716f
--- /dev/null
+++ b/new3d/src/com/android/gallery3d/ui/OverlayLayout.java
@@ -0,0 +1,14 @@
+package com.android.gallery3d.ui;
+
+public class OverlayLayout extends GLView {
+
+    @Override
+    protected void onLayout(boolean changed, int l, int t, int r, int b) {
+        int width = r - l;
+        int height = b - t;
+        for (int i = 0, n = getComponentCount(); i < n; ++i) {
+            GLView component = getComponent(i);
+            component.layout(0, 0, width, height);
+        }
+    }
+}
diff --git a/new3d/src/com/android/gallery3d/ui/SlotView.java b/new3d/src/com/android/gallery3d/ui/SlotView.java
index a4b6ada..0137531 100644
--- a/new3d/src/com/android/gallery3d/ui/SlotView.java
+++ b/new3d/src/com/android/gallery3d/ui/SlotView.java
@@ -6,7 +6,6 @@
 import android.view.animation.DecelerateInterpolator;
 
 import javax.microedition.khronos.opengles.GL11;
-import android.util.Log;
 
 public class SlotView extends GLView {
 
diff --git a/new3d/src/com/android/gallery3d/ui/Util.java b/new3d/src/com/android/gallery3d/ui/Util.java
index 33d8bfd..a6dca05 100644
--- a/new3d/src/com/android/gallery3d/ui/Util.java
+++ b/new3d/src/com/android/gallery3d/ui/Util.java
@@ -96,5 +96,4 @@
     public static boolean isOpaque(int color) {
         return color >>> 24 == 0xFF;
     }
-
 }