Chromium Code Reviews| Index: chrome/android/java/src/org/chromium/chrome/browser/ntp/LogoView.java |
| diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/LogoView.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/LogoView.java |
| index 94a7f3df7f0e7521d7ddb30dcf304a1a0a6a6cda..73cc5517833383513a37e2c506ed8f512b7e97eb 100644 |
| --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/LogoView.java |
| +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/LogoView.java |
| @@ -8,10 +8,12 @@ import android.animation.Animator; |
| import android.animation.ObjectAnimator; |
| import android.content.Context; |
| import android.graphics.Bitmap; |
| +import android.graphics.Bitmap.Config; |
| import android.graphics.BitmapFactory; |
| import android.graphics.Canvas; |
| import android.graphics.Matrix; |
| import android.graphics.Paint; |
| +import android.graphics.drawable.Drawable; |
| import android.text.TextUtils; |
| import android.util.AttributeSet; |
| import android.util.Property; |
| @@ -24,9 +26,13 @@ import org.chromium.chrome.browser.ntp.NewTabPageView.NewTabPageManager; |
| import java.lang.ref.WeakReference; |
| +import jp.tomorrowkey.android.gifplayer.BaseGifDrawable; |
| +import jp.tomorrowkey.android.gifplayer.BaseGifImage; |
| + |
| /** |
| * This view shows the default search provider's logo and fades in a new logo if one becomes |
| - * available. |
| + * available. It also maintains a {@link BaseGifDrawable} that will be played when the user clicks |
| + * this view and we have an animated GIF ready. |
| */ |
| public class LogoView extends View implements OnClickListener { |
| @@ -36,14 +42,18 @@ public class LogoView extends View implements OnClickListener { |
| // The default logo is shared across all NTPs. |
| private static WeakReference<Bitmap> sDefaultLogo; |
| - private Paint mPaint; |
| + // mLogo and mNewLogo are remembered for cross fading animation. |
| private Bitmap mLogo; |
| private Bitmap mNewLogo; |
| + private ObjectAnimator mAnimation; |
|
newt (away)
2015/09/23 20:38:43
It's probably good to rename this to mFadeAnimatio
Ian Wen
2015/09/23 21:59:51
Done.
|
| + |
| + private BaseGifDrawable mGifDrawable; |
|
newt (away)
2015/09/23 20:38:43
I'd call this mAnimatedLogoDrawable for clarity an
Ian Wen
2015/09/23 21:59:51
Done.
|
| + private Matrix mAnimatedLogoMatrix; |
|
newt (away)
2015/09/23 20:38:43
nit: put this with the other Matrix objects
Ian Wen
2015/09/23 21:59:51
Done.
|
| + private Paint mPaint; |
| private Matrix mLogoMatrix; |
| private Matrix mNewLogoMatrix; |
| private boolean mLogoIsDefault; |
| private boolean mNewLogoIsDefault; |
| - private ObjectAnimator mAnimation; |
| /** |
| * A measure from 0 to 1 of how much the new logo has faded in. 0 shows the old logo, 1 shows |
| @@ -99,15 +109,36 @@ public class LogoView extends View implements OnClickListener { |
| } |
| /** |
| - * Jumps to the end of the current logo animation, if any. |
| + * Jumps to the end of the logo cross-fading animation, if any. |
| */ |
| - public void endAnimation() { |
| + public void endFadingAnimation() { |
| if (mAnimation != null) { |
| mAnimation.end(); |
| mAnimation = null; |
| } |
| } |
| + |
| + /** |
| + * @return True after the animated GIF starts playing. False otherwise. |
| + */ |
| + public boolean isAnimatedLogoShowing() { |
| + return mGifDrawable != null && mGifDrawable.isRunning() && mGifDrawable.isValid(); |
| + } |
| + |
| + /** |
| + * Updates the GIF contained in this View and starts playing it. |
|
newt (away)
2015/09/23 20:38:43
"animated GIF logo"
Ian Wen
2015/09/23 21:59:51
Done.
|
| + */ |
| + public void updateAnimatedLogo(BaseGifImage gifImage) { |
| + mGifDrawable = new BaseGifDrawable(gifImage, Config.ARGB_8888); |
| + mAnimatedLogoMatrix = new Matrix(); |
| + setMatrix(mGifDrawable.getIntrinsicWidth(), mGifDrawable.getIntrinsicHeight(), |
| + mAnimatedLogoMatrix, false); |
| + // Set callback here to ensure #invalidateDrawable() is called. |
| + mGifDrawable.setCallback(this); |
| + mGifDrawable.start(); |
| + } |
| + |
| /** |
| * Fades in a new logo over the current logo. |
| * |
| @@ -179,13 +210,17 @@ public class LogoView extends View implements OnClickListener { |
| * not fill the entire view but will still be centered. |
| */ |
| private void setMatrix(Bitmap image, Matrix matrix, boolean preventUpscaling) { |
|
newt (away)
2015/09/23 20:38:43
you could just remove this method and update calle
Ian Wen
2015/09/23 21:59:51
Done.
|
| - int width = getWidth(); |
| - int height = getHeight(); |
| int imageWidth = image.getWidth(); |
| int imageHeight = image.getHeight(); |
| + setMatrix(imageWidth, imageHeight, matrix, preventUpscaling); |
| + } |
| + |
| + private void setMatrix(int imageWidth, int imageHeight, Matrix matrix, boolean preventUpscale) { |
|
newt (away)
2015/09/23 20:38:43
s/preventUpscale/preventUpscaling/
preventUpscale
Ian Wen
2015/09/23 21:59:51
Done.
|
| + int width = getWidth(); |
| + int height = getHeight(); |
| float scale = Math.min((float) width / imageWidth, (float) height / imageHeight); |
| - if (preventUpscaling) scale = Math.min(1.0f, scale); |
| + if (preventUpscale) scale = Math.min(1.0f, scale); |
| int imageOffsetX = Math.round((width - imageWidth * scale) * 0.5f); |
| int imageOffsetY = Math.round((height - imageHeight * scale) * 0.5f); |
| @@ -207,21 +242,47 @@ public class LogoView extends View implements OnClickListener { |
| } |
| @Override |
| + protected boolean verifyDrawable(Drawable who) { |
| + return (who == mGifDrawable) || super.verifyDrawable(who); |
| + } |
| + |
| + @Override |
| + public void invalidateDrawable(Drawable drawable) { |
| + // Drawable inside of the view does not have complete information about its boundary, making |
|
newt (away)
2015/09/23 20:38:43
How about: "mGifDrawable doesn't actually know its
Ian Wen
2015/09/23 21:59:51
Done.
|
| + // it unable to only invalidate the area the drawable lives. Instead we invalidate the whole |
| + // view every time the drawable requests a invalidation. See ImageView#invalidateDrawable() |
| + // for more information. |
| + if (drawable == mGifDrawable) invalidate(); |
| + else super.invalidateDrawable(drawable); |
| + } |
| + |
| + @Override |
| protected void onDraw(Canvas canvas) { |
| - if (mLogo != null && mTransitionAmount < 0.5f) { |
| - mPaint.setAlpha((int) (255 * 2 * (0.5f - mTransitionAmount))); |
| - canvas.save(); |
| - canvas.concat(mLogoMatrix); |
| - canvas.drawBitmap(mLogo, 0, 0, mPaint); |
| - canvas.restore(); |
| - } |
| + if (isAnimatedLogoShowing()) { |
| + if (mAnimation != null) mAnimation.cancel(); |
| + // Free the old bitmaps to allow them to be GC'd. |
| + mLogo = mNewLogo = null; |
|
newt (away)
2015/09/23 20:38:43
I'd avoid fancy tricks here. Use two separate stat
Ian Wen
2015/09/23 21:59:51
Done.
|
| - if (mNewLogo != null && mTransitionAmount > 0.5f) { |
| - mPaint.setAlpha((int) (255 * 2 * (mTransitionAmount - 0.5f))); |
| canvas.save(); |
| - canvas.concat(mNewLogoMatrix); |
| - canvas.drawBitmap(mNewLogo, 0, 0, mPaint); |
| + canvas.concat(mAnimatedLogoMatrix); |
| + mGifDrawable.draw(canvas); |
| canvas.restore(); |
| + } else { |
| + if (mLogo != null && mTransitionAmount < 0.5f) { |
| + mPaint.setAlpha((int) (255 * 2 * (0.5f - mTransitionAmount))); |
| + canvas.save(); |
| + canvas.concat(mLogoMatrix); |
| + canvas.drawBitmap(mLogo, 0, 0, mPaint); |
| + canvas.restore(); |
| + } |
| + |
| + if (mNewLogo != null && mTransitionAmount > 0.5f) { |
| + mPaint.setAlpha((int) (255 * 2 * (mTransitionAmount - 0.5f))); |
| + canvas.save(); |
| + canvas.concat(mNewLogoMatrix); |
| + canvas.drawBitmap(mNewLogo, 0, 0, mPaint); |
| + canvas.restore(); |
| + } |
| } |
| } |
| @@ -236,7 +297,7 @@ public class LogoView extends View implements OnClickListener { |
| @Override |
| public void onClick(View view) { |
| if (view == this && mManager != null && !isTransitioning()) { |
| - mManager.openLogoLink(); |
| + mManager.onLogoClicked(isAnimatedLogoShowing()); |
| } |
| } |
| } |