LIBXDOT(3)

πŸ“¦
version 16.1.0 Β· 2 versions
  • 16.1.0 Β· alpine 3.22, alpine 3.23, alpine 3.24, arch rolling, centos-stream 10, fedora 43, fedora 44, nixos 26.05, nixpkgs unstable, opensuse-leap 16.0, ubuntu resolute, ubuntu stonking (latest)
  • 2.44.0 Β· centos-stream 9
, in alpine 3.22, alpine 3.23, alpine 3.24, arch rolling, centos-stream 10, fedora 43, fedora 44, nixos 26.05, nixpkgs unstable, opensuse-leap 16.0, ubuntu resolute, ubuntu stonking

πŸ’– LIBXDOT(3) β€” the manual page, but make it a group chat πŸ’–

okay so bestie, sit down, hydrate, because we're talking about libxdot today and she is lowkey iconic. This is section 3 of the Library Functions Manual, she parses and deparses xdot operations, and by the end of this page you're gonna be obsessed. no cap. πŸ¦‹


✨ NAME ✨

libxdot β€” parsing and deparsing of xdot operations

like literally that's the whole job description and she does it flawlessly πŸ’…


🌈 SYNOPSIS 🌈

first thing's first, you gotta pull her in:

#include <graphviz/xdot.h>

and then there's a whole glow-up of typedefs and structs, here they all are, exactly, no notes, no cap:

typedef enum {
    xd_none,
    xd_linear,
    xd_radial
} xdot_grad_type;

typedef struct {
    float frac;
    char* color;
} xdot_color_stop;

typedef struct {
    double x0, y0;
    double x1, y1;
    int n_stops;
    xdot_color_stop* stops;
} xdot_linear_grad;

typedef struct {
    double x0, y0, r0;
    double x1, y1, r1;
    int n_stops;
    xdot_color_stop* stops;
} xdot_radial_grad;

typedef struct {
    xdot_grad_type type;
    union {
       char* clr;
       xdot_linear_grad ling;
       xdot_radial_grad ring;
    } u;
} xdot_color;

typedef enum {
    xd_left, xd_center, xd_right
} xdot_align;

typedef struct {
    double x, y, z;
} xdot_point;

typedef struct {
    double x, y, w, h;
} xdot_rect;

typedef struct {
    int cnt;
    xdot_point* pts;
} xdot_polyline;

typedef struct {
  double x, y;
  xdot_align align;
  double width;
  char* text;
} xdot_text;

typedef struct {
    xdot_rect pos;
    char* name;
} xdot_image;

typedef struct {
    double size;
    char* name;
} xdot_font;

typedef enum {
    xd_filled_ellipse, xd_unfilled_ellipse,
    xd_filled_polygon, xd_unfilled_polygon,
    xd_filled_bezier,  xd_unfilled_bezier,
    xd_polyline,       xd_text,
    xd_fill_color,     xd_pen_color, xd_font, xd_style, xd_image,
    xd_grad_fill_color,     xd_grad_pen_color,
    xd_fontchar
} xdot_kind;

typedef enum {
    xop_ellipse,
    xop_polygon,
    xop_bezier,
    xop_polyline,       xop_text,
    xop_fill_color,     xop_pen_color, xop_font, xop_style, xop_image,
    xop_grad_color,
    xop_fontchar
} xop_kind;

typedef struct _xdot_op xdot_op;
typedef void (*drawfunc_t)(xdot_op*, int);
typedef void (*freefunc_t)(xdot_op*);

struct _xdot_op {
    xdot_kind kind;
    union {
      xdot_rect ellipse;       /* xd_filled_ellipse, xd_unfilled_ellipse */
      xdot_polyline polygon;   /* xd_filled_polygon, xd_unfilled_polygon */
      xdot_polyline polyline;  /* xd_polyline */
      xdot_polyline bezier;    /* xd_filled_bezier,  xd_unfilled_bezier */
      xdot_text text;          /* xd_text */
      xdot_image image;        /* xd_image */
      char* color;             /* xd_fill_color, xd_pen_color */
      xdot_color grad_color;   /* xd_grad_fill_color, xd_grad_pen_color */
      xdot_font font;          /* xd_font */
      char* style;             /* xd_style */
      unsigned int fontchar;   /* xd_fontchar */
    } u;
    drawfunc_t drawfunc;
};

