30#include <pango/pangocairo.h>
41#define ARRAY_SIZE(A) (sizeof(A)/sizeof(A[0]))
49#ifdef CAIRO_HAS_PS_SURFACE
53#ifdef CAIRO_HAS_PDF_SURFACE
57#ifdef CAIRO_HAS_SVG_SURFACE
65 cairo_set_source_rgba(cr,
color->u.RGBA[0],
color->u.RGBA[1],
71 cairo_pattern_add_color_stop_rgba (pat, stop,
color->u.RGBA[0],
color->u.RGBA[1],
77writer (
void *closure,
const unsigned char *
data,
unsigned int length)
79 if (length ==
gvwrite(closure, (
const char*)
data, length))
80 return CAIRO_STATUS_SUCCESS;
81 return CAIRO_STATUS_WRITE_ERROR;
108 cairo_surface_t *surface;
109 cairo_status_t status;
115#ifdef CAIRO_HAS_PS_SURFACE
116 surface = cairo_ps_surface_create_for_stream (
writer,
119 cairo_ps_surface_set_eps (surface, TRUE);
123#ifdef CAIRO_HAS_PDF_SURFACE
124 surface = cairo_pdf_surface_create_for_stream (
writer,
128 const char *source_date_epoch = getenv(
"SOURCE_DATE_EPOCH");
129 if (source_date_epoch !=
NULL) {
132 long epoch = strtol(source_date_epoch, &end, 10);
137 if ((epoch == LONG_MAX && errno != 0) || epoch < 0
140 "malformed value %s for $SOURCE_DATE_EPOCH\n",
144 time_t tepoch = (time_t)epoch;
145 struct tm *tm = gmtime(&tepoch);
148 "malformed value %s for $SOURCE_DATE_EPOCH\n",
152#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 16, 0)
153 char iso8601[
sizeof(
"YYYY-MM-DDThh:mm:ss")] = {0};
154 (void)strftime(iso8601,
sizeof(iso8601),
"%Y-%m-%dT%H:%M:%SZ", tm);
155 cairo_pdf_surface_set_metadata(surface,
156 CAIRO_PDF_METADATA_CREATE_DATE,
158 cairo_pdf_surface_set_metadata(surface,
159 CAIRO_PDF_METADATA_MOD_DATE,
167#ifdef CAIRO_HAS_SVG_SURFACE
168 surface = cairo_svg_surface_create_for_stream (
writer,
184 "%s: graph is too large for cairo-renderer bitmaps. Scaling by %g to fit\n",
187 assert(job->
width <= INT_MAX);
188 assert(job->
height <= INT_MAX);
189 surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
193 "%s: allocating a %.0fK cairo image surface (%d x %d pixels)\n",
199 status = cairo_surface_status(surface);
200 if (status != CAIRO_STATUS_SUCCESS) {
201 fprintf(stderr,
"%s: failure to create cairo surface: %s\n",
203 cairo_status_to_string(status));
204 cairo_surface_destroy (surface);
207 cr = cairo_create(surface);
208 cairo_surface_destroy (surface);
224 cairo_surface_t *surface;
225 cairo_status_t status;
229#ifdef CAIRO_HAS_PNG_FUNCTIONS
231 surface = cairo_get_target(cr);
232 cairo_surface_write_to_png_stream(surface,
writer, job);
240 surface = cairo_surface_reference(cairo_get_target(cr));
241 cairo_surface_finish(surface);
242 status = cairo_surface_status(surface);
243 cairo_surface_destroy(surface);
244 if (status != CAIRO_STATUS_SUCCESS)
245 fprintf(stderr,
"cairo: %s\n", cairo_status_to_string(status));
250 surface = cairo_get_target(cr);
251 if (cairo_image_surface_get_width(surface) == 0 || cairo_image_surface_get_height(surface) == 0) {
257 job->
imagedata = cairo_image_surface_get_data(surface);
267 double p0x, p0y, p1x, p1y;
277 cairo_user_to_device (cr, &p0x, &p0y);
280 cairo_user_to_device (cr, &p1x, &p1y);
282 agxbprint(&buf,
"rect=[%f %f %f %f] uri='%s'", p0x, p0y, p1x - p0x,
284#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 16, 0)
285 cairo_tag_begin(cr, CAIRO_TAG_LINK,
agxbuse(&buf));
286 cairo_tag_end (cr, CAIRO_TAG_LINK);
298 cairo_set_dash (cr,
dashed, 0, 0.0);
301 switch (span->
just) {
310 p.
x -= span->
size.
x / 2.0;
315 cairo_move_to (cr, p.
x, -p.
y);
318 pango_cairo_show_layout(cr, (PangoLayout*)span->
layout);
324 A[1].y =
A[0].y = p.
y;
338 cairo_set_dash (cr,
dashed, 0, 0.0);
340 cairo_set_line_width (cr, obj->
penwidth);
345 cairo_pattern_t* pat;
351 pat = cairo_pattern_create_linear (
G[0].x,
G[0].y,
G[1].x,
G[1].y);
356 const double r1 =
G[1].x;
357 const double r2 =
G[1].y;
363 c1.
x =
G[0].x + r1 * cos(angle);
364 c1.
y =
G[0].y - r1 * sin(angle);
366 pat = cairo_pattern_create_radial(c1.
x,c1.
y,r1,
G[0].x,
G[0].y,r2);
376 cairo_set_source (cr, pat);
377 cairo_fill_preserve (cr);
378 cairo_pattern_destroy (pat);
385 cairo_matrix_t matrix;
390 cairo_get_matrix(cr, &matrix);
392 rx =
A[1].x -
A[0].x;
393 ry =
A[1].y -
A[0].y;
399 cairo_translate(cr,
A[0].x, -
A[0].y);
400 cairo_scale(cr, rx, ry);
401 cairo_move_to(cr, 1., 0.);
402 cairo_arc(cr, 0., 0., 1., 0., 2 *
M_PI);
404 cairo_set_matrix(cr, &matrix);
411 cairo_fill_preserve(cr);
423 cairo_move_to(cr,
A[0].x, -
A[0].y);
424 for (
size_t i = 1; i < n; i++)
425 cairo_line_to(cr,
A[i].x, -
A[i].y);
426 cairo_close_path(cr);
432 cairo_fill_preserve(cr);
444 cairo_move_to(cr,
A[0].x, -
A[0].y);
445 for (
size_t i = 1; i < n; i += 3)
446 cairo_curve_to(cr,
A[i].x, -
A[i].y,
A[i + 1].x, -
A[i + 1].y,
447 A[i + 2].x, -
A[i + 2].y);
453 cairo_fill_preserve(cr);
465 cairo_move_to(cr,
A[0].x, -
A[0].y);
466 for (
size_t i = 1; i < n; i++)
467 cairo_line_to(cr,
A[i].x, -
A[i].y);
563#ifdef CAIRO_HAS_PNG_FUNCTIONS
566#ifdef CAIRO_HAS_PS_SURFACE
570#ifdef CAIRO_HAS_PDF_SURFACE
573#ifdef CAIRO_HAS_SVG_SURFACE
static void agxbfree(agxbuf *xb)
free any malloced resources
static int agxbprint(agxbuf *xb, const char *fmt,...)
Printf-style output to an agxbuf.
static WUR char * agxbuse(agxbuf *xb)
void get_gradient_points(pointf *A, pointf *G, size_t n, double angle, int flags)
static pointf scale(double c, pointf p)
#define GVRENDER_NO_WHITE_BG
#define GVDEVICE_DOES_TRUECOLOR
#define GVDEVICE_BINARY_FORMAT
#define GVRENDER_DOES_MAPS
#define GVRENDER_DOES_TRANSFORM
#define GVRENDER_Y_GOES_DOWN
#define GVRENDER_DOES_MAP_RECTANGLE
static void color(Agraph_t *g)
size_t gvwrite(GVJ_t *job, const char *s, size_t len)
static void cairogen_begin_page(GVJ_t *job)
gvplugin_installed_t gvrender_pango_types[]
static gvdevice_features_t device_features_eps
static void cairogen_end_page(GVJ_t *job)
static gvdevice_features_t device_features_pdf
static void cairogen_textspan(GVJ_t *job, pointf p, textspan_t *span)
static gvdevice_features_t device_features_svg
static void cairogen_begin_job(GVJ_t *job)
static void cairogen_ellipse(GVJ_t *job, pointf *A, int filled)
static void cairogen_bezier(GVJ_t *job, pointf *A, size_t n, int filled)
static void cairogen_set_penstyle(GVJ_t *job, cairo_t *cr)
static const double CAIRO_XMAX
static const double CAIRO_YMAX
static void cairogen_polygon(GVJ_t *job, pointf *A, size_t n, int filled)
static gvdevice_features_t device_features_ps
static void cairogen_add_color_stop_rgba(cairo_pattern_t *pat, double stop, gvcolor_t *color)
static cairo_status_t writer(void *closure, const unsigned char *data, unsigned int length)
static void cairogen_polyline(GVJ_t *job, pointf *A, size_t n)
static void cairogen_end_job(GVJ_t *job)
static gvrender_engine_t cairogen_engine
static void cairogen_begin_anchor(GVJ_t *job, char *url, char *tooltip, char *target, char *id)
static void cairo_gradient_fill(cairo_t *cr, obj_state_t *obj, int filled, pointf *A, size_t n)
static gvrender_features_t render_features_cairo
gvplugin_installed_t gvdevice_pango_types[]
static gvdevice_features_t device_features_png
static void cairogen_set_color(cairo_t *cr, gvcolor_t *color)
gvplugin_active_render_t render
unsigned char * imagedata
location of imagedata
double yoffset_centerline