Text wrapping with dot (graphviz)

Solution 1:

graphviz doesn't support automatic line breaks. You have to put the \n in manually.

you can set a width and a height to a node and define it as fixedsized - this will limit the size of the node and draw only as much text as fits into the node

Solution 2:

Although graphviz does not support text wrapping by itself, dot2tex (latex+graphviz) does. The dot2texi latex package gives an all-in-one solution, with (from the users point of view) a single call to a single tool to build the graph.

A short example:

\documentclass{standalone}
\usepackage{dot2texi}
\usepackage{tikz}
\usetikzlibrary{shapes,arrows}
\begin{document}
\begin{dot2tex}[dot]
digraph G {                                             
d2toptions ="--autosize"
node    [lblstyle="text width=10em,align=center"]
a       [texlbl="This text will be automatically wrapped, for example at a fixed width."]
b       [texlbl="Manual linebreaks from past century can be avoided!"]
a -> b
}
\end{dot2tex}                                               
\end{document}

This can be compiled invoking for example: pdflatex --shell-escape myFile.tex, the text will be automatically wrapped at the prescribed fixed width.

As a side note, this tool seems a handy workaround for graphviz' limited typesetting control of the nodes contents.

Solution 3:

The OP wrote a whole Perl script to achieve this. I found it in his blog: Text wrapping with dot (graphviz).

⚠ Note

This only works if the labels are in the format node [ label=”node label” ]. If the nodes are declared directly (e.g. ”node label”) then it doesn’t work

Perl script:

#!/usr/bin/perl
use strict;
 
my $usage = "setdotlabelwidth [char-width] < [dotfile]";
my $width = shift() or die("Usage: $usage $!");
 
while(<STDIN>)
{
  if(m/label="(.*?)"/)
  {
    my $labeltext = $1;
    my @words = split(/ /, $labeltext);
    my @newtext = ();
    my $newline = "";
    foreach my $word(@words)
    {
      if( length($newline) > 0 and
          length($newline) + length($word) > $width )
      {
        push(@newtext, $newline);
        $newline = "";
      }
      $newline .= " " if( length($newline) > 0 );
      $newline .= $word;
    }
    push(@newtext, $newline) if( length($newline) > 0 );
    my $newlabel = join("\\n", @newtext);
    s/label=".*?"/label="$newlabel"/;
  }
  print;
}

Save this program as setdotlabelwidth, then simply pipe the output into GraphViz. If for example you want to set the width to 35 characters, then the command is:

./setdotlabelwidth 35 < tile-error-correction.dot | dot -Tpng -o tile-error-correction.png

Before: After: