Skip to content

Commit

Permalink
Add a DrawableTransformation that runs wrapped BitmapTransformations.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
sjudd committed Oct 22, 2017
1 parent fc4a456 commit 90f1cc9
Show file tree
Hide file tree
Showing 10 changed files with 459 additions and 61 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
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;
Expand All @@ -15,6 +17,7 @@
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;
Expand All @@ -41,6 +44,7 @@ public void setUp() {

@After
public void tearDown() {
Glide.get(context).clearDiskCache();
Glide.tearDown();
}

Expand All @@ -54,6 +58,17 @@ public void load_withBitmapResourceId_asDrawable_producesNonNullDrawable()
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 {
Expand All @@ -75,6 +90,17 @@ public void load_withBitmapAliasResourceId_asDrawable_producesNonNullDrawable()
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 {
Expand All @@ -96,6 +122,30 @@ public void load_withShapeDrawableResourceId_asDrawable_producesNonNullDrawable(
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 {
Expand All @@ -120,6 +170,20 @@ public void load_withShapeDrawableResourceId_asBitmap_withValidSize_returnsNonNu
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 {
Expand All @@ -130,6 +194,17 @@ public void load_withStateListDrawableResourceId_asDrawable_producesNonNullDrawa
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 {
Expand All @@ -141,6 +216,18 @@ public void load_withStateListDrawableResourceId_asBitmap_producesNonNullBitmap(
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 {
Expand All @@ -151,6 +238,17 @@ public void load_withVectorDrawableResourceId_asDrawable_producesNonNullDrawable
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 {
Expand All @@ -162,6 +260,18 @@ public void load_withVectorDrawableResourceId_asBitmap_producesNonNullBitmap()
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 {
Expand All @@ -173,6 +283,17 @@ public void load_withNinePatchResourceId_asDrawable_producesNonNullDrawable()
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()
Expand All @@ -186,6 +307,19 @@ public void load_withNinePatchResourceId_asBitmap_producesNonNullBitmap()
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 {
Expand All @@ -206,6 +340,27 @@ public void load_withApplicationIconResourceIdUri_asDrawable_producesNonNullDraw
}
}

@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 {
Expand All @@ -227,6 +382,28 @@ public void load_withApplicationIconResourceIdUri_asBitmap_producesNonNullBitmap
}
}

@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 {
Expand All @@ -251,6 +428,32 @@ public void load_withApplicationIconResourceNameUri_asDrawable_producesNonNullDr
}
}


@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 {
Expand All @@ -276,6 +479,32 @@ public void load_withApplicationIconResourceNameUri_asBitmap_producesNonNullBitm
}
}

@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);
Expand Down
5 changes: 3 additions & 2 deletions library/src/main/java/com/bumptech/glide/Glide.java
Original file line number Diff line number Diff line change
Expand Up @@ -333,9 +333,10 @@ private static GeneratedAppGlideModule getAnnotationGeneratedGlideModules() {
.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())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

final class DecodeHelper<Transcode> {

Expand Down Expand Up @@ -142,7 +143,16 @@ boolean isScaleOnlyOrNoTransform() {
@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"
Expand Down
Loading

0 comments on commit 90f1cc9

Please sign in to comment.