New Upstream Snapshot - dot2tex

Ready changes

Summary

Merged new upstream version: 2.11.3+git20221216.1.0e2b1d9 (was: 2.11.3).

Resulting package

Built on 2023-01-22T05:07 (took 3m24s)

The resulting binary packages can be installed (if you have the apt repository enabled) by running one of:

apt install -t fresh-snapshots dot2tex

Lintian Result

Diff

diff --git a/CHANGES b/CHANGES
index a58aa5d..e5456b9 100644
--- a/CHANGES
+++ b/CHANGES
@@ -3,9 +3,16 @@ dot2tex change log
 
 Here you can see the full list of changes between each dot2tex release.
 
+2.12.dev
+--------
+
+- Major code refactoring
+
 2.11.3
 ------
 
+Released 2019-03-31
+
 - Ignore multiline edge labels during preprocessing (issue #27)
 - Fixed parsing of DOT IDs. Numerals can now be used as node IDs.
 - Fixed issue #64. Remove \ characters from drawsting.
diff --git a/PKG-INFO b/PKG-INFO
index ed8b0ad..64abd8d 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,36 +1,36 @@
-Metadata-Version: 1.1
-Name: dot2tex
-Version: 2.11.3
-Summary: A Graphviz to LaTeX converter
-Home-page: https://github.com/kjellmf/dot2tex
-Author: Kjell Magne Fauske
-Author-email: kjellmf@gmail.com
-License: UNKNOWN
-Description: The purpose of dot2tex is to give graphs generated by the graph layout tool
-        Graphviz_, a more LaTeX friendly look and feel. This is accomplished by:
-        
-        - Using native PSTricks_ and `PGF/TikZ`_ commands for drawing arrows,
-          edges and nodes.
-        - Typesetting labels with LaTeX, allowing mathematical notation.
-        - Using backend specific styles to customize the output.
-        
-        .. _Graphviz: http://www.graphviz.org/
-        .. _PSTricks: http://tug.org/PSTricks/main.cgi/
-        .. _PGF/TikZ: http://www.ctan.org/tex-archive/help/Catalogue/entries/pgf.html
-        
-Platform: UNKNOWN
-Classifier: Development Status :: 4 - Beta
-Classifier: Environment :: Console
-Classifier: Intended Audience :: Science/Research
-Classifier: License :: OSI Approved :: MIT License
-Classifier: Natural Language :: English
-Classifier: Operating System :: OS Independent
-Classifier: Programming Language :: Python :: 2
-Classifier: Programming Language :: Python :: 2.7
-Classifier: Programming Language :: Python :: 3
-Classifier: Programming Language :: Python :: 3.5
-Classifier: Programming Language :: Python :: 3.6
-Classifier: Programming Language :: Python :: 3.7
-Classifier: Topic :: Scientific/Engineering :: Visualization
-Classifier: Topic :: Text Processing :: Markup :: LaTeX
-Classifier: Topic :: Utilities
+Metadata-Version: 2.1
+Name: dot2tex
+Version: 2.12.dev0
+Summary: A Graphviz to LaTeX converter
+Home-page: https://github.com/kjellmf/dot2tex
+Author: Kjell Magne Fauske
+Author-email: kjellmf@gmail.com
+Classifier: Development Status :: 4 - Beta
+Classifier: Environment :: Console
+Classifier: Intended Audience :: Science/Research
+Classifier: License :: OSI Approved :: MIT License
+Classifier: Natural Language :: English
+Classifier: Operating System :: OS Independent
+Classifier: Programming Language :: Python :: 2
+Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3.5
+Classifier: Programming Language :: Python :: 3.6
+Classifier: Programming Language :: Python :: 3.7
+Classifier: Topic :: Scientific/Engineering :: Visualization
+Classifier: Topic :: Text Processing :: Markup :: LaTeX
+Classifier: Topic :: Utilities
+License-File: LICENSE
+License-File: AUTHORS
+
+The purpose of dot2tex is to give graphs generated by the graph layout tool
+Graphviz_, a more LaTeX friendly look and feel. This is accomplished by:
+
+- Using native PSTricks_ and `PGF/TikZ`_ commands for drawing arrows,
+  edges and nodes.
+- Typesetting labels with LaTeX, allowing mathematical notation.
+- Using backend specific styles to customize the output.
+
+.. _Graphviz: http://www.graphviz.org/
+.. _PSTricks: http://tug.org/PSTricks/main.cgi/
+.. _PGF/TikZ: http://www.ctan.org/tex-archive/help/Catalogue/entries/pgf.html
diff --git a/debian/changelog b/debian/changelog
index b262e22..cb85d9a 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,9 +1,10 @@
-dot2tex (2.11.3-4) UNRELEASED; urgency=medium
+dot2tex (2.11.3+git20221216.1.0e2b1d9-1) UNRELEASED; urgency=medium
 
   * Bump debhelper from old 12 to 13.
   * Update standards version to 4.6.2, no changes needed.
+  * New upstream snapshot.
 
- -- Debian Janitor <janitor@jelmer.uk>  Fri, 06 Jan 2023 04:13:59 -0000
+ -- Debian Janitor <janitor@jelmer.uk>  Sun, 22 Jan 2023 05:05:04 -0000
 
 dot2tex (2.11.3-3) unstable; urgency=medium
 
diff --git a/docs/common.inc b/docs/common.inc
index a64cd2b..5202af1 100644
--- a/docs/common.inc
+++ b/docs/common.inc
@@ -1,14 +1,14 @@
-.. _CTAN: http://www.ctan.org/tex-archive/help/Catalogue/entries/dot2tex.html
-.. _easy_install: https://pypi.python.org/pypi/setuptools
-.. _Graphviz: http://www.graphviz.org/
-.. _PSTricks: http://tug.org/PSTricks/main.cgi/
-.. _PGF/TikZ: http://www.ctan.org/pkg/pgf
-.. _MIT: http://opensource.org/licenses/mit-license.php
-.. _Python: https://www.python.org
-.. _pyparsing: http://pyparsing.wikispaces.com/
-.. _pydot: https://pypi.python.org/pypi/pydot
-.. _preview: http://www.ctan.org/pkg/preview
-.. _preview-latex: http://www.gnu.org/software/auctex/preview-latex.html
-.. _AUCTeX: http://www.gnu.org/software/auctex/
-.. _dot2texi: http://www.ctan.org/pkg/dot2texi
+.. _CTAN: http://www.ctan.org/tex-archive/help/Catalogue/entries/dot2tex.html
+.. _easy_install: https://pypi.python.org/pypi/setuptools
+.. _Graphviz: http://www.graphviz.org/
+.. _PSTricks: http://tug.org/PSTricks/main.cgi/
+.. _PGF/TikZ: http://www.ctan.org/pkg/pgf
+.. _MIT: http://opensource.org/licenses/mit-license.php
+.. _Python: https://www.python.org
+.. _pyparsing: http://pyparsing.wikispaces.com/
+.. _pydot: https://pypi.python.org/pypi/pydot
+.. _preview: http://www.ctan.org/pkg/preview
+.. _preview-latex: http://www.gnu.org/software/auctex/preview-latex.html
+.. _AUCTeX: http://www.gnu.org/software/auctex/
+.. _dot2texi: http://www.ctan.org/pkg/dot2texi
 .. _pip: https://pypi.python.org/pypi/pip
\ No newline at end of file
diff --git a/docs/conf.py b/docs/conf.py
index 78a2881..7b942e9 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -48,9 +48,9 @@ copyright = u'2019, Kjell Magne Fauske'
 # built documents.
 #
 # The short X.Y version.
-version = '2.11.3'
+version = '2.12.dev'
 # The full version, including alpha/beta/rc tags.
-release = '2.11.3'
+release = '2.12.dev'
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.
diff --git a/docs/docgraphs/balls.dot b/docs/docgraphs/balls.dot
index fb9a15e..0a8a82d 100644
--- a/docs/docgraphs/balls.dot
+++ b/docs/docgraphs/balls.dot
@@ -1,13 +1,13 @@
-// This graph uses special PGF/TikZ styles to create some interesting
-// visual effects. To get the snaked edges run dot2tex with the -s option
-// to force straight edges. Example
-// $ fdp -Txdot balls.dot | dot2tex -s > balls.tex
-graph G {
-	node [shape=circle, fixedsize=True, width="0.2", style="ball color = green", label=""];
-	edge [style="snake=zigzag, green"];
-	a_1 -- c -- a_2;
-	c [style="ball color=black"];
-	edge [style="snake=snake, blue", color=red];
-	node [style="ball color = red", label=""];
-	a_3 -- c -- a_4 --a_3;
+// This graph uses special PGF/TikZ styles to create some interesting
+// visual effects. To get the snaked edges run dot2tex with the -s option
+// to force straight edges. Example
+// $ fdp -Txdot balls.dot | dot2tex -s > balls.tex
+graph G {
+	node [shape=circle, fixedsize=True, width="0.2", style="ball color = green", label=""];
+	edge [style="snake=zigzag, green"];
+	a_1 -- c -- a_2;
+	c [style="ball color=black"];
+	edge [style="snake=snake, blue", color=red];
+	node [style="ball color = red", label=""];
+	a_3 -- c -- a_4 --a_3;
 }
\ No newline at end of file
diff --git a/docs/docgraphs/ex1.dot b/docs/docgraphs/ex1.dot
index 52dce89..aa26d70 100644
--- a/docs/docgraphs/ex1.dot
+++ b/docs/docgraphs/ex1.dot
@@ -1,3 +1,3 @@
-digraph G {
-	a_1-> a_2 -> a_3 -> a_1;
+digraph G {
+	a_1-> a_2 -> a_3 -> a_1;
 }
\ No newline at end of file
diff --git a/docs/docgraphs/ex1b.dot b/docs/docgraphs/ex1b.dot
index 6e9aa7c..89503ee 100644
--- a/docs/docgraphs/ex1b.dot
+++ b/docs/docgraphs/ex1b.dot
@@ -1,4 +1,4 @@
-digraph G {
-	node [shape=circle];
-	a_1-> a_2 -> a_3 -> a_1;
+digraph G {
+	node [shape=circle];
+	a_1-> a_2 -> a_3 -> a_1;
 }
\ No newline at end of file
diff --git a/docs/docgraphs/ex2.dot b/docs/docgraphs/ex2.dot
index 8a66242..dbbeb14 100644
--- a/docs/docgraphs/ex2.dot
+++ b/docs/docgraphs/ex2.dot
@@ -1,4 +1,4 @@
-digraph G {
-    a_1 [texlbl="$\frac{\gamma}{x^2}$"];
-    a_1-> a_2 -> a_3 -> a_1;
+digraph G {
+    a_1 [texlbl="$\frac{\gamma}{x^2}$"];
+    a_1-> a_2 -> a_3 -> a_1;
 }
\ No newline at end of file
diff --git a/docs/docgraphs/ex3.dot b/docs/docgraphs/ex3.dot
index 41b9f8a..69dcd79 100644
--- a/docs/docgraphs/ex3.dot
+++ b/docs/docgraphs/ex3.dot
@@ -1,8 +1,8 @@
-digraph G {
-	start;
-	end;
-	node [texmode="math"];
-	a_1;
-	a_2;
-	start -> a_1 -> a_2 -> end;
+digraph G {
+	start;
+	end;
+	node [texmode="math"];
+	a_1;
+	a_2;
+	start -> a_1 -> a_2 -> end;
 }
\ No newline at end of file
diff --git a/docs/docgraphs/ex4.dot b/docs/docgraphs/ex4.dot
index b6df705..b382ad1 100644
--- a/docs/docgraphs/ex4.dot
+++ b/docs/docgraphs/ex4.dot
@@ -1,10 +1,10 @@
-digraph G {
-	a_1 [texlbl="$\frac{\gamma}{2x^2+y^3}$"];
-	a_1 -> a_2 -> a_3 -> a_1
-	node [texmode="math"];
-	a_1 -> b_1 -> b_2 -> a_3;
-	b_1 [label="\\frac{\\gamma}{x^2}"];
-	node [texmode="verbatim"]
-	b_4 [label="\\beta"] 
-	a_3 -> b_4 -> a_1;
+digraph G {
+	a_1 [texlbl="$\frac{\gamma}{2x^2+y^3}$"];
+	a_1 -> a_2 -> a_3 -> a_1
+	node [texmode="math"];
+	a_1 -> b_1 -> b_2 -> a_3;
+	b_1 [label="\\frac{\\gamma}{x^2}"];
+	node [texmode="verbatim"]
+	b_4 [label="\\beta"] 
+	a_3 -> b_4 -> a_1;
 }
\ No newline at end of file
diff --git a/docs/docgraphs/lblstyle.dot b/docs/docgraphs/lblstyle.dot
index f729f64..2215b7a 100644
--- a/docs/docgraphs/lblstyle.dot
+++ b/docs/docgraphs/lblstyle.dot
@@ -1,11 +1,11 @@
-digraph G {
-    node [shape=circle];
-    a -> b [label="label",lblstyle="draw=red,cross out"];
-    b -> c [label="test",lblstyle="below=0.5cm,rotate=20,fill=blue!20"];
-    a [label="aa",lblstyle="blue"];
-    b [lblstyle="font=\Huge"];
-    c [label="ccc", lblstyle="red,rotate=90"];
-    rankdir=LR;
-    label="Graph label";
-    lblstyle="draw,fill=red!20";
+digraph G {
+    node [shape=circle];
+    a -> b [label="label",lblstyle="draw=red,cross out"];
+    b -> c [label="test",lblstyle="below=0.5cm,rotate=20,fill=blue!20"];
+    a [label="aa",lblstyle="blue"];
+    b [lblstyle="font=\Huge"];
+    c [label="ccc", lblstyle="red,rotate=90"];
+    rankdir=LR;
+    label="Graph label";
+    lblstyle="draw,fill=red!20";
 }
\ No newline at end of file
diff --git a/docs/docgraphs/nodesize.dot b/docs/docgraphs/nodesize.dot
index 4637b7c..96c5ca5 100644
--- a/docs/docgraphs/nodesize.dot
+++ b/docs/docgraphs/nodesize.dot
@@ -1,7 +1,7 @@
-digraph G {
-	node [shape=rectangle];
-	a_1 [margin="0"]; // will have no effect
-	a_2 [margin="0.7,0.4"];
-	a_3 [width="2",height="1"];
-	a_1-> a_2 -> a_3 -> a_1;
+digraph G {
+	node [shape=rectangle];
+	a_1 [margin="0"]; // will have no effect
+	a_2 [margin="0.7,0.4"];
+	a_3 [width="2",height="1"];
+	a_1-> a_2 -> a_3 -> a_1;
 }
\ No newline at end of file
diff --git a/docs/docgraphs/pgfarrows.dot b/docs/docgraphs/pgfarrows.dot
index 8e70440..eec85a0 100644
--- a/docs/docgraphs/pgfarrows.dot
+++ b/docs/docgraphs/pgfarrows.dot
@@ -1,18 +1,18 @@
-// Examples of PGF/TikZ style arrows. See chapter 14.1 in the PGF/TikZ manual
-// for all availale arrow styles. 
-// To generate this graph you can write:
-// $ circo -Txdot pgfarrows.dot | dot2tex.py > pgfarrows.tex
-digraph G {
-	graph [mindist=0.5];
-	node [texmode="math", fixedsize=true, shape=circle, width=0.4, style="fill=green!20"];
-	c -> n_1 [style="-stealth"];
-	c -> n_2 [style="-to"];
-	c -> n_3 [style="-latex"];
-	c -> n_4 [style="-diamond"];
-	c -> n_5 [style="-o"];
-	c -> n_6 [style="{-]}"]; 
-	c -> n_7 [style="-triangle 90"];
-	c -> n_8 [style="-hooks"];
-	c -> n_9 [style="->>"];
-	c [style="fill=red!80"];
+// Examples of PGF/TikZ style arrows. See chapter 14.1 in the PGF/TikZ manual
+// for all availale arrow styles. 
+// To generate this graph you can write:
+// $ circo -Txdot pgfarrows.dot | dot2tex.py > pgfarrows.tex
+digraph G {
+	graph [mindist=0.5];
+	node [texmode="math", fixedsize=true, shape=circle, width=0.4, style="fill=green!20"];
+	c -> n_1 [style="-stealth"];
+	c -> n_2 [style="-to"];
+	c -> n_3 [style="-latex"];
+	c -> n_4 [style="-diamond"];
+	c -> n_5 [style="-o"];
+	c -> n_6 [style="{-]}"]; 
+	c -> n_7 [style="-triangle 90"];
+	c -> n_8 [style="-hooks"];
+	c -> n_9 [style="->>"];
+	c [style="fill=red!80"];
 }
\ No newline at end of file
diff --git a/docs/docgraphs/preproc1.dot b/docs/docgraphs/preproc1.dot
index fa48c0d..9bf7edf 100644
--- a/docs/docgraphs/preproc1.dot
+++ b/docs/docgraphs/preproc1.dot
@@ -1,6 +1,6 @@
-digraph G {	
-	node [shape=circle];
-	a_1 [texlbl="$x^2+\frac{\sin y}{y^2+\cos \beta}+\gamma_3$"];
-	a_1 -> a_2 [label=" ", texlbl="$x_1+x_3^2+z+c+v~~$"];
-	a_2 -> a_1;
+digraph G {	
+	node [shape=circle];
+	a_1 [texlbl="$x^2+\frac{\sin y}{y^2+\cos \beta}+\gamma_3$"];
+	a_1 -> a_2 [label=" ", texlbl="$x_1+x_3^2+z+c+v~~$"];
+	a_2 -> a_1;
 }
\ No newline at end of file
diff --git a/docs/docgraphs/pstarrows.dot b/docs/docgraphs/pstarrows.dot
index 4ae525d..03e592e 100644
--- a/docs/docgraphs/pstarrows.dot
+++ b/docs/docgraphs/pstarrows.dot
@@ -1,15 +1,15 @@
-// Examples of Pstricks style arrows. 
-// To generate this graph you can write:
-// $ circo -Txdot pstarrows.dot | dot2tex.py -fpst > pstarrows.tex
-digraph G {
-	d2tdocpreamble="\usepackage{pstricks-add}";
-	graph [mindist=0.5];
-	node [texmode="math", fixedsize=true, shape=circle, width=0.4];
-	c -> n_1 [style="arrows=->"];
-	c -> n_2 [style="arrows=->>"];
-	c -> n_3 [style="arrows=-<"];
-	c -> n_4 [style="arrows=-*"];
-	c -> n_5 [style="arrows=-{]}"];
-	c -> n_6 [style="arrows=-o"];
-	c -> n_7 [style="arrows=-H"];
+// Examples of Pstricks style arrows. 
+// To generate this graph you can write:
+// $ circo -Txdot pstarrows.dot | dot2tex.py -fpst > pstarrows.tex
+digraph G {
+	d2tdocpreamble="\usepackage{pstricks-add}";
+	graph [mindist=0.5];
+	node [texmode="math", fixedsize=true, shape=circle, width=0.4];
+	c -> n_1 [style="arrows=->"];
+	c -> n_2 [style="arrows=->>"];
+	c -> n_3 [style="arrows=-<"];
+	c -> n_4 [style="arrows=-*"];
+	c -> n_5 [style="arrows=-{]}"];
+	c -> n_6 [style="arrows=-o"];
+	c -> n_7 [style="arrows=-H"];
 }
\ No newline at end of file
diff --git a/docs/docgraphs/simple.dot b/docs/docgraphs/simple.dot
index d10b50f..a16a7cf 100644
--- a/docs/docgraphs/simple.dot
+++ b/docs/docgraphs/simple.dot
@@ -1,5 +1,5 @@
-graph G {
-	mindist = 0.5;
-	node [shape="circle"];
-	a -- b -- c -- a;
+graph G {
+	mindist = 0.5;
+	node [shape="circle"];
+	a -- b -- c -- a;
 }
\ No newline at end of file
diff --git a/docs/docgraphs/simplelbl.dot b/docs/docgraphs/simplelbl.dot
index 96b6f9e..c424a3e 100644
--- a/docs/docgraphs/simplelbl.dot
+++ b/docs/docgraphs/simplelbl.dot
@@ -1,9 +1,9 @@
-graph G {
-	mindist = 0.5;
-	node [shape="circle"];
-	d2tfigpreamble = "\tikzstyle{mystyle}=[fill=blue!20]";
-	edge [lblstyle="mystyle"];
-	a -- b [label="ab"];
-	b -- c [label="bc"];
-	c -- a [label="ca"];
+graph G {
+	mindist = 0.5;
+	node [shape="circle"];
+	d2tfigpreamble = "\tikzstyle{mystyle}=[fill=blue!20]";
+	edge [lblstyle="mystyle"];
+	a -- b [label="ab"];
+	b -- c [label="bc"];
+	c -- a [label="ca"];
 }
\ No newline at end of file
diff --git a/docs/docgraphs/topaths1.dot b/docs/docgraphs/topaths1.dot
index cfb436a..7fc64c5 100644
--- a/docs/docgraphs/topaths1.dot
+++ b/docs/docgraphs/topaths1.dot
@@ -1,8 +1,8 @@
-digraph G {
-    mindist = 0.5;
-    node [shape="circle"];
-    a -> b [topath="bend right"];
-    c -> b [topath="bend left"];
-    c -> a [topath="out=10,in=-90"];
-    b -> b [topath="loop above"];
+digraph G {
+    mindist = 0.5;
+    node [shape="circle"];
+    a -> b [topath="bend right"];
+    c -> b [topath="bend left"];
+    c -> a [topath="out=10,in=-90"];
+    b -> b [topath="loop above"];
 }
\ No newline at end of file
diff --git a/docs/docgraphs/valignmode1.dot b/docs/docgraphs/valignmode1.dot
index e35d83d..ad18b9f 100644
--- a/docs/docgraphs/valignmode1.dot
+++ b/docs/docgraphs/valignmode1.dot
@@ -1,7 +1,7 @@
-digraph G { 
-	node [fontsize=10];
-	node0 [label="{left|right}", shape=record];
-	node1 [shape=rectangle, label="node 1"]; 
-	node0 -> node1; 
-	rankdir=LR;
+digraph G { 
+	node [fontsize=10];
+	node0 [label="{left|right}", shape=record];
+	node1 [shape=rectangle, label="node 1"]; 
+	node0 -> node1; 
+	rankdir=LR;
 }
\ No newline at end of file
diff --git a/docs/index.rst b/docs/index.rst
index 498370b..33e17b5 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -1,55 +1,55 @@
-dot2tex - A Graphviz to LaTeX converter
-=======================================
-
-:Author: Kjell Magne Fauske
-:Version: 2.11.2
-:Licence: MIT_
-
-
-The purpose of dot2tex is to give graphs generated by Graphviz_ a more LaTeX
-friendly look and feel. This is accomplished by converting xdot output from
-Graphviz_ to a series of PSTricks_ or `PGF/TikZ`_ commands. This approach allows:
-
-    * Typesetting labels with LaTeX, allowing mathematical notation
-    * Using native PSTricks and PGF/TikZ commands for drawing arrows
-    * Using backend specific styles to customize the output
-
-
-User's guide
-============
-
-.. toctree::
-   :maxdepth: 2
-   :numbered:
-
-   installation_guide
-   usage_guide
-   customization_guide
-   tipsandtricks
-   module_guide
-
-
-Additional notes
-================
-
-.. toctree::
-   :maxdepth: 2
-
-   Change log <changelog>
-   license
-
-
-Acknowledgements
-================
-
-The dot parser used by dot2tex is based on code from the pydot_ project.
-
-
-Indices and tables
-==================
-
-* :ref:`genindex`
-* :ref:`modindex`
-* :ref:`search`
-
+dot2tex - A Graphviz to LaTeX converter
+=======================================
+
+:Author: Kjell Magne Fauske
+:Version: 2.12.dev
+:Licence: MIT_
+
+
+The purpose of dot2tex is to give graphs generated by Graphviz_ a more LaTeX
+friendly look and feel. This is accomplished by converting xdot output from
+Graphviz_ to a series of PSTricks_ or `PGF/TikZ`_ commands. This approach allows:
+
+    * Typesetting labels with LaTeX, allowing mathematical notation
+    * Using native PSTricks and PGF/TikZ commands for drawing arrows
+    * Using backend specific styles to customize the output
+
+
+User's guide
+============
+
+.. toctree::
+   :maxdepth: 2
+   :numbered:
+
+   installation_guide
+   usage_guide
+   customization_guide
+   tipsandtricks
+   module_guide
+
+
+Additional notes
+================
+
+.. toctree::
+   :maxdepth: 2
+
+   Change log <changelog>
+   license
+
+
+Acknowledgements
+================
+
+The dot parser used by dot2tex is based on code from the pydot_ project.
+
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`
+
 .. include:: common.inc
\ No newline at end of file
diff --git a/docs/make.bat b/docs/make.bat
old mode 100755
new mode 100644
diff --git a/docs/roadmap.rst b/docs/roadmap.rst
deleted file mode 100644
index a6d0dfb..0000000
--- a/docs/roadmap.rst
+++ /dev/null
@@ -1,12 +0,0 @@
-Road map
-========
-
-The dot2tex project is relatively old. The first release was back in 2006
-
-3.0
----
-
-- Python 3.0 support
-
-
-
diff --git a/docs/usage_guide.rst b/docs/usage_guide.rst
index 270817a..9ff58fa 100644
--- a/docs/usage_guide.rst
+++ b/docs/usage_guide.rst
@@ -33,7 +33,7 @@ Load ``test.dot``, convert it to xdot format and output the resulting graph usin
 
 The same as above, but use neato for graph layout::
 
-    $ dot2tex --prog=neato -ftikz test.dot > testtikz.tex
+    $ dot2tex --prog=neato -ftikz test.dot > testneato.tex
 
 
 .. admonition:: Invoking dot2tex
diff --git a/dot2tex.egg-info/PKG-INFO b/dot2tex.egg-info/PKG-INFO
index ed8b0ad..64abd8d 100644
--- a/dot2tex.egg-info/PKG-INFO
+++ b/dot2tex.egg-info/PKG-INFO
@@ -1,36 +1,36 @@
-Metadata-Version: 1.1
-Name: dot2tex
-Version: 2.11.3
-Summary: A Graphviz to LaTeX converter
-Home-page: https://github.com/kjellmf/dot2tex
-Author: Kjell Magne Fauske
-Author-email: kjellmf@gmail.com
-License: UNKNOWN
-Description: The purpose of dot2tex is to give graphs generated by the graph layout tool
-        Graphviz_, a more LaTeX friendly look and feel. This is accomplished by:
-        
-        - Using native PSTricks_ and `PGF/TikZ`_ commands for drawing arrows,
-          edges and nodes.
-        - Typesetting labels with LaTeX, allowing mathematical notation.
-        - Using backend specific styles to customize the output.
-        
-        .. _Graphviz: http://www.graphviz.org/
-        .. _PSTricks: http://tug.org/PSTricks/main.cgi/
-        .. _PGF/TikZ: http://www.ctan.org/tex-archive/help/Catalogue/entries/pgf.html
-        
-Platform: UNKNOWN
-Classifier: Development Status :: 4 - Beta
-Classifier: Environment :: Console
-Classifier: Intended Audience :: Science/Research
-Classifier: License :: OSI Approved :: MIT License
-Classifier: Natural Language :: English
-Classifier: Operating System :: OS Independent
-Classifier: Programming Language :: Python :: 2
-Classifier: Programming Language :: Python :: 2.7
-Classifier: Programming Language :: Python :: 3
-Classifier: Programming Language :: Python :: 3.5
-Classifier: Programming Language :: Python :: 3.6
-Classifier: Programming Language :: Python :: 3.7
-Classifier: Topic :: Scientific/Engineering :: Visualization
-Classifier: Topic :: Text Processing :: Markup :: LaTeX
-Classifier: Topic :: Utilities
+Metadata-Version: 2.1
+Name: dot2tex
+Version: 2.12.dev0
+Summary: A Graphviz to LaTeX converter
+Home-page: https://github.com/kjellmf/dot2tex
+Author: Kjell Magne Fauske
+Author-email: kjellmf@gmail.com
+Classifier: Development Status :: 4 - Beta
+Classifier: Environment :: Console
+Classifier: Intended Audience :: Science/Research
+Classifier: License :: OSI Approved :: MIT License
+Classifier: Natural Language :: English
+Classifier: Operating System :: OS Independent
+Classifier: Programming Language :: Python :: 2
+Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3.5
+Classifier: Programming Language :: Python :: 3.6
+Classifier: Programming Language :: Python :: 3.7
+Classifier: Topic :: Scientific/Engineering :: Visualization
+Classifier: Topic :: Text Processing :: Markup :: LaTeX
+Classifier: Topic :: Utilities
+License-File: LICENSE
+License-File: AUTHORS
+
+The purpose of dot2tex is to give graphs generated by the graph layout tool
+Graphviz_, a more LaTeX friendly look and feel. This is accomplished by:
+
+- Using native PSTricks_ and `PGF/TikZ`_ commands for drawing arrows,
+  edges and nodes.
+- Typesetting labels with LaTeX, allowing mathematical notation.
+- Using backend specific styles to customize the output.
+
+.. _Graphviz: http://www.graphviz.org/
+.. _PSTricks: http://tug.org/PSTricks/main.cgi/
+.. _PGF/TikZ: http://www.ctan.org/tex-archive/help/Catalogue/entries/pgf.html
diff --git a/dot2tex.egg-info/SOURCES.txt b/dot2tex.egg-info/SOURCES.txt
index 34d596a..04b259d 100644
--- a/dot2tex.egg-info/SOURCES.txt
+++ b/dot2tex.egg-info/SOURCES.txt
@@ -14,7 +14,6 @@ docs/installation_guide.rst
 docs/license.rst
 docs/make.bat
 docs/module_guide.rst
-docs/roadmap.rst
 docs/tipsandtricks.rst
 docs/usage_guide.rst
 docs/docgraphs/balls.dot
@@ -88,9 +87,14 @@ docs/img/valignmode2.png
 docs/img/valignmode3.pdf
 docs/img/valignmode3.png
 dot2tex/__init__.py
+dot2tex/__main__.py
+dot2tex/base.py
 dot2tex/dot2tex
 dot2tex/dot2tex.py
 dot2tex/dotparsing.py
+dot2tex/pgfformat.py
+dot2tex/pstricksformat.py
+dot2tex/utils.py
 dot2tex.egg-info/PKG-INFO
 dot2tex.egg-info/SOURCES.txt
 dot2tex.egg-info/dependency_links.txt
@@ -128,7 +132,6 @@ tests/testgraphs/d2topts.dot
 tests/testgraphs/dot2tikznodeshapesmapping.dot
 tests/testgraphs/escstr.dot
 tests/testgraphs/invis.dot
-tests/testgraphs/issue.dot
 tests/testgraphs/latin1.dot
 tests/testgraphs/markup.dot
 tests/testgraphs/markup2.dot
diff --git a/dot2tex.egg-info/entry_points.txt b/dot2tex.egg-info/entry_points.txt
index fb9dd6d..0827cd7 100644
--- a/dot2tex.egg-info/entry_points.txt
+++ b/dot2tex.egg-info/entry_points.txt
@@ -1,3 +1,2 @@
 [console_scripts]
 dot2tex = dot2tex.dot2tex:main
-
diff --git a/dot2tex/__init__.py b/dot2tex/__init__.py
index e60b1ae..61ab088 100644
--- a/dot2tex/__init__.py
+++ b/dot2tex/__init__.py
@@ -33,10 +33,10 @@ __author__ = 'Kjell Magne Fauske'
 __license__ = 'MIT'
 
 from . import dot2tex as d2t
+from pyparsing import ParseException
 
 __version__ = d2t.__version__
 
-from pyparsing import ParseException
 import logging
 
 
diff --git a/dot2tex/__main__.py b/dot2tex/__main__.py
new file mode 100644
index 0000000..bf444f0
--- /dev/null
+++ b/dot2tex/__main__.py
@@ -0,0 +1,4 @@
+from .dot2tex import main
+
+if __name__ == '__main__':
+    main()
diff --git a/dot2tex/base.py b/dot2tex/base.py
new file mode 100644
index 0000000..3936f66
--- /dev/null
+++ b/dot2tex/base.py
@@ -0,0 +1,1081 @@
+import logging
+import os
+import re
+import sys
+import tempfile
+from subprocess import Popen, PIPE
+
+from . import dotparsing
+from .utils import nsplit, chunks, escape_texchars, smart_float, replace_tags, is_multiline_label
+
+# initialize logging module
+log = logging.getLogger("dot2tex")
+
+
+DEFAULT_TEXTENCODING = 'utf8'
+DEFAULT_OUTPUT_FORMAT = 'pgf'
+DEFAULT_LABEL_XMARGIN = 0.11
+DEFAULT_LABEL_YMARGIN = 0.055
+DEFAULT_EDGELABEL_XMARGIN = 0.01
+DEFAULT_EDGELABEL_YMARGIN = 0.01
+
+
+def create_xdot(dotdata, prog='dot', options=''):
+    """Run a graph through Graphviz and return an xdot-version of the graph"""
+    # The following code is from the pydot module written by Ero Carrera
+    progs = dotparsing.find_graphviz()
+
+    # prog = 'dot'
+    if progs is None:
+        log.error('Could not locate Graphviz binaries')
+        return None
+    if not prog in progs:
+        log.error('Invalid prog=%s', prog)
+        raise NameError('The %s program is not recognized. Valid values are %s' % (prog, list(progs)))
+
+    tmp_fd, tmp_name = tempfile.mkstemp()
+    os.close(tmp_fd)
+    if os.sys.version_info[0] >= 3:
+        with open(tmp_name, 'w', encoding="utf8") as f:
+            f.write(dotdata)
+    else:
+        with open(tmp_name, 'w') as f:
+            f.write(dotdata)
+    output_format = 'xdot'
+    progpath = '"%s"' % progs[prog].strip()
+    cmd = progpath + ' -T' + output_format + ' ' + options + ' ' + tmp_name
+    log.debug('Creating xdot data with: %s', cmd)
+    p = Popen(cmd, shell=True, stdout=PIPE, stderr=PIPE, close_fds=(sys.platform != 'win32'))
+    (stdout, stderr) = (p.stdout, p.stderr)
+    try:
+        data = stdout.read()
+    finally:
+        stdout.close()
+
+    try:
+        error_data = stderr.read()
+        if error_data:
+            if b'Error:' in error_data:
+                log.error("Graphviz returned with the following message: %s", error_data)
+            else:
+                # Graphviz raises a lot of warnings about too small labels,
+                # we therefore log them using log.debug to "hide" them
+                log.debug('Graphviz STDERR %s', error_data)
+    finally:
+        stderr.close()
+    p.kill()
+    p.wait()
+
+    os.unlink(tmp_name)
+    return data
+
+
+def parse_dot_data(dotdata):
+    """Wrapper for pydot.graph_from_dot_data
+
+    Redirects error messages to the log.
+    """
+    parser = dotparsing.DotDataParser()
+    try:
+        graph = parser.parse_dot_data(dotdata)
+    except dotparsing.ParseException:
+        raise
+    finally:
+        del parser
+    log.debug('Parsed graph:\n%s', str(graph))
+    return graph
+
+
+def parse_drawstring(drawstring):
+    """Parse drawstring and returns a list of draw operations"""
+
+    # The draw string parser is a bit clumsy and slow
+    def doeE(c, s):
+        """Parse ellipse"""
+        # E x0 y0 w h  Filled ellipse ((x-x0)/w)^2 + ((y-y0)/h)^2 = 1
+        # e x0 y0 w h  Unfilled ellipse ((x-x0)/w)^2 + ((y-y0)/h)^2 = 1
+        tokens = s.split()[0:4]
+        if not tokens:
+            return None
+        points = [float(t) for t in tokens]
+        didx = sum(len(t) for t in tokens) + len(points) + 1
+        return didx, (c, points[0], points[1], points[2], points[3])
+
+    def doPLB(c, s):
+        """Parse polygon, polyline og B-spline"""
+        # P n x1 y1 ... xn yn  Filled polygon using the given n points
+        # p n x1 y1 ... xn yn  Unfilled polygon using the given n points
+        # L n x1 y1 ... xn yn  Polyline using the given n points
+        # B n x1 y1 ... xn yn  B-spline using the given n control points
+        # b n x1 y1 ... xn yn  Filled B-spline using the given n control points
+        tokens = s.split()
+        n = int(tokens[0])
+        points = [float(t) for t in tokens[1:n * 2 + 1]]
+        didx = sum(len(t) for t in tokens[1:n * 2 + 1]) + n * 2 + 2
+        npoints = nsplit(points, 2)
+        return didx, (c, npoints)
+
+    def doCS(c, s):
+        """Parse fill or pen color"""
+        # C n -c1c2...cn  Set fill color.
+        # c n -c1c2...cn  Set pen color.
+        # Graphviz uses the following color formats:
+        # "#%2x%2x%2x"    Red-Green-Blue (RGB)
+        #   "#%2x%2x%2x%2x" Red-Green-Blue-Alpha (RGBA)
+        #   H[, ]+S[, ]+V   Hue-Saturation-Value (HSV) 0.0 <= H,S,V <= 1.0
+        #   string  color name
+        tokens = s.split()
+        n = int(tokens[0])
+        tmp = len(tokens[0]) + 3
+        d = s[tmp:tmp + n]
+        didx = len(d) + tmp + 1
+        return didx, (c, d)
+
+    def doFont(c, s):
+        # F s n -c1c2...cn
+        # Set font. The font size is s points. The font name consists of
+        # the n characters following '-'.
+        tokens = s.split()
+        size = tokens[0]
+        n = int(tokens[1])
+        tmp = len(size) + len(tokens[1]) + 4
+        d = s[tmp:tmp + n]
+        didx = len(d) + tmp
+        return didx, (c, size, d)
+
+    def doText(c, s):
+        # T x y j w n -c1c2...cn
+        # Text drawn using the baseline point (x,y). The text consists of the
+        # n characters following '-'. The text should be left-aligned
+        # (centered, right-aligned) on the point if j is -1 (0, 1), respectively.
+        # The value w gives the width of the text as computed by the library.
+        tokens = s.split()
+        x, y, j, w = tokens[0:4]
+        n = int(tokens[4])
+        tmp = sum(len(t) for t in tokens[0:5]) + 7
+        text = s[tmp:tmp + n]
+        didx = len(text) + tmp
+        return didx, [c, x, y, j, w, text]
+
+    cmdlist = []
+    stat = {}
+    idx = 0
+    s = drawstring.strip().replace('\\', '')
+    while idx < len(s) - 1:
+        didx = 1
+        c = s[idx]
+        stat[c] = stat.get(c, 0) + 1
+        try:
+            if c in ('e', 'E'):
+                didx, cmd = doeE(c, s[idx + 1:])
+                cmdlist.append(cmd)
+            elif c in ('p', 'P', 'L', 'b', 'B'):
+                didx, cmd = doPLB(c, s[idx + 1:])
+                cmdlist.append(cmd)
+            elif c in ('c', 'C', 'S'):
+                didx, cmd = doCS(c, s[idx + 1:])
+                cmdlist.append(cmd)
+            elif c == 'F':
+                didx, cmd = doFont(c, s[idx + 1:])
+                cmdlist.append(cmd)
+            elif c == 'T':
+                didx, cmd = doText(c, s[idx + 1:])
+                cmdlist.append(cmd)
+        except Exception as err:
+            log.debug("Failed to parse drawstring %s\n%s", s, str(err))
+
+        idx += didx
+    return cmdlist, stat
+
+
+def get_graphlist(gg, l=None):
+    """Traverse a graph with subgraphs and return them as a list"""
+    if not l:
+        l = []
+        outer = True
+    else:
+        outer = False
+    l.append(gg)
+    if gg.get_subgraphs():
+        for g in gg.get_subgraphs():
+            get_graphlist(g, l)
+    if outer:
+        return l
+
+
+def get_drawobj_lblstyle(drawobj, extra_styles=None):
+    try:
+        textcolor = f'text={drawobj.attr["fontcolor"]}'
+    except KeyError:
+        textcolor = None
+
+    return ', '.join(filter(None, [
+        drawobj.attr.get('lblstyle'),
+        textcolor,
+        extra_styles,
+    ])) or None
+
+
+class DotConvBase(object):
+    """Dot2TeX converter base"""
+
+    def __init__(self, options=None):
+        self.color = ""
+        self.opacity = None
+        try:
+            self.template
+        except AttributeError:
+            self.template = options.get('template', '')
+        self.textencoding = options.get('encoding', DEFAULT_TEXTENCODING)
+        self.templatevars = {}
+        self.body = ""
+        if options.get('templatefile', ''):
+            self.load_template(options['templatefile'])
+        if options.get('template', ''):
+            self.template = options['template']
+
+        self.options = options or {}
+        if options.get('texpreproc') or options.get('autosize'):
+            self.dopreproc = True
+        else:
+            self.dopreproc = False
+
+    def load_template(self, templatefile):
+        try:
+            with open(templatefile) as f:
+                self.template = f.read()
+        except:
+            pass
+
+    def convert_file(self, filename):
+        """Load dot file and convert"""
+        pass
+
+    def start_fig(self):
+        return ""
+
+    def end_fig(self):
+        return ""
+
+    def draw_ellipse(self, drawop, style=None):
+        return ""
+
+    def draw_bezier(self, drawop, style=None):
+        return ""
+
+    def draw_polygon(self, drawop, style=None):
+        return ""
+
+    def draw_polyline(self, drawop, style=None):
+        return ""
+
+    def draw_text(self, drawop, style=None):
+        return ""
+
+    def output_node_comment(self, node):
+        return "  %% Node: %s\n" % node.name
+
+    def output_edge_comment(self, edge):
+        src = edge.get_source()
+        dst = edge.get_destination()
+        if self.directedgraph:
+            edge = '->'
+        else:
+            edge = '--'
+        return "  %% Edge: %s %s %s\n" % (src, edge, dst)
+
+    def set_color(self, node):
+        return ""
+
+    def set_style(self, node):
+        return ""
+
+    def draw_edge(self, edge):
+        return ""
+
+    def start_node(self, node):
+        return ""
+
+    def end_node(self, node):
+        return ""
+
+    def start_graph(self, graph):
+        return ""
+
+    def end_graph(self, graph):
+        return ""
+
+    def start_edge(self):
+        return ""
+
+    def end_edge(self):
+        return ""
+
+    def filter_styles(self, style):
+        return style
+
+    def convert_color(self, drawopcolor, pgf=False):
+        """Convert color to a format usable by LaTeX and XColor"""
+        # Graphviz uses the following color formats:
+        # "#%2x%2x%2x"    Red-Green-Blue (RGB)
+        #   "#%2x%2x%2x%2x" Red-Green-Blue-Alpha (RGBA)
+        #   H[, ]+S[, ]+V   Hue-Saturation-Value (HSV) 0.0 <= H,S,V <= 1.0
+        #   string  color name
+
+        # Is the format RBG(A)?
+        if drawopcolor.startswith('#'):
+            t = list(chunks(drawopcolor[1:], 2))
+            # parallell lines not yet supported
+            if len(t) > 6:
+                t = t[0:3]
+            rgb = [(round((int(n, 16) / 255.0), 2)) for n in t]
+            if pgf:
+                colstr = "{rgb}{%s,%s,%s}" % tuple(rgb[0:3])
+                opacity = "1"
+                if len(rgb) == 4:
+                    opacity = rgb[3]
+                return colstr, opacity
+            else:
+                return "[rgb]{%s,%s,%s}" % tuple(rgb[0:3])
+
+        elif (len(drawopcolor.split(' ')) == 3) or (len(drawopcolor.split(',')) == 3):
+            # are the values space or comma separated?
+            hsb = drawopcolor.split(',')
+            if not len(hsb) == 3:
+                hsb = drawopcolor.split(' ')
+            if pgf:
+                return "{hsb}{%s,%s,%s}" % tuple(hsb)
+            else:
+                return "[hsb]{%s,%s,%s}" % tuple(hsb)
+        else:
+            drawopcolor = drawopcolor.replace('grey', 'gray')
+            drawopcolor = drawopcolor.replace('_', '')
+            drawopcolor = drawopcolor.replace(' ', '')
+            return drawopcolor
+
+    def do_drawstring(self, drawstring, drawobj, texlbl_name="texlbl", use_drawstring_pos=False):
+        """Parse and draw drawsting
+
+        Just a wrapper around do_draw_op.
+        """
+        drawoperations, stat = parse_drawstring(drawstring)
+        return self.do_draw_op(drawoperations, drawobj, stat, texlbl_name, use_drawstring_pos)
+
+    def do_draw_op(self, drawoperations, drawobj, stat, texlbl_name="texlbl", use_drawstring_pos=False):
+        """Excecute the operations in drawoperations"""
+        s = ""
+        for drawop in drawoperations:
+            op = drawop[0]
+            style = getattr(drawobj, 'style', None)
+            # styles are not passed to the draw operations in the
+            # duplicate mode
+            if style and not self.options.get('duplicate'):
+                # map Graphviz styles to backend styles
+                style = self.filter_styles(style)
+                styles = [self.styles.get(key.strip(), key.strip())
+                          for key in style.split(',') if key]
+                style = ','.join(styles)
+            else:
+                style = None
+
+            if op in ['e', 'E']:
+                s += self.draw_ellipse(drawop, style)
+            elif op in ['p', 'P']:
+                s += self.draw_polygon(drawop, style)
+            elif op == 'L':
+                s += self.draw_polyline(drawop, style)
+            elif op in ['C', 'c']:
+                s += self.set_color(drawop)
+            elif op == 'S':
+                s += self.set_style(drawop)
+            elif op in ['B']:
+                s += self.draw_bezier(drawop, style)
+            elif op in ['T']:
+                # Need to decide what to do with the text
+                # Note that graphviz removes the \ character from the draw
+                # string. Use \\ instead
+                # Todo: Use text from node|edge.label or name
+                # Todo: What about multiline labels?
+                text = drawop[5]
+                # head and tail label
+                texmode = self.options.get('texmode', 'verbatim')
+                label = text = drawobj.attr.get('label', '')
+                if drawobj.attr.get('texmode', ''):
+                    texmode = drawobj.attr['texmode']
+                if texlbl_name in drawobj.attr:
+                    # the texlbl overrides everything
+                    text = drawobj.attr[texlbl_name]
+                elif texmode == 'verbatim':
+                    # verbatim mode
+                    text = escape_texchars(text)
+                    pass
+                elif texmode == 'math':
+                    # math mode
+                    text = "$%s$" % text
+                elif label and len(drawoperations) == 1:
+                    text = label
+
+                drawop[5] = text
+                if self.options.get('alignstr', ''):
+                    drawop.append(self.options.get('alignstr'))
+                if stat['T'] == 1 and \
+                        self.options.get('valignmode', 'center') == 'center':
+                    # do this for single line only
+                    # force centered alignment
+                    drawop[3] = '0'
+                    if not use_drawstring_pos:
+                        if texlbl_name == "tailtexlbl":
+                            pos = drawobj.attr.get('tail_lp') or \
+                                  drawobj.attr.get('pos')
+                        elif texlbl_name == "headtexlbl":
+                            pos = drawobj.attr.get('head_lp') or \
+                                  drawobj.attr.get('pos')
+                        else:
+                            pos = drawobj.attr.get('lp') or \
+                                  drawobj.attr.get('pos')
+
+                        if pos:
+                            coord = pos.split(',')
+                            if len(coord) == 2:
+                                drawop[1] = coord[0]
+                                drawop[2] = coord[1]
+                            pass
+
+                lblstyle = get_drawobj_lblstyle(drawobj, extra_styles=drawobj.attr.get('exstyle'))
+                s += self.draw_text(drawop, lblstyle)
+        return s
+
+    def do_nodes(self):
+        s = ""
+        for node in self.nodes:
+            self.currentnode = node
+            general_draw_string = node.attr.get('_draw_', "")
+            label_string = node.attr.get('_ldraw_', "")
+
+            drawstring = general_draw_string + " " + label_string
+
+            if not drawstring.strip():
+                continue
+            # detect node type
+            shape = node.attr.get('shape', '')
+            if not shape:
+                shape = 'ellipse'  # default
+                # extract size information
+            x, y = node.attr.get('pos', '').split(',')
+
+            # width and height are in inches. Convert to bp units
+            # w = float(node.attr['width']) * INCH2BP
+            # h = float(node.attr['height']) * INCH2BP
+
+            s += self.output_node_comment(node)
+            s += self.start_node(node)
+            s += self.do_drawstring(drawstring, node)
+            s += self.end_node(node)
+        self.body += s
+
+    def get_edge_points(self, edge):
+        # edge BNF
+        # <edge>   :: <spline> (';' <spline>)*
+        #   <spline> :: <endp>? <startp>? <point> <triple>+
+        #   <point>  :: <x> ',' <y>
+        #   <triple> :: <point> <point> <point>
+        #   <endp>   :: "e" "," <x> "," <y>
+        ##        spline ( ';' spline )*
+        ##where spline  =   (endp)? (startp)? point (triple)+
+        ##and triple    =   point point point
+        ##and endp  =   "e,%d,%d"
+        ##and startp    =   "s,%d,%d"
+        ##If a spline has points p1 p2 p3 ... pn, (n = 1 (mod 3)), the points correspond to the control points of a B-spline from p1 to pn. If startp is given, it touches one node of the edge, and the arrowhead goes from p1 to startp. If startp is not given, p1 touches a node. Similarly for pn and endp.
+        pos = edge.attr.get('pos')
+        if pos:
+            segments = pos.split(';')
+        else:
+            return []
+
+        return_segments = []
+        for pos in segments:
+            points = pos.split(' ')
+            # check direction
+            arrow_style = '--'
+            i = 0
+            if points[i].startswith('s'):
+                p = points[0].split(',')
+                tmp = "%s,%s" % (p[1], p[2])
+                if points[1].startswith('e'):
+                    points[2] = tmp
+                else:
+                    points[1] = tmp
+                del points[0]
+                arrow_style = '<-'
+                i += 1
+            if points[0].startswith('e'):
+                p = points[0].split(',')
+                points.pop()
+                points.append("%s,%s" % (p[1], p[2]))
+                del points[0]
+                arrow_style = '->'
+                i += 1
+            if i > 1:
+                arrow_style = '<->'
+
+            arrow_style = self.get_output_arrow_styles(arrow_style, edge)
+
+            return_segments.append((arrow_style, points))
+
+        return return_segments
+
+    def do_edges(self):
+        s = ""
+        s += self.set_color(('cC', "black"))
+        for edge in self.edges:
+            general_draw_string = edge.attr.get('_draw_', "")
+            label_string = edge.attr.get('_ldraw_', "")
+            head_arrow_string = edge.attr.get('_hdraw_', "")
+            tail_arrow_string = edge.attr.get('_tdraw_', "")
+            tail_label_string = edge.attr.get('_tldraw_', "")
+            head_label_string = edge.attr.get('_hldraw_', "")
+
+            # Note that the order of the draw strings should be the same
+            # as in the xdot output.
+            drawstring = general_draw_string + " " + head_arrow_string + " " + tail_arrow_string \
+                         + " " + label_string
+            drawop, stat = parse_drawstring(drawstring)
+            if not drawstring.strip():
+                continue
+            s += self.output_edge_comment(edge)
+            if self.options.get('duplicate'):
+                s += self.start_edge()
+                s += self.do_draw_op(drawop, edge, stat)
+                s += self.do_drawstring(tail_label_string, edge, "tailtexlbl")
+                s += self.do_drawstring(head_label_string, edge, "headtexlbl")
+                s += self.end_edge()
+            else:
+                s += self.draw_edge(edge)
+                s += self.do_drawstring(label_string, edge)
+                s += self.do_drawstring(tail_label_string, edge, "tailtexlbl")
+                s += self.do_drawstring(head_label_string, edge, "headtexlbl")
+        self.body += s
+
+    def do_graph(self):
+        general_draw_string = self.graph.attr.get('_draw_', "")
+        label_string = self.graph.attr.get('_ldraw_', "")
+        # Avoid filling background of graphs with white
+        if general_draw_string.startswith('c 5 -white C 5 -white') \
+                and not self.graph.attr.get('style'):
+            general_draw_string = ''
+        if getattr(self.graph, '_draw_', None):
+            # bug
+            general_draw_string = "c 5 -black " + general_draw_string  # self.graph._draw_
+            pass
+        drawstring = general_draw_string + " " + label_string
+        if drawstring.strip():
+            s = self.start_graph(self.graph)
+            g = self.do_drawstring(drawstring, self.graph)
+            e = self.end_graph(self.graph)
+            if g.strip():
+                self.body += s + g + e
+
+    def set_options(self):
+        # process options
+        # Warning! If graph attribute is true and command line option is false,
+        # the graph attribute will be used. Command line option should have
+        # precedence.
+        self.options['alignstr'] = self.options.get('alignstr', '') \
+                                   or getattr(self.main_graph, 'd2talignstr', '')
+
+        # Todo: bad!
+        self.options['valignmode'] = getattr(self.main_graph, 'd2tvalignmode', '') \
+                                     or self.options.get('valignmode', 'center')
+
+    def convert(self, dotdata):
+        # parse data processed by dot.
+        log.debug('Start conversion')
+        main_graph = parse_dot_data(dotdata)
+
+        if not self.dopreproc and not hasattr(main_graph, 'xdotversion'):
+            # Older versions of Graphviz does not include the xdotversion
+            # attribute
+            if not (dotdata.find('_draw_') > 0 or dotdata.find('_ldraw_') > 0):
+                # need to convert to xdot format
+                # Warning. Pydot will not include custom attributes
+                log.info('Trying to create xdotdata')
+
+                tmpdata = create_xdot(dotdata, self.options.get('prog', 'dot'),
+                                      options=self.options.get('progoptions', ''))
+                if tmpdata is None or not tmpdata.strip():
+                    log.error('Failed to create xdotdata. Is Graphviz installed?')
+                    sys.exit(1)
+                log.debug('xdotdata:\n' + str(tmpdata))
+                main_graph = parse_dot_data(tmpdata)
+                log.debug('dotparsing graph:\n' + str(main_graph))
+            else:
+                # old version
+                pass
+
+        self.main_graph = main_graph
+        self.pencolor = ""
+        self.fillcolor = ""
+        self.linewidth = 1
+        # Detect graph type
+        self.directedgraph = main_graph.directed
+
+        if self.dopreproc:
+            return self.do_preview_preproc()
+
+        # Remove annoying square
+        # Todo: Remove squares from subgraphs. See pgram.dot
+        dstring = self.main_graph.attr.get('_draw_', "")
+        if dstring:
+            self.main_graph.attr['_draw_'] = ""
+
+        self.set_options()
+
+        # A graph can consists of nested graph. Extract all graphs
+        graphlist = get_graphlist(self.main_graph, [])
+
+        self.body += self.start_fig()
+
+        # To get correct drawing order we need to iterate over the graphs
+        # multiple times. First we draw the graph graphics, then nodes and
+        # finally the edges.
+
+        # todo: support the outputorder attribute
+        for graph in graphlist:
+            self.graph = graph
+            self.do_graph()
+
+        if True:
+            self.nodes = list(main_graph.allnodes)
+            self.edges = list(main_graph.alledges)
+            if not self.options.get('switchdraworder'):
+                self.do_edges()  # tmp
+                self.do_nodes()
+            else:
+                self.do_nodes()
+                self.do_edges()
+
+        self.body += self.end_fig()
+        return self.output()
+
+    def clean_template(self, template):
+        """Remove preprocsection or outputsection"""
+        if not self.dopreproc and self.options.get('codeonly'):
+            r = re.compile('<<startcodeonlysection>>(.*?)<<endcodeonlysection>>',
+                           re.DOTALL | re.MULTILINE)
+            m = r.search(template)
+            if m:
+                return m.group(1).strip()
+        if not self.dopreproc and self.options.get('figonly'):
+            r = re.compile('<<start_figonlysection>>(.*?)<<end_figonlysection>>',
+                           re.DOTALL | re.MULTILINE)
+            m = r.search(template)
+            if m:
+                return m.group(1)
+            r = re.compile('<<startfigonlysection>>(.*?)<<endfigonlysection>>',
+                           re.DOTALL | re.MULTILINE)
+            m = r.search(template)
+            if m:
+                return m.group(1)
+
+        if self.dopreproc:
+            r = re.compile('<<startoutputsection>>.*?<<endoutputsection>>',
+                           re.DOTALL | re.MULTILINE)
+        else:
+            r = re.compile('<<startpreprocsection>>.*?<<endpreprocsection>>',
+                           re.DOTALL | re.MULTILINE)
+            # remove codeonly and figonly section
+        r2 = re.compile('<<start_figonlysection>>.*?<<end_figonlysection>>',
+                        re.DOTALL | re.MULTILINE)
+        tmp = r2.sub('', template)
+        r2 = re.compile('<<startcodeonlysection>>.*?<<endcodeonlysection>>',
+                        re.DOTALL | re.MULTILINE)
+        tmp = r2.sub('', tmp)
+        return r.sub('', tmp)
+
+    def init_template_vars(self):
+        variables = {}
+        # get bounding box
+        bbstr = self.main_graph.attr.get('bb', '')
+        if bbstr:
+            bb = bbstr.split(',')
+            variables['<<bbox>>'] = "(%sbp,%sbp)(%sbp,%sbp)\n" % (
+                smart_float(bb[0]), smart_float(bb[1]), smart_float(bb[2]), smart_float(bb[3]))
+            variables['<<bbox.x0>>'] = bb[0]
+            variables['<<bbox.y0>>'] = bb[1]
+            variables['<<bbox.x1>>'] = bb[2]
+            variables['<<bbox.y1>>'] = bb[3]
+        variables['<<figcode>>'] = self.body.strip()
+        variables['<<drawcommands>>'] = self.body.strip()
+        variables['<<textencoding>>'] = self.textencoding
+        docpreamble = (self.options.get('docpreamble', '')
+                       or getattr(self.main_graph, 'd2tdocpreamble', ''))
+        variables['<<docpreamble>>'] = docpreamble
+        variables['<<figpreamble>>'] = self.options.get('figpreamble', '') \
+                                       or getattr(self.main_graph, 'd2tfigpreamble', '%')
+        variables['<<figpostamble>>'] = self.options.get('figpostamble', '') \
+                                        or getattr(self.main_graph, 'd2tfigpostamble', '')
+        variables['<<graphstyle>>'] = self.options.get('graphstyle', '') \
+                                      or getattr(self.main_graph, 'd2tgraphstyle', '')
+        variables['<<margin>>'] = self.options.get('margin', '0pt')
+        variables['<<startpreprocsection>>'] = variables['<<endpreprocsection>>'] = ''
+        variables['<<startoutputsection>>'] = variables['<<endoutputsection>>'] = ''
+        if self.options.get('gvcols'):
+            variables['<<gvcols>>'] = "\input{gvcols.tex}"
+        else:
+            variables['<<gvcols>>'] = ""
+        self.templatevars = variables
+
+    def output(self):
+        self.init_template_vars()
+        template = self.clean_template(self.template)
+        code = replace_tags(template, self.templatevars,
+                            self.templatevars)
+        return code
+
+    def get_label(self, drawobj, label_attribute="label", tex_label_attribute="texlbl"):
+        text = ""
+        texmode = self.options.get('texmode', 'verbatim')
+        if getattr(drawobj, 'texmode', ''):
+            texmode = drawobj.texmode
+        text = getattr(drawobj, label_attribute, None)
+
+        # log.warning('text %s %s',text,str(drawobj))
+
+        if text is None or text.strip() == '\\N':
+            if not isinstance(drawobj, dotparsing.DotEdge):
+                text = getattr(drawobj, 'name', None) or \
+                       getattr(drawobj, 'graph_name', '')
+                text = text.replace("\\\\", "\\")
+            else:
+                text = ''
+        elif text.strip() == '\\N':
+            text = ''
+        else:
+            text = text.replace("\\\\", "\\")
+
+        if getattr(drawobj, tex_label_attribute, ''):
+            # the texlbl overrides everything
+            text = drawobj.texlbl
+        elif texmode == 'verbatim':
+            # verbatim mode
+            text = escape_texchars(text)
+            pass
+        elif texmode == 'math':
+            # math mode
+            text = "$%s$" % text
+
+        return text
+
+    def get_node_preproc_code(self, node):
+        return node.attr.get('texlbl', '')
+
+    def get_edge_preproc_code(self, edge, attribute="texlbl"):
+        return edge.attr.get(attribute, '')
+
+    def get_graph_preproc_code(self, graph):
+        return graph.attr.get('texlbl', '')
+
+    def get_margins(self, element):
+        """Return element margins"""
+        margins = element.attr.get('margin')
+
+        if margins:
+            margins = margins.split(',')
+            if len(margins) == 1:
+                xmargin = ymargin = float(margins[0])
+            else:
+                xmargin = float(margins[0])
+                ymargin = float(margins[1])
+        else:
+            # use default values
+            if isinstance(element, dotparsing.DotEdge):
+                xmargin = DEFAULT_EDGELABEL_XMARGIN
+                ymargin = DEFAULT_EDGELABEL_YMARGIN
+            else:
+                xmargin = DEFAULT_LABEL_XMARGIN
+                ymargin = DEFAULT_LABEL_YMARGIN
+        return xmargin, ymargin
+
+    # Todo: Add support for head and tail labels!
+    # Todo: Support rect nodes if possible.
+    def do_preview_preproc(self):
+        # setDotAttr(self.maingraph)
+        self.init_template_vars()
+        template = self.clean_template(self.template)
+        template = replace_tags(template, self.templatevars,
+                                self.templatevars)
+        pp = TeXDimProc(template, self.options)
+        usednodes = {}
+        usededges = {}
+        usedgraphs = {}
+
+        # iterate over every element in the graph
+        counter = 0
+        for node in self.main_graph.allnodes:
+            name = node.name
+            if node.attr.get('fixedsize', '') == 'true' \
+                    or node.attr.get('style', '') in ['invis', 'invisible']:
+                continue
+            if node.attr.get('shape', '') == 'record':
+                log.warning('Record nodes not supported in preprocessing mode: %s', name)
+                continue
+            texlbl = self.get_label(node)
+
+            if texlbl:
+                node.attr['texlbl'] = texlbl
+                code = self.get_node_preproc_code(node)
+                pp.add_snippet(name, code)
+
+            usednodes[name] = node
+
+        for edge in dotparsing.flatten(self.main_graph.alledges):
+            if not edge.attr.get('label') and not edge.attr.get('texlbl') and not edge.attr.get("headlabel") \
+                    and not edge.attr.get("taillabel"):
+                continue
+            # Ensure that the edge name is unique.
+            name = edge.src.name + edge.dst.name + str(counter)
+            if is_multiline_label(edge):
+                continue
+            label = self.get_label(edge)
+            headlabel = self.get_label(edge, "headlabel", "headtexlbl")
+            taillabel = self.get_label(edge, "taillabel", "tailtexlbl")
+            if label:
+                name = edge.src.name + edge.dst.name + str(counter)
+                edge.attr['texlbl'] = label
+                code = self.get_edge_preproc_code(edge)
+                pp.add_snippet(name, code)
+
+            if headlabel:
+                headlabel_name = name + "headlabel"
+                edge.attr['headtexlbl'] = headlabel
+                code = self.get_edge_preproc_code(edge, "headtexlbl")
+                pp.add_snippet(headlabel_name, code)
+
+            if taillabel:
+                taillabel_name = name + "taillabel"
+                edge.attr['tailtexlbl'] = taillabel
+                code = self.get_edge_preproc_code(edge, "tailtexlbl")
+                pp.add_snippet(taillabel_name, code)
+
+            counter += 1
+            usededges[name] = edge
+
+        for graph in self.main_graph.allgraphs:
+            if not graph.attr.get('label') and not graph.attr.get('texlbl'):
+                continue
+            # Make sure that the name is unique
+            name = graph.name + str(counter)
+
+            counter += 1
+            label = self.get_label(graph)
+            graph.attr['texlbl'] = label
+            code = self.get_graph_preproc_code(graph)
+            pp.add_snippet(name, code)
+            usedgraphs[name] = graph
+
+        ok = pp.process()
+
+        if not ok:
+            errormsg = """\
+Failed to preprocess the graph.
+Is the preview LaTeX package installed? ((Debian package preview-latex-style)
+To see what happened, run dot2tex with the --debug option.
+"""
+            log.error(errormsg)
+            sys.exit(1)
+
+        for name, item in usednodes.items():
+            if not item.attr.get('texlbl'):
+                continue
+            node = item
+            hp, dp, wt = pp.texdims[name]
+            if self.options.get('rawdim'):
+                # use dimensions from preview.sty directly
+                node.attr['width'] = wt
+                node.attr['height'] = hp + dp
+                node.attr['label'] = " "
+                node.attr['fixedsize'] = 'true'
+                self.main_graph.allitems.append(node)
+                continue
+
+            xmargin, ymargin = self.get_margins(node)
+            ht = hp + dp
+            minwidth = float(item.attr.get('width') or DEFAULT_NODE_WIDTH)
+            minheight = float(item.attr.get('height') or DEFAULT_NODE_HEIGHT)
+            if self.options.get('nominsize'):
+                width = wt + 2 * xmargin
+                height = ht + 2 * ymargin
+            else:
+                if (wt + 2 * xmargin) < minwidth:
+                    width = minwidth
+                else:
+                    width = wt + 2 * xmargin
+                height = ht
+                if ((hp + dp) + 2 * ymargin) < minheight:
+                    height = minheight
+                else:
+                    height = ht + 2 * ymargin
+            # Treat shapes with equal width and height differently
+            # Warning! Rectangles will not always fit inside a circle
+            #          Should use the diagonal.
+            if item.attr.get('shape', '') in ['circle', 'Msquare', 'doublecircle', 'Mcircle']:
+                if wt < height and width < height:
+                    width = height
+                else:
+                    height = width
+
+            node.attr['width'] = width
+            node.attr['height'] = height
+            node.attr['label'] = " "
+
+            node.attr['fixedsize'] = 'true'
+            self.main_graph.allitems.append(node)
+
+        for name, item in usededges.items():
+            edge = item
+            hp, dp, wt = pp.texdims[name]
+            xmargin, ymargin = self.get_margins(edge)
+            labelcode = '<<<table border="0" cellborder="0" cellpadding="0">' \
+                        '<tr><td fixedsize="true" width="%s" height="%s">a</td>' \
+                        '</tr></table>>>'
+            if "texlbl" in edge.attr:
+                edge.attr['label'] = labelcode % ((wt + 2 * xmargin) * 72, (hp + dp + 2 * ymargin) * 72)
+            if "tailtexlbl" in edge.attr:
+                hp, dp, wt = pp.texdims[name + "taillabel"]
+                edge.attr['taillabel'] = labelcode % ((wt + 2 * xmargin) * 72, (hp + dp + 2 * ymargin) * 72)
+            if "headtexlbl" in edge.attr:
+                hp, dp, wt = pp.texdims[name + "headlabel"]
+                edge.attr['headlabel'] = labelcode % ((wt + 2 * xmargin) * 72, (hp + dp + 2 * ymargin) * 72)
+
+        for name, item in usedgraphs.items():
+            graph = item
+            hp, dp, wt = pp.texdims[name]
+            xmargin, ymargin = self.get_margins(graph)
+            labelcode = '<<<table border="0" cellborder="0" cellpadding="0">' \
+                        '<tr><td fixedsize="true" width="%s" height="%s">a</td>' \
+                        '</tr></table>>>'
+            graph.attr['label'] = labelcode % ((wt + 2 * xmargin) * 72, (hp + dp + 2 * ymargin) * 72)
+
+        self.main_graph.attr['d2toutputformat'] = self.options.get('format',
+                                                                   DEFAULT_OUTPUT_FORMAT)
+        graphcode = str(self.main_graph)
+        graphcode = graphcode.replace('<<<', '<<')
+        graphcode = graphcode.replace('>>>', '>>')
+        return graphcode
+
+    def get_output_arrow_styles(self, arrow_style, edge):
+        return arrow_style
+
+
+DEFAULT_GRAPHLABEL_XMARGIN = 0.01
+DEFAULT_GRAPHLABEL_YMARGIN = 0.01
+DEFAULT_NODE_WIDTH = 0.75
+DEFAULT_NODE_HEIGHT = 0.5
+dimext = r"""
+^.*? Preview:\s Snippet\s
+(?P<number>\d*)\s ended.
+\((?P<ht>\d*)\+(?P<dp>\d*)x(?P<wd>\d*)\)"""
+
+
+class TeXDimProc:
+    """Helper class for for finding the size of TeX snippets
+
+    Uses preview.sty
+    """
+
+    # Produce document
+    # Create a temporary directory
+    # Compile file with latex
+    # Parse log file
+    # Update graph with with and height parameters
+    # Clean up
+    def __init__(self, template, options):
+        self.template = template
+        self.snippets_code = []
+        self.snippets_id = []
+        self.options = options
+        self.dimext_re = re.compile(dimext, re.MULTILINE | re.VERBOSE)
+        pass
+
+    def add_snippet(self, snippet_id, code):
+        """A a snippet of code to be processed"""
+        self.snippets_id.append(snippet_id)
+        self.snippets_code.append(code)
+
+    def process(self):
+        """Process all snippets of code with TeX and preview.sty
+
+        Results are stored in the texdimlist and texdims class attributes.
+        Returns False if preprocessing fails
+        """
+        import shutil
+
+        if len(self.snippets_code) == 0:
+            log.warning('No labels to preprocess')
+            return True
+        self.tempdir = tempfile.mkdtemp(prefix='dot2tex')
+        log.debug('Creating temporary directroy %s' % self.tempdir)
+        self.tempfilename = os.path.join(self.tempdir, 'dot2tex.tex')
+        log.debug('Creating temporary file %s' % self.tempfilename)
+        s = ""
+        for n in self.snippets_code:
+            s += "\\begin{preview}%\n"
+            s += n.strip() + "%\n"
+            s += "\end{preview}%\n"
+        with open(self.tempfilename, 'w') as f:
+            f.write(self.template.replace('<<preproccode>>', s))
+        with open(self.tempfilename, 'r') as f:
+            s = f.read()
+        log.debug('Code written to %s\n' % self.tempfilename + s)
+        self.parse_log_file()
+        shutil.rmtree(self.tempdir)
+        log.debug('Temporary directory and files deleted')
+        if self.texdims:
+            return True
+        else:
+            return False
+            # cleanup
+
+    def parse_log_file(self):
+        logfilename = os.path.splitext(self.tempfilename)[0] + '.log'
+        tmpdir = os.getcwd()
+        os.chdir(os.path.split(logfilename)[0])
+        if self.options.get('usepdflatex'):
+            command = 'pdflatex -interaction=nonstopmode %s' % self.tempfilename
+        else:
+            command = 'latex -interaction=nonstopmode %s' % self.tempfilename
+        log.debug('Running command: %s' % command)
+
+        p = Popen(command, shell=True, stdout=PIPE, stderr=PIPE, close_fds=(sys.platform != 'win32'))
+        (stdout, stderr) = (p.stdout, p.stderr)
+        try:
+            data = stdout.read()
+            log.debug("stdout from latex\n %s", data)
+        finally:
+            stdout.close()
+
+        try:
+            error_data = stderr.read()
+            if error_data:
+                log.debug('latex STDERR %s', error_data)
+        finally:
+            stderr.close()
+        p.kill()
+        p.wait()
+
+        with open(logfilename, 'r') as f:
+            logdata = f.read()
+        log.debug('Logfile from LaTeX run: \n' + logdata)
+        os.chdir(tmpdir)
+
+        texdimdata = self.dimext_re.findall(logdata)
+        log.debug('Texdimdata: ' + str(texdimdata))
+        if len(texdimdata) == 0:
+            log.error('No dimension data could be extracted from dot2tex.tex.')
+            self.texdims = None
+            return
+
+        c = 1.0 / 4736286
+        self.texdims = {}
+        self.texdimlist = [(float(i[1]) * c, float(i[2]) * c, float(i[3]) * c) for i in texdimdata]
+        self.texdims = dict(zip(self.snippets_id, self.texdimlist))
diff --git a/dot2tex/dot2tex.py b/dot2tex/dot2tex.py
index 3c650c2..2a28674 100644
--- a/dot2tex/dot2tex.py
+++ b/dot2tex/dot2tex.py
@@ -27,56 +27,37 @@ Copyright (c) 2006-2019, Kjell Magne Fauske
 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 # IN THE SOFTWARE.
+from .base import DEFAULT_TEXTENCODING, DEFAULT_OUTPUT_FORMAT
+from .pgfformat import Dot2PGFConv, Dot2TikZConv, PositionsDotConv
+from .pstricksformat import Dot2PSTricksConv, Dot2PSTricksNConv
 
 __author__ = 'Kjell Magne Fauske'
-__version__ = '2.11.3'
+__version__ = '2.12.dev'
 __license__ = 'MIT'
 
 import argparse
 import os.path as path
-import sys, tempfile, os, re
+import sys, os, re
 import logging
-import warnings
-from subprocess import Popen, PIPE
 
 from . import dotparsing
 
 # initialize logging module
 log = logging.getLogger("dot2tex")
 
-DEFAULT_TEXTENCODING = 'utf8'
-DEFAULT_OUTPUT_FORMAT = 'pgf'
-
 # label margins in inches
-DEFAULT_LABEL_XMARGIN = 0.11
-DEFAULT_LABEL_YMARGIN = 0.055
-DEFAULT_EDGELABEL_XMARGIN = 0.01
-DEFAULT_EDGELABEL_YMARGIN = 0.01
-DEFAULT_GRAPHLABEL_XMARGIN = 0.01
-DEFAULT_GRAPHLABEL_YMARGIN = 0.01
-
-DEFAULT_NODE_WIDTH = 0.75
-DEFAULT_NODE_HEIGHT = 0.5
 
 # Todo: set papersize based on bb
-# Todo: Fontcolor
 
 # Todo: Support linewidth in draw string
 # Todo: Support linestyle in draw string
 # Todo: Need to reconsider edge draw order.
 # See for instance html2.xdot
 
-# Inch to bp conversion factor
-INCH2BP = 72.0
-
 # Examples of draw strings
 # c 5 -black F 14.000000 11 -Times-Roman T 99 159 0 44 8 -a_1 test
 
 
-SPECIAL_CHARS = ['$', '\\', '%', '_', '#', '{', r'}', '^', '&']
-SPECIAL_CHARS_REPLACE = [r'\$', r'$\backslash$', r'\%', r'\_', r'\#',
-                         r'\{', r'\}', r'\^{}', r'\&']
-charmap = dict(zip(SPECIAL_CHARS, SPECIAL_CHARS_REPLACE))
 
 helpmsg = """Failed to parse the input data. Is it a valid dot file?
 Try to input xdot data directly. Example:
@@ -90,2615 +71,8 @@ A file dot2tex.log will be written to the current directory with detailed
 information useful for debugging."""
 
 
-def mreplace(s, chararray, newchararray):
-    for a, b in zip(chararray, newchararray):
-        s = s.replace(a, b)
-    return s
-
-
-def escape_texchars(string):
-    r"""Escape the special LaTeX-chars %{}_^
-
-    Examples:
-
-    >>> escape_texchars('10%')
-    '10\\%'
-    >>> escape_texchars('%{}_^\\$')
-    '\\%\\{\\}\\_\\^{}$\\backslash$\\$'
-    """
-    return "".join([charmap.get(c, c) for c in string])
-
-
-def tikzify(s):
-    if s.strip():
-        return mreplace(s, r'\,:.()', '-+_*{}')
-    else:
-        return "d2tnn%i" % (len(s) + 1)
-
-
-def nsplit(seq, n=2):
-    """Split a sequence into pieces of length n
-
-    If the length of the sequence isn't a multiple of n, the rest is discarded.
-    Note that nsplit will strings into individual characters.
-
-    Examples:
-    >>> nsplit('aabbcc')
-    [('a', 'a'), ('b', 'b'), ('c', 'c')]
-    >>> nsplit('aabbcc',n=3)
-    [('a', 'a', 'b'), ('b', 'c', 'c')]
-
-    # Note that cc is discarded
-    >>> nsplit('aabbcc',n=4)
-    [('a', 'a', 'b', 'b')]
-    """
-    return [xy for xy in zip(*[iter(seq)] * n)]
-
-
-def chunks(s, cl):
-    """Split a string or sequence into pieces of length cl and return an iterator
-    """
-    for i in range(0, len(s), cl):
-        yield s[i:i + cl]
-
-
-def replace_tags(template, tags, tagsreplace):
-    """Replace occurrences of tags with tagsreplace
-
-    Example:
-    >>> replace_tags('a b c d',('b','d'),{'b':'bbb','d':'ddd'})
-    'a bbb c ddd'
-    """
-    s = template
-    for tag in tags:
-        replacestr = tagsreplace.get(tag, '')
-        if not replacestr:
-            replacestr = ''
-        s = s.replace(tag, replacestr)
-    return s
-
-
-def getboolattr(item, key, default):
-    if str(getattr(item, key, '')).lower() == 'true':
-        return True
-    else:
-        return False
-
-
-def smart_float(number):
-    number_as_string = "%s" % float(number)
-    if 'e' in number_as_string:
-        return "%.4f" % float(number)
-    else:
-        return number_as_string
-
-
-def is_multiline_label(drawobject):
-    # https://graphviz.gitlab.io/_pages/doc/info/attrs.html#k:escString
-    if getattr(drawobject, "texlbl", None):
-        return False
-
-    label = getattr(drawobject, "label", "")
-    return any(x in label for x in [r"\n", r"\l", r"\r"])
-
-
-def create_xdot(dotdata, prog='dot', options=''):
-    """Run a graph through Graphviz and return an xdot-version of the graph"""
-    # The following code is from the pydot module written by Ero Carrera
-    progs = dotparsing.find_graphviz()
-
-    # prog = 'dot'
-    if progs is None:
-        log.error('Could not locate Graphviz binaries')
-        return None
-    if not prog in progs:
-        log.error('Invalid prog=%s', prog)
-        raise NameError('The %s program is not recognized. Valid values are %s' % (prog, list(progs)))
-
-    tmp_fd, tmp_name = tempfile.mkstemp()
-    os.close(tmp_fd)
-    if os.sys.version_info[0] >= 3:
-        with open(tmp_name, 'w', encoding="utf8") as f:
-            f.write(dotdata)
-    else:
-        with open(tmp_name, 'w') as f:
-            f.write(dotdata)
-    output_format = 'xdot'
-    progpath = '"%s"' % progs[prog].strip()
-    cmd = progpath + ' -T' + output_format + ' ' + options + ' ' + tmp_name
-    log.debug('Creating xdot data with: %s', cmd)
-    p = Popen(cmd, shell=True, stdout=PIPE, stderr=PIPE, close_fds=(sys.platform != 'win32'))
-    (stdout, stderr) = (p.stdout, p.stderr)
-    try:
-        data = stdout.read()
-    finally:
-        stdout.close()
-
-    try:
-        error_data = stderr.read()
-        if error_data:
-            if b'Error:' in error_data:
-                log.error("Graphviz returned with the following message: %s", error_data)
-            else:
-                # Graphviz raises a lot of warnings about too small labels,
-                # we therefore log them using log.debug to "hide" them
-                log.debug('Graphviz STDERR %s', error_data)
-    finally:
-        stderr.close()
-    p.kill()
-    p.wait()
-
-    os.unlink(tmp_name)
-    return data
-
-
-def parse_dot_data(dotdata):
-    """Wrapper for pydot.graph_from_dot_data
-
-    Redirects error messages to the log.
-    """
-    parser = dotparsing.DotDataParser()
-    try:
-        graph = parser.parse_dot_data(dotdata)
-    except dotparsing.ParseException:
-        raise
-    finally:
-        del parser
-    log.debug('Parsed graph:\n%s', str(graph))
-    return graph
-
-
-def parse_drawstring(drawstring):
-    """Parse drawstring and returns a list of draw operations"""
-
-    # The draw string parser is a bit clumsy and slow
-    def doeE(c, s):
-        """Parse ellipse"""
-        # E x0 y0 w h  Filled ellipse ((x-x0)/w)^2 + ((y-y0)/h)^2 = 1
-        # e x0 y0 w h  Unfilled ellipse ((x-x0)/w)^2 + ((y-y0)/h)^2 = 1
-        tokens = s.split()[0:4]
-        if not tokens:
-            return None
-        points = [float(t) for t in tokens]
-        didx = sum(len(t) for t in tokens) + len(points) + 1
-        return didx, (c, points[0], points[1], points[2], points[3])
-
-    def doPLB(c, s):
-        """Parse polygon, polyline og B-spline"""
-        # P n x1 y1 ... xn yn  Filled polygon using the given n points
-        # p n x1 y1 ... xn yn  Unfilled polygon using the given n points
-        # L n x1 y1 ... xn yn  Polyline using the given n points
-        # B n x1 y1 ... xn yn  B-spline using the given n control points
-        # b n x1 y1 ... xn yn  Filled B-spline using the given n control points
-        tokens = s.split()
-        n = int(tokens[0])
-        points = [float(t) for t in tokens[1:n * 2 + 1]]
-        didx = sum(len(t) for t in tokens[1:n * 2 + 1]) + n * 2 + 2
-        npoints = nsplit(points, 2)
-        return didx, (c, npoints)
-
-    def doCS(c, s):
-        """Parse fill or pen color"""
-        # C n -c1c2...cn  Set fill color.
-        # c n -c1c2...cn  Set pen color.
-        # Graphviz uses the following color formats:
-        # "#%2x%2x%2x"    Red-Green-Blue (RGB)
-        #   "#%2x%2x%2x%2x" Red-Green-Blue-Alpha (RGBA)
-        #   H[, ]+S[, ]+V   Hue-Saturation-Value (HSV) 0.0 <= H,S,V <= 1.0
-        #   string  color name
-        tokens = s.split()
-        n = int(tokens[0])
-        tmp = len(tokens[0]) + 3
-        d = s[tmp:tmp + n]
-        didx = len(d) + tmp + 1
-        return didx, (c, d)
-
-    def doFont(c, s):
-        # F s n -c1c2...cn
-        # Set font. The font size is s points. The font name consists of
-        # the n characters following '-'.
-        tokens = s.split()
-        size = tokens[0]
-        n = int(tokens[1])
-        tmp = len(size) + len(tokens[1]) + 4
-        d = s[tmp:tmp + n]
-        didx = len(d) + tmp
-        return didx, (c, size, d)
-
-    def doText(c, s):
-        # T x y j w n -c1c2...cn
-        # Text drawn using the baseline point (x,y). The text consists of the
-        # n characters following '-'. The text should be left-aligned
-        # (centered, right-aligned) on the point if j is -1 (0, 1), respectively.
-        # The value w gives the width of the text as computed by the library.
-        tokens = s.split()
-        x, y, j, w = tokens[0:4]
-        n = int(tokens[4])
-        tmp = sum(len(t) for t in tokens[0:5]) + 7
-        text = s[tmp:tmp + n]
-        didx = len(text) + tmp
-        return didx, [c, x, y, j, w, text]
-
-    cmdlist = []
-    stat = {}
-    idx = 0
-    s = drawstring.strip().replace('\\', '')
-    while idx < len(s) - 1:
-        didx = 1
-        c = s[idx]
-        stat[c] = stat.get(c, 0) + 1
-        try:
-            if c in ('e', 'E'):
-                didx, cmd = doeE(c, s[idx + 1:])
-                cmdlist.append(cmd)
-            elif c in ('p', 'P', 'L', 'b', 'B'):
-                didx, cmd = doPLB(c, s[idx + 1:])
-                cmdlist.append(cmd)
-            elif c in ('c', 'C', 'S'):
-                didx, cmd = doCS(c, s[idx + 1:])
-                cmdlist.append(cmd)
-            elif c == 'F':
-                didx, cmd = doFont(c, s[idx + 1:])
-                cmdlist.append(cmd)
-            elif c == 'T':
-                didx, cmd = doText(c, s[idx + 1:])
-                cmdlist.append(cmd)
-        except Exception as err:
-            log.debug("Failed to parse drawstring %s\n%s", s, err.message)
-
-        idx += didx
-    return cmdlist, stat
-
-
-def get_graphlist(gg, l=None):
-    """Traverse a graph with subgraphs and return them as a list"""
-    if not l:
-        l = []
-        outer = True
-    else:
-        outer = False
-    l.append(gg)
-    if gg.get_subgraphs():
-        for g in gg.get_subgraphs():
-            get_graphlist(g, l)
-    if outer:
-        return l
-
-
-class EndOfGraphElement(object):
-    def __init__(self):
-        pass
-
-
-def get_all_graph_elements(graph, l=None):
-    """Return all nodes and edges, including elements in subgraphs"""
-    if not l:
-        l = []
-        outer = True
-        l.append(graph)
-    else:
-        outer = False
-    for element in graph.allitems:
-        if isinstance(element, dotparsing.DotSubGraph):
-            l.append(element)
-            get_all_graph_elements(element, l)
-        else:
-            l.append(element)
-
-    if outer:
-        return l
-    else:
-        l.append(EndOfGraphElement())
-
-
-class DotConvBase(object):
-    """Dot2TeX converter base"""
-
-    def __init__(self, options=None):
-        self.color = ""
-        self.opacity = None
-        try:
-            self.template
-        except AttributeError:
-            self.template = options.get('template', '')
-        self.textencoding = options.get('encoding', DEFAULT_TEXTENCODING)
-        self.templatevars = {}
-        self.body = ""
-        if options.get('templatefile', ''):
-            self.load_template(options['templatefile'])
-        if options.get('template', ''):
-            self.template = options['template']
-
-        self.options = options or {}
-        if options.get('texpreproc') or options.get('autosize'):
-            self.dopreproc = True
-        else:
-            self.dopreproc = False
-
-    def load_template(self, templatefile):
-        try:
-            with open(templatefile) as f:
-                self.template = f.read()
-        except:
-            pass
-
-    def convert_file(self, filename):
-        """Load dot file and convert"""
-        pass
-
-    def start_fig(self):
-        return ""
-
-    def end_fig(self):
-        return ""
-
-    def draw_ellipse(self, drawop, style=None):
-        return ""
-
-    def draw_bezier(self, drawop, style=None):
-        return ""
-
-    def draw_polygon(self, drawop, style=None):
-        return ""
-
-    def draw_polyline(self, drawop, style=None):
-        return ""
-
-    def draw_text(self, drawop, style=None):
-        return ""
-
-    def output_node_comment(self, node):
-        return "  %% Node: %s\n" % node.name
-
-    def output_edge_comment(self, edge):
-        src = edge.get_source()
-        dst = edge.get_destination()
-        if self.directedgraph:
-            edge = '->'
-        else:
-            edge = '--'
-        return "  %% Edge: %s %s %s\n" % (src, edge, dst)
-
-    def set_color(self, node):
-        return ""
-
-    def set_style(self, node):
-        return ""
-
-    def draw_edge(self, edge):
-        return ""
-
-    def start_node(self, node):
-        return ""
-
-    def end_node(self, node):
-        return ""
-
-    def start_graph(self, graph):
-        return ""
-
-    def end_graph(self, graph):
-        return ""
-
-    def start_edge(self):
-        return ""
-
-    def end_edge(self):
-        return ""
-
-    def filter_styles(self, style):
-        return style
-
-    def convert_color(self, drawopcolor, pgf=False):
-        """Convert color to a format usable by LaTeX and XColor"""
-        # Graphviz uses the following color formats:
-        # "#%2x%2x%2x"    Red-Green-Blue (RGB)
-        #   "#%2x%2x%2x%2x" Red-Green-Blue-Alpha (RGBA)
-        #   H[, ]+S[, ]+V   Hue-Saturation-Value (HSV) 0.0 <= H,S,V <= 1.0
-        #   string  color name
-
-        # Is the format RBG(A)?
-        if drawopcolor.startswith('#'):
-            t = list(chunks(drawopcolor[1:], 2))
-            # parallell lines not yet supported
-            if len(t) > 6:
-                t = t[0:3]
-            rgb = [(round((int(n, 16) / 255.0), 2)) for n in t]
-            if pgf:
-                colstr = "{rgb}{%s,%s,%s}" % tuple(rgb[0:3])
-                opacity = "1"
-                if len(rgb) == 4:
-                    opacity = rgb[3]
-                return colstr, opacity
-            else:
-                return "[rgb]{%s,%s,%s}" % tuple(rgb[0:3])
-
-        elif (len(drawopcolor.split(' ')) == 3) or (len(drawopcolor.split(',')) == 3):
-            # are the values space or comma separated?
-            hsb = drawopcolor.split(',')
-            if not len(hsb) == 3:
-                hsb = drawopcolor.split(' ')
-            if pgf:
-                return "{hsb}{%s,%s,%s}" % tuple(hsb)
-            else:
-                return "[hsb]{%s,%s,%s}" % tuple(hsb)
-        else:
-            drawopcolor = drawopcolor.replace('grey', 'gray')
-            drawopcolor = drawopcolor.replace('_', '')
-            drawopcolor = drawopcolor.replace(' ', '')
-            return drawopcolor
-
-    def do_drawstring(self, drawstring, drawobj, texlbl_name="texlbl", use_drawstring_pos=False):
-        """Parse and draw drawsting
-
-        Just a wrapper around do_draw_op.
-        """
-        drawoperations, stat = parse_drawstring(drawstring)
-        return self.do_draw_op(drawoperations, drawobj, stat, texlbl_name, use_drawstring_pos)
-
-    def do_draw_op(self, drawoperations, drawobj, stat, texlbl_name="texlbl", use_drawstring_pos=False):
-        """Excecute the operations in drawoperations"""
-        s = ""
-        for drawop in drawoperations:
-            op = drawop[0]
-            style = getattr(drawobj, 'style', None)
-            # styles are not passed to the draw operations in the
-            # duplicate mode
-            if style and not self.options.get('duplicate'):
-                # map Graphviz styles to backend styles
-                style = self.filter_styles(style)
-                styles = [self.styles.get(key.strip(), key.strip())
-                          for key in style.split(',') if key]
-                style = ','.join(styles)
-            else:
-                style = None
-
-            if op in ['e', 'E']:
-                s += self.draw_ellipse(drawop, style)
-            elif op in ['p', 'P']:
-                s += self.draw_polygon(drawop, style)
-            elif op == 'L':
-                s += self.draw_polyline(drawop, style)
-            elif op in ['C', 'c']:
-                s += self.set_color(drawop)
-            elif op == 'S':
-                s += self.set_style(drawop)
-            elif op in ['B']:
-                s += self.draw_bezier(drawop, style)
-            elif op in ['T']:
-                # Need to decide what to do with the text
-                # Note that graphviz removes the \ character from the draw
-                # string. Use \\ instead
-                # Todo: Use text from node|edge.label or name
-                # Todo: What about multiline labels?
-                text = drawop[5]
-                # head and tail label
-                texmode = self.options.get('texmode', 'verbatim')
-                if drawobj.attr.get('texmode', ''):
-                    texmode = drawobj.attr['texmode']
-                if texlbl_name in drawobj.attr:
-                    # the texlbl overrides everything
-                    text = drawobj.attr[texlbl_name]
-                elif texmode == 'verbatim':
-                    # verbatim mode
-                    text = escape_texchars(text)
-                    pass
-                elif texmode == 'math':
-                    # math mode
-                    text = "$%s$" % text
-
-                drawop[5] = text
-                if self.options.get('alignstr', ''):
-                    drawop.append(self.options.get('alignstr'))
-                if stat['T'] == 1 and \
-                        self.options.get('valignmode', 'center') == 'center':
-                    # do this for single line only
-                    # force centered alignment
-                    drawop[3] = '0'
-                    if not use_drawstring_pos:
-                        if texlbl_name == "tailtexlbl":
-                            pos = drawobj.attr.get('tail_lp') or \
-                                  drawobj.attr.get('pos')
-                        elif texlbl_name == "headtexlbl":
-                            pos = drawobj.attr.get('head_lp') or \
-                                  drawobj.attr.get('pos')
-                        else:
-                            pos = drawobj.attr.get('lp') or \
-                                  drawobj.attr.get('pos')
-
-                        if pos:
-                            coord = pos.split(',')
-                            if len(coord) == 2:
-                                drawop[1] = coord[0]
-                                drawop[2] = coord[1]
-                            pass
-                lblstyle = drawobj.attr.get('lblstyle')
-                exstyle = drawobj.attr.get('exstyle', '')
-                if exstyle:
-                    if lblstyle:
-                        lblstyle += ',' + exstyle
-                    else:
-                        lblstyle = exstyle
-                s += self.draw_text(drawop, lblstyle)
-        return s
-
-    def do_nodes(self):
-        s = ""
-        for node in self.nodes:
-            self.currentnode = node
-            general_draw_string = node.attr.get('_draw_', "")
-            label_string = node.attr.get('_ldraw_', "")
-
-            drawstring = general_draw_string + " " + label_string
-
-            if not drawstring.strip():
-                continue
-            # detect node type
-            shape = node.attr.get('shape', '')
-            if not shape:
-                shape = 'ellipse'  # default
-                # extract size information
-            x, y = node.attr.get('pos', '').split(',')
-
-            # width and height are in inches. Convert to bp units
-            # w = float(node.attr['width']) * INCH2BP
-            # h = float(node.attr['height']) * INCH2BP
-
-            s += self.output_node_comment(node)
-            s += self.start_node(node)
-            s += self.do_drawstring(drawstring, node)
-            s += self.end_node(node)
-        self.body += s
-
-    def get_edge_points(self, edge):
-        # edge BNF
-        # <edge>   :: <spline> (';' <spline>)*
-        #   <spline> :: <endp>? <startp>? <point> <triple>+
-        #   <point>  :: <x> ',' <y>
-        #   <triple> :: <point> <point> <point>
-        #   <endp>   :: "e" "," <x> "," <y>
-        ##        spline ( ';' spline )*
-        ##where spline  =   (endp)? (startp)? point (triple)+
-        ##and triple    =   point point point
-        ##and endp  =   "e,%d,%d"
-        ##and startp    =   "s,%d,%d"
-        ##If a spline has points p1 p2 p3 ... pn, (n = 1 (mod 3)), the points correspond to the control points of a B-spline from p1 to pn. If startp is given, it touches one node of the edge, and the arrowhead goes from p1 to startp. If startp is not given, p1 touches a node. Similarly for pn and endp.
-        pos = edge.attr.get('pos')
-        if pos:
-            segments = pos.split(';')
-        else:
-            return []
-
-        return_segments = []
-        for pos in segments:
-            points = pos.split(' ')
-            # check direction
-            arrow_style = '--'
-            i = 0
-            if points[i].startswith('s'):
-                p = points[0].split(',')
-                tmp = "%s,%s" % (p[1], p[2])
-                if points[1].startswith('e'):
-                    points[2] = tmp
-                else:
-                    points[1] = tmp
-                del points[0]
-                arrow_style = '<-'
-                i += 1
-            if points[0].startswith('e'):
-                p = points[0].split(',')
-                points.pop()
-                points.append("%s,%s" % (p[1], p[2]))
-                del points[0]
-                arrow_style = '->'
-                i += 1
-            if i > 1:
-                arrow_style = '<->'
-
-            arrow_style = self.get_output_arrow_styles(arrow_style, edge)
-
-            return_segments.append((arrow_style, points))
-
-        return return_segments
-
-    def do_edges(self):
-        s = ""
-        s += self.set_color(('cC', "black"))
-        for edge in self.edges:
-            general_draw_string = edge.attr.get('_draw_', "")
-            label_string = edge.attr.get('_ldraw_', "")
-            head_arrow_string = edge.attr.get('_hdraw_', "")
-            tail_arrow_string = edge.attr.get('_tdraw_', "")
-            tail_label_string = edge.attr.get('_tldraw_', "")
-            head_label_string = edge.attr.get('_hldraw_', "")
-
-            # Note that the order of the draw strings should be the same
-            # as in the xdot output.
-            drawstring = general_draw_string + " " + head_arrow_string + " " + tail_arrow_string \
-                         + " " + label_string
-            drawop, stat = parse_drawstring(drawstring)
-            if not drawstring.strip():
-                continue
-            s += self.output_edge_comment(edge)
-            if self.options.get('duplicate'):
-                s += self.start_edge()
-                s += self.do_draw_op(drawop, edge, stat)
-                s += self.do_drawstring(tail_label_string, edge, "tailtexlbl")
-                s += self.do_drawstring(head_label_string, edge, "headtexlbl")
-                s += self.end_edge()
-            else:
-                s += self.draw_edge(edge)
-                s += self.do_drawstring(label_string, edge)
-                s += self.do_drawstring(tail_label_string, edge, "tailtexlbl")
-                s += self.do_drawstring(head_label_string, edge, "headtexlbl")
-        self.body += s
-
-    def do_graph(self):
-        general_draw_string = self.graph.attr.get('_draw_', "")
-        label_string = self.graph.attr.get('_ldraw_', "")
-        # Avoid filling background of graphs with white
-        if general_draw_string.startswith('c 5 -white C 5 -white') \
-                and not self.graph.attr.get('style'):
-            general_draw_string = ''
-        if getattr(self.graph, '_draw_', None):
-            # bug
-            general_draw_string = "c 5 -black " + general_draw_string  # self.graph._draw_
-            pass
-        drawstring = general_draw_string + " " + label_string
-        if drawstring.strip():
-            s = self.start_graph(self.graph)
-            g = self.do_drawstring(drawstring, self.graph)
-            e = self.end_graph(self.graph)
-            if g.strip():
-                self.body += s + g + e
-
-    def set_options(self):
-        # process options
-        # Warning! If graph attribute is true and command line option is false,
-        # the graph attribute will be used. Command line option should have
-        # precedence.
-        self.options['alignstr'] = self.options.get('alignstr', '') \
-                                   or getattr(self.main_graph, 'd2talignstr', '')
-
-        # Todo: bad!
-        self.options['valignmode'] = getattr(self.main_graph, 'd2tvalignmode', '') \
-                                     or self.options.get('valignmode', 'center')
-
-    def convert(self, dotdata):
-        # parse data processed by dot.
-        log.debug('Start conversion')
-        main_graph = parse_dot_data(dotdata)
-
-        if not self.dopreproc and not hasattr(main_graph, 'xdotversion'):
-            # Older versions of Graphviz does not include the xdotversion
-            # attribute
-            if not (dotdata.find('_draw_') > 0 or dotdata.find('_ldraw_') > 0):
-                # need to convert to xdot format
-                # Warning. Pydot will not include custom attributes
-                log.info('Trying to create xdotdata')
-
-                tmpdata = create_xdot(dotdata, self.options.get('prog', 'dot'),
-                                      options=self.options.get('progoptions', ''))
-                if tmpdata is None or not tmpdata.strip():
-                    log.error('Failed to create xdotdata. Is Graphviz installed?')
-                    sys.exit(1)
-                log.debug('xdotdata:\n' + str(tmpdata))
-                main_graph = parse_dot_data(tmpdata)
-                log.debug('dotparsing graph:\n' + str(main_graph))
-            else:
-                # old version
-                pass
-
-        self.main_graph = main_graph
-        self.pencolor = ""
-        self.fillcolor = ""
-        self.linewidth = 1
-        # Detect graph type
-        self.directedgraph = main_graph.directed
-
-        if self.dopreproc:
-            return self.do_preview_preproc()
-
-        # Remove annoying square
-        # Todo: Remove squares from subgraphs. See pgram.dot
-        dstring = self.main_graph.attr.get('_draw_', "")
-        if dstring:
-            self.main_graph.attr['_draw_'] = ""
-
-        self.set_options()
-
-        # A graph can consists of nested graph. Extract all graphs
-        graphlist = get_graphlist(self.main_graph, [])
-
-        self.body += self.start_fig()
-
-        # To get correct drawing order we need to iterate over the graphs
-        # multiple times. First we draw the graph graphics, then nodes and
-        # finally the edges.
-
-        # todo: support the outputorder attribute
-        for graph in graphlist:
-            self.graph = graph
-            self.do_graph()
-
-        if True:
-            self.nodes = list(main_graph.allnodes)
-            self.edges = list(main_graph.alledges)
-            if not self.options.get('switchdraworder'):
-                self.do_edges()  # tmp
-                self.do_nodes()
-            else:
-                self.do_nodes()
-                self.do_edges()
-
-        self.body += self.end_fig()
-        return self.output()
-
-    def clean_template(self, template):
-        """Remove preprocsection or outputsection"""
-        if not self.dopreproc and self.options.get('codeonly'):
-            r = re.compile('<<startcodeonlysection>>(.*?)<<endcodeonlysection>>',
-                           re.DOTALL | re.MULTILINE)
-            m = r.search(template)
-            if m:
-                return m.group(1).strip()
-        if not self.dopreproc and self.options.get('figonly'):
-            r = re.compile('<<start_figonlysection>>(.*?)<<end_figonlysection>>',
-                           re.DOTALL | re.MULTILINE)
-            m = r.search(template)
-            if m:
-                return m.group(1)
-            r = re.compile('<<startfigonlysection>>(.*?)<<endfigonlysection>>',
-                           re.DOTALL | re.MULTILINE)
-            m = r.search(template)
-            if m:
-                return m.group(1)
-
-        if self.dopreproc:
-            r = re.compile('<<startoutputsection>>.*?<<endoutputsection>>',
-                           re.DOTALL | re.MULTILINE)
-        else:
-            r = re.compile('<<startpreprocsection>>.*?<<endpreprocsection>>',
-                           re.DOTALL | re.MULTILINE)
-            # remove codeonly and figonly section
-        r2 = re.compile('<<start_figonlysection>>.*?<<end_figonlysection>>',
-                        re.DOTALL | re.MULTILINE)
-        tmp = r2.sub('', template)
-        r2 = re.compile('<<startcodeonlysection>>.*?<<endcodeonlysection>>',
-                        re.DOTALL | re.MULTILINE)
-        tmp = r2.sub('', tmp)
-        return r.sub('', tmp)
-
-    def init_template_vars(self):
-        variables = {}
-        # get bounding box
-        bbstr = self.main_graph.attr.get('bb', '')
-        if bbstr:
-            bb = bbstr.split(',')
-            variables['<<bbox>>'] = "(%sbp,%sbp)(%sbp,%sbp)\n" % (
-                smart_float(bb[0]), smart_float(bb[1]), smart_float(bb[2]), smart_float(bb[3]))
-            variables['<<bbox.x0>>'] = bb[0]
-            variables['<<bbox.y0>>'] = bb[1]
-            variables['<<bbox.x1>>'] = bb[2]
-            variables['<<bbox.y1>>'] = bb[3]
-        variables['<<figcode>>'] = self.body.strip()
-        variables['<<drawcommands>>'] = self.body.strip()
-        variables['<<textencoding>>'] = self.textencoding
-        docpreamble = (self.options.get('docpreamble', '')
-                       or getattr(self.main_graph, 'd2tdocpreamble', ''))
-        variables['<<docpreamble>>'] = docpreamble
-        variables['<<figpreamble>>'] = self.options.get('figpreamble', '') \
-                                       or getattr(self.main_graph, 'd2tfigpreamble', '%')
-        variables['<<figpostamble>>'] = self.options.get('figpostamble', '') \
-                                        or getattr(self.main_graph, 'd2tfigpostamble', '')
-        variables['<<graphstyle>>'] = self.options.get('graphstyle', '') \
-                                      or getattr(self.main_graph, 'd2tgraphstyle', '')
-        variables['<<margin>>'] = self.options.get('margin', '0pt')
-        variables['<<startpreprocsection>>'] = variables['<<endpreprocsection>>'] = ''
-        variables['<<startoutputsection>>'] = variables['<<endoutputsection>>'] = ''
-        if self.options.get('gvcols'):
-            variables['<<gvcols>>'] = "\input{gvcols.tex}"
-        else:
-            variables['<<gvcols>>'] = ""
-        self.templatevars = variables
-
-    def output(self):
-        self.init_template_vars()
-        template = self.clean_template(self.template)
-        code = replace_tags(template, self.templatevars,
-                            self.templatevars)
-        return code
-
-    def get_label(self, drawobj, label_attribute="label", tex_label_attribute="texlbl"):
-        text = ""
-        texmode = self.options.get('texmode', 'verbatim')
-        if getattr(drawobj, 'texmode', ''):
-            texmode = drawobj.texmode
-        text = getattr(drawobj, label_attribute, None)
-
-        # log.warning('text %s %s',text,str(drawobj))
-
-        if text is None or text.strip() == '\\N':
-            if not isinstance(drawobj, dotparsing.DotEdge):
-                text = getattr(drawobj, 'name', None) or \
-                       getattr(drawobj, 'graph_name', '')
-                text = text.replace("\\\\", "\\")
-            else:
-                text = ''
-        elif text.strip() == '\\N':
-            text = ''
-        else:
-            text = text.replace("\\\\", "\\")
-
-        if getattr(drawobj, tex_label_attribute, ''):
-            # the texlbl overrides everything
-            text = drawobj.texlbl
-        elif texmode == 'verbatim':
-            # verbatim mode
-            text = escape_texchars(text)
-            pass
-        elif texmode == 'math':
-            # math mode
-            text = "$%s$" % text
-
-        return text
-
-    def get_node_preproc_code(self, node):
-        return node.attr.get('texlbl', '')
-
-    def get_edge_preproc_code(self, edge, attribute="texlbl"):
-        return edge.attr.get(attribute, '')
-
-    def get_graph_preproc_code(self, graph):
-        return graph.attr.get('texlbl', '')
-
-    def get_margins(self, element):
-        """Return element margins"""
-        margins = element.attr.get('margin')
-
-        if margins:
-            margins = margins.split(',')
-            if len(margins) == 1:
-                xmargin = ymargin = float(margins[0])
-            else:
-                xmargin = float(margins[0])
-                ymargin = float(margins[1])
-        else:
-            # use default values
-            if isinstance(element, dotparsing.DotEdge):
-                xmargin = DEFAULT_EDGELABEL_XMARGIN
-                ymargin = DEFAULT_EDGELABEL_YMARGIN
-            else:
-                xmargin = DEFAULT_LABEL_XMARGIN
-                ymargin = DEFAULT_LABEL_YMARGIN
-        return xmargin, ymargin
-
-    # Todo: Add support for head and tail labels!
-    # Todo: Support rect nodes if possible.
-    def do_preview_preproc(self):
-        # setDotAttr(self.maingraph)
-        self.init_template_vars()
-        template = self.clean_template(self.template)
-        template = replace_tags(template, self.templatevars,
-                                self.templatevars)
-        pp = TeXDimProc(template, self.options)
-        usednodes = {}
-        usededges = {}
-        usedgraphs = {}
-
-        # iterate over every element in the graph
-        counter = 0
-        for node in self.main_graph.allnodes:
-            name = node.name
-            if node.attr.get('fixedsize', '') == 'true' \
-                    or node.attr.get('style', '') in ['invis', 'invisible']:
-                continue
-            if node.attr.get('shape', '') == 'record':
-                log.warning('Record nodes not supported in preprocessing mode: %s', name)
-                continue
-            texlbl = self.get_label(node)
-
-            if texlbl:
-                node.attr['texlbl'] = texlbl
-                code = self.get_node_preproc_code(node)
-                pp.add_snippet(name, code)
-
-            usednodes[name] = node
-
-        for edge in dotparsing.flatten(self.main_graph.alledges):
-            if not edge.attr.get('label') and not edge.attr.get('texlbl') and not edge.attr.get("headlabel") \
-                    and not edge.attr.get("taillabel"):
-                continue
-            # Ensure that the edge name is unique.
-            name = edge.src.name + edge.dst.name + str(counter)
-            if is_multiline_label(edge):
-                continue
-            label = self.get_label(edge)
-            headlabel = self.get_label(edge, "headlabel", "headtexlbl")
-            taillabel = self.get_label(edge, "taillabel", "tailtexlbl")
-            if label:
-                name = edge.src.name + edge.dst.name + str(counter)
-                edge.attr['texlbl'] = label
-                code = self.get_edge_preproc_code(edge)
-                pp.add_snippet(name, code)
-
-            if headlabel:
-                headlabel_name = name + "headlabel"
-                edge.attr['headtexlbl'] = headlabel
-                code = self.get_edge_preproc_code(edge, "headtexlbl")
-                pp.add_snippet(headlabel_name, code)
-
-            if taillabel:
-                taillabel_name = name + "taillabel"
-                edge.attr['tailtexlbl'] = taillabel
-                code = self.get_edge_preproc_code(edge, "tailtexlbl")
-                pp.add_snippet(taillabel_name, code)
-
-            counter += 1
-            usededges[name] = edge
-
-        for graph in self.main_graph.allgraphs:
-            if not graph.attr.get('label') and not graph.attr.get('texlbl'):
-                continue
-            # Make sure that the name is unique
-            name = graph.name + str(counter)
-
-            counter += 1
-            label = self.get_label(graph)
-            graph.attr['texlbl'] = label
-            code = self.get_graph_preproc_code(graph)
-            pp.add_snippet(name, code)
-            usedgraphs[name] = graph
-
-        ok = pp.process()
-
-        if not ok:
-            errormsg = """\
-Failed to preprocess the graph.
-Is the preview LaTeX package installed? ((Debian package preview-latex-style)
-To see what happened, run dot2tex with the --debug option.
-"""
-            log.error(errormsg)
-            sys.exit(1)
-
-        for name, item in usednodes.items():
-            if not item.attr.get('texlbl'):
-                continue
-            node = item
-            hp, dp, wt = pp.texdims[name]
-            if self.options.get('rawdim'):
-                # use dimensions from preview.sty directly
-                node.attr['width'] = wt
-                node.attr['height'] = hp + dp
-                node.attr['label'] = " "
-                node.attr['fixedsize'] = 'true'
-                self.main_graph.allitems.append(node)
-                continue
-
-            xmargin, ymargin = self.get_margins(node)
-            ht = hp + dp
-            minwidth = float(item.attr.get('width') or DEFAULT_NODE_WIDTH)
-            minheight = float(item.attr.get('height') or DEFAULT_NODE_HEIGHT)
-            if self.options.get('nominsize'):
-                width = wt + 2 * xmargin
-                height = ht + 2 * ymargin
-            else:
-                if (wt + 2 * xmargin) < minwidth:
-                    width = minwidth
-                else:
-                    width = wt + 2 * xmargin
-                height = ht
-                if ((hp + dp) + 2 * ymargin) < minheight:
-                    height = minheight
-                else:
-                    height = ht + 2 * ymargin
-            # Treat shapes with equal width and height differently
-            # Warning! Rectangles will not always fit inside a circle
-            #          Should use the diagonal.
-            if item.attr.get('shape', '') in ['circle', 'Msquare', 'doublecircle', 'Mcircle']:
-                if wt < height and width < height:
-                    width = height
-                else:
-                    height = width
-
-            node.attr['width'] = width
-            node.attr['height'] = height
-            node.attr['label'] = " "
-
-            node.attr['fixedsize'] = 'true'
-            self.main_graph.allitems.append(node)
-
-        for name, item in usededges.items():
-            edge = item
-            hp, dp, wt = pp.texdims[name]
-            xmargin, ymargin = self.get_margins(edge)
-            labelcode = '<<<table border="0" cellborder="0" cellpadding="0">' \
-                        '<tr><td fixedsize="true" width="%s" height="%s">a</td>' \
-                        '</tr></table>>>'
-            if "texlbl" in edge.attr:
-                edge.attr['label'] = labelcode % ((wt + 2 * xmargin) * 72, (hp + dp + 2 * ymargin) * 72)
-            if "tailtexlbl" in edge.attr:
-                hp, dp, wt = pp.texdims[name + "taillabel"]
-                edge.attr['taillabel'] = labelcode % ((wt + 2 * xmargin) * 72, (hp + dp + 2 * ymargin) * 72)
-            if "headtexlbl" in edge.attr:
-                hp, dp, wt = pp.texdims[name + "headlabel"]
-                edge.attr['headlabel'] = labelcode % ((wt + 2 * xmargin) * 72, (hp + dp + 2 * ymargin) * 72)
-
-        for name, item in usedgraphs.items():
-            graph = item
-            hp, dp, wt = pp.texdims[name]
-            xmargin, ymargin = self.get_margins(graph)
-            labelcode = '<<<table border="0" cellborder="0" cellpadding="0">' \
-                        '<tr><td fixedsize="true" width="%s" height="%s">a</td>' \
-                        '</tr></table>>>'
-            graph.attr['label'] = labelcode % ((wt + 2 * xmargin) * 72, (hp + dp + 2 * ymargin) * 72)
-
-        self.main_graph.attr['d2toutputformat'] = self.options.get('format',
-                                                                   DEFAULT_OUTPUT_FORMAT)
-        graphcode = str(self.main_graph)
-        graphcode = graphcode.replace('<<<', '<<')
-        graphcode = graphcode.replace('>>>', '>>')
-        return graphcode
-
-    def get_output_arrow_styles(self, arrow_style, edge):
-        return arrow_style
-
-
-PSTRICKS_TEMPLATE = r"""\documentclass{article}
-% <<bbox>>
-\usepackage[x11names,svgnames]{xcolor}
-\usepackage[<<textencoding>>]{inputenc}
-\usepackage{graphicx}
-\usepackage{pstricks}
-\usepackage{amsmath}
-<<startpreprocsection>>%
-\usepackage[active,auctex]{preview}
-<<endpreprocsection>>%
-<<gvcols>>%
-<<docpreamble>>%
-
-
-\begin{document}
-\pagestyle{empty}
-<<startpreprocsection>>%
-<<preproccode>>%
-<<endpreprocsection>>%
-<<startoutputsection>>%
-\enlargethispage{100cm}
-
-% Start of code
-\begin{pspicture}[linewidth=1bp<<graphstyle>>]<<bbox>>
-  \pstVerb{2 setlinejoin} % set line join style to 'mitre'
-<<figpreamble>>%
-<<drawcommands>>
-<<figpostamble>>%
-\end{pspicture}
-% End of code
-<<endoutputsection>>%
-\end{document}
-%
-<<start_figonlysection>>
-\begin{pspicture}[linewidth=1bp<<graphstyle>>]<<bbox>>
-  \pstVerb{2 setlinejoin} % set line join style to 'mitre'
-<<figpreamble>>%
-<<drawcommands>>
-<<figpostamble>>%
-\end{pspicture}
-<<end_figonlysection>>
-%
-<<startcodeonlysection>>
-<<figpreamble>>%
-<<drawcommands>>
-<<figpostamble>>%
-<<endcodeonlysection>>
-"""
-
-
-class Dot2PSTricksConv(DotConvBase):
-    """PSTricks converter backend"""
-
-    def __init__(self, options=None):
-        DotConvBase.__init__(self, options)
-        if not self.template:
-            self.template = PSTRICKS_TEMPLATE
-        self.styles = dict(
-            dotted="linestyle=dotted",
-            dashed="linestyle=dashed",
-            bold="linewidth=2pt",
-            solid="",
-            filled="",
-        )
-
-    def do_graphtmp(self):
-        self.pencolor = ""
-        self.fillcolor = ""
-        self.color = ""
-        self.body += '{\n'
-        DotConvBase.do_graph(self)
-        self.body += '}\n'
-
-    def draw_ellipse(self, drawop, style=None):
-        op, x, y, w, h = drawop
-        s = ""
-        if op == 'E':
-            if style:
-                style = style.replace('filled', '')
-            stylestr = 'fillstyle=solid'
-        else:
-            stylestr = ""
-
-        if style:
-            if stylestr:
-                stylestr += ',' + style
-            else:
-                stylestr = style
-
-        s += "  \psellipse[%s](%sbp,%sbp)(%sbp,%sbp)\n" % (stylestr, smart_float(x), smart_float(y),
-                                                           # w+self.linewidth,h+self.linewidth)
-                                                           smart_float(w), smart_float(h))
-
-        return s
-
-    def draw_polygon(self, drawop, style=None):
-        op, points = drawop
-        pp = ['(%sbp,%sbp)' % (smart_float(p[0]), smart_float(p[1])) for p in points]
-        stylestr = ""
-        if op == 'P':
-            if style:
-                style = style.replace('filled', '')
-            stylestr = "fillstyle=solid"
-        if style:
-            if stylestr:
-                stylestr += ',' + style
-            else:
-                stylestr = style
-
-        s = "  \pspolygon[%s]%s\n" % (stylestr, "".join(pp))
-        return s
-
-    def draw_polyline(self, drawop, style=None):
-        op, points = drawop
-        pp = ['(%sbp,%sbp)' % (smart_float(p[0]), smart_float(p[1])) for p in points]
-        s = "  \psline%s\n" % "".join(pp)
-        return s
-
-    def draw_bezier(self, drawop, style=None):
-        op, points = drawop
-        pp = []
-        for point in points:
-            pp.append("(%sbp,%sbp)" % (smart_float(point[0]), smart_float(point[1])))
-
-        arrowstyle = ""
-        return "  \psbezier{%s}%s\n" % (arrowstyle, "".join(pp))
-
-    def draw_text(self, drawop, style=None):
-        if len(drawop) == 7:
-            c, x, y, align, w, text, valign = drawop
-        else:
-            c, x, y, align, w, text = drawop
-            valign = ""
-        if align == "-1":
-            alignstr = 'l'  # left aligned
-        elif align == "1":
-            alignstr = 'r'  # right aligned
-        else:
-            alignstr = ""  # centered (default)
-        if alignstr or valign:
-            alignstr = '[' + alignstr + valign + ']'
-        s = "  \\rput%s(%sbp,%sbp){%s}\n" % (alignstr, smart_float(x), smart_float(y), text)
-        return s
-
-    def set_color(self, drawop):
-        c, color = drawop
-        color = self.convert_color(color)
-        s = ""
-        if c == 'c':
-            # set pen color
-            if self.pencolor != color:
-                self.pencolor = color
-                s = "  \psset{linecolor=%s}\n" % color
-            else:
-                return ""
-        elif c == 'C':
-            # set fill color
-            if self.fillcolor != color:
-                self.fillcolor = color
-                s = "  \psset{fillcolor=%s}\n" % color
-            else:
-                return ""
-        elif c == 'cC':
-            if self.color != color:
-                self.color = color
-                self.pencolor = self.fillcolor = color
-                s = "  \psset{linecolor=%s}\n" % color
-        else:
-            log.warning('Unhandled color: %s', drawop)
-        return s
-
-    def set_style(self, drawop):
-        c, style = drawop
-        psstyle = self.styles.get(style, "")
-        if psstyle:
-            return "  \psset{%s}\n" % psstyle
-        else:
-            return ""
-
-    def filter_styles(self, style):
-        filtered_styles = []
-        for item in style.split(','):
-            keyval = item.strip()
-            if keyval.find('setlinewidth') < 0:
-                filtered_styles.append(keyval)
-        return ', '.join(filtered_styles)
-
-    def start_node(self, node):
-        self.pencolor = ""
-        self.fillcolor = ""
-        self.color = ""
-        return "{%\n"
-
-    def end_node(self, node):
-        return "}%\n"
-
-    def start_edge(self):
-        self.pencolor = ""
-        self.fillcolor = ""
-        return "{%\n"
-
-    def end_edge(self):
-        return "}%\n"
-
-    def start_graph(self, graph):
-        self.pencolor = ""
-        self.fillcolor = ""
-        self.color = ""
-        return "{\n"
-
-    def end_graph(self, node):
-        return "}\n"
-
-    def draw_edge(self, edge):
-        s = ""
-        if edge.attr.get('style', '') in ['invis', 'invisible']:
-            return ""
-        edges = self.get_edge_points(edge)
-        for arrowstyle, points in edges:
-            if arrowstyle == '--':
-                arrowstyle = ''
-            color = getattr(edge, 'color', '')
-            if self.color != color:
-                if color:
-                    s += self.set_color(('c', color))
-                else:
-                    # reset to default color
-                    s += self.set_color(('c', 'black'))
-            pp = []
-            for point in points:
-                p = point.split(',')
-                pp.append("(%sbp,%sbp)" % (smart_float(p[0]), smart_float(p[1])))
-
-            edgestyle = edge.attr.get('style', '')
-            styles = []
-            if arrowstyle:
-                styles.append('arrows=%s' % arrowstyle)
-            if edgestyle:
-                edgestyles = [self.styles.get(key.strip(), key.strip())
-                              for key in edgestyle.split(',') if key]
-                styles.extend(edgestyles)
-            if styles:
-                stylestr = ",".join(styles)
-            else:
-                stylestr = ""
-            if not self.options.get('straightedges'):
-                s += "  \psbezier[%s]%s\n" % (stylestr, "".join(pp))
-            else:
-                s += "  \psline[%s]%s%s\n" % (stylestr, pp[0], pp[-1])
-                # s += "  \psbezier[%s]{%s}%s\n" % (stylestr, arrowstyle,"".join(pp))
-                ##        if edge.label:
-                ##            x,y = edge.lp.split(',')
-                ##            #s += "\\rput(%s,%s){%s}\n" % (x,y,edge.label)
-        return s
-
-    def init_template_vars(self):
-        DotConvBase.init_template_vars(self)
-        # Put a ',' before <<graphstyle>>
-        graphstyle = self.templatevars.get('<<graphstyle>>', '')
-        if graphstyle:
-            graphstyle = graphstyle.strip()
-            if not graphstyle.startswith(','):
-                graphstyle = ',' + graphstyle
-                self.templatevars['<<graphstyle>>'] = graphstyle
-
-
-PGF_TEMPLATE = r"""\documentclass{article}
-\usepackage[x11names, svgnames, rgb]{xcolor}
-\usepackage[<<textencoding>>]{inputenc}
-\usepackage{tikz}
-\usetikzlibrary{snakes,arrows,shapes}
-\usepackage{amsmath}
-<<startpreprocsection>>%
-\usepackage[active,auctex]{preview}
-<<endpreprocsection>>%
-<<gvcols>>%
-<<startoutputsection>>
-<<cropcode>>%
-<<endoutputsection>>
-<<docpreamble>>%
-
-\begin{document}
-\pagestyle{empty}
-%
-<<startpreprocsection>>%
-<<preproccode>>
-<<endpreprocsection>>%
-%
-<<startoutputsection>>
-\enlargethispage{100cm}
-% Start of code
-% \begin{tikzpicture}[anchor=mid,>=latex',line join=bevel,<<graphstyle>>]
-\begin{tikzpicture}[>=latex',line join=bevel,<<graphstyle>>]
-  \pgfsetlinewidth{1bp}
-<<figpreamble>>%
-<<drawcommands>>
-<<figpostamble>>%
-\end{tikzpicture}
-% End of code
-<<endoutputsection>>
-%
-\end{document}
-%
-<<start_figonlysection>>
-\begin{tikzpicture}[>=latex,line join=bevel,<<graphstyle>>]
-  \pgfsetlinewidth{1bp}
-<<figpreamble>>%
-<<drawcommands>>
-<<figpostamble>>%
-\end{tikzpicture}
-<<end_figonlysection>>
-<<startcodeonlysection>>
-<<figpreamble>>%
-<<drawcommands>>
-<<figpostamble>>%
-<<endcodeonlysection>>
-"""
-
-PGF210_TEMPLATE = r"""\documentclass{article}
-% dot2tex template for PGF 2.10
-\usepackage[x11names, svgnames, rgb]{xcolor}
-\usepackage[<<textencoding>>]{inputenc}
-\usepackage{tikz}
-\usetikzlibrary{snakes,arrows,shapes}
-\usepackage{amsmath}
-<<startpreprocsection>>%
-\usepackage[active,auctex]{preview}
-<<endpreprocsection>>%
-<<gvcols>>%
-<<startoutputsection>>
-<<cropcode>>%
-<<endoutputsection>>
-<<docpreamble>>%
-
-\begin{document}
-\pagestyle{empty}
-%
-<<startpreprocsection>>%
-<<preproccode>>
-<<endpreprocsection>>%
-%
-<<startoutputsection>>
-\enlargethispage{100cm}
-% Start of code
-% \begin{tikzpicture}[anchor=mid,>=latex',line join=bevel,<<graphstyle>>]
-\begin{tikzpicture}[>=latex',line join=bevel,<<graphstyle>>]
-  \pgfsetlinewidth{1bp}
-<<figpreamble>>%
-<<drawcommands>>
-<<figpostamble>>%
-\end{tikzpicture}
-% End of code
-<<endoutputsection>>
-%
-\end{document}
-%
-<<start_figonlysection>>
-\begin{tikzpicture}[>=latex,line join=bevel,<<graphstyle>>]
-  \pgfsetlinewidth{1bp}
-<<figpreamble>>%
-<<drawcommands>>
-<<figpostamble>>%
-\end{tikzpicture}
-<<end_figonlysection>>
-<<startcodeonlysection>>
-<<figpreamble>>%
-<<drawcommands>>
-<<figpostamble>>%
-<<endcodeonlysection>>
-"""
-
-PGF118_TEMPLATE = r"""\documentclass{article}
-\usepackage[x11names, rgb]{xcolor}
-\usepackage[<<textencoding>>]{inputenc}
-\usepackage{tikz}
-\usepackage{pgflibrarysnakes}
-\usepackage{pgflibraryarrows,pgflibraryshapes}
-\usepackage{amsmath}
-<<startpreprocsection>>%
-\usepackage[active,auctex]{preview}
-<<endpreprocsection>>%
-<<gvcols>>%
-<<cropcode>>%
-<<docpreamble>>%
-
-\begin{document}
-\pagestyle{empty}
-%
-<<startpreprocsection>>%
-<<preproccode>>
-<<endpreprocsection>>%
-%
-<<startoutputsection>>
-\enlargethispage{100cm}
-% Start of code
-\begin{tikzpicture}[>=latex',join=bevel,<<graphstyle>>]
-  \pgfsetlinewidth{1bp}
-<<figpreamble>>%
-<<drawcommands>>
-<<figpostamble>>%
-\end{tikzpicture}
-% End of code
-<<endoutputsection>>
-%
-\end{document}
-%
-<<start_figonlysection>>
-\begin{tikzpicture}[>=latex,join=bevel,<<graphstyle>>]
-  \pgfsetlinewidth{1bp}
-<<figpreamble>>%
-<<drawcommands>>
-<<figpostamble>>%
-\end{tikzpicture}
-<<end_figonlysection>>
-<<startcodeonlysection>>
-<<figpreamble>>%
-<<drawcommands>>
-<<figpostamble>>%
-<<endcodeonlysection>>
-"""
-
-
-class Dot2PGFConv(DotConvBase):
-    """PGF/TikZ converter backend"""
-    arrows_map_210 = {"dot": "*", "odot": "o", "empty": "open triangle 45", "invempty": "open triangle 45 reversed",
-                      "diamond": "diamond", "odiamond": "open diamond", "ediamond": "open diamond", "box": "square",
-                      "obox": "open square", "vee": "stealth'", "open": "stealth'", "tee": "|",
-                      "crow": "stealth reversed"}
-
-    def __init__(self, options=None):
-        DotConvBase.__init__(self, options)
-        if not self.template:
-            if options.get('pgf118'):
-                self.template = PGF118_TEMPLATE
-            elif options.get('pgf210'):
-                self.template = PGF210_TEMPLATE
-            else:
-                self.template = PGF_TEMPLATE
-        self.styles = dict(dashed='dashed', dotted='dotted',
-                           bold='very thick', filled='fill', invis="",
-                           rounded='rounded corners', )
-        self.dashstyles = dict(
-            dashed='\pgfsetdash{{3pt}{3pt}}{0pt}',
-            dotted='\pgfsetdash{{\pgflinewidth}{2pt}}{0pt}',
-            bold='\pgfsetlinewidth{1.2pt}')
-
-    def start_node(self, node):
-        # Todo: Should find a more elegant solution
-        self.pencolor = ""
-        self.fillcolor = ""
-        self.color = ""
-        return "\\begin{scope}\n"
-
-    def end_node(self, node):
-        return "\\end{scope}\n"
-
-    def start_edge(self):
-        # Todo: Should find a more elegant solution
-        # self.pencolor = "";
-        # self.fillcolor = ""
-        # self.color = ""
-        return "\\begin{scope}\n"
-
-    def end_edge(self):
-        return "\\end{scope}\n"
-
-    def start_graph(self, graph):
-        # Todo: Should find a more elegant solution
-        self.pencolor = ""
-        self.fillcolor = ""
-        self.color = ""
-        return "\\begin{scope}\n"
-
-    def end_graph(self, graph):
-        return "\\end{scope}\n"
-
-    def set_color(self, drawop):
-        c, color = drawop
-        res = self.convert_color(color, True)
-        opacity = None
-        if len(res) == 2:
-            ccolor, opacity = res
-        else:
-            ccolor = res
-        s = ""
-        if c == 'cC':
-            if self.color != color:
-                self.color = color
-                self.pencolor = color
-                self.fillcolor = color
-                if ccolor.startswith('{'):
-                    # rgb or hsb
-                    s += "  \definecolor{newcol}%s;\n" % ccolor
-                    ccolor = 'newcol'
-                s += "  \pgfsetcolor{%s}\n" % ccolor
-        elif c == 'c':
-            # set pen color
-            if self.pencolor != color:
-                self.pencolor = color
-                self.color = ''
-                if ccolor.startswith('{'):
-                    # rgb or hsb
-                    s += "  \definecolor{strokecol}%s;\n" % ccolor
-                    ccolor = 'strokecol'
-                s += "  \pgfsetstrokecolor{%s}\n" % ccolor
-            else:
-                return ""
-        elif c == 'C':
-            # set fill color
-            if self.fillcolor != color:
-                self.fillcolor = color
-                self.color = ''
-                if ccolor.startswith('{'):
-                    # rgb
-                    s += "  \definecolor{fillcol}%s;\n" % ccolor
-                    ccolor = 'fillcol'
-                s += "  \pgfsetfillcolor{%s}\n" % ccolor
-                if not opacity is None:
-                    self.opacity = opacity
-                    # Todo: The opacity should probably be set directly when drawing
-                    # The \pgfsetfillcopacity cmd affects text as well
-                    # s += "  \pgfsetfillopacity{%s};\n" % opacity
-                else:
-                    self.opacity = None
-            else:
-                return ""
-        return s
-
-    def set_style(self, drawop):
-        c, style = drawop
-        pgfstyle = self.dashstyles.get(style, "")
-        if pgfstyle:
-            return "  %s\n" % pgfstyle
-        else:
-            return ""
-
-    def filter_styles(self, style):
-        filtered_styles = []
-        for item in style.split(','):
-            keyval = item.strip()
-            if keyval.find('setlinewidth') < 0 and not keyval == 'filled':
-                filtered_styles.append(keyval)
-        return ', '.join(filtered_styles)
-
-    def draw_ellipse(self, drawop, style=None):
-        op, x, y, w, h = drawop
-        s = ""
-        if op == 'E':
-            if self.opacity is not None:
-                # Todo: Need to know the state of the current node
-                cmd = 'filldraw [opacity=%s]' % self.opacity
-            else:
-                cmd = 'filldraw'
-        else:
-            cmd = "draw"
-
-        if style:
-            stylestr = " [%s]" % style
-        else:
-            stylestr = ''
-        s += "  \%s%s (%sbp,%sbp) ellipse (%sbp and %sbp);\n" % (cmd, stylestr, smart_float(x), smart_float(y),
-                                                                 # w+self.linewidth,h+self.linewidth)
-                                                                 smart_float(w), smart_float(h))
-        return s
-
-    def draw_polygon(self, drawop, style=None):
-        op, points = drawop
-        pp = ['(%sbp,%sbp)' % (smart_float(p[0]), smart_float(p[1])) for p in points]
-        cmd = "draw"
-        if op == 'P':
-            cmd = "filldraw"
-
-        if style:
-            stylestr = " [%s]" % style
-        else:
-            stylestr = ''
-        s = "  \%s%s %s -- cycle;\n" % (cmd, stylestr, " -- ".join(pp))
-        return s
-
-    def draw_polyline(self, drawop, style=None):
-        op, points = drawop
-        pp = ['(%sbp,%sbp)' % (smart_float(p[0]), smart_float(p[1])) for p in points]
-        stylestr = ''
-        return "  \draw%s %s;\n" % (stylestr, " -- ".join(pp))
-
-    def draw_text(self, drawop, style=None):
-        # The coordinates given by drawop are not the same as the node
-        # coordinates! This may give som odd results if graphviz' and
-        # LaTeX' fonts are very different.
-        if len(drawop) == 7:
-            c, x, y, align, w, text, valign = drawop
-        else:
-            c, x, y, align, w, text = drawop
-
-        styles = []
-        if align == "-1":
-            alignstr = 'right'  # left aligned
-        elif align == "1":
-            alignstr = 'left'  # right aligned
-        else:
-            alignstr = ""  # centered (default)
-        styles.append(alignstr)
-        styles.append(style)
-        lblstyle = ",".join([i for i in styles if i])
-        if lblstyle:
-            lblstyle = '[' + lblstyle + ']'
-        s = "  \draw (%sbp,%sbp) node%s {%s};\n" % (smart_float(x), smart_float(y), lblstyle, text)
-        return s
-
-    def draw_bezier(self, drawop, style=None):
-        s = ""
-        c, points = drawop
-        pp = []
-        for point in points:
-            pp.append("(%sbp,%sbp)" % (smart_float(point[0]), smart_float(point[1])))
-
-        pstrs = ["%s .. controls %s and %s " % p for p in nsplit(pp, 3)]
-        stylestr = ''
-        s += "  \draw%s %s .. %s;\n" % (stylestr, " .. ".join(pstrs), pp[-1])
-        return s
-
-    def do_edges(self):
-        s = ""
-        s += self.set_color(('cC', "black"))
-        for edge in self.edges:
-            general_draw_string = getattr(edge, '_draw_', "")
-            label_string = getattr(edge, '_ldraw_', "")
-            head_arrow_string = getattr(edge, '_hdraw_', "")
-            tail_arrow_string = getattr(edge, '_tdraw_', "")
-            tail_label_string = getattr(edge, '_tldraw_', "")
-            head_label_string = getattr(edge, '_hldraw_', "")
-
-            # Note that the order of the draw strings should be the same
-            # as in the xdot output.
-            drawstring = general_draw_string + " " + head_arrow_string + " " + tail_arrow_string \
-                         + " " + label_string
-            draw_operations, stat = parse_drawstring(drawstring)
-            if not drawstring.strip():
-                continue
-            s += self.output_edge_comment(edge)
-            if self.options.get('duplicate'):
-                s += self.start_edge()
-                s += self.do_draw_op(draw_operations, edge, stat)
-                s += self.do_drawstring(tail_label_string, edge, "tailtexlbl")
-                s += self.do_drawstring(head_label_string, edge, "headtexlbl")
-                s += self.end_edge()
-            else:
-                topath = getattr(edge, 'topath', None)
-                s += self.draw_edge(edge)
-                if not self.options.get('tikzedgelabels') and not topath:
-                    s += self.do_drawstring(label_string, edge)
-                    s += self.do_drawstring(tail_label_string, edge, "tailtexlbl")
-                    s += self.do_drawstring(head_label_string, edge, "headtexlbl")
-                else:
-                    s += self.do_drawstring(tail_label_string, edge, "tailtexlbl")
-                    s += self.do_drawstring(head_label_string, edge, "headtexlbl")
-
-        self.body += s
-
-    def draw_edge(self, edge):
-        s = ""
-        if edge.attr.get('style', '') in ['invis', 'invisible']:
-            return ""
-        edges = self.get_edge_points(edge)
-        for arrowstyle, points in edges:
-            # arrowstyle, points = self.get_edge_points(edge)
-            # PGF uses the fill style when drawing some arrowheads. We have to
-            # ensure that the fill color is the same as the pen color.
-            color = getattr(edge, 'color', '')
-
-            if self.color != color:
-                if color:
-                    s += self.set_color(('cC', color))
-                else:
-                    # reset to default color
-                    s += self.set_color(('cC', 'black'))
-
-            pp = []
-            for point in points:
-                p = point.split(',')
-                pp.append("(%sbp,%sbp)" % (smart_float(p[0]), smart_float(p[1])))
-
-            edgestyle = edge.attr.get('style', '')
-
-            styles = []
-            if arrowstyle != '--':
-                styles = [arrowstyle]
-
-            if edgestyle:
-                edgestyles = [self.styles.get(key.strip(), key.strip()) for key in edgestyle.split(',') if key]
-                styles.extend(edgestyles)
-
-            stylestr = ",".join(styles)
-            topath = getattr(edge, 'topath', None)
-
-            pstrs = ["%s .. controls %s and %s " % x for x in nsplit(pp, 3)]
-            extra = ""
-            if self.options.get('tikzedgelabels') or topath:
-                edgelabel = self.get_label(edge)
-                # log.warning('label: %s', edgelabel)
-                lblstyle = getattr(edge, 'lblstyle', '')
-                if lblstyle:
-                    lblstyle = '[' + lblstyle + ']'
-                else:
-                    lblstyle = ''
-                if edgelabel:
-                    extra = " node%s {%s}" % (lblstyle, edgelabel)
-            src = pp[0]
-            dst = pp[-1]
-            if topath:
-                s += "  \draw [%s] %s to[%s]%s %s;\n" % (stylestr, src,
-                                                         topath, extra, dst)
-            elif not self.options.get('straightedges'):
-                s += "  \draw [%s] %s ..%s %s;\n" % (stylestr, " .. ".join(pstrs), extra, pp[-1])
-            else:
-                s += "  \draw [%s] %s --%s %s;\n" % (stylestr, pp[0], extra, pp[-1])
-
-        return s
-
-    def get_output_arrow_styles(self, arrow_style, edge):
-        dot_arrow_head = edge.attr.get("arrowhead")
-        dot_arrow_tail = edge.attr.get("arrowtail")
-        output_arrow_style = arrow_style
-        if dot_arrow_head:
-            pgf_arrow_head = self.arrows_map_210.get(dot_arrow_head)
-            if pgf_arrow_head:
-                output_arrow_style = output_arrow_style.replace(">", pgf_arrow_head)
-        if dot_arrow_tail:
-            pgf_arrow_tail = self.arrows_map_210.get(dot_arrow_tail)
-            if pgf_arrow_tail:
-                output_arrow_style = output_arrow_style.replace("<", pgf_arrow_tail)
-        return output_arrow_style
-
-    def init_template_vars(self):
-        DotConvBase.init_template_vars(self)
-        if self.options.get('crop'):
-            cropcode = "\\usepackage[active,tightpage]{preview}\n" + \
-                       "\\PreviewEnvironment{tikzpicture}\n" + \
-                       "\\setlength\\PreviewBorder{%s}" % self.options.get('margin', '0pt')
-        else:
-            cropcode = ""
-        variables = {'<<cropcode>>': cropcode}
-        self.templatevars.update(variables)
-
-    def get_node_preproc_code(self, node):
-        lblstyle = node.attr.get('lblstyle', '')
-        text = node.attr.get('texlbl', '')
-        if lblstyle:
-            return "  \\tikz \\node[%s] {%s};\n" % (lblstyle, text)
-        else:
-            return r"\tikz \node {" + text + "};"
-
-    def get_edge_preproc_code(self, edge, attribute="texlbl"):
-        lblstyle = edge.attr.get('lblstyle', '')
-        text = edge.attr.get(attribute, '')
-        if lblstyle:
-            return "  \\tikz \\node[%s] {%s};\n" % (lblstyle, text)
-        else:
-            return r"\tikz \node " + "{" + text + "};"
-
-    def get_graph_preproc_code(self, graph):
-        lblstyle = graph.attr.get('lblstyle', '')
-        text = graph.attr.get('texlbl', '')
-        if lblstyle:
-            return "  \\tikz \\node[%s] {%s};\n" % (lblstyle, text)
-        else:
-            return r"\tikz \node {" + text + "};"
-
-
-TIKZ_TEMPLATE = r"""\documentclass{article}
-\usepackage[x11names, svgnames, rgb]{xcolor}
-\usepackage[<<textencoding>>]{inputenc}
-\usepackage{tikz}
-\usetikzlibrary{snakes,arrows,shapes}
-\usepackage{amsmath}
-<<startpreprocsection>>%
-\usepackage[active,auctex]{preview}
-<<endpreprocsection>>%
-<<gvcols>>%
-<<startoutputsection>>
-<<cropcode>>%
-<<endoutputsection>>
-<<docpreamble>>%
-
-\begin{document}
-\pagestyle{empty}
-%
-<<startpreprocsection>>%
-<<preproccode>>
-<<endpreprocsection>>%
-%
-<<startoutputsection>>
-\enlargethispage{100cm}
-% Start of code
-\begin{tikzpicture}[>=latex',line join=bevel,<<graphstyle>>]
-<<figpreamble>>%
-<<drawcommands>>
-<<figpostamble>>%
-\end{tikzpicture}
-% End of code
-<<endoutputsection>>
-%
-\end{document}
-%
-<<start_figonlysection>>
-\begin{tikzpicture}[>=latex,line join=bevel,<<graphstyle>>]
-<<figpreamble>>%
-<<drawcommands>>
-<<figpostamble>>%
-\end{tikzpicture}
-<<end_figonlysection>>
-<<startcodeonlysection>>
-<<figpreamble>>%
-<<drawcommands>>
-<<figpostamble>>%
-<<endcodeonlysection>>
-"""
-
-TIKZ210_TEMPLATE = r"""\documentclass{article}
-% dot2tex template for PGF 2.10
-\usepackage[x11names, svgnames, rgb]{xcolor}
-\usepackage[<<textencoding>>]{inputenc}
-\usepackage{tikz}
-\usetikzlibrary{snakes,arrows,shapes}
-\usepackage{amsmath}
-<<startpreprocsection>>%
-\usepackage[active,auctex]{preview}
-<<endpreprocsection>>%
-<<gvcols>>%
-<<startoutputsection>>
-<<cropcode>>%
-<<endoutputsection>>
-<<docpreamble>>%
-
-\begin{document}
-\pagestyle{empty}
-%
-<<startpreprocsection>>%
-<<preproccode>>
-<<endpreprocsection>>%
-%
-<<startoutputsection>>
-\enlargethispage{100cm}
-% Start of code
-\begin{tikzpicture}[>=latex',line join=bevel,<<graphstyle>>]
-<<figpreamble>>%
-<<drawcommands>>
-<<figpostamble>>%
-\end{tikzpicture}
-% End of code
-<<endoutputsection>>
-%
-\end{document}
-%
-<<start_figonlysection>>
-\begin{tikzpicture}[>=latex,line join=bevel,<<graphstyle>>]
-<<figpreamble>>%
-<<drawcommands>>
-<<figpostamble>>%
-\end{tikzpicture}
-<<end_figonlysection>>
-<<startcodeonlysection>>
-<<figpreamble>>%
-<<drawcommands>>
-<<figpostamble>>%
-<<endcodeonlysection>>
-"""
-
-TIKZ118_TEMPLATE = r"""\documentclass{article}
-\usepackage[x11names, svgnames, rgb]{xcolor}
-\usepackage[<<textencoding>>]{inputenc}
-\usepackage{tikz}
-\usepackage{pgflibrarysnakes}
-\usepackage{pgflibraryarrows,pgflibraryshapes}
-\usepackage{amsmath}
-<<startpreprocsection>>%
-\usepackage[active,auctex]{preview}
-<<endpreprocsection>>%
-<<gvcols>>%
-<<cropcode>>%
-<<docpreamble>>%
-
-\begin{document}
-\pagestyle{empty}
-%
-<<startpreprocsection>>%
-<<preproccode>>
-<<endpreprocsection>>%
-%
-<<startoutputsection>>
-\enlargethispage{100cm}
-% Start of code
-\begin{tikzpicture}[>=latex',join=bevel,<<graphstyle>>]
-<<figpreamble>>%
-<<drawcommands>>
-<<figpostamble>>%
-\end{tikzpicture}
-% End of code
-<<endoutputsection>>
-%
-\end{document}
-%
-<<start_figonlysection>>
-\begin{tikzpicture}[>=latex,join=bevel,<<graphstyle>>]
-<<figpreamble>>%
-<<drawcommands>>
-<<figpostamble>>%
-\end{tikzpicture}
-<<end_figonlysection>>
-<<startcodeonlysection>>
-<<figpreamble>>%
-<<drawcommands>>
-<<figpostamble>>%
-<<endcodeonlysection>>
-"""
-
-
-class Dot2TikZConv(Dot2PGFConv):
-    """A backend that utilizes the node and edge mechanism of PGF/TikZ"""
-    shape_map = {'doublecircle': 'circle, double',
-                 'box': 'rectangle',
-                 'rect': 'rectangle',
-                 'none': 'draw=none',
-                 'plaintext': 'draw=none',
-                 'polygon': 'regular polygon, regular polygon sides=7',
-                 'triangle': 'regular polygon, regular polygon sides=3',
-                 'square': 'regular polygon, regular polygon sides=4',
-                 'pentagon': 'regular polygon, regular polygon sides=5',
-                 'hexagon': 'regular polygon, regular polygon sides=6',
-                 'septagon': 'regular polygon, regular polygon sides=7',
-                 'octagon': 'regular polygon, regular polygon sides=8',
-                 'point': 'circle, fill',
-                 'ellipse': 'ellipse',
-                 'oval': 'ellipse',
-                 'diamond': 'diamond',
-                 'trapezium': 'trapezium',
-                 'star': 'star',
-                 'circle': 'circle',
-                 }
-
-    compass_map = {'n': 'north', 'ne': 'north east', 'e': 'east',
-                   'se': 'south east', 's': 'south', 'sw': 'south west',
-                   'w': 'west', 'nw': 'north west', 'center': 'center'}
-
-    def __init__(self, options=None):
-        # to connect nodes they have to defined. Therefore we have to ensure
-        # that code for generating nodes is outputted first.
-        options = options or {}
-        options['switchdraworder'] = True
-        options['flattengraph'] = True
-        options['rawdim'] = True
-        if options.get('pgf118'):
-            self.template = TIKZ118_TEMPLATE
-        elif options.get('pgf210'):
-            self.template = TIKZ210_TEMPLATE
-        else:
-            self.template = TIKZ_TEMPLATE
-        DotConvBase.__init__(self, options)
-
-        self.styles = dict(dashed='dashed', dotted='dotted',
-                           bold='very thick', filled='fill', invis="", invisible="",
-                           rounded='rounded corners', )
-        self.dashstyles = dict(
-            dashed='\pgfsetdash{{3pt}{3pt}}{0pt}',
-            dotted='\pgfsetdash{{\pgflinewidth}{2pt}}{0pt}',
-            bold='\pgfsetlinewidth{1.2pt}')
-
-    def set_options(self):
-        Dot2PGFConv.set_options(self)
-        self.options['tikzedgelabels'] = self.options.get('tikzedgelabels', '') \
-                                         or getboolattr(self.main_graph, 'd2ttikzedgelabels', '')
-        self.options['styleonly'] = self.options.get('styleonly', '') \
-                                    or getboolattr(self.main_graph, 'd2tstyleonly', '')
-        self.options['nodeoptions'] = self.options.get('nodeoptions', '') \
-                                      or getattr(self.main_graph, 'd2tnodeoptions', '')
-        self.options['edgeoptions'] = self.options.get('edgeoptions', '') \
-                                      or getattr(self.main_graph, 'd2tedgeoptions', '')
-
-    def output_node_comment(self, node):
-        # With the node syntax comments are unnecessary
-        return ""
-
-    def set_tikzcolor(self, color, colorname):
-        res = self.convert_color(color, True)
-        if len(res) == 2:
-            ccolor, opacity = res
-            if not (opacity == '1'):
-                log.warning('Opacity not supported yet: %s', res)
-        else:
-            ccolor = res
-        s = ""
-        if ccolor.startswith('{'):
-            # rgb or hsb
-            s += "  \definecolor{%s}%s;\n" % (colorname, ccolor)
-            cname = colorname
-        else:
-            cname = color
-
-        return s, cname
-
-    def get_node_preproc_code(self, node):
-        lblstyle = node.attr.get('lblstyle', '')
-
-        shape = node.attr.get('shape', 'ellipse')
-        shape = self.shape_map.get(shape, shape)
-        # s += "%% %s\n" % (shape)
-        label = node.attr.get('texlbl', '')
-        style = node.attr.get('style', " ") or " "
-        if lblstyle:
-            if style.strip():
-                style += ',' + lblstyle
-            else:
-                style = lblstyle
-
-        sn = ""
-        if self.options.get('styleonly'):
-            sn += "\\tikz  \\node [%s] {%s};\n" % \
-                  (style, label)
-        else:
-            sn += "\\tikz  \\node [draw,%s,%s] {%s};\n" % \
-                  (shape, style, label)
-        return sn
-
-    def do_nodes(self):
-        s = ""
-        nodeoptions = self.options.get('nodeoptions')
-        if nodeoptions:
-            s += "\\begin{scope}[%s]\n" % nodeoptions
-        for node in self.nodes:
-            self.currentnode = node
-            # detect node type
-            dotshape = getattr(node, 'shape', 'ellipse')
-            shape = None
-
-            if node.attr.get('style') in ['invis', 'invisible']:
-                shape = "coordinate"
-            else:
-                shape = self.shape_map.get(dotshape, shape)
-            if shape is None:
-                shape = 'ellipse'
-
-            pos = getattr(node, 'pos', None)
-            if not pos:
-                continue
-            x, y = pos.split(',')
-            if dotshape != 'point':
-                label = self.get_label(node)
-            else:
-                label = ''
-
-            pos = "%sbp,%sbp" % (smart_float(x), smart_float(y))
-            style = node.attr.get('style') or ""
-            if node.attr.get('lblstyle'):
-                if style:
-                    style += ',' + node.attr['lblstyle']
-                else:
-                    style = node.attr['lblstyle']
-            if node.attr.get('exstyle'):
-                if style:
-                    style += ',' + node.attr['exstyle']
-                else:
-                    style = node.attr['exstyle']
-            sn = ""
-            sn += self.output_node_comment(node)
-            sn += self.start_node(node)
-            if shape == "coordinate":
-                sn += "  \\coordinate (%s) at (%s);\n" % (tikzify(node.name), pos)
-            elif self.options.get('styleonly'):
-                sn += "  \\node (%s) at (%s) [%s] {%s};\n" % \
-                      (tikzify(node.name), pos, style, label)
-            else:
-                color = node.attr.get('color', '')
-                drawstr = 'draw'
-                if style.strip() == 'filled':
-                    fillcolor = node.attr.get('fillcolor') or \
-                                node.attr.get('color') or "gray"
-                    drawstr = 'fill,draw'
-                    style = ''
-                    if color:
-                        code, color = self.set_tikzcolor(color, 'strokecolor')
-                        sn += code
-                        code, fillcolor = self.set_tikzcolor(fillcolor, 'fillcolor')
-                        sn += code
-                        drawstr = "draw=%s,fill=%s" % (color, fillcolor)
-                    else:
-                        code, fillcolor = self.set_tikzcolor(fillcolor, 'fillcolor')
-                        sn += code
-                        drawstr = "draw,fill=%s" % fillcolor
-                elif color:
-                    code, color = self.set_tikzcolor(color, 'strokecolor')
-                    sn += code
-                    drawstr += '=' + color
-
-                if style.strip():
-                    sn += "  \\node (%s) at (%s) [%s,%s,%s] {%s};\n" % \
-                          (tikzify(node.name), pos, drawstr, shape, style, label)
-                else:
-                    sn += "  \\node (%s) at (%s) [%s,%s] {%s};\n" % \
-                          (tikzify(node.name), pos, drawstr, shape, label)
-            sn += self.end_node(node)
-
-            s += sn
-        if nodeoptions:
-            s += "\\end{scope}\n"
-        self.body += s
-
-    def do_edges(self):
-        s = ""
-        edgeoptions = self.options.get('edgeoptions')
-        if edgeoptions:
-            s += "\\begin{scope}[%s]\n" % edgeoptions
-        for edge in self.edges:
-            # general_draw_string = getattr(edge, '_draw_', "")
-            label_string = getattr(edge, '_ldraw_', "")
-            # head_arrow_string = getattr(edge, '_hdraw_', "")
-            # tail_arrow_string = getattr(edge, '_tdraw_', "")
-            tail_label_string = getattr(edge, '_tldraw_', "")
-            head_label_string = getattr(edge, '_hldraw_', "")
-            topath = getattr(edge, 'topath', None)
-            s += self.draw_edge(edge)
-            if not self.options.get('tikzedgelabels') and not topath:
-                s += self.do_drawstring(label_string, edge)
-                s += self.do_drawstring(tail_label_string, edge, "tailtexlbl")
-                s += self.do_drawstring(head_label_string, edge, "headtexlbl")
-            else:
-                s += self.do_drawstring(tail_label_string, edge, "tailtexlbl")
-                s += self.do_drawstring(head_label_string, edge, "headtexlbl")
-
-        if edgeoptions:
-            s += "\\end{scope}\n"
-        self.body += s
-
-    def draw_edge(self, edge):
-        s = ""
-        if edge.attr.get('style', '') in ['invis', 'invisible']:
-            return ""
-        edges = self.get_edge_points(edge)
-        if len(edges) > 1:
-            log.warning('The tikz output format does not support edge'
-                        'concentrators yet. Expect ugly output or try the pgf or '
-                        'pstricks output formats.')
-        for arrowstyle, points in edges:
-            # PGF uses the fill style when drawing some arrowheads. We have to
-            # ensure that the fill color is the same as the pen color.
-            color = edge.attr.get('color', '')
-            pp = []
-            for point in points:
-                p = point.split(',')
-                pp.append("(%sbp,%sbp)" % (smart_float(p[0]), smart_float(p[1])))
-
-            edgestyle = edge.attr.get('style')
-
-            styles = []
-            if arrowstyle != '--':
-                # styles.append(arrowstyle)
-                styles = [arrowstyle]
-
-            if edgestyle:
-                edgestyles = [self.styles.get(key.strip(), key.strip()) \
-                              for key in edgestyle.split(',') if key]
-                styles.extend(edgestyles)
-
-            stylestr = ",".join(styles)
-            if color:
-                code, color = self.set_tikzcolor(color, 'strokecolor')
-                s += code
-                stylestr = color + ',' + stylestr
-            src = tikzify(edge.get_source())
-            # check for a port
-            if edge.src_port:
-                src_anchor = self.compass_map.get(edge.src_port.split(':')[-1], '')
-                if src_anchor:
-                    src = "%s.%s" % (src, src_anchor)
-            dst = tikzify(edge.get_destination())
-            if edge.dst_port:
-                dst_anchor = self.compass_map.get(edge.dst_port.split(':')[-1], '')
-                if dst_anchor:
-                    dst = "%s.%s" % (dst, dst_anchor)
-            topath = edge.attr.get('topath')
-
-            pstrs = ["%s .. controls %s and %s " % x for x in nsplit(pp, 3)]
-            pstrs[0] = "(%s) ..controls %s and %s " % (src, pp[1], pp[2])
-            extra = ""
-            if self.options.get('tikzedgelabels') or topath:
-                edgelabel = self.get_label(edge)
-                # log.warning('label: %s', edgelabel)
-                lblstyle = getattr(edge, 'lblstyle', '')
-                exstyle = getattr(edge, 'exstyle', '')
-                if exstyle:
-                    if lblstyle:
-                        lblstyle += ',' + exstyle
-                    else:
-                        lblstyle = exstyle
-                if lblstyle:
-                    lblstyle = '[' + lblstyle + ']'
-                else:
-                    lblstyle = ''
-                if edgelabel:
-                    extra = " node%s {%s}" % (lblstyle, edgelabel)
-
-            if topath:
-                s += "  \draw [%s] (%s) to[%s]%s (%s);\n" % (stylestr, src,
-                                                             topath, extra, dst)
-            elif not self.options.get('straightedges'):
-                s += "  \draw [%s] %s ..%s (%s);\n" % (stylestr,
-                                                       " .. ".join(pstrs), extra, dst)
-            else:
-                s += "  \draw [%s] (%s) --%s (%s);\n" % (stylestr, src, extra, dst)
-
-        return s
-
-    def start_node(self, node):
-        return ""
-
-    def end_node(self, node):
-        return ""
-
-
-PSTRICKSN_TEMPLATE = r"""\documentclass{article}
-% <<bbox>>
-\usepackage[x11names, svgnames]{xcolor}
-\usepackage[<<textencoding>>]{inputenc}
-\usepackage{graphicx}
-\usepackage{pst-all}
-\usepackage[a3paper,landscape]{geometry}
-\usepackage{amsmath}
-<<startpreprocsection>>%
-\usepackage[active,auctex]{preview}
-<<endpreprocsection>>%
-<<gvcols>>%
-<<docpreamble>>%
-
-
-\begin{document}
-\pagestyle{empty}
-<<startpreprocsection>>%
-<<preproccode>>%
-<<endpreprocsection>>%
-<<startoutputsection>>%
-\enlargethispage{100cm}
-
-% Start of code
-\begin{pspicture}[linewidth=1bp<<graphstyle>>]<<bbox>>
-  \pstVerb{2 setlinejoin} % set line join style to 'mitre'
-<<figpreamble>>%
-<<drawcommands>>
-<<figpostamble>>%
-\end{pspicture}
-% End of code
-<<endoutputsection>>%
-\end{document}
-%
-<<start_figonlysection>>
-\begin{pspicture}[linewidth=1bp<<graphstyle>>]<<bbox>>
-  \pstVerb{2 setlinejoin} % set line join style to 'mitre'
-<<figpreamble>>%
-<<drawcommands>>
-<<figpostamble>>%
-\end{pspicture}
-<<end_figonlysection>>
-%
-<<startcodeonlysection>>
-<<figpreamble>>%
-<<drawcommands>>
-<<figpostamble>>%
-<<endcodeonlysection>>
-"""
-
-
-# ----------------- mgn --------------
-
-
-class Dot2PSTricksNConv(Dot2PSTricksConv):
-    """A backend that utilizes the node and edge mechanism of PSTricks-Node"""
-
-    def __init__(self, options=None):
-        options = options or {}
-        # to connect nodes they have to defined. Therefore we have to ensure
-        # that code for generating nodes is outputted first.
-        options['switchdraworder'] = True
-        options['flattengraph'] = True
-        options['rawdim'] = True
-        self.template = PSTRICKSN_TEMPLATE
-        Dot2PSTricksConv.__init__(self, options)
-
-    def output_node_comment(self, node):
-        # With the node syntax comments are unnecessary
-        return ""
-
-    def do_nodes(self):
-        s = ""
-        for node in self.nodes:
-            self.currentnode = node
-
-            psshadeoption = getattr(node, 'psshadeoption', '')
-            psshape = getattr(node, 'psshape', '')
-
-            # detect node type, if psshape is not set
-            if len(psshape) == 0:
-                shape = getattr(node, 'shape', 'ellipse')
-                # box       -> psframebox
-                # circle    -> pscirclebox
-                # rectangle -> psframebox
-                psshape = "psframebox"
-                if shape == "circle":
-                    psshape = "pscirclebox"
-                if shape == "ellipse":
-                    psshape = "psovalbox"
-                if shape == "triangle":
-                    psshape = "pstribox"
-                    # TODO incomplete
-
-            width = getattr(node, 'width', '1')
-            height = getattr(node, 'height', '1')
-            psbox = getattr(node, 'psbox', 'false')
-
-            color = getattr(node, 'color', '')
-            fillcolor = getattr(node, 'fillcolor', '')
-
-            if len(color) > 0:
-                psshadeoption = "linecolor=" + color + "," + psshadeoption
-            if len(fillcolor) > 0:
-                psshadeoption = "fillcolor=" + fillcolor + "," + psshadeoption
-
-            style = getattr(node, 'style', '')
-            if len(style) > 0:
-                if style == "dotted":
-                    psshadeoption = "linestyle=dotted," + psshadeoption
-                if style == "dashed":
-                    psshadeoption = "linestyle=dashed," + psshadeoption
-                if style == "solid":
-                    psshadeoption = "linestyle=solid," + psshadeoption
-                if style == "bold":
-                    psshadeoption = "linewidth=2pt," + psshadeoption
-
-            pos = getattr(node, 'pos')
-            if not pos:
-                continue
-            x, y = pos.split(',')
-            label = self.get_label(node)
-            pos = "%sbp,%sbp" % (smart_float(x), smart_float(y))
-            # TODO style
-
-            sn = ""
-            sn += self.output_node_comment(node)
-            sn += self.start_node(node)
-            if psbox == "false":
-                sn += "\\rput(%s){\\rnode{%s}{\\%s[%s]{%s}}}\n" % \
-                      (pos, tikzify(node.name), psshape, psshadeoption, label)
-            else:
-                sn += "\\rput(%s){\\rnode{%s}{\\%s[%s]{\parbox[c][%sin][c]{%sin}{\centering %s}}}}\n" % \
-                      (pos, tikzify(node.name), psshape, psshadeoption, height, width, label)
-            sn += self.end_node(node)
-            s += sn
-        self.body += s
-
-    def do_edges(self):
-        s = ""
-        for edge in self.edges:
-            s += self.draw_edge(edge)
-        self.body += s
-
-    def draw_edge(self, edge):
-        s = ""
-        edges = self.get_edge_points(edge)
-        for arrowstyle, points in edges:
-            # styles = []
-            psarrow = getattr(edge, 'psarrow', '')
-
-            if len(psarrow) == 0:
-                stylestr = '-'
-            else:
-                stylestr = psarrow
-
-            psedge = getattr(edge, 'psedge', 'ncline')
-            psedgeoption = getattr(edge, 'psedgeoption', '')
-
-            color = getattr(edge, 'color', '')
-            fillcolor = getattr(edge, 'fillcolor', '')
-
-            if len(color) > 0:
-                psedgeoption = "linecolor=" + color + "," + psedgeoption
-            if len(fillcolor) > 0:
-                psedgeoption = "fillcolor=" + fillcolor + "," + psedgeoption
-
-            style = getattr(edge, 'style', '')
-            if len(style) > 0:
-                if style == "dotted":
-                    psedgeoption = "linestyle=dotted," + psedgeoption
-                if style == "dashed":
-                    psedgeoption = "linestyle=dashed," + psedgeoption
-                if style == "solid":
-                    psedgeoption = "linestyle=solid," + psedgeoption
-                if style == "bold":
-                    psedgeoption = "linewidth=2pt," + psedgeoption
-
-            pslabel = getattr(edge, 'pslabel', 'ncput')
-            pslabeloption = getattr(edge, 'pslabeloption', '')
-            label = getattr(edge, 'label', '')
-            headlabel = getattr(edge, 'headlabel', '')
-            taillabel = getattr(edge, 'taillabel', '')
-
-            src = tikzify(edge.get_source())
-            dst = tikzify(edge.get_destination())
-            s = "\\%s[%s]{%s}{%s}{%s}\n" % (psedge, psedgeoption, stylestr, src, dst)
-            if len(label) != 0:
-                s += "\\%s[%s]{%s}\n" % (pslabel, pslabeloption, label)
-            if len(headlabel) != 0:
-                pslabelhead = 'npos=0.8,' + pslabeloption
-                s += "\\%s[%s]{%s}\n" % (pslabel, pslabelhead, headlabel)
-            if len(taillabel) != 0:
-                pslabeltail = 'npos=0.2,' + pslabeloption
-                s += "\\%s[%s]{%s}\n" % (pslabel, pslabeltail, taillabel)
-        return s
-
-    def start_node(self, node):
-        return ""
-
-    def end_node(self, node):
-        return ""
-
-
-# ------------------ mgn ------------------
-
-class PositionsDotConv(Dot2PGFConv):
-    """A converter that returns a dictionary with node positions
-
-    Returns a dictionary with node name as key and a (x, y) tuple as value.
-    """
-
-    def output(self):
-        positions = {}
-        for node in self.nodes:
-            pos = getattr(node, 'pos', None)
-            if pos:
-                try:
-                    positions[node.name] = [int(p) for p in pos.split(',')]
-                except ValueError:
-                    positions[node.name] = [float(p) for p in pos.split(',')]
-        return positions
-
-
-dimext = r"""
-^.*? Preview:\s Snippet\s
-(?P<number>\d*)\s ended.
-\((?P<ht>\d*)\+(?P<dp>\d*)x(?P<wd>\d*)\)"""
-
-
-class TeXDimProc:
-    """Helper class for for finding the size of TeX snippets
-
-    Uses preview.sty
-    """
-
-    # Produce document
-    # Create a temporary directory
-    # Compile file with latex
-    # Parse log file
-    # Update graph with with and height parameters
-    # Clean up
-    def __init__(self, template, options):
-        self.template = template
-        self.snippets_code = []
-        self.snippets_id = []
-        self.options = options
-        self.dimext_re = re.compile(dimext, re.MULTILINE | re.VERBOSE)
-        pass
-
-    def add_snippet(self, snippet_id, code):
-        """A a snippet of code to be processed"""
-        self.snippets_id.append(snippet_id)
-        self.snippets_code.append(code)
-
-    def process(self):
-        """Process all snippets of code with TeX and preview.sty
-
-        Results are stored in the texdimlist and texdims class attributes.
-        Returns False if preprocessing fails
-        """
-        import shutil
-
-        if len(self.snippets_code) == 0:
-            log.warning('No labels to preprocess')
-            return True
-        self.tempdir = tempfile.mkdtemp(prefix='dot2tex')
-        log.debug('Creating temporary directroy %s' % self.tempdir)
-        self.tempfilename = os.path.join(self.tempdir, 'dot2tex.tex')
-        log.debug('Creating temporary file %s' % self.tempfilename)
-        s = ""
-        for n in self.snippets_code:
-            s += "\\begin{preview}%\n"
-            s += n.strip() + "%\n"
-            s += "\end{preview}%\n"
-        with open(self.tempfilename, 'w') as f:
-            f.write(self.template.replace('<<preproccode>>', s))
-        with open(self.tempfilename, 'r') as f:
-            s = f.read()
-        log.debug('Code written to %s\n' % self.tempfilename + s)
-        self.parse_log_file()
-        shutil.rmtree(self.tempdir)
-        log.debug('Temporary directory and files deleted')
-        if self.texdims:
-            return True
-        else:
-            return False
-            # cleanup
-
-    def parse_log_file(self):
-        logfilename = os.path.splitext(self.tempfilename)[0] + '.log'
-        tmpdir = os.getcwd()
-        os.chdir(os.path.split(logfilename)[0])
-        if self.options.get('usepdflatex'):
-            command = 'pdflatex -interaction=nonstopmode %s' % self.tempfilename
-        else:
-            command = 'latex -interaction=nonstopmode %s' % self.tempfilename
-        log.debug('Running command: %s' % command)
-
-        p = Popen(command, shell=True, stdout=PIPE, stderr=PIPE, close_fds=(sys.platform != 'win32'))
-        (stdout, stderr) = (p.stdout, p.stderr)
-        try:
-            data = stdout.read()
-            log.debug("stdout from latex\n %s", data)
-        finally:
-            stdout.close()
-
-        try:
-            error_data = stderr.read()
-            if error_data:
-                log.debug('latex STDERR %s', error_data)
-        finally:
-            stderr.close()
-        p.kill()
-        p.wait()
-
-        with open(logfilename, 'r') as f:
-            logdata = f.read()
-        log.debug('Logfile from LaTeX run: \n' + logdata)
-        os.chdir(tmpdir)
-
-        texdimdata = self.dimext_re.findall(logdata)
-        log.debug('Texdimdata: ' + str(texdimdata))
-        if len(texdimdata) == 0:
-            log.error('No dimension data could be extracted from dot2tex.tex.')
-            self.texdims = None
-            return
-
-        c = 1.0 / 4736286
-        self.texdims = {}
-        self.texdimlist = [(float(i[1]) * c, float(i[2]) * c, float(i[3]) * c) for i in texdimdata]
-        self.texdims = dict(zip(self.snippets_id, self.texdimlist))
-
-
 def create_options_parser():
-    """Create and and return an options parser.
-    """
+    """Create and and return an options parser."""
     description = 'Convert dot files to PGF/TikZ graphics' + \
                   ' for inclusion in LaTeX.'
     parser = argparse.ArgumentParser(prog='dot2tex', description=description)
@@ -2883,8 +257,6 @@ def load_dot_file(filename):
     return dotdata
 
 
-# # Program interface
-
 def main(run_as_module=False, dotdata=None, options=None):
     """Run dot2tex and convert graph
 
@@ -2995,14 +367,14 @@ def main(run_as_module=False, dotdata=None, options=None):
     dotdata = "".join(lines)
 
     if options.cache and not run_as_module:
-        import hashlib, cPickle
+        import hashlib, pickle
 
         if options.inputfile is not None and options.outputfile:
             log.info('Caching enabled')
             inputfilename = options.inputfile
             # calculate hash from command line options and dotdata
             m = hashlib.md5()
-            m.update(dotdata + "".join(sys.argv))
+            m.update((dotdata + "".join(sys.argv)).encode('utf-8'))
             inputhash = m.digest()
             log.debug('Hash for %s and command line : %s', inputfilename, inputhash)
             # now look for a hash file
@@ -3011,9 +383,9 @@ def main(run_as_module=False, dotdata=None, options=None):
             hashes = {}
             if path.exists(hashfilename):
                 log.info('Loading hash file %s', hashfilename)
-                with open(hashfilename, 'r') as f:
+                with open(hashfilename, 'rb') as f:
                     try:
-                        hashes = cPickle.load(f)
+                        hashes = pickle.load(f)
                     except:
                         log.exception('Failed to load hashfile')
             if hashes.get(key) == inputhash and path.exists(options.outputfile):
@@ -3022,9 +394,9 @@ def main(run_as_module=False, dotdata=None, options=None):
             else:
                 log.info('Hash or output file not found. Converting file')
                 hashes[key] = inputhash
-                with open(hashfilename, 'w') as f:
+                with open(hashfilename, 'wb') as f:
                     try:
-                        cPickle.dump(hashes, f)
+                        pickle.dump(hashes, f)
                     except:
                         log.warning('Failed to write hashfile')
         else:
@@ -3125,6 +497,3 @@ def convert_graph(dotsource, **kwargs):
     tex = main(True, dotsource, options)
     return tex
 
-
-if __name__ == '__main__':
-    main()
diff --git a/dot2tex/dotparsing.py b/dot2tex/dotparsing.py
index 391b5dc..c039eb2 100644
--- a/dot2tex/dotparsing.py
+++ b/dot2tex/dotparsing.py
@@ -8,7 +8,7 @@ Michael Krause <michael AT krause-software.de>
 Ero Carrera <ero AT dkbza.org>
 """
 
-__version__ = '2.11.3'
+__version__ = '2.12.dev'
 __author__ = ['Michael Krause', 'Ero Carrera', 'Kjell Magne Fauske']
 __license__ = 'MIT'
 
@@ -251,7 +251,7 @@ def find_graphviz():
 
         else:
             # Just in case, try the default...
-            path = r"C:\Program Files\att\Graphviz\bin"
+            path = r"C:\Program Files\Graphviz\bin"
 
         progs = __find_executables(path)
 
diff --git a/dot2tex/pgfformat.py b/dot2tex/pgfformat.py
new file mode 100644
index 0000000..23ccd3e
--- /dev/null
+++ b/dot2tex/pgfformat.py
@@ -0,0 +1,970 @@
+import logging
+
+from .base import DotConvBase, parse_drawstring, get_drawobj_lblstyle
+from .utils import smart_float, nsplit, getboolattr, tikzify
+
+log = logging.getLogger("dot2tex")
+
+PGF_TEMPLATE = r"""\documentclass{standalone}
+\usepackage[x11names, svgnames, rgb]{xcolor}
+\usepackage[<<textencoding>>]{inputenc}
+\usepackage{tikz}
+\usetikzlibrary{snakes,arrows,shapes}
+\usepackage{amsmath}
+<<startpreprocsection>>%
+\usepackage[active,auctex]{preview}
+<<endpreprocsection>>%
+<<gvcols>>%
+<<startoutputsection>>
+<<cropcode>>%
+<<endoutputsection>>
+<<docpreamble>>%
+
+\begin{document}
+%
+<<startpreprocsection>>%
+<<preproccode>>
+<<endpreprocsection>>%
+%
+<<startoutputsection>>
+% Start of code
+% \begin{tikzpicture}[anchor=mid,>=latex',line join=bevel,<<graphstyle>>]
+\begin{tikzpicture}[>=latex',line join=bevel,<<graphstyle>>]
+  \pgfsetlinewidth{1bp}
+<<figpreamble>>%
+<<drawcommands>>
+<<figpostamble>>%
+\end{tikzpicture}
+% End of code
+<<endoutputsection>>
+%
+\end{document}
+%
+<<start_figonlysection>>
+\begin{tikzpicture}[>=latex,line join=bevel,<<graphstyle>>]
+  \pgfsetlinewidth{1bp}
+<<figpreamble>>%
+<<drawcommands>>
+<<figpostamble>>%
+\end{tikzpicture}
+<<end_figonlysection>>
+<<startcodeonlysection>>
+<<figpreamble>>%
+<<drawcommands>>
+<<figpostamble>>%
+<<endcodeonlysection>>
+"""
+PGF210_TEMPLATE = r"""\documentclass{standalone}
+% dot2tex template for PGF 2.10
+\usepackage[x11names, svgnames, rgb]{xcolor}
+\usepackage[<<textencoding>>]{inputenc}
+\usepackage{tikz}
+\usetikzlibrary{snakes,arrows,shapes}
+\usepackage{amsmath}
+<<startpreprocsection>>%
+\usepackage[active,auctex]{preview}
+<<endpreprocsection>>%
+<<gvcols>>%
+<<startoutputsection>>
+<<cropcode>>%
+<<endoutputsection>>
+<<docpreamble>>%
+
+\begin{document}
+%
+<<startpreprocsection>>%
+<<preproccode>>
+<<endpreprocsection>>%
+%
+<<startoutputsection>>
+% Start of code
+% \begin{tikzpicture}[anchor=mid,>=latex',line join=bevel,<<graphstyle>>]
+\begin{tikzpicture}[>=latex',line join=bevel,<<graphstyle>>]
+  \pgfsetlinewidth{1bp}
+<<figpreamble>>%
+<<drawcommands>>
+<<figpostamble>>%
+\end{tikzpicture}
+% End of code
+<<endoutputsection>>
+%
+\end{document}
+%
+<<start_figonlysection>>
+\begin{tikzpicture}[>=latex,line join=bevel,<<graphstyle>>]
+  \pgfsetlinewidth{1bp}
+<<figpreamble>>%
+<<drawcommands>>
+<<figpostamble>>%
+\end{tikzpicture}
+<<end_figonlysection>>
+<<startcodeonlysection>>
+<<figpreamble>>%
+<<drawcommands>>
+<<figpostamble>>%
+<<endcodeonlysection>>
+"""
+PGF118_TEMPLATE = r"""\documentclass{standalone}
+\usepackage[x11names, rgb]{xcolor}
+\usepackage[<<textencoding>>]{inputenc}
+\usepackage{tikz}
+\usepackage{pgflibrarysnakes}
+\usepackage{pgflibraryarrows,pgflibraryshapes}
+\usepackage{amsmath}
+<<startpreprocsection>>%
+\usepackage[active,auctex]{preview}
+<<endpreprocsection>>%
+<<gvcols>>%
+<<cropcode>>%
+<<docpreamble>>%
+
+\begin{document}
+%
+<<startpreprocsection>>%
+<<preproccode>>
+<<endpreprocsection>>%
+%
+<<startoutputsection>>
+% Start of code
+\begin{tikzpicture}[>=latex',join=bevel,<<graphstyle>>]
+  \pgfsetlinewidth{1bp}
+<<figpreamble>>%
+<<drawcommands>>
+<<figpostamble>>%
+\end{tikzpicture}
+% End of code
+<<endoutputsection>>
+%
+\end{document}
+%
+<<start_figonlysection>>
+\begin{tikzpicture}[>=latex,join=bevel,<<graphstyle>>]
+  \pgfsetlinewidth{1bp}
+<<figpreamble>>%
+<<drawcommands>>
+<<figpostamble>>%
+\end{tikzpicture}
+<<end_figonlysection>>
+<<startcodeonlysection>>
+<<figpreamble>>%
+<<drawcommands>>
+<<figpostamble>>%
+<<endcodeonlysection>>
+"""
+
+
+class Dot2PGFConv(DotConvBase):
+    """PGF/TikZ converter backend"""
+    arrows_map_210 = {"dot": "*", "odot": "o", "empty": "open triangle 45", "invempty": "open triangle 45 reversed",
+                      "diamond": "diamond", "odiamond": "open diamond", "ediamond": "open diamond", "box": "square",
+                      "obox": "open square", "vee": "stealth'", "open": "stealth'", "tee": "|",
+                      "crow": "stealth reversed"}
+
+    def __init__(self, options=None):
+        DotConvBase.__init__(self, options)
+        if not self.template:
+            if options.get('pgf118'):
+                self.template = PGF118_TEMPLATE
+            elif options.get('pgf210'):
+                self.template = PGF210_TEMPLATE
+            else:
+                self.template = PGF_TEMPLATE
+        self.styles = dict(dashed='dashed', dotted='dotted',
+                           bold='very thick', filled='fill', invis="",
+                           rounded='rounded corners', )
+        self.dashstyles = dict(
+            dashed='\pgfsetdash{{3pt}{3pt}}{0pt}',
+            dotted='\pgfsetdash{{\pgflinewidth}{2pt}}{0pt}',
+            bold='\pgfsetlinewidth{1.2pt}')
+
+    def start_node(self, node):
+        # Todo: Should find a more elegant solution
+        self.pencolor = ""
+        self.fillcolor = ""
+        self.color = ""
+        return "\\begin{scope}\n"
+
+    def end_node(self, node):
+        return "\\end{scope}\n"
+
+    def start_edge(self):
+        # Todo: Should find a more elegant solution
+        # self.pencolor = "";
+        # self.fillcolor = ""
+        # self.color = ""
+        return "\\begin{scope}\n"
+
+    def end_edge(self):
+        return "\\end{scope}\n"
+
+    def start_graph(self, graph):
+        # Todo: Should find a more elegant solution
+        self.pencolor = ""
+        self.fillcolor = ""
+        self.color = ""
+        return "\\begin{scope}\n"
+
+    def end_graph(self, graph):
+        return "\\end{scope}\n"
+
+    def set_color(self, drawop):
+        c, color = drawop
+        res = self.convert_color(color, True)
+        opacity = None
+        if len(res) == 2:
+            ccolor, opacity = res
+        else:
+            ccolor = res
+        s = ""
+        if c == 'cC':
+            if self.color != color:
+                self.color = color
+                self.pencolor = color
+                self.fillcolor = color
+                if ccolor.startswith('{'):
+                    # rgb or hsb
+                    s += "  \definecolor{newcol}%s\n" % ccolor
+                    ccolor = 'newcol'
+                s += "  \pgfsetcolor{%s}\n" % ccolor
+        elif c == 'c':
+            # set pen color
+            if self.pencolor != color:
+                self.pencolor = color
+                self.color = ''
+                if ccolor.startswith('{'):
+                    # rgb or hsb
+                    s += "  \definecolor{strokecol}%s\n" % ccolor
+                    ccolor = 'strokecol'
+                s += "  \pgfsetstrokecolor{%s}\n" % ccolor
+            else:
+                return ""
+        elif c == 'C':
+            # set fill color
+            if self.fillcolor != color:
+                self.fillcolor = color
+                self.color = ''
+                if ccolor.startswith('{'):
+                    # rgb
+                    s += "  \definecolor{fillcol}%s\n" % ccolor
+                    ccolor = 'fillcol'
+                s += "  \pgfsetfillcolor{%s}\n" % ccolor
+                if not opacity is None:
+                    self.opacity = opacity
+                    # Todo: The opacity should probably be set directly when drawing
+                    # The \pgfsetfillcopacity cmd affects text as well
+                    # s += "  \pgfsetfillopacity{%s}\n" % opacity
+                else:
+                    self.opacity = None
+            else:
+                return ""
+        return s
+
+    def set_style(self, drawop):
+        c, style = drawop
+        pgfstyle = self.dashstyles.get(style, "")
+        if pgfstyle:
+            return "  %s\n" % pgfstyle
+        else:
+            return ""
+
+    def filter_styles(self, style):
+        filtered_styles = []
+        for item in style.split(','):
+            keyval = item.strip()
+            if keyval.find('setlinewidth') < 0 and not keyval == 'filled':
+                filtered_styles.append(keyval)
+        return ', '.join(filtered_styles)
+
+    def draw_ellipse(self, drawop, style=None):
+        op, x, y, w, h = drawop
+        s = ""
+        if op == 'E':
+            if self.opacity is not None:
+                # Todo: Need to know the state of the current node
+                cmd = 'filldraw [opacity=%s]' % self.opacity
+            else:
+                cmd = 'filldraw'
+        else:
+            cmd = "draw"
+
+        if style:
+            stylestr = " [%s]" % style
+        else:
+            stylestr = ''
+        s += "  \%s%s (%sbp,%sbp) ellipse (%sbp and %sbp);\n" % (cmd, stylestr, smart_float(x), smart_float(y),
+                                                                 # w+self.linewidth,h+self.linewidth)
+                                                                 smart_float(w), smart_float(h))
+        return s
+
+    def draw_polygon(self, drawop, style=None):
+        op, points = drawop
+        pp = ['(%sbp,%sbp)' % (smart_float(p[0]), smart_float(p[1])) for p in points]
+        cmd = "draw"
+        if op == 'P':
+            cmd = "filldraw"
+
+        if style:
+            stylestr = " [%s]" % style
+        else:
+            stylestr = ''
+        s = "  \%s%s %s -- cycle;\n" % (cmd, stylestr, " -- ".join(pp))
+        return s
+
+    def draw_polyline(self, drawop, style=None):
+        op, points = drawop
+        pp = ['(%sbp,%sbp)' % (smart_float(p[0]), smart_float(p[1])) for p in points]
+        stylestr = ''
+        return "  \draw%s %s;\n" % (stylestr, " -- ".join(pp))
+
+    def draw_text(self, drawop, style=None):
+        # The coordinates given by drawop are not the same as the node
+        # coordinates! This may give som odd results if graphviz' and
+        # LaTeX' fonts are very different.
+        if len(drawop) == 7:
+            c, x, y, align, w, text, valign = drawop
+        else:
+            c, x, y, align, w, text = drawop
+
+        styles = []
+        if align == "-1":
+            alignstr = 'right'  # left aligned
+        elif align == "1":
+            alignstr = 'left'  # right aligned
+        else:
+            alignstr = ""  # centered (default)
+        styles.append(alignstr)
+        styles.append(style)
+        lblstyle = ",".join([i for i in styles if i])
+        if lblstyle:
+            lblstyle = '[' + lblstyle + ']'
+        s = "  \draw (%sbp,%sbp) node%s {%s};\n" % (smart_float(x), smart_float(y), lblstyle, text)
+        return s
+
+    def draw_bezier(self, drawop, style=None):
+        s = ""
+        c, points = drawop
+        pp = []
+        for point in points:
+            pp.append("(%sbp,%sbp)" % (smart_float(point[0]), smart_float(point[1])))
+
+        pstrs = ["%s .. controls %s and %s " % p for p in nsplit(pp, 3)]
+        stylestr = ''
+        s += "  \draw%s %s .. %s;\n" % (stylestr, " .. ".join(pstrs), pp[-1])
+        return s
+
+    def do_edges(self):
+        s = ""
+        s += self.set_color(('cC', "black"))
+        for edge in self.edges:
+            general_draw_string = getattr(edge, '_draw_', "")
+            label_string = getattr(edge, '_ldraw_', "")
+            head_arrow_string = getattr(edge, '_hdraw_', "")
+            tail_arrow_string = getattr(edge, '_tdraw_', "")
+            tail_label_string = getattr(edge, '_tldraw_', "")
+            head_label_string = getattr(edge, '_hldraw_', "")
+
+            # Note that the order of the draw strings should be the same
+            # as in the xdot output.
+            drawstring = general_draw_string + " " + head_arrow_string + " " + tail_arrow_string \
+                         + " " + label_string
+            draw_operations, stat = parse_drawstring(drawstring)
+            if not drawstring.strip():
+                continue
+            s += self.output_edge_comment(edge)
+            if self.options.get('duplicate'):
+                s += self.start_edge()
+                s += self.do_draw_op(draw_operations, edge, stat)
+                s += self.do_drawstring(tail_label_string, edge, "tailtexlbl")
+                s += self.do_drawstring(head_label_string, edge, "headtexlbl")
+                s += self.end_edge()
+            else:
+                topath = getattr(edge, 'topath', None)
+                s += self.draw_edge(edge)
+                if not self.options.get('tikzedgelabels') and not topath:
+                    s += self.do_drawstring(label_string, edge)
+                    s += self.do_drawstring(tail_label_string, edge, "tailtexlbl")
+                    s += self.do_drawstring(head_label_string, edge, "headtexlbl")
+                else:
+                    s += self.do_drawstring(tail_label_string, edge, "tailtexlbl")
+                    s += self.do_drawstring(head_label_string, edge, "headtexlbl")
+
+        self.body += s
+
+    def draw_edge(self, edge):
+        s = ""
+        if edge.attr.get('style', '') in ['invis', 'invisible']:
+            return ""
+        edges = self.get_edge_points(edge)
+        for arrowstyle, points in edges:
+            # arrowstyle, points = self.get_edge_points(edge)
+            # PGF uses the fill style when drawing some arrowheads. We have to
+            # ensure that the fill color is the same as the pen color.
+            color = getattr(edge, 'color', '')
+
+            if self.color != color:
+                if color:
+                    s += self.set_color(('cC', color))
+                else:
+                    # reset to default color
+                    s += self.set_color(('cC', 'black'))
+
+            pp = []
+            for point in points:
+                p = point.split(',')
+                pp.append("(%sbp,%sbp)" % (smart_float(p[0]), smart_float(p[1])))
+
+            edgestyle = edge.attr.get('style', '')
+
+            styles = []
+            if arrowstyle != '--':
+                styles = [arrowstyle]
+
+            if edgestyle:
+                edgestyles = [self.styles.get(key.strip(), key.strip()) for key in edgestyle.split(',') if key]
+                styles.extend(edgestyles)
+
+            stylestr = ",".join(styles)
+            topath = getattr(edge, 'topath', None)
+
+            pstrs = ["%s .. controls %s and %s " % x for x in nsplit(pp, 3)]
+            extra = ""
+            if self.options.get('tikzedgelabels') or topath:
+                edgelabel = self.get_label(edge)
+                # log.warning('label: %s', edgelabel)
+
+                lblstyle = get_drawobj_lblstyle(edge)
+                if lblstyle:
+                    lblstyle = '[' + lblstyle + ']'
+                else:
+                    lblstyle = ''
+                if edgelabel:
+                    extra = " node%s {%s}" % (lblstyle, edgelabel)
+            src = pp[0]
+            dst = pp[-1]
+            if topath:
+                s += "  \draw [%s] %s to[%s]%s %s;\n" % (stylestr, src,
+                                                         topath, extra, dst)
+            elif not self.options.get('straightedges'):
+                s += "  \draw [%s] %s ..%s %s;\n" % (stylestr, " .. ".join(pstrs), extra, pp[-1])
+            else:
+                s += "  \draw [%s] %s --%s %s;\n" % (stylestr, pp[0], extra, pp[-1])
+
+        return s
+
+    def get_output_arrow_styles(self, arrow_style, edge):
+        dot_arrow_head = edge.attr.get("arrowhead")
+        dot_arrow_tail = edge.attr.get("arrowtail")
+        output_arrow_style = arrow_style
+        if dot_arrow_head:
+            pgf_arrow_head = self.arrows_map_210.get(dot_arrow_head)
+            if pgf_arrow_head:
+                output_arrow_style = output_arrow_style.replace(">", pgf_arrow_head)
+        if dot_arrow_tail:
+            pgf_arrow_tail = self.arrows_map_210.get(dot_arrow_tail)
+            if pgf_arrow_tail:
+                output_arrow_style = output_arrow_style.replace("<", pgf_arrow_tail)
+        return output_arrow_style
+
+    def init_template_vars(self):
+        DotConvBase.init_template_vars(self)
+        if self.options.get('crop'):
+            cropcode = "\\usepackage[active,tightpage]{preview}\n" + \
+                       "\\PreviewEnvironment{tikzpicture}\n" + \
+                       "\\setlength\\PreviewBorder{%s}" % self.options.get('margin', '0pt')
+        else:
+            cropcode = ""
+        variables = {'<<cropcode>>': cropcode}
+        self.templatevars.update(variables)
+
+    def get_node_preproc_code(self, node):
+        lblstyle = get_drawobj_lblstyle(node)
+        text = node.attr.get('texlbl', '')
+        if lblstyle:
+            return "  \\tikz \\node[%s] {%s};\n" % (lblstyle, text)
+        else:
+            return r"\tikz \node {" + text + "};"
+
+    def get_edge_preproc_code(self, edge, attribute="texlbl"):
+        lblstyle = edge.attr.get('lblstyle', '')
+        text = edge.attr.get(attribute, '')
+        if lblstyle:
+            return "  \\tikz \\node[%s] {%s};\n" % (lblstyle, text)
+        else:
+            return r"\tikz \node " + "{" + text + "};"
+
+    def get_graph_preproc_code(self, graph):
+        lblstyle = graph.attr.get('lblstyle', '')
+        text = graph.attr.get('texlbl', '')
+        if lblstyle:
+            return "  \\tikz \\node[%s] {%s};\n" % (lblstyle, text)
+        else:
+            return r"\tikz \node {" + text + "};"
+
+
+TIKZ_TEMPLATE = r"""\documentclass{standalone}
+\usepackage[x11names, svgnames, rgb]{xcolor}
+\usepackage[<<textencoding>>]{inputenc}
+\usepackage{tikz}
+\usetikzlibrary{snakes,arrows,shapes}
+\usepackage{amsmath}
+<<startpreprocsection>>%
+\usepackage[active,auctex]{preview}
+<<endpreprocsection>>%
+<<gvcols>>%
+<<startoutputsection>>
+<<cropcode>>%
+<<endoutputsection>>
+<<docpreamble>>%
+
+\begin{document}
+%
+<<startpreprocsection>>%
+<<preproccode>>
+<<endpreprocsection>>%
+%
+<<startoutputsection>>
+% Start of code
+\begin{tikzpicture}[>=latex',line join=bevel,<<graphstyle>>]
+<<figpreamble>>%
+<<drawcommands>>
+<<figpostamble>>%
+\end{tikzpicture}
+% End of code
+<<endoutputsection>>
+%
+\end{document}
+%
+<<start_figonlysection>>
+\begin{tikzpicture}[>=latex,line join=bevel,<<graphstyle>>]
+<<figpreamble>>%
+<<drawcommands>>
+<<figpostamble>>%
+\end{tikzpicture}
+<<end_figonlysection>>
+<<startcodeonlysection>>
+<<figpreamble>>%
+<<drawcommands>>
+<<figpostamble>>%
+<<endcodeonlysection>>
+"""
+TIKZ210_TEMPLATE = r"""\documentclass{standalone}
+% dot2tex template for PGF 2.10
+\usepackage[x11names, svgnames, rgb]{xcolor}
+\usepackage[<<textencoding>>]{inputenc}
+\usepackage{tikz}
+\usetikzlibrary{snakes,arrows,shapes}
+\usepackage{amsmath}
+<<startpreprocsection>>%
+\usepackage[active,auctex]{preview}
+<<endpreprocsection>>%
+<<gvcols>>%
+<<startoutputsection>>
+<<cropcode>>%
+<<endoutputsection>>
+<<docpreamble>>%
+
+\begin{document}
+%
+<<startpreprocsection>>%
+<<preproccode>>
+<<endpreprocsection>>%
+%
+<<startoutputsection>>
+% Start of code
+\begin{tikzpicture}[>=latex',line join=bevel,<<graphstyle>>]
+<<figpreamble>>%
+<<drawcommands>>
+<<figpostamble>>%
+\end{tikzpicture}
+% End of code
+<<endoutputsection>>
+%
+\end{document}
+%
+<<start_figonlysection>>
+\begin{tikzpicture}[>=latex,line join=bevel,<<graphstyle>>]
+<<figpreamble>>%
+<<drawcommands>>
+<<figpostamble>>%
+\end{tikzpicture}
+<<end_figonlysection>>
+<<startcodeonlysection>>
+<<figpreamble>>%
+<<drawcommands>>
+<<figpostamble>>%
+<<endcodeonlysection>>
+"""
+TIKZ118_TEMPLATE = r"""\documentclass{standalone}
+\usepackage[x11names, svgnames, rgb]{xcolor}
+\usepackage[<<textencoding>>]{inputenc}
+\usepackage{tikz}
+\usepackage{pgflibrarysnakes}
+\usepackage{pgflibraryarrows,pgflibraryshapes}
+\usepackage{amsmath}
+<<startpreprocsection>>%
+\usepackage[active,auctex]{preview}
+<<endpreprocsection>>%
+<<gvcols>>%
+<<cropcode>>%
+<<docpreamble>>%
+
+\begin{document}
+%
+<<startpreprocsection>>%
+<<preproccode>>
+<<endpreprocsection>>%
+%
+<<startoutputsection>>
+% Start of code
+\begin{tikzpicture}[>=latex',join=bevel,<<graphstyle>>]
+<<figpreamble>>%
+<<drawcommands>>
+<<figpostamble>>%
+\end{tikzpicture}
+% End of code
+<<endoutputsection>>
+%
+\end{document}
+%
+<<start_figonlysection>>
+\begin{tikzpicture}[>=latex,join=bevel,<<graphstyle>>]
+<<figpreamble>>%
+<<drawcommands>>
+<<figpostamble>>%
+\end{tikzpicture}
+<<end_figonlysection>>
+<<startcodeonlysection>>
+<<figpreamble>>%
+<<drawcommands>>
+<<figpostamble>>%
+<<endcodeonlysection>>
+"""
+
+
+class Dot2TikZConv(Dot2PGFConv):
+    """A backend that utilizes the node and edge mechanism of PGF/TikZ"""
+    shape_map = {'doublecircle': 'circle, double',
+                 'box': 'rectangle',
+                 'rect': 'rectangle',
+                 'none': 'draw=none',
+                 'plaintext': 'draw=none',
+                 'polygon': 'regular polygon, regular polygon sides=7',
+                 'triangle': 'regular polygon, regular polygon sides=3',
+                 'square': 'regular polygon, regular polygon sides=4',
+                 'pentagon': 'regular polygon, regular polygon sides=5',
+                 'hexagon': 'regular polygon, regular polygon sides=6',
+                 'septagon': 'regular polygon, regular polygon sides=7',
+                 'octagon': 'regular polygon, regular polygon sides=8',
+                 'point': 'circle, fill',
+                 'ellipse': 'ellipse',
+                 'oval': 'ellipse',
+                 'diamond': 'diamond',
+                 'trapezium': 'trapezium',
+                 'star': 'star',
+                 'circle': 'circle',
+                 'parallelogram': 'trapezium, trapezium left angle = 120, trapezium right angle = 60',
+                 }
+
+    compass_map = {'n': 'north', 'ne': 'north east', 'e': 'east',
+                   'se': 'south east', 's': 'south', 'sw': 'south west',
+                   'w': 'west', 'nw': 'north west', 'center': 'center'}
+
+    def __init__(self, options=None):
+        # to connect nodes they have to defined. Therefore we have to ensure
+        # that code for generating nodes is outputted first.
+        options = options or {}
+        options['switchdraworder'] = True
+        options['flattengraph'] = True
+        options['rawdim'] = True
+        if options.get('pgf118'):
+            self.template = TIKZ118_TEMPLATE
+        elif options.get('pgf210'):
+            self.template = TIKZ210_TEMPLATE
+        else:
+            self.template = TIKZ_TEMPLATE
+        DotConvBase.__init__(self, options)
+
+        self.styles = dict(dashed='dashed', dotted='dotted',
+                           bold='very thick', filled='fill', invis="", invisible="",
+                           rounded='rounded corners', )
+        self.dashstyles = dict(
+            dashed='\pgfsetdash{{3pt}{3pt}}{0pt}',
+            dotted='\pgfsetdash{{\pgflinewidth}{2pt}}{0pt}',
+            bold='\pgfsetlinewidth{1.2pt}')
+
+    def set_options(self):
+        Dot2PGFConv.set_options(self)
+        self.options['tikzedgelabels'] = self.options.get('tikzedgelabels', '') \
+                                         or getboolattr(self.main_graph, 'd2ttikzedgelabels', '')
+        self.options['styleonly'] = self.options.get('styleonly', '') \
+                                    or getboolattr(self.main_graph, 'd2tstyleonly', '')
+        self.options['nodeoptions'] = self.options.get('nodeoptions', '') \
+                                      or getattr(self.main_graph, 'd2tnodeoptions', '')
+        self.options['edgeoptions'] = self.options.get('edgeoptions', '') \
+                                      or getattr(self.main_graph, 'd2tedgeoptions', '')
+
+    def output_node_comment(self, node):
+        # With the node syntax comments are unnecessary
+        return ""
+
+    def set_tikzcolor(self, color, colorname):
+        res = self.convert_color(color, True)
+        if len(res) == 2:
+            ccolor, opacity = res
+            if not (opacity == '1'):
+                log.warning('Opacity not supported yet: %s', res)
+        else:
+            ccolor = res
+        s = ""
+        if ccolor.startswith('{'):
+            # rgb or hsb
+            s += "  \definecolor{%s}%s;\n" % (colorname, ccolor)
+            cname = colorname
+        else:
+            cname = color
+
+        return s, cname
+
+    def get_node_preproc_code(self, node):
+        shape = node.attr.get('shape', 'ellipse')
+        shape = self.shape_map.get(shape, shape)
+        # s += "%% %s\n" % (shape)
+        label = node.attr.get('texlbl', '')
+        style = node.attr.get('style', " ") or " "
+        lblstyle = get_drawobj_lblstyle(node)
+        if lblstyle:
+            if style.strip():
+                style += ',' + lblstyle
+            else:
+                style = lblstyle
+
+        sn = ""
+        if self.options.get('styleonly'):
+            sn += "\\tikz  \\node [%s] {%s};\n" % \
+                  (style, label)
+        else:
+            sn += "\\tikz  \\node [draw,%s,%s] {%s};\n" % \
+                  (shape, style, label)
+        return sn
+
+    def do_nodes(self):
+        s = ""
+        nodeoptions = self.options.get('nodeoptions')
+        if nodeoptions:
+            s += "\\begin{scope}[%s]\n" % nodeoptions
+        for node in self.nodes:
+            self.currentnode = node
+            # detect node type
+            dotshape = getattr(node, 'shape', 'ellipse')
+            shape = None
+
+            if node.attr.get('style') in ['invis', 'invisible']:
+                shape = "coordinate"
+            else:
+                shape = self.shape_map.get(dotshape, shape)
+            if shape is None:
+                shape = 'ellipse'
+
+            pos = getattr(node, 'pos', None)
+            if not pos:
+                continue
+            x, y = pos.split(',')
+            if dotshape != 'point':
+                label = self.get_label(node)
+            else:
+                label = ''
+
+            pos = "%sbp,%sbp" % (smart_float(x), smart_float(y))
+            style = node.attr.get('style') or ""
+            lblstyle = get_drawobj_lblstyle(node, extra_styles=node.attr.get('exstyle'))
+            if lblstyle:
+                if style:
+                    style += ',' + lblstyle
+                else:
+                    style = lblstyle
+            sn = ""
+            sn += self.output_node_comment(node)
+            sn += self.start_node(node)
+
+            # Quick and dirty introduction of handling for xlabel
+            # xlabel = self.get_label(node, label_attribute="xlabel")
+            xlabel = None
+            if 'xlabel' in node.attr:
+                #node.attr['texlbl'] = node.attr['xlabel']
+                node.attr['texlbl'] = None
+                xlabel = self.get_label(node,label_attribute="xlabel")
+            #xlabel = node.attr['xlabel'] if 'xlabel' in node.attr else None
+            if xlabel is not None:
+                #xlpos = "%sbp,%sbp" % (smart_float(str(float(x)+len(xlabel)*5)), smart_float(y))
+                xlp = getattr(node, 'xlp', None)
+                if not xlp:
+                    continue
+                xlpx, xlpy = xlp.split(',')
+                xlpx = str(abs(float(x)-float(xlpx))+float(x))
+                xlpy = y
+                xlpos = "%sbp,%sbp" % (smart_float(xlpx), smart_float(xlpy))
+                sn += "  \\node (%s) at (%s) [%s] {%s};\n" % \
+                      (tikzify(node.name+"xl"), xlpos, "", xlabel)
+            if shape == "coordinate":
+                sn += "  \\coordinate (%s) at (%s);\n" % (tikzify(node.name), pos)
+            elif self.options.get('styleonly'):
+                sn += "  \\node (%s) at (%s) [%s] {%s};\n" % \
+                      (tikzify(node.name), pos, style, label)
+            else:
+                color = node.attr.get('color', '')
+                drawstr = 'draw'
+                if style.strip() == 'filled':
+                    fillcolor = node.attr.get('fillcolor') or \
+                                node.attr.get('color') or "gray"
+                    drawstr = 'fill,draw'
+                    style = ''
+                    if color:
+                        code, color = self.set_tikzcolor(color, 'strokecolor')
+                        sn += code
+                        code, fillcolor = self.set_tikzcolor(fillcolor, 'fillcolor')
+                        sn += code
+                        drawstr = "draw=%s,fill=%s" % (color, fillcolor)
+                    else:
+                        code, fillcolor = self.set_tikzcolor(fillcolor, 'fillcolor')
+                        sn += code
+                        drawstr = "draw,fill=%s" % fillcolor
+                elif color:
+                    code, color = self.set_tikzcolor(color, 'strokecolor')
+                    sn += code
+                    drawstr += '=' + color
+
+                if style.strip():
+                    sn += "  \\node (%s) at (%s) [%s,%s,%s] {%s};\n" % \
+                          (tikzify(node.name), pos, drawstr, shape, style, label)
+                else:
+                    sn += "  \\node (%s) at (%s) [%s,%s] {%s};\n" % \
+                          (tikzify(node.name), pos, drawstr, shape, label)
+            sn += self.end_node(node)
+
+            s += sn
+        if nodeoptions:
+            s += "\\end{scope}\n"
+        self.body += s
+
+    def do_edges(self):
+        s = ""
+        edgeoptions = self.options.get('edgeoptions')
+        if edgeoptions:
+            s += "\\begin{scope}[%s]\n" % edgeoptions
+        for edge in self.edges:
+            # general_draw_string = getattr(edge, '_draw_', "")
+            label_string = getattr(edge, '_ldraw_', "")
+            # head_arrow_string = getattr(edge, '_hdraw_', "")
+            # tail_arrow_string = getattr(edge, '_tdraw_', "")
+            tail_label_string = getattr(edge, '_tldraw_', "")
+            head_label_string = getattr(edge, '_hldraw_', "")
+            topath = getattr(edge, 'topath', None)
+            s += self.draw_edge(edge)
+            if not self.options.get('tikzedgelabels') and not topath:
+                s += self.do_drawstring(label_string, edge)
+                s += self.do_drawstring(tail_label_string, edge, "tailtexlbl")
+                s += self.do_drawstring(head_label_string, edge, "headtexlbl")
+            else:
+                s += self.do_drawstring(tail_label_string, edge, "tailtexlbl")
+                s += self.do_drawstring(head_label_string, edge, "headtexlbl")
+
+        if edgeoptions:
+            s += "\\end{scope}\n"
+        self.body += s
+
+    def draw_edge(self, edge):
+        s = ""
+        if edge.attr.get('style', '') in ['invis', 'invisible']:
+            return ""
+        edges = self.get_edge_points(edge)
+        if len(edges) > 1:
+            log.warning('The tikz output format does not support edge'
+                        'concentrators yet. Expect ugly output or try the pgf or '
+                        'pstricks output formats.')
+        for arrowstyle, points in edges:
+            # PGF uses the fill style when drawing some arrowheads. We have to
+            # ensure that the fill color is the same as the pen color.
+            color = edge.attr.get('color', '')
+            pp = []
+            for point in points:
+                p = point.split(',')
+                pp.append("(%sbp,%sbp)" % (smart_float(p[0]), smart_float(p[1])))
+
+            edgestyle = edge.attr.get('style')
+
+            styles = []
+            if arrowstyle != '--':
+                # styles.append(arrowstyle)
+                styles = [arrowstyle]
+
+            if edgestyle:
+                edgestyles = [self.styles.get(key.strip(), key.strip()) \
+                              for key in edgestyle.split(',') if key]
+                styles.extend(edgestyles)
+
+            stylestr = ",".join(styles)
+            if color:
+                code, color = self.set_tikzcolor(color, 'strokecolor')
+                s += code
+                stylestr = color + ',' + stylestr
+            src = tikzify(edge.get_source())
+            # check for a port
+            if edge.src_port:
+                src_anchor = self.compass_map.get(edge.src_port.split(':')[-1], '')
+                if src_anchor:
+                    src = "%s.%s" % (src, src_anchor)
+            dst = tikzify(edge.get_destination())
+            if edge.dst_port:
+                dst_anchor = self.compass_map.get(edge.dst_port.split(':')[-1], '')
+                if dst_anchor:
+                    dst = "%s.%s" % (dst, dst_anchor)
+            topath = edge.attr.get('topath')
+
+            pstrs = ["%s .. controls %s and %s " % x for x in nsplit(pp, 3)]
+            pstrs[0] = "(%s) ..controls %s and %s " % (src, pp[1], pp[2])
+            extra = ""
+            if self.options.get('tikzedgelabels') or topath:
+                edgelabel = self.get_label(edge)
+                # log.warning('label: %s', edgelabel)
+                lblstyle = get_drawobj_lblstyle(edge, extra_styles=edge.attr.get('exstyle'))
+                if lblstyle:
+                    lblstyle = '[' + lblstyle + ']'
+                else:
+                    lblstyle = ''
+                if edgelabel:
+                    extra = " node%s {%s}" % (lblstyle, edgelabel)
+
+            if topath:
+                s += "  \draw [%s] (%s) to[%s]%s (%s);\n" % (stylestr, src,
+                                                             topath, extra, dst)
+            elif not self.options.get('straightedges'):
+                s += "  \draw [%s] %s ..%s (%s);\n" % (stylestr,
+                                                       " .. ".join(pstrs), extra, dst)
+            else:
+                s += "  \draw [%s] (%s) --%s (%s);\n" % (stylestr, src, extra, dst)
+
+        return s
+
+    def start_node(self, node):
+        return ""
+
+    def end_node(self, node):
+        return ""
+
+
+class PositionsDotConv(Dot2PGFConv):
+    """A converter that returns a dictionary with node positions
+
+    Returns a dictionary with node name as key and a (x, y) tuple as value.
+    """
+
+    def output(self):
+        positions = {}
+        for node in self.nodes:
+            pos = getattr(node, 'pos', None)
+            if pos:
+                try:
+                    positions[node.name] = [int(p) for p in pos.split(',')]
+                except ValueError:
+                    positions[node.name] = [float(p) for p in pos.split(',')]
+        return positions
diff --git a/dot2tex/pstricksformat.py b/dot2tex/pstricksformat.py
new file mode 100644
index 0000000..45e9678
--- /dev/null
+++ b/dot2tex/pstricksformat.py
@@ -0,0 +1,468 @@
+import logging
+
+from .base import DotConvBase
+from .utils import smart_float, tikzify
+
+log = logging.getLogger("dot2tex")
+
+PSTRICKS_TEMPLATE = r"""\documentclass{standalone}
+% <<bbox>>
+\usepackage[x11names,svgnames]{xcolor}
+\usepackage[<<textencoding>>]{inputenc}
+\usepackage{graphicx}
+\usepackage{pstricks}
+\usepackage{amsmath}
+<<startpreprocsection>>%
+\usepackage[active,auctex]{preview}
+<<endpreprocsection>>%
+<<gvcols>>%
+<<docpreamble>>%
+
+
+\begin{document}
+<<startpreprocsection>>%
+<<preproccode>>%
+<<endpreprocsection>>%
+<<startoutputsection>>%
+
+% Start of code
+\begin{pspicture}[linewidth=1bp<<graphstyle>>]<<bbox>>
+  \pstVerb{2 setlinejoin} % set line join style to 'mitre'
+<<figpreamble>>%
+<<drawcommands>>
+<<figpostamble>>%
+\end{pspicture}
+% End of code
+<<endoutputsection>>%
+\end{document}
+%
+<<start_figonlysection>>
+\begin{pspicture}[linewidth=1bp<<graphstyle>>]<<bbox>>
+  \pstVerb{2 setlinejoin} % set line join style to 'mitre'
+<<figpreamble>>%
+<<drawcommands>>
+<<figpostamble>>%
+\end{pspicture}
+<<end_figonlysection>>
+%
+<<startcodeonlysection>>
+<<figpreamble>>%
+<<drawcommands>>
+<<figpostamble>>%
+<<endcodeonlysection>>
+"""
+
+
+class Dot2PSTricksConv(DotConvBase):
+    """PSTricks converter backend"""
+
+    def __init__(self, options=None):
+        DotConvBase.__init__(self, options)
+        if not self.template:
+            self.template = PSTRICKS_TEMPLATE
+        self.styles = dict(
+            dotted="linestyle=dotted",
+            dashed="linestyle=dashed",
+            bold="linewidth=2pt",
+            solid="",
+            filled="",
+        )
+
+    def do_graphtmp(self):
+        self.pencolor = ""
+        self.fillcolor = ""
+        self.color = ""
+        self.body += '{\n'
+        DotConvBase.do_graph(self)
+        self.body += '}\n'
+
+    def draw_ellipse(self, drawop, style=None):
+        op, x, y, w, h = drawop
+        s = ""
+        if op == 'E':
+            if style:
+                style = style.replace('filled', '')
+            stylestr = 'fillstyle=solid'
+        else:
+            stylestr = ""
+
+        if style:
+            if stylestr:
+                stylestr += ',' + style
+            else:
+                stylestr = style
+
+        s += "  \psellipse[%s](%sbp,%sbp)(%sbp,%sbp)\n" % (stylestr, smart_float(x), smart_float(y),
+                                                           # w+self.linewidth,h+self.linewidth)
+                                                           smart_float(w), smart_float(h))
+
+        return s
+
+    def draw_polygon(self, drawop, style=None):
+        op, points = drawop
+        pp = ['(%sbp,%sbp)' % (smart_float(p[0]), smart_float(p[1])) for p in points]
+        stylestr = ""
+        if op == 'P':
+            if style:
+                style = style.replace('filled', '')
+            stylestr = "fillstyle=solid"
+        if style:
+            if stylestr:
+                stylestr += ',' + style
+            else:
+                stylestr = style
+
+        s = "  \pspolygon[%s]%s\n" % (stylestr, "".join(pp))
+        return s
+
+    def draw_polyline(self, drawop, style=None):
+        op, points = drawop
+        pp = ['(%sbp,%sbp)' % (smart_float(p[0]), smart_float(p[1])) for p in points]
+        s = "  \psline%s\n" % "".join(pp)
+        return s
+
+    def draw_bezier(self, drawop, style=None):
+        op, points = drawop
+        pp = []
+        for point in points:
+            pp.append("(%sbp,%sbp)" % (smart_float(point[0]), smart_float(point[1])))
+
+        arrowstyle = ""
+        return "  \psbezier{%s}%s\n" % (arrowstyle, "".join(pp))
+
+    def draw_text(self, drawop, style=None):
+        if len(drawop) == 7:
+            c, x, y, align, w, text, valign = drawop
+        else:
+            c, x, y, align, w, text = drawop
+            valign = ""
+        if align == "-1":
+            alignstr = 'l'  # left aligned
+        elif align == "1":
+            alignstr = 'r'  # right aligned
+        else:
+            alignstr = ""  # centered (default)
+        if alignstr or valign:
+            alignstr = '[' + alignstr + valign + ']'
+        s = "  \\rput%s(%sbp,%sbp){%s}\n" % (alignstr, smart_float(x), smart_float(y), text)
+        return s
+
+    def set_color(self, drawop):
+        c, color = drawop
+        color = self.convert_color(color)
+        s = ""
+        if c == 'c':
+            # set pen color
+            if self.pencolor != color:
+                self.pencolor = color
+                s = "  \psset{linecolor=%s}\n" % color
+            else:
+                return ""
+        elif c == 'C':
+            # set fill color
+            if self.fillcolor != color:
+                self.fillcolor = color
+                s = "  \psset{fillcolor=%s}\n" % color
+            else:
+                return ""
+        elif c == 'cC':
+            if self.color != color:
+                self.color = color
+                self.pencolor = self.fillcolor = color
+                s = "  \psset{linecolor=%s}\n" % color
+        else:
+            log.warning('Unhandled color: %s', drawop)
+        return s
+
+    def set_style(self, drawop):
+        c, style = drawop
+        psstyle = self.styles.get(style, "")
+        if psstyle:
+            return "  \psset{%s}\n" % psstyle
+        else:
+            return ""
+
+    def filter_styles(self, style):
+        filtered_styles = []
+        for item in style.split(','):
+            keyval = item.strip()
+            if keyval.find('setlinewidth') < 0:
+                filtered_styles.append(keyval)
+        return ', '.join(filtered_styles)
+
+    def start_node(self, node):
+        self.pencolor = ""
+        self.fillcolor = ""
+        self.color = ""
+        return "{%\n"
+
+    def end_node(self, node):
+        return "}%\n"
+
+    def start_edge(self):
+        self.pencolor = ""
+        self.fillcolor = ""
+        return "{%\n"
+
+    def end_edge(self):
+        return "}%\n"
+
+    def start_graph(self, graph):
+        self.pencolor = ""
+        self.fillcolor = ""
+        self.color = ""
+        return "{\n"
+
+    def end_graph(self, node):
+        return "}\n"
+
+    def draw_edge(self, edge):
+        s = ""
+        if edge.attr.get('style', '') in ['invis', 'invisible']:
+            return ""
+        edges = self.get_edge_points(edge)
+        for arrowstyle, points in edges:
+            if arrowstyle == '--':
+                arrowstyle = ''
+            color = getattr(edge, 'color', '')
+            if self.color != color:
+                if color:
+                    s += self.set_color(('c', color))
+                else:
+                    # reset to default color
+                    s += self.set_color(('c', 'black'))
+            pp = []
+            for point in points:
+                p = point.split(',')
+                pp.append("(%sbp,%sbp)" % (smart_float(p[0]), smart_float(p[1])))
+
+            edgestyle = edge.attr.get('style', '')
+            styles = []
+            if arrowstyle:
+                styles.append('arrows=%s' % arrowstyle)
+            if edgestyle:
+                edgestyles = [self.styles.get(key.strip(), key.strip())
+                              for key in edgestyle.split(',') if key]
+                styles.extend(edgestyles)
+            if styles:
+                stylestr = ",".join(styles)
+            else:
+                stylestr = ""
+            if not self.options.get('straightedges'):
+                s += "  \psbezier[%s]%s\n" % (stylestr, "".join(pp))
+            else:
+                s += "  \psline[%s]%s%s\n" % (stylestr, pp[0], pp[-1])
+                # s += "  \psbezier[%s]{%s}%s\n" % (stylestr, arrowstyle,"".join(pp))
+                ##        if edge.label:
+                ##            x,y = edge.lp.split(',')
+                ##            #s += "\\rput(%s,%s){%s}\n" % (x,y,edge.label)
+        return s
+
+    def init_template_vars(self):
+        DotConvBase.init_template_vars(self)
+        # Put a ',' before <<graphstyle>>
+        graphstyle = self.templatevars.get('<<graphstyle>>', '')
+        if graphstyle:
+            graphstyle = graphstyle.strip()
+            if not graphstyle.startswith(','):
+                graphstyle = ',' + graphstyle
+                self.templatevars['<<graphstyle>>'] = graphstyle
+
+
+PSTRICKSN_TEMPLATE = r"""\documentclass{standalone}
+% <<bbox>>
+\usepackage[x11names, svgnames]{xcolor}
+\usepackage[<<textencoding>>]{inputenc}
+\usepackage{graphicx}
+\usepackage{pst-all}
+\usepackage[a3paper,landscape]{geometry}
+\usepackage{amsmath}
+<<startpreprocsection>>%
+\usepackage[active,auctex]{preview}
+<<endpreprocsection>>%
+<<gvcols>>%
+<<docpreamble>>%
+
+
+\begin{document}
+<<startpreprocsection>>%
+<<preproccode>>%
+<<endpreprocsection>>%
+<<startoutputsection>>%
+
+% Start of code
+\begin{pspicture}[linewidth=1bp<<graphstyle>>]<<bbox>>
+  \pstVerb{2 setlinejoin} % set line join style to 'mitre'
+<<figpreamble>>%
+<<drawcommands>>
+<<figpostamble>>%
+\end{pspicture}
+% End of code
+<<endoutputsection>>%
+\end{document}
+%
+<<start_figonlysection>>
+\begin{pspicture}[linewidth=1bp<<graphstyle>>]<<bbox>>
+  \pstVerb{2 setlinejoin} % set line join style to 'mitre'
+<<figpreamble>>%
+<<drawcommands>>
+<<figpostamble>>%
+\end{pspicture}
+<<end_figonlysection>>
+%
+<<startcodeonlysection>>
+<<figpreamble>>%
+<<drawcommands>>
+<<figpostamble>>%
+<<endcodeonlysection>>
+"""
+
+
+class Dot2PSTricksNConv(Dot2PSTricksConv):
+    """A backend that utilizes the node and edge mechanism of PSTricks-Node"""
+
+    def __init__(self, options=None):
+        options = options or {}
+        # to connect nodes they have to defined. Therefore we have to ensure
+        # that code for generating nodes is outputted first.
+        options['switchdraworder'] = True
+        options['flattengraph'] = True
+        options['rawdim'] = True
+        self.template = PSTRICKSN_TEMPLATE
+        Dot2PSTricksConv.__init__(self, options)
+
+    def output_node_comment(self, node):
+        # With the node syntax comments are unnecessary
+        return ""
+
+    def do_nodes(self):
+        s = ""
+        for node in self.nodes:
+            self.currentnode = node
+
+            psshadeoption = getattr(node, 'psshadeoption', '')
+            psshape = getattr(node, 'psshape', '')
+
+            # detect node type, if psshape is not set
+            if len(psshape) == 0:
+                shape = getattr(node, 'shape', 'ellipse')
+                # box       -> psframebox
+                # circle    -> pscirclebox
+                # rectangle -> psframebox
+                psshape = "psframebox"
+                if shape == "circle":
+                    psshape = "pscirclebox"
+                if shape == "ellipse":
+                    psshape = "psovalbox"
+                if shape == "triangle":
+                    psshape = "pstribox"
+                    # TODO incomplete
+
+            width = getattr(node, 'width', '1')
+            height = getattr(node, 'height', '1')
+            psbox = getattr(node, 'psbox', 'false')
+
+            color = getattr(node, 'color', '')
+            fillcolor = getattr(node, 'fillcolor', '')
+
+            if len(color) > 0:
+                psshadeoption = "linecolor=" + color + "," + psshadeoption
+            if len(fillcolor) > 0:
+                psshadeoption = "fillcolor=" + fillcolor + "," + psshadeoption
+
+            style = getattr(node, 'style', '')
+            if len(style) > 0:
+                if style == "dotted":
+                    psshadeoption = "linestyle=dotted," + psshadeoption
+                if style == "dashed":
+                    psshadeoption = "linestyle=dashed," + psshadeoption
+                if style == "solid":
+                    psshadeoption = "linestyle=solid," + psshadeoption
+                if style == "bold":
+                    psshadeoption = "linewidth=2pt," + psshadeoption
+
+            pos = getattr(node, 'pos')
+            if not pos:
+                continue
+            x, y = pos.split(',')
+            label = self.get_label(node)
+            pos = "%sbp,%sbp" % (smart_float(x), smart_float(y))
+            # TODO style
+
+            sn = ""
+            sn += self.output_node_comment(node)
+            sn += self.start_node(node)
+            if psbox == "false":
+                sn += "\\rput(%s){\\rnode{%s}{\\%s[%s]{%s}}}\n" % \
+                      (pos, tikzify(node.name), psshape, psshadeoption, label)
+            else:
+                sn += "\\rput(%s){\\rnode{%s}{\\%s[%s]{\parbox[c][%sin][c]{%sin}{\centering %s}}}}\n" % \
+                      (pos, tikzify(node.name), psshape, psshadeoption, height, width, label)
+            sn += self.end_node(node)
+            s += sn
+        self.body += s
+
+    def do_edges(self):
+        s = ""
+        for edge in self.edges:
+            s += self.draw_edge(edge)
+        self.body += s
+
+    def draw_edge(self, edge):
+        s = ""
+        edges = self.get_edge_points(edge)
+        for arrowstyle, points in edges:
+            # styles = []
+            psarrow = getattr(edge, 'psarrow', '')
+
+            if len(psarrow) == 0:
+                stylestr = '-'
+            else:
+                stylestr = psarrow
+
+            psedge = getattr(edge, 'psedge', 'ncline')
+            psedgeoption = getattr(edge, 'psedgeoption', '')
+
+            color = getattr(edge, 'color', '')
+            fillcolor = getattr(edge, 'fillcolor', '')
+
+            if len(color) > 0:
+                psedgeoption = "linecolor=" + color + "," + psedgeoption
+            if len(fillcolor) > 0:
+                psedgeoption = "fillcolor=" + fillcolor + "," + psedgeoption
+
+            style = getattr(edge, 'style', '')
+            if len(style) > 0:
+                if style == "dotted":
+                    psedgeoption = "linestyle=dotted," + psedgeoption
+                if style == "dashed":
+                    psedgeoption = "linestyle=dashed," + psedgeoption
+                if style == "solid":
+                    psedgeoption = "linestyle=solid," + psedgeoption
+                if style == "bold":
+                    psedgeoption = "linewidth=2pt," + psedgeoption
+
+            pslabel = getattr(edge, 'pslabel', 'ncput')
+            pslabeloption = getattr(edge, 'pslabeloption', '')
+            label = getattr(edge, 'label', '')
+            headlabel = getattr(edge, 'headlabel', '')
+            taillabel = getattr(edge, 'taillabel', '')
+
+            src = tikzify(edge.get_source())
+            dst = tikzify(edge.get_destination())
+            s = "\\%s[%s]{%s}{%s}{%s}\n" % (psedge, psedgeoption, stylestr, src, dst)
+            if len(label) != 0:
+                s += "\\%s[%s]{%s}\n" % (pslabel, pslabeloption, label)
+            if len(headlabel) != 0:
+                pslabelhead = 'npos=0.8,' + pslabeloption
+                s += "\\%s[%s]{%s}\n" % (pslabel, pslabelhead, headlabel)
+            if len(taillabel) != 0:
+                pslabeltail = 'npos=0.2,' + pslabeloption
+                s += "\\%s[%s]{%s}\n" % (pslabel, pslabeltail, taillabel)
+        return s
+
+    def start_node(self, node):
+        return ""
+
+    def end_node(self, node):
+        return ""
\ No newline at end of file
diff --git a/dot2tex/utils.py b/dot2tex/utils.py
new file mode 100644
index 0000000..09739c7
--- /dev/null
+++ b/dot2tex/utils.py
@@ -0,0 +1,127 @@
+from . import dotparsing
+
+# Inch to bp conversion factor
+INCH2BP = 72.0
+SPECIAL_CHARS = ['$', '\\', '%', '_', '#', '{', r'}', '^', '&']
+SPECIAL_CHARS_REPLACE = [r'\$', r'$\backslash$', r'\%', r'\_', r'\#',
+                         r'\{', r'\}', r'\^{}', r'\&']
+charmap = dict(zip(SPECIAL_CHARS, SPECIAL_CHARS_REPLACE))
+
+
+def mreplace(s, chararray, newchararray):
+    for a, b in zip(chararray, newchararray):
+        s = s.replace(a, b)
+    return s
+
+
+def escape_texchars(string):
+    r"""Escape the special LaTeX-chars %{}_^
+
+    Examples:
+
+    >>> escape_texchars('10%')
+    '10\\%'
+    >>> escape_texchars('%{}_^\\$')
+    '\\%\\{\\}\\_\\^{}$\\backslash$\\$'
+    """
+    return "".join([charmap.get(c, c) for c in string])
+
+
+def tikzify(s):
+    if s.strip():
+        return mreplace(s, r'\,:.()', '-+_*{}')
+    else:
+        return "d2tnn%i" % (len(s) + 1)
+
+
+def nsplit(seq, n=2):
+    """Split a sequence into pieces of length n
+
+    If the length of the sequence isn't a multiple of n, the rest is discarded.
+    Note that nsplit will strings into individual characters.
+
+    Examples:
+    >>> nsplit('aabbcc')
+    [('a', 'a'), ('b', 'b'), ('c', 'c')]
+    >>> nsplit('aabbcc',n=3)
+    [('a', 'a', 'b'), ('b', 'c', 'c')]
+
+    # Note that cc is discarded
+    >>> nsplit('aabbcc',n=4)
+    [('a', 'a', 'b', 'b')]
+    """
+    return [xy for xy in zip(*[iter(seq)] * n)]
+
+
+def chunks(s, cl):
+    """Split a string or sequence into pieces of length cl and return an iterator"""
+    for i in range(0, len(s), cl):
+        yield s[i:i + cl]
+
+
+def replace_tags(template, tags, tagsreplace):
+    """Replace occurrences of tags with tagsreplace
+
+    Example:
+    >>> replace_tags('a b c d',('b','d'),{'b':'bbb','d':'ddd'})
+    'a bbb c ddd'
+    """
+    s = template
+    for tag in tags:
+        replacestr = tagsreplace.get(tag, '')
+        if not replacestr:
+            replacestr = ''
+        s = s.replace(tag, replacestr)
+    return s
+
+
+def getboolattr(item, key, default):
+    if str(getattr(item, key, '')).lower() == 'true':
+        return True
+    else:
+        return False
+
+
+def smart_float(number):
+    if type(number) is str: # handle newlines
+        number = number.strip('\\\r\n')
+    number_as_string = "%s" % float(number)
+    if 'e' in number_as_string:
+        return "%.4f" % float(number)
+    else:
+        return number_as_string
+
+
+def is_multiline_label(drawobject):
+    # https://graphviz.gitlab.io/_pages/doc/info/attrs.html#k:escString
+    if getattr(drawobject, "texlbl", None):
+        return False
+
+    label = getattr(drawobject, "label", "")
+    return any(x in label for x in [r"\n", r"\l", r"\r"])
+
+
+class EndOfGraphElement(object):
+    def __init__(self):
+        pass
+
+
+def get_all_graph_elements(graph, l=None):
+    """Return all nodes and edges, including elements in subgraphs"""
+    if not l:
+        l = []
+        outer = True
+        l.append(graph)
+    else:
+        outer = False
+    for element in graph.allitems:
+        if isinstance(element, dotparsing.DotSubGraph):
+            l.append(element)
+            get_all_graph_elements(element, l)
+        else:
+            l.append(element)
+
+    if outer:
+        return l
+    else:
+        l.append(EndOfGraphElement())
\ No newline at end of file
diff --git a/examples/balls.dot b/examples/balls.dot
index f133045..d69b2f6 100644
--- a/examples/balls.dot
+++ b/examples/balls.dot
@@ -1,24 +1,24 @@
-/*
-
-:Title: Snaked edges
-:Tags: PGF
-
-This graph uses special `PGF/TikZ`_ styles to create some interesting
-visual effects. To get the snaked edges run dot2tex with the ``-s`` option
-to force straight edges. 
-
-Generated with::
-
-    $ dot2tex -s --prog fdp balls.dot > balls.tex
-
-.. _PGF/TikZ: http://www.ctan.org/tex-archive/help/Catalogue/entries/pgf.html    
-*/
-graph G {
-	node [shape=circle, fixedsize=True, width="0.2", style="ball color = green", label=""];
-	edge [style="snake=zigzag, green"];
-	a_1 -- c -- a_2;
-	c [style="ball color=black"];
-	edge [style="snake=snake, blue", color=red];
-	node [style="ball color = red", label=""];
-	a_3 -- c -- a_4 --a_3;
+/*
+
+:Title: Snaked edges
+:Tags: PGF
+
+This graph uses special `PGF/TikZ`_ styles to create some interesting
+visual effects. To get the snaked edges run dot2tex with the ``-s`` option
+to force straight edges. 
+
+Generated with::
+
+    $ dot2tex -s --prog fdp balls.dot > balls.tex
+
+.. _PGF/TikZ: http://www.ctan.org/tex-archive/help/Catalogue/entries/pgf.html    
+*/
+graph G {
+	node [shape=circle, fixedsize=True, width="0.2", style="ball color = green", label=""];
+	edge [style="snake=zigzag, green"];
+	a_1 -- c -- a_2;
+	c [style="ball color=black"];
+	edge [style="snake=snake, blue", color=red];
+	node [style="ball color = red", label=""];
+	a_3 -- c -- a_4 --a_3;
 }
\ No newline at end of file
diff --git a/examples/distances.dot b/examples/distances.dot
index 5daebb9..cd204df 100644
--- a/examples/distances.dot
+++ b/examples/distances.dot
@@ -1,25 +1,25 @@
-/* 
-:Title: Distances
-:Tags: TikZ, tikzedgelabels
-
-Generated with::
-
-	$ circo -Txdot distances.dot | dot2tex --crop --tikzedgelabels -ftikz -tmath -s > distances.tex
-
-*/
-graph G {
-	node [shape=circle,fixedsize = true,width=0.1,style="fill=blue!20"];
-	edge [lblstyle="fill=black!10,inner sep=1pt,sloped"];
-	K -- F [label="120"];
-	H -- S [label="650"];
-	H -- M [label="780"];
-	D -- B [label="490"];
-	D -- M [label="600"];
-	B -- M [label="580"];
-	H -- N [label="600"];
-	F -- H [label="490"];
-	S -- B [label="630"];
-	S -- N [label="210"];
-	S -- M [label="230"];
-	F --M [label="100"];  
+/* 
+:Title: Distances
+:Tags: TikZ, tikzedgelabels
+
+Generated with::
+
+	$ circo -Txdot distances.dot | dot2tex --crop --tikzedgelabels -ftikz -tmath -s > distances.tex
+
+*/
+graph G {
+	node [shape=circle,fixedsize = true,width=0.1,style="fill=blue!20"];
+	edge [lblstyle="fill=black!10,inner sep=1pt,sloped"];
+	K -- F [label="120"];
+	H -- S [label="650"];
+	H -- M [label="780"];
+	D -- B [label="490"];
+	D -- M [label="600"];
+	B -- M [label="580"];
+	H -- N [label="600"];
+	F -- H [label="490"];
+	S -- B [label="630"];
+	S -- N [label="210"];
+	S -- M [label="230"];
+	F --M [label="100"];  
 }
\ No newline at end of file
diff --git a/examples/dotarrows.dot b/examples/dotarrows.dot
index 14f5a15..d3a1269 100644
--- a/examples/dotarrows.dot
+++ b/examples/dotarrows.dot
@@ -1,39 +1,39 @@
-/*
-
-:Title: Graphviz arrows
-:Tags: PGF
-
-Shows how Graphviz arrows are mapped to PGF/TikZ arrows
-
-Generated with::
-
-    $ dot2tex --prog=circo -s -ftikz dotarrows.dot > dotarrows.tex
-
-*/
-digraph G {
-	graph [mindist=0.5];
-	node [texmode="math", shape=circle, style="circle, fill=green!20"];
-	edge [lblstyle="above,sloped"];
-	d2ttikzedgelabels=true;
-	c -> n_1 [arrowhead="normal", label="normal"];
-	c -> n_2 [arrowhead="inv", label="inv"];
-	c -> n_3 [arrowhead="dot", label="dot"];
-	c -> n_4 [arrowhead="invdot", label="invdot"];
-	c -> n_5 [arrowhead="odot", label="odot"];
-	c -> n_6 [arrowhead="invodot", label="invodot"];
-	c -> n_7 [arrowhead="none", label="none"];
-	c -> n_8 [arrowhead="tee", label="tee"];
-	c -> n_9 [arrowhead="empty", label="empty"];
-	c -> "n_{10}" [arrowhead="invempty", label="invempty"];
-	c -> "n_{11}" [arrowhead="diamond", label="diamond"];
-	c -> "n_{12}" [arrowhead="odiamond", label="odiamond"];
-	c -> "n_{13}" [arrowhead="ediamond", label="ediamond"];
-	c -> "n_{14}" [arrowhead="crow", label="crow"];
-	c -> "n_{15}" [arrowhead="box", label="box"];
-	c -> "n_{16}" [arrowhead="obox", label="obox"];
-	c -> "n_{17}" [arrowhead="open", label="open"];
-	c -> "n_{18}" [arrowhead="halfopen", label="halfopen"];
-	c -> "n_{19}" [arrowhead="vee", label="vee"];
-	c -> "n_{20}" [arrowhead="circle", label="circle"];
-	c [style="fill=red!80"];
+/*
+
+:Title: Graphviz arrows
+:Tags: PGF
+
+Shows how Graphviz arrows are mapped to PGF/TikZ arrows
+
+Generated with::
+
+    $ dot2tex --prog=circo -s -ftikz dotarrows.dot > dotarrows.tex
+
+*/
+digraph G {
+	graph [mindist=0.5];
+	node [texmode="math", shape=circle, style="circle, fill=green!20"];
+	edge [lblstyle="above,sloped"];
+	d2ttikzedgelabels=true;
+	c -> n_1 [arrowhead="normal", label="normal"];
+	c -> n_2 [arrowhead="inv", label="inv"];
+	c -> n_3 [arrowhead="dot", label="dot"];
+	c -> n_4 [arrowhead="invdot", label="invdot"];
+	c -> n_5 [arrowhead="odot", label="odot"];
+	c -> n_6 [arrowhead="invodot", label="invodot"];
+	c -> n_7 [arrowhead="none", label="none"];
+	c -> n_8 [arrowhead="tee", label="tee"];
+	c -> n_9 [arrowhead="empty", label="empty"];
+	c -> "n_{10}" [arrowhead="invempty", label="invempty"];
+	c -> "n_{11}" [arrowhead="diamond", label="diamond"];
+	c -> "n_{12}" [arrowhead="odiamond", label="odiamond"];
+	c -> "n_{13}" [arrowhead="ediamond", label="ediamond"];
+	c -> "n_{14}" [arrowhead="crow", label="crow"];
+	c -> "n_{15}" [arrowhead="box", label="box"];
+	c -> "n_{16}" [arrowhead="obox", label="obox"];
+	c -> "n_{17}" [arrowhead="open", label="open"];
+	c -> "n_{18}" [arrowhead="halfopen", label="halfopen"];
+	c -> "n_{19}" [arrowhead="vee", label="vee"];
+	c -> "n_{20}" [arrowhead="circle", label="circle"];
+	c [style="fill=red!80"];
 }
\ No newline at end of file
diff --git a/examples/dropshadows.dot b/examples/dropshadows.dot
index ef20b3b..da60665 100644
--- a/examples/dropshadows.dot
+++ b/examples/dropshadows.dot
@@ -1,28 +1,28 @@
-/*
-
-:Title: Node drop shadows
-:Tags: TikZ
-
-
-The ``tikz`` output format is highly customizable thanks to TikZ' powerful
-style options. In this example drop shadows have been added to all the nodes.
-
-**Note**: This example requires PGF 2.00 or later. Download the PDF to fully see
-the drop shadow effect. The bitmap rendering does not render transparency well. 
-
-
-Generated with::
-
- $ dot2tex -ftikz --prog neato -s --crop dropshadows.dot > dropshadows.tex
- 
-
-*/
-graph G {
-    d2tdocpreamble = "\usetikzlibrary{shadows}";
-    node [shape=circle,style="fill=red!20,circular drop shadow"];
-    "Node A" -- {"Node B"; "Node C"};
-    "Node B" -- {"Node E"; "Node G"};
-    "Node C" -- "Node D";
-    "Node D" -- {"Node F"; "Node H"};
-    "Node E" -- {"Node F"; "Node H"; "Node G"};
-}
+/*
+
+:Title: Node drop shadows
+:Tags: TikZ
+
+
+The ``tikz`` output format is highly customizable thanks to TikZ' powerful
+style options. In this example drop shadows have been added to all the nodes.
+
+**Note**: This example requires PGF 2.00 or later. Download the PDF to fully see
+the drop shadow effect. The bitmap rendering does not render transparency well. 
+
+
+Generated with::
+
+ $ dot2tex -ftikz --prog neato -s --crop dropshadows.dot > dropshadows.tex
+ 
+
+*/
+graph G {
+    d2tdocpreamble = "\usetikzlibrary{shadows}";
+    node [shape=circle,style="fill=red!20,circular drop shadow"];
+    "Node A" -- {"Node B"; "Node C"};
+    "Node B" -- {"Node E"; "Node G"};
+    "Node C" -- "Node D";
+    "Node D" -- {"Node F"; "Node H"};
+    "Node E" -- {"Node F"; "Node H"; "Node G"};
+}
diff --git a/examples/ex1.dot b/examples/ex1.dot
index c4f93f2..67ccc2d 100644
--- a/examples/ex1.dot
+++ b/examples/ex1.dot
@@ -1,15 +1,15 @@
-/*
-:Title: Basic example
-:Tags: PGF
-
-A basic example.
-
-Generated with::
-
-    $ dot2tex --preproc -tmath ex1.dot | dot2tex > ex1.tex
-    
-*/
-
-digraph G {
-	a_1-> a_2 -> a_3 -> a_1;
+/*
+:Title: Basic example
+:Tags: PGF
+
+A basic example.
+
+Generated with::
+
+    $ dot2tex --preproc -tmath ex1.dot | dot2tex > ex1.tex
+    
+*/
+
+digraph G {
+	a_1-> a_2 -> a_3 -> a_1;
 }
\ No newline at end of file
diff --git a/examples/graphofgraphs.dot b/examples/graphofgraphs.dot
index a4baf9e..e36fe4b 100644
--- a/examples/graphofgraphs.dot
+++ b/examples/graphofgraphs.dot
@@ -1,26 +1,26 @@
-/*
-
-:Title: Graph of graphs
-:Tags: PGF
-
-This example shows that node content is not limited to text and math. 
-You can for instance insert graphics and create this weird graph of graphs.
-Download the PDF and zoom in to see the details. 
-
-Generated with::
-
-    $ neato -Txdot graphofgraphs.dot | dot2tex --crop -fpgf > graphofgraphs.tex
-    
-*/
-digraph G {
-	graph [mindist=0.5];
-	node [shape=plaintext, height=0.5];
-	edge [style="black!50, thin,-to"];
-	a_1 [texlbl="\raisebox{-.4\height}{\includegraphics[height=30bp]{balls.pdf}}"];
-	a_2 [texlbl="\raisebox{-.4\height}{\includegraphics[height=30bp]{pgfsnakes.pdf}}"];
-	a_3 [texlbl="\raisebox{-.4\height}{\includegraphics[height=30bp]{pgfarrows.pdf}}"];
-	a_4 [texlbl="\raisebox{-.4\height}{\includegraphics[height=30bp]{poltab.pdf}}"];
-	a_5 [texlbl="\raisebox{-.4\height}{\includegraphics[height=30bp]{subgraphs.pdf}}"];
-	a_1-> a_2 -> a_3 -> a_4 -> a_5 -> a_1;
-	a_2 -> a_5;
+/*
+
+:Title: Graph of graphs
+:Tags: PGF
+
+This example shows that node content is not limited to text and math. 
+You can for instance insert graphics and create this weird graph of graphs.
+Download the PDF and zoom in to see the details. 
+
+Generated with::
+
+    $ neato -Txdot graphofgraphs.dot | dot2tex --crop -fpgf > graphofgraphs.tex
+    
+*/
+digraph G {
+	graph [mindist=0.5];
+	node [shape=plaintext, height=0.5];
+	edge [style="black!50, thin,-to"];
+	a_1 [texlbl="\raisebox{-.4\height}{\includegraphics[height=30bp]{balls.pdf}}"];
+	a_2 [texlbl="\raisebox{-.4\height}{\includegraphics[height=30bp]{pgfsnakes.pdf}}"];
+	a_3 [texlbl="\raisebox{-.4\height}{\includegraphics[height=30bp]{pgfarrows.pdf}}"];
+	a_4 [texlbl="\raisebox{-.4\height}{\includegraphics[height=30bp]{poltab.pdf}}"];
+	a_5 [texlbl="\raisebox{-.4\height}{\includegraphics[height=30bp]{subgraphs.pdf}}"];
+	a_1-> a_2 -> a_3 -> a_4 -> a_5 -> a_1;
+	a_2 -> a_5;
 }
\ No newline at end of file
diff --git a/examples/gvcols.tex b/examples/gvcols.tex
index 2b2eb50..395cc99 100644
--- a/examples/gvcols.tex
+++ b/examples/gvcols.tex
@@ -1,655 +1,655 @@
-\def\rangeHSB{255}
-\preparecolorset{HSB}{}{}{%
-aliceblue,147,15,255;%
-antiquewhite,24,35,250;%
-antiquewhite1,23,36,255;%
-antiquewhite2,23,36,238;%
-antiquewhite3,23,36,205;%
-antiquewhite4,24,34,139;%
-aquamarine,113,128,255;%
-aquamarine1,113,128,255;%
-aquamarine2,113,128,238;%
-aquamarine3,113,128,205;%
-aquamarine4,113,128,139;%
-azure,127,15,255;%
-azure1,127,15,255;%
-azure2,127,15,238;%
-azure3,127,14,205;%
-azure4,127,14,139;%
-beige,42,26,245;%
-bisque,23,58,255;%
-bisque1,23,58,255;%
-bisque2,23,58,238;%
-bisque3,22,58,205;%
-bisque4,23,58,139;%
-black,0,0,0;%
-blanchedalmond,25,49,255;%
-blue,170,255,255;%
-blue1,170,255,255;%
-blue2,170,255,238;%
-blue3,170,255,205;%
-blue4,170,255,139;%
-blueviolet,192,206,226;%
-brown,0,190,165;%
-brown1,0,191,255;%
-brown2,0,191,238;%
-brown3,0,191,205;%
-brown4,0,190,139;%
-burlywood,23,99,222;%
-burlywood1,23,100,255;%
-burlywood2,23,99,238;%
-burlywood3,23,99,205;%
-burlywood4,23,99,139;%
-cadetblue,128,103,160;%
-cadetblue1,131,103,255;%
-cadetblue2,131,102,238;%
-cadetblue3,131,103,205;%
-cadetblue4,131,102,139;%
-chartreuse,63,255,255;%
-chartreuse1,63,255,255;%
-chartreuse2,63,255,238;%
-chartreuse3,63,255,205;%
-chartreuse4,63,255,139;%
-chocolate,17,218,210;%
-chocolate1,17,219,255;%
-chocolate2,17,219,238;%
-chocolate3,17,218,205;%
-chocolate4,17,220,139;%
-coral,11,175,255;%
-coral1,7,169,255;%
-coral2,6,169,238;%
-coral3,6,169,205;%
-coral4,6,168,139;%
-cornflowerblue,154,147,237;%
-cornsilk,33,34,255;%
-cornsilk1,33,34,255;%
-cornsilk2,34,35,238;%
-cornsilk3,34,34,205;%
-cornsilk4,35,34,139;%
-crimson,246,231,220;%
-cyan,127,255,255;%
-cyan1,127,255,255;%
-cyan2,127,255,238;%
-cyan3,127,255,205;%
-cyan4,127,255,139;%
-darkgoldenrod,30,239,184;%
-darkgoldenrod1,30,240,255;%
-darkgoldenrod2,30,240,238;%
-darkgoldenrod3,30,240,205;%
-darkgoldenrod4,30,240,139;%
-darkgreen,85,255,100;%
-darkkhaki,39,110,189;%
-darkolivegreen,58,142,107;%
-darkolivegreen1,58,143,255;%
-darkolivegreen2,58,143,238;%
-darkolivegreen3,58,143,205;%
-darkolivegreen4,58,143,139;%
-darkorange,23,255,255;%
-darkorange1,21,255,255;%
-darkorange2,21,255,238;%
-darkorange3,21,255,205;%
-darkorange4,21,255,139;%
-darkorchid,198,192,204;%
-darkorchid1,198,193,255;%
-darkorchid2,198,192,238;%
-darkorchid3,198,192,205;%
-darkorchid4,198,192,139;%
-darksalmon,10,121,233;%
-darkseagreen,85,61,188;%
-darkseagreen1,85,62,255;%
-darkseagreen2,85,62,238;%
-darkseagreen3,85,62,205;%
-darkseagreen4,85,62,139;%
-darkslateblue,175,143,139;%
-darkslategray,127,103,79;%
-darkslategray1,127,104,255;%
-darkslategray2,127,103,238;%
-darkslategray3,127,104,205;%
-darkslategray4,127,104,139;%
-darkslategrey,127,103,79;%
-darkturquoise,128,255,209;%
-darkviolet,199,255,211;%
-deeppink,232,235,255;%
-deeppink1,232,235,255;%
-deeppink2,232,235,238;%
-deeppink3,232,235,205;%
-deeppink4,231,236,139;%
-deepskyblue,138,255,255;%
-deepskyblue1,138,255,255;%
-deepskyblue2,138,255,238;%
-deepskyblue3,138,255,205;%
-deepskyblue4,138,255,139;%
-dimgray,0,0,105;%
-dimgrey,0,0,105;%
-dodgerblue,148,225,255;%
-dodgerblue1,148,225,255;%
-dodgerblue2,148,225,238;%
-dodgerblue3,148,225,205;%
-dodgerblue4,148,225,139;%
-firebrick,0,206,178;%
-firebrick1,0,207,255;%
-firebrick2,0,207,238;%
-firebrick3,0,207,205;%
-firebrick4,0,207,139;%
-floralwhite,28,15,255;%
-forestgreen,85,192,139;%
-gainsboro,0,0,220;%
-ghostwhite,170,7,255;%
-gold,35,255,255;%
-gold1,35,255,255;%
-gold2,35,255,238;%
-gold3,35,255,205;%
-gold4,35,255,139;%
-goldenrod,30,217,218;%
-goldenrod1,30,218,255;%
-goldenrod2,30,218,238;%
-goldenrod3,30,218,205;%
-goldenrod4,30,218,139;%
-gray,0,0,192;%
-gray0,0,0,0;%
-gray1,0,0,3;%
-gray10,0,0,26;%
-gray100,0,0,255;%
-gray11,0,0,28;%
-gray12,0,0,31;%
-gray13,0,0,33;%
-gray14,0,0,36;%
-gray15,0,0,38;%
-gray16,0,0,41;%
-gray17,0,0,43;%
-gray18,0,0,46;%
-gray19,0,0,48;%
-gray2,0,0,5;%
-gray20,0,0,51;%
-gray21,0,0,54;%
-gray22,0,0,56;%
-gray23,0,0,59;%
-gray24,0,0,61;%
-gray25,0,0,64;%
-gray26,0,0,66;%
-gray27,0,0,69;%
-gray28,0,0,71;%
-gray29,0,0,74;%
-gray3,0,0,8;%
-gray30,0,0,77;%
-gray31,0,0,79;%
-gray32,0,0,82;%
-gray33,0,0,84;%
-gray34,0,0,87;%
-gray35,0,0,89;%
-gray36,0,0,92;%
-gray37,0,0,94;%
-gray38,0,0,97;%
-gray39,0,0,99;%
-gray4,0,0,10;%
-gray40,0,0,102;%
-gray41,0,0,105;%
-gray42,0,0,107;%
-gray43,0,0,110;%
-gray44,0,0,112;%
-gray45,0,0,115;%
-gray46,0,0,117;%
-gray47,0,0,120;%
-gray48,0,0,122;%
-gray49,0,0,125;%
-gray5,0,0,13;%
-gray50,0,0,127;%
-gray51,0,0,130;%
-gray52,0,0,133;%
-gray53,0,0,135;%
-gray54,0,0,138;%
-gray55,0,0,140;%
-gray56,0,0,143;%
-gray57,0,0,145;%
-gray58,0,0,148;%
-gray59,0,0,150;%
-gray6,0,0,15;%
-gray60,0,0,153;%
-gray61,0,0,156;%
-gray62,0,0,158;%
-gray63,0,0,161;%
-gray64,0,0,163;%
-gray65,0,0,166;%
-gray66,0,0,168;%
-gray67,0,0,171;%
-gray68,0,0,173;%
-gray69,0,0,176;%
-gray7,0,0,18;%
-gray70,0,0,179;%
-gray71,0,0,181;%
-gray72,0,0,184;%
-gray73,0,0,186;%
-gray74,0,0,189;%
-gray75,0,0,191;%
-gray76,0,0,194;%
-gray77,0,0,196;%
-gray78,0,0,199;%
-gray79,0,0,201;%
-gray8,0,0,20;%
-gray80,0,0,204;%
-gray81,0,0,207;%
-gray82,0,0,209;%
-gray83,0,0,212;%
-gray84,0,0,214;%
-gray85,0,0,217;%
-gray86,0,0,219;%
-gray87,0,0,222;%
-gray88,0,0,224;%
-gray89,0,0,227;%
-gray9,0,0,23;%
-gray90,0,0,229;%
-gray91,0,0,232;%
-gray92,0,0,235;%
-gray93,0,0,237;%
-gray94,0,0,240;%
-gray95,0,0,242;%
-gray96,0,0,245;%
-gray97,0,0,247;%
-gray98,0,0,250;%
-gray99,0,0,252;%
-green,85,255,255;%
-green1,85,255,255;%
-green2,85,255,238;%
-green3,85,255,205;%
-green4,85,255,139;%
-greenyellow,59,208,255;%
-grey,0,0,192;%
-grey0,0,0,0;%
-grey1,0,0,3;%
-grey10,0,0,26;%
-grey100,0,0,255;%
-grey11,0,0,28;%
-grey12,0,0,31;%
-grey13,0,0,33;%
-grey14,0,0,36;%
-grey15,0,0,38;%
-grey16,0,0,41;%
-grey17,0,0,43;%
-grey18,0,0,46;%
-grey19,0,0,48;%
-grey2,0,0,5;%
-grey20,0,0,51;%
-grey21,0,0,54;%
-grey22,0,0,56;%
-grey23,0,0,59;%
-grey24,0,0,61;%
-grey25,0,0,64;%
-grey26,0,0,66;%
-grey27,0,0,69;%
-grey28,0,0,71;%
-grey29,0,0,74;%
-grey3,0,0,8;%
-grey30,0,0,77;%
-grey31,0,0,79;%
-grey32,0,0,82;%
-grey33,0,0,84;%
-grey34,0,0,87;%
-grey35,0,0,89;%
-grey36,0,0,92;%
-grey37,0,0,94;%
-grey38,0,0,97;%
-grey39,0,0,99;%
-grey4,0,0,10;%
-grey40,0,0,102;%
-grey41,0,0,105;%
-grey42,0,0,107;%
-grey43,0,0,110;%
-grey44,0,0,112;%
-grey45,0,0,115;%
-grey46,0,0,117;%
-grey47,0,0,120;%
-grey48,0,0,122;%
-grey49,0,0,125;%
-grey5,0,0,13;%
-grey50,0,0,127;%
-grey51,0,0,130;%
-grey52,0,0,133;%
-grey53,0,0,135;%
-grey54,0,0,138;%
-grey55,0,0,140;%
-grey56,0,0,143;%
-grey57,0,0,145;%
-grey58,0,0,148;%
-grey59,0,0,150;%
-grey6,0,0,15;%
-grey60,0,0,153;%
-grey61,0,0,156;%
-grey62,0,0,158;%
-grey63,0,0,161;%
-grey64,0,0,163;%
-grey65,0,0,166;%
-grey66,0,0,168;%
-grey67,0,0,171;%
-grey68,0,0,173;%
-grey69,0,0,176;%
-grey7,0,0,18;%
-grey70,0,0,179;%
-grey71,0,0,181;%
-grey72,0,0,184;%
-grey73,0,0,186;%
-grey74,0,0,189;%
-grey75,0,0,191;%
-grey76,0,0,194;%
-grey77,0,0,196;%
-grey78,0,0,199;%
-grey79,0,0,201;%
-grey8,0,0,20;%
-grey80,0,0,204;%
-grey81,0,0,207;%
-grey82,0,0,209;%
-grey83,0,0,212;%
-grey84,0,0,214;%
-grey85,0,0,217;%
-grey86,0,0,219;%
-grey87,0,0,222;%
-grey88,0,0,224;%
-grey89,0,0,227;%
-grey9,0,0,23;%
-grey90,0,0,229;%
-grey91,0,0,232;%
-grey92,0,0,235;%
-grey93,0,0,237;%
-grey94,0,0,240;%
-grey95,0,0,242;%
-grey96,0,0,245;%
-grey97,0,0,247;%
-grey98,0,0,250;%
-grey99,0,0,252;%
-honeydew,85,15,255;%
-honeydew1,85,15,255;%
-honeydew2,85,15,238;%
-honeydew3,85,14,205;%
-honeydew4,85,14,139;%
-hotpink,233,150,255;%
-hotpink1,234,145,255;%
-hotpink2,235,141,238;%
-hotpink3,236,135,205;%
-hotpink4,234,148,139;%
-indianred,0,140,205;%
-indianred1,0,148,255;%
-indianred2,0,148,238;%
-indianred3,0,149,205;%
-indianred4,0,148,139;%
-indigo,194,255,130;%
-ivory,42,15,255;%
-ivory1,42,15,255;%
-ivory2,42,15,238;%
-ivory3,42,14,205;%
-ivory4,42,14,139;%
-khaki,38,106,240;%
-khaki1,39,112,255;%
-khaki2,39,112,238;%
-khaki3,39,111,205;%
-khaki4,39,111,139;%
-lavender,170,20,250;%
-lavenderblush,240,15,255;%
-lavenderblush1,240,15,255;%
-lavenderblush2,239,15,238;%
-lavenderblush3,240,14,205;%
-lavenderblush4,239,14,139;%
-lawngreen,64,255,252;%
-lemonchiffon,38,49,255;%
-lemonchiffon1,38,49,255;%
-lemonchiffon2,37,50,238;%
-lemonchiffon3,38,49,205;%
-lemonchiffon4,39,49,139;%
-lightblue,137,63,230;%
-lightblue1,138,64,255;%
-lightblue2,138,64,238;%
-lightblue3,138,63,205;%
-lightblue4,137,64,139;%
-lightcoral,0,119,240;%
-lightcyan,127,31,255;%
-lightcyan1,127,31,255;%
-lightcyan2,127,31,238;%
-lightcyan3,127,31,205;%
-lightcyan4,127,31,139;%
-lightgoldenrod,35,115,238;%
-lightgoldenrod1,35,116,255;%
-lightgoldenrod2,35,115,238;%
-lightgoldenrod3,35,115,205;%
-lightgoldenrod4,35,115,139;%
-lightgoldenrodyellow,42,40,250;%
-lightgray,0,0,211;%
-lightgrey,0,0,211;%
-lightpink,248,73,255;%
-lightpink1,249,81,255;%
-lightpink2,248,81,238;%
-lightpink3,249,80,205;%
-lightpink4,249,80,139;%
-lightsalmon,12,132,255;%
-lightsalmon1,12,132,255;%
-lightsalmon2,11,132,238;%
-lightsalmon3,12,133,205;%
-lightsalmon4,12,133,139;%
-lightseagreen,125,209,178;%
-lightskyblue,143,117,250;%
-lightskyblue1,143,79,255;%
-lightskyblue2,143,79,238;%
-lightskyblue3,142,79,205;%
-lightskyblue4,143,78,139;%
-lightslateblue,175,143,255;%
-lightslategray,148,56,153;%
-lightslategrey,148,56,153;%
-lightsteelblue,151,52,222;%
-lightsteelblue1,151,53,255;%
-lightsteelblue2,151,53,238;%
-lightsteelblue3,151,53,205;%
-lightsteelblue4,150,53,139;%
-lightyellow,42,31,255;%
-lightyellow1,42,31,255;%
-lightyellow2,42,31,238;%
-lightyellow3,42,31,205;%
-lightyellow4,42,31,139;%
-limegreen,85,192,205;%
-linen,21,20,250;%
-magenta,212,255,255;%
-magenta1,212,255,255;%
-magenta2,212,255,238;%
-magenta3,212,255,205;%
-magenta4,212,255,139;%
-maroon,239,185,176;%
-maroon1,228,203,255;%
-maroon2,228,203,238;%
-maroon3,228,204,205;%
-maroon4,228,203,139;%
-mediumaquamarine,113,128,205;%
-mediumblue,170,255,205;%
-mediumorchid,204,152,211;%
-mediumorchid1,203,153,255;%
-mediumorchid2,203,153,238;%
-mediumorchid3,203,153,205;%
-mediumorchid4,203,154,139;%
-mediumpurple,183,124,219;%
-mediumpurple1,183,125,255;%
-mediumpurple2,183,125,238;%
-mediumpurple3,183,125,205;%
-mediumpurple4,183,124,139;%
-mediumseagreen,103,169,179;%
-mediumslateblue,176,143,238;%
-mediumspringgreen,111,255,250;%
-mediumturquoise,125,167,209;%
-mediumvioletred,228,228,199;%
-midnightblue,170,198,112;%
-mintcream,106,9,255;%
-mistyrose,4,30,255;%
-mistyrose1,4,30,255;%
-mistyrose2,4,30,238;%
-mistyrose3,3,29,205;%
-mistyrose4,5,29,139;%
-moccasin,26,73,255;%
-navajowhite,25,81,255;%
-navajowhite1,25,81,255;%
-navajowhite2,25,82,238;%
-navajowhite3,25,82,205;%
-navajowhite4,25,82,139;%
-navy,170,255,128;%
-navyblue,170,255,128;%
-oldlace,27,23,253;%
-olivedrab,56,192,142;%
-olivedrab1,56,193,255;%
-olivedrab2,56,192,238;%
-olivedrab3,56,192,205;%
-olivedrab4,56,192,139;%
-orange,27,255,255;%
-orange1,27,255,255;%
-orange2,27,255,238;%
-orange3,27,255,205;%
-orange4,27,255,139;%
-orangered,11,255,255;%
-orangered1,11,255,255;%
-orangered2,11,255,238;%
-orangered3,11,255,205;%
-orangered4,11,255,139;%
-orchid,214,123,218;%
-orchid1,214,124,255;%
-orchid2,214,124,238;%
-orchid3,214,124,205;%
-orchid4,213,124,139;%
-palegoldenrod,38,72,238;%
-palegreen,85,100,251;%
-palegreen1,85,101,255;%
-palegreen2,85,100,238;%
-palegreen3,85,100,205;%
-palegreen4,85,100,139;%
-paleturquoise,127,67,238;%
-paleturquoise1,127,68,255;%
-paleturquoise2,127,68,238;%
-paleturquoise3,127,68,205;%
-paleturquoise4,127,67,139;%
-palevioletred,241,124,219;%
-palevioletred1,241,125,255;%
-palevioletred2,241,125,238;%
-palevioletred3,241,125,205;%
-palevioletred4,241,124,139;%
-papayawhip,26,41,255;%
-peachpuff,20,70,255;%
-peachpuff1,20,70,255;%
-peachpuff2,19,69,238;%
-peachpuff3,19,69,205;%
-peachpuff4,20,69,139;%
-peru,20,176,205;%
-pink,247,63,255;%
-pink1,245,73,255;%
-pink2,245,73,238;%
-pink3,245,74,205;%
-pink4,245,73,139;%
-plum,212,70,221;%
-plum1,212,68,255;%
-plum2,212,68,238;%
-plum3,212,68,205;%
-plum4,212,67,139;%
-powderblue,132,59,230;%
-purple,196,221,240;%
-purple1,191,207,255;%
-purple2,192,207,238;%
-purple3,192,207,205;%
-purple4,192,207,139;%
-red,0,255,255;%
-red1,0,255,255;%
-red2,0,255,238;%
-red3,0,255,205;%
-red4,0,255,139;%
-rosybrown,0,61,188;%
-rosybrown1,0,62,255;%
-rosybrown2,0,62,238;%
-rosybrown3,0,62,205;%
-rosybrown4,0,62,139;%
-royalblue,159,181,225;%
-royalblue1,159,183,255;%
-royalblue2,159,183,238;%
-royalblue3,159,182,205;%
-royalblue4,159,183,139;%
-saddlebrown,17,220,139;%
-salmon,4,138,250;%
-salmon1,9,150,255;%
-salmon2,9,150,238;%
-salmon3,9,150,205;%
-salmon4,9,150,139;%
-sandybrown,19,154,244;%
-seagreen,103,170,139;%
-seagreen1,103,171,255;%
-seagreen2,103,171,238;%
-seagreen3,103,171,205;%
-seagreen4,103,170,139;%
-seashell,17,16,255;%
-seashell1,17,16,255;%
-seashell2,18,17,238;%
-seashell3,18,17,205;%
-seashell4,18,16,139;%
-sienna,13,183,160;%
-sienna1,13,184,255;%
-sienna2,13,184,238;%
-sienna3,13,184,205;%
-sienna4,13,185,139;%
-skyblue,139,108,235;%
-skyblue1,144,120,255;%
-skyblue2,144,120,238;%
-skyblue3,144,120,205;%
-skyblue4,145,119,139;%
-slateblue,175,143,205;%
-slateblue1,175,144,255;%
-slateblue2,175,144,238;%
-slateblue3,175,144,205;%
-slateblue4,175,144,139;%
-slategray,148,56,144;%
-slategray1,149,56,255;%
-slategray2,149,56,238;%
-slategray3,148,57,205;%
-slategray4,149,56,139;%
-slategrey,148,56,144;%
-snow,0,5,255;%
-snow1,0,5,255;%
-snow2,0,5,238;%
-snow3,0,4,205;%
-snow4,0,3,139;%
-springgreen,106,255,255;%
-springgreen1,106,255,255;%
-springgreen2,106,255,238;%
-springgreen3,106,255,205;%
-springgreen4,106,255,139;%
-steelblue,146,155,180;%
-steelblue1,146,156,255;%
-steelblue2,146,156,238;%
-steelblue3,146,156,205;%
-steelblue4,147,155,139;%
-tan,24,84,210;%
-tan1,20,176,255;%
-tan2,20,176,238;%
-tan3,20,176,205;%
-tan4,20,176,139;%
-thistle,212,29,216;%
-thistle1,212,30,255;%
-thistle2,212,30,238;%
-thistle3,212,29,205;%
-thistle4,212,29,139;%
-tomato,6,184,255;%
-tomato1,6,184,255;%
-tomato2,6,184,238;%
-tomato3,6,184,205;%
-tomato4,6,185,139;%
-transparent,42,0,255;%
-turquoise,123,182,224;%
-turquoise1,129,255,255;%
-turquoise2,129,255,238;%
-turquoise3,129,255,205;%
-turquoise4,129,255,139;%
-violet,212,115,238;%
-violetred,227,215,208;%
-violetred1,235,193,255;%
-violetred2,235,192,238;%
-violetred3,235,192,205;%
-violetred4,235,192,139;%
-wheat,27,68,245;%
-wheat1,27,69,255;%
-wheat2,27,68,238;%
-wheat3,27,68,205;%
-wheat4,27,67,139;%
-white,0,0,255;%
-whitesmoke,0,0,245;%
-yellow,42,255,255;%
-yellow1,42,255,255;%
-yellow2,42,255,238;%
-yellow3,42,255,205;%
-yellow4,42,255,139;%
+\def\rangeHSB{255}
+\preparecolorset{HSB}{}{}{%
+aliceblue,147,15,255;%
+antiquewhite,24,35,250;%
+antiquewhite1,23,36,255;%
+antiquewhite2,23,36,238;%
+antiquewhite3,23,36,205;%
+antiquewhite4,24,34,139;%
+aquamarine,113,128,255;%
+aquamarine1,113,128,255;%
+aquamarine2,113,128,238;%
+aquamarine3,113,128,205;%
+aquamarine4,113,128,139;%
+azure,127,15,255;%
+azure1,127,15,255;%
+azure2,127,15,238;%
+azure3,127,14,205;%
+azure4,127,14,139;%
+beige,42,26,245;%
+bisque,23,58,255;%
+bisque1,23,58,255;%
+bisque2,23,58,238;%
+bisque3,22,58,205;%
+bisque4,23,58,139;%
+black,0,0,0;%
+blanchedalmond,25,49,255;%
+blue,170,255,255;%
+blue1,170,255,255;%
+blue2,170,255,238;%
+blue3,170,255,205;%
+blue4,170,255,139;%
+blueviolet,192,206,226;%
+brown,0,190,165;%
+brown1,0,191,255;%
+brown2,0,191,238;%
+brown3,0,191,205;%
+brown4,0,190,139;%
+burlywood,23,99,222;%
+burlywood1,23,100,255;%
+burlywood2,23,99,238;%
+burlywood3,23,99,205;%
+burlywood4,23,99,139;%
+cadetblue,128,103,160;%
+cadetblue1,131,103,255;%
+cadetblue2,131,102,238;%
+cadetblue3,131,103,205;%
+cadetblue4,131,102,139;%
+chartreuse,63,255,255;%
+chartreuse1,63,255,255;%
+chartreuse2,63,255,238;%
+chartreuse3,63,255,205;%
+chartreuse4,63,255,139;%
+chocolate,17,218,210;%
+chocolate1,17,219,255;%
+chocolate2,17,219,238;%
+chocolate3,17,218,205;%
+chocolate4,17,220,139;%
+coral,11,175,255;%
+coral1,7,169,255;%
+coral2,6,169,238;%
+coral3,6,169,205;%
+coral4,6,168,139;%
+cornflowerblue,154,147,237;%
+cornsilk,33,34,255;%
+cornsilk1,33,34,255;%
+cornsilk2,34,35,238;%
+cornsilk3,34,34,205;%
+cornsilk4,35,34,139;%
+crimson,246,231,220;%
+cyan,127,255,255;%
+cyan1,127,255,255;%
+cyan2,127,255,238;%
+cyan3,127,255,205;%
+cyan4,127,255,139;%
+darkgoldenrod,30,239,184;%
+darkgoldenrod1,30,240,255;%
+darkgoldenrod2,30,240,238;%
+darkgoldenrod3,30,240,205;%
+darkgoldenrod4,30,240,139;%
+darkgreen,85,255,100;%
+darkkhaki,39,110,189;%
+darkolivegreen,58,142,107;%
+darkolivegreen1,58,143,255;%
+darkolivegreen2,58,143,238;%
+darkolivegreen3,58,143,205;%
+darkolivegreen4,58,143,139;%
+darkorange,23,255,255;%
+darkorange1,21,255,255;%
+darkorange2,21,255,238;%
+darkorange3,21,255,205;%
+darkorange4,21,255,139;%
+darkorchid,198,192,204;%
+darkorchid1,198,193,255;%
+darkorchid2,198,192,238;%
+darkorchid3,198,192,205;%
+darkorchid4,198,192,139;%
+darksalmon,10,121,233;%
+darkseagreen,85,61,188;%
+darkseagreen1,85,62,255;%
+darkseagreen2,85,62,238;%
+darkseagreen3,85,62,205;%
+darkseagreen4,85,62,139;%
+darkslateblue,175,143,139;%
+darkslategray,127,103,79;%
+darkslategray1,127,104,255;%
+darkslategray2,127,103,238;%
+darkslategray3,127,104,205;%
+darkslategray4,127,104,139;%
+darkslategrey,127,103,79;%
+darkturquoise,128,255,209;%
+darkviolet,199,255,211;%
+deeppink,232,235,255;%
+deeppink1,232,235,255;%
+deeppink2,232,235,238;%
+deeppink3,232,235,205;%
+deeppink4,231,236,139;%
+deepskyblue,138,255,255;%
+deepskyblue1,138,255,255;%
+deepskyblue2,138,255,238;%
+deepskyblue3,138,255,205;%
+deepskyblue4,138,255,139;%
+dimgray,0,0,105;%
+dimgrey,0,0,105;%
+dodgerblue,148,225,255;%
+dodgerblue1,148,225,255;%
+dodgerblue2,148,225,238;%
+dodgerblue3,148,225,205;%
+dodgerblue4,148,225,139;%
+firebrick,0,206,178;%
+firebrick1,0,207,255;%
+firebrick2,0,207,238;%
+firebrick3,0,207,205;%
+firebrick4,0,207,139;%
+floralwhite,28,15,255;%
+forestgreen,85,192,139;%
+gainsboro,0,0,220;%
+ghostwhite,170,7,255;%
+gold,35,255,255;%
+gold1,35,255,255;%
+gold2,35,255,238;%
+gold3,35,255,205;%
+gold4,35,255,139;%
+goldenrod,30,217,218;%
+goldenrod1,30,218,255;%
+goldenrod2,30,218,238;%
+goldenrod3,30,218,205;%
+goldenrod4,30,218,139;%
+gray,0,0,192;%
+gray0,0,0,0;%
+gray1,0,0,3;%
+gray10,0,0,26;%
+gray100,0,0,255;%
+gray11,0,0,28;%
+gray12,0,0,31;%
+gray13,0,0,33;%
+gray14,0,0,36;%
+gray15,0,0,38;%
+gray16,0,0,41;%
+gray17,0,0,43;%
+gray18,0,0,46;%
+gray19,0,0,48;%
+gray2,0,0,5;%
+gray20,0,0,51;%
+gray21,0,0,54;%
+gray22,0,0,56;%
+gray23,0,0,59;%
+gray24,0,0,61;%
+gray25,0,0,64;%
+gray26,0,0,66;%
+gray27,0,0,69;%
+gray28,0,0,71;%
+gray29,0,0,74;%
+gray3,0,0,8;%
+gray30,0,0,77;%
+gray31,0,0,79;%
+gray32,0,0,82;%
+gray33,0,0,84;%
+gray34,0,0,87;%
+gray35,0,0,89;%
+gray36,0,0,92;%
+gray37,0,0,94;%
+gray38,0,0,97;%
+gray39,0,0,99;%
+gray4,0,0,10;%
+gray40,0,0,102;%
+gray41,0,0,105;%
+gray42,0,0,107;%
+gray43,0,0,110;%
+gray44,0,0,112;%
+gray45,0,0,115;%
+gray46,0,0,117;%
+gray47,0,0,120;%
+gray48,0,0,122;%
+gray49,0,0,125;%
+gray5,0,0,13;%
+gray50,0,0,127;%
+gray51,0,0,130;%
+gray52,0,0,133;%
+gray53,0,0,135;%
+gray54,0,0,138;%
+gray55,0,0,140;%
+gray56,0,0,143;%
+gray57,0,0,145;%
+gray58,0,0,148;%
+gray59,0,0,150;%
+gray6,0,0,15;%
+gray60,0,0,153;%
+gray61,0,0,156;%
+gray62,0,0,158;%
+gray63,0,0,161;%
+gray64,0,0,163;%
+gray65,0,0,166;%
+gray66,0,0,168;%
+gray67,0,0,171;%
+gray68,0,0,173;%
+gray69,0,0,176;%
+gray7,0,0,18;%
+gray70,0,0,179;%
+gray71,0,0,181;%
+gray72,0,0,184;%
+gray73,0,0,186;%
+gray74,0,0,189;%
+gray75,0,0,191;%
+gray76,0,0,194;%
+gray77,0,0,196;%
+gray78,0,0,199;%
+gray79,0,0,201;%
+gray8,0,0,20;%
+gray80,0,0,204;%
+gray81,0,0,207;%
+gray82,0,0,209;%
+gray83,0,0,212;%
+gray84,0,0,214;%
+gray85,0,0,217;%
+gray86,0,0,219;%
+gray87,0,0,222;%
+gray88,0,0,224;%
+gray89,0,0,227;%
+gray9,0,0,23;%
+gray90,0,0,229;%
+gray91,0,0,232;%
+gray92,0,0,235;%
+gray93,0,0,237;%
+gray94,0,0,240;%
+gray95,0,0,242;%
+gray96,0,0,245;%
+gray97,0,0,247;%
+gray98,0,0,250;%
+gray99,0,0,252;%
+green,85,255,255;%
+green1,85,255,255;%
+green2,85,255,238;%
+green3,85,255,205;%
+green4,85,255,139;%
+greenyellow,59,208,255;%
+grey,0,0,192;%
+grey0,0,0,0;%
+grey1,0,0,3;%
+grey10,0,0,26;%
+grey100,0,0,255;%
+grey11,0,0,28;%
+grey12,0,0,31;%
+grey13,0,0,33;%
+grey14,0,0,36;%
+grey15,0,0,38;%
+grey16,0,0,41;%
+grey17,0,0,43;%
+grey18,0,0,46;%
+grey19,0,0,48;%
+grey2,0,0,5;%
+grey20,0,0,51;%
+grey21,0,0,54;%
+grey22,0,0,56;%
+grey23,0,0,59;%
+grey24,0,0,61;%
+grey25,0,0,64;%
+grey26,0,0,66;%
+grey27,0,0,69;%
+grey28,0,0,71;%
+grey29,0,0,74;%
+grey3,0,0,8;%
+grey30,0,0,77;%
+grey31,0,0,79;%
+grey32,0,0,82;%
+grey33,0,0,84;%
+grey34,0,0,87;%
+grey35,0,0,89;%
+grey36,0,0,92;%
+grey37,0,0,94;%
+grey38,0,0,97;%
+grey39,0,0,99;%
+grey4,0,0,10;%
+grey40,0,0,102;%
+grey41,0,0,105;%
+grey42,0,0,107;%
+grey43,0,0,110;%
+grey44,0,0,112;%
+grey45,0,0,115;%
+grey46,0,0,117;%
+grey47,0,0,120;%
+grey48,0,0,122;%
+grey49,0,0,125;%
+grey5,0,0,13;%
+grey50,0,0,127;%
+grey51,0,0,130;%
+grey52,0,0,133;%
+grey53,0,0,135;%
+grey54,0,0,138;%
+grey55,0,0,140;%
+grey56,0,0,143;%
+grey57,0,0,145;%
+grey58,0,0,148;%
+grey59,0,0,150;%
+grey6,0,0,15;%
+grey60,0,0,153;%
+grey61,0,0,156;%
+grey62,0,0,158;%
+grey63,0,0,161;%
+grey64,0,0,163;%
+grey65,0,0,166;%
+grey66,0,0,168;%
+grey67,0,0,171;%
+grey68,0,0,173;%
+grey69,0,0,176;%
+grey7,0,0,18;%
+grey70,0,0,179;%
+grey71,0,0,181;%
+grey72,0,0,184;%
+grey73,0,0,186;%
+grey74,0,0,189;%
+grey75,0,0,191;%
+grey76,0,0,194;%
+grey77,0,0,196;%
+grey78,0,0,199;%
+grey79,0,0,201;%
+grey8,0,0,20;%
+grey80,0,0,204;%
+grey81,0,0,207;%
+grey82,0,0,209;%
+grey83,0,0,212;%
+grey84,0,0,214;%
+grey85,0,0,217;%
+grey86,0,0,219;%
+grey87,0,0,222;%
+grey88,0,0,224;%
+grey89,0,0,227;%
+grey9,0,0,23;%
+grey90,0,0,229;%
+grey91,0,0,232;%
+grey92,0,0,235;%
+grey93,0,0,237;%
+grey94,0,0,240;%
+grey95,0,0,242;%
+grey96,0,0,245;%
+grey97,0,0,247;%
+grey98,0,0,250;%
+grey99,0,0,252;%
+honeydew,85,15,255;%
+honeydew1,85,15,255;%
+honeydew2,85,15,238;%
+honeydew3,85,14,205;%
+honeydew4,85,14,139;%
+hotpink,233,150,255;%
+hotpink1,234,145,255;%
+hotpink2,235,141,238;%
+hotpink3,236,135,205;%
+hotpink4,234,148,139;%
+indianred,0,140,205;%
+indianred1,0,148,255;%
+indianred2,0,148,238;%
+indianred3,0,149,205;%
+indianred4,0,148,139;%
+indigo,194,255,130;%
+ivory,42,15,255;%
+ivory1,42,15,255;%
+ivory2,42,15,238;%
+ivory3,42,14,205;%
+ivory4,42,14,139;%
+khaki,38,106,240;%
+khaki1,39,112,255;%
+khaki2,39,112,238;%
+khaki3,39,111,205;%
+khaki4,39,111,139;%
+lavender,170,20,250;%
+lavenderblush,240,15,255;%
+lavenderblush1,240,15,255;%
+lavenderblush2,239,15,238;%
+lavenderblush3,240,14,205;%
+lavenderblush4,239,14,139;%
+lawngreen,64,255,252;%
+lemonchiffon,38,49,255;%
+lemonchiffon1,38,49,255;%
+lemonchiffon2,37,50,238;%
+lemonchiffon3,38,49,205;%
+lemonchiffon4,39,49,139;%
+lightblue,137,63,230;%
+lightblue1,138,64,255;%
+lightblue2,138,64,238;%
+lightblue3,138,63,205;%
+lightblue4,137,64,139;%
+lightcoral,0,119,240;%
+lightcyan,127,31,255;%
+lightcyan1,127,31,255;%
+lightcyan2,127,31,238;%
+lightcyan3,127,31,205;%
+lightcyan4,127,31,139;%
+lightgoldenrod,35,115,238;%
+lightgoldenrod1,35,116,255;%
+lightgoldenrod2,35,115,238;%
+lightgoldenrod3,35,115,205;%
+lightgoldenrod4,35,115,139;%
+lightgoldenrodyellow,42,40,250;%
+lightgray,0,0,211;%
+lightgrey,0,0,211;%
+lightpink,248,73,255;%
+lightpink1,249,81,255;%
+lightpink2,248,81,238;%
+lightpink3,249,80,205;%
+lightpink4,249,80,139;%
+lightsalmon,12,132,255;%
+lightsalmon1,12,132,255;%
+lightsalmon2,11,132,238;%
+lightsalmon3,12,133,205;%
+lightsalmon4,12,133,139;%
+lightseagreen,125,209,178;%
+lightskyblue,143,117,250;%
+lightskyblue1,143,79,255;%
+lightskyblue2,143,79,238;%
+lightskyblue3,142,79,205;%
+lightskyblue4,143,78,139;%
+lightslateblue,175,143,255;%
+lightslategray,148,56,153;%
+lightslategrey,148,56,153;%
+lightsteelblue,151,52,222;%
+lightsteelblue1,151,53,255;%
+lightsteelblue2,151,53,238;%
+lightsteelblue3,151,53,205;%
+lightsteelblue4,150,53,139;%
+lightyellow,42,31,255;%
+lightyellow1,42,31,255;%
+lightyellow2,42,31,238;%
+lightyellow3,42,31,205;%
+lightyellow4,42,31,139;%
+limegreen,85,192,205;%
+linen,21,20,250;%
+magenta,212,255,255;%
+magenta1,212,255,255;%
+magenta2,212,255,238;%
+magenta3,212,255,205;%
+magenta4,212,255,139;%
+maroon,239,185,176;%
+maroon1,228,203,255;%
+maroon2,228,203,238;%
+maroon3,228,204,205;%
+maroon4,228,203,139;%
+mediumaquamarine,113,128,205;%
+mediumblue,170,255,205;%
+mediumorchid,204,152,211;%
+mediumorchid1,203,153,255;%
+mediumorchid2,203,153,238;%
+mediumorchid3,203,153,205;%
+mediumorchid4,203,154,139;%
+mediumpurple,183,124,219;%
+mediumpurple1,183,125,255;%
+mediumpurple2,183,125,238;%
+mediumpurple3,183,125,205;%
+mediumpurple4,183,124,139;%
+mediumseagreen,103,169,179;%
+mediumslateblue,176,143,238;%
+mediumspringgreen,111,255,250;%
+mediumturquoise,125,167,209;%
+mediumvioletred,228,228,199;%
+midnightblue,170,198,112;%
+mintcream,106,9,255;%
+mistyrose,4,30,255;%
+mistyrose1,4,30,255;%
+mistyrose2,4,30,238;%
+mistyrose3,3,29,205;%
+mistyrose4,5,29,139;%
+moccasin,26,73,255;%
+navajowhite,25,81,255;%
+navajowhite1,25,81,255;%
+navajowhite2,25,82,238;%
+navajowhite3,25,82,205;%
+navajowhite4,25,82,139;%
+navy,170,255,128;%
+navyblue,170,255,128;%
+oldlace,27,23,253;%
+olivedrab,56,192,142;%
+olivedrab1,56,193,255;%
+olivedrab2,56,192,238;%
+olivedrab3,56,192,205;%
+olivedrab4,56,192,139;%
+orange,27,255,255;%
+orange1,27,255,255;%
+orange2,27,255,238;%
+orange3,27,255,205;%
+orange4,27,255,139;%
+orangered,11,255,255;%
+orangered1,11,255,255;%
+orangered2,11,255,238;%
+orangered3,11,255,205;%
+orangered4,11,255,139;%
+orchid,214,123,218;%
+orchid1,214,124,255;%
+orchid2,214,124,238;%
+orchid3,214,124,205;%
+orchid4,213,124,139;%
+palegoldenrod,38,72,238;%
+palegreen,85,100,251;%
+palegreen1,85,101,255;%
+palegreen2,85,100,238;%
+palegreen3,85,100,205;%
+palegreen4,85,100,139;%
+paleturquoise,127,67,238;%
+paleturquoise1,127,68,255;%
+paleturquoise2,127,68,238;%
+paleturquoise3,127,68,205;%
+paleturquoise4,127,67,139;%
+palevioletred,241,124,219;%
+palevioletred1,241,125,255;%
+palevioletred2,241,125,238;%
+palevioletred3,241,125,205;%
+palevioletred4,241,124,139;%
+papayawhip,26,41,255;%
+peachpuff,20,70,255;%
+peachpuff1,20,70,255;%
+peachpuff2,19,69,238;%
+peachpuff3,19,69,205;%
+peachpuff4,20,69,139;%
+peru,20,176,205;%
+pink,247,63,255;%
+pink1,245,73,255;%
+pink2,245,73,238;%
+pink3,245,74,205;%
+pink4,245,73,139;%
+plum,212,70,221;%
+plum1,212,68,255;%
+plum2,212,68,238;%
+plum3,212,68,205;%
+plum4,212,67,139;%
+powderblue,132,59,230;%
+purple,196,221,240;%
+purple1,191,207,255;%
+purple2,192,207,238;%
+purple3,192,207,205;%
+purple4,192,207,139;%
+red,0,255,255;%
+red1,0,255,255;%
+red2,0,255,238;%
+red3,0,255,205;%
+red4,0,255,139;%
+rosybrown,0,61,188;%
+rosybrown1,0,62,255;%
+rosybrown2,0,62,238;%
+rosybrown3,0,62,205;%
+rosybrown4,0,62,139;%
+royalblue,159,181,225;%
+royalblue1,159,183,255;%
+royalblue2,159,183,238;%
+royalblue3,159,182,205;%
+royalblue4,159,183,139;%
+saddlebrown,17,220,139;%
+salmon,4,138,250;%
+salmon1,9,150,255;%
+salmon2,9,150,238;%
+salmon3,9,150,205;%
+salmon4,9,150,139;%
+sandybrown,19,154,244;%
+seagreen,103,170,139;%
+seagreen1,103,171,255;%
+seagreen2,103,171,238;%
+seagreen3,103,171,205;%
+seagreen4,103,170,139;%
+seashell,17,16,255;%
+seashell1,17,16,255;%
+seashell2,18,17,238;%
+seashell3,18,17,205;%
+seashell4,18,16,139;%
+sienna,13,183,160;%
+sienna1,13,184,255;%
+sienna2,13,184,238;%
+sienna3,13,184,205;%
+sienna4,13,185,139;%
+skyblue,139,108,235;%
+skyblue1,144,120,255;%
+skyblue2,144,120,238;%
+skyblue3,144,120,205;%
+skyblue4,145,119,139;%
+slateblue,175,143,205;%
+slateblue1,175,144,255;%
+slateblue2,175,144,238;%
+slateblue3,175,144,205;%
+slateblue4,175,144,139;%
+slategray,148,56,144;%
+slategray1,149,56,255;%
+slategray2,149,56,238;%
+slategray3,148,57,205;%
+slategray4,149,56,139;%
+slategrey,148,56,144;%
+snow,0,5,255;%
+snow1,0,5,255;%
+snow2,0,5,238;%
+snow3,0,4,205;%
+snow4,0,3,139;%
+springgreen,106,255,255;%
+springgreen1,106,255,255;%
+springgreen2,106,255,238;%
+springgreen3,106,255,205;%
+springgreen4,106,255,139;%
+steelblue,146,155,180;%
+steelblue1,146,156,255;%
+steelblue2,146,156,238;%
+steelblue3,146,156,205;%
+steelblue4,147,155,139;%
+tan,24,84,210;%
+tan1,20,176,255;%
+tan2,20,176,238;%
+tan3,20,176,205;%
+tan4,20,176,139;%
+thistle,212,29,216;%
+thistle1,212,30,255;%
+thistle2,212,30,238;%
+thistle3,212,29,205;%
+thistle4,212,29,139;%
+tomato,6,184,255;%
+tomato1,6,184,255;%
+tomato2,6,184,238;%
+tomato3,6,184,205;%
+tomato4,6,185,139;%
+transparent,42,0,255;%
+turquoise,123,182,224;%
+turquoise1,129,255,255;%
+turquoise2,129,255,238;%
+turquoise3,129,255,205;%
+turquoise4,129,255,139;%
+violet,212,115,238;%
+violetred,227,215,208;%
+violetred1,235,193,255;%
+violetred2,235,192,238;%
+violetred3,235,192,205;%
+violetred4,235,192,139;%
+wheat,27,68,245;%
+wheat1,27,69,255;%
+wheat2,27,68,238;%
+wheat3,27,68,205;%
+wheat4,27,67,139;%
+white,0,0,255;%
+whitesmoke,0,0,245;%
+yellow,42,255,255;%
+yellow1,42,255,255;%
+yellow2,42,255,238;%
+yellow3,42,255,205;%
+yellow4,42,255,139;%
 yellowgreen,56,192,205}
\ No newline at end of file
diff --git a/examples/latexmarkup.dot b/examples/latexmarkup.dot
index 60c118c..af48930 100644
--- a/examples/latexmarkup.dot
+++ b/examples/latexmarkup.dot
@@ -1,32 +1,32 @@
-/*
-
-:Title: LaTeX markup
-:Tags: PGF
-
-*/
-digraph G {
-	node [fontcolor=red];
-	subgraph cluster0 {
-		node [style=filled,color=white, texmode=math];
-		style=filled;
-		color=lightgrey;
-		a_0 -> a_1 -> a_2 -> a_3;
-		label="latex";
-		texlbl="\LaTeX";
-	}
-	subgraph cluster1 {
-		node [style=filled, texmode=math, fontcolor=red];
-		b_0 -> b_1 -> b_2 -> b_3;
-		label = "process #2";
-		color=blue
-	}
-	start -> a_0;
-	start -> b_0;
-	a_1 -> b_3;
-	b_2 -> a_3;
-	a_3 -> a_0;
-	a_3 -> end;
-	b_3 -> end;
-	start [shape=diamond, texlbl="${\frac{\sqrt{\gamma+\beta}}{x^2+y^2}}$"];
-	end [shape=Msquare];
+/*
+
+:Title: LaTeX markup
+:Tags: PGF
+
+*/
+digraph G {
+	node [fontcolor=red];
+	subgraph cluster0 {
+		node [style=filled,color=white, texmode=math];
+		style=filled;
+		color=lightgrey;
+		a_0 -> a_1 -> a_2 -> a_3;
+		label="latex";
+		texlbl="\LaTeX";
+	}
+	subgraph cluster1 {
+		node [style=filled, texmode=math, fontcolor=red];
+		b_0 -> b_1 -> b_2 -> b_3;
+		label = "process #2";
+		color=blue
+	}
+	start -> a_0;
+	start -> b_0;
+	a_1 -> b_3;
+	b_2 -> a_3;
+	a_3 -> a_0;
+	a_3 -> end;
+	b_3 -> end;
+	start [shape=diamond, texlbl="${\frac{\sqrt{\gamma+\beta}}{x^2+y^2}}$"];
+	end [shape=Msquare];
 }
\ No newline at end of file
diff --git a/examples/pgfarrows.dot b/examples/pgfarrows.dot
index ce69f6b..a0c097a 100644
--- a/examples/pgfarrows.dot
+++ b/examples/pgfarrows.dot
@@ -1,27 +1,27 @@
-/*
-
-:Title: PGF and TikZ arrows
-:Tags: PGF
-
-Examples of PGF/TikZ style arrows. See chapter 14.1 in the PGF/TikZ manual
-for all availale arrow styles.
-
-Generated with::
-
-    $ dot2tex --prog=circo pgfarrows.dot > pgfarrows.tex
-
-*/
-digraph G {
-	graph [mindist=0.5];
-	node [texmode="math", fixedsize=true, shape=circle, width=0.4, style="fill=green!20"];
-	c -> n_1 [style="-stealth", label="stealth"];
-	c -> n_2 [style="-to", label="to"];
-	c -> n_3 [style="-latex", label="latex"];
-	c -> n_4 [style="-diamond", label="diamond"];
-	c -> n_5 [style="-o", label="o"];
-	c -> n_6 [style="{-]}", label="]"]; 
-	c -> n_7 [style="-triangle 90", label="triangle 90"];
-	c -> n_8 [style="-hooks", label="hooks"];
-	c -> n_9 [style="->>", texmode="math", label=">>"];
-	c [style="fill=red!80"];
+/*
+
+:Title: PGF and TikZ arrows
+:Tags: PGF
+
+Examples of PGF/TikZ style arrows. See chapter 14.1 in the PGF/TikZ manual
+for all availale arrow styles.
+
+Generated with::
+
+    $ dot2tex --prog=circo pgfarrows.dot > pgfarrows.tex
+
+*/
+digraph G {
+	graph [mindist=0.5];
+	node [texmode="math", fixedsize=true, shape=circle, width=0.4, style="fill=green!20"];
+	c -> n_1 [style="-stealth", label="stealth"];
+	c -> n_2 [style="-to", label="to"];
+	c -> n_3 [style="-latex", label="latex"];
+	c -> n_4 [style="-diamond", label="diamond"];
+	c -> n_5 [style="-o", label="o"];
+	c -> n_6 [style="{-]}", label="]"]; 
+	c -> n_7 [style="-triangle 90", label="triangle 90"];
+	c -> n_8 [style="-hooks", label="hooks"];
+	c -> n_9 [style="->>", texmode="math", label=">>"];
+	c [style="fill=red!80"];
 }
\ No newline at end of file
diff --git a/examples/pgfsnakes.dot b/examples/pgfsnakes.dot
index 1218315..23f307f 100644
--- a/examples/pgfsnakes.dot
+++ b/examples/pgfsnakes.dot
@@ -1,26 +1,26 @@
-/*
-
-:Title: PGF snakes
-:Tags: PGF
-
-Examples of PGF/TikZ snake line styles. See chapter 14.2 in the PGF/TikZ 
-manual for all availale snake styles. Note that the snake styles requires
-line operations, so you have to use the ``-s`` option.
-
-Generated with::
-
- $ dot2tex -fpgf -s --prog circo pgfsnakes.dot > pgfsnakes.tex
- 
-*/
-graph G {
-	graph [mindist=0.5];
-	node [texmode="math", fixedsize=true, shape=circle, width=0.4, style="fill=green!20"];
-	c -- n_1 [style="snake=zigzag"];
-	c -- n_2 [style="snake=saw"];
-	c -- n_3 [style="snake=expanding waves, segment angle=10"];
-	c -- n_4 [style="snake=snake"];
-	c -- n_5 [style="snake=coil, segment amplitude=6pt"];
-	c -- n_6 [style="snake=brace"];
-	c -- n_7 [style="snake=triangles"];
-	c [style="fill=red!80"];
+/*
+
+:Title: PGF snakes
+:Tags: PGF
+
+Examples of PGF/TikZ snake line styles. See chapter 14.2 in the PGF/TikZ 
+manual for all availale snake styles. Note that the snake styles requires
+line operations, so you have to use the ``-s`` option.
+
+Generated with::
+
+ $ dot2tex -fpgf -s --prog circo pgfsnakes.dot > pgfsnakes.tex
+ 
+*/
+graph G {
+	graph [mindist=0.5];
+	node [texmode="math", fixedsize=true, shape=circle, width=0.4, style="fill=green!20"];
+	c -- n_1 [style="snake=zigzag"];
+	c -- n_2 [style="snake=saw"];
+	c -- n_3 [style="snake=expanding waves, segment angle=10"];
+	c -- n_4 [style="snake=snake"];
+	c -- n_5 [style="snake=coil, segment amplitude=6pt"];
+	c -- n_6 [style="snake=brace"];
+	c -- n_7 [style="snake=triangles"];
+	c [style="fill=red!80"];
 }
\ No newline at end of file
diff --git a/examples/poltab.dot b/examples/poltab.dot
index f4027b4..c3a232d 100644
--- a/examples/poltab.dot
+++ b/examples/poltab.dot
@@ -1,33 +1,33 @@
-/*
-
-:Tags: PGF, Preproc
-
-This example graph was contributed by Teresa Gomez-Diaz, and shows
-that the ``texlbl`` attriute can contain arbitrary LaTeX markup.
-
-Generated with::
-
-    $ dot2tex -tmath --autosize poltab.dot > poltab.tex
-    
-
-*/
-digraph G {
-	rankdir=LR;
-	node [shape=plaintext];
-	a_1 [texlbl="$\begin{array}{l} \fbox{1}\fbox{1} \end{array}$"];
-	a_2 [texlbl="$\frac{1}{q} \begin{array}{l} \fbox{2}\fbox{1} \end{array} + \begin{array}{l} \fbox{1}\fbox{2} \end{array}$"];
-	a_3 [texlbl="$(q+\frac{1}{q}) \begin{array}{l} \fbox{2}\fbox{2} \end{array}$"];
-
-	a_4 [texlbl="$\frac{1}{q} \frac{1}{z_1} \begin{array}{l} \fbox{1}\fbox{2} \end{array} + \frac{1}{z_2}\begin{array}{l} \fbox{2}\fbox{1} \end{array}$"];
-
-	{ rank=same; a_1;  a_2; a_3;}
-	{ nodesep =1; a_2; a_4;}
-
-	a_1 -> a_2 [label="f_1" ];
-	a_2 -> a_3 [label="f_1" ];
-	a_1 -> a_4 [label="f_0" dir=back];
-	a_3 -> a_4 [label="f_0" ];
-
-}
-
-
+/*
+
+:Tags: PGF, Preproc
+
+This example graph was contributed by Teresa Gomez-Diaz, and shows
+that the ``texlbl`` attriute can contain arbitrary LaTeX markup.
+
+Generated with::
+
+    $ dot2tex -tmath --autosize poltab.dot > poltab.tex
+    
+
+*/
+digraph G {
+	rankdir=LR;
+	node [shape=plaintext];
+	a_1 [texlbl="$\begin{array}{l} \fbox{1}\fbox{1} \end{array}$"];
+	a_2 [texlbl="$\frac{1}{q} \begin{array}{l} \fbox{2}\fbox{1} \end{array} + \begin{array}{l} \fbox{1}\fbox{2} \end{array}$"];
+	a_3 [texlbl="$(q+\frac{1}{q}) \begin{array}{l} \fbox{2}\fbox{2} \end{array}$"];
+
+	a_4 [texlbl="$\frac{1}{q} \frac{1}{z_1} \begin{array}{l} \fbox{1}\fbox{2} \end{array} + \frac{1}{z_2}\begin{array}{l} \fbox{2}\fbox{1} \end{array}$"];
+
+	{ rank=same; a_1;  a_2; a_3;}
+	{ nodesep =1; a_2; a_4;}
+
+	a_1 -> a_2 [label="f_1" ];
+	a_2 -> a_3 [label="f_1" ];
+	a_1 -> a_4 [label="f_0" dir=back];
+	a_3 -> a_4 [label="f_0" ];
+
+}
+
+
diff --git a/examples/pstarrows.dot b/examples/pstarrows.dot
index 444a9f1..93d8c91 100644
--- a/examples/pstarrows.dot
+++ b/examples/pstarrows.dot
@@ -1,25 +1,25 @@
-/*
-:Title: PSTricks arrows
-:Tags: PSTricks
-
-Examples of Pstricks style arrows. 
-To generate this graph you can write::
-
-    $ circo -Txdot pstarrows.dot | dot2tex -fpst > pstarrows.tex
-
-*/
-digraph G {
-	d2tdocpreamble="\usepackage{pstricks-add}";
-	graph [mindist=0.5];
-	node [texmode="math", fixedsize=true, shape=circle, width=0.4, style="linecolor=red, fillcolor=white"];
-	edge [color="blue"];
-	c -> n_1 [style="arrows=->", texmode="math", label=">"];
-	c -> n_2 [style="arrows=->>", texmode="math", label=">>"];
-	c -> n_3 [style="arrows=-<", texmode="math", label="<"];
-	c -> n_4 [style="arrows=-*", texmode="math", label="*"];
-	c -> n_5 [style="arrows=-{]}", texmode="math", label="]"];
-	edge [color="red"];
-	c -> n_6 [style="arrows=-o", texmode="math", label="o"];
-	c -> n_7 [style="arrows=-H", texmode="math", label="H"];
-	c -> n_8 [style="arrows=->, nArrowsA=5", texmode="math"];
+/*
+:Title: PSTricks arrows
+:Tags: PSTricks
+
+Examples of Pstricks style arrows. 
+To generate this graph you can write::
+
+    $ circo -Txdot pstarrows.dot | dot2tex -fpst > pstarrows.tex
+
+*/
+digraph G {
+	d2tdocpreamble="\usepackage{pstricks-add}";
+	graph [mindist=0.5];
+	node [texmode="math", fixedsize=true, shape=circle, width=0.4, style="linecolor=red, fillcolor=white"];
+	edge [color="blue"];
+	c -> n_1 [style="arrows=->", texmode="math", label=">"];
+	c -> n_2 [style="arrows=->>", texmode="math", label=">>"];
+	c -> n_3 [style="arrows=-<", texmode="math", label="<"];
+	c -> n_4 [style="arrows=-*", texmode="math", label="*"];
+	c -> n_5 [style="arrows=-{]}", texmode="math", label="]"];
+	edge [color="red"];
+	c -> n_6 [style="arrows=-o", texmode="math", label="o"];
+	c -> n_7 [style="arrows=-H", texmode="math", label="H"];
+	c -> n_8 [style="arrows=->, nArrowsA=5", texmode="math"];
 }
\ No newline at end of file
diff --git a/examples/showpoints.dot b/examples/showpoints.dot
index 0851f2b..c9f830b 100644
--- a/examples/showpoints.dot
+++ b/examples/showpoints.dot
@@ -1,89 +1,89 @@
-/*
-:Title: Control points
-:Tags: PSTricks
-
-This example uses the ``showpoints`` PSTricks style to show the
-control points of the edge curves. 
-
-Generated with::
-
-    $ dot2tex -fpst showpoints.dot > showpoints.tex
-
-
-*/
-digraph G {
-	size = "8,8";
-	{rank=min S8 S24 S1 S35 S30}
-	{rank=max T8 T24 T1 T35 T30}
-	edge [exstyle="showpoints=true, linecolor=red"];
-	node [style="fillstyle=solid"];
-	S8 -> 9;
-	S24 -> 27;
-	S24 -> 25;
-	S1 -> 10;
-	S1 -> 2;
-	S35 -> 36;
-	S35 -> 43;
-	S30 -> 31;
-	S30 -> 33;
-	9 -> 42;
-	9 -> T1;
-	25 -> T1;
-	25 -> 26;
-	27 -> T24;
-	2 -> 3;
-	2 -> 16;
-	2 -> 17;
-	2 -> T1;
-	2 -> 18;
-	10 -> 11;
-	10 -> 14;
-	10 -> T1;
-	10 -> 13;
-	10 -> 12;
-	31 -> T1;
-	31 -> 32;
-	33 -> T30;
-	33 -> 34;
-	42 -> 4;
-	26 -> 4;
-	3 -> 4;
-	16 -> 15;
-	17 -> 19;
-	18 -> 29;
-	11 -> 4;
-	14 -> 15;
-	37 -> 39;
-	37 -> 41;
-	37 -> 38;
-	37 -> 40;
-	13 -> 19;
-	12 -> 29;
-	43 -> 38;
-	43 -> 40;
-	36 -> 19;
-	32 -> 23;
-	34 -> 29;
-	39 -> 15;
-	41 -> 29;
-	38 -> 4;
-	40 -> 19;
-	4 -> 5;
-	19 -> 21;
-	19 -> 20;
-	19 -> 28;
-	5 -> 6;
-	5 -> T35;
-	5 -> 23;
-	21 -> 22;
-	20 -> 15;
-	28 -> 29;
-	6 -> 7;
-	15 -> T1;
-	22 -> 23;
-	22 -> T35;
-	29 -> T30;
-	7 -> T8;
-	23 -> T24;
-	23 -> T1; 
-}
+/*
+:Title: Control points
+:Tags: PSTricks
+
+This example uses the ``showpoints`` PSTricks style to show the
+control points of the edge curves. 
+
+Generated with::
+
+    $ dot2tex -fpst showpoints.dot > showpoints.tex
+
+
+*/
+digraph G {
+	size = "8,8";
+	{rank=min S8 S24 S1 S35 S30}
+	{rank=max T8 T24 T1 T35 T30}
+	edge [exstyle="showpoints=true, linecolor=red"];
+	node [style="fillstyle=solid"];
+	S8 -> 9;
+	S24 -> 27;
+	S24 -> 25;
+	S1 -> 10;
+	S1 -> 2;
+	S35 -> 36;
+	S35 -> 43;
+	S30 -> 31;
+	S30 -> 33;
+	9 -> 42;
+	9 -> T1;
+	25 -> T1;
+	25 -> 26;
+	27 -> T24;
+	2 -> 3;
+	2 -> 16;
+	2 -> 17;
+	2 -> T1;
+	2 -> 18;
+	10 -> 11;
+	10 -> 14;
+	10 -> T1;
+	10 -> 13;
+	10 -> 12;
+	31 -> T1;
+	31 -> 32;
+	33 -> T30;
+	33 -> 34;
+	42 -> 4;
+	26 -> 4;
+	3 -> 4;
+	16 -> 15;
+	17 -> 19;
+	18 -> 29;
+	11 -> 4;
+	14 -> 15;
+	37 -> 39;
+	37 -> 41;
+	37 -> 38;
+	37 -> 40;
+	13 -> 19;
+	12 -> 29;
+	43 -> 38;
+	43 -> 40;
+	36 -> 19;
+	32 -> 23;
+	34 -> 29;
+	39 -> 15;
+	41 -> 29;
+	38 -> 4;
+	40 -> 19;
+	4 -> 5;
+	19 -> 21;
+	19 -> 20;
+	19 -> 28;
+	5 -> 6;
+	5 -> T35;
+	5 -> 23;
+	21 -> 22;
+	20 -> 15;
+	28 -> 29;
+	6 -> 7;
+	15 -> T1;
+	22 -> 23;
+	22 -> T35;
+	29 -> T30;
+	7 -> T8;
+	23 -> T24;
+	23 -> T1; 
+}
diff --git a/examples/sportsbracket.dot b/examples/sportsbracket.dot
index 74f33e0..ba254ac 100644
--- a/examples/sportsbracket.dot
+++ b/examples/sportsbracket.dot
@@ -1,108 +1,108 @@
-/*
-
-:Title: Orthogonal edges
-:Tags: PGF, topath
-
-
-This example is adapted from an example posted by Ryan Schmidt to the `graphviz-interest`_ mailing
-list. Graphviz currently does not support orthogonal edges. However,
-with dot2tex you can use the ``topath``  attribute to create custom edges. 
-
-Here is the definition of the ``fork horizontal`` to-path. It uses the powerful 
-*coordinate calculations* feature introduced in PGF 2.00. 
-
-.. sourcecode:: latex
-    
-    ...
-    \usetikzlibrary{calc}
-    ...
-    \tikzstyle{fork horizontal} =[to path={
-    -| ($(\tikztostart)!0.5!(\tikztotarget)$) |- (\tikztotarget) \tikztonodes}]
-
-
-**Note**: This example requires PGF 2.00 or later. 
-
-Generated with::
-
- $ dot2tex --crop sportsbracket.dot > sportsbracket.tex
-
-.. _graphviz-interest: https://mailman.research.att.com/pipermail/graphviz-interest/2008q2/thread.html#5129 
-
-*/
-digraph G {
-    // Put our custom fork horizontal to path in the document preamble
-    d2tdocpreamble = "\usetikzlibrary{calc}\
-\tikzstyle{fork horizontal} =[to path={\
--| ($(\tikztostart)!0.5!(\tikztotarget)$) |- (\tikztotarget) \tikztonodes}]";
-    rankdir=LR
-    node [shape=box, width=2]
-    
-    graph [size="8.5,11" label="NCAA Men's Basketball: 2008 Tournament"]
-    
-    11 [label="North Carolina"]
-    12 [label="Mount St. Mary's"]
-    13 [label="Indiana"]
-    14 [label="Arkansas"]
-    15 [label="Notre Dame"]
-    16 [label="George Mason"]
-    17 [label="Washington St."]
-    18 [label="Winthrop"]
-    19 [label="Oklahoma"]
-    110 [label="St. Joseph's"]
-    111 [label="Louisville"]
-    112 [label="Boise St."]
-    113 [label="Butler"]
-    114 [label="South Alabama"]
-    115 [label="Tennessee"]
-    116 [label="American"]
-    21 [label="North Carolina"]
-    22 [label="Arkansas"]
-    23 [label="Notre Dame"]
-    24 [label="Washington St."]
-    25 [label="Oklahoma"]
-    26 [label="Louisville"]
-    27 [label="Butler"]
-    28 [label="Tennessee"]
-    31 [label="North Carolina"]
-    32 [label="Washington St."]
-    33 [label="Louisville"]
-    34 [label="Tennessee"]
-    41 [label="North Carolina"]
-    42 [label="Louisville"]
-    51 [label="North Carolina"]
-    // Use the custom 'fork horizontal' to path defined above
-    edge [topath="fork horizontal"];
-    11:e->21:w
-    12:e->21:w
-    13:e->22:w
-    14:e->22:w
-    15:e->23:w
-    16:e->23:w
-    17:e->24:w
-    18:e->24:w
-    19:e->25:w
-    110:e->25:w
-    111:e->26:w
-    112:e->26:w
-    113:e->27:w
-    114:e->27:w
-    115:e->28:w
-    116:e->28:w
-    21:e->31:w
-    22:e->31:w
-    23:e->32:w
-    24:e->32:w
-    25:e->33:w
-    26:e->33:w
-    27:e->34:w
-    28:e->34:w
-    31:e->41:w
-    32:e->41:w
-    33:e->42:w
-    34:e->42:w
-    41:e->51:w
-    42:e->51:w
-    
-    edge [style=invis]
-    rank=same {11->12->13->14->15->16->17->18->19->110->111->112->113->114->115->116}
-}
+/*
+
+:Title: Orthogonal edges
+:Tags: PGF, topath
+
+
+This example is adapted from an example posted by Ryan Schmidt to the `graphviz-interest`_ mailing
+list. Graphviz currently does not support orthogonal edges. However,
+with dot2tex you can use the ``topath``  attribute to create custom edges. 
+
+Here is the definition of the ``fork horizontal`` to-path. It uses the powerful 
+*coordinate calculations* feature introduced in PGF 2.00. 
+
+.. sourcecode:: latex
+    
+    ...
+    \usetikzlibrary{calc}
+    ...
+    \tikzstyle{fork horizontal} =[to path={
+    -| ($(\tikztostart)!0.5!(\tikztotarget)$) |- (\tikztotarget) \tikztonodes}]
+
+
+**Note**: This example requires PGF 2.00 or later. 
+
+Generated with::
+
+ $ dot2tex --crop sportsbracket.dot > sportsbracket.tex
+
+.. _graphviz-interest: https://mailman.research.att.com/pipermail/graphviz-interest/2008q2/thread.html#5129 
+
+*/
+digraph G {
+    // Put our custom fork horizontal to path in the document preamble
+    d2tdocpreamble = "\usetikzlibrary{calc}\
+\tikzstyle{fork horizontal} =[to path={\
+-| ($(\tikztostart)!0.5!(\tikztotarget)$) |- (\tikztotarget) \tikztonodes}]";
+    rankdir=LR
+    node [shape=box, width=2]
+    
+    graph [size="8.5,11" label="NCAA Men's Basketball: 2008 Tournament"]
+    
+    11 [label="North Carolina"]
+    12 [label="Mount St. Mary's"]
+    13 [label="Indiana"]
+    14 [label="Arkansas"]
+    15 [label="Notre Dame"]
+    16 [label="George Mason"]
+    17 [label="Washington St."]
+    18 [label="Winthrop"]
+    19 [label="Oklahoma"]
+    110 [label="St. Joseph's"]
+    111 [label="Louisville"]
+    112 [label="Boise St."]
+    113 [label="Butler"]
+    114 [label="South Alabama"]
+    115 [label="Tennessee"]
+    116 [label="American"]
+    21 [label="North Carolina"]
+    22 [label="Arkansas"]
+    23 [label="Notre Dame"]
+    24 [label="Washington St."]
+    25 [label="Oklahoma"]
+    26 [label="Louisville"]
+    27 [label="Butler"]
+    28 [label="Tennessee"]
+    31 [label="North Carolina"]
+    32 [label="Washington St."]
+    33 [label="Louisville"]
+    34 [label="Tennessee"]
+    41 [label="North Carolina"]
+    42 [label="Louisville"]
+    51 [label="North Carolina"]
+    // Use the custom 'fork horizontal' to path defined above
+    edge [topath="fork horizontal"];
+    11:e->21:w
+    12:e->21:w
+    13:e->22:w
+    14:e->22:w
+    15:e->23:w
+    16:e->23:w
+    17:e->24:w
+    18:e->24:w
+    19:e->25:w
+    110:e->25:w
+    111:e->26:w
+    112:e->26:w
+    113:e->27:w
+    114:e->27:w
+    115:e->28:w
+    116:e->28:w
+    21:e->31:w
+    22:e->31:w
+    23:e->32:w
+    24:e->32:w
+    25:e->33:w
+    26:e->33:w
+    27:e->34:w
+    28:e->34:w
+    31:e->41:w
+    32:e->41:w
+    33:e->42:w
+    34:e->42:w
+    41:e->51:w
+    42:e->51:w
+    
+    edge [style=invis]
+    rank=same {11->12->13->14->15->16->17->18->19->110->111->112->113->114->115->116}
+}
diff --git a/examples/subgraphs.dot b/examples/subgraphs.dot
index 7c3873b..bc6cf03 100644
--- a/examples/subgraphs.dot
+++ b/examples/subgraphs.dot
@@ -1,47 +1,47 @@
-/*
-:Title: Styled subgraphs
-:Tags: PGF, Preproc
-
-This example shows how subgraphs can be styled using PGF/TikZ styles.
-Note that version 1.09 or higher of PGF/TikZ is required. 
-
-Generated with::
-
-    $ dot2tex -tmath --autosize --crop subgraphs.dot > subgraphs.tex
-
-*/
-digraph G {
-	d2tdocpreamble="\usetikzlibrary{patterns}";
-	size="6,6";
-	node [style="fill=blue!40"];
-	node [shape=circle, width=0.4];
-	a -> b -> c;
-	graph [style="rounded corners, shade"];
-	
-	subgraph cluster0 {
-		graph [style="pattern color=red, pattern=bricks, rounded corners"];
-		node [style = "fill=blue, semitransparent"];
-		x_0 -> y_0;
-		x_0 -> z_0;
-	}
-
-	subgraph cluster1 {
-		graph [style="snake=snake, fill=green!20"];
-		node [style = "fill=red!20"];
-		edge [style="->>"];
-		x_1 -> y_1;
-		x_1 -> z_1;
-	}
-
-	subgraph cluster2 {
-	    node [style=" "];
-		x_2 -> y_2;
-		x_2 -> z_2;
-	}
-
-	a -> x_0;
-	b -> x_1;
-	b -> x_2;
-	a -> z_2;
-	c -> z_1;
-}
+/*
+:Title: Styled subgraphs
+:Tags: PGF, Preproc
+
+This example shows how subgraphs can be styled using PGF/TikZ styles.
+Note that version 1.09 or higher of PGF/TikZ is required. 
+
+Generated with::
+
+    $ dot2tex -tmath --autosize --crop subgraphs.dot > subgraphs.tex
+
+*/
+digraph G {
+	d2tdocpreamble="\usetikzlibrary{patterns}";
+	size="6,6";
+	node [style="fill=blue!40"];
+	node [shape=circle, width=0.4];
+	a -> b -> c;
+	graph [style="rounded corners, shade"];
+	
+	subgraph cluster0 {
+		graph [style="pattern color=red, pattern=bricks, rounded corners"];
+		node [style = "fill=blue, semitransparent"];
+		x_0 -> y_0;
+		x_0 -> z_0;
+	}
+
+	subgraph cluster1 {
+		graph [style="snake=snake, fill=green!20"];
+		node [style = "fill=red!20"];
+		edge [style="->>"];
+		x_1 -> y_1;
+		x_1 -> z_1;
+	}
+
+	subgraph cluster2 {
+	    node [style=" "];
+		x_2 -> y_2;
+		x_2 -> z_2;
+	}
+
+	a -> x_0;
+	b -> x_1;
+	b -> x_2;
+	a -> z_2;
+	c -> z_1;
+}
diff --git a/examples/tikzautomata.dot b/examples/tikzautomata.dot
index 742b63d..e1d8122 100644
--- a/examples/tikzautomata.dot
+++ b/examples/tikzautomata.dot
@@ -1,34 +1,34 @@
-/*
-
-:Title: Automata
-:Tags: TikZ, topath, tikzedgelabels
-
-An example of how to use TikZ' automata libray and to paths to
-create a pretty state machine. 
-
-Generated with::
-
-	$ neato -Txdot tikzautomata.dot | dot2tex -ftikz > tikzautomata.tex
-
-*/
-digraph G {
-    d2ttikzedgelabels = true;
-    d2tstyleonly = true;
-    d2tdocpreamble = "\usetikzlibrary{automata}";
-    d2tfigpreamble = "\tikzstyle{every state}= \
-    [draw=blue!50,very thick,fill=blue!20]";
-    node [style="state"];
-    edge [lblstyle="auto",topath="bend left"];
-    A [style="state, initial"];
-    A -> B [label=2];
-    A -> D [label=7];
-    B -> A [label=1];
-    B -> B [label=3,topath="loop above"];
-    B -> C [label=4];
-    C -> F [label=5];
-    F -> B [label=8];
-    F -> D [label=7];
-    D -> E [label=2];
-    E -> A [label="1,6"];
-    F [style="state,accepting"];
+/*
+
+:Title: Automata
+:Tags: TikZ, topath, tikzedgelabels
+
+An example of how to use TikZ' automata libray and to paths to
+create a pretty state machine. 
+
+Generated with::
+
+	$ neato -Txdot tikzautomata.dot | dot2tex -ftikz > tikzautomata.tex
+
+*/
+digraph G {
+    d2ttikzedgelabels = true;
+    d2tstyleonly = true;
+    d2tdocpreamble = "\usetikzlibrary{automata}";
+    d2tfigpreamble = "\tikzstyle{every state}= \
+    [draw=blue!50,very thick,fill=blue!20]";
+    node [style="state"];
+    edge [lblstyle="auto",topath="bend left"];
+    A [style="state, initial"];
+    A -> B [label=2];
+    A -> D [label=7];
+    B -> A [label=1];
+    B -> B [label=3,topath="loop above"];
+    B -> C [label=4];
+    C -> F [label=5];
+    F -> B [label=8];
+    F -> D [label=7];
+    D -> E [label=2];
+    E -> A [label="1,6"];
+    F [style="state,accepting"];
 }
\ No newline at end of file
diff --git a/examples/tikzshapes.dot b/examples/tikzshapes.dot
index 95ed3a4..b18e56b 100644
--- a/examples/tikzshapes.dot
+++ b/examples/tikzshapes.dot
@@ -1,38 +1,38 @@
-/*
-
-:Title: TikZ node shapes
-:Tags: TikZ, tikzedgelabels
-
-This example shows some of special `TikZ node shapes`_ that are available when using
-the ``tikz`` output format.
-
-Generated with::
-
- $ dot2tex -ftikz --prog circo -s tikzshapes.dot > tikzshapes.tex
-
-
-.. _TikZ node shapes: http://www.fauskes.net/pgftikzexamples/node-shapes/
-
-*/
-graph G {
-	graph [mindist=0.5];
-	node [style="fill=green!20",texmode=math];
-	edge [lblstyle="above,sloped"];
-	d2ttikzedgelabels=true;
-	c [style=circle];
-	n_1 [lblstyle=diamond];
-	n_2 [lblstyle=star];
-	n_3 [lblstyle="forbidden sign"];
-	n_4 [lblstyle="circle split", texlbl="$n$ \nodepart{lower} $4$"];
-	n_5 [lblstyle="cross out"];
-	n_6 [lblstyle="strike out"];
-	n_7 [lblstyle="regular polygon,regular polygon sides=7"];
-	c -- n_1 [label="diamond"]; 
-	c -- n_2 [label="star"];
-	c -- n_3 [label="forbidden sign"];
-	c -- n_4 [label="circle split"];
-	c -- n_5 [label="cross out"];
-	c -- n_6 [label="strike out"];
-	c -- n_7 [label="regular polygon"];
-	c [style="fill=red!80"];
+/*
+
+:Title: TikZ node shapes
+:Tags: TikZ, tikzedgelabels
+
+This example shows some of special `TikZ node shapes`_ that are available when using
+the ``tikz`` output format.
+
+Generated with::
+
+ $ dot2tex -ftikz --prog circo -s tikzshapes.dot > tikzshapes.tex
+
+
+.. _TikZ node shapes: http://www.fauskes.net/pgftikzexamples/node-shapes/
+
+*/
+graph G {
+	graph [mindist=0.5];
+	node [style="fill=green!20",texmode=math];
+	edge [lblstyle="above,sloped"];
+	d2ttikzedgelabels=true;
+	c [style=circle];
+	n_1 [lblstyle=diamond];
+	n_2 [lblstyle=star];
+	n_3 [lblstyle="forbidden sign"];
+	n_4 [lblstyle="circle split", texlbl="$n$ \nodepart{lower} $4$"];
+	n_5 [lblstyle="cross out"];
+	n_6 [lblstyle="strike out"];
+	n_7 [lblstyle="regular polygon,regular polygon sides=7"];
+	c -- n_1 [label="diamond"]; 
+	c -- n_2 [label="star"];
+	c -- n_3 [label="forbidden sign"];
+	c -- n_4 [label="circle split"];
+	c -- n_5 [label="cross out"];
+	c -- n_6 [label="strike out"];
+	c -- n_7 [label="regular polygon"];
+	c [style="fill=red!80"];
 }
\ No newline at end of file
diff --git a/examples/transp.dot b/examples/transp.dot
index 1f0f6f5..dae2142 100644
--- a/examples/transp.dot
+++ b/examples/transp.dot
@@ -1,118 +1,118 @@
-/*
-
-:Title: Node transparency
-:Tags: PGF
-
-Example of node transparency. 
-Based on the graph on http://www.graphviz.org/Gallery/undirected/transparency.html
-
-The overlapping nodes are achieved with::
-
-    $ dot2tex --prog neato -fpgf transp.dot > transp.tex
-    
-*/
-graph G {
-	node [style=filled, fillcolor="#00ff005f"]
-	1 -- 30 [f=1];
-	1 -- 40 [f=14];
-	8 -- 46 [f=1];
-	8 -- 16 [f=18];
-	10 -- 25 [f=1];
-	10 -- 19 [f=5];
-	10 -- 33 [f=1];
-	12 -- 8 [f=1];
-	12 -- 36 [f=5];
-	12 -- 17 [f=16];
-	13 -- 38 [f=1];
-	13 -- 24 [f=19];
-	24 -- 49 [f=1];
-	24 -- 13 [f=1];
-	24 -- 47 [f=12];
-	24 -- 12 [f=19];
-	25 -- 27 [f=1];
-	25 -- 12 [f=1];
-	27 -- 12 [f=1];
-	27 -- 14 [f=8];
-	29 -- 10 [f=1];
-	29 -- 8 [f=17];
-	30 -- 24 [f=1];
-	30 -- 44 [f=15];
-	38 -- 29 [f=1];
-	38 -- 35 [f=15];
-	2 -- 42 [f=2];
-	2 -- 35 [f=3];
-	2 -- 11 [f=19];
-	14 -- 18 [f=2];
-	14 -- 24 [f=15];
-	14 -- 38 [f=18];
-	18 -- 49 [f=2];
-	18 -- 47 [f=20];
-	26 -- 41 [f=2];
-	node [style=filled fillcolor="#ff00005f"]
-	26 -- 42 [f=15];
-	31 -- 39 [f=2];
-	31 -- 47 [f=17];
-	31 -- 25 [f=14];
-	37 -- 26 [f=2];
-	37 -- 16 [f=14];
-	39 -- 50 [f=2];
-	39 -- 14 [f=2];
-	39 -- 18 [f=17];
-	39 -- 47 [f=10];
-	41 -- 31 [f=2];
-	41 -- 8 [f=16];
-	42 -- 44 [f=2];
-	42 -- 29 [f=12];
-	44 -- 37 [f=2];
-	44 -- 32 [f=15];
-	3 -- 20 [f=2];
-	3 -- 28 [f=19];
-	6 -- 45 [f=2];
-	6 -- 28 [f=10];
-	9 -- 6 [f=2];
-	9 -- 16 [f=1];
-	node [style=filled fillcolor="#0000ff5f"]
-	15 -- 16 [f=2];
-	15 -- 48 [f=2];
-	16 -- 50 [f=2];
-	16 -- 32 [f=14];
-	16 -- 39 [f=8];
-	20 -- 33 [f=2];
-	33 -- 9 [f=2];
-	33 -- 46 [f=3];
-	33 -- 48 [f=17];
-	45 -- 15 [f=2];
-	4 -- 17 [f=4];
-	4 -- 15 [f=6];
-	4 -- 12 [f=16];
-	17 -- 21 [f=4];
-	19 -- 35 [f=4];
-	19 -- 15 [f=9];
-	19 -- 43 [f=4];
-	21 -- 19 [f=4];
-	21 -- 50 [f=4];
-	23 -- 36 [f=4];
-	34 -- 23 [f=4];
-	34 -- 24 [f=11];
-	35 -- 34 [f=4];
-	35 -- 16 [f=6];
-	35 -- 18 [f=16];
-	36 -- 46 [f=4];
-	5 -- 7 [f=1];
-	5 -- 36 [f=6];
-	7 -- 32 [f=1];
-	7 -- 11 [f=2];
-	7 -- 14 [f=17];
-	11 -- 40 [f=1];
-	11 -- 50 [f=1];
-	22 -- 46 [f=1];
-	28 -- 43 [f=1];
-	28 -- 8 [f=18];
-	32 -- 28 [f=1];
-	32 -- 39 [f=13];
-	32 -- 42 [f=15];
-	40 -- 22 [f=1];
-	40 -- 47 [f=1];
-	43 -- 11 [f=1];
-	43 -- 17 [f=19];
-}
+/*
+
+:Title: Node transparency
+:Tags: PGF
+
+Example of node transparency. 
+Based on the graph on http://www.graphviz.org/Gallery/undirected/transparency.html
+
+The overlapping nodes are achieved with::
+
+    $ dot2tex --prog neato -fpgf transp.dot > transp.tex
+    
+*/
+graph G {
+	node [style=filled, fillcolor="#00ff005f"]
+	1 -- 30 [f=1];
+	1 -- 40 [f=14];
+	8 -- 46 [f=1];
+	8 -- 16 [f=18];
+	10 -- 25 [f=1];
+	10 -- 19 [f=5];
+	10 -- 33 [f=1];
+	12 -- 8 [f=1];
+	12 -- 36 [f=5];
+	12 -- 17 [f=16];
+	13 -- 38 [f=1];
+	13 -- 24 [f=19];
+	24 -- 49 [f=1];
+	24 -- 13 [f=1];
+	24 -- 47 [f=12];
+	24 -- 12 [f=19];
+	25 -- 27 [f=1];
+	25 -- 12 [f=1];
+	27 -- 12 [f=1];
+	27 -- 14 [f=8];
+	29 -- 10 [f=1];
+	29 -- 8 [f=17];
+	30 -- 24 [f=1];
+	30 -- 44 [f=15];
+	38 -- 29 [f=1];
+	38 -- 35 [f=15];
+	2 -- 42 [f=2];
+	2 -- 35 [f=3];
+	2 -- 11 [f=19];
+	14 -- 18 [f=2];
+	14 -- 24 [f=15];
+	14 -- 38 [f=18];
+	18 -- 49 [f=2];
+	18 -- 47 [f=20];
+	26 -- 41 [f=2];
+	node [style=filled fillcolor="#ff00005f"]
+	26 -- 42 [f=15];
+	31 -- 39 [f=2];
+	31 -- 47 [f=17];
+	31 -- 25 [f=14];
+	37 -- 26 [f=2];
+	37 -- 16 [f=14];
+	39 -- 50 [f=2];
+	39 -- 14 [f=2];
+	39 -- 18 [f=17];
+	39 -- 47 [f=10];
+	41 -- 31 [f=2];
+	41 -- 8 [f=16];
+	42 -- 44 [f=2];
+	42 -- 29 [f=12];
+	44 -- 37 [f=2];
+	44 -- 32 [f=15];
+	3 -- 20 [f=2];
+	3 -- 28 [f=19];
+	6 -- 45 [f=2];
+	6 -- 28 [f=10];
+	9 -- 6 [f=2];
+	9 -- 16 [f=1];
+	node [style=filled fillcolor="#0000ff5f"]
+	15 -- 16 [f=2];
+	15 -- 48 [f=2];
+	16 -- 50 [f=2];
+	16 -- 32 [f=14];
+	16 -- 39 [f=8];
+	20 -- 33 [f=2];
+	33 -- 9 [f=2];
+	33 -- 46 [f=3];
+	33 -- 48 [f=17];
+	45 -- 15 [f=2];
+	4 -- 17 [f=4];
+	4 -- 15 [f=6];
+	4 -- 12 [f=16];
+	17 -- 21 [f=4];
+	19 -- 35 [f=4];
+	19 -- 15 [f=9];
+	19 -- 43 [f=4];
+	21 -- 19 [f=4];
+	21 -- 50 [f=4];
+	23 -- 36 [f=4];
+	34 -- 23 [f=4];
+	34 -- 24 [f=11];
+	35 -- 34 [f=4];
+	35 -- 16 [f=6];
+	35 -- 18 [f=16];
+	36 -- 46 [f=4];
+	5 -- 7 [f=1];
+	5 -- 36 [f=6];
+	7 -- 32 [f=1];
+	7 -- 11 [f=2];
+	7 -- 14 [f=17];
+	11 -- 40 [f=1];
+	11 -- 50 [f=1];
+	22 -- 46 [f=1];
+	28 -- 43 [f=1];
+	28 -- 8 [f=18];
+	32 -- 28 [f=1];
+	32 -- 39 [f=13];
+	32 -- 42 [f=15];
+	40 -- 22 [f=1];
+	40 -- 47 [f=1];
+	43 -- 11 [f=1];
+	43 -- 17 [f=19];
+}
diff --git a/readme.md b/readme.md
index 13da6dc..91c3fe4 100644
--- a/readme.md
+++ b/readme.md
@@ -5,7 +5,7 @@ Copyright (C) 2006-2019 Kjell Magne Fauske
 
 License: MIT (See LICENSE for details.)
 
-Version: 2.11.3
+Version: 2.12.dev
 
 URL: https://github.com/kjellmf/dot2tex
 
@@ -21,7 +21,7 @@ Before you install dot2tex you have to have a working Python environment
 installed on your system. Dot2tex works with Python 2.7 and Python 3. In addition
 you'll need the following modules:
 
-* [pyparsing](http://pyparsing.wikispaces.com/). A recent version is required.
+* [pyparsing](https://github.com/pyparsing/pyparsing). A recent version is required.
       Older version like for instance 1.3.2 does not work with dot2tex.
 * [preview](http://www.ctan.org/tex-archive/help/Catalogue/entries/preview.html)
       A stand-alone part of the preview-latex/AUCTeX bundle.
diff --git a/setup.cfg b/setup.cfg
index 4927abe..8bfd5a1 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,4 +1,4 @@
-[egg_info]
-tag_build = 
-tag_date = 0
-
+[egg_info]
+tag_build = 
+tag_date = 0
+
diff --git a/setup.py b/setup.py
index d107eed..82508a4 100644
--- a/setup.py
+++ b/setup.py
@@ -1,12 +1,8 @@
 #!/usr/bin/env python
-
-try:
-    from setuptools import setup
-except ImportError:
-    from distutils.core import setup
+from setuptools import setup
 
 setup(name='dot2tex',
-      version='2.11.3',
+      version='2.12.dev',
       description='A Graphviz to LaTeX converter',
       long_description="""\
 The purpose of dot2tex is to give graphs generated by the graph layout tool
@@ -24,7 +20,7 @@ Graphviz_, a more LaTeX friendly look and feel. This is accomplished by:
       author='Kjell Magne Fauske',
       author_email='kjellmf@gmail.com',
       url="https://github.com/kjellmf/dot2tex",
-      py_modules=['dot2tex.dot2tex', 'dot2tex.dotparsing'],
+      packages=['dot2tex'],
       scripts=['dot2tex/dot2tex'],
       classifiers=[
           'Development Status :: 4 - Beta',
diff --git a/tests/test_dot2tex.py b/tests/test_dot2tex.py
index 74b01ed..b3d63de 100644
--- a/tests/test_dot2tex.py
+++ b/tests/test_dot2tex.py
@@ -6,7 +6,7 @@ from pyparsing import ParseException
 
 import dot2tex
 import re
-from dot2tex.dot2tex import smart_float, is_multiline_label
+from dot2tex.utils import smart_float, is_multiline_label
 
 testgraph = """
 digraph G {
@@ -219,7 +219,7 @@ class EdgeLabelsTests(unittest.TestCase):
 
 class GraphvizInterfaceTests(unittest.TestCase):
     def test_prog_options(self):
-        from dot2tex.dot2tex import create_xdot
+        from dot2tex.base import create_xdot
 
         xdot_data = create_xdot(testgraph)
         xdot_data2 = create_xdot(testgraph)
@@ -229,7 +229,7 @@ class GraphvizInterfaceTests(unittest.TestCase):
 
     def test_invalid_program(self):
         """Invoking create_xdot with an invalid prog parameter should raise an exception"""
-        from dot2tex.dot2tex import create_xdot
+        from dot2tex.base import create_xdot
         # xdot_data = create_xdot(testgraph, prog="dummy")
         self.assertRaises(NameError, create_xdot, testgraph, prog="dummy")
 
@@ -237,7 +237,7 @@ class GraphvizInterfaceTests(unittest.TestCase):
 class AutosizeTests(unittest.TestCase):
     def test__dim_extraction(self):
         """Failed to extract dimension data from logfile"""
-        from dot2tex.dot2tex import dimext
+        from dot2tex.base import dimext
 
         logdata = r"""
 ABD: EveryShipout initializing macros
@@ -296,7 +296,7 @@ Here is how much of TeX's memory you used:
     def test__dim_extraction_cygwin(self):
         """Failed to extract dimension data from logfile generated under Cygwin"""
         # issue [14] http://code.google.com/p/dot2tex/issues/detail?id=14
-        from dot2tex.dot2tex import dimext
+        from dot2tex.base import dimext
 
         logdata = r"""
 Preview: Fontsize 10pt
@@ -385,7 +385,13 @@ class TestBugs(unittest.TestCase):
         self.assertTrue('HEADLABEL' in code)
         self.assertTrue('LABEL' in code)
         self.assertTrue('TAILLABEL' in code)
-
+    
+    # https://github.com/kjellmf/dot2tex/issues/92
+    def test_newline_in_num_list(self):
+        """Test for issue 92, newlines in number lists cause `ValueError`s in smart_float"""        
+        graph = 'strict digraph "" {\n\tgraph [bb="0,0,945,1116"];\n\tnode [label="\\N"];\n\t0\t[height=0.5,\n\t\tpos="99,1026",\n\t\twidth=0.75];\n\t16\t[height=0.5,\n\t\tpos="94,954",\n\t\twidth=0.75];\n\t0 -> 16\t[pos="e,95.222,972.1 97.764,1007.7 97.213,999.98 96.551,990.71 95.937,982.11"];\n\t1\t[height=0.5,\n\t\tpos="144,882",\n\t\twidth=0.75];\n\t16 -> 1\t[pos="e,132.93,898.49 105.1,937.46 111.51,928.49 119.7,917.02 126.92,906.92"];\n\t17\t[height=0.5,\n\t\tpos="144,810",\n\t\twidth=0.75];\n\t1 -> 17\t[pos="e,144,828.1 144,863.7 144,855.98 144,846.71 144,838.11"];\n\t3\t[height=0.5,\n\t\tpos="369,738",\n\t\twidth=0.75];\n\t17 -> 3\t[pos="e,345.09,746.44 168.08,801.51 208.34,788.98 289.42,763.76 335.32,749.48"];\n\t18\t[height=0.5,\n\t\tpos="551,666",\n\t\twidth=0.75];\n\t3 -> 18\t[pos="e,528.14,675.79 392.05,728.13 424.05,715.83 482.1,693.5 518.49,679.51"];\n\t29\t[height=0.5,\n\t\tpos="550,522",\n\t\twidth=0.75];\n\t3 -> 29\t[pos="e,537.29,538.03 381.73,721.95 412.95,685.04 493.48,589.82 530.66,545.86"];\n\t55\t[height=0.5,\n\t\tpos="292,522",\n\t\twidth=0.75];\n\t3 -> 55\t[pos="e,298.01,539.71 362.96,720.21 349.6,683.09 317.5,593.86 301.45,549.27"];\n\t2\t[height=0.5,\n\t\tpos="204,378",\n\t\twidth=0.75];\n\t2 -> 16\t[pos="e,93.012,935.96 184.49,390.77 151.68,412.22 89,461.04 89,521 89,811 89,811 89,811 89,851.03 91.009,897.37 92.48,925.93"];\n\t5\t[height=0.5,\n\t\tpos="551,594",\n\t\twidth=0.75];\n\t18 -> 5\t[pos="e,551,612.1 551,647.7 551,639.98 551,630.71 551,622.11"];\n\t28\t[height=0.5,\n\t\tpos="808,450",\n\t\twidth=0.75];\n\t29 -> 28\t[pos="e,783.34,457.69 574.74,514.29 620.97,501.74 720.57,474.72 773.42,460.38"];\n\t57\t[height=0.5,\n\t\tpos="550,450",\n\t\twidth=0.75];\n\t29 -> 57\t[pos="e,550,468.1 550,503.7 550,495.98 550,486.71 550,478.11"];\n\t25\t[height=0.5,\n\t\tpos="264,450",\n\t\twidth=0.75];\n\t55 -> 25\t[pos="e,270.59,467.47 285.36,504.41 282.09,496.22 278.06,486.14 274.38,476.95"];\n\t26\t[height=0.5,\n\t\tpos="350,450",\n\t\twidth=0.75];\n\t55 -> 26\t[pos="e,337.44,466.16 304.59,505.81 312.26,496.55 322.23,484.52 330.86,474.09"];\n\t5 -> 29\t[pos="e,550.24,540.1 550.75,575.7 550.64,567.98 550.51,558.71 550.39,550.11"];\n\t19\t[height=0.5,\n\t\tpos="660,522",\n\t\twidth=0.75];\n\t5 -> 19\t[pos="e,641.23,535.05 569.99,580.81 587.34,569.67 613.19,553.06 632.74,540.5"];\n\t21\t[height=0.5,\n\t\tpos="660,378",\n\t\twidth=0.75];\n\t5 -> 21\t[pos="e,647.84,394.57 562.79,577.38 570.15,567.13 579.43,553.23 586,540 608.63,494.43 601.07,477.42 624,432 629.04,422.02 635.67,411.71 \\\r\n\\\n641.86,402.86"];\n\t56\t[height=0.5,\n\t\tpos="364,522",\n\t\twidth=0.75];\n\t5 -> 56\t[pos="e,387.12,531.65 528.07,584.42 495.12,572.08 434.23,549.29 396.61,535.21"];\n\t49\t[height=0.5,\n\t\tpos="808,378",\n\t\twidth=0.75];\n\t28 -> 49\t[pos="e,802.12,395.96 802.16,432.41 801.3,424.51 801.05,414.85 801.41,405.94"];\n\t25 -> 2\t[pos="e,216.99,394.16 250.98,433.81 242.96,424.45 232.53,412.28 223.53,401.79"];\n\t12\t[height=0.5,\n\t\tpos="350,378",\n\t\twidth=0.75];\n\t26 -> 12\t[pos="e,350,396.1 350,431.7 350,423.98 350,414.71 350,406.11"];\n\t4\t[height=0.5,\n\t\tpos="564,738",\n\t\twidth=0.75];\n\t4 -> 18\t[pos="e,554.21,684.28 560.85,720.05 559.42,712.35 557.69,703.03 556.08,694.36"];\n\t4 -> 28\t[pos="e,795.84,466.57 585.84,727.23 606.21,717.63 636.98,701.86 661,684 697.57,656.81 709.59,650.48 734,612 761.26,569.03 749.07,549.42 \\\r\n\\\n772,504 777.04,494.02 783.67,483.71 789.86,474.86"];\n\t49 -> 28\t[pos="e,813.84,432.41 813.88,395.96 814.71,403.83 814.95,413.37 814.58,422.19"];\n\t6\t[height=0.5,\n\t\tpos="660,450",\n\t\twidth=0.75];\n\t19 -> 6\t[pos="e,660,468.1 660,503.7 660,495.98 660,486.71 660,478.11"];\n\t7\t[height=0.5,\n\t\tpos="715,306",\n\t\twidth=0.75];\n\t21 -> 7\t[pos="e,698.8,320.65 667.19,360.41 673.67,350.84 683.06,338.7 691.9,328.42"];\n\t56 -> 25\t[pos="e,282.06,463.64 346.12,508.49 330.72,497.7 308.26,481.98 290.72,469.7"];\n\t56 -> 26\t[pos="e,353.46,468.28 360.61,504.05 359.07,496.35 357.21,487.03 355.47,478.36"];\n\t6 -> 21\t[pos="e,660,396.1 660,431.7 660,423.98 660,414.71 660,406.11"];\n\t20\t[height=0.5,\n\t\tpos="605,234",\n\t\twidth=0.75];\n\t6 -> 20\t[pos="e,604.4,252.07 646.81,433.88 638.83,423.83 629.21,409.97 624,396 607.3,351.22 604.39,295.01 604.33,262.24"];\n\t7 -> 19\t[pos="e,673.19,505.88 715.6,324.07 716.09,354.16 714.59,418.16 696,468 692.09,478.47 685.7,488.89 679.39,497.68"];\n\t7 -> 21\t[pos="e,676.06,363.5 707.93,323.41 701.36,333.14 691.75,345.55 682.75,355.99"];\n\t7 -> 20\t[pos="e,623.94,247.05 695.84,292.81 678.33,281.67 652.24,265.06 632.51,252.5"];\n\t39\t[height=0.5,\n\t\tpos="715,90",\n\t\twidth=0.75];\n\t7 -> 39\t[pos="e,711.14,107.94 711.12,287.85 707.58,250.74 707.31,162.75 710.33,118.05"];\n\t40\t[height=0.5,\n\t\tpos="779,234",\n\t\twidth=0.75];\n\t7 -> 40\t[pos="e,765.45,249.82 728.57,290.15 737.31,280.6 748.83,267.99 758.66,257.25"];\n\t9\t[height=0.5,\n\t\tpos="647,162",\n\t\twidth=0.75];\n\t20 -> 9\t[pos="e,637.22,179.31 614.53,217.12 619.67,208.56 626.12,197.8 631.92,188.13"];\n\t9 -> 21\t[pos="e,658.96,359.85 648.05,180.23 650.3,217.32 655.63,304.98 658.34,349.71"];\n\t9 -> 39\t[pos="e,700.93,105.49 661.09,146.5 670.57,136.73 683.24,123.69 693.92,112.7"];\n\t34\t[height=0.5,\n\t\tpos="643,90",\n\t\twidth=0.75];\n\t9 -> 34\t[pos="e,643.98,108.1 646.01,143.7 645.57,135.98 645.04,126.71 644.55,118.11"];\n\t39 -> 7\t[pos="e,718.88,287.85 718.86,107.94 722.41,144.85 722.69,232.83 719.69,277.69"];\n\t8\t[height=0.5,\n\t\tpos="27,1026",\n\t\twidth=0.75];\n\t8 -> 16\t[pos="e,80.135,969.49 40.882,1010.5 50.135,1000.8 62.471,987.94 72.926,977.02"];\n\t35\t[height=0.5,\n\t\tpos="535,18",\n\t\twidth=0.75];\n\t34 -> 35\t[pos="e,553.6,31.053 624.19,76.807 607,65.665 581.38,49.062 562.01,36.504"];\n\t36\t[height=0.5,\n\t\tpos="607,18",\n\t\twidth=0.75];\n\t34 -> 36\t[pos="e,615.3,35.147 634.65,72.765 630.29,64.283 624.85,53.714 619.96,44.197"];\n\t37\t[height=0.5,\n\t\tpos="679,18",\n\t\twidth=0.75];\n\t34 -> 37\t[pos="e,670.7,35.147 651.35,72.765 655.71,64.283 661.15,53.714 666.04,44.197"];\n\t38\t[height=0.5,\n\t\tpos="751,18",\n\t\twidth=0.75];\n\t34 -> 38\t[pos="e,732.4,31.053 661.81,76.807 679,65.665 704.62,49.062 723.99,36.504"];\n\t10\t[height=0.5,\n\t\tpos="560,882",\n\t\twidth=0.75];\n\t22\t[height=0.5,\n\t\tpos="488,810",\n\t\twidth=0.75];\n\t10 -> 22\t[pos="e,502.8,825.38 545.43,866.83 535.25,856.94 521.48,843.55 509.97,832.36"];\n\t41\t[height=0.5,\n\t\tpos="560,810",\n\t\twidth=0.75];\n\t10 -> 41\t[pos="e,560,828.1 560,863.7 560,855.98 560,846.71 560,838.11"];\n\t22 -> 4\t[pos="e,548.64,753.14 503.38,794.83 514.2,784.87 528.86,771.37 541.05,760.14"];\n\t11\t[height=0.5,\n\t\tpos="488,882",\n\t\twidth=0.75];\n\t11 -> 22\t[pos="e,488,828.1 488,863.7 488,855.98 488,846.71 488,838.11"];\n\t12 -> 17\t[pos="e,145.78,791.97 324.65,384.61 271.44,398.03 153,437.31 153,521 153,667 153,667 153,667 153,707.08 149.38,753.41 146.74,781.95"];\n\t13\t[height=0.5,\n\t\tpos="626,594",\n\t\twidth=0.75];\n\t13 -> 19\t[pos="e,651.92,539.63 633.89,576.76 637.9,568.49 642.89,558.23 647.42,548.9"];\n\t14\t[height=0.5,\n\t\tpos="523,306",\n\t\twidth=0.75];\n\t14 -> 20\t[pos="e,589.11,248.56 539.2,291.17 551.18,280.94 567.69,266.85 581.18,255.34"];\n\t15\t[height=0.5,\n\t\tpos="698,594",\n\t\twidth=0.75];\n\t15 -> 21\t[pos="e,673.69,393.95 700.92,576.05 705.38,546.14 711.84,482.4 696,432 692.65,421.34 686.38,410.88 680,402.1"];\n\t23\t[height=0.5,\n\t\tpos="397,954",\n\t\twidth=0.75];\n\t33\t[height=0.5,\n\t\tpos="389,810",\n\t\twidth=0.75];\n\t23 -> 33\t[pos="e,384.75,827.8 390.11,936.14 386.3,925.88 381.94,912.41 380,900 376.76,879.29 379.44,855.67 382.7,837.98"];\n\t42\t[height=0.5,\n\t\tpos="416,882",\n\t\twidth=0.75];\n\t23 -> 42\t[pos="e,411.44,899.79 401.6,936.05 403.75,928.14 406.35,918.54 408.76,909.69"];\n\t30\t[height=0.5,\n\t\tpos="625,666",\n\t\twidth=0.75];\n\t33 -> 30\t[pos="e,604.33,677.76 407.63,796.49 434.06,778.87 484.12,746 528,720 550.28,706.8 576.02,692.8 595.38,682.5"];\n\t42 -> 22\t[pos="e,473.2,825.38 430.57,866.83 440.75,856.94 454.52,843.55 466.03,832.36"];\n\t42 -> 33\t[pos="e,395.54,827.96 409.6,864.41 406.49,856.34 402.67,846.43 399.17,837.35"];\n\t30 -> 26\t[pos="e,366.09,465.02 603.56,654.62 598.22,652.26 592.46,649.89 587,648 524.65,626.45 492.66,655.42 443,612 404.1,577.99 427.78,547.56 \\\r\n\\\n400,504 392.67,492.5 382.64,481.29 373.5,472.16"];\n\t30 -> 12\t[pos="e,361.18,394.47 603.45,654.94 598.11,652.56 592.38,650.11 587,648 540.69,629.82 518.85,644.29 481,612 463.8,597.32 397.65,451.38 \\\r\n\\\n386,432 380.16,422.28 373.25,411.89 367.06,402.91"];\n\t30 -> 13\t[pos="e,625.76,612.1 625.25,647.7 625.36,639.98 625.49,630.71 625.61,622.11"];\n\t30 -> 14\t[pos="e,517.47,323.84 603.23,655.1 572.03,640.83 517.99,615.77 515,612 489.78,580.26 495,563.54 495,523 495,523 495,523 495,449 495,408.23 \\\r\n\\\n506.25,362.09 514.49,333.77"];\n\t30 -> 15\t[pos="e,683.25,609.14 639.77,650.83 650.16,640.87 664.24,627.37 675.96,616.14"];\n\t24\t[height=0.5,\n\t\tpos="253,1026",\n\t\twidth=0.75];\n\t24 -> 25\t[pos="e,258.67,467.85 249.84,1008 245.18,981.45 237,928.4 237,883 237,883 237,883 237,593 237,552.28 247.85,506.13 255.79,477.79"];\n\t32\t[height=0.5,\n\t\tpos="632,954",\n\t\twidth=0.75];\n\t24 -> 32\t[pos="e,611.47,965.94 279.83,1023.5 338.4,1019.6 481.64,1007 596,972 597.93,971.41 599.89,970.73 601.85,969.99"];\n\t46\t[height=0.5,\n\t\tpos="182,954",\n\t\twidth=0.75];\n\t24 -> 46\t[pos="e,196.69,969.49 238.29,1010.5 228.39,1000.7 215.16,987.69 204.01,976.7"];\n\t51\t[height=0.5,\n\t\tpos="918,738",\n\t\twidth=0.75];\n\t24 -> 51\t[pos="e,912,755.86 280.36,1024.7 347.76,1023.1 526.59,1015 668,972 736.46,951.17 755.04,943.31 812,900 846.32,873.91 853.27,863.99 877,\\\r\n\\\n828 890.04,808.23 901.02,783.64 908.33,765.32"];\n\t31\t[height=0.5,\n\t\tpos="632,882",\n\t\twidth=0.75];\n\t32 -> 31\t[pos="e,632,900.1 632,935.7 632,927.98 632,918.71 632,910.11"];\n\t46 -> 26\t[pos="e,327.07,459.95 185.36,936.03 190.31,909.48 199,856.44 199,811 199,811 199,811 199,593 199,528.29 273.49,484.43 317.83,464.05"];\n\t51 -> 28\t[pos="e,820.3,466.5 914.38,719.98 905.63,680.61 881.27,580.74 844,504 839.12,493.94 832.52,483.62 826.31,474.78"];\n\t31 -> 30\t[pos="e,625.56,684.23 631.44,863.85 630.23,826.83 627.36,739.18 625.9,694.39"];\n\t27\t[height=0.5,\n\t\tpos="693,810",\n\t\twidth=0.75];\n\t31 -> 27\t[pos="e,680.08,825.82 644.94,866.15 653.19,856.69 664.04,844.24 673.34,833.56"];\n\t27 -> 4\t[pos="e,584.34,750.04 672.56,797.91 651.24,786.34 617.6,768.09 593.42,754.97"];\n\t43\t[height=0.5,\n\t\tpos="252,1098",\n\t\twidth=0.75];\n\t43 -> 24\t[pos="e,252.76,1044.1 252.25,1079.7 252.36,1072 252.49,1062.7 252.61,1054.1"];\n\t44\t[height=0.5,\n\t\tpos="180,1098",\n\t\twidth=0.75];\n\t44 -> 24\t[pos="e,238.25,1041.1 194.77,1082.8 205.16,1072.9 219.24,1059.4 230.96,1048.1"];\n\t45\t[height=0.5,\n\t\tpos="324,1098",\n\t\twidth=0.75];\n\t45 -> 33\t[pos="e,383.85,828.11 327.27,1080 334.75,1041.3 354.04,944.3 374,864 376.13,855.42 378.68,846.13 381.06,837.76"];\n\t45 -> 24\t[pos="e,267.69,1041.5 309.29,1082.5 299.39,1072.7 286.16,1059.7 275.01,1048.7"];\n\t47\t[height=0.5,\n\t\tpos="776,882",\n\t\twidth=0.75];\n\t47 -> 39\t[pos="e,737.48,100.08 791.96,867.02 817.07,843.37 863,792.78 863,739 863,739 863,739 863,233 863,169.11 790.29,125.02 746.8,104.36"];\n\t47 -> 30\t[pos="e,638.88,681.59 768.64,864.67 760.11,846.37 745.14,816.1 729,792 703.32,753.64 668.02,713.29 645.86,689.14"];\n\t47 -> 27\t[pos="e,709.08,824.56 759.6,867.17 747.36,856.85 730.45,842.58 716.73,831.01"];\n\t48\t[height=0.5,\n\t\tpos="704,882",\n\t\twidth=0.75];\n\t48 -> 27\t[pos="e,695.71,828.28 701.34,864.05 700.13,856.35 698.66,847.03 697.3,838.36"];\n\t50\t[height=0.5,\n\t\tpos="808,522",\n\t\twidth=0.75];\n\t50 -> 28\t[pos="e,808,468.1 808,503.7 808,495.98 808,486.71 808,478.11"];\n\t52\t[height=0.5,\n\t\tpos="560,954",\n\t\twidth=0.75];\n\t52 -> 31\t[pos="e,617.2,897.38 574.57,938.83 584.75,928.94 598.52,915.55 610.03,904.36"];\n\t53\t[height=0.5,\n\t\tpos="181,1026",\n\t\twidth=0.75];\n\t53 -> 46\t[pos="e,181.76,972.1 181.25,1007.7 181.36,999.98 181.49,990.71 181.61,982.11"];\n\t54\t[height=0.5,\n\t\tpos="488,954",\n\t\twidth=0.75];\n\t54 -> 11\t[pos="e,488,900.1 488,935.7 488,927.98 488,918.71 488,910.11"];\n}\n'
+        #'digraph { a->b [pos="e,1973.5,1067.3 1048.5,\\\r\n\\\n1243.5 1613.9,1127.1 1973.3,\\\r\n1072.6"];}' # too short, doesn't work for some reason
+        code = dot2tex.dot2tex(graph)
 
 class TestNumberFormatting(unittest.TestCase):
     def test_numbers(self):
diff --git a/tests/testgraphs/autosize.dot b/tests/testgraphs/autosize.dot
index 80efc75..7e2ac4c 100644
--- a/tests/testgraphs/autosize.dot
+++ b/tests/testgraphs/autosize.dot
@@ -1,9 +1,9 @@
-digraph G {
-	d2toptions="--autosize";
-    node [shape=circle];
-    a_1 [texlbl="$x^2+\frac{\sin y}{y^2+\cos \beta}+\gamma_3$"];
-    a_1 -> a_2 [label=" ", texlbl="$x_1+x_3^2+z+c+v~~$"];
-    a_2 -> a_1;
-    a_2 -> a_3;
-    a_3 [lblstyle="minimum size=4cm"];
+digraph G {
+	d2toptions="--autosize";
+    node [shape=circle];
+    a_1 [texlbl="$x^2+\frac{\sin y}{y^2+\cos \beta}+\gamma_3$"];
+    a_1 -> a_2 [label=" ", texlbl="$x_1+x_3^2+z+c+v~~$"];
+    a_2 -> a_1;
+    a_2 -> a_3;
+    a_3 [lblstyle="minimum size=4cm"];
 }
\ No newline at end of file
diff --git a/tests/testgraphs/clust.dot b/tests/testgraphs/clust.dot
index e35418f..43c1ecc 100644
--- a/tests/testgraphs/clust.dot
+++ b/tests/testgraphs/clust.dot
@@ -1,26 +1,26 @@
-digraph G {
-	node [fontcolor=red];
-	subgraph cluster0 {
-		node [style=filled,color=white, texmode=math];
-		style=filled;
-		color=lightgrey;
-		a_0 -> a_1 -> a_2 -> a_3;
-		label="latex";
-		texlbl="\LaTeX";
-	}
-	subgraph cluster1 {
-		node [style=filled, texmode=math, fontcolor=red];
-		b_0 -> b_1 -> b_2 -> b_3;
-		label = "process #2";
-		color=blue
-	}
-	start -> a_0;
-	start -> b_0;
-	a_1 -> b_3;
-	b_2 -> a_3;
-	a_3 -> a_0;
-	a_3 -> end;
-	b_3 -> end;
-	start [shape=diamond, texlbl="${\frac{\sqrt{\gamma+\beta}}{x^2+y^2}}$"];
-	end [shape=Msquare];
+digraph G {
+	node [fontcolor=red];
+	subgraph cluster0 {
+		node [style=filled,color=white, texmode=math];
+		style=filled;
+		color=lightgrey;
+		a_0 -> a_1 -> a_2 -> a_3;
+		label="latex";
+		texlbl="\LaTeX";
+	}
+	subgraph cluster1 {
+		node [style=filled, texmode=math, fontcolor=red];
+		b_0 -> b_1 -> b_2 -> b_3;
+		label = "process #2";
+		color=blue
+	}
+	start -> a_0;
+	start -> b_0;
+	a_1 -> b_3;
+	b_2 -> a_3;
+	a_3 -> a_0;
+	a_3 -> end;
+	b_3 -> end;
+	start [shape=diamond, texlbl="${\frac{\sqrt{\gamma+\beta}}{x^2+y^2}}$"];
+	end [shape=Msquare];
 }
\ No newline at end of file
diff --git a/tests/testgraphs/colors.dot b/tests/testgraphs/colors.dot
index 17b3638..0ce64a1 100644
--- a/tests/testgraphs/colors.dot
+++ b/tests/testgraphs/colors.dot
@@ -1,17 +1,17 @@
-/* Test stroke and fill coloring */
-digraph G {
-
-a [color=red];
-b [style="filled", fillcolor=blue];
-c [style="filled", color=yellow];
-d [style=filled];
-b [style="filled", fillcolor=pink, color=green];
-f [style="filled", fillcolor="0.051 0.718 0.627",color="#40e0d0"];
-g [color="#ffff00"];
-a -> {b c d e f g};
-i -> b [color=red];
-i -> d [color="#ffff00"];
-i -> d [color="0.051 0.718 0.627"];
-
-
+/* Test stroke and fill coloring */
+digraph G {
+
+a [color=red];
+b [style="filled", fillcolor=blue];
+c [style="filled", color=yellow];
+d [style=filled];
+b [style="filled", fillcolor=pink, color=green];
+f [style="filled", fillcolor="0.051 0.718 0.627",color="#40e0d0"];
+g [color="#ffff00"];
+a -> {b c d e f g};
+i -> b [color=red];
+i -> d [color="#ffff00"];
+i -> d [color="0.051 0.718 0.627"];
+
+
 }
\ No newline at end of file
diff --git a/tests/testgraphs/compassports.dot b/tests/testgraphs/compassports.dot
index 672ef43..1c17f98 100644
--- a/tests/testgraphs/compassports.dot
+++ b/tests/testgraphs/compassports.dot
@@ -1,18 +1,18 @@
-/* Test compass points */
-digraph g {
-	graph [rankdir=LR];
-	node [shape=rectangle];
-	a [label="node A"];
-	b [label="node B"];
-	a:n ->  b:n;
-	a:ne ->  b:ne;
-	a:e ->  b:e;
-	a:se -> b:se;
-	a:s -> b:s;
-	a:sw -> b:sw;
-	a:w -> b:w;
-	a:nw -> b:nw;
-	a:center -> b:center;
-	a:dummy -> c:dummy;
-	
-}
+/* Test compass points */
+digraph g {
+	graph [rankdir=LR];
+	node [shape=rectangle];
+	a [label="node A"];
+	b [label="node B"];
+	a:n ->  b:n;
+	a:ne ->  b:ne;
+	a:e ->  b:e;
+	a:se -> b:se;
+	a:s -> b:s;
+	a:sw -> b:sw;
+	a:w -> b:w;
+	a:nw -> b:nw;
+	a:center -> b:center;
+	a:dummy -> c:dummy;
+	
+}
diff --git a/tests/testgraphs/concentrate.dot b/tests/testgraphs/concentrate.dot
index 1cacb66..d36ec7e 100644
--- a/tests/testgraphs/concentrate.dot
+++ b/tests/testgraphs/concentrate.dot
@@ -1,9 +1,9 @@
-/* Test concentrate option */
-digraph g {
-graph [rankdir=LR, concentrate=1];
-trans1 -> trans2;
-trans2 -> trans3;
-trans1 -> state1;
-trans2 -> state1;
-trans3 -> state1;
-}
+/* Test concentrate option */
+digraph g {
+graph [rankdir=LR, concentrate=1];
+trans1 -> trans2;
+trans2 -> trans3;
+trans1 -> state1;
+trans2 -> state1;
+trans3 -> state1;
+}
diff --git a/tests/testgraphs/d2topts.dot b/tests/testgraphs/d2topts.dot
index 7100a87..7ca7e54 100644
--- a/tests/testgraphs/d2topts.dot
+++ b/tests/testgraphs/d2topts.dot
@@ -1,5 +1,5 @@
-digraph G {
-	d2toptions = "-ftikz -tmath"  
-	  ;
-	a_1-> a_2 -> a_3 -> a_1;
+digraph G {
+	d2toptions = "-ftikz -tmath"  
+	  ;
+	a_1-> a_2 -> a_3 -> a_1;
 }
\ No newline at end of file
diff --git a/tests/testgraphs/dot2tikznodeshapesmapping.dot b/tests/testgraphs/dot2tikznodeshapesmapping.dot
index 210ce99..5e7ff93 100644
--- a/tests/testgraphs/dot2tikznodeshapesmapping.dot
+++ b/tests/testgraphs/dot2tikznodeshapesmapping.dot
@@ -1,36 +1,36 @@
-graph G {
-	c [shape=circle];
-	n_1 [shape=box];
-	n_2 [shape=ellipse];
-	n_3 [shape=oval];
-	n_4 [shape="point"];
-	n_5 [shape="egg"];
-	n_6 [shape="triangle"];
-	n_7 [shape="plaintext"];
-	n_8 [shape="diamond"];
-	n_9 [shape="trapezium"];
-	n_10 [shape="parallelogram"];
-	n_11 [shape="house"];
-	n_12 [shape="pentagon"];
-	n_13 [shape="hexagon"];
-	n_14 [shape="septagon"];
-    n_15 [shape="square"];
-    n_16 [shape="star"];
-	c -- n_1 [label="box"];
-	c -- n_2 [label="ellipse"];
-	c -- n_3 [label="oval"];
-	c -- n_4 [label="point"];
-	c -- n_5 [label="egg"];
-	c -- n_6 [label="triangle"];
-	c -- n_7 [label="plaintext"];
-	c -- n_8 [label="diamond"];
-	c -- n_9 [label="trapezium"];
-	c -- n_10 [label="parallelogram"];
-	c -- n_11 [label="house"];
-	c -- n_12 [label="pentagon"];
-	c -- n_13 [label="hexagon"];
-	c -- n_14 [label="septagon"];
-	c -- n_15 [label="square"];
-    c -- n_16 [label="star"];
-
+graph G {
+	c [shape=circle];
+	n_1 [shape=box];
+	n_2 [shape=ellipse];
+	n_3 [shape=oval];
+	n_4 [shape="point"];
+	n_5 [shape="egg"];
+	n_6 [shape="triangle"];
+	n_7 [shape="plaintext"];
+	n_8 [shape="diamond"];
+	n_9 [shape="trapezium"];
+	n_10 [shape="parallelogram"];
+	n_11 [shape="house"];
+	n_12 [shape="pentagon"];
+	n_13 [shape="hexagon"];
+	n_14 [shape="septagon"];
+    n_15 [shape="square"];
+    n_16 [shape="star"];
+	c -- n_1 [label="box"];
+	c -- n_2 [label="ellipse"];
+	c -- n_3 [label="oval"];
+	c -- n_4 [label="point"];
+	c -- n_5 [label="egg"];
+	c -- n_6 [label="triangle"];
+	c -- n_7 [label="plaintext"];
+	c -- n_8 [label="diamond"];
+	c -- n_9 [label="trapezium"];
+	c -- n_10 [label="parallelogram"];
+	c -- n_11 [label="house"];
+	c -- n_12 [label="pentagon"];
+	c -- n_13 [label="hexagon"];
+	c -- n_14 [label="septagon"];
+	c -- n_15 [label="square"];
+    c -- n_16 [label="star"];
+
 }
\ No newline at end of file
diff --git a/tests/testgraphs/escstr.dot b/tests/testgraphs/escstr.dot
index 8edd0f5..1e578ec 100644
--- a/tests/testgraphs/escstr.dot
+++ b/tests/testgraphs/escstr.dot
@@ -1,10 +1,10 @@
-digraph testG {
-	d2tdocpreamble="\usepackage[T1]{fontenc}\usepackage{lmodern}"; 
-	a [label="\N"];
-	b [label="\G"];
-	a -> b [label="\E"];
-	subgraph clusterA {
-		c -> f [label="\T connect \H"];
-	}
-	a -> c;
+digraph testG {
+	d2tdocpreamble="\usepackage[T1]{fontenc}\usepackage{lmodern}"; 
+	a [label="\N"];
+	b [label="\G"];
+	a -> b [label="\E"];
+	subgraph clusterA {
+		c -> f [label="\T connect \H"];
+	}
+	a -> c;
 }
\ No newline at end of file
diff --git a/tests/testgraphs/invis.dot b/tests/testgraphs/invis.dot
index 4b62793..185207c 100644
--- a/tests/testgraphs/invis.dot
+++ b/tests/testgraphs/invis.dot
@@ -1,11 +1,11 @@
-/* Test invisible edges and nodes */
-digraph G {
-a -> {
-node[style="invis"]
-b c d;
-}
-f [style="invisible"];
-a -> e [style="invisible"];
-a -> g [style="invis"];
-a -> f;
+/* Test invisible edges and nodes */
+digraph G {
+a -> {
+node[style="invis"]
+b c d;
+}
+f [style="invisible"];
+a -> e [style="invisible"];
+a -> g [style="invis"];
+a -> f;
 }
\ No newline at end of file
diff --git a/tests/testgraphs/issue.dot b/tests/testgraphs/issue.dot
deleted file mode 100644
index 111320d..0000000
--- a/tests/testgraphs/issue.dot
+++ /dev/null
@@ -1,91 +0,0 @@
-digraph G{
-    subgraph {
-        S8;
-        S24;
-        S1;
-        S35;
-        S30;
-
-        graph [rank=min,size="8,8"];
-        }    subgraph {
-        T8;
-        T24;
-        T1;
-        T35;
-        T30;
-
-        graph [rank=max,size="8,8"];
-        }    edge[style="showpoints=true, linecolor=red"];
-    node[style="fillstyle=solid"];
-    S8 -> 9 [style="showpoints=true, linecolor=red"];
-    S24 -> 27 [style="showpoints=true, linecolor=red"];
-    S24 -> 25 [style="showpoints=true, linecolor=red"];
-    S1 -> 10 [style="showpoints=true, linecolor=red"];
-    S1 -> 2 [style="showpoints=true, linecolor=red"];
-    S35 -> 36 [style="showpoints=true, linecolor=red"];
-    S35 -> 43 [style="showpoints=true, linecolor=red"];
-    S30 -> 31 [style="showpoints=true, linecolor=red"];
-    S30 -> 33 [style="showpoints=true, linecolor=red"];
-    9 -> 42 [style="showpoints=true, linecolor=red"];
-    9 -> T1 [style="showpoints=true, linecolor=red"];
-    25 -> T1 [style="showpoints=true, linecolor=red"];
-    25 -> 26 [style="showpoints=true, linecolor=red"];
-    27 -> T24 [style="showpoints=true, linecolor=red"];
-    2 -> 3 [style="showpoints=true, linecolor=red"];
-    2 -> 16 [style="showpoints=true, linecolor=red"];
-    2 -> 17 [style="showpoints=true, linecolor=red"];
-    2 -> T1 [style="showpoints=true, linecolor=red"];
-    2 -> 18 [style="showpoints=true, linecolor=red"];
-    10 -> 11 [style="showpoints=true, linecolor=red"];
-    10 -> 14 [style="showpoints=true, linecolor=red"];
-    10 -> T1 [style="showpoints=true, linecolor=red"];
-    10 -> 13 [style="showpoints=true, linecolor=red"];
-    10 -> 12 [style="showpoints=true, linecolor=red"];
-    31 -> T1 [style="showpoints=true, linecolor=red"];
-    31 -> 32 [style="showpoints=true, linecolor=red"];
-    33 -> T30 [style="showpoints=true, linecolor=red"];
-    33 -> 34 [style="showpoints=true, linecolor=red"];
-    42 -> 4 [style="showpoints=true, linecolor=red"];
-    26 -> 4 [style="showpoints=true, linecolor=red"];
-    3 -> 4 [style="showpoints=true, linecolor=red"];
-    16 -> 15 [style="showpoints=true, linecolor=red"];
-    17 -> 19 [style="showpoints=true, linecolor=red"];
-    18 -> 29 [style="showpoints=true, linecolor=red"];
-    11 -> 4 [style="showpoints=true, linecolor=red"];
-    14 -> 15 [style="showpoints=true, linecolor=red"];
-    37 -> 39 [style="showpoints=true, linecolor=red"];
-    37 -> 41 [style="showpoints=true, linecolor=red"];
-    37 -> 38 [style="showpoints=true, linecolor=red"];
-    37 -> 40 [style="showpoints=true, linecolor=red"];
-    13 -> 19 [style="showpoints=true, linecolor=red"];
-    12 -> 29 [style="showpoints=true, linecolor=red"];
-    43 -> 38 [style="showpoints=true, linecolor=red"];
-    43 -> 40 [style="showpoints=true, linecolor=red"];
-    36 -> 19 [style="showpoints=true, linecolor=red"];
-    32 -> 23 [style="showpoints=true, linecolor=red"];
-    34 -> 29 [style="showpoints=true, linecolor=red"];
-    39 -> 15 [style="showpoints=true, linecolor=red"];
-    41 -> 29 [style="showpoints=true, linecolor=red"];
-    38 -> 4 [style="showpoints=true, linecolor=red"];
-    40 -> 19 [style="showpoints=true, linecolor=red"];
-    4 -> 5 [style="showpoints=true, linecolor=red"];
-    19 -> 21 [style="showpoints=true, linecolor=red"];
-    19 -> 20 [style="showpoints=true, linecolor=red"];
-    19 -> 28 [style="showpoints=true, linecolor=red"];
-    5 -> 6 [style="showpoints=true, linecolor=red"];
-    5 -> T35 [style="showpoints=true, linecolor=red"];
-    5 -> 23 [style="showpoints=true, linecolor=red"];
-    21 -> 22 [style="showpoints=true, linecolor=red"];
-    20 -> 15 [style="showpoints=true, linecolor=red"];
-    28 -> 29 [style="showpoints=true, linecolor=red"];
-    6 -> 7 [style="showpoints=true, linecolor=red"];
-    15 -> T1 [style="showpoints=true, linecolor=red"];
-    22 -> 23 [style="showpoints=true, linecolor=red"];
-    22 -> T35 [style="showpoints=true, linecolor=red"];
-    29 -> T30 [style="showpoints=true, linecolor=red"];
-    7 -> T8 [style="showpoints=true, linecolor=red"];
-    23 -> T24 [style="showpoints=true, linecolor=red"];
-    23 -> T1 [style="showpoints=true, linecolor=red"];
-
-    graph [size="8,8"];
-}
\ No newline at end of file
diff --git a/tests/testgraphs/latin1.dot b/tests/testgraphs/latin1.dot
index e26f62a..0613da2 100644
--- a/tests/testgraphs/latin1.dot
+++ b/tests/testgraphs/latin1.dot
@@ -1,6 +1,6 @@
-digraph G {
-	graph [charset="Latin1"];
-	a -> b;
-	a [label="���"];
-	b [label="��"];
+digraph G {
+	graph [charset="Latin1"];
+	a -> b;
+	a [label="���"];
+	b [label="��"];
 }
\ No newline at end of file
diff --git a/tests/testgraphs/markup.dot b/tests/testgraphs/markup.dot
index 9da71f9..823f181 100644
--- a/tests/testgraphs/markup.dot
+++ b/tests/testgraphs/markup.dot
@@ -1,12 +1,12 @@
-digraph G {
-	a_1 [texlbl="$\frac{\gamma}{2x^2+y^3}$"];
-	a_1 -> a_2 -> a_3 -> a_1
-	node [texmode="math"];
-	a_1 -> b_1 -> b_2 -> a_3;
-	b_1 [label="\\frac{\\gamma}{x^2}"];
-	node [texmode="verbatim"]
-	b_4 [label="\\feta"] 
-	b_5 [label="\\frac"]
-	a_3 -> b_4;
-	a_1 -> b_4;
+digraph G {
+	a_1 [texlbl="$\frac{\gamma}{2x^2+y^3}$"];
+	a_1 -> a_2 -> a_3 -> a_1
+	node [texmode="math"];
+	a_1 -> b_1 -> b_2 -> a_3;
+	b_1 [label="\\frac{\\gamma}{x^2}"];
+	node [texmode="verbatim"]
+	b_4 [label="\\feta"] 
+	b_5 [label="\\frac"]
+	a_3 -> b_4;
+	a_1 -> b_4;
 }
\ No newline at end of file
diff --git a/tests/testgraphs/markup2.dot b/tests/testgraphs/markup2.dot
index cf79168..f99f7a8 100644
--- a/tests/testgraphs/markup2.dot
+++ b/tests/testgraphs/markup2.dot
@@ -1,14 +1,14 @@
-digraph G {
-Decl [ shape=record, label = "\n\nDecl|{name|access|decl_flags|extern_c_linkage}"];
-a_1 [label="$\\frac{\\gamma}{2x^2+y^3}$"];
-a_1 -> a_2 -> a_3 -> a_1
-node [texmode="math"];
-a_1 -> b_1 -> b_2 -> a_3;
-node [texmode="verbatim"]
-b_4 [label="\\feta"] 
-b_5 [label="\frac"]
-a_3 -> b_4;
-c5 -> b_4;
-a_1 -> Decl;
-
+digraph G {
+Decl [ shape=record, label = "\n\nDecl|{name|access|decl_flags|extern_c_linkage}"];
+a_1 [label="$\\frac{\\gamma}{2x^2+y^3}$"];
+a_1 -> a_2 -> a_3 -> a_1
+node [texmode="math"];
+a_1 -> b_1 -> b_2 -> a_3;
+node [texmode="verbatim"]
+b_4 [label="\\feta"] 
+b_5 [label="\frac"]
+a_3 -> b_4;
+c5 -> b_4;
+a_1 -> Decl;
+
 }
\ No newline at end of file
diff --git a/tests/testgraphs/multilines.dot b/tests/testgraphs/multilines.dot
index ecb72ac..30fc9ed 100644
--- a/tests/testgraphs/multilines.dot
+++ b/tests/testgraphs/multilines.dot
@@ -1,11 +1,11 @@
-/* Test multilineattributes and concatination */
-digraph G {
-	a [label="This is\
-a multiline\
-text", color=red
-style=filled];
-	b [label="partA"+"partB"+"partC"];
-	b [label="partA" + "partB"+
-	"partC"];	
-	a -> b -> c;
+/* Test multilineattributes and concatination */
+digraph G {
+	a [label="This is\
+a multiline\
+text", color=red
+style=filled];
+	b [label="partA"+"partB"+"partC"];
+	b [label="partA" + "partB"+
+	"partC"];	
+	a -> b -> c;
 }
\ No newline at end of file
diff --git a/tests/testgraphs/nodenames.dot b/tests/testgraphs/nodenames.dot
index 9a9bc9a..debd2e5 100644
--- a/tests/testgraphs/nodenames.dot
+++ b/tests/testgraphs/nodenames.dot
@@ -1,11 +1,11 @@
-/* Test various tikz-unfriendly node names */
-
-digraph G {
-	"" -> {a b c};
-	{e f g} -> " ";
-	"a,b" -> c;
-	"a.b" -> c;
-	"a:b" -> c;
-	"\\a:b" -> c;
-	a [label="\\a"];
+/* Test various tikz-unfriendly node names */
+
+digraph G {
+	"" -> {a b c};
+	{e f g} -> " ";
+	"a,b" -> c;
+	"a.b" -> c;
+	"a:b" -> c;
+	"\\a:b" -> c;
+	a [label="\\a"];
 }
\ No newline at end of file
diff --git a/tests/testgraphs/parsetests/multilines.dot b/tests/testgraphs/parsetests/multilines.dot
index 04ec9c6..8a30741 100644
--- a/tests/testgraphs/parsetests/multilines.dot
+++ b/tests/testgraphs/parsetests/multilines.dot
@@ -1,13 +1,13 @@
-/* Test line joining and multiline stuff*/
-digraph G {
-	a [label="partA"+"partB"];
-	b [label="Line1\
-line2\
-line3"];
-	d [label="Test",
-		color=red,
-		style=filled];
-e [shape = record,label="\n\nDecl|{name|access|decl_flags|extern_c_linkage}"];
-f [label="Line1\lLine2\rLine3\nLine4",width=2];
-	a -> b -> c -> d -> e -> f;
+/* Test line joining and multiline stuff*/
+digraph G {
+	a [label="partA"+"partB"];
+	b [label="Line1\
+line2\
+line3"];
+	d [label="Test",
+		color=red,
+		style=filled];
+e [shape = record,label="\n\nDecl|{name|access|decl_flags|extern_c_linkage}"];
+f [label="Line1\lLine2\rLine3\nLine4",width=2];
+	a -> b -> c -> d -> e -> f;
 }
\ No newline at end of file
diff --git a/tests/testgraphs/parsetests/subgraphs.dot b/tests/testgraphs/parsetests/subgraphs.dot
index 87e8f8e..06f0d80 100644
--- a/tests/testgraphs/parsetests/subgraphs.dot
+++ b/tests/testgraphs/parsetests/subgraphs.dot
@@ -1,10 +1,10 @@
-/* Test subgraphs */
-digraph G {
-	a -> {
-		c; d; e;
-	}
-	subgraph clusterA {
-		f;g;h;
-	} -> a;
-	{i; j; k} -> {s;t;m};
+/* Test subgraphs */
+digraph G {
+	a -> {
+		c; d; e;
+	}
+	subgraph clusterA {
+		f;g;h;
+	} -> a;
+	{i; j; k} -> {s;t;m};
 }
\ No newline at end of file
diff --git a/tests/testgraphs/pststyles.dot b/tests/testgraphs/pststyles.dot
index 53377ed..7f7bcd8 100644
--- a/tests/testgraphs/pststyles.dot
+++ b/tests/testgraphs/pststyles.dot
@@ -1,8 +1,8 @@
-graph G {
-	node [shape=circle, texmode=math, fixedsize=True, width="0.4", style="filled, shadow=true", color="blue"];
-	edge [style="linecolor=green, showpoints=true,dotstyle=triangle"];
-	a_1-- a_2 -- a_3 -- a_1;
-	node [shape=box, style="shadow=true", label=""];
-	edge [style="linecolor=red, shadow=true"];
-	b_1 -- b_2 -- a_2;
+graph G {
+	node [shape=circle, texmode=math, fixedsize=True, width="0.4", style="filled, shadow=true", color="blue"];
+	edge [style="linecolor=green, showpoints=true,dotstyle=triangle"];
+	a_1-- a_2 -- a_3 -- a_1;
+	node [shape=box, style="shadow=true", label=""];
+	edge [style="linecolor=red, shadow=true"];
+	b_1 -- b_2 -- a_2;
 }
\ No newline at end of file
diff --git a/tests/testgraphs/specialchars.dot b/tests/testgraphs/specialchars.dot
index 88871ba..d308972 100644
--- a/tests/testgraphs/specialchars.dot
+++ b/tests/testgraphs/specialchars.dot
@@ -1,5 +1,5 @@
-digraph G {
-	a -> b;
-	a [label="$\\%_#{}^&"];
-	b [label="&^}{#_%\\$"];
+digraph G {
+	a -> b;
+	a [label="$\\%_#{}^&"];
+	b [label="&^}{#_%\\$"];
 }
\ No newline at end of file
diff --git a/tests/testgraphs/styles.dot b/tests/testgraphs/styles.dot
index 8ec7252..aa1a185 100644
--- a/tests/testgraphs/styles.dot
+++ b/tests/testgraphs/styles.dot
@@ -1,9 +1,9 @@
-graph G {
-	graph [splines=false]
-	node [shape=circle, texmode=math, fixedsize=True, width="0.4", style="ball color = green", label=""];
-	edge [style="snake=zigzag, green"];
-	a_1-- a_2 -- a_3 -- a_1;
-	node [style="ball color = red", label=""];
-	edge [style="snake=snake, blue", color=red];
-	b_1 -- b_2 -- a_2;
+graph G {
+	graph [splines=false]
+	node [shape=circle, texmode=math, fixedsize=True, width="0.4", style="ball color = green", label=""];
+	edge [style="snake=zigzag, green"];
+	a_1-- a_2 -- a_3 -- a_1;
+	node [style="ball color = red", label=""];
+	edge [style="snake=snake, blue", color=red];
+	b_1 -- b_2 -- a_2;
 }
\ No newline at end of file
diff --git a/tests/testgraphs/transp.dot b/tests/testgraphs/transp.dot
index 4126d8d..aeedc4c 100644
--- a/tests/testgraphs/transp.dot
+++ b/tests/testgraphs/transp.dot
@@ -1,107 +1,107 @@
-graph G {
-//	graph [splines=true overlap=false]
-	//graph [truecolor bgcolor="#ff00005f"]
-	node [style=filled fillcolor="#00ff005f"]
-	1 -- 30 [f=1];
-	1 -- 40 [f=14];
-	8 -- 46 [f=1];
-	8 -- 16 [f=18];
-	10 -- 25 [f=1];
-	10 -- 19 [f=5];
-	10 -- 33 [f=1];
-	12 -- 8 [f=1];
-	12 -- 36 [f=5];
-	12 -- 17 [f=16];
-	13 -- 38 [f=1];
-	13 -- 24 [f=19];
-	24 -- 49 [f=1];
-	24 -- 13 [f=1];
-	24 -- 47 [f=12];
-	24 -- 12 [f=19];
-	25 -- 27 [f=1];
-	25 -- 12 [f=1];
-	27 -- 12 [f=1];
-	27 -- 14 [f=8];
-	29 -- 10 [f=1];
-	29 -- 8 [f=17];
-	30 -- 24 [f=1];
-	30 -- 44 [f=15];
-	38 -- 29 [f=1];
-	38 -- 35 [f=15];
-	2 -- 42 [f=2];
-	2 -- 35 [f=3];
-	2 -- 11 [f=19];
-	14 -- 18 [f=2];
-	14 -- 24 [f=15];
-	14 -- 38 [f=18];
-	18 -- 49 [f=2];
-	18 -- 47 [f=20];
-	26 -- 41 [f=2];
-	node [style=filled fillcolor="#ff00005f"]
-	26 -- 42 [f=15];
-	31 -- 39 [f=2];
-	31 -- 47 [f=17];
-	31 -- 25 [f=14];
-	37 -- 26 [f=2];
-	37 -- 16 [f=14];
-	39 -- 50 [f=2];
-	39 -- 14 [f=2];
-	39 -- 18 [f=17];
-	39 -- 47 [f=10];
-	41 -- 31 [f=2];
-	41 -- 8 [f=16];
-	42 -- 44 [f=2];
-	42 -- 29 [f=12];
-	44 -- 37 [f=2];
-	44 -- 32 [f=15];
-	3 -- 20 [f=2];
-	3 -- 28 [f=19];
-	6 -- 45 [f=2];
-	6 -- 28 [f=10];
-	9 -- 6 [f=2];
-	9 -- 16 [f=1];
-	node [style=filled fillcolor="#0000ff5f"]
-	15 -- 16 [f=2];
-	15 -- 48 [f=2];
-	16 -- 50 [f=2];
-	16 -- 32 [f=14];
-	16 -- 39 [f=8];
-	20 -- 33 [f=2];
-	33 -- 9 [f=2];
-	33 -- 46 [f=3];
-	33 -- 48 [f=17];
-	45 -- 15 [f=2];
-	4 -- 17 [f=4];
-	4 -- 15 [f=6];
-	4 -- 12 [f=16];
-	17 -- 21 [f=4];
-	19 -- 35 [f=4];
-	19 -- 15 [f=9];
-	19 -- 43 [f=4];
-	21 -- 19 [f=4];
-	21 -- 50 [f=4];
-	23 -- 36 [f=4];
-	34 -- 23 [f=4];
-	34 -- 24 [f=11];
-	35 -- 34 [f=4];
-	35 -- 16 [f=6];
-	35 -- 18 [f=16];
-	36 -- 46 [f=4];
-	5 -- 7 [f=1];
-	5 -- 36 [f=6];
-	7 -- 32 [f=1];
-	7 -- 11 [f=2];
-	7 -- 14 [f=17];
-	11 -- 40 [f=1];
-	11 -- 50 [f=1];
-	22 -- 46 [f=1];
-	28 -- 43 [f=1];
-	28 -- 8 [f=18];
-	32 -- 28 [f=1];
-	32 -- 39 [f=13];
-	32 -- 42 [f=15];
-	40 -- 22 [f=1];
-	40 -- 47 [f=1];
-	43 -- 11 [f=1];
-	43 -- 17 [f=19];
-}
+graph G {
+//	graph [splines=true overlap=false]
+	//graph [truecolor bgcolor="#ff00005f"]
+	node [style=filled fillcolor="#00ff005f"]
+	1 -- 30 [f=1];
+	1 -- 40 [f=14];
+	8 -- 46 [f=1];
+	8 -- 16 [f=18];
+	10 -- 25 [f=1];
+	10 -- 19 [f=5];
+	10 -- 33 [f=1];
+	12 -- 8 [f=1];
+	12 -- 36 [f=5];
+	12 -- 17 [f=16];
+	13 -- 38 [f=1];
+	13 -- 24 [f=19];
+	24 -- 49 [f=1];
+	24 -- 13 [f=1];
+	24 -- 47 [f=12];
+	24 -- 12 [f=19];
+	25 -- 27 [f=1];
+	25 -- 12 [f=1];
+	27 -- 12 [f=1];
+	27 -- 14 [f=8];
+	29 -- 10 [f=1];
+	29 -- 8 [f=17];
+	30 -- 24 [f=1];
+	30 -- 44 [f=15];
+	38 -- 29 [f=1];
+	38 -- 35 [f=15];
+	2 -- 42 [f=2];
+	2 -- 35 [f=3];
+	2 -- 11 [f=19];
+	14 -- 18 [f=2];
+	14 -- 24 [f=15];
+	14 -- 38 [f=18];
+	18 -- 49 [f=2];
+	18 -- 47 [f=20];
+	26 -- 41 [f=2];
+	node [style=filled fillcolor="#ff00005f"]
+	26 -- 42 [f=15];
+	31 -- 39 [f=2];
+	31 -- 47 [f=17];
+	31 -- 25 [f=14];
+	37 -- 26 [f=2];
+	37 -- 16 [f=14];
+	39 -- 50 [f=2];
+	39 -- 14 [f=2];
+	39 -- 18 [f=17];
+	39 -- 47 [f=10];
+	41 -- 31 [f=2];
+	41 -- 8 [f=16];
+	42 -- 44 [f=2];
+	42 -- 29 [f=12];
+	44 -- 37 [f=2];
+	44 -- 32 [f=15];
+	3 -- 20 [f=2];
+	3 -- 28 [f=19];
+	6 -- 45 [f=2];
+	6 -- 28 [f=10];
+	9 -- 6 [f=2];
+	9 -- 16 [f=1];
+	node [style=filled fillcolor="#0000ff5f"]
+	15 -- 16 [f=2];
+	15 -- 48 [f=2];
+	16 -- 50 [f=2];
+	16 -- 32 [f=14];
+	16 -- 39 [f=8];
+	20 -- 33 [f=2];
+	33 -- 9 [f=2];
+	33 -- 46 [f=3];
+	33 -- 48 [f=17];
+	45 -- 15 [f=2];
+	4 -- 17 [f=4];
+	4 -- 15 [f=6];
+	4 -- 12 [f=16];
+	17 -- 21 [f=4];
+	19 -- 35 [f=4];
+	19 -- 15 [f=9];
+	19 -- 43 [f=4];
+	21 -- 19 [f=4];
+	21 -- 50 [f=4];
+	23 -- 36 [f=4];
+	34 -- 23 [f=4];
+	34 -- 24 [f=11];
+	35 -- 34 [f=4];
+	35 -- 16 [f=6];
+	35 -- 18 [f=16];
+	36 -- 46 [f=4];
+	5 -- 7 [f=1];
+	5 -- 36 [f=6];
+	7 -- 32 [f=1];
+	7 -- 11 [f=2];
+	7 -- 14 [f=17];
+	11 -- 40 [f=1];
+	11 -- 50 [f=1];
+	22 -- 46 [f=1];
+	28 -- 43 [f=1];
+	28 -- 8 [f=18];
+	32 -- 28 [f=1];
+	32 -- 39 [f=13];
+	32 -- 42 [f=15];
+	40 -- 22 [f=1];
+	40 -- 47 [f=1];
+	43 -- 11 [f=1];
+	43 -- 17 [f=19];
+}
diff --git a/tests/testgraphs/utf8.dot b/tests/testgraphs/utf8.dot
index abb304e..e01544a 100644
--- a/tests/testgraphs/utf8.dot
+++ b/tests/testgraphs/utf8.dot
@@ -1,6 +1,6 @@
-digraph G {
-	a -> b -> c;
-	a [label="æøå"];
-	b [label="üù"];
-	c [label="Éß"];
+digraph G {
+	a -> b -> c;
+	a [label="æøå"];
+	b [label="üù"];
+	c [label="Éß"];
 }
\ No newline at end of file

Debdiff

[The following lists of changes regard files as different if they have different names, permissions or owners.]

Files in second set of .debs but not in first

-rw-r--r--  root/root   /usr/lib/python3/dist-packages/dot2tex-2.12.dev0.egg-info/PKG-INFO
-rw-r--r--  root/root   /usr/lib/python3/dist-packages/dot2tex-2.12.dev0.egg-info/dependency_links.txt
-rw-r--r--  root/root   /usr/lib/python3/dist-packages/dot2tex-2.12.dev0.egg-info/entry_points.txt
-rw-r--r--  root/root   /usr/lib/python3/dist-packages/dot2tex-2.12.dev0.egg-info/requires.txt
-rw-r--r--  root/root   /usr/lib/python3/dist-packages/dot2tex-2.12.dev0.egg-info/top_level.txt
-rw-r--r--  root/root   /usr/lib/python3/dist-packages/dot2tex/__main__.py
-rw-r--r--  root/root   /usr/lib/python3/dist-packages/dot2tex/base.py
-rw-r--r--  root/root   /usr/lib/python3/dist-packages/dot2tex/pgfformat.py
-rw-r--r--  root/root   /usr/lib/python3/dist-packages/dot2tex/pstricksformat.py
-rw-r--r--  root/root   /usr/lib/python3/dist-packages/dot2tex/utils.py
lrwxrwxrwx  root/root   /usr/share/doc/dot2tex/html/_static/sphinx_highlight.js -> ../../../../javascript/sphinxdoc/1.0/sphinx_highlight.js

Files in first set of .debs but not in second

-rw-r--r--  root/root   /usr/lib/python3/dist-packages/dot2tex-2.11.3.egg-info/PKG-INFO
-rw-r--r--  root/root   /usr/lib/python3/dist-packages/dot2tex-2.11.3.egg-info/dependency_links.txt
-rw-r--r--  root/root   /usr/lib/python3/dist-packages/dot2tex-2.11.3.egg-info/entry_points.txt
-rw-r--r--  root/root   /usr/lib/python3/dist-packages/dot2tex-2.11.3.egg-info/requires.txt
-rw-r--r--  root/root   /usr/lib/python3/dist-packages/dot2tex-2.11.3.egg-info/top_level.txt
-rw-r--r--  root/root   /usr/share/doc/dot2tex/html/_sources/roadmap.rst.txt
-rw-r--r--  root/root   /usr/share/doc/dot2tex/html/roadmap.html

Control files: lines which differ (wdiff format)

  • Depends: graphviz, python3-pyparsing (>= 0.4.8), python3:any, libjs-sphinxdoc (>= 5.0) 5.2)

More details

Full run details