diff --git a/library/src/androidTest/java/com/bumptech/glide/load/resource/bitmap/BitmapTransformationTest.java b/library/src/androidTest/java/com/bumptech/glide/load/resource/bitmap/BitmapTransformationTest.java
index 7ee9161f6f..8606c6fa71 100644
--- a/library/src/androidTest/java/com/bumptech/glide/load/resource/bitmap/BitmapTransformationTest.java
+++ b/library/src/androidTest/java/com/bumptech/glide/load/resource/bitmap/BitmapTransformationTest.java
@@ -10,10 +10,13 @@
import com.bumptech.glide.load.engine.Resource;
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
+import com.bumptech.glide.request.target.Target;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
@@ -21,11 +24,12 @@
@Config(manifest = Config.NONE, emulateSdk = 18)
public class BitmapTransformationTest {
+ @Mock
private BitmapPool bitmapPool;
@Before
public void setUp() {
- bitmapPool = mock(BitmapPool.class);
+ MockitoAnnotations.initMocks(this);
}
@Test
@@ -42,14 +46,12 @@ public String getId() {
}
};
- Resource resource = mock(Resource.class);
- when(resource.get()).thenReturn(Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_4444));
+ Resource resource = mockResource(100, 100);
assertEquals(resource, transformation.transform(resource, 1, 1));
}
@Test
public void testReturnsNewResourceWhenBitmapTransformed() {
- final Bitmap toTransform = Bitmap.createBitmap(1, 2, Bitmap.Config.RGB_565);
final Bitmap transformed = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_4444);
BitmapTransformation transformation = new BitmapTransformation(bitmapPool) {
@Override
@@ -63,9 +65,7 @@ public String getId() {
}
};
- Resource resource = mock(Resource.class);
- when(resource.get()).thenReturn(toTransform);
-
+ Resource resource = mockResource(1, 2);
assertNotSame(resource, transformation.transform(resource, 100, 100));
}
@@ -73,15 +73,15 @@ public String getId() {
public void testPassesGivenArgumentsToTransform() {
final int expectedWidth = 13;
final int expectedHeight = 148;
- final Bitmap expected = Bitmap.createBitmap(223, 4123, Bitmap.Config.RGB_565);
+ final Resource resource = mockResource(223, 4123);
BitmapTransformation transformation = new BitmapTransformation(bitmapPool) {
@Override
protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
assertEquals(bitmapPool, pool);
- assertEquals(expected, toTransform);
+ assertEquals(resource.get(), toTransform);
assertEquals(expectedWidth, outWidth);
assertEquals(expectedHeight, outHeight);
- return expected;
+ return resource.get();
}
@Override
@@ -89,8 +89,7 @@ public String getId() {
return null;
}
};
- Resource resource = mock(Resource.class);
- when(resource.get()).thenReturn(expected);
+
transformation.transform(resource, expectedWidth, expectedHeight);
}
@@ -145,8 +144,58 @@ protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, in
}
};
- Resource resource = mock(Resource.class);
- when(resource.get()).thenReturn(Bitmap.createBitmap(100, 100, Bitmap.Config.RGB_565));
+ Resource resource = mockResource(100, 100);
assertNull(transform.transform(resource, 100, 100));
}
+
+ @Test
+ public void testCallsTransformWithGivenBitmapWidthIfWidthIsSizeOriginal() {
+ SizeTrackingTransform transform = new SizeTrackingTransform();
+
+ int expectedWidth = 200;
+ Resource resource = mockResource(expectedWidth, 300);
+ transform.transform(resource, Target.SIZE_ORIGINAL, 500);
+
+ assertEquals(expectedWidth, transform.givenWidth);
+ }
+
+ @Test
+ public void testCallsTransformWithGivenBitmapHeightIfHeightIsSizeOriginal() {
+ SizeTrackingTransform transform = new SizeTrackingTransform();
+
+ int expectedHeight = 500;
+ Resource resource = mockResource(123, expectedHeight);
+ transform.transform(resource, 444, expectedHeight);
+
+ assertEquals(expectedHeight, transform.givenHeight);
+ }
+
+ @SuppressWarnings("unchecked")
+ private Resource mockResource(int width, int height) {
+ Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+ Resource resource = mock(Resource.class);
+ when(resource.get()).thenReturn(bitmap);
+ return resource;
+ }
+
+ private class SizeTrackingTransform extends BitmapTransformation {
+ int givenWidth;
+ int givenHeight;
+
+ public SizeTrackingTransform() {
+ super(bitmapPool);
+ }
+
+ @Override
+ protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
+ givenWidth = outWidth;
+ givenHeight = outHeight;
+ return null;
+ }
+
+ @Override
+ public String getId() {
+ return null;
+ }
+ }
}
\ No newline at end of file
diff --git a/library/src/androidTest/java/com/bumptech/glide/load/resource/bitmap/TransformationUtilsTest.java b/library/src/androidTest/java/com/bumptech/glide/load/resource/bitmap/TransformationUtilsTest.java
index a73988b7c0..123f1fb615 100644
--- a/library/src/androidTest/java/com/bumptech/glide/load/resource/bitmap/TransformationUtilsTest.java
+++ b/library/src/androidTest/java/com/bumptech/glide/load/resource/bitmap/TransformationUtilsTest.java
@@ -4,6 +4,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
@@ -135,6 +136,22 @@ public void testFitCenterReturnsGivenBitmapIfGivenBitmapHeightMatchesExactly() {
assertTrue(toFit == transformed);
}
+ @Test
+ public void testCenterCropReturnsNullIfGivenBitmapIsNull() {
+ Bitmap transformed = TransformationUtils.centerCrop(null /*recycled*/, null /*toCrop*/, 100, 100);
+ assertNull(transformed);
+ }
+
+ @Test
+ public void testCenterCropReturnsGivenBitmapIfGivenBitmapExactlyMatchesGivenDimensions() {
+ Bitmap toCrop = Bitmap.createBitmap(200, 300, Bitmap.Config.ARGB_8888);
+ Bitmap transformed = TransformationUtils.centerCrop(null /*recycled*/, toCrop, toCrop.getWidth(),
+ toCrop.getHeight());
+
+ // Robolectric incorrectly implements equals() for Bitmaps, we want the original object not just an equivalent.
+ assertTrue(toCrop == transformed);
+ }
+
@Test
public void testCenterCropSetsOutBitmapToHaveAlphaIfInBitmapHasAlphaAndOutBitmapIsReused() {
Bitmap toTransform = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
@@ -179,7 +196,7 @@ public void testCenterCropSetsOutBitmapToHaveAlphaIfInBitmapHasAlpha() {
}
@Test
- public void testSetsOutBitmapToNotHaveAlphaIfInBitmapDoesNotHaveAlpha() {
+ public void testCenterCropSetsOutBitmapToNotHaveAlphaIfInBitmapDoesNotHaveAlpha() {
Bitmap toTransform = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
toTransform.setHasAlpha(false);
diff --git a/library/src/androidTest/java/com/bumptech/glide/request/target/ViewTargetTest.java b/library/src/androidTest/java/com/bumptech/glide/request/target/ViewTargetTest.java
index cd1f6e24e2..9339a34ae2 100644
--- a/library/src/androidTest/java/com/bumptech/glide/request/target/ViewTargetTest.java
+++ b/library/src/androidTest/java/com/bumptech/glide/request/target/ViewTargetTest.java
@@ -112,22 +112,134 @@ public void testSizeCallbackIsCalledSynchronouslyIfLayoutParamsConcreteSizeSet()
verify(cb).onSizeReady(eq(dimens), eq(dimens));
}
+ private void setDisplayDimens(Integer width, Integer height) {
+ WindowManager windowManager = (WindowManager) Robolectric.application.getSystemService(Context.WINDOW_SERVICE);
+ ShadowDisplay shadowDisplay = Robolectric.shadowOf(windowManager.getDefaultDisplay());
+ if (width != null) {
+ shadowDisplay.setWidth(width);
+ }
+
+ if (height != null) {
+ shadowDisplay.setHeight(height);
+ }
+ }
+
+ private void setDisplayWidth(int width) {
+ setDisplayDimens(width, null);
+ }
+
+ private void setDisplayHeight(int height) {
+ setDisplayDimens(null, height);
+ }
+
@Test
- public void testSizeCallbackIsCalledSynchronouslyWithScreenSizeIfLayoutParamsWrapContent() {
+ public void testBothParamsWrapContent() {
LayoutParams layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
view.setLayoutParams(layoutParams);
- int width = 1234;
- int height = 674;
- WindowManager windowManager = (WindowManager) view.getContext()
- .getSystemService(Context.WINDOW_SERVICE);
- ShadowDisplay shadowDisplay = Robolectric.shadowOf(windowManager.getDefaultDisplay());
- shadowDisplay.setWidth(width);
- shadowDisplay.setHeight(height);
+ int width = 123;
+ int height = 456;
+ setDisplayDimens(width, height);
+ SizeReadyCallback cb = mock(SizeReadyCallback.class);
+ target.getSize(cb);
+
+ verify(cb).onSizeReady(eq(width), eq(height));
+ }
+
+ @Test
+ public void testWrapContentWidthWithValidHeight() {
+ int displayWidth = 500;
+ setDisplayWidth(displayWidth);
+
+ int height = 100;
+ LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, height);
+ view.setLayoutParams(params);
SizeReadyCallback cb = mock(SizeReadyCallback.class);
target.getSize(cb);
+ verify(cb).onSizeReady(eq(displayWidth), eq(height));
+ }
+
+ @Test
+ public void testWrapContentHeightWithValidWidth() {
+ int displayHeight = 700;
+ setDisplayHeight(displayHeight);
+ int width = 100;
+ LayoutParams params = new LayoutParams(width, LayoutParams.WRAP_CONTENT);
+ view.setLayoutParams(params);
+
+ SizeReadyCallback cb = mock(SizeReadyCallback.class);
+ target.getSize(cb);
+
+ verify(cb).onSizeReady(eq(width), eq(displayHeight));
+ }
+
+ @Test
+ public void testWrapContentWidthWithMatchParentHeight() {
+ int displayWidth = 1234;
+ setDisplayWidth(displayWidth);
+
+ LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
+ view.setLayoutParams(params);
+
+ SizeReadyCallback cb = mock(SizeReadyCallback.class);
+ target.getSize(cb);
+
+ verify(cb, never()).onSizeReady(anyInt(), anyInt());
+
+ int height = 32;
+ SizedShadowView shadowView = Robolectric.shadowOf_(view);
+ shadowView.setHeight(height);
+
+ PreDrawShadowViewTreeObserver shadowObserver = Robolectric.shadowOf_(view.getViewTreeObserver());
+ shadowObserver.fireOnPreDrawListeners();
+
+ verify(cb).onSizeReady(eq(displayWidth), eq(height));
+ }
+
+ @Test
+ public void testWrapContentHeightWithMatchParentWidth() {
+ int displayHeight = 5812;
+ setDisplayHeight(displayHeight);
+
+ LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
+ view.setLayoutParams(params);
+
+ SizeReadyCallback cb = mock(SizeReadyCallback.class);
+ target.getSize(cb);
+
+ verify(cb, never()).onSizeReady(anyInt(), anyInt());
+
+ int width = 32;
+ SizedShadowView shadowView = Robolectric.shadowOf_(view);
+ shadowView.setWidth(width);
+
+ PreDrawShadowViewTreeObserver shadowObserver = Robolectric.shadowOf_(view.getViewTreeObserver());
+ shadowObserver.fireOnPreDrawListeners();
+
+ verify(cb).onSizeReady(eq(width), eq(displayHeight));
+ }
+
+ @Test
+ public void testMatchParentWidthAndHeight() {
+ LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
+ view.setLayoutParams(params);
+
+ SizeReadyCallback cb = mock(SizeReadyCallback.class);
+ target.getSize(cb);
+
+ verify(cb, never()).onSizeReady(anyInt(), anyInt());
+
+ int width = 32;
+ int height = 45;
+ SizedShadowView shadowView = Robolectric.shadowOf_(view);
+ shadowView.setWidth(width);
+ shadowView.setHeight(height);
+
+ PreDrawShadowViewTreeObserver shadowObserver = Robolectric.shadowOf_(view.getViewTreeObserver());
+ shadowObserver.fireOnPreDrawListeners();
+
verify(cb).onSizeReady(eq(width), eq(height));
}
@@ -299,7 +411,7 @@ public void testDoesNotThrowOnPreDrawIfViewTreeObserverIsDead() {
@Test(expected = NullPointerException.class)
public void testThrowsIfGivenNullView() {
- ViewTarget viewTarget = new TestViewTarget(null);
+ new TestViewTarget(null);
}
@Implements(ViewTreeObserver.class)
diff --git a/library/src/main/java/com/bumptech/glide/GenericRequestBuilder.java b/library/src/main/java/com/bumptech/glide/GenericRequestBuilder.java
index 65ba231d2c..b8eb0fc686 100644
--- a/library/src/main/java/com/bumptech/glide/GenericRequestBuilder.java
+++ b/library/src/main/java/com/bumptech/glide/GenericRequestBuilder.java
@@ -643,8 +643,7 @@ public Target into(ImageView view) {
break;
//$CASES-OMITTED$
default:
- // silently ignore
- break;
+ // Do nothing.
}
}
@@ -654,10 +653,10 @@ public Target into(ImageView view) {
/**
* Returns a future that can be used to do a blocking get on a background thread.
*
- * @param width The desired width in pixels (note this will be overriden by {@link #override(int, int)} if
- * previously called).
- * @param height The desired height in pixels (note this will be overriden by {@link #override(int, int)}}
- * if previously called).
+ * @param width The desired width in pixels, or {@link Target#SIZE_ORIGINAL}. This will be overridden by
+ * {@link #override * (int, int)} if previously called.
+ * @param height The desired height in pixels, or {@link Target#SIZE_ORIGINAL}. This will be overridden by
+ * {@link #override * (int, int)}} if previously called).
*
* @see Glide#clear(com.bumptech.glide.request.FutureTarget)
*
@@ -689,13 +688,34 @@ public void run() {
* available quickly.
*
*
+ *
* @see com.bumptech.glide.ListPreloader
+ *
+ * @param width The desired width in pixels, or {@link Target#SIZE_ORIGINAL}. This will be overridden by
+ * {@link #override * (int, int)} if previously called.
+ * @param height The desired height in pixels, or {@link Target#SIZE_ORIGINAL}. This will be overridden by
+ * {@link #override * (int, int)}} if previously called).
+ * @return A {@link Target} that can be used to cancel the load via
+ * {@link Glide#clear(com.bumptech.glide.request.target.Target)}.
*/
public Target preload(int width, int height) {
final PreloadTarget target = PreloadTarget.obtain(width, height);
return into(target);
}
+ /**
+ * Preloads the resource into the cache using {@link Target#SIZE_ORIGINAL} as the target width and height.
+ * Equivalent to calling {@link #preload(int, int)} with {@link Target#SIZE_ORIGINAL} as the width and height.
+ *
+ * @see #preload(int, int)
+ *
+ * @return A {@link Target} that can be used to cancel the load via
+ * {@link Glide#clear(com.bumptech.glide.request.target.Target)}.
+ */
+ public Target preload() {
+ return preload(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL);
+ }
+
void applyCenterCrop() {
// To be implemented by subclasses when possible.
}
diff --git a/library/src/main/java/com/bumptech/glide/load/ResourceDecoder.java b/library/src/main/java/com/bumptech/glide/load/ResourceDecoder.java
index 3de450f632..b80e8080e3 100644
--- a/library/src/main/java/com/bumptech/glide/load/ResourceDecoder.java
+++ b/library/src/main/java/com/bumptech/glide/load/ResourceDecoder.java
@@ -26,8 +26,12 @@ public interface ResourceDecoder {
*
*
* @param source The data the resource should be decoded from.
- * @param width The ideal width in pixels of the decoded resource.
- * @param height The ideal height in pixels of the decoded resource.
+ * @param width The ideal width in pixels of the decoded resource, or
+ * {@link com.bumptech.glide.request.target.Target#SIZE_ORIGINAL} to indicate the original resource
+ * width.
+ * @param height The ideal height in pixels of the decoded resource, or
+ * {@link com.bumptech.glide.request.target.Target#SIZE_ORIGINAL} to indicate the original resource
+ * height.
* @throws IOException
*/
Resource decode(T source, int width, int height) throws IOException;
diff --git a/library/src/main/java/com/bumptech/glide/load/Transformation.java b/library/src/main/java/com/bumptech/glide/load/Transformation.java
index ae7f3ffef3..34db29e561 100644
--- a/library/src/main/java/com/bumptech/glide/load/Transformation.java
+++ b/library/src/main/java/com/bumptech/glide/load/Transformation.java
@@ -21,8 +21,12 @@ public interface Transformation {
*
*
* @param resource The resource to transform.
- * @param outWidth The width of the view or target the resource will be displayed in.
- * @param outHeight The height of the view or target the resource will be displayed in.
+ * @param outWidth The width of the view or target the resource will be displayed in, or
+ * {@link com.bumptech.glide.request.target.Target#SIZE_ORIGINAL} to indicate the original
+ * resource width.
+ * @param outHeight The height of the view or target the resource will be displayed in, or
+ * {@link com.bumptech.glide.request.target.Target#SIZE_ORIGINAL} to indicate the original
+ * resource height.
* @return The transformed resource.
*/
Resource transform(Resource resource, int outWidth, int outHeight);
diff --git a/library/src/main/java/com/bumptech/glide/load/model/ModelLoader.java b/library/src/main/java/com/bumptech/glide/load/model/ModelLoader.java
index 164f1d7235..4c2e43ff4a 100644
--- a/library/src/main/java/com/bumptech/glide/load/model/ModelLoader.java
+++ b/library/src/main/java/com/bumptech/glide/load/model/ModelLoader.java
@@ -37,8 +37,12 @@ public interface ModelLoader {
*
*
* @param model The model representing the resource.
- * @param width The width in pixels of the view or target the resource will be loaded into
- * @param height The height in pixels of the view or target the resource will be loaded into
+ * @param width The width in pixels of the view or target the resource will be loaded into, or
+ * {@link com.bumptech.glide.request.target.Target#SIZE_ORIGINAL} to indicate that the resource should
+ * be loaded at its original width.
+ * @param height The height in pixels of the view or target the resource will be loaded into, or
+ * {@link com.bumptech.glide.request.target.Target#SIZE_ORIGINAL} to indicate that the resource should
+ * be loaded at its original height.
* @return A {@link DataFetcher} that can obtain the data the resource can be decoded from if the resource is not
* cached, or null if no valid {@link com.bumptech.glide.load.data.DataFetcher} could be constructed.
*/
diff --git a/library/src/main/java/com/bumptech/glide/load/resource/bitmap/BitmapTransformation.java b/library/src/main/java/com/bumptech/glide/load/resource/bitmap/BitmapTransformation.java
index c3624b1c92..d119964fb6 100644
--- a/library/src/main/java/com/bumptech/glide/load/resource/bitmap/BitmapTransformation.java
+++ b/library/src/main/java/com/bumptech/glide/load/resource/bitmap/BitmapTransformation.java
@@ -7,6 +7,7 @@
import com.bumptech.glide.load.Transformation;
import com.bumptech.glide.load.engine.Resource;
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
+import com.bumptech.glide.request.target.Target;
/**
* A simple {@link com.bumptech.glide.load.Transformation} for transforming {@link android.graphics.Bitmap}s that
@@ -42,12 +43,15 @@ public BitmapTransformation(BitmapPool bitmapPool) {
@Override
public final Resource transform(Resource resource, int outWidth, int outHeight) {
- if (outWidth <= 0 || outHeight <= 0) {
+ if ((outWidth <= 0 && outWidth != Target.SIZE_ORIGINAL)
+ || (outHeight <= 0 && outHeight != Target.SIZE_ORIGINAL)) {
throw new IllegalArgumentException("Cannot apply transformation on width: " + outWidth + " or height: "
- + outHeight + " less than or equal to zero");
+ + outHeight + " less than or equal to zero and not Target.SIZE_ORIGINAL");
}
Bitmap toTransform = resource.get();
- Bitmap transformed = transform(bitmapPool, toTransform, outWidth, outHeight);
+ int targetWidth = outWidth == Target.SIZE_ORIGINAL ? toTransform.getWidth() : outWidth;
+ int targetHeight = outHeight == Target.SIZE_ORIGINAL ? toTransform.getHeight() : outHeight;
+ Bitmap transformed = transform(bitmapPool, toTransform, targetWidth, targetHeight);
final Resource result;
if (toTransform.equals(transformed)) {
@@ -63,13 +67,19 @@ public final Resource transform(Resource resource, int outWidth,
* Transforms the given {@link android.graphics.Bitmap} based on the given dimensions and returns the transformed
* result.
*
+ *
+ * outWidth and outHeight will never be {@link com.bumptech.glide.request.target.Target#SIZE_ORIGINAL}, this
+ * class converts them to be the size of the Bitmap we're going to transform before calling this method.
+ *
+ *
* @param pool A {@link com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool} that can be used to obtain and
* return intermediate {@link Bitmap}s used in this transformation. For every
* {@link android.graphics.Bitmap} obtained from the pool during this transformation, a
* {@link android.graphics.Bitmap} must also be returned.
* @param toTransform The {@link android.graphics.Bitmap} to transform.
- * @param outWidth The ideal width of the transformed bitmap (does not need to match exactly).
- * @param outHeight The ideal height of the transformed bitmap (does not need to match exactly).
+ * @param outWidth The ideal width of the transformed bitmap (the transformed width does not need to match exactly).
+ * @param outHeight The ideal height of the transformed bitmap (the transformed heightdoes not need to match
+ * exactly).
*/
protected abstract Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight);
}
diff --git a/library/src/main/java/com/bumptech/glide/load/resource/bitmap/Downsampler.java b/library/src/main/java/com/bumptech/glide/load/resource/bitmap/Downsampler.java
index 904a7c45b8..4185c54b9e 100644
--- a/library/src/main/java/com/bumptech/glide/load/resource/bitmap/Downsampler.java
+++ b/library/src/main/java/com/bumptech/glide/load/resource/bitmap/Downsampler.java
@@ -8,6 +8,7 @@
import com.bumptech.glide.load.DecodeFormat;
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
+import com.bumptech.glide.request.target.Target;
import com.bumptech.glide.util.ByteArrayPool;
import com.bumptech.glide.util.ExceptionCatchingInputStream;
import com.bumptech.glide.util.Util;
@@ -168,13 +169,16 @@ public Bitmap decode(InputStream is, BitmapPool pool, int outWidth, int outHeigh
}
private int getRoundedSampleSize(int degreesToRotate, int inWidth, int inHeight, int outWidth, int outHeight) {
+ int targetHeight = outHeight == Target.SIZE_ORIGINAL ? inHeight : outHeight;
+ int targetWidth = outWidth == Target.SIZE_ORIGINAL ? inWidth : outWidth;
+
final int exactSampleSize;
if (degreesToRotate == 90 || degreesToRotate == 270) {
// If we're rotating the image +-90 degrees, we need to downsample accordingly so the image width is
// decreased to near our target's height and the image height is decreased to near our target width.
- exactSampleSize = getSampleSize(inHeight, inWidth, outWidth, outHeight);
+ exactSampleSize = getSampleSize(inHeight, inWidth, targetWidth, targetHeight);
} else {
- exactSampleSize = getSampleSize(inWidth, inHeight, outWidth, outHeight);
+ exactSampleSize = getSampleSize(inWidth, inHeight, targetWidth, targetHeight);
}
// BitmapFactory only accepts powers of 2, so it will round down to the nearest power of two that is less than
@@ -264,10 +268,10 @@ private static Bitmap.Config getConfig(InputStream is, DecodeFormat format) {
*
* @see android.graphics.BitmapFactory.Options#inSampleSize
*
- * @param inWidth The width of the image to be downsampled.
- * @param inHeight The height of the image to be downsampled.
- * @param outWidth The width of the view/target the image will be displayed in.
- * @param outHeight The height of the view/target the imag will be displayed in.
+ * @param inWidth The width in pixels of the image to be downsampled.
+ * @param inHeight The height in piexels of the image to be downsampled.
+ * @param outWidth The width in pixels of the view/target the image will be displayed in.
+ * @param outHeight The height in pixels of the view/target the imag will be displayed in.
* @return An integer to pass in to {@link BitmapFactory#decodeStream(java.io.InputStream, android.graphics.Rect,
* android.graphics.BitmapFactory.Options)}.
*/
diff --git a/library/src/main/java/com/bumptech/glide/request/target/AppWidgetTarget.java b/library/src/main/java/com/bumptech/glide/request/target/AppWidgetTarget.java
index 3dc2207160..592de62820 100644
--- a/library/src/main/java/com/bumptech/glide/request/target/AppWidgetTarget.java
+++ b/library/src/main/java/com/bumptech/glide/request/target/AppWidgetTarget.java
@@ -32,9 +32,9 @@ public class AppWidgetTarget extends SimpleTarget {
* @param context Context to use in the AppWidgetManager initialization.
* @param remoteViews RemoteViews object which contains the ImageView that will load the bitmap.
* @param viewId The id of the ImageView view that will load the image.
- * @param width Desired width of the bitmap that will be loaded.(Need to be manually set
+ * @param width Desired width in pixels of the bitmap that will be loaded. (Needs to be manually set
* because of RemoteViews limitations.)
- * @param height Desired height of the bitmap that will be loaded. (Need to be manually set
+ * @param height Desired height in pixels of the bitmap that will be loaded. (Needs to be manually set
* because of RemoteViews limitations.)
* @param widgetIds The int[] that contains the widget ids of an application.
*/
@@ -61,8 +61,8 @@ public AppWidgetTarget(Context context, RemoteViews remoteViews, int viewId, int
}
/**
- * Constructor using an int array of widgetIds to get a handle on the Widget in order to update it when an override
- * width and height have been set been set.
+ * Constructor using an int array of widgetIds to get a handle on the Widget in order to update it that uses
+ * {@link #SIZE_ORIGINAL} as the target width and height.
*
* @param context Context to use in the AppWidgetManager initialization.
* @param remoteViews RemoteViews object which contains the ImageView that will load the bitmap.
@@ -70,7 +70,7 @@ public AppWidgetTarget(Context context, RemoteViews remoteViews, int viewId, int
* @param widgetIds The int[] that contains the widget ids of an application.
*/
public AppWidgetTarget(Context context, RemoteViews remoteViews, int viewId, int... widgetIds) {
- this(context, remoteViews, viewId, INVALID_SIZE, INVALID_SIZE, widgetIds);
+ this(context, remoteViews, viewId, SIZE_ORIGINAL, SIZE_ORIGINAL, widgetIds);
}
/**
@@ -79,9 +79,9 @@ public AppWidgetTarget(Context context, RemoteViews remoteViews, int viewId, int
* @param context Context to use in the AppWidgetManager initialization.
* @param remoteViews RemoteViews object which contains the ImageView that will load the bitmap.
* @param viewId The id of the ImageView view that will load the image.
- * @param width Desired width of the bitmap that will be loaded.(Need to be manually set
+ * @param width Desired width in pixels of the bitmap that will be loaded. (Needs to be manually set
* because of RemoteViews limitations.)
- * @param height Desired height of the bitmap that will be loaded. (Need to be manually set
+ * @param height Desired height in pixels of the bitmap that will be loaded. (Needs to be manually set
* because of RemoteViews limitations.)
* @param componentName The ComponentName that refers to our AppWidget.
*/
@@ -106,7 +106,7 @@ public AppWidgetTarget(Context context, RemoteViews remoteViews, int viewId, int
/**
* Constructor using a ComponentName, when override has been set to get a handle on the Widget in order to update
- * it.
+ * it that uses {@link #SIZE_ORIGINAL} as the target width and height.
*
* @param context Context to use in the AppWidgetManager initialization.
* @param remoteViews RemoteViews object which contains the ImageView that will load the bitmap.
@@ -114,7 +114,7 @@ public AppWidgetTarget(Context context, RemoteViews remoteViews, int viewId, int
* @param componentName The ComponentName that refers to our AppWidget.
*/
public AppWidgetTarget(Context context, RemoteViews remoteViews, int viewId, ComponentName componentName) {
- this(context, remoteViews, viewId, INVALID_SIZE, INVALID_SIZE, componentName);
+ this(context, remoteViews, viewId, SIZE_ORIGINAL, SIZE_ORIGINAL, componentName);
}
/**
diff --git a/library/src/main/java/com/bumptech/glide/request/target/NotificationTarget.java b/library/src/main/java/com/bumptech/glide/request/target/NotificationTarget.java
index ff4d4c3147..5f1f88b5bb 100644
--- a/library/src/main/java/com/bumptech/glide/request/target/NotificationTarget.java
+++ b/library/src/main/java/com/bumptech/glide/request/target/NotificationTarget.java
@@ -27,7 +27,7 @@ public class NotificationTarget extends SimpleTarget {
/**
* Constructor using a Notification object and a notificationId to get a handle on the Notification in order to
- * update it when an override width and height have been set.
+ * update it that uses {@link #SIZE_ORIGINAL} as the target width and height.
*
* @param context Context to use in the AppWidgetManager initialization.
* @param remoteViews RemoteViews object which contains the ImageView that will load the bitmap.
@@ -37,7 +37,7 @@ public class NotificationTarget extends SimpleTarget {
*/
public NotificationTarget(Context context, RemoteViews remoteViews, int viewId, Notification notification,
int notificationId) {
- this(context, remoteViews, viewId, INVALID_SIZE, INVALID_SIZE, notification, notificationId);
+ this(context, remoteViews, viewId, SIZE_ORIGINAL, SIZE_ORIGINAL, notification, notificationId);
}
/**
diff --git a/library/src/main/java/com/bumptech/glide/request/target/SimpleTarget.java b/library/src/main/java/com/bumptech/glide/request/target/SimpleTarget.java
index c6487e9655..c55e29ab86 100644
--- a/library/src/main/java/com/bumptech/glide/request/target/SimpleTarget.java
+++ b/library/src/main/java/com/bumptech/glide/request/target/SimpleTarget.java
@@ -24,24 +24,14 @@
* @param The type of resource that this target will receive.
*/
public abstract class SimpleTarget extends BaseTarget {
- /** A constant indicating an invalid pixel size. */
- protected static final int INVALID_SIZE = -1;
-
private final int width;
private final int height;
/**
- * Constructor for the target that assumes you will have called
- * {@link com.bumptech.glide.GenericRequestBuilder#override(int, int)} on the request builder this target is given
- * to.
- *
- *
- * Requests that load into this target will throw an {@link java.lang.IllegalArgumentException} if
- * {@link com.bumptech.glide.GenericRequestBuilder#override(int, int)} was not called on the request builder.
- *
+ * Constructor for the target that uses {@link Target#SIZE_ORIGINAL} as the target width and height.
*/
public SimpleTarget() {
- this(INVALID_SIZE, INVALID_SIZE);
+ this(SIZE_ORIGINAL, SIZE_ORIGINAL);
}
/**
diff --git a/library/src/main/java/com/bumptech/glide/request/target/SizeReadyCallback.java b/library/src/main/java/com/bumptech/glide/request/target/SizeReadyCallback.java
index 22b41180db..f492caf524 100644
--- a/library/src/main/java/com/bumptech/glide/request/target/SizeReadyCallback.java
+++ b/library/src/main/java/com/bumptech/glide/request/target/SizeReadyCallback.java
@@ -8,8 +8,10 @@ public interface SizeReadyCallback {
/**
* A callback called on the main thread.
*
- * @param width The width in pixels of the target.
- * @param height The height in pixels of the target.
+ * @param width The width in pixels of the target, or {@link Target#SIZE_ORIGINAL} to indicate that we want the
+ * resource at its original width.
+ * @param height The height in pixels of the target, or {@link Target#SIZE_ORIGINAL} to indicate that we want the
+ * resource at its original height.
*/
void onSizeReady(int width, int height);
}
diff --git a/library/src/main/java/com/bumptech/glide/request/target/Target.java b/library/src/main/java/com/bumptech/glide/request/target/Target.java
index 4613206fb1..4ddd8cad5a 100644
--- a/library/src/main/java/com/bumptech/glide/request/target/Target.java
+++ b/library/src/main/java/com/bumptech/glide/request/target/Target.java
@@ -27,6 +27,10 @@
* @param The type of resource the target can display.
*/
public interface Target extends LifecycleListener {
+ /**
+ * Indicates that we want the resource in its original unmodified width and/or height.
+ */
+ int SIZE_ORIGINAL = Integer.MIN_VALUE;
/**
* A lifecycle callback that is called when a load is started.
diff --git a/library/src/main/java/com/bumptech/glide/request/target/ViewTarget.java b/library/src/main/java/com/bumptech/glide/request/target/ViewTarget.java
index dcf7f5d0e5..9497a7d96e 100644
--- a/library/src/main/java/com/bumptech/glide/request/target/ViewTarget.java
+++ b/library/src/main/java/com/bumptech/glide/request/target/ViewTarget.java
@@ -1,10 +1,13 @@
package com.bumptech.glide.request.target;
+import android.annotation.TargetApi;
import android.content.Context;
+import android.graphics.Point;
+import android.os.Build;
import android.util.Log;
import android.view.Display;
import android.view.View;
-import android.view.ViewGroup;
+import android.view.ViewGroup.LayoutParams;
import android.view.ViewTreeObserver;
import android.view.WindowManager;
@@ -58,7 +61,7 @@ public T getView() {
/**
* Determines the size of the view by first checking {@link android.view.View#getWidth()} and
* {@link android.view.View#getHeight()}. If one or both are zero, it then checks the view's
- * {@link android.view.ViewGroup.LayoutParams}. If one or both of the params width and height are less than or
+ * {@link LayoutParams}. If one or both of the params width and height are less than or
* equal to zero, it then adds an {@link android.view.ViewTreeObserver.OnPreDrawListener} which waits until the view
* has been measured before calling the callback with the view's drawn width and height.
*
@@ -111,9 +114,14 @@ public String toString() {
}
private static class SizeDeterminer {
+ // Some negative sizes (WRAP_CONTENT) are valid, 0 is never valid.
+ private static final int PENDING_SIZE = 0;
+
private final View view;
private final List cbs = new ArrayList();
+
private SizeDeterminerLayoutListener layoutListener;
+ private Point displayDimens;
public SizeDeterminer(View view) {
this.view = view;
@@ -131,48 +139,31 @@ private void checkCurrentDimens() {
return;
}
- boolean calledCallback = true;
- ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
- if (isViewSizeValid()) {
- notifyCbs(view.getWidth(), view.getHeight());
- } else if (isLayoutParamsSizeValid()) {
- notifyCbs(layoutParams.width, layoutParams.height);
- } else {
- calledCallback = false;
+ int currentWidth = getViewWidthOrParam();
+ int currentHeight = getViewHeightOrParam();
+ if (!isSizeValid(currentWidth) || !isSizeValid(currentHeight)) {
+ return;
}
- if (calledCallback) {
- // Keep a reference to the layout listener and remove it here
- // rather than having the observer remove itself because the observer
- // we add the listener to will be almost immediately merged into
- // another observer and will therefore never be alive. If we instead
- // keep a reference to the listener and remove it here, we get the
- // current view tree observer and should succeed.
- ViewTreeObserver observer = view.getViewTreeObserver();
- if (observer.isAlive()) {
- observer.removeOnPreDrawListener(layoutListener);
- }
- layoutListener = null;
+ notifyCbs(currentWidth, currentHeight);
+ // Keep a reference to the layout listener and remove it here
+ // rather than having the observer remove itself because the observer
+ // we add the listener to will be almost immediately merged into
+ // another observer and will therefore never be alive. If we instead
+ // keep a reference to the listener and remove it here, we get the
+ // current view tree observer and should succeed.
+ ViewTreeObserver observer = view.getViewTreeObserver();
+ if (observer.isAlive()) {
+ observer.removeOnPreDrawListener(layoutListener);
}
+ layoutListener = null;
}
public void getSize(SizeReadyCallback cb) {
- ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
- if (isViewSizeValid()) {
- cb.onSizeReady(view.getWidth(), view.getHeight());
- } else if (isLayoutParamsSizeValid()) {
- cb.onSizeReady(layoutParams.width, layoutParams.height);
- } else if (isUsingWrapContent()) {
- WindowManager windowManager =
- (WindowManager) view.getContext().getSystemService(Context.WINDOW_SERVICE);
- Display display = windowManager.getDefaultDisplay();
- @SuppressWarnings("deprecation") final int width = display.getWidth(), height = display.getHeight();
- if (Log.isLoggable(TAG, Log.WARN)) {
- Log.w(TAG, "Trying to load image into ImageView using WRAP_CONTENT, defaulting to screen"
- + " dimensions: [" + width + "x" + height + "]. Give the view an actual width and height "
- + " for better performance.");
- }
- cb.onSizeReady(width, height);
+ int currentWidth = getViewWidthOrParam();
+ int currentHeight = getViewHeightOrParam();
+ if (isSizeValid(currentWidth) && isSizeValid(currentHeight)) {
+ cb.onSizeReady(currentWidth, currentHeight);
} else {
// We want to notify callbacks in the order they were added and we only expect one or two callbacks to
// be added a time, so a List is a reasonable choice.
@@ -187,19 +178,56 @@ public void getSize(SizeReadyCallback cb) {
}
}
- private boolean isViewSizeValid() {
- return view.getWidth() > 0 && view.getHeight() > 0;
+ private int getViewHeightOrParam() {
+ final LayoutParams layoutParams = view.getLayoutParams();
+ if (isSizeValid(view.getHeight())) {
+ return view.getHeight();
+ } else if (layoutParams != null) {
+ return getSizeForParam(layoutParams.height, true /*isHeight*/);
+ } else {
+ return PENDING_SIZE;
+ }
+ }
+
+ private int getViewWidthOrParam() {
+ final LayoutParams layoutParams = view.getLayoutParams();
+ if (isSizeValid(view.getWidth())) {
+ return view.getWidth();
+ } else if (layoutParams != null) {
+ return getSizeForParam(layoutParams.width, false /*isHeight*/);
+ } else {
+ return PENDING_SIZE;
+ }
+ }
+
+ private int getSizeForParam(int param, boolean isHeight) {
+ if (param == LayoutParams.WRAP_CONTENT) {
+ Point displayDimens = getDisplayDimens();
+ return isHeight ? displayDimens.y : displayDimens.x;
+ } else {
+ return param;
+ }
}
- private boolean isUsingWrapContent() {
- final ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
- return layoutParams != null && (layoutParams.width == ViewGroup.LayoutParams.WRAP_CONTENT
- || layoutParams.height == ViewGroup.LayoutParams.WRAP_CONTENT);
+ @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2)
+ @SuppressWarnings("deprecation")
+ private Point getDisplayDimens() {
+ if (displayDimens != null) {
+ return displayDimens;
+ }
+ WindowManager windowManager = (WindowManager) view.getContext().getSystemService(Context.WINDOW_SERVICE);
+ Display display = windowManager.getDefaultDisplay();
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
+ displayDimens = new Point();
+ display.getSize(displayDimens);
+ } else {
+ displayDimens = new Point(display.getWidth(), display.getHeight());
+ }
+ return displayDimens;
}
- private boolean isLayoutParamsSizeValid() {
- final ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
- return layoutParams != null && layoutParams.width > 0 && layoutParams.height > 0;
+ private boolean isSizeValid(int size) {
+ return size > 0 || size == LayoutParams.WRAP_CONTENT;
}
private static class SizeDeterminerLayoutListener implements ViewTreeObserver.OnPreDrawListener {