/**
 * @file
 * @ingroup public_apis
 * @brief parsing and deparsing of
 * [xdot](https://graphviz.org/docs/outputs/canon/#xdot) operations
 *
 * **libxdot** provides support for parsing and deparsing graphical operations
 * specified by the xdot language.
 * [xdot](https://graphviz.org/docs/outputs/canon/#xdot) is extended dot format
 * containing complete layout information.
 *
 * [man 3 xdot](https://graphviz.org/pdf/xdot.3.pdf)
 *
 */
/*************************************************************************
 * Copyright (c) 2011 AT&T Intellectual Property
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html
 *
 * Contributors: Details at https://graphviz.org
 *************************************************************************/

#pragma once

#include <stddef.h>
#include <stdio.h>

#ifdef __cplusplus
extern "C" {
#endif

#ifdef GVDLL
#ifdef EXPORT_XDOT
#define XDOT_API __declspec(dllexport)
#else
#define XDOT_API __declspec(dllimport)
#endif
#endif

#ifndef XDOT_API
#define XDOT_API /* nothing */
#endif

typedef enum { xd_none, xd_linear, xd_radial } xdot_grad_type;

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

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

typedef struct {
  double x0, y0, r0;
  double x1, y1, r1;
  unsigned 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 {
  size_t 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 {
  size_t cnt; /* no. of xdot ops */
  size_t sz;  /* sizeof structure containing xdot_op as first field */
  xdot_op *ops;
  freefunc_t freefunc;
  int flags;
} xdot;

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

/* ops are indexed by xop_kind */
XDOT_API xdot *parseXDotF(char *, drawfunc_t opfns[], size_t sz);
XDOT_API xdot *parseXDotFOn(char *, drawfunc_t opfns[], size_t sz, xdot *);
XDOT_API xdot *parseXDot(char *);
XDOT_API char *sprintXDot(xdot *);
XDOT_API void fprintXDot(FILE *, xdot *);
XDOT_API void jsonXDot(FILE *, xdot *);
XDOT_API void freeXDot(xdot *);
XDOT_API int statXDot(xdot *, xdot_stats *);
XDOT_API xdot_grad_type colorTypeXDot(char *);
XDOT_API char *parseXDotColor(char *cp, xdot_color *clr);
XDOT_API void freeXDotColor(xdot_color *);

#ifdef __cplusplus
}
#endif
