aboutsummaryrefslogtreecommitdiff
path: root/gfsm/gfsm/src/libgfsm/gfsmDraw.c
diff options
context:
space:
mode:
Diffstat (limited to 'gfsm/gfsm/src/libgfsm/gfsmDraw.c')
-rw-r--r--gfsm/gfsm/src/libgfsm/gfsmDraw.c293
1 files changed, 293 insertions, 0 deletions
diff --git a/gfsm/gfsm/src/libgfsm/gfsmDraw.c b/gfsm/gfsm/src/libgfsm/gfsmDraw.c
new file mode 100644
index 0000000..3c10991
--- /dev/null
+++ b/gfsm/gfsm/src/libgfsm/gfsmDraw.c
@@ -0,0 +1,293 @@
+
+/*=============================================================================*\
+ * File: gfsmDraw.c
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: finite state machine library: automata: visualization
+ *
+ * Copyright (c) 2004 Bryan Jurish.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *=============================================================================*/
+
+#include <gfsmDraw.h>
+#include <gfsmArcIter.h>
+#include <gfsmUtils.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*======================================================================
+ * Methods: Text I/O: vcg
+ */
+
+/*--------------------------------------------------------------
+ * draw_vcg_file()
+ */
+gboolean gfsm_automaton_draw_vcg_file_full (gfsmAutomaton *fsm,
+ FILE *f,
+ gfsmAlphabet *lo_alphabet,
+ gfsmAlphabet *hi_alphabet,
+ gfsmAlphabet *state_alphabet,
+ const gchar *title,
+ int xspace, // ?
+ int yspace, // ?
+ const gchar *orientation, // "(top|bottom|left|right)_to_(ditto)"
+ const gchar *state_shape,
+ const gchar *state_color,
+ const gchar *final_color,
+ gfsmError **errp)
+{
+ gfsmStateId id;
+ GString *gstr = g_string_new("");
+
+ fprintf(f, "graph: {\n");
+ fprintf(f, " title: \"%s\"\n", (title ? title : "(gfsm)"));
+ fprintf(f, " display_edge_labels:yes\n");
+ fprintf(f, " splines:yes\n");
+ fprintf(f, " color:white\n");
+ fprintf(f, " xspace:%d\n", (xspace ? xspace : 40));
+ fprintf(f, " yspace:%d\n", (yspace ? yspace : 20));
+ fprintf(f, " orientation:%s\n", (orientation ? orientation : "left_to_right"));
+ fprintf(f, " node.shape:%s\n", (state_shape ? state_shape : "ellipse"));
+ fprintf(f, " node.color:%s\n", (state_color ? state_color : "white"));
+ fprintf(f, " node.borderwidth:1\n");
+
+ //-- ye olde iterationne
+ for (id = 0; id < fsm->states->len; id++) {
+ gfsmState *s = gfsm_automaton_find_state(fsm,id);
+ gfsmArcIter ai;
+ gchar *sym;
+ if (!s || !s->is_valid) continue;
+
+ //-- source state
+ fprintf(f, " node: {title:\"%u\" label:\"", id);
+ if (state_alphabet && (sym=gfsm_alphabet_find_key(state_alphabet,id)) != NULL) {
+ gfsm_alphabet_key2string(state_alphabet, sym, gstr);
+ fprintf(f, "%s", gstr->str);
+ } else {
+ if (state_alphabet) g_printerr("Warning: no label defined for state '%u'!\n", id);
+ fprintf(f, "%u", id);
+ }
+ if (fsm->flags.is_weighted) {
+ fprintf(f, "/%g", gfsm_automaton_get_final_weight(fsm,id));
+ }
+ fprintf(f, "\"");
+
+ if (s->is_final) {
+ fprintf(f, " color:%s", (final_color ? final_color : "lightgrey"));
+ }
+ if (id == fsm->root_id) fputs(" borderwidth:3", f);
+ fputs("}\n", f);
+
+ for (gfsm_arciter_open_ptr(&ai,fsm,s); gfsm_arciter_ok(&ai); gfsm_arciter_next(&ai)) {
+ gfsmArc *a = gfsm_arciter_arc(&ai);
+ fprintf(f, " edge: {sourcename:\"%u\" targetname:\"%u\" label:\"", id, a->target);
+
+ if (lo_alphabet && (sym=gfsm_alphabet_find_key(lo_alphabet,a->lower)) != NULL) {
+ gfsm_alphabet_key2string(lo_alphabet, sym, gstr);
+ fputs(gstr->str, f);
+ } else {
+ if (lo_alphabet)
+ g_printerr("Warning: no label defined for lower label '%u'!\n", a->lower);
+ fprintf(f, "%u", a->lower);
+ }
+
+ if (fsm->flags.is_transducer) {
+ fputc(':', f);
+ if (hi_alphabet && (sym=gfsm_alphabet_find_key(hi_alphabet,a->upper)) != NULL) {
+ gfsm_alphabet_key2string(hi_alphabet, sym, gstr);
+ fputs(gstr->str, f);
+ } else {
+ if (hi_alphabet)
+ g_printerr("Warning: no label defined for upper label '%u'!\n", a->upper);
+ fprintf(f, "%u", a->upper);
+ }
+ }
+
+ if (fsm->flags.is_weighted) fprintf(f, "/%g", a->weight);
+ fprintf(f, "\"}\n");
+ }
+ }
+ fputs("}\n", f);
+
+ return TRUE;
+}
+
+
+/*--------------------------------------------------------------
+ * draw_vcg_filename()
+ */
+gboolean gfsm_automaton_draw_vcg_filename_full (gfsmAutomaton *fsm,
+ const gchar *filename,
+ gfsmAlphabet *lo_alphabet,
+ gfsmAlphabet *hi_alphabet,
+ gfsmAlphabet *state_alphabet,
+ const gchar *title,
+ int xspace,
+ int yspace,
+ const gchar *orientation,
+ const gchar *state_shape,
+ const gchar *state_color,
+ const gchar *final_color,
+ gfsmError **errp)
+{
+ FILE *f;
+ gboolean rc;
+ if (!(f=gfsm_open_filename(filename, "w", errp))) return FALSE;
+ rc = gfsm_automaton_draw_vcg_file_full(fsm, f, lo_alphabet, hi_alphabet, state_alphabet,
+ title, xspace, yspace, orientation,
+ state_shape, state_color, final_color,
+ errp);
+ if (f != stdout) fclose(f);
+ return rc;
+}
+
+
+/*======================================================================
+ * Methods: Draw: dot
+ */
+
+/*--------------------------------------------------------------
+ * draw_dot_file()
+ */
+gboolean gfsm_automaton_draw_dot_file_full (gfsmAutomaton *fsm,
+ FILE *f,
+ gfsmAlphabet *lo_alphabet,
+ gfsmAlphabet *hi_alphabet,
+ gfsmAlphabet *state_alphabet,
+ const gchar *title,
+ float width,
+ float height,
+ int fontsize,
+ const gchar *fontname,
+ gboolean portrait,
+ gboolean vertical,
+ float nodesep,
+ float ranksep,
+ gfsmError **errp)
+{
+ gfsmStateId id;
+ GString *gstr = g_string_new("");
+
+ fprintf(f, "digraph GFSM {\n");
+ fprintf(f, " rankdir = %s;\n", vertical ? "TB" : "LR");
+ if (width>0 && height>0) {
+ fprintf(f, " size = \"%g,\%g\";\n", (width ? width : 8.5), (height ? height : 11));
+ }
+ fprintf(f, " label = \"%s\";\n", (title ? title : "(gfsm)"));
+ fprintf(f, " center = 1;\n");
+ fprintf(f, " nodesep = \"%f\";\n", (nodesep ? nodesep : 0.25));
+ fprintf(f, " ranksep = \"%f\";\n", (ranksep ? ranksep : 0.4));
+ if (!portrait) {
+ //fprintf(f, " orientation = \"Landscape\";\n");
+ fprintf(f, " rotate = 90;\n");
+ }
+
+ //-- ye olde iterationne
+ for (id = 0; id < fsm->states->len; id++) {
+ gfsmState *s = gfsm_automaton_find_state(fsm,id);
+ gfsmArcIter ai;
+ gchar *sym;
+ if (!s || !s->is_valid) continue;
+
+ //-- source state
+ fprintf(f, "%u [label=\"", id);
+ if (state_alphabet && (sym=gfsm_alphabet_find_key(state_alphabet,id)) != NULL) {
+ gfsm_alphabet_key2string(state_alphabet, sym, gstr);
+ fputs(gstr->str, f);
+ } else {
+ if (state_alphabet) g_printerr("Warning: no label defined for state '%u'!\n", id);
+ fprintf(f, "%u", id);
+ }
+ if (fsm->flags.is_weighted && s->is_final) {
+ fprintf(f, "/%g", gfsm_automaton_get_final_weight(fsm,id));
+ }
+ fprintf(f, "\", shape=%s, style=%s, fontsize=%d",
+ (s->is_final ? "doublecircle" : "circle"),
+ (id == fsm->root_id ? "bold" : "solid"),
+ (fontsize ? fontsize : 14));
+ if (fontname && *fontname) fprintf(f, ", fontname=\"%s\"", fontname);
+ fprintf(f, "]\n");
+
+ for (gfsm_arciter_open_ptr(&ai,fsm,s); gfsm_arciter_ok(&ai); gfsm_arciter_next(&ai)) {
+ gfsmArc *a = gfsm_arciter_arc(&ai);
+ fprintf(f, " %u -> %u \[label=\"", id, a->target);
+
+ if (lo_alphabet && (sym=gfsm_alphabet_find_key(lo_alphabet,a->lower)) != NULL) {
+ gfsm_alphabet_key2string(lo_alphabet, sym, gstr);
+ fputs(gstr->str, f);
+ } else {
+ if (lo_alphabet)
+ g_printerr("Warning: no label defined for lower label '%u'!\n", a->lower);
+ fprintf(f, "%u", a->lower);
+ }
+
+ if (fsm->flags.is_transducer) {
+ fputc(':', f);
+ if (hi_alphabet && (sym=gfsm_alphabet_find_key(hi_alphabet,a->upper)) != NULL) {
+ gfsm_alphabet_key2string(hi_alphabet, sym, gstr);
+ fputs(gstr->str, f);
+ } else {
+ if (hi_alphabet)
+ g_printerr("Warning: no label defined for upper label '%u'!\n", a->upper);
+ fprintf(f, "%u", a->upper);
+ }
+ }
+
+ if (fsm->flags.is_weighted) fprintf(f, "/%g", a->weight);
+
+ fprintf(f, "\", fontsize=%d", (fontsize ? fontsize : 14));
+ if (fontname && *fontname) fprintf(f, ", fontname=\"%s\"", fontname);
+ fprintf(f, "];\n");
+ }
+ }
+ fputs("}\n", f);
+
+ //--cleanup
+ g_string_free(gstr,TRUE);
+
+ return TRUE;
+}
+
+
+/*--------------------------------------------------------------
+ * draw_dot_filename()
+ */
+gboolean gfsm_automaton_draw_dot_filename_full (gfsmAutomaton *fsm,
+ const gchar *filename,
+ gfsmAlphabet *lo_alphabet,
+ gfsmAlphabet *hi_alphabet,
+ gfsmAlphabet *state_alphabet,
+ const gchar *title,
+ float width,
+ float height,
+ int fontsize,
+ const gchar *fontname,
+ gboolean portrait,
+ gboolean vertical,
+ float nodesep,
+ float ranksep,
+ gfsmError **errp)
+{
+ FILE *f;
+ gboolean rc;
+ if (!(f=gfsm_open_filename(filename, "w", errp))) return FALSE;
+ rc = gfsm_automaton_draw_dot_file_full(fsm, f, lo_alphabet, hi_alphabet, state_alphabet,
+ title, width, height, fontsize, fontname,
+ portrait, vertical, nodesep, ranksep,
+ errp);
+ if (f != stdout) fclose(f);
+ return rc;
+}