mirror of
https://github.com/zoriya/react-native-svg.git
synced 2026-06-08 09:10:44 +00:00
add Image support for Android
This commit is contained in:
@@ -38,14 +38,14 @@ public class RNSVGGroupShadowNode extends RNSVGVirtualNode {
|
||||
if (opacity > MIN_OPACITY_FOR_DRAW) {
|
||||
saveAndSetupCanvas(canvas);
|
||||
clip(canvas, paint);
|
||||
RNSVGSvgViewShadowNode svg = getSvgView();
|
||||
RNSVGSvgViewShadowNode svg = getSvgShadowNode();
|
||||
|
||||
if (mAsClipPath == null) {
|
||||
for (int i = 0; i < getChildCount(); i++) {
|
||||
RNSVGVirtualNode child = (RNSVGVirtualNode) getChildAt(i);
|
||||
child.setDimensions(mWidth, mHeight);
|
||||
child.draw(canvas, paint, opacity);
|
||||
child.markUpdateSeen();
|
||||
//child.markUpdateSeen();
|
||||
|
||||
if (child.isTouchable() && !svg.touchable) {
|
||||
svg.touchable = true;
|
||||
@@ -87,13 +87,4 @@ public class RNSVGGroupShadowNode extends RNSVGVirtualNode {
|
||||
|
||||
return viewTag;
|
||||
}
|
||||
|
||||
private RNSVGSvgViewShadowNode getSvgView() {
|
||||
ReactShadowNode parent = getParent();
|
||||
|
||||
while (!(parent instanceof RNSVGSvgViewShadowNode)) {
|
||||
parent = parent.getParent();
|
||||
}
|
||||
return (RNSVGSvgViewShadowNode)parent;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,9 @@ import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.net.Uri;
|
||||
@@ -40,16 +42,18 @@ public class RNSVGImageShadowNode extends RNSVGPathShadowNode {
|
||||
private String mH;
|
||||
private ReadableMap mSrc;
|
||||
private Uri mUri;
|
||||
private Bitmap mBitmap;
|
||||
private boolean mLocalImage;
|
||||
private class BitmapWorkerTask extends AsyncTask<Integer, Void, Bitmap> {
|
||||
private final Canvas mCanvas;
|
||||
private final Paint mPaint;
|
||||
private int data = 0;
|
||||
|
||||
public BitmapWorkerTask(Canvas canvas, Paint paint) {
|
||||
private RNSVGSvgViewShadowNode mSvgShadowNode;
|
||||
public BitmapWorkerTask(Canvas canvas, Paint paint, RNSVGSvgViewShadowNode node) {
|
||||
// Use a WeakReference to ensure the ImageView can be garbage collected
|
||||
mCanvas = canvas;
|
||||
mPaint = paint;
|
||||
mSvgShadowNode = node;
|
||||
mSvgShadowNode.mBitmapCount++;
|
||||
}
|
||||
|
||||
// Decode image in background.
|
||||
@@ -75,15 +79,11 @@ public class RNSVGImageShadowNode extends RNSVGPathShadowNode {
|
||||
@Override
|
||||
protected void onPostExecute(@Nullable Bitmap bitmap) {
|
||||
if (bitmap != null) {
|
||||
float x = PropHelper.fromPercentageToFloat(mX, mWidth, 0, mScale);
|
||||
float y = PropHelper.fromPercentageToFloat(mY, mHeight, 0, mScale);
|
||||
float w = PropHelper.fromPercentageToFloat(mW, mWidth, 0, mScale);
|
||||
float h = PropHelper.fromPercentageToFloat(mH, mHeight, 0, mScale);
|
||||
|
||||
clip(mCanvas, mPaint);
|
||||
mCanvas.restoreToCount(1);
|
||||
mCanvas.drawBitmap(bitmap, null, new Rect((int)x, (int)y, (int)(x + w), (int)(y + h)), null);
|
||||
mCanvas.restoreToCount(2);
|
||||
mBitmap = bitmap;
|
||||
mCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
|
||||
mPaint.reset();
|
||||
mSvgShadowNode.mBitmapCount--;
|
||||
mSvgShadowNode.drawChildren(mCanvas, mPaint, mWidth, mHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -141,12 +141,27 @@ public class RNSVGImageShadowNode extends RNSVGPathShadowNode {
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas, Paint paint, float opacity) {
|
||||
canvas.saveLayer(0f, 0f, 0f, 0f, paint, Canvas.ALL_SAVE_FLAG);
|
||||
loadBitmap(getResourceDrawableId(getThemedContext(), null), canvas, paint);
|
||||
RNSVGSvgViewShadowNode node = getSvgShadowNode();
|
||||
if (mBitmap != null) {
|
||||
// TODO: fixme
|
||||
// clip(canvas, paint);
|
||||
float x = PropHelper.fromPercentageToFloat(mX, mWidth, 0, mScale);
|
||||
float y = PropHelper.fromPercentageToFloat(mY, mHeight, 0, mScale);
|
||||
float w = PropHelper.fromPercentageToFloat(mW, mWidth, 0, mScale);
|
||||
float h = PropHelper.fromPercentageToFloat(mH, mHeight, 0, mScale);
|
||||
canvas.drawBitmap(mBitmap, null, new Rect((int) x, (int) y, (int) (x + w), (int)(y + h)), null);
|
||||
|
||||
if (node.mBitmapCount == 0) {
|
||||
mBitmap.recycle();
|
||||
}
|
||||
} else {
|
||||
loadBitmap(getResourceDrawableId(getThemedContext(), null), canvas, paint, node);
|
||||
}
|
||||
}
|
||||
|
||||
public void loadBitmap(int resId, Canvas canvas, Paint paint) {
|
||||
BitmapWorkerTask task = new BitmapWorkerTask(canvas, paint);
|
||||
public void loadBitmap(int resId, Canvas canvas, Paint paint, RNSVGSvgViewShadowNode node) {
|
||||
|
||||
BitmapWorkerTask task = new BitmapWorkerTask(canvas, paint, node);
|
||||
task.execute(resId);
|
||||
}
|
||||
|
||||
|
||||
@@ -11,8 +11,10 @@ package com.horcrux.svg;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.util.Log;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
@@ -25,6 +27,8 @@ import com.facebook.react.uimanager.UIViewOperationQueue;
|
||||
public class RNSVGSvgViewShadowNode extends LayoutShadowNode {
|
||||
public boolean touchable = false;
|
||||
|
||||
public int mBitmapCount = 0;
|
||||
|
||||
@Override
|
||||
public void onCollectExtraUpdates(UIViewOperationQueue uiUpdater) {
|
||||
super.onCollectExtraUpdates(uiUpdater);
|
||||
@@ -32,8 +36,6 @@ public class RNSVGSvgViewShadowNode extends LayoutShadowNode {
|
||||
}
|
||||
|
||||
private Object drawOutput() {
|
||||
// TODO(7255985): Use TextureView and pass Svg from the view to draw on it asynchronously
|
||||
// instead of passing the bitmap (which is inefficient especially in terms of memory usage)
|
||||
float width = (int) getLayoutWidth();
|
||||
float height = (int) getLayoutHeight();
|
||||
Bitmap bitmap = Bitmap.createBitmap(
|
||||
@@ -43,18 +45,22 @@ public class RNSVGSvgViewShadowNode extends LayoutShadowNode {
|
||||
Canvas canvas = new Canvas(bitmap);
|
||||
Paint paint = new Paint();
|
||||
|
||||
drawChildren(canvas, paint, width, height);
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
public void drawChildren(Canvas canvas, Paint paint, float width, float height) {
|
||||
for (int i = 0; i < getChildCount(); i++) {
|
||||
RNSVGVirtualNode child = (RNSVGVirtualNode) getChildAt(i);
|
||||
child.setDimensions(width, height);
|
||||
child.draw(canvas, paint, 1f);
|
||||
child.markUpdateSeen();
|
||||
//child.markUpdateSeen();
|
||||
|
||||
if (child.isTouchable() && !touchable) {
|
||||
touchable = true;
|
||||
}
|
||||
}
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
public int hitTest(Point point, ViewGroup view) {
|
||||
|
||||
@@ -263,10 +263,8 @@ public abstract class RNSVGVirtualNode extends LayoutShadowNode {
|
||||
}
|
||||
|
||||
protected void clip(Canvas canvas, Paint paint) {
|
||||
Path clip = null;
|
||||
if (mClipPath != null) {
|
||||
clip = mClipPath;
|
||||
} else if (mClipPathId != null) {
|
||||
Path clip = mClipPath;
|
||||
if (clip == null && mClipPathId != null) {
|
||||
clip = CLIP_PATHS.get(mClipPathId);
|
||||
}
|
||||
|
||||
@@ -294,6 +292,15 @@ public abstract class RNSVGVirtualNode extends LayoutShadowNode {
|
||||
|
||||
abstract protected Path getPath(Canvas canvas, Paint paint);
|
||||
|
||||
protected RNSVGSvgViewShadowNode getSvgShadowNode() {
|
||||
ReactShadowNode parent = getParent();
|
||||
|
||||
while (!(parent instanceof RNSVGSvgViewShadowNode)) {
|
||||
parent = parent.getParent();
|
||||
}
|
||||
return (RNSVGSvgViewShadowNode)parent;
|
||||
}
|
||||
|
||||
protected void finalize() {
|
||||
if (mDefinedClipPathId != null) {
|
||||
CLIP_PATHS.remove(mDefinedClipPathId);
|
||||
|
||||
Reference in New Issue
Block a user