Skip to content

Commit

Permalink
Alternative approach without TextureView.
Browse files Browse the repository at this point in the history
  • Loading branch information
msand committed Mar 18, 2018
1 parent 7deabf8 commit 0eb501d
Show file tree
Hide file tree
Showing 15 changed files with 89 additions and 135 deletions.
4 changes: 2 additions & 2 deletions android/src/main/java/com/horcrux/svg/ImageShadowNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -75,13 +75,13 @@ public void setY(String y) {
markUpdated();
}

@ReactProp(name = "width")
@ReactProp(name = "imagewidth")
public void setWidth(String width) {
mW = width;
markUpdated();
}

@ReactProp(name = "height")
@ReactProp(name = "imageheight")
public void seHeight(String height) {
mH = height;
markUpdated();
Expand Down
19 changes: 14 additions & 5 deletions android/src/main/java/com/horcrux/svg/RenderableViewManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

package com.horcrux.svg;

import android.graphics.Bitmap;
import android.util.SparseArray;

import com.facebook.react.bridge.ReadableArray;
Expand Down Expand Up @@ -183,12 +184,12 @@ public void setY(RenderableView node, String y) {
((ImageShadowNode) node.getShadowNode()).setY(y);
}

@ReactProp(name = "width")
@ReactProp(name = "imagewidth")
public void setWidth(RenderableView node, String width) {
((ImageShadowNode) node.getShadowNode()).setWidth(width);
}

@ReactProp(name = "height")
@ReactProp(name = "imageheight")
public void seHeight(RenderableView node, String height) {
((ImageShadowNode) node.getShadowNode()).seHeight(height);
}
Expand Down Expand Up @@ -340,12 +341,12 @@ public void setHref(RenderableView node, String href) {
((UseShadowNode) node.getShadowNode()).setHref(href);
}

@ReactProp(name = "width")
@ReactProp(name = "usewidth")
public void setWidth(RenderableView node, String width) {
((UseShadowNode) node.getShadowNode()).setWidth(width);
}

@ReactProp(name = "height")
@ReactProp(name = "useheight")
public void setHeight(RenderableView node, String height) {
((UseShadowNode) node.getShadowNode()).setHeight(height);
}
Expand Down Expand Up @@ -637,7 +638,15 @@ protected void onAfterUpdateTransaction(RenderableView node) {
super.onAfterUpdateTransaction(node);
VirtualNode shadow = node.getShadowNode();
SvgViewShadowNode view = shadow.getSvgShadowNode();
if (view != null) view.drawOutput();
if (view == null) {
return;
}
SvgView root = SvgViewManager.getSvgViewByTag(view.getReactTag());
if (root == null) {
return;
}
Bitmap output = view.drawOutput();
root.setBitmap(output);
}

@Override
Expand Down
40 changes: 19 additions & 21 deletions android/src/main/java/com/horcrux/svg/SvgView.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@
package com.horcrux.svg;

import android.annotation.SuppressLint;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Point;
import android.util.Log;
import android.view.MotionEvent;
import android.view.TextureView;
import android.view.View;
import android.view.ViewGroup;

Expand All @@ -28,6 +28,8 @@
import com.facebook.react.uimanager.events.TouchEventType;
import com.facebook.react.views.view.ReactViewGroup;

import javax.annotation.Nullable;

/**
* Custom {@link View} implementation that draws an RNSVGSvg React view and its children.
*/
Expand All @@ -51,7 +53,7 @@ public String toString() {
}
}

private TextureView mTextureView;
private @Nullable Bitmap mBitmap;
private final EventDispatcher mEventDispatcher;
private long mGestureStartTime = TouchEvent.UNSET;
private int mTargetTag;
Expand All @@ -61,9 +63,6 @@ public String toString() {

public SvgView(ReactContext reactContext) {
super(reactContext);
mTextureView = new TextureView(reactContext);
mTextureView.setOpaque(false);
addView(mTextureView);
mEventDispatcher = reactContext.getNativeModule(UIManagerModule.class).getEventDispatcher();
}

Expand All @@ -73,27 +72,26 @@ public void addView(View child, int index, LayoutParams params) {
}
}

