SVGKParserDefsAndUse.m 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. #import "SVGKParserDefsAndUse.h"
  2. #import "Node.h"
  3. #import "SVGKSource.h"
  4. #import "SVGKParseResult.h"
  5. #import "SVGDefsElement.h"
  6. #import "SVGUseElement.h"
  7. #import "SVGUseElement_Mutable.h"
  8. #import "SVGElementInstance.h"
  9. #import "SVGElementInstance_Mutable.h"
  10. #import "SVGElementInstanceList.h"
  11. #import "SVGElement_ForParser.h"
  12. @implementation SVGKParserDefsAndUse
  13. -(NSArray*) supportedNamespaces
  14. {
  15. return [NSArray arrayWithObjects:
  16. @"http://www.w3.org/2000/svg",
  17. nil];
  18. }
  19. /** "tags supported" is exactly the set of all SVGElement subclasses that already exist */
  20. -(NSArray*) supportedTags
  21. {
  22. return [NSMutableArray arrayWithObjects: @"defs", @"use", nil];
  23. }
  24. -(SVGElementInstance*) convertSVGElementToElementInstanceTree:(SVGElement*) original outermostUseElement:(SVGUseElement*) outermostUseElement
  25. {
  26. SVGElementInstance* instance = [[SVGElementInstance alloc] init];
  27. instance.correspondingElement = original;
  28. instance.correspondingUseElement = outermostUseElement;
  29. for( Node* subNode in original.childNodes )
  30. {
  31. if( [subNode isKindOfClass:[SVGElement class]])
  32. {
  33. SVGElement* subElement = (SVGElement*) subNode;
  34. SVGElementInstance *newSubInstance = [self convertSVGElementToElementInstanceTree:subElement outermostUseElement:outermostUseElement];
  35. newSubInstance.parentNode = instance; // side-effect: automatically adds sub as child
  36. }
  37. }
  38. return instance;
  39. }
  40. - (Node*) handleStartElement:(NSString *)name document:(SVGKSource*) SVGKSource namePrefix:(NSString*)prefix namespaceURI:(NSString*) XMLNSURI attributes:(NSMutableDictionary *)attributes parseResult:(SVGKParseResult *)parseResult parentNode:(Node*) parentNode
  41. {
  42. if( [[self supportedNamespaces] containsObject:XMLNSURI] )
  43. {
  44. NSString* qualifiedName = (prefix == nil) ? name : [NSString stringWithFormat:@"%@:%@", prefix, name];
  45. if( [name isEqualToString:@"defs"])
  46. {
  47. /** NB: must supply a NON-qualified name if we have no specific prefix here ! */
  48. SVGDefsElement *element = [[SVGDefsElement alloc] initWithQualifiedName:qualifiedName inNameSpaceURI:XMLNSURI attributes:attributes];
  49. return element;
  50. }
  51. else if( [name isEqualToString:@"use"])
  52. {
  53. /** NB: must supply a NON-qualified name if we have no specific prefix here ! */
  54. SVGUseElement *useElement = [[SVGUseElement alloc] initWithQualifiedName:qualifiedName inNameSpaceURI:XMLNSURI attributes:attributes];
  55. [useElement postProcessAttributesAddingErrorsTo:parseResult]; // handles "transform" and "style"
  56. if( [attributes valueForKey:@"x"] != nil )
  57. useElement.x = [SVGLength svgLengthFromNSString:[((Attr*)[attributes valueForKey:@"x"]) value]];
  58. if( [attributes valueForKey:@"y"] != nil )
  59. useElement.y = [SVGLength svgLengthFromNSString:[((Attr*)[attributes valueForKey:@"y"]) value]];
  60. if( [attributes valueForKey:@"width"] != nil )
  61. useElement.width = [SVGLength svgLengthFromNSString:[((Attr*)[attributes valueForKey:@"width"]) value]];
  62. if( [attributes valueForKey:@"height"] != nil )
  63. useElement.height = [SVGLength svgLengthFromNSString:[((Attr*)[attributes valueForKey:@"height"]) value]];
  64. NSString* hrefAttribute = [useElement getAttributeNS:@"http://www.w3.org/1999/xlink" localName:@"href"];
  65. NSAssert( [hrefAttribute length] > 0, @"Found an SVG <use> tag that has no 'xlink:href' attribute. File is invalid / don't know how to parse this" );
  66. if( [hrefAttribute length] > 0 )
  67. {
  68. NSString* linkHref = [((Attr*)[attributes valueForKey:@"xlink:href"]) value];
  69. /** support `url(#id) funcIRI as well to follow SVG spec` */
  70. if ([linkHref hasPrefix:@"url"]) {
  71. NSRange range = NSMakeRange(4, linkHref.length - 5);
  72. linkHref = [linkHref substringWithRange:range];
  73. }
  74. NSAssert( [linkHref hasPrefix:@"#"], @"Not supported: <use> tags that declare an href to something that DOESN'T begin with #. Href supplied = %@", linkHref );
  75. linkHref = [linkHref substringFromIndex:1];
  76. /** have to find the node in the DOM tree with id = xlink:href's value */
  77. SVGElement* linkedElement = (SVGElement*) [parseResult.parsedDocument getElementById:linkHref];
  78. NSAssert( linkedElement != nil, @"Found an SVG <use> tag that points to a non-existent element. Missing element: id = %@", linkHref );
  79. useElement.instanceRoot = [self convertSVGElementToElementInstanceTree:linkedElement outermostUseElement:useElement];
  80. }
  81. return useElement;
  82. }
  83. }
  84. return nil;
  85. }
  86. -(void)handleEndElement:(Node *)newNode document:(SVGKSource *)document parseResult:(SVGKParseResult *)parseResult
  87. {
  88. }
  89. @end