Deploying to gh-pages from @ fd9fc786df 🚀

This commit is contained in:
Lemmih 2020-08-25 09:00:01 +00:00
commit bfdde68529
10 changed files with 771 additions and 747 deletions

View file

@ -1,24 +1,24 @@
100% ( 55 / 55) in 'Reanimate.Svg.Constructors' 100% ( 55 / 55) in 'Reanimate.Svg.Constructors'
100% ( 41 / 41) in 'Reanimate.Animation'
100% ( 40 / 40) in 'Reanimate.GeoProjection' 100% ( 40 / 40) in 'Reanimate.GeoProjection'
100% ( 22 / 22) in 'Reanimate.Effect' 100% ( 22 / 22) in 'Reanimate.Effect'
100% ( 17 / 17) in 'Reanimate.Parameters' 100% ( 17 / 17) in 'Reanimate.Parameters'
100% ( 14 / 14) in 'Reanimate.Raster'
100% ( 13 / 13) in 'Reanimate.ColorMap' 100% ( 13 / 13) in 'Reanimate.ColorMap'
100% ( 12 / 12) in 'Reanimate.ColorComponents' 100% ( 12 / 12) in 'Reanimate.ColorComponents'
100% ( 9 / 9) in 'Reanimate.Voice' 100% ( 9 / 9) in 'Reanimate.Voice'
100% ( 9 / 9) in 'Reanimate.Povray' 100% ( 9 / 9) in 'Reanimate.Povray'
100% ( 9 / 9) in 'Reanimate.Constants' 100% ( 9 / 9) in 'Reanimate.Constants'
100% ( 8 / 8) in 'Reanimate.Builtin.TernaryPlot' 100% ( 8 / 8) in 'Reanimate.Builtin.TernaryPlot'
100% ( 7 / 7) in 'Reanimate.Builtin.Documentation'
100% ( 6 / 6) in 'Reanimate.Builtin.Images' 100% ( 6 / 6) in 'Reanimate.Builtin.Images'
100% ( 5 / 5) in 'Reanimate.Transform' 100% ( 5 / 5) in 'Reanimate.Transform'
100% ( 4 / 4) in 'Reanimate.Svg.BoundingBox' 100% ( 4 / 4) in 'Reanimate.Svg.BoundingBox'
100% ( 3 / 3) in 'Reanimate.Blender' 100% ( 3 / 3) in 'Reanimate.Blender'
99% (155 /156) in 'Reanimate' 99% (155 /156) in 'Reanimate'
95% ( 40 / 42) in 'Reanimate.Animation'
93% ( 13 / 14) in 'Reanimate.Raster'
91% ( 10 / 11) in 'Reanimate.Ease' 91% ( 10 / 11) in 'Reanimate.Ease'
88% ( 7 / 8) in 'Reanimate.Transition' 88% ( 7 / 8) in 'Reanimate.Transition'
81% ( 92 /114) in 'Reanimate.Scene' 81% ( 92 /114) in 'Reanimate.Scene'
75% ( 6 / 8) in 'Reanimate.Builtin.Documentation'
75% ( 3 / 4) in 'Reanimate.Svg.Unuse' 75% ( 3 / 4) in 'Reanimate.Svg.Unuse'
62% ( 23 / 37) in 'Reanimate.Internal.CubicBezier' 62% ( 23 / 37) in 'Reanimate.Internal.CubicBezier'
56% ( 10 / 18) in 'Reanimate.Svg' 56% ( 10 / 18) in 'Reanimate.Svg'
@ -34,7 +34,6 @@
0% ( 0 / 13) in 'Reanimate.Morph.Common' 0% ( 0 / 13) in 'Reanimate.Morph.Common'
0% ( 0 / 10) in 'Reanimate.ColorSpace' 0% ( 0 / 10) in 'Reanimate.ColorSpace'
0% ( 0 / 8) in 'Reanimate.Misc' 0% ( 0 / 8) in 'Reanimate.Misc'
0% ( 0 / 8) in 'Reanimate.Math.Balloon'
0% ( 0 / 7) in 'Reanimate.Morph.Linear' 0% ( 0 / 7) in 'Reanimate.Morph.Linear'
0% ( 0 / 7) in 'Reanimate.Math.Visibility' 0% ( 0 / 7) in 'Reanimate.Math.Visibility'
0% ( 0 / 6) in 'Reanimate.Math.Triangulate' 0% ( 0 / 6) in 'Reanimate.Math.Triangulate'
@ -43,4 +42,5 @@
0% ( 0 / 4) in 'Reanimate.Debug' 0% ( 0 / 4) in 'Reanimate.Debug'
0% ( 0 / 3) in 'Reanimate.Morph.Rotational' 0% ( 0 / 3) in 'Reanimate.Morph.Rotational'
0% ( 0 / 3) in 'Reanimate.Memo' 0% ( 0 / 3) in 'Reanimate.Memo'
0% ( 0 / 3) in 'Reanimate.Math.Balloon'
0% ( 0 / 2) in 'Reanimate.Morph.Cache' 0% ( 0 / 2) in 'Reanimate.Morph.Cache'