/**
* Sets the {@link TextureView.SurfaceTextureListener} used to listen to surface
* texture events.
*
* @see TextureView#getSurfaceTextureListener
* @see TextureView.SurfaceTextureListener
*/
public void setSurfaceTextureListener(TextureView.SurfaceTextureListener listener) {
mTextureView.setSurfaceTextureListener(listener);
@Override
public void setId(int id) {
super.setId(id);
SvgViewManager.setSvgView(this);
}

@Override
public final void draw(Canvas canvas) {
super.draw(canvas);
mTextureView.draw(canvas);
public void setBitmap(Bitmap bitmap) {
if (mBitmap != null) {
mBitmap.recycle();
}
mBitmap = bitmap;
invalidate();
}

@Override
public void setId(int id) {
super.setId(id);
SvgViewManager.setSvgView(this);
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mBitmap != null) {
canvas.drawBitmap(mBitmap, 0, 0, null);
}
}

private SvgViewShadowNode getShadowNode() {
Expand Down
3 changes: 2 additions & 1 deletion android/src/main/java/com/horcrux/svg/SvgViewManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

package com.horcrux.svg;

import android.graphics.Bitmap;
import android.util.SparseArray;

import com.facebook.react.uimanager.ThemedReactContext;
Expand Down Expand Up @@ -90,7 +91,7 @@ protected SvgView createViewInstance(ThemedReactContext reactContext) {

@Override
public void updateExtraData(SvgView root, Object extraData) {
root.setSurfaceTextureListener((SvgViewShadowNode) extraData);
root.setBitmap((Bitmap) extraData);
}

}
96 changes: 21 additions & 75 deletions android/src/main/java/com/horcrux/svg/SvgViewShadowNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,50 +11,29 @@

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.SurfaceTexture;
import android.graphics.Typeface;
import android.util.Base64;
import android.view.Surface;
import android.view.TextureView;

import com.facebook.common.logging.FLog;
import com.facebook.react.common.ReactConstants;
import com.facebook.react.uimanager.DisplayMetricsHolder;
import com.facebook.react.uimanager.LayoutShadowNode;
import com.facebook.react.uimanager.ReactShadowNode;
import com.facebook.react.uimanager.ReactShadowNodeImpl;
import com.facebook.react.uimanager.UIViewOperationQueue;
import com.facebook.react.uimanager.ViewProps;
import com.facebook.react.uimanager.annotations.ReactProp;

import java.io.ByteArrayOutputStream;
import java.util.HashMap;
import java.util.Map;

import javax.annotation.Nullable;

/**
* Shadow node for RNSVG virtual tree root - RNSVGSvgView
*/
public class SvgViewShadowNode extends LayoutShadowNode
implements TextureView.SurfaceTextureListener {

private @Nullable Surface mSurface;

private @Nullable Integer mBackgroundColor;

@ReactProp(name = ViewProps.BACKGROUND_COLOR, customType = "Color")
public void setBackgroundColor(Integer color) {
mBackgroundColor = color;
markUpdated();
}

public class SvgViewShadowNode extends LayoutShadowNode {
private boolean mResponsible = false;

private final Map<String, VirtualNode> mDefinedClipPaths = new HashMap<>();
Expand Down Expand Up @@ -139,8 +118,7 @@ public boolean isVirtualAnchor() {
@Override
public void onCollectExtraUpdates(UIViewOperationQueue uiUpdater) {
super.onCollectExtraUpdates(uiUpdater);
drawOutput();
uiUpdater.enqueueUpdateExtraData(getReactTag(), this);
uiUpdater.enqueueUpdateExtraData(getReactTag(), drawOutput());
}

@Override
Expand All @@ -149,37 +127,24 @@ public void setReactTag(int reactTag) {
SvgViewManager.setShadowNode(this);
}

void drawOutput() {
if (mSurface == null || !mSurface.isValid()) {
markChildrenUpdatesSeen(this);
return;
Bitmap drawOutput() {
float width = getLayoutWidth();
float height = getLayoutHeight();
boolean early = Float.isNaN(width) || Float.isNaN(height) || width * height == 0;
if (early) {
ReactShadowNodeImpl parent = getParent();
float parentWidth = parent == null ? 0 : parent.getLayoutWidth();
float parentHeight = parent == null ? 0 : parent.getLayoutHeight();
width = (float) PropHelper.fromRelative(mbbWidth, parentWidth, 0, mScale, 12);
height = (float) PropHelper.fromRelative(mbbHeight, parentHeight, 0, mScale, 12);
}
Bitmap bitmap = Bitmap.createBitmap(
(int) width,
(int) height,
Bitmap.Config.ARGB_8888);

try {
Canvas canvas = mSurface.lockCanvas(null);
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
if (mBackgroundColor != null) {
canvas.drawColor(mBackgroundColor);
}

drawChildren(canvas);

if (mSurface == null) {
return;
}

mSurface.unlockCanvasAndPost(canvas);
} catch (IllegalArgumentException | IllegalStateException e) {
FLog.e(ReactConstants.TAG, e.getClass().getSimpleName() + " in Surface.unlockCanvasAndPost");
}
}

private void markChildrenUpdatesSeen(ReactShadowNode shadowNode) {
for (int i = 0; i < shadowNode.getChildCount(); i++) {
ReactShadowNode child = shadowNode.getChildAt(i);
child.markUpdateSeen();
markChildrenUpdatesSeen(child);
}
drawChildren(new Canvas(bitmap));
return bitmap;
}

Rect getCanvasBounds() {
Expand All @@ -194,8 +159,8 @@ void drawChildren(final Canvas canvas) {
float height = getLayoutHeight();
boolean nested = Float.isNaN(width) || Float.isNaN(height);
if (nested) {
width = Float.parseFloat(mbbWidth) * mScale;
height = Float.parseFloat(mbbHeight) * mScale;
width = (float) PropHelper.fromRelative(mbbWidth, canvas.getWidth(), 0f, mScale, 12);
height = (float) PropHelper.fromRelative(mbbHeight, canvas.getHeight(), 0f, mScale, 12);
}
RectF eRect = new RectF(0,0, width, height);
if (nested) {
Expand Down Expand Up @@ -318,23 +283,4 @@ void traverseChildren(VirtualNode.NodeRunnable runner) {
runner.run(child);
}
}

@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
mSurface = new Surface(surface);
drawOutput();
}

@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
surface.release();
mSurface = null;
return true;
}

@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {}

@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {}
}
4 changes: 2 additions & 2 deletions android/src/main/java/com/horcrux/svg/UseShadowNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@ public void setHref(String href) {
markUpdated();
}

@ReactProp(name = "width")
@ReactProp(name = "usewidth")
public void setWidth(String width) {
mWidth = width;
markUpdated();
}

@ReactProp(name = "height")
@ReactProp(name = "useheight")
public void setHeight(String height) {
mHeight = height;
markUpdated();
Expand Down
4 changes: 2 additions & 2 deletions elements/Image.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ export default class extends Shape {
{...extractProps({...props, x: null, y: null}, this)}
x={props.x.toString()}
y={props.y.toString()}
width={props.width.toString()}
height={props.height.toString()}
imagewidth={props.width.toString()}
imageheight={props.height.toString()}
meetOrSlice={meetOrSlice}
align={align}
src={resolveAssetSource(props.href)}
Expand Down
4 changes: 2 additions & 2 deletions elements/Use.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ export default class extends Shape {
ref={ele => {this.root = ele;}}
{...extractProps(props, this)}
href={href}
width={props.width}
height={props.height}
usewidth={props.width}
useheight={props.height}
>{props.children}</RNSVGUse>;
}
}
Expand Down
4 changes: 2 additions & 2 deletions ios/Elements/RNSVGImage.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
@property (nonatomic, assign) id src;
@property (nonatomic, strong) NSString* x;
@property (nonatomic, strong) NSString* y;
@property (nonatomic, strong) NSString* width;
@property (nonatomic, strong) NSString* height;
@property (nonatomic, strong) NSString* imagewidth;
@property (nonatomic, strong) NSString* imageheight;
@property (nonatomic, strong) NSString *align;
@property (nonatomic, assign) RNSVGVBMOS meetOrSlice;

Expand Down
Loading

0 comments on commit 0eb501d

Please sign in to comment.