Graphviz 13.0.0~dev.20250121.0651
Loading...
Searching...
No Matches
gvrender_pango.c
Go to the documentation of this file.
1/*************************************************************************
2 * Copyright (c) 2011 AT&T Intellectual Property
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * https://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors: Details at https://graphviz.org
9 *************************************************************************/
10
11#include "config.h"
12
13#include <assert.h>
14#include <errno.h>
15#include <limits.h>
16#include <stdio.h>
17#include <stdlib.h>
18#include <string.h>
19#include <time.h>
20#include <common/const.h>
21#include <gvc/gvplugin_render.h>
22#include <common/utils.h>
23#include <gvc/gvplugin_device.h>
24#include <gvc/gvio.h>
25#include <math.h>
26#include <util/agxbuf.h>
27#include <util/gv_math.h>
28
29#include "gvplugin_pango.h"
30
31#include <pango/pangocairo.h>
32
41
42#define ARRAY_SIZE(A) (sizeof(A)/sizeof(A[0]))
43
44static double dashed[] = {6.};
46
47static double dotted[] = {2., 6.};
49
50#ifdef CAIRO_HAS_PS_SURFACE
51#include <cairo-ps.h>
52#endif
53
54#ifdef CAIRO_HAS_PDF_SURFACE
55#include <cairo-pdf.h>
56#endif
57
58#ifdef CAIRO_HAS_SVG_SURFACE
59#include <cairo-svg.h>
60#endif
61
62static void cairogen_polyline(GVJ_t *job, pointf *A, size_t n);
63
64static void cairogen_set_color(cairo_t * cr, gvcolor_t * color)
65{
66 cairo_set_source_rgba(cr, color->u.RGBA[0], color->u.RGBA[1],
67 color->u.RGBA[2], color->u.RGBA[3]);
68}
69
70static void cairogen_add_color_stop_rgba(cairo_pattern_t *pat, double stop , gvcolor_t * color)
71{
72 cairo_pattern_add_color_stop_rgba (pat, stop,color->u.RGBA[0], color->u.RGBA[1],
73 color->u.RGBA[2], color->u.RGBA[3]);
74}
75
76
77static cairo_status_t
78writer (void *closure, const unsigned char *data, unsigned int length)
79{
80 if (length == gvwrite(closure, (const char*)data, length))
81 return CAIRO_STATUS_SUCCESS;
82 return CAIRO_STATUS_WRITE_ERROR;
83}
84
85static void cairogen_begin_job(GVJ_t * job)
86{
87 if (job->external_context && job->context)
88 cairo_save(job->context);
89}
90
91static void cairogen_end_job(GVJ_t * job)
92{
93 cairo_t *cr = job->context;
94
95 if (job->external_context)
96 cairo_restore(cr);
97 else {
98 cairo_destroy(cr);
99 job->context = NULL;
100 }
101}
102
103static const double CAIRO_XMAX = 32767;
104static const double CAIRO_YMAX = 32767;
105
106static void cairogen_begin_page(GVJ_t * job)
107{
108 cairo_t *cr = job->context;
109 cairo_surface_t *surface;
110 cairo_status_t status;
111
112 if (cr == NULL) {
113 switch (job->render.id) {
114 case FORMAT_PS:
115 case FORMAT_EPS:
116#ifdef CAIRO_HAS_PS_SURFACE
117 surface = cairo_ps_surface_create_for_stream (writer,
118 job, job->width, job->height);
119 if (job->render.id == FORMAT_EPS)
120 cairo_ps_surface_set_eps (surface, TRUE);
121#endif
122 break;
123 case FORMAT_PDF:
124#ifdef CAIRO_HAS_PDF_SURFACE
125 surface = cairo_pdf_surface_create_for_stream (writer,
126 job, job->width, job->height);
127
128 {
129 const char *source_date_epoch = getenv("SOURCE_DATE_EPOCH");
130 if (source_date_epoch != NULL) {
131 char *end = NULL;
132 errno = 0;
133 long epoch = strtol(source_date_epoch, &end, 10);
134 // from https://reproducible-builds.org/specs/source-date-epoch/
135 //
136 // If the value is malformed, the build process SHOULD
137 // exit with a non-zero error code.
138 if ((epoch == LONG_MAX && errno != 0) || epoch < 0
139 || *end != '\0') {
140 fprintf(stderr,
141 "malformed value %s for $SOURCE_DATE_EPOCH\n",
142 source_date_epoch);
143 exit(EXIT_FAILURE);
144 }
145 time_t tepoch = (time_t)epoch;
146 struct tm *tm = gmtime(&tepoch);
147 if (tm == NULL) {
148 fprintf(stderr,
149 "malformed value %s for $SOURCE_DATE_EPOCH\n",
150 source_date_epoch);
151 exit(EXIT_FAILURE);
152 }
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,
158 iso8601);
159 cairo_pdf_surface_set_metadata(surface,
160 CAIRO_PDF_METADATA_MOD_DATE,
161 iso8601);
162#endif
163 }
164 }
165#endif
166 break;
167 case FORMAT_SVG:
168#ifdef CAIRO_HAS_SVG_SURFACE
169 surface = cairo_svg_surface_create_for_stream (writer,
170 job, job->width, job->height);
171#endif
172 break;
173 case FORMAT_CAIRO:
174 case FORMAT_PNG:
175 default:
176 if (job->width >= CAIRO_XMAX || job->height >= CAIRO_YMAX) {
177 double scale = fmin(CAIRO_XMAX / job->width, CAIRO_YMAX / job->height);
178 assert(job->width * scale <= UINT_MAX);
179 job->width = (unsigned)(job->width * scale);
180 assert(job->height * scale <= UINT_MAX);
181 job->height = (unsigned)(job->height * scale);
182 job->scale.x *= scale;
183 job->scale.y *= scale;
184 fprintf(stderr,
185 "%s: graph is too large for cairo-renderer bitmaps. Scaling by %g to fit\n",
186 job->common->cmdname, scale);
187 }
188 assert(job->width <= INT_MAX);
189 assert(job->height <= INT_MAX);
190 surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
191 (int)job->width, (int)job->height);
192 if (job->common->verbose)
193 fprintf(stderr,
194 "%s: allocating a %.0fK cairo image surface (%d x %d pixels)\n",
195 job->common->cmdname,
196 round(job->width * job->height * BYTES_PER_PIXEL / 1024.),
197 job->width, job->height);
198 break;
199 }
200 status = cairo_surface_status(surface);
201 if (status != CAIRO_STATUS_SUCCESS) {
202 fprintf(stderr, "%s: failure to create cairo surface: %s\n",
203 job->common->cmdname,
204 cairo_status_to_string(status));
205 cairo_surface_destroy (surface);
206 return;
207 }
208 cr = cairo_create(surface);
209 cairo_surface_destroy (surface);
210 job->context = cr;
211 }
212
213 cairo_scale(cr, job->scale.x, job->scale.y);
214 cairo_rotate(cr, -job->rotation * M_PI / 180.);
215 cairo_translate(cr, job->translation.x, -job->translation.y);
216
217 cairo_rectangle(cr, job->clip.LL.x, - job->clip.LL.y,
218 job->clip.UR.x - job->clip.LL.x, - (job->clip.UR.y - job->clip.LL.y));
219 cairo_clip(cr);
220}
221
222static void cairogen_end_page(GVJ_t * job)
223{
224 cairo_t *cr = job->context;
225 cairo_surface_t *surface;
226 cairo_status_t status;
227
228 switch (job->render.id) {
229
230#ifdef CAIRO_HAS_PNG_FUNCTIONS
231 case FORMAT_PNG:
232 surface = cairo_get_target(cr);
233 cairo_surface_write_to_png_stream(surface, writer, job);
234 break;
235#endif
236
237 case FORMAT_PS:
238 case FORMAT_PDF:
239 case FORMAT_SVG:
240 cairo_show_page(cr);
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));
247 break;
248
249 case FORMAT_CAIRO:
250 default:
251 surface = cairo_get_target(cr);
252 if (cairo_image_surface_get_width(surface) == 0 || cairo_image_surface_get_height(surface) == 0) {
253 /* apparently cairo never allocates a surface if nothing was ever written to it */
254/* but suppress this error message since a zero area surface seems to happen during normal operations, particular in -Tx11
255 fprintf(stderr, "ERROR: cairo surface has zero area, this may indicate some problem during rendering shapes.\n");
256 - jce */
257 }
258 job->imagedata = cairo_image_surface_get_data(surface);
259 break;
260 /* formatting will be done by gvdevice_format() */
261 }
262}
263
264static void cairogen_begin_anchor(GVJ_t *job, char *url, char *tooltip, char *target, char *id)
265{
266 obj_state_t *obj = job->obj;
267 cairo_t *cr = job->context;
268 double p0x, p0y, p1x, p1y;
269
270 // suppress unused parameter warnings
271 (void)tooltip;
272 (void)target;
273 (void)id;
274
275 if (url && obj->url_map_p) {
276 p0x = obj->url_map_p[0].x;
277 p0y = -obj->url_map_p[0].y;
278 cairo_user_to_device (cr, &p0x, &p0y);
279 p1x = obj->url_map_p[1].x;
280 p1y = -obj->url_map_p[1].y;
281 cairo_user_to_device (cr, &p1x, &p1y);
282 agxbuf buf = {0};
283 agxbprint(&buf, "rect=[%f %f %f %f] uri='%s'", p0x, p0y, p1x - p0x,
284 p1y - p0y, url);
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);
288#endif
289 agxbfree(&buf);
290 }
291}
292
293static void cairogen_textspan(GVJ_t * job, pointf p, textspan_t * span)
294{
295 obj_state_t *obj = job->obj;
296 cairo_t *cr = job->context;
297 pointf A[2];
298
299 cairo_set_dash (cr, dashed, 0, 0.0); /* clear any dashing */
300 cairogen_set_color(cr, &obj->pencolor);
301
302 switch (span->just) {
303 case 'r':
304 p.x -= span->size.x;
305 break;
306 case 'l':
307 p.x -= 0.0;
308 break;
309 case 'n':
310 default:
311 p.x -= span->size.x / 2.0;
312 break;
313 }
314 p.y += span->yoffset_centerline + span->yoffset_layout;
315
316 cairo_move_to (cr, p.x, -p.y);
317 cairo_save(cr);
318 cairo_scale(cr, POINTS_PER_INCH / FONT_DPI, POINTS_PER_INCH / FONT_DPI);
319 pango_cairo_show_layout(cr, (PangoLayout*)span->layout);
320 cairo_restore(cr);
321
322 if (span->font && (span->font->flags & HTML_OL)) {
323 A[0].x = p.x;
324 A[1].x = p.x + span->size.x;
325 A[1].y = A[0].y = p.y;
326 cairogen_polyline(job, A, 2);
327 }
328}
329
330static void cairogen_set_penstyle(GVJ_t *job, cairo_t *cr)
331{
332 obj_state_t *obj = job->obj;
333
334 if (obj->pen == PEN_DASHED) {
335 cairo_set_dash (cr, dashed, dashed_len, 0.0);
336 } else if (obj->pen == PEN_DOTTED) {
337 cairo_set_dash (cr, dotted, dotted_len, 0.0);
338 } else {
339 cairo_set_dash (cr, dashed, 0, 0.0);
340 }
341 cairo_set_line_width (cr, obj->penwidth);
342}
343
344static void cairo_gradient_fill(cairo_t *cr, obj_state_t *obj, int filled,
345 pointf *A, size_t n) {
346 cairo_pattern_t* pat;
347 double angle = obj->gradient_angle * M_PI / 180;
348 pointf G[2],c1;
349
350 if (filled == GRADIENT) {
351 get_gradient_points(A, G, n, angle, 0);
352 pat = cairo_pattern_create_linear (G[0].x,G[0].y,G[1].x,G[1].y);
353 }
354 else {
355 get_gradient_points(A, G, n, 0, 1);
356 //r1 is inner radius, r2 is outer radius
357 const double r1 = G[1].x; // set a r2 ÷ 4 in get_gradient_points
358 const double r2 = G[1].y;
359 if (obj->gradient_angle == 0) {
360 c1.x = G[0].x;
361 c1.y = G[0].y;
362 }
363 else {
364 c1.x = G[0].x + r1 * cos(angle);
365 c1.y = G[0].y - r1 * sin(angle);
366 }
367 pat = cairo_pattern_create_radial(c1.x,c1.y,r1,G[0].x,G[0].y,r2);
368 }
369 if (obj->gradient_frac > 0) {
370 cairogen_add_color_stop_rgba(pat,obj->gradient_frac - 0.001,&(obj->fillcolor));
372 }
373 else {
376 }
377 cairo_set_source (cr, pat);
378 cairo_fill_preserve (cr);
379 cairo_pattern_destroy (pat);
380}
381
382static void cairogen_ellipse(GVJ_t * job, pointf * A, int filled)
383{
384 obj_state_t *obj = job->obj;
385 cairo_t *cr = job->context;
386 cairo_matrix_t matrix;
387 double rx, ry;
388
389 cairogen_set_penstyle(job, cr);
390
391 cairo_get_matrix(cr, &matrix);
392
393 rx = A[1].x - A[0].x;
394 ry = A[1].y - A[0].y;
395
396#define RMIN 0.01
397 rx = fmax(rx, RMIN);
398 ry = fmax(ry, RMIN);
399
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);
404
405 cairo_set_matrix(cr, &matrix);
406
407 if (filled == GRADIENT || filled == RGRADIENT) {
408 cairo_gradient_fill (cr, obj, filled, A, 2);
409 }
410 else if (filled) {
411 cairogen_set_color(cr, &obj->fillcolor);
412 cairo_fill_preserve(cr);
413 }
414 cairogen_set_color(cr, &obj->pencolor);
415 cairo_stroke(cr);
416}
417
418static void cairogen_polygon(GVJ_t *job, pointf *A, size_t n, int filled) {
419 obj_state_t *obj = job->obj;
420 cairo_t *cr = job->context;
421
422 cairogen_set_penstyle(job, cr);
423
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);
428 if (filled == GRADIENT || filled == RGRADIENT) {
429 cairo_gradient_fill(cr, obj, filled, A, n);
430 }
431 else if (filled) {
432 cairogen_set_color(cr, &obj->fillcolor);
433 cairo_fill_preserve(cr);
434 }
435 cairogen_set_color(cr, &obj->pencolor);
436 cairo_stroke(cr);
437}
438
439static void cairogen_bezier(GVJ_t *job, pointf *A, size_t n, int filled) {
440 obj_state_t *obj = job->obj;
441 cairo_t *cr = job->context;
442
443 cairogen_set_penstyle(job, cr);
444
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);
449 if (filled == GRADIENT || filled == RGRADIENT) {
450 cairo_gradient_fill(cr, obj, filled, A, n);
451 }
452 else if (filled) {
453 cairogen_set_color(cr, &obj->fillcolor);
454 cairo_fill_preserve(cr);
455 }
456 cairogen_set_color(cr, &obj->pencolor);
457 cairo_stroke(cr);
458}
459
460static void cairogen_polyline(GVJ_t *job, pointf *A, size_t n) {
461 obj_state_t *obj = job->obj;
462 cairo_t *cr = job->context;
463
464 cairogen_set_penstyle(job, cr);
465
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);
469 cairogen_set_color(cr, &obj->pencolor);
470 cairo_stroke(cr);
471}
472
476 0, /* cairogen_begin_graph */
477 0, /* cairogen_end_graph */
478 0, /* cairogen_begin_layer */
479 0, /* cairogen_end_layer */
482 0, /* cairogen_begin_cluster */
483 0, /* cairogen_end_cluster */
484 0, /* cairogen_begin_nodes */
485 0, /* cairogen_end_nodes */
486 0, /* cairogen_begin_edges */
487 0, /* cairogen_end_edges */
488 0, /* cairogen_begin_node */
489 0, /* cairogen_end_node */
490 0, /* cairogen_begin_edge */
491 0, /* cairogen_end_edge */
492 cairogen_begin_anchor, /* cairogen_begin_anchor */
493 0, /* cairogen_end_anchor */
494 0, /* cairogen_begin_label */
495 0, /* cairogen_end_label */
497 0, /* cairogen_resolve_color */
502 0, /* cairogen_comment */
503 0, /* cairogen_library_shape */
504};
505
508 | GVRENDER_DOES_TRANSFORM, /* flags */
509 4., /* default pad - graph units */
510 0, /* knowncolors */
511 0, /* sizeof knowncolors */
512 RGBA_DOUBLE, /* color_type */
513};
514
517 | GVDEVICE_DOES_TRUECOLOR,/* flags */
518 {0.,0.}, /* default margin - points */
519 {0.,0.}, /* default page width, height - points */
520 {96.,96.}, /* typical monitor dpi */
521};
522
525 | GVDEVICE_DOES_TRUECOLOR, /* flags */
526 {36.,36.}, /* default margin - points */
527 {0.,0.}, /* default page width, height - points */
528 {72.,72.}, /* postscript 72 dpi */
529};
530
533 | GVDEVICE_DOES_TRUECOLOR, /* flags */
534 {36.,36.}, /* default margin - points */
535 {0.,0.}, /* default page width, height - points */
536 {72.,72.}, /* postscript 72 dpi */
537};
538
544 | GVDEVICE_DOES_TRUECOLOR,/* flags */
545 {36.,36.}, /* default margin - points */
546 {0.,0.}, /* default page width, height - points */
547 {72.,72.}, /* postscript 72 dpi */
548};
549
552 | GVDEVICE_DOES_TRUECOLOR, /* flags */
553 {0.,0.}, /* default margin - points */
554 {0.,0.}, /* default page width, height - points */
555 {72.,72.}, /* svg 72 dpi */
556};
557
562
564#ifdef CAIRO_HAS_PNG_FUNCTIONS
565 {FORMAT_PNG, "png:cairo", 10, NULL, &device_features_png},
566#endif
567#ifdef CAIRO_HAS_PS_SURFACE
568 {FORMAT_PS, "ps:cairo", -10, NULL, &device_features_ps},
569 {FORMAT_EPS, "eps:cairo", -10, NULL, &device_features_eps},
570#endif
571#ifdef CAIRO_HAS_PDF_SURFACE
572 {FORMAT_PDF, "pdf:cairo", 10, NULL, &device_features_pdf},
573#endif
574#ifdef CAIRO_HAS_SVG_SURFACE
575 {FORMAT_SVG, "svg:cairo", -10, NULL, &device_features_svg},
576#endif
577 {0, NULL, 0, NULL, NULL}
578};
static void agxbfree(agxbuf *xb)
free any malloced resources
Definition agxbuf.h:78
static int agxbprint(agxbuf *xb, const char *fmt,...)
Printf-style output to an agxbuf.
Definition agxbuf.h:234
static WUR char * agxbuse(agxbuf *xb)
Definition agxbuf.h:307
#define M_PI
Definition arith.h:41
@ RGBA_DOUBLE
Definition color.h:27
void get_gradient_points(pointf *A, pointf *G, size_t n, double angle, int flags)
Definition utils.c:1457
#define GRADIENT
Definition const.h:232
#define RGRADIENT
Definition const.h:233
#define A(n, t)
Definition expr.h:76
#define G
Definition gdefs.h:7
#define POINTS_PER_INCH
Definition geom.h:58
static pointf scale(double c, pointf p)
Definition geomprocs.h:155
node NULL
Definition grammar.y:163
Arithmetic helper functions.
@ BYTES_PER_PIXEL
Definition gv_math.h:87
@ PEN_DOTTED
Definition gvcjob.h:35
@ PEN_DASHED
Definition gvcjob.h:35
#define GVRENDER_NO_WHITE_BG
Definition gvcjob.h:106
#define GVDEVICE_DOES_TRUECOLOR
Definition gvcjob.h:90
#define GVDEVICE_BINARY_FORMAT
Definition gvcjob.h:91
#define GVRENDER_DOES_MAPS
Definition gvcjob.h:97
#define GVRENDER_DOES_TRANSFORM
Definition gvcjob.h:95
#define GVRENDER_Y_GOES_DOWN
Definition gvcjob.h:94
#define GVRENDER_DOES_MAP_RECTANGLE
Definition gvcjob.h:98
static void color(Agraph_t *g)
Definition gvcolor.c:129
size_t gvwrite(GVJ_t *job, const char *s, size_t len)
Definition gvdevice.c:180
#define FONT_DPI
static void cairogen_begin_page(GVJ_t *job)
static int dotted_len
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 int dashed_len
#define RMIN
static void cairogen_textspan(GVJ_t *job, pointf p, textspan_t *span)
#define ARRAY_SIZE(A)
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 double dashed[]
format_type
@ FORMAT_CAIRO
@ FORMAT_SVG
@ FORMAT_EPS
@ FORMAT_PDF
@ FORMAT_PS
@ FORMAT_PNG
static double dotted[]
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)
char * cmdname
Definition gvcommon.h:21
int verbose
Definition gvcommon.h:22
int rotation
Definition gvcjob.h:319
boxf clip
Definition gvcjob.h:313
obj_state_t * obj
Definition gvcjob.h:269
void * context
Definition gvcjob.h:295
bool external_context
Definition gvcjob.h:296
gvplugin_active_render_t render
Definition gvcjob.h:285
unsigned char * imagedata
location of imagedata
Definition gvcjob.h:297
GVCOMMON_t * common
Definition gvcjob.h:267
pointf scale
Definition gvcjob.h:332
unsigned int width
Definition gvcjob.h:327
pointf translation
Definition gvcjob.h:333
unsigned int height
Definition gvcjob.h:328
pointf UR
Definition geom.h:41
pointf LL
Definition geom.h:41
Definition legal.c:50
ingroup plugin_api
Definition gvplugin.h:35
pointf * url_map_p
Definition gvcjob.h:240
gvcolor_t fillcolor
Definition gvcjob.h:194
double gradient_frac
Definition gvcjob.h:196
gvcolor_t stopcolor
Definition gvcjob.h:194
pen_type pen
Definition gvcjob.h:197
gvcolor_t pencolor
Definition gvcjob.h:194
int gradient_angle
Definition gvcjob.h:195
double penwidth
Definition gvcjob.h:199
double x
Definition geom.h:29
double y
Definition geom.h:29
unsigned int flags
Definition textspan.h:58
double yoffset_layout
Definition textspan.h:69
char just
'l' 'n' 'r'
Definition textspan.h:71
void * layout
Definition textspan.h:67
pointf size
Definition textspan.h:70
textfont_t * font
Definition textspan.h:66
double yoffset_centerline
Definition textspan.h:69
#define HTML_OL
Definition textspan.h:35