Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/curthard89/IJSVG into Lat…
Browse files Browse the repository at this point in the history
…estFixes2
  • Loading branch information
mattreagan29 committed Dec 12, 2015
2 parents a3d48a1 + d50d375 commit c721749
Show file tree
Hide file tree
Showing 3 changed files with 135 additions and 44 deletions.
110 changes: 81 additions & 29 deletions source/IJSVGRadialGradient.m
Original file line number Diff line number Diff line change
Expand Up @@ -35,24 +35,34 @@ + (NSGradient *)parseGradient:(NSXMLElement *)element
startPoint:(CGPoint *)startPoint
endPoint:(CGPoint *)endPoint
{
// assume its a vertical / horizonal
gradient.cx = [[[element attributeForName:@"cx"] stringValue] floatValue]/100;
gradient.cy = [[[element attributeForName:@"cy"] stringValue] floatValue]/100;
gradient.radius = [[[element attributeForName:@"r"] stringValue] floatValue]/100;
gradient.fx = [[[element attributeForName:@"fx"] stringValue] floatValue]/100;
gradient.fy = [[[element attributeForName:@"fy"] stringValue] floatValue]/100;
// cx defaults to 50% if not specified
if( [element attributeForName:@"cx"] )
gradient.cx = [[[element attributeForName:@"cx"] stringValue] floatValue]/100;
else
gradient.cx = .5f;

// nothing has been specified, make it 50% for everything
if( gradient.cx == 0.f && gradient.cy == 0.f
&& gradient.fx == 0.f && gradient.fy == 0.f
&& gradient.radius == 0.f )
{
gradient.cx = .5;
gradient.cy = .5;
gradient.radius = .5;
gradient.fx = .5;
gradient.fy = .5;
}
// cy defaults to 50% is not specified
if([element attributeForName:@"cy"])
gradient.cy = [[[element attributeForName:@"cy"] stringValue] floatValue]/100;
else
gradient.cy = .5f;

if( [element attributeForName:@"r"] )
gradient.radius = [[[element attributeForName:@"r"] stringValue] floatValue]/100;
else
gradient.radius = .5f;

// fx defaults to cx if not specified
if( [element attributeForName:@"fx"] != nil )
gradient.fx = [[[element attributeForName:@"fx"] stringValue] floatValue]/100;
else
gradient.fx = gradient.cx;

// fy defaults to cy if not specified
if( [element attributeForName:@"fy"] != nil )
gradient.fy = [[[element attributeForName:@"fx"] stringValue] floatValue]/100;
else
gradient.fy = gradient.cy;

if( gradient.gradient != nil )
return nil;
Expand All @@ -69,28 +79,70 @@ + (NSGradient *)parseGradient:(NSXMLElement *)element
return ret;
}

- (CGFloat)_handleTransform:(IJSVGTransform *)transform
bounds:(CGRect)bounds
index:(NSInteger)index
value:(CGFloat)value
{
// rotate transform, assume its based on percentages
// if lower then 0 is specified for 1 or 2
CGFloat max = bounds.size.width>bounds.size.height?bounds.size.width:bounds.size.height;
if( transform.command == IJSVGTransformCommandRotate )
{
switch(index)
{
case 1: {
if(value<1.f)
return max*value;
break;
}

case 2: {
if(value<1.f)
return max*value;
break;
}
}
}
return value;

}

- (void)drawInContextRef:(CGContextRef)ctx
path:(IJSVGPath *)path
{
// apply any transforms to the current context
CGRect bounds = path.path.bounds;
CGContextTranslateCTM( ctx, bounds.origin.x, bounds.origin.y );

for( IJSVGTransform * transform in self.transforms )
{
transform = [[transform copy] autorelease];
[transform recalculateWithBounds:bounds];
CGAffineTransform trans = transform.CGAffineTransform;
CGContextConcatCTM(ctx, trans);
IJSVGTransformParameterModifier modifier = ^CGFloat(NSInteger index, CGFloat value) {
return [self _handleTransform:transform
bounds:bounds
index:index
value:value];
};
CGContextConcatCTM(ctx, [transform CGAffineTransformWithModifier:modifier]);
}

CGPoint sp = CGPointMake( bounds.size.width*self.cx, bounds.size.height*self.cy);
CGPoint ep = CGPointMake( bounds.size.width*self.fx, bounds.size.height*self.fy);

// draw the gradient
CGPoint sp = self.startPoint;
CGPoint ep = self.endPoint;

if( self.startPoint.x == .5f )
sp.x = bounds.size.width*self.startPoint.x;
if(startPoint.y == .5f)
sp.y = bounds.size.height*self.startPoint.y;

if(self.endPoint.x == .5f)
ep.x = bounds.size.width*self.endPoint.x;
if(self.endPoint.y == .5f)
ep.y = bounds.size.height*self.endPoint.y;

CGFloat r = self.radius;
if(r == .5f)
r = (sp.x>sp.y?sp.x:sp.y);

CGGradientDrawingOptions options = kCGGradientDrawsBeforeStartLocation|kCGGradientDrawsAfterEndLocation;
CGGradientRef grad = self.CGGradient;
CGContextDrawRadialGradient(ctx, grad, sp, 0.f, ep, bounds.size.height*self.radius, options);
CGContextDrawRadialGradient(ctx, grad, sp, 0.f, ep, r, options);
}

