• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // draw.h
2 
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 // Copyright 2005-2010 Google, Inc.
16 // Author: allauzen@google.com (Cyril Allauzen)
17 //
18 // \file
19 // Class to draw a binary FST by producing a text file in dot format,
20 // helper class to fstdraw.cc
21 
22 #ifndef FST_SCRIPT_DRAW_IMPL_H_
23 #define FST_SCRIPT_DRAW_IMPL_H_
24 
25 #include <sstream>
26 #include <string>
27 
28 #include <fst/script/fst-class.h>
29 #include <fst/fst.h>
30 #include <fst/util.h>
31 
32 namespace fst {
33 
34 // Print a binary Fst in the dot textual format, helper class for fstdraw.cc
35 // WARNING: Stand-alone use not recommend.
36 template <class A> class FstDrawer {
37  public:
38   typedef A Arc;
39   typedef typename A::StateId StateId;
40   typedef typename A::Label Label;
41   typedef typename A::Weight Weight;
42 
FstDrawer(const Fst<A> & fst,const SymbolTable * isyms,const SymbolTable * osyms,const SymbolTable * ssyms,bool accep,string title,float width,float height,bool portrait,bool vertical,float ranksep,float nodesep,int fontsize,int precision,bool show_weight_one)43   FstDrawer(const Fst<A> &fst,
44             const SymbolTable *isyms,
45             const SymbolTable *osyms,
46             const SymbolTable *ssyms,
47             bool accep,
48             string title,
49             float width,
50             float height,
51             bool portrait,
52             bool vertical,
53             float ranksep,
54             float nodesep,
55             int fontsize,
56             int precision,
57             bool show_weight_one)
58       : fst_(fst), isyms_(isyms), osyms_(osyms), ssyms_(ssyms),
59         accep_(accep && fst.Properties(kAcceptor, true)), ostrm_(0),
60         title_(title), width_(width), height_(height), portrait_(portrait),
61         vertical_(vertical), ranksep_(ranksep), nodesep_(nodesep),
62         fontsize_(fontsize), precision_(precision),
63         show_weight_one_(show_weight_one) {}
64 
65   // Draw Fst to an output buffer (or stdout if buf = 0)
Draw(ostream * strm,const string & dest)66   void Draw(ostream *strm, const string &dest) {
67     ostrm_ = strm;
68     dest_ = dest;
69     StateId start = fst_.Start();
70     if (start == kNoStateId)
71       return;
72 
73     PrintString("digraph FST {\n");
74     if (vertical_)
75       PrintString("rankdir = BT;\n");
76     else
77       PrintString("rankdir = LR;\n");
78     PrintString("size = \"");
79     Print(width_);
80     PrintString(",");
81     Print(height_);
82     PrintString("\";\n");
83     if (!dest_.empty())
84       PrintString("label = \"" + title_ + "\";\n");
85     PrintString("center = 1;\n");
86     if (portrait_)
87       PrintString("orientation = Portrait;\n");
88     else
89       PrintString("orientation = Landscape;\n");
90     PrintString("ranksep = \"");
91     Print(ranksep_);
92     PrintString("\";\n");
93     PrintString("nodesep = \"");
94     Print(nodesep_);
95     PrintString("\";\n");
96     // initial state first
97     DrawState(start);
98     for (StateIterator< Fst<A> > siter(fst_);
99          !siter.Done();
100          siter.Next()) {
101       StateId s = siter.Value();
102       if (s != start)
103         DrawState(s);
104     }
105     PrintString("}\n");
106   }
107 
108  private:
109   // Maximum line length in text file.
110   static const int kLineLen = 8096;
111 
PrintString(const string & s)112   void PrintString(const string &s) const {
113     *ostrm_ << s;
114   }
115 
116   // Escapes backslash and double quote if these occur in the string. Dot will
117   // not deal gracefully with these if they are not escaped.
EscapeChars(const string & s,string * ns)118   inline void EscapeChars(const string &s, string* ns) const {
119     const char* c = s.c_str();
120     while (*c) {
121       if (*c == '\\' || *c == '"') ns->push_back('\\');
122       ns->push_back(*c);
123       ++c;
124     }
125   }
126 
PrintId(int64 id,const SymbolTable * syms,const char * name)127   void PrintId(int64 id, const SymbolTable *syms,
128                const char *name) const {
129     if (syms) {
130       string symbol = syms->Find(id);
131       if (symbol == "") {
132         FSTERROR() << "FstDrawer: Integer " << id
133                    << " is not mapped to any textual symbol"
134                    << ", symbol table = " << syms->Name()
135                    << ", destination = " << dest_;
136         symbol = "?";
137       }
138       string nsymbol;
139       EscapeChars(symbol, &nsymbol);
140       PrintString(nsymbol);
141     } else {
142       string idstr;
143       Int64ToStr(id, &idstr);
144       PrintString(idstr);
145     }
146   }
147 
PrintStateId(StateId s)148   void PrintStateId(StateId s) const {
149      PrintId(s, ssyms_, "state ID");
150   }
151 
PrintILabel(Label l)152   void PrintILabel(Label l) const {
153      PrintId(l, isyms_, "arc input label");
154   }
155 
PrintOLabel(Label l)156   void PrintOLabel(Label l) const {
157      PrintId(l, osyms_, "arc output label");
158   }
159 
160   template <class T>
Print(T t)161   void Print(T t) const {
162     *ostrm_ << t;
163   }
164 
DrawState(StateId s)165   void DrawState(StateId s) const {
166     Print(s);
167     PrintString(" [label = \"");
168     PrintStateId(s);
169     Weight final = fst_.Final(s);
170     if (final != Weight::Zero()) {
171       if (show_weight_one_ || (final != Weight::One())) {
172         PrintString("/");
173         Print(final);
174       }
175       PrintString("\", shape = doublecircle,");
176     } else {
177       PrintString("\", shape = circle,");
178     }
179     if (s == fst_.Start())
180       PrintString(" style = bold,");
181     else
182       PrintString(" style = solid,");
183     PrintString(" fontsize = ");
184     Print(fontsize_);
185     PrintString("]\n");
186     for (ArcIterator< Fst<A> > aiter(fst_, s);
187          !aiter.Done();
188          aiter.Next()) {
189       Arc arc = aiter.Value();
190       PrintString("\t");
191       Print(s);
192       PrintString(" -> ");
193       Print(arc.nextstate);
194       PrintString(" [label = \"");
195       PrintILabel(arc.ilabel);
196       if (!accep_) {
197         PrintString(":");
198         PrintOLabel(arc.olabel);
199       }
200       if (show_weight_one_ || (arc.weight != Weight::One())) {
201         PrintString("/");
202         Print(arc.weight);
203       }
204       PrintString("\", fontsize = ");
205       Print(fontsize_);
206       PrintString("];\n");
207     }
208   }
209 
210   const Fst<A> &fst_;
211   const SymbolTable *isyms_;     // ilabel symbol table
212   const SymbolTable *osyms_;     // olabel symbol table
213   const SymbolTable *ssyms_;     // slabel symbol table
214   bool accep_;                   // print as acceptor when possible
215   ostream *ostrm_;               // drawn FST destination
216   string dest_;                  // drawn FST destination name
217 
218   string title_;
219   float width_;
220   float height_;
221   bool portrait_;
222   bool vertical_;
223   float ranksep_;
224   float nodesep_;
225   int fontsize_;
226   int precision_;
227   bool show_weight_one_;
228 
229   DISALLOW_COPY_AND_ASSIGN(FstDrawer);
230 };
231 
232 }  // namespace fst
233 
234 #endif  // FST_SCRIPT_DRAW_IMPL_H_
235