Summary:
The nodes version of D3364550. The only difference is that here we
don't get `onSizeChanged` but `onBoundsChanged`, and we need to compute the
height/width of the target image from those bounds. ahmedre please let me know
if any of these assumptions are in any way incorrect.

Reviewed By: ahmedre

Differential Revision: D3424843
This commit is contained in:
Andrei Coman 2016-06-16 07:13:57 -07:00 коммит произвёл Ahmed El-Helw
Родитель f2a6570b07
Коммит c61aafe95d
5 изменённых файлов: 136 добавлений и 27 удалений

Просмотреть файл

@ -14,6 +14,7 @@ import javax.annotation.Nullable;
import android.content.Context; import android.content.Context;
import com.facebook.drawee.drawable.ScalingUtils.ScaleType; import com.facebook.drawee.drawable.ScalingUtils.ScaleType;
import com.facebook.react.bridge.ReadableArray;
/** /**
* Common interface for DrawImageWithPipeline and DrawImageWithDrawee. * Common interface for DrawImageWithPipeline and DrawImageWithDrawee.
@ -28,7 +29,7 @@ import com.facebook.drawee.drawable.ScalingUtils.ScaleType;
/** /**
* Assigns a new image source to the DrawImage, or null to clear the image request. * Assigns a new image source to the DrawImage, or null to clear the image request.
*/ */
void setSource(Context context, @Nullable String source); void setSource(Context context, @Nullable ReadableArray sources);
/** /**
* Assigns a tint color to apply to the image drawn. * Assigns a tint color to apply to the image drawn.

Просмотреть файл

@ -11,6 +11,9 @@ package com.facebook.react.flat;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.HashMap;
import java.util.Map;
import android.content.Context; import android.content.Context;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.PorterDuff; import android.graphics.PorterDuff;
@ -23,6 +26,8 @@ import com.facebook.drawee.generic.GenericDraweeHierarchy;
import com.facebook.drawee.generic.RoundingParams; import com.facebook.drawee.generic.RoundingParams;
import com.facebook.imagepipeline.request.ImageRequest; import com.facebook.imagepipeline.request.ImageRequest;
import com.facebook.infer.annotation.Assertions; import com.facebook.infer.annotation.Assertions;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.views.image.ImageLoadEvent; import com.facebook.react.views.image.ImageLoadEvent;
import com.facebook.react.views.image.ImageResizeMode; import com.facebook.react.views.image.ImageResizeMode;
import com.facebook.react.views.image.ReactImageView; import com.facebook.react.views.image.ReactImageView;
@ -34,7 +39,8 @@ import com.facebook.react.views.image.ReactImageView;
/* package */ final class DrawImageWithDrawee extends AbstractDrawCommand /* package */ final class DrawImageWithDrawee extends AbstractDrawCommand
implements DrawImage, ControllerListener { implements DrawImage, ControllerListener {
private @Nullable String mSource; private @Nullable Map<String, Double> mSources;
private @Nullable String mImageSource;
private @Nullable Context mContext; private @Nullable Context mContext;
private @Nullable DraweeRequestHelper mRequestHelper; private @Nullable DraweeRequestHelper mRequestHelper;
private @Nullable PorterDuffColorFilter mColorFilter; private @Nullable PorterDuffColorFilter mColorFilter;
@ -48,12 +54,28 @@ import com.facebook.react.views.image.ReactImageView;
@Override @Override
public boolean hasImageRequest() { public boolean hasImageRequest() {
return mSource != null; return mSources != null && !mSources.isEmpty();
} }
@Override @Override
public void setSource(Context context, @Nullable String source) { public void setSource(Context context, @Nullable ReadableArray sources) {
mSource = source; if (mSources == null) {
mSources = new HashMap<>();
}
mSources.clear();
if (sources != null && sources.size() != 0) {
// Optimize for the case where we have just one uri, case in which we don't need the sizes
if (sources.size() == 1) {
mSources.put(sources.getMap(0).getString("uri"), 0.0d);
} else {
for (int idx = 0; idx < sources.size(); idx++) {
ReadableMap source = sources.getMap(idx);
mSources.put(
source.getString("uri"),
source.getDouble("width") * source.getDouble("height"));
}
}
}
mContext = context; mContext = context;
} }
@ -202,23 +224,36 @@ import com.facebook.react.views.image.ReactImageView;
@Override @Override
protected void onBoundsChanged() { protected void onBoundsChanged() {
super.onBoundsChanged(); super.onBoundsChanged();
maybeComputeRequestHelper(); computeRequestHelper();
} }
private void maybeComputeRequestHelper() { private void computeRequestHelper() {
if (mRequestHelper != null) { mImageSource = getSourceImage();
return; if (mImageSource == null) {
}
if (mSource == null) {
mRequestHelper = null; mRequestHelper = null;
return; return;
} }
ImageRequest imageRequest = ImageRequest imageRequest =
ImageRequestHelper.createImageRequest(Assertions.assertNotNull(mContext), mSource); ImageRequestHelper.createImageRequest(Assertions.assertNotNull(mContext),
mImageSource);
mRequestHelper = new DraweeRequestHelper(Assertions.assertNotNull(imageRequest), this); mRequestHelper = new DraweeRequestHelper(Assertions.assertNotNull(imageRequest), this);
} }
private @Nullable String getSourceImage() {
if (mSources == null || mSources.isEmpty()) {
return null;
}
if (hasMultipleSources()) {
final double targetImageSize = (getRight() - getLeft()) * (getBottom() - getTop());
return MultiSourceImageHelper.getImageSourceFromMultipleSources(targetImageSize, mSources);
}
return mSources.keySet().iterator().next();
}
private boolean hasMultipleSources() {
return Assertions.assertNotNull(mSources).size() > 1;
}
private boolean shouldDisplayBorder() { private boolean shouldDisplayBorder() {
return mBorderColor != 0 || mBorderRadius >= 0.5f; return mBorderColor != 0 || mBorderRadius >= 0.5f;
} }

Просмотреть файл

@ -11,6 +11,9 @@ package com.facebook.react.flat;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.HashMap;
import java.util.Map;
import android.content.Context; import android.content.Context;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.BitmapShader; import android.graphics.BitmapShader;
@ -25,6 +28,8 @@ import android.graphics.Shader;
import com.facebook.drawee.drawable.ScalingUtils.ScaleType; import com.facebook.drawee.drawable.ScalingUtils.ScaleType;
import com.facebook.imagepipeline.request.ImageRequest; import com.facebook.imagepipeline.request.ImageRequest;
import com.facebook.infer.annotation.Assertions; import com.facebook.infer.annotation.Assertions;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.views.image.ImageResizeMode; import com.facebook.react.views.image.ImageResizeMode;
import com.facebook.react.views.image.ReactImageView; import com.facebook.react.views.image.ReactImageView;
@ -38,7 +43,8 @@ import com.facebook.react.views.image.ReactImageView;
private static final Paint PAINT = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG); private static final Paint PAINT = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
private static final int BORDER_BITMAP_PATH_DIRTY = 1 << 1; private static final int BORDER_BITMAP_PATH_DIRTY = 1 << 1;
private @Nullable String mSource; private @Nullable Map<String, Double> mSources;
private @Nullable String mImageSource;
private @Nullable Context mContext; private @Nullable Context mContext;
private final Matrix mTransform = new Matrix(); private final Matrix mTransform = new Matrix();
private ScaleType mScaleType = ImageResizeMode.defaultValue(); private ScaleType mScaleType = ImageResizeMode.defaultValue();
@ -61,8 +67,24 @@ import com.facebook.react.views.image.ReactImageView;
} }
@Override @Override
public void setSource(Context context, @Nullable String source) { public void setSource(Context context, @Nullable ReadableArray sources) {
mSource = source; if (mSources == null) {
mSources = new HashMap<>();
}
mSources.clear();
if (sources != null && sources.size() != 0) {
// Optimize for the case where we have just one uri, case in which we don't need the sizes
if (sources.size() == 1) {
mSources.put(sources.getMap(0).getString("uri"), 0.0d);
} else {
for (int idx = 0; idx < sources.size(); idx++) {
ReadableMap source = sources.getMap(idx);
mSources.put(
source.getString("uri"),
source.getDouble("width") * source.getDouble("height"));
}
}
}
mContext = context; mContext = context;
mBitmapShader = null; mBitmapShader = null;
} }
@ -183,7 +205,7 @@ import com.facebook.react.views.image.ReactImageView;
protected void onBoundsChanged() { protected void onBoundsChanged() {
super.onBoundsChanged(); super.onBoundsChanged();
setFlag(BORDER_BITMAP_PATH_DIRTY); setFlag(BORDER_BITMAP_PATH_DIRTY);
maybeComputeRequestHelper(); computeRequestHelper();
} }
@Override @Override
@ -203,20 +225,33 @@ import com.facebook.react.views.image.ReactImageView;
} }
} }
private void maybeComputeRequestHelper() { private void computeRequestHelper() {
if (mRequestHelper == null) { mImageSource = getSourceImage();
return; if (mImageSource == null) {
}
if (mSource == null) {
mRequestHelper = null; mRequestHelper = null;
return; return;
} }
ImageRequest imageRequest = ImageRequest imageRequest =
ImageRequestHelper.createImageRequest(Assertions.assertNotNull(mContext), mSource); ImageRequestHelper.createImageRequest(Assertions.assertNotNull(mContext),
mImageSource);
mRequestHelper = new PipelineRequestHelper(Assertions.assertNotNull(imageRequest)); mRequestHelper = new PipelineRequestHelper(Assertions.assertNotNull(imageRequest));
} }
private String getSourceImage() {
if (mSources == null || mSources.isEmpty()) {
return null;
}
if (hasMultipleSources()) {
final double targetImageSize = (getRight() - getLeft()) * (getBottom() - getTop());
return MultiSourceImageHelper.getImageSourceFromMultipleSources(targetImageSize, mSources);
}
return mSources.keySet().iterator().next();
}
private boolean hasMultipleSources() {
return Assertions.assertNotNull(mSources).size() > 1;
}
/* package */ void updateBounds(Bitmap bitmap) { /* package */ void updateBounds(Bitmap bitmap) {
Assertions.assumeNotNull(mCallback).invalidate(); Assertions.assumeNotNull(mCallback).invalidate();

Просмотреть файл

@ -0,0 +1,40 @@
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
package com.facebook.react.flat;
import javax.annotation.Nullable;
import java.util.Map;
/**
* Helper class for computing the source to be used for an Image.
*/
/* package */ class MultiSourceImageHelper {
/**
* Chooses the image source with the size closest to the target image size. Must be called only
* after the layout pass when the sizes of the target image have been computed, and when there
* are at least two sources to choose from.
*/
public static @Nullable String getImageSourceFromMultipleSources(
double targetImageSize,
Map<String, Double> sources) {
double bestPrecision = Double.MAX_VALUE;
String imageSource = null;
for (Map.Entry<String, Double> source : sources.entrySet()) {
final double precision = Math.abs(1.0 - (source.getValue()) / targetImageSize);
if (precision < bestPrecision) {
bestPrecision = precision;
imageSource = source.getKey();
}
}
return imageSource;
}
}

Просмотреть файл

@ -88,9 +88,7 @@ import com.facebook.react.views.image.ImageResizeMode;
@ReactProp(name = "src") @ReactProp(name = "src")
public void setSource(@Nullable ReadableArray sources) { public void setSource(@Nullable ReadableArray sources) {
final String source = getMutableDrawImage().setSource(getThemedContext(), sources);
(sources == null || sources.size() == 0) ? null : sources.getMap(0).getString("uri");
getMutableDrawImage().setSource(getThemedContext(), source);
} }
@ReactProp(name = "tintColor") @ReactProp(name = "tintColor")