#include "const.h"
-#ifndef HAVE_STRCASECMP
-extern int strcasecmp(const char *s1, const char *s2);
-#endif
-
/*
* Define an apis array of name strings using an enumerated api_t as index.
* The enumerated type is defined gvplugin.h. The apis array is
continue; /* types empty or mismatched */
if (dep && reqdep && strcmp(dep, reqdep))
continue; /* dependencies not empty, but mismatched */
- if (! reqpkg || strcmp(reqpkg, (*pnext)->package->name) == 0)
- {
- /* found with no packagename constraints, or with required matching packagname */
-
- if (dep && (apidep != api)) /* load dependency if needed, continue if can't find */
- if (! (gvplugin_load(gvc, apidep, dep)))
- continue;
- break;
- }
+ if (! reqpkg)
+ break; /* found with no packagename constraints */
+ if (strcmp(reqpkg, (*pnext)->package->name) == 0)
+ break; /* found with required matching packagname */
}
rv = *pnext;
+ if (dep && (apidep != api)) /* load dependency if needed */
+ if (! (gvplugin_load(gvc, apidep, dep)))
+ rv = NULL;
+
if (rv && rv->typeptr == NULL) {
library = gvplugin_library_load(gvc, rv->package->path);
if (library) {
Agsym_t *a;
gvplugin_package_t *package;
gvplugin_available_t **pnext;
- char bufa[100], *buf1, *buf2, bufb[100], *p, *q;
+ char bufa[100], *buf1, *buf2, bufb[100], *p, *q, *t;
int api, found;
#ifndef WITH_CGRAPH
for (pnext = &(gvc->apis[api]); *pnext; pnext = &((*pnext)->next)) {
if ((*pnext)->package == package) {
found++;
- q = strdup((*pnext)->typestr);
+ t = q = strdup((*pnext)->typestr);
if ((p = strchr(q, ':'))) *p++ = '\0';
+ /* Now p = renderer, e.g. "gd"
+ * and q = device, e.g. "png"
+ * or q = imageloader, e.g. "png" */
switch (api) {
case API_device:
case API_loadimage:
+
+ /* hack for aliases */
+ if (!strncmp(q,"jp",2))
+ q = "jpeg/jpe/jpg";
+ else if (!strncmp(q,"tif",3))
+ q = "tiff/tif";
+ else if (!strcmp(q,"x11") || !strcmp(q,"xlib"))
+ q = "x11/xlib";
+ else if (!strcmp(q,"dot") || !strcmp(q,"gv"))
+ q = "gv/dot";
+
strcpy(buf2, q);
#ifndef WITH_CGRAPH
n = agnode(ssg, bufa);
default:
break;
}
- free(q);
+ free(t);
}
}
if (!found)
}
#ifndef WITH_CGRAPH
- ssg = agsubg(g, "o_formats");
+ ssg = agsubg(g, "output_formats");
#else
- ssg = agsubg(g, "o_formats", 1);
+ ssg = agsubg(g, "output_formats", 1);
#endif
a = agfindgraphattr(ssg, "rank");
#ifndef WITH_CGRAPH
buf2 = bufa + strlen(bufa);
for (pnext = &(gvc->apis[api]); *pnext; pnext = &((*pnext)->next)) {
if ((*pnext)->package == package) {
- q = strdup((*pnext)->typestr);
+ t = q = strdup((*pnext)->typestr);
if ((p = strchr(q, ':'))) *p++ = '\0';
+ /* Now p = renderer, e.g. "gd"
+ * and q = device, e.g. "png"
+ * or q = imageloader, e.g. "png" */
+
+ /* hack for aliases */
+ if (!strncmp(q,"jp",2))
+ q = "jpeg/jpe/jpg";
+ else if (!strncmp(q,"tif",3))
+ q = "tiff/tif";
+ else if (!strcmp(q,"x11") || !strcmp(q,"xlib"))
+ q = "x11/xlib";
+ else if (!strcmp(q,"dot") || !strcmp(q,"gv"))
+ q = "gv/dot";
+
switch (api) {
case API_device:
strcpy(buf2, q);
#else
n = agnode(g, bufa, 1);
#endif
- strcpy(bufb, "o_");
+ strcpy(bufb, "output_");
strcat(bufb, q);
m = agfindnode(ssg, bufb);
if (!m) {
if (p && *p) {
strcpy(bufb, "render_");
strcat(bufb, p);
+ m = agfindnode(ssg, bufb);
+ if (!m)
#ifndef WITH_CGRAPH
- m = agnode(g, bufb);
- agedge(g, m, n);
+ m = agnode(g, bufb);
#else
- m = agnode(g, bufb, 1);
- agedge(g, m, n, NULL, 1);
+ m = agnode(g, bufb, 1);
+#endif
+ e = agfindedge(g, m, n);
+ if (!e)
+#ifndef WITH_CGRAPH
+ e = agedge(g, m, n);
+#else
+ e = agedge(g, m, n, NULL, 1);
#endif
}
break;
#else
n = agnode(g, bufa, 1);
#endif
- strcpy(bufb, "i_");
+ strcpy(bufb, "input_");
strcat(bufb, q);
m = agfindnode(g, bufb);
if (!m) {
#endif
strcpy(bufb, "render_");
strcat(bufb, p);
+ m = agfindnode(g, bufb);
+ if (!m)
+#ifndef WITH_CGRAPH
+ m = agnode(g, bufb);
+#else
+ m = agnode(g, bufb, 1);
+#endif
+ e = agfindedge(g, n, m);
+ if (!e)
#ifndef WITH_CGRAPH
- m = agnode(g, bufb);
- agedge(g, n, m);
+ e = agedge(g, n, m);
#else
- m = agnode(g, bufb, 1);
- agedge(g, n, m, NULL, 1);
+ e = agedge(g, n, m, NULL, 1);
#endif
break;
default:
break;
}
- free(q);
+ free(t);
}
}
}
* clusters, edges and labels. If certain position information
* is missing, init_nop will use a standard neato technique to
* supply it.
+ *
+ * If adjust is false, init_nop does nothing but initialize all
+ * of the basic graph information. No tweaking of positions or
+ * filling in edge splines is done.
+ *
+ * Returns 0 on success.
*/
int init_nop(Agraph_t * g, int adjust)
{
pos_edge posEdges; /* How many edges have spline info */
attrsym_t *G_lp = agfindgraphattr(g, "lp");
attrsym_t *G_bb = agfindgraphattr(g, "bb");
+ int didAdjust = 0; /* Have nodes been moved? */
/* If G_bb not defined, define it */
if (!G_bb)
nop_init_graphs(g, G_lp, G_bb);
posEdges = nop_init_edges(g);
- if (adjust && Nop == 1)
- adjustNodes(g);
+ if (adjust && (Nop == 1))
+ didAdjust = adjustNodes(g);
+
+ if (didAdjust) {
+ if (GD_label(g)) GD_label(g)->set = FALSE;
+/* FIX:
+ * - if nodes are moved, clusters are no longer valid.
+ */
+ }
/* If g does not have a good "bb" attribute or we adjusted the nodes,
* compute it.
*/
- if (!chkBB(g, G_bb) || (adjust && Nop == 1))
+ if (!chkBB(g, G_bb) || didAdjust)
compute_bb(g);
/* At this point, all bounding boxes should be correctly defined.
char *p = agget(g, "model");
char c;
- if (!p || (!(c = *p)))
+ if (!p || (!(c = *p))) /* if p is NULL or "" */
return MODEL_SHORTPATH;
if ((c == 'c') && streq(p, "circuit"))
return MODEL_CIRCUIT;
else if (streq(p, "shortpath"))
return MODEL_SHORTPATH;
}
+ if ((c == 'm') && streq(p, "mds")) {
+#ifndef WITH_CGRAPH
+ if (agindex(g->root->proto->e, "len") >= 0)
+#else /* WITH_CGRAPH */
+ if (agattr(g, AGEDGE, "len", 0))
+#endif /* WITH_CGRAPH */
+ return MODEL_MDS;
+ else {
+ agerr(AGWARN,
+ "edges in graph %s have no len attribute. Hence, the mds model\n", agnameof(g));
+ agerr(AGPREV, "is inappropriate. Reverting to the shortest path model.\n");
+ return MODEL_SHORTPATH;
+ }
+ }
agerr(AGWARN,
"Unknown value %s for attribute \"model\" in graph %s - ignored\n",
p, agnameof(g));
long seed;
/* Check for seed value */
if (!isdigit(*(unsigned char *)p) || sscanf(p, "%ld", &seed) < 1) {
-#if defined(MSWIN32) || defined(WIN32)
+#ifdef MSWIN32
seed = (unsigned) time(NULL);
#else
seed = (unsigned) getpid() ^ (unsigned) time(NULL);
/* majorization:
* Solve stress using majorization.
* Old neato attributes to incorporate:
- * weight?
- * model will be MODE_MAJOR, MODE_HIER or MODE_IPSEP
+ * weight
+ * mode will be MODE_MAJOR, MODE_HIER or MODE_IPSEP
*/
static void
majorization(graph_t *mg, graph_t * g, int nv, int mode, int model, int dim, int steps)
freeGraphData(gp);
}
+/* mds_model:
+ * Assume the matrix already contains shortest path values.
+ * Use the actual lengths provided the input for edges.
+ */
+static void mds_model(graph_t * g, int nG)
+{
+ long i, j;
+ node_t *v;
+ edge_t *e;
+
+ for (v = agfstnode(g); v; v = agnxtnode(g, v)) {
+ for (e = agfstout(g, v); e; e = agnxtout(g, e)) {
+ i = AGID(agtail(e));
+ j = AGID(aghead(e));
+ if (i == j)
+ continue;
+ GD_dist(g)[i][j] = GD_dist(g)[j][i] = GD_dist(e);
+ }
+ }
+}
+
/* kkNeato:
* Solve using gradient descent a la Kamada-Kawai.
*/
agerr(AGPREV, "the graph into connected components.\n");
shortest_path(g, nG);
}
+ } else if (model == MODEL_MDS) {
+ shortest_path(g, nG);
+ mds_model(g, nG);
} else
shortest_path(g, nG);
initial_positions(g, nG);
int layoutMode;
int model;
pack_mode mode;
+ pack_info pinfo;
if (Nop) {
int save = PSinputscale;
neato_init_graph(g);
layoutMode = neatoMode(g);
model = neatoModel(g);
- mode = getPackMode(g, l_undef);
+ mode = getPackModeInfo (g, l_undef, &pinfo);
Pack = getPack(g, -1, CL_OFFSET);
/* pack if just packmode defined. */
if (mode == l_undef) {
*/
if ((Pack < 0) && layoutMode)
Pack = CL_OFFSET;
- mode = l_node;
+ pinfo.mode = l_node;
} else if (Pack < 0)
Pack = CL_OFFSET;
if (Pack >= 0) {
graph_t **cc;
int n_cc;
int i;
- pack_info pinfo;
boolean pin;
cc = pccomps(g, &n_cc, cc_pfx, &pin);
} else
bp = 0;
pinfo.margin = Pack;
- pinfo.doSplines = 0;
- pinfo.mode = mode;
pinfo.fixed = bp;
packGraphs(n_cc, cc, 0, &pinfo);
if (bp)