[rt #69243] add the T_AVARRAY typemap and use it
authorTony Cook <tony@develop-help.com>
Tue, 21 May 2013 13:13:42 +0000 (23:13 +1000)
committerTony Cook <tony@develop-help.com>
Tue, 21 May 2013 13:13:42 +0000 (23:13 +1000)
Changes
Imager.xs
typemap

diff --git a/Changes b/Changes
index c703648..c10aa5d 100644 (file)
--- a/Changes
+++ b/Changes
@@ -20,9 +20,11 @@ Imager release history.  Older releases can be found in Changes.old
    - Imager::Color's rgba() method now returns it's values as integers
      instead of floating point. (IV instead of NV).
 
-   - The XS for i_poly_aa(), i_poly_aa_cfill(), i_map(), i_transform()
-     and i_matrix_transform() now use the AV * typemap instead of
-     rolling their own.
+   - 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.
 
    - some XS code formatting
 
index e643aec..fe1273a 100644 (file)
--- a/Imager.xs
+++ b/Imager.xs
@@ -122,6 +122,13 @@ malloc_temp(pTHX_ size_t size) {
   return SvPVX(sv);
 }
 
+/* for use with the T_AVARRAY typemap */
+#define doublePtr(size) ((double *)malloc_temp(aTHX_ sizeof(double) * (size)))
+#define SvDouble(sv) (SvNV(sv))
+
+#define intPtr(size) ((int *)malloc_temp(aTHX_ sizeof(int) * (size)))
+#define SvInt(sv) (SvIV(sv))
+
 /* These functions are all shared - then comes platform dependant code */
 static int getstr(void *hv_t,char *key,char **store) {
   dTHX;
@@ -1743,62 +1750,34 @@ i_bezier_multi(im,xc,yc,val)
 
 
 int
-i_poly_aa(im,x_av,y_av,val)
+i_poly_aa(im,x,y,val)
     Imager::ImgRaw     im
-    AV *x_av
-    AV *y_av
+    double *x
+    double *y
     Imager::Color  val
   PREINIT:
-    double   *x,*y;
-    int       len;
-    SV       *x_sv;
-    SV       *y_sv;
-    SSize_t   i;
+    STRLEN   size_x;
+    STRLEN   size_y;
   CODE:
-    if (av_len(x_av) != av_len(y_av))
+    if (size_x != size_y)
       croak("Imager: x and y arrays to i_poly_aa must be equal length\n");
-    len=av_len(x_av)+1;
-    x=mymalloc( len*sizeof(double) );
-    y=mymalloc( len*sizeof(double) );
-    for(i=0;i<len;i++) {
-      x_sv=(*(av_fetch(x_av,i,0)));
-      y_sv=(*(av_fetch(y_av,i,0)));
-      x[i]=(double)SvNV(x_sv);
-      y[i]=(double)SvNV(y_sv);
-    }
-    RETVAL = i_poly_aa(im,len,x,y,val);
-    myfree(x);
-    myfree(y);
+    RETVAL = i_poly_aa(im, size_x, x, y, val);
   OUTPUT:
     RETVAL
 
 int
-i_poly_aa_cfill(im,x_av,y_av,fill)
+i_poly_aa_cfill(im, x, y, fill)
     Imager::ImgRaw     im
-    AV *x_av
-    AV *y_av
+    double *x
+    double *y
     Imager::FillHandle     fill
   PREINIT:
-    double   *x,*y;
-    STRLEN   len;
-    SV       *x_sv;
-    SV       *y_sv;
-    int i;
+    STRLEN size_x;
+    STRLEN size_y;
   CODE:
-    if (av_len(x_av) != av_len(y_av))
+    if (size_x != size_y)
       croak("Imager: x and y arrays to i_poly_aa_cfill must be equal length\n");
-    len=av_len(x_av)+1;
-    x=mymalloc( len*sizeof(double) );
-    y=mymalloc( len*sizeof(double) );
-    for(i=0;i<len;i++) {
-      x_sv=(*(av_fetch(x_av,i,0)));
-      y_sv=(*(av_fetch(y_av,i,0)));
-      x[i]=(double)SvNV(x_sv);
-      y[i]=(double)SvNV(y_sv);
-    }
-    RETVAL = i_poly_aa_cfill(im,len,x,y,fill);
-    myfree(x);
-    myfree(y);
+    RETVAL = i_poly_aa_cfill(im, size_x, x, y, fill);
   OUTPUT:
     RETVAL
 
@@ -2509,45 +2488,16 @@ i_get_anonymous_color_histo(im, maxc = 0x40000000)
 
 
 void
-i_transform(im,opx_av,opy_av,parm_av)
+i_transform(im, opx, opy, parm)
     Imager::ImgRaw     im
-    AV *opx_av
-    AV *opy_av
-    AV *parm_av
+    int *opx
+    int *opy
+    double *parm
              PREINIT:
-             double* parm;
-             int *opx;
-             int *opy;
-             int     opxl;
-             int     opyl;
-             int     parmlen;
-             AV* av;
-             SV* sv1;
-             int i;
+            STRLEN size_opx, size_opy, size_parm;
             i_img *result;
              PPCODE:
-             opxl=av_len(opx_av)+1;
-             opx=mymalloc( opxl*sizeof(int) );
-             for(i=0;i<opxl;i++) {
-               sv1=(*(av_fetch(opx_av,i,0)));
-               opx[i]=(int)SvIV(sv1);
-             }
-             opyl=av_len(opy_av)+1;
-             opy=mymalloc( opyl*sizeof(int) );
-             for(i=0;i<opyl;i++) {
-               sv1=(*(av_fetch(opy_av,i,0)));
-               opy[i]=(int)SvIV(sv1);
-             }
-             parmlen=av_len(parm_av)+1;
-             parm=mymalloc( parmlen*sizeof(double) );
-             for(i=0;i<parmlen;i++) {
-               sv1=(*(av_fetch(parm_av,i,0)));
-               parm[i]=(double)SvNV(sv1);
-             }
-             result=i_transform(im,opx,opxl,opy,opyl,parm,parmlen);
-             myfree(parm);
-             myfree(opy);
-             myfree(opx);
+             result=i_transform(im,opx,size_opx,opy,size_opy,parm,size_parm);
             if (result) {
               SV *result_sv = sv_newmortal();
               EXTEND(SP, 1);
diff --git a/typemap b/typemap
index ad3a028..5bd5a47 100644 (file)
--- a/typemap
+++ b/typemap
@@ -14,6 +14,9 @@ HASH                  T_HVREF
 utf8_str               T_UTF8_STR
 i_img_dim              T_IV
 
+double *               T_AVARRAY
+int *                          T_AVARRAY
+
 # these types are for use by Inline, which can't handle types containing ::
 Imager__Color           T_PTROBJ_INV
 Imager__Color__Float    T_PTROBJ_INV
@@ -76,6 +79,32 @@ T_PTROBJ_INV
         else
             croak(\"$var is not of type ${(my $ntt=$ntype)=~s/__/::/g;\$ntt}\");
 
+T_AVARRAY
+       STMT_START {
+               SV* const xsub_tmp_sv = $arg;
+               SvGETMAGIC(xsub_tmp_sv);
+               if (SvROK(xsub_tmp_sv) && SvTYPE(SvRV(xsub_tmp_sv)) == SVt_PVAV){
+                   AV *xsub_tmp_av = (AV*)SvRV(xsub_tmp_sv);
+                   STRLEN xsub_index;
+                   size_$var = av_len(xsub_tmp_av) + 1;
+                   $var = $ntype(size_$var);
+                   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);
+                        }
+                       else
+                         ${var}[xsub_index] = 0;
+                   }
+               }
+               else{
+                   Perl_croak(aTHX_ \"%s: %s is not an ARRAY reference\",
+                               ${$ALIAS?\q[GvNAME(CvGV(cv))]:\qq[\"$pname\"]},
+                               \"$var\");
+               }
+       } STMT_END
+
+
 #############################################################################
 OUTPUT
 T_IV_U