#include "config.h" #include #include #include #if GIMP_MAJOR_VERSION>1 || (GIMP_MAJOR_VERSION==1 && GIMP_MINOR_VERSION>=1) # define GIMP11 1 # define GIMP_PARASITE 1 #endif /* FIXME */ /* sys/param.h is redefining these! */ #undef MIN #undef MAX #if HAVE_PDL #define PDL_clean_namespace #include #undef croak #define croak Perl_croak #endif /* various functions allocate static buffers, STILL. */ #define MAX_STRING 4096 /* dunno where this comes from */ #undef VOIDUSED #include "EXTERN.h" #include "perl.h" #include "XSUB.h" #include "gppport.h" #ifndef pTHX_ #define pTHX_ #endif #include "../perl-intl.h" /* dirty is used in gimp.h AND in perl < 5.005 or with PERL_POLLUTE. */ #ifdef dirty # undef dirty #endif #include "extradefs.h" #define GIMP_PKG "Gimp::" /* the package name */ #define PKG_COLOR GIMP_PKG "Color" #define PKG_REGION GIMP_PKG "Region" #define PKG_DISPLAY GIMP_PKG "Display" #define PKG_IMAGE GIMP_PKG "Image" #define PKG_LAYER GIMP_PKG "Layer" #define PKG_CHANNEL GIMP_PKG "Channel" #define PKG_DRAWABLE GIMP_PKG "Drawable" #define PKG_SELECTION GIMP_PKG "Selection" #define PKG_REGION GIMP_PKG "Region" #if GIMP_PARASITE # define PKG_PARASITE GIMP_PKG "Parasite" #else # define PKG_PARASITE ((char *)0) #endif #define PKG_GDRAWABLE GIMP_PKG "GimpDrawable" #define PKG_TILE GIMP_PKG "Tile" #define PKG_PIXELRGN GIMP_PKG "PixelRgn" #define PKG_ANY ((char *)0) static char pkg_anyable[] = PKG_DRAWABLE ", " PKG_LAYER " or " PKG_CHANNEL; #define PKG_ANYABLE (pkg_anyable) static int trace = TRACE_NONE; #if HAVE_PDL typedef GimpPixelRgn GimpPixelRgn_PDL; /* hack, undocumented, argh! */ static Core* PDL; /* Structure hold core C functions */ /* get pointer to PDL structure. */ static void need_pdl (void) { SV *CoreSV; if (!PDL) { /* the perl-server can't be bothered to do this itself! */ perl_require_pv ("PDL::Core"); /* Get pointer to structure of core shared C routines */ CoreSV = perl_get_sv("PDL::SHARE", FALSE); if (!CoreSV) croak("gimp-perl-pixel functions require the PDL::Core module, which was not found"); PDL = (Core*) SvIV(CoreSV); } } static pdl *new_pdl (int a, int b, int c) { pdl *p = PDL->new(); PDL_Long dims[3]; int ndims = 0; if (c > 0) dims[ndims++] = c; if (b > 0) dims[ndims++] = b; if (a > 0) dims[ndims++] = a; PDL->setdims (p, dims, ndims); p->datatype = PDL_B; PDL->allocdata (p); return p; } static void old_pdl (pdl **p, short ndims, int dim0) { PDL->make_physical (*p); PDL->converttype (p, PDL_B, PDL_PERM); if ((*p)->ndims < ndims + (dim0 > 1)) croak (__("dimension mismatch, pdl has dimension %d but at least %d dimensions required"), (*p)->ndims, ndims + (dim0 > 1)); if ((*p)->ndims > ndims + 1) croak (__("dimension mismatch, pdl has dimension %d but at most %d dimensions allowed"), (*p)->ndims, ndims + 1); if ((*p)->ndims > ndims && (*p)->dims[0] != dim0) croak (__("pixel size mismatch, pdl has %d channel pixels but %d channels are required"), (*p)->dims[0], dim0); } static void pixel_rgn_pdl_delete_data (pdl *p, int param) { p->data = 0; } /* please optimize! */ static pdl *redim_pdl (pdl *p, int ndim, int newsize) { pdl *r = PDL->null (); AV *dims, *dimincs; int i; dims = newAV (); dimincs = newAV (); for (i = 0; i < p->ndims; i++) { av_push (dims , newSViv (p->dims [i])); av_push (dimincs, newSViv (p->dimincs[i])); } sv_setiv (*av_fetch (dims, ndim, 0), newsize); PDL->affine_new (p, r, 0, sv_2mortal (newRV_noinc ((SV*)dims)), sv_2mortal (newRV_noinc ((SV*)dimincs))); return r; } #endif /* set when its safe to call gimp functions. */ static int gimp_is_initialized = 0; typedef gint32 IMAGE; typedef gint32 LAYER; typedef gint32 CHANNEL; typedef gint32 DRAWABLE; typedef gint32 SELECTION; typedef gint32 DISPLAY; typedef gint32 REGION; typedef gint32 COLOR; typedef gpointer GimpPixelRgnIterator; /* new SV with len len. There _must_ be a better way, but newSV doesn't work. */ static SV *newSVn (STRLEN len) { SV *sv = newSVpv ("", 0); (void) SvUPGRADE (sv, SVt_PV); SvGROW (sv, len); SvCUR_set (sv, len); return sv; } static GHashTable *gdrawable_cache; /* magic stuff. literally. */ static int gdrawable_free (pTHX_ SV *obj, MAGIC *mg) { GimpDrawable *gdr = (GimpDrawable *)SvIV(obj); g_hash_table_remove (gdrawable_cache, (gpointer)gdr->id); gimp_drawable_detach (gdr); return 0; } static MGVTBL vtbl_gdrawable = {0, 0, 0, 0, gdrawable_free}; static SV *new_gdrawable (gint32 id) { static HV *stash; SV *sv; if (!gdrawable_cache) gdrawable_cache = g_hash_table_new (g_direct_hash, g_direct_equal); assert (sizeof (gpointer) >= sizeof (id)); if ((sv = (SV*)g_hash_table_lookup (gdrawable_cache, (gpointer)id))) SvREFCNT_inc (sv); else { GimpDrawable *gdr = gimp_drawable_get (id); if (!gdr) croak (__("unable to convert Gimp::Drawable into Gimp::GimpDrawable (id %d)"), id); if (!stash) stash = gv_stashpv (PKG_GDRAWABLE, 1); sv = newSViv ((IV) gdr); sv_magic (sv, 0, '~', 0, 0); mg_find (sv, '~')->mg_virtual = &vtbl_gdrawable; g_hash_table_insert (gdrawable_cache, (gpointer)id, (void *)sv); } return sv_bless (newRV_noinc (sv), stash); } static GimpDrawable *old_gdrawable (SV *sv) { if (!(sv_derived_from (sv, PKG_GDRAWABLE))) croak (__("argument is not of type %s"), PKG_GDRAWABLE); /* the next line lacks any type of checking. */ return (GimpDrawable *)SvIV(SvRV(sv)); } static /* drawable/tile/region stuff. */ SV *new_tile (GimpTile *tile, SV *gdrawable) { static HV *stash; HV *hv = newHV (); hv_store (hv, "_gdrawable" ,10, SvREFCNT_inc (gdrawable) , 0); if (!stash) stash = gv_stashpv (PKG_TILE, 1); return sv_bless (newRV_noinc ((SV*)hv), stash); } static GimpTile *old_tile (SV *sv) { if (!sv_derived_from (sv, PKG_TILE)) croak (__("argument is not of type %s"), PKG_TILE); /* the next line lacks any type of checking. */ return (GimpTile *)SvIV(*(hv_fetch ((HV*)SvRV(sv), "_tile", 5, 0))); } /* magic stuff. literally. */ static int gpixelrgn_free (pTHX_ SV *obj, MAGIC *mg) { /* GimpPixelRgn *pr = (GimpPixelRgn *)SvPV_nolen(obj); */ /* automatically done on detach */ /* if (pr->dirty) gimp_drawable_flush (pr->drawable);*/ return 0; } static MGVTBL vtbl_gpixelrgn = {0, 0, 0, 0, gpixelrgn_free}; /* coerce whatever was given into a gdrawable-sv */ static SV *force_gdrawable (SV *drawable) { if (!(sv_derived_from (drawable, PKG_GDRAWABLE))) { if (sv_derived_from (drawable, PKG_DRAWABLE) || sv_derived_from (drawable, PKG_LAYER) || sv_derived_from (drawable, PKG_CHANNEL)) drawable = sv_2mortal (new_gdrawable (SvIV (SvRV (drawable)))); else croak (__("argument is not of type %s"), PKG_GDRAWABLE); } return drawable; } static SV *new_gpixelrgn (SV *gdrawable, int x, int y, int width, int height, int dirty, int shadow) { static HV *stash; SV *sv = newSVn (sizeof (GimpPixelRgn)); GimpPixelRgn *pr = (GimpPixelRgn *)SvPV_nolen(sv); if (!stash) stash = gv_stashpv (PKG_PIXELRGN, 1); gimp_pixel_rgn_init (pr, old_gdrawable (gdrawable), x, y, width, height, dirty, shadow); sv_magic (sv, SvRV(gdrawable), '~', 0, 0); mg_find (sv, '~')->mg_virtual = &vtbl_gpixelrgn; return sv_bless (newRV_noinc (sv), stash); } static GimpPixelRgn *old_pixelrgn (SV *sv) { if (!sv_derived_from (sv, PKG_PIXELRGN)) croak (__("argument is not of type %s"), PKG_PIXELRGN); return (GimpPixelRgn *)SvPV_nolen(SvRV(sv)); } static GimpPixelRgn *old_pixelrgn_pdl (SV *sv) { #if HAVE_PDL need_pdl (); #endif return old_pixelrgn (sv); } /* tracing stuff. */ static SV *trace_var = 0; static PerlIO *trace_file = 0; /* FIXME: unportable. */ static void trace_init () { if (!trace_file) SvCUR_set (trace_var, 0); } #ifndef __STDC__ #error You need to compile with an ansi-c compiler!!! #error Remove these lines to continue at your own risk! #endif #if __STDC_VERSION__ > 199900 #define trace_printf(...) \ do { \ if (trace_file) PerlIO_printf (trace_file, __VA_ARGS__); \ else sv_catpvf (trace_var, __VA_ARGS__); \ } while(0) #elif __GNUC__ #define trace_printf(frmt,args...) \ do { \ if (trace_file) PerlIO_printf (trace_file, frmt, ## args); \ else sv_catpvf (trace_var, frmt, ## args); \ } while(0) #elif defined(__STDC__) /* sigh */ #include static void trace_printf (char *frmt, ...) { va_list args; char buffer[MAX_STRING]; /* sorry... */ va_start (args, frmt); #ifdef HAVE_VSNPRINTF vsnprintf (buffer, sizeof buffer, frmt, args); #else vsprintf (buffer, frmt, args); #endif if (trace_file) PerlIO_printf (trace_file, "%s", buffer); else sv_catpv (trace_var, buffer); } #endif static int is_array (GimpPDBArgType typ) { return typ == GIMP_PDB_INT32ARRAY || typ == GIMP_PDB_INT16ARRAY || typ == GIMP_PDB_INT8ARRAY || typ == GIMP_PDB_FLOATARRAY || typ == GIMP_PDB_STRINGARRAY; } static int perl_param_count (GimpParam *arg, int count) { GimpParam *end = arg + count; while (arg < end) if (is_array (arg++->type)) count--; return count; } /* * count actual parameter number */ static int perl_paramdef_count (GimpParamDef *arg, int count) { GimpParamDef *end = arg + count; while (arg < end) if (is_array (arg++->type)) count--; return count; } /* horrors! c wasn't designed for this! */ #define dump_printarray(args,index,ctype,datatype,frmt) {\ int j; \ trace_printf ("["); \ if (args[index].data.datatype || !args[index-1].data.d_int32) \ { \ for (j = 0; j < args[index-1].data.d_int32; j++) \ trace_printf (frmt ## "%s", (ctype) args[index].data.datatype[j], \ j < args[index-1].data.d_int32 - 1 ? ", " : ""); \ } \ else \ trace_printf (__("(UNINITIALIZED)")); \ trace_printf ("]"); \ } static void dump_params (int nparams, GimpParam *args, GimpParamDef *params) { static char *ptype[GIMP_PDB_END+1] = { "INT32" , "INT16" , "INT8" , "FLOAT" , "STRING" , "INT32ARRAY" , "INT16ARRAY" , "INT8ARRAY" , "FLOATARRAY" , "STRINGARRAY", "COLOR" , "REGION" , "DISPLAY" , "IMAGE" , "LAYER" , "CHANNEL" , "DRAWABLE" , "SELECTION" , "BOUNDARY" , "PATH" , #if GIMP_PARASITE "PARASITE" , #endif "STATUS" , "END" }; int i; trace_printf ("("); if ((trace & TRACE_DESC) == TRACE_DESC) trace_printf ("\n\t"); for (i = 0; i < nparams; i++) { if ((trace & TRACE_TYPE) == TRACE_TYPE) { if ((unsigned int)params[i].type < GIMP_PDB_END+1) trace_printf ("%s ", ptype[params[i].type]); else trace_printf ("T%d ", params[i].type); } if ((trace & TRACE_NAME) == TRACE_NAME) trace_printf ("%s=", params[i].name); switch (args[i].type) { case GIMP_PDB_INT32: trace_printf ("%d", args[i].data.d_int32); break; case GIMP_PDB_INT16: trace_printf ("%d", args[i].data.d_int16); break; case GIMP_PDB_INT8: trace_printf ("%d", (guint8) args[i].data.d_int8); break; case GIMP_PDB_FLOAT: trace_printf ("%f", args[i].data.d_float); break; case GIMP_PDB_STRING: trace_printf ("\"%s\"", args[i].data.d_string ? args[i].data.d_string : "[null]"); break; case GIMP_PDB_DISPLAY: trace_printf ("%d", args[i].data.d_display); break; case GIMP_PDB_IMAGE: trace_printf ("%d", args[i].data.d_image); break; case GIMP_PDB_LAYER: trace_printf ("%d", args[i].data.d_layer); break; case GIMP_PDB_CHANNEL: trace_printf ("%d", args[i].data.d_channel); break; case GIMP_PDB_DRAWABLE: trace_printf ("%d", args[i].data.d_drawable); break; case GIMP_PDB_SELECTION: trace_printf ("%d", args[i].data.d_selection); break; case GIMP_PDB_BOUNDARY: trace_printf ("%d", args[i].data.d_boundary); break; case GIMP_PDB_PATH: trace_printf ("%d", args[i].data.d_path); break; case GIMP_PDB_STATUS: trace_printf ("%d", args[i].data.d_status); break; case GIMP_PDB_INT32ARRAY: dump_printarray (args, i, gint32, d_int32array, "%d"); break; case GIMP_PDB_INT16ARRAY: dump_printarray (args, i, gint16, d_int16array, "%d"); break; case GIMP_PDB_INT8ARRAY: dump_printarray (args, i, guint8, d_int8array , "%d"); break; case GIMP_PDB_FLOATARRAY: dump_printarray (args, i, gfloat, d_floatarray, "%f"); break; case GIMP_PDB_STRINGARRAY: dump_printarray (args, i, char* , d_stringarray, "'%s'"); break; case GIMP_PDB_COLOR: trace_printf ("[%d,%d,%d]", args[i].data.d_color.red, args[i].data.d_color.green, args[i].data.d_color.blue); break; #if GIMP_PARASITE case GIMP_PDB_PARASITE: { gint32 found = 0; if (args[i].data.d_parasite.name) { trace_printf ("[%s, ", args[i].data.d_parasite.name); if (args[i].data.d_parasite.flags & GIMP_PARASITE_PERSISTENT) { trace_printf ("GIMP_PARASITE_PERSISTENT"); found |= GIMP_PARASITE_PERSISTENT; } if (args[i].data.d_parasite.flags & ~found) { if (found) trace_printf ("|"); trace_printf ("%d", args[i].data.d_parasite.flags & ~found); } trace_printf (__(", %d bytes data]"), args[i].data.d_parasite.size); } else trace_printf (__("[undefined]")); } break; #endif default: trace_printf ("(?%d?)", args[i].type); } if ((trace & TRACE_DESC) == TRACE_DESC) trace_printf ("\t\"%s\"\n\t", params[i].description); else if (i < nparams - 1) trace_printf (", "); } trace_printf (")"); } static int convert_array2paramdef (AV *av, GimpParamDef **res) { int count = 0; GimpParamDef *def = 0; if (av_len (av) >= 0) for(;;) { int idx; for (idx = 0; idx <= av_len (av); idx++) { SV *sv = *av_fetch (av, idx, 0); SV *type = 0; SV *name = 0; SV *help = 0; if (SvROK (sv) && SvTYPE (SvRV (sv)) == SVt_PVAV) { AV *av = (AV *)SvRV(sv); SV **x; if ((x = av_fetch (av, 0, 0))) type = *x; if ((x = av_fetch (av, 1, 0))) name = *x; if ((x = av_fetch (av, 2, 0))) help = *x; } else if (SvIOK(sv)) type = sv; if (type) { if (def) { if (is_array (SvIV (type))) { def->type = GIMP_PDB_INT32; def->name = "array_size"; def->description = "the size of the following array"; def++; } def->type = SvIV (type); def->name = name ? SvPV_nolen (name) : 0; def->description = help ? SvPV_nolen (help) : 0; def++; } else count += 1 + !!is_array (SvIV (type)); } else croak (__("malformed paramdef, expected [PARAM_TYPE,\"NAME\",\"DESCRIPTION\"] or PARAM_TYPE")); } if (def) break; *res = def = g_new (GimpParamDef, count); } else *res = 0; return count; } static SV * newSV_paramdefs (GimpParamDef *p, int n) { int i; AV *av = newAV (); av_extend (av, n-1); for (i=0; itype)); av_store (a, 1, newSVpv (p->name,0)); av_store (a, 2, newSVpv (p->description,0)); p++; av_store (av, i, newRV_noinc ((SV*)a)); } return newRV_noinc ((SV*)av); } static HV * param_stash (GimpPDBArgType type) { static HV *bless_hv[GIMP_PDB_END]; /* initialized to zero */ static char *bless[GIMP_PDB_END] = { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , PKG_COLOR , PKG_REGION , PKG_DISPLAY , PKG_IMAGE , PKG_LAYER , PKG_CHANNEL , PKG_DRAWABLE , PKG_SELECTION , 0 , 0 , #if GIMP_PARASITE PKG_PARASITE, #endif 0 }; if (bless [type] && !bless_hv [type]) bless_hv [type] = gv_stashpv (bless [type], 1); return bless_hv [type]; } /* automatically bless SV into PARAM_type. */ /* for what it's worth, we cache the stashes. */ static SV * autobless (SV *sv, int type) { HV *stash = param_stash (type); if (stash) sv = sv_bless (newRV_noinc (sv), stash); if (stash && !SvOBJECT(SvRV(sv))) croak ("jupp\n"); return sv; } /* return gint32 from object, wether iv or rv. */ static gint32 unbless (SV *sv, char *type, char *croak_str) { if (sv_isobject (sv)) if (type == PKG_ANY || (type == PKG_ANYABLE && (sv_derived_from (sv, PKG_DRAWABLE) || sv_derived_from (sv, PKG_LAYER) || sv_derived_from (sv, PKG_CHANNEL))) || sv_derived_from (sv, type)) { if (SvTYPE (SvRV (sv)) == SVt_PVMG) return SvIV (SvRV (sv)); else strcpy (croak_str, __("only blessed scalars accepted here")); } else sprintf (croak_str, __("argument type %s expected (not %s)"), type, HvNAME(SvSTASH(SvRV(sv)))); else return SvIV (sv); return -1; } static gint32 unbless_croak (SV *sv, char *type) { char croak_str[MAX_STRING]; gint32 r; croak_str[0] = 0; r = unbless (sv, type, croak_str); if (croak_str [0]) croak (croak_str); return r; } static void canonicalize_colour (char *err, SV *sv, GimpParamColor *c) { dSP; ENTER; SAVETMPS; PUSHMARK(SP); XPUSHs (sv); PUTBACK; if (perl_call_pv ("Gimp::canonicalize_colour", G_SCALAR) != 1) croak (__("FATAL: canonicalize_colour did not return a value!")); SPAGAIN; sv = POPs; if (SvROK(sv)) { if (SvTYPE(SvRV(sv)) == SVt_PVAV) { AV *av = (AV *)SvRV(sv); if (av_len(av) == 2) { c->red = SvIV(*av_fetch(av, 0, 0)); c->green = SvIV(*av_fetch(av, 1, 0)); c->blue = SvIV(*av_fetch(av, 2, 0)); } else sprintf (err, __("a color must have three components (array elements)")); } else sprintf (err, __("illegal type for colour specification")); } else sprintf (err, __("unable to grok colour specification")); PUTBACK; FREETMPS; LEAVE; } /* check for common typoes. */ static void check_for_typoe (char *croak_str, char *p) { char b[80]; g_snprintf (b, sizeof b, "%s_MODE", p); if (perl_get_cv (b, 0)) goto gotit; g_snprintf (b, sizeof b, "%s_MASK", p); if (perl_get_cv (b, 0)) goto gotit; g_snprintf (b, sizeof b, "SELECTION_%s", p); if (perl_get_cv (b, 0)) goto gotit; g_snprintf (b, sizeof b, "%s_IMAGE", p); if (perl_get_cv (b, 0)) goto gotit; strcpy (b, "1"); if (strEQ (p, "TRUE" )) goto gotit; strcpy (b, "0"); if (strEQ (p, "FALSE")) goto gotit; return; gotit: sprintf (croak_str, __("Expected an INT32 but got '%s'. Maybe you meant '%s' instead and forgot to 'use strict'"), p, b); } /* check for 'enumeration types', i.e. integer constants. do not allow string constants here, and check for common typoes. */ static int check_int (char *croak_str, SV *sv) { if (SvTYPE (sv) == SVt_PV && !SvIOKp(sv)) { char *p = SvPV_nolen (sv); if (*p && *p != '0' && *p != '1' && *p != '2' && *p != '3' && *p != '4' && *p != '5' && *p != '6' && *p != '7' && *p != '8' && *p != '9' && *p != '-') { sprintf (croak_str, __("Expected an INT32 but got '%s'. Add '*1' if you really intend to pass in a string"), p); check_for_typoe (croak_str, p); return 0; } } return 1; } /* replacement newSVpv with only one argument. */ #define neuSVpv(arg) ((arg) ? newSVpv((arg),0) : newSVsv (&PL_sv_undef)) /* replacement newSViv which casts to unsigned char. */ #define newSVu8(arg) newSViv((unsigned char)(arg)) /* create sv's using newsv, from the array arg. */ #define push_gimp_av(arg,datatype,newsv,as_ref) { \ int j; \ AV *av; \ if (as_ref) \ av = newAV (); \ else \ { av = 0; EXTEND (SP, arg[-1].data.d_int32); } \ for (j = 0; j < arg[-1].data.d_int32; j++) \ if (as_ref) \ av_push (av, newsv (arg->data.datatype[j])); \ else \ PUSHs (sv_2mortal (newsv (arg->data.datatype[j]))); \ if (as_ref) \ PUSHs (sv_2mortal (newRV_noinc ((SV *)av))); \ } static void push_gimp_sv (GimpParam *arg, int array_as_ref) { dSP; SV *sv = 0; switch (arg->type) { case GIMP_PDB_INT32: sv = newSViv(arg->data.d_int32 ); break; case GIMP_PDB_INT16: sv = newSViv(arg->data.d_int16 ); break; case GIMP_PDB_INT8: sv = newSVu8(arg->data.d_int8 ); break; case GIMP_PDB_FLOAT: sv = newSVnv(arg->data.d_float ); break; case GIMP_PDB_STRING: sv = neuSVpv(arg->data.d_string ); break; case GIMP_PDB_DISPLAY: case GIMP_PDB_IMAGE: case GIMP_PDB_LAYER: case GIMP_PDB_CHANNEL: case GIMP_PDB_DRAWABLE: case GIMP_PDB_SELECTION: case GIMP_PDB_BOUNDARY: case GIMP_PDB_PATH: case GIMP_PDB_STATUS: { int id; switch (arg->type) { case GIMP_PDB_DISPLAY: id = arg->data.d_display; break; case GIMP_PDB_IMAGE: id = arg->data.d_image; break; case GIMP_PDB_LAYER: id = arg->data.d_layer; break; case GIMP_PDB_CHANNEL: id = arg->data.d_channel; break; case GIMP_PDB_DRAWABLE: id = arg->data.d_drawable; break; case GIMP_PDB_SELECTION: id = arg->data.d_selection; break; case GIMP_PDB_BOUNDARY: id = arg->data.d_boundary; break; case GIMP_PDB_PATH: id = arg->data.d_path; break; case GIMP_PDB_STATUS: id = arg->data.d_status; break; default: abort (); } if (id == -1) PUSHs (newSVsv (&PL_sv_undef)); else sv = newSViv (id); } break; case GIMP_PDB_COLOR: { /* difficult */ AV *av = newAV (); av_push (av, newSViv (arg->data.d_color.red)); av_push (av, newSViv (arg->data.d_color.green)); av_push (av, newSViv (arg->data.d_color.blue)); sv = (SV *)av; /* no newRV_inc, since we're getting autoblessed! */ } break; #if GIMP_PARASITE case GIMP_PDB_PARASITE: if (arg->data.d_parasite.name) { AV *av = newAV (); av_push (av, neuSVpv (arg->data.d_parasite.name)); av_push (av, newSViv (arg->data.d_parasite.flags)); av_push (av, newSVpv (arg->data.d_parasite.data, arg->data.d_parasite.size)); sv = (SV *)av; } break; #endif /* did I say difficult before???? */ case GIMP_PDB_INT32ARRAY: push_gimp_av (arg, d_int32array , newSViv, array_as_ref); break; case GIMP_PDB_INT16ARRAY: push_gimp_av (arg, d_int16array , newSViv, array_as_ref); break; case GIMP_PDB_INT8ARRAY: push_gimp_av (arg, d_int8array , newSVu8, array_as_ref); break; case GIMP_PDB_FLOATARRAY: push_gimp_av (arg, d_floatarray , newSVnv, array_as_ref); break; case GIMP_PDB_STRINGARRAY: push_gimp_av (arg, d_stringarray, neuSVpv, array_as_ref); break; default: croak (__("dunno how to return param type %d"), arg->type); } if (sv) PUSHs (sv_2mortal (autobless (sv, arg->type))); PUTBACK; } #define SvPv(sv) (SvOK(sv) ? SvPV_nolen(sv) : 0) #define Sv32(sv) unbless ((sv), PKG_ANY, croak_str) #define av2gimp(arg,sv,datatype,type,svxv) { \ if (SvROK (sv) && SvTYPE(SvRV(sv)) == SVt_PVAV) \ { \ int i; \ AV *av = (AV *)SvRV(sv); \ arg[-1].data.d_int32 = av_len (av) + 1; \ arg->data.datatype = g_new (type, av_len (av) + 1); \ for (i = 0; i <= av_len (av); i++) \ arg->data.datatype[i] = svxv (*av_fetch (av, i, 0)); \ } \ else \ { \ sprintf (croak_str, __("perl-arrayref required as datatype for a gimp-array")); \ arg->data.datatype = 0; \ } \ } #define sv2gimp_extract_noref(fun,str) \ fun(sv); \ if (SvROK(sv)) \ sprintf (croak_str, __("Unable to convert a reference to type '%s'"), str); \ break; /* * convert a perl scalar into a GimpParam, return true if * the argument has been consumed. */ static int convert_sv2gimp (char *croak_str, GimpParam *arg, SV *sv) { switch (arg->type) { case GIMP_PDB_INT32: check_int (croak_str, sv); arg->data.d_int32 = sv2gimp_extract_noref (SvIV, "INT32"); case GIMP_PDB_INT16: arg->data.d_int16 = sv2gimp_extract_noref (SvIV, "INT16"); case GIMP_PDB_INT8: arg->data.d_int8 = sv2gimp_extract_noref (SvIV, "INT8"); case GIMP_PDB_FLOAT: arg->data.d_float = sv2gimp_extract_noref (SvNV, "FLOAT"); case GIMP_PDB_STRING: arg->data.d_string = sv2gimp_extract_noref (SvPv, "STRING"); case GIMP_PDB_DISPLAY: case GIMP_PDB_IMAGE: case GIMP_PDB_LAYER: case GIMP_PDB_CHANNEL: case GIMP_PDB_DRAWABLE: case GIMP_PDB_SELECTION: case GIMP_PDB_BOUNDARY: case GIMP_PDB_PATH: case GIMP_PDB_STATUS: if (SvOK(sv)) switch (arg->type) { case GIMP_PDB_DISPLAY: arg->data.d_display = unbless(sv, PKG_DISPLAY , croak_str); break; case GIMP_PDB_LAYER: arg->data.d_layer = unbless(sv, PKG_ANYABLE , croak_str); break; case GIMP_PDB_CHANNEL: arg->data.d_channel = unbless(sv, PKG_ANYABLE , croak_str); break; case GIMP_PDB_DRAWABLE: arg->data.d_drawable = unbless(sv, PKG_ANYABLE , croak_str); break; case GIMP_PDB_SELECTION: arg->data.d_selection = unbless(sv, PKG_SELECTION, croak_str); break; case GIMP_PDB_BOUNDARY: arg->data.d_boundary = sv2gimp_extract_noref (SvIV, "BOUNDARY"); break; case GIMP_PDB_PATH: arg->data.d_path = sv2gimp_extract_noref (SvIV, "PATH"); break; case GIMP_PDB_STATUS: arg->data.d_status = sv2gimp_extract_noref (SvIV, "STATUS"); break; case GIMP_PDB_IMAGE: { if (sv_derived_from (sv, PKG_DRAWABLE)) arg->data.d_image = gimp_drawable_image_id (unbless(sv, PKG_DRAWABLE, croak_str)); else if (sv_derived_from (sv, PKG_LAYER )) arg->data.d_image = gimp_layer_get_image_id (unbless(sv, PKG_LAYER , croak_str)); else if (sv_derived_from (sv, PKG_CHANNEL )) arg->data.d_image = gimp_channel_get_image_id (unbless(sv, PKG_CHANNEL , croak_str)); else if (sv_derived_from (sv, PKG_IMAGE) || !SvROK (sv)) { arg->data.d_image = unbless(sv, PKG_IMAGE , croak_str); break; } else strcpy (croak_str, __("argument incompatible with type IMAGE")); return 0; } default: abort (); } else switch (arg->type) { case GIMP_PDB_DISPLAY: arg->data.d_display = -1; break; case GIMP_PDB_LAYER: arg->data.d_layer = -1; break; case GIMP_PDB_CHANNEL: arg->data.d_channel = -1; break; case GIMP_PDB_DRAWABLE: arg->data.d_drawable = -1; break; case GIMP_PDB_SELECTION: arg->data.d_selection = -1; break; case GIMP_PDB_BOUNDARY: arg->data.d_boundary = -1; break; case GIMP_PDB_PATH: arg->data.d_path = -1; break; case GIMP_PDB_STATUS: arg->data.d_status = -1; break; case GIMP_PDB_IMAGE: arg->data.d_image = -1; return 0; break; default: abort (); } break; case GIMP_PDB_COLOR: canonicalize_colour (croak_str, sv, &arg->data.d_color); break; #if GIMP_PARASITE case GIMP_PDB_PARASITE: if (SvROK(sv)) { if (SvTYPE(SvRV(sv)) == SVt_PVAV) { AV *av = (AV *)SvRV(sv); if (av_len(av) == 2) { STRLEN size; arg->data.d_parasite.name = SvPv(*av_fetch(av, 0, 0)); arg->data.d_parasite.flags = SvIV(*av_fetch(av, 1, 0)); arg->data.d_parasite.data = SvPV(*av_fetch(av, 2, 0), size); arg->data.d_parasite.size = size; } else sprintf (croak_str, __("illegal parasite specification, expected three array members")); } else sprintf (croak_str, __("illegal parasite specification, arrayref expected")); } else sprintf (croak_str, __("illegal parasite specification, reference expected")); break; #endif case GIMP_PDB_INT32ARRAY: av2gimp (arg, sv, d_int32array , gint32 , Sv32); break; case GIMP_PDB_INT16ARRAY: av2gimp (arg, sv, d_int16array , gint16 , SvIV); break; case GIMP_PDB_INT8ARRAY: av2gimp (arg, sv, d_int8array , gint8 , SvIV); break; case GIMP_PDB_FLOATARRAY: av2gimp (arg, sv, d_floatarray , gdouble, SvNV); break; case GIMP_PDB_STRINGARRAY: av2gimp (arg, sv, d_stringarray, gchar *, SvPv); break; default: sprintf (croak_str, __("dunno how to pass arg type %d"), arg->type); } return 1; } /* do not free actual string or parasite data */ static void destroy_params (GimpParam *arg, int count) { int i; for (i = 0; i < count; i++) switch (arg[i].type) { case GIMP_PDB_INT32ARRAY: g_free (arg[i].data.d_int32array); break; case GIMP_PDB_INT16ARRAY: g_free (arg[i].data.d_int16array); break; case GIMP_PDB_INT8ARRAY: g_free (arg[i].data.d_int8array); break; case GIMP_PDB_FLOATARRAY: g_free (arg[i].data.d_floatarray); break; case GIMP_PDB_STRINGARRAY: g_free (arg[i].data.d_stringarray); break; default: ; } g_free (arg); } #ifdef GIMP_HAVE_DESTROY_PARAMDEFS #define destroy_paramdefs gimp_destroy_paramdefs #else static void destroy_paramdefs (GimpParamDef *arg, int count) { int i; for (i = 0; i < count; i++) { g_free (arg[i].name); g_free (arg[i].description); } g_free (arg); } #endif #ifdef GIMP_HAVE_PROCEDURAL_DB_GET_DATA_SIZE #define get_data_size gimp_get_data_size #else static guint32 get_data_size (gchar *id) { GimpParam *return_vals; int nreturn_vals; int length; return_vals = gimp_run_procedure ("gimp_procedural_db_get_data", &nreturn_vals, GIMP_PDB_STRING, id, GIMP_PDB_END); if (return_vals[0].data.d_status == GIMP_PDB_SUCCESS) length = return_vals[1].data.d_int32; else length = 0; gimp_destroy_params (return_vals, nreturn_vals); return length; } #endif static void simple_perl_call (char *function, char *arg1) { dSP; ENTER; SAVETMPS; PUSHMARK (SP); XPUSHs (sv_2mortal (newSVpv (arg1, 0))); PUTBACK; perl_call_pv (function, G_VOID); SPAGAIN; FREETMPS; LEAVE; } #define gimp_die_msg(msg) simple_perl_call ("Gimp::die_msg" , (msg)) #define try_call(cb) simple_perl_call ("Gimp::callback", (cb) ) static void pii_init (void) { try_call ("-init" ); } static void pii_query(void) { try_call ("-query"); } static void pii_quit (void) { try_call ("-quit" ); } static void pii_run(char *name, int nparams, GimpParam *param, int *xnreturn_vals, GimpParam **xreturn_vals) { static GimpParam *return_vals; static int nreturn_vals; dSP; int i, count; char *err_msg = 0; char *proc_blurb; char *proc_help; char *proc_author; char *proc_copyright; char *proc_date; GimpPDBProcType proc_type; int _nparams; GimpParamDef *params; GimpParamDef *return_defs; if (return_vals) /* the libgimp is soooooooo braindamaged. */ { destroy_params (return_vals, nreturn_vals); return_vals = 0; } if (gimp_procedural_db_proc_info (name, &proc_blurb, &proc_help, &proc_author, &proc_copyright, &proc_date, &proc_type, &_nparams, &nreturn_vals, ¶ms, &return_defs) == TRUE) { g_free (proc_blurb); g_free (proc_help); g_free (proc_author); g_free (proc_copyright); g_free (proc_date); destroy_paramdefs (params, _nparams); PUSHMARK(SP); EXTEND (SP, 3); PUSHs (sv_2mortal (newSVpv ("-run", 4))); PUSHs (sv_2mortal (newSVpv (name, 0))); if (nparams) { EXTEND (SP, perl_param_count (param, nparams)); PUTBACK; for (i = 0; i < nparams; i++) { if (i < nparams-1 && is_array (param[i+1].type)) i++; push_gimp_sv (param+i, nparams > 2); } SPAGAIN; } else PUTBACK; count = perl_call_pv ("Gimp::callback", G_EVAL | (nreturn_vals == 0 ? G_VOID : nreturn_vals == 1 ? G_SCALAR : G_ARRAY)); SPAGAIN; if (SvTRUE (ERRSV)) { if (strEQ ("IGNORE THIS MESSAGE\n", SvPV_nolen (ERRSV))) { nreturn_vals = 0; return_vals = g_new (GimpParam, 1); return_vals->type = GIMP_PDB_STATUS; return_vals->data.d_status = GIMP_PDB_SUCCESS; *xnreturn_vals = nreturn_vals+1; *xreturn_vals = return_vals; } else err_msg = g_strdup (SvPV_nolen (ERRSV)); } else { int i; char errmsg [MAX_STRING]; errmsg [0] = 0; return_vals = (GimpParam *) g_new0 (GimpParam, nreturn_vals+1); return_vals->type = GIMP_PDB_STATUS; return_vals->data.d_status = GIMP_PDB_SUCCESS; *xnreturn_vals = nreturn_vals+1; *xreturn_vals = return_vals++; for (i = nreturn_vals; i-- && count; ) { return_vals[i].type = return_defs[i].type; if ((i >= nreturn_vals-1 || !is_array (return_defs[i+1].type)) && convert_sv2gimp (errmsg, &return_vals[i], TOPs)) { --count; (void) POPs; } if (errmsg [0]) { err_msg = g_strdup (errmsg); break; } } if (count && !err_msg) err_msg = g_strdup_printf (__("plug-in returned %d more values than expected"), count); } destroy_paramdefs (return_defs, nreturn_vals); PUTBACK; } else err_msg = g_strdup_printf (__("being called as '%s', but '%s' not registered in the pdb"), name, name); if (err_msg) { gimp_die_msg (err_msg); g_free (err_msg); if (return_vals) destroy_params (*xreturn_vals, nreturn_vals+1); nreturn_vals = 0; return_vals = g_new (GimpParam, 1); return_vals->type = GIMP_PDB_STATUS; return_vals->data.d_status = GIMP_PDB_EXECUTION_ERROR; *xnreturn_vals = nreturn_vals+1; *xreturn_vals = return_vals; } } GimpPlugInInfo PLUG_IN_INFO = { pii_init, pii_quit, pii_query, pii_run }; MODULE = Gimp::Lib PACKAGE = Gimp::Lib PROTOTYPES: ENABLE # # usage: # set_trace (int new_trace_mask); # set_trace (\$variable_to_trace_into); # set_trace (*STDOUT); # I32 set_trace (var) CODE: { SV *sv = ST (0); RETVAL = trace; if (SvROK (sv) || SvTYPE (sv) == SVt_PVGV) { if (trace_var) SvREFCNT_dec (trace_var), trace_var = 0; if (SvTYPE (sv) == SVt_PVGV) /* pray it's a filehandle! */ trace_file = IoOFP (GvIO (sv)); else { trace_file = 0; sv = SvRV (sv); SvREFCNT_inc (sv); (void) SvUPGRADE (sv, SVt_PV); trace_var = sv; } } else trace = SvIV (ST (0)); } OUTPUT: RETVAL SV * _autobless (sv,type) SV * sv gint32 type CODE: RETVAL = autobless (newSVsv (sv), type); OUTPUT: RETVAL PROTOTYPES: DISABLE int gimp_main(...) PREINIT: CODE: SV *sv; if ((sv = perl_get_sv ("Gimp::help", FALSE)) && SvTRUE (sv)) RETVAL = 0; else { char *argv [10]; int argc = 0; if (items == 0) { AV *av = perl_get_av ("ARGV", FALSE); argv [argc++] = SvPV_nolen (perl_get_sv ("0", FALSE)); if (av && av_len (av) < 10-1) { while (argc-1 <= av_len (av)) argv [argc] = SvPV_nolen (*av_fetch (av, argc-1, 0)), argc++; } else croak ("internal error (please report): too many arguments to main"); } else croak (__("arguments to main not yet supported!")); gimp_is_initialized = 1; RETVAL = gimp_main (argc, argv); gimp_is_initialized = 0; /*exit (0);*/ /*D*//* shit, some memory problem here, so just exit */ } OUTPUT: RETVAL PROTOTYPES: ENABLE int initialized() CODE: RETVAL = gimp_is_initialized; OUTPUT: RETVAL int gimp_major_version() CODE: RETVAL = gimp_major_version; OUTPUT: RETVAL int gimp_minor_version() CODE: RETVAL = gimp_minor_version; OUTPUT: RETVAL int gimp_micro_version() CODE: RETVAL = gimp_micro_version; OUTPUT: RETVAL # checks wether a gimp procedure exists int _gimp_procedure_available(proc_name) char * proc_name CODE: { char *proc_blurb; char *proc_help; char *proc_author; char *proc_copyright; char *proc_date; GimpPDBProcType proc_type; int nparams; int nreturn_vals; GimpParamDef *params; GimpParamDef *return_vals; if (!gimp_is_initialized) croak ("_gimp_procedure_available(%s) called without an active connection", proc_name); if (gimp_procedural_db_proc_info (proc_name, &proc_blurb, &proc_help, &proc_author, &proc_copyright, &proc_date, &proc_type, &nparams, &nreturn_vals, ¶ms, &return_vals) == TRUE) { g_free (proc_blurb); g_free (proc_help); g_free (proc_author); g_free (proc_copyright); g_free (proc_date); destroy_paramdefs (params, nparams); destroy_paramdefs (return_vals, nreturn_vals); RETVAL = TRUE; } else RETVAL = FALSE; } OUTPUT: RETVAL #if 0 # checks wether a gimp procedure exists void gimp_procedural_db_proc_info(proc_name) char * proc_name PPCODE: { char *proc_blurb; char *proc_help; char *proc_author; char *proc_copyright; char *proc_date; GimpPDBProcType proc_type; int nparams; int nreturn_vals; GimpParamDef *params; GimpParamDef *return_vals; if (!gimp_is_initialized) croak ("gimp_procedural_db_proc_info called without an active connection"); if (gimp_procedural_db_proc_info (proc_name, &proc_blurb, &proc_help, &proc_author, &proc_copyright, &proc_date, &proc_type, &nparams, &nreturn_vals, ¶ms, &return_vals) == TRUE) { EXTEND (SP,8); PUSHs (newSVpv (proc_blurb,0)); g_free (proc_blurb); PUSHs (newSVpv (proc_help,0)); g_free (proc_help); PUSHs (newSVpv (proc_author,0)); g_free (proc_author); PUSHs (newSVpv (proc_copyright,0)); g_free (proc_copyright); PUSHs (newSVpv (proc_date,0)); g_free (proc_date); PUSHs (newSViv (proc_type)); PUSHs (newSV_paramdefs (params, nparams)); destroy_paramdefs (params, nparams); PUSHs (newSV_paramdefs (return_vals, nreturn_vals));destroy_paramdefs (return_vals, nreturn_vals); } } #endif void gimp_call_procedure (proc_name, ...) char * proc_name PPCODE: { char croak_str[MAX_STRING] = ""; char *proc_blurb; char *proc_help; char *proc_author; char *proc_copyright; char *proc_date; GimpPDBProcType proc_type; int nparams; int nreturn_vals; GimpParam *args = 0; GimpParam *values = 0; int nvalues; GimpParamDef *params; GimpParamDef *return_vals; int i=0, j=0; /* work around bogus warning. */ if (!gimp_is_initialized) croak ("gimp_call_procedure(%s,...) called without an active connection", proc_name); if (trace) trace_init (); if (trace & TRACE_CALL) trace_printf ("%s", proc_name); if (gimp_procedural_db_proc_info (proc_name, &proc_blurb, &proc_help, &proc_author, &proc_copyright, &proc_date, &proc_type, &nparams, &nreturn_vals, ¶ms, &return_vals) == TRUE) { int runmode = nparams && params[0].type == GIMP_PDB_INT32 && !strcmp (params[0].name, "run_mode"); g_free (proc_blurb); g_free (proc_help); g_free (proc_author); g_free (proc_copyright); g_free (proc_date); if (nparams) args = (GimpParam *) g_new0 (GimpParam, nparams); for (i = 0, j = 1; i < nparams && j < items; i++) { args[i].type = params[i].type; if (i == 0 && runmode) { if (sv_isa (ST(j), "Gimp::run_mode")) { args->data.d_int32 = SvIV(SvRV(ST(j))); j++; } else args->data.d_int32 = GIMP_RUN_NONINTERACTIVE; } else if ((!SvROK(ST(j)) || i >= nparams-1 || !is_array (params[i+1].type)) && convert_sv2gimp (croak_str, &args[i], ST(j))) j++; if (croak_str [0]) { if (trace & TRACE_CALL) { dump_params (i, args, params); trace_printf (__(" = [argument error]\n")); } goto error; } } if (trace & TRACE_CALL) { dump_params (i, args, params); trace_printf (" = "); } if (i < nparams || j < items) { if (trace & TRACE_CALL) trace_printf (__("[unfinished]\n")); sprintf (croak_str, __("%s arguments for function '%s'"), i < nparams ? __("not enough") : __("too many"), proc_name); if (nparams) destroy_params (args, nparams); } else { values = gimp_run_procedure2 (proc_name, &nvalues, nparams, args); if (nparams) destroy_params (args, nparams); if (trace & TRACE_CALL) { dump_params (nvalues-1, values+1, return_vals); trace_printf ("\n"); } if (values && values[0].type == GIMP_PDB_STATUS) { if (values[0].data.d_status == GIMP_PDB_EXECUTION_ERROR) sprintf (croak_str, __("%s: procedural database execution failed"), proc_name); else if (values[0].data.d_status == GIMP_PDB_CALLING_ERROR) sprintf (croak_str, __("%s: procedural database execution failed on invalid input arguments"), proc_name); else if (values[0].data.d_status == GIMP_PDB_SUCCESS) { EXTEND(SP, perl_paramdef_count (return_vals, nvalues-1)); PUTBACK; for (i = 0; i < nvalues-1; i++) { if (i < nvalues-2 && is_array (values[i+2].type)) i++; push_gimp_sv (values+i+1, nvalues > 2+1); } SPAGAIN; } else sprintf (croak_str, "unsupported status code: %d, fatal error\n", values[0].data.d_status); } else sprintf (croak_str, "gimp didn't return an execution status, fatal error"); } error: if (values) gimp_destroy_params (values, nreturn_vals); destroy_paramdefs (params, nparams); destroy_paramdefs (return_vals, nreturn_vals); if (croak_str[0]) croak (croak_str); } else croak (__("gimp procedure '%s' not found"), proc_name); } void gimp_install_procedure(name, blurb, help, author, copyright, date, menu_path, image_types, type, params, return_vals) char * name char * blurb char * help char * author char * copyright char * date SV * menu_path SV * image_types int type SV * params SV * return_vals ALIAS: gimp_install_temp_proc = 1 CODE: if (SvROK(params) && SvTYPE(SvRV(params)) == SVt_PVAV && SvROK(return_vals) && SvTYPE(SvRV(return_vals)) == SVt_PVAV) { GimpParamDef *apd; int nparams; GimpParamDef *rpd; int nreturn_vals; nparams = convert_array2paramdef ((AV *)SvRV(params) , &apd); nreturn_vals = convert_array2paramdef ((AV *)SvRV(return_vals), &rpd); if (ix) gimp_install_temp_proc(name,blurb,help,author,copyright,date,SvPv(menu_path),SvPv(image_types), type,nparams,nreturn_vals,apd,rpd,pii_run); else { gimp_plugin_domain_register ("gimp-perl", datadir "/locale"); gimp_install_procedure(name,blurb,help,author,copyright,date,SvPv(menu_path),SvPv(image_types), type,nparams,nreturn_vals,apd,rpd); } g_free (rpd); g_free (apd); } else croak (__("params and return_vals must be array refs (even if empty)!")); void gimp_uninstall_temp_proc(name) char * name void gimp_lib_quit() CODE: gimp_quit (); void gimp_set_data(id, data) SV * id SV * data; CODE: { STRLEN dlen; void *dta; dta = SvPV (data, dlen); gimp_set_data (SvPV_nolen (id), dta, dlen); } void gimp_get_data(id) SV * id; PPCODE: { SV *data; STRLEN dlen; dlen = get_data_size (SvPV_nolen (id)); /* I count on dlen being zero if "id" doesn't exist. */ data = newSVpv ("", 0); gimp_get_data (SvPV_nolen (id), SvGROW (data, dlen+1)); SvCUR_set (data, dlen); *((char *)SvPV_nolen (data) + dlen) = 0; XPUSHs (sv_2mortal (data)); } gdouble gimp_gamma() gint gimp_install_cmap() gint gimp_use_xshm() void gimp_color_cube() PPCODE: { guchar *cc = gimp_color_cube (); EXTEND (SP, 4); PUSHs (sv_2mortal (newSViv (cc [0]))); PUSHs (sv_2mortal (newSViv (cc [1]))); PUSHs (sv_2mortal (newSViv (cc [2]))); PUSHs (sv_2mortal (newSViv (cc [3]))); } char * gimp_gtkrc() #ifdef GIMP11 char * gimp_directory() char * gimp_data_directory() SV * gimp_personal_rc_file(basename) char * basename CODE: basename = gimp_personal_rc_file (basename); RETVAL = sv_2mortal (newSVpv (basename, 0)); g_free (basename); OUTPUT: RETVAL #endif guint gimp_tile_width() guint gimp_tile_height() void gimp_tile_cache_size(kilobytes) gulong kilobytes void gimp_tile_cache_ntiles(ntiles) gulong ntiles SV * gimp_drawable_get(drawable_ID) DRAWABLE drawable_ID CODE: RETVAL = new_gdrawable (drawable_ID); OUTPUT: RETVAL void gimp_drawable_flush(drawable) GimpDrawable * drawable SV * gimp_pixel_rgn_init(gdrawable, x, y, width, height, dirty, shadow) SV * gdrawable int x int y int width int height int dirty int shadow CODE: RETVAL = new_gpixelrgn (force_gdrawable (gdrawable),x,y,width,height,dirty,shadow); OUTPUT: RETVAL void gimp_pixel_rgn_resize(pr, x, y, width, height) GimpPixelRgn * pr int x int y int width int height CODE: gimp_pixel_rgn_resize (pr, x, y, width, height); GimpPixelRgnIterator gimp_pixel_rgns_register(...) CODE: if (items == 1) RETVAL = gimp_pixel_rgns_register (1, old_pixelrgn (ST (0))); else if (items == 2) RETVAL = gimp_pixel_rgns_register (2, old_pixelrgn (ST (0)), old_pixelrgn (ST (1))); else if (items == 3) RETVAL = gimp_pixel_rgns_register (3, old_pixelrgn (ST (0)), old_pixelrgn (ST (1)), old_pixelrgn (ST (2))); else croak (__("gimp_pixel_rgns_register supports only 1, 2 or 3 arguments, upgrade to gimp-1.1 and report this error")); OUTPUT: RETVAL SV * gimp_pixel_rgns_process(pri_ptr) GimpPixelRgnIterator pri_ptr CODE: RETVAL = boolSV (gimp_pixel_rgns_process (pri_ptr)); OUTPUT: RETVAL # struct accessor functions guint gimp_gdrawable_width(gdrawable) GimpDrawable *gdrawable CODE: RETVAL = gdrawable->width; OUTPUT: RETVAL guint gimp_gdrawable_height(gdrawable) GimpDrawable *gdrawable CODE: RETVAL = gdrawable->height; OUTPUT: RETVAL guint gimp_gdrawable_ntile_rows(gdrawable) GimpDrawable *gdrawable CODE: RETVAL = gdrawable->ntile_rows; OUTPUT: RETVAL guint gimp_gdrawable_ntile_cols(gdrawable) GimpDrawable *gdrawable CODE: RETVAL = gdrawable->ntile_cols; OUTPUT: RETVAL guint gimp_gdrawable_bpp(gdrawable) GimpDrawable *gdrawable CODE: RETVAL = gdrawable->bpp; OUTPUT: RETVAL gint32 gimp_gdrawable_id(gdrawable) GimpDrawable *gdrawable CODE: RETVAL = gdrawable->id; OUTPUT: RETVAL guint gimp_pixel_rgn_x(pr) GimpPixelRgn *pr CODE: RETVAL = pr->x; OUTPUT: RETVAL guint gimp_pixel_rgn_y(pr) GimpPixelRgn *pr CODE: RETVAL = pr->y; OUTPUT: RETVAL guint gimp_pixel_rgn_w(pr) GimpPixelRgn *pr CODE: RETVAL = pr->w; OUTPUT: RETVAL guint gimp_pixel_rgn_h(pr) GimpPixelRgn *pr CODE: RETVAL = pr->h; OUTPUT: RETVAL guint gimp_pixel_rgn_rowstride(pr) GimpPixelRgn *pr CODE: RETVAL = pr->rowstride; OUTPUT: RETVAL guint gimp_pixel_rgn_bpp(pr) GimpPixelRgn *pr CODE: RETVAL = pr->bpp; OUTPUT: RETVAL guint gimp_pixel_rgn_shadow(pr) GimpPixelRgn *pr CODE: RETVAL = pr->shadow; OUTPUT: RETVAL gint32 gimp_pixel_rgn_drawable(pr) GimpPixelRgn *pr CODE: RETVAL = pr->drawable->id; OUTPUT: RETVAL guint gimp_tile_ewidth(tile) GimpTile *tile CODE: RETVAL = tile->ewidth; OUTPUT: RETVAL guint gimp_tile_eheight(tile) GimpTile *tile CODE: RETVAL = tile->eheight; OUTPUT: RETVAL guint gimp_tile_bpp(tile) GimpTile *tile CODE: RETVAL = tile->bpp; OUTPUT: RETVAL guint gimp_tile_shadow(tile) GimpTile *tile CODE: RETVAL = tile->shadow; OUTPUT: RETVAL guint gimp_tile_dirty(tile) GimpTile *tile CODE: RETVAL = tile->dirty; OUTPUT: RETVAL DRAWABLE gimp_tile_drawable(tile) GimpTile *tile CODE: RETVAL = tile->drawable->id; OUTPUT: RETVAL SV * gimp_pixel_rgn_get_row2(pr, x, y, width) GimpPixelRgn * pr int x int y int width CODE: RETVAL = newSVn (width * pr->bpp); gimp_pixel_rgn_get_row (pr, (guchar *)SvPV_nolen(RETVAL), x, y, width); OUTPUT: RETVAL SV * gimp_pixel_rgn_get_rect2(pr, x, y, width, height) GimpPixelRgn * pr int x int y int width int height CODE: RETVAL = newSVn (width * height * pr->bpp); gimp_pixel_rgn_get_rect (pr, (guchar *)SvPV_nolen(RETVAL), x, y, width, height); OUTPUT: RETVAL void gimp_pixel_rgn_set_rect2(pr, data, x, y, w=pr->w) GimpPixelRgn * pr SV * data int x int y int w CODE: { STRLEN dlen; guchar *dta = (guchar *)SvPV (data, dlen); gimp_pixel_rgn_set_rect (pr, dta, x, y, w, dlen / (w*pr->bpp)); } #if HAVE_PDL SV * gimp_drawable_get_tile(gdrawable, shadow, row, col) SV * gdrawable gint shadow gint row gint col CODE: need_pdl (); RETVAL = new_tile (gimp_drawable_get_tile (old_gdrawable (gdrawable), shadow, row, col), gdrawable); OUTPUT: RETVAL SV * gimp_drawable_get_tile2(gdrawable, shadow, x, y) SV * gdrawable gint shadow gint x gint y CODE: need_pdl (); RETVAL = new_tile (gimp_drawable_get_tile2 (old_gdrawable (gdrawable), shadow, x, y), gdrawable); OUTPUT: RETVAL pdl * gimp_pixel_rgn_get_pixel(pr, x, y) GimpPixelRgn_PDL * pr int x int y CODE: RETVAL = new_pdl (0, 0, pr->bpp); gimp_pixel_rgn_get_pixel (pr, RETVAL->data, x, y); OUTPUT: RETVAL pdl * gimp_pixel_rgn_get_row(pr, x, y, width) GimpPixelRgn_PDL * pr int x int y int width CODE: RETVAL = new_pdl (0, width, pr->bpp); gimp_pixel_rgn_get_row (pr, RETVAL->data, x, y, width); OUTPUT: RETVAL pdl * gimp_pixel_rgn_get_col(pr, x, y, height) GimpPixelRgn_PDL * pr int x int y int height CODE: RETVAL = new_pdl (height, 0, pr->bpp); gimp_pixel_rgn_get_col (pr, RETVAL->data, x, y, height); OUTPUT: RETVAL pdl * gimp_pixel_rgn_get_rect(pr, x, y, width, height) GimpPixelRgn_PDL * pr int x int y int width int height CODE: RETVAL = new_pdl (height, width, pr->bpp); gimp_pixel_rgn_get_rect (pr, RETVAL->data, x, y, width, height); OUTPUT: RETVAL void gimp_pixel_rgn_set_pixel(pr, pdl, x, y) GimpPixelRgn_PDL * pr pdl * pdl int x int y CODE: old_pdl (&pdl, 0, pr->bpp); gimp_pixel_rgn_set_pixel (pr, pdl->data, x, y); void gimp_pixel_rgn_set_row(pr, pdl, x, y) GimpPixelRgn_PDL * pr pdl * pdl int x int y CODE: old_pdl (&pdl, 1, pr->bpp); gimp_pixel_rgn_set_row (pr, pdl->data, x, y, pdl->dims[pdl->ndims-1]); void gimp_pixel_rgn_set_col(pr, pdl, x, y) GimpPixelRgn_PDL * pr pdl * pdl int x int y CODE: old_pdl (&pdl, 1, pr->bpp); gimp_pixel_rgn_set_col (pr, pdl->data, x, y, pdl->dims[pdl->ndims-1]); void gimp_pixel_rgn_set_rect(pr, pdl, x, y) GimpPixelRgn_PDL * pr pdl * pdl int x int y CODE: old_pdl (&pdl, 2, pr->bpp); gimp_pixel_rgn_set_rect (pr, pdl->data, x, y, pdl->dims[pdl->ndims-2], pdl->dims[pdl->ndims-1]); pdl * gimp_pixel_rgn_data(pr,newdata=0) GimpPixelRgn_PDL * pr pdl * newdata CODE: if (newdata) { guchar *src; guchar *dst; int y, stride; old_pdl (&newdata, 2, pr->bpp); stride = pr->bpp * newdata->dims[newdata->ndims-2]; if ((int)pr->h != newdata->dims[newdata->ndims-1]) croak (__("pdl height != region height")); for (y = 0, src = newdata->data, dst = pr->data; y < (int)pr->h; y++ , src += stride , dst += pr->rowstride) Copy (src, dst, stride, char); RETVAL = newdata; } else { pdl *p = PDL->new(); PDL_Long dims[3]; dims[0] = pr->bpp; dims[1] = pr->rowstride / pr->bpp; dims[2] = pr->h; PDL->setdims (p, dims, 3); p->datatype = PDL_B; p->data = pr->data; p->state |= PDL_DONTTOUCHDATA | PDL_ALLOCATED; PDL->add_deletedata_magic(p, pixel_rgn_pdl_delete_data, 0); if ((int)pr->w != dims[1]) p = redim_pdl (p, 1, pr->w); RETVAL = p; } OUTPUT: RETVAL # ??? optimize these two functions so tile_*ref will only be called once on # construction/destruction. SV * gimp_tile_get_data(tile) GimpTile * tile CODE: need_pdl (); croak (__("gimp_tile_get_data is not yet implemented\n")); gimp_tile_ref (tile); gimp_tile_unref (tile, 0); OUTPUT: RETVAL void gimp_tile_set_data(tile,data) GimpTile * tile SV * data CODE: croak (__("gimp_tile_set_data is not yet implemented\n")); /*(void *)data;*/ gimp_tile_ref_zero (tile); gimp_tile_unref (tile, 1); #else void gimp_pixel_rgn_data(...) ALIAS: gimp_drawable_get_tile = 1 gimp_drawable_get_tile2 = 2 gimp_pixel_rgn_get_pixel = 3 gimp_pixel_rgn_get_row = 4 gimp_pixel_rgn_get_col = 5 gimp_pixel_rgn_get_rect = 6 gimp_pixel_rgn_set_pixel = 7 gimp_pixel_rgn_set_row = 8 gimp_pixel_rgn_set_col = 9 gimp_pixel_rgn_set_rect = 10 gimp_tile_get_data = 11 gimp_tile_set_data = 12 CODE: croak (__("This module was built without support for PDL.")); #endif BOOT: trace_file = PerlIO_stderr (); # # this function overrides a pdb function for speed # void gimp_patterns_get_pattern_data(name) SV * name PPCODE: { GimpParam *return_vals; int nreturn_vals; return_vals = gimp_run_procedure ("gimp_patterns_get_pattern_data", &nreturn_vals, GIMP_PDB_STRING, SvPV_nolen (name), GIMP_PDB_END); if (nreturn_vals == 7 && return_vals[0].data.d_status == GIMP_PDB_SUCCESS) { EXTEND (SP, 5); PUSHs (sv_2mortal (newSVpv ( return_vals[1].data.d_string, 0))); PUSHs (sv_2mortal (newSViv ( return_vals[2].data.d_int32))); PUSHs (sv_2mortal (newSViv ( return_vals[3].data.d_int32))); PUSHs (sv_2mortal (newSViv ( return_vals[4].data.d_int32))); PUSHs (sv_2mortal (newSVpvn((char *)return_vals[6].data.d_int8array, return_vals[5].data.d_int32))); } gimp_destroy_params (return_vals, nreturn_vals); } void _gimp_progress_init (message) gchar * message CODE: gimp_progress_init (message); #ifdef GIMP_HAVE_DEFAULT_DISPLAY DISPLAY gimp_default_display() #endif # functions using different calling conventions: #void #gimp_channel_get_color(channel_ID, red, green, blue) # CHANNEL channel_ID # guchar * red # guchar * green # guchar * blue #gint32 * #gimp_image_get_channels(image_ID, nchannels) # IMAGE image_ID # gint * nchannels #guchar * #gimp_image_get_cmap(image_ID, ncolors) # IMAGE image_ID # gint * ncolors #gint32 * #gimp_image_get_layers(image_ID, nlayers) # IMAGE image_ID # gint * nlayers #gint32 #gimp_layer_new(image_ID, name, width, height, type, opacity, mode) # gint32 image_ID # char * name # guint width # guint height # GimpImageType type # gdouble opacity # GimpLayerModeEffects mode #gint32 #gimp_layer_copy(layer_ID) # gint32 layer_ID #void #gimp_channel_set_color(channel_ID, red, green, blue) # gint32 channel_ID # guchar red # guchar green # guchar blue #gint #gimp_drawable_mask_bounds(drawable_ID, x1, y1, x2, y2) # DRAWABLE drawable_ID # gint * x1 # gint * y1 # gint * x2 # gint * y2 #void #gimp_drawable_offsets(drawable_ID, offset_x, offset_y) # DRAWABLE drawable_ID # gint * offset_x # gint * offset_y # ??? almost synonymous to gimp_list_images #gint32 * #gimp_image_list(nimages) # int * nimages