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 (at) 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 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) 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 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. 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 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 148 void PrintStateId(StateId s) const { 149 PrintId(s, ssyms_, "state ID"); 150 } 151 152 void PrintILabel(Label l) const { 153 PrintId(l, isyms_, "arc input label"); 154 } 155 156 void PrintOLabel(Label l) const { 157 PrintId(l, osyms_, "arc output label"); 158 } 159 160 template <class T> 161 void Print(T t) const { 162 *ostrm_ << t; 163 } 164 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