Deploying to gh-pages from @ d1b0a50e51 🚀

This commit is contained in:
Lemmih 2020-08-07 03:17:08 +00:00
commit b86ff4e028
16 changed files with 2552 additions and 2469 deletions

View file

@ -1,25 +1,29 @@
100% ( 55 / 55) in 'Reanimate.Svg.Constructors'
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% ( 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.Povray'
100% ( 9 / 9) in 'Reanimate.Constants' 100% ( 9 / 9) in 'Reanimate.Constants'
94% (145 /155) in 'Reanimate' 100% ( 5 / 5) in 'Reanimate.Transform'
100% ( 4 / 4) in 'Reanimate.Svg.BoundingBox'
100% ( 3 / 3) in 'Reanimate.Blender'
99% (154 /155) in 'Reanimate'
95% ( 40 / 42) in 'Reanimate.Animation'
93% ( 13 / 14) in 'Reanimate.Raster'
91% ( 10 / 11) in 'Reanimate.Ease'
88% ( 7 / 8) in 'Reanimate.Transition' 88% ( 7 / 8) in 'Reanimate.Transition'
85% ( 47 / 55) in 'Reanimate.Svg.Constructors' 75% ( 6 / 8) in 'Reanimate.Builtin.Documentation'
77% ( 33 / 43) in 'Reanimate.Animation' 75% ( 3 / 4) in 'Reanimate.Svg.Unuse'
73% ( 8 / 11) in 'Reanimate.Ease'
71% ( 10 / 14) in 'Reanimate.Raster'
67% ( 6 / 9) in 'Reanimate.Voice'
67% ( 4 / 6) in 'Reanimate.Builtin.Images' 67% ( 4 / 6) in 'Reanimate.Builtin.Images'
56% ( 10 / 18) in 'Reanimate.Svg'
50% ( 1 / 2) in 'Reanimate.Builtin.CirclePlot' 50% ( 1 / 2) in 'Reanimate.Builtin.CirclePlot'
44% ( 4 / 9) in 'Reanimate.LaTeX' 44% ( 4 / 9) in 'Reanimate.LaTeX'
42% ( 47 /111) in 'Reanimate.Scene'
42% ( 17 / 40) in 'Reanimate.GeoProjection' 42% ( 17 / 40) in 'Reanimate.GeoProjection'
41% ( 45 /111) in 'Reanimate.Scene'
38% ( 3 / 8) in 'Reanimate.Builtin.Documentation'
33% ( 4 / 12) in 'Reanimate.Render' 33% ( 4 / 12) in 'Reanimate.Render'
28% ( 5 / 18) in 'Reanimate.Svg'
25% ( 1 / 4) in 'Reanimate.Builtin.Slide' 25% ( 1 / 4) in 'Reanimate.Builtin.Slide'
17% ( 1 / 6) in 'Reanimate.Svg.BoundingBox'
12% ( 2 / 17) in 'Reanimate.Math.SSSP' 12% ( 2 / 17) in 'Reanimate.Math.SSSP'
10% ( 3 / 30) in 'Reanimate.PolyShape' 10% ( 3 / 30) in 'Reanimate.PolyShape'
7% ( 2 / 29) in 'Reanimate.Math.Common' 7% ( 2 / 29) in 'Reanimate.Math.Common'
@ -34,7 +38,6 @@
0% ( 0 / 10) in 'Reanimate.Math.Render' 0% ( 0 / 10) in 'Reanimate.Math.Render'
0% ( 0 / 10) in 'Reanimate.ColorSpace' 0% ( 0 / 10) in 'Reanimate.ColorSpace'
0% ( 0 / 10) in 'Reanimate.Builtin.TernaryPlot' 0% ( 0 / 10) in 'Reanimate.Builtin.TernaryPlot'
0% ( 0 / 9) in 'Reanimate.Povray'
0% ( 0 / 9) in 'Reanimate.Math.Smooth' 0% ( 0 / 9) in 'Reanimate.Math.Smooth'
0% ( 0 / 8) in 'Reanimate.Misc' 0% ( 0 / 8) in 'Reanimate.Misc'
0% ( 0 / 8) in 'Reanimate.Math.Balloon' 0% ( 0 / 8) in 'Reanimate.Math.Balloon'
@ -43,12 +46,9 @@
0% ( 0 / 6) in 'Reanimate.Morph.Linear' 0% ( 0 / 6) in 'Reanimate.Morph.Linear'
0% ( 0 / 6) in 'Reanimate.Math.Triangulate' 0% ( 0 / 6) in 'Reanimate.Math.Triangulate'
0% ( 0 / 6) in 'Reanimate.Math.EarClip' 0% ( 0 / 6) in 'Reanimate.Math.EarClip'
0% ( 0 / 5) in 'Reanimate.Transform'
0% ( 0 / 5) in 'Reanimate.Builtin.Flip' 0% ( 0 / 5) in 'Reanimate.Builtin.Flip'
0% ( 0 / 4) in 'Reanimate.Svg.Unuse'
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.Morph.LineBend' 0% ( 0 / 3) in 'Reanimate.Morph.LineBend'
0% ( 0 / 3) in 'Reanimate.Memo' 0% ( 0 / 3) in 'Reanimate.Memo'
0% ( 0 / 3) in 'Reanimate.Blender'
0% ( 0 / 2) in 'Reanimate.Morph.Cache' 0% ( 0 / 2) in 'Reanimate.Morph.Cache'

View file

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

View file

@ -11,7 +11,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.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">84%</td><td>28/33</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="84%"><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/349</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">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>
<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">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>
@ -131,5 +131,5 @@ table.dashboard { border-collapse: collapse ; border: solid 1px black }
<td align="right">100%</td><td>6/6</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">50%</td><td>1/2</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="50%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">95%</td><td>43/45</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="95%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr> <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">31%</td><td>253/803</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="31%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">16%</td><td>131/811</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="16%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">30%</td><td>4760/15671</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">31%</td><td>253/802</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="31%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">16%</td><td>131/811</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="16%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">30%</td><td>4760/15669</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>
</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">84%</td><td>28/33</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="84%"><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/349</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">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>
<tr> <tr>
<td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.1.0-inplace/Reanimate.Chiphunk.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Chiphunk</a></tt></td> <td>&nbsp;&nbsp;<tt>module <a href="reanimate-0.4.1.0-inplace/Reanimate.Chiphunk.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Chiphunk</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">50%</td><td>2/4</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">63%</td><td>121/192</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="63%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></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">50%</td><td>2/4</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">63%</td><td>121/192</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="63%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td></tr>
@ -131,5 +131,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">31%</td><td>253/803</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="31%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">16%</td><td>131/811</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="16%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">30%</td><td>4760/15671</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">31%</td><td>253/802</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="31%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">16%</td><td>131/811</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="16%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">30%</td><td>4760/15669</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>
</table></body></html> </table></body></html>

View file

@ -17,7 +17,7 @@ table.dashboard { border-collapse: collapse ; border: solid 1px black }
<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">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.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">84%</td><td>28/33</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="84%"><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/349</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">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>
<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>
@ -131,5 +131,5 @@ table.dashboard { border-collapse: collapse ; border: solid 1px black }
<td align="right">0%</td><td>0/1</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td><td align="right">0%</td><td>0/4</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td><td align="right">0%</td><td>0/61</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td></tr> <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">31%</td><td>253/803</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="31%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">16%</td><td>131/811</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="16%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">30%</td><td>4760/15671</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">31%</td><td>253/802</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="31%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">16%</td><td>131/811</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="16%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">30%</td><td>4760/15669</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>
</table></body></html> </table></body></html>

View file

@ -13,12 +13,12 @@ table.dashboard { border-collapse: collapse ; border: solid 1px black }
<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.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>
<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">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.Animation.hs.html">reanimate-0.4.1.0-inplace/Reanimate.Animation</a></tt></td>
<td align="right">84%</td><td>28/33</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="84%"><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/349</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>
<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>
<tr> <tr>
@ -131,5 +131,5 @@ table.dashboard { border-collapse: collapse ; border: solid 1px black }
<td align="right">0%</td><td>0/1</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td><td align="right">0%</td><td>0/4</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td><td align="right">0%</td><td>0/61</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="100%"><tr><td height=12 class="invbar"></td></tr></table></td></tr></table></td></tr> <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">31%</td><td>253/803</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="31%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">16%</td><td>131/811</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="16%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">30%</td><td>4760/15671</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">31%</td><td>253/802</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="31%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">16%</td><td>131/811</td><td width=100><table cellpadding=0 cellspacing=0 width="100" class="bar"><tr><td><table cellpadding=0 cellspacing=0 width="16%"><tr><td height=12 class="bar"></td></tr></table></td></tr></table></td><td align="right">30%</td><td>4760/15669</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>
</table></body></html> </table></body></html>

View file

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

View file

@ -25,51 +25,54 @@ span.spaces { background: white }
<span class="lineno"> 6 </span>import Reanimate.Constants <span class="lineno"> 6 </span>import Reanimate.Constants
<span class="lineno"> 7 </span>import Codec.Picture <span class="lineno"> 7 </span>import Codec.Picture
<span class="lineno"> 8 </span> <span class="lineno"> 8 </span>
<span class="lineno"> 9 </span>docEnv :: Animation -&gt; Animation <span class="lineno"> 9 </span>-- | Default environment for API documentation GIFs.
<span class="lineno"> 10 </span><span class="decl"><span class="istickedoff">docEnv = mapA $ \svg -&gt; mkGroup</span> <span class="lineno"> 10 </span>docEnv :: Animation -&gt; Animation
<span class="lineno"> 11 </span><span class="spaces"> </span><span class="istickedoff">[ mkBackground &quot;white&quot;</span> <span class="lineno"> 11 </span><span class="decl"><span class="istickedoff">docEnv = mapA $ \svg -&gt; mkGroup</span>
<span class="lineno"> 12 </span><span class="spaces"> </span><span class="istickedoff">, withFillOpacity 0 $</span> <span class="lineno"> 12 </span><span class="spaces"> </span><span class="istickedoff">[ mkBackground &quot;white&quot;</span>
<span class="lineno"> 13 </span><span class="spaces"> </span><span class="istickedoff">withStrokeWidth 0.1 $</span> <span class="lineno"> 13 </span><span class="spaces"> </span><span class="istickedoff">, withFillOpacity 0 $</span>
<span class="lineno"> 14 </span><span class="spaces"> </span><span class="istickedoff">withStrokeColor &quot;black&quot; (mkGroup [svg]) ]</span></span> <span class="lineno"> 14 </span><span class="spaces"> </span><span class="istickedoff">withStrokeWidth 0.1 $</span>
<span class="lineno"> 15 </span> <span class="lineno"> 15 </span><span class="spaces"> </span><span class="istickedoff">withStrokeColor &quot;black&quot; (mkGroup [svg]) ]</span></span>
<span class="lineno"> 16 </span>-- | &lt;&lt;docs/gifs/doc_drawBox.gif&gt;&gt; <span class="lineno"> 16 </span>
<span class="lineno"> 17 </span>drawBox :: Animation <span class="lineno"> 17 </span>-- | &lt;&lt;docs/gifs/doc_drawBox.gif&gt;&gt;
<span class="lineno"> 18 </span><span class="decl"><span class="istickedoff">drawBox = mkAnimation 2 $ \t -&gt;</span> <span class="lineno"> 18 </span>drawBox :: Animation
<span class="lineno"> 19 </span><span class="spaces"> </span><span class="istickedoff">partialSvg t $ pathify $</span> <span class="lineno"> 19 </span><span class="decl"><span class="istickedoff">drawBox = mkAnimation 2 $ \t -&gt;</span>
<span class="lineno"> 20 </span><span class="spaces"> </span><span class="istickedoff">mkRect (screenWidth/2) (screenHeight/2)</span></span> <span class="lineno"> 20 </span><span class="spaces"> </span><span class="istickedoff">partialSvg t $ pathify $</span>
<span class="lineno"> 21 </span> <span class="lineno"> 21 </span><span class="spaces"> </span><span class="istickedoff">mkRect (screenWidth/2) (screenHeight/2)</span></span>
<span class="lineno"> 22 </span>-- | &lt;&lt;docs/gifs/doc_drawCircle.gif&gt;&gt; <span class="lineno"> 22 </span>
<span class="lineno"> 23 </span>drawCircle :: Animation <span class="lineno"> 23 </span>-- | &lt;&lt;docs/gifs/doc_drawCircle.gif&gt;&gt;
<span class="lineno"> 24 </span><span class="decl"><span class="istickedoff">drawCircle = mkAnimation 2 $ \t -&gt;</span> <span class="lineno"> 24 </span>drawCircle :: Animation
<span class="lineno"> 25 </span><span class="spaces"> </span><span class="istickedoff">partialSvg t $ pathify $</span> <span class="lineno"> 25 </span><span class="decl"><span class="istickedoff">drawCircle = mkAnimation 2 $ \t -&gt;</span>
<span class="lineno"> 26 </span><span class="spaces"> </span><span class="istickedoff">mkCircle (screenHeight/3)</span></span> <span class="lineno"> 26 </span><span class="spaces"> </span><span class="istickedoff">partialSvg t $ pathify $</span>
<span class="lineno"> 27 </span> <span class="lineno"> 27 </span><span class="spaces"> </span><span class="istickedoff">mkCircle (screenHeight/3)</span></span>
<span class="lineno"> 28 </span>drawBall :: Animation <span class="lineno"> 28 </span>
<span class="lineno"> 29 </span><span class="decl"><span class="nottickedoff">drawBall = mkAnimation 2 $ \t -&gt;</span> <span class="lineno"> 29 </span>drawBall :: Animation
<span class="lineno"> 30 </span><span class="spaces"> </span><span class="nottickedoff">scale t $ withFillOpacity 1 $ withFillColor &quot;red&quot; $</span> <span class="lineno"> 30 </span><span class="decl"><span class="nottickedoff">drawBall = mkAnimation 2 $ \t -&gt;</span>
<span class="lineno"> 31 </span><span class="spaces"> </span><span class="nottickedoff">mkCircle (screenHeight/3)</span></span> <span class="lineno"> 31 </span><span class="spaces"> </span><span class="nottickedoff">scale t $ withFillOpacity 1 $ withFillColor &quot;red&quot; $</span>
<span class="lineno"> 32 </span> <span class="lineno"> 32 </span><span class="spaces"> </span><span class="nottickedoff">mkCircle (screenHeight/3)</span></span>
<span class="lineno"> 33 </span>-- | &lt;&lt;docs/gifs/doc_drawProgress.gif&gt;&gt; <span class="lineno"> 33 </span>
<span class="lineno"> 34 </span>drawProgress :: Animation <span class="lineno"> 34 </span>-- | &lt;&lt;docs/gifs/doc_drawProgress.gif&gt;&gt;
<span class="lineno"> 35 </span><span class="decl"><span class="istickedoff">drawProgress = mkAnimation 2 $ \t -&gt;</span> <span class="lineno"> 35 </span>drawProgress :: Animation
<span class="lineno"> 36 </span><span class="spaces"> </span><span class="istickedoff">mkGroup</span> <span class="lineno"> 36 </span><span class="decl"><span class="istickedoff">drawProgress = mkAnimation 2 $ \t -&gt;</span>
<span class="lineno"> 37 </span><span class="spaces"> </span><span class="istickedoff">[ mkLine (-screenWidth/2*widthP,0)</span> <span class="lineno"> 37 </span><span class="spaces"> </span><span class="istickedoff">mkGroup</span>
<span class="lineno"> 38 </span><span class="spaces"> </span><span class="istickedoff">(screenWidth/2*widthP,0)</span> <span class="lineno"> 38 </span><span class="spaces"> </span><span class="istickedoff">[ mkLine (-screenWidth/2*widthP,0)</span>
<span class="lineno"> 39 </span><span class="spaces"> </span><span class="istickedoff">, translate (-screenWidth/2*widthP + screenWidth*widthP*t) 0 $</span> <span class="lineno"> 39 </span><span class="spaces"> </span><span class="istickedoff">(screenWidth/2*widthP,0)</span>
<span class="lineno"> 40 </span><span class="spaces"> </span><span class="istickedoff">withFillOpacity 1 $ mkCircle 0.5 ]</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"> 41 </span><span class="spaces"> </span><span class="istickedoff">where</span> <span class="lineno"> 41 </span><span class="spaces"> </span><span class="istickedoff">withFillOpacity 1 $ mkCircle 0.5 ]</span>
<span class="lineno"> 42 </span><span class="spaces"> </span><span class="istickedoff">widthP = 0.8</span></span> <span class="lineno"> 42 </span><span class="spaces"> </span><span class="istickedoff">where</span>
<span class="lineno"> 43 </span> <span class="lineno"> 43 </span><span class="spaces"> </span><span class="istickedoff">widthP = 0.8</span></span>
<span class="lineno"> 44 </span>showColorMap :: (Double -&gt; PixelRGB8) -&gt; SVG <span class="lineno"> 44 </span>
<span class="lineno"> 45 </span><span class="decl"><span class="istickedoff">showColorMap f = center $ scaleToSize screenWidth screenHeight $ embedImage img</span> <span class="lineno"> 45 </span>-- | Render a full-screen view of a color-map.
<span class="lineno"> 46 </span><span class="spaces"> </span><span class="istickedoff">where</span> <span class="lineno"> 46 </span>showColorMap :: (Double -&gt; PixelRGB8) -&gt; SVG
<span class="lineno"> 47 </span><span class="spaces"> </span><span class="istickedoff">width = 256</span> <span class="lineno"> 47 </span><span class="decl"><span class="istickedoff">showColorMap f = center $ scaleToSize screenWidth screenHeight $ embedImage img</span>
<span class="lineno"> 48 </span><span class="spaces"> </span><span class="istickedoff">height = 1</span> <span class="lineno"> 48 </span><span class="spaces"> </span><span class="istickedoff">where</span>
<span class="lineno"> 49 </span><span class="spaces"> </span><span class="istickedoff">img = generateImage pixelRenderer width height</span> <span class="lineno"> 49 </span><span class="spaces"> </span><span class="istickedoff">width = 256</span>
<span class="lineno"> 50 </span><span class="spaces"> </span><span class="istickedoff">pixelRenderer x _y = f (fromIntegral x / fromIntegral (width-1))</span></span> <span class="lineno"> 50 </span><span class="spaces"> </span><span class="istickedoff">height = 1</span>
<span class="lineno"> 51 </span> <span class="lineno"> 51 </span><span class="spaces"> </span><span class="istickedoff">img = generateImage pixelRenderer width height</span>
<span class="lineno"> 52 </span>rtfdBackgroundColor :: PixelRGBA8 <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"> 53 </span><span class="decl"><span class="istickedoff">rtfdBackgroundColor = PixelRGBA8 252 252 252 0xFF</span></span> <span class="lineno"> 53 </span>
<span class="lineno"> 54 </span>-- | Default background color for videos on reanimate.rtfd.io
<span class="lineno"> 55 </span>rtfdBackgroundColor :: PixelRGBA8
<span class="lineno"> 56 </span><span class="decl"><span class="istickedoff">rtfdBackgroundColor = PixelRGBA8 252 252 252 0xFF</span></span>
</pre> </pre>
</body> </body>

View file

@ -17,113 +17,124 @@ 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.Ease <span class="lineno"> 1 </span>{-|
<span class="lineno"> 2 </span> ( Signal <span class="lineno"> 2 </span> Easing functions modify the rate of change in animations.
<span class="lineno"> 3 </span> , constantS <span class="lineno"> 3 </span> More examples can be seen here: &lt;https://easings.net/&gt;.
<span class="lineno"> 4 </span> , fromToS <span class="lineno"> 4 </span>-}
<span class="lineno"> 5 </span> , reverseS <span class="lineno"> 5 </span>module Reanimate.Ease
<span class="lineno"> 6 </span> , curveS <span class="lineno"> 6 </span> ( Signal
<span class="lineno"> 7 </span> , powerS <span class="lineno"> 7 </span> , constantS
<span class="lineno"> 8 </span> , bellS <span class="lineno"> 8 </span> , fromToS
<span class="lineno"> 9 </span> , oscillateS <span class="lineno"> 9 </span> , reverseS
<span class="lineno"> 10 </span> , fromListS <span class="lineno"> 10 </span> , curveS
<span class="lineno"> 11 </span> , cubicBezierS <span class="lineno"> 11 </span> , powerS
<span class="lineno"> 12 </span> ) where <span class="lineno"> 12 </span> , bellS
<span class="lineno"> 13 </span> <span class="lineno"> 13 </span> , oscillateS
<span class="lineno"> 14 </span>-- | Signals are time-varying variables. Signals can be composed using function <span class="lineno"> 14 </span> , fromListS
<span class="lineno"> 15 </span>-- composition. <span class="lineno"> 15 </span> , cubicBezierS
<span class="lineno"> 16 </span>type Signal = Double -&gt; Double <span class="lineno"> 16 </span> ) where
<span class="lineno"> 17 </span> <span class="lineno"> 17 </span>
<span class="lineno"> 18 </span>fromListS :: [(Double, Signal)] -&gt; Signal <span class="lineno"> 18 </span>-- | Signals are time-varying variables. Signals can be composed using function
<span class="lineno"> 19 </span><span class="decl"><span class="nottickedoff">fromListS fns t = worker 0 fns</span> <span class="lineno"> 19 </span>-- composition.
<span class="lineno"> 20 </span><span class="spaces"> </span><span class="nottickedoff">where</span> <span class="lineno"> 20 </span>type Signal = Double -&gt; Double
<span class="lineno"> 21 </span><span class="spaces"> </span><span class="nottickedoff">worker _ [] = 0</span> <span class="lineno"> 21 </span>
<span class="lineno"> 22 </span><span class="spaces"> </span><span class="nottickedoff">worker now [(len, fn)] = fn (min 1 ((t-now) / min (1-now) len))</span> <span class="lineno"> 22 </span>fromListS :: [(Double, Signal)] -&gt; Signal
<span class="lineno"> 23 </span><span class="spaces"> </span><span class="nottickedoff">worker now ((len, fn):rest)</span> <span class="lineno"> 23 </span><span class="decl"><span class="nottickedoff">fromListS fns t = worker 0 fns</span>
<span class="lineno"> 24 </span><span class="spaces"> </span><span class="nottickedoff">| now+len &lt; t = worker (now+len) rest</span> <span class="lineno"> 24 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 25 </span><span class="spaces"> </span><span class="nottickedoff">| otherwise = fn ((t-now) / len)</span></span> <span class="lineno"> 25 </span><span class="spaces"> </span><span class="nottickedoff">worker _ [] = 0</span>
<span class="lineno"> 26 </span> <span class="lineno"> 26 </span><span class="spaces"> </span><span class="nottickedoff">worker now [(len, fn)] = fn (min 1 ((t-now) / min (1-now) len))</span>
<span class="lineno"> 27 </span>-- | Constant signal. <span class="lineno"> 27 </span><span class="spaces"> </span><span class="nottickedoff">worker now ((len, fn):rest)</span>
<span class="lineno"> 28 </span>-- <span class="lineno"> 28 </span><span class="spaces"> </span><span class="nottickedoff">| now+len &lt; t = worker (now+len) rest</span>
<span class="lineno"> 29 </span>-- Example: <span class="lineno"> 29 </span><span class="spaces"> </span><span class="nottickedoff">| otherwise = fn ((t-now) / len)</span></span>
<span class="lineno"> 30 </span>-- <span class="lineno"> 30 </span>
<span class="lineno"> 31 </span>-- &gt; signalA (constantS 0.5) drawProgress <span class="lineno"> 31 </span>-- | Constant signal.
<span class="lineno"> 32 </span>-- <span class="lineno"> 32 </span>--
<span class="lineno"> 33 </span>-- &lt;&lt;docs/gifs/doc_constantS.gif&gt;&gt; <span class="lineno"> 33 </span>-- Example:
<span class="lineno"> 34 </span>constantS :: Double -&gt; Signal <span class="lineno"> 34 </span>--
<span class="lineno"> 35 </span><span class="decl"><span class="istickedoff">constantS = const</span></span> <span class="lineno"> 35 </span>-- &gt; signalA (constantS 0.5) drawProgress
<span class="lineno"> 36 </span> <span class="lineno"> 36 </span>--
<span class="lineno"> 37 </span>-- | Signal with new starting and end values. <span class="lineno"> 37 </span>-- &lt;&lt;docs/gifs/doc_constantS.gif&gt;&gt;
<span class="lineno"> 38 </span>-- <span class="lineno"> 38 </span>constantS :: Double -&gt; Signal
<span class="lineno"> 39 </span>-- Example: <span class="lineno"> 39 </span><span class="decl"><span class="istickedoff">constantS = const</span></span>
<span class="lineno"> 40 </span>-- <span class="lineno"> 40 </span>
<span class="lineno"> 41 </span>-- &gt; signalA (fromToS 0.8 0.2) drawProgress <span class="lineno"> 41 </span>-- | Signal with new starting and end values.
<span class="lineno"> 42 </span>-- <span class="lineno"> 42 </span>--
<span class="lineno"> 43 </span>-- &lt;&lt;docs/gifs/doc_fromToS.gif&gt;&gt; <span class="lineno"> 43 </span>-- Example:
<span class="lineno"> 44 </span>fromToS :: Double -&gt; Double -&gt; Signal <span class="lineno"> 44 </span>--
<span class="lineno"> 45 </span><span class="decl"><span class="istickedoff">fromToS from to t = from + (to-from)*t</span></span> <span class="lineno"> 45 </span>-- &gt; signalA (fromToS 0.8 0.2) drawProgress
<span class="lineno"> 46 </span> <span class="lineno"> 46 </span>--
<span class="lineno"> 47 </span>-- | Reverse signal order. <span class="lineno"> 47 </span>-- &lt;&lt;docs/gifs/doc_fromToS.gif&gt;&gt;
<span class="lineno"> 48 </span>-- <span class="lineno"> 48 </span>fromToS :: Double -&gt; Double -&gt; Signal
<span class="lineno"> 49 </span>-- Example: <span class="lineno"> 49 </span><span class="decl"><span class="istickedoff">fromToS from to t = from + (to-from)*t</span></span>
<span class="lineno"> 50 </span>-- <span class="lineno"> 50 </span>
<span class="lineno"> 51 </span>-- &gt; signalA reverseS drawProgress <span class="lineno"> 51 </span>-- | Reverse signal order.
<span class="lineno"> 52 </span>-- <span class="lineno"> 52 </span>--
<span class="lineno"> 53 </span>-- &lt;&lt;docs/gifs/doc_reverseS.gif&gt;&gt; <span class="lineno"> 53 </span>-- Example:
<span class="lineno"> 54 </span>reverseS :: Signal <span class="lineno"> 54 </span>--
<span class="lineno"> 55 </span><span class="decl"><span class="istickedoff">reverseS t = 1-t</span></span> <span class="lineno"> 55 </span>-- &gt; signalA reverseS drawProgress
<span class="lineno"> 56 </span> <span class="lineno"> 56 </span>--
<span class="lineno"> 57 </span>-- | S-curve signal. Takes a steepness parameter. 2 is a good default. <span class="lineno"> 57 </span>-- &lt;&lt;docs/gifs/doc_reverseS.gif&gt;&gt;
<span class="lineno"> 58 </span>-- <span class="lineno"> 58 </span>reverseS :: Signal
<span class="lineno"> 59 </span>-- Example: <span class="lineno"> 59 </span><span class="decl"><span class="istickedoff">reverseS t = 1-t</span></span>
<span class="lineno"> 60 </span>-- <span class="lineno"> 60 </span>
<span class="lineno"> 61 </span>-- &gt; signalA (curveS 2) drawProgress <span class="lineno"> 61 </span>-- | S-curve signal. Takes a steepness parameter. 2 is a good default.
<span class="lineno"> 62 </span>-- <span class="lineno"> 62 </span>--
<span class="lineno"> 63 </span>-- &lt;&lt;docs/gifs/doc_curveS.gif&gt;&gt; <span class="lineno"> 63 </span>-- Example:
<span class="lineno"> 64 </span>curveS :: Double -&gt; Signal <span class="lineno"> 64 </span>--
<span class="lineno"> 65 </span><span class="decl"><span class="istickedoff">curveS steepness s =</span> <span class="lineno"> 65 </span>-- &gt; signalA (curveS 2) drawProgress
<span class="lineno"> 66 </span><span class="spaces"> </span><span class="istickedoff">if s &lt; 0.5</span> <span class="lineno"> 66 </span>--
<span class="lineno"> 67 </span><span class="spaces"> </span><span class="istickedoff">then 0.5 * (2*s)**steepness</span> <span class="lineno"> 67 </span>-- &lt;&lt;docs/gifs/doc_curveS.gif&gt;&gt;
<span class="lineno"> 68 </span><span class="spaces"> </span><span class="istickedoff">else 1-0.5 * (2 - 2*s)**steepness</span></span> <span class="lineno"> 68 </span>curveS :: Double -&gt; Signal
<span class="lineno"> 69 </span> <span class="lineno"> 69 </span><span class="decl"><span class="istickedoff">curveS steepness s =</span>
<span class="lineno"> 70 </span>powerS :: Double -&gt; Signal <span class="lineno"> 70 </span><span class="spaces"> </span><span class="istickedoff">if s &lt; 0.5</span>
<span class="lineno"> 71 </span><span class="decl"><span class="nottickedoff">powerS steepness s = s**steepness</span></span> <span class="lineno"> 71 </span><span class="spaces"> </span><span class="istickedoff">then 0.5 * (2*s)**steepness</span>
<span class="lineno"> 72 </span> <span class="lineno"> 72 </span><span class="spaces"> </span><span class="istickedoff">else 1-0.5 * (2 - 2*s)**steepness</span></span>
<span class="lineno"> 73 </span>-- | Oscillate signal. <span class="lineno"> 73 </span>
<span class="lineno"> 74 </span>-- <span class="lineno"> 74 </span>-- | Power curve signal. Takes a steepness parameter. 2 is a good default.
<span class="lineno"> 75 </span>-- Example: <span class="lineno"> 75 </span>--
<span class="lineno"> 76 </span>-- <span class="lineno"> 76 </span>-- Example:
<span class="lineno"> 77 </span>-- &gt; signalA oscillateS drawProgress <span class="lineno"> 77 </span>--
<span class="lineno"> 78 </span>-- <span class="lineno"> 78 </span>-- &gt; signalA (powerS 2) drawProgress
<span class="lineno"> 79 </span>-- &lt;&lt;docs/gifs/doc_oscillateS.gif&gt;&gt; <span class="lineno"> 79 </span>--
<span class="lineno"> 80 </span>oscillateS :: Signal <span class="lineno"> 80 </span>-- &lt;&lt;docs/gifs/doc_powerS.gif&gt;&gt;
<span class="lineno"> 81 </span><span class="decl"><span class="istickedoff">oscillateS t =</span> <span class="lineno"> 81 </span>powerS :: Double -&gt; Signal
<span class="lineno"> 82 </span><span class="spaces"> </span><span class="istickedoff">if t &lt; 1/2</span> <span class="lineno"> 82 </span><span class="decl"><span class="nottickedoff">powerS steepness s = s**steepness</span></span>
<span class="lineno"> 83 </span><span class="spaces"> </span><span class="istickedoff">then t*2</span> <span class="lineno"> 83 </span>
<span class="lineno"> 84 </span><span class="spaces"> </span><span class="istickedoff">else 2-t*2</span></span> <span class="lineno"> 84 </span>-- | Oscillate signal.
<span class="lineno"> 85 </span> <span class="lineno"> 85 </span>--
<span class="lineno"> 86 </span>-- | Bell-curve signal. Takes a steepness parameter. 2 is a good default. <span class="lineno"> 86 </span>-- Example:
<span class="lineno"> 87 </span>-- <span class="lineno"> 87 </span>--
<span class="lineno"> 88 </span>-- Example: <span class="lineno"> 88 </span>-- &gt; signalA oscillateS drawProgress
<span class="lineno"> 89 </span>-- <span class="lineno"> 89 </span>--
<span class="lineno"> 90 </span>-- &gt; signalA (bellS 2) drawProgress <span class="lineno"> 90 </span>-- &lt;&lt;docs/gifs/doc_oscillateS.gif&gt;&gt;
<span class="lineno"> 91 </span>-- <span class="lineno"> 91 </span>oscillateS :: Signal
<span class="lineno"> 92 </span>-- &lt;&lt;docs/gifs/doc_bellS.gif&gt;&gt; <span class="lineno"> 92 </span><span class="decl"><span class="istickedoff">oscillateS t =</span>
<span class="lineno"> 93 </span>bellS :: Double -&gt; Signal <span class="lineno"> 93 </span><span class="spaces"> </span><span class="istickedoff">if t &lt; 1/2</span>
<span class="lineno"> 94 </span><span class="decl"><span class="istickedoff">bellS steepness = curveS steepness . oscillateS</span></span> <span class="lineno"> 94 </span><span class="spaces"> </span><span class="istickedoff">then t*2</span>
<span class="lineno"> 95 </span> <span class="lineno"> 95 </span><span class="spaces"> </span><span class="istickedoff">else 2-t*2</span></span>
<span class="lineno"> 96 </span>-- | Cubic Bezier signal. Gives you a fair amount of control over how the <span class="lineno"> 96 </span>
<span class="lineno"> 97 </span>-- signal will 'curve'. <span class="lineno"> 97 </span>-- | Bell-curve signal. Takes a steepness parameter. 2 is a good default.
<span class="lineno"> 98 </span>-- <span class="lineno"> 98 </span>--
<span class="lineno"> 99 </span>-- Example: <span class="lineno"> 99 </span>-- Example:
<span class="lineno"> 100 </span>-- <span class="lineno"> 100 </span>--
<span class="lineno"> 101 </span>-- &gt; signalA (cubicBezierS (0.0, 0.8, 0.9, 1.0)) drawProgress <span class="lineno"> 101 </span>-- &gt; signalA (bellS 2) drawProgress
<span class="lineno"> 102 </span>-- <span class="lineno"> 102 </span>--
<span class="lineno"> 103 </span>-- &lt;&lt;docs/gifs/doc_cubicBezierS.gif&gt;&gt; <span class="lineno"> 103 </span>-- &lt;&lt;docs/gifs/doc_bellS.gif&gt;&gt;
<span class="lineno"> 104 </span>cubicBezierS :: (Double, Double, Double, Double) -&gt; Signal <span class="lineno"> 104 </span>bellS :: Double -&gt; Signal
<span class="lineno"> 105 </span><span class="decl"><span class="istickedoff">cubicBezierS (x1, x2, x3, x4) s = </span> <span class="lineno"> 105 </span><span class="decl"><span class="istickedoff">bellS steepness = curveS steepness . oscillateS</span></span>
<span class="lineno"> 106 </span><span class="spaces"> </span><span class="istickedoff">let ms = 1-s</span> <span class="lineno"> 106 </span>
<span class="lineno"> 107 </span><span class="spaces"> </span><span class="istickedoff">in x1*ms^(3::Int) + 3*x2*ms^(2::Int)*s + 3*x3*ms*s^(2::Int) + x4*s^(3::Int)</span></span> <span class="lineno"> 107 </span>-- | Cubic Bezier signal. Gives you a fair amount of control over how the
<span class="lineno"> 108 </span>-- signal will 'curve'.
<span class="lineno"> 109 </span>--
<span class="lineno"> 110 </span>-- Example:
<span class="lineno"> 111 </span>--
<span class="lineno"> 112 </span>-- &gt; signalA (cubicBezierS (0.0, 0.8, 0.9, 1.0)) drawProgress
<span class="lineno"> 113 </span>--
<span class="lineno"> 114 </span>-- &lt;&lt;docs/gifs/doc_cubicBezierS.gif&gt;&gt;
<span class="lineno"> 115 </span>cubicBezierS :: (Double, Double, Double, Double) -&gt; Signal
<span class="lineno"> 116 </span><span class="decl"><span class="istickedoff">cubicBezierS (x1, x2, x3, x4) s = </span>
<span class="lineno"> 117 </span><span class="spaces"> </span><span class="istickedoff">let ms = 1-s</span>
<span class="lineno"> 118 </span><span class="spaces"> </span><span class="istickedoff">in x1*ms^(3::Int) + 3*x2*ms^(2::Int)*s + 3*x3*ms*s^(2::Int) + x4*s^(3::Int)</span></span>
</pre> </pre>
</body> </body>

View file

@ -138,180 +138,189 @@ span.spaces { background: white }
<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">target = pRootDirectory &lt;/&gt; encodeInt hashPath &lt;.&gt; takeExtension path</span>
<span class="lineno"> 120 </span><span class="spaces"> </span><span class="nottickedoff">hashPath = hash path</span></span> <span class="lineno"> 120 </span><span class="spaces"> </span><span class="nottickedoff">hashPath = hash path</span></span>
<span class="lineno"> 121 </span> <span class="lineno"> 121 </span>
<span class="lineno"> 122 </span>cacheImage :: (PngSavable pixel, Hashable a) =&gt; a -&gt; Image pixel -&gt; FilePath <span class="lineno"> 122 </span>-- | Write in-memory image to cache file if (and only if) such cache file doesn't
<span class="lineno"> 123 </span><span class="decl"><span class="nottickedoff">cacheImage key gen = unsafePerformIO $ cacheFile template $ \path -&gt;</span> <span class="lineno"> 123 </span>-- already exist.
<span class="lineno"> 124 </span><span class="spaces"> </span><span class="nottickedoff">writePng path gen</span> <span class="lineno"> 124 </span>cacheImage :: (PngSavable pixel, Hashable a) =&gt; a -&gt; Image pixel -&gt; FilePath
<span class="lineno"> 125 </span><span class="spaces"> </span><span class="nottickedoff">where template = encodeInt (hash key) &lt;.&gt; &quot;png&quot;</span></span> <span class="lineno"> 125 </span><span class="decl"><span class="nottickedoff">cacheImage key gen = unsafePerformIO $ cacheFile template $ \path -&gt;</span>
<span class="lineno"> 126 </span> <span class="lineno"> 126 </span><span class="spaces"> </span><span class="nottickedoff">writePng path gen</span>
<span class="lineno"> 127 </span>-- Warning: Caching svg elements with links to external objects does <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"> 128 </span>-- not work. 2020-06-01 <span class="lineno"> 128 </span>
<span class="lineno"> 129 </span>prerenderSvgFile :: Hashable a =&gt; a -&gt; Width -&gt; Height -&gt; SVG -&gt; FilePath <span class="lineno"> 129 </span>-- Warning: Caching svg elements with links to external objects does
<span class="lineno"> 130 </span><span class="decl"><span class="nottickedoff">prerenderSvgFile key width height svg =</span> <span class="lineno"> 130 </span>-- not work. 2020-06-01
<span class="lineno"> 131 </span><span class="spaces"> </span><span class="nottickedoff">unsafePerformIO $ cacheFile template $ \path -&gt; do</span> <span class="lineno"> 131 </span>-- | Same as 'prerenderSvg' but returns the location of the rendered image
<span class="lineno"> 132 </span><span class="spaces"> </span><span class="nottickedoff">let svgPath = replaceExtension path &quot;svg&quot;</span> <span class="lineno"> 132 </span>-- as a FilePath.
<span class="lineno"> 133 </span><span class="spaces"> </span><span class="nottickedoff">writeFile svgPath rendered</span> <span class="lineno"> 133 </span>prerenderSvgFile :: Hashable a =&gt; a -&gt; Width -&gt; Height -&gt; SVG -&gt; FilePath
<span class="lineno"> 134 </span><span class="spaces"> </span><span class="nottickedoff">engine &lt;- requireRaster pRaster</span> <span class="lineno"> 134 </span><span class="decl"><span class="nottickedoff">prerenderSvgFile key width height svg =</span>
<span class="lineno"> 135 </span><span class="spaces"> </span><span class="nottickedoff">applyRaster engine svgPath</span> <span class="lineno"> 135 </span><span class="spaces"> </span><span class="nottickedoff">unsafePerformIO $ cacheFile template $ \path -&gt; do</span>
<span class="lineno"> 136 </span><span class="spaces"> </span><span class="nottickedoff">where</span> <span class="lineno"> 136 </span><span class="spaces"> </span><span class="nottickedoff">let svgPath = replaceExtension path &quot;svg&quot;</span>
<span class="lineno"> 137 </span><span class="spaces"> </span><span class="nottickedoff">template = encodeInt (hash (key, width, height)) &lt;.&gt; &quot;png&quot;</span> <span class="lineno"> 137 </span><span class="spaces"> </span><span class="nottickedoff">writeFile svgPath rendered</span>
<span class="lineno"> 138 </span><span class="spaces"> </span><span class="nottickedoff">rendered = renderSvg (Just $ Px $ fromIntegral width)</span> <span class="lineno"> 138 </span><span class="spaces"> </span><span class="nottickedoff">engine &lt;- requireRaster pRaster</span>
<span class="lineno"> 139 </span><span class="spaces"> </span><span class="nottickedoff">(Just $ Px $ fromIntegral height)</span> <span class="lineno"> 139 </span><span class="spaces"> </span><span class="nottickedoff">applyRaster engine svgPath</span>
<span class="lineno"> 140 </span><span class="spaces"> </span><span class="nottickedoff">svg</span></span> <span class="lineno"> 140 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 141 </span> <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"> 142 </span>prerenderSvg :: Hashable a =&gt; a -&gt; SVG -&gt; SVG <span class="lineno"> 142 </span><span class="spaces"> </span><span class="nottickedoff">rendered = renderSvg (Just $ Px $ fromIntegral width)</span>
<span class="lineno"> 143 </span><span class="decl"><span class="nottickedoff">prerenderSvg key =</span> <span class="lineno"> 143 </span><span class="spaces"> </span><span class="nottickedoff">(Just $ Px $ fromIntegral height)</span>
<span class="lineno"> 144 </span><span class="spaces"> </span><span class="nottickedoff">mkImage screenWidth screenHeight . prerenderSvgFile key pWidth pHeight</span></span> <span class="lineno"> 144 </span><span class="spaces"> </span><span class="nottickedoff">svg</span></span>
<span class="lineno"> 145 </span> <span class="lineno"> 145 </span>
<span class="lineno"> 146 </span> <span class="lineno"> 146 </span>-- | Render SVG node to a PNG file and return a new node containing
<span class="lineno"> 147 </span>{-# INLINE embedImage #-} <span class="lineno"> 147 </span>-- that image. For static SVG nodes, this can hugely improve performance.
<span class="lineno"> 148 </span>-- | Embed an in-memory PNG image. Note, the pixel size of the image <span class="lineno"> 148 </span>-- The first argument is the key that determines SVG uniqueness. It
<span class="lineno"> 149 </span>-- is used as the dimensions. As such, embedding a 100x100 PNG will <span class="lineno"> 149 </span>-- is entirely your responsibility to ensure that all keys are unique.
<span class="lineno"> 150 </span>-- result in an image 100 units wide and 100 units high. Consider <span class="lineno"> 150 </span>-- If they are not, you will be served stale results from the cache.
<span class="lineno"> 151 </span>-- using with 'scaleToSize'. <span class="lineno"> 151 </span>prerenderSvg :: Hashable a =&gt; a -&gt; SVG -&gt; SVG
<span class="lineno"> 152 </span>embedImage :: PngSavable a =&gt; Image a -&gt; SVG <span class="lineno"> 152 </span><span class="decl"><span class="nottickedoff">prerenderSvg key =</span>
<span class="lineno"> 153 </span><span class="decl"><span class="istickedoff">embedImage img = embedPng width height (encodePng img)</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"> 154 </span><span class="spaces"> </span><span class="istickedoff">where</span> <span class="lineno"> 154 </span>
<span class="lineno"> 155 </span><span class="spaces"> </span><span class="istickedoff">width = fromIntegral $ imageWidth img</span> <span class="lineno"> 155 </span>
<span class="lineno"> 156 </span><span class="spaces"> </span><span class="istickedoff">height = fromIntegral $ imageHeight img</span></span> <span class="lineno"> 156 </span>{-# INLINE embedImage #-}
<span class="lineno"> 157 </span> <span class="lineno"> 157 </span>-- | Embed an in-memory PNG image. Note, the pixel size of the image
<span class="lineno"> 158 </span>-- | Embed in-memory PNG bytestring without parsing it. <span class="lineno"> 158 </span>-- is used as the dimensions. As such, embedding a 100x100 PNG will
<span class="lineno"> 159 </span>embedPng <span class="lineno"> 159 </span>-- result in an image 100 units wide and 100 units high. Consider
<span class="lineno"> 160 </span> :: Double -- ^ Width <span class="lineno"> 160 </span>-- using with 'scaleToSize'.
<span class="lineno"> 161 </span> -&gt; Double -- ^ Height <span class="lineno"> 161 </span>embedImage :: PngSavable a =&gt; Image a -&gt; SVG
<span class="lineno"> 162 </span> -&gt; LBS.ByteString -- ^ Raw PNG data <span class="lineno"> 162 </span><span class="decl"><span class="istickedoff">embedImage img = embedPng width height (encodePng img)</span>
<span class="lineno"> 163 </span> -&gt; SVG <span class="lineno"> 163 </span><span class="spaces"> </span><span class="istickedoff">where</span>
<span class="lineno"> 164 </span>-- embedPng w h png = unsafePerformIO $ do <span class="lineno"> 164 </span><span class="spaces"> </span><span class="istickedoff">width = fromIntegral $ imageWidth img</span>
<span class="lineno"> 165 </span>-- LBS.writeFile path png <span class="lineno"> 165 </span><span class="spaces"> </span><span class="istickedoff">height = fromIntegral $ imageHeight img</span></span>
<span class="lineno"> 166 </span>-- return $ ImageTree $ defaultSvg <span class="lineno"> 166 </span>
<span class="lineno"> 167 </span>-- &amp; Svg.imageCornerUpperLeft .~ (Svg.Num (-w/2), Svg.Num (-h/2)) <span class="lineno"> 167 </span>-- | Embed in-memory PNG bytestring without parsing it.
<span class="lineno"> 168 </span>-- &amp; Svg.imageWidth .~ Svg.Num w <span class="lineno"> 168 </span>embedPng
<span class="lineno"> 169 </span>-- &amp; Svg.imageHeight .~ Svg.Num h <span class="lineno"> 169 </span> :: Double -- ^ Width
<span class="lineno"> 170 </span>-- &amp; Svg.imageHref .~ (&quot;file://&quot;++path) <span class="lineno"> 170 </span> -&gt; Double -- ^ Height
<span class="lineno"> 171 </span>-- where <span class="lineno"> 171 </span> -&gt; LBS.ByteString -- ^ Raw PNG data
<span class="lineno"> 172 </span>-- path = &quot;/tmp&quot; &lt;/&gt; show (hash png) &lt;.&gt; &quot;png&quot; <span class="lineno"> 172 </span> -&gt; SVG
<span class="lineno"> 173 </span><span class="decl"><span class="istickedoff">embedPng w h png =</span> <span class="lineno"> 173 </span>-- embedPng w h png = unsafePerformIO $ do
<span class="lineno"> 174 </span><span class="spaces"> </span><span class="istickedoff">flipYAxis</span> <span class="lineno"> 174 </span>-- LBS.writeFile path png
<span class="lineno"> 175 </span><span class="spaces"> </span><span class="istickedoff">$ ImageTree</span> <span class="lineno"> 175 </span>-- return $ ImageTree $ defaultSvg
<span class="lineno"> 176 </span><span class="spaces"> </span><span class="istickedoff">$ defaultSvg</span> <span class="lineno"> 176 </span>-- &amp; Svg.imageCornerUpperLeft .~ (Svg.Num (-w/2), Svg.Num (-h/2))
<span class="lineno"> 177 </span><span class="spaces"> </span><span class="istickedoff">&amp; Svg.imageCornerUpperLeft</span> <span class="lineno"> 177 </span>-- &amp; Svg.imageWidth .~ Svg.Num w
<span class="lineno"> 178 </span><span class="spaces"> </span><span class="istickedoff">.~ (Svg.Num (-w / 2), Svg.Num (-h / 2))</span> <span class="lineno"> 178 </span>-- &amp; Svg.imageHeight .~ Svg.Num h
<span class="lineno"> 179 </span><span class="spaces"> </span><span class="istickedoff">&amp; Svg.imageWidth</span> <span class="lineno"> 179 </span>-- &amp; Svg.imageHref .~ (&quot;file://&quot;++path)
<span class="lineno"> 180 </span><span class="spaces"> </span><span class="istickedoff">.~ Svg.Num w</span> <span class="lineno"> 180 </span>-- where
<span class="lineno"> 181 </span><span class="spaces"> </span><span class="istickedoff">&amp; Svg.imageHeight</span> <span class="lineno"> 181 </span>-- path = &quot;/tmp&quot; &lt;/&gt; show (hash png) &lt;.&gt; &quot;png&quot;
<span class="lineno"> 182 </span><span class="spaces"> </span><span class="istickedoff">.~ Svg.Num h</span> <span class="lineno"> 182 </span><span class="decl"><span class="istickedoff">embedPng w h png =</span>
<span class="lineno"> 183 </span><span class="spaces"> </span><span class="istickedoff">&amp; Svg.imageHref</span> <span class="lineno"> 183 </span><span class="spaces"> </span><span class="istickedoff">flipYAxis</span>
<span class="lineno"> 184 </span><span class="spaces"> </span><span class="istickedoff">.~ (&quot;data:image/png;base64,&quot; ++ imgData)</span> <span class="lineno"> 184 </span><span class="spaces"> </span><span class="istickedoff">$ ImageTree</span>
<span class="lineno"> 185 </span><span class="spaces"> </span><span class="istickedoff">where imgData = LBS.unpack $ Base64.encode png</span></span> <span class="lineno"> 185 </span><span class="spaces"> </span><span class="istickedoff">$ defaultSvg</span>
<span class="lineno"> 186 </span> <span class="lineno"> 186 </span><span class="spaces"> </span><span class="istickedoff">&amp; Svg.imageCornerUpperLeft</span>
<span class="lineno"> 187 </span> <span class="lineno"> 187 </span><span class="spaces"> </span><span class="istickedoff">.~ (Svg.Num (-w / 2), Svg.Num (-h / 2))</span>
<span class="lineno"> 188 </span>{-# INLINE embedDynamicImage #-} <span class="lineno"> 188 </span><span class="spaces"> </span><span class="istickedoff">&amp; Svg.imageWidth</span>
<span class="lineno"> 189 </span>-- | Embed an in-memory image. Note, the pixel size of the image <span class="lineno"> 189 </span><span class="spaces"> </span><span class="istickedoff">.~ Svg.Num w</span>
<span class="lineno"> 190 </span>-- is used as the dimensions. As such, embedding a 100x100 image will <span class="lineno"> 190 </span><span class="spaces"> </span><span class="istickedoff">&amp; Svg.imageHeight</span>
<span class="lineno"> 191 </span>-- result in an image 100 units wide and 100 units high. Consider <span class="lineno"> 191 </span><span class="spaces"> </span><span class="istickedoff">.~ Svg.Num h</span>
<span class="lineno"> 192 </span>-- using with 'scaleToSize'. <span class="lineno"> 192 </span><span class="spaces"> </span><span class="istickedoff">&amp; Svg.imageHref</span>
<span class="lineno"> 193 </span>embedDynamicImage :: DynamicImage -&gt; SVG <span class="lineno"> 193 </span><span class="spaces"> </span><span class="istickedoff">.~ (&quot;data:image/png;base64,&quot; ++ imgData)</span>
<span class="lineno"> 194 </span><span class="decl"><span class="nottickedoff">embedDynamicImage img = embedPng width height imgData</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"> 195 </span><span class="spaces"> </span><span class="nottickedoff">where</span> <span class="lineno"> 195 </span>
<span class="lineno"> 196 </span><span class="spaces"> </span><span class="nottickedoff">width = fromIntegral $ dynamicMap imageWidth img</span> <span class="lineno"> 196 </span>
<span class="lineno"> 197 </span><span class="spaces"> </span><span class="nottickedoff">height = fromIntegral $ dynamicMap imageHeight img</span> <span class="lineno"> 197 </span>{-# INLINE embedDynamicImage #-}
<span class="lineno"> 198 </span><span class="spaces"> </span><span class="nottickedoff">imgData = case encodeDynamicPng img of</span> <span class="lineno"> 198 </span>-- | Embed an in-memory image. Note, the pixel size of the image
<span class="lineno"> 199 </span><span class="spaces"> </span><span class="nottickedoff">Left err -&gt; error err</span> <span class="lineno"> 199 </span>-- is used as the dimensions. As such, embedding a 100x100 image will
<span class="lineno"> 200 </span><span class="spaces"> </span><span class="nottickedoff">Right dat -&gt; dat</span></span> <span class="lineno"> 200 </span>-- result in an image 100 units wide and 100 units high. Consider
<span class="lineno"> 201 </span> <span class="lineno"> 201 </span>-- using with 'scaleToSize'.
<span class="lineno"> 202 </span>-- embedImageFile :: FilePath -&gt; Tree <span class="lineno"> 202 </span>embedDynamicImage :: DynamicImage -&gt; SVG
<span class="lineno"> 203 </span>-- embedImageFile path = unsafePerformIO $ do <span class="lineno"> 203 </span><span class="decl"><span class="nottickedoff">embedDynamicImage img = embedPng width height imgData</span>
<span class="lineno"> 204 </span>-- png &lt;- B.readFile path <span class="lineno"> 204 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 205 </span>-- case decodePng png of <span class="lineno"> 205 </span><span class="spaces"> </span><span class="nottickedoff">width = fromIntegral $ dynamicMap imageWidth img</span>
<span class="lineno"> 206 </span>-- Left{} -&gt; error &quot;bad image&quot; <span class="lineno"> 206 </span><span class="spaces"> </span><span class="nottickedoff">height = fromIntegral $ dynamicMap imageHeight img</span>
<span class="lineno"> 207 </span>-- Right img -&gt; return $ <span class="lineno"> 207 </span><span class="spaces"> </span><span class="nottickedoff">imgData = case encodeDynamicPng img of</span>
<span class="lineno"> 208 </span>-- let width = fromIntegral $ dynamicMap imageWidth img <span class="lineno"> 208 </span><span class="spaces"> </span><span class="nottickedoff">Left err -&gt; error err</span>
<span class="lineno"> 209 </span>-- height = fromIntegral $ dynamicMap imageHeight img in <span class="lineno"> 209 </span><span class="spaces"> </span><span class="nottickedoff">Right dat -&gt; dat</span></span>
<span class="lineno"> 210 </span>-- ImageTree $ defaultSvg <span class="lineno"> 210 </span>
<span class="lineno"> 211 </span>-- &amp; Svg.imageCornerUpperLeft .~ (Svg.Num (-width/2), Svg.Num (-height/2)) <span class="lineno"> 211 </span>-- embedImageFile :: FilePath -&gt; Tree
<span class="lineno"> 212 </span>-- &amp; Svg.imageWidth .~ Svg.Num width <span class="lineno"> 212 </span>-- embedImageFile path = unsafePerformIO $ do
<span class="lineno"> 213 </span>-- &amp; Svg.imageHeight .~ Svg.Num height <span class="lineno"> 213 </span>-- png &lt;- B.readFile path
<span class="lineno"> 214 </span>-- &amp; Svg.imageHref .~ (&quot;file://&quot; ++ path) <span class="lineno"> 214 </span>-- case decodePng png of
<span class="lineno"> 215 </span> <span class="lineno"> 215 </span>-- Left{} -&gt; error &quot;bad image&quot;
<span class="lineno"> 216 </span> <span class="lineno"> 216 </span>-- Right img -&gt; return $
<span class="lineno"> 217 </span>-- | Convert an SVG object to a pixel-based image. The default resolution <span class="lineno"> 217 </span>-- let width = fromIntegral $ dynamicMap imageWidth img
<span class="lineno"> 218 </span>-- is 2560x1440. See also 'rasterSized'. Multiple raster engines are supported <span class="lineno"> 218 </span>-- height = fromIntegral $ dynamicMap imageHeight img in
<span class="lineno"> 219 </span>-- and are selected using the '--raster' flag in the driver. <span class="lineno"> 219 </span>-- ImageTree $ defaultSvg
<span class="lineno"> 220 </span>raster :: SVG -&gt; DynamicImage <span class="lineno"> 220 </span>-- &amp; Svg.imageCornerUpperLeft .~ (Svg.Num (-width/2), Svg.Num (-height/2))
<span class="lineno"> 221 </span><span class="decl"><span class="nottickedoff">raster = rasterSized 2560 1440</span></span> <span class="lineno"> 221 </span>-- &amp; Svg.imageWidth .~ Svg.Num width
<span class="lineno"> 222 </span> <span class="lineno"> 222 </span>-- &amp; Svg.imageHeight .~ Svg.Num height
<span class="lineno"> 223 </span>-- | Convert an SVG object to a pixel-based image. <span class="lineno"> 223 </span>-- &amp; Svg.imageHref .~ (&quot;file://&quot; ++ path)
<span class="lineno"> 224 </span>rasterSized <span class="lineno"> 224 </span>
<span class="lineno"> 225 </span> :: Width -- ^ X resolution in pixels <span class="lineno"> 225 </span>
<span class="lineno"> 226 </span> -&gt; Height -- ^ Y resolution in pixels <span class="lineno"> 226 </span>-- | Convert an SVG object to a pixel-based image. The default resolution
<span class="lineno"> 227 </span> -&gt; SVG -- ^ SVG object <span class="lineno"> 227 </span>-- is 2560x1440. See also 'rasterSized'. Multiple raster engines are supported
<span class="lineno"> 228 </span> -&gt; DynamicImage <span class="lineno"> 228 </span>-- and are selected using the '--raster' flag in the driver.
<span class="lineno"> 229 </span><span class="decl"><span class="nottickedoff">rasterSized w h svg = unsafePerformIO $ do</span> <span class="lineno"> 229 </span>raster :: SVG -&gt; DynamicImage
<span class="lineno"> 230 </span><span class="spaces"> </span><span class="nottickedoff">png &lt;- B.readFile (svgAsPngFile' w h svg)</span> <span class="lineno"> 230 </span><span class="decl"><span class="nottickedoff">raster = rasterSized 2560 1440</span></span>
<span class="lineno"> 231 </span><span class="spaces"> </span><span class="nottickedoff">case decodePng png of</span> <span class="lineno"> 231 </span>
<span class="lineno"> 232 </span><span class="spaces"> </span><span class="nottickedoff">Left{} -&gt; error &quot;bad image&quot;</span> <span class="lineno"> 232 </span>-- | Convert an SVG object to a pixel-based image.
<span class="lineno"> 233 </span><span class="spaces"> </span><span class="nottickedoff">Right img -&gt; return img</span></span> <span class="lineno"> 233 </span>rasterSized
<span class="lineno"> 234 </span> <span class="lineno"> 234 </span> :: Width -- ^ X resolution in pixels
<span class="lineno"> 235 </span>-- | Use 'potrace' to trace edges in a raster image and convert them to SVG polygons. <span class="lineno"> 235 </span> -&gt; Height -- ^ Y resolution in pixels
<span class="lineno"> 236 </span>vectorize :: FilePath -&gt; SVG <span class="lineno"> 236 </span> -&gt; SVG -- ^ SVG object
<span class="lineno"> 237 </span><span class="decl"><span class="nottickedoff">vectorize = vectorize_ []</span></span> <span class="lineno"> 237 </span> -&gt; DynamicImage
<span class="lineno"> 238 </span> <span class="lineno"> 238 </span><span class="decl"><span class="nottickedoff">rasterSized w h svg = unsafePerformIO $ do</span>
<span class="lineno"> 239 </span>-- | Same as 'vectorize' but takes a list of arguments for 'potrace'. <span class="lineno"> 239 </span><span class="spaces"> </span><span class="nottickedoff">png &lt;- B.readFile (svgAsPngFile' w h svg)</span>
<span class="lineno"> 240 </span>vectorize_ :: [String] -&gt; FilePath -&gt; SVG <span class="lineno"> 240 </span><span class="spaces"> </span><span class="nottickedoff">case decodePng png of</span>
<span class="lineno"> 241 </span><span class="decl"><span class="nottickedoff">vectorize_ _ path | pNoExternals = mkText $ T.pack path</span> <span class="lineno"> 241 </span><span class="spaces"> </span><span class="nottickedoff">Left{} -&gt; error &quot;bad image&quot;</span>
<span class="lineno"> 242 </span><span class="spaces"></span><span class="nottickedoff">vectorize_ args path = unsafePerformIO $ do</span> <span class="lineno"> 242 </span><span class="spaces"> </span><span class="nottickedoff">Right img -&gt; return img</span></span>
<span class="lineno"> 243 </span><span class="spaces"> </span><span class="nottickedoff">root &lt;- getXdgDirectory XdgCache &quot;reanimate&quot;</span> <span class="lineno"> 243 </span>
<span class="lineno"> 244 </span><span class="spaces"> </span><span class="nottickedoff">createDirectoryIfMissing True root</span> <span class="lineno"> 244 </span>-- | Use 'potrace' to trace edges in a raster image and convert them to SVG polygons.
<span class="lineno"> 245 </span><span class="spaces"> </span><span class="nottickedoff">let svgPath = root &lt;/&gt; encodeInt key &lt;.&gt; &quot;svg&quot;</span> <span class="lineno"> 245 </span>vectorize :: FilePath -&gt; SVG
<span class="lineno"> 246 </span><span class="spaces"> </span><span class="nottickedoff">hit &lt;- doesFileExist svgPath</span> <span class="lineno"> 246 </span><span class="decl"><span class="nottickedoff">vectorize = vectorize_ []</span></span>
<span class="lineno"> 247 </span><span class="spaces"> </span><span class="nottickedoff">unless hit $ withSystemTempFile &quot;file.svg&quot; $ \tmpSvgPath svgH -&gt;</span> <span class="lineno"> 247 </span>
<span class="lineno"> 248 </span><span class="spaces"> </span><span class="nottickedoff">withSystemTempFile &quot;file.bmp&quot; $ \tmpBmpPath bmpH -&gt; do</span> <span class="lineno"> 248 </span>-- | Same as 'vectorize' but takes a list of arguments for 'potrace'.
<span class="lineno"> 249 </span><span class="spaces"> </span><span class="nottickedoff">hClose svgH</span> <span class="lineno"> 249 </span>vectorize_ :: [String] -&gt; FilePath -&gt; SVG
<span class="lineno"> 250 </span><span class="spaces"> </span><span class="nottickedoff">hClose bmpH</span> <span class="lineno"> 250 </span><span class="decl"><span class="nottickedoff">vectorize_ _ path | pNoExternals = mkText $ T.pack path</span>
<span class="lineno"> 251 </span><span class="spaces"> </span><span class="nottickedoff">potrace &lt;- requireExecutable &quot;potrace&quot;</span> <span class="lineno"> 251 </span><span class="spaces"></span><span class="nottickedoff">vectorize_ args path = unsafePerformIO $ do</span>
<span class="lineno"> 252 </span><span class="spaces"> </span><span class="nottickedoff">magick &lt;- requireExecutable magickCmd</span> <span class="lineno"> 252 </span><span class="spaces"> </span><span class="nottickedoff">root &lt;- getXdgDirectory XdgCache &quot;reanimate&quot;</span>
<span class="lineno"> 253 </span><span class="spaces"> </span><span class="nottickedoff">runCmd magick [path, &quot;-flatten&quot;, tmpBmpPath]</span> <span class="lineno"> 253 </span><span class="spaces"> </span><span class="nottickedoff">createDirectoryIfMissing True root</span>
<span class="lineno"> 254 </span><span class="spaces"> </span><span class="nottickedoff">runCmd potrace (args ++ [&quot;--svg&quot;, &quot;--output&quot;, tmpSvgPath, tmpBmpPath])</span> <span class="lineno"> 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"> 255 </span><span class="spaces"> </span><span class="nottickedoff">renameOrCopyFile tmpSvgPath svgPath</span> <span class="lineno"> 255 </span><span class="spaces"> </span><span class="nottickedoff">hit &lt;- doesFileExist svgPath</span>
<span class="lineno"> 256 </span><span class="spaces"> </span><span class="nottickedoff">svg_data &lt;- B.readFile svgPath</span> <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"> 257 </span><span class="spaces"> </span><span class="nottickedoff">case parseSvgFile svgPath svg_data of</span> <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"> 258 </span><span class="spaces"> </span><span class="nottickedoff">Nothing -&gt; do</span> <span class="lineno"> 258 </span><span class="spaces"> </span><span class="nottickedoff">hClose svgH</span>
<span class="lineno"> 259 </span><span class="spaces"> </span><span class="nottickedoff">removeFile svgPath</span> <span class="lineno"> 259 </span><span class="spaces"> </span><span class="nottickedoff">hClose bmpH</span>
<span class="lineno"> 260 </span><span class="spaces"> </span><span class="nottickedoff">error &quot;Malformed svg&quot;</span> <span class="lineno"> 260 </span><span class="spaces"> </span><span class="nottickedoff">potrace &lt;- requireExecutable &quot;potrace&quot;</span>
<span class="lineno"> 261 </span><span class="spaces"> </span><span class="nottickedoff">Just svg -&gt; return $ unbox $ replaceUses svg</span> <span class="lineno"> 261 </span><span class="spaces"> </span><span class="nottickedoff">magick &lt;- requireExecutable magickCmd</span>
<span class="lineno"> 262 </span><span class="spaces"> </span><span class="nottickedoff">where key = hash (path, args)</span></span> <span class="lineno"> 262 </span><span class="spaces"> </span><span class="nottickedoff">runCmd magick [path, &quot;-flatten&quot;, tmpBmpPath]</span>
<span class="lineno"> 263 </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"> 264 </span>-- imageAsFile :: DynamicImage -&gt; FilePath <span class="lineno"> 264 </span><span class="spaces"> </span><span class="nottickedoff">renameOrCopyFile tmpSvgPath svgPath</span>
<span class="lineno"> 265 </span>-- imageAsFile img <span class="lineno"> 265 </span><span class="spaces"> </span><span class="nottickedoff">svg_data &lt;- B.readFile svgPath</span>
<span class="lineno"> 266 </span> <span class="lineno"> 266 </span><span class="spaces"> </span><span class="nottickedoff">case parseSvgFile svgPath svg_data of</span>
<span class="lineno"> 267 </span>-- | Convert an SVG object to a pixel-based image and save it to disk, returning <span class="lineno"> 267 </span><span class="spaces"> </span><span class="nottickedoff">Nothing -&gt; do</span>
<span class="lineno"> 268 </span>-- the filepath. The default resolution is 2560x1440. See also 'svgAsPngFile''. <span class="lineno"> 268 </span><span class="spaces"> </span><span class="nottickedoff">removeFile svgPath</span>
<span class="lineno"> 269 </span>-- Multiple raster engines are supported and are selected using the '--raster' <span class="lineno"> 269 </span><span class="spaces"> </span><span class="nottickedoff">error &quot;Malformed svg&quot;</span>
<span class="lineno"> 270 </span>-- flag in the driver. <span class="lineno"> 270 </span><span class="spaces"> </span><span class="nottickedoff">Just svg -&gt; return $ unbox $ replaceUses svg</span>
<span class="lineno"> 271 </span>svgAsPngFile :: SVG -&gt; FilePath <span class="lineno"> 271 </span><span class="spaces"> </span><span class="nottickedoff">where key = hash (path, args)</span></span>
<span class="lineno"> 272 </span><span class="decl"><span class="nottickedoff">svgAsPngFile = svgAsPngFile' width height</span> <span class="lineno"> 272 </span>
<span class="lineno"> 273 </span><span class="spaces"> </span><span class="nottickedoff">where</span> <span class="lineno"> 273 </span>-- imageAsFile :: DynamicImage -&gt; FilePath
<span class="lineno"> 274 </span><span class="spaces"> </span><span class="nottickedoff">width = 2560</span> <span class="lineno"> 274 </span>-- imageAsFile img
<span class="lineno"> 275 </span><span class="spaces"> </span><span class="nottickedoff">height = width * 9 `div` 16</span></span> <span class="lineno"> 275 </span>
<span class="lineno"> 276 </span> <span class="lineno"> 276 </span>-- | Convert an SVG object to a pixel-based image and save it to disk, returning
<span class="lineno"> 277 </span>-- | Convert an SVG object to a pixel-based image and save it to disk, returning <span class="lineno"> 277 </span>-- the filepath. The default resolution is 2560x1440. See also 'svgAsPngFile''.
<span class="lineno"> 278 </span>-- the filepath. <span class="lineno"> 278 </span>-- Multiple raster engines are supported and are selected using the '--raster'
<span class="lineno"> 279 </span>svgAsPngFile' <span class="lineno"> 279 </span>-- flag in the driver.
<span class="lineno"> 280 </span> :: Width -- ^ Width <span class="lineno"> 280 </span>svgAsPngFile :: SVG -&gt; FilePath
<span class="lineno"> 281 </span> -&gt; Height -- ^ Height <span class="lineno"> 281 </span><span class="decl"><span class="nottickedoff">svgAsPngFile = svgAsPngFile' width height</span>
<span class="lineno"> 282 </span> -&gt; SVG -- ^ SVG object <span class="lineno"> 282 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 283 </span> -&gt; FilePath <span class="lineno"> 283 </span><span class="spaces"> </span><span class="nottickedoff">width = 2560</span>
<span class="lineno"> 284 </span><span class="decl"><span class="nottickedoff">svgAsPngFile' _ _ _ | pNoExternals = &quot;/svgAsPngFile/has/been/disabled&quot;</span> <span class="lineno"> 284 </span><span class="spaces"> </span><span class="nottickedoff">height = width * 9 `div` 16</span></span>
<span class="lineno"> 285 </span><span class="spaces"></span><span class="nottickedoff">svgAsPngFile' width height svg =</span> <span class="lineno"> 285 </span>
<span class="lineno"> 286 </span><span class="spaces"> </span><span class="nottickedoff">unsafePerformIO $ cacheFile template $ \pngPath -&gt; do</span> <span class="lineno"> 286 </span>-- | Convert an SVG object to a pixel-based image and save it to disk, returning
<span class="lineno"> 287 </span><span class="spaces"> </span><span class="nottickedoff">let svgPath = replaceExtension pngPath &quot;svg&quot;</span> <span class="lineno"> 287 </span>-- the filepath.
<span class="lineno"> 288 </span><span class="spaces"> </span><span class="nottickedoff">writeFile svgPath rendered</span> <span class="lineno"> 288 </span>svgAsPngFile'
<span class="lineno"> 289 </span><span class="spaces"> </span><span class="nottickedoff">engine &lt;- requireRaster pRaster</span> <span class="lineno"> 289 </span> :: Width -- ^ Width
<span class="lineno"> 290 </span><span class="spaces"> </span><span class="nottickedoff">applyRaster engine svgPath</span> <span class="lineno"> 290 </span> -&gt; Height -- ^ Height
<span class="lineno"> 291 </span><span class="spaces"> </span><span class="nottickedoff">where</span> <span class="lineno"> 291 </span> -&gt; SVG -- ^ SVG object
<span class="lineno"> 292 </span><span class="spaces"> </span><span class="nottickedoff">template = encodeInt (hash rendered) &lt;.&gt; &quot;png&quot;</span> <span class="lineno"> 292 </span> -&gt; FilePath
<span class="lineno"> 293 </span><span class="spaces"> </span><span class="nottickedoff">rendered = renderSvg (Just $ Px $ fromIntegral width)</span> <span class="lineno"> 293 </span><span class="decl"><span class="nottickedoff">svgAsPngFile' _ _ _ | pNoExternals = &quot;/svgAsPngFile/has/been/disabled&quot;</span>
<span class="lineno"> 294 </span><span class="spaces"> </span><span class="nottickedoff">(Just $ Px $ fromIntegral height)</span> <span class="lineno"> 294 </span><span class="spaces"></span><span class="nottickedoff">svgAsPngFile' width height svg =</span>
<span class="lineno"> 295 </span><span class="spaces"> </span><span class="nottickedoff">svg</span></span> <span class="lineno"> 295 </span><span class="spaces"> </span><span class="nottickedoff">unsafePerformIO $ cacheFile template $ \pngPath -&gt; do</span>
<span class="lineno"> 296 </span><span class="spaces"> </span><span class="nottickedoff">let svgPath = replaceExtension pngPath &quot;svg&quot;</span>
<span class="lineno"> 297 </span><span class="spaces"> </span><span class="nottickedoff">writeFile svgPath rendered</span>
<span class="lineno"> 298 </span><span class="spaces"> </span><span class="nottickedoff">engine &lt;- requireRaster pRaster</span>
<span class="lineno"> 299 </span><span class="spaces"> </span><span class="nottickedoff">applyRaster engine svgPath</span>
<span class="lineno"> 300 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<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"> 302 </span><span class="spaces"> </span><span class="nottickedoff">rendered = renderSvg (Just $ Px $ fromIntegral width)</span>
<span class="lineno"> 303 </span><span class="spaces"> </span><span class="nottickedoff">(Just $ Px $ fromIntegral height)</span>
<span class="lineno"> 304 </span><span class="spaces"> </span><span class="nottickedoff">svg</span></span>
</pre> </pre>
</body> </body>

File diff suppressed because it is too large Load diff

View file

@ -17,119 +17,135 @@ 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.Svg.BoundingBox where <span class="lineno"> 1 </span>{-|
<span class="lineno"> 2 </span> <span class="lineno"> 2 </span> Bounding-boxes can be immensely useful for aligning objects
<span class="lineno"> 3 </span>import Control.Arrow ((***)) <span class="lineno"> 3 </span> but they are not part of the SVG specification and cannot be
<span class="lineno"> 4 </span>import Control.Lens ((^.)) <span class="lineno"> 4 </span> computed for all SVG nodes. In particular, you'll get bad results
<span class="lineno"> 5 </span>import Data.List <span class="lineno"> 5 </span> when asking for the bounding boxes of Text nodes (because fonts
<span class="lineno"> 6 </span>import Data.Maybe (mapMaybe) <span class="lineno"> 6 </span> are difficult), clipped nodes, and filtered nodes.
<span class="lineno"> 7 </span>import Graphics.SvgTree hiding (height, line, path, use, <span class="lineno"> 7 </span>-}
<span class="lineno"> 8 </span> width) <span class="lineno"> 8 </span>module Reanimate.Svg.BoundingBox
<span class="lineno"> 9 </span>import Linear.V2 hiding (angle) <span class="lineno"> 9 </span> ( boundingBox
<span class="lineno"> 10 </span>import Linear.Vector <span class="lineno"> 10 </span> , svgHeight
<span class="lineno"> 11 </span>import Reanimate.Constants <span class="lineno"> 11 </span> , svgWidth
<span class="lineno"> 12 </span>import Reanimate.Svg.LineCommand <span class="lineno"> 12 </span> ) where
<span class="lineno"> 13 </span>import qualified Reanimate.Transform as Transform <span class="lineno"> 13 </span>
<span class="lineno"> 14 </span>-- import qualified Geom2D.CubicBezier as Bezier <span class="lineno"> 14 </span>import Control.Arrow ((***))
<span class="lineno"> 15 </span> <span class="lineno"> 15 </span>import Control.Lens ((^.))
<span class="lineno"> 16 </span>-- | Return bounding box of SVG tree. <span class="lineno"> 16 </span>import Data.List
<span class="lineno"> 17 </span>-- The four numbers returned are (minimal X-coordinate, minimal Y-coordinate, width, height) <span class="lineno"> 17 </span>import Data.Maybe (mapMaybe)
<span class="lineno"> 18 </span>-- <span class="lineno"> 18 </span>import Graphics.SvgTree hiding (height, line, path, use,
<span class="lineno"> 19 </span>-- Note: Bounding boxes are computed on a best-effort basis and will not work <span class="lineno"> 19 </span> width)
<span class="lineno"> 20 </span>-- in all cases. The only supported SVG nodes are: path, circle, polyline, <span class="lineno"> 20 </span>import Linear.V2 hiding (angle)
<span class="lineno"> 21 </span>-- ellipse, line, rectangle, image. All other nodes return (0,0,0,0). <span class="lineno"> 21 </span>import Linear.Vector
<span class="lineno"> 22 </span>boundingBox :: Tree -&gt; (Double, Double, Double, Double) <span class="lineno"> 22 </span>import Reanimate.Constants
<span class="lineno"> 23 </span><span class="decl"><span class="istickedoff">boundingBox t =</span> <span class="lineno"> 23 </span>import Reanimate.Svg.LineCommand
<span class="lineno"> 24 </span><span class="spaces"> </span><span class="istickedoff">case svgBoundingPoints t of</span> <span class="lineno"> 24 </span>import qualified Reanimate.Transform as Transform
<span class="lineno"> 25 </span><span class="spaces"> </span><span class="istickedoff">[] -&gt; (0,0,0,0)</span> <span class="lineno"> 25 </span>-- import qualified Geom2D.CubicBezier as Bezier
<span class="lineno"> 26 </span><span class="spaces"> </span><span class="istickedoff">(V2 x y:rest) -&gt;</span> <span class="lineno"> 26 </span>
<span class="lineno"> 27 </span><span class="spaces"> </span><span class="istickedoff">let (minx, miny, maxx, maxy) = foldl' worker (x, y, x, y) rest</span> <span class="lineno"> 27 </span>-- | Return bounding box of SVG tree.
<span class="lineno"> 28 </span><span class="spaces"> </span><span class="istickedoff">in (minx, miny, maxx-minx, maxy-miny)</span> <span class="lineno"> 28 </span>-- The four numbers returned are (minimal X-coordinate, minimal Y-coordinate, width, height)
<span class="lineno"> 29 </span><span class="spaces"> </span><span class="istickedoff">where</span> <span class="lineno"> 29 </span>--
<span class="lineno"> 30 </span><span class="spaces"> </span><span class="istickedoff">worker (minx, miny, maxx, maxy) (V2 x y) =</span> <span class="lineno"> 30 </span>-- Note: Bounding boxes are computed on a best-effort basis and will not work
<span class="lineno"> 31 </span><span class="spaces"> </span><span class="istickedoff">(min minx x, min miny y, max maxx x, max maxy y)</span></span> <span class="lineno"> 31 </span>-- in all cases. The only supported SVG nodes are: path, circle, polyline,
<span class="lineno"> 32 </span> <span class="lineno"> 32 </span>-- ellipse, line, rectangle, image. All other nodes return (0,0,0,0).
<span class="lineno"> 33 </span>svgHeight :: Tree -&gt; Double <span class="lineno"> 33 </span>boundingBox :: Tree -&gt; (Double, Double, Double, Double)
<span class="lineno"> 34 </span><span class="decl"><span class="nottickedoff">svgHeight t = h</span> <span class="lineno"> 34 </span><span class="decl"><span class="istickedoff">boundingBox t =</span>
<span class="lineno"> 35 </span><span class="spaces"> </span><span class="nottickedoff">where</span> <span class="lineno"> 35 </span><span class="spaces"> </span><span class="istickedoff">case svgBoundingPoints t of</span>
<span class="lineno"> 36 </span><span class="spaces"> </span><span class="nottickedoff">(_x, _y, _w, h) = boundingBox t</span></span> <span class="lineno"> 36 </span><span class="spaces"> </span><span class="istickedoff">[] -&gt; (0,0,0,0)</span>
<span class="lineno"> 37 </span> <span class="lineno"> 37 </span><span class="spaces"> </span><span class="istickedoff">(V2 x y:rest) -&gt;</span>
<span class="lineno"> 38 </span>svgWidth :: Tree -&gt; Double <span class="lineno"> 38 </span><span class="spaces"> </span><span class="istickedoff">let (minx, miny, maxx, maxy) = foldl' worker (x, y, x, y) rest</span>
<span class="lineno"> 39 </span><span class="decl"><span class="nottickedoff">svgWidth t = w</span> <span class="lineno"> 39 </span><span class="spaces"> </span><span class="istickedoff">in (minx, miny, maxx-minx, maxy-miny)</span>
<span class="lineno"> 40 </span><span class="spaces"> </span><span class="nottickedoff">where</span> <span class="lineno"> 40 </span><span class="spaces"> </span><span class="istickedoff">where</span>
<span class="lineno"> 41 </span><span class="spaces"> </span><span class="nottickedoff">(_x, _y, w, _h) = boundingBox t</span></span> <span class="lineno"> 41 </span><span class="spaces"> </span><span class="istickedoff">worker (minx, miny, maxx, maxy) (V2 x y) =</span>
<span class="lineno"> 42 </span> <span class="lineno"> 42 </span><span class="spaces"> </span><span class="istickedoff">(min minx x, min miny y, max maxx x, max maxy y)</span></span>
<span class="lineno"> 43 </span>linePoints :: [LineCommand] -&gt; [RPoint] <span class="lineno"> 43 </span>
<span class="lineno"> 44 </span><span class="decl"><span class="nottickedoff">linePoints = worker zero</span> <span class="lineno"> 44 </span>-- | Height of SVG node in local units (not pixels). Computed on best-effort basis
<span class="lineno"> 45 </span><span class="spaces"> </span><span class="nottickedoff">where</span> <span class="lineno"> 45 </span>-- and will not give accurate results for all SVG nodes.
<span class="lineno"> 46 </span><span class="spaces"> </span><span class="nottickedoff">worker _from [] = []</span> <span class="lineno"> 46 </span>svgHeight :: Tree -&gt; Double
<span class="lineno"> 47 </span><span class="spaces"> </span><span class="nottickedoff">worker from (x:xs) =</span> <span class="lineno"> 47 </span><span class="decl"><span class="nottickedoff">svgHeight t = h</span>
<span class="lineno"> 48 </span><span class="spaces"> </span><span class="nottickedoff">case x of</span> <span class="lineno"> 48 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 49 </span><span class="spaces"> </span><span class="nottickedoff">LineMove to -&gt; worker to xs</span> <span class="lineno"> 49 </span><span class="spaces"> </span><span class="nottickedoff">(_x, _y, _w, h) = boundingBox t</span></span>
<span class="lineno"> 50 </span><span class="spaces"> </span><span class="nottickedoff">-- LineDraw to -&gt; from:to:worker to xs</span> <span class="lineno"> 50 </span>
<span class="lineno"> 51 </span><span class="spaces"> </span><span class="nottickedoff">LineBezier [p] -&gt;</span> <span class="lineno"> 51 </span>-- | Width of SVG node in local units (not pixels). Computed on best-effort basis
<span class="lineno"> 52 </span><span class="spaces"> </span><span class="nottickedoff">p : worker p xs</span> <span class="lineno"> 52 </span>-- and will not give accurate results for all SVG nodes.
<span class="lineno"> 53 </span><span class="spaces"> </span><span class="nottickedoff">LineBezier ctrl -&gt; -- approximation</span> <span class="lineno"> 53 </span>svgWidth :: Tree -&gt; Double
<span class="lineno"> 54 </span><span class="spaces"> </span><span class="nottickedoff">[ last (partialBezierPoints (from:ctrl) 0 (recip chunks*i)) | i &lt;- [0..chunks]] ++</span> <span class="lineno"> 54 </span><span class="decl"><span class="nottickedoff">svgWidth t = w</span>
<span class="lineno"> 55 </span><span class="spaces"> </span><span class="nottickedoff">worker (last ctrl) xs</span> <span class="lineno"> 55 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 56 </span><span class="spaces"> </span><span class="nottickedoff">LineEnd p -&gt; p : worker p xs</span> <span class="lineno"> 56 </span><span class="spaces"> </span><span class="nottickedoff">(_x, _y, w, _h) = boundingBox t</span></span>
<span class="lineno"> 57 </span><span class="spaces"> </span><span class="nottickedoff">chunks = 10</span></span> <span class="lineno"> 57 </span>
<span class="lineno"> 58 </span> <span class="lineno"> 58 </span>-- | Sampling of points in a line path.
<span class="lineno"> 59 </span>svgBoundingPoints :: Tree -&gt; [RPoint] <span class="lineno"> 59 </span>linePoints :: [LineCommand] -&gt; [RPoint]
<span class="lineno"> 60 </span><span class="decl"><span class="istickedoff">svgBoundingPoints t = map (Transform.transformPoint m) $</span> <span class="lineno"> 60 </span><span class="decl"><span class="nottickedoff">linePoints = worker zero</span>
<span class="lineno"> 61 </span><span class="spaces"> </span><span class="istickedoff">case t of</span> <span class="lineno"> 61 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 62 </span><span class="spaces"> </span><span class="istickedoff">None -&gt; <span class="nottickedoff">[]</span></span> <span class="lineno"> 62 </span><span class="spaces"> </span><span class="nottickedoff">worker _from [] = []</span>
<span class="lineno"> 63 </span><span class="spaces"> </span><span class="istickedoff">UseTree{} -&gt; <span class="nottickedoff">[]</span></span> <span class="lineno"> 63 </span><span class="spaces"> </span><span class="nottickedoff">worker from (x:xs) =</span>
<span class="lineno"> 64 </span><span class="spaces"> </span><span class="istickedoff">GroupTree g -&gt; concatMap svgBoundingPoints (g^.groupChildren)</span> <span class="lineno"> 64 </span><span class="spaces"> </span><span class="nottickedoff">case x of</span>
<span class="lineno"> 65 </span><span class="spaces"> </span><span class="istickedoff">SymbolTree (Symbol g) -&gt; <span class="nottickedoff">concatMap svgBoundingPoints (g^.groupChildren)</span></span> <span class="lineno"> 65 </span><span class="spaces"> </span><span class="nottickedoff">LineMove to -&gt; worker to xs</span>
<span class="lineno"> 66 </span><span class="spaces"> </span><span class="istickedoff">FilterTree{} -&gt; <span class="nottickedoff">[]</span></span> <span class="lineno"> 66 </span><span class="spaces"> </span><span class="nottickedoff">-- LineDraw to -&gt; from:to:worker to xs</span>
<span class="lineno"> 67 </span><span class="spaces"> </span><span class="istickedoff">DefinitionTree{} -&gt; <span class="nottickedoff">[]</span></span> <span class="lineno"> 67 </span><span class="spaces"> </span><span class="nottickedoff">LineBezier [p] -&gt;</span>
<span class="lineno"> 68 </span><span class="spaces"> </span><span class="istickedoff">PathTree p -&gt; <span class="nottickedoff">linePoints $ toLineCommands (p^.pathDefinition)</span></span> <span class="lineno"> 68 </span><span class="spaces"> </span><span class="nottickedoff">p : worker p xs</span>
<span class="lineno"> 69 </span><span class="spaces"> </span><span class="istickedoff">CircleTree c -&gt; <span class="nottickedoff">circleBoundingPoints c</span></span> <span class="lineno"> 69 </span><span class="spaces"> </span><span class="nottickedoff">LineBezier ctrl -&gt; -- approximation</span>
<span class="lineno"> 70 </span><span class="spaces"> </span><span class="istickedoff">PolyLineTree pl -&gt; <span class="nottickedoff">pl ^. polyLinePoints</span></span> <span class="lineno"> 70 </span><span class="spaces"> </span><span class="nottickedoff">[ last (partialBezierPoints (from:ctrl) 0 (recip chunks*i)) | i &lt;- [0..chunks]] ++</span>
<span class="lineno"> 71 </span><span class="spaces"> </span><span class="istickedoff">EllipseTree e -&gt; <span class="nottickedoff">ellipseBoundingPoints e</span></span> <span class="lineno"> 71 </span><span class="spaces"> </span><span class="nottickedoff">worker (last ctrl) xs</span>
<span class="lineno"> 72 </span><span class="spaces"> </span><span class="istickedoff">LineTree line -&gt; <span class="nottickedoff">map pointToRPoint [line^.linePoint1, line^.linePoint2]</span></span> <span class="lineno"> 72 </span><span class="spaces"> </span><span class="nottickedoff">LineEnd p -&gt; p : worker p xs</span>
<span class="lineno"> 73 </span><span class="spaces"> </span><span class="istickedoff">RectangleTree rect -&gt;</span> <span class="lineno"> 73 </span><span class="spaces"> </span><span class="nottickedoff">chunks = 10</span></span>
<span class="lineno"> 74 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">case pointToRPoint (rect^.rectUpperLeftCorner) of</span></span> <span class="lineno"> 74 </span>
<span class="lineno"> 75 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">V2 x y -&gt; V2 x y :</span></span> <span class="lineno"> 75 </span>svgBoundingPoints :: Tree -&gt; [RPoint]
<span class="lineno"> 76 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">case mapTuple (fmap $ toUserUnit defaultDPI) (rect^.rectWidth, rect^.rectHeight) of</span></span> <span class="lineno"> 76 </span><span class="decl"><span class="istickedoff">svgBoundingPoints t = map (Transform.transformPoint m) $</span>
<span class="lineno"> 77 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">(Just (Num w), Just (Num h)) -&gt; [V2 (x+w) (y+h)]</span></span> <span class="lineno"> 77 </span><span class="spaces"> </span><span class="istickedoff">case t of</span>
<span class="lineno"> 78 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">_ -&gt; []</span></span> <span class="lineno"> 78 </span><span class="spaces"> </span><span class="istickedoff">None -&gt; <span class="nottickedoff">[]</span></span>
<span class="lineno"> 79 </span><span class="spaces"> </span><span class="istickedoff">TextTree{} -&gt; []</span> <span class="lineno"> 79 </span><span class="spaces"> </span><span class="istickedoff">UseTree{} -&gt; <span class="nottickedoff">[]</span></span>
<span class="lineno"> 80 </span><span class="spaces"> </span><span class="istickedoff">ImageTree img -&gt;</span> <span class="lineno"> 80 </span><span class="spaces"> </span><span class="istickedoff">GroupTree g -&gt; concatMap svgBoundingPoints (g^.groupChildren)</span>
<span class="lineno"> 81 </span><span class="spaces"> </span><span class="istickedoff">case (img^.imageCornerUpperLeft, img^.imageWidth, img^.imageHeight) of</span> <span class="lineno"> 81 </span><span class="spaces"> </span><span class="istickedoff">SymbolTree (Symbol g) -&gt; <span class="nottickedoff">concatMap svgBoundingPoints (g^.groupChildren)</span></span>
<span class="lineno"> 82 </span><span class="spaces"> </span><span class="istickedoff">((Num x, Num y), Num w, Num h) -&gt;</span> <span class="lineno"> 82 </span><span class="spaces"> </span><span class="istickedoff">FilterTree{} -&gt; <span class="nottickedoff">[]</span></span>
<span class="lineno"> 83 </span><span class="spaces"> </span><span class="istickedoff">[V2 x y, V2 (x+w) (y+h)]</span> <span class="lineno"> 83 </span><span class="spaces"> </span><span class="istickedoff">DefinitionTree{} -&gt; <span class="nottickedoff">[]</span></span>
<span class="lineno"> 84 </span><span class="spaces"> </span><span class="istickedoff">_ -&gt; <span class="nottickedoff">[]</span></span> <span class="lineno"> 84 </span><span class="spaces"> </span><span class="istickedoff">PathTree p -&gt; <span class="nottickedoff">linePoints $ toLineCommands (p^.pathDefinition)</span></span>
<span class="lineno"> 85 </span><span class="spaces"> </span><span class="istickedoff">MeshGradientTree{} -&gt; <span class="nottickedoff">[]</span></span> <span class="lineno"> 85 </span><span class="spaces"> </span><span class="istickedoff">CircleTree c -&gt; <span class="nottickedoff">circleBoundingPoints c</span></span>
<span class="lineno"> 86 </span><span class="spaces"> </span><span class="istickedoff">_ -&gt; <span class="nottickedoff">[]</span></span> <span class="lineno"> 86 </span><span class="spaces"> </span><span class="istickedoff">PolyLineTree pl -&gt; <span class="nottickedoff">pl ^. polyLinePoints</span></span>
<span class="lineno"> 87 </span><span class="spaces"> </span><span class="istickedoff">where</span> <span class="lineno"> 87 </span><span class="spaces"> </span><span class="istickedoff">EllipseTree e -&gt; <span class="nottickedoff">ellipseBoundingPoints e</span></span>
<span class="lineno"> 88 </span><span class="spaces"> </span><span class="istickedoff">m = Transform.mkMatrix (t^.transform)</span> <span class="lineno"> 88 </span><span class="spaces"> </span><span class="istickedoff">LineTree line -&gt; <span class="nottickedoff">map pointToRPoint [line^.linePoint1, line^.linePoint2]</span></span>
<span class="lineno"> 89 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">mapTuple f = f *** f</span></span> <span class="lineno"> 89 </span><span class="spaces"> </span><span class="istickedoff">RectangleTree rect -&gt;</span>
<span class="lineno"> 90 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">pointToRPoint p =</span></span> <span class="lineno"> 90 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">case pointToRPoint (rect^.rectUpperLeftCorner) of</span></span>
<span class="lineno"> 91 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">case mapTuple (toUserUnit defaultDPI) p of</span></span> <span class="lineno"> 91 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">V2 x y -&gt; V2 x y :</span></span>
<span class="lineno"> 92 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">(Num x, Num y) -&gt; V2 x y</span></span> <span class="lineno"> 92 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">case mapTuple (fmap $ toUserUnit defaultDPI) (rect^.rectWidth, rect^.rectHeight) of</span></span>
<span class="lineno"> 93 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">_ -&gt; error &quot;Reanimate.Svg.svgBoundingPoints: Unrecognized number format.&quot;</span></span> <span class="lineno"> 93 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">(Just (Num w), Just (Num h)) -&gt; [V2 (x+w) (y+h)]</span></span>
<span class="lineno"> 94 </span><span class="spaces"></span><span class="istickedoff"></span> <span class="lineno"> 94 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">_ -&gt; []</span></span>
<span class="lineno"> 95 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">circleBoundingPoints circ =</span></span> <span class="lineno"> 95 </span><span class="spaces"> </span><span class="istickedoff">TextTree{} -&gt; []</span>
<span class="lineno"> 96 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">let (xnum, ynum) = circ ^. circleCenter</span></span> <span class="lineno"> 96 </span><span class="spaces"> </span><span class="istickedoff">ImageTree img -&gt;</span>
<span class="lineno"> 97 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">rnum = circ ^. circleRadius</span></span> <span class="lineno"> 97 </span><span class="spaces"> </span><span class="istickedoff">case (img^.imageCornerUpperLeft, img^.imageWidth, img^.imageHeight) of</span>
<span class="lineno"> 98 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">in case mapMaybe unpackNumber [xnum, ynum, rnum] of</span></span> <span class="lineno"> 98 </span><span class="spaces"> </span><span class="istickedoff">((Num x, Num y), Num w, Num h) -&gt;</span>
<span class="lineno"> 99 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">[x, y, r] -&gt; [ V2 (x + r * cos angle) (y + r * sin angle) | angle &lt;- [0, pi/10 .. 2 * pi]]</span></span> <span class="lineno"> 99 </span><span class="spaces"> </span><span class="istickedoff">[V2 x y, V2 (x+w) (y+h)]</span>
<span class="lineno"> 100 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">_ -&gt; []</span></span> <span class="lineno"> 100 </span><span class="spaces"> </span><span class="istickedoff">_ -&gt; <span class="nottickedoff">[]</span></span>
<span class="lineno"> 101 </span><span class="spaces"></span><span class="istickedoff"></span> <span class="lineno"> 101 </span><span class="spaces"> </span><span class="istickedoff">MeshGradientTree{} -&gt; <span class="nottickedoff">[]</span></span>
<span class="lineno"> 102 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">ellipseBoundingPoints e =</span></span> <span class="lineno"> 102 </span><span class="spaces"> </span><span class="istickedoff">_ -&gt; <span class="nottickedoff">[]</span></span>
<span class="lineno"> 103 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">let (xnum,ynum) = e ^. ellipseCenter</span></span> <span class="lineno"> 103 </span><span class="spaces"> </span><span class="istickedoff">where</span>
<span class="lineno"> 104 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">xrnum = e ^. ellipseXRadius</span></span> <span class="lineno"> 104 </span><span class="spaces"> </span><span class="istickedoff">m = Transform.mkMatrix (t^.transform)</span>
<span class="lineno"> 105 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">yrnum = e ^. ellipseYRadius</span></span> <span class="lineno"> 105 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">mapTuple f = f *** f</span></span>
<span class="lineno"> 106 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">in case mapMaybe unpackNumber [xnum, ynum, xrnum, yrnum] of</span></span> <span class="lineno"> 106 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">pointToRPoint p =</span></span>
<span class="lineno"> 107 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">[x,y,xr,yr] -&gt; [V2 (x + xr * cos angle) (y + yr * sin angle) | angle &lt;- [0, pi/10 .. 2 * pi]]</span></span> <span class="lineno"> 107 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">case mapTuple (toUserUnit defaultDPI) p of</span></span>
<span class="lineno"> 108 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">_ -&gt; []</span></span> <span class="lineno"> 108 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">(Num x, Num y) -&gt; V2 x y</span></span>
<span class="lineno"> 109 </span><span class="spaces"></span><span class="istickedoff"></span> <span class="lineno"> 109 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">_ -&gt; error &quot;Reanimate.Svg.svgBoundingPoints: Unrecognized number format.&quot;</span></span>
<span class="lineno"> 110 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">unpackNumber n =</span></span> <span class="lineno"> 110 </span><span class="spaces"></span><span class="istickedoff"></span>
<span class="lineno"> 111 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">case toUserUnit defaultDPI n of</span></span> <span class="lineno"> 111 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">circleBoundingPoints circ =</span></span>
<span class="lineno"> 112 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">Num d -&gt; Just d</span></span> <span class="lineno"> 112 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">let (xnum, ynum) = circ ^. circleCenter</span></span>
<span class="lineno"> 113 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">_ -&gt; Nothing</span></span></span> <span class="lineno"> 113 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">rnum = circ ^. circleRadius</span></span>
<span class="lineno"> 114 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">in case mapMaybe unpackNumber [xnum, ynum, rnum] of</span></span>
<span class="lineno"> 115 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">[x, y, r] -&gt; [ V2 (x + r * cos angle) (y + r * sin angle) | angle &lt;- [0, pi/10 .. 2 * pi]]</span></span>
<span class="lineno"> 116 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">_ -&gt; []</span></span>
<span class="lineno"> 117 </span><span class="spaces"></span><span class="istickedoff"></span>
<span class="lineno"> 118 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">ellipseBoundingPoints e =</span></span>
<span class="lineno"> 119 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">let (xnum,ynum) = e ^. ellipseCenter</span></span>
<span class="lineno"> 120 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">xrnum = e ^. ellipseXRadius</span></span>
<span class="lineno"> 121 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">yrnum = e ^. ellipseYRadius</span></span>
<span class="lineno"> 122 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">in case mapMaybe unpackNumber [xnum, ynum, xrnum, yrnum] of</span></span>
<span class="lineno"> 123 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">[x,y,xr,yr] -&gt; [V2 (x + xr * cos angle) (y + yr * sin angle) | angle &lt;- [0, pi/10 .. 2 * pi]]</span></span>
<span class="lineno"> 124 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">_ -&gt; []</span></span>
<span class="lineno"> 125 </span><span class="spaces"></span><span class="istickedoff"></span>
<span class="lineno"> 126 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">unpackNumber n =</span></span>
<span class="lineno"> 127 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">case toUserUnit defaultDPI n of</span></span>
<span class="lineno"> 128 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">Num d -&gt; Just d</span></span>
<span class="lineno"> 129 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">_ -&gt; Nothing</span></span></span>
</pre> </pre>
</body> </body>

View file

@ -127,309 +127,317 @@ span.spaces { background: white }
<span class="lineno"> 108 </span><span class="spaces"> </span><span class="nottickedoff">offsetY = -y-h/2</span> <span class="lineno"> 108 </span><span class="spaces"> </span><span class="nottickedoff">offsetY = -y-h/2</span>
<span class="lineno"> 109 </span><span class="spaces"> </span><span class="nottickedoff">(x,y,w,h) = boundingBox t</span></span> <span class="lineno"> 109 </span><span class="spaces"> </span><span class="nottickedoff">(x,y,w,h) = boundingBox t</span></span>
<span class="lineno"> 110 </span> <span class="lineno"> 110 </span>
<span class="lineno"> 111 </span>aroundCenterY :: (Tree -&gt; Tree) -&gt; Tree -&gt; Tree <span class="lineno"> 111 </span>-- | Same as 'aroundCenter' but only for the Y-axis.
<span class="lineno"> 112 </span><span class="decl"><span class="nottickedoff">aroundCenterY fn t =</span> <span class="lineno"> 112 </span>aroundCenterY :: (Tree -&gt; Tree) -&gt; Tree -&gt; Tree
<span class="lineno"> 113 </span><span class="spaces"> </span><span class="nottickedoff">translate 0 (-offsetY) $ fn $ translate 0 offsetY t</span> <span class="lineno"> 113 </span><span class="decl"><span class="nottickedoff">aroundCenterY fn t =</span>
<span class="lineno"> 114 </span><span class="spaces"> </span><span class="nottickedoff">where</span> <span class="lineno"> 114 </span><span class="spaces"> </span><span class="nottickedoff">translate 0 (-offsetY) $ fn $ translate 0 offsetY t</span>
<span class="lineno"> 115 </span><span class="spaces"> </span><span class="nottickedoff">offsetY = -y-h/2</span> <span class="lineno"> 115 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 116 </span><span class="spaces"> </span><span class="nottickedoff">(_x,y,_w,h) = boundingBox t</span></span> <span class="lineno"> 116 </span><span class="spaces"> </span><span class="nottickedoff">offsetY = -y-h/2</span>
<span class="lineno"> 117 </span> <span class="lineno"> 117 </span><span class="spaces"> </span><span class="nottickedoff">(_x,y,_w,h) = boundingBox t</span></span>
<span class="lineno"> 118 </span>aroundCenterX :: (Tree -&gt; Tree) -&gt; Tree -&gt; Tree <span class="lineno"> 118 </span>
<span class="lineno"> 119 </span><span class="decl"><span class="nottickedoff">aroundCenterX fn t =</span> <span class="lineno"> 119 </span>-- | Same as 'aroundCenter' but only for the X-axis.
<span class="lineno"> 120 </span><span class="spaces"> </span><span class="nottickedoff">translate (-offsetX) 0 $ fn $ translate offsetX 0 t</span> <span class="lineno"> 120 </span>aroundCenterX :: (Tree -&gt; Tree) -&gt; Tree -&gt; Tree
<span class="lineno"> 121 </span><span class="spaces"> </span><span class="nottickedoff">where</span> <span class="lineno"> 121 </span><span class="decl"><span class="nottickedoff">aroundCenterX fn t =</span>
<span class="lineno"> 122 </span><span class="spaces"> </span><span class="nottickedoff">offsetX = -x-w/2</span> <span class="lineno"> 122 </span><span class="spaces"> </span><span class="nottickedoff">translate (-offsetX) 0 $ fn $ translate offsetX 0 t</span>
<span class="lineno"> 123 </span><span class="spaces"> </span><span class="nottickedoff">(x,_y,w,_h) = boundingBox t</span></span> <span class="lineno"> 123 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 124 </span> <span class="lineno"> 124 </span><span class="spaces"> </span><span class="nottickedoff">offsetX = -x-w/2</span>
<span class="lineno"> 125 </span>-- | Scale the image uniformly by given factor along both X and Y axes. <span class="lineno"> 125 </span><span class="spaces"> </span><span class="nottickedoff">(x,_y,w,_h) = boundingBox t</span></span>
<span class="lineno"> 126 </span>-- For example @scale 2 image@ makes the image twice as large, while @scale 0.5 image@ makes it <span class="lineno"> 126 </span>
<span class="lineno"> 127 </span>-- half the original size. Negative values are also allowed, and lead to flipping the image along <span class="lineno"> 127 </span>-- | Scale the image uniformly by given factor along both X and Y axes.
<span class="lineno"> 128 </span>-- both X and Y axes. <span class="lineno"> 128 </span>-- For example @scale 2 image@ makes the image twice as large, while @scale 0.5 image@ makes it
<span class="lineno"> 129 </span>scale :: Double -&gt; Tree -&gt; Tree <span class="lineno"> 129 </span>-- half the original size. Negative values are also allowed, and lead to flipping the image along
<span class="lineno"> 130 </span><span class="decl"><span class="istickedoff">scale a = withTransformations [Scale a Nothing]</span></span> <span class="lineno"> 130 </span>-- both X and Y axes.
<span class="lineno"> 131 </span> <span class="lineno"> 131 </span>scale :: Double -&gt; Tree -&gt; Tree
<span class="lineno"> 132 </span>-- | @scaleToSize width height@ resizes the image so that its bounding box has corresponding @width@ <span class="lineno"> 132 </span><span class="decl"><span class="istickedoff">scale a = withTransformations [Scale a Nothing]</span></span>
<span class="lineno"> 133 </span>-- and @height@. <span class="lineno"> 133 </span>
<span class="lineno"> 134 </span>scaleToSize :: Double -&gt; Double -&gt; Tree -&gt; Tree <span class="lineno"> 134 </span>-- | @scaleToSize width height@ resizes the image so that its bounding box has corresponding @width@
<span class="lineno"> 135 </span><span class="decl"><span class="istickedoff">scaleToSize w h t =</span> <span class="lineno"> 135 </span>-- and @height@.
<span class="lineno"> 136 </span><span class="spaces"> </span><span class="istickedoff">scaleXY (w/w') (h/h') t</span> <span class="lineno"> 136 </span>scaleToSize :: Double -&gt; Double -&gt; Tree -&gt; Tree
<span class="lineno"> 137 </span><span class="spaces"> </span><span class="istickedoff">where</span> <span class="lineno"> 137 </span><span class="decl"><span class="istickedoff">scaleToSize w h t =</span>
<span class="lineno"> 138 </span><span class="spaces"> </span><span class="istickedoff">(_x, _y, w', h') = boundingBox t</span></span> <span class="lineno"> 138 </span><span class="spaces"> </span><span class="istickedoff">scaleXY (w/w') (h/h') t</span>
<span class="lineno"> 139 </span> <span class="lineno"> 139 </span><span class="spaces"> </span><span class="istickedoff">where</span>
<span class="lineno"> 140 </span>-- | @scaleToWidth width@ scales the image so that the width of its bounding box ends up having <span class="lineno"> 140 </span><span class="spaces"> </span><span class="istickedoff">(_x, _y, w', h') = boundingBox t</span></span>
<span class="lineno"> 141 </span>-- given @width@. <span class="lineno"> 141 </span>
<span class="lineno"> 142 </span>scaleToWidth :: Double -&gt; Tree -&gt; Tree <span class="lineno"> 142 </span>-- | @scaleToWidth width@ scales the image so that the width of its bounding box ends up having
<span class="lineno"> 143 </span><span class="decl"><span class="istickedoff">scaleToWidth w t =</span> <span class="lineno"> 143 </span>-- given @width@.
<span class="lineno"> 144 </span><span class="spaces"> </span><span class="istickedoff">scale (w/w') t</span> <span class="lineno"> 144 </span>scaleToWidth :: Double -&gt; Tree -&gt; Tree
<span class="lineno"> 145 </span><span class="spaces"> </span><span class="istickedoff">where</span> <span class="lineno"> 145 </span><span class="decl"><span class="istickedoff">scaleToWidth w t =</span>
<span class="lineno"> 146 </span><span class="spaces"> </span><span class="istickedoff">(_x, _y, w', _h') = boundingBox t</span></span> <span class="lineno"> 146 </span><span class="spaces"> </span><span class="istickedoff">scale (w/w') t</span>
<span class="lineno"> 147 </span> <span class="lineno"> 147 </span><span class="spaces"> </span><span class="istickedoff">where</span>
<span class="lineno"> 148 </span>-- | @scaleToHeight height@ scales the image so that the height of its bounding box ends up having <span class="lineno"> 148 </span><span class="spaces"> </span><span class="istickedoff">(_x, _y, w', _h') = boundingBox t</span></span>
<span class="lineno"> 149 </span>-- given @height@. <span class="lineno"> 149 </span>
<span class="lineno"> 150 </span>scaleToHeight :: Double -&gt; Tree -&gt; Tree <span class="lineno"> 150 </span>-- | @scaleToHeight height@ scales the image so that the height of its bounding box ends up having
<span class="lineno"> 151 </span><span class="decl"><span class="nottickedoff">scaleToHeight h t =</span> <span class="lineno"> 151 </span>-- given @height@.
<span class="lineno"> 152 </span><span class="spaces"> </span><span class="nottickedoff">scale (h/h') t</span> <span class="lineno"> 152 </span>scaleToHeight :: Double -&gt; Tree -&gt; Tree
<span class="lineno"> 153 </span><span class="spaces"> </span><span class="nottickedoff">where</span> <span class="lineno"> 153 </span><span class="decl"><span class="nottickedoff">scaleToHeight h t =</span>
<span class="lineno"> 154 </span><span class="spaces"> </span><span class="nottickedoff">(_x, _y, _w', h') = boundingBox t</span></span> <span class="lineno"> 154 </span><span class="spaces"> </span><span class="nottickedoff">scale (h/h') t</span>
<span class="lineno"> 155 </span> <span class="lineno"> 155 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 156 </span>-- | Similar to 'scale', except scale factors for X and Y axes are specified separately. <span class="lineno"> 156 </span><span class="spaces"> </span><span class="nottickedoff">(_x, _y, _w', h') = boundingBox t</span></span>
<span class="lineno"> 157 </span>scaleXY :: Double -&gt; Double -&gt; Tree -&gt; Tree <span class="lineno"> 157 </span>
<span class="lineno"> 158 </span><span class="decl"><span class="istickedoff">scaleXY x y = withTransformations [Scale x (Just y)]</span></span> <span class="lineno"> 158 </span>-- | Similar to 'scale', except scale factors for X and Y axes are specified separately.
<span class="lineno"> 159 </span> <span class="lineno"> 159 </span>scaleXY :: Double -&gt; Double -&gt; Tree -&gt; Tree
<span class="lineno"> 160 </span> <span class="lineno"> 160 </span><span class="decl"><span class="istickedoff">scaleXY x y = withTransformations [Scale x (Just y)]</span></span>
<span class="lineno"> 161 </span>-- | Flip the image along vertical axis so that what was on the right will end up on left and vice <span class="lineno"> 161 </span>
<span class="lineno"> 162 </span>-- versa. <span class="lineno"> 162 </span>
<span class="lineno"> 163 </span>flipXAxis :: Tree -&gt; Tree <span class="lineno"> 163 </span>-- | Flip the image along vertical axis so that what was on the right will end up on left and vice
<span class="lineno"> 164 </span><span class="decl"><span class="istickedoff">flipXAxis = scaleXY (-1) 1</span></span> <span class="lineno"> 164 </span>-- versa.
<span class="lineno"> 165 </span> <span class="lineno"> 165 </span>flipXAxis :: Tree -&gt; Tree
<span class="lineno"> 166 </span>-- | Flip the image along horizontal so that what was on the top will end up in the bottom and vice <span class="lineno"> 166 </span><span class="decl"><span class="istickedoff">flipXAxis = scaleXY (-1) 1</span></span>
<span class="lineno"> 167 </span>-- versa. <span class="lineno"> 167 </span>
<span class="lineno"> 168 </span>flipYAxis :: Tree -&gt; Tree <span class="lineno"> 168 </span>-- | Flip the image along horizontal so that what was on the top will end up in the bottom and vice
<span class="lineno"> 169 </span><span class="decl"><span class="istickedoff">flipYAxis = scaleXY 1 (-1)</span></span> <span class="lineno"> 169 </span>-- versa.
<span class="lineno"> 170 </span> <span class="lineno"> 170 </span>flipYAxis :: Tree -&gt; Tree
<span class="lineno"> 171 </span>-- | Translate given image so that the center of its bouding box coincides with coordinates <span class="lineno"> 171 </span><span class="decl"><span class="istickedoff">flipYAxis = scaleXY 1 (-1)</span></span>
<span class="lineno"> 172 </span>-- @(0, 0)@. <span class="lineno"> 172 </span>
<span class="lineno"> 173 </span>center :: Tree -&gt; Tree <span class="lineno"> 173 </span>-- | Translate given image so that the center of its bouding box coincides with coordinates
<span class="lineno"> 174 </span><span class="decl"><span class="istickedoff">center t = centerUsing t t</span></span> <span class="lineno"> 174 </span>-- @(0, 0)@.
<span class="lineno"> 175 </span> <span class="lineno"> 175 </span>center :: Tree -&gt; Tree
<span class="lineno"> 176 </span>-- | Translate given image so that the X-coordinate of the center of its bouding box is 0. <span class="lineno"> 176 </span><span class="decl"><span class="istickedoff">center t = centerUsing t t</span></span>
<span class="lineno"> 177 </span>centerX :: Tree -&gt; Tree <span class="lineno"> 177 </span>
<span class="lineno"> 178 </span><span class="decl"><span class="nottickedoff">centerX t = translate (-x-w/2) 0 t</span> <span class="lineno"> 178 </span>-- | Translate given image so that the X-coordinate of the center of its bouding box is 0.
<span class="lineno"> 179 </span><span class="spaces"> </span><span class="nottickedoff">where</span> <span class="lineno"> 179 </span>centerX :: Tree -&gt; Tree
<span class="lineno"> 180 </span><span class="spaces"> </span><span class="nottickedoff">(x, _y, w, _h) = boundingBox t</span></span> <span class="lineno"> 180 </span><span class="decl"><span class="nottickedoff">centerX t = translate (-x-w/2) 0 t</span>
<span class="lineno"> 181 </span> <span class="lineno"> 181 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 182 </span>-- | Translate given image so that the Y-coordinate of the center of its bouding box is 0. <span class="lineno"> 182 </span><span class="spaces"> </span><span class="nottickedoff">(x, _y, w, _h) = boundingBox t</span></span>
<span class="lineno"> 183 </span>centerY :: Tree -&gt; Tree <span class="lineno"> 183 </span>
<span class="lineno"> 184 </span><span class="decl"><span class="nottickedoff">centerY t = translate 0 (-y-h/2) t</span> <span class="lineno"> 184 </span>-- | Translate given image so that the Y-coordinate of the center of its bouding box is 0.
<span class="lineno"> 185 </span><span class="spaces"> </span><span class="nottickedoff">where</span> <span class="lineno"> 185 </span>centerY :: Tree -&gt; Tree
<span class="lineno"> 186 </span><span class="spaces"> </span><span class="nottickedoff">(_x, y, _w, h) = boundingBox t</span></span> <span class="lineno"> 186 </span><span class="decl"><span class="nottickedoff">centerY t = translate 0 (-y-h/2) t</span>
<span class="lineno"> 187 </span> <span class="lineno"> 187 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 188 </span>centerUsing :: Tree -&gt; Tree -&gt; Tree <span class="lineno"> 188 </span><span class="spaces"> </span><span class="nottickedoff">(_x, y, _w, h) = boundingBox t</span></span>
<span class="lineno"> 189 </span><span class="decl"><span class="istickedoff">centerUsing a = translate (-x-w/2) (-y-h/2)</span> <span class="lineno"> 189 </span>
<span class="lineno"> 190 </span><span class="spaces"> </span><span class="istickedoff">where</span> <span class="lineno"> 190 </span>-- | Center the second argument using the bounding-box of the first.
<span class="lineno"> 191 </span><span class="spaces"> </span><span class="istickedoff">(x, y, w, h) = boundingBox a</span></span> <span class="lineno"> 191 </span>centerUsing :: Tree -&gt; Tree -&gt; Tree
<span class="lineno"> 192 </span> <span class="lineno"> 192 </span><span class="decl"><span class="istickedoff">centerUsing a = translate (-x-w/2) (-y-h/2)</span>
<span class="lineno"> 193 </span>-- | Create 'Texture' based on SVG color name. <span class="lineno"> 193 </span><span class="spaces"> </span><span class="istickedoff">where</span>
<span class="lineno"> 194 </span>-- See &lt;https://en.wikipedia.org/wiki/Web_colors#X11_color_names&gt; for the list of available names. <span class="lineno"> 194 </span><span class="spaces"> </span><span class="istickedoff">(x, y, w, h) = boundingBox a</span></span>
<span class="lineno"> 195 </span>-- If the provided name doesn't correspond to valid SVG color name, white-ish color is used. <span class="lineno"> 195 </span>
<span class="lineno"> 196 </span>mkColor :: String -&gt; Texture <span class="lineno"> 196 </span>-- | Create 'Texture' based on SVG color name.
<span class="lineno"> 197 </span><span class="decl"><span class="istickedoff">mkColor name =</span> <span class="lineno"> 197 </span>-- See &lt;https://en.wikipedia.org/wiki/Web_colors#X11_color_names&gt; for the list of available names.
<span class="lineno"> 198 </span><span class="spaces"> </span><span class="istickedoff">case Map.lookup (T.pack name) svgNamedColors of</span> <span class="lineno"> 198 </span>-- If the provided name doesn't correspond to valid SVG color name, white-ish color is used.
<span class="lineno"> 199 </span><span class="spaces"> </span><span class="istickedoff">Nothing -&gt; <span class="nottickedoff">ColorRef (PixelRGBA8 240 248 255 255)</span></span> <span class="lineno"> 199 </span>mkColor :: String -&gt; Texture
<span class="lineno"> 200 </span><span class="spaces"> </span><span class="istickedoff">Just c -&gt; ColorRef c</span></span> <span class="lineno"> 200 </span><span class="decl"><span class="istickedoff">mkColor name =</span>
<span class="lineno"> 201 </span> <span class="lineno"> 201 </span><span class="spaces"> </span><span class="istickedoff">case Map.lookup (T.pack name) svgNamedColors of</span>
<span class="lineno"> 202 </span>-- | See &lt;https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke&gt; <span class="lineno"> 202 </span><span class="spaces"> </span><span class="istickedoff">Nothing -&gt; <span class="nottickedoff">ColorRef (PixelRGBA8 240 248 255 255)</span></span>
<span class="lineno"> 203 </span>withStrokeColor :: String -&gt; Tree -&gt; Tree <span class="lineno"> 203 </span><span class="spaces"> </span><span class="istickedoff">Just c -&gt; ColorRef c</span></span>
<span class="lineno"> 204 </span><span class="decl"><span class="istickedoff">withStrokeColor color = strokeColor .~ pure (mkColor color)</span></span> <span class="lineno"> 204 </span>
<span class="lineno"> 205 </span> <span class="lineno"> 205 </span>-- | See &lt;https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke&gt;
<span class="lineno"> 206 </span>withStrokeColorPixel :: PixelRGBA8 -&gt; Tree -&gt; Tree <span class="lineno"> 206 </span>withStrokeColor :: String -&gt; Tree -&gt; Tree
<span class="lineno"> 207 </span><span class="decl"><span class="istickedoff">withStrokeColorPixel color = strokeColor .~ pure (ColorRef color)</span></span> <span class="lineno"> 207 </span><span class="decl"><span class="istickedoff">withStrokeColor color = strokeColor .~ pure (mkColor color)</span></span>
<span class="lineno"> 208 </span> <span class="lineno"> 208 </span>
<span class="lineno"> 209 </span>withStrokeDashArray :: [Double] -&gt; Tree -&gt; Tree <span class="lineno"> 209 </span>-- | See &lt;https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke&gt;
<span class="lineno"> 210 </span><span class="decl"><span class="nottickedoff">withStrokeDashArray arr = strokeDashArray .~ pure (map Num arr)</span></span> <span class="lineno"> 210 </span>withStrokeColorPixel :: PixelRGBA8 -&gt; Tree -&gt; Tree
<span class="lineno"> 211 </span> <span class="lineno"> 211 </span><span class="decl"><span class="istickedoff">withStrokeColorPixel color = strokeColor .~ pure (ColorRef color)</span></span>
<span class="lineno"> 212 </span>-- | See &lt;https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin&gt; <span class="lineno"> 212 </span>
<span class="lineno"> 213 </span>withStrokeLineJoin :: LineJoin -&gt; Tree -&gt; Tree <span class="lineno"> 213 </span>-- | See &lt;https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray&gt;
<span class="lineno"> 214 </span><span class="decl"><span class="nottickedoff">withStrokeLineJoin ljoin = strokeLineJoin .~ pure ljoin</span></span> <span class="lineno"> 214 </span>withStrokeDashArray :: [Double] -&gt; Tree -&gt; Tree
<span class="lineno"> 215 </span> <span class="lineno"> 215 </span><span class="decl"><span class="nottickedoff">withStrokeDashArray arr = strokeDashArray .~ pure (map Num arr)</span></span>
<span class="lineno"> 216 </span>-- | See &lt;https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill&gt; <span class="lineno"> 216 </span>
<span class="lineno"> 217 </span>withFillColor :: String -&gt; Tree -&gt; Tree <span class="lineno"> 217 </span>-- | See &lt;https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin&gt;
<span class="lineno"> 218 </span><span class="decl"><span class="istickedoff">withFillColor color = fillColor .~ pure (mkColor color)</span></span> <span class="lineno"> 218 </span>withStrokeLineJoin :: LineJoin -&gt; Tree -&gt; Tree
<span class="lineno"> 219 </span> <span class="lineno"> 219 </span><span class="decl"><span class="nottickedoff">withStrokeLineJoin ljoin = strokeLineJoin .~ pure ljoin</span></span>
<span class="lineno"> 220 </span>withFillColorPixel :: PixelRGBA8 -&gt; Tree -&gt; Tree <span class="lineno"> 220 </span>
<span class="lineno"> 221 </span><span class="decl"><span class="istickedoff">withFillColorPixel color = fillColor .~ pure (ColorRef color)</span></span> <span class="lineno"> 221 </span>-- | See &lt;https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill&gt;
<span class="lineno"> 222 </span> <span class="lineno"> 222 </span>withFillColor :: String -&gt; Tree -&gt; Tree
<span class="lineno"> 223 </span>-- | See &lt;https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity&gt; <span class="lineno"> 223 </span><span class="decl"><span class="istickedoff">withFillColor color = fillColor .~ pure (mkColor color)</span></span>
<span class="lineno"> 224 </span>withFillOpacity :: Double -&gt; Tree -&gt; Tree <span class="lineno"> 224 </span>
<span class="lineno"> 225 </span><span class="decl"><span class="istickedoff">withFillOpacity opacity = fillOpacity ?~ realToFrac opacity</span></span> <span class="lineno"> 225 </span>-- | See &lt;https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill&gt;
<span class="lineno"> 226 </span> <span class="lineno"> 226 </span>withFillColorPixel :: PixelRGBA8 -&gt; Tree -&gt; Tree
<span class="lineno"> 227 </span>withGroupOpacity :: Double -&gt; Tree -&gt; Tree <span class="lineno"> 227 </span><span class="decl"><span class="istickedoff">withFillColorPixel color = fillColor .~ pure (ColorRef color)</span></span>
<span class="lineno"> 228 </span><span class="decl"><span class="istickedoff">withGroupOpacity opacity = groupOpacity ?~ realToFrac opacity</span></span> <span class="lineno"> 228 </span>
<span class="lineno"> 229 </span> <span class="lineno"> 229 </span>-- | See &lt;https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity&gt;
<span class="lineno"> 230 </span>-- | See &lt;https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width&gt; <span class="lineno"> 230 </span>withFillOpacity :: Double -&gt; Tree -&gt; Tree
<span class="lineno"> 231 </span>withStrokeWidth :: Double -&gt; Tree -&gt; Tree <span class="lineno"> 231 </span><span class="decl"><span class="istickedoff">withFillOpacity opacity = fillOpacity ?~ realToFrac opacity</span></span>
<span class="lineno"> 232 </span><span class="decl"><span class="istickedoff">withStrokeWidth width = strokeWidth .~ pure (Num width)</span></span> <span class="lineno"> 232 </span>
<span class="lineno"> 233 </span> <span class="lineno"> 233 </span>-- | See &lt;https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity&gt;
<span class="lineno"> 234 </span>-- | See &lt;https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/clip-path&gt; <span class="lineno"> 234 </span>withGroupOpacity :: Double -&gt; Tree -&gt; Tree
<span class="lineno"> 235 </span>withClipPathRef :: ElementRef -- ^ Reference to clip path defined previously (e.g. by 'mkClipPath') <span class="lineno"> 235 </span><span class="decl"><span class="istickedoff">withGroupOpacity opacity = groupOpacity ?~ realToFrac opacity</span></span>
<span class="lineno"> 236 </span> -&gt; Tree -- ^ Image that will be clipped by the referenced clip path <span class="lineno"> 236 </span>
<span class="lineno"> 237 </span> -&gt; Tree <span class="lineno"> 237 </span>-- | See &lt;https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width&gt;
<span class="lineno"> 238 </span><span class="decl"><span class="nottickedoff">withClipPathRef ref sub = mkGroup [sub] &amp; clipPathRef .~ pure ref</span></span> <span class="lineno"> 238 </span>withStrokeWidth :: Double -&gt; Tree -&gt; Tree
<span class="lineno"> 239 </span> <span class="lineno"> 239 </span><span class="decl"><span class="istickedoff">withStrokeWidth width = strokeWidth .~ pure (Num width)</span></span>
<span class="lineno"> 240 </span>-- | Assigns ID attribute to given image. <span class="lineno"> 240 </span>
<span class="lineno"> 241 </span>withId :: String -&gt; Tree -&gt; Tree <span class="lineno"> 241 </span>-- | See &lt;https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/clip-path&gt;
<span class="lineno"> 242 </span><span class="decl"><span class="nottickedoff">withId idTag = attrId ?~ idTag</span></span> <span class="lineno"> 242 </span>withClipPathRef :: ElementRef -- ^ Reference to clip path defined previously (e.g. by 'mkClipPath')
<span class="lineno"> 243 </span> <span class="lineno"> 243 </span> -&gt; Tree -- ^ Image that will be clipped by the referenced clip path
<span class="lineno"> 244 </span>-- | @mkRect width height@ creates a rectangle with given @with@ and @height@, centered at @(0, 0)@. <span class="lineno"> 244 </span> -&gt; Tree
<span class="lineno"> 245 </span>-- See &lt;https://developer.mozilla.org/en-US/docs/Web/SVG/Element/rect&gt; <span class="lineno"> 245 </span><span class="decl"><span class="nottickedoff">withClipPathRef ref sub = mkGroup [sub] &amp; clipPathRef .~ pure ref</span></span>
<span class="lineno"> 246 </span>mkRect :: Double -&gt; Double -&gt; Tree <span class="lineno"> 246 </span>
<span class="lineno"> 247 </span><span class="decl"><span class="istickedoff">mkRect width height = translate (-width/2) (-height/2) $ RectangleTree $ defaultSvg</span> <span class="lineno"> 247 </span>-- | Assigns ID attribute to given image.
<span class="lineno"> 248 </span><span class="spaces"> </span><span class="istickedoff">&amp; rectUpperLeftCorner .~ (Num 0, Num 0)</span> <span class="lineno"> 248 </span>withId :: String -&gt; Tree -&gt; Tree
<span class="lineno"> 249 </span><span class="spaces"> </span><span class="istickedoff">&amp; rectWidth ?~ Num width</span> <span class="lineno"> 249 </span><span class="decl"><span class="nottickedoff">withId idTag = attrId ?~ idTag</span></span>
<span class="lineno"> 250 </span><span class="spaces"> </span><span class="istickedoff">&amp; rectHeight ?~ Num height</span></span> <span class="lineno"> 250 </span>
<span class="lineno"> 251 </span> <span class="lineno"> 251 </span>-- | @mkRect width height@ creates a rectangle with given @with@ and @height@, centered at @(0, 0)@.
<span class="lineno"> 252 </span>-- | Create a circle with given radius, centered at @(0, 0)@. <span class="lineno"> 252 </span>-- See &lt;https://developer.mozilla.org/en-US/docs/Web/SVG/Element/rect&gt;
<span class="lineno"> 253 </span>-- See &lt;https://developer.mozilla.org/en-US/docs/Web/SVG/Element/circle&gt; <span class="lineno"> 253 </span>mkRect :: Double -&gt; Double -&gt; Tree
<span class="lineno"> 254 </span>mkCircle :: Double -&gt; Tree <span class="lineno"> 254 </span><span class="decl"><span class="istickedoff">mkRect width height = translate (-width/2) (-height/2) $ RectangleTree $ defaultSvg</span>
<span class="lineno"> 255 </span><span class="decl"><span class="istickedoff">mkCircle radius = CircleTree $ defaultSvg</span> <span class="lineno"> 255 </span><span class="spaces"> </span><span class="istickedoff">&amp; rectUpperLeftCorner .~ (Num 0, Num 0)</span>
<span class="lineno"> 256 </span><span class="spaces"> </span><span class="istickedoff">&amp; circleCenter .~ (Num 0, Num 0)</span> <span class="lineno"> 256 </span><span class="spaces"> </span><span class="istickedoff">&amp; rectWidth ?~ Num width</span>
<span class="lineno"> 257 </span><span class="spaces"> </span><span class="istickedoff">&amp; circleRadius .~ Num radius</span></span> <span class="lineno"> 257 </span><span class="spaces"> </span><span class="istickedoff">&amp; rectHeight ?~ Num height</span></span>
<span class="lineno"> 258 </span> <span class="lineno"> 258 </span>
<span class="lineno"> 259 </span>-- | Create an ellipse given X-axis radius, and Y-axis radius, with center at @(0, 0)@. <span class="lineno"> 259 </span>-- | Create a circle with given radius, centered at @(0, 0)@.
<span class="lineno"> 260 </span>-- See &lt;https://developer.mozilla.org/en-US/docs/Web/SVG/Element/ellipse&gt; <span class="lineno"> 260 </span>-- See &lt;https://developer.mozilla.org/en-US/docs/Web/SVG/Element/circle&gt;
<span class="lineno"> 261 </span>mkEllipse :: Double -&gt; Double -&gt; Tree <span class="lineno"> 261 </span>mkCircle :: Double -&gt; Tree
<span class="lineno"> 262 </span><span class="decl"><span class="istickedoff">mkEllipse rx ry = EllipseTree $ defaultSvg</span> <span class="lineno"> 262 </span><span class="decl"><span class="istickedoff">mkCircle radius = CircleTree $ defaultSvg</span>
<span class="lineno"> 263 </span><span class="spaces"> </span><span class="istickedoff">&amp; ellipseCenter .~ (Num 0, Num 0)</span> <span class="lineno"> 263 </span><span class="spaces"> </span><span class="istickedoff">&amp; circleCenter .~ (Num 0, Num 0)</span>
<span class="lineno"> 264 </span><span class="spaces"> </span><span class="istickedoff">&amp; ellipseXRadius .~ Num rx</span> <span class="lineno"> 264 </span><span class="spaces"> </span><span class="istickedoff">&amp; circleRadius .~ Num radius</span></span>
<span class="lineno"> 265 </span><span class="spaces"> </span><span class="istickedoff">&amp; ellipseYRadius .~ Num ry</span></span> <span class="lineno"> 265 </span>
<span class="lineno"> 266 </span> <span class="lineno"> 266 </span>-- | Create an ellipse given X-axis radius, and Y-axis radius, with center at @(0, 0)@.
<span class="lineno"> 267 </span>-- | Create a line segment between two points given by their @(x, y)@ coordinates. <span class="lineno"> 267 </span>-- See &lt;https://developer.mozilla.org/en-US/docs/Web/SVG/Element/ellipse&gt;
<span class="lineno"> 268 </span>-- See &lt;https://developer.mozilla.org/en-US/docs/Web/SVG/Element/line&gt; <span class="lineno"> 268 </span>mkEllipse :: Double -&gt; Double -&gt; Tree
<span class="lineno"> 269 </span>mkLine :: (Double,Double) -&gt; (Double, Double) -&gt; Tree <span class="lineno"> 269 </span><span class="decl"><span class="istickedoff">mkEllipse rx ry = EllipseTree $ defaultSvg</span>
<span class="lineno"> 270 </span><span class="decl"><span class="istickedoff">mkLine (x1,y1) (x2,y2) = LineTree $ defaultSvg</span> <span class="lineno"> 270 </span><span class="spaces"> </span><span class="istickedoff">&amp; ellipseCenter .~ (Num 0, Num 0)</span>
<span class="lineno"> 271 </span><span class="spaces"> </span><span class="istickedoff">&amp; linePoint1 .~ (Num x1, Num y1)</span> <span class="lineno"> 271 </span><span class="spaces"> </span><span class="istickedoff">&amp; ellipseXRadius .~ Num rx</span>
<span class="lineno"> 272 </span><span class="spaces"> </span><span class="istickedoff">&amp; linePoint2 .~ (Num x2, Num y2)</span></span> <span class="lineno"> 272 </span><span class="spaces"> </span><span class="istickedoff">&amp; ellipseYRadius .~ Num ry</span></span>
<span class="lineno"> 273 </span> <span class="lineno"> 273 </span>
<span class="lineno"> 274 </span>-- | Merges multiple images into one. <span class="lineno"> 274 </span>-- | Create a line segment between two points given by their @(x, y)@ coordinates.
<span class="lineno"> 275 </span>-- See &lt;https://developer.mozilla.org/en-US/docs/Web/SVG/Element/g&gt; <span class="lineno"> 275 </span>-- See &lt;https://developer.mozilla.org/en-US/docs/Web/SVG/Element/line&gt;
<span class="lineno"> 276 </span>mkGroup :: [Tree] -&gt; Tree <span class="lineno"> 276 </span>mkLine :: (Double,Double) -&gt; (Double, Double) -&gt; Tree
<span class="lineno"> 277 </span><span class="decl"><span class="istickedoff">mkGroup forest = GroupTree $ defaultSvg</span> <span class="lineno"> 277 </span><span class="decl"><span class="istickedoff">mkLine (x1,y1) (x2,y2) = LineTree $ defaultSvg</span>
<span class="lineno"> 278 </span><span class="spaces"> </span><span class="istickedoff">&amp; groupChildren .~ forest</span></span> <span class="lineno"> 278 </span><span class="spaces"> </span><span class="istickedoff">&amp; linePoint1 .~ (Num x1, Num y1)</span>
<span class="lineno"> 279 </span> <span class="lineno"> 279 </span><span class="spaces"> </span><span class="istickedoff">&amp; linePoint2 .~ (Num x2, Num y2)</span></span>
<span class="lineno"> 280 </span>-- | Create definition of graphical objects that can be used at later time. <span class="lineno"> 280 </span>
<span class="lineno"> 281 </span>-- See &lt;https://developer.mozilla.org/en-US/docs/Web/SVG/Element/defs&gt; <span class="lineno"> 281 </span>-- | Merges multiple images into one.
<span class="lineno"> 282 </span>mkDefinitions :: [Tree] -&gt; Tree <span class="lineno"> 282 </span>-- See &lt;https://developer.mozilla.org/en-US/docs/Web/SVG/Element/g&gt;
<span class="lineno"> 283 </span><span class="decl"><span class="nottickedoff">mkDefinitions forest = DefinitionTree $ defaultSvg</span> <span class="lineno"> 283 </span>mkGroup :: [Tree] -&gt; Tree
<span class="lineno"> 284 </span><span class="spaces"> </span><span class="nottickedoff">&amp; groupChildren .~ forest</span></span> <span class="lineno"> 284 </span><span class="decl"><span class="istickedoff">mkGroup forest = GroupTree $ defaultSvg</span>
<span class="lineno"> 285 </span> <span class="lineno"> 285 </span><span class="spaces"> </span><span class="istickedoff">&amp; groupChildren .~ forest</span></span>
<span class="lineno"> 286 </span>-- | Create an element by referring to existing element defined previously. <span class="lineno"> 286 </span>
<span class="lineno"> 287 </span>-- For example you can create a graphical element, assign ID to it using 'withId', wrap it in <span class="lineno"> 287 </span>-- | Create definition of graphical objects that can be used at later time.
<span class="lineno"> 288 </span>-- 'mkDefinitions' and then use it via @use &quot;myId&quot;@. <span class="lineno"> 288 </span>-- See &lt;https://developer.mozilla.org/en-US/docs/Web/SVG/Element/defs&gt;
<span class="lineno"> 289 </span>-- See &lt;https://developer.mozilla.org/en-US/docs/Web/SVG/Element/use&gt; <span class="lineno"> 289 </span>mkDefinitions :: [Tree] -&gt; Tree
<span class="lineno"> 290 </span>mkUse :: String -&gt; Tree <span class="lineno"> 290 </span><span class="decl"><span class="nottickedoff">mkDefinitions forest = DefinitionTree $ defaultSvg</span>
<span class="lineno"> 291 </span><span class="decl"><span class="nottickedoff">mkUse name = UseTree (defaultSvg &amp; useName .~ name) Nothing</span></span> <span class="lineno"> 291 </span><span class="spaces"> </span><span class="nottickedoff">&amp; groupChildren .~ forest</span></span>
<span class="lineno"> 292 </span> <span class="lineno"> 292 </span>
<span class="lineno"> 293 </span>-- | A clip path restricts the region to which paint can be applied. <span class="lineno"> 293 </span>-- | Create an element by referring to existing element defined previously.
<span class="lineno"> 294 </span>-- See &lt;https://developer.mozilla.org/en-US/docs/Web/SVG/Element/clipPath&gt; <span class="lineno"> 294 </span>-- For example you can create a graphical element, assign ID to it using 'withId', wrap it in
<span class="lineno"> 295 </span>mkClipPath :: String -- ^ ID of the clip path, which can then be referred to by other elements <span class="lineno"> 295 </span>-- 'mkDefinitions' and then use it via @use &quot;myId&quot;@.
<span class="lineno"> 296 </span> -- using 'withClipPathRef'. <span class="lineno"> 296 </span>-- See &lt;https://developer.mozilla.org/en-US/docs/Web/SVG/Element/use&gt;
<span class="lineno"> 297 </span> -&gt; [Tree] -- ^ List of shapes that will determine the final shape of the clipping region <span class="lineno"> 297 </span>mkUse :: String -&gt; Tree
<span class="lineno"> 298 </span> -&gt; Tree <span class="lineno"> 298 </span><span class="decl"><span class="nottickedoff">mkUse name = UseTree (defaultSvg &amp; useName .~ name) Nothing</span></span>
<span class="lineno"> 299 </span><span class="decl"><span class="nottickedoff">mkClipPath idTag forest = withId idTag $ ClipPathTree $ defaultSvg</span> <span class="lineno"> 299 </span>
<span class="lineno"> 300 </span><span class="spaces"> </span><span class="nottickedoff">&amp; clipPathContent .~ forest</span></span> <span class="lineno"> 300 </span>-- | A clip path restricts the region to which paint can be applied.
<span class="lineno"> 301 </span> <span class="lineno"> 301 </span>-- See &lt;https://developer.mozilla.org/en-US/docs/Web/SVG/Element/clipPath&gt;
<span class="lineno"> 302 </span>-- | Create a path from the list of path commands. <span class="lineno"> 302 </span>mkClipPath :: String -- ^ ID of the clip path, which can then be referred to by other elements
<span class="lineno"> 303 </span>-- See &lt;https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/d#Path_commands&gt; <span class="lineno"> 303 </span> -- using 'withClipPathRef'.
<span class="lineno"> 304 </span>mkPath :: [PathCommand] -&gt; Tree <span class="lineno"> 304 </span> -&gt; [Tree] -- ^ List of shapes that will determine the final shape of the clipping region
<span class="lineno"> 305 </span><span class="decl"><span class="istickedoff">mkPath cmds = PathTree $ defaultSvg &amp; pathDefinition .~ cmds</span></span> <span class="lineno"> 305 </span> -&gt; Tree
<span class="lineno"> 306 </span> <span class="lineno"> 306 </span><span class="decl"><span class="nottickedoff">mkClipPath idTag forest = withId idTag $ ClipPathTree $ defaultSvg</span>
<span class="lineno"> 307 </span>-- | Similar to 'mkPathText', but taking SVG path command as a String. <span class="lineno"> 307 </span><span class="spaces"> </span><span class="nottickedoff">&amp; clipPathContent .~ forest</span></span>
<span class="lineno"> 308 </span>mkPathString :: String -&gt; Tree <span class="lineno"> 308 </span>
<span class="lineno"> 309 </span><span class="decl"><span class="istickedoff">mkPathString = mkPathText . T.pack</span></span> <span class="lineno"> 309 </span>-- | Create a path from the list of path commands.
<span class="lineno"> 310 </span> <span class="lineno"> 310 </span>-- See &lt;https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/d#Path_commands&gt;
<span class="lineno"> 311 </span>-- | Create path from textual representation of SVG path command. <span class="lineno"> 311 </span>mkPath :: [PathCommand] -&gt; Tree
<span class="lineno"> 312 </span>-- If the text doesn't represent valid path command, this function fails with 'Prelude.error'. <span class="lineno"> 312 </span><span class="decl"><span class="istickedoff">mkPath cmds = PathTree $ defaultSvg &amp; pathDefinition .~ cmds</span></span>
<span class="lineno"> 313 </span>-- Use 'mkPath' for type safe way of creating paths. <span class="lineno"> 313 </span>
<span class="lineno"> 314 </span>mkPathText :: T.Text -&gt; Tree <span class="lineno"> 314 </span>-- | Similar to 'mkPathText', but taking SVG path command as a String.
<span class="lineno"> 315 </span><span class="decl"><span class="istickedoff">mkPathText str =</span> <span class="lineno"> 315 </span>mkPathString :: String -&gt; Tree
<span class="lineno"> 316 </span><span class="spaces"> </span><span class="istickedoff">case parseOnly pathParser str of</span> <span class="lineno"> 316 </span><span class="decl"><span class="istickedoff">mkPathString = mkPathText . T.pack</span></span>
<span class="lineno"> 317 </span><span class="spaces"> </span><span class="istickedoff">Left err -&gt; <span class="nottickedoff">error err</span></span> <span class="lineno"> 317 </span>
<span class="lineno"> 318 </span><span class="spaces"> </span><span class="istickedoff">Right cmds -&gt; mkPath cmds</span></span> <span class="lineno"> 318 </span>-- | Create path from textual representation of SVG path command.
<span class="lineno"> 319 </span> <span class="lineno"> 319 </span>-- If the text doesn't represent valid path command, this function fails with 'Prelude.error'.
<span class="lineno"> 320 </span>-- | Create a path from a list of @(x, y)@ coordinates of points along the path. <span class="lineno"> 320 </span>-- Use 'mkPath' for type safe way of creating paths.
<span class="lineno"> 321 </span>mkLinePath :: [(Double, Double)] -&gt; Tree <span class="lineno"> 321 </span>mkPathText :: T.Text -&gt; Tree
<span class="lineno"> 322 </span><span class="decl"><span class="nottickedoff">mkLinePath [] = mkGroup []</span> <span class="lineno"> 322 </span><span class="decl"><span class="istickedoff">mkPathText str =</span>
<span class="lineno"> 323 </span><span class="spaces"></span><span class="nottickedoff">mkLinePath ((startX, startY):rest) =</span> <span class="lineno"> 323 </span><span class="spaces"> </span><span class="istickedoff">case parseOnly pathParser str of</span>
<span class="lineno"> 324 </span><span class="spaces"> </span><span class="nottickedoff">PathTree $ defaultSvg &amp; pathDefinition .~ cmds</span> <span class="lineno"> 324 </span><span class="spaces"> </span><span class="istickedoff">Left err -&gt; <span class="nottickedoff">error err</span></span>
<span class="lineno"> 325 </span><span class="spaces"> </span><span class="nottickedoff">where</span> <span class="lineno"> 325 </span><span class="spaces"> </span><span class="istickedoff">Right cmds -&gt; mkPath cmds</span></span>
<span class="lineno"> 326 </span><span class="spaces"> </span><span class="nottickedoff">cmds = [ MoveTo OriginAbsolute [V2 startX startY]</span> <span class="lineno"> 326 </span>
<span class="lineno"> 327 </span><span class="spaces"> </span><span class="nottickedoff">, LineTo OriginAbsolute [ V2 x y | (x, y) &lt;- rest ] ]</span></span> <span class="lineno"> 327 </span>-- | Create a path from a list of @(x, y)@ coordinates of points along the path.
<span class="lineno"> 328 </span> <span class="lineno"> 328 </span>mkLinePath :: [(Double, Double)] -&gt; Tree
<span class="lineno"> 329 </span>-- | Create a path from a list of @(x, y)@ coordinates of points along the path. <span class="lineno"> 329 </span><span class="decl"><span class="nottickedoff">mkLinePath [] = mkGroup []</span>
<span class="lineno"> 330 </span>mkLinePathClosed :: [(Double, Double)] -&gt; Tree <span class="lineno"> 330 </span><span class="spaces"></span><span class="nottickedoff">mkLinePath ((startX, startY):rest) =</span>
<span class="lineno"> 331 </span><span class="decl"><span class="istickedoff">mkLinePathClosed [] = <span class="nottickedoff">mkGroup []</span></span> <span class="lineno"> 331 </span><span class="spaces"> </span><span class="nottickedoff">PathTree $ defaultSvg &amp; pathDefinition .~ cmds</span>
<span class="lineno"> 332 </span><span class="spaces"></span><span class="istickedoff">mkLinePathClosed ((startX, startY):rest) =</span> <span class="lineno"> 332 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 333 </span><span class="spaces"> </span><span class="istickedoff">PathTree $ defaultSvg &amp; pathDefinition .~ cmds</span> <span class="lineno"> 333 </span><span class="spaces"> </span><span class="nottickedoff">cmds = [ MoveTo OriginAbsolute [V2 startX startY]</span>
<span class="lineno"> 334 </span><span class="spaces"> </span><span class="istickedoff">where</span> <span class="lineno"> 334 </span><span class="spaces"> </span><span class="nottickedoff">, LineTo OriginAbsolute [ V2 x y | (x, y) &lt;- rest ] ]</span></span>
<span class="lineno"> 335 </span><span class="spaces"> </span><span class="istickedoff">cmds = [ MoveTo OriginAbsolute [V2 startX startY]</span> <span class="lineno"> 335 </span>
<span class="lineno"> 336 </span><span class="spaces"> </span><span class="istickedoff">, LineTo OriginAbsolute [ V2 x y | (x, y) &lt;- rest ]</span> <span class="lineno"> 336 </span>-- | Create a path from a list of @(x, y)@ coordinates of points along the path.
<span class="lineno"> 337 </span><span class="spaces"> </span><span class="istickedoff">, EndPath ]</span></span> <span class="lineno"> 337 </span>mkLinePathClosed :: [(Double, Double)] -&gt; Tree
<span class="lineno"> 338 </span> <span class="lineno"> 338 </span><span class="decl"><span class="istickedoff">mkLinePathClosed [] = <span class="nottickedoff">mkGroup []</span></span>
<span class="lineno"> 339 </span>-- | Rectangle with a uniform color and the same size as the screen. <span class="lineno"> 339 </span><span class="spaces"></span><span class="istickedoff">mkLinePathClosed ((startX, startY):rest) =</span>
<span class="lineno"> 340 </span>-- <span class="lineno"> 340 </span><span class="spaces"> </span><span class="istickedoff">PathTree $ defaultSvg &amp; pathDefinition .~ cmds</span>
<span class="lineno"> 341 </span>-- Example: <span class="lineno"> 341 </span><span class="spaces"> </span><span class="istickedoff">where</span>
<span class="lineno"> 342 </span>-- <span class="lineno"> 342 </span><span class="spaces"> </span><span class="istickedoff">cmds = [ MoveTo OriginAbsolute [V2 startX startY]</span>
<span class="lineno"> 343 </span>-- &gt; animate $ const $ mkBackground &quot;yellow&quot; <span class="lineno"> 343 </span><span class="spaces"> </span><span class="istickedoff">, LineTo OriginAbsolute [ V2 x y | (x, y) &lt;- rest ]</span>
<span class="lineno"> 344 </span>-- <span class="lineno"> 344 </span><span class="spaces"> </span><span class="istickedoff">, EndPath ]</span></span>
<span class="lineno"> 345 </span>-- &lt;&lt;docs/gifs/doc_mkBackground.gif&gt;&gt; <span class="lineno"> 345 </span>
<span class="lineno"> 346 </span>mkBackground :: String -&gt; Tree <span class="lineno"> 346 </span>-- | Rectangle with a uniform color and the same size as the screen.
<span class="lineno"> 347 </span><span class="decl"><span class="istickedoff">mkBackground color = withFillOpacity 1 $ withStrokeWidth 0 $</span> <span class="lineno"> 347 </span>--
<span class="lineno"> 348 </span><span class="spaces"> </span><span class="istickedoff">withFillColor color $ mkRect screenWidth screenHeight</span></span> <span class="lineno"> 348 </span>-- Example:
<span class="lineno"> 349 </span> <span class="lineno"> 349 </span>--
<span class="lineno"> 350 </span>mkBackgroundPixel :: PixelRGBA8 -&gt; Tree <span class="lineno"> 350 </span>-- &gt; animate $ const $ mkBackground &quot;yellow&quot;
<span class="lineno"> 351 </span><span class="decl"><span class="istickedoff">mkBackgroundPixel pixel =</span> <span class="lineno"> 351 </span>--
<span class="lineno"> 352 </span><span class="spaces"> </span><span class="istickedoff">withFillOpacity 1 $ withStrokeWidth 0 $</span> <span class="lineno"> 352 </span>-- &lt;&lt;docs/gifs/doc_mkBackground.gif&gt;&gt;
<span class="lineno"> 353 </span><span class="spaces"> </span><span class="istickedoff">withFillColorPixel pixel $ mkRect screenWidth screenHeight</span></span> <span class="lineno"> 353 </span>mkBackground :: String -&gt; Tree
<span class="lineno"> 354 </span> <span class="lineno"> 354 </span><span class="decl"><span class="istickedoff">mkBackground color = withFillOpacity 1 $ withStrokeWidth 0 $</span>
<span class="lineno"> 355 </span>-- | Take list of rows, where each row consists of number of images and display them in regular <span class="lineno"> 355 </span><span class="spaces"> </span><span class="istickedoff">withFillColor color $ mkRect screenWidth screenHeight</span></span>
<span class="lineno"> 356 </span>-- grid structure. <span class="lineno"> 356 </span>
<span class="lineno"> 357 </span>-- All rows will get equal amount of vertical space. <span class="lineno"> 357 </span>-- | Rectangle with a uniform color and the same size as the screen.
<span class="lineno"> 358 </span>-- The images within each row will get equal amount of horizontal space, independent of the other <span class="lineno"> 358 </span>mkBackgroundPixel :: PixelRGBA8 -&gt; Tree
<span class="lineno"> 359 </span>-- rows. Each row can contain different number of cells. <span class="lineno"> 359 </span><span class="decl"><span class="istickedoff">mkBackgroundPixel pixel =</span>
<span class="lineno"> 360 </span>gridLayout :: [[Tree]] -&gt; Tree <span class="lineno"> 360 </span><span class="spaces"> </span><span class="istickedoff">withFillOpacity 1 $ withStrokeWidth 0 $</span>
<span class="lineno"> 361 </span><span class="decl"><span class="istickedoff">gridLayout rows = mkGroup</span> <span class="lineno"> 361 </span><span class="spaces"> </span><span class="istickedoff">withFillColorPixel pixel $ mkRect screenWidth screenHeight</span></span>
<span class="lineno"> 362 </span><span class="spaces"> </span><span class="istickedoff">[ translate (-screenWidth/2+colSep*nCol + colSep*0.5)</span> <span class="lineno"> 362 </span>
<span class="lineno"> 363 </span><span class="spaces"> </span><span class="istickedoff">(screenHeight/2-rowSep*nRow - rowSep*0.5)</span> <span class="lineno"> 363 </span>-- | Take list of rows, where each row consists of number of images and display them in regular
<span class="lineno"> 364 </span><span class="spaces"> </span><span class="istickedoff">elt</span> <span class="lineno"> 364 </span>-- grid structure.
<span class="lineno"> 365 </span><span class="spaces"> </span><span class="istickedoff">| (nRow, row) &lt;- zip [0..] rows</span> <span class="lineno"> 365 </span>-- All rows will get equal amount of vertical space.
<span class="lineno"> 366 </span><span class="spaces"> </span><span class="istickedoff">, let nCols = length row</span> <span class="lineno"> 366 </span>-- The images within each row will get equal amount of horizontal space, independent of the other
<span class="lineno"> 367 </span><span class="spaces"> </span><span class="istickedoff">colSep = screenWidth / fromIntegral nCols</span> <span class="lineno"> 367 </span>-- rows. Each row can contain different number of cells.
<span class="lineno"> 368 </span><span class="spaces"> </span><span class="istickedoff">, (nCol, elt) &lt;- zip [0..] row ]</span> <span class="lineno"> 368 </span>gridLayout :: [[Tree]] -&gt; Tree
<span class="lineno"> 369 </span><span class="spaces"> </span><span class="istickedoff">where</span> <span class="lineno"> 369 </span><span class="decl"><span class="istickedoff">gridLayout rows = mkGroup</span>
<span class="lineno"> 370 </span><span class="spaces"> </span><span class="istickedoff">rowSep = screenHeight / fromIntegral nRows</span> <span class="lineno"> 370 </span><span class="spaces"> </span><span class="istickedoff">[ translate (-screenWidth/2+colSep*nCol + colSep*0.5)</span>
<span class="lineno"> 371 </span><span class="spaces"> </span><span class="istickedoff">nRows = length rows</span></span> <span class="lineno"> 371 </span><span class="spaces"> </span><span class="istickedoff">(screenHeight/2-rowSep*nRow - rowSep*0.5)</span>
<span class="lineno"> 372 </span> <span class="lineno"> 372 </span><span class="spaces"> </span><span class="istickedoff">elt</span>
<span class="lineno"> 373 </span>-- | Insert a native text object anchored at the middle. <span class="lineno"> 373 </span><span class="spaces"> </span><span class="istickedoff">| (nRow, row) &lt;- zip [0..] rows</span>
<span class="lineno"> 374 </span>-- <span class="lineno"> 374 </span><span class="spaces"> </span><span class="istickedoff">, let nCols = length row</span>
<span class="lineno"> 375 </span>-- Example: <span class="lineno"> 375 </span><span class="spaces"> </span><span class="istickedoff">colSep = screenWidth / fromIntegral nCols</span>
<span class="lineno"> 376 </span>-- <span class="lineno"> 376 </span><span class="spaces"> </span><span class="istickedoff">, (nCol, elt) &lt;- zip [0..] row ]</span>
<span class="lineno"> 377 </span>-- &gt; mkAnimation 2 $ \t -&gt; scale 2 $ withStrokeWidth 0.05 $ mkText (T.take (round $ t*15) &quot;text&quot;) <span class="lineno"> 377 </span><span class="spaces"> </span><span class="istickedoff">where</span>
<span class="lineno"> 378 </span>-- <span class="lineno"> 378 </span><span class="spaces"> </span><span class="istickedoff">rowSep = screenHeight / fromIntegral nRows</span>
<span class="lineno"> 379 </span>-- &lt;&lt;docs/gifs/doc_mkText.gif&gt;&gt; <span class="lineno"> 379 </span><span class="spaces"> </span><span class="istickedoff">nRows = length rows</span></span>
<span class="lineno"> 380 </span>mkText :: T.Text -&gt; Tree <span class="lineno"> 380 </span>
<span class="lineno"> 381 </span><span class="decl"><span class="istickedoff">mkText str =</span> <span class="lineno"> 381 </span>-- | Insert a native text object anchored at the middle.
<span class="lineno"> 382 </span><span class="spaces"> </span><span class="istickedoff">flipYAxis</span> <span class="lineno"> 382 </span>--
<span class="lineno"> 383 </span><span class="spaces"> </span><span class="istickedoff">(TextTree Nothing $ defaultSvg</span> <span class="lineno"> 383 </span>-- Example:
<span class="lineno"> 384 </span><span class="spaces"> </span><span class="istickedoff">&amp; textRoot .~ span_</span> <span class="lineno"> 384 </span>--
<span class="lineno"> 385 </span><span class="spaces"> </span><span class="istickedoff">&amp; fontSize .~ pure (Num 2))</span> <span class="lineno"> 385 </span>-- &gt; mkAnimation 2 $ \t -&gt; scale 2 $ withStrokeWidth 0.05 $ mkText (T.take (round $ t*15) &quot;text&quot;)
<span class="lineno"> 386 </span><span class="spaces"> </span><span class="istickedoff">&amp; textAnchor .~ pure TextAnchorMiddle</span> <span class="lineno"> 386 </span>--
<span class="lineno"> 387 </span><span class="spaces"> </span><span class="istickedoff">-- Note: TextAnchorMiddle is placed on the 'flipYAxis' group such that it can easily</span> <span class="lineno"> 387 </span>-- &lt;&lt;docs/gifs/doc_mkText.gif&gt;&gt;
<span class="lineno"> 388 </span><span class="spaces"> </span><span class="istickedoff">-- be overwritten by the user.</span> <span class="lineno"> 388 </span>mkText :: T.Text -&gt; Tree
<span class="lineno"> 389 </span><span class="spaces"> </span><span class="istickedoff">where</span> <span class="lineno"> 389 </span><span class="decl"><span class="istickedoff">mkText str =</span>
<span class="lineno"> 390 </span><span class="spaces"> </span><span class="istickedoff">span_ = defaultSvg &amp; spanContent .~ [SpanText str]</span></span> <span class="lineno"> 390 </span><span class="spaces"> </span><span class="istickedoff">flipYAxis</span>
<span class="lineno"> 391 </span> <span class="lineno"> 391 </span><span class="spaces"> </span><span class="istickedoff">(TextTree Nothing $ defaultSvg</span>
<span class="lineno"> 392 </span>-- | Switch from the default viewbox to a custom viewbox. Nesting custom viewboxes is <span class="lineno"> 392 </span><span class="spaces"> </span><span class="istickedoff">&amp; textRoot .~ span_</span>
<span class="lineno"> 393 </span>-- unlikely to give good results. If you need nested custom viewboxes, you will have <span class="lineno"> 393 </span><span class="spaces"> </span><span class="istickedoff">&amp; fontSize .~ pure (Num 2))</span>
<span class="lineno"> 394 </span>-- to configure them by hand. <span class="lineno"> 394 </span><span class="spaces"> </span><span class="istickedoff">&amp; textAnchor .~ pure TextAnchorMiddle</span>
<span class="lineno"> 395 </span>-- <span class="lineno"> 395 </span><span class="spaces"> </span><span class="istickedoff">-- Note: TextAnchorMiddle is placed on the 'flipYAxis' group such that it can easily</span>
<span class="lineno"> 396 </span>-- The viewbox argument is (min-x, min-y, width, height). <span class="lineno"> 396 </span><span class="spaces"> </span><span class="istickedoff">-- be overwritten by the user.</span>
<span class="lineno"> 397 </span>-- <span class="lineno"> 397 </span><span class="spaces"> </span><span class="istickedoff">where</span>
<span class="lineno"> 398 </span>-- Example: <span class="lineno"> 398 </span><span class="spaces"> </span><span class="istickedoff">span_ = defaultSvg &amp; spanContent .~ [SpanText str]</span></span>
<span class="lineno"> 399 </span>-- <span class="lineno"> 399 </span>
<span class="lineno"> 400 </span>-- &gt; withViewBox (0,0,1,1) $ mkBackground &quot;yellow&quot; <span class="lineno"> 400 </span>-- | Switch from the default viewbox to a custom viewbox. Nesting custom viewboxes is
<span class="lineno"> 401 </span>-- <span class="lineno"> 401 </span>-- unlikely to give good results. If you need nested custom viewboxes, you will have
<span class="lineno"> 402 </span>-- &lt;&lt;docs/gifs/doc_withViewBox.gif&gt;&gt; <span class="lineno"> 402 </span>-- to configure them by hand.
<span class="lineno"> 403 </span>withViewBox :: (Double, Double, Double, Double) -&gt; Tree -&gt; Tree <span class="lineno"> 403 </span>--
<span class="lineno"> 404 </span><span class="decl"><span class="istickedoff">withViewBox vbox child = translate (-screenWidth/2) (-screenHeight/2) $</span> <span class="lineno"> 404 </span>-- The viewbox argument is (min-x, min-y, width, height).
<span class="lineno"> 405 </span><span class="spaces"> </span><span class="istickedoff">SvgTree $ Document</span> <span class="lineno"> 405 </span>--
<span class="lineno"> 406 </span><span class="spaces"> </span><span class="istickedoff">{ _viewBox = Just vbox</span> <span class="lineno"> 406 </span>-- Example:
<span class="lineno"> 407 </span><span class="spaces"> </span><span class="istickedoff">, _width = Just (Num screenWidth)</span> <span class="lineno"> 407 </span>--
<span class="lineno"> 408 </span><span class="spaces"> </span><span class="istickedoff">, _height = Just (Num screenHeight)</span> <span class="lineno"> 408 </span>-- &gt; withViewBox (0,0,1,1) $ mkBackground &quot;yellow&quot;
<span class="lineno"> 409 </span><span class="spaces"> </span><span class="istickedoff">, _elements = [child]</span> <span class="lineno"> 409 </span>--
<span class="lineno"> 410 </span><span class="spaces"> </span><span class="istickedoff">, _description = &quot;&quot;</span> <span class="lineno"> 410 </span>-- &lt;&lt;docs/gifs/doc_withViewBox.gif&gt;&gt;
<span class="lineno"> 411 </span><span class="spaces"> </span><span class="istickedoff">, _documentLocation = <span class="nottickedoff">&quot;&quot;</span></span> <span class="lineno"> 411 </span>withViewBox :: (Double, Double, Double, Double) -&gt; Tree -&gt; Tree
<span class="lineno"> 412 </span><span class="spaces"> </span><span class="istickedoff">, _documentAspectRatio = PreserveAspectRatio False AlignNone Nothing</span> <span class="lineno"> 412 </span><span class="decl"><span class="istickedoff">withViewBox vbox child = translate (-screenWidth/2) (-screenHeight/2) $</span>
<span class="lineno"> 413 </span><span class="spaces"> </span><span class="istickedoff">}</span></span> <span class="lineno"> 413 </span><span class="spaces"> </span><span class="istickedoff">SvgTree $ Document</span>
<span class="lineno"> 414 </span><span class="spaces"> </span><span class="istickedoff">{ _viewBox = Just vbox</span>
<span class="lineno"> 415 </span><span class="spaces"> </span><span class="istickedoff">, _width = Just (Num screenWidth)</span>
<span class="lineno"> 416 </span><span class="spaces"> </span><span class="istickedoff">, _height = Just (Num screenHeight)</span>
<span class="lineno"> 417 </span><span class="spaces"> </span><span class="istickedoff">, _elements = [child]</span>
<span class="lineno"> 418 </span><span class="spaces"> </span><span class="istickedoff">, _description = &quot;&quot;</span>
<span class="lineno"> 419 </span><span class="spaces"> </span><span class="istickedoff">, _documentLocation = <span class="nottickedoff">&quot;&quot;</span></span>
<span class="lineno"> 420 </span><span class="spaces"> </span><span class="istickedoff">, _documentAspectRatio = PreserveAspectRatio False AlignNone Nothing</span>
<span class="lineno"> 421 </span><span class="spaces"> </span><span class="istickedoff">}</span></span>
</pre> </pre>
</body> </body>

View file

@ -30,53 +30,56 @@ span.spaces { background: white }
<span class="lineno"> 11 </span>import Reanimate.Constants <span class="lineno"> 11 </span>import Reanimate.Constants
<span class="lineno"> 12 </span>import Reanimate.Svg.Constructors <span class="lineno"> 12 </span>import Reanimate.Svg.Constructors
<span class="lineno"> 13 </span> <span class="lineno"> 13 </span>
<span class="lineno"> 14 </span>replaceUses :: Document -&gt; Document <span class="lineno"> 14 </span>-- | Replace all @&lt;use&gt;@ nodes with their definition.
<span class="lineno"> 15 </span><span class="decl"><span class="nottickedoff">replaceUses doc = doc &amp; elements %~ map (mapTree replace)</span> <span class="lineno"> 15 </span>replaceUses :: Document -&gt; Document
<span class="lineno"> 16 </span><span class="spaces"> </span><span class="nottickedoff">where</span> <span class="lineno"> 16 </span><span class="decl"><span class="nottickedoff">replaceUses doc = doc &amp; elements %~ map (mapTree replace)</span>
<span class="lineno"> 17 </span><span class="spaces"> </span><span class="nottickedoff">replaceDefinition PathTree{} = None</span> <span class="lineno"> 17 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 18 </span><span class="spaces"> </span><span class="nottickedoff">replaceDefinition t = t</span> <span class="lineno"> 18 </span><span class="spaces"> </span><span class="nottickedoff">replaceDefinition PathTree{} = None</span>
<span class="lineno"> 19 </span><span class="spaces"></span><span class="nottickedoff"></span> <span class="lineno"> 19 </span><span class="spaces"> </span><span class="nottickedoff">replaceDefinition t = t</span>
<span class="lineno"> 20 </span><span class="spaces"> </span><span class="nottickedoff">replace t@DefinitionTree{} = mapTree replaceDefinition t</span> <span class="lineno"> 20 </span><span class="spaces"></span><span class="nottickedoff"></span>
<span class="lineno"> 21 </span><span class="spaces"> </span><span class="nottickedoff">replace (UseTree _ Just{}) = error &quot;replaceUses: subtree in use?&quot;</span> <span class="lineno"> 21 </span><span class="spaces"> </span><span class="nottickedoff">replace t@DefinitionTree{} = mapTree replaceDefinition t</span>
<span class="lineno"> 22 </span><span class="spaces"> </span><span class="nottickedoff">replace (UseTree use Nothing) =</span> <span class="lineno"> 22 </span><span class="spaces"> </span><span class="nottickedoff">replace (UseTree _ Just{}) = error &quot;replaceUses: subtree in use?&quot;</span>
<span class="lineno"> 23 </span><span class="spaces"> </span><span class="nottickedoff">case Map.lookup (use^.useName) idMap of</span> <span class="lineno"> 23 </span><span class="spaces"> </span><span class="nottickedoff">replace (UseTree use Nothing) =</span>
<span class="lineno"> 24 </span><span class="spaces"> </span><span class="nottickedoff">Nothing -&gt; error $ &quot;Unknown id: &quot; ++ (use^.useName)</span> <span class="lineno"> 24 </span><span class="spaces"> </span><span class="nottickedoff">case Map.lookup (use^.useName) idMap of</span>
<span class="lineno"> 25 </span><span class="spaces"> </span><span class="nottickedoff">Just tree -&gt; mapTree replace $</span> <span class="lineno"> 25 </span><span class="spaces"> </span><span class="nottickedoff">Nothing -&gt; error $ &quot;Unknown id: &quot; ++ (use^.useName)</span>
<span class="lineno"> 26 </span><span class="spaces"> </span><span class="nottickedoff">GroupTree $</span> <span class="lineno"> 26 </span><span class="spaces"> </span><span class="nottickedoff">Just tree -&gt; mapTree replace $</span>
<span class="lineno"> 27 </span><span class="spaces"> </span><span class="nottickedoff">defaultSvg &amp; groupChildren .~ [tree]</span> <span class="lineno"> 27 </span><span class="spaces"> </span><span class="nottickedoff">GroupTree $</span>
<span class="lineno"> 28 </span><span class="spaces"> </span><span class="nottickedoff">&amp; transform ?~</span> <span class="lineno"> 28 </span><span class="spaces"> </span><span class="nottickedoff">defaultSvg &amp; groupChildren .~ [tree]</span>
<span class="lineno"> 29 </span><span class="spaces"> </span><span class="nottickedoff">fromMaybe [] (use^.transform) ++</span> <span class="lineno"> 29 </span><span class="spaces"> </span><span class="nottickedoff">&amp; transform ?~</span>
<span class="lineno"> 30 </span><span class="spaces"> </span><span class="nottickedoff">[baseToTransformation (use^.useBase)]</span> <span class="lineno"> 30 </span><span class="spaces"> </span><span class="nottickedoff">fromMaybe [] (use^.transform) ++</span>
<span class="lineno"> 31 </span><span class="spaces"> </span><span class="nottickedoff">replace x = x</span> <span class="lineno"> 31 </span><span class="spaces"> </span><span class="nottickedoff">[baseToTransformation (use^.useBase)]</span>
<span class="lineno"> 32 </span><span class="spaces"> </span><span class="nottickedoff">baseToTransformation (x,y) =</span> <span class="lineno"> 32 </span><span class="spaces"> </span><span class="nottickedoff">replace x = x</span>
<span class="lineno"> 33 </span><span class="spaces"> </span><span class="nottickedoff">case (toUserUnit defaultDPI x, toUserUnit defaultDPI y) of</span> <span class="lineno"> 33 </span><span class="spaces"> </span><span class="nottickedoff">baseToTransformation (x,y) =</span>
<span class="lineno"> 34 </span><span class="spaces"> </span><span class="nottickedoff">(Num a, Num b) -&gt; Translate a b</span> <span class="lineno"> 34 </span><span class="spaces"> </span><span class="nottickedoff">case (toUserUnit defaultDPI x, toUserUnit defaultDPI y) of</span>
<span class="lineno"> 35 </span><span class="spaces"> </span><span class="nottickedoff">_ -&gt; TransformUnknown</span> <span class="lineno"> 35 </span><span class="spaces"> </span><span class="nottickedoff">(Num a, Num b) -&gt; Translate a b</span>
<span class="lineno"> 36 </span><span class="spaces"> </span><span class="nottickedoff">docTree = mkGroup (doc^.elements)</span> <span class="lineno"> 36 </span><span class="spaces"> </span><span class="nottickedoff">_ -&gt; TransformUnknown</span>
<span class="lineno"> 37 </span><span class="spaces"> </span><span class="nottickedoff">idMap = foldTree updMap Map.empty docTree</span> <span class="lineno"> 37 </span><span class="spaces"> </span><span class="nottickedoff">docTree = mkGroup (doc^.elements)</span>
<span class="lineno"> 38 </span><span class="spaces"> </span><span class="nottickedoff">updMap m tree =</span> <span class="lineno"> 38 </span><span class="spaces"> </span><span class="nottickedoff">idMap = foldTree updMap Map.empty docTree</span>
<span class="lineno"> 39 </span><span class="spaces"> </span><span class="nottickedoff">case tree^.attrId of</span> <span class="lineno"> 39 </span><span class="spaces"> </span><span class="nottickedoff">updMap m tree =</span>
<span class="lineno"> 40 </span><span class="spaces"> </span><span class="nottickedoff">Nothing -&gt; m</span> <span class="lineno"> 40 </span><span class="spaces"> </span><span class="nottickedoff">case tree^.attrId of</span>
<span class="lineno"> 41 </span><span class="spaces"> </span><span class="nottickedoff">Just tid -&gt; Map.insert tid tree m</span></span> <span class="lineno"> 41 </span><span class="spaces"> </span><span class="nottickedoff">Nothing -&gt; m</span>
<span class="lineno"> 42 </span> <span class="lineno"> 42 </span><span class="spaces"> </span><span class="nottickedoff">Just tid -&gt; Map.insert tid tree m</span></span>
<span class="lineno"> 43 </span>-- FIXME: the viewbox is ignored. Can we use the viewbox as a mask? <span class="lineno"> 43 </span>
<span class="lineno"> 44 </span>-- Transform out viewbox. defs and CSS rules are discarded. <span class="lineno"> 44 </span>-- FIXME: the viewbox is ignored. Can we use the viewbox as a mask?
<span class="lineno"> 45 </span>unbox :: Document -&gt; Tree <span class="lineno"> 45 </span>-- | Transform out viewbox. Definitions and CSS rules are discarded.
<span class="lineno"> 46 </span><span class="decl"><span class="nottickedoff">unbox doc@Document{_viewBox = Just (_minx, _minw, _width, _height)} =</span> <span class="lineno"> 46 </span>unbox :: Document -&gt; Tree
<span class="lineno"> 47 </span><span class="spaces"> </span><span class="nottickedoff">GroupTree $ defaultSvg</span> <span class="lineno"> 47 </span><span class="decl"><span class="nottickedoff">unbox doc@Document{_viewBox = Just (_minx, _minw, _width, _height)} =</span>
<span class="lineno"> 48 </span><span class="spaces"> </span><span class="nottickedoff">&amp; groupChildren .~ doc^.elements</span> <span class="lineno"> 48 </span><span class="spaces"> </span><span class="nottickedoff">GroupTree $ defaultSvg</span>
<span class="lineno"> 49 </span><span class="spaces"></span><span class="nottickedoff">unbox doc =</span> <span class="lineno"> 49 </span><span class="spaces"> </span><span class="nottickedoff">&amp; groupChildren .~ doc^.elements</span>
<span class="lineno"> 50 </span><span class="spaces"> </span><span class="nottickedoff">GroupTree $ defaultSvg</span> <span class="lineno"> 50 </span><span class="spaces"></span><span class="nottickedoff">unbox doc =</span>
<span class="lineno"> 51 </span><span class="spaces"> </span><span class="nottickedoff">&amp; groupChildren .~ doc^.elements</span></span> <span class="lineno"> 51 </span><span class="spaces"> </span><span class="nottickedoff">GroupTree $ defaultSvg</span>
<span class="lineno"> 52 </span> <span class="lineno"> 52 </span><span class="spaces"> </span><span class="nottickedoff">&amp; groupChildren .~ doc^.elements</span></span>
<span class="lineno"> 53 </span>embedDocument :: Document -&gt; Tree <span class="lineno"> 53 </span>
<span class="lineno"> 54 </span><span class="decl"><span class="istickedoff">embedDocument doc =</span> <span class="lineno"> 54 </span>-- | Embed 'Document'. This keeps the entire document intact but makes
<span class="lineno"> 55 </span><span class="spaces"> </span><span class="istickedoff">translate (-screenWidth/2) (screenHeight/2) $</span> <span class="lineno"> 55 </span>-- it more difficult to use, say, `Reanimate.Svg.pathify` on it.
<span class="lineno"> 56 </span><span class="spaces"> </span><span class="istickedoff">withFillOpacity 1 $</span> <span class="lineno"> 56 </span>embedDocument :: Document -&gt; Tree
<span class="lineno"> 57 </span><span class="spaces"> </span><span class="istickedoff">withStrokeWidth 0 $</span> <span class="lineno"> 57 </span><span class="decl"><span class="istickedoff">embedDocument doc =</span>
<span class="lineno"> 58 </span><span class="spaces"> </span><span class="istickedoff">flipYAxis $</span> <span class="lineno"> 58 </span><span class="spaces"> </span><span class="istickedoff">translate (-screenWidth/2) (screenHeight/2) $</span>
<span class="lineno"> 59 </span><span class="spaces"> </span><span class="istickedoff">SvgTree $ doc &amp; width .~ Nothing</span> <span class="lineno"> 59 </span><span class="spaces"> </span><span class="istickedoff">withFillOpacity 1 $</span>
<span class="lineno"> 60 </span><span class="spaces"> </span><span class="istickedoff">&amp; height .~ Nothing</span></span> <span class="lineno"> 60 </span><span class="spaces"> </span><span class="istickedoff">withStrokeWidth 0 $</span>
<span class="lineno"> 61 </span><span class="spaces"> </span><span class="istickedoff">flipYAxis $</span>
<span class="lineno"> 62 </span><span class="spaces"> </span><span class="istickedoff">SvgTree $ doc &amp; width .~ Nothing</span>
<span class="lineno"> 63 </span><span class="spaces"> </span><span class="istickedoff">&amp; height .~ Nothing</span></span>
</pre> </pre>
</body> </body>

View file

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

View file

@ -18,66 +18,76 @@ span.spaces { background: white }
</pre> </pre>
<pre> <pre>
<span class="lineno"> 1 </span>{-# LANGUAGE BangPatterns #-} <span class="lineno"> 1 </span>{-# LANGUAGE BangPatterns #-}
<span class="lineno"> 2 </span>{-# LANGUAGE PackageImports #-} <span class="lineno"> 2 </span>{-|
<span class="lineno"> 3 </span>module Reanimate.Transform <span class="lineno"> 3 </span> 2D transformation matrices capable of translating, scaling,
<span class="lineno"> 4 </span> ( identity <span class="lineno"> 4 </span> rotating, and skewing.
<span class="lineno"> 5 </span> , transformPoint <span class="lineno"> 5 </span>-}
<span class="lineno"> 6 </span> , mkMatrix <span class="lineno"> 6 </span>module Reanimate.Transform
<span class="lineno"> 7 </span> , toTransformation <span class="lineno"> 7 </span> ( identity
<span class="lineno"> 8 </span> ) where <span class="lineno"> 8 </span> , transformPoint
<span class="lineno"> 9 </span> <span class="lineno"> 9 </span> , mkMatrix
<span class="lineno"> 10 </span>-- XXX: Use Linear.Matrix instead of Data.Matrix to drop the 'matrix' dependency. <span class="lineno"> 10 </span> , toTransformation
<span class="lineno"> 11 </span>import Data.List <span class="lineno"> 11 </span> ) where
<span class="lineno"> 12 </span>import &quot;matrix&quot; Data.Matrix (Matrix) <span class="lineno"> 12 </span>
<span class="lineno"> 13 </span>import qualified &quot;matrix&quot; Data.Matrix as M <span class="lineno"> 13 </span>-- XXX: Use Linear.Matrix instead of Data.Matrix to drop the 'matrix' dependency.
<span class="lineno"> 14 </span>import Data.Maybe <span class="lineno"> 14 </span>import Data.List
<span class="lineno"> 15 </span>import Graphics.SvgTree <span class="lineno"> 15 </span>import Data.Matrix (Matrix)
<span class="lineno"> 16 </span>import Linear.V2 <span class="lineno"> 16 </span>import qualified Data.Matrix as M
<span class="lineno"> 17 </span> <span class="lineno"> 17 </span>import Data.Maybe
<span class="lineno"> 18 </span>type TMatrix = Matrix Coord <span class="lineno"> 18 </span>import Graphics.SvgTree
<span class="lineno"> 19 </span> <span class="lineno"> 19 </span>import Linear.V2
<span class="lineno"> 20 </span>identity :: TMatrix <span class="lineno"> 20 </span>
<span class="lineno"> 21 </span><span class="decl"><span class="istickedoff">identity = M.identity 3</span></span> <span class="lineno"> 21 </span>type TMatrix = Matrix Coord
<span class="lineno"> 22 </span> <span class="lineno"> 22 </span>
<span class="lineno"> 23 </span>fromList :: [Coord] -&gt; TMatrix <span class="lineno"> 23 </span>-- | Identity matrix.
<span class="lineno"> 24 </span><span class="decl"><span class="istickedoff">fromList [a,b,c,d,e,f] = M.fromList 3 3 [a,c,e,b,d,f,0,0,1]</span> <span class="lineno"> 24 </span>--
<span class="lineno"> 25 </span><span class="spaces"></span><span class="istickedoff">fromList _ = <span class="nottickedoff">error &quot;Reanimate.Transform.fromList: bad input&quot;</span></span></span> <span class="lineno"> 25 </span>-- @transformPoints identity x = x@
<span class="lineno"> 26 </span> <span class="lineno"> 26 </span>identity :: TMatrix
<span class="lineno"> 27 </span>transformPoint :: TMatrix -&gt; RPoint -&gt; RPoint <span class="lineno"> 27 </span><span class="decl"><span class="istickedoff">identity = M.identity 3</span></span>
<span class="lineno"> 28 </span><span class="decl"><span class="istickedoff">transformPoint m (V2 x y) = V2 (a*x +c*y + e) (b*x + d*y +f)</span> <span class="lineno"> 28 </span>
<span class="lineno"> 29 </span><span class="spaces"> </span><span class="istickedoff">where</span> <span class="lineno"> 29 </span>fromList :: [Coord] -&gt; TMatrix
<span class="lineno"> 30 </span><span class="spaces"> </span><span class="istickedoff">!a = M.unsafeGet 1 1 m</span> <span class="lineno"> 30 </span><span class="decl"><span class="istickedoff">fromList [a,b,c,d,e,f] = M.fromList 3 3 [a,c,e,b,d,f,0,0,1]</span>
<span class="lineno"> 31 </span><span class="spaces"> </span><span class="istickedoff">!c = M.unsafeGet 1 2 m</span> <span class="lineno"> 31 </span><span class="spaces"></span><span class="istickedoff">fromList _ = <span class="nottickedoff">error &quot;Reanimate.Transform.fromList: bad input&quot;</span></span></span>
<span class="lineno"> 32 </span><span class="spaces"> </span><span class="istickedoff">!e = M.unsafeGet 1 3 m</span> <span class="lineno"> 32 </span>
<span class="lineno"> 33 </span><span class="spaces"> </span><span class="istickedoff">!b = M.unsafeGet 2 1 m</span> <span class="lineno"> 33 </span>-- | Apply a transformation matrix to a 2D point.
<span class="lineno"> 34 </span><span class="spaces"> </span><span class="istickedoff">!d = M.unsafeGet 2 2 m</span> <span class="lineno"> 34 </span>transformPoint :: TMatrix -&gt; RPoint -&gt; RPoint
<span class="lineno"> 35 </span><span class="spaces"> </span><span class="istickedoff">!f = M.unsafeGet 2 3 m</span></span> <span class="lineno"> 35 </span><span class="decl"><span class="istickedoff">transformPoint m (V2 x y) = V2 (a*x +c*y + e) (b*x + d*y +f)</span>
<span class="lineno"> 36 </span> -- (a:c:e:b:d:f:_) = M.toList m <span class="lineno"> 36 </span><span class="spaces"> </span><span class="istickedoff">where</span>
<span class="lineno"> 37 </span> <span class="lineno"> 37 </span><span class="spaces"> </span><span class="istickedoff">!a = M.unsafeGet 1 1 m</span>
<span class="lineno"> 38 </span>mkMatrix :: Maybe [Transformation] -&gt; TMatrix <span class="lineno"> 38 </span><span class="spaces"> </span><span class="istickedoff">!c = M.unsafeGet 1 2 m</span>
<span class="lineno"> 39 </span><span class="decl"><span class="istickedoff">mkMatrix Nothing = identity</span> <span class="lineno"> 39 </span><span class="spaces"> </span><span class="istickedoff">!e = M.unsafeGet 1 3 m</span>
<span class="lineno"> 40 </span><span class="spaces"></span><span class="istickedoff">mkMatrix (Just ts) = foldl' (*) identity (map transformationMatrix ts)</span></span> <span class="lineno"> 40 </span><span class="spaces"> </span><span class="istickedoff">!b = M.unsafeGet 2 1 m</span>
<span class="lineno"> 41 </span> <span class="lineno"> 41 </span><span class="spaces"> </span><span class="istickedoff">!d = M.unsafeGet 2 2 m</span>
<span class="lineno"> 42 </span>transformationMatrix :: Transformation -&gt; TMatrix <span class="lineno"> 42 </span><span class="spaces"> </span><span class="istickedoff">!f = M.unsafeGet 2 3 m</span></span>
<span class="lineno"> 43 </span><span class="decl"><span class="istickedoff">transformationMatrix transformation =</span> <span class="lineno"> 43 </span> -- (a:c:e:b:d:f:_) = M.toList m
<span class="lineno"> 44 </span><span class="spaces"> </span><span class="istickedoff">case transformation of</span> <span class="lineno"> 44 </span>
<span class="lineno"> 45 </span><span class="spaces"> </span><span class="istickedoff">TransformMatrix a b c d e f -&gt; <span class="nottickedoff">fromList [a,b,c,d,e,f]</span></span> <span class="lineno"> 45 </span>-- | Convert multiple SVG transformations into a single transformation matrix.
<span class="lineno"> 46 </span><span class="spaces"> </span><span class="istickedoff">Translate x y -&gt; <span class="nottickedoff">translate x y</span></span> <span class="lineno"> 46 </span>mkMatrix :: Maybe [Transformation] -&gt; TMatrix
<span class="lineno"> 47 </span><span class="spaces"> </span><span class="istickedoff">Scale sx mbSy -&gt; fromList [sx,0,0,fromMaybe <span class="nottickedoff">sx</span> mbSy,0,0]</span> <span class="lineno"> 47 </span><span class="decl"><span class="istickedoff">mkMatrix Nothing = identity</span>
<span class="lineno"> 48 </span><span class="spaces"> </span><span class="istickedoff">Rotate a Nothing -&gt; <span class="nottickedoff">rotate a</span></span> <span class="lineno"> 48 </span><span class="spaces"></span><span class="istickedoff">mkMatrix (Just ts) = foldl' (*) identity (map transformationMatrix ts)</span></span>
<span class="lineno"> 49 </span><span class="spaces"> </span><span class="istickedoff">Rotate a (Just (x,y)) -&gt; <span class="nottickedoff">translate x y * rotate a * translate (-x) (-y)</span></span> <span class="lineno"> 49 </span>
<span class="lineno"> 50 </span><span class="spaces"> </span><span class="istickedoff">SkewX a -&gt; <span class="nottickedoff">fromList [1,0,tan (a*pi/180),1,0,0]</span></span> <span class="lineno"> 50 </span>-- | Convert an SVG transformation into a transformation matrix.
<span class="lineno"> 51 </span><span class="spaces"> </span><span class="istickedoff">SkewY a -&gt; <span class="nottickedoff">fromList [1,tan (a*pi/180),0,1,0,0]</span></span> <span class="lineno"> 51 </span>transformationMatrix :: Transformation -&gt; TMatrix
<span class="lineno"> 52 </span><span class="spaces"> </span><span class="istickedoff">TransformUnknown -&gt; <span class="nottickedoff">identity</span></span> <span class="lineno"> 52 </span><span class="decl"><span class="istickedoff">transformationMatrix transformation =</span>
<span class="lineno"> 53 </span><span class="spaces"> </span><span class="istickedoff">where</span> <span class="lineno"> 53 </span><span class="spaces"> </span><span class="istickedoff">case transformation of</span>
<span class="lineno"> 54 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">translate x y = fromList [1,0,0,1,x,y]</span></span> <span class="lineno"> 54 </span><span class="spaces"> </span><span class="istickedoff">TransformMatrix a b c d e f -&gt; <span class="nottickedoff">fromList [a,b,c,d,e,f]</span></span>
<span class="lineno"> 55 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">rotate a = fromList [cos r,sin r,-sin r,cos r,0,0]</span></span> <span class="lineno"> 55 </span><span class="spaces"> </span><span class="istickedoff">Translate x y -&gt; <span class="nottickedoff">translate x y</span></span>
<span class="lineno"> 56 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">where r = a * pi / 180</span></span></span> <span class="lineno"> 56 </span><span class="spaces"> </span><span class="istickedoff">Scale sx mbSy -&gt; fromList [sx,0,0,fromMaybe <span class="nottickedoff">sx</span> mbSy,0,0]</span>
<span class="lineno"> 57 </span> <span class="lineno"> 57 </span><span class="spaces"> </span><span class="istickedoff">Rotate a Nothing -&gt; <span class="nottickedoff">rotate a</span></span>
<span class="lineno"> 58 </span>toTransformation :: TMatrix -&gt; Transformation <span class="lineno"> 58 </span><span class="spaces"> </span><span class="istickedoff">Rotate a (Just (x,y)) -&gt; <span class="nottickedoff">translate x y * rotate a * translate (-x) (-y)</span></span>
<span class="lineno"> 59 </span><span class="decl"><span class="nottickedoff">toTransformation m = TransformMatrix a b c d e f</span> <span class="lineno"> 59 </span><span class="spaces"> </span><span class="istickedoff">SkewX a -&gt; <span class="nottickedoff">fromList [1,0,tan (a*pi/180),1,0,0]</span></span>
<span class="lineno"> 60 </span><span class="spaces"> </span><span class="nottickedoff">where</span> <span class="lineno"> 60 </span><span class="spaces"> </span><span class="istickedoff">SkewY a -&gt; <span class="nottickedoff">fromList [1,tan (a*pi/180),0,1,0,0]</span></span>
<span class="lineno"> 61 </span><span class="spaces"> </span><span class="nottickedoff">[a,c,e,b,d,f,_,_,_] = M.toList m</span></span> <span class="lineno"> 61 </span><span class="spaces"> </span><span class="istickedoff">TransformUnknown -&gt; <span class="nottickedoff">identity</span></span>
<span class="lineno"> 62 </span><span class="spaces"> </span><span class="istickedoff">where</span>
<span class="lineno"> 63 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">translate x y = fromList [1,0,0,1,x,y]</span></span>
<span class="lineno"> 64 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">rotate a = fromList [cos r,sin r,-sin r,cos r,0,0]</span></span>
<span class="lineno"> 65 </span><span class="spaces"> </span><span class="istickedoff"><span class="nottickedoff">where r = a * pi / 180</span></span></span>
<span class="lineno"> 66 </span>
<span class="lineno"> 67 </span>-- | Convert a transformation matrix back into an SVG transformation.
<span class="lineno"> 68 </span>toTransformation :: TMatrix -&gt; Transformation
<span class="lineno"> 69 </span><span class="decl"><span class="nottickedoff">toTransformation m = TransformMatrix a b c d e f</span>
<span class="lineno"> 70 </span><span class="spaces"> </span><span class="nottickedoff">where</span>
<span class="lineno"> 71 </span><span class="spaces"> </span><span class="nottickedoff">[a,c,e,b,d,f,_,_,_] = M.toList m</span></span>
</pre> </pre>
</body> </body>