mirror of
https://github.com/zoriya/react-native-svg.git
synced 2025-12-20 05:55:10 +00:00
refactor gradients on Android merge #86 into branch
This commit is contained in:
@@ -48,6 +48,7 @@ class ClipImage extends Component{
|
||||
width="90%"
|
||||
height="90%"
|
||||
href={require('../image.jpg')}
|
||||
opacity="0.6"
|
||||
clipPath="url(#clip)"
|
||||
/>
|
||||
<Text
|
||||
|
||||
@@ -9,6 +9,13 @@
|
||||
|
||||
package com.horcrux.svg;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.RadialGradient;
|
||||
import android.graphics.LinearGradient;
|
||||
import android.graphics.Shader;
|
||||
import android.graphics.Matrix;
|
||||
import android.util.Log;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
@@ -29,7 +36,10 @@ import java.util.regex.Pattern;
|
||||
* @return a {@code float[]} if converted successfully, or {@code null} if {@param value} was
|
||||
* {@code null}.
|
||||
*/
|
||||
/*package*/ static @Nullable float[] toFloatArray(@Nullable ReadableArray value) {
|
||||
/*package*/
|
||||
static
|
||||
@Nullable
|
||||
float[] toFloatArray(@Nullable ReadableArray value) {
|
||||
if (value != null) {
|
||||
float[] result = new float[value.size()];
|
||||
toFloatArray(value, result);
|
||||
@@ -45,10 +55,11 @@ import java.util.regex.Pattern;
|
||||
* will not be converted.
|
||||
*
|
||||
* @param value input array
|
||||
* @param into output array
|
||||
* @param into output array
|
||||
* @return number of items copied from input to the output array
|
||||
*/
|
||||
/*package*/ static int toFloatArray(ReadableArray value, float[] into) {
|
||||
/*package*/
|
||||
static int toFloatArray(ReadableArray value, float[] into) {
|
||||
int length = value.size() > into.length ? into.length : value.size();
|
||||
for (int i = 0; i < length; i++) {
|
||||
into[i] = (float) value.getDouble(i);
|
||||
@@ -62,18 +73,20 @@ import java.util.regex.Pattern;
|
||||
* Converts percentage string into actual based on a relative number
|
||||
*
|
||||
* @param percentage percentage string
|
||||
* @param relative relative number
|
||||
* @param offset offset number
|
||||
* @param relative relative number
|
||||
* @param offset offset number
|
||||
* @return actual float based on relative number
|
||||
*/
|
||||
/*package*/ static float fromPercentageToFloat(String percentage, float relative, float offset, float scale) {
|
||||
Matcher matched = Pattern.compile("^(\\-?\\d+(?:\\.\\d+)?)%$").matcher(percentage);
|
||||
/*package*/
|
||||
static float fromPercentageToFloat(String percentage, float relative, float offset, float scale) {
|
||||
Matcher matched = Pattern.compile("^(\\-?\\d+(?:\\.\\d+)?)%$").matcher(percentage);
|
||||
if (matched.matches()) {
|
||||
return Float.valueOf(matched.group(1)) / 100 * relative + offset;
|
||||
} else {
|
||||
return Float.valueOf(percentage) * scale;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Judge given string is a percentage-like string or not.
|
||||
*
|
||||
@@ -81,8 +94,101 @@ import java.util.regex.Pattern;
|
||||
* @return string is percentage-like or not.
|
||||
*/
|
||||
|
||||
/*package*/ static boolean isPercentage(String string) {
|
||||
/*package*/
|
||||
static boolean isPercentage(String string) {
|
||||
Pattern pattern = Pattern.compile("^(\\-?\\d+(?:\\.\\d+)?)%$");
|
||||
return pattern.matcher(string).matches();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
/*package*/ static class RNSVGBrush {
|
||||
|
||||
private GradientType mType = GradientType.LINEAR_GRADIENT;
|
||||
private ReadableArray mPoints;
|
||||
private ReadableArray mColors;
|
||||
|
||||
public RNSVGBrush(GradientType type, ReadableArray points, ReadableArray colors) {
|
||||
mType = type;
|
||||
mPoints = points;
|
||||
mColors = colors;
|
||||
}
|
||||
|
||||
public enum GradientType {
|
||||
LINEAR_GRADIENT(0),
|
||||
RADIAL_GRADIENT(1);
|
||||
|
||||
GradientType(int ni) {
|
||||
nativeInt = ni;
|
||||
}
|
||||
|
||||
final int nativeInt;
|
||||
}
|
||||
|
||||
private static void parseGradientStops(ReadableArray value, int stopsCount, float[] stops, int[] stopsColors) {
|
||||
int startStops = value.size() - stopsCount;
|
||||
for (int i = 0; i < stopsCount; i++) {
|
||||
stops[i] = (float) value.getDouble(startStops + i);
|
||||
stopsColors[i] = Color.argb(
|
||||
(int) (value.getDouble(i * 4 + 3) * 255),
|
||||
(int) (value.getDouble(i * 4) * 255),
|
||||
(int) (value.getDouble(i * 4 + 1) * 255),
|
||||
(int) (value.getDouble(i * 4 + 2) * 255));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void setupPaint(Paint paint, RectF box, float mScale) {
|
||||
float height = box.height();
|
||||
float width = box.width();
|
||||
float midX = box.centerX();
|
||||
float midY = box.centerY();
|
||||
float offsetX = (midX - width / 2);
|
||||
float offsetY = (midY - height / 2);
|
||||
|
||||
|
||||
int stopsCount = mColors.size() / 5;
|
||||
int[] stopsColors = new int[stopsCount];
|
||||
float[] stops = new float[stopsCount];
|
||||
parseGradientStops(mColors, stopsCount, stops, stopsColors);
|
||||
|
||||
if (mType == GradientType.LINEAR_GRADIENT) {
|
||||
float x1 = PropHelper.fromPercentageToFloat(mPoints.getString(0), width, offsetX, mScale);
|
||||
float y1 = PropHelper.fromPercentageToFloat(mPoints.getString(1), height, offsetY, mScale);
|
||||
float x2 = PropHelper.fromPercentageToFloat(mPoints.getString(2), width, offsetX, mScale);
|
||||
float y2 = PropHelper.fromPercentageToFloat(mPoints.getString(3), height, offsetY, mScale);
|
||||
paint.setShader(
|
||||
new LinearGradient(
|
||||
x1,
|
||||
y1,
|
||||
x2,
|
||||
y2,
|
||||
stopsColors,
|
||||
stops,
|
||||
Shader.TileMode.CLAMP));
|
||||
} else {
|
||||
float rx = PropHelper.fromPercentageToFloat(mPoints.getString(2), width, 0f, mScale);
|
||||
float ry = PropHelper.fromPercentageToFloat(mPoints.getString(3), height, 0f, mScale);
|
||||
float cx = PropHelper.fromPercentageToFloat(mPoints.getString(4), width, offsetX, mScale);
|
||||
float cy = PropHelper.fromPercentageToFloat(mPoints.getString(5), height, offsetY, mScale) / (ry / rx);
|
||||
// TODO: support focus point.
|
||||
//float fx = PropHelper.fromPercentageToFloat(mPoints.getString(0), width, offsetX) * mScale;
|
||||
//float fy = PropHelper.fromPercentageToFloat(mPoints.getString(1), height, offsetY) * mScale / (ry / rx);
|
||||
Shader radialGradient = new RadialGradient(
|
||||
cx,
|
||||
cy,
|
||||
rx,
|
||||
stopsColors,
|
||||
stops,
|
||||
Shader.TileMode.CLAMP
|
||||
);
|
||||
|
||||
Matrix radialMatrix = new Matrix();
|
||||
radialMatrix.preScale(1f, ry / rx);
|
||||
radialGradient.setLocalMatrix(radialMatrix);
|
||||
paint.setShader(radialGradient);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,14 +9,8 @@
|
||||
|
||||
package com.horcrux.svg;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.Point;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.facebook.react.uimanager.annotations.ReactProp;
|
||||
|
||||
/**
|
||||
* Shadow node for virtual RNSVGClipPath view
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* 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.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.Point;
|
||||
import android.view.View;
|
||||
|
||||
import com.facebook.react.bridge.ReadableArray;
|
||||
|
||||
/**
|
||||
* Shadow node for virtual Definition type views
|
||||
*/
|
||||
public class RNSVGDefinitionShadowNode extends RNSVGVirtualNode {
|
||||
|
||||
public void draw(Canvas canvas, Paint paint, float opacity) {}
|
||||
|
||||
@Override
|
||||
public boolean isResponsible() {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected Path getPath(Canvas canvas, Paint paint) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public int hitTest(Point point, View view) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
public void mergeProperties(RNSVGVirtualNode target, ReadableArray mergeList, boolean inherited) {}
|
||||
|
||||
public void mergeProperties(RNSVGVirtualNode target, ReadableArray mergeList) {}
|
||||
|
||||
public void resetProperties() {}
|
||||
}
|
||||
@@ -11,20 +11,11 @@ package com.horcrux.svg;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.Point;
|
||||
import android.view.View;
|
||||
import android.util.Log;
|
||||
|
||||
import com.facebook.react.bridge.ReadableArray;
|
||||
import com.facebook.react.uimanager.annotations.ReactProp;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Shadow node for virtual RNSVGPath view
|
||||
*/
|
||||
public class RNSVGDefsShadowNode extends RNSVGVirtualNode {
|
||||
public class RNSVGDefsShadowNode extends RNSVGDefinitionShadowNode {
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas, Paint paint, float opacity) {
|
||||
@@ -38,27 +29,4 @@ public class RNSVGDefsShadowNode extends RNSVGVirtualNode {
|
||||
|
||||
restoreCanvas(canvas, count);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isResponsible() {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected Path getPath(Canvas canvas, Paint paint) {
|
||||
return new Path();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hitTest(Point point, View view) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mergeProperties(RNSVGVirtualNode target, ReadableArray mergeList, boolean inherited) {}
|
||||
|
||||
@Override
|
||||
public void mergeProperties(RNSVGVirtualNode target, ReadableArray mergeList) {}
|
||||
|
||||
@Override
|
||||
public void resetProperties() {}
|
||||
}
|
||||
|
||||
@@ -23,11 +23,8 @@ import com.facebook.react.uimanager.annotations.ReactProp;
|
||||
public class RNSVGEllipseShadowNode extends RNSVGPathShadowNode {
|
||||
|
||||
private String mCx;
|
||||
|
||||
private String mCy;
|
||||
|
||||
private String mRx;
|
||||
|
||||
private String mRy;
|
||||
|
||||
@ReactProp(name = "cx")
|
||||
|
||||
@@ -19,8 +19,6 @@ import android.view.ViewGroup;
|
||||
|
||||
import com.facebook.react.bridge.ReadableArray;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Shadow node for virtual RNSVGGroup view
|
||||
*/
|
||||
|
||||
@@ -17,7 +17,8 @@ import android.graphics.PorterDuff;
|
||||
import android.graphics.Rect;
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
|
||||
import com.facebook.common.executors.UiThreadImmediateExecutorService;
|
||||
import com.facebook.common.logging.FLog;
|
||||
import com.facebook.common.executors.CallerThreadExecutor;
|
||||
import com.facebook.common.references.CloseableReference;
|
||||
import com.facebook.datasource.DataSource;
|
||||
@@ -25,12 +26,14 @@ import com.facebook.common.logging.FLog;
|
||||
import com.facebook.drawee.backends.pipeline.Fresco;
|
||||
import com.facebook.imagepipeline.core.ImagePipeline;
|
||||
import com.facebook.imagepipeline.datasource.BaseBitmapDataSubscriber;
|
||||
import com.facebook.imagepipeline.image.CloseableBitmap;
|
||||
import com.facebook.imagepipeline.image.CloseableImage;
|
||||
import com.facebook.imagepipeline.request.ImageRequest;
|
||||
import com.facebook.imagepipeline.request.ImageRequestBuilder;
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
import com.facebook.react.common.ReactConstants;
|
||||
import com.facebook.react.uimanager.annotations.ReactProp;
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
@@ -43,7 +46,6 @@ public class RNSVGImageShadowNode extends RNSVGPathShadowNode {
|
||||
private String mW;
|
||||
private String mH;
|
||||
private Uri mUri;
|
||||
private Bitmap mBitmap;
|
||||
private boolean mLoading;
|
||||
|
||||
@ReactProp(name = "x")
|
||||
@@ -85,40 +87,30 @@ public class RNSVGImageShadowNode extends RNSVGPathShadowNode {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas, Paint paint, float opacity) {
|
||||
RNSVGSvgViewShadowNode node = getSvgShadowNode();
|
||||
if (mBitmap != null) {
|
||||
int count = saveAndSetupCanvas(canvas);
|
||||
public void draw(final Canvas canvas, final Paint paint, final float opacity) {
|
||||
final ImageRequest request = ImageRequestBuilder.newBuilderWithSource(mUri).build();
|
||||
final boolean inMemoryCache = Fresco.getImagePipeline().isInBitmapMemoryCache(request);
|
||||
|
||||
clip(canvas, paint);
|
||||
float x = PropHelper.fromPercentageToFloat(mX, mCanvasWidth, 0, mScale);
|
||||
float y = PropHelper.fromPercentageToFloat(mY, mCanvasHeight, 0, mScale);
|
||||
float w = PropHelper.fromPercentageToFloat(mW, mCanvasWidth, 0, mScale);
|
||||
float h = PropHelper.fromPercentageToFloat(mH, mCanvasHeight, 0, mScale);
|
||||
canvas.drawBitmap(mBitmap, null, new Rect((int) x, (int) y, (int) (x + w), (int)(y + h)), null);
|
||||
|
||||
restoreCanvas(canvas, count);
|
||||
markUpdateSeen();
|
||||
if (inMemoryCache) {
|
||||
tryRender(request, canvas, paint, opacity * mOpacity);
|
||||
} else if (!mLoading) {
|
||||
mLoading = true;
|
||||
loadBitmap(canvas, paint, node);
|
||||
loadBitmap(request, canvas, paint);
|
||||
}
|
||||
}
|
||||
|
||||
public void loadBitmap(final Canvas canvas, final Paint paint, final RNSVGSvgViewShadowNode node) {
|
||||
ImageRequest request = ImageRequestBuilder.newBuilderWithSource(mUri).build();
|
||||
private void loadBitmap(@Nonnull final ImageRequest request, @Nonnull final Canvas canvas, @Nonnull final Paint paint) {
|
||||
final DataSource<CloseableReference<CloseableImage>> dataSource
|
||||
= Fresco.getImagePipeline().fetchDecodedImage(request, getThemedContext());
|
||||
|
||||
ImagePipeline imagePipeline = Fresco.getImagePipeline();
|
||||
DataSource<CloseableReference<CloseableImage>>
|
||||
dataSource = imagePipeline.fetchDecodedImage(request, getThemedContext());
|
||||
dataSource.subscribe(new BaseBitmapDataSubscriber() {
|
||||
@Override
|
||||
public void onNewResultImpl(@Nullable Bitmap bitmap) {
|
||||
if (bitmap != null) {
|
||||
mBitmap = bitmap;
|
||||
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
|
||||
paint.reset();
|
||||
node.drawChildren(canvas, paint);
|
||||
mLoading = false;
|
||||
getSvgShadowNode().drawChildren(canvas, paint);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,9 +118,51 @@ public class RNSVGImageShadowNode extends RNSVGPathShadowNode {
|
||||
public void onFailureImpl(DataSource dataSource) {
|
||||
// No cleanup required here.
|
||||
// TODO: more details about this failure
|
||||
FLog.w(ReactConstants.TAG, "RNSVG: load Image load failed!:");
|
||||
mLoading = false;
|
||||
FLog.w(ReactConstants.TAG, dataSource.getFailureCause(), "RNSVG: fetchDecodedImage failed!");
|
||||
}
|
||||
},
|
||||
CallerThreadExecutor.getInstance());
|
||||
UiThreadImmediateExecutorService.getInstance()
|
||||
);
|
||||
}
|
||||
|
||||
private void doRender(@Nonnull final Canvas canvas, @Nonnull final Paint paint, @Nonnull final Bitmap bitmap, final float opacity) {
|
||||
final int count = saveAndSetupCanvas(canvas);
|
||||
|
||||
clip(canvas, paint);
|
||||
float x = PropHelper.fromPercentageToFloat(mX, mCanvasWidth, 0, mScale);
|
||||
float y = PropHelper.fromPercentageToFloat(mY, mCanvasHeight, 0, mScale);
|
||||
float w = PropHelper.fromPercentageToFloat(mW, mCanvasWidth, 0, mScale);
|
||||
float h = PropHelper.fromPercentageToFloat(mH, mCanvasHeight, 0, mScale);
|
||||
Paint alphaPaint = new Paint();
|
||||
|
||||
alphaPaint.setAlpha((int) (opacity * 255));
|
||||
canvas.drawBitmap(bitmap, null, new Rect((int) x, (int) y, (int) (x + w), (int) (y + h)), alphaPaint);
|
||||
|
||||
restoreCanvas(canvas, count);
|
||||
}
|
||||
|
||||
private void tryRender(@Nonnull final ImageRequest request, @Nonnull final Canvas canvas, @Nonnull final Paint paint, final float opacity) {
|
||||
final DataSource<CloseableReference<CloseableImage>> dataSource
|
||||
= Fresco.getImagePipeline().fetchImageFromBitmapCache(request, getThemedContext());
|
||||
|
||||
try {
|
||||
final CloseableReference<CloseableImage> imageReference = dataSource.getResult();
|
||||
if (imageReference != null) {
|
||||
try {
|
||||
if (imageReference.get() instanceof CloseableBitmap) {
|
||||
final Bitmap bitmap = ((CloseableBitmap) imageReference.get()).getUnderlyingBitmap();
|
||||
|
||||
if (bitmap != null) {
|
||||
doRender(canvas, paint, bitmap, opacity);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
CloseableReference.closeSafely(imageReference);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
dataSource.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,12 +12,6 @@ package com.horcrux.svg;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
|
||||
import com.facebook.common.logging.FLog;
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
import com.facebook.react.common.ReactConstants;
|
||||
import com.facebook.react.uimanager.annotations.ReactProp;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
* 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 com.facebook.react.bridge.JavaOnlyArray;
|
||||
import com.facebook.react.bridge.ReadableArray;
|
||||
import com.facebook.react.bridge.WritableArray;
|
||||
import com.facebook.react.uimanager.annotations.ReactProp;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Shadow node for virtual LinearGradient definition view
|
||||
*/
|
||||
public class RNSVGLinearGradientShadowNode extends RNSVGDefinitionShadowNode {
|
||||
|
||||
private String mX1;
|
||||
private String mY1;
|
||||
private String mX2;
|
||||
private String mY2;
|
||||
private ReadableArray mGradient;
|
||||
|
||||
@ReactProp(name = "x1")
|
||||
public void setX1(String x1) {
|
||||
mX1 = x1;
|
||||
markUpdated();
|
||||
}
|
||||
|
||||
@ReactProp(name = "y1")
|
||||
public void setCx(String y1) {
|
||||
mY1 = y1;
|
||||
markUpdated();
|
||||
}
|
||||
|
||||
@ReactProp(name = "x2")
|
||||
public void setX2(String x2) {
|
||||
mX2 = x2;
|
||||
markUpdated();
|
||||
}
|
||||
|
||||
@ReactProp(name = "y2")
|
||||
public void setY2(String y2) {
|
||||
mY2 = y2;
|
||||
markUpdated();
|
||||
}
|
||||
|
||||
@ReactProp(name = "gradient")
|
||||
public void setGradient(ReadableArray gradient) {
|
||||
mGradient = gradient;
|
||||
markUpdated();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void saveDefinition() {
|
||||
if (mName != null) {
|
||||
WritableArray points = new JavaOnlyArray();
|
||||
points.pushString(mX1);
|
||||
points.pushString(mY1);
|
||||
points.pushString(mX2);
|
||||
points.pushString(mY2);
|
||||
|
||||
PropHelper.RNSVGBrush brush = new PropHelper.RNSVGBrush(PropHelper.RNSVGBrush.GradientType.LINEAR_GRADIENT, points, mGradient);
|
||||
getSvgShadowNode().defineBrush(brush, mName);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void removeDefinition() {
|
||||
if (mName != null) {
|
||||
getSvgShadowNode().removeBrush(mName);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -17,18 +17,11 @@ import android.graphics.DashPathEffect;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.RadialGradient;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.graphics.LinearGradient;
|
||||
import android.graphics.Region;
|
||||
import android.graphics.Shader;
|
||||
import android.graphics.Matrix;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.facebook.common.logging.FLog;
|
||||
import com.facebook.react.bridge.JSApplicationIllegalArgumentException;
|
||||
@@ -78,7 +71,7 @@ public class RNSVGPathShadowNode extends RNSVGVirtualNode {
|
||||
|
||||
private ArrayList<String> mChangedList;
|
||||
private ArrayList<Object> mOriginProperties;
|
||||
protected ReadableArray mPropList = new JavaOnlyArray();;
|
||||
protected ReadableArray mPropList = new JavaOnlyArray();
|
||||
|
||||
@ReactProp(name = "d")
|
||||
public void setPath(@Nullable ReadableArray shapePath) {
|
||||
@@ -281,10 +274,11 @@ public class RNSVGPathShadowNode extends RNSVGVirtualNode {
|
||||
* if the stroke should be drawn, {@code false} if not.
|
||||
*/
|
||||
protected boolean setupStrokePaint(Paint paint, float opacity, @Nullable RectF box) {
|
||||
paint.reset();
|
||||
if (mStrokeWidth == 0 || mStroke == null || mStroke.size() == 0) {
|
||||
return false;
|
||||
}
|
||||
paint.reset();
|
||||
|
||||
paint.setFlags(Paint.ANTI_ALIAS_FLAG);
|
||||
paint.setStyle(Paint.Style.STROKE);
|
||||
paint.setStrokeCap(mStrokeLinecap);
|
||||
@@ -310,62 +304,13 @@ public class RNSVGPathShadowNode extends RNSVGVirtualNode {
|
||||
(int) (colors.getDouble(1) * 255),
|
||||
(int) (colors.getDouble(2) * 255),
|
||||
(int) (colors.getDouble(3) * 255));
|
||||
} else if (colorType == 1 || colorType == 2) {
|
||||
} else if (colorType == 1) {
|
||||
if (box == null) {
|
||||
box = new RectF();
|
||||
mPath.computeBounds(box, true);
|
||||
}
|
||||
|
||||
int startColorsPosition = colorType == 1 ? 5 : 7;
|
||||
|
||||
int stopsCount = (colors.size() - startColorsPosition) / 5;
|
||||
int [] stopsColors = new int [stopsCount];
|
||||
float [] stops = new float[stopsCount];
|
||||
float height = box.height();
|
||||
float width = box.width();
|
||||
float midX = box.centerX();
|
||||
float midY = box.centerY();
|
||||
float offsetX = (midX - width / 2);
|
||||
float offsetY = (midY - height / 2);
|
||||
|
||||
parseGradientStops(colors, stopsCount, stops, stopsColors, startColorsPosition);
|
||||
|
||||
if (colorType == 1) {
|
||||
float x1 = PropHelper.fromPercentageToFloat(colors.getString(1), width, offsetX, mScale);
|
||||
float y1 = PropHelper.fromPercentageToFloat(colors.getString(2), height, offsetY, mScale);
|
||||
float x2 = PropHelper.fromPercentageToFloat(colors.getString(3), width, offsetX, mScale);
|
||||
float y2 = PropHelper.fromPercentageToFloat(colors.getString(4), height, offsetY, mScale);
|
||||
paint.setShader(
|
||||
new LinearGradient(
|
||||
x1,
|
||||
y1,
|
||||
x2,
|
||||
y2,
|
||||
stopsColors,
|
||||
stops,
|
||||
Shader.TileMode.CLAMP));
|
||||
} else {
|
||||
float rx = PropHelper.fromPercentageToFloat(colors.getString(3), width, 0f, mScale);
|
||||
float ry = PropHelper.fromPercentageToFloat(colors.getString(4), height, 0f, mScale);
|
||||
float cx = PropHelper.fromPercentageToFloat(colors.getString(5), width, offsetX, mScale);
|
||||
float cy = PropHelper.fromPercentageToFloat(colors.getString(6), height, offsetY, mScale) / (ry / rx);
|
||||
// TODO: do not support focus point.
|
||||
//float fx = PropHelper.fromPercentageToFloat(colors.getString(1), width, offsetX) * mScale;
|
||||
//float fy = PropHelper.fromPercentageToFloat(colors.getString(2), height, offsetY) * mScale / (ry / rx);
|
||||
Shader radialGradient = new RadialGradient(
|
||||
cx,
|
||||
cy,
|
||||
rx,
|
||||
stopsColors,
|
||||
stops,
|
||||
Shader.TileMode.CLAMP
|
||||
);
|
||||
|
||||
Matrix radialMatrix = new Matrix();
|
||||
radialMatrix.preScale(1f, ry / rx);
|
||||
radialGradient.setLocalMatrix(radialMatrix);
|
||||
paint.setShader(radialGradient);
|
||||
}
|
||||
PropHelper.RNSVGBrush brush = getSvgShadowNode().getDefinedBrush(colors.getString(1));
|
||||
brush.setupPaint(paint, box, mScale);
|
||||
} else {
|
||||
// TODO: Support pattern.
|
||||
FLog.w(ReactConstants.TAG, "RNSVG: Color type " + colorType + " not supported!");
|
||||
@@ -455,7 +400,7 @@ public class RNSVGPathShadowNode extends RNSVGVirtualNode {
|
||||
for (int i = 0, size = mergeList.size(); i < size; i++) {
|
||||
try {
|
||||
String fieldName = mergeList.getString(i);
|
||||
Field field = target.getClass().getField(fieldName);
|
||||
Field field = getClass().getField(fieldName);
|
||||
Object value = field.get(target);
|
||||
|
||||
if (inherited) {
|
||||
@@ -464,9 +409,9 @@ public class RNSVGPathShadowNode extends RNSVGVirtualNode {
|
||||
propList.pushString(fieldName);
|
||||
}
|
||||
} else {
|
||||
field.set(this, value);
|
||||
mOriginProperties.add(value);
|
||||
mOriginProperties.add(field.get(this));
|
||||
mChangedList.add(fieldName);
|
||||
field.set(this, value);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new IllegalStateException(e);
|
||||
@@ -497,6 +442,7 @@ public class RNSVGPathShadowNode extends RNSVGVirtualNode {
|
||||
}
|
||||
|
||||
mChangedList = null;
|
||||
mOriginProperties = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
/**
|
||||
* 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 com.facebook.react.bridge.JavaOnlyArray;
|
||||
import com.facebook.react.bridge.ReadableArray;
|
||||
import com.facebook.react.bridge.WritableArray;
|
||||
import com.facebook.react.uimanager.annotations.ReactProp;
|
||||
|
||||
/**
|
||||
* Shadow node for virtual LinearGradient definition view
|
||||
*/
|
||||
public class RNSVGRadialGradientShadowNode extends RNSVGDefinitionShadowNode {
|
||||
private String mFx;
|
||||
private String mFy;
|
||||
private String mRx;
|
||||
private String mRy;
|
||||
private String mCx;
|
||||
private String mCy;
|
||||
private ReadableArray mGradient;
|
||||
|
||||
@ReactProp(name = "fx")
|
||||
public void setFX(String fx) {
|
||||
mFx = fx;
|
||||
markUpdated();
|
||||
}
|
||||
|
||||
@ReactProp(name = "fy")
|
||||
public void setFy(String fy) {
|
||||
mFy = fy;
|
||||
markUpdated();
|
||||
}
|
||||
|
||||
@ReactProp(name = "rx")
|
||||
public void setRx(String rx) {
|
||||
mRx = rx;
|
||||
markUpdated();
|
||||
}
|
||||
|
||||
@ReactProp(name = "ry")
|
||||
public void setRy(String ry) {
|
||||
mRy = ry;
|
||||
markUpdated();
|
||||
}
|
||||
|
||||
@ReactProp(name = "cx")
|
||||
public void setCx(String cx) {
|
||||
mCx = cx;
|
||||
markUpdated();
|
||||
}
|
||||
|
||||
@ReactProp(name = "cy")
|
||||
public void setCy(String cy) {
|
||||
mCy = cy;
|
||||
markUpdated();
|
||||
}
|
||||
|
||||
@ReactProp(name = "gradient")
|
||||
public void setGradient(ReadableArray gradient) {
|
||||
mGradient = gradient;
|
||||
markUpdated();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void saveDefinition() {
|
||||
if (mName != null) {
|
||||
WritableArray points = new JavaOnlyArray();
|
||||
points.pushString(mFx);
|
||||
points.pushString(mFy);
|
||||
points.pushString(mRx);
|
||||
points.pushString(mRy);
|
||||
points.pushString(mCx);
|
||||
points.pushString(mCy);
|
||||
|
||||
PropHelper.RNSVGBrush brush = new PropHelper.RNSVGBrush(PropHelper.RNSVGBrush.GradientType.RADIAL_GRADIENT, points, mGradient);
|
||||
getSvgShadowNode().defineBrush(brush, mName);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void removeDefinition() {
|
||||
if (mName != null) {
|
||||
getSvgShadowNode().removeBrush(mName);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -12,12 +12,7 @@ package com.horcrux.svg;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
|
||||
import com.facebook.common.logging.FLog;
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
import com.facebook.react.common.ReactConstants;
|
||||
import com.facebook.react.uimanager.annotations.ReactProp;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@@ -10,24 +10,9 @@
|
||||
package com.horcrux.svg;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Point;
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.facebook.infer.annotation.Assertions;
|
||||
import com.facebook.react.common.SystemClock;
|
||||
import com.facebook.react.uimanager.ThemedReactContext;
|
||||
import com.facebook.react.uimanager.UIManagerModule;
|
||||
import com.facebook.react.uimanager.events.EventDispatcher;
|
||||
import com.facebook.react.uimanager.events.TouchEvent;
|
||||
import com.facebook.react.uimanager.events.TouchEventType;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
// NativeGestureUtil.notifyNativeGestureStarted
|
||||
|
||||
/**
|
||||
|
||||
@@ -11,7 +11,6 @@ package com.horcrux.svg;
|
||||
|
||||
import android.view.ViewGroup;
|
||||
|
||||
//import com.facebook.react.uimanager.ReactStylesDiffMap;
|
||||
import com.facebook.react.uimanager.ThemedReactContext;
|
||||
import com.facebook.react.uimanager.ViewGroupManager;
|
||||
|
||||
@@ -34,6 +33,8 @@ public class RNSVGRenderableViewManager extends ViewGroupManager<ViewGroup> {
|
||||
/* 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_LINEAR_GRADIENT = "RNSVGLinearGradient";
|
||||
/* package */ static final String CLASS_RADIAL_GRADIENT = "RNSVGRadialGradient";
|
||||
|
||||
private final String mClassName;
|
||||
|
||||
@@ -87,6 +88,14 @@ public class RNSVGRenderableViewManager extends ViewGroupManager<ViewGroup> {
|
||||
return new RNSVGRenderableViewManager(CLASS_VIEW_BOX);
|
||||
}
|
||||
|
||||
public static RNSVGRenderableViewManager createRNSVGLinearGradientManager() {
|
||||
return new RNSVGRenderableViewManager(CLASS_LINEAR_GRADIENT);
|
||||
}
|
||||
|
||||
public static RNSVGRenderableViewManager createRNSVGRadialGradientManager() {
|
||||
return new RNSVGRenderableViewManager(CLASS_RADIAL_GRADIENT);
|
||||
}
|
||||
|
||||
private RNSVGRenderableViewManager(String className) {
|
||||
mClassName = className;
|
||||
}
|
||||
@@ -135,6 +144,12 @@ public class RNSVGRenderableViewManager extends ViewGroupManager<ViewGroup> {
|
||||
case CLASS_VIEW_BOX:
|
||||
mVirtualNode = new RNSVGViewBoxShadowNode();
|
||||
break;
|
||||
case CLASS_LINEAR_GRADIENT:
|
||||
mVirtualNode = new RNSVGLinearGradientShadowNode();
|
||||
break;
|
||||
case CLASS_RADIAL_GRADIENT:
|
||||
mVirtualNode = new RNSVGRadialGradientShadowNode();
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException("Unexpected type " + mClassName);
|
||||
}
|
||||
@@ -170,6 +185,10 @@ public class RNSVGRenderableViewManager extends ViewGroupManager<ViewGroup> {
|
||||
return RNSVGUseShadowNode.class;
|
||||
case CLASS_VIEW_BOX:
|
||||
return RNSVGViewBoxShadowNode.class;
|
||||
case CLASS_LINEAR_GRADIENT:
|
||||
return RNSVGLinearGradientShadowNode.class;
|
||||
case CLASS_RADIAL_GRADIENT:
|
||||
return RNSVGRadialGradientShadowNode.class;
|
||||
default:
|
||||
throw new IllegalStateException("Unexpected type " + mClassName);
|
||||
}
|
||||
|
||||
@@ -19,21 +19,15 @@ import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
import com.facebook.infer.annotation.Assertions;
|
||||
import com.facebook.react.common.SystemClock;
|
||||
import com.facebook.react.touch.OnInterceptTouchEventListener;
|
||||
import com.facebook.react.touch.ReactInterceptingViewGroup;
|
||||
import com.facebook.react.uimanager.ThemedReactContext;
|
||||
import com.facebook.react.uimanager.TouchTargetHelper;
|
||||
import com.facebook.react.uimanager.UIManagerModule;
|
||||
import com.facebook.react.uimanager.events.TouchEvent;
|
||||
import com.facebook.react.uimanager.events.TouchEventCoalescingKeyHelper;
|
||||
import com.facebook.react.uimanager.events.TouchEventType;
|
||||
import com.facebook.react.views.view.ReactClippingViewGroup;
|
||||
import com.facebook.react.uimanager.events.EventDispatcher;
|
||||
import com.facebook.react.uimanager.events.NativeGestureUtil;
|
||||
|
||||
// NativeGestureUtil.notifyNativeGestureStarted
|
||||
/**
|
||||
|
||||
@@ -11,9 +11,7 @@ package com.horcrux.svg;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.Point;
|
||||
import android.util.Log;
|
||||
import android.view.ViewGroup;
|
||||
@@ -30,10 +28,9 @@ import java.util.Map;
|
||||
public class RNSVGSvgViewShadowNode extends LayoutShadowNode {
|
||||
|
||||
private boolean mResponsible = false;
|
||||
|
||||
private static final Map<String, RNSVGVirtualNode> mDefinedClipPaths = new HashMap<>();
|
||||
|
||||
private static final Map<String, RNSVGVirtualNode> mDefinedTemplates = new HashMap<>();
|
||||
private static final Map<String, PropHelper.RNSVGBrush> mDefinedBrushes = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void onCollectExtraUpdates(UIViewOperationQueue uiUpdater) {
|
||||
@@ -54,7 +51,17 @@ public class RNSVGSvgViewShadowNode extends LayoutShadowNode {
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
public void drawChildren(Canvas canvas, Paint paint) {
|
||||
/**
|
||||
* Draw all of the child nodes of this root node
|
||||
*
|
||||
* This method is synchronized since
|
||||
* {@link com.horcrux.svg.RNSVGImageShadowNode#loadImage(ImageRequest, Canvas, Paint)} calls it
|
||||
* asynchronously after images have loaded and are ready to be drawn.
|
||||
*
|
||||
* @param canvas
|
||||
* @param paint
|
||||
*/
|
||||
public synchronized void drawChildren(Canvas canvas, Paint paint) {
|
||||
for (int i = 0; i < getChildCount(); i++) {
|
||||
RNSVGVirtualNode child = (RNSVGVirtualNode) getChildAt(i);
|
||||
child.setupDimensions(canvas);
|
||||
@@ -114,4 +121,15 @@ public class RNSVGSvgViewShadowNode extends LayoutShadowNode {
|
||||
return mDefinedTemplates.get(templateRef);
|
||||
}
|
||||
|
||||
public void defineBrush(PropHelper.RNSVGBrush brush, String brushRef) {
|
||||
mDefinedBrushes.put(brushRef, brush);
|
||||
}
|
||||
|
||||
public void removeBrush(String brushRef) {
|
||||
mDefinedBrushes.remove(brushRef);
|
||||
}
|
||||
|
||||
public PropHelper.RNSVGBrush getDefinedBrush(String brushRef) {
|
||||
return mDefinedBrushes.get(brushRef);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import javax.annotation.Nullable;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.Point;
|
||||
@@ -22,7 +23,6 @@ import android.graphics.Typeface;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.facebook.react.bridge.ReadableArray;
|
||||
import com.facebook.react.bridge.ReadableMap;
|
||||
@@ -102,6 +102,9 @@ public class RNSVGTextShadowNode extends RNSVGPathShadowNode {
|
||||
if (mPath == null) {
|
||||
canvas.drawText(text, 0, -paint.ascent(), paint);
|
||||
} else {
|
||||
Matrix matrix = new Matrix();
|
||||
matrix.setTranslate(0, -paint.getTextSize() * 1.1f);
|
||||
mPath.transform(matrix);
|
||||
canvas.drawTextOnPath(text, mPath, 0, -paint.ascent(), paint);
|
||||
}
|
||||
}
|
||||
@@ -186,6 +189,7 @@ public class RNSVGTextShadowNode extends RNSVGPathShadowNode {
|
||||
if (setupFillPaint(paint, 1.0f, getBox(paint, text))) {
|
||||
applyTextPropertiesToPaint(paint);
|
||||
paint.getTextPath(text, 0, text.length(), 0, -paint.ascent(), path);
|
||||
path.transform(mMatrix);
|
||||
}
|
||||
|
||||
return path;
|
||||
|
||||
@@ -11,15 +11,12 @@ package com.horcrux.svg;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.util.Log;
|
||||
|
||||
import com.facebook.common.logging.FLog;
|
||||
import com.facebook.react.common.ReactConstants;
|
||||
import com.facebook.react.uimanager.annotations.ReactProp;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Shadow node for virtual RNSVGPath view
|
||||
*/
|
||||
|
||||
@@ -10,9 +10,7 @@
|
||||
package com.horcrux.svg;
|
||||
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.util.Log;
|
||||
|
||||
import com.facebook.react.bridge.ReadableArray;
|
||||
|
||||
@@ -11,33 +11,23 @@ package com.horcrux.svg;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.Region;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.facebook.react.bridge.JSApplicationIllegalArgumentException;
|
||||
import com.facebook.react.bridge.ReadableArray;
|
||||
import com.facebook.react.uimanager.DisplayMetricsHolder;
|
||||
import com.facebook.react.uimanager.LayoutShadowNode;
|
||||
import com.facebook.react.uimanager.ThemedReactContext;
|
||||
import com.facebook.react.uimanager.annotations.ReactProp;
|
||||
import com.facebook.react.uimanager.ReactShadowNode;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Base class for RNSVGView virtual nodes: {@link RNSVGGroupShadowNode}, {@link RNSVGPathShadowNode} and
|
||||
@@ -76,7 +66,7 @@ public abstract class RNSVGVirtualNode extends LayoutShadowNode {
|
||||
private RNSVGSvgViewShadowNode mSvgShadowNode;
|
||||
|
||||
public RNSVGVirtualNode() {
|
||||
mScale = DisplayMetricsHolder.getWindowDisplayMetrics().density;
|
||||
mScale = DisplayMetricsHolder.getScreenDisplayMetrics().density;
|
||||
}
|
||||
|
||||
public abstract void draw(Canvas canvas, Paint paint, float opacity);
|
||||
|
||||
@@ -37,6 +37,8 @@ public class RNSvgPackage implements ReactPackage {
|
||||
RNSVGRenderableViewManager.createRNSVGDefsViewManager(),
|
||||
RNSVGRenderableViewManager.createRNSVGUseViewManager(),
|
||||
RNSVGRenderableViewManager.createRNSVGViewBoxViewManager(),
|
||||
RNSVGRenderableViewManager.createRNSVGLinearGradientManager(),
|
||||
RNSVGRenderableViewManager.createRNSVGRadialGradientManager(),
|
||||
new RNSVGSvgViewManager());
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,6 @@
|
||||
|
||||
- (void) drawLinearGradient:(CGContextRef)context;
|
||||
|
||||
- (void)drawRidialGradient:(CGContextRef)context;
|
||||
- (void) drawRidialGradient:(CGContextRef)context;
|
||||
|
||||
@end
|
||||
@@ -313,10 +313,10 @@
|
||||
10ABC7381D43982B006CCF6E /* RNSVGVBMOS.h */,
|
||||
10ABC7371D439779006CCF6E /* RNSVGCGFCRule.h */,
|
||||
1039D2AE1CE72F27001E90A8 /* RNSVGPercentageConverter.h */,
|
||||
1039D2AF1CE72F27001E90A8 /* RNSVGPercentageConverter.m */,
|
||||
1039D29B1CE72177001E90A8 /* RCTConvert+RNSVG.h */,
|
||||
1039D29C1CE72177001E90A8 /* RCTConvert+RNSVG.m */,
|
||||
1039D29E1CE72177001E90A8 /* RNSVGCGFloatArray.h */,
|
||||
1039D2AF1CE72F27001E90A8 /* RNSVGPercentageConverter.m */,
|
||||
);
|
||||
name = Utils;
|
||||
sourceTree = "<group>";
|
||||
|
||||
Reference in New Issue
Block a user