View file

@ -1 +1 @@
{ "schemaVersion": 1, "label": "api docs", "message": "68%", "color": "success" } { "schemaVersion": 1, "label": "api docs", "message": "70%", "color": "success" }

View file

@ -11,10 +11,10 @@ table.dashboard { border-collapse: collapse ; border: solid 1px black }
<td align="right">20%</td><td>3/15</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="20%"><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">20%</td><td>12/58</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="20%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr> <td align="right">20%</td><td>3/15</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="20%"><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">20%</td><td>12/58</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="20%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
<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>&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">87%</td><td>28/32</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="87%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">57%</td><td>8/14</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="57%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">85%</td><td>298/347</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="85%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr> <td align="right">90%</td><td>28/31</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="90%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">57%</td><td>8/14</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="57%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">87%</td><td>298/341</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="87%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
<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>&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">85%</td><td>6/7</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="85%"><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">87%</td><td>117/134</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="87%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr> <td align="right">100%</td><td>6/6</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">-&nbsp;</td><td>0/0</td><td width=100>&nbsp;</td><td align="right">100%</td><td>117/117</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
<tr> <tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.1.0-inplace/Reanimate.Builtin.Images.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Builtin.Images</a></tt></td> <td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.1.0-inplace/Reanimate.Builtin.Images.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Builtin.Images</a></tt></td>
<td align="right">57%</td><td>4/7</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="57%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">25%</td><td>1/4</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="25%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">48%</td><td>24/49</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="48%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr> <td align="right">57%</td><td>4/7</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="57%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">25%</td><td>1/4</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="25%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">48%</td><td>24/49</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="48%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
@ -128,5 +128,5 @@ table.dashboard { border-collapse: collapse ; border: solid 1px black }
<td align="right">100%</td><td>6/6</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">50%</td><td>1/2</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="50%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">95%</td><td>43/45</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="95%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr> <td align="right">100%</td><td>6/6</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">50%</td><td>1/2</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="50%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">95%</td><td>43/45</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="95%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
<tr></tr><tr style="background: #e0e0e0"> <tr></tr><tr style="background: #e0e0e0">
<th align=left>&nbsp;&nbsp;Program Coverage Total</tt></th> <th align=left>&nbsp;&nbsp;Program Coverage Total</tt></th>
<td align="right">30%</td><td>247/805</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="30%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">15%</td><td>131/833</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="15%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">29%</td><td>4647/15897</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="29%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr> <td align="right">30%</td><td>247/803</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="30%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">15%</td><td>131/833</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="15%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">29%</td><td>4647/15874</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="29%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
</table></body></html> </table></body></html>

View file

@ -20,7 +20,7 @@ table.dashboard { border-collapse: collapse ; border: solid 1px black }
<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">58%</td><td>43/74</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="58%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">69%</td><td>659/943</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="69%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr> <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">58%</td><td>43/74</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="58%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">69%</td><td>659/943</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="69%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
<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>&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">87%</td><td>28/32</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="87%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">57%</td><td>8/14</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="57%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">85%</td><td>298/347</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="85%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr> <td align="right">90%</td><td>28/31</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="90%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">57%</td><td>8/14</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="57%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">87%</td><td>298/341</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="87%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
<tr> <tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.1.0-inplace/Reanimate.ColorComponents.hs.html">reanimate-0.4.1.0-inplace/Reanimate.ColorComponents</a></tt></td> <td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.1.0-inplace/Reanimate.ColorComponents.hs.html">reanimate-0.4.1.0-inplace/Reanimate.ColorComponents</a></tt></td>
<td align="right">75%</td><td>9/12</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">50%</td><td>1/2</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="50%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">81%</td><td>135/166</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="81%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr> <td align="right">75%</td><td>9/12</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">50%</td><td>1/2</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="50%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">81%</td><td>135/166</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="81%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
@ -110,7 +110,7 @@ table.dashboard { border-collapse: collapse ; border: solid 1px black }
<td align="right">20%</td><td>3/15</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="20%"><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">20%</td><td>12/58</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="20%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr> <td align="right">20%</td><td>3/15</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="20%"><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">20%</td><td>12/58</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="20%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
<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>&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">85%</td><td>6/7</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="85%"><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">87%</td><td>117/134</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="87%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr> <td align="right">100%</td><td>6/6</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">-&nbsp;</td><td>0/0</td><td width=100>&nbsp;</td><td align="right">100%</td><td>117/117</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
<tr> <tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.1.0-inplace/Reanimate.Builtin.Slide.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Builtin.Slide</a></tt></td> <td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.1.0-inplace/Reanimate.Builtin.Slide.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Builtin.Slide</a></tt></td>
<td align="right">33%</td><td>1/3</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="33%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">-&nbsp;</td><td>0/0</td><td width=100>&nbsp;</td><td align="right">30%</td><td>18/60</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="30%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr> <td align="right">33%</td><td>1/3</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="33%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">-&nbsp;</td><td>0/0</td><td width=100>&nbsp;</td><td align="right">30%</td><td>18/60</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="30%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
@ -128,5 +128,5 @@ table.dashboard { border-collapse: collapse ; border: solid 1px black }
<td align="right">15%</td><td>3/20</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="15%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">-&nbsp;</td><td>0/0</td><td width=100>&nbsp;</td><td align="right">14%</td><td>7/49</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></tr> <td align="right">15%</td><td>3/20</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="15%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">-&nbsp;</td><td>0/0</td><td width=100>&nbsp;</td><td align="right">14%</td><td>7/49</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></tr>
<tr></tr><tr style="background: #e0e0e0"> <tr></tr><tr style="background: #e0e0e0">
<th align=left>&nbsp;&nbsp;Program Coverage Total</tt></th> <th align=left>&nbsp;&nbsp;Program Coverage Total</tt></th>
<td align="right">30%</td><td>247/805</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="30%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">15%</td><td>131/833</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="15%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">29%</td><td>4647/15897</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="29%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr> <td align="right">30%</td><td>247/803</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="30%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">15%</td><td>131/833</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="15%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">29%</td><td>4647/15874</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="29%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
</table></body></html> </table></body></html>

