[rt #69243] use T_AVARRAY for i_gradgen too
authorTony Cook <tony@develop-help.com>
Tue, 21 May 2013 13:51:53 +0000 (23:51 +1000)
committerTony Cook <tony@develop-help.com>
Tue, 21 May 2013 13:51:53 +0000 (23:51 +1000)
Changes
Imager.xs
typemap

diff --git a/Changes b/Changes
index c10aa5d..6588a45 100644 (file)
--- a/Changes
+++ b/Changes
@@ -23,8 +23,9 @@ Imager release history.  Older releases can be found in Changes.old
    - The XS for i_map() and i_matrix_transform() now use the AV *
      typemap instead of rolling their own.
 
-   - The XS for i_poly_aa(), i_poly_aa_cfill(), i_transform() now use
-     a new T_AVARRAY typemap that greatly simplifies the XS code.
+   - The XS for i_poly_aa(), i_poly_aa_cfill(), i_transform() and
+     i_gradgen() now use a new T_AVARRAY typemap that greatly
+     simplifies the XS code.
 
    - some XS code formatting
 
index fe1273a..05ae303 100644 (file)
--- a/Imager.xs
+++ b/Imager.xs
@@ -122,12 +122,35 @@ malloc_temp(pTHX_ size_t size) {
   return SvPVX(sv);
 }
 
+static void *
+calloc_temp(pTHX_ size_t size) {
+  void *result = malloc_temp(aTHX_ size);
+  memset(result, 0, size);
+
+  return result;
+}
+
 /* for use with the T_AVARRAY typemap */
-#define doublePtr(size) ((double *)malloc_temp(aTHX_ sizeof(double) * (size)))
-#define SvDouble(sv) (SvNV(sv))
+#define doublePtr(size) ((double *)calloc_temp(aTHX_ sizeof(double) * (size)))
+#define SvDouble(sv, pname) (SvNV(sv))
+
+#define intPtr(size) ((int *)calloc_temp(aTHX_ sizeof(int) * (size)))
+#define SvInt(sv, pname) (SvIV(sv))
 
-#define intPtr(size) ((int *)malloc_temp(aTHX_ sizeof(int) * (size)))
-#define SvInt(sv) (SvIV(sv))
+#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 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");
+  }
+  return *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
+}
 
 /* These functions are all shared - then comes platform dependant code */
 static int getstr(void *hv_t,char *key,char **store) {
@@ -2691,54 +2714,22 @@ i_turbnoise(im, xo, yo, scale)
 
 
 void
-i_gradgen(im, ...)
+i_gradgen(im, xo, yo, ac, dmeasure)
     Imager::ImgRaw     im
+    i_img_dim *xo
+    i_img_dim *yo
+    i_color *ac
+    int dmeasure
       PREINIT:
-       int num;
-       i_img_dim *xo;
-       i_img_dim *yo;
-        i_color *ival;
-       int dmeasure;
-       int i;
-       SV *sv;
-       AV *axx;
-       AV *ayy;
-       AV *ac;
+       STRLEN size_xo;
+       STRLEN size_yo;
+        STRLEN size_ac;
       CODE:
-       if (items != 5)
-           croak("Usage: i_gradgen(im, xo, yo, ival, dmeasure)");
-       if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
-           croak("i_gradgen: Second argument must be an array ref");
-       if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
-           croak("i_gradgen: Third argument must be an array ref");
-       if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
-           croak("i_gradgen: Fourth argument must be an array ref");
-       axx = (AV *)SvRV(ST(1));
-       ayy = (AV *)SvRV(ST(2));
-       ac  = (AV *)SvRV(ST(3));
-       dmeasure = (int)SvIV(ST(4));
-       
-        num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
-       num = num <= av_len(ac) ? num : av_len(ac);
-       num++; 
-       if (num < 2) croak("Usage: i_gradgen array refs must have more than 1 entry each");
-       xo = mymalloc( sizeof(i_img_dim) * num );
-       yo = mymalloc( sizeof(i_img_dim) * num );
-       ival = mymalloc( sizeof(i_color) * num );
-       for(i = 0; i<num; i++) {
-         xo[i]   = (i_img_dim)SvIV(* av_fetch(axx, i, 0));
-         yo[i]   = (i_img_dim)SvIV(* av_fetch(ayy, i, 0));
-          sv = *av_fetch(ac, i, 0);
-         if ( !sv_derived_from(sv, "Imager::Color") ) {
-           free(axx); free(ayy); free(ac);
-            croak("i_gradgen: Element of fourth argument is not derived from Imager::Color");
-         }
-         ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
-       }
-        i_gradgen(im, num, xo, yo, ival, dmeasure);
-        myfree(xo);
-        myfree(yo);
-        myfree(ival);
+        if (size_xo != size_yo || size_xo != size_ac)
+         croak("i_gradgen: x, y and color arrays must be the same size");
+       if (size_xo < 2)
+          croak("Usage: i_gradgen array refs must have more than 1 entry each");
+        i_gradgen(im, size_xo, xo, yo, ac, dmeasure);
 
 Imager::ImgRaw
 i_diff_image(im, im2, mindist=0)
diff --git a/typemap b/typemap
index 5bd5a47..907451e 100644 (file)
--- a/typemap
+++ b/typemap
@@ -16,6 +16,8 @@ i_img_dim             T_IV
 
 double *               T_AVARRAY
 int *                          T_AVARRAY
+i_img_dim *            T_AVARRAY
+i_color *              T_AVARRAY
 
 # these types are for use by Inline, which can't handle types containing ::
 Imager__Color           T_PTROBJ_INV
@@ -91,10 +93,8 @@ T_AVARRAY
                    for (xsub_index = 0; xsub_index < size_$var; ++xsub_index) {
                        SV **sv = av_fetch(xsub_tmp_av, xsub_index, 0);
                        if (sv) {
-                         ${var}[xsub_index] = Sv${(my $ntt = $ntype) =~ s/Ptr$//; \(ucfirst $ntt)}(*sv);
+                         ${var}[xsub_index] = Sv${(my $ntt = $ntype) =~ s/Ptr$//; \(ucfirst $ntt)}(*sv, \"$pname\");
                         }
-                       else
-                         ${var}[xsub_index] = 0;
                    }
                }
                else{