michael@0: /* michael@0: * Copyright (C) 2013 Square, Inc. michael@0: * michael@0: * Licensed under the Apache License, Version 2.0 (the "License"); michael@0: * you may not use this file except in compliance with the License. michael@0: * You may obtain a copy of the License at michael@0: * michael@0: * http://www.apache.org/licenses/LICENSE-2.0 michael@0: * michael@0: * Unless required by applicable law or agreed to in writing, software michael@0: * distributed under the License is distributed on an "AS IS" BASIS, michael@0: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. michael@0: * See the License for the specific language governing permissions and michael@0: * limitations under the License. michael@0: */ michael@0: package com.squareup.picasso; michael@0: michael@0: import android.content.Context; michael@0: import android.content.res.Resources; michael@0: import android.graphics.Bitmap; michael@0: import android.graphics.Canvas; michael@0: import android.graphics.ColorFilter; michael@0: import android.graphics.Paint; michael@0: import android.graphics.Path; michael@0: import android.graphics.Point; michael@0: import android.graphics.Rect; michael@0: import android.graphics.drawable.AnimationDrawable; michael@0: import android.graphics.drawable.BitmapDrawable; michael@0: import android.graphics.drawable.Drawable; michael@0: import android.os.SystemClock; michael@0: import android.widget.ImageView; michael@0: michael@0: import static android.graphics.Color.WHITE; michael@0: import static com.squareup.picasso.Picasso.LoadedFrom.MEMORY; michael@0: michael@0: final class PicassoDrawable extends Drawable { michael@0: // Only accessed from main thread. michael@0: private static final Paint DEBUG_PAINT = new Paint(); michael@0: michael@0: private static final float FADE_DURATION = 200f; //ms michael@0: michael@0: /** michael@0: * Create or update the drawable on the target {@link ImageView} to display the supplied bitmap michael@0: * image. michael@0: */ michael@0: static void setBitmap(ImageView target, Context context, Bitmap bitmap, michael@0: Picasso.LoadedFrom loadedFrom, boolean noFade, boolean debugging) { michael@0: Drawable placeholder = target.getDrawable(); michael@0: if (placeholder instanceof AnimationDrawable) { michael@0: ((AnimationDrawable) placeholder).stop(); michael@0: } michael@0: PicassoDrawable drawable = michael@0: new PicassoDrawable(context, placeholder, bitmap, loadedFrom, noFade, debugging); michael@0: target.setImageDrawable(drawable); michael@0: } michael@0: michael@0: /** michael@0: * Create or update the drawable on the target {@link ImageView} to display the supplied michael@0: * placeholder image. michael@0: */ michael@0: static void setPlaceholder(ImageView target, int placeholderResId, Drawable placeholderDrawable) { michael@0: if (placeholderResId != 0) { michael@0: target.setImageResource(placeholderResId); michael@0: } else { michael@0: target.setImageDrawable(placeholderDrawable); michael@0: } michael@0: if (target.getDrawable() instanceof AnimationDrawable) { michael@0: ((AnimationDrawable) target.getDrawable()).start(); michael@0: } michael@0: } michael@0: michael@0: private final boolean debugging; michael@0: private final float density; michael@0: private final Picasso.LoadedFrom loadedFrom; michael@0: final BitmapDrawable image; michael@0: michael@0: Drawable placeholder; michael@0: michael@0: long startTimeMillis; michael@0: boolean animating; michael@0: int alpha = 0xFF; michael@0: michael@0: PicassoDrawable(Context context, Drawable placeholder, Bitmap bitmap, michael@0: Picasso.LoadedFrom loadedFrom, boolean noFade, boolean debugging) { michael@0: Resources res = context.getResources(); michael@0: michael@0: this.debugging = debugging; michael@0: this.density = res.getDisplayMetrics().density; michael@0: michael@0: this.loadedFrom = loadedFrom; michael@0: michael@0: this.image = new BitmapDrawable(res, bitmap); michael@0: michael@0: boolean fade = loadedFrom != MEMORY && !noFade; michael@0: if (fade) { michael@0: this.placeholder = placeholder; michael@0: animating = true; michael@0: startTimeMillis = SystemClock.uptimeMillis(); michael@0: } michael@0: } michael@0: michael@0: @Override public void draw(Canvas canvas) { michael@0: if (!animating) { michael@0: image.draw(canvas); michael@0: } else { michael@0: float normalized = (SystemClock.uptimeMillis() - startTimeMillis) / FADE_DURATION; michael@0: if (normalized >= 1f) { michael@0: animating = false; michael@0: placeholder = null; michael@0: image.draw(canvas); michael@0: } else { michael@0: if (placeholder != null) { michael@0: placeholder.draw(canvas); michael@0: } michael@0: michael@0: int partialAlpha = (int) (alpha * normalized); michael@0: image.setAlpha(partialAlpha); michael@0: image.draw(canvas); michael@0: image.setAlpha(alpha); michael@0: invalidateSelf(); michael@0: } michael@0: } michael@0: michael@0: if (debugging) { michael@0: drawDebugIndicator(canvas); michael@0: } michael@0: } michael@0: michael@0: @Override public int getIntrinsicWidth() { michael@0: return image.getIntrinsicWidth(); michael@0: } michael@0: michael@0: @Override public int getIntrinsicHeight() { michael@0: return image.getIntrinsicHeight(); michael@0: } michael@0: michael@0: @Override public void setAlpha(int alpha) { michael@0: this.alpha = alpha; michael@0: if (placeholder != null) { michael@0: placeholder.setAlpha(alpha); michael@0: } michael@0: image.setAlpha(alpha); michael@0: } michael@0: michael@0: @Override public void setColorFilter(ColorFilter cf) { michael@0: if (placeholder != null) { michael@0: placeholder.setColorFilter(cf); michael@0: } michael@0: image.setColorFilter(cf); michael@0: } michael@0: michael@0: @Override public int getOpacity() { michael@0: return image.getOpacity(); michael@0: } michael@0: michael@0: @Override protected void onBoundsChange(Rect bounds) { michael@0: super.onBoundsChange(bounds); michael@0: michael@0: image.setBounds(bounds); michael@0: if (placeholder != null) { michael@0: placeholder.setBounds(bounds); michael@0: } michael@0: } michael@0: michael@0: private void drawDebugIndicator(Canvas canvas) { michael@0: DEBUG_PAINT.setColor(WHITE); michael@0: Path path = getTrianglePath(new Point(0, 0), (int) (16 * density)); michael@0: canvas.drawPath(path, DEBUG_PAINT); michael@0: michael@0: DEBUG_PAINT.setColor(loadedFrom.debugColor); michael@0: path = getTrianglePath(new Point(0, 0), (int) (15 * density)); michael@0: canvas.drawPath(path, DEBUG_PAINT); michael@0: } michael@0: michael@0: private static Path getTrianglePath(Point p1, int width) { michael@0: Point p2 = new Point(p1.x + width, p1.y); michael@0: Point p3 = new Point(p1.x, p1.y + width); michael@0: michael@0: Path path = new Path(); michael@0: path.moveTo(p1.x, p1.y); michael@0: path.lineTo(p2.x, p2.y); michael@0: path.lineTo(p3.x, p3.y); michael@0: michael@0: return path; michael@0: } michael@0: }