X-Git-Url: http://git.imager.perl.org/imager.git/blobdiff_plain/73d80423249a58de4924523adb881070c7e4d300..6a160bce857f1d340fa20c1d4a67d242b5e098f1:/Imager.xs?ds=sidebyside diff --git a/Imager.xs b/Imager.xs index 53e91852..2b757fed 100644 --- a/Imager.xs +++ b/Imager.xs @@ -30,6 +30,10 @@ extern "C" { #include "imperl.h" +#ifndef SV_COW_DROP_PV +#define SV_COW_DROP_PV +#endif + /* Context object management @@ -147,7 +151,7 @@ calloc_temp(pTHX_ size_t size) { 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 +238,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 +415,6 @@ static int io_closer(void *p) { if (SvOK(cbd->closecb)) { dSP; I32 count; - SV *sv; ENTER; SAVETMPS; @@ -422,8 +425,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 +451,41 @@ static void io_destroyer(void *p) { myfree(cbd); } +static bool +im_SvREFSCALAR(SV *sv) { + svtype type = SvTYPE(sv); + return type == SVt_PV || type == SVt_PVIV || type == SVt_PVNV + || type == SVt_PVMG || type == SVt_IV || type == SVt_NV + || type == SVt_PVLV || type == SVt_REGEXP; +} + 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(data_sv)) { + sv = SvRV(data_sv); + } + else { + i_push_error(0, "data is not a scalar or a reference to scalar"); + return NULL; + } + } + else { + sv = data_sv; + } - data = SvPVbyte(data_sv, length); - SvREFCNT_inc(data_sv); - return io_new_buffer(data, length, my_SvREFCNT_dec, 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 const char * @@ -1103,7 +1137,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 +1150,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 +1211,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 @@ -1245,15 +1284,9 @@ i_io_raw_read(ig, buffer_sv, size) PPCODE: if (size <= 0) croak("size negative in call to i_io_raw_read()"); - /* prevent an undefined value warning if they supplied an - undef buffer. - Orginally conditional on !SvOK(), but this will prevent the - downgrade from croaking */ - sv_setpvn(buffer_sv, "", 0); -#ifdef SvUTF8 - if (SvUTF8(buffer_sv)) - sv_utf8_downgrade(buffer_sv, FALSE); -#endif + if (SvTHINKFIRST(buffer_sv)) + sv_force_normal_flags(buffer_sv, SV_COW_DROP_PV); + SvUPGRADE(buffer_sv, SVt_PV); buffer = SvGROW(buffer_sv, size+1); result = i_io_raw_read(ig, buffer, size); if (result >= 0) { @@ -1376,15 +1409,9 @@ i_io_read(ig, buffer_sv, size) PPCODE: if (size <= 0) croak("size negative in call to i_io_read()"); - /* prevent an undefined value warning if they supplied an - undef buffer. - Orginally conditional on !SvOK(), but this will prevent the - downgrade from croaking */ - sv_setpvn(buffer_sv, "", 0); -#ifdef SvUTF8 - if (SvUTF8(buffer_sv)) - sv_utf8_downgrade(buffer_sv, FALSE); -#endif + if (SvTHINKFIRST(buffer_sv)) + sv_force_normal_flags(buffer_sv, SV_COW_DROP_PV); + SvUPGRADE(buffer_sv, SVt_PV); buffer = SvGROW(buffer_sv, size+1); result = i_io_read(ig, buffer, size); if (result >= 0) { @@ -1739,39 +1766,18 @@ i_arc_out_aa(im,x,y,rad,d1,d2,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, code, idata); @@ -3647,21 +3654,25 @@ i_tags_addn(im, name, code, idata) RETVAL undef_int -i_tags_add(im, name, code, data, idata) +i_tags_add(im, name_sv, code, data_sv, idata) Imager::ImgRaw im + SV *name_sv int code + SV *data_sv int idata PREINIT: char *name; char *data; STRLEN len; CODE: - if (SvOK(ST(1))) - name = SvPV(ST(1), len); + SvGETMAGIC(name_sv); + if (SvOK(name_sv)) + name = SvPV_nomg(name_sv, len); else name = NULL; - if (SvOK(ST(3))) - data = SvPV(ST(3), len); + SvGETMAGIC(data_sv); + if (SvOK(data_sv)) + data = SvPV(data_sv, len); else { data = NULL; len = 0; @@ -3670,7 +3681,7 @@ i_tags_add(im, name, code, data, idata) OUTPUT: RETVAL -SV * +SysRet i_tags_find(im, name, start) Imager::ImgRaw im char *name @@ -3679,17 +3690,14 @@ i_tags_find(im, name, start) int entry; CODE: if (i_tags_find(&im->tags, 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 @@ -3698,13 +3706,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 @@ -3818,19 +3823,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; @@ -3839,19 +3846,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; @@ -3860,8 +3869,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 @@ -3873,13 +3883,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;