28 #define INT32_MAX (2147483647)
31 #define UINT32_MAX (4294967295U)
48 #define BEZIERSUBDIVISION 10
52 gdImagePtr im = (gdImagePtr) job->
context;
59 alpha = (255 - color->
u.
rgba[3]) * gdAlphaMax / 255;
61 if(
alpha == gdAlphaMax)
62 color->
u.
index = gdImageGetTransparent(im);
64 color->
u.
index = gdImageColorResolveAlpha(im,
72 static int white, black, transparent, basecolor;
74 #define GD_XYMAX INT32_MAX
76 static void gdgen_begin_page(
GVJ_t * job)
78 char *bgcolor_str =
NULL, *truecolor_str =
NULL;
79 boolean truecolor_p =
FALSE;
80 boolean bg_transparent_p =
FALSE;
86 if (truecolor_str && truecolor_str[0])
87 truecolor_p =
mapbool(truecolor_str);
89 if (bgcolor_str && strcmp(bgcolor_str,
"transparent") == 0) {
90 bg_transparent_p =
TRUE;
100 fprintf(stderr,
"%s: using existing GD image\n", job->
common->
cmdname);
101 im = (gdImagePtr) (job->
context);
109 "%s: graph is too large for gd-renderer bitmaps. Scaling by %g to fit\n",
115 "%s: allocating a %dK TrueColor GD image (%d x %d pixels)\n",
119 im = gdImageCreateTrueColor(job->
width, job->
height);
123 "%s: allocating a %dK PaletteColor GD image (%d x %d pixels)\n",
133 job->
common->
errorfn(
"gdImageCreate returned NULL. Malloc problem?\n");
139 transparent = gdImageColorResolveAlpha(im,
140 gdRedMax - 1, gdGreenMax,
141 gdBlueMax, gdAlphaTransparent);
142 gdImageColorTransparent(im, transparent);
144 white = gdImageColorResolveAlpha(im,
145 gdRedMax, gdGreenMax, gdBlueMax,
148 black = gdImageColorResolveAlpha(im, 0, 0, 0, gdAlphaOpaque);
152 gdImageAlphaBlending(im,
FALSE);
153 gdImageFill(im, im->sx / 2, im->sy / 2, transparent);
156 gdImageAlphaBlending(im,
TRUE);
162 static void gdgen_end_page(
GVJ_t * job)
164 gdImagePtr im = (gdImagePtr) job->
context;
170 ctx.tell = (
void*)job;
177 fprintf(stderr,
"gdgen_end_graph (to memory)\n");
183 gdImageSaveAlpha(im, (basecolor == transparent));
187 gdImageTrueColorToPalette(im, 0, 256);
188 gdImageGifCtx(im, &ctx);
201 #define JPEG_QUALITY -1
202 gdImageJpegCtx(im, &ctx, JPEG_QUALITY);
208 gdImagePngCtx(im, &ctx);
216 int black = gdImageColorResolveAlpha(im, 0, 0, 0, gdAlphaOpaque);
217 gdImageWBMPCtx(im, black, &ctx);
228 #define GD2_CHUNKSIZE 128
230 #define GD2_COMPRESSED 2
231 gdImageGd2(im, job->
output_file, GD2_CHUNKSIZE, GD2_COMPRESSED);
246 fprintf(stderr,
"gdgen_end_graph (to file)\n");
252 static void gdgen_missingfont(
char *err,
char *fontreq)
254 static char *lastmissing = 0;
255 static int n_errors = 0;
259 if ((lastmissing == 0) || (strcmp(lastmissing, fontreq))) {
260 #ifdef HAVE_GD_FONTCONFIG
266 char *p = getenv(
"GDFONTPATH");
268 p = DEFAULT_FONTPATH;
271 agerr(
AGERR,
"%s : %s in %s\n", err, fontreq, p);
276 lastmissing = strdup(fontreq);
287 #define FONTSIZE_MUCH_TOO_SMALL 0.15
289 #define FONTSIZE_TOO_SMALL 1.5
292 # define GD_IMPORT __declspec(dllimport)
294 # define GD_IMPORT extern
298 void gdgen_text(gdImagePtr im,
pointf spf,
pointf epf,
int fontcolor,
double fontsize,
int fontdpi,
double fontangle,
char *fontname,
char *
str)
300 gdFTStringExtra strex;
306 strex.flags = gdFTEX_RESOLUTION;
307 strex.hdpi = strex.vdpi = fontdpi;
309 if (strstr(fontname,
"/"))
310 strex.flags |= gdFTEX_FONTPATHNAME;
312 strex.flags |= gdFTEX_FONTCONFIG;
318 gdImageLine(im, sp.
x, sp.
y, ep.
x, ep.
y, fontcolor);
320 #ifdef HAVE_GD_FREETYPE
323 #ifdef HAVE_GD_FONTCONFIG
324 char* fontlist = fontname;
326 extern char *gd_alternate_fontlist(
char *font);
327 char* fontlist = gd_alternate_fontlist(fontname);
329 err = gdImageStringFTEx(im, brect, fontcolor,
330 fontlist, fontsize, fontangle, sp.
x, sp.
y, str, &strex);
334 gdgen_missingfont(err, fontname);
337 if (fontsize <= 8.5) {
338 gdImageString(im, gdFontTiny, sp.
x, sp.
y - 9, (
unsigned char*)str, fontcolor);
339 }
else if (fontsize <= 9.5) {
340 gdImageString(im, gdFontSmall, sp.
x, sp.
y - 12, (
unsigned char*)str, fontcolor);
341 }
else if (fontsize <= 10.5) {
342 gdImageString(im, gdFontMediumBold, sp.
x, sp.
y - 13, (
unsigned char*)str, fontcolor);
343 }
else if (fontsize <= 11.5) {
344 gdImageString(im, gdFontLarge, sp.
x, sp.
y - 14, (
unsigned char*)str, fontcolor);
346 gdImageString(im, gdFontGiant, sp.
x, sp.
y - 15, (
unsigned char*)str, fontcolor);
348 #ifdef HAVE_GD_FREETYPE
358 gdImagePtr im = (gdImagePtr) job->
context;
362 #ifdef HAVE_GD_FONTCONFIG
369 switch (span->
just) {
378 spf.
x = -spanwidth / 2;
381 epf.x = spf.
x + spanwidth;
384 spf.
y = -spf.
x + p.
y;
394 #ifdef HAVE_GD_FONTCONFIG
411 static int gdgen_set_penstyle(
GVJ_t * job, gdImagePtr im, gdImagePtr* brush)
414 int i, pen, width, dashstyle[40];
417 for (i = 0; i < 10; i++)
420 dashstyle[i] = gdTransparent;
421 gdImageSetStyle(im, dashstyle, 20);
424 for (i = 0; i < 2; i++)
427 dashstyle[i] = gdTransparent;
428 gdImageSetStyle(im, dashstyle, 12);
437 gdImageSetThickness(im, width);
441 *brush = gdImageCreateTrueColor(width,width);
444 *brush = gdImageCreate(width, width);
445 gdImagePaletteCopy(*brush, im);
447 gdImageFilledRectangle(*brush, 0, 0, width - 1, width - 1,
449 gdImageSetBrush(im, *brush);
451 pen = gdStyledBrushed;
460 gdgen_bezier(
GVJ_t * job,
pointf * A,
int n,
int arrow_at_start,
461 int arrow_at_end,
int filled)
464 gdImagePtr im = (gdImagePtr) job->
context;
467 boolean pen_ok, fill_ok;
468 gdImagePtr brush =
NULL;
474 pen = gdgen_set_penstyle(job, im, &brush);
475 pen_ok = (pen != gdImageGetTransparent(im));
476 fill_ok = (filled && obj->
fillcolor.
u.
index != gdImageGetTransparent(im));
478 if (pen_ok || fill_ok) {
482 for (i = 0; i + 3 < n; i += 3) {
484 for (j = 1; j <= 3; j++)
492 gdImageLine(im, F[1].x, F[1].y, F[2].x, F[2].y, pen);
500 gdImageDestroy(brush);
503 static gdPoint *points;
504 static int points_allocated;
506 static void gdgen_polygon(
GVJ_t * job,
pointf * A,
int n,
int filled)
509 gdImagePtr im = (gdImagePtr) job->
context;
510 gdImagePtr brush =
NULL;
513 boolean pen_ok, fill_ok;
518 pen = gdgen_set_penstyle(job, im, &brush);
519 pen_ok = (pen != gdImageGetTransparent(im));
520 fill_ok = (filled && obj->
fillcolor.
u.
index != gdImageGetTransparent(im));
522 if (pen_ok || fill_ok) {
523 if (n > points_allocated) {
524 points = realloc(points, n *
sizeof(gdPoint));
525 points_allocated = n;
527 for (i = 0; i < n; i++) {
528 points[i].x =
ROUND(A[i].x);
529 points[i].y =
ROUND(A[i].y);
535 gdImagePolygon(im, points, n, pen);
538 gdImageDestroy(brush);
541 static void gdgen_ellipse(
GVJ_t * job,
pointf * A,
int filled)
544 gdImagePtr im = (gdImagePtr) job->
context;
547 boolean pen_ok, fill_ok;
548 gdImagePtr brush =
NULL;
553 pen = gdgen_set_penstyle(job, im, &brush);
554 pen_ok = (pen != gdImageGetTransparent(im));
555 fill_ok = (filled && obj->
fillcolor.
u.
index != gdImageGetTransparent(im));
557 dx = 2 * (A[1].
x - A[0].
x);
558 dy = 2 * (A[1].
y - A[0].
y);
561 gdImageFilledEllipse(im,
ROUND(A[0].x),
ROUND(A[0].y),
568 gdImageDestroy(brush);
571 static void gdgen_polyline(
GVJ_t * job,
pointf * A,
int n)
573 gdImagePtr im = (gdImagePtr) job->
context;
578 gdImagePtr brush =
NULL;
583 pen = gdgen_set_penstyle(job, im, &brush);
584 pen_ok = (pen != gdImageGetTransparent(im));
588 for (i = 1; i < n; i++) {
596 gdImageDestroy(brush);
665 {
FORMAT_GD,
"gd", 1, &gdgen_engine, &render_features_gd},
685 {
FORMAT_GD,
"gd:gd", 1,
NULL, &device_features_gd_tc_no_writer},
688 {
FORMAT_GD2,
"gd2:gd", 1,
NULL, &device_features_gd_tc_no_writer},
void gdgen_text(gdImagePtr im, pointf spf, pointf epf, int fontcolor, double fontsize, int fontdpi, double fontangle, char *fontname, char *str)
#define FONTSIZE_MUCH_TOO_SMALL
GD_IMPORT gdFontPtr gdFontSmall
#define GVDEVICE_BINARY_FORMAT
char * gd_psfontResolve(PostscriptAlias *pa)
gvplugin_installed_t gvdevice_gd_types2[]
GD_IMPORT gdFontPtr gdFontMediumBold
int agerr(agerrlevel_t level, const char *fmt,...)
char * agget(void *obj, char *name)
#define GVRENDER_Y_GOES_DOWN
#define GVDEVICE_NO_WRITER
gvplugin_active_render_t render
gvrender_features_t * features
gvplugin_installed_t gvrender_gd_types[]
double yoffset_centerline
PostscriptAlias * postscript_alias
GD_IMPORT gdFontPtr gdFontGiant
if(aagss+aagstacksize-1<=aagssp)
void(* errorfn)(const char *fmt,...)
pointf Bezier(pointf *V, int degree, double t, pointf *Left, pointf *Right)
GD_IMPORT gdFontPtr gdFontTiny
void gvdevice_gd_putC(gdIOCtx *context, int C)
#define BEZIERSUBDIVISION
GD_IMPORT gdFontPtr gdFontLarge
int gvdevice_gd_putBuf(gdIOCtx *context, const void *buffer, int len)
#define FONTSIZE_TOO_SMALL
#define GVDEVICE_DOES_TRUECOLOR