View file

@ -7,17 +7,17 @@ table.dashboard { border-collapse: collapse ; border: solid 1px black }
</style> </style>
</head><body><table class="dashboard" width="100%" border=1> </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> <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.Builtin.Documentation.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Builtin.Documentation</a></tt></td>
<td align="right">100%</td><td>6/6</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">-&nbsp;</td><td>0/0</td><td width=100>&nbsp;</td><td align="right">100%</td><td>117/117</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
<tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.1.0-inplace/Reanimate.ColorMap.hs.html">reanimate-0.4.1.0-inplace/Reanimate.ColorMap</a></tt></td> <td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.1.0-inplace/Reanimate.ColorMap.hs.html">reanimate-0.4.1.0-inplace/Reanimate.ColorMap</a></tt></td>
<td align="right">100%</td><td>14/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="bar"></td></tr></table></td></tr></table></td><td align="right">60%</td><td>3/5</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="60%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">99%</td><td>1176/1180</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="99%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr> <td align="right">100%</td><td>14/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="bar"></td></tr></table></td></tr></table></td><td align="right">60%</td><td>3/5</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="60%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">99%</td><td>1176/1180</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="99%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
<tr> <tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.1.0-inplace/Reanimate.Transition.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Transition</a></tt></td> <td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.1.0-inplace/Reanimate.Transition.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Transition</a></tt></td>
<td align="right">100%</td><td>6/6</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">50%</td><td>1/2</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="50%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">95%</td><td>43/45</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="95%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr> <td align="right">100%</td><td>6/6</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">50%</td><td>1/2</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="50%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">95%</td><td>43/45</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="95%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
<tr> <tr>
<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">85%</td><td>6/7</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="85%"><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">87%</td><td>117/134</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="87%"><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>&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">87%</td><td>28/32</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="87%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">57%</td><td>8/14</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="57%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">85%</td><td>298/347</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="85%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr> <td align="right">90%</td><td>28/31</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="90%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">57%</td><td>8/14</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="57%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">87%</td><td>298/341</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="87%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
<tr> <tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.1.0-inplace/Reanimate.ColorComponents.hs.html">reanimate-0.4.1.0-inplace/Reanimate.ColorComponents</a></tt></td> <td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.1.0-inplace/Reanimate.ColorComponents.hs.html">reanimate-0.4.1.0-inplace/Reanimate.ColorComponents</a></tt></td>
<td align="right">75%</td><td>9/12</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">50%</td><td>1/2</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="50%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">81%</td><td>135/166</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="81%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr> <td align="right">75%</td><td>9/12</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">50%</td><td>1/2</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="50%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">81%</td><td>135/166</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="81%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
@ -128,5 +128,5 @@ table.dashboard { border-collapse: collapse ; border: solid 1px black }
<td align="right">0%</td><td>0/1</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td><td align="right">0%</td><td>0/4</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td><td align="right">0%</td><td>0/61</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td></tr> <td align="right">0%</td><td>0/1</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td><td align="right">0%</td><td>0/4</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td><td align="right">0%</td><td>0/61</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td></tr>
<tr></tr><tr style="background: #e0e0e0"> <tr></tr><tr style="background: #e0e0e0">
<th align=left>&nbsp;&nbsp;Program Coverage Total</tt></th> <th align=left>&nbsp;&nbsp;Program Coverage Total</tt></th>
<td align="right">30%</td><td>247/805</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="30%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">15%</td><td>131/833</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="15%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">29%</td><td>4647/15897</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="29%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr> <td align="right">30%</td><td>247/803</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="30%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">15%</td><td>131/833</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="15%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">29%</td><td>4647/15874</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="29%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
</table></body></html> </table></body></html>

View file

