/************************************************************************* * Copyright (c) 2011 AT&T Intellectual Property * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * https://www.eclipse.org/legal/epl-v10.html * * Contributors: Details at https://graphviz.org *************************************************************************/ /* * layout engine wrapper * */ #include "config.h" #include #include #include #include #include #include #include #include extern void graph_init(Agraph_t *g, bool use_rankdir); extern void graph_cleanup(Agraph_t *g); extern void gv_fixLocale (int set); int gvlayout_select(GVC_t * gvc, const char *layout) { gvplugin_available_t *plugin; gvplugin_installed_t *typeptr; plugin = gvplugin_load(gvc, API_layout, layout, NULL); if (plugin) { typeptr = plugin->typeptr; gvc->layout.type = typeptr->type; gvc->layout.engine = typeptr->engine; gvc->layout.id = typeptr->id; gvc->layout.features = typeptr->features; return GVRENDER_PLUGIN; /* FIXME - need better return code */ } return NO_SUPPORT; } /* gvLayoutJobs: * Layout input graph g based on layout engine attached to gvc. * Check that the root graph has been initialized. If not, initialize it. * Return 0 on success. */ int gvLayoutJobs(GVC_t * gvc, Agraph_t * g) { gvlayout_engine_t *gvle; char *p; int rc; agbindrec(g, "Agraphinfo_t", sizeof(Agraphinfo_t), true); GD_gvc(g) = gvc; if (g != agroot(g)) { agbindrec(agroot(g), "Agraphinfo_t", sizeof(Agraphinfo_t), true); GD_gvc(agroot(g)) = gvc; } if ((p = agget(g, "layout"))) { gvc->layout.engine = NULL; rc = gvlayout_select(gvc, p); if (rc == NO_SUPPORT) { agerrorf("Layout type: \"%s\" not recognized. Use one of:%s\n", p, gvplugin_list(gvc, API_layout, p)); return -1; } } gvle = gvc->layout.engine; if (! gvle) return -1; gv_fixLocale (1); graph_init(g, !!(gvc->layout.features->flags & LAYOUT_USES_RANKDIR)); GD_drawing(agroot(g)) = GD_drawing(g); if (gvle && gvle->layout) { gvle->layout(g); if (gvle->cleanup) GD_cleanup(g) = gvle->cleanup; } gv_fixLocale (0); return 0; } bool gvLayoutDone(Agraph_t * g) { return LAYOUT_DONE(g); } /* gvFreeLayout: * Free layout resources. * First, if the graph has a layout-specific cleanup function attached, * use it and reset. * Then do the general graph cleanup. */ int gvFreeLayout(GVC_t * gvc, Agraph_t * g) { (void)gvc; /* skip if no Agraphinfo_t yet */ if (! agbindrec(g, "Agraphinfo_t", 0, true)) return 0; if (GD_cleanup(g)) { (GD_cleanup(g))(g); GD_cleanup(g) = NULL; } graph_cleanup(g); return 0; }