diff --git a/elements/Shape.js b/elements/Shape.js index b1945c66..d0b4c586 100644 --- a/elements/Shape.js +++ b/elements/Shape.js @@ -6,7 +6,7 @@ class Shape extends Component { super(...arguments); for (let key of Object.keys(SvgTouchableMixin)) { const method = SvgTouchableMixin[key]; - if (typeof method === 'function') { + if (typeof method === "function") { this[key] = method.bind(this); } else { this[key] = method; diff --git a/elements/Svg.js b/elements/Svg.js index 43070769..3467d1ab 100644 --- a/elements/Svg.js +++ b/elements/Svg.js @@ -89,7 +89,10 @@ class Svg extends Shape { onLayout, ...props } = this.props; - const stylesAndProps = { ...(style && style.length ? Object.assign({}, ...style) : style), ...props }; + const stylesAndProps = { + ...(style && style.length ? Object.assign({}, ...style) : style), + ...props, + }; const { color, width, height } = stylesAndProps; let dimensions; @@ -125,7 +128,7 @@ class Svg extends Shape { dimensions, ]} > - + {children} diff --git a/ios/Brushes/RNSVGPainter.m b/ios/Brushes/RNSVGPainter.m index 8ffcee44..0a10ed07 100644 --- a/ios/Brushes/RNSVGPainter.m +++ b/ios/Brushes/RNSVGPainter.m @@ -176,7 +176,7 @@ void PatternFunction(void* info, CGContextRef context) - (void)paintLinearGradient:(CGContextRef)context bounds:(CGRect)bounds { - CGGradientRef gradient = CGGradientRetain([RCTConvert RNSVGCGGradient:_colors offset:0]); + CGGradientRef gradient = CGGradientRetain([RCTConvert RNSVGCGGradient:_colors]); CGGradientDrawingOptions extendOptions = kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation; CGRect rect = [self getPaintRect:context bounds:bounds]; @@ -206,7 +206,7 @@ void PatternFunction(void* info, CGContextRef context) - (void)paintRadialGradient:(CGContextRef)context bounds:(CGRect)bounds { - CGGradientRef gradient = CGGradientRetain([RCTConvert RNSVGCGGradient:_colors offset:0]); + CGGradientRef gradient = CGGradientRetain([RCTConvert RNSVGCGGradient:_colors]); CGGradientDrawingOptions extendOptions = kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation; CGRect rect = [self getPaintRect:context bounds:bounds]; diff --git a/ios/Utils/RCTConvert+RNSVG.h b/ios/Utils/RCTConvert+RNSVG.h index b773f00c..4388e0ca 100644 --- a/ios/Utils/RCTConvert+RNSVG.h +++ b/ios/Utils/RCTConvert+RNSVG.h @@ -29,6 +29,6 @@ + (RNSVGPathParser *)RNSVGCGPath:(NSString *)d; + (CGRect)RNSVGCGRect:(id)json offset:(NSUInteger)offset; + (CGColorRef)RNSVGCGColor:(id)json offset:(NSUInteger)offset; -+ (CGGradientRef)RNSVGCGGradient:(id)json offset:(NSUInteger)offset; ++ (CGGradientRef)RNSVGCGGradient:(id)json; @end diff --git a/ios/Utils/RCTConvert+RNSVG.m b/ios/Utils/RCTConvert+RNSVG.m index eac67ad4..6fb92902 100644 --- a/ios/Utils/RCTConvert+RNSVG.m +++ b/ios/Utils/RCTConvert+RNSVG.m @@ -33,25 +33,6 @@ RCT_ENUM_CONVERTER(RNSVGUnits, (@{ @"userSpaceOnUse": @(kRNSVGUnitsUserSpaceOnUse), }), kRNSVGUnitsObjectBoundingBox, intValue) -+ (CGFloat*)RNSVGCGFloatArray:(id)json -{ - NSArray *arr = [self NSNumberArray:json]; - NSUInteger count = arr.count; - - CGFloat* array = nil; - - if (count) { - // Ideally, these arrays should already use the same memory layout. - // In that case we shouldn't need this new malloc. - array = malloc(sizeof(CGFloat) * count); - for (NSUInteger i = 0; i < count; i++) { - array[i] = (CGFloat)[arr[i] doubleValue]; - } - } - - return array; -} - + (RNSVGBrush *)RNSVGBrush:(id)json { if ([json isKindOfClass:[NSString class]]) { @@ -151,28 +132,29 @@ RCT_ENUM_CONVERTER(RNSVGUnits, (@{ return [self CGColor:[arr subarrayWithRange:(NSRange){offset, 4}]]; } -+ (CGGradientRef)RNSVGCGGradient:(id)json offset:(NSUInteger)offset ++ (CGGradientRef)RNSVGCGGradient:(id)json { - NSArray *arr = [self NSArray:json]; - if (arr.count < offset) { + NSArray *arr = [self NSNumberArray:json]; + NSUInteger count = arr.count; + if (count < 5) { RCTLogError(@"Too few elements in array (expected at least %zd): %@", (unsigned long)offset, arr); return nil; } - arr = [arr subarrayWithRange:(NSRange){offset, arr.count - offset}]; - CGFloat* colorsAndOffsets = [self RNSVGCGFloatArray:arr]; - size_t stops = arr.count / 5; + + CGFloat colorsAndOffsets[count]; + for (NSUInteger i = 0; i < count; i++) { + colorsAndOffsets[i] = (CGFloat)[arr[i] doubleValue]; + } + + size_t stops = count / 5; CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB(); - - CGGradientRef gradient = CGGradientCreateWithColorComponents( rgb, colorsAndOffsets, colorsAndOffsets + stops * 4, stops ); - CGColorSpaceRelease(rgb); - free(colorsAndOffsets); return (CGGradientRef)CFAutorelease(gradient); } diff --git a/lib/SvgTouchableMixin.js b/lib/SvgTouchableMixin.js index 760872be..9313ac07 100644 --- a/lib/SvgTouchableMixin.js +++ b/lib/SvgTouchableMixin.js @@ -11,7 +11,7 @@ export default { } else { return Touchable.Mixin.touchableHandleStartShouldSetResponder.call( this, - e + e, ); } }, @@ -22,7 +22,7 @@ export default { } else { return Touchable.Mixin.touchableHandleResponderTerminationRequest.call( this, - e + e, ); } }, @@ -49,7 +49,7 @@ export default { } else { return Touchable.Mixin.touchableHandleResponderRelease.call( this, - e + e, ); } }, @@ -60,7 +60,7 @@ export default { } else { return Touchable.Mixin.touchableHandleResponderTerminate.call( this, - e + e, ); } }, @@ -101,5 +101,5 @@ export default { touchableGetPressOutDelayMS: function() { return this.props.delayPressOut || 0; - } + }, }; diff --git a/lib/extract/extractGradient.js b/lib/extract/extractGradient.js index bad9cd28..58672e6a 100644 --- a/lib/extract/extractGradient.js +++ b/lib/extract/extractGradient.js @@ -22,66 +22,41 @@ function percentToFloat(percent) { return matched[2] ? matched[1] / 100 : +matched[1]; } -function compareAscending(value, other) { - if (value !== other) { - if (value > other) { - return 1; - } - if (value < other) { - return -1; - } - } - return 0; -} - -const offsetComparator = (object, other) => compareAscending(object.offset, other.offset); +const offsetComparator = (object, other) => object[0] - other[0]; export default function(props) { - if (!props.id) { + const { id, children, gradientTransform, transform, gradientUnits } = props; + if (!id) { return null; } const stops = []; - Children.forEach( - props.children, - ({ props: { offset, stopColor, stopOpacity } }) => { - offset = percentToFloat(offset); - if (stopColor && !isNaN(offset)) { - //noinspection JSUnresolvedFunction - stops.push({ - stop: Color(stopColor).alpha(extractOpacity(stopOpacity)), - offset, - }); - } - }, - ); + for (let child of Children.toArray(children)) { + const { props: { offset, stopColor, stopOpacity } } = child; + const offsetNumber = percentToFloat(offset); + if (stopColor && !isNaN(offsetNumber)) { + //noinspection JSUnresolvedFunction + const color = Color(stopColor).alpha(extractOpacity(stopOpacity)); + const [r, g, b, a = 1] = color.rgb().array(); + stops.push([offsetNumber, [r / 255, g / 255, b / 255, a]]); + } + } stops.sort(offsetComparator); const gradient = []; - - stops.forEach(({ stop }) => { - const [r, g, b, a = 1] = stop.rgb().array(); - gradient.push(r / 255); - gradient.push(g / 255); - gradient.push(b / 255); - gradient.push(a); - }); - - gradient.push(...stops.map(({ offset }) => offset)); - - let gradientTransform; - if (props.gradientTransform) { - gradientTransform = extractTransform(props.gradientTransform); - } else if (props.transform) { - gradientTransform = extractTransform(props.transform); - } else { - gradientTransform = extractTransform(props); + for (let stop of stops) { + gradient.push(...stop[1]); } + for (let stop of stops) { + gradient.push(stop[0]); + } + + const gt = extractTransform(gradientTransform || transform || props); return { gradient, - name: props.id, - gradientTransform, - gradientUnits: units[props.gradientUnits] || 0, + name: id, + gradientTransform: gt, + gradientUnits: units[gradientUnits] || 0, }; } diff --git a/lib/extract/extractResponder.js b/lib/extract/extractResponder.js index 780c6df9..a5bf29c5 100644 --- a/lib/extract/extractResponder.js +++ b/lib/extract/extractResponder.js @@ -2,7 +2,7 @@ import { PanResponder } from "react-native"; const responderProps = [ ...Object.keys(PanResponder.create({}).panHandlers), - "pointerEvents" + "pointerEvents", ]; const touchableProps = [ diff --git a/lib/extract/extractTransform.js b/lib/extract/extractTransform.js index 8facbf0f..523879b4 100644 --- a/lib/extract/extractTransform.js +++ b/lib/extract/extractTransform.js @@ -86,8 +86,12 @@ export function props2transform(props) { const [skewX, skewY] = universal2axis(props.skew, props.skewX, props.skewY); const [translateX, translateY] = universal2axis( props.translate, - props.translateX === undefined || props.translateX === null ? props.x || 0 : props.translateX, - props.translateY === undefined || props.translateY === null ? props.y || 0 : props.translateY, + props.translateX === undefined || props.translateX === null + ? props.x || 0 + : props.translateX, + props.translateY === undefined || props.translateY === null + ? props.y || 0 + : props.translateY, ); return { diff --git a/lib/extract/extractViewBox.js b/lib/extract/extractViewBox.js index 12b8710a..b718277a 100644 --- a/lib/extract/extractViewBox.js +++ b/lib/extract/extractViewBox.js @@ -29,9 +29,12 @@ export default function(props) { return null; } - const params = viewBox.trim().split(spacesRegExp); + const params = viewBox + .trim() + .split(spacesRegExp) + .map(Number); - if (params.length === 4 && params.some(param => isNaN(+param))) { + if (params.length === 4 && params.some(isNaN)) { console.warn("Invalid `viewBox` prop:" + viewBox); return null; } @@ -42,12 +45,13 @@ export default function(props) { const meetOrSlice = meetOrSliceTypes[modes[1]] || 0; const align = alignEnum[modes[0]] || "xMidYMid"; + const [minX, minY, vbWidth, vbHeight] = params; return { - minX: +params[0], - minY: +params[1], - vbWidth: +params[2], - vbHeight: +params[3], + minX, + minY, + vbWidth, + vbHeight, align, meetOrSlice, }; diff --git a/lib/units.js b/lib/units.js index 7222f319..035a1598 100644 --- a/lib/units.js +++ b/lib/units.js @@ -1,4 +1,4 @@ export default { objectBoundingBox: 0, - userSpaceOnUse: 1 + userSpaceOnUse: 1, }; diff --git a/lib/util.js b/lib/util.js index 586a4961..7a861d5b 100644 --- a/lib/util.js +++ b/lib/util.js @@ -1,4 +1,3 @@ - // eslint-disable-next-line eqeqeq export const notNil = a => a != null;