#ifdef PERL_CAPI #define WIN32IO_IS_STDIO #endif #include "EXTERN.h" #include "perl.h" #include "XSUB.h" #include #include #include #include #include #include #include #ifdef FCGI #include #else #ifdef USE_SFIO #include #else #include #endif #include #endif /* Copyright 1995 - 1998, Lincoln D. Stein. See accompanying README file for usage restrictions */ #ifndef PERL_REVISION # ifndef __PATCHLEVEL_H_INCLUDED__ # include "patchlevel.h" # endif # ifndef PERL_REVISION # define PERL_REVISION (5) /* Replace: 1 */ # define PERL_VERSION PATCHLEVEL # define PERL_SUBVERSION SUBVERSION /* Replace PERL_PATCHLEVEL with PERL_VERSION */ /* Replace: 0 */ # endif #endif #if (PERL_VERSION == 5) && (PERL_SUBVERSION==3) #ifndef PL_na # define PL_na na #endif #ifndef SvPV_nolen # define SvPV_nolen(sv) SvPV(sv, PL_na) #endif #endif /* 5.00503 */ #ifdef WIN32 #define snprintf _snprintf #endif #ifndef START_MY_CXT static truecolor_default = 0; #endif static int not_here(char *s) { croak("%s not implemented on this architecture", s); return -1; } static double constant(char *name) { errno = 0; switch (*name) { case 'A': break; case 'B': break; case 'C': break; case 'D': break; case 'E': break; case 'F': break; case 'G': if (strEQ(name, "GD_CMP_IMAGE")) #ifdef GD_CMP_IMAGE return GD_CMP_IMAGE; #else goto not_there; #endif if (strEQ(name, "GD_CMP_NUM_COLORS")) #ifdef GD_CMP_NUM_COLORS return GD_CMP_NUM_COLORS; #else goto not_there; #endif if (strEQ(name, "GD_CMP_COLOR")) #ifdef GD_CMP_COLOR return GD_CMP_COLOR; #else goto not_there; #endif if (strEQ(name, "GD_CMP_SIZE_X")) #ifdef GD_CMP_SIZE_X return GD_CMP_SIZE_X; #else goto not_there; #endif if (strEQ(name, "GD_CMP_SIZE_Y")) #ifdef GD_CMP_SIZE_Y return GD_CMP_SIZE_Y; #else goto not_there; #endif if (strEQ(name, "GD_CMP_TRANSPARENT")) #ifdef GD_CMP_TRANSPARENT return GD_CMP_TRANSPARENT; #else goto not_there; #endif if (strEQ(name, "GD_CMP_BACKGROUND")) #ifdef GD_CMP_BACKGROUND return GD_CMP_BACKGROUND; #else goto not_there; #endif if (strEQ(name, "GD_CMP_INTERLACE")) #ifdef GD_CMP_INTERLACE return GD_CMP_INTERLACE; #else goto not_there; #endif if (strEQ(name, "GD_CMP_TRUECOLOR")) #ifdef GD_CMP_TRUECOLOR return GD_CMP_TRUECOLOR; #else goto not_there; #endif break; case 'H': break; case 'I': break; case 'J': break; case 'K': break; case 'L': break; case 'M': break; case 'N': break; case 'O': break; case 'P': break; case 'Q': break; case 'R': break; case 'S': break; case 'T': break; case 'U': break; case 'V': break; case 'W': break; case 'X': break; case 'Y': break; case 'Z': break; case 'a': break; case 'b': break; case 'c': break; case 'd': break; case 'e': break; case 'f': break; case 'g': if (strEQ(name, "gdBrushed")) #ifdef gdBrushed return gdBrushed; #else goto not_there; #endif if (strEQ(name, "gdDashSize")) #ifdef gdDashSize return gdDashSize; #else goto not_there; #endif if (strEQ(name, "gdMaxColors")) #ifdef gdMaxColors return gdMaxColors; #else goto not_there; #endif if (strEQ(name, "gdStyled")) #ifdef gdStyled return gdStyled; #else goto not_there; #endif if (strEQ(name, "gdStyledBrushed")) #ifdef gdStyledBrushed return gdStyledBrushed; #else goto not_there; #endif if (strEQ(name, "gdTiled")) #ifdef gdTiled return gdTiled; #else goto not_there; #endif if (strEQ(name, "gdTransparent")) #ifdef gdTransparent return gdTransparent; #else goto not_there; #endif if (strEQ(name,"gdAntiAliased")) #ifdef gdAntiAliased return gdAntiAliased; #else goto not_there; #endif if (strEQ(name,"gdAntiAliased")) #ifdef gdAntiAliased return gdAntiAliased; #else goto not_there; #endif if (strEQ(name,"gdArc")) #ifdef gdArc return gdArc; #else goto not_there; #endif if (strEQ(name,"gdPie")) #ifdef gdPie return gdPie; #else goto not_there; #endif if (strEQ(name,"gdChord")) #ifdef gdChord return gdChord; #else goto not_there; #endif if (strEQ(name,"gdNoFill")) #ifdef gdNoFill return gdNoFill; #else goto not_there; #endif if (strEQ(name,"gdEdged")) #ifdef gdEdged return gdEdged; #else goto not_there; #endif if (strEQ(name,"gdAlphaMax")) #ifdef gdAlphaMax return gdAlphaMax; #else goto not_there; #endif if (strEQ(name,"gdAlphaOpaque")) #ifdef gdAlphaOpaque return gdAlphaOpaque; #else goto not_there; #endif if (strEQ(name,"gdAlphaTransparent")) #ifdef gdAlphaTransparent return gdAlphaTransparent; #else goto not_there; #endif break; case 'h': break; case 'i': break; case 'j': break; case 'k': break; case 'l': break; case 'm': break; case 'n': break; case 'o': break; case 'p': break; case 'q': break; case 'r': break; case 's': break; case 't': break; case 'u': break; case 'v': break; case 'w': break; case 'x': break; case 'y': break; case 'z': break; } errno = EINVAL; return 0; not_there: errno = ENOENT; return 0; } typedef gdImagePtr GD__Image; typedef gdFontPtr GD__Font; typedef PerlIO * InputStream; #ifdef PERL_OBJECT # ifdef WIN32 #define GDIMAGECREATEFROMPNG(x) gdImageCreateFromPng((FILE*)x) #define GDIMAGECREATEFROMXBM(x) gdImageCreateFromXbm((FILE*)x) #define GDIMAGECREATEFROMJPEG(x) gdImageCreateFromJpeg((FILE*)x) #define GDIMAGECREATEFROMGIF(x) gdImageCreateFromGif((FILE*)x) #define GDIMAGECREATEFROMWBMP(x) gdImageCreateFromWBMP((FILE*)x) #define GDIMAGECREATEFROMGD(x) gdImageCreateFromGd((FILE*)x) #define GDIMAGECREATEFROMGD2(x) gdImageCreateFromGd2((FILE*)x) #define GDIMAGECREATEFROMGD2PART(x,a,b,c,d) gdImageCreateFromGd2Part((FILE*)x,a,b,c,d) # endif #else # ifdef USE_PERLIO #define GDIMAGECREATEFROMPNG(x) gdImageCreateFromPng(PerlIO_findFILE(x)) #define GDIMAGECREATEFROMXBM(x) gdImageCreateFromXbm(PerlIO_findFILE(x)) #define GDIMAGECREATEFROMJPEG(x) gdImageCreateFromJpeg(PerlIO_findFILE(x)) #define GDIMAGECREATEFROMGIF(x) gdImageCreateFromGif(PerlIO_findFILE(x)) #define GDIMAGECREATEFROMWBMP(x) gdImageCreateFromWBMP(PerlIO_findFILE(x)) #define GDIMAGECREATEFROMGD(x) gdImageCreateFromGd(PerlIO_findFILE(x)) #define GDIMAGECREATEFROMGD2(x) gdImageCreateFromGd2(PerlIO_findFILE(x)) #define GDIMAGECREATEFROMGD2PART(x,a,b,c,d) gdImageCreateFromGd2Part(PerlIO_findFILE(x),a,b,c,d) # else #define GDIMAGECREATEFROMPNG(x) gdImageCreateFromPng(x) #define GDIMAGECREATEFROMXBM(x) gdImageCreateFromXbm(x) #define GDIMAGECREATEFROMJPEG(x) gdImageCreateFromJpeg(x) #define GDIMAGECREATEFROMGIF(x) gdImageCreateFromGif(x) #define GDIMAGECREATEFROMWBMP(x) gdImageCreateFromWBMP(x) #define GDIMAGECREATEFROMGD(x) gdImageCreateFromGd(x) #define GDIMAGECREATEFROMGD2(x) gdImageCreateFromGd2(x) #define GDIMAGECREATEFROMGD2PART(x,a,b,c,d) gdImageCreateFromGd2Part(x,a,b,c,d) # endif #endif #define littleendian(a) \ (a[3]<<24)+(a[2]<<16)+(a[1]<<8)+a[0] /* definitions required to create images from in-memory buffers */ typedef struct bufIOCtx { gdIOCtx ctx; char* data; int length; int pos; } bufIOCtx; typedef struct bufIOCtx *bufIOCtxPtr; static int bufGetC (gdIOCtxPtr ctx) { bufIOCtxPtr bctx = (bufIOCtxPtr) ctx; if (bctx->pos >= bctx->length) return EOF; return bctx->data[bctx->pos]; } static int bufGetBuf (gdIOCtxPtr ctx, void* buf, int len) { bufIOCtxPtr bctx = (bufIOCtxPtr) ctx; int remain,rlen; remain = bctx->length - bctx->pos; if (remain >= len) { rlen = len; } else { if (remain <= 0) return EOF; rlen = remain; } memcpy(buf,(void*)(bctx->data + bctx->pos),rlen); bctx->pos += rlen; return rlen; } static int bufSeek (gdIOCtxPtr ctx, const int pos) { bufIOCtxPtr bctx = (bufIOCtxPtr) ctx; bctx->pos = pos; if (bctx->pos > bctx->length) bctx->pos = bctx->length; return TRUE; } static long bufTell (gdIOCtxPtr ctx) { bufIOCtxPtr bctx = (bufIOCtxPtr) ctx; return bctx->pos; } static void bufFree(gdIOCtxPtr ctx) { Safefree(ctx); } static gdIOCtx* newDynamicCtx (char* data, int length) { bufIOCtxPtr ctx; #ifdef Newz Newz(0,ctx,1,bufIOCtx); #else Newxz(ctx,1,bufIOCtx); #endif if (ctx == NULL) return NULL; ctx->data = data; ctx->pos = 0; ctx->length = length; ctx->ctx.getC = bufGetC; ctx->ctx.getBuf = bufGetBuf; ctx->ctx.seek = bufSeek; ctx->ctx.tell = bufTell; ctx->ctx.gd_free = bufFree; ctx->ctx.putC = NULL; ctx->ctx.putBuf = NULL; return (gdIOCtx*)ctx; } /* helper routines for image transformation */ static GD__Image gd_cloneDim(GD__Image src, int x, int y) { GD__Image dst; if (gdImageTrueColor(src)) { dst = (GD__Image) gdImageCreateTrueColor(x,y); } else { int i; dst = (GD__Image) gdImageCreatePalette(x,y); /* copy across the palette information */ for (i = 0; i < gdMaxColors; i++) { dst->red[i] = src->red[i]; dst->green[i] = src->green[i]; dst->blue[i] = src->blue[i]; dst->alpha[i] = src->alpha[i]; dst->open[i] = src->open[i]; } dst->colorsTotal = src->colorsTotal; dst->transparent = src->transparent; dst->interlace = src->interlace; dst->thick = src->thick; } return(dst); } void get_xformbounds(GD__Image src, int *x, int *y, int *x1, int *y1, int *x2, int *y2) { *x = gdImageSX(src); *y = gdImageSY(src); *x1 = *x - 1; *y1 = *y - 1; *x2 = *x / 2; *y2 = *y / 2; } /* helper macros for image transformations */ #define GDGetImagePixel(im,x,y) \ gdImageTrueColor(im) ? \ gdImageTrueColorPixel(im,x,y) : \ gdImagePalettePixel(im,x,y) #define GDSetImagePixel(im,x,y,p) \ gdImageTrueColor(im) ? \ (gdImageTrueColorPixel(im,x,y) = p) : \ (gdImagePalettePixel(im,x,y) = p) #define GDCopyImagePixel(dst,dx,dy,src,sx,sy) \ gdImageTrueColor(src) ? \ (gdImageTrueColorPixel(dst,dx,dy)=gdImageTrueColorPixel(src,sx,sy)) : \ (gdImagePalettePixel(dst,dx,dy)=gdImagePalettePixel(src,sx,sy)) /* Check the image format being returned */ void gd_chkimagefmt(GD__Image image, int truecolor) { if ((image != NULL) && !truecolor) { /* return a palette image */ if (gdImageTrueColor(image)) { gdImageTrueColorToPalette(image,1,gdMaxColors); } } } /* GLOBAL THREAD-SAFE DATA */ #ifdef START_MY_CXT #define MY_CXT_KEY "GD::_guts" XS_VERSION typedef struct { /* Current image true color default * 0 - create palette based images by default * 1 - create true color images by default */ int truecolor_default; } my_cxt_t; START_MY_CXT #endif MODULE = GD PACKAGE = GD double constant(name) char * name BOOT: { #ifdef START_MY_CXT MY_CXT_INIT; MY_CXT.truecolor_default = 0; #endif } MODULE = GD PACKAGE = GD::Image PREFIX=gd # Set the new image true color default # 0 - create palette based images by default # 1 - create true color images by default int gdtrueColor(packname="GD::Image", ...) char * packname PROTOTYPE: $$ PREINIT: #ifdef START_MY_CXT dMY_CXT; int previous_value = MY_CXT.truecolor_default; #else int previous_value = truecolor_default; #endif CODE: { if (items > 1) #ifdef START_MY_CXT MY_CXT.truecolor_default = (int)SvIV(ST(1)); #else truecolor_default = (int)SvIV(ST(1)); #endif RETVAL = previous_value; } OUTPUT: RETVAL GD::Image gd_new(packname="GD::Image", x=64, y=64, ...) char * packname int x int y PROTOTYPE: $;$$$ PREINIT: #ifdef START_MY_CXT dMY_CXT; int truecolor = MY_CXT.truecolor_default; #else int truecolor = truecolor_default; #endif CODE: { gdImagePtr theImage; if (items > 3) truecolor = (int)SvIV(ST(3)); if (truecolor) { theImage = (GD__Image) gdImageCreateTrueColor(x,y); } else { theImage = (GD__Image) gdImageCreate(x,y); } RETVAL = theImage; } OUTPUT: RETVAL #ifdef HAVE_PNG GD::Image gd_newFromPng(packname="GD::Image", filehandle, ...) char * packname InputStream filehandle PROTOTYPE: $$;$ PREINIT: #ifdef START_MY_CXT dMY_CXT; int truecolor = MY_CXT.truecolor_default; #else int truecolor = truecolor_default; #endif CODE: RETVAL = (GD__Image) GDIMAGECREATEFROMPNG(filehandle); if (items > 2) truecolor = (int)SvIV(ST(2)); gd_chkimagefmt(RETVAL, truecolor); OUTPUT: RETVAL GD::Image gdnewFromPngData(packname="GD::Image", imageData, ...) char * packname SV * imageData PROTOTYPE: $$;$ PREINIT: gdIOCtx* ctx; char* data; STRLEN len; #ifdef START_MY_CXT dMY_CXT; int truecolor = MY_CXT.truecolor_default; #else int truecolor = truecolor_default; #endif CODE: data = SvPV(imageData,len); ctx = newDynamicCtx(data,len); RETVAL = (GD__Image) gdImageCreateFromPngCtx(ctx); (ctx->gd_free)(ctx); if (items > 2) truecolor = (int)SvIV(ST(2)); gd_chkimagefmt(RETVAL, truecolor); OUTPUT: RETVAL #endif GD::Image gdnewFromGdData(packname="GD::Image", imageData) char * packname SV * imageData PROTOTYPE: $$ PREINIT: char* data; STRLEN len; CODE: data = SvPV(imageData,len); RETVAL = (GD__Image) gdImageCreateFromGdPtr(len,(void*) data); OUTPUT: RETVAL GD::Image gdnewFromGd2Data(packname="GD::Image", imageData) char * packname SV * imageData PROTOTYPE: $$ PREINIT: char* data; STRLEN len; CODE: data = SvPV(imageData,len); RETVAL = (GD__Image) gdImageCreateFromGd2Ptr(len,(void*) data); OUTPUT: RETVAL #ifdef HAVE_JPEG GD::Image gdnewFromJpegData(packname="GD::Image", imageData, ...) char * packname SV * imageData PROTOTYPE: $$;$ PREINIT: gdIOCtx* ctx; char* data; STRLEN len; #ifdef START_MY_CXT dMY_CXT; int truecolor = MY_CXT.truecolor_default; #else int truecolor = truecolor_default; #endif CODE: data = SvPV(imageData,len); ctx = newDynamicCtx(data,len); RETVAL = (GD__Image) gdImageCreateFromJpegCtx(ctx); (ctx->gd_free)(ctx); if (items > 2) truecolor = (int)SvIV(ST(2)); gd_chkimagefmt(RETVAL, truecolor); OUTPUT: RETVAL #endif GD::Image gdnewFromWBMPData(packname="GD::Image", imageData, ...) char * packname SV * imageData PROTOTYPE: $$;$ PREINIT: gdIOCtx* ctx; char* data; STRLEN len; #ifdef START_MY_CXT dMY_CXT; int truecolor = MY_CXT.truecolor_default; #else int truecolor = truecolor_default; #endif CODE: data = SvPV(imageData,len); ctx = newDynamicCtx(data,len); RETVAL = (GD__Image) gdImageCreateFromWBMPCtx(ctx); (ctx->gd_free)(ctx); if (items > 2) truecolor = (int)SvIV(ST(2)); gd_chkimagefmt(RETVAL, truecolor); OUTPUT: RETVAL GD::Image gd_newFromXbm(packname="GD::Image", filehandle) char * packname InputStream filehandle PROTOTYPE: $$ CODE: RETVAL = GDIMAGECREATEFROMXBM(filehandle); OUTPUT: RETVAL GD::Image gd_newFromGd(packname="GD::Image", filehandle) char * packname InputStream filehandle PROTOTYPE: $$ CODE: RETVAL = GDIMAGECREATEFROMGD(filehandle); OUTPUT: RETVAL GD::Image gd_newFromGd2(packname="GD::Image", filehandle) char * packname InputStream filehandle PROTOTYPE: $$ CODE: RETVAL = GDIMAGECREATEFROMGD2(filehandle); OUTPUT: RETVAL #ifdef HAVE_JPEG GD::Image gd_newFromJpeg(packname="GD::Image", filehandle, ...) char * packname InputStream filehandle PROTOTYPE: $$;$ PREINIT: #ifdef START_MY_CXT dMY_CXT; int truecolor = MY_CXT.truecolor_default; #else int truecolor = truecolor_default; #endif CODE: RETVAL = GDIMAGECREATEFROMJPEG(filehandle); if (items > 2) truecolor = (int)SvIV(ST(2)); gd_chkimagefmt(RETVAL, truecolor); OUTPUT: RETVAL #endif GD::Image gd_newFromWBMP(packname="GD::Image", filehandle) char * packname InputStream filehandle PROTOTYPE: $$ PREINIT: gdImagePtr img; SV* errormsg; CODE: img = GDIMAGECREATEFROMWBMP(filehandle); if (img == NULL) { errormsg = perl_get_sv("@",0); if (errormsg != NULL) sv_setpv(errormsg,"libgd was not built with WBMP support\n"); XSRETURN_EMPTY; } RETVAL = img; OUTPUT: RETVAL GD::Image gdnewFromXpm(packname="GD::Image", filename) char * packname char * filename PROTOTYPE: $$ PREINIT: gdImagePtr img; SV* errormsg; CODE: #ifdef HAVE_XPM img = (GD__Image) gdImageCreateFromXpm(filename); if (img == NULL) { errormsg = perl_get_sv("@",0); if (errormsg != NULL) sv_setpv(errormsg,"libgd was not built with xpm support\n"); XSRETURN_EMPTY; } RETVAL = img; #else errormsg = perl_get_sv("@",0); sv_setpv(errormsg,"libgd was not built with xpm support\n"); XSRETURN_EMPTY; #endif OUTPUT: RETVAL GD::Image gd_newFromGd2Part(packname="GD::Image", filehandle,srcX,srcY,width,height) char * packname InputStream filehandle int srcX int srcY int width int height PROTOTYPE: $$$$$$ CODE: RETVAL = GDIMAGECREATEFROMGD2PART(filehandle,srcX,srcY,width,height); OUTPUT: RETVAL #ifdef HAVE_GIF GD::Image gd_newFromGif(packname="GD::Image", filehandle) char * packname InputStream filehandle PROTOTYPE: $$;$ PREINIT: #ifdef START_MY_CXT dMY_CXT; int truecolor = MY_CXT.truecolor_default; #else int truecolor = truecolor_default; #endif CODE: RETVAL = GDIMAGECREATEFROMGIF(filehandle); OUTPUT: RETVAL GD::Image gdnewFromGifData(packname="GD::Image", imageData) char * packname SV * imageData PROTOTYPE: $$;$ PREINIT: gdIOCtx* ctx; char* data; STRLEN len; #ifdef START_MY_CXT dMY_CXT; int truecolor = MY_CXT.truecolor_default; #else int truecolor = truecolor_default; #endif CODE: data = SvPV(imageData,len); ctx = newDynamicCtx(data,len); RETVAL = (GD__Image) gdImageCreateFromGifCtx(ctx); (ctx->gd_free)(ctx); OUTPUT: RETVAL #endif void gdDESTROY(image) GD::Image image PROTOTYPE: $ CODE: { gdImageDestroy(image); } SV* gdSTORABLE_freeze(image,cloning) GD::Image image int cloning PROTOTYPE: $$ CODE: { void* data; int size; if (cloning) XSRETURN_UNDEF; data = gdImageGd2Ptr(image,0,GD2_FMT_COMPRESSED,&size); RETVAL=newSVpvn((char*)data,size); gdFree(data); } OUTPUT: RETVAL void gdSTORABLE_thaw(object,cloning,serialized) SV* object int cloning SV* serialized PREINIT: STRLEN length; void* data; GD__Image image; CODE: { if (cloning) XSRETURN_UNDEF; data = (void*) SvPV(serialized,length); image = gdImageCreateFromGd2Ptr(length,data); /* sv_setiv(SvRV(object),(int)image); */ sv_setiv(SvRV(object),(long int)image); } #ifdef HAVE_PNG SV* gdpng(image, ...) GD::Image image PROTOTYPE: $;$ PREINIT: CODE: { void* data; int size; int level; if (items > 1) { level = (int)SvIV(ST(1)); data = (void *) gdImagePngPtrEx(image,&size,level); } else { data = (void *) gdImagePngPtr(image,&size); } RETVAL = newSVpvn((char*) data,size); gdFree(data); } OUTPUT: RETVAL #endif #ifdef HAVE_JPEG SV* gdjpeg(image,quality=-1) GD::Image image int quality PROTOTYPE: $ PREINIT: SV* errormsg; CODE: { void* data; int size; data = (void *) gdImageJpegPtr(image,&size,quality); if (data == NULL) { errormsg = perl_get_sv("@",0); if (errormsg != NULL) sv_setpv(errormsg,"libgd was not built with jpeg support\n"); XSRETURN_EMPTY; } RETVAL = newSVpvn((char*) data,size); gdFree(data); } OUTPUT: RETVAL #endif SV* gdgifanimbegin(image,globalcm=-1,loops=-1) GD::Image image int globalcm int loops PROTOTYPE: $$$ PREINIT: CODE: { void* data; int size; #ifdef HAVE_ANIMGIF data = (void *) gdImageGifAnimBeginPtr(image,&size,globalcm,loops); RETVAL = newSVpvn((char*) data,size); gdFree(data); #else die("libgd 2.0.33 or higher required for animated GIF support"); #endif } OUTPUT: RETVAL SV* gdgifanimadd(image,localcm=-1,leftofs=-1,topofs=-1,delay=-1,disposal=-1,previm=0) GD::Image image int localcm int leftofs int topofs int delay int disposal GD::Image previm PROTOTYPE: $$$$$$$ CODE: { void* data; int size; #ifdef HAVE_ANIMGIF data = (void *) gdImageGifAnimAddPtr(image,&size,localcm,leftofs,topofs,delay,disposal,previm); RETVAL = newSVpvn((char*) data,size); gdFree(data); #else die("libgd 2.0.33 or higher required for animated GIF support"); #endif } OUTPUT: RETVAL SV* gdgifanimend(image) GD::Image image PROTOTYPE: $ CODE: { void* data; int size; #ifdef HAVE_ANIMGIF data = (void *) gdImageGifAnimEndPtr(&size); RETVAL = newSVpvn((char*) data,size); gdFree(data); #else die("libgd 2.0.33 or higher required for animated GIF support"); #endif } OUTPUT: RETVAL SV* gdwbmp(image,fg) GD::Image image int fg PROTOTYPE: $ PREINIT: SV* errormsg; CODE: { void* data; int size; data = (void *) gdImageWBMPPtr(image,&size,fg); if (data == NULL) { errormsg = perl_get_sv("@",0); if (errormsg != NULL) sv_setpv(errormsg,"libgd was not built with WBMP support\n"); XSRETURN_EMPTY; } RETVAL = newSVpvn((char*) data,size); gdFree(data); } OUTPUT: RETVAL #ifdef HAVE_GIF SV* gdgif(image) GD::Image image PROTOTYPE: $ PREINIT: SV* errormsg; CODE: { void* data; int size; data = (void *) gdImageGifPtr(image,&size); if (data == NULL) { errormsg = perl_get_sv("@",0); if (errormsg != NULL) sv_setpv(errormsg,"libgd was not built with gif support\n"); XSRETURN_EMPTY; } RETVAL = newSVpvn((char*) data,size); gdFree(data); } OUTPUT: RETVAL #endif SV* gdgd(image) GD::Image image PROTOTYPE: $ CODE: { void* data; int size; data = gdImageGdPtr(image,&size); RETVAL = newSVpvn((char*) data,size); gdFree(data); } OUTPUT: RETVAL SV* gdgd2(image) GD::Image image PROTOTYPE: $ CODE: { void* data; int size; data = gdImageGd2Ptr(image,0,GD2_FMT_COMPRESSED,&size); RETVAL = newSVpvn((char*) data,size); gdFree(data); } OUTPUT: RETVAL int gdtransparent(image, ...) GD::Image image PROTOTYPE: $;$ CODE: { int color; if (items > 1) { color=(int)SvIV(ST(1)); gdImageColorTransparent(image,color); } RETVAL = gdImageGetTransparent(image); } OUTPUT: RETVAL void gdgetBounds(image) GD::Image image PROTOTYPE: $ PPCODE: { int sx,sy; sx = gdImageSX(image); sy = gdImageSY(image); EXTEND(sp,2); PUSHs(sv_2mortal(newSViv(sx))); PUSHs(sv_2mortal(newSViv(sy))); } int gdisTrueColor(image) GD::Image image PROTOTYPE: $ CODE: { RETVAL=gdImageTrueColor(image); } OUTPUT: RETVAL void gdtrueColorToPalette(image, dither=0, colors=gdMaxColors) GD::Image image int dither int colors PROTOTYPE: $;$$ CODE: { gdImageTrueColorToPalette(image,dither,colors); } void gdrgb(image,color) GD::Image image int color PROTOTYPE: $$ PPCODE: { int r,g,b; r = gdImageRed(image,color); g = gdImageGreen(image,color); b = gdImageBlue(image,color); EXTEND(sp,3); PUSHs(sv_2mortal(newSViv(r))); PUSHs(sv_2mortal(newSViv(g))); PUSHs(sv_2mortal(newSViv(b))); } int gdboundsSafe(image,x,y) GD::Image image int x int y PROTOTYPE: $$$ CODE: { RETVAL=gdImageBoundsSafe(image,x,y); if (RETVAL == 0) XSRETURN_UNDEF; } OUTPUT: RETVAL int gdgetPixel(image,x,y) GD::Image image int x int y PROTOTYPE: $$$ CODE: { RETVAL=gdImageGetPixel(image,x,y); } OUTPUT: RETVAL void gdsetPixel(image,x,y,color) GD::Image image int x int y int color PROTOTYPE: $$$$ CODE: { gdImageSetPixel(image,x,y,color); } GD::Image gdcopyRotate90(src) GD::Image src PROTOTYPE: $ CODE: { int x, y, x1, y1, x2, y2, i, j; GD__Image dst; get_xformbounds(src, &x, &y, &x1, &y1, &x2, &y2); dst = (GD__Image) gd_cloneDim(src, y, x); for (j=0;j 1) { if (SvOK(ST(1))) gdImageInterlace(image,1); else gdImageInterlace(image,0); } RETVAL = gdImageGetInterlaced(image); } OUTPUT: RETVAL int compare(image1,image2) GD::Image image1 GD::Image image2 PROTOTYPE: $$ CODE: { RETVAL = gdImageCompare(image1,image2); } OUTPUT: RETVAL void colorDeallocate(image,color) GD::Image image int color PROTOTYPE: $$ CODE: { gdImageColorDeallocate(image,color); } void copy(destination,source,dstX,dstY,srcX,srcY,w,h) GD::Image destination GD::Image source int dstX int dstY int srcX int srcY int w int h PROTOTYPE: $$$$$$$$ CODE: { gdImageCopy(destination,source,dstX,dstY,srcX,srcY,w,h); } void copyResized(destination,source,dstX,dstY,srcX,srcY,destW,destH,srcW,srcH) GD::Image destination GD::Image source int dstX int dstY int srcX int srcY int destW int destH int srcW int srcH PROTOTYPE: $$$$$$$$$$ CODE: { gdImageCopyResized(destination,source,dstX,dstY,srcX,srcY,destW,destH,srcW,srcH); } void copyResampled(destination,source,dstX,dstY,srcX,srcY,destW,destH,srcW,srcH) GD::Image destination GD::Image source int dstX int dstY int srcX int srcY int destW int destH int srcW int srcH PROTOTYPE: $$$$$$$$$$ CODE: { gdImageCopyResampled(destination,source,dstX,dstY,srcX,srcY,destW,destH,srcW,srcH); } void copyMerge(destination,source,dstX,dstY,srcX,srcY,w,h,pct) GD::Image destination GD::Image source int dstX int dstY int srcX int srcY int w int h int pct PROTOTYPE: $$$$$$$$$ CODE: { gdImageCopyMerge(destination,source,dstX,dstY,srcX,srcY,w,h,pct); } void copyMergeGray(destination,source,dstX,dstY,srcX,srcY,w,h,pct) GD::Image destination GD::Image source int dstX int dstY int srcX int srcY int w int h int pct PROTOTYPE: $$$$$$$$$ CODE: { gdImageCopyMergeGray(destination,source,dstX,dstY,srcX,srcY,w,h,pct); } void paletteCopy(destination,source) GD::Image destination GD::Image source PROTOTYPE: $$ CODE: { gdImagePaletteCopy(destination,source); } void gdchar(image,font,x,y,c,color) GD::Image image GD::Font font int x int y char * c int color PROTOTYPE: $$$$$$ CODE: { gdImageChar(image,font,x,y,*c,color); } void gdcharUp(image,font,x,y,c,color) GD::Image image GD::Font font int x int y char * c int color PROTOTYPE: $$$$$$ CODE: { gdImageCharUp(image,font,x,y,*c,color); } void gdstring(image,font,x,y,s,color) GD::Image image GD::Font font int x int y char * s int color PROTOTYPE: $$$$$$ CODE: { gdImageString(image,font,x,y,(unsigned char*)s,color); } void gdstringUp(image,font,x,y,s,color) GD::Image image GD::Font font int x int y char * s int color PROTOTYPE: $$$$$$ CODE: { gdImageStringUp(image,font,x,y,(unsigned char*)s,color); } void gdstringFT(image,fgcolor,fontname,ptsize,angle,x,y,string,...) SV * image int fgcolor char * fontname double ptsize double angle int x int y char * string PROTOTYPE: $$$$$$$$;$ PREINIT: gdImagePtr img; int brect[8]; char *err; char *a; SV* errormsg; HV* hash; SV** value; int i; int hdpi; int vdpi; gdFTStringExtra strex; PPCODE: { #ifndef HAVE_FT errormsg = perl_get_sv("@",0); sv_setpv(errormsg,"libgd was not built with FreeType font support\n"); XSRETURN_EMPTY; #endif if (sv_isobject(image) && sv_derived_from(image, "GD::Image")) { IV tmp = SvIV((SV*)SvRV(image)); img = (gdImagePtr) tmp; } else { img = NULL; } if (items == 9) { /* hashref options at end */ if (SvTYPE(SvRV(ST(8))) != SVt_PVHV) croak ("Usage: $gd->stringFT(image,fgcolor,fontname,ptsize,angle,x,y,string,[{options}])"); hash = (HV*)SvRV(ST(8)); strex.flags = 0; strex.linespacing = 0; strex.charmap = 0; if (value = hv_fetch(hash,"linespacing",strlen("linespacing"),0)) { strex.flags |= gdFTEX_LINESPACE; strex.linespacing = SvNV(*value); } if (value = hv_fetch(hash,"charmap",strlen("charmap"),0)) { strex.flags |= gdFTEX_CHARMAP; if (strEQ(SvPV_nolen(*value),"Unicode")) strex.charmap = gdFTEX_Unicode; else if (strEQ(SvPV_nolen(*value),"Shift_JIS")) strex.charmap = gdFTEX_Shift_JIS; else if (strEQ(SvPV_nolen(*value),"Big5")) strex.charmap = gdFTEX_Big5; else croak("Unknown charmap %s",SvPV_nolen(*value)); } #ifdef VERSION_33 if (value = hv_fetch(hash,"resolution",strlen("resolution"),0)) { strex.flags |= gdFTEX_RESOLUTION; a = SvPV_nolen(*value); if (sscanf(a,"%d,%d",&hdpi,&vdpi) == 2) { strex.hdpi = hdpi; strex.vdpi = vdpi; } } if (value = hv_fetch(hash,"kerning",strlen("kerning"),0)) { if (!SvTRUE(*value)) { strex.flags |= gdFTEX_DISABLE_KERNING; } else strex.flags &= gdFTEX_DISABLE_KERNING; } #endif err = gdImageStringFTEx(img,brect,fgcolor,fontname,ptsize,angle,x,y,string,&strex); } else { err = gdImageStringFT(img,brect,fgcolor,fontname,ptsize,angle,x,y,string); } if (err) { errormsg = perl_get_sv("@",0); if (errormsg != NULL) sv_setpv(errormsg,err); XSRETURN_EMPTY; } else { EXTEND(sp,8); for (i=0;i<8;i++) { PUSHs(sv_2mortal(newSViv(brect[i]))); } } } int gdstringFTCircle(image,cx,cy,radius,textRadius,fillPortion,fontname,points,top,bottom,fgcolor) GD::Image image int cx int cy double radius double textRadius double fillPortion char * fontname double points char * top char * bottom int fgcolor PROTOTYPE: $$$$$$$$$$$ PREINIT: char* err; SV* errormsg; CODE: { #ifdef HAVE_FT #ifdef HAVE_FTCIRCLE fprintf(stderr,"cx=%d,cy=%d,radius=%f,textRadius=%f,fillPortion=%f,fontname=%s,points=%f,top=%s,bottom=%s,fgcolor=%d", cx,cy,radius,textRadius, fillPortion,fontname,points,top,bottom,fgcolor); err = gdImageStringFTCircle(image,cx,cy,radius,textRadius, fillPortion,fontname,points,top,bottom,fgcolor); if (err) { errormsg = perl_get_sv("@",0); if (errormsg != NULL) sv_setpv(errormsg,err); XSRETURN_EMPTY; } else { RETVAL = 1; } #else errormsg = perl_get_sv("@",0); sv_setpv(errormsg,"libgd must be version 2.0.33 or higher to use this function\n"); XSRETURN_EMPTY; #endif #else errormsg = perl_get_sv("@",0); sv_setpv(errormsg,"libgd was not built with FreeType support\n"); XSRETURN_EMPTY; #endif } OUTPUT: RETVAL int gduseFontConfig(image,flag) SV* image int flag PROTOTYPE: $$ PREINIT: SV* errormsg; CODE: { #ifdef HAVE_FONTCONFIG RETVAL = gdFTUseFontConfig(flag); #else errormsg = perl_get_sv("@",0); sv_setpv(errormsg,"libgd was not built with fontconfig support\n"); XSRETURN_EMPTY; #endif } OUTPUT: RETVAL void gdalphaBlending(image,blending) GD::Image image int blending PROTOTYPE: $$ CODE: { gdImageAlphaBlending(image,blending); } void gdsaveAlpha(image,saveAlphaArg) GD::Image image int saveAlphaArg PROTOTYPE: $$ CODE: { gdImageSaveAlpha(image,saveAlphaArg) ; } void gdclip(image,...) GD::Image image PROTOTYPE: $;$$$$ PREINIT: int coords[4]; int i; PPCODE: { if (items == 5) { for (i=0;i<4;i++) coords[i] = (int)SvIV(ST(i+1)); gdImageSetClip(image,coords[0],coords[1],coords[2],coords[3]); } else if (items > 1) /* something weird */ croak("Usage: $gd->clip() or $gd->clip(x1,x2,y1,y2)"); gdImageGetClip(image,&coords[0],&coords[1],&coords[2],&coords[3]); EXTEND(sp,4); for (i=0;i<4;i++) PUSHs(sv_2mortal(newSViv(coords[i]))); } void gdsetAntiAliased(image,color) GD::Image image int color PROTOTYPE: $$ CODE: { gdImageSetAntiAliased(image,color); } void gdsetAntiAliasedDontBlend(image,color,flag=1) GD::Image image int color int flag PROTOTYPE: $$$ CODE: { gdImageSetAntiAliasedDontBlend(image,color,flag); } MODULE = GD PACKAGE = GD::Font PREFIX=gd GD::Font gdload(packname="GD::Font",fontpath) char * packname char * fontpath PROTOTYPE: $$ PREINIT: int fontfile; int datasize; SV* errormsg; char errstr[256]; gdFontPtr font; unsigned char word[4]; char* fontdata; CODE: { fontfile = open(fontpath,O_RDONLY); if (fontfile < 0) { errormsg = perl_get_sv("@",0); snprintf(errstr,256,"could not open font file %s: %s",fontpath,strerror(errno)); sv_setpv(errormsg,errstr); XSRETURN_EMPTY; } font = (gdFontPtr)safemalloc(sizeof(gdFont)); if (font == NULL) croak("safemalloc() returned NULL while trying to allocate font struct.\n"); /* read header from font - note that the file is assumed to be littleendian*/ if (read(fontfile,word,4) < 4) croak("error while reading font file: %s",strerror(errno)); font->nchars = littleendian(word); if (read(fontfile,word,4) < 4) croak("error while reading font file: %s",strerror(errno)); font->offset = littleendian(word); if (read(fontfile,word,4) < 4) croak("error while reading font file: %s",strerror(errno)); font->w = littleendian(word); if (read(fontfile,word,4) < 4) croak("error while reading font file: %s",strerror(errno)); font->h = littleendian(word); datasize = font->nchars * font->w * font->h; fontdata = (char*)safemalloc(datasize); if (fontdata == NULL) croak("safemalloc() returned NULL while trying to allocate font bitmap.\n"); if (read(fontfile,fontdata,datasize) < datasize) croak("error while reading font file: %s",strerror(errno)); font->data = fontdata; close(fontfile); /* please don't leak file descriptors! */ RETVAL = font; } OUTPUT: RETVAL void gdDESTROY(self) GD::Font self PROTOTYPE: $ CODE: { if (self == gdFontGetSmall() || self == gdFontGetLarge() || self == gdFontGetGiant() || self == gdFontGetMediumBold() || self == gdFontGetTiny() ) XSRETURN_EMPTY; safefree(self->data); safefree(self); } GD::Font gdSmall(packname="GD::Font") char * packname PROTOTYPE: $ CODE: { RETVAL = gdFontGetSmall(); } OUTPUT: RETVAL GD::Font gdLarge(packname="GD::Font") char * packname PROTOTYPE: $ CODE: { RETVAL = gdFontGetLarge(); } OUTPUT: RETVAL GD::Font gdGiant(packname="GD::Font") char * packname PROTOTYPE: $ CODE: { RETVAL = gdFontGetGiant(); } OUTPUT: RETVAL GD::Font gdMediumBold(packname="GD::Font") char * packname PROTOTYPE: $ CODE: { RETVAL = gdFontGetMediumBold(); } OUTPUT: RETVAL GD::Font gdTiny(packname="GD::Font") char * packname PROTOTYPE: $ CODE: { RETVAL = gdFontGetTiny(); } OUTPUT: RETVAL int gdnchars(font) GD::Font font PROTOTYPE: $ CODE: { RETVAL = font->nchars; } OUTPUT: RETVAL int gdoffset(font) GD::Font font PROTOTYPE: $ CODE: { RETVAL = font->offset; } OUTPUT: RETVAL int gdwidth(font) GD::Font font PROTOTYPE: $ CODE: { RETVAL = font->w; } OUTPUT: RETVAL int gdheight(font) GD::Font font PROTOTYPE: $ CODE: { RETVAL = font->h; } OUTPUT: RETVAL