1 /* $Id$ $Revision$ */
2 /* vim:set shiftwidth=4 ts=8: */
3 
4 /*************************************************************************
5  * Copyright (c) 2011 AT&T Intellectual Property
6  * All rights reserved. This program and the accompanying materials
7  * are made available under the terms of the Eclipse Public License v1.0
8  * which accompanies this distribution, and is available at
9  * http://www.eclipse.org/legal/epl-v10.html
10  *
11  * Contributors: See CVS logs. Details at http://www.graphviz.org/
12  *************************************************************************/
13 
14 /*
15  *  layout engine wrapper
16  *
17  */
18 
19 #include "config.h"
20 
21 #include "const.h"
22 #include "gvplugin_layout.h"
23 #include "gvcint.h"
24 #include "cgraph.h"
25 #include "gvcproc.h"
26 #include "gvc.h"
27 
28 extern void graph_init(Agraph_t *g, boolean use_rankdir);
29 extern void graph_cleanup(Agraph_t *g);
30 extern void gv_fixLocale (int set);
31 extern void gv_initShapes (void);
32 
gvlayout_select(GVC_t * gvc,const char * layout)33 int gvlayout_select(GVC_t * gvc, const char *layout)
34 {
35     gvplugin_available_t *plugin;
36     gvplugin_installed_t *typeptr;
37 
38     plugin = gvplugin_load(gvc, API_layout, layout);
39     if (plugin) {
40 	typeptr = plugin->typeptr;
41 	gvc->layout.type = typeptr->type;
42 	gvc->layout.engine = (gvlayout_engine_t *) (typeptr->engine);
43 	gvc->layout.id = typeptr->id;
44 	gvc->layout.features = (gvlayout_features_t *) (typeptr->features);
45 	return GVRENDER_PLUGIN;  /* FIXME - need better return code */
46     }
47     return NO_SUPPORT;
48 }
49 
50 /* gvLayoutJobs:
51  * Layout input graph g based on layout engine attached to gvc.
52  * Check that the root graph has been initialized. If not, initialize it.
53  * Return 0 on success.
54  */
gvLayoutJobs(GVC_t * gvc,Agraph_t * g)55 int gvLayoutJobs(GVC_t * gvc, Agraph_t * g)
56 {
57     gvlayout_engine_t *gvle;
58     char *p;
59     int rc;
60 
61     agbindrec(g, "Agraphinfo_t", sizeof(Agraphinfo_t), TRUE);
62     GD_gvc(g) = gvc;
63     if (g != agroot(g))
64 	GD_gvc(agroot(g)) = gvc;
65 
66     if ((p = agget(g, "layout"))) {
67         gvc->layout.engine = NULL;
68 	rc = gvlayout_select(gvc, p);
69 	if (rc == NO_SUPPORT) {
70 	    agerr (AGERR, "Layout type: \"%s\" not recognized. Use one of:%s\n",
71 	        p, gvplugin_list(gvc, API_layout, p));
72 	    return -1;
73 	}
74     }
75 
76     gvle = gvc->layout.engine;
77     if (! gvle)
78 	return -1;
79 
80     gv_fixLocale (1);
81     graph_init(g, gvc->layout.features->flags & LAYOUT_USES_RANKDIR);
82     GD_drawing(agroot(g)) = GD_drawing(g);
83     gv_initShapes ();
84     if (gvle && gvle->layout) {
85 	gvle->layout(g);
86 
87 
88 	if (gvle->cleanup)
89 	    GD_cleanup(g) = gvle->cleanup;
90     }
91     gv_fixLocale (0);
92     return 0;
93 }
94 
95 /* gvFreeLayout:
96  * Free layout resources.
97  * First, if the graph has a layout-specific cleanup function attached,
98  * use it and reset.
99  * Then, if the root graph has not been cleaned up, clean it up and reset.
100  * Only the root graph has GD_drawing non-null.
101  */
gvFreeLayout(GVC_t * gvc,Agraph_t * g)102 int gvFreeLayout(GVC_t * gvc, Agraph_t * g)
103 {
104     /* skip if no Agraphinfo_t yet */
105     if (! agbindrec(g, "Agraphinfo_t", 0, TRUE))
106 	    return 0;
107 
108     if (GD_cleanup(g)) {
109 	(GD_cleanup(g))(g);
110 	GD_cleanup(g) = NULL;
111     }
112 
113     if (GD_drawing(g)) {
114 	graph_cleanup(g);
115     }
116     return 0;
117 }
118