mirror of
https://github.com/zoriya/react-native-svg.git
synced 2025-12-20 14:05:09 +00:00
complete percentage coords refactor on ios
This commit is contained in:
@@ -12,7 +12,7 @@ import insertColorStopsIntoArray from '../lib/insertProcessor';
|
||||
|
||||
function RadialGradientGenerator(stops, fx, fy, rx, ry, cx, cy) {
|
||||
var brushData = [RADIAL_GRADIENT, fx, fy, rx, ry, cx, cy];
|
||||
insertColorStopsIntoArray(stops, brushData, 7, 0.5);
|
||||
insertColorStopsIntoArray(stops, brushData, 7);
|
||||
this._brush = brushData;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,9 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface RNSVGBrush : NSObject
|
||||
{
|
||||
NSArray *_points;
|
||||
}
|
||||
|
||||
/* @abstract */
|
||||
- (instancetype)initWithArray:(NSArray *)data NS_DESIGNATED_INITIALIZER;
|
||||
@@ -26,6 +29,8 @@
|
||||
|
||||
- (BOOL)applyStrokeColor:(CGContextRef)context;
|
||||
|
||||
- (CGFloat)getActualProp:(int)percent relative:(CGFloat)relative offset:(CGFloat)offset;
|
||||
|
||||
/**
|
||||
* paint fills the context with a brush. The context is assumed to
|
||||
* be clipped.
|
||||
|
||||
@@ -29,6 +29,30 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (CGFloat)getActualProp:(int)index relative:(CGFloat)relative offset:(CGFloat)offset
|
||||
{
|
||||
id coord = [_points objectAtIndex:index];
|
||||
|
||||
if ([coord isKindOfClass:[NSString class]]) {
|
||||
__block float matched = [coord floatValue];
|
||||
NSString *percentage = (NSString *)coord;
|
||||
NSRegularExpression *regex = [[NSRegularExpression alloc] initWithPattern:@"^(\\-?\\d+(?:\\.\\d+)?)%$" options:0 error:NULL];
|
||||
[regex enumerateMatchesInString:percentage
|
||||
options:0
|
||||
range:NSMakeRange(0, percentage.length)
|
||||
usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop)
|
||||
{
|
||||
|
||||
matched = [[percentage substringWithRange:NSMakeRange(result.range.location, result.range.length)] floatValue];
|
||||
matched = matched / 100 * relative + offset;
|
||||
}];
|
||||
|
||||
return matched;
|
||||
} else {
|
||||
return [coord floatValue];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)paint:(CGContextRef)context
|
||||
{
|
||||
// abstract
|
||||
|
||||
@@ -13,36 +13,47 @@
|
||||
|
||||
@implementation RNSVGLinearGradient
|
||||
{
|
||||
CGGradientRef _gradient;
|
||||
CGPoint _startPoint;
|
||||
CGPoint _endPoint;
|
||||
CGGradientRef _gradient;
|
||||
}
|
||||
|
||||
- (instancetype)initWithArray:(NSArray<NSNumber *> *)array
|
||||
- (instancetype)initWithArray:(NSArray *)array
|
||||
{
|
||||
if ((self = [super initWithArray:array])) {
|
||||
if (array.count < 5) {
|
||||
RCTLogError(@"-[%@ %@] expects 5 elements, received %@",
|
||||
self.class, NSStringFromSelector(_cmd), array);
|
||||
return nil;
|
||||
if ((self = [super initWithArray:array])) {
|
||||
if (array.count < 5) {
|
||||
RCTLogError(@"-[%@ %@] expects 5 elements, received %@",
|
||||
self.class, NSStringFromSelector(_cmd), array);
|
||||
return nil;
|
||||
}
|
||||
|
||||
_points = [array subarrayWithRange:NSMakeRange(1, 4)];
|
||||
_gradient = CGGradientRetain([RCTConvert CGGradient:array offset:5]);
|
||||
}
|
||||
_startPoint = [RCTConvert CGPoint:array offset:1];
|
||||
_endPoint = [RCTConvert CGPoint:array offset:3];
|
||||
_gradient = CGGradientRetain([RCTConvert CGGradient:array offset:5]);
|
||||
}
|
||||
return self;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
CGGradientRelease(_gradient);
|
||||
CGGradientRelease(_gradient);
|
||||
}
|
||||
|
||||
- (void)paint:(CGContextRef)context
|
||||
{
|
||||
CGGradientDrawingOptions extendOptions =
|
||||
CGGradientDrawingOptions extendOptions =
|
||||
kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation;
|
||||
CGContextDrawLinearGradient(context, _gradient, _startPoint, _endPoint, extendOptions);
|
||||
|
||||
CGRect box = CGContextGetClipBoundingBox(context);
|
||||
float height = CGRectGetHeight(box);
|
||||
float width = CGRectGetWidth(box);
|
||||
float midX = CGRectGetMidX(box);
|
||||
float midY = CGRectGetMidY(box);
|
||||
float offsetX = (midX - width / 2);
|
||||
float offsetY = (midY - height / 2);
|
||||
|
||||
CGFloat x1 = [self getActualProp:0 relative:width offset:offsetX];
|
||||
CGFloat y1 = [self getActualProp:1 relative:height offset:offsetY];
|
||||
CGFloat x2 = [self getActualProp:2 relative:width offset:offsetX];
|
||||
CGFloat y2 = [self getActualProp:3 relative:height offset:offsetY];
|
||||
CGContextDrawLinearGradient(context, _gradient, CGPointMake(x1, y1), CGPointMake(x2, y2), extendOptions);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -13,43 +13,65 @@
|
||||
|
||||
@implementation RNSVGRadialGradient
|
||||
{
|
||||
CGGradientRef _gradient;
|
||||
CGPoint _focusPoint;
|
||||
CGPoint _centerPoint;
|
||||
CGFloat _radius;
|
||||
CGFloat _radiusRatio;
|
||||
CGGradientRef _gradient;
|
||||
}
|
||||
|
||||
- (instancetype)initWithArray:(NSArray<NSNumber *> *)array
|
||||
- (instancetype)initWithArray:(NSArray *)array
|
||||
{
|
||||
if ((self = [super initWithArray:array])) {
|
||||
if (array.count < 7) {
|
||||
RCTLogError(@"-[%@ %@] expects 7 elements, received %@",
|
||||
self.class, NSStringFromSelector(_cmd), array);
|
||||
return nil;
|
||||
if ((self = [super initWithArray:array])) {
|
||||
if (array.count < 7) {
|
||||
RCTLogError(@"-[%@ %@] expects 7 elements, received %@",
|
||||
self.class, NSStringFromSelector(_cmd), array);
|
||||
return nil;
|
||||
}
|
||||
_points = [array subarrayWithRange:NSMakeRange(1, 6)];
|
||||
|
||||
NSMutableArray *gradient = [[NSMutableArray alloc] init];
|
||||
int count = ([array count] - 7) / 5;
|
||||
int startStops = [array count] - count;
|
||||
for (int i = 0; i < count; i++) {
|
||||
[gradient insertObject:[array objectAtIndex:(i * 4 + 7)] atIndex:(i * 4)];
|
||||
[gradient insertObject:[array objectAtIndex:(i * 4 + 8)] atIndex:(i * 4 + 1)];
|
||||
[gradient insertObject:[array objectAtIndex:(i * 4 + 9)] atIndex:(i * 4 + 2)];
|
||||
[gradient insertObject:[array objectAtIndex:(i * 4 + 10)] atIndex:(i * 4 + 3)];
|
||||
NSNumber *stop = [NSNumber numberWithFloat:[[array objectAtIndex:(startStops + (count - i - 1))] floatValue]];
|
||||
|
||||
[gradient insertObject:stop atIndex:i * 4 + 4];
|
||||
|
||||
}
|
||||
|
||||
_gradient = CGGradientRetain([RCTConvert CGGradient:gradient offset:0]);
|
||||
}
|
||||
_radius = [RCTConvert CGFloat:array[3]];
|
||||
_radiusRatio = [RCTConvert CGFloat:array[4]] / _radius;
|
||||
_focusPoint.x = [RCTConvert CGFloat:array[1]];
|
||||
_focusPoint.y = [RCTConvert CGFloat:array[2]] / _radiusRatio;
|
||||
_centerPoint.x = [RCTConvert CGFloat:array[5]];
|
||||
_centerPoint.y = [RCTConvert CGFloat:array[6]] / _radiusRatio;
|
||||
_gradient = CGGradientRetain([RCTConvert CGGradient:array offset:7]);
|
||||
}
|
||||
return self;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
CGGradientRelease(_gradient);
|
||||
CGGradientRelease(_gradient);
|
||||
}
|
||||
|
||||
- (void)paint:(CGContextRef)context
|
||||
{
|
||||
CGAffineTransform transform = CGAffineTransformMakeScale(1, _radiusRatio);
|
||||
CGContextConcatCTM(context, transform);
|
||||
CGGradientDrawingOptions extendOptions = kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation;
|
||||
CGContextDrawRadialGradient(context, _gradient, _focusPoint, 0, _centerPoint, _radius, extendOptions);
|
||||
|
||||
CGRect box = CGContextGetClipBoundingBox(context);
|
||||
float height = CGRectGetHeight(box);
|
||||
float width = CGRectGetWidth(box);
|
||||
float midX = CGRectGetMidX(box);
|
||||
float midY = CGRectGetMidY(box);
|
||||
float offsetX = (midX - width / 2);
|
||||
float offsetY = (midY - height / 2);
|
||||
CGFloat rx = [self getActualProp:2 relative:width offset:0];
|
||||
CGFloat ry = [self getActualProp:3 relative:height offset:0];
|
||||
CGFloat fx = [self getActualProp:0 relative:width offset:offsetX];
|
||||
CGFloat fy = [self getActualProp:1 relative:height offset:offsetY] / (ry / rx); // fx == fy
|
||||
CGFloat cx = [self getActualProp:4 relative:width offset:offsetX];
|
||||
CGFloat cy = [self getActualProp:5 relative:height offset:offsetY] / (ry / rx); // rx == ry
|
||||
|
||||
CGAffineTransform transform = CGAffineTransformMakeScale(1, ry / rx);
|
||||
CGContextConcatCTM(context, transform);
|
||||
CGGradientDrawingOptions extendOptions = kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation;
|
||||
|
||||
CGContextDrawRadialGradient(context, _gradient, CGPointMake(fx, fy), 0, CGPointMake(cx, cy), rx, extendOptions);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -161,6 +161,8 @@ RCT_ENUM_CONVERTER(RNSVGCGFCRule, (@{
|
||||
case 2: // radial gradient
|
||||
return [[RNSVGRadialGradient alloc] initWithArray:arr];
|
||||
case 3: // pattern
|
||||
// TODO:
|
||||
return nil;
|
||||
return [[RNSVGPattern alloc] initWithArray:arr];
|
||||
default:
|
||||
RCTLogError(@"Unknown brush type: %zd", type);
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
CGFloat cx = [self getActualProp:@"cx" relative:width];
|
||||
CGFloat cy = [self getActualProp:@"cy" relative:height];
|
||||
CGFloat r = [self getActualProp:@"r" relative:height];
|
||||
CGPathAddArc(path, nil, cx, cy, r, 0, 2*M_PI, YES);
|
||||
CGPathAddArc(path, nil, cx, cy, r, -M_PI, M_PI, YES);
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
|
||||
@@ -11,7 +11,6 @@ function insertColorIntoArray(color, targetArray, atIndex) {
|
||||
|
||||
function insertColorsIntoArray(stops, targetArray, atIndex) {
|
||||
let i = 0;
|
||||
|
||||
if ('length' in stops) {
|
||||
while (i < stops.length) {
|
||||
insertColorIntoArray(stops[i], targetArray, atIndex + i * 4);
|
||||
@@ -28,27 +27,28 @@ function insertColorsIntoArray(stops, targetArray, atIndex) {
|
||||
return atIndex + i * 4;
|
||||
}
|
||||
|
||||
function insertColorStopsIntoArray(stops, targetArray, atIndex, multi = 1) {
|
||||
let lastIndex = insertColorsIntoArray(stops, targetArray, atIndex, false);
|
||||
insertOffsetsIntoArray(stops, targetArray, lastIndex, multi, false);
|
||||
function insertColorStopsIntoArray(stops, targetArray, atIndex) {
|
||||
let lastIndex = insertColorsIntoArray(stops, targetArray, atIndex);
|
||||
insertOffsetsIntoArray(stops, targetArray, lastIndex);
|
||||
}
|
||||
|
||||
function insertOffsetsIntoArray(stops, targetArray, atIndex, multi) {
|
||||
function insertOffsetsIntoArray(stops, targetArray, atIndex) {
|
||||
let offsetNumber;
|
||||
let i = 0;
|
||||
let arr = [];
|
||||
if ('length' in stops) {
|
||||
while (i < stops.length) {
|
||||
offsetNumber = i / (stops.length - 1) * multi;
|
||||
offsetNumber = i / (stops.length - 1);
|
||||
targetArray[atIndex + i] = offsetNumber;
|
||||
i++;
|
||||
}
|
||||
} else {
|
||||
_.forEach(stops, (stop, offsetString) => {
|
||||
offsetNumber = (+offsetString) * multi;
|
||||
offsetNumber = (+offsetString);
|
||||
arr.push(offsetNumber);
|
||||
i++;
|
||||
});
|
||||
|
||||
arr.sort();
|
||||
targetArray.splice(atIndex, 0, ...arr);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user