提交 90f1cc93 编写于 作者: S Sam Judd

Add a DrawableTransformation that runs wrapped BitmapTransformations.

The transformation uses the same logic used by the ResourceBitmapDecoder
to try to convert non-Bitmap Drawables to BitmapDrawables. Exceptions 
are thrown that will cause the load to fail if the conversion can’t happen. The primary benefit of this approach is that transformations
work similarly for the non-Bitmap Drawables that we’re now decoding. 
Unfortunately this isn’t a super efficient process, so hopefully it’s
rare. 
上级 fc4a4560
package com.bumptech.glide;
import static com.bumptech.glide.request.RequestOptions.bitmapTransform;
import static com.bumptech.glide.request.RequestOptions.centerCropTransform;
import static com.google.common.truth.Truth.assertThat;
import android.content.ContentResolver;
......@@ -15,6 +17,7 @@ import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
import com.bumptech.glide.test.ResourceIds;
import java.util.HashSet;
import java.util.List;
......@@ -41,6 +44,7 @@ public class NonBitmapDrawableResourcesTest {
@After
public void tearDown() {
Glide.get(context).clearDiskCache();
Glide.tearDown();
}
......@@ -54,6 +58,17 @@ public class NonBitmapDrawableResourcesTest {
assertThat(drawable).isNotNull();
}
@Test
public void load_withBitmapResourceId_asDrawable_withTransformation_producesNonNullBitmap()
throws ExecutionException, InterruptedException {
Drawable drawable = Glide.with(context)
.load(android.R.drawable.star_big_off)
.apply(centerCropTransform())
.submit()
.get();
assertThat(drawable).isNotNull();
}
@Test
public void load_withBitmapResourceId_asBitmap_producesNonNullBitmap()
throws ExecutionException, InterruptedException {
......@@ -75,6 +90,17 @@ public class NonBitmapDrawableResourcesTest {
assertThat(drawable).isNotNull();
}
@Test
public void load_withBitmapAliasResourceId_asDrawable_withTransformation_producesNonNullDrawable()
throws ExecutionException, InterruptedException {
Drawable drawable = Glide.with(context)
.load(ResourceIds.drawable.bitmap_alias)
.apply(centerCropTransform())
.submit()
.get();
assertThat(drawable).isNotNull();
}
@Test
public void load_withBitmapAliasResourceId_asBitmap_producesNonNullBitmap()
throws ExecutionException, InterruptedException {
......@@ -96,6 +122,30 @@ public class NonBitmapDrawableResourcesTest {
assertThat(drawable).isNotNull();
}
@Test
public void load_withShapeDrawableResourceId_asDrawable_withTransformation_sizeOriginal_fails()
throws ExecutionException, InterruptedException {
expectedException.expect(ExecutionException.class);
Glide.with(context)
.load(ResourceIds.drawable.shape_drawable)
.apply(centerCropTransform())
.submit()
.get();
}
@Test
public void load_withShapeDrawableResourceId_asDrawable_withTransformation_validSize_succeeds()
throws ExecutionException, InterruptedException {
Drawable drawable = Glide.with(context)
.load(ResourceIds.drawable.shape_drawable)
.apply(bitmapTransform(new RoundedCorners(10)))
.submit(100, 200)
.get();
assertThat(drawable).isNotNull();
assertThat(drawable.getIntrinsicWidth()).isEqualTo(100);
assertThat(drawable.getIntrinsicHeight()).isEqualTo(200);
}
@Test
public void load_withShapeDrawableResourceId_asBitmap_withSizeOriginal_fails()
throws ExecutionException, InterruptedException {
......@@ -120,6 +170,20 @@ public class NonBitmapDrawableResourcesTest {
assertThat(bitmap.getHeight()).isEqualTo(200);
}
@Test
public void load_withShapeDrawableResourceId_asBitmap_withValidSizeAndTransform_nonNullBitmap()
throws ExecutionException, InterruptedException {
Bitmap bitmap = Glide.with(context)
.asBitmap()
.load(ResourceIds.drawable.shape_drawable)
.apply(centerCropTransform())
.submit(100, 200)
.get();
assertThat(bitmap).isNotNull();
assertThat(bitmap.getWidth()).isEqualTo(100);
assertThat(bitmap.getHeight()).isEqualTo(200);
}
@Test
public void load_withStateListDrawableResourceId_asDrawable_producesNonNullDrawable()
throws ExecutionException, InterruptedException {
......@@ -130,6 +194,17 @@ public class NonBitmapDrawableResourcesTest {
assertThat(drawable).isNotNull();
}
@Test
public void load_withStateListDrawableResourceId_asDrawable_withTransformation_nonNullDrawable()
throws ExecutionException, InterruptedException {
Drawable drawable = Glide.with(context)
.load(ResourceIds.drawable.state_list_drawable)
.apply(centerCropTransform())
.submit()
.get();
assertThat(drawable).isNotNull();
}
@Test
public void load_withStateListDrawableResourceId_asBitmap_producesNonNullBitmap()
throws ExecutionException, InterruptedException {
......@@ -141,6 +216,18 @@ public class NonBitmapDrawableResourcesTest {
assertThat(bitmap).isNotNull();
}
@Test
public void load_withStateListDrawableResourceId_asBitmap_withTransformation_nonNullBitmap()
throws ExecutionException, InterruptedException {
Bitmap bitmap = Glide.with(context)
.asBitmap()
.load(ResourceIds.drawable.state_list_drawable)
.apply(centerCropTransform())
.submit()
.get();
assertThat(bitmap).isNotNull();
}
@Test
public void load_withVectorDrawableResourceId_asDrawable_producesNonNullDrawable()
throws ExecutionException, InterruptedException {
......@@ -151,6 +238,17 @@ public class NonBitmapDrawableResourcesTest {
assertThat(drawable).isNotNull();
}
@Test
public void load_withVectorDrawableResourceId_asDrawable_withTransformation_nonNullDrawable()
throws ExecutionException, InterruptedException {
Drawable drawable = Glide.with(context)
.load(ResourceIds.drawable.vector_drawable)
.apply(centerCropTransform())
.submit()
.get();
assertThat(drawable).isNotNull();
}
@Test
public void load_withVectorDrawableResourceId_asBitmap_producesNonNullBitmap()
throws ExecutionException, InterruptedException {
......@@ -162,6 +260,18 @@ public class NonBitmapDrawableResourcesTest {
assertThat(bitmap).isNotNull();
}
@Test
public void load_withVectorDrawableResourceId_asBitmap_withTransformation_producesNonNullBitmap()
throws ExecutionException, InterruptedException {
Bitmap bitmap = Glide.with(context)
.asBitmap()
.load(ResourceIds.drawable.vector_drawable)
.apply(centerCropTransform())
.submit()
.get();
assertThat(bitmap).isNotNull();
}
@Test
public void load_withNinePatchResourceId_asDrawable_producesNonNullDrawable()
throws ExecutionException, InterruptedException {
......@@ -173,6 +283,17 @@ public class NonBitmapDrawableResourcesTest {
assertThat(drawable).isNotNull();
}
@Test
public void load_withNinePatchResourceId_asDrawable_withTransformation_producesNonNullDrawable()
throws ExecutionException, InterruptedException {
Drawable drawable = Glide.with(context)
.load(ResourceIds.drawable.googlelogo_color_120x44dp)
.apply(centerCropTransform())
.submit()
.get();
assertThat(drawable).isNotNull();
}
@Test
public void load_withNinePatchResourceId_asBitmap_producesNonNullBitmap()
......@@ -186,6 +307,19 @@ public class NonBitmapDrawableResourcesTest {
assertThat(bitmap).isNotNull();
}
@Test
public void load_withNinePatchResourceId_asBitmap_withTransformation_producesNonNullBitmap()
throws ExecutionException, InterruptedException {
Bitmap bitmap = Glide.with(context)
.asBitmap()
.load(ResourceIds.drawable.googlelogo_color_120x44dp)
.apply(centerCropTransform())
.submit()
.get();
assertThat(bitmap).isNotNull();
}
@Test
public void load_withApplicationIconResourceIdUri_asDrawable_producesNonNullDrawable()
throws NameNotFoundException, ExecutionException, InterruptedException {
......@@ -206,6 +340,27 @@ public class NonBitmapDrawableResourcesTest {
}
}
@Test
public void load_withApplicationIconResourceIdUri_asDrawable_withTransformation_nonNullDrawable()
throws NameNotFoundException, ExecutionException, InterruptedException {
for (String packageName : getInstalledPackages()) {
int iconResourceId = getResourceId(packageName);
Uri uri = new Uri.Builder()
.scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
.authority(packageName)
.path(String.valueOf(iconResourceId))
.build();
Drawable drawable = Glide.with(context)
.load(uri)
.apply(centerCropTransform())
.submit()
.get();
assertThat(drawable).isNotNull();
}
}
@Test
public void load_withApplicationIconResourceIdUri_asBitmap_producesNonNullBitmap()
throws NameNotFoundException, ExecutionException, InterruptedException {
......@@ -227,6 +382,28 @@ public class NonBitmapDrawableResourcesTest {
}
}
@Test
public void load_withApplicationIconResourceIdUri_asBitmap_withTransformation_nonNullBitmap()
throws NameNotFoundException, ExecutionException, InterruptedException {
for (String packageName : getInstalledPackages()) {
int iconResourceId = getResourceId(packageName);
Uri uri = new Uri.Builder()
.scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
.authority(packageName)
.path(String.valueOf(iconResourceId))
.build();
Bitmap bitmap = Glide.with(context)
.asBitmap()
.apply(centerCropTransform())
.load(uri)
.submit()
.get();
assertThat(bitmap).isNotNull();
}
}
@Test
public void load_withApplicationIconResourceNameUri_asDrawable_producesNonNullDrawable()
throws ExecutionException, InterruptedException, NameNotFoundException {
......@@ -251,6 +428,32 @@ public class NonBitmapDrawableResourcesTest {
}
}
@Test
public void load_withApplicationIconResourceNameUri_asDrawable_withTransform_nonNullDrawable()
throws ExecutionException, InterruptedException, NameNotFoundException {
for (String packageName : getInstalledPackages()) {
int iconResourceId = getResourceId(packageName);
Context toUse = context.createPackageContext(packageName, /*flags=*/ 0);
Resources resources = toUse.getResources();
Uri uri = new Uri.Builder()
.scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
.authority(packageName)
.path(resources.getResourceTypeName(iconResourceId))
.path(resources.getResourceEntryName(iconResourceId))
.path(String.valueOf(iconResourceId))
.build();
Drawable drawable = Glide.with(context)
.load(uri)
.apply(centerCropTransform())
.submit()
.get();
assertThat(drawable).isNotNull();
}
}
@Test
public void load_withApplicationIconResourceNameUri_asBitmap_producesNonNullBitmap()
throws ExecutionException, InterruptedException, NameNotFoundException {
......@@ -276,6 +479,32 @@ public class NonBitmapDrawableResourcesTest {
}
}
@Test
public void load_withApplicationIconResourceNameUri_asBitmap_withTransform_nonNullBitmap()
throws ExecutionException, InterruptedException, NameNotFoundException {
for (String packageName : getInstalledPackages()) {
int iconResourceId = getResourceId(packageName);
Context toUse = context.createPackageContext(packageName, /*flags=*/ 0);
Resources resources = toUse.getResources();
Uri uri = new Uri.Builder()
.scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
.authority(packageName)
.path(resources.getResourceTypeName(iconResourceId))
.path(resources.getResourceEntryName(iconResourceId))
.path(String.valueOf(iconResourceId))
.build();
Bitmap bitmap = Glide.with(context)
.asBitmap()
.apply(centerCropTransform())
.load(uri)
.submit()
.get();
assertThat(bitmap).isNotNull();
}
}
private Set<String> getInstalledPackages() {
Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
......
......@@ -333,9 +333,10 @@ public class Glide implements ComponentCallbacks2 {
.append(Registry.BUCKET_BITMAP, GifDecoder.class, Bitmap.class,
new GifFrameResourceDecoder(bitmapPool))
/* Drawables */
.append(Uri.class, Drawable.class, new ResourceDrawableDecoder(context))
.append(Uri.class, Drawable.class, new ResourceDrawableDecoder(context, bitmapPool))
.append(Uri.class, Bitmap.class,
new ResourceBitmapDecoder(new ResourceDrawableDecoder(context), bitmapPool))
new ResourceBitmapDecoder(
new ResourceDrawableDecoder(context, bitmapPool), bitmapPool))
/* Files */
.register(new ByteBufferRewinder.Factory())
.append(File.class, ByteBuffer.class, new ByteBufferFileLoader.Factory())
......
......@@ -16,6 +16,7 @@ import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
final class DecodeHelper<Transcode> {
......@@ -142,7 +143,16 @@ final class DecodeHelper<Transcode> {
@SuppressWarnings("unchecked")
<Z> Transformation<Z> getTransformation(Class<Z> resourceClass) {
Transformation<Z> result = (Transformation<Z>) transformations.get(resourceClass);
if (result == null) {
if (result == null) {
for (Entry<Class<?>, Transformation<?>> entry : transformations.entrySet()) {
if (entry.getKey().isAssignableFrom(resourceClass)) {
result = (Transformation<Z>) entry.getValue();
break;
}
}
}
if (result == null) {
if (transformations.isEmpty() && isTransformationRequired) {
throw new IllegalArgumentException(
"Missing transformation for " + resourceClass + ". If you wish to"
......
......@@ -3,7 +3,7 @@ package com.bumptech.glide.load.resource.bitmap;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import com.bumptech.glide.Glide;
import android.graphics.drawable.Drawable;
import com.bumptech.glide.load.Transformation;
import com.bumptech.glide.load.engine.Resource;
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
......@@ -12,13 +12,16 @@ import java.security.MessageDigest;
/**
* Transforms {@link android.graphics.drawable.BitmapDrawable}s.
*
* @deprecated Use {@link DrawableTransformation} instead.
*/
@Deprecated
public class BitmapDrawableTransformation implements Transformation<BitmapDrawable> {
private final Transformation<Bitmap> wrapped;
private final Transformation<Drawable> wrapped;
public BitmapDrawableTransformation(Transformation<Bitmap> wrapped) {
this.wrapped = Preconditions.checkNotNull(wrapped);
this.wrapped = Preconditions.checkNotNull(new DrawableTransformation(wrapped));
}
/**
......@@ -45,19 +48,27 @@ public class BitmapDrawableTransformation implements Transformation<BitmapDrawab
public Resource<BitmapDrawable> transform(
Context context, Resource<BitmapDrawable> drawableResourceToTransform, int outWidth,
int outHeight) {
BitmapDrawable drawableToTransform = drawableResourceToTransform.get();
Bitmap bitmapToTransform = drawableToTransform.getBitmap();
BitmapPool bitmapPool = Glide.get(context).getBitmapPool();
BitmapResource bitmapResourceToTransform = BitmapResource.obtain(bitmapToTransform, bitmapPool);
Resource<Bitmap> transformedBitmapResource =
wrapped.transform(context, bitmapResourceToTransform, outWidth, outHeight);
Resource<Drawable> toTransform = convertToDrawableResource(drawableResourceToTransform);
Resource<Drawable> transformed = wrapped.transform(context, toTransform, outWidth, outHeight);
return convertToBitmapDrawableResource(transformed);
}
if (transformedBitmapResource.equals(bitmapResourceToTransform)) {
return drawableResourceToTransform;
} else {
return LazyBitmapDrawableResource.obtain(context, transformedBitmapResource.get());
@SuppressWarnings("unchecked")
private static Resource<BitmapDrawable> convertToBitmapDrawableResource(
Resource<Drawable> resource) {
if (!(resource.get() instanceof BitmapDrawable)) {
throw new IllegalArgumentException(
"Wrapped transformation unexpectedly returned a non BitmapDrawable resource: "
+ resource.get());
}
return (Resource<BitmapDrawable>) (Resource<?>) resource;
}
@SuppressWarnings("unchecked")
private static Resource<Drawable> convertToDrawableResource(
Resource<BitmapDrawable> toConvert) {
return (Resource<Drawable>) (Resource<? extends Drawable>) toConvert;
}
@Override
......
package com.bumptech.glide.load.resource.bitmap;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.drawable.Animatable;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.support.annotation.Nullable;
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
import com.bumptech.glide.request.target.Target;
import java.util.concurrent.locks.Lock;
final class DrawableToBitmapConverter {
private DrawableToBitmapConverter() {
// Utility class.
}
static boolean willDraw(Drawable drawable) {
return !(drawable.getCurrent() instanceof BitmapDrawable);
}
@Nullable
static Bitmap convert(BitmapPool bitmapPool, Drawable drawable, int width, int height) {
// Handle DrawableContainer or StateListDrawables that may contain one or more BitmapDrawables.
drawable = drawable.getCurrent();
Bitmap result = null;
if (drawable instanceof BitmapDrawable) {
result = ((BitmapDrawable) drawable).getBitmap();
} else if (!(drawable instanceof Animatable)) {
result = drawToBitmap(bitmapPool, drawable, width, height);
}
if (result == null) {
return null;
}
return result;
}
private static Bitmap drawToBitmap(
BitmapPool bitmapPool, Drawable drawable, int width, int height) {
if (width == Target.SIZE_ORIGINAL && drawable.getIntrinsicWidth() <= 0) {
throw new IllegalArgumentException("Unable to draw " + drawable + " to Bitmap with "
+ "Target.SIZE_ORIGINAL because the Drawable has no intrinsic width");
}
if (height == Target.SIZE_ORIGINAL && drawable.getIntrinsicHeight() <= 0) {
throw new IllegalArgumentException("Unable to draw " + drawable + " to Bitmap with "
+ "Target.SIZE_ORIGINAL because the Drawable has no intrinsic height");
}
int targetWidth = drawable.getIntrinsicWidth() > 0 ? drawable.getIntrinsicWidth() : width;
int targetHeight = drawable.getIntrinsicHeight() > 0 ? drawable.getIntrinsicHeight() : height;
Lock lock = TransformationUtils.getBitmapDrawableLock();
lock.lock();
Bitmap result = bitmapPool.get(targetWidth, targetHeight, Bitmap.Config.ARGB_8888);
try {
Canvas canvas = new Canvas(result);
drawable.setBounds(0, 0, targetWidth, targetHeight);
drawable.draw(canvas);
canvas.setBitmap(null);
} finally {
lock.unlock();
}
return result;
}
}
package com.bumptech.glide.load.resource.bitmap;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.Transformation;
import com.bumptech.glide.load.engine.Resource;
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
import java.security.MessageDigest;
/**
* Applies a {@link Bitmap} {@link Transformation} to {@link Drawable}s by first attempting to
* convert the {@link Drawable} to a {@link Bitmap} and then running the {@link Transformation}
* on the converted {@link Bitmap}.
*
* <p>This class is relatively efficient for {@link BitmapDrawable} where the {@link Bitmap} is
* readily accessible. For non-{@link Bitmap} based {@link Drawable}s, this class must first try to
* draw the {@link Drawable} to a {@link Bitmap} using {@link android.graphics.Canvas}, which is
* less efficient. {@link Drawable}s that implement {@link android.graphics.drawable.Animatable}
* will fail with an exception. {@link Drawable}s that return <= 0 for
* {@link Drawable#getIntrinsicHeight()} and/or {@link Drawable#getIntrinsicWidth()} will fail
* with an exception if the requested size is
* {@link com.bumptech.glide.request.target.Target#SIZE_ORIGINAL}. {@link Drawable}s without
* intrinsic dimensions are drawn using the dimensions provided in
* {@link Transformation#transform(Context, Resource, int, int)}. As a result, they may be
* transformed incorrectly or in unexpected ways.
*/
public class DrawableTransformation implements Transformation<Drawable> {
private final Transformation<Bitmap> wrapped;
public DrawableTransformation(Transformation<Bitmap> wrapped) {
this.wrapped = wrapped;
}
@SuppressWarnings("unchecked")
public Transformation<BitmapDrawable> asBitmapDrawable() {
return (Transformation<BitmapDrawable>) (Transformation<?>) this;
}
@Override
public Resource<Drawable> transform(Context context, Resource<Drawable> resource, int outWidth,
int outHeight) {
BitmapPool bitmapPool = Glide.get(context).getBitmapPool();
Drawable drawable = resource.get();
Bitmap bitmap = DrawableToBitmapConverter.convert(bitmapPool, drawable, outWidth, outHeight);
if (bitmap == null) {
throw new IllegalArgumentException("Unable to convert " + drawable + " to a Bitmap");
}
Resource<Bitmap> bitmapResourceToTransform = new BitmapResource(bitmap, bitmapPool);
Resource<Bitmap> transformedBitmapResource =
wrapped.transform(context, bitmapResourceToTransform, outWidth, outHeight);
if (transformedBitmapResource.equals(bitmapResourceToTransform)) {
transformedBitmapResource.recycle();
// If we extracted the Bitmap from a StateListDrawable, or a BitmapDrawable then we can't
// recycle it here. If on the other hand, we drew the Drawable to a Canvas, we can recycle
// the resulting unused Bitmap.
if (DrawableToBitmapConverter.willDraw(drawable)) {
bitmapResourceToTransform.recycle();
}
return resource;
} else {
return newDrawableResource(context, transformedBitmapResource.get());
}
}
@SuppressWarnings("unchecked")
private Resource<Drawable> newDrawableResource(
Context context, Bitmap transformed) {
Resource<? extends Drawable> result =
LazyBitmapDrawableResource.obtain(context, transformed);
return (Resource<Drawable>) result;
}
@Override
public boolean equals(Object o) {
if (o instanceof DrawableTransformation) {
DrawableTransformation other = (DrawableTransformation) o;
return wrapped.equals(other.wrapped);
}
return false;
}
@Override
public int hashCode() {
return wrapped.hashCode();
}
@Override
public void updateDiskCacheKey(MessageDigest messageDigest) {
wrapped.updateDiskCacheKey(messageDigest);
}
}
......@@ -2,10 +2,7 @@ package com.bumptech.glide.load.resource.bitmap;
import android.content.ContentResolver;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.drawable.Animatable;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.support.annotation.Nullable;
......@@ -51,42 +48,11 @@ public class ResourceBitmapDecoder implements ResourceDecoder<Uri, Bitmap> {
public Resource<Bitmap> decode(Uri source, int width, int height, Options options)
throws IOException {
Resource<Drawable> drawableResource = drawableDecoder.decode(source, width, height, options);
if (drawableResource == null) {
Bitmap bitmap =
DrawableToBitmapConverter.convert(bitmapPool, drawableResource.get(), width, height);
if (bitmap == null) {
return null;
}
// Handle DrawableContainer or StateListDrawables that may contain one or more BitmapDrawables.
Drawable drawable = drawableResource.get().getCurrent();
Bitmap result = null;
if (drawable instanceof BitmapDrawable) {
result = ((BitmapDrawable) drawable).getBitmap();
} else if (!(drawable instanceof Animatable)) {
result = drawToBitmap(drawable, width, height);
}
if (result == null) {
return null;
}
return new BitmapResource(result, bitmapPool);
}
private Bitmap drawToBitmap(Drawable drawable, int width, int height) {
if (width == Target.SIZE_ORIGINAL && drawable.getIntrinsicWidth() <= 0) {
throw new IllegalArgumentException("Unable to draw " + drawable + " to Bitmap with "
+ "Target.SIZE_ORIGINAL because the Drawable has no intrinsic width");
}
if (height == Target.SIZE_ORIGINAL && drawable.getIntrinsicHeight() <= 0) {
throw new IllegalArgumentException("Unable to draw " + drawable + " to Bitmap with "
+ "Target.SIZE_ORIGINAL because the Drawable has no intrinsic height");
}
int targetWidth = drawable.getIntrinsicWidth() > 0 ? drawable.getIntrinsicWidth() : width;
int targetHeight = drawable.getIntrinsicHeight() > 0 ? drawable.getIntrinsicHeight() : height;
Bitmap result = Bitmap.createBitmap(targetWidth, targetHeight, Config.ARGB_8888);
Canvas canvas = new Canvas(result);
drawable.setBounds(0, 0, targetWidth, targetHeight);
drawable.draw(canvas);
canvas.setBitmap(null);
return result;
return new BitmapResource(bitmap, bitmapPool);
}
}
......@@ -3,14 +3,16 @@ package com.bumptech.glide.load.resource.drawable;
import android.content.ContentResolver;
import android.content.Context;
import android.content.pm.PackageManager.NameNotFoundException;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.support.annotation.DrawableRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.bumptech.glide.load.Options;
import com.bumptech.glide.load.ResourceDecoder;
import com.bumptech.glide.load.engine.Resource;
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
import com.bumptech.glide.load.resource.bitmap.BitmapDrawableResource;
import java.io.IOException;
import java.util.List;
......@@ -32,9 +34,11 @@ public class ResourceDrawableDecoder implements ResourceDecoder<Uri, Drawable> {
private static final int RESOURCE_ID_SEGMENT_INDEX = 0;
private final Context context;
private final BitmapPool bitmapPool;
public ResourceDrawableDecoder(Context context) {
public ResourceDrawableDecoder(Context context, BitmapPool bitmapPool) {
this.context = context.getApplicationContext();
this.bitmapPool = bitmapPool;
}
@Override
......@@ -42,7 +46,7 @@ public class ResourceDrawableDecoder implements ResourceDecoder<Uri, Drawable> {
return source.getScheme().equals(ContentResolver.SCHEME_ANDROID_RESOURCE);
}
@Nullable
@NonNull
@Override
public Resource<Drawable> decode(Uri source, int width, int height, Options options)
throws IOException {
......@@ -52,6 +56,16 @@ public class ResourceDrawableDecoder implements ResourceDecoder<Uri, Drawable> {
? context : getContextForPackage(source, packageName);
// We can't get a theme from another application.
Drawable drawable = DrawableDecoderCompat.getDrawable(toUse, resId);
return getDrawableResource(drawable);
}
@SuppressWarnings("unchecked")
private Resource<Drawable> getDrawableResource(Drawable drawable) {
if (drawable instanceof BitmapDrawable) {
BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
return (Resource<Drawable>) (Resource<? extends Drawable>)
new BitmapDrawableResource(bitmapDrawable, bitmapPool);
}
return new InternalDrawableResource(drawable);
}
......
......@@ -19,13 +19,13 @@ import com.bumptech.glide.load.Options;
import com.bumptech.glide.load.Transformation;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.load.model.stream.HttpGlideUrlLoader;
import com.bumptech.glide.load.resource.bitmap.BitmapDrawableTransformation;
import com.bumptech.glide.load.resource.bitmap.BitmapEncoder;
import com.bumptech.glide.load.resource.bitmap.CenterCrop;
import com.bumptech.glide.load.resource.bitmap.CenterInside;
import com.bumptech.glide.load.resource.bitmap.CircleCrop;
import com.bumptech.glide.load.resource.bitmap.DownsampleStrategy;
import com.bumptech.glide.load.resource.bitmap.Downsampler;
import com.bumptech.glide.load.resource.bitmap.DrawableTransformation;
import com.bumptech.glide.load.resource.bitmap.FitCenter;
import com.bumptech.glide.load.resource.bitmap.VideoBitmapDecoder;
import com.bumptech.glide.load.resource.gif.GifDrawable;
......@@ -1170,9 +1170,14 @@ public class RequestOptions implements Cloneable {
return clone().optionalTransform(transformation);
}
DrawableTransformation drawableTransformation = new DrawableTransformation(transformation);
optionalTransform(Bitmap.class, transformation);
optionalTransform(Drawable.class, drawableTransformation);
// TODO: remove BitmapDrawable decoder and this transformation.
optionalTransform(BitmapDrawable.class, new BitmapDrawableTransformation(transformation));
// Registering as BitmapDrawable is simply an optimization to avoid some iteration and
// isAssignableFrom checks when obtaining the transformation later on. It can be removed without
// affecting the functionality.
optionalTransform(BitmapDrawable.class, drawableTransformation.asBitmapDrawable());
optionalTransform(GifDrawable.class, new GifDrawableTransformation(transformation));
return selfOrThrowIfLocked();
}
......
......@@ -37,12 +37,12 @@ import org.robolectric.annotation.Config;
@RunWith(RobolectricTestRunner.class)
@Config(manifest = Config.NONE, sdk = 18)
@SuppressWarnings("deprecation")
public class BitmapDrawableTransformationTest {
@Mock BitmapPool bitmapPool;
@Mock Transformation<Bitmap> wrapped;
@Mock Resource<BitmapDrawable> drawableResourceToTransform;
@Mock BitmapDrawable drawableToTransform;
private BitmapDrawableTransformation transformation;
private Bitmap bitmapToTransform;
......@@ -52,11 +52,11 @@ public class BitmapDrawableTransformationTest {
public void setUp() {
MockitoAnnotations.initMocks(this);
bitmapToTransform = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
BitmapDrawable drawableToTransform = new BitmapDrawable(bitmapToTransform);
context = RuntimeEnvironment.application;
Glide.init(new GlideBuilder().setBitmapPool(bitmapPool).build(context));
when(drawableResourceToTransform.get()).thenReturn(drawableToTransform);
when(drawableToTransform.getBitmap()).thenReturn(bitmapToTransform);
transformation = new BitmapDrawableTransformation(wrapped);
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册