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;
}
-
}