]> granicus.if.org Git - graphviz/commitdiff
Fix bug 2336;
authorEmden R. Gansner <erg@research.att.com>
Fri, 6 Sep 2013 21:49:55 +0000 (17:49 -0400)
committerEmden R. Gansner <erg@research.att.com>
Fri, 6 Sep 2013 21:49:55 +0000 (17:49 -0400)
add support for dynamic versions of xdot output.

doc/info/attrs.html
doc/info/output.html
doc/infosrc/attrs
doc/infosrc/outputs
lib/common/utils.c
lib/common/utils.h
plugin/core/gvrender_core_dot.c

index 8bd4cc2ef5c984febad9ede0604108901f6d2a15..5ec9771b63849807f3440b3e858155527f5ce8de 100644 (file)
@@ -501,6 +501,8 @@ This field indicates which graph component uses the attribute.
 </TD><TD>E</TD><TD>int<BR>double</TD><TD ALIGN="CENTER">1</TD><TD>0(dot)<BR>1(neato,fdp)</TD><TD></TD> </TR>
  <TR><TD><A NAME=a:width HREF=#d:width>width</A>
 </TD><TD>N</TD><TD>double</TD><TD ALIGN="CENTER">0.75</TD><TD>0.01</TD><TD></TD> </TR>
+ <TR><TD><A NAME=a:xdotversion HREF=#d:xdotversion>xdotversion</A>
+</TD><TD>G</TD><TD>string</TD><TD ALIGN="CENTER"></TD><TD></TD><TD>xdot only</TD> </TR>
  <TR><TD><A NAME=a:xlabel HREF=#d:xlabel>xlabel</A>
 </TD><TD>EN</TD><TD><A HREF=#k:lblString>lblString</A>
 </TD><TD ALIGN="CENTER">""</TD><TD></TD><TD></TD> </TR>
@@ -1950,6 +1952,10 @@ This field indicates which graph component uses the attribute.
   If neither is set explicitly, the minimum of the two default values
   is used.
 
+<DT><A NAME=d:xdotversion HREF=#a:xdotversion><STRONG>xdotversion</STRONG></A>
+<DD>  For xdot output, if this attribute is set, this determines the version of xdot used in output.
+  If not set, the attribute will be set to the xdot version used for output.
+
 <DT><A NAME=d:xlabel HREF=#a:xlabel><STRONG>xlabel</STRONG></A>
 <DD>  External label for a node or edge. For nodes, the label will be placed outside of the
   node but near it. For edges, the label will be placed near the center of the edge.
index df2a6edd25e09b6b43bcece2c46fe55e79dbfe15..325d535503976d184266ffd90d2a3214890a43e0 100644 (file)
@@ -249,13 +249,14 @@ Note though that if
 an edge or node is invisible, no drawing operations are attached to it.
 <P>
 Version info:
-<TABLE  border >
-<TR><TH>Xdot version</TH><TH>Graphviz version</TH></TR>
-<TR><TD>1.0</TD><TD>1.9</TD></TR>
-<TR><TD>1.1</TD><TD>2.8</TD></TR>
-<TR><TD>1.2</TD><TD>2.13</TD></TR>
-<TR><TD>1.3</TD><TD>2.31</TD></TR>
-<TR><TD>1.4</TD><TD>2.32</TD></TR>
+<TABLE  border="1" >
+<TR><TH>Xdot version</TH><TH>Graphviz version</TH><TH>Modification</TH></TR>
+<TR><TD>1.0</TD> <TD>1.9</TD><TD> </TD></TR>
+<TR><TD>1.1</TD> <TD>2.8</TD><TD>First plug-in version</TD></TR>
+<TR><TD>1.2</TD><TD>2.13</TD><TD>Support image operator <b>I</b></TD></TR>
+<TR><TD>1.3</TD><TD>2.31</TD><TD>Add numerical precision</TD</TR>
+<TR><TD>1.4</TD><TD>2.32</TD><TD>Add gradient colors</TD</TR>
+<TR><TD>1.5</TD><TD>2.34</TD><TD>Fix text layout problem; fix inverted vector in gradient; support version-specific output</TD</TR>
 </TABLE>
 
 <DT><A NAME=d:cmap HREF=#a:cmap><STRONG>cmap</STRONG></A>
