Graphviz 14.1.2~dev.20260104.2039
Loading...
Searching...
No Matches
gvrender_gd.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#include "gdioctx_wrapper.h"
13#include "gdgen_text.h"
14#include "gd_psfontResolve.h"
15#include <assert.h>
16#include <limits.h>
17#include <math.h>
18#include <stdbool.h>
19#include <stdlib.h>
20#include <stdint.h>
21#include <string.h>
22#include <fcntl.h>
23#include <gvc/gvplugin_render.h>
24#include <gvc/gvplugin_device.h>
25#include <gvc/gvcint.h> /* for gvc->g for agget */
26#include <gd.h>
27#include <gdfontt.h>
28#include <gdfonts.h>
29#include <gdfontmb.h>
30#include <gdfontl.h>
31#include <gdfontg.h>
32#include <util/alloc.h>
33#include <util/gv_math.h>
34#include <util/unreachable.h>
35
36enum {
44};
45
46extern bool mapbool(const char *);
47extern pointf Bezier(pointf *V, double t, pointf *Left, pointf *Right);
48
49#define BEZIERSUBDIVISION 10
50
52{
53 gdImagePtr im = job->context;
54 int alpha;
55
56 if (!im)
57 return;
58
59 /* convert alpha (normally an "opacity" value) to gd's "transparency" */
60 alpha = (255 - color->u.rgba[3]) * gdAlphaMax / 255;
61
62 if(alpha == gdAlphaMax)
63 color->u.index = gdImageGetTransparent(im);
64 else
65 color->u.index = gdImageColorResolveAlpha(im,
66 color->u.rgba[0],
67 color->u.rgba[1],
68 color->u.rgba[2],
69 alpha);
70 color->type = COLOR_INDEX;
71}
72
74
75#define GD_XYMAX INT32_MAX
76
77static void gdgen_begin_page(GVJ_t * job)
78{
79 bool truecolor_p = false; /* try to use cheaper paletted mode */
80 gdImagePtr im = NULL;
81
82 const char *const truecolor_str = agget(job->gvc->g, "truecolor"); // allow user to force truecolor
83 const char *const bgcolor_str = agget(job->gvc->g, "bgcolor");
84
85 if (truecolor_str && truecolor_str[0])
86 truecolor_p = mapbool(truecolor_str);
87
88 if (bgcolor_str && strcmp(bgcolor_str, "transparent") == 0) {
90 truecolor_p = true; /* force truecolor */
91 }
92
93 if (GD_has_images(job->gvc->g))
94 truecolor_p = true; /* force truecolor */
95
96 if (job->external_context) {
97 if (job->common->verbose)
98 fprintf(stderr, "%s: using existing GD image\n", job->common->cmdname);
99 im = job->context;
100 } else {
101 if (job->width * job->height >= GD_XYMAX) {
102 double scale = sqrt(GD_XYMAX / (job->width * job->height));
103 assert(scale > 0 && scale <= 1);
104 job->width = (unsigned)(job->width * scale);
105 job->height = (unsigned)(job->height * scale);
106 job->zoom *= scale;
107 fprintf(stderr,
108 "%s: graph is too large for gd-renderer bitmaps. Scaling by %g to fit\n",
109 job->common->cmdname, scale);
110 }
111 assert(job->width <= INT_MAX);
112 assert(job->height <= INT_MAX);
113 if (truecolor_p) {
114 if (job->common->verbose)
115 fprintf(stderr,
116 "%s: allocating a %0.fK TrueColor GD image (%d x %d pixels)\n",
117 job->common->cmdname,
118 round(job->width * job->height * 4 / 1024.),
119 job->width, job->height);
120 im = gdImageCreateTrueColor((int)job->width, (int)job->height);
121 } else {
122 if (job->common->verbose)
123 fprintf(stderr,
124 "%s: allocating a %.0fK PaletteColor GD image (%d x %d pixels)\n",
125 job->common->cmdname,
126 round(job->width * job->height / 1024.),
127 job->width, job->height);
128 im = gdImageCreate((int)job->width, (int)job->height);
129 }
130 job->context = im;
131 }
132
133 if (!im) {
134 job->common->errorfn("gdImageCreate returned NULL. Malloc problem?\n");
135 return;
136 }
137
138 /* first color is the default background color */
139 /* - used for margins - if any */
140 transparent = gdImageColorResolveAlpha(im,
141 gdRedMax - 1, gdGreenMax,
142 gdBlueMax, gdAlphaTransparent);
143 gdImageColorTransparent(im, transparent);
144
145 /* Blending must be off to lay a transparent basecolor.
146 Nothing to blend with anyway. */
147 gdImageAlphaBlending(im, false);
148 gdImageFill(im, im->sx / 2, im->sy / 2, transparent);
149 /* Blend everything else together,
150 especially fonts over non-transparent backgrounds */
151 gdImageAlphaBlending(im, true);
152}
153
154static void gdgen_end_page(GVJ_t * job)
155{
156 gdImagePtr im = job->context;
157
158 gd_context_t gd_context = {
159 .ctx = {.putBuf = gvdevice_gd_putBuf, .putC = gvdevice_gd_putC},
160 .job = job,
161 };
162
163 if (!im)
164 return;
165 if (job->external_context) {
166 /* leave image in memory to be handled by Gdtclft output routines */
167 } else {
168 /* Only save the alpha channel in outputs that support it if
169 the base color was transparent. Otherwise everything
170 was blended so there is no useful alpha info */
171 gdImageSaveAlpha(im, basecolor == transparent);
172 switch (job->render.id) {
173 case FORMAT_GIF:
174 gdImageTrueColorToPalette(im, 0, 256);
175 gdImageGifCtx(im, &gd_context.ctx);
176 break;
177 case FORMAT_JPEG:
178#ifdef HAVE_GD_JPEG
179 /*
180 * Write IM to OUTFILE as a JFIF-formatted JPEG image, using
181 * quality JPEG_QUALITY. If JPEG_QUALITY is in the range
182 * 0-100, increasing values represent higher quality but also
183 * larger image size. If JPEG_QUALITY is negative, the
184 * IJG JPEG library's default quality is used (which should
185 * be near optimal for many applications). See the IJG JPEG
186 * library documentation for more details. */
187#define JPEG_QUALITY -1
188 gdImageJpegCtx(im, &gd_context.ctx, JPEG_QUALITY);
189#endif
190
191 break;
192 case FORMAT_PNG:
193#ifdef HAVE_GD_PNG
194 gdImagePngCtx(im, &gd_context.ctx);
195#endif
196 break;
197
198 case FORMAT_WBMP:
199 {
200 /* Use black for the foreground color for the B&W wbmp image. */
201 int black = gdImageColorResolveAlpha(im, 0, 0, 0, gdAlphaOpaque);
202 gdImageWBMPCtx(im, black, &gd_context.ctx);
203 }
204 break;
205
206 case FORMAT_GD:
207 gdImageGd(im, job->output_file);
208 break;
209
210#ifdef HAVE_LIBZ
211 case FORMAT_GD2:
212#define GD2_CHUNKSIZE 128
213#define GD2_COMPRESSED 2
214 gdImageGd2(im, job->output_file, GD2_CHUNKSIZE, GD2_COMPRESSED);
215 break;
216#endif
217
218 case FORMAT_XBM:
219 break;
220 default:
221 UNREACHABLE();
222 }
223 gdImageDestroy(im);
224 job->context = NULL;
225 }
226}
227
228/* fontsize at which text is omitted entirely */
229#define FONTSIZE_MUCH_TOO_SMALL 0.15
230/* fontsize at which text is rendered by a simple line */
231#define FONTSIZE_TOO_SMALL 1.5
232
233void gdgen_text(gdImagePtr im, pointf spf, pointf epf, int fontcolor, double fontsize, int fontdpi, double fontangle, char *fontname, char *str)
234{
235 point sp, ep; /* start point, end point, in pixels */
236
237 PF2P(spf, sp);
238 PF2P(epf, ep);
239
240 gdFTStringExtra strex = {
241 .flags = gdFTEX_RESOLUTION,
242 .hdpi = fontdpi,
243 .vdpi = fontdpi,
244 };
245
246 if (strchr(fontname, '/'))
247 strex.flags |= gdFTEX_FONTPATHNAME;
248 else
249 strex.flags |= gdFTEX_FONTCONFIG;
250
251 if (fontsize <= FONTSIZE_MUCH_TOO_SMALL) {
252 /* ignore entirely */
253 } else if (fontsize <= FONTSIZE_TOO_SMALL) {
254 /* draw line in place of text */
255 gdImageLine(im, sp.x, sp.y, ep.x, ep.y, fontcolor);
256 } else {
257#ifdef HAVE_GD_FREETYPE
258 int brect[8];
259#ifdef HAVE_GD_FONTCONFIG
260 char* fontlist = fontname;
261#else
262 extern char *gd_alternate_fontlist(const char *font);
263 char* fontlist = gd_alternate_fontlist(fontname);
264#endif
265 const char *const err = gdImageStringFTEx(im, brect, fontcolor,
266 fontlist, fontsize, fontangle, sp.x, sp.y, str, &strex);
267#ifndef HAVE_GD_FONTCONFIG
268 free(fontlist);
269#endif
270
271 if (err) {
272 /* revert to builtin fonts */
273#endif
274 sp.y += 2;
275 if (fontsize <= 8.5) {
276 gdImageString(im, gdFontTiny, sp.x, sp.y - 9, (unsigned char*)str, fontcolor);
277 } else if (fontsize <= 9.5) {
278 gdImageString(im, gdFontSmall, sp.x, sp.y - 12, (unsigned char*)str, fontcolor);
279 } else if (fontsize <= 10.5) {
280 gdImageString(im, gdFontMediumBold, sp.x, sp.y - 13, (unsigned char*)str, fontcolor);
281 } else if (fontsize <= 11.5) {
282 gdImageString(im, gdFontLarge, sp.x, sp.y - 14, (unsigned char*)str, fontcolor);
283 } else {
284 gdImageString(im, gdFontGiant, sp.x, sp.y - 15, (unsigned char*)str, fontcolor);
285 }
286#ifdef HAVE_GD_FREETYPE
287 }
288#endif
289 }
290}
291
292static void gdgen_textspan(GVJ_t * job, pointf p, textspan_t * span)
293{
294 gdImagePtr im = job->context;
295 pointf spf, epf;
296 double spanwidth = span->size.x * job->zoom * job->dpi.x / POINTS_PER_INCH;
297 char* fontname;
298
299 if (!im)
300 return;
301
302 switch (span->just) {
303 case 'l':
304 spf.x = 0.0;
305 break;
306 case 'r':
307 spf.x = -spanwidth;
308 break;
309 default:
310 case 'n':
311 spf.x = -spanwidth / 2;
312 break;
313 }
314 epf.x = spf.x + spanwidth;
315
316 if (job->rotation) {
317 spf.y = -spf.x + p.y;
318 epf.y = epf.x + p.y;
319 epf.x = spf.x = p.x;
320 }
321 else {
322 spf.x += p.x;
323 epf.x += p.x;
324 epf.y = spf.y = p.y - span->yoffset_centerline * job->zoom * job->dpi.x / POINTS_PER_INCH;
325 }
326
327#ifdef HAVE_GD_FONTCONFIG
328 PostscriptAlias *const pA = span->font->postscript_alias;
329 if (pA)
330 fontname = gd_psfontResolve (pA);
331 else
332#endif
333 fontname = span->font->name;
334
335 gdgen_text(im, spf, epf,
336 job->obj->pencolor.u.index,
337 span->font->size * job->zoom,
338 d2i(job->dpi.x),
339 job->rotation ? M_PI / 2 : 0,
340 fontname,
341 span->str);
342}
343
344static int gdgen_set_penstyle(GVJ_t * job, gdImagePtr im, gdImagePtr* brush)
345{
346 obj_state_t *obj = job->obj;
347 int i, pen, dashstyle[20];
348
349 if (obj->pen == PEN_DASHED) {
350 for (i = 0; i < 10; i++)
351 dashstyle[i] = obj->pencolor.u.index;
352 for (; i < 20; i++)
353 dashstyle[i] = gdTransparent;
354 gdImageSetStyle(im, dashstyle, 20);
355 pen = gdStyled;
356 } else if (obj->pen == PEN_DOTTED) {
357 for (i = 0; i < 2; i++)
358 dashstyle[i] = obj->pencolor.u.index;
359 for (; i < 12; i++)
360 dashstyle[i] = gdTransparent;
361 gdImageSetStyle(im, dashstyle, 12);
362 pen = gdStyled;
363 } else {
364 pen = obj->pencolor.u.index;
365 }
366
367 int width = d2i(obj->penwidth * job->zoom);
368 if (width < PENWIDTH_NORMAL)
369 width = PENWIDTH_NORMAL; /* gd can't do thin lines */
370 gdImageSetThickness(im, width);
371 /* use brush instead of Thickness to improve end butts */
372 if (width != (int)PENWIDTH_NORMAL) {
373 if (im->trueColor) {
374 *brush = gdImageCreateTrueColor(width,width);
375 }
376 else {
377 *brush = gdImageCreate(width, width);
378 gdImagePaletteCopy(*brush, im);
379 }
380 gdImageFilledRectangle(*brush, 0, 0, width - 1, width - 1,
381 obj->pencolor.u.index);
382 gdImageSetBrush(im, *brush);
383 if (pen == gdStyled)
384 pen = gdStyledBrushed;
385 else
386 pen = gdBrushed;
387 }
388
389 return pen;
390}
391
392static void gdgen_bezier(GVJ_t *job, pointf *A, size_t n, int filled) {
393 obj_state_t *obj = job->obj;
394 gdImagePtr im = job->context;
395 pointf V[4];
396 gdImagePtr brush = NULL;
397 gdPoint F[4];
398
399 if (!im)
400 return;
401
402 const int pen = gdgen_set_penstyle(job, im, &brush);
403 const bool pen_ok = pen != gdImageGetTransparent(im);
404 const bool fill_ok = filled && obj->fillcolor.u.index != gdImageGetTransparent(im);
405
406 if (pen_ok || fill_ok) {
407 V[3] = A[0];
408 PF2P(A[0], F[0]);
409 PF2P(A[n-1], F[3]);
410 for (size_t i = 0; i + 3 < n; i += 3) {
411 V[0] = V[3];
412 for (size_t j = 1; j <= 3; j++)
413 V[j] = A[i + j];
414 pointf p0 = V[0];
415 for (int step = 1; step <= BEZIERSUBDIVISION; step++) {
416 const pointf p1 = Bezier(V, (double)step / BEZIERSUBDIVISION, NULL, NULL);
417 PF2P(p0, F[1]);
418 PF2P(p1, F[2]);
419 if (pen_ok)
420 gdImageLine(im, F[1].x, F[1].y, F[2].x, F[2].y, pen);
421 if (fill_ok)
422 gdImageFilledPolygon(im, F, 4, obj->fillcolor.u.index);
423 p0 = p1;
424 }
425 }
426 }
427 if (brush)
428 gdImageDestroy(brush);
429}
430
431static gdPoint *points;
432static size_t points_allocated;
433
434static void gdgen_polygon(GVJ_t *job, pointf *A, size_t n, int filled) {
435 obj_state_t *obj = job->obj;
436 gdImagePtr im = job->context;
437 gdImagePtr brush = NULL;
438
439 if (!im)
440 return;
441
442 const int pen = gdgen_set_penstyle(job, im, &brush);
443 const bool pen_ok = pen != gdImageGetTransparent(im);
444 const bool fill_ok = filled && obj->fillcolor.u.index != gdImageGetTransparent(im);
445
446 if (pen_ok || fill_ok) {
447 if (n > points_allocated) {
448 points = gv_recalloc(points, points_allocated, n, sizeof(gdPoint));
450 }
451 for (size_t i = 0; i < n; i++) {
452 points[i].x = ROUND(A[i].x);
453 points[i].y = ROUND(A[i].y);
454 }
455 assert(n <= INT_MAX);
456 if (fill_ok)
457 gdImageFilledPolygon(im, points, (int)n, obj->fillcolor.u.index);
458
459 if (pen_ok)
460 gdImagePolygon(im, points, (int)n, pen);
461 }
462 if (brush)
463 gdImageDestroy(brush);
464}
465
466static void gdgen_ellipse(GVJ_t * job, pointf * A, int filled)
467{
468 obj_state_t *obj = job->obj;
469 gdImagePtr im = job->context;
470 gdImagePtr brush = NULL;
471
472 if (!im)
473 return;
474
475 const int pen = gdgen_set_penstyle(job, im, &brush);
476 const bool pen_ok = pen != gdImageGetTransparent(im);
477 const bool fill_ok = filled && obj->fillcolor.u.index != gdImageGetTransparent(im);
478
479 const double dx = 2 * (A[1].x - A[0].x);
480 const double dy = 2 * (A[1].y - A[0].y);
481
482 if (fill_ok)
483 gdImageFilledEllipse(im, ROUND(A[0].x), ROUND(A[0].y),
484 ROUND(dx), ROUND(dy),
485 obj->fillcolor.u.index);
486 if (pen_ok)
487 gdImageArc(im, ROUND(A[0].x), ROUND(A[0].y), ROUND(dx), ROUND(dy),
488 0, 360, pen);
489 if (brush)
490 gdImageDestroy(brush);
491}
492
493static void gdgen_polyline(GVJ_t *job, pointf *A, size_t n) {
494 gdImagePtr im = job->context;
495 gdImagePtr brush = NULL;
496
497 if (!im)
498 return;
499
500 const int pen = gdgen_set_penstyle(job, im, &brush);
501 const bool pen_ok = pen != gdImageGetTransparent(im);
502
503 if (pen_ok) {
504 pointf p = A[0];
505 for (size_t i = 1; i < n; i++) {
506 const pointf p1 = A[i];
507 gdImageLine(im, ROUND(p.x), ROUND(p.y),
508 ROUND(p1.x), ROUND(p1.y), pen);
509 p = p1;
510 }
511 }
512 if (brush)
513 gdImageDestroy(brush);
514}
515
517 0, /* gdgen_begin_job */
518 0, /* gdgen_end_job */
519 0, /* gdgen_begin_graph */
520 0, /* gdgen_end_graph */
521 0, /* gdgen_begin_layer */
522 0, /* gdgen_end_layer */
525 0, /* gdgen_begin_cluster */
526 0, /* gdgen_end_cluster */
527 0, /* gdgen_begin_nodes */
528 0, /* gdgen_end_nodes */
529 0, /* gdgen_begin_edges */
530 0, /* gdgen_end_edges */
531 0, /* gdgen_begin_node */
532 0, /* gdgen_end_node */
533 0, /* gdgen_begin_edge */
534 0, /* gdgen_end_edge */
535 0, /* gdgen_begin_anchor */
536 0, /* gdgen_end_anchor */
537 0, /* gdgen_begin_label */
538 0, /* gdgen_end_label */
545 0, /* gdgen_comment */
546 0, /* gdgen_library_shape */
547};
548
550 GVRENDER_Y_GOES_DOWN, /* flags */
551 4., /* default pad - graph units */
552 NULL, /* knowncolors */
553 0, /* sizeof knowncolors */
554 RGBA_BYTE, /* color_type */
555};
556
558 GVDEVICE_BINARY_FORMAT, /* flags */
559 {0.,0.}, /* default margin - points */
560 {0.,0.}, /* default page width, height - points */
561 {96.,96.}, /* default dpi */
562};
563
566 | GVDEVICE_DOES_TRUECOLOR,/* flags */
567 {0.,0.}, /* default margin - points */
568 {0.,0.}, /* default page width, height - points */
569 {96.,96.}, /* default dpi */
570};
571
575 | GVDEVICE_NO_WRITER, /* flags */
576 {0.,0.}, /* default margin - points */
577 {0.,0.}, /* default page width, height - points */
578 {96.,96.}, /* default dpi */
579};
580
585
587 {FORMAT_GIF, "gif:gd", 1, NULL, &device_features_gd_tc}, /* pretend gif is truecolor because it supports transparency */
588 {FORMAT_WBMP, "wbmp:gd", 1, NULL, &device_features_gd},
589
590#ifdef HAVE_GD_JPEG
591 {FORMAT_JPEG, "jpe:gd", 1, NULL, &device_features_gd},
592 {FORMAT_JPEG, "jpeg:gd", 1, NULL, &device_features_gd},
593 {FORMAT_JPEG, "jpg:gd", 1, NULL, &device_features_gd},
594#endif
595
596#ifdef HAVE_GD_PNG
597 {FORMAT_PNG, "png:gd", 1, NULL, &device_features_gd_tc},
598#endif
599
601
602#ifdef HAVE_LIBZ
604#endif
605
606 {0, NULL, 0, NULL, NULL}
607};
Memory allocation wrappers that exit on failure.
static void * gv_recalloc(void *ptr, size_t old_nmemb, size_t new_nmemb, size_t size)
Definition alloc.h:73
#define ROUND(f)
Definition arith.h:48
#define M_PI
Definition arith.h:41
@ RGBA_BYTE
Definition color.h:26
@ COLOR_INDEX
Definition color.h:27
static char * err
Definition delaunay.c:532
static float dy
Definition draw.c:40
static float dx
Definition draw.c:39
#define A(n, t)
Definition expr.h:76
#define F
Definition expr.h:70
char * gd_psfontResolve(PostscriptAlias *pa)
#define V
Definition gdefs.h:5
int gvdevice_gd_putBuf(gdIOCtx *context, const void *buffer, int len)
Definition gvdevice_gd.c:24
void gvdevice_gd_putC(gdIOCtx *context, int C)
Definition gvdevice_gd.c:33
#define PF2P(pf, p)
Definition geom.h:67
#define POINTS_PER_INCH
Definition geom.h:58
static WUR pointf scale(double c, pointf p)
Definition geomprocs.h:148
void free(void *)
node NULL
Definition grammar.y:181
char * agget(void *obj, char *name)
Definition attr.c:448
#define GD_has_images(g)
Definition types.h:369
Arithmetic helper functions.
static int d2i(double v)
Definition gv_math.h:154
@ PEN_DOTTED
Definition gvcjob.h:35
@ PEN_DASHED
Definition gvcjob.h:35
#define GVDEVICE_NO_WRITER
Definition gvcjob.h:93
#define GVDEVICE_DOES_TRUECOLOR
Definition gvcjob.h:90
#define GVDEVICE_BINARY_FORMAT
Definition gvcjob.h:91
#define PENWIDTH_NORMAL
Definition gvcjob.h:40
#define GVRENDER_Y_GOES_DOWN
Definition gvcjob.h:94
static void color(Agraph_t *g)
Definition gvcolor.c:116
static const char black[]
pointf Bezier(pointf *V, double t, pointf *Left, pointf *Right)
static void gdgen_end_page(GVJ_t *job)
@ FORMAT_JPEG
Definition gvrender_gd.c:38
@ FORMAT_GD
Definition gvrender_gd.c:41
@ FORMAT_GD2
Definition gvrender_gd.c:42
@ FORMAT_WBMP
Definition gvrender_gd.c:40
@ FORMAT_GIF
Definition gvrender_gd.c:37
@ FORMAT_XBM
Definition gvrender_gd.c:43
@ FORMAT_PNG
Definition gvrender_gd.c:39
static void gdgen_polyline(GVJ_t *job, pointf *A, size_t n)
static gdPoint * points
bool mapbool(const char *)
Definition utils.c:339
static gvdevice_features_t device_features_gd
static int gdgen_set_penstyle(GVJ_t *job, gdImagePtr im, gdImagePtr *brush)
static gvdevice_features_t device_features_gd_tc
static void gdgen_ellipse(GVJ_t *job, pointf *A, int filled)
static int transparent
Definition gvrender_gd.c:73
static void gdgen_bezier(GVJ_t *job, pointf *A, size_t n, int filled)
static int basecolor
Definition gvrender_gd.c:73
gvplugin_installed_t gvrender_gd_types[]
static void gdgen_resolve_color(GVJ_t *job, gvcolor_t *color)
Definition gvrender_gd.c:51
static void gdgen_textspan(GVJ_t *job, pointf p, textspan_t *span)
static gvdevice_features_t device_features_gd_tc_no_writer
gvplugin_installed_t gvdevice_gd_types2[]
static void gdgen_begin_page(GVJ_t *job)
Definition gvrender_gd.c:77
static size_t points_allocated
#define GD_XYMAX
Definition gvrender_gd.c:75
static gvrender_features_t render_features_gd
#define FONTSIZE_MUCH_TOO_SMALL
static void gdgen_polygon(GVJ_t *job, pointf *A, size_t n, int filled)
static gvrender_engine_t gdgen_engine
#define BEZIERSUBDIVISION
Definition gvrender_gd.c:49
void gdgen_text(gdImagePtr im, pointf spf, pointf epf, int fontcolor, double fontsize, int fontdpi, double fontangle, char *fontname, char *str)
#define FONTSIZE_TOO_SMALL
textitem scanner parser str
Definition htmlparse.y:218
$2 font
Definition htmlparse.y:294
#define alpha
Definition shapes.c:4056
char * cmdname
Definition gvcommon.h:21
void(* errorfn)(const char *fmt,...)
Definition gvcommon.h:24
int verbose
Definition gvcommon.h:22
graph_t * g
Definition gvcint.h:118
int rotation
Definition gvcjob.h:319
pointf dpi
Definition gvcjob.h:325
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
GVCOMMON_t * common
Definition gvcjob.h:267
FILE * output_file
Definition gvcjob.h:277
double zoom
Definition gvcjob.h:318
GVC_t * gvc
Definition gvcjob.h:263
unsigned int width
Definition gvcjob.h:327
unsigned int height
Definition gvcjob.h:328
int index
Definition color.h:37
union color_s::@40 u
gvrender_features_t * features
Definition gvcjob.h:137
ingroup plugin_api
Definition gvplugin.h:35
gvcolor_t fillcolor
Definition gvcjob.h:194
pen_type pen
Definition gvcjob.h:197
gvcolor_t pencolor
Definition gvcjob.h:194
double penwidth
Definition gvcjob.h:199
Definition geom.h:27
int y
Definition geom.h:27
int x
Definition geom.h:27
double x
Definition geom.h:29
double y
Definition geom.h:29
char * name
Definition textspan.h:54
PostscriptAlias * postscript_alias
Definition textspan.h:56
double size
Definition textspan.h:57
char * str
Definition textspan.h:65
char just
'l' 'n' 'r'
Definition textspan.h:71
pointf size
Definition textspan.h:70
textfont_t * font
Definition textspan.h:66
double yoffset_centerline
Definition textspan.h:69
#define UNREACHABLE()
Definition unreachable.h:30