From 8b4ce4ef61c242d43a1bb5d5f3142a033863bfb8 Mon Sep 17 00:00:00 2001 From: Curtis Hard Date: Fri, 10 Apr 2015 20:09:46 +0100 Subject: [PATCH] Parser fixes and style computation FIxed various issues with parser not finding linked elements. Also added much better support for style attribute. Also added overal viewbox clipping and various other fixes. --- .../UserInterfaceState.xcuserstate | Bin 41712 -> 41649 bytes source/IJSVG.m | 26 +- source/IJSVGCache.m | 2 +- source/IJSVGColor.h | 1 + source/IJSVGColor.m | 7 + source/IJSVGCommand.m | 2 +- source/IJSVGCommandMove.m | 14 + source/IJSVGGroup.m | 17 +- source/IJSVGNode.m | 3 + source/IJSVGParser.m | 247 ++++++++++++++---- source/IJSVGStyle.m | 67 ++--- source/IJSVGTransform.h | 2 + source/IJSVGTransform.m | 71 +++-- source/IJSVGUtils.h | 2 + source/IJSVGUtils.m | 37 ++- 15 files changed, 361 insertions(+), 137 deletions(-) diff --git a/IJSVGExample/IJSVGExample.xcodeproj/project.xcworkspace/xcuserdata/curtishard.xcuserdatad/UserInterfaceState.xcuserstate b/IJSVGExample/IJSVGExample.xcodeproj/project.xcworkspace/xcuserdata/curtishard.xcuserdatad/UserInterfaceState.xcuserstate index 81be11a8f2504d38b9d9928b19791875c68bc4c8..ab7ee28fbdd3d91aa32a009266dbc19c56ea9b27 100644 GIT binary patch delta 21740 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%0DY#RpC`+m0^`tm2H(n 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 eV^)mWK4#aL1M1^M99RDq_Nae<_=%7C 4 ) - { - // is RGBA value - if( [[value substringToIndex:3] isEqualToString:@"rgb"] ) - { - NSInteger count = 0; - CGFloat * params = [IJSVGUtils commandParameters:value - count:&count]; - CGFloat alpha = 1; - if( count == 4 ) - alpha = params[3]; - val = [NSColor colorWithCalibratedRed:params[0]/255 - green:params[1]/255 - blue:params[2]/255 - alpha:alpha]; - free(params); - } else if( [[value substringToIndex:1] isEqualToString:@"#"] ) { - // hex value - val = [IJSVGColor colorFromHEXString:value - alpha:1.f]; - } - } - // value is numeric, convert to a float - if( [[self class] isNumeric:value] ) - val = @([value floatValue]); - + // is it a color? + NSColor * color = [IJSVGColor colorFromString:value]; + if( color == nil || ![[self allowedColourKeys] containsObject:key] ) + { + // value is numeric, convert to a float + val = value; + if( [[self class] isNumeric:value] ) + val = @([value floatValue]); + } else + val = color; + // set the value if( val != nil ) [style setPropertyValue:val @@ -110,8 +100,7 @@ + (BOOL)isNumeric:(NSString *)string { - NSCharacterSet * nonNumbers = [[NSCharacterSet decimalDigitCharacterSet] invertedSet]; - return [string rangeOfCharacterFromSet:nonNumbers].location == NSNotFound; + return [[NSScanner scannerWithString:string] scanFloat:NULL]; } - (NSString *)description diff --git a/source/IJSVGTransform.h b/source/IJSVGTransform.h index b0e0864..9aefe56 100644 --- a/source/IJSVGTransform.h +++ b/source/IJSVGTransform.h @@ -22,12 +22,14 @@ typedef NS_OPTIONS( NSInteger, IJSVGTransformCommand ) { IJSVGTransformCommand command; CGFloat * parameters; NSInteger parameterCount; + NSInteger sort; } @property ( nonatomic, assign ) IJSVGTransformCommand command; @property ( nonatomic, assign ) CGFloat * parameters; @property ( nonatomic, assign ) NSInteger parameterCount; +@property ( nonatomic, assign ) NSInteger sort; + (NSArray *)transformsForString:(NSString *)string; + (void)performTransform:(IJSVGTransform *)transform diff --git a/source/IJSVGTransform.m b/source/IJSVGTransform.m index 071142d..4fb70e2 100644 --- a/source/IJSVGTransform.m +++ b/source/IJSVGTransform.m @@ -13,6 +13,7 @@ @synthesize command; @synthesize parameters; @synthesize parameterCount; +@synthesize sort; - (void)dealloc { @@ -33,6 +34,23 @@ return IJSVGTransformCommandNotImplemented; } ++ (NSInteger)sortForTransformCommand:(IJSVGTransformCommand)command +{ + switch (command) { + case IJSVGTransformCommandScale: + return 0; + case IJSVGTransformCommandRotate: + return 1; + case IJSVGTransformCommandMatrix: + return 2; + case IJSVGTransformCommandTranslate: + return -1; + default: + return 10; + } + return 10; +} + + (NSArray *)transformsForString:(NSString *)string { static NSRegularExpression * _reg = nil; @@ -48,22 +66,23 @@ options:0 range:NSMakeRange( 0, string.length ) usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) - { - NSString * command = [string substringWithRange:[result rangeAtIndex:1]]; - IJSVGTransformCommand commandType = [[self class] commandForCommandString:command]; - if( commandType == IJSVGTransformCommandNotImplemented ) - return; - - // create the transform - NSString * params = [string substringWithRange:[result rangeAtIndex:2]]; - IJSVGTransform * transform = [[[[self class] alloc] init] autorelease]; - NSInteger count = 0; - transform.command = commandType; - transform.parameters = [IJSVGUtils commandParameters:params - count:&count]; - transform.parameterCount = count; - [transforms addObject:transform]; - }]; + { + NSString * command = [string substringWithRange:[result rangeAtIndex:1]]; + IJSVGTransformCommand commandType = [[self class] commandForCommandString:command]; + if( commandType == IJSVGTransformCommandNotImplemented ) + return; + + // create the transform + NSString * params = [string substringWithRange:[result rangeAtIndex:2]]; + IJSVGTransform * transform = [[[[self class] alloc] init] autorelease]; + NSInteger count = 0; + transform.command = commandType; + transform.parameters = [IJSVGUtils commandParameters:params + count:&count]; + transform.parameterCount = count; + transform.sort = [[self class] sortForTransformCommand:commandType]; + [transforms addObject:transform]; + }]; } return transforms; } @@ -73,7 +92,7 @@ { switch( transform.command ) { - // matrix + // matrix case IJSVGTransformCommandMatrix: { CGContextConcatCTM( context, CGAffineTransformMake( transform.parameters[0], transform.parameters[1], @@ -83,8 +102,8 @@ transform.parameters[5])); break; } - - // translate + + // translate case IJSVGTransformCommandTranslate: { if( transform.parameterCount == 1 ) CGContextTranslateCTM( context, transform.parameters[0], 0 ); @@ -93,20 +112,24 @@ break; } - // scale + // scale case IJSVGTransformCommandScale: { - CGContextScaleCTM( context, transform.parameters[0], transform.parameters[1] ); + if( transform.parameterCount == 1 ) + CGContextScaleCTM( context, transform.parameters[0], transform.parameters[0] ); + else + CGContextScaleCTM( context, transform.parameters[0], transform.parameters[1] ); break; } - // rotate + // rotate case IJSVGTransformCommandRotate: { + // these are in radians, not degrees if( transform.parameterCount == 1 ) - CGContextRotateCTM( context, transform.parameters[0]); + CGContextRotateCTM( context, (transform.parameters[0] / 180) * M_PI); // need support for rotate around a point } - // do nothing + // do nothing case IJSVGTransformCommandNotImplemented: { } diff --git a/source/IJSVGUtils.h b/source/IJSVGUtils.h index 172c196..09183e9 100644 --- a/source/IJSVGUtils.h +++ b/source/IJSVGUtils.h @@ -26,5 +26,7 @@ + (CGFloat)angleBetweenPointA:(NSPoint)point pointb:(NSPoint)point; + (NSString *)defURL:(NSString *)string; ++ (CGFloat)floatValue:(NSString *)string + fallBackForPercent:(CGFloat)viewBox; @end diff --git a/source/IJSVGUtils.m b/source/IJSVGUtils.m index 2a627f5..71097c1 100644 --- a/source/IJSVGUtils.m +++ b/source/IJSVGUtils.m @@ -10,7 +10,7 @@ @implementation IJSVGUtils -#define FLOAT_EXP @"[-+]?[0-9]*\\.?[0-9]+" +#define FLOAT_EXP @"[-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?" + (IJSVGCommandType)typeForCommandString:(NSString *)string { @@ -22,7 +22,7 @@ static NSRegularExpression *_commandRegex; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ - _commandRegex = [[NSRegularExpression alloc] initWithPattern:@"[A-Za-z]" + _commandRegex = [[NSRegularExpression alloc] initWithPattern:@"[MmZzLlHhVvCcSsQqTtAa]{1}" options:0 error:nil]; }); @@ -51,9 +51,9 @@ error:nil]; }); return [_reg stringByReplacingMatchesInString:string - options:0 - range:NSMakeRange( 0, string.length ) - withTemplate:@""]; + options:0 + range:NSMakeRange( 0, string.length ) + withTemplate:@""]; } + (NSString *)defURL:(NSString *)string @@ -70,10 +70,10 @@ options:0 range:NSMakeRange( 0, string.length ) usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) - { - if( ( foundID = [string substringWithRange:[result rangeAtIndex:1]] ) != nil ) - *stop = YES; - }]; + { + if( ( foundID = [string substringWithRange:[result rangeAtIndex:1]] ) != nil ) + *stop = YES; + }]; return foundID; } @@ -119,11 +119,19 @@ options:0 range:NSMakeRange( 0, command.length)]; CGFloat * ret = (CGFloat *)malloc(matches.count*sizeof(CGFloat)); + NSDictionary * dict = [NSDictionary dictionaryWithObject:@"." + forKey:NSLocaleDecimalSeparator]; for( NSInteger i = 0; i < matches.count; i++ ) { NSTextCheckingResult * match = [matches objectAtIndex:i]; NSString * paramString = [command substringWithRange:match.range]; - ret[i] = (CGFloat)[paramString floatValue]; + NSDecimalNumber * decimal = nil; + if( [paramString rangeOfString:@"."].location != NSNotFound ) + decimal = [NSDecimalNumber decimalNumberWithString:paramString + locale:dict]; + else + decimal = [NSDecimalNumber decimalNumberWithString:paramString]; + ret[i] = (CGFloat)[decimal floatValue]; *count += 1; } return ret; @@ -145,6 +153,15 @@ return ret; } ++ (CGFloat)floatValue:(NSString *)string + fallBackForPercent:(CGFloat)fallBack +{ + CGFloat val = [string floatValue]; + if( [string rangeOfString:@"%"].location != NSNotFound ) + val = (fallBack * val)/100; + return val; +} + + (void)logParameters:(CGFloat *)param count:(NSInteger)count {