@ -7,6 +7,9 @@ table.dashboard { border-collapse: collapse ; border: solid 1px black }
</style> </style>
</head><body><table class="dashboard" width="100%" border=1> </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> <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.Builtin.Documentation.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Builtin.Documentation</a></tt></td>
<td align="right">100%</td><td>6/6</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">-&nbsp;</td><td>0/0</td><td width=100>&nbsp;</td><td align="right">100%</td><td>117/117</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
<tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.1.0-inplace/Reanimate.ColorMap.hs.html">reanimate-0.4.1.0-inplace/Reanimate.ColorMap</a></tt></td> <td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.1.0-inplace/Reanimate.ColorMap.hs.html">reanimate-0.4.1.0-inplace/Reanimate.ColorMap</a></tt></td>
<td align="right">100%</td><td>14/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="bar"></td></tr></table></td></tr></table></td><td align="right">60%</td><td>3/5</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="60%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">99%</td><td>1176/1180</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="99%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr> <td align="right">100%</td><td>14/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="bar"></td></tr></table></td></tr></table></td><td align="right">60%</td><td>3/5</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="60%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">99%</td><td>1176/1180</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="99%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
<tr> <tr>
@ -14,10 +17,7 @@ table.dashboard { border-collapse: collapse ; border: solid 1px black }
<td align="right">100%</td><td>6/6</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">50%</td><td>1/2</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="50%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">95%</td><td>43/45</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="95%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr> <td align="right">100%</td><td>6/6</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">50%</td><td>1/2</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="50%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">95%</td><td>43/45</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="95%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
<tr> <tr>
<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>&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">87%</td><td>28/32</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="87%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">57%</td><td>8/14</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="57%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">85%</td><td>298/347</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="85%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr> <td align="right">90%</td><td>28/31</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="90%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">57%</td><td>8/14</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="57%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">87%</td><td>298/341</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="87%"><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">85%</td><td>6/7</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="85%"><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">87%</td><td>117/134</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="87%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
<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>&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">83%</td><td>5/6</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="83%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">33%</td><td>4/12</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="33%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">45%</td><td>76/166</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="45%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr> <td align="right">83%</td><td>5/6</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="83%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">33%</td><td>4/12</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="33%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">45%</td><td>76/166</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="45%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
@ -128,5 +128,5 @@ table.dashboard { border-collapse: collapse ; border: solid 1px black }
<td align="right">0%</td><td>0/1</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td><td align="right">0%</td><td>0/4</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td><td align="right">0%</td><td>0/61</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td></tr> <td align="right">0%</td><td>0/1</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td><td align="right">0%</td><td>0/4</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td><td align="right">0%</td><td>0/61</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td></tr>
<tr></tr><tr style="background: #e0e0e0"> <tr></tr><tr style="background: #e0e0e0">
<th align=left>&nbsp;&nbsp;Program Coverage Total</tt></th> <th align=left>&nbsp;&nbsp;Program Coverage Total</tt></th>
<td align="right">30%</td><td>247/805</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="30%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">15%</td><td>131/833</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="15%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">29%</td><td>4647/15897</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="29%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr> <td align="right">30%</td><td>247/803</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="30%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">15%</td><td>131/833</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="15%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">29%</td><td>4647/15874</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="29%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
</table></body></html> </table></body></html>

View file

