mirror of
https://github.com/zoriya/react-native-svg.git
synced 2026-05-25 03:53:31 +00:00
Finish Symbol refactor on Android
This commit is contained in:
@@ -178,7 +178,7 @@ public class ImageShadowNode extends RenderableShadowNode {
|
||||
|
||||
RectF vbRect = new RectF(0, 0, renderRect.width() / mScale, renderRect.height() / mScale);
|
||||
RectF eRect = new RectF(getCanvasLeft(), getCanvasTop(), rectWidth / mScale + getCanvasLeft(), rectHeight / mScale + getCanvasTop());
|
||||
Matrix transform = ViewBoxShadowNode.getTransform(vbRect, eRect, mAlign, mMeetOrSlice, false);
|
||||
Matrix transform = ViewBox.getTransform(vbRect, eRect, mAlign, mMeetOrSlice, false);
|
||||
|
||||
transform.mapRect(renderRect);
|
||||
Matrix translation = new Matrix();
|
||||
|
||||
@@ -176,8 +176,8 @@ class PropHelper {
|
||||
float cx = PropHelper.fromPercentageToFloat(mPoints.getString(4), width, offsetX, scale);
|
||||
float cy = PropHelper.fromPercentageToFloat(mPoints.getString(5), height, offsetY, scale) / (ry / rx);
|
||||
// TODO: support focus point.
|
||||
//float fx = PropHelper.fromPercentageToFloat(mPoints.getString(0), width, offsetX) * scale;
|
||||
//float fy = PropHelper.fromPercentageToFloat(mPoints.getString(1), height, offsetY) * scale / (ry / rx);
|
||||
//float fx = PropHelper.fromPercentageToFloat(mPoints.getString(0), width, offsetX, scale);
|
||||
//float fy = PropHelper.fromPercentageToFloat(mPoints.getString(1), height, offsetY, scale) / (ry / rx);
|
||||
Shader radialGradient = new RadialGradient(
|
||||
cx,
|
||||
cy,
|
||||
|
||||
@@ -35,7 +35,7 @@ public class RenderableViewManager extends ViewManager<View, LayoutShadowNode> {
|
||||
/* package */ static final String CLASS_CLIP_PATH = "RNSVGClipPath";
|
||||
/* package */ static final String CLASS_DEFS = "RNSVGDefs";
|
||||
/* package */ static final String CLASS_USE = "RNSVGUse";
|
||||
/* package */ static final String CLASS_VIEW_BOX = "RNSVGViewBox";
|
||||
/* package */ static final String CLASS_SYMBOL = "RNSVGSymbol";
|
||||
/* package */ static final String CLASS_LINEAR_GRADIENT = "RNSVGLinearGradient";
|
||||
/* package */ static final String CLASS_RADIAL_GRADIENT = "RNSVGRadialGradient";
|
||||
|
||||
@@ -94,8 +94,8 @@ public class RenderableViewManager extends ViewManager<View, LayoutShadowNode> {
|
||||
return new RenderableViewManager(CLASS_USE);
|
||||
}
|
||||
|
||||
public static RenderableViewManager createViewBoxViewManager() {
|
||||
return new RenderableViewManager(CLASS_VIEW_BOX);
|
||||
public static RenderableViewManager createSymbolManager() {
|
||||
return new RenderableViewManager(CLASS_SYMBOL);
|
||||
}
|
||||
|
||||
public static RenderableViewManager createLinearGradientManager() {
|
||||
@@ -144,8 +144,8 @@ public class RenderableViewManager extends ViewManager<View, LayoutShadowNode> {
|
||||
return new DefsShadowNode();
|
||||
case CLASS_USE:
|
||||
return new UseShadowNode();
|
||||
case CLASS_VIEW_BOX:
|
||||
return new ViewBoxShadowNode();
|
||||
case CLASS_SYMBOL:
|
||||
return new SymbolShadowNode();
|
||||
case CLASS_LINEAR_GRADIENT:
|
||||
return new LinearGradientShadowNode();
|
||||
case CLASS_RADIAL_GRADIENT:
|
||||
@@ -184,8 +184,8 @@ public class RenderableViewManager extends ViewManager<View, LayoutShadowNode> {
|
||||
return DefsShadowNode.class;
|
||||
case CLASS_USE:
|
||||
return UseShadowNode.class;
|
||||
case CLASS_VIEW_BOX:
|
||||
return ViewBoxShadowNode.class;
|
||||
case CLASS_SYMBOL:
|
||||
return SymbolShadowNode.class;
|
||||
case CLASS_LINEAR_GRADIENT:
|
||||
return LinearGradientShadowNode.class;
|
||||
case CLASS_RADIAL_GRADIENT:
|
||||
|
||||
@@ -38,7 +38,7 @@ public class SvgPackage implements ReactPackage {
|
||||
RenderableViewManager.createClipPathViewManager(),
|
||||
RenderableViewManager.createDefsViewManager(),
|
||||
RenderableViewManager.createUseViewManager(),
|
||||
RenderableViewManager.createViewBoxViewManager(),
|
||||
RenderableViewManager.createSymbolManager(),
|
||||
RenderableViewManager.createLinearGradientManager(),
|
||||
RenderableViewManager.createRadialGradientManager(),
|
||||
new SvgViewManager());
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.facebook.react.bridge.Arguments;
|
||||
import com.facebook.react.bridge.ReactContext;
|
||||
import com.facebook.react.bridge.WritableMap;
|
||||
import com.facebook.react.uimanager.UIManagerModule;
|
||||
import com.facebook.react.uimanager.annotations.ReactProp;
|
||||
import com.facebook.react.uimanager.events.RCTEventEmitter;
|
||||
import com.facebook.react.uimanager.events.TouchEvent;
|
||||
import com.facebook.react.uimanager.events.TouchEventCoalescingKeyHelper;
|
||||
|
||||
@@ -11,15 +11,20 @@ package com.horcrux.svg;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.util.Base64;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.PorterDuff;
|
||||
import android.util.Log;
|
||||
|
||||
import com.facebook.react.uimanager.DisplayMetricsHolder;
|
||||
import com.facebook.react.uimanager.LayoutShadowNode;
|
||||
import com.facebook.react.uimanager.UIViewOperationQueue;
|
||||
import com.facebook.react.uimanager.annotations.ReactProp;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.util.HashMap;
|
||||
@@ -35,6 +40,54 @@ public class SvgViewShadowNode extends LayoutShadowNode {
|
||||
private final Map<String, VirtualNode> mDefinedTemplates = new HashMap<>();
|
||||
private final Map<String, PropHelper.RNSVGBrush> mDefinedBrushes = new HashMap<>();
|
||||
private Canvas mCanvas;
|
||||
protected final float mScale;
|
||||
|
||||
private float mMinX;
|
||||
private float mMinY;
|
||||
private float mVbWidth;
|
||||
private float mVbHeight;
|
||||
private String mAlign;
|
||||
private int mMeetOrSlice;
|
||||
|
||||
public SvgViewShadowNode() {
|
||||
mScale = DisplayMetricsHolder.getScreenDisplayMetrics().density;
|
||||
}
|
||||
|
||||
@ReactProp(name = "minX")
|
||||
public void setMinX(float minX) {
|
||||
mMinX = minX;
|
||||
markUpdated();
|
||||
}
|
||||
|
||||
@ReactProp(name = "minY")
|
||||
public void setMinY(float minY) {
|
||||
mMinY = minY;
|
||||
markUpdated();
|
||||
}
|
||||
|
||||
@ReactProp(name = "vbWidth")
|
||||
public void setVbWidth(float vbWidth) {
|
||||
mVbWidth = vbWidth;
|
||||
markUpdated();
|
||||
}
|
||||
|
||||
@ReactProp(name = "vbHeight")
|
||||
public void setVbHeight(float vbHeight) {
|
||||
mVbHeight = vbHeight;
|
||||
markUpdated();
|
||||
}
|
||||
|
||||
@ReactProp(name = "align")
|
||||
public void setAlign(String align) {
|
||||
mAlign = align;
|
||||
markUpdated();
|
||||
}
|
||||
|
||||
@ReactProp(name = "meetOrSlice")
|
||||
public void setMeetOrSlice(int meetOrSlice) {
|
||||
mMeetOrSlice = meetOrSlice;
|
||||
markUpdated();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVirtual() {
|
||||
@@ -66,7 +119,6 @@ public class SvgViewShadowNode extends LayoutShadowNode {
|
||||
|
||||
mCanvas = new Canvas(bitmap);
|
||||
drawChildren(mCanvas);
|
||||
mCanvas = null;
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
@@ -75,6 +127,14 @@ public class SvgViewShadowNode extends LayoutShadowNode {
|
||||
}
|
||||
|
||||
private void drawChildren(Canvas canvas) {
|
||||
|
||||
if (mAlign != null) {
|
||||
RectF vbRect = new RectF(mMinX * mScale, mMinY * mScale, (mMinX + mVbWidth) * mScale, (mMinY + mVbHeight) * mScale);
|
||||
RectF eRect = new RectF(0, 0, getLayoutWidth(), getLayoutHeight());
|
||||
Matrix viewBoxMatrix = ViewBox.getTransform(vbRect, eRect, mAlign, mMeetOrSlice, false);
|
||||
canvas.concat(viewBoxMatrix);
|
||||
}
|
||||
|
||||
Paint paint = new Paint();
|
||||
|
||||
for (int i = 0; i < getChildCount(); i++) {
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* Copyright (c) 2015-present, Horcrux.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the MIT-style license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
|
||||
package com.horcrux.svg;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.RectF;
|
||||
|
||||
import com.facebook.react.uimanager.annotations.ReactProp;
|
||||
|
||||
public class SymbolShadowNode extends GroupShadowNode {
|
||||
|
||||
private float mMinX;
|
||||
private float mMinY;
|
||||
private float mVbWidth;
|
||||
private float mVbHeight;
|
||||
private String mAlign;
|
||||
private int mMeetOrSlice;
|
||||
|
||||
@ReactProp(name = "minX")
|
||||
public void setMinX(float minX) {
|
||||
mMinX = minX;
|
||||
markUpdated();
|
||||
}
|
||||
|
||||
@ReactProp(name = "minY")
|
||||
public void setMinY(float minY) {
|
||||
mMinY = minY;
|
||||
markUpdated();
|
||||
}
|
||||
|
||||
@ReactProp(name = "vbWidth")
|
||||
public void setVbWidth(float vbWidth) {
|
||||
mVbWidth = vbWidth;
|
||||
markUpdated();
|
||||
}
|
||||
|
||||
@ReactProp(name = "vbHeight")
|
||||
public void setVbHeight(float vbHeight) {
|
||||
mVbHeight = vbHeight;
|
||||
markUpdated();
|
||||
}
|
||||
|
||||
@ReactProp(name = "align")
|
||||
public void setAlign(String align) {
|
||||
mAlign = align;
|
||||
markUpdated();
|
||||
}
|
||||
|
||||
@ReactProp(name = "meetOrSlice")
|
||||
public void setMeetOrSlice(int meetOrSlice) {
|
||||
mMeetOrSlice = meetOrSlice;
|
||||
markUpdated();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas, Paint paint, float opacity) {
|
||||
saveDefinition();
|
||||
}
|
||||
|
||||
public void drawSymbol(Canvas canvas, Paint paint, float opacity, float width, float height) {
|
||||
if (mAlign != null) {
|
||||
RectF vbRect = new RectF(mMinX * mScale, mMinY * mScale, (mMinX + mVbWidth) * mScale, (mMinY + mVbHeight) * mScale);
|
||||
RectF eRect = new RectF(0, 0, width, height);
|
||||
Matrix viewBoxMatrix = ViewBox.getTransform(vbRect, eRect, mAlign, mMeetOrSlice, false);
|
||||
canvas.concat(viewBoxMatrix);
|
||||
super.draw(canvas, paint, opacity);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -60,7 +60,14 @@ public class UseShadowNode extends RenderableShadowNode {
|
||||
template.mergeProperties(this, mAttributeList, true);
|
||||
int count = template.saveAndSetupCanvas(canvas);
|
||||
clip(canvas, paint);
|
||||
template.draw(canvas, paint, opacity * mOpacity);
|
||||
|
||||
if (template instanceof SymbolShadowNode) {
|
||||
SymbolShadowNode symbol = (SymbolShadowNode)template;
|
||||
symbol.drawSymbol(canvas, paint, opacity, relativeOnWidth(mWidth), relativeOnHeight(mHeight));
|
||||
} else {
|
||||
template.draw(canvas, paint, opacity * mOpacity);
|
||||
}
|
||||
|
||||
template.restoreCanvas(canvas, count);
|
||||
template.resetProperties();
|
||||
} else {
|
||||
|
||||
+1
-101
@@ -9,103 +9,18 @@
|
||||
|
||||
package com.horcrux.svg;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.RectF;
|
||||
|
||||
import com.facebook.react.bridge.ReadableArray;
|
||||
import com.facebook.react.uimanager.annotations.ReactProp;
|
||||
|
||||
/**
|
||||
* Shadow node for virtual ViewBox
|
||||
*/
|
||||
public class ViewBoxShadowNode extends GroupShadowNode {
|
||||
public class ViewBox extends GroupShadowNode {
|
||||
|
||||
private static final int MOS_MEET = 0;
|
||||
private static final int MOS_SLICE = 1;
|
||||
private static final int MOS_NONE = 2;
|
||||
|
||||
private String mMinX;
|
||||
private String mMinY;
|
||||
private String mVbWidth;
|
||||
private String mVbHeight;
|
||||
private String mBoxWidth;
|
||||
private String mBoxHeight;
|
||||
private String mAlign;
|
||||
private int mMeetOrSlice;
|
||||
private boolean mFromSymbol = false;
|
||||
|
||||
@ReactProp(name = "minX")
|
||||
public void setMinX(String minX) {
|
||||
mMinX = minX;
|
||||
markUpdated();
|
||||
}
|
||||
|
||||
@ReactProp(name = "minY")
|
||||
public void setMinY(String minY) {
|
||||
mMinY = minY;
|
||||
markUpdated();
|
||||
}
|
||||
|
||||
@ReactProp(name = "vbWidth")
|
||||
public void setVbWidth(String vbWidth) {
|
||||
mVbWidth = vbWidth;
|
||||
markUpdated();
|
||||
}
|
||||
|
||||
@ReactProp(name = "vbHeight")
|
||||
public void setVbHeight(String vbHeight) {
|
||||
mVbHeight = vbHeight;
|
||||
markUpdated();
|
||||
}
|
||||
|
||||
|
||||
@ReactProp(name = "width")
|
||||
public void setWidth(String width) {
|
||||
mBoxWidth = width;
|
||||
markUpdated();
|
||||
}
|
||||
|
||||
@ReactProp(name = "height")
|
||||
public void setHeight(String height) {
|
||||
mBoxHeight = height;
|
||||
markUpdated();
|
||||
}
|
||||
|
||||
@ReactProp(name = "align")
|
||||
public void setAlign(String align) {
|
||||
mAlign = align;
|
||||
markUpdated();
|
||||
}
|
||||
|
||||
@ReactProp(name = "meetOrSlice")
|
||||
public void setMeetOrSlice(int meetOrSlice) {
|
||||
mMeetOrSlice = meetOrSlice;
|
||||
markUpdated();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int saveAndSetupCanvas(Canvas canvas) {
|
||||
mMatrix = getTransformFromProps();
|
||||
return super.saveAndSetupCanvas(canvas);
|
||||
}
|
||||
|
||||
private Matrix getTransformFromProps() {
|
||||
|
||||
float vbX = relativeOnWidth(mMinX);
|
||||
float vbY = relativeOnHeight(mMinY);
|
||||
float vbWidth = relativeOnWidth(mVbWidth);
|
||||
float vbHeight = relativeOnHeight(mVbHeight);
|
||||
|
||||
|
||||
float eX = getCanvasLeft();
|
||||
float eY = getCanvasTop();
|
||||
float eWidth = mBoxWidth != null ? relativeOnWidth(mBoxWidth) : getCanvasWidth();
|
||||
float eHeight = mBoxHeight != null ? relativeOnHeight(mBoxHeight) : getCanvasHeight();
|
||||
|
||||
return getTransform(new RectF(vbX, vbY, vbWidth + vbX, vbHeight + vbY), new RectF(eX, eY, eWidth + eX, eHeight + eY), mAlign, mMeetOrSlice, mFromSymbol);
|
||||
}
|
||||
|
||||
static public Matrix getTransform(RectF vbRect, RectF eRect, String align, int meetOrSlice, boolean fromSymbol) {
|
||||
// based on https://svgwg.org/svg2-draft/coords.html#ComputingAViewportsTransform
|
||||
|
||||
@@ -188,19 +103,4 @@ public class ViewBoxShadowNode extends GroupShadowNode {
|
||||
transform.postScale(scaleX, scaleY);
|
||||
return transform;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mergeProperties(VirtualNode target, ReadableArray mergeList, boolean inherited) {
|
||||
if (target instanceof UseShadowNode) {
|
||||
mFromSymbol = true;
|
||||
mBoxWidth = ((UseShadowNode)target).getWidth();
|
||||
mBoxHeight = ((UseShadowNode)target).getHeight();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetProperties() {
|
||||
mBoxWidth = mBoxHeight = null;
|
||||
mFromSymbol = false;
|
||||
}
|
||||
}
|
||||
@@ -206,12 +206,12 @@ public abstract class VirtualNode extends LayoutShadowNode {
|
||||
return mSvgShadowNode;
|
||||
}
|
||||
|
||||
protected float relativeOnWidth(String position) {
|
||||
return PropHelper.fromPercentageToFloat(position, getCanvasWidth(), 0, mScale);
|
||||
protected float relativeOnWidth(String length) {
|
||||
return PropHelper.fromPercentageToFloat(length, getCanvasWidth(), 0, mScale);
|
||||
}
|
||||
|
||||
protected float relativeOnHeight(String position) {
|
||||
return PropHelper.fromPercentageToFloat(position, getCanvasHeight(), 0, mScale);
|
||||
protected float relativeOnHeight(String length) {
|
||||
return PropHelper.fromPercentageToFloat(length, getCanvasHeight(), 0, mScale);
|
||||
}
|
||||
|
||||
protected float getCanvasWidth() {
|
||||
|
||||
@@ -28,13 +28,12 @@
|
||||
if (template) {
|
||||
[self beginTransparencyLayer:context];
|
||||
[self clip:context];
|
||||
[template mergeProperties:self];
|
||||
|
||||
if ([template class] == [RNSVGSymbol class]) {
|
||||
[template mergeProperties:self];
|
||||
RNSVGSymbol *symbol = template;
|
||||
[symbol renderSymbolTo:context width:[self relativeOnWidth:self.width] height:[self relativeOnWidth:self.height]];
|
||||
} else {
|
||||
[template mergeProperties:self];
|
||||
[template renderTo:context];
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user