index 3ee2c2be7eee8e7e4f85268d92d5a78466ede919..f6a775e972884ce8be04a95fe6a401a0b3efa2b7 100644 (file)
@@ -1289,6 +1289,9 @@ However, if one uses <A HREF=#d:bgcolor>bgcolor</A>=transparent with
 a color palette, font
 antialiasing can show up as a fuzzy white area around characters.
 Using <B>truecolor</B>=true avoids this problem.
+:xdotversion:G:string:;   xdot
+For xdot output, if this attribute is set, this determines the version of xdot used in output.
+If not set, the attribute will be set to the xdot version used for output.
 :vertices:N:pointList; write
 If the input graph defines this attribute, the node is polygonal,
 and output is dot or xdot, this attribute provides the
index ccb61fd8c2df19b4f82019a90464d76ee3bc2672..ed57bd42d49ca63ece5c319832ab0e811db58cd3 100644 (file)
@@ -299,13 +299,14 @@ Note though that if
 an edge or node is invisible, no drawing operations are attached to it.
 <P>
 Version info:
-<TABLE  border >
-<TR><TH>Xdot version</TH><TH>Graphviz version</TH></TR>
-<TR><TD>1.0</TD><TD>1.9</TD></TR>
-<TR><TD>1.1</TD><TD>2.8</TD></TR>
-<TR><TD>1.2</TD><TD>2.13</TD></TR>
-<TR><TD>1.3</TD><TD>2.31</TD></TR>
-<TR><TD>1.4</TD><TD>2.32</TD></TR>
+<TABLE  border="1" >
+<TR><TH>Xdot version</TH><TH>Graphviz version</TH><TH>Modification</TH></TR>
+<TR><TD>1.0</TD> <TD>1.9</TD><TD> </TD></TR>
+<TR><TD>1.1</TD> <TD>2.8</TD><TD>First plug-in version</TD></TR>
+<TR><TD>1.2</TD><TD>2.13</TD><TD>Support image operator <b>I</b></TD></TR>
+<TR><TD>1.3</TD><TD>2.31</TD><TD>Add numerical precision</TD</TR>
+<TR><TD>1.4</TD><TD>2.32</TD><TD>Add gradient colors</TD</TR>
+<TR><TD>1.5</TD><TD>2.34</TD><TD>Fix text layout problem; fix inverted vector in gradient; support version-specific output</TD</TR>
 </TABLE>
 :plain/plain-ext:Simple text format
 The plain and plain-ext formats produce output using
index aa67f4c25bb5bedb308d435bfdb61efccfa89ee3..db3e287477b8d7960551e41342871dd617cd07ac 100644 (file)
@@ -1876,12 +1876,16 @@ void setEdgeType (graph_t* g, int dflt)
  * If isRadial is true,sets the inner radius to half the distance to the min point;
  * else uses the angle parameter to identify two points on a line that defines the 
  * gradient direction
+ * By default, this assumes a left-hand coordinate system (for svg); if RHS = 2 flag
+ * is set, use standard coordinate system.
  */
