packages feed

asciidiagram 1.2 → 1.3

raw patch · 20 files changed

+1440/−421 lines, 20 filesdep ~svg-tree

Dependency ranges changed: svg-tree

Files

asciidiagram.cabal view
@@ -1,10 +1,10 @@ -- Initial hitaa.cabal generated by cabal init.  For further documentation, --  see http://haskell.org/cabal/users-guide/ name:                asciidiagram-version:             1.2+version:             1.3 synopsis:            Pretty rendering of Ascii diagram into svg or png. description:         -    Asciidiagram Ascii art diagram like this:+    Transform Ascii art diagram like this:     .     @     ,               \/---------+@@ -40,17 +40,19 @@ Source-Repository this     Type:      git     Location:  git://github.com/Twinside/asciidiagram.git-    Tag:       v1.2+    Tag:       v1.3  library   ghc-options: -O2 -Wall   exposed-modules: Text.AsciiDiagram    other-modules: Text.AsciiDiagram.DiagramCleaner+               , Text.AsciiDiagram.DefaultContext                , Text.AsciiDiagram.Geometry                , Text.AsciiDiagram.Graph                , Text.AsciiDiagram.Parser                , Text.AsciiDiagram.Reconstructor+               , Text.AsciiDiagram.BoundingBoxEstimation                , Text.AsciiDiagram.SvgRender    -- containers >= 0.5.2.1 for Set.elemAt@@ -62,7 +64,7 @@                , containers >= 0.5                , mtl        >= 2.1 && < 2.3                , lens       >= 4.6 && < 5.0-               , svg-tree       >= 0.4.1 && < 0.5+               , svg-tree       >= 0.5 && < 0.6                , rasterific-svg >= 0.3 && < 0.4                , FontyFruity    >= 0.5 && < 0.6                , JuicyPixels    >= 3.2
docimages/arrows.svg view
@@ -1,5 +1,5 @@ <?xml version='1.0' ?>
-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="165.0" height="117.0">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="165.0" height="131.0">
   <style type="text/css">text {
   font-family: Consolas , &quot;DejaVu Sans Mono&quot; , monospace;
   font-size: 16.0px;
@@ -9,35 +9,59 @@ }
 .filled_shape {
   fill: url(#shape_light);
+  stroke: #000000;
+  stroke-width: 1.0px;
 }
+.line_element {
+  fill: none;
+  stroke: #000000;
+  stroke-width: 1.0px;
+}
 .bullet {
   stroke-width: 1.0px;
   fill: #FFFFFF;
   stroke: #000000;
 }
+.arrow_head {
+  fill: #000000;
+  stroke: none;
+}
 </style>
   <defs>
+    <symbol id="circle" viewBox="0.0 0.0 50.0 50.0" preserveAspectRatio="none">
+      <circle class="filled_shape" cx="25.0" cy="25.0" r="24.5" />
+    </symbol>
+    <symbol id="document" viewBox="0.0 0.0 51.0 51.0" preserveAspectRatio="none">
+      <path class="filled_shape" d="m49.98,0.79 -49.166,0.0 0.0,45.402 c15.92,12.45 30.4,-13.44 49.17,0.0 Z" />
+    </symbol>
+    <symbol id="io" viewBox="0.0 0.0 100.0 100.0" preserveAspectRatio="none">
+      <path class="filled_shape" d="m19.207,1.6 h79.414 l-17.192,97.297 h-79.414 Z" />
+    </symbol>
     <linearGradient id="shape_light" x2="0%" y2="100%">
       <stop offset="0%" stop-color="#F5F5F5" />
       <stop offset="100%" stop-color="#D8D8D8" />
     </linearGradient>
+    <symbol id="storage" viewBox="0.0 0.0 80.0 80.0" preserveAspectRatio="none">
+      <path class="filled_shape" d="m4.8122,67.74 v-53.769 c0.0,-3.2991 16.067,-5.9743 35.845,-5.9743 19.78,0.0 35.848,2.6752 35.848,5.9743 v53.769 c0.0,3.2925 -16.068,5.9743 -35.848,5.9743 -19.779,0.0 -35.845,-2.6818 -35.845,-5.9743 Z" />
+      <path class="filled_shape" d="m4.8122,13.97 4.779e-2,0.30672 0.13807,0.30272 0.22834,0.29872 0.31464,0.29344 0.40094,0.28944 0.48325,0.2828 0.56423,0.27744 0.64256,0.2708 0.71823,0.26416 0.79258,0.25752 0.86294,0.25096 0.9333,0.2416 0.99968,0.23496 1.0647,0.22568 1.1271,0.2164 1.1869,0.2084 1.2453,0.19784 1.301,0.1872 1.3555,0.17792 1.4046,0.16728 1.455,0.15536 1.5002,0.14336 1.5466,0.1328 1.5865,0.11952 1.6276,0.10752 1.6648,9.42e-2 1.7007,8.1e-2 1.7338,6.64e-2 1.7644,5.31e-2 1.7923,3.72e-2 1.8188,2.39e-2 1.8427,8.0e-3 c19.78,0.0 35.848,-2.6818 35.848,-5.9743" />
+    </symbol>
   </defs>
-  <path stroke-width="1.0" stroke="#000000" fill="none" class="line_element" d="M60.0,56.0 L60.0,56.0" />
-  <g stroke-width="1.0" stroke="#000000" fill="none" class="line_element">
-    <path class="" d="M60.0,56.0 L60.0,56.0 L20.0,56.0 L10.0,56.0" />
-    <path stroke-width="0.0" stroke="none" fill="#000000" class="" d="M10.0,49.0 L0.0,56.0 L10.0,63.0 Z" />
+  <text x="85.5" y="77.5">&lt; &gt; v ^</text>
+  <path class="line_element" d="M60.0,56.0 L60.0,56.0" />
+  <g class="line_element">
+    <path d="M60.0,56.0 L60.0,56.0 L20.0,56.0 L10.0,56.0" />
+    <path class="arrow_head" d="M10.0,49.0 L0.0,56.0 L10.0,63.0 Z" />
   </g>
-  <g stroke-width="1.0" stroke="#000000" fill="none" class="line_element">
-    <path class="" d="M60.0,56.0 L60.0,56.0 L60.0,28.0 L60.0,14.0" />
-    <path stroke-width="0.0" stroke="none" fill="#000000" class="" d="M55.0,14.0 L65.0,14.0 L60.0,0.0 Z" />
+  <g class="line_element">
+    <path d="M60.0,56.0 L60.0,56.0 L60.0,28.0 L60.0,14.0" />
+    <path class="arrow_head" d="M55.0,14.0 L65.0,14.0 L60.0,0.0 Z" />
   </g>
-  <g stroke-width="1.0" stroke="#000000" fill="none" class="line_element">
-    <path class="" d="M60.0,56.0 L60.0,56.0 L100.0,56.0 L110.0,56.0" />
-    <path stroke-width="0.0" stroke="none" fill="#000000" class="" d="M110.0,49.0 L120.0,56.0 L110.0,63.0 Z" />
+  <g class="line_element">
+    <path d="M60.0,56.0 L60.0,56.0 L100.0,56.0 L110.0,56.0" />
+    <path class="arrow_head" d="M110.0,49.0 L120.0,56.0 L110.0,63.0 Z" />
   </g>
-  <g stroke-width="1.0" stroke="#000000" fill="none" class="line_element">
-    <path class="" d="M60.0,98.0 L60.0,98.0 L60.0,70.0 L60.0,56.0" />
-    <path stroke-width="0.0" stroke="none" fill="#000000" class="" d="M55.0,98.0 L65.0,98.0 L60.0,112.0 Z" />
+  <g class="line_element">
+    <path d="M60.0,98.0 L60.0,98.0 L60.0,70.0 L60.0,56.0" />
+    <path class="arrow_head" d="M55.0,98.0 L65.0,98.0 L60.0,112.0 Z" />
   </g>
-  <text class="" x="85.5" y="77.5">&lt; &gt; v ^</text>
 </svg>
docimages/baseExample.svg view
@@ -1,5 +1,5 @@ <?xml version='1.0' ?>
-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="285.0" height="103.0">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="405.0" height="103.0">
   <style type="text/css">text {
   font-family: Consolas , &quot;DejaVu Sans Mono&quot; , monospace;
   font-size: 16.0px;
@@ -9,38 +9,65 @@ }
 .filled_shape {
   fill: url(#shape_light);
+  stroke: #000000;
+  stroke-width: 1.0px;
 }
+.line_element {
+  fill: none;
+  stroke: #000000;
+  stroke-width: 1.0px;
+}
 .bullet {
   stroke-width: 1.0px;
   fill: #FFFFFF;
   stroke: #000000;
 }
-.flat {
-  fill: #DDDDDD;
+.arrow_head {
+  fill: #000000;
+  stroke: none;
 }
+.flat .filled_shape {
+  fill: #DDEEDD;
+}
 </style>
   <defs>
+    <symbol id="circle" viewBox="0.0 0.0 50.0 50.0" preserveAspectRatio="none">
+      <circle class="filled_shape" cx="25.0" cy="25.0" r="24.5" />
+    </symbol>
+    <symbol id="document" viewBox="0.0 0.0 51.0 51.0" preserveAspectRatio="none">
+      <path class="filled_shape" d="m49.98,0.79 -49.166,0.0 0.0,45.402 c15.92,12.45 30.4,-13.44 49.17,0.0 Z" />
+    </symbol>
+    <symbol id="io" viewBox="0.0 0.0 100.0 100.0" preserveAspectRatio="none">
+      <path class="filled_shape" d="m19.207,1.6 h79.414 l-17.192,97.297 h-79.414 Z" />
+    </symbol>
     <linearGradient id="shape_light" x2="0%" y2="100%">
       <stop offset="0%" stop-color="#F5F5F5" />
       <stop offset="100%" stop-color="#D8D8D8" />
     </linearGradient>
+    <symbol id="storage" viewBox="0.0 0.0 80.0 80.0" preserveAspectRatio="none">
+      <path class="filled_shape" d="m4.8122,67.74 v-53.769 c0.0,-3.2991 16.067,-5.9743 35.845,-5.9743 19.78,0.0 35.848,2.6752 35.848,5.9743 v53.769 c0.0,3.2925 -16.068,5.9743 -35.848,5.9743 -19.779,0.0 -35.845,-2.6818 -35.845,-5.9743 Z" />
+      <path class="filled_shape" d="m4.8122,13.97 4.779e-2,0.30672 0.13807,0.30272 0.22834,0.29872 0.31464,0.29344 0.40094,0.28944 0.48325,0.2828 0.56423,0.27744 0.64256,0.2708 0.71823,0.26416 0.79258,0.25752 0.86294,0.25096 0.9333,0.2416 0.99968,0.23496 1.0647,0.22568 1.1271,0.2164 1.1869,0.2084 1.2453,0.19784 1.301,0.1872 1.3555,0.17792 1.4046,0.16728 1.455,0.15536 1.5002,0.14336 1.5466,0.1328 1.5865,0.11952 1.6276,0.10752 1.6648,9.42e-2 1.7007,8.1e-2 1.7338,6.64e-2 1.7644,5.31e-2 1.7923,3.72e-2 1.8188,2.39e-2 1.8427,8.0e-3 c19.78,0.0 35.848,-2.6818 35.848,-5.9743" />
+    </symbol>
   </defs>
-  <path stroke-width="1.0" stroke="#000000" class="filled_shape" d="M11.5,42.0 L11.5,42.0 L11.5,54.5 L100.0,54.5 L108.5,54.5 L108.5,42.0 L108.5,29.5 L20.0,29.5 L11.5,29.5 Z" />
-  <g stroke-width="1.0" stroke="#000000" class="filled_shape">
+  <g class="line_element">
+    <path d="M160.0,42.0 L160.0,42.0 L120.0,42.0 L110.0,42.0" />
+    <path class="arrow_head" d="M160.0,35.0 L170.0,42.0 L160.0,49.0 Z" />
+  </g>
+  <path class="line_element" d="M200.0,70.0 L200.0,70.0" />
+  <g class="line_element">
+    <path class="dashed_elem" d="M200.0,70.0 L200.0,70.0 S200.0,84.0 190.0,84.0 L130.0,84.0 L120.0,84.0" />
+    <path class="arrow_head" d="M120.0,77.0 L110.0,84.0 L120.0,91.0 Z" />
+  </g>
+  <g>
+    <path class="filled_shape" d="M11.5,42.0 L11.5,42.0 L11.5,54.5 L100.0,54.5 L108.5,54.5 L108.5,42.0 L108.5,29.5 L20.0,29.5 L11.5,29.5 Z" />
+    <text x="35.5" y="49.5">ASCII </text>
+  </g>
+  <g class="filled_shape">
     <path class="flat" d="M11.5,70.0 L11.5,70.0 S10.0,84.0 20.0,82.5 L40.0,82.5 L50.0,82.5 L100.0,82.5 S110.0,84.0 108.5,70.0 L108.5,70.0 L108.5,57.5 L20.0,57.5 L11.5,57.5 Z" />
     <circle class="bullet" cx="50.0" cy="82.5" r="3.0" />
   </g>
-  <path stroke-width="1.0" stroke="#000000" class="filled_shape" d="M171.5,28.0 L171.5,56.0 L171.5,68.5 L190.0,68.5 L200.0,68.5 L260.0,68.5 S270.0,70.0 268.5,56.0 L268.5,28.0 L268.5,15.5 L180.0,15.5 S170.0,14.0 171.5,28.0 Z" />
-  <g stroke-width="1.0" stroke="#000000" fill="none" class="line_element">
-    <path class="" d="M160.0,42.0 L160.0,42.0 L120.0,42.0 L110.0,42.0" />
-    <path stroke-width="0.0" stroke="none" fill="#000000" class="" d="M160.0,35.0 L170.0,42.0 L160.0,49.0 Z" />
-  </g>
-  <path stroke-width="1.0" stroke="#000000" fill="none" class="line_element" d="M200.0,70.0 L200.0,70.0" />
-  <g stroke-width="1.0" stroke="#000000" fill="none" class="line_element">
-    <path class="dashed_elem" d="M200.0,70.0 L200.0,70.0 S200.0,84.0 190.0,84.0 L130.0,84.0 L120.0,84.0" />
-    <path stroke-width="0.0" stroke="none" fill="#000000" class="" d="M120.0,77.0 L110.0,84.0 L120.0,91.0 Z" />
+  <g>
+    <path class="filled_shape" d="M171.5,28.0 L171.5,56.0 L171.5,68.5 L190.0,68.5 L200.0,68.5 L260.0,68.5 S270.0,70.0 268.5,56.0 L268.5,28.0 L268.5,15.5 L180.0,15.5 S170.0,14.0 171.5,28.0 Z" />
+    <text x="185.5" y="49.5">Diagram </text>
   </g>
-  <text class="" x="35.5" y="49.5">ASCII </text>
-  <text class="" x="185.5" y="49.5">Diagram </text>
-  <text class="" x="85.5" y="77.5"></text>
 </svg>
docimages/bulletTest.svg view
@@ -9,30 +9,54 @@ }
 .filled_shape {
   fill: url(#shape_light);
+  stroke: #000000;
+  stroke-width: 1.0px;
 }
+.line_element {
+  fill: none;
+  stroke: #000000;
+  stroke-width: 1.0px;
+}
 .bullet {
   stroke-width: 1.0px;
   fill: #FFFFFF;
   stroke: #000000;
 }
+.arrow_head {
+  fill: #000000;
+  stroke: none;
+}
 </style>
   <defs>
+    <symbol id="circle" viewBox="0.0 0.0 50.0 50.0" preserveAspectRatio="none">
+      <circle class="filled_shape" cx="25.0" cy="25.0" r="24.5" />
+    </symbol>
+    <symbol id="document" viewBox="0.0 0.0 51.0 51.0" preserveAspectRatio="none">
+      <path class="filled_shape" d="m49.98,0.79 -49.166,0.0 0.0,45.402 c15.92,12.45 30.4,-13.44 49.17,0.0 Z" />
+    </symbol>
+    <symbol id="io" viewBox="0.0 0.0 100.0 100.0" preserveAspectRatio="none">
+      <path class="filled_shape" d="m19.207,1.6 h79.414 l-17.192,97.297 h-79.414 Z" />
+    </symbol>
     <linearGradient id="shape_light" x2="0%" y2="100%">
       <stop offset="0%" stop-color="#F5F5F5" />
       <stop offset="100%" stop-color="#D8D8D8" />
     </linearGradient>
+    <symbol id="storage" viewBox="0.0 0.0 80.0 80.0" preserveAspectRatio="none">
+      <path class="filled_shape" d="m4.8122,67.74 v-53.769 c0.0,-3.2991 16.067,-5.9743 35.845,-5.9743 19.78,0.0 35.848,2.6752 35.848,5.9743 v53.769 c0.0,3.2925 -16.068,5.9743 -35.848,5.9743 -19.779,0.0 -35.845,-2.6818 -35.845,-5.9743 Z" />
+      <path class="filled_shape" d="m4.8122,13.97 4.779e-2,0.30672 0.13807,0.30272 0.22834,0.29872 0.31464,0.29344 0.40094,0.28944 0.48325,0.2828 0.56423,0.27744 0.64256,0.2708 0.71823,0.26416 0.79258,0.25752 0.86294,0.25096 0.9333,0.2416 0.99968,0.23496 1.0647,0.22568 1.1271,0.2164 1.1869,0.2084 1.2453,0.19784 1.301,0.1872 1.3555,0.17792 1.4046,0.16728 1.455,0.15536 1.5002,0.14336 1.5466,0.1328 1.5865,0.11952 1.6276,0.10752 1.6648,9.42e-2 1.7007,8.1e-2 1.7338,6.64e-2 1.7644,5.31e-2 1.7923,3.72e-2 1.8188,2.39e-2 1.8427,8.0e-3 c19.78,0.0 35.848,-2.6818 35.848,-5.9743" />
+    </symbol>
   </defs>
-  <g stroke-width="1.0" stroke="#000000" class="filled_shape">
-    <path class="" d="M31.5,28.0 L31.5,28.0 L31.5,40.5 L60.0,40.5 S70.0,42.0 68.5,28.0 L68.5,28.0 L68.5,15.5 L60.0,15.5 L50.0,15.5 L40.0,15.5 L31.5,15.5 Z" />
-    <circle class="bullet" cx="68.5" cy="15.5" r="3.0" />
-    <circle class="bullet" cx="50.0" cy="15.5" r="3.0" />
-    <circle class="bullet" cx="31.5" cy="15.5" r="3.0" />
-  </g>
-  <g stroke-width="1.0" stroke="#000000" fill="none" class="line_element">
-    <path class="" d="M150.0,56.0 L150.0,56.0 L150.0,42.0 L150.0,28.0 L110.0,28.0 L100.0,28.0" />
+  <text x="105.5" y="63.5">* * </text>
+  <g class="line_element">
+    <path d="M150.0,56.0 L150.0,56.0 L150.0,42.0 L150.0,28.0 L110.0,28.0 L100.0,28.0" />
     <circle class="bullet" cx="150.0" cy="56.0" r="3.0" />
     <circle class="bullet" cx="150.0" cy="28.0" r="3.0" />
     <circle class="bullet" cx="100.0" cy="28.0" r="3.0" />
   </g>
-  <text class="" x="105.5" y="63.5">* * </text>
+  <g class="filled_shape">
+    <path d="M31.5,28.0 L31.5,28.0 L31.5,40.5 L60.0,40.5 S70.0,42.0 68.5,28.0 L68.5,28.0 L68.5,15.5 L60.0,15.5 L50.0,15.5 L40.0,15.5 L31.5,15.5 Z" />
+    <circle class="bullet" cx="68.5" cy="15.5" r="3.0" />
+    <circle class="bullet" cx="50.0" cy="15.5" r="3.0" />
+    <circle class="bullet" cx="31.5" cy="15.5" r="3.0" />
+  </g>
 </svg>
docimages/cabalSchema.svg view
@@ -9,34 +9,62 @@ }
 .filled_shape {
   fill: url(#shape_light);
+  stroke: #000000;
+  stroke-width: 1.0px;
 }
+.line_element {
+  fill: none;
+  stroke: #000000;
+  stroke-width: 1.0px;
+}
 .bullet {
   stroke-width: 1.0px;
   fill: #FFFFFF;
   stroke: #000000;
 }
+.arrow_head {
+  fill: #000000;
+  stroke: none;
+}
 </style>
   <defs>
+    <symbol id="circle" viewBox="0.0 0.0 50.0 50.0" preserveAspectRatio="none">
+      <circle class="filled_shape" cx="25.0" cy="25.0" r="24.5" />
+    </symbol>
+    <symbol id="document" viewBox="0.0 0.0 51.0 51.0" preserveAspectRatio="none">
+      <path class="filled_shape" d="m49.98,0.79 -49.166,0.0 0.0,45.402 c15.92,12.45 30.4,-13.44 49.17,0.0 Z" />
+    </symbol>
+    <symbol id="io" viewBox="0.0 0.0 100.0 100.0" preserveAspectRatio="none">
+      <path class="filled_shape" d="m19.207,1.6 h79.414 l-17.192,97.297 h-79.414 Z" />
+    </symbol>
     <linearGradient id="shape_light" x2="0%" y2="100%">
       <stop offset="0%" stop-color="#F5F5F5" />
       <stop offset="100%" stop-color="#D8D8D8" />
     </linearGradient>
+    <symbol id="storage" viewBox="0.0 0.0 80.0 80.0" preserveAspectRatio="none">
+      <path class="filled_shape" d="m4.8122,67.74 v-53.769 c0.0,-3.2991 16.067,-5.9743 35.845,-5.9743 19.78,0.0 35.848,2.6752 35.848,5.9743 v53.769 c0.0,3.2925 -16.068,5.9743 -35.848,5.9743 -19.779,0.0 -35.845,-2.6818 -35.845,-5.9743 Z" />
+      <path class="filled_shape" d="m4.8122,13.97 4.779e-2,0.30672 0.13807,0.30272 0.22834,0.29872 0.31464,0.29344 0.40094,0.28944 0.48325,0.2828 0.56423,0.27744 0.64256,0.2708 0.71823,0.26416 0.79258,0.25752 0.86294,0.25096 0.9333,0.2416 0.99968,0.23496 1.0647,0.22568 1.1271,0.2164 1.1869,0.2084 1.2453,0.19784 1.301,0.1872 1.3555,0.17792 1.4046,0.16728 1.455,0.15536 1.5002,0.14336 1.5466,0.1328 1.5865,0.11952 1.6276,0.10752 1.6648,9.42e-2 1.7007,8.1e-2 1.7338,6.64e-2 1.7644,5.31e-2 1.7923,3.72e-2 1.8188,2.39e-2 1.8427,8.0e-3 c19.78,0.0 35.848,-2.6818 35.848,-5.9743" />
+    </symbol>
   </defs>
-  <path stroke-width="1.0" stroke="#000000" class="filled_shape" d="M11.5,42.0 L11.5,42.0 L11.5,54.5 L100.0,54.5 L108.5,54.5 L108.5,42.0 L108.5,29.5 L20.0,29.5 L11.5,29.5 Z" />
-  <g stroke-width="1.0" stroke="#000000" class="filled_shape">
-    <path class="" d="M11.5,70.0 L11.5,70.0 S10.0,84.0 20.0,82.5 L40.0,82.5 L50.0,82.5 L100.0,82.5 S110.0,84.0 108.5,70.0 L108.5,70.0 L108.5,57.5 L20.0,57.5 L11.5,57.5 Z" />
-    <circle class="bullet" cx="50.0" cy="82.5" r="3.0" />
-  </g>
-  <path stroke-width="1.0" stroke="#000000" class="filled_shape" d="M171.5,28.0 L171.5,56.0 L171.5,68.5 L190.0,68.5 L200.0,68.5 L260.0,68.5 S270.0,70.0 268.5,56.0 L268.5,28.0 L268.5,15.5 L180.0,15.5 S170.0,14.0 171.5,28.0 Z" />
-  <g stroke-width="1.0" stroke="#000000" fill="none" class="line_element">
-    <path class="" d="M160.0,42.0 L160.0,42.0 L120.0,42.0 L110.0,42.0" />
-    <path stroke-width="0.0" stroke="none" fill="#000000" class="" d="M160.0,35.0 L170.0,42.0 L160.0,49.0 Z" />
+  <g class="line_element">
+    <path d="M160.0,42.0 L160.0,42.0 L120.0,42.0 L110.0,42.0" />
+    <path class="arrow_head" d="M160.0,35.0 L170.0,42.0 L160.0,49.0 Z" />
   </g>
-  <path stroke-width="1.0" stroke="#000000" fill="none" class="line_element" d="M200.0,70.0 L200.0,70.0" />
-  <g stroke-width="1.0" stroke="#000000" fill="none" class="line_element">
+  <path class="line_element" d="M200.0,70.0 L200.0,70.0" />
+  <g class="line_element">
     <path class="dashed_elem" d="M200.0,70.0 L200.0,70.0 S200.0,84.0 190.0,84.0 L130.0,84.0 L120.0,84.0" />
-    <path stroke-width="0.0" stroke="none" fill="#000000" class="" d="M120.0,77.0 L110.0,84.0 L120.0,91.0 Z" />
+    <path class="arrow_head" d="M120.0,77.0 L110.0,84.0 L120.0,91.0 Z" />
   </g>
-  <text class="" x="35.5" y="49.5">ASCII </text>
-  <text class="" x="185.5" y="49.5">Diagram </text>
+  <g>
+    <path class="filled_shape" d="M11.5,42.0 L11.5,42.0 L11.5,54.5 L100.0,54.5 L108.5,54.5 L108.5,42.0 L108.5,29.5 L20.0,29.5 L11.5,29.5 Z" />
+    <text x="35.5" y="49.5">ASCII </text>
+  </g>
+  <g class="filled_shape">
+    <path d="M11.5,70.0 L11.5,70.0 S10.0,84.0 20.0,82.5 L40.0,82.5 L50.0,82.5 L100.0,82.5 S110.0,84.0 108.5,70.0 L108.5,70.0 L108.5,57.5 L20.0,57.5 L11.5,57.5 Z" />
+    <circle class="bullet" cx="50.0" cy="82.5" r="3.0" />
+  </g>
+  <g>
+    <path class="filled_shape" d="M171.5,28.0 L171.5,56.0 L171.5,68.5 L190.0,68.5 L200.0,68.5 L260.0,68.5 S270.0,70.0 268.5,56.0 L268.5,28.0 L268.5,15.5 L180.0,15.5 S170.0,14.0 171.5,28.0 Z" />
+    <text x="185.5" y="49.5">Diagram </text>
+  </g>
 </svg>
docimages/complexClosed.svg view
@@ -9,19 +9,43 @@ }
 .filled_shape {
   fill: url(#shape_light);
+  stroke: #000000;
+  stroke-width: 1.0px;
 }
+.line_element {
+  fill: none;
+  stroke: #000000;
+  stroke-width: 1.0px;
+}
 .bullet {
   stroke-width: 1.0px;
   fill: #FFFFFF;
   stroke: #000000;
 }
+.arrow_head {
+  fill: #000000;
+  stroke: none;
+}
 </style>
   <defs>
+    <symbol id="circle" viewBox="0.0 0.0 50.0 50.0" preserveAspectRatio="none">
+      <circle class="filled_shape" cx="25.0" cy="25.0" r="24.5" />
+    </symbol>
+    <symbol id="document" viewBox="0.0 0.0 51.0 51.0" preserveAspectRatio="none">
+      <path class="filled_shape" d="m49.98,0.79 -49.166,0.0 0.0,45.402 c15.92,12.45 30.4,-13.44 49.17,0.0 Z" />
+    </symbol>
+    <symbol id="io" viewBox="0.0 0.0 100.0 100.0" preserveAspectRatio="none">
+      <path class="filled_shape" d="m19.207,1.6 h79.414 l-17.192,97.297 h-79.414 Z" />
+    </symbol>
     <linearGradient id="shape_light" x2="0%" y2="100%">
       <stop offset="0%" stop-color="#F5F5F5" />
       <stop offset="100%" stop-color="#D8D8D8" />
     </linearGradient>
+    <symbol id="storage" viewBox="0.0 0.0 80.0 80.0" preserveAspectRatio="none">
+      <path class="filled_shape" d="m4.8122,67.74 v-53.769 c0.0,-3.2991 16.067,-5.9743 35.845,-5.9743 19.78,0.0 35.848,2.6752 35.848,5.9743 v53.769 c0.0,3.2925 -16.068,5.9743 -35.848,5.9743 -19.779,0.0 -35.845,-2.6818 -35.845,-5.9743 Z" />
+      <path class="filled_shape" d="m4.8122,13.97 4.779e-2,0.30672 0.13807,0.30272 0.22834,0.29872 0.31464,0.29344 0.40094,0.28944 0.48325,0.2828 0.56423,0.27744 0.64256,0.2708 0.71823,0.26416 0.79258,0.25752 0.86294,0.25096 0.9333,0.2416 0.99968,0.23496 1.0647,0.22568 1.1271,0.2164 1.1869,0.2084 1.2453,0.19784 1.301,0.1872 1.3555,0.17792 1.4046,0.16728 1.455,0.15536 1.5002,0.14336 1.5466,0.1328 1.5865,0.11952 1.6276,0.10752 1.6648,9.42e-2 1.7007,8.1e-2 1.7338,6.64e-2 1.7644,5.31e-2 1.7923,3.72e-2 1.8188,2.39e-2 1.8427,8.0e-3 c19.78,0.0 35.848,-2.6818 35.848,-5.9743" />
+    </symbol>
   </defs>
-  <path stroke-width="1.0" stroke="#000000" class="filled_shape" d="M31.5,28.0 L31.5,56.0 L31.5,68.5 L60.0,68.5 L70.0,68.5 L90.0,68.5 L98.5,68.5 L98.5,56.0 L98.5,42.0 L98.5,28.0 L98.5,15.5 L40.0,15.5 L31.5,15.5 Z" />
-  <path stroke-width="1.0" stroke="#000000" class="filled_shape" d="M71.5,84.0 L71.5,84.0 L71.5,96.5 L120.0,96.5 L128.5,96.5 L128.5,56.0 L128.5,43.5 L110.0,43.5 L101.5,43.5 L101.5,56.0 L101.5,71.5 L80.0,71.5 L71.5,71.5 Z" />
+  <path class="filled_shape" d="M31.5,28.0 L31.5,56.0 L31.5,68.5 L60.0,68.5 L70.0,68.5 L90.0,68.5 L98.5,68.5 L98.5,56.0 L98.5,42.0 L98.5,28.0 L98.5,15.5 L40.0,15.5 L31.5,15.5 Z" />
+  <path class="filled_shape" d="M71.5,84.0 L71.5,84.0 L71.5,96.5 L120.0,96.5 L128.5,96.5 L128.5,56.0 L128.5,43.5 L110.0,43.5 L101.5,43.5 L101.5,56.0 L101.5,71.5 L80.0,71.5 L71.5,71.5 Z" />
 </svg>
docimages/curvedCorner.svg view
@@ -9,29 +9,53 @@ }
 .filled_shape {
   fill: url(#shape_light);
+  stroke: #000000;
+  stroke-width: 1.0px;
 }
+.line_element {
+  fill: none;
+  stroke: #000000;
+  stroke-width: 1.0px;
+}
 .bullet {
   stroke-width: 1.0px;
   fill: #FFFFFF;
   stroke: #000000;
 }
+.arrow_head {
+  fill: #000000;
+  stroke: none;
+}
 </style>
   <defs>
+    <symbol id="circle" viewBox="0.0 0.0 50.0 50.0" preserveAspectRatio="none">
+      <circle class="filled_shape" cx="25.0" cy="25.0" r="24.5" />
+    </symbol>
+    <symbol id="document" viewBox="0.0 0.0 51.0 51.0" preserveAspectRatio="none">
+      <path class="filled_shape" d="m49.98,0.79 -49.166,0.0 0.0,45.402 c15.92,12.45 30.4,-13.44 49.17,0.0 Z" />
+    </symbol>
+    <symbol id="io" viewBox="0.0 0.0 100.0 100.0" preserveAspectRatio="none">
+      <path class="filled_shape" d="m19.207,1.6 h79.414 l-17.192,97.297 h-79.414 Z" />
+    </symbol>
     <linearGradient id="shape_light" x2="0%" y2="100%">
       <stop offset="0%" stop-color="#F5F5F5" />
       <stop offset="100%" stop-color="#D8D8D8" />
     </linearGradient>
+    <symbol id="storage" viewBox="0.0 0.0 80.0 80.0" preserveAspectRatio="none">
+      <path class="filled_shape" d="m4.8122,67.74 v-53.769 c0.0,-3.2991 16.067,-5.9743 35.845,-5.9743 19.78,0.0 35.848,2.6752 35.848,5.9743 v53.769 c0.0,3.2925 -16.068,5.9743 -35.848,5.9743 -19.779,0.0 -35.845,-2.6818 -35.845,-5.9743 Z" />
+      <path class="filled_shape" d="m4.8122,13.97 4.779e-2,0.30672 0.13807,0.30272 0.22834,0.29872 0.31464,0.29344 0.40094,0.28944 0.48325,0.2828 0.56423,0.27744 0.64256,0.2708 0.71823,0.26416 0.79258,0.25752 0.86294,0.25096 0.9333,0.2416 0.99968,0.23496 1.0647,0.22568 1.1271,0.2164 1.1869,0.2084 1.2453,0.19784 1.301,0.1872 1.3555,0.17792 1.4046,0.16728 1.455,0.15536 1.5002,0.14336 1.5466,0.1328 1.5865,0.11952 1.6276,0.10752 1.6648,9.42e-2 1.7007,8.1e-2 1.7338,6.64e-2 1.7644,5.31e-2 1.7923,3.72e-2 1.8188,2.39e-2 1.8427,8.0e-3 c19.78,0.0 35.848,-2.6818 35.848,-5.9743" />
+    </symbol>
   </defs>
-  <path stroke-width="1.0" stroke="#000000" class="filled_shape" d="M31.5,28.0 L31.5,28.0 L31.5,40.5 L50.0,40.5 L58.5,40.5 L58.5,28.0 L58.5,15.5 L40.0,15.5 S30.0,14.0 31.5,28.0 Z" />
-  <path stroke-width="1.0" stroke="#000000" class="filled_shape" d="M31.5,84.0 L31.5,84.0 L31.5,96.5 L50.0,96.5 S60.0,98.0 58.5,84.0 L58.5,84.0 L58.5,71.5 L40.0,71.5 S30.0,70.0 31.5,84.0 Z" />
-  <path stroke-width="1.0" stroke="#000000" class="filled_shape" d="M31.5,140.0 L31.5,140.0 S30.0,154.0 40.0,152.5 L50.0,152.5 S60.0,154.0 58.5,140.0 L58.5,140.0 S60.0,126.0 50.0,127.5 L40.0,127.5 S30.0,126.0 31.5,140.0 Z" />
-  <path stroke-width="1.0" stroke="#000000" class="filled_shape" d="M91.5,28.0 L91.5,28.0 L91.5,40.5 L110.0,40.5 L118.5,40.5 L118.5,28.0 S120.0,14.0 110.0,15.5 L100.0,15.5 L91.5,15.5 Z" />
-  <path stroke-width="1.0" stroke="#000000" class="filled_shape" d="M91.5,84.0 L91.5,84.0 L91.5,96.5 L110.0,96.5 L118.5,96.5 L118.5,84.0 S120.0,70.0 110.0,71.5 L100.0,71.5 S90.0,70.0 91.5,84.0 Z" />
-  <path stroke-width="1.0" stroke="#000000" class="filled_shape" d="M151.5,28.0 L151.5,28.0 S150.0,42.0 160.0,40.5 L170.0,40.5 L178.5,40.5 L178.5,28.0 L178.5,15.5 L160.0,15.5 L151.5,15.5 Z" />
-  <path stroke-width="1.0" stroke="#000000" class="filled_shape" d="M151.5,84.0 L151.5,84.0 S150.0,98.0 160.0,96.5 L170.0,96.5 S180.0,98.0 178.5,84.0 L178.5,84.0 L178.5,71.5 L160.0,71.5 S150.0,70.0 151.5,84.0 Z" />
-  <path stroke-width="1.0" stroke="#000000" class="filled_shape" d="M211.5,28.0 L211.5,28.0 L211.5,40.5 L230.0,40.5 L238.5,40.5 L238.5,28.0 L238.5,15.5 L220.0,15.5 S210.0,14.0 211.5,28.0 Z" />
-  <path stroke-width="1.0" stroke="#000000" class="filled_shape" d="M211.5,84.0 L211.5,84.0 L211.5,96.5 L230.0,96.5 S240.0,98.0 238.5,84.0 L238.5,84.0 S240.0,70.0 230.0,71.5 L220.0,71.5 S210.0,70.0 211.5,84.0 Z" />
-  <text class="" x="255.5" y="77.5">.</text>
-  <text class="" x="75.5" y="133.5">. </text>
-  <text class="" x="5.5" y="175.5">. </text>
+  <text x="5.5" y="175.5">. </text>
+  <text x="75.5" y="133.5">. </text>
+  <text x="255.5" y="77.5">.</text>
+  <path class="filled_shape" d="M31.5,28.0 L31.5,28.0 L31.5,40.5 L50.0,40.5 L58.5,40.5 L58.5,28.0 L58.5,15.5 L40.0,15.5 S30.0,14.0 31.5,28.0 Z" />
+  <path class="filled_shape" d="M31.5,84.0 L31.5,84.0 L31.5,96.5 L50.0,96.5 S60.0,98.0 58.5,84.0 L58.5,84.0 L58.5,71.5 L40.0,71.5 S30.0,70.0 31.5,84.0 Z" />
+  <path class="filled_shape" d="M31.5,140.0 L31.5,140.0 S30.0,154.0 40.0,152.5 L50.0,152.5 S60.0,154.0 58.5,140.0 L58.5,140.0 S60.0,126.0 50.0,127.5 L40.0,127.5 S30.0,126.0 31.5,140.0 Z" />
+  <path class="filled_shape" d="M91.5,28.0 L91.5,28.0 L91.5,40.5 L110.0,40.5 L118.5,40.5 L118.5,28.0 S120.0,14.0 110.0,15.5 L100.0,15.5 L91.5,15.5 Z" />
+  <path class="filled_shape" d="M91.5,84.0 L91.5,84.0 L91.5,96.5 L110.0,96.5 L118.5,96.5 L118.5,84.0 S120.0,70.0 110.0,71.5 L100.0,71.5 S90.0,70.0 91.5,84.0 Z" />
+  <path class="filled_shape" d="M151.5,28.0 L151.5,28.0 S150.0,42.0 160.0,40.5 L170.0,40.5 L178.5,40.5 L178.5,28.0 L178.5,15.5 L160.0,15.5 L151.5,15.5 Z" />
+  <path class="filled_shape" d="M151.5,84.0 L151.5,84.0 S150.0,98.0 160.0,96.5 L170.0,96.5 S180.0,98.0 178.5,84.0 L178.5,84.0 L178.5,71.5 L160.0,71.5 S150.0,70.0 151.5,84.0 Z" />
+  <path class="filled_shape" d="M211.5,28.0 L211.5,28.0 L211.5,40.5 L230.0,40.5 L238.5,40.5 L238.5,28.0 L238.5,15.5 L220.0,15.5 S210.0,14.0 211.5,28.0 Z" />
+  <path class="filled_shape" d="M211.5,84.0 L211.5,84.0 L211.5,96.5 L230.0,96.5 S240.0,98.0 238.5,84.0 L238.5,84.0 S240.0,70.0 230.0,71.5 L220.0,71.5 S210.0,70.0 211.5,84.0 Z" />
 </svg>
docimages/dashed_lines.svg view
@@ -9,22 +9,46 @@ }
 .filled_shape {
   fill: url(#shape_light);
+  stroke: #000000;
+  stroke-width: 1.0px;
 }
+.line_element {
+  fill: none;
+  stroke: #000000;
+  stroke-width: 1.0px;
+}
 .bullet {
   stroke-width: 1.0px;
   fill: #FFFFFF;
   stroke: #000000;
 }
+.arrow_head {
+  fill: #000000;
+  stroke: none;
+}
 </style>
   <defs>
+    <symbol id="circle" viewBox="0.0 0.0 50.0 50.0" preserveAspectRatio="none">
+      <circle class="filled_shape" cx="25.0" cy="25.0" r="24.5" />
+    </symbol>
+    <symbol id="document" viewBox="0.0 0.0 51.0 51.0" preserveAspectRatio="none">
+      <path class="filled_shape" d="m49.98,0.79 -49.166,0.0 0.0,45.402 c15.92,12.45 30.4,-13.44 49.17,0.0 Z" />
+    </symbol>
+    <symbol id="io" viewBox="0.0 0.0 100.0 100.0" preserveAspectRatio="none">
+      <path class="filled_shape" d="m19.207,1.6 h79.414 l-17.192,97.297 h-79.414 Z" />
+    </symbol>
     <linearGradient id="shape_light" x2="0%" y2="100%">
       <stop offset="0%" stop-color="#F5F5F5" />
       <stop offset="100%" stop-color="#D8D8D8" />
     </linearGradient>
+    <symbol id="storage" viewBox="0.0 0.0 80.0 80.0" preserveAspectRatio="none">
+      <path class="filled_shape" d="m4.8122,67.74 v-53.769 c0.0,-3.2991 16.067,-5.9743 35.845,-5.9743 19.78,0.0 35.848,2.6752 35.848,5.9743 v53.769 c0.0,3.2925 -16.068,5.9743 -35.848,5.9743 -19.779,0.0 -35.845,-2.6818 -35.845,-5.9743 Z" />
+      <path class="filled_shape" d="m4.8122,13.97 4.779e-2,0.30672 0.13807,0.30272 0.22834,0.29872 0.31464,0.29344 0.40094,0.28944 0.48325,0.2828 0.56423,0.27744 0.64256,0.2708 0.71823,0.26416 0.79258,0.25752 0.86294,0.25096 0.9333,0.2416 0.99968,0.23496 1.0647,0.22568 1.1271,0.2164 1.1869,0.2084 1.2453,0.19784 1.301,0.1872 1.3555,0.17792 1.4046,0.16728 1.455,0.15536 1.5002,0.14336 1.5466,0.1328 1.5865,0.11952 1.6276,0.10752 1.6648,9.42e-2 1.7007,8.1e-2 1.7338,6.64e-2 1.7644,5.31e-2 1.7923,3.72e-2 1.8188,2.39e-2 1.8427,8.0e-3 c19.78,0.0 35.848,-2.6818 35.848,-5.9743" />
+    </symbol>
   </defs>
-  <path stroke-width="1.0" stroke="#000000" fill="none" class="line_element" d="M20.0,112.0 L20.0,112.0 L20.0,56.0" />
-  <path stroke-width="1.0" stroke="#000000" fill="none" class="line_element" d="M20.0,14.0 L60.0,14.0" />
-  <path stroke-width="1.0" stroke="#000000" fill="none" class="line_element dashed_elem" d="M70.0,112.0 L30.0,112.0 L20.0,112.0" />
-  <path stroke-width="1.0" stroke="#000000" fill="none" class="line_element dashed_elem" d="M40.0,28.0 L100.0,28.0" />
-  <path stroke-width="1.0" stroke="#000000" fill="none" class="line_element dashed_elem" d="M90.0,84.0 L60.0,84.0 S50.0,84.0 50.0,70.0 L50.0,56.0" />
+  <path class="line_element" d="M20.0,112.0 L20.0,112.0 L20.0,56.0" />
+  <path class="line_element" d="M20.0,14.0 L60.0,14.0" />
+  <path class="line_element dashed_elem" d="M70.0,112.0 L30.0,112.0 L20.0,112.0" />
+  <path class="line_element dashed_elem" d="M40.0,28.0 L100.0,28.0" />
+  <path class="line_element dashed_elem" d="M90.0,84.0 L60.0,84.0 S50.0,84.0 50.0,70.0 L50.0,56.0" />
 </svg>
docimages/dashingClosed.svg view
@@ -9,21 +9,45 @@ }
 .filled_shape {
   fill: url(#shape_light);
+  stroke: #000000;
+  stroke-width: 1.0px;
 }
+.line_element {
+  fill: none;
+  stroke: #000000;
+  stroke-width: 1.0px;
+}
 .bullet {
   stroke-width: 1.0px;
   fill: #FFFFFF;
   stroke: #000000;
 }
+.arrow_head {
+  fill: #000000;
+  stroke: none;
+}
 </style>
   <defs>
+    <symbol id="circle" viewBox="0.0 0.0 50.0 50.0" preserveAspectRatio="none">
+      <circle class="filled_shape" cx="25.0" cy="25.0" r="24.5" />
+    </symbol>
+    <symbol id="document" viewBox="0.0 0.0 51.0 51.0" preserveAspectRatio="none">
+      <path class="filled_shape" d="m49.98,0.79 -49.166,0.0 0.0,45.402 c15.92,12.45 30.4,-13.44 49.17,0.0 Z" />
+    </symbol>
+    <symbol id="io" viewBox="0.0 0.0 100.0 100.0" preserveAspectRatio="none">
+      <path class="filled_shape" d="m19.207,1.6 h79.414 l-17.192,97.297 h-79.414 Z" />
+    </symbol>
     <linearGradient id="shape_light" x2="0%" y2="100%">
       <stop offset="0%" stop-color="#F5F5F5" />
       <stop offset="100%" stop-color="#D8D8D8" />
     </linearGradient>
+    <symbol id="storage" viewBox="0.0 0.0 80.0 80.0" preserveAspectRatio="none">
+      <path class="filled_shape" d="m4.8122,67.74 v-53.769 c0.0,-3.2991 16.067,-5.9743 35.845,-5.9743 19.78,0.0 35.848,2.6752 35.848,5.9743 v53.769 c0.0,3.2925 -16.068,5.9743 -35.848,5.9743 -19.779,0.0 -35.845,-2.6818 -35.845,-5.9743 Z" />
+      <path class="filled_shape" d="m4.8122,13.97 4.779e-2,0.30672 0.13807,0.30272 0.22834,0.29872 0.31464,0.29344 0.40094,0.28944 0.48325,0.2828 0.56423,0.27744 0.64256,0.2708 0.71823,0.26416 0.79258,0.25752 0.86294,0.25096 0.9333,0.2416 0.99968,0.23496 1.0647,0.22568 1.1271,0.2164 1.1869,0.2084 1.2453,0.19784 1.301,0.1872 1.3555,0.17792 1.4046,0.16728 1.455,0.15536 1.5002,0.14336 1.5466,0.1328 1.5865,0.11952 1.6276,0.10752 1.6648,9.42e-2 1.7007,8.1e-2 1.7338,6.64e-2 1.7644,5.31e-2 1.7923,3.72e-2 1.8188,2.39e-2 1.8427,8.0e-3 c19.78,0.0 35.848,-2.6818 35.848,-5.9743" />
+    </symbol>
   </defs>
-  <rect stroke-width="1.0" stroke="#000000" class="filled_shape" width="27.0" height="25.0" x="31.5" y="15.5" />
-  <rect stroke-width="1.0" stroke="#000000" class="filled_shape dashed_elem" width="27.0" height="25.0" x="91.5" y="15.5" />
-  <rect stroke-width="1.0" stroke="#000000" class="filled_shape dashed_elem" width="27.0" height="25.0" x="151.5" y="15.5" />
-  <rect stroke-width="1.0" stroke="#000000" class="filled_shape dashed_elem" width="27.0" height="25.0" x="211.5" y="15.5" />
+  <rect class="filled_shape" width="27.0" height="25.0" x="31.5" y="15.5" />
+  <rect class="filled_shape dashed_elem" width="27.0" height="25.0" x="91.5" y="15.5" />
+  <rect class="filled_shape dashed_elem" width="27.0" height="25.0" x="151.5" y="15.5" />
+  <rect class="filled_shape dashed_elem" width="27.0" height="25.0" x="211.5" y="15.5" />
 </svg>
+ docimages/deepStyleExample.svg view
@@ -0,0 +1,171 @@+<?xml version='1.0' ?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="865.0" height="327.0">
+  <style type="text/css">text {
+  font-family: Consolas , &quot;DejaVu Sans Mono&quot; , monospace;
+  font-size: 16.0px;
+}
+.dashed_elem {
+  stroke-dasharray: 4.0 , 3.0;
+}
+.filled_shape {
+  fill: url(#shape_light);
+  stroke: #000000;
+  stroke-width: 1.0px;
+}
+.line_element {
+  fill: none;
+  stroke: #000000;
+  stroke-width: 1.0px;
+}
+.bullet {
+  stroke-width: 1.0px;
+  fill: #FFFFFF;
+  stroke: #000000;
+}
+.arrow_head {
+  fill: #000000;
+  stroke: none;
+}
+.li .line_element {
+  stroke: #800080;
+}
+.li .arrow_head,
+.li text {
+  fill: #808080;
+}
+.lo .line_element {
+  stroke: #0000FF;
+}
+.lo .arrow_head,
+.lo text {
+  fill: #008000;
+}
+.lu .line_element {
+  stroke: #FF0000;
+}
+.lu .arrow_head,
+.lu text {
+  fill: #FFA500;
+}
+.ii .filled_shape {
+  fill: #DDDDFF;
+}
+.ii text {
+  fill: #0000FF;
+}
+.oo .filled_shape {
+  fill: #DDFFDD;
+}
+.oo text {
+  fill: #FFC0CB;
+}
+</style>
+  <defs>
+    <symbol id="circle" viewBox="0.0 0.0 50.0 50.0" preserveAspectRatio="none">
+      <circle class="filled_shape" cx="25.0" cy="25.0" r="24.5" />
+    </symbol>
+    <symbol id="document" viewBox="0.0 0.0 51.0 51.0" preserveAspectRatio="none">
+      <path class="filled_shape" d="m49.98,0.79 -49.166,0.0 0.0,45.402 c15.92,12.45 30.4,-13.44 49.17,0.0 Z" />
+    </symbol>
+    <symbol id="io" viewBox="0.0 0.0 100.0 100.0" preserveAspectRatio="none">
+      <path class="filled_shape" d="m19.207,1.6 h79.414 l-17.192,97.297 h-79.414 Z" />
+    </symbol>
+    <linearGradient id="shape_light" x2="0%" y2="100%">
+      <stop offset="0%" stop-color="#F5F5F5" />
+      <stop offset="100%" stop-color="#D8D8D8" />
+    </linearGradient>
+    <symbol id="storage" viewBox="0.0 0.0 80.0 80.0" preserveAspectRatio="none">
+      <path class="filled_shape" d="m4.8122,67.74 v-53.769 c0.0,-3.2991 16.067,-5.9743 35.845,-5.9743 19.78,0.0 35.848,2.6752 35.848,5.9743 v53.769 c0.0,3.2925 -16.068,5.9743 -35.848,5.9743 -19.779,0.0 -35.845,-2.6818 -35.845,-5.9743 Z" />
+      <path class="filled_shape" d="m4.8122,13.97 4.779e-2,0.30672 0.13807,0.30272 0.22834,0.29872 0.31464,0.29344 0.40094,0.28944 0.48325,0.2828 0.56423,0.27744 0.64256,0.2708 0.71823,0.26416 0.79258,0.25752 0.86294,0.25096 0.9333,0.2416 0.99968,0.23496 1.0647,0.22568 1.1271,0.2164 1.1869,0.2084 1.2453,0.19784 1.301,0.1872 1.3555,0.17792 1.4046,0.16728 1.455,0.15536 1.5002,0.14336 1.5466,0.1328 1.5865,0.11952 1.6276,0.10752 1.6648,9.42e-2 1.7007,8.1e-2 1.7338,6.64e-2 1.7644,5.31e-2 1.7923,3.72e-2 1.8188,2.39e-2 1.8427,8.0e-3 c19.78,0.0 35.848,-2.6818 35.848,-5.9743" />
+    </symbol>
+  </defs>
+  <text x="585.5" y="21.5">. </text>
+  <text x="605.5" y="133.5">e0 </text>
+  <text x="845.5" y="133.5">.</text>
+  <g class="line_element">
+    <path d="M680.0,140.0 L680.0,140.0 L580.0,140.0 L570.0,140.0" />
+    <path class="arrow_head" d="M680.0,133.0 L690.0,140.0 L680.0,147.0 Z" />
+  </g>
+  <g class="li">
+    <path class="filled_shape li" d="M21.5,28.0 L21.5,280.0 S20.0,294.0 30.0,292.5 L560.0,292.5 S570.0,294.0 568.5,280.0 L568.5,154.0 L568.5,140.0 L568.5,28.0 S570.0,14.0 560.0,15.5 L30.0,15.5 S20.0,14.0 21.5,28.0 Z" />
+    <g class="lo">
+      <path class="filled_shape lo" d="M71.5,56.0 L71.5,70.0 L71.5,82.5 L110.0,82.5 L121.5,82.5 L121.5,98.0 L121.5,112.0 L121.5,127.5 L80.0,127.5 L71.5,127.5 L71.5,140.0 L71.5,152.5 L110.0,152.5 S120.0,154.0 121.5,168.0 L121.5,182.0 L121.5,194.5 L320.0,194.5 L330.0,194.5 L350.0,194.5 S360.0,196.0 358.5,182.0 L358.5,154.0 L358.5,140.0 L358.5,84.0 L358.5,70.0 L358.5,56.0 S360.0,42.0 350.0,43.5 L80.0,43.5 S70.0,42.0 71.5,56.0 Z" />
+      <g class="lu">
+        <path class="filled_shape lu" d="M201.5,154.0 L201.5,154.0 S200.0,168.0 210.0,166.5 L220.0,166.5 L230.0,166.5 L280.0,166.5 S290.0,168.0 288.5,154.0 L288.5,154.0 S290.0,140.0 280.0,141.5 L210.0,141.5 S200.0,140.0 201.5,154.0 Z" />
+        <text x="215.5" y="161.5">s3</text>
+      </g>
+      <g>
+        <path class="filled_shape" d="M191.5,70.0 L191.5,70.0 S190.0,84.0 200.0,82.5 L220.0,82.5 L230.0,82.5 L270.0,82.5 S280.0,84.0 278.5,70.0 L278.5,70.0 S280.0,56.0 270.0,57.5 L200.0,57.5 S190.0,56.0 191.5,70.0 Z" />
+        <text x="215.5" y="77.5">s2 </text>
+      </g>
+      <path class="line_element" d="M120.0,112.0 L120.0,112.0" />
+      <g class="line_element">
+        <path d="M120.0,112.0 L120.0,112.0 L210.0,112.0 S220.0,112.0 220.0,126.0 L220.0,126.0" />
+        <path class="arrow_head" d="M215.0,126.0 L225.0,126.0 L220.0,140.0 Z" />
+      </g>
+      <g class="line_element">
+        <path d="M180.0,70.0 L180.0,70.0 L150.0,70.0 L140.0,70.0" />
+        <path class="arrow_head" d="M180.0,63.0 L190.0,70.0 L180.0,77.0 Z" />
+        <circle class="bullet" cx="140.0" cy="70.0" r="3.0" />
+      </g>
+      <g class="line_element">
+        <path d="M230.0,126.0 L230.0,126.0 L230.0,98.0 L230.0,84.0" />
+        <path class="arrow_head" d="M225.0,126.0 L235.0,126.0 L230.0,140.0 Z" />
+      </g>
+      <path class="line_element" d="M230.0,168.0 L230.0,168.0" />
+      <g class="line_element">
+        <path d="M230.0,168.0 L230.0,168.0 S230.0,182.0 220.0,182.0 L140.0,182.0 L130.0,182.0" />
+        <path class="arrow_head" d="M130.0,175.0 L120.0,182.0 L130.0,189.0 Z" />
+      </g>
+      <path class="line_element" d="M360.0,140.0 L360.0,140.0" />
+      <path class="line_element" d="M360.0,140.0 L360.0,140.0 L360.0,84.0 L360.0,70.0" />
+      <text x="75.5" y="63.5">s1 </text>
+      <text x="245.5" y="119.5">e1 </text>
+      <text x="155.5" y="175.5">e2 </text>
+    </g>
+    <g class="oo">
+      <path class="filled_shape oo" d="M71.5,168.0 L71.5,182.0 S70.0,196.0 80.0,194.5 L80.0,194.5 L90.0,194.5 L110.0,194.5 L118.5,194.5 L118.5,168.0 S120.0,154.0 110.0,155.5 L80.0,155.5 L71.5,155.5 Z" />
+      <text x="85.5" y="175.5">o5 </text>
+    </g>
+    <g class="ii">
+      <path class="filled_shape ii" d="M71.5,98.0 L71.5,112.0 L71.5,124.5 L110.0,124.5 L118.5,124.5 L118.5,112.0 L118.5,98.0 L118.5,85.5 L80.0,85.5 L71.5,85.5 Z" />
+      <text x="85.5" y="105.5">i4 </text>
+    </g>
+    <g>
+      <path class="filled_shape" d="M451.5,70.0 L451.5,70.0 S450.0,84.0 460.0,82.5 L530.0,82.5 S540.0,84.0 538.5,70.0 L538.5,70.0 S540.0,56.0 530.0,57.5 L460.0,57.5 S450.0,56.0 451.5,70.0 Z" />
+      <text x="475.5" y="77.5">s10 </text>
+    </g>
+    <g>
+      <path class="filled_shape" d="M51.5,266.0 L51.5,266.0 S50.0,280.0 60.0,278.5 L130.0,278.5 S140.0,280.0 138.5,266.0 L138.5,266.0 S140.0,252.0 130.0,253.5 L60.0,253.5 S50.0,252.0 51.5,266.0 Z" />
+      <text x="75.5" y="273.5">s20 </text>
+    </g>
+    <path class="line_element" d="M90.0,196.0 L90.0,196.0 L110.0,196.0 L120.0,196.0" />
+    <g class="line_element">
+      <path d="M90.0,238.0 L90.0,238.0 L90.0,210.0 L90.0,196.0" />
+      <path class="arrow_head" d="M85.0,238.0 L95.0,238.0 L90.0,252.0 Z" />
+    </g>
+    <path class="line_element" d="M120.0,196.0 L120.0,196.0 L320.0,196.0 L330.0,196.0" />
+    <path class="line_element" d="M330.0,196.0 L330.0,196.0" />
+    <g class="line_element">
+      <path d="M330.0,196.0 L330.0,196.0 L330.0,210.0 S330.0,224.0 340.0,224.0 L380.0,224.0 S390.0,224.0 390.0,210.0 L390.0,196.0 S390.0,182.0 380.0,182.0 L380.0,182.0 L370.0,182.0" />
+      <path class="arrow_head" d="M370.0,175.0 L360.0,182.0 L370.0,189.0 Z" />
+    </g>
+    <path class="line_element" d="M330.0,196.0 L330.0,196.0 L350.0,196.0 S360.0,196.0 360.0,182.0 L360.0,154.0 L360.0,140.0" />
+    <g class="line_element">
+      <path d="M360.0,70.0 L360.0,70.0 L430.0,70.0 L440.0,70.0" />
+      <path class="arrow_head" d="M440.0,63.0 L450.0,70.0 L440.0,77.0 Z" />
+    </g>
+    <g class="line_element">
+      <path d="M360.0,140.0 L360.0,140.0 L470.0,140.0 S480.0,140.0 480.0,126.0 L480.0,112.0 L480.0,98.0" />
+      <path class="arrow_head" d="M475.0,98.0 L485.0,98.0 L480.0,84.0 Z" />
+    </g>
+    <text x="25.5" y="35.5">s100 </text>
+    <text x="385.5" y="63.5">e1 </text>
+    <text x="375.5" y="133.5">ealarm </text>
+    <text x="405.5" y="217.5">eReset </text>
+  </g>
+  <g>
+    <path class="filled_shape" d="M691.5,140.0 L691.5,140.0 S690.0,154.0 700.0,152.5 L820.0,152.5 S830.0,154.0 828.5,140.0 L828.5,140.0 S830.0,126.0 820.0,127.5 L700.0,127.5 S690.0,126.0 691.5,140.0 Z" />
+    <text x="735.5" y="147.5">s50 </text>
+  </g>
+</svg>
+ docimages/shapeExample.svg view
@@ -0,0 +1,77 @@+<?xml version='1.0' ?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="495.0" height="215.0">
+  <style type="text/css">text {
+  font-family: Consolas , &quot;DejaVu Sans Mono&quot; , monospace;
+  font-size: 16.0px;
+}
+.dashed_elem {
+  stroke-dasharray: 4.0 , 3.0;
+}
+.filled_shape {
+  fill: url(#shape_light);
+  stroke: #000000;
+  stroke-width: 1.0px;
+}
+.line_element {
+  fill: none;
+  stroke: #000000;
+  stroke-width: 1.0px;
+}
+.bullet {
+  stroke-width: 1.0px;
+  fill: #FFFFFF;
+  stroke: #000000;
+}
+.arrow_head {
+  fill: #000000;
+  stroke: none;
+}
+.circle .filled_shape {
+  shape: circle;
+}
+.document .filled_shape {
+  shape: document;
+}
+.storage .filled_shape {
+  shape: storage;
+}
+.io .filled_shape {
+  shape: io;
+}
+</style>
+  <defs>
+    <symbol id="circle" viewBox="0.0 0.0 50.0 50.0" preserveAspectRatio="none">
+      <circle class="filled_shape" cx="25.0" cy="25.0" r="24.5" />
+    </symbol>
+    <symbol id="document" viewBox="0.0 0.0 51.0 51.0" preserveAspectRatio="none">
+      <path class="filled_shape" d="m49.98,0.79 -49.166,0.0 0.0,45.402 c15.92,12.45 30.4,-13.44 49.17,0.0 Z" />
+    </symbol>
+    <symbol id="io" viewBox="0.0 0.0 100.0 100.0" preserveAspectRatio="none">
+      <path class="filled_shape" d="m19.207,1.6 h79.414 l-17.192,97.297 h-79.414 Z" />
+    </symbol>
+    <linearGradient id="shape_light" x2="0%" y2="100%">
+      <stop offset="0%" stop-color="#F5F5F5" />
+      <stop offset="100%" stop-color="#D8D8D8" />
+    </linearGradient>
+    <symbol id="storage" viewBox="0.0 0.0 80.0 80.0" preserveAspectRatio="none">
+      <path class="filled_shape" d="m4.8122,67.74 v-53.769 c0.0,-3.2991 16.067,-5.9743 35.845,-5.9743 19.78,0.0 35.848,2.6752 35.848,5.9743 v53.769 c0.0,3.2925 -16.068,5.9743 -35.848,5.9743 -19.779,0.0 -35.845,-2.6818 -35.845,-5.9743 Z" />
+      <path class="filled_shape" d="m4.8122,13.97 4.779e-2,0.30672 0.13807,0.30272 0.22834,0.29872 0.31464,0.29344 0.40094,0.28944 0.48325,0.2828 0.56423,0.27744 0.64256,0.2708 0.71823,0.26416 0.79258,0.25752 0.86294,0.25096 0.9333,0.2416 0.99968,0.23496 1.0647,0.22568 1.1271,0.2164 1.1869,0.2084 1.2453,0.19784 1.301,0.1872 1.3555,0.17792 1.4046,0.16728 1.455,0.15536 1.5002,0.14336 1.5466,0.1328 1.5865,0.11952 1.6276,0.10752 1.6648,9.42e-2 1.7007,8.1e-2 1.7338,6.64e-2 1.7644,5.31e-2 1.7923,3.72e-2 1.8188,2.39e-2 1.8427,8.0e-3 c19.78,0.0 35.848,-2.6818 35.848,-5.9743" />
+    </symbol>
+  </defs>
+  <g class="circle">
+    <use x="21.5" y="15.5" width="97.0" height="67.0" xlink:href="#circle" />
+    <text x="35.5" y="49.5">circle </text>
+  </g>
+  <g class="document">
+    <use x="21.5" y="113.5" width="107.0" height="67.0" xlink:href="#document" />
+    <text x="25.5" y="133.5">document </text>
+  </g>
+  <g class="io">
+    <use x="151.5" y="15.5" width="107.0" height="67.0" xlink:href="#io" />
+    <text x="195.5" y="63.5">io </text>
+  </g>
+  <g class="storage">
+    <use x="161.5" y="113.5" width="107.0" height="67.0" xlink:href="#storage" />
+    <text x="175.5" y="161.5">storage </text>
+  </g>
+</svg>
docimages/simple_lines.svg view
@@ -9,22 +9,46 @@ }
 .filled_shape {
   fill: url(#shape_light);
+  stroke: #000000;
+  stroke-width: 1.0px;
 }
+.line_element {
+  fill: none;
+  stroke: #000000;
+  stroke-width: 1.0px;
+}
 .bullet {
   stroke-width: 1.0px;
   fill: #FFFFFF;
   stroke: #000000;
 }
+.arrow_head {
+  fill: #000000;
+  stroke: none;
+}
 </style>
   <defs>
+    <symbol id="circle" viewBox="0.0 0.0 50.0 50.0" preserveAspectRatio="none">
+      <circle class="filled_shape" cx="25.0" cy="25.0" r="24.5" />
+    </symbol>
+    <symbol id="document" viewBox="0.0 0.0 51.0 51.0" preserveAspectRatio="none">
+      <path class="filled_shape" d="m49.98,0.79 -49.166,0.0 0.0,45.402 c15.92,12.45 30.4,-13.44 49.17,0.0 Z" />
+    </symbol>
+    <symbol id="io" viewBox="0.0 0.0 100.0 100.0" preserveAspectRatio="none">
+      <path class="filled_shape" d="m19.207,1.6 h79.414 l-17.192,97.297 h-79.414 Z" />
+    </symbol>
     <linearGradient id="shape_light" x2="0%" y2="100%">
       <stop offset="0%" stop-color="#F5F5F5" />
       <stop offset="100%" stop-color="#D8D8D8" />
     </linearGradient>
+    <symbol id="storage" viewBox="0.0 0.0 80.0 80.0" preserveAspectRatio="none">
+      <path class="filled_shape" d="m4.8122,67.74 v-53.769 c0.0,-3.2991 16.067,-5.9743 35.845,-5.9743 19.78,0.0 35.848,2.6752 35.848,5.9743 v53.769 c0.0,3.2925 -16.068,5.9743 -35.848,5.9743 -19.779,0.0 -35.845,-2.6818 -35.845,-5.9743 Z" />
+      <path class="filled_shape" d="m4.8122,13.97 4.779e-2,0.30672 0.13807,0.30272 0.22834,0.29872 0.31464,0.29344 0.40094,0.28944 0.48325,0.2828 0.56423,0.27744 0.64256,0.2708 0.71823,0.26416 0.79258,0.25752 0.86294,0.25096 0.9333,0.2416 0.99968,0.23496 1.0647,0.22568 1.1271,0.2164 1.1869,0.2084 1.2453,0.19784 1.301,0.1872 1.3555,0.17792 1.4046,0.16728 1.455,0.15536 1.5002,0.14336 1.5466,0.1328 1.5865,0.11952 1.6276,0.10752 1.6648,9.42e-2 1.7007,8.1e-2 1.7338,6.64e-2 1.7644,5.31e-2 1.7923,3.72e-2 1.8188,2.39e-2 1.8427,8.0e-3 c19.78,0.0 35.848,-2.6818 35.848,-5.9743" />
+    </symbol>
   </defs>
-  <path stroke-width="1.0" stroke="#000000" fill="none" class="line_element" d="M20.0,112.0 L20.0,112.0 L20.0,56.0" />
-  <path stroke-width="1.0" stroke="#000000" fill="none" class="line_element" d="M20.0,14.0 L60.0,14.0" />
-  <path stroke-width="1.0" stroke="#000000" fill="none" class="line_element" d="M70.0,112.0 L30.0,112.0 L20.0,112.0" />
-  <path stroke-width="1.0" stroke="#000000" fill="none" class="line_element" d="M40.0,28.0 L100.0,28.0" />
-  <path stroke-width="1.0" stroke="#000000" fill="none" class="line_element" d="M90.0,84.0 L60.0,84.0 S50.0,84.0 50.0,70.0 L50.0,56.0" />
+  <path class="line_element" d="M20.0,112.0 L20.0,112.0 L20.0,56.0" />
+  <path class="line_element" d="M20.0,14.0 L60.0,14.0" />
+  <path class="line_element" d="M70.0,112.0 L30.0,112.0 L20.0,112.0" />
+  <path class="line_element" d="M40.0,28.0 L100.0,28.0" />
+  <path class="line_element" d="M90.0,84.0 L60.0,84.0 S50.0,84.0 50.0,70.0 L50.0,56.0" />
 </svg>
docimages/styleExample.svg view
@@ -9,50 +9,80 @@ }
 .filled_shape {
   fill: url(#shape_light);
+  stroke: #000000;
+  stroke-width: 1.0px;
 }
+.line_element {
+  fill: none;
+  stroke: #000000;
+  stroke-width: 1.0px;
+}
 .bullet {
   stroke-width: 1.0px;
   fill: #FFFFFF;
   stroke: #000000;
 }
-.dst {
-  stroke: #FFAAAA;
-  stroke-width: 3.0px;
+.arrow_head {
+  fill: #000000;
+  stroke: none;
 }
 .src {
   fill: #AAAAFF;
 }
+.dst {
+  stroke: #FFAAAA;
+  stroke-width: 3.0px;
+}
 </style>
   <defs>
+    <symbol id="circle" viewBox="0.0 0.0 50.0 50.0" preserveAspectRatio="none">
+      <circle class="filled_shape" cx="25.0" cy="25.0" r="24.5" />
+    </symbol>
+    <symbol id="document" viewBox="0.0 0.0 51.0 51.0" preserveAspectRatio="none">
+      <path class="filled_shape" d="m49.98,0.79 -49.166,0.0 0.0,45.402 c15.92,12.45 30.4,-13.44 49.17,0.0 Z" />
+    </symbol>
+    <symbol id="io" viewBox="0.0 0.0 100.0 100.0" preserveAspectRatio="none">
+      <path class="filled_shape" d="m19.207,1.6 h79.414 l-17.192,97.297 h-79.414 Z" />
+    </symbol>
     <linearGradient id="shape_light" x2="0%" y2="100%">
       <stop offset="0%" stop-color="#F5F5F5" />
       <stop offset="100%" stop-color="#D8D8D8" />
     </linearGradient>
+    <symbol id="storage" viewBox="0.0 0.0 80.0 80.0" preserveAspectRatio="none">
+      <path class="filled_shape" d="m4.8122,67.74 v-53.769 c0.0,-3.2991 16.067,-5.9743 35.845,-5.9743 19.78,0.0 35.848,2.6752 35.848,5.9743 v53.769 c0.0,3.2925 -16.068,5.9743 -35.848,5.9743 -19.779,0.0 -35.845,-2.6818 -35.845,-5.9743 Z" />
+      <path class="filled_shape" d="m4.8122,13.97 4.779e-2,0.30672 0.13807,0.30272 0.22834,0.29872 0.31464,0.29344 0.40094,0.28944 0.48325,0.2828 0.56423,0.27744 0.64256,0.2708 0.71823,0.26416 0.79258,0.25752 0.86294,0.25096 0.9333,0.2416 0.99968,0.23496 1.0647,0.22568 1.1271,0.2164 1.1869,0.2084 1.2453,0.19784 1.301,0.1872 1.3555,0.17792 1.4046,0.16728 1.455,0.15536 1.5002,0.14336 1.5466,0.1328 1.5865,0.11952 1.6276,0.10752 1.6648,9.42e-2 1.7007,8.1e-2 1.7338,6.64e-2 1.7644,5.31e-2 1.7923,3.72e-2 1.8188,2.39e-2 1.8427,8.0e-3 c19.78,0.0 35.848,-2.6818 35.848,-5.9743" />
+    </symbol>
   </defs>
-  <path stroke-width="1.0" stroke="#000000" class="filled_shape src" d="M21.5,28.0 L21.5,42.0 L21.5,54.5 L100.0,54.5 L108.5,54.5 L108.5,42.0 L108.5,28.0 L108.5,15.5 L30.0,15.5 L21.5,15.5 Z" />
-  <rect stroke-width="1.0" stroke="#000000" class="filled_shape dst" width="67.0" height="39.0" x="21.5" y="85.5" />
-  <g stroke-width="1.0" stroke="#000000" class="filled_shape">
-    <path class="" d="M131.5,84.0 L131.5,84.0 L131.5,96.5 L200.0,96.5 L208.5,96.5 L208.5,84.0 L208.5,71.5 L140.0,71.5 L131.5,71.5 Z" />
-    <circle class="bullet" cx="208.5" cy="71.5" r="3.0" />
+  <g class="line_element">
+    <path d="M200.0,28.0 L200.0,28.0 L120.0,28.0 L110.0,28.0" />
+    <path class="arrow_head" d="M200.0,21.0 L210.0,28.0 L200.0,35.0 Z" />
   </g>
-  <path stroke-width="1.0" stroke="#000000" class="filled_shape" d="M211.5,28.0 L211.5,28.0 S210.0,42.0 220.0,40.5 L240.0,40.5 L250.0,40.5 L290.0,40.5 S300.0,42.0 298.5,28.0 L298.5,28.0 L298.5,15.5 L220.0,15.5 L211.5,15.5 Z" />
-  <g stroke-width="1.0" stroke="#000000" fill="none" class="line_element">
-    <path class="" d="M200.0,28.0 L200.0,28.0 L120.0,28.0 L110.0,28.0" />
-    <path stroke-width="0.0" stroke="none" fill="#000000" class="" d="M200.0,21.0 L210.0,28.0 L200.0,35.0 Z" />
+  <path class="line_element" d="M250.0,42.0 L250.0,42.0" />
+  <g class="line_element">
+    <path d="M250.0,42.0 L250.0,42.0 L250.0,56.0 S250.0,70.0 240.0,70.0 L230.0,70.0 L220.0,70.0" />
+    <path class="arrow_head" d="M220.0,63.0 L210.0,70.0 L220.0,77.0 Z" />
   </g>
-  <path stroke-width="1.0" stroke="#000000" fill="none" class="line_element" d="M250.0,42.0 L250.0,42.0" />
-  <g stroke-width="1.0" stroke="#000000" fill="none" class="line_element">
-    <path class="" d="M250.0,42.0 L250.0,42.0 L250.0,56.0 S250.0,70.0 240.0,70.0 L230.0,70.0 L220.0,70.0" />
-    <path stroke-width="0.0" stroke="none" fill="#000000" class="" d="M220.0,63.0 L210.0,70.0 L220.0,77.0 Z" />
+  <g class="src">
+    <path class="filled_shape src" d="M21.5,28.0 L21.5,42.0 L21.5,54.5 L100.0,54.5 L108.5,54.5 L108.5,42.0 L108.5,28.0 L108.5,15.5 L30.0,15.5 L21.5,15.5 Z" />
+    <text x="35.5" y="35.5">Source </text>
   </g>
-  <g stroke-width="1.0" stroke="#000000" fill="none" class="line_element">
-    <path class="" d="M120.0,84.0 L110.0,84.0 L100.0,84.0" />
-    <path stroke-width="0.0" stroke="none" fill="#000000" class="" d="M100.0,77.0 L90.0,84.0 L100.0,91.0 Z" />
+  <g class="dst">
+    <rect class="filled_shape dst" width="67.0" height="39.0" x="21.5" y="85.5" />
+    <text x="35.5" y="105.5">Dest </text>
   </g>
-  <text class="" x="35.5" y="35.5">Source </text>
-  <text class="" x="225.5" y="35.5">op1 </text>
-  <text class="" x="95.5" y="49.5"></text>
-  <text class="" x="145.5" y="91.5">op2 </text>
-  <text class="" x="35.5" y="105.5">Dest </text>
-  <text class="" x="85.5" y="119.5"></text>
+  <g class="line_element">
+    <path d="M120.0,84.0 L110.0,84.0 L100.0,84.0" />
+    <path class="arrow_head" d="M100.0,77.0 L90.0,84.0 L100.0,91.0 Z" />
+  </g>
+  <g>
+    <g class="filled_shape">
+      <path d="M131.5,84.0 L131.5,84.0 L131.5,96.5 L200.0,96.5 L208.5,96.5 L208.5,84.0 L208.5,71.5 L140.0,71.5 L131.5,71.5 Z" />
+      <circle class="bullet" cx="208.5" cy="71.5" r="3.0" />
+    </g>
+    <text x="145.5" y="91.5">op2 </text>
+  </g>
+  <g>
+    <path class="filled_shape" d="M211.5,28.0 L211.5,28.0 S210.0,42.0 220.0,40.5 L240.0,40.5 L250.0,40.5 L290.0,40.5 S300.0,42.0 298.5,28.0 L298.5,28.0 L298.5,15.5 L220.0,15.5 L211.5,15.5 Z" />
+    <text x="225.5" y="35.5">op1 </text>
+  </g>
 </svg>
exec-src/asciidiagram.hs view
@@ -17,6 +17,7 @@                       , replaceExtension                       , takeExtension ) +import Graphics.Svg( Document, loadSvgFile, saveXmlFile ) import Graphics.Rasterific.Svg( loadCreateFontCache ) import Graphics.Text.TrueType( FontCache ) import Codec.Picture( writePng )@@ -32,32 +33,59 @@                           , info                           , long                           , metavar+                          , optional                           , progDesc+                          , short                           , str+                          , strOption                           , switch                           )+import Graphics.Rasterific.Svg( renderSvgDocument+                              , pdfOfSvgDocument ) import Text.AsciiDiagram +data Mode+  = Convert !(FilePath, FilePath)+  | DumpLibrary !FilePath+ data Options = Options-  { _inputFile  :: !FilePath-  , _outputFile :: !FilePath-  , _verbose    :: !Bool-  , _format     :: !(Maybe Format)+  { _workingMode :: !Mode+  , _verbose     :: !Bool+  , _withLibrary :: !(Maybe FilePath)+  , _format      :: !(Maybe Format)   }  data Format = FormatSvg | FormatPng | FormatPdf -argParser :: Parser Options-argParser = Options-  <$> ( argument str-            (metavar "INPUTFILE"-            <> help "Text file of the Ascii diagram to parse."))-  <*> ( argument str+ioParser :: Parser (String, String)+ioParser = (,)+    <$> argument str+          (metavar "INPUTFILE"+          <> help "Text file of the Ascii diagram to parse.")+    <*> (argument str             (metavar "OUTPUTFILE"             <> help ("Output file name, same as input with"                     <> " different extension if unspecified."))-        <|> pure "" )+        <|> pure "")++modeParser :: Parser Mode+modeParser = (Convert <$> ioParser) <|> (DumpLibrary <$> dumpParser)+  where +    dumpParser = strOption +      ( long "dump-library"+      <> short 'd'+      <> metavar "FILENAME"+      <> help "Dump the default shape library & styles in an SVG document") ++argParser :: Parser Options+argParser = Options+  <$> modeParser   <*> ( switch (long "verbose" <> help "Display more information") )+  <*> ( optional $ strOption+            ( long "with-library"+            <> short 'l'+            <> metavar "LIBRARY_FILENAME"+            <> help "Use a custom shape & style library instead of the default one") )   <*> ( flag Nothing (Just FormatSvg)             (  long "svg"             <> help "Force the use of the SVG format (deduced from extension otherwise)")@@ -88,39 +116,63 @@   tempDir <- getTemporaryDirectory    loadCreateFontCache $ tempDir </> "asciidiagram-fonty-fontcache" -runConversion :: Options -> IO ()-runConversion opt = do-  verbose . putStrLn $ "Loading file " ++ _inputFile opt-  inputData <- STIO.readFile $ _inputFile opt++loadLibrary :: Options -> IO Document+loadLibrary opt = case _withLibrary opt of+   Nothing -> return defaultLib+   Just p -> loadLib p+  where+    defaultLib = defaultLibrary defaultGridSize+    loadLib p = do+      f <- loadSvgFile p+      case f of+        Just doc -> return doc+        Nothing -> do+          putStrLn "Invalid library file, using default lib"+          return defaultLib ++runConversion :: Options -> FilePath -> FilePath -> IO ()+runConversion opt inputFile outputFile = do+  verbose . putStrLn $ "Loading file " ++ inputFile+  inputData <- STIO.readFile inputFile+  lib <- loadLibrary opt   let diag = parseAsciiDiagram inputData-      format = _format opt <|> (pure . formatOfOuputFilename $ _outputFile opt)+      svg = svgOfDiagramAtSize defaultGridSize lib diag+      format = _format opt <|> (pure $ formatOfOuputFilename outputFile)   case format of-    Nothing -> saveDoc diag-    Just FormatSvg -> saveDoc diag-    Just FormatPng -> savePng diag-    Just FormatPdf -> savePdf diag+    Nothing -> saveDoc svg+    Just FormatSvg -> saveDoc svg+    Just FormatPng -> savePng svg+    Just FormatPdf -> savePdf svg   where     verbose = when $ _verbose opt-    saveDoc diag = do-      verbose . putStrLn $ "Writing SVG file " ++ _outputFile opt-      saveAsciiDiagramAsSvg (savingPath "svg") diag+    saveDoc svg = do+      verbose . putStrLn $ "Writing SVG file " ++ outputFile+      saveXmlFile (savingPath "svg") svg -    savingPath ext = case _outputFile opt of-      "" -> replaceExtension (_inputFile opt) ext+    savingPath ext = case outputFile of+      "" -> replaceExtension inputFile ext       p -> p -    savePdf diag = do+    savePdf svg = do       cache <- getFontCache  $ _verbose opt-      verbose . putStrLn $ "Writing PDF file " ++ _outputFile opt-      pdf <- pdfOfDiagram cache diag+      verbose . putStrLn $ "Writing PDF file " ++ outputFile+      (pdf, _) <- pdfOfSvgDocument cache Nothing 96 svg       LB.writeFile (savingPath "pdf") pdf -    savePng diag = do+    savePng svg = do       cache <- getFontCache  $ _verbose opt-      verbose . putStrLn $ "Writing PNG file " ++ _outputFile opt-      img <- imageOfDiagram cache diag+      verbose . putStrLn $ "Writing PNG file " ++ outputFile+      (img, _) <- renderSvgDocument cache Nothing 96 svg       writePng (savingPath "png") img +dumpLibrary :: FilePath -> IO ()+dumpLibrary path =+  saveXmlFile path $ defaultLibrary defaultGridSize+ main :: IO ()-main = execParser progOptions >>= runConversion+main = execParser progOptions >>= \opts ->+  case _workingMode opts of+    Convert (i, o) -> runConversion opts i o+    DumpLibrary p -> dumpLibrary p 
src/Text/AsciiDiagram.hs view
@@ -15,7 +15,7 @@ -- +---------+     |         | -- |{flat}   |     +--+------\/ -- \\---*-----\/\<=======\/--- ::: .flat { fill: #DDD; }+-- ::: .flat .filled_shape { fill: #DDD; } -- @ -- <<docimages/baseExample.svg>> -- @@ -52,9 +52,12 @@     -- ** Styles     -- $styledoc -    -- * Usage example-    -- $example+    -- ** Hierarchical styles+    -- $hierarchicalDoc +    -- ** Shapes+    -- $shapeDoc+     -- * Functions     svgOfDiagram   , parseAsciiDiagram@@ -70,6 +73,8 @@   , imageOfDiagramAtSize   , pdfOfDiagramAtSize +    -- * Library+  , defaultLibrary      -- * Document description   , Diagram( .. ) @@ -90,7 +95,6 @@ import Data.Monoid( (<>)) import Control.Monad( forM_ ) import Control.Monad.ST( runST )-import Control.Monad.State.Strict( runState, put, get ) import Data.Function( on ) import Data.List( partition, sortBy ) import qualified Data.ByteString.Lazy as LB@@ -154,27 +158,15 @@        VU.unsafeFreeze emptyBoard -data HorizontalPoints-  = WithHorizontalSegments-  | WithoutHorizontalSegments-  deriving Eq -allowsHorizontal :: HorizontalPoints -> Bool-allowsHorizontal WithHorizontalSegments = True-allowsHorizontal WithoutHorizontalSegments = False--pointsOfShape :: F.Foldable f => HorizontalPoints -> f Shape -> [Point]-pointsOfShape horizInfo = F.concatMap (F.concatMap go . shapeElements) where-  withHorizontal = allowsHorizontal horizInfo-+pointsOfShape :: F.Foldable f => f Shape -> [Point]+pointsOfShape = F.concatMap (F.concatMap go . shapeElements) where   go (ShapeAnchor p _) = [p]   go (ShapeSegment Segment { _segStart = V2 sx sy, _segEnd = V2 ex ey })     | sx == ex && sy >= ey = [V2 sx yy | yy <- [ey .. sy]]     | sx == ex             = [V2 sx yy | yy <- [sy .. ey]]-    | withHorizontal && sy == ey && sx >= ex =-        [V2 xx sy | xx <- [ex .. sx]]-    | withHorizontal && sy == ey =-        [V2 xx sy | xx <- [sx .. ex]]+    | sy == ey && sx >= ex = [V2 xx sy | xx <- [ex .. sx]]+    | sy == ey = [V2 xx sy | xx <- [sx .. ex]]     | otherwise            = []  cleanLines :: [Int] -> CharBoard -> CharBoard@@ -189,8 +181,8 @@  cleanupShapes :: (F.Foldable f) => f Shape -> CharBoard -> CharBoard cleanupShapes shapes board = board { _boardData = _boardData board VU.// toSet }-  where toSet = [(x + y * _boardWidth board, ' ')-                    | V2 x y <- pointsOfShape WithHorizontalSegments shapes]+  where+    toSet = [(x + y * _boardWidth board, ' ') | V2 x y <- pointsOfShape shapes]   pointComp :: Point -> Point -> Ordering@@ -198,8 +190,29 @@   EQ -> compare x1 x2   a -> a -rangesOfShapes :: Shape -> [(Point, Point)]-rangesOfShapes shape = pairAssoc sortedPoints+featuresOfClosedShape :: Shape -> [Point]+featuresOfClosedShape = F.fold . go . shapeElements where+   go [] = []+   -- If we got something like +----+ we skip the first anchor and+   -- the segment.+   go ( ShapeAnchor (V2 _ ay1) _+      : ShapeSegment Segment { _segStart = V2 _ sy, _segEnd = V2 _ ey }+      : rest@(ShapeAnchor (V2 _ ay2) _ : _)+      )+       | ay1 == ay2 && sy == ey && ay1 == sy = go rest+   go (ShapeAnchor p _: rest) = [p] : go rest+   go (ShapeSegment Segment { _segStart = V2 sx sy, _segEnd = V2 ex ey } : rest)+     | sx == ex && sy >= ey = [V2 sx yy | yy <- [ey .. sy]] : after+     | sx == ex             = [V2 sx yy | yy <- [sy .. ey]] : after+     | otherwise           = after+       where after = go rest++rangesOfOpenedShape :: Shape -> [(Point, Point)]+rangesOfOpenedShape s = fmap dup . sortBy pointComp $ pointsOfShape [s]+  where dup a = (a, a)++rangesOfClosedShape :: Shape -> [(Point, Point)]+rangesOfClosedShape shape = pairAssoc sortedPoints   where    pairAssoc  [] = []    pairAssoc [_] = []@@ -207,56 +220,98 @@       | y1 == y2 = (p1, p2) : pairAssoc rest       | otherwise = pairAssoc lst -   sortedPoints = sortBy pointComp-                $ pointsOfShape WithoutHorizontalSegments [shape]+   sortedPoints = sortBy pointComp $ featuresOfClosedShape shape  -associateTags :: [Shape] -> [TextZone] -> ([Shape], [TextZone])-associateTags shapes tagZones =-  expandTag $ runState (mapM go shapes) sortedZones where+class RangeDecomposable a where+  rangesOf :: a -> [(Point, Point)] -  sortedZones =-    sortBy (pointComp `on` _textZoneOrigin) tagZones+instance RangeDecomposable Shape where+  rangesOf s+     | shapeIsClosed s = rangesOfClosedShape s+     | otherwise = rangesOfOpenedShape s -  isInRange (V2 px py) (V2 x1 y1, V2 x2 y2) =-    py == y1 && py == y2 && x1 < px && px < x2+instance RangeDecomposable TextZone where+  rangesOf txt = [(orig, V2 (x + txtLength) y)] where+    orig@(V2 x y) = _textZoneOrigin txt+    txtLength = T.length $ _textZoneContent txt+++contains :: (RangeDecomposable a, RangeDecomposable b) => a -> b -> Bool+contains sa sb = go (rangesOf sa) (rangesOf sb) where+  go _      []    = True+  go []     (_:_) = False+  go ((V2 _ ya, _):rest1) rest2@((V2 _ yb, _):_)+    -- A part of second shape is before potentially englobing shpae+    -- so sa can't contain sb+    | ya > yb = False   +    -- sa may be bigger, just skip+    | ya < yb = go rest1 rest2+  -- here ya == yb+  go sal@((V2 xa1 _, V2 xa2 _):rest1)+     sar@((V2 xb1 _, V2 xb2 _):rest2)+    -- sb is before any range of sa, so we must have+    -- missed something, sa not containing sb+    | xb1 < xa1 = False+    -- sb is in the range bounds+    | xa1 <= xb1 && xb2 <= xa2 = go sal rest2+    -- Maybe sa has another range on the same line+    | xb1 > xa2 = go rest1 sar+    | otherwise = False   -  expandTag (s, zones) = (s, fmap expander zones) where-    expander t = t { _textZoneContent = "{" <> _textZoneContent t <> "}" }+areaOfShape :: Shape -> Int+areaOfShape = F.sum . fmap dist . rangesOfClosedShape+  where+    -- we can use manathan distance here+    dist (V2 x1 y1, V2 x2 y2) = abs (x1 - x2) + abs (y1 - y2) -  insertAlls shape =-    foldr S.insert (shapeTags shape) . fmap _textZoneContent+sortByArea :: [Shape] -> [Shape]+sortByArea shapes = sorted <> opened+  where+    (closed, opened) = partition shapeIsClosed shapes+    sorted =+        fmap snd . reverse $ sortBy (compare `on` fst) [(areaOfShape s, s) | s <- closed] -  go shape | not $ shapeIsClosed shape = return shape-  go shape = do-    zones <- get+hierarchise :: [Shape] -> [TextZone] -> [TextZone] -> [Element]+hierarchise shapes allTexts = finalize . go areaSortedShapes allTexts where+  areaSortedShapes = sortByArea shapes -    let ranges = rangesOfShapes shape-        isInShape TextZone { _textZoneOrigin = orig } =-          any (isInRange orig) ranges-        (inRanges, other) = partition isInShape zones+  finalize (topShapes, topText, _topTags) =+    (ElemShape <$> topShapes) <> (ElemText <$> topText) -    put other+  go [] texts tags = ([], texts, tags)+  go (x:xs) texts tags | not (shapeIsClosed x) = (x:outShapes, outTexts, outTags)+    where+      (outShapes, outTexts, outTags) = go xs texts tags+  go (x:xs) texts tags = (newShape : restShapes, restText, restTags)+    where+      (shapeInShape, shapeOutShape) = partition (x `contains`) xs+      (textInShape, textOutShape) = partition (x `contains`) texts+      (tagsInShape, tagsOutShape) = partition (x `contains`) tags -    return shape { shapeTags = insertAlls shape inRanges }+      (innerShapes, innerText, innerTags) = go shapeInShape textInShape tagsInShape+      (restShapes, restText, restTags) = go shapeOutShape textOutShape tagsOutShape +      newShape = x+        { shapeChildren =+            (ElemShape <$> innerShapes) <> (ElemText <$> innerText)+        , shapeTags = S.fromList $ _textZoneContent <$> innerTags+        }  -- | Analyze an ascii diagram and extract all it's features. parseAsciiDiagram :: T.Text -> Diagram parseAsciiDiagram content = Diagram-    { _diagramShapes = S.fromList taggedShape-    , _diagramTexts = zones ++ unusedTags+    { _diagramElements = S.fromList allElements     , _diagramCellWidth = maximum $ fmap T.length textLines     , _diagramCellHeight = length textLines - length styleLines-    , _diagramStyles = styleLines+    , _diagramStyles = reverse styleLines     }   where     textLines = T.lines content-    (taggedShape, unusedTags) = associateTags (S.toList validShapes) tags--    (tags, zones) = detectTagFromTextZone-                  $ extractTextZones shapeCleanedText +    allElements = hierarchise (S.toList validShapes) nonEmptyZones tags +    nonEmptyZones = [t | t <- zones, not . T.null $ _textZoneContent t]+    (tags, zones) = detectTagFromTextZone $ extractTextZones shapeCleanedText      (styleLineNumber, styleLines) = unzip $ styleLine parsed      shapeCleanedText =@@ -279,7 +334,7 @@ -- a SVG file on disk with a customized grid size. saveAsciiDiagramAsSvgAtSize :: FilePath -> GridSize -> Diagram -> IO () saveAsciiDiagramAsSvgAtSize fileName gridSize =-  saveXmlFile fileName . svgOfDiagramAtSize gridSize+  saveXmlFile fileName . svgOfDiagramAtSize gridSize (defaultLibrary gridSize)  -- | Render a Diagram as an image. The Dpi -- is 96. The IO dependency is there to allow loading of the@@ -293,7 +348,8 @@ -- font files used in the document. imageOfDiagramAtSize :: FontCache -> GridSize -> Diagram -> IO (Image PixelRGBA8) imageOfDiagramAtSize cache gridSize =-  fmap fst . renderSvgDocument cache Nothing 96 . svgOfDiagramAtSize gridSize+  fmap fst . renderSvgDocument cache Nothing 96+           . svgOfDiagramAtSize gridSize (defaultLibrary gridSize)  -- | Render a Diagram into a PDF file. IO dependency to allow -- loading of the font files used in the document.@@ -305,20 +361,40 @@ -- IO dependency to allow loading of the font files used in the document. pdfOfDiagramAtSize :: FontCache -> GridSize -> Diagram -> IO LB.ByteString pdfOfDiagramAtSize cache size =-  fmap fst . pdfOfSvgDocument cache Nothing 96 . svgOfDiagramAtSize size+  fmap fst . pdfOfSvgDocument cache Nothing 96+           . svgOfDiagramAtSize size (defaultLibrary size) +-- $introDoc+-- Ascii diagram, transform your ASCII art drawing to a nicer+-- representation+-- +-- +-- @+--                 \/---------++-- +---------+     |         |+-- |  ASCII  +----\>| Diagram |+-- +---------+     |         |+-- |{flat}   |     +--+------\/+-- \\---*-----\/\<=======\/+-- ::: .flat .filled_shape { fill: #DED; }+-- @+-- <<docimages/baseExample.svg>>+-- + -- $linesdoc -- The basic syntax of asciidiagrams is made of lines made out\nof \'-\' and \'|\' characters. They can be connected with anchors\nlike \'+\' (direct connection) or \'\\\' and \'\/\' (smooth connections)\n -- --- >-----       --- >  -------   --- >            --- >|  |        --- >|  |        --- >|  \----    --- >|           --- >+-----      ---+-- +-- @+--  -----       +--    -------   +--              +--  |  |        +--  |  |        +--  |  \\----    +--  |           +--  +-----      +-- @ -- <<docimages/simple_lines.svg>> --  -- You can use dashed lines by using ':' for vertical lines or '=' for\nhorizontal lines.@@ -445,13 +521,102 @@ -- The generated geometry also possess some predefined class -- which are overidable: -- ---  * `dashed_elem` is applyied on every dashed element.+--  * "dashed_elem" is applied on every dashed element. -- ---  * `filled_shape` is applyied on every closed shape.+--  * "filled_shape" is applied on every closed shape. -- ---  * `bullet` on every bullet placed on a shape or line.+--  * "arrow_head" is applied on arrow head. -- ---  * `line_element` on every line element, this include the arrow head.+--  * "bullet" on every bullet placed on a shape or line. -- +--  * "line_element" on every line element, this include the arrow head.+--  -- You can then customize the appearance of the diagram as you want.+-- ++-- $hierarchicalDoc+-- Starting with version 1.3, all shapes, text and lines are+-- hierachised, a shape within a shape will be integrated within+-- the same group. This allows more complex styling: +-- +-- +-- @+--  \/------------------------------------------------------\\ .+--  |s100                                                  |+--  |    \/----------------------------\\                    |+--  |    |s1         \/--------\\       |  e1    \/--------\\  |+--  |    |      *---\>|  s2    |       +-------\>|  s10   |  |+--  |    +----+      \\---+----\/       |        \\--------\/  |+--  |    | i4 |          |            |           ^        |+--  |    |{ii}+---------\\| e1  {lo}   |           |        |+--  |    +----+         vv            | ealarm    |        |   e0      \/-------------\\ .+--  |    |            \/--------\\      +-----------\/        +----------\>|    s50      |+--  |    +----\\       | s3 {lu}|      |                    |           \\-------------\/+--  |    | o5 |   e2  \\--+-----\/      |                    |+--  |    |{oo}|\<---------\/            |\<-\\                 |+--  |    \\-+--+--------------------+--\/  |                 |+--  |      |                       |     | eReset          |+--  |      |                       \\-----\/                 |+--  |      v                                               |+--  |  \/--------\\                                          |+--  |  |  s20   |                  {li}                    |+--  |  \\--------\/                                          |+--  \\------------------------------------------------------\/+-- +-- ::: .li .line_element { stroke: purple; }+-- ::: .li .arrow_head, .li text { fill: gray; }+-- ::: .lo .line_element { stroke: blue; }+-- ::: .lo .arrow_head, .lo text { fill: green; }+-- ::: .lu .line_element { stroke: red; }+-- ::: .lu .arrow_head, .lu text { fill: orange; }+-- ::: .ii .filled_shape { fill: #DDF; }+-- ::: .ii text { fill: blue; }+-- ::: .oo .filled_shape { fill: #DFD; }+-- ::: .oo text { fill: pink; }+-- @+-- <<docimages/deepStyleExample.svg>>+-- +-- In the previous example, we can see that the lines color are+-- 'shape scoped' and the tag applied to the shape above them+-- applies to them+-- ++-- $shapeDoc+-- From version 1.3, you can substitute the shape of your element+-- with one from a shape library. Right now the shape library is+-- relatively small:+-- +-- +-- @+--  +---------+  +----------++--  |         |  |          |+--  | circle  |  |          |+--  |         |  |    io    |+--  |{circle} |  | {io}     |+--  +---------+  +----------++-- +--  +----------+  +----------++--  |document  |  |          |+--  |          |  |          |+--  |          |  | storage  |+--  |{document}|  | {storage}|+--  +----------+  +----------++-- +-- ::: .circle .filled_shape { shape: circle; }+-- ::: .document .filled_shape { shape: document; }+-- ::: .storage .filled_shape { shape: storage; }+-- ::: .io .filled_shape { shape: io; }+-- @+-- <<docimages/shapeExample.svg>>+-- +-- The mechanism use CSS styling to change the shape, if a CSS rule+-- possess a `shape` pseudo attribute, then the generated shape is replaced+-- with a SVG `use` tag with the value of the shape attribute as `href`+-- +-- But, you can create your own style library and change the default+-- stylesheet. You can retrieve the default one with the shell command+-- `asciidiagram --dump-library default-lib.svg`+-- +-- You can then add your own symbols tag in it and use it by calling+-- `asciidiagram --with-library your-lib.svg`. -- 
+ src/Text/AsciiDiagram/BoundingBoxEstimation.hs view
@@ -0,0 +1,124 @@+{-# LANGUAGE CPP #-}+module Text.AsciiDiagram.BoundingBoxEstimation where++#if !MIN_VERSION_base(4,8,0)+import Control.Applicative( (<$>), (<*>)+                          , pure+                          )+import Data.Foldable( foldMap )+import Data.Monoid( Monoid( mappend, mempty )+                  , mconcat+                  )+#endif++import Data.Monoid( (<>) )+import Linear( V2( .. )+             , (^+^)+             , (^-^)+             )++import Graphics.Svg.Types++data BoundingBox = BoundingBox+  { _boundingLow    :: !RPoint+  , _boundingHight  :: !RPoint+  }+  deriving (Eq, Show)++instance Monoid BoundingBox where+  mempty = BoundingBox (V2 0 0) (V2 0 0)+  mappend (BoundingBox min1 max1) (BoundingBox min2 max2) =+    BoundingBox (min <$> min1 <*> min2) (max <$> max1 <*> max2)++toEstimatedLength :: Number -> Coord+toEstimatedLength n = case toUserUnit 96 n of+  Num p -> p+  _ -> 0++toEstimatedPoint :: (Number, Number) -> RPoint+toEstimatedPoint (a, b) = V2 a' b' where+  a' = toEstimatedLength a+  b' = toEstimatedLength b++toB :: RPoint -> BoundingBox+toB p = BoundingBox p p++class WithBoundingBox a where+  boundingBoxOf :: a -> BoundingBox++instance WithBoundingBox PolyLine where+  boundingBoxOf = foldMap toB . _polyLinePoints++instance WithBoundingBox Polygon where+  boundingBoxOf = foldMap toB . _polygonPoints++instance WithBoundingBox Line where+  boundingBoxOf (Line _ p1 p2) =+      toB (toEstimatedPoint p1) <> toB (toEstimatedPoint p2)++instance WithBoundingBox Rectangle where+  boundingBoxOf (Rectangle _ base w h _) =+      toB base' <> toB (base' ^+^ toEstimatedPoint (w, h))+     where base' = toEstimatedPoint base++pointOfPath :: PathCommand -> [RPoint]+pointOfPath c = case c of+ MoveTo _ l -> l+ LineTo _ l -> l+ HorizontalTo _ _ -> mempty+ VerticalTo   _ _ -> mempty+ CurveTo _ l -> mconcat [[a, b, cc] | (a, b, cc) <- l]+ SmoothCurveTo _ l -> mconcat [[a, b] | (a, b) <- l]+ QuadraticBezier _ l -> mconcat [[a, b] | (a, b) <- l]+ SmoothQuadraticBezierCurveTo _ l -> l+ EllipticalArc _ _ -> mempty+ EndPath -> mempty++instance WithBoundingBox Path where+  boundingBoxOf (Path _ p) = foldMap (foldMap toB . pointOfPath) p++instance WithBoundingBox a => WithBoundingBox (Group a) where+  boundingBoxOf (Group _ child _ _) = foldMap boundingBoxOf child++instance WithBoundingBox a => WithBoundingBox (Symbol a) where+  boundingBoxOf (Symbol g) = boundingBoxOf g++instance WithBoundingBox Text where+  boundingBoxOf = boundingBoxOf . _textRoot++instance WithBoundingBox TextSpan where+  boundingBoxOf = boundingBoxOf . _spanInfo++instance WithBoundingBox TextInfo where+  boundingBoxOf t = case (_textInfoX t, _textInfoY t) of+    (x1:_, y1:_) -> toB (toEstimatedPoint (x1, y1))+    _ -> mempty++instance WithBoundingBox Circle where+  boundingBoxOf (Circle _ center rad) = BoundingBox (c ^-^ r) (c ^+^ r)+    where+     c = toEstimatedPoint center+     r = pure $ toEstimatedLength rad++instance WithBoundingBox Ellipse where+  boundingBoxOf (Ellipse _ center xrad yrad) = BoundingBox (c ^-^ r) (c ^+^ r)+    where+     c = toEstimatedPoint center+     r = V2 (toEstimatedLength xrad) (toEstimatedLength yrad)++instance WithBoundingBox Tree where+  boundingBoxOf t = case t of+    None            -> mempty+    UseTree _ _     -> mempty+    PathTree p      -> boundingBoxOf p+    CircleTree c    -> boundingBoxOf c+    PolyLineTree pl -> boundingBoxOf pl+    PolygonTree po  -> boundingBoxOf po+    EllipseTree e   -> boundingBoxOf e+    LineTree l      -> boundingBoxOf l+    RectangleTree r -> boundingBoxOf r+    TextTree  _ txt -> boundingBoxOf txt+    ImageTree _     -> mempty+    GroupTree g     -> boundingBoxOf g+    SymbolTree s    -> boundingBoxOf s+
+ src/Text/AsciiDiagram/DefaultContext.hs view
@@ -0,0 +1,151 @@+{-# LANGUAGE OverloadedStrings #-}+module Text.AsciiDiagram.DefaultContext+    ( defaultCss+    , defaultCssRules+    , defaultDefinitions+    ) where++import Control.Monad.State.Strict( execState )+import Data.Monoid( (<>) )++import Graphics.Svg.Types ( HasDrawAttributes( .. ), drawAttr )+import Graphics.Svg( cssRulesOfText )++import Codec.Picture( PixelRGBA8( PixelRGBA8 ) )+import qualified Graphics.Svg.Types as Svg+import qualified Graphics.Svg.CssTypes as Css+import qualified Data.Map as M+import qualified Data.Text as T+import Text.Printf+import Linear( V2( .. ) )+import Control.Lens( (.=), (.~), (&) )+++defaultCss :: Float -> T.Text+defaultCss textSize = T.pack $ printf+  ("\n" <>+   "text { font-family: Consolas, \"DejaVu Sans Mono\", monospace; font-size: %dpx }\n" <>+   ".dashed_elem { stroke-dasharray: 4, 3 }\n" <>+   ".filled_shape { fill: url(#shape_light); stroke: black; stroke-width: 1px; }\n" <>+   ".line_element { fill: none; stroke: black; stroke-width: 1px; }\n" <>+   ".bullet { stroke-width: 1px; fill: white; stroke: black }\n" <>+   ".arrow_head { fill: black; stroke: none; }\n"+  )+  (2 + floor textSize :: Int)++defaultCssRules :: Float -> [Css.CssRule]+defaultCssRules = cssRulesOfText . defaultCss++lightShapeGradient :: Svg.Element+lightShapeGradient = Svg.ElementLinearGradient $+    Svg.defaultSvg+        { Svg._linearGradientStart = (Svg.Percent 0, Svg.Percent 0)+        , Svg._linearGradientStop =  (Svg.Percent 0, Svg.Percent 1)+        , Svg._linearGradientStops =+            [ Svg.GradientStop 0 $ PixelRGBA8 245 245 245 255+            , Svg.GradientStop 1 $ PixelRGBA8 216 216 216 255+            ]+        }++toSymbol :: Double -> Double -> [Svg.Tree] -> Svg.Element+toSymbol width height geom = element where+  element = Svg.ElementGeometry $ Svg.SymbolTree tree+  tree = Svg.Symbol $ execState build Svg.defaultSvg++  build = do+    Svg.groupChildren .= geom+    Svg.groupViewBox .= Just (0, 0, width, height)+    Svg.groupAspectRatio . Svg.aspectRatioAlign .= Svg.AlignNone++asFilled :: (Svg.WithDrawAttributes a) => a -> a+asFilled el = el & drawAttr.attrClass .~ ["filled_shape"]++defaultCircle :: Svg.Element+defaultCircle = toSymbol 50 50 [Svg.CircleTree $ asFilled circle] where+  circle = Svg.defaultSvg+    { Svg._circleCenter = (Css.Num 25, Css.Num 25)+    , Svg._circleRadius = Css.Num 24.5+    }++h, v :: [Svg.Coord] -> Svg.PathCommand+h = Svg.HorizontalTo Svg.OriginRelative+v = Svg.VerticalTo Svg.OriginRelative++m :: [Svg.RPoint] -> Svg.PathCommand+m = Svg.MoveTo Svg.OriginRelative++c :: [(Svg.RPoint, Svg.RPoint, Svg.RPoint)] -> Svg.PathCommand+c = Svg.CurveTo Svg.OriginRelative++l :: [Svg.RPoint] -> Svg.PathCommand+l = Svg.LineTo Svg.OriginRelative++z :: Svg.PathCommand+z = Svg.EndPath++defaultDocument :: Svg.Element+defaultDocument = toSymbol 51 51 [Svg.PathTree $ asFilled path] where+  path = Svg.defaultSvg+    { Svg._pathDefinition =+        [ m [V2 49.98 0.79, V2 (-49.166) 0, V2 0 45.402]+        , c [(V2 15.92 12.45, V2 30.40 (-13.44), V2 49.17 0)]+        , z+        ]+    }++ioShape :: Svg.Element+ioShape = toSymbol 100 100 [Svg.PathTree $ asFilled path] where+  path = Svg.defaultSvg+    { Svg._pathDefinition =+        [ m [V2 19.207 1.6]+        , h [79.414]+        , l [V2 (-17.192) 97.297]+        , h [-79.414]+        , z+        ]+    }++storageShape :: Svg.Element+storageShape = toSymbol 80 80 geometry where+  geometry = Svg.PathTree . asFilled <$> [path1, path2]+  path1 = Svg.defaultSvg+    { Svg._pathDefinition =+        [ m [V2 4.8122 67.74]+        , v [-53.769]+        , c [ (V2 0.0 (-3.2991) , V2 16.067 (-5.9743), V2 35.845 (-5.9743))+            , (V2 19.78 0.0, V2 35.848 2.6752, V2 35.848 5.9743)+            ]+       , v [53.769]+       , c [(V2 0.0 3.2925, V2 (-16.068) 5.9743, V2 (-35.848) 5.9743)+           , (V2 (-19.779) 0.0, V2 (-35.845) (-2.6818), V2 (-35.845) (-5.9743))+           ]+        , z+        ]+    }+  path2 = Svg.defaultSvg+    { Svg._pathDefinition =+        [ m [ V2 4.8122 13.97, V2 4.779e-2 0.30672, V2 0.13807 0.30272+            , V2 0.22834 0.29872, V2 0.31464 0.29344, V2 0.40094 0.28944+            , V2 0.48325 0.2828, V2 0.56423 0.27744, V2 0.64256 0.2708+            , V2 0.71823 0.26416, V2 0.79258 0.25752, V2 0.86294 0.25096+            , V2 0.9333 0.2416, V2 0.99968 0.23496, V2 1.0647 0.22568+            , V2 1.1271 0.2164, V2 1.1869 0.2084, V2 1.2453 0.19784+            , V2 1.301 0.1872, V2 1.3555 0.17792, V2 1.4046 0.16728+            , V2 1.455 0.15536, V2 1.5002 0.14336, V2 1.5466 0.1328+            , V2 1.5865 0.11952, V2 1.6276 0.10752, V2 1.6648 9.42e-2+            , V2 1.7007 8.1e-2, V2 1.7338 6.64e-2, V2 1.7644 5.31e-2+            , V2 1.7923 3.72e-2, V2 1.8188 2.39e-2, V2 1.8427 8.0e-3+            ]+        , c [(V2 19.78 0.0, V2 35.848 (-2.6818), V2 35.848 (-5.9743))]+        ]+    }++defaultDefinitions :: M.Map String Svg.Element+defaultDefinitions = M.fromList+  [ ("shape_light", lightShapeGradient)+  , ("circle", defaultCircle)+  , ("document", defaultDocument)+  , ("io", ioShape)+  , ("storage", storageShape)+  ]+
src/Text/AsciiDiagram/Geometry.hs view
@@ -1,125 +1,132 @@-{-# LANGUAGE CPP #-}
--- | Defines the geometry extracted from the asciidiagram.
-module Text.AsciiDiagram.Geometry( Point
-                                 , Vector
-                                 , Anchor( .. )
-                                 , Shape( .. )
-                                 , Segment( .. )
-                                 , SegmentDraw( .. )
-                                 , SegmentKind( .. )
-                                 , ShapeElement( .. )
-                                 , Diagram( .. )
-                                 , TextZone( .. )
-                                 ) where
-
-#if !MIN_VERSION_base(4,8,0)
-import Data.Monoid( Monoid( mappend, mempty ))
-#endif
-
-import qualified Data.Set as S
-import qualified Data.Text as T
-import Linear( V2( .. ) )
-
--- | Position of a an element in the character grids
-type Point = V2 Int
-
--- | Direction in the character grid.
-type Vector = V2 Int
-
--- | Describe the geomtry of a full Ascii Diagram
--- document
-data Diagram = Diagram
-  { -- | All the extracted tshapes
-    _diagramShapes     :: S.Set Shape
-    -- | All the extracted text zones
-  , _diagramTexts      :: [TextZone]
-    -- | Width in characters of the document
-  , _diagramCellWidth  :: !Int
-    -- | Height in characters of the document
-  , _diagramCellHeight :: !Int
-    -- | CSS styles associated to the document.
-  , _diagramStyles     :: [T.Text]
-  }
-  deriving (Eq, Show)
-
--- | Describe where to place a text snippet.
-data TextZone = TextZone
-  { _textZoneOrigin  :: Point
-  , _textZoneContent :: T.Text
-  }
-  deriving (Eq, Show)
-
--- | Define the different connection points
--- between the segments.
-data Anchor
-  = AnchorMulti       -- ^ Associated to '+'
-  | AnchorFirstDiag   -- ^ Associated to '/'
-  | AnchorSecondDiag  -- ^ Associated to '\'
-
-  | AnchorPoint       -- ^ Kind of "end anchor", without continuation.
-  | AnchorBullet      -- ^ Used as a '*'
-
-  | AnchorArrowUp     -- ^ Associated to '^'
-  | AnchorArrowDown   -- ^ Associated to 'V'
-  | AnchorArrowLeft   -- ^ Associated to '<'
-  | AnchorArrowRight  -- ^ Associated to '>'
-  deriving (Eq, Ord, Show)
-
--- | Helper data for segment composed of only
--- one character
-data SegmentKind
-  = SegmentHorizontal
-  | SegmentVertical
-  deriving (Eq, Ord, Show)
-
--- | Differentiate between elements drawn with a
--- solid line or with dashed lines.
-data SegmentDraw
-  = SegmentSolid
-  | SegmentDashed
-  deriving (Eq, Ord, Show)
-
--- | Define an horizontal or vertical segment.
-data Segment = Segment
-  { _segStart :: {-# UNPACK #-} !Point
-  , _segEnd   :: {-# UNPACK #-} !Point
-  , _segKind  :: !SegmentKind
-  , _segDraw  :: !SegmentDraw
-  }
-  deriving (Eq, Ord)
-
-instance Show Segment where
-    showsPrec d (Segment s e k dr) =
-      showParen (d >= 10) $
-          showString "Segment " . start . end . kind . (' ':) . draw
-      where
-        start = showParen True $ shows s
-        end = showParen True $ shows e
-        kind = shows k
-        draw = shows dr
-
-instance Monoid Segment where
-    mempty = Segment 0 0 SegmentVertical SegmentSolid
-    mappend (Segment a _ _ _) (Segment _ b k d) =
-        Segment a b k d
-
--- | Describe a composant of shapes. Can
--- be composed of anchors like "+*/\\" or
--- segments.
-data ShapeElement
-  = ShapeAnchor !Point !Anchor
-  | ShapeSegment !Segment
-  deriving (Eq, Ord, Show)
-
--- | Shape extracted from the text
-data Shape = Shape
-  { -- | Elements composing the shape.
-    shapeElements :: [ShapeElement]
-    -- | When False it's just lines possibly with
-    -- an arrow, when True it's a polygon.
-  , shapeIsClosed :: Bool
-    -- | Tags "{tagname}" placed inside the shape.
-  , shapeTags     :: S.Set T.Text
-  }
-  deriving (Eq, Ord, Show)
-
+{-# LANGUAGE CPP #-}+-- | Defines the geometry extracted from the asciidiagram.+module Text.AsciiDiagram.Geometry( Point+                                 , Vector+                                 , Anchor( .. )+                                 , Shape( .. )+                                 , Element( .. )+                                 , Segment( .. )+                                 , SegmentDraw( .. )+                                 , SegmentKind( .. )+                                 , ShapeElement( .. )+                                 , Diagram( .. )+                                 , TextZone( .. )+                                 ) where++#if !MIN_VERSION_base(4,8,0)+import Data.Monoid( Monoid( mappend, mempty ))+#endif++import qualified Data.Set as S+import qualified Data.Text as T+import Linear( V2( .. ) )++-- | Position of a an element in the character grids+type Point = V2 Int++-- | Direction in the character grid.+type Vector = V2 Int++-- | Describe the geomtry of a full Ascii Diagram+-- document+data Diagram = Diagram+  { -- | All the extracted tshapes+    _diagramElements   :: S.Set Element+    -- | Width in characters of the document+  , _diagramCellWidth  :: !Int+    -- | Height in characters of the document+  , _diagramCellHeight :: !Int+    -- | CSS styles associated to the document.+  , _diagramStyles     :: [T.Text]+  }+  deriving (Eq, Show)++-- | Describe where to place a text snippet.+data TextZone = TextZone+  { _textZoneOrigin  :: Point+  , _textZoneContent :: T.Text+  }+  deriving (Eq, Ord, Show)++-- | Define the different connection points+-- between the segments.+data Anchor+  = AnchorMulti       -- ^ Associated to '+'+  | AnchorFirstDiag   -- ^ Associated to '/'+  | AnchorSecondDiag  -- ^ Associated to '\'++  | AnchorPoint       -- ^ Kind of "end anchor", without continuation.+  | AnchorBullet      -- ^ Used as a '*'++  | AnchorArrowUp     -- ^ Associated to '^'+  | AnchorArrowDown   -- ^ Associated to 'V'+  | AnchorArrowLeft   -- ^ Associated to '<'+  | AnchorArrowRight  -- ^ Associated to '>'+  deriving (Eq, Ord, Show)++-- | Helper data for segment composed of only+-- one character+data SegmentKind+  = SegmentHorizontal+  | SegmentVertical+  deriving (Eq, Ord, Show)++-- | Differentiate between elements drawn with a+-- solid line or with dashed lines.+data SegmentDraw+  = SegmentSolid+  | SegmentDashed+  deriving (Eq, Ord, Show)++-- | Define an horizontal or vertical segment.+data Segment = Segment+  { _segStart :: {-# UNPACK #-} !Point+  , _segEnd   :: {-# UNPACK #-} !Point+  , _segKind  :: !SegmentKind+  , _segDraw  :: !SegmentDraw+  }+  deriving (Eq, Ord)++instance Show Segment where+    showsPrec d (Segment s e k dr) =+      showParen (d >= 10) $+          showString "Segment " . start . end . kind . (' ':) . draw+      where+        start = showParen True $ shows s+        end = showParen True $ shows e+        kind = shows k+        draw = shows dr++instance Monoid Segment where+    mempty = Segment 0 0 SegmentVertical SegmentSolid+    mappend (Segment a _ _ _) (Segment _ b k d) =+        Segment a b k d++-- | Describe a composant of shapes. Can+-- be composed of anchors like "+*/\\" or+-- segments.+data ShapeElement+  = ShapeAnchor !Point !Anchor+  | ShapeSegment !Segment+  deriving (Eq, Ord, Show)++-- | Shape extracted from the text+data Shape = Shape+  { -- | Elements composing the shape.+    shapeElements :: ![ShapeElement]+    -- | When False it's just lines possibly with+    -- an arrow, when True it's a polygon.+  , shapeIsClosed :: !Bool+    -- | Tags "{tagname}" placed inside the shape.+  , shapeTags        :: !(S.Set T.Text)++  , shapeChildren    :: ![Element]+  }+  deriving (Eq, Ord, Show)++-- | Define an element to be drawn.+data Element+  = ElemText  !TextZone+  | ElemShape !Shape+  deriving (Eq, Show, Ord)+
src/Text/AsciiDiagram/Reconstructor.hs view
@@ -260,7 +260,7 @@             . fmap (`M.lookup` _vertices graph)      toFilaments shapes =-      [Shape piece False mempty | piece <- breakFilaments $ toElems shapes] +      [Shape piece False mempty mempty | piece <- breakFilaments $ toElems shapes]  -    toShapes shapes = Shape (toElems shapes) True mempty+    toShapes shapes = Shape (toElems shapes) True mempty mempty 
src/Text/AsciiDiagram/SvgRender.hs view
@@ -1,32 +1,31 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE OverloadedStrings #-}-module Text.AsciiDiagram.SvgRender( GridSize( .. )-                                  , defaultGridSize-                                  , svgOfDiagram-                                  , svgOfDiagramAtSize-                                  ) where+module Text.AsciiDiagram.SvgRender+    ( GridSize( .. )+    , defaultGridSize+    , svgOfDiagram+    , svgOfDiagramAtSize+    , defaultLibrary+    ) where  #if !MIN_VERSION_base(4,8,0) import Data.Monoid( mempty ) import Control.Applicative( (<$>) ) #endif +import Data.Monoid( (<>) ) import Control.Monad.State.Strict( execState )-import Data.Monoid( Last( .. ), (<>) )  import Graphics.Svg.Types                    ( HasDrawAttributes( .. )-                   , Texture( ColorRef )                    , Document( .. )                    , drawAttr ) import Graphics.Svg( cssRulesOfText ) -import Codec.Picture( PixelRGBA8( PixelRGBA8 ) ) import qualified Graphics.Svg.Types as Svg-import qualified Data.Map as M+import qualified Graphics.Svg.CssTypes as Css import qualified Data.Set as S import qualified Data.Text as T-import Text.Printf import Linear( V2( .. )              , (^+^)              , (^-^)@@ -34,10 +33,12 @@              , perp              , normalize              )-import Control.Lens( zoom, (.=), (%=), (%~), (&) )+import Control.Lens( zoom, (^.), (.=), (%=), (%~), (&) ) -import Text.AsciiDiagram.Geometry+import Text.AsciiDiagram.BoundingBoxEstimation+import Text.AsciiDiagram.DefaultContext import Text.AsciiDiagram.DiagramCleaner+import Text.AsciiDiagram.Geometry  {-import Debug.Trace-} {-import Text.Groom-}@@ -78,39 +79,24 @@   isDashed (ShapeSegment Segment { _segDraw = SegmentDashed }) = True  applyDefaultShapeDrawAttr :: (Svg.WithDrawAttributes a) => a -> a-applyDefaultShapeDrawAttr = execState . zoom drawAttr $ do-    strokeColor .= toLC 0 0 0 255-    attrClass %= ("filled_shape":) -    strokeWidth .= toL (Svg.Num 1)-  where-    toL = Last . Just-    toLC r g b a =-        toL . ColorRef $ PixelRGBA8 r g b a+applyDefaultShapeDrawAttr el =+  el & drawAttr.attrClass %~ ("filled_shape":)   applyLineArrowDrawAttr :: (Svg.WithDrawAttributes a) => a -> a-applyLineArrowDrawAttr = execState . zoom drawAttr $ do-    fillColor .= toLC 0 0 0 255-    strokeColor .= toL Svg.FillNone-    strokeWidth .= toL (Svg.Num 0)-  where-    toL = Last . Just-    toLC r g b a =-        toL . ColorRef $ PixelRGBA8 r g b a+applyLineArrowDrawAttr el =+  el & drawAttr.attrClass %~ ("arrow_head":)  applyBulletDrawAttr :: (Svg.WithDrawAttributes a) => a -> a-applyBulletDrawAttr = execState . zoom drawAttr $ do-    attrClass %= ("bullet":)+applyBulletDrawAttr el =+  el & drawAttr.attrClass %~ ("bullet":) +cleanupUseAttributes ::  (Svg.WithDrawAttributes a) => a -> a+cleanupUseAttributes = execState . zoom drawAttr $ do+  attrClass .= []+ applyDefaultLineDrawAttr :: (Svg.WithDrawAttributes a) => a -> a-applyDefaultLineDrawAttr = execState . zoom drawAttr $ do-    attrClass %= ("line_element":)-    fillColor .= toL Svg.FillNone-    strokeColor .= toLC 0 0 0 255-    strokeWidth .= toL (Svg.Num 1)-  where-    toL = Last . Just-    toLC r g b a =-        toL . ColorRef $ PixelRGBA8 r g b a+applyDefaultLineDrawAttr el =+  el & drawAttr.attrClass %~ ("line_element":)   startPointOf :: ShapeElement -> Point@@ -448,70 +434,101 @@     V2 x y = toSvg gscale (_textZoneOrigin zone) ^+^ correction     txt = Svg.textAt (Svg.Num (x+0.5), Svg.Num (y+0.5)) $ _textZoneContent zone -defaultCss :: Float -> T.Text-defaultCss textSize = T.pack $ printf-  ("\n" <>-   "text { font-family: Consolas, \"DejaVu Sans Mono\", monospace; font-size: %dpx }\n" <>-   ".dashed_elem { stroke-dasharray: 4, 3 }\n" <>-   ".filled_shape { fill: url(#shape_light) }\n" <>-   ".bullet { stroke-width: 1px; fill: white; stroke: black }\n"-  )-  (2 + floor textSize :: Int) -lightShapeGradient :: Svg.Element-lightShapeGradient = Svg.ElementLinearGradient $-    Svg.defaultSvg-        { Svg._linearGradientStart = (Svg.Percent 0, Svg.Percent 0)-        , Svg._linearGradientStop =  (Svg.Percent 0, Svg.Percent 1)-        , Svg._linearGradientStops =-            [ Svg.GradientStop 0 $ PixelRGBA8 245 245 245 255-            , Svg.GradientStop 1 $ PixelRGBA8 216 216 216 255-            ]-        }- -- | Transform an Ascii diagram to a SVG document which -- can be saved or converted to an image. svgOfDiagram :: Diagram -> Svg.Document-svgOfDiagram = svgOfDiagramAtSize defaultGridSize where+svgOfDiagram =+    svgOfDiagramAtSize defaultGridSize (defaultLibrary defaultGridSize) +svgOfShape :: GridSize -> Shape -> Svg.Tree+svgOfShape scale shape+  | shapeIsClosed shape =+      applyDefaultShapeDrawAttr $ shapeToTree scale shape+  | otherwise =+      applyDefaultLineDrawAttr $ shapeToTree strokeScale shape+  where+    strokeScale = scale { _gridShapeContraction = 0 }+++svgOfElement :: GridSize -> Element -> Svg.Tree+svgOfElement scale (ElemText txt) = textToTree scale txt+svgOfElement scale (ElemShape shape) = +  case shapeChildren shape of+    [] -> svgOfShape scale shape+    _:_ -> Svg.GroupTree $ group+  where+    thisShape = svgOfShape scale shape+    group = Svg.defaultSvg+      { Svg._groupDrawAttributes =+          mempty { Svg._attrClass = S.toList $ shapeTags shape }+      , Svg._groupChildren =+          thisShape : fmap (svgOfElement scale) (shapeChildren shape)+      , Svg._groupViewBox = Nothing+      }++shapeRewriter :: [Css.CssRule] -> Svg.Tree -> Svg.Tree+shapeRewriter rules = Svg.zipTree go where+  go [] = Svg.None+  go ([]:_) = Svg.None+  go context@((t:_):_) = case reverse shapeDeclarations of+      [] -> t+      (([Css.CssIdent i]:_): _) -> Svg.UseTree (useInfo i) Nothing+      _ -> t+   where+     useInfo name = cleanupUseAttributes $ Svg.Use+        { Svg._useDrawAttributes = t ^. Svg.drawAttr+        , Svg._useBase = (Css.Num x, Css.Num y)+        , Svg._useName = T.unpack name+        , Svg._useWidth = Just (Css.Num w)+        , Svg._useHeight = Just (Css.Num h)+        }++     BoundingBox pMin@(V2 x y) pMax = boundingBoxOf t+     V2 w h = pMax ^-^ pMin++     shapeDeclarations = +        [el | Css.CssDeclaration "shape" el <- Css.findMatchingDeclarations rules context]+ -- | Transform an Ascii diagram to a SVG document which -- can be saved or converted to an image, with a customizable -- grid size.-svgOfDiagramAtSize :: GridSize -> Diagram -> Svg.Document-svgOfDiagramAtSize scale diagram = Document+svgOfDiagramAtSize :: GridSize -> Svg.Document -> Diagram -> Svg.Document+svgOfDiagramAtSize scale style diagram = Document   { _viewBox = Nothing   , _width =       toSvgSize _gridCellWidth $ _diagramCellWidth diagram + 1   , _height =       toSvgSize _gridCellHeight $ _diagramCellHeight diagram + 1-  , _elements = closedSvg ++ lineSvg ++ textSvg-  , _definitions = M.fromList-        [("shape_light", lightShapeGradient)]+  , _elements =+      shapeRewriter allRules . svgOfElement scale <$> shapes+  , _definitions = _definitions style   , _description = ""-  , _styleRules = defaultCssRules ++ customCssRules+  , _styleRules = allRules   , _documentLocation = ""   }   where-    (closed, opened) = S.partition shapeIsClosed shapes--    defaultCssRules =-      cssRulesOfText . defaultCss $ _gridCellHeight scale-+    allRules = _styleRules style <> customCssRules     customCssRules =        cssRulesOfText . T.unlines $ _diagramStyles diagram -    shapes = _diagramShapes diagram--    closedSvg =-        applyDefaultShapeDrawAttr . shapeToTree scale <$> filter isShapePossible-                                                            (S.toList closed)-    lineSvg =-        applyDefaultLineDrawAttr . shapeToTree strokeScale <$> S.toList opened+    isDrawable (ElemText _) = True+    isDrawable (ElemShape shape) =+      not (shapeIsClosed shape) || isShapePossible shape+    shapes = filter isDrawable . S.toList $ _diagramElements diagram      toSvgSize accessor var =         Just . Svg.Num . realToFrac $ fromIntegral var * accessor scale + 5 -    textSvg = textToTree scale <$> _diagramTexts diagram--    strokeScale = scale { _gridShapeContraction = 0 }+defaultLibrary :: GridSize -> Svg.Document+defaultLibrary size = Document+  { _viewBox = Nothing+  , _width = Nothing+  , _height = Nothing+  , _elements =  []+  , _definitions = defaultDefinitions+  , _description = ""+  , _styleRules = defaultCssRules $ _gridCellHeight size+  , _documentLocation = ""+  }