#define XDOT_PARSE_ERROR 1

typedef struct {
    int cnt;
    int sz;
    xdot_op* ops;
    freefunc_t freefunc;
    int flags;
} xdot;

typedef struct {
    int cnt;  /* no. of xdot ops */
    int n_ellipse;
    int n_polygon;
    int n_polygon_pts;
    int n_polyline;
    int n_polyline_pts;
    int n_bezier;
    int n_bezier_pts;
    int n_text;
    int n_font;
    int n_style;
    int n_color;
    int n_image;
    int n_gradcolor;
    int n_fontchar;
} xdot_stats;

xdot* parseXDotF (char*, drawfunc_t opfns[], int sz);
xdot* parseXDotFOn (char*, drawfunc_t opfns[], int sz, xdot*);
xdot* parseXDot (char*);
char* sprintXDot (xdot*);
void fprintXDot (FILE*, xdot*);
void jsonXDot (FILE*, xdot*);
void freeXDot (xdot*);
int statXDot (xdot*, xdot_stats*);

xdot_grad_type colorType (char*);
xdot_color* parseXDotColor (char*);
void freeXDotColor (xdot_color*);

okay breathe. that's a lot of structs but every single one of them is doing her little job and we respect her for it. 🫢


πŸ’œ DESCRIPTION πŸ’œ

so the whole vibe of libxdot is: she provides support for parsing and deparsing graphical operations specified by the xdot language. that's it. that's the mission. and she ate. πŸ”₯

🌸 Types 🌸

xdot

this one encapsulates a whole series of cnt xdot operations, all chillin' in the array pointed to by ops. the sz tells you the size of each item stored in ops.

now listen: if you set the freefunc field, that function gets called on each item in ops during freeXDot, and it runs before the library does its own clean-up of the item. why do we care? because it lets you free any resources you stashed in the item by using an expansion of the xdot_op structure. custom cleanup, main character energy. ✨

xdot_op

a value of this type = one single xdot operation. the operation itself is specified by the kind field, and the matching data lives in the union u, with the subfield associated with a given kind indicated by the comments (you saw them up in the synopsis, bestie, they're doing the lord's work).

the drawfunc field lets you attach a drawing-specific function to the operation β€” it's giving object-based interface πŸ‘‘. and these functions can be automatically attached during parsing if you hand a non-NULL second argument to parseXDotF.

xop_kind

this type gives you the enumeration of the allowed xdot operations. for the specific semantics associated with each operation, go look at:

https://graphviz.org/docs/outputs/canon/#xdot

