html-like label port unrecognized

Hi, I want to connect edges to nodes' port using html-like labels, but I get warnings like below:

Warning: node o, port 0 unrecognized
Warning: node o, port 1 unrecognized
Warning: node o, port 0 unrecognized
Warning: node o, port 1 unrecognized

This is the generated png. I put the equivalent dot description in gvedit, and it works fine. So am i miss something in the c++ code?

The dot:

digraph {

node[shape=none];

o[label=<<table border="0" cellborder="1" cellspacing="0"> \

        <tr><td fixedsize="true" width="36" height="20" port="0">0</td></tr> \

        <tr><td fixedsize="true" width="36" height="20" port="1">1</td></tr> \

        </table>>];

a[label=<<table border="0" cellborder="1" cellspacing="0"> \

        <tr><td fixedsize="true" width="36" height="20" port="0">0</td></tr> \

        <tr><td fixedsize="true" width="36" height="20" port="1">1</td></tr> \

        </table>>];

b[label=<<table border="0" cellborder="1" cellspacing="0"> \

        <tr><td fixedsize="true" width="36" height="20" port="0">0</td></tr> \

        <tr><td fixedsize="true" width="36" height="20" port="1">1</td></tr> \

        </table>>];

a->o[headport=0];

a->o[headport=1];

b->o[headport=0];

b->o[headport=1];

}

and the c++ code:

#include "gvc.h"
#include "cgraph.h"
#include <iostream>
using namespace std;

int main()
{
    GVC_t *context = gvContext();
    Agdesc_t dir = { 1, 0, 0, 1 };
    Agraph_t *graph = agopen((char *)("graph"), dir, NULL);

    Agnode_t *o = agnode(graph, (char *)("o"), 1);
    Agnode_t *a = agnode(graph, (char *)("a"), 1);
    Agnode_t *b = agnode(graph, (char *)("b"), 1);
    agsafeset(o, (char *)("shape"), (char *)("none"), (char *)(""));
    agsafeset(a, (char *)("shape"), (char *)("none"), (char *)(""));
    agsafeset(b, (char *)("shape"), (char *)("none"), (char *)(""));

    const char *labelo = "<<table border=\"0\" cellborder=\"1\" cellspacing=\"0\"> \
                          <tr><td fixedsize=\"true\" width=\"36\" height=\"20\" port=\"0\">0</td></tr> \
                          <tr><td fixedsize=\"true\" width=\"36\" height=\"20\" port=\"1\">1</td></tr> \
                          </table>>";
    const char *labela = "<<table border=\"0\" cellborder=\"1\" cellspacing=\"0\"> \
                          <tr><td fixedsize=\"true\" width=\"36\" height=\"20\" port=\"0\">0</td></tr> \
                          <tr><td fixedsize=\"true\" width=\"36\" height=\"20\" port=\"1\">1</td></tr> \
                          </table>>";
    const char *labelb = "<<table border=\"0\" cellborder=\"1\" cellspacing=\"0\"> \
                          <tr><td fixedsize=\"true\" width=\"36\" height=\"20\" port=\"0\">0</td></tr> \
                          <tr><td fixedsize=\"true\" width=\"36\" height=\"20\" port=\"1\">1</td></tr> \
                          </table>>";
    agsafeset(o, (char *)("label"), (char *)(labelo), (char *)(""));
    agsafeset(a, (char *)("label"), (char *)(labela), (char *)(""));
    agsafeset(b, (char *)("label"), (char *)(labelb), (char *)(""));

    Agedge_t *ao0 = agedge(graph, a, o, (char *)("ao0"), 1);
    Agedge_t *ao1 = agedge(graph, a, o, (char *)("ao1"), 1);
    Agedge_t *bo0 = agedge(graph, b, o, (char *)("bo0"), 1);
    Agedge_t *bo1 = agedge(graph, b, o, (char *)("bo1"), 1);

    agsafeset(ao0, (char *)("headport"), (char *)("0"), (char *)(""));
    agsafeset(ao1, (char *)("headport"), (char *)("1"), (char *)(""));
    agsafeset(bo0, (char *)("headport"), (char *)("0"), (char *)(""));
    agsafeset(bo1, (char *)("headport"), (char *)("1"), (char *)(""));

    gvLayout(context, graph, "twopi");
    gvRenderFilename(context, graph, "png", "htmlnode.png");

    gvFreeLayout(context, graph);
    agclose(graph);
    gvFreeContext(context);

    return 0;
}

 

AttachmentSize
htmlnode.png17.26 KB

In the dot language, <..> act

In the dot language, <..> act as string delimiters just like "...". The actual content of the string is what is left after you strip off the delimiters. So if you use <<font color="blue">this</font>> in dot, the actual string is <font color="blue">this</font>, so in C++ you would do

  agsafeset(o, (char *)("label"), (char *)("<font color="blue">this</font>"), (char *)(""));

Secondly, you need to tell graphviz that you want the string interpreted as an HTML-like label. Otherwise, the content will be interpreted literally, just as though you put "..." around the string in your dot file. In C++, this is done by calling agstrdup_html:

  agsafeset(o, (char *)("label"), agstrdup_html("<font color="blue">this</font>"), (char *)(""));

gap between edge tail and node

Thanks. I also find the agstrdup_html in the doc. I should have read it thoroughly. And another question. See the pic,I want an edge from center south port of the whole node a to c, but there's a gap between edge tail and node. It seems the edge ac originates from a hidden box of node a. Is there any way to make the edge originate just close to node a?

This is the dot:

digraph {

a[label=<<table border="0" cellborder="1" cellspacing="0"> \

  <tr><td port="0">0</td><td rowspan="2" port="right">right</td></tr> \

  <tr><td port="1">1</td></tr> \

  </table>> shape=none];

b[shape=box];

a->b[tailport="1:s"];

a->c[tailport=s];

}

 

Set margin=0 in a

Set margin=0 in a

Recent comments