X-Git-Url: http://git.imager.perl.org/imager.git/blobdiff_plain/b9e2571f45fe236eacc2249b4695e54e8e9a517a..e1c0692925:/Imager.xs diff --git a/Imager.xs b/Imager.xs index 3dc6d0b2..58d92aa4 100644 --- a/Imager.xs +++ b/Imager.xs @@ -30,6 +30,8 @@ extern "C" { #include "imperl.h" +#define ARRAY_COUNT(array) (sizeof(array)/sizeof(*array)) + /* Context object management @@ -50,22 +52,11 @@ typedef struct { START_MY_CXT -im_context_t fallback_context; - static void start_context(pTHX) { dMY_CXT; MY_CXT.ctx = im_context_new(); sv_setref_pv(get_sv("Imager::_context", GV_ADD), "Imager::Context", MY_CXT.ctx); - - /* Ideally we'd free this reference, but the error message memory - was never released on exit, so the associated memory here is reasonable - to keep. - With logging enabled we always need at least one context, since - objects may be released fairly late and attempt to get the log file. - */ - im_context_refinc(MY_CXT.ctx, "start_context"); - fallback_context = MY_CXT.ctx; } static im_context_t @@ -73,7 +64,7 @@ perl_get_context(void) { dTHX; dMY_CXT; - return MY_CXT.ctx ? MY_CXT.ctx : fallback_context; + return MY_CXT.ctx; } #else @@ -83,7 +74,9 @@ static im_context_t perl_context; static void start_context(pTHX) { perl_context = im_context_new(); - im_context_refinc(perl_context, "start_context"); + + /* just so it gets destroyed */ + sv_setref_pv(get_sv("Imager::_context", GV_ADD), "Imager::Context", perl_context); } static im_context_t @@ -109,6 +102,11 @@ typedef struct { const i_fsample_t *samples; } i_fsample_list; +typedef struct { + size_t count; + const i_polygon_t *polygons; +} i_polygon_list; + /* Allocate memory that will be discarded when mortals are discarded. @@ -117,15 +115,18 @@ Allocate memory that will be discarded when mortals are discarded. static void * malloc_temp(pTHX_ size_t size) { - SV *sv = sv_2mortal(newSV(size)); + void *result; + Newx(result, size, char); + SAVEFREEPV(result); - return SvPVX(sv); + return result; } static void * calloc_temp(pTHX_ size_t size) { - void *result = malloc_temp(aTHX_ size); - memset(result, 0, size); + void *result; + Newxz(result, size, char); + SAVEFREEPV(result); return result; } @@ -140,14 +141,14 @@ calloc_temp(pTHX_ size_t size) { #define i_img_dimPtr(size) ((i_img_dim *)calloc_temp(aTHX_ sizeof(i_img_dim) * (size))) #define SvI_img_dim(sv, pname) (SvIV(sv)) -#define i_colorPtr(size) ((i_color *)calloc_temp(aTHX_ sizeof(i_color *) * (size))) +#define i_colorPtr(size) ((i_color *)calloc_temp(aTHX_ sizeof(i_color) * (size))) #define SvI_color(sv, pname) S_sv_to_i_color(aTHX_ sv, pname) static i_color S_sv_to_i_color(pTHX_ SV *sv, const char *pname) { if (!sv_derived_from(sv, "Imager::Color")) { - croak("%s: not a color object"); + croak("%s: not a color object", pname); } return *INT2PTR(i_color *, SvIV((SV *)SvRV(sv))); } @@ -234,9 +235,9 @@ static int getobj(void *hv_t,char *key,char *type,void **store) { UTIL_table_t i_UTIL_table={getstr,getint,getdouble,getvoid,getobj}; -void my_SvREFCNT_dec(void *p) { - dTHX; - SvREFCNT_dec((SV*)p); +static void +free_buffer(void *p) { + myfree(p); } @@ -411,7 +412,6 @@ static int io_closer(void *p) { if (SvOK(cbd->closecb)) { dSP; I32 count; - SV *sv; ENTER; SAVETMPS; @@ -422,8 +422,12 @@ static int io_closer(void *p) { SPAGAIN; - sv = POPs; - success = SvTRUE(sv); + if (count) { + SV *sv = POPs; + success = SvTRUE(sv); + } + else + success = 0; PUTBACK; FREETMPS; @@ -444,14 +448,26 @@ static void io_destroyer(void *p) { myfree(cbd); } -static i_io_glue_t * -do_io_new_buffer(pTHX_ SV *data_sv) { - const char *data; - STRLEN length; +static bool +im_SvREFSCALAR(SV *sv) { + svtype type = SvTYPE(sv); + + switch (type) { + case SVt_PV: + case SVt_PVIV: + case SVt_PVNV: + case SVt_PVMG: + case SVt_IV: + case SVt_NV: + case SVt_PVLV: +#if PERL_VERSION > 10 + case SVt_REGEXP: +#endif + return 1; - data = SvPVbyte(data_sv, length); - SvREFCNT_inc(data_sv); - return io_new_buffer(data, length, my_SvREFCNT_dec, data_sv); + default: + return 0; + } } static const char * @@ -475,6 +491,35 @@ describe_sv(SV *sv) { } } +static i_io_glue_t * +do_io_new_buffer(pTHX_ SV *data_sv) { + const char *data; + char *data_copy; + STRLEN length; + SV *sv; + + SvGETMAGIC(data_sv); + if (SvROK(data_sv)) { + if (im_SvREFSCALAR(SvRV(data_sv))) { + sv = SvRV(data_sv); + } + else { + i_push_errorf(0, "data is not a scalar or a reference to scalar"); + return NULL; + } + } + else { + sv = data_sv; + } + + /* previously this would keep the SV around, but this is unsafe in + many ways, so always copy the bytes */ + data = SvPVbyte(sv, length); + data_copy = mymalloc(length); + memcpy(data_copy, data, length); + return io_new_buffer(data_copy, length, free_buffer, data_copy); +} + static i_io_glue_t * do_io_new_cb(pTHX_ SV *writecb, SV *readcb, SV *seekcb, SV *closecb) { struct cbdata *cbd; @@ -492,18 +537,29 @@ do_io_new_cb(pTHX_ SV *writecb, SV *readcb, SV *seekcb, SV *closecb) { } struct value_name { - char *name; + const char *name; int value; }; -static int lookup_name(struct value_name *names, int count, char *name, int def_value) +static int +lookup_name(const struct value_name *names, int count, char *name, int def_value, int push_errors, const char *id, int *failed) { int i; + + if (push_errors) + *failed = 0; + for (i = 0; i < count; ++i) if (strEQ(names[i].name, name)) return names[i].value; + if (push_errors) { + i_push_errorf(0, "unknown value '%s' for %s", name, id); + *failed = 1; + } + return def_value; } + static struct value_name transp_names[] = { { "none", tr_none }, @@ -557,14 +613,14 @@ static struct value_name orddith_names[] = }; /* look through the hash for quantization options */ -static void -ip_handle_quant_opts(pTHX_ i_quantize *quant, HV *hv) +static int +ip_handle_quant_opts_low(pTHX_ i_quantize *quant, HV *hv, int push_errors) { - /*** POSSIBLY BROKEN: do I need to unref the SV from hv_fetch ***/ SV **sv; int i; STRLEN len; char *str; + int failed = 0; quant->mc_colors = mymalloc(quant->mc_size * sizeof(i_color)); @@ -572,7 +628,9 @@ ip_handle_quant_opts(pTHX_ i_quantize *quant, HV *hv) if (sv && *sv && (str = SvPV(*sv, len))) { quant->transp = lookup_name(transp_names, sizeof(transp_names)/sizeof(*transp_names), - str, tr_none); + str, tr_none, push_errors, "transp", &failed); + if (failed) + return 0; if (quant->transp != tr_none) { quant->tr_threshold = 127; sv = hv_fetch(hv, "tr_threshold", 12, 0); @@ -582,13 +640,18 @@ ip_handle_quant_opts(pTHX_ i_quantize *quant, HV *hv) if (quant->transp == tr_errdiff) { sv = hv_fetch(hv, "tr_errdiff", 10, 0); if (sv && *sv && (str = SvPV(*sv, len))) - quant->tr_errdiff = lookup_name(errdiff_names, sizeof(errdiff_names)/sizeof(*errdiff_names), str, ed_floyd); + quant->tr_errdiff = lookup_name(errdiff_names, sizeof(errdiff_names)/sizeof(*errdiff_names), str, ed_floyd, push_errors, "tr_errdiff", &failed); + if (failed) + return 0; } if (quant->transp == tr_ordered) { quant->tr_orddith = od_tiny; sv = hv_fetch(hv, "tr_orddith", 10, 0); - if (sv && *sv && (str = SvPV(*sv, len))) - quant->tr_orddith = lookup_name(orddith_names, sizeof(orddith_names)/sizeof(*orddith_names), str, od_random); + if (sv && *sv && (str = SvPV(*sv, len))) { + quant->tr_orddith = lookup_name(orddith_names, sizeof(orddith_names)/sizeof(*orddith_names), str, od_random, push_errors, "tr_orddith", &failed); + if (failed) + return 0; + } if (quant->tr_orddith == od_custom) { sv = hv_fetch(hv, "tr_map", 6, 0); @@ -613,7 +676,9 @@ ip_handle_quant_opts(pTHX_ i_quantize *quant, HV *hv) sv = hv_fetch(hv, "make_colors", 11, 0); if (sv && *sv && (str = SvPV(*sv, len))) { quant->make_colors = - lookup_name(make_color_names, sizeof(make_color_names)/sizeof(*make_color_names), str, mc_median_cut); + lookup_name(make_color_names, sizeof(make_color_names)/sizeof(*make_color_names), str, mc_median_cut, push_errors, "make_colors", &failed); + if (failed) + return 0; } sv = hv_fetch(hv, "colors", 6, 0); if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) { @@ -630,6 +695,10 @@ ip_handle_quant_opts(pTHX_ i_quantize *quant, HV *hv) i_color *col = INT2PTR(i_color *, SvIV((SV*)SvRV(*sv1))); quant->mc_colors[i] = *col; } + else if (push_errors) { + i_push_errorf(0, "colors[%d] isn't an Imager::Color object", i); + return 0; + } } } sv = hv_fetch(hv, "max_colors", 10, 0); @@ -642,11 +711,15 @@ ip_handle_quant_opts(pTHX_ i_quantize *quant, HV *hv) quant->translate = pt_closest; sv = hv_fetch(hv, "translate", 9, 0); if (sv && *sv && (str = SvPV(*sv, len))) { - quant->translate = lookup_name(translate_names, sizeof(translate_names)/sizeof(*translate_names), str, pt_closest); + quant->translate = lookup_name(translate_names, sizeof(translate_names)/sizeof(*translate_names), str, pt_closest, push_errors, "translate", &failed); + if (failed) + return 0; } sv = hv_fetch(hv, "errdiff", 7, 0); if (sv && *sv && (str = SvPV(*sv, len))) { - quant->errdiff = lookup_name(errdiff_names, sizeof(errdiff_names)/sizeof(*errdiff_names), str, ed_floyd); + quant->errdiff = lookup_name(errdiff_names, sizeof(errdiff_names)/sizeof(*errdiff_names), str, ed_floyd, push_errors, "errdiff", &failed); + if (failed) + return 0; } if (quant->translate == pt_errdiff && quant->errdiff == ed_custom) { /* get the error diffusion map */ @@ -671,7 +744,12 @@ ip_handle_quant_opts(pTHX_ i_quantize *quant, HV *hv) for (i = 0; i < len; ++i) { SV **sv2 = av_fetch(av, i, 0); if (sv2 && *sv2) { - quant->ed_map[i] = SvIV(*sv2); + IV iv = SvIV(*sv2); + if (push_errors && iv < 0) { + i_push_errorf(0, "errdiff_map values must be non-negative, errdiff[%d] is negative", i); + return 0; + } + quant->ed_map[i] = iv; sum += quant->ed_map[i]; } } @@ -681,12 +759,18 @@ ip_handle_quant_opts(pTHX_ i_quantize *quant, HV *hv) myfree(quant->ed_map); quant->ed_map = 0; quant->errdiff = ed_floyd; + if (push_errors) { + i_push_error(0, "error diffusion map must contain some non-zero values"); + return 0; + } } } } sv = hv_fetch(hv, "perturb", 7, 0); if (sv && *sv) quant->perturb = SvIV(*sv); + + return 1; } static void @@ -696,6 +780,20 @@ ip_cleanup_quant_opts(pTHX_ i_quantize *quant) { myfree(quant->ed_map); } +static int +ip_handle_quant_opts2(pTHX_ i_quantize *quant, HV *hv) { + int result = ip_handle_quant_opts_low(aTHX_ quant, hv, 1); + if (!result) { + ip_cleanup_quant_opts(aTHX_ quant); + } + return result; +} + +static void +ip_handle_quant_opts(pTHX_ i_quantize *quant, HV *hv) { + (void)ip_handle_quant_opts_low(aTHX_ quant, hv, 0); +} + /* copies the color map from the hv into the colors member of the HV */ static void ip_copy_colors_back(pTHX_ HV *hv, i_quantize *quant) { @@ -723,6 +821,95 @@ ip_copy_colors_back(pTHX_ HV *hv, i_quantize *quant) { } } +static struct value_name +poly_fill_mode_names[] = +{ + { "evenodd", i_pfm_evenodd }, + { "nonzero", i_pfm_nonzero } +}; + +static i_poly_fill_mode_t +S_get_poly_fill_mode(pTHX_ SV *sv) { + if (looks_like_number(sv)) { + IV work = SvIV(sv); + if (work < (IV)i_pfm_evenodd || work > (IV)i_pfm_nonzero) + work = (IV)i_pfm_evenodd; + return (i_poly_fill_mode_t)work; + } + else { + return (i_poly_fill_mode_t)lookup_name + (poly_fill_mode_names, ARRAY_COUNT(poly_fill_mode_names), + SvPV_nolen(sv), i_pfm_evenodd, 0, NULL, NULL); + } +} + +static void +S_get_polygon_list(pTHX_ i_polygon_list *polys, SV *sv) { + AV *av; + int i; + i_polygon_t *s; + + SvGETMAGIC(sv); + if (!SvOK(sv) || !SvROK(sv) || SvTYPE(SvRV(sv)) != SVt_PVAV) + croak("polys must be an arrayref"); + + av = (AV*)SvRV(sv); + polys->count = av_len(av) + 1; + if (polys->count < 1) + croak("polypolygon: no polygons provided"); + s = malloc_temp(aTHX_ sizeof(i_polygon_t) * polys->count); + for (i = 0; i < polys->count; ++i) { + SV **poly_sv = av_fetch(av, i, 0); + AV *poly_av; + SV **x_sv, **y_sv; + AV *x_av, *y_av; + double *x_data, *y_data; + ssize_t j; + ssize_t point_count; + + if (!poly_sv) + croak("poly_polygon: nothing found for polygon %d", i); + /* needs to be another av */ + SvGETMAGIC(*poly_sv); + if (!SvOK(*poly_sv) || !SvROK(*poly_sv) || SvTYPE(SvRV(*poly_sv)) != SVt_PVAV) + croak("poly_polygon: polygon %d isn't an arrayref", i); + poly_av = (AV*)SvRV(*poly_sv); + /* with two elements */ + if (av_len(poly_av) != 1) + croak("poly_polygon: polygon %d should contain two arrays", i); + x_sv = av_fetch(poly_av, 0, 0); + y_sv = av_fetch(poly_av, 1, 0); + if (!x_sv) + croak("poly_polygon: polygon %d has no x elements", i); + if (!y_sv) + croak("poly_polygon: polygon %d has no y elements", i); + SvGETMAGIC(*x_sv); + SvGETMAGIC(*y_sv); + if (!SvOK(*x_sv) || !SvROK(*x_sv) || SvTYPE(SvRV(*x_sv)) != SVt_PVAV) + croak("poly_polygon: polygon %d x elements isn't an array", i); + if (!SvOK(*y_sv) || !SvROK(*y_sv) || SvTYPE(SvRV(*y_sv)) != SVt_PVAV) + croak("poly_polygon: polygon %d y elements isn't an array", i); + x_av = (AV*)SvRV(*x_sv); + y_av = (AV*)SvRV(*y_sv); + if (av_len(x_av) != av_len(y_av)) + croak("poly_polygon: polygon %d x and y arrays different lengths", i+1); + point_count = av_len(x_av)+1; + x_data = malloc_temp(aTHX_ sizeof(double) * point_count * 2); + y_data = x_data + point_count; + + for (j = 0; j < point_count; ++j) { + SV **x_item_sv = av_fetch(x_av, j, 0); + SV **y_item_sv = av_fetch(y_av, j, 0); + x_data[j] = x_item_sv ? SvNV(*x_item_sv) : 0; + y_data[j] = y_item_sv ? SvNV(*y_item_sv) : 0; + } + s[i].x = x_data; + s[i].y = y_data; + s[i].count = point_count; + } + polys->polygons = s; +} + /* loads the segments of a fountain fill into an array */ static i_fountain_seg * load_fount_segs(pTHX_ AV *asegs, int *count) { @@ -922,7 +1109,8 @@ static im_pl_ext_funcs im_perl_funcs = IMAGER_PL_API_LEVEL, ip_handle_quant_opts, ip_cleanup_quant_opts, - ip_copy_colors_back + ip_copy_colors_back, + ip_handle_quant_opts2 }; #define PERL_PL_SET_GLOBAL_CALLBACKS \ @@ -971,7 +1159,10 @@ ICL_set_internal(cl,r,g,b,a) unsigned char b unsigned char a PPCODE: - ICL_set_internal(cl, r, g, b, a); + cl->rgba.r = r; + cl->rgba.g = g; + cl->rgba.b = b; + cl->rgba.a = a; EXTEND(SP, 1); PUSHs(ST(0)); @@ -1016,10 +1207,10 @@ MODULE = Imager PACKAGE = Imager::Color::Float PREFIX=ICLF_ Imager::Color::Float ICLF_new_internal(r, g, b, a) - double r - double g - double b - double a + im_double r + im_double g + im_double b + im_double a void ICLF_DESTROY(cl) @@ -1040,10 +1231,10 @@ ICLF_rgba(cl) void ICLF_set_internal(cl,r,g,b,a) Imager::Color::Float cl - double r - double g - double b - double a + im_double r + im_double g + im_double b + im_double a PPCODE: cl->rgba.r = r; cl->rgba.g = g; @@ -1075,9 +1266,9 @@ i_rgb_to_hsv(c) MODULE = Imager PACKAGE = Imager::ImgRaw PREFIX = IIM_ Imager::ImgRaw -IIM_new(x,y,ch) - i_img_dim x - i_img_dim y +IIM_new(xsize,ysize,ch) + i_img_dim xsize + i_img_dim ysize int ch void @@ -1103,7 +1294,10 @@ Imager::IO io_new_buffer(data_sv) SV *data_sv CODE: + i_clear_error(); RETVAL = do_io_new_buffer(aTHX_ data_sv); + if (!RETVAL) + XSRETURN(0); OUTPUT: RETVAL @@ -1113,7 +1307,6 @@ io_new_cb(writecb, readcb, seekcb, closecb, maxwrite = CBDATA_BUFSIZE) SV *readcb; SV *seekcb; SV *closecb; - int maxwrite; CODE: RETVAL = do_io_new_cb(aTHX_ writecb, readcb, seekcb, closecb); OUTPUT: @@ -1175,7 +1368,10 @@ Imager::IO io_new_buffer(class, data_sv) SV *data_sv CODE: + i_clear_error(); RETVAL = do_io_new_buffer(aTHX_ data_sv); + if (!RETVAL) + XSRETURN(0); OUTPUT: RETVAL @@ -1246,12 +1442,12 @@ i_io_raw_read(ig, buffer_sv, size) if (size <= 0) croak("size negative in call to i_io_raw_read()"); /* prevent an undefined value warning if they supplied an - undef buffer. + undef buffer. Orginally conditional on !SvOK(), but this will prevent the - downgrade from croaking */ - sv_setpvn(buffer_sv, "", 0); + downgrade from croaking */ + sv_setpvn(buffer_sv, "", 0); #ifdef SvUTF8 - if (SvUTF8(buffer_sv)) + if (SvUTF8(buffer_sv)) sv_utf8_downgrade(buffer_sv, FALSE); #endif buffer = SvGROW(buffer_sv, size+1); @@ -1318,6 +1514,10 @@ int i_io_getc(ig) Imager::IO ig +void +i_io_nextc(ig) + Imager::IO ig + int i_io_putc(ig, c) Imager::IO ig @@ -1377,12 +1577,12 @@ i_io_read(ig, buffer_sv, size) if (size <= 0) croak("size negative in call to i_io_read()"); /* prevent an undefined value warning if they supplied an - undef buffer. + undef buffer. Orginally conditional on !SvOK(), but this will prevent the - downgrade from croaking */ - sv_setpvn(buffer_sv, "", 0); + downgrade from croaking */ + sv_setpvn(buffer_sv, "", 0); #ifdef SvUTF8 - if (SvUTF8(buffer_sv)) + if (SvUTF8(buffer_sv)) sv_utf8_downgrade(buffer_sv, FALSE); #endif buffer = SvGROW(buffer_sv, size+1); @@ -1575,6 +1775,22 @@ IV i_img_get_height(im) Imager::ImgRaw im +int +i_img_color_model(im) + Imager::ImgRaw im + +int +i_img_color_channels(im) + Imager::ImgRaw im + +int +i_img_alpha_channel(im) + Imager::ImgRaw im + CODE: + if (!i_img_alpha_channel(im, &RETVAL)) + XSRETURN(0); + OUTPUT: + RETVAL void i_img_is_monochrome(im) @@ -1657,19 +1873,19 @@ i_arc(im,x,y,rad,d1,d2,val) Imager::ImgRaw im i_img_dim x i_img_dim y - double rad - double d1 - double d2 + im_double rad + im_double d1 + im_double d2 Imager::Color val void i_arc_aa(im,x,y,rad,d1,d2,val) Imager::ImgRaw im - double x - double y - double rad - double d1 - double d2 + im_double x + im_double y + im_double rad + im_double d1 + im_double d2 Imager::Color val void @@ -1677,30 +1893,38 @@ i_arc_cfill(im,x,y,rad,d1,d2,fill) Imager::ImgRaw im i_img_dim x i_img_dim y - double rad - double d1 - double d2 + im_double rad + im_double d1 + im_double d2 Imager::FillHandle fill void i_arc_aa_cfill(im,x,y,rad,d1,d2,fill) Imager::ImgRaw im - double x - double y - double rad - double d1 - double d2 + im_double x + im_double y + im_double rad + im_double d1 + im_double d2 Imager::FillHandle fill void i_circle_aa(im,x,y,rad,val) Imager::ImgRaw im - double x - double y - double rad + im_double x + im_double y + im_double rad Imager::Color val +void +i_circle_aa_fill(im,x,y,rad,fill) + Imager::ImgRaw im + im_double x + im_double y + im_double rad + Imager::FillHandle fill + int i_circle_out(im,x,y,rad,val) Imager::ImgRaw im @@ -1723,8 +1947,8 @@ i_arc_out(im,x,y,rad,d1,d2,val) i_img_dim x i_img_dim y i_img_dim rad - double d1 - double d2 + im_double d1 + im_double d2 Imager::Color val int @@ -1733,51 +1957,31 @@ i_arc_out_aa(im,x,y,rad,d1,d2,val) i_img_dim x i_img_dim y i_img_dim rad - double d1 - double d2 + im_double d1 + im_double d2 Imager::Color val void -i_bezier_multi(im,xc,yc,val) +i_bezier_multi(im,x,y,val) Imager::ImgRaw im - Imager::Color val - PREINIT: - double *x,*y; - int len; - AV *av1; - AV *av2; - SV *sv1; - SV *sv2; - int i; - PPCODE: - ICL_info(val); - if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_bezier_multi must be a reference to an array\n"); - if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_bezier_multi must be a reference to an array\n"); - if (!SvROK(ST(2))) croak("Imager: Parameter 2 to i_bezier_multi must be a reference to an array\n"); - if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 2 to i_bezier_multi must be a reference to an array\n"); - av1=(AV*)SvRV(ST(1)); - av2=(AV*)SvRV(ST(2)); - if (av_len(av1) != av_len(av2)) croak("Imager: x and y arrays to i_bezier_multi must be equal length\n"); - len=av_len(av1)+1; - x=mymalloc( len*sizeof(double) ); - y=mymalloc( len*sizeof(double) ); - for(i=0;itags, name, start, &entry)) { - if (entry == 0) - RETVAL = newSVpv("0 but true", 0); - else - RETVAL = newSViv(entry); + RETVAL = entry; } else { - RETVAL = &PL_sv_undef; + XSRETURN_UNDEF; } OUTPUT: RETVAL -SV * +SysRet i_tags_findn(im, code, start) Imager::ImgRaw im int code @@ -3700,13 +3941,10 @@ i_tags_findn(im, code, start) int entry; CODE: if (i_tags_findn(&im->tags, code, start, &entry)) { - if (entry == 0) - RETVAL = newSVpv("0 but true", 0); - else - RETVAL = newSViv(entry); + RETVAL = entry; } else { - RETVAL = &PL_sv_undef; + XSRETURN_UNDEF; } OUTPUT: RETVAL @@ -3820,19 +4058,21 @@ i_new_fill_solidf(cl, combine) int combine Imager::FillHandle -i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy) +i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch_sv, dx, dy) Imager::Color fg Imager::Color bg int combine int hatch + SV *cust_hatch_sv i_img_dim dx i_img_dim dy PREINIT: unsigned char *cust_hatch; STRLEN len; CODE: - if (SvOK(ST(4))) { - cust_hatch = (unsigned char *)SvPV(ST(4), len); + SvGETMAGIC(cust_hatch_sv); + if (SvOK(cust_hatch_sv)) { + cust_hatch = (unsigned char *)SvPV_nomg(cust_hatch_sv, len); } else cust_hatch = NULL; @@ -3841,19 +4081,21 @@ i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy) RETVAL Imager::FillHandle -i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy) +i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch_sv, dx, dy) Imager::Color::Float fg Imager::Color::Float bg int combine int hatch + SV *cust_hatch_sv i_img_dim dx i_img_dim dy PREINIT: unsigned char *cust_hatch; STRLEN len; CODE: - if (SvOK(ST(4))) { - cust_hatch = (unsigned char *)SvPV(ST(4), len); + SvGETMAGIC(cust_hatch_sv); + if (SvOK(cust_hatch_sv)) { + cust_hatch = (unsigned char *)SvPV(cust_hatch_sv, len); } else cust_hatch = NULL; @@ -3862,8 +4104,9 @@ i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy) RETVAL Imager::FillHandle -i_new_fill_image(src, matrix, xoff, yoff, combine) +i_new_fill_image(src, matrix_sv, xoff, yoff, combine) Imager::ImgRaw src + SV *matrix_sv i_img_dim xoff i_img_dim yoff int combine @@ -3875,13 +4118,14 @@ i_new_fill_image(src, matrix, xoff, yoff, combine) SV *sv1; int i; CODE: - if (!SvOK(ST(1))) { + SvGETMAGIC(matrix_sv); + if (!SvOK(matrix_sv)) { matrixp = NULL; } else { - if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV) - croak("i_new_fill_image: parameter must be an arrayref"); - av=(AV*)SvRV(ST(1)); + if (!SvROK(matrix_sv) || SvTYPE(SvRV(matrix_sv)) != SVt_PVAV) + croak("i_new_fill_image: matrix parameter must be an arrayref or undef"); + av=(AV*)SvRV(matrix_sv); len=av_len(av)+1; if (len > 9) len = 9; @@ -3953,6 +4197,9 @@ im_context_CLONE(...) /* the following sv_setref_pv() will free this inc */ im_context_refinc(MY_CXT.ctx, "CLONE"); MY_CXT.ctx = im_context_clone(MY_CXT.ctx, "CLONE"); + if (MY_CXT.ctx == NULL) { + croak("Failed to clone Imager context"); + } sv_setref_pv(get_sv("Imager::_context", GV_ADD), "Imager::Context", MY_CXT.ctx); #endif