mirror of
https://github.com/zoriya/react-native-svg.git
synced 2026-05-29 21:25:00 +00:00
fix: PlatformColor crashes on iOS and Android (#1703)
Follow-up PR to https://github.com/react-native-svg/react-native-svg/pull/1561 fixing the problems mentioned there. Also fixing the wrong releasing introduced in https://github.com/react-native-svg/react-native-svg/commit/027b8c16aa99267467b5aef0fcfd1aa8c2c8582a
This commit is contained in:
@@ -1,30 +1,49 @@
|
||||
import React from 'react';
|
||||
import { PlatformColor, Platform, Button } from 'react-native';
|
||||
import {
|
||||
Svg,
|
||||
Circle,
|
||||
Rect,
|
||||
Text,
|
||||
TSpan
|
||||
} from 'react-native-svg';
|
||||
|
||||
const color = PlatformColor(Platform.select({
|
||||
ios: 'label',
|
||||
android: '@android:color/primary_text_light',
|
||||
default: 'black',
|
||||
}))
|
||||
|
||||
export default () => {
|
||||
const [test, setTest] = React.useState(50);
|
||||
|
||||
return (
|
||||
<Svg height="100" width="100">
|
||||
<Circle
|
||||
cx="50"
|
||||
cy="50"
|
||||
r="45"
|
||||
stroke="blue"
|
||||
strokeWidth="2.5"
|
||||
fill="green"
|
||||
/>
|
||||
<Rect
|
||||
x="15"
|
||||
y="15"
|
||||
width="70"
|
||||
height="70"
|
||||
stroke="red"
|
||||
strokeWidth="2"
|
||||
fill="yellow"
|
||||
/>
|
||||
</Svg>
|
||||
<>
|
||||
<Svg height="100" width="100" color={color}>
|
||||
<Circle
|
||||
cx="50"
|
||||
cy="50"
|
||||
r={test}
|
||||
strokeWidth="2.5"
|
||||
fill={color}
|
||||
/>
|
||||
<Rect
|
||||
x="15"
|
||||
y="15"
|
||||
width="70"
|
||||
height="70"
|
||||
stroke="currentColor"
|
||||
strokeWidth="5"
|
||||
/>
|
||||
</Svg>
|
||||
<Svg height="300" width="300" fill="red">
|
||||
<Text x={0} y={0} fontSize={20}>
|
||||
<TSpan dx={test} inlineSize={"100%"} fill="currentColor">
|
||||
Testing word-wrap... Testing word-wrap... Testing word-wrap... Testing word-wrap...
|
||||
</TSpan>
|
||||
</Text>
|
||||
</Svg>
|
||||
<Button title="Click me" onPress={()=> setTest(test + 1)}/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -23,6 +23,7 @@ import android.view.ViewParent;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.facebook.react.bridge.ColorPropConverter;
|
||||
import com.facebook.react.bridge.Dynamic;
|
||||
import com.facebook.react.bridge.ReactContext;
|
||||
import com.facebook.react.uimanager.DisplayMetricsHolder;
|
||||
@@ -173,12 +174,17 @@ public class SvgView extends ReactViewGroup implements ReactCompoundView, ReactC
|
||||
}
|
||||
|
||||
@ReactProp(name = "tintColor")
|
||||
public void setTintColor(@Nullable Integer tintColor) {
|
||||
if (tintColor == null) {
|
||||
mTintColor = 0;
|
||||
} else {
|
||||
mTintColor = tintColor;
|
||||
}
|
||||
public void setTintColor(@Nullable Dynamic tintColor) {
|
||||
switch (tintColor.getType()) {
|
||||
case Map:
|
||||
mTintColor = ColorPropConverter.getColor(tintColor.asMap(), getContext());
|
||||
break;
|
||||
case Number:
|
||||
mTintColor = tintColor.asInt();
|
||||
break;
|
||||
default:
|
||||
mTintColor = 0;
|
||||
}
|
||||
invalidate();
|
||||
clearChildCache();
|
||||
}
|
||||
|
||||
@@ -78,12 +78,12 @@ class SvgViewManager extends ReactViewManager {
|
||||
}
|
||||
|
||||
@ReactProp(name = "tintColor")
|
||||
public void setTintColor(SvgView node, @Nullable Integer tintColor) {
|
||||
public void setTintColor(SvgView node, @Nullable Dynamic tintColor) {
|
||||
node.setTintColor(tintColor);
|
||||
}
|
||||
|
||||
@ReactProp(name = "color")
|
||||
public void setColor(SvgView node, @Nullable Integer color) {
|
||||
public void setColor(SvgView node, @Nullable Dynamic color) {
|
||||
node.setTintColor(color);
|
||||
}
|
||||
|
||||
|
||||
@@ -7,19 +7,20 @@
|
||||
*/
|
||||
|
||||
#import "RNSVGSolidColorBrush.h"
|
||||
#import "RNSVGUIKit.h"
|
||||
|
||||
#import "RCTConvert+RNSVG.h"
|
||||
#import <React/RCTLog.h>
|
||||
|
||||
@implementation RNSVGSolidColorBrush
|
||||
{
|
||||
UIColor *_color;
|
||||
RNSVGColor *_color;
|
||||
}
|
||||
|
||||
- (instancetype)initWithArray:(NSArray<RNSVGLength *> *)array
|
||||
{
|
||||
if ((self = [super initWithArray:array])) {
|
||||
_color = [RCTConvert RNSVGUIColor:array offset:1];
|
||||
_color = [RCTConvert RNSVGColor:array offset:1];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@@ -27,7 +28,7 @@
|
||||
- (instancetype)initWithNumber:(NSNumber *)number
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
_color = [RCTConvert UIColor:number];
|
||||
_color = [RCTConvert RNSVGColor:number];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@@ -41,7 +42,6 @@
|
||||
{
|
||||
CGColorRef baseColor = _color.CGColor;
|
||||
CGColorRef color = CGColorCreateCopyWithAlpha(baseColor, opacity * CGColorGetAlpha(baseColor));
|
||||
CGColorRelease(baseColor);
|
||||
return color;
|
||||
}
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
{
|
||||
CGColorRef color = [self getColorWithOpacity:opacity];
|
||||
CGContextSetFillColorWithColor(context, color);
|
||||
CGColorRelease(color);
|
||||
return YES;
|
||||
}
|
||||
|
||||
@@ -56,6 +57,7 @@
|
||||
{
|
||||
CGColorRef color = [self getColorWithOpacity:opacity];
|
||||
CGContextSetStrokeColorWithColor(context, color);
|
||||
CGColorRelease(color);
|
||||
return YES;
|
||||
}
|
||||
|
||||
|
||||
+4
-11
@@ -65,31 +65,24 @@ static CGFloat RNSVGTSpan_radToDeg = 180 / (CGFloat)M_PI;
|
||||
if (self.content) {
|
||||
RNSVGGlyphContext* gc = [self.textRoot getGlyphContext];
|
||||
if (self.inlineSize != nil && self.inlineSize.value != 0) {
|
||||
CGColorRef color;
|
||||
if (self.fill) {
|
||||
if (self.fill.class == RNSVGBrush.class) {
|
||||
color = [self.tintColor CGColor];
|
||||
CGColorRef color = [self.tintColor CGColor];
|
||||
[self drawWrappedText:context gc:gc rect:rect color:color];
|
||||
} else {
|
||||
color = [self.fill getColorWithOpacity:self.fillOpacity];
|
||||
CGColorRef color = [self.fill getColorWithOpacity:self.fillOpacity];
|
||||
[self drawWrappedText:context gc:gc rect:rect color:color];
|
||||
}
|
||||
if (color) {
|
||||
CGColorRelease(color);
|
||||
color = nil;
|
||||
}
|
||||
}
|
||||
if (self.stroke) {
|
||||
if (self.stroke.class == RNSVGBrush.class) {
|
||||
color = [self.tintColor CGColor];
|
||||
CGColorRef color = [self.tintColor CGColor];
|
||||
[self drawWrappedText:context gc:gc rect:rect color:color];
|
||||
} else {
|
||||
color = [self.stroke getColorWithOpacity:self.strokeOpacity];
|
||||
CGColorRef color = [self.stroke getColorWithOpacity:self.strokeOpacity];
|
||||
[self drawWrappedText:context gc:gc rect:rect color:color];
|
||||
}
|
||||
if (color) {
|
||||
CGColorRelease(color);
|
||||
color = nil;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
+ (RNSVGBrush *)RNSVGBrush:(id)json;
|
||||
+ (RNSVGPathParser *)RNSVGCGPath:(NSString *)d;
|
||||
+ (CGRect)RNSVGCGRect:(id)json offset:(NSUInteger)offset;
|
||||
+ (UIColor *)RNSVGUIColor:(id)json offset:(NSUInteger)offset;
|
||||
+ (RNSVGColor *)RNSVGColor:(id)json offset:(NSUInteger)offset;
|
||||
+ (CGGradientRef)RNSVGCGGradient:(id)json;
|
||||
|
||||
@end
|
||||
|
||||
@@ -130,17 +130,17 @@ RCT_ENUM_CONVERTER(RNSVGUnits, (@{
|
||||
};
|
||||
}
|
||||
|
||||
+ (UIColor *)RNSVGUIColor:(id)json offset:(NSUInteger)offset
|
||||
+ (RNSVGColor *)RNSVGColor:(id)json offset:(NSUInteger)offset
|
||||
{
|
||||
NSArray *arr = [self NSArray:json];
|
||||
if (arr.count == offset + 1) {
|
||||
return [self UIColor:[arr objectAtIndex:offset]];
|
||||
return [self RNSVGColor:[arr objectAtIndex:offset]];
|
||||
}
|
||||
if (arr.count < offset + 4) {
|
||||
RCTLogError(@"Too few elements in array (expected at least %zd): %@", (ssize_t)(4 + offset), arr);
|
||||
return nil;
|
||||
}
|
||||
return [self UIColor:[arr subarrayWithRange:(NSRange){offset, 4}]];
|
||||
return [self RNSVGColor:[arr subarrayWithRange:(NSRange){offset, 4}]];
|
||||
}
|
||||
|
||||
+ (CGGradientRef)RNSVGCGGradient:(id)json
|
||||
|
||||
+31
-27
@@ -1,12 +1,16 @@
|
||||
/**
|
||||
* Flowtype definitions for index
|
||||
* Generated by Flowgen from a Typescript Definition
|
||||
* Flowgen v1.14.1
|
||||
* Flowgen v1.17.0
|
||||
*/
|
||||
|
||||
import * as React from "react";
|
||||
import * as ReactNative from "react-native";
|
||||
import { GestureResponderEvent, TransformsStyle } from "react-native";
|
||||
import {
|
||||
GestureResponderEvent,
|
||||
TransformsStyle,
|
||||
OpaqueColorValue,
|
||||
} from "react-native";
|
||||
export type NumberProp = string | number;
|
||||
export type NumberArray = NumberProp[] | NumberProp;
|
||||
export type FillRule = "evenodd" | "nonzero";
|
||||
@@ -93,7 +97,7 @@ export type ResponderProps = {
|
||||
} & ReactNative.GestureResponderHandlers;
|
||||
export type rgbaArray = $ReadOnlyArray<number>;
|
||||
export type int32ARGBColor = number;
|
||||
export type Color = int32ARGBColor | rgbaArray | string;
|
||||
export type Color = int32ARGBColor | rgbaArray | OpaqueColorValue | string;
|
||||
export interface FillProps {
|
||||
fill?: Color;
|
||||
fillOpacity?: NumberProp;
|
||||
@@ -205,14 +209,14 @@ export type CircleProps = {
|
||||
...
|
||||
} & CommonPathProps;
|
||||
declare export var Circle: React.ComponentClass<CircleProps>;
|
||||
export type Circle = React.ComponentClass<CircleProps>;
|
||||
export type CircleType = React.ComponentClass<CircleProps>;
|
||||
export interface ClipPathProps {
|
||||
id?: string;
|
||||
}
|
||||
declare export var ClipPath: React.ComponentClass<ClipPathProps>;
|
||||
export type ClipPath = React.ComponentClass<ClipPathProps>;
|
||||
export type ClipPathType = React.ComponentClass<ClipPathProps>;
|
||||
declare export var Defs: React.ComponentClass<{ ... }>;
|
||||
export type Defs = React.ComponentClass<{ ... }>;
|
||||
export type DefsType = React.ComponentClass<{ ... }>;
|
||||
export type EllipseProps = {
|
||||
cx?: NumberProp,
|
||||
cy?: NumberProp,
|
||||
@@ -222,13 +226,13 @@ export type EllipseProps = {
|
||||
...
|
||||
} & CommonPathProps;
|
||||
declare export var Ellipse: React.ComponentClass<EllipseProps>;
|
||||
export type Ellipse = React.ComponentClass<EllipseProps>;
|
||||
export type EllipseType = React.ComponentClass<EllipseProps>;
|
||||
export type GProps = {
|
||||
opacity?: NumberProp,
|
||||
...
|
||||
} & CommonPathProps;
|
||||
declare export var G: React.ComponentClass<GProps>;
|
||||
export type G = React.ComponentClass<GProps>;
|
||||
export type GType = React.ComponentClass<GProps>;
|
||||
export interface ForeignObjectProps {
|
||||
x?: NumberProp;
|
||||
y?: NumberProp;
|
||||
@@ -236,7 +240,7 @@ export interface ForeignObjectProps {
|
||||
height?: NumberProp;
|
||||
}
|
||||
declare export var ForeignObject: React.ComponentClass<ForeignObjectProps>;
|
||||
export type ForeignObject = React.ComponentClass<ForeignObjectProps>;
|
||||
export type ForeignObjectType = React.ComponentClass<ForeignObjectProps>;
|
||||
export type ImageProps = {
|
||||
x?: NumberProp,
|
||||
y?: NumberProp,
|
||||
@@ -254,7 +258,7 @@ export type ImageProps = {
|
||||
ClipProps &
|
||||
TouchableProps;
|
||||
declare export var Image: React.ComponentClass<ImageProps>;
|
||||
export type Image = React.ComponentClass<ImageProps>;
|
||||
export type ImageType = React.ComponentClass<ImageProps>;
|
||||
export type LineProps = {
|
||||
opacity?: NumberProp,
|
||||
x1?: NumberProp,
|
||||
@@ -264,7 +268,7 @@ export type LineProps = {
|
||||
...
|
||||
} & CommonPathProps;
|
||||
declare export var Line: React.ComponentClass<LineProps>;
|
||||
export type Line = React.ComponentClass<LineProps>;
|
||||
export type LineType = React.ComponentClass<LineProps>;
|
||||
export interface LinearGradientProps {
|
||||
x1?: NumberProp;
|
||||
x2?: NumberProp;
|
||||
@@ -275,14 +279,14 @@ export interface LinearGradientProps {
|
||||
id?: string;
|
||||
}
|
||||
declare export var LinearGradient: React.ComponentClass<LinearGradientProps>;
|
||||
export type LinearGradient = React.ComponentClass<LinearGradientProps>;
|
||||
export type LinearGradientType = React.ComponentClass<LinearGradientProps>;
|
||||
export type PathProps = {
|
||||
d?: string,
|
||||
opacity?: NumberProp,
|
||||
...
|
||||
} & CommonPathProps;
|
||||
declare export var Path: React.ComponentClass<PathProps>;
|
||||
export type Path = React.ComponentClass<PathProps>;
|
||||
export type PathType = React.ComponentClass<PathProps>;
|
||||
export interface PatternProps {
|
||||
id?: string;
|
||||
x?: NumberProp;
|
||||
@@ -296,21 +300,21 @@ export interface PatternProps {
|
||||
preserveAspectRatio?: string;
|
||||
}
|
||||
declare export var Pattern: React.ComponentClass<PatternProps>;
|
||||
export type Pattern = React.ComponentClass<PatternProps>;
|
||||
export type PatternType = React.ComponentClass<PatternProps>;
|
||||
export type PolygonProps = {
|
||||
opacity?: NumberProp,
|
||||
points?: string | $ReadOnlyArray<NumberProp>,
|
||||
...
|
||||
} & CommonPathProps;
|
||||
declare export var Polygon: React.ComponentClass<PolygonProps>;
|
||||
export type Polygon = React.ComponentClass<PolygonProps>;
|
||||
export type PolygonType = React.ComponentClass<PolygonProps>;
|
||||
export type PolylineProps = {
|
||||
opacity?: NumberProp,
|
||||
points?: string | $ReadOnlyArray<NumberProp>,
|
||||
...
|
||||
} & CommonPathProps;
|
||||
declare export var Polyline: React.ComponentClass<PolylineProps>;
|
||||
export type Polyline = React.ComponentClass<PolylineProps>;
|
||||
export type PolylineType = React.ComponentClass<PolylineProps>;
|
||||
export interface RadialGradientProps {
|
||||
fx?: NumberProp;
|
||||
fy?: NumberProp;
|
||||
@@ -324,7 +328,7 @@ export interface RadialGradientProps {
|
||||
id?: string;
|
||||
}
|
||||
declare export var RadialGradient: React.ComponentClass<RadialGradientProps>;
|
||||
export type RadialGradient = React.ComponentClass<RadialGradientProps>;
|
||||
export type RadialGradientType = React.ComponentClass<RadialGradientProps>;
|
||||
export type RectProps = {
|
||||
x?: NumberProp,
|
||||
y?: NumberProp,
|
||||
@@ -336,14 +340,14 @@ export type RectProps = {
|
||||
...
|
||||
} & CommonPathProps;
|
||||
declare export var Rect: React.ComponentClass<RectProps>;
|
||||
export type Rect = React.ComponentClass<RectProps>;
|
||||
export type RectType = React.ComponentClass<RectProps>;
|
||||
export interface StopProps {
|
||||
stopColor?: Color;
|
||||
stopOpacity?: NumberProp;
|
||||
offset?: NumberProp;
|
||||
}
|
||||
declare export var Stop: React.ComponentClass<StopProps>;
|
||||
export type Stop = React.ComponentClass<StopProps>;
|
||||
export type StopType = React.ComponentClass<StopProps>;
|
||||
export type SvgProps = {
|
||||
width?: NumberProp,
|
||||
height?: NumberProp,
|
||||
@@ -355,7 +359,7 @@ export type SvgProps = {
|
||||
} & GProps &
|
||||
ReactNative.ViewProperties;
|
||||
declare export var Svg: React.ComponentClass<SvgProps>;
|
||||
export type Svg = React.ComponentClass<SvgProps>;
|
||||
export type SvgType = React.ComponentClass<SvgProps>;
|
||||
declare export default typeof Svg;
|
||||
export interface SymbolProps {
|
||||
id?: string;
|
||||
@@ -364,7 +368,7 @@ export interface SymbolProps {
|
||||
opacity?: NumberProp;
|
||||
}
|
||||
declare export var Symbol: React.ComponentClass<SymbolProps>;
|
||||
export type Symbol = React.ComponentClass<SymbolProps>;
|
||||
export type SymbolType = React.ComponentClass<SymbolProps>;
|
||||
export type TSpanProps = {
|
||||
x?: NumberArray,
|
||||
y?: NumberArray,
|
||||
@@ -376,7 +380,7 @@ export type TSpanProps = {
|
||||
} & CommonPathProps &
|
||||
FontProps;
|
||||
declare export var TSpan: React.ComponentClass<TSpanProps>;
|
||||
export type TSpan = React.ComponentClass<TSpanProps>;
|
||||
export type TSpanType = React.ComponentClass<TSpanProps>;
|
||||
export type TextSpecificProps = {
|
||||
alignmentBaseline?: AlignmentBaseline,
|
||||
baselineShift?: BaselineShift,
|
||||
@@ -402,7 +406,7 @@ export type TextProps = {
|
||||
...
|
||||
} & TextSpecificProps;
|
||||
declare export var Text: React.ComponentClass<TextProps>;
|
||||
export type Text = React.ComponentClass<TextProps>;
|
||||
export type TextType = React.ComponentClass<TextProps>;
|
||||
export type TextPathProps = {
|
||||
xlinkHref?: string,
|
||||
href?: string,
|
||||
@@ -413,7 +417,7 @@ export type TextPathProps = {
|
||||
...
|
||||
} & TextSpecificProps;
|
||||
declare export var TextPath: React.ComponentClass<TextPathProps>;
|
||||
export type TextPath = React.ComponentClass<TextPathProps>;
|
||||
export type TextPathType = React.ComponentClass<TextPathProps>;
|
||||
export type UseProps = {
|
||||
xlinkHref?: string,
|
||||
href?: string,
|
||||
@@ -425,7 +429,7 @@ export type UseProps = {
|
||||
...
|
||||
} & CommonPathProps;
|
||||
declare export var Use: React.ComponentClass<UseProps>;
|
||||
export type Use = React.ComponentClass<UseProps>;
|
||||
export type UseType = React.ComponentClass<UseProps>;
|
||||
declare export var EMaskUnits: {|
|
||||
+USER_SPACE_ON_USE: "userSpaceOnUse", // "userSpaceOnUse"
|
||||
+OBJECT_BOUNDING_BOX: "objectBoundingBox", // "objectBoundingBox"
|
||||
@@ -445,7 +449,7 @@ export type MaskProps = {
|
||||
...
|
||||
} & CommonPathProps;
|
||||
declare export var Mask: React.ComponentClass<MaskProps>;
|
||||
export type Mask = React.ComponentClass<MaskProps>;
|
||||
export type MaskType = React.ComponentClass<MaskProps>;
|
||||
declare export var MarkerUnits: {|
|
||||
+STROKE_WIDTH: "strokeWidth", // "strokeWidth"
|
||||
+USER_SPACE_ON_USE: "userSpaceOnUse", // "userSpaceOnUse"
|
||||
@@ -467,7 +471,7 @@ export interface MarkerProps {
|
||||
orient?: $Values<typeof Orient> | NumberProp;
|
||||
}
|
||||
declare export var Marker: React.ComponentClass<MarkerProps>;
|
||||
export type Marker = React.ComponentClass<MarkerProps>;
|
||||
export type MarkerType = React.ComponentClass<MarkerProps>;
|
||||
export type Styles = {
|
||||
[property: string]: string,
|
||||
...
|
||||
|
||||
@@ -40,14 +40,16 @@ export default function extractBrush(color?: Color) {
|
||||
return int32ARGBColor;
|
||||
}
|
||||
|
||||
// iOS PlatformColor
|
||||
if ('semantic' in color) {
|
||||
return [0, color];
|
||||
}
|
||||
if (typeof color === 'object' && color !== null) {
|
||||
// iOS PlatformColor
|
||||
if ('semantic' in color) {
|
||||
return [0, color];
|
||||
}
|
||||
|
||||
// Android PlatformColor
|
||||
if ('resource_paths' in color) {
|
||||
return [0, color];
|
||||
// Android PlatformColor
|
||||
if ('resource_paths' in color) {
|
||||
return [0, color];
|
||||
}
|
||||
}
|
||||
|
||||
console.warn(`"${color}" is not a valid color or brush`);
|
||||
|
||||
Reference in New Issue
Block a user