@ -8,4 +8,4 @@ const snippets = [{"title": "Hello World","url": "https://reanimate.clozecards.c
,{"title": "Easing Graphs","url": "https://reanimate.clozecards.com/FEyCDsj0V82/255.svg","code": "colorPalette = parula -- try: viridis, sinebow, turbo, cividis\nfns =\n [(\"curveS\", curveS 2)\n ,(\"bellS\", bellS 2)\n ,(\"constantS\", constantS 0.7)\n ,(\"oscillateS\", oscillateS)\n ,(\"powerS\", powerS 2)\n ,(\"reverseS\", reverseS)\n ,(\"id\", id)\n ]\n\nanimation :: Animation\nanimation = docEnv $ pauseAtEnd 1 $ sceneAnimation $ do\n newSpriteSVG_ $ mkBackground \"white\"\n play $ signalA (curveS 2) $ animate $ \\t -> partialSvg t grid\n newSpriteSVG_ grid\n wait 1\n flip mapM_ (zip [0..] fns) $ \\(nth, (txt, fn)) -> do\n let color = promotePixel $ colorPalette (nth / fromIntegral (length fns-1))\n showEasing nth txt fn color\n {- showEasing 3 \"oscillateS\" oscillateS\n showEasing 4 \"powerS\" (powerS 2)\n showEasing 5 \"reverseS\" reverseS\n showEasing 6 \"id\" id -}\n\ngridOffset = -2\ngridHeight = 5\ngridWidth = 8\n\ngrid :: SVG\ngrid = translate gridOffset 0 $\n withStrokeWidth defaultStrokeWidth $\n withStrokeColor \"grey\" $ mkGroup\n [ mkPath $ concat\n [[ SVG.MoveTo SVG.OriginAbsolute [V2 (-gridWidth/2) (gridHeight/2-n)]\n ,SVG.HorizontalTo SVG.OriginRelative [gridWidth] ]\n | n <- [1..gridHeight-1]\n ]\n , mkPath \n [ SVG.MoveTo SVG.OriginAbsolute [V2 (-gridWidth/2) (gridHeight/2)]\n , SVG.VerticalTo SVG.OriginRelative [-gridHeight]\n , SVG.HorizontalTo SVG.OriginRelative [gridWidth]\n , SVG.VerticalTo SVG.OriginRelative [gridHeight]\n , SVG.EndPath\n ]\n ]\n\nshowEasing nth txt fn color = do\n let steps = 100\n slope = withStrokeColorPixel color $\n translate gridOffset 0 $ mkLinePath\n [ ((x/steps-0.5)*gridWidth, (y-0.5)*gridHeight)\n | x <- [0..steps]\n , let y = fn (x/steps) ]\n s <- newSpriteSVG $\n withFillColorPixel color $\n translate (gridWidth/2+gridOffset+0.5) (gridHeight/2-nth) $\n label txt\n spriteE s $ overBeginning 0.2 fadeInE\n play $ animate $ \\t -> partialSvg t slope\n newSpriteSVG_ slope\n wait 1\n \nlabel txt = withStrokeColor \"black\" $\n withStrokeWidth (defaultStrokeWidth*2) $\n withFillOpacity 1 $\n latex txt\n"} ,{"title": "Easing Graphs","url": "https://reanimate.clozecards.com/FEyCDsj0V82/255.svg","code": "colorPalette = parula -- try: viridis, sinebow, turbo, cividis\nfns =\n [(\"curveS\", curveS 2)\n ,(\"bellS\", bellS 2)\n ,(\"constantS\", constantS 0.7)\n ,(\"oscillateS\", oscillateS)\n ,(\"powerS\", powerS 2)\n ,(\"reverseS\", reverseS)\n ,(\"id\", id)\n ]\n\nanimation :: Animation\nanimation = docEnv $ pauseAtEnd 1 $ sceneAnimation $ do\n newSpriteSVG_ $ mkBackground \"white\"\n play $ signalA (curveS 2) $ animate $ \\t -> partialSvg t grid\n newSpriteSVG_ grid\n wait 1\n flip mapM_ (zip [0..] fns) $ \\(nth, (txt, fn)) -> do\n let color = promotePixel $ colorPalette (nth / fromIntegral (length fns-1))\n showEasing nth txt fn color\n {- showEasing 3 \"oscillateS\" oscillateS\n showEasing 4 \"powerS\" (powerS 2)\n showEasing 5 \"reverseS\" reverseS\n showEasing 6 \"id\" id -}\n\ngridOffset = -2\ngridHeight = 5\ngridWidth = 8\n\ngrid :: SVG\ngrid = translate gridOffset 0 $\n withStrokeWidth defaultStrokeWidth $\n withStrokeColor \"grey\" $ mkGroup\n [ mkPath $ concat\n [[ SVG.MoveTo SVG.OriginAbsolute [V2 (-gridWidth/2) (gridHeight/2-n)]\n ,SVG.HorizontalTo SVG.OriginRelative [gridWidth] ]\n | n <- [1..gridHeight-1]\n ]\n , mkPath \n [ SVG.MoveTo SVG.OriginAbsolute [V2 (-gridWidth/2) (gridHeight/2)]\n , SVG.VerticalTo SVG.OriginRelative [-gridHeight]\n , SVG.HorizontalTo SVG.OriginRelative [gridWidth]\n , SVG.VerticalTo SVG.OriginRelative [gridHeight]\n , SVG.EndPath\n ]\n ]\n\nshowEasing nth txt fn color = do\n let steps = 100\n slope = withStrokeColorPixel color $\n translate gridOffset 0 $ mkLinePath\n [ ((x/steps-0.5)*gridWidth, (y-0.5)*gridHeight)\n | x <- [0..steps]\n , let y = fn (x/steps) ]\n s <- newSpriteSVG $\n withFillColorPixel color $\n translate (gridWidth/2+gridOffset+0.5) (gridHeight/2-nth) $\n label txt\n spriteE s $ overBeginning 0.2 fadeInE\n play $ animate $ \\t -> partialSvg t slope\n newSpriteSVG_ slope\n wait 1\n \nlabel txt = withStrokeColor \"black\" $\n withStrokeWidth (defaultStrokeWidth*2) $\n withFillOpacity 1 $\n latex txt\n"}
,{"title": "Object Positions","url": "https://reanimate.clozecards.com/IAQhjO0Ke7h/195.svg","code": "env =\n addStatic (mkBackground \"white\") .\n mapA (withStrokeColor \"black\")\n\nanimation :: Animation\nanimation = env $\n sceneAnimation $ do\n -- Configure objects\n txt <- newText \"Center\"\n top <- newText \"Top\"\n oModifyS top $ \n oTopY .= screenTop\n topR <- newText \"Top right\"\n oModifyS topR $ do\n oTopY .= screenTop\n oRightX .= screenRight\n botR <- newText \"Bottom right\"\n oModifyS botR $ do\n oBottomY .= screenBottom\n oRightX .= screenRight\n botL <- newText \"Bottom left\"\n oModifyS botL $ do\n oBottomY .= screenBottom\n oLeftX .= screenLeft\n topL <- newText \"Top left\"\n oModifyS topL $ do\n oTopY .= screenTop\n oLeftX .= screenLeft\n -- Show objects\n oShow txt\n wait 1\n switchTo txt top\n switchTo top topR\n switchTo topR botR\n switchTo botR botL\n switchTo botL topL\n switchTo topL txt\n\nswitchTo src dst = do\n fork $ oFadeOut src 1\n oModify dst $ oOpacity .~ 1\n oFadeIn dst 1\n wait 1\n\nnewText txt =\n newObject $ scale 1.5 $ center $ latex txt\n"} ,{"title": "Object Positions","url": "https://reanimate.clozecards.com/IAQhjO0Ke7h/195.svg","code": "env =\n addStatic (mkBackground \"white\") .\n mapA (withStrokeColor \"black\")\n\nanimation :: Animation\nanimation = env $\n sceneAnimation $ do\n -- Configure objects\n txt <- newText \"Center\"\n top <- newText \"Top\"\n oModifyS top $ \n oTopY .= screenTop\n topR <- newText \"Top right\"\n oModifyS topR $ do\n oTopY .= screenTop\n oRightX .= screenRight\n botR <- newText \"Bottom right\"\n oModifyS botR $ do\n oBottomY .= screenBottom\n oRightX .= screenRight\n botL <- newText \"Bottom left\"\n oModifyS botL $ do\n oBottomY .= screenBottom\n oLeftX .= screenLeft\n topL <- newText \"Top left\"\n oModifyS topL $ do\n oTopY .= screenTop\n oLeftX .= screenLeft\n -- Show objects\n oShow txt\n wait 1\n switchTo txt top\n switchTo top topR\n switchTo topR botR\n switchTo botR botL\n switchTo botL topL\n switchTo topL txt\n\nswitchTo src dst = do\n fork $ oFadeOut src 1\n oModify dst $ oOpacity .~ 1\n oFadeIn dst 1\n wait 1\n\nnewText txt =\n newObject $ scale 1.5 $ center $ latex txt\n"}
]; ];
const playgroundVersion = "2020-08-25 (41d6a)"; const playgroundVersion = "2020-08-25 (fd9fc)";

