Giter Club home page Giter Club logo

go-graphviz's Introduction

trophy

go-graphviz's People

Contributors

ankon avatar denk0403 avatar goccy avatar joelanford avatar k1low avatar leonnicolas avatar mranney-dd avatar negbie avatar onwsk8r avatar zaporter-work avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

go-graphviz's Issues

Vendoring with `go mod vendor` leads to "fatal error: 'config.h' file not found"

Note: apologies if this issue has been reported before, or if there's a common solution to this problem -- it's the first time I've ever run into vendoring issues with a module including C source code so I'm still researching what's going on!

This could also be an issue with go mod vendor or my understanding of it.


I'm on Mac OS X 10.14.6.

When I vendor in graphviz using go mod vendor, I get a missing C header error:

# github.com/goccy/go-graphviz/internal/ccall
vendor/github.com/goccy/go-graphviz/internal/ccall/ccall.go:27:10: fatal error: 'config.h' file not found
#include "config.h"
         ^~~~~~~~~~
1 error generated.

I'm on graphviz 0.0.6:

✗ grep -i graphviz go.sum
github.com/goccy/go-graphviz v0.0.6 h1:sCT69fmH2KKsObVfsozYyKXxrqmIfo3SyHZs72xkgxs=
github.com/goccy/go-graphviz v0.0.6/go.mod h1:wXVsXxmyMQU6TN3zGRttjNn3h+iCAS7xQFC6TlNvLhk=

Here's what gets vendored in -- none of the headers:

✗ tree vendor/github.com/goccy/go-graphviz/        
vendor/github.com/goccy/go-graphviz/
├── LICENSE
├── README.md
├── cdt
│   └── cdt.go
├── cgraph
│   ├── attribute.go
│   └── cgraph.go
├── go.mod
├── go.sum
├── graphviz.go
├── gvc
│   ├── gvc.go
│   ├── image_renderer.go
│   └── renderer.go
├── internal
│   └── ccall
│       ├── builtin.c
│       ├── ccall.go
│       ├── cdt.c
│       ├── cdt.go
│       ├── cgraph.c
│       ├── cgraph.go
│       ├── circogen.c
│       ├── common.c
│       ├── common.go
│       ├── dotgen.c
│       ├── expat.c
│       ├── expat.go
│       ├── fdpgen.c
│       ├── gvc.c
│       ├── gvc.go
│       ├── label.c
│       ├── neatogen.c
│       ├── ortho.c
│       ├── osage.c
│       ├── pack.c
│       ├── patchwork.c
│       ├── pathplan.c
│       ├── plugin.c
│       ├── rbtree.c
│       ├── sfdpgen.c
│       ├── sparse.c
│       ├── twopigen.c
│       └── xdot.c
└── option.go

