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