Deploying to gh-pages from @ e369dbec36 🚀

This commit is contained in:
Lemmih 2020-09-08 12:06:19 +00:00
commit 84a82512eb
7 changed files with 549 additions and 549 deletions

View file

@ -41,7 +41,7 @@ table.dashboard { border-collapse: collapse ; border: solid 1px black }
<td align="right">8%</td><td>1/12</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="8%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">1%</td><td>1/55</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="1%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">3%</td><td>9/245</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="3%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
<tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.3.0-inplace/Reanimate.Driver.CLI.hs.html">reanimate-0.4.3.0-inplace/Reanimate.Driver.CLI</a></tt></td>
<td align="right">14%</td><td>5/35</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="14%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">0%</td><td>0/63</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td><td align="right">8%</td><td>31/376</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="8%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
<td align="right">13%</td><td>5/36</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="13%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">0%</td><td>0/65</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td><td align="right">7%</td><td>31/388</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="7%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
<tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.3.0-inplace/Reanimate.Driver.Check.hs.html">reanimate-0.4.3.0-inplace/Reanimate.Driver.Check</a></tt></td>
<td align="right">0%</td><td>0/21</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td><td align="right">0%</td><td>0/27</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td><td align="right">0%</td><td>0/396</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td></tr>
@ -98,7 +98,7 @@ table.dashboard { border-collapse: collapse ; border: solid 1px black }
<td align="right">15%</td><td>2/13</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="15%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">0%</td><td>0/17</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td><td align="right">11%</td><td>52/443</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="11%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
<tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.3.0-inplace/Reanimate.Render.hs.html">reanimate-0.4.3.0-inplace/Reanimate.Render</a></tt></td>
<td align="right">5%</td><td>1/19</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="5%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">0%</td><td>0/55</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td><td align="right">4%</td><td>39/875</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="4%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
<td align="right">5%</td><td>1/19</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="5%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">0%</td><td>0/53</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td><td align="right">4%</td><td>39/852</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="4%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
<tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.3.0-inplace/Reanimate.Scene.Core.hs.html">reanimate-0.4.3.0-inplace/Reanimate.Scene.Core</a></tt></td>
<td align="right">63%</td><td>12/19</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="63%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">-&nbsp;</td><td>0/0</td><td width=100>&nbsp;</td><td align="right">72%</td><td>172/237</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="72%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
@ -131,5 +131,5 @@ table.dashboard { border-collapse: collapse ; border: solid 1px black }
<td align="right">100%</td><td>6/6</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">50%</td><td>1/2</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="50%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">95%</td><td>43/45</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="95%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
<tr></tr><tr style="background: #e0e0e0">
<th align=left>&nbsp;&nbsp;Program Coverage Total</tt></th>
<td align="right">35%</td><td>261/739</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="35%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">17%</td><td>144/846</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="17%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">32%</td><td>4843/15004</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="32%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
<td align="right">35%</td><td>261/740</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="35%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">17%</td><td>144/846</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="17%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">32%</td><td>4843/14993</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="32%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
</table></body></html>

View file

@ -74,7 +74,7 @@ table.dashboard { border-collapse: collapse ; border: solid 1px black }
<td align="right">0%</td><td>0/8</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td><td align="right">0%</td><td>0/12</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td><td align="right">0%</td><td>0/160</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td></tr>
<tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.3.0-inplace/Reanimate.Driver.CLI.hs.html">reanimate-0.4.3.0-inplace/Reanimate.Driver.CLI</a></tt></td>
<td align="right">14%</td><td>5/35</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="14%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">0%</td><td>0/63</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td><td align="right">8%</td><td>31/376</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="8%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
<td align="right">13%</td><td>5/36</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="13%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">0%</td><td>0/65</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td><td align="right">7%</td><td>31/388</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="7%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
<tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.3.0-inplace/Reanimate.Driver.Check.hs.html">reanimate-0.4.3.0-inplace/Reanimate.Driver.Check</a></tt></td>
<td align="right">0%</td><td>0/21</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td><td align="right">0%</td><td>0/27</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td><td align="right">0%</td><td>0/396</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td></tr>
@ -101,7 +101,7 @@ table.dashboard { border-collapse: collapse ; border: solid 1px black }
<td align="right">15%</td><td>2/13</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="15%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">0%</td><td>0/17</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td><td align="right">11%</td><td>52/443</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="11%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
<tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.3.0-inplace/Reanimate.Render.hs.html">reanimate-0.4.3.0-inplace/Reanimate.Render</a></tt></td>
<td align="right">5%</td><td>1/19</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="5%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">0%</td><td>0/55</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td><td align="right">4%</td><td>39/875</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="4%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
<td align="right">5%</td><td>1/19</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="5%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">0%</td><td>0/53</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td><td align="right">4%</td><td>39/852</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="4%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
<tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.3.0-inplace/Reanimate.Svg.Unuse.hs.html">reanimate-0.4.3.0-inplace/Reanimate.Svg.Unuse</a></tt></td>
<td align="right">33%</td><td>1/3</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="33%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">0%</td><td>0/14</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td><td align="right">22%</td><td>28/127</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="22%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
@ -131,5 +131,5 @@ table.dashboard { border-collapse: collapse ; border: solid 1px black }
<td align="right">63%</td><td>12/19</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="63%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">-&nbsp;</td><td>0/0</td><td width=100>&nbsp;</td><td align="right">72%</td><td>172/237</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="72%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
<tr></tr><tr style="background: #e0e0e0">
<th align=left>&nbsp;&nbsp;Program Coverage Total</tt></th>
<td align="right">35%</td><td>261/739</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="35%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">17%</td><td>144/846</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="17%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">32%</td><td>4843/15004</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="32%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
<td align="right">35%</td><td>261/740</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="35%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">17%</td><td>144/846</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="17%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">32%</td><td>4843/14993</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="32%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
</table></body></html>

View file

@ -86,13 +86,13 @@ table.dashboard { border-collapse: collapse ; border: solid 1px black }
<td align="right">15%</td><td>2/13</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="15%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">0%</td><td>0/17</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td><td align="right">11%</td><td>52/443</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="11%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
<tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.3.0-inplace/Reanimate.Driver.CLI.hs.html">reanimate-0.4.3.0-inplace/Reanimate.Driver.CLI</a></tt></td>
<td align="right">14%</td><td>5/35</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="14%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">0%</td><td>0/63</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td><td align="right">8%</td><td>31/376</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="8%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
<td align="right">13%</td><td>5/36</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="13%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">0%</td><td>0/65</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td><td align="right">7%</td><td>31/388</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="7%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
<tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.3.0-inplace/Reanimate.LaTeX.hs.html">reanimate-0.4.3.0-inplace/Reanimate.LaTeX</a></tt></td>
<td align="right">33%</td><td>4/12</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="33%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">11%</td><td>1/9</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="11%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">7%</td><td>12/167</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="7%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
<tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.3.0-inplace/Reanimate.Render.hs.html">reanimate-0.4.3.0-inplace/Reanimate.Render</a></tt></td>
<td align="right">5%</td><td>1/19</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="5%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">0%</td><td>0/55</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td><td align="right">4%</td><td>39/875</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="4%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
<td align="right">5%</td><td>1/19</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="5%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">0%</td><td>0/53</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td><td align="right">4%</td><td>39/852</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="4%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
<tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.3.0-inplace/Reanimate.Driver.hs.html">reanimate-0.4.3.0-inplace/Reanimate.Driver</a></tt></td>
<td align="right">8%</td><td>1/12</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="8%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">1%</td><td>1/55</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="1%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">3%</td><td>9/245</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="3%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
@ -131,5 +131,5 @@ table.dashboard { border-collapse: collapse ; border: solid 1px black }
<td align="right">0%</td><td>0/1</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td><td align="right">0%</td><td>0/4</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td><td align="right">0%</td><td>0/61</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td></tr>
<tr></tr><tr style="background: #e0e0e0">
<th align=left>&nbsp;&nbsp;Program Coverage Total</tt></th>
<td align="right">35%</td><td>261/739</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="35%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">17%</td><td>144/846</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="17%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">32%</td><td>4843/15004</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="32%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
<td align="right">35%</td><td>261/740</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="35%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">17%</td><td>144/846</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="17%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">32%</td><td>4843/14993</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="32%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
</table></body></html>

View file

@ -89,7 +89,7 @@ table.dashboard { border-collapse: collapse ; border: solid 1px black }
<td align="right">15%</td><td>2/13</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="15%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">0%</td><td>0/17</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td><td align="right">11%</td><td>52/443</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="11%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
<tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.3.0-inplace/Reanimate.Driver.CLI.hs.html">reanimate-0.4.3.0-inplace/Reanimate.Driver.CLI</a></tt></td>
<td align="right">14%</td><td>5/35</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="14%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">0%</td><td>0/63</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td><td align="right">8%</td><td>31/376</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="8%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
<td align="right">13%</td><td>5/36</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="13%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">0%</td><td>0/65</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td><td align="right">7%</td><td>31/388</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="7%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
<tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.3.0-inplace/Reanimate.Math.Polygon.hs.html">reanimate-0.4.3.0-inplace/Reanimate.Math.Polygon</a></tt></td>
<td align="right">9%</td><td>8/82</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="9%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">5%</td><td>4/75</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="5%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">2%</td><td>59/2409</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="2%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
@ -98,7 +98,7 @@ table.dashboard { border-collapse: collapse ; border: solid 1px black }
<td align="right">8%</td><td>1/12</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="8%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">1%</td><td>1/55</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="1%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">3%</td><td>9/245</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="3%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
<tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.3.0-inplace/Reanimate.Render.hs.html">reanimate-0.4.3.0-inplace/Reanimate.Render</a></tt></td>
<td align="right">5%</td><td>1/19</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="5%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">0%</td><td>0/55</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td><td align="right">4%</td><td>39/875</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="4%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
<td align="right">5%</td><td>1/19</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="5%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">0%</td><td>0/53</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td><td align="right">4%</td><td>39/852</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="4%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
<tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.3.0-inplace/Reanimate.Cache.hs.html">reanimate-0.4.3.0-inplace/Reanimate.Cache</a></tt></td>
<td align="right">0%</td><td>0/8</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td><td align="right">0%</td><td>0/12</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td><td align="right">0%</td><td>0/160</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td></tr>
@ -131,5 +131,5 @@ table.dashboard { border-collapse: collapse ; border: solid 1px black }
<td align="right">0%</td><td>0/1</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td><td align="right">0%</td><td>0/4</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td><td align="right">0%</td><td>0/61</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td></tr>
<tr></tr><tr style="background: #e0e0e0">
<th align=left>&nbsp;&nbsp;Program Coverage Total</tt></th>
<td align="right">35%</td><td>261/739</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="35%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">17%</td><td>144/846</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="17%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">32%</td><td>4843/15004</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="32%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
<td align="right">35%</td><td>261/740</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="35%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">17%</td><td>144/846</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="17%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">32%</td><td>4843/14993</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="32%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
</table></body></html>

View file