When I just rm -r vendor, this problem goes away and everything works fine. (Unfortunately, I may be forced to vendor :( )

Can't create two edges between two nodes

Short description

I can't create two edges between two nodes. (two from node a to b).
graph
Second edge replaces the first one.

Code example

Go code
g := graphviz.New()
graph, err := g.Graph()
n, err := graph.CreateNode("n")
if err != nil {
	log.Err(err.Error())
}
m, err := graph.CreateNode("m")
if err != nil {
	log.Err(err.Error())
}
e, err := graph.CreateEdge("e", n, m)
if err != nil {
	log.Err(err.Error())
}
e.SetLabel("e")
f, err := graph.CreateEdge("f", n, m)
if err != nil {
	log.Err(err.Error())
}
f.SetLabel("f")
var buf bytes.Buffer
if err := g.Render(graph, "dot", &buf); err != nil {
	log.Err(err.Error())
}
Dot output
digraph "" {
	graph [bb="0,0,54,124.8"];
	node [label="\N"];
	n	 [height=0.5,
		pos="27,106.8",
		width=0.75];
	m	 [height=0.5,
		pos="27,18",
		width=0.75];
	n -> m [key=e,
	label=f,
	lp="29.33,62.4",
	pos="e,27,36.072 27,88.401 27,76.295 27,60.208 27,46.467"];
}
Generated graph

Screenshot

Text Overflow

Playing around with this library for fun. Running into an issue where the default renderer seems to produce images that have the text overflowed beyond their bounding boxes.

Using a fairly simple digraph:

digraph test {
	graph [bb="0,0,1075.5,373",
		fontsize=9,
		rankdir=LR
	];
	node [label="\N",
		shape=ellipse
	];
	edge [arrowhead=normal];
	"warehouse_clean.champion_data"	 [height=0.5,
		pos="179.66,18",
		shape=box,
		width=2.4736];
	"warehouse_clean.raw_game_champions"	 [height=0.5,
		pos="496.04,72",
		shape=box,
		width=2.7979];
	"warehouse_raw.raw_game_champions"	 [height=0.5,
		pos="179.66,72",
		shape=box,
		width=2.6791];
	"warehouse_raw.raw_game_champions" -> "warehouse_clean.raw_game_champions" [key=e,
	arrowhead=empty,
	pos="e,395.05,72 276.3,72 310.54,72 349.33,72 384.69,72"];
"warehouse_clean.participant_information" [height=0.5,
	pos="496.04,153",
	shape=box,
	width=2.722];
"warehouse_dw.dim_mmr_percentiles" [height=0.5,
	pos="734.26,180",
	shape=box,
	width=2.8194];
"warehouse_clean.participant_information" -> "warehouse_dw.dim_mmr_percentiles" [key=e,
arrowhead=empty,
pos="e,632.75,168.49 594.31,164.14 603.62,165.19 613.12,166.27 622.55,167.34"];
"raw_production.internal__player_participant_information" [height=0.5,
pos="179.66,193",
shape=box,
width=4.4287];
"raw_production.internal__player_participant_information" -> "warehouse_clean.participant_information" [key=e,
arrowhead=empty,
pos="e,397.82,165.42 322.11,174.99 344.2,172.2 366.7,169.35 387.87,166.68"];
"raw_production.internal__lol__eogd__participant_information" [height=0.5,
pos="179.66,139",
shape=box,
width=4.9904];
"raw_production.internal__lol__eogd__participant_information" -> "warehouse_clean.participant_information" [key=e,
arrowhead=empty,
pos="e,397.83,148.65 359.57,146.96 369.07,147.38 378.46,147.8 387.61,148.2"];
"warehouse_dm.dim_mmr_percentiles" [height=0.5,
pos="973.65,180",
shape=box,
width=2.8303];
"warehouse_dw.dim_mmr_percentiles" -> "warehouse_dm.dim_mmr_percentiles" [key=e,
arrowhead=empty,
pos="e,871.59,180 835.78,180 844.3,180 852.95,180 861.54,180"];
"warehouse_dw.dim_env" [height=0.5,
pos="496.04,207",
shape=box,
width=1.7936];
"warehouse_dw.dim_env" -> "warehouse_dw.dim_mmr_percentiles" [key=e,
arrowhead=empty,
pos="e,632.76,191.5 560.82,199.66 579.97,197.49 601.5,195.05 622.71,192.64"];
"warehouse_raw.raw__game_items" [height=0.5,
pos="179.66,247",
shape=box,
width=2.3552];
"warehouse_raw.raw_game_items" [height=0.5,
pos="179.66,301",
shape=box,
width=2.258];
"warehouse_raw.raw_game_map_modes" [height=0.5,
pos="179.66,355",
shape=box,
width=2.7763];
}

Produces an image where the text is completely overflow'd past the bounding box.

Build warnings of [-Wsingle-bit-bitfield-constant-conversion] from outdated GraphViz library

Environment details

Go version

$ go version
go version go1.21.1 darwin/arm64

C Compiler

$ go env
...
CC='clang'
...

$ clang --version
Apple clang version 15.0.0 (clang-1500.1.0.2.5)
Target: arm64-apple-darwin23.2.0
Thread model: posix
...

Issue

When building the example code in the repository's readme with go build, I see the following compiler warnings from clang:

# github.com/goccy/go-graphviz/internal/ccall
In file included from common.c:5:
../../../../go/modcache/github.com/goccy/[email protected]/internal/ccall/common/emit.c:165:35: warning: implicit truncation from 'int' to a one-bit wide bit-field changes value from 1 to -1 [-Wsingle-bit-bitfield-constant-conversion]
../../../../go/modcache/github.com/goccy/[email protected]/internal/ccall/common/emit.c:2540:24: warning: implicit truncation from 'int' to a one-bit wide bit-field changes value from 1 to -1 [-Wsingle-bit-bitfield-constant-conversion]
../../../../go/modcache/github.com/goccy/[email protected]/internal/ccall/common/emit.c:2596:35: warning: implicit truncation from 'int' to a one-bit wide bit-field changes value from 1 to -1 [-Wsingle-bit-bitfield-constant-conversion]
../../../../go/modcache/github.com/goccy/[email protected]/internal/ccall/common/emit.c:2602:35: warning: implicit truncation from 'int' to a one-bit wide bit-field changes value from 1 to -1 [-Wsingle-bit-bitfield-constant-conversion]
../../../../go/modcache/github.com/goccy/[email protected]/internal/ccall/common/emit.c:2612:31: warning: implicit truncation from 'int' to a one-bit wide bit-field changes value from 1 to -1 [-Wsingle-bit-bitfield-constant-conversion]
../../../../go/modcache/github.com/goccy/[email protected]/internal/ccall/common/emit.c:2623:31: warning: implicit truncation from 'int' to a one-bit wide bit-field changes value from 1 to -1 [-Wsingle-bit-bitfield-constant-conversion]
../../../../go/modcache/github.com/goccy/[email protected]/internal/ccall/common/emit.c:2628:31: warning: implicit truncation from 'int' to a one-bit wide bit-field changes value from 1 to -1 [-Wsingle-bit-bitfield-constant-conversion]
../../../../go/modcache/github.com/goccy/[email protected]/internal/ccall/common/emit.c:2641:28: warning: implicit truncation from 'int' to a one-bit wide bit-field changes value from 1 to -1 [-Wsingle-bit-bitfield-constant-conversion]
../../../../go/modcache/github.com/goccy/[email protected]/internal/ccall/common/emit.c:2650:33: warning: implicit truncation from 'int' to a one-bit wide bit-field changes value from 1 to -1 [-Wsingle-bit-bitfield-constant-conversion]
../../../../go/modcache/github.com/goccy/[email protected]/internal/ccall/common/emit.c:2659:32: warning: implicit truncation from 'int' to a one-bit wide bit-field changes value from 1 to -1 [-Wsingle-bit-bitfield-constant-conversion]
../../../../go/modcache/github.com/goccy/[email protected]/internal/ccall/common/emit.c:2668:32: warning: implicit truncation from 'int' to a one-bit wide bit-field changes value from 1 to -1 [-Wsingle-bit-bitfield-constant-conversion]

Note that this is a separate issue from #72 and is not fixed by #77.

These come from the bundled GraphViz library assigning a literal 1 to signed int bitfields of an obj_state_t. This issue was resolved in GraphViz 3.0.0 released on 2022-02-26. The specific commit with the fix is 96f9d101, which simply changes the relevant bitfields to unsigned ints. These bitfields are present in go-graphviz here:

int explicit_tooltip:1;
int explicit_tailtooltip:1;
int explicit_headtooltip:1;
int explicit_labeltooltip:1;
int explicit_tailtarget:1;
int explicit_headtarget:1;
int explicit_edgetarget:1;
int explicit_tailurl:1;
int explicit_headurl:1;
int labeledgealigned:1;

This issue can be resolved extremely easily by replacing the int keyword with unsigned (alias for unsigned int) in the above code, just as the GraphViz developers did. However, I would like to push for #42 to be finished and the bundled libraries (including GraphViz and Expat) to be updated to more recent versions. Updating the bundled dependencies would close out several other issues in this repository, like #47. More pressingly, bundling outdated libraries poses a security risk, as evidenced by the Expat CVEs mentioned in #76.

Please let me know if you would like me to submit a PR for the specific issue of the bitfield warnings. In the meantime, can you provide a timeline on when the bundled libraries might be able to be updated? Thank you.

Graphviz built without any triangulation library

Using

g := graphviz.New()
	graph, err := g.Graph()
	graph.SetLayout("fdp") 
	graph.SetOverlap(false)

And rendering to svg

	var buf bytes.Buffer
	if err := g.Render(graph, graphviz.SVG, &buf); err != nil {
	log.Fatal(err)
	}
	_, err = g.RenderImage(graph)
	if err != nil {
	log.Fatal(err)
	}
	if err := g.RenderFilename(graph, graphviz.SVG, "mygraph.svg"); err != nil {
	log.Fatal(err)
	}

Results in an error 2023/02/07 10:51:52 delaunay_tri: Graphviz built without any triangulation library

I'm running MacOS Ventura 13.1, fully updated. GTS is installed

brew list --versions gts
gts 0.7.6_2

Since graphviz is packaged with go-graphviz, I'm guessing it probably has to be built with gts?

Support multi-byte fonts

Hi @goccy !

This is feature request.

I want to use go-graphviz with multi-byte fonts.

Example DOT and current render results

Example DOT
digraph "blog" {
  // Config
  graph [rankdir=TB, layout=dot, fontname="Arial"];
  node [shape=record, fontsize=14, margin=0.6, fontname="Arial"];
  edge [fontsize=10, labelfloat=false, splines=none, fontname="Arial"];

  // Tables
  "users" [shape=none, label=<<table border="0" cellborder="1" cellspacing="0" cellpadding="6">
                 <tr><td bgcolor="#EFEFEF"><font face="Arial Bold" point-size="18">users</font> <font color="#666666">[BASE TABLE]</font><br /><font color="#333333">ユーザテーブル</font></td></tr>
                 <tr><td port="id" align="left">id <font color="#666666">[int(11)]</font></td></tr>
                 <tr><td port="username" align="left">username <font color="#666666">[varchar(50)]</font></td></tr>
                 <tr><td port="password" align="left">password <font color="#666666">[varchar(50)]</font></td></tr>
                 <tr><td port="email" align="left">email <font color="#666666">[varchar(355)]</font> ex. [email protected]</td></tr>
                 <tr><td port="created" align="left">created <font color="#666666">[timestamp]</font></td></tr>
                 <tr><td port="updated" align="left">updated <font color="#666666">[timestamp]</font></td></tr>
              </table>>];
  "posts" [shape=none, label=<<table border="0" cellborder="1" cellspacing="0" cellpadding="6">
                 <tr><td bgcolor="#EFEFEF"><font face="Arial Bold" point-size="18">posts</font> <font color="#666666">[BASE TABLE]</font><br /><font color="#333333">投稿テーブル</font></td></tr>
                 <tr><td port="id" align="left">id <font color="#666666">[bigint(20)]</font></td></tr>
                 <tr><td port="user_id" align="left">user_id <font color="#666666">[int(11)]</font></td></tr>
                 <tr><td port="title" align="left">title <font color="#666666">[varchar(255)]</font></td></tr>
                 <tr><td port="body" align="left">body <font color="#666666">[text]</font> post body</td></tr>
                 <tr><td port="post_type" align="left">post_type <font color="#666666">[enum(&#39;public&#39;,&#39;private&#39;,&#39;draft&#39;)]</font> public/private/draft</td></tr>
                 <tr><td port="created" align="left">created <font color="#666666">[datetime]</font></td></tr>
                 <tr><td port="updated" align="left">updated <font color="#666666">[datetime]</font></td></tr>
              </table>>];

  // Relations
  "posts":"user_id" -> "users":"id" [dir=back, arrowtail=crow, style ="dashed", taillabel=<<table cellpadding="5" border="0" cellborder="0"><tr><td>ユーザと投稿の関連</td></tr></table>>];
}

Render results

Graphviz 2.44.0 via Homebrew goccy/go-graphviz/cmd/dot
logs dot logs dot2

Best Regards.

Edge is not getting labeled

The Edge name or label is getting marked as key, and svg image generated doesn't show any name for the edge. (If I change key to label, then edge name shows up)

digraph "" {
	graph [bb="0,0,236.29,108"];
	node [fillcolor=lightgrey,
		label="\N"
	];
	subgraph preupgrade {
		graph [label=preupgrade];
		"A/a.preupgrade"		 [URL="sample/library/A/a.preupgrade",
			height=0.5,
			label="Checking for \"A\" settings",
			pos="118.15,90",
			style=filled,
			width=3.0807];
		"D/d.preupgrade"		 [URL="sample/library/D/d.preupgrade",
			height=0.5,
			label="Checking for \"D\" settings...",
			pos="118.15,18",
			style=filled,
			width=3.2818];
		"A/a.preupgrade" -> "D/d.preupgrade" [key=Requires,pos="e,112.17,36.413 112.19,71.831 111.44,64.131 111.22,54.974 111.53,46.417"];
	"D/d.preupgrade" -> "A/a.preupgrade" [key=RequiredBy,
	pos="e,124.1,71.831 124.12,36.413 124.85,44.059 125.07,53.108 124.76,61.573"];
}
}

Code related to above dot / image: https://github.com/VeritasOS/plugin-manager/blob/v2/vendor/github.com/abhijithda/pm-graph/v3/graph.go#L95-L103 .

image

HTML labels containing images and their locations

Maybe this is a documentation quest, or maybe it is an enhancement request.

I have a web server that uses goccy/go-graphviz to render several different graphs to SVG.

GraphViz.Render() needs to read the images on the HTML labels to learn their size, and also preserve the image URLs so the browser can also fetch them.

As far as I can see, GraphViz.Render() is using the current working directory and opening the file. I would like to be able to customize the way Render() looks up the images, so that the rendering isn't tied to the filesystem. I'd like to supply GraphViz with a callback for image file data and metadata retrieval. Is this currently possible?

Example

mynode [ label=<<TABLE BORDER="0"><TR><TD><IMG SRC="./static/icons/pod-128.png" /></TD></TR><TR><TD>Pod</TD></TR></TABLE>> ]

lld-link: error in Windows

Hi, I am new in Golang, when I install go-graphviz, I can install successful in Linux, but got error in Windows10.

Environment: Windows 10 x64, go1.15,llvm-mingw-20201020-ucrt-x86_64,Visual Studio 2019

Here is the log:

PS C:\Users\Administrator\go> go get -u github.com/goccy/go-graphviz
# github.com/goccy/go-graphviz/internal/ccall
lld-link: error: duplicate symbol: lt_preloaded_symbols
>>> defined at src\github.com\goccy\go-graphviz\internal\ccall\gvc\gvcext.h:73
>>>            $WORK\b038\_x001.o
>>> defined at src\github.com\goccy\go-graphviz\internal\ccall\gvc\gvcext.h:73
>>>            $WORK\b038\_x002.o

lld-link: error: duplicate symbol: Dtset
>>> defined at src\github.com\goccy\go-graphviz\internal\ccall\cdt\cdt.h:169
>>>            $WORK\b038\_x001.o
>>> defined at src\github.com\goccy\go-graphviz\internal\ccall\cdt\cdt.h:169
>>>            $WORK\b038\_x002.o

lld-link: error: duplicate symbol: Dtbag
>>> defined at src\github.com\goccy\go-graphviz\internal\ccall\cdt\cdt.h:170
>>>            $WORK\b038\_x001.o
>>> defined at src\github.com\goccy\go-graphviz\internal\ccall\cdt\cdt.h:170
>>>            $WORK\b038\_x002.o

lld-link: error: duplicate symbol: Dtoset
>>> defined at src\github.com\goccy\go-graphviz\internal\ccall\cdt\cdt.h:171
>>>            $WORK\b038\_x001.o
>>> defined at src\github.com\goccy\go-graphviz\internal\ccall\cdt\cdt.h:171
>>>            $WORK\b038\_x002.o

lld-link: error: duplicate symbol: Dtobag
>>> defined at src\github.com\goccy\go-graphviz\internal\ccall\cdt\cdt.h:172
>>>            $WORK\b038\_x001.o
>>> defined at src\github.com\goccy\go-graphviz\internal\ccall\cdt\cdt.h:172
>>>            $WORK\b038\_x002.o

lld-link: error: duplicate symbol: Dtlist
>>> defined at src\github.com\goccy\go-graphviz\internal\ccall\cdt\cdt.h:173
>>>            $WORK\b038\_x001.o
>>> defined at src\github.com\goccy\go-graphviz\internal\ccall\cdt\cdt.h:173
>>>            $WORK\b038\_x002.o

lld-link: error: duplicate symbol: Dtstack
>>> defined at src\github.com\goccy\go-graphviz\internal\ccall\cdt\cdt.h:174
>>>            $WORK\b038\_x001.o
>>> defined at src\github.com\goccy\go-graphviz\internal\ccall\cdt\cdt.h:174
>>>            $WORK\b038\_x002.o

lld-link: error: duplicate symbol: Dtqueue
>>> defined at src\github.com\goccy\go-graphviz\internal\ccall\cdt\cdt.h:175
>>>            $WORK\b038\_x001.o
>>> defined at src\github.com\goccy\go-graphviz\internal\ccall\cdt\cdt.h:175
>>>            $WORK\b038\_x002.o

lld-link: error: duplicate symbol: Dtdeque
>>> defined at src\github.com\goccy\go-graphviz\internal\ccall\cdt\cdt.h:176
>>>            $WORK\b038\_x001.o
>>> defined at src\github.com\goccy\go-graphviz\internal\ccall\cdt\cdt.h:176
>>>            $WORK\b038\_x002.o

lld-link: error: duplicate symbol: Dtorder
>>> defined at src\github.com\goccy\go-graphviz\internal\ccall\cdt\cdt.h:180
>>>            $WORK\b038\_x001.o
>>> defined at src\github.com\goccy\go-graphviz\internal\ccall\cdt\cdt.h:180
>>>            $WORK\b038\_x002.o

lld-link: error: duplicate symbol: Dttree
>>> defined at src\github.com\goccy\go-graphviz\internal\ccall\cdt\cdt.h:181
>>>            $WORK\b038\_x001.o
>>> defined at src\github.com\goccy\go-graphviz\internal\ccall\cdt\cdt.h:181
>>>            $WORK\b038\_x002.o

lld-link: error: duplicate symbol: Dthash
>>> defined at src\github.com\goccy\go-graphviz\internal\ccall\cdt\cdt.h:182
>>>            $WORK\b038\_x001.o
>>> defined at src\github.com\goccy\go-graphviz\internal\ccall\cdt\cdt.h:182
>>>            $WORK\b038\_x002.o

lld-link: error: duplicate symbol: _Dttree
>>> defined at src\github.com\goccy\go-graphviz\internal\ccall\cdt\cdt.h:183
>>>            $WORK\b038\_x001.o
>>> defined at src\github.com\goccy\go-graphviz\internal\ccall\cdt\cdt.h:183
>>>            $WORK\b038\_x002.o

lld-link: error: duplicate symbol: _Dthash
>>> defined at src\github.com\goccy\go-graphviz\internal\ccall\cdt\cdt.h:184
>>>            $WORK\b038\_x001.o
>>> defined at src\github.com\goccy\go-graphviz\internal\ccall\cdt\cdt.h:184
>>>            $WORK\b038\_x002.o

lld-link: error: duplicate symbol: _Dtlist
>>> defined at src\github.com\goccy\go-graphviz\internal\ccall\cdt\cdt.h:185
>>>            $WORK\b038\_x001.o
>>> defined at src\github.com\goccy\go-graphviz\internal\ccall\cdt\cdt.h:185
>>>            $WORK\b038\_x002.o

lld-link: error: duplicate symbol: _Dtqueue
>>> defined at src\github.com\goccy\go-graphviz\internal\ccall\cdt\cdt.h:186
>>>            $WORK\b038\_x001.o
>>> defined at src\github.com\goccy\go-graphviz\internal\ccall\cdt\cdt.h:186
>>>            $WORK\b038\_x002.o

lld-link: error: duplicate symbol: _Dtstack
>>> defined at src\github.com\goccy\go-graphviz\internal\ccall\cdt\cdt.h:187
>>>            $WORK\b038\_x001.o
>>> defined at src\github.com\goccy\go-graphviz\internal\ccall\cdt\cdt.h:187
>>>            $WORK\b038\_x002.o

lld-link: error: duplicate symbol: Dtset
>>> defined at src\github.com\goccy\go-graphviz\internal\ccall\cdt\cdt.h:169
>>>            $WORK\b038\_x001.o
>>> defined at src\github.com\goccy\go-graphviz\internal\ccall\cdt\cdt.h:169
>>>            $WORK\b038\_x003.o

lld-link: error: duplicate symbol: Dtbag
>>> defined at src\github.com\goccy\go-graphviz\internal\ccall\cdt\cdt.h:170
>>>            $WORK\b038\_x001.o
>>> defined at src\github.com\goccy\go-graphviz\internal\ccall\cdt\cdt.h:170
>>>            $WORK\b038\_x003.o

lld-link: error: duplicate symbol: Dtoset
>>> defined at src\github.com\goccy\go-graphviz\internal\ccall\cdt\cdt.h:171
>>>            $WORK\b038\_x001.o
>>> defined at src\github.com\goccy\go-graphviz\internal\ccall\cdt\cdt.h:171
>>>            $WORK\b038\_x003.o

lld-link: error: too many errors emitted, stopping now (use /errorlimit:0 to see all errors)
clang-11: error: linker command failed with exit code 1 (use -v to see invocation)
# github.com/goccy/go-graphviz/internal/ccall
In file included from common.c:17:
src\github.com\goccy\go-graphviz\internal\ccall/common/postproc.c:685:6: warning: 'sprintf' will always overflow; destination buffer has size 512, but format string expands to at least 813 [-Wfortify-source]
PS C:\Users\Administrator\go>

Thank you for see this, hope this not disturb you.

How to Change Rendered Image Resolution?

I am currently using the RenderImage function. However, the resolution of the resulting image is too low for my needs. Is there any way to change the resolution of the rendered image using the RenderImage function?

Unable to build binary for project with a dependency on go-graphviz

Based on this example, I put together a tiny example repo bringing in go-graphviz.

I'm able to run go run successfully, but I'm not able to build binaries -- either for mac, or cross-compiling for linux.

package main

import (
	"github.com/goccy/go-graphviz"
)

func main() {
	g := graphviz.New()
	graph, _ := g.Graph()
	a, _ := graph.CreateNode("a")
	b, _ := graph.CreateNode("b")
	graph.CreateEdge("a2b", a, b)

	g.RenderFilename(graph, graphviz.PNG, "./graph.png")
}

Output:

./build.sh 
#set -euo pipefail

go run cmd/graphviz/main.go
+ go run cmd/graphviz/main.go

CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build -o ./cmd/graphviz/main ./cmd/graphviz
+ CGO_ENABLED=0
+ GOOS=darwin
+ GOARCH=amd64
+ go build -o ./cmd/graphviz/main ./cmd/graphviz
package github.com/mattfenwick/graphviz-test/cmd/graphviz
	imports github.com/goccy/go-graphviz
	imports github.com/goccy/go-graphviz/cgraph
	imports github.com/goccy/go-graphviz/internal/ccall: build constraints exclude all Go files in /Users/mfenwick/go/pkg/mod/github.com/goccy/[email protected]/internal/ccall

CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o ./cmd/graphviz/main ./cmd/graphviz
+ CGO_ENABLED=0
+ GOOS=linux
+ GOARCH=amd64
+ go build -o ./cmd/graphviz/main ./cmd/graphviz
package github.com/mattfenwick/graphviz-test/cmd/graphviz
	imports github.com/goccy/go-graphviz
	imports github.com/goccy/go-graphviz/cgraph
	imports github.com/goccy/go-graphviz/internal/ccall: build constraints exclude all Go files in /Users/mfenwick/go/pkg/mod/github.com/goccy/[email protected]/internal/ccall

I'm working on a Mac.

How can I build mac and linux binaries where I'm including go-graphviz ?

unexpected signal during runtime execution

When I use RenderFilename to generate a SVG, something happend:

fatal error: unexpected signal during runtime execution
[signal SIGSEGV: segmentation violation code=0x1 addr=0x10 pc=0x4bedd62]

runtime stack:
runtime.throw(0x4f91d88, 0x2a)
	/.../.gvm/gos/go1.13.10/src/runtime/panic.go:774 +0x72
runtime.sigpanic()
	/.../.gvm/gos/go1.13.10/src/runtime/signal_unix.go:378 +0x47c

goroutine 801 [syscall]:
runtime.cgocall(0x4b9aab0, 0xc000541ba0, 0x3)
	/.../.gvm/gos/go1.13.10/src/runtime/cgocall.go:128 +0x5b fp=0xc000541b70 sp=0xc000541b38 pc=0x400588b
github.com/goccy/go-graphviz/internal/ccall._Cfunc_gvLayout(0x6613d80, 0x6615530, 0x653ac70, 0x0)
	_cgo_gotypes.go:2365 +0x4d fp=0xc000541ba0 sp=0xc000541b70 pc=0x48da6ad
github.com/goccy/go-graphviz/internal/ccall.GvLayout.func1(0xc000f25048, 0xc000f25058, 0x4f6278f, 0x3, 0x4070b0c)
	/.../.gvm/pkgsets/go1.13.10/global/pkg/mod/github.com/goccy/[email protected]/internal/ccall/gvc.go:736 +0xe7 fp=0xc000541bf0 sp=0xc000541ba0 pc=0x48ea547
github.com/goccy/go-graphviz/internal/ccall.GvLayout(0xc000f25048, 0xc000f25058, 0x4f6278f, 0x3, 0x4f39e00, 0xc0001520d0)
	/.../.gvm/pkgsets/go1.13.10/global/pkg/mod/github.com/goccy/[email protected]/internal/ccall/gvc.go:736 +0x49 fp=0xc000541c28 sp=0xc000541bf0 pc=0x48e5e29
github.com/goccy/go-graphviz/gvc.(*Context).Layout(...)
	/.../.gvm/pkgsets/go1.13.10/global/pkg/mod/github.com/goccy/[email protected]/gvc/gvc.go:29
github.com/goccy/go-graphviz.(*Graphviz).RenderFilename(0xc000c9a990, 0xc000f25060, 0x4f628f7, 0x3, 0xc0003c5ce0, 0x5f, 0x0, 0x0)
	/.../.gvm/pkgsets/go1.13.10/global/pkg/mod/github.com/goccy/[email protected]/graphviz.go:115 +0x73 fp=0xc000541cc0 sp=0xc000541c28 pc=0x4962243

It happened on my mac (v10.14.5)

$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/.../Library/Caches/go-build"
GOENV="/.../Library/Application Support/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GONOPROXY=""
GONOSUMDB=""
GOOS="darwin"
GOPATH="/.../.gvm/pkgsets/go1.13.10/global"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/.../.gvm/gos/go1.13.10"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/.../.gvm/gos/go1.13.10/pkg/tool/darwin_amd64"
GCCGO="gccgo"
AR="ar"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD="/.../go.mod"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/hj/c7qldcv90n59k0bddyjm3mkw0000gn/T/go-build047072890=/tmp/go-build -gno-record-gcc-switches -fno-common"

Would you like to take a look?

ccache: invalid option -- 'E'

when I install by executing this command, 'go get github.com/goccy/go-graphviz'

my go env:

GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/data/ptt/.cache/go-build"
GOENV="/data/ptt/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/data/ptt/private/Server/src/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/opt/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/opt/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
AR="ar"
CC="ccache"
CXX="ccache"
CGO_ENABLED="1"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="/opt/rh/devtoolset-8/root/usr/bin/gcc -fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build559118463=/tmp/go-build -gno-record-gcc-switches"

I got a cgo error.
`# runtime/cgo
ccache: invalid option -- 'E'
Usage:
ccache [options]
ccache compiler [compiler options]
compiler [compiler options] (via symbolic link)

Common options:
-c, --cleanup delete old files and recalculate size counters
(normally not needed as this is done
automatically)
-C, --clear clear the cache completely (except configuration)
-F, --max-files=N set maximum number of files in cache to N (use 0
for no limit)
-M, --max-size=SIZE set maximum size of cache to SIZE (use 0 for no
limit); available suffixes: k, M, G, T (decimal)
and Ki, Mi, Gi, Ti (binary); default suffix: G
-p, --show-config show current configuration options in
human-readable format
-s, --show-stats show summary of configuration and statistics
counters in human-readable format
-z, --zero-stats zero statistics counters

-h, --help                print this help text
-V, --version             print version and copyright information

Options for scripting or debugging:
--dump-manifest=PATH dump manifest file at PATH in text format
-k, --get-config=K print the value of configuration key K
--hash-file=PATH print the hash (-) of the file at PATH
--print-stats print statistics counter IDs and corresponding
values in machine-parsable format
-o, --set-config=K=V set configuration item K to value V

See also https://ccache.dev.`

support setAttr fontname

like this:
func (n *Node) SetFontName(name string) *Node {
n.SafeSet(string(fontNameAttr), name, "")
return n
}

image

Example linker error (macOS)

Amazing package Masaaki! However, I cannot seem to compile your example application after following the installation commands. It fails at the linking stage, with the following error:

/usr/local/go/pkg/tool/darwin_amd64/link: /usr/local/go/pkg/tool/darwin_amd64/link: combining dwarf failed: Unknown load command 0x32 (50)

I am running MacOS 10.15.7, with go1.10 darwin/amd64

Graphviz Update?

One of our internal scanning tools identified the following CVEs present in the included graphviz library: CVE-2019-9904 & CVE-2019-11023. I haven't validated those but I do believe the library is a handful of version behind anyway... not sure how much work it is updating the library code?

panic: segmentation violation

I encountered a crash when using go-callvis, and it seems program crash at go-graphviz/internal/ccall._Cfunc_agmemread Agraph_t *agmemread(const char *cp), i am not sure if it is fixed by graphviz, maybe you should update cgraph?

> go-callvis -group pkg -nostd .
2023/09/06 21:27:57 http serving at http://localhost:7878



2023/09/06 21:49:32 converting dot to svg..
2023/09/06 21:49:32 serving file: /var/folders/6_/65ws8fc97bz20h4r7knc5ngh0000gn/T/go-callvis_export.svg
2023/09/06 22:52:16 converting dot to svg..
2023/09/06 22:52:46 serving file: /var/folders/6_/65ws8fc97bz20h4r7knc5ngh0000gn/T/go-callvis_export.svg
2023/09/06 23:42:05 converting dot to svg..
2023/09/06 23:42:06 serving file: /var/folders/6_/65ws8fc97bz20h4r7knc5ngh0000gn/T/go-callvis_export.svg
2023/09/06 23:42:07 converting dot to svg..
2023/09/06 23:42:08 serving file: /var/folders/6_/65ws8fc97bz20h4r7knc5ngh0000gn/T/go-callvis_export.svg
2023/09/06 23:42:13 converting dot to svg..
2023/09/06 23:42:14 serving file: /var/folders/6_/65ws8fc97bz20h4r7knc5ngh0000gn/T/go-callvis_export.svg
2023/09/06 23:44:03 converting dot to svg..
2023/09/06 23:44:05 serving file: /var/folders/6_/65ws8fc97bz20h4r7knc5ngh0000gn/T/go-callvis_export.svg
2023/09/06 23:46:39 converting dot to svg..
2023/09/06 23:46:40 serving file: /var/folders/6_/65ws8fc97bz20h4r7knc5ngh0000gn/T/go-callvis_export.svg
2023/09/06 23:47:26 converting dot to svg..
2023/09/06 23:47:26 converting dot to svg..
fatal error: unexpected signal during runtime execution
[signal SIGSEGV: segmentation violation code=0x1 addr=0x68 pc=0x1004f68f7]

runtime stack:
runtime.throw({0x10072676a?, 0x600000c1a510?})
        /usr/local/Cellar/[email protected]/1.18.10/libexec/src/runtime/panic.go:992 +0x71
runtime.sigpanic()
        /usr/local/Cellar/[email protected]/1.18.10/libexec/src/runtime/signal_unix.go:802 +0x396

goroutine 8433 [syscall]:
runtime.cgocall(0x1004e0bd0, 0xc015da7788)
        /usr/local/Cellar/[email protected]/1.18.10/libexec/src/runtime/cgocall.go:157 +0x5c fp=0xc015da7760 sp=0xc015da7728 pc=0x10000515c
github.com/goccy/go-graphviz/internal/ccall._Cfunc_agmemread(0x134c35000)
        _cgo_gotypes.go:1449 +0x49 fp=0xc015da7788 sp=0xc015da7760 pc=0x100471e09
github.com/goccy/go-graphviz/internal/ccall.Agmemread({0xc018100000?, 0xc01743e000?})
        /Users/ruokeqx/go/pkg/mod/github.com/goccy/[email protected]/internal/ccall/cgraph.go:883 +0x2e fp=0xc015da77b8 sp=0xc015da7788 pc=0x1004781ce
github.com/goccy/go-graphviz/cgraph.ParseBytes({0xc01743e000, 0x3440b, 0x2c?})
        /Users/ruokeqx/go/pkg/mod/github.com/goccy/[email protected]/cgraph/cgraph.go:105 +0x4d fp=0xc015da7808 sp=0xc015da77b8 pc=0x10047db0d
github.com/goccy/go-graphviz.ParseBytes(...)
        /Users/ruokeqx/go/pkg/mod/github.com/goccy/[email protected]/graphviz.go:50
main.runDotToImage({0x0, 0x0}, {0x10070d734, 0x3}, {0xc01743e000, 0x3440b, 0x3440b})
        /Users/ruokeqx/go/pkg/mod/github.com/ofabry/[email protected]/dot_cgo.go:17 +0xa7 fp=0xc015da7910 sp=0xc015da7808 pc=0x1004d8627
main.dotToImage({0x0?, 0x3?}, {0x10070d734?, 0x6?}, {0xc01743e000?, 0x100b7c000?, 0xc01d58e734?})
        /Users/ruokeqx/go/pkg/mod/github.com/ofabry/[email protected]/dot.go:153 +0x45 fp=0xc015da7958 sp=0xc015da7910 pc=0x1004d7f45
main.handler({0x1007e8f70?, 0xc02d258000}, 0xc021abba00)
        /Users/ruokeqx/go/pkg/mod/github.com/ofabry/[email protected]/handler.go:53 +0x5f7 fp=0xc015da7a20 sp=0xc015da7958 pc=0x1004d9017
net/http.HandlerFunc.ServeHTTP(0x12e42f890?, {0x1007e8f70?, 0xc02d258000?}, 0x10000ec45?)
        /usr/local/Cellar/[email protected]/1.18.10/libexec/src/net/http/server.go:2084 +0x2f fp=0xc015da7a48 sp=0xc015da7a20 pc=0x100428fef
net/http.(*ServeMux).ServeHTTP(0x0?, {0x1007e8f70, 0xc02d258000}, 0xc021abba00)
        /usr/local/Cellar/[email protected]/1.18.10/libexec/src/net/http/server.go:2462 +0x149 fp=0xc015da7a98 sp=0xc015da7a48 pc=0x10042a989
net/http.serverHandler.ServeHTTP({0xc027d39770?}, {0x1007e8f70, 0xc02d258000}, 0xc021abba00)
        /usr/local/Cellar/[email protected]/1.18.10/libexec/src/net/http/server.go:2916 +0x43b fp=0xc015da7b58 sp=0xc015da7a98 pc=0x10042c5db
net/http.(*conn).serve(0xc0159a5220, {0x1007e9348, 0xc05b92eba0})
        /usr/local/Cellar/[email protected]/1.18.10/libexec/src/net/http/server.go:1966 +0x5d7 fp=0xc015da7fb8 sp=0xc015da7b58 pc=0x100427a97
net/http.(*Server).Serve.func3()
        /usr/local/Cellar/[email protected]/1.18.10/libexec/src/net/http/server.go:3071 +0x2e fp=0xc015da7fe0 sp=0xc015da7fb8 pc=0x10042cf2e
runtime.goexit()
        /usr/local/Cellar/[email protected]/1.18.10/libexec/src/runtime/asm_amd64.s:1571 +0x1 fp=0xc015da7fe8 sp=0xc015da7fe0 pc=0x100064881
created by net/http.(*Server).Serve
        /usr/local/Cellar/[email protected]/1.18.10/libexec/src/net/http/server.go:3071 +0x4db

goroutine 1 [IO wait, 70 minutes]:
internal/poll.runtime_pollWait(0x128c20308, 0x72)
        /usr/local/Cellar/[email protected]/1.18.10/libexec/src/runtime/netpoll.go:302 +0x89
internal/poll.(*pollDesc).wait(0xc022b82900?, 0x48?, 0x0)
        /usr/local/Cellar/[email protected]/1.18.10/libexec/src/internal/poll/fd_poll_runtime.go:83 +0x32
internal/poll.(*pollDesc).waitRead(...)
        /usr/local/Cellar/[email protected]/1.18.10/libexec/src/internal/poll/fd_poll_runtime.go:88
internal/poll.(*FD).Accept(0xc022b82900)
        /usr/local/Cellar/[email protected]/1.18.10/libexec/src/internal/poll/fd_unix.go:614 +0x22c
net.(*netFD).accept(0xc022b82900)
        /usr/local/Cellar/[email protected]/1.18.10/libexec/src/net/fd_unix.go:172 +0x35
net.(*TCPListener).accept(0xc015259ae8)
        /usr/local/Cellar/[email protected]/1.18.10/libexec/src/net/tcpsock_posix.go:139 +0x28
net.(*TCPListener).Accept(0xc015259ae8)
        /usr/local/Cellar/[email protected]/1.18.10/libexec/src/net/tcpsock.go:288 +0x3d
net/http.(*Server).Serve(0xc02ba58fc0, {0x1007e8d90, 0xc015259ae8})
        /usr/local/Cellar/[email protected]/1.18.10/libexec/src/net/http/server.go:3039 +0x385
net/http.(*Server).ListenAndServe(0xc02ba58fc0)
        /usr/local/Cellar/[email protected]/1.18.10/libexec/src/net/http/server.go:2968 +0x7d
net/http.ListenAndServe(...)
        /usr/local/Cellar/[email protected]/1.18.10/libexec/src/net/http/server.go:3222
main.main()
        /Users/ruokeqx/go/pkg/mod/github.com/ofabry/[email protected]/main.go:159 +0x425

goroutine 8869 [runnable]:
net/http.(*conn).hijacked(0x10000ec45?)
        /usr/local/Cellar/[email protected]/1.18.10/libexec/src/net/http/server.go:307 +0xa7
net/http.(*response).WriteHeader(0xc02d2580e0, 0x1f4)
        /usr/local/Cellar/[email protected]/1.18.10/libexec/src/net/http/server.go:1135 +0x45
net/http.Error({0x1007e8f70, 0xc02d2580e0}, {0xc060c6fb90, 0x22}, 0xc018f80000?)
        /usr/local/Cellar/[email protected]/1.18.10/libexec/src/net/http/server.go:2096 +0x198
main.handler({0x1007e8f70?, 0xc02d2580e0}, 0xc014e85400)
        /Users/ruokeqx/go/pkg/mod/github.com/ofabry/[email protected]/handler.go:55 +0x745
net/http.HandlerFunc.ServeHTTP(0x12e42f980?, {0x1007e8f70?, 0xc02d2580e0?}, 0x10000ec45?)
        /usr/local/Cellar/[email protected]/1.18.10/libexec/src/net/http/server.go:2084 +0x2f
net/http.(*ServeMux).ServeHTTP(0x0?, {0x1007e8f70, 0xc02d2580e0}, 0xc014e85400)
        /usr/local/Cellar/[email protected]/1.18.10/libexec/src/net/http/server.go:2462 +0x149
net/http.serverHandler.ServeHTTP({0xc02ef201b0?}, {0x1007e8f70, 0xc02d2580e0}, 0xc014e85400)
        /usr/local/Cellar/[email protected]/1.18.10/libexec/src/net/http/server.go:2916 +0x43b
net/http.(*conn).serve(0xc0228f7900, {0x1007e9348, 0xc05b92eba0})
        /usr/local/Cellar/[email protected]/1.18.10/libexec/src/net/http/server.go:1966 +0x5d7
created by net/http.(*Server).Serve
        /usr/local/Cellar/[email protected]/1.18.10/libexec/src/net/http/server.go:3071 +0x4db

Libexpat before 2.4.5 contains a CVE

The "Mend" tool complains about a CVE in the embedded version of Expat. Consider replacing the current Expat source with newer version.

The claim is that

  • xmltok_impl.c in Expat (aka libexpat) before 2.4.5 lacks certain validation of encoding, such as checks for whether a UTF-8 character is valid in a certain context.

Here is Expat's fix of the issue

Go-graphviz is using this version

Related: #42 (comment)

ring bug

a->b->a->b like this , losing the first connecting line

C2x

vendor/github.com/goccy/go-graphviz/internal/ccall/dotgen/dotsplines.c:2310:13: warning: a function declaration without a prototype is deprecated in all versions of C and is not supported in C2x [-Wdeprecated-non-prototype]

occur in mac os 13.3 and go version 1.18

Setting `cluster=true` is still rendering nodes without a cluster box

Setting cluster=true is still rendering nodes without a cluster box via this package. Whereas in the playground, it working fine...
Similar issue with other attributes like bgcolor...

Sample

digraph "" {
	subgraph test {
		graph [bgcolor=red,
			cluster=true,
			label=test,
			style="filled,rounded"
		];
               a -> b
               c -> b
       }
}

Getting:
image

Expected:

image

multi-edges generate error on non-strict digraph

Version

github.com/goccy/go-graphviz v0.0.9

Example Code

package main

import (
	"os"

	"github.com/goccy/go-graphviz"
)

func main() {
	graph := graphviz.New()
	g, _ := graph.Graph(graphviz.Directed, graphviz.Name("G"))

	n1, _ := g.CreateNode("1")
	n2, _ := g.CreateNode("2")
	g.CreateEdge("e1", n1, n2)
	g.CreateEdge("re1", n2, n1)

	g.CreateEdge("e2", n1, n2)
	g.CreateEdge("re2", n2, n1)

	graph.Render(g, graphviz.Format(graphviz.DOT), os.Stdout)
}

Real Output

digraph G {
	graph [bb="0,0,54,108"];
	node [label="\N"];
	1	 [height=0.5,
		pos="27,90",
		width=0.75];
	2	 [height=0.5,
		pos="27,18",
		width=0.75];
	1 -> 2 [key=e1,
	pos="e,21.105,35.593 21.084,72.202 20.28,64.181 20.057,54.523 20.416,45.596"];
2 -> 1 [key=re1,
pos="e,32.916,72.202 32.895,35.593 33.709,43.586 33.942,53.236 33.593,62.176"];
}

Expect

As the graphviz doc, a non-strict graph should allow multi-edges without merging them.

so it should output something like:

digraph G {
	graph [bb="0,0,54,108"];
	node [label="\N"];
	1	 [height=0.5,
		pos="27,90",
		width=0.75];
	2	 [height=0.5,
		pos="27,18",
		width=0.75];
	1 -> 2 [key=e1,
	pos="e,21.105,35.593 21.084,72.202 20.28,64.181 20.057,54.523 20.416,45.596"];
  1 -> 2 [key=e2,
	pos="e,21.105,35.593 21.084,72.202 20.28,64.181 20.057,54.523 20.416,45.596"];
2 -> 1 [key=re1,
pos="e,32.916,72.202 32.895,35.593 33.709,43.586 33.942,53.236 33.593,62.176"];
2 -> 1 [key=re2,
pos="e,32.916,72.202 32.895,35.593 33.709,43.586 33.942,53.236 33.593,62.176"];
}

Apply All node Attribute

Hi,

I want to apply all node to same attribute.

digraph "" {
        graph [bb="0,0,0,0",
                nodesep=0.1,
                rankdir=TB,
                ranksep=0.5,
                stylesheet="../css/svg.css"
        ];
        node [label="\N"]; // → this is auto generated.. 
}

I checked node line is created. But I cannot rich by API.
How can I do that?

Help with graph layout

I have a graph, and I want to set some nodes to be on the far left, some to be on the far right, and the rest can be anywhere in the middle. I have found some code that does what I want in the dot format directly, but I am not sure how to implement this using this package:

digraph G { 

  rankdir = LR;

  A -> B;
  A -> C -> D;
  X -> Y;

  { rank=min; A; X; } // These two lines do what I want
  { rank=max; B; D; Y; } 

}

I have already got all of the code to create and connect the nodes and render them, but I just need what will probably be the two lines of code to do the laying out.

node styles striped/wedged don't work

I see these node styles and graph styles https://github.com/goccy/go-graphviz/blob/master/cgraph/attribute.go#L2491-L2503

However, when I try to actually use them, they don't get rendered properly.

var buf bytes.Buffer
g := graphviz.New()

graph := graphviz.ParseBytes(b) // valid dot file

graph.SetStyle(cgraph.StripedGraphStyle)
graph.FirstNode().SetStyle(cgraph.WedgesNodeStyle)
graph.LastNode().SetStyle(cgraph.StripedNodeStyle)

if err = g.Render(graph, graphviz.PNG, &buf); err != nil {
	return err
}

Setting the style on the graph does nothing. Setting the style of a node to "wedged" puts wedges but the fillcolor is white. Setting the style of a node to "striped" yields an error when I try to render gvrender_set_style: unsupported style striped - ignoring

I have also tried setting these styles in the dot format, rather than after parsing, but I see the same thing.

Could you update the repo to support these styles?

In Windows 'go get' the library fails

Not sure why this is happening, but in Windows 10, performing the 'go get' operation returns the below result.
The package fails to download.

go get "github.com/goccy/go-graphviz"
# github.com/goccy/go-graphviz/internal/ccall
In file included from common.c:5:0:
common/emit.c: In function 'selectedLayer':
common/emit.c:31:18: warning: implicit declaration of function 'strtok_s' [-Wimplicit-function-declaration]
 #define strtok_r strtok_s
                  ^
common/emit.c:1061:38: note: in expansion of macro 'strtok_r'
     while ((rval == FALSE) && (cur = strtok_r(part_in_p, gvc->layerListDelims, &buf_part_p))) {
                                      ^
common/emit.c:1061:36: warning: assignment makes pointer from integer without a cast [-Wint-conversion]
     while ((rval == FALSE) && (cur = strtok_r(part_in_p, gvc->layerListDelims, &buf_part_p))) {
                                    ^
common/emit.c:1062:10: warning: assignment makes pointer from integer without a cast [-Wint-conversion]
  w1 = w0 = strtok_r (cur, gvc->layerDelims, &buf_p);
          ^
common/emit.c:1064:9: warning: assignment makes pointer from integer without a cast [-Wint-conversion]
      w1 = strtok_r (NULL, gvc->layerDelims, &buf_p);
         ^

lightgreen is not a known color.

version

v0.0.9

sample code

package main

import (
	"bytes"
	"log"

	"github.com/goccy/go-graphviz"
	"github.com/goccy/go-graphviz/cgraph"
)

func main() {
	g := graphviz.New()
	graph, err := g.Graph()
	if err != nil {
		log.Fatal(err)
	}

	t, err := graph.CreateNode("test")
	if err != nil {
		log.Fatal(err)
	}

	t.SetFillColor("lightgreen")
	t.SetStyle(cgraph.FilledNodeStyle)

	var buf bytes.Buffer
	if err := g.Render(graph, "dot", &buf); err != nil {
		log.Fatal(err)
	}
}

output

2021/08/15 15:54:00 lightgreen is not a known color.
exit status 1

Probably this is because color_names is outdated.
https://gitlab.com/graphviz/graphviz/-/issues/1446
https://gitlab.com/graphviz/graphviz/-/commit/ae160d36572253aa4edfdb14fefe2729bbdfc771

related in #42

Intermittent SIGSEGV on RenderFilename

Intermittently get SIGSEGV on RenderFilename. Sometimes works 5/10 times doesnt.

This is my code

func generateImage(outputFolder string, buff bytes.Buffer) {
	g := graphviz.New().SetLayout(graphviz.FDP)
	graph, err := graphviz.ParseBytes(buff.Bytes())

	defer func() {
		if err := graph.Close(); err != nil {
			log.Fatal().Err(err)
		}
		g.Close()
	}()

	if err != nil {
		log.Fatal().Err(err).Msg("Failed to initialize graph library")
	}
	if err := g.RenderFilename(graph, graphviz.PNG, outputFolder+"/dependencies.png"); err != nil {
		log.Fatal().Err(err).Msg("Failed to create dependencies.png")
	}
	log.Info().Msg("File " + outputFolder + "/" + "dependencies.png generated")
}

This is the stack trace 5/10 times.

fatal error: unexpected signal during runtime execution
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x8f5f7a]

runtime stack:
runtime.throw({0xa28ac6, 0x8652ed})
        /usr/local/go/src/runtime/panic.go:1198 +0x71
runtime.sigpanic()
        /usr/local/go/src/runtime/signal_unix.go:719 +0x396

goroutine 1 [syscall]:
runtime.cgocall(0x8493c0, 0xc0003178b8)
        /usr/local/go/src/runtime/cgocall.go:156 +0x5c fp=0xc000317890 sp=0xc000317858 pc=0x41d3dc
github.com/goccy/go-graphviz/internal/ccall._Cfunc_gvLayout(0x7f7ea00012b0, 0x7f7ea0009180, 0x7f7ea001e520)
        _cgo_gotypes.go:2378 +0x4c fp=0xc0003178b8 sp=0xc000317890 pc=0x5a278c
github.com/goccy/go-graphviz/internal/ccall.GvLayout.func1(0x11, 0x17, {0xa13625, 0x11})
        /home/smene/go/pkg/mod/github.com/goccy/[email protected]/internal/ccall/gvc.go:736 +0xa7 fp=0xc000317900 sp=0xc0003178b8 pc=0x5aa607
github.com/goccy/go-graphviz/internal/ccall.GvLayout(0xc000317a16, 0xc000317990, {0xa13625, 0x7f7ea0009101})
        /home/smene/go/pkg/mod/github.com/goccy/[email protected]/internal/ccall/gvc.go:736 +0x1e fp=0xc000317930 sp=0xc000317900 pc=0x5aa51e
github.com/goccy/go-graphviz/gvc.(*Context).Layout(...)
        /home/smene/go/pkg/mod/github.com/goccy/[email protected]/gvc/gvc.go:29
github.com/goccy/go-graphviz.(*Graphviz).RenderFilename(0xc00011a4e0, 0xc0001280b0, {0xa136ac, 0x3}, {0xc000317a10, 0x17})
        /home/smene/go/pkg/mod/github.com/goccy/[email protected]/graphviz.go:115 +0x85 fp=0xc0003179b0 sp=0xc000317930 pc=0x60db85
infovista/devops/ait/internal/systembom.generateImage({0xa143c6, 0x6})
        /home/smene/git/assets-identification-tool/internal/systembom/dependency_graph.go:198 +0x45a fp=0xc000317b48 sp=0xc0003179b0 pc=0x7a753a
infovista/devops/ait/internal/systembom.GenerateDependencyGraph({0xa143c6, 0x6}, {0xa1353b, 0x3})
        /home/smene/git/assets-identification-tool/internal/systembom/dependency_graph.go:50 +0x58 fp=0xc000317b88 sp=0xc000317b48 pc=0x7a5a58
infovista/devops/ait/cmd.glob..func4(0xfcc7e0, {0xa139ce, 0x0, 0x0})
        /home/smene/git/assets-identification-tool/cmd/graph.go:25 +0xac fp=0xc000317bc0 sp=0xc000317b88 pc=0x84666c
github.com/spf13/cobra.(*Command).execute(0xfcc7e0, {0x10b5838, 0x0, 0x0})
        /home/smene/go/pkg/mod/github.com/spf13/[email protected]/command.go:860 +0x5f8 fp=0xc000317c80 sp=0xc000317bc0 pc=0x7d8738
github.com/spf13/cobra.(*Command).ExecuteC(0xfcc060)
        /home/smene/go/pkg/mod/github.com/spf13/[email protected]/command.go:974 +0x3bc fp=0xc000317d38 sp=0xc000317c80 pc=0x7d8e3c
github.com/spf13/cobra.(*Command).Execute(...)
        /home/smene/go/pkg/mod/github.com/spf13/[email protected]/command.go:902
infovista/devops/ait/cmd.Execute()
        /home/smene/git/assets-identification-tool/cmd/root.go:32 +0x17c fp=0xc000317f70 sp=0xc000317d38 pc=0x845ddc
main.main()
        /home/smene/git/assets-identification-tool/main.go:10 +0x17 fp=0xc000317f80 sp=0xc000317f70 pc=0x846a37
runtime.main()
        /usr/local/go/src/runtime/proc.go:255 +0x227 fp=0xc000317fe0 sp=0xc000317f80 pc=0x44fd67
runtime.goexit()
        /usr/local/go/src/runtime/asm_amd64.s:1581 +0x1 fp=0xc000317fe8 sp=0xc000317fe0 pc=0x47ca21

goroutine 18 [IO wait]:
internal/poll.runtime_pollWait(0x7f7ec01311b0, 0x72)
        /usr/local/go/src/runtime/netpoll.go:234 +0x89
internal/poll.(*pollDesc).wait(0xc00003ce80, 0xc000288000, 0x0)
        /usr/local/go/src/internal/poll/fd_poll_runtime.go:84 +0x32
internal/poll.(*pollDesc).waitRead(...)
        /usr/local/go/src/internal/poll/fd_poll_runtime.go:89
internal/poll.(*FD).Read(0xc00003ce80, {0xc000288000, 0x1000, 0x1000})
        /usr/local/go/src/internal/poll/fd_unix.go:167 +0x25a
net.(*netFD).Read(0xc00003ce80, {0xc000288000, 0x4501e7, 0xc00007dc30})
        /usr/local/go/src/net/fd_posix.go:56 +0x29
net.(*conn).Read(0xc000286000, {0xc000288000, 0x27, 0xc0000001a0})
        /usr/local/go/src/net/net.go:183 +0x45
net/http.(*persistConn).Read(0xc00020a5a0, {0xc000288000, 0xc000034600, 0xc00007dd30})
        /usr/local/go/src/net/http/transport.go:1926 +0x4e
bufio.(*Reader).fill(0xc000282060)
        /usr/local/go/src/bufio/bufio.go:101 +0x103
bufio.(*Reader).Peek(0xc000282060, 0x1)
        /usr/local/go/src/bufio/bufio.go:139 +0x5d
net/http.(*persistConn).readLoop(0xc00020a5a0)
        /usr/local/go/src/net/http/transport.go:2087 +0x1ac
created by net/http.(*Transport).dialConn
        /usr/local/go/src/net/http/transport.go:1747 +0x1e05

goroutine 19 [select]:
net/http.(*persistConn).writeLoop(0xc00020a5a0)
        /usr/local/go/src/net/http/transport.go:2386 +0xfb
created by net/http.(*Transport).dialConn
        /usr/local/go/src/net/http/transport.go:1748 +0x1e65

Info

go version
go version go1.17.6 linux/amd64
uname -a
Linux klerity-dev-smene 4.18.0-365.el8.x86_64 #1 SMP Thu Feb 10 16:11:23 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
cat /etc/os-release
NAME="CentOS Stream"
VERSION="8"
ID="centos"
ID_LIKE="rhel fedora"
VERSION_ID="8"
PLATFORM_ID="platform:el8"
PRETTY_NAME="CentOS Stream 8"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:centos:centos:8"
HOME_URL="https://centos.org/"
BUG_REPORT_URL="https://bugzilla.redhat.com/"
REDHAT_SUPPORT_PRODUCT="Red Hat Enterprise Linux 8"
REDHAT_SUPPORT_PRODUCT_VERSION="CentOS Stream"

redefinition of typedef ‘radfunc_t’

when i build go-graphviz, the follow errors occured

 # github.com/goccy/go-graphviz/internal/ccall
common/taper.c:258: error: redefinition of typedef ‘radfunc_t’
common/emit.c:2241: note: previous declaration of ‘radfunc_t’ was here

need help: how to create edges from and point to specified fields of record nodes?

For example, I need create a graph like below, there exists an edge from struct1:f1 to struct2:f. I find that the input parameters are *Node.

func (g *Graph) CreateEdge(name string, start *Node, end *Node)
digraph structs {
    node [shape=record];
    struct1 [label="<f0> left|<f1> mid&#92; dle|<f2> right"];
    struct2 [label="<f0> one|<f1> two"];
    struct3 [label="hello&#92;nworld |{ b |{c|<here> d|e}| f}| g | h"];
    struct1:f1 -> struct2:f0;
    struct1:f2 -> struct3:here;
}

image

Show DEBUG output when using `splines=ortho`

Hi @goccy !

Converting a dot file using splines=ortho seems to produce debugging output.

I think it's probably compiled with DEBUG enabled in internal/ccall/ortho/ortho.c or internal/ccall/ortho/maze.c, but I can't find a way to undefine this using the cgo mechanism was.

I'll share just how to reproduce it.

$ pwd
/Users/k1low/src/github.com/goccy/go-graphviz
$ git pull origin master
From https://github.com/goccy/go-graphviz
 * branch            master     -> FETCH_HEAD
Already up to date.
$ git rev-parse HEAD
aabab27138e820d03b5046855296a73a20e1ac09
$ go build cmd/dot/dot.go
$ cat test.dot
digraph G {
  graph [splines=ortho];
  subgraph cluster_0 {
    a0 -> a1 -> a2 -> a3;
  }
}
$ ./dot test.dot -o out.svg
make_poly: mcur = 0, (v0, v1) = (2, 17)
next posns = (p, q) = (2, 17)
make_poly: mcur = 0, (v0, v1) = (19, 13)
next posns = (p, q) = (19, 13)
make_poly: mcur = 0, (v0, v1) = (15, 9)
next posns = (p, q) = (15, 9)
make_poly: mcur = 0, (v0, v1) = (11, 5)
next posns = (p, q) = (11, 5)
make_poly: mcur = 0, (v0, v1) = (7, 4)
[...]
process 2
new 3 (536)
new 1 (536)
process 41
new 4 (545)
new 22 (545)
new 40 (36)
process 40
new 42 (36)
process 42

Couldn't compile on CentOS 7

# github.com/goccy/go-graphviz/internal/ccall
In file included from expat.c:3:
../expat/xmlparse.c:75:14: fatal error: sys/random.h: No such file or directory
   75 | #    include <sys/random.h> /* getrandom */
      |              ^~~~~~~~~~~~~~
compilation terminated.

CentOS 7 doesn't ship with a recent enough glibc, so that sys/random.h isn't actually available. I saw that this is manually configured here. The libc in my system is:

GNU C Library (GNU libc) stable release version 2.17, by Roland McGrath et al.
Copyright (C) 2012 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 4.8.5 20150623 (Red Hat 4.8.5-39).
Compiled on a Linux 3.10.0 system on 2019-08-06.

Cannot render image after setting node SetImage

I'm attempting to render a graph containing nodes with png icons.

node, _ := graph.CreateNode("mynode")

node.SetImage("/path/to/image.png")

When the graph is rendered:

g.RenderFilename(graph, "png", "mygraph.png")

I'm getting an error:

No loadimage plugin for "png:png"

Rendering to "dot" format and creating the image with graphviz works as intended.

I've attempted to troubleshoot and as near as I can tell, the pango/cairo plugin must be enabled to allow this but I'm not familiar enough with the C/Go bindings to know how this could be done. For what it's worth, I've tried #define HAVE_PANGOCAIRO 1 in /internal/config.h to no effect.

Any guidance on how I could enable this?

Lack of documentation for methods in cgraph package

There are some methods in the cgraph package that doesn't have documentations. Their names and parameters don't necessarily make the functioning of those entities obvious, for example the method func (g *Graph) Degree(n *Node, in, out int) int, I don't know what the in and out parameters means, for me the degree of a vertex, is simply the number of edges connected to it, so it should just have the n parameter. I have to look at the source code, find the C function underline agdegree and look at the documentation of graphViz C implementation to figure out what that function does and the role of those parameters.

The function agdegree(g, n, in, out) gives the degree of a node in (sub)graph g, where in and
out select the edge sets.
• agdegree(g,n,TRUE,FALSE) returns the in-degree.
• agdegree(g,n,FALSE,TRUE) returns the out-degree.
• agdegree(g,n,TRUE,TRUE) returns their sum.

And some confusion remains because it seems like the parameters in and out should be boolean, at least in the Go implementation.

So I think that more documentation would be beneficial.

ParseBytes method error every time after the first error

graphviz.ParseBytes([]byte(`digraph{a->b;b->d;a->c;c->d;}`)) // success
graphviz.ParseBytes([]byte(`digraph{a->b;b->d;a->c;c->d;}www`)) // error
graphviz.ParseBytes([]byte(`digraph{a->b;b->d;a->c;c->d;}`)) // error
graphviz.ParseBytes([]byte(`digraph{a->b;b->d;a->c;c->d;}`)) // error
graphviz.ParseBytes([]byte(`digraph{a->b;b->d;a->c;c->d;}`)) // error

Can this render the image in pure Go?

I see a lot of CGO in the code, but the Readme says "Supports rendering graph in pure Go".

Is there a way to build this without CGO cause I get this error when trying it:

go-graphviz$ CGO_ENABLED=0 go build
package github.com/goccy/go-graphviz
imports github.com/goccy/go-graphviz/cgraph
imports github.com/goccy/go-graphviz/internal/ccall: build constraints exclude all Go files in GOPATH/src/github.com/goccy/go-graphviz/internal/ccall

(but builds fine if I set CGO_ENABLED=1)

twopi and setRoot -> crash

I'm trying to graph using twopi and sent one of the nodes to be the graph root.
This lead to a crash.

fatal error: unexpected signal during runtime execution
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x52d5a4]

runtime stack:
runtime.throw(0x67e1e8, 0x2a)
        /usr/local/go/src/runtime/panic.go:1116 +0x72
runtime.sigpanic()
        /usr/local/go/src/runtime/signal_unix.go:679 +0x46a

goroutine 1 [syscall]:
runtime.cgocall(0x526ce0, 0xc000045dc8, 0x3)
        /usr/local/go/src/runtime/cgocall.go:133 +0x5b fp=0xc000045d98 sp=0xc000045d60 pc=0x41c90b
github.com/goccy/go-graphviz/internal/ccall._Cfunc_gvLayout(0x9fff70, 0xa01810, 0xa026d0, 0x0)
        _cgo_gotypes.go:2372 +0x4d fp=0xc000045dc8 sp=0xc000045d98 pc=0x4c2b3d
github.com/goccy/go-graphviz/internal/ccall.GvLayout.func1(0xc0000100a8, 0xc0000100b8, 0x676be7, 0x3, 0xc00006e1e0)
        /home/offerm/go/pkg/mod/github.com/goccy/[email protected]/internal/ccall/gvc.go:736 +0xd5 fp=0xc000045e10 sp=0xc000045dc8 pc=0x4c69a5
github.com/goccy/go-graphviz/internal/ccall.GvLayout(0xc0000100a8, 0xc0000100b8, 0x676be7, 0x3, 0x4c8827, 0xa01810)
        /home/offerm/go/pkg/mod/github.com/goccy/[email protected]/internal/ccall/gvc.go:736 +0x49 fp=0xc000045e48 sp=0xc000045e10 pc=0x4c5ec9
github.com/goccy/go-graphviz/gvc.(*Context).Layout(...)
        /home/offerm/go/pkg/mod/github.com/goccy/[email protected]/gvc/gvc.go:29
github.com/goccy/go-graphviz.(*Graphviz).Render(0xc00006e1b0, 0xc0000100c0, 0x676be7, 0x3, 0x6a0ee0, 0xc00006e1e0, 0x0, 0x0)
        /home/offerm/go/pkg/mod/github.com/goccy/[email protected]/graphviz.go:83 +0x74 fp=0xc000045ec0 sp=0xc000045e48 pc=0x522584
main.main()
        /home/offerm/github/ln-name-server/graph/test.go:45 +0x3d0 fp=0xc000045f88 sp=0xc000045ec0 pc=0x524300
runtime.main()
        /usr/local/go/src/runtime/proc.go:203 +0x1fa fp=0xc000045fe0 sp=0xc000045f88 pc=0x44befa
runtime.goexit()
        /usr/local/go/src/runtime/asm_amd64.s:1373 +0x1 fp=0xc000045fe8 sp=0xc000045fe0 pc=0x476731

not using twopi or setRoot prevent this error.

source code:

package main

import (
	"bytes"
	"fmt"
	"github.com/goccy/go-graphviz"
	"log"
)

func main() {

	g := graphviz.New()
	graph, err := g.Graph(graphviz.UnDirected)
	if err != nil {
		log.Fatal(err)
	}
	defer func() {
		if err := graph.Close(); err != nil {
			log.Fatal(err)
		}
		g.Close()
	}()
	n, err := graph.CreateNode("n")
	if err != nil {
		log.Fatal(err)
	}
	m, err := graph.CreateNode("m")
	if err != nil {
		log.Fatal(err)
	}
	_, err = graph.CreateNode("l")
	if err != nil {
		log.Fatal(err)
	}

	e, err := graph.CreateEdge("e", n, m)
	if err != nil {
		log.Fatal(err)
	}
	e.SetLabel("e")
	n.SetRoot(true)
	graph.SetLayout("twopi")

	var buf bytes.Buffer
	if err := g.Render(graph, "dot", &buf); err != nil {
		log.Fatal(err)
	}
	fmt.Println(buf.String())

	if err := g.Render(graph, graphviz.PNG, &buf); err != nil {
		log.Fatal(err)
	}

	if err := g.RenderFilename(graph, graphviz.PNG, "/tmp/graph.png"); err != nil {
		log.Fatal(err)
	}

}

edge question

n, _ := graph.CreateNode("n")
n.SetShape("record")
n.SetLabel("<prev>|B|<next>")
m, err := graph.CreateNode("m")
e, err := graph.CreateEdge("e", n:prev, m)

I want to draw edge from prev to m, but I can't found some useful function, how to do ?
thanks

Gcc Wformat-security causes errors building this module

Hi! A project I work on recently added a dep on go-graphviz and I am experiencing the following error when building:

# github.com/goccy/go-graphviz/internal/ccall
cc1: error: '-Wformat-security' ignored without '-Wformat' [-Werror=format-security]
cc1: some warnings being treated as errors

It seems like the -Wno-format line is causing issues when paired with compilers that want to call -Wformat-security

✗ go version
go version go1.21.4 linux/amd64
✗ gcc --version
gcc (GCC) 11.4.0
Copyright (C) 2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE

(I also tried gcc 13, 12, and 10)

Any help is appreciated!

Support HTML-Like Labels

Hi @goccy !

This is feature request.

I want to use go-graphviz with HTML-Like Labels.

Example DOT and output

DOT

digraph "testdb" {
  // Config
  graph [rankdir=TB, layout=dot, fontname="Arial"];
  node [shape=record, fontsize=14, margin=0.6, fontname="Arial"];
  edge [fontsize=10, labelfloat=false, splines=none, fontname="Arial"];

  // Tables
  "users" [shape=none, label=<<table border="0" cellborder="1" cellspacing="0" cellpadding="6">
                 <tr><td bgcolor="#EFEFEF"><font face="Arial Bold" point-size="18">users</font> <font color="#666666">[BASE TABLE]</font></td></tr>
                 <tr><td port="id" align="left">id <font color="#666666">[integer]</font></td></tr>
                 <tr><td port="username" align="left">username <font color="#666666">[varchar(50)]</font></td></tr>
                 <tr><td port="password" align="left">password <font color="#666666">[varchar(50)]</font></td></tr>
                 <tr><td port="email" align="left">email <font color="#666666">[varchar(355)]</font></td></tr>
                 <tr><td port="created" align="left">created <font color="#666666">[timestamp without time zone]</font></td></tr>
                 <tr><td port="updated" align="left">updated <font color="#666666">[timestamp without time zone]</font></td></tr>
              </table>>];
}

Render result ( Graphviz 2.40.1 via Homebrew )

schema

goccy/go-graphviz/cmd/dot v1.3.1 result

$ cat schema.dot | ~/path/to/go-graphviz/cmd/dot -Tpng -o schema.png # error
Not built with libexpat. Table formatting is not available.
in label of node users

Thank you for a very good library !!

PNG renderer default font selection on macOS is worse than `dot`

When rendering with dot -Tpng, you get a result using Times,serif on my system.

When rendering with go-graphviz to SVG, you also get the same font.

But when rendering with go-graphviz to PNG, you end-up with a sans font that does looks quirky - specifically, it does overflow from the shape.

Am I missing something that would allow to get a consistent behavior here?

Though, I would expect by default that go-graphviz PNG renderer behaves the same as the SVG renderer, and the same as the default dot png output.

Might be related to #25

Attaching screenshots.

Thanks!

dot_render
gograph_render

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.