31#include <pango/pangocairo.h>
42#define ARRAY_SIZE(A) (sizeof(A)/sizeof(A[0]))
50#ifdef CAIRO_HAS_PS_SURFACE
54#ifdef CAIRO_HAS_PDF_SURFACE
58#ifdef CAIRO_HAS_SVG_SURFACE
66 cairo_set_source_rgba(cr,
color->u.RGBA[0],
color->u.RGBA[1],
72 cairo_pattern_add_color_stop_rgba (pat, stop,
color->u.RGBA[0],
color->u.RGBA[1],
78writer (
void *closure,
const unsigned char *
data,
unsigned int length)
80 if (length ==
gvwrite(closure, (
const char*)
data, length))
81 return CAIRO_STATUS_SUCCESS;
82 return CAIRO_STATUS_WRITE_ERROR;
109 cairo_surface_t *surface;
110 cairo_status_t status;
116#ifdef CAIRO_HAS_PS_SURFACE
117 surface = cairo_ps_surface_create_for_stream (
writer,
120 cairo_ps_surface_set_eps (surface, TRUE);
124#ifdef CAIRO_HAS_PDF_SURFACE
125 surface = cairo_pdf_surface_create_for_stream (
writer,
129 const char *source_date_epoch = getenv(
"SOURCE_DATE_EPOCH");
130 if (source_date_epoch !=
NULL) {
133 long epoch = strtol(source_date_epoch, &end, 10);
138 if ((epoch == LONG_MAX && errno != 0) || epoch < 0
141 "malformed value %s for $SOURCE_DATE_EPOCH\n",
145 time_t tepoch = (time_t)epoch;
146 struct tm *tm = gmtime(&tepoch);
149 "malformed value %s for $SOURCE_DATE_EPOCH\n",
153#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 16, 0)
154 char iso8601[
sizeof(
"YYYY-MM-DDThh:mm:ss")] = {0};
155 (void)strftime(iso8601,
sizeof(iso8601),
"%Y-%m-%dT%H:%M:%SZ", tm);
156 cairo_pdf_surface_set_metadata(surface,
157 CAIRO_PDF_METADATA_CREATE_DATE,
159 cairo_pdf_surface_set_metadata(surface,
160 CAIRO_PDF_METADATA_MOD_DATE,
168#ifdef CAIRO_HAS_SVG_SURFACE
169 surface = cairo_svg_surface_create_for_stream (
writer,
185 "%s: graph is too large for cairo-renderer bitmaps. Scaling by %g to fit\n",
188 assert(job->
width <= INT_MAX);
189 assert(job->
height <= INT_MAX);
190 surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
194 "%s: allocating a %.0fK cairo image surface (%d x %d pixels)\n",
200 status = cairo_surface_status(surface);
201 if (status != CAIRO_STATUS_SUCCESS) {
202 fprintf(stderr,
"%s: failure to create cairo surface: %s\n",
204 cairo_status_to_string(status));
205 cairo_surface_destroy (surface);
208 cr = cairo_create(surface);
209 cairo_surface_destroy (surface);
225 cairo_surface_t *surface;
226 cairo_status_t status;
230#ifdef CAIRO_HAS_PNG_FUNCTIONS
232 surface = cairo_get_target(cr);
233 cairo_surface_write_to_png_stream(surface,
writer, job);
241 surface = cairo_surface_reference(cairo_get_target(cr));
242 cairo_surface_finish(surface);
243 status = cairo_surface_status(surface);
244 cairo_surface_destroy(surface);
245 if (status != CAIRO_STATUS_SUCCESS)
246 fprintf(stderr,
"cairo: %s\n", cairo_status_to_string(status));
251 surface = cairo_get_target(cr);
252 if (cairo_image_surface_get_width(surface) == 0 || cairo_image_surface_get_height(surface) == 0) {
258 job->
imagedata = cairo_image_surface_get_data(surface);
268 double p0x, p0y, p1x, p1y;
278 cairo_user_to_device (cr, &p0x, &p0y);
281 cairo_user_to_device (cr, &p1x, &p1y);
283 agxbprint(&buf,
"rect=[%f %f %f %f] uri='%s'", p0x, p0y, p1x - p0x,
285#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 16, 0)
286 cairo_tag_begin(cr, CAIRO_TAG_LINK,
agxbuse(&buf));
287 cairo_tag_end (cr, CAIRO_TAG_LINK);
299 cairo_set_dash (cr,
dashed, 0, 0.0);
302 switch (span->
just) {
311 p.
x -= span->
size.
x / 2.0;
316 cairo_move_to (cr, p.
x, -p.
y);
319 pango_cairo_show_layout(cr, (PangoLayout*)span->
layout);
325 A[1].y =
A[0].y = p.
y;
339 cairo_set_dash (cr,
dashed, 0, 0.0);
341 cairo_set_line_width (cr, obj->
penwidth);
346 cairo_pattern_t* pat;
352 pat = cairo_pattern_create_linear (
G[0].x,
G[0].y,
G[1].x,
G[1].y);
357 const double r1 =
G[1].x;
358 const double r2 =
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
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)
Arithmetic helper functions.
#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