27#include <pango/pangocairo.h>
38#define ARRAY_SIZE(A) (sizeof(A)/sizeof(A[0]))
46#ifdef CAIRO_HAS_PS_SURFACE
50#ifdef CAIRO_HAS_PDF_SURFACE
54#ifdef CAIRO_HAS_SVG_SURFACE
62 cairo_set_source_rgba(cr,
color->u.RGBA[0],
color->u.RGBA[1],
68 cairo_pattern_add_color_stop_rgba (pat, stop,
color->u.RGBA[0],
color->u.RGBA[1],
74writer (
void *closure,
const unsigned char *
data,
unsigned int length)
76 if (length ==
gvwrite(closure, (
const char*)
data, length))
77 return CAIRO_STATUS_SUCCESS;
78 return CAIRO_STATUS_WRITE_ERROR;
105 cairo_surface_t *surface;
106 cairo_status_t status;
112#ifdef CAIRO_HAS_PS_SURFACE
113 surface = cairo_ps_surface_create_for_stream (
writer,
116 cairo_ps_surface_set_eps (surface, TRUE);
120#ifdef CAIRO_HAS_PDF_SURFACE
121 surface = cairo_pdf_surface_create_for_stream (
writer,
125 const char *source_date_epoch = getenv(
"SOURCE_DATE_EPOCH");
126 if (source_date_epoch !=
NULL) {
129 long epoch = strtol(source_date_epoch, &end, 10);
134 if ((epoch == LONG_MAX && errno != 0) || epoch < 0
137 "malformed value %s for $SOURCE_DATE_EPOCH\n",
141 time_t tepoch = (time_t)epoch;
142 struct tm *tm = gmtime(&tepoch);
145 "malformed value %s for $SOURCE_DATE_EPOCH\n",
149#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 16, 0)
150 char iso8601[
sizeof(
"YYYY-MM-DDThh:mm:ss")] = {0};
151 (void)strftime(iso8601,
sizeof(iso8601),
"%Y-%m-%dT%H:%M:%SZ", tm);
152 cairo_pdf_surface_set_metadata(surface,
153 CAIRO_PDF_METADATA_CREATE_DATE,
155 cairo_pdf_surface_set_metadata(surface,
156 CAIRO_PDF_METADATA_MOD_DATE,
164#ifdef CAIRO_HAS_SVG_SURFACE
165 surface = cairo_svg_surface_create_for_stream (
writer,
179 "%s: graph is too large for cairo-renderer bitmaps. Scaling by %g to fit\n",
182 surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
186 "%s: allocating a %.0fK cairo image surface (%d x %d pixels)\n",
192 status = cairo_surface_status(surface);
193 if (status != CAIRO_STATUS_SUCCESS) {
194 fprintf(stderr,
"%s: failure to create cairo surface: %s\n",
196 cairo_status_to_string(status));
197 cairo_surface_destroy (surface);
200 cr = cairo_create(surface);
201 cairo_surface_destroy (surface);
217 cairo_surface_t *surface;
218 cairo_status_t status;
222#ifdef CAIRO_HAS_PNG_FUNCTIONS
224 surface = cairo_get_target(cr);
225 cairo_surface_write_to_png_stream(surface,
writer, job);
233 surface = cairo_surface_reference(cairo_get_target(cr));
234 cairo_surface_finish(surface);
235 status = cairo_surface_status(surface);
236 cairo_surface_destroy(surface);
237 if (status != CAIRO_STATUS_SUCCESS)
238 fprintf(stderr,
"cairo: %s\n", cairo_status_to_string(status));
243 surface = cairo_get_target(cr);
244 if (cairo_image_surface_get_width(surface) == 0 || cairo_image_surface_get_height(surface) == 0) {
250 job->
imagedata = (
char *)(cairo_image_surface_get_data(surface));
260 double p0x, p0y, p1x, p1y;
272 cairo_user_to_device (cr, &p0x, &p0y);
275 cairo_user_to_device (cr, &p1x, &p1y);
276 buf_len = strlen(url) + 200;
278 snprintf(buf, buf_len,
"rect=[%f %f %f %f] uri='%s'",
284#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 16, 0)
285 cairo_tag_begin (cr, CAIRO_TAG_LINK, 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;
352 pat = cairo_pattern_create_linear (
G[0].x,
G[0].y,
G[1].x,
G[1].y);
364 c1.
x =
G[0].x + r1 * cos(angle);
365 c1.
y =
G[0].y - r1 * sin(angle);
367 pat = cairo_pattern_create_radial(c1.
x,c1.
y,r1,
G[0].x,
G[0].y,r2);
377 cairo_set_source (cr, pat);
378 cairo_fill_preserve (cr);
379 cairo_pattern_destroy (pat);
386 cairo_matrix_t matrix;
391 cairo_get_matrix(cr, &matrix);
393 rx =
A[1].x -
A[0].x;
394 ry =
A[1].y -
A[0].y;
400 cairo_translate(cr,
A[0].x, -
A[0].y);
401 cairo_scale(cr, rx, ry);
402 cairo_move_to(cr, 1., 0.);
403 cairo_arc(cr, 0., 0., 1., 0., 2 *
M_PI);
405 cairo_set_matrix(cr, &matrix);
412 cairo_fill_preserve(cr);
424 cairo_move_to(cr,
A[0].x, -
A[0].y);
425 for (
size_t i = 1; i < n; i++)
426 cairo_line_to(cr,
A[i].x, -
A[i].y);
427 cairo_close_path(cr);
433 cairo_fill_preserve(cr);
445 cairo_move_to(cr,
A[0].x, -
A[0].y);
446 for (
size_t i = 1; i < n; i += 3)
447 cairo_curve_to(cr,
A[i].x, -
A[i].y,
A[i + 1].x, -
A[i + 1].y,
448 A[i + 2].x, -
A[i + 2].y);
454 cairo_fill_preserve(cr);
466 cairo_move_to(cr,
A[0].x, -
A[0].y);
467 for (
size_t i = 1; i < n; i++)
468 cairo_line_to(cr,
A[i].x, -
A[i].y);
564#ifdef CAIRO_HAS_PNG_FUNCTIONS
567#ifdef CAIRO_HAS_PS_SURFACE
571#ifdef CAIRO_HAS_PDF_SURFACE
574#ifdef CAIRO_HAS_SVG_SURFACE
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
double yoffset_centerline