-void get_gradient_points(pointf * A, pointf * G, int n, float angle, boolean isRadial)
+void get_gradient_points(pointf * A, pointf * G, int n, float angle, int flags)
 {
     int i;
     double rx, ry;
     pointf min,max,center;
+    int isRadial = flags & 1;
+    int isRHS = flags & 2;
     
     if (n == 2) {
       rx = A[1].x - A[0].x;
@@ -1905,19 +1909,34 @@ void get_gradient_points(pointf * A, pointf * G, int n, float angle, boolean isR
       center.y = min.y + (max.y - min.y)/2;
     if (isRadial) {
        double inner_r, outer_r;
-      outer_r = sqrt((center.x - min.x)*(center.x - min.x) +
+       outer_r = sqrt((center.x - min.x)*(center.x - min.x) +
                      (center.y - min.y)*(center.y - min.y));
-      inner_r = outer_r /4.;
-      G[0].x = center.x;
-      G[0].y = -center.y;
-      G[1].x = inner_r;
-      G[1].y = outer_r;
+       inner_r = outer_r /4.;
+       if (isRHS) {
+           G[0].y = center.y;
+       }
+       else {
+           G[0].y = -center.y;
+       }
+       G[0].x = center.x;
+       G[1].x = inner_r;
+       G[1].y = outer_r;
     }
     else {
-      G[0].x = center.x - (max.x - center.x) * cos(angle);
-      G[0].y = -center.y + (max.y - center.y) * sin(angle);
-      G[1].x = center.x + (center.x - min.x) * cos(angle);
-      G[1].y = -center.y - (center.y - min.y) * sin(angle);
+       double half_x = max.x - center.x;
+       double half_y = max.y - center.y;
+       double sina = sin(angle);
+       double cosa = cos(angle);
+       if (isRHS) {
+           G[0].y = center.y - half_y * sina;
+           G[1].y = center.y + half_y * sina;
+       }
+       else {
+           G[0].y = -center.y + (max.y - center.y) * sin(angle);
+           G[1].y = -center.y - (center.y - min.y) * sin(angle);
+       }
+       G[0].x = center.x - half_x * cosa;
+       G[1].x = center.x + half_x * cosa;
     }
 }
 
index d5facc8eed1914e2b8a5afe5adeffc99fe1930f6..8228dcbbe0b095663118728bea8e56b0afb378d4 100644 (file)
@@ -96,7 +96,7 @@ extern "C" {
     extern boolean overlap_label(textlabel_t *lp, boxf b);
     extern boolean overlap_edge(edge_t *e, boxf b);
 
-    extern void get_gradient_points(pointf * A, pointf * G, int n, float angle, boolean isRadial);
+    extern void get_gradient_points(pointf * A, pointf * G, int n, float angle, int flags);
 
     extern int processClusterEdges(graph_t * g);
 
index 6a712f90ba3bc29fc2a27f5dd164e489bddedabd..6cda497ceaf911dd402388556567281e9aba77fb 100644 (file)
@@ -23,6 +23,7 @@
 #include <stdarg.h>
 #include <stdlib.h>
 #include <string.h>
+#include <ctype.h>
 
 #include "macros.h"
 #include "const.h"
@@ -42,7 +43,9 @@ typedef enum {
        FORMAT_CANON,
        FORMAT_PLAIN,
        FORMAT_PLAIN_EXT,
-       FORMAT_XDOT
+       FORMAT_XDOT,
+       FORMAT_XDOT12,
+       FORMAT_XDOT14,
 } format_type;
 
 #ifdef WIN32 /*dependencies*/
@@ -86,6 +89,8 @@ typedef struct {
     attrsym_t *hl_draw;
     attrsym_t *tl_draw;
     unsigned char buf[NUMXBUFS][BUFSIZ];
+    unsigned short version;
+    char* version_s;
 } xdot_state_t;
 static xdot_state_t* xd;
 
@@ -368,6 +373,29 @@ static void xdot_end_cluster(GVJ_t * job)
     penwidth[EMIT_CLABEL] = 1;
 }
 
+static unsigned short
+versionStr2Version (char* str)
+{
+    char c, buf[BUFSIZ];
+    int n = 0;
+    char* s = str;
+    unsigned short us;
+
+    while ((c = *s++)) {
+       if (isdigit(c)) {
+           if (n < BUFSIZ-1) buf[n++] = c;
+           else {
+               agerr(AGWARN, "xdot version \"%s\" too long", str);
+               break;
+           }
+       }
+    }
+    buf[n] = '\0';
+    
+    us = atoi(buf);
+    return us;
+}
+
 /* 
  * John M. suggests:
  * You might want to add four more:
@@ -391,12 +419,30 @@ static void xdot_end_cluster(GVJ_t * job)
  * output with them, it could break what we have. 
  */
 static void
-xdot_begin_graph (graph_t *g, int s_arrows, int e_arrows)
+xdot_begin_graph (graph_t *g, int s_arrows, int e_arrows, format_type id)
 {
-    int i;
+    int i, us;
+    char* s;
 
     xd = GNEW(xdot_state_t);
 
+    if (id == FORMAT_XDOT14) {
+       xd->version = 14;
+       xd->version_s = "1.4";
+    }
+    else if (id == FORMAT_XDOT12) {
+       xd->version = 12;
+       xd->version_s = "1.2";
+    }
+    else if ((s = agget(g, "xdotversion")) && s[0] && ((us = versionStr2Version(s)) > 10)) {
+       xd->version = us;
+       xd->version_s = s;
+    }
+    else {
+       xd->version = versionStr2Version(XDOTVERSION);
+       xd->version_s = XDOTVERSION;
+    }
+
     if (GD_n_cluster(g))
 #ifndef WITH_CGRAPH
        xd->g_draw = safe_dcl(g, g, "_draw_", "", agraphattr);
@@ -488,8 +534,11 @@ static void dot_begin_graph(GVJ_t *job)
        case FORMAT_PLAIN_EXT:
            break;
        case FORMAT_XDOT:
+       case FORMAT_XDOT12:
+       case FORMAT_XDOT14:
            attach_attrs_and_arrows(g, &s_arrows, &e_arrows);
-           xdot_begin_graph(g, s_arrows, e_arrows);
+           xdot_begin_graph(g, s_arrows, e_arrows, job->render.id);
+           break;
     }
 }
 
@@ -513,7 +562,7 @@ static void xdot_end_graph(graph_t* g)
 #else /* WITH_CGRAPH */
        agxset(g, xd->g_l_draw, agxbuse(xbufs[EMIT_GLABEL]));
 #endif /* WITH_CGRAPH */
-    agsafeset (g, "xdotversion", XDOTVERSION, "");
+    agsafeset (g, "xdotversion", xd->version_s, "");
 
     for (i = 0; i < NUMXBUFS; i++)
        agxbfree(xbuf+i);
@@ -559,6 +608,8 @@ static void dot_end_graph(GVJ_t *job)
                agwrite(g, (FILE*)job);
            break;
        case FORMAT_XDOT:
+       case FORMAT_XDOT12:
+       case FORMAT_XDOT14:
            xdot_end_graph(g);
            if (!(job->flags & OUTPUT_NOT_REQUIRED))
                agwrite(g, (FILE*)job);
@@ -624,15 +675,20 @@ static void xdot_gradient_fillcolor (GVJ_t* job, int filled, pointf* A, int n)
     float r1,r2;
     pointf G[2],c1,c2;
 
+    if (xd->version < 14) {
+       xdot_fillcolor (job);
+       return;
+    }
+
     agxbinit(&xbuf, BUFSIZ, buf0);
     if (filled == GRADIENT) {
-       get_gradient_points(A, G, n, angle, 0);
+       get_gradient_points(A, G, n, angle, 2);
        agxbputc (&xbuf, '[');
        xdot_point (&xbuf, G[0]);
        xdot_point (&xbuf, G[1]);
     }
     else {
-       get_gradient_points(A, G, n, 0, 1);
+       get_gradient_points(A, G, n, 0, 3);
          //r1 is inner radius, r2 is outer radius
        r1 = G[1].x;
        r2 = G[1].y;
@@ -867,5 +923,7 @@ gvplugin_installed_t gvdevice_dot_types[] = {
     {FORMAT_PLAIN, "plain:dot", 1, NULL, &device_features_dot},
     {FORMAT_PLAIN_EXT, "plain-ext:dot", 1, NULL, &device_features_dot},
     {FORMAT_XDOT, "xdot:xdot", 1, NULL, &device_features_dot},
+    {FORMAT_XDOT12, "xdot1.2:xdot", 1, NULL, &device_features_dot},
+    {FORMAT_XDOT14, "xdot1.4:xdot", 1, NULL, &device_features_dot},
     {0, NULL, 0, NULL, NULL}
 };