238 lines
21 KiB
HTML
238 lines
21 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<title>YBlog - Increase the power of deficient languages.</title>
|
||
<meta name="keywords" content="m4, SVG, XSLT, XML, design, programming, fractal" />
|
||
|
||
<link rel="shortcut icon" type="image/x-icon" href="../../../../Scratch/img/favicon.ico" />
|
||
<link rel="stylesheet" type="text/css" href="/css/y.css" />
|
||
<link rel="stylesheet" type="text/css" href="/css/legacy.css" />
|
||
<link rel="alternate" type="application/rss+xml" title="RSS" href="/rss.xml" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<link rel="apple-touch-icon" href="../../../../Scratch/img/about/FlatAvatar@2x.png" />
|
||
<!--[if lt IE 9]>
|
||
<script src="http://ie7-js.googlecode.com/svn/version/2.1(beta4)/IE9.js"></script>
|
||
<![endif]-->
|
||
<!-- IndieAuth -->
|
||
<link href="https://twitter.com/yogsototh" rel="me">
|
||
<link href="https://github.com/yogsototh" rel="me">
|
||
<link href="mailto:yann.esposito@gmail.com" rel="me">
|
||
<link rel="pgpkey" href="../../../../pubkey.txt">
|
||
</head>
|
||
<body lang="en" class="article">
|
||
<div id="content">
|
||
<div id="header">
|
||
<div id="choix">
|
||
<span id="choixlang">
|
||
<a href="../../../../Scratch/fr/blog/SVG-and-m4-fractals/">French</a>
|
||
</span>
|
||
<span class="tomenu"><a href="#navigation">↓ Menu ↓</a></span>
|
||
<span class="flush"></span>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="titre">
|
||
<h1>Increase the power of deficient languages.</h1>
|
||
<h2>Fractals with SVG and m4</h2>
|
||
|
||
</div>
|
||
<div class="flush"></div>
|
||
<div id="afterheader" class="article">
|
||
<div class="corps">
|
||
<div>
|
||
<img src="../../../../Scratch/img/blog/SVG-and-m4-fractals/main.png" alt="Yesod logo made in SVG and m4" />
|
||
</div>
|
||
<div class="intro">
|
||
<p><span class="sc"><abbr title="Too long; didn't read">tl;dr</abbr>: </span> How to use m4 to increase the power of deficient languages. Two examples: improve <span class="sc">xslt</span> syntax and make fractal with <span class="sc">svg</span>.</p>
|
||
</div>
|
||
<p><span class="sc">xml</span> was a very nice idea about structuring data. Some people where so enthusiastic about <span class="sc">xml</span> they saw it everywhere. The idea was: the future is <span class="sc">xml</span>. Then some believed it would be a good idea to invent many <span class="sc">xml</span> compatible format and even programming languages with <span class="sc">xml</span> syntax.</p>
|
||
<p>Happy! Happy! Joy! Joy!</p>
|
||
<p>Unfortunately, <span class="sc">xml</span> was made to transfert structured data. Not a format a human should see or edit directly. The sad reality is <span class="sc">xml</span> syntax is simply verbose and ugly. Most of the time it shouldn’t be a problem, as nobody should see it. In a perfect nice world, we should never deal directly with <span class="sc">xml</span> but only use software which deal with it for us. Guess what? Our world isn’t perfect. Too sad, a bunch of developer have to deal directly with this ugly <span class="sc">xml</span>.</p>
|
||
<p>Unfortunately <span class="sc">xml</span> isn’t the only case of misused format I know. You have many format for which it would be very nice to add variables, loops, functions…</p>
|
||
<p>If like me you hate with passion <span class="sc">xslt</span> or writing <span class="sc">xml</span>, I will show you how you could deal with this bad format or language.</p>
|
||
<h2 id="the-xslt-example">The <span class="sc">xslt</span> Example</h2>
|
||
<p>Let’s start by the worst case of misused <span class="sc">xml</span> I know: <span class="sc">xslt</span>. Any developer who had to deal with <span class="sc">xslt</span> know how horrible it is.</p>
|
||
<p>In order to reduce the verbosity of such a bad languages, there is a way. <strong><code>m4</code></strong>. Yes, the preprocessor you use when you program in <code>C</code> and <code>C++</code>.</p>
|
||
<p>Here are some example:</p>
|
||
<ul>
|
||
<li>Variable, instead of writing the natural <code>myvar = value</code>, here is the <sc>xslt</sc> way of doing this:</li>
|
||
</ul>
|
||
<div class="sourceCode" id="cb1"><pre class="sourceCode xml"><code class="sourceCode xml"><a class="sourceLine" id="cb1-1" title="1"><span class="kw"><xsl:variable</span><span class="ot"> name=</span><span class="st">"myvar"</span><span class="ot"> select=</span><span class="st">"value"</span><span class="kw">/></span></a></code></pre></div>
|
||
<ul>
|
||
<li>Printing something. Instead of <code>print "Hello world!"</code> here is the <sc>xslt</sc> equivalent:</li>
|
||
</ul>
|
||
<div class="sourceCode" id="cb2"><pre class="sourceCode xml"><code class="sourceCode xml"><a class="sourceLine" id="cb2-1" title="1"><span class="kw"><xsl:text</span> </a>
|
||
<a class="sourceLine" id="cb2-2" title="2"><span class="ot"> disable-output-escaping=</span><span class="st">"yes"</span><span class="kw">></span><span class="bn"><![CDATA[</span>Hello world!</a>
|
||
<a class="sourceLine" id="cb2-3" title="3"><span class="bn">]]></span><span class="kw"></xsl:text></span></a></code></pre></div>
|
||
<ul>
|
||
<li>printing the value of a variable, instead of <code>print myvar</code> the <sc>xslt</sc> is:</li>
|
||
</ul>
|
||
<div class="sourceCode" id="cb3"><pre class="sourceCode xml"><code class="sourceCode xml"><a class="sourceLine" id="cb3-1" title="1"><span class="kw"><xslt:value-of</span><span class="ot"> select=</span><span class="st">"myvar"</span><span class="kw">/></span></a></code></pre></div>
|
||
<ul>
|
||
<li>Just try to imagine how verbose it is to declare a function with this language.</li>
|
||
</ul>
|
||
<h2 id="the-cure-m4-to-the-rescue">The cure (m4 to the rescue)</h2>
|
||
<div class="sourceCode" id="cb4"><pre class="sourceCode xml"><code class="sourceCode xml"><a class="sourceLine" id="cb4-1" title="1"><span class="kw"><?xml</span> version="1.0" standalone="yes"<span class="kw">?></span> <span class="co"><!-- YES its <span class="sc">xml</span> --></span></a>
|
||
<a class="sourceLine" id="cb4-2" title="2"><span class="co"><!-- ← start a comment, then write some m4 directives:</span></a>
|
||
<a class="sourceLine" id="cb4-3" title="3"></a>
|
||
<a class="sourceLine" id="cb4-4" title="4"><span class="co">define(`ydef',`<xsl:variable name="$1" select="$2"/>')</span></a>
|
||
<a class="sourceLine" id="cb4-5" title="5"><span class="co">define(`yprint',`<xsl:text disable-output-escaping="yes"><![CDATA[$1]]></xsl:text>')</span></a>
|
||
<a class="sourceLine" id="cb4-6" title="6"><span class="co">define(`yshow',`<xsl:value-of select="$1"/>')</span></a>
|
||
<a class="sourceLine" id="cb4-7" title="7"></a>
|
||
<a class="sourceLine" id="cb4-8" title="8"><span class="co">--></span></a>
|
||
<a class="sourceLine" id="cb4-9" title="9"><span class="co"><!-- Yes, <span class="sc">xml</span> sucks to be read --></span></a>
|
||
<a class="sourceLine" id="cb4-10" title="10"><span class="kw"><xsl:stylesheet</span><span class="ot"> version=</span><span class="st">"1.0"</span><span class="ot"> xmlns:xsl=</span><span class="st">"http://www.w3.org/1999/XSL/Transform"</span><span class="kw">></span></a>
|
||
<a class="sourceLine" id="cb4-11" title="11"><span class="co"><!-- And it sucks even more to edit --></span></a>
|
||
<a class="sourceLine" id="cb4-12" title="12"><span class="kw"><xsl:template</span><span class="ot"> match=</span><span class="st">"/"</span><span class="kw">></span></a>
|
||
<a class="sourceLine" id="cb4-13" title="13"> ydef(myvar,value)</a>
|
||
<a class="sourceLine" id="cb4-14" title="14"> yprint(Hello world!)</a>
|
||
<a class="sourceLine" id="cb4-15" title="15"> yshow(myvar)</a>
|
||
<a class="sourceLine" id="cb4-16" title="16"><span class="kw"></xsl:template></span></a></code></pre></div>
|
||
<p>Now just compile this file:</p>
|
||
<div class="sourceCode" id="cb5"><pre class="sourceCode zsh"><code class="sourceCode zsh"><a class="sourceLine" id="cb5-1" title="1"><span class="kw">m4</span> myfile.m4 <span class="kw">></span> myfile.xslt</a></code></pre></div>
|
||
<p>Profit! Now <sc>xslt</sc> is more readable and easier to edit!</p>
|
||
<h2 id="the-cool-part-fractals">The cool part: Fractals!</h2>
|
||
<p><span class="sc">svg</span> is an <span class="sc">xml</span> format used to represent 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.</p>
|
||
<p>Let me show you the result:</p>
|
||
<a href="../../../../Scratch/img/blog/SVG-and-m4-fractals/main.svg">
|
||
<div>
|
||
<img src="../../../../Scratch/img/blog/SVG-and-m4-fractals/main.png" alt="Yesod logo made in SVG and m4" />
|
||
</div>
|
||
<p>Click to view directly the <span class="sc">svg</span>. It might slow down your computers if you have an old one. </a></p>
|
||
<p>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.</p>
|
||
<p>Making such a fractal is mostly:</p>
|
||
<ol type="1">
|
||
<li>take a root element</li>
|
||
<li>duplicate and transform it (scaling, translating, rotate)</li>
|
||
<li>the result is a sub new element.</li>
|
||
<li>repeat from 2 but by taking the sub new element as new root.</li>
|
||
<li>Stop when recursion is deep enough.</li>
|
||
</ol>
|
||
<p>If I had to do this for each step, I had make a lot of copy/paste in my <span class="sc">svg</span>, because the transformation is always the same, but I cannot say, use transformation named “titi”. Then instead of manually copying some <span class="sc">xml</span>, I used m4</p>
|
||
<p>and here is the commented code:</p>
|
||
<div class="sourceCode" id="cb6"><pre class="sourceCode xml"><code class="sourceCode xml"><a class="sourceLine" id="cb6-1" title="1"><span class="kw"><?xml</span> version="1.0" encoding="UTF-8" standalone="no"<span class="kw">?></span></a>
|
||
<a class="sourceLine" id="cb6-2" title="2"><span class="co"><!--</span></a>
|
||
<a class="sourceLine" id="cb6-3" title="3"><span class="co"> M4 Macros</span></a>
|
||
<a class="sourceLine" id="cb6-4" title="4"><span class="co">define(`YTRANSFORMONE', `scale(.43) translate(-120,-69) rotate(-10)')</span></a>
|
||
<a class="sourceLine" id="cb6-5" title="5"><span class="co">define(`YTRANSFORMTWO', `scale(.43) translate(-9,-67.5) rotate(10)')</span></a>
|
||
<a class="sourceLine" id="cb6-6" title="6"><span class="co">define(`YTRANSFORMTHREE', `scale(.43) translate(53,41) rotate(120)')</span></a>
|
||
<a class="sourceLine" id="cb6-7" title="7"><span class="co">define(`YGENTRANSFORM', `translate(364,274) scale(3)')</span></a>
|
||
<a class="sourceLine" id="cb6-8" title="8"><span class="co">define(`YTRANSCOMPLETE', `</span></a>
|
||
<a class="sourceLine" id="cb6-9" title="9"><span class="co"> <g id="level_$1"></span></a>
|
||
<a class="sourceLine" id="cb6-10" title="10"><span class="co"> <use style="opacity: .8" transform="YTRANSFORMONE" xlink:href="#level_$2" /></span></a>
|
||
<a class="sourceLine" id="cb6-11" title="11"><span class="co"> <use style="opacity: .8" transform="YTRANSFORMTWO" xlink:href="#level_$2" /></span></a>
|
||
<a class="sourceLine" id="cb6-12" title="12"><span class="co"> <use style="opacity: .8" transform="YTRANSFORMTHREE" xlink:href="#level_$2" /></span></a>
|
||
<a class="sourceLine" id="cb6-13" title="13"><span class="co"> </g></span></a>
|
||
<a class="sourceLine" id="cb6-14" title="14"><span class="co"> <use transform="YGENTRANSFORM" xlink:href="#level_$1" /></span></a>
|
||
<a class="sourceLine" id="cb6-15" title="15"><span class="co">')</span></a>
|
||
<a class="sourceLine" id="cb6-16" title="16"><span class="co"> --></span></a>
|
||
<a class="sourceLine" id="cb6-17" title="17"><span class="kw"><svg</span> </a>
|
||
<a class="sourceLine" id="cb6-18" title="18"><span class="ot"> xmlns=</span><span class="st">"http://www.w3.org/2000/svg"</span> </a>
|
||
<a class="sourceLine" id="cb6-19" title="19"><span class="ot"> xmlns:xlink=</span><span class="st">"http://www.w3.org/1999/xlink"</span></a>
|
||
<a class="sourceLine" id="cb6-20" title="20"><span class="ot"> x=</span><span class="st">"64"</span><span class="ot"> y=</span><span class="st">"64"</span><span class="ot"> width=</span><span class="st">"512"</span><span class="ot"> height=</span><span class="st">"512"</span><span class="ot"> viewBox=</span><span class="st">"64 64 512 512"</span></a>
|
||
<a class="sourceLine" id="cb6-21" title="21"><span class="ot"> id=</span><span class="st">"svg2"</span><span class="ot"> version=</span><span class="st">"1.1"</span><span class="kw">></span></a>
|
||
<a class="sourceLine" id="cb6-22" title="22"> <span class="kw"><g</span><span class="ot"> id=</span><span class="st">"level_0"</span><span class="kw">></span> <span class="co"><!-- some group, if I want to add other elements --></span></a>
|
||
<a class="sourceLine" id="cb6-23" title="23"> <span class="co"><!-- the text "λ" --></span></a>
|
||
<a class="sourceLine" id="cb6-24" title="24"> <span class="kw"><text</span><span class="ot"> id=</span><span class="st">"lambda"</span> </a>
|
||
<a class="sourceLine" id="cb6-25" title="25"><span class="ot"> fill=</span><span class="st">"#333"</span><span class="ot"> style=</span><span class="st">"font-family:Ubuntu; font-size: 100px"</span></a>
|
||
<a class="sourceLine" id="cb6-26" title="26"><span class="ot"> transform=</span><span class="st">"rotate(180)"</span><span class="kw">></span>λ<span class="kw"></text></span></a>
|
||
<a class="sourceLine" id="cb6-27" title="27"> <span class="kw"></g></span></a>
|
||
<a class="sourceLine" id="cb6-28" title="28"> <span class="co"><!-- the text "esod" --></span></a>
|
||
<a class="sourceLine" id="cb6-29" title="29"> <span class="kw"><text</span> </a>
|
||
<a class="sourceLine" id="cb6-30" title="30"><span class="ot"> fill=</span><span class="st">"#333"</span> </a>
|
||
<a class="sourceLine" id="cb6-31" title="31"><span class="ot"> style=</span><span class="st">"font-family:Ubuntu; font-size: 28px; letter-spacing: -0.10em"</span> </a>
|
||
<a class="sourceLine" id="cb6-32" title="32"><span class="ot"> x=</span><span class="st">"-17.3"</span> </a>
|
||
<a class="sourceLine" id="cb6-33" title="33"><span class="ot"> y=</span><span class="st">"69"</span> </a>
|
||
<a class="sourceLine" id="cb6-34" title="34"><span class="ot"> transform=</span><span class="st">"YGENTRANSFORM"</span><span class="kw">></span>esod<span class="kw"></text></span></a>
|
||
<a class="sourceLine" id="cb6-35" title="35"> <span class="co"><!-- ROOT ELEMENT --></span></a>
|
||
<a class="sourceLine" id="cb6-36" title="36"> <span class="kw"><use</span><span class="ot"> transform=</span><span class="st">"YGENTRANSFORM"</span><span class="ot"> xlink:href=</span><span class="st">"#level_0"</span> <span class="kw">/></span></a>
|
||
<a class="sourceLine" id="cb6-37" title="37"></a>
|
||
<a class="sourceLine" id="cb6-38" title="38"> YTRANSCOMPLETE(1,0) <span class="co"><!-- First recursion --></span></a>
|
||
<a class="sourceLine" id="cb6-39" title="39"> YTRANSCOMPLETE(2,1) <span class="co"><!-- deeper --></span></a>
|
||
<a class="sourceLine" id="cb6-40" title="40"> YTRANSCOMPLETE(3,2) <span class="co"><!-- deeper --></span></a>
|
||
<a class="sourceLine" id="cb6-41" title="41"> YTRANSCOMPLETE(4,3) <span class="co"><!-- even deeper --></span></a>
|
||
<a class="sourceLine" id="cb6-42" title="42"> YTRANSCOMPLETE(5,4) <span class="co"><!-- Five level seems enough --></span></a>
|
||
<a class="sourceLine" id="cb6-43" title="43"><span class="kw"></svg></span></a></code></pre></div>
|
||
<p>and I compiled it to <sc>svg</sc> and then to <sc>png</sc> with:</p>
|
||
<div class="sourceCode" id="cb7"><pre class="sourceCode zsh"><code class="sourceCode zsh"><a class="sourceLine" id="cb7-1" title="1"><span class="kw">m4</span> yesodlogo.m4 <span class="kw">></span> yesodlogo.svg <span class="kw">&&</span> convert yesodlogo.svg yesodlogo.png</a></code></pre></div>
|
||
<p>The main λ is duplicated 3 times. Each transformation is named by: <code>YTRANSFORMONE</code>, <code>YTRANSFORMTWO</code> and <code>YTRANSFORMTHREE</code>.</p>
|
||
<p>Each transformation is just a similarity (translate + rotation + scale).</p>
|
||
<p>Once fixed, we should now simply copy and repeat for each new level.</p>
|
||
<p>Now it is time to talk about where the magic occurs: <code>YTRANSCOMPLETE</code>. This macro takes two arguments. The current depth and the preceding one. It duplicates using the three transformations the preceding level.</p>
|
||
<ul>
|
||
<li>At level 0 there is only one λ,</li>
|
||
<li>at level 1 there is 3 λ,</li>
|
||
<li>at level 2 there is 9 λ</li>
|
||
<li>etc…</li>
|
||
</ul>
|
||
<p>At the final 5th level there is 3<sup>5</sup>=243 λ. All level combined have 3<sup>6</sup>-1 / 2 = 364 λ.</p>
|
||
<p>I could preview the final result easily. Without the macro system, I would have to make 5 copy/paste + modifications for each try.</p>
|
||
<h2 id="conclusion">Conclusion</h2>
|
||
<p>It was fun to make a fractal in <sc>svg</sc>, but the interesting part is how to augment the power of a language using this preprocessor method. I used the <sc>xslt</sc> trick at work for example. I also used it to make include inside obscure format. If all you want is to generate a minimal static website withou using nanoc, jekyll or hakyll (ther are plenty other alternatives). You can consider using m4 to generate your <sc>html</sc> instead of copy/paste the menu and the footer, or using AJAX.</p>
|
||
<p>Another usage I thouhgt about is to use m4 to organize languages such as brainfuck.</p>
|
||
</div>
|
||
<div id="afterarticle">
|
||
<div id="social">
|
||
<a href="/rss.xml" target="_blank" rel="noopener noreferrer nofollow" class="social">RSS</a>
|
||
·
|
||
<a href="https://twitter.com/home?status=http%3A%2F%2Fyannesposito.com/Scratch/en/blog/SVG-and-m4-fractals/%20via%20@yogsototh" target="_blank" rel="noopener noreferrer nofollow" class="social">Tweet</a>
|
||
·
|
||
<a href="http://www.facebook.com/sharer/sharer.php?u=http%3A%2F%2Fyannesposito.com/Scratch/en/blog/SVG-and-m4-fractals/" target="_blank" rel="noopener noreferrer nofollow" class="social">FB</a>
|
||
<br />
|
||
<a class="message" href="../../../../Scratch/en/blog/Social-link-the-right-way/">These social sharing links preserve your privacy</a>
|
||
</div>
|
||
<div id="navigation">
|
||
<a href="../../../../">Home</a>
|
||
<span class="sep">¦</span>
|
||
<a href="../../../../Scratch/en/blog">Blog</a>
|
||
<span class="sep">¦</span>
|
||
<a href="../../../../Scratch/en/softwares">Softwares</a>
|
||
<span class="sep">¦</span>
|
||
<a href="../../../../Scratch/en/about">About</a>
|
||
</div>
|
||
<div id="totop"><a href="#header">↑ Top ↑</a></div>
|
||
<div id="bottom">
|
||
<div>
|
||
Published on 2011-10-20
|
||
</div>
|
||
<div>
|
||
<a href="https://twitter.com/yogsototh">Follow @yogsototh</a>
|
||
</div>
|
||
<div>
|
||
<a rel="license" href="http://creativecommons.org/licenses/by/3.0/deed.en_US">Yann Esposito©</a>
|
||
</div>
|
||
|
||
<div>
|
||
Done with
|
||
<a href="http://www.vim.org" target="_blank" rel="noopener noreferrer nofollow"><strike>Vim</strike></a>
|
||
<a href="http://spacemacs.org" target="_blank" rel="noopener noreferrer nofollow">spacemacs</a>
|
||
<span class="pala">&</span>
|
||
<a href="http://nanoc.ws" target="_blank" rel="noopener noreferrer nofollow"><strike>nanoc</strike></a>
|
||
<a href="http://jaspervdj.be/hakyll" target="_blank" rel="noopener noreferrer nofollow">Hakyll</a>
|
||
</div>
|
||
<hr />
|
||
<div style="max-width: 100%">
|
||
<a href="https://cardanohub.org">
|
||
<img src="../../../../Scratch/img/ada-logo.png" class="simple" style="height: 16px;
|
||
border-radius: 50%;
|
||
vertical-align:middle;
|
||
display:inline-block;" />
|
||
ADA:
|
||
</a>
|
||
<code style="display:inline-block;
|
||
word-wrap:break-word;
|
||
text-align: left;
|
||
vertical-align: top;
|
||
max-width: 85%;">
|
||
DdzFFzCqrhtAvdkmATx5Fm8NPJViDy85ZBw13p4XcNzVzvQg8e3vWLXq23JQWFxPEXK6Kvhaxxe7oJt4VMYHxpA2vtCFiP8fziohN6Yp
|
||
</code>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
</body>
|
||
</html>
|