@end
3 changes: 3 additions & 0 deletions source/IJSVGTransform.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
#import <Foundation/Foundation.h>
#import "IJSVGUtils.h"

typedef CGFloat (^IJSVGTransformParameterModifier)(NSInteger index, CGFloat value);

typedef NS_OPTIONS( NSInteger, IJSVGTransformCommand ) {
IJSVGTransformCommandMatrix,
IJSVGTransformCommandTranslate,
Expand Down Expand Up @@ -36,6 +38,7 @@ typedef NS_OPTIONS( NSInteger, IJSVGTransformCommand ) {
inContext:(CGContextRef)context;
+ (NSBezierPath *)transformedPath:(IJSVGPath *)path;
- (CGAffineTransform)CGAffineTransform;
- (CGAffineTransform)CGAffineTransformWithModifier:(IJSVGTransformParameterModifier)modifier;
- (void)recalculateWithBounds:(CGRect)bounds;

@end
66 changes: 51 additions & 15 deletions source/IJSVGTransform.m
Original file line number Diff line number Diff line change
Expand Up @@ -245,45 +245,81 @@ + (void)performTransform:(IJSVGTransform *)transform
}

- (CGAffineTransform)CGAffineTransform
{
return [self CGAffineTransformWithModifier:nil];
}

- (CGAffineTransform)CGAffineTransformWithModifier:(IJSVGTransformParameterModifier)modifier
{
switch(self.command)
{
// matrix
case IJSVGTransformCommandMatrix: {
return CGAffineTransformMake( self.parameters[0],
self.parameters[1],
self.parameters[2],
self.parameters[3],
self.parameters[4],
self.parameters[5]);
CGFloat p0 = self.parameters[0];
CGFloat p1 = self.parameters[1];
CGFloat p2 = self.parameters[2];
CGFloat p3 = self.parameters[3];
CGFloat p4 = self.parameters[4];
CGFloat p5 = self.parameters[5];
if(modifier != nil)
{
p0 = modifier(0,p0);
p1 = modifier(1,p1);
p2 = modifier(2,p2);
p3 = modifier(2,p3);
p4 = modifier(2,p4);
p5 = modifier(2,p5);
}
return CGAffineTransformMake(p0, p1, p2, p3, p4, p5);
}

// translate
case IJSVGTransformCommandTranslate: {
CGFloat p0 = self.parameters[0];
CGFloat p1 = self.parameters[1];
if(modifier != nil)
{
p0 = modifier(0,p0);
p1 = modifier(1,p1);
}
if(self.parameterCount == 1)
return CGAffineTransformMakeTranslation( self.parameters[0], 0 );
return CGAffineTransformMakeTranslation(self.parameters[0], self.parameters[1]);
return CGAffineTransformMakeTranslation( p0, 0 );
return CGAffineTransformMakeTranslation(p0, p1);
}

// scale
case IJSVGTransformCommandScale: {
CGFloat p0 = self.parameters[0];
CGFloat p1 = self.parameters[1];
if(modifier != nil)
{
p0 = modifier(0,p0);
p1 = modifier(1,p1);
}
if(self.parameterCount == 1)
return CGAffineTransformMakeScale( self.parameters[0], self.parameters[0]);
return CGAffineTransformMakeScale( self.parameters[0], self.parameters[1]);
return CGAffineTransformMakeScale( p0, p0);
return CGAffineTransformMakeScale( p0, p1);
}

// rotate
case IJSVGTransformCommandRotate: {
if(self.parameterCount == 1)
return CGAffineTransformMakeRotation((self.parameters[0]/180) * M_PI);
else {
CGFloat centerX = self.parameters[1];
CGFloat centerY = self.parameters[2];
CGFloat angle = self.parameters[0]*(M_PI/180.f);
CGFloat p0 = self.parameters[0];
CGFloat p1 = self.parameters[1];
CGFloat p2 = self.parameters[2];
if(modifier != nil)
{
p0 = modifier(0,p0);
p1 = modifier(1,p1);
p2 = modifier(2,p2);
}
CGFloat angle = p0*(M_PI/180.f);
CGAffineTransform def = CGAffineTransformIdentity;
def = CGAffineTransformTranslate(def, centerX, centerY);
def = CGAffineTransformTranslate(def, p1, p2);
def = CGAffineTransformRotate(def, angle);
def = CGAffineTransformTranslate(def, -1.f*centerX, -1.f*centerY);
def = CGAffineTransformTranslate(def, -1.f*p1, -1.f*p2);
return def;
}
break;
Expand Down

0 comments on commit c721749

Please sign in to comment.