View file

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

View file

@ -17,62 +17,69 @@ span.spaces { background: white }
<span class="decl"><span class="nottickedoff">never executed</span> <span class="tickonlytrue">always true</span> <span class="tickonlyfalse">always false</span></span> <span class="decl"><span class="nottickedoff">never executed</span> <span class="tickonlytrue">always true</span> <span class="tickonlyfalse">always false</span></span>
</pre> </pre>
<pre> <pre>
<span class="lineno"> 1 </span>module Reanimate.Builtin.Documentation where <span class="lineno"> 1 </span>{-|
<span class="lineno"> 2 </span> <span class="lineno"> 2 </span>Module : Reanimate.Builtin.Documentation
<span class="lineno"> 3 </span>import Reanimate.Animation <span class="lineno"> 3 </span>Copyright : Written by David Himmelstrup
<span class="lineno"> 4 </span>import Reanimate.Svg <span class="lineno"> 4 </span>License : Unlicense
<span class="lineno"> 5 </span>import Reanimate.Raster <span class="lineno"> 5 </span>Maintainer : lemmih@gmail.com
<span class="lineno"> 6 </span>import Reanimate.Constants <span class="lineno"> 6 </span>Stability : experimental
<span class="lineno"> 7 </span>import Codec.Picture <span class="lineno"> 7 </span>Portability : POSIX
<span class="lineno"> 8 </span> <span class="lineno"> 8 </span>
<span class="lineno"> 9 </span>-- | Default environment for API documentation GIFs. <span class="lineno"> 9 </span>This module contains convenience functions used in documention
<span class="lineno"> 10 </span>docEnv :: Animation -&gt; Animation <span class="lineno"> 10 </span>GIFs for a consistent look and feel.
<span class="lineno"> 11 </span><span class="decl"><span class="istickedoff">docEnv = mapA $ \svg -&gt; mkGroup</span> <span class="lineno"> 11 </span>
<span class="lineno"> 12 </span><span class="spaces"> </span><span class="istickedoff">[ mkBackground &quot;white&quot;</span> <span class="lineno"> 12 </span>-}
<span class="lineno"> 13 </span><span class="spaces"> </span><span class="istickedoff">, withFillOpacity 0 $</span> <span class="lineno"> 13 </span>module Reanimate.Builtin.Documentation where
<span class="lineno"> 14 </span><span class="spaces"> </span><span class="istickedoff">withStrokeWidth 0.1 $</span> <span class="lineno"> 14 </span>
<span class="lineno"> 15 </span><span class="spaces"> </span><span class="istickedoff">withStrokeColor &quot;black&quot; (mkGroup [svg]) ]</span></span> <span class="lineno"> 15 </span>import Reanimate.Animation
<span class="lineno"> 16 </span> <span class="lineno"> 16 </span>import Reanimate.Svg
<span class="lineno"> 17 </span>-- | &lt;&lt;docs/gifs/doc_drawBox.gif&gt;&gt; <span class="lineno"> 17 </span>import Reanimate.Raster
<span class="lineno"> 18 </span>drawBox :: Animation <span class="lineno"> 18 </span>import Reanimate.Constants
<span class="lineno"> 19 </span><span class="decl"><span class="istickedoff">drawBox = mkAnimation 2 $ \t -&gt;</span> <span class="lineno"> 19 </span>import Codec.Picture
<span class="lineno"> 20 </span><span class="spaces"> </span><span class="istickedoff">partialSvg t $ pathify $</span> <span class="lineno"> 20 </span>
<span class="lineno"> 21 </span><span class="spaces"> </span><span class="istickedoff">mkRect (screenWidth/2) (screenHeight/2)</span></span> <span class="lineno"> 21 </span>-- | Default environment for API documentation GIFs.
<span class="lineno"> 22 </span> <span class="lineno"> 22 </span>docEnv :: Animation -&gt; Animation
<span class="lineno"> 23 </span>-- | &lt;&lt;docs/gifs/doc_drawCircle.gif&gt;&gt; <span class="lineno"> 23 </span><span class="decl"><span class="istickedoff">docEnv = mapA $ \svg -&gt; mkGroup</span>
<span class="lineno"> 24 </span>drawCircle :: Animation <span class="lineno"> 24 </span><span class="spaces"> </span><span class="istickedoff">[ mkBackground &quot;white&quot;</span>
<span class="lineno"> 25 </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">, withFillOpacity 0 $</span>
<span class="lineno"> 26 </span><span class="spaces"> </span><span class="istickedoff">partialSvg t $ pathify $</span> <span class="lineno"> 26 </span><span class="spaces"> </span><span class="istickedoff">withStrokeWidth 0.1 $</span>
<span class="lineno"> 27 </span><span class="spaces"> </span><span class="istickedoff">mkCircle (screenHeight/3)</span></span> <span class="lineno"> 27 </span><span class="spaces"> </span><span class="istickedoff">withStrokeColor &quot;black&quot; (mkGroup [svg]) ]</span></span>
<span class="lineno"> 28 </span> <span class="lineno"> 28 </span>
<span class="lineno"> 29 </span>drawBall :: Animation <span class="lineno"> 29 </span>-- | &lt;&lt;docs/gifs/doc_drawBox.gif&gt;&gt;
<span class="lineno"> 30 </span><span class="decl"><span class="nottickedoff">drawBall = mkAnimation 2 $ \t -&gt;</span> <span class="lineno"> 30 </span>drawBox :: Animation
<span class="lineno"> 31 </span><span class="spaces"> </span><span class="nottickedoff">scale t $ withFillOpacity 1 $ withFillColor &quot;red&quot; $</span> <span class="lineno"> 31 </span><span class="decl"><span class="istickedoff">drawBox = mkAnimation 2 $ \t -&gt;</span>
<span class="lineno"> 32 </span><span class="spaces"> </span><span class="nottickedoff">mkCircle (screenHeight/3)</span></span> <span class="lineno"> 32 </span><span class="spaces"> </span><span class="istickedoff">partialSvg t $ pathify $</span>
<span class="lineno"> 33 </span> <span class="lineno"> 33 </span><span class="spaces"> </span><span class="istickedoff">mkRect (screenWidth/2) (screenHeight/2)</span></span>
<span class="lineno"> 34 </span>-- | &lt;&lt;docs/gifs/doc_drawProgress.gif&gt;&gt; <span class="lineno"> 34 </span>
<span class="lineno"> 35 </span>drawProgress :: Animation <span class="lineno"> 35 </span>-- | &lt;&lt;docs/gifs/doc_drawCircle.gif&gt;&gt;
<span class="lineno"> 36 </span><span class="decl"><span class="istickedoff">drawProgress = mkAnimation 2 $ \t -&gt;</span> <span class="lineno"> 36 </span>drawCircle :: Animation
<span class="lineno"> 37 </span><span class="spaces"> </span><span class="istickedoff">mkGroup</span> <span class="lineno"> 37 </span><span class="decl"><span class="istickedoff">drawCircle = mkAnimation 2 $ \t -&gt;</span>
<span class="lineno"> 38 </span><span class="spaces"> </span><span class="istickedoff">[ mkLine (-screenWidth/2*widthP,0)</span> <span class="lineno"> 38 </span><span class="spaces"> </span><span class="istickedoff">partialSvg t $ pathify $</span>
<span class="lineno"> 39 </span><span class="spaces"> </span><span class="istickedoff">(screenWidth/2*widthP,0)</span> <span class="lineno"> 39 </span><span class="spaces"> </span><span class="istickedoff">mkCircle (screenHeight/3)</span></span>
<span class="lineno"> 40 </span><span class="spaces"> </span><span class="istickedoff">, translate (-screenWidth/2*widthP + screenWidth*widthP*t) 0 $</span> <span class="lineno"> 40 </span>
<span class="lineno"> 41 </span><span class="spaces"> </span><span class="istickedoff">withFillOpacity 1 $ mkCircle 0.5 ]</span> <span class="lineno"> 41 </span>-- | &lt;&lt;docs/gifs/doc_drawProgress.gif&gt;&gt;
<span class="lineno"> 42 </span><span class="spaces"> </span><span class="istickedoff">where</span> <span class="lineno"> 42 </span>drawProgress :: Animation
<span class="lineno"> 43 </span><span class="spaces"> </span><span class="istickedoff">widthP = 0.8</span></span> <span class="lineno"> 43 </span><span class="decl"><span class="istickedoff">drawProgress = mkAnimation 2 $ \t -&gt;</span>
<span class="lineno"> 44 </span> <span class="lineno"> 44 </span><span class="spaces"> </span><span class="istickedoff">mkGroup</span>
<span class="lineno"> 45 </span>-- | Render a full-screen view of a color-map. <span class="lineno"> 45 </span><span class="spaces"> </span><span class="istickedoff">[ mkLine (-screenWidth/2*widthP,0)</span>
<span class="lineno"> 46 </span>showColorMap :: (Double -&gt; PixelRGB8) -&gt; SVG <span class="lineno"> 46 </span><span class="spaces"> </span><span class="istickedoff">(screenWidth/2*widthP,0)</span>
<span class="lineno"> 47 </span><span class="decl"><span class="istickedoff">showColorMap f = center $ scaleToSize screenWidth screenHeight $ embedImage img</span> <span class="lineno"> 47 </span><span class="spaces"> </span><span class="istickedoff">, translate (-screenWidth/2*widthP + screenWidth*widthP*t) 0 $</span>
<span class="lineno"> 48 </span><span class="spaces"> </span><span class="istickedoff">where</span> <span class="lineno"> 48 </span><span class="spaces"> </span><span class="istickedoff">withFillOpacity 1 $ mkCircle 0.5 ]</span>
<span class="lineno"> 49 </span><span class="spaces"> </span><span class="istickedoff">width = 256</span> <span class="lineno"> 49 </span><span class="spaces"> </span><span class="istickedoff">where</span>
<span class="lineno"> 50 </span><span class="spaces"> </span><span class="istickedoff">height = 1</span> <span class="lineno"> 50 </span><span class="spaces"> </span><span class="istickedoff">widthP = 0.8</span></span>
<span class="lineno"> 51 </span><span class="spaces"> </span><span class="istickedoff">img = generateImage pixelRenderer width height</span> <span class="lineno"> 51 </span>
<span class="lineno"> 52 </span><span class="spaces"> </span><span class="istickedoff">pixelRenderer x _y = f (fromIntegral x / fromIntegral (width-1))</span></span> <span class="lineno"> 52 </span>-- | Render a full-screen view of a color-map.
<span class="lineno"> 53 </span> <span class="lineno"> 53 </span>showColorMap :: (Double -&gt; PixelRGB8) -&gt; SVG
<span class="lineno"> 54 </span>-- | Default background color for videos on reanimate.rtfd.io <span class="lineno"> 54 </span><span class="decl"><span class="istickedoff">showColorMap f = center $ scaleToSize screenWidth screenHeight $ embedImage img</span>
<span class="lineno"> 55 </span>rtfdBackgroundColor :: PixelRGBA8 <span class="lineno"> 55 </span><span class="spaces"> </span><span class="istickedoff">where</span>
<span class="lineno"> 56 </span><span class="decl"><span class="istickedoff">rtfdBackgroundColor = PixelRGBA8 252 252 252 0xFF</span></span> <span class="lineno"> 56 </span><span class="spaces"> </span><span class="istickedoff">width = 256</span>
<span class="lineno"> 57 </span><span class="spaces"> </span><span class="istickedoff">height = 1</span>
<span class="lineno"> 58 </span><span class="spaces"> </span><span class="istickedoff">img = generateImage pixelRenderer width height</span>
<span class="lineno"> 59 </span><span class="spaces"> </span><span class="istickedoff">pixelRenderer x _y = f (fromIntegral x / fromIntegral (width-1))</span></span>
<span class="lineno"> 60 </span>
<span class="lineno"> 61 </span>-- | Default background color for videos on reanimate.rtfd.io
<span class="lineno"> 62 </span>rtfdBackgroundColor :: PixelRGBA8
<span class="lineno"> 63 </span><span class="decl"><span class="istickedoff">rtfdBackgroundColor = PixelRGBA8 252 252 252 0xFF</span></span>
</pre> </pre>
</body> </body>

View file

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