@ -9,4 +9,4 @@ const snippets = [{"title": "Hello World","url": "https://reanimate.clozecards.c
,{"title": "Object Positions","url": "https://reanimate.clozecards.com/Mf4zcImo+I7/195.svg","code": "env =\n addStatic (mkBackground \"white\") .\n mapA (withStrokeColor \"black\")\n\nanimation :: Animation\nanimation = env $\n sceneAnimation $ do\n -- Configure objects\n txt <- newText \"Center\"\n top <- newText \"Top\"\n oModifyS top $ \n oTopY .= screenTop\n topR <- newText \"Top right\"\n oModifyS topR $ do\n oTopY .= screenTop\n oRightX .= screenRight\n botR <- newText \"Bottom right\"\n oModifyS botR $ do\n oTranslate .= (0, screenBottom+0.5)\n oRightX .= screenRight\n botL <- newText \"Bottom left\"\n oModifyS botL $ do\n oTranslate .= (0, screenBottom+0.5)\n oLeftX .= screenLeft\n topL <- newText \"Top left\"\n oModifyS topL $ do\n oTopY .= screenTop\n oLeftX .= screenLeft\n -- Show objects\n oShow txt\n wait 1\n switchTo txt top\n switchTo top topR\n switchTo topR botR\n switchTo botR botL\n switchTo botL topL\n switchTo topL txt\n\nswitchTo src dst = do\n fork $ oHideWith src oFadeOut\n oShowWith dst oFadeIn\n wait 1\n\nnewText txt =\n newObject $ scale 1.5 $ centerX $ latex txt\n"}
,{"title": "Camera","url": "https://reanimate.clozecards.com/Hcx00P+aeph/150.svg","code": "animation :: Animation\nanimation = docEnv $ mapA (withFillOpacity 1) $ sceneAnimation $ do\n cam <- newObject Camera\n\n txt <- newObject $ center $ latex \"Fixed (non-cam)\"\n oModifyS txt $ do\n oTopY .= screenTop \n oZIndex .= 2\n\n circle <- newObject $ withFillColor \"blue\" $ mkCircle 1\n cameraAttach cam circle\n circleRight <- oRead circle oRightX\n\n box <- newObject $ withFillColor \"green\" $ mkRect 2 2\n cameraAttach cam box\n oModify box $ oLeftX .~ circleRight\n boxCenter <- oRead box oCenterXY\n\n small <- newObject $ center $ latex \"This text is very small\"\n cameraAttach cam small\n oModifyS small $ do\n oCenterXY .= boxCenter\n oScale .= 0.1\n \n oShow txt\n oShow small\n oShow circle\n oShow box\n\n wait 1\n\n cameraFocus cam boxCenter\n waitOn $ do\n fork $ cameraPan cam 3 boxCenter\n fork $ cameraZoom cam 3 15\n \n wait 2\n cameraZoom cam 3 1\n cameraPan cam 1 (0,0)\n"}
];
const playgroundVersion = "2020-09-08 (e9f89)";
const playgroundVersion = "2020-09-08 (e369d)";

View file

@ -63,183 +63,188 @@ span.spaces { background: white }
<span class="lineno"> 44 </span> , <span class="nottickedoff"><span class="decl"><span class="nottickedoff">renderPreset</span></span></span> :: Maybe Preset
<span class="lineno"> 45 </span> , <span class="nottickedoff"><span class="decl"><span class="nottickedoff">renderRaster</span></span></span> :: Raster
<span class="lineno"> 46 </span> , <span class="nottickedoff"><span class="decl"><span class="nottickedoff">renderPartial</span></span></span> :: Bool
<span class="lineno"> 47 </span> }
<span class="lineno"> 48 </span> deriving (<span class="decl"><span class="nottickedoff">Show</span></span>)
<span class="lineno"> 49 </span>
<span class="lineno"> 50 </span>data Preset = Youtube | ExampleGif | Quick | MediumQ | HighQ | LowFPS
<span class="lineno"> 51 </span> deriving (<span class="decl"><span class="nottickedoff">Show</span></span>)
<span class="lineno"> 52 </span>
<span class="lineno"> 53 </span>readRaster :: String -&gt; Maybe Raster
<span class="lineno"> 54 </span><span class="decl"><span class="nottickedoff">readRaster raster =</span>
<span class="lineno"> 55 </span><span class="spaces"> </span><span class="nottickedoff">case map toLower raster of</span>
<span class="lineno"> 56 </span><span class="spaces"> </span><span class="nottickedoff">&quot;none&quot; -&gt; Just RasterNone</span>
<span class="lineno"> 57 </span><span class="spaces"> </span><span class="nottickedoff">&quot;auto&quot; -&gt; Just RasterAuto</span>
<span class="lineno"> 58 </span><span class="spaces"> </span><span class="nottickedoff">&quot;inkscape&quot; -&gt; Just RasterInkscape</span>
<span class="lineno"> 59 </span><span class="spaces"> </span><span class="nottickedoff">&quot;rsvg&quot; -&gt; Just RasterRSvg</span>
<span class="lineno"> 60 </span><span class="spaces"> </span><span class="nottickedoff">&quot;imagemagick&quot; -&gt; Just RasterMagick</span>
<span class="lineno"> 61 </span><span class="spaces"> </span><span class="nottickedoff">_ -&gt; Nothing</span></span>
<span class="lineno"> 62 </span>
<span class="lineno"> 63 </span>showRaster :: Raster -&gt; String
<span class="lineno"> 64 </span><span class="decl"><span class="nottickedoff">showRaster RasterNone = &quot;none&quot;</span>
<span class="lineno"> 65 </span><span class="spaces"></span><span class="nottickedoff">showRaster RasterAuto = &quot;auto&quot;</span>
<span class="lineno"> 66 </span><span class="spaces"></span><span class="nottickedoff">showRaster RasterInkscape = &quot;inkscape&quot;</span>
<span class="lineno"> 67 </span><span class="spaces"></span><span class="nottickedoff">showRaster RasterRSvg = &quot;rsvg&quot;</span>
<span class="lineno"> 68 </span><span class="spaces"></span><span class="nottickedoff">showRaster RasterMagick = &quot;imagemagick&quot;</span></span>
<span class="lineno"> 69 </span>
<span class="lineno"> 70 </span>readFormat :: String -&gt; Maybe Format
<span class="lineno"> 71 </span><span class="decl"><span class="nottickedoff">readFormat fmt =</span>
<span class="lineno"> 72 </span><span class="spaces"> </span><span class="nottickedoff">case map toLower fmt of</span>
<span class="lineno"> 73 </span><span class="spaces"> </span><span class="nottickedoff">&quot;mp4&quot; -&gt; Just RenderMp4</span>
<span class="lineno"> 74 </span><span class="spaces"> </span><span class="nottickedoff">&quot;gif&quot; -&gt; Just RenderGif</span>
<span class="lineno"> 75 </span><span class="spaces"> </span><span class="nottickedoff">&quot;webm&quot; -&gt; Just RenderWebm</span>
<span class="lineno"> 76 </span><span class="spaces"> </span><span class="nottickedoff">_ -&gt; Nothing</span></span>
<span class="lineno"> 77 </span>
<span class="lineno"> 78 </span>showFormat :: Format -&gt; String
<span class="lineno"> 79 </span><span class="decl"><span class="nottickedoff">showFormat RenderMp4 = &quot;mp4&quot;</span>
<span class="lineno"> 80 </span><span class="spaces"></span><span class="nottickedoff">showFormat RenderGif = &quot;gif&quot;</span>
<span class="lineno"> 81 </span><span class="spaces"></span><span class="nottickedoff">showFormat RenderWebm = &quot;webm&quot;</span></span>
<span class="lineno"> 82 </span>
<span class="lineno"> 83 </span>readPreset :: String -&gt; Maybe Preset
<span class="lineno"> 84 </span><span class="decl"><span class="nottickedoff">readPreset preset =</span>
<span class="lineno"> 85 </span><span class="spaces"> </span><span class="nottickedoff">case map toLower preset of</span>
<span class="lineno"> 86 </span><span class="spaces"> </span><span class="nottickedoff">&quot;youtube&quot; -&gt; Just Youtube</span>
<span class="lineno"> 87 </span><span class="spaces"> </span><span class="nottickedoff">&quot;gif&quot; -&gt; Just ExampleGif</span>
<span class="lineno"> 88 </span><span class="spaces"> </span><span class="nottickedoff">&quot;quick&quot; -&gt; Just Quick</span>
<span class="lineno"> 89 </span><span class="spaces"> </span><span class="nottickedoff">&quot;medium&quot; -&gt; Just MediumQ</span>
<span class="lineno"> 90 </span><span class="spaces"> </span><span class="nottickedoff">&quot;high&quot; -&gt; Just HighQ</span>
<span class="lineno"> 91 </span><span class="spaces"> </span><span class="nottickedoff">&quot;lowfps&quot; -&gt; Just LowFPS</span>
<span class="lineno"> 92 </span><span class="spaces"> </span><span class="nottickedoff">_ -&gt; Nothing</span></span>
<span class="lineno"> 93 </span>
<span class="lineno"> 94 </span>showPreset :: Preset -&gt; String
<span class="lineno"> 95 </span><span class="decl"><span class="nottickedoff">showPreset Youtube = &quot;youtube&quot;</span>
<span class="lineno"> 96 </span><span class="spaces"></span><span class="nottickedoff">showPreset ExampleGif = &quot;gif&quot;</span>
<span class="lineno"> 97 </span><span class="spaces"></span><span class="nottickedoff">showPreset Quick = &quot;quick&quot;</span>
<span class="lineno"> 98 </span><span class="spaces"></span><span class="nottickedoff">showPreset MediumQ = &quot;medium&quot;</span>
<span class="lineno"> 99 </span><span class="spaces"></span><span class="nottickedoff">showPreset HighQ = &quot;high&quot;</span>
<span class="lineno"> 100 </span><span class="spaces"></span><span class="nottickedoff">showPreset LowFPS = &quot;lowfps&quot;</span></span>
<span class="lineno"> 101 </span>
<span class="lineno"> 102 </span>options :: Parser Options
<span class="lineno"> 103 </span><span class="decl"><span class="istickedoff">options = Options &lt;$&gt; commandP</span></span>
<span class="lineno"> 104 </span>
<span class="lineno"> 105 </span>commandP :: Parser Command
<span class="lineno"> 106 </span><span class="decl"><span class="istickedoff">commandP = subparser(</span>
<span class="lineno"> 107 </span><span class="spaces"> </span><span class="istickedoff">command &quot;test&quot; testCommand</span>
<span class="lineno"> 108 </span><span class="spaces"> </span><span class="istickedoff">&lt;&gt; commandGroup <span class="nottickedoff">&quot;Internal commands&quot;</span></span>
<span class="lineno"> 109 </span><span class="spaces"> </span><span class="istickedoff">&lt;&gt; internal )</span>
<span class="lineno"> 110 </span><span class="spaces"> </span><span class="istickedoff">&lt;|&gt; <span class="nottickedoff">hsubparser</span></span>
<span class="lineno"> 111 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">( command &quot;check&quot; checkCommand</span></span>
<span class="lineno"> 112 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">&lt;&gt; command &quot;view&quot; viewCommand</span></span>
<span class="lineno"> 113 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">&lt;&gt; command &quot;render&quot; renderCommand</span></span>
<span class="lineno"> 114 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">&lt;&gt; command &quot;raw&quot; rawCommand</span></span>
<span class="lineno"> 115 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">)</span></span>
<span class="lineno"> 116 </span><span class="spaces"> </span><span class="istickedoff">&lt;|&gt; <span class="nottickedoff">infoParser viewCommand</span></span></span>
<span class="lineno"> 117 </span>
<span class="lineno"> 118 </span>rawCommand :: ParserInfo Command
<span class="lineno"> 119 </span><span class="decl"><span class="nottickedoff">rawCommand = info parse</span>
<span class="lineno"> 120 </span><span class="spaces"> </span><span class="nottickedoff">(progDesc &quot;Output raw SVGs for animation at 60 fps. Used internally by viewer.&quot;)</span>
<span class="lineno"> 121 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 122 </span><span class="spaces"> </span><span class="nottickedoff">parse = Raw</span>
<span class="lineno"> 123 </span><span class="spaces"> </span><span class="nottickedoff">&lt;$&gt; strOption</span>
<span class="lineno"> 124 </span><span class="spaces"> </span><span class="nottickedoff">( long &quot;output&quot; &lt;&gt;</span>
<span class="lineno"> 125 </span><span class="spaces"> </span><span class="nottickedoff">short 'o' &lt;&gt;</span>
<span class="lineno"> 126 </span><span class="spaces"> </span><span class="nottickedoff">metavar &quot;PATH&quot; &lt;&gt;</span>
<span class="lineno"> 127 </span><span class="spaces"> </span><span class="nottickedoff">help &quot;Output folder&quot; &lt;&gt;</span>
<span class="lineno"> 128 </span><span class="spaces"> </span><span class="nottickedoff">value &quot;.&quot;)</span>
<span class="lineno"> 129 </span><span class="spaces"> </span><span class="nottickedoff">&lt;*&gt; option auto</span>
<span class="lineno"> 130 </span><span class="spaces"> </span><span class="nottickedoff">( long &quot;offset&quot; &lt;&gt;</span>
<span class="lineno"> 131 </span><span class="spaces"> </span><span class="nottickedoff">metavar &quot;NUMBER&quot; &lt;&gt;</span>
<span class="lineno"> 132 </span><span class="spaces"> </span><span class="nottickedoff">help &quot;Frame offset&quot; &lt;&gt;</span>
<span class="lineno"> 133 </span><span class="spaces"> </span><span class="nottickedoff">value 0)</span>
<span class="lineno"> 134 </span><span class="spaces"> </span><span class="nottickedoff">&lt;*&gt; switch</span>
<span class="lineno"> 135 </span><span class="spaces"> </span><span class="nottickedoff">( long &quot;pretty-print&quot; &lt;&gt;</span>
<span class="lineno"> 136 </span><span class="spaces"> </span><span class="nottickedoff">short 'p' &lt;&gt;</span>
<span class="lineno"> 137 </span><span class="spaces"> </span><span class="nottickedoff">help &quot;Pretty print svg&quot;)</span></span>
<span class="lineno"> 138 </span>
<span class="lineno"> 139 </span>testCommand :: ParserInfo Command
<span class="lineno"> 140 </span><span class="decl"><span class="istickedoff">testCommand = info (parse &lt;**&gt; helper)</span>
<span class="lineno"> 141 </span><span class="spaces"> </span><span class="istickedoff">(progDesc <span class="nottickedoff">&quot;Generate 10 frames spread out evenly across the animation. Used \</span></span>
<span class="lineno"> 142 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">\internally by the test-suite.&quot;</span>)</span>
<span class="lineno"> 143 </span><span class="spaces"> </span><span class="istickedoff">where</span>
<span class="lineno"> 144 </span><span class="spaces"> </span><span class="istickedoff">parse = pure Test</span></span>
<span class="lineno"> 145 </span>
<span class="lineno"> 146 </span>checkCommand :: ParserInfo Command
<span class="lineno"> 147 </span><span class="decl"><span class="nottickedoff">checkCommand = info parse</span>
<span class="lineno"> 148 </span><span class="spaces"> </span><span class="nottickedoff">(progDesc &quot;Run a system's diagnostic and report any missing external dependencies.&quot;)</span>
<span class="lineno"> 149 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 150 </span><span class="spaces"> </span><span class="nottickedoff">parse = pure Check</span></span>
<span class="lineno"> 151 </span>
<span class="lineno"> 152 </span>viewCommand :: ParserInfo Command
<span class="lineno"> 153 </span><span class="decl"><span class="nottickedoff">viewCommand = info parse</span>
<span class="lineno"> 154 </span><span class="spaces"> </span><span class="nottickedoff">(progDesc &quot;Play animation in browser window.&quot;)</span>
<span class="lineno"> 155 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 156 </span><span class="spaces"> </span><span class="nottickedoff">parse = View</span>
<span class="lineno"> 157 </span><span class="spaces"> </span><span class="nottickedoff">&lt;$&gt; switch</span>
<span class="lineno"> 158 </span><span class="spaces"> </span><span class="nottickedoff">(long &quot;verbose&quot; &lt;&gt; short 'v')</span>
<span class="lineno"> 159 </span><span class="spaces"> </span><span class="nottickedoff">&lt;*&gt; optional (strOption (long &quot;ghc&quot;</span>
<span class="lineno"> 160 </span><span class="spaces"> </span><span class="nottickedoff">&lt;&gt; metavar &quot;PATH&quot;</span>
<span class="lineno"> 161 </span><span class="spaces"> </span><span class="nottickedoff">&lt;&gt; help &quot;Path to GHC binary&quot;))</span>
<span class="lineno"> 162 </span><span class="spaces"> </span><span class="nottickedoff">&lt;*&gt; many (strOption (long &quot;ghc-opt&quot;</span>
<span class="lineno"> 163 </span><span class="spaces"> </span><span class="nottickedoff">&lt;&gt; short 'G'</span>
<span class="lineno"> 164 </span><span class="spaces"> </span><span class="nottickedoff">&lt;&gt; help &quot;Additional option to pass to ghc&quot;))</span>
<span class="lineno"> 165 </span><span class="spaces"> </span><span class="nottickedoff">&lt;*&gt; optional (strOption (long &quot;self&quot;</span>
<span class="lineno"> 166 </span><span class="spaces"> </span><span class="nottickedoff">&lt;&gt; metavar &quot;PATH&quot;</span>
<span class="lineno"> 167 </span><span class="spaces"> </span><span class="nottickedoff">&lt;&gt; help &quot;Source file used for live-reloading&quot;))</span></span>
<span class="lineno"> 168 </span>
<span class="lineno"> 169 </span>renderCommand :: ParserInfo Command
<span class="lineno"> 170 </span><span class="decl"><span class="nottickedoff">renderCommand = info parse</span>
<span class="lineno"> 171 </span><span class="spaces"> </span><span class="nottickedoff">(progDesc &quot;Render animation to file.&quot;)</span>
<span class="lineno"> 172 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 173 </span><span class="spaces"> </span><span class="nottickedoff">-- fromPreset :: (Maybe Preset -&gt; (Command -&gt; Command))</span>
<span class="lineno"> 174 </span><span class="spaces"> </span><span class="nottickedoff">-- fromPreset Nothing = id</span>
<span class="lineno"> 175 </span><span class="spaces"> </span><span class="nottickedoff">-- fromPreset (Just ExampleGif) = \cmd -&gt; cmd{renderFPS=24}</span>
<span class="lineno"> 176 </span><span class="spaces"> </span><span class="nottickedoff">-- modParser :: Parser (Command -&gt; Command)</span>
<span class="lineno"> 177 </span><span class="spaces"> </span><span class="nottickedoff">-- modParser = fmap fromPreset $</span>
<span class="lineno"> 178 </span><span class="spaces"> </span><span class="nottickedoff">-- optional (option (maybeReader readPreset)</span>
<span class="lineno"> 179 </span><span class="spaces"> </span><span class="nottickedoff">-- (long &quot;preset&quot; &lt;&gt; showDefaultWith showPreset</span>
<span class="lineno"> 180 </span><span class="spaces"> </span><span class="nottickedoff">-- &lt;&gt; metavar &quot;TYPE&quot;</span>
<span class="lineno"> 181 </span><span class="spaces"> </span><span class="nottickedoff">-- &lt;&gt; help &quot;Parameter presets: youtube, gif, quick&quot;))</span>
<span class="lineno"> 182 </span><span class="spaces"> </span><span class="nottickedoff">parse = Render</span>
<span class="lineno"> 183 </span><span class="spaces"> </span><span class="nottickedoff">&lt;$&gt; optional (strOption (long &quot;target&quot;</span>
<span class="lineno"> 184 </span><span class="spaces"> </span><span class="nottickedoff">&lt;&gt; short 'o'</span>
<span class="lineno"> 185 </span><span class="spaces"> </span><span class="nottickedoff">&lt;&gt; metavar &quot;FILE&quot;</span>
<span class="lineno"> 186 </span><span class="spaces"> </span><span class="nottickedoff">&lt;&gt; help &quot;Write output to FILE&quot;))</span>
<span class="lineno"> 187 </span><span class="spaces"> </span><span class="nottickedoff">&lt;*&gt; optional (option auto</span>
<span class="lineno"> 188 </span><span class="spaces"> </span><span class="nottickedoff">(long &quot;fps&quot; &lt;&gt; metavar &quot;FPS&quot;</span>
<span class="lineno"> 189 </span><span class="spaces"> </span><span class="nottickedoff">&lt;&gt; help &quot;Set frames per second.&quot;))</span>
<span class="lineno"> 190 </span><span class="spaces"> </span><span class="nottickedoff">&lt;*&gt; optional (option auto</span>
<span class="lineno"> 191 </span><span class="spaces"> </span><span class="nottickedoff">(long &quot;width&quot; &lt;&gt; short 'w' &lt;&gt; metavar &quot;PIXELS&quot;</span>
<span class="lineno"> 192 </span><span class="spaces"> </span><span class="nottickedoff">&lt;&gt; help &quot;Set video width.&quot;))</span>
<span class="lineno"> 193 </span><span class="spaces"> </span><span class="nottickedoff">&lt;*&gt; optional (option auto</span>
<span class="lineno"> 194 </span><span class="spaces"> </span><span class="nottickedoff">(long &quot;height&quot; &lt;&gt; short 'h'</span>
<span class="lineno"> 195 </span><span class="spaces"> </span><span class="nottickedoff">&lt;&gt; metavar &quot;PIXELS&quot; &lt;&gt; help &quot;Set video height.&quot;))</span>
<span class="lineno"> 196 </span><span class="spaces"> </span><span class="nottickedoff">&lt;*&gt; switch (long &quot;compile&quot;</span>
<span class="lineno"> 197 </span><span class="spaces"> </span><span class="nottickedoff">&lt;&gt; help &quot;Compile source code before rendering.&quot;)</span>
<span class="lineno"> 198 </span><span class="spaces"> </span><span class="nottickedoff">&lt;*&gt; optional (option (maybeReader readFormat)</span>
<span class="lineno"> 199 </span><span class="spaces"> </span><span class="nottickedoff">(long &quot;format&quot; &lt;&gt; metavar &quot;FMT&quot;</span>
<span class="lineno"> 200 </span><span class="spaces"> </span><span class="nottickedoff">&lt;&gt; help &quot;Video format: mp4, gif, webm&quot;))</span>
<span class="lineno"> 201 </span><span class="spaces"> </span><span class="nottickedoff">&lt;*&gt; optional (option (maybeReader readPreset)</span>
<span class="lineno"> 202 </span><span class="spaces"> </span><span class="nottickedoff">(long &quot;preset&quot; &lt;&gt; showDefaultWith showPreset</span>
<span class="lineno"> 203 </span><span class="spaces"> </span><span class="nottickedoff">&lt;&gt; metavar &quot;TYPE&quot;</span>
<span class="lineno"> 204 </span><span class="spaces"> </span><span class="nottickedoff">&lt;&gt; help &quot;Parameter presets: youtube, gif, quick, medium, high&quot;))</span>
<span class="lineno"> 205 </span><span class="spaces"> </span><span class="nottickedoff">&lt;*&gt; option (maybeReader readRaster)</span>
<span class="lineno"> 206 </span><span class="spaces"> </span><span class="nottickedoff">(long &quot;raster&quot; &lt;&gt; showDefaultWith showRaster</span>
<span class="lineno"> 207 </span><span class="spaces"> </span><span class="nottickedoff">&lt;&gt; metavar &quot;RASTER&quot;</span>
<span class="lineno"> 208 </span><span class="spaces"> </span><span class="nottickedoff">&lt;&gt; value RasterNone</span>
<span class="lineno"> 209 </span><span class="spaces"> </span><span class="nottickedoff">&lt;&gt; help &quot;Raster engine: none, auto, inkscape, rsvg, imagemagick&quot;)</span>
<span class="lineno"> 210 </span><span class="spaces"> </span><span class="nottickedoff">&lt;*&gt; switch</span>
<span class="lineno"> 211 </span><span class="spaces"> </span><span class="nottickedoff">(long &quot;partial&quot;</span>
<span class="lineno"> 212 </span><span class="spaces"> </span><span class="nottickedoff">&lt;&gt; help &quot;Produce partial animation even if frame generation was \</span>
<span class="lineno"> 213 </span><span class="spaces"> </span><span class="nottickedoff">\interrupted by ctrl-c&quot;)</span></span>
<span class="lineno"> 214 </span>
<span class="lineno"> 215 </span>opts :: ParserInfo Options
<span class="lineno"> 216 </span><span class="decl"><span class="istickedoff">opts = info (options &lt;**&gt; helper )</span>
<span class="lineno"> 217 </span><span class="spaces"> </span><span class="istickedoff">( fullDesc</span>
<span class="lineno"> 218 </span><span class="spaces"> </span><span class="istickedoff">&lt;&gt; progDesc <span class="nottickedoff">&quot;This program contains an animation which can either be viewed \</span></span>
<span class="lineno"> 219 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">\in a web-browser or rendered to disk.&quot;</span></span>
<span class="lineno"> 220 </span><span class="spaces"> </span><span class="istickedoff">)</span></span>
<span class="lineno"> 221 </span>
<span class="lineno"> 222 </span>getDriverOptions :: IO Options
<span class="lineno"> 223 </span><span class="decl"><span class="istickedoff">getDriverOptions = customExecParser (prefs showHelpOnError) opts</span></span>
<span class="lineno"> 47 </span> , <span class="nottickedoff"><span class="decl"><span class="nottickedoff">renderHash</span></span></span> :: Bool
<span class="lineno"> 48 </span> }
<span class="lineno"> 49 </span> deriving (<span class="decl"><span class="nottickedoff">Show</span></span>)
<span class="lineno"> 50 </span>
<span class="lineno"> 51 </span>data Preset = Youtube | ExampleGif | Quick | MediumQ | HighQ | LowFPS
<span class="lineno"> 52 </span> deriving (<span class="decl"><span class="nottickedoff">Show</span></span>)
<span class="lineno"> 53 </span>
<span class="lineno"> 54 </span>readRaster :: String -&gt; Maybe Raster
<span class="lineno"> 55 </span><span class="decl"><span class="nottickedoff">readRaster raster =</span>
<span class="lineno"> 56 </span><span class="spaces"> </span><span class="nottickedoff">case map toLower raster of</span>
<span class="lineno"> 57 </span><span class="spaces"> </span><span class="nottickedoff">&quot;none&quot; -&gt; Just RasterNone</span>
<span class="lineno"> 58 </span><span class="spaces"> </span><span class="nottickedoff">&quot;auto&quot; -&gt; Just RasterAuto</span>
<span class="lineno"> 59 </span><span class="spaces"> </span><span class="nottickedoff">&quot;inkscape&quot; -&gt; Just RasterInkscape</span>
<span class="lineno"> 60 </span><span class="spaces"> </span><span class="nottickedoff">&quot;rsvg&quot; -&gt; Just RasterRSvg</span>
<span class="lineno"> 61 </span><span class="spaces"> </span><span class="nottickedoff">&quot;imagemagick&quot; -&gt; Just RasterMagick</span>
<span class="lineno"> 62 </span><span class="spaces"> </span><span class="nottickedoff">_ -&gt; Nothing</span></span>
<span class="lineno"> 63 </span>
<span class="lineno"> 64 </span>showRaster :: Raster -&gt; String
<span class="lineno"> 65 </span><span class="decl"><span class="nottickedoff">showRaster RasterNone = &quot;none&quot;</span>
<span class="lineno"> 66 </span><span class="spaces"></span><span class="nottickedoff">showRaster RasterAuto = &quot;auto&quot;</span>
<span class="lineno"> 67 </span><span class="spaces"></span><span class="nottickedoff">showRaster RasterInkscape = &quot;inkscape&quot;</span>
<span class="lineno"> 68 </span><span class="spaces"></span><span class="nottickedoff">showRaster RasterRSvg = &quot;rsvg&quot;</span>
<span class="lineno"> 69 </span><span class="spaces"></span><span class="nottickedoff">showRaster RasterMagick = &quot;imagemagick&quot;</span></span>
<span class="lineno"> 70 </span>
<span class="lineno"> 71 </span>readFormat :: String -&gt; Maybe Format
<span class="lineno"> 72 </span><span class="decl"><span class="nottickedoff">readFormat fmt =</span>
<span class="lineno"> 73 </span><span class="spaces"> </span><span class="nottickedoff">case map toLower fmt of</span>
<span class="lineno"> 74 </span><span class="spaces"> </span><span class="nottickedoff">&quot;mp4&quot; -&gt; Just RenderMp4</span>
<span class="lineno"> 75 </span><span class="spaces"> </span><span class="nottickedoff">&quot;gif&quot; -&gt; Just RenderGif</span>
<span class="lineno"> 76 </span><span class="spaces"> </span><span class="nottickedoff">&quot;webm&quot; -&gt; Just RenderWebm</span>
<span class="lineno"> 77 </span><span class="spaces"> </span><span class="nottickedoff">_ -&gt; Nothing</span></span>
<span class="lineno"> 78 </span>
<span class="lineno"> 79 </span>showFormat :: Format -&gt; String
<span class="lineno"> 80 </span><span class="decl"><span class="nottickedoff">showFormat RenderMp4 = &quot;mp4&quot;</span>
<span class="lineno"> 81 </span><span class="spaces"></span><span class="nottickedoff">showFormat RenderGif = &quot;gif&quot;</span>
<span class="lineno"> 82 </span><span class="spaces"></span><span class="nottickedoff">showFormat RenderWebm = &quot;webm&quot;</span></span>
<span class="lineno"> 83 </span>
<span class="lineno"> 84 </span>readPreset :: String -&gt; Maybe Preset
<span class="lineno"> 85 </span><span class="decl"><span class="nottickedoff">readPreset preset =</span>
<span class="lineno"> 86 </span><span class="spaces"> </span><span class="nottickedoff">case map toLower preset of</span>
<span class="lineno"> 87 </span><span class="spaces"> </span><span class="nottickedoff">&quot;youtube&quot; -&gt; Just Youtube</span>
<span class="lineno"> 88 </span><span class="spaces"> </span><span class="nottickedoff">&quot;gif&quot; -&gt; Just ExampleGif</span>
<span class="lineno"> 89 </span><span class="spaces"> </span><span class="nottickedoff">&quot;quick&quot; -&gt; Just Quick</span>
<span class="lineno"> 90 </span><span class="spaces"> </span><span class="nottickedoff">&quot;medium&quot; -&gt; Just MediumQ</span>
<span class="lineno"> 91 </span><span class="spaces"> </span><span class="nottickedoff">&quot;high&quot; -&gt; Just HighQ</span>
<span class="lineno"> 92 </span><span class="spaces"> </span><span class="nottickedoff">&quot;lowfps&quot; -&gt; Just LowFPS</span>
<span class="lineno"> 93 </span><span class="spaces"> </span><span class="nottickedoff">_ -&gt; Nothing</span></span>
<span class="lineno"> 94 </span>
<span class="lineno"> 95 </span>showPreset :: Preset -&gt; String
<span class="lineno"> 96 </span><span class="decl"><span class="nottickedoff">showPreset Youtube = &quot;youtube&quot;</span>
<span class="lineno"> 97 </span><span class="spaces"></span><span class="nottickedoff">showPreset ExampleGif = &quot;gif&quot;</span>
<span class="lineno"> 98 </span><span class="spaces"></span><span class="nottickedoff">showPreset Quick = &quot;quick&quot;</span>
<span class="lineno"> 99 </span><span class="spaces"></span><span class="nottickedoff">showPreset MediumQ = &quot;medium&quot;</span>
<span class="lineno"> 100 </span><span class="spaces"></span><span class="nottickedoff">showPreset HighQ = &quot;high&quot;</span>
<span class="lineno"> 101 </span><span class="spaces"></span><span class="nottickedoff">showPreset LowFPS = &quot;lowfps&quot;</span></span>
<span class="lineno"> 102 </span>
<span class="lineno"> 103 </span>options :: Parser Options
<span class="lineno"> 104 </span><span class="decl"><span class="istickedoff">options = Options &lt;$&gt; commandP</span></span>
<span class="lineno"> 105 </span>
<span class="lineno"> 106 </span>commandP :: Parser Command
<span class="lineno"> 107 </span><span class="decl"><span class="istickedoff">commandP = subparser(</span>
<span class="lineno"> 108 </span><span class="spaces"> </span><span class="istickedoff">command &quot;test&quot; testCommand</span>
<span class="lineno"> 109 </span><span class="spaces"> </span><span class="istickedoff">&lt;&gt; commandGroup <span class="nottickedoff">&quot;Internal commands&quot;</span></span>
<span class="lineno"> 110 </span><span class="spaces"> </span><span class="istickedoff">&lt;&gt; internal )</span>
<span class="lineno"> 111 </span><span class="spaces"> </span><span class="istickedoff">&lt;|&gt; <span class="nottickedoff">hsubparser</span></span>
<span class="lineno"> 112 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">( command &quot;check&quot; checkCommand</span></span>
<span class="lineno"> 113 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">&lt;&gt; command &quot;view&quot; viewCommand</span></span>
<span class="lineno"> 114 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">&lt;&gt; command &quot;render&quot; renderCommand</span></span>
<span class="lineno"> 115 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">&lt;&gt; command &quot;raw&quot; rawCommand</span></span>
<span class="lineno"> 116 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">)</span></span>
<span class="lineno"> 117 </span><span class="spaces"> </span><span class="istickedoff">&lt;|&gt; <span class="nottickedoff">infoParser viewCommand</span></span></span>
<span class="lineno"> 118 </span>
<span class="lineno"> 119 </span>rawCommand :: ParserInfo Command
<span class="lineno"> 120 </span><span class="decl"><span class="nottickedoff">rawCommand = info parse</span>
<span class="lineno"> 121 </span><span class="spaces"> </span><span class="nottickedoff">(progDesc &quot;Output raw SVGs for animation at 60 fps. Used internally by viewer.&quot;)</span>
<span class="lineno"> 122 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 123 </span><span class="spaces"> </span><span class="nottickedoff">parse = Raw</span>
<span class="lineno"> 124 </span><span class="spaces"> </span><span class="nottickedoff">&lt;$&gt; strOption</span>
<span class="lineno"> 125 </span><span class="spaces"> </span><span class="nottickedoff">( long &quot;output&quot; &lt;&gt;</span>
<span class="lineno"> 126 </span><span class="spaces"> </span><span class="nottickedoff">short 'o' &lt;&gt;</span>
<span class="lineno"> 127 </span><span class="spaces"> </span><span class="nottickedoff">metavar &quot;PATH&quot; &lt;&gt;</span>
<span class="lineno"> 128 </span><span class="spaces"> </span><span class="nottickedoff">help &quot;Output folder&quot; &lt;&gt;</span>
<span class="lineno"> 129 </span><span class="spaces"> </span><span class="nottickedoff">value &quot;.&quot;)</span>
<span class="lineno"> 130 </span><span class="spaces"> </span><span class="nottickedoff">&lt;*&gt; option auto</span>
<span class="lineno"> 131 </span><span class="spaces"> </span><span class="nottickedoff">( long &quot;offset&quot; &lt;&gt;</span>
<span class="lineno"> 132 </span><span class="spaces"> </span><span class="nottickedoff">metavar &quot;NUMBER&quot; &lt;&gt;</span>
<span class="lineno"> 133 </span><span class="spaces"> </span><span class="nottickedoff">help &quot;Frame offset&quot; &lt;&gt;</span>
<span class="lineno"> 134 </span><span class="spaces"> </span><span class="nottickedoff">value 0)</span>
<span class="lineno"> 135 </span><span class="spaces"> </span><span class="nottickedoff">&lt;*&gt; switch</span>
<span class="lineno"> 136 </span><span class="spaces"> </span><span class="nottickedoff">( long &quot;pretty-print&quot; &lt;&gt;</span>
<span class="lineno"> 137 </span><span class="spaces"> </span><span class="nottickedoff">short 'p' &lt;&gt;</span>
<span class="lineno"> 138 </span><span class="spaces"> </span><span class="nottickedoff">help &quot;Pretty print svg&quot;)</span></span>
<span class="lineno"> 139 </span>
<span class="lineno"> 140 </span>testCommand :: ParserInfo Command
<span class="lineno"> 141 </span><span class="decl"><span class="istickedoff">testCommand = info (parse &lt;**&gt; helper)</span>
<span class="lineno"> 142 </span><span class="spaces"> </span><span class="istickedoff">(progDesc <span class="nottickedoff">&quot;Generate 10 frames spread out evenly across the animation. Used \</span></span>
<span class="lineno"> 143 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">\internally by the test-suite.&quot;</span>)</span>
<span class="lineno"> 144 </span><span class="spaces"> </span><span class="istickedoff">where</span>
<span class="lineno"> 145 </span><span class="spaces"> </span><span class="istickedoff">parse = pure Test</span></span>
<span class="lineno"> 146 </span>
<span class="lineno"> 147 </span>checkCommand :: ParserInfo Command
<span class="lineno"> 148 </span><span class="decl"><span class="nottickedoff">checkCommand = info parse</span>
<span class="lineno"> 149 </span><span class="spaces"> </span><span class="nottickedoff">(progDesc &quot;Run a system's diagnostic and report any missing external dependencies.&quot;)</span>
<span class="lineno"> 150 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 151 </span><span class="spaces"> </span><span class="nottickedoff">parse = pure Check</span></span>
<span class="lineno"> 152 </span>
<span class="lineno"> 153 </span>viewCommand :: ParserInfo Command
<span class="lineno"> 154 </span><span class="decl"><span class="nottickedoff">viewCommand = info parse</span>
<span class="lineno"> 155 </span><span class="spaces"> </span><span class="nottickedoff">(progDesc &quot;Play animation in browser window.&quot;)</span>
<span class="lineno"> 156 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 157 </span><span class="spaces"> </span><span class="nottickedoff">parse = View</span>
<span class="lineno"> 158 </span><span class="spaces"> </span><span class="nottickedoff">&lt;$&gt; switch</span>
<span class="lineno"> 159 </span><span class="spaces"> </span><span class="nottickedoff">(long &quot;verbose&quot; &lt;&gt; short 'v')</span>
<span class="lineno"> 160 </span><span class="spaces"> </span><span class="nottickedoff">&lt;*&gt; optional (strOption (long &quot;ghc&quot;</span>
<span class="lineno"> 161 </span><span class="spaces"> </span><span class="nottickedoff">&lt;&gt; metavar &quot;PATH&quot;</span>
<span class="lineno"> 162 </span><span class="spaces"> </span><span class="nottickedoff">&lt;&gt; help &quot;Path to GHC binary&quot;))</span>
<span class="lineno"> 163 </span><span class="spaces"> </span><span class="nottickedoff">&lt;*&gt; many (strOption (long &quot;ghc-opt&quot;</span>
<span class="lineno"> 164 </span><span class="spaces"> </span><span class="nottickedoff">&lt;&gt; short 'G'</span>
<span class="lineno"> 165 </span><span class="spaces"> </span><span class="nottickedoff">&lt;&gt; help &quot;Additional option to pass to ghc&quot;))</span>
<span class="lineno"> 166 </span><span class="spaces"> </span><span class="nottickedoff">&lt;*&gt; optional (strOption (long &quot;self&quot;</span>
<span class="lineno"> 167 </span><span class="spaces"> </span><span class="nottickedoff">&lt;&gt; metavar &quot;PATH&quot;</span>
<span class="lineno"> 168 </span><span class="spaces"> </span><span class="nottickedoff">&lt;&gt; help &quot;Source file used for live-reloading&quot;))</span></span>
<span class="lineno"> 169 </span>
<span class="lineno"> 170 </span>renderCommand :: ParserInfo Command
<span class="lineno"> 171 </span><span class="decl"><span class="nottickedoff">renderCommand = info parse</span>
<span class="lineno"> 172 </span><span class="spaces"> </span><span class="nottickedoff">(progDesc &quot;Render animation to file.&quot;)</span>
<span class="lineno"> 173 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 174 </span><span class="spaces"> </span><span class="nottickedoff">-- fromPreset :: (Maybe Preset -&gt; (Command -&gt; Command))</span>
<span class="lineno"> 175 </span><span class="spaces"> </span><span class="nottickedoff">-- fromPreset Nothing = id</span>
<span class="lineno"> 176 </span><span class="spaces"> </span><span class="nottickedoff">-- fromPreset (Just ExampleGif) = \cmd -&gt; cmd{renderFPS=24}</span>
<span class="lineno"> 177 </span><span class="spaces"> </span><span class="nottickedoff">-- modParser :: Parser (Command -&gt; Command)</span>
<span class="lineno"> 178 </span><span class="spaces"> </span><span class="nottickedoff">-- modParser = fmap fromPreset $</span>
<span class="lineno"> 179 </span><span class="spaces"> </span><span class="nottickedoff">-- optional (option (maybeReader readPreset)</span>
<span class="lineno"> 180 </span><span class="spaces"> </span><span class="nottickedoff">-- (long &quot;preset&quot; &lt;&gt; showDefaultWith showPreset</span>
<span class="lineno"> 181 </span><span class="spaces"> </span><span class="nottickedoff">-- &lt;&gt; metavar &quot;TYPE&quot;</span>
<span class="lineno"> 182 </span><span class="spaces"> </span><span class="nottickedoff">-- &lt;&gt; help &quot;Parameter presets: youtube, gif, quick&quot;))</span>
<span class="lineno"> 183 </span><span class="spaces"> </span><span class="nottickedoff">parse = Render</span>
<span class="lineno"> 184 </span><span class="spaces"> </span><span class="nottickedoff">&lt;$&gt; optional (strOption (long &quot;target&quot;</span>
<span class="lineno"> 185 </span><span class="spaces"> </span><span class="nottickedoff">&lt;&gt; short 'o'</span>
<span class="lineno"> 186 </span><span class="spaces"> </span><span class="nottickedoff">&lt;&gt; metavar &quot;FILE&quot;</span>
<span class="lineno"> 187 </span><span class="spaces"> </span><span class="nottickedoff">&lt;&gt; help &quot;Write output to FILE&quot;))</span>
<span class="lineno"> 188 </span><span class="spaces"> </span><span class="nottickedoff">&lt;*&gt; optional (option auto</span>
<span class="lineno"> 189 </span><span class="spaces"> </span><span class="nottickedoff">(long &quot;fps&quot; &lt;&gt; metavar &quot;FPS&quot;</span>
<span class="lineno"> 190 </span><span class="spaces"> </span><span class="nottickedoff">&lt;&gt; help &quot;Set frames per second.&quot;))</span>
<span class="lineno"> 191 </span><span class="spaces"> </span><span class="nottickedoff">&lt;*&gt; optional (option auto</span>
<span class="lineno"> 192 </span><span class="spaces"> </span><span class="nottickedoff">(long &quot;width&quot; &lt;&gt; short 'w' &lt;&gt; metavar &quot;PIXELS&quot;</span>
<span class="lineno"> 193 </span><span class="spaces"> </span><span class="nottickedoff">&lt;&gt; help &quot;Set video width.&quot;))</span>
<span class="lineno"> 194 </span><span class="spaces"> </span><span class="nottickedoff">&lt;*&gt; optional (option auto</span>
<span class="lineno"> 195 </span><span class="spaces"> </span><span class="nottickedoff">(long &quot;height&quot; &lt;&gt; short 'h'</span>
<span class="lineno"> 196 </span><span class="spaces"> </span><span class="nottickedoff">&lt;&gt; metavar &quot;PIXELS&quot; &lt;&gt; help &quot;Set video height.&quot;))</span>
<span class="lineno"> 197 </span><span class="spaces"> </span><span class="nottickedoff">&lt;*&gt; switch (long &quot;compile&quot;</span>
<span class="lineno"> 198 </span><span class="spaces"> </span><span class="nottickedoff">&lt;&gt; help &quot;Compile source code before rendering.&quot;)</span>
<span class="lineno"> 199 </span><span class="spaces"> </span><span class="nottickedoff">&lt;*&gt; optional (option (maybeReader readFormat)</span>
<span class="lineno"> 200 </span><span class="spaces"> </span><span class="nottickedoff">(long &quot;format&quot; &lt;&gt; metavar &quot;FMT&quot;</span>
<span class="lineno"> 201 </span><span class="spaces"> </span><span class="nottickedoff">&lt;&gt; help &quot;Video format: mp4, gif, webm&quot;))</span>
<span class="lineno"> 202 </span><span class="spaces"> </span><span class="nottickedoff">&lt;*&gt; optional (option (maybeReader readPreset)</span>
<span class="lineno"> 203 </span><span class="spaces"> </span><span class="nottickedoff">(long &quot;preset&quot; &lt;&gt; showDefaultWith showPreset</span>
<span class="lineno"> 204 </span><span class="spaces"> </span><span class="nottickedoff">&lt;&gt; metavar &quot;TYPE&quot;</span>
<span class="lineno"> 205 </span><span class="spaces"> </span><span class="nottickedoff">&lt;&gt; help &quot;Parameter presets: youtube, gif, quick, medium, high&quot;))</span>
<span class="lineno"> 206 </span><span class="spaces"> </span><span class="nottickedoff">&lt;*&gt; option (maybeReader readRaster)</span>
<span class="lineno"> 207 </span><span class="spaces"> </span><span class="nottickedoff">(long &quot;raster&quot; &lt;&gt; showDefaultWith showRaster</span>
<span class="lineno"> 208 </span><span class="spaces"> </span><span class="nottickedoff">&lt;&gt; metavar &quot;RASTER&quot;</span>
<span class="lineno"> 209 </span><span class="spaces"> </span><span class="nottickedoff">&lt;&gt; value RasterNone</span>
<span class="lineno"> 210 </span><span class="spaces"> </span><span class="nottickedoff">&lt;&gt; help &quot;Raster engine: none, auto, inkscape, rsvg, imagemagick&quot;)</span>
<span class="lineno"> 211 </span><span class="spaces"> </span><span class="nottickedoff">&lt;*&gt; switch</span>
<span class="lineno"> 212 </span><span class="spaces"> </span><span class="nottickedoff">(long &quot;partial&quot;</span>
<span class="lineno"> 213 </span><span class="spaces"> </span><span class="nottickedoff">&lt;&gt; help &quot;Produce partial animation even if frame generation was \</span>
<span class="lineno"> 214 </span><span class="spaces"> </span><span class="nottickedoff">\interrupted by ctrl-c&quot;)</span>
<span class="lineno"> 215 </span><span class="spaces"> </span><span class="nottickedoff">&lt;*&gt; flag True False</span>
<span class="lineno"> 216 </span><span class="spaces"> </span><span class="nottickedoff">(long &quot;disable-hashing&quot;</span>
<span class="lineno"> 217 </span><span class="spaces"> </span><span class="nottickedoff">&lt;&gt; help &quot;Disable SVG dedup via hashing. This might improve performance \</span>
<span class="lineno"> 218 </span><span class="spaces"> </span><span class="nottickedoff">\if all your frames are unique.&quot;)</span></span>
<span class="lineno"> 219 </span>
<span class="lineno"> 220 </span>opts :: ParserInfo Options
<span class="lineno"> 221 </span><span class="decl"><span class="istickedoff">opts = info (options &lt;**&gt; helper )</span>
<span class="lineno"> 222 </span><span class="spaces"> </span><span class="istickedoff">( fullDesc</span>
<span class="lineno"> 223 </span><span class="spaces"> </span><span class="istickedoff">&lt;&gt; progDesc <span class="nottickedoff">&quot;This program contains an animation which can either be viewed \</span></span>
<span class="lineno"> 224 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">\in a web-browser or rendered to disk.&quot;</span></span>
<span class="lineno"> 225 </span><span class="spaces"> </span><span class="istickedoff">)</span></span>
<span class="lineno"> 226 </span>
<span class="lineno"> 227 </span>getDriverOptions :: IO Options
<span class="lineno"> 228 </span><span class="decl"><span class="istickedoff">getDriverOptions = customExecParser (prefs showHelpOnError) opts</span></span>
</pre>
</body>

View file

@ -83,368 +83,363 @@ span.spaces { background: white }
<span class="lineno"> 64 </span><span class="decl"><span class="nottickedoff">renderSvgs folder offset _prettyPrint ani = do</span>
<span class="lineno"> 65 </span><span class="spaces"> </span><span class="nottickedoff">print frameCount</span>
<span class="lineno"> 66 </span><span class="spaces"> </span><span class="nottickedoff">lock &lt;- newMVar ()</span>
<span class="lineno"> 67 </span><span class="spaces"> </span><span class="nottickedoff">hashedFrames &lt;- newMVar M.empty</span>
<span class="lineno"> 68 </span><span class="spaces"> </span><span class="nottickedoff">handle errHandler $ concurrentForM_ (frameOrder rate frameCount) $ \nth' -&gt; do</span>
<span class="lineno"> 69 </span><span class="spaces"> </span><span class="nottickedoff">let nth = (nth'+offset) `mod` frameCount</span>
<span class="lineno"> 70 </span><span class="spaces"> </span><span class="nottickedoff">now = (duration ani / (fromIntegral frameCount - 1)) * fromIntegral nth</span>
<span class="lineno"> 71 </span><span class="spaces"> </span><span class="nottickedoff">frame = frameAt (if frameCount &lt;= 1 then 0 else now) ani</span>
<span class="lineno"> 72 </span><span class="spaces"> </span><span class="nottickedoff">path = folder &lt;/&gt; show nth &lt;.&gt; &quot;svg&quot;</span>
<span class="lineno"> 73 </span><span class="spaces"> </span><span class="nottickedoff">cachedFrame &lt;- M.lookup frame &lt;$&gt; readMVar hashedFrames</span>
<span class="lineno"> 67 </span><span class="spaces"> </span><span class="nottickedoff">handle errHandler $ concurrentForM_ (frameOrder rate frameCount) $ \nth' -&gt; do</span>
<span class="lineno"> 68 </span><span class="spaces"> </span><span class="nottickedoff">let nth = (nth'+offset) `mod` frameCount</span>
<span class="lineno"> 69 </span><span class="spaces"> </span><span class="nottickedoff">now = (duration ani / (fromIntegral frameCount - 1)) * fromIntegral nth</span>
<span class="lineno"> 70 </span><span class="spaces"> </span><span class="nottickedoff">frame = frameAt (if frameCount &lt;= 1 then 0 else now) ani</span>
<span class="lineno"> 71 </span><span class="spaces"> </span><span class="nottickedoff">path = folder &lt;/&gt; show nth &lt;.&gt; &quot;svg&quot;</span>
<span class="lineno"> 72 </span><span class="spaces"> </span><span class="nottickedoff">~svg = renderSvg Nothing Nothing frame</span>
<span class="lineno"> 73 </span><span class="spaces"></span><span class="nottickedoff"></span>
<span class="lineno"> 74 </span><span class="spaces"> </span><span class="nottickedoff">idempotentFile path $</span>
<span class="lineno"> 75 </span><span class="spaces"> </span><span class="nottickedoff">case cachedFrame of </span>
<span class="lineno"> 76 </span><span class="spaces"> </span><span class="nottickedoff">Nothing -&gt; do</span>
<span class="lineno"> 77 </span><span class="spaces"> </span><span class="nottickedoff">let svg = renderSvg Nothing Nothing frame</span>
<span class="lineno"> 78 </span><span class="spaces"> </span><span class="nottickedoff">writeFile path svg</span>
<span class="lineno"> 79 </span><span class="spaces"> </span><span class="nottickedoff">modifyMVar_ hashedFrames $ \hm -&gt; pure $ M.insert frame path hm</span>
<span class="lineno"> 80 </span><span class="spaces"> </span><span class="nottickedoff">Just frameFile -&gt; copyFile frameFile path</span>
<span class="lineno"> 81 </span><span class="spaces"> </span><span class="nottickedoff">withMVar lock $ \_ -&gt; do</span>
<span class="lineno"> 82 </span><span class="spaces"> </span><span class="nottickedoff">print nth</span>
<span class="lineno"> 83 </span><span class="spaces"> </span><span class="nottickedoff">hFlush stdout</span>
<span class="lineno"> 84 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 85 </span><span class="spaces"> </span><span class="nottickedoff">rate = 60</span>
<span class="lineno"> 86 </span><span class="spaces"> </span><span class="nottickedoff">frameCount = round (duration ani * fromIntegral rate) :: Int</span>
<span class="lineno"> 87 </span><span class="spaces"> </span><span class="nottickedoff">errHandler (ErrorCall msg) = do</span>
<span class="lineno"> 88 </span><span class="spaces"> </span><span class="nottickedoff">hPutStrLn stderr msg</span>
<span class="lineno"> 89 </span><span class="spaces"> </span><span class="nottickedoff">exitWith (ExitFailure 1)</span></span>
<span class="lineno"> 90 </span>
<span class="lineno"> 91 </span>-- | Render as many frames as possible in 2 seconds. Limited to 20 frames.
<span class="lineno"> 92 </span>renderLimitedFrames :: FilePath -&gt; Int -&gt; Bool -&gt; Int -&gt; Animation -&gt; IO ()
<span class="lineno"> 93 </span><span class="decl"><span class="nottickedoff">renderLimitedFrames folder offset _prettyPrint rate ani = do</span>
<span class="lineno"> 94 </span><span class="spaces"> </span><span class="nottickedoff">now &lt;- getCurrentTime</span>
<span class="lineno"> 95 </span><span class="spaces"> </span><span class="nottickedoff">worker (addUTCTime timeLimit now) frameLimit (frameOrder rate frameCount)</span>
<span class="lineno"> 96 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 97 </span><span class="spaces"> </span><span class="nottickedoff">timeLimit = 2</span>
<span class="lineno"> 98 </span><span class="spaces"> </span><span class="nottickedoff">frameLimit = 20 :: Int</span>
<span class="lineno"> 99 </span><span class="spaces"> </span><span class="nottickedoff">worker _ 0 _ = return ()</span>
<span class="lineno"> 100 </span><span class="spaces"> </span><span class="nottickedoff">worker _ _ [] = putStrLn &quot;Done&quot;</span>
<span class="lineno"> 101 </span><span class="spaces"> </span><span class="nottickedoff">worker localTimeLimit l (x:xs) = do</span>
<span class="lineno"> 102 </span><span class="spaces"> </span><span class="nottickedoff">curTime &lt;- getCurrentTime</span>
<span class="lineno"> 103 </span><span class="spaces"> </span><span class="nottickedoff">if curTime &gt; localTimeLimit</span>
<span class="lineno"> 104 </span><span class="spaces"> </span><span class="nottickedoff">then return ()</span>
<span class="lineno"> 105 </span><span class="spaces"> </span><span class="nottickedoff">else do</span>
<span class="lineno"> 106 </span><span class="spaces"> </span><span class="nottickedoff">let nth = (x+offset) `mod` frameCount</span>
<span class="lineno"> 107 </span><span class="spaces"> </span><span class="nottickedoff">now = (duration ani / (fromIntegral frameCount - 1)) * fromIntegral nth</span>
<span class="lineno"> 108 </span><span class="spaces"> </span><span class="nottickedoff">frame = frameAt (if frameCount &lt;= 1 then 0 else now) ani</span>
<span class="lineno"> 109 </span><span class="spaces"> </span><span class="nottickedoff">svg = renderSvg Nothing Nothing frame</span>
<span class="lineno"> 110 </span><span class="spaces"> </span><span class="nottickedoff">path = folder &lt;/&gt; show nth &lt;.&gt; &quot;svg&quot;</span>
<span class="lineno"> 111 </span><span class="spaces"> </span><span class="nottickedoff">tmpPath = path &lt;.&gt; &quot;tmp&quot;</span>
<span class="lineno"> 112 </span><span class="spaces"> </span><span class="nottickedoff">haveFile &lt;- doesFileExist path</span>
<span class="lineno"> 113 </span><span class="spaces"> </span><span class="nottickedoff">if haveFile</span>
<span class="lineno"> 114 </span><span class="spaces"> </span><span class="nottickedoff">then worker localTimeLimit l xs</span>
<span class="lineno"> 115 </span><span class="spaces"> </span><span class="nottickedoff">else do</span>
<span class="lineno"> 116 </span><span class="spaces"> </span><span class="nottickedoff">writeFile tmpPath svg</span>
<span class="lineno"> 117 </span><span class="spaces"> </span><span class="nottickedoff">renameOrCopyFile tmpPath path</span>
<span class="lineno"> 118 </span><span class="spaces"> </span><span class="nottickedoff">print nth</span>
<span class="lineno"> 119 </span><span class="spaces"> </span><span class="nottickedoff">worker localTimeLimit (l-1) xs</span>
<span class="lineno"> 120 </span><span class="spaces"> </span><span class="nottickedoff">frameCount = round (duration ani * fromIntegral rate) :: Int</span></span>
<span class="lineno"> 121 </span>
<span class="lineno"> 122 </span>-- XXX: Merge with 'renderSvgs'
<span class="lineno"> 123 </span>-- | Render 10 frames and print them to stdout. Used for testing.
<span class="lineno"> 124 </span>--
<span class="lineno"> 125 </span>-- XXX: Not related to the snippets in the playground.
<span class="lineno"> 126 </span>renderSnippets :: Animation -&gt; IO ()
<span class="lineno"> 127 </span><span class="decl"><span class="istickedoff">renderSnippets ani = forM_ [0 .. frameCount - 1] $ \nth -&gt; do</span>
<span class="lineno"> 128 </span><span class="spaces"> </span><span class="istickedoff">let now = (duration ani / (fromIntegral frameCount - 1)) * fromIntegral nth</span>
<span class="lineno"> 129 </span><span class="spaces"> </span><span class="istickedoff">frame = frameAt now ani</span>
<span class="lineno"> 130 </span><span class="spaces"> </span><span class="istickedoff">svg = renderSvg Nothing Nothing frame</span>
<span class="lineno"> 131 </span><span class="spaces"> </span><span class="istickedoff">putStr (show nth)</span>
<span class="lineno"> 132 </span><span class="spaces"> </span><span class="istickedoff">T.putStrLn $ T.concat . T.lines . T.pack $ svg</span>
<span class="lineno"> 133 </span><span class="spaces"> </span><span class="istickedoff">where frameCount = 10 :: Integer</span></span>
<span class="lineno"> 134 </span>
<span class="lineno"> 135 </span>frameOrder :: Int -&gt; Int -&gt; [Int]
<span class="lineno"> 136 </span><span class="decl"><span class="nottickedoff">frameOrder fps nFrames = worker [] fps</span>
<span class="lineno"> 137 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 138 </span><span class="spaces"> </span><span class="nottickedoff">worker _seen 0 = []</span>
<span class="lineno"> 139 </span><span class="spaces"> </span><span class="nottickedoff">worker seen nthFrame = filterFrameList seen nthFrame nFrames</span>
<span class="lineno"> 140 </span><span class="spaces"> </span><span class="nottickedoff">++ worker (nthFrame : seen) (nthFrame `div` 2)</span></span>
<span class="lineno"> 75 </span><span class="spaces"> </span><span class="nottickedoff">writeFile path svg</span>
<span class="lineno"> 76 </span><span class="spaces"> </span><span class="nottickedoff">withMVar lock $ \_ -&gt; do</span>
<span class="lineno"> 77 </span><span class="spaces"> </span><span class="nottickedoff">print nth</span>
<span class="lineno"> 78 </span><span class="spaces"> </span><span class="nottickedoff">hFlush stdout</span>
<span class="lineno"> 79 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 80 </span><span class="spaces"> </span><span class="nottickedoff">rate = 60</span>
<span class="lineno"> 81 </span><span class="spaces"> </span><span class="nottickedoff">frameCount = round (duration ani * fromIntegral rate) :: Int</span>
<span class="lineno"> 82 </span><span class="spaces"> </span><span class="nottickedoff">errHandler (ErrorCall msg) = do</span>
<span class="lineno"> 83 </span><span class="spaces"> </span><span class="nottickedoff">hPutStrLn stderr msg</span>
<span class="lineno"> 84 </span><span class="spaces"> </span><span class="nottickedoff">exitWith (ExitFailure 1)</span></span>
<span class="lineno"> 85 </span>
<span class="lineno"> 86 </span>-- | Render as many frames as possible in 2 seconds. Limited to 20 frames.
<span class="lineno"> 87 </span>renderLimitedFrames :: FilePath -&gt; Int -&gt; Bool -&gt; Int -&gt; Animation -&gt; IO ()
<span class="lineno"> 88 </span><span class="decl"><span class="nottickedoff">renderLimitedFrames folder offset _prettyPrint rate ani = do</span>
<span class="lineno"> 89 </span><span class="spaces"> </span><span class="nottickedoff">now &lt;- getCurrentTime</span>
<span class="lineno"> 90 </span><span class="spaces"> </span><span class="nottickedoff">worker (addUTCTime timeLimit now) frameLimit (frameOrder rate frameCount)</span>
<span class="lineno"> 91 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 92 </span><span class="spaces"> </span><span class="nottickedoff">timeLimit = 2</span>
<span class="lineno"> 93 </span><span class="spaces"> </span><span class="nottickedoff">frameLimit = 20 :: Int</span>
<span class="lineno"> 94 </span><span class="spaces"> </span><span class="nottickedoff">worker _ 0 _ = return ()</span>
<span class="lineno"> 95 </span><span class="spaces"> </span><span class="nottickedoff">worker _ _ [] = putStrLn &quot;Done&quot;</span>
<span class="lineno"> 96 </span><span class="spaces"> </span><span class="nottickedoff">worker localTimeLimit l (x:xs) = do</span>
<span class="lineno"> 97 </span><span class="spaces"> </span><span class="nottickedoff">curTime &lt;- getCurrentTime</span>
<span class="lineno"> 98 </span><span class="spaces"> </span><span class="nottickedoff">if curTime &gt; localTimeLimit</span>
<span class="lineno"> 99 </span><span class="spaces"> </span><span class="nottickedoff">then return ()</span>
<span class="lineno"> 100 </span><span class="spaces"> </span><span class="nottickedoff">else do</span>
<span class="lineno"> 101 </span><span class="spaces"> </span><span class="nottickedoff">let nth = (x+offset) `mod` frameCount</span>
<span class="lineno"> 102 </span><span class="spaces"> </span><span class="nottickedoff">now = (duration ani / (fromIntegral frameCount - 1)) * fromIntegral nth</span>
<span class="lineno"> 103 </span><span class="spaces"> </span><span class="nottickedoff">frame = frameAt (if frameCount &lt;= 1 then 0 else now) ani</span>
<span class="lineno"> 104 </span><span class="spaces"> </span><span class="nottickedoff">svg = renderSvg Nothing Nothing frame</span>
<span class="lineno"> 105 </span><span class="spaces"> </span><span class="nottickedoff">path = folder &lt;/&gt; show nth &lt;.&gt; &quot;svg&quot;</span>
<span class="lineno"> 106 </span><span class="spaces"> </span><span class="nottickedoff">tmpPath = path &lt;.&gt; &quot;tmp&quot;</span>
<span class="lineno"> 107 </span><span class="spaces"> </span><span class="nottickedoff">haveFile &lt;- doesFileExist path</span>
<span class="lineno"> 108 </span><span class="spaces"> </span><span class="nottickedoff">if haveFile</span>
<span class="lineno"> 109 </span><span class="spaces"> </span><span class="nottickedoff">then worker localTimeLimit l xs</span>
<span class="lineno"> 110 </span><span class="spaces"> </span><span class="nottickedoff">else do</span>
<span class="lineno"> 111 </span><span class="spaces"> </span><span class="nottickedoff">writeFile tmpPath svg</span>
<span class="lineno"> 112 </span><span class="spaces"> </span><span class="nottickedoff">renameOrCopyFile tmpPath path</span>
<span class="lineno"> 113 </span><span class="spaces"> </span><span class="nottickedoff">print nth</span>
<span class="lineno"> 114 </span><span class="spaces"> </span><span class="nottickedoff">worker localTimeLimit (l-1) xs</span>
<span class="lineno"> 115 </span><span class="spaces"> </span><span class="nottickedoff">frameCount = round (duration ani * fromIntegral rate) :: Int</span></span>
<span class="lineno"> 116 </span>
<span class="lineno"> 117 </span>-- XXX: Merge with 'renderSvgs'
<span class="lineno"> 118 </span>-- | Render 10 frames and print them to stdout. Used for testing.
<span class="lineno"> 119 </span>--
<span class="lineno"> 120 </span>-- XXX: Not related to the snippets in the playground.
<span class="lineno"> 121 </span>renderSnippets :: Animation -&gt; IO ()
<span class="lineno"> 122 </span><span class="decl"><span class="istickedoff">renderSnippets ani = forM_ [0 .. frameCount - 1] $ \nth -&gt; do</span>
<span class="lineno"> 123 </span><span class="spaces"> </span><span class="istickedoff">let now = (duration ani / (fromIntegral frameCount - 1)) * fromIntegral nth</span>
<span class="lineno"> 124 </span><span class="spaces"> </span><span class="istickedoff">frame = frameAt now ani</span>
<span class="lineno"> 125 </span><span class="spaces"> </span><span class="istickedoff">svg = renderSvg Nothing Nothing frame</span>
<span class="lineno"> 126 </span><span class="spaces"> </span><span class="istickedoff">putStr (show nth)</span>
<span class="lineno"> 127 </span><span class="spaces"> </span><span class="istickedoff">T.putStrLn $ T.concat . T.lines . T.pack $ svg</span>
<span class="lineno"> 128 </span><span class="spaces"> </span><span class="istickedoff">where frameCount = 10 :: Integer</span></span>
<span class="lineno"> 129 </span>
<span class="lineno"> 130 </span>frameOrder :: Int -&gt; Int -&gt; [Int]
<span class="lineno"> 131 </span><span class="decl"><span class="nottickedoff">frameOrder fps nFrames = worker [] fps</span>
<span class="lineno"> 132 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 133 </span><span class="spaces"> </span><span class="nottickedoff">worker _seen 0 = []</span>
<span class="lineno"> 134 </span><span class="spaces"> </span><span class="nottickedoff">worker seen nthFrame = filterFrameList seen nthFrame nFrames</span>
<span class="lineno"> 135 </span><span class="spaces"> </span><span class="nottickedoff">++ worker (nthFrame : seen) (nthFrame `div` 2)</span></span>
<span class="lineno"> 136 </span>
<span class="lineno"> 137 </span>filterFrameList :: [Int] -&gt; Int -&gt; Int -&gt; [Int]
<span class="lineno"> 138 </span><span class="decl"><span class="nottickedoff">filterFrameList seen nthFrame nFrames = filter (not . isSeen)</span>
<span class="lineno"> 139 </span><span class="spaces"> </span><span class="nottickedoff">[0, nthFrame .. nFrames - 1]</span>
<span class="lineno"> 140 </span><span class="spaces"> </span><span class="nottickedoff">where isSeen x = any (\y -&gt; x `mod` y == 0) seen</span></span>
<span class="lineno"> 141 </span>
<span class="lineno"> 142 </span>filterFrameList :: [Int] -&gt; Int -&gt; Int -&gt; [Int]
<span class="lineno"> 143 </span><span class="decl"><span class="nottickedoff">filterFrameList seen nthFrame nFrames = filter (not . isSeen)</span>
<span class="lineno"> 144 </span><span class="spaces"> </span><span class="nottickedoff">[0, nthFrame .. nFrames - 1]</span>
<span class="lineno"> 145 </span><span class="spaces"> </span><span class="nottickedoff">where isSeen x = any (\y -&gt; x `mod` y == 0) seen</span></span>
<span class="lineno"> 146 </span>
<span class="lineno"> 147 </span>-- | Video formats supported by reanimate.
<span class="lineno"> 148 </span>data Format = RenderMp4 | RenderGif | RenderWebm
<span class="lineno"> 149 </span> deriving (<span class="decl"><span class="nottickedoff">Show</span></span>)
<span class="lineno"> 150 </span>
<span class="lineno"> 151 </span>mp4Arguments :: FPS -&gt; FilePath -&gt; FilePath -&gt; FilePath -&gt; [String]
<span class="lineno"> 152 </span><span class="decl"><span class="nottickedoff">mp4Arguments fps progress template target =</span>
<span class="lineno"> 153 </span><span class="spaces"> </span><span class="nottickedoff">[ &quot;-r&quot;</span>
<span class="lineno"> 154 </span><span class="spaces"> </span><span class="nottickedoff">, show fps</span>
<span class="lineno"> 155 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-i&quot;</span>
<span class="lineno"> 156 </span><span class="spaces"> </span><span class="nottickedoff">, template</span>
<span class="lineno"> 157 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-y&quot;</span>
<span class="lineno"> 158 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-c:v&quot;</span>
<span class="lineno"> 159 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;libx264&quot;</span>
<span class="lineno"> 160 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-vf&quot;</span>
<span class="lineno"> 161 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;fps=&quot; ++ show fps</span>
<span class="lineno"> 162 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-preset&quot;</span>
<span class="lineno"> 163 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;slow&quot;</span>
<span class="lineno"> 164 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-crf&quot;</span>
<span class="lineno"> 165 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;18&quot;</span>
<span class="lineno"> 166 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-movflags&quot;</span>
<span class="lineno"> 167 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;+faststart&quot;</span>
<span class="lineno"> 168 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-progress&quot;</span>
<span class="lineno"> 169 </span><span class="spaces"> </span><span class="nottickedoff">, progress</span>
<span class="lineno"> 170 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-pix_fmt&quot;</span>
<span class="lineno"> 171 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;yuv420p&quot;</span>
<span class="lineno"> 172 </span><span class="spaces"> </span><span class="nottickedoff">, target</span>
<span class="lineno"> 173 </span><span class="spaces"> </span><span class="nottickedoff">]</span></span>
<span class="lineno"> 174 </span>
<span class="lineno"> 175 </span>-- gifArguments :: FPS -&gt; FilePath -&gt; FilePath -&gt; FilePath -&gt; [String]
<span class="lineno"> 176 </span>-- gifArguments fps progress template target =
<span class="lineno"> 177 </span>
<span class="lineno"> 178 </span>-- | Render animation to a video file with given parameters.
<span class="lineno"> 179 </span>render
<span class="lineno"> 180 </span> :: Animation
<span class="lineno"> 181 </span> -&gt; FilePath
<span class="lineno"> 182 </span> -&gt; Raster
<span class="lineno"> 183 </span> -&gt; Format
<span class="lineno"> 184 </span> -&gt; Width
<span class="lineno"> 185 </span> -&gt; Height
<span class="lineno"> 186 </span> -&gt; FPS
<span class="lineno"> 187 </span> -&gt; Bool
<span class="lineno"> 188 </span> -&gt; IO ()
<span class="lineno"> 189 </span><span class="decl"><span class="nottickedoff">render ani target raster format width height fps partial = do</span>
<span class="lineno"> 190 </span><span class="spaces"> </span><span class="nottickedoff">printf &quot;Starting render of animation: %.1f\n&quot; (duration ani)</span>
<span class="lineno"> 191 </span><span class="spaces"> </span><span class="nottickedoff">ffmpeg &lt;- requireExecutable &quot;ffmpeg&quot;</span>
<span class="lineno"> 192 </span><span class="spaces"> </span><span class="nottickedoff">generateFrames raster ani width height fps partial $ \template -&gt;</span>
<span class="lineno"> 193 </span><span class="spaces"> </span><span class="nottickedoff">withTempFile &quot;txt&quot; $ \progress -&gt; do</span>
<span class="lineno"> 194 </span><span class="spaces"> </span><span class="nottickedoff">writeFile progress &quot;&quot;</span>
<span class="lineno"> 195 </span><span class="spaces"> </span><span class="nottickedoff">progressH &lt;- openFile progress ReadMode</span>
<span class="lineno"> 196 </span><span class="spaces"> </span><span class="nottickedoff">hSetBuffering progressH NoBuffering</span>
<span class="lineno"> 197 </span><span class="spaces"> </span><span class="nottickedoff">allFinished &lt;- newEmptyMVar</span>
<span class="lineno"> 198 </span><span class="spaces"> </span><span class="nottickedoff">void $ forkIO $ do</span>
<span class="lineno"> 199 </span><span class="spaces"> </span><span class="nottickedoff">progressPrinter &quot;rendered&quot; (animationFrameCount ani fps)</span>
<span class="lineno"> 200 </span><span class="spaces"> </span><span class="nottickedoff">$ \done -&gt; fix $ \loop -&gt; do</span>
<span class="lineno"> 201 </span><span class="spaces"> </span><span class="nottickedoff">eof &lt;- hIsEOF progressH</span>
<span class="lineno"> 202 </span><span class="spaces"> </span><span class="nottickedoff">if eof</span>
<span class="lineno"> 203 </span><span class="spaces"> </span><span class="nottickedoff">then threadDelay 1000000 &gt;&gt; loop</span>
<span class="lineno"> 204 </span><span class="spaces"> </span><span class="nottickedoff">else do</span>
<span class="lineno"> 205 </span><span class="spaces"> </span><span class="nottickedoff">l &lt;- try (hGetLine progressH)</span>
<span class="lineno"> 206 </span><span class="spaces"> </span><span class="nottickedoff">case l of</span>
<span class="lineno"> 207 </span><span class="spaces"> </span><span class="nottickedoff">Left SomeException{} -&gt; return ()</span>
<span class="lineno"> 208 </span><span class="spaces"> </span><span class="nottickedoff">Right str -&gt;</span>
<span class="lineno"> 209 </span><span class="spaces"> </span><span class="nottickedoff">case take 6 str of</span>
<span class="lineno"> 210 </span><span class="spaces"> </span><span class="nottickedoff">&quot;frame=&quot; -&gt; do</span>
<span class="lineno"> 211 </span><span class="spaces"> </span><span class="nottickedoff">void $ swapMVar done (read (drop 6 str))</span>
<span class="lineno"> 212 </span><span class="spaces"> </span><span class="nottickedoff">loop</span>
<span class="lineno"> 213 </span><span class="spaces"> </span><span class="nottickedoff">_ | str == &quot;progress=end&quot; -&gt; return ()</span>
<span class="lineno"> 214 </span><span class="spaces"> </span><span class="nottickedoff">_ -&gt; loop</span>
<span class="lineno"> 215 </span><span class="spaces"> </span><span class="nottickedoff">putMVar allFinished ()</span>
<span class="lineno"> 216 </span><span class="spaces"> </span><span class="nottickedoff">case format of</span>
<span class="lineno"> 217 </span><span class="spaces"> </span><span class="nottickedoff">RenderMp4 -&gt; runCmd ffmpeg (mp4Arguments fps progress template target)</span>
<span class="lineno"> 218 </span><span class="spaces"> </span><span class="nottickedoff">RenderGif -&gt; withTempFile &quot;png&quot; $ \palette -&gt; do</span>
<span class="lineno"> 219 </span><span class="spaces"> </span><span class="nottickedoff">runCmd</span>
<span class="lineno"> 220 </span><span class="spaces"> </span><span class="nottickedoff">ffmpeg</span>
<span class="lineno"> 221 </span><span class="spaces"> </span><span class="nottickedoff">[ &quot;-i&quot;</span>
<span class="lineno"> 222 </span><span class="spaces"> </span><span class="nottickedoff">, template</span>
<span class="lineno"> 223 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-y&quot;</span>
<span class="lineno"> 224 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-vf&quot;</span>
<span class="lineno"> 225 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;fps=&quot;</span>
<span class="lineno"> 226 </span><span class="spaces"> </span><span class="nottickedoff">++ show fps</span>
<span class="lineno"> 227 </span><span class="spaces"> </span><span class="nottickedoff">++ &quot;,scale=&quot;</span>
<span class="lineno"> 228 </span><span class="spaces"> </span><span class="nottickedoff">++ show width</span>
<span class="lineno"> 229 </span><span class="spaces"> </span><span class="nottickedoff">++ &quot;:&quot;</span>
<span class="lineno"> 230 </span><span class="spaces"> </span><span class="nottickedoff">++ show height</span>
<span class="lineno"> 231 </span><span class="spaces"> </span><span class="nottickedoff">++ &quot;:flags=lanczos,palettegen&quot;</span>
<span class="lineno"> 232 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-t&quot;</span>
<span class="lineno"> 233 </span><span class="spaces"> </span><span class="nottickedoff">, showFFloat Nothing (duration ani) &quot;&quot;</span>
<span class="lineno"> 234 </span><span class="spaces"> </span><span class="nottickedoff">, palette</span>
<span class="lineno"> 235 </span><span class="spaces"> </span><span class="nottickedoff">]</span>
<span class="lineno"> 236 </span><span class="spaces"> </span><span class="nottickedoff">runCmd</span>
<span class="lineno"> 237 </span><span class="spaces"> </span><span class="nottickedoff">ffmpeg</span>
<span class="lineno"> 238 </span><span class="spaces"> </span><span class="nottickedoff">[ &quot;-framerate&quot;</span>
<span class="lineno"> 239 </span><span class="spaces"> </span><span class="nottickedoff">, show fps</span>
<span class="lineno"> 240 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-i&quot;</span>
<span class="lineno"> 241 </span><span class="spaces"> </span><span class="nottickedoff">, template</span>
<span class="lineno"> 242 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-y&quot;</span>
<span class="lineno"> 243 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-i&quot;</span>
<span class="lineno"> 244 </span><span class="spaces"> </span><span class="nottickedoff">, palette</span>
<span class="lineno"> 245 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-progress&quot;</span>
<span class="lineno"> 246 </span><span class="spaces"> </span><span class="nottickedoff">, progress</span>
<span class="lineno"> 247 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-filter_complex&quot;</span>
<span class="lineno"> 248 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;fps=&quot;</span>
<span class="lineno"> 249 </span><span class="spaces"> </span><span class="nottickedoff">++ show fps</span>
<span class="lineno"> 250 </span><span class="spaces"> </span><span class="nottickedoff">++ &quot;,scale=&quot;</span>
<span class="lineno"> 251 </span><span class="spaces"> </span><span class="nottickedoff">++ show width</span>
<span class="lineno"> 252 </span><span class="spaces"> </span><span class="nottickedoff">++ &quot;:&quot;</span>
<span class="lineno"> 253 </span><span class="spaces"> </span><span class="nottickedoff">++ show height</span>
<span class="lineno"> 254 </span><span class="spaces"> </span><span class="nottickedoff">++ &quot;:flags=lanczos[x];[x][1:v]paletteuse&quot;</span>
<span class="lineno"> 255 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-t&quot;</span>
<span class="lineno"> 256 </span><span class="spaces"> </span><span class="nottickedoff">, showFFloat Nothing (duration ani) &quot;&quot;</span>
<span class="lineno"> 257 </span><span class="spaces"> </span><span class="nottickedoff">, target</span>
<span class="lineno"> 258 </span><span class="spaces"> </span><span class="nottickedoff">]</span>
<span class="lineno"> 259 </span><span class="spaces"> </span><span class="nottickedoff">RenderWebm -&gt; runCmd</span>
<span class="lineno"> 260 </span><span class="spaces"> </span><span class="nottickedoff">ffmpeg</span>
<span class="lineno"> 261 </span><span class="spaces"> </span><span class="nottickedoff">[ &quot;-r&quot;</span>
<span class="lineno"> 262 </span><span class="spaces"> </span><span class="nottickedoff">, show fps</span>
<span class="lineno"> 263 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-i&quot;</span>
<span class="lineno"> 264 </span><span class="spaces"> </span><span class="nottickedoff">, template</span>
<span class="lineno"> 265 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-y&quot;</span>
<span class="lineno"> 266 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-progress&quot;</span>
<span class="lineno"> 267 </span><span class="spaces"> </span><span class="nottickedoff">, progress</span>
<span class="lineno"> 268 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-c:v&quot;</span>
<span class="lineno"> 269 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;libvpx-vp9&quot;</span>
<span class="lineno"> 270 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-vf&quot;</span>
<span class="lineno"> 271 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;fps=&quot; ++ show fps</span>
<span class="lineno"> 272 </span><span class="spaces"> </span><span class="nottickedoff">, target</span>
<span class="lineno"> 273 </span><span class="spaces"> </span><span class="nottickedoff">]</span>
<span class="lineno"> 274 </span><span class="spaces"> </span><span class="nottickedoff">takeMVar allFinished</span></span>
<span class="lineno"> 275 </span>
<span class="lineno"> 276 </span>---------------------------------------------------------------------------------
<span class="lineno"> 277 </span>-- Helpers
<span class="lineno"> 278 </span>
<span class="lineno"> 279 </span>progressPrinter :: String -&gt; Int -&gt; (MVar Int -&gt; IO ()) -&gt; IO ()
<span class="lineno"> 280 </span><span class="decl"><span class="nottickedoff">progressPrinter typeName maxCount action = do</span>
<span class="lineno"> 281 </span><span class="spaces"> </span><span class="nottickedoff">printf &quot;\rFrames %s: 0/%d&quot; typeName maxCount</span>
<span class="lineno"> 282 </span><span class="spaces"> </span><span class="nottickedoff">putStr $ clearFromCursorToLineEndCode ++ &quot;\r&quot;</span>
<span class="lineno"> 283 </span><span class="spaces"> </span><span class="nottickedoff">done &lt;- newMVar (0 :: Int)</span>
<span class="lineno"> 284 </span><span class="spaces"> </span><span class="nottickedoff">start &lt;- getCurrentTime</span>
<span class="lineno"> 285 </span><span class="spaces"> </span><span class="nottickedoff">let bgThread = forever $ do</span>
<span class="lineno"> 286 </span><span class="spaces"> </span><span class="nottickedoff">nDone &lt;- readMVar done</span>
<span class="lineno"> 287 </span><span class="spaces"> </span><span class="nottickedoff">now &lt;- getCurrentTime</span>
<span class="lineno"> 288 </span><span class="spaces"> </span><span class="nottickedoff">let spent = diffUTCTime now start</span>
<span class="lineno"> 289 </span><span class="spaces"> </span><span class="nottickedoff">remaining =</span>
<span class="lineno"> 290 </span><span class="spaces"> </span><span class="nottickedoff">(spent / (fromIntegral nDone / fromIntegral maxCount)) - spent</span>
<span class="lineno"> 291 </span><span class="spaces"> </span><span class="nottickedoff">printf &quot;\rFrames %s: %d/%d&quot; typeName nDone maxCount</span>
<span class="lineno"> 292 </span><span class="spaces"> </span><span class="nottickedoff">putStr $ &quot;, time spent: &quot; ++ ppDiff spent</span>
<span class="lineno"> 293 </span><span class="spaces"> </span><span class="nottickedoff">unless (nDone == 0) $ do</span>
<span class="lineno"> 294 </span><span class="spaces"> </span><span class="nottickedoff">putStr $ &quot;, time remaining: &quot; ++ ppDiff remaining</span>
<span class="lineno"> 295 </span><span class="spaces"> </span><span class="nottickedoff">putStr $ &quot;, total time: &quot; ++ ppDiff (remaining + spent)</span>
<span class="lineno"> 296 </span><span class="spaces"> </span><span class="nottickedoff">putStr $ clearFromCursorToLineEndCode ++ &quot;\r&quot;</span>
<span class="lineno"> 297 </span><span class="spaces"> </span><span class="nottickedoff">hFlush stdout</span>
<span class="lineno"> 298 </span><span class="spaces"> </span><span class="nottickedoff">threadDelay 1000000</span>
<span class="lineno"> 299 </span><span class="spaces"> </span><span class="nottickedoff">withBackgroundThread bgThread $ action done</span>
<span class="lineno"> 300 </span><span class="spaces"> </span><span class="nottickedoff">now &lt;- getCurrentTime</span>
<span class="lineno"> 301 </span><span class="spaces"> </span><span class="nottickedoff">let spent = diffUTCTime now start</span>
<span class="lineno"> 302 </span><span class="spaces"> </span><span class="nottickedoff">printf &quot;\rFrames %s: %d/%d&quot; typeName maxCount maxCount</span>
<span class="lineno"> 303 </span><span class="spaces"> </span><span class="nottickedoff">putStr $ &quot;, time spent: &quot; ++ ppDiff spent</span>
<span class="lineno"> 304 </span><span class="spaces"> </span><span class="nottickedoff">putStr $ clearFromCursorToLineEndCode ++ &quot;\n&quot;</span></span>
<span class="lineno"> 305 </span>
<span class="lineno"> 306 </span>animationFrameCount :: Animation -&gt; FPS -&gt; Int
<span class="lineno"> 307 </span><span class="decl"><span class="nottickedoff">animationFrameCount ani rate = round (duration ani * fromIntegral rate) :: Int</span></span>
<span class="lineno"> 308 </span>
<span class="lineno"> 309 </span>generateFrames
<span class="lineno"> 310 </span> :: Raster -&gt; Animation -&gt; Width -&gt; Height -&gt; FPS -&gt; Bool -&gt; (FilePath -&gt; IO a) -&gt; IO a
<span class="lineno"> 311 </span><span class="decl"><span class="nottickedoff">generateFrames raster ani width_ height_ rate partial action = withTempDir $ \tmp -&gt; do</span>
<span class="lineno"> 312 </span><span class="spaces"> </span><span class="nottickedoff">let frameName nth = tmp &lt;/&gt; printf nameTemplate nth</span>
<span class="lineno"> 313 </span><span class="spaces"> </span><span class="nottickedoff">setRootDirectory tmp</span>
<span class="lineno"> 314 </span><span class="spaces"> </span><span class="nottickedoff">progressPrinter &quot;generated&quot; frameCount</span>
<span class="lineno"> 315 </span><span class="spaces"> </span><span class="nottickedoff">$ \done -&gt; handle h $ concurrentForM_ frames $ \n -&gt; do</span>
<span class="lineno"> 316 </span><span class="spaces"> </span><span class="nottickedoff">writeFile (frameName n) $ renderSvg width height $ nthFrame n</span>
<span class="lineno"> 317 </span><span class="spaces"> </span><span class="nottickedoff">modifyMVar_ done $ \nDone -&gt; return (nDone + 1)</span>
<span class="lineno"> 318 </span><span class="spaces"></span><span class="nottickedoff"></span>
<span class="lineno"> 319 </span><span class="spaces"> </span><span class="nottickedoff">when (isValidRaster raster)</span>
<span class="lineno"> 320 </span><span class="spaces"> </span><span class="nottickedoff">$ progressPrinter &quot;rastered&quot; frameCount</span>
<span class="lineno"> 321 </span><span class="spaces"> </span><span class="nottickedoff">$ \done -&gt; handle h $ concurrentForM_ frames $ \n -&gt; do</span>
<span class="lineno"> 322 </span><span class="spaces"> </span><span class="nottickedoff">applyRaster raster (frameName n)</span>
<span class="lineno"> 323 </span><span class="spaces"> </span><span class="nottickedoff">modifyMVar_ done $ \nDone -&gt; return (nDone + 1)</span>
<span class="lineno"> 324 </span><span class="spaces"></span><span class="nottickedoff"></span>
<span class="lineno"> 325 </span><span class="spaces"> </span><span class="nottickedoff">action (tmp &lt;/&gt; rasterTemplate raster)</span>
<span class="lineno"> 326 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 327 </span><span class="spaces"> </span><span class="nottickedoff">isValidRaster RasterNone = False</span>
<span class="lineno"> 328 </span><span class="spaces"> </span><span class="nottickedoff">isValidRaster RasterAuto = False</span>
<span class="lineno"> 329 </span><span class="spaces"> </span><span class="nottickedoff">isValidRaster _ = True</span>
<span class="lineno"> 330 </span><span class="spaces"></span><span class="nottickedoff"></span>
<span class="lineno"> 331 </span><span class="spaces"> </span><span class="nottickedoff">width = Just $ Px $ fromIntegral width_</span>
<span class="lineno"> 332 </span><span class="spaces"> </span><span class="nottickedoff">height = Just $ Px $ fromIntegral height_</span>
<span class="lineno"> 333 </span><span class="spaces"> </span><span class="nottickedoff">h UserInterrupt | partial = do</span>
<span class="lineno"> 334 </span><span class="spaces"> </span><span class="nottickedoff">hPutStrLn</span>
<span class="lineno"> 335 </span><span class="spaces"> </span><span class="nottickedoff">stderr</span>
<span class="lineno"> 336 </span><span class="spaces"> </span><span class="nottickedoff">&quot;\nCtrl-C detected. Trying to generate video with available frames. \</span>
<span class="lineno"> 337 </span><span class="spaces"> </span><span class="nottickedoff">\Hit ctrl-c again to abort.&quot;</span>
<span class="lineno"> 338 </span><span class="spaces"> </span><span class="nottickedoff">return ()</span>
<span class="lineno"> 339 </span><span class="spaces"> </span><span class="nottickedoff">h other = throwIO other</span>
<span class="lineno"> 340 </span><span class="spaces"> </span><span class="nottickedoff">-- frames = [0..frameCount-1]</span>
<span class="lineno"> 341 </span><span class="spaces"> </span><span class="nottickedoff">frames = frameOrder rate frameCount</span>
<span class="lineno"> 342 </span><span class="spaces"> </span><span class="nottickedoff">nthFrame nth = frameAt (recip (fromIntegral rate) * fromIntegral nth) ani</span>
<span class="lineno"> 343 </span><span class="spaces"> </span><span class="nottickedoff">frameCount = animationFrameCount ani rate</span>
<span class="lineno"> 344 </span><span class="spaces"> </span><span class="nottickedoff">nameTemplate :: String</span>
<span class="lineno"> 345 </span><span class="spaces"> </span><span class="nottickedoff">nameTemplate = &quot;render-%05d.svg&quot;</span></span>
<span class="lineno"> 346 </span>
<span class="lineno"> 347 </span>withBackgroundThread :: IO () -&gt; IO a -&gt; IO a
<span class="lineno"> 348 </span><span class="decl"><span class="nottickedoff">withBackgroundThread t = bracket (forkIO t) killThread . const</span></span>
<span class="lineno"> 349 </span>
<span class="lineno"> 350 </span>ppDiff :: NominalDiffTime -&gt; String
<span class="lineno"> 351 </span><span class="decl"><span class="nottickedoff">ppDiff diff | hours == 0 &amp;&amp; mins == 0 = show secs ++ &quot;s&quot;</span>
<span class="lineno"> 352 </span><span class="spaces"> </span><span class="nottickedoff">| hours == 0 = printf &quot;%.2d:%.2d&quot; mins secs</span>
<span class="lineno"> 353 </span><span class="spaces"> </span><span class="nottickedoff">| otherwise = printf &quot;%.2d:%.2d:%.2d&quot; hours mins secs</span>
<span class="lineno"> 354 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 355 </span><span class="spaces"> </span><span class="nottickedoff">(osecs, secs) = round diff `divMod` (60 :: Int)</span>
<span class="lineno"> 356 </span><span class="spaces"> </span><span class="nottickedoff">(hours, mins) = osecs `divMod` 60</span></span>
<span class="lineno"> 142 </span>-- | Video formats supported by reanimate.
<span class="lineno"> 143 </span>data Format = RenderMp4 | RenderGif | RenderWebm
<span class="lineno"> 144 </span> deriving (<span class="decl"><span class="nottickedoff">Show</span></span>)
<span class="lineno"> 145 </span>
<span class="lineno"> 146 </span>mp4Arguments :: FPS -&gt; FilePath -&gt; FilePath -&gt; FilePath -&gt; [String]
<span class="lineno"> 147 </span><span class="decl"><span class="nottickedoff">mp4Arguments fps progress template target =</span>
<span class="lineno"> 148 </span><span class="spaces"> </span><span class="nottickedoff">[ &quot;-r&quot;</span>
<span class="lineno"> 149 </span><span class="spaces"> </span><span class="nottickedoff">, show fps</span>
<span class="lineno"> 150 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-i&quot;</span>
<span class="lineno"> 151 </span><span class="spaces"> </span><span class="nottickedoff">, template</span>
<span class="lineno"> 152 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-y&quot;</span>
<span class="lineno"> 153 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-c:v&quot;</span>
<span class="lineno"> 154 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;libx264&quot;</span>
<span class="lineno"> 155 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-vf&quot;</span>
<span class="lineno"> 156 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;fps=&quot; ++ show fps</span>
<span class="lineno"> 157 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-preset&quot;</span>
<span class="lineno"> 158 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;slow&quot;</span>
<span class="lineno"> 159 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-crf&quot;</span>
<span class="lineno"> 160 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;18&quot;</span>
<span class="lineno"> 161 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-movflags&quot;</span>
<span class="lineno"> 162 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;+faststart&quot;</span>
<span class="lineno"> 163 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-progress&quot;</span>
<span class="lineno"> 164 </span><span class="spaces"> </span><span class="nottickedoff">, progress</span>
<span class="lineno"> 165 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-pix_fmt&quot;</span>
<span class="lineno"> 166 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;yuv420p&quot;</span>
<span class="lineno"> 167 </span><span class="spaces"> </span><span class="nottickedoff">, target</span>
<span class="lineno"> 168 </span><span class="spaces"> </span><span class="nottickedoff">]</span></span>
<span class="lineno"> 169 </span>
<span class="lineno"> 170 </span>-- gifArguments :: FPS -&gt; FilePath -&gt; FilePath -&gt; FilePath -&gt; [String]
<span class="lineno"> 171 </span>-- gifArguments fps progress template target =
<span class="lineno"> 172 </span>
<span class="lineno"> 173 </span>-- | Render animation to a video file with given parameters.
<span class="lineno"> 174 </span>render
<span class="lineno"> 175 </span> :: Animation
<span class="lineno"> 176 </span> -&gt; FilePath
<span class="lineno"> 177 </span> -&gt; Raster
<span class="lineno"> 178 </span> -&gt; Format
<span class="lineno"> 179 </span> -&gt; Width
<span class="lineno"> 180 </span> -&gt; Height
<span class="lineno"> 181 </span> -&gt; FPS
<span class="lineno"> 182 </span> -&gt; Bool
<span class="lineno"> 183 </span> -&gt; IO ()
<span class="lineno"> 184 </span><span class="decl"><span class="nottickedoff">render ani target raster format width height fps partial = do</span>
<span class="lineno"> 185 </span><span class="spaces"> </span><span class="nottickedoff">printf &quot;Starting render of animation: %.1f\n&quot; (duration ani)</span>
<span class="lineno"> 186 </span><span class="spaces"> </span><span class="nottickedoff">ffmpeg &lt;- requireExecutable &quot;ffmpeg&quot;</span>
<span class="lineno"> 187 </span><span class="spaces"> </span><span class="nottickedoff">generateFrames raster ani width height fps partial $ \template -&gt;</span>
<span class="lineno"> 188 </span><span class="spaces"> </span><span class="nottickedoff">withTempFile &quot;txt&quot; $ \progress -&gt; do</span>
<span class="lineno"> 189 </span><span class="spaces"> </span><span class="nottickedoff">writeFile progress &quot;&quot;</span>
<span class="lineno"> 190 </span><span class="spaces"> </span><span class="nottickedoff">progressH &lt;- openFile progress ReadMode</span>
<span class="lineno"> 191 </span><span class="spaces"> </span><span class="nottickedoff">hSetBuffering progressH NoBuffering</span>
<span class="lineno"> 192 </span><span class="spaces"> </span><span class="nottickedoff">allFinished &lt;- newEmptyMVar</span>
<span class="lineno"> 193 </span><span class="spaces"> </span><span class="nottickedoff">void $ forkIO $ do</span>
<span class="lineno"> 194 </span><span class="spaces"> </span><span class="nottickedoff">progressPrinter &quot;rendered&quot; (animationFrameCount ani fps)</span>
<span class="lineno"> 195 </span><span class="spaces"> </span><span class="nottickedoff">$ \done -&gt; fix $ \loop -&gt; do</span>
<span class="lineno"> 196 </span><span class="spaces"> </span><span class="nottickedoff">eof &lt;- hIsEOF progressH</span>
<span class="lineno"> 197 </span><span class="spaces"> </span><span class="nottickedoff">if eof</span>
<span class="lineno"> 198 </span><span class="spaces"> </span><span class="nottickedoff">then threadDelay 1000000 &gt;&gt; loop</span>
<span class="lineno"> 199 </span><span class="spaces"> </span><span class="nottickedoff">else do</span>
<span class="lineno"> 200 </span><span class="spaces"> </span><span class="nottickedoff">l &lt;- try (hGetLine progressH)</span>
<span class="lineno"> 201 </span><span class="spaces"> </span><span class="nottickedoff">case l of</span>
<span class="lineno"> 202 </span><span class="spaces"> </span><span class="nottickedoff">Left SomeException{} -&gt; return ()</span>
<span class="lineno"> 203 </span><span class="spaces"> </span><span class="nottickedoff">Right str -&gt;</span>
<span class="lineno"> 204 </span><span class="spaces"> </span><span class="nottickedoff">case take 6 str of</span>
<span class="lineno"> 205 </span><span class="spaces"> </span><span class="nottickedoff">&quot;frame=&quot; -&gt; do</span>
<span class="lineno"> 206 </span><span class="spaces"> </span><span class="nottickedoff">void $ swapMVar done (read (drop 6 str))</span>
<span class="lineno"> 207 </span><span class="spaces"> </span><span class="nottickedoff">loop</span>
<span class="lineno"> 208 </span><span class="spaces"> </span><span class="nottickedoff">_ | str == &quot;progress=end&quot; -&gt; return ()</span>
<span class="lineno"> 209 </span><span class="spaces"> </span><span class="nottickedoff">_ -&gt; loop</span>
<span class="lineno"> 210 </span><span class="spaces"> </span><span class="nottickedoff">putMVar allFinished ()</span>
<span class="lineno"> 211 </span><span class="spaces"> </span><span class="nottickedoff">case format of</span>
<span class="lineno"> 212 </span><span class="spaces"> </span><span class="nottickedoff">RenderMp4 -&gt; runCmd ffmpeg (mp4Arguments fps progress template target)</span>
<span class="lineno"> 213 </span><span class="spaces"> </span><span class="nottickedoff">RenderGif -&gt; withTempFile &quot;png&quot; $ \palette -&gt; do</span>
<span class="lineno"> 214 </span><span class="spaces"> </span><span class="nottickedoff">runCmd</span>
<span class="lineno"> 215 </span><span class="spaces"> </span><span class="nottickedoff">ffmpeg</span>
<span class="lineno"> 216 </span><span class="spaces"> </span><span class="nottickedoff">[ &quot;-i&quot;</span>
<span class="lineno"> 217 </span><span class="spaces"> </span><span class="nottickedoff">, template</span>
<span class="lineno"> 218 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-y&quot;</span>
<span class="lineno"> 219 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-vf&quot;</span>
<span class="lineno"> 220 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;fps=&quot;</span>
<span class="lineno"> 221 </span><span class="spaces"> </span><span class="nottickedoff">++ show fps</span>
<span class="lineno"> 222 </span><span class="spaces"> </span><span class="nottickedoff">++ &quot;,scale=&quot;</span>
<span class="lineno"> 223 </span><span class="spaces"> </span><span class="nottickedoff">++ show width</span>
<span class="lineno"> 224 </span><span class="spaces"> </span><span class="nottickedoff">++ &quot;:&quot;</span>
<span class="lineno"> 225 </span><span class="spaces"> </span><span class="nottickedoff">++ show height</span>
<span class="lineno"> 226 </span><span class="spaces"> </span><span class="nottickedoff">++ &quot;:flags=lanczos,palettegen&quot;</span>
<span class="lineno"> 227 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-t&quot;</span>
<span class="lineno"> 228 </span><span class="spaces"> </span><span class="nottickedoff">, showFFloat Nothing (duration ani) &quot;&quot;</span>
<span class="lineno"> 229 </span><span class="spaces"> </span><span class="nottickedoff">, palette</span>
<span class="lineno"> 230 </span><span class="spaces"> </span><span class="nottickedoff">]</span>
<span class="lineno"> 231 </span><span class="spaces"> </span><span class="nottickedoff">runCmd</span>
<span class="lineno"> 232 </span><span class="spaces"> </span><span class="nottickedoff">ffmpeg</span>
<span class="lineno"> 233 </span><span class="spaces"> </span><span class="nottickedoff">[ &quot;-framerate&quot;</span>
<span class="lineno"> 234 </span><span class="spaces"> </span><span class="nottickedoff">, show fps</span>
<span class="lineno"> 235 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-i&quot;</span>
<span class="lineno"> 236 </span><span class="spaces"> </span><span class="nottickedoff">, template</span>
<span class="lineno"> 237 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-y&quot;</span>
<span class="lineno"> 238 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-i&quot;</span>
<span class="lineno"> 239 </span><span class="spaces"> </span><span class="nottickedoff">, palette</span>
<span class="lineno"> 240 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-progress&quot;</span>
<span class="lineno"> 241 </span><span class="spaces"> </span><span class="nottickedoff">, progress</span>
<span class="lineno"> 242 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-filter_complex&quot;</span>
<span class="lineno"> 243 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;fps=&quot;</span>
<span class="lineno"> 244 </span><span class="spaces"> </span><span class="nottickedoff">++ show fps</span>
<span class="lineno"> 245 </span><span class="spaces"> </span><span class="nottickedoff">++ &quot;,scale=&quot;</span>
<span class="lineno"> 246 </span><span class="spaces"> </span><span class="nottickedoff">++ show width</span>
<span class="lineno"> 247 </span><span class="spaces"> </span><span class="nottickedoff">++ &quot;:&quot;</span>
<span class="lineno"> 248 </span><span class="spaces"> </span><span class="nottickedoff">++ show height</span>
<span class="lineno"> 249 </span><span class="spaces"> </span><span class="nottickedoff">++ &quot;:flags=lanczos[x];[x][1:v]paletteuse&quot;</span>
<span class="lineno"> 250 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-t&quot;</span>
<span class="lineno"> 251 </span><span class="spaces"> </span><span class="nottickedoff">, showFFloat Nothing (duration ani) &quot;&quot;</span>
<span class="lineno"> 252 </span><span class="spaces"> </span><span class="nottickedoff">, target</span>
<span class="lineno"> 253 </span><span class="spaces"> </span><span class="nottickedoff">]</span>
<span class="lineno"> 254 </span><span class="spaces"> </span><span class="nottickedoff">RenderWebm -&gt; runCmd</span>
<span class="lineno"> 255 </span><span class="spaces"> </span><span class="nottickedoff">ffmpeg</span>
<span class="lineno"> 256 </span><span class="spaces"> </span><span class="nottickedoff">[ &quot;-r&quot;</span>
<span class="lineno"> 257 </span><span class="spaces"> </span><span class="nottickedoff">, show fps</span>
<span class="lineno"> 258 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-i&quot;</span>
<span class="lineno"> 259 </span><span class="spaces"> </span><span class="nottickedoff">, template</span>
<span class="lineno"> 260 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-y&quot;</span>
<span class="lineno"> 261 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-progress&quot;</span>
<span class="lineno"> 262 </span><span class="spaces"> </span><span class="nottickedoff">, progress</span>
<span class="lineno"> 263 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-c:v&quot;</span>
<span class="lineno"> 264 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;libvpx-vp9&quot;</span>
<span class="lineno"> 265 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-vf&quot;</span>
<span class="lineno"> 266 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;fps=&quot; ++ show fps</span>
<span class="lineno"> 267 </span><span class="spaces"> </span><span class="nottickedoff">, target</span>
<span class="lineno"> 268 </span><span class="spaces"> </span><span class="nottickedoff">]</span>
<span class="lineno"> 269 </span><span class="spaces"> </span><span class="nottickedoff">takeMVar allFinished</span></span>
<span class="lineno"> 270 </span>
<span class="lineno"> 271 </span>---------------------------------------------------------------------------------
<span class="lineno"> 272 </span>-- Helpers
<span class="lineno"> 273 </span>
<span class="lineno"> 274 </span>progressPrinter :: String -&gt; Int -&gt; (MVar Int -&gt; IO ()) -&gt; IO ()
<span class="lineno"> 275 </span><span class="decl"><span class="nottickedoff">progressPrinter typeName maxCount action = do</span>
<span class="lineno"> 276 </span><span class="spaces"> </span><span class="nottickedoff">printf &quot;\rFrames %s: 0/%d&quot; typeName maxCount</span>
<span class="lineno"> 277 </span><span class="spaces"> </span><span class="nottickedoff">putStr $ clearFromCursorToLineEndCode ++ &quot;\r&quot;</span>
<span class="lineno"> 278 </span><span class="spaces"> </span><span class="nottickedoff">done &lt;- newMVar (0 :: Int)</span>
<span class="lineno"> 279 </span><span class="spaces"> </span><span class="nottickedoff">start &lt;- getCurrentTime</span>
<span class="lineno"> 280 </span><span class="spaces"> </span><span class="nottickedoff">let bgThread = forever $ do</span>
<span class="lineno"> 281 </span><span class="spaces"> </span><span class="nottickedoff">nDone &lt;- readMVar done</span>
<span class="lineno"> 282 </span><span class="spaces"> </span><span class="nottickedoff">now &lt;- getCurrentTime</span>
<span class="lineno"> 283 </span><span class="spaces"> </span><span class="nottickedoff">let spent = diffUTCTime now start</span>
<span class="lineno"> 284 </span><span class="spaces"> </span><span class="nottickedoff">remaining =</span>
<span class="lineno"> 285 </span><span class="spaces"> </span><span class="nottickedoff">(spent / (fromIntegral nDone / fromIntegral maxCount)) - spent</span>
<span class="lineno"> 286 </span><span class="spaces"> </span><span class="nottickedoff">printf &quot;\rFrames %s: %d/%d&quot; typeName nDone maxCount</span>
<span class="lineno"> 287 </span><span class="spaces"> </span><span class="nottickedoff">putStr $ &quot;, time spent: &quot; ++ ppDiff spent</span>
<span class="lineno"> 288 </span><span class="spaces"> </span><span class="nottickedoff">unless (nDone == 0) $ do</span>
<span class="lineno"> 289 </span><span class="spaces"> </span><span class="nottickedoff">putStr $ &quot;, time remaining: &quot; ++ ppDiff remaining</span>
<span class="lineno"> 290 </span><span class="spaces"> </span><span class="nottickedoff">putStr $ &quot;, total time: &quot; ++ ppDiff (remaining + spent)</span>
<span class="lineno"> 291 </span><span class="spaces"> </span><span class="nottickedoff">putStr $ clearFromCursorToLineEndCode ++ &quot;\r&quot;</span>
<span class="lineno"> 292 </span><span class="spaces"> </span><span class="nottickedoff">hFlush stdout</span>
<span class="lineno"> 293 </span><span class="spaces"> </span><span class="nottickedoff">threadDelay 1000000</span>
<span class="lineno"> 294 </span><span class="spaces"> </span><span class="nottickedoff">withBackgroundThread bgThread $ action done</span>
<span class="lineno"> 295 </span><span class="spaces"> </span><span class="nottickedoff">now &lt;- getCurrentTime</span>
<span class="lineno"> 296 </span><span class="spaces"> </span><span class="nottickedoff">let spent = diffUTCTime now start</span>
<span class="lineno"> 297 </span><span class="spaces"> </span><span class="nottickedoff">printf &quot;\rFrames %s: %d/%d&quot; typeName maxCount maxCount</span>
<span class="lineno"> 298 </span><span class="spaces"> </span><span class="nottickedoff">putStr $ &quot;, time spent: &quot; ++ ppDiff spent</span>
<span class="lineno"> 299 </span><span class="spaces"> </span><span class="nottickedoff">putStr $ clearFromCursorToLineEndCode ++ &quot;\n&quot;</span></span>
<span class="lineno"> 300 </span>
<span class="lineno"> 301 </span>animationFrameCount :: Animation -&gt; FPS -&gt; Int
<span class="lineno"> 302 </span><span class="decl"><span class="nottickedoff">animationFrameCount ani rate = round (duration ani * fromIntegral rate) :: Int</span></span>
<span class="lineno"> 303 </span>
<span class="lineno"> 304 </span>generateFrames
<span class="lineno"> 305 </span> :: Raster -&gt; Animation -&gt; Width -&gt; Height -&gt; FPS -&gt; Bool -&gt; (FilePath -&gt; IO a) -&gt; IO a
<span class="lineno"> 306 </span><span class="decl"><span class="nottickedoff">generateFrames raster ani width_ height_ rate partial action = withTempDir $ \tmp -&gt; do</span>
<span class="lineno"> 307 </span><span class="spaces"> </span><span class="nottickedoff">let frameName nth = tmp &lt;/&gt; printf nameTemplate nth</span>
<span class="lineno"> 308 </span><span class="spaces"> </span><span class="nottickedoff">setRootDirectory tmp</span>
<span class="lineno"> 309 </span><span class="spaces"> </span><span class="nottickedoff">progressPrinter &quot;generated&quot; frameCount</span>
<span class="lineno"> 310 </span><span class="spaces"> </span><span class="nottickedoff">$ \done -&gt; handle h $ concurrentForM_ frames $ \n -&gt; do</span>
<span class="lineno"> 311 </span><span class="spaces"> </span><span class="nottickedoff">writeFile (frameName n) $ renderSvg width height $ nthFrame n</span>
<span class="lineno"> 312 </span><span class="spaces"> </span><span class="nottickedoff">modifyMVar_ done $ \nDone -&gt; return (nDone + 1)</span>
<span class="lineno"> 313 </span><span class="spaces"></span><span class="nottickedoff"></span>
<span class="lineno"> 314 </span><span class="spaces"> </span><span class="nottickedoff">when (isValidRaster raster)</span>
<span class="lineno"> 315 </span><span class="spaces"> </span><span class="nottickedoff">$ progressPrinter &quot;rastered&quot; frameCount</span>
<span class="lineno"> 316 </span><span class="spaces"> </span><span class="nottickedoff">$ \done -&gt; handle h $ concurrentForM_ frames $ \n -&gt; do</span>
<span class="lineno"> 317 </span><span class="spaces"> </span><span class="nottickedoff">applyRaster raster (frameName n)</span>
<span class="lineno"> 318 </span><span class="spaces"> </span><span class="nottickedoff">modifyMVar_ done $ \nDone -&gt; return (nDone + 1)</span>
<span class="lineno"> 319 </span><span class="spaces"></span><span class="nottickedoff"></span>
<span class="lineno"> 320 </span><span class="spaces"> </span><span class="nottickedoff">action (tmp &lt;/&gt; rasterTemplate raster)</span>
<span class="lineno"> 321 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 322 </span><span class="spaces"> </span><span class="nottickedoff">isValidRaster RasterNone = False</span>
<span class="lineno"> 323 </span><span class="spaces"> </span><span class="nottickedoff">isValidRaster RasterAuto = False</span>
<span class="lineno"> 324 </span><span class="spaces"> </span><span class="nottickedoff">isValidRaster _ = True</span>
<span class="lineno"> 325 </span><span class="spaces"></span><span class="nottickedoff"></span>
<span class="lineno"> 326 </span><span class="spaces"> </span><span class="nottickedoff">width = Just $ Px $ fromIntegral width_</span>
<span class="lineno"> 327 </span><span class="spaces"> </span><span class="nottickedoff">height = Just $ Px $ fromIntegral height_</span>
<span class="lineno"> 328 </span><span class="spaces"> </span><span class="nottickedoff">h UserInterrupt | partial = do</span>
<span class="lineno"> 329 </span><span class="spaces"> </span><span class="nottickedoff">hPutStrLn</span>
<span class="lineno"> 330 </span><span class="spaces"> </span><span class="nottickedoff">stderr</span>
<span class="lineno"> 331 </span><span class="spaces"> </span><span class="nottickedoff">&quot;\nCtrl-C detected. Trying to generate video with available frames. \</span>
<span class="lineno"> 332 </span><span class="spaces"> </span><span class="nottickedoff">\Hit ctrl-c again to abort.&quot;</span>
<span class="lineno"> 333 </span><span class="spaces"> </span><span class="nottickedoff">return ()</span>
<span class="lineno"> 334 </span><span class="spaces"> </span><span class="nottickedoff">h other = throwIO other</span>
<span class="lineno"> 335 </span><span class="spaces"> </span><span class="nottickedoff">-- frames = [0..frameCount-1]</span>
<span class="lineno"> 336 </span><span class="spaces"> </span><span class="nottickedoff">frames = frameOrder rate frameCount</span>
<span class="lineno"> 337 </span><span class="spaces"> </span><span class="nottickedoff">nthFrame nth = frameAt (recip (fromIntegral rate) * fromIntegral nth) ani</span>
<span class="lineno"> 338 </span><span class="spaces"> </span><span class="nottickedoff">frameCount = animationFrameCount ani rate</span>
<span class="lineno"> 339 </span><span class="spaces"> </span><span class="nottickedoff">nameTemplate :: String</span>
<span class="lineno"> 340 </span><span class="spaces"> </span><span class="nottickedoff">nameTemplate = &quot;render-%05d.svg&quot;</span></span>
<span class="lineno"> 341 </span>
<span class="lineno"> 342 </span>withBackgroundThread :: IO () -&gt; IO a -&gt; IO a
<span class="lineno"> 343 </span><span class="decl"><span class="nottickedoff">withBackgroundThread t = bracket (forkIO t) killThread . const</span></span>
<span class="lineno"> 344 </span>
<span class="lineno"> 345 </span>ppDiff :: NominalDiffTime -&gt; String
<span class="lineno"> 346 </span><span class="decl"><span class="nottickedoff">ppDiff diff | hours == 0 &amp;&amp; mins == 0 = show secs ++ &quot;s&quot;</span>
<span class="lineno"> 347 </span><span class="spaces"> </span><span class="nottickedoff">| hours == 0 = printf &quot;%.2d:%.2d&quot; mins secs</span>
<span class="lineno"> 348 </span><span class="spaces"> </span><span class="nottickedoff">| otherwise = printf &quot;%.2d:%.2d:%.2d&quot; hours mins secs</span>
<span class="lineno"> 349 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 350 </span><span class="spaces"> </span><span class="nottickedoff">(osecs, secs) = round diff `divMod` (60 :: Int)</span>
<span class="lineno"> 351 </span><span class="spaces"> </span><span class="nottickedoff">(hours, mins) = osecs `divMod` 60</span></span>
<span class="lineno"> 352 </span>
<span class="lineno"> 353 </span>rasterTemplate :: Raster -&gt; String
<span class="lineno"> 354 </span><span class="decl"><span class="nottickedoff">rasterTemplate RasterNone = &quot;render-%05d.svg&quot;</span>
<span class="lineno"> 355 </span><span class="spaces"></span><span class="nottickedoff">rasterTemplate RasterAuto = &quot;render-%05d.svg&quot;</span>
<span class="lineno"> 356 </span><span class="spaces"></span><span class="nottickedoff">rasterTemplate _ = &quot;render-%05d.png&quot;</span></span>
<span class="lineno"> 357 </span>
<span class="lineno"> 358 </span>rasterTemplate :: Raster -&gt; String
<span class="lineno"> 359 </span><span class="decl"><span class="nottickedoff">rasterTemplate RasterNone = &quot;render-%05d.svg&quot;</span>
<span class="lineno"> 360 </span><span class="spaces"></span><span class="nottickedoff">rasterTemplate RasterAuto = &quot;render-%05d.svg&quot;</span>
<span class="lineno"> 361 </span><span class="spaces"></span><span class="nottickedoff">rasterTemplate _ = &quot;render-%05d.png&quot;</span></span>
<span class="lineno"> 362 </span>
<span class="lineno"> 363 </span>-- | Resolve RasterNone and RasterAuto. If no valid raster can
<span class="lineno"> 364 </span>-- be found, exit with an error message.
<span class="lineno"> 365 </span>requireRaster :: Raster -&gt; IO Raster
<span class="lineno"> 366 </span><span class="decl"><span class="nottickedoff">requireRaster raster = do</span>
<span class="lineno"> 367 </span><span class="spaces"> </span><span class="nottickedoff">raster' &lt;- selectRaster (if raster == RasterNone then RasterAuto else raster)</span>
<span class="lineno"> 368 </span><span class="spaces"> </span><span class="nottickedoff">case raster' of</span>
<span class="lineno"> 369 </span><span class="spaces"> </span><span class="nottickedoff">RasterNone -&gt; do</span>
<span class="lineno"> 370 </span><span class="spaces"> </span><span class="nottickedoff">hPutStrLn</span>
<span class="lineno"> 371 </span><span class="spaces"> </span><span class="nottickedoff">stderr</span>
<span class="lineno"> 372 </span><span class="spaces"> </span><span class="nottickedoff">&quot;Raster required but none could be found. \</span>
<span class="lineno"> 373 </span><span class="spaces"> </span><span class="nottickedoff">\Please install either inkscape, imagemagick, or rsvg-convert.&quot;</span>
<span class="lineno"> 374 </span><span class="spaces"> </span><span class="nottickedoff">exitWith (ExitFailure 1)</span>
<span class="lineno"> 375 </span><span class="spaces"> </span><span class="nottickedoff">_ -&gt; pure raster'</span></span>
<span class="lineno"> 376 </span>
<span class="lineno"> 377 </span>-- | Resolve RasterNone and RasterAuto. If no valid raster can
<span class="lineno"> 378 </span>-- be found, return RasterNone.
<span class="lineno"> 379 </span>selectRaster :: Raster -&gt; IO Raster
<span class="lineno"> 380 </span><span class="decl"><span class="nottickedoff">selectRaster RasterAuto = do</span>
<span class="lineno"> 381 </span><span class="spaces"> </span><span class="nottickedoff">rsvg &lt;- hasRSvg</span>
<span class="lineno"> 382 </span><span class="spaces"> </span><span class="nottickedoff">ink &lt;- hasInkscape</span>
<span class="lineno"> 383 </span><span class="spaces"> </span><span class="nottickedoff">magick &lt;- hasMagick</span>
<span class="lineno"> 384 </span><span class="spaces"> </span><span class="nottickedoff">if</span>
<span class="lineno"> 385 </span><span class="spaces"> </span><span class="nottickedoff">| isRight rsvg -&gt; pure RasterRSvg</span>
<span class="lineno"> 386 </span><span class="spaces"> </span><span class="nottickedoff">| isRight ink -&gt; pure RasterInkscape</span>
<span class="lineno"> 387 </span><span class="spaces"> </span><span class="nottickedoff">| isRight magick -&gt; pure RasterMagick</span>
<span class="lineno"> 388 </span><span class="spaces"> </span><span class="nottickedoff">| otherwise -&gt; pure RasterNone</span>
<span class="lineno"> 389 </span><span class="spaces"></span><span class="nottickedoff">selectRaster r = pure r</span></span>
<span class="lineno"> 390 </span>
<span class="lineno"> 391 </span>-- | Convert SVG file to a PNG file with selected raster engine. If
<span class="lineno"> 392 </span>-- raster engine is RasterAuto or RasterNone, do nothing.
<span class="lineno"> 393 </span>applyRaster :: Raster -&gt; FilePath -&gt; IO ()
<span class="lineno"> 394 </span><span class="decl"><span class="nottickedoff">applyRaster RasterNone _ = return ()</span>
<span class="lineno"> 395 </span><span class="spaces"></span><span class="nottickedoff">applyRaster RasterAuto _ = return ()</span>
<span class="lineno"> 396 </span><span class="spaces"></span><span class="nottickedoff">applyRaster RasterInkscape path = runCmd</span>
<span class="lineno"> 397 </span><span class="spaces"> </span><span class="nottickedoff">&quot;inkscape&quot;</span>
<span class="lineno"> 398 </span><span class="spaces"> </span><span class="nottickedoff">[ &quot;--without-gui&quot;</span>
<span class="lineno"> 399 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;--file=&quot; ++ path</span>
<span class="lineno"> 400 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;--export-png=&quot; ++ replaceExtension path &quot;png&quot;</span>
<span class="lineno"> 401 </span><span class="spaces"> </span><span class="nottickedoff">]</span>
<span class="lineno"> 402 </span><span class="spaces"></span><span class="nottickedoff">applyRaster RasterRSvg path = runCmd</span>
<span class="lineno"> 403 </span><span class="spaces"> </span><span class="nottickedoff">&quot;rsvg-convert&quot;</span>
<span class="lineno"> 404 </span><span class="spaces"> </span><span class="nottickedoff">[path, &quot;--unlimited&quot;, &quot;--output&quot;, replaceExtension path &quot;png&quot;]</span>
<span class="lineno"> 405 </span><span class="spaces"></span><span class="nottickedoff">applyRaster RasterMagick path =</span>
<span class="lineno"> 406 </span><span class="spaces"> </span><span class="nottickedoff">runCmd magickCmd [path, replaceExtension path &quot;png&quot;]</span></span>
<span class="lineno"> 407 </span>
<span class="lineno"> 408 </span>concurrentForM_ :: [a] -&gt; (a -&gt; IO ()) -&gt; IO ()
<span class="lineno"> 409 </span><span class="decl"><span class="nottickedoff">concurrentForM_ lst action = do</span>
<span class="lineno"> 410 </span><span class="spaces"> </span><span class="nottickedoff">n &lt;- getNumCapabilities</span>
<span class="lineno"> 411 </span><span class="spaces"> </span><span class="nottickedoff">sem &lt;- newQSemN n</span>
<span class="lineno"> 412 </span><span class="spaces"> </span><span class="nottickedoff">eVar &lt;- newEmptyMVar</span>
<span class="lineno"> 413 </span><span class="spaces"> </span><span class="nottickedoff">forM_ lst $ \elt -&gt; do</span>
<span class="lineno"> 414 </span><span class="spaces"> </span><span class="nottickedoff">waitQSemN sem 1</span>
<span class="lineno"> 415 </span><span class="spaces"> </span><span class="nottickedoff">emp &lt;- isEmptyMVar eVar</span>
<span class="lineno"> 416 </span><span class="spaces"> </span><span class="nottickedoff">if emp</span>
<span class="lineno"> 417 </span><span class="spaces"> </span><span class="nottickedoff">then</span>
<span class="lineno"> 418 </span><span class="spaces"> </span><span class="nottickedoff">void</span>
<span class="lineno"> 419 </span><span class="spaces"> </span><span class="nottickedoff">$ forkIO</span>
<span class="lineno"> 420 </span><span class="spaces"> </span><span class="nottickedoff">( catch (action elt) (void . tryPutMVar eVar)</span>
<span class="lineno"> 421 </span><span class="spaces"> </span><span class="nottickedoff">`finally` signalQSemN sem 1</span>
<span class="lineno"> 422 </span><span class="spaces"> </span><span class="nottickedoff">)</span>
<span class="lineno"> 423 </span><span class="spaces"> </span><span class="nottickedoff">else signalQSemN sem 1</span>
<span class="lineno"> 424 </span><span class="spaces"> </span><span class="nottickedoff">waitQSemN sem n</span>
<span class="lineno"> 425 </span><span class="spaces"> </span><span class="nottickedoff">mbE &lt;- tryTakeMVar eVar</span>
<span class="lineno"> 426 </span><span class="spaces"> </span><span class="nottickedoff">case mbE of</span>
<span class="lineno"> 427 </span><span class="spaces"> </span><span class="nottickedoff">Nothing -&gt; return ()</span>
<span class="lineno"> 428 </span><span class="spaces"> </span><span class="nottickedoff">Just e -&gt; throwIO (e :: SomeException)</span></span>
<span class="lineno"> 358 </span>-- | Resolve RasterNone and RasterAuto. If no valid raster can
<span class="lineno"> 359 </span>-- be found, exit with an error message.
<span class="lineno"> 360 </span>requireRaster :: Raster -&gt; IO Raster
<span class="lineno"> 361 </span><span class="decl"><span class="nottickedoff">requireRaster raster = do</span>
<span class="lineno"> 362 </span><span class="spaces"> </span><span class="nottickedoff">raster' &lt;- selectRaster (if raster == RasterNone then RasterAuto else raster)</span>
<span class="lineno"> 363 </span><span class="spaces"> </span><span class="nottickedoff">case raster' of</span>
<span class="lineno"> 364 </span><span class="spaces"> </span><span class="nottickedoff">RasterNone -&gt; do</span>
<span class="lineno"> 365 </span><span class="spaces"> </span><span class="nottickedoff">hPutStrLn</span>
<span class="lineno"> 366 </span><span class="spaces"> </span><span class="nottickedoff">stderr</span>
<span class="lineno"> 367 </span><span class="spaces"> </span><span class="nottickedoff">&quot;Raster required but none could be found. \</span>
<span class="lineno"> 368 </span><span class="spaces"> </span><span class="nottickedoff">\Please install either inkscape, imagemagick, or rsvg-convert.&quot;</span>
<span class="lineno"> 369 </span><span class="spaces"> </span><span class="nottickedoff">exitWith (ExitFailure 1)</span>
<span class="lineno"> 370 </span><span class="spaces"> </span><span class="nottickedoff">_ -&gt; pure raster'</span></span>
<span class="lineno"> 371 </span>
<span class="lineno"> 372 </span>-- | Resolve RasterNone and RasterAuto. If no valid raster can
<span class="lineno"> 373 </span>-- be found, return RasterNone.
<span class="lineno"> 374 </span>selectRaster :: Raster -&gt; IO Raster
<span class="lineno"> 375 </span><span class="decl"><span class="nottickedoff">selectRaster RasterAuto = do</span>
<span class="lineno"> 376 </span><span class="spaces"> </span><span class="nottickedoff">rsvg &lt;- hasRSvg</span>
<span class="lineno"> 377 </span><span class="spaces"> </span><span class="nottickedoff">ink &lt;- hasInkscape</span>
<span class="lineno"> 378 </span><span class="spaces"> </span><span class="nottickedoff">magick &lt;- hasMagick</span>
<span class="lineno"> 379 </span><span class="spaces"> </span><span class="nottickedoff">if</span>
<span class="lineno"> 380 </span><span class="spaces"> </span><span class="nottickedoff">| isRight rsvg -&gt; pure RasterRSvg</span>
<span class="lineno"> 381 </span><span class="spaces"> </span><span class="nottickedoff">| isRight ink -&gt; pure RasterInkscape</span>
<span class="lineno"> 382 </span><span class="spaces"> </span><span class="nottickedoff">| isRight magick -&gt; pure RasterMagick</span>
<span class="lineno"> 383 </span><span class="spaces"> </span><span class="nottickedoff">| otherwise -&gt; pure RasterNone</span>
<span class="lineno"> 384 </span><span class="spaces"></span><span class="nottickedoff">selectRaster r = pure r</span></span>
<span class="lineno"> 385 </span>
<span class="lineno"> 386 </span>-- | Convert SVG file to a PNG file with selected raster engine. If
<span class="lineno"> 387 </span>-- raster engine is RasterAuto or RasterNone, do nothing.
<span class="lineno"> 388 </span>applyRaster :: Raster -&gt; FilePath -&gt; IO ()
<span class="lineno"> 389 </span><span class="decl"><span class="nottickedoff">applyRaster RasterNone _ = return ()</span>
<span class="lineno"> 390 </span><span class="spaces"></span><span class="nottickedoff">applyRaster RasterAuto _ = return ()</span>
<span class="lineno"> 391 </span><span class="spaces"></span><span class="nottickedoff">applyRaster RasterInkscape path = runCmd</span>
<span class="lineno"> 392 </span><span class="spaces"> </span><span class="nottickedoff">&quot;inkscape&quot;</span>
<span class="lineno"> 393 </span><span class="spaces"> </span><span class="nottickedoff">[ &quot;--without-gui&quot;</span>
<span class="lineno"> 394 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;--file=&quot; ++ path</span>
<span class="lineno"> 395 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;--export-png=&quot; ++ replaceExtension path &quot;png&quot;</span>
<span class="lineno"> 396 </span><span class="spaces"> </span><span class="nottickedoff">]</span>
<span class="lineno"> 397 </span><span class="spaces"></span><span class="nottickedoff">applyRaster RasterRSvg path = runCmd</span>
<span class="lineno"> 398 </span><span class="spaces"> </span><span class="nottickedoff">&quot;rsvg-convert&quot;</span>
<span class="lineno"> 399 </span><span class="spaces"> </span><span class="nottickedoff">[path, &quot;--unlimited&quot;, &quot;--output&quot;, replaceExtension path &quot;png&quot;]</span>
<span class="lineno"> 400 </span><span class="spaces"></span><span class="nottickedoff">applyRaster RasterMagick path =</span>
<span class="lineno"> 401 </span><span class="spaces"> </span><span class="nottickedoff">runCmd magickCmd [path, replaceExtension path &quot;png&quot;]</span></span>
<span class="lineno"> 402 </span>
<span class="lineno"> 403 </span>concurrentForM_ :: [a] -&gt; (a -&gt; IO ()) -&gt; IO ()
<span class="lineno"> 404 </span><span class="decl"><span class="nottickedoff">concurrentForM_ lst action = do</span>
<span class="lineno"> 405 </span><span class="spaces"> </span><span class="nottickedoff">n &lt;- getNumCapabilities</span>
<span class="lineno"> 406 </span><span class="spaces"> </span><span class="nottickedoff">sem &lt;- newQSemN n</span>
<span class="lineno"> 407 </span><span class="spaces"> </span><span class="nottickedoff">eVar &lt;- newEmptyMVar</span>
<span class="lineno"> 408 </span><span class="spaces"> </span><span class="nottickedoff">forM_ lst $ \elt -&gt; do</span>
<span class="lineno"> 409 </span><span class="spaces"> </span><span class="nottickedoff">waitQSemN sem 1</span>
<span class="lineno"> 410 </span><span class="spaces"> </span><span class="nottickedoff">emp &lt;- isEmptyMVar eVar</span>
<span class="lineno"> 411 </span><span class="spaces"> </span><span class="nottickedoff">if emp</span>
<span class="lineno"> 412 </span><span class="spaces"> </span><span class="nottickedoff">then</span>
<span class="lineno"> 413 </span><span class="spaces"> </span><span class="nottickedoff">void</span>
<span class="lineno"> 414 </span><span class="spaces"> </span><span class="nottickedoff">$ forkIO</span>
<span class="lineno"> 415 </span><span class="spaces"> </span><span class="nottickedoff">( catch (action elt) (void . tryPutMVar eVar)</span>
<span class="lineno"> 416 </span><span class="spaces"> </span><span class="nottickedoff">`finally` signalQSemN sem 1</span>
<span class="lineno"> 417 </span><span class="spaces"> </span><span class="nottickedoff">)</span>
<span class="lineno"> 418 </span><span class="spaces"> </span><span class="nottickedoff">else signalQSemN sem 1</span>
<span class="lineno"> 419 </span><span class="spaces"> </span><span class="nottickedoff">waitQSemN sem n</span>
<span class="lineno"> 420 </span><span class="spaces"> </span><span class="nottickedoff">mbE &lt;- tryTakeMVar eVar</span>
<span class="lineno"> 421 </span><span class="spaces"> </span><span class="nottickedoff">case mbE of</span>
<span class="lineno"> 422 </span><span class="spaces"> </span><span class="nottickedoff">Nothing -&gt; return ()</span>
<span class="lineno"> 423 </span><span class="spaces"> </span><span class="nottickedoff">Just e -&gt; throwIO (e :: SomeException)</span></span>
</pre>
</body>