]> git.imager.perl.org - imager.git/blobdiff - Imager.xs
update Changes
[imager.git] / Imager.xs
index 53e91852d34fffada6ee37f4fb670e9f6bd21839..2b757fed6e3b830ac247e576fc266056b88dc66e 100644 (file)
--- a/Imager.xs
+++ b/Imager.xs
@@ -30,6 +30,10 @@ extern "C" {
 
 #include "imperl.h"
 
 
 #include "imperl.h"
 
+#ifndef SV_COW_DROP_PV
+#define SV_COW_DROP_PV
+#endif
+
 /*
 
 Context object management
 /*
 
 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")) {
 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)));
 }
   }
   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};
 
 
 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;
   if (SvOK(cbd->closecb)) {
     dSP;
     I32 count;
-    SV *sv;
 
     ENTER;
     SAVETMPS;
 
     ENTER;
     SAVETMPS;
@@ -422,8 +425,12 @@ static int io_closer(void *p) {
 
     SPAGAIN;
     
 
     SPAGAIN;
     
-    sv = POPs;
-    success = SvTRUE(sv);
+    if (count) {
+      SV *sv = POPs;
+      success = SvTRUE(sv);
+    }
+    else
+      success = 0;
 
     PUTBACK;
     FREETMPS;
 
     PUTBACK;
     FREETMPS;
@@ -444,14 +451,41 @@ static void io_destroyer(void *p) {
   myfree(cbd);
 }
 
   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;
 static i_io_glue_t *
 do_io_new_buffer(pTHX_ SV *data_sv) {
   const char *data;
+  char *data_copy;
   STRLEN length;
   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 *
 }
 
 static const char *
@@ -1103,7 +1137,10 @@ Imager::IO
 io_new_buffer(data_sv)
          SV   *data_sv
        CODE:
 io_new_buffer(data_sv)
          SV   *data_sv
        CODE:
+         i_clear_error();
          RETVAL = do_io_new_buffer(aTHX_ data_sv);
          RETVAL = do_io_new_buffer(aTHX_ data_sv);
+         if (!RETVAL)
+           XSRETURN(0);
         OUTPUT:
           RETVAL
 
         OUTPUT:
           RETVAL
 
@@ -1113,7 +1150,6 @@ io_new_cb(writecb, readcb, seekcb, closecb, maxwrite = CBDATA_BUFSIZE)
         SV *readcb;
         SV *seekcb;
         SV *closecb;
         SV *readcb;
         SV *seekcb;
         SV *closecb;
-        int maxwrite;
       CODE:
         RETVAL = do_io_new_cb(aTHX_ writecb, readcb, seekcb, closecb);
       OUTPUT:
       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:
 io_new_buffer(class, data_sv)
        SV *data_sv
     CODE:
+        i_clear_error();
         RETVAL = do_io_new_buffer(aTHX_ data_sv);
         RETVAL = do_io_new_buffer(aTHX_ data_sv);
+       if (!RETVAL)
+         XSRETURN(0);
     OUTPUT:
         RETVAL
 
     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()");
       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) {
        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()");
       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) {
        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
 
 
 void
-i_bezier_multi(im,xc,yc,val)
+i_bezier_multi(im,x,y,val)
     Imager::ImgRaw     im
     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;i<len;i++) {
-              sv1=(*(av_fetch(av1,i,0)));
-              sv2=(*(av_fetch(av2,i,0)));
-              x[i]=(double)SvNV(sv1);
-              y[i]=(double)SvNV(sv2);
-            }
-             i_bezier_multi(im,len,x,y,val);
-             myfree(x);
-             myfree(y);
-
+    double *x
+    double *y
+    Imager::Color  val
+  PREINIT:
+    STRLEN size_x;
+    STRLEN size_y;
+  PPCODE:
+    if (size_x != size_y)
+      croak("Imager: x and y arrays to i_bezier_multi must be equal length\n");
+    i_bezier_multi(im,size_x,x,y,val);
 
 int
 i_poly_aa(im,x,y,val)
 
 int
 i_poly_aa(im,x,y,val)
@@ -2110,7 +2116,6 @@ i_map(im, pmaps_av)
     AV *pmaps_av
   PREINIT:
     unsigned int mask = 0;
     AV *pmaps_av
   PREINIT:
     unsigned int mask = 0;
-    AV *avmain;
     AV *avsub;
     SV **temp;
     int len;
     AV *avsub;
     SV **temp;
     int len;
@@ -3630,16 +3635,18 @@ i_img_to_drgb(im)
        Imager::ImgRaw im
 
 undef_int
        Imager::ImgRaw im
 
 undef_int
-i_tags_addn(im, name, code, idata)
+i_tags_addn(im, name_sv, code, idata)
         Imager::ImgRaw im
         Imager::ImgRaw im
+       SV *name_sv
         int     code
         int     idata
       PREINIT:
         char *name;
         STRLEN len;
       CODE:
         int     code
         int     idata
       PREINIT:
         char *name;
         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;
         RETVAL = i_tags_addn(&im->tags, name, code, idata);
         else
           name = NULL;
         RETVAL = i_tags_addn(&im->tags, name, code, idata);
@@ -3647,21 +3654,25 @@ i_tags_addn(im, name, code, idata)
         RETVAL
 
 undef_int
         RETVAL
 
 undef_int
-i_tags_add(im, name, code, data, idata)
+i_tags_add(im, name_sv, code, data_sv, idata)
         Imager::ImgRaw  im
         Imager::ImgRaw  im
+       SV *name_sv
         int code
         int code
+       SV *data_sv
         int idata
       PREINIT:
         char *name;
         char *data;
         STRLEN len;
       CODE:
         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;
         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;
         else {
           data = NULL;
           len = 0;
@@ -3670,7 +3681,7 @@ i_tags_add(im, name, code, data, idata)
       OUTPUT:
         RETVAL
 
       OUTPUT:
         RETVAL
 
-SV *
+SysRet
 i_tags_find(im, name, start)
         Imager::ImgRaw  im
         char *name
 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)) {
         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 {
         } else {
-          RETVAL = &PL_sv_undef;
+          XSRETURN_UNDEF;
         }
       OUTPUT:
         RETVAL
 
         }
       OUTPUT:
         RETVAL
 
-SV *
+SysRet
 i_tags_findn(im, code, start)
         Imager::ImgRaw  im
         int             code
 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)) {
         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 {
         }
         else {
-          RETVAL = &PL_sv_undef;
+          XSRETURN_UNDEF;
         }
       OUTPUT:
         RETVAL
         }
       OUTPUT:
         RETVAL
@@ -3818,19 +3823,21 @@ i_new_fill_solidf(cl, combine)
         int combine
 
 Imager::FillHandle
         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
         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:
         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;
         }
         else
           cust_hatch = NULL;
@@ -3839,19 +3846,21 @@ i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy)
         RETVAL
 
 Imager::FillHandle
         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
         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:
         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;
         }
         else
           cust_hatch = NULL;
@@ -3860,8 +3869,9 @@ i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy)
         RETVAL
 
 Imager::FillHandle
         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
         Imager::ImgRaw src
+       SV *matrix_sv
         i_img_dim xoff
         i_img_dim yoff
         int combine
         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:
         SV *sv1;
         int i;
       CODE:
-        if (!SvOK(ST(1))) {
+        SvGETMAGIC(matrix_sv);
+        if (!SvOK(matrix_sv)) {
           matrixp = NULL;
         }
         else {
           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;
          len=av_len(av)+1;
           if (len > 9)
             len = 9;