From 0292c5193b54ebe9e5bf9b71fde3403afca269df Mon Sep 17 00:00:00 2001 From: Curtis Hard Date: Tue, 19 Jan 2016 22:09:16 +0000 Subject: [PATCH] Better rule support --- .../UserInterfaceState.xcuserstate | Bin 47677 -> 48654 bytes IJSVGExample/IJSVGExample/test.svg | 20 +- source/IJSVGStyleSheet.m | 50 +++- source/IJSVGStyleSheetRule.h | 3 +- source/IJSVGStyleSheetRule.m | 5 +- source/IJSVGStyleSheetSelector.h | 3 + source/IJSVGStyleSheetSelector.m | 214 +++++++++++++----- 7 files changed, 233 insertions(+), 62 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 b4fb2a8c19822649b44144a77463b85ba10fd911..bc76c745b93e4e6ff8fc625ec655084ca125e2b2 100644 GIT binary patch literal 48654 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 - g rect.bacon { + line { + fill: white; + stroke: white; + stroke-width: 5; + } + + g + g.woop line.willy ~ rect { + fill: blue; + } + + g + g.woop > rect.bacon#really { fill: red; } + + + - + + + + diff --git a/source/IJSVGStyleSheet.m b/source/IJSVGStyleSheet.m index 8a43e47..7ad0348 100644 --- a/source/IJSVGStyleSheet.m +++ b/source/IJSVGStyleSheet.m @@ -10,6 +10,31 @@ #import "IJSVGStyle.h" #import "IJSVGNode.h" +@interface IJSVGStyleSheetSelectorWrapper : NSObject { + + IJSVGStyleSheetSelector * selector; + IJSVGStyleSheetRule * rule; + +} + +@property (nonatomic, retain) IJSVGStyleSheetRule * rule; +@property (nonatomic, retain) IJSVGStyleSheetSelector * selector; + +@end + +@implementation IJSVGStyleSheetSelectorWrapper + +@synthesize rule, selector; + +- (void)dealloc +{ + [rule release], rule = nil; + [selector release], selector = nil; + [super dealloc]; +} + +@end + @implementation IJSVGStyleSheet - (void)dealloc @@ -135,11 +160,32 @@ - (IJSVGStyle *)styleForNode:(IJSVGNode *)node { IJSVGStyle * style = [[[IJSVGStyle alloc] init] autorelease]; + NSMutableArray * matchedRules = [[[NSMutableArray alloc] init] autorelease]; for(IJSVGStyleSheetRule * rule in _rules) { - if([rule matchesNode:node]) - style = [style mergedStyle:rule.style]; + IJSVGStyleSheetSelector * matchedSelector = nil; + if([rule matchesNode:node selector:&matchedSelector]) { + + // make a wrapper for the selector with the rule + IJSVGStyleSheetSelectorWrapper * wrapper = [[[IJSVGStyleSheetSelectorWrapper alloc] init] autorelease]; + wrapper.rule = rule; + wrapper.selector = matchedSelector; + + // add it to the array of matches + [matchedRules addObject:wrapper]; + } } + + // now we have all the wrappers, we need to sort them + // by specificity + NSSortDescriptor * sort = [NSSortDescriptor sortDescriptorWithKey:@"selector.specificity" ascending:YES]; + [matchedRules sortUsingDescriptors:@[sort]]; + + // combine the rule + for(IJSVGStyleSheetSelectorWrapper * wrapper in matchedRules) { + style = [style mergedStyle:wrapper.rule.style]; + } + return style; } diff --git a/source/IJSVGStyleSheetRule.h b/source/IJSVGStyleSheetRule.h index c34f1d5..85de67a 100644 --- a/source/IJSVGStyleSheetRule.h +++ b/source/IJSVGStyleSheetRule.h @@ -22,6 +22,7 @@ @property (nonatomic, retain) NSArray * selectors; @property (nonatomic, retain) IJSVGStyle * style; -- (BOOL)matchesNode:(IJSVGNode *)node; +- (BOOL)matchesNode:(IJSVGNode *)node + selector:(IJSVGStyleSheetSelector **)matchedSelector; @end diff --git a/source/IJSVGStyleSheetRule.m b/source/IJSVGStyleSheetRule.m index 5e50979..528bb70 100644 --- a/source/IJSVGStyleSheetRule.m +++ b/source/IJSVGStyleSheetRule.m @@ -20,12 +20,15 @@ } - (BOOL)matchesNode:(IJSVGNode *)node + selector:(IJSVGStyleSheetSelector **)matchedSelector { // interate over each select and work out if // it allows us to be applied for(IJSVGStyleSheetSelector * selector in selectors) { - if([selector matchesNode:node]) + if([selector matchesNode:node]) { + *matchedSelector = selector; return YES; + } } return NO; } diff --git a/source/IJSVGStyleSheetSelector.h b/source/IJSVGStyleSheetSelector.h index 92b4c5d..96bd602 100644 --- a/source/IJSVGStyleSheetSelector.h +++ b/source/IJSVGStyleSheetSelector.h @@ -14,11 +14,14 @@ @interface IJSVGStyleSheetSelector : NSObject { NSString * selector; + NSUInteger specificity; @private NSMutableArray * _rawSelectors; } +@property (nonatomic, assign) NSUInteger specificity; + - (id)initWithSelectorString:(NSString *)string; - (BOOL)matchesNode:(IJSVGNode *)node; diff --git a/source/IJSVGStyleSheetSelector.m b/source/IJSVGStyleSheetSelector.m index f716e56..4cee59d 100644 --- a/source/IJSVGStyleSheetSelector.m +++ b/source/IJSVGStyleSheetSelector.m @@ -12,22 +12,22 @@ @implementation IJSVGStyleSheetSelector +#define SPECIFICITY_TAG 1 +#define SPECIFICITY_CLASS 10 +#define SPECIFICITY_IDENTIFIER 100 + +@synthesize specificity; + - (void)dealloc { [selector release], selector = nil; [super dealloc]; } -- (BOOL)combinatorIsGreedy:(IJSVGStyleSheetSelectorCombinator)combinator +- (BOOL)isSiblingCombinator:(IJSVGStyleSheetSelectorCombinator)combinator { - return combinator == IJSVGStyleSheetSelectorCombinatorDescendant || - combinator == IJSVGStyleSheetSelectorCombinatorPrecededSibling; -} - -- (BOOL)isAncestorOperator:(IJSVGStyleSheetSelectorCombinator)combinator -{ - return combinator == IJSVGStyleSheetSelectorCombinatorDescendant || - combinator == IJSVGStyleSheetSelectorCombinatorDirectDescendant; + return combinator == IJSVGStyleSheetSelectorCombinatorNextSibling || + combinator == IJSVGStyleSheetSelectorCombinatorPrecededSibling; } - (IJSVGStyleSheetSelectorCombinator)combinatorForUnichar:(unichar)aChar @@ -48,10 +48,31 @@ selector = [string copy]; _rawSelectors = [[NSMutableArray alloc] init]; [self _compile]; + [self _calculate]; } return self; } +- (void)_calculate +{ + // calculate the specificity + // of the selector + for(IJSVGStyleSheetSelectorRaw * rawSelector in _rawSelectors) { + + // 1 for a tag + if(rawSelector.tag != nil) { + self.specificity += SPECIFICITY_TAG; + } + + // 100 for a id + if(rawSelector.identifier != nil) + self.specificity += SPECIFICITY_IDENTIFIER; + + // 10 for a class + self.specificity += (rawSelector.classes.count*SPECIFICITY_CLASS); + } +} + - (void)_compile { NSUInteger length = selector.length; @@ -153,7 +174,8 @@ // add raw selector if( i == length - 1 ) { - [sels addObject:rawSelector]; + if(rawSelector != nil) + [sels addObject:rawSelector]; rawSelector = nil; } @@ -226,62 +248,136 @@ - (BOOL)_matches:(IJSVGNode *)aNode selector:(IJSVGStyleSheetSelectorRaw *)rawSelector { - IJSVGNode * prevNode = aNode; IJSVGStyleSheetSelectorRaw * aSelector = rawSelector; + // loop until aSelector is nil while(aSelector != nil) { - IJSVGNode * workingNode = nil; - - // for adjacent node, the content to test against - // is the previous sibling - if(rawSelector.combinator == IJSVGStyleSheetSelectorCombinatorNextSibling || - rawSelector.combinator == IJSVGStyleSheetSelectorCombinatorPrecededSibling) { - workingNode = [self _previousNode:prevNode]; + // sibling, so + or ~ + if([self isSiblingCombinator:aSelector.combinator]) { + + // the + + if(aSelector.combinator == IJSVGStyleSheetSelectorCombinatorNextSibling) { + + // straight forward again, find the previous sibling + // and match it against the next selector in the list + IJSVGNode * previousNode = [self _previousNode:aNode]; + IJSVGStyleSheetSelectorRaw * s = [self _nextSelector:aSelector]; + + if(previousNode != nil && [self _match:previousNode selector:s]) { + // set the new starting selector and node + aSelector = s; + aNode = previousNode; + } + + // didnt match previous element + else { + return NO; + } + + } + + // the ~ + if(aSelector.combinator == IJSVGStyleSheetSelectorCombinatorPrecededSibling) { + + IJSVGGroup * parentNode = (IJSVGGroup *)aNode.parentNode; + + // no parent, just return no + if(parentNode == nil) { + return NO; + } + + // grab the children + NSArray * nodes = parentNode.children; + NSInteger index = [nodes indexOfObject:aNode]; + + // doesnt contain the child + if(index == NSNotFound) { + return NO; + } + + // find the next selector + IJSVGStyleSheetSelectorRaw * s = [self _nextSelector:aSelector]; + BOOL found = NO; + for( NSUInteger i = index; index > 0; i-- ) { + + // grab the child node + IJSVGNode * childNode = nodes[i]; + + // matches, huzzah! + if([self _match:childNode selector:s]) { + // set the new starting selector and node + found = YES; + aSelector = s; + aNode = childNode; + break; + } + } + + // nothing found + if(found == NO) { + return NO; + } + + } + } - // for descedant combinators and child, the element - // to test against is the parent node + // not a + or a ~ else { - // find the parent - IJSVGGroup * possibleParent = (IJSVGGroup *)prevNode.parentNode; - if(possibleParent != nil) { - workingNode = possibleParent; - } - } - - // no node - just kill - if(workingNode == nil) - return NO; - - // test the working node against the current selector - if([self _match:workingNode - selector:aSelector]) { - - // check for greedy - IJSVGStyleSheetSelectorRaw * nSelector = [self _nextSelector:rawSelector]; - - if([self combinatorIsGreedy:aSelector.combinator] && - nSelector.combinator != rawSelector.combinator && - (rawSelector.combinator == IJSVGStyleSheetSelectorCombinatorPrecededSibling - && [self isAncestorOperator:nSelector.combinator]) == NO) { - // just do a quick dirty check - if([self _matches:workingNode selector:rawSelector]) { - return YES; + // can up to the matching parent, if not found, nothing! + if(aSelector.combinator == IJSVGStyleSheetSelectorCombinatorDescendant) { + // go up the chain until we match a parent that + // matches the next selector + IJSVGStyleSheetSelectorRaw * s = [self _nextSelector:aSelector];; + IJSVGNode * p = aNode; + while(p != nil) { + + // set p to current parentNode + p = p.parentNode; + + // p must exist and match the selector + if(p != nil && [self _match:p selector:s]) { + // set the new starting selector and node + aSelector = s; + aNode = p; + break; + } + + // no parent match found + else if(p == nil) { + return NO; + } } } - // get the next selector - aSelector = [self _nextSelector:aSelector]; - } else { - - // is its greedy, if we didnt match, just return NO - if([self combinatorIsGreedy:aSelector.combinator] == NO) { - return NO; + // > direct descedant + else if(aSelector.combinator == IJSVGStyleSheetSelectorCombinatorDirectDescendant) { + + // grab parent + IJSVGGroup * parentNode = (IJSVGGroup *)aNode.parentNode; + + // no parent, just return + if(parentNode == nil) + return NO; + + // really straight forward, just check if the parent + // matches the next selector and... contains the node in question + IJSVGStyleSheetSelectorRaw * s = [self _nextSelector:aSelector]; + if([self _match:parentNode selector:s] && + [parentNode.children containsObject:aNode]) { + // set the new starting selector and node + aSelector = s; + aNode = parentNode; + } + + // no match found + else { + return NO; + } } } - prevNode = workingNode; } return YES; } @@ -289,10 +385,16 @@ - (BOOL)matchesNode:(IJSVGNode *)node { - IJSVGStyleSheetSelectorRaw * raw = _rawSelectors[0]; - if([self _match:node selector:raw] && - ([self _matches:node selector:raw] || _rawSelectors.count == 1 )) + IJSVGStyleSheetSelectorRaw * sel = _rawSelectors[0]; + // return YES only if the first selector matches the node + // and the next selector is nil, or the next selector isnt nil + // and the node then goes up the tree and works itself out with the + // selectors in question + if([self _match:node selector:sel] && + ([self _nextSelector:sel] == nil || + [self _matches:node selector:sel])) { return YES; + } return NO; }