Add support for the Z coordinate in GLCanvas and thus a new set of animations
to support this.
Change-Id: I652bbe48082a17bce4dca86217dc1351edd74f13
diff --git a/new3d/src/com/android/gallery3d/anim/AlphaAnimation.java b/new3d/src/com/android/gallery3d/anim/AlphaAnimation.java
new file mode 100644
index 0000000..d806885
--- /dev/null
+++ b/new3d/src/com/android/gallery3d/anim/AlphaAnimation.java
@@ -0,0 +1,34 @@
+// Copyright 2010 Google Inc. All Rights Reserved.
+
+package com.android.gallery3d.anim;
+
+import com.android.gallery3d.ui.GLCanvas;
+import com.android.gallery3d.ui.Util;
+
+public class AlphaAnimation extends CanvasAnimation {
+ private final float mStartAlpha;
+ private final float mEndAlpha;
+ private float mCurrentAlpha;
+
+ public AlphaAnimation(float from, float to) {
+ mStartAlpha = from;
+ mEndAlpha = to;
+ mCurrentAlpha = from;
+ }
+
+ @Override
+ public void apply(GLCanvas canvas) {
+ canvas.multiplyAlpha(mCurrentAlpha);
+ }
+
+ @Override
+ public int getCanvasSaveFlags() {
+ return GLCanvas.ALPHA_SAVE_FLAG;
+ }
+
+ @Override
+ protected void onCalculate(float progress) {
+ mCurrentAlpha = Util.clamp(mStartAlpha
+ + (mEndAlpha - mStartAlpha) * progress, 0f, 1f);
+ }
+}
diff --git a/new3d/src/com/android/gallery3d/anim/Animation.java b/new3d/src/com/android/gallery3d/anim/Animation.java
index 9cbef24..be9f5b7 100644
--- a/new3d/src/com/android/gallery3d/anim/Animation.java
+++ b/new3d/src/com/android/gallery3d/anim/Animation.java
@@ -49,6 +49,10 @@
mStartTime = ANIMATION_START;
}
+ public void setStartTime(long time) {
+ mStartTime = time;
+ }
+
public boolean isActive() {
return mStartTime != NO_ANIMATION;
}
@@ -58,11 +62,16 @@
if (mStartTime == ANIMATION_START) mStartTime = currentTimeMillis;
int elapse = (int) (currentTimeMillis - mStartTime);
float x = Util.clamp((float) elapse / mDuration, 0f, 1f);
- if (mInterpolator != null) x = mInterpolator.getInterpolation(x);
- if (onCalculate(x)) return true;
- mStartTime = NO_ANIMATION;
- return false;
+ onCalculate(mInterpolator != null
+ ? mInterpolator.getInterpolation(x)
+ : x);
+ if (elapse >= mDuration) {
+ mStartTime = NO_ANIMATION;
+ return false;
+ } else {
+ return true;
+ }
}
- abstract protected boolean onCalculate(float progress);
+ abstract protected void onCalculate(float progress);
}
diff --git a/new3d/src/com/android/gallery3d/anim/AnimationSet.java b/new3d/src/com/android/gallery3d/anim/AnimationSet.java
new file mode 100644
index 0000000..b4d2e99
--- /dev/null
+++ b/new3d/src/com/android/gallery3d/anim/AnimationSet.java
@@ -0,0 +1,62 @@
+// Copyright 2010 Google Inc. All Rights Reserved.
+
+package com.android.gallery3d.anim;
+
+import com.android.gallery3d.ui.GLCanvas;
+
+import java.util.ArrayList;
+
+public class AnimationSet extends CanvasAnimation {
+
+ private final ArrayList<CanvasAnimation> mAnimations =
+ new ArrayList<CanvasAnimation>();
+ private int mSaveFlags = 0;
+
+
+ public void addAnimation(CanvasAnimation anim) {
+ mAnimations.add(anim);
+ mSaveFlags |= anim.getCanvasSaveFlags();
+ }
+
+ @Override
+ public void apply(GLCanvas canvas) {
+ for (CanvasAnimation anim : mAnimations) {
+ anim.apply(canvas);
+ }
+ }
+
+ @Override
+ public int getCanvasSaveFlags() {
+ return mSaveFlags;
+ }
+
+ @Override
+ protected void onCalculate(float progress) {
+ // DO NOTHING
+ }
+
+ @Override
+ public boolean calculate(long currentTimeMillis) {
+ boolean more = false;
+ for (CanvasAnimation anim : mAnimations) {
+ more |= anim.calculate(currentTimeMillis);
+ }
+ return more;
+ }
+
+ @Override
+ public void start() {
+ for (CanvasAnimation anim : mAnimations) {
+ anim.start();
+ }
+ }
+
+ @Override
+ public boolean isActive() {
+ for (CanvasAnimation anim : mAnimations) {
+ if (anim.isActive()) return true;
+ }
+ return false;
+ }
+
+}
diff --git a/new3d/src/com/android/gallery3d/anim/CanvasAnimation.java b/new3d/src/com/android/gallery3d/anim/CanvasAnimation.java
new file mode 100644
index 0000000..de24ae4
--- /dev/null
+++ b/new3d/src/com/android/gallery3d/anim/CanvasAnimation.java
@@ -0,0 +1,11 @@
+// Copyright 2010 Google Inc. All Rights Reserved.
+
+package com.android.gallery3d.anim;
+
+import com.android.gallery3d.ui.GLCanvas;
+
+public abstract class CanvasAnimation extends Animation {
+
+ public abstract int getCanvasSaveFlags();
+ public abstract void apply(GLCanvas canvas);
+}
diff --git a/new3d/src/com/android/gallery3d/anim/FloatAnimation.java b/new3d/src/com/android/gallery3d/anim/FloatAnimation.java
index 7b3a2db..084383f 100644
--- a/new3d/src/com/android/gallery3d/anim/FloatAnimation.java
+++ b/new3d/src/com/android/gallery3d/anim/FloatAnimation.java
@@ -13,14 +13,8 @@
}
@Override
- protected boolean onCalculate(float progress) {
- if (progress < 1f) {
- mCurrent = mFrom + (mTo - mFrom) * progress;
- return true;
- } else {
- mCurrent = mTo;
- return false;
- }
+ protected void onCalculate(float progress) {
+ mCurrent = mFrom + (mTo - mFrom) * progress;
}
public float get() {
diff --git a/new3d/src/com/android/gallery3d/anim/IntAnimation.java b/new3d/src/com/android/gallery3d/anim/IntAnimation.java
index 2fdeb5d..9bdd5fe 100644
--- a/new3d/src/com/android/gallery3d/anim/IntAnimation.java
+++ b/new3d/src/com/android/gallery3d/anim/IntAnimation.java
@@ -13,14 +13,8 @@
}
@Override
- protected boolean onCalculate(float progress) {
- if (progress < 1f) {
- mCurrent = mFrom + (int)((mTo - mFrom) * progress + .5f);
- return true;
- } else {
- mCurrent = mTo;
- return false;
- }
+ protected void onCalculate(float progress) {
+ mCurrent = mFrom + (int)((mTo - mFrom) * progress + .5f);
}
public int get() {
diff --git a/new3d/src/com/android/gallery3d/anim/ScaleAnimation.java b/new3d/src/com/android/gallery3d/anim/ScaleAnimation.java
new file mode 100644
index 0000000..f5dca50
--- /dev/null
+++ b/new3d/src/com/android/gallery3d/anim/ScaleAnimation.java
@@ -0,0 +1,63 @@
+// Copyright 2010 Google Inc. All Rights Reserved.
+
+package com.android.gallery3d.anim;
+
+import com.android.gallery3d.ui.GLCanvas;
+
+public class ScaleAnimation extends CanvasAnimation {
+ private final float mFromX;
+ private final float mFromY;
+ private final float mFromZ;
+ private final float mToX;
+ private final float mToY;
+ private final float mToZ;
+
+ private float mCurrentX;
+ private float mCurrentY;
+ private float mCurrentZ;
+
+ private final float mPivotX;
+ private final float mPivotY;
+ private final float mPivotZ;
+
+ public ScaleAnimation(float fromX, float toX,
+ float fromY, float toY, float pivotX, float pivotY) {
+ this(fromX, toX, fromY, toY, 0, 0, pivotX, pivotY, 0);
+ }
+
+ public ScaleAnimation(float fromX, float toX, float fromY, float toY,
+ float fromZ, float toZ, float px, float py, float pz) {
+ mFromX = fromX;
+ mFromY = fromY;
+ mFromZ = fromZ;
+ mToX = toX;
+ mToY = toY;
+ mToZ = toZ;
+ mPivotX = px;
+ mPivotY = py;
+ mPivotZ = pz;
+ }
+
+ @Override
+ public void apply(GLCanvas canvas) {
+ if (mPivotX != 0 || mPivotY != 0 || mPivotZ != 0) {
+ canvas.translate(mPivotX, mPivotY, mPivotZ);
+ canvas.scale(mCurrentX, mCurrentY, mCurrentZ);
+ canvas.translate(-mPivotX, -mPivotY, -mPivotZ);
+ } else {
+ canvas.scale(mCurrentX, mCurrentY, mCurrentZ);
+ }
+ }
+
+ @Override
+ public int getCanvasSaveFlags() {
+ return GLCanvas.MATRIX_SAVE_FLAG;
+ }
+
+ @Override
+ protected void onCalculate(float progress) {
+ mCurrentX = mFromX + (mToX - mFromX) * progress;
+ mCurrentY = mFromY + (mToY - mFromY) * progress;
+ mCurrentZ = mFromZ + (mToZ - mFromZ) * progress;
+ }
+}
diff --git a/new3d/src/com/android/gallery3d/ui/DisplayItem.java b/new3d/src/com/android/gallery3d/ui/DisplayItem.java
index 2d97804..1174e5b 100644
--- a/new3d/src/com/android/gallery3d/ui/DisplayItem.java
+++ b/new3d/src/com/android/gallery3d/ui/DisplayItem.java
@@ -1,6 +1,5 @@
package com.android.gallery3d.ui;
-import android.graphics.Matrix;
public abstract class DisplayItem {
@@ -22,14 +21,9 @@
mTheata = p.mTheata;
}
- public void apply(Matrix matrix) {
- matrix.preTranslate(mX, mY);
- matrix.preRotate(mTheata);
- }
-
- public void inverse(Matrix matrix) {
- matrix.preRotate(-mTheata);
- matrix.preTranslate(-mX, -mY);
+ public void apply(GLCanvas canvas) {
+ canvas.translate(mX, mY, 0);
+ canvas.rotate(mTheata, 0, 0, 1);
}
}
diff --git a/new3d/src/com/android/gallery3d/ui/DisplayItemPanel.java b/new3d/src/com/android/gallery3d/ui/DisplayItemPanel.java
index 41bf59c..ba6ec37 100644
--- a/new3d/src/com/android/gallery3d/ui/DisplayItemPanel.java
+++ b/new3d/src/com/android/gallery3d/ui/DisplayItemPanel.java
@@ -1,9 +1,7 @@
package com.android.gallery3d.ui;
-import android.graphics.Matrix;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
-import android.view.animation.Transformation;
import java.util.ArrayList;
@@ -89,9 +87,7 @@
@Override
protected void render(GLCanvas canvas) {
- Transformation transform = canvas.getTransformation();
- Matrix matrix = transform.getMatrix();
- matrix.preTranslate(-mScrollX, 0);
+ canvas.translate(-mScrollX, 0, 0);
if (mAnimationStartTime == NO_ANIMATION) {
for (DisplayItem item: mItems) {
renderItem(canvas, item);
@@ -114,35 +110,32 @@
invalidate();
}
}
- matrix.preTranslate(mScrollX, 0);
+ canvas.translate(mScrollX, 0, 0);
}
private void renderItem(GLCanvas canvas, DisplayItem item) {
- Transformation transformation = canvas.pushTransform();
- item.mCurrent.apply(transformation.getMatrix());
+ canvas.save(GLCanvas.ALPHA_SAVE_FLAG | GLCanvas.MATRIX_SAVE_FLAG);
+ item.mCurrent.apply(canvas);
item.render(canvas);
- canvas.popTransform();
+ canvas.restore();
}
private void renderItem(
GLCanvas canvas, DisplayItem item, float interpolate) {
- Transformation transform = canvas.getTransformation();
- float alpha = transform.getAlpha();
- Matrix matrix = transform.getMatrix();
+ canvas.save(GLCanvas.ALPHA_SAVE_FLAG | GLCanvas.MATRIX_SAVE_FLAG);
switch (item.mState) {
case STATE_MOVED:
item.updateCurrentPosition(interpolate);
break;
case STATE_NEWBIE:
- transform.setAlpha(alpha * interpolate);
+ canvas.multiplyAlpha(interpolate);
break;
case STATE_REMOVED:
- transform.setAlpha(alpha * (1.0f - interpolate));
+ canvas.multiplyAlpha(1.0f - interpolate);
break;
}
- item.mCurrent.apply(matrix);
+ item.mCurrent.apply(canvas);
item.render(canvas);
- item.mCurrent.inverse(matrix);
- transform.setAlpha(alpha);
+ canvas.restore();
}
}
diff --git a/new3d/src/com/android/gallery3d/ui/GLCanvas.java b/new3d/src/com/android/gallery3d/ui/GLCanvas.java
index 448b31d..770cac4 100644
--- a/new3d/src/com/android/gallery3d/ui/GLCanvas.java
+++ b/new3d/src/com/android/gallery3d/ui/GLCanvas.java
@@ -1,10 +1,9 @@
package com.android.gallery3d.ui;
-import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.RectF;
import android.opengl.GLU;
-import android.view.animation.Transformation;
+import android.opengl.Matrix;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
@@ -17,6 +16,12 @@
import javax.microedition.khronos.opengles.GL11Ext;
public class GLCanvas {
+
+ public static final int ALL_SAVE_FLAG = 0xFFFFFFFF;
+ public static final int CLIP_SAVE_FLAG = 0x01;
+ public static final int ALPHA_SAVE_FLAG = 0x02;
+ public static final int MATRIX_SAVE_FLAG = 0x04;
+
// We need 16 vertices for a normal nine-patch image (the 4x4 vertices)
private static final int VERTEX_BUFFER_SIZE = 16 * 2;
@@ -27,13 +32,6 @@
private final GL11 mGL;
- private final Stack<Transformation> mFreeTransform =
- new Stack<Transformation>();
-
- private final Transformation mTransformation = new Transformation();
- private final Stack<Transformation> mTransformStack =
- new Stack<Transformation>();
-
private final float mMatrixValues[] = new float[16];
private final float mUvBuffer[] = new float[VERTEX_BUFFER_SIZE];
@@ -54,8 +52,11 @@
private long mAnimationTime;
- private int mWidth;
- private int mHeight;
+ private float mAlpha;
+ private final Rect mClipRect = new Rect();
+ private final Stack<ConfigState> mRestoreStack =
+ new Stack<ConfigState>();
+ private ConfigState mRecycledRestoreAction;
GLCanvas(GL11 gl) {
mGL = gl;
@@ -64,53 +65,41 @@
}
public void setSize(int width, int height) {
- mWidth = width;
- mHeight = height;
GL11 gl = mGL;
-
gl.glViewport(0, 0, width, height);
gl.glMatrixMode(GL11.GL_PROJECTION);
gl.glLoadIdentity();
GLU.gluOrtho2D(gl, 0, width, 0, height);
- Matrix matrix = mTransformation.getMatrix();
- matrix.reset();
- matrix.preTranslate(0, mHeight);
- matrix.preScale(1, -1);
+ gl.glMatrixMode(GL11.GL_MODELVIEW);
+ gl.glLoadIdentity();
+
+ // The positive direction in Y coordinate in OpenGL is from bottom to
+ // top, which is different from the coordinate system in Java. So, we
+ // flip it here.
+ float matrix[] = mMatrixValues;
+ Matrix.setIdentityM(matrix, 0);
+ Matrix.translateM(matrix, 0, 0, height, 0);
+ Matrix.scaleM(matrix, 0, 1, -1, 1);
+
+ mClipRect.set(0, 0, width, height);
+ gl.glScissor(0, 0, width, height);
}
public long currentAnimationTimeMillis() {
return mAnimationTime;
}
- public Transformation obtainTransformation() {
- if (!mFreeTransform.isEmpty()) {
- Transformation t = mFreeTransform.pop();
- t.clear();
- return t;
- }
- return new Transformation();
+ public void setAlpha(float alpha) {
+ mAlpha = alpha;
}
- public void freeTransformation(Transformation freeTransformation) {
- mFreeTransform.push(freeTransformation);
+ public void multiplyAlpha(float alpha) {
+ mAlpha *= alpha;
}
- public Transformation getTransformation() {
- return mTransformation;
- }
-
- public Transformation pushTransform() {
- Transformation trans = obtainTransformation();
- trans.set(mTransformation);
- mTransformStack.push(trans);
- return mTransformation;
- }
-
- public void popTransform() {
- Transformation trans = mTransformStack.pop();
- mTransformation.set(trans);
- freeTransformation(trans);
+ public float getAlpha() {
+ return mAlpha;
}
private static ByteBuffer allocateDirectNativeOrderBuffer(int size) {
@@ -133,6 +122,8 @@
gl.glTexCoordPointer(2, GL11.GL_FLOAT, 0, mUvPointer);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
+ // mMatrixValues will be initialized in setSize()
+ mAlpha = 1.0f;
}
private static void putRectangle(float x, float y,
@@ -149,17 +140,14 @@
}
public void setColor(int color) {
- float alpha = mTransformation.getAlpha();
+ float alpha = mAlpha;
mGLState.setBlendEnabled(!Util.isOpaque(color) || alpha < OPAQUE_ALPHA);
mGLState.setFragmentColor(color, alpha);
}
public void drawLine(int x1, int y1, int x2, int y2) {
- float matrix[] = mMatrixValues;
- mTransformation.getMatrix().getValues(matrix);
GL11 gl = mGL;
- gl.glPushMatrix();
- gl.glMultMatrixf(toGLMatrix(matrix), 0);
+ gl.glLoadMatrixf(mMatrixValues, 0);
float buffer[] = mXyBuffer;
buffer[0] = x1;
buffer[1] = y1;
@@ -167,32 +155,34 @@
buffer[3] = y2;
mXyPointer.put(buffer, 0, 4).position(0);
gl.glDrawArrays(GL11.GL_LINE_STRIP, 0, 2);
- gl.glPopMatrix();
}
public void fillRect(Rect r) {
fillRect(r.left, r.top, r.right - r.left, r.bottom - r.top);
}
- public void fillRect(int x, int y, int width, int height) {
- float matrix[] = mMatrixValues;
- mTransformation.getMatrix().getValues(matrix);
- fillRect(x, y, width, height, matrix);
+ public void translate(float x, float y, float z) {
+ Matrix.translateM(mMatrixValues, 0, x, y, z);
}
- private void fillRect(
- int x, int y, int width, int height, float matrix[]) {
+ public void scale(float sx, float sy, float sz) {
+ Matrix.scaleM(mMatrixValues, 0, sx, sy, sz);
+ }
+
+ public void rotate(float angle, float x, float y, float z) {
+ Matrix.rotateM(mMatrixValues, 0, angle, x, y, z);
+ }
+
+ public void fillRect(int x, int y, int width, int height) {
GL11 gl = mGL;
- gl.glPushMatrix();
- gl.glMultMatrixf(toGLMatrix(matrix), 0);
+ gl.glLoadMatrixf(mMatrixValues, 0);
putRectangle(x, y, width, height, mXyBuffer, mXyPointer);
gl.glDrawArrays(GL11.GL_TRIANGLE_STRIP, 0, 4);
- gl.glPopMatrix();
}
public void drawNinePatch(
NinePatchTexture tex, int x, int y, int width, int height) {
- float alpha = mTransformation.getAlpha();
+ float alpha = mAlpha;
NinePatchChunk chunk = tex.getNinePatchChunk();
mGLState.setTexture2DEnabled(true);
@@ -216,14 +206,11 @@
mGLState.setBlendEnabled(!tex.isOpaque() || alpha < OPAQUE_ALPHA);
mGLState.setTextureAlpha(alpha);
- Matrix matrix = mTransformation.getMatrix();
- matrix.getValues(mMatrixValues);
+
GL11 gl = mGL;
- gl.glPushMatrix();
- gl.glMultMatrixf(toGLMatrix(mMatrixValues), 0);
+ gl.glLoadMatrixf(mMatrixValues, 0);
gl.glTranslatef(x, y, 0);
drawMesh(divX, divY, divU, divV, nx, ny);
- gl.glPopMatrix();
}
/**
@@ -368,50 +355,60 @@
idxCount, GL11.GL_UNSIGNED_BYTE, mIndexPointer);
}
- private float[] mapPoints(Matrix matrix, int x1, int y1, int x2, int y2) {
+ private float[] mapPoints(float matrix[], int x1, int y1, int x2, int y2) {
float[] point = mXyBuffer;
- point[0] = x1; point[1] = y1; point[2] = x2; point[3] = y2;
- matrix.mapPoints(point, 0, point, 0, 4);
+ int srcOffset = 6;
+ point[srcOffset] = x1;
+ point[srcOffset + 1] = y1;
+ point[srcOffset + 2] = 0;
+ point[srcOffset + 3] = 1;
+
+ int resultOffset = 0;
+ Matrix.multiplyMV(point, resultOffset, matrix, 0, point, srcOffset);
+ point[resultOffset] /= point[resultOffset + 3];
+ point[resultOffset + 1] /= point[resultOffset + 3];
+
+ // map the second point
+ point[srcOffset] = x2;
+ point[srcOffset + 1] = y2;
+ resultOffset = 2;
+ Matrix.multiplyMV(point, resultOffset, matrix, 0, point, srcOffset);
+ point[resultOffset] /= point[resultOffset + 3];
+ point[resultOffset + 1] /= point[resultOffset + 3];
+
return point;
}
- public void clipRect(int x, int y, int width, int height) {
- float point[] = mapPoints(
- mTransformation.getMatrix(), x, y + height, x + width, y);
+
+ public boolean clipRect(int left, int top, int right, int bottom) {
+ float point[] = mapPoints(mMatrixValues, left, top, right, bottom);
// mMatrix could be a rotation matrix. In this case, we need to find
// the boundaries after rotation. (only handle 90 * n degrees)
if (point[0] > point[2]) {
- x = (int) point[2];
- width = (int) point[0] - x;
+ left = (int) point[2];
+ right = (int) point[0];
} else {
- x = (int) point[0];
- width = (int) point[2] - x;
+ left = (int) point[0];
+ right = (int) point[2];
}
if (point[1] > point[3]) {
- y = (int) point[3];
- height = (int) point[1] - y;
+ top = (int) point[3];
+ bottom = (int) point[1];
} else {
- y = (int) point[1];
- height = (int) point[3] - y;
+ top = (int) point[1];
+ bottom = (int) point[3];
}
- mGL.glScissor(x, y, width, height);
- }
+ Rect clip = mClipRect;
- public void clearClip() {
- mGL.glScissor(0, 0, mWidth, mHeight);
- }
-
- private static float[] toGLMatrix(float v[]) {
- v[15] = v[8]; v[13] = v[5]; v[5] = v[4]; v[4] = v[1];
- v[12] = v[2]; v[1] = v[3]; v[3] = v[6];
- v[2] = v[6] = v[8] = v[9] = 0;
- v[10] = 1;
- return v;
+ boolean intersect = clip.intersect(left, top, right, bottom);
+ if (!intersect) clip.set(0, 0, 0, 0);
+ mGL.glScissor(clip.left, clip.top, clip.width(), clip.height());
+ return intersect;
}
public void drawColor(int x, int y, int width, int height, int color) {
- float alpha = mTransformation.getAlpha();
+ float alpha = mAlpha;
mGLState.setBlendEnabled(!Util.isOpaque(color) || alpha < OPAQUE_ALPHA);
mGLState.setFragmentColor(color, alpha);
fillRect(x, y, width, height);
@@ -419,9 +416,6 @@
private void drawBoundTexture(
BasicTexture texture, int x, int y, int width, int height) {
- Matrix matrix = mTransformation.getMatrix();
- matrix.getValues(mMatrixValues);
-
// Test whether it has been rotated or flipped, if so, glDrawTexiOES
// won't work
if (isMatrixRotatedOrFlipped(mMatrixValues)) {
@@ -429,10 +423,11 @@
(texture.mWidth - 0.5f) / texture.mTextureWidth,
(texture.mHeight - 0.5f) / texture.mTextureHeight,
mUvBuffer, mUvPointer);
- fillRect(x, y, width, height, mMatrixValues);
+ fillRect(x, y, width, height);
} else {
// draw the rect from bottom-left to top-right
- float points[] = mapPoints(matrix, x, y + height, x + width, y);
+ float points[] = mapPoints(
+ mMatrixValues, x, y + height, x + width, y);
x = (int) points[0];
y = (int) points[1];
width = (int) points[2] - x;
@@ -446,7 +441,7 @@
public void drawTexture(
BasicTexture texture, int x, int y, int width, int height) {
- drawTexture(texture, x, y, width, height, mTransformation.getAlpha());
+ drawTexture(texture, x, y, width, height, mAlpha);
}
public void drawTexture(BasicTexture texture,
@@ -462,7 +457,7 @@
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());
+ drawMixed(from, to, ratio, x, y, w, h, mAlpha);
}
private void setTextureColor(float r, float g, float b, float alpha) {
@@ -519,20 +514,24 @@
gl.glActiveTexture(GL11.GL_TEXTURE0);
}
+ // TODO: the code only work for 2D should get fixed for 3D or removed
+ private static final int MSKEW_X = 4;
+ private static final int MSKEW_Y = 1;
+ private static final int MSCALE_X = 0;
+ private static final int MSCALE_Y = 5;
+
private static boolean isMatrixRotatedOrFlipped(float matrix[]) {
- return matrix[Matrix.MSKEW_X] != 0 || matrix[Matrix.MSKEW_Y] != 0
- || matrix[Matrix.MSCALE_X] < 0 || matrix[Matrix.MSCALE_Y] > 0;
+ return matrix[MSKEW_X] != 0 || matrix[MSKEW_Y] != 0
+ || matrix[MSCALE_X] < 0 || matrix[MSCALE_Y] > 0;
}
public void copyTexture2D(
RawTexture texture, int x, int y, int width, int height) {
- Matrix matrix = mTransformation.getMatrix();
- matrix.getValues(mMatrixValues);
if (isMatrixRotatedOrFlipped(mMatrixValues)) {
throw new IllegalArgumentException("cannot support rotated matrix");
}
- float points[] = mapPoints(matrix, x, y + height, x + width, y);
+ float points[] = mapPoints(mMatrixValues, x, y + height, x + width, y);
x = (int) points[0];
y = (int) points[1];
width = (int) points[2] - x;
@@ -696,4 +695,80 @@
mGL.glDeleteTextures(array.size(), array.toArray(null), 0);
}
}
+
+ public int save() {
+ return save(ALL_SAVE_FLAG);
+ }
+
+ public int save(int saveFlags) {
+ ConfigState config = obtainRestoreConfig();
+
+ if ((saveFlags & ALPHA_SAVE_FLAG) != 0) {
+ config.mAlpha = mAlpha;
+ } else {
+ config.mAlpha = -1;
+ }
+
+ if ((saveFlags & CLIP_SAVE_FLAG) != 0) {
+ config.mRect.set(mClipRect);
+ } else {
+ config.mRect.left = Integer.MAX_VALUE;
+ }
+
+ if ((saveFlags & MATRIX_SAVE_FLAG) != 0) {
+ System.arraycopy(mMatrixValues, 0, config.mMatrix, 0, 16);
+ } else {
+ config.mMatrix[0] = Float.NEGATIVE_INFINITY;
+ }
+
+ mRestoreStack.push(config);
+ return mRestoreStack.size() - 1;
+ }
+
+ public void restore() {
+ if (mRestoreStack.isEmpty()) throw new IllegalStateException();
+ ConfigState config = mRestoreStack.pop();
+ config.restore(this);
+ freeRestoreConfig(config);
+ }
+
+ public void restoreToCount(int saveCount) {
+ while (mRestoreStack.size() > saveCount) {
+ restore();
+ }
+ }
+
+ private void freeRestoreConfig(ConfigState action) {
+ action.mNextFree = mRecycledRestoreAction;
+ mRecycledRestoreAction = action;
+ }
+
+ private ConfigState obtainRestoreConfig() {
+ if (mRecycledRestoreAction != null) {
+ ConfigState result = mRecycledRestoreAction;
+ mRecycledRestoreAction = result.mNextFree;
+ return result;
+ }
+ return new ConfigState();
+ }
+
+ private static class ConfigState {
+ float mAlpha;
+ Rect mRect = new Rect();
+ float mMatrix[] = new float[16];
+ ConfigState mNextFree;
+
+ public void restore(GLCanvas canvas) {
+ if (mAlpha >= 0) canvas.setAlpha(mAlpha);
+ if (mRect.left != Integer.MAX_VALUE) {
+ Rect rect = mRect;
+ canvas.mClipRect.set(rect);
+ canvas.mGL.glScissor(
+ rect.left, rect.top, rect.width(), rect.height());
+ }
+ if (mMatrix[0] != Float.NEGATIVE_INFINITY) {
+ System.arraycopy(mMatrix, 0, canvas.mMatrixValues, 0, 16);
+ }
+ }
+ }
}
diff --git a/new3d/src/com/android/gallery3d/ui/GLListView.java b/new3d/src/com/android/gallery3d/ui/GLListView.java
index 5d68b13..b2042c5 100644
--- a/new3d/src/com/android/gallery3d/ui/GLListView.java
+++ b/new3d/src/com/android/gallery3d/ui/GLListView.java
@@ -1,7 +1,6 @@
package com.android.gallery3d.ui;
import static android.view.View.MeasureSpec.makeMeasureSpec;
-
import android.content.Context;
import android.graphics.Rect;
import android.os.Handler;
@@ -9,11 +8,11 @@
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View.MeasureSpec;
-import android.view.animation.AlphaAnimation;
-import android.view.animation.Animation;
-import android.view.animation.Transformation;
import android.widget.Scroller;
+import com.android.gallery3d.anim.AlphaAnimation;
+import com.android.gallery3d.anim.CanvasAnimation;
+
public class GLListView extends GLView {
@SuppressWarnings("unused")
private static final String TAG = "GLListView";
@@ -37,7 +36,7 @@
private boolean mHasMeasured = false;
private boolean mScrollBarVisible = false;
- private Animation mScrollBarAnimation;
+ private CanvasAnimation mScrollBarAnimation;
private OnItemSelectedListener mOnItemSelectedListener;
private final GestureDetector mGestureDetector;
@@ -120,20 +119,20 @@
}
private boolean drawWithAnimation(GLCanvas canvas,
- Texture texture, int x, int y, int w, int h, Animation anim) {
+ Texture texture, int x, int y, int w, int h, CanvasAnimation anim) {
long now = canvas.currentAnimationTimeMillis();
- Transformation temp = canvas.obtainTransformation();
- boolean more = anim.getTransformation(now, temp);
- Transformation transformation = canvas.pushTransform();
- transformation.compose(temp);
+ canvas.save(anim.getCanvasSaveFlags());
+ boolean more = anim.calculate(canvas.currentAnimationTimeMillis());
+ anim.apply(canvas);
texture.draw(canvas, x, y, w, h);
- invalidate();
- canvas.popTransform();
+ canvas.restore();
+ if (more) invalidate();
return more;
}
@Override
protected void render(GLCanvas canvas) {
+ canvas.save(GLCanvas.CLIP_SAVE_FLAG);
canvas.clipRect(0, 0, getWidth(), getHeight());
if (mHighlightIndex != INDEX_NONE) {
GLView view = mModel.getView(mHighlightIndex);
@@ -147,7 +146,7 @@
}
}
super.render(canvas);
- canvas.clearClip();
+ canvas.restore();
if (mScrollBarAnimation != null || mScrollBarVisible) {
int width = mScrollbar.getWidth();
diff --git a/new3d/src/com/android/gallery3d/ui/GLRootView.java b/new3d/src/com/android/gallery3d/ui/GLRootView.java
index a4c215b..659a4be 100644
--- a/new3d/src/com/android/gallery3d/ui/GLRootView.java
+++ b/new3d/src/com/android/gallery3d/ui/GLRootView.java
@@ -24,7 +24,8 @@
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.MotionEvent;
-import android.view.animation.Animation;
+
+import com.android.gallery3d.anim.CanvasAnimation;
import java.util.ArrayList;
import java.util.LinkedList;
@@ -64,7 +65,8 @@
private final GalleryEGLConfigChooser mEglConfigChooser =
new GalleryEGLConfigChooser();
- private final ArrayList<Animation> mAnimations = new ArrayList<Animation>();
+ private final ArrayList<CanvasAnimation> mAnimations =
+ new ArrayList<CanvasAnimation>();
private final LinkedList<OnGLIdleListener> mIdleListeners =
new LinkedList<OnGLIdleListener>();
@@ -91,7 +93,7 @@
return mEglConfigChooser;
}
- void registerLaunchedAnimation(Animation animation) {
+ void registerLaunchedAnimation(CanvasAnimation animation) {
// Register the newly launched animation so that we can set the start
// time more precisely. (Usually, it takes much longer for first
// rendering, so we set the animation start time as the time we
@@ -204,13 +206,19 @@
mRenderRequested = false;
if ((mFlags & FLAG_NEED_LAYOUT) != 0) layoutContentPane();
- mCanvas.clearClip();
mCanvas.clearBuffer();
mCanvas.setCurrentTimeMillis(SystemClock.uptimeMillis());
if (mContentView != null) {
mContentView.render(mCanvas);
}
- mAnimations.clear();
+
+ if (!mAnimations.isEmpty()) {
+ long now = SystemClock.uptimeMillis();
+ for (CanvasAnimation anim : mAnimations) {
+ anim.setStartTime(now);
+ }
+ mAnimations.clear();
+ }
if (!mRenderRequested
&& !mIdleRunner.mActive && !mIdleListeners.isEmpty()) {
diff --git a/new3d/src/com/android/gallery3d/ui/GLView.java b/new3d/src/com/android/gallery3d/ui/GLView.java
index a9e88d1..7b18d2a 100644
--- a/new3d/src/com/android/gallery3d/ui/GLView.java
+++ b/new3d/src/com/android/gallery3d/ui/GLView.java
@@ -16,12 +16,11 @@
package com.android.gallery3d.ui;
-import android.graphics.Matrix;
import android.graphics.Rect;
import android.os.SystemClock;
import android.view.MotionEvent;
-import android.view.animation.Animation;
-import android.view.animation.Transformation;
+
+import com.android.gallery3d.anim.CanvasAnimation;
import java.util.ArrayList;
@@ -45,7 +44,7 @@
private GLView mMotionTarget;
private OnTouchListener mOnTouchListener;
- private Animation mAnimation;
+ private CanvasAnimation mAnimation;
protected int mViewFlags = 0;
@@ -60,13 +59,11 @@
protected int mScrollHeight = 0;
protected int mScrollWidth = 0;
- public void startAnimation(Animation animation) {
+ public void startAnimation(CanvasAnimation animation) {
GLRootView root = getGLRootView();
if (root == null) throw new IllegalStateException();
mAnimation = animation;
- animation.initialize(getWidth(),
- getHeight(), mParent.getWidth(), mParent.getHeight());
mAnimation.start();
root.registerLaunchedAnimation(mAnimation);
invalidate();
@@ -203,25 +200,21 @@
int xoffset = component.mBounds.left - mScrollX;
int yoffset = component.mBounds.top - mScrollY;
- Transformation transform = canvas.getTransformation();
- Matrix matrix = transform.getMatrix();
- matrix.preTranslate(xoffset, yoffset);
+ canvas.translate(xoffset, yoffset, 0);
- Animation anim = component.mAnimation;
+ CanvasAnimation anim = component.mAnimation;
if (anim != null) {
- long now = canvas.currentAnimationTimeMillis();
- Transformation temp = canvas.obtainTransformation();
- if (!anim.getTransformation(now, temp)) {
+ canvas.save(anim.getCanvasSaveFlags());
+ if (anim.calculate(canvas.currentAnimationTimeMillis())) {
+ invalidate();
+ } else {
component.mAnimation = null;
}
- invalidate();
- canvas.pushTransform();
- transform.compose(temp);
- canvas.freeTransformation(temp);
+ anim.apply(canvas);
}
component.render(canvas);
- if (anim != null) canvas.popTransform();
- matrix.preTranslate(-xoffset, -yoffset);
+ if (anim != null) canvas.restore();
+ canvas.translate(-xoffset, -yoffset, 0);
}
protected boolean onTouch(MotionEvent event) {
diff --git a/new3d/src/com/android/gallery3d/ui/IconLabel.java b/new3d/src/com/android/gallery3d/ui/IconLabel.java
index c9c679e..0af1dc7 100644
--- a/new3d/src/com/android/gallery3d/ui/IconLabel.java
+++ b/new3d/src/com/android/gallery3d/ui/IconLabel.java
@@ -4,7 +4,6 @@
import android.content.Context;
import android.graphics.Color;
import android.graphics.Rect;
-import android.view.animation.Transformation;
public class IconLabel extends GLView {
@@ -91,9 +90,8 @@
int xoffset = p.left;
- Transformation trans = canvas.getTransformation();
- float oldAlpha = trans.getAlpha();
- trans.setAlpha(oldAlpha * (mEnabled ? ENABLED_ALPHA : DISABLED_ALPHA));
+ float oldAlpha = canvas.getAlpha();
+ canvas.multiplyAlpha(mEnabled ? ENABLED_ALPHA : DISABLED_ALPHA);
BasicTexture icon = mIcon;
if (icon != null) {
@@ -110,7 +108,7 @@
//TODO: cut the text if it is too long
title.draw(canvas, xoffset, yoffset);
- trans.setAlpha(oldAlpha);
+ canvas.setAlpha(oldAlpha);
}
public void setEnabled(boolean enabled) {
diff --git a/new3d/src/com/android/gallery3d/ui/Pathbar.java b/new3d/src/com/android/gallery3d/ui/Pathbar.java
index ab06601..06cf4e0 100644
--- a/new3d/src/com/android/gallery3d/ui/Pathbar.java
+++ b/new3d/src/com/android/gallery3d/ui/Pathbar.java
@@ -1,10 +1,6 @@
package com.android.gallery3d.ui;
import static com.android.gallery3d.ui.Util.dpToPixel;
-
-import com.android.gallery3d.R;
-import com.android.gallery3d.anim.IntAnimation;
-
import android.content.Context;
import android.graphics.Color;
import android.graphics.Rect;
@@ -12,7 +8,9 @@
import android.os.Message;
import android.util.Log;
import android.view.MotionEvent;
-import android.view.animation.Transformation;
+
+import com.android.gallery3d.R;
+import com.android.gallery3d.anim.IntAnimation;
import java.util.ArrayList;
import java.util.NoSuchElementException;
@@ -245,17 +243,20 @@
background.draw(
canvas, offsetX - p.left, 0, width + p.left + p.right, height);
- int yoffset = (height - icon.getHeight()) / 2;
+ int offsetY = (height - icon.getHeight()) / 2;
offsetX += sHorizontalPadding;
if (icon != mProgressIcon) {
- icon.draw(canvas, offsetX, yoffset);
+ icon.draw(canvas, offsetX, offsetY);
} else {
- Transformation t = canvas.pushTransform();
int degrees = mProgressStep * 360 / PROGRESS_STEP_COUNT;
- t.getMatrix().preRotate(degrees, offsetX
- + icon.getWidth() / 2, yoffset + icon.getHeight() / 2);
- icon.draw(canvas, offsetX, yoffset);
- canvas.popTransform();
+ int pivotX = offsetX + icon.getWidth() / 2;
+ int pivotY = offsetY + icon.getHeight() / 2;
+ canvas.save(GLCanvas.MATRIX_SAVE_FLAG);
+ canvas.translate(pivotX, pivotY, 0);
+ canvas.rotate(degrees, 0, 0, 1);
+ canvas.translate(-pivotX, -pivotY, 0);
+ icon.draw(canvas, offsetX, offsetY);
+ canvas.restore();
if (!mProgressUpdated) {
mProgressUpdated = true;
mHandler.sendEmptyMessageDelayed(UPDATE_PROGRESS, 125);
@@ -263,8 +264,8 @@
}
offsetX += icon.getWidth();
if (title != null) {
- yoffset = (height - title.getHeight()) / 2;
- title.draw(canvas, offsetX, yoffset);
+ offsetY = (height - title.getHeight()) / 2;
+ title.draw(canvas, offsetX, offsetY);
}
mOffsetX += width + p.right;
}
diff --git a/new3d/src/com/android/gallery3d/ui/PopupWindow.java b/new3d/src/com/android/gallery3d/ui/PopupWindow.java
index 7f27b72..5867433 100644
--- a/new3d/src/com/android/gallery3d/ui/PopupWindow.java
+++ b/new3d/src/com/android/gallery3d/ui/PopupWindow.java
@@ -19,11 +19,12 @@
import android.graphics.Rect;
import android.util.Log;
import android.view.View.MeasureSpec;
-import android.view.animation.AlphaAnimation;
-import android.view.animation.Animation;
-import android.view.animation.AnimationSet;
import android.view.animation.OvershootInterpolator;
-import android.view.animation.ScaleAnimation;
+
+import com.android.gallery3d.anim.AlphaAnimation;
+import com.android.gallery3d.anim.AnimationSet;
+import com.android.gallery3d.anim.CanvasAnimation;
+import com.android.gallery3d.anim.ScaleAnimation;
import javax.microedition.khronos.opengles.GL11;
@@ -202,11 +203,10 @@
public void popup() {
setVisibility(GLView.VISIBLE);
- AnimationSet set = new AnimationSet(false);
- Animation scale = new ScaleAnimation(
+ AnimationSet set = new AnimationSet();
+ CanvasAnimation scale = new ScaleAnimation(
0.7f, 1f, 0.7f, 1f, mAnchorPosition, getHeight());
- Animation alpha = new AlphaAnimation(0.5f, 1.0f);
-
+ CanvasAnimation alpha = new AlphaAnimation(0.5f, 1.0f);
set.addAnimation(scale);
set.addAnimation(alpha);
scale.setDuration(150);
@@ -217,7 +217,7 @@
public void popoff() {
setVisibility(GLView.INVISIBLE);
- Animation alpha = new AlphaAnimation(0.7f, 0.0f);
+ AlphaAnimation alpha = new AlphaAnimation(0.7f, 0.0f);
alpha.setDuration(100);
startAnimation(alpha);
}