Deploying to gh-pages from @ 569b794d74f425480f70187ffc8ee8923860d5fa 🚀

This commit is contained in:
Lemmih 2020-08-05 13:36:11 +00:00
commit c657d1a52d
27 changed files with 4942 additions and 0 deletions

81
hpc_index.html Normal file
View file

@ -0,0 +1,81 @@
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><style type="text/css">table.bar { background-color: #f25913; }
td.bar { background-color: #60de51; }
td.invbar { background-color: #f25913; }
table.dashboard { border-collapse: collapse ; border: solid 1px black }
.dashboard td { border: solid 1px black }
.dashboard th { border: solid 1px black }
</style>
</head><body><table class="dashboard" width="100%" border=1>
<tr><th rowspan=2><a href="hpc_index.html">module</a></th><th colspan=3><a href="hpc_index_fun.html">Top Level Definitions</a></th><th colspan=3><a href="hpc_index_alt.html">Alternatives</a></th><th colspan=3><a href="hpc_index_exp.html">Expressions</a></th></tr><tr><th>%</th><th colspan=2>covered / total</th><th>%</th><th colspan=2>covered / total</th><th>%</th><th colspan=2>covered / total</th></tr><tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.1.0-inplace/Paths_reanimate.hs.html">reanimate-0.4.1.0-inplace/Paths_reanimate</a></tt></td>
<td align="right">0%</td><td>0/15</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">-&nbsp;</td><td>0/0</td><td width=100>&nbsp;</td><td align="right">0%</td><td>0/58</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.1.0-inplace/Reanimate.Animation.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Animation</a></tt></td>
<td align="right">21%</td><td>7/33</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="21%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">21%</td><td>3/14</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="21%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">24%</td><td>84/349</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="24%"><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.1.0-inplace/Reanimate.Builtin.Documentation.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Builtin.Documentation</a></tt></td>
<td align="right">42%</td><td>3/7</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="42%"><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">35%</td><td>47/134</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></tr>
<tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.1.0-inplace/Reanimate.Cache.hs.html">reanimate-0.4.1.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>
<tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.1.0-inplace/Reanimate.Constants.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Constants</a></tt></td>
<td align="right">37%</td><td>3/8</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="37%"><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">16%</td><td>3/18</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="16%"><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.1.0-inplace/Reanimate.Driver.hs.html">reanimate-0.4.1.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>8/246</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.1.0-inplace/Reanimate.Driver.CLI.hs.html">reanimate-0.4.1.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>
<tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.1.0-inplace/Reanimate.Driver.Check.hs.html">reanimate-0.4.1.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>
<tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.1.0-inplace/Reanimate.Driver.Compile.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Driver.Compile</a></tt></td>
<td align="right">0%</td><td>0/2</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/64</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.1.0-inplace/Reanimate.Driver.Magick.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Driver.Magick</a></tt></td>
<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">-&nbsp;</td><td>0/0</td><td width=100>&nbsp;</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></tr>
<tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.1.0-inplace/Reanimate.Driver.Server.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Driver.Server</a></tt></td>
<td align="right">0%</td><td>0/16</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/30</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/634</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.1.0-inplace/Reanimate.Ease.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Ease</a></tt></td>
<td align="right">0%</td><td>0/9</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/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/121</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.1.0-inplace/Reanimate.Internal.CubicBezier.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Internal.CubicBezier</a></tt></td>
<td align="right">8%</td><td>7/86</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">0%</td><td>0/26</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>39/337</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.1.0-inplace/Reanimate.Misc.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Misc</a></tt></td>
<td align="right">0%</td><td>0/7</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/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">0%</td><td>0/162</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.1.0-inplace/Reanimate.Parameters.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Parameters</a></tt></td>
<td align="right">10%</td><td>2/20</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="10%"><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">8%</td><td>4/49</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>
<tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.1.0-inplace/Reanimate.Raster.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Raster</a></tt></td>
<td align="right">0%</td><td>0/13</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/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">0%</td><td>0/443</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.1.0-inplace/Reanimate.Render.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Render</a></tt></td>
<td align="right">5%</td><td>1/18</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/44</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">5%</td><td>39/762</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></tr>
<tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.1.0-inplace/Reanimate.Svg.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Svg</a></tt></td>
<td align="right">7%</td><td>1/13</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><td align="right">5%</td><td>4/80</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">17%</td><td>137/777</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></tr>
<tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.1.0-inplace/Reanimate.Svg.BoundingBox.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Svg.BoundingBox</a></tt></td>
<td align="right">0%</td><td>0/5</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/36</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/281</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.1.0-inplace/Reanimate.Svg.Constructors.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Svg.Constructors</a></tt></td>
<td align="right">24%</td><td>12/49</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="24%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">12%</td><td>1/8</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="12%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">19%</td><td>110/565</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="19%"><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.1.0-inplace/Reanimate.Svg.LineCommand.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Svg.LineCommand</a></tt></td>
<td align="right">75%</td><td>12/16</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="75%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">51%</td><td>38/74</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="51%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">65%</td><td>620/943</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="65%"><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.1.0-inplace/Reanimate.Svg.Unuse.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Svg.Unuse</a></tt></td>
<td align="right">0%</td><td>0/3</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/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">0%</td><td>0/128</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.1.0-inplace/Reanimate.Transform.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Transform</a></tt></td>
<td align="right">0%</td><td>0/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="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/166</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">13%</td><td>54/403</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">8%</td><td>47/538</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">15%</td><td>1122/7181</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></tr>
</table></body></html>

81
hpc_index_alt.html Normal file
View file

@ -0,0 +1,81 @@
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><style type="text/css">table.bar { background-color: #f25913; }
td.bar { background-color: #60de51; }
td.invbar { background-color: #f25913; }
table.dashboard { border-collapse: collapse ; border: solid 1px black }
.dashboard td { border: solid 1px black }
.dashboard th { border: solid 1px black }
</style>
</head><body><table class="dashboard" width="100%" border=1>
<tr><th rowspan=2><a href="hpc_index.html">module</a></th><th colspan=3><a href="hpc_index_fun.html">Top Level Definitions</a></th><th colspan=3><a href="hpc_index_alt.html">Alternatives</a></th><th colspan=3><a href="hpc_index_exp.html">Expressions</a></th></tr><tr><th>%</th><th colspan=2>covered / total</th><th>%</th><th colspan=2>covered / total</th><th>%</th><th colspan=2>covered / total</th></tr><tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.1.0-inplace/Reanimate.Svg.LineCommand.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Svg.LineCommand</a></tt></td>
<td align="right">75%</td><td>12/16</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="75%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">51%</td><td>38/74</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="51%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">65%</td><td>620/943</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="65%"><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.1.0-inplace/Reanimate.Animation.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Animation</a></tt></td>
<td align="right">21%</td><td>7/33</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="21%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">21%</td><td>3/14</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="21%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">24%</td><td>84/349</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="24%"><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.1.0-inplace/Reanimate.Svg.Constructors.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Svg.Constructors</a></tt></td>
<td align="right">24%</td><td>12/49</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="24%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">12%</td><td>1/8</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="12%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">19%</td><td>110/565</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="19%"><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.1.0-inplace/Reanimate.Svg.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Svg</a></tt></td>
<td align="right">7%</td><td>1/13</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><td align="right">5%</td><td>4/80</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">17%</td><td>137/777</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></tr>
<tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.1.0-inplace/Reanimate.Driver.hs.html">reanimate-0.4.1.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>8/246</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.1.0-inplace/Reanimate.Svg.Unuse.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Svg.Unuse</a></tt></td>
<td align="right">0%</td><td>0/3</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/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">0%</td><td>0/128</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.1.0-inplace/Reanimate.Cache.hs.html">reanimate-0.4.1.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>
<tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.1.0-inplace/Reanimate.Raster.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Raster</a></tt></td>
<td align="right">0%</td><td>0/13</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/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">0%</td><td>0/443</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.1.0-inplace/Reanimate.Misc.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Misc</a></tt></td>
<td align="right">0%</td><td>0/7</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/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">0%</td><td>0/162</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.1.0-inplace/Reanimate.Render.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Render</a></tt></td>
<td align="right">5%</td><td>1/18</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/44</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">5%</td><td>39/762</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></tr>
<tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.1.0-inplace/Reanimate.Driver.Compile.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Driver.Compile</a></tt></td>
<td align="right">0%</td><td>0/2</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/64</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.1.0-inplace/Reanimate.Driver.Server.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Driver.Server</a></tt></td>
<td align="right">0%</td><td>0/16</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/30</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/634</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.1.0-inplace/Reanimate.Driver.CLI.hs.html">reanimate-0.4.1.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>
<tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.1.0-inplace/Reanimate.Driver.Check.hs.html">reanimate-0.4.1.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>
<tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.1.0-inplace/Reanimate.Internal.CubicBezier.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Internal.CubicBezier</a></tt></td>
<td align="right">8%</td><td>7/86</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">0%</td><td>0/26</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>39/337</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.1.0-inplace/Reanimate.Transform.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Transform</a></tt></td>
<td align="right">0%</td><td>0/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="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/166</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.1.0-inplace/Reanimate.Svg.BoundingBox.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Svg.BoundingBox</a></tt></td>
<td align="right">0%</td><td>0/5</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/36</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/281</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.1.0-inplace/Reanimate.Ease.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Ease</a></tt></td>
<td align="right">0%</td><td>0/9</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/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/121</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.1.0-inplace/Reanimate.Parameters.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Parameters</a></tt></td>
<td align="right">10%</td><td>2/20</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="10%"><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">8%</td><td>4/49</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>
<tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.1.0-inplace/Paths_reanimate.hs.html">reanimate-0.4.1.0-inplace/Paths_reanimate</a></tt></td>
<td align="right">0%</td><td>0/15</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">-&nbsp;</td><td>0/0</td><td width=100>&nbsp;</td><td align="right">0%</td><td>0/58</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.1.0-inplace/Reanimate.Driver.Magick.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Driver.Magick</a></tt></td>
<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">-&nbsp;</td><td>0/0</td><td width=100>&nbsp;</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></tr>
<tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.1.0-inplace/Reanimate.Builtin.Documentation.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Builtin.Documentation</a></tt></td>
<td align="right">42%</td><td>3/7</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="42%"><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">35%</td><td>47/134</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></tr>
<tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.1.0-inplace/Reanimate.Constants.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Constants</a></tt></td>
<td align="right">37%</td><td>3/8</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="37%"><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">16%</td><td>3/18</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="16%"><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">13%</td><td>54/403</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">8%</td><td>47/538</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">15%</td><td>1122/7181</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></tr>
</table></body></html>

81
hpc_index_exp.html Normal file
View file

@ -0,0 +1,81 @@
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><style type="text/css">table.bar { background-color: #f25913; }
td.bar { background-color: #60de51; }
td.invbar { background-color: #f25913; }
table.dashboard { border-collapse: collapse ; border: solid 1px black }
.dashboard td { border: solid 1px black }
.dashboard th { border: solid 1px black }
</style>
</head><body><table class="dashboard" width="100%" border=1>
<tr><th rowspan=2><a href="hpc_index.html">module</a></th><th colspan=3><a href="hpc_index_fun.html">Top Level Definitions</a></th><th colspan=3><a href="hpc_index_alt.html">Alternatives</a></th><th colspan=3><a href="hpc_index_exp.html">Expressions</a></th></tr><tr><th>%</th><th colspan=2>covered / total</th><th>%</th><th colspan=2>covered / total</th><th>%</th><th colspan=2>covered / total</th></tr><tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.1.0-inplace/Reanimate.Svg.LineCommand.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Svg.LineCommand</a></tt></td>
<td align="right">75%</td><td>12/16</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="75%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">51%</td><td>38/74</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="51%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">65%</td><td>620/943</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="65%"><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.1.0-inplace/Reanimate.Builtin.Documentation.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Builtin.Documentation</a></tt></td>
<td align="right">42%</td><td>3/7</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="42%"><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">35%</td><td>47/134</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></tr>
<tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.1.0-inplace/Reanimate.Animation.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Animation</a></tt></td>
<td align="right">21%</td><td>7/33</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="21%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">21%</td><td>3/14</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="21%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">24%</td><td>84/349</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="24%"><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.1.0-inplace/Reanimate.Svg.Constructors.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Svg.Constructors</a></tt></td>
<td align="right">24%</td><td>12/49</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="24%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">12%</td><td>1/8</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="12%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">19%</td><td>110/565</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="19%"><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.1.0-inplace/Reanimate.Svg.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Svg</a></tt></td>
<td align="right">7%</td><td>1/13</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><td align="right">5%</td><td>4/80</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">17%</td><td>137/777</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></tr>
<tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.1.0-inplace/Reanimate.Constants.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Constants</a></tt></td>
<td align="right">37%</td><td>3/8</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="37%"><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">16%</td><td>3/18</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="16%"><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.1.0-inplace/Reanimate.Internal.CubicBezier.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Internal.CubicBezier</a></tt></td>
<td align="right">8%</td><td>7/86</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">0%</td><td>0/26</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>39/337</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.1.0-inplace/Reanimate.Parameters.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Parameters</a></tt></td>
<td align="right">10%</td><td>2/20</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="10%"><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">8%</td><td>4/49</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>
<tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.1.0-inplace/Reanimate.Driver.CLI.hs.html">reanimate-0.4.1.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>
<tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.1.0-inplace/Reanimate.Render.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Render</a></tt></td>
<td align="right">5%</td><td>1/18</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/44</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">5%</td><td>39/762</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></tr>
<tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.1.0-inplace/Reanimate.Driver.hs.html">reanimate-0.4.1.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>8/246</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.1.0-inplace/Reanimate.Svg.Unuse.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Svg.Unuse</a></tt></td>
<td align="right">0%</td><td>0/3</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/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">0%</td><td>0/128</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.1.0-inplace/Reanimate.Cache.hs.html">reanimate-0.4.1.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>
<tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.1.0-inplace/Reanimate.Raster.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Raster</a></tt></td>
<td align="right">0%</td><td>0/13</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/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">0%</td><td>0/443</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.1.0-inplace/Reanimate.Misc.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Misc</a></tt></td>
<td align="right">0%</td><td>0/7</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/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">0%</td><td>0/162</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.1.0-inplace/Paths_reanimate.hs.html">reanimate-0.4.1.0-inplace/Paths_reanimate</a></tt></td>
<td align="right">0%</td><td>0/15</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">-&nbsp;</td><td>0/0</td><td width=100>&nbsp;</td><td align="right">0%</td><td>0/58</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.1.0-inplace/Reanimate.Driver.Compile.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Driver.Compile</a></tt></td>
<td align="right">0%</td><td>0/2</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/64</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.1.0-inplace/Reanimate.Driver.Server.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Driver.Server</a></tt></td>
<td align="right">0%</td><td>0/16</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/30</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/634</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.1.0-inplace/Reanimate.Driver.Magick.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Driver.Magick</a></tt></td>
<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">-&nbsp;</td><td>0/0</td><td width=100>&nbsp;</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></tr>
<tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.1.0-inplace/Reanimate.Driver.Check.hs.html">reanimate-0.4.1.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>
<tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.1.0-inplace/Reanimate.Transform.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Transform</a></tt></td>
<td align="right">0%</td><td>0/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="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/166</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.1.0-inplace/Reanimate.Svg.BoundingBox.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Svg.BoundingBox</a></tt></td>
<td align="right">0%</td><td>0/5</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/36</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/281</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.1.0-inplace/Reanimate.Ease.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Ease</a></tt></td>
<td align="right">0%</td><td>0/9</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/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/121</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">13%</td><td>54/403</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">8%</td><td>47/538</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">15%</td><td>1122/7181</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></tr>
</table></body></html>

81
hpc_index_fun.html Normal file
View file

@ -0,0 +1,81 @@
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><style type="text/css">table.bar { background-color: #f25913; }
td.bar { background-color: #60de51; }
td.invbar { background-color: #f25913; }
table.dashboard { border-collapse: collapse ; border: solid 1px black }
.dashboard td { border: solid 1px black }
.dashboard th { border: solid 1px black }
</style>
</head><body><table class="dashboard" width="100%" border=1>
<tr><th rowspan=2><a href="hpc_index.html">module</a></th><th colspan=3><a href="hpc_index_fun.html">Top Level Definitions</a></th><th colspan=3><a href="hpc_index_alt.html">Alternatives</a></th><th colspan=3><a href="hpc_index_exp.html">Expressions</a></th></tr><tr><th>%</th><th colspan=2>covered / total</th><th>%</th><th colspan=2>covered / total</th><th>%</th><th colspan=2>covered / total</th></tr><tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.1.0-inplace/Reanimate.Svg.LineCommand.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Svg.LineCommand</a></tt></td>
<td align="right">75%</td><td>12/16</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="75%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">51%</td><td>38/74</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="51%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">65%</td><td>620/943</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="65%"><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.1.0-inplace/Reanimate.Builtin.Documentation.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Builtin.Documentation</a></tt></td>
<td align="right">42%</td><td>3/7</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="42%"><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">35%</td><td>47/134</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></tr>
<tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.1.0-inplace/Reanimate.Constants.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Constants</a></tt></td>
<td align="right">37%</td><td>3/8</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="37%"><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">16%</td><td>3/18</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="16%"><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.1.0-inplace/Reanimate.Svg.Constructors.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Svg.Constructors</a></tt></td>
<td align="right">24%</td><td>12/49</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="24%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">12%</td><td>1/8</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="12%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">19%</td><td>110/565</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="19%"><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.1.0-inplace/Reanimate.Animation.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Animation</a></tt></td>
<td align="right">21%</td><td>7/33</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="21%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">21%</td><td>3/14</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="21%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">24%</td><td>84/349</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="24%"><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.1.0-inplace/Reanimate.Driver.CLI.hs.html">reanimate-0.4.1.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>
<tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.1.0-inplace/Reanimate.Parameters.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Parameters</a></tt></td>
<td align="right">10%</td><td>2/20</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="10%"><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">8%</td><td>4/49</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>
<tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.1.0-inplace/Reanimate.Driver.hs.html">reanimate-0.4.1.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>8/246</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.1.0-inplace/Reanimate.Internal.CubicBezier.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Internal.CubicBezier</a></tt></td>
<td align="right">8%</td><td>7/86</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">0%</td><td>0/26</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>39/337</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.1.0-inplace/Reanimate.Svg.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Svg</a></tt></td>
<td align="right">7%</td><td>1/13</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><td align="right">5%</td><td>4/80</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">17%</td><td>137/777</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></tr>
<tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.1.0-inplace/Reanimate.Render.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Render</a></tt></td>
<td align="right">5%</td><td>1/18</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/44</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">5%</td><td>39/762</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></tr>
<tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.1.0-inplace/Reanimate.Svg.Unuse.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Svg.Unuse</a></tt></td>
<td align="right">0%</td><td>0/3</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/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">0%</td><td>0/128</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.1.0-inplace/Reanimate.Cache.hs.html">reanimate-0.4.1.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>
<tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.1.0-inplace/Reanimate.Raster.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Raster</a></tt></td>
<td align="right">0%</td><td>0/13</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/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">0%</td><td>0/443</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.1.0-inplace/Reanimate.Misc.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Misc</a></tt></td>
<td align="right">0%</td><td>0/7</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/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">0%</td><td>0/162</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.1.0-inplace/Paths_reanimate.hs.html">reanimate-0.4.1.0-inplace/Paths_reanimate</a></tt></td>
<td align="right">0%</td><td>0/15</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">-&nbsp;</td><td>0/0</td><td width=100>&nbsp;</td><td align="right">0%</td><td>0/58</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.1.0-inplace/Reanimate.Driver.Compile.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Driver.Compile</a></tt></td>
<td align="right">0%</td><td>0/2</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/64</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.1.0-inplace/Reanimate.Driver.Server.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Driver.Server</a></tt></td>
<td align="right">0%</td><td>0/16</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/30</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/634</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.1.0-inplace/Reanimate.Driver.Magick.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Driver.Magick</a></tt></td>
<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">-&nbsp;</td><td>0/0</td><td width=100>&nbsp;</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></tr>
<tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.1.0-inplace/Reanimate.Driver.Check.hs.html">reanimate-0.4.1.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>
<tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.1.0-inplace/Reanimate.Transform.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Transform</a></tt></td>
<td align="right">0%</td><td>0/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="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/166</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.1.0-inplace/Reanimate.Svg.BoundingBox.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Svg.BoundingBox</a></tt></td>
<td align="right">0%</td><td>0/5</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/36</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/281</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.1.0-inplace/Reanimate.Ease.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Ease</a></tt></td>
<td align="right">0%</td><td>0/9</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/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/121</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">13%</td><td>54/403</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">8%</td><td>47/538</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">15%</td><td>1122/7181</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></tr>
</table></body></html>

View file

@ -0,0 +1,73 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style type="text/css">
span.lineno { color: white; background: #aaaaaa; border-right: solid white 12px }
span.nottickedoff { background: yellow}
span.istickedoff { background: white }
span.tickonlyfalse { margin: -1px; border: 1px solid #f20913; background: #f20913 }
span.tickonlytrue { margin: -1px; border: 1px solid #60de51; background: #60de51 }
span.funcount { font-size: small; color: orange; z-index: 2; position: absolute; right: 20 }
span.decl { font-weight: bold }
span.spaces { background: white }
</style>
</head>
<body>
<pre>
<span class="decl"><span class="nottickedoff">never executed</span> <span class="tickonlytrue">always true</span> <span class="tickonlyfalse">always false</span></span>
</pre>
<pre>
<span class="lineno"> 1 </span>{-# LANGUAGE CPP #-}
<span class="lineno"> 2 </span>{-# LANGUAGE NoRebindableSyntax #-}
<span class="lineno"> 3 </span>{-# OPTIONS_GHC -fno-warn-missing-import-lists #-}
<span class="lineno"> 4 </span>module Paths_reanimate (
<span class="lineno"> 5 </span> version,
<span class="lineno"> 6 </span> getBinDir, getLibDir, getDynLibDir, getDataDir, getLibexecDir,
<span class="lineno"> 7 </span> getDataFileName, getSysconfDir
<span class="lineno"> 8 </span> ) where
<span class="lineno"> 9 </span>
<span class="lineno"> 10 </span>import qualified Control.Exception as Exception
<span class="lineno"> 11 </span>import Data.Version (Version(..))
<span class="lineno"> 12 </span>import System.Environment (getEnv)
<span class="lineno"> 13 </span>import Prelude
<span class="lineno"> 14 </span>
<span class="lineno"> 15 </span>#if defined(VERSION_base)
<span class="lineno"> 16 </span>
<span class="lineno"> 17 </span>#if MIN_VERSION_base(4,0,0)
<span class="lineno"> 18 </span>catchIO :: IO a -&gt; (Exception.IOException -&gt; IO a) -&gt; IO a
<span class="lineno"> 19 </span>#else
<span class="lineno"> 20 </span>catchIO :: IO a -&gt; (Exception.Exception -&gt; IO a) -&gt; IO a
<span class="lineno"> 21 </span>#endif
<span class="lineno"> 22 </span>
<span class="lineno"> 23 </span>#else
<span class="lineno"> 24 </span>catchIO :: IO a -&gt; (Exception.IOException -&gt; IO a) -&gt; IO a
<span class="lineno"> 25 </span>#endif
<span class="lineno"> 26 </span><span class="decl"><span class="nottickedoff">catchIO = Exception.catch</span></span>
<span class="lineno"> 27 </span>
<span class="lineno"> 28 </span>version :: Version
<span class="lineno"> 29 </span><span class="decl"><span class="nottickedoff">version = Version [0,4,1,0] []</span></span>
<span class="lineno"> 30 </span>bindir, libdir, dynlibdir, datadir, libexecdir, sysconfdir :: FilePath
<span class="lineno"> 31 </span>
<span class="lineno"> 32 </span><span class="decl"><span class="nottickedoff">bindir = &quot;/home/runner/.cabal/bin&quot;</span></span>
<span class="lineno"> 33 </span><span class="decl"><span class="nottickedoff">libdir = &quot;/home/runner/.cabal/lib/x86_64-linux-ghc-8.8.2/reanimate-0.4.1.0-inplace&quot;</span></span>
<span class="lineno"> 34 </span><span class="decl"><span class="nottickedoff">dynlibdir = &quot;/home/runner/.cabal/lib/x86_64-linux-ghc-8.8.2&quot;</span></span>
<span class="lineno"> 35 </span><span class="decl"><span class="nottickedoff">datadir = &quot;/home/runner/.cabal/share/x86_64-linux-ghc-8.8.2/reanimate-0.4.1.0&quot;</span></span>
<span class="lineno"> 36 </span><span class="decl"><span class="nottickedoff">libexecdir = &quot;/home/runner/.cabal/libexec/x86_64-linux-ghc-8.8.2/reanimate-0.4.1.0&quot;</span></span>
<span class="lineno"> 37 </span><span class="decl"><span class="nottickedoff">sysconfdir = &quot;/home/runner/.cabal/etc&quot;</span></span>
<span class="lineno"> 38 </span>
<span class="lineno"> 39 </span>getBinDir, getLibDir, getDynLibDir, getDataDir, getLibexecDir, getSysconfDir :: IO FilePath
<span class="lineno"> 40 </span><span class="decl"><span class="nottickedoff">getBinDir = catchIO (getEnv &quot;reanimate_bindir&quot;) (\_ -&gt; return bindir)</span></span>
<span class="lineno"> 41 </span><span class="decl"><span class="nottickedoff">getLibDir = catchIO (getEnv &quot;reanimate_libdir&quot;) (\_ -&gt; return libdir)</span></span>
<span class="lineno"> 42 </span><span class="decl"><span class="nottickedoff">getDynLibDir = catchIO (getEnv &quot;reanimate_dynlibdir&quot;) (\_ -&gt; return dynlibdir)</span></span>
<span class="lineno"> 43 </span><span class="decl"><span class="nottickedoff">getDataDir = catchIO (getEnv &quot;reanimate_datadir&quot;) (\_ -&gt; return datadir)</span></span>
<span class="lineno"> 44 </span><span class="decl"><span class="nottickedoff">getLibexecDir = catchIO (getEnv &quot;reanimate_libexecdir&quot;) (\_ -&gt; return libexecdir)</span></span>
<span class="lineno"> 45 </span><span class="decl"><span class="nottickedoff">getSysconfDir = catchIO (getEnv &quot;reanimate_sysconfdir&quot;) (\_ -&gt; return sysconfdir)</span></span>
<span class="lineno"> 46 </span>
<span class="lineno"> 47 </span>getDataFileName :: FilePath -&gt; IO FilePath
<span class="lineno"> 48 </span><span class="decl"><span class="nottickedoff">getDataFileName name = do</span>
<span class="lineno"> 49 </span><span class="spaces"> </span><span class="nottickedoff">dir &lt;- getDataDir</span>
<span class="lineno"> 50 </span><span class="spaces"> </span><span class="nottickedoff">return (dir ++ &quot;/&quot; ++ name)</span></span>
</pre>
</body>
</html>

View file

@ -0,0 +1,405 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style type="text/css">
span.lineno { color: white; background: #aaaaaa; border-right: solid white 12px }
span.nottickedoff { background: yellow}
span.istickedoff { background: white }
span.tickonlyfalse { margin: -1px; border: 1px solid #f20913; background: #f20913 }
span.tickonlytrue { margin: -1px; border: 1px solid #60de51; background: #60de51 }
span.funcount { font-size: small; color: orange; z-index: 2; position: absolute; right: 20 }
span.decl { font-weight: bold }
span.spaces { background: white }
</style>
</head>
<body>
<pre>
<span class="decl"><span class="nottickedoff">never executed</span> <span class="tickonlytrue">always true</span> <span class="tickonlyfalse">always false</span></span>
</pre>
<pre>
<span class="lineno"> 1 </span>module Reanimate.Animation
<span class="lineno"> 2 </span> ( Duration
<span class="lineno"> 3 </span> , Time
<span class="lineno"> 4 </span> , SVG
<span class="lineno"> 5 </span> , Animation(..) -- TODO should this be exposed? The constructor is used directly in Effect.hs
<span class="lineno"> 6 </span> -- * Creating animations
<span class="lineno"> 7 </span> , mkAnimation
<span class="lineno"> 8 </span> , animate
<span class="lineno"> 9 </span> , staticFrame
<span class="lineno"> 10 </span> , pause
<span class="lineno"> 11 </span> -- * Querying animations
<span class="lineno"> 12 </span> , duration
<span class="lineno"> 13 </span> , frameAt
<span class="lineno"> 14 </span> -- * Composing animations
<span class="lineno"> 15 </span> , seqA
<span class="lineno"> 16 </span> , andThen
<span class="lineno"> 17 </span> , parA
<span class="lineno"> 18 </span> , parLoopA
<span class="lineno"> 19 </span> , parDropA
<span class="lineno"> 20 </span> -- * Modifying animations
<span class="lineno"> 21 </span> , setDuration
<span class="lineno"> 22 </span> , adjustDuration
<span class="lineno"> 23 </span> , mapA
<span class="lineno"> 24 </span> , takeA
<span class="lineno"> 25 </span> , dropA
<span class="lineno"> 26 </span> , lastA
<span class="lineno"> 27 </span> , pauseAtEnd
<span class="lineno"> 28 </span> , pauseAtBeginning
<span class="lineno"> 29 </span> , pauseAround
<span class="lineno"> 30 </span> , pauseUntil
<span class="lineno"> 31 </span> , repeatA
<span class="lineno"> 32 </span> , reverseA
<span class="lineno"> 33 </span> , playThenReverseA
<span class="lineno"> 34 </span> , signalA
<span class="lineno"> 35 </span> , freezeAtPercentage
<span class="lineno"> 36 </span> , addStatic
<span class="lineno"> 37 </span> -- * Misc
<span class="lineno"> 38 </span> , (#)
<span class="lineno"> 39 </span> , getAnimationFrame
<span class="lineno"> 40 </span> , Sync(..)
<span class="lineno"> 41 </span> -- * Rendering
<span class="lineno"> 42 </span> , renderTree
<span class="lineno"> 43 </span> , renderSvg
<span class="lineno"> 44 </span> ) where
<span class="lineno"> 45 </span>
<span class="lineno"> 46 </span>import Control.Arrow ()
<span class="lineno"> 47 </span>import Data.Fixed (mod')
<span class="lineno"> 48 </span>import Graphics.SvgTree (Alignment (..), Document (..),
<span class="lineno"> 49 </span> Number (..),
<span class="lineno"> 50 </span> PreserveAspectRatio (..),
<span class="lineno"> 51 </span> Tree (..), xmlOfTree)
<span class="lineno"> 52 </span>import Graphics.SvgTree.Printer
<span class="lineno"> 53 </span>import Reanimate.Constants
<span class="lineno"> 54 </span>import Reanimate.Ease
<span class="lineno"> 55 </span>import Reanimate.Svg.Constructors
<span class="lineno"> 56 </span>import Text.XML.Light.Output
<span class="lineno"> 57 </span>
<span class="lineno"> 58 </span>-- | Duration of an animation or effect. Usually measured in seconds.
<span class="lineno"> 59 </span>type Duration = Double
<span class="lineno"> 60 </span>-- | Time signal. Goes from 0 to 1, inclusive.
<span class="lineno"> 61 </span>type Time = Double
<span class="lineno"> 62 </span>
<span class="lineno"> 63 </span>type SVG = Tree
<span class="lineno"> 64 </span>
<span class="lineno"> 65 </span>-- | Animations are SVGs over a finite time.
<span class="lineno"> 66 </span>data Animation = Animation Duration (Time -&gt; SVG)
<span class="lineno"> 67 </span>
<span class="lineno"> 68 </span>mkAnimation :: Duration -&gt; (Time -&gt; SVG) -&gt; Animation
<span class="lineno"> 69 </span><span class="decl"><span class="istickedoff">mkAnimation = Animation</span></span>
<span class="lineno"> 70 </span>
<span class="lineno"> 71 </span>-- | Construct an animation with a duration of @1@.
<span class="lineno"> 72 </span>animate :: (Time -&gt; SVG) -&gt; Animation
<span class="lineno"> 73 </span><span class="decl"><span class="nottickedoff">animate = Animation 1</span></span>
<span class="lineno"> 74 </span>
<span class="lineno"> 75 </span>-- | Create an animation with provided @duration@, which consists of stationary frame displayed for its entire duration.
<span class="lineno"> 76 </span>staticFrame :: Duration -&gt; SVG -&gt; Animation
<span class="lineno"> 77 </span><span class="decl"><span class="nottickedoff">staticFrame d svg = Animation d (const svg)</span></span>
<span class="lineno"> 78 </span>
<span class="lineno"> 79 </span>-- | Query the duration of an animation.
<span class="lineno"> 80 </span>duration :: Animation -&gt; Duration
<span class="lineno"> 81 </span><span class="decl"><span class="istickedoff">duration (Animation d _) = d</span></span>
<span class="lineno"> 82 </span>
<span class="lineno"> 83 </span>-- | Play animations in sequence. The @lhs@ animation is removed after it has
<span class="lineno"> 84 </span>-- completed. New animation duration is '@duration lhs + duration rhs@'.
<span class="lineno"> 85 </span>--
<span class="lineno"> 86 </span>-- Example:
<span class="lineno"> 87 </span>--
<span class="lineno"> 88 </span>-- &gt; drawBox `seqA` drawCircle
<span class="lineno"> 89 </span>--
<span class="lineno"> 90 </span>-- &lt;&lt;docs/gifs/doc_seqA.gif&gt;&gt;
<span class="lineno"> 91 </span>seqA :: Animation -&gt; Animation -&gt; Animation
<span class="lineno"> 92 </span><span class="decl"><span class="istickedoff">seqA (Animation d1 f1) (Animation d2 f2) =</span>
<span class="lineno"> 93 </span><span class="spaces"> </span><span class="istickedoff">Animation totalD $ \t -&gt;</span>
<span class="lineno"> 94 </span><span class="spaces"> </span><span class="istickedoff">if t &lt; d1/totalD</span>
<span class="lineno"> 95 </span><span class="spaces"> </span><span class="istickedoff">then f1 (t * totalD/d1)</span>
<span class="lineno"> 96 </span><span class="spaces"> </span><span class="istickedoff">else f2 ((t-d1/totalD) * totalD/d2)</span>
<span class="lineno"> 97 </span><span class="spaces"> </span><span class="istickedoff">where</span>
<span class="lineno"> 98 </span><span class="spaces"> </span><span class="istickedoff">totalD = d1+d2</span></span>
<span class="lineno"> 99 </span>
<span class="lineno"> 100 </span>-- | Play two animation concurrently. Shortest animation freezes on last frame.
<span class="lineno"> 101 </span>-- New animation duration is '@max (duration lhs) (duration rhs)@'.
<span class="lineno"> 102 </span>--
<span class="lineno"> 103 </span>-- Example:
<span class="lineno"> 104 </span>--
<span class="lineno"> 105 </span>-- &gt; drawBox `parA` adjustDuration (*2) drawCircle
<span class="lineno"> 106 </span>--
<span class="lineno"> 107 </span>-- &lt;&lt;docs/gifs/doc_parA.gif&gt;&gt;
<span class="lineno"> 108 </span>parA :: Animation -&gt; Animation -&gt; Animation
<span class="lineno"> 109 </span><span class="decl"><span class="nottickedoff">parA (Animation d1 f1) (Animation d2 f2) =</span>
<span class="lineno"> 110 </span><span class="spaces"> </span><span class="nottickedoff">Animation (max d1 d2) $ \t -&gt;</span>
<span class="lineno"> 111 </span><span class="spaces"> </span><span class="nottickedoff">let t1 = t * totalD/d1</span>
<span class="lineno"> 112 </span><span class="spaces"> </span><span class="nottickedoff">t2 = t * totalD/d2 in</span>
<span class="lineno"> 113 </span><span class="spaces"> </span><span class="nottickedoff">mkGroup</span>
<span class="lineno"> 114 </span><span class="spaces"> </span><span class="nottickedoff">[ f1 (min 1 t1)</span>
<span class="lineno"> 115 </span><span class="spaces"> </span><span class="nottickedoff">, f2 (min 1 t2) ]</span>
<span class="lineno"> 116 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 117 </span><span class="spaces"> </span><span class="nottickedoff">totalD = max d1 d2</span></span>
<span class="lineno"> 118 </span>
<span class="lineno"> 119 </span>-- | Play two animation concurrently. Shortest animation loops.
<span class="lineno"> 120 </span>-- New animation duration is '@max (duration lhs) (duration rhs)@'.
<span class="lineno"> 121 </span>--
<span class="lineno"> 122 </span>-- Example:
<span class="lineno"> 123 </span>--
<span class="lineno"> 124 </span>-- &gt; drawBox `parLoopA` adjustDuration (*2) drawCircle
<span class="lineno"> 125 </span>--
<span class="lineno"> 126 </span>-- &lt;&lt;docs/gifs/doc_parLoopA.gif&gt;&gt;
<span class="lineno"> 127 </span>parLoopA :: Animation -&gt; Animation -&gt; Animation
<span class="lineno"> 128 </span><span class="decl"><span class="nottickedoff">parLoopA (Animation d1 f1) (Animation d2 f2) =</span>
<span class="lineno"> 129 </span><span class="spaces"> </span><span class="nottickedoff">Animation totalD $ \t -&gt;</span>
<span class="lineno"> 130 </span><span class="spaces"> </span><span class="nottickedoff">let t1 = t * totalD/d1</span>
<span class="lineno"> 131 </span><span class="spaces"> </span><span class="nottickedoff">t2 = t * totalD/d2 in</span>
<span class="lineno"> 132 </span><span class="spaces"> </span><span class="nottickedoff">mkGroup</span>
<span class="lineno"> 133 </span><span class="spaces"> </span><span class="nottickedoff">[ f1 (t1 `mod'` 1)</span>
<span class="lineno"> 134 </span><span class="spaces"> </span><span class="nottickedoff">, f2 (t2 `mod'` 1) ]</span>
<span class="lineno"> 135 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 136 </span><span class="spaces"> </span><span class="nottickedoff">totalD = max d1 d2</span></span>
<span class="lineno"> 137 </span>
<span class="lineno"> 138 </span>-- | Play two animation concurrently. Animations disappear after playing once.
<span class="lineno"> 139 </span>-- New animation duration is '@max (duration lhs) (duration rhs)@'.
<span class="lineno"> 140 </span>--
<span class="lineno"> 141 </span>-- Example:
<span class="lineno"> 142 </span>--
<span class="lineno"> 143 </span>-- &gt; drawBox `parLoopA` adjustDuration (*2) drawCircle
<span class="lineno"> 144 </span>--
<span class="lineno"> 145 </span>-- &lt;&lt;docs/gifs/doc_parDropA.gif&gt;&gt;
<span class="lineno"> 146 </span>parDropA :: Animation -&gt; Animation -&gt; Animation
<span class="lineno"> 147 </span><span class="decl"><span class="nottickedoff">parDropA (Animation d1 f1) (Animation d2 f2) =</span>
<span class="lineno"> 148 </span><span class="spaces"> </span><span class="nottickedoff">Animation totalD $ \t -&gt;</span>
<span class="lineno"> 149 </span><span class="spaces"> </span><span class="nottickedoff">let t1 = t * totalD/d1</span>
<span class="lineno"> 150 </span><span class="spaces"> </span><span class="nottickedoff">t2 = t * totalD/d2 in</span>
<span class="lineno"> 151 </span><span class="spaces"> </span><span class="nottickedoff">mkGroup</span>
<span class="lineno"> 152 </span><span class="spaces"> </span><span class="nottickedoff">[ if t1&gt;1 then None else f1 t1</span>
<span class="lineno"> 153 </span><span class="spaces"> </span><span class="nottickedoff">, if t2&gt;1 then None else f2 t2 ]</span>
<span class="lineno"> 154 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 155 </span><span class="spaces"> </span><span class="nottickedoff">totalD = max d1 d2</span></span>
<span class="lineno"> 156 </span>
<span class="lineno"> 157 </span>-- | Empty animation (no SVG output) with a fixed duration.
<span class="lineno"> 158 </span>--
<span class="lineno"> 159 </span>-- Example:
<span class="lineno"> 160 </span>--
<span class="lineno"> 161 </span>-- &gt; pause 1 `seqA` drawProgress
<span class="lineno"> 162 </span>--
<span class="lineno"> 163 </span>-- &lt;&lt;docs/gifs/doc_pause.gif&gt;&gt;
<span class="lineno"> 164 </span>pause :: Duration -&gt; Animation
<span class="lineno"> 165 </span><span class="decl"><span class="nottickedoff">pause d = Animation d (const None)</span></span>
<span class="lineno"> 166 </span>
<span class="lineno"> 167 </span>-- | Play left animation and freeze on the last frame, then play the right
<span class="lineno"> 168 </span>-- animation. New duration is '@duration lhs + duration rhs@'.
<span class="lineno"> 169 </span>--
<span class="lineno"> 170 </span>-- Example:
<span class="lineno"> 171 </span>--
<span class="lineno"> 172 </span>-- &gt; drawBox `andThen` drawCircle
<span class="lineno"> 173 </span>--
<span class="lineno"> 174 </span>-- &lt;&lt;docs/gifs/doc_andThen.gif&gt;&gt;
<span class="lineno"> 175 </span>andThen :: Animation -&gt; Animation -&gt; Animation
<span class="lineno"> 176 </span><span class="decl"><span class="nottickedoff">andThen a b = a `parA` (pause (duration a) `seqA` b)</span></span>
<span class="lineno"> 177 </span>
<span class="lineno"> 178 </span>-- | Calculate the frame that would be displayed at given point in @time@ of running @animation@.
<span class="lineno"> 179 </span>--
<span class="lineno"> 180 </span>-- The provided time parameter is clamped between 0 and animation duration.
<span class="lineno"> 181 </span>frameAt :: Time -&gt; Animation -&gt; SVG
<span class="lineno"> 182 </span><span class="decl"><span class="istickedoff">frameAt t (Animation d f) = f t'</span>
<span class="lineno"> 183 </span><span class="spaces"> </span><span class="istickedoff">where</span>
<span class="lineno"> 184 </span><span class="spaces"> </span><span class="istickedoff">t' = clamp 0 1 (t/d)</span></span>
<span class="lineno"> 185 </span>
<span class="lineno"> 186 </span>renderTree :: SVG -&gt; String
<span class="lineno"> 187 </span><span class="decl"><span class="nottickedoff">renderTree t = maybe &quot;&quot; ppElement $ xmlOfTree t</span></span>
<span class="lineno"> 188 </span>
<span class="lineno"> 189 </span>renderSvg :: Maybe Number -- ^ The number to use as value of the @width@ attribute of the resulting top-level svg element. If @Nothing@, the width attribute won't be rendered.
<span class="lineno"> 190 </span> -&gt; Maybe Number -- ^ Similar to previous argument, but for @height@ attribute.
<span class="lineno"> 191 </span> -&gt; SVG -- ^ SVG to render
<span class="lineno"> 192 </span> -&gt; String -- ^ String representation of SVG XML markup
<span class="lineno"> 193 </span><span class="decl"><span class="istickedoff">renderSvg w h t = ppDocument doc</span>
<span class="lineno"> 194 </span><span class="spaces"></span><span class="istickedoff">-- renderSvg w h t = ppFastElement (xmlOfDocument doc)</span>
<span class="lineno"> 195 </span><span class="spaces"> </span><span class="istickedoff">where</span>
<span class="lineno"> 196 </span><span class="spaces"> </span><span class="istickedoff">width = 16</span>
<span class="lineno"> 197 </span><span class="spaces"> </span><span class="istickedoff">height = 9</span>
<span class="lineno"> 198 </span><span class="spaces"> </span><span class="istickedoff">doc = Document</span>
<span class="lineno"> 199 </span><span class="spaces"> </span><span class="istickedoff">{ _viewBox = Just (-width/2, -height/2, width, height)</span>
<span class="lineno"> 200 </span><span class="spaces"> </span><span class="istickedoff">, _width = w</span>
<span class="lineno"> 201 </span><span class="spaces"> </span><span class="istickedoff">, _height = h</span>
<span class="lineno"> 202 </span><span class="spaces"> </span><span class="istickedoff">, _elements = [withStrokeWidth defaultStrokeWidth $ scaleXY 1 (-1) t]</span>
<span class="lineno"> 203 </span><span class="spaces"> </span><span class="istickedoff">, _description = <span class="nottickedoff">&quot;&quot;</span></span>
<span class="lineno"> 204 </span><span class="spaces"> </span><span class="istickedoff">, _documentLocation = <span class="nottickedoff">&quot;&quot;</span></span>
<span class="lineno"> 205 </span><span class="spaces"> </span><span class="istickedoff">, _documentAspectRatio = PreserveAspectRatio False AlignNone Nothing</span>
<span class="lineno"> 206 </span><span class="spaces"> </span><span class="istickedoff">}</span></span>
<span class="lineno"> 207 </span>
<span class="lineno"> 208 </span>-- | Map over the SVG produced by an animation at every frame.
<span class="lineno"> 209 </span>--
<span class="lineno"> 210 </span>-- Example:
<span class="lineno"> 211 </span>--
<span class="lineno"> 212 </span>-- &gt; mapA (scale 0.5) drawCircle
<span class="lineno"> 213 </span>--
<span class="lineno"> 214 </span>-- &lt;&lt;docs/gifs/doc_mapA.gif&gt;&gt;
<span class="lineno"> 215 </span>
<span class="lineno"> 216 </span>mapA :: (SVG -&gt; SVG) -&gt; Animation -&gt; Animation
<span class="lineno"> 217 </span><span class="decl"><span class="istickedoff">mapA fn (Animation d f) = Animation d (fn . f)</span></span>
<span class="lineno"> 218 </span>
<span class="lineno"> 219 </span>-- | Freeze the last frame for @t@ seconds at the end of the animation.
<span class="lineno"> 220 </span>--
<span class="lineno"> 221 </span>-- Example:
<span class="lineno"> 222 </span>--
<span class="lineno"> 223 </span>-- &gt; pauseAtEnd 1 drawProgress
<span class="lineno"> 224 </span>--
<span class="lineno"> 225 </span>-- &lt;&lt;docs/gifs/doc_pauseAtEnd.gif&gt;&gt;
<span class="lineno"> 226 </span>pauseAtEnd :: Duration -&gt; Animation -&gt; Animation
<span class="lineno"> 227 </span><span class="decl"><span class="nottickedoff">pauseAtEnd t a = a `andThen` pause t</span></span>
<span class="lineno"> 228 </span>
<span class="lineno"> 229 </span>-- | Freeze the first frame for @t@ seconds at the beginning of the animation.
<span class="lineno"> 230 </span>--
<span class="lineno"> 231 </span>-- Example:
<span class="lineno"> 232 </span>--
<span class="lineno"> 233 </span>-- &gt; pauseAtBeginning 1 drawProgress
<span class="lineno"> 234 </span>--
<span class="lineno"> 235 </span>-- &lt;&lt;docs/gifs/doc_pauseAtBeginning.gif&gt;&gt;
<span class="lineno"> 236 </span>pauseAtBeginning :: Duration -&gt; Animation -&gt; Animation
<span class="lineno"> 237 </span><span class="decl"><span class="nottickedoff">pauseAtBeginning t a =</span>
<span class="lineno"> 238 </span><span class="spaces"> </span><span class="nottickedoff">Animation t (freezeFrame 0 a) `seqA` a</span></span>
<span class="lineno"> 239 </span>
<span class="lineno"> 240 </span>-- | Freeze the first and the last frame of the animation for a specified duration.
<span class="lineno"> 241 </span>--
<span class="lineno"> 242 </span>-- Example:
<span class="lineno"> 243 </span>--
<span class="lineno"> 244 </span>-- &gt; pauseAround 1 1 drawProgress
<span class="lineno"> 245 </span>--
<span class="lineno"> 246 </span>-- &lt;&lt;docs/gifs/doc_pauseAround.gif&gt;&gt;
<span class="lineno"> 247 </span>pauseAround :: Duration -&gt; Duration -&gt; Animation -&gt; Animation
<span class="lineno"> 248 </span><span class="decl"><span class="nottickedoff">pauseAround start end = pauseAtEnd end . pauseAtBeginning start</span></span>
<span class="lineno"> 249 </span>
<span class="lineno"> 250 </span>-- XXX: Rename to 'setDurationFreeze'. Add 'setDurationDrop' and
<span class="lineno"> 251 </span>-- 'setDurationLoop'.
<span class="lineno"> 252 </span>pauseUntil :: Duration -&gt; Animation -&gt; Animation
<span class="lineno"> 253 </span><span class="decl"><span class="nottickedoff">pauseUntil d a = pauseAtEnd (d-duration a) a</span></span>
<span class="lineno"> 254 </span>
<span class="lineno"> 255 </span>-- Freeze frame at time @t@.
<span class="lineno"> 256 </span>freezeFrame :: Time -&gt; Animation -&gt; (Time -&gt; SVG)
<span class="lineno"> 257 </span><span class="decl"><span class="nottickedoff">freezeFrame t (Animation d f) = const $ f (t/d)</span></span>
<span class="lineno"> 258 </span>
<span class="lineno"> 259 </span>-- | Change the duration of an animation. Animates are stretched or squished
<span class="lineno"> 260 </span>-- (rather than truncated) to fit the new duration.
<span class="lineno"> 261 </span>adjustDuration :: (Duration -&gt; Duration) -&gt; Animation -&gt; Animation
<span class="lineno"> 262 </span><span class="decl"><span class="nottickedoff">adjustDuration fn (Animation d gen) =</span>
<span class="lineno"> 263 </span><span class="spaces"> </span><span class="nottickedoff">Animation (fn d) gen</span></span>
<span class="lineno"> 264 </span>
<span class="lineno"> 265 </span>-- | Set the duration of an animation by adjusting its playback rate. The
<span class="lineno"> 266 </span>-- animation is still played from start to finish without being cropped.
<span class="lineno"> 267 </span>setDuration :: Duration -&gt; Animation -&gt; Animation
<span class="lineno"> 268 </span><span class="decl"><span class="nottickedoff">setDuration newD = adjustDuration (const newD)</span></span>
<span class="lineno"> 269 </span>
<span class="lineno"> 270 </span>-- | Play an animation in reverse. Duration remains unchanged. Shorthand for:
<span class="lineno"> 271 </span>-- @'signalA' 'reverseS'@.
<span class="lineno"> 272 </span>--
<span class="lineno"> 273 </span>-- Example:
<span class="lineno"> 274 </span>--
<span class="lineno"> 275 </span>-- &gt; reverseA drawCircle
<span class="lineno"> 276 </span>--
<span class="lineno"> 277 </span>-- &lt;&lt;docs/gifs/doc_reverseA.gif&gt;&gt;
<span class="lineno"> 278 </span>reverseA :: Animation -&gt; Animation
<span class="lineno"> 279 </span><span class="decl"><span class="nottickedoff">reverseA = signalA reverseS</span></span>
<span class="lineno"> 280 </span>
<span class="lineno"> 281 </span>-- | Play animation before playing it again in reverse. Duration is twice
<span class="lineno"> 282 </span>-- the duration of the input.
<span class="lineno"> 283 </span>--
<span class="lineno"> 284 </span>-- Example:
<span class="lineno"> 285 </span>--
<span class="lineno"> 286 </span>-- &gt; playThenReverseA drawCircle
<span class="lineno"> 287 </span>--
<span class="lineno"> 288 </span>-- &lt;&lt;docs/gifs/doc_playThenReverseA.gif&gt;&gt;
<span class="lineno"> 289 </span>playThenReverseA :: Animation -&gt; Animation
<span class="lineno"> 290 </span><span class="decl"><span class="nottickedoff">playThenReverseA a = a `seqA` reverseA a</span></span>
<span class="lineno"> 291 </span>
<span class="lineno"> 292 </span>-- | Loop animation @n@ number of times. This number may be fractional and it
<span class="lineno"> 293 </span>-- may be less than 1. It must be greater than or equal to 0, though.
<span class="lineno"> 294 </span>-- New duration is @n*duration input@.
<span class="lineno"> 295 </span>--
<span class="lineno"> 296 </span>-- Example:
<span class="lineno"> 297 </span>--
<span class="lineno"> 298 </span>-- &gt; repeatA 1.5 drawCircle
<span class="lineno"> 299 </span>--
<span class="lineno"> 300 </span>-- &lt;&lt;docs/gifs/doc_repeatA.gif&gt;&gt;
<span class="lineno"> 301 </span>repeatA :: Double -&gt; Animation -&gt; Animation
<span class="lineno"> 302 </span><span class="decl"><span class="nottickedoff">repeatA n (Animation d f) = Animation (d*n) $ \t -&gt;</span>
<span class="lineno"> 303 </span><span class="spaces"> </span><span class="nottickedoff">f ((t*n) `mod'` 1)</span></span>
<span class="lineno"> 304 </span>
<span class="lineno"> 305 </span>
<span class="lineno"> 306 </span>-- | @freezeAtPercentage time animation@ creates an animation consisting of stationary frame,
<span class="lineno"> 307 </span>-- that would be displayed in the provided @animation@ at given @time@.
<span class="lineno"> 308 </span>-- The duration of the new animation is the same as the duration of provided @animation@.
<span class="lineno"> 309 </span>freezeAtPercentage :: Time -- ^ value between 0 and 1. The frame displayed at this point in the original animation will be displayed for the duration of the new animation
<span class="lineno"> 310 </span> -&gt; Animation -- ^ original animation, from which the frame will be taken
<span class="lineno"> 311 </span> -&gt; Animation -- ^ new animation consisting of static frame displayed for the duration of the original animation
<span class="lineno"> 312 </span><span class="decl"><span class="nottickedoff">freezeAtPercentage frac (Animation d genFrame) =</span>
<span class="lineno"> 313 </span><span class="spaces"> </span><span class="nottickedoff">Animation d $ const $ genFrame frac</span></span>
<span class="lineno"> 314 </span>
<span class="lineno"> 315 </span>-- | Overlay animation on top of static SVG image.
<span class="lineno"> 316 </span>--
<span class="lineno"> 317 </span>-- Example:
<span class="lineno"> 318 </span>--
<span class="lineno"> 319 </span>-- &gt; addStatic (mkBackground &quot;lightblue&quot;) drawCircle
<span class="lineno"> 320 </span>--
<span class="lineno"> 321 </span>-- &lt;&lt;docs/gifs/doc_addStatic.gif&gt;&gt;
<span class="lineno"> 322 </span>addStatic :: SVG -&gt; Animation -&gt; Animation
<span class="lineno"> 323 </span><span class="decl"><span class="nottickedoff">addStatic static = mapA (\frame -&gt; mkGroup [static, frame])</span></span>
<span class="lineno"> 324 </span>
<span class="lineno"> 325 </span>-- | Modify the time component of an animation. Animation duration is unchanged.
<span class="lineno"> 326 </span>--
<span class="lineno"> 327 </span>-- Example:
<span class="lineno"> 328 </span>--
<span class="lineno"> 329 </span>-- &gt; signalA (fromToS 0.25 0.75) drawCircle
<span class="lineno"> 330 </span>--
<span class="lineno"> 331 </span>-- &lt;&lt;docs/gifs/doc_signalA.gif&gt;&gt;
<span class="lineno"> 332 </span>signalA :: Signal -&gt; Animation -&gt; Animation
<span class="lineno"> 333 </span><span class="decl"><span class="nottickedoff">signalA fn (Animation d gen) = Animation d $ gen . fn</span></span>
<span class="lineno"> 334 </span>
<span class="lineno"> 335 </span>-- | @takeA duration animation@ creates a new animation consisting of initial segment of
<span class="lineno"> 336 </span>-- @animation@ of given @duration@, played at the same rate as the original animation.
<span class="lineno"> 337 </span>--
<span class="lineno"> 338 </span>-- The @duration@ parameter is clamped to be between 0 and @animation@'s duration.
<span class="lineno"> 339 </span>-- New animation duration is equal to (eventually clamped) @duration@.
<span class="lineno"> 340 </span>takeA :: Duration -&gt; Animation -&gt; Animation
<span class="lineno"> 341 </span><span class="decl"><span class="nottickedoff">takeA len (Animation d gen) = Animation len' $ \t -&gt;</span>
<span class="lineno"> 342 </span><span class="spaces"> </span><span class="nottickedoff">gen (t * len'/d)</span>
<span class="lineno"> 343 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 344 </span><span class="spaces"> </span><span class="nottickedoff">len' = clamp 0 d len</span></span>
<span class="lineno"> 345 </span>
<span class="lineno"> 346 </span>-- | @dropA duration animation@ creates a new animation by dropping initial segment
<span class="lineno"> 347 </span>-- of length @duration@ from the provided @animation@, played at the same rate as the original animation.
<span class="lineno"> 348 </span>--
<span class="lineno"> 349 </span>-- The @duration@ parameter is clamped to be between 0 and @animation@'s duration.
<span class="lineno"> 350 </span>-- The duration of the resulting animation is duration of provided @animation@ minus (eventually clamped) @duration@.
<span class="lineno"> 351 </span>dropA :: Duration -&gt; Animation -&gt; Animation
<span class="lineno"> 352 </span><span class="decl"><span class="nottickedoff">dropA len (Animation d gen) = Animation len' $ \t -&gt;</span>
<span class="lineno"> 353 </span><span class="spaces"> </span><span class="nottickedoff">gen (t * len'/d + len/d)</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">len' = d - clamp 0 d len</span></span>
<span class="lineno"> 356 </span>
<span class="lineno"> 357 </span>lastA :: Duration -&gt; Animation -&gt; Animation
<span class="lineno"> 358 </span><span class="decl"><span class="nottickedoff">lastA len a = dropA (duration a - len) a</span></span>
<span class="lineno"> 359 </span>
<span class="lineno"> 360 </span>clamp :: Double -&gt; Double -&gt; Double -&gt; Double
<span class="lineno"> 361 </span><span class="decl"><span class="istickedoff">clamp a b number</span>
<span class="lineno"> 362 </span><span class="spaces"> </span><span class="istickedoff">| <span class="tickonlytrue">a &lt; b</span> = max a (min b number)</span>
<span class="lineno"> 363 </span><span class="spaces"> </span><span class="istickedoff">| <span class="nottickedoff">otherwise</span> = <span class="nottickedoff">max b (min a number)</span></span></span>
<span class="lineno"> 364 </span>
<span class="lineno"> 365 </span>(#) :: a -&gt; (a -&gt; b) -&gt; b
<span class="lineno"> 366 </span><span class="decl"><span class="nottickedoff">o # f = f o</span></span>
<span class="lineno"> 367 </span>
<span class="lineno"> 368 </span>getAnimationFrame :: Sync -&gt; Animation -&gt; Time -&gt; Duration -&gt; SVG
<span class="lineno"> 369 </span><span class="decl"><span class="nottickedoff">getAnimationFrame sync (Animation aDur aGen) t d =</span>
<span class="lineno"> 370 </span><span class="spaces"> </span><span class="nottickedoff">case sync of</span>
<span class="lineno"> 371 </span><span class="spaces"> </span><span class="nottickedoff">SyncStretch -&gt; aGen (t/d)</span>
<span class="lineno"> 372 </span><span class="spaces"> </span><span class="nottickedoff">SyncLoop -&gt; aGen (takeFrac $ t/aDur)</span>
<span class="lineno"> 373 </span><span class="spaces"> </span><span class="nottickedoff">SyncDrop -&gt; if t &gt; aDur then None else aGen (t/aDur)</span>
<span class="lineno"> 374 </span><span class="spaces"> </span><span class="nottickedoff">SyncFreeze -&gt; aGen (min 1 $ t/aDur)</span>
<span class="lineno"> 375 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 376 </span><span class="spaces"> </span><span class="nottickedoff">takeFrac f = snd (properFraction f :: (Int, Double))</span></span>
<span class="lineno"> 377 </span>
<span class="lineno"> 378 </span>data Sync
<span class="lineno"> 379 </span> = SyncStretch
<span class="lineno"> 380 </span> | SyncLoop
<span class="lineno"> 381 </span> | SyncDrop
<span class="lineno"> 382 </span> | SyncFreeze
</pre>
</body>
</html>

View file

@ -0,0 +1,76 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style type="text/css">
span.lineno { color: white; background: #aaaaaa; border-right: solid white 12px }
span.nottickedoff { background: yellow}
span.istickedoff { background: white }
span.tickonlyfalse { margin: -1px; border: 1px solid #f20913; background: #f20913 }
span.tickonlytrue { margin: -1px; border: 1px solid #60de51; background: #60de51 }
span.funcount { font-size: small; color: orange; z-index: 2; position: absolute; right: 20 }
span.decl { font-weight: bold }
span.spaces { background: white }
</style>
</head>
<body>
<pre>
<span class="decl"><span class="nottickedoff">never executed</span> <span class="tickonlytrue">always true</span> <span class="tickonlyfalse">always false</span></span>
</pre>
<pre>
<span class="lineno"> 1 </span>module Reanimate.Builtin.Documentation where
<span class="lineno"> 2 </span>
<span class="lineno"> 3 </span>import Reanimate.Animation
<span class="lineno"> 4 </span>import Reanimate.Svg
<span class="lineno"> 5 </span>import Reanimate.Raster
<span class="lineno"> 6 </span>import Reanimate.Constants
<span class="lineno"> 7 </span>import Codec.Picture
<span class="lineno"> 8 </span>
<span class="lineno"> 9 </span>docEnv :: Animation -&gt; Animation
<span class="lineno"> 10 </span><span class="decl"><span class="istickedoff">docEnv = mapA $ \svg -&gt; mkGroup</span>
<span class="lineno"> 11 </span><span class="spaces"> </span><span class="istickedoff">[ mkBackground &quot;white&quot;</span>
<span class="lineno"> 12 </span><span class="spaces"> </span><span class="istickedoff">, withFillOpacity 0 $</span>
<span class="lineno"> 13 </span><span class="spaces"> </span><span class="istickedoff">withStrokeWidth 0.1 $</span>
<span class="lineno"> 14 </span><span class="spaces"> </span><span class="istickedoff">withStrokeColor &quot;black&quot; (mkGroup [svg]) ]</span></span>
<span class="lineno"> 15 </span>
<span class="lineno"> 16 </span>-- | &lt;&lt;docs/gifs/doc_drawBox.gif&gt;&gt;
<span class="lineno"> 17 </span>drawBox :: Animation
<span class="lineno"> 18 </span><span class="decl"><span class="istickedoff">drawBox = mkAnimation 2 $ \t -&gt;</span>
<span class="lineno"> 19 </span><span class="spaces"> </span><span class="istickedoff">partialSvg t $ pathify $</span>
<span class="lineno"> 20 </span><span class="spaces"> </span><span class="istickedoff">mkRect (screenWidth/2) (screenHeight/2)</span></span>
<span class="lineno"> 21 </span>
<span class="lineno"> 22 </span>-- | &lt;&lt;docs/gifs/doc_drawCircle.gif&gt;&gt;
<span class="lineno"> 23 </span>drawCircle :: Animation
<span class="lineno"> 24 </span><span class="decl"><span class="istickedoff">drawCircle = mkAnimation 2 $ \t -&gt;</span>
<span class="lineno"> 25 </span><span class="spaces"> </span><span class="istickedoff">partialSvg t $ pathify $</span>
<span class="lineno"> 26 </span><span class="spaces"> </span><span class="istickedoff">mkCircle (screenHeight/3)</span></span>
<span class="lineno"> 27 </span>
<span class="lineno"> 28 </span>drawBall :: Animation
<span class="lineno"> 29 </span><span class="decl"><span class="nottickedoff">drawBall = mkAnimation 2 $ \t -&gt;</span>
<span class="lineno"> 30 </span><span class="spaces"> </span><span class="nottickedoff">scale t $ withFillOpacity 1 $ withFillColor &quot;red&quot; $</span>
<span class="lineno"> 31 </span><span class="spaces"> </span><span class="nottickedoff">mkCircle (screenHeight/3)</span></span>
<span class="lineno"> 32 </span>
<span class="lineno"> 33 </span>-- | &lt;&lt;docs/gifs/doc_drawProgress.gif&gt;&gt;
<span class="lineno"> 34 </span>drawProgress :: Animation
<span class="lineno"> 35 </span><span class="decl"><span class="nottickedoff">drawProgress = mkAnimation 2 $ \t -&gt;</span>
<span class="lineno"> 36 </span><span class="spaces"> </span><span class="nottickedoff">mkGroup</span>
<span class="lineno"> 37 </span><span class="spaces"> </span><span class="nottickedoff">[ mkLine (-screenWidth/2*widthP,0)</span>
<span class="lineno"> 38 </span><span class="spaces"> </span><span class="nottickedoff">(screenWidth/2*widthP,0)</span>
<span class="lineno"> 39 </span><span class="spaces"> </span><span class="nottickedoff">, translate (-screenWidth/2*widthP + screenWidth*widthP*t) 0 $</span>
<span class="lineno"> 40 </span><span class="spaces"> </span><span class="nottickedoff">withFillOpacity 1 $ mkCircle 0.5 ]</span>
<span class="lineno"> 41 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 42 </span><span class="spaces"> </span><span class="nottickedoff">widthP = 0.8</span></span>
<span class="lineno"> 43 </span>
<span class="lineno"> 44 </span>showColorMap :: (Double -&gt; PixelRGB8) -&gt; SVG
<span class="lineno"> 45 </span><span class="decl"><span class="nottickedoff">showColorMap f = center $ scaleToSize screenWidth screenHeight $ embedImage img</span>
<span class="lineno"> 46 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 47 </span><span class="spaces"> </span><span class="nottickedoff">width = 256</span>
<span class="lineno"> 48 </span><span class="spaces"> </span><span class="nottickedoff">height = 1</span>
<span class="lineno"> 49 </span><span class="spaces"> </span><span class="nottickedoff">img = generateImage pixelRenderer width height</span>
<span class="lineno"> 50 </span><span class="spaces"> </span><span class="nottickedoff">pixelRenderer x _y = f (fromIntegral x / fromIntegral (width-1))</span></span>
<span class="lineno"> 51 </span>
<span class="lineno"> 52 </span>rtfdBackgroundColor :: PixelRGBA8
<span class="lineno"> 53 </span><span class="decl"><span class="nottickedoff">rtfdBackgroundColor = PixelRGBA8 252 252 252 0xFF</span></span>
</pre>
</body>
</html>

View file

@ -0,0 +1,134 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style type="text/css">
span.lineno { color: white; background: #aaaaaa; border-right: solid white 12px }
span.nottickedoff { background: yellow}
span.istickedoff { background: white }
span.tickonlyfalse { margin: -1px; border: 1px solid #f20913; background: #f20913 }
span.tickonlytrue { margin: -1px; border: 1px solid #60de51; background: #60de51 }
span.funcount { font-size: small; color: orange; z-index: 2; position: absolute; right: 20 }
span.decl { font-weight: bold }
span.spaces { background: white }
</style>
</head>
<body>
<pre>
<span class="decl"><span class="nottickedoff">never executed</span> <span class="tickonlytrue">always true</span> <span class="tickonlyfalse">always false</span></span>
</pre>
<pre>
<span class="lineno"> 1 </span>module Reanimate.Cache
<span class="lineno"> 2 </span> ( cacheFile -- :: FilePath -&gt; (FilePath -&gt; IO ()) -&gt; IO FilePath
<span class="lineno"> 3 </span> , cacheMem
<span class="lineno"> 4 </span> , cacheDisk
<span class="lineno"> 5 </span> , cacheDiskSvg
<span class="lineno"> 6 </span> , cacheDiskKey
<span class="lineno"> 7 </span> , cacheDiskLines
<span class="lineno"> 8 </span> , encodeInt
<span class="lineno"> 9 </span> ) where
<span class="lineno"> 10 </span>
<span class="lineno"> 11 </span>import Control.Exception
<span class="lineno"> 12 </span>import Control.Monad (unless)
<span class="lineno"> 13 </span>import Data.Bits
<span class="lineno"> 14 </span>import Data.Hashable
<span class="lineno"> 15 </span>import Data.IORef
<span class="lineno"> 16 </span>import Data.Map (Map)
<span class="lineno"> 17 </span>import qualified Data.Map as Map
<span class="lineno"> 18 </span>import Data.Text (Text)
<span class="lineno"> 19 </span>import qualified Data.Text as T
<span class="lineno"> 20 </span>import qualified Data.Text.IO as T
<span class="lineno"> 21 </span>import Graphics.SvgTree (Tree (..), unparse)
<span class="lineno"> 22 </span>import Reanimate.Animation (renderTree)
<span class="lineno"> 23 </span>import Reanimate.Misc (renameOrCopyFile)
<span class="lineno"> 24 </span>import System.Directory
<span class="lineno"> 25 </span>import System.FilePath
<span class="lineno"> 26 </span>import System.IO
<span class="lineno"> 27 </span>import System.IO.Temp
<span class="lineno"> 28 </span>import System.IO.Unsafe
<span class="lineno"> 29 </span>import Text.XML.Light (Content (..), parseXML)
<span class="lineno"> 30 </span>
<span class="lineno"> 31 </span>-- Memory cache and disk cache
<span class="lineno"> 32 </span>
<span class="lineno"> 33 </span>cacheFile :: FilePath -&gt; (FilePath -&gt; IO ()) -&gt; IO FilePath
<span class="lineno"> 34 </span><span class="decl"><span class="nottickedoff">cacheFile template gen = do</span>
<span class="lineno"> 35 </span><span class="spaces"> </span><span class="nottickedoff">root &lt;- getXdgDirectory XdgCache &quot;reanimate&quot;</span>
<span class="lineno"> 36 </span><span class="spaces"> </span><span class="nottickedoff">createDirectoryIfMissing True root</span>
<span class="lineno"> 37 </span><span class="spaces"> </span><span class="nottickedoff">let path = root &lt;/&gt; template</span>
<span class="lineno"> 38 </span><span class="spaces"> </span><span class="nottickedoff">hit &lt;- doesFileExist path</span>
<span class="lineno"> 39 </span><span class="spaces"> </span><span class="nottickedoff">unless hit $ withSystemTempFile template $ \tmp h -&gt; do</span>
<span class="lineno"> 40 </span><span class="spaces"> </span><span class="nottickedoff">hClose h</span>
<span class="lineno"> 41 </span><span class="spaces"> </span><span class="nottickedoff">gen tmp</span>
<span class="lineno"> 42 </span><span class="spaces"> </span><span class="nottickedoff">renameOrCopyFile tmp path</span>
<span class="lineno"> 43 </span><span class="spaces"> </span><span class="nottickedoff">evaluate path</span></span>
<span class="lineno"> 44 </span>
<span class="lineno"> 45 </span>cacheDisk :: String -&gt; (T.Text -&gt; Maybe a) -&gt; (a -&gt; T.Text) -&gt; (Text -&gt; IO a) -&gt; (Text -&gt; IO a)
<span class="lineno"> 46 </span><span class="decl"><span class="nottickedoff">cacheDisk cacheType parse render gen key = do</span>
<span class="lineno"> 47 </span><span class="spaces"> </span><span class="nottickedoff">root &lt;- getXdgDirectory XdgCache &quot;reanimate&quot;</span>
<span class="lineno"> 48 </span><span class="spaces"> </span><span class="nottickedoff">createDirectoryIfMissing True root</span>
<span class="lineno"> 49 </span><span class="spaces"> </span><span class="nottickedoff">let path = root &lt;/&gt; encodeInt (hash key) &lt;.&gt; cacheType</span>
<span class="lineno"> 50 </span><span class="spaces"> </span><span class="nottickedoff">hit &lt;- doesFileExist path</span>
<span class="lineno"> 51 </span><span class="spaces"> </span><span class="nottickedoff">if hit</span>
<span class="lineno"> 52 </span><span class="spaces"> </span><span class="nottickedoff">then do</span>
<span class="lineno"> 53 </span><span class="spaces"> </span><span class="nottickedoff">inp &lt;- T.readFile path</span>
<span class="lineno"> 54 </span><span class="spaces"> </span><span class="nottickedoff">case parse inp of</span>
<span class="lineno"> 55 </span><span class="spaces"> </span><span class="nottickedoff">Nothing -&gt; genCache root path</span>
<span class="lineno"> 56 </span><span class="spaces"> </span><span class="nottickedoff">Just val -&gt; pure val</span>
<span class="lineno"> 57 </span><span class="spaces"> </span><span class="nottickedoff">else genCache root path</span>
<span class="lineno"> 58 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 59 </span><span class="spaces"> </span><span class="nottickedoff">genCache root path = do</span>
<span class="lineno"> 60 </span><span class="spaces"> </span><span class="nottickedoff">(tmpPath, tmpHandle) &lt;- openTempFile root (encodeInt (hash key))</span>
<span class="lineno"> 61 </span><span class="spaces"> </span><span class="nottickedoff">new &lt;- gen key</span>
<span class="lineno"> 62 </span><span class="spaces"> </span><span class="nottickedoff">T.hPutStr tmpHandle (render new)</span>
<span class="lineno"> 63 </span><span class="spaces"> </span><span class="nottickedoff">hClose tmpHandle</span>
<span class="lineno"> 64 </span><span class="spaces"> </span><span class="nottickedoff">renameOrCopyFile tmpPath path</span>
<span class="lineno"> 65 </span><span class="spaces"> </span><span class="nottickedoff">return new</span></span>
<span class="lineno"> 66 </span>
<span class="lineno"> 67 </span>cacheDiskKey :: Text -&gt; IO Tree -&gt; IO Tree
<span class="lineno"> 68 </span><span class="decl"><span class="nottickedoff">cacheDiskKey key gen = cacheDiskSvg (const gen) key</span></span>
<span class="lineno"> 69 </span>
<span class="lineno"> 70 </span>cacheDiskSvg :: (Text -&gt; IO Tree) -&gt; (Text -&gt; IO Tree)
<span class="lineno"> 71 </span><span class="decl"><span class="nottickedoff">cacheDiskSvg = cacheDisk &quot;svg&quot; parse render</span>
<span class="lineno"> 72 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 73 </span><span class="spaces"> </span><span class="nottickedoff">parse txt = case parseXML txt of</span>
<span class="lineno"> 74 </span><span class="spaces"> </span><span class="nottickedoff">[Elem t] -&gt; Just (unparse t)</span>
<span class="lineno"> 75 </span><span class="spaces"> </span><span class="nottickedoff">_ -&gt; Nothing</span>
<span class="lineno"> 76 </span><span class="spaces"> </span><span class="nottickedoff">render = T.pack . renderTree</span></span>
<span class="lineno"> 77 </span>
<span class="lineno"> 78 </span>cacheDiskLines :: (Text -&gt; IO [Text]) -&gt; (Text -&gt; IO [Text])
<span class="lineno"> 79 </span><span class="decl"><span class="nottickedoff">cacheDiskLines = cacheDisk &quot;txt&quot; parse render</span>
<span class="lineno"> 80 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 81 </span><span class="spaces"> </span><span class="nottickedoff">parse = Just . T.lines</span>
<span class="lineno"> 82 </span><span class="spaces"> </span><span class="nottickedoff">render = T.unlines</span></span>
<span class="lineno"> 83 </span>
<span class="lineno"> 84 </span>
<span class="lineno"> 85 </span>{-# NOINLINE cache #-}
<span class="lineno"> 86 </span>cache :: IORef (Map Text Tree)
<span class="lineno"> 87 </span><span class="decl"><span class="nottickedoff">cache = unsafePerformIO (newIORef Map.empty)</span></span>
<span class="lineno"> 88 </span>
<span class="lineno"> 89 </span>cacheMem :: (Text -&gt; IO Tree) -&gt; (Text -&gt; IO Tree)
<span class="lineno"> 90 </span><span class="decl"><span class="nottickedoff">cacheMem gen key = do</span>
<span class="lineno"> 91 </span><span class="spaces"> </span><span class="nottickedoff">store &lt;- readIORef cache</span>
<span class="lineno"> 92 </span><span class="spaces"> </span><span class="nottickedoff">case Map.lookup key store of</span>
<span class="lineno"> 93 </span><span class="spaces"> </span><span class="nottickedoff">Just svg -&gt; return svg</span>
<span class="lineno"> 94 </span><span class="spaces"> </span><span class="nottickedoff">Nothing -&gt; do</span>
<span class="lineno"> 95 </span><span class="spaces"> </span><span class="nottickedoff">svg &lt;- gen key</span>
<span class="lineno"> 96 </span><span class="spaces"> </span><span class="nottickedoff">case svg of</span>
<span class="lineno"> 97 </span><span class="spaces"> </span><span class="nottickedoff">-- None usually indicates that latex or another tool was misconfigured. In this case,</span>
<span class="lineno"> 98 </span><span class="spaces"> </span><span class="nottickedoff">-- don't store the result.</span>
<span class="lineno"> 99 </span><span class="spaces"> </span><span class="nottickedoff">None -&gt; pure None</span>
<span class="lineno"> 100 </span><span class="spaces"> </span><span class="nottickedoff">_ -&gt; atomicModifyIORef cache (\m -&gt; (Map.insert key svg m, svg))</span></span>
<span class="lineno"> 101 </span>
<span class="lineno"> 102 </span>encodeInt :: Int -&gt; String
<span class="lineno"> 103 </span><span class="decl"><span class="nottickedoff">encodeInt i = worker (fromIntegral i) 60</span>
<span class="lineno"> 104 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 105 </span><span class="spaces"> </span><span class="nottickedoff">worker :: Word -&gt; Int -&gt; String</span>
<span class="lineno"> 106 </span><span class="spaces"> </span><span class="nottickedoff">worker key sh</span>
<span class="lineno"> 107 </span><span class="spaces"> </span><span class="nottickedoff">| sh &lt; 0 = []</span>
<span class="lineno"> 108 </span><span class="spaces"> </span><span class="nottickedoff">| otherwise =</span>
<span class="lineno"> 109 </span><span class="spaces"> </span><span class="nottickedoff">case (key `shiftR` sh) `mod` 64 of</span>
<span class="lineno"> 110 </span><span class="spaces"> </span><span class="nottickedoff">idx -&gt; alphabet !! fromIntegral idx : worker key (sh-6)</span>
<span class="lineno"> 111 </span><span class="spaces"> </span><span class="nottickedoff">alphabet = &quot;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+$&quot;</span></span>
</pre>
</body>
</html>

View file

@ -0,0 +1,51 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style type="text/css">
span.lineno { color: white; background: #aaaaaa; border-right: solid white 12px }
span.nottickedoff { background: yellow}
span.istickedoff { background: white }
span.tickonlyfalse { margin: -1px; border: 1px solid #f20913; background: #f20913 }
span.tickonlytrue { margin: -1px; border: 1px solid #60de51; background: #60de51 }
span.funcount { font-size: small; color: orange; z-index: 2; position: absolute; right: 20 }
span.decl { font-weight: bold }
span.spaces { background: white }
</style>
</head>
<body>
<pre>
<span class="decl"><span class="nottickedoff">never executed</span> <span class="tickonlytrue">always true</span> <span class="tickonlyfalse">always false</span></span>
</pre>
<pre>
<span class="lineno"> 1 </span>module Reanimate.Constants
<span class="lineno"> 2 </span> ( screenWidth
<span class="lineno"> 3 </span> , screenHeight
<span class="lineno"> 4 </span> , screenTop
<span class="lineno"> 5 </span> , screenBottom
<span class="lineno"> 6 </span> , screenLeft
<span class="lineno"> 7 </span> , screenRight
<span class="lineno"> 8 </span> , defaultDPI
<span class="lineno"> 9 </span> , defaultStrokeWidth
<span class="lineno"> 10 </span> ) where
<span class="lineno"> 11 </span>
<span class="lineno"> 12 </span>import Graphics.SvgTree
<span class="lineno"> 13 </span>
<span class="lineno"> 14 </span>screenWidth, screenHeight, screenTop :: Fractional a =&gt; a
<span class="lineno"> 15 </span>screenBottom, screenLeft, screenRight :: Fractional a =&gt; a
<span class="lineno"> 16 </span>
<span class="lineno"> 17 </span><span class="decl"><span class="istickedoff">screenWidth = 16</span></span>
<span class="lineno"> 18 </span><span class="decl"><span class="istickedoff">screenHeight = 9</span></span>
<span class="lineno"> 19 </span><span class="decl"><span class="nottickedoff">screenTop = screenHeight/2</span></span>
<span class="lineno"> 20 </span><span class="decl"><span class="nottickedoff">screenBottom = -screenHeight/2</span></span>
<span class="lineno"> 21 </span><span class="decl"><span class="nottickedoff">screenLeft = -screenWidth/2</span></span>
<span class="lineno"> 22 </span><span class="decl"><span class="nottickedoff">screenRight = screenWidth/2</span></span>
<span class="lineno"> 23 </span>
<span class="lineno"> 24 </span>defaultDPI :: Dpi
<span class="lineno"> 25 </span><span class="decl"><span class="nottickedoff">defaultDPI = 96</span></span>
<span class="lineno"> 26 </span>
<span class="lineno"> 27 </span>defaultStrokeWidth :: Double
<span class="lineno"> 28 </span><span class="decl"><span class="istickedoff">defaultStrokeWidth = 0.05</span></span>
</pre>
</body>
</html>

View file

@ -0,0 +1,246 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style type="text/css">
span.lineno { color: white; background: #aaaaaa; border-right: solid white 12px }
span.nottickedoff { background: yellow}
span.istickedoff { background: white }
span.tickonlyfalse { margin: -1px; border: 1px solid #f20913; background: #f20913 }
span.tickonlytrue { margin: -1px; border: 1px solid #60de51; background: #60de51 }
span.funcount { font-size: small; color: orange; z-index: 2; position: absolute; right: 20 }
span.decl { font-weight: bold }
span.spaces { background: white }
</style>
</head>
<body>
<pre>
<span class="decl"><span class="nottickedoff">never executed</span> <span class="tickonlytrue">always true</span> <span class="tickonlyfalse">always false</span></span>
</pre>
<pre>
<span class="lineno"> 1 </span>module Reanimate.Driver.CLI
<span class="lineno"> 2 </span> ( getDriverOptions
<span class="lineno"> 3 </span> , Options(..)
<span class="lineno"> 4 </span> , Command(..)
<span class="lineno"> 5 </span> , Preset(..)
<span class="lineno"> 6 </span> , Format(..)
<span class="lineno"> 7 </span> , Raster(..)
<span class="lineno"> 8 </span> , showFormat
<span class="lineno"> 9 </span> , showRaster
<span class="lineno"> 10 </span> ) where
<span class="lineno"> 11 </span>
<span class="lineno"> 12 </span>import Data.Char
<span class="lineno"> 13 </span>import Data.Monoid
<span class="lineno"> 14 </span>import Options.Applicative
<span class="lineno"> 15 </span>import Prelude
<span class="lineno"> 16 </span>import Reanimate.Render (FPS, Format (..), Height, Raster (..),
<span class="lineno"> 17 </span> Width)
<span class="lineno"> 18 </span>
<span class="lineno"> 19 </span>newtype Options = Options
<span class="lineno"> 20 </span> { <span class="nottickedoff"><span class="decl"><span class="nottickedoff">optsCommand</span></span></span> :: Command
<span class="lineno"> 21 </span> } deriving (<span class="decl"><span class="nottickedoff">Show</span></span>)
<span class="lineno"> 22 </span>
<span class="lineno"> 23 </span>data Command
<span class="lineno"> 24 </span> = Raw
<span class="lineno"> 25 </span> { <span class="nottickedoff"><span class="decl"><span class="nottickedoff">rawOutputFolder</span></span></span> :: FilePath
<span class="lineno"> 26 </span> , <span class="nottickedoff"><span class="decl"><span class="nottickedoff">rawFrameOffset</span></span></span> :: Int
<span class="lineno"> 27 </span> , <span class="nottickedoff"><span class="decl"><span class="nottickedoff">rawPrettyPrint</span></span></span> :: Bool
<span class="lineno"> 28 </span> }
<span class="lineno"> 29 </span> | Test
<span class="lineno"> 30 </span> | Check
<span class="lineno"> 31 </span> | View
<span class="lineno"> 32 </span> { <span class="nottickedoff"><span class="decl"><span class="nottickedoff">viewVerbose</span></span></span> :: Bool
<span class="lineno"> 33 </span> , <span class="nottickedoff"><span class="decl"><span class="nottickedoff">viewGHCPath</span></span></span> :: Maybe FilePath
<span class="lineno"> 34 </span> , <span class="nottickedoff"><span class="decl"><span class="nottickedoff">viewGHCOpts</span></span></span> :: [String]
<span class="lineno"> 35 </span> , <span class="nottickedoff"><span class="decl"><span class="nottickedoff">viewOrigin</span></span></span> :: Maybe FilePath
<span class="lineno"> 36 </span> }
<span class="lineno"> 37 </span> | Render
<span class="lineno"> 38 </span> { <span class="nottickedoff"><span class="decl"><span class="nottickedoff">renderTarget</span></span></span> :: Maybe String
<span class="lineno"> 39 </span> , <span class="nottickedoff"><span class="decl"><span class="nottickedoff">renderFPS</span></span></span> :: Maybe FPS
<span class="lineno"> 40 </span> , <span class="nottickedoff"><span class="decl"><span class="nottickedoff">renderWidth</span></span></span> :: Maybe Width
<span class="lineno"> 41 </span> , <span class="nottickedoff"><span class="decl"><span class="nottickedoff">renderHeight</span></span></span> :: Maybe Height
<span class="lineno"> 42 </span> , <span class="nottickedoff"><span class="decl"><span class="nottickedoff">renderCompile</span></span></span> :: Bool
<span class="lineno"> 43 </span> , <span class="nottickedoff"><span class="decl"><span class="nottickedoff">renderFormat</span></span></span> :: Maybe Format
<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>
</pre>
</body>
</html>

View file

@ -0,0 +1,229 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style type="text/css">
span.lineno { color: white; background: #aaaaaa; border-right: solid white 12px }
span.nottickedoff { background: yellow}
span.istickedoff { background: white }
span.tickonlyfalse { margin: -1px; border: 1px solid #f20913; background: #f20913 }
span.tickonlytrue { margin: -1px; border: 1px solid #60de51; background: #60de51 }
span.funcount { font-size: small; color: orange; z-index: 2; position: absolute; right: 20 }
span.decl { font-weight: bold }
span.spaces { background: white }
</style>
</head>
<body>
<pre>
<span class="decl"><span class="nottickedoff">never executed</span> <span class="tickonlytrue">always true</span> <span class="tickonlyfalse">always false</span></span>
</pre>
<pre>
<span class="lineno"> 1 </span>{-# LANGUAGE ScopedTypeVariables #-}
<span class="lineno"> 2 </span>module Reanimate.Driver.Check
<span class="lineno"> 3 </span> ( checkEnvironment
<span class="lineno"> 4 </span> , hasRSvg
<span class="lineno"> 5 </span> , hasInkscape
<span class="lineno"> 6 </span> , hasMagick
<span class="lineno"> 7 </span> , hasFFmpegRSvg
<span class="lineno"> 8 </span> ) where
<span class="lineno"> 9 </span>
<span class="lineno"> 10 </span>import Control.Exception (SomeException, handle)
<span class="lineno"> 11 </span>import Control.Monad
<span class="lineno"> 12 </span>import Data.Maybe
<span class="lineno"> 13 </span>import Data.Version
<span class="lineno"> 14 </span>import Reanimate.Misc (runCmd_)
<span class="lineno"> 15 </span>import Reanimate.Driver.Magick (magickCmd)
<span class="lineno"> 16 </span>import System.Console.ANSI.Codes
<span class="lineno"> 17 </span>import System.Directory (findExecutable)
<span class="lineno"> 18 </span>import System.IO
<span class="lineno"> 19 </span>import System.IO.Temp
<span class="lineno"> 20 </span>import Text.ParserCombinators.ReadP
<span class="lineno"> 21 </span>import Text.Printf
<span class="lineno"> 22 </span>
<span class="lineno"> 23 </span>--------------------------------------------------------------------------
<span class="lineno"> 24 </span>-- Check environment
<span class="lineno"> 25 </span>
<span class="lineno"> 26 </span>checkEnvironment :: IO ()
<span class="lineno"> 27 </span><span class="decl"><span class="nottickedoff">checkEnvironment = do</span>
<span class="lineno"> 28 </span><span class="spaces"> </span><span class="nottickedoff">putStrLn &quot;reanimate checks:&quot;</span>
<span class="lineno"> 29 </span><span class="spaces"> </span><span class="nottickedoff">runCheck &quot;Has ffmpeg&quot; hasFFmpeg</span>
<span class="lineno"> 30 </span><span class="spaces"> </span><span class="nottickedoff">runCheck &quot;Has ffmpeg(rsvg)&quot; hasFFmpegRSvg</span>
<span class="lineno"> 31 </span><span class="spaces"> </span><span class="nottickedoff">runCheck &quot;Has dvisvgm&quot; hasDvisvgm</span>
<span class="lineno"> 32 </span><span class="spaces"> </span><span class="nottickedoff">runCheck &quot;Has povray&quot; hasPovray</span>
<span class="lineno"> 33 </span><span class="spaces"> </span><span class="nottickedoff">runCheck &quot;Has blender&quot; hasBlender</span>
<span class="lineno"> 34 </span><span class="spaces"> </span><span class="nottickedoff">runCheck &quot;Has rsvg-convert&quot; hasRSvg</span>
<span class="lineno"> 35 </span><span class="spaces"> </span><span class="nottickedoff">runCheck &quot;Has inkscape&quot; hasInkscape</span>
<span class="lineno"> 36 </span><span class="spaces"> </span><span class="nottickedoff">runCheck &quot;Has imagemagick&quot; hasMagick</span>
<span class="lineno"> 37 </span><span class="spaces"> </span><span class="nottickedoff">runCheck &quot;Has LaTeX&quot; hasLaTeX</span>
<span class="lineno"> 38 </span><span class="spaces"> </span><span class="nottickedoff">runCheck (&quot;Has LaTeX package '&quot;++ &quot;babel&quot; ++ &quot;'&quot;) $ hasTeXPackage &quot;latex&quot;</span>
<span class="lineno"> 39 </span><span class="spaces"> </span><span class="nottickedoff">&quot;[english]{babel}&quot;</span>
<span class="lineno"> 40 </span><span class="spaces"> </span><span class="nottickedoff">forM_ latexPackages $ \pkg -&gt;</span>
<span class="lineno"> 41 </span><span class="spaces"> </span><span class="nottickedoff">runCheck (&quot;Has LaTeX package '&quot;++ pkg ++ &quot;'&quot;) $ hasTeXPackage &quot;latex&quot; $</span>
<span class="lineno"> 42 </span><span class="spaces"> </span><span class="nottickedoff">&quot;{&quot;++pkg++&quot;}&quot;</span>
<span class="lineno"> 43 </span><span class="spaces"> </span><span class="nottickedoff">runCheck &quot;Has XeLaTeX&quot; hasXeLaTeX</span>
<span class="lineno"> 44 </span><span class="spaces"> </span><span class="nottickedoff">forM_ xelatexPackages $ \pkg -&gt;</span>
<span class="lineno"> 45 </span><span class="spaces"> </span><span class="nottickedoff">runCheck (&quot;Has XeLaTeX package '&quot;++ pkg ++ &quot;'&quot;) $ hasTeXPackage &quot;xelatex&quot; $</span>
<span class="lineno"> 46 </span><span class="spaces"> </span><span class="nottickedoff">&quot;{&quot;++pkg++&quot;}&quot;</span>
<span class="lineno"> 47 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 48 </span><span class="spaces"> </span><span class="nottickedoff">latexPackages =</span>
<span class="lineno"> 49 </span><span class="spaces"> </span><span class="nottickedoff">[&quot;preview&quot;</span>
<span class="lineno"> 50 </span><span class="spaces"> </span><span class="nottickedoff">,&quot;amsmath&quot;</span>
<span class="lineno"> 51 </span><span class="spaces"> </span><span class="nottickedoff">--,&quot;amssymb&quot;</span>
<span class="lineno"> 52 </span><span class="spaces"> </span><span class="nottickedoff">--,&quot;dsfont&quot;</span>
<span class="lineno"> 53 </span><span class="spaces"> </span><span class="nottickedoff">--,&quot;setspace&quot;</span>
<span class="lineno"> 54 </span><span class="spaces"> </span><span class="nottickedoff">--,&quot;relsize&quot;</span>
<span class="lineno"> 55 </span><span class="spaces"> </span><span class="nottickedoff">--,&quot;textcomp&quot;</span>
<span class="lineno"> 56 </span><span class="spaces"> </span><span class="nottickedoff">--,&quot;mathrsfs&quot;</span>
<span class="lineno"> 57 </span><span class="spaces"> </span><span class="nottickedoff">--,&quot;calligra&quot;</span>
<span class="lineno"> 58 </span><span class="spaces"> </span><span class="nottickedoff">--,&quot;wasysym&quot;</span>
<span class="lineno"> 59 </span><span class="spaces"> </span><span class="nottickedoff">--,&quot;ragged2e&quot;</span>
<span class="lineno"> 60 </span><span class="spaces"> </span><span class="nottickedoff">--,&quot;physics&quot;</span>
<span class="lineno"> 61 </span><span class="spaces"> </span><span class="nottickedoff">--,&quot;xcolor&quot;</span>
<span class="lineno"> 62 </span><span class="spaces"> </span><span class="nottickedoff">--,&quot;textcomp&quot;</span>
<span class="lineno"> 63 </span><span class="spaces"> </span><span class="nottickedoff">--,&quot;xfrac&quot;</span>
<span class="lineno"> 64 </span><span class="spaces"> </span><span class="nottickedoff">--,&quot;microtype&quot;</span>
<span class="lineno"> 65 </span><span class="spaces"> </span><span class="nottickedoff">]</span>
<span class="lineno"> 66 </span><span class="spaces"> </span><span class="nottickedoff">xelatexPackages =</span>
<span class="lineno"> 67 </span><span class="spaces"> </span><span class="nottickedoff">[&quot;ctex&quot;]</span>
<span class="lineno"> 68 </span><span class="spaces"> </span><span class="nottickedoff">runCheck msg fn = do</span>
<span class="lineno"> 69 </span><span class="spaces"> </span><span class="nottickedoff">printf &quot; %-35s&quot; (msg ++ &quot;:&quot;)</span>
<span class="lineno"> 70 </span><span class="spaces"> </span><span class="nottickedoff">val &lt;- fn</span>
<span class="lineno"> 71 </span><span class="spaces"> </span><span class="nottickedoff">case val of</span>
<span class="lineno"> 72 </span><span class="spaces"> </span><span class="nottickedoff">Left err -&gt; putStrLnColor Red err</span>
<span class="lineno"> 73 </span><span class="spaces"> </span><span class="nottickedoff">Right ok -&gt; putStrLnColor Green ok</span></span>
<span class="lineno"> 74 </span>
<span class="lineno"> 75 </span>putStrLnColor :: Color -&gt; String -&gt; IO ()
<span class="lineno"> 76 </span><span class="decl"><span class="nottickedoff">putStrLnColor color msg =</span>
<span class="lineno"> 77 </span><span class="spaces"> </span><span class="nottickedoff">putStrLn $ setSGRCode [SetColor Foreground Vivid color] ++ msg ++ setSGRCode [Reset]</span></span>
<span class="lineno"> 78 </span>
<span class="lineno"> 79 </span>-- latex, dvisvgm, xelatex
<span class="lineno"> 80 </span>
<span class="lineno"> 81 </span>hasLaTeX :: IO (Either String String)
<span class="lineno"> 82 </span><span class="decl"><span class="nottickedoff">hasLaTeX = hasProgram &quot;latex&quot;</span></span>
<span class="lineno"> 83 </span>
<span class="lineno"> 84 </span>hasXeLaTeX :: IO (Either String String)
<span class="lineno"> 85 </span><span class="decl"><span class="nottickedoff">hasXeLaTeX = hasProgram &quot;xelatex&quot;</span></span>
<span class="lineno"> 86 </span>
<span class="lineno"> 87 </span>hasDvisvgm :: IO (Either String String)
<span class="lineno"> 88 </span><span class="decl"><span class="nottickedoff">hasDvisvgm = hasProgram &quot;dvisvgm&quot;</span></span>
<span class="lineno"> 89 </span>
<span class="lineno"> 90 </span>hasPovray :: IO (Either String String)
<span class="lineno"> 91 </span><span class="decl"><span class="nottickedoff">hasPovray = hasProgram &quot;povray&quot;</span></span>
<span class="lineno"> 92 </span>
<span class="lineno"> 93 </span>hasFFmpeg :: IO (Either String String)
<span class="lineno"> 94 </span><span class="decl"><span class="nottickedoff">hasFFmpeg = checkMinVersion minVersion &lt;$&gt; ffmpegVersion</span>
<span class="lineno"> 95 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 96 </span><span class="spaces"> </span><span class="nottickedoff">minVersion = Version [4,1,3] []</span></span>
<span class="lineno"> 97 </span>
<span class="lineno"> 98 </span>hasFFmpegRSvg :: IO (Either String String)
<span class="lineno"> 99 </span><span class="decl"><span class="nottickedoff">hasFFmpegRSvg = do</span>
<span class="lineno"> 100 </span><span class="spaces"> </span><span class="nottickedoff">mbPath &lt;- findExecutable &quot;ffmpeg&quot;</span>
<span class="lineno"> 101 </span><span class="spaces"> </span><span class="nottickedoff">case mbPath of</span>
<span class="lineno"> 102 </span><span class="spaces"> </span><span class="nottickedoff">Nothing -&gt; return $ Left &quot;n/a&quot;</span>
<span class="lineno"> 103 </span><span class="spaces"> </span><span class="nottickedoff">Just path -&gt; do</span>
<span class="lineno"> 104 </span><span class="spaces"> </span><span class="nottickedoff">ret &lt;- runCmd_ path [&quot;-version&quot;]</span>
<span class="lineno"> 105 </span><span class="spaces"> </span><span class="nottickedoff">pure $ case ret of</span>
<span class="lineno"> 106 </span><span class="spaces"> </span><span class="nottickedoff">Right out | &quot;--enable-librsvg&quot; `elem` words out</span>
<span class="lineno"> 107 </span><span class="spaces"> </span><span class="nottickedoff">-&gt; Right &quot;yes&quot;</span>
<span class="lineno"> 108 </span><span class="spaces"> </span><span class="nottickedoff">_ -&gt; Left &quot;no&quot;</span></span>
<span class="lineno"> 109 </span>
<span class="lineno"> 110 </span>hasBlender :: IO (Either String String)
<span class="lineno"> 111 </span><span class="decl"><span class="nottickedoff">hasBlender = checkMinVersion minVersion &lt;$&gt; blenderVersion</span>
<span class="lineno"> 112 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 113 </span><span class="spaces"> </span><span class="nottickedoff">minVersion = Version [2,80] []</span></span>
<span class="lineno"> 114 </span>
<span class="lineno"> 115 </span>hasRSvg :: IO (Either String String)
<span class="lineno"> 116 </span><span class="decl"><span class="nottickedoff">hasRSvg = checkMinVersion minVersion &lt;$&gt; rsvgVersion</span>
<span class="lineno"> 117 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 118 </span><span class="spaces"> </span><span class="nottickedoff">minVersion = Version [2,44,0] []</span></span>
<span class="lineno"> 119 </span>
<span class="lineno"> 120 </span>hasInkscape :: IO (Either String String)
<span class="lineno"> 121 </span><span class="decl"><span class="nottickedoff">hasInkscape = checkMinVersion minVersion &lt;$&gt; inkscapeVersion</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">minVersion = Version [0,92] []</span></span>
<span class="lineno"> 124 </span>
<span class="lineno"> 125 </span>hasMagick :: IO (Either String String)
<span class="lineno"> 126 </span><span class="decl"><span class="nottickedoff">hasMagick = checkMinVersion minVersion &lt;$&gt; magickVersion</span>
<span class="lineno"> 127 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 128 </span><span class="spaces"> </span><span class="nottickedoff">minVersion = Version [6,0,0] []</span></span>
<span class="lineno"> 129 </span>
<span class="lineno"> 130 </span>ffmpegVersion :: IO (Maybe Version)
<span class="lineno"> 131 </span><span class="decl"><span class="nottickedoff">ffmpegVersion = extractVersion &quot;ffmpeg&quot; [&quot;-version&quot;] $ \line -&gt;</span>
<span class="lineno"> 132 </span><span class="spaces"> </span><span class="nottickedoff">case take 3 $ words line of</span>
<span class="lineno"> 133 </span><span class="spaces"> </span><span class="nottickedoff">[&quot;ffmpeg&quot;, &quot;version&quot;, vs] -&gt; vs</span>
<span class="lineno"> 134 </span><span class="spaces"> </span><span class="nottickedoff">_ -&gt; &quot;&quot;</span></span>
<span class="lineno"> 135 </span>
<span class="lineno"> 136 </span>blenderVersion :: IO (Maybe Version)
<span class="lineno"> 137 </span><span class="decl"><span class="nottickedoff">blenderVersion = extractVersion &quot;blender&quot; [&quot;--version&quot;] $ \line -&gt;</span>
<span class="lineno"> 138 </span><span class="spaces"> </span><span class="nottickedoff">case take 2 (words line) of</span>
<span class="lineno"> 139 </span><span class="spaces"> </span><span class="nottickedoff">[&quot;Blender&quot;, vs] -&gt; vs</span>
<span class="lineno"> 140 </span><span class="spaces"> </span><span class="nottickedoff">_ -&gt; &quot;&quot;</span></span>
<span class="lineno"> 141 </span>
<span class="lineno"> 142 </span>rsvgVersion :: IO (Maybe Version)
<span class="lineno"> 143 </span><span class="decl"><span class="nottickedoff">rsvgVersion = extractVersion &quot;rsvg-convert&quot; [&quot;--version&quot;] $ \line -&gt;</span>
<span class="lineno"> 144 </span><span class="spaces"> </span><span class="nottickedoff">case words line of</span>
<span class="lineno"> 145 </span><span class="spaces"> </span><span class="nottickedoff">[&quot;rsvg-convert&quot;, &quot;version&quot;, vs] -&gt; vs</span>
<span class="lineno"> 146 </span><span class="spaces"> </span><span class="nottickedoff">_ -&gt; &quot;&quot;</span></span>
<span class="lineno"> 147 </span>
<span class="lineno"> 148 </span>inkscapeVersion :: IO (Maybe Version)
<span class="lineno"> 149 </span><span class="decl"><span class="nottickedoff">inkscapeVersion = extractVersion &quot;inkscape&quot; [&quot;--version&quot;] $ \line -&gt;</span>
<span class="lineno"> 150 </span><span class="spaces"> </span><span class="nottickedoff">case take 2 $ words line of</span>
<span class="lineno"> 151 </span><span class="spaces"> </span><span class="nottickedoff">[&quot;Inkscape&quot;, vs] -&gt; vs</span>
<span class="lineno"> 152 </span><span class="spaces"> </span><span class="nottickedoff">_ -&gt; &quot;&quot;</span></span>
<span class="lineno"> 153 </span>
<span class="lineno"> 154 </span>magickVersion :: IO (Maybe Version)
<span class="lineno"> 155 </span><span class="decl"><span class="nottickedoff">magickVersion = extractVersion magickCmd [&quot;-version&quot;] $ \line -&gt;</span>
<span class="lineno"> 156 </span><span class="spaces"> </span><span class="nottickedoff">case take 3 $ words line of</span>
<span class="lineno"> 157 </span><span class="spaces"> </span><span class="nottickedoff">[&quot;Version:&quot;, &quot;ImageMagick&quot;, vs] -&gt; vs</span>
<span class="lineno"> 158 </span><span class="spaces"> </span><span class="nottickedoff">_ -&gt; &quot;&quot;</span></span>
<span class="lineno"> 159 </span>
<span class="lineno"> 160 </span>checkMinVersion :: Version -&gt; Maybe Version -&gt; Either String String
<span class="lineno"> 161 </span><span class="decl"><span class="nottickedoff">checkMinVersion _minVersion Nothing = Left &quot;no&quot;</span>
<span class="lineno"> 162 </span><span class="spaces"></span><span class="nottickedoff">checkMinVersion minVersion (Just vs)</span>
<span class="lineno"> 163 </span><span class="spaces"> </span><span class="nottickedoff">| vs &lt; minVersion = Left $ &quot;too old: &quot; ++ showVersion vs ++ &quot; &lt; &quot; ++ showVersion minVersion</span>
<span class="lineno"> 164 </span><span class="spaces"> </span><span class="nottickedoff">| otherwise = Right (showVersion vs)</span></span>
<span class="lineno"> 165 </span>
<span class="lineno"> 166 </span>extractVersion :: FilePath -&gt; [String] -&gt; (String -&gt; String) -&gt; IO (Maybe Version)
<span class="lineno"> 167 </span><span class="decl"><span class="nottickedoff">extractVersion execPath args outputFilter = do</span>
<span class="lineno"> 168 </span><span class="spaces"> </span><span class="nottickedoff">mbPath &lt;- findExecutable execPath</span>
<span class="lineno"> 169 </span><span class="spaces"> </span><span class="nottickedoff">case mbPath of</span>
<span class="lineno"> 170 </span><span class="spaces"> </span><span class="nottickedoff">Nothing -&gt; return Nothing</span>
<span class="lineno"> 171 </span><span class="spaces"> </span><span class="nottickedoff">Just path -&gt; do</span>
<span class="lineno"> 172 </span><span class="spaces"> </span><span class="nottickedoff">ret &lt;- runCmd_ path args</span>
<span class="lineno"> 173 </span><span class="spaces"> </span><span class="nottickedoff">case ret of</span>
<span class="lineno"> 174 </span><span class="spaces"> </span><span class="nottickedoff">Left{} -&gt; return $ Just noVersion</span>
<span class="lineno"> 175 </span><span class="spaces"> </span><span class="nottickedoff">Right out -&gt;</span>
<span class="lineno"> 176 </span><span class="spaces"> </span><span class="nottickedoff">pure $ Just $ fromMaybe noVersion $ parseVS $ outputFilter out</span>
<span class="lineno"> 177 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 178 </span><span class="spaces"> </span><span class="nottickedoff">noVersion = Version [] []</span>
<span class="lineno"> 179 </span><span class="spaces"> </span><span class="nottickedoff">parseVS vs = listToMaybe $ reverse</span>
<span class="lineno"> 180 </span><span class="spaces"> </span><span class="nottickedoff">[ v | (v, _) &lt;- readP_to_S parseVersion vs ]</span></span>
<span class="lineno"> 181 </span>
<span class="lineno"> 182 </span>hasTeXPackage :: FilePath -&gt; String -&gt; IO (Either String String)
<span class="lineno"> 183 </span><span class="decl"><span class="nottickedoff">hasTeXPackage exec pkg = handle (\(_::SomeException) -&gt; return $ Left &quot;n/a&quot;) $</span>
<span class="lineno"> 184 </span><span class="spaces"> </span><span class="nottickedoff">withSystemTempDirectory &quot;reanimate&quot; $ \tmp_dir -&gt; withTempFile tmp_dir &quot;test.tex&quot; $ \tex_file tex_handle -&gt; do</span>
<span class="lineno"> 185 </span><span class="spaces"> </span><span class="nottickedoff">hPutStr tex_handle tex_document</span>
<span class="lineno"> 186 </span><span class="spaces"> </span><span class="nottickedoff">hPutStr tex_handle $ &quot;\\usepackage&quot; ++ pkg ++ &quot;\n&quot;</span>
<span class="lineno"> 187 </span><span class="spaces"> </span><span class="nottickedoff">hPutStr tex_handle &quot;\\begin{document}\n&quot;</span>
<span class="lineno"> 188 </span><span class="spaces"> </span><span class="nottickedoff">hPutStr tex_handle &quot;blah\n&quot;</span>
<span class="lineno"> 189 </span><span class="spaces"> </span><span class="nottickedoff">hPutStr tex_handle tex_epilogue</span>
<span class="lineno"> 190 </span><span class="spaces"> </span><span class="nottickedoff">hClose tex_handle</span>
<span class="lineno"> 191 </span><span class="spaces"> </span><span class="nottickedoff">ret &lt;- runCmd_ exec [&quot;-interaction=batchmode&quot;, &quot;-halt-on-error&quot;, &quot;-output-directory=&quot;++tmp_dir, tex_file]</span>
<span class="lineno"> 192 </span><span class="spaces"> </span><span class="nottickedoff">return $ case ret of</span>
<span class="lineno"> 193 </span><span class="spaces"> </span><span class="nottickedoff">Right{} -&gt; Right &quot;OK&quot;</span>
<span class="lineno"> 194 </span><span class="spaces"> </span><span class="nottickedoff">Left{} -&gt; Left &quot;missing&quot;</span>
<span class="lineno"> 195 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 196 </span><span class="spaces"> </span><span class="nottickedoff">tex_document = &quot;\\documentclass[preview]{standalone}\n&quot;</span>
<span class="lineno"> 197 </span><span class="spaces"> </span><span class="nottickedoff">tex_epilogue =</span>
<span class="lineno"> 198 </span><span class="spaces"> </span><span class="nottickedoff">&quot;\n\</span>
<span class="lineno"> 199 </span><span class="spaces"> </span><span class="nottickedoff">\\\end{document}&quot;</span></span>
<span class="lineno"> 200 </span>
<span class="lineno"> 201 </span>hasProgram :: String -&gt; IO (Either String String)
<span class="lineno"> 202 </span><span class="decl"><span class="nottickedoff">hasProgram exec = do</span>
<span class="lineno"> 203 </span><span class="spaces"> </span><span class="nottickedoff">mbPath &lt;- findExecutable exec</span>
<span class="lineno"> 204 </span><span class="spaces"> </span><span class="nottickedoff">return $ case mbPath of</span>
<span class="lineno"> 205 </span><span class="spaces"> </span><span class="nottickedoff">Nothing -&gt; Left $ &quot;'&quot; ++ exec ++ &quot;' not found&quot;</span>
<span class="lineno"> 206 </span><span class="spaces"> </span><span class="nottickedoff">Just path -&gt; Right path</span></span>
</pre>
</body>
</html>

View file

@ -0,0 +1,58 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style type="text/css">
span.lineno { color: white; background: #aaaaaa; border-right: solid white 12px }
span.nottickedoff { background: yellow}
span.istickedoff { background: white }
span.tickonlyfalse { margin: -1px; border: 1px solid #f20913; background: #f20913 }
span.tickonlytrue { margin: -1px; border: 1px solid #60de51; background: #60de51 }
span.funcount { font-size: small; color: orange; z-index: 2; position: absolute; right: 20 }
span.decl { font-weight: bold }
span.spaces { background: white }
</style>
</head>
<body>
<pre>
<span class="decl"><span class="nottickedoff">never executed</span> <span class="tickonlytrue">always true</span> <span class="tickonlyfalse">always false</span></span>
</pre>
<pre>
<span class="lineno"> 1 </span>module Reanimate.Driver.Compile ( compile ) where
<span class="lineno"> 2 </span>
<span class="lineno"> 3 </span>import Reanimate.Driver.Server (findOwnSource)
<span class="lineno"> 4 </span>import System.Directory
<span class="lineno"> 5 </span>import System.Exit
<span class="lineno"> 6 </span>import System.FilePath
<span class="lineno"> 7 </span>import System.Process
<span class="lineno"> 8 </span>import System.IO
<span class="lineno"> 9 </span>
<span class="lineno"> 10 </span>compile :: [String] -&gt; IO ()
<span class="lineno"> 11 </span><span class="decl"><span class="nottickedoff">compile opts = do</span>
<span class="lineno"> 12 </span><span class="spaces"> </span><span class="nottickedoff">mbSelf &lt;- findOwnSource</span>
<span class="lineno"> 13 </span><span class="spaces"> </span><span class="nottickedoff">case mbSelf of</span>
<span class="lineno"> 14 </span><span class="spaces"> </span><span class="nottickedoff">Nothing -&gt; do</span>
<span class="lineno"> 15 </span><span class="spaces"> </span><span class="nottickedoff">hPutStrLn stderr</span>
<span class="lineno"> 16 </span><span class="spaces"> </span><span class="nottickedoff">&quot;Failed to find source code. Did you already compile the animations?\n\</span>
<span class="lineno"> 17 </span><span class="spaces"> </span><span class="nottickedoff">\Try running again without the --compile flag.&quot;</span>
<span class="lineno"> 18 </span><span class="spaces"> </span><span class="nottickedoff">exitFailure</span>
<span class="lineno"> 19 </span><span class="spaces"> </span><span class="nottickedoff">Just self -&gt; do</span>
<span class="lineno"> 20 </span><span class="spaces"> </span><span class="nottickedoff">let selfDir = takeDirectory self</span>
<span class="lineno"> 21 </span><span class="spaces"> </span><span class="nottickedoff">selfName = takeBaseName self</span>
<span class="lineno"> 22 </span><span class="spaces"> </span><span class="nottickedoff">outDir = selfDir &lt;/&gt; &quot;.reanimate&quot; &lt;/&gt; selfName</span>
<span class="lineno"> 23 </span><span class="spaces"> </span><span class="nottickedoff">target = outDir &lt;/&gt; selfName</span>
<span class="lineno"> 24 </span><span class="spaces"> </span><span class="nottickedoff">ghcOptions =</span>
<span class="lineno"> 25 </span><span class="spaces"> </span><span class="nottickedoff">[&quot;-rtsopts&quot;, &quot;--make&quot;, &quot;-threaded&quot;, &quot;-O2&quot;] ++</span>
<span class="lineno"> 26 </span><span class="spaces"> </span><span class="nottickedoff">[&quot;-odir&quot;, outDir, &quot;-hidir&quot;, outDir] ++</span>
<span class="lineno"> 27 </span><span class="spaces"> </span><span class="nottickedoff">[self, &quot;-o&quot;, target]</span>
<span class="lineno"> 28 </span><span class="spaces"> </span><span class="nottickedoff">createDirectoryIfMissing True outDir</span>
<span class="lineno"> 29 </span><span class="spaces"> </span><span class="nottickedoff">withCurrentDirectory selfDir $ do</span>
<span class="lineno"> 30 </span><span class="spaces"> </span><span class="nottickedoff">checkExitCode =&lt;&lt; rawSystem &quot;stack&quot; ([&quot;ghc&quot;, &quot;--&quot;] ++ ghcOptions)</span>
<span class="lineno"> 31 </span><span class="spaces"> </span><span class="nottickedoff">checkExitCode =&lt;&lt; rawSystem target opts</span></span>
<span class="lineno"> 32 </span>
<span class="lineno"> 33 </span>checkExitCode :: ExitCode -&gt; IO ()
<span class="lineno"> 34 </span><span class="decl"><span class="nottickedoff">checkExitCode ExitSuccess = return ()</span>
<span class="lineno"> 35 </span><span class="spaces"></span><span class="nottickedoff">checkExitCode (ExitFailure n) = exitWith (ExitFailure n)</span></span>
</pre>
</body>
</html>

View file

@ -0,0 +1,41 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style type="text/css">
span.lineno { color: white; background: #aaaaaa; border-right: solid white 12px }
span.nottickedoff { background: yellow}
span.istickedoff { background: white }
span.tickonlyfalse { margin: -1px; border: 1px solid #f20913; background: #f20913 }
span.tickonlytrue { margin: -1px; border: 1px solid #60de51; background: #60de51 }
span.funcount { font-size: small; color: orange; z-index: 2; position: absolute; right: 20 }
span.decl { font-weight: bold }
span.spaces { background: white }
</style>
</head>
<body>
<pre>
<span class="decl"><span class="nottickedoff">never executed</span> <span class="tickonlytrue">always true</span> <span class="tickonlyfalse">always false</span></span>
</pre>
<pre>
<span class="lineno"> 1 </span>module Reanimate.Driver.Magick
<span class="lineno"> 2 </span> ( magickCmd
<span class="lineno"> 3 </span> ) where
<span class="lineno"> 4 </span>
<span class="lineno"> 5 </span>import System.IO.Unsafe (unsafePerformIO)
<span class="lineno"> 6 </span>import System.Directory (findExecutable)
<span class="lineno"> 7 </span>
<span class="lineno"> 8 </span>-- |The name of the ImageMagick command. On Unix-like operating systems, the
<span class="lineno"> 9 </span>-- command 'convert' does not conflict with the name of other commands. On
<span class="lineno"> 10 </span>-- Windows, ImageMagick version 7 is readily available, the command 'magick'
<span class="lineno"> 11 </span>-- should be present, and is preferred over 'convert'. If it is not present,
<span class="lineno"> 12 </span>-- 'convert' is assumed to be the relevant command.
<span class="lineno"> 13 </span>magickCmd :: String
<span class="lineno"> 14 </span>-- The use of 'unsafeperformIO' is justified on the basis that if 'magick' is
<span class="lineno"> 15 </span>-- found once, it will always be present.
<span class="lineno"> 16 </span><span class="decl"><span class="nottickedoff">magickCmd = unsafePerformIO $ do</span>
<span class="lineno"> 17 </span><span class="spaces"> </span><span class="nottickedoff">mPath &lt;- findExecutable &quot;magick&quot;</span>
<span class="lineno"> 18 </span><span class="spaces"> </span><span class="nottickedoff">pure $ maybe &quot;convert&quot; (const &quot;magick&quot;) mPath</span></span>
</pre>
</body>
</html>

View file

@ -0,0 +1,321 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style type="text/css">
span.lineno { color: white; background: #aaaaaa; border-right: solid white 12px }
span.nottickedoff { background: yellow}
span.istickedoff { background: white }
span.tickonlyfalse { margin: -1px; border: 1px solid #f20913; background: #f20913 }
span.tickonlytrue { margin: -1px; border: 1px solid #60de51; background: #60de51 }
span.funcount { font-size: small; color: orange; z-index: 2; position: absolute; right: 20 }
span.decl { font-weight: bold }
span.spaces { background: white }
</style>
</head>
<body>
<pre>
<span class="decl"><span class="nottickedoff">never executed</span> <span class="tickonlytrue">always true</span> <span class="tickonlyfalse">always false</span></span>
</pre>
<pre>
<span class="lineno"> 1 </span>{-# LANGUAGE OverloadedStrings #-}
<span class="lineno"> 2 </span>{-# LANGUAGE ScopedTypeVariables #-}
<span class="lineno"> 3 </span>module Reanimate.Driver.Server
<span class="lineno"> 4 </span> ( serve
<span class="lineno"> 5 </span> , findOwnSource
<span class="lineno"> 6 </span> ) where
<span class="lineno"> 7 </span>
<span class="lineno"> 8 </span>import Control.Concurrent
<span class="lineno"> 9 </span>import Control.Exception (SomeException, catch, finally)
<span class="lineno"> 10 </span>import Control.Monad
<span class="lineno"> 11 </span>import Data.IORef
<span class="lineno"> 12 </span>import Data.Text (Text)
<span class="lineno"> 13 </span>import qualified Data.Text as T
<span class="lineno"> 14 </span>import qualified Data.Text.Read as T
<span class="lineno"> 15 </span>import Data.Time
<span class="lineno"> 16 </span>import GHC.Environment (getFullArgs)
<span class="lineno"> 17 </span>import Language.Haskell.Ghcid
<span class="lineno"> 18 </span>import Network.WebSockets
<span class="lineno"> 19 </span>import Paths_reanimate
<span class="lineno"> 20 </span>import Reanimate.Misc (runCmdLazy, runCmd_)
<span class="lineno"> 21 </span>import System.Directory (createDirectoryIfMissing,
<span class="lineno"> 22 </span> doesFileExist, findFile, listDirectory,
<span class="lineno"> 23 </span> makeAbsolute,
<span class="lineno"> 24 </span> withCurrentDirectory)
<span class="lineno"> 25 </span>import System.Environment (getProgName)
<span class="lineno"> 26 </span>import System.Exit
<span class="lineno"> 27 </span>import System.FilePath
<span class="lineno"> 28 </span>import System.FSNotify
<span class="lineno"> 29 </span>import System.IO
<span class="lineno"> 30 </span>import System.IO.Temp
<span class="lineno"> 31 </span>import System.Process
<span class="lineno"> 32 </span>import Web.Browser (openBrowser)
<span class="lineno"> 33 </span>
<span class="lineno"> 34 </span>opts :: ConnectionOptions
<span class="lineno"> 35 </span><span class="decl"><span class="nottickedoff">opts = defaultConnectionOptions</span>
<span class="lineno"> 36 </span><span class="spaces"> </span><span class="nottickedoff">{ connectionCompressionOptions = PermessageDeflateCompression defaultPermessageDeflate }</span></span>
<span class="lineno"> 37 </span>
<span class="lineno"> 38 </span>serve :: Bool -&gt; Maybe FilePath -&gt; [String] -&gt; Maybe FilePath -&gt; IO ()
<span class="lineno"> 39 </span><span class="decl"><span class="nottickedoff">serve verbose mbGHCPath extraGHCOpts mbSelfPath = withManager $ \watch -&gt; do</span>
<span class="lineno"> 40 </span><span class="spaces"> </span><span class="nottickedoff">hSetBuffering stdin NoBuffering</span>
<span class="lineno"> 41 </span><span class="spaces"> </span><span class="nottickedoff">self &lt;- maybe requireOwnSource pure mbSelfPath</span>
<span class="lineno"> 42 </span><span class="spaces"> </span><span class="nottickedoff">when verbose $</span>
<span class="lineno"> 43 </span><span class="spaces"> </span><span class="nottickedoff">logMsg $ &quot;Found own source code at: &quot; ++ self</span>
<span class="lineno"> 44 </span><span class="spaces"> </span><span class="nottickedoff">hasConnectionVar &lt;- newMVar False</span>
<span class="lineno"> 45 </span><span class="spaces"></span><span class="nottickedoff"></span>
<span class="lineno"> 46 </span><span class="spaces"> </span><span class="nottickedoff">ghci &lt;- ghciBackend mbGHCPath self</span>
<span class="lineno"> 47 </span><span class="spaces"></span><span class="nottickedoff"></span>
<span class="lineno"> 48 </span><span class="spaces"> </span><span class="nottickedoff">-- There might already browser window open. Wait 2s to see if that window</span>
<span class="lineno"> 49 </span><span class="spaces"> </span><span class="nottickedoff">-- connects to us. If not, open a new window.</span>
<span class="lineno"> 50 </span><span class="spaces"> </span><span class="nottickedoff">_ &lt;- forkIO $ do</span>
<span class="lineno"> 51 </span><span class="spaces"> </span><span class="nottickedoff">threadDelay (2*10^(6::Int))</span>
<span class="lineno"> 52 </span><span class="spaces"> </span><span class="nottickedoff">hasConn &lt;- readMVar hasConnectionVar</span>
<span class="lineno"> 53 </span><span class="spaces"> </span><span class="nottickedoff">unless hasConn openViewer</span>
<span class="lineno"> 54 </span><span class="spaces"> </span><span class="nottickedoff">logMsg &quot;Listening...&quot;</span>
<span class="lineno"> 55 </span><span class="spaces"> </span><span class="nottickedoff">let options = ServerOptions</span>
<span class="lineno"> 56 </span><span class="spaces"> </span><span class="nottickedoff">{ serverHost = &quot;127.0.0.1&quot;</span>
<span class="lineno"> 57 </span><span class="spaces"> </span><span class="nottickedoff">, serverPort = 9161</span>
<span class="lineno"> 58 </span><span class="spaces"> </span><span class="nottickedoff">, serverConnectionOptions = opts</span>
<span class="lineno"> 59 </span><span class="spaces"> </span><span class="nottickedoff">, serverRequirePong = Nothing }</span>
<span class="lineno"> 60 </span><span class="spaces"> </span><span class="nottickedoff">withSystemTempDirectory &quot;reanimate-svgs&quot; $ \tmpDir -&gt;</span>
<span class="lineno"> 61 </span><span class="spaces"> </span><span class="nottickedoff">runServerWithOptions options $ \pending -&gt; do</span>
<span class="lineno"> 62 </span><span class="spaces"> </span><span class="nottickedoff">logMsg &quot;New connection received.&quot;</span>
<span class="lineno"> 63 </span><span class="spaces"> </span><span class="nottickedoff">hasConn &lt;- swapMVar hasConnectionVar True</span>
<span class="lineno"> 64 </span><span class="spaces"> </span><span class="nottickedoff">if hasConn</span>
<span class="lineno"> 65 </span><span class="spaces"> </span><span class="nottickedoff">then do</span>
<span class="lineno"> 66 </span><span class="spaces"> </span><span class="nottickedoff">logMsg &quot;Already connected to browser. Rejecting.&quot;</span>
<span class="lineno"> 67 </span><span class="spaces"> </span><span class="nottickedoff">rejectRequestWith pending defaultRejectRequest</span>
<span class="lineno"> 68 </span><span class="spaces"> </span><span class="nottickedoff">else do</span>
<span class="lineno"> 69 </span><span class="spaces"> </span><span class="nottickedoff">createDirectoryIfMissing True tmpDir</span>
<span class="lineno"> 70 </span><span class="spaces"> </span><span class="nottickedoff">conn &lt;- acceptRequest pending</span>
<span class="lineno"> 71 </span><span class="spaces"> </span><span class="nottickedoff">slave &lt;- newEmptyMVar</span>
<span class="lineno"> 72 </span><span class="spaces"> </span><span class="nottickedoff">let handler = modifyMVar_ slave $ \tid -&gt; do</span>
<span class="lineno"> 73 </span><span class="spaces"> </span><span class="nottickedoff">logMsg &quot;Reloading code...&quot;</span>
<span class="lineno"> 74 </span><span class="spaces"> </span><span class="nottickedoff">killThread tid</span>
<span class="lineno"> 75 </span><span class="spaces"> </span><span class="nottickedoff">forkIO $ ignoreErrors $ slaveHandler verbose mbGHCPath extraGHCOpts conn ghci self tmpDir</span>
<span class="lineno"> 76 </span><span class="spaces"> </span><span class="nottickedoff">killSlave = do</span>
<span class="lineno"> 77 </span><span class="spaces"> </span><span class="nottickedoff">tid &lt;- takeMVar slave</span>
<span class="lineno"> 78 </span><span class="spaces"> </span><span class="nottickedoff">killThread tid</span>
<span class="lineno"> 79 </span><span class="spaces"> </span><span class="nottickedoff">stop &lt;- watchFile watch self handler</span>
<span class="lineno"> 80 </span><span class="spaces"> </span><span class="nottickedoff">putMVar slave =&lt;&lt; forkIO (return ())</span>
<span class="lineno"> 81 </span><span class="spaces"> </span><span class="nottickedoff">handler</span>
<span class="lineno"> 82 </span><span class="spaces"> </span><span class="nottickedoff">let loop = do</span>
<span class="lineno"> 83 </span><span class="spaces"> </span><span class="nottickedoff">-- FIXME: We don't use msg here.</span>
<span class="lineno"> 84 </span><span class="spaces"> </span><span class="nottickedoff">_msg &lt;- receiveData conn :: IO T.Text</span>
<span class="lineno"> 85 </span><span class="spaces"> </span><span class="nottickedoff">handler</span>
<span class="lineno"> 86 </span><span class="spaces"> </span><span class="nottickedoff">loop</span>
<span class="lineno"> 87 </span><span class="spaces"> </span><span class="nottickedoff">cleanup = do</span>
<span class="lineno"> 88 </span><span class="spaces"> </span><span class="nottickedoff">stop</span>
<span class="lineno"> 89 </span><span class="spaces"> </span><span class="nottickedoff">killSlave</span>
<span class="lineno"> 90 </span><span class="spaces"> </span><span class="nottickedoff">_ &lt;- swapMVar hasConnectionVar False</span>
<span class="lineno"> 91 </span><span class="spaces"> </span><span class="nottickedoff">return ()</span>
<span class="lineno"> 92 </span><span class="spaces"> </span><span class="nottickedoff">loop `finally` cleanup</span></span>
<span class="lineno"> 93 </span>
<span class="lineno"> 94 </span>ignoreErrors :: IO () -&gt; IO ()
<span class="lineno"> 95 </span><span class="decl"><span class="nottickedoff">ignoreErrors action = action `catch` \(_::SomeException) -&gt; return ()</span></span>
<span class="lineno"> 96 </span>
<span class="lineno"> 97 </span>openViewer :: IO ()
<span class="lineno"> 98 </span><span class="decl"><span class="nottickedoff">openViewer = do</span>
<span class="lineno"> 99 </span><span class="spaces"> </span><span class="nottickedoff">url &lt;- getDataFileName &quot;viewer-elm/dist/index.html&quot;</span>
<span class="lineno"> 100 </span><span class="spaces"> </span><span class="nottickedoff">logMsg &quot;Opening browser...&quot;</span>
<span class="lineno"> 101 </span><span class="spaces"> </span><span class="nottickedoff">bSucc &lt;- openBrowser url</span>
<span class="lineno"> 102 </span><span class="spaces"> </span><span class="nottickedoff">if bSucc</span>
<span class="lineno"> 103 </span><span class="spaces"> </span><span class="nottickedoff">then logMsg &quot;Browser opened.&quot;</span>
<span class="lineno"> 104 </span><span class="spaces"> </span><span class="nottickedoff">else hPutStrLn stderr $ &quot;Failed to open browser. Manually visit: &quot; ++ url</span></span>
<span class="lineno"> 105 </span>
<span class="lineno"> 106 </span>slaveHandler :: Bool -&gt; Maybe FilePath -&gt; [String] -&gt; Connection -&gt; GhciBackend
<span class="lineno"> 107 </span> -&gt; FilePath -&gt; FilePath -&gt; IO ()
<span class="lineno"> 108 </span><span class="decl"><span class="nottickedoff">slaveHandler verbose mbGHCPath extraGHCOpts conn ghci self svgDir =</span>
<span class="lineno"> 109 </span><span class="spaces"> </span><span class="nottickedoff">withCurrentDirectory (takeDirectory self) $</span>
<span class="lineno"> 110 </span><span class="spaces"> </span><span class="nottickedoff">withSystemTempDirectory &quot;reanimate&quot; $ \tmpDir -&gt;</span>
<span class="lineno"> 111 </span><span class="spaces"> </span><span class="nottickedoff">withTempFile tmpDir &quot;reanimate.exe&quot; $ \tmpExecutable handle -&gt; do</span>
<span class="lineno"> 112 </span><span class="spaces"> </span><span class="nottickedoff">outputFolder &lt;- createTempDirectory svgDir &quot;svgs&quot;</span>
<span class="lineno"> 113 </span><span class="spaces"> </span><span class="nottickedoff">let frameFileName frameIdx =</span>
<span class="lineno"> 114 </span><span class="spaces"> </span><span class="nottickedoff">outputFolder &lt;/&gt; show frameIdx &lt;.&gt; &quot;svg&quot;</span>
<span class="lineno"> 115 </span><span class="spaces"></span><span class="nottickedoff"></span>
<span class="lineno"> 116 </span><span class="spaces"> </span><span class="nottickedoff">sentFrameCount &lt;- newMVar False</span>
<span class="lineno"> 117 </span><span class="spaces"> </span><span class="nottickedoff">hClose handle</span>
<span class="lineno"> 118 </span><span class="spaces"> </span><span class="nottickedoff">lock &lt;- newMVar ()</span>
<span class="lineno"> 119 </span><span class="spaces"> </span><span class="nottickedoff">sendWebMessage conn $ WebStatus &quot;Compiling&quot;</span>
<span class="lineno"> 120 </span><span class="spaces"> </span><span class="nottickedoff">ghciThread &lt;- forkIO $ do</span>
<span class="lineno"> 121 </span><span class="spaces"> </span><span class="nottickedoff">firstFrame &lt;- newIORef True</span>
<span class="lineno"> 122 </span><span class="spaces"> </span><span class="nottickedoff">ghciReload ghci</span>
<span class="lineno"> 123 </span><span class="spaces"> </span><span class="nottickedoff">logMsg &quot;GHCi reload done.&quot;</span>
<span class="lineno"> 124 </span><span class="spaces"> </span><span class="nottickedoff">ghciGenerate ghci outputFolder $ \frameIdx -&gt; do</span>
<span class="lineno"> 125 </span><span class="spaces"> </span><span class="nottickedoff">first &lt;- readIORef firstFrame</span>
<span class="lineno"> 126 </span><span class="spaces"> </span><span class="nottickedoff">writeIORef firstFrame False</span>
<span class="lineno"> 127 </span><span class="spaces"> </span><span class="nottickedoff">if first</span>
<span class="lineno"> 128 </span><span class="spaces"> </span><span class="nottickedoff">then do</span>
<span class="lineno"> 129 </span><span class="spaces"> </span><span class="nottickedoff">modifyMVar_ sentFrameCount $ \sent -&gt; do</span>
<span class="lineno"> 130 </span><span class="spaces"> </span><span class="nottickedoff">unless sent $</span>
<span class="lineno"> 131 </span><span class="spaces"> </span><span class="nottickedoff">sendWebMessage conn $ WebFrameCount frameIdx</span>
<span class="lineno"> 132 </span><span class="spaces"> </span><span class="nottickedoff">logMsg &quot;Framecount sent.&quot;</span>
<span class="lineno"> 133 </span><span class="spaces"> </span><span class="nottickedoff">return True</span>
<span class="lineno"> 134 </span><span class="spaces"> </span><span class="nottickedoff">else</span>
<span class="lineno"> 135 </span><span class="spaces"> </span><span class="nottickedoff">withMVar lock $ \_ -&gt;</span>
<span class="lineno"> 136 </span><span class="spaces"> </span><span class="nottickedoff">sendWebMessage conn $ WebFrame frameIdx (frameFileName frameIdx)</span>
<span class="lineno"> 137 </span><span class="spaces"> </span><span class="nottickedoff">logMsg &quot;GHCi render done.&quot;</span>
<span class="lineno"> 138 </span><span class="spaces"> </span><span class="nottickedoff">ret &lt;- case mbGHCPath of</span>
<span class="lineno"> 139 </span><span class="spaces"> </span><span class="nottickedoff">Nothing -&gt; do</span>
<span class="lineno"> 140 </span><span class="spaces"> </span><span class="nottickedoff">let args = [&quot;ghc&quot;, &quot;--&quot;] ++ ghcOptions tmpDir ++ extraGHCOpts ++ [takeFileName self, &quot;-o&quot;, tmpExecutable]</span>
<span class="lineno"> 141 </span><span class="spaces"> </span><span class="nottickedoff">when verbose $</span>
<span class="lineno"> 142 </span><span class="spaces"> </span><span class="nottickedoff">logMsg $ &quot;Running: &quot; ++ showCommandForUser &quot;stack&quot; args</span>
<span class="lineno"> 143 </span><span class="spaces"> </span><span class="nottickedoff">runCmd_ &quot;stack&quot; args</span>
<span class="lineno"> 144 </span><span class="spaces"> </span><span class="nottickedoff">Just ghc -&gt; do</span>
<span class="lineno"> 145 </span><span class="spaces"> </span><span class="nottickedoff">let args = ghcOptions tmpDir ++ extraGHCOpts ++ [takeFileName self, &quot;-o&quot;, tmpExecutable]</span>
<span class="lineno"> 146 </span><span class="spaces"> </span><span class="nottickedoff">when verbose $</span>
<span class="lineno"> 147 </span><span class="spaces"> </span><span class="nottickedoff">logMsg $ &quot;Running: &quot; ++ showCommandForUser ghc args</span>
<span class="lineno"> 148 </span><span class="spaces"> </span><span class="nottickedoff">runCmd_ ghc args</span>
<span class="lineno"> 149 </span><span class="spaces"> </span><span class="nottickedoff">logMsg &quot;Compile done.&quot;</span>
<span class="lineno"> 150 </span><span class="spaces"> </span><span class="nottickedoff">case ret of</span>
<span class="lineno"> 151 </span><span class="spaces"> </span><span class="nottickedoff">Left err -&gt;</span>
<span class="lineno"> 152 </span><span class="spaces"> </span><span class="nottickedoff">sendWebMessage conn $ WebError $ unlines (lines err)</span>
<span class="lineno"> 153 </span><span class="spaces"> </span><span class="nottickedoff">Right{} -&gt; runCmdLazy tmpExecutable (execOpts outputFolder) $ \getFrame -&gt; do</span>
<span class="lineno"> 154 </span><span class="spaces"> </span><span class="nottickedoff">frameCount &lt;- expectFrame =&lt;&lt; getFrame</span>
<span class="lineno"> 155 </span><span class="spaces"> </span><span class="nottickedoff">modifyMVar_ sentFrameCount $ \sent -&gt; do</span>
<span class="lineno"> 156 </span><span class="spaces"> </span><span class="nottickedoff">unless sent $</span>
<span class="lineno"> 157 </span><span class="spaces"> </span><span class="nottickedoff">sendWebMessage conn $ WebFrameCount frameCount</span>
<span class="lineno"> 158 </span><span class="spaces"> </span><span class="nottickedoff">return True</span>
<span class="lineno"> 159 </span><span class="spaces"> </span><span class="nottickedoff">replicateM_ frameCount $ do</span>
<span class="lineno"> 160 </span><span class="spaces"> </span><span class="nottickedoff">frameIdx &lt;- expectFrame =&lt;&lt; getFrame</span>
<span class="lineno"> 161 </span><span class="spaces"> </span><span class="nottickedoff">withMVar lock $ \_ -&gt;</span>
<span class="lineno"> 162 </span><span class="spaces"> </span><span class="nottickedoff">sendWebMessage conn $ WebFrame frameIdx (frameFileName frameIdx)</span>
<span class="lineno"> 163 </span><span class="spaces"> </span><span class="nottickedoff">logMsg &quot;Optimized render done.&quot;</span>
<span class="lineno"> 164 </span><span class="spaces"> </span><span class="nottickedoff">killThread ghciThread</span>
<span class="lineno"> 165 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 166 </span><span class="spaces"> </span><span class="nottickedoff">execOpts output =</span>
<span class="lineno"> 167 </span><span class="spaces"> </span><span class="nottickedoff">[ &quot;raw&quot;, &quot;--output&quot;, output, &quot;--offset&quot;, &quot;1&quot;</span>
<span class="lineno"> 168 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;+RTS&quot;, &quot;-N&quot;, &quot;-M2G&quot;, &quot;-RTS&quot;]</span>
<span class="lineno"> 169 </span><span class="spaces"> </span><span class="nottickedoff">expectFrame :: Either String Text -&gt; IO Int</span>
<span class="lineno"> 170 </span><span class="spaces"> </span><span class="nottickedoff">expectFrame (Left &quot;&quot;) = do</span>
<span class="lineno"> 171 </span><span class="spaces"> </span><span class="nottickedoff">sendWebMessage conn $ WebStatus &quot;Done&quot;</span>
<span class="lineno"> 172 </span><span class="spaces"> </span><span class="nottickedoff">exitSuccess</span>
<span class="lineno"> 173 </span><span class="spaces"> </span><span class="nottickedoff">expectFrame (Left err) = do</span>
<span class="lineno"> 174 </span><span class="spaces"> </span><span class="nottickedoff">sendWebMessage conn $ WebError err</span>
<span class="lineno"> 175 </span><span class="spaces"> </span><span class="nottickedoff">exitWith (ExitFailure 1)</span>
<span class="lineno"> 176 </span><span class="spaces"> </span><span class="nottickedoff">expectFrame (Right frame) =</span>
<span class="lineno"> 177 </span><span class="spaces"> </span><span class="nottickedoff">case T.decimal frame of</span>
<span class="lineno"> 178 </span><span class="spaces"> </span><span class="nottickedoff">Left err -&gt; do</span>
<span class="lineno"> 179 </span><span class="spaces"> </span><span class="nottickedoff">hPutStrLn stderr (T.unpack frame)</span>
<span class="lineno"> 180 </span><span class="spaces"> </span><span class="nottickedoff">hPutStrLn stderr $ &quot;expectFrame: &quot; ++ err</span>
<span class="lineno"> 181 </span><span class="spaces"> </span><span class="nottickedoff">sendWebMessage conn $ WebError err</span>
<span class="lineno"> 182 </span><span class="spaces"> </span><span class="nottickedoff">exitWith (ExitFailure 1)</span>
<span class="lineno"> 183 </span><span class="spaces"> </span><span class="nottickedoff">Right (frameNumber, &quot;&quot;) -&gt;</span>
<span class="lineno"> 184 </span><span class="spaces"> </span><span class="nottickedoff">pure frameNumber</span>
<span class="lineno"> 185 </span><span class="spaces"> </span><span class="nottickedoff">Right {} -&gt; do</span>
<span class="lineno"> 186 </span><span class="spaces"> </span><span class="nottickedoff">let err = &quot;Unexpected output&quot;</span>
<span class="lineno"> 187 </span><span class="spaces"> </span><span class="nottickedoff">hPutStrLn stderr (T.unpack frame)</span>
<span class="lineno"> 188 </span><span class="spaces"> </span><span class="nottickedoff">hPutStrLn stderr $ &quot;expectFrame: &quot; ++ err</span>
<span class="lineno"> 189 </span><span class="spaces"> </span><span class="nottickedoff">sendWebMessage conn $ WebError err</span>
<span class="lineno"> 190 </span><span class="spaces"> </span><span class="nottickedoff">exitWith (ExitFailure 1)</span></span>
<span class="lineno"> 191 </span>
<span class="lineno"> 192 </span>watchFile :: WatchManager -&gt; FilePath -&gt; IO () -&gt; IO StopListening
<span class="lineno"> 193 </span><span class="decl"><span class="nottickedoff">watchFile watch file action = watchTree watch (takeDirectory file) check (const action)</span>
<span class="lineno"> 194 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 195 </span><span class="spaces"> </span><span class="nottickedoff">check event =</span>
<span class="lineno"> 196 </span><span class="spaces"> </span><span class="nottickedoff">takeFileName (eventPath event) == takeFileName file ||</span>
<span class="lineno"> 197 </span><span class="spaces"> </span><span class="nottickedoff">takeExtension (eventPath event) `elem` sourceExtensions ||</span>
<span class="lineno"> 198 </span><span class="spaces"> </span><span class="nottickedoff">takeExtension (eventPath event) `elem` dataExtensions</span>
<span class="lineno"> 199 </span><span class="spaces"> </span><span class="nottickedoff">sourceExtensions = [&quot;.hs&quot;, &quot;.lhs&quot;]</span>
<span class="lineno"> 200 </span><span class="spaces"> </span><span class="nottickedoff">dataExtensions = [&quot;.jpg&quot;, &quot;.png&quot;, &quot;.bmp&quot;, &quot;.pov&quot;, &quot;.tex&quot;, &quot;.csv&quot;]</span></span>
<span class="lineno"> 201 </span>
<span class="lineno"> 202 </span>ghcOptions :: FilePath -&gt; [String]
<span class="lineno"> 203 </span><span class="decl"><span class="nottickedoff">ghcOptions tmpDir =</span>
<span class="lineno"> 204 </span><span class="spaces"> </span><span class="nottickedoff">[&quot;-rtsopts&quot;, &quot;--make&quot;, &quot;-threaded&quot;, &quot;-O2&quot;] ++</span>
<span class="lineno"> 205 </span><span class="spaces"> </span><span class="nottickedoff">[&quot;-odir&quot;, tmpDir, &quot;-hidir&quot;, tmpDir]</span></span>
<span class="lineno"> 206 </span>
<span class="lineno"> 207 </span>-- FIXME: Move to a different module
<span class="lineno"> 208 </span>requireOwnSource :: IO FilePath
<span class="lineno"> 209 </span><span class="decl"><span class="nottickedoff">requireOwnSource = do</span>
<span class="lineno"> 210 </span><span class="spaces"> </span><span class="nottickedoff">mbSelf &lt;- findOwnSource</span>
<span class="lineno"> 211 </span><span class="spaces"> </span><span class="nottickedoff">case mbSelf of</span>
<span class="lineno"> 212 </span><span class="spaces"> </span><span class="nottickedoff">Nothing -&gt; do</span>
<span class="lineno"> 213 </span><span class="spaces"> </span><span class="nottickedoff">hPutStrLn stderr</span>
<span class="lineno"> 214 </span><span class="spaces"> </span><span class="nottickedoff">&quot;Rendering in browser window is only available when interpreting.\n\</span>
<span class="lineno"> 215 </span><span class="spaces"> </span><span class="nottickedoff">\To render a video file, use the 'render' command or run again with --help\n\</span>
<span class="lineno"> 216 </span><span class="spaces"> </span><span class="nottickedoff">\to see all available options.&quot;</span>
<span class="lineno"> 217 </span><span class="spaces"> </span><span class="nottickedoff">exitFailure</span>
<span class="lineno"> 218 </span><span class="spaces"> </span><span class="nottickedoff">Just self -&gt; pure self</span></span>
<span class="lineno"> 219 </span>
<span class="lineno"> 220 </span>findOwnSource :: IO (Maybe FilePath)
<span class="lineno"> 221 </span><span class="decl"><span class="nottickedoff">findOwnSource = do</span>
<span class="lineno"> 222 </span><span class="spaces"> </span><span class="nottickedoff">fullArgs &lt;- getFullArgs</span>
<span class="lineno"> 223 </span><span class="spaces"> </span><span class="nottickedoff">stackSource &lt;- makeAbsolute (last fullArgs)</span>
<span class="lineno"> 224 </span><span class="spaces"> </span><span class="nottickedoff">exist &lt;- doesFileExist stackSource</span>
<span class="lineno"> 225 </span><span class="spaces"> </span><span class="nottickedoff">if exist &amp;&amp; isHaskellFile stackSource</span>
<span class="lineno"> 226 </span><span class="spaces"> </span><span class="nottickedoff">then return (Just stackSource)</span>
<span class="lineno"> 227 </span><span class="spaces"> </span><span class="nottickedoff">else do</span>
<span class="lineno"> 228 </span><span class="spaces"> </span><span class="nottickedoff">prog &lt;- getProgName</span>
<span class="lineno"> 229 </span><span class="spaces"> </span><span class="nottickedoff">let hsProg</span>
<span class="lineno"> 230 </span><span class="spaces"> </span><span class="nottickedoff">| isHaskellFile prog = prog</span>
<span class="lineno"> 231 </span><span class="spaces"> </span><span class="nottickedoff">| otherwise = replaceExtension prog &quot;hs&quot;</span>
<span class="lineno"> 232 </span><span class="spaces"> </span><span class="nottickedoff">lst &lt;- listDirectory &quot;.&quot;</span>
<span class="lineno"> 233 </span><span class="spaces"> </span><span class="nottickedoff">findFile (&quot;.&quot; : lst) hsProg</span></span>
<span class="lineno"> 234 </span>
<span class="lineno"> 235 </span>isHaskellFile :: FilePath -&gt; Bool
<span class="lineno"> 236 </span><span class="decl"><span class="nottickedoff">isHaskellFile path = takeExtension path `elem` [&quot;.hs&quot;, &quot;.lhs&quot;]</span></span>
<span class="lineno"> 237 </span>
<span class="lineno"> 238 </span>logMsg :: String -&gt; IO ()
<span class="lineno"> 239 </span><span class="decl"><span class="nottickedoff">logMsg msg = do</span>
<span class="lineno"> 240 </span><span class="spaces"> </span><span class="nottickedoff">now &lt;- getCurrentTime</span>
<span class="lineno"> 241 </span><span class="spaces"> </span><span class="nottickedoff">putStrLn $ formatTime defaultTimeLocale fmt now ++ &quot;: &quot; ++ msg</span>
<span class="lineno"> 242 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 243 </span><span class="spaces"> </span><span class="nottickedoff">fmt = &quot;%F %T%2Q&quot;</span></span>
<span class="lineno"> 244 </span>
<span class="lineno"> 245 </span>-------------------------------------------------------------------------------
<span class="lineno"> 246 </span>-- Ghci interface
<span class="lineno"> 247 </span>
<span class="lineno"> 248 </span>-- stack
<span class="lineno"> 249 </span>-- cabal
<span class="lineno"> 250 </span>-- raw
<span class="lineno"> 251 </span>-- none?
<span class="lineno"> 252 </span>data GhciBackend = GhciBackend (MVar Ghci)
<span class="lineno"> 253 </span>
<span class="lineno"> 254 </span>ghciBackend :: Maybe FilePath -&gt; FilePath -&gt; IO GhciBackend
<span class="lineno"> 255 </span><span class="decl"><span class="nottickedoff">ghciBackend mbGHCPath self = do</span>
<span class="lineno"> 256 </span><span class="spaces"> </span><span class="nottickedoff">let ghciProc =</span>
<span class="lineno"> 257 </span><span class="spaces"> </span><span class="nottickedoff">case mbGHCPath of</span>
<span class="lineno"> 258 </span><span class="spaces"> </span><span class="nottickedoff">Just ghcPath -&gt;</span>
<span class="lineno"> 259 </span><span class="spaces"> </span><span class="nottickedoff">proc ghcPath $ [&quot;--interactive&quot;, &quot;+RTS&quot;] ++ words memoryLimit ++ [&quot;-RTS&quot;]</span>
<span class="lineno"> 260 </span><span class="spaces"> </span><span class="nottickedoff">Nothing -&gt;</span>
<span class="lineno"> 261 </span><span class="spaces"> </span><span class="nottickedoff">proc &quot;stack&quot; [&quot;exec&quot;, &quot;ghci&quot;, &quot;--rts-options=&quot;++memoryLimit]</span>
<span class="lineno"> 262 </span><span class="spaces"> </span><span class="nottickedoff">(ghci, _loads) &lt;- startGhciProcess ghciProc $ \_stream _msg -&gt; return ()</span>
<span class="lineno"> 263 </span><span class="spaces"> </span><span class="nottickedoff">void $ exec ghci $ &quot;:load &quot; ++ self</span>
<span class="lineno"> 264 </span><span class="spaces"> </span><span class="nottickedoff">ref &lt;- newMVar ghci</span>
<span class="lineno"> 265 </span><span class="spaces"> </span><span class="nottickedoff">return $ GhciBackend ref</span></span>
<span class="lineno"> 266 </span>
<span class="lineno"> 267 </span>ghciReload :: GhciBackend -&gt; IO ()
<span class="lineno"> 268 </span><span class="decl"><span class="nottickedoff">ghciReload (GhciBackend ref) =</span>
<span class="lineno"> 269 </span><span class="spaces"> </span><span class="nottickedoff">withMVar ref $ \ghci -&gt;</span>
<span class="lineno"> 270 </span><span class="spaces"> </span><span class="nottickedoff">void $ reload ghci</span></span>
<span class="lineno"> 271 </span>
<span class="lineno"> 272 </span>ghciGenerate :: GhciBackend -&gt; FilePath -&gt; (Int -&gt; IO ()) -&gt; IO ()
<span class="lineno"> 273 </span><span class="decl"><span class="nottickedoff">ghciGenerate (GhciBackend ref) target cb = withMVar ref $ \ghci -&gt; do</span>
<span class="lineno"> 274 </span><span class="spaces"> </span><span class="nottickedoff">execStream ghci (&quot;:main raw --output=&quot; ++ target ++ &quot; --offset=1&quot;)</span>
<span class="lineno"> 275 </span><span class="spaces"> </span><span class="nottickedoff">$ \_ msg -&gt;</span>
<span class="lineno"> 276 </span><span class="spaces"> </span><span class="nottickedoff">case reads msg of</span>
<span class="lineno"> 277 </span><span class="spaces"> </span><span class="nottickedoff">[(frameIdx,&quot;&quot;)] -&gt; cb frameIdx</span>
<span class="lineno"> 278 </span><span class="spaces"> </span><span class="nottickedoff">_ -&gt; return ()</span></span>
<span class="lineno"> 279 </span>
<span class="lineno"> 280 </span>memoryLimit :: String
<span class="lineno"> 281 </span><span class="decl"><span class="nottickedoff">memoryLimit = &quot;-M1G&quot;</span></span>
<span class="lineno"> 282 </span>
<span class="lineno"> 283 </span>-------------------------------------------------------------------------------
<span class="lineno"> 284 </span>-- Websocket API
<span class="lineno"> 285 </span>
<span class="lineno"> 286 </span>data WebMessage
<span class="lineno"> 287 </span> = WebStatus String
<span class="lineno"> 288 </span> | WebError String
<span class="lineno"> 289 </span> | WebFrameCount Int
<span class="lineno"> 290 </span> | WebFrame Int FilePath
<span class="lineno"> 291 </span>
<span class="lineno"> 292 </span>sendWebMessage :: Connection -&gt; WebMessage -&gt; IO ()
<span class="lineno"> 293 </span><span class="decl"><span class="nottickedoff">sendWebMessage conn msg = sendTextData conn $</span>
<span class="lineno"> 294 </span><span class="spaces"> </span><span class="nottickedoff">case msg of</span>
<span class="lineno"> 295 </span><span class="spaces"> </span><span class="nottickedoff">WebStatus txt -&gt; T.pack &quot;status\n&quot; &lt;&gt; T.pack txt</span>
<span class="lineno"> 296 </span><span class="spaces"> </span><span class="nottickedoff">WebError txt -&gt; T.pack &quot;error\n&quot; &lt;&gt; T.pack txt</span>
<span class="lineno"> 297 </span><span class="spaces"> </span><span class="nottickedoff">WebFrameCount n -&gt; T.pack $ &quot;frame_count\n&quot; ++ show n</span>
<span class="lineno"> 298 </span><span class="spaces"> </span><span class="nottickedoff">WebFrame n path -&gt; T.pack $ &quot;frame\n&quot; ++ show n ++ &quot;\n&quot; ++ path</span></span>
</pre>
</body>
</html>

View file

@ -0,0 +1,246 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style type="text/css">
span.lineno { color: white; background: #aaaaaa; border-right: solid white 12px }
span.nottickedoff { background: yellow}
span.istickedoff { background: white }
span.tickonlyfalse { margin: -1px; border: 1px solid #f20913; background: #f20913 }
span.tickonlytrue { margin: -1px; border: 1px solid #60de51; background: #60de51 }
span.funcount { font-size: small; color: orange; z-index: 2; position: absolute; right: 20 }
span.decl { font-weight: bold }
span.spaces { background: white }
</style>
</head>
<body>
<pre>
<span class="decl"><span class="nottickedoff">never executed</span> <span class="tickonlytrue">always true</span> <span class="tickonlyfalse">always false</span></span>
</pre>
<pre>
<span class="lineno"> 1 </span>{-# LANGUAGE MultiWayIf #-}
<span class="lineno"> 2 </span>{-# LANGUAGE RecordWildCards #-}
<span class="lineno"> 3 </span>module Reanimate.Driver
<span class="lineno"> 4 </span> ( reanimate
<span class="lineno"> 5 </span> )
<span class="lineno"> 6 </span>where
<span class="lineno"> 7 </span>
<span class="lineno"> 8 </span>import Control.Applicative ((&lt;|&gt;))
<span class="lineno"> 9 </span>import Control.Monad
<span class="lineno"> 10 </span>import Data.Maybe
<span class="lineno"> 11 </span>import Data.Either
<span class="lineno"> 12 </span>import Reanimate.Animation (Animation)
<span class="lineno"> 13 </span>import Reanimate.Driver.Check
<span class="lineno"> 14 </span>import Reanimate.Driver.CLI
<span class="lineno"> 15 </span>import Reanimate.Driver.Compile
<span class="lineno"> 16 </span>import Reanimate.Driver.Server
<span class="lineno"> 17 </span>import Reanimate.Parameters
<span class="lineno"> 18 </span>import Reanimate.Render (render, renderSnippets, renderSvgs,
<span class="lineno"> 19 </span> selectRaster)
<span class="lineno"> 20 </span>import System.Directory
<span class="lineno"> 21 </span>import System.Exit
<span class="lineno"> 22 </span>import System.FilePath
<span class="lineno"> 23 </span>import System.IO
<span class="lineno"> 24 </span>import Text.Printf
<span class="lineno"> 25 </span>
<span class="lineno"> 26 </span>presetFormat :: Preset -&gt; Format
<span class="lineno"> 27 </span><span class="decl"><span class="nottickedoff">presetFormat Youtube = RenderMp4</span>
<span class="lineno"> 28 </span><span class="spaces"></span><span class="nottickedoff">presetFormat ExampleGif = RenderGif</span>
<span class="lineno"> 29 </span><span class="spaces"></span><span class="nottickedoff">presetFormat Quick = RenderMp4</span>
<span class="lineno"> 30 </span><span class="spaces"></span><span class="nottickedoff">presetFormat MediumQ = RenderMp4</span>
<span class="lineno"> 31 </span><span class="spaces"></span><span class="nottickedoff">presetFormat HighQ = RenderMp4</span>
<span class="lineno"> 32 </span><span class="spaces"></span><span class="nottickedoff">presetFormat LowFPS = RenderMp4</span></span>
<span class="lineno"> 33 </span>
<span class="lineno"> 34 </span>presetFPS :: Preset -&gt; FPS
<span class="lineno"> 35 </span><span class="decl"><span class="nottickedoff">presetFPS Youtube = 60</span>
<span class="lineno"> 36 </span><span class="spaces"></span><span class="nottickedoff">presetFPS ExampleGif = 25</span>
<span class="lineno"> 37 </span><span class="spaces"></span><span class="nottickedoff">presetFPS Quick = 15</span>
<span class="lineno"> 38 </span><span class="spaces"></span><span class="nottickedoff">presetFPS MediumQ = 30</span>
<span class="lineno"> 39 </span><span class="spaces"></span><span class="nottickedoff">presetFPS HighQ = 30</span>
<span class="lineno"> 40 </span><span class="spaces"></span><span class="nottickedoff">presetFPS LowFPS = 10</span></span>
<span class="lineno"> 41 </span>
<span class="lineno"> 42 </span>presetWidth :: Preset -&gt; Width
<span class="lineno"> 43 </span><span class="decl"><span class="nottickedoff">presetWidth Youtube = 2560</span>
<span class="lineno"> 44 </span><span class="spaces"></span><span class="nottickedoff">presetWidth ExampleGif = 320</span>
<span class="lineno"> 45 </span><span class="spaces"></span><span class="nottickedoff">presetWidth Quick = 320</span>
<span class="lineno"> 46 </span><span class="spaces"></span><span class="nottickedoff">presetWidth MediumQ = 800</span>
<span class="lineno"> 47 </span><span class="spaces"></span><span class="nottickedoff">presetWidth HighQ = 1920</span>
<span class="lineno"> 48 </span><span class="spaces"></span><span class="nottickedoff">presetWidth LowFPS = presetWidth HighQ</span></span>
<span class="lineno"> 49 </span>
<span class="lineno"> 50 </span>presetHeight :: Preset -&gt; Height
<span class="lineno"> 51 </span><span class="decl"><span class="nottickedoff">presetHeight preset = presetWidth preset * 9 `div` 16</span></span>
<span class="lineno"> 52 </span>
<span class="lineno"> 53 </span>formatFPS :: Format -&gt; FPS
<span class="lineno"> 54 </span><span class="decl"><span class="nottickedoff">formatFPS RenderMp4 = 60</span>
<span class="lineno"> 55 </span><span class="spaces"></span><span class="nottickedoff">formatFPS RenderGif = 25</span>
<span class="lineno"> 56 </span><span class="spaces"></span><span class="nottickedoff">formatFPS RenderWebm = 60</span></span>
<span class="lineno"> 57 </span>
<span class="lineno"> 58 </span>formatWidth :: Format -&gt; Width
<span class="lineno"> 59 </span><span class="decl"><span class="nottickedoff">formatWidth RenderMp4 = 2560</span>
<span class="lineno"> 60 </span><span class="spaces"></span><span class="nottickedoff">formatWidth RenderGif = 320</span>
<span class="lineno"> 61 </span><span class="spaces"></span><span class="nottickedoff">formatWidth RenderWebm = 2560</span></span>
<span class="lineno"> 62 </span>
<span class="lineno"> 63 </span>formatHeight :: Format -&gt; Height
<span class="lineno"> 64 </span><span class="decl"><span class="nottickedoff">formatHeight RenderMp4 = 1440</span>
<span class="lineno"> 65 </span><span class="spaces"></span><span class="nottickedoff">formatHeight RenderGif = 180</span>
<span class="lineno"> 66 </span><span class="spaces"></span><span class="nottickedoff">formatHeight RenderWebm = 1440</span></span>
<span class="lineno"> 67 </span>
<span class="lineno"> 68 </span>formatExtension :: Format -&gt; String
<span class="lineno"> 69 </span><span class="decl"><span class="nottickedoff">formatExtension RenderMp4 = &quot;mp4&quot;</span>
<span class="lineno"> 70 </span><span class="spaces"></span><span class="nottickedoff">formatExtension RenderGif = &quot;gif&quot;</span>
<span class="lineno"> 71 </span><span class="spaces"></span><span class="nottickedoff">formatExtension RenderWebm = &quot;webm&quot;</span></span>
<span class="lineno"> 72 </span>
<span class="lineno"> 73 </span>{-|
<span class="lineno"> 74 </span>Main entry-point for accessing an animation. Creates a program that takes the
<span class="lineno"> 75 </span>following command-line arguments:
<span class="lineno"> 76 </span>
<span class="lineno"> 77 </span>&gt; Usage: PROG [COMMAND]
<span class="lineno"> 78 </span>&gt; This program contains an animation which can either be viewed in a web-browser
<span class="lineno"> 79 </span>&gt; or rendered to disk.
<span class="lineno"> 80 </span>&gt;
<span class="lineno"> 81 </span>&gt; Available options:
<span class="lineno"> 82 </span>&gt; -h,--help Show this help text
<span class="lineno"> 83 </span>&gt;
<span class="lineno"> 84 </span>&gt; Available commands:
<span class="lineno"> 85 </span>&gt; check Run a system's diagnostic and report any missing
<span class="lineno"> 86 </span>&gt; external dependencies.
<span class="lineno"> 87 </span>&gt; view Play animation in browser window.
<span class="lineno"> 88 </span>&gt; render Render animation to file.
<span class="lineno"> 89 </span>
<span class="lineno"> 90 </span>Neither the 'check' nor the 'view' command take any additional arguments.
<span class="lineno"> 91 </span>Rendering animation can be controlled with these arguments:
<span class="lineno"> 92 </span>
<span class="lineno"> 93 </span>&gt; Usage: PROG render [-o|--target FILE] [--fps FPS] [-w|--width PIXELS]
<span class="lineno"> 94 </span>&gt; [-h|--height PIXELS] [--compile] [--format FMT]
<span class="lineno"> 95 </span>&gt; [--preset TYPE]
<span class="lineno"> 96 </span>&gt; Render animation to file.
<span class="lineno"> 97 </span>&gt;
<span class="lineno"> 98 </span>&gt; Available options:
<span class="lineno"> 99 </span>&gt; -o,--target FILE Write output to FILE
<span class="lineno"> 100 </span>&gt; --fps FPS Set frames per second.
<span class="lineno"> 101 </span>&gt; -w,--width PIXELS Set video width.
<span class="lineno"> 102 </span>&gt; -h,--height PIXELS Set video height.
<span class="lineno"> 103 </span>&gt; --compile Compile source code before rendering.
<span class="lineno"> 104 </span>&gt; --format FMT Video format: mp4, gif, webm
<span class="lineno"> 105 </span>&gt; --preset TYPE Parameter presets: youtube, gif, quick
<span class="lineno"> 106 </span>&gt; -h,--help Show this help text
<span class="lineno"> 107 </span>-}
<span class="lineno"> 108 </span>reanimate :: Animation -&gt; IO ()
<span class="lineno"> 109 </span><span class="decl"><span class="istickedoff">reanimate animation = do</span>
<span class="lineno"> 110 </span><span class="spaces"> </span><span class="istickedoff">Options {..} &lt;- getDriverOptions</span>
<span class="lineno"> 111 </span><span class="spaces"> </span><span class="istickedoff">case optsCommand of</span>
<span class="lineno"> 112 </span><span class="spaces"> </span><span class="istickedoff">Raw {..} -&gt; <span class="nottickedoff">do</span></span>
<span class="lineno"> 113 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">setFPS 60</span></span>
<span class="lineno"> 114 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">renderSvgs rawOutputFolder rawFrameOffset rawPrettyPrint animation</span></span>
<span class="lineno"> 115 </span><span class="spaces"> </span><span class="istickedoff">Test -&gt; do</span>
<span class="lineno"> 116 </span><span class="spaces"> </span><span class="istickedoff">setNoExternals <span class="nottickedoff">True</span></span>
<span class="lineno"> 117 </span><span class="spaces"> </span><span class="istickedoff">-- hSetBinaryMode stdout True</span>
<span class="lineno"> 118 </span><span class="spaces"> </span><span class="istickedoff">renderSnippets animation</span>
<span class="lineno"> 119 </span><span class="spaces"> </span><span class="istickedoff">Check -&gt; <span class="nottickedoff">checkEnvironment</span></span>
<span class="lineno"> 120 </span><span class="spaces"> </span><span class="istickedoff">View {..} -&gt; <span class="nottickedoff">serve viewVerbose viewGHCPath viewGHCOpts viewOrigin</span></span>
<span class="lineno"> 121 </span><span class="spaces"> </span><span class="istickedoff">Render {..} -&gt; <span class="nottickedoff">do</span></span>
<span class="lineno"> 122 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">let fmt =</span></span>
<span class="lineno"> 123 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">guessParameter renderFormat (fmap presetFormat renderPreset)</span></span>
<span class="lineno"> 124 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">$ case renderTarget of</span></span>
<span class="lineno"> 125 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">-- Format guessed from output</span></span>
<span class="lineno"> 126 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">Just target -&gt; case takeExtension target of</span></span>
<span class="lineno"> 127 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">&quot;.mp4&quot; -&gt; RenderMp4</span></span>
<span class="lineno"> 128 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">&quot;.gif&quot; -&gt; RenderGif</span></span>
<span class="lineno"> 129 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">&quot;.webm&quot; -&gt; RenderWebm</span></span>
<span class="lineno"> 130 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">_ -&gt; RenderMp4</span></span>
<span class="lineno"> 131 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">-- Default to mp4 rendering.</span></span>
<span class="lineno"> 132 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">Nothing -&gt; RenderMp4</span></span>
<span class="lineno"> 133 </span><span class="spaces"></span><span class="istickedoff"><span class="nottickedoff"></span></span>
<span class="lineno"> 134 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">target &lt;- case renderTarget of</span></span>
<span class="lineno"> 135 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">Nothing -&gt; do</span></span>
<span class="lineno"> 136 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">mbSelf &lt;- findOwnSource</span></span>
<span class="lineno"> 137 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">let ext = formatExtension fmt</span></span>
<span class="lineno"> 138 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">self = fromMaybe &quot;output&quot; mbSelf</span></span>
<span class="lineno"> 139 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">pure $ replaceExtension self ext</span></span>
<span class="lineno"> 140 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">Just target -&gt; makeAbsolute target</span></span>
<span class="lineno"> 141 </span><span class="spaces"></span><span class="istickedoff"><span class="nottickedoff"></span></span>
<span class="lineno"> 142 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">let</span></span>
<span class="lineno"> 143 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">fps =</span></span>
<span class="lineno"> 144 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">guessParameter renderFPS (fmap presetFPS renderPreset) $ formatFPS fmt</span></span>
<span class="lineno"> 145 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">(width, height) = fromMaybe</span></span>
<span class="lineno"> 146 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">( maybe (formatWidth fmt) presetWidth renderPreset</span></span>
<span class="lineno"> 147 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">, maybe (formatHeight fmt) presetHeight renderPreset</span></span>
<span class="lineno"> 148 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">)</span></span>
<span class="lineno"> 149 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">(userPreferredDimensions renderWidth renderHeight)</span></span>
<span class="lineno"> 150 </span><span class="spaces"></span><span class="istickedoff"><span class="nottickedoff"></span></span>
<span class="lineno"> 151 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">raster &lt;-</span></span>
<span class="lineno"> 152 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">if renderRaster == RasterNone || renderRaster == RasterAuto then do</span></span>
<span class="lineno"> 153 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">svgSupport &lt;- hasFFmpegRSvg</span></span>
<span class="lineno"> 154 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">if isRight svgSupport</span></span>
<span class="lineno"> 155 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">then selectRaster renderRaster</span></span>
<span class="lineno"> 156 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">else do</span></span>
<span class="lineno"> 157 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">raster &lt;- selectRaster RasterAuto</span></span>
<span class="lineno"> 158 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">when (raster == RasterNone) $ do</span></span>
<span class="lineno"> 159 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">hPutStrLn stderr $</span></span>
<span class="lineno"> 160 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">&quot;Error: your FFmpeg was built without SVG support and no raster engines \</span></span>
<span class="lineno"> 161 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">\are available. Please install either inkscape, imagemagick, or rsvg.&quot;</span></span>
<span class="lineno"> 162 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">exitWith (ExitFailure 1)</span></span>
<span class="lineno"> 163 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">return raster</span></span>
<span class="lineno"> 164 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">else selectRaster renderRaster</span></span>
<span class="lineno"> 165 </span><span class="spaces"></span><span class="istickedoff"><span class="nottickedoff"></span></span>
<span class="lineno"> 166 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">if renderCompile</span></span>
<span class="lineno"> 167 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">then compile $</span></span>
<span class="lineno"> 168 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">[ &quot;render&quot;</span></span>
<span class="lineno"> 169 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">, &quot;--fps&quot;</span></span>
<span class="lineno"> 170 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">, show fps</span></span>
<span class="lineno"> 171 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">, &quot;--width&quot;</span></span>
<span class="lineno"> 172 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">, show width</span></span>
<span class="lineno"> 173 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">, &quot;--height&quot;</span></span>
<span class="lineno"> 174 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">, show height</span></span>
<span class="lineno"> 175 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">, &quot;--format&quot;</span></span>
<span class="lineno"> 176 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">, showFormat fmt</span></span>
<span class="lineno"> 177 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">, &quot;--raster&quot;</span></span>
<span class="lineno"> 178 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">, showRaster raster</span></span>
<span class="lineno"> 179 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">, &quot;--target&quot;</span></span>
<span class="lineno"> 180 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">, target</span></span>
<span class="lineno"> 181 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">, &quot;+RTS&quot;</span></span>
<span class="lineno"> 182 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">, &quot;-N&quot;</span></span>
<span class="lineno"> 183 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">, &quot;-RTS&quot;</span></span>
<span class="lineno"> 184 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">] ++ [ &quot;--partial&quot; | renderPartial ]</span></span>
<span class="lineno"> 185 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">else do</span></span>
<span class="lineno"> 186 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">setRaster raster</span></span>
<span class="lineno"> 187 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">setFPS fps</span></span>
<span class="lineno"> 188 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">setWidth width</span></span>
<span class="lineno"> 189 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">setHeight height</span></span>
<span class="lineno"> 190 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">printf</span></span>
<span class="lineno"> 191 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">&quot;Animation options:\n\</span></span>
<span class="lineno"> 192 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">\ fps: %d\n\</span></span>
<span class="lineno"> 193 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">\ width: %d\n\</span></span>
<span class="lineno"> 194 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">\ height: %d\n\</span></span>
<span class="lineno"> 195 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">\ fmt: %s\n\</span></span>
<span class="lineno"> 196 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">\ target: %s\n\</span></span>
<span class="lineno"> 197 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">\ raster: %s\n&quot;</span></span>
<span class="lineno"> 198 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">fps</span></span>
<span class="lineno"> 199 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">width</span></span>
<span class="lineno"> 200 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">height</span></span>
<span class="lineno"> 201 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">(showFormat fmt)</span></span>
<span class="lineno"> 202 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">target</span></span>
<span class="lineno"> 203 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">(show raster)</span></span>
<span class="lineno"> 204 </span><span class="spaces"></span><span class="istickedoff"><span class="nottickedoff"></span></span>
<span class="lineno"> 205 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">render animation target raster fmt width height fps renderPartial</span></span></span>
<span class="lineno"> 206 </span>
<span class="lineno"> 207 </span>guessParameter :: Maybe a -&gt; Maybe a -&gt; a -&gt; a
<span class="lineno"> 208 </span><span class="decl"><span class="nottickedoff">guessParameter a b def = fromMaybe def (a &lt;|&gt; b)</span></span>
<span class="lineno"> 209 </span>
<span class="lineno"> 210 </span>
<span class="lineno"> 211 </span>-- If user specifies exactly one dimension explicitly, calculate the other
<span class="lineno"> 212 </span>userPreferredDimensions :: Maybe Width -&gt; Maybe Height -&gt; Maybe (Width, Height)
<span class="lineno"> 213 </span><span class="decl"><span class="nottickedoff">userPreferredDimensions (Just width) (Just height) = Just (width, height)</span>
<span class="lineno"> 214 </span><span class="spaces"></span><span class="nottickedoff">userPreferredDimensions (Just width) Nothing =</span>
<span class="lineno"> 215 </span><span class="spaces"> </span><span class="nottickedoff">Just (width, makeEven $ width * 9 `div` 16)</span>
<span class="lineno"> 216 </span><span class="spaces"></span><span class="nottickedoff">userPreferredDimensions Nothing (Just height) =</span>
<span class="lineno"> 217 </span><span class="spaces"> </span><span class="nottickedoff">Just (makeEven $ height * 16 `div` 9, height)</span>
<span class="lineno"> 218 </span><span class="spaces"></span><span class="nottickedoff">userPreferredDimensions Nothing Nothing = Nothing</span></span>
<span class="lineno"> 219 </span>
<span class="lineno"> 220 </span>-- Avoid ffmpeg failures &quot;height not divisible by 2&quot;
<span class="lineno"> 221 </span>makeEven :: Int -&gt; Int
<span class="lineno"> 222 </span><span class="decl"><span class="nottickedoff">makeEven x | even x = x</span>
<span class="lineno"> 223 </span><span class="spaces"> </span><span class="nottickedoff">| otherwise = x - 1</span></span>
</pre>
</body>
</html>

View file

@ -0,0 +1,130 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style type="text/css">
span.lineno { color: white; background: #aaaaaa; border-right: solid white 12px }
span.nottickedoff { background: yellow}
span.istickedoff { background: white }
span.tickonlyfalse { margin: -1px; border: 1px solid #f20913; background: #f20913 }
span.tickonlytrue { margin: -1px; border: 1px solid #60de51; background: #60de51 }
span.funcount { font-size: small; color: orange; z-index: 2; position: absolute; right: 20 }
span.decl { font-weight: bold }
span.spaces { background: white }
</style>
</head>
<body>
<pre>
<span class="decl"><span class="nottickedoff">never executed</span> <span class="tickonlytrue">always true</span> <span class="tickonlyfalse">always false</span></span>
</pre>
<pre>
<span class="lineno"> 1 </span>module Reanimate.Ease
<span class="lineno"> 2 </span> ( Signal
<span class="lineno"> 3 </span> , constantS
<span class="lineno"> 4 </span> , fromToS
<span class="lineno"> 5 </span> , reverseS
<span class="lineno"> 6 </span> , curveS
<span class="lineno"> 7 </span> , powerS
<span class="lineno"> 8 </span> , bellS
<span class="lineno"> 9 </span> , oscillateS
<span class="lineno"> 10 </span> , fromListS
<span class="lineno"> 11 </span> , cubicBezierS
<span class="lineno"> 12 </span> ) where
<span class="lineno"> 13 </span>
<span class="lineno"> 14 </span>-- | Signals are time-varying variables. Signals can be composed using function
<span class="lineno"> 15 </span>-- composition.
<span class="lineno"> 16 </span>type Signal = Double -&gt; Double
<span class="lineno"> 17 </span>
<span class="lineno"> 18 </span>fromListS :: [(Double, Signal)] -&gt; Signal
<span class="lineno"> 19 </span><span class="decl"><span class="nottickedoff">fromListS fns t = worker 0 fns</span>
<span class="lineno"> 20 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 21 </span><span class="spaces"> </span><span class="nottickedoff">worker _ [] = 0</span>
<span class="lineno"> 22 </span><span class="spaces"> </span><span class="nottickedoff">worker now [(len, fn)] = fn (min 1 ((t-now) / min (1-now) len))</span>
<span class="lineno"> 23 </span><span class="spaces"> </span><span class="nottickedoff">worker now ((len, fn):rest)</span>
<span class="lineno"> 24 </span><span class="spaces"> </span><span class="nottickedoff">| now+len &lt; t = worker (now+len) rest</span>
<span class="lineno"> 25 </span><span class="spaces"> </span><span class="nottickedoff">| otherwise = fn ((t-now) / len)</span></span>
<span class="lineno"> 26 </span>
<span class="lineno"> 27 </span>-- | Constant signal.
<span class="lineno"> 28 </span>--
<span class="lineno"> 29 </span>-- Example:
<span class="lineno"> 30 </span>--
<span class="lineno"> 31 </span>-- &gt; signalA (constantS 0.5) drawProgress
<span class="lineno"> 32 </span>--
<span class="lineno"> 33 </span>-- &lt;&lt;docs/gifs/doc_constantS.gif&gt;&gt;
<span class="lineno"> 34 </span>constantS :: Double -&gt; Signal
<span class="lineno"> 35 </span><span class="decl"><span class="nottickedoff">constantS = const</span></span>
<span class="lineno"> 36 </span>
<span class="lineno"> 37 </span>-- | Signal with new starting and end values.
<span class="lineno"> 38 </span>--
<span class="lineno"> 39 </span>-- Example:
<span class="lineno"> 40 </span>--
<span class="lineno"> 41 </span>-- &gt; signalA (fromToS 0.8 0.2) drawProgress
<span class="lineno"> 42 </span>--
<span class="lineno"> 43 </span>-- &lt;&lt;docs/gifs/doc_fromToS.gif&gt;&gt;
<span class="lineno"> 44 </span>fromToS :: Double -&gt; Double -&gt; Signal
<span class="lineno"> 45 </span><span class="decl"><span class="nottickedoff">fromToS from to t = from + (to-from)*t</span></span>
<span class="lineno"> 46 </span>
<span class="lineno"> 47 </span>-- | Reverse signal order.
<span class="lineno"> 48 </span>--
<span class="lineno"> 49 </span>-- Example:
<span class="lineno"> 50 </span>--
<span class="lineno"> 51 </span>-- &gt; signalA reverseS drawProgress
<span class="lineno"> 52 </span>--
<span class="lineno"> 53 </span>-- &lt;&lt;docs/gifs/doc_reverseS.gif&gt;&gt;
<span class="lineno"> 54 </span>reverseS :: Signal
<span class="lineno"> 55 </span><span class="decl"><span class="nottickedoff">reverseS t = 1-t</span></span>
<span class="lineno"> 56 </span>
<span class="lineno"> 57 </span>-- | S-curve signal. Takes a steepness parameter. 2 is a good default.
<span class="lineno"> 58 </span>--
<span class="lineno"> 59 </span>-- Example:
<span class="lineno"> 60 </span>--
<span class="lineno"> 61 </span>-- &gt; signalA (curveS 2) drawProgress
<span class="lineno"> 62 </span>--
<span class="lineno"> 63 </span>-- &lt;&lt;docs/gifs/doc_curveS.gif&gt;&gt;
<span class="lineno"> 64 </span>curveS :: Double -&gt; Signal
<span class="lineno"> 65 </span><span class="decl"><span class="nottickedoff">curveS steepness s =</span>
<span class="lineno"> 66 </span><span class="spaces"> </span><span class="nottickedoff">if s &lt; 0.5</span>
<span class="lineno"> 67 </span><span class="spaces"> </span><span class="nottickedoff">then 0.5 * (2*s)**steepness</span>
<span class="lineno"> 68 </span><span class="spaces"> </span><span class="nottickedoff">else 1-0.5 * (2 - 2*s)**steepness</span></span>
<span class="lineno"> 69 </span>
<span class="lineno"> 70 </span>powerS :: Double -&gt; Signal
<span class="lineno"> 71 </span><span class="decl"><span class="nottickedoff">powerS steepness s = s**steepness</span></span>
<span class="lineno"> 72 </span>
<span class="lineno"> 73 </span>-- | Oscillate signal.
<span class="lineno"> 74 </span>--
<span class="lineno"> 75 </span>-- Example:
<span class="lineno"> 76 </span>--
<span class="lineno"> 77 </span>-- &gt; signalA oscillateS drawProgress
<span class="lineno"> 78 </span>--
<span class="lineno"> 79 </span>-- &lt;&lt;docs/gifs/doc_oscillateS.gif&gt;&gt;
<span class="lineno"> 80 </span>oscillateS :: Signal
<span class="lineno"> 81 </span><span class="decl"><span class="nottickedoff">oscillateS t =</span>
<span class="lineno"> 82 </span><span class="spaces"> </span><span class="nottickedoff">if t &lt; 1/2</span>
<span class="lineno"> 83 </span><span class="spaces"> </span><span class="nottickedoff">then t*2</span>
<span class="lineno"> 84 </span><span class="spaces"> </span><span class="nottickedoff">else 2-t*2</span></span>
<span class="lineno"> 85 </span>
<span class="lineno"> 86 </span>-- | Bell-curve signal. Takes a steepness parameter. 2 is a good default.
<span class="lineno"> 87 </span>--
<span class="lineno"> 88 </span>-- Example:
<span class="lineno"> 89 </span>--
<span class="lineno"> 90 </span>-- &gt; signalA (bellS 2) drawProgress
<span class="lineno"> 91 </span>--
<span class="lineno"> 92 </span>-- &lt;&lt;docs/gifs/doc_bellS.gif&gt;&gt;
<span class="lineno"> 93 </span>bellS :: Double -&gt; Signal
<span class="lineno"> 94 </span><span class="decl"><span class="nottickedoff">bellS steepness = curveS steepness . oscillateS</span></span>
<span class="lineno"> 95 </span>
<span class="lineno"> 96 </span>-- | Cubic Bezier signal. Gives you a fair amount of control over how the
<span class="lineno"> 97 </span>-- signal will 'curve'.
<span class="lineno"> 98 </span>--
<span class="lineno"> 99 </span>-- Example:
<span class="lineno"> 100 </span>--
<span class="lineno"> 101 </span>-- &gt; signalA (cubicBezierS (0.0, 0.8, 0.9, 1.0)) drawProgress
<span class="lineno"> 102 </span>--
<span class="lineno"> 103 </span>-- &lt;&lt;docs/gifs/doc_cubicBezierS.gif&gt;&gt;
<span class="lineno"> 104 </span>cubicBezierS :: (Double, Double, Double, Double) -&gt; Signal
<span class="lineno"> 105 </span><span class="decl"><span class="nottickedoff">cubicBezierS (x1, x2, x3, x4) s = </span>
<span class="lineno"> 106 </span><span class="spaces"> </span><span class="nottickedoff">let ms = 1-s</span>
<span class="lineno"> 107 </span><span class="spaces"> </span><span class="nottickedoff">in x1*ms^(3::Int) + 3*x2*ms^(2::Int)*s + 3*x3*ms*s^(2::Int) + x4*s^(3::Int)</span></span>
</pre>
</body>
</html>

View file

@ -0,0 +1,287 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style type="text/css">
span.lineno { color: white; background: #aaaaaa; border-right: solid white 12px }
span.nottickedoff { background: yellow}
span.istickedoff { background: white }
span.tickonlyfalse { margin: -1px; border: 1px solid #f20913; background: #f20913 }
span.tickonlytrue { margin: -1px; border: 1px solid #60de51; background: #60de51 }
span.funcount { font-size: small; color: orange; z-index: 2; position: absolute; right: 20 }
span.decl { font-weight: bold }
span.spaces { background: white }
</style>
</head>
<body>
<pre>
<span class="decl"><span class="nottickedoff">never executed</span> <span class="tickonlytrue">always true</span> <span class="tickonlyfalse">always false</span></span>
</pre>
<pre>
<span class="lineno"> 1 </span>{-# LANGUAGE FunctionalDependencies #-}
<span class="lineno"> 2 </span>{-# LANGUAGE MultiParamTypeClasses #-}
<span class="lineno"> 3 </span>{-# LANGUAGE UndecidableInstances #-}
<span class="lineno"> 4 </span>module Reanimate.Internal.CubicBezier
<span class="lineno"> 5 </span> ( AnyBezier(..)
<span class="lineno"> 6 </span> , CubicBezier(..)
<span class="lineno"> 7 </span> , QuadBezier(..)
<span class="lineno"> 8 </span> , OpenPath(..)
<span class="lineno"> 9 </span> , ClosedPath(..)
<span class="lineno"> 10 </span> , PathJoin(..)
<span class="lineno"> 11 </span> , ClosedMetaPath(..)
<span class="lineno"> 12 </span> , OpenMetaPath(..)
<span class="lineno"> 13 </span> , MetaJoin(..)
<span class="lineno"> 14 </span> , MetaNodeType(..)
<span class="lineno"> 15 </span> , C.GenericBezier(..)
<span class="lineno"> 16 </span> , C.FillRule(..)
<span class="lineno"> 17 </span> , C.Tension(..)
<span class="lineno"> 18 </span> , quadToCubic
<span class="lineno"> 19 </span> , arcLength
<span class="lineno"> 20 </span> , arcLengthParam
<span class="lineno"> 21 </span> , C.splitBezier
<span class="lineno"> 22 </span> , colinear
<span class="lineno"> 23 </span> , evalBezier
<span class="lineno"> 24 </span> , evalBezierDeriv
<span class="lineno"> 25 </span> , bezierHoriz
<span class="lineno"> 26 </span> , bezierVert
<span class="lineno"> 27 </span> , C.bezierSubsegment
<span class="lineno"> 28 </span> , C.reorient
<span class="lineno"> 29 </span> , closedPathCurves
<span class="lineno"> 30 </span> , openPathCurves
<span class="lineno"> 31 </span> , curvesToClosed
<span class="lineno"> 32 </span> , closest
<span class="lineno"> 33 </span> , unmetaOpen
<span class="lineno"> 34 </span> , unmetaClosed
<span class="lineno"> 35 </span> , union
<span class="lineno"> 36 </span> , bezierIntersection
<span class="lineno"> 37 </span> , interpolateVector
<span class="lineno"> 38 </span> , vectorDistance
<span class="lineno"> 39 </span> , findBezierInflection
<span class="lineno"> 40 </span> , findBezierCusp
<span class="lineno"> 41 </span> ) where
<span class="lineno"> 42 </span>
<span class="lineno"> 43 </span>import qualified Data.Vector.Unboxed as V
<span class="lineno"> 44 </span>import qualified Geom2D.CubicBezier as C
<span class="lineno"> 45 </span>import Linear.V2
<span class="lineno"> 46 </span>
<span class="lineno"> 47 </span>------------------------------------------------------------
<span class="lineno"> 48 </span>-- Data types
<span class="lineno"> 49 </span>
<span class="lineno"> 50 </span>newtype AnyBezier a = AnyBezier (V.Vector (V2 a))
<span class="lineno"> 51 </span>
<span class="lineno"> 52 </span>data CubicBezier a = CubicBezier
<span class="lineno"> 53 </span> { <span class="nottickedoff"><span class="decl"><span class="nottickedoff">cubicC0</span></span></span> :: !(V2 a)
<span class="lineno"> 54 </span> , <span class="nottickedoff"><span class="decl"><span class="nottickedoff">cubicC1</span></span></span> :: !(V2 a)
<span class="lineno"> 55 </span> , <span class="nottickedoff"><span class="decl"><span class="nottickedoff">cubicC2</span></span></span> :: !(V2 a)
<span class="lineno"> 56 </span> , <span class="nottickedoff"><span class="decl"><span class="nottickedoff">cubicC3</span></span></span> :: !(V2 a)
<span class="lineno"> 57 </span> } deriving (<span class="decl"><span class="nottickedoff">Show</span></span>, <span class="decl"><span class="nottickedoff">Eq</span></span>)
<span class="lineno"> 58 </span>
<span class="lineno"> 59 </span>data QuadBezier a = QuadBezier
<span class="lineno"> 60 </span> { <span class="nottickedoff"><span class="decl"><span class="nottickedoff">quadC0</span></span></span> :: !(V2 a)
<span class="lineno"> 61 </span> , <span class="nottickedoff"><span class="decl"><span class="nottickedoff">quadC1</span></span></span> :: !(V2 a)
<span class="lineno"> 62 </span> , <span class="nottickedoff"><span class="decl"><span class="nottickedoff">quadC2</span></span></span> :: !(V2 a)
<span class="lineno"> 63 </span> } deriving (<span class="decl"><span class="nottickedoff">Show</span></span>, <span class="decl"><span class="nottickedoff">Eq</span></span>)
<span class="lineno"> 64 </span>
<span class="lineno"> 65 </span>data OpenPath a = OpenPath [(V2 a, PathJoin a)] (V2 a)
<span class="lineno"> 66 </span> deriving (<span class="decl"><span class="nottickedoff">Show</span></span>, <span class="decl"><span class="nottickedoff">Eq</span></span>)
<span class="lineno"> 67 </span>data ClosedPath a = ClosedPath [(V2 a, PathJoin a)]
<span class="lineno"> 68 </span> deriving (<span class="decl"><span class="nottickedoff">Show</span></span>, <span class="decl"><span class="nottickedoff">Eq</span></span>)
<span class="lineno"> 69 </span>
<span class="lineno"> 70 </span>data PathJoin a
<span class="lineno"> 71 </span> = JoinLine
<span class="lineno"> 72 </span> | JoinCurve (V2 a) (V2 a)
<span class="lineno"> 73 </span> deriving (<span class="decl"><span class="nottickedoff">Show</span></span>, <span class="decl"><span class="nottickedoff">Eq</span></span>)
<span class="lineno"> 74 </span>
<span class="lineno"> 75 </span>data ClosedMetaPath a = ClosedMetaPath [(V2 a, MetaJoin a)]
<span class="lineno"> 76 </span> deriving (<span class="decl"><span class="nottickedoff">Show</span></span>, <span class="decl"><span class="nottickedoff">Eq</span></span>)
<span class="lineno"> 77 </span>data OpenMetaPath a = OpenMetaPath [(V2 a, MetaJoin a)] (V2 a)
<span class="lineno"> 78 </span> deriving (<span class="decl"><span class="nottickedoff">Show</span></span>, <span class="decl"><span class="nottickedoff">Eq</span></span>)
<span class="lineno"> 79 </span>
<span class="lineno"> 80 </span>data MetaJoin a
<span class="lineno"> 81 </span> = MetaJoin
<span class="lineno"> 82 </span> { <span class="nottickedoff"><span class="decl"><span class="nottickedoff">metaTypeL</span></span></span> :: MetaNodeType a
<span class="lineno"> 83 </span> , <span class="nottickedoff"><span class="decl"><span class="nottickedoff">tensionL</span></span></span> :: C.Tension a
<span class="lineno"> 84 </span> , <span class="nottickedoff"><span class="decl"><span class="nottickedoff">tensionR</span></span></span> :: C.Tension a
<span class="lineno"> 85 </span> , <span class="nottickedoff"><span class="decl"><span class="nottickedoff">metaTypeR</span></span></span> :: MetaNodeType a
<span class="lineno"> 86 </span> }
<span class="lineno"> 87 </span> | Controls (V2 a) (V2 a)
<span class="lineno"> 88 </span> deriving (<span class="decl"><span class="nottickedoff">Show</span></span>, <span class="decl"><span class="nottickedoff">Eq</span></span>)
<span class="lineno"> 89 </span>
<span class="lineno"> 90 </span>data MetaNodeType a
<span class="lineno"> 91 </span> = Open
<span class="lineno"> 92 </span> | Curl { <span class="nottickedoff"><span class="decl"><span class="nottickedoff">curlgamma</span></span></span> :: a }
<span class="lineno"> 93 </span> | Direction { <span class="nottickedoff"><span class="decl"><span class="nottickedoff">nodedir</span></span></span> :: V2 a }
<span class="lineno"> 94 </span> deriving (<span class="decl"><span class="nottickedoff">Show</span></span>, <span class="decl"><span class="nottickedoff">Eq</span></span>)
<span class="lineno"> 95 </span>
<span class="lineno"> 96 </span>------------------------------------------------------------
<span class="lineno"> 97 </span>-- Methods
<span class="lineno"> 98 </span>
<span class="lineno"> 99 </span>quadToCubic :: Fractional a =&gt; QuadBezier a -&gt; CubicBezier a
<span class="lineno"> 100 </span><span class="decl"><span class="nottickedoff">quadToCubic = upCast . C.quadToCubic . downCast</span></span>
<span class="lineno"> 101 </span>
<span class="lineno"> 102 </span>arcLength :: CubicBezier Double -&gt; Double -&gt; Double -&gt; Double
<span class="lineno"> 103 </span><span class="decl"><span class="istickedoff">arcLength bezier t tol = C.arcLength (downCast bezier) t tol</span></span>
<span class="lineno"> 104 </span>
<span class="lineno"> 105 </span>arcLengthParam :: CubicBezier Double -&gt; Double -&gt; Double -&gt; Double
<span class="lineno"> 106 </span><span class="decl"><span class="nottickedoff">arcLengthParam bezier t tol = C.arcLengthParam (downCast bezier) t tol</span></span>
<span class="lineno"> 107 </span>
<span class="lineno"> 108 </span>colinear :: CubicBezier Double -&gt; Double -&gt; Bool
<span class="lineno"> 109 </span><span class="decl"><span class="nottickedoff">colinear bezier tol = C.colinear (downCast bezier) tol</span></span>
<span class="lineno"> 110 </span>
<span class="lineno"> 111 </span>evalBezier :: (C.GenericBezier b, V.Unbox a, Fractional a) =&gt; b a -&gt; a -&gt; V2 a
<span class="lineno"> 112 </span><span class="decl"><span class="nottickedoff">evalBezier c p = upCast $ C.evalBezier c p</span></span>
<span class="lineno"> 113 </span>
<span class="lineno"> 114 </span>evalBezierDeriv :: (V.Unbox a, Fractional a,C.GenericBezier b) =&gt; b a -&gt; a -&gt; (V2 a, V2 a)
<span class="lineno"> 115 </span><span class="decl"><span class="nottickedoff">evalBezierDeriv c p = upCast $ C.evalBezierDeriv c p</span></span>
<span class="lineno"> 116 </span>
<span class="lineno"> 117 </span>bezierHoriz :: CubicBezier Double -&gt; [Double]
<span class="lineno"> 118 </span><span class="decl"><span class="nottickedoff">bezierHoriz = C.bezierHoriz . downCast</span></span>
<span class="lineno"> 119 </span>
<span class="lineno"> 120 </span>bezierVert :: CubicBezier Double -&gt; [Double]
<span class="lineno"> 121 </span><span class="decl"><span class="nottickedoff">bezierVert = C.bezierVert . downCast</span></span>
<span class="lineno"> 122 </span>
<span class="lineno"> 123 </span>unmetaOpen :: OpenMetaPath Double -&gt; OpenPath Double
<span class="lineno"> 124 </span><span class="decl"><span class="nottickedoff">unmetaOpen = upCast . C.unmetaOpen . downCast</span></span>
<span class="lineno"> 125 </span>
<span class="lineno"> 126 </span>unmetaClosed :: ClosedMetaPath Double -&gt; ClosedPath Double
<span class="lineno"> 127 </span><span class="decl"><span class="nottickedoff">unmetaClosed = upCast . C.unmetaClosed . downCast</span></span>
<span class="lineno"> 128 </span>
<span class="lineno"> 129 </span>union :: [ClosedPath Double] -&gt; C.FillRule -&gt; Double -&gt; [ClosedPath Double]
<span class="lineno"> 130 </span><span class="decl"><span class="nottickedoff">union p fill tol = upCast (C.union (downCast p) fill tol)</span></span>
<span class="lineno"> 131 </span>
<span class="lineno"> 132 </span>bezierIntersection :: CubicBezier Double -&gt; CubicBezier Double -&gt; Double -&gt; [(Double, Double)]
<span class="lineno"> 133 </span><span class="decl"><span class="nottickedoff">bezierIntersection a b t = C.bezierIntersection (downCast a) (downCast b) t</span></span>
<span class="lineno"> 134 </span>
<span class="lineno"> 135 </span>closest :: CubicBezier Double -&gt; V2 Double -&gt; Double -&gt; Double
<span class="lineno"> 136 </span><span class="decl"><span class="nottickedoff">closest c p t = C.closest (downCast c) (downCast p) t</span></span>
<span class="lineno"> 137 </span>
<span class="lineno"> 138 </span>closedPathCurves :: Fractional a =&gt; ClosedPath a -&gt; [CubicBezier a]
<span class="lineno"> 139 </span><span class="decl"><span class="nottickedoff">closedPathCurves = upCast . C.closedPathCurves . downCast</span></span>
<span class="lineno"> 140 </span>
<span class="lineno"> 141 </span>openPathCurves :: Fractional a =&gt; OpenPath a -&gt; [CubicBezier a]
<span class="lineno"> 142 </span><span class="decl"><span class="nottickedoff">openPathCurves = upCast . C.openPathCurves . downCast</span></span>
<span class="lineno"> 143 </span>
<span class="lineno"> 144 </span>curvesToClosed :: [CubicBezier a] -&gt; ClosedPath a
<span class="lineno"> 145 </span><span class="decl"><span class="nottickedoff">curvesToClosed = upCast . C.curvesToClosed . downCast</span></span>
<span class="lineno"> 146 </span>
<span class="lineno"> 147 </span>interpolateVector :: Num a =&gt; V2 a -&gt; V2 a -&gt; a -&gt; V2 a
<span class="lineno"> 148 </span><span class="decl"><span class="nottickedoff">interpolateVector a b p = upCast $ C.interpolateVector (downCast a) (downCast b) p</span></span>
<span class="lineno"> 149 </span>
<span class="lineno"> 150 </span>vectorDistance :: Floating a =&gt; V2 a -&gt; V2 a -&gt; a
<span class="lineno"> 151 </span><span class="decl"><span class="nottickedoff">vectorDistance a b = C.vectorDistance (downCast a) (downCast b)</span></span>
<span class="lineno"> 152 </span>
<span class="lineno"> 153 </span>findBezierInflection :: CubicBezier Double -&gt; [Double]
<span class="lineno"> 154 </span><span class="decl"><span class="nottickedoff">findBezierInflection = C.findBezierInflection . downCast</span></span>
<span class="lineno"> 155 </span>
<span class="lineno"> 156 </span>findBezierCusp :: CubicBezier Double -&gt; [Double]
<span class="lineno"> 157 </span><span class="decl"><span class="nottickedoff">findBezierCusp = C.findBezierCusp . downCast</span></span>
<span class="lineno"> 158 </span>
<span class="lineno"> 159 </span>------------------------------------------------------------
<span class="lineno"> 160 </span>-- Instances
<span class="lineno"> 161 </span>
<span class="lineno"> 162 </span>instance C.GenericBezier QuadBezier where
<span class="lineno"> 163 </span> <span class="decl"><span class="nottickedoff">degree = C.degree . downCast</span></span>
<span class="lineno"> 164 </span> <span class="decl"><span class="nottickedoff">toVector = C.toVector . downCast</span></span>
<span class="lineno"> 165 </span> <span class="decl"><span class="nottickedoff">unsafeFromVector = upCast . C.unsafeFromVector</span></span>
<span class="lineno"> 166 </span>
<span class="lineno"> 167 </span>instance C.GenericBezier CubicBezier where
<span class="lineno"> 168 </span> <span class="decl"><span class="nottickedoff">degree = C.degree . downCast</span></span>
<span class="lineno"> 169 </span> <span class="decl"><span class="nottickedoff">toVector = C.toVector . downCast</span></span>
<span class="lineno"> 170 </span> <span class="decl"><span class="nottickedoff">unsafeFromVector = upCast . C.unsafeFromVector</span></span>
<span class="lineno"> 171 </span>
<span class="lineno"> 172 </span>instance C.GenericBezier AnyBezier where
<span class="lineno"> 173 </span> <span class="decl"><span class="nottickedoff">degree = C.degree . downCast</span></span>
<span class="lineno"> 174 </span> <span class="decl"><span class="istickedoff">toVector = C.toVector . downCast</span></span>
<span class="lineno"> 175 </span> <span class="decl"><span class="istickedoff">unsafeFromVector = upCast . C.unsafeFromVector</span></span>
<span class="lineno"> 176 </span>
<span class="lineno"> 177 </span>------------------------------------------------------------
<span class="lineno"> 178 </span>-- Casting
<span class="lineno"> 179 </span>
<span class="lineno"> 180 </span>class Cast a b | a -&gt; b, b -&gt; a where
<span class="lineno"> 181 </span> downCast :: a -&gt; b
<span class="lineno"> 182 </span> upCast :: b -&gt; a
<span class="lineno"> 183 </span>
<span class="lineno"> 184 </span>instance Cast a b =&gt; Cast [a] [b] where
<span class="lineno"> 185 </span> <span class="decl"><span class="nottickedoff">downCast = map downCast</span></span>
<span class="lineno"> 186 </span> <span class="decl"><span class="nottickedoff">upCast = map upCast</span></span>
<span class="lineno"> 187 </span>
<span class="lineno"> 188 </span>instance (Cast a a', Cast b b') =&gt; Cast (a,b) (a',b') where
<span class="lineno"> 189 </span> <span class="decl"><span class="nottickedoff">downCast (a, b) = (downCast a, downCast b)</span></span>
<span class="lineno"> 190 </span> <span class="decl"><span class="nottickedoff">upCast (a, b) = (upCast a, upCast b)</span></span>
<span class="lineno"> 191 </span>
<span class="lineno"> 192 </span>instance Cast (V2 a) (C.Point a) where
<span class="lineno"> 193 </span> <span class="decl"><span class="istickedoff">downCast (V2 a b) = C.Point a b</span></span>
<span class="lineno"> 194 </span> <span class="decl"><span class="nottickedoff">upCast (C.Point a b) = V2 a b</span></span>
<span class="lineno"> 195 </span>
<span class="lineno"> 196 </span>instance Cast (CubicBezier a) (C.CubicBezier a) where
<span class="lineno"> 197 </span> <span class="decl"><span class="istickedoff">downCast (CubicBezier a b c d) = C.CubicBezier</span>
<span class="lineno"> 198 </span><span class="spaces"> </span><span class="istickedoff">(downCast a) (downCast b) (downCast c) (downCast d)</span></span>
<span class="lineno"> 199 </span> <span class="decl"><span class="nottickedoff">upCast (C.CubicBezier a b c d) = CubicBezier</span>
<span class="lineno"> 200 </span><span class="spaces"> </span><span class="nottickedoff">(upCast a) (upCast b) (upCast c) (upCast d)</span></span>
<span class="lineno"> 201 </span>
<span class="lineno"> 202 </span>instance Cast (QuadBezier a) (C.QuadBezier a) where
<span class="lineno"> 203 </span> <span class="decl"><span class="nottickedoff">downCast (QuadBezier a b c) = C.QuadBezier</span>
<span class="lineno"> 204 </span><span class="spaces"> </span><span class="nottickedoff">(downCast a) (downCast b) (downCast c)</span></span>
<span class="lineno"> 205 </span> <span class="decl"><span class="nottickedoff">upCast (C.QuadBezier a b c)= QuadBezier</span>
<span class="lineno"> 206 </span><span class="spaces"> </span><span class="nottickedoff">(upCast a) (upCast b) (upCast c)</span></span>
<span class="lineno"> 207 </span>
<span class="lineno"> 208 </span>instance V.Unbox a =&gt; Cast (AnyBezier a) (C.AnyBezier a) where
<span class="lineno"> 209 </span> <span class="decl"><span class="istickedoff">downCast (AnyBezier arr) = C.AnyBezier $</span>
<span class="lineno"> 210 </span><span class="spaces"> </span><span class="istickedoff">V.map (\(V2 a b) -&gt; (a,b)) arr</span></span>
<span class="lineno"> 211 </span> <span class="decl"><span class="istickedoff">upCast (C.AnyBezier arr) = AnyBezier $</span>
<span class="lineno"> 212 </span><span class="spaces"> </span><span class="istickedoff">V.map (\(a, b) -&gt; V2 a b) arr</span></span>
<span class="lineno"> 213 </span>
<span class="lineno"> 214 </span>instance Cast (MetaNodeType a) (C.MetaNodeType a) where
<span class="lineno"> 215 </span> <span class="decl"><span class="nottickedoff">downCast Open = C.Open</span>
<span class="lineno"> 216 </span><span class="spaces"> </span><span class="nottickedoff">downCast (Curl gamma) = C.Curl gamma</span>
<span class="lineno"> 217 </span><span class="spaces"> </span><span class="nottickedoff">downCast (Direction dir) = C.Direction (downCast dir)</span></span>
<span class="lineno"> 218 </span> <span class="decl"><span class="nottickedoff">upCast C.Open = Open</span>
<span class="lineno"> 219 </span><span class="spaces"> </span><span class="nottickedoff">upCast (C.Curl gamma) = Curl gamma</span>
<span class="lineno"> 220 </span><span class="spaces"> </span><span class="nottickedoff">upCast (C.Direction dir) = Direction (upCast dir)</span></span>
<span class="lineno"> 221 </span>
<span class="lineno"> 222 </span>instance Cast (MetaJoin a) (C.MetaJoin a) where
<span class="lineno"> 223 </span> <span class="decl"><span class="nottickedoff">downCast (MetaJoin tyL tL tR tyR) = C.MetaJoin (downCast tyL) tL tR (downCast tyR)</span>
<span class="lineno"> 224 </span><span class="spaces"> </span><span class="nottickedoff">downCast (Controls p1 p2) = C.Controls (downCast p1) (downCast p2)</span></span>
<span class="lineno"> 225 </span> <span class="decl"><span class="nottickedoff">upCast (C.MetaJoin tyL tL tR tyR) = MetaJoin (upCast tyL) tL tR (upCast tyR)</span>
<span class="lineno"> 226 </span><span class="spaces"> </span><span class="nottickedoff">upCast (C.Controls p1 p2) = Controls (upCast p1) (upCast p2)</span></span>
<span class="lineno"> 227 </span>
<span class="lineno"> 228 </span>instance Cast (PathJoin a) (C.PathJoin a) where
<span class="lineno"> 229 </span> <span class="decl"><span class="nottickedoff">downCast JoinLine = C.JoinLine</span>
<span class="lineno"> 230 </span><span class="spaces"> </span><span class="nottickedoff">downCast (JoinCurve a b) = C.JoinCurve (downCast a) (downCast b)</span></span>
<span class="lineno"> 231 </span> <span class="decl"><span class="nottickedoff">upCast C.JoinLine = JoinLine</span>
<span class="lineno"> 232 </span><span class="spaces"> </span><span class="nottickedoff">upCast (C.JoinCurve a b) = JoinCurve (upCast a) (upCast b)</span></span>
<span class="lineno"> 233 </span>
<span class="lineno"> 234 </span>instance Cast (OpenMetaPath a) (C.OpenMetaPath a) where
<span class="lineno"> 235 </span> <span class="decl"><span class="nottickedoff">downCast (OpenMetaPath lst end) = C.OpenMetaPath</span>
<span class="lineno"> 236 </span><span class="spaces"> </span><span class="nottickedoff">[ (downCast p, downCast j)</span>
<span class="lineno"> 237 </span><span class="spaces"> </span><span class="nottickedoff">| (p, j) &lt;- lst ] (downCast end)</span></span>
<span class="lineno"> 238 </span> <span class="decl"><span class="nottickedoff">upCast (C.OpenMetaPath lst end) = OpenMetaPath</span>
<span class="lineno"> 239 </span><span class="spaces"> </span><span class="nottickedoff">[ (upCast p, upCast j)</span>
<span class="lineno"> 240 </span><span class="spaces"> </span><span class="nottickedoff">| (p, j) &lt;- lst ] (upCast end)</span></span>
<span class="lineno"> 241 </span>
<span class="lineno"> 242 </span>instance Cast (ClosedMetaPath a) (C.ClosedMetaPath a) where
<span class="lineno"> 243 </span> <span class="decl"><span class="nottickedoff">downCast (ClosedMetaPath lst) = C.ClosedMetaPath</span>
<span class="lineno"> 244 </span><span class="spaces"> </span><span class="nottickedoff">[ (downCast p, downCast j)</span>
<span class="lineno"> 245 </span><span class="spaces"> </span><span class="nottickedoff">| (p, j) &lt;- lst ]</span></span>
<span class="lineno"> 246 </span> <span class="decl"><span class="nottickedoff">upCast (C.ClosedMetaPath lst) = ClosedMetaPath</span>
<span class="lineno"> 247 </span><span class="spaces"> </span><span class="nottickedoff">[ (upCast p, upCast j)</span>
<span class="lineno"> 248 </span><span class="spaces"> </span><span class="nottickedoff">| (p, j) &lt;- lst ]</span></span>
<span class="lineno"> 249 </span>
<span class="lineno"> 250 </span>instance Cast (OpenPath a) (C.OpenPath a) where
<span class="lineno"> 251 </span> <span class="decl"><span class="nottickedoff">downCast (OpenPath lst end) = C.OpenPath</span>
<span class="lineno"> 252 </span><span class="spaces"> </span><span class="nottickedoff">[ (downCast p, downCast j)</span>
<span class="lineno"> 253 </span><span class="spaces"> </span><span class="nottickedoff">| (p, j) &lt;- lst ] (downCast end)</span></span>
<span class="lineno"> 254 </span> <span class="decl"><span class="nottickedoff">upCast (C.OpenPath lst end) = OpenPath</span>
<span class="lineno"> 255 </span><span class="spaces"> </span><span class="nottickedoff">[ (upCast p, upCast j)</span>
<span class="lineno"> 256 </span><span class="spaces"> </span><span class="nottickedoff">| (p, j) &lt;- lst ] (upCast end)</span></span>
<span class="lineno"> 257 </span>
<span class="lineno"> 258 </span>instance Cast (ClosedPath a) (C.ClosedPath a) where
<span class="lineno"> 259 </span> <span class="decl"><span class="nottickedoff">downCast (ClosedPath lst) = C.ClosedPath</span>
<span class="lineno"> 260 </span><span class="spaces"> </span><span class="nottickedoff">[ (downCast p, downCast j)</span>
<span class="lineno"> 261 </span><span class="spaces"> </span><span class="nottickedoff">| (p, j) &lt;- lst ]</span></span>
<span class="lineno"> 262 </span> <span class="decl"><span class="nottickedoff">upCast (C.ClosedPath lst) = ClosedPath</span>
<span class="lineno"> 263 </span><span class="spaces"> </span><span class="nottickedoff">[ (upCast p, upCast j)</span>
<span class="lineno"> 264 </span><span class="spaces"> </span><span class="nottickedoff">| (p, j) &lt;- lst ]</span></span>
</pre>
</body>
</html>

View file

@ -0,0 +1,131 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style type="text/css">
span.lineno { color: white; background: #aaaaaa; border-right: solid white 12px }
span.nottickedoff { background: yellow}
span.istickedoff { background: white }
span.tickonlyfalse { margin: -1px; border: 1px solid #f20913; background: #f20913 }
span.tickonlytrue { margin: -1px; border: 1px solid #60de51; background: #60de51 }
span.funcount { font-size: small; color: orange; z-index: 2; position: absolute; right: 20 }
span.decl { font-weight: bold }
span.spaces { background: white }
</style>
</head>
<body>
<pre>
<span class="decl"><span class="nottickedoff">never executed</span> <span class="tickonlytrue">always true</span> <span class="tickonlyfalse">always false</span></span>
</pre>
<pre>
<span class="lineno"> 1 </span>module Reanimate.Misc
<span class="lineno"> 2 </span> ( requireExecutable
<span class="lineno"> 3 </span> , runCmd
<span class="lineno"> 4 </span> , runCmd_
<span class="lineno"> 5 </span> , runCmdLazy
<span class="lineno"> 6 </span> , withTempDir
<span class="lineno"> 7 </span> , withTempFile
<span class="lineno"> 8 </span> , renameOrCopyFile
<span class="lineno"> 9 </span> ) where
<span class="lineno"> 10 </span>
<span class="lineno"> 11 </span>import Control.Concurrent
<span class="lineno"> 12 </span>import Control.Exception (catch, evaluate, finally, throw)
<span class="lineno"> 13 </span>import qualified Data.Text as T
<span class="lineno"> 14 </span>import qualified Data.Text.IO as T
<span class="lineno"> 15 </span>import Foreign.C.Error
<span class="lineno"> 16 </span>import GHC.IO.Exception
<span class="lineno"> 17 </span>import System.Directory (copyFile, findExecutable, removeFile,
<span class="lineno"> 18 </span> renameFile)
<span class="lineno"> 19 </span>import System.FilePath ((&lt;.&gt;))
<span class="lineno"> 20 </span>import System.IO (hClose, hGetContents, hIsEOF, hPutStr,
<span class="lineno"> 21 </span> stderr)
<span class="lineno"> 22 </span>import System.IO.Temp (withSystemTempDirectory,
<span class="lineno"> 23 </span> withSystemTempFile)
<span class="lineno"> 24 </span>import System.Process (readProcessWithExitCode,
<span class="lineno"> 25 </span> runInteractiveProcess, showCommandForUser,
<span class="lineno"> 26 </span> terminateProcess, waitForProcess)
<span class="lineno"> 27 </span>
<span class="lineno"> 28 </span>
<span class="lineno"> 29 </span>requireExecutable :: String -&gt; IO FilePath
<span class="lineno"> 30 </span><span class="decl"><span class="nottickedoff">requireExecutable exec = do</span>
<span class="lineno"> 31 </span><span class="spaces"> </span><span class="nottickedoff">mbPath &lt;- findExecutable exec</span>
<span class="lineno"> 32 </span><span class="spaces"> </span><span class="nottickedoff">case mbPath of</span>
<span class="lineno"> 33 </span><span class="spaces"> </span><span class="nottickedoff">Nothing -&gt; error $ &quot;Couldn't find executable: &quot; ++ exec</span>
<span class="lineno"> 34 </span><span class="spaces"> </span><span class="nottickedoff">Just path -&gt; return path</span></span>
<span class="lineno"> 35 </span>
<span class="lineno"> 36 </span>runCmd :: FilePath -&gt; [String] -&gt; IO ()
<span class="lineno"> 37 </span><span class="decl"><span class="nottickedoff">runCmd exec args = do</span>
<span class="lineno"> 38 </span><span class="spaces"> </span><span class="nottickedoff">ret &lt;- runCmd_ exec args</span>
<span class="lineno"> 39 </span><span class="spaces"> </span><span class="nottickedoff">case ret of</span>
<span class="lineno"> 40 </span><span class="spaces"> </span><span class="nottickedoff">Left err -&gt; error $ showCommandForUser exec args ++ &quot;:\n&quot; ++ err</span>
<span class="lineno"> 41 </span><span class="spaces"> </span><span class="nottickedoff">Right{} -&gt; return ()</span></span>
<span class="lineno"> 42 </span>
<span class="lineno"> 43 </span>runCmd_ :: FilePath -&gt; [String] -&gt; IO (Either String String)
<span class="lineno"> 44 </span><span class="decl"><span class="nottickedoff">runCmd_ exec args = do</span>
<span class="lineno"> 45 </span><span class="spaces"> </span><span class="nottickedoff">(ret, stdout, errMsg) &lt;- readProcessWithExitCode exec args &quot;&quot;</span>
<span class="lineno"> 46 </span><span class="spaces"> </span><span class="nottickedoff">_ &lt;- evaluate (length stdout + length errMsg)</span>
<span class="lineno"> 47 </span><span class="spaces"> </span><span class="nottickedoff">case ret of</span>
<span class="lineno"> 48 </span><span class="spaces"> </span><span class="nottickedoff">ExitSuccess -&gt; return (Right stdout)</span>
<span class="lineno"> 49 </span><span class="spaces"> </span><span class="nottickedoff">ExitFailure err | False -&gt;</span>
<span class="lineno"> 50 </span><span class="spaces"> </span><span class="nottickedoff">return</span>
<span class="lineno"> 51 </span><span class="spaces"> </span><span class="nottickedoff">$ Left</span>
<span class="lineno"> 52 </span><span class="spaces"> </span><span class="nottickedoff">$ &quot;Failed to run: &quot;</span>
<span class="lineno"> 53 </span><span class="spaces"> </span><span class="nottickedoff">++ showCommandForUser exec args</span>
<span class="lineno"> 54 </span><span class="spaces"> </span><span class="nottickedoff">++ &quot;\n&quot;</span>
<span class="lineno"> 55 </span><span class="spaces"> </span><span class="nottickedoff">++ &quot;Error code: &quot;</span>
<span class="lineno"> 56 </span><span class="spaces"> </span><span class="nottickedoff">++ show err</span>
<span class="lineno"> 57 </span><span class="spaces"> </span><span class="nottickedoff">++ &quot;\n&quot;</span>
<span class="lineno"> 58 </span><span class="spaces"> </span><span class="nottickedoff">++ &quot;stderr: &quot;</span>
<span class="lineno"> 59 </span><span class="spaces"> </span><span class="nottickedoff">++ errMsg</span>
<span class="lineno"> 60 </span><span class="spaces"> </span><span class="nottickedoff">ExitFailure{} | null errMsg -&gt; -- LaTeX prints errors to stdout. :(</span>
<span class="lineno"> 61 </span><span class="spaces"> </span><span class="nottickedoff">return $ Left stdout</span>
<span class="lineno"> 62 </span><span class="spaces"> </span><span class="nottickedoff">ExitFailure{} -&gt; return $ Left errMsg</span></span>
<span class="lineno"> 63 </span>
<span class="lineno"> 64 </span>runCmdLazy
<span class="lineno"> 65 </span> :: FilePath -&gt; [String] -&gt; (IO (Either String T.Text) -&gt; IO a) -&gt; IO a
<span class="lineno"> 66 </span><span class="decl"><span class="nottickedoff">runCmdLazy exec args handler = do</span>
<span class="lineno"> 67 </span><span class="spaces"> </span><span class="nottickedoff">(inp, out, err, pid) &lt;- runInteractiveProcess exec args Nothing Nothing</span>
<span class="lineno"> 68 </span><span class="spaces"> </span><span class="nottickedoff">hClose inp</span>
<span class="lineno"> 69 </span><span class="spaces"> </span><span class="nottickedoff">errOutput &lt;- hGetContents err</span>
<span class="lineno"> 70 </span><span class="spaces"> </span><span class="nottickedoff">_ &lt;- forkIO $ hPutStr stderr errOutput</span>
<span class="lineno"> 71 </span><span class="spaces"> </span><span class="nottickedoff">let fetch = do</span>
<span class="lineno"> 72 </span><span class="spaces"> </span><span class="nottickedoff">eof &lt;- hIsEOF out</span>
<span class="lineno"> 73 </span><span class="spaces"> </span><span class="nottickedoff">if eof</span>
<span class="lineno"> 74 </span><span class="spaces"> </span><span class="nottickedoff">then do</span>
<span class="lineno"> 75 </span><span class="spaces"> </span><span class="nottickedoff">_ &lt;- evaluate (length errOutput)</span>
<span class="lineno"> 76 </span><span class="spaces"> </span><span class="nottickedoff">ret &lt;- waitForProcess pid</span>
<span class="lineno"> 77 </span><span class="spaces"> </span><span class="nottickedoff">case ret of</span>
<span class="lineno"> 78 </span><span class="spaces"> </span><span class="nottickedoff">ExitSuccess -&gt; return (Left &quot;&quot;)</span>
<span class="lineno"> 79 </span><span class="spaces"> </span><span class="nottickedoff">ExitFailure{} -&gt; return (Left errOutput)</span>
<span class="lineno"> 80 </span><span class="spaces"> </span><span class="nottickedoff">{-ExitFailure errMsg -&gt; do</span>
<span class="lineno"> 81 </span><span class="spaces"> </span><span class="nottickedoff">return $ Left $</span>
<span class="lineno"> 82 </span><span class="spaces"> </span><span class="nottickedoff">&quot;Failed to run: &quot; ++ showCommandForUser exec args ++ &quot;\n&quot; ++</span>
<span class="lineno"> 83 </span><span class="spaces"> </span><span class="nottickedoff">&quot;Error code: &quot; ++ show errMsg ++ &quot;\n&quot; ++</span>
<span class="lineno"> 84 </span><span class="spaces"> </span><span class="nottickedoff">&quot;stderr: &quot; ++ stderr-}</span>
<span class="lineno"> 85 </span><span class="spaces"> </span><span class="nottickedoff">else do</span>
<span class="lineno"> 86 </span><span class="spaces"> </span><span class="nottickedoff">line &lt;- T.hGetLine out</span>
<span class="lineno"> 87 </span><span class="spaces"> </span><span class="nottickedoff">return (Right line)</span>
<span class="lineno"> 88 </span><span class="spaces"> </span><span class="nottickedoff">handler fetch `finally` do</span>
<span class="lineno"> 89 </span><span class="spaces"> </span><span class="nottickedoff">terminateProcess pid</span>
<span class="lineno"> 90 </span><span class="spaces"> </span><span class="nottickedoff">_ &lt;- waitForProcess pid</span>
<span class="lineno"> 91 </span><span class="spaces"> </span><span class="nottickedoff">return ()</span></span>
<span class="lineno"> 92 </span>
<span class="lineno"> 93 </span>-- renameFile fails if we're crossing filesystem boundaries. If this happens,
<span class="lineno"> 94 </span>-- revert back to copyFile + removeFile.
<span class="lineno"> 95 </span>renameOrCopyFile :: FilePath -&gt; FilePath -&gt; IO ()
<span class="lineno"> 96 </span><span class="decl"><span class="nottickedoff">renameOrCopyFile src dst = renameFile src dst `catch` exdev</span>
<span class="lineno"> 97 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 98 </span><span class="spaces"> </span><span class="nottickedoff">exdev e = if fmap Errno (ioe_errno e) == Just eXDEV</span>
<span class="lineno"> 99 </span><span class="spaces"> </span><span class="nottickedoff">then copyFile src dst &gt;&gt; removeFile src</span>
<span class="lineno"> 100 </span><span class="spaces"> </span><span class="nottickedoff">else throw e</span></span>
<span class="lineno"> 101 </span>
<span class="lineno"> 102 </span>withTempDir :: (FilePath -&gt; IO a) -&gt; IO a
<span class="lineno"> 103 </span><span class="decl"><span class="nottickedoff">withTempDir = withSystemTempDirectory &quot;reanimate&quot;</span></span>
<span class="lineno"> 104 </span>
<span class="lineno"> 105 </span>withTempFile :: String -&gt; (FilePath -&gt; IO a) -&gt; IO a
<span class="lineno"> 106 </span><span class="decl"><span class="nottickedoff">withTempFile ext action =</span>
<span class="lineno"> 107 </span><span class="spaces"> </span><span class="nottickedoff">withSystemTempFile (&quot;reanimate&quot; &lt;.&gt; ext) $ \path hd -&gt;</span>
<span class="lineno"> 108 </span><span class="spaces"> </span><span class="nottickedoff">hClose hd &gt;&gt; action path</span></span>
</pre>
</body>
</html>

View file

@ -0,0 +1,123 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style type="text/css">
span.lineno { color: white; background: #aaaaaa; border-right: solid white 12px }
span.nottickedoff { background: yellow}
span.istickedoff { background: white }
span.tickonlyfalse { margin: -1px; border: 1px solid #f20913; background: #f20913 }
span.tickonlytrue { margin: -1px; border: 1px solid #60de51; background: #60de51 }
span.funcount { font-size: small; color: orange; z-index: 2; position: absolute; right: 20 }
span.decl { font-weight: bold }
span.spaces { background: white }
</style>
</head>
<body>
<pre>
<span class="decl"><span class="nottickedoff">never executed</span> <span class="tickonlytrue">always true</span> <span class="tickonlyfalse">always false</span></span>
</pre>
<pre>
<span class="lineno"> 1 </span>module Reanimate.Parameters
<span class="lineno"> 2 </span> ( Raster(..)
<span class="lineno"> 3 </span> , Width
<span class="lineno"> 4 </span> , Height
<span class="lineno"> 5 </span> , FPS
<span class="lineno"> 6 </span> , pRaster
<span class="lineno"> 7 </span> , pFPS
<span class="lineno"> 8 </span> , pWidth
<span class="lineno"> 9 </span> , pHeight
<span class="lineno"> 10 </span> , pNoExternals
<span class="lineno"> 11 </span> , pRootDirectory
<span class="lineno"> 12 </span> , setRaster
<span class="lineno"> 13 </span> , setFPS
<span class="lineno"> 14 </span> , setWidth
<span class="lineno"> 15 </span> , setHeight
<span class="lineno"> 16 </span> , setNoExternals
<span class="lineno"> 17 </span> , setRootDirectory
<span class="lineno"> 18 </span> ) where
<span class="lineno"> 19 </span>
<span class="lineno"> 20 </span>import System.IO.Unsafe
<span class="lineno"> 21 </span>import Data.IORef
<span class="lineno"> 22 </span>
<span class="lineno"> 23 </span>type Width = Int
<span class="lineno"> 24 </span>type Height = Int
<span class="lineno"> 25 </span>type FPS = Int
<span class="lineno"> 26 </span>
<span class="lineno"> 27 </span>data Raster
<span class="lineno"> 28 </span> = RasterNone
<span class="lineno"> 29 </span> | RasterAuto
<span class="lineno"> 30 </span> | RasterInkscape
<span class="lineno"> 31 </span> | RasterRSvg
<span class="lineno"> 32 </span> | RasterMagick
<span class="lineno"> 33 </span> deriving (<span class="decl"><span class="nottickedoff">Show</span></span>, <span class="decl"><span class="nottickedoff">Eq</span></span>)
<span class="lineno"> 34 </span>
<span class="lineno"> 35 </span>{-# NOINLINE pRasterRef #-}
<span class="lineno"> 36 </span>pRasterRef :: IORef Raster
<span class="lineno"> 37 </span><span class="decl"><span class="nottickedoff">pRasterRef = unsafePerformIO (newIORef RasterNone)</span></span>
<span class="lineno"> 38 </span>
<span class="lineno"> 39 </span>{-# NOINLINE pRaster #-}
<span class="lineno"> 40 </span>pRaster :: Raster
<span class="lineno"> 41 </span><span class="decl"><span class="nottickedoff">pRaster = unsafePerformIO (readIORef pRasterRef)</span></span>
<span class="lineno"> 42 </span>
<span class="lineno"> 43 </span>setRaster :: Raster -&gt; IO ()
<span class="lineno"> 44 </span><span class="decl"><span class="nottickedoff">setRaster = writeIORef pRasterRef</span></span>
<span class="lineno"> 45 </span>
<span class="lineno"> 46 </span>{-# NOINLINE pFPSRef #-}
<span class="lineno"> 47 </span>pFPSRef :: IORef FPS
<span class="lineno"> 48 </span><span class="decl"><span class="nottickedoff">pFPSRef = unsafePerformIO (newIORef 0)</span></span>
<span class="lineno"> 49 </span>
<span class="lineno"> 50 </span>{-# NOINLINE pFPS #-}
<span class="lineno"> 51 </span>pFPS :: FPS
<span class="lineno"> 52 </span><span class="decl"><span class="nottickedoff">pFPS = unsafePerformIO (readIORef pFPSRef)</span></span>
<span class="lineno"> 53 </span>
<span class="lineno"> 54 </span>setFPS :: FPS -&gt; IO ()
<span class="lineno"> 55 </span><span class="decl"><span class="nottickedoff">setFPS = writeIORef pFPSRef</span></span>
<span class="lineno"> 56 </span>
<span class="lineno"> 57 </span>{-# NOINLINE pWidthRef #-}
<span class="lineno"> 58 </span>pWidthRef :: IORef FPS
<span class="lineno"> 59 </span><span class="decl"><span class="nottickedoff">pWidthRef = unsafePerformIO (newIORef 0)</span></span>
<span class="lineno"> 60 </span>
<span class="lineno"> 61 </span>{-# NOINLINE pWidth #-}
<span class="lineno"> 62 </span>pWidth :: Width
<span class="lineno"> 63 </span><span class="decl"><span class="nottickedoff">pWidth = unsafePerformIO (readIORef pWidthRef)</span></span>
<span class="lineno"> 64 </span>
<span class="lineno"> 65 </span>setWidth :: Width -&gt; IO ()
<span class="lineno"> 66 </span><span class="decl"><span class="nottickedoff">setWidth = writeIORef pWidthRef</span></span>
<span class="lineno"> 67 </span>
<span class="lineno"> 68 </span>
<span class="lineno"> 69 </span>{-# NOINLINE pHeightRef #-}
<span class="lineno"> 70 </span>pHeightRef :: IORef FPS
<span class="lineno"> 71 </span><span class="decl"><span class="nottickedoff">pHeightRef = unsafePerformIO (newIORef 0)</span></span>
<span class="lineno"> 72 </span>
<span class="lineno"> 73 </span>{-# NOINLINE pHeight #-}
<span class="lineno"> 74 </span>pHeight :: Height
<span class="lineno"> 75 </span><span class="decl"><span class="nottickedoff">pHeight = unsafePerformIO (readIORef pHeightRef)</span></span>
<span class="lineno"> 76 </span>
<span class="lineno"> 77 </span>setHeight :: Height -&gt; IO ()
<span class="lineno"> 78 </span><span class="decl"><span class="nottickedoff">setHeight = writeIORef pHeightRef</span></span>
<span class="lineno"> 79 </span>
<span class="lineno"> 80 </span>{-# NOINLINE pNoExternalsRef #-}
<span class="lineno"> 81 </span>pNoExternalsRef :: IORef Bool
<span class="lineno"> 82 </span><span class="decl"><span class="istickedoff">pNoExternalsRef = unsafePerformIO (newIORef <span class="nottickedoff">False</span>)</span></span>
<span class="lineno"> 83 </span>
<span class="lineno"> 84 </span>{-# NOINLINE pNoExternals #-}
<span class="lineno"> 85 </span>pNoExternals :: Bool
<span class="lineno"> 86 </span><span class="decl"><span class="nottickedoff">pNoExternals = unsafePerformIO (readIORef pNoExternalsRef)</span></span>
<span class="lineno"> 87 </span>
<span class="lineno"> 88 </span>setNoExternals :: Bool -&gt; IO ()
<span class="lineno"> 89 </span><span class="decl"><span class="istickedoff">setNoExternals = writeIORef pNoExternalsRef</span></span>
<span class="lineno"> 90 </span>
<span class="lineno"> 91 </span>{-# NOINLINE pRootDirectoryRef #-}
<span class="lineno"> 92 </span>pRootDirectoryRef :: IORef FilePath
<span class="lineno"> 93 </span><span class="decl"><span class="nottickedoff">pRootDirectoryRef = unsafePerformIO (newIORef (error &quot;root directory not set&quot;))</span></span>
<span class="lineno"> 94 </span>
<span class="lineno"> 95 </span>{-# NOINLINE pRootDirectory #-}
<span class="lineno"> 96 </span>pRootDirectory :: FilePath
<span class="lineno"> 97 </span><span class="decl"><span class="nottickedoff">pRootDirectory = unsafePerformIO (readIORef pRootDirectoryRef)</span></span>
<span class="lineno"> 98 </span>
<span class="lineno"> 99 </span>setRootDirectory :: FilePath -&gt; IO ()
<span class="lineno"> 100 </span><span class="decl"><span class="nottickedoff">setRootDirectory = writeIORef pRootDirectoryRef</span></span>
</pre>
</body>
</html>

View file

@ -0,0 +1,318 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style type="text/css">
span.lineno { color: white; background: #aaaaaa; border-right: solid white 12px }
span.nottickedoff { background: yellow}
span.istickedoff { background: white }
span.tickonlyfalse { margin: -1px; border: 1px solid #f20913; background: #f20913 }
span.tickonlytrue { margin: -1px; border: 1px solid #60de51; background: #60de51 }
span.funcount { font-size: small; color: orange; z-index: 2; position: absolute; right: 20 }
span.decl { font-weight: bold }
span.spaces { background: white }
</style>
</head>
<body>
<pre>
<span class="decl"><span class="nottickedoff">never executed</span> <span class="tickonlytrue">always true</span> <span class="tickonlyfalse">always false</span></span>
</pre>
<pre>
<span class="lineno"> 1 </span>module Reanimate.Raster
<span class="lineno"> 2 </span> ( mkImage -- :: Double -&gt; Double -&gt; FilePath -&gt; SVG
<span class="lineno"> 3 </span> , cacheImage -- :: (PngSavable pixel, Hashable a) =&gt; a -&gt; Image pixel -&gt; FilePath
<span class="lineno"> 4 </span> , prerenderSvg -- :: Hashable a =&gt; a -&gt; SVG -&gt; SVG
<span class="lineno"> 5 </span> , prerenderSvgFile -- :: Hashable a =&gt; a -&gt; Width -&gt; Height -&gt; SVG -&gt; FilePath
<span class="lineno"> 6 </span> , embedImage -- :: PngSavable a =&gt; Image a -&gt; SVG
<span class="lineno"> 7 </span> , embedDynamicImage -- :: DynamicImage -&gt; SVG
<span class="lineno"> 8 </span> , embedPng -- :: Double -&gt; Double -&gt; LBS.ByteString -&gt; SVG
<span class="lineno"> 9 </span> , raster -- :: SVG -&gt; DynamicImage
<span class="lineno"> 10 </span> , rasterSized -- :: Width -&gt; Height -&gt; SVG -&gt; DynamicImage
<span class="lineno"> 11 </span> , vectorize -- :: FilePath -&gt; SVG
<span class="lineno"> 12 </span> , vectorize_ -- :: [String] -&gt; FilePath -&gt; SVG
<span class="lineno"> 13 </span> , svgAsPngFile -- :: SVG -&gt; FilePath
<span class="lineno"> 14 </span> , svgAsPngFile' -- :: Width -&gt; Height -&gt; SVG -&gt; FilePath
<span class="lineno"> 15 </span> )
<span class="lineno"> 16 </span>where
<span class="lineno"> 17 </span>
<span class="lineno"> 18 </span>import Codec.Picture
<span class="lineno"> 19 </span>import Control.Lens ( (&amp;)
<span class="lineno"> 20 </span> , (.~)
<span class="lineno"> 21 </span> )
<span class="lineno"> 22 </span>import Control.Monad
<span class="lineno"> 23 </span>import qualified Data.ByteString as B
<span class="lineno"> 24 </span>import qualified Data.ByteString.Base64.Lazy as Base64
<span class="lineno"> 25 </span>import qualified Data.ByteString.Lazy.Char8 as LBS
<span class="lineno"> 26 </span>import Data.Hashable
<span class="lineno"> 27 </span>import qualified Data.Text as T
<span class="lineno"> 28 </span>import Graphics.SvgTree ( Number(..)
<span class="lineno"> 29 </span> , Tree(..)
<span class="lineno"> 30 </span> , defaultSvg
<span class="lineno"> 31 </span> , parseSvgFile
<span class="lineno"> 32 </span> )
<span class="lineno"> 33 </span>import qualified Graphics.SvgTree as Svg
<span class="lineno"> 34 </span>import Reanimate.Animation
<span class="lineno"> 35 </span>import Reanimate.Cache
<span class="lineno"> 36 </span>import Reanimate.Driver.Magick
<span class="lineno"> 37 </span>import Reanimate.Misc
<span class="lineno"> 38 </span>import Reanimate.Render
<span class="lineno"> 39 </span>import Reanimate.Parameters
<span class="lineno"> 40 </span>import Reanimate.Constants
<span class="lineno"> 41 </span>import Reanimate.Svg.Constructors
<span class="lineno"> 42 </span>import Reanimate.Svg.Unuse
<span class="lineno"> 43 </span>import System.Directory
<span class="lineno"> 44 </span>import System.FilePath
<span class="lineno"> 45 </span>import System.IO
<span class="lineno"> 46 </span>import System.IO.Temp
<span class="lineno"> 47 </span>import System.IO.Unsafe
<span class="lineno"> 48 </span>
<span class="lineno"> 49 </span>-- | Load an external image. Width and height must be specified,
<span class="lineno"> 50 </span>-- ignoring the image's aspect ratio. The center of the image is
<span class="lineno"> 51 </span>-- placed at position (0,0).
<span class="lineno"> 52 </span>--
<span class="lineno"> 53 </span>-- For security reasons, must SVG renderer do not allow arbitrary
<span class="lineno"> 54 </span>-- image links. For some renderers, we can get around this by placing
<span class="lineno"> 55 </span>-- the images in the same root directory as the parent SVG file. Other
<span class="lineno"> 56 </span>-- renderers (like Chrome and ffmpeg) requires that the image is inlined
<span class="lineno"> 57 </span>-- as base64 data. External SVG files are an exception, though, as must
<span class="lineno"> 58 </span>-- always be inlined directly. `mkImage` attempts to hide all the complexity
<span class="lineno"> 59 </span>-- but edge-cases may exist.
<span class="lineno"> 60 </span>--
<span class="lineno"> 61 </span>-- Example:
<span class="lineno"> 62 </span>--
<span class="lineno"> 63 </span>-- &gt; mkImage screenWidth screenHeight &quot;../data/haskell.svg&quot;
<span class="lineno"> 64 </span>--
<span class="lineno"> 65 </span>-- &lt;&lt;docs/gifs/doc_mkImage.gif&gt;&gt;
<span class="lineno"> 66 </span>mkImage
<span class="lineno"> 67 </span> :: Double -- ^ Desired image width.
<span class="lineno"> 68 </span> -&gt; Double -- ^ Desired image height.
<span class="lineno"> 69 </span> -&gt; FilePath -- ^ Path to external image file.
<span class="lineno"> 70 </span> -&gt; SVG
<span class="lineno"> 71 </span><span class="decl"><span class="nottickedoff">mkImage width height path | takeExtension path == &quot;.svg&quot; = unsafePerformIO $ do</span>
<span class="lineno"> 72 </span><span class="spaces"> </span><span class="nottickedoff">svg_data &lt;- B.readFile path</span>
<span class="lineno"> 73 </span><span class="spaces"> </span><span class="nottickedoff">case parseSvgFile path svg_data of</span>
<span class="lineno"> 74 </span><span class="spaces"> </span><span class="nottickedoff">Nothing -&gt; error &quot;Malformed svg&quot;</span>
<span class="lineno"> 75 </span><span class="spaces"> </span><span class="nottickedoff">Just svg -&gt;</span>
<span class="lineno"> 76 </span><span class="spaces"> </span><span class="nottickedoff">return</span>
<span class="lineno"> 77 </span><span class="spaces"> </span><span class="nottickedoff">$ scaleXY (width / screenWidth) (height / screenHeight)</span>
<span class="lineno"> 78 </span><span class="spaces"> </span><span class="nottickedoff">$ embedDocument svg</span>
<span class="lineno"> 79 </span><span class="spaces"></span><span class="nottickedoff">mkImage width height path | pRaster == RasterNone = unsafePerformIO $ do</span>
<span class="lineno"> 80 </span><span class="spaces"> </span><span class="nottickedoff">inp &lt;- LBS.readFile path</span>
<span class="lineno"> 81 </span><span class="spaces"> </span><span class="nottickedoff">let imgData = LBS.unpack $ Base64.encode inp</span>
<span class="lineno"> 82 </span><span class="spaces"> </span><span class="nottickedoff">return</span>
<span class="lineno"> 83 </span><span class="spaces"> </span><span class="nottickedoff">$ flipYAxis</span>
<span class="lineno"> 84 </span><span class="spaces"> </span><span class="nottickedoff">$ ImageTree</span>
<span class="lineno"> 85 </span><span class="spaces"> </span><span class="nottickedoff">$ defaultSvg</span>
<span class="lineno"> 86 </span><span class="spaces"> </span><span class="nottickedoff">&amp; Svg.imageWidth</span>
<span class="lineno"> 87 </span><span class="spaces"> </span><span class="nottickedoff">.~ Svg.Num width</span>
<span class="lineno"> 88 </span><span class="spaces"> </span><span class="nottickedoff">&amp; Svg.imageHeight</span>
<span class="lineno"> 89 </span><span class="spaces"> </span><span class="nottickedoff">.~ Svg.Num height</span>
<span class="lineno"> 90 </span><span class="spaces"> </span><span class="nottickedoff">&amp; Svg.imageHref</span>
<span class="lineno"> 91 </span><span class="spaces"> </span><span class="nottickedoff">.~ (&quot;data:&quot; ++ mimeType ++ &quot;;base64,&quot; ++ imgData)</span>
<span class="lineno"> 92 </span><span class="spaces"> </span><span class="nottickedoff">&amp; Svg.imageCornerUpperLeft</span>
<span class="lineno"> 93 </span><span class="spaces"> </span><span class="nottickedoff">.~ (Svg.Num (-width / 2), Svg.Num (-height / 2))</span>
<span class="lineno"> 94 </span><span class="spaces"> </span><span class="nottickedoff">&amp; Svg.imageAspectRatio</span>
<span class="lineno"> 95 </span><span class="spaces"> </span><span class="nottickedoff">.~ Svg.PreserveAspectRatio False Svg.AlignNone Nothing</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">-- FIXME: Is there a better way to do this?</span>
<span class="lineno"> 98 </span><span class="spaces"> </span><span class="nottickedoff">mimeType = case takeExtension path of</span>
<span class="lineno"> 99 </span><span class="spaces"> </span><span class="nottickedoff">&quot;.jpg&quot; -&gt; &quot;image/jpeg&quot;</span>
<span class="lineno"> 100 </span><span class="spaces"> </span><span class="nottickedoff">ext -&gt; &quot;image/&quot; ++ drop 1 ext</span>
<span class="lineno"> 101 </span><span class="spaces"></span><span class="nottickedoff">mkImage width height path = unsafePerformIO $ do</span>
<span class="lineno"> 102 </span><span class="spaces"> </span><span class="nottickedoff">exists &lt;- doesFileExist target</span>
<span class="lineno"> 103 </span><span class="spaces"> </span><span class="nottickedoff">unless exists $ copyFile path target</span>
<span class="lineno"> 104 </span><span class="spaces"> </span><span class="nottickedoff">return</span>
<span class="lineno"> 105 </span><span class="spaces"> </span><span class="nottickedoff">$ flipYAxis</span>
<span class="lineno"> 106 </span><span class="spaces"> </span><span class="nottickedoff">$ ImageTree</span>
<span class="lineno"> 107 </span><span class="spaces"> </span><span class="nottickedoff">$ defaultSvg</span>
<span class="lineno"> 108 </span><span class="spaces"> </span><span class="nottickedoff">&amp; Svg.imageWidth</span>
<span class="lineno"> 109 </span><span class="spaces"> </span><span class="nottickedoff">.~ Svg.Num width</span>
<span class="lineno"> 110 </span><span class="spaces"> </span><span class="nottickedoff">&amp; Svg.imageHeight</span>
<span class="lineno"> 111 </span><span class="spaces"> </span><span class="nottickedoff">.~ Svg.Num height</span>
<span class="lineno"> 112 </span><span class="spaces"> </span><span class="nottickedoff">&amp; Svg.imageHref</span>
<span class="lineno"> 113 </span><span class="spaces"> </span><span class="nottickedoff">.~ (&quot;file://&quot; ++ target)</span>
<span class="lineno"> 114 </span><span class="spaces"> </span><span class="nottickedoff">&amp; Svg.imageCornerUpperLeft</span>
<span class="lineno"> 115 </span><span class="spaces"> </span><span class="nottickedoff">.~ (Svg.Num (-width / 2), Svg.Num (-height / 2))</span>
<span class="lineno"> 116 </span><span class="spaces"> </span><span class="nottickedoff">&amp; Svg.imageAspectRatio</span>
<span class="lineno"> 117 </span><span class="spaces"> </span><span class="nottickedoff">.~ Svg.PreserveAspectRatio False Svg.AlignNone Nothing</span>
<span class="lineno"> 118 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 119 </span><span class="spaces"> </span><span class="nottickedoff">target = pRootDirectory &lt;/&gt; encodeInt hashPath &lt;.&gt; takeExtension path</span>
<span class="lineno"> 120 </span><span class="spaces"> </span><span class="nottickedoff">hashPath = hash path</span></span>
<span class="lineno"> 121 </span>
<span class="lineno"> 122 </span>cacheImage :: (PngSavable pixel, Hashable a) =&gt; a -&gt; Image pixel -&gt; FilePath
<span class="lineno"> 123 </span><span class="decl"><span class="nottickedoff">cacheImage key gen = unsafePerformIO $ cacheFile template $ \path -&gt;</span>
<span class="lineno"> 124 </span><span class="spaces"> </span><span class="nottickedoff">writePng path gen</span>
<span class="lineno"> 125 </span><span class="spaces"> </span><span class="nottickedoff">where template = encodeInt (hash key) &lt;.&gt; &quot;png&quot;</span></span>
<span class="lineno"> 126 </span>
<span class="lineno"> 127 </span>-- Warning: Caching svg elements with links to external objects does
<span class="lineno"> 128 </span>-- not work. 2020-06-01
<span class="lineno"> 129 </span>prerenderSvgFile :: Hashable a =&gt; a -&gt; Width -&gt; Height -&gt; SVG -&gt; FilePath
<span class="lineno"> 130 </span><span class="decl"><span class="nottickedoff">prerenderSvgFile key width height svg =</span>
<span class="lineno"> 131 </span><span class="spaces"> </span><span class="nottickedoff">unsafePerformIO $ cacheFile template $ \path -&gt; do</span>
<span class="lineno"> 132 </span><span class="spaces"> </span><span class="nottickedoff">let svgPath = replaceExtension path &quot;svg&quot;</span>
<span class="lineno"> 133 </span><span class="spaces"> </span><span class="nottickedoff">writeFile svgPath rendered</span>
<span class="lineno"> 134 </span><span class="spaces"> </span><span class="nottickedoff">engine &lt;- requireRaster pRaster</span>
<span class="lineno"> 135 </span><span class="spaces"> </span><span class="nottickedoff">applyRaster engine svgPath</span>
<span class="lineno"> 136 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 137 </span><span class="spaces"> </span><span class="nottickedoff">template = encodeInt (hash (key, width, height)) &lt;.&gt; &quot;png&quot;</span>
<span class="lineno"> 138 </span><span class="spaces"> </span><span class="nottickedoff">rendered = renderSvg (Just $ Px $ fromIntegral width)</span>
<span class="lineno"> 139 </span><span class="spaces"> </span><span class="nottickedoff">(Just $ Px $ fromIntegral height)</span>
<span class="lineno"> 140 </span><span class="spaces"> </span><span class="nottickedoff">svg</span></span>
<span class="lineno"> 141 </span>
<span class="lineno"> 142 </span>prerenderSvg :: Hashable a =&gt; a -&gt; SVG -&gt; SVG
<span class="lineno"> 143 </span><span class="decl"><span class="nottickedoff">prerenderSvg key =</span>
<span class="lineno"> 144 </span><span class="spaces"> </span><span class="nottickedoff">mkImage screenWidth screenHeight . prerenderSvgFile key pWidth pHeight</span></span>
<span class="lineno"> 145 </span>
<span class="lineno"> 146 </span>
<span class="lineno"> 147 </span>{-# INLINE embedImage #-}
<span class="lineno"> 148 </span>-- | Embed an in-memory PNG image. Note, the pixel size of the image
<span class="lineno"> 149 </span>-- is used as the dimensions. As such, embedding a 100x100 PNG will
<span class="lineno"> 150 </span>-- result in an image 100 units wide and 100 units high. Consider
<span class="lineno"> 151 </span>-- using with 'scaleToSize'.
<span class="lineno"> 152 </span>embedImage :: PngSavable a =&gt; Image a -&gt; SVG
<span class="lineno"> 153 </span><span class="decl"><span class="nottickedoff">embedImage img = embedPng width height (encodePng img)</span>
<span class="lineno"> 154 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 155 </span><span class="spaces"> </span><span class="nottickedoff">width = fromIntegral $ imageWidth img</span>
<span class="lineno"> 156 </span><span class="spaces"> </span><span class="nottickedoff">height = fromIntegral $ imageHeight img</span></span>
<span class="lineno"> 157 </span>
<span class="lineno"> 158 </span>-- | Embed in-memory PNG bytestring without parsing it.
<span class="lineno"> 159 </span>embedPng
<span class="lineno"> 160 </span> :: Double -- ^ Width
<span class="lineno"> 161 </span> -&gt; Double -- ^ Height
<span class="lineno"> 162 </span> -&gt; LBS.ByteString -- ^ Raw PNG data
<span class="lineno"> 163 </span> -&gt; SVG
<span class="lineno"> 164 </span>-- embedPng w h png = unsafePerformIO $ do
<span class="lineno"> 165 </span>-- LBS.writeFile path png
<span class="lineno"> 166 </span>-- return $ ImageTree $ defaultSvg
<span class="lineno"> 167 </span>-- &amp; Svg.imageCornerUpperLeft .~ (Svg.Num (-w/2), Svg.Num (-h/2))
<span class="lineno"> 168 </span>-- &amp; Svg.imageWidth .~ Svg.Num w
<span class="lineno"> 169 </span>-- &amp; Svg.imageHeight .~ Svg.Num h
<span class="lineno"> 170 </span>-- &amp; Svg.imageHref .~ (&quot;file://&quot;++path)
<span class="lineno"> 171 </span>-- where
<span class="lineno"> 172 </span>-- path = &quot;/tmp&quot; &lt;/&gt; show (hash png) &lt;.&gt; &quot;png&quot;
<span class="lineno"> 173 </span><span class="decl"><span class="nottickedoff">embedPng w h png =</span>
<span class="lineno"> 174 </span><span class="spaces"> </span><span class="nottickedoff">flipYAxis</span>
<span class="lineno"> 175 </span><span class="spaces"> </span><span class="nottickedoff">$ ImageTree</span>
<span class="lineno"> 176 </span><span class="spaces"> </span><span class="nottickedoff">$ defaultSvg</span>
<span class="lineno"> 177 </span><span class="spaces"> </span><span class="nottickedoff">&amp; Svg.imageCornerUpperLeft</span>
<span class="lineno"> 178 </span><span class="spaces"> </span><span class="nottickedoff">.~ (Svg.Num (-w / 2), Svg.Num (-h / 2))</span>
<span class="lineno"> 179 </span><span class="spaces"> </span><span class="nottickedoff">&amp; Svg.imageWidth</span>
<span class="lineno"> 180 </span><span class="spaces"> </span><span class="nottickedoff">.~ Svg.Num w</span>
<span class="lineno"> 181 </span><span class="spaces"> </span><span class="nottickedoff">&amp; Svg.imageHeight</span>
<span class="lineno"> 182 </span><span class="spaces"> </span><span class="nottickedoff">.~ Svg.Num h</span>
<span class="lineno"> 183 </span><span class="spaces"> </span><span class="nottickedoff">&amp; Svg.imageHref</span>
<span class="lineno"> 184 </span><span class="spaces"> </span><span class="nottickedoff">.~ (&quot;data:image/png;base64,&quot; ++ imgData)</span>
<span class="lineno"> 185 </span><span class="spaces"> </span><span class="nottickedoff">where imgData = LBS.unpack $ Base64.encode png</span></span>
<span class="lineno"> 186 </span>
<span class="lineno"> 187 </span>
<span class="lineno"> 188 </span>{-# INLINE embedDynamicImage #-}
<span class="lineno"> 189 </span>-- | Embed an in-memory image. Note, the pixel size of the image
<span class="lineno"> 190 </span>-- is used as the dimensions. As such, embedding a 100x100 image will
<span class="lineno"> 191 </span>-- result in an image 100 units wide and 100 units high. Consider
<span class="lineno"> 192 </span>-- using with 'scaleToSize'.
<span class="lineno"> 193 </span>embedDynamicImage :: DynamicImage -&gt; SVG
<span class="lineno"> 194 </span><span class="decl"><span class="nottickedoff">embedDynamicImage img = embedPng width height imgData</span>
<span class="lineno"> 195 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 196 </span><span class="spaces"> </span><span class="nottickedoff">width = fromIntegral $ dynamicMap imageWidth img</span>
<span class="lineno"> 197 </span><span class="spaces"> </span><span class="nottickedoff">height = fromIntegral $ dynamicMap imageHeight img</span>
<span class="lineno"> 198 </span><span class="spaces"> </span><span class="nottickedoff">imgData = case encodeDynamicPng img of</span>
<span class="lineno"> 199 </span><span class="spaces"> </span><span class="nottickedoff">Left err -&gt; error err</span>
<span class="lineno"> 200 </span><span class="spaces"> </span><span class="nottickedoff">Right dat -&gt; dat</span></span>
<span class="lineno"> 201 </span>
<span class="lineno"> 202 </span>-- embedImageFile :: FilePath -&gt; Tree
<span class="lineno"> 203 </span>-- embedImageFile path = unsafePerformIO $ do
<span class="lineno"> 204 </span>-- png &lt;- B.readFile path
<span class="lineno"> 205 </span>-- case decodePng png of
<span class="lineno"> 206 </span>-- Left{} -&gt; error &quot;bad image&quot;
<span class="lineno"> 207 </span>-- Right img -&gt; return $
<span class="lineno"> 208 </span>-- let width = fromIntegral $ dynamicMap imageWidth img
<span class="lineno"> 209 </span>-- height = fromIntegral $ dynamicMap imageHeight img in
<span class="lineno"> 210 </span>-- ImageTree $ defaultSvg
<span class="lineno"> 211 </span>-- &amp; Svg.imageCornerUpperLeft .~ (Svg.Num (-width/2), Svg.Num (-height/2))
<span class="lineno"> 212 </span>-- &amp; Svg.imageWidth .~ Svg.Num width
<span class="lineno"> 213 </span>-- &amp; Svg.imageHeight .~ Svg.Num height
<span class="lineno"> 214 </span>-- &amp; Svg.imageHref .~ (&quot;file://&quot; ++ path)
<span class="lineno"> 215 </span>
<span class="lineno"> 216 </span>
<span class="lineno"> 217 </span>-- | Convert an SVG object to a pixel-based image. The default resolution
<span class="lineno"> 218 </span>-- is 2560x1440. See also 'rasterSized'. Multiple raster engines are supported
<span class="lineno"> 219 </span>-- and are selected using the '--raster' flag in the driver.
<span class="lineno"> 220 </span>raster :: SVG -&gt; DynamicImage
<span class="lineno"> 221 </span><span class="decl"><span class="nottickedoff">raster = rasterSized 2560 1440</span></span>
<span class="lineno"> 222 </span>
<span class="lineno"> 223 </span>-- | Convert an SVG object to a pixel-based image.
<span class="lineno"> 224 </span>rasterSized
<span class="lineno"> 225 </span> :: Width -- ^ X resolution in pixels
<span class="lineno"> 226 </span> -&gt; Height -- ^ Y resolution in pixels
<span class="lineno"> 227 </span> -&gt; SVG -- ^ SVG object
<span class="lineno"> 228 </span> -&gt; DynamicImage
<span class="lineno"> 229 </span><span class="decl"><span class="nottickedoff">rasterSized w h svg = unsafePerformIO $ do</span>
<span class="lineno"> 230 </span><span class="spaces"> </span><span class="nottickedoff">png &lt;- B.readFile (svgAsPngFile' w h svg)</span>
<span class="lineno"> 231 </span><span class="spaces"> </span><span class="nottickedoff">case decodePng png of</span>
<span class="lineno"> 232 </span><span class="spaces"> </span><span class="nottickedoff">Left{} -&gt; error &quot;bad image&quot;</span>
<span class="lineno"> 233 </span><span class="spaces"> </span><span class="nottickedoff">Right img -&gt; return img</span></span>
<span class="lineno"> 234 </span>
<span class="lineno"> 235 </span>-- | Use 'potrace' to trace edges in a raster image and convert them to SVG polygons.
<span class="lineno"> 236 </span>vectorize :: FilePath -&gt; SVG
<span class="lineno"> 237 </span><span class="decl"><span class="nottickedoff">vectorize = vectorize_ []</span></span>
<span class="lineno"> 238 </span>
<span class="lineno"> 239 </span>-- | Same as 'vectorize' but takes a list of arguments for 'potrace'.
<span class="lineno"> 240 </span>vectorize_ :: [String] -&gt; FilePath -&gt; SVG
<span class="lineno"> 241 </span><span class="decl"><span class="nottickedoff">vectorize_ _ path | pNoExternals = mkText $ T.pack path</span>
<span class="lineno"> 242 </span><span class="spaces"></span><span class="nottickedoff">vectorize_ args path = unsafePerformIO $ do</span>
<span class="lineno"> 243 </span><span class="spaces"> </span><span class="nottickedoff">root &lt;- getXdgDirectory XdgCache &quot;reanimate&quot;</span>
<span class="lineno"> 244 </span><span class="spaces"> </span><span class="nottickedoff">createDirectoryIfMissing True root</span>
<span class="lineno"> 245 </span><span class="spaces"> </span><span class="nottickedoff">let svgPath = root &lt;/&gt; encodeInt key &lt;.&gt; &quot;svg&quot;</span>
<span class="lineno"> 246 </span><span class="spaces"> </span><span class="nottickedoff">hit &lt;- doesFileExist svgPath</span>
<span class="lineno"> 247 </span><span class="spaces"> </span><span class="nottickedoff">unless hit $ withSystemTempFile &quot;file.svg&quot; $ \tmpSvgPath svgH -&gt;</span>
<span class="lineno"> 248 </span><span class="spaces"> </span><span class="nottickedoff">withSystemTempFile &quot;file.bmp&quot; $ \tmpBmpPath bmpH -&gt; do</span>
<span class="lineno"> 249 </span><span class="spaces"> </span><span class="nottickedoff">hClose svgH</span>
<span class="lineno"> 250 </span><span class="spaces"> </span><span class="nottickedoff">hClose bmpH</span>
<span class="lineno"> 251 </span><span class="spaces"> </span><span class="nottickedoff">potrace &lt;- requireExecutable &quot;potrace&quot;</span>
<span class="lineno"> 252 </span><span class="spaces"> </span><span class="nottickedoff">magick &lt;- requireExecutable magickCmd</span>
<span class="lineno"> 253 </span><span class="spaces"> </span><span class="nottickedoff">runCmd magick [path, &quot;-flatten&quot;, tmpBmpPath]</span>
<span class="lineno"> 254 </span><span class="spaces"> </span><span class="nottickedoff">runCmd potrace (args ++ [&quot;--svg&quot;, &quot;--output&quot;, tmpSvgPath, tmpBmpPath])</span>
<span class="lineno"> 255 </span><span class="spaces"> </span><span class="nottickedoff">renameOrCopyFile tmpSvgPath svgPath</span>
<span class="lineno"> 256 </span><span class="spaces"> </span><span class="nottickedoff">svg_data &lt;- B.readFile svgPath</span>
<span class="lineno"> 257 </span><span class="spaces"> </span><span class="nottickedoff">case parseSvgFile svgPath svg_data of</span>
<span class="lineno"> 258 </span><span class="spaces"> </span><span class="nottickedoff">Nothing -&gt; do</span>
<span class="lineno"> 259 </span><span class="spaces"> </span><span class="nottickedoff">removeFile svgPath</span>
<span class="lineno"> 260 </span><span class="spaces"> </span><span class="nottickedoff">error &quot;Malformed svg&quot;</span>
<span class="lineno"> 261 </span><span class="spaces"> </span><span class="nottickedoff">Just svg -&gt; return $ unbox $ replaceUses svg</span>
<span class="lineno"> 262 </span><span class="spaces"> </span><span class="nottickedoff">where key = hash (path, args)</span></span>
<span class="lineno"> 263 </span>
<span class="lineno"> 264 </span>-- imageAsFile :: DynamicImage -&gt; FilePath
<span class="lineno"> 265 </span>-- imageAsFile img
<span class="lineno"> 266 </span>
<span class="lineno"> 267 </span>-- | Convert an SVG object to a pixel-based image and save it to disk, returning
<span class="lineno"> 268 </span>-- the filepath. The default resolution is 2560x1440. See also 'svgAsPngFile''.
<span class="lineno"> 269 </span>-- Multiple raster engines are supported and are selected using the '--raster'
<span class="lineno"> 270 </span>-- flag in the driver.
<span class="lineno"> 271 </span>svgAsPngFile :: SVG -&gt; FilePath
<span class="lineno"> 272 </span><span class="decl"><span class="nottickedoff">svgAsPngFile = svgAsPngFile' width height</span>
<span class="lineno"> 273 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 274 </span><span class="spaces"> </span><span class="nottickedoff">width = 2560</span>
<span class="lineno"> 275 </span><span class="spaces"> </span><span class="nottickedoff">height = width * 9 `div` 16</span></span>
<span class="lineno"> 276 </span>
<span class="lineno"> 277 </span>-- | Convert an SVG object to a pixel-based image and save it to disk, returning
<span class="lineno"> 278 </span>-- the filepath.
<span class="lineno"> 279 </span>svgAsPngFile'
<span class="lineno"> 280 </span> :: Width -- ^ Width
<span class="lineno"> 281 </span> -&gt; Height -- ^ Height
<span class="lineno"> 282 </span> -&gt; SVG -- ^ SVG object
<span class="lineno"> 283 </span> -&gt; FilePath
<span class="lineno"> 284 </span><span class="decl"><span class="nottickedoff">svgAsPngFile' _ _ _ | pNoExternals = &quot;/svgAsPngFile/has/been/disabled&quot;</span>
<span class="lineno"> 285 </span><span class="spaces"></span><span class="nottickedoff">svgAsPngFile' width height svg =</span>
<span class="lineno"> 286 </span><span class="spaces"> </span><span class="nottickedoff">unsafePerformIO $ cacheFile template $ \pngPath -&gt; do</span>
<span class="lineno"> 287 </span><span class="spaces"> </span><span class="nottickedoff">let svgPath = replaceExtension pngPath &quot;svg&quot;</span>
<span class="lineno"> 288 </span><span class="spaces"> </span><span class="nottickedoff">writeFile svgPath rendered</span>
<span class="lineno"> 289 </span><span class="spaces"> </span><span class="nottickedoff">engine &lt;- requireRaster pRaster</span>
<span class="lineno"> 290 </span><span class="spaces"> </span><span class="nottickedoff">applyRaster engine svgPath</span>
<span class="lineno"> 291 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 292 </span><span class="spaces"> </span><span class="nottickedoff">template = encodeInt (hash rendered) &lt;.&gt; &quot;png&quot;</span>
<span class="lineno"> 293 </span><span class="spaces"> </span><span class="nottickedoff">rendered = renderSvg (Just $ Px $ fromIntegral width)</span>
<span class="lineno"> 294 </span><span class="spaces"> </span><span class="nottickedoff">(Just $ Px $ fromIntegral height)</span>
<span class="lineno"> 295 </span><span class="spaces"> </span><span class="nottickedoff">svg</span></span>
</pre>
</body>
</html>

View file

@ -0,0 +1,390 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style type="text/css">
span.lineno { color: white; background: #aaaaaa; border-right: solid white 12px }
span.nottickedoff { background: yellow}
span.istickedoff { background: white }
span.tickonlyfalse { margin: -1px; border: 1px solid #f20913; background: #f20913 }
span.tickonlytrue { margin: -1px; border: 1px solid #60de51; background: #60de51 }
span.funcount { font-size: small; color: orange; z-index: 2; position: absolute; right: 20 }
span.decl { font-weight: bold }
span.spaces { background: white }
</style>
</head>
<body>
<pre>
<span class="decl"><span class="nottickedoff">never executed</span> <span class="tickonlytrue">always true</span> <span class="tickonlyfalse">always false</span></span>
</pre>
<pre>
<span class="lineno"> 1 </span>{-# LANGUAGE MultiWayIf #-}
<span class="lineno"> 2 </span>module Reanimate.Render
<span class="lineno"> 3 </span> ( render
<span class="lineno"> 4 </span> , renderSvgs
<span class="lineno"> 5 </span> , renderSnippets -- :: Animation -&gt; IO ()
<span class="lineno"> 6 </span> , Format(..)
<span class="lineno"> 7 </span> , Raster(..)
<span class="lineno"> 8 </span> , Width, Height, FPS
<span class="lineno"> 9 </span> , requireRaster -- :: Raster -&gt; IO Raster
<span class="lineno"> 10 </span> , selectRaster -- :: Raster -&gt; IO Raster
<span class="lineno"> 11 </span> , applyRaster -- :: Raster -&gt; FilePath -&gt; IO ()
<span class="lineno"> 12 </span> ) where
<span class="lineno"> 13 </span>
<span class="lineno"> 14 </span>import Control.Concurrent
<span class="lineno"> 15 </span>import Control.Exception
<span class="lineno"> 16 </span>import Control.Monad (forM_, forever, unless, void, when)
<span class="lineno"> 17 </span>import Data.Either
<span class="lineno"> 18 </span>import Data.Function
<span class="lineno"> 19 </span>import qualified Data.Text as T
<span class="lineno"> 20 </span>import qualified Data.Text.IO as T
<span class="lineno"> 21 </span>import Data.Time
<span class="lineno"> 22 </span>import Graphics.SvgTree (Number (..))
<span class="lineno"> 23 </span>import Numeric
<span class="lineno"> 24 </span>import Reanimate.Animation
<span class="lineno"> 25 </span>import Reanimate.Driver.Check
<span class="lineno"> 26 </span>import Reanimate.Driver.Magick
<span class="lineno"> 27 </span>import Reanimate.Misc
<span class="lineno"> 28 </span>import Reanimate.Parameters
<span class="lineno"> 29 </span>import System.Console.ANSI.Codes
<span class="lineno"> 30 </span>import System.Exit
<span class="lineno"> 31 </span>import System.FileLock (withTryFileLock, SharedExclusive(..), unlockFile)
<span class="lineno"> 32 </span>import System.Directory
<span class="lineno"> 33 </span>import System.FilePath (replaceExtension, (&lt;.&gt;), (&lt;/&gt;))
<span class="lineno"> 34 </span>import System.IO
<span class="lineno"> 35 </span>import Text.Printf (printf)
<span class="lineno"> 36 </span>
<span class="lineno"> 37 </span>idempotentFile :: FilePath -&gt; IO () -&gt; IO ()
<span class="lineno"> 38 </span><span class="decl"><span class="nottickedoff">idempotentFile path action = do</span>
<span class="lineno"> 39 </span><span class="spaces"> </span><span class="nottickedoff">_ &lt;- withTryFileLock lockFile Exclusive $ \lock -&gt; do</span>
<span class="lineno"> 40 </span><span class="spaces"> </span><span class="nottickedoff">haveFile &lt;- doesFileExist path</span>
<span class="lineno"> 41 </span><span class="spaces"> </span><span class="nottickedoff">unless haveFile action</span>
<span class="lineno"> 42 </span><span class="spaces"> </span><span class="nottickedoff">unlockFile lock</span>
<span class="lineno"> 43 </span><span class="spaces"> </span><span class="nottickedoff">_ &lt;- try (removeFile lockFile) :: IO (Either SomeException ())</span>
<span class="lineno"> 44 </span><span class="spaces"> </span><span class="nottickedoff">return ()</span>
<span class="lineno"> 45 </span><span class="spaces"> </span><span class="nottickedoff">return ()</span>
<span class="lineno"> 46 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 47 </span><span class="spaces"> </span><span class="nottickedoff">lockFile = path &lt;.&gt; &quot;lock&quot;</span></span>
<span class="lineno"> 48 </span>
<span class="lineno"> 49 </span>renderSvgs :: FilePath -&gt; Int -&gt; Bool -&gt; Animation -&gt; IO ()
<span class="lineno"> 50 </span><span class="decl"><span class="nottickedoff">renderSvgs folder offset _prettyPrint ani = do</span>
<span class="lineno"> 51 </span><span class="spaces"> </span><span class="nottickedoff">print frameCount</span>
<span class="lineno"> 52 </span><span class="spaces"> </span><span class="nottickedoff">lock &lt;- newMVar ()</span>
<span class="lineno"> 53 </span><span class="spaces"></span><span class="nottickedoff"></span>
<span class="lineno"> 54 </span><span class="spaces"> </span><span class="nottickedoff">handle errHandler $ concurrentForM_ (frameOrder rate frameCount) $ \nth' -&gt; do</span>
<span class="lineno"> 55 </span><span class="spaces"> </span><span class="nottickedoff">let nth = (nth'+offset) `mod` frameCount</span>
<span class="lineno"> 56 </span><span class="spaces"> </span><span class="nottickedoff">now = (duration ani / (fromIntegral frameCount - 1)) * fromIntegral nth</span>
<span class="lineno"> 57 </span><span class="spaces"> </span><span class="nottickedoff">frame = frameAt (if frameCount &lt;= 1 then 0 else now) ani</span>
<span class="lineno"> 58 </span><span class="spaces"> </span><span class="nottickedoff">svg = renderSvg Nothing Nothing frame</span>
<span class="lineno"> 59 </span><span class="spaces"> </span><span class="nottickedoff">path = folder &lt;/&gt; show nth &lt;.&gt; &quot;svg&quot;</span>
<span class="lineno"> 60 </span><span class="spaces"></span><span class="nottickedoff"></span>
<span class="lineno"> 61 </span><span class="spaces"> </span><span class="nottickedoff">idempotentFile path $ writeFile path svg</span>
<span class="lineno"> 62 </span><span class="spaces"> </span><span class="nottickedoff">withMVar lock $ \_ -&gt; do</span>
<span class="lineno"> 63 </span><span class="spaces"> </span><span class="nottickedoff">print nth</span>
<span class="lineno"> 64 </span><span class="spaces"> </span><span class="nottickedoff">hFlush stdout</span>
<span class="lineno"> 65 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 66 </span><span class="spaces"> </span><span class="nottickedoff">rate = 60</span>
<span class="lineno"> 67 </span><span class="spaces"> </span><span class="nottickedoff">frameCount = round (duration ani * fromIntegral rate) :: Int</span>
<span class="lineno"> 68 </span><span class="spaces"> </span><span class="nottickedoff">errHandler (ErrorCall msg) = do</span>
<span class="lineno"> 69 </span><span class="spaces"> </span><span class="nottickedoff">hPutStrLn stderr msg</span>
<span class="lineno"> 70 </span><span class="spaces"> </span><span class="nottickedoff">exitWith (ExitFailure 1)</span></span>
<span class="lineno"> 71 </span>
<span class="lineno"> 72 </span>-- XXX: Merge with 'renderSvgs'
<span class="lineno"> 73 </span>renderSnippets :: Animation -&gt; IO ()
<span class="lineno"> 74 </span><span class="decl"><span class="istickedoff">renderSnippets ani = forM_ [0 .. frameCount - 1] $ \nth -&gt; do</span>
<span class="lineno"> 75 </span><span class="spaces"> </span><span class="istickedoff">let now = (duration ani / (fromIntegral frameCount - 1)) * fromIntegral nth</span>
<span class="lineno"> 76 </span><span class="spaces"> </span><span class="istickedoff">frame = frameAt now ani</span>
<span class="lineno"> 77 </span><span class="spaces"> </span><span class="istickedoff">svg = renderSvg Nothing Nothing frame</span>
<span class="lineno"> 78 </span><span class="spaces"> </span><span class="istickedoff">putStr (show nth)</span>
<span class="lineno"> 79 </span><span class="spaces"> </span><span class="istickedoff">T.putStrLn $ T.concat . T.lines . T.pack $ svg</span>
<span class="lineno"> 80 </span><span class="spaces"> </span><span class="istickedoff">where frameCount = 10 :: Integer</span></span>
<span class="lineno"> 81 </span>
<span class="lineno"> 82 </span>frameOrder :: Int -&gt; Int -&gt; [Int]
<span class="lineno"> 83 </span><span class="decl"><span class="nottickedoff">frameOrder fps nFrames = worker [] fps</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">worker _seen 0 = []</span>
<span class="lineno"> 86 </span><span class="spaces"> </span><span class="nottickedoff">worker seen nthFrame = filterFrameList seen nthFrame nFrames</span>
<span class="lineno"> 87 </span><span class="spaces"> </span><span class="nottickedoff">++ worker (nthFrame : seen) (nthFrame `div` 2)</span></span>
<span class="lineno"> 88 </span>
<span class="lineno"> 89 </span>filterFrameList :: [Int] -&gt; Int -&gt; Int -&gt; [Int]
<span class="lineno"> 90 </span><span class="decl"><span class="nottickedoff">filterFrameList seen nthFrame nFrames = filter (not . isSeen)</span>
<span class="lineno"> 91 </span><span class="spaces"> </span><span class="nottickedoff">[0, nthFrame .. nFrames - 1]</span>
<span class="lineno"> 92 </span><span class="spaces"> </span><span class="nottickedoff">where isSeen x = any (\y -&gt; x `mod` y == 0) seen</span></span>
<span class="lineno"> 93 </span>
<span class="lineno"> 94 </span>data Format = RenderMp4 | RenderGif | RenderWebm
<span class="lineno"> 95 </span> deriving (<span class="decl"><span class="nottickedoff">Show</span></span>)
<span class="lineno"> 96 </span>
<span class="lineno"> 97 </span>mp4Arguments :: FPS -&gt; FilePath -&gt; FilePath -&gt; FilePath -&gt; [String]
<span class="lineno"> 98 </span><span class="decl"><span class="nottickedoff">mp4Arguments fps progress template target =</span>
<span class="lineno"> 99 </span><span class="spaces"> </span><span class="nottickedoff">[ &quot;-r&quot;</span>
<span class="lineno"> 100 </span><span class="spaces"> </span><span class="nottickedoff">, show fps</span>
<span class="lineno"> 101 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-i&quot;</span>
<span class="lineno"> 102 </span><span class="spaces"> </span><span class="nottickedoff">, template</span>
<span class="lineno"> 103 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-y&quot;</span>
<span class="lineno"> 104 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-c:v&quot;</span>
<span class="lineno"> 105 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;libx264&quot;</span>
<span class="lineno"> 106 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-vf&quot;</span>
<span class="lineno"> 107 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;fps=&quot; ++ show fps</span>
<span class="lineno"> 108 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-preset&quot;</span>
<span class="lineno"> 109 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;slow&quot;</span>
<span class="lineno"> 110 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-crf&quot;</span>
<span class="lineno"> 111 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;18&quot;</span>
<span class="lineno"> 112 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-movflags&quot;</span>
<span class="lineno"> 113 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;+faststart&quot;</span>
<span class="lineno"> 114 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-progress&quot;</span>
<span class="lineno"> 115 </span><span class="spaces"> </span><span class="nottickedoff">, progress</span>
<span class="lineno"> 116 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-pix_fmt&quot;</span>
<span class="lineno"> 117 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;yuv420p&quot;</span>
<span class="lineno"> 118 </span><span class="spaces"> </span><span class="nottickedoff">, target</span>
<span class="lineno"> 119 </span><span class="spaces"> </span><span class="nottickedoff">]</span></span>
<span class="lineno"> 120 </span>
<span class="lineno"> 121 </span>-- gifArguments :: FPS -&gt; FilePath -&gt; FilePath -&gt; FilePath -&gt; [String]
<span class="lineno"> 122 </span>-- gifArguments fps progress template target =
<span class="lineno"> 123 </span>
<span class="lineno"> 124 </span>render
<span class="lineno"> 125 </span> :: Animation
<span class="lineno"> 126 </span> -&gt; FilePath
<span class="lineno"> 127 </span> -&gt; Raster
<span class="lineno"> 128 </span> -&gt; Format
<span class="lineno"> 129 </span> -&gt; Width
<span class="lineno"> 130 </span> -&gt; Height
<span class="lineno"> 131 </span> -&gt; FPS
<span class="lineno"> 132 </span> -&gt; Bool
<span class="lineno"> 133 </span> -&gt; IO ()
<span class="lineno"> 134 </span><span class="decl"><span class="nottickedoff">render ani target raster format width height fps partial = do</span>
<span class="lineno"> 135 </span><span class="spaces"> </span><span class="nottickedoff">printf &quot;Starting render of animation: %.1f\n&quot; (duration ani)</span>
<span class="lineno"> 136 </span><span class="spaces"> </span><span class="nottickedoff">ffmpeg &lt;- requireExecutable &quot;ffmpeg&quot;</span>
<span class="lineno"> 137 </span><span class="spaces"> </span><span class="nottickedoff">generateFrames raster ani width height fps partial $ \template -&gt;</span>
<span class="lineno"> 138 </span><span class="spaces"> </span><span class="nottickedoff">withTempFile &quot;txt&quot; $ \progress -&gt; do</span>
<span class="lineno"> 139 </span><span class="spaces"> </span><span class="nottickedoff">writeFile progress &quot;&quot;</span>
<span class="lineno"> 140 </span><span class="spaces"> </span><span class="nottickedoff">progressH &lt;- openFile progress ReadMode</span>
<span class="lineno"> 141 </span><span class="spaces"> </span><span class="nottickedoff">hSetBuffering progressH NoBuffering</span>
<span class="lineno"> 142 </span><span class="spaces"> </span><span class="nottickedoff">allFinished &lt;- newEmptyMVar</span>
<span class="lineno"> 143 </span><span class="spaces"> </span><span class="nottickedoff">void $ forkIO $ do</span>
<span class="lineno"> 144 </span><span class="spaces"> </span><span class="nottickedoff">progressPrinter &quot;rendered&quot; (animationFrameCount ani fps)</span>
<span class="lineno"> 145 </span><span class="spaces"> </span><span class="nottickedoff">$ \done -&gt; fix $ \loop -&gt; do</span>
<span class="lineno"> 146 </span><span class="spaces"> </span><span class="nottickedoff">eof &lt;- hIsEOF progressH</span>
<span class="lineno"> 147 </span><span class="spaces"> </span><span class="nottickedoff">if eof</span>
<span class="lineno"> 148 </span><span class="spaces"> </span><span class="nottickedoff">then threadDelay 1000000 &gt;&gt; loop</span>
<span class="lineno"> 149 </span><span class="spaces"> </span><span class="nottickedoff">else do</span>
<span class="lineno"> 150 </span><span class="spaces"> </span><span class="nottickedoff">l &lt;- try (hGetLine progressH)</span>
<span class="lineno"> 151 </span><span class="spaces"> </span><span class="nottickedoff">case l of</span>
<span class="lineno"> 152 </span><span class="spaces"> </span><span class="nottickedoff">Left SomeException{} -&gt; return ()</span>
<span class="lineno"> 153 </span><span class="spaces"> </span><span class="nottickedoff">Right str -&gt;</span>
<span class="lineno"> 154 </span><span class="spaces"> </span><span class="nottickedoff">case take 6 str of</span>
<span class="lineno"> 155 </span><span class="spaces"> </span><span class="nottickedoff">&quot;frame=&quot; -&gt; do</span>
<span class="lineno"> 156 </span><span class="spaces"> </span><span class="nottickedoff">void $ swapMVar done (read (drop 6 str))</span>
<span class="lineno"> 157 </span><span class="spaces"> </span><span class="nottickedoff">loop</span>
<span class="lineno"> 158 </span><span class="spaces"> </span><span class="nottickedoff">_ | str == &quot;progress=end&quot; -&gt; return ()</span>
<span class="lineno"> 159 </span><span class="spaces"> </span><span class="nottickedoff">_ -&gt; loop</span>
<span class="lineno"> 160 </span><span class="spaces"> </span><span class="nottickedoff">putMVar allFinished ()</span>
<span class="lineno"> 161 </span><span class="spaces"> </span><span class="nottickedoff">case format of</span>
<span class="lineno"> 162 </span><span class="spaces"> </span><span class="nottickedoff">RenderMp4 -&gt; runCmd ffmpeg (mp4Arguments fps progress template target)</span>
<span class="lineno"> 163 </span><span class="spaces"> </span><span class="nottickedoff">RenderGif -&gt; withTempFile &quot;png&quot; $ \palette -&gt; do</span>
<span class="lineno"> 164 </span><span class="spaces"> </span><span class="nottickedoff">runCmd</span>
<span class="lineno"> 165 </span><span class="spaces"> </span><span class="nottickedoff">ffmpeg</span>
<span class="lineno"> 166 </span><span class="spaces"> </span><span class="nottickedoff">[ &quot;-i&quot;</span>
<span class="lineno"> 167 </span><span class="spaces"> </span><span class="nottickedoff">, template</span>
<span class="lineno"> 168 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-y&quot;</span>
<span class="lineno"> 169 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-vf&quot;</span>
<span class="lineno"> 170 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;fps=&quot;</span>
<span class="lineno"> 171 </span><span class="spaces"> </span><span class="nottickedoff">++ show fps</span>
<span class="lineno"> 172 </span><span class="spaces"> </span><span class="nottickedoff">++ &quot;,scale=&quot;</span>
<span class="lineno"> 173 </span><span class="spaces"> </span><span class="nottickedoff">++ show width</span>
<span class="lineno"> 174 </span><span class="spaces"> </span><span class="nottickedoff">++ &quot;:&quot;</span>
<span class="lineno"> 175 </span><span class="spaces"> </span><span class="nottickedoff">++ show height</span>
<span class="lineno"> 176 </span><span class="spaces"> </span><span class="nottickedoff">++ &quot;:flags=lanczos,palettegen&quot;</span>
<span class="lineno"> 177 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-t&quot;</span>
<span class="lineno"> 178 </span><span class="spaces"> </span><span class="nottickedoff">, showFFloat Nothing (duration ani) &quot;&quot;</span>
<span class="lineno"> 179 </span><span class="spaces"> </span><span class="nottickedoff">, palette</span>
<span class="lineno"> 180 </span><span class="spaces"> </span><span class="nottickedoff">]</span>
<span class="lineno"> 181 </span><span class="spaces"> </span><span class="nottickedoff">runCmd</span>
<span class="lineno"> 182 </span><span class="spaces"> </span><span class="nottickedoff">ffmpeg</span>
<span class="lineno"> 183 </span><span class="spaces"> </span><span class="nottickedoff">[ &quot;-framerate&quot;</span>
<span class="lineno"> 184 </span><span class="spaces"> </span><span class="nottickedoff">, show fps</span>
<span class="lineno"> 185 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-i&quot;</span>
<span class="lineno"> 186 </span><span class="spaces"> </span><span class="nottickedoff">, template</span>
<span class="lineno"> 187 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-y&quot;</span>
<span class="lineno"> 188 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-i&quot;</span>
<span class="lineno"> 189 </span><span class="spaces"> </span><span class="nottickedoff">, palette</span>
<span class="lineno"> 190 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-progress&quot;</span>
<span class="lineno"> 191 </span><span class="spaces"> </span><span class="nottickedoff">, progress</span>
<span class="lineno"> 192 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-filter_complex&quot;</span>
<span class="lineno"> 193 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;fps=&quot;</span>
<span class="lineno"> 194 </span><span class="spaces"> </span><span class="nottickedoff">++ show fps</span>
<span class="lineno"> 195 </span><span class="spaces"> </span><span class="nottickedoff">++ &quot;,scale=&quot;</span>
<span class="lineno"> 196 </span><span class="spaces"> </span><span class="nottickedoff">++ show width</span>
<span class="lineno"> 197 </span><span class="spaces"> </span><span class="nottickedoff">++ &quot;:&quot;</span>
<span class="lineno"> 198 </span><span class="spaces"> </span><span class="nottickedoff">++ show height</span>
<span class="lineno"> 199 </span><span class="spaces"> </span><span class="nottickedoff">++ &quot;:flags=lanczos[x];[x][1:v]paletteuse&quot;</span>
<span class="lineno"> 200 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-t&quot;</span>
<span class="lineno"> 201 </span><span class="spaces"> </span><span class="nottickedoff">, showFFloat Nothing (duration ani) &quot;&quot;</span>
<span class="lineno"> 202 </span><span class="spaces"> </span><span class="nottickedoff">, target</span>
<span class="lineno"> 203 </span><span class="spaces"> </span><span class="nottickedoff">]</span>
<span class="lineno"> 204 </span><span class="spaces"> </span><span class="nottickedoff">RenderWebm -&gt; runCmd</span>
<span class="lineno"> 205 </span><span class="spaces"> </span><span class="nottickedoff">ffmpeg</span>
<span class="lineno"> 206 </span><span class="spaces"> </span><span class="nottickedoff">[ &quot;-r&quot;</span>
<span class="lineno"> 207 </span><span class="spaces"> </span><span class="nottickedoff">, show fps</span>
<span class="lineno"> 208 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-i&quot;</span>
<span class="lineno"> 209 </span><span class="spaces"> </span><span class="nottickedoff">, template</span>
<span class="lineno"> 210 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-y&quot;</span>
<span class="lineno"> 211 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-progress&quot;</span>
<span class="lineno"> 212 </span><span class="spaces"> </span><span class="nottickedoff">, progress</span>
<span class="lineno"> 213 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-c:v&quot;</span>
<span class="lineno"> 214 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;libvpx-vp9&quot;</span>
<span class="lineno"> 215 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;-vf&quot;</span>
<span class="lineno"> 216 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;fps=&quot; ++ show fps</span>
<span class="lineno"> 217 </span><span class="spaces"> </span><span class="nottickedoff">, target</span>
<span class="lineno"> 218 </span><span class="spaces"> </span><span class="nottickedoff">]</span>
<span class="lineno"> 219 </span><span class="spaces"> </span><span class="nottickedoff">takeMVar allFinished</span></span>
<span class="lineno"> 220 </span>
<span class="lineno"> 221 </span>---------------------------------------------------------------------------------
<span class="lineno"> 222 </span>-- Helpers
<span class="lineno"> 223 </span>
<span class="lineno"> 224 </span>progressPrinter :: String -&gt; Int -&gt; (MVar Int -&gt; IO ()) -&gt; IO ()
<span class="lineno"> 225 </span><span class="decl"><span class="nottickedoff">progressPrinter typeName maxCount action = do</span>
<span class="lineno"> 226 </span><span class="spaces"> </span><span class="nottickedoff">printf &quot;\rFrames %s: 0/%d&quot; typeName maxCount</span>
<span class="lineno"> 227 </span><span class="spaces"> </span><span class="nottickedoff">putStr $ clearFromCursorToLineEndCode ++ &quot;\r&quot;</span>
<span class="lineno"> 228 </span><span class="spaces"> </span><span class="nottickedoff">done &lt;- newMVar (0 :: Int)</span>
<span class="lineno"> 229 </span><span class="spaces"> </span><span class="nottickedoff">start &lt;- getCurrentTime</span>
<span class="lineno"> 230 </span><span class="spaces"> </span><span class="nottickedoff">let bgThread = forever $ do</span>
<span class="lineno"> 231 </span><span class="spaces"> </span><span class="nottickedoff">nDone &lt;- readMVar done</span>
<span class="lineno"> 232 </span><span class="spaces"> </span><span class="nottickedoff">now &lt;- getCurrentTime</span>
<span class="lineno"> 233 </span><span class="spaces"> </span><span class="nottickedoff">let spent = diffUTCTime now start</span>
<span class="lineno"> 234 </span><span class="spaces"> </span><span class="nottickedoff">remaining =</span>
<span class="lineno"> 235 </span><span class="spaces"> </span><span class="nottickedoff">(spent / (fromIntegral nDone / fromIntegral maxCount)) - spent</span>
<span class="lineno"> 236 </span><span class="spaces"> </span><span class="nottickedoff">printf &quot;\rFrames %s: %d/%d&quot; typeName nDone maxCount</span>
<span class="lineno"> 237 </span><span class="spaces"> </span><span class="nottickedoff">putStr $ &quot;, time spent: &quot; ++ ppDiff spent</span>
<span class="lineno"> 238 </span><span class="spaces"> </span><span class="nottickedoff">unless (nDone == 0) $ do</span>
<span class="lineno"> 239 </span><span class="spaces"> </span><span class="nottickedoff">putStr $ &quot;, time remaining: &quot; ++ ppDiff remaining</span>
<span class="lineno"> 240 </span><span class="spaces"> </span><span class="nottickedoff">putStr $ &quot;, total time: &quot; ++ ppDiff (remaining + spent)</span>
<span class="lineno"> 241 </span><span class="spaces"> </span><span class="nottickedoff">putStr $ clearFromCursorToLineEndCode ++ &quot;\r&quot;</span>
<span class="lineno"> 242 </span><span class="spaces"> </span><span class="nottickedoff">hFlush stdout</span>
<span class="lineno"> 243 </span><span class="spaces"> </span><span class="nottickedoff">threadDelay 1000000</span>
<span class="lineno"> 244 </span><span class="spaces"> </span><span class="nottickedoff">withBackgroundThread bgThread $ action done</span>
<span class="lineno"> 245 </span><span class="spaces"> </span><span class="nottickedoff">now &lt;- getCurrentTime</span>
<span class="lineno"> 246 </span><span class="spaces"> </span><span class="nottickedoff">let spent = diffUTCTime now start</span>
<span class="lineno"> 247 </span><span class="spaces"> </span><span class="nottickedoff">printf &quot;\rFrames %s: %d/%d&quot; typeName maxCount maxCount</span>
<span class="lineno"> 248 </span><span class="spaces"> </span><span class="nottickedoff">putStr $ &quot;, time spent: &quot; ++ ppDiff spent</span>
<span class="lineno"> 249 </span><span class="spaces"> </span><span class="nottickedoff">putStr $ clearFromCursorToLineEndCode ++ &quot;\n&quot;</span></span>
<span class="lineno"> 250 </span>
<span class="lineno"> 251 </span>animationFrameCount :: Animation -&gt; FPS -&gt; Int
<span class="lineno"> 252 </span><span class="decl"><span class="nottickedoff">animationFrameCount ani rate = round (duration ani * fromIntegral rate) :: Int</span></span>
<span class="lineno"> 253 </span>
<span class="lineno"> 254 </span>generateFrames
<span class="lineno"> 255 </span> :: Raster -&gt; Animation -&gt; Width -&gt; Height -&gt; FPS -&gt; Bool -&gt; (FilePath -&gt; IO a) -&gt; IO a
<span class="lineno"> 256 </span><span class="decl"><span class="nottickedoff">generateFrames raster ani width_ height_ rate partial action = withTempDir $ \tmp -&gt; do</span>
<span class="lineno"> 257 </span><span class="spaces"> </span><span class="nottickedoff">let frameName nth = tmp &lt;/&gt; printf nameTemplate nth</span>
<span class="lineno"> 258 </span><span class="spaces"> </span><span class="nottickedoff">setRootDirectory tmp</span>
<span class="lineno"> 259 </span><span class="spaces"> </span><span class="nottickedoff">progressPrinter &quot;generated&quot; frameCount</span>
<span class="lineno"> 260 </span><span class="spaces"> </span><span class="nottickedoff">$ \done -&gt; handle h $ concurrentForM_ frames $ \n -&gt; do</span>
<span class="lineno"> 261 </span><span class="spaces"> </span><span class="nottickedoff">writeFile (frameName n) $ renderSvg width height $ nthFrame n</span>
<span class="lineno"> 262 </span><span class="spaces"> </span><span class="nottickedoff">modifyMVar_ done $ \nDone -&gt; return (nDone + 1)</span>
<span class="lineno"> 263 </span><span class="spaces"></span><span class="nottickedoff"></span>
<span class="lineno"> 264 </span><span class="spaces"> </span><span class="nottickedoff">when (isValidRaster raster)</span>
<span class="lineno"> 265 </span><span class="spaces"> </span><span class="nottickedoff">$ progressPrinter &quot;rastered&quot; frameCount</span>
<span class="lineno"> 266 </span><span class="spaces"> </span><span class="nottickedoff">$ \done -&gt; handle h $ concurrentForM_ frames $ \n -&gt; do</span>
<span class="lineno"> 267 </span><span class="spaces"> </span><span class="nottickedoff">applyRaster raster (frameName n)</span>
<span class="lineno"> 268 </span><span class="spaces"> </span><span class="nottickedoff">modifyMVar_ done $ \nDone -&gt; return (nDone + 1)</span>
<span class="lineno"> 269 </span><span class="spaces"></span><span class="nottickedoff"></span>
<span class="lineno"> 270 </span><span class="spaces"> </span><span class="nottickedoff">action (tmp &lt;/&gt; rasterTemplate raster)</span>
<span class="lineno"> 271 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 272 </span><span class="spaces"> </span><span class="nottickedoff">isValidRaster RasterNone = False</span>
<span class="lineno"> 273 </span><span class="spaces"> </span><span class="nottickedoff">isValidRaster RasterAuto = False</span>
<span class="lineno"> 274 </span><span class="spaces"> </span><span class="nottickedoff">isValidRaster _ = True</span>
<span class="lineno"> 275 </span><span class="spaces"></span><span class="nottickedoff"></span>
<span class="lineno"> 276 </span><span class="spaces"> </span><span class="nottickedoff">width = Just $ Px $ fromIntegral width_</span>
<span class="lineno"> 277 </span><span class="spaces"> </span><span class="nottickedoff">height = Just $ Px $ fromIntegral height_</span>
<span class="lineno"> 278 </span><span class="spaces"> </span><span class="nottickedoff">h UserInterrupt | partial = do</span>
<span class="lineno"> 279 </span><span class="spaces"> </span><span class="nottickedoff">hPutStrLn</span>
<span class="lineno"> 280 </span><span class="spaces"> </span><span class="nottickedoff">stderr</span>
<span class="lineno"> 281 </span><span class="spaces"> </span><span class="nottickedoff">&quot;\nCtrl-C detected. Trying to generate video with available frames. \</span>
<span class="lineno"> 282 </span><span class="spaces"> </span><span class="nottickedoff">\Hit ctrl-c again to abort.&quot;</span>
<span class="lineno"> 283 </span><span class="spaces"> </span><span class="nottickedoff">return ()</span>
<span class="lineno"> 284 </span><span class="spaces"> </span><span class="nottickedoff">h other = throwIO other</span>
<span class="lineno"> 285 </span><span class="spaces"> </span><span class="nottickedoff">-- frames = [0..frameCount-1]</span>
<span class="lineno"> 286 </span><span class="spaces"> </span><span class="nottickedoff">frames = frameOrder rate frameCount</span>
<span class="lineno"> 287 </span><span class="spaces"> </span><span class="nottickedoff">nthFrame nth = frameAt (recip (fromIntegral rate) * fromIntegral nth) ani</span>
<span class="lineno"> 288 </span><span class="spaces"> </span><span class="nottickedoff">frameCount = animationFrameCount ani rate</span>
<span class="lineno"> 289 </span><span class="spaces"> </span><span class="nottickedoff">nameTemplate :: String</span>
<span class="lineno"> 290 </span><span class="spaces"> </span><span class="nottickedoff">nameTemplate = &quot;render-%05d.svg&quot;</span></span>
<span class="lineno"> 291 </span>
<span class="lineno"> 292 </span>withBackgroundThread :: IO () -&gt; IO a -&gt; IO a
<span class="lineno"> 293 </span><span class="decl"><span class="nottickedoff">withBackgroundThread t = bracket (forkIO t) killThread . const</span></span>
<span class="lineno"> 294 </span>
<span class="lineno"> 295 </span>ppDiff :: NominalDiffTime -&gt; String
<span class="lineno"> 296 </span><span class="decl"><span class="nottickedoff">ppDiff diff | hours == 0 &amp;&amp; mins == 0 = show secs ++ &quot;s&quot;</span>
<span class="lineno"> 297 </span><span class="spaces"> </span><span class="nottickedoff">| hours == 0 = printf &quot;%.2d:%.2d&quot; mins secs</span>
<span class="lineno"> 298 </span><span class="spaces"> </span><span class="nottickedoff">| otherwise = printf &quot;%.2d:%.2d:%.2d&quot; hours mins secs</span>
<span class="lineno"> 299 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 300 </span><span class="spaces"> </span><span class="nottickedoff">(osecs, secs) = round diff `divMod` (60 :: Int)</span>
<span class="lineno"> 301 </span><span class="spaces"> </span><span class="nottickedoff">(hours, mins) = osecs `divMod` 60</span></span>
<span class="lineno"> 302 </span>
<span class="lineno"> 303 </span>rasterTemplate :: Raster -&gt; String
<span class="lineno"> 304 </span><span class="decl"><span class="nottickedoff">rasterTemplate RasterNone = &quot;render-%05d.svg&quot;</span>
<span class="lineno"> 305 </span><span class="spaces"></span><span class="nottickedoff">rasterTemplate RasterAuto = &quot;render-%05d.svg&quot;</span>
<span class="lineno"> 306 </span><span class="spaces"></span><span class="nottickedoff">rasterTemplate _ = &quot;render-%05d.png&quot;</span></span>
<span class="lineno"> 307 </span>
<span class="lineno"> 308 </span>requireRaster :: Raster -&gt; IO Raster
<span class="lineno"> 309 </span><span class="decl"><span class="nottickedoff">requireRaster raster = do</span>
<span class="lineno"> 310 </span><span class="spaces"> </span><span class="nottickedoff">raster' &lt;- selectRaster (if raster == RasterNone then RasterAuto else raster)</span>
<span class="lineno"> 311 </span><span class="spaces"> </span><span class="nottickedoff">case raster' of</span>
<span class="lineno"> 312 </span><span class="spaces"> </span><span class="nottickedoff">RasterNone -&gt; do</span>
<span class="lineno"> 313 </span><span class="spaces"> </span><span class="nottickedoff">hPutStrLn</span>
<span class="lineno"> 314 </span><span class="spaces"> </span><span class="nottickedoff">stderr</span>
<span class="lineno"> 315 </span><span class="spaces"> </span><span class="nottickedoff">&quot;Raster required but none could be found. \</span>
<span class="lineno"> 316 </span><span class="spaces"> </span><span class="nottickedoff">\Please install either inkscape, imagemagick, or rsvg-convert.&quot;</span>
<span class="lineno"> 317 </span><span class="spaces"> </span><span class="nottickedoff">exitWith (ExitFailure 1)</span>
<span class="lineno"> 318 </span><span class="spaces"> </span><span class="nottickedoff">_ -&gt; pure raster'</span></span>
<span class="lineno"> 319 </span>
<span class="lineno"> 320 </span>selectRaster :: Raster -&gt; IO Raster
<span class="lineno"> 321 </span><span class="decl"><span class="nottickedoff">selectRaster RasterAuto = do</span>
<span class="lineno"> 322 </span><span class="spaces"> </span><span class="nottickedoff">rsvg &lt;- hasRSvg</span>
<span class="lineno"> 323 </span><span class="spaces"> </span><span class="nottickedoff">ink &lt;- hasInkscape</span>
<span class="lineno"> 324 </span><span class="spaces"> </span><span class="nottickedoff">magick &lt;- hasMagick</span>
<span class="lineno"> 325 </span><span class="spaces"> </span><span class="nottickedoff">if</span>
<span class="lineno"> 326 </span><span class="spaces"> </span><span class="nottickedoff">| isRight rsvg -&gt; pure RasterRSvg</span>
<span class="lineno"> 327 </span><span class="spaces"> </span><span class="nottickedoff">| isRight ink -&gt; pure RasterInkscape</span>
<span class="lineno"> 328 </span><span class="spaces"> </span><span class="nottickedoff">| isRight magick -&gt; pure RasterMagick</span>
<span class="lineno"> 329 </span><span class="spaces"> </span><span class="nottickedoff">| otherwise -&gt; pure RasterNone</span>
<span class="lineno"> 330 </span><span class="spaces"></span><span class="nottickedoff">selectRaster r = pure r</span></span>
<span class="lineno"> 331 </span>
<span class="lineno"> 332 </span>applyRaster :: Raster -&gt; FilePath -&gt; IO ()
<span class="lineno"> 333 </span><span class="decl"><span class="nottickedoff">applyRaster RasterNone _ = return ()</span>
<span class="lineno"> 334 </span><span class="spaces"></span><span class="nottickedoff">applyRaster RasterAuto _ = return ()</span>
<span class="lineno"> 335 </span><span class="spaces"></span><span class="nottickedoff">applyRaster RasterInkscape path = runCmd</span>
<span class="lineno"> 336 </span><span class="spaces"> </span><span class="nottickedoff">&quot;inkscape&quot;</span>
<span class="lineno"> 337 </span><span class="spaces"> </span><span class="nottickedoff">[ &quot;--without-gui&quot;</span>
<span class="lineno"> 338 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;--file=&quot; ++ path</span>
<span class="lineno"> 339 </span><span class="spaces"> </span><span class="nottickedoff">, &quot;--export-png=&quot; ++ replaceExtension path &quot;png&quot;</span>
<span class="lineno"> 340 </span><span class="spaces"> </span><span class="nottickedoff">]</span>
<span class="lineno"> 341 </span><span class="spaces"></span><span class="nottickedoff">applyRaster RasterRSvg path = runCmd</span>
<span class="lineno"> 342 </span><span class="spaces"> </span><span class="nottickedoff">&quot;rsvg-convert&quot;</span>
<span class="lineno"> 343 </span><span class="spaces"> </span><span class="nottickedoff">[path, &quot;--unlimited&quot;, &quot;--output&quot;, replaceExtension path &quot;png&quot;]</span>
<span class="lineno"> 344 </span><span class="spaces"></span><span class="nottickedoff">applyRaster RasterMagick path =</span>
<span class="lineno"> 345 </span><span class="spaces"> </span><span class="nottickedoff">runCmd magickCmd [path, replaceExtension path &quot;png&quot;]</span></span>
<span class="lineno"> 346 </span>
<span class="lineno"> 347 </span>concurrentForM_ :: [a] -&gt; (a -&gt; IO ()) -&gt; IO ()
<span class="lineno"> 348 </span><span class="decl"><span class="nottickedoff">concurrentForM_ lst action = do</span>
<span class="lineno"> 349 </span><span class="spaces"> </span><span class="nottickedoff">n &lt;- getNumCapabilities</span>
<span class="lineno"> 350 </span><span class="spaces"> </span><span class="nottickedoff">sem &lt;- newQSemN n</span>
<span class="lineno"> 351 </span><span class="spaces"> </span><span class="nottickedoff">eVar &lt;- newEmptyMVar</span>
<span class="lineno"> 352 </span><span class="spaces"> </span><span class="nottickedoff">forM_ lst $ \elt -&gt; do</span>
<span class="lineno"> 353 </span><span class="spaces"> </span><span class="nottickedoff">waitQSemN sem 1</span>
<span class="lineno"> 354 </span><span class="spaces"> </span><span class="nottickedoff">emp &lt;- isEmptyMVar eVar</span>
<span class="lineno"> 355 </span><span class="spaces"> </span><span class="nottickedoff">if emp</span>
<span class="lineno"> 356 </span><span class="spaces"> </span><span class="nottickedoff">then</span>
<span class="lineno"> 357 </span><span class="spaces"> </span><span class="nottickedoff">void</span>
<span class="lineno"> 358 </span><span class="spaces"> </span><span class="nottickedoff">$ forkIO</span>
<span class="lineno"> 359 </span><span class="spaces"> </span><span class="nottickedoff">( catch (action elt) (void . tryPutMVar eVar)</span>
<span class="lineno"> 360 </span><span class="spaces"> </span><span class="nottickedoff">`finally` signalQSemN sem 1</span>
<span class="lineno"> 361 </span><span class="spaces"> </span><span class="nottickedoff">)</span>
<span class="lineno"> 362 </span><span class="spaces"> </span><span class="nottickedoff">else signalQSemN sem 1</span>
<span class="lineno"> 363 </span><span class="spaces"> </span><span class="nottickedoff">waitQSemN sem n</span>
<span class="lineno"> 364 </span><span class="spaces"> </span><span class="nottickedoff">mbE &lt;- tryTakeMVar eVar</span>
<span class="lineno"> 365 </span><span class="spaces"> </span><span class="nottickedoff">case mbE of</span>
<span class="lineno"> 366 </span><span class="spaces"> </span><span class="nottickedoff">Nothing -&gt; return ()</span>
<span class="lineno"> 367 </span><span class="spaces"> </span><span class="nottickedoff">Just e -&gt; throwIO (e :: SomeException)</span></span>
</pre>
</body>
</html>

View file

@ -0,0 +1,136 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style type="text/css">
span.lineno { color: white; background: #aaaaaa; border-right: solid white 12px }
span.nottickedoff { background: yellow}
span.istickedoff { background: white }
span.tickonlyfalse { margin: -1px; border: 1px solid #f20913; background: #f20913 }
span.tickonlytrue { margin: -1px; border: 1px solid #60de51; background: #60de51 }
span.funcount { font-size: small; color: orange; z-index: 2; position: absolute; right: 20 }
span.decl { font-weight: bold }
span.spaces { background: white }
</style>
</head>
<body>
<pre>
<span class="decl"><span class="nottickedoff">never executed</span> <span class="tickonlytrue">always true</span> <span class="tickonlyfalse">always false</span></span>
</pre>
<pre>
<span class="lineno"> 1 </span>module Reanimate.Svg.BoundingBox where
<span class="lineno"> 2 </span>
<span class="lineno"> 3 </span>import Control.Arrow ((***))
<span class="lineno"> 4 </span>import Control.Lens ((^.))
<span class="lineno"> 5 </span>import Data.List
<span class="lineno"> 6 </span>import Data.Maybe (mapMaybe)
<span class="lineno"> 7 </span>import Graphics.SvgTree hiding (height, line, path, use,
<span class="lineno"> 8 </span> width)
<span class="lineno"> 9 </span>import Linear.V2 hiding (angle)
<span class="lineno"> 10 </span>import Linear.Vector
<span class="lineno"> 11 </span>import Reanimate.Constants
<span class="lineno"> 12 </span>import Reanimate.Svg.LineCommand
<span class="lineno"> 13 </span>import qualified Reanimate.Transform as Transform
<span class="lineno"> 14 </span>-- import qualified Geom2D.CubicBezier as Bezier
<span class="lineno"> 15 </span>
<span class="lineno"> 16 </span>-- | Return bounding box of SVG tree.
<span class="lineno"> 17 </span>-- The four numbers returned are (minimal X-coordinate, minimal Y-coordinate, width, height)
<span class="lineno"> 18 </span>--
<span class="lineno"> 19 </span>-- Note: Bounding boxes are computed on a best-effort basis and will not work
<span class="lineno"> 20 </span>-- in all cases. The only supported SVG nodes are: path, circle, polyline,
<span class="lineno"> 21 </span>-- ellipse, line, rectangle, image. All other nodes return (0,0,0,0).
<span class="lineno"> 22 </span>boundingBox :: Tree -&gt; (Double, Double, Double, Double)
<span class="lineno"> 23 </span><span class="decl"><span class="nottickedoff">boundingBox t =</span>
<span class="lineno"> 24 </span><span class="spaces"> </span><span class="nottickedoff">case svgBoundingPoints t of</span>
<span class="lineno"> 25 </span><span class="spaces"> </span><span class="nottickedoff">[] -&gt; (0,0,0,0)</span>
<span class="lineno"> 26 </span><span class="spaces"> </span><span class="nottickedoff">(V2 x y:rest) -&gt;</span>
<span class="lineno"> 27 </span><span class="spaces"> </span><span class="nottickedoff">let (minx, miny, maxx, maxy) = foldl' worker (x, y, x, y) rest</span>
<span class="lineno"> 28 </span><span class="spaces"> </span><span class="nottickedoff">in (minx, miny, maxx-minx, maxy-miny)</span>
<span class="lineno"> 29 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 30 </span><span class="spaces"> </span><span class="nottickedoff">worker (minx, miny, maxx, maxy) (V2 x y) =</span>
<span class="lineno"> 31 </span><span class="spaces"> </span><span class="nottickedoff">(min minx x, min miny y, max maxx x, max maxy y)</span></span>
<span class="lineno"> 32 </span>
<span class="lineno"> 33 </span>svgHeight :: Tree -&gt; Double
<span class="lineno"> 34 </span><span class="decl"><span class="nottickedoff">svgHeight t = h</span>
<span class="lineno"> 35 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 36 </span><span class="spaces"> </span><span class="nottickedoff">(_x, _y, _w, h) = boundingBox t</span></span>
<span class="lineno"> 37 </span>
<span class="lineno"> 38 </span>svgWidth :: Tree -&gt; Double
<span class="lineno"> 39 </span><span class="decl"><span class="nottickedoff">svgWidth t = w</span>
<span class="lineno"> 40 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 41 </span><span class="spaces"> </span><span class="nottickedoff">(_x, _y, w, _h) = boundingBox t</span></span>
<span class="lineno"> 42 </span>
<span class="lineno"> 43 </span>linePoints :: [LineCommand] -&gt; [RPoint]
<span class="lineno"> 44 </span><span class="decl"><span class="nottickedoff">linePoints = worker zero</span>
<span class="lineno"> 45 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 46 </span><span class="spaces"> </span><span class="nottickedoff">worker _from [] = []</span>
<span class="lineno"> 47 </span><span class="spaces"> </span><span class="nottickedoff">worker from (x:xs) =</span>
<span class="lineno"> 48 </span><span class="spaces"> </span><span class="nottickedoff">case x of</span>
<span class="lineno"> 49 </span><span class="spaces"> </span><span class="nottickedoff">LineMove to -&gt; worker to xs</span>
<span class="lineno"> 50 </span><span class="spaces"> </span><span class="nottickedoff">-- LineDraw to -&gt; from:to:worker to xs</span>
<span class="lineno"> 51 </span><span class="spaces"> </span><span class="nottickedoff">LineBezier [p] -&gt;</span>
<span class="lineno"> 52 </span><span class="spaces"> </span><span class="nottickedoff">p : worker p xs</span>
<span class="lineno"> 53 </span><span class="spaces"> </span><span class="nottickedoff">LineBezier ctrl -&gt; -- approximation</span>
<span class="lineno"> 54 </span><span class="spaces"> </span><span class="nottickedoff">[ last (partialBezierPoints (from:ctrl) 0 (recip chunks*i)) | i &lt;- [0..chunks]] ++</span>
<span class="lineno"> 55 </span><span class="spaces"> </span><span class="nottickedoff">worker (last ctrl) xs</span>
<span class="lineno"> 56 </span><span class="spaces"> </span><span class="nottickedoff">LineEnd p -&gt; p : worker p xs</span>
<span class="lineno"> 57 </span><span class="spaces"> </span><span class="nottickedoff">chunks = 10</span></span>
<span class="lineno"> 58 </span>
<span class="lineno"> 59 </span>svgBoundingPoints :: Tree -&gt; [RPoint]
<span class="lineno"> 60 </span><span class="decl"><span class="nottickedoff">svgBoundingPoints t = map (Transform.transformPoint m) $</span>
<span class="lineno"> 61 </span><span class="spaces"> </span><span class="nottickedoff">case t of</span>
<span class="lineno"> 62 </span><span class="spaces"> </span><span class="nottickedoff">None -&gt; []</span>
<span class="lineno"> 63 </span><span class="spaces"> </span><span class="nottickedoff">UseTree{} -&gt; []</span>
<span class="lineno"> 64 </span><span class="spaces"> </span><span class="nottickedoff">GroupTree g -&gt; concatMap svgBoundingPoints (g^.groupChildren)</span>
<span class="lineno"> 65 </span><span class="spaces"> </span><span class="nottickedoff">SymbolTree (Symbol g) -&gt; concatMap svgBoundingPoints (g^.groupChildren)</span>
<span class="lineno"> 66 </span><span class="spaces"> </span><span class="nottickedoff">FilterTree{} -&gt; []</span>
<span class="lineno"> 67 </span><span class="spaces"> </span><span class="nottickedoff">DefinitionTree{} -&gt; []</span>
<span class="lineno"> 68 </span><span class="spaces"> </span><span class="nottickedoff">PathTree p -&gt; linePoints $ toLineCommands (p^.pathDefinition)</span>
<span class="lineno"> 69 </span><span class="spaces"> </span><span class="nottickedoff">CircleTree c -&gt; circleBoundingPoints c</span>
<span class="lineno"> 70 </span><span class="spaces"> </span><span class="nottickedoff">PolyLineTree pl -&gt; pl ^. polyLinePoints</span>
<span class="lineno"> 71 </span><span class="spaces"> </span><span class="nottickedoff">EllipseTree e -&gt; ellipseBoundingPoints e</span>
<span class="lineno"> 72 </span><span class="spaces"> </span><span class="nottickedoff">LineTree line -&gt; map pointToRPoint [line^.linePoint1, line^.linePoint2]</span>
<span class="lineno"> 73 </span><span class="spaces"> </span><span class="nottickedoff">RectangleTree rect -&gt;</span>
<span class="lineno"> 74 </span><span class="spaces"> </span><span class="nottickedoff">case pointToRPoint (rect^.rectUpperLeftCorner) of</span>
<span class="lineno"> 75 </span><span class="spaces"> </span><span class="nottickedoff">V2 x y -&gt; V2 x y :</span>
<span class="lineno"> 76 </span><span class="spaces"> </span><span class="nottickedoff">case mapTuple (fmap $ toUserUnit defaultDPI) (rect^.rectWidth, rect^.rectHeight) of</span>
<span class="lineno"> 77 </span><span class="spaces"> </span><span class="nottickedoff">(Just (Num w), Just (Num h)) -&gt; [V2 (x+w) (y+h)]</span>
<span class="lineno"> 78 </span><span class="spaces"> </span><span class="nottickedoff">_ -&gt; []</span>
<span class="lineno"> 79 </span><span class="spaces"> </span><span class="nottickedoff">TextTree{} -&gt; []</span>
<span class="lineno"> 80 </span><span class="spaces"> </span><span class="nottickedoff">ImageTree img -&gt;</span>
<span class="lineno"> 81 </span><span class="spaces"> </span><span class="nottickedoff">case (img^.imageCornerUpperLeft, img^.imageWidth, img^.imageHeight) of</span>
<span class="lineno"> 82 </span><span class="spaces"> </span><span class="nottickedoff">((Num x, Num y), Num w, Num h) -&gt;</span>
<span class="lineno"> 83 </span><span class="spaces"> </span><span class="nottickedoff">[V2 x y, V2 (x+w) (y+h)]</span>
<span class="lineno"> 84 </span><span class="spaces"> </span><span class="nottickedoff">_ -&gt; []</span>
<span class="lineno"> 85 </span><span class="spaces"> </span><span class="nottickedoff">MeshGradientTree{} -&gt; []</span>
<span class="lineno"> 86 </span><span class="spaces"> </span><span class="nottickedoff">_ -&gt; []</span>
<span class="lineno"> 87 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 88 </span><span class="spaces"> </span><span class="nottickedoff">m = Transform.mkMatrix (t^.transform)</span>
<span class="lineno"> 89 </span><span class="spaces"> </span><span class="nottickedoff">mapTuple f = f *** f</span>
<span class="lineno"> 90 </span><span class="spaces"> </span><span class="nottickedoff">pointToRPoint p =</span>
<span class="lineno"> 91 </span><span class="spaces"> </span><span class="nottickedoff">case mapTuple (toUserUnit defaultDPI) p of</span>
<span class="lineno"> 92 </span><span class="spaces"> </span><span class="nottickedoff">(Num x, Num y) -&gt; V2 x y</span>
<span class="lineno"> 93 </span><span class="spaces"> </span><span class="nottickedoff">_ -&gt; error &quot;Reanimate.Svg.svgBoundingPoints: Unrecognized number format.&quot;</span>
<span class="lineno"> 94 </span><span class="spaces"></span><span class="nottickedoff"></span>
<span class="lineno"> 95 </span><span class="spaces"> </span><span class="nottickedoff">circleBoundingPoints circ =</span>
<span class="lineno"> 96 </span><span class="spaces"> </span><span class="nottickedoff">let (xnum, ynum) = circ ^. circleCenter</span>
<span class="lineno"> 97 </span><span class="spaces"> </span><span class="nottickedoff">rnum = circ ^. circleRadius</span>
<span class="lineno"> 98 </span><span class="spaces"> </span><span class="nottickedoff">in case mapMaybe unpackNumber [xnum, ynum, rnum] of</span>
<span class="lineno"> 99 </span><span class="spaces"> </span><span class="nottickedoff">[x, y, r] -&gt; [ V2 (x + r * cos angle) (y + r * sin angle) | angle &lt;- [0, pi/10 .. 2 * pi]]</span>
<span class="lineno"> 100 </span><span class="spaces"> </span><span class="nottickedoff">_ -&gt; []</span>
<span class="lineno"> 101 </span><span class="spaces"></span><span class="nottickedoff"></span>
<span class="lineno"> 102 </span><span class="spaces"> </span><span class="nottickedoff">ellipseBoundingPoints e =</span>
<span class="lineno"> 103 </span><span class="spaces"> </span><span class="nottickedoff">let (xnum,ynum) = e ^. ellipseCenter</span>
<span class="lineno"> 104 </span><span class="spaces"> </span><span class="nottickedoff">xrnum = e ^. ellipseXRadius</span>
<span class="lineno"> 105 </span><span class="spaces"> </span><span class="nottickedoff">yrnum = e ^. ellipseYRadius</span>
<span class="lineno"> 106 </span><span class="spaces"> </span><span class="nottickedoff">in case mapMaybe unpackNumber [xnum, ynum, xrnum, yrnum] of</span>
<span class="lineno"> 107 </span><span class="spaces"> </span><span class="nottickedoff">[x,y,xr,yr] -&gt; [V2 (x + xr * cos angle) (y + yr * sin angle) | angle &lt;- [0, pi/10 .. 2 * pi]]</span>
<span class="lineno"> 108 </span><span class="spaces"> </span><span class="nottickedoff">_ -&gt; []</span>
<span class="lineno"> 109 </span><span class="spaces"></span><span class="nottickedoff"></span>
<span class="lineno"> 110 </span><span class="spaces"> </span><span class="nottickedoff">unpackNumber n =</span>
<span class="lineno"> 111 </span><span class="spaces"> </span><span class="nottickedoff">case toUserUnit defaultDPI n of</span>
<span class="lineno"> 112 </span><span class="spaces"> </span><span class="nottickedoff">Num d -&gt; Just d</span>
<span class="lineno"> 113 </span><span class="spaces"> </span><span class="nottickedoff">_ -&gt; Nothing</span></span>
</pre>
</body>
</html>

View file

@ -0,0 +1,436 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style type="text/css">
span.lineno { color: white; background: #aaaaaa; border-right: solid white 12px }
span.nottickedoff { background: yellow}
span.istickedoff { background: white }
span.tickonlyfalse { margin: -1px; border: 1px solid #f20913; background: #f20913 }
span.tickonlytrue { margin: -1px; border: 1px solid #60de51; background: #60de51 }
span.funcount { font-size: small; color: orange; z-index: 2; position: absolute; right: 20 }
span.decl { font-weight: bold }
span.spaces { background: white }
</style>
</head>
<body>
<pre>
<span class="decl"><span class="nottickedoff">never executed</span> <span class="tickonlytrue">always true</span> <span class="tickonlyfalse">always false</span></span>
</pre>
<pre>
<span class="lineno"> 1 </span>{-| Functions for creating basic SVG elements and applying transformations to them. -}
<span class="lineno"> 2 </span>module Reanimate.Svg.Constructors
<span class="lineno"> 3 </span> ( -- * Primitive shapes
<span class="lineno"> 4 </span> mkCircle
<span class="lineno"> 5 </span> , mkEllipse
<span class="lineno"> 6 </span> , mkRect
<span class="lineno"> 7 </span> , mkLine
<span class="lineno"> 8 </span> , mkPath
<span class="lineno"> 9 </span> , mkPathString
<span class="lineno"> 10 </span> , mkPathText
<span class="lineno"> 11 </span> , mkLinePath
<span class="lineno"> 12 </span> , mkLinePathClosed
<span class="lineno"> 13 </span> , mkClipPath
<span class="lineno"> 14 </span> , mkText
<span class="lineno"> 15 </span> -- * Grouping shapes and definitions
<span class="lineno"> 16 </span> , mkGroup
<span class="lineno"> 17 </span> , mkDefinitions
<span class="lineno"> 18 </span> , mkUse
<span class="lineno"> 19 </span> -- * Attributes
<span class="lineno"> 20 </span> , withId
<span class="lineno"> 21 </span> , withStrokeColor
<span class="lineno"> 22 </span> , withStrokeColorPixel
<span class="lineno"> 23 </span> , withStrokeDashArray
<span class="lineno"> 24 </span> , withStrokeLineJoin
<span class="lineno"> 25 </span> , withFillColor
<span class="lineno"> 26 </span> , withFillColorPixel
<span class="lineno"> 27 </span> , withFillOpacity
<span class="lineno"> 28 </span> , withGroupOpacity
<span class="lineno"> 29 </span> , withStrokeWidth
<span class="lineno"> 30 </span> , withClipPathRef
<span class="lineno"> 31 </span> -- * Transformations
<span class="lineno"> 32 </span> , center
<span class="lineno"> 33 </span> , centerX
<span class="lineno"> 34 </span> , centerY
<span class="lineno"> 35 </span> , centerUsing
<span class="lineno"> 36 </span> , translate
<span class="lineno"> 37 </span> , rotate
<span class="lineno"> 38 </span> , rotateAroundCenter
<span class="lineno"> 39 </span> , rotateAround
<span class="lineno"> 40 </span> , scale
<span class="lineno"> 41 </span> , scaleToSize
<span class="lineno"> 42 </span> , scaleToWidth
<span class="lineno"> 43 </span> , scaleToHeight
<span class="lineno"> 44 </span> , scaleXY
<span class="lineno"> 45 </span> , flipXAxis
<span class="lineno"> 46 </span> , flipYAxis
<span class="lineno"> 47 </span> , aroundCenter
<span class="lineno"> 48 </span> , aroundCenterX
<span class="lineno"> 49 </span> , aroundCenterY
<span class="lineno"> 50 </span> , withTransformations
<span class="lineno"> 51 </span> , withViewBox
<span class="lineno"> 52 </span> -- * Other
<span class="lineno"> 53 </span> , mkColor
<span class="lineno"> 54 </span> , mkBackground
<span class="lineno"> 55 </span> , mkBackgroundPixel
<span class="lineno"> 56 </span> , gridLayout
<span class="lineno"> 57 </span>
<span class="lineno"> 58 </span> ) where
<span class="lineno"> 59 </span>
<span class="lineno"> 60 </span>import Codec.Picture (PixelRGBA8 (..))
<span class="lineno"> 61 </span>import Control.Lens ((&amp;), (.~), (?~))
<span class="lineno"> 62 </span>import Data.Attoparsec.Text (parseOnly)
<span class="lineno"> 63 </span>import qualified Data.Map as Map
<span class="lineno"> 64 </span>import qualified Data.Text as T
<span class="lineno"> 65 </span>import Graphics.SvgTree hiding (height, line, path, use,
<span class="lineno"> 66 </span> width)
<span class="lineno"> 67 </span>import Graphics.SvgTree.NamedColors
<span class="lineno"> 68 </span>import Graphics.SvgTree.PathParser
<span class="lineno"> 69 </span>import Linear.V2 hiding (angle)
<span class="lineno"> 70 </span>import Reanimate.Constants
<span class="lineno"> 71 </span>import Reanimate.Svg.BoundingBox
<span class="lineno"> 72 </span>
<span class="lineno"> 73 </span>-- | Apply list of transformations to given image.
<span class="lineno"> 74 </span>withTransformations :: [Transformation] -&gt; Tree -&gt; Tree
<span class="lineno"> 75 </span><span class="decl"><span class="istickedoff">withTransformations transformations t =</span>
<span class="lineno"> 76 </span><span class="spaces"> </span><span class="istickedoff">mkGroup [t] &amp; transform ?~ transformations</span></span>
<span class="lineno"> 77 </span>
<span class="lineno"> 78 </span>-- | @translate x y image@ moves the @image@ by @x@ along X-axis and by @y@ along Y-axis.
<span class="lineno"> 79 </span>translate :: Double -&gt; Double -&gt; Tree -&gt; Tree
<span class="lineno"> 80 </span><span class="decl"><span class="istickedoff">translate x y = withTransformations [Translate x y]</span></span>
<span class="lineno"> 81 </span>
<span class="lineno"> 82 </span>-- | @rotate angle image@ rotates the @image@ around origin @(0,0)@ counterclockwise by @angle@
<span class="lineno"> 83 </span>-- given in degrees.
<span class="lineno"> 84 </span>rotate :: Double -&gt; Tree -&gt; Tree
<span class="lineno"> 85 </span><span class="decl"><span class="nottickedoff">rotate a = withTransformations [Rotate a Nothing]</span></span>
<span class="lineno"> 86 </span>
<span class="lineno"> 87 </span>-- | @rotate angle point image@ rotates the @image@ around given @point@ counterclockwise by
<span class="lineno"> 88 </span>-- @angle@ given in degrees.
<span class="lineno"> 89 </span>rotateAround :: Double -&gt; RPoint -&gt; Tree -&gt; Tree
<span class="lineno"> 90 </span><span class="decl"><span class="nottickedoff">rotateAround a (V2 x y) = withTransformations [Rotate a (Just (x,y))]</span></span>
<span class="lineno"> 91 </span>
<span class="lineno"> 92 </span>-- | @rotate angle image@ rotates the @image@ around the center of its bounding box counterclockwise
<span class="lineno"> 93 </span>-- by @angle@ given in degrees.
<span class="lineno"> 94 </span>rotateAroundCenter :: Double -&gt; Tree -&gt; Tree
<span class="lineno"> 95 </span><span class="decl"><span class="nottickedoff">rotateAroundCenter a t =</span>
<span class="lineno"> 96 </span><span class="spaces"> </span><span class="nottickedoff">rotateAround a (V2 (x+w/2) (y+h/2)) t</span>
<span class="lineno"> 97 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 98 </span><span class="spaces"> </span><span class="nottickedoff">(x,y,w,h) = boundingBox t</span></span>
<span class="lineno"> 99 </span>
<span class="lineno"> 100 </span>-- | @aroundCenter f image@ first moves the image so the center of its bounding box is at the origin
<span class="lineno"> 101 </span>-- @(0, 0)@, applies transformation @f@ to it and then moves the transformed image back to its
<span class="lineno"> 102 </span>-- original position.
<span class="lineno"> 103 </span>aroundCenter :: (Tree -&gt; Tree) -&gt; Tree -&gt; Tree
<span class="lineno"> 104 </span><span class="decl"><span class="nottickedoff">aroundCenter fn t =</span>
<span class="lineno"> 105 </span><span class="spaces"> </span><span class="nottickedoff">translate (-offsetX) (-offsetY) $ fn $ translate offsetX offsetY t</span>
<span class="lineno"> 106 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 107 </span><span class="spaces"> </span><span class="nottickedoff">offsetX = -x-w/2</span>
<span class="lineno"> 108 </span><span class="spaces"> </span><span class="nottickedoff">offsetY = -y-h/2</span>
<span class="lineno"> 109 </span><span class="spaces"> </span><span class="nottickedoff">(x,y,w,h) = boundingBox t</span></span>
<span class="lineno"> 110 </span>
<span class="lineno"> 111 </span>aroundCenterY :: (Tree -&gt; Tree) -&gt; Tree -&gt; Tree
<span class="lineno"> 112 </span><span class="decl"><span class="nottickedoff">aroundCenterY fn t =</span>
<span class="lineno"> 113 </span><span class="spaces"> </span><span class="nottickedoff">translate 0 (-offsetY) $ fn $ translate 0 offsetY t</span>
<span class="lineno"> 114 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 115 </span><span class="spaces"> </span><span class="nottickedoff">offsetY = -y-h/2</span>
<span class="lineno"> 116 </span><span class="spaces"> </span><span class="nottickedoff">(_x,y,_w,h) = boundingBox t</span></span>
<span class="lineno"> 117 </span>
<span class="lineno"> 118 </span>aroundCenterX :: (Tree -&gt; Tree) -&gt; Tree -&gt; Tree
<span class="lineno"> 119 </span><span class="decl"><span class="nottickedoff">aroundCenterX fn t =</span>
<span class="lineno"> 120 </span><span class="spaces"> </span><span class="nottickedoff">translate (-offsetX) 0 $ fn $ translate offsetX 0 t</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">offsetX = -x-w/2</span>
<span class="lineno"> 123 </span><span class="spaces"> </span><span class="nottickedoff">(x,_y,w,_h) = boundingBox t</span></span>
<span class="lineno"> 124 </span>
<span class="lineno"> 125 </span>-- | Scale the image uniformly by given factor along both X and Y axes.
<span class="lineno"> 126 </span>-- For example @scale 2 image@ makes the image twice as large, while @scale 0.5 image@ makes it
<span class="lineno"> 127 </span>-- half the original size. Negative values are also allowed, and lead to flipping the image along
<span class="lineno"> 128 </span>-- both X and Y axes.
<span class="lineno"> 129 </span>scale :: Double -&gt; Tree -&gt; Tree
<span class="lineno"> 130 </span><span class="decl"><span class="nottickedoff">scale a = withTransformations [Scale a Nothing]</span></span>
<span class="lineno"> 131 </span>
<span class="lineno"> 132 </span>-- | @scaleToSize width height@ resizes the image so that its bounding box has corresponding @width@
<span class="lineno"> 133 </span>-- and @height@.
<span class="lineno"> 134 </span>scaleToSize :: Double -&gt; Double -&gt; Tree -&gt; Tree
<span class="lineno"> 135 </span><span class="decl"><span class="nottickedoff">scaleToSize w h t =</span>
<span class="lineno"> 136 </span><span class="spaces"> </span><span class="nottickedoff">scaleXY (w/w') (h/h') t</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">(_x, _y, w', h') = boundingBox t</span></span>
<span class="lineno"> 139 </span>
<span class="lineno"> 140 </span>-- | @scaleToWidth width@ scales the image so that the width of its bounding box ends up having
<span class="lineno"> 141 </span>-- given @width@.
<span class="lineno"> 142 </span>scaleToWidth :: Double -&gt; Tree -&gt; Tree
<span class="lineno"> 143 </span><span class="decl"><span class="nottickedoff">scaleToWidth w t =</span>
<span class="lineno"> 144 </span><span class="spaces"> </span><span class="nottickedoff">scale (w/w') t</span>
<span class="lineno"> 145 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 146 </span><span class="spaces"> </span><span class="nottickedoff">(_x, _y, w', _h') = boundingBox t</span></span>
<span class="lineno"> 147 </span>
<span class="lineno"> 148 </span>-- | @scaleToHeight height@ scales the image so that the height of its bounding box ends up having
<span class="lineno"> 149 </span>-- given @height@.
<span class="lineno"> 150 </span>scaleToHeight :: Double -&gt; Tree -&gt; Tree
<span class="lineno"> 151 </span><span class="decl"><span class="nottickedoff">scaleToHeight h t =</span>
<span class="lineno"> 152 </span><span class="spaces"> </span><span class="nottickedoff">scale (h/h') t</span>
<span class="lineno"> 153 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 154 </span><span class="spaces"> </span><span class="nottickedoff">(_x, _y, _w', h') = boundingBox t</span></span>
<span class="lineno"> 155 </span>
<span class="lineno"> 156 </span>-- | Similar to 'scale', except scale factors for X and Y axes are specified separately.
<span class="lineno"> 157 </span>scaleXY :: Double -&gt; Double -&gt; Tree -&gt; Tree
<span class="lineno"> 158 </span><span class="decl"><span class="istickedoff">scaleXY x y = withTransformations [Scale x (Just y)]</span></span>
<span class="lineno"> 159 </span>
<span class="lineno"> 160 </span>
<span class="lineno"> 161 </span>-- | Flip the image along vertical axis so that what was on the right will end up on left and vice
<span class="lineno"> 162 </span>-- versa.
<span class="lineno"> 163 </span>flipXAxis :: Tree -&gt; Tree
<span class="lineno"> 164 </span><span class="decl"><span class="nottickedoff">flipXAxis = scaleXY (-1) 1</span></span>
<span class="lineno"> 165 </span>
<span class="lineno"> 166 </span>-- | Flip the image along horizontal so that what was on the top will end up in the bottom and vice
<span class="lineno"> 167 </span>-- versa.
<span class="lineno"> 168 </span>flipYAxis :: Tree -&gt; Tree
<span class="lineno"> 169 </span><span class="decl"><span class="nottickedoff">flipYAxis = scaleXY 1 (-1)</span></span>
<span class="lineno"> 170 </span>
<span class="lineno"> 171 </span>-- | Translate given image so that the center of its bouding box coincides with coordinates
<span class="lineno"> 172 </span>-- @(0, 0)@.
<span class="lineno"> 173 </span>center :: Tree -&gt; Tree
<span class="lineno"> 174 </span><span class="decl"><span class="nottickedoff">center t = centerUsing t t</span></span>
<span class="lineno"> 175 </span>
<span class="lineno"> 176 </span>-- | Translate given image so that the X-coordinate of the center of its bouding box is 0.
<span class="lineno"> 177 </span>centerX :: Tree -&gt; Tree
<span class="lineno"> 178 </span><span class="decl"><span class="nottickedoff">centerX t = translate (-x-w/2) 0 t</span>
<span class="lineno"> 179 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 180 </span><span class="spaces"> </span><span class="nottickedoff">(x, _y, w, _h) = boundingBox t</span></span>
<span class="lineno"> 181 </span>
<span class="lineno"> 182 </span>-- | Translate given image so that the Y-coordinate of the center of its bouding box is 0.
<span class="lineno"> 183 </span>centerY :: Tree -&gt; Tree
<span class="lineno"> 184 </span><span class="decl"><span class="nottickedoff">centerY t = translate 0 (-y-h/2) t</span>
<span class="lineno"> 185 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 186 </span><span class="spaces"> </span><span class="nottickedoff">(_x, y, _w, h) = boundingBox t</span></span>
<span class="lineno"> 187 </span>
<span class="lineno"> 188 </span>centerUsing :: Tree -&gt; Tree -&gt; Tree
<span class="lineno"> 189 </span><span class="decl"><span class="nottickedoff">centerUsing a = translate (-x-w/2) (-y-h/2)</span>
<span class="lineno"> 190 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 191 </span><span class="spaces"> </span><span class="nottickedoff">(x, y, w, h) = boundingBox a</span></span>
<span class="lineno"> 192 </span>
<span class="lineno"> 193 </span>-- | Create 'Texture' based on SVG color name.
<span class="lineno"> 194 </span>-- See &lt;https://en.wikipedia.org/wiki/Web_colors#X11_color_names&gt; for the list of available names.
<span class="lineno"> 195 </span>-- If the provided name doesn't correspond to valid SVG color name, white-ish color is used.
<span class="lineno"> 196 </span>mkColor :: String -&gt; Texture
<span class="lineno"> 197 </span><span class="decl"><span class="istickedoff">mkColor name =</span>
<span class="lineno"> 198 </span><span class="spaces"> </span><span class="istickedoff">case Map.lookup (T.pack name) svgNamedColors of</span>
<span class="lineno"> 199 </span><span class="spaces"> </span><span class="istickedoff">Nothing -&gt; <span class="nottickedoff">ColorRef (PixelRGBA8 240 248 255 255)</span></span>
<span class="lineno"> 200 </span><span class="spaces"> </span><span class="istickedoff">Just c -&gt; ColorRef c</span></span>
<span class="lineno"> 201 </span>
<span class="lineno"> 202 </span>-- | See &lt;https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke&gt;
<span class="lineno"> 203 </span>withStrokeColor :: String -&gt; Tree -&gt; Tree
<span class="lineno"> 204 </span><span class="decl"><span class="istickedoff">withStrokeColor color = strokeColor .~ pure (mkColor color)</span></span>
<span class="lineno"> 205 </span>
<span class="lineno"> 206 </span>withStrokeColorPixel :: PixelRGBA8 -&gt; Tree -&gt; Tree
<span class="lineno"> 207 </span><span class="decl"><span class="nottickedoff">withStrokeColorPixel color = strokeColor .~ pure (ColorRef color)</span></span>
<span class="lineno"> 208 </span>
<span class="lineno"> 209 </span>withStrokeDashArray :: [Double] -&gt; Tree -&gt; Tree
<span class="lineno"> 210 </span><span class="decl"><span class="nottickedoff">withStrokeDashArray arr = strokeDashArray .~ pure (map Num arr)</span></span>
<span class="lineno"> 211 </span>
<span class="lineno"> 212 </span>-- | See &lt;https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin&gt;
<span class="lineno"> 213 </span>withStrokeLineJoin :: LineJoin -&gt; Tree -&gt; Tree
<span class="lineno"> 214 </span><span class="decl"><span class="nottickedoff">withStrokeLineJoin ljoin = strokeLineJoin .~ pure ljoin</span></span>
<span class="lineno"> 215 </span>
<span class="lineno"> 216 </span>-- | See &lt;https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill&gt;
<span class="lineno"> 217 </span>withFillColor :: String -&gt; Tree -&gt; Tree
<span class="lineno"> 218 </span><span class="decl"><span class="istickedoff">withFillColor color = fillColor .~ pure (mkColor color)</span></span>
<span class="lineno"> 219 </span>
<span class="lineno"> 220 </span>withFillColorPixel :: PixelRGBA8 -&gt; Tree -&gt; Tree
<span class="lineno"> 221 </span><span class="decl"><span class="nottickedoff">withFillColorPixel color = fillColor .~ pure (ColorRef color)</span></span>
<span class="lineno"> 222 </span>
<span class="lineno"> 223 </span>-- | See &lt;https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity&gt;
<span class="lineno"> 224 </span>withFillOpacity :: Double -&gt; Tree -&gt; Tree
<span class="lineno"> 225 </span><span class="decl"><span class="istickedoff">withFillOpacity opacity = fillOpacity ?~ realToFrac opacity</span></span>
<span class="lineno"> 226 </span>
<span class="lineno"> 227 </span>withGroupOpacity :: Double -&gt; Tree -&gt; Tree
<span class="lineno"> 228 </span><span class="decl"><span class="nottickedoff">withGroupOpacity opacity = groupOpacity ?~ realToFrac opacity</span></span>
<span class="lineno"> 229 </span>
<span class="lineno"> 230 </span>-- | See &lt;https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width&gt;
<span class="lineno"> 231 </span>withStrokeWidth :: Double -&gt; Tree -&gt; Tree
<span class="lineno"> 232 </span><span class="decl"><span class="istickedoff">withStrokeWidth width = strokeWidth .~ pure (Num width)</span></span>
<span class="lineno"> 233 </span>
<span class="lineno"> 234 </span>-- | See &lt;https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/clip-path&gt;
<span class="lineno"> 235 </span>withClipPathRef :: ElementRef -- ^ Reference to clip path defined previously (e.g. by 'mkClipPath')
<span class="lineno"> 236 </span> -&gt; Tree -- ^ Image that will be clipped by the referenced clip path
<span class="lineno"> 237 </span> -&gt; Tree
<span class="lineno"> 238 </span><span class="decl"><span class="nottickedoff">withClipPathRef ref sub = mkGroup [sub] &amp; clipPathRef .~ pure ref</span></span>
<span class="lineno"> 239 </span>
<span class="lineno"> 240 </span>-- | Assigns ID attribute to given image.
<span class="lineno"> 241 </span>withId :: String -&gt; Tree -&gt; Tree
<span class="lineno"> 242 </span><span class="decl"><span class="nottickedoff">withId idTag = attrId ?~ idTag</span></span>
<span class="lineno"> 243 </span>
<span class="lineno"> 244 </span>-- | @mkRect width height@ creates a rectangle with given @with@ and @height@, centered at @(0, 0)@.
<span class="lineno"> 245 </span>-- See &lt;https://developer.mozilla.org/en-US/docs/Web/SVG/Element/rect&gt;
<span class="lineno"> 246 </span>mkRect :: Double -&gt; Double -&gt; Tree
<span class="lineno"> 247 </span><span class="decl"><span class="istickedoff">mkRect width height = translate (-width/2) (-height/2) $ RectangleTree $ defaultSvg</span>
<span class="lineno"> 248 </span><span class="spaces"> </span><span class="istickedoff">&amp; rectUpperLeftCorner .~ (Num 0, Num 0)</span>
<span class="lineno"> 249 </span><span class="spaces"> </span><span class="istickedoff">&amp; rectWidth ?~ Num width</span>
<span class="lineno"> 250 </span><span class="spaces"> </span><span class="istickedoff">&amp; rectHeight ?~ Num height</span></span>
<span class="lineno"> 251 </span>
<span class="lineno"> 252 </span>-- | Create a circle with given radius, centered at @(0, 0)@.
<span class="lineno"> 253 </span>-- See &lt;https://developer.mozilla.org/en-US/docs/Web/SVG/Element/circle&gt;
<span class="lineno"> 254 </span>mkCircle :: Double -&gt; Tree
<span class="lineno"> 255 </span><span class="decl"><span class="istickedoff">mkCircle radius = CircleTree $ defaultSvg</span>
<span class="lineno"> 256 </span><span class="spaces"> </span><span class="istickedoff">&amp; circleCenter .~ (Num 0, Num 0)</span>
<span class="lineno"> 257 </span><span class="spaces"> </span><span class="istickedoff">&amp; circleRadius .~ Num radius</span></span>
<span class="lineno"> 258 </span>
<span class="lineno"> 259 </span>-- | Create an ellipse given X-axis radius, and Y-axis radius, with center at @(0, 0)@.
<span class="lineno"> 260 </span>-- See &lt;https://developer.mozilla.org/en-US/docs/Web/SVG/Element/ellipse&gt;
<span class="lineno"> 261 </span>mkEllipse :: Double -&gt; Double -&gt; Tree
<span class="lineno"> 262 </span><span class="decl"><span class="nottickedoff">mkEllipse rx ry = EllipseTree $ defaultSvg</span>
<span class="lineno"> 263 </span><span class="spaces"> </span><span class="nottickedoff">&amp; ellipseCenter .~ (Num 0, Num 0)</span>
<span class="lineno"> 264 </span><span class="spaces"> </span><span class="nottickedoff">&amp; ellipseXRadius .~ Num rx</span>
<span class="lineno"> 265 </span><span class="spaces"> </span><span class="nottickedoff">&amp; ellipseYRadius .~ Num ry</span></span>
<span class="lineno"> 266 </span>
<span class="lineno"> 267 </span>-- | Create a line segment between two points given by their @(x, y)@ coordinates.
<span class="lineno"> 268 </span>-- See &lt;https://developer.mozilla.org/en-US/docs/Web/SVG/Element/line&gt;
<span class="lineno"> 269 </span>mkLine :: (Double,Double) -&gt; (Double, Double) -&gt; Tree
<span class="lineno"> 270 </span><span class="decl"><span class="nottickedoff">mkLine (x1,y1) (x2,y2) = LineTree $ defaultSvg</span>
<span class="lineno"> 271 </span><span class="spaces"> </span><span class="nottickedoff">&amp; linePoint1 .~ (Num x1, Num y1)</span>
<span class="lineno"> 272 </span><span class="spaces"> </span><span class="nottickedoff">&amp; linePoint2 .~ (Num x2, Num y2)</span></span>
<span class="lineno"> 273 </span>
<span class="lineno"> 274 </span>-- | Merges multiple images into one.
<span class="lineno"> 275 </span>-- See &lt;https://developer.mozilla.org/en-US/docs/Web/SVG/Element/g&gt;
<span class="lineno"> 276 </span>mkGroup :: [Tree] -&gt; Tree
<span class="lineno"> 277 </span><span class="decl"><span class="istickedoff">mkGroup forest = GroupTree $ defaultSvg</span>
<span class="lineno"> 278 </span><span class="spaces"> </span><span class="istickedoff">&amp; groupChildren .~ forest</span></span>
<span class="lineno"> 279 </span>
<span class="lineno"> 280 </span>-- | Create definition of graphical objects that can be used at later time.
<span class="lineno"> 281 </span>-- See &lt;https://developer.mozilla.org/en-US/docs/Web/SVG/Element/defs&gt;
<span class="lineno"> 282 </span>mkDefinitions :: [Tree] -&gt; Tree
<span class="lineno"> 283 </span><span class="decl"><span class="nottickedoff">mkDefinitions forest = DefinitionTree $ defaultSvg</span>
<span class="lineno"> 284 </span><span class="spaces"> </span><span class="nottickedoff">&amp; groupChildren .~ forest</span></span>
<span class="lineno"> 285 </span>
<span class="lineno"> 286 </span>-- | Create an element by referring to existing element defined previously.
<span class="lineno"> 287 </span>-- For example you can create a graphical element, assign ID to it using 'withId', wrap it in
<span class="lineno"> 288 </span>-- 'mkDefinitions' and then use it via @use &quot;myId&quot;@.
<span class="lineno"> 289 </span>-- See &lt;https://developer.mozilla.org/en-US/docs/Web/SVG/Element/use&gt;
<span class="lineno"> 290 </span>mkUse :: String -&gt; Tree
<span class="lineno"> 291 </span><span class="decl"><span class="nottickedoff">mkUse name = UseTree (defaultSvg &amp; useName .~ name) Nothing</span></span>
<span class="lineno"> 292 </span>
<span class="lineno"> 293 </span>-- | A clip path restricts the region to which paint can be applied.
<span class="lineno"> 294 </span>-- See &lt;https://developer.mozilla.org/en-US/docs/Web/SVG/Element/clipPath&gt;
<span class="lineno"> 295 </span>mkClipPath :: String -- ^ ID of the clip path, which can then be referred to by other elements
<span class="lineno"> 296 </span> -- using 'withClipPathRef'.
<span class="lineno"> 297 </span> -&gt; [Tree] -- ^ List of shapes that will determine the final shape of the clipping region
<span class="lineno"> 298 </span> -&gt; Tree
<span class="lineno"> 299 </span><span class="decl"><span class="nottickedoff">mkClipPath idTag forest = withId idTag $ ClipPathTree $ defaultSvg</span>
<span class="lineno"> 300 </span><span class="spaces"> </span><span class="nottickedoff">&amp; clipPathContent .~ forest</span></span>
<span class="lineno"> 301 </span>
<span class="lineno"> 302 </span>-- | Create a path from the list of path commands.
<span class="lineno"> 303 </span>-- See &lt;https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/d#Path_commands&gt;
<span class="lineno"> 304 </span>mkPath :: [PathCommand] -&gt; Tree
<span class="lineno"> 305 </span><span class="decl"><span class="nottickedoff">mkPath cmds = PathTree $ defaultSvg &amp; pathDefinition .~ cmds</span></span>
<span class="lineno"> 306 </span>
<span class="lineno"> 307 </span>-- | Similar to 'mkPathText', but taking SVG path command as a String.
<span class="lineno"> 308 </span>mkPathString :: String -&gt; Tree
<span class="lineno"> 309 </span><span class="decl"><span class="nottickedoff">mkPathString = mkPathText . T.pack</span></span>
<span class="lineno"> 310 </span>
<span class="lineno"> 311 </span>-- | Create path from textual representation of SVG path command.
<span class="lineno"> 312 </span>-- If the text doesn't represent valid path command, this function fails with 'Prelude.error'.
<span class="lineno"> 313 </span>-- Use 'mkPath' for type safe way of creating paths.
<span class="lineno"> 314 </span>mkPathText :: T.Text -&gt; Tree
<span class="lineno"> 315 </span><span class="decl"><span class="nottickedoff">mkPathText str =</span>
<span class="lineno"> 316 </span><span class="spaces"> </span><span class="nottickedoff">case parseOnly pathParser str of</span>
<span class="lineno"> 317 </span><span class="spaces"> </span><span class="nottickedoff">Left err -&gt; error err</span>
<span class="lineno"> 318 </span><span class="spaces"> </span><span class="nottickedoff">Right cmds -&gt; mkPath cmds</span></span>
<span class="lineno"> 319 </span>
<span class="lineno"> 320 </span>-- | Create a path from a list of @(x, y)@ coordinates of points along the path.
<span class="lineno"> 321 </span>mkLinePath :: [(Double, Double)] -&gt; Tree
<span class="lineno"> 322 </span><span class="decl"><span class="nottickedoff">mkLinePath [] = mkGroup []</span>
<span class="lineno"> 323 </span><span class="spaces"></span><span class="nottickedoff">mkLinePath ((startX, startY):rest) =</span>
<span class="lineno"> 324 </span><span class="spaces"> </span><span class="nottickedoff">PathTree $ defaultSvg &amp; pathDefinition .~ cmds</span>
<span class="lineno"> 325 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 326 </span><span class="spaces"> </span><span class="nottickedoff">cmds = [ MoveTo OriginAbsolute [V2 startX startY]</span>
<span class="lineno"> 327 </span><span class="spaces"> </span><span class="nottickedoff">, LineTo OriginAbsolute [ V2 x y | (x, y) &lt;- rest ] ]</span></span>
<span class="lineno"> 328 </span>
<span class="lineno"> 329 </span>-- | Create a path from a list of @(x, y)@ coordinates of points along the path.
<span class="lineno"> 330 </span>mkLinePathClosed :: [(Double, Double)] -&gt; Tree
<span class="lineno"> 331 </span><span class="decl"><span class="nottickedoff">mkLinePathClosed [] = mkGroup []</span>
<span class="lineno"> 332 </span><span class="spaces"></span><span class="nottickedoff">mkLinePathClosed ((startX, startY):rest) =</span>
<span class="lineno"> 333 </span><span class="spaces"> </span><span class="nottickedoff">PathTree $ defaultSvg &amp; pathDefinition .~ cmds</span>
<span class="lineno"> 334 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 335 </span><span class="spaces"> </span><span class="nottickedoff">cmds = [ MoveTo OriginAbsolute [V2 startX startY]</span>
<span class="lineno"> 336 </span><span class="spaces"> </span><span class="nottickedoff">, LineTo OriginAbsolute [ V2 x y | (x, y) &lt;- rest ]</span>
<span class="lineno"> 337 </span><span class="spaces"> </span><span class="nottickedoff">, EndPath ]</span></span>
<span class="lineno"> 338 </span>
<span class="lineno"> 339 </span>-- | Rectangle with a uniform color and the same size as the screen.
<span class="lineno"> 340 </span>--
<span class="lineno"> 341 </span>-- Example:
<span class="lineno"> 342 </span>--
<span class="lineno"> 343 </span>-- &gt; animate $ const $ mkBackground &quot;yellow&quot;
<span class="lineno"> 344 </span>--
<span class="lineno"> 345 </span>-- &lt;&lt;docs/gifs/doc_mkBackground.gif&gt;&gt;
<span class="lineno"> 346 </span>mkBackground :: String -&gt; Tree
<span class="lineno"> 347 </span><span class="decl"><span class="istickedoff">mkBackground color = withFillOpacity 1 $ withStrokeWidth 0 $</span>
<span class="lineno"> 348 </span><span class="spaces"> </span><span class="istickedoff">withFillColor color $ mkRect screenWidth screenHeight</span></span>
<span class="lineno"> 349 </span>
<span class="lineno"> 350 </span>mkBackgroundPixel :: PixelRGBA8 -&gt; Tree
<span class="lineno"> 351 </span><span class="decl"><span class="nottickedoff">mkBackgroundPixel pixel =</span>
<span class="lineno"> 352 </span><span class="spaces"> </span><span class="nottickedoff">withFillOpacity 1 $ withStrokeWidth 0 $</span>
<span class="lineno"> 353 </span><span class="spaces"> </span><span class="nottickedoff">withFillColorPixel pixel $ mkRect screenWidth screenHeight</span></span>
<span class="lineno"> 354 </span>
<span class="lineno"> 355 </span>-- | Take list of rows, where each row consists of number of images and display them in regular
<span class="lineno"> 356 </span>-- grid structure.
<span class="lineno"> 357 </span>-- All rows will get equal amount of vertical space.
<span class="lineno"> 358 </span>-- The images within each row will get equal amount of horizontal space, independent of the other
<span class="lineno"> 359 </span>-- rows. Each row can contain different number of cells.
<span class="lineno"> 360 </span>gridLayout :: [[Tree]] -&gt; Tree
<span class="lineno"> 361 </span><span class="decl"><span class="nottickedoff">gridLayout rows = mkGroup</span>
<span class="lineno"> 362 </span><span class="spaces"> </span><span class="nottickedoff">[ translate (-screenWidth/2+colSep*nCol + colSep*0.5)</span>
<span class="lineno"> 363 </span><span class="spaces"> </span><span class="nottickedoff">(screenHeight/2-rowSep*nRow - rowSep*0.5)</span>
<span class="lineno"> 364 </span><span class="spaces"> </span><span class="nottickedoff">elt</span>
<span class="lineno"> 365 </span><span class="spaces"> </span><span class="nottickedoff">| (nRow, row) &lt;- zip [0..] rows</span>
<span class="lineno"> 366 </span><span class="spaces"> </span><span class="nottickedoff">, let nCols = length row</span>
<span class="lineno"> 367 </span><span class="spaces"> </span><span class="nottickedoff">colSep = screenWidth / fromIntegral nCols</span>
<span class="lineno"> 368 </span><span class="spaces"> </span><span class="nottickedoff">, (nCol, elt) &lt;- zip [0..] row ]</span>
<span class="lineno"> 369 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 370 </span><span class="spaces"> </span><span class="nottickedoff">rowSep = screenHeight / fromIntegral nRows</span>
<span class="lineno"> 371 </span><span class="spaces"> </span><span class="nottickedoff">nRows = length rows</span></span>
<span class="lineno"> 372 </span>
<span class="lineno"> 373 </span>-- | Insert a native text object anchored at the middle.
<span class="lineno"> 374 </span>--
<span class="lineno"> 375 </span>-- Example:
<span class="lineno"> 376 </span>--
<span class="lineno"> 377 </span>-- &gt; mkAnimation 2 $ \t -&gt; scale 2 $ withStrokeWidth 0.05 $ mkText (T.take (round $ t*15) &quot;text&quot;)
<span class="lineno"> 378 </span>--
<span class="lineno"> 379 </span>-- &lt;&lt;docs/gifs/doc_mkText.gif&gt;&gt;
<span class="lineno"> 380 </span>mkText :: T.Text -&gt; Tree
<span class="lineno"> 381 </span><span class="decl"><span class="nottickedoff">mkText str =</span>
<span class="lineno"> 382 </span><span class="spaces"> </span><span class="nottickedoff">flipYAxis</span>
<span class="lineno"> 383 </span><span class="spaces"> </span><span class="nottickedoff">(TextTree Nothing $ defaultSvg</span>
<span class="lineno"> 384 </span><span class="spaces"> </span><span class="nottickedoff">&amp; textRoot .~ span_</span>
<span class="lineno"> 385 </span><span class="spaces"> </span><span class="nottickedoff">&amp; fontSize .~ pure (Num 2))</span>
<span class="lineno"> 386 </span><span class="spaces"> </span><span class="nottickedoff">&amp; textAnchor .~ pure TextAnchorMiddle</span>
<span class="lineno"> 387 </span><span class="spaces"> </span><span class="nottickedoff">-- Note: TextAnchorMiddle is placed on the 'flipYAxis' group such that it can easily</span>
<span class="lineno"> 388 </span><span class="spaces"> </span><span class="nottickedoff">-- be overwritten by the user.</span>
<span class="lineno"> 389 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 390 </span><span class="spaces"> </span><span class="nottickedoff">span_ = defaultSvg &amp; spanContent .~ [SpanText str]</span></span>
<span class="lineno"> 391 </span>
<span class="lineno"> 392 </span>-- | Switch from the default viewbox to a custom viewbox. Nesting custom viewboxes is
<span class="lineno"> 393 </span>-- unlikely to give good results. If you need nested custom viewboxes, you will have
<span class="lineno"> 394 </span>-- to configure them by hand.
<span class="lineno"> 395 </span>--
<span class="lineno"> 396 </span>-- The viewbox argument is (min-x, min-y, width, height).
<span class="lineno"> 397 </span>--
<span class="lineno"> 398 </span>-- Example:
<span class="lineno"> 399 </span>--
<span class="lineno"> 400 </span>-- &gt; withViewBox (0,0,1,1) $ mkBackground &quot;yellow&quot;
<span class="lineno"> 401 </span>--
<span class="lineno"> 402 </span>-- &lt;&lt;docs/gifs/doc_withViewBox.gif&gt;&gt;
<span class="lineno"> 403 </span>withViewBox :: (Double, Double, Double, Double) -&gt; Tree -&gt; Tree
<span class="lineno"> 404 </span><span class="decl"><span class="nottickedoff">withViewBox vbox child = translate (-screenWidth/2) (-screenHeight/2) $</span>
<span class="lineno"> 405 </span><span class="spaces"> </span><span class="nottickedoff">SvgTree $ Document</span>
<span class="lineno"> 406 </span><span class="spaces"> </span><span class="nottickedoff">{ _viewBox = Just vbox</span>
<span class="lineno"> 407 </span><span class="spaces"> </span><span class="nottickedoff">, _width = Just (Num screenWidth)</span>
<span class="lineno"> 408 </span><span class="spaces"> </span><span class="nottickedoff">, _height = Just (Num screenHeight)</span>
<span class="lineno"> 409 </span><span class="spaces"> </span><span class="nottickedoff">, _elements = [child]</span>
<span class="lineno"> 410 </span><span class="spaces"> </span><span class="nottickedoff">, _description = &quot;&quot;</span>
<span class="lineno"> 411 </span><span class="spaces"> </span><span class="nottickedoff">, _documentLocation = &quot;&quot;</span>
<span class="lineno"> 412 </span><span class="spaces"> </span><span class="nottickedoff">, _documentAspectRatio = PreserveAspectRatio False AlignNone Nothing</span>
<span class="lineno"> 413 </span><span class="spaces"> </span><span class="nottickedoff">}</span></span>
</pre>
</body>
</html>

View file

@ -0,0 +1,284 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style type="text/css">
span.lineno { color: white; background: #aaaaaa; border-right: solid white 12px }
span.nottickedoff { background: yellow}
span.istickedoff { background: white }
span.tickonlyfalse { margin: -1px; border: 1px solid #f20913; background: #f20913 }
span.tickonlytrue { margin: -1px; border: 1px solid #60de51; background: #60de51 }
span.funcount { font-size: small; color: orange; z-index: 2; position: absolute; right: 20 }
span.decl { font-weight: bold }
span.spaces { background: white }
</style>
</head>
<body>
<pre>
<span class="decl"><span class="nottickedoff">never executed</span> <span class="tickonlytrue">always true</span> <span class="tickonlyfalse">always false</span></span>
</pre>
<pre>
<span class="lineno"> 1 </span>module Reanimate.Svg.LineCommand where
<span class="lineno"> 2 </span>
<span class="lineno"> 3 </span>import Control.Lens ((%~), (&amp;), (.~))
<span class="lineno"> 4 </span>import Control.Monad.Fix
<span class="lineno"> 5 </span>import Control.Monad.State
<span class="lineno"> 6 </span>import Data.Functor
<span class="lineno"> 7 </span>import qualified Data.Vector.Unboxed as V
<span class="lineno"> 8 </span>import qualified Reanimate.Internal.CubicBezier as Bezier
<span class="lineno"> 9 </span>import Graphics.SvgTree hiding (height, line, path, use, width)
<span class="lineno"> 10 </span>import Linear.Metric
<span class="lineno"> 11 </span>import Linear.V2 hiding (angle)
<span class="lineno"> 12 </span>import Linear.Vector
<span class="lineno"> 13 </span>
<span class="lineno"> 14 </span>type CmdM a = State RPoint a
<span class="lineno"> 15 </span>
<span class="lineno"> 16 </span>data LineCommand
<span class="lineno"> 17 </span> = LineMove RPoint
<span class="lineno"> 18 </span> -- | LineDraw RPoint
<span class="lineno"> 19 </span> | LineBezier [RPoint]
<span class="lineno"> 20 </span> | LineEnd RPoint
<span class="lineno"> 21 </span> deriving (<span class="decl"><span class="nottickedoff">Show</span></span>)
<span class="lineno"> 22 </span>
<span class="lineno"> 23 </span>lineToPath :: [LineCommand] -&gt; [PathCommand]
<span class="lineno"> 24 </span><span class="decl"><span class="istickedoff">lineToPath = map worker</span>
<span class="lineno"> 25 </span><span class="spaces"> </span><span class="istickedoff">where</span>
<span class="lineno"> 26 </span><span class="spaces"> </span><span class="istickedoff">worker (LineMove p) = MoveTo OriginAbsolute [p]</span>
<span class="lineno"> 27 </span><span class="spaces"> </span><span class="istickedoff">-- worker (LineDraw p) = LineTo OriginAbsolute [p]</span>
<span class="lineno"> 28 </span><span class="spaces"> </span><span class="istickedoff">worker (LineBezier [a,b,c]) = CurveTo OriginAbsolute [(a,b,c)]</span>
<span class="lineno"> 29 </span><span class="spaces"> </span><span class="istickedoff">worker (LineBezier [a,b]) = <span class="nottickedoff">QuadraticBezier OriginAbsolute [(a,b)]</span></span>
<span class="lineno"> 30 </span><span class="spaces"> </span><span class="istickedoff">worker (LineBezier [a]) = LineTo OriginAbsolute [a]</span>
<span class="lineno"> 31 </span><span class="spaces"> </span><span class="istickedoff">worker LineBezier{} = <span class="nottickedoff">error &quot;Reanimate.Svg.lineToPath: invalid bezier curve&quot;</span></span>
<span class="lineno"> 32 </span><span class="spaces"> </span><span class="istickedoff">worker LineEnd{} = <span class="nottickedoff">EndPath</span></span></span>
<span class="lineno"> 33 </span>
<span class="lineno"> 34 </span>lineToPoints :: Int -&gt; [LineCommand] -&gt; [RPoint]
<span class="lineno"> 35 </span><span class="decl"><span class="nottickedoff">lineToPoints nPoints cmds =</span>
<span class="lineno"> 36 </span><span class="spaces"> </span><span class="nottickedoff">map lineEnd lineSegments</span>
<span class="lineno"> 37 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 38 </span><span class="spaces"> </span><span class="nottickedoff">lineSegments = [ partialLine (fromIntegral n/ fromIntegral nPoints) cmds | n &lt;- [0 .. nPoints-1] ]</span>
<span class="lineno"> 39 </span><span class="spaces"> </span><span class="nottickedoff">lineEnd [LineBezier pts] = last pts</span>
<span class="lineno"> 40 </span><span class="spaces"> </span><span class="nottickedoff">lineEnd (_:xs) = lineEnd xs</span>
<span class="lineno"> 41 </span><span class="spaces"> </span><span class="nottickedoff">lineEnd _ = error &quot;invalid line&quot;</span></span>
<span class="lineno"> 42 </span>
<span class="lineno"> 43 </span>partialLine :: Double -&gt; [LineCommand] -&gt; [LineCommand]
<span class="lineno"> 44 </span><span class="decl"><span class="istickedoff">partialLine alpha cmds = evalState (worker 0 cmds) <span class="nottickedoff">zero</span></span>
<span class="lineno"> 45 </span><span class="spaces"> </span><span class="istickedoff">where</span>
<span class="lineno"> 46 </span><span class="spaces"> </span><span class="istickedoff">worker _d [] = <span class="nottickedoff">pure []</span></span>
<span class="lineno"> 47 </span><span class="spaces"> </span><span class="istickedoff">worker d (cmd:xs) = do</span>
<span class="lineno"> 48 </span><span class="spaces"> </span><span class="istickedoff">from &lt;- get</span>
<span class="lineno"> 49 </span><span class="spaces"> </span><span class="istickedoff">len &lt;- lineLength cmd</span>
<span class="lineno"> 50 </span><span class="spaces"> </span><span class="istickedoff">let frac = (targetLen-d) / len</span>
<span class="lineno"> 51 </span><span class="spaces"> </span><span class="istickedoff">if len == 0 || frac &gt;= 1</span>
<span class="lineno"> 52 </span><span class="spaces"> </span><span class="istickedoff">then (cmd:) &lt;$&gt; worker (d+len) xs</span>
<span class="lineno"> 53 </span><span class="spaces"> </span><span class="istickedoff">else pure [adjustLineLength frac from cmd]</span>
<span class="lineno"> 54 </span><span class="spaces"> </span><span class="istickedoff">totalLen = evalState (sum &lt;$&gt; mapM lineLength cmds) <span class="nottickedoff">zero</span></span>
<span class="lineno"> 55 </span><span class="spaces"> </span><span class="istickedoff">targetLen = totalLen * alpha</span></span>
<span class="lineno"> 56 </span>
<span class="lineno"> 57 </span>adjustLineLength :: Double -&gt; RPoint -&gt; LineCommand -&gt; LineCommand
<span class="lineno"> 58 </span><span class="decl"><span class="istickedoff">adjustLineLength alpha from cmd =</span>
<span class="lineno"> 59 </span><span class="spaces"> </span><span class="istickedoff">case cmd of</span>
<span class="lineno"> 60 </span><span class="spaces"> </span><span class="istickedoff">LineBezier points -&gt; LineBezier $ drop 1 $ partialBezierPoints (from:points) 0 alpha</span>
<span class="lineno"> 61 </span><span class="spaces"> </span><span class="istickedoff">LineMove p -&gt; <span class="nottickedoff">LineMove p</span></span>
<span class="lineno"> 62 </span><span class="spaces"> </span><span class="istickedoff">-- LineDraw t -&gt; LineDraw (lerp alpha t from)</span>
<span class="lineno"> 63 </span><span class="spaces"> </span><span class="istickedoff">LineEnd p -&gt; LineBezier [lerp alpha p from]</span></span>
<span class="lineno"> 64 </span>
<span class="lineno"> 65 </span>lineLength :: LineCommand -&gt; CmdM Double
<span class="lineno"> 66 </span><span class="decl"><span class="istickedoff">lineLength cmd =</span>
<span class="lineno"> 67 </span><span class="spaces"> </span><span class="istickedoff">case cmd of</span>
<span class="lineno"> 68 </span><span class="spaces"> </span><span class="istickedoff">LineMove to -&gt; 0 &lt;$ put to</span>
<span class="lineno"> 69 </span><span class="spaces"> </span><span class="istickedoff">-- Straight line:</span>
<span class="lineno"> 70 </span><span class="spaces"> </span><span class="istickedoff">LineBezier [dst] -&gt; gets (distance dst) &lt;* put dst</span>
<span class="lineno"> 71 </span><span class="spaces"> </span><span class="istickedoff">-- Some kind of curve:</span>
<span class="lineno"> 72 </span><span class="spaces"> </span><span class="istickedoff">LineBezier lst -&gt; do</span>
<span class="lineno"> 73 </span><span class="spaces"> </span><span class="istickedoff">from &lt;- get</span>
<span class="lineno"> 74 </span><span class="spaces"> </span><span class="istickedoff">let bezier = rpointsToBezier (from:lst)</span>
<span class="lineno"> 75 </span><span class="spaces"> </span><span class="istickedoff">tol = 0.0001</span>
<span class="lineno"> 76 </span><span class="spaces"> </span><span class="istickedoff">put (last lst)</span>
<span class="lineno"> 77 </span><span class="spaces"> </span><span class="istickedoff">pure $ Bezier.arcLength bezier 1 tol</span>
<span class="lineno"> 78 </span><span class="spaces"> </span><span class="istickedoff">LineEnd to -&gt; gets (distance to) &lt;* <span class="nottickedoff">put to</span></span></span>
<span class="lineno"> 79 </span>
<span class="lineno"> 80 </span>rpointsToBezier :: [RPoint] -&gt; Bezier.CubicBezier Double
<span class="lineno"> 81 </span><span class="decl"><span class="istickedoff">rpointsToBezier lst =</span>
<span class="lineno"> 82 </span><span class="spaces"> </span><span class="istickedoff">case lst of</span>
<span class="lineno"> 83 </span><span class="spaces"> </span><span class="istickedoff">[a,b] -&gt; <span class="nottickedoff">Bezier.CubicBezier a a b b</span></span>
<span class="lineno"> 84 </span><span class="spaces"> </span><span class="istickedoff">[a,b,c] -&gt; <span class="nottickedoff">Bezier.quadToCubic (Bezier.QuadBezier a b c)</span></span>
<span class="lineno"> 85 </span><span class="spaces"> </span><span class="istickedoff">[a,b,c,d] -&gt; Bezier.CubicBezier a b c d</span>
<span class="lineno"> 86 </span><span class="spaces"> </span><span class="istickedoff">_ -&gt; <span class="nottickedoff">error $ &quot;rpointsToBezier: Invalid list of points: &quot; ++ show lst</span></span></span>
<span class="lineno"> 87 </span>
<span class="lineno"> 88 </span>toLineCommands :: [PathCommand] -&gt; [LineCommand]
<span class="lineno"> 89 </span><span class="decl"><span class="istickedoff">toLineCommands ps = evalState (worker <span class="nottickedoff">zero</span> <span class="nottickedoff">Nothing</span> ps) <span class="nottickedoff">zero</span></span>
<span class="lineno"> 90 </span><span class="spaces"> </span><span class="istickedoff">where</span>
<span class="lineno"> 91 </span><span class="spaces"> </span><span class="istickedoff">worker _startPos _mbPrevControlPt [] = pure []</span>
<span class="lineno"> 92 </span><span class="spaces"> </span><span class="istickedoff">worker startPos mbPrevControlPt (cmd:cmds) = do</span>
<span class="lineno"> 93 </span><span class="spaces"> </span><span class="istickedoff">lcmds &lt;- toLineCommand startPos <span class="nottickedoff">mbPrevControlPt</span> cmd</span>
<span class="lineno"> 94 </span><span class="spaces"> </span><span class="istickedoff">let startPos' =</span>
<span class="lineno"> 95 </span><span class="spaces"> </span><span class="istickedoff">case lcmds of</span>
<span class="lineno"> 96 </span><span class="spaces"> </span><span class="istickedoff">[LineMove pos] -&gt; pos</span>
<span class="lineno"> 97 </span><span class="spaces"> </span><span class="istickedoff">_ -&gt; startPos</span>
<span class="lineno"> 98 </span><span class="spaces"> </span><span class="istickedoff">(lcmds++) &lt;$&gt; worker startPos' <span class="nottickedoff">(cmdToControlPoint $ last lcmds)</span> cmds</span></span>
<span class="lineno"> 99 </span>
<span class="lineno"> 100 </span>cmdToControlPoint :: LineCommand -&gt; Maybe RPoint
<span class="lineno"> 101 </span><span class="decl"><span class="nottickedoff">cmdToControlPoint (LineBezier points) = Just (last (init points))</span>
<span class="lineno"> 102 </span><span class="spaces"></span><span class="nottickedoff">cmdToControlPoint _ = Nothing</span></span>
<span class="lineno"> 103 </span>
<span class="lineno"> 104 </span>mkStraightLine :: RPoint -&gt; LineCommand
<span class="lineno"> 105 </span><span class="decl"><span class="istickedoff">mkStraightLine p = LineBezier [p]</span></span>
<span class="lineno"> 106 </span>
<span class="lineno"> 107 </span>toLineCommand :: RPoint -&gt; Maybe RPoint -&gt; PathCommand -&gt; CmdM [LineCommand]
<span class="lineno"> 108 </span><span class="decl"><span class="istickedoff">toLineCommand startPos mbPrevControlPt cmd =</span>
<span class="lineno"> 109 </span><span class="spaces"> </span><span class="istickedoff">case cmd of</span>
<span class="lineno"> 110 </span><span class="spaces"> </span><span class="istickedoff">MoveTo OriginAbsolute [] -&gt; <span class="nottickedoff">pure []</span></span>
<span class="lineno"> 111 </span><span class="spaces"> </span><span class="istickedoff">MoveTo OriginAbsolute lst -&gt; put (last lst) *&gt; gets (pure.LineMove)</span>
<span class="lineno"> 112 </span><span class="spaces"> </span><span class="istickedoff">MoveTo OriginRelative lst -&gt; <span class="nottickedoff">modify (+ sum lst) *&gt; gets (pure.LineMove)</span></span>
<span class="lineno"> 113 </span><span class="spaces"> </span><span class="istickedoff">LineTo OriginAbsolute lst -&gt; <span class="nottickedoff">forM lst (\to -&gt; put to $&gt; mkStraightLine to)</span></span>
<span class="lineno"> 114 </span><span class="spaces"> </span><span class="istickedoff">LineTo OriginRelative lst -&gt; <span class="nottickedoff">forM lst (\to -&gt; modify (+to) *&gt; gets mkStraightLine)</span></span>
<span class="lineno"> 115 </span><span class="spaces"> </span><span class="istickedoff">HorizontalTo OriginAbsolute lst -&gt;</span>
<span class="lineno"> 116 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">forM lst $ \x -&gt; modify (_x .~ x) *&gt; gets mkStraightLine</span></span>
<span class="lineno"> 117 </span><span class="spaces"> </span><span class="istickedoff">HorizontalTo OriginRelative lst -&gt;</span>
<span class="lineno"> 118 </span><span class="spaces"> </span><span class="istickedoff">forM lst $ \x -&gt; modify (_x %~ (+x)) *&gt; gets mkStraightLine</span>
<span class="lineno"> 119 </span><span class="spaces"> </span><span class="istickedoff">VerticalTo OriginAbsolute lst -&gt;</span>
<span class="lineno"> 120 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">forM lst $ \y -&gt; modify (_y .~ y) *&gt; gets mkStraightLine</span></span>
<span class="lineno"> 121 </span><span class="spaces"> </span><span class="istickedoff">VerticalTo OriginRelative lst -&gt;</span>
<span class="lineno"> 122 </span><span class="spaces"> </span><span class="istickedoff">forM lst $ \y -&gt; modify (_y %~ (+y)) *&gt; gets mkStraightLine</span>
<span class="lineno"> 123 </span><span class="spaces"> </span><span class="istickedoff">CurveTo OriginAbsolute quads -&gt;</span>
<span class="lineno"> 124 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">forM quads $ \(a,b,c) -&gt; put c $&gt; LineBezier [a,b,c]</span></span>
<span class="lineno"> 125 </span><span class="spaces"> </span><span class="istickedoff">CurveTo OriginRelative quads -&gt;</span>
<span class="lineno"> 126 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">forM quads $ \(a,b,c) -&gt; do</span></span>
<span class="lineno"> 127 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">from &lt;- get &lt;* modify (+c)</span></span>
<span class="lineno"> 128 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">pure $ LineBezier $ map (+from) [a,b,c]</span></span>
<span class="lineno"> 129 </span><span class="spaces"> </span><span class="istickedoff">SmoothCurveTo o lst -&gt; <span class="nottickedoff">mfix $ \result -&gt; do</span></span>
<span class="lineno"> 130 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">let ctrl = mbPrevControlPt : map cmdToControlPoint result</span></span>
<span class="lineno"> 131 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">forM (zip lst ctrl) $ \((c2,to), mbControl) -&gt; do</span></span>
<span class="lineno"> 132 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">from &lt;- get &lt;* adjustPosition o to</span></span>
<span class="lineno"> 133 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">let c1 = maybe (makeAbsolute o from c2) (mirrorPoint from) mbControl</span></span>
<span class="lineno"> 134 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">pure $ LineBezier [c1,makeAbsolute o from c2,makeAbsolute o from to]</span></span>
<span class="lineno"> 135 </span><span class="spaces"> </span><span class="istickedoff">QuadraticBezier OriginAbsolute pairs -&gt;</span>
<span class="lineno"> 136 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">forM pairs $ \(a,b) -&gt; put b $&gt; LineBezier [a,b]</span></span>
<span class="lineno"> 137 </span><span class="spaces"> </span><span class="istickedoff">QuadraticBezier OriginRelative pairs -&gt;</span>
<span class="lineno"> 138 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">forM pairs $ \(a,b) -&gt; do</span></span>
<span class="lineno"> 139 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">from &lt;- get &lt;* modify (+b)</span></span>
<span class="lineno"> 140 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">pure $ LineBezier $ map (+from) [a,b]</span></span>
<span class="lineno"> 141 </span><span class="spaces"> </span><span class="istickedoff">SmoothQuadraticBezierCurveTo o lst -&gt; <span class="nottickedoff">mfix $ \result -&gt; do</span></span>
<span class="lineno"> 142 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">let ctrl = mbPrevControlPt : map cmdToControlPoint result</span></span>
<span class="lineno"> 143 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">forM (zip lst ctrl) $ \(to, mbControl) -&gt; do</span></span>
<span class="lineno"> 144 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">from &lt;- get &lt;* adjustPosition o to</span></span>
<span class="lineno"> 145 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">let c1 = maybe from (mirrorPoint from) mbControl</span></span>
<span class="lineno"> 146 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">pure $ LineBezier [c1,makeAbsolute o from to]</span></span>
<span class="lineno"> 147 </span><span class="spaces"> </span><span class="istickedoff">EllipticalArc o points -&gt; concat &lt;$&gt;</span>
<span class="lineno"> 148 </span><span class="spaces"> </span><span class="istickedoff">forM points (\(rotX, rotY, angle, largeArc, sweepFlag, to) -&gt; do</span>
<span class="lineno"> 149 </span><span class="spaces"> </span><span class="istickedoff">from &lt;- get &lt;* adjustPosition o to</span>
<span class="lineno"> 150 </span><span class="spaces"> </span><span class="istickedoff">return $ convertSvgArc from rotX rotY angle largeArc sweepFlag (makeAbsolute o from to))</span>
<span class="lineno"> 151 </span><span class="spaces"> </span><span class="istickedoff">EndPath -&gt; <span class="nottickedoff">put startPos</span> $&gt; [LineEnd startPos]</span>
<span class="lineno"> 152 </span><span class="spaces"> </span><span class="istickedoff">where</span>
<span class="lineno"> 153 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">mirrorPoint c p = c*2-p</span></span>
<span class="lineno"> 154 </span><span class="spaces"> </span><span class="istickedoff">adjustPosition OriginRelative p = modify (+p)</span>
<span class="lineno"> 155 </span><span class="spaces"> </span><span class="istickedoff">adjustPosition OriginAbsolute p = <span class="nottickedoff">put p</span></span>
<span class="lineno"> 156 </span><span class="spaces"> </span><span class="istickedoff">makeAbsolute OriginAbsolute _from p = <span class="nottickedoff">p</span></span>
<span class="lineno"> 157 </span><span class="spaces"> </span><span class="istickedoff">makeAbsolute OriginRelative from p = from+p</span></span>
<span class="lineno"> 158 </span>
<span class="lineno"> 159 </span>
<span class="lineno"> 160 </span>calculateVectorAngle :: Double -&gt; Double -&gt; Double -&gt; Double -&gt; Double
<span class="lineno"> 161 </span><span class="decl"><span class="istickedoff">calculateVectorAngle ux uy vx vy</span>
<span class="lineno"> 162 </span><span class="spaces"> </span><span class="istickedoff">| tb &gt;= ta</span>
<span class="lineno"> 163 </span><span class="spaces"> </span><span class="istickedoff">= tb - ta</span>
<span class="lineno"> 164 </span><span class="spaces"> </span><span class="istickedoff">| <span class="tickonlytrue">otherwise</span></span>
<span class="lineno"> 165 </span><span class="spaces"> </span><span class="istickedoff">= pi * 2 - (ta - tb)</span>
<span class="lineno"> 166 </span><span class="spaces"> </span><span class="istickedoff">where</span>
<span class="lineno"> 167 </span><span class="spaces"> </span><span class="istickedoff">ta = atan2 uy ux</span>
<span class="lineno"> 168 </span><span class="spaces"> </span><span class="istickedoff">tb = atan2 vy vx</span></span>
<span class="lineno"> 169 </span>
<span class="lineno"> 170 </span>-- ported from: https://github.com/vvvv/SVG/blob/master/Source/Paths/SvgArcSegment.cs
<span class="lineno"> 171 </span>{- HLINT ignore convertSvgArc -}
<span class="lineno"> 172 </span>convertSvgArc :: RPoint -&gt; Coord -&gt; Coord -&gt; Coord -&gt; Bool -&gt; Bool -&gt; RPoint -&gt; [LineCommand]
<span class="lineno"> 173 </span><span class="decl"><span class="istickedoff">convertSvgArc (V2 x0 y0) radiusX radiusY angle largeArcFlag sweepFlag (V2 x y)</span>
<span class="lineno"> 174 </span><span class="spaces"> </span><span class="istickedoff">| <span class="tickonlyfalse">x0 == x &amp;&amp; <span class="nottickedoff">y0 == y</span></span></span>
<span class="lineno"> 175 </span><span class="spaces"> </span><span class="istickedoff">= <span class="nottickedoff">[]</span></span>
<span class="lineno"> 176 </span><span class="spaces"> </span><span class="istickedoff">| <span class="tickonlyfalse">radiusX == 0.0 &amp;&amp; <span class="nottickedoff">radiusY == 0.0</span></span></span>
<span class="lineno"> 177 </span><span class="spaces"> </span><span class="istickedoff">= <span class="nottickedoff">[LineBezier [V2 x y]]</span></span>
<span class="lineno"> 178 </span><span class="spaces"> </span><span class="istickedoff">| <span class="tickonlytrue">otherwise</span></span>
<span class="lineno"> 179 </span><span class="spaces"> </span><span class="istickedoff">= calcSegments x0 y0 theta1' segments'</span>
<span class="lineno"> 180 </span><span class="spaces"> </span><span class="istickedoff">where</span>
<span class="lineno"> 181 </span><span class="spaces"> </span><span class="istickedoff">sinPhi = sin (angle * pi/180)</span>
<span class="lineno"> 182 </span><span class="spaces"> </span><span class="istickedoff">cosPhi = cos (angle * pi/180)</span>
<span class="lineno"> 183 </span><span class="spaces"></span><span class="istickedoff"></span>
<span class="lineno"> 184 </span><span class="spaces"> </span><span class="istickedoff">x1dash = cosPhi * (x0 - x) / 2.0 + sinPhi * (y0 - y) / 2.0</span>
<span class="lineno"> 185 </span><span class="spaces"> </span><span class="istickedoff">y1dash = -sinPhi * (x0 - x) / 2.0 + cosPhi * (y0 - y) / 2.0</span>
<span class="lineno"> 186 </span><span class="spaces"></span><span class="istickedoff"></span>
<span class="lineno"> 187 </span><span class="spaces"> </span><span class="istickedoff">numerator = radiusX * radiusX * radiusY * radiusY - radiusX * radiusX * y1dash * y1dash - radiusY * radiusY * x1dash * x1dash</span>
<span class="lineno"> 188 </span><span class="spaces"></span><span class="istickedoff"></span>
<span class="lineno"> 189 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">s = sqrt(1.0 - numerator / (radiusX * radiusX * radiusY * radiusY))</span></span>
<span class="lineno"> 190 </span><span class="spaces"> </span><span class="istickedoff">rx = if <span class="tickonlyfalse">(numerator &lt; 0.0)</span> then <span class="nottickedoff">(radiusX * s)</span> else radiusX</span>
<span class="lineno"> 191 </span><span class="spaces"> </span><span class="istickedoff">ry = if <span class="tickonlyfalse">(numerator &lt; 0.0)</span> then <span class="nottickedoff">(radiusY * s)</span> else radiusY</span>
<span class="lineno"> 192 </span><span class="spaces"> </span><span class="istickedoff">root = if <span class="tickonlyfalse">(numerator &lt; 0.0)</span></span>
<span class="lineno"> 193 </span><span class="spaces"> </span><span class="istickedoff">then <span class="nottickedoff">(0.0)</span></span>
<span class="lineno"> 194 </span><span class="spaces"> </span><span class="istickedoff">else ((if <span class="tickonlyfalse">((largeArcFlag &amp;&amp; sweepFlag) || (not largeArcFlag &amp;&amp; <span class="nottickedoff">not sweepFlag</span>))</span> then <span class="nottickedoff">(-1.0)</span> else 1.0) *</span>
<span class="lineno"> 195 </span><span class="spaces"> </span><span class="istickedoff">sqrt(numerator / (radiusX * radiusX * y1dash * y1dash + radiusY * radiusY * x1dash * x1dash)))</span>
<span class="lineno"> 196 </span><span class="spaces"></span><span class="istickedoff"></span>
<span class="lineno"> 197 </span><span class="spaces"> </span><span class="istickedoff">cxdash = root * rx * y1dash / ry</span>
<span class="lineno"> 198 </span><span class="spaces"> </span><span class="istickedoff">cydash = -root * ry * x1dash / rx</span>
<span class="lineno"> 199 </span><span class="spaces"></span><span class="istickedoff"></span>
<span class="lineno"> 200 </span><span class="spaces"> </span><span class="istickedoff">cx = cosPhi * cxdash - sinPhi * cydash + (x0 + x) / 2.0</span>
<span class="lineno"> 201 </span><span class="spaces"> </span><span class="istickedoff">cy = sinPhi * cxdash + cosPhi * cydash + (y0 + y) / 2.0</span>
<span class="lineno"> 202 </span><span class="spaces"></span><span class="istickedoff"></span>
<span class="lineno"> 203 </span><span class="spaces"> </span><span class="istickedoff">theta1' = calculateVectorAngle 1.0 0.0 ((x1dash - cxdash) / rx) ((y1dash - cydash) / ry)</span>
<span class="lineno"> 204 </span><span class="spaces"> </span><span class="istickedoff">dtheta' = calculateVectorAngle ((x1dash - cxdash) / rx) ((y1dash - cydash) / ry) ((-x1dash - cxdash) / rx) ((-y1dash - cydash) / ry)</span>
<span class="lineno"> 205 </span><span class="spaces"> </span><span class="istickedoff">dtheta = if <span class="tickonlytrue">(not sweepFlag &amp;&amp; dtheta' &gt; 0)</span></span>
<span class="lineno"> 206 </span><span class="spaces"> </span><span class="istickedoff">then (dtheta' - 2 * pi)</span>
<span class="lineno"> 207 </span><span class="spaces"> </span><span class="istickedoff">else <span class="nottickedoff">(if (sweepFlag &amp;&amp; dtheta' &lt; 0) then dtheta' + 2 * pi else dtheta')</span></span>
<span class="lineno"> 208 </span><span class="spaces"></span><span class="istickedoff"></span>
<span class="lineno"> 209 </span><span class="spaces"> </span><span class="istickedoff">segments' = ceiling (abs (dtheta / (pi / 2.0)))</span>
<span class="lineno"> 210 </span><span class="spaces"> </span><span class="istickedoff">delta = dtheta / fromInteger segments'</span>
<span class="lineno"> 211 </span><span class="spaces"> </span><span class="istickedoff">t = 8.0 / 3.0 * sin(delta / 4.0) * sin(delta / 4.0) / sin(delta / 2.0)</span>
<span class="lineno"> 212 </span><span class="spaces"></span><span class="istickedoff"></span>
<span class="lineno"> 213 </span><span class="spaces"> </span><span class="istickedoff">calcSegments startX startY theta1 segments</span>
<span class="lineno"> 214 </span><span class="spaces"> </span><span class="istickedoff">| segments == 0</span>
<span class="lineno"> 215 </span><span class="spaces"> </span><span class="istickedoff">= []</span>
<span class="lineno"> 216 </span><span class="spaces"> </span><span class="istickedoff">| <span class="tickonlytrue">otherwise</span></span>
<span class="lineno"> 217 </span><span class="spaces"> </span><span class="istickedoff">= LineBezier [ V2 (startX + dx1) (startY + dy1)</span>
<span class="lineno"> 218 </span><span class="spaces"> </span><span class="istickedoff">, V2 (endpointX + dxe) (endpointY + dye)</span>
<span class="lineno"> 219 </span><span class="spaces"> </span><span class="istickedoff">, V2 endpointX endpointY ] : calcSegments endpointX endpointY theta2 (segments - 1)</span>
<span class="lineno"> 220 </span><span class="spaces"> </span><span class="istickedoff">where</span>
<span class="lineno"> 221 </span><span class="spaces"> </span><span class="istickedoff">cosTheta1 = cos theta1</span>
<span class="lineno"> 222 </span><span class="spaces"> </span><span class="istickedoff">sinTheta1 = sin theta1</span>
<span class="lineno"> 223 </span><span class="spaces"> </span><span class="istickedoff">theta2 = theta1 + delta</span>
<span class="lineno"> 224 </span><span class="spaces"> </span><span class="istickedoff">cosTheta2 = cos theta2</span>
<span class="lineno"> 225 </span><span class="spaces"> </span><span class="istickedoff">sinTheta2 = sin theta2</span>
<span class="lineno"> 226 </span><span class="spaces"></span><span class="istickedoff"></span>
<span class="lineno"> 227 </span><span class="spaces"> </span><span class="istickedoff">endpointX = cosPhi * rx * cosTheta2 - sinPhi * ry * sinTheta2 + cx</span>
<span class="lineno"> 228 </span><span class="spaces"> </span><span class="istickedoff">endpointY = sinPhi * rx * cosTheta2 + cosPhi * ry * sinTheta2 + cy</span>
<span class="lineno"> 229 </span><span class="spaces"></span><span class="istickedoff"></span>
<span class="lineno"> 230 </span><span class="spaces"> </span><span class="istickedoff">dx1 = t * (-cosPhi * rx * sinTheta1 - sinPhi * ry * cosTheta1)</span>
<span class="lineno"> 231 </span><span class="spaces"> </span><span class="istickedoff">dy1 = t * (-sinPhi * rx * sinTheta1 + cosPhi * ry * cosTheta1)</span>
<span class="lineno"> 232 </span><span class="spaces"></span><span class="istickedoff"></span>
<span class="lineno"> 233 </span><span class="spaces"> </span><span class="istickedoff">dxe = t * (cosPhi * rx * sinTheta2 + sinPhi * ry * cosTheta2)</span>
<span class="lineno"> 234 </span><span class="spaces"> </span><span class="istickedoff">dye = t * (sinPhi * rx * sinTheta2 - cosPhi * ry * cosTheta2)</span></span>
<span class="lineno"> 235 </span>
<span class="lineno"> 236 </span>partialBezierPoints :: [RPoint] -&gt; Double -&gt; Double -&gt; [RPoint]
<span class="lineno"> 237 </span><span class="decl"><span class="istickedoff">partialBezierPoints ps a b =</span>
<span class="lineno"> 238 </span><span class="spaces"> </span><span class="istickedoff">let c1 = Bezier.AnyBezier (V.fromList ps)</span>
<span class="lineno"> 239 </span><span class="spaces"> </span><span class="istickedoff">Bezier.AnyBezier os = Bezier.bezierSubsegment c1 a b</span>
<span class="lineno"> 240 </span><span class="spaces"> </span><span class="istickedoff">in V.toList os</span></span>
<span class="lineno"> 241 </span>
<span class="lineno"> 242 </span>interpolatePathCommands :: Double -&gt; [PathCommand] -&gt; [PathCommand]
<span class="lineno"> 243 </span><span class="decl"><span class="nottickedoff">interpolatePathCommands alpha = lineToPath . partialLine alpha . toLineCommands</span></span>
<span class="lineno"> 244 </span>
<span class="lineno"> 245 </span>{- | Create an image showing portion of a path.
<span class="lineno"> 246 </span> Note that this only affects paths (see 'Reanimate.Svg.Constructors.mkPath').
<span class="lineno"> 247 </span> You can also use this with other SVG shapes if you convert them to path first (see 'Reanimate.Svg.pathify').
<span class="lineno"> 248 </span>
<span class="lineno"> 249 </span> Typical usage:
<span class="lineno"> 250 </span>
<span class="lineno"> 251 </span> &gt; animate $ \t -&gt; partialSvg t myPath
<span class="lineno"> 252 </span>-}
<span class="lineno"> 253 </span>partialSvg :: Double -- ^ number between 0 and 1 inclusively, determining what portion of the path to show
<span class="lineno"> 254 </span> -&gt; Tree -- ^ Image representing a path, of which we only want to display a portion determined by the first argument
<span class="lineno"> 255 </span> -&gt; Tree
<span class="lineno"> 256 </span><span class="decl"><span class="istickedoff">partialSvg alpha | alpha &gt;= 1 = id</span>
<span class="lineno"> 257 </span><span class="spaces"></span><span class="istickedoff">partialSvg alpha = mapTree worker</span>
<span class="lineno"> 258 </span><span class="spaces"> </span><span class="istickedoff">where</span>
<span class="lineno"> 259 </span><span class="spaces"> </span><span class="istickedoff">worker (PathTree path) =</span>
<span class="lineno"> 260 </span><span class="spaces"> </span><span class="istickedoff">PathTree $ path &amp; pathDefinition %~ lineToPath . partialLine alpha . toLineCommands</span>
<span class="lineno"> 261 </span><span class="spaces"> </span><span class="istickedoff">worker t = t</span></span>
</pre>
</body>
</html>

View file

@ -0,0 +1,83 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style type="text/css">
span.lineno { color: white; background: #aaaaaa; border-right: solid white 12px }
span.nottickedoff { background: yellow}
span.istickedoff { background: white }
span.tickonlyfalse { margin: -1px; border: 1px solid #f20913; background: #f20913 }
span.tickonlytrue { margin: -1px; border: 1px solid #60de51; background: #60de51 }
span.funcount { font-size: small; color: orange; z-index: 2; position: absolute; right: 20 }
span.decl { font-weight: bold }
span.spaces { background: white }
</style>
</head>
<body>
<pre>
<span class="decl"><span class="nottickedoff">never executed</span> <span class="tickonlytrue">always true</span> <span class="tickonlyfalse">always false</span></span>
</pre>
<pre>
<span class="lineno"> 1 </span>module Reanimate.Svg.Unuse
<span class="lineno"> 2 </span> ( replaceUses
<span class="lineno"> 3 </span> , unbox
<span class="lineno"> 4 </span> , embedDocument
<span class="lineno"> 5 </span> ) where
<span class="lineno"> 6 </span>
<span class="lineno"> 7 </span>import Control.Lens ((%~), (&amp;), (.~), (?~), (^.))
<span class="lineno"> 8 </span>import qualified Data.Map as Map
<span class="lineno"> 9 </span>import Data.Maybe
<span class="lineno"> 10 </span>import Graphics.SvgTree hiding (line, path, use)
<span class="lineno"> 11 </span>import Reanimate.Constants
<span class="lineno"> 12 </span>import Reanimate.Svg.Constructors
<span class="lineno"> 13 </span>
<span class="lineno"> 14 </span>replaceUses :: Document -&gt; Document
<span class="lineno"> 15 </span><span class="decl"><span class="nottickedoff">replaceUses doc = doc &amp; elements %~ map (mapTree replace)</span>
<span class="lineno"> 16 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 17 </span><span class="spaces"> </span><span class="nottickedoff">replaceDefinition PathTree{} = None</span>
<span class="lineno"> 18 </span><span class="spaces"> </span><span class="nottickedoff">replaceDefinition t = t</span>
<span class="lineno"> 19 </span><span class="spaces"></span><span class="nottickedoff"></span>
<span class="lineno"> 20 </span><span class="spaces"> </span><span class="nottickedoff">replace t@DefinitionTree{} = mapTree replaceDefinition t</span>
<span class="lineno"> 21 </span><span class="spaces"> </span><span class="nottickedoff">replace (UseTree _ Just{}) = error &quot;replaceUses: subtree in use?&quot;</span>
<span class="lineno"> 22 </span><span class="spaces"> </span><span class="nottickedoff">replace (UseTree use Nothing) =</span>
<span class="lineno"> 23 </span><span class="spaces"> </span><span class="nottickedoff">case Map.lookup (use^.useName) idMap of</span>
<span class="lineno"> 24 </span><span class="spaces"> </span><span class="nottickedoff">Nothing -&gt; error $ &quot;Unknown id: &quot; ++ (use^.useName)</span>
<span class="lineno"> 25 </span><span class="spaces"> </span><span class="nottickedoff">Just tree -&gt; mapTree replace $</span>
<span class="lineno"> 26 </span><span class="spaces"> </span><span class="nottickedoff">GroupTree $</span>
<span class="lineno"> 27 </span><span class="spaces"> </span><span class="nottickedoff">defaultSvg &amp; groupChildren .~ [tree]</span>
<span class="lineno"> 28 </span><span class="spaces"> </span><span class="nottickedoff">&amp; transform ?~</span>
<span class="lineno"> 29 </span><span class="spaces"> </span><span class="nottickedoff">fromMaybe [] (use^.transform) ++</span>
<span class="lineno"> 30 </span><span class="spaces"> </span><span class="nottickedoff">[baseToTransformation (use^.useBase)]</span>
<span class="lineno"> 31 </span><span class="spaces"> </span><span class="nottickedoff">replace x = x</span>
<span class="lineno"> 32 </span><span class="spaces"> </span><span class="nottickedoff">baseToTransformation (x,y) =</span>
<span class="lineno"> 33 </span><span class="spaces"> </span><span class="nottickedoff">case (toUserUnit defaultDPI x, toUserUnit defaultDPI y) of</span>
<span class="lineno"> 34 </span><span class="spaces"> </span><span class="nottickedoff">(Num a, Num b) -&gt; Translate a b</span>
<span class="lineno"> 35 </span><span class="spaces"> </span><span class="nottickedoff">_ -&gt; TransformUnknown</span>
<span class="lineno"> 36 </span><span class="spaces"> </span><span class="nottickedoff">docTree = mkGroup (doc^.elements)</span>
<span class="lineno"> 37 </span><span class="spaces"> </span><span class="nottickedoff">idMap = foldTree updMap Map.empty docTree</span>
<span class="lineno"> 38 </span><span class="spaces"> </span><span class="nottickedoff">updMap m tree =</span>
<span class="lineno"> 39 </span><span class="spaces"> </span><span class="nottickedoff">case tree^.attrId of</span>
<span class="lineno"> 40 </span><span class="spaces"> </span><span class="nottickedoff">Nothing -&gt; m</span>
<span class="lineno"> 41 </span><span class="spaces"> </span><span class="nottickedoff">Just tid -&gt; Map.insert tid tree m</span></span>
<span class="lineno"> 42 </span>
<span class="lineno"> 43 </span>-- FIXME: the viewbox is ignored. Can we use the viewbox as a mask?
<span class="lineno"> 44 </span>-- Transform out viewbox. defs and CSS rules are discarded.
<span class="lineno"> 45 </span>unbox :: Document -&gt; Tree
<span class="lineno"> 46 </span><span class="decl"><span class="nottickedoff">unbox doc@Document{_viewBox = Just (_minx, _minw, _width, _height)} =</span>
<span class="lineno"> 47 </span><span class="spaces"> </span><span class="nottickedoff">GroupTree $ defaultSvg</span>
<span class="lineno"> 48 </span><span class="spaces"> </span><span class="nottickedoff">&amp; groupChildren .~ doc^.elements</span>
<span class="lineno"> 49 </span><span class="spaces"></span><span class="nottickedoff">unbox doc =</span>
<span class="lineno"> 50 </span><span class="spaces"> </span><span class="nottickedoff">GroupTree $ defaultSvg</span>
<span class="lineno"> 51 </span><span class="spaces"> </span><span class="nottickedoff">&amp; groupChildren .~ doc^.elements</span></span>
<span class="lineno"> 52 </span>
<span class="lineno"> 53 </span>embedDocument :: Document -&gt; Tree
<span class="lineno"> 54 </span><span class="decl"><span class="nottickedoff">embedDocument doc =</span>
<span class="lineno"> 55 </span><span class="spaces"> </span><span class="nottickedoff">translate (-screenWidth/2) (screenHeight/2) $</span>
<span class="lineno"> 56 </span><span class="spaces"> </span><span class="nottickedoff">withFillOpacity 1 $</span>
<span class="lineno"> 57 </span><span class="spaces"> </span><span class="nottickedoff">withStrokeWidth 0 $</span>
<span class="lineno"> 58 </span><span class="spaces"> </span><span class="nottickedoff">flipYAxis $</span>
<span class="lineno"> 59 </span><span class="spaces"> </span><span class="nottickedoff">SvgTree $ doc &amp; width .~ Nothing</span>
<span class="lineno"> 60 </span><span class="spaces"> </span><span class="nottickedoff">&amp; height .~ Nothing</span></span>
</pre>
</body>
</html>

View file

@ -0,0 +1,336 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style type="text/css">
span.lineno { color: white; background: #aaaaaa; border-right: solid white 12px }
span.nottickedoff { background: yellow}
span.istickedoff { background: white }
span.tickonlyfalse { margin: -1px; border: 1px solid #f20913; background: #f20913 }
span.tickonlytrue { margin: -1px; border: 1px solid #60de51; background: #60de51 }
span.funcount { font-size: small; color: orange; z-index: 2; position: absolute; right: 20 }
span.decl { font-weight: bold }
span.spaces { background: white }
</style>
</head>
<body>
<pre>
<span class="decl"><span class="nottickedoff">never executed</span> <span class="tickonlytrue">always true</span> <span class="tickonlyfalse">always false</span></span>
</pre>
<pre>
<span class="lineno"> 1 </span>{-# LANGUAGE LambdaCase #-}
<span class="lineno"> 2 </span>module Reanimate.Svg
<span class="lineno"> 3 </span> ( module Reanimate.Svg
<span class="lineno"> 4 </span> , module Reanimate.Svg.Constructors
<span class="lineno"> 5 </span> , module Reanimate.Svg.LineCommand
<span class="lineno"> 6 </span> , module Reanimate.Svg.BoundingBox
<span class="lineno"> 7 </span> , module Reanimate.Svg.Unuse
<span class="lineno"> 8 </span> ) where
<span class="lineno"> 9 </span>
<span class="lineno"> 10 </span>import Control.Lens ((%~), (&amp;), (.~), (^.), (?~))
<span class="lineno"> 11 </span>import Control.Monad.State
<span class="lineno"> 12 </span>import Graphics.SvgTree hiding (height, line, path, use,
<span class="lineno"> 13 </span> width)
<span class="lineno"> 14 </span>import Linear.V2 hiding (angle)
<span class="lineno"> 15 </span>import Reanimate.Constants
<span class="lineno"> 16 </span>import Reanimate.Animation (SVG)
<span class="lineno"> 17 </span>import Reanimate.Svg.Constructors
<span class="lineno"> 18 </span>import Reanimate.Svg.LineCommand
<span class="lineno"> 19 </span>import Reanimate.Svg.BoundingBox
<span class="lineno"> 20 </span>import Reanimate.Svg.Unuse
<span class="lineno"> 21 </span>import qualified Reanimate.Transform as Transform
<span class="lineno"> 22 </span>
<span class="lineno"> 23 </span>lowerTransformations :: Tree -&gt; Tree
<span class="lineno"> 24 </span><span class="decl"><span class="nottickedoff">lowerTransformations = worker False Transform.identity</span>
<span class="lineno"> 25 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 26 </span><span class="spaces"> </span><span class="nottickedoff">updLineCmd m cmd =</span>
<span class="lineno"> 27 </span><span class="spaces"> </span><span class="nottickedoff">case cmd of</span>
<span class="lineno"> 28 </span><span class="spaces"> </span><span class="nottickedoff">LineMove p -&gt; LineMove $ Transform.transformPoint m p</span>
<span class="lineno"> 29 </span><span class="spaces"> </span><span class="nottickedoff">-- LineDraw p -&gt; LineDraw $ Transform.transformPoint m p</span>
<span class="lineno"> 30 </span><span class="spaces"> </span><span class="nottickedoff">LineBezier ps -&gt; LineBezier $ map (Transform.transformPoint m) ps</span>
<span class="lineno"> 31 </span><span class="spaces"> </span><span class="nottickedoff">LineEnd p -&gt; LineEnd $ Transform.transformPoint m p</span>
<span class="lineno"> 32 </span><span class="spaces"> </span><span class="nottickedoff">updPath m = lineToPath . map (updLineCmd m) . toLineCommands</span>
<span class="lineno"> 33 </span><span class="spaces"> </span><span class="nottickedoff">updPoint m (Num a,Num b) =</span>
<span class="lineno"> 34 </span><span class="spaces"> </span><span class="nottickedoff">case Transform.transformPoint m (V2 a b) of</span>
<span class="lineno"> 35 </span><span class="spaces"> </span><span class="nottickedoff">V2 x y -&gt; (Num x, Num y)</span>
<span class="lineno"> 36 </span><span class="spaces"> </span><span class="nottickedoff">updPoint _ other = other -- XXX: Can we do better here?</span>
<span class="lineno"> 37 </span><span class="spaces"> </span><span class="nottickedoff">worker hasPathified m t =</span>
<span class="lineno"> 38 </span><span class="spaces"> </span><span class="nottickedoff">let m' = m * Transform.mkMatrix (t^.transform) in</span>
<span class="lineno"> 39 </span><span class="spaces"> </span><span class="nottickedoff">case t of</span>
<span class="lineno"> 40 </span><span class="spaces"> </span><span class="nottickedoff">PathTree path -&gt; PathTree $</span>
<span class="lineno"> 41 </span><span class="spaces"> </span><span class="nottickedoff">path &amp; pathDefinition %~ updPath m'</span>
<span class="lineno"> 42 </span><span class="spaces"> </span><span class="nottickedoff">&amp; transform .~ Nothing</span>
<span class="lineno"> 43 </span><span class="spaces"> </span><span class="nottickedoff">GroupTree g -&gt; GroupTree $</span>
<span class="lineno"> 44 </span><span class="spaces"> </span><span class="nottickedoff">g &amp; groupChildren %~ map (worker hasPathified m')</span>
<span class="lineno"> 45 </span><span class="spaces"> </span><span class="nottickedoff">&amp; transform .~ Nothing</span>
<span class="lineno"> 46 </span><span class="spaces"> </span><span class="nottickedoff">LineTree line -&gt;</span>
<span class="lineno"> 47 </span><span class="spaces"> </span><span class="nottickedoff">LineTree $</span>
<span class="lineno"> 48 </span><span class="spaces"> </span><span class="nottickedoff">line &amp; linePoint1 %~ updPoint m</span>
<span class="lineno"> 49 </span><span class="spaces"> </span><span class="nottickedoff">&amp; linePoint2 %~ updPoint m</span>
<span class="lineno"> 50 </span><span class="spaces"> </span><span class="nottickedoff">ClipPathTree{} -&gt; t</span>
<span class="lineno"> 51 </span><span class="spaces"> </span><span class="nottickedoff">-- If we encounter an unknown node and we've already tried to convert</span>
<span class="lineno"> 52 </span><span class="spaces"> </span><span class="nottickedoff">-- to paths, give up and insert an explicit transformation.</span>
<span class="lineno"> 53 </span><span class="spaces"> </span><span class="nottickedoff">_ | hasPathified -&gt;</span>
<span class="lineno"> 54 </span><span class="spaces"> </span><span class="nottickedoff">mkGroup [t] &amp; transform ?~ [ Transform.toTransformation m ]</span>
<span class="lineno"> 55 </span><span class="spaces"> </span><span class="nottickedoff">-- If we haven't tried to pathify, run pathify only once.</span>
<span class="lineno"> 56 </span><span class="spaces"> </span><span class="nottickedoff">_ -&gt; worker True m (pathify t)</span></span>
<span class="lineno"> 57 </span>
<span class="lineno"> 58 </span>lowerIds :: Tree -&gt; Tree
<span class="lineno"> 59 </span><span class="decl"><span class="nottickedoff">lowerIds = mapTree worker</span>
<span class="lineno"> 60 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 61 </span><span class="spaces"> </span><span class="nottickedoff">worker t@GroupTree{} = t &amp; attrId .~ Nothing</span>
<span class="lineno"> 62 </span><span class="spaces"> </span><span class="nottickedoff">worker t@PathTree{} = t &amp; attrId .~ Nothing</span>
<span class="lineno"> 63 </span><span class="spaces"> </span><span class="nottickedoff">worker t = t</span></span>
<span class="lineno"> 64 </span>
<span class="lineno"> 65 </span>simplify :: Tree -&gt; Tree
<span class="lineno"> 66 </span><span class="decl"><span class="nottickedoff">simplify root =</span>
<span class="lineno"> 67 </span><span class="spaces"> </span><span class="nottickedoff">case worker root of</span>
<span class="lineno"> 68 </span><span class="spaces"> </span><span class="nottickedoff">[] -&gt; None</span>
<span class="lineno"> 69 </span><span class="spaces"> </span><span class="nottickedoff">[x] -&gt; x</span>
<span class="lineno"> 70 </span><span class="spaces"> </span><span class="nottickedoff">xs -&gt; mkGroup xs</span>
<span class="lineno"> 71 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 72 </span><span class="spaces"> </span><span class="nottickedoff">worker None = []</span>
<span class="lineno"> 73 </span><span class="spaces"> </span><span class="nottickedoff">worker (DefinitionTree d) =</span>
<span class="lineno"> 74 </span><span class="spaces"> </span><span class="nottickedoff">concatMap dropNulls</span>
<span class="lineno"> 75 </span><span class="spaces"> </span><span class="nottickedoff">[DefinitionTree $ d &amp; groupChildren %~ concatMap worker]</span>
<span class="lineno"> 76 </span><span class="spaces"> </span><span class="nottickedoff">worker (GroupTree g)</span>
<span class="lineno"> 77 </span><span class="spaces"> </span><span class="nottickedoff">| g ^. drawAttributes == defaultSvg =</span>
<span class="lineno"> 78 </span><span class="spaces"> </span><span class="nottickedoff">concatMap dropNulls $</span>
<span class="lineno"> 79 </span><span class="spaces"> </span><span class="nottickedoff">concatMap worker (g^.groupChildren)</span>
<span class="lineno"> 80 </span><span class="spaces"> </span><span class="nottickedoff">| otherwise =</span>
<span class="lineno"> 81 </span><span class="spaces"> </span><span class="nottickedoff">dropNulls $</span>
<span class="lineno"> 82 </span><span class="spaces"> </span><span class="nottickedoff">GroupTree $ g &amp; groupChildren %~ concatMap worker</span>
<span class="lineno"> 83 </span><span class="spaces"> </span><span class="nottickedoff">worker t = dropNulls t</span>
<span class="lineno"> 84 </span><span class="spaces"></span><span class="nottickedoff"></span>
<span class="lineno"> 85 </span><span class="spaces"> </span><span class="nottickedoff">dropNulls None = []</span>
<span class="lineno"> 86 </span><span class="spaces"> </span><span class="nottickedoff">dropNulls (DefinitionTree d)</span>
<span class="lineno"> 87 </span><span class="spaces"> </span><span class="nottickedoff">| null (d^.groupChildren) = []</span>
<span class="lineno"> 88 </span><span class="spaces"> </span><span class="nottickedoff">dropNulls (GroupTree g)</span>
<span class="lineno"> 89 </span><span class="spaces"> </span><span class="nottickedoff">| null (g^.groupChildren) = []</span>
<span class="lineno"> 90 </span><span class="spaces"> </span><span class="nottickedoff">dropNulls t = [t]</span></span>
<span class="lineno"> 91 </span>
<span class="lineno"> 92 </span>removeGroups :: Tree -&gt; [Tree]
<span class="lineno"> 93 </span><span class="decl"><span class="nottickedoff">removeGroups = worker defaultSvg</span>
<span class="lineno"> 94 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 95 </span><span class="spaces"> </span><span class="nottickedoff">worker _attr None = []</span>
<span class="lineno"> 96 </span><span class="spaces"> </span><span class="nottickedoff">worker _attr (DefinitionTree d) =</span>
<span class="lineno"> 97 </span><span class="spaces"> </span><span class="nottickedoff">concatMap dropNulls</span>
<span class="lineno"> 98 </span><span class="spaces"> </span><span class="nottickedoff">[DefinitionTree $ d &amp; groupChildren %~ concatMap (worker defaultSvg)]</span>
<span class="lineno"> 99 </span><span class="spaces"> </span><span class="nottickedoff">worker attr (GroupTree g)</span>
<span class="lineno"> 100 </span><span class="spaces"> </span><span class="nottickedoff">| g ^. drawAttributes == defaultSvg =</span>
<span class="lineno"> 101 </span><span class="spaces"> </span><span class="nottickedoff">concatMap dropNulls $</span>
<span class="lineno"> 102 </span><span class="spaces"> </span><span class="nottickedoff">concatMap (worker attr) (g^.groupChildren)</span>
<span class="lineno"> 103 </span><span class="spaces"> </span><span class="nottickedoff">| otherwise =</span>
<span class="lineno"> 104 </span><span class="spaces"> </span><span class="nottickedoff">concatMap (worker (attr &lt;&gt; g ^. drawAttributes)) (g^.groupChildren)</span>
<span class="lineno"> 105 </span><span class="spaces"> </span><span class="nottickedoff">worker attr t = dropNulls (t &amp; drawAttributes .~ attr)</span>
<span class="lineno"> 106 </span><span class="spaces"></span><span class="nottickedoff"></span>
<span class="lineno"> 107 </span><span class="spaces"> </span><span class="nottickedoff">dropNulls None = []</span>
<span class="lineno"> 108 </span><span class="spaces"> </span><span class="nottickedoff">dropNulls (DefinitionTree d)</span>
<span class="lineno"> 109 </span><span class="spaces"> </span><span class="nottickedoff">| null (d^.groupChildren) = []</span>
<span class="lineno"> 110 </span><span class="spaces"> </span><span class="nottickedoff">dropNulls (GroupTree g)</span>
<span class="lineno"> 111 </span><span class="spaces"> </span><span class="nottickedoff">| null (g^.groupChildren) = []</span>
<span class="lineno"> 112 </span><span class="spaces"> </span><span class="nottickedoff">dropNulls t = [t]</span></span>
<span class="lineno"> 113 </span>
<span class="lineno"> 114 </span>extractPath :: Tree -&gt; [PathCommand]
<span class="lineno"> 115 </span><span class="decl"><span class="nottickedoff">extractPath = worker . simplify . lowerTransformations . pathify</span>
<span class="lineno"> 116 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 117 </span><span class="spaces"> </span><span class="nottickedoff">worker (GroupTree g) = concatMap worker (g^.groupChildren)</span>
<span class="lineno"> 118 </span><span class="spaces"> </span><span class="nottickedoff">worker (PathTree p) = p^.pathDefinition</span>
<span class="lineno"> 119 </span><span class="spaces"> </span><span class="nottickedoff">worker _ = []</span></span>
<span class="lineno"> 120 </span>
<span class="lineno"> 121 </span>withSubglyphs :: [Int] -&gt; (Tree -&gt; Tree) -&gt; Tree -&gt; Tree
<span class="lineno"> 122 </span><span class="decl"><span class="nottickedoff">withSubglyphs target fn = \t -&gt; evalState (worker t) 0</span>
<span class="lineno"> 123 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 124 </span><span class="spaces"> </span><span class="nottickedoff">worker :: Tree -&gt; State Int Tree</span>
<span class="lineno"> 125 </span><span class="spaces"> </span><span class="nottickedoff">worker t =</span>
<span class="lineno"> 126 </span><span class="spaces"> </span><span class="nottickedoff">case t of</span>
<span class="lineno"> 127 </span><span class="spaces"> </span><span class="nottickedoff">GroupTree g -&gt; do</span>
<span class="lineno"> 128 </span><span class="spaces"> </span><span class="nottickedoff">cs &lt;- mapM worker (g ^. groupChildren)</span>
<span class="lineno"> 129 </span><span class="spaces"> </span><span class="nottickedoff">return $ GroupTree $ g &amp; groupChildren .~ cs</span>
<span class="lineno"> 130 </span><span class="spaces"> </span><span class="nottickedoff">PathTree{} -&gt; handleGlyph t</span>
<span class="lineno"> 131 </span><span class="spaces"> </span><span class="nottickedoff">CircleTree{} -&gt; handleGlyph t</span>
<span class="lineno"> 132 </span><span class="spaces"> </span><span class="nottickedoff">PolyLineTree{} -&gt; handleGlyph t</span>
<span class="lineno"> 133 </span><span class="spaces"> </span><span class="nottickedoff">PolygonTree{} -&gt; handleGlyph t</span>
<span class="lineno"> 134 </span><span class="spaces"> </span><span class="nottickedoff">EllipseTree{} -&gt; handleGlyph t</span>
<span class="lineno"> 135 </span><span class="spaces"> </span><span class="nottickedoff">LineTree{} -&gt; handleGlyph t</span>
<span class="lineno"> 136 </span><span class="spaces"> </span><span class="nottickedoff">RectangleTree{} -&gt; handleGlyph t</span>
<span class="lineno"> 137 </span><span class="spaces"> </span><span class="nottickedoff">_ -&gt; return t</span>
<span class="lineno"> 138 </span><span class="spaces"> </span><span class="nottickedoff">handleGlyph :: Tree -&gt; State Int Tree</span>
<span class="lineno"> 139 </span><span class="spaces"> </span><span class="nottickedoff">handleGlyph svg = do</span>
<span class="lineno"> 140 </span><span class="spaces"> </span><span class="nottickedoff">n &lt;- get &lt;* modify (+1)</span>
<span class="lineno"> 141 </span><span class="spaces"> </span><span class="nottickedoff">if n `elem` target</span>
<span class="lineno"> 142 </span><span class="spaces"> </span><span class="nottickedoff">then return $ fn svg</span>
<span class="lineno"> 143 </span><span class="spaces"> </span><span class="nottickedoff">else return svg</span></span>
<span class="lineno"> 144 </span>
<span class="lineno"> 145 </span>splitGlyphs :: [Int] -&gt; Tree -&gt; (Tree, Tree)
<span class="lineno"> 146 </span><span class="decl"><span class="nottickedoff">splitGlyphs target = \t -&gt;</span>
<span class="lineno"> 147 </span><span class="spaces"> </span><span class="nottickedoff">let (_, l, r) = execState (worker id t) (0, [], [])</span>
<span class="lineno"> 148 </span><span class="spaces"> </span><span class="nottickedoff">in (mkGroup l, mkGroup r)</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">handleGlyph :: Tree -&gt; State (Int, [Tree], [Tree]) ()</span>
<span class="lineno"> 151 </span><span class="spaces"> </span><span class="nottickedoff">handleGlyph t = do</span>
<span class="lineno"> 152 </span><span class="spaces"> </span><span class="nottickedoff">(n, l, r) &lt;- get</span>
<span class="lineno"> 153 </span><span class="spaces"> </span><span class="nottickedoff">if n `elem` target</span>
<span class="lineno"> 154 </span><span class="spaces"> </span><span class="nottickedoff">then put (n+1, l, t:r)</span>
<span class="lineno"> 155 </span><span class="spaces"> </span><span class="nottickedoff">else put (n+1, t:l, r)</span>
<span class="lineno"> 156 </span><span class="spaces"> </span><span class="nottickedoff">worker :: (Tree -&gt; Tree) -&gt; Tree -&gt; State (Int, [Tree], [Tree]) ()</span>
<span class="lineno"> 157 </span><span class="spaces"> </span><span class="nottickedoff">worker acc t =</span>
<span class="lineno"> 158 </span><span class="spaces"> </span><span class="nottickedoff">case t of</span>
<span class="lineno"> 159 </span><span class="spaces"> </span><span class="nottickedoff">GroupTree g -&gt; do</span>
<span class="lineno"> 160 </span><span class="spaces"> </span><span class="nottickedoff">let acc' sub = acc (GroupTree $ g &amp; groupChildren .~ [sub])</span>
<span class="lineno"> 161 </span><span class="spaces"> </span><span class="nottickedoff">mapM_ (worker acc') (g ^. groupChildren)</span>
<span class="lineno"> 162 </span><span class="spaces"> </span><span class="nottickedoff">PathTree{} -&gt; handleGlyph $ acc t</span>
<span class="lineno"> 163 </span><span class="spaces"> </span><span class="nottickedoff">CircleTree{} -&gt; handleGlyph $ acc t</span>
<span class="lineno"> 164 </span><span class="spaces"> </span><span class="nottickedoff">PolyLineTree{} -&gt; handleGlyph $ acc t</span>
<span class="lineno"> 165 </span><span class="spaces"> </span><span class="nottickedoff">PolygonTree{} -&gt; handleGlyph $ acc t</span>
<span class="lineno"> 166 </span><span class="spaces"> </span><span class="nottickedoff">EllipseTree{} -&gt; handleGlyph $ acc t</span>
<span class="lineno"> 167 </span><span class="spaces"> </span><span class="nottickedoff">LineTree{} -&gt; handleGlyph $ acc t</span>
<span class="lineno"> 168 </span><span class="spaces"> </span><span class="nottickedoff">RectangleTree{} -&gt; handleGlyph $ acc t</span>
<span class="lineno"> 169 </span><span class="spaces"> </span><span class="nottickedoff">DefinitionTree{} -&gt; return ()</span>
<span class="lineno"> 170 </span><span class="spaces"> </span><span class="nottickedoff">_ -&gt;</span>
<span class="lineno"> 171 </span><span class="spaces"> </span><span class="nottickedoff">modify $ \(n, l, r) -&gt; (n, acc t:l, r)</span></span>
<span class="lineno"> 172 </span>{-
<span class="lineno"> 173 </span>&lt;g transform=&quot;translate(10,10)&quot;&gt;
<span class="lineno"> 174 </span> &lt;g transform=&quot;scale(2)&quot;&gt;
<span class="lineno"> 175 </span> &lt;circle/&gt;
<span class="lineno"> 176 </span> &lt;/g&gt;
<span class="lineno"> 177 </span> &lt;g transform=&quot;scale(0.5)&quot;&gt;
<span class="lineno"> 178 </span> &lt;rect/&gt;
<span class="lineno"> 179 </span> &lt;/g&gt;
<span class="lineno"> 180 </span>&lt;/g&gt;
<span class="lineno"> 181 </span>
<span class="lineno"> 182 </span>[ (\svg -&gt; &lt;g transform=&quot;translate(10,10)&quot;&gt;&lt;g transform=&quot;scale(2)&quot;&gt;svg&lt;/g&gt;&lt;/g&gt;, &lt;circle/&gt;)
<span class="lineno"> 183 </span>, (\svg -&gt; &lt;g transform=&quot;translate(10,10)&quot;&gt;&lt;g transform=&quot;scale(0.5)&quot;&gt;svg&lt;/g&gt;&lt;/g&gt;, &lt;rect/&gt;)]
<span class="lineno"> 184 </span>-}
<span class="lineno"> 185 </span>svgGlyphs :: Tree -&gt; [(Tree -&gt; Tree, DrawAttributes, Tree)]
<span class="lineno"> 186 </span><span class="decl"><span class="nottickedoff">svgGlyphs = worker id defaultSvg</span>
<span class="lineno"> 187 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 188 </span><span class="spaces"> </span><span class="nottickedoff">worker acc attr =</span>
<span class="lineno"> 189 </span><span class="spaces"> </span><span class="nottickedoff">\case</span>
<span class="lineno"> 190 </span><span class="spaces"> </span><span class="nottickedoff">None -&gt; []</span>
<span class="lineno"> 191 </span><span class="spaces"> </span><span class="nottickedoff">GroupTree g -&gt;</span>
<span class="lineno"> 192 </span><span class="spaces"> </span><span class="nottickedoff">let acc' sub = acc (GroupTree $ g &amp; groupChildren .~ [sub])</span>
<span class="lineno"> 193 </span><span class="spaces"> </span><span class="nottickedoff">attr' = (g^.drawAttributes) `mappend` attr</span>
<span class="lineno"> 194 </span><span class="spaces"> </span><span class="nottickedoff">in concatMap (worker acc' attr') (g ^. groupChildren)</span>
<span class="lineno"> 195 </span><span class="spaces"> </span><span class="nottickedoff">t -&gt; [(acc, (t^.drawAttributes) `mappend` attr, t)]</span></span>
<span class="lineno"> 196 </span>
<span class="lineno"> 197 </span>{-| Convert primitive SVG shapes (like those created by 'mkCircle', 'mkRect', 'mkLine' or
<span class="lineno"> 198 </span> 'mkEllipse') into SVG path. This can be useful for creating animations of these shapes being
<span class="lineno"> 199 </span> drawn progressively with 'partialSvg'.
<span class="lineno"> 200 </span>
<span class="lineno"> 201 </span> Example:
<span class="lineno"> 202 </span>
<span class="lineno"> 203 </span> &gt; pathifyExample :: Animation
<span class="lineno"> 204 </span> &gt; pathifyExample = animate $ \t -&gt; gridLayout
<span class="lineno"> 205 </span> &gt; [ [ partialSvg t $ pathify $ mkCircle 1
<span class="lineno"> 206 </span> &gt; , partialSvg t $ pathify $ mkRect 2 2
<span class="lineno"> 207 </span> &gt; ]
<span class="lineno"> 208 </span> &gt; , [ partialSvg t $ pathify $ mkEllipse 1 0.5
<span class="lineno"> 209 </span> &gt; , partialSvg t $ pathify $ mkLine (-1, -1) (1, 1)
<span class="lineno"> 210 </span> &gt; ]
<span class="lineno"> 211 </span> &gt; ]
<span class="lineno"> 212 </span>
<span class="lineno"> 213 </span> &lt;&lt;docs/gifs/doc_pathify.gif&gt;&gt;
<span class="lineno"> 214 </span> -}
<span class="lineno"> 215 </span>pathify :: Tree -&gt; Tree
<span class="lineno"> 216 </span><span class="decl"><span class="istickedoff">pathify = mapTree worker</span>
<span class="lineno"> 217 </span><span class="spaces"> </span><span class="istickedoff">where</span>
<span class="lineno"> 218 </span><span class="spaces"> </span><span class="istickedoff">worker =</span>
<span class="lineno"> 219 </span><span class="spaces"> </span><span class="istickedoff">\case</span>
<span class="lineno"> 220 </span><span class="spaces"> </span><span class="istickedoff">RectangleTree rect | Just (x,y,w,h) &lt;- unpackRect rect -&gt;</span>
<span class="lineno"> 221 </span><span class="spaces"> </span><span class="istickedoff">PathTree $ defaultSvg</span>
<span class="lineno"> 222 </span><span class="spaces"> </span><span class="istickedoff">&amp; drawAttributes .~ rect ^. drawAttributes</span>
<span class="lineno"> 223 </span><span class="spaces"> </span><span class="istickedoff">&amp; strokeLineCap .~ pure CapSquare</span>
<span class="lineno"> 224 </span><span class="spaces"> </span><span class="istickedoff">&amp; pathDefinition .~</span>
<span class="lineno"> 225 </span><span class="spaces"> </span><span class="istickedoff">[MoveTo OriginAbsolute [V2 x y]</span>
<span class="lineno"> 226 </span><span class="spaces"> </span><span class="istickedoff">,HorizontalTo OriginRelative [w]</span>
<span class="lineno"> 227 </span><span class="spaces"> </span><span class="istickedoff">,VerticalTo OriginRelative [h]</span>
<span class="lineno"> 228 </span><span class="spaces"> </span><span class="istickedoff">,HorizontalTo OriginRelative [-w]</span>
<span class="lineno"> 229 </span><span class="spaces"> </span><span class="istickedoff">,EndPath ]</span>
<span class="lineno"> 230 </span><span class="spaces"> </span><span class="istickedoff">LineTree line | Just (x1,y1, x2, y2) &lt;- <span class="nottickedoff">unpackLine line</span> -&gt;</span>
<span class="lineno"> 231 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">PathTree $ defaultSvg</span></span>
<span class="lineno"> 232 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">&amp; drawAttributes .~ line ^. drawAttributes</span></span>
<span class="lineno"> 233 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">&amp; pathDefinition .~</span></span>
<span class="lineno"> 234 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">[MoveTo OriginAbsolute [V2 x1 y1]</span></span>
<span class="lineno"> 235 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">,LineTo OriginAbsolute [V2 x2 y2] ]</span></span>
<span class="lineno"> 236 </span><span class="spaces"> </span><span class="istickedoff">CircleTree circ | Just (x, y, r) &lt;- unpackCircle circ -&gt;</span>
<span class="lineno"> 237 </span><span class="spaces"> </span><span class="istickedoff">PathTree $ defaultSvg</span>
<span class="lineno"> 238 </span><span class="spaces"> </span><span class="istickedoff">&amp; drawAttributes .~ circ ^. drawAttributes</span>
<span class="lineno"> 239 </span><span class="spaces"> </span><span class="istickedoff">&amp; pathDefinition .~</span>
<span class="lineno"> 240 </span><span class="spaces"> </span><span class="istickedoff">[MoveTo OriginAbsolute [V2 (x-r) y]</span>
<span class="lineno"> 241 </span><span class="spaces"> </span><span class="istickedoff">,EllipticalArc OriginRelative [(r, r, 0,True,False,V2 (r*2) 0)</span>
<span class="lineno"> 242 </span><span class="spaces"> </span><span class="istickedoff">,(r, r, 0,True,False,V2 (-r*2) 0)]]</span>
<span class="lineno"> 243 </span><span class="spaces"> </span><span class="istickedoff">PolyLineTree pl -&gt;</span>
<span class="lineno"> 244 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">let points = pl ^. polyLinePoints</span></span>
<span class="lineno"> 245 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">in PathTree $ defaultSvg</span></span>
<span class="lineno"> 246 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">&amp; drawAttributes .~ pl ^. drawAttributes</span></span>
<span class="lineno"> 247 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">&amp; pathDefinition .~ pointsToPathCommands points</span></span>
<span class="lineno"> 248 </span><span class="spaces"> </span><span class="istickedoff">PolygonTree pg -&gt;</span>
<span class="lineno"> 249 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">let points = pg ^. polygonPoints</span></span>
<span class="lineno"> 250 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">in PathTree $ defaultSvg</span></span>
<span class="lineno"> 251 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">&amp; drawAttributes .~ pg ^. drawAttributes</span></span>
<span class="lineno"> 252 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">-- Polygon automatically connects the last point to the first. For path we must do</span></span>
<span class="lineno"> 253 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">-- it explicitly</span></span>
<span class="lineno"> 254 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">&amp; pathDefinition .~ (pointsToPathCommands points ++ [EndPath])</span></span>
<span class="lineno"> 255 </span><span class="spaces"> </span><span class="istickedoff">EllipseTree elip | Just (cx,cy,rx,ry) &lt;- <span class="nottickedoff">unpackEllipse elip</span> -&gt;</span>
<span class="lineno"> 256 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">PathTree $ defaultSvg</span></span>
<span class="lineno"> 257 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">&amp; drawAttributes .~ elip ^. drawAttributes</span></span>
<span class="lineno"> 258 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">&amp; pathDefinition .~</span></span>
<span class="lineno"> 259 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">[ MoveTo OriginAbsolute [V2 (cx-rx) cy]</span></span>
<span class="lineno"> 260 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">, EllipticalArc OriginRelative [(rx, ry, 0,True,False,V2 (rx*2) 0)</span></span>
<span class="lineno"> 261 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">,(rx, ry, 0,True,False,V2 (-rx*2) 0)]]</span></span>
<span class="lineno"> 262 </span><span class="spaces"> </span><span class="istickedoff">t -&gt; t</span>
<span class="lineno"> 263 </span><span class="spaces"> </span><span class="istickedoff">unpackCircle circ = do</span>
<span class="lineno"> 264 </span><span class="spaces"> </span><span class="istickedoff">let (x,y) = circ ^. circleCenter</span>
<span class="lineno"> 265 </span><span class="spaces"> </span><span class="istickedoff">liftM3 (,,) (unpackNumber x) (unpackNumber y) (unpackNumber $ circ ^. circleRadius)</span>
<span class="lineno"> 266 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">unpackEllipse elip = do</span></span>
<span class="lineno"> 267 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">let (x,y) = elip ^. ellipseCenter</span></span>
<span class="lineno"> 268 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">liftM4 (,,,) (unpackNumber x) (unpackNumber y) (unpackNumber $ elip ^. ellipseXRadius)</span></span>
<span class="lineno"> 269 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">(unpackNumber $ elip ^. ellipseYRadius)</span></span>
<span class="lineno"> 270 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">unpackLine line = do</span></span>
<span class="lineno"> 271 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">let (x1,y1) = line ^. linePoint1</span></span>
<span class="lineno"> 272 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">(x2,y2) = line ^. linePoint2</span></span>
<span class="lineno"> 273 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">liftM4 (,,,) (unpackNumber x1) (unpackNumber y1) (unpackNumber x2) (unpackNumber y2)</span></span>
<span class="lineno"> 274 </span><span class="spaces"> </span><span class="istickedoff">unpackRect rect = do</span>
<span class="lineno"> 275 </span><span class="spaces"> </span><span class="istickedoff">let (x', y') = rect ^. rectUpperLeftCorner</span>
<span class="lineno"> 276 </span><span class="spaces"> </span><span class="istickedoff">x &lt;- unpackNumber x'</span>
<span class="lineno"> 277 </span><span class="spaces"> </span><span class="istickedoff">y &lt;- unpackNumber y'</span>
<span class="lineno"> 278 </span><span class="spaces"> </span><span class="istickedoff">w &lt;- unpackNumber =&lt;&lt; rect ^. rectWidth</span>
<span class="lineno"> 279 </span><span class="spaces"> </span><span class="istickedoff">h &lt;- unpackNumber =&lt;&lt; rect ^. rectHeight</span>
<span class="lineno"> 280 </span><span class="spaces"> </span><span class="istickedoff">return (x,y,w,h)</span>
<span class="lineno"> 281 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">pointsToPathCommands points = case points of</span></span>
<span class="lineno"> 282 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">[] -&gt; []</span></span>
<span class="lineno"> 283 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">(p:ps) -&gt; [ MoveTo OriginAbsolute [p]</span></span>
<span class="lineno"> 284 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">, LineTo OriginAbsolute ps ]</span></span>
<span class="lineno"> 285 </span><span class="spaces"> </span><span class="istickedoff">unpackNumber n =</span>
<span class="lineno"> 286 </span><span class="spaces"> </span><span class="istickedoff">case toUserUnit <span class="nottickedoff">defaultDPI</span> n of</span>
<span class="lineno"> 287 </span><span class="spaces"> </span><span class="istickedoff">Num d -&gt; Just d</span>
<span class="lineno"> 288 </span><span class="spaces"> </span><span class="istickedoff">_ -&gt; <span class="nottickedoff">Nothing</span></span></span>
<span class="lineno"> 289 </span>
<span class="lineno"> 290 </span>mapSvgPaths :: ([PathCommand] -&gt; [PathCommand]) -&gt; SVG -&gt; SVG
<span class="lineno"> 291 </span><span class="decl"><span class="nottickedoff">mapSvgPaths fn = mapTree worker</span>
<span class="lineno"> 292 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 293 </span><span class="spaces"> </span><span class="nottickedoff">worker =</span>
<span class="lineno"> 294 </span><span class="spaces"> </span><span class="nottickedoff">\case</span>
<span class="lineno"> 295 </span><span class="spaces"> </span><span class="nottickedoff">PathTree path -&gt; PathTree $</span>
<span class="lineno"> 296 </span><span class="spaces"> </span><span class="nottickedoff">path &amp; pathDefinition %~ fn</span>
<span class="lineno"> 297 </span><span class="spaces"> </span><span class="nottickedoff">t -&gt; t</span></span>
<span class="lineno"> 298 </span>
<span class="lineno"> 299 </span>mapSvgLines :: ([LineCommand] -&gt; [LineCommand]) -&gt; SVG -&gt; SVG
<span class="lineno"> 300 </span><span class="decl"><span class="nottickedoff">mapSvgLines fn = mapSvgPaths (lineToPath . fn . toLineCommands)</span></span>
<span class="lineno"> 301 </span>
<span class="lineno"> 302 </span>-- Only maps points in paths
<span class="lineno"> 303 </span>mapSvgPoints :: (RPoint -&gt; RPoint) -&gt; SVG -&gt; SVG
<span class="lineno"> 304 </span><span class="decl"><span class="nottickedoff">mapSvgPoints fn = mapSvgLines (map worker)</span>
<span class="lineno"> 305 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 306 </span><span class="spaces"> </span><span class="nottickedoff">worker (LineMove p) = LineMove (fn p)</span>
<span class="lineno"> 307 </span><span class="spaces"> </span><span class="nottickedoff">worker (LineBezier ps) = LineBezier (map fn ps)</span>
<span class="lineno"> 308 </span><span class="spaces"> </span><span class="nottickedoff">worker (LineEnd p) = LineEnd (fn p)</span></span>
<span class="lineno"> 309 </span>
<span class="lineno"> 310 </span>svgPointsToRadians :: SVG -&gt; SVG
<span class="lineno"> 311 </span><span class="decl"><span class="nottickedoff">svgPointsToRadians = mapSvgPoints worker</span>
<span class="lineno"> 312 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 313 </span><span class="spaces"> </span><span class="nottickedoff">worker (V2 x y) = V2 (x/180*pi) (y/180*pi)</span></span>
</pre>
</body>
</html>

View file

@ -0,0 +1,84 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<style type="text/css">
span.lineno { color: white; background: #aaaaaa; border-right: solid white 12px }
span.nottickedoff { background: yellow}
span.istickedoff { background: white }
span.tickonlyfalse { margin: -1px; border: 1px solid #f20913; background: #f20913 }
span.tickonlytrue { margin: -1px; border: 1px solid #60de51; background: #60de51 }
span.funcount { font-size: small; color: orange; z-index: 2; position: absolute; right: 20 }
span.decl { font-weight: bold }
span.spaces { background: white }
</style>
</head>
<body>
<pre>
<span class="decl"><span class="nottickedoff">never executed</span> <span class="tickonlytrue">always true</span> <span class="tickonlyfalse">always false</span></span>
</pre>
<pre>
<span class="lineno"> 1 </span>{-# LANGUAGE BangPatterns #-}
<span class="lineno"> 2 </span>{-# LANGUAGE PackageImports #-}
<span class="lineno"> 3 </span>module Reanimate.Transform
<span class="lineno"> 4 </span> ( identity
<span class="lineno"> 5 </span> , transformPoint
<span class="lineno"> 6 </span> , mkMatrix
<span class="lineno"> 7 </span> , toTransformation
<span class="lineno"> 8 </span> ) where
<span class="lineno"> 9 </span>
<span class="lineno"> 10 </span>-- XXX: Use Linear.Matrix instead of Data.Matrix to drop the 'matrix' dependency.
<span class="lineno"> 11 </span>import Data.List
<span class="lineno"> 12 </span>import &quot;matrix&quot; Data.Matrix (Matrix)
<span class="lineno"> 13 </span>import qualified &quot;matrix&quot; Data.Matrix as M
<span class="lineno"> 14 </span>import Data.Maybe
<span class="lineno"> 15 </span>import Graphics.SvgTree
<span class="lineno"> 16 </span>import Linear.V2
<span class="lineno"> 17 </span>
<span class="lineno"> 18 </span>type TMatrix = Matrix Coord
<span class="lineno"> 19 </span>
<span class="lineno"> 20 </span>identity :: TMatrix
<span class="lineno"> 21 </span><span class="decl"><span class="nottickedoff">identity = M.identity 3</span></span>
<span class="lineno"> 22 </span>
<span class="lineno"> 23 </span>fromList :: [Coord] -&gt; TMatrix
<span class="lineno"> 24 </span><span class="decl"><span class="nottickedoff">fromList [a,b,c,d,e,f] = M.fromList 3 3 [a,c,e,b,d,f,0,0,1]</span>
<span class="lineno"> 25 </span><span class="spaces"></span><span class="nottickedoff">fromList _ = error &quot;Reanimate.Transform.fromList: bad input&quot;</span></span>
<span class="lineno"> 26 </span>
<span class="lineno"> 27 </span>transformPoint :: TMatrix -&gt; RPoint -&gt; RPoint
<span class="lineno"> 28 </span><span class="decl"><span class="nottickedoff">transformPoint m (V2 x y) = V2 (a*x +c*y + e) (b*x + d*y +f)</span>
<span class="lineno"> 29 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 30 </span><span class="spaces"> </span><span class="nottickedoff">!a = M.unsafeGet 1 1 m</span>
<span class="lineno"> 31 </span><span class="spaces"> </span><span class="nottickedoff">!c = M.unsafeGet 1 2 m</span>
<span class="lineno"> 32 </span><span class="spaces"> </span><span class="nottickedoff">!e = M.unsafeGet 1 3 m</span>
<span class="lineno"> 33 </span><span class="spaces"> </span><span class="nottickedoff">!b = M.unsafeGet 2 1 m</span>
<span class="lineno"> 34 </span><span class="spaces"> </span><span class="nottickedoff">!d = M.unsafeGet 2 2 m</span>
<span class="lineno"> 35 </span><span class="spaces"> </span><span class="nottickedoff">!f = M.unsafeGet 2 3 m</span></span>
<span class="lineno"> 36 </span> -- (a:c:e:b:d:f:_) = M.toList m
<span class="lineno"> 37 </span>
<span class="lineno"> 38 </span>mkMatrix :: Maybe [Transformation] -&gt; TMatrix
<span class="lineno"> 39 </span><span class="decl"><span class="nottickedoff">mkMatrix Nothing = identity</span>
<span class="lineno"> 40 </span><span class="spaces"></span><span class="nottickedoff">mkMatrix (Just ts) = foldl' (*) identity (map transformationMatrix ts)</span></span>
<span class="lineno"> 41 </span>
<span class="lineno"> 42 </span>transformationMatrix :: Transformation -&gt; TMatrix
<span class="lineno"> 43 </span><span class="decl"><span class="nottickedoff">transformationMatrix transformation =</span>
<span class="lineno"> 44 </span><span class="spaces"> </span><span class="nottickedoff">case transformation of</span>
<span class="lineno"> 45 </span><span class="spaces"> </span><span class="nottickedoff">TransformMatrix a b c d e f -&gt; fromList [a,b,c,d,e,f]</span>
<span class="lineno"> 46 </span><span class="spaces"> </span><span class="nottickedoff">Translate x y -&gt; translate x y</span>
<span class="lineno"> 47 </span><span class="spaces"> </span><span class="nottickedoff">Scale sx mbSy -&gt; fromList [sx,0,0,fromMaybe sx mbSy,0,0]</span>
<span class="lineno"> 48 </span><span class="spaces"> </span><span class="nottickedoff">Rotate a Nothing -&gt; rotate a</span>
<span class="lineno"> 49 </span><span class="spaces"> </span><span class="nottickedoff">Rotate a (Just (x,y)) -&gt; translate x y * rotate a * translate (-x) (-y)</span>
<span class="lineno"> 50 </span><span class="spaces"> </span><span class="nottickedoff">SkewX a -&gt; fromList [1,0,tan (a*pi/180),1,0,0]</span>
<span class="lineno"> 51 </span><span class="spaces"> </span><span class="nottickedoff">SkewY a -&gt; fromList [1,tan (a*pi/180),0,1,0,0]</span>
<span class="lineno"> 52 </span><span class="spaces"> </span><span class="nottickedoff">TransformUnknown -&gt; identity</span>
<span class="lineno"> 53 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 54 </span><span class="spaces"> </span><span class="nottickedoff">translate x y = fromList [1,0,0,1,x,y]</span>
<span class="lineno"> 55 </span><span class="spaces"> </span><span class="nottickedoff">rotate a = fromList [cos r,sin r,-sin r,cos r,0,0]</span>
<span class="lineno"> 56 </span><span class="spaces"> </span><span class="nottickedoff">where r = a * pi / 180</span></span>
<span class="lineno"> 57 </span>
<span class="lineno"> 58 </span>toTransformation :: TMatrix -&gt; Transformation
<span class="lineno"> 59 </span><span class="decl"><span class="nottickedoff">toTransformation m = TransformMatrix a b c d e f</span>
<span class="lineno"> 60 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 61 </span><span class="spaces"> </span><span class="nottickedoff">[a,c,e,b,d,f,_,_,_] = M.toList m</span></span>
</pre>
</body>
</html>