| // draw.h |
| |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| // |
| // Copyright 2005-2010 Google, Inc. |
| // Author: allauzen@google.com (Cyril Allauzen) |
| // |
| // \file |
| // Class to draw a binary FST by producing a text file in dot format, |
| // helper class to fstdraw.cc |
| |
| #ifndef FST_SCRIPT_DRAW_IMPL_H_ |
| #define FST_SCRIPT_DRAW_IMPL_H_ |
| |
| #include <sstream> |
| #include <string> |
| |
| #include <fst/script/fst-class.h> |
| #include <fst/fst.h> |
| #include <fst/util.h> |
| |
| namespace fst { |
| |
| // Print a binary Fst in the dot textual format, helper class for fstdraw.cc |
| // WARNING: Stand-alone use not recommend. |
| template <class A> class FstDrawer { |
| public: |
| typedef A Arc; |
| typedef typename A::StateId StateId; |
| typedef typename A::Label Label; |
| typedef typename A::Weight Weight; |
| |
| 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) |
| : fst_(fst), isyms_(isyms), osyms_(osyms), ssyms_(ssyms), |
| accep_(accep && fst.Properties(kAcceptor, true)), ostrm_(0), |
| title_(title), width_(width), height_(height), portrait_(portrait), |
| vertical_(vertical), ranksep_(ranksep), nodesep_(nodesep), |
| fontsize_(fontsize), precision_(precision), |
| show_weight_one_(show_weight_one) {} |
| |
| // Draw Fst to an output buffer (or stdout if buf = 0) |
| void Draw(ostream *strm, const string &dest) { |
| ostrm_ = strm; |
| dest_ = dest; |
| StateId start = fst_.Start(); |
| if (start == kNoStateId) |
| return; |
| |
| PrintString("digraph FST {\n"); |
| if (vertical_) |
| PrintString("rankdir = BT;\n"); |
| else |
| PrintString("rankdir = LR;\n"); |
| PrintString("size = \""); |
| Print(width_); |
| PrintString(","); |
| Print(height_); |
| PrintString("\";\n"); |
| if (!dest_.empty()) |
| PrintString("label = \"" + title_ + "\";\n"); |
| PrintString("center = 1;\n"); |
| if (portrait_) |
| PrintString("orientation = Portrait;\n"); |
| else |
| PrintString("orientation = Landscape;\n"); |
| PrintString("ranksep = \""); |
| Print(ranksep_); |
| PrintString("\";\n"); |
| PrintString("nodesep = \""); |
| Print(nodesep_); |
| PrintString("\";\n"); |
| // initial state first |
| DrawState(start); |
| for (StateIterator< Fst<A> > siter(fst_); |
| !siter.Done(); |
| siter.Next()) { |
| StateId s = siter.Value(); |
| if (s != start) |
| DrawState(s); |
| } |
| PrintString("}\n"); |
| } |
| |
| private: |
| // Maximum line length in text file. |
| static const int kLineLen = 8096; |
| |
| void PrintString(const string &s) const { |
| *ostrm_ << s; |
| } |
| |
| // Escapes backslash and double quote if these occur in the string. Dot will |
| // not deal gracefully with these if they are not escaped. |
| inline void EscapeChars(const string &s, string* ns) const { |
| const char* c = s.c_str(); |
| while (*c) { |
| if (*c == '\\' || *c == '"') ns->push_back('\\'); |
| ns->push_back(*c); |
| ++c; |
| } |
| } |
| |
| void PrintId(int64 id, const SymbolTable *syms, |
| const char *name) const { |
| if (syms) { |
| string symbol = syms->Find(id); |
| if (symbol == "") { |
| FSTERROR() << "FstDrawer: Integer " << id |
| << " is not mapped to any textual symbol" |
| << ", symbol table = " << syms->Name() |
| << ", destination = " << dest_; |
| symbol = "?"; |
| } |
| string nsymbol; |
| EscapeChars(symbol, &nsymbol); |
| PrintString(nsymbol); |
| } else { |
| string idstr; |
| Int64ToStr(id, &idstr); |
| PrintString(idstr); |
| } |
| } |
| |
| void PrintStateId(StateId s) const { |
| PrintId(s, ssyms_, "state ID"); |
| } |
| |
| void PrintILabel(Label l) const { |
| PrintId(l, isyms_, "arc input label"); |
| } |
| |
| void PrintOLabel(Label l) const { |
| PrintId(l, osyms_, "arc output label"); |
| } |
| |
| template <class T> |
| void Print(T t) const { |
| *ostrm_ << t; |
| } |
| |
| void DrawState(StateId s) const { |
| Print(s); |
| PrintString(" [label = \""); |
| PrintStateId(s); |
| Weight final = fst_.Final(s); |
| if (final != Weight::Zero()) { |
| if (show_weight_one_ || (final != Weight::One())) { |
| PrintString("/"); |
| Print(final); |
| } |
| PrintString("\", shape = doublecircle,"); |
| } else { |
| PrintString("\", shape = circle,"); |
| } |
| if (s == fst_.Start()) |
| PrintString(" style = bold,"); |
| else |
| PrintString(" style = solid,"); |
| PrintString(" fontsize = "); |
| Print(fontsize_); |
| PrintString("]\n"); |
| for (ArcIterator< Fst<A> > aiter(fst_, s); |
| !aiter.Done(); |
| aiter.Next()) { |
| Arc arc = aiter.Value(); |
| PrintString("\t"); |
| Print(s); |
| PrintString(" -> "); |
| Print(arc.nextstate); |
| PrintString(" [label = \""); |
| PrintILabel(arc.ilabel); |
| if (!accep_) { |
| PrintString(":"); |
| PrintOLabel(arc.olabel); |
| } |
| if (show_weight_one_ || (arc.weight != Weight::One())) { |
| PrintString("/"); |
| Print(arc.weight); |
| } |
| PrintString("\", fontsize = "); |
| Print(fontsize_); |
| PrintString("];\n"); |
| } |
| } |
| |
| const Fst<A> &fst_; |
| const SymbolTable *isyms_; // ilabel symbol table |
| const SymbolTable *osyms_; // olabel symbol table |
| const SymbolTable *ssyms_; // slabel symbol table |
| bool accep_; // print as acceptor when possible |
| ostream *ostrm_; // drawn FST destination |
| string dest_; // drawn FST destination name |
| |
| string title_; |
| float width_; |
| float height_; |
| bool portrait_; |
| bool vertical_; |
| float ranksep_; |
| float nodesep_; |
| int fontsize_; |
| int precision_; |
| bool show_weight_one_; |
| |
| DISALLOW_COPY_AND_ASSIGN(FstDrawer); |
| }; |
| |
| } // namespace fst |
| |
| #endif // FST_SCRIPT_DRAW_IMPL_H_ |