(that's where the lore lives πŸ“–)

xdot_rect

this represents a rectangle. for ellipses, the x and x fields represent the center of the rectangle, and w and h give the half-width and half-height, respectively (yes, the page really does say x and x β€” we don't make the rules, we just relay them πŸ™ˆ).

for images, (x,y) gives the lower left corner of the rectangle, and w and h give the width and height, respectively.

xdot_polyline

this type encapsulates a series of cnt points. simple. clean. beautiful.

xdot_text

a value of this type corresponds to printing the string text using the baseline point (x,y). the width field gives an approximation of how wide the printed string will be using the current font and font size. and align tells you how the text should be horizontally aligned with the point (x,y).

xdot_image

this denotes the insertion of an image πŸ–ΌοΈ. the image source is given by name, and the image is to be placed into the rectangle pos.

xdot_font

the fields give the name and size, in points, of a font.

xdot_align

this enumeration type corresponds to the xdot alignment values -1, 0 and 1 used with the text operator, or '\l', '\n' and '\r' used in dot text.


πŸŽ€ Functions πŸŽ€

xdot* parseXDotF (char *str, drawfunc_t* opfns, int sz)

parses the string str as a sequence of xdot operations and returns a pointer to the resulting xdot structure. she parses as many xdot operations as she can β€” maximum effort, always. πŸ’ͺ

if some unknown or incorrect input was encountered in str, then the ops and cnt fields will reflect the operations parsed before the error, and the XDOT_PARSE_ERROR bit will be set in the flags field. and if she can't parse anything at all? she returns NULL. 😭

if sz is non-zero, it's assumed to be the size of some structure type containing xdot_op as a prefix. in that case, the elements in the array pointed to by ops will each have size sz.

if opfns is non-zero, it's taken to be any array of functions indexed by xop_kind. during parsing, the drawfunc member of xop_op will be set to the corresponding function in opfns. (yes it says xop_op there, we're just reporting the news πŸ“°)

xdot* parseXDotFOn (char *str, drawfunc_t* opfns, int sz, xdot* x)

the same as parseXDotF, except she appends to the given xdot object x. it's giving "yes and…" energy. πŸ’…

xdot* parseXDot (char *str)

this is equivalent to parseXDotF(str, 0, 0).

void freeXDot (xdot* xp)

frees the resources associated with the argument. and if xp is NULL, nothing happens β€” she simply does not perceive it. πŸ™ˆ

extern char* sprintXDot (xdot* xp) and extern void fprintXDot (FILE* fp, xdot* xp)

these two functions deparse the argument xdot structure, producing a string representation. fprintXDot writes the output onto the open stream fp; sprintXDot returns a heap-allocated string. 🎁

now here's the juicy bit: the color string with fill and draw operations can encode linear and radial gradients. these values are parsed automatically by parseXDotF or parseXDot, with xdot_op having kind xd_grad_pen_color or xd_grad_fill_color, and the value is stored in grad_color. automatic. effortless. iconic. 🌈

and for an application that handles its own parsing of xdot, the library provides three helper functions. here they are, bestie:

void jsonXDot(FILE * fp, xdot * x)

translates a given xdot object to a JSON representation.

⚠️ heads up: this functionality is currently considered experimental, and the format of the JSON output may not be stable across Graphviz releases. don't build your whole personality on it, ok? πŸ’€

xdot_grad_type colorTypeXDot (char *str)

returns the color type described by the input string.

(tiny side note bestie: the synopsis up top calls this one colorType, and this description calls it colorTypeXDot. both are on the page, both are valid, we contain multitudes. πŸ‘€)

char* parseXDotColor (char *str, xdot_color* clr)

attempts to parse the string str as a color value, storing the result in clr. it returns NULL on failure. she tries her best and if it doesn't work out she simply returns NULL and moves on. 🧚

void freeXDotColor (xdot_color* cp)

frees the resources associated with a value of type xdot_color.

int statXDot (xdot *x, xdot_stats *sp)

this function is provided for retrieving various statistics about an xdot object. it returns 0 on success and populates the output parameter sp with counts of various entities in the xdot object. numbers! data! we love her. πŸ“Š


πŸ’€ BUGS πŸ’€

okay so, the honest section. although some small checking is done on the sz argument to parseXDotF, it is assumed to be a valid value from sizeof applied to some structure type containing xdot_op as its first field. and there can be no validation of the opfns argument. at all. none. she trusts you completely and that is both beautiful and terrifying. 🫠


πŸ‘‘ AUTHORS πŸ‘‘

Emden R. Gansner (erg@research.att.com).


and that's the whole page bestie!! πŸŽ€ this one's dated 31 JULY 2009, and it lives in section 3 as LIBXDOT β€” so if you ever forget where you found all this, it's LIBXDOT(3), always and forever. go forth and parse something gorgeous. πŸ’–βœ¨πŸ¦‹πŸŒΈ

πŸ“¦ where this page comes from