diff --git a/src/com/hippo/ehviewer/gallery/anim/StateTransitionAnimation.java b/src/com/hippo/ehviewer/gallery/anim/StateTransitionAnimation.java new file mode 100644 index 000000000..9f3b565bc --- /dev/null +++ b/src/com/hippo/ehviewer/gallery/anim/StateTransitionAnimation.java @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.hippo.ehviewer.gallery.anim; + +import android.view.animation.DecelerateInterpolator; +import android.view.animation.Interpolator; + +import com.hippo.ehviewer.gallery.glrenderer.GLCanvas; +import com.hippo.ehviewer.gallery.glrenderer.RawTexture; +import com.hippo.ehviewer.gallery.ui.GLView; + +public class StateTransitionAnimation extends Animation { + + public static class Spec { + public static final Spec OUTGOING; + public static final Spec INCOMING; + public static final Spec PHOTO_INCOMING; + + private static final Interpolator DEFAULT_INTERPOLATOR = + new DecelerateInterpolator(); + + public int duration = 330; + public float backgroundAlphaFrom = 0; + public float backgroundAlphaTo = 0; + public float backgroundScaleFrom = 0; + public float backgroundScaleTo = 0; + public float contentAlphaFrom = 1; + public float contentAlphaTo = 1; + public float contentScaleFrom = 1; + public float contentScaleTo = 1; + public float overlayAlphaFrom = 0; + public float overlayAlphaTo = 0; + public float overlayScaleFrom = 0; + public float overlayScaleTo = 0; + public Interpolator interpolator = DEFAULT_INTERPOLATOR; + + static { + OUTGOING = new Spec(); + OUTGOING.backgroundAlphaFrom = 0.5f; + OUTGOING.backgroundAlphaTo = 0f; + OUTGOING.backgroundScaleFrom = 1f; + OUTGOING.backgroundScaleTo = 0f; + OUTGOING.contentAlphaFrom = 0.5f; + OUTGOING.contentAlphaTo = 1f; + OUTGOING.contentScaleFrom = 3f; + OUTGOING.contentScaleTo = 1f; + + INCOMING = new Spec(); + INCOMING.overlayAlphaFrom = 1f; + INCOMING.overlayAlphaTo = 0f; + INCOMING.overlayScaleFrom = 1f; + INCOMING.overlayScaleTo = 3f; + INCOMING.contentAlphaFrom = 0f; + INCOMING.contentAlphaTo = 1f; + INCOMING.contentScaleFrom = 0.25f; + INCOMING.contentScaleTo = 1f; + + PHOTO_INCOMING = INCOMING; + } + + private static Spec specForTransition(Transition t) { + switch (t) { + case Outgoing: + return Spec.OUTGOING; + case Incoming: + return Spec.INCOMING; + case PhotoIncoming: + return Spec.PHOTO_INCOMING; + case None: + default: + return null; + } + } + } + + public static enum Transition { None, Outgoing, Incoming, PhotoIncoming } + + private final Spec mTransitionSpec; + private float mCurrentContentScale; + private float mCurrentContentAlpha; + private float mCurrentBackgroundScale; + private float mCurrentBackgroundAlpha; + private float mCurrentOverlayScale; + private float mCurrentOverlayAlpha; + private RawTexture mOldScreenTexture; + + public StateTransitionAnimation(Transition t, RawTexture oldScreen) { + this(Spec.specForTransition(t), oldScreen); + } + + public StateTransitionAnimation(Spec spec, RawTexture oldScreen) { + mTransitionSpec = spec != null ? spec : Spec.OUTGOING; + setDuration(mTransitionSpec.duration); + setInterpolator(mTransitionSpec.interpolator); + mOldScreenTexture = oldScreen; + } + + @Override + public boolean calculate(long currentTimeMillis) { + boolean retval = super.calculate(currentTimeMillis); + if (!isActive()) { + if (mOldScreenTexture != null) { + mOldScreenTexture.recycle(); + mOldScreenTexture = null; + } + } + return retval; + } + + @Override + protected void onCalculate(float progress) { + mCurrentContentScale = mTransitionSpec.contentScaleFrom + + (mTransitionSpec.contentScaleTo - mTransitionSpec.contentScaleFrom) * progress; + mCurrentContentAlpha = mTransitionSpec.contentAlphaFrom + + (mTransitionSpec.contentAlphaTo - mTransitionSpec.contentAlphaFrom) * progress; + mCurrentBackgroundAlpha = mTransitionSpec.backgroundAlphaFrom + + (mTransitionSpec.backgroundAlphaTo - mTransitionSpec.backgroundAlphaFrom) + * progress; + mCurrentBackgroundScale = mTransitionSpec.backgroundScaleFrom + + (mTransitionSpec.backgroundScaleTo - mTransitionSpec.backgroundScaleFrom) + * progress; + mCurrentOverlayScale = mTransitionSpec.overlayScaleFrom + + (mTransitionSpec.overlayScaleTo - mTransitionSpec.overlayScaleFrom) * progress; + mCurrentOverlayAlpha = mTransitionSpec.overlayAlphaFrom + + (mTransitionSpec.overlayAlphaTo - mTransitionSpec.overlayAlphaFrom) * progress; + } + + private void applyOldTexture(GLView view, GLCanvas canvas, float alpha, float scale, boolean clear) { + if (mOldScreenTexture == null) + return; + if (clear) canvas.clearBuffer(view.getBackgroundColor()); + canvas.save(); + canvas.setAlpha(alpha); + int xOffset = view.getWidth() / 2; + int yOffset = view.getHeight() / 2; + canvas.translate(xOffset, yOffset); + canvas.scale(scale, scale, 1); + mOldScreenTexture.draw(canvas, -xOffset, -yOffset); + canvas.restore(); + } + + public void applyBackground(GLView view, GLCanvas canvas) { + if (mCurrentBackgroundAlpha > 0f) { + applyOldTexture(view, canvas, mCurrentBackgroundAlpha, mCurrentBackgroundScale, true); + } + } + + public void applyContentTransform(GLView view, GLCanvas canvas) { + int xOffset = view.getWidth() / 2; + int yOffset = view.getHeight() / 2; + canvas.translate(xOffset, yOffset); + canvas.scale(mCurrentContentScale, mCurrentContentScale, 1); + canvas.translate(-xOffset, -yOffset); + canvas.setAlpha(mCurrentContentAlpha); + } + + public void applyOverlay(GLView view, GLCanvas canvas) { + if (mCurrentOverlayAlpha > 0f) { + applyOldTexture(view, canvas, mCurrentOverlayAlpha, mCurrentOverlayScale, false); + } + } +} diff --git a/src/com/hippo/ehviewer/gallery/glrenderer/BasicTexture.java b/src/com/hippo/ehviewer/gallery/glrenderer/BasicTexture.java index ec10f7738..9e1caa27e 100644 --- a/src/com/hippo/ehviewer/gallery/glrenderer/BasicTexture.java +++ b/src/com/hippo/ehviewer/gallery/glrenderer/BasicTexture.java @@ -19,8 +19,8 @@ package com.hippo.ehviewer.gallery.glrenderer; import java.util.WeakHashMap; import android.graphics.RectF; +import android.util.Log; -import com.hippo.ehviewer.util.Log; import com.hippo.ehviewer.util.MathUtils; // BasicTexture is a Texture corresponds to a real GL texture. @@ -28,7 +28,6 @@ import com.hippo.ehviewer.util.MathUtils; // If a BasicTexture is loaded into GL memory, it has a GL texture id. public abstract class BasicTexture implements Texture { - @SuppressWarnings("unused") private static final String TAG = "BasicTexture"; protected static final int UNSPECIFIED = -1; @@ -53,6 +52,7 @@ public abstract class BasicTexture implements Texture { protected GLCanvas mCanvasRef = null; private static WeakHashMap sAllTextures = new WeakHashMap(); + @SuppressWarnings("rawtypes") private static ThreadLocal sInFinalizer = new ThreadLocal(); protected BasicTexture(GLCanvas canvas, int id, int state) { @@ -185,6 +185,7 @@ public abstract class BasicTexture implements Texture { } @Override + @SuppressWarnings("unchecked") protected void finalize() { sInFinalizer.set(BasicTexture.class); recycle(); diff --git a/src/com/hippo/ehviewer/gallery/glrenderer/BitmapTexture.java b/src/com/hippo/ehviewer/gallery/glrenderer/BitmapTexture.java index ed686bc8b..120f62c28 100644 --- a/src/com/hippo/ehviewer/gallery/glrenderer/BitmapTexture.java +++ b/src/com/hippo/ehviewer/gallery/glrenderer/BitmapTexture.java @@ -16,9 +16,8 @@ package com.hippo.ehviewer.gallery.glrenderer; -import android.graphics.Bitmap; - import junit.framework.Assert; +import android.graphics.Bitmap; // BitmapTexture is a texture whose content is specified by a fixed Bitmap. // diff --git a/src/com/hippo/ehviewer/gallery/glrenderer/CanvasTexture.java b/src/com/hippo/ehviewer/gallery/glrenderer/CanvasTexture.java index e59be3225..24b23d90a 100644 --- a/src/com/hippo/ehviewer/gallery/glrenderer/CanvasTexture.java +++ b/src/com/hippo/ehviewer/gallery/glrenderer/CanvasTexture.java @@ -34,8 +34,8 @@ abstract class CanvasTexture extends UploadedTexture { setOpaque(false); } - @SuppressLint("WrongCall") @Override + @SuppressLint("WrongCall") protected Bitmap onGetBitmap() { Bitmap bitmap = Bitmap.createBitmap(mWidth, mHeight, mConfig); mCanvas = new Canvas(bitmap); diff --git a/src/com/hippo/ehviewer/gallery/glrenderer/ExtTexture.java b/src/com/hippo/ehviewer/gallery/glrenderer/ExtTexture.java index 6f6b1085d..9b249cc4c 100644 --- a/src/com/hippo/ehviewer/gallery/glrenderer/ExtTexture.java +++ b/src/com/hippo/ehviewer/gallery/glrenderer/ExtTexture.java @@ -20,7 +20,7 @@ package com.hippo.ehviewer.gallery.glrenderer; // Before drawing, setSize() should be called. public class ExtTexture extends BasicTexture { - private int mTarget; + private final int mTarget; public ExtTexture(GLCanvas canvas, int target) { GLId glId = canvas.getGLId(); diff --git a/src/com/hippo/ehviewer/gallery/glrenderer/GLCanvas.java b/src/com/hippo/ehviewer/gallery/glrenderer/GLCanvas.java index 204e7c2f3..83cfd5685 100644 --- a/src/com/hippo/ehviewer/gallery/glrenderer/GLCanvas.java +++ b/src/com/hippo/ehviewer/gallery/glrenderer/GLCanvas.java @@ -20,8 +20,6 @@ import android.graphics.Bitmap; import android.graphics.Rect; import android.graphics.RectF; -import javax.microedition.khronos.opengles.GL11; - // // GLCanvas gives a convenient interface to draw using OpenGL. // @@ -179,18 +177,6 @@ public interface GLCanvas { public abstract void texSubImage2D(BasicTexture texture, int xOffset, int yOffset, Bitmap bitmap, int format, int type); - - /** - * Calls glTexSubImage2D to upload a bitmap to the texture. - * - * @param texture The target texture to write to. - * @param xOffset Specifies a texel offset in the x direction within the - * texture array. - * @param yOffset Specifies a texel offset in the y direction within the - * texture array. - */ - public abstract void texSubImage2D(BasicTexture texture, int xOffset, int yOffset, - Bitmap bitmap); /** * Generates buffers and uploads the buffer data. diff --git a/src/com/hippo/ehviewer/gallery/glrenderer/GLES11Canvas.java b/src/com/hippo/ehviewer/gallery/glrenderer/GLES11Canvas.java index 4b36dd802..79fdf820b 100644 --- a/src/com/hippo/ehviewer/gallery/glrenderer/GLES11Canvas.java +++ b/src/com/hippo/ehviewer/gallery/glrenderer/GLES11Canvas.java @@ -28,19 +28,19 @@ import javax.microedition.khronos.opengles.GL11Ext; import javax.microedition.khronos.opengles.GL11ExtensionPack; import junit.framework.Assert; +import android.annotation.SuppressLint; import android.graphics.Bitmap; import android.graphics.Rect; import android.graphics.RectF; import android.opengl.GLU; import android.opengl.GLUtils; import android.opengl.Matrix; +import android.util.Log; import com.hippo.ehviewer.util.IntArray; -import com.hippo.ehviewer.util.Log; import com.hippo.ehviewer.util.Utils; public class GLES11Canvas implements GLCanvas { - @SuppressWarnings("unused") private static final String TAG = "GLCanvasImp"; private static final float OPAQUE_ALPHA = 0.95f; @@ -557,7 +557,6 @@ public class GLES11Canvas implements GLCanvas { mGLState.setBlendEnabled(mBlendEnabled && (!from.isOpaque() || !Utils.isOpaque(toColor) || alpha < OPAQUE_ALPHA)); - final GL11 gl = mGL; if (!bindTexture(from)) return; // Interpolate the RGB and alpha values between both textures. @@ -591,7 +590,6 @@ public class GLES11Canvas implements GLCanvas { private int mTextureTarget = GL11.GL_TEXTURE_2D; private boolean mBlendEnabled = true; private float mLineWidth = 1.0f; - private final boolean mLineSmooth = false; public GLState(GL11 gl) { mGL = gl; @@ -817,6 +815,7 @@ public class GLES11Canvas implements GLCanvas { } @Override + @SuppressLint("DefaultLocale") public void dumpStatisticsAndClear() { String line = String.format( "MESH:%d, TEX_OES:%d, TEX_RECT:%d, FILL_RECT:%d, LINE:%d", @@ -959,13 +958,6 @@ public class GLES11Canvas implements GLCanvas { GLUtils.texSubImage2D(target, 0, xOffset, yOffset, bitmap, format, type); } - @Override - public void texSubImage2D(BasicTexture texture, int xOffset, int yOffset, Bitmap bitmap) { - int target = texture.getTarget(); - mGL.glBindTexture(target, texture.getId()); - GLUtils.texSubImage2D(target, 0, xOffset, yOffset, bitmap); - } - @Override public int uploadBuffer(FloatBuffer buf) { return uploadBuffer(buf, Float.SIZE / Byte.SIZE); diff --git a/src/com/hippo/ehviewer/gallery/glrenderer/GLES20Canvas.java b/src/com/hippo/ehviewer/gallery/glrenderer/GLES20Canvas.java index 867fc5b6d..8bbbdea48 100644 --- a/src/com/hippo/ehviewer/gallery/glrenderer/GLES20Canvas.java +++ b/src/com/hippo/ehviewer/gallery/glrenderer/GLES20Canvas.java @@ -22,15 +22,16 @@ import java.nio.FloatBuffer; import java.util.ArrayList; import java.util.Arrays; +import android.annotation.SuppressLint; import android.graphics.Bitmap; import android.graphics.Rect; import android.graphics.RectF; import android.opengl.GLES20; import android.opengl.GLUtils; import android.opengl.Matrix; +import android.util.Log; import com.hippo.ehviewer.util.IntArray; -import com.hippo.ehviewer.util.Log; public class GLES20Canvas implements GLCanvas { // ************** Constants ********************** @@ -818,6 +819,7 @@ public class GLES20Canvas implements GLCanvas { } @Override + @SuppressLint("DefaultLocale") public void dumpStatisticsAndClear() { String line = String.format("MESH:%d, TEX_RECT:%d, FILL_RECT:%d, LINE:%d", mCountDrawMesh, mCountTextureRect, mCountFillRect, mCountDrawLine); @@ -938,14 +940,6 @@ public class GLES20Canvas implements GLCanvas { GLUtils.texSubImage2D(target, 0, xOffset, yOffset, bitmap, format, type); } - @Override - public void texSubImage2D(BasicTexture texture, int xOffset, int yOffset, Bitmap bitmap) { - int target = texture.getTarget(); - GLES20.glBindTexture(target, texture.getId()); - checkError(); - GLUtils.texSubImage2D(target, 0, xOffset, yOffset, bitmap); - } - @Override public int uploadBuffer(FloatBuffer buf) { return uploadBuffer(buf, FLOAT_SIZE); diff --git a/src/com/hippo/ehviewer/gallery/glrenderer/GLES20IdImpl.java b/src/com/hippo/ehviewer/gallery/glrenderer/GLES20IdImpl.java index 4bd8497b7..11ce2142e 100644 --- a/src/com/hippo/ehviewer/gallery/glrenderer/GLES20IdImpl.java +++ b/src/com/hippo/ehviewer/gallery/glrenderer/GLES20IdImpl.java @@ -1,10 +1,10 @@ package com.hippo.ehviewer.gallery.glrenderer; -import android.opengl.GLES20; - import javax.microedition.khronos.opengles.GL11; import javax.microedition.khronos.opengles.GL11ExtensionPack; +import android.opengl.GLES20; + public class GLES20IdImpl implements GLId { private final int[] mTempIntArray = new int[1]; diff --git a/src/com/hippo/ehviewer/gallery/glrenderer/GLPaint.java b/src/com/hippo/ehviewer/gallery/glrenderer/GLPaint.java index c2feb8005..84e93554f 100644 --- a/src/com/hippo/ehviewer/gallery/glrenderer/GLPaint.java +++ b/src/com/hippo/ehviewer/gallery/glrenderer/GLPaint.java @@ -21,14 +21,12 @@ import junit.framework.Assert; public class GLPaint { private float mLineWidth = 1f; private int mColor = 0; - - public GLPaint() {} - - public GLPaint(int color, float width) { + + public GLPaint(int color, float lineWidth) { setColor(color); - setLineWidth(width); + setLineWidth(lineWidth); } - + public void setColor(int color) { mColor = color; } diff --git a/src/com/hippo/ehviewer/gallery/glrenderer/NinePatchChunk.java b/src/com/hippo/ehviewer/gallery/glrenderer/NinePatchChunk.java index 4998436d5..df204e852 100644 --- a/src/com/hippo/ehviewer/gallery/glrenderer/NinePatchChunk.java +++ b/src/com/hippo/ehviewer/gallery/glrenderer/NinePatchChunk.java @@ -16,11 +16,11 @@ package com.hippo.ehviewer.gallery.glrenderer; -import android.graphics.Rect; - import java.nio.ByteBuffer; import java.nio.ByteOrder; +import android.graphics.Rect; + // See "frameworks/base/include/utils/ResourceTypes.h" for the format of // NinePatch chunk. class NinePatchChunk { diff --git a/src/com/hippo/ehviewer/gallery/glrenderer/NinePatchTexture.java b/src/com/hippo/ehviewer/gallery/glrenderer/NinePatchTexture.java index fc2deee44..dd2d38a05 100644 --- a/src/com/hippo/ehviewer/gallery/glrenderer/NinePatchTexture.java +++ b/src/com/hippo/ehviewer/gallery/glrenderer/NinePatchTexture.java @@ -81,6 +81,7 @@ public class NinePatchTexture extends ResourceTexture { private static final int CACHE_SIZE = 16; private static final int CACHE_SIZE_START_MOVE = CACHE_SIZE / 2; private final int[] mKey = new int[CACHE_SIZE]; + @SuppressWarnings("unchecked") private final V[] mValue = (V[]) new Object[CACHE_SIZE]; private int mCount; // number of items in this cache diff --git a/src/com/hippo/ehviewer/gallery/glrenderer/RawTexture.java b/src/com/hippo/ehviewer/gallery/glrenderer/RawTexture.java index 1fd1db059..44e1390b8 100644 --- a/src/com/hippo/ehviewer/gallery/glrenderer/RawTexture.java +++ b/src/com/hippo/ehviewer/gallery/glrenderer/RawTexture.java @@ -16,10 +16,10 @@ package com.hippo.ehviewer.gallery.glrenderer; -import com.hippo.ehviewer.util.Log; - import javax.microedition.khronos.opengles.GL11; +import android.util.Log; + public class RawTexture extends BasicTexture { private static final String TAG = "RawTexture"; diff --git a/src/com/hippo/ehviewer/gallery/glrenderer/ResourceTexture.java b/src/com/hippo/ehviewer/gallery/glrenderer/ResourceTexture.java index db71a4e2b..c2580e630 100644 --- a/src/com/hippo/ehviewer/gallery/glrenderer/ResourceTexture.java +++ b/src/com/hippo/ehviewer/gallery/glrenderer/ResourceTexture.java @@ -16,12 +16,11 @@ package com.hippo.ehviewer.gallery.glrenderer; +import junit.framework.Assert; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; -import junit.framework.Assert; - // ResourceTexture is a texture whose Bitmap is decoded from a resource. // By default ResourceTexture is not opaque. public class ResourceTexture extends UploadedTexture { diff --git a/src/com/hippo/ehviewer/gallery/glrenderer/StringTexture.java b/src/com/hippo/ehviewer/gallery/glrenderer/StringTexture.java index 7bcdd17b5..24f364765 100644 --- a/src/com/hippo/ehviewer/gallery/glrenderer/StringTexture.java +++ b/src/com/hippo/ehviewer/gallery/glrenderer/StringTexture.java @@ -23,7 +23,6 @@ import android.graphics.Paint.FontMetricsInt; import android.graphics.Typeface; import android.text.TextPaint; import android.text.TextUtils; -import android.util.FloatMath; // StringTexture is a texture shows the content of a specified String. // @@ -72,7 +71,7 @@ public class StringTexture extends CanvasTexture { private static StringTexture newInstance(String text, TextPaint paint) { FontMetricsInt metrics = paint.getFontMetricsInt(); - int width = (int) FloatMath.ceil(paint.measureText(text)); + int width = (int)Math.ceil(paint.measureText(text)); int height = metrics.bottom - metrics.top; // The texture size needs to be at least 1x1. if (width <= 0) width = 1; diff --git a/src/com/hippo/ehviewer/gallery/glrenderer/TextureUploader.java b/src/com/hippo/ehviewer/gallery/glrenderer/TextureUploader.java index fab40fad7..14332e6e5 100644 --- a/src/com/hippo/ehviewer/gallery/glrenderer/TextureUploader.java +++ b/src/com/hippo/ehviewer/gallery/glrenderer/TextureUploader.java @@ -16,11 +16,11 @@ package com.hippo.ehviewer.gallery.glrenderer; +import java.util.ArrayDeque; + import com.hippo.ehviewer.gallery.ui.GLRoot; import com.hippo.ehviewer.gallery.ui.GLRoot.OnGLIdleListener; -import java.util.ArrayDeque; - public class TextureUploader implements OnGLIdleListener { private static final int INIT_CAPACITY = 64; private static final int QUOTA_PER_FRAME = 1; diff --git a/src/com/hippo/ehviewer/gallery/glrenderer/TiledTexture.java b/src/com/hippo/ehviewer/gallery/glrenderer/TiledTexture.java index 1599239f7..3831a02e0 100644 --- a/src/com/hippo/ehviewer/gallery/glrenderer/TiledTexture.java +++ b/src/com/hippo/ehviewer/gallery/glrenderer/TiledTexture.java @@ -16,6 +16,9 @@ package com.hippo.ehviewer.gallery.glrenderer; +import java.util.ArrayDeque; +import java.util.ArrayList; + import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.Canvas; @@ -29,9 +32,6 @@ import android.os.SystemClock; import com.hippo.ehviewer.gallery.ui.GLRoot; import com.hippo.ehviewer.gallery.ui.GLRoot.OnGLIdleListener; -import java.util.ArrayDeque; -import java.util.ArrayList; - // This class is similar to BitmapTexture, except the bitmap is // split into tiles. By doing so, we may increase the time required to // upload the whole bitmap but we reduce the time of uploading each tile @@ -129,18 +129,25 @@ public class TiledTexture implements Texture { @Override protected Bitmap onGetBitmap() { - int x = BORDER_SIZE - offsetX; - int y = BORDER_SIZE - offsetY; - int r = bitmap.getWidth() + x; - int b = bitmap.getHeight() + y; - sCanvas.drawBitmap(bitmap, x, y, sBitmapPaint); + // make a local copy of the reference to the bitmap, + // since it might be null'd in a different thread. b/8694871 + Bitmap localBitmapRef = bitmap; bitmap = null; - // draw borders if need - if (x > 0) sCanvas.drawLine(x - 1, 0, x - 1, TILE_SIZE, sPaint); - if (y > 0) sCanvas.drawLine(0, y - 1, TILE_SIZE, y - 1, sPaint); - if (r < CONTENT_SIZE) sCanvas.drawLine(r, 0, r, TILE_SIZE, sPaint); - if (b < CONTENT_SIZE) sCanvas.drawLine(0, b, TILE_SIZE, b, sPaint); + if (localBitmapRef != null) { + int x = BORDER_SIZE - offsetX; + int y = BORDER_SIZE - offsetY; + int r = localBitmapRef.getWidth() + x; + int b = localBitmapRef.getHeight() + y; + sCanvas.drawBitmap(localBitmapRef, x, y, sBitmapPaint); + localBitmapRef = null; + + // draw borders if need + if (x > 0) sCanvas.drawLine(x - 1, 0, x - 1, TILE_SIZE, sPaint); + if (y > 0) sCanvas.drawLine(0, y - 1, TILE_SIZE, y - 1, sPaint); + if (r < CONTENT_SIZE) sCanvas.drawLine(r, 0, r, TILE_SIZE, sPaint); + if (b < CONTENT_SIZE) sCanvas.drawLine(0, b, TILE_SIZE, b, sPaint); + } return sUploadBitmap; } diff --git a/src/com/hippo/ehviewer/gallery/glrenderer/UploadedTexture.java b/src/com/hippo/ehviewer/gallery/glrenderer/UploadedTexture.java index 7e6d2b402..1d0f0c39b 100644 --- a/src/com/hippo/ehviewer/gallery/glrenderer/UploadedTexture.java +++ b/src/com/hippo/ehviewer/gallery/glrenderer/UploadedTexture.java @@ -143,9 +143,8 @@ public abstract class UploadedTexture extends BasicTexture { } private void freeBitmap() { - //Assert.assertTrue(mBitmap != null); - if (mBitmap != null) - onFreeBitmap(mBitmap); + Assert.assertTrue(mBitmap != null); + onFreeBitmap(mBitmap); mBitmap = null; } @@ -210,10 +209,12 @@ public abstract class UploadedTexture extends BasicTexture { private void uploadToCanvas(GLCanvas canvas) { Bitmap bitmap = getBitmap(); - if (bitmap != null && !bitmap.isRecycled()) { + if (bitmap != null) { try { int bWidth = bitmap.getWidth(); int bHeight = bitmap.getHeight(); + int width = bWidth + mBorder * 2; + int height = bHeight + mBorder * 2; int texWidth = getTextureWidth(); int texHeight = getTextureHeight(); diff --git a/src/com/hippo/ehviewer/gallery/ui/DownUpDetector.java b/src/com/hippo/ehviewer/gallery/ui/DownUpDetector.java index 1b0a2deb0..ebb0bb401 100644 --- a/src/com/hippo/ehviewer/gallery/ui/DownUpDetector.java +++ b/src/com/hippo/ehviewer/gallery/ui/DownUpDetector.java @@ -25,7 +25,7 @@ public class DownUpDetector { } private boolean mStillDown; - private DownUpListener mListener; + private final DownUpListener mListener; public DownUpDetector(DownUpListener listener) { mListener = listener; diff --git a/src/com/hippo/ehviewer/gallery/ui/GLRootView.java b/src/com/hippo/ehviewer/gallery/ui/GLRootView.java index 7ac3f7524..f96fbcc7c 100644 --- a/src/com/hippo/ehviewer/gallery/ui/GLRootView.java +++ b/src/com/hippo/ehviewer/gallery/ui/GLRootView.java @@ -25,7 +25,6 @@ import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.opengles.GL10; import javax.microedition.khronos.opengles.GL11; -import android.annotation.SuppressLint; import android.annotation.TargetApi; import android.content.Context; import android.graphics.Matrix; @@ -39,12 +38,12 @@ import android.view.MotionEvent; import android.view.SurfaceHolder; import com.hippo.ehviewer.gallery.anim.CanvasAnimation; -import com.hippo.ehviewer.gallery.common.ApiHelper; import com.hippo.ehviewer.gallery.glrenderer.BasicTexture; import com.hippo.ehviewer.gallery.glrenderer.GLCanvas; import com.hippo.ehviewer.gallery.glrenderer.GLES11Canvas; import com.hippo.ehviewer.gallery.glrenderer.GLES20Canvas; import com.hippo.ehviewer.gallery.glrenderer.UploadedTexture; +import com.hippo.ehviewer.gallery.util.ApiHelper; import com.hippo.ehviewer.gallery.util.GalleryUtils; import com.hippo.ehviewer.gallery.util.MotionEventHelper; import com.hippo.ehviewer.util.Log; @@ -71,9 +70,6 @@ public class GLRootView extends GLSurfaceView private static final boolean DEBUG_DRAWING_STAT = false; - private static final boolean DEBUG_PROFILE = false; - private static final boolean DEBUG_PROFILE_SLOW_ONLY = false; - private static final int FLAG_INITIALIZED = 1; private static final int FLAG_NEED_LAYOUT = 2; @@ -106,14 +102,13 @@ public class GLRootView extends GLSurfaceView mRenderLock.newCondition(); private boolean mFreeze; - private long mLastDrawFinishTime; private boolean mInDownState = false; - //private boolean mFirstDraw = true; public GLRootView(Context context) { this(context, null); } + @SuppressWarnings("deprecation") public GLRootView(Context context, AttributeSet attrs) { super(context, attrs); mFlags |= FLAG_INITIALIZED; @@ -179,8 +174,8 @@ public class GLRootView extends GLSurfaceView superRequestRender(); } - @SuppressLint("NewApi") @Override + @TargetApi(Build.VERSION_CODES.JELLY_BEAN) public void requestRender() { if (DEBUG_INVALIDATE) { StackTraceElement e = Thread.currentThread().getStackTrace()[4]; @@ -296,7 +291,7 @@ public class GLRootView extends GLSurfaceView mRenderLock.unlock(); } - if (DEBUG_FPS || DEBUG_PROFILE) { + if (DEBUG_FPS) { setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY); } else { setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); @@ -314,6 +309,7 @@ public class GLRootView extends GLSurfaceView + ", gl10: " + gl1.toString()); Process.setThreadPriority(Process.THREAD_PRIORITY_DISPLAY); GalleryUtils.setRenderThread(); + GL11 gl = (GL11) gl1; Utils.assertTrue(mGL == gl); @@ -347,21 +343,6 @@ public class GLRootView extends GLSurfaceView } finally { mRenderLock.unlock(); } -/* - // We put a black cover View in front of the SurfaceView and hide it - // after the first draw. This prevents the SurfaceView being transparent - // before the first draw. - if (mFirstDraw) { - mFirstDraw = false; - post(new Runnable() { - @Override - public void run() { - View root = getRootView(); - View cover = root.findViewById(R.id.gl_root_cover); - cover.setVisibility(GONE); - } - }); - }*/ } private void onDrawFrameLocked(GL10 gl) { @@ -385,6 +366,9 @@ public class GLRootView extends GLSurfaceView rotateCanvas(-mCompensation); if (mContentView != null) { mContentView.render(mCanvas); + } else { + // Make sure we always draw something to prevent displaying garbage + mCanvas.clearBuffer(); } mCanvas.restore(); @@ -544,6 +528,7 @@ public class GLRootView extends GLSurfaceView } @Override + @SuppressWarnings("deprecation") @TargetApi(Build.VERSION_CODES.JELLY_BEAN) public void setLightsOutMode(boolean enabled) { if (!ApiHelper.HAS_SET_SYSTEM_UI_VISIBILITY) return; diff --git a/src/com/hippo/ehviewer/gallery/ui/GLView.java b/src/com/hippo/ehviewer/gallery/ui/GLView.java index 22841248c..203e3373b 100644 --- a/src/com/hippo/ehviewer/gallery/ui/GLView.java +++ b/src/com/hippo/ehviewer/gallery/ui/GLView.java @@ -24,6 +24,7 @@ import android.os.SystemClock; import android.view.MotionEvent; import com.hippo.ehviewer.gallery.anim.CanvasAnimation; +import com.hippo.ehviewer.gallery.anim.StateTransitionAnimation; import com.hippo.ehviewer.gallery.glrenderer.GLCanvas; import com.hippo.ehviewer.util.Log; import com.hippo.ehviewer.util.Utils; @@ -81,6 +82,7 @@ public class GLView { protected int mScrollWidth = 0; private float [] mBackgroundColor; + private StateTransitionAnimation mTransition; public void startAnimation(CanvasAnimation animation) { GLRoot root = getGLRoot(); @@ -222,12 +224,28 @@ public class GLView { } protected void render(GLCanvas canvas) { + boolean transitionActive = false; + if (mTransition != null && mTransition.calculate(AnimationTime.get())) { + invalidate(); + transitionActive = mTransition.isActive(); + } renderBackground(canvas); canvas.save(); + if (transitionActive) { + mTransition.applyContentTransform(this, canvas); + } for (int i = 0, n = getComponentCount(); i < n; ++i) { renderChild(canvas, getComponent(i)); } canvas.restore(); + if (transitionActive) { + mTransition.applyOverlay(this, canvas); + } + } + + public void setIntroAnimation(StateTransitionAnimation intro) { + mTransition = intro; + if (mTransition != null) mTransition.start(); } public float [] getBackgroundColor() { @@ -242,6 +260,10 @@ public class GLView { if (mBackgroundColor != null) { view.clearBuffer(mBackgroundColor); } + if (mTransition != null && mTransition.isActive()) { + mTransition.applyBackground(this, view); + return; + } } protected void renderChild(GLCanvas canvas, GLView component) { diff --git a/src/com/hippo/ehviewer/gallery/common/ApiHelper.java b/src/com/hippo/ehviewer/gallery/util/ApiHelper.java similarity index 96% rename from src/com/hippo/ehviewer/gallery/common/ApiHelper.java rename to src/com/hippo/ehviewer/gallery/util/ApiHelper.java index 5f1118676..3b063564a 100644 --- a/src/com/hippo/ehviewer/gallery/common/ApiHelper.java +++ b/src/com/hippo/ehviewer/gallery/util/ApiHelper.java @@ -14,7 +14,9 @@ * limitations under the License. */ -package com.hippo.ehviewer.gallery.common; +package com.hippo.ehviewer.gallery.util; + +import java.lang.reflect.Field; import android.app.admin.DevicePolicyManager; import android.content.ComponentName; @@ -24,8 +26,6 @@ import android.provider.MediaStore.MediaColumns; import android.view.View; import android.view.WindowManager; -import java.lang.reflect.Field; - public class ApiHelper { public static interface VERSION_CODES { // These value are copied from Build.VERSION_CODES @@ -113,9 +113,6 @@ public class ApiHelper { public static final boolean HAS_MEDIA_ACTION_SOUND = Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN; - public static final boolean HAS_OLD_PANORAMA = - Build.VERSION.SDK_INT >= VERSION_CODES.ICE_CREAM_SANDWICH; - public static final boolean HAS_TIME_LAPSE_RECORDING = Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB; @@ -128,9 +125,6 @@ public class ApiHelper { public static final boolean HAS_CAMERA_METERING_AREA = Build.VERSION.SDK_INT >= VERSION_CODES.ICE_CREAM_SANDWICH; - public static final boolean HAS_FINE_RESOLUTION_QUALITY_LEVELS = - Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB; - public static final boolean HAS_MOTION_EVENT_TRANSFORM = Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB; diff --git a/src/com/hippo/ehviewer/gallery/util/GalleryUtils.java b/src/com/hippo/ehviewer/gallery/util/GalleryUtils.java index 6c0e51804..348ce71b2 100644 --- a/src/com/hippo/ehviewer/gallery/util/GalleryUtils.java +++ b/src/com/hippo/ehviewer/gallery/util/GalleryUtils.java @@ -42,10 +42,6 @@ public class GalleryUtils { sCurrentThread = Thread.currentThread(); } - public static boolean isRenderThread() { - return sCurrentThread == Thread.currentThread(); - } - public static void assertNotInRenderThread() { if (!sWarned) { if (Thread.currentThread() == sCurrentThread) { diff --git a/src/com/hippo/ehviewer/gallery/util/MotionEventHelper.java b/src/com/hippo/ehviewer/gallery/util/MotionEventHelper.java index ea562148a..228163437 100644 --- a/src/com/hippo/ehviewer/gallery/util/MotionEventHelper.java +++ b/src/com/hippo/ehviewer/gallery/util/MotionEventHelper.java @@ -15,14 +15,12 @@ */ package com.hippo.ehviewer.gallery.util; +import android.annotation.SuppressLint; import android.annotation.TargetApi; import android.graphics.Matrix; -import android.util.FloatMath; import android.view.MotionEvent; import android.view.MotionEvent.PointerCoords; -import com.hippo.ehviewer.gallery.common.ApiHelper; - public final class MotionEventHelper { private MotionEventHelper() {} @@ -36,6 +34,7 @@ public final class MotionEventHelper { } } + @SuppressLint("Recycle") @TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB) private static MotionEvent transformEventNew(MotionEvent e, Matrix m) { MotionEvent newEvent = MotionEvent.obtain(e); @@ -44,6 +43,7 @@ public final class MotionEventHelper { } // This is copied from Input.cpp in the android framework. + @SuppressLint("Recycle") private static MotionEvent transformEventOld(MotionEvent e, Matrix m) { long downTime = e.getDownTime(); long eventTime = e.getEventTime(); @@ -73,6 +73,7 @@ public final class MotionEventHelper { m, pointerCoords[i].orientation); } + @SuppressWarnings("deprecation") MotionEvent n = MotionEvent.obtain(downTime, eventTime, action, pointerCount, pointerIds, pointerCoords, metaState, xPrecision, yPrecision, deviceId, edgeFlags, source, flags); @@ -104,8 +105,8 @@ public final class MotionEventHelper { // angle from vertical. Coordinate system: down is increasing Y, right is // increasing X. float[] v = new float[2]; - v[0] = FloatMath.sin(angleRadians); - v[1] = -FloatMath.cos(angleRadians); + v[0] = (float)Math.sin(angleRadians); + v[1] = -(float)Math.cos(angleRadians); m.mapVectors(v); // Derive the transformed vector's clockwise angle from vertical. diff --git a/src/com/hippo/ehviewer/util/ThreadPool.java b/src/com/hippo/ehviewer/util/ThreadPool.java deleted file mode 100644 index 7d30abb58..000000000 --- a/src/com/hippo/ehviewer/util/ThreadPool.java +++ /dev/null @@ -1,268 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.hippo.ehviewer.util; - -import com.hippo.ehviewer.util.Log; - -import java.util.concurrent.Executor; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - -public class ThreadPool { - @SuppressWarnings("unused") - private static final String TAG = "ThreadPool"; - private static final int CORE_POOL_SIZE = 4; - private static final int MAX_POOL_SIZE = 8; - private static final int KEEP_ALIVE_TIME = 10; // 10 seconds - - // Resource type - public static final int MODE_NONE = 0; - public static final int MODE_CPU = 1; - public static final int MODE_NETWORK = 2; - - public static final JobContext JOB_CONTEXT_STUB = new JobContextStub(); - - ResourceCounter mCpuCounter = new ResourceCounter(2); - ResourceCounter mNetworkCounter = new ResourceCounter(2); - - // A Job is like a Callable, but it has an addition JobContext parameter. - public interface Job { - public T run(JobContext jc); - } - - public interface JobContext { - boolean isCancelled(); - void setCancelListener(CancelListener listener); - boolean setMode(int mode); - } - - private static class JobContextStub implements JobContext { - @Override - public boolean isCancelled() { - return false; - } - - @Override - public void setCancelListener(CancelListener listener) { - } - - @Override - public boolean setMode(int mode) { - return true; - } - } - - public interface CancelListener { - public void onCancel(); - } - - private static class ResourceCounter { - public int value; - public ResourceCounter(int v) { - value = v; - } - } - - private final Executor mExecutor; - - public ThreadPool() { - this(CORE_POOL_SIZE, MAX_POOL_SIZE); - } - - public ThreadPool(int initPoolSize, int maxPoolSize) { - mExecutor = new ThreadPoolExecutor( - initPoolSize, maxPoolSize, KEEP_ALIVE_TIME, - TimeUnit.SECONDS, new LinkedBlockingQueue(), - new PriorityThreadFactory("thread-pool", - android.os.Process.THREAD_PRIORITY_DEFAULT)); - } - - // Submit a job to the thread pool. The listener will be called when the - // job is finished (or cancelled). - public Future submit(Job job, FutureListener listener) { - Worker w = new Worker(job, listener); - mExecutor.execute(w); - return w; - } - - public Future submit(Job job) { - return submit(job, null); - } - - private class Worker implements Runnable, Future, JobContext { - @SuppressWarnings("hiding") - private static final String TAG = "Worker"; - private Job mJob; - private FutureListener mListener; - private CancelListener mCancelListener; - private ResourceCounter mWaitOnResource; - private volatile boolean mIsCancelled; - private boolean mIsDone; - private T mResult; - private int mMode; - - public Worker(Job job, FutureListener listener) { - mJob = job; - mListener = listener; - } - - // This is called by a thread in the thread pool. - @Override - public void run() { - T result = null; - - // A job is in CPU mode by default. setMode returns false - // if the job is cancelled. - if (setMode(MODE_CPU)) { - try { - result = mJob.run(this); - } catch (Throwable ex) { - Log.w(TAG, "Exception in running a job", ex); - } - } - - synchronized(this) { - setMode(MODE_NONE); - mResult = result; - mIsDone = true; - notifyAll(); - } - if (mListener != null) mListener.onFutureDone(this); - } - - // Below are the methods for Future. - @Override - public synchronized void cancel() { - if (mIsCancelled) return; - mIsCancelled = true; - if (mWaitOnResource != null) { - synchronized (mWaitOnResource) { - mWaitOnResource.notifyAll(); - } - } - if (mCancelListener != null) { - mCancelListener.onCancel(); - } - } - - @Override - public boolean isCancelled() { - return mIsCancelled; - } - - @Override - public synchronized boolean isDone() { - return mIsDone; - } - - @Override - public synchronized T get() { - while (!mIsDone) { - try { - wait(); - } catch (Exception ex) { - Log.w(TAG, "ingore exception", ex); - // ignore. - } - } - return mResult; - } - - @Override - public void waitDone() { - get(); - } - - // Below are the methods for JobContext (only called from the - // thread running the job) - @Override - public synchronized void setCancelListener(CancelListener listener) { - mCancelListener = listener; - if (mIsCancelled && mCancelListener != null) { - mCancelListener.onCancel(); - } - } - - @Override - public boolean setMode(int mode) { - // Release old resource - ResourceCounter rc = modeToCounter(mMode); - if (rc != null) releaseResource(rc); - mMode = MODE_NONE; - - // Acquire new resource - rc = modeToCounter(mode); - if (rc != null) { - if (!acquireResource(rc)) { - return false; - } - mMode = mode; - } - - return true; - } - - private ResourceCounter modeToCounter(int mode) { - if (mode == MODE_CPU) { - return mCpuCounter; - } else if (mode == MODE_NETWORK) { - return mNetworkCounter; - } else { - return null; - } - } - - private boolean acquireResource(ResourceCounter counter) { - while (true) { - synchronized (this) { - if (mIsCancelled) { - mWaitOnResource = null; - return false; - } - mWaitOnResource = counter; - } - - synchronized (counter) { - if (counter.value > 0) { - counter.value--; - break; - } else { - try { - counter.wait(); - } catch (InterruptedException ex) { - // ignore. - } - } - } - } - - synchronized (this) { - mWaitOnResource = null; - } - - return true; - } - - private void releaseResource(ResourceCounter counter) { - synchronized (counter) { - counter.value++; - counter.notifyAll(); - } - } - } -}