4

Is there an existing renderer that can intelligently handle a recursive (that is, self-referential) svg file?

For example, this code from this question:

<svg width="100%" height="100%" viewBox="-100 -100 200 200" version="1.1"
     xmlns="http://www.w3.org/2000/svg"
     xmlns:xlink="http://www.w3.org/1999/xlink">
  <circle cx="-50" cy="-50" r="30" style="fill:red" />
  <image x="10" y="20" width="80" height="80" xlink:href="recursion.svg" />
</svg>

is not rendered properly in Firefox, Chrome, or Inkscape - but it doesn't seem that hard to make a renderer that keeps track of how many time it's opened a particular file, and stop after some sane number of iterations...

(If one doesn't exist, where might I go looking if I wanted to code one myself?)

Community
  • 1
  • 1
linkhyrule5
  • 871
  • 13
  • 29
  • 1
    Circular dependencies like these are considered errors according to the SVG spec, and UAs are required to detect and break out of such loops. At what point they break out is not defined, see e.g http://www.w3.org/TR/SVGTiny12/linking.html#circular-iri. – Erik Dahlström Mar 28 '14 at 11:28
  • Phooey. Guess I'll try and write my own, then... – linkhyrule5 Mar 28 '14 at 18:16

2 Answers2

5

You can reference a definition repeatedly. Though this isn't infinite recursion, it is much simpler than the nesting method referenced in the other answer/comments.

See these examples (Example 1, Example 2) by Dudley Storey that I found:

svg {
display: block;
width: 40%;
margin: 0 auto;
}
polygon, line { 
fill: none; stroke: #32679D; 
stroke-width: 5px; 
vector-effect: non-scaling-stroke;
}
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 750 750">
<defs>
 <g id="hex" transform="rotate(30 375 375)">
  <polygon points="229.3,627.5 83.6,375.5 229.3,123.5 520.7,123.5 666.4,375.5 520.7,627.5" />
  <line x1="229.3" y1="123.5" x2="520.7" y2="627.5"/>
  <line x1="666" y1="375.5" x2="84" y2="375.5"/>
  <line x1="520.7" y1="123.5" x2="229.3" y2="627.5"/>
 </g>
</defs> 
<use xlink:href="#hex" />
<use xlink:href="#hex" transform="translate(470.75, 172) scale(.25)" />
<use xlink:href="#hex" transform="translate(470.75, 390.5) scale(.25)" />
<use xlink:href="#hex" transform="translate(91.75, 172) scale(.25)" /> 
<use xlink:href="#hex" transform="translate(91.75, 390.5) scale(.25)" />  
<use xlink:href="#hex" transform="translate(155, 281.25) scale(.25)" />
<use xlink:href="#hex" transform="translate(407.5, 281.25) scale(.25)" />
<use xlink:href="#hex" transform="translate(281.25, 63.5) scale(.25)" />
<use xlink:href="#hex" transform="translate(281.25, 500) scale(.25)" />
<use xlink:href="#hex" transform="translate(344.5, 172) scale(.25)" />
<use xlink:href="#hex" transform="translate(218, 172) scale(.25)" />
<use xlink:href="#hex" transform="translate(344.5, 390.5) scale(.25)" />
<use xlink:href="#hex" transform="translate(218, 390.5) scale(.25)" />
</svg>

It is possible to get more complicated by nesting:

body {
margin: 0;
min-height: 100vh;
background: #fff;
}
svg {
display: block;
width: 100%;
min-height: 100vh;
}
polygon { 
fill: none; 
stroke: rgba(0,0,0,0.3); 
stroke-width: 3; 
}
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<defs>
 <pattern id="tesselation" patternUnits="userSpaceOnUse" width="562.6" height="325" patternTransform="scale(.75)">
 <g id="group">
  <polygon points="281.4,0 375.2, 162.5 281.4, 325 187, 161.5" id="base" />
  <g id="basetwist" >
   <use xlink:href="#base" transform="rotate(90 280 162.5) translate(116, 67) scale(.58)" id="base_level1" />
   <g id="diamond"> 
    <use xlink:href="#base" transform="translate(188.85, 108) scale(.33)" id="base_level2" />
    <g id="sidediamond">
     <use xlink:href="#base_level1" transform="translate(188.85, 108) scale(.33)" id="base_level3" />
      <use xlink:href="#base_level2" transform="translate(188.85, 108) scale(.33)" id="base_level4" />
       <use xlink:href="#base_level3" transform="translate(188.85, 108) scale(.33)" /> 
        <use xlink:href="#base_level4" transform="translate(188.85, 108) scale(.33)" />
    </g>
   </g>
   <use xlink:href="#sidediamond" transform="translate(62,0)" />
   <use xlink:href="#sidediamond" transform="translate(-62,0)" />
   <use xlink:href="#diamond" transform="translate(0,-107)" />
   <use xlink:href="#diamond" transform="translate(0, 107)" />
  </g>
 </g>
 <g id="tesselation">
  <use xlink:href="#group" />
  <use xlink:href="#group" transform="rotate(60 281 0)" />
  <use xlink:href="#group" transform="rotate(-60 281 0)" />
  <use xlink:href="#group" transform="rotate(-60 281 325)" />
  <use xlink:href="#group" transform="rotate(60 281 325)" />
  <g id="vert">
   <use xlink:href="#group" transform="translate(-282, -162)" />
   <use xlink:href="#group" transform="translate(-282, 162)" />
  </g>
  <use xlink:href="#vert" transform="translate(564, 0)" />
 </g>
 </pattern>
</defs>
<rect width="100%" height="100%" fill="url(#tesselation)" /> 
</svg>

EDIT: He has blog posts describing how he created them:

mbomb007
  • 3,788
  • 3
  • 39
  • 68
  • As a side note, I can't get the first leading "column" of tabs in the code blocks to display properly. If someone can figure that out, an edit would be appreciated. – mbomb007 Mar 12 '18 at 20:48
0

In order to protect user's privacy image files must be self contained. I.e. If you're referencing an SVG file from an image tag and that SVG file itself contains images then the image data must be specified as a data URL.

You can nest images as deep as you want using data URLs, though it's not really recursion as you have to provide a complete copy each time and your data URLs will grow very large.

Robert Longson
  • 118,664
  • 26
  • 252
  • 242
  • I'm sorry, I don't really understand this answer. – linkhyrule5 Mar 27 '14 at 17:33
  • First - I'm not expecting this to be used in a browser or an HTML document at all, this is intended to be standalone. Second - what do you mean by a data URL? And does this mean that in general, I can't easily nest complex image files? – linkhyrule5 Mar 27 '14 at 17:34
  • Here's an example of SVGs as data URLs https://codepen.io/tigt/post/optimizing-svgs-in-data-uris You can easily nest a complex SVG, but you can't easily do multiple layers of nesting. – nHaskins Feb 10 '17 at 19:18