46extern bool mapbool(
const char *);
49#define BEZIERSUBDIVISION 10
60 alpha = (255 -
color->u.rgba[3]) * gdAlphaMax / 255;
62 if(
alpha == gdAlphaMax)
63 color->u.index = gdImageGetTransparent(im);
65 color->u.index = gdImageColorResolveAlpha(im,
75#define GD_XYMAX INT32_MAX
79 bool truecolor_p =
false;
82 const char *
const truecolor_str =
agget(job->
gvc->
g,
"truecolor");
83 const char *
const bgcolor_str =
agget(job->
gvc->
g,
"bgcolor");
85 if (truecolor_str && truecolor_str[0])
86 truecolor_p =
mapbool(truecolor_str);
88 if (bgcolor_str && strcmp(bgcolor_str,
"transparent") == 0) {
98 fprintf(stderr,
"%s: using existing GD image\n", job->
common->
cmdname);
108 "%s: graph is too large for gd-renderer bitmaps. Scaling by %g to fit\n",
111 assert(job->
width <= INT_MAX);
112 assert(job->
height <= INT_MAX);
116 "%s: allocating a %0.fK TrueColor GD image (%d x %d pixels)\n",
120 im = gdImageCreateTrueColor((
int)job->
width, (
int)job->
height);
124 "%s: allocating a %.0fK PaletteColor GD image (%d x %d pixels)\n",
128 im = gdImageCreate((
int)job->
width, (
int)job->
height);
134 job->
common->
errorfn(
"gdImageCreate returned NULL. Malloc problem?\n");
141 gdRedMax - 1, gdGreenMax,
142 gdBlueMax, gdAlphaTransparent);
147 gdImageAlphaBlending(im,
false);
148 gdImageFill(im, im->sx / 2, im->sy / 2,
transparent);
151 gdImageAlphaBlending(im,
true);
174 gdImageTrueColorToPalette(im, 0, 256);
175 gdImageGifCtx(im, &gd_context.
ctx);
187#define JPEG_QUALITY -1
188 gdImageJpegCtx(im, &gd_context.
ctx, JPEG_QUALITY);
194 gdImagePngCtx(im, &gd_context.
ctx);
201 int black = gdImageColorResolveAlpha(im, 0, 0, 0, gdAlphaOpaque);
202 gdImageWBMPCtx(im,
black, &gd_context.
ctx);
212#define GD2_CHUNKSIZE 128
213#define GD2_COMPRESSED 2
214 gdImageGd2(im, job->
output_file, GD2_CHUNKSIZE, GD2_COMPRESSED);
229#define FONTSIZE_MUCH_TOO_SMALL 0.15
231#define FONTSIZE_TOO_SMALL 1.5
233void gdgen_text(gdImagePtr im,
pointf spf,
pointf epf,
int fontcolor,
double fontsize,
int fontdpi,
double fontangle,
char *fontname,
char *
str)
240 gdFTStringExtra strex = {
241 .flags = gdFTEX_RESOLUTION,
246 if (strchr(fontname,
'/'))
247 strex.flags |= gdFTEX_FONTPATHNAME;
249 strex.flags |= gdFTEX_FONTCONFIG;
255 gdImageLine(im, sp.
x, sp.
y, ep.
x, ep.
y, fontcolor);
257#ifdef HAVE_GD_FREETYPE
259#ifdef HAVE_GD_FONTCONFIG
260 char* fontlist = fontname;
262 extern char *gd_alternate_fontlist(
const char *
font);
263 char* fontlist = gd_alternate_fontlist(fontname);
265 const char *
const err = gdImageStringFTEx(im, brect, fontcolor,
266 fontlist, fontsize, fontangle, sp.
x, sp.
y,
str, &strex);
267#ifndef HAVE_GD_FONTCONFIG
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);
284 gdImageString(im, gdFontGiant, sp.
x, sp.
y - 15, (
unsigned char*)
str, fontcolor);
286#ifdef HAVE_GD_FREETYPE
302 switch (span->
just) {
311 spf.
x = -spanwidth / 2;
314 epf.
x = spf.
x + spanwidth;
317 spf.
y = -spf.
x + p.
y;
327#ifdef HAVE_GD_FONTCONFIG
347 int i, pen, dashstyle[20];
350 for (i = 0; i < 10; i++)
353 dashstyle[i] = gdTransparent;
354 gdImageSetStyle(im, dashstyle, 20);
357 for (i = 0; i < 2; i++)
360 dashstyle[i] = gdTransparent;
361 gdImageSetStyle(im, dashstyle, 12);
370 gdImageSetThickness(im, width);
374 *brush = gdImageCreateTrueColor(width,width);
377 *brush = gdImageCreate(width, width);
378 gdImagePaletteCopy(*brush, im);
380 gdImageFilledRectangle(*brush, 0, 0, width - 1, width - 1,
382 gdImageSetBrush(im, *brush);
384 pen = gdStyledBrushed;
396 gdImagePtr brush =
NULL;
403 const bool pen_ok = pen != gdImageGetTransparent(im);
404 const bool fill_ok = filled && obj->
fillcolor.
u.
index != gdImageGetTransparent(im);
406 if (pen_ok || fill_ok) {
410 for (
size_t i = 0; i + 3 < n; i += 3) {
412 for (
size_t j = 1; j <= 3; j++)
420 gdImageLine(im,
F[1].x,
F[1].y,
F[2].x,
F[2].y, pen);
428 gdImageDestroy(brush);
437 gdImagePtr brush =
NULL;
443 const bool pen_ok = pen != gdImageGetTransparent(im);
444 const bool fill_ok = filled && obj->
fillcolor.
u.
index != gdImageGetTransparent(im);
446 if (pen_ok || fill_ok) {
451 for (
size_t i = 0; i < n; i++) {
455 assert(n <= INT_MAX);
460 gdImagePolygon(im,
points, (
int)n, pen);
463 gdImageDestroy(brush);
470 gdImagePtr brush =
NULL;
476 const bool pen_ok = pen != gdImageGetTransparent(im);
477 const bool fill_ok = filled && obj->
fillcolor.
u.
index != gdImageGetTransparent(im);
479 const double dx = 2 * (
A[1].x -
A[0].x);
480 const double dy = 2 * (
A[1].y -
A[0].y);
490 gdImageDestroy(brush);
495 gdImagePtr brush =
NULL;
501 const bool pen_ok = pen != gdImageGetTransparent(im);
505 for (
size_t i = 1; i < n; i++) {
513 gdImageDestroy(brush);
Memory allocation wrappers that exit on failure.
static void * gv_recalloc(void *ptr, size_t old_nmemb, size_t new_nmemb, size_t size)
char * gd_psfontResolve(PostscriptAlias *pa)
int gvdevice_gd_putBuf(gdIOCtx *context, const void *buffer, int len)
void gvdevice_gd_putC(gdIOCtx *context, int C)
static WUR pointf scale(double c, pointf p)
char * agget(void *obj, char *name)
Arithmetic helper functions.
#define GVDEVICE_NO_WRITER
#define GVDEVICE_DOES_TRUECOLOR
#define GVDEVICE_BINARY_FORMAT
#define GVRENDER_Y_GOES_DOWN
static void color(Agraph_t *g)
static const char black[]
pointf Bezier(pointf *V, double t, pointf *Left, pointf *Right)
static void gdgen_end_page(GVJ_t *job)
static void gdgen_polyline(GVJ_t *job, pointf *A, size_t n)
bool mapbool(const char *)
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 void gdgen_bezier(GVJ_t *job, pointf *A, size_t n, int filled)
gvplugin_installed_t gvrender_gd_types[]
static void gdgen_resolve_color(GVJ_t *job, gvcolor_t *color)
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)
static size_t points_allocated
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
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
void(* errorfn)(const char *fmt,...)
gvplugin_active_render_t render
gvrender_features_t * features
PostscriptAlias * postscript_alias
double yoffset_centerline