Created
June 7, 2012 04:28
-
-
Save drewis/2886557 to your computer and use it in GitHub Desktop.
android-4.0.4_r1.2..android-4.0.4_r2.1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[drew@master aosp]$ repo forall -pcv git log --oneline --no-merges android-4.0.4_r1.2..android-4.0.4_r2.1 | |
project build/ | |
1bbaf73 IMM76L | |
b0936b7 IMM76K | |
396c8cf IMM76J | |
project device/moto/stingray/ | |
ca7247e Update for cmda radio 3.1A.65P | |
project packages/apps/Gallery2/ | |
fd69559 Patch 2 for MR1. | |
1cdcda4 Patch for MR1. | |
[drew@master aosp]$ repo forall -pcv git log -p --oneline --no-merges android-4.0.4_r1.2..android-4.0.4_r2.1 | |
project build/ | |
1bbaf73 IMM76L | |
diff --git a/core/build_id.mk b/core/build_id.mk | |
index 77e9923..8f1b5ba 100644 | |
--- a/core/build_id.mk | |
+++ b/core/build_id.mk | |
@@ -19,4 +19,4 @@ | |
# (like "CRB01"). It must be a single word, and is | |
# capitalized by convention. | |
-export BUILD_ID=IMM76K | |
+export BUILD_ID=IMM76L | |
b0936b7 IMM76K | |
diff --git a/core/build_id.mk b/core/build_id.mk | |
index c7f7c2b..77e9923 100644 | |
--- a/core/build_id.mk | |
+++ b/core/build_id.mk | |
@@ -19,4 +19,4 @@ | |
# (like "CRB01"). It must be a single word, and is | |
# capitalized by convention. | |
-export BUILD_ID=IMM76J | |
+export BUILD_ID=IMM76K | |
396c8cf IMM76J | |
diff --git a/core/build_id.mk b/core/build_id.mk | |
index 9d1709c..c7f7c2b 100644 | |
--- a/core/build_id.mk | |
+++ b/core/build_id.mk | |
@@ -19,4 +19,4 @@ | |
# (like "CRB01"). It must be a single word, and is | |
# capitalized by convention. | |
-export BUILD_ID=IMM76I | |
+export BUILD_ID=IMM76J | |
project device/moto/stingray/ | |
ca7247e Update for cmda radio 3.1A.65P | |
diff --git a/board-info.txt b/board-info.txt | |
index d69c0e0..0095444 100644 | |
--- a/board-info.txt | |
+++ b/board-info.txt | |
@@ -1,4 +1,4 @@ | |
require product=stingray|xoom-cdma|xoom-cdma-lte | |
require version-bootloader=1050 | |
-require version-baseband=CDMA_N_03.1A.64PS | |
+require version-baseband=CDMA_N_03.1A.65PS | |
require-for-product:xoom-cdma-lte version-baseband-2=LTEDC_U_07.1F.00 | |
project external/android-clat/ | |
project external/ant-glob/ | |
project external/apache-qp/ | |
project external/checkpolicy/ | |
project external/eclipse-basebuilder/ | |
project external/eclipse-windowbuilder/ | |
project external/libmtp/ | |
project external/libselinux/ | |
project external/libsepol/ | |
project external/libusb/ | |
project external/libusb-compat/ | |
project external/sepolicy/ | |
project frameworks/opt/carddav/ | |
project hardware/ti/wlan/ | |
project hardware/ti/wpan/ | |
project packages/apps/Gallery2/ | |
fd69559 Patch 2 for MR1. | |
diff --git a/src/com/android/gallery3d/ui/PhotoView.java b/src/com/android/gallery3d/ui/PhotoView.java | |
index aeed577..217a290 100644 | |
--- a/src/com/android/gallery3d/ui/PhotoView.java | |
+++ b/src/com/android/gallery3d/ui/PhotoView.java | |
@@ -43,6 +43,7 @@ public class PhotoView extends GLView { | |
private static final int MSG_TRANSITION_COMPLETE = 1; | |
private static final int MSG_SHOW_LOADING = 2; | |
+ private static final int MSG_CANCEL_EXTRA_SCALING = 3; | |
private static final long DELAY_SHOW_LOADING = 250; // 250ms; | |
@@ -111,6 +112,7 @@ public class PhotoView extends GLView { | |
private Path mOpenedItemPath; | |
private GalleryActivity mActivity; | |
private Point mImageCenter = new Point(); | |
+ private boolean mCancelExtraScalingPending; | |
public PhotoView(GalleryActivity activity) { | |
mActivity = activity; | |
@@ -146,6 +148,12 @@ public class PhotoView extends GLView { | |
} | |
break; | |
} | |
+ case MSG_CANCEL_EXTRA_SCALING: { | |
+ cancelScaleGesture(); | |
+ mPositionController.setExtraScalingRange(false); | |
+ mCancelExtraScalingPending = false; | |
+ break; | |
+ } | |
default: throw new AssertionError(message.what); | |
} | |
} | |
@@ -585,8 +593,22 @@ public class PhotoView extends GLView { | |
float scale = detector.getScaleFactor(); | |
if (Float.isNaN(scale) || Float.isInfinite(scale) | |
|| mTransitionMode != TRANS_NONE) return true; | |
- mPositionController.scaleBy(scale, | |
+ boolean outOfRange = mPositionController.scaleBy(scale, | |
detector.getFocusX(), detector.getFocusY()); | |
+ if (outOfRange) { | |
+ if (!mCancelExtraScalingPending) { | |
+ mHandler.sendEmptyMessageDelayed( | |
+ MSG_CANCEL_EXTRA_SCALING, 700); | |
+ mPositionController.setExtraScalingRange(true); | |
+ mCancelExtraScalingPending = true; | |
+ } | |
+ } else { | |
+ if (mCancelExtraScalingPending) { | |
+ mHandler.removeMessages(MSG_CANCEL_EXTRA_SCALING); | |
+ mPositionController.setExtraScalingRange(false); | |
+ mCancelExtraScalingPending = false; | |
+ } | |
+ } | |
return true; | |
} | |
@@ -605,6 +627,14 @@ public class PhotoView extends GLView { | |
} | |
} | |
+ private void cancelScaleGesture() { | |
+ long now = SystemClock.uptimeMillis(); | |
+ MotionEvent cancelEvent = MotionEvent.obtain( | |
+ now, now, MotionEvent.ACTION_CANCEL, 0, 0, 0); | |
+ mScaleDetector.onTouchEvent(cancelEvent); | |
+ cancelEvent.recycle(); | |
+ } | |
+ | |
public boolean jumpTo(int index) { | |
if (mTransitionMode != TRANS_NONE) return false; | |
mModel.jumpTo(index); | |
diff --git a/src/com/android/gallery3d/ui/PositionController.java b/src/com/android/gallery3d/ui/PositionController.java | |
index b4dac97..2068446 100644 | |
--- a/src/com/android/gallery3d/ui/PositionController.java | |
+++ b/src/com/android/gallery3d/ui/PositionController.java | |
@@ -64,6 +64,9 @@ class PositionController { | |
private static final float SCALE_LIMIT = 4; | |
private static final int sHorizontalSlack = GalleryUtils.dpToPixel(12); | |
+ private static final float SCALE_MIN_EXTRA = 0.6f; | |
+ private static final float SCALE_MAX_EXTRA = 1.4f; | |
+ | |
private PhotoView mViewer; | |
private EdgeView mEdgeView; | |
private int mImageW, mImageH; | |
@@ -83,6 +86,7 @@ class PositionController { | |
// The minimum and maximum scale we allow. | |
private float mScaleMin, mScaleMax = SCALE_LIMIT; | |
+ private boolean mExtraScalingRange = false; | |
// This is used by the fling animation | |
private FlingScroller mScroller; | |
@@ -268,7 +272,8 @@ class PositionController { | |
(focusY - mViewH / 2f) / mCurrentScale); | |
} | |
- public void scaleBy(float s, float focusX, float focusY) { | |
+ // Returns true if the result scale is outside the stable range. | |
+ public boolean scaleBy(float s, float focusX, float focusY) { | |
// We want to keep the focus point (on the bitmap) the same as when | |
// we begin the scale guesture, that is, | |
@@ -280,6 +285,7 @@ class PositionController { | |
int y = Math.round(mFocusBitmapY - (focusY - mViewH / 2f) / s); | |
startAnimation(x, y, s, ANIM_KIND_SCALE); | |
+ return (s < mScaleMin || s > mScaleMax); | |
} | |
public void endScale() { | |
@@ -287,6 +293,13 @@ class PositionController { | |
startSnapbackIfNeeded(); | |
} | |
+ public void setExtraScalingRange(boolean enabled) { | |
+ mExtraScalingRange = enabled; | |
+ if (!enabled) { | |
+ startSnapbackIfNeeded(); | |
+ } | |
+ } | |
+ | |
public float getCurrentScale() { | |
return mCurrentScale; | |
} | |
@@ -400,7 +413,8 @@ class PositionController { | |
mToX = targetX; | |
mToY = targetY; | |
- mToScale = Utils.clamp(scale, 0.6f * mScaleMin, 1.4f * mScaleMax); | |
+ mToScale = Utils.clamp(scale, SCALE_MIN_EXTRA * mScaleMin, | |
+ SCALE_MAX_EXTRA * mScaleMax); | |
// If the scaled height is smaller than the view height, | |
// force it to be in the center. | |
@@ -540,9 +554,14 @@ class PositionController { | |
boolean needAnimation = false; | |
float scale = mCurrentScale; | |
- if (mCurrentScale < mScaleMin || mCurrentScale > mScaleMax) { | |
+ float scaleMin = mExtraScalingRange ? | |
+ mScaleMin * SCALE_MIN_EXTRA : mScaleMin; | |
+ float scaleMax = mExtraScalingRange ? | |
+ mScaleMax * SCALE_MAX_EXTRA : mScaleMax; | |
+ | |
+ if (mCurrentScale < scaleMin || mCurrentScale > scaleMax) { | |
needAnimation = true; | |
- scale = Utils.clamp(mCurrentScale, mScaleMin, mScaleMax); | |
+ scale = Utils.clamp(mCurrentScale, scaleMin, scaleMax); | |
} | |
calculateStableBound(scale, sHorizontalSlack); | |
1cdcda4 Patch for MR1. | |
diff --git a/src/com/android/gallery3d/app/PhotoDataAdapter.java b/src/com/android/gallery3d/app/PhotoDataAdapter.java | |
index 9b1c8c4..d7d1168 100644 | |
--- a/src/com/android/gallery3d/app/PhotoDataAdapter.java | |
+++ b/src/com/android/gallery3d/app/PhotoDataAdapter.java | |
@@ -365,8 +365,9 @@ public class PhotoDataAdapter implements PhotoPage.Model { | |
return mTileProvider.getLevelCount(); | |
} | |
- public Bitmap getTile(int level, int x, int y, int tileSize) { | |
- return mTileProvider.getTile(level, x, y, tileSize); | |
+ public Bitmap getTile(int level, int x, int y, int tileSize, | |
+ int borderSize) { | |
+ return mTileProvider.getTile(level, x, y, tileSize, borderSize); | |
} | |
public boolean isFailedToLoad() { | |
diff --git a/src/com/android/gallery3d/ui/BitmapTileProvider.java b/src/com/android/gallery3d/ui/BitmapTileProvider.java | |
index a47337f..3d4d4dc 100644 | |
--- a/src/com/android/gallery3d/ui/BitmapTileProvider.java | |
+++ b/src/com/android/gallery3d/ui/BitmapTileProvider.java | |
@@ -65,11 +65,28 @@ public class BitmapTileProvider implements TileImageView.Model { | |
return mMipmaps.length; | |
} | |
- public Bitmap getTile(int level, int x, int y, int tileSize) { | |
- Bitmap result = Bitmap.createBitmap(tileSize, tileSize, mConfig); | |
+ public Bitmap getTile(int level, int x, int y, int tileSize, | |
+ int borderSize) { | |
+ x >>= level; | |
+ y >>= level; | |
+ int size = tileSize + 2 * borderSize; | |
+ Bitmap result = Bitmap.createBitmap(size, size, mConfig); | |
+ Bitmap mipmap = mMipmaps[level]; | |
Canvas canvas = new Canvas(result); | |
- canvas.drawBitmap(mMipmaps[level], -(x >> level), -(y >> level), null); | |
- return result; | |
+ int offsetX = -x + borderSize; | |
+ int offsetY = -y + borderSize; | |
+ canvas.drawBitmap(mipmap, offsetX, offsetY, null); | |
+ | |
+ // If the valid region (covered by mipmap or border) is smaller than the | |
+ // result bitmap, subset it. | |
+ int endX = offsetX + mipmap.getWidth() + borderSize; | |
+ int endY = offsetY + mipmap.getHeight() + borderSize; | |
+ if (endX < size || endY < size) { | |
+ return Bitmap.createBitmap(result, 0, 0, Math.min(size, endX), | |
+ Math.min(size, endY)); | |
+ } else { | |
+ return result; | |
+ } | |
} | |
public void recycle() { | |
diff --git a/src/com/android/gallery3d/ui/PhotoView.java b/src/com/android/gallery3d/ui/PhotoView.java | |
index 5062c0e..aeed577 100644 | |
--- a/src/com/android/gallery3d/ui/PhotoView.java | |
+++ b/src/com/android/gallery3d/ui/PhotoView.java | |
@@ -25,12 +25,15 @@ import com.android.gallery3d.ui.PositionRepository.Position; | |
import android.content.Context; | |
import android.graphics.Bitmap; | |
import android.graphics.Color; | |
+import android.graphics.Point; | |
+import android.graphics.Rect; | |
import android.graphics.RectF; | |
import android.os.Message; | |
import android.os.SystemClock; | |
import android.view.GestureDetector; | |
import android.view.MotionEvent; | |
import android.view.ScaleGestureDetector; | |
+import android.view.animation.AccelerateInterpolator; | |
public class PhotoView extends GLView { | |
@SuppressWarnings("unused") | |
@@ -64,6 +67,14 @@ public class PhotoView extends GLView { | |
private static final float SWIPE_THRESHOLD = 300f; | |
private static final float DEFAULT_TEXT_SIZE = 20; | |
+ private static float TRANSITION_SCALE_FACTOR = 0.74f; | |
+ | |
+ // Used to calculate the scaling factor for the fading animation. | |
+ private ZInterpolator mScaleInterpolator = new ZInterpolator(0.5f); | |
+ | |
+ // Used to calculate the alpha factor for the fading animation. | |
+ private AccelerateInterpolator mAlphaInterpolator = | |
+ new AccelerateInterpolator(0.9f); | |
public interface PhotoTapListener { | |
public void onSingleTapUp(int x, int y); | |
@@ -99,6 +110,7 @@ public class PhotoView extends GLView { | |
private Path mOpenedItemPath; | |
private GalleryActivity mActivity; | |
+ private Point mImageCenter = new Point(); | |
public PhotoView(GalleryActivity activity) { | |
mActivity = activity; | |
@@ -164,24 +176,49 @@ public class PhotoView extends GLView { | |
mPhotoTapListener = listener; | |
} | |
- private boolean setTileViewPosition(int centerX, int centerY, float scale) { | |
+ private void setTileViewPosition(int centerX, int centerY, float scale) { | |
+ TileImageView t = mTileView; | |
+ | |
+ // Calculate the move-out progress value. | |
+ RectF bounds = mPositionController.getImageBounds(); | |
+ int left = Math.round(bounds.left); | |
+ int right = Math.round(bounds.right); | |
+ int width = getWidth(); | |
+ float progress = calculateMoveOutProgress(left, right, width); | |
+ progress = Utils.clamp(progress, -1f, 1f); | |
+ | |
+ // We only want to apply the fading animation if the scrolling movement | |
+ // is to the right. | |
+ if (progress < 0) { | |
+ if (right - left < width) { | |
+ // If the picture is narrower than the view, keep it at the center | |
+ // of the view. | |
+ centerX = mPositionController.getImageWidth() / 2; | |
+ } else { | |
+ // If the picture is wider than the view (it's zoomed-in), keep | |
+ // the left edge of the object align the the left edge of the view. | |
+ centerX = Math.round(width / 2f / scale); | |
+ } | |
+ scale *= getScrollScale(progress); | |
+ t.setAlpha(getScrollAlpha(progress)); | |
+ } | |
+ | |
+ // set the position of the tile view | |
int inverseX = mPositionController.getImageWidth() - centerX; | |
int inverseY = mPositionController.getImageHeight() - centerY; | |
- TileImageView t = mTileView; | |
int rotation = mImageRotation; | |
switch (rotation) { | |
- case 0: return t.setPosition(centerX, centerY, scale, 0); | |
- case 90: return t.setPosition(centerY, inverseX, scale, 90); | |
- case 180: return t.setPosition(inverseX, inverseY, scale, 180); | |
- case 270: return t.setPosition(inverseY, centerX, scale, 270); | |
+ case 0: t.setPosition(centerX, centerY, scale, 0); break; | |
+ case 90: t.setPosition(centerY, inverseX, scale, 90); break; | |
+ case 180: t.setPosition(inverseX, inverseY, scale, 180); break; | |
+ case 270: t.setPosition(inverseY, centerX, scale, 270); break; | |
default: throw new IllegalArgumentException(String.valueOf(rotation)); | |
} | |
} | |
public void setPosition(int centerX, int centerY, float scale) { | |
- if (setTileViewPosition(centerX, centerY, scale)) { | |
- layoutScreenNails(); | |
- } | |
+ setTileViewPosition(centerX, centerY, scale); | |
+ layoutScreenNails(); | |
} | |
private void updateScreenNailEntry(int which, ImageData data) { | |
@@ -217,6 +254,7 @@ public class PhotoView extends GLView { | |
case 0: { | |
// mImageWidth and mImageHeight will get updated | |
mTileView.notifyModelInvalidated(); | |
+ mTileView.setAlpha(1.0f); | |
mImageRotation = mModel.getImageRotation(); | |
if (((mImageRotation / 90) & 1) == 0) { | |
@@ -264,6 +302,7 @@ public class PhotoView extends GLView { | |
if (mModel == null) { | |
mTileView.notifyModelInvalidated(); | |
+ mTileView.setAlpha(1.0f); | |
mImageRotation = 0; | |
mPositionController.setImageSize(0, 0); | |
updateLoadingState(); | |
@@ -341,23 +380,40 @@ public class PhotoView extends GLView { | |
@Override | |
protected void render(GLCanvas canvas) { | |
PositionController p = mPositionController; | |
+ boolean drawScreenNail = (mTransitionMode != TRANS_SLIDE_IN_LEFT | |
+ && mTransitionMode != TRANS_SLIDE_IN_RIGHT | |
+ && mTransitionMode != TRANS_OPEN_ANIMATION); | |
+ | |
+ // Draw the next photo | |
+ if (drawScreenNail) { | |
+ ScreenNailEntry nextNail = mScreenNails[ENTRY_NEXT]; | |
+ if (nextNail.mVisible) nextNail.draw(canvas, true); | |
+ } | |
// Draw the current photo | |
if (mLoadingState == LOADING_COMPLETE) { | |
super.render(canvas); | |
} | |
- // Draw the previous and the next photo | |
- if (mTransitionMode != TRANS_SLIDE_IN_LEFT | |
- && mTransitionMode != TRANS_SLIDE_IN_RIGHT | |
- && mTransitionMode != TRANS_OPEN_ANIMATION) { | |
- ScreenNailEntry prevNail = mScreenNails[ENTRY_PREVIOUS]; | |
- ScreenNailEntry nextNail = mScreenNails[ENTRY_NEXT]; | |
+ // If the photo is loaded, draw the message/icon at the center of it, | |
+ // otherwise draw the message/icon at the center of the view. | |
+ if (mLoadingState == LOADING_COMPLETE) { | |
+ mTileView.getImageCenter(mImageCenter); | |
+ renderMessage(canvas, mImageCenter.x, mImageCenter.y); | |
+ } else { | |
+ renderMessage(canvas, getWidth() / 2, getHeight() / 2); | |
+ } | |
- if (prevNail.mVisible) prevNail.draw(canvas); | |
- if (nextNail.mVisible) nextNail.draw(canvas); | |
+ // Draw the previous photo | |
+ if (drawScreenNail) { | |
+ ScreenNailEntry prevNail = mScreenNails[ENTRY_PREVIOUS]; | |
+ if (prevNail.mVisible) prevNail.draw(canvas, false); | |
} | |
+ if (mPositionController.advanceAnimation()) invalidate(); | |
+ } | |
+ | |
+ private void renderMessage(GLCanvas canvas, int x, int y) { | |
// Draw the progress spinner and the text below it | |
// | |
// (x, y) is where we put the center of the spinner. | |
@@ -366,8 +422,6 @@ public class PhotoView extends GLView { | |
// play icon is shown instead of the spinner. | |
int w = getWidth(); | |
int h = getHeight(); | |
- int x = Math.round(mPositionController.getImageBounds().centerX()); | |
- int y = h / 2; | |
int s = Math.min(getWidth(), getHeight()) / 6; | |
if (mLoadingState == LOADING_TIMEOUT) { | |
@@ -387,8 +441,6 @@ public class PhotoView extends GLView { | |
&& mLoadingState != LOADING_TIMEOUT) { | |
mVideoPlayIcon.draw(canvas, x - s / 2, y - s / 2, s, s); | |
} | |
- | |
- if (mPositionController.advanceAnimation()) invalidate(); | |
} | |
private void stopCurrentSwipingIfNeeded() { | |
@@ -731,23 +783,107 @@ public class PhotoView extends GLView { | |
return mEnabled; | |
} | |
- public void draw(GLCanvas canvas) { | |
- int x = mOffsetX; | |
- int y = getHeight() / 2; | |
+ public void draw(GLCanvas canvas, boolean applyFadingAnimation) { | |
+ if (mTexture == null) return; | |
- if (mTexture != null) { | |
- if (mRotation != 0) { | |
- canvas.save(GLCanvas.SAVE_FLAG_MATRIX); | |
- canvas.translate(x, y, 0); | |
- canvas.rotate(mRotation, 0, 0, 1); //mRotation | |
- canvas.translate(-x, -y, 0); | |
- } | |
- mTexture.draw(canvas, x - mDrawWidth / 2, y - mDrawHeight / 2, | |
- mDrawWidth, mDrawHeight); | |
- if (mRotation != 0) { | |
- canvas.restore(); | |
- } | |
+ int w = getWidth(); | |
+ int x = applyFadingAnimation ? w / 2 : mOffsetX; | |
+ int y = getHeight() / 2; | |
+ int flags = GLCanvas.SAVE_FLAG_MATRIX; | |
+ | |
+ if (applyFadingAnimation) flags |= GLCanvas.SAVE_FLAG_ALPHA; | |
+ canvas.save(flags); | |
+ canvas.translate(x, y, 0); | |
+ if (applyFadingAnimation) { | |
+ float progress = (float) (x - mOffsetX) / w; | |
+ float alpha = getScrollAlpha(progress); | |
+ float scale = getScrollScale(progress); | |
+ canvas.multiplyAlpha(alpha); | |
+ canvas.scale(scale, scale, 1); | |
} | |
+ if (mRotation != 0) { | |
+ canvas.rotate(mRotation, 0, 0, 1); | |
+ } | |
+ canvas.translate(-x, -y, 0); | |
+ mTexture.draw(canvas, x - mDrawWidth / 2, y - mDrawHeight / 2, | |
+ mDrawWidth, mDrawHeight); | |
+ canvas.restore(); | |
+ } | |
+ } | |
+ | |
+ // Returns the scrolling progress value for an object moving out of a | |
+ // view. The progress value measures how much the object has moving out of | |
+ // the view. The object currently displays in [left, right), and the view is | |
+ // at [0, viewWidth]. | |
+ // | |
+ // The returned value is negative when the object is moving right, and | |
+ // positive when the object is moving left. The value goes to -1 or 1 when | |
+ // the object just moves out of the view completely. The value is 0 if the | |
+ // object currently fills the view. | |
+ private static float calculateMoveOutProgress(int left, int right, | |
+ int viewWidth) { | |
+ // w = object width | |
+ // viewWidth = view width | |
+ int w = right - left; | |
+ | |
+ // If the object width is smaller than the view width, | |
+ // |....view....| | |
+ // |<-->| progress = -1 when left = viewWidth | |
+ // |<-->| progress = 1 when left = -w | |
+ // So progress = 1 - 2 * (left + w) / (viewWidth + w) | |
+ if (w < viewWidth) { | |
+ return 1f - 2f * (left + w) / (viewWidth + w); | |
+ } | |
+ | |
+ // If the object width is larger than the view width, | |
+ // |..view..| | |
+ // |<--------->| progress = -1 when left = viewWidth | |
+ // |<--------->| progress = 0 between left = 0 | |
+ // |<--------->| and right = viewWidth | |
+ // |<--------->| progress = 1 when right = 0 | |
+ if (left > 0) { | |
+ return -left / (float) viewWidth; | |
+ } | |
+ | |
+ if (right < viewWidth) { | |
+ return (viewWidth - right) / (float) viewWidth; | |
+ } | |
+ | |
+ return 0; | |
+ } | |
+ | |
+ // Maps a scrolling progress value to the alpha factor in the fading | |
+ // animation. | |
+ private float getScrollAlpha(float scrollProgress) { | |
+ return scrollProgress < 0 ? mAlphaInterpolator.getInterpolation( | |
+ 1 - Math.abs(scrollProgress)) : 1.0f; | |
+ } | |
+ | |
+ // Maps a scrolling progress value to the scaling factor in the fading | |
+ // animation. | |
+ private float getScrollScale(float scrollProgress) { | |
+ float interpolatedProgress = mScaleInterpolator.getInterpolation( | |
+ Math.abs(scrollProgress)); | |
+ float scale = (1 - interpolatedProgress) + | |
+ interpolatedProgress * TRANSITION_SCALE_FACTOR; | |
+ return scale; | |
+ } | |
+ | |
+ | |
+ // This interpolator emulates the rate at which the perceived scale of an | |
+ // object changes as its distance from a camera increases. When this | |
+ // interpolator is applied to a scale animation on a view, it evokes the | |
+ // sense that the object is shrinking due to moving away from the camera. | |
+ private static class ZInterpolator { | |
+ private float focalLength; | |
+ | |
+ public ZInterpolator(float foc) { | |
+ focalLength = foc; | |
+ } | |
+ | |
+ public float getInterpolation(float input) { | |
+ return (1.0f - focalLength / (focalLength + input)) / | |
+ (1.0f - focalLength / (focalLength + 1.0f)); | |
} | |
} | |
diff --git a/src/com/android/gallery3d/ui/TileImageView.java b/src/com/android/gallery3d/ui/TileImageView.java | |
index 980f7b2..5c9f3f4 100644 | |
--- a/src/com/android/gallery3d/ui/TileImageView.java | |
+++ b/src/com/android/gallery3d/ui/TileImageView.java | |
@@ -17,6 +17,7 @@ | |
package com.android.gallery3d.ui; | |
import android.graphics.Bitmap; | |
+import android.graphics.Point; | |
import android.graphics.Rect; | |
import android.graphics.RectF; | |
@@ -108,6 +109,7 @@ public class TileImageView extends GLView { | |
protected int mCenterY; | |
protected float mScale; | |
protected int mRotation; | |
+ protected float mAlpha = 1.0f; | |
// Temp variables to avoid memory allocation | |
private final Rect mTileRange = new Rect(); | |
@@ -125,8 +127,20 @@ public class TileImageView extends GLView { | |
public int getImageWidth(); | |
public int getImageHeight(); | |
- // The method would be called in another thread | |
- public Bitmap getTile(int level, int x, int y, int tileSize); | |
+ // The tile returned by this method can be specified this way: Assuming | |
+ // the image size is (width, height), first take the intersection of (0, | |
+ // 0) - (width, height) and (x, y) - (x + tileSize, y + tileSize). Then | |
+ // extend this intersection region by borderSize pixels on each side. If | |
+ // in extending the region, we found some part of the region are outside | |
+ // the image, those pixels are filled with black. | |
+ // | |
+ // If level > 0, it does the same operation on a down-scaled version of | |
+ // the original image (down-scaled by a factor of 2^level), but (x, y) | |
+ // still refers to the coordinate on the original image. | |
+ // | |
+ // The method would be called in another thread. | |
+ public Bitmap getTile(int level, int x, int y, int tileSize, | |
+ int borderSize); | |
public boolean isFailedToLoad(); | |
} | |
@@ -308,6 +322,30 @@ public class TileImageView extends GLView { | |
out.set(left, top, right, bottom); | |
} | |
+ // Calculate where the center of the image is, in the view coordinates. | |
+ public void getImageCenter(Point center) { | |
+ // The width and height of this view. | |
+ int viewW = getWidth(); | |
+ int viewH = getHeight(); | |
+ | |
+ // The distance between the center of the view to the center of the | |
+ // bitmap, in bitmap units. (mCenterX and mCenterY are the bitmap | |
+ // coordinates correspond to the center of view) | |
+ int distW, distH; | |
+ if (mRotation % 180 == 0) { | |
+ distW = mImageWidth / 2 - mCenterX; | |
+ distH = mImageHeight / 2 - mCenterY; | |
+ } else { | |
+ distW = mImageHeight / 2 - mCenterY; | |
+ distH = mImageWidth / 2 - mCenterX; | |
+ } | |
+ | |
+ // Convert to view coordinates. mScale translates from bitmap units to | |
+ // view units. | |
+ center.x = Math.round(viewW / 2f + distW * mScale); | |
+ center.y = Math.round(viewH / 2f + distH * mScale); | |
+ } | |
+ | |
public boolean setPosition(int centerX, int centerY, float scale, int rotation) { | |
if (mCenterX == centerX | |
&& mCenterY == centerY && mScale == scale) return false; | |
@@ -320,6 +358,13 @@ public class TileImageView extends GLView { | |
return true; | |
} | |
+ public boolean setAlpha(float alpha) { | |
+ if (mAlpha == alpha) return false; | |
+ mAlpha = alpha; | |
+ invalidate(); | |
+ return true; | |
+ } | |
+ | |
public void freeTextures() { | |
mIsTextureFreed = true; | |
@@ -365,13 +410,19 @@ public class TileImageView extends GLView { | |
int level = mLevel; | |
int rotation = mRotation; | |
- | |
- if (rotation != 0) { | |
- canvas.save(GLCanvas.SAVE_FLAG_MATRIX); | |
- int centerX = getWidth() / 2, centerY = getHeight() / 2; | |
- canvas.translate(centerX, centerY, 0); | |
- canvas.rotate(rotation, 0, 0, 1); | |
- canvas.translate(-centerX, -centerY, 0); | |
+ int flags = 0; | |
+ if (rotation != 0) flags |= GLCanvas.SAVE_FLAG_MATRIX; | |
+ if (mAlpha != 1.0f) flags |= GLCanvas.SAVE_FLAG_ALPHA; | |
+ | |
+ if (flags != 0) { | |
+ canvas.save(flags); | |
+ if (rotation != 0) { | |
+ int centerX = getWidth() / 2, centerY = getHeight() / 2; | |
+ canvas.translate(centerX, centerY, 0); | |
+ canvas.rotate(rotation, 0, 0, 1); | |
+ canvas.translate(-centerX, -centerY, 0); | |
+ } | |
+ if (mAlpha != 1.0f) canvas.multiplyAlpha(mAlpha); | |
} | |
try { | |
if (level != mLevelCount) { | |
@@ -392,7 +443,7 @@ public class TileImageView extends GLView { | |
Math.round(mImageHeight * mScale)); | |
} | |
} finally { | |
- if (rotation != 0) canvas.restore(); | |
+ if (flags != 0) canvas.restore(); | |
} | |
if (mRenderComplete) { | |
@@ -601,11 +652,9 @@ public class TileImageView extends GLView { | |
boolean decode() { | |
// Get a tile from the original image. The tile is down-scaled | |
// by (1 << mTilelevel) from a region in the original image. | |
- int tileLength = (TILE_SIZE + 2 * TILE_BORDER); | |
- int borderLength = TILE_BORDER << mTileLevel; | |
try { | |
mDecodedTile = DecodeUtils.ensureGLCompatibleBitmap(mModel.getTile( | |
- mTileLevel, mX - borderLength, mY - borderLength, tileLength)); | |
+ mTileLevel, mX, mY, TILE_SIZE, TILE_BORDER)); | |
} catch (Throwable t) { | |
Log.w(TAG, "fail to decode tile", t); | |
} | |
@@ -621,6 +670,20 @@ public class TileImageView extends GLView { | |
return bitmap; | |
} | |
+ // We override getTextureWidth() and getTextureHeight() here, so the | |
+ // texture can be re-used for different tiles regardless of the actual | |
+ // size of the tile (which may be small because it is a tile at the | |
+ // boundary). | |
+ @Override | |
+ public int getTextureWidth() { | |
+ return TILE_SIZE + TILE_BORDER * 2; | |
+ } | |
+ | |
+ @Override | |
+ public int getTextureHeight() { | |
+ return TILE_SIZE + TILE_BORDER * 2; | |
+ } | |
+ | |
public void update(int x, int y, int level) { | |
mX = x; | |
mY = y; | |
diff --git a/src/com/android/gallery3d/ui/TileImageViewAdapter.java b/src/com/android/gallery3d/ui/TileImageViewAdapter.java | |
index 63bb0b2..be255d2 100644 | |
--- a/src/com/android/gallery3d/ui/TileImageViewAdapter.java | |
+++ b/src/com/android/gallery3d/ui/TileImageViewAdapter.java | |
@@ -34,9 +34,6 @@ public class TileImageViewAdapter implements TileImageView.Model { | |
protected int mLevelCount; | |
protected boolean mFailedToLoad; | |
- private final Rect mIntersectRect = new Rect(); | |
- private final Rect mRegionRect = new Rect(); | |
- | |
public TileImageViewAdapter() { | |
} | |
@@ -80,16 +77,24 @@ public class TileImageViewAdapter implements TileImageView.Model { | |
} | |
@Override | |
- public synchronized Bitmap getTile(int level, int x, int y, int length) { | |
+ public synchronized Bitmap getTile(int level, int x, int y, int tileSize, | |
+ int borderSize) { | |
if (mRegionDecoder == null) return null; | |
- Rect region = mRegionRect; | |
- Rect intersectRect = mIntersectRect; | |
- region.set(x, y, x + (length << level), y + (length << level)); | |
- intersectRect.set(0, 0, mImageWidth, mImageHeight); | |
+ // wantRegion is the rectangle on the original image we want. askRegion | |
+ // is the rectangle on the original image that we will ask from | |
+ // mRegionDecoder. Both are in the coordinates of the original image, | |
+ // not the coordinates of the scaled-down images. | |
+ Rect wantRegion = new Rect(); | |
+ Rect askRegion = new Rect(); | |
+ | |
+ int b = borderSize << level; | |
+ wantRegion.set(x - b, y - b, x + (tileSize << level) + b, | |
+ y + (tileSize << level) + b); | |
- // Get the intersected rect of the requested region and the image. | |
- Utils.assertTrue(intersectRect.intersect(region)); | |
+ // askRegion is the intersection of wantRegion and the original image. | |
+ askRegion.set(0, 0, mImageWidth, mImageHeight); | |
+ Utils.assertTrue(askRegion.intersect(wantRegion)); | |
BitmapFactory.Options options = new BitmapFactory.Options(); | |
options.inPreferredConfig = Config.ARGB_8888; | |
@@ -100,25 +105,37 @@ public class TileImageViewAdapter implements TileImageView.Model { | |
// In CropImage, we may call the decodeRegion() concurrently. | |
synchronized (mRegionDecoder) { | |
- bitmap = mRegionDecoder.decodeRegion(intersectRect, options); | |
+ bitmap = mRegionDecoder.decodeRegion(askRegion, options); | |
} | |
- // The returned region may not match with the targetLength. | |
- // If so, we fill black pixels on it. | |
- if (intersectRect.equals(region)) return bitmap; | |
- | |
if (bitmap == null) { | |
Log.w(TAG, "fail in decoding region"); | |
return null; | |
} | |
- Bitmap tile = Bitmap.createBitmap(length, length, Config.ARGB_8888); | |
- Canvas canvas = new Canvas(tile); | |
- canvas.drawBitmap(bitmap, | |
- (intersectRect.left - region.left) >> level, | |
- (intersectRect.top - region.top) >> level, null); | |
+ if (wantRegion.equals(askRegion)) return bitmap; | |
+ | |
+ // Now the wantRegion does not match the askRegion. This means we are at | |
+ // a boundary tile, and we need to add paddings. Create a new Bitmap | |
+ // and copy over. | |
+ int size = tileSize + 2 * borderSize; | |
+ Bitmap result = Bitmap.createBitmap(size, size, Config.ARGB_8888); | |
+ Canvas canvas = new Canvas(result); | |
+ int offsetX = (askRegion.left - wantRegion.left) >> level; | |
+ int offsetY = (askRegion.top - wantRegion.top) >> level; | |
+ canvas.drawBitmap(bitmap, offsetX, offsetY, null); | |
+ | |
+ // If the valid region (covered by bitmap or border) is smaller than the | |
+ // result bitmap, subset it. | |
+ int endX = offsetX + bitmap.getWidth() + borderSize; | |
+ int endY = offsetY + bitmap.getHeight() + borderSize; | |
bitmap.recycle(); | |
- return tile; | |
+ if (endX < size || endY < size) { | |
+ return Bitmap.createBitmap(result, 0, 0, Math.min(size, endX), | |
+ Math.min(size, endY)); | |
+ } else { | |
+ return result; | |
+ } | |
} | |
@Override | |
diff --git a/src/com/android/gallery3d/ui/UploadedTexture.java b/src/com/android/gallery3d/ui/UploadedTexture.java | |
index b2b8cd5..1777048 100644 | |
--- a/src/com/android/gallery3d/ui/UploadedTexture.java | |
+++ b/src/com/android/gallery3d/ui/UploadedTexture.java | |
@@ -161,6 +161,8 @@ abstract class UploadedTexture extends BasicTexture { | |
protected void invalidateContent() { | |
if (mBitmap != null) freeBitmap(); | |
mContentValid = false; | |
+ mWidth = UNSPECIFIED; | |
+ mHeight = UNSPECIFIED; | |
} | |
/** | |
project packages/apps/SmartCardService/ | |
project prebuilts/eclipse/ | |
project prebuilts/gcc/darwin-x86/arm/arm-linux-androideabi-4.6/ | |
project prebuilts/gcc/darwin-x86/mips/mipsel-linux-android-4.4.3/ | |
project prebuilts/gcc/darwin-x86/mips/mipsel-linux-android-4.6/ | |
project prebuilts/gcc/darwin-x86/x86/i686-linux-android-4.6/ | |
project prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.6/ | |
project prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6/ | |
project prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6/ | |
project prebuilts/gcc/linux-x86/mips/mipsel-linux-android-4.4.3/ | |
project prebuilts/gcc/linux-x86/mips/mipsel-linux-android-4.6/ | |
project prebuilts/gcc/linux-x86/x86/i686-linux-android-4.6/ | |
project prebuilts/misc/ | |
project prebuilts/qemu-kernel/ | |
project prebuilts/tools/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment