SVG and m4 fractals

Accroître le pouvoir des languages déficients.

Yesod logo made in SVG and m4

tlàl : Voilà comment faire des fractales avec m4 et SVG.

You might want to know how I made the logo for yesod in my preceding post.

First, I hate with passion most XML based languages. Because XML wasn’t created to be exposed to developer. XML should be read and generated by some software. But you should never read or edit it manually.

The XSLT Example

The main language where XML fail terribly is XSLT. XPath is very good, but XSLT use one of the worst syntax I ever crossed in my life of developer.

In order to reduce the verbosity of such so bad languages, there is a way. m4. Yes, the preprocessor you use when you program in C and C++.

Here are some example:

  • Variable, instead of writing the natural myvar = value, here is the xslt way of doing this:
<xsl:variable name="myvar" select="value"/>
  • Printing something. Instead of print "Hello world!" here is the xslt equivalent:
<xsl:text 
    disable-output-escaping="yes"><![CDATA[Hello world!
]]></xsl:text>
  • printing the value of a variable, instead of print myvar the xslt is:
<xslt:value-of select="myvar"/>
  • Just try to imagine how verbose it is to declare a function with this language.

The cure (m4 to the rescue)

<?xml version="1.0" standalone="yes"?> <!-- YES its XML -→
<!-- ← start a comment, then write some m4 directives:

define(`ydef',`<xsl:variable name="$1" select="$2"/>')
define(`yprint',`<xsl:text disable-output-escaping="yes"><![CDATA[$1]]></xsl:text>')
define(`yshow',`<xsl:value-of select="$1"/>')

-→
<!-- Yes, XML sucks to be read -→
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- And it sucks even more to edit -→
<xsl:template match="/">
    ydef(myvar,value)
    yprint(Hello world!)
    yshow(myvar)
</xsl:template>

Now just compile this file:

m4 myfile.m4 > myfile.xslt

And you can profit! Now xslt is more readable and easier to edit!

The cool part: Fractals!

SVG is a format to display vector graphics, it even support animations. At its beginning some people believed it would be the new Flash. Apparently, it will be more canvas + js.

Let me show you the result:

Yesod logo made in SVG and m4

The positionning of the “esod” text with regards to the reversed “λ” was done by changing position in firebug. I didn’t had to manually regenerate to test.

Making such a fractal is mostly:

  1. take a root element
  2. duplicate and transform it (scaling, translating, rotate)
  3. the result is a sub new element.
  4. repeat from 2 but by taking the sub new element as new root.
  5. Stop when recursion is deep enough.

If I had to do this for each step, I had make a lot of copy/paste in my SVG, because the transformation is always the same, but I cannot say, use transformation named “titi”. Then instead of manually copying some XML, I used m4

and here is the commented code:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!--
     M4 Macros
define(`YTRANSFORMONE', `scale(.43) translate(-120,-69) rotate(-10)')
define(`YTRANSFORMTWO', `scale(.43) translate(-9,-67.5) rotate(10)')
define(`YTRANSFORMTHREE', `scale(.43) translate(53,41) rotate(120)')
define(`YGENTRANSFORM', `translate(364,274) scale(3)')
define(`YTRANSCOMPLETE', `
    <g id="level_$1">
        <use style="opacity: .8" transform="YTRANSFORMONE" xlink:href="#level_$2" />
        <use style="opacity: .8" transform="YTRANSFORMTWO" xlink:href="#level_$2" />
        <use style="opacity: .8" transform="YTRANSFORMTHREE" xlink:href="#level_$2" />
    </g>
    <use transform="YGENTRANSFORM" xlink:href="#level_$1" />
')
 -→
<svg 
    xmlns="http://www.w3.org/2000/svg" 
    xmlns:xlink="http://www.w3.org/1999/xlink"
    x="64" y="64" width="512" height="512" viewBox="64 64 512 512"
    id="svg2" version="1.1">
    <g id="level_0"> <!-- some group, if I want to add other elements -→
        <!-- the text "λ" -→
        <text id="lambda" 
            fill="#333" style="font-family:Ubuntu; font-size: 100px"
            transform="rotate(180)">λ</text>
    </g>
    <!-- the text "esod" -→
    <text 
        fill="#333" 
        style="font-family:Ubuntu; font-size: 28px; letter-spacing: -0.10em" 
        x="-17.3" 
        y="69" 
        transform="YGENTRANSFORM">esod</text>
    <!-- ROOT ELEMENT -→
    <use transform="YGENTRANSFORM" xlink:href="#level_0" />

    YTRANSCOMPLETE(1,0) <!-- First recursion -→
    YTRANSCOMPLETE(2,1) <!-- deeper -→
    YTRANSCOMPLETE(3,2) <!-- deeper -→
    YTRANSCOMPLETE(4,3) <!-- even deeper -→
    YTRANSCOMPLETE(5,4) <!-- Five level seems enough -→
</svg>

and I compiled it to svg and then to png with:

m4 yesodlogo.m4 > yesodlogo.svg && convert yesodlogo.svg yesodlogo.png

Conclusion

It was fun to make a fractal in svg, but the interesting part is how to augment the power of a language using this preprocessor method. I used the xslt trick at work for example.

commentaires

Droits de reproduction ©, Yann Esposito
Écrit le : 20/10/2011 modifié le : 21/10/2011
Site entièrement réalisé avec Vim et nanoc
Validation [xhtml] . [css] . [rss]