mirror of
https://github.com/zoriya/react-native-svg.git
synced 2025-12-20 14:05:09 +00:00
Merge branch 'master' into NativeAnimation
# Conflicts: # android/src/main/java/com/horcrux/svg/RenderableShadowNode.java # android/src/main/java/com/horcrux/svg/SvgViewShadowNode.java # elements/Image.js # elements/Rect.js # elements/Use.js # lib/attributes.js
This commit is contained in:
@@ -179,7 +179,7 @@
|
|||||||
"no-underscore-dangle": 0, // disallow dangling underscores in identifiers
|
"no-underscore-dangle": 0, // disallow dangling underscores in identifiers
|
||||||
//"no-wrap-func": 1, // disallow wrapping of non-IIFE statements in parens
|
//"no-wrap-func": 1, // disallow wrapping of non-IIFE statements in parens
|
||||||
"no-mixed-spaces-and-tabs": 1, // disallow mixed spaces and tabs for indentation
|
"no-mixed-spaces-and-tabs": 1, // disallow mixed spaces and tabs for indentation
|
||||||
"quotes": [1, "single", "avoid-escape"], // specify whether double or single quotes should be used
|
"quotes": [1, "double", "avoid-escape"], // specify whether double or single quotes should be used
|
||||||
"quote-props": 0, // require quotes around object literal property names (off by default)
|
"quote-props": 0, // require quotes around object literal property names (off by default)
|
||||||
"semi": 1, // require or disallow use of semicolons instead of ASI
|
"semi": 1, // require or disallow use of semicolons instead of ASI
|
||||||
"sort-vars": 0, // sort variables within the same declaration block (off by default)
|
"sort-vars": 0, // sort variables within the same declaration block (off by default)
|
||||||
|
|||||||
24
README.md
24
README.md
@@ -43,13 +43,27 @@
|
|||||||
react-native link react-native-svg
|
react-native link react-native-svg
|
||||||
```
|
```
|
||||||
|
|
||||||
A bug in react-native currently links the tvOS library into the iOS project as well.
|
* A bug in react-native currently links the tvOS library into the iOS project as well.
|
||||||
|
|
||||||
Until the fix is released:
|
Until the fix is released:
|
||||||
https://github.com/facebook/react-native/issues/13783
|
https://github.com/facebook/react-native/issues/13783
|
||||||
https://github.com/facebook/react-native/commit/a63fd378a47173cc9f750e9980f18dc12dd7ea51
|
https://github.com/facebook/react-native/commit/a63fd378a47173cc9f750e9980f18dc12dd7ea51
|
||||||
|
|
||||||
|
Follow the instructions here: https://github.com/react-native-community/react-native-svg/issues/544
|
||||||
|
|
||||||
|
* If `cocoapods` is used and if error `RNSVGImage.m:12:9: 'React/RCTImageLoader.h' file not found` occurs:
|
||||||
|
|
||||||
|
Add the following entry in Podfile:
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
pod 'React', :path => '../node_modules/react-native', :subspecs => [
|
||||||
|
[...]
|
||||||
|
'RCTImage', # !!!!!
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
and run `pod install` from `ios` folder
|
||||||
|
|
||||||
Follow the instructions here: https://github.com/react-native-community/react-native-svg/issues/544
|
|
||||||
|
|
||||||
#### Manual
|
#### Manual
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,14 @@
|
|||||||
|
def safeExtGet(prop, fallback) {
|
||||||
|
rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
|
||||||
|
}
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
repositories {
|
repositories {
|
||||||
jcenter()
|
jcenter()
|
||||||
|
maven {
|
||||||
|
url 'https://maven.google.com/'
|
||||||
|
name 'Google'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
@@ -12,16 +20,14 @@ buildscript {
|
|||||||
apply plugin: 'com.android.library'
|
apply plugin: 'com.android.library'
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 23
|
compileSdkVersion safeExtGet('compileSdkVersion', 26)
|
||||||
//noinspection GradleDependency
|
//noinspection GradleDependency
|
||||||
buildToolsVersion "23.0.1"
|
buildToolsVersion safeExtGet('buildToolsVersion', '26.0.3')
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdkVersion 16
|
minSdkVersion safeExtGet('minSdkVersion', 16)
|
||||||
//noinspection OldTargetApi
|
//noinspection OldTargetApi
|
||||||
targetSdkVersion 22
|
targetSdkVersion safeExtGet('targetSdkVersion', 26)
|
||||||
versionCode 1
|
|
||||||
versionName "1.0"
|
|
||||||
}
|
}
|
||||||
lintOptions {
|
lintOptions {
|
||||||
abortOnError false
|
abortOnError false
|
||||||
@@ -35,6 +41,10 @@ repositories {
|
|||||||
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
|
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
|
||||||
url "$projectDir/../../../node_modules/react-native/android"
|
url "$projectDir/../../../node_modules/react-native/android"
|
||||||
}
|
}
|
||||||
|
maven {
|
||||||
|
url 'https://maven.google.com/'
|
||||||
|
name 'Google'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|||||||
@@ -18,7 +18,9 @@ import android.graphics.Rect;
|
|||||||
import android.graphics.RectF;
|
import android.graphics.RectF;
|
||||||
import android.graphics.Shader;
|
import android.graphics.Shader;
|
||||||
|
|
||||||
|
import com.facebook.common.logging.FLog;
|
||||||
import com.facebook.react.bridge.ReadableArray;
|
import com.facebook.react.bridge.ReadableArray;
|
||||||
|
import com.facebook.react.common.ReactConstants;
|
||||||
|
|
||||||
class Brush {
|
class Brush {
|
||||||
private BrushType mType = BrushType.LINEAR_GRADIENT;
|
private BrushType mType = BrushType.LINEAR_GRADIENT;
|
||||||
@@ -108,6 +110,17 @@ class Brush {
|
|||||||
float[] stops = new float[stopsCount];
|
float[] stops = new float[stopsCount];
|
||||||
parseGradientStops(mColors, stopsCount, stops, stopsColors, opacity);
|
parseGradientStops(mColors, stopsCount, stops, stopsColors, opacity);
|
||||||
|
|
||||||
|
if (stops.length == 1) {
|
||||||
|
// Gradient with only one stop will make LinearGradient/RadialGradient
|
||||||
|
// throw. It may happen when source SVG contains only one stop or
|
||||||
|
// two stops at the same spot (see lib/extract/extractGradient.js).
|
||||||
|
// Although it's mistake SVGs like this can be produced by vector
|
||||||
|
// editors or other tools, so let's handle that gracefully.
|
||||||
|
stopsColors = new int[] { stopsColors[0], stopsColors[0] };
|
||||||
|
stops = new float[] { stops[0], stops[0] };
|
||||||
|
FLog.w(ReactConstants.TAG, "Gradient contains only on stop");
|
||||||
|
}
|
||||||
|
|
||||||
if (mType == BrushType.LINEAR_GRADIENT) {
|
if (mType == BrushType.LINEAR_GRADIENT) {
|
||||||
double x1 = PropHelper.fromRelative(mPoints.getString(0), width, offsetX, scale, paint.getTextSize());
|
double x1 = PropHelper.fromRelative(mPoints.getString(0), width, offsetX, scale, paint.getTextSize());
|
||||||
double y1 = PropHelper.fromRelative(mPoints.getString(1), height, offsetY, scale, paint.getTextSize());
|
double y1 = PropHelper.fromRelative(mPoints.getString(1), height, offsetY, scale, paint.getTextSize());
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ class GroupShadowNode extends RenderableShadowNode {
|
|||||||
pushGlyphContext();
|
pushGlyphContext();
|
||||||
final SvgViewShadowNode svg = getSvgShadowNode();
|
final SvgViewShadowNode svg = getSvgShadowNode();
|
||||||
final GroupShadowNode self = this;
|
final GroupShadowNode self = this;
|
||||||
|
final RectF groupRect = new RectF();
|
||||||
traverseChildren(new NodeRunnable() {
|
traverseChildren(new NodeRunnable() {
|
||||||
public void run(ReactShadowNode lNode) {
|
public void run(ReactShadowNode lNode) {
|
||||||
if (lNode instanceof VirtualNode) {
|
if (lNode instanceof VirtualNode) {
|
||||||
@@ -79,6 +80,11 @@ class GroupShadowNode extends RenderableShadowNode {
|
|||||||
|
|
||||||
int count = node.saveAndSetupCanvas(canvas);
|
int count = node.saveAndSetupCanvas(canvas);
|
||||||
node.draw(canvas, paint, opacity * mOpacity);
|
node.draw(canvas, paint, opacity * mOpacity);
|
||||||
|
RectF r = node.getClientRect();
|
||||||
|
if (r != null) {
|
||||||
|
groupRect.union(r);
|
||||||
|
}
|
||||||
|
|
||||||
node.restoreCanvas(canvas, count);
|
node.restoreCanvas(canvas, count);
|
||||||
|
|
||||||
if (node instanceof RenderableShadowNode) {
|
if (node instanceof RenderableShadowNode) {
|
||||||
@@ -98,6 +104,7 @@ class GroupShadowNode extends RenderableShadowNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
this.setClientRect(groupRect);
|
||||||
popGlyphContext();
|
popGlyphContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import com.facebook.react.bridge.ReadableMap;
|
|||||||
import com.facebook.react.common.ReactConstants;
|
import com.facebook.react.common.ReactConstants;
|
||||||
import com.facebook.react.uimanager.annotations.ReactProp;
|
import com.facebook.react.uimanager.annotations.ReactProp;
|
||||||
import com.facebook.react.views.imagehelper.ResourceDrawableIdHelper;
|
import com.facebook.react.views.imagehelper.ResourceDrawableIdHelper;
|
||||||
|
import com.facebook.react.views.imagehelper.ImageSource;
|
||||||
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
@@ -50,6 +51,7 @@ class ImageShadowNode extends RenderableShadowNode {
|
|||||||
private String mW;
|
private String mW;
|
||||||
private String mH;
|
private String mH;
|
||||||
private Uri mUri;
|
private Uri mUri;
|
||||||
|
private String uriString;
|
||||||
private int mImageWidth;
|
private int mImageWidth;
|
||||||
private int mImageHeight;
|
private int mImageHeight;
|
||||||
private String mAlign;
|
private String mAlign;
|
||||||
@@ -90,7 +92,7 @@ class ImageShadowNode extends RenderableShadowNode {
|
|||||||
@ReactProp(name = "src")
|
@ReactProp(name = "src")
|
||||||
public void setSrc(@Nullable ReadableMap src) {
|
public void setSrc(@Nullable ReadableMap src) {
|
||||||
if (src != null) {
|
if (src != null) {
|
||||||
String uriString = src.getString("uri");
|
uriString = src.getString("uri");
|
||||||
|
|
||||||
if (uriString == null || uriString.isEmpty()) {
|
if (uriString == null || uriString.isEmpty()) {
|
||||||
//TODO: give warning about this
|
//TODO: give warning about this
|
||||||
@@ -147,7 +149,9 @@ class ImageShadowNode extends RenderableShadowNode {
|
|||||||
@Override
|
@Override
|
||||||
public void draw(final Canvas canvas, final Paint paint, final float opacity) {
|
public void draw(final Canvas canvas, final Paint paint, final float opacity) {
|
||||||
if (!mLoading.get()) {
|
if (!mLoading.get()) {
|
||||||
final ImageRequest request = ImageRequestBuilder.newBuilderWithSource(mUri).build();
|
final ImageSource imageSource = new ImageSource(getThemedContext(), uriString);
|
||||||
|
|
||||||
|
final ImageRequest request = ImageRequestBuilder.newBuilderWithSource(imageSource.getUri()).build();
|
||||||
if (Fresco.getImagePipeline().isInBitmapMemoryCache(request)) {
|
if (Fresco.getImagePipeline().isInBitmapMemoryCache(request)) {
|
||||||
tryRender(request, canvas, paint, opacity * mOpacity);
|
tryRender(request, canvas, paint, opacity * mOpacity);
|
||||||
} else {
|
} else {
|
||||||
@@ -170,7 +174,10 @@ class ImageShadowNode extends RenderableShadowNode {
|
|||||||
@Override
|
@Override
|
||||||
public void onNewResultImpl(Bitmap bitmap) {
|
public void onNewResultImpl(Bitmap bitmap) {
|
||||||
mLoading.set(false);
|
mLoading.set(false);
|
||||||
bitmapTryRender(bitmap, canvas, paint, opacity * mOpacity);
|
SvgViewShadowNode shadowNode = getSvgShadowNode();
|
||||||
|
if(shadowNode != null) {
|
||||||
|
shadowNode.markUpdated();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -562,10 +562,10 @@ class PropHelper {
|
|||||||
arc -= Math.PI * 2;
|
arc -= Math.PI * 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
int n = (int) Math.ceil(Math.abs(arc / (Math.PI / 2)));
|
int n = (int) Math.ceil(Math.abs(round(arc / (Math.PI / 2), 4)));
|
||||||
|
|
||||||
float step = arc / n;
|
float step = arc / n;
|
||||||
float k = (4 / 3) * (float) Math.tan(step / 4);
|
float k = (float) ((4 / 3.0) * Math.tan(step / 4));
|
||||||
|
|
||||||
float x = (float) Math.cos(sa);
|
float x = (float) Math.cos(sa);
|
||||||
float y = (float) Math.sin(sa);
|
float y = (float) Math.sin(sa);
|
||||||
@@ -581,14 +581,14 @@ class PropHelper {
|
|||||||
float cp2x = x + k * y;
|
float cp2x = x + k * y;
|
||||||
float cp2y = y - k * x;
|
float cp2y = y - k * x;
|
||||||
|
|
||||||
mPath.cubicTo(
|
float c1x = (cx + xx * cp1x + yx * cp1y);
|
||||||
(cx + xx * cp1x + yx * cp1y) * mScale,
|
float c1y = (cy + xy * cp1x + yy * cp1y);
|
||||||
(cy + xy * cp1x + yy * cp1y) * mScale,
|
float c2x = (cx + xx * cp2x + yx * cp2y);
|
||||||
(cx + xx * cp2x + yx * cp2y) * mScale,
|
float c2y = (cy + xy * cp2x + yy * cp2y);
|
||||||
(cy + xy * cp2x + yy * cp2y) * mScale,
|
float ex = (cx + xx * x + yx * y);
|
||||||
(cx + xx * x + yx * y) * mScale,
|
float ey = (cy + xy * x + yy * y);
|
||||||
(cy + xy * x + yy * y) * mScale
|
|
||||||
);
|
mPath.cubicTo(c1x * mScale, c1y * mScale, c2x * mScale, c2y * mScale, ex * mScale, ey * mScale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -599,5 +599,10 @@ class PropHelper {
|
|||||||
mPendDownSet = true;
|
mPendDownSet = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private double round(double val, int sigDig) {
|
||||||
|
double multiplier = Math.pow(10, sigDig);
|
||||||
|
return Math.round(val * multiplier) / multiplier;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ package com.horcrux.svg;
|
|||||||
|
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.DashPathEffect;
|
import android.graphics.DashPathEffect;
|
||||||
|
import android.graphics.Matrix;
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
import android.graphics.Path;
|
import android.graphics.Path;
|
||||||
import android.graphics.RectF;
|
import android.graphics.RectF;
|
||||||
@@ -23,14 +24,16 @@ import com.facebook.react.bridge.JavaOnlyArray;
|
|||||||
import com.facebook.react.bridge.ReadableArray;
|
import com.facebook.react.bridge.ReadableArray;
|
||||||
import com.facebook.react.bridge.ReadableType;
|
import com.facebook.react.bridge.ReadableType;
|
||||||
import com.facebook.react.bridge.WritableArray;
|
import com.facebook.react.bridge.WritableArray;
|
||||||
|
import com.facebook.react.uimanager.OnLayoutEvent;
|
||||||
|
import com.facebook.react.uimanager.UIManagerModule;
|
||||||
import com.facebook.react.uimanager.annotations.ReactProp;
|
import com.facebook.react.uimanager.annotations.ReactProp;
|
||||||
|
import com.facebook.react.uimanager.events.EventDispatcher;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -68,10 +71,10 @@ abstract public class RenderableShadowNode extends VirtualNode {
|
|||||||
public float mFillOpacity = 1;
|
public float mFillOpacity = 1;
|
||||||
public Path.FillType mFillRule = Path.FillType.WINDING;
|
public Path.FillType mFillRule = Path.FillType.WINDING;
|
||||||
|
|
||||||
private @Nullable ReadableArray mLastMergedList;
|
private @Nullable ArrayList<String> mLastMergedList;
|
||||||
private @Nullable ArrayList<Object> mOriginProperties;
|
private @Nullable ArrayList<Object> mOriginProperties;
|
||||||
protected @Nullable ReadableArray mPropList;
|
protected @Nullable ArrayList<String> mPropList;
|
||||||
protected @Nullable WritableArray mAttributeList;
|
protected @Nullable ArrayList<String> mAttributeList;
|
||||||
|
|
||||||
static final Pattern regex = Pattern.compile("[0-9.-]+");
|
static final Pattern regex = Pattern.compile("[0-9.-]+");
|
||||||
|
|
||||||
@@ -213,12 +216,11 @@ abstract public class RenderableShadowNode extends VirtualNode {
|
|||||||
@ReactProp(name = "propList")
|
@ReactProp(name = "propList")
|
||||||
public void setPropList(@Nullable ReadableArray propList) {
|
public void setPropList(@Nullable ReadableArray propList) {
|
||||||
if (propList != null) {
|
if (propList != null) {
|
||||||
WritableArray copy = Arguments.createArray();
|
mPropList = mAttributeList = new ArrayList<>();
|
||||||
for (int i = 0; i < propList.size(); i++) {
|
for (int i = 0; i < propList.size(); i++) {
|
||||||
String fieldName = propertyNameToFieldName(propList.getString(i));
|
String fieldName = propertyNameToFieldName(propList.getString(i));
|
||||||
copy.pushString(fieldName);
|
mPropList.add(fieldName);
|
||||||
}
|
}
|
||||||
mPropList = mAttributeList = copy;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
markUpdated();
|
markUpdated();
|
||||||
@@ -235,6 +237,12 @@ abstract public class RenderableShadowNode extends VirtualNode {
|
|||||||
}
|
}
|
||||||
Path path = mPath;
|
Path path = mPath;
|
||||||
|
|
||||||
|
RectF clientRect = new RectF();
|
||||||
|
path.computeBounds(clientRect, true);
|
||||||
|
Matrix svgToViewMatrix = new Matrix(canvas.getMatrix());
|
||||||
|
svgToViewMatrix.mapRect(clientRect);
|
||||||
|
this.setClientRect(clientRect);
|
||||||
|
|
||||||
clip(canvas, paint);
|
clip(canvas, paint);
|
||||||
|
|
||||||
if (setupFillPaint(paint, opacity * mFillOpacity)) {
|
if (setupFillPaint(paint, opacity * mFillOpacity)) {
|
||||||
@@ -327,10 +335,10 @@ abstract public class RenderableShadowNode extends VirtualNode {
|
|||||||
int x = Math.round(dst[0]);
|
int x = Math.round(dst[0]);
|
||||||
int y = Math.round(dst[1]);
|
int y = Math.round(dst[1]);
|
||||||
|
|
||||||
if (mRegion == null) {
|
if (mRegion == null && mPath != null) {
|
||||||
mRegion = getRegion(mPath);
|
mRegion = getRegion(mPath);
|
||||||
}
|
}
|
||||||
if (!mRegion.contains(x, y)) {
|
if (mRegion == null || !mRegion.contains(x, y)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -365,12 +373,12 @@ abstract public class RenderableShadowNode extends VirtualNode {
|
|||||||
return region;
|
return region;
|
||||||
}
|
}
|
||||||
|
|
||||||
private WritableArray getAttributeList() {
|
private ArrayList<String> getAttributeList() {
|
||||||
return mAttributeList;
|
return mAttributeList;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mergeProperties(RenderableShadowNode target) {
|
void mergeProperties(RenderableShadowNode target) {
|
||||||
WritableArray targetAttributeList = target.getAttributeList();
|
ArrayList<String> targetAttributeList = target.getAttributeList();
|
||||||
|
|
||||||
if (targetAttributeList == null ||
|
if (targetAttributeList == null ||
|
||||||
targetAttributeList.size() == 0) {
|
targetAttributeList.size() == 0) {
|
||||||
@@ -378,17 +386,17 @@ abstract public class RenderableShadowNode extends VirtualNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mOriginProperties = new ArrayList<>();
|
mOriginProperties = new ArrayList<>();
|
||||||
mAttributeList = clonePropList();
|
mAttributeList = mPropList == null ? new ArrayList<String>() : new ArrayList<>(mPropList);
|
||||||
|
|
||||||
for (int i = 0, size = targetAttributeList.size(); i < size; i++) {
|
for (int i = 0, size = targetAttributeList.size(); i < size; i++) {
|
||||||
try {
|
try {
|
||||||
String fieldName = targetAttributeList.getString(i);
|
String fieldName = targetAttributeList.get(i);
|
||||||
Field field = getClass().getField(fieldName);
|
Field field = getClass().getField(fieldName);
|
||||||
Object value = field.get(target);
|
Object value = field.get(target);
|
||||||
mOriginProperties.add(field.get(this));
|
mOriginProperties.add(field.get(this));
|
||||||
|
|
||||||
if (!hasOwnProperty(fieldName)) {
|
if (!hasOwnProperty(fieldName)) {
|
||||||
mAttributeList.pushString(fieldName);
|
mAttributeList.add(fieldName);
|
||||||
field.set(this, value);
|
field.set(this, value);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@@ -403,7 +411,7 @@ abstract public class RenderableShadowNode extends VirtualNode {
|
|||||||
if (mLastMergedList != null && mOriginProperties != null) {
|
if (mLastMergedList != null && mOriginProperties != null) {
|
||||||
try {
|
try {
|
||||||
for (int i = mLastMergedList.size() - 1; i >= 0; i--) {
|
for (int i = mLastMergedList.size() - 1; i >= 0; i--) {
|
||||||
Field field = getClass().getField(mLastMergedList.getString(i));
|
Field field = getClass().getField(mLastMergedList.get(i));
|
||||||
field.set(this, mOriginProperties.get(i));
|
field.set(this, mOriginProperties.get(i));
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@@ -412,22 +420,10 @@ abstract public class RenderableShadowNode extends VirtualNode {
|
|||||||
|
|
||||||
mLastMergedList = null;
|
mLastMergedList = null;
|
||||||
mOriginProperties = null;
|
mOriginProperties = null;
|
||||||
mAttributeList = clonePropList();
|
mAttributeList = mPropList;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private @Nonnull WritableArray clonePropList() {
|
|
||||||
WritableArray attributeList = Arguments.createArray();
|
|
||||||
|
|
||||||
if (mPropList != null) {
|
|
||||||
for (int i = 0; i < mPropList.size(); i++) {
|
|
||||||
attributeList.pushString(mPropList.getString(i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return attributeList;
|
|
||||||
}
|
|
||||||
|
|
||||||
// convert propertyName something like fillOpacity to fieldName like mFillOpacity
|
// convert propertyName something like fillOpacity to fieldName like mFillOpacity
|
||||||
private String propertyNameToFieldName(String fieldName) {
|
private String propertyNameToFieldName(String fieldName) {
|
||||||
Pattern pattern = Pattern.compile("^(\\w)");
|
Pattern pattern = Pattern.compile("^(\\w)");
|
||||||
@@ -441,15 +437,6 @@ abstract public class RenderableShadowNode extends VirtualNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean hasOwnProperty(String propName) {
|
private boolean hasOwnProperty(String propName) {
|
||||||
if (mAttributeList == null) {
|
return mAttributeList != null && mAttributeList.contains(propName);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = mAttributeList.size() - 1; i >= 0; i--) {
|
|
||||||
if (mAttributeList.getString(i).equals(propName)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,6 +78,12 @@ public class SvgView extends ViewGroup {
|
|||||||
SvgViewManager.setSvgView(this);
|
SvgViewManager.setSvgView(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onDetachedFromWindow() {
|
||||||
|
super.onDetachedFromWindow();
|
||||||
|
SvgViewManager.dropSvgView(this);
|
||||||
|
}
|
||||||
|
|
||||||
public void setBitmap(Bitmap bitmap) {
|
public void setBitmap(Bitmap bitmap) {
|
||||||
if (mBitmap != null) {
|
if (mBitmap != null) {
|
||||||
mBitmap.recycle();
|
mBitmap.recycle();
|
||||||
@@ -100,11 +106,13 @@ public class SvgView extends ViewGroup {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean dispatchTouchEvent(MotionEvent ev) {
|
public boolean dispatchTouchEvent(MotionEvent ev) {
|
||||||
mTargetTag = getShadowNode().hitTest(new Point((int) ev.getX(), (int) ev.getY()));
|
SvgViewShadowNode node = getShadowNode();
|
||||||
|
if (node != null) {
|
||||||
if (mTargetTag != -1) {
|
mTargetTag = node.hitTest(new Point((int) ev.getX(), (int) ev.getY()));
|
||||||
handleTouchEvent(ev);
|
if (mTargetTag != -1) {
|
||||||
return true;
|
handleTouchEvent(ev);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return super.dispatchTouchEvent(ev);
|
return super.dispatchTouchEvent(ev);
|
||||||
|
|||||||
@@ -51,6 +51,12 @@ class SvgViewManager extends ViewGroupManager<SvgView> {
|
|||||||
mTagToSvgView.put(svg.getId(), svg);
|
mTagToSvgView.put(svg.getId(), svg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void dropSvgView(SvgView view) {
|
||||||
|
int tag = view.getId();
|
||||||
|
mTagToShadowNode.remove(tag);
|
||||||
|
mTagToSvgView.remove(tag);
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
static @Nullable SvgView getSvgViewByTag(int tag) {
|
static @Nullable SvgView getSvgViewByTag(int tag) {
|
||||||
return mTagToSvgView.get(tag);
|
return mTagToSvgView.get(tag);
|
||||||
@@ -77,13 +83,6 @@ class SvgViewManager extends ViewGroupManager<SvgView> {
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDropViewInstance(SvgView view) {
|
|
||||||
int tag = view.getId();
|
|
||||||
mTagToShadowNode.remove(tag);
|
|
||||||
mTagToSvgView.remove(tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected SvgView createViewInstance(ThemedReactContext reactContext) {
|
protected SvgView createViewInstance(ThemedReactContext reactContext) {
|
||||||
return new SvgView(reactContext);
|
return new SvgView(reactContext);
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import com.facebook.react.uimanager.annotations.ReactProp;
|
|||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Stack;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shadow node for RNSVG virtual tree root - RNSVGSvgView
|
* Shadow node for RNSVG virtual tree root - RNSVGSvgView
|
||||||
@@ -53,6 +54,7 @@ public class SvgViewShadowNode extends LayoutShadowNode {
|
|||||||
private Matrix mInvViewBoxMatrix = new Matrix();
|
private Matrix mInvViewBoxMatrix = new Matrix();
|
||||||
private boolean mInvertible = true;
|
private boolean mInvertible = true;
|
||||||
|
|
||||||
|
|
||||||
public SvgViewShadowNode() {
|
public SvgViewShadowNode() {
|
||||||
mScale = DisplayMetricsHolder.getScreenDisplayMetrics().density;
|
mScale = DisplayMetricsHolder.getScreenDisplayMetrics().density;
|
||||||
}
|
}
|
||||||
@@ -155,12 +157,15 @@ public class SvgViewShadowNode extends LayoutShadowNode {
|
|||||||
mCanvas = canvas;
|
mCanvas = canvas;
|
||||||
if (mAlign != null) {
|
if (mAlign != null) {
|
||||||
RectF vbRect = getViewBox();
|
RectF vbRect = getViewBox();
|
||||||
float width = getLayoutWidth();
|
float width;
|
||||||
float height = getLayoutHeight();
|
float height;
|
||||||
boolean nested = Float.isNaN(width) || Float.isNaN(height);
|
boolean nested = getNativeParent() instanceof SvgViewShadowNode;
|
||||||
if (nested) {
|
if (nested) {
|
||||||
width = (float) PropHelper.fromRelative(mbbWidth, canvas.getWidth(), 0f, mScale, 12);
|
width = (float) PropHelper.fromRelative(mbbWidth, canvas.getWidth(), 0f, mScale, 12);
|
||||||
height = (float) PropHelper.fromRelative(mbbHeight, canvas.getHeight(), 0f, mScale, 12);
|
height = (float) PropHelper.fromRelative(mbbHeight, canvas.getHeight(), 0f, mScale, 12);
|
||||||
|
} else {
|
||||||
|
width = getLayoutWidth();
|
||||||
|
height = getLayoutHeight();
|
||||||
}
|
}
|
||||||
RectF eRect = new RectF(0,0, width, height);
|
RectF eRect = new RectF(0,0, width, height);
|
||||||
if (nested) {
|
if (nested) {
|
||||||
@@ -284,4 +289,5 @@ public class SvgViewShadowNode extends LayoutShadowNode {
|
|||||||
runner.run(child);
|
runner.run(child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -946,4 +946,39 @@ class TSpanShadowNode extends TextShadowNode {
|
|||||||
parent = parent.getParent();
|
parent = parent.getParent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hitTest(final float[] src) {
|
||||||
|
if (mContent == null) {
|
||||||
|
return super.hitTest(src);
|
||||||
|
}
|
||||||
|
if (mPath == null || !mInvertible) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
float[] dst = new float[2];
|
||||||
|
mInvMatrix.mapPoints(dst, src);
|
||||||
|
int x = Math.round(dst[0]);
|
||||||
|
int y = Math.round(dst[1]);
|
||||||
|
|
||||||
|
if (mRegion == null && mPath != null) {
|
||||||
|
mRegion = getRegion(mPath);
|
||||||
|
}
|
||||||
|
if (mRegion == null || !mRegion.contains(x, y)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Path clipPath = getClipPath();
|
||||||
|
if (clipPath != null) {
|
||||||
|
if (mClipRegionPath != clipPath) {
|
||||||
|
mClipRegionPath = clipPath;
|
||||||
|
mClipRegion = getRegion(clipPath);
|
||||||
|
}
|
||||||
|
if (!mClipRegion.contains(x, y)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return getReactTag();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,6 +63,8 @@ class UseShadowNode extends RenderableShadowNode {
|
|||||||
template.draw(canvas, paint, opacity * mOpacity);
|
template.draw(canvas, paint, opacity * mOpacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.setClientRect(template.getClientRect());
|
||||||
|
|
||||||
template.restoreCanvas(canvas, count);
|
template.restoreCanvas(canvas, count);
|
||||||
if (template instanceof RenderableShadowNode) {
|
if (template instanceof RenderableShadowNode) {
|
||||||
((RenderableShadowNode)template).resetProperties();
|
((RenderableShadowNode)template).resetProperties();
|
||||||
@@ -73,6 +75,24 @@ class UseShadowNode extends RenderableShadowNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hitTest(float[] src) {
|
||||||
|
if (!mInvertible) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
float[] dst = new float[2];
|
||||||
|
mInvMatrix.mapPoints(dst, src);
|
||||||
|
|
||||||
|
VirtualNode template = getSvgShadowNode().getDefinedTemplate(mHref);
|
||||||
|
int hitChild = template.hitTest(dst);
|
||||||
|
if (hitChild != -1) {
|
||||||
|
return (template.isResponsible() || hitChild != template.getReactTag()) ? hitChild : getReactTag();
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Path getPath(Canvas canvas, Paint paint) {
|
protected Path getPath(Canvas canvas, Paint paint) {
|
||||||
// todo:
|
// todo:
|
||||||
|
|||||||
@@ -21,8 +21,11 @@ import com.facebook.react.bridge.ReadableArray;
|
|||||||
import com.facebook.react.common.ReactConstants;
|
import com.facebook.react.common.ReactConstants;
|
||||||
import com.facebook.react.uimanager.DisplayMetricsHolder;
|
import com.facebook.react.uimanager.DisplayMetricsHolder;
|
||||||
import com.facebook.react.uimanager.LayoutShadowNode;
|
import com.facebook.react.uimanager.LayoutShadowNode;
|
||||||
|
import com.facebook.react.uimanager.OnLayoutEvent;
|
||||||
import com.facebook.react.uimanager.ReactShadowNode;
|
import com.facebook.react.uimanager.ReactShadowNode;
|
||||||
|
import com.facebook.react.uimanager.UIManagerModule;
|
||||||
import com.facebook.react.uimanager.annotations.ReactProp;
|
import com.facebook.react.uimanager.annotations.ReactProp;
|
||||||
|
import com.facebook.react.uimanager.events.EventDispatcher;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
@@ -53,6 +56,7 @@ abstract class VirtualNode extends LayoutShadowNode {
|
|||||||
Matrix mMatrix = new Matrix();
|
Matrix mMatrix = new Matrix();
|
||||||
Matrix mInvMatrix = new Matrix();
|
Matrix mInvMatrix = new Matrix();
|
||||||
boolean mInvertible = true;
|
boolean mInvertible = true;
|
||||||
|
RectF mClientRect;
|
||||||
|
|
||||||
private int mClipRule;
|
private int mClipRule;
|
||||||
private @Nullable String mClipPath;
|
private @Nullable String mClipPath;
|
||||||
@@ -234,7 +238,7 @@ abstract class VirtualNode extends LayoutShadowNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable Path getClipPath(Canvas canvas, Paint paint) {
|
@Nullable Path getClipPath(Canvas canvas, Paint paint) {
|
||||||
if (mClipPath != null && mCachedClipPath == null) {
|
if (mClipPath != null) {
|
||||||
VirtualNode node = getSvgShadowNode().getDefinedClipPath(mClipPath);
|
VirtualNode node = getSvgShadowNode().getDefinedClipPath(mClipPath);
|
||||||
|
|
||||||
if (node != null) {
|
if (node != null) {
|
||||||
@@ -350,4 +354,29 @@ abstract class VirtualNode extends LayoutShadowNode {
|
|||||||
runner.run(child);
|
runner.run(child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setClientRect(RectF rect) {
|
||||||
|
if (mClientRect != null && mClientRect.equals(rect)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mClientRect = rect;
|
||||||
|
if (mClientRect == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
EventDispatcher eventDispatcher = this.getThemedContext()
|
||||||
|
.getNativeModule(UIManagerModule.class)
|
||||||
|
.getEventDispatcher();
|
||||||
|
eventDispatcher.dispatchEvent(OnLayoutEvent.obtain(
|
||||||
|
this.getReactTag(),
|
||||||
|
(int) mClientRect.left,
|
||||||
|
(int) mClientRect.top,
|
||||||
|
(int) mClientRect.width(),
|
||||||
|
(int) mClientRect.height()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
public RectF getClientRect() {
|
||||||
|
return mClientRect;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import React from 'react';
|
import React from "react";
|
||||||
import createReactNativeComponentClass from '../lib/createReactNativeComponentClass';
|
import { requireNativeComponent } from "react-native";
|
||||||
import Shape from './Shape';
|
import Shape from "./Shape";
|
||||||
import {CircleAttributes} from '../lib/attributes';
|
import { CircleAttributes } from "../lib/attributes";
|
||||||
import {pathProps, numberProp} from '../lib/props';
|
import { pathProps, numberProp } from "../lib/props";
|
||||||
import extractProps from '../lib/extract/extractProps';
|
import extractProps from "../lib/extract/extractProps";
|
||||||
|
|
||||||
export default class extends Shape {
|
export default class extends Shape {
|
||||||
static displayName = 'Circle';
|
static displayName = "Circle";
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
...pathProps,
|
...pathProps,
|
||||||
@@ -27,17 +27,20 @@ export default class extends Shape {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
let props = this.props;
|
let props = this.props;
|
||||||
return <RNSVGCircle
|
return (
|
||||||
ref={ele => {this.root = ele;}}
|
<RNSVGCircle
|
||||||
{...extractProps(props, this)}
|
ref={ele => {
|
||||||
cx={props.cx.toString()}
|
this.root = ele;
|
||||||
cy={props.cy.toString()}
|
}}
|
||||||
r={props.r.toString()}
|
{...extractProps(props, this)}
|
||||||
/>;
|
cx={props.cx.toString()}
|
||||||
|
cy={props.cy.toString()}
|
||||||
|
r={props.r.toString()}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const RNSVGCircle = createReactNativeComponentClass('RNSVGCircle', () => ({
|
const RNSVGCircle = requireNativeComponent("RNSVGCircle", null, {
|
||||||
validAttributes: CircleAttributes,
|
nativeOnly: CircleAttributes
|
||||||
uiViewClassName: 'RNSVGCircle'
|
});
|
||||||
}));
|
|
||||||
|
|||||||
@@ -1,20 +1,23 @@
|
|||||||
import React, {Component} from 'react';
|
import React, { Component } from "react";
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from "prop-types";
|
||||||
import createReactNativeComponentClass from '../lib/createReactNativeComponentClass';
|
import { requireNativeComponent } from "react-native";
|
||||||
import {ClipPathAttributes} from '../lib/attributes';
|
import { ClipPathAttributes } from "../lib/attributes";
|
||||||
|
|
||||||
export default class extends Component{
|
export default class extends Component {
|
||||||
static displayName = 'ClipPath';
|
static displayName = "ClipPath";
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
id: PropTypes.string.isRequired
|
id: PropTypes.string.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return <RNSVGClipPath name={this.props.id}>{this.props.children}</RNSVGClipPath>;
|
return (
|
||||||
|
<RNSVGClipPath name={this.props.id}>
|
||||||
|
{this.props.children}
|
||||||
|
</RNSVGClipPath>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const RNSVGClipPath = createReactNativeComponentClass('RNSVGClipPath', () => ({
|
const RNSVGClipPath = requireNativeComponent("RNSVGClipPath", null, {
|
||||||
validAttributes: ClipPathAttributes,
|
nativeOnly: ClipPathAttributes
|
||||||
uiViewClassName: 'RNSVGClipPath'
|
});
|
||||||
}));
|
|
||||||
|
|||||||
@@ -1,15 +1,14 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from "react";
|
||||||
import createReactNativeComponentClass from '../lib/createReactNativeComponentClass';
|
import { requireNativeComponent } from "react-native";
|
||||||
|
|
||||||
export default class extends Component {
|
export default class extends Component {
|
||||||
static displayName = 'Defs';
|
static displayName = "Defs";
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return <RNSVGDefs>{this.props.children}</RNSVGDefs>;
|
return <RNSVGDefs>{this.props.children}</RNSVGDefs>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const RNSVGDefs = createReactNativeComponentClass('RNSVGDefs', () => ({
|
const RNSVGDefs = requireNativeComponent("RNSVGDefs", null, {
|
||||||
validAttributes: {},
|
nativeOnly: {}
|
||||||
uiViewClassName: 'RNSVGDefs'
|
});
|
||||||
}));
|
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import React from 'react';
|
import React from "react";
|
||||||
import createReactNativeComponentClass from '../lib/createReactNativeComponentClass';
|
import { requireNativeComponent } from "react-native";
|
||||||
import Shape from './Shape';
|
import Shape from "./Shape";
|
||||||
import {pathProps, numberProp} from '../lib/props';
|
import { pathProps, numberProp } from "../lib/props";
|
||||||
import {EllipseAttributes} from '../lib/attributes';
|
import { EllipseAttributes } from "../lib/attributes";
|
||||||
import extractProps from '../lib/extract/extractProps';
|
import extractProps from "../lib/extract/extractProps";
|
||||||
|
|
||||||
export default class extends Shape{
|
export default class extends Shape {
|
||||||
static displayName = 'Ellipse';
|
static displayName = "Ellipse";
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
...pathProps,
|
...pathProps,
|
||||||
@@ -30,18 +30,21 @@ export default class extends Shape{
|
|||||||
render() {
|
render() {
|
||||||
let props = this.props;
|
let props = this.props;
|
||||||
|
|
||||||
return <RNSVGEllipse
|
return (
|
||||||
ref={ele => {this.root = ele;}}
|
<RNSVGEllipse
|
||||||
{...extractProps(props, this)}
|
ref={ele => {
|
||||||
cx={props.cx.toString()}
|
this.root = ele;
|
||||||
cy={props.cy.toString()}
|
}}
|
||||||
rx={props.rx.toString()}
|
{...extractProps(props, this)}
|
||||||
ry={props.ry.toString()}
|
cx={props.cx.toString()}
|
||||||
/>;
|
cy={props.cy.toString()}
|
||||||
|
rx={props.rx.toString()}
|
||||||
|
ry={props.ry.toString()}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const RNSVGEllipse = createReactNativeComponentClass('RNSVGEllipse', () => ({
|
const RNSVGEllipse = requireNativeComponent("RNSVGEllipse", null, {
|
||||||
validAttributes: EllipseAttributes,
|
nativeOnly: EllipseAttributes
|
||||||
uiViewClassName: 'RNSVGEllipse'
|
});
|
||||||
}));
|
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
import React from 'react';
|
import React from "react";
|
||||||
import createReactNativeComponentClass from '../lib/createReactNativeComponentClass';
|
import { requireNativeComponent } from "react-native";
|
||||||
import Shape from './Shape';
|
import Shape from "./Shape";
|
||||||
import {pathProps, fontProps} from '../lib/props';
|
import { pathProps, fontProps } from "../lib/props";
|
||||||
import {GroupAttributes} from '../lib/attributes';
|
import { GroupAttributes } from "../lib/attributes";
|
||||||
import extractProps from '../lib/extract/extractProps';
|
import extractProps from "../lib/extract/extractProps";
|
||||||
import {extractFont} from '../lib/extract/extractText';
|
import { extractFont } from "../lib/extract/extractText";
|
||||||
|
|
||||||
export default class extends Shape{
|
export default class extends Shape {
|
||||||
static displayName = 'G';
|
static displayName = "G";
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
...pathProps,
|
...pathProps,
|
||||||
...fontProps,
|
...fontProps
|
||||||
};
|
};
|
||||||
|
|
||||||
setNativeProps = (...args) => {
|
setNativeProps = (...args) => {
|
||||||
@@ -19,19 +19,22 @@ export default class extends Shape{
|
|||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let {props} = this;
|
let { props } = this;
|
||||||
|
|
||||||
return <RNSVGGroup
|
return (
|
||||||
{...extractProps(props, this)}
|
<RNSVGGroup
|
||||||
font={extractFont(props)}
|
{...extractProps(props, this)}
|
||||||
ref={ele => {this.root = ele;}}
|
font={extractFont(props)}
|
||||||
>
|
ref={ele => {
|
||||||
{props.children}
|
this.root = ele;
|
||||||
</RNSVGGroup>;
|
}}
|
||||||
|
>
|
||||||
|
{props.children}
|
||||||
|
</RNSVGGroup>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const RNSVGGroup = createReactNativeComponentClass('RNSVGGroup', () => ({
|
const RNSVGGroup = requireNativeComponent("RNSVGGroup", null, {
|
||||||
validAttributes: GroupAttributes,
|
nativeOnly: GroupAttributes
|
||||||
uiViewClassName: 'RNSVGGroup'
|
});
|
||||||
}));
|
|
||||||
|
|||||||
@@ -1,19 +1,17 @@
|
|||||||
import React from 'react';
|
import React from "react";
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from "prop-types";
|
||||||
import { Image } from 'react-native';
|
import { Image, requireNativeComponent } from "react-native";
|
||||||
import createReactNativeComponentClass from '../lib/createReactNativeComponentClass';
|
import ImageSourcePropType from 'react-native/Libraries/Image/ImageSourcePropType';
|
||||||
import {ImageAttributes} from '../lib/attributes';
|
import { ImageAttributes } from "../lib/attributes";
|
||||||
import {numberProp, touchableProps, responderProps} from '../lib/props';
|
import { numberProp, touchableProps, responderProps } from "../lib/props";
|
||||||
import Shape from './Shape';
|
import Shape from "./Shape";
|
||||||
//noinspection JSUnresolvedVariable
|
import { meetOrSliceTypes, alignEnum } from "../lib/extract/extractViewBox";
|
||||||
import resolveAssetSource from 'react-native/Libraries/Image/resolveAssetSource';
|
import extractProps from "../lib/extract/extractProps";
|
||||||
import {meetOrSliceTypes, alignEnum} from '../lib/extract/extractViewBox';
|
|
||||||
import extractProps from '../lib/extract/extractProps';
|
|
||||||
|
|
||||||
const spacesRegExp = /\s+/;
|
const spacesRegExp = /\s+/;
|
||||||
|
|
||||||
export default class extends Shape {
|
export default class extends Shape {
|
||||||
static displayName = 'Image';
|
static displayName = "Image";
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
...responderProps,
|
...responderProps,
|
||||||
...touchableProps,
|
...touchableProps,
|
||||||
@@ -21,7 +19,7 @@ export default class extends Shape {
|
|||||||
y: numberProp,
|
y: numberProp,
|
||||||
width: numberProp.isRequired,
|
width: numberProp.isRequired,
|
||||||
height: numberProp.isRequired,
|
height: numberProp.isRequired,
|
||||||
href: Image.propTypes.source,
|
href: ImageSourcePropType,
|
||||||
preserveAspectRatio: PropTypes.string
|
preserveAspectRatio: PropTypes.string
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -30,7 +28,7 @@ export default class extends Shape {
|
|||||||
y: 0,
|
y: 0,
|
||||||
width: 0,
|
width: 0,
|
||||||
height: 0,
|
height: 0,
|
||||||
preserveAspectRatio: 'xMidYMid meet'
|
preserveAspectRatio: "xMidYMid meet"
|
||||||
};
|
};
|
||||||
|
|
||||||
setNativeProps = (...args) => {
|
setNativeProps = (...args) => {
|
||||||
@@ -38,26 +36,29 @@ export default class extends Shape {
|
|||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let {props} = this;
|
let { props } = this;
|
||||||
let modes = props.preserveAspectRatio.trim().split(spacesRegExp);
|
let modes = props.preserveAspectRatio.trim().split(spacesRegExp);
|
||||||
let meetOrSlice = meetOrSliceTypes[modes[1]] || 0;
|
let meetOrSlice = meetOrSliceTypes[modes[1]] || 0;
|
||||||
let align = alignEnum[modes[0]] || 'xMidYMid';
|
let align = alignEnum[modes[0]] || "xMidYMid";
|
||||||
|
|
||||||
return <RNSVGImage
|
return (
|
||||||
ref={ele => {this.root = ele;}}
|
<RNSVGImage
|
||||||
{...extractProps({...props, x: null, y: null}, this)}
|
ref={ele => {
|
||||||
x={props.x.toString()}
|
this.root = ele;
|
||||||
y={props.y.toString()}
|
}}
|
||||||
imagewidth={props.width.toString()}
|
{...extractProps({ ...props, x: null, y: null }, this)}
|
||||||
imageheight={props.height.toString()}
|
x={props.x.toString()}
|
||||||
meetOrSlice={meetOrSlice}
|
y={props.y.toString()}
|
||||||
align={align}
|
imagewidth={props.width.toString()}
|
||||||
src={resolveAssetSource(props.href)}
|
imageheight={props.height.toString()}
|
||||||
/>;
|
meetOrSlice={meetOrSlice}
|
||||||
|
align={align}
|
||||||
|
src={Image.resolveAssetSource(props.href)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const RNSVGImage = createReactNativeComponentClass('RNSVGImage', () => ({
|
const RNSVGImage = requireNativeComponent("RNSVGImage", null, {
|
||||||
validAttributes: ImageAttributes,
|
nativeOnly: ImageAttributes
|
||||||
uiViewClassName: 'RNSVGImage'
|
});
|
||||||
}));
|
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import React from 'react';
|
import React from "react";
|
||||||
import createReactNativeComponentClass from '../lib/createReactNativeComponentClass';
|
import { requireNativeComponent } from "react-native";
|
||||||
import {LineAttributes} from '../lib/attributes';
|
import { LineAttributes } from "../lib/attributes";
|
||||||
import Shape from './Shape';
|
import Shape from "./Shape";
|
||||||
import {pathProps, numberProp} from '../lib/props';
|
import { pathProps, numberProp } from "../lib/props";
|
||||||
import extractProps from '../lib/extract/extractProps';
|
import extractProps from "../lib/extract/extractProps";
|
||||||
|
|
||||||
export default class extends Shape {
|
export default class extends Shape {
|
||||||
static displayName = 'Line';
|
static displayName = "Line";
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
...pathProps,
|
...pathProps,
|
||||||
@@ -29,18 +29,21 @@ export default class extends Shape {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
let props = this.props;
|
let props = this.props;
|
||||||
return <RNSVGLine
|
return (
|
||||||
ref={ele => {this.root = ele;}}
|
<RNSVGLine
|
||||||
{...extractProps(props, this)}
|
ref={ele => {
|
||||||
x1={props.x1.toString()}
|
this.root = ele;
|
||||||
y1={props.y1.toString()}
|
}}
|
||||||
x2={props.x2.toString()}
|
{...extractProps(props, this)}
|
||||||
y2={props.y2.toString()}
|
x1={props.x1.toString()}
|
||||||
/>;
|
y1={props.y1.toString()}
|
||||||
|
x2={props.x2.toString()}
|
||||||
|
y2={props.y2.toString()}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const RNSVGLine = createReactNativeComponentClass('RNSVGLine', () => ({
|
const RNSVGLine = requireNativeComponent("RNSVGLine", null, {
|
||||||
validAttributes: LineAttributes,
|
nativeOnly: LineAttributes
|
||||||
uiViewClassName: 'RNSVGLine'
|
});
|
||||||
}));
|
|
||||||
|
|||||||
@@ -1,45 +1,46 @@
|
|||||||
import React, {Component} from 'react';
|
import React, { Component } from "react";
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from "prop-types";
|
||||||
import {numberProp} from '../lib/props';
|
import { numberProp } from "../lib/props";
|
||||||
import extractGradient from '../lib/extract/extractGradient';
|
import extractGradient from "../lib/extract/extractGradient";
|
||||||
import createReactNativeComponentClass from '../lib/createReactNativeComponentClass';
|
import { requireNativeComponent } from "react-native";
|
||||||
import {LinearGradientAttributes} from '../lib/attributes';
|
import { LinearGradientAttributes } from "../lib/attributes";
|
||||||
|
|
||||||
export default class extends Component{
|
export default class extends Component {
|
||||||
static displayName = 'LinearGradient';
|
static displayName = "LinearGradient";
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
x1: numberProp.isRequired,
|
x1: numberProp.isRequired,
|
||||||
x2: numberProp.isRequired,
|
x2: numberProp.isRequired,
|
||||||
y1: numberProp.isRequired,
|
y1: numberProp.isRequired,
|
||||||
y2: numberProp.isRequired,
|
y2: numberProp.isRequired,
|
||||||
gradientUnits: PropTypes.oneOf(['objectBoundingBox', 'userSpaceOnUse']),
|
gradientUnits: PropTypes.oneOf(["objectBoundingBox", "userSpaceOnUse"]),
|
||||||
id: PropTypes.string.isRequired
|
id: PropTypes.string.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
x1: '0%',
|
x1: "0%",
|
||||||
y1: '0%',
|
y1: "0%",
|
||||||
x2: '100%',
|
x2: "100%",
|
||||||
y2: '0%'
|
y2: "0%"
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let {props} = this;
|
let { props } = this;
|
||||||
return <RNSVGLinearGradient
|
return (
|
||||||
x1={props.x1.toString()}
|
<RNSVGLinearGradient
|
||||||
y1={props.y1.toString()}
|
x1={props.x1.toString()}
|
||||||
x2={props.x2.toString()}
|
y1={props.y1.toString()}
|
||||||
y2={props.y2.toString()}
|
x2={props.x2.toString()}
|
||||||
{...extractGradient(this.props)}
|
y2={props.y2.toString()}
|
||||||
/>;
|
{...extractGradient(this.props)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const RNSVGLinearGradient = createReactNativeComponentClass(
|
const RNSVGLinearGradient = requireNativeComponent(
|
||||||
'RNSVGLinearGradient',
|
"RNSVGLinearGradient",
|
||||||
() => ({
|
null,
|
||||||
validAttributes: LinearGradientAttributes,
|
{
|
||||||
uiViewClassName: 'RNSVGLinearGradient'
|
nativeOnly: LinearGradientAttributes
|
||||||
})
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import React from 'react';
|
import React from "react";
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from "prop-types";
|
||||||
import createReactNativeComponentClass from '../lib/createReactNativeComponentClass';
|
import { requireNativeComponent } from "react-native";
|
||||||
import {PathAttributes} from '../lib/attributes';
|
import { PathAttributes } from "../lib/attributes";
|
||||||
import Shape from './Shape';
|
import Shape from "./Shape";
|
||||||
import {pathProps} from '../lib/props';
|
import { pathProps } from "../lib/props";
|
||||||
import extractProps from '../lib/extract/extractProps';
|
import extractProps from "../lib/extract/extractProps";
|
||||||
|
|
||||||
export default class extends Shape {
|
export default class extends Shape {
|
||||||
static displayName = 'Path';
|
static displayName = "Path";
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
...pathProps,
|
...pathProps,
|
||||||
@@ -23,7 +23,9 @@ export default class extends Shape {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<RNSVGPath
|
<RNSVGPath
|
||||||
ref={ele => {this.root = ele;}}
|
ref={ele => {
|
||||||
|
this.root = ele;
|
||||||
|
}}
|
||||||
{...extractProps(props, this)}
|
{...extractProps(props, this)}
|
||||||
d={props.d}
|
d={props.d}
|
||||||
/>
|
/>
|
||||||
@@ -31,7 +33,6 @@ export default class extends Shape {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const RNSVGPath = createReactNativeComponentClass('RNSVGPath', () => ({
|
const RNSVGPath = requireNativeComponent("RNSVGPath", null, {
|
||||||
validAttributes: PathAttributes,
|
nativeOnly: PathAttributes
|
||||||
uiViewClassName: 'RNSVGPath'
|
});
|
||||||
}));
|
|
||||||
|
|||||||
@@ -1,20 +1,22 @@
|
|||||||
import {Component} from 'react';
|
import { Component } from "react";
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from "prop-types";
|
||||||
import {numberProp} from '../lib/props';
|
import { numberProp } from "../lib/props";
|
||||||
|
|
||||||
export default class extends Component{
|
export default class extends Component {
|
||||||
static displayName = 'Pattern';
|
static displayName = "Pattern";
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
x1: numberProp,
|
x1: numberProp,
|
||||||
x2: numberProp,
|
x2: numberProp,
|
||||||
y1: numberProp,
|
y1: numberProp,
|
||||||
y2: numberProp,
|
y2: numberProp,
|
||||||
patternTransform: PropTypes.string,
|
patternTransform: PropTypes.string,
|
||||||
patternUnits: PropTypes.oneOf(['userSpaceOnUse', 'objectBoundingBox']),
|
patternUnits: PropTypes.oneOf(["userSpaceOnUse", "objectBoundingBox"]),
|
||||||
patternContentUnits: PropTypes.oneOf(['userSpaceOnUse', 'objectBoundingBox'])
|
patternContentUnits: PropTypes.oneOf([
|
||||||
|
"userSpaceOnUse",
|
||||||
|
"objectBoundingBox"
|
||||||
|
])
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,35 +1,47 @@
|
|||||||
import React, {Component} from 'react';
|
import React, { Component } from "react";
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from "prop-types";
|
||||||
import Path from './Path';
|
import Path from "./Path";
|
||||||
import {pathProps} from '../lib/props';
|
import { pathProps } from "../lib/props";
|
||||||
import extractPolyPoints from '../lib/extract/extractPolyPoints';
|
import extractPolyPoints from "../lib/extract/extractPolyPoints";
|
||||||
|
|
||||||
export default class extends Component{
|
export default class extends Component {
|
||||||
static displayName = 'Polygon';
|
static displayName = "Polygon";
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
...pathProps,
|
...pathProps,
|
||||||
points: PropTypes.oneOfType([PropTypes.string, PropTypes.array]).isRequired
|
points: PropTypes.oneOfType([PropTypes.string, PropTypes.array])
|
||||||
|
.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
points: ''
|
points: ""
|
||||||
};
|
};
|
||||||
|
|
||||||
setNativeProps = (...args) => {
|
setNativeProps = (...args) => {
|
||||||
//noinspection JSUnresolvedFunction
|
//noinspection JSUnresolvedFunction
|
||||||
this.root.getNativeElement().setNativeProps(...args);
|
var points = [...args][0].points;
|
||||||
|
if (points) {
|
||||||
|
if (Array.isArray(points)) {
|
||||||
|
points = points.join(",");
|
||||||
|
}
|
||||||
|
[...args][0].d = `M${extractPolyPoints(points)}`
|
||||||
|
}
|
||||||
|
this.root.setNativeProps(...args);
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let points = this.props.points;
|
let points = this.props.points;
|
||||||
if (Array.isArray(points)) {
|
if (Array.isArray(points)) {
|
||||||
points = points.join(',');
|
points = points.join(",");
|
||||||
}
|
}
|
||||||
|
|
||||||
return <Path
|
return (
|
||||||
ref={ele => {this.root = ele;}}
|
<Path
|
||||||
{...this.props}
|
ref={ele => {
|
||||||
d={`M${extractPolyPoints(points)}z`}
|
this.root = ele;
|
||||||
/>;
|
}}
|
||||||
|
{...this.props}
|
||||||
|
d={`M${extractPolyPoints(points)}z`}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,35 +1,47 @@
|
|||||||
import React, {Component} from 'react';
|
import React, { Component } from "react";
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from "prop-types";
|
||||||
import Path from './Path';
|
import Path from "./Path";
|
||||||
import {pathProps} from '../lib/props';
|
import { pathProps } from "../lib/props";
|
||||||
import extractPolyPoints from '../lib/extract/extractPolyPoints';
|
import extractPolyPoints from "../lib/extract/extractPolyPoints";
|
||||||
|
|
||||||
export default class extends Component{
|
export default class extends Component {
|
||||||
static displayName = 'Polyline';
|
static displayName = "Polyline";
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
...pathProps,
|
...pathProps,
|
||||||
points: PropTypes.oneOfType([PropTypes.string, PropTypes.array]).isRequired
|
points: PropTypes.oneOfType([PropTypes.string, PropTypes.array])
|
||||||
|
.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
points: ''
|
points: ""
|
||||||
};
|
};
|
||||||
|
|
||||||
setNativeProps = (...args) => {
|
setNativeProps = (...args) => {
|
||||||
//noinspection JSUnresolvedFunction
|
//noinspection JSUnresolvedFunction
|
||||||
this.root.getNativeElement().setNativeProps(...args);
|
var points = [...args][0].points;
|
||||||
|
if (points) {
|
||||||
|
if (Array.isArray(points)) {
|
||||||
|
points = points.join(",");
|
||||||
|
}
|
||||||
|
[...args][0].d = `M${extractPolyPoints(points)}`
|
||||||
|
}
|
||||||
|
this.root.setNativeProps(...args);
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let points = this.props.points;
|
let points = this.props.points;
|
||||||
if (Array.isArray(points)) {
|
if (Array.isArray(points)) {
|
||||||
points = points.join(',');
|
points = points.join(",");
|
||||||
}
|
}
|
||||||
|
|
||||||
return <Path
|
return (
|
||||||
ref={ele => {this.root = ele;}}
|
<Path
|
||||||
{...this.props}
|
ref={ele => {
|
||||||
d={`M${extractPolyPoints(points)}`}
|
this.root = ele;
|
||||||
/>;
|
}}
|
||||||
|
{...this.props}
|
||||||
|
d={`M${extractPolyPoints(points)}`}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import React, {Component} from 'react';
|
import React, { Component } from "react";
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from "prop-types";
|
||||||
import {numberProp} from '../lib/props';
|
import { numberProp } from "../lib/props";
|
||||||
import extractGradient from '../lib/extract/extractGradient';
|
import extractGradient from "../lib/extract/extractGradient";
|
||||||
import createReactNativeComponentClass from '../lib/createReactNativeComponentClass';
|
import { requireNativeComponent } from "react-native";
|
||||||
import {RadialGradientAttributes} from '../lib/attributes';
|
import { RadialGradientAttributes } from "../lib/attributes";
|
||||||
|
|
||||||
export default class extends Component{
|
export default class extends Component {
|
||||||
static displayName = 'RadialGradient';
|
static displayName = "RadialGradient";
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
fx: numberProp.isRequired,
|
fx: numberProp.isRequired,
|
||||||
fy: numberProp.isRequired,
|
fy: numberProp.isRequired,
|
||||||
@@ -15,37 +15,38 @@ export default class extends Component{
|
|||||||
cx: numberProp.isRequired,
|
cx: numberProp.isRequired,
|
||||||
cy: numberProp.isRequired,
|
cy: numberProp.isRequired,
|
||||||
r: numberProp,
|
r: numberProp,
|
||||||
gradientUnits: PropTypes.oneOf(['objectBoundingBox', 'userSpaceOnUse']),
|
gradientUnits: PropTypes.oneOf(["objectBoundingBox", "userSpaceOnUse"]),
|
||||||
id: PropTypes.string.isRequired
|
id: PropTypes.string.isRequired
|
||||||
};
|
};
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
fx: '50%',
|
fx: "50%",
|
||||||
fy: '50%',
|
fy: "50%",
|
||||||
cx: '50%',
|
cx: "50%",
|
||||||
cy: '50%',
|
cy: "50%",
|
||||||
r: '50%'
|
r: "50%"
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let {props} = this;
|
let { props } = this;
|
||||||
return <RNSVGRadialGradient
|
return (
|
||||||
fx={props.fx.toString()}
|
<RNSVGRadialGradient
|
||||||
fy={props.fy.toString()}
|
fx={props.fx.toString()}
|
||||||
rx={(props.rx || props.r).toString()}
|
fy={props.fy.toString()}
|
||||||
ry={(props.ry || props.r).toString()}
|
rx={(props.rx || props.r).toString()}
|
||||||
cx={props.cx.toString()}
|
ry={(props.ry || props.r).toString()}
|
||||||
cy={props.cy.toString()}
|
cx={props.cx.toString()}
|
||||||
{...extractGradient(this.props)}
|
cy={props.cy.toString()}
|
||||||
/>;
|
{...extractGradient(this.props)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const RNSVGRadialGradient = createReactNativeComponentClass(
|
const RNSVGRadialGradient = requireNativeComponent(
|
||||||
'RNSVGRadialGradient',
|
"RNSVGRadialGradient",
|
||||||
() => ({
|
null,
|
||||||
validAttributes: RadialGradientAttributes,
|
{
|
||||||
uiViewClassName: 'RNSVGRadialGradient'
|
nativeOnly: RadialGradientAttributes
|
||||||
})
|
}
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import React from 'react';
|
import React from "react";
|
||||||
import './Path'; // must import Path first, don`t know why. without this will throw an `Super expression must either be null or a function, not undefined`
|
import "./Path"; // must import Path first, don`t know why. without this will throw an `Super expression must either be null or a function, not undefined`
|
||||||
import createReactNativeComponentClass from '../lib/createReactNativeComponentClass';
|
import { requireNativeComponent } from "react-native";
|
||||||
import {pathProps, numberProp} from '../lib/props';
|
import { pathProps, numberProp } from "../lib/props";
|
||||||
import {RectAttributes} from '../lib/attributes';
|
import { RectAttributes } from "../lib/attributes";
|
||||||
import extractProps from '../lib/extract/extractProps';
|
import extractProps from "../lib/extract/extractProps";
|
||||||
import Shape from './Shape';
|
import Shape from "./Shape";
|
||||||
|
|
||||||
export default class extends Shape {
|
export default class extends Shape {
|
||||||
static displayName = 'Rect';
|
static displayName = "Rect";
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
...pathProps,
|
...pathProps,
|
||||||
@@ -35,24 +35,30 @@ export default class extends Shape {
|
|||||||
render() {
|
render() {
|
||||||
let props = this.props;
|
let props = this.props;
|
||||||
|
|
||||||
return <RNSVGRect
|
return (
|
||||||
ref={ele => {this.root = ele;}}
|
<RNSVGRect
|
||||||
{...extractProps({
|
ref={ele => {
|
||||||
...props,
|
this.root = ele;
|
||||||
x: null,
|
}}
|
||||||
y: null
|
{...extractProps(
|
||||||
}, this)}
|
{
|
||||||
x={props.x.toString()}
|
...props,
|
||||||
y={props.y.toString()}
|
x: null,
|
||||||
rectwidth={props.width.toString()}
|
y: null
|
||||||
rectheight={props.height.toString()}
|
},
|
||||||
rx={props.rx.toString()}
|
this
|
||||||
ry={props.ry.toString()}
|
)}
|
||||||
/>;
|
x={props.x.toString()}
|
||||||
|
y={props.y.toString()}
|
||||||
|
rectwidth={props.width.toString()}
|
||||||
|
rectheight={props.height.toString()}
|
||||||
|
rx={props.rx.toString()}
|
||||||
|
ry={props.ry.toString()}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const RNSVGRect = createReactNativeComponentClass('RNSVGRect', () => ({
|
const RNSVGRect = requireNativeComponent("RNSVGRect", null, {
|
||||||
validAttributes: RectAttributes,
|
nativeOnly: RectAttributes
|
||||||
uiViewClassName: 'RNSVGRect'
|
});
|
||||||
}));
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import {Component} from 'react';
|
import { Component } from "react";
|
||||||
import SvgTouchableMixin from '../lib/SvgTouchableMixin';
|
import SvgTouchableMixin from "../lib/SvgTouchableMixin";
|
||||||
import _ from 'lodash';
|
import _ from "lodash";
|
||||||
|
|
||||||
class Shape extends Component {
|
class Shape extends Component {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
import {Component} from 'react';
|
import { Component } from "react";
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from "prop-types";
|
||||||
import {numberProp} from '../lib/props';
|
import { numberProp } from "../lib/props";
|
||||||
|
|
||||||
export default class extends Component{
|
export default class extends Component {
|
||||||
static displayName = 'Stop';
|
static displayName = "Stop";
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
stopColor: PropTypes.string,
|
stopColor: PropTypes.string,
|
||||||
stopOpacity: numberProp
|
stopOpacity: numberProp
|
||||||
};
|
};
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
stopColor: '#000',
|
stopColor: "#000",
|
||||||
stopOpacity: 1
|
stopOpacity: 1
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +1,16 @@
|
|||||||
//noinspection JSUnresolvedVariable
|
//noinspection JSUnresolvedVariable
|
||||||
import React, {
|
import React, { Component } from "react";
|
||||||
Component
|
import PropTypes from "prop-types";
|
||||||
} from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import {
|
import {
|
||||||
ViewPropTypes,
|
ViewPropTypes,
|
||||||
requireNativeComponent,
|
requireNativeComponent,
|
||||||
StyleSheet,
|
StyleSheet,
|
||||||
findNodeHandle,
|
findNodeHandle,
|
||||||
NativeModules
|
NativeModules
|
||||||
} from 'react-native';
|
} from "react-native";
|
||||||
import extractViewBox from '../lib/extract/extractViewBox';
|
import extractViewBox from "../lib/extract/extractViewBox";
|
||||||
import {ViewBoxAttributes} from '../lib/attributes';
|
import { ViewBoxAttributes } from "../lib/attributes";
|
||||||
|
import { numberProp } from "../lib/props";
|
||||||
|
|
||||||
/** @namespace NativeModules.RNSVGSvgViewManager */
|
/** @namespace NativeModules.RNSVGSvgViewManager */
|
||||||
const RNSVGSvgViewManager = NativeModules.RNSVGSvgViewManager;
|
const RNSVGSvgViewManager = NativeModules.RNSVGSvgViewManager;
|
||||||
@@ -21,32 +20,29 @@ let id = 0;
|
|||||||
|
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
svg: {
|
svg: {
|
||||||
backgroundColor: 'transparent'
|
backgroundColor: "transparent"
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
class Svg extends Component{
|
class Svg extends Component {
|
||||||
static displayName = 'Svg';
|
static displayName = "Svg";
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
...ViewPropTypes,
|
...ViewPropTypes,
|
||||||
opacity: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
opacity: numberProp,
|
||||||
width: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
width: numberProp,
|
||||||
height: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
height: numberProp,
|
||||||
// more detail https://svgwg.org/svg2-draft/coords.html#ViewBoxAttribute
|
// more detail https://svgwg.org/svg2-draft/coords.html#ViewBoxAttribute
|
||||||
viewBox: PropTypes.string,
|
viewBox: PropTypes.string,
|
||||||
preserveAspectRatio: PropTypes.string
|
preserveAspectRatio: PropTypes.string
|
||||||
};
|
};
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
preserveAspectRatio: 'xMidYMid meet'
|
preserveAspectRatio: "xMidYMid meet"
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super(...arguments);
|
super(...arguments);
|
||||||
id++;
|
this.id = ++id;
|
||||||
this.id = id;
|
|
||||||
//noinspection JSUnusedGlobalSymbols
|
|
||||||
this.onDataURLCallbacks = [];
|
|
||||||
}
|
}
|
||||||
measureInWindow = (...args) => {
|
measureInWindow = (...args) => {
|
||||||
this.root.measureInWindow(...args);
|
this.root.measureInWindow(...args);
|
||||||
@@ -64,18 +60,27 @@ class Svg extends Component{
|
|||||||
this.root.setNativeProps(...args);
|
this.root.setNativeProps(...args);
|
||||||
};
|
};
|
||||||
|
|
||||||
toDataURL = (callback) => {
|
toDataURL = callback => {
|
||||||
callback && RNSVGSvgViewManager.toDataURL(findNodeHandle(this.root), callback);
|
callback &&
|
||||||
|
RNSVGSvgViewManager.toDataURL(findNodeHandle(this.root), callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {opacity, width, height, viewBox, preserveAspectRatio, style, ...props} = this.props;
|
const {
|
||||||
|
opacity,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
viewBox,
|
||||||
|
preserveAspectRatio,
|
||||||
|
style,
|
||||||
|
...props
|
||||||
|
} = this.props;
|
||||||
let dimensions;
|
let dimensions;
|
||||||
|
|
||||||
if (width && height) {
|
if (width && height) {
|
||||||
dimensions = {
|
dimensions = {
|
||||||
width: width[width.length - 1] === '%' ? width : +width,
|
width: width[width.length - 1] === "%" ? width : +width,
|
||||||
height: height[height.length - 1] === '%' ? height : +height,
|
height: height[height.length - 1] === "%" ? height : +height,
|
||||||
flex: 0
|
flex: 0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -83,29 +88,33 @@ class Svg extends Component{
|
|||||||
const w = `${width}`;
|
const w = `${width}`;
|
||||||
const h = `${height}`;
|
const h = `${height}`;
|
||||||
|
|
||||||
return <NativeSvgView
|
return (
|
||||||
{...props}
|
<NativeSvgView
|
||||||
bbWidth={w}
|
{...props}
|
||||||
bbHeight={h}
|
bbWidth={w}
|
||||||
{...extractViewBox({ viewBox, preserveAspectRatio })}
|
bbHeight={h}
|
||||||
ref={ele => {this.root = ele;}}
|
{...extractViewBox({ viewBox, preserveAspectRatio })}
|
||||||
style={[
|
ref={ele => {
|
||||||
styles.svg,
|
this.root = ele;
|
||||||
style,
|
}}
|
||||||
!isNaN(+opacity) && {
|
style={[
|
||||||
opacity: +opacity
|
styles.svg,
|
||||||
},
|
style,
|
||||||
dimensions
|
!isNaN(+opacity) && {
|
||||||
]}
|
opacity: +opacity
|
||||||
/>;
|
},
|
||||||
|
dimensions
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const NativeSvgView = requireNativeComponent('RNSVGSvgView', null, {
|
const NativeSvgView = requireNativeComponent("RNSVGSvgView", null, {
|
||||||
nativeOnly: {
|
nativeOnly: {
|
||||||
...ViewBoxAttributes,
|
...ViewBoxAttributes,
|
||||||
width: true,
|
width: true,
|
||||||
height: true,
|
height: true
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,29 +1,27 @@
|
|||||||
import React, {Component} from 'react';
|
import React, { Component } from "react";
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from "prop-types";
|
||||||
import extractViewBox from '../lib/extract/extractViewBox';
|
import extractViewBox from "../lib/extract/extractViewBox";
|
||||||
import createReactNativeComponentClass from '../lib/createReactNativeComponentClass';
|
import { requireNativeComponent } from "react-native";
|
||||||
import {SymbolAttributes} from '../lib/attributes';
|
import { SymbolAttributes } from "../lib/attributes";
|
||||||
|
|
||||||
export default class extends Component{
|
export default class extends Component {
|
||||||
static displayName = 'Symbol';
|
static displayName = "Symbol";
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
id: PropTypes.string.isRequired,
|
id: PropTypes.string.isRequired,
|
||||||
viewBox: PropTypes.string,
|
viewBox: PropTypes.string,
|
||||||
preserveAspectRatio: PropTypes.string
|
preserveAspectRatio: PropTypes.string
|
||||||
};
|
};
|
||||||
render() {
|
render() {
|
||||||
let {props} = this;
|
let { props } = this;
|
||||||
|
|
||||||
return <RNSVGSymbol
|
return (
|
||||||
name={props.id}
|
<RNSVGSymbol name={props.id} {...extractViewBox(props)}>
|
||||||
{...extractViewBox(props)}
|
{props.children}
|
||||||
>
|
</RNSVGSymbol>
|
||||||
{props.children}
|
);
|
||||||
</RNSVGSymbol>;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const RNSVGSymbol = createReactNativeComponentClass('RNSVGSymbol', () => ({
|
const RNSVGSymbol = requireNativeComponent("RNSVGSymbol", null, {
|
||||||
validAttributes: SymbolAttributes,
|
nativeOnly: SymbolAttributes
|
||||||
uiViewClassName: 'RNSVGSymbol'
|
});
|
||||||
}));
|
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
import React from 'react';
|
import React from "react";
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from "prop-types";
|
||||||
import createReactNativeComponentClass from '../lib/createReactNativeComponentClass';
|
import { requireNativeComponent } from "react-native";
|
||||||
import extractText from '../lib/extract/extractText';
|
import extractText from "../lib/extract/extractText";
|
||||||
import {textProps} from '../lib/props';
|
import { textProps } from "../lib/props";
|
||||||
import {TSpanAttibutes} from '../lib/attributes';
|
import { TSpanAttibutes } from "../lib/attributes";
|
||||||
import extractProps from '../lib/extract/extractProps';
|
import extractProps from "../lib/extract/extractProps";
|
||||||
import Shape from './Shape';
|
import Shape from "./Shape";
|
||||||
|
|
||||||
// TSpan elements are shadow components
|
// TSpan elements are shadow components
|
||||||
export default class extends Shape {
|
export default class extends Shape {
|
||||||
static displayName = 'TSpan';
|
static displayName = "TSpan";
|
||||||
|
|
||||||
static propTypes = textProps;
|
static propTypes = textProps;
|
||||||
|
|
||||||
@@ -38,19 +38,25 @@ export default class extends Shape {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
let props = this.props;
|
let props = this.props;
|
||||||
return <RNSVGTSpan
|
return (
|
||||||
ref={ele => {this.root = ele;}}
|
<RNSVGTSpan
|
||||||
{...extractProps({
|
ref={ele => {
|
||||||
...props,
|
this.root = ele;
|
||||||
x: null,
|
}}
|
||||||
y: null
|
{...extractProps(
|
||||||
}, this)}
|
{
|
||||||
{...extractText(props)}
|
...props,
|
||||||
/>;
|
x: null,
|
||||||
|
y: null
|
||||||
|
},
|
||||||
|
this
|
||||||
|
)}
|
||||||
|
{...extractText(props)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const RNSVGTSpan = createReactNativeComponentClass('RNSVGTSpan', () => ({
|
const RNSVGTSpan = requireNativeComponent("RNSVGTSpan", null, {
|
||||||
validAttributes: TSpanAttibutes,
|
nativeOnly: TSpanAttibutes
|
||||||
uiViewClassName: 'RNSVGTSpan'
|
});
|
||||||
}));
|
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
import React from 'react';
|
import React from "react";
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from "prop-types";
|
||||||
import createReactNativeComponentClass from '../lib/createReactNativeComponentClass';
|
import { requireNativeComponent } from "react-native";
|
||||||
import extractText from '../lib/extract/extractText';
|
import extractText from "../lib/extract/extractText";
|
||||||
import {textProps} from '../lib/props';
|
import { textProps } from "../lib/props";
|
||||||
import {TextAttributes} from '../lib/attributes';
|
import { TextAttributes } from "../lib/attributes";
|
||||||
import extractProps from '../lib/extract/extractProps';
|
import extractProps from "../lib/extract/extractProps";
|
||||||
import Shape from './Shape';
|
import Shape from "./Shape";
|
||||||
|
|
||||||
export default class extends Shape {
|
export default class extends Shape {
|
||||||
static displayName = 'Text';
|
static displayName = "Text";
|
||||||
|
|
||||||
static propTypes = textProps;
|
static propTypes = textProps;
|
||||||
|
|
||||||
@@ -38,19 +38,25 @@ export default class extends Shape {
|
|||||||
render() {
|
render() {
|
||||||
const props = this.props;
|
const props = this.props;
|
||||||
|
|
||||||
return <RNSVGText
|
return (
|
||||||
ref={ele => {this.root = ele;}}
|
<RNSVGText
|
||||||
{...extractProps({
|
ref={ele => {
|
||||||
...props,
|
this.root = ele;
|
||||||
x: null,
|
}}
|
||||||
y: null
|
{...extractProps(
|
||||||
}, this)}
|
{
|
||||||
{...extractText(props, true)}
|
...props,
|
||||||
/>;
|
x: null,
|
||||||
|
y: null
|
||||||
|
},
|
||||||
|
this
|
||||||
|
)}
|
||||||
|
{...extractText(props, true)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const RNSVGText = createReactNativeComponentClass('RNSVGText', () => ({
|
const RNSVGText = requireNativeComponent("RNSVGText", null, {
|
||||||
validAttributes: TextAttributes,
|
nativeOnly: TextAttributes
|
||||||
uiViewClassName: 'RNSVGText'
|
});
|
||||||
}));
|
|
||||||
|
|||||||
@@ -1,49 +1,77 @@
|
|||||||
import React from 'react';
|
import React from "react";
|
||||||
|
|
||||||
import createReactNativeComponentClass from '../lib/createReactNativeComponentClass';
|
import { requireNativeComponent } from "react-native";
|
||||||
import {TextPathAttributes} from '../lib/attributes';
|
import { TextPathAttributes } from "../lib/attributes";
|
||||||
import extractText from '../lib/extract/extractText';
|
import extractText from "../lib/extract/extractText";
|
||||||
import Shape from './Shape';
|
import Shape from "./Shape";
|
||||||
import {textPathProps} from '../lib/props';
|
import { textPathProps } from "../lib/props";
|
||||||
import extractProps from '../lib/extract/extractProps';
|
import extractProps from "../lib/extract/extractProps";
|
||||||
import TSpan from './TSpan';
|
import TSpan from "./TSpan";
|
||||||
|
|
||||||
const idExpReg = /^#(.+)$/;
|
const idExpReg = /^#(.+)$/;
|
||||||
|
|
||||||
export default class extends Shape {
|
export default class extends Shape {
|
||||||
static displayName = 'Span';
|
static displayName = "TextPath";
|
||||||
|
|
||||||
static propTypes = textPathProps;
|
static propTypes = textPathProps;
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let {children, href, startOffset, method, spacing, side, alignmentBaseline, midLine, ...props} = this.props;
|
let {
|
||||||
|
children,
|
||||||
|
href,
|
||||||
|
startOffset,
|
||||||
|
method,
|
||||||
|
spacing,
|
||||||
|
side,
|
||||||
|
alignmentBaseline,
|
||||||
|
midLine,
|
||||||
|
...props
|
||||||
|
} = this.props;
|
||||||
if (href) {
|
if (href) {
|
||||||
let matched = href.match(idExpReg);
|
let matched = href.match(idExpReg);
|
||||||
|
|
||||||
if (matched) {
|
if (matched) {
|
||||||
href = matched[1];
|
href = matched[1];
|
||||||
startOffset = `${startOffset || 0}`;
|
startOffset = `${startOffset || 0}`;
|
||||||
return <RNSVGTextPath
|
return (
|
||||||
{...{href, startOffset, method, spacing, side, alignmentBaseline, midLine}}
|
<RNSVGTextPath
|
||||||
{...extractProps({
|
{...{
|
||||||
...props,
|
href,
|
||||||
x: null,
|
startOffset,
|
||||||
y: null,
|
method,
|
||||||
}, this)}
|
spacing,
|
||||||
{...extractText({
|
side,
|
||||||
children,
|
alignmentBaseline,
|
||||||
}, true)}
|
midLine
|
||||||
/>;
|
}}
|
||||||
|
{...extractProps(
|
||||||
|
{
|
||||||
|
...props,
|
||||||
|
x: null,
|
||||||
|
y: null
|
||||||
|
},
|
||||||
|
this
|
||||||
|
)}
|
||||||
|
{...extractText(
|
||||||
|
{
|
||||||
|
children
|
||||||
|
},
|
||||||
|
true
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.warn('Invalid `href` prop for `TextPath` element, expected a href like `"#id"`, but got: "' + props.href + '"');
|
console.warn(
|
||||||
|
'Invalid `href` prop for `TextPath` element, expected a href like `"#id"`, but got: "' +
|
||||||
|
props.href +
|
||||||
|
'"'
|
||||||
|
);
|
||||||
return <TSpan>{children}</TSpan>;
|
return <TSpan>{children}</TSpan>;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const RNSVGTextPath = createReactNativeComponentClass('RNSVGTextPath', () => ({
|
const RNSVGTextPath = requireNativeComponent("RNSVGTextPath", null, {
|
||||||
validAttributes: TextPathAttributes,
|
nativeOnly: TextPathAttributes
|
||||||
uiViewClassName: 'RNSVGTextPath'
|
});
|
||||||
}));
|
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
import React from 'react';
|
import React from "react";
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from "prop-types";
|
||||||
import createReactNativeComponentClass from '../lib/createReactNativeComponentClass';
|
import { requireNativeComponent } from "react-native";
|
||||||
import extractProps from '../lib/extract/extractProps';
|
import extractProps from "../lib/extract/extractProps";
|
||||||
import {pathProps, numberProp} from '../lib/props';
|
import { pathProps, numberProp } from "../lib/props";
|
||||||
import {UseAttributes} from '../lib/attributes';
|
import { UseAttributes } from "../lib/attributes";
|
||||||
import Shape from './Shape';
|
import Shape from "./Shape";
|
||||||
|
|
||||||
const idExpReg = /^#(.+)$/;
|
const idExpReg = /^#(.+)$/;
|
||||||
export default class extends Shape {
|
export default class extends Shape {
|
||||||
static displayName = 'Use';
|
static displayName = "Use";
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
href: PropTypes.string.isRequired,
|
href: PropTypes.string.isRequired,
|
||||||
@@ -17,12 +17,18 @@ export default class extends Shape {
|
|||||||
...pathProps
|
...pathProps
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static defaultProps = {
|
||||||
|
width: 0,
|
||||||
|
height: 0
|
||||||
|
};
|
||||||
|
|
||||||
setNativeProps = (...args) => {
|
setNativeProps = (...args) => {
|
||||||
this.root.setNativeProps(...args);
|
this.root.setNativeProps(...args);
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {props} = this;
|
const { props } = this;
|
||||||
|
const { children, width, height } = props;
|
||||||
// match "url(#pattern)"
|
// match "url(#pattern)"
|
||||||
const matched = props.href.match(idExpReg);
|
const matched = props.href.match(idExpReg);
|
||||||
let href;
|
let href;
|
||||||
@@ -32,20 +38,29 @@ export default class extends Shape {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!href) {
|
if (!href) {
|
||||||
console.warn('Invalid `href` prop for `Use` element, expected a href like `"#id"`, but got: "' + props.href + '"');
|
console.warn(
|
||||||
|
'Invalid `href` prop for `Use` element, expected a href like `"#id"`, but got: "' +
|
||||||
|
props.href +
|
||||||
|
'"'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return <RNSVGUse
|
return (
|
||||||
ref={ele => {this.root = ele;}}
|
<RNSVGUse
|
||||||
{...extractProps(props, this)}
|
ref={ele => {
|
||||||
href={href}
|
this.root = ele;
|
||||||
usewidth={props.width}
|
}}
|
||||||
useheight={props.height}
|
{...extractProps(props, this)}
|
||||||
>{props.children}</RNSVGUse>;
|
href={href}
|
||||||
|
usewidth={width !== undefined ? width.toString() : ""}
|
||||||
|
useheight={height !== undefined ? height.toString() : ""}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</RNSVGUse>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const RNSVGUse = createReactNativeComponentClass('RNSVGUse', () => ({
|
const RNSVGUse = requireNativeComponent("RNSVGUse", null, {
|
||||||
validAttributes: UseAttributes,
|
nativeOnly: UseAttributes
|
||||||
uiViewClassName: 'RNSVGUse'
|
});
|
||||||
}));
|
|
||||||
|
|||||||
1
index.d.ts
vendored
1
index.d.ts
vendored
@@ -267,7 +267,6 @@ export interface StopProps {
|
|||||||
export const Stop: React.ComponentClass<StopProps>;
|
export const Stop: React.ComponentClass<StopProps>;
|
||||||
|
|
||||||
export interface SvgProps extends ReactNative.ViewProperties {
|
export interface SvgProps extends ReactNative.ViewProperties {
|
||||||
opacity?: NumberProp,
|
|
||||||
width: NumberProp,
|
width: NumberProp,
|
||||||
height: NumberProp,
|
height: NumberProp,
|
||||||
viewBox?: string,
|
viewBox?: string,
|
||||||
|
|||||||
40
index.js
40
index.js
@@ -1,23 +1,23 @@
|
|||||||
import Rect from './elements/Rect';
|
import Rect from "./elements/Rect";
|
||||||
import Circle from './elements/Circle';
|
import Circle from "./elements/Circle";
|
||||||
import Ellipse from './elements/Ellipse';
|
import Ellipse from "./elements/Ellipse";
|
||||||
import Polygon from './elements/Polygon';
|
import Polygon from "./elements/Polygon";
|
||||||
import Polyline from './elements/Polyline';
|
import Polyline from "./elements/Polyline";
|
||||||
import Line from './elements/Line';
|
import Line from "./elements/Line";
|
||||||
import Svg from './elements/Svg';
|
import Svg from "./elements/Svg";
|
||||||
import Path from './elements/Path';
|
import Path from "./elements/Path";
|
||||||
import G from './elements/G';
|
import G from "./elements/G";
|
||||||
import Text from './elements/Text';
|
import Text from "./elements/Text";
|
||||||
import TSpan from './elements/TSpan';
|
import TSpan from "./elements/TSpan";
|
||||||
import TextPath from './elements/TextPath';
|
import TextPath from "./elements/TextPath";
|
||||||
import Use from './elements/Use';
|
import Use from "./elements/Use";
|
||||||
import Image from './elements/Image';
|
import Image from "./elements/Image";
|
||||||
import Symbol from './elements/Symbol';
|
import Symbol from "./elements/Symbol";
|
||||||
import Defs from './elements/Defs';
|
import Defs from "./elements/Defs";
|
||||||
import LinearGradient from './elements/LinearGradient';
|
import LinearGradient from "./elements/LinearGradient";
|
||||||
import RadialGradient from './elements/RadialGradient';
|
import RadialGradient from "./elements/RadialGradient";
|
||||||
import Stop from './elements/Stop';
|
import Stop from "./elements/Stop";
|
||||||
import ClipPath from './elements/ClipPath';
|
import ClipPath from "./elements/ClipPath";
|
||||||
|
|
||||||
export {
|
export {
|
||||||
Svg,
|
Svg,
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
- (void)parseReference
|
- (void)parseReference
|
||||||
{
|
{
|
||||||
[[self getSvgView] defineClipPath:self clipPathName:self.name];
|
[self.svgView defineClipPath:self clipPathName:self.name];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -33,12 +33,14 @@
|
|||||||
- (void)renderGroupTo:(CGContextRef)context rect:(CGRect)rect
|
- (void)renderGroupTo:(CGContextRef)context rect:(CGRect)rect
|
||||||
{
|
{
|
||||||
[self pushGlyphContext];
|
[self pushGlyphContext];
|
||||||
RNSVGSvgView* svg = [self getSvgView];
|
|
||||||
|
__block CGRect groupRect = CGRectNull;
|
||||||
|
|
||||||
[self traverseSubviews:^(UIView *node) {
|
[self traverseSubviews:^(UIView *node) {
|
||||||
if ([node isKindOfClass:[RNSVGNode class]]) {
|
if ([node isKindOfClass:[RNSVGNode class]]) {
|
||||||
RNSVGNode* svgNode = (RNSVGNode*)node;
|
RNSVGNode* svgNode = (RNSVGNode*)node;
|
||||||
if (svgNode.responsible && !svg.responsible) {
|
if (svgNode.responsible && !self.svgView.responsible) {
|
||||||
svg.responsible = YES;
|
self.svgView.responsible = YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ([node isKindOfClass:[RNSVGRenderable class]]) {
|
if ([node isKindOfClass:[RNSVGRenderable class]]) {
|
||||||
@@ -46,6 +48,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
[svgNode renderTo:context rect:rect];
|
[svgNode renderTo:context rect:rect];
|
||||||
|
|
||||||
|
CGRect nodeRect = svgNode.clientRect;
|
||||||
|
if (!CGRectIsEmpty(nodeRect)) {
|
||||||
|
groupRect = CGRectUnion(groupRect, nodeRect);
|
||||||
|
}
|
||||||
|
|
||||||
if ([node isKindOfClass:[RNSVGRenderable class]]) {
|
if ([node isKindOfClass:[RNSVGRenderable class]]) {
|
||||||
[(RNSVGRenderable*)node resetProperties];
|
[(RNSVGRenderable*)node resetProperties];
|
||||||
@@ -63,6 +70,8 @@
|
|||||||
|
|
||||||
return YES;
|
return YES;
|
||||||
}];
|
}];
|
||||||
|
[self setHitArea:[self getPath:context]];
|
||||||
|
self.clientRect = groupRect;
|
||||||
[self popGlyphContext];
|
[self popGlyphContext];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,12 +93,13 @@
|
|||||||
|
|
||||||
- (void)pushGlyphContext
|
- (void)pushGlyphContext
|
||||||
{
|
{
|
||||||
[[[self getTextRoot] getGlyphContext] pushContext:self font:self.font];
|
__weak typeof(self) weakSelf = self;
|
||||||
|
[[self.textRoot getGlyphContext] pushContext:weakSelf font:self.font];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)popGlyphContext
|
- (void)popGlyphContext
|
||||||
{
|
{
|
||||||
[[[self getTextRoot] getGlyphContext] popContext];
|
[[self.textRoot getGlyphContext] popContext];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)renderPathTo:(CGContextRef)context rect:(CGRect)rect
|
- (void)renderPathTo:(CGContextRef)context rect:(CGRect)rect
|
||||||
@@ -114,16 +124,19 @@
|
|||||||
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
|
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
|
||||||
{
|
{
|
||||||
CGPoint transformed = CGPointApplyAffineTransform(point, self.invmatrix);
|
CGPoint transformed = CGPointApplyAffineTransform(point, self.invmatrix);
|
||||||
|
|
||||||
UIView *hitSelf = [super hitTest:transformed withEvent:event];
|
|
||||||
if (hitSelf) {
|
|
||||||
return hitSelf;
|
|
||||||
}
|
|
||||||
|
|
||||||
CGPathRef clip = [self getClipPath];
|
CGPathRef clip = [self getClipPath];
|
||||||
if (clip && !CGPathContainsPoint(clip, nil, transformed, self.clipRule == kRNSVGCGFCRuleEvenodd)) {
|
if (clip && !CGPathContainsPoint(clip, nil, transformed, self.clipRule == kRNSVGCGFCRuleEvenodd)) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!event) {
|
||||||
|
NSPredicate *const anyActive = [NSPredicate predicateWithFormat:@"active == TRUE"];
|
||||||
|
NSArray *const filtered = [self.subviews filteredArrayUsingPredicate:anyActive];
|
||||||
|
if ([filtered count] != 0) {
|
||||||
|
return filtered.firstObject;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (RNSVGNode *node in [self.subviews reverseObjectEnumerator]) {
|
for (RNSVGNode *node in [self.subviews reverseObjectEnumerator]) {
|
||||||
if (![node isKindOfClass:[RNSVGNode class]]) {
|
if (![node isKindOfClass:[RNSVGNode class]]) {
|
||||||
@@ -143,15 +156,20 @@
|
|||||||
return (node.responsible || (node != hitChild)) ? hitChild : self;
|
return (node.responsible || (node != hitChild)) ? hitChild : self;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UIView *hitSelf = [super hitTest:transformed withEvent:event];
|
||||||
|
if (hitSelf) {
|
||||||
|
return hitSelf;
|
||||||
|
}
|
||||||
|
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)parseReference
|
- (void)parseReference
|
||||||
{
|
{
|
||||||
if (self.name) {
|
if (self.name) {
|
||||||
RNSVGSvgView* svg = [self getSvgView];
|
typeof(self) __weak weakSelf = self;
|
||||||
[svg defineTemplate:self templateName:self.name];
|
[self.svgView defineTemplate:weakSelf templateName:self.name];
|
||||||
}
|
}
|
||||||
|
|
||||||
[self traverseSubviews:^(__kindof RNSVGNode *node) {
|
[self traverseSubviews:^(__kindof RNSVGNode *node) {
|
||||||
|
|||||||
@@ -8,11 +8,13 @@
|
|||||||
|
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
#import <React/RCTBridge.h>
|
||||||
#import "RNSVGRenderable.h"
|
#import "RNSVGRenderable.h"
|
||||||
#import "RNSVGVBMOS.h"
|
#import "RNSVGVBMOS.h"
|
||||||
|
|
||||||
@interface RNSVGImage : RNSVGRenderable
|
@interface RNSVGImage : RNSVGRenderable
|
||||||
|
|
||||||
|
@property (nonatomic, weak) RCTBridge *bridge;
|
||||||
@property (nonatomic, assign) id src;
|
@property (nonatomic, assign) id src;
|
||||||
@property (nonatomic, strong) NSString* x;
|
@property (nonatomic, strong) NSString* x;
|
||||||
@property (nonatomic, strong) NSString* y;
|
@property (nonatomic, strong) NSString* y;
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#import "RNSVGImage.h"
|
#import "RNSVGImage.h"
|
||||||
#import "RCTConvert+RNSVG.h"
|
#import "RCTConvert+RNSVG.h"
|
||||||
#import <React/RCTImageSource.h>
|
#import <React/RCTImageSource.h>
|
||||||
|
#import <React/RCTImageLoader.h>
|
||||||
#import <React/RCTLog.h>
|
#import <React/RCTLog.h>
|
||||||
#import "RNSVGViewBox.h"
|
#import "RNSVGViewBox.h"
|
||||||
|
|
||||||
@@ -16,6 +17,7 @@
|
|||||||
{
|
{
|
||||||
CGImageRef _image;
|
CGImageRef _image;
|
||||||
CGSize _imageSize;
|
CGSize _imageSize;
|
||||||
|
RCTImageLoaderCancellationBlock _reloadImageCancellationBlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setSrc:(id)src
|
- (void)setSrc:(id)src
|
||||||
@@ -25,14 +27,26 @@
|
|||||||
}
|
}
|
||||||
_src = src;
|
_src = src;
|
||||||
CGImageRelease(_image);
|
CGImageRelease(_image);
|
||||||
_image = CGImageRetain([RCTConvert CGImage:src]);
|
|
||||||
RCTImageSource *source = [RCTConvert RCTImageSource:src];
|
RCTImageSource *source = [RCTConvert RCTImageSource:src];
|
||||||
if (source.size.width != 0 && source.size.height != 0) {
|
if (source.size.width != 0 && source.size.height != 0) {
|
||||||
_imageSize = source.size;
|
_imageSize = source.size;
|
||||||
} else {
|
} else {
|
||||||
_imageSize = CGSizeMake(CGImageGetWidth(_image), CGImageGetHeight(_image));
|
_imageSize = CGSizeMake(0, 0);
|
||||||
}
|
}
|
||||||
[self invalidate];
|
|
||||||
|
RCTImageLoaderCancellationBlock previousCancellationBlock = _reloadImageCancellationBlock;
|
||||||
|
if (previousCancellationBlock) {
|
||||||
|
previousCancellationBlock();
|
||||||
|
_reloadImageCancellationBlock = nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
_reloadImageCancellationBlock = [self.bridge.imageLoader loadImageWithURLRequest:[RCTConvert NSURLRequest:src] callback:^(NSError *error, UIImage *image) {
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
self->_image = CGImageRetain(image.CGImage);
|
||||||
|
self->_imageSize = CGSizeMake(CGImageGetWidth(self->_image), CGImageGetHeight(self->_image));
|
||||||
|
[self invalidate];
|
||||||
|
});
|
||||||
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setX:(NSString *)x
|
- (void)setX:(NSString *)x
|
||||||
@@ -94,7 +108,7 @@
|
|||||||
CGImageRelease(_image);
|
CGImageRelease(_image);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)renderLayerTo:(CGContextRef)context
|
- (void)renderLayerTo:(CGContextRef)context rect:(CGRect)rect
|
||||||
{
|
{
|
||||||
CGContextSaveGState(context);
|
CGContextSaveGState(context);
|
||||||
|
|
||||||
|
|||||||
@@ -34,12 +34,11 @@
|
|||||||
[painter setTransform:self.gradientTransform];
|
[painter setTransform:self.gradientTransform];
|
||||||
[painter setLinearGradientColors:self.gradient];
|
[painter setLinearGradientColors:self.gradient];
|
||||||
|
|
||||||
RNSVGSvgView *svg = [self getSvgView];
|
|
||||||
if (self.gradientUnits == kRNSVGUnitsUserSpaceOnUse) {
|
if (self.gradientUnits == kRNSVGUnitsUserSpaceOnUse) {
|
||||||
[painter setUserSpaceBoundingBox:[svg getContextBounds]];
|
[painter setUserSpaceBoundingBox:[self.svgView getContextBounds]];
|
||||||
}
|
}
|
||||||
|
|
||||||
[svg definePainter:painter painterName:self.name];
|
[self.svgView definePainter:painter painterName:self.name];
|
||||||
}
|
}
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|||||||
@@ -32,12 +32,11 @@
|
|||||||
[painter setTransform:self.gradientTransform];
|
[painter setTransform:self.gradientTransform];
|
||||||
[painter setRadialGradientColors:self.gradient];
|
[painter setRadialGradientColors:self.gradient];
|
||||||
|
|
||||||
RNSVGSvgView *svg = [self getSvgView];
|
|
||||||
if (self.gradientUnits == kRNSVGUnitsUserSpaceOnUse) {
|
if (self.gradientUnits == kRNSVGUnitsUserSpaceOnUse) {
|
||||||
[painter setUserSpaceBoundingBox:[svg getContextBounds]];
|
[painter setUserSpaceBoundingBox:[self.svgView getContextBounds]];
|
||||||
}
|
}
|
||||||
|
|
||||||
[svg definePainter:painter painterName:self.name];
|
[self.svgView definePainter:painter painterName:self.name];
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -24,7 +24,11 @@
|
|||||||
@property (nonatomic, strong) NSString *align;
|
@property (nonatomic, strong) NSString *align;
|
||||||
@property (nonatomic, assign) RNSVGVBMOS meetOrSlice;
|
@property (nonatomic, assign) RNSVGVBMOS meetOrSlice;
|
||||||
@property (nonatomic, assign) BOOL responsible;
|
@property (nonatomic, assign) BOOL responsible;
|
||||||
|
@property (nonatomic, assign) BOOL active;
|
||||||
@property (nonatomic, assign) CGRect boundingBox;
|
@property (nonatomic, assign) CGRect boundingBox;
|
||||||
|
@property (nonatomic, assign) CGAffineTransform initialCTM;
|
||||||
|
@property (nonatomic, assign) CGAffineTransform invInitialCTM;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -20,6 +20,16 @@
|
|||||||
CGAffineTransform _invviewBoxTransform;
|
CGAffineTransform _invviewBoxTransform;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (instancetype)initWithFrame:(CGRect)frame
|
||||||
|
{
|
||||||
|
if (self = [super initWithFrame:frame]) {
|
||||||
|
// This is necessary to ensure that [self setNeedsDisplay] actually triggers
|
||||||
|
// a redraw when our parent transitions between hidden and visible.
|
||||||
|
self.contentMode = UIViewContentModeRedraw;
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
- (void)insertReactSubview:(UIView *)subview atIndex:(NSInteger)atIndex
|
- (void)insertReactSubview:(UIView *)subview atIndex:(NSInteger)atIndex
|
||||||
{
|
{
|
||||||
[super insertReactSubview:subview atIndex:atIndex];
|
[super insertReactSubview:subview atIndex:atIndex];
|
||||||
@@ -125,6 +135,8 @@
|
|||||||
|
|
||||||
- (void)drawToContext:(CGContextRef)context withRect:(CGRect)rect {
|
- (void)drawToContext:(CGContextRef)context withRect:(CGRect)rect {
|
||||||
|
|
||||||
|
self.initialCTM = CGContextGetCTM(context);
|
||||||
|
self.invInitialCTM = CGAffineTransformInvert(self.initialCTM);
|
||||||
if (self.align) {
|
if (self.align) {
|
||||||
_viewBoxTransform = [RNSVGViewBox getTransform:CGRectMake(self.minX, self.minY, self.vbWidth, self.vbHeight)
|
_viewBoxTransform = [RNSVGViewBox getTransform:CGRectMake(self.minX, self.minY, self.vbWidth, self.vbHeight)
|
||||||
eRect:rect
|
eRect:rect
|
||||||
@@ -137,7 +149,8 @@
|
|||||||
for (UIView *node in self.subviews) {
|
for (UIView *node in self.subviews) {
|
||||||
if ([node isKindOfClass:[RNSVGNode class]]) {
|
if ([node isKindOfClass:[RNSVGNode class]]) {
|
||||||
RNSVGNode *svg = (RNSVGNode *)node;
|
RNSVGNode *svg = (RNSVGNode *)node;
|
||||||
[svg renderTo:context rect:rect];
|
[svg renderTo:context
|
||||||
|
rect:rect];
|
||||||
} else {
|
} else {
|
||||||
[node drawRect:rect];
|
[node drawRect:rect];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
- (void)renderLayerTo:(CGContextRef)context rect:(CGRect)rect
|
- (void)renderLayerTo:(CGContextRef)context rect:(CGRect)rect
|
||||||
{
|
{
|
||||||
RNSVGNode* template = [[self getSvgView] getDefinedTemplate:self.href];
|
RNSVGNode* template = [self.svgView getDefinedTemplate:self.href];
|
||||||
if (template) {
|
if (template) {
|
||||||
[self beginTransparencyLayer:context];
|
[self beginTransparencyLayer:context];
|
||||||
[self clip:context];
|
[self clip:context];
|
||||||
@@ -49,6 +49,23 @@
|
|||||||
// TODO: calling yellow box here
|
// TODO: calling yellow box here
|
||||||
RCTLogWarn(@"`Use` element expected a pre-defined svg template as `href` prop, template named: %@ is not defined.", self.href);
|
RCTLogWarn(@"`Use` element expected a pre-defined svg template as `href` prop, template named: %@ is not defined.", self.href);
|
||||||
}
|
}
|
||||||
|
self.clientRect = template.clientRect;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
|
||||||
|
const CGPoint transformed = CGPointApplyAffineTransform(point, self.invmatrix);
|
||||||
|
RNSVGNode const* template = [self.svgView getDefinedTemplate:self.href];
|
||||||
|
if (event) {
|
||||||
|
self.active = NO;
|
||||||
|
} else if (self.active) {
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
UIView const* hitChild = [template hitTest:transformed withEvent:event];
|
||||||
|
if (hitChild) {
|
||||||
|
self.active = YES;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -45,6 +45,11 @@
|
|||||||
10ED4A9E1CF0656A0078BC02 /* RNSVGClipPathManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 10ED4A9D1CF0656A0078BC02 /* RNSVGClipPathManager.m */; };
|
10ED4A9E1CF0656A0078BC02 /* RNSVGClipPathManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 10ED4A9D1CF0656A0078BC02 /* RNSVGClipPathManager.m */; };
|
||||||
10ED4AA21CF078830078BC02 /* RNSVGNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 10ED4AA11CF078830078BC02 /* RNSVGNode.m */; };
|
10ED4AA21CF078830078BC02 /* RNSVGNode.m in Sources */ = {isa = PBXBuildFile; fileRef = 10ED4AA11CF078830078BC02 /* RNSVGNode.m */; };
|
||||||
10FDEEB21D3FB60500A5C46C /* RNSVGPainterBrush.m in Sources */ = {isa = PBXBuildFile; fileRef = 10FDEEB11D3FB60500A5C46C /* RNSVGPainterBrush.m */; };
|
10FDEEB21D3FB60500A5C46C /* RNSVGPainterBrush.m in Sources */ = {isa = PBXBuildFile; fileRef = 10FDEEB11D3FB60500A5C46C /* RNSVGPainterBrush.m */; };
|
||||||
|
167AF4572087C26F0035AA75 /* RNSVGBezierElement.m in Sources */ = {isa = PBXBuildFile; fileRef = B56895A820352B35004DBF1E /* RNSVGBezierElement.m */; };
|
||||||
|
167AF4582087C2910035AA75 /* RNSVGFontData.m in Sources */ = {isa = PBXBuildFile; fileRef = B56895B020352B9B004DBF1E /* RNSVGFontData.m */; };
|
||||||
|
167AF4592087C2950035AA75 /* RNSVGGlyphContext.m in Sources */ = {isa = PBXBuildFile; fileRef = B56895AF20352B9B004DBF1E /* RNSVGGlyphContext.m */; };
|
||||||
|
167AF45A2087C2990035AA75 /* RNSVGPropHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = B56895AB20352B9B004DBF1E /* RNSVGPropHelper.m */; };
|
||||||
|
167AF45B2087C2A10035AA75 /* RNSVGTextProperties.m in Sources */ = {isa = PBXBuildFile; fileRef = B56895A62035274F004DBF1E /* RNSVGTextProperties.m */; };
|
||||||
7F08CE9A1E23476900650F83 /* RNSVGTextPathManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 7F08CE971E23476900650F83 /* RNSVGTextPathManager.m */; };
|
7F08CE9A1E23476900650F83 /* RNSVGTextPathManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 7F08CE971E23476900650F83 /* RNSVGTextPathManager.m */; };
|
||||||
7F08CE9B1E23476900650F83 /* RNSVGTSpanManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 7F08CE991E23476900650F83 /* RNSVGTSpanManager.m */; };
|
7F08CE9B1E23476900650F83 /* RNSVGTSpanManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 7F08CE991E23476900650F83 /* RNSVGTSpanManager.m */; };
|
||||||
7F08CEA01E23479700650F83 /* RNSVGTextPath.m in Sources */ = {isa = PBXBuildFile; fileRef = 7F08CE9D1E23479700650F83 /* RNSVGTextPath.m */; };
|
7F08CEA01E23479700650F83 /* RNSVGTextPath.m in Sources */ = {isa = PBXBuildFile; fileRef = 7F08CE9D1E23479700650F83 /* RNSVGTextPath.m */; };
|
||||||
@@ -614,7 +619,9 @@
|
|||||||
A361E7811EB0C33D00646005 /* RNSVGClipPath.m in Sources */,
|
A361E7811EB0C33D00646005 /* RNSVGClipPath.m in Sources */,
|
||||||
A361E7821EB0C33D00646005 /* RNSVGSvgViewManager.m in Sources */,
|
A361E7821EB0C33D00646005 /* RNSVGSvgViewManager.m in Sources */,
|
||||||
A361E7831EB0C33D00646005 /* RNSVGSolidColorBrush.m in Sources */,
|
A361E7831EB0C33D00646005 /* RNSVGSolidColorBrush.m in Sources */,
|
||||||
|
167AF45A2087C2990035AA75 /* RNSVGPropHelper.m in Sources */,
|
||||||
A361E7841EB0C33D00646005 /* RNSVGPathManager.m in Sources */,
|
A361E7841EB0C33D00646005 /* RNSVGPathManager.m in Sources */,
|
||||||
|
167AF4572087C26F0035AA75 /* RNSVGBezierElement.m in Sources */,
|
||||||
A361E7861EB0C33D00646005 /* RNSVGRenderableManager.m in Sources */,
|
A361E7861EB0C33D00646005 /* RNSVGRenderableManager.m in Sources */,
|
||||||
A361E7871EB0C33D00646005 /* RNSVGRadialGradient.m in Sources */,
|
A361E7871EB0C33D00646005 /* RNSVGRadialGradient.m in Sources */,
|
||||||
A361E7881EB0C33D00646005 /* RNSVGRadialGradientManager.m in Sources */,
|
A361E7881EB0C33D00646005 /* RNSVGRadialGradientManager.m in Sources */,
|
||||||
@@ -623,6 +630,7 @@
|
|||||||
A361E78B1EB0C33D00646005 /* RNSVGSymbol.m in Sources */,
|
A361E78B1EB0C33D00646005 /* RNSVGSymbol.m in Sources */,
|
||||||
A361E78C1EB0C33D00646005 /* RNSVGDefs.m in Sources */,
|
A361E78C1EB0C33D00646005 /* RNSVGDefs.m in Sources */,
|
||||||
A361E78D1EB0C33D00646005 /* RNSVGLineManager.m in Sources */,
|
A361E78D1EB0C33D00646005 /* RNSVGLineManager.m in Sources */,
|
||||||
|
167AF4592087C2950035AA75 /* RNSVGGlyphContext.m in Sources */,
|
||||||
A361E78E1EB0C33D00646005 /* RNSVGCircle.m in Sources */,
|
A361E78E1EB0C33D00646005 /* RNSVGCircle.m in Sources */,
|
||||||
A361E78F1EB0C33D00646005 /* RNSVGEllipseManager.m in Sources */,
|
A361E78F1EB0C33D00646005 /* RNSVGEllipseManager.m in Sources */,
|
||||||
A361E7901EB0C33D00646005 /* RCTConvert+RNSVG.m in Sources */,
|
A361E7901EB0C33D00646005 /* RCTConvert+RNSVG.m in Sources */,
|
||||||
@@ -631,10 +639,12 @@
|
|||||||
A361E7931EB0C33D00646005 /* RNSVGPathParser.m in Sources */,
|
A361E7931EB0C33D00646005 /* RNSVGPathParser.m in Sources */,
|
||||||
A361E7941EB0C33D00646005 /* RNSVGGroupManager.m in Sources */,
|
A361E7941EB0C33D00646005 /* RNSVGGroupManager.m in Sources */,
|
||||||
A361E7951EB0C33D00646005 /* RNSVGTextPathManager.m in Sources */,
|
A361E7951EB0C33D00646005 /* RNSVGTextPathManager.m in Sources */,
|
||||||
|
167AF45B2087C2A10035AA75 /* RNSVGTextProperties.m in Sources */,
|
||||||
A361E7961EB0C33D00646005 /* RNSVGTSpanManager.m in Sources */,
|
A361E7961EB0C33D00646005 /* RNSVGTSpanManager.m in Sources */,
|
||||||
A361E7971EB0C33D00646005 /* RNSVGViewBox.m in Sources */,
|
A361E7971EB0C33D00646005 /* RNSVGViewBox.m in Sources */,
|
||||||
A361E7981EB0C33D00646005 /* RNSVGTSpan.m in Sources */,
|
A361E7981EB0C33D00646005 /* RNSVGTSpan.m in Sources */,
|
||||||
A361E7991EB0C33D00646005 /* RNSVGLine.m in Sources */,
|
A361E7991EB0C33D00646005 /* RNSVGLine.m in Sources */,
|
||||||
|
167AF4582087C2910035AA75 /* RNSVGFontData.m in Sources */,
|
||||||
A361E79A1EB0C33D00646005 /* RNSVGPainterBrush.m in Sources */,
|
A361E79A1EB0C33D00646005 /* RNSVGPainterBrush.m in Sources */,
|
||||||
A361E79B1EB0C33D00646005 /* RNSVGSvgView.m in Sources */,
|
A361E79B1EB0C33D00646005 /* RNSVGSvgView.m in Sources */,
|
||||||
A361E79C1EB0C33D00646005 /* RNSVGUseManager.m in Sources */,
|
A361E79C1EB0C33D00646005 /* RNSVGUseManager.m in Sources */,
|
||||||
|
|||||||
@@ -35,10 +35,18 @@ extern CGFloat const RNSVG_DEFAULT_FONT_SIZE;
|
|||||||
@property (nonatomic, assign) CGAffineTransform invmatrix;
|
@property (nonatomic, assign) CGAffineTransform invmatrix;
|
||||||
@property (nonatomic, assign) BOOL active;
|
@property (nonatomic, assign) BOOL active;
|
||||||
@property (nonatomic, assign) CGPathRef path;
|
@property (nonatomic, assign) CGPathRef path;
|
||||||
|
@property (nonatomic, assign) CGRect clientRect;
|
||||||
|
@property (nonatomic, copy) RCTDirectEventBlock onLayout;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RNSVGSvgView which ownes current RNSVGNode
|
||||||
|
*/
|
||||||
|
@property (nonatomic, readonly, weak) RNSVGSvgView *svgView;
|
||||||
|
@property (nonatomic, readonly, weak) RNSVGGroup *textRoot;
|
||||||
|
|
||||||
- (void)invalidate;
|
- (void)invalidate;
|
||||||
|
|
||||||
- (RNSVGGroup *)getTextRoot;
|
|
||||||
- (RNSVGGroup *)getParentTextRoot;
|
- (RNSVGGroup *)getParentTextRoot;
|
||||||
|
|
||||||
- (void)renderTo:(CGContextRef)context rect:(CGRect)rect;
|
- (void)renderTo:(CGContextRef)context rect:(CGRect)rect;
|
||||||
@@ -70,11 +78,6 @@ extern CGFloat const RNSVG_DEFAULT_FONT_SIZE;
|
|||||||
*/
|
*/
|
||||||
- (CGPathRef)getPath:(CGContextRef) context;
|
- (CGPathRef)getPath:(CGContextRef) context;
|
||||||
|
|
||||||
/**
|
|
||||||
* get RNSVGSvgView which ownes current RNSVGNode
|
|
||||||
*/
|
|
||||||
- (RNSVGSvgView *)getSvgView;
|
|
||||||
|
|
||||||
- (CGFloat)relativeOnWidth:(NSString *)length;
|
- (CGFloat)relativeOnWidth:(NSString *)length;
|
||||||
|
|
||||||
- (CGFloat)relativeOnHeight:(NSString *)length;
|
- (CGFloat)relativeOnHeight:(NSString *)length;
|
||||||
|
|||||||
@@ -12,13 +12,16 @@
|
|||||||
#import "RNSVGGroup.h"
|
#import "RNSVGGroup.h"
|
||||||
#import "RNSVGGlyphContext.h"
|
#import "RNSVGGlyphContext.h"
|
||||||
|
|
||||||
|
@interface RNSVGNode()
|
||||||
|
@property (nonatomic, readwrite, weak) RNSVGSvgView *svgView;
|
||||||
|
@property (nonatomic, readwrite, weak) RNSVGGroup *textRoot;
|
||||||
|
@end
|
||||||
|
|
||||||
@implementation RNSVGNode
|
@implementation RNSVGNode
|
||||||
{
|
{
|
||||||
RNSVGGroup *_textRoot;
|
|
||||||
RNSVGGlyphContext *glyphContext;
|
RNSVGGlyphContext *glyphContext;
|
||||||
BOOL _transparent;
|
BOOL _transparent;
|
||||||
CGPathRef _cachedClipPath;
|
CGPathRef _cachedClipPath;
|
||||||
RNSVGSvgView *_svgView;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CGFloat const RNSVG_M_SQRT1_2l = 0.707106781186547524400844362104849039;
|
CGFloat const RNSVG_M_SQRT1_2l = 0.707106781186547524400844362104849039;
|
||||||
@@ -60,23 +63,25 @@ CGFloat const RNSVG_DEFAULT_FONT_SIZE = 12;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (RNSVGGroup *)getTextRoot
|
- (RNSVGGroup *)textRoot
|
||||||
{
|
{
|
||||||
|
if (_textRoot) {
|
||||||
|
return _textRoot;
|
||||||
|
}
|
||||||
|
|
||||||
RNSVGNode* node = self;
|
RNSVGNode* node = self;
|
||||||
if (_textRoot == nil) {
|
while (node != nil) {
|
||||||
while (node != nil) {
|
if ([node isKindOfClass:[RNSVGGroup class]] && [((RNSVGGroup*) node) getGlyphContext] != nil) {
|
||||||
if ([node isKindOfClass:[RNSVGGroup class]] && [((RNSVGGroup*) node) getGlyphContext] != nil) {
|
_textRoot = (RNSVGGroup*)node;
|
||||||
_textRoot = (RNSVGGroup*)node;
|
break;
|
||||||
break;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
UIView* parent = [node superview];
|
UIView* parent = [node superview];
|
||||||
|
|
||||||
if (![node isKindOfClass:[RNSVGNode class]]) {
|
if (![node isKindOfClass:[RNSVGNode class]]) {
|
||||||
node = nil;
|
node = nil;
|
||||||
} else {
|
} else {
|
||||||
node = (RNSVGNode*)parent;
|
node = (RNSVGNode*)parent;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,13 +94,13 @@ CGFloat const RNSVG_DEFAULT_FONT_SIZE = 12;
|
|||||||
if (![parent isKindOfClass:[RNSVGGroup class]]) {
|
if (![parent isKindOfClass:[RNSVGGroup class]]) {
|
||||||
return nil;
|
return nil;
|
||||||
} else {
|
} else {
|
||||||
return [parent getTextRoot];
|
return parent.textRoot;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (CGFloat)getFontSizeFromContext
|
- (CGFloat)getFontSizeFromContext
|
||||||
{
|
{
|
||||||
RNSVGGroup* root = [self getTextRoot];
|
RNSVGGroup* root = self.textRoot;
|
||||||
if (root == nil) {
|
if (root == nil) {
|
||||||
return RNSVG_DEFAULT_FONT_SIZE;
|
return RNSVG_DEFAULT_FONT_SIZE;
|
||||||
}
|
}
|
||||||
@@ -140,6 +145,24 @@ CGFloat const RNSVG_DEFAULT_FONT_SIZE = 12;
|
|||||||
[container invalidate];
|
[container invalidate];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)setClientRect:(CGRect)clientRect {
|
||||||
|
if (CGRectEqualToRect(_clientRect, clientRect)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_clientRect = clientRect;
|
||||||
|
if (self.onLayout) {
|
||||||
|
self.onLayout(@{
|
||||||
|
@"layout": @{
|
||||||
|
@"x": @(_clientRect.origin.x),
|
||||||
|
@"y": @(_clientRect.origin.y),
|
||||||
|
@"width": @(_clientRect.size.width),
|
||||||
|
@"height": @(_clientRect.size.height),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
- (void)setClipPath:(NSString *)clipPath
|
- (void)setClipPath:(NSString *)clipPath
|
||||||
{
|
{
|
||||||
if (_clipPath == clipPath) {
|
if (_clipPath == clipPath) {
|
||||||
@@ -177,8 +200,8 @@ CGFloat const RNSVG_DEFAULT_FONT_SIZE = 12;
|
|||||||
|
|
||||||
- (CGPathRef)getClipPath:(CGContextRef)context
|
- (CGPathRef)getClipPath:(CGContextRef)context
|
||||||
{
|
{
|
||||||
if (self.clipPath && !_cachedClipPath) {
|
if (self.clipPath) {
|
||||||
_cachedClipPath = CGPathRetain([[[self getSvgView] getDefinedClipPath:self.clipPath] getPath:context]);
|
_cachedClipPath = CGPathRetain([[self.svgView getDefinedClipPath:self.clipPath] getPath:context]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return [self getClipPath];
|
return [self getClipPath];
|
||||||
@@ -217,7 +240,7 @@ CGFloat const RNSVG_DEFAULT_FONT_SIZE = 12;
|
|||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (RNSVGSvgView *)getSvgView
|
- (RNSVGSvgView *)svgView
|
||||||
{
|
{
|
||||||
if (_svgView) {
|
if (_svgView) {
|
||||||
return _svgView;
|
return _svgView;
|
||||||
@@ -228,8 +251,7 @@ CGFloat const RNSVG_DEFAULT_FONT_SIZE = 12;
|
|||||||
if ([parent class] == [RNSVGSvgView class]) {
|
if ([parent class] == [RNSVGSvgView class]) {
|
||||||
_svgView = parent;
|
_svgView = parent;
|
||||||
} else if ([parent isKindOfClass:[RNSVGNode class]]) {
|
} else if ([parent isKindOfClass:[RNSVGNode class]]) {
|
||||||
RNSVGNode *node = parent;
|
_svgView = ((RNSVGNode *)parent).svgView;
|
||||||
_svgView = [node getSvgView];
|
|
||||||
} else {
|
} else {
|
||||||
RCTLogError(@"RNSVG: %@ should be descendant of a SvgViewShadow.", NSStringFromClass(self.class));
|
RCTLogError(@"RNSVG: %@ should be descendant of a SvgViewShadow.", NSStringFromClass(self.class));
|
||||||
}
|
}
|
||||||
@@ -271,10 +293,10 @@ CGFloat const RNSVG_DEFAULT_FONT_SIZE = 12;
|
|||||||
|
|
||||||
- (CGFloat)getContextWidth
|
- (CGFloat)getContextWidth
|
||||||
{
|
{
|
||||||
RNSVGGroup * root = [self getTextRoot];
|
RNSVGGroup * root = self.textRoot;
|
||||||
RNSVGGlyphContext * gc = [root getGlyphContext];
|
RNSVGGlyphContext * gc = [root getGlyphContext];
|
||||||
if (root == nil || gc == nil) {
|
if (root == nil || gc == nil) {
|
||||||
return CGRectGetWidth([[self getSvgView] getContextBounds]);
|
return CGRectGetWidth([self.svgView getContextBounds]);
|
||||||
} else {
|
} else {
|
||||||
return [gc getWidth];
|
return [gc getWidth];
|
||||||
}
|
}
|
||||||
@@ -282,10 +304,10 @@ CGFloat const RNSVG_DEFAULT_FONT_SIZE = 12;
|
|||||||
|
|
||||||
- (CGFloat)getContextHeight
|
- (CGFloat)getContextHeight
|
||||||
{
|
{
|
||||||
RNSVGGroup * root = [self getTextRoot];
|
RNSVGGroup * root = self.textRoot;
|
||||||
RNSVGGlyphContext * gc = [root getGlyphContext];
|
RNSVGGlyphContext * gc = [root getGlyphContext];
|
||||||
if (root == nil || gc == nil) {
|
if (root == nil || gc == nil) {
|
||||||
return CGRectGetHeight([[self getSvgView] getContextBounds]);
|
return CGRectGetHeight([self.svgView getContextBounds]);
|
||||||
} else {
|
} else {
|
||||||
return [gc getHeight];
|
return [gc getHeight];
|
||||||
}
|
}
|
||||||
@@ -293,19 +315,19 @@ CGFloat const RNSVG_DEFAULT_FONT_SIZE = 12;
|
|||||||
|
|
||||||
- (CGFloat)getContextLeft
|
- (CGFloat)getContextLeft
|
||||||
{
|
{
|
||||||
return CGRectGetMinX([[self getSvgView] getContextBounds]);
|
return CGRectGetMinX([self.svgView getContextBounds]);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (CGFloat)getContextTop
|
- (CGFloat)getContextTop
|
||||||
{
|
{
|
||||||
return CGRectGetMinY([[self getSvgView] getContextBounds]);
|
return CGRectGetMinY([self.svgView getContextBounds]);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)parseReference
|
- (void)parseReference
|
||||||
{
|
{
|
||||||
if (self.name) {
|
if (self.name) {
|
||||||
RNSVGSvgView* svg = [self getSvgView];
|
typeof(self) __weak weakSelf = self;
|
||||||
[svg defineTemplate:self templateName:self.name];
|
[self.svgView defineTemplate:weakSelf templateName:self.name];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -187,6 +187,10 @@
|
|||||||
self.path = CGPathRetain(CFAutorelease(CGPathCreateCopy([self getPath:context])));
|
self.path = CGPathRetain(CFAutorelease(CGPathCreateCopy([self getPath:context])));
|
||||||
[self setHitArea:self.path];
|
[self setHitArea:self.path];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const CGRect pathBounding = CGPathGetBoundingBox(self.path);
|
||||||
|
const CGAffineTransform svgToClientTransform = CGAffineTransformConcat(CGContextGetCTM(context), self.svgView.invInitialCTM);
|
||||||
|
self.clientRect = CGRectApplyAffineTransform(pathBounding, svgToClientTransform);
|
||||||
|
|
||||||
CGPathDrawingMode mode = kCGPathStroke;
|
CGPathDrawingMode mode = kCGPathStroke;
|
||||||
BOOL fillColor = NO;
|
BOOL fillColor = NO;
|
||||||
@@ -205,7 +209,7 @@
|
|||||||
CGContextClip(context);
|
CGContextClip(context);
|
||||||
[self.fill paint:context
|
[self.fill paint:context
|
||||||
opacity:self.fillOpacity
|
opacity:self.fillOpacity
|
||||||
painter:[[self getSvgView] getDefinedPainter:self.fill.brushRef]
|
painter:[self.svgView getDefinedPainter:self.fill.brushRef]
|
||||||
];
|
];
|
||||||
CGContextRestoreGState(context);
|
CGContextRestoreGState(context);
|
||||||
|
|
||||||
@@ -250,7 +254,7 @@
|
|||||||
|
|
||||||
[self.stroke paint:context
|
[self.stroke paint:context
|
||||||
opacity:self.strokeOpacity
|
opacity:self.strokeOpacity
|
||||||
painter:[[self getSvgView] getDefinedPainter:self.stroke.brushRef]
|
painter:[self.svgView getDefinedPainter:self.stroke.brushRef]
|
||||||
];
|
];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -264,21 +268,19 @@
|
|||||||
{
|
{
|
||||||
CGPathRelease(_hitArea);
|
CGPathRelease(_hitArea);
|
||||||
_hitArea = nil;
|
_hitArea = nil;
|
||||||
if (self.responsible) {
|
// Add path to hitArea
|
||||||
// Add path to hitArea
|
CGMutablePathRef hitArea = CGPathCreateMutableCopy(path);
|
||||||
CGMutablePathRef hitArea = CGPathCreateMutableCopy(path);
|
|
||||||
|
if (self.stroke && self.strokeWidth) {
|
||||||
if (self.stroke && self.strokeWidth) {
|
// Add stroke to hitArea
|
||||||
// Add stroke to hitArea
|
CGFloat width = [self relativeOnOther:self.strokeWidth];
|
||||||
CGFloat width = [self relativeOnOther:self.strokeWidth];
|
CGPathRef strokePath = CGPathCreateCopyByStrokingPath(hitArea, nil, width, self.strokeLinecap, self.strokeLinejoin, self.strokeMiterlimit);
|
||||||
CGPathRef strokePath = CGPathCreateCopyByStrokingPath(hitArea, nil, width, self.strokeLinecap, self.strokeLinejoin, self.strokeMiterlimit);
|
CGPathAddPath(hitArea, nil, strokePath);
|
||||||
CGPathAddPath(hitArea, nil, strokePath);
|
CGPathRelease(strokePath);
|
||||||
CGPathRelease(strokePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
_hitArea = CGPathRetain(CFAutorelease(CGPathCreateCopy(hitArea)));
|
|
||||||
CGPathRelease(hitArea);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_hitArea = CGPathRetain(CFAutorelease(CGPathCreateCopy(hitArea)));
|
||||||
|
CGPathRelease(hitArea);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ static double RNSVGTSpan_radToDeg = 180 / M_PI;
|
|||||||
// Create a dictionary for this font
|
// Create a dictionary for this font
|
||||||
CTFontRef fontRef = [self getFontFromContext];
|
CTFontRef fontRef = [self getFontFromContext];
|
||||||
CGMutablePathRef path = CGPathCreateMutable();
|
CGMutablePathRef path = CGPathCreateMutable();
|
||||||
RNSVGGlyphContext* gc = [[self getTextRoot] getGlyphContext];
|
RNSVGGlyphContext* gc = [self.textRoot getGlyphContext];
|
||||||
RNSVGFontData* font = [gc getFont];
|
RNSVGFontData* font = [gc getFont];
|
||||||
NSUInteger n = str.length;
|
NSUInteger n = str.length;
|
||||||
/*
|
/*
|
||||||
@@ -230,17 +230,30 @@ static double RNSVGTSpan_radToDeg = 180 / M_PI;
|
|||||||
*/
|
*/
|
||||||
// OpenType.js font data
|
// OpenType.js font data
|
||||||
NSDictionary * fontData = font->fontData;
|
NSDictionary * fontData = font->fontData;
|
||||||
|
NSMutableDictionary *attrs = [[NSMutableDictionary alloc] init];
|
||||||
|
|
||||||
NSNumber *lig = [NSNumber numberWithInt:allowOptionalLigatures ? 2 : 1];
|
NSNumber *lig = [NSNumber numberWithInt:allowOptionalLigatures ? 2 : 1];
|
||||||
|
attrs[NSLigatureAttributeName] = lig;
|
||||||
CFDictionaryRef attributes;
|
CFDictionaryRef attributes;
|
||||||
if (fontRef != nil) {
|
if (fontRef != nil) {
|
||||||
attributes = (__bridge CFDictionaryRef)@{
|
attrs[NSFontAttributeName] = (__bridge id)fontRef;
|
||||||
(NSString *)kCTFontAttributeName: (__bridge id)fontRef,
|
|
||||||
(NSString *)NSLigatureAttributeName: lig };
|
|
||||||
} else {
|
|
||||||
attributes = (__bridge CFDictionaryRef)@{
|
|
||||||
(NSString *)NSLigatureAttributeName: lig };
|
|
||||||
}
|
}
|
||||||
|
if (!autoKerning) {
|
||||||
|
NSNumber *noAutoKern = [NSNumber numberWithFloat:0.0f];
|
||||||
|
|
||||||
|
#if DTCORETEXT_SUPPORT_NS_ATTRIBUTES
|
||||||
|
if (___useiOS6Attributes)
|
||||||
|
{
|
||||||
|
[attrs setObject:noAutoKern forKey:NSKernAttributeName];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
[attrs setObject:noAutoKern forKey:(id)kCTKernAttributeName];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
attributes = (__bridge CFDictionaryRef)attrs;
|
||||||
|
|
||||||
CFStringRef string = (__bridge CFStringRef)str;
|
CFStringRef string = (__bridge CFStringRef)str;
|
||||||
CFAttributedStringRef attrString = CFAttributedStringCreate(kCFAllocatorDefault, string, attributes);
|
CFAttributedStringRef attrString = CFAttributedStringCreate(kCFAllocatorDefault, string, attributes);
|
||||||
@@ -509,8 +522,8 @@ static double RNSVGTSpan_radToDeg = 180 / M_PI;
|
|||||||
double top = ascenderHeight;
|
double top = ascenderHeight;
|
||||||
double totalHeight = top + bottom;
|
double totalHeight = top + bottom;
|
||||||
double baselineShift = 0;
|
double baselineShift = 0;
|
||||||
NSString *baselineShiftString = [self getBaselineShift];
|
NSString *baselineShiftString = self.baselineShift;
|
||||||
enum RNSVGAlignmentBaseline baseline = RNSVGAlignmentBaselineFromString([self getAlignmentBaseline]);
|
enum RNSVGAlignmentBaseline baseline = RNSVGAlignmentBaselineFromString(self.alignmentBaseline);
|
||||||
if (baseline != RNSVGAlignmentBaselineBaseline) {
|
if (baseline != RNSVGAlignmentBaselineBaseline) {
|
||||||
// TODO alignment-baseline, test / verify behavior
|
// TODO alignment-baseline, test / verify behavior
|
||||||
// TODO get per glyph baselines from font baseline table, for high-precision alignment
|
// TODO get per glyph baselines from font baseline table, for high-precision alignment
|
||||||
@@ -683,11 +696,7 @@ static double RNSVGTSpan_radToDeg = 180 / M_PI;
|
|||||||
/*
|
/*
|
||||||
Determine the glyph's charwidth (i.e., the amount which the current text position
|
Determine the glyph's charwidth (i.e., the amount which the current text position
|
||||||
advances horizontally when the glyph is drawn using horizontal text layout).
|
advances horizontally when the glyph is drawn using horizontal text layout).
|
||||||
*/
|
|
||||||
double unkernedAdvance = CTFontGetAdvancesForGlyphs(fontRef, kCTFontOrientationHorizontal, &glyph, NULL, 1);
|
|
||||||
CGFloat charWidth = unkernedAdvance * scaleSpacingAndGlyphs;
|
|
||||||
|
|
||||||
/*
|
|
||||||
For each subsequent glyph, set a new startpoint-on-the-path as the previous
|
For each subsequent glyph, set a new startpoint-on-the-path as the previous
|
||||||
endpoint-on-the-path, but with appropriate adjustments taking into account
|
endpoint-on-the-path, but with appropriate adjustments taking into account
|
||||||
horizontal kerning tables in the font and current values of various attributes
|
horizontal kerning tables in the font and current values of various attributes
|
||||||
@@ -696,10 +705,7 @@ static double RNSVGTSpan_radToDeg = 180 / M_PI;
|
|||||||
adjustments are calculated as distance adjustments along the path, calculated
|
adjustments are calculated as distance adjustments along the path, calculated
|
||||||
using the user agent's distance along the path algorithm.
|
using the user agent's distance along the path algorithm.
|
||||||
*/
|
*/
|
||||||
if (autoKerning) {
|
CGFloat charWidth = advances[g].width * scaleSpacingAndGlyphs;
|
||||||
double kerned = advances[g].width * scaleSpacingAndGlyphs;
|
|
||||||
kerning = kerned - charWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
CFIndex currIndex = indices[g];
|
CFIndex currIndex = indices[g];
|
||||||
char currentChar = [str characterAtIndex:currIndex];
|
char currentChar = [str characterAtIndex:currIndex];
|
||||||
|
|||||||
@@ -24,7 +24,5 @@
|
|||||||
- (void)releaseCachedPath;
|
- (void)releaseCachedPath;
|
||||||
- (CGPathRef)getGroupPath:(CGContextRef)context;
|
- (CGPathRef)getGroupPath:(CGContextRef)context;
|
||||||
- (CTFontRef)getFontFromContext;
|
- (CTFontRef)getFontFromContext;
|
||||||
- (NSString*) getAlignmentBaseline;
|
|
||||||
- (NSString*) getBaselineShift;
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -15,7 +15,6 @@
|
|||||||
|
|
||||||
@implementation RNSVGText
|
@implementation RNSVGText
|
||||||
{
|
{
|
||||||
RNSVGText *_textRoot;
|
|
||||||
RNSVGGlyphContext *_glyphContext;
|
RNSVGGlyphContext *_glyphContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,68 +75,69 @@
|
|||||||
[self popGlyphContext];
|
[self popGlyphContext];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (RNSVGText *)getTextRoot
|
// TODO: Optimisation required
|
||||||
|
- (RNSVGText *)textRoot
|
||||||
{
|
{
|
||||||
if (!_textRoot) {
|
RNSVGText *root = self;
|
||||||
_textRoot = self;
|
while (root && [root class] != [RNSVGText class]) {
|
||||||
while (_textRoot && [_textRoot class] != [RNSVGText class]) {
|
if (![root isKindOfClass:[RNSVGText class]]) {
|
||||||
if (![_textRoot isKindOfClass:[RNSVGText class]]) {
|
//todo: throw exception here
|
||||||
//todo: throw exception here
|
break;
|
||||||
break;
|
|
||||||
}
|
|
||||||
_textRoot = (RNSVGText*)[_textRoot superview];
|
|
||||||
}
|
}
|
||||||
|
root = (RNSVGText*)[root superview];
|
||||||
}
|
}
|
||||||
|
|
||||||
return _textRoot;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString*) getAlignmentBaseline
|
- (NSString *)alignmentBaseline
|
||||||
{
|
{
|
||||||
if (self.alignmentBaseline != nil) {
|
if (_alignmentBaseline != nil) {
|
||||||
return self.alignmentBaseline;
|
return _alignmentBaseline;
|
||||||
}
|
}
|
||||||
UIView* parent = [self superview];
|
|
||||||
|
UIView* parent = self.superview;
|
||||||
while (parent != nil) {
|
while (parent != nil) {
|
||||||
if ([parent isKindOfClass:[RNSVGText class]]) {
|
if ([parent isKindOfClass:[RNSVGText class]]) {
|
||||||
RNSVGText* node = (RNSVGText*)parent;
|
RNSVGText* node = (RNSVGText*)parent;
|
||||||
NSString* baseline = node.alignmentBaseline;
|
NSString* baseline = node.alignmentBaseline;
|
||||||
if (baseline != nil) {
|
if (baseline != nil) {
|
||||||
self.alignmentBaseline = baseline;
|
_alignmentBaseline = baseline;
|
||||||
return baseline;
|
return baseline;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
parent = [parent superview];
|
parent = [parent superview];
|
||||||
}
|
}
|
||||||
if (self.alignmentBaseline == nil) {
|
|
||||||
self.alignmentBaseline = RNSVGAlignmentBaselineStrings[0];
|
if (_alignmentBaseline == nil) {
|
||||||
|
_alignmentBaseline = RNSVGAlignmentBaselineStrings[0];
|
||||||
}
|
}
|
||||||
return self.alignmentBaseline;
|
return _alignmentBaseline;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString*) getBaselineShift
|
- (NSString *)baselineShift
|
||||||
{
|
{
|
||||||
if (self.baselineShift != nil) {
|
if (_baselineShift != nil) {
|
||||||
return self.baselineShift;
|
return _baselineShift;
|
||||||
}
|
}
|
||||||
if (self.baselineShift == nil) {
|
|
||||||
UIView* parent = [self superview];
|
UIView* parent = [self superview];
|
||||||
while (parent != nil) {
|
while (parent != nil) {
|
||||||
if ([parent isKindOfClass:[RNSVGText class]]) {
|
if ([parent isKindOfClass:[RNSVGText class]]) {
|
||||||
RNSVGText* node = (RNSVGText*)parent;
|
RNSVGText* node = (RNSVGText*)parent;
|
||||||
NSString* baselineShift = node.baselineShift;
|
NSString* baselineShift = node.baselineShift;
|
||||||
if (baselineShift != nil) {
|
if (baselineShift != nil) {
|
||||||
self.baselineShift = baselineShift;
|
_baselineShift = baselineShift;
|
||||||
return baselineShift;
|
return baselineShift;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
parent = [parent superview];
|
|
||||||
}
|
}
|
||||||
|
parent = [parent superview];
|
||||||
}
|
}
|
||||||
if (self.baselineShift == nil) {
|
|
||||||
self.baselineShift = @"";
|
// set default value
|
||||||
}
|
_baselineShift = @"";
|
||||||
return self.baselineShift;
|
|
||||||
|
return _baselineShift;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (RNSVGGlyphContext *)getGlyphContext
|
- (RNSVGGlyphContext *)getGlyphContext
|
||||||
@@ -147,23 +147,23 @@
|
|||||||
|
|
||||||
- (void)pushGlyphContext
|
- (void)pushGlyphContext
|
||||||
{
|
{
|
||||||
[[[self getTextRoot] getGlyphContext] pushContext:self
|
[[self.textRoot getGlyphContext] pushContext:self
|
||||||
font:self.font
|
font:self.font
|
||||||
x:self.positionX
|
x:self.positionX
|
||||||
y:self.positionY
|
y:self.positionY
|
||||||
deltaX:self.deltaX
|
deltaX:self.deltaX
|
||||||
deltaY:self.deltaY
|
deltaY:self.deltaY
|
||||||
rotate:self.rotate];
|
rotate:self.rotate];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)popGlyphContext
|
- (void)popGlyphContext
|
||||||
{
|
{
|
||||||
[[[self getTextRoot] getGlyphContext] popContext];
|
[[self.textRoot getGlyphContext] popContext];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (CTFontRef)getFontFromContext
|
- (CTFontRef)getFontFromContext
|
||||||
{
|
{
|
||||||
return [[[self getTextRoot] getGlyphContext] getGlyphFont];
|
return [[self.textRoot getGlyphContext] getGlyphFont];
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -114,8 +114,7 @@ void RNSVGPerformanceBezier_addLine(CGPoint *last, const CGPoint *next, NSMutabl
|
|||||||
|
|
||||||
- (void)getPathLength:(CGFloat*)lengthP lineCount:(NSUInteger*)lineCountP lengths:(NSArray* __strong *)lengthsP lines:(NSArray* __strong *)linesP isClosed:(BOOL*)isClosedP
|
- (void)getPathLength:(CGFloat*)lengthP lineCount:(NSUInteger*)lineCountP lengths:(NSArray* __strong *)lengthsP lines:(NSArray* __strong *)linesP isClosed:(BOOL*)isClosedP
|
||||||
{
|
{
|
||||||
RNSVGSvgView *svg = [self getSvgView];
|
RNSVGNode *template = [self.svgView getDefinedTemplate:self.href];
|
||||||
RNSVGNode *template = [svg getDefinedTemplate:self.href];
|
|
||||||
CGPathRef path = [template getPath:nil];
|
CGPathRef path = [template getPath:nil];
|
||||||
|
|
||||||
if (_path != path) {
|
if (_path != path) {
|
||||||
|
|||||||
@@ -17,7 +17,10 @@ RCT_EXPORT_MODULE()
|
|||||||
|
|
||||||
- (RNSVGRenderable *)node
|
- (RNSVGRenderable *)node
|
||||||
{
|
{
|
||||||
return [RNSVGImage new];
|
RNSVGImage *svgImage = [RNSVGImage new];
|
||||||
|
svgImage.bridge = self.bridge;
|
||||||
|
|
||||||
|
return svgImage;
|
||||||
}
|
}
|
||||||
|
|
||||||
RCT_EXPORT_VIEW_PROPERTY(x, NSString)
|
RCT_EXPORT_VIEW_PROPERTY(x, NSString)
|
||||||
|
|||||||
@@ -30,5 +30,7 @@ RCT_EXPORT_VIEW_PROPERTY(matrix, CGAffineTransform)
|
|||||||
RCT_EXPORT_VIEW_PROPERTY(clipPath, NSString)
|
RCT_EXPORT_VIEW_PROPERTY(clipPath, NSString)
|
||||||
RCT_EXPORT_VIEW_PROPERTY(clipRule, RNSVGCGFCRule)
|
RCT_EXPORT_VIEW_PROPERTY(clipRule, RNSVGCGFCRule)
|
||||||
RCT_EXPORT_VIEW_PROPERTY(responsible, BOOL)
|
RCT_EXPORT_VIEW_PROPERTY(responsible, BOOL)
|
||||||
|
RCT_EXPORT_VIEW_PROPERTY(onLayout, RCTDirectEventBlock)
|
||||||
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
112
lib/Matrix2D.js
112
lib/Matrix2D.js
@@ -119,7 +119,14 @@ export default class Matrix2D {
|
|||||||
*/
|
*/
|
||||||
copy = function(matrix) {
|
copy = function(matrix) {
|
||||||
//noinspection JSUnresolvedVariable
|
//noinspection JSUnresolvedVariable
|
||||||
return this.setTransform(matrix.a, matrix.b, matrix.c, matrix.d, matrix.tx, matrix.ty);
|
return this.setTransform(
|
||||||
|
matrix.a,
|
||||||
|
matrix.b,
|
||||||
|
matrix.c,
|
||||||
|
matrix.d,
|
||||||
|
matrix.tx,
|
||||||
|
matrix.ty
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
//noinspection JSUnusedGlobalSymbols
|
//noinspection JSUnusedGlobalSymbols
|
||||||
@@ -150,10 +157,10 @@ export default class Matrix2D {
|
|||||||
const c1 = this.c;
|
const c1 = this.c;
|
||||||
const tx1 = this.tx;
|
const tx1 = this.tx;
|
||||||
|
|
||||||
this.a = a * a1 + c * this.b;
|
this.a = a * a1 + c * this.b;
|
||||||
this.b = b * a1 + d * this.b;
|
this.b = b * a1 + d * this.b;
|
||||||
this.c = a * c1 + c * this.d;
|
this.c = a * c1 + c * this.d;
|
||||||
this.d = b * c1 + d * this.d;
|
this.d = b * c1 + d * this.d;
|
||||||
this.tx = a * tx1 + c * this.ty + tx;
|
this.tx = a * tx1 + c * this.ty + tx;
|
||||||
this.ty = b * tx1 + d * this.ty + ty;
|
this.ty = b * tx1 + d * this.ty + ty;
|
||||||
//noinspection JSValidateTypes
|
//noinspection JSValidateTypes
|
||||||
@@ -178,10 +185,10 @@ export default class Matrix2D {
|
|||||||
const c1 = this.c;
|
const c1 = this.c;
|
||||||
const d1 = this.d;
|
const d1 = this.d;
|
||||||
if (a !== 1 || b !== 0 || c !== 0 || d !== 1) {
|
if (a !== 1 || b !== 0 || c !== 0 || d !== 1) {
|
||||||
this.a = a1 * a + c1 * b;
|
this.a = a1 * a + c1 * b;
|
||||||
this.b = b1 * a + d1 * b;
|
this.b = b1 * a + d1 * b;
|
||||||
this.c = a1 * c + c1 * d;
|
this.c = a1 * c + c1 * d;
|
||||||
this.d = b1 * c + d1 * d;
|
this.d = b1 * c + d1 * d;
|
||||||
}
|
}
|
||||||
this.tx = a1 * tx + c1 * ty + this.tx;
|
this.tx = a1 * tx + c1 * ty + this.tx;
|
||||||
this.ty = b1 * tx + d1 * ty + this.ty;
|
this.ty = b1 * tx + d1 * ty + this.ty;
|
||||||
@@ -207,7 +214,17 @@ export default class Matrix2D {
|
|||||||
* @param {Number} regY Optional.
|
* @param {Number} regY Optional.
|
||||||
* @return {Matrix2D} This matrix. Useful for chaining method calls.
|
* @return {Matrix2D} This matrix. Useful for chaining method calls.
|
||||||
**/
|
**/
|
||||||
appendTransform = function(x, y, scaleX, scaleY, rotation, skewX, skewY, regX, regY) {
|
appendTransform = function(
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
scaleX,
|
||||||
|
scaleY,
|
||||||
|
rotation,
|
||||||
|
skewX,
|
||||||
|
skewY,
|
||||||
|
regX,
|
||||||
|
regY
|
||||||
|
) {
|
||||||
let cos, sin;
|
let cos, sin;
|
||||||
if (rotation % 360) {
|
if (rotation % 360) {
|
||||||
const r = rotation * DEG_TO_RAD;
|
const r = rotation * DEG_TO_RAD;
|
||||||
@@ -222,10 +239,31 @@ export default class Matrix2D {
|
|||||||
// TODO: can this be combined into a single append operation?
|
// TODO: can this be combined into a single append operation?
|
||||||
skewX *= DEG_TO_RAD;
|
skewX *= DEG_TO_RAD;
|
||||||
skewY *= DEG_TO_RAD;
|
skewY *= DEG_TO_RAD;
|
||||||
this.append(Math.cos(skewY), Math.sin(skewY), Math.sin(skewX), Math.cos(skewX), x, y);
|
this.append(
|
||||||
this.append(cos * scaleX, sin * scaleX, -sin * scaleY, cos * scaleY, 0, 0);
|
Math.cos(skewY),
|
||||||
|
Math.sin(skewY),
|
||||||
|
Math.sin(skewX),
|
||||||
|
Math.cos(skewX),
|
||||||
|
x,
|
||||||
|
y
|
||||||
|
);
|
||||||
|
this.append(
|
||||||
|
cos * scaleX,
|
||||||
|
sin * scaleX,
|
||||||
|
-sin * scaleY,
|
||||||
|
cos * scaleY,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
this.append(cos * scaleX, sin * scaleX, -sin * scaleY, cos * scaleY, x, y);
|
this.append(
|
||||||
|
cos * scaleX,
|
||||||
|
sin * scaleX,
|
||||||
|
-sin * scaleY,
|
||||||
|
cos * scaleY,
|
||||||
|
x,
|
||||||
|
y
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (regX || regY) {
|
if (regX || regY) {
|
||||||
@@ -245,9 +283,9 @@ export default class Matrix2D {
|
|||||||
* var o = myDisplayObject;
|
* var o = myDisplayObject;
|
||||||
* var mtx = new createjs.Matrix2D();
|
* var mtx = new createjs.Matrix2D();
|
||||||
* do {
|
* do {
|
||||||
* // prepend each parent's transformation in turn:
|
* // prepend each parent's transformation in turn:
|
||||||
* mtx.prependTransform(o.x, o.y, o.scaleX, o.scaleY, o.rotation, o.skewX, o.skewY, o.regX, o.regY);
|
* mtx.prependTransform(o.x, o.y, o.scaleX, o.scaleY, o.rotation, o.skewX, o.skewY, o.regX, o.regY);
|
||||||
* } while (o = o.parent);
|
* } while (o = o.parent);
|
||||||
*
|
*
|
||||||
* Note that the above example would not account for {{#crossLink "DisplayObject/transformMatrix:property"}}{{/crossLink}}
|
* Note that the above example would not account for {{#crossLink "DisplayObject/transformMatrix:property"}}{{/crossLink}}
|
||||||
* values. See {{#crossLink "Matrix2D/prependMatrix"}}{{/crossLink}} for an example that does.
|
* values. See {{#crossLink "Matrix2D/prependMatrix"}}{{/crossLink}} for an example that does.
|
||||||
@@ -263,7 +301,17 @@ export default class Matrix2D {
|
|||||||
* @param {Number} regY Optional.
|
* @param {Number} regY Optional.
|
||||||
* @return {Matrix2D} This matrix. Useful for chaining method calls.
|
* @return {Matrix2D} This matrix. Useful for chaining method calls.
|
||||||
**/
|
**/
|
||||||
prependTransform = function(x, y, scaleX, scaleY, rotation, skewX, skewY, regX, regY) {
|
prependTransform = function(
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
scaleX,
|
||||||
|
scaleY,
|
||||||
|
rotation,
|
||||||
|
skewX,
|
||||||
|
skewY,
|
||||||
|
regX,
|
||||||
|
regY
|
||||||
|
) {
|
||||||
let cos, sin;
|
let cos, sin;
|
||||||
if (rotation % 360) {
|
if (rotation % 360) {
|
||||||
const r = rotation * DEG_TO_RAD;
|
const r = rotation * DEG_TO_RAD;
|
||||||
@@ -276,16 +324,38 @@ export default class Matrix2D {
|
|||||||
|
|
||||||
if (regX || regY) {
|
if (regX || regY) {
|
||||||
// prepend the registration offset:
|
// prepend the registration offset:
|
||||||
this.tx -= regX; this.ty -= regY;
|
this.tx -= regX;
|
||||||
|
this.ty -= regY;
|
||||||
}
|
}
|
||||||
if (skewX || skewY) {
|
if (skewX || skewY) {
|
||||||
// TODO: can this be combined into a single prepend operation?
|
// TODO: can this be combined into a single prepend operation?
|
||||||
skewX *= DEG_TO_RAD;
|
skewX *= DEG_TO_RAD;
|
||||||
skewY *= DEG_TO_RAD;
|
skewY *= DEG_TO_RAD;
|
||||||
this.prepend(cos * scaleX, sin * scaleX, -sin * scaleY, cos * scaleY, 0, 0);
|
this.prepend(
|
||||||
this.prepend(Math.cos(skewY), Math.sin(skewY), -Math.sin(skewX), Math.cos(skewX), x, y);
|
cos * scaleX,
|
||||||
|
sin * scaleX,
|
||||||
|
-sin * scaleY,
|
||||||
|
cos * scaleY,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
);
|
||||||
|
this.prepend(
|
||||||
|
Math.cos(skewY),
|
||||||
|
Math.sin(skewY),
|
||||||
|
-Math.sin(skewX),
|
||||||
|
Math.cos(skewX),
|
||||||
|
x,
|
||||||
|
y
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
this.prepend(cos * scaleX, sin * scaleX, -sin * scaleY, cos * scaleY, x, y);
|
this.prepend(
|
||||||
|
cos * scaleX,
|
||||||
|
sin * scaleX,
|
||||||
|
-sin * scaleY,
|
||||||
|
cos * scaleY,
|
||||||
|
x,
|
||||||
|
y
|
||||||
|
);
|
||||||
}
|
}
|
||||||
//noinspection JSValidateTypes
|
//noinspection JSValidateTypes
|
||||||
return this;
|
return this;
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
objectBoundingBox: 0,
|
objectBoundingBox: 0,
|
||||||
userSpaceOnUse: 1
|
userSpaceOnUse: 1
|
||||||
|
|||||||
@@ -1,28 +1,33 @@
|
|||||||
import Touchable from 'react-native/Libraries/Components/Touchable/Touchable';
|
import { Touchable } from "react-native";
|
||||||
const PRESS_RETENTION_OFFSET = {top: 20, left: 20, right: 20, bottom: 30};
|
const PRESS_RETENTION_OFFSET = { top: 20, left: 20, right: 20, bottom: 30 };
|
||||||
|
|
||||||
//noinspection JSUnusedGlobalSymbols
|
//noinspection JSUnusedGlobalSymbols
|
||||||
export default {
|
export default {
|
||||||
...Touchable.Mixin,
|
...Touchable.Mixin,
|
||||||
|
|
||||||
touchableHandleStartShouldSetResponder: function (e) {
|
touchableHandleStartShouldSetResponder: function(e) {
|
||||||
|
|
||||||
if (this.props.onStartShouldSetResponder) {
|
if (this.props.onStartShouldSetResponder) {
|
||||||
return this.props.onStartShouldSetResponder(e);
|
return this.props.onStartShouldSetResponder(e);
|
||||||
} else {
|
} else {
|
||||||
return Touchable.Mixin.touchableHandleStartShouldSetResponder.call(this, e);
|
return Touchable.Mixin.touchableHandleStartShouldSetResponder.call(
|
||||||
|
this,
|
||||||
|
e
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
touchableHandleResponderTerminationRequest: function (e) {
|
touchableHandleResponderTerminationRequest: function(e) {
|
||||||
if (this.props.onResponderTerminationRequest) {
|
if (this.props.onResponderTerminationRequest) {
|
||||||
return this.props.onResponderTerminationRequest(e);
|
return this.props.onResponderTerminationRequest(e);
|
||||||
} else {
|
} else {
|
||||||
return Touchable.Mixin.touchableHandleResponderTerminationRequest.call(this, e);
|
return Touchable.Mixin.touchableHandleResponderTerminationRequest.call(
|
||||||
|
this,
|
||||||
|
e
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
touchableHandleResponderGrant: function (e) {
|
touchableHandleResponderGrant: function(e) {
|
||||||
if (this.props.onResponderGrant) {
|
if (this.props.onResponderGrant) {
|
||||||
return this.props.onResponderGrant(e);
|
return this.props.onResponderGrant(e);
|
||||||
} else {
|
} else {
|
||||||
@@ -30,7 +35,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
touchableHandleResponderMove: function (e) {
|
touchableHandleResponderMove: function(e) {
|
||||||
if (this.props.onResponderMove) {
|
if (this.props.onResponderMove) {
|
||||||
return this.props.onResponderMove(e);
|
return this.props.onResponderMove(e);
|
||||||
} else {
|
} else {
|
||||||
@@ -38,19 +43,25 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
touchableHandleResponderRelease: function (e) {
|
touchableHandleResponderRelease: function(e) {
|
||||||
if (this.props.onResponderRelease) {
|
if (this.props.onResponderRelease) {
|
||||||
return this.props.onResponderRelease(e);
|
return this.props.onResponderRelease(e);
|
||||||
} else {
|
} else {
|
||||||
return Touchable.Mixin.touchableHandleResponderRelease.call(this, e);
|
return Touchable.Mixin.touchableHandleResponderRelease.call(
|
||||||
|
this,
|
||||||
|
e
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
touchableHandleResponderTerminate: function (e) {
|
touchableHandleResponderTerminate: function(e) {
|
||||||
if (this.props.onResponderTerminate) {
|
if (this.props.onResponderTerminate) {
|
||||||
return this.props.onResponderTerminate(e);
|
return this.props.onResponderTerminate(e);
|
||||||
} else {
|
} else {
|
||||||
return Touchable.Mixin.touchableHandleResponderTerminate.call(this, e);
|
return Touchable.Mixin.touchableHandleResponderTerminate.call(
|
||||||
|
this,
|
||||||
|
e
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -83,8 +94,9 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
touchableGetLongPressDelayMS: function() {
|
touchableGetLongPressDelayMS: function() {
|
||||||
return this.props.delayLongPress === 0 ? 0 :
|
return this.props.delayLongPress === 0
|
||||||
this.props.delayLongPress || 500;
|
? 0
|
||||||
|
: this.props.delayLongPress || 500;
|
||||||
},
|
},
|
||||||
|
|
||||||
touchableGetPressOutDelayMS: function() {
|
touchableGetPressOutDelayMS: function() {
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
function arrayDiffer(a, b) {
|
function arrayDiffer(a, b) {
|
||||||
if (!a || !b) {
|
if (!a || !b) {
|
||||||
return true;
|
return true;
|
||||||
@@ -91,7 +90,7 @@ const GroupAttributes = {
|
|||||||
...RenderableAttributes,
|
...RenderableAttributes,
|
||||||
font: {
|
font: {
|
||||||
diff: fontDiffer
|
diff: fontDiffer
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const UseAttributes = {
|
const UseAttributes = {
|
||||||
@@ -103,12 +102,12 @@ const UseAttributes = {
|
|||||||
|
|
||||||
const SymbolAttributes = {
|
const SymbolAttributes = {
|
||||||
...ViewBoxAttributes,
|
...ViewBoxAttributes,
|
||||||
name: true,
|
name: true
|
||||||
};
|
};
|
||||||
|
|
||||||
const PathAttributes = {
|
const PathAttributes = {
|
||||||
...RenderableAttributes,
|
...RenderableAttributes,
|
||||||
d: true,
|
d: true
|
||||||
};
|
};
|
||||||
|
|
||||||
const TextSpecificAttributes = {
|
const TextSpecificAttributes = {
|
||||||
@@ -117,7 +116,7 @@ const TextSpecificAttributes = {
|
|||||||
baselineShift: true,
|
baselineShift: true,
|
||||||
verticalAlign: true,
|
verticalAlign: true,
|
||||||
lengthAdjust: true,
|
lengthAdjust: true,
|
||||||
textLength: true,
|
textLength: true
|
||||||
};
|
};
|
||||||
|
|
||||||
const TextAttributes = {
|
const TextAttributes = {
|
||||||
@@ -129,7 +128,7 @@ const TextAttributes = {
|
|||||||
deltaY: arrayDiffer,
|
deltaY: arrayDiffer,
|
||||||
rotate: arrayDiffer,
|
rotate: arrayDiffer,
|
||||||
positionX: arrayDiffer,
|
positionX: arrayDiffer,
|
||||||
positionY: arrayDiffer,
|
positionY: arrayDiffer
|
||||||
};
|
};
|
||||||
|
|
||||||
const TextPathAttributes = {
|
const TextPathAttributes = {
|
||||||
@@ -139,12 +138,12 @@ const TextPathAttributes = {
|
|||||||
method: true,
|
method: true,
|
||||||
spacing: true,
|
spacing: true,
|
||||||
side: true,
|
side: true,
|
||||||
midLine: true,
|
midLine: true
|
||||||
};
|
};
|
||||||
|
|
||||||
const TSpanAttibutes = {
|
const TSpanAttibutes = {
|
||||||
...TextAttributes,
|
...TextAttributes,
|
||||||
content: true,
|
content: true
|
||||||
};
|
};
|
||||||
|
|
||||||
const ClipPathAttributes = {
|
const ClipPathAttributes = {
|
||||||
@@ -159,7 +158,7 @@ const GradientAttributes = {
|
|||||||
gradientUnits: true,
|
gradientUnits: true,
|
||||||
gradientTransform: {
|
gradientTransform: {
|
||||||
diff: arrayDiffer
|
diff: arrayDiffer
|
||||||
},
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const LinearGradientAttributes = {
|
const LinearGradientAttributes = {
|
||||||
@@ -167,7 +166,7 @@ const LinearGradientAttributes = {
|
|||||||
x1: true,
|
x1: true,
|
||||||
y1: true,
|
y1: true,
|
||||||
x2: true,
|
x2: true,
|
||||||
y2: true,
|
y2: true
|
||||||
};
|
};
|
||||||
|
|
||||||
const RadialGradientAttributes = {
|
const RadialGradientAttributes = {
|
||||||
@@ -178,15 +177,14 @@ const RadialGradientAttributes = {
|
|||||||
ry: true,
|
ry: true,
|
||||||
cx: true,
|
cx: true,
|
||||||
cy: true,
|
cy: true,
|
||||||
r: true,
|
r: true
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const CircleAttributes = {
|
const CircleAttributes = {
|
||||||
...RenderableAttributes,
|
...RenderableAttributes,
|
||||||
cx: true,
|
cx: true,
|
||||||
cy: true,
|
cy: true,
|
||||||
r: true,
|
r: true
|
||||||
};
|
};
|
||||||
|
|
||||||
const EllipseAttributes = {
|
const EllipseAttributes = {
|
||||||
@@ -194,7 +192,7 @@ const EllipseAttributes = {
|
|||||||
cx: true,
|
cx: true,
|
||||||
cy: true,
|
cy: true,
|
||||||
rx: true,
|
rx: true,
|
||||||
ry: true,
|
ry: true
|
||||||
};
|
};
|
||||||
|
|
||||||
const ImageAttributes = {
|
const ImageAttributes = {
|
||||||
@@ -205,7 +203,7 @@ const ImageAttributes = {
|
|||||||
imageheight: true,
|
imageheight: true,
|
||||||
src: true,
|
src: true,
|
||||||
align: true,
|
align: true,
|
||||||
meetOrSlice: true,
|
meetOrSlice: true
|
||||||
};
|
};
|
||||||
|
|
||||||
const LineAttributes = {
|
const LineAttributes = {
|
||||||
@@ -213,7 +211,7 @@ const LineAttributes = {
|
|||||||
x1: true,
|
x1: true,
|
||||||
y1: true,
|
y1: true,
|
||||||
x2: true,
|
x2: true,
|
||||||
y2: true,
|
y2: true
|
||||||
};
|
};
|
||||||
|
|
||||||
const RectAttributes = {
|
const RectAttributes = {
|
||||||
@@ -223,7 +221,7 @@ const RectAttributes = {
|
|||||||
rectwidth: true,
|
rectwidth: true,
|
||||||
rectheight: true,
|
rectheight: true,
|
||||||
rx: true,
|
rx: true,
|
||||||
ry: true,
|
ry: true
|
||||||
};
|
};
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
import createReactNativeComponentClass from 'react-native/Libraries/Renderer/shims/createReactNativeComponentClass.js'
|
|
||||||
|
|
||||||
export default (uiViewClassName, getViewConfig) =>
|
|
||||||
createReactNativeComponentClass.length >= 2
|
|
||||||
? createReactNativeComponentClass(uiViewClassName, getViewConfig)
|
|
||||||
: createReactNativeComponentClass(getViewConfig())
|
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
import Color from 'color';
|
import Color from "color";
|
||||||
import patternReg from './patternReg';
|
import patternReg from "./patternReg";
|
||||||
|
|
||||||
export default function (colorOrBrush) {
|
export default function(colorOrBrush) {
|
||||||
if (colorOrBrush === 'none' || !colorOrBrush) {
|
if (colorOrBrush === "none" || !colorOrBrush) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -12,8 +12,11 @@ export default function (colorOrBrush) {
|
|||||||
if (matched) {
|
if (matched) {
|
||||||
return [1, matched[1]];
|
return [1, matched[1]];
|
||||||
//todo:
|
//todo:
|
||||||
} else { // solid color
|
} else {
|
||||||
let [r, g, b, a = 1] = Color(colorOrBrush).rgb().array();
|
// solid color
|
||||||
|
let [r, g, b, a = 1] = Color(colorOrBrush)
|
||||||
|
.rgb()
|
||||||
|
.array();
|
||||||
return [0, r / 255, g / 255, b / 255, a];
|
return [0, r / 255, g / 255, b / 255, a];
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import clipReg from './patternReg';
|
import clipReg from "./patternReg";
|
||||||
|
|
||||||
const clipRules = {
|
const clipRules = {
|
||||||
evenodd: 0,
|
evenodd: 0,
|
||||||
nonzero: 1
|
nonzero: 1
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function (props) {
|
export default function(props) {
|
||||||
let {clipPath, clipRule} = props;
|
let { clipPath, clipRule } = props;
|
||||||
let clipPathProps = {};
|
let clipPathProps = {};
|
||||||
|
|
||||||
if (clipPath) {
|
if (clipPath) {
|
||||||
@@ -17,7 +17,11 @@ export default function (props) {
|
|||||||
if (matched) {
|
if (matched) {
|
||||||
clipPathProps.clipPath = matched[1];
|
clipPathProps.clipPath = matched[1];
|
||||||
} else {
|
} else {
|
||||||
console.warn('Invalid `clipPath` prop, expected a clipPath like `"#id"`, but got: "' + clipPath + '"');
|
console.warn(
|
||||||
|
'Invalid `clipPath` prop, expected a clipPath like `"#id"`, but got: "' +
|
||||||
|
clipPath +
|
||||||
|
'"'
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import extractBrush from './extractBrush';
|
import extractBrush from "./extractBrush";
|
||||||
import extractOpacity from './extractOpacity';
|
import extractOpacity from "./extractOpacity";
|
||||||
import {fillProps} from '../props';
|
import { fillProps } from "../props";
|
||||||
|
|
||||||
const fillRules = {
|
const fillRules = {
|
||||||
evenodd: 0,
|
evenodd: 0,
|
||||||
@@ -10,7 +10,7 @@ const fillRules = {
|
|||||||
const fillKeys = Object.keys(fillProps);
|
const fillKeys = Object.keys(fillProps);
|
||||||
|
|
||||||
export default function(props, styleProperties) {
|
export default function(props, styleProperties) {
|
||||||
fillKeys.forEach((name) => {
|
fillKeys.forEach(name => {
|
||||||
if (props.hasOwnProperty(name)) {
|
if (props.hasOwnProperty(name)) {
|
||||||
styleProperties.push(name);
|
styleProperties.push(name);
|
||||||
}
|
}
|
||||||
@@ -18,7 +18,7 @@ export default function(props, styleProperties) {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
// default fill is black
|
// default fill is black
|
||||||
fill: extractBrush(props.fill || '#000'),
|
fill: extractBrush(props.fill || "#000"),
|
||||||
fillOpacity: extractOpacity(props.fillOpacity),
|
fillOpacity: extractOpacity(props.fillOpacity),
|
||||||
fillRule: fillRules[props.fillRule] === 0 ? 0 : 1
|
fillRule: fillRules[props.fillRule] === 0 ? 0 : 1
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import {Children} from 'react';
|
import { Children } from "react";
|
||||||
import _ from 'lodash';
|
import _ from "lodash";
|
||||||
import Color from 'color';
|
import Color from "color";
|
||||||
|
|
||||||
import extractOpacity from './extractOpacity';
|
import extractOpacity from "./extractOpacity";
|
||||||
import extractTransform from './extractTransform';
|
import extractTransform from "./extractTransform";
|
||||||
import PATTERN_UNITS from '../PATTERN_UNITS';
|
import PATTERN_UNITS from "../PATTERN_UNITS";
|
||||||
import percentToFloat from '../percentToFloat';
|
import percentToFloat from "../percentToFloat";
|
||||||
import Stop from '../../elements/Stop';
|
import Stop from "../../elements/Stop";
|
||||||
|
|
||||||
export default function(props) {
|
export default function(props) {
|
||||||
if (!props.id) {
|
if (!props.id) {
|
||||||
@@ -15,27 +15,28 @@ export default function(props) {
|
|||||||
|
|
||||||
const stops = {};
|
const stops = {};
|
||||||
Children.forEach(props.children, child => {
|
Children.forEach(props.children, child => {
|
||||||
if (child.type === Stop) {
|
if (child.props.stopColor && child.props.offset) {
|
||||||
if (child.props.stopColor && child.props.offset) {
|
// convert percent to float.
|
||||||
// convert percent to float.
|
let offset = percentToFloat(child.props.offset);
|
||||||
let offset = percentToFloat(child.props.offset);
|
|
||||||
|
|
||||||
// add stop
|
// add stop
|
||||||
//noinspection JSUnresolvedFunction
|
//noinspection JSUnresolvedFunction
|
||||||
stops[offset] = Color(child.props.stopColor).alpha(extractOpacity(child.props.stopOpacity));
|
stops[offset] = Color(child.props.stopColor).alpha(
|
||||||
}
|
extractOpacity(child.props.stopOpacity)
|
||||||
} else {
|
);
|
||||||
console.warn('`Gradient` elements only accept `Stop` elements as children');
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const sorted = _.sortBy(_.map(stops, (stop, offset) => {
|
const sorted = _.sortBy(
|
||||||
return {stop, offset};
|
_.map(stops, (stop, offset) => {
|
||||||
}), 'offset');
|
return { stop, offset };
|
||||||
|
}),
|
||||||
|
"offset"
|
||||||
|
);
|
||||||
|
|
||||||
const gradient = [];
|
const gradient = [];
|
||||||
|
|
||||||
sorted.forEach(({stop}) => {
|
sorted.forEach(({ stop }) => {
|
||||||
let [r, g, b, a = 1] = stop.rgb().array();
|
let [r, g, b, a = 1] = stop.rgb().array();
|
||||||
gradient.push(r / 255);
|
gradient.push(r / 255);
|
||||||
gradient.push(g / 255);
|
gradient.push(g / 255);
|
||||||
@@ -43,8 +44,7 @@ export default function(props) {
|
|||||||
gradient.push(a);
|
gradient.push(a);
|
||||||
});
|
});
|
||||||
|
|
||||||
gradient.push(...sorted.map(({offset}) => +offset));
|
gradient.push(...sorted.map(({ offset }) => +offset));
|
||||||
|
|
||||||
|
|
||||||
let gradientTransform;
|
let gradientTransform;
|
||||||
if (props.gradientTransform) {
|
if (props.gradientTransform) {
|
||||||
|
|||||||
@@ -1,12 +1,15 @@
|
|||||||
const spaceReg = /\s+/;
|
const spaceReg = /\s+/;
|
||||||
const commaReg = /,/g;
|
const commaReg = /,/g;
|
||||||
|
|
||||||
export default function (lengthList) {
|
export default function(lengthList) {
|
||||||
if (typeof lengthList === 'string') {
|
if (typeof lengthList === "string") {
|
||||||
return lengthList.trim().replace(commaReg, ' ').split(spaceReg);
|
return lengthList
|
||||||
} else if (typeof lengthList === 'number') {
|
.trim()
|
||||||
|
.replace(commaReg, " ")
|
||||||
|
.split(spaceReg);
|
||||||
|
} else if (typeof lengthList === "number") {
|
||||||
return [`${lengthList}`];
|
return [`${lengthList}`];
|
||||||
} else if (lengthList && typeof lengthList.map === 'function') {
|
} else if (lengthList && typeof lengthList.map === "function") {
|
||||||
return lengthList.map(d => `${d}`);
|
return lengthList.map(d => `${d}`);
|
||||||
} else {
|
} else {
|
||||||
return [];
|
return [];
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
export default function (opacity) {
|
export default function(opacity) {
|
||||||
const value = +opacity;
|
const value = +opacity;
|
||||||
return (typeof value !== 'number' || isNaN(value)) ? 1 : value;
|
return typeof value !== "number" || isNaN(value) ? 1 : value;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
|
export default function(polyPoints) {
|
||||||
export default function (polyPoints) {
|
return polyPoints
|
||||||
return polyPoints.replace(/[^e]-/, ' -').split(/(?:\s+|\s*,\s*)/g).join(' ');
|
.replace(/[^e]-/, " -")
|
||||||
|
.split(/(?:\s+|\s*,\s*)/g)
|
||||||
|
.join(" ");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,17 @@
|
|||||||
import extractFill from './extractFill';
|
import extractFill from "./extractFill";
|
||||||
import extractStroke from './extractStroke';
|
import extractStroke from "./extractStroke";
|
||||||
import extractTransform, {props2transform} from './extractTransform';
|
import extractTransform, { props2transform } from "./extractTransform";
|
||||||
import extractClipPath from './extractClipPath';
|
import extractClipPath from "./extractClipPath";
|
||||||
import extractResponder from './extractResponder';
|
import extractResponder from "./extractResponder";
|
||||||
import extractOpacity from './extractOpacity';
|
import extractOpacity from "./extractOpacity";
|
||||||
|
|
||||||
export default function(props, ref) {
|
export default function(props, ref) {
|
||||||
const styleProperties = [];
|
const styleProperties = [];
|
||||||
|
|
||||||
const extractedProps = {
|
const extractedProps = {
|
||||||
opacity: extractOpacity(props.opacity),
|
opacity: extractOpacity(props.opacity),
|
||||||
propList: styleProperties
|
propList: styleProperties,
|
||||||
|
onLayout: props.onLayout
|
||||||
};
|
};
|
||||||
|
|
||||||
if (props.id) {
|
if (props.id) {
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import {responderProps, touchableProps} from '../props';
|
import { responderProps, touchableProps } from "../props";
|
||||||
import _ from 'lodash';
|
import _ from "lodash";
|
||||||
|
|
||||||
export default function (props, ref) {
|
export default function(props, ref) {
|
||||||
const extractedProps = {};
|
const extractedProps = {};
|
||||||
|
|
||||||
_.forEach(responderProps, (v, key) => {
|
_.forEach(responderProps, (v, key) => {
|
||||||
const value = props[key];
|
const value = props[key];
|
||||||
if (props[key]) {
|
if (props[key]) {
|
||||||
if (!extractedProps.responsible && key !== 'pointerEvents') {
|
if (!extractedProps.responsible && key !== "pointerEvents") {
|
||||||
extractedProps.responsible = true;
|
extractedProps.responsible = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -22,8 +22,10 @@ export default function (props, ref) {
|
|||||||
|
|
||||||
extractedProps.responsible = true;
|
extractedProps.responsible = true;
|
||||||
Object.assign(extractedProps, {
|
Object.assign(extractedProps, {
|
||||||
onStartShouldSetResponder: ref.touchableHandleStartShouldSetResponder,
|
onStartShouldSetResponder:
|
||||||
onResponderTerminationRequest: ref.touchableHandleResponderTerminationRequest,
|
ref.touchableHandleStartShouldSetResponder,
|
||||||
|
onResponderTerminationRequest:
|
||||||
|
ref.touchableHandleResponderTerminationRequest,
|
||||||
onResponderGrant: ref.touchableHandleResponderGrant,
|
onResponderGrant: ref.touchableHandleResponderGrant,
|
||||||
onResponderMove: ref.touchableHandleResponderMove,
|
onResponderMove: ref.touchableHandleResponderMove,
|
||||||
onResponderRelease: ref.touchableHandleResponderRelease,
|
onResponderRelease: ref.touchableHandleResponderRelease,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import extractBrush from './extractBrush';
|
import extractBrush from "./extractBrush";
|
||||||
import extractOpacity from './extractOpacity';
|
import extractOpacity from "./extractOpacity";
|
||||||
import {strokeProps} from '../props';
|
import { strokeProps } from "../props";
|
||||||
import extractLengthList from "./extractLengthList";
|
import extractLengthList from "./extractLengthList";
|
||||||
|
|
||||||
const caps = {
|
const caps = {
|
||||||
@@ -18,19 +18,16 @@ const joins = {
|
|||||||
const strokeKeys = Object.keys(strokeProps);
|
const strokeKeys = Object.keys(strokeProps);
|
||||||
|
|
||||||
export default function(props, styleProperties) {
|
export default function(props, styleProperties) {
|
||||||
strokeKeys.forEach((name) => {
|
strokeKeys.forEach(name => {
|
||||||
if (props.hasOwnProperty(name)) {
|
if (props.hasOwnProperty(name)) {
|
||||||
styleProperties.push(name);
|
styleProperties.push(name);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const {stroke} = props;
|
const { stroke } = props;
|
||||||
let {
|
let { strokeWidth, strokeDasharray } = props;
|
||||||
strokeWidth,
|
|
||||||
strokeDasharray
|
|
||||||
} = props;
|
|
||||||
|
|
||||||
if (!strokeDasharray || strokeDasharray === 'none') {
|
if (!strokeDasharray || strokeDasharray === "none") {
|
||||||
strokeDasharray = null;
|
strokeDasharray = null;
|
||||||
} else {
|
} else {
|
||||||
// <dasharray> It's a list of comma and/or white space separated <length>s
|
// <dasharray> It's a list of comma and/or white space separated <length>s
|
||||||
@@ -38,12 +35,12 @@ export default function(props, styleProperties) {
|
|||||||
// If an odd number of values is provided, then the list of values is repeated
|
// If an odd number of values is provided, then the list of values is repeated
|
||||||
// to yield an even number of values. Thus, 5,3,2 is equivalent to 5,3,2,5,3,2.
|
// to yield an even number of values. Thus, 5,3,2 is equivalent to 5,3,2,5,3,2.
|
||||||
strokeDasharray = extractLengthList(strokeDasharray);
|
strokeDasharray = extractLengthList(strokeDasharray);
|
||||||
if (strokeDasharray && (strokeDasharray.length % 2) === 1) {
|
if (strokeDasharray && strokeDasharray.length % 2 === 1) {
|
||||||
strokeDasharray = strokeDasharray.concat(strokeDasharray);
|
strokeDasharray = strokeDasharray.concat(strokeDasharray);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strokeWidth || typeof strokeWidth !== 'string') {
|
if (!strokeWidth || typeof strokeWidth !== "string") {
|
||||||
strokeWidth = `${strokeWidth || 1}`;
|
strokeWidth = `${strokeWidth || 1}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,8 +51,7 @@ export default function(props, styleProperties) {
|
|||||||
strokeLinejoin: joins[props.strokeLinejoin] || 0,
|
strokeLinejoin: joins[props.strokeLinejoin] || 0,
|
||||||
strokeDasharray: strokeDasharray,
|
strokeDasharray: strokeDasharray,
|
||||||
strokeWidth: strokeWidth,
|
strokeWidth: strokeWidth,
|
||||||
strokeDashoffset: strokeDasharray ? (+props.strokeDashoffset || 0) : null,
|
strokeDashoffset: strokeDasharray ? +props.strokeDashoffset || 0 : null,
|
||||||
strokeMiterlimit: props.strokeMiterlimit || 4,
|
strokeMiterlimit: parseFloat(props.strokeMiterlimit) || 4
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import _ from 'lodash';
|
import _ from "lodash";
|
||||||
//noinspection JSUnresolvedVariable
|
//noinspection JSUnresolvedVariable
|
||||||
import React, {Children} from 'react';
|
import React, { Children } from "react";
|
||||||
import TSpan from '../../elements/TSpan';
|
import TSpan from "../../elements/TSpan";
|
||||||
import extractLengthList from './extractLengthList';
|
import extractLengthList from "./extractLengthList";
|
||||||
|
|
||||||
const fontRegExp = /^\s*((?:(?:normal|bold|italic)\s+)*)(?:(\d+(?:\.\d+)?[ptexm%])*(?:\s*\/.*?)?\s+)?\s*"?([^"]*)/i;
|
const fontRegExp = /^\s*((?:(?:normal|bold|italic)\s+)*)(?:(\d+(?:\.\d+)?[ptexm%])*(?:\s*\/.*?)?\s+)?\s*"?([^"]*)/i;
|
||||||
const fontFamilyPrefix = /^[\s"']*/;
|
const fontFamilyPrefix = /^[\s"']*/;
|
||||||
@@ -15,9 +15,12 @@ function extractSingleFontFamily(fontFamilyString) {
|
|||||||
// SVG on the web allows for multiple font-families to be specified.
|
// SVG on the web allows for multiple font-families to be specified.
|
||||||
// For compatibility, we extract the first font-family, hoping
|
// For compatibility, we extract the first font-family, hoping
|
||||||
// we'll get a match.
|
// we'll get a match.
|
||||||
return fontFamilyString ? fontFamilyString.split(commaReg)[0]
|
return fontFamilyString
|
||||||
.replace(fontFamilyPrefix, '')
|
? fontFamilyString
|
||||||
.replace(fontFamilySuffix, '') : null;
|
.split(commaReg)[0]
|
||||||
|
.replace(fontFamilyPrefix, "")
|
||||||
|
.replace(fontFamilySuffix, "")
|
||||||
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseFontString(font) {
|
function parseFontString(font) {
|
||||||
@@ -29,16 +32,16 @@ function parseFontString(font) {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const fontFamily = extractSingleFontFamily(match[3]);
|
const fontFamily = extractSingleFontFamily(match[3]);
|
||||||
const fontSize = match[2] || '12';
|
const fontSize = match[2] || "12";
|
||||||
const isBold = /bold/.exec(match[1]);
|
const isBold = /bold/.exec(match[1]);
|
||||||
const isItalic = /italic/.exec(match[1]);
|
const isItalic = /italic/.exec(match[1]);
|
||||||
const fontWeight = isBold ? 'bold' : 'normal';
|
const fontWeight = isBold ? "bold" : "normal";
|
||||||
const fontStyle = isItalic ? 'italic' : 'normal';
|
const fontStyle = isItalic ? "italic" : "normal";
|
||||||
cachedFontObjectsFromString[font] = {
|
cachedFontObjectsFromString[font] = {
|
||||||
fontSize,
|
fontSize,
|
||||||
fontFamily,
|
fontFamily,
|
||||||
fontWeight,
|
fontWeight,
|
||||||
fontStyle,
|
fontStyle
|
||||||
};
|
};
|
||||||
return cachedFontObjectsFromString[font];
|
return cachedFontObjectsFromString[font];
|
||||||
}
|
}
|
||||||
@@ -56,35 +59,34 @@ export function extractFont(props) {
|
|||||||
wordSpacing,
|
wordSpacing,
|
||||||
kerning,
|
kerning,
|
||||||
fontVariantLigatures,
|
fontVariantLigatures,
|
||||||
fontFeatureSettings,
|
fontFeatureSettings
|
||||||
} = props;
|
|
||||||
let {
|
|
||||||
fontSize,
|
|
||||||
fontFamily,
|
|
||||||
font,
|
|
||||||
} = props;
|
} = props;
|
||||||
|
let { fontSize, fontFamily, font } = props;
|
||||||
|
|
||||||
fontFamily = extractSingleFontFamily(fontFamily);
|
fontFamily = extractSingleFontFamily(fontFamily);
|
||||||
fontSize = fontSize ? '' + fontSize : null;
|
fontSize = fontSize ? "" + fontSize : null;
|
||||||
|
|
||||||
const ownedFont = _.pickBy({
|
const ownedFont = _.pickBy(
|
||||||
fontData,
|
{
|
||||||
fontStyle,
|
fontData,
|
||||||
fontVariant,
|
fontStyle,
|
||||||
fontWeight,
|
fontVariant,
|
||||||
fontStretch,
|
fontWeight,
|
||||||
fontSize,
|
fontStretch,
|
||||||
fontFamily,
|
fontSize,
|
||||||
textAnchor,
|
fontFamily,
|
||||||
textDecoration,
|
textAnchor,
|
||||||
letterSpacing,
|
textDecoration,
|
||||||
wordSpacing,
|
letterSpacing,
|
||||||
kerning,
|
wordSpacing,
|
||||||
fontVariantLigatures,
|
kerning,
|
||||||
fontFeatureSettings,
|
fontVariantLigatures,
|
||||||
}, prop => !_.isNil(prop));
|
fontFeatureSettings
|
||||||
|
},
|
||||||
|
prop => !_.isNil(prop)
|
||||||
|
);
|
||||||
|
|
||||||
if (typeof font === 'string') {
|
if (typeof font === "string") {
|
||||||
font = parseFontString(font);
|
font = parseFontString(font);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,12 +101,9 @@ export default function(props, container) {
|
|||||||
dy,
|
dy,
|
||||||
alignmentBaseline,
|
alignmentBaseline,
|
||||||
baselineShift,
|
baselineShift,
|
||||||
verticalAlign,
|
verticalAlign
|
||||||
} = props;
|
|
||||||
let {
|
|
||||||
rotate,
|
|
||||||
children
|
|
||||||
} = props;
|
} = props;
|
||||||
|
let { rotate, children } = props;
|
||||||
|
|
||||||
const positionX = extractLengthList(x);
|
const positionX = extractLengthList(x);
|
||||||
const positionY = extractLengthList(y);
|
const positionY = extractLengthList(y);
|
||||||
@@ -113,7 +112,7 @@ export default function(props, container) {
|
|||||||
rotate = extractLengthList(rotate);
|
rotate = extractLengthList(rotate);
|
||||||
|
|
||||||
let content = null;
|
let content = null;
|
||||||
if (typeof children === 'string' || typeof children === 'number') {
|
if (typeof children === "string" || typeof children === "number") {
|
||||||
const childrenString = children.toString();
|
const childrenString = children.toString();
|
||||||
if (container) {
|
if (container) {
|
||||||
children = <TSpan>{childrenString}</TSpan>;
|
children = <TSpan>{childrenString}</TSpan>;
|
||||||
@@ -123,7 +122,7 @@ export default function(props, container) {
|
|||||||
}
|
}
|
||||||
} else if (Children.count(children) > 1 || Array.isArray(children)) {
|
} else if (Children.count(children) > 1 || Array.isArray(children)) {
|
||||||
children = Children.map(children, child => {
|
children = Children.map(children, child => {
|
||||||
if (typeof child === 'string' || typeof child === 'number') {
|
if (typeof child === "string" || typeof child === "number") {
|
||||||
return <TSpan>{child.toString()}</TSpan>;
|
return <TSpan>{child.toString()}</TSpan>;
|
||||||
} else {
|
} else {
|
||||||
return child;
|
return child;
|
||||||
@@ -144,6 +143,6 @@ export default function(props, container) {
|
|||||||
deltaY,
|
deltaY,
|
||||||
alignmentBaseline,
|
alignmentBaseline,
|
||||||
baselineShift,
|
baselineShift,
|
||||||
verticalAlign,
|
verticalAlign
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import Matrix2D from '../Matrix2D';
|
import Matrix2D from "../Matrix2D";
|
||||||
import _ from 'lodash';
|
import _ from "lodash";
|
||||||
let pooledMatrix = new Matrix2D();
|
let pooledMatrix = new Matrix2D();
|
||||||
import peg from 'pegjs';
|
import peg from "pegjs";
|
||||||
|
|
||||||
function transformToMatrix(props, transform) {
|
function transformToMatrix(props, transform) {
|
||||||
pooledMatrix.reset();
|
pooledMatrix.reset();
|
||||||
@@ -172,7 +172,7 @@ wsp
|
|||||||
|
|
||||||
function appendTransform(transform) {
|
function appendTransform(transform) {
|
||||||
if (transform) {
|
if (transform) {
|
||||||
if (typeof transform === 'string') {
|
if (typeof transform === "string") {
|
||||||
try {
|
try {
|
||||||
const [a, c, e, b, d, f] = transformParser.parse(transform);
|
const [a, c, e, b, d, f] = transformParser.parse(transform);
|
||||||
pooledMatrix.append(...[a, b, c, d, e, f]);
|
pooledMatrix.append(...[a, b, c, d, e, f]);
|
||||||
@@ -180,17 +180,17 @@ function appendTransform(transform) {
|
|||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
pooledMatrix
|
pooledMatrix.appendTransform(
|
||||||
.appendTransform(
|
transform.x + transform.originX,
|
||||||
transform.x + transform.originX,
|
transform.y + transform.originY,
|
||||||
transform.y + transform.originY,
|
transform.scaleX,
|
||||||
transform.scaleX, transform.scaleY,
|
transform.scaleY,
|
||||||
transform.rotation,
|
transform.rotation,
|
||||||
transform.skewX,
|
transform.skewX,
|
||||||
transform.skewY,
|
transform.skewY,
|
||||||
transform.originX,
|
transform.originX,
|
||||||
transform.originY
|
transform.originY
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -204,7 +204,7 @@ function universal2axis(universal, axisX, axisY, defaultValue) {
|
|||||||
if (coords.length === 2) {
|
if (coords.length === 2) {
|
||||||
x = +coords[0];
|
x = +coords[0];
|
||||||
y = +coords[1];
|
y = +coords[1];
|
||||||
} else if (coords.length === 1) {
|
} else if (coords.length === 1) {
|
||||||
x = y = +coords[0];
|
x = y = +coords[0];
|
||||||
}
|
}
|
||||||
} else if (_.isNumber(universal)) {
|
} else if (_.isNumber(universal)) {
|
||||||
@@ -225,16 +225,25 @@ function universal2axis(universal, axisX, axisY, defaultValue) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function props2transform(props) {
|
export function props2transform(props) {
|
||||||
if (props && (typeof props === 'string')) {
|
if (props && typeof props === "string") {
|
||||||
return props;
|
return props;
|
||||||
}
|
}
|
||||||
let [originX, originY] = universal2axis(props.origin, props.originX, props.originY);
|
let [originX, originY] = universal2axis(
|
||||||
let [scaleX, scaleY] = universal2axis(props.scale, props.scaleX, props.scaleY, 1);
|
props.origin,
|
||||||
|
props.originX,
|
||||||
|
props.originY
|
||||||
|
);
|
||||||
|
let [scaleX, scaleY] = universal2axis(
|
||||||
|
props.scale,
|
||||||
|
props.scaleX,
|
||||||
|
props.scaleY,
|
||||||
|
1
|
||||||
|
);
|
||||||
let [skewX, skewY] = universal2axis(props.skew, props.skewX, props.skewY);
|
let [skewX, skewY] = universal2axis(props.skew, props.skewX, props.skewY);
|
||||||
let [translateX, translateY] = universal2axis(
|
let [translateX, translateY] = universal2axis(
|
||||||
props.translate,
|
props.translate,
|
||||||
_.isNil(props.translateX) ? (props.x || 0) : props.translateX,
|
_.isNil(props.translateX) ? props.x || 0 : props.translateX,
|
||||||
_.isNil(props.translateY) ? (props.y || 0) : props.translateY
|
_.isNil(props.translateY) ? props.y || 0 : props.translateY
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -250,6 +259,9 @@ export function props2transform(props) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function (props) {
|
export default function(props) {
|
||||||
return transformToMatrix(props2transform(props), props.transform ? props2transform(props.transform) : null);
|
return transformToMatrix(
|
||||||
|
props2transform(props),
|
||||||
|
props.transform ? props2transform(props.transform) : null
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,10 +5,16 @@ const meetOrSliceTypes = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const alignEnum = [
|
const alignEnum = [
|
||||||
'xMinYMin', 'xMidYMin', 'xMaxYMin',
|
"xMinYMin",
|
||||||
'xMinYMid', 'xMidYMid', 'xMaxYMid',
|
"xMidYMin",
|
||||||
'xMinYMax', 'xMidYMax', 'xMaxYMax',
|
"xMaxYMin",
|
||||||
'none'
|
"xMinYMid",
|
||||||
|
"xMidYMid",
|
||||||
|
"xMaxYMid",
|
||||||
|
"xMinYMax",
|
||||||
|
"xMidYMax",
|
||||||
|
"xMaxYMax",
|
||||||
|
"none"
|
||||||
].reduce((prev, name) => {
|
].reduce((prev, name) => {
|
||||||
prev[name] = name;
|
prev[name] = name;
|
||||||
return prev;
|
return prev;
|
||||||
@@ -16,8 +22,8 @@ const alignEnum = [
|
|||||||
|
|
||||||
const spacesRegExp = /\s+/;
|
const spacesRegExp = /\s+/;
|
||||||
|
|
||||||
export default function (props) {
|
export default function(props) {
|
||||||
const {viewBox, preserveAspectRatio} = props;
|
const { viewBox, preserveAspectRatio } = props;
|
||||||
|
|
||||||
if (!viewBox) {
|
if (!viewBox) {
|
||||||
return null;
|
return null;
|
||||||
@@ -25,15 +31,17 @@ export default function (props) {
|
|||||||
|
|
||||||
let params = viewBox.trim().split(spacesRegExp);
|
let params = viewBox.trim().split(spacesRegExp);
|
||||||
|
|
||||||
if (params.length === 4 && params.every(param => !isNaN(+params))) {
|
if (params.length === 4 && params.every(param => !isNaN(+params))) {
|
||||||
console.warn('Invalid `viewBox` prop:' + viewBox);
|
console.warn("Invalid `viewBox` prop:" + viewBox);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
let modes = preserveAspectRatio ? preserveAspectRatio.trim().split(spacesRegExp) : [];
|
let modes = preserveAspectRatio
|
||||||
|
? preserveAspectRatio.trim().split(spacesRegExp)
|
||||||
|
: [];
|
||||||
|
|
||||||
let meetOrSlice = meetOrSliceTypes[modes[1]] || 0;
|
let meetOrSlice = meetOrSliceTypes[modes[1]] || 0;
|
||||||
let align = alignEnum[modes[0]] || 'xMidYMid';
|
let align = alignEnum[modes[0]] || "xMidYMid";
|
||||||
|
|
||||||
return {
|
return {
|
||||||
minX: +params[0],
|
minX: +params[0],
|
||||||
@@ -45,7 +53,4 @@ export default function (props) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export {
|
export { meetOrSliceTypes, alignEnum };
|
||||||
meetOrSliceTypes,
|
|
||||||
alignEnum
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
let percentReg = /^([+\-]?\d+(?:\.\d+)?(?:[eE][+\-]?\d+)?)(%?)$/;
|
let percentReg = /^([+\-]?\d+(?:\.\d+)?(?:[eE][+\-]?\d+)?)(%?)$/;
|
||||||
export default function (percent) {
|
export default function(percent) {
|
||||||
let matched = percent.match(percentReg);
|
let matched = percent.match(percentReg);
|
||||||
if (!matched) {
|
if (!matched) {
|
||||||
console.warn(`\`${percent}\` is not a valid number or percentage string.`);
|
console.warn(
|
||||||
|
`\`${percent}\` is not a valid number or percentage string.`
|
||||||
|
);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
113
lib/props.js
113
lib/props.js
@@ -1,8 +1,11 @@
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from "prop-types";
|
||||||
import {PanResponder} from 'react-native';
|
import { PanResponder } from "react-native";
|
||||||
|
|
||||||
const numberProp = PropTypes.oneOfType([PropTypes.string, PropTypes.number]);
|
const numberProp = PropTypes.oneOfType([PropTypes.string, PropTypes.number]);
|
||||||
const numberArrayProp = PropTypes.oneOfType([PropTypes.arrayOf(numberProp), numberProp]);
|
const numberArrayProp = PropTypes.oneOfType([
|
||||||
|
PropTypes.arrayOf(numberProp),
|
||||||
|
numberProp
|
||||||
|
]);
|
||||||
|
|
||||||
const touchableProps = {
|
const touchableProps = {
|
||||||
disabled: PropTypes.bool,
|
disabled: PropTypes.bool,
|
||||||
@@ -15,9 +18,13 @@ const touchableProps = {
|
|||||||
delayLongPress: PropTypes.number
|
delayLongPress: PropTypes.number
|
||||||
};
|
};
|
||||||
|
|
||||||
const responderProps = [
|
const layoutProps = {
|
||||||
|
onLayout: PropTypes.func
|
||||||
|
};
|
||||||
|
|
||||||
|
const responderProps = [
|
||||||
...Object.keys(PanResponder.create({}).panHandlers),
|
...Object.keys(PanResponder.create({}).panHandlers),
|
||||||
'pointerEvents'
|
"pointerEvents"
|
||||||
].reduce((props, name) => {
|
].reduce((props, name) => {
|
||||||
props[name] = PropTypes.func;
|
props[name] = PropTypes.func;
|
||||||
return props;
|
return props;
|
||||||
@@ -26,11 +33,11 @@ const responderProps = [
|
|||||||
const fillProps = {
|
const fillProps = {
|
||||||
fill: PropTypes.string,
|
fill: PropTypes.string,
|
||||||
fillOpacity: numberProp,
|
fillOpacity: numberProp,
|
||||||
fillRule: PropTypes.oneOf(['evenodd', 'nonzero'])
|
fillRule: PropTypes.oneOf(["evenodd", "nonzero"])
|
||||||
};
|
};
|
||||||
|
|
||||||
const clipProps = {
|
const clipProps = {
|
||||||
clipRule: PropTypes.oneOf(['evenodd', 'nonzero']),
|
clipRule: PropTypes.oneOf(["evenodd", "nonzero"]),
|
||||||
clipPath: PropTypes.string
|
clipPath: PropTypes.string
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -44,8 +51,8 @@ const strokeProps = {
|
|||||||
strokeOpacity: numberProp,
|
strokeOpacity: numberProp,
|
||||||
strokeDasharray: numberArrayProp,
|
strokeDasharray: numberArrayProp,
|
||||||
strokeDashoffset: numberProp,
|
strokeDashoffset: numberProp,
|
||||||
strokeLinecap: PropTypes.oneOf(['butt', 'square', 'round']),
|
strokeLinecap: PropTypes.oneOf(["butt", "square", "round"]),
|
||||||
strokeLinejoin: PropTypes.oneOf(['miter', 'bevel', 'round']),
|
strokeLinejoin: PropTypes.oneOf(["miter", "bevel", "round"]),
|
||||||
strokeMiterlimit: numberProp
|
strokeMiterlimit: numberProp
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -76,24 +83,51 @@ const pathProps = {
|
|||||||
...transformProps,
|
...transformProps,
|
||||||
...responderProps,
|
...responderProps,
|
||||||
...touchableProps,
|
...touchableProps,
|
||||||
|
...layoutProps,
|
||||||
...definationProps
|
...definationProps
|
||||||
};
|
};
|
||||||
|
|
||||||
// normal | italic | oblique | inherit
|
// normal | italic | oblique | inherit
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/font-style
|
// https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/font-style
|
||||||
const fontStyle = PropTypes.oneOf(['normal', 'italic', 'oblique']);
|
const fontStyle = PropTypes.oneOf(["normal", "italic", "oblique"]);
|
||||||
|
|
||||||
// normal | small-caps | inherit
|
// normal | small-caps | inherit
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/font-variant
|
// https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/font-variant
|
||||||
const fontVariant = PropTypes.oneOf(['normal', 'small-caps']);
|
const fontVariant = PropTypes.oneOf(["normal", "small-caps"]);
|
||||||
|
|
||||||
// normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900
|
// normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/font-weight
|
// https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/font-weight
|
||||||
const fontWeight = PropTypes.oneOf(['normal', 'bold', 'bolder', 'lighter', '100', '200', '300', '400', '500', '600', '700', '800', '900']);
|
const fontWeight = PropTypes.oneOf([
|
||||||
|
"normal",
|
||||||
|
"bold",
|
||||||
|
"bolder",
|
||||||
|
"lighter",
|
||||||
|
"100",
|
||||||
|
"200",
|
||||||
|
"300",
|
||||||
|
"400",
|
||||||
|
"500",
|
||||||
|
"600",
|
||||||
|
"700",
|
||||||
|
"800",
|
||||||
|
"900"
|
||||||
|
]);
|
||||||
|
|
||||||
// normal | wider | narrower | ultra-condensed | extra-condensed | condensed | semi-condensed | semi-expanded | expanded | extra-expanded | ultra-expanded | inherit
|
// normal | wider | narrower | ultra-condensed | extra-condensed | condensed | semi-condensed | semi-expanded | expanded | extra-expanded | ultra-expanded | inherit
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/font-stretch
|
// https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/font-stretch
|
||||||
const fontStretch = PropTypes.oneOf(['normal', 'wider', 'narrower', 'ultra-condensed', 'extra-condensed', 'condensed', 'semi-condensed', 'semi-expanded', 'expanded', 'extra-expanded', 'ultra-expanded']);
|
const fontStretch = PropTypes.oneOf([
|
||||||
|
"normal",
|
||||||
|
"wider",
|
||||||
|
"narrower",
|
||||||
|
"ultra-condensed",
|
||||||
|
"extra-condensed",
|
||||||
|
"condensed",
|
||||||
|
"semi-condensed",
|
||||||
|
"semi-expanded",
|
||||||
|
"expanded",
|
||||||
|
"extra-expanded",
|
||||||
|
"ultra-expanded"
|
||||||
|
]);
|
||||||
|
|
||||||
// <absolute-size> | <relative-size> | <length> | <percentage> | inherit
|
// <absolute-size> | <relative-size> | <length> | <percentage> | inherit
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/font-size
|
// https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/font-size
|
||||||
@@ -125,11 +159,17 @@ const font = PropTypes.object;
|
|||||||
|
|
||||||
// start | middle | end | inherit
|
// start | middle | end | inherit
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor
|
// https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor
|
||||||
const textAnchor = PropTypes.oneOf(['start', 'middle', 'end']);
|
const textAnchor = PropTypes.oneOf(["start", "middle", "end"]);
|
||||||
|
|
||||||
// none | underline | overline | line-through | blink | inherit
|
// none | underline | overline | line-through | blink | inherit
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-decoration
|
// https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-decoration
|
||||||
const textDecoration = PropTypes.oneOf(['none', 'underline', 'overline', 'line-through', 'blink']);
|
const textDecoration = PropTypes.oneOf([
|
||||||
|
"none",
|
||||||
|
"underline",
|
||||||
|
"overline",
|
||||||
|
"line-through",
|
||||||
|
"blink"
|
||||||
|
]);
|
||||||
|
|
||||||
// normal | <length> | inherit
|
// normal | <length> | inherit
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/letter-spacing
|
// https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/letter-spacing
|
||||||
@@ -164,7 +204,7 @@ Value: normal | none | [ <common-lig-values> || <discretionary-lig-values> || <h
|
|||||||
https://developer.mozilla.org/en/docs/Web/CSS/font-variant-ligatures
|
https://developer.mozilla.org/en/docs/Web/CSS/font-variant-ligatures
|
||||||
https://www.w3.org/TR/css-fonts-3/#font-variant-ligatures-prop
|
https://www.w3.org/TR/css-fonts-3/#font-variant-ligatures-prop
|
||||||
*/
|
*/
|
||||||
const fontVariantLigatures = PropTypes.oneOf(['normal', 'none']);
|
const fontVariantLigatures = PropTypes.oneOf(["normal", "none"]);
|
||||||
|
|
||||||
const fontProps = {
|
const fontProps = {
|
||||||
fontStyle,
|
fontStyle,
|
||||||
@@ -188,7 +228,7 @@ const fontProps = {
|
|||||||
https://svgwg.org/svg2-draft/text.html#TextElementLengthAdjustAttribute
|
https://svgwg.org/svg2-draft/text.html#TextElementLengthAdjustAttribute
|
||||||
https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/lengthAdjust
|
https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/lengthAdjust
|
||||||
*/
|
*/
|
||||||
const lengthAdjust = PropTypes.oneOf(['spacing', 'spacingAndGlyphs']);
|
const lengthAdjust = PropTypes.oneOf(["spacing", "spacingAndGlyphs"]);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Name Value Initial value Animatable
|
Name Value Initial value Animatable
|
||||||
@@ -239,7 +279,24 @@ const verticalAlign = numberProp;
|
|||||||
https://svgwg.org/svg2-draft/text.html#AlignmentBaselineProperty
|
https://svgwg.org/svg2-draft/text.html#AlignmentBaselineProperty
|
||||||
https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/alignment-baseline
|
https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/alignment-baseline
|
||||||
*/
|
*/
|
||||||
const alignmentBaseline = PropTypes.oneOf(['baseline', 'text-bottom', 'alphabetic', 'ideographic', 'middle', 'central', 'mathematical', 'text-top', 'bottom', 'center', 'top', 'text-before-edge', 'text-after-edge', 'before-edge', 'after-edge', 'hanging']);
|
const alignmentBaseline = PropTypes.oneOf([
|
||||||
|
"baseline",
|
||||||
|
"text-bottom",
|
||||||
|
"alphabetic",
|
||||||
|
"ideographic",
|
||||||
|
"middle",
|
||||||
|
"central",
|
||||||
|
"mathematical",
|
||||||
|
"text-top",
|
||||||
|
"bottom",
|
||||||
|
"center",
|
||||||
|
"top",
|
||||||
|
"text-before-edge",
|
||||||
|
"text-after-edge",
|
||||||
|
"before-edge",
|
||||||
|
"after-edge",
|
||||||
|
"hanging"
|
||||||
|
]);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
2.2.2. Alignment Shift: baseline-shift longhand
|
2.2.2. Alignment Shift: baseline-shift longhand
|
||||||
@@ -259,7 +316,11 @@ const alignmentBaseline = PropTypes.oneOf(['baseline', 'text-bottom', 'alphabeti
|
|||||||
|
|
||||||
https://www.w3.org/TR/css-inline-3/#propdef-baseline-shift
|
https://www.w3.org/TR/css-inline-3/#propdef-baseline-shift
|
||||||
*/
|
*/
|
||||||
const baselineShift = PropTypes.oneOfType([PropTypes.oneOf(['sub', 'super', 'baseline']), PropTypes.arrayOf(numberProp), numberProp]);
|
const baselineShift = PropTypes.oneOfType([
|
||||||
|
PropTypes.oneOf(["sub", "super", "baseline"]),
|
||||||
|
PropTypes.arrayOf(numberProp),
|
||||||
|
numberProp
|
||||||
|
]);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
6.12. Low-level font feature settings control: the font-feature-settings property
|
6.12. Low-level font feature settings control: the font-feature-settings property
|
||||||
@@ -370,14 +431,14 @@ const textSpecificProps = {
|
|||||||
lengthAdjust,
|
lengthAdjust,
|
||||||
textLength,
|
textLength,
|
||||||
fontData: PropTypes.object,
|
fontData: PropTypes.object,
|
||||||
fontFeatureSettings,
|
fontFeatureSettings
|
||||||
};
|
};
|
||||||
|
|
||||||
// https://svgwg.org/svg2-draft/text.html#TSpanAttributes
|
// https://svgwg.org/svg2-draft/text.html#TSpanAttributes
|
||||||
const textProps = {
|
const textProps = {
|
||||||
...textSpecificProps,
|
...textSpecificProps,
|
||||||
dx: numberArrayProp,
|
dx: numberArrayProp,
|
||||||
dy: numberArrayProp,
|
dy: numberArrayProp
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -391,7 +452,7 @@ const textProps = {
|
|||||||
yes
|
yes
|
||||||
https://svgwg.org/svg2-draft/text.html#TextPathElementSideAttribute
|
https://svgwg.org/svg2-draft/text.html#TextPathElementSideAttribute
|
||||||
*/
|
*/
|
||||||
const side = PropTypes.oneOf(['left', 'right']);
|
const side = PropTypes.oneOf(["left", "right"]);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Name
|
Name
|
||||||
@@ -419,7 +480,7 @@ const startOffset = numberProp;
|
|||||||
https://svgwg.org/svg2-draft/text.html#TextPathElementMethodAttribute
|
https://svgwg.org/svg2-draft/text.html#TextPathElementMethodAttribute
|
||||||
https://developer.mozilla.org/en/docs/Web/SVG/Element/textPath
|
https://developer.mozilla.org/en/docs/Web/SVG/Element/textPath
|
||||||
*/
|
*/
|
||||||
const method = PropTypes.oneOf(['align', 'stretch']);
|
const method = PropTypes.oneOf(["align", "stretch"]);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Name
|
Name
|
||||||
@@ -433,7 +494,7 @@ const method = PropTypes.oneOf(['align', 'stretch']);
|
|||||||
https://svgwg.org/svg2-draft/text.html#TextPathElementSpacingAttribute
|
https://svgwg.org/svg2-draft/text.html#TextPathElementSpacingAttribute
|
||||||
https://developer.mozilla.org/en/docs/Web/SVG/Element/textPath
|
https://developer.mozilla.org/en/docs/Web/SVG/Element/textPath
|
||||||
*/
|
*/
|
||||||
const spacing = PropTypes.oneOf(['auto', 'exact']);
|
const spacing = PropTypes.oneOf(["auto", "exact"]);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Name
|
Name
|
||||||
@@ -445,7 +506,7 @@ const spacing = PropTypes.oneOf(['auto', 'exact']);
|
|||||||
Animatable
|
Animatable
|
||||||
yes
|
yes
|
||||||
*/
|
*/
|
||||||
const midLine = PropTypes.oneOf(['sharp', 'smooth']);
|
const midLine = PropTypes.oneOf(["sharp", "smooth"]);
|
||||||
|
|
||||||
// https://svgwg.org/svg2-draft/text.html#TextPathAttributes
|
// https://svgwg.org/svg2-draft/text.html#TextPathAttributes
|
||||||
// https://developer.mozilla.org/en/docs/Web/SVG/Element/textPath
|
// https://developer.mozilla.org/en/docs/Web/SVG/Element/textPath
|
||||||
@@ -456,7 +517,7 @@ const textPathProps = {
|
|||||||
method,
|
method,
|
||||||
spacing,
|
spacing,
|
||||||
side,
|
side,
|
||||||
midLine,
|
midLine
|
||||||
};
|
};
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"version": "6.2.2",
|
"version": "6.5.2",
|
||||||
"name": "react-native-svg",
|
"name": "react-native-svg",
|
||||||
"description": "SVG library for react-native",
|
"description": "SVG library for react-native",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
|||||||
Reference in New Issue
Block a user