her.esy.fun/src/Scratch/en/blog/SVG-and-m4-fractals/index.html

238 lines
21 KiB
HTML
Raw Normal View History

2021-04-18 10:23:24 +00:00
<!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" />
2021-05-25 20:25:47 +00:00
<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" />
2021-04-18 10:23:24 +00:00
<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 shouldnt 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 isnt 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> isnt 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>Lets 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">&lt;xsl:variable</span><span class="ot"> name=</span><span class="st">&quot;myvar&quot;</span><span class="ot"> select=</span><span class="st">&quot;value&quot;</span><span class="kw">/&gt;</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">&lt;xsl:text</span> </a>
<a class="sourceLine" id="cb2-2" title="2"><span class="ot"> disable-output-escaping=</span><span class="st">&quot;yes&quot;</span><span class="kw">&gt;</span><span class="bn">&lt;![CDATA[</span>Hello world!</a>
<a class="sourceLine" id="cb2-3" title="3"><span class="bn">]]&gt;</span><span class="kw">&lt;/xsl:text&gt;</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">&lt;xslt:value-of</span><span class="ot"> select=</span><span class="st">&quot;myvar&quot;</span><span class="kw">/&gt;</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">&lt;?xml</span> version=&quot;1.0&quot; standalone=&quot;yes&quot;<span class="kw">?&gt;</span> <span class="co">&lt;!-- YES its &lt;span class=&quot;sc&quot;&gt;xml&lt;/span&gt; --&gt;</span></a>
<a class="sourceLine" id="cb4-2" title="2"><span class="co">&lt;!-- ← 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',`&lt;xsl:variable name=&quot;$1&quot; select=&quot;$2&quot;/&gt;')</span></a>
<a class="sourceLine" id="cb4-5" title="5"><span class="co">define(`yprint',`&lt;xsl:text disable-output-escaping=&quot;yes&quot;&gt;&lt;![CDATA[$1]]&gt;&lt;/xsl:text&gt;')</span></a>
<a class="sourceLine" id="cb4-6" title="6"><span class="co">define(`yshow',`&lt;xsl:value-of select=&quot;$1&quot;/&gt;')</span></a>
<a class="sourceLine" id="cb4-7" title="7"></a>
<a class="sourceLine" id="cb4-8" title="8"><span class="co">--&gt;</span></a>
<a class="sourceLine" id="cb4-9" title="9"><span class="co">&lt;!-- Yes, &lt;span class=&quot;sc&quot;&gt;xml&lt;/span&gt; sucks to be read --&gt;</span></a>
<a class="sourceLine" id="cb4-10" title="10"><span class="kw">&lt;xsl:stylesheet</span><span class="ot"> version=</span><span class="st">&quot;1.0&quot;</span><span class="ot"> xmlns:xsl=</span><span class="st">&quot;http://www.w3.org/1999/XSL/Transform&quot;</span><span class="kw">&gt;</span></a>
<a class="sourceLine" id="cb4-11" title="11"><span class="co">&lt;!-- And it sucks even more to edit --&gt;</span></a>
<a class="sourceLine" id="cb4-12" title="12"><span class="kw">&lt;xsl:template</span><span class="ot"> match=</span><span class="st">&quot;/&quot;</span><span class="kw">&gt;</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">&lt;/xsl:template&gt;</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">&gt;</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 didnt 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">&lt;?xml</span> version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;<span class="kw">?&gt;</span></a>
<a class="sourceLine" id="cb6-2" title="2"><span class="co">&lt;!--</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"> &lt;g id=&quot;level_$1&quot;&gt;</span></a>
<a class="sourceLine" id="cb6-10" title="10"><span class="co"> &lt;use style=&quot;opacity: .8&quot; transform=&quot;YTRANSFORMONE&quot; xlink:href=&quot;#level_$2&quot; /&gt;</span></a>
<a class="sourceLine" id="cb6-11" title="11"><span class="co"> &lt;use style=&quot;opacity: .8&quot; transform=&quot;YTRANSFORMTWO&quot; xlink:href=&quot;#level_$2&quot; /&gt;</span></a>
<a class="sourceLine" id="cb6-12" title="12"><span class="co"> &lt;use style=&quot;opacity: .8&quot; transform=&quot;YTRANSFORMTHREE&quot; xlink:href=&quot;#level_$2&quot; /&gt;</span></a>
<a class="sourceLine" id="cb6-13" title="13"><span class="co"> &lt;/g&gt;</span></a>
<a class="sourceLine" id="cb6-14" title="14"><span class="co"> &lt;use transform=&quot;YGENTRANSFORM&quot; xlink:href=&quot;#level_$1&quot; /&gt;</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"> --&gt;</span></a>
<a class="sourceLine" id="cb6-17" title="17"><span class="kw">&lt;svg</span> </a>
<a class="sourceLine" id="cb6-18" title="18"><span class="ot"> xmlns=</span><span class="st">&quot;http://www.w3.org/2000/svg&quot;</span> </a>
<a class="sourceLine" id="cb6-19" title="19"><span class="ot"> xmlns:xlink=</span><span class="st">&quot;http://www.w3.org/1999/xlink&quot;</span></a>
<a class="sourceLine" id="cb6-20" title="20"><span class="ot"> x=</span><span class="st">&quot;64&quot;</span><span class="ot"> y=</span><span class="st">&quot;64&quot;</span><span class="ot"> width=</span><span class="st">&quot;512&quot;</span><span class="ot"> height=</span><span class="st">&quot;512&quot;</span><span class="ot"> viewBox=</span><span class="st">&quot;64 64 512 512&quot;</span></a>
<a class="sourceLine" id="cb6-21" title="21"><span class="ot"> id=</span><span class="st">&quot;svg2&quot;</span><span class="ot"> version=</span><span class="st">&quot;1.1&quot;</span><span class="kw">&gt;</span></a>
<a class="sourceLine" id="cb6-22" title="22"> <span class="kw">&lt;g</span><span class="ot"> id=</span><span class="st">&quot;level_0&quot;</span><span class="kw">&gt;</span> <span class="co">&lt;!-- some group, if I want to add other elements --&gt;</span></a>
<a class="sourceLine" id="cb6-23" title="23"> <span class="co">&lt;!-- the text &quot;λ&quot; --&gt;</span></a>
<a class="sourceLine" id="cb6-24" title="24"> <span class="kw">&lt;text</span><span class="ot"> id=</span><span class="st">&quot;lambda&quot;</span> </a>
<a class="sourceLine" id="cb6-25" title="25"><span class="ot"> fill=</span><span class="st">&quot;#333&quot;</span><span class="ot"> style=</span><span class="st">&quot;font-family:Ubuntu; font-size: 100px&quot;</span></a>
<a class="sourceLine" id="cb6-26" title="26"><span class="ot"> transform=</span><span class="st">&quot;rotate(180)&quot;</span><span class="kw">&gt;</span>λ<span class="kw">&lt;/text&gt;</span></a>
<a class="sourceLine" id="cb6-27" title="27"> <span class="kw">&lt;/g&gt;</span></a>
<a class="sourceLine" id="cb6-28" title="28"> <span class="co">&lt;!-- the text &quot;esod&quot; --&gt;</span></a>
<a class="sourceLine" id="cb6-29" title="29"> <span class="kw">&lt;text</span> </a>
<a class="sourceLine" id="cb6-30" title="30"><span class="ot"> fill=</span><span class="st">&quot;#333&quot;</span> </a>
<a class="sourceLine" id="cb6-31" title="31"><span class="ot"> style=</span><span class="st">&quot;font-family:Ubuntu; font-size: 28px; letter-spacing: -0.10em&quot;</span> </a>
<a class="sourceLine" id="cb6-32" title="32"><span class="ot"> x=</span><span class="st">&quot;-17.3&quot;</span> </a>
<a class="sourceLine" id="cb6-33" title="33"><span class="ot"> y=</span><span class="st">&quot;69&quot;</span> </a>
<a class="sourceLine" id="cb6-34" title="34"><span class="ot"> transform=</span><span class="st">&quot;YGENTRANSFORM&quot;</span><span class="kw">&gt;</span>esod<span class="kw">&lt;/text&gt;</span></a>
<a class="sourceLine" id="cb6-35" title="35"> <span class="co">&lt;!-- ROOT ELEMENT --&gt;</span></a>
<a class="sourceLine" id="cb6-36" title="36"> <span class="kw">&lt;use</span><span class="ot"> transform=</span><span class="st">&quot;YGENTRANSFORM&quot;</span><span class="ot"> xlink:href=</span><span class="st">&quot;#level_0&quot;</span> <span class="kw">/&gt;</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">&lt;!-- First recursion --&gt;</span></a>
<a class="sourceLine" id="cb6-39" title="39"> YTRANSCOMPLETE(2,1) <span class="co">&lt;!-- deeper --&gt;</span></a>
<a class="sourceLine" id="cb6-40" title="40"> YTRANSCOMPLETE(3,2) <span class="co">&lt;!-- deeper --&gt;</span></a>
<a class="sourceLine" id="cb6-41" title="41"> YTRANSCOMPLETE(4,3) <span class="co">&lt;!-- even deeper --&gt;</span></a>
<a class="sourceLine" id="cb6-42" title="42"> YTRANSCOMPLETE(5,4) <span class="co">&lt;!-- Five level seems enough --&gt;</span></a>
<a class="sourceLine" id="cb6-43" title="43"><span class="kw">&lt;/svg&gt;</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">&gt;</span> yesodlogo.svg <span class="kw">&amp;&amp;</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">
2021-05-25 20:25:47 +00:00
<a href="/rss.xml" target="_blank" rel="noopener noreferrer nofollow" class="social">RSS</a>
2021-04-18 10:23:24 +00:00
·
<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">&amp;</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>