Merge branch 'css_refactor'
This commit is contained in:
BIN
Binary file not shown.
@@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="6206.9" systemVersion="14A343f" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none">
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="9531" systemVersion="15C50" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none">
|
||||
<dependencies>
|
||||
<deployment defaultVersion="1070" identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="6206.9"/>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="9531"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
|
||||
@@ -673,32 +673,12 @@
|
||||
<rect key="contentRect" x="335" y="390" width="556" height="452"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="877"/>
|
||||
<view key="contentView" id="EiT-Mj-1SZ">
|
||||
<rect key="frame" x="0.0" y="-1" width="556" height="452"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="556" height="452"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<customView id="hhC-1S-CCX" customClass="SVGView">
|
||||
<rect key="frame" x="0.0" y="227" width="161" height="225"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
</customView>
|
||||
<customView id="jOS-l1-voG" customClass="SVGExampleView2">
|
||||
<rect key="frame" x="395" y="227" width="161" height="225"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMinY="YES"/>
|
||||
</customView>
|
||||
<customView id="mxr-zw-MsV" customClass="SVGExampleView1">
|
||||
<rect key="frame" x="160.5" y="227" width="235.5" height="225"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
</customView>
|
||||
<customView id="bHV-ou-brV" customClass="SVGExampleView3">
|
||||
<rect key="frame" x="0.0" y="0.0" width="161" height="228"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/>
|
||||
</customView>
|
||||
<customView id="osq-NY-OyC" customClass="SVGExampleView4">
|
||||
<rect key="frame" x="160" y="0.0" width="236" height="228"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" flexibleMaxX="YES" heightSizable="YES"/>
|
||||
</customView>
|
||||
<customView id="PEb-ng-OIe" customClass="SVGExampleView5">
|
||||
<rect key="frame" x="395" y="0.0" width="161" height="228"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" widthSizable="YES" heightSizable="YES"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="556" height="452"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
</customView>
|
||||
</subviews>
|
||||
</view>
|
||||
|
||||
+29
-8436
File diff suppressed because it is too large
Load Diff
|
Before Width: | Height: | Size: 590 KiB After Width: | Height: | Size: 1.5 KiB |
@@ -43,6 +43,7 @@ handleForeignObject:(IJSVGForeignObject *)foreignObject
|
||||
NSXMLDocument * _document;
|
||||
NSMutableArray * _glyphs;
|
||||
IJSVGStyleSheet * _styleSheet;
|
||||
NSMutableArray * _parsedNodes;
|
||||
}
|
||||
|
||||
@property ( nonatomic, readonly ) NSRect viewBox;
|
||||
|
||||
+43
-25
@@ -41,6 +41,7 @@
|
||||
{
|
||||
[_glyphs release], _glyphs = nil;
|
||||
[_styleSheet release], _styleSheet = nil;
|
||||
[_parsedNodes release], _parsedNodes = nil;
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
@@ -52,6 +53,7 @@
|
||||
{
|
||||
_delegate = delegate;
|
||||
_glyphs = [[NSMutableArray alloc] init];
|
||||
_parsedNodes = [[NSMutableArray alloc] init];
|
||||
|
||||
// load the document / file, assume its UTF8
|
||||
|
||||
@@ -249,10 +251,19 @@
|
||||
intoGroup:self
|
||||
def:NO];
|
||||
|
||||
// now everything has been done we need to compute the style tree
|
||||
for(NSDictionary * dict in _parsedNodes) {
|
||||
[self _postParseElementForCommonAttributes:dict[@"element"]
|
||||
node:dict[@"node"]];
|
||||
}
|
||||
|
||||
// dont need the style sheet or the parsed nodes as this point
|
||||
[_styleSheet release], _styleSheet = nil;
|
||||
[_parsedNodes release], _parsedNodes = nil;
|
||||
}
|
||||
|
||||
- (void)_parseElementForCommonAttributes:(NSXMLElement *)element
|
||||
node:(IJSVGNode *)node
|
||||
- (void)_postParseElementForCommonAttributes:(NSXMLElement *)element
|
||||
node:(IJSVGNode *)node
|
||||
{
|
||||
|
||||
// unicode
|
||||
@@ -556,6 +567,12 @@
|
||||
[_glyphs addObject:glyph];
|
||||
}
|
||||
|
||||
- (void)_parseElementForCommonAttributes:(NSXMLElement *)element
|
||||
node:(IJSVGNode *)node
|
||||
{
|
||||
[_parsedNodes addObject:@{@"node":node,@"element":element}];
|
||||
}
|
||||
|
||||
- (void)_parseBlock:(NSXMLElement *)anElement
|
||||
intoGroup:(IJSVGGroup*)parentGroup
|
||||
def:(BOOL)flag
|
||||
@@ -616,13 +633,13 @@
|
||||
group.name = subName;
|
||||
group.parentNode = parentGroup;
|
||||
|
||||
if( !flag )
|
||||
[parentGroup addChild:group];
|
||||
|
||||
// find common attributes
|
||||
[self _parseElementForCommonAttributes:element
|
||||
node:group];
|
||||
|
||||
if( !flag )
|
||||
[parentGroup addChild:group];
|
||||
|
||||
// recursively parse blocks
|
||||
[self _parseBlock:element
|
||||
intoGroup:group
|
||||
@@ -641,15 +658,15 @@
|
||||
path.name = subName;
|
||||
path.parentNode = parentGroup;
|
||||
|
||||
if( !flag )
|
||||
[parentGroup addChild:path];
|
||||
|
||||
// find common attributes
|
||||
[self _parseElementForCommonAttributes:element
|
||||
node:path];
|
||||
[self _parsePathCommandData:[[element attributeForName:@"d"] stringValue]
|
||||
intoPath:path];
|
||||
|
||||
if( !flag )
|
||||
[parentGroup addChild:path];
|
||||
|
||||
// could be defined
|
||||
if( flag || [element attributeForName:@"id"] != nil )
|
||||
[parentGroup addDef:path];
|
||||
@@ -663,15 +680,15 @@
|
||||
path.name = subName;
|
||||
path.parentNode = parentGroup;
|
||||
|
||||
if( !flag )
|
||||
[parentGroup addChild:path];
|
||||
|
||||
// find common attributes
|
||||
[self _parseElementForCommonAttributes:element
|
||||
node:path];
|
||||
[self _parsePolygon:element
|
||||
intoPath:path];
|
||||
|
||||
if( !flag )
|
||||
[parentGroup addChild:path];
|
||||
|
||||
// could be defined
|
||||
if( flag || [element attributeForName:@"id"] != nil )
|
||||
[parentGroup addDef:path];
|
||||
@@ -685,15 +702,15 @@
|
||||
path.name = subName;
|
||||
path.parentNode = parentGroup;
|
||||
|
||||
if( !flag )
|
||||
[parentGroup addChild:path];
|
||||
|
||||
// find common attributes
|
||||
[self _parseElementForCommonAttributes:element
|
||||
node:path];
|
||||
[self _parsePolyline:element
|
||||
intoPath:path];
|
||||
|
||||
if( !flag )
|
||||
[parentGroup addChild:path];
|
||||
|
||||
// could be defined
|
||||
if( flag || [element attributeForName:@"id"] != nil )
|
||||
[parentGroup addDef:path];
|
||||
@@ -707,6 +724,9 @@
|
||||
path.name = subName;
|
||||
path.parentNode = parentGroup;
|
||||
|
||||
if( !flag )
|
||||
[parentGroup addChild:path];
|
||||
|
||||
// find common attributes
|
||||
[self _parseRect:element
|
||||
intoPath:path];
|
||||
@@ -714,9 +734,6 @@
|
||||
[self _parseElementForCommonAttributes:element
|
||||
node:path];
|
||||
|
||||
if( !flag )
|
||||
[parentGroup addChild:path];
|
||||
|
||||
// could be defined
|
||||
if( flag || [element attributeForName:@"id"] != nil )
|
||||
[parentGroup addDef:path];
|
||||
@@ -730,12 +747,13 @@
|
||||
path.name = subName;
|
||||
path.parentNode = parentGroup;
|
||||
|
||||
[parentGroup addChild:path];
|
||||
|
||||
// find common attributes
|
||||
[self _parseElementForCommonAttributes:element
|
||||
node:path];
|
||||
[self _parseLine:element
|
||||
intoPath:path];
|
||||
[parentGroup addChild:path];
|
||||
|
||||
// could be defined
|
||||
if( flag || [element attributeForName:@"id"] != nil )
|
||||
@@ -750,15 +768,15 @@
|
||||
path.name = subName;
|
||||
path.parentNode = parentGroup;
|
||||
|
||||
if( !flag )
|
||||
[parentGroup addChild:path];
|
||||
|
||||
// find common attributes
|
||||
[self _parseElementForCommonAttributes:element
|
||||
node:path];
|
||||
[self _parseCircle:element
|
||||
intoPath:path];
|
||||
|
||||
if( !flag )
|
||||
[parentGroup addChild:path];
|
||||
|
||||
// could be defined
|
||||
if( flag || [element attributeForName:@"id"] != nil)
|
||||
[parentGroup addDef:path];
|
||||
@@ -772,15 +790,15 @@
|
||||
path.name = subName;
|
||||
path.parentNode = parentGroup;
|
||||
|
||||
if( !flag )
|
||||
[parentGroup addChild:path];
|
||||
|
||||
// find common attributes
|
||||
[self _parseElementForCommonAttributes:element
|
||||
node:path];
|
||||
[self _parseEllipse:element
|
||||
intoPath:path];
|
||||
|
||||
if( !flag )
|
||||
[parentGroup addChild:path];
|
||||
|
||||
// could be defined
|
||||
if( flag || [element attributeForName:@"id"] != nil )
|
||||
[parentGroup addDef:path];
|
||||
@@ -800,13 +818,13 @@
|
||||
IJSVGNode * theNode = [[node copy] autorelease];
|
||||
theNode.parentNode = parentGroup;
|
||||
|
||||
[parentGroup addChild:theNode];
|
||||
// grab common attributes
|
||||
[self _parseElementForCommonAttributes:element
|
||||
node:theNode];
|
||||
|
||||
// add them
|
||||
[parentGroup addDef:theNode];
|
||||
[parentGroup addChild:theNode];
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,31 @@
|
||||
#import "IJSVGStyle.h"
|
||||
#import "IJSVGNode.h"
|
||||
|
||||
@interface IJSVGStyleSheetSelectorListItem : NSObject {
|
||||
|
||||
IJSVGStyleSheetSelector * selector;
|
||||
IJSVGStyleSheetRule * rule;
|
||||
|
||||
}
|
||||
|
||||
@property (nonatomic, retain) IJSVGStyleSheetRule * rule;
|
||||
@property (nonatomic, retain) IJSVGStyleSheetSelector * selector;
|
||||
|
||||
@end
|
||||
|
||||
@implementation IJSVGStyleSheetSelectorListItem
|
||||
|
||||
@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
|
||||
IJSVGStyleSheetSelectorListItem * listItem = [[[IJSVGStyleSheetSelectorListItem alloc] init] autorelease];
|
||||
listItem.rule = rule;
|
||||
listItem.selector = matchedSelector;
|
||||
|
||||
// add it to the array of matches
|
||||
[matchedRules addObject:listItem];
|
||||
}
|
||||
}
|
||||
|
||||
// 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(IJSVGStyleSheetSelectorListItem * listItem in matchedRules) {
|
||||
style = [style mergedStyle:listItem.rule.style];
|
||||
}
|
||||
|
||||
return style;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -8,9 +8,231 @@
|
||||
|
||||
#import "IJSVGStyleSheetSelector.h"
|
||||
#import "IJSVGNode.h"
|
||||
#import "IJSVGGroup.h"
|
||||
|
||||
@implementation IJSVGStyleSheetSelector
|
||||
|
||||
#define SPECIFICITY_TAG 1
|
||||
#define SPECIFICITY_CLASS 10
|
||||
#define SPECIFICITY_IDENTIFIER 100
|
||||
|
||||
@synthesize specificity;
|
||||
|
||||
BOOL IJSVGStyleSheetIsSiblingCombinator(IJSVGStyleSheetSelectorCombinator combinator)
|
||||
{
|
||||
return combinator == IJSVGStyleSheetSelectorCombinatorNextSibling ||
|
||||
combinator == IJSVGStyleSheetSelectorCombinatorPrecededSibling;
|
||||
};
|
||||
|
||||
IJSVGStyleSheetSelectorCombinator IJSVGStyleSheetCombinatorForUnichar(unichar aChar)
|
||||
{
|
||||
if(aChar == '+')
|
||||
return IJSVGStyleSheetSelectorCombinatorNextSibling;
|
||||
if(aChar == '~')
|
||||
return IJSVGStyleSheetSelectorCombinatorPrecededSibling;
|
||||
if(aChar == '>')
|
||||
return IJSVGStyleSheetSelectorCombinatorDirectDescendant;
|
||||
return IJSVGStyleSheetSelectorCombinatorDescendant;
|
||||
};
|
||||
|
||||
IJSVGNode * IJSVGStyleSheetPreviousNode(IJSVGNode * node)
|
||||
{
|
||||
IJSVGGroup * group = (IJSVGGroup *)node.parentNode;
|
||||
if([group isKindOfClass:[IJSVGGroup class]] == NO)
|
||||
return nil;
|
||||
NSInteger currentIndex = [group.children indexOfObject:node];
|
||||
if(currentIndex == 0)
|
||||
return nil;
|
||||
return group.children[currentIndex-1];
|
||||
};
|
||||
|
||||
IJSVGNode * IJSVGStyleSheetNextNode(IJSVGNode * node)
|
||||
{
|
||||
IJSVGGroup * group = (IJSVGGroup *)node.parentNode;
|
||||
if([group isKindOfClass:[IJSVGGroup class]] == NO)
|
||||
return nil;
|
||||
NSInteger currentIndex = [group.children indexOfObject:node];
|
||||
if(currentIndex == group.children.count-1)
|
||||
return nil;
|
||||
return group.children[currentIndex+1];
|
||||
};
|
||||
|
||||
IJSVGStyleSheetSelectorRaw * IJSVGStyleSheetPreviousSelector(IJSVGStyleSheetSelectorRaw * aSelector, NSArray * _rawSelectors)
|
||||
{
|
||||
NSInteger index = [_rawSelectors indexOfObject:aSelector];
|
||||
if(index == 0)
|
||||
return nil;
|
||||
return _rawSelectors[index-1];
|
||||
};
|
||||
|
||||
IJSVGStyleSheetSelectorRaw * IJSVGStyleSheetNextSelector(IJSVGStyleSheetSelectorRaw * aSelector, NSArray * _rawSelectors)
|
||||
{
|
||||
NSInteger index = [_rawSelectors indexOfObject:aSelector];
|
||||
if(index == _rawSelectors.count-1)
|
||||
return nil;
|
||||
return _rawSelectors[index+1];
|
||||
};
|
||||
|
||||
BOOL IJSVGStyleSheetMatchSelector(IJSVGNode * node, IJSVGStyleSheetSelectorRaw * rawSelector)
|
||||
{
|
||||
// return no if the tag is set but doesnt match the node
|
||||
if(rawSelector.tag != nil && [rawSelector.tag isEqualToString:node.name] == NO)
|
||||
return NO;
|
||||
|
||||
// check if the classes match the class
|
||||
if(rawSelector.classes.count != 0) {
|
||||
for(NSString * className in rawSelector.classes) {
|
||||
if([node.classNameList containsObject:className] == NO)
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
// check the idenfitier
|
||||
if(rawSelector.identifier != nil &&
|
||||
[rawSelector.identifier isEqualToString:node.identifier] == NO)
|
||||
return NO;
|
||||
|
||||
return YES;
|
||||
};
|
||||
|
||||
|
||||
- (BOOL)_matches:(IJSVGNode *)aNode
|
||||
selector:(IJSVGStyleSheetSelectorRaw *)rawSelector
|
||||
{
|
||||
IJSVGStyleSheetSelectorRaw * aSelector = rawSelector;
|
||||
|
||||
// loop until aSelector is nil
|
||||
while(aSelector != nil) {
|
||||
|
||||
// sibling, so + or ~
|
||||
if(IJSVGStyleSheetIsSiblingCombinator(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 = IJSVGStyleSheetPreviousNode(aNode);
|
||||
IJSVGStyleSheetSelectorRaw * s = IJSVGStyleSheetNextSelector(aSelector, _rawSelectors);
|
||||
|
||||
if(previousNode != nil && IJSVGStyleSheetMatchSelector(previousNode, 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 = IJSVGStyleSheetNextSelector(aSelector,_rawSelectors);
|
||||
BOOL found = NO;
|
||||
for( NSUInteger i = index; index > 0; i-- ) {
|
||||
|
||||
// grab the child node
|
||||
IJSVGNode * childNode = nodes[i];
|
||||
|
||||
// matches, huzzah!
|
||||
if(IJSVGStyleSheetMatchSelector(childNode, s)) {
|
||||
// set the new starting selector and node
|
||||
found = YES;
|
||||
aSelector = s;
|
||||
aNode = childNode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// nothing found
|
||||
if(found == NO) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// not a + or a ~
|
||||
else {
|
||||
|
||||
// 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 = IJSVGStyleSheetNextSelector(aSelector,_rawSelectors);
|
||||
IJSVGNode * p = aNode;
|
||||
while(p != nil) {
|
||||
|
||||
// set p to current parentNode
|
||||
p = p.parentNode;
|
||||
|
||||
// p must exist and match the selector
|
||||
if(p != nil && IJSVGStyleSheetMatchSelector(p, s)) {
|
||||
// set the new starting selector and node
|
||||
aSelector = s;
|
||||
aNode = p;
|
||||
break;
|
||||
}
|
||||
|
||||
// no parent match found
|
||||
else if(p == nil) {
|
||||
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 = IJSVGStyleSheetNextSelector(aSelector,_rawSelectors);
|
||||
if(IJSVGStyleSheetMatchSelector(parentNode, s) &&
|
||||
[parentNode.children containsObject:aNode]) {
|
||||
// set the new starting selector and node
|
||||
aSelector = s;
|
||||
aNode = parentNode;
|
||||
}
|
||||
|
||||
// no match found
|
||||
else {
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[selector release], selector = nil;
|
||||
@@ -23,12 +245,33 @@
|
||||
{
|
||||
selector = [string copy];
|
||||
_rawSelectors = [[NSMutableArray alloc] init];
|
||||
[self compile];
|
||||
[self _compile];
|
||||
[self _calculate];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)compile
|
||||
- (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;
|
||||
NSMutableArray * sels = [[[NSMutableArray alloc] init] autorelease];
|
||||
@@ -38,6 +281,7 @@
|
||||
for(NSUInteger i = 0; i < length; i++)
|
||||
{
|
||||
unichar c = [selector characterAtIndex:i];
|
||||
|
||||
// beginning of class
|
||||
if( c == '.' ) {
|
||||
i++;
|
||||
@@ -70,21 +314,51 @@
|
||||
}
|
||||
}
|
||||
|
||||
// space
|
||||
// white space or end of string
|
||||
else if ( c == ' ' || i == length-1 ) {
|
||||
|
||||
// add the current parsed selector into the list
|
||||
if(rawSelector != nil) {
|
||||
[sels addObject:rawSelector];
|
||||
rawSelector = nil;
|
||||
}
|
||||
|
||||
// need to skip until we find something that isnt white space....
|
||||
for( NSUInteger s = i; s < length; s++ ) {
|
||||
unichar sc = [selector characterAtIndex:s];
|
||||
if( sc != ' ' ) {
|
||||
i = --s;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// reset the raw selector
|
||||
if(!(i == length-1))
|
||||
rawSelector = [[[IJSVGStyleSheetSelectorRaw alloc] init] autorelease];
|
||||
}
|
||||
|
||||
// combinator
|
||||
else if ( c == '+' || c == '~' || c == '>' ) {
|
||||
|
||||
// set the combinator onto the selector
|
||||
rawSelector.combinator = IJSVGStyleSheetCombinatorForUnichar(c);
|
||||
rawSelector.combinatorString = [NSString stringWithFormat:@"%c",c];
|
||||
|
||||
// skip until non white space
|
||||
// need to skip until we find something that isnt white space....
|
||||
for( NSUInteger s = i+1; s < length; s++ ) {
|
||||
unichar sc = [selector characterAtIndex:s];
|
||||
if( sc != ' ' ) {
|
||||
i = --s;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// tag name / any other character
|
||||
else {
|
||||
for(NSUInteger a = i; a < length; a++ ) {
|
||||
for( NSUInteger a = i; a < length; a++ ) {
|
||||
unichar ca = [selector characterAtIndex:a];
|
||||
if([alphaNumeric characterIsMember:ca] == NO || a == length-1) {
|
||||
if( a == length-1 )
|
||||
@@ -98,85 +372,30 @@
|
||||
|
||||
// add raw selector
|
||||
if( i == length - 1 ) {
|
||||
[sels addObject:rawSelector];
|
||||
if(rawSelector != nil)
|
||||
[sels addObject:rawSelector];
|
||||
rawSelector = nil;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// now its compiled, we need to reverse the selectors
|
||||
[_rawSelectors addObjectsFromArray:[sels reverseObjectEnumerator].allObjects];
|
||||
}
|
||||
|
||||
- (BOOL)_matchesNode:(IJSVGNode *)node
|
||||
rawSelector:(IJSVGStyleSheetSelectorRaw *)rawSelector
|
||||
{
|
||||
// no need to attempt to match
|
||||
if(node.identifier == nil && node.classNameList.count == 0)
|
||||
return NO;
|
||||
|
||||
// check if the classes match the lcass
|
||||
if(rawSelector.classes.count != 0) {
|
||||
for(NSString * className in rawSelector.classes) {
|
||||
if([node.classNameList containsObject:className] == NO)
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
// check the idenfitier
|
||||
if(rawSelector.identifier != nil &&
|
||||
[rawSelector.identifier isEqualToString:node.identifier] == NO)
|
||||
return NO;
|
||||
|
||||
// check the tag
|
||||
if(rawSelector.tag != nil &&
|
||||
[rawSelector.tag isEqualToString:node.name] == NO)
|
||||
return NO;
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)matchesNode:(IJSVGNode *)node
|
||||
{
|
||||
|
||||
// check item matches first part
|
||||
if([self _matchesNode:node
|
||||
rawSelector:_rawSelectors[0]] == NO)
|
||||
return NO;
|
||||
|
||||
// only check the parents if the count has more then 1
|
||||
if(_rawSelectors.count > 1) {
|
||||
|
||||
// grab the list of remaing selectors
|
||||
NSArray * selectors = [_rawSelectors subarrayWithRange:NSMakeRange( 1, _rawSelectors.count-1)];
|
||||
for(IJSVGStyleSheetSelectorRaw * rawSelector in selectors) {
|
||||
|
||||
// set the parent node
|
||||
IJSVGNode * parent = node;
|
||||
BOOL matches = NO;
|
||||
|
||||
// interate over parents until find a match
|
||||
while(parent != nil) {
|
||||
parent = parent.parentNode;
|
||||
|
||||
// if we find a match, reset the node to being the parent
|
||||
// and go up the chain again
|
||||
if([self _matchesNode:parent
|
||||
rawSelector:rawSelector])
|
||||
{
|
||||
matches = YES;
|
||||
node = parent;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// if not match for this selector then it doesnt match
|
||||
// so return no
|
||||
if(!matches)
|
||||
return NO;
|
||||
}
|
||||
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(IJSVGStyleSheetMatchSelector(node, sel) &&
|
||||
(IJSVGStyleSheetNextSelector(sel,_rawSelectors) == nil ||
|
||||
[self _matches:node selector:sel])) {
|
||||
return YES;
|
||||
}
|
||||
return YES;
|
||||
return NO;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -10,18 +10,30 @@
|
||||
|
||||
@class IJSVGNode;
|
||||
|
||||
typedef NS_ENUM(NSUInteger, IJSVGStyleSheetSelectorCombinator) {
|
||||
IJSVGStyleSheetSelectorCombinatorDescendant, // space
|
||||
IJSVGStyleSheetSelectorCombinatorDirectDescendant, // >
|
||||
IJSVGStyleSheetSelectorCombinatorPrecededSibling, // ~
|
||||
IJSVGStyleSheetSelectorCombinatorNextSibling // +
|
||||
};
|
||||
|
||||
@interface IJSVGStyleSheetSelectorRaw : NSObject {
|
||||
|
||||
NSString * tag;
|
||||
NSString * identifier;
|
||||
|
||||
NSMutableArray * classes;
|
||||
|
||||
IJSVGStyleSheetSelectorCombinator combinator;
|
||||
NSString * combinatorString;
|
||||
|
||||
}
|
||||
|
||||
@property (nonatomic, copy) NSString * tag;
|
||||
@property (nonatomic, copy) NSString * identifier;
|
||||
@property (nonatomic, copy) NSString * combinatorString;
|
||||
@property (nonatomic, retain) NSArray * classes;
|
||||
|
||||
@property (nonatomic, assign) IJSVGStyleSheetSelectorCombinator combinator;
|
||||
- (void)addClassName:(NSString *)className;
|
||||
|
||||
@end
|
||||
|
||||
@@ -10,13 +10,14 @@
|
||||
|
||||
@implementation IJSVGStyleSheetSelectorRaw
|
||||
|
||||
@synthesize classes, identifier, tag;
|
||||
@synthesize classes, identifier, tag, combinator, combinatorString;
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
[classes release], classes = nil;
|
||||
[identifier release], identifier = nil;
|
||||
[tag release], tag = nil;
|
||||
[combinatorString release], combinatorString = nil;
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
@@ -25,6 +26,8 @@
|
||||
if( ( self = [super init] ) != nil )
|
||||
{
|
||||
classes = [[NSMutableArray alloc] init];
|
||||
combinator = IJSVGStyleSheetSelectorCombinatorDescendant;
|
||||
combinatorString = @" ";
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@@ -36,7 +39,7 @@
|
||||
|
||||
- (NSString *)description
|
||||
{
|
||||
return [NSString stringWithFormat:@"Tag: %@, Classes: %@, Identifier: %@", tag, classes, identifier];
|
||||
return [NSString stringWithFormat:@"Combinator: %@, Tag: %@, Classes: %@, Identifier: %@", combinatorString, tag, classes, identifier];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Reference in New Issue
Block a user