diff -bru GDD/R/GDD.R GDD.patched/R/GDD.R --- GDD/R/GDD.R 2005-12-03 20:10:07.000000000 -0600 +++ GDD.patched/R/GDD.R 2005-12-07 16:12:17.000000000 -0600 @@ -1,5 +1,5 @@ -GDD <- function(file="plot", type="png", width=400, height=300, ps=12, bg="white") { - invisible(.External("gdd_create_new_device", as.character(type), as.character(file), width, height, ps, bg, PACKAGE="GDD")) +GDD <- function(file="plot", type="png", width=400, height=300, ps=12, bg="white",ctx=NULL) { + invisible(.External("gdd_create_new_device", as.character(type), as.character(file), width, height, ps, bg, ctx, PACKAGE="GDD")) } .GDD.font <- function(name=NULL) { diff -bru GDD/src/GDD.c GDD.patched/src/GDD.c --- GDD/src/GDD.c 2005-12-03 20:10:07.000000000 -0600 +++ GDD.patched/src/GDD.c 2005-12-07 16:12:05.000000000 -0600 @@ -32,7 +32,7 @@ bgcolor: currently only -1 (transparent) and 0xffffff (white) are really supported */ Rboolean gdd_new_device_driver(DevDesc *dd, char *type, char *file, double width, double height, double initps, - int bgcolor) + int bgcolor, gdIOCtxPtr ioctx) { GDDDesc *xd; @@ -54,7 +54,7 @@ xd->basefontface = 1; xd->basefontsize = initps; - if (!GDD_Open((NewDevDesc*)(dd), xd, type, file, width, height, bgcolor)) { + if (!GDD_Open((NewDevDesc*)(dd), xd, type, file, width, height, bgcolor, ioctx)) { free(xd); return FALSE; } @@ -141,6 +141,11 @@ char *type, *file; double width, height, initps; int bgcolor = -1; + gdIOCtxPtr ioctx; + + /* Output initialize */ + file = NULL; + ioctx = NULL; SEXP v; args=CDR(args); @@ -168,6 +173,11 @@ #ifdef JGD_DEBUG printf("type=%s, file=%s, bgcolor=0x%08x\n", type, file, bgcolor); #endif + v=CAR(args); args=CDR(args); + if (v != R_NilValue && TYPEOF(v) == EXTPTRSXP){ + file = NULL; + ioctx = (gdIOCtxPtr) R_ExternalPtrAddr(v); + } R_CheckDeviceAvailable(); @@ -179,7 +189,7 @@ dev->savedSnapshot = R_NilValue; - if (!gdd_new_device_driver((DevDesc*)(dev), type, file, width, height, initps, bgcolor)) + if (!gdd_new_device_driver((DevDesc*)(dev), type, file, width, height, initps, bgcolor, ioctx)) { free(dev); error("unable to start device %s", devname); diff -bru GDD/src/GDD.h GDD.patched/src/GDD.h --- GDD/src/GDD.h 2005-12-03 20:10:07.000000000 -0600 +++ GDD.patched/src/GDD.h 2005-12-07 16:12:05.000000000 -0600 @@ -17,6 +17,7 @@ #include #include #include +#include /* the internal representation of a color in this (R) API is RGBa with a=0 meaning transparent and a=255 meaning opaque (hence a means 'opacity'). previous implementation was different (inverse meaning and 0x80 as NA), so watch out. */ #if R_VERSION < 0x20000 @@ -47,7 +48,7 @@ int gd_fill, gd_draw; /* current GD colors */ double gd_ftsize, gd_ftm_ascent, gd_ftm_descent, gd_ftm_width; int gd_ftm_char; /*gd_ftm_xxx are font-metric cached values - char specifying the last query */ - + gdIOCtxPtr ioctx; /* Context for doing output IO, rather than outputing to a file */ char *img_name; /* file name prefix */ int img_seq; /* sequence # in case multiple pages are requested */ char img_type[8]; /* image type [png/png8/png24/gif] */ @@ -55,8 +56,8 @@ } GDDDesc; void setupGDDfunctions(NewDevDesc *dd); -Rboolean GDD_Open(NewDevDesc *dd, GDDDesc *xd, char *type, char *file, double w, double h, int bgcolor); -Rboolean gdd_new_device_driver(DevDesc*, char*, char *, double, double, double, int); +Rboolean GDD_Open(NewDevDesc *dd, GDDDesc *xd, char *type, char *file, double w, double h, int bgcolor, gdIOCtxPtr); +Rboolean gdd_new_device_driver(DevDesc*, char*, char *, double, double, double, int, gdIOCtxPtr); int gdd_set_new_device_data(NewDevDesc *dd, double gamma_fac, GDDDesc *xd); GDDDesc * gdd_alloc_device_desc(double ps); diff -bru GDD/src/GDDtalk.c GDD.patched/src/GDDtalk.c --- GDD/src/GDDtalk.c 2005-12-03 20:10:07.000000000 -0600 +++ GDD.patched/src/GDDtalk.c 2005-12-07 16:12:05.000000000 -0600 @@ -263,12 +263,38 @@ error("Unsupported image type (%s).", it); } +static void sendActiveImage(GDDDesc *xd){ + if (!strcmp(xd->img_type, "png") || !strcmp(xd->img_type, "png24") || !strcmp(xd->img_type,"png8")) { + gdImagePngCtx (xd->img, xd->ioctx); + return; + } + + if (!strcmp(xd->img_type, "gif")) { + gdImageGifCtx(xd->img, xd->ioctx); + return; + } + + if (!strcmp(xd->img_type, "jpeg") || !strcmp(xd->img_type, "jpg")) { + gdImageJpegCtx (xd->img, xd->ioctx, 80); + return; + } +} + +static void genActiveImage(GDDDesc * xd){ + if (xd->img_name != NULL) + saveActiveImage(xd); + else if (xd->ioctx != NULL) + sendActiveImage(xd); + else + error("output to file or context not specified"); +} + static void GDD_Close(NewDevDesc *dd) { GDDDesc *xd = (GDDDesc *) dd->deviceSpecific; if(!xd || !xd->img) return; - saveActiveImage(xd); + genActiveImage(xd); gdImageDestroy (xd->img); xd->img=0; } @@ -360,8 +386,8 @@ devNr = devNumber((DevDesc*) dd); - if (xd->img_seq!=-1) /* first request is not saved as this is part of the init */ - saveActiveImage(xd); + if (xd->img_seq!=-1) /* first request is not generated as this is part of the init */ + genActiveImage(xd); xd->img_seq++; white = gdTrueColor (255, 255, 255); /* FIXME: we don't respect canvas color here */ @@ -371,7 +397,7 @@ sendGC(xd, gc, 1); } -Rboolean GDD_Open(NewDevDesc *dd, GDDDesc *xd, char *type, char *file, double w, double h, int bgcolor) +Rboolean GDD_Open(NewDevDesc *dd, GDDDesc *xd, char *type, char *file, double w, double h, int bgcolor, gdIOCtxPtr ioctx) { int white; @@ -383,8 +409,18 @@ xd->img_type[7]=0; strncpy(xd->img_type, type, 7); + if (file != NULL){ xd->img_name=(char*) malloc(strlen(file)+1); strcpy(xd->img_name, file); + xd->ioctx = NULL; + } else if (ioctx != NULL){ + xd->img_name=NULL; + xd->ioctx = ioctx; + } else { + error("output not specified as either to a file or to a context"); + return FALSE; + } + xd->img_seq=-1; xd->img = gdImageCreateTrueColor(R2I(w), R2I(h));