fix: units in linear and radial gradients

fixes #1110
fixes #1118
This commit is contained in:
Mikael Sand
2019-09-28 00:45:07 +03:00
parent e91b40677a
commit 70c54e61a4
7 changed files with 33 additions and 139 deletions

View File

@@ -171,10 +171,10 @@ class Brush {
}
if (mType == BrushType.LINEAR_GRADIENT) {
double x1 = PropHelper.fromRelative(mPoints[0], width, offsetX, scale, textSize);
double y1 = PropHelper.fromRelative(mPoints[1], height, offsetY, scale, textSize);
double x2 = PropHelper.fromRelative(mPoints[2], width, offsetX, scale, textSize);
double y2 = PropHelper.fromRelative(mPoints[3], height, offsetY, scale, textSize);
double x1 = getVal(mPoints[0], width, scale, textSize) + offsetX;
double y1 = getVal(mPoints[1], height, scale, textSize) + offsetY;
double x2 = getVal(mPoints[2], width, scale, textSize) + offsetX;
double y2 = getVal(mPoints[3], height, scale, textSize) + offsetY;
Shader linearGradient = new LinearGradient(
(float) x1,
@@ -193,13 +193,18 @@ class Brush {
paint.setShader(linearGradient);
} else if (mType == BrushType.RADIAL_GRADIENT) {
double rx = PropHelper.fromRelative(mPoints[2], width, 0f, scale, textSize);
double ry = PropHelper.fromRelative(mPoints[3], height, 0f, scale, textSize);
double cx = PropHelper.fromRelative(mPoints[4], width, offsetX, scale, textSize);
double cy = PropHelper.fromRelative(mPoints[5], height, offsetY, scale, textSize) / (ry / rx);
double rx = getVal(mPoints[2], width, scale, textSize);
double ry = getVal(mPoints[3], height, scale, textSize);
double ratio = ry / rx;
double cx = getVal(mPoints[4], width, scale, textSize) + offsetX;
double cy = getVal(mPoints[5], height, scale, textSize) + offsetY / ratio;
// TODO: support focus point.
//double fx = PropHelper.fromRelative(mPoints[0], width, offsetX, scale);
//double fy = PropHelper.fromRelative(mPoints[1], height, offsetY, scale) / (ry / rx);
Shader radialGradient = new RadialGradient(
(float) cx,
(float) cy,
@@ -210,7 +215,7 @@ class Brush {
);
Matrix radialMatrix = new Matrix();
radialMatrix.preScale(1f, (float) (ry / rx));
radialMatrix.preScale(1f, (float) ratio);
if (mMatrix != null) {
radialMatrix.preConcat(mMatrix);

View File

@@ -8,7 +8,6 @@
#import <CoreGraphics/CoreGraphics.h>
#import <Foundation/Foundation.h>
#import "RNSVGPercentageConverter.h"
#import "RNSVGPainter.h"
@interface RNSVGBrush : NSObject

View File

@@ -8,7 +8,6 @@
#import "RNSVGPainter.h"
#import "RNSVGPattern.h"
#import "RNSVGPercentageConverter.h"
#import "RNSVGViewBox.h"
@implementation RNSVGPainter
@@ -188,7 +187,6 @@ void PatternFunction(void* info, CGContextRef context)
- (void)paintLinearGradient:(CGContextRef)context bounds:(CGRect)bounds
{
CGGradientRef gradient = CGGradientRetain([RCTConvert RNSVGCGGradient:_colors]);
CGGradientDrawingOptions extendOptions = kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation;
@@ -198,19 +196,10 @@ void PatternFunction(void* info, CGContextRef context)
CGFloat offsetX = CGRectGetMinX(rect);
CGFloat offsetY = CGRectGetMinY(rect);
CGFloat x1 = [RNSVGPercentageConverter lengthToFloat:[_points objectAtIndex:0]
relative:width
offset:offsetX];
CGFloat y1 = [RNSVGPercentageConverter lengthToFloat:[_points objectAtIndex:1]
relative:height
offset:offsetY];
CGFloat x2 = [RNSVGPercentageConverter lengthToFloat:[_points objectAtIndex:2]
relative:width
offset:offsetX];
CGFloat y2 = [RNSVGPercentageConverter lengthToFloat:[_points objectAtIndex:3]
relative:height
offset:offsetY];
CGFloat x1 = [self getVal:[_points objectAtIndex:0] relative:width] + offsetX;
CGFloat y1 = [self getVal:[_points objectAtIndex:1] relative:height] + offsetY;
CGFloat x2 = [self getVal:[_points objectAtIndex:2] relative:width] + offsetX;
CGFloat y2 = [self getVal:[_points objectAtIndex:3] relative:height] + offsetY;
CGContextConcatCTM(context, _transform);
CGContextDrawLinearGradient(context, gradient, CGPointMake(x1, y1), CGPointMake(x2, y2), extendOptions);
@@ -223,31 +212,25 @@ void PatternFunction(void* info, CGContextRef context)
CGGradientDrawingOptions extendOptions = kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation;
CGRect rect = [self getPaintRect:context bounds:bounds];
CGFloat height = CGRectGetHeight(rect);
CGFloat width = CGRectGetWidth(rect);
CGFloat height = CGRectGetHeight(rect);
CGFloat offsetX = CGRectGetMinX(rect);
CGFloat offsetY = CGRectGetMinY(rect);
CGFloat rx = [RNSVGPercentageConverter lengthToFloat:[_points objectAtIndex:2]
relative:width
offset:0];
CGFloat ry = [RNSVGPercentageConverter lengthToFloat:[_points objectAtIndex:3]
relative:height
offset:0];
CGFloat fx = [RNSVGPercentageConverter lengthToFloat:[_points objectAtIndex:0]
relative:width
offset:offsetX];
CGFloat fy = [RNSVGPercentageConverter lengthToFloat:[_points objectAtIndex:1]
relative:height
offset:offsetY] / (ry / rx);
CGFloat cx = [RNSVGPercentageConverter lengthToFloat:[_points objectAtIndex:4]
relative:width
offset:offsetX];
CGFloat cy = [RNSVGPercentageConverter lengthToFloat:[_points objectAtIndex:5]
relative:height
offset:offsetY] / (ry / rx);
CGFloat rx = [self getVal:[_points objectAtIndex:2] relative:width];
CGFloat ry = [self getVal:[_points objectAtIndex:3] relative:height];
CGAffineTransform transform = CGAffineTransformMakeScale(1, ry / rx);
double ratio = ry / rx;
CGFloat fx = [self getVal:[_points objectAtIndex:0] relative:width] + offsetX;
CGFloat fy = ([self getVal:[_points objectAtIndex:1] relative:height] + offsetY) / ratio;
CGFloat cx = [self getVal:[_points objectAtIndex:4] relative:width] + offsetX;
CGFloat cy = ([self getVal:[_points objectAtIndex:5] relative:height] + offsetY) / ratio;
CGAffineTransform transform = CGAffineTransformMakeScale(1, ratio);
CGContextConcatCTM(context, transform);
CGContextConcatCTM(context, _transform);

View File

@@ -13,7 +13,6 @@
#import "RNSVGNode.h"
#import "RNSVGLength.h"
#import "RNSVGVectorEffect.h"
#import "RNSVGPercentageConverter.h"
@interface RNSVGRenderable : RNSVGNode

View File

@@ -1,23 +0,0 @@
/**
* Copyright (c) 2015-present, Horcrux.
* All rights reserved.
*
* This source code is licensed under the MIT-style license found in the
* LICENSE file in the root directory of this source tree.
*/
#import <Foundation/Foundation.h>
#import <QuartzCore/QuartzCore.h>
#import "RNSVGLength.h"
@interface RNSVGPercentageConverter : NSObject
+ (CGFloat) percentageToFloat:(NSString *)percentage relative:(CGFloat)relative offset:(CGFloat)offset;
+ (CGFloat) stringToFloat:(NSString *)string relative:(CGFloat)relative offset:(CGFloat)offset;
+ (BOOL) isPercentage:(NSString *) string;
+ (CGFloat)lengthToFloat:(RNSVGLength *)length relative:(CGFloat)relative offset:(CGFloat)offset;
@end

View File

@@ -1,67 +0,0 @@
/**
* Copyright (c) 2015-present, Horcrux.
* All rights reserved.
*
* This source code is licensed under the MIT-style license found in the
* LICENSE file in the root directory of this source tree.
*/
#import "RNSVGPercentageConverter.h"
@implementation RNSVGPercentageConverter
static NSRegularExpression* percentageRegExp;
+(void)initialize
{
percentageRegExp = [[NSRegularExpression alloc] initWithPattern:@"^(\\-?\\d+(?:\\.\\d+)?)%$" options:0 error:nil];
}
+ (CGFloat)stringToFloat:(NSString *)string relative:(CGFloat)relative offset:(CGFloat)offset
{
if (string == nil) {
return offset;
} else if (![self isPercentage:string]) {
return (CGFloat)[string doubleValue] + offset;
} else {
return [self percentageToFloat:string relative:relative offset:offset];
}
}
+ (CGFloat)lengthToFloat:(RNSVGLength *)length relative:(CGFloat)relative offset:(CGFloat)offset
{
if (length == nil) {
return offset;
} else if ([length unit] != SVG_LENGTHTYPE_PERCENTAGE) {
return [length value] + offset;
} else {
return [length value] / 100 * relative + offset;
}
}
+ (CGFloat)percentageToFloat:(NSString *)percentage relative:(CGFloat)relative offset:(CGFloat)offset
{
__block CGFloat matched;
[percentageRegExp enumerateMatchesInString:percentage
options:0
range:NSMakeRange(0, percentage.length)
usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop)
{
matched = (CGFloat)[[percentage substringWithRange:NSMakeRange(result.range.location, result.range.length)] doubleValue];
matched = matched / 100 * relative + offset;
}];
return matched;
}
+ (BOOL)isPercentage:(NSString *) string
{
if (![string isKindOfClass:[NSString class]]) {
return NO;
}
return [percentageRegExp firstMatchInString:string options:0 range:NSMakeRange(0, [string length])] != nil;
}
@end

View File

@@ -21,8 +21,6 @@ export default class RadialGradient extends Shape<{
static displayName = 'RadialGradient';
static defaultProps = {
fx: '50%',
fy: '50%',
cx: '50%',
cy: '50%',
r: '50%',
@@ -30,7 +28,7 @@ export default class RadialGradient extends Shape<{
render() {
const { props } = this;
const { fx, fy, rx, ry, r, cx, cy } = props;
const { rx, ry, r, cx, cy, fx = cx, fy = cy } = props;
return (
<RNSVGRadialGradient
ref={this.refMethod}