SVGKParserSVG.m 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. #import "SVGKParserSVG.h"
  2. #import "SVGSVGElement.h"
  3. #import "SVGCircleElement.h"
  4. #import "SVGClipPathElement.h"
  5. #import "SVGDefsElement.h"
  6. #import "SVGDescriptionElement.h"
  7. //#import "SVGKSource.h"
  8. #import "SVGEllipseElement.h"
  9. #import "SVGGElement.h"
  10. #import "SVGImageElement.h"
  11. #import "SVGLineElement.h"
  12. #import "SVGPathElement.h"
  13. #import "SVGPolygonElement.h"
  14. #import "SVGPolylineElement.h"
  15. #import "SVGRectElement.h"
  16. #import "SVGSwitchElement.h"
  17. #import "SVGTitleElement.h"
  18. #import "SVGTextElement.h"
  19. #import "TinySVGTextAreaElement.h"
  20. #import "SVGDocument_Mutable.h"
  21. #import "SVGKDefine_Private.h"
  22. @interface SVGKParserSVG ()
  23. @property (nonatomic) NSArray *supportedNamespaces;
  24. @property (nonatomic) NSDictionary *elementMap;
  25. @end
  26. @implementation SVGKParserSVG
  27. - (NSDictionary *)elementMap {
  28. if (!_elementMap) {
  29. _elementMap = [NSDictionary dictionaryWithObjectsAndKeys:
  30. [SVGSVGElement class], @"svg",
  31. [SVGCircleElement class], @"circle",
  32. [SVGDescriptionElement class], @"description",
  33. [SVGEllipseElement class], @"ellipse",
  34. [SVGGElement class], @"g",
  35. [SVGClipPathElement class], @"clipPath",
  36. [SVGImageElement class], @"image",
  37. [SVGLineElement class], @"line",
  38. [SVGPathElement class], @"path",
  39. [SVGPolygonElement class], @"polygon",
  40. [SVGPolylineElement class], @"polyline",
  41. [SVGRectElement class], @"rect",
  42. [SVGSwitchElement class], @"switch",
  43. [SVGTitleElement class], @"title",
  44. [SVGTextElement class], @"text",
  45. [TinySVGTextAreaElement class], @"textArea",
  46. nil];
  47. }
  48. return _elementMap;
  49. }
  50. -(NSArray *)supportedNamespaces
  51. {
  52. if( _supportedNamespaces == nil )
  53. _supportedNamespaces = @[@"http://www.w3.org/2000/svg"];
  54. return _supportedNamespaces;
  55. }
  56. /** "tags supported" is exactly the set of all SVGElement subclasses that already exist */
  57. -(NSArray*) supportedTags
  58. {
  59. return [self.elementMap allKeys];
  60. }
  61. - (Node*) handleStartElement:(NSString *)name document:(SVGKSource*) SVGKSource namePrefix:(NSString*)prefix namespaceURI:(NSString*) XMLNSURI attributes:(NSMutableDictionary *)attributes parseResult:(SVGKParseResult *)parseResult parentNode:(Node*) parentNode
  62. {
  63. if( [[self supportedNamespaces] containsObject:XMLNSURI] )
  64. {
  65. Class elementClass = [self.elementMap objectForKey:name];
  66. if (!elementClass) {
  67. elementClass = [SVGElement class];
  68. SVGKitLogWarn(@"Support for '%@' element has not been implemented", name);
  69. }
  70. /**
  71. NB: following the SVG Spec, it's critical that we ONLY use the DOM methods for creating
  72. basic 'Element' nodes.
  73. Our SVGElement root class has an implementation of init that delegates to the same
  74. private methods that the DOM methods use, so it's safe...
  75. FIXME: ...but in reality we ought to be using the DOMDocument createElement/NS methods, although "good luck" trying to find a DOMDocument if your SVG is embedded inside a larger XML document :(
  76. */
  77. NSString* qualifiedName = (prefix == nil) ? name : [NSString stringWithFormat:@"%@:%@", prefix, name];
  78. /** NB: must supply a NON-qualified name if we have no specific prefix here ! */
  79. SVGElement *element = [[elementClass alloc] initWithQualifiedName:qualifiedName inNameSpaceURI:XMLNSURI attributes:attributes];
  80. /** NB: all the interesting handling of shared / generic attributes - e.g. the whole of CSS styling etc - takes place in this method: */
  81. [element postProcessAttributesAddingErrorsTo:parseResult];
  82. /** special case: <svg:svg ... version="XXX"> */
  83. if( [@"svg" isEqualToString:name] )
  84. {
  85. ((SVGSVGElement *) element).source = SVGKSource;
  86. NSString* svgVersion = nil;
  87. /** According to spec, if the first XML node is an SVG node, then it
  88. becomes TWO THINGS:
  89. - An SVGSVGElement
  90. *and*
  91. - An SVGDocument
  92. - ...and that becomes "the root SVGDocument"
  93. If it's NOT the first XML node, but it's the first SVG node, then it ONLY becomes:
  94. - An SVGSVGElement
  95. If it's NOT the first SVG node, then it becomes:
  96. - An SVGSVGElement
  97. *and*
  98. - An SVGDocument
  99. Yes. It's Very confusing! Go read the SVG Spec!
  100. */
  101. BOOL generateAnSVGDocument = FALSE;
  102. BOOL overwriteRootSVGDocument = FALSE;
  103. BOOL overwriteRootOfTree = FALSE;
  104. if( parentNode == nil )
  105. {
  106. /** This start element is the first item in the document
  107. PS: xcode has a new bug for Lion: it can't format single-line comments with two asterisks. This line added because Xcode sucks.
  108. */
  109. generateAnSVGDocument = overwriteRootSVGDocument = overwriteRootOfTree = TRUE;
  110. }
  111. else if( parseResult.rootOfSVGTree == nil )
  112. {
  113. /** It's not the first XML, but it's the first SVG node */
  114. overwriteRootOfTree = TRUE;
  115. }
  116. else
  117. {
  118. /** It's not the first SVG node */
  119. // ... so: do nothing special
  120. }
  121. /**
  122. Handle the complex stuff above about SVGDocument and SVG node
  123. */
  124. if( overwriteRootOfTree )
  125. {
  126. parseResult.rootOfSVGTree = (SVGSVGElement*) element;
  127. /** Post-processing of the ROOT SVG ONLY (doesn't apply to embedded SVG's )
  128. */
  129. if ((svgVersion = [attributes objectForKey:@"version"])) {
  130. SVGKSource.svgLanguageVersion = svgVersion;
  131. }
  132. }
  133. if( generateAnSVGDocument )
  134. {
  135. NSAssert( [element isKindOfClass:[SVGSVGElement class]], @"Trying to create a new internal SVGDocument from a Node that is NOT of type SVGSVGElement (tag: svg). Node was of type: %@", NSStringFromClass([element class]));
  136. SVGDocument* newDocument = [[SVGDocument alloc] init];
  137. newDocument.rootElement = (SVGSVGElement*) element;
  138. if( overwriteRootSVGDocument )
  139. {
  140. parseResult.parsedDocument = newDocument;
  141. }
  142. else
  143. {
  144. NSAssert( FALSE, @"Currently not supported: multiple SVG Document nodes in a single SVG file" );
  145. }
  146. }
  147. }
  148. return element;
  149. }
  150. return nil;
  151. }
  152. -(void)handleEndElement:(Node *)newNode document:(SVGKSource *)document parseResult:(SVGKParseResult *)parseResult
  153. {
  154. }
  155. @end