/************************************************************* GD.c - Ruby extension library to use Boutell's gd library. Originally written: Yukihiro Matsumoto (matz@ruby-lang.org) Current maintainer: Ryuichi Tamura (tam@kais.kyoto-u.ac.jp) $Date: 2001/05/30 14:06:40 $ $Revision: 1.6.2.3 $ **************************************************************/ #include "ruby.h" #include "rubyio.h" #include "version.h" #include "gd.h" #include "gdfontg.h" /* giant */ #include "gdfontl.h" /* large */ #include "gdfontmb.h" /* medium bold */ #include "gdfonts.h" /* small */ #include "gdfontt.h" /* tiny */ extern VALUE rb_io_binmode(VALUE io); extern gdImagePtr gdImageCreateFromXpm(char* ); static VALUE mGD, cImage, cFont, cPolygon; #ifdef ENABLE_GD_2_0 static VALUE is_truecolor(im) gdImagePtr im; { return im->trueColor ? Qtrue : Qfalse; } #endif /* ENABLE_GD_2_0 */ static void free_img(iptr) gdImagePtr iptr; { if (iptr) { gdImageDestroy(iptr); } } static VALUE img_s_new(klass, w, h) VALUE klass, w, h; { gdImagePtr iptr; if (NUM2INT(w)<0 || NUM2INT(h)<0) rb_raise(rb_eArgError, "Negative width/height not allowed"); iptr = gdImageCreate(NUM2INT(w), NUM2INT(h)); return Data_Wrap_Struct(klass,0,free_img,iptr); } static VALUE img_from_pngfname(klass, fname) VALUE klass, fname; { VALUE f; OpenFile *fptr; gdImagePtr iptr; Check_Type(fname, T_STRING); f = rb_file_open(STR2CSTR(fname), "r"); rb_io_binmode(f); GetOpenFile(f, fptr); rb_io_check_readable(fptr); iptr = gdImageCreateFromPng(fptr->f); if (!iptr) rb_raise(rb_eArgError, "%s is not a valid PNG File", fptr->path); return Data_Wrap_Struct(klass,0,free_img,iptr); } static VALUE img_from_png(klass, f) VALUE klass, f; { OpenFile *fptr; gdImagePtr iptr; Check_Type(f, T_FILE); rb_io_binmode(f); GetOpenFile(f, fptr); rb_io_check_readable(fptr); iptr = gdImageCreateFromPng(fptr->f); if (!iptr) rb_raise(rb_eArgError, "%s is not a valid PNG File", fptr->path); return Data_Wrap_Struct(klass,0,free_img,iptr); } static VALUE img_from_gdfname(klass, fname) VALUE klass, fname; { VALUE f; OpenFile *fptr; gdImagePtr iptr; Check_Type(fname, T_STRING); f = rb_file_open(STR2CSTR(fname), "r"); rb_io_binmode(f); GetOpenFile(f, fptr); rb_io_check_readable(fptr); iptr = gdImageCreateFromGd(fptr->f); if (!iptr) rb_raise(rb_eArgError, "%s is not a valid Gd File", fptr->path); return Data_Wrap_Struct(klass,0,free_img,iptr); } static VALUE img_from_gd(klass, f) VALUE klass, f; { OpenFile *fptr; gdImagePtr iptr; Check_Type(f, T_FILE); rb_io_binmode(f); GetOpenFile(f, fptr); rb_io_check_readable(fptr); iptr = gdImageCreateFromGd(fptr->f); if (!iptr) rb_raise(rb_eArgError, "%s is not a valid Gd File", fptr->path); return Data_Wrap_Struct(klass,0,free_img,iptr); } static VALUE img_from_gd2fname(klass, fname) VALUE klass, fname; { VALUE f; OpenFile *fptr; gdImagePtr iptr; Check_Type(fname, T_STRING); f = rb_file_open(STR2CSTR(fname), "r"); rb_io_binmode(f); GetOpenFile(f, fptr); rb_io_check_readable(fptr); iptr = gdImageCreateFromGd2(fptr->f); if (!iptr) rb_raise(rb_eArgError, "%s is not a valid Gd2 File", fptr->path); return Data_Wrap_Struct(klass,0,free_img,iptr); } static VALUE img_from_gd2(klass, f) VALUE klass, f; { OpenFile *fptr; gdImagePtr iptr; Check_Type(f, T_FILE); rb_io_binmode(f); GetOpenFile(f, fptr); rb_io_check_readable(fptr); iptr = gdImageCreateFromGd2(fptr->f); if (!iptr) rb_raise(rb_eArgError, "%s is not a valid Gd2 File", fptr->path); return Data_Wrap_Struct(klass,0,free_img,iptr); } static VALUE img_from_gd2_partfname(klass, fname, srcx, srcy, w, h) VALUE klass, fname, srcx, srcy, w, h; { VALUE f; OpenFile *fptr; gdImagePtr iptr; Check_Type(fname, T_STRING); f = rb_file_open(STR2CSTR(fname), "r"); rb_io_binmode(f); GetOpenFile(f, fptr); rb_io_check_readable(fptr); iptr = gdImageCreateFromGd2Part(fptr->f, NUM2INT(srcx), NUM2INT(srcy), NUM2INT(w), NUM2INT(h)); if (!iptr) rb_raise(rb_eArgError, "%s is not a valid Gd2 File", fptr->path); return Data_Wrap_Struct(klass,0,free_img,iptr); } static VALUE img_from_gd2_part(klass, f, srcx, srcy, w, h) VALUE klass, f, srcx, srcy, w, h; { OpenFile *fptr; gdImagePtr iptr; Check_Type(f, T_FILE); rb_io_binmode(f); GetOpenFile(f, fptr); rb_io_check_readable(fptr); iptr = gdImageCreateFromGd2Part(fptr->f, NUM2INT(srcx), NUM2INT(srcy), NUM2INT(w), NUM2INT(h)); if (!iptr) rb_raise(rb_eArgError, "%s is not a valid Gd2 File", fptr->path); return Data_Wrap_Struct(klass,0,free_img,iptr); } static VALUE img_from_xbm(klass, f) VALUE klass, f; { OpenFile *fptr; gdImagePtr iptr; Check_Type(f, T_FILE); rb_io_binmode(f); GetOpenFile(f, fptr); rb_io_check_readable(fptr); iptr = gdImageCreateFromXbm(fptr->f); if (!iptr) rb_raise(rb_eArgError, "%s is not a valid Xbm File", fptr->path); return Data_Wrap_Struct(klass,0,free_img,iptr); } static VALUE img_from_xbmfname(klass, fname) VALUE klass, fname; { VALUE f; OpenFile *fptr; gdImagePtr iptr; Check_Type(fname, T_STRING); f = rb_file_open(STR2CSTR(fname), "r"); rb_io_binmode(f); GetOpenFile(f, fptr); rb_io_check_readable(fptr); iptr = gdImageCreateFromXbm(fptr->f); if (!iptr) rb_raise(rb_eArgError, "%s is not a valid Xbm File", fptr->path); return Data_Wrap_Struct(klass,0,free_img,iptr); } #ifdef HAVE_GDIMAGECREATEFROMXPM static VALUE img_from_xpm(klass, f) VALUE klass, f; { OpenFile *fptr; gdImagePtr iptr; Check_Type(f, T_FILE); rb_io_binmode(f); GetOpenFile(f, fptr); rb_io_check_readable(fptr); /* need cast, and the argument is char* type */ iptr = (gdImagePtr)gdImageCreateFromXpm(fptr->path); if (!iptr) rb_raise(rb_eArgError, "%s is not a valid XPM File", fptr->path); return Data_Wrap_Struct(klass,0,free_img,iptr); } static VALUE img_from_xpmfname(klass, fname) VALUE klass, fname; { VALUE f; OpenFile *fptr; gdImagePtr iptr; Check_Type(fname, T_STRING); f = rb_file_open(STR2CSTR(fname), "r"); rb_io_binmode(f); GetOpenFile(f, fptr); rb_io_check_readable(fptr); /* need cast, and the argument is char* type */ iptr = (gdImagePtr)gdImageCreateFromXpm(fptr->path); if (!iptr) rb_raise(rb_eArgError, "%s is not a valid XPM File", fptr->path); return Data_Wrap_Struct(klass,0,free_img,iptr); } #endif #ifdef HAVE_GDIMAGECREATEFROMJPEG static VALUE img_from_jpeg(klass, f) VALUE klass, f; { OpenFile *fptr; gdImagePtr iptr; Check_Type(f, T_FILE); rb_io_binmode(f); GetOpenFile(f, fptr); rb_io_check_readable(fptr); iptr = gdImageCreateFromJpeg(fptr->f); if (!iptr) rb_raise(rb_eArgError, "%s is not a valid Jpeg File", fptr->path); return Data_Wrap_Struct(klass,0,free_img,iptr); } static VALUE img_from_jpegfname(klass, fname) VALUE klass, fname; { VALUE f; OpenFile *fptr; gdImagePtr iptr; Check_Type(fname, T_STRING); f = rb_file_open(STR2CSTR(fname), "r"); rb_io_binmode(f); GetOpenFile(f, fptr); rb_io_check_readable(fptr); iptr = gdImageCreateFromJpeg(fptr->f); if (!iptr) rb_raise(rb_eArgError, "%s is not a valid Jpeg File", fptr->path); return Data_Wrap_Struct(klass,0,free_img,iptr); } #endif static VALUE img_destroy(img) struct RData *img; { if (img->data) { gdImageDestroy((gdImagePtr)img->data); img->data = 0; } return Qnil; } static VALUE hex2triplet(hex) VALUE hex; { VALUE rstr, gstr, bstr; VALUE ret_ary; Check_Type(hex, T_STRING); if (RSTRING(hex)->len != 7) rb_raise(rb_eArgError, "Invalid format: %s", RSTRING(hex)->ptr); rstr = rb_str_new(RSTRING(hex)->ptr + 1, 2); gstr = rb_str_new(RSTRING(hex)->ptr + 3, 2); bstr = rb_str_new(RSTRING(hex)->ptr + 5, 2); ret_ary = rb_ary_new(); rb_ary_push(ret_ary, rb_funcall(rstr, rb_intern("hex"), 0)); rb_ary_push(ret_ary, rb_funcall(gstr, rb_intern("hex"), 0)); rb_ary_push(ret_ary, rb_funcall(bstr, rb_intern("hex"), 0)); return ret_ary; } static VALUE img_color_allocate_tri(img, r, g, b) VALUE img, r, g, b; { gdImagePtr im; int c; Data_Get_Struct(img, gdImage, im); c = gdImageColorAllocate(im, NUM2INT(r), NUM2INT(g), NUM2INT(b)); return INT2FIX(c); } static VALUE img_color_allocate_str(img, rgbstr) VALUE img, rgbstr; { gdImagePtr im; int c; VALUE ary; Data_Get_Struct(img, gdImage, im); ary = hex2triplet(rgbstr); c = gdImageColorAllocate(im, NUM2INT(*(RARRAY(ary)->ptr)), NUM2INT(*(RARRAY(ary)->ptr+1)), NUM2INT(*(RARRAY(ary)->ptr+2))); return INT2FIX(c); } static VALUE img_color_allocate(argc, argv, img) int argc; VALUE *argv; VALUE img; { int i; VALUE rgbstr, r, g, b, retval; if (!(argc == 1 || argc == 3)) rb_raise(rb_eArgError, "Wrong # of arguments (1 or 3 for %d)", argc); switch(TYPE(argv[0])) { case T_STRING: i = rb_scan_args(argc, argv, "10", &rgbstr); retval = img_color_allocate_str(img, rgbstr); break; case T_FIXNUM: i = rb_scan_args(argc, argv, "30", &r, &g, &b); retval = img_color_allocate_tri(img, r, g, b); break; default: rb_raise(rb_eTypeError, "String or Fixnum expected"); break; } return retval; } static VALUE img_color_deallocate(img, color) VALUE img, color; { gdImagePtr im; Data_Get_Struct(img, gdImage, im); gdImageColorDeallocate(im, NUM2INT(color)); return img; } #ifdef HAVE_GDIMAGECOLORRESOLVE static VALUE img_color_resolve_tri(img, r, g, b) VALUE img, r, g, b; { gdImagePtr im; int c; Data_Get_Struct(img, gdImage, im); c = gdImageColorResolve(im, NUM2INT(r), NUM2INT(g), NUM2INT(b)); return INT2FIX(c); } static VALUE img_color_resolve_str(img, rgbstr) VALUE img, rgbstr; { gdImagePtr im; int c; VALUE ary; Data_Get_Struct(img, gdImage, im); ary = hex2triplet(rgbstr); c = gdImageColorResolve(im, NUM2INT(*(RARRAY(ary)->ptr)), NUM2INT(*(RARRAY(ary)->ptr+1)), NUM2INT(*(RARRAY(ary)->ptr+2))); return INT2FIX(c); } static VALUE img_color_resolve(argc, argv, img) int argc; VALUE *argv; VALUE img; { int i; VALUE rgbstr, r, g, b, retval; if (!(argc == 1 || argc == 3)) rb_raise(rb_eArgError, "Wrong # of arguments (1 or 3 for %d)", argc); switch(TYPE(argv[0])) { case T_STRING: i = rb_scan_args(argc, argv, "10", &rgbstr); retval = img_color_resolve_str(img, rgbstr); break; case T_FIXNUM: i = rb_scan_args(argc, argv, "30", &r, &g, &b); retval = img_color_resolve_tri(img, r, g, b); break; default: rb_raise(rb_eTypeError, "String or Fixnum expected"); break; } return retval; } #endif /* HAVE_GDIMAGECOLORRESOLVE */ static VALUE img_color_closest_tri(img, r, g, b) VALUE img, r, g, b; { gdImagePtr im; int c; Data_Get_Struct(img, gdImage, im); c = gdImageColorClosest(im, NUM2INT(r), NUM2INT(g), NUM2INT(b)); return INT2FIX(c); } static VALUE img_color_closest_str(img, rgbstr) VALUE img, rgbstr; { gdImagePtr im; int c; VALUE ary; Data_Get_Struct(img, gdImage, im); ary = hex2triplet(rgbstr); c = gdImageColorClosest(im, NUM2INT(*(RARRAY(ary)->ptr)), NUM2INT(*(RARRAY(ary)->ptr+1)), NUM2INT(*(RARRAY(ary)->ptr+2))); return INT2FIX(c); } static VALUE img_color_closest(argc, argv, img) int argc; VALUE *argv; VALUE img; { int i; VALUE rgbstr, r, g, b, retval; if (!(argc == 1 || argc == 3)) rb_raise(rb_eArgError, "Wrong # of arguments (1 or 3 for %d)", argc); switch(TYPE(argv[0])) { case T_STRING: i = rb_scan_args(argc, argv, "10", &rgbstr); retval = img_color_closest_str(img, rgbstr); break; case T_FIXNUM: i = rb_scan_args(argc, argv, "30", &r, &g, &b); retval = img_color_closest_tri(img, r, g, b); break; default: rb_raise(rb_eTypeError, "String or Fixnum expected"); break; } return retval; } extern int gdImageColorClosestHWB(gdImagePtr, int, int, int); static VALUE img_color_closestHWB_tri(img, r, g, b) VALUE img, r, g, b; { gdImagePtr im; int c; Data_Get_Struct(img, gdImage, im); c = gdImageColorClosestHWB(im, NUM2INT(r), NUM2INT(g), NUM2INT(b)); return INT2FIX(c); } static VALUE img_color_closestHWB_str(img, rgbstr) VALUE img, rgbstr; { gdImagePtr im; int c; VALUE ary; Data_Get_Struct(img, gdImage, im); ary = hex2triplet(rgbstr); c = gdImageColorClosestHWB(im, NUM2INT(*(RARRAY(ary)->ptr)), NUM2INT(*(RARRAY(ary)->ptr+1)), NUM2INT(*(RARRAY(ary)->ptr+2))); return INT2FIX(c); } static VALUE img_color_closestHWB(argc, argv, img) int argc; VALUE *argv; VALUE img; { int i; VALUE rgbstr, r, g, b, retval; if (!(argc == 1 || argc == 3)) rb_raise(rb_eArgError, "Wrong # of arguments (1 or 3 for %d)", argc); switch(TYPE(argv[0])) { case T_STRING: i = rb_scan_args(argc, argv, "10", &rgbstr); retval = img_color_closestHWB_str(img, rgbstr); break; case T_FIXNUM: i = rb_scan_args(argc, argv, "30", &r, &g, &b); retval = img_color_closestHWB_tri(img, r, g, b); break; default: rb_raise(rb_eTypeError, "String or Fixnum expected"); break; } return retval; } static VALUE img_color_exact_tri(img, r, g, b) VALUE img, r, g, b; { gdImagePtr im; int c; Data_Get_Struct(img, gdImage, im); c = gdImageColorExact(im, NUM2INT(r), NUM2INT(g), NUM2INT(b)); return INT2FIX(c); } static VALUE img_color_exact_str(img, rgbstr) VALUE img, rgbstr; { gdImagePtr im; int c; VALUE ary; Data_Get_Struct(img, gdImage, im); ary = hex2triplet(rgbstr); c = gdImageColorExact(im, NUM2INT(*(RARRAY(ary)->ptr)), NUM2INT(*(RARRAY(ary)->ptr+1)), NUM2INT(*(RARRAY(ary)->ptr+2))); return INT2FIX(c); } static VALUE img_color_exact(argc, argv, img) int argc; VALUE *argv; VALUE img; { int i; VALUE rgbstr, r, g, b, retval; if (!(argc == 1 || argc == 3)) rb_raise(rb_eArgError, "Wrong # of arguments (1 or 3 for %d)", argc); switch(TYPE(argv[0])) { case T_STRING: i = rb_scan_args(argc, argv, "10", &rgbstr); retval = img_color_exact_str(img, rgbstr); break; case T_FIXNUM: i = rb_scan_args(argc, argv, "30", &r, &g, &b); retval = img_color_exact_tri(img, r, g, b); break; default: rb_raise(rb_eTypeError, "String or Fixnum expected"); break; } return retval; } static VALUE img_colors_total(img) VALUE img; { gdImagePtr im; int c; Data_Get_Struct(img, gdImage, im); c = gdImageColorsTotal(im); return INT2FIX(c); } static VALUE img_get_pixel(img, x, y) VALUE img, x, y; { gdImagePtr im; int c; Data_Get_Struct(img, gdImage, im); c = gdImageGetPixel(im, NUM2INT(x), NUM2INT(y)); return INT2FIX(c); } static VALUE img_set_pixel(img, x, y, color) VALUE img, x, y, color; { gdImagePtr im; Data_Get_Struct(img, gdImage, im); gdImageSetPixel(im, NUM2INT(x), NUM2INT(y), NUM2INT(color)); return img; } static VALUE img_red(img, idx) VALUE img, idx; { gdImagePtr im; int i,c; Data_Get_Struct(img, gdImage, im); i = NUM2INT(idx); c = gdImageRed(im, i); return INT2FIX(c); } static VALUE img_green(img, idx) VALUE img, idx; { gdImagePtr im; int i,c; Data_Get_Struct(img, gdImage, im); i = NUM2INT(idx); c = gdImageGreen(im, i); return INT2FIX(c); } static VALUE img_blue(img, idx) VALUE img, idx; { gdImagePtr im; int i,c; Data_Get_Struct(img, gdImage, im); i = NUM2INT(idx); c = gdImageBlue(im, i); return INT2FIX(c); } static VALUE img_rgb(img, idx) VALUE img, idx; { gdImagePtr im; VALUE ary = rb_ary_new2(3); int i, c; Data_Get_Struct(img, gdImage, im); i = NUM2INT(idx); c = gdImageRed(im, i); rb_ary_push(ary, INT2FIX(c)); c = gdImageGreen(im, i); rb_ary_push(ary, INT2FIX(c)); c = gdImageBlue(im, i); rb_ary_push(ary, INT2FIX(c)); return ary; } static VALUE img_transparent(img, idx) VALUE img, idx; { gdImagePtr im; Data_Get_Struct(img, gdImage, im); gdImageColorTransparent(im, NUM2INT(idx)); return img; } static void image_req(img) VALUE img; { if (!rb_obj_is_kind_of(img, cImage)) { rb_raise(rb_eTypeError, "GD::Image required"); } } static VALUE img_set_blush(img, brush) VALUE img, brush; { gdImagePtr im, br; Data_Get_Struct(img, gdImage, im); image_req(brush); Data_Get_Struct(brush, gdImage, br); gdImageSetBrush(im, br); return img; } static VALUE img_set_style(argc, argv, img) int argc; VALUE *argv; VALUE img; { gdImagePtr im; int *style; int i; Data_Get_Struct(img, gdImage, im); style = ALLOCA_N(int, argc); for (i=0; ilen/2; pnt = ALLOCA_N(gdPoint, len); for (i=0; iptr[i*2]); pnt[i].y = NUM2INT(ply->ptr[i*2+1]); } gdImagePolygon(im, pnt, len, NUM2INT(c)); return img; } static VALUE img_filled_polygon(img, ply, c) VALUE img; struct RArray *ply; VALUE c; { gdImagePtr im; gdPointPtr pnt; int i, len; Data_Get_Struct(img, gdImage, im); poly_req(ply); len = ply->len/2; pnt = ALLOCA_N(gdPoint, len); for (i=0; iptr[i*2]); pnt[i].y = NUM2INT(ply->ptr[i*2+1]); } gdImageFilledPolygon(im, pnt, len, NUM2INT(c)); return img; } static VALUE img_arc(img, cx, cy, w, h, s, e, c) VALUE img, cx, cy, w, h, s, e, c; { gdImagePtr im; Data_Get_Struct(img, gdImage, im); gdImageArc(im,NUM2INT(cx),NUM2INT(cy),NUM2INT(w),NUM2INT(h),NUM2INT(s),NUM2INT(e),NUM2INT(c)); return img; } static VALUE img_fill(img, x, y, c) VALUE img, x, y, c; { gdImagePtr im; Data_Get_Struct(img, gdImage, im); gdImageFill(im,NUM2INT(x),NUM2INT(y),NUM2INT(c)); return img; } static VALUE img_fill_to_border(img, x, y, b, c) VALUE img, x, y, b, c; { gdImagePtr im; Data_Get_Struct(img, gdImage, im); gdImageFillToBorder(im,NUM2INT(x),NUM2INT(y),NUM2INT(b),NUM2INT(c)); return img; } static VALUE img_copy(img, img2, dx, dy, sx, sy, w, h) VALUE img, img2, dx, dy, sx, sy, w, h; { gdImagePtr im, im2; Data_Get_Struct(img, gdImage, im); image_req(img2); Data_Get_Struct(img2, gdImage, im2); #ifdef ENABLE_GD_2_0 if (is_truecolor(im) && (!is_truecolor(im2))){ rb_raise(rb_eRuntimeError, "Copying truecolor image to palette image is not permitted"); } #endif gdImageCopy(im2, im, NUM2INT(dx), NUM2INT(dy), NUM2INT(sx), NUM2INT(sy), NUM2INT(w),NUM2INT(h)); return img; } static VALUE img_copy_resized(img, img2, dx, dy, sx, sy, dw, dh, sw, sh) VALUE img, img2, dx, dy, sx, sy, dw, dh, sw, sh; { gdImagePtr im, im2; Data_Get_Struct(img, gdImage, im); image_req(img2); Data_Get_Struct(img2, gdImage, im2); #ifdef ENABLE_GD_2_0 if (is_truecolor(im) && (!is_truecolor(im2))){ rb_raise(rb_eRuntimeError, "Copying truecolor image to palette image is not permitted"); } #endif gdImageCopyResized(im2,im,NUM2INT(dx),NUM2INT(dy),NUM2INT(sx),NUM2INT(sy),NUM2INT(dw),NUM2INT(dh),NUM2INT(sw),NUM2INT(sh)); return img; } static VALUE img_copy_merge(img, img_dest, dx, dy, sx, sy, w, h, pct) VALUE img, img_dest, dx, dy, sx, sy, w, h, pct; { gdImagePtr im, im_dest; Data_Get_Struct(img, gdImage, im); image_req(img_dest); Data_Get_Struct(img_dest, gdImage, im_dest); #ifdef ENABLE_GD_2_0 if (is_truecolor(im) && (!is_truecolor(im_dest))){ rb_raise(rb_eRuntimeError, "Copying truecolor image to palette image is not permitted"); } #endif gdImageCopyMerge(im_dest,im,NUM2INT(dx),NUM2INT(dy),NUM2INT(sx),NUM2INT(sy),NUM2INT(w),NUM2INT(h), NUM2INT(pct)); return img; } static VALUE img_copy_merge_gray(img, img_dest, dx, dy, sx, sy, w, h, pct) VALUE img, img_dest, dx, dy, sx, sy, w, h, pct; { gdImagePtr im, im_dest; Data_Get_Struct(img, gdImage, im); image_req(img_dest); Data_Get_Struct(img_dest, gdImage, im_dest); #ifdef ENABLE_GD_2_0 if (is_truecolor(im) && (!is_truecolor(im_dest))){ rb_raise(rb_eRuntimeError, "Copying truecolor image to palette image is not permitted"); } #endif gdImageCopyMergeGray(im_dest,im,NUM2INT(dx),NUM2INT(dy),NUM2INT(sx),NUM2INT(sy),NUM2INT(w),NUM2INT(h), NUM2INT(pct)); return img; } static VALUE img_palette_copy(img, img2) VALUE img, img2; { gdImagePtr im, im2; image_req(img2); Data_Get_Struct(img, gdImage, im); Data_Get_Struct(img2, gdImage, im2); gdImagePaletteCopy(im, im2); return img; } static void font_req(fnt) VALUE fnt; { if (!rb_obj_is_kind_of(fnt, cFont)) { rb_raise(rb_eTypeError, "GD::Font required"); } } static VALUE img_string(img, fnt, x, y, str, c) VALUE img, fnt, x, y, str, c; { gdImagePtr im; gdFontPtr f; Check_Type(str, T_STRING); Data_Get_Struct(img, gdImage, im); font_req(fnt); Data_Get_Struct(fnt, gdFont, f); gdImageString(im,f,NUM2INT(x),NUM2INT(y),RSTRING(str)->ptr,NUM2INT(c)); return img; } static VALUE img_string_up(img, fnt, x, y, str, c) VALUE img, fnt, x, y, str, c; { gdImagePtr im; gdFontPtr f; Check_Type(str, T_STRING); Data_Get_Struct(img, gdImage, im); font_req(fnt); Data_Get_Struct(fnt, gdFont, f); gdImageStringUp(im,f,NUM2INT(x),NUM2INT(y),RSTRING(str)->ptr,NUM2INT(c)); return img; } #ifdef HAVE_GDIMAGESTRINGTTF static VALUE img_s_string_ttf(klass, fgcolor, fontname, ptsize, angle, x, y, string) VALUE klass, fgcolor, fontname, ptsize, angle, x, y, string; { int brect[8], i; char *msg; VALUE ary = rb_ary_new2(8); Check_Type(fontname, T_STRING); Check_Type(string, T_STRING); msg = gdImageStringTTF(NULL, &brect[0], NUM2INT(fgcolor), RSTRING(fontname)->ptr, NUM2DBL(ptsize), NUM2DBL(angle), NUM2INT(x), NUM2INT(y), RSTRING(string)->ptr); for (i=0; i<8; i++) { rb_ary_push(ary, INT2FIX(brect[i])); } if (msg) { return rb_ary_new3(2, rb_str_new2(msg), ary); } else { return rb_ary_new3(2, Qnil, ary); } } static VALUE img_string_ttf(img, fgcolor, fontname, ptsize, angle, x, y, string) VALUE img, fgcolor, fontname, ptsize, angle, x, y, string; { gdImagePtr im; int brect[8], i; char *msg; VALUE ary = rb_ary_new2(8); Check_Type(fontname, T_STRING); Check_Type(string, T_STRING); Data_Get_Struct(img, gdImage, im); msg = gdImageStringTTF(im, &brect[0], NUM2INT(fgcolor), RSTRING(fontname)->ptr, NUM2DBL(ptsize), NUM2DBL(angle), NUM2INT(x), NUM2INT(y), RSTRING(string)->ptr); for (i=0; i<8; i++) { rb_ary_push(ary, INT2FIX(brect[i])); } if (msg) { return rb_ary_new3(2, rb_str_new2(msg), ary); } else { return rb_ary_new3(2, Qnil, ary); } } #endif /* HAVE_GDIMAGESTRINGTTF */ #ifdef HAVE_GDIMAGESTRINGFT static VALUE img_s_string_ft(klass, fgcolor, fontname, ptsize, angle, x, y, string) VALUE klass, fgcolor, fontname, ptsize, angle, x, y, string; { int brect[8], i; char *msg; VALUE ary = rb_ary_new2(8); Check_Type(fontname, T_STRING); Check_Type(string, T_STRING); msg = gdImageStringFT(NULL, &brect[0], NUM2INT(fgcolor), RSTRING(fontname)->ptr, NUM2DBL(ptsize), NUM2DBL(angle), NUM2INT(x), NUM2INT(y), RSTRING(string)->ptr); for (i=0; i<8; i++) { rb_ary_push(ary, INT2FIX(brect[i])); } if (msg) { return rb_ary_new3(2, rb_str_new2(msg), ary); } else { return rb_ary_new3(2, Qnil, ary); } } static VALUE img_string_ft(img, fgcolor, fontname, ptsize, angle, x, y, string) VALUE img, fgcolor, fontname, ptsize, angle, x, y, string; { gdImagePtr im; int brect[8], i; char *msg; VALUE ary = rb_ary_new2(8); Check_Type(fontname, T_STRING); Check_Type(string, T_STRING); Data_Get_Struct(img, gdImage, im); msg = gdImageStringFT(im, &brect[0], NUM2INT(fgcolor), RSTRING(fontname)->ptr, NUM2DBL(ptsize), NUM2DBL(angle), NUM2INT(x), NUM2INT(y), RSTRING(string)->ptr); for (i=0; i<8; i++) { rb_ary_push(ary, INT2FIX(brect[i])); } if (msg) { return rb_ary_new3(2, rb_str_new2(msg), ary); } else { return rb_ary_new3(2, Qnil, ary); } } #endif /* HAVE_GDIMAGESTRINGFT */ static VALUE img_char(img, fnt, x, y, ch, c) VALUE img, fnt, x, y, ch, c; { gdImagePtr im; gdFontPtr f; int ci; Data_Get_Struct(img, gdImage, im); font_req(fnt); Data_Get_Struct(fnt, gdFont, f); if (TYPE(ch) == T_STRING) { if (RSTRING(ch)->len != 1) { rb_raise(rb_eArgError, "string must be 1 byte(%d bytes)", RSTRING(ch)->len); } ci = RSTRING(ch)->ptr[0]; } else { ci = NUM2INT(ch); } gdImageChar(im,f,NUM2INT(x),NUM2INT(y),ci,NUM2INT(c)); return img; } static VALUE img_char_up(img, fnt, x, y, ch, c) VALUE img, fnt, x, y, ch, c; { gdImagePtr im; gdFontPtr f; int ci; Data_Get_Struct(img, gdImage, im); font_req(fnt); Data_Get_Struct(fnt, gdFont, f); if (TYPE(ch) == T_STRING) { if (RSTRING(ch)->len != 1) { rb_raise(rb_eArgError, "string must be 1 byte(%d bytes)", RSTRING(ch)->len); } ci = RSTRING(ch)->ptr[0]; } else { ci = NUM2INT(ch); } gdImageCharUp(im,f,NUM2INT(x),NUM2INT(y),ci,NUM2INT(c)); return img; } static VALUE img_get_interlace(img) VALUE img; { gdImagePtr im; Data_Get_Struct(img, gdImage, im); if (gdImageGetInterlaced(im)) { return Qtrue; } return Qfalse; } static VALUE img_set_interlace(img, val) { gdImagePtr im; Data_Get_Struct(img, gdImage, im); gdImageInterlace(im, RTEST(val)); return img; } static VALUE img_bounds(img) VALUE img; { gdImagePtr im; VALUE ary = rb_ary_new2(2); int i; Data_Get_Struct(img, gdImage, im); i = gdImageSX(im); rb_ary_push(ary, INT2FIX(i)); i = gdImageSY(im); rb_ary_push(ary, INT2FIX(i)); return ary; } static VALUE img_bounds_safe(img, x, y) VALUE img, x, y; { gdImagePtr im; Data_Get_Struct(img, gdImage, im); if ( gdImageBoundsSafe(im, NUM2INT(x), NUM2INT(y)) ) { return Qtrue; } else { return Qfalse; } } static VALUE img_get_transparent(img) VALUE img; { gdImagePtr im; Data_Get_Struct(img, gdImage, im); return INT2NUM(gdImageGetTransparent(im)); } static VALUE img_width(img) VALUE img; { gdImagePtr im; int i; Data_Get_Struct(img, gdImage, im); i = gdImageSX(im); return INT2FIX(i); } static VALUE img_height(img) VALUE img; { gdImagePtr im; int i; Data_Get_Struct(img, gdImage, im); i = gdImageSY(im); return INT2FIX(i); } static VALUE img_png(img, out) VALUE img, out; { gdImagePtr im; OpenFile *fptr; FILE *f; Data_Get_Struct(img, gdImage, im); Check_Type(out, T_FILE); rb_io_binmode(out); GetOpenFile(out, fptr); rb_io_check_writable(fptr); f = (fptr->f2) ? fptr->f2 : fptr->f; gdImagePng(im, f); return img; } static VALUE img_png_str(img) VALUE img; { int size; void *ptr; gdImagePtr im; VALUE imageString; Data_Get_Struct(img, gdImage, im); ptr = gdImagePngPtr(im, &size); imageString = rb_str_new(ptr, size); #ifdef ENABLE_GD_2_0 gdFree(ptr); #else free(ptr); #endif return imageString; } static VALUE img_gd(img, out) VALUE img, out; { gdImagePtr im; OpenFile *fptr; FILE *f; Data_Get_Struct(img, gdImage, im); Check_Type(out, T_FILE); rb_io_binmode(out); GetOpenFile(out, fptr); rb_io_check_writable(fptr); f = (fptr->f2) ? fptr->f2 : fptr->f; gdImageGd(im, f); return img; } static VALUE img_gd2(img, out, cs, fmt) VALUE img, out, cs, fmt; { OpenFile *fptr; gdImagePtr im; FILE *f; Check_Type(out, T_FILE); rb_io_binmode(out); GetOpenFile(out, fptr); rb_io_check_writable(fptr); f = (fptr->f2) ? fptr->f2 : fptr->f; Data_Get_Struct(img, gdImage, im); gdImageGd2(im, f, NUM2INT(cs), NUM2INT(fmt)); return img; } #ifdef HAVE_GDIMAGECREATEFROMJPEG static VALUE img_jpeg(img, out, quality) VALUE img, out, quality; { gdImagePtr im; OpenFile *fptr; FILE *f; Data_Get_Struct(img, gdImage, im); Check_Type(out, T_FILE); rb_io_binmode(out); GetOpenFile(out, fptr); rb_io_check_writable(fptr); f = (fptr->f2) ? fptr->f2 : fptr->f; gdImageJpeg(im, f, FIX2INT(quality)); return img; } static VALUE img_jpeg_str(img, quality) VALUE img, quality; { int size; void *ptr; gdImagePtr im; VALUE imageString; Data_Get_Struct(img, gdImage, im); ptr = gdImageJpegPtr(im, &size, FIX2INT(quality)); imageString = rb_str_new(ptr, size); #ifdef ENABLE_GD_2_0 gdFree(ptr); #else free(ptr); #endif return imageString; } #endif static VALUE img_wbmp(img, fg, out) VALUE img, out, fg; { gdImagePtr im; OpenFile *fptr; FILE *f; Data_Get_Struct(img, gdImage, im); Check_Type(out, T_FILE); rb_io_binmode(out); GetOpenFile(out, fptr); rb_io_check_writable(fptr); f = (fptr->f2) ? fptr->f2 : fptr->f; gdImageWBMP(im, FIX2INT(fg), f); return img; } /* * * Poligon * */ static VALUE ply_new(klass) VALUE klass; { VALUE self = rb_ary_new(); RBASIC(self)->klass = klass; return self; } static VALUE ply_add_pt(ply, x, y) VALUE ply, x, y; { /* type check */ NUM2INT(x); NUM2INT(y); rb_ary_push(ply, x); rb_ary_push(ply, y); return ply; } static VALUE ply_to_pt(ply, dx, dy) VALUE ply, dx, dy; { VALUE x, y; /* type check */ NUM2INT(dx); NUM2INT(dy); if (RARRAY(ply)->len > 0) { x = rb_ary_entry(ply, RARRAY(ply)->len - 2); y = rb_ary_entry(ply, RARRAY(ply)->len - 1); rb_ary_push(ply, INT2NUM(NUM2INT(x) + NUM2INT(dx))); rb_ary_push(ply, INT2NUM(NUM2INT(y) + NUM2INT(dy))); } else { ply_add_pt(ply, dx, dy); } return ply; } static VALUE ply_get_pt(ply, idx) VALUE ply, idx; { int i = NUM2INT(idx); if (RARRAY(ply)->len < idx) return Qnil; i *= 2; return rb_assoc_new(rb_ary_entry(ply, i), rb_ary_entry(ply, i+1)); } static VALUE ply_set_pt(ply, idx, x, y) VALUE ply, idx, x, y; { int i = NUM2INT(idx)*2; /* type check */ NUM2INT(x); NUM2INT(y); rb_ary_store(ply, i, x); rb_ary_store(ply, i+1, y); return ply; } static VALUE ply_delete_pt(ply, idx) VALUE ply, idx; { int i = NUM2INT(idx)*2; rb_ary_delete_at(ply, INT2FIX(i)); rb_ary_delete_at(ply, INT2FIX(i+1)); return ply; } static VALUE ply_length(ply) VALUE ply; { return INT2FIX(RARRAY(ply)->len / 2); } static VALUE ply_vertices(ply) struct RArray *ply; { int i; VALUE ary = rb_ary_new2(ply->len/2); for (i = 0; ilen; i+=2) { rb_ary_push(ary, rb_assoc_new(ply->ptr[i], ply->ptr[i+1])); } return ary; } static VALUE ply_bounds(ply) struct RArray *ply; { int i, l, t, r, b; int nx, ny; if (ply->len == 0) { l = t = r = b = 0; } else { l = r = NUM2INT(ply->ptr[0]); t = b = NUM2INT(ply->ptr[1]); } for (i = 2; ilen; i+=2) { nx = NUM2INT(ply->ptr[i]); if (nx < l) l = nx; if (nx > r) r = nx; ny = NUM2INT(ply->ptr[i+1]); if (ny < t) t = ny; if (ny > b) b = ny; } return rb_ary_new3(4, INT2FIX(l), INT2FIX(t), INT2FIX(r), INT2FIX(b)); } static VALUE ply_offset(ply, vx, vy) struct RArray *ply; VALUE vx, vy; { int i, x, y, c; x = NUM2INT(vx); y = NUM2INT(vy); for (i = 0; ilen; i+=2) { c = NUM2INT(ply->ptr[i]) + x; ply->ptr[i] = INT2FIX(c); c = NUM2INT(ply->ptr[i+1]) + y; ply->ptr[i+1] = INT2FIX(c); } return (VALUE)ply; } static VALUE ply_map(argc, argv, ply) int argc; VALUE *argv; struct RArray *ply; { VALUE sl, st, sr, sb, dl, dt, dr, db; int sx, sy, dx, dy; double xmag, ymag; int i, c; i = rb_scan_args(argc,argv,"44",&sl,&st,&sr,&sb, &dl,&dt,&dr,&db); if (i == 4) { int i, l, t, r, b; int nx, ny; if (ply->len == 0) { l = t = r = b = 0; } else { l = r = NUM2INT(ply->ptr[0]); t = b = NUM2INT(ply->ptr[1]); } for (i = 2; ilen; i+=2) { nx = NUM2INT(ply->ptr[i]); if (nx < l) l = nx; if (nx > r) r = nx; ny = NUM2INT(ply->ptr[i+1]); if (ny < t) t = ny; if (ny > b) b = ny; } sx = l; sy = t; dx = NUM2INT(sl); dy = NUM2INT(st); xmag = (double)(NUM2INT(sr) - NUM2INT(sl))/(double)(r - l); ymag = (double)(NUM2INT(sb) - NUM2INT(st))/(double)(b - t); } else if (i == 8) { sx = NUM2INT(sl); sy = NUM2INT(st); dx = NUM2INT(dl); dy = NUM2INT(dt); xmag = (double)(NUM2INT(dr) - NUM2INT(dl))/ (double)(NUM2INT(sr) - NUM2INT(sl)); ymag = (double)(NUM2INT(db) - NUM2INT(dt))/ (double)(NUM2INT(sb) - NUM2INT(st)); } else { rb_raise(rb_eArgError, "wrong # of arguments (%d for 4 or 8)", argc); } for (i = 0; ilen; i+=2) { c = NUM2INT(ply->ptr[i]); c = (c-sx)*xmag+dx; ply->ptr[i] = INT2FIX(c); c = NUM2INT(ply->ptr[i+1]); c = (c-sy)*ymag+dy; ply->ptr[i+1] = INT2FIX(c); } return (VALUE)ply; } static VALUE ply_transform(ply, a, b, c, d, tx, ty) VALUE ply, a, b, c, d, tx, ty; { int i; VALUE x, y; for (i = 0; i < RARRAY(ply)->len / 2; i++) { /* x = rb_ary_entry(ply, i * 2); y = rb_ary_entry(ply, i * 2 + 1);*/ x = RARRAY(ply)->ptr[i * 2]; y = RARRAY(ply)->ptr[i * 2 + 1]; ply_set_pt(ply, INT2NUM(i), INT2NUM(NUM2DBL(a) * NUM2INT(x) + NUM2DBL(c) * NUM2INT(y) + NUM2INT(tx)), INT2NUM(NUM2DBL(b) * NUM2INT(x) + NUM2DBL(d) * NUM2INT(y) + NUM2INT(ty))); } return ply; } static VALUE ply_scale(ply, sx, sy) VALUE ply, sx, sy; { return ply_transform(ply, sx, INT2NUM(0), INT2NUM(0), sy, INT2NUM(0), INT2NUM(0)); } static VALUE fnt_create(fnt) gdFontPtr fnt; { return Data_Wrap_Struct(cFont, 0, 0, fnt); } static VALUE fnt_new(name) char *name; { if (strcmp(name, "Giant") == 0) { return fnt_create(gdFontGiant); } if (strcmp(name, "Large") == 0) { return fnt_create(gdFontLarge); } if (strcmp(name, "Medium") == 0) { return fnt_create(gdFontMediumBold); } if (strcmp(name, "Small") == 0) { return fnt_create(gdFontSmall); } if (strcmp(name, "Tiny") == 0) { return fnt_create(gdFontTiny); } rb_raise(rb_eArgError, "undefined font name `%s'", name); } static VALUE fnt_s_new(obj, name) VALUE obj; struct RString *name; { Check_Type(name, T_STRING); return fnt_new(name->ptr); } static VALUE fnt_nchars(fnt) VALUE fnt; { gdFontPtr fp; Data_Get_Struct(fnt,gdFont,fp); return INT2FIX(fp->nchars); } static VALUE fnt_offset(fnt) VALUE fnt; { gdFontPtr fp; Data_Get_Struct(fnt,gdFont,fp); return INT2FIX(fp->offset); } static VALUE fnt_width(fnt) VALUE fnt; { gdFontPtr fp; Data_Get_Struct(fnt,gdFont,fp); return INT2FIX(fp->w); } static VALUE fnt_height(fnt) VALUE fnt; { gdFontPtr fp; Data_Get_Struct(fnt,gdFont,fp); return INT2FIX(fp->h); } /* * * gd-2.0.x features : experimental * */ #ifdef ENABLE_GD_2_0 static VALUE img_s_new_tc(klass, sx, sy) VALUE klass, sx, sy; { gdImagePtr iptr; if (NUM2INT(sx)<0 || NUM2INT(sy)<0) rb_raise(rb_eArgError, "Negative width/height not allowed"); iptr = gdImageCreateTrueColor(NUM2INT(sx), NUM2INT(sy)); if (!iptr) rb_raise(rb_eRuntimeError, "Unable to allocate the new image"); return Data_Wrap_Struct(klass,0,free_img,iptr); } static VALUE img_color_allocate_alpha_tri(img, r, g, b, a) VALUE img, r, g, b, a; { gdImagePtr im; int c; Data_Get_Struct(img, gdImage, im); c = gdImageColorAllocateAlpha(im, NUM2INT(r), NUM2INT(g), NUM2INT(b), NUM2INT(a)); return INT2NUM(c); } static VALUE img_color_allocate_alpha_str(img, rgbstr, a) VALUE img, rgbstr, a; { gdImagePtr im; int c; VALUE ary; Data_Get_Struct(img, gdImage, im); ary = hex2triplet(rgbstr); c = gdImageColorAllocateAlpha(im, NUM2INT(*(RARRAY(ary)->ptr)), NUM2INT(*(RARRAY(ary)->ptr+1)), NUM2INT(*(RARRAY(ary)->ptr+2)), NUM2INT(a)); return INT2NUM(c); } static VALUE img_color_allocate_alpha(argc, argv, img) int argc; VALUE *argv; VALUE img; { int i; VALUE rgbstr, r, g, b, a, retval; if (!(argc == 2 || argc == 4)) rb_raise(rb_eArgError, "Wrong # of arguments (2 or 4 for %d)", argc); switch(TYPE(argv[0])) { case T_STRING: i = rb_scan_args(argc, argv, "20", &rgbstr, &a); retval = img_color_allocate_alpha_str(img, rgbstr, a); break; case T_FIXNUM: i = rb_scan_args(argc, argv, "40", &r, &g, &b, &a); retval = img_color_allocate_alpha_tri(img, r, g, b, a); break; default: rb_raise(rb_eTypeError, "String or Fixnum expected"); break; } return retval; } static VALUE img_color_resolve_alpha_tri(img, r, g, b, a) VALUE img, r, g, b, a; { gdImagePtr im; int c; Data_Get_Struct(img, gdImage, im); c = gdImageColorResolveAlpha(im, NUM2INT(r), NUM2INT(g), NUM2INT(b), NUM2INT(a)); return INT2NUM(c); } static VALUE img_color_resolve_alpha_str(img, rgbstr, a) VALUE img, rgbstr, a; { gdImagePtr im; int c; VALUE ary; Data_Get_Struct(img, gdImage, im); ary = hex2triplet(rgbstr); c = gdImageColorResolveAlpha(im, NUM2INT(*(RARRAY(ary)->ptr)), NUM2INT(*(RARRAY(ary)->ptr+1)), NUM2INT(*(RARRAY(ary)->ptr+2)), NUM2INT(a)); return INT2NUM(c); } static VALUE img_color_resolve_alpha(argc, argv, img) int argc; VALUE *argv; VALUE img; { int i; VALUE rgbstr, r, g, b, a, retval; if (!(argc == 2 || argc == 4)) rb_raise(rb_eArgError, "Wrong # of arguments (2 or 4 for %d)", argc); switch(TYPE(argv[0])) { case T_STRING: i = rb_scan_args(argc, argv, "20", &rgbstr, &a); retval = img_color_resolve_alpha_str(img, rgbstr, a); break; case T_FIXNUM: i = rb_scan_args(argc, argv, "40", &r, &g, &b, &a); retval = img_color_resolve_alpha_tri(img, r, g, b, a); break; default: rb_raise(rb_eTypeError, "String or Fixnum expected"); break; } return retval; } static VALUE img_color_closest_alpha_tri(img, r, g, b, a) VALUE img, r, g, b, a; { gdImagePtr im; int c; Data_Get_Struct(img, gdImage, im); c = gdImageColorClosestAlpha(im, NUM2INT(r), NUM2INT(g), NUM2INT(b), NUM2INT(a)); return INT2NUM(c); } static VALUE img_color_closest_alpha_str(img, rgbstr, a) VALUE img, rgbstr, a; { gdImagePtr im; int c; VALUE ary; Data_Get_Struct(img, gdImage, im); ary = hex2triplet(rgbstr); c = gdImageColorClosestAlpha(im, NUM2INT(*(RARRAY(ary)->ptr)), NUM2INT(*(RARRAY(ary)->ptr+1)), NUM2INT(*(RARRAY(ary)->ptr+2)), NUM2INT(a)); return INT2NUM(c); } static VALUE img_color_closest_alpha(argc, argv, img) int argc; VALUE *argv; VALUE img; { int i; VALUE rgbstr, r, g, b, a, retval; if (!(argc == 2 || argc == 4)) rb_raise(rb_eArgError, "Wrong # of arguments (2 or 4 for %d)", argc); switch(TYPE(argv[0])) { case T_STRING: i = rb_scan_args(argc, argv, "20", &rgbstr, &a); retval = img_color_closest_alpha_str(img, rgbstr, a); break; case T_FIXNUM: i = rb_scan_args(argc, argv, "40", &r, &g, &b, &a); retval = img_color_closest_alpha_tri(img, r, g, b, a); break; default: rb_raise(rb_eTypeError, "String or Fixnum expected"); break; } return retval; } static VALUE img_color_exact_alpha_tri(img, r, g, b, a) VALUE img, r, g, b, a; { gdImagePtr im; int c; Data_Get_Struct(img, gdImage, im); c = gdImageColorExactAlpha(im, NUM2INT(r), NUM2INT(g), NUM2INT(b), NUM2INT(a)); return INT2NUM(c); } static VALUE img_color_exact_alpha_str(img, rgbstr, a) VALUE img, rgbstr, a; { gdImagePtr im; int c; VALUE ary; Data_Get_Struct(img, gdImage, im); ary = hex2triplet(rgbstr); c = gdImageColorExactAlpha(im, NUM2INT(*(RARRAY(ary)->ptr)), NUM2INT(*(RARRAY(ary)->ptr+1)), NUM2INT(*(RARRAY(ary)->ptr+2)), NUM2INT(a)); return INT2NUM(c); } static VALUE img_color_exact_alpha(argc, argv, img) int argc; VALUE *argv; VALUE img; { int i; VALUE rgbstr, r, g, b, a, retval; if (!(argc == 2 || argc == 4)) rb_raise(rb_eArgError, "Wrong # of arguments (2 or 4 for %d)", argc); switch(TYPE(argv[0])) { case T_STRING: i = rb_scan_args(argc, argv, "20", &rgbstr, &a); retval = img_color_exact_alpha_str(img, rgbstr, a); break; case T_FIXNUM: i = rb_scan_args(argc, argv, "40", &r, &g, &b, &a); retval = img_color_exact_alpha_tri(img, r, g, b, a); break; default: rb_raise(rb_eTypeError, "String or Fixnum expected"); break; } return retval; } static VALUE img_alpha_blending(img, blending_mode) VALUE img, blending_mode; { gdImagePtr im; Data_Get_Struct(img, gdImage, im); gdImageAlphaBlending(im, RTEST(blending_mode)); return img; } static VALUE img_alpha(img, color) VALUE img, color; { gdImagePtr im; Data_Get_Struct(img, gdImage, im); return INT2NUM(gdImageAlpha(im, NUM2INT(color))); } static VALUE img_s_truecolor_str(rgbstr) VALUE rgbstr; { int c; VALUE ary; ary = hex2triplet(rgbstr); c = gdTrueColor(NUM2INT(*(RARRAY(ary)->ptr)), NUM2INT(*(RARRAY(ary)->ptr+1)), NUM2INT(*(RARRAY(ary)->ptr+2))); return INT2NUM(c); } static VALUE img_s_truecolor_tri(r, g, b) VALUE r, g, b; { int c; c = gdTrueColor(NUM2INT(r), NUM2INT(g), NUM2INT(b)); return INT2NUM(c); } static VALUE img_s_truecolor(argc, argv, img) int argc; VALUE *argv; VALUE img; { int i; VALUE rgbstr, r, g, b, retval; if (!(argc == 1 || argc == 3)) rb_raise(rb_eArgError, "Wrong # of arguments (1 or 3 for %d)", argc); switch(TYPE(argv[0])) { case T_STRING: i = rb_scan_args(argc, argv, "10", &rgbstr); retval = img_s_truecolor_str(rgbstr); break; case T_FIXNUM: i = rb_scan_args(argc, argv, "30", &r, &g, &b); retval = img_s_truecolor_tri(r, g, b); break; default: rb_raise(rb_eTypeError, "String or Fixnum expected"); break; } return retval; } static VALUE img_s_truecolor_alpha_str(rgbstr, a) VALUE rgbstr, a; { int c; VALUE ary; ary = hex2triplet(rgbstr); c = gdTrueColorAlpha(NUM2INT(*(RARRAY(ary)->ptr)), NUM2INT(*(RARRAY(ary)->ptr+1)), NUM2INT(*(RARRAY(ary)->ptr+2)), NUM2INT(a)); return INT2NUM(c); } static VALUE img_s_truecolor_alpha_tri(r, g, b, a) VALUE r, g, b, a; { int c; c = gdTrueColorAlpha(NUM2INT(r), NUM2INT(g), NUM2INT(b), NUM2INT(a)); return INT2NUM(c); } static VALUE img_s_truecolor_alpha(argc, argv, img) int argc; VALUE *argv; VALUE img; { int i; VALUE rgbstr, r, g, b, a, retval; if (!(argc == 2 || argc == 4)) rb_raise(rb_eArgError, "Wrong # of arguments (2 or 4 for %d)", argc); switch(TYPE(argv[0])) { case T_STRING: i = rb_scan_args(argc, argv, "20", &rgbstr, &a); retval = img_s_truecolor_alpha_str(rgbstr, a); break; case T_FIXNUM: i = rb_scan_args(argc, argv, "40", &r, &g, &b, &a); retval = img_s_truecolor_alpha_tri(r, g, b, a); break; default: rb_raise(rb_eTypeError, "String or Fixnum expected"); break; } return retval; } static VALUE img_copy_resampled(img, img2, dx, dy, sx, sy, dw, dh, sw, sh) VALUE img, img2, dx, dy, sx, sy, dw, dh, sw, sh; { gdImagePtr im, im2; Data_Get_Struct(img, gdImage, im); image_req(img2); Data_Get_Struct(img2, gdImage, im2); if (is_truecolor(im) && (!is_truecolor(im2))){ rb_raise(rb_eRuntimeError, "Copying truecolor image to palette image is not permitted"); } gdImageCopyResampled(im2, im, NUM2INT(dx), NUM2INT(dy), NUM2INT(sx), NUM2INT(sy), NUM2INT(dw), NUM2INT(dh), NUM2INT(sw), NUM2INT(sh)); return img; } static VALUE img_filled_ellipse(img, cx, cy, w, h, start, end, color) VALUE img, cx, cy, w, h, start, end, color; { gdImagePtr im; Data_Get_Struct(img, gdImage, im); gdImageFilledEllipse(im, NUM2INT(cx), NUM2INT(cy), NUM2INT(w), NUM2INT(h), NUM2INT(color)); return img; } static VALUE img_filled_arc(img, cx, cy, w, h, start, end, color, style) VALUE img, cx, cy, w, h, start, end, color, style; { gdImagePtr im; Data_Get_Struct(img, gdImage, im); gdImageFilledArc(im, NUM2INT(cx), NUM2INT(cy), NUM2INT(w), NUM2INT(h), NUM2INT(start), NUM2INT(end), NUM2INT(color), NUM2INT(style)); return img; } static VALUE img_is_truecolor_image(img) VALUE img; { gdImagePtr im; Data_Get_Struct(img, gdImage, im); return is_truecolor(im); } static VALUE img_is_palette_image(img) VALUE img; { gdImagePtr im; Data_Get_Struct(img, gdImage, im); return is_truecolor(im) ? Qfalse : Qtrue; } static VALUE img_to_palette_image(img, dither_flag, max_colors) VALUE img, dither_flag, max_colors; { gdImagePtr im; Data_Get_Struct(img, gdImage, im); gdImageTrueColorToPalette(im, dither_flag, FIX2INT(max_colors)); return img; } static VALUE img_set_thickness(img, thickness) VALUE img, thickness; { gdImagePtr im; Data_Get_Struct(img, gdImage, im); gdImageSetThickness(im, FIX2INT(thickness)); return img; } #endif /* ENABLE_GD_2_0 */ void Init_GD() { mGD = rb_define_module("GD"); cImage = rb_define_class_under(mGD, "Image", rb_cObject); rb_define_singleton_method(cImage, "new", img_s_new, 2); rb_define_singleton_method(cImage, "newPalette", img_s_new, 2); rb_define_singleton_method(cImage, "newFromPng", img_from_png, 1); rb_define_singleton_method(cImage, "new_from_png", img_from_pngfname, 1); rb_define_singleton_method(cImage, "newFromXbm", img_from_xbm, 1); rb_define_singleton_method(cImage, "new_from_xbm", img_from_xbmfname, 1); rb_define_singleton_method(cImage, "newFromGd", img_from_gd, 1); rb_define_singleton_method(cImage, "new_from_gd", img_from_gdfname, 1); #ifdef HAVE_GDIMAGECREATEFROMXPM rb_define_singleton_method(cImage, "newFromXpm", img_from_xpm, 1); rb_define_singleton_method(cImage, "new_from_xpm", img_from_xpmfname, 1); #endif /* HAVE_GDIMAGECREATEFROMXPM */ rb_define_singleton_method(cImage, "newFromGd2", img_from_gd2, 1); rb_define_singleton_method(cImage, "new_from_gd2", img_from_gd2fname, 1); rb_define_singleton_method(cImage, "newFromGd2Part", img_from_gd2_part, 5); rb_define_singleton_method(cImage, "new_from_gd2_Part", img_from_gd2_partfname, 5); #ifdef HAVE_GDIMAGECREATEFROMJPEG rb_define_singleton_method(cImage, "newFromJpeg", img_from_jpeg, 1); rb_define_singleton_method(cImage, "new_from_jpeg", img_from_jpegfname, 1); #endif /* HAVE_GDIMAGECREATEFROMJPEG */ rb_define_method(cImage, "destroy", img_destroy, 0); rb_define_method(cImage, "colorAllocate", img_color_allocate, -1); rb_define_method(cImage, "colorDeallocate", img_color_deallocate, 1); rb_define_method(cImage, "colorClosest", img_color_closest, -1); rb_define_method(cImage, "colorClosestHWB", img_color_closestHWB, -1); rb_define_method(cImage, "colorExact", img_color_exact, -1); #ifdef HAVE_GDIMAGECOLORRESOLVE rb_define_method(cImage, "colorResolve", img_color_resolve, -1); #endif /* HAVE_GDIMAGECOLORRESOLVE */ rb_define_method(cImage, "colorsTotal", img_colors_total, 0); rb_define_method(cImage, "getPixel", img_get_pixel, 2); rb_define_method(cImage, "red", img_red, 1); rb_define_method(cImage, "green", img_green, 1); rb_define_method(cImage, "blue", img_blue, 1); rb_define_method(cImage, "rgb", img_rgb, 1); rb_define_method(cImage, "transparent", img_transparent, 1); rb_define_method(cImage, "setBrush", img_set_blush, 1); rb_define_const(mGD, "Brushed", INT2FIX(gdBrushed)); rb_define_method(cImage, "setStyle", img_set_style, -1); rb_define_const(mGD, "Styled", INT2FIX(gdStyled)); rb_define_const(mGD, "StyledBrushed", INT2FIX(gdStyledBrushed)); rb_define_method(cImage, "setTile", img_set_tile, 1); rb_define_const(mGD, "Tiled", INT2FIX(gdTiled)); rb_define_const(mGD, "Transparent", INT2FIX(gdTransparent)); rb_define_const(mGD, "GD2_FMT_COMPRESSED", INT2FIX(GD2_FMT_COMPRESSED)); rb_define_const(mGD, "GD2_FMT_RAW", INT2FIX(GD2_FMT_RAW)); rb_define_method(cImage, "setPixel", img_set_pixel, 3); rb_define_method(cImage, "line", img_line, 5); rb_define_method(cImage, "dashedLine", img_dashed_line, 5); rb_define_method(cImage, "rectangle", img_rectangle, 5); rb_define_method(cImage, "filledRectangle", img_filled_rectangle, 5); rb_define_method(cImage, "polygon", img_polygon, 2); rb_define_method(cImage, "filledPolygon", img_filled_polygon, 2); rb_define_method(cImage, "arc", img_arc, 7); rb_define_method(cImage, "fill", img_fill, 3); rb_define_method(cImage, "fillToBorder", img_fill_to_border, 4); rb_define_method(cImage, "line", img_line, 5); rb_define_method(cImage, "copy", img_copy, 7); rb_define_method(cImage, "copyResized", img_copy_resized, 9); rb_define_method(cImage, "copyMerge", img_copy_merge, 8); rb_define_method(cImage, "copyMergeGray", img_copy_merge_gray, 8); rb_define_method(cImage, "paletteCopy", img_palette_copy, 1); rb_define_method(cImage, "string", img_string, 5); rb_define_method(cImage, "stringUp", img_string_up, 5); #ifdef HAVE_GDIMAGESTRINGTTF rb_define_singleton_method(cImage, "stringTTF", img_s_string_ttf, 7); rb_define_method(cImage, "stringTTF", img_string_ttf, 7); #endif #ifdef HAVE_GDIMAGESTRINGFT rb_define_singleton_method(cImage, "stringFT", img_s_string_ft, 7); rb_define_method(cImage, "stringFT", img_string_ft, 7); #endif rb_define_method(cImage, "char", img_char, 5); rb_define_method(cImage, "charUp", img_char_up, 5); rb_define_method(cImage, "interlace", img_get_interlace, 0); rb_define_method(cImage, "interlace=", img_set_interlace, 1); rb_define_method(cImage, "getTransparent", img_get_transparent, 0); rb_define_method(cImage, "bounds", img_bounds, 0); rb_define_method(cImage, "boundsSafe", img_bounds_safe, 2); rb_define_method(cImage, "width", img_width, 0); rb_define_method(cImage, "height", img_height, 0); rb_define_method(cImage, "png", img_png, 1); rb_define_method(cImage, "pngStr", img_png_str, 0); rb_define_method(cImage, "gd2", img_gd2, 3); rb_define_method(cImage, "gd", img_gd, 1); #ifdef HAVE_GDIMAGECREATEFROMJPEG rb_define_method(cImage, "jpeg", img_jpeg, 2); rb_define_method(cImage, "jpegStr", img_jpeg_str, 1); #endif /* HAVE_GDIMAGECREATEFROMJPEG */ rb_define_method(cImage, "wbmp", img_wbmp, 2); cPolygon = rb_define_class_under(mGD, "Polygon", rb_cObject); rb_define_singleton_method(cPolygon, "new", ply_new, 0); rb_define_method(cPolygon, "addPt", ply_add_pt, 2); rb_define_method(cPolygon, "toPt", ply_to_pt, 2); rb_define_method(cPolygon, "getPt", ply_get_pt, 1); rb_define_method(cPolygon, "setPt", ply_set_pt, 3); rb_define_method(cPolygon, "deletePt", ply_delete_pt, 1); rb_define_method(cPolygon, "length", ply_length, 0); rb_define_method(cPolygon, "vertices", ply_vertices, 0); rb_define_method(cPolygon, "bounds", ply_bounds, 0); rb_define_method(cPolygon, "offset", ply_offset, 2); rb_define_method(cPolygon, "map", ply_map, -1); rb_define_method(cPolygon, "transform", ply_transform, 6); rb_define_method(cPolygon, "scale", ply_scale, 2); cFont = rb_define_class_under(mGD, "Font", rb_cObject); rb_define_singleton_method(cFont, "new", fnt_s_new, 1); rb_define_const(cFont, "GiantFont", fnt_new("Giant")); rb_define_const(cFont, "SmallFont", fnt_new("Small")); rb_define_const(cFont, "LargeFont", fnt_new("Large")); rb_define_const(cFont, "MediumFont", fnt_new("Medium")); rb_define_const(cFont, "MediumBoldFont", fnt_new("Medium")); rb_define_const(cFont, "TinyFont", fnt_new("Tiny")); rb_define_method(cFont, "nchars", fnt_nchars, 0); rb_define_method(cFont, "offset", fnt_offset, 0); rb_define_method(cFont, "width", fnt_width, 0); rb_define_method(cFont, "height", fnt_height, 0); #ifdef ENABLE_GD_2_0 rb_define_singleton_method(cImage, "newTrueColor", img_s_new_tc, 2); rb_define_method(cImage, "colorAllocateAlpha", img_color_allocate_alpha, -1); rb_define_method(cImage, "colorResolveAlpha", img_color_resolve_alpha, -1); rb_define_method(cImage, "colorClosestAlpha", img_color_closest_alpha, -1); rb_define_method(cImage, "colorExactAlpha", img_color_exact_alpha, -1); rb_define_method(cImage, "alphaBlending=", img_alpha_blending, 1); rb_define_method(cImage, "alpha", img_alpha, 1); rb_define_singleton_method(cImage, "trueColor", img_s_truecolor, -1); rb_define_singleton_method(cImage, "trueColorAlpha", img_s_truecolor_alpha, -1); rb_define_method(cImage, "copyResampled", img_copy_resampled, 9); rb_define_method(cImage, "filledEllipse", img_filled_ellipse, 7); rb_define_method(cImage, "filledArc", img_filled_arc, 8); rb_define_method(cImage, "is_trueColor?", img_is_truecolor_image, 0); rb_define_method(cImage, "is_palette?", img_is_palette_image, 0); rb_define_method(cImage, "to_paletteImage", img_to_palette_image, 2); rb_define_method(cImage, "thickness=", img_set_thickness, 1); rb_define_const(mGD, "AlphaTransparent", INT2FIX(gdAlphaTransparent)); rb_define_const(mGD, "AlphaOpaque", INT2FIX(gdAlphaOpaque)); rb_define_const(mGD, "Arc", INT2FIX(gdArc)); rb_define_const(mGD, "Chord", INT2FIX(gdChord)); rb_define_const(mGD, "Pie", INT2FIX(gdPie)); rb_define_const(mGD, "NoFill", INT2FIX(gdNoFill)); rb_define_const(mGD, "Edged", INT2FIX(gdEdged)); #endif /* ENABLE_GD_2_0 */ }