]> git.imager.perl.org - imager.git/blobdiff - Imager.xs
remove buffering from the callback IO object implementation
[imager.git] / Imager.xs
index f0afbe57aa7843ebfe2119584c48fcc73dd5ddaf..1a8672c88204513e75de7cae7a1c88536b986abe 100644 (file)
--- a/Imager.xs
+++ b/Imager.xs
@@ -28,13 +28,26 @@ extern "C" {
 
 #include "imperl.h"
 
 
 #include "imperl.h"
 
+/*
+
+Allocate memory that will be discarded when mortals are discarded.
+
+*/
+
+static void *
+malloc_temp(pTHX_ size_t size) {
+  SV *sv = sv_2mortal(newSV(size));
+
+  return SvPVX(sv);
+}
+
 /* These functions are all shared - then comes platform dependant code */
 static int getstr(void *hv_t,char *key,char **store) {
   dTHX;
   SV** svpp;
   HV* hv=(HV*)hv_t;
 
 /* These functions are all shared - then comes platform dependant code */
 static int getstr(void *hv_t,char *key,char **store) {
   dTHX;
   SV** svpp;
   HV* hv=(HV*)hv_t;
 
-  mm_log((1,"getstr(hv_t 0x%X, key %s, store 0x%X)\n",hv_t,key,store));
+  mm_log((1,"getstr(hv_t %p, key %s, store %p)\n",hv_t,key,store));
 
   if ( !hv_exists(hv,key,strlen(key)) ) return 0;
 
 
   if ( !hv_exists(hv,key,strlen(key)) ) return 0;
 
@@ -49,7 +62,7 @@ static int getint(void *hv_t,char *key,int *store) {
   SV** svpp;
   HV* hv=(HV*)hv_t;  
 
   SV** svpp;
   HV* hv=(HV*)hv_t;  
 
-  mm_log((1,"getint(hv_t 0x%X, key %s, store 0x%X)\n",hv_t,key,store));
+  mm_log((1,"getint(hv_t %p, key %s, store %p)\n",hv_t,key,store));
 
   if ( !hv_exists(hv,key,strlen(key)) ) return 0;
 
 
   if ( !hv_exists(hv,key,strlen(key)) ) return 0;
 
@@ -63,11 +76,11 @@ static int getdouble(void *hv_t,char* key,double *store) {
   SV** svpp;
   HV* hv=(HV*)hv_t;
 
   SV** svpp;
   HV* hv=(HV*)hv_t;
 
-  mm_log((1,"getdouble(hv_t 0x%X, key %s, store 0x%X)\n",hv_t,key,store));
+  mm_log((1,"getdouble(hv_t %p, key %s, store %p)\n",hv_t,key,store));
 
   if ( !hv_exists(hv,key,strlen(key)) ) return 0;
   svpp=hv_fetch(hv, key, strlen(key), 0);
 
   if ( !hv_exists(hv,key,strlen(key)) ) return 0;
   svpp=hv_fetch(hv, key, strlen(key), 0);
-  *store=(float)SvNV(*svpp);
+  *store=(double)SvNV(*svpp);
   return 1;
 }
 
   return 1;
 }
 
@@ -76,7 +89,7 @@ static int getvoid(void *hv_t,char* key,void **store) {
   SV** svpp;
   HV* hv=(HV*)hv_t;
 
   SV** svpp;
   HV* hv=(HV*)hv_t;
 
-  mm_log((1,"getvoid(hv_t 0x%X, key %s, store 0x%X)\n",hv_t,key,store));
+  mm_log((1,"getvoid(hv_t %p, key %s, store %p)\n",hv_t,key,store));
 
   if ( !hv_exists(hv,key,strlen(key)) ) return 0;
 
 
   if ( !hv_exists(hv,key,strlen(key)) ) return 0;
 
@@ -91,7 +104,7 @@ static int getobj(void *hv_t,char *key,char *type,void **store) {
   SV** svpp;
   HV* hv=(HV*)hv_t;
 
   SV** svpp;
   HV* hv=(HV*)hv_t;
 
-  mm_log((1,"getobj(hv_t 0x%X, key %s,type %s, store 0x%X)\n",hv_t,key,type,store));
+  mm_log((1,"getobj(hv_t %p, key %s,type %s, store %p)\n",hv_t,key,type,store));
 
   if ( !hv_exists(hv,key,strlen(key)) ) return 0;
 
 
   if ( !hv_exists(hv,key,strlen(key)) ) return 0;
 
@@ -122,98 +135,6 @@ i_log_entry(char *string, int level) {
 }
 
 
 }
 
 
-typedef struct i_reader_data_tag
-{
-  /* presumably a CODE ref or name of a sub */
-  SV *sv;
-} i_reader_data;
-
-/* used by functions that want callbacks */
-static int read_callback(char *userdata, char *buffer, int need, int want) {
-  dTHX;
-  i_reader_data *rd = (i_reader_data *)userdata;
-  int count;
-  int result;
-  SV *data;
-  dSP; dTARG = sv_newmortal();
-  /* thanks to Simon Cozens for help with the dTARG above */
-
-  ENTER;
-  SAVETMPS;
-  EXTEND(SP, 2);
-  PUSHMARK(SP);
-  PUSHi(want);
-  PUSHi(need);
-  PUTBACK;
-
-  count = perl_call_sv(rd->sv, G_SCALAR);
-
-  SPAGAIN;
-
-  if (count != 1)
-    croak("Result of perl_call_sv(..., G_SCALAR) != 1");
-
-  data = POPs;
-
-  if (SvOK(data)) {
-    STRLEN len;
-    char *ptr = SvPV(data, len);
-    if (len > want)
-      croak("Too much data returned in reader callback");
-    
-    memcpy(buffer, ptr, len);
-    result = len;
-  }
-  else {
-    result = -1;
-  }
-
-  PUTBACK;
-  FREETMPS;
-  LEAVE;
-
-  return result;
-}
-
-typedef struct
-{
-  SV *sv; /* a coderef or sub name */
-} i_writer_data;
-
-/* used by functions that want callbacks */
-static int write_callback(char *userdata, char const *data, int size) {
-  dTHX;
-  i_writer_data *wd = (i_writer_data *)userdata;
-  int count;
-  int success;
-  SV *sv;
-  dSP; 
-
-  ENTER;
-  SAVETMPS;
-  EXTEND(SP, 1);
-  PUSHMARK(SP);
-  XPUSHs(sv_2mortal(newSVpv((char *)data, size)));
-  PUTBACK;
-
-  count = perl_call_sv(wd->sv, G_SCALAR);
-
-  SPAGAIN;
-
-  if (count != 1)
-    croak("Result of perl_call_sv(..., G_SCALAR) != 1");
-
-  sv = POPs;
-  success = SvTRUE(sv);
-
-
-  PUTBACK;
-  FREETMPS;
-  LEAVE;
-
-  return success;
-}
-
 #define CBDATA_BUFSIZE 8192
 
 struct cbdata {
 #define CBDATA_BUFSIZE 8192
 
 struct cbdata {
@@ -222,73 +143,11 @@ struct cbdata {
   SV *readcb;
   SV *seekcb;
   SV *closecb;
   SV *readcb;
   SV *seekcb;
   SV *closecb;
-
-  /* we need to remember whether the buffer contains write data or 
-     read data
-   */
-  int reading;
-  int writing;
-
-  /* how far we've read into the buffer (not used for writing) */
-  int where;
-
-  /* the amount of space used/data available in the buffer */
-  int used;
-
-  /* the maximum amount to fill the buffer before flushing
-     If any write is larger than this then the buffer is flushed and 
-     the full write is performed.  The write is _not_ split into 
-     maxwrite sized calls
-   */
-  int maxlength;
-
-  char buffer[CBDATA_BUFSIZE];
 };
 
 };
 
-/* 
-
-call_writer(cbd, buf, size)
-
-Low-level function to call the perl writer callback.
-
-*/
-
-static ssize_t call_writer(struct cbdata *cbd, void const *buf, size_t size) {
-  dTHX;
-  int count;
-  int success;
-  SV *sv;
-  dSP;
-
-  if (!SvOK(cbd->writecb))
-    return -1;
-
-  ENTER;
-  SAVETMPS;
-  EXTEND(SP, 1);
-  PUSHMARK(SP);
-  PUSHs(sv_2mortal(newSVpv((char *)buf, size)));
-  PUTBACK;
-
-  count = perl_call_sv(cbd->writecb, G_SCALAR);
-
-  SPAGAIN;
-  if (count != 1)
-    croak("Result of perl_call_sv(..., G_SCALAR) != 1");
-
-  sv = POPs;
-  success = SvTRUE(sv);
-
-
-  PUTBACK;
-  FREETMPS;
-  LEAVE;
-
-  return success ? size : -1;
-}
-
-static ssize_t call_reader(struct cbdata *cbd, void *buf, size_t size, 
-                           size_t maxread) {
+static ssize_t
+call_reader(struct cbdata *cbd, void *buf, size_t size, 
+            size_t maxread) {
   dTHX;
   int count;
   int result;
   dTHX;
   int count;
   int result;
@@ -319,7 +178,8 @@ static ssize_t call_reader(struct cbdata *cbd, void *buf, size_t size,
     STRLEN len;
     char *ptr = SvPV(data, len);
     if (len > maxread)
     STRLEN len;
     char *ptr = SvPV(data, len);
     if (len > maxread)
-      croak("Too much data returned in reader callback");
+      croak("Too much data returned in reader callback (wanted %d, got %d, expected %d)",
+      (int)size, (int)len, (int)maxread);
     
     memcpy(buf, ptr, len);
     result = len;
     
     memcpy(buf, ptr, len);
     result = len;
@@ -335,21 +195,8 @@ static ssize_t call_reader(struct cbdata *cbd, void *buf, size_t size,
   return result;
 }
 
   return result;
 }
 
-static ssize_t write_flush(struct cbdata *cbd) {
-  dTHX;
-  ssize_t result;
-
-  if (cbd->used) {
-    result = call_writer(cbd, cbd->buffer, cbd->used);
-    cbd->used = 0;
-    return result;
-  }
-  else {
-    return 1; /* success of some sort */
-  }
-}
-
-static off_t io_seeker(void *p, off_t offset, int whence) {
+static off_t
+io_seeker(void *p, off_t offset, int whence) {
   dTHX;
   struct cbdata *cbd = p;
   int count;
   dTHX;
   struct cbdata *cbd = p;
   int count;
@@ -359,17 +206,6 @@ static off_t io_seeker(void *p, off_t offset, int whence) {
   if (!SvOK(cbd->seekcb))
     return -1;
 
   if (!SvOK(cbd->seekcb))
     return -1;
 
-  if (cbd->writing) {
-    if (cbd->used && write_flush(cbd) <= 0)
-      return -1;
-    cbd->writing = 0;
-  }
-  if (whence == SEEK_CUR && cbd->reading && cbd->where != cbd->used) {
-    offset -= cbd->where - cbd->used;
-  }
-  cbd->reading = 0;
-  cbd->where = cbd->used = 0;
-  
   ENTER;
   SAVETMPS;
   EXTEND(SP, 2);
   ENTER;
   SAVETMPS;
   EXTEND(SP, 2);
@@ -394,95 +230,57 @@ static off_t io_seeker(void *p, off_t offset, int whence) {
   return result;
 }
 
   return result;
 }
 
-static ssize_t io_writer(void *p, void const *data, size_t size) {
+static ssize_t
+io_writer(void *p, void const *data, size_t size) {
   dTHX;
   struct cbdata *cbd = p;
   dTHX;
   struct cbdata *cbd = p;
+  I32 count;
+  SV *sv;
+  dSP;
+  bool success;
 
 
-  /* printf("io_writer(%p, %p, %u)\n", p, data, size); */
-  if (!cbd->writing) {
-    if (cbd->reading && cbd->where < cbd->used) {
-      /* we read past the place where the caller expected us to be
-         so adjust our position a bit */
-      if (io_seeker(p, cbd->where - cbd->used, SEEK_CUR) < 0) {
-        return -1;
-      }
-      cbd->reading = 0;
-    }
-    cbd->where = cbd->used = 0;
-  }
-  cbd->writing = 1;
-  if (cbd->used && cbd->used + size > cbd->maxlength) {
-    int write_res = write_flush(cbd);
-    if (write_res <= 0) {
-      return write_res;
-    }
-    cbd->used = 0;
-  }
-  if (cbd->used+size <= cbd->maxlength) {
-    memcpy(cbd->buffer + cbd->used, data, size);
-    cbd->used += size;
-    return size;
-  }
-  /* it doesn't fit - just pass it up */
-  return call_writer(cbd, data, size);
+  if (!SvOK(cbd->writecb))
+    return -1;
+
+  ENTER;
+  SAVETMPS;
+  EXTEND(SP, 1);
+  PUSHMARK(SP);
+  PUSHs(sv_2mortal(newSVpv((char *)data, size)));
+  PUTBACK;
+
+  count = perl_call_sv(cbd->writecb, G_SCALAR);
+
+  SPAGAIN;
+  if (count != 1)
+    croak("Result of perl_call_sv(..., G_SCALAR) != 1");
+
+  sv = POPs;
+  success = SvTRUE(sv);
+
+
+  PUTBACK;
+  FREETMPS;
+  LEAVE;
+
+  return success ? size : -1;
 }
 
 static ssize_t 
 io_reader(void *p, void *data, size_t size) {
   dTHX;
   struct cbdata *cbd = p;
 }
 
 static ssize_t 
 io_reader(void *p, void *data, size_t size) {
   dTHX;
   struct cbdata *cbd = p;
-  ssize_t total;
+  ssize_t total = 0;
   char *out = data; /* so we can do pointer arithmetic */
 
   char *out = data; /* so we can do pointer arithmetic */
 
-  /* printf("io_reader(%p, %p, %d)\n", p, data, size); */
-  if (cbd->writing) {
-    if (write_flush(cbd) <= 0)
-      return 0;
-    cbd->writing = 0;
-  }
-
-  cbd->reading = 1;
-  if (size <= cbd->used - cbd->where) {
-    /* simplest case */
-    memcpy(data, cbd->buffer+cbd->where, size);
-    cbd->where += size;
-    return size;
-  }
-  total = 0;
-  memcpy(out, cbd->buffer + cbd->where, cbd->used - cbd->where);
-  total += cbd->used - cbd->where;
-  size  -= cbd->used - cbd->where;
-  out   += cbd->used - cbd->where;
-  if (size < sizeof(cbd->buffer)) {
-    int did_read = 0;
-    int copy_size;
-    while (size
-          && (did_read = call_reader(cbd, cbd->buffer, size, 
-                                   sizeof(cbd->buffer))) > 0) {
-      cbd->where = 0;
-      cbd->used  = did_read;
-
-      copy_size = i_min(size, cbd->used);
-      memcpy(out, cbd->buffer, copy_size);
-      cbd->where += copy_size;
-      out   += copy_size;
-      total += copy_size;
-      size  -= copy_size;
-    }
-    if (did_read < 0)
-      return -1;
-  }
-  else {
-    /* just read the rest - too big for our buffer*/
-    int did_read;
-    while ((did_read = call_reader(cbd, out, size, size)) > 0) {
-      size  -= did_read;
-      total += did_read;
-      out   += did_read;
-    }
-    if (did_read < 0)
-      return -1;
+  int did_read;
+  while (size > 0 && (did_read = call_reader(cbd, out, size, size)) > 0) {
+    size  -= did_read;
+    total += did_read;
+    out   += did_read;
   }
   }
+  if (total == 0 && did_read < 0)
+    return -1;
 
   return total;
 }
 
   return total;
 }
@@ -490,30 +288,31 @@ io_reader(void *p, void *data, size_t size) {
 static int io_closer(void *p) {
   dTHX;
   struct cbdata *cbd = p;
 static int io_closer(void *p) {
   dTHX;
   struct cbdata *cbd = p;
-
-  if (cbd->writing && cbd->used > 0) {
-    if (write_flush(cbd) < 0)
-      return -1;
-    cbd->writing = 0;
-  }
+  int success = 1;
 
   if (SvOK(cbd->closecb)) {
     dSP;
 
   if (SvOK(cbd->closecb)) {
     dSP;
+    I32 count;
+    SV *sv;
 
     ENTER;
     SAVETMPS;
     PUSHMARK(SP);
     PUTBACK;
 
 
     ENTER;
     SAVETMPS;
     PUSHMARK(SP);
     PUTBACK;
 
-    perl_call_sv(cbd->closecb, G_VOID);
+    count = perl_call_sv(cbd->closecb, G_SCALAR);
 
     SPAGAIN;
 
     SPAGAIN;
+    
+    sv = POPs;
+    success = SvTRUE(sv);
+
     PUTBACK;
     FREETMPS;
     LEAVE;
   }
 
     PUTBACK;
     FREETMPS;
     LEAVE;
   }
 
-  return 0;
+  return success ? 0 : -1;
 }
 
 static void io_destroyer(void *p) {
 }
 
 static void io_destroyer(void *p) {
@@ -862,12 +661,18 @@ validate_i_ppal(i_img *im, i_palidx const *indexes, int count) {
 #define ICLF_new_internal(r, g, b, a) i_fcolor_new((r), (g), (b), (a))
 #define ICLF_DESTROY(cl) i_fcolor_destroy(cl)
 
 #define ICLF_new_internal(r, g, b, a) i_fcolor_new((r), (g), (b), (a))
 #define ICLF_DESTROY(cl) i_fcolor_destroy(cl)
 
+#ifdef IMAGER_LOG
+#define i_log_enabled() 1
+#else
+#define i_log_enabled() 0
+#endif
+
 #if i_int_hlines_testing()
 
 typedef i_int_hlines *Imager__Internal__Hlines;
 
 static i_int_hlines *
 #if i_int_hlines_testing()
 
 typedef i_int_hlines *Imager__Internal__Hlines;
 
 static i_int_hlines *
-i_int_hlines_new(int start_y, int count_y, int start_x, int count_x) {
+i_int_hlines_new(i_img_dim start_y, i_img_dim count_y, i_img_dim start_x, i_img_dim count_x) {
   i_int_hlines *result = mymalloc(sizeof(i_int_hlines));
   i_int_init_hlines(result, start_y, count_y, start_x, count_x);
 
   i_int_hlines *result = mymalloc(sizeof(i_int_hlines));
   i_int_init_hlines(result, start_y, count_y, start_x, count_x);
 
@@ -900,9 +705,9 @@ static int seg_compare(const void *vleft, const void *vright) {
 static SV *
 i_int_hlines_dump(i_int_hlines *hlines) {
   dTHX;
 static SV *
 i_int_hlines_dump(i_int_hlines *hlines) {
   dTHX;
-  SV *dump = newSVpvf("start_y: %d limit_y: %d start_x: %d limit_x: %d\n",
-       hlines->start_y, hlines->limit_y, hlines->start_x, hlines->limit_x);
-  int y;
+  SV *dump = newSVpvf("start_y: %" i_DF " limit_y: %" i_DF " start_x: %" i_DF " limit_x: %" i_DF"\n",
+       i_DFc(hlines->start_y), i_DFc(hlines->limit_y), i_DFc(hlines->start_x), i_DFc(hlines->limit_x));
+  i_img_dim y;
   
   for (y = hlines->start_y; y < hlines->limit_y; ++y) {
     i_int_hline_entry *entry = hlines->entries[y-hlines->start_y];
   
   for (y = hlines->start_y; y < hlines->limit_y; ++y) {
     i_int_hline_entry *entry = hlines->entries[y-hlines->start_y];
@@ -912,10 +717,10 @@ i_int_hlines_dump(i_int_hlines *hlines) {
       if (entry->count)
         qsort(entry->segs, entry->count, sizeof(i_int_hline_seg), seg_compare);
 
       if (entry->count)
         qsort(entry->segs, entry->count, sizeof(i_int_hline_seg), seg_compare);
 
-      sv_catpvf(dump, " %d (%d):", y, entry->count);
+      sv_catpvf(dump, " %" i_DF " (%" i_DF "):", i_DFc(y), i_DFc(entry->count));
       for (i = 0; i < entry->count; ++i) {
       for (i = 0; i < entry->count; ++i) {
-        sv_catpvf(dump, " [%d, %d)", entry->segs[i].minx
-                  entry->segs[i].x_limit);
+        sv_catpvf(dump, " [%" i_DF ", %" i_DF ")", i_DFc(entry->segs[i].minx)
+                  i_DFc(entry->segs[i].x_limit));
       }
       sv_catpv(dump, "\n");
     }
       }
       sv_catpv(dump, "\n");
     }
@@ -926,6 +731,24 @@ i_int_hlines_dump(i_int_hlines *hlines) {
 
 #endif
 
 
 #endif
 
+static off_t
+i_sv_off_t(pTHX_ SV *sv) {
+#if LSEEKSIZE > IVSIZE
+  return (off_t)SvNV(sv);
+#else
+  return (off_t)SvIV(sv);
+#endif
+}
+
+static SV *
+i_new_sv_off_t(pTHX_ off_t off) {
+#if LSEEKSIZE > IVSIZE
+  return newSVnv(off);
+#else
+  return newSViv(off);
+#endif
+}
+
 static im_pl_ext_funcs im_perl_funcs =
 {
   IMAGER_PL_API_VERSION,
 static im_pl_ext_funcs im_perl_funcs =
 {
   IMAGER_PL_API_VERSION,
@@ -1079,8 +902,8 @@ MODULE = Imager            PACKAGE = Imager::ImgRaw        PREFIX = IIM_
 
 Imager::ImgRaw
 IIM_new(x,y,ch)
 
 Imager::ImgRaw
 IIM_new(x,y,ch)
-               int     x
-              int     y
+               i_img_dim     x
+              i_img_dim     y
               int     ch
 
 void
               int     ch
 
 void
@@ -1133,10 +956,6 @@ io_new_cb(writecb, readcb, seekcb, closecb, maxwrite = CBDATA_BUFSIZE)
         cbd->seekcb = seekcb;
         SvREFCNT_inc(closecb);
         cbd->closecb = closecb;
         cbd->seekcb = seekcb;
         SvREFCNT_inc(closecb);
         cbd->closecb = closecb;
-        cbd->reading = cbd->writing = cbd->where = cbd->used = 0;
-        if (maxwrite > CBDATA_BUFSIZE)
-          maxwrite = CBDATA_BUFSIZE;
-        cbd->maxlength = maxwrite;
         RETVAL = io_new_cb(cbd, io_reader, io_writer, io_seeker, io_closer, 
                            io_destroyer);
       OUTPUT:
         RETVAL = io_new_cb(cbd, io_reader, io_writer, io_seeker, io_closer, 
                            io_destroyer);
       OUTPUT:
@@ -1158,26 +977,27 @@ io_slurp(ig)
 
 undef_int
 i_set_image_file_limits(width, height, bytes)
 
 undef_int
 i_set_image_file_limits(width, height, bytes)
-       int width
-       int height
-       int bytes
+       i_img_dim width
+       i_img_dim height
+       size_t bytes
 
 void
 i_get_image_file_limits()
       PREINIT:
 
 void
 i_get_image_file_limits()
       PREINIT:
-        int width, height, bytes;
+        i_img_dim width, height;
+       size_t bytes;
       PPCODE:
         if (i_get_image_file_limits(&width, &height, &bytes)) {
          EXTEND(SP, 3);
           PUSHs(sv_2mortal(newSViv(width)));
           PUSHs(sv_2mortal(newSViv(height)));
       PPCODE:
         if (i_get_image_file_limits(&width, &height, &bytes)) {
          EXTEND(SP, 3);
           PUSHs(sv_2mortal(newSViv(width)));
           PUSHs(sv_2mortal(newSViv(height)));
-          PUSHs(sv_2mortal(newSViv(bytes)));
+          PUSHs(sv_2mortal(newSVuv(bytes)));
         }
 
 MODULE = Imager                PACKAGE = Imager::IO    PREFIX = i_io_
 
 int
         }
 
 MODULE = Imager                PACKAGE = Imager::IO    PREFIX = i_io_
 
 int
-i_io_write(ig, data_sv)
+i_io_raw_write(ig, data_sv)
        Imager::IO ig
        SV *data_sv
       PREINIT:
        Imager::IO ig
        SV *data_sv
       PREINIT:
@@ -1192,18 +1012,18 @@ i_io_write(ig, data_sv)
        }
 #endif        
        data = SvPV(data_sv, size);
        }
 #endif        
        data = SvPV(data_sv, size);
-        RETVAL = i_io_write(ig, data, size);
+        RETVAL = i_io_raw_write(ig, data, size);
       OUTPUT:
        RETVAL
 
 void
       OUTPUT:
        RETVAL
 
 void
-i_io_read(ig, buffer_sv, size)
+i_io_raw_read(ig, buffer_sv, size)
        Imager::IO ig
        SV *buffer_sv
        Imager::IO ig
        SV *buffer_sv
-       int size
+       IV size
       PREINIT:
         void *buffer;
       PREINIT:
         void *buffer;
-       int result;
+       ssize_t result;
       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()");
@@ -1217,7 +1037,7 @@ i_io_read(ig, buffer_sv, size)
           sv_utf8_downgrade(buffer_sv, FALSE);
 #endif
        buffer = SvGROW(buffer_sv, size+1);
           sv_utf8_downgrade(buffer_sv, FALSE);
 #endif
        buffer = SvGROW(buffer_sv, size+1);
-        result = i_io_read(ig, buffer, size);
+        result = i_io_raw_read(ig, buffer, size);
         if (result >= 0) {
          SvCUR_set(buffer_sv, result);
          *SvEND(buffer_sv) = '\0';
         if (result >= 0) {
          SvCUR_set(buffer_sv, result);
          *SvEND(buffer_sv) = '\0';
@@ -1229,19 +1049,19 @@ i_io_read(ig, buffer_sv, size)
        SvSETMAGIC(ST(1));
 
 void
        SvSETMAGIC(ST(1));
 
 void
-i_io_read2(ig, size)
+i_io_raw_read2(ig, size)
        Imager::IO ig
        Imager::IO ig
-       int size
+       IV size
       PREINIT:
        SV *buffer_sv;
         void *buffer;
       PREINIT:
        SV *buffer_sv;
         void *buffer;
-       int result;
+       ssize_t result;
       PPCODE:
         if (size <= 0)
          croak("size negative in call to i_io_read2()");
        buffer_sv = newSV(size);
        buffer = SvGROW(buffer_sv, size+1);
       PPCODE:
         if (size <= 0)
          croak("size negative in call to i_io_read2()");
        buffer_sv = newSV(size);
        buffer = SvGROW(buffer_sv, size+1);
-        result = i_io_read(ig, buffer, size);
+        result = i_io_raw_read(ig, buffer, size);
         if (result >= 0) {
          SvCUR_set(buffer_sv, result);
          *SvEND(buffer_sv) = '\0';
         if (result >= 0) {
          SvCUR_set(buffer_sv, result);
          *SvEND(buffer_sv) = '\0';
@@ -1254,14 +1074,14 @@ i_io_read2(ig, size)
          SvREFCNT_dec(buffer_sv);
         }
 
          SvREFCNT_dec(buffer_sv);
         }
 
-int
-i_io_seek(ig, position, whence)
+off_t
+i_io_raw_seek(ig, position, whence)
        Imager::IO ig
        Imager::IO ig
-       long position
+       off_t position
        int whence
 
 int
        int whence
 
 int
-i_io_close(ig)
+i_io_raw_close(ig)
        Imager::IO ig
 
 void
        Imager::IO ig
 
 void
@@ -1271,10 +1091,152 @@ i_io_DESTROY(ig)
 int
 i_io_CLONE_SKIP(...)
     CODE:
 int
 i_io_CLONE_SKIP(...)
     CODE:
+        (void)items; /* avoid unused warning for XS variable */
        RETVAL = 1;
     OUTPUT:
        RETVAL
 
        RETVAL = 1;
     OUTPUT:
        RETVAL
 
+int
+i_io_getc(ig)
+       Imager::IO ig
+
+int
+i_io_putc(ig, c)
+       Imager::IO ig
+        int c
+
+int
+i_io_close(ig)
+       Imager::IO ig
+
+int
+i_io_flush(ig)
+       Imager::IO ig
+
+int
+i_io_peekc(ig)
+       Imager::IO ig
+
+int
+i_io_seek(ig, off, whence)
+       Imager::IO ig
+       off_t off
+        int whence
+
+void
+i_io_peekn(ig, size)
+       Imager::IO ig
+       STRLEN size
+      PREINIT:
+       SV *buffer_sv;
+        void *buffer;
+       size_t result;
+      PPCODE:
+        if (size == 0)
+         croak("size zero in call to peekn()");
+       buffer_sv = newSV(size);
+       buffer = SvGROW(buffer_sv, size+1);
+        result = i_io_peekn(ig, buffer, size);
+        if (result > 0) {
+         SvCUR_set(buffer_sv, result);
+         *SvEND(buffer_sv) = '\0';
+         SvPOK_only(buffer_sv);
+         EXTEND(SP, 1);
+         PUSHs(sv_2mortal(buffer_sv));
+       }
+       else {
+          /* discard it */
+         SvREFCNT_dec(buffer_sv);
+        }
+
+void
+i_io_read(ig, buffer_sv, size)
+       Imager::IO ig
+       SV *buffer_sv
+       IV size
+      PREINIT:
+        void *buffer;
+       ssize_t result;
+      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
+       buffer = SvGROW(buffer_sv, size+1);
+        result = i_io_read(ig, buffer, size);
+        if (result >= 0) {
+         SvCUR_set(buffer_sv, result);
+         *SvEND(buffer_sv) = '\0';
+         SvPOK_only(buffer_sv);
+         EXTEND(SP, 1);
+         PUSHs(sv_2mortal(newSViv(result)));
+       }
+       ST(1) = buffer_sv;
+       SvSETMAGIC(ST(1));
+
+void
+i_io_read2(ig, size)
+       Imager::IO ig
+       STRLEN size
+      PREINIT:
+       SV *buffer_sv;
+        void *buffer;
+       size_t result;
+      PPCODE:
+        if (size == 0)
+         croak("size zero in call to bread()");
+       buffer_sv = newSV(size);
+       buffer = SvGROW(buffer_sv, size+1);
+        result = i_io_read(ig, buffer, size);
+        if (result > 0) {
+         SvCUR_set(buffer_sv, result);
+         *SvEND(buffer_sv) = '\0';
+         SvPOK_only(buffer_sv);
+         EXTEND(SP, 1);
+         PUSHs(sv_2mortal(buffer_sv));
+       }
+       else {
+          /* discard it */
+         SvREFCNT_dec(buffer_sv);
+        }
+
+size_t
+i_io_write(ig, data_sv)
+       Imager::IO ig
+       SV *data_sv
+      PREINIT:
+        void *data;
+       STRLEN size;
+      CODE:
+#ifdef SvUTF8
+        if (SvUTF8(data_sv)) {
+         data_sv = sv_2mortal(newSVsv(data_sv));
+          /* yes, we want this to croak() if the SV can't be downgraded */
+         sv_utf8_downgrade(data_sv, FALSE);
+       }
+#endif        
+       data = SvPV(data_sv, size);
+        RETVAL = i_io_write(ig, data, size);
+      OUTPUT:
+       RETVAL
+
+void
+i_io_dump(ig, flags = I_IO_DUMP_DEFAULT)
+       Imager::IO ig
+       int flags
+
+void
+i_io_set_buffered(ig, flag = 1)
+       Imager::IO ig
+       int flag
+
 MODULE = Imager                PACKAGE = Imager
 
 PROTOTYPES: ENABLE
 MODULE = Imager                PACKAGE = Imager
 
 PROTOTYPES: ENABLE
@@ -1297,43 +1259,47 @@ i_img_new()
 Imager::ImgRaw
 i_img_empty(im,x,y)
     Imager::ImgRaw     im
 Imager::ImgRaw
 i_img_empty(im,x,y)
     Imager::ImgRaw     im
-               int     x
-              int     y
+               i_img_dim     x
+              i_img_dim     y
 
 Imager::ImgRaw
 i_img_empty_ch(im,x,y,ch)
     Imager::ImgRaw     im
 
 Imager::ImgRaw
 i_img_empty_ch(im,x,y,ch)
     Imager::ImgRaw     im
-               int     x
-              int     y
+               i_img_dim     x
+              i_img_dim     y
               int     ch
 
 Imager::ImgRaw
 i_sametype(im, x, y)
     Imager::ImgRaw im
               int     ch
 
 Imager::ImgRaw
 i_sametype(im, x, y)
     Imager::ImgRaw im
-               int x
-               int y
+               i_img_dim x
+               i_img_dim y
 
 Imager::ImgRaw
 i_sametype_chans(im, x, y, channels)
     Imager::ImgRaw im
 
 Imager::ImgRaw
 i_sametype_chans(im, x, y, channels)
     Imager::ImgRaw im
-               int x
-               int y
+               i_img_dim x
+               i_img_dim y
                int channels
 
                int channels
 
-void
+int
 i_init_log(name_sv,level)
              SV*    name_sv
               int     level
        PREINIT:
          const char *name = SvOK(name_sv) ? SvPV_nolen(name_sv) : NULL;
        CODE:
 i_init_log(name_sv,level)
              SV*    name_sv
               int     level
        PREINIT:
          const char *name = SvOK(name_sv) ? SvPV_nolen(name_sv) : NULL;
        CODE:
-         i_init_log(name, level);
+         RETVAL = i_init_log(name, level);
+       OUTPUT:
+         RETVAL
 
 void
 i_log_entry(string,level)
              char*    string
               int     level
 
 
 void
 i_log_entry(string,level)
              char*    string
               int     level
 
+int
+i_log_enabled()
 
 void
 i_img_exorcise(im)
 
 void
 i_img_exorcise(im)
@@ -1347,7 +1313,7 @@ void
 i_img_info(im)
     Imager::ImgRaw     im
             PREINIT:
 i_img_info(im)
     Imager::ImgRaw     im
             PREINIT:
-              int     info[4];
+              i_img_dim     info[4];
             PPCODE:
               i_img_info(im,info);
                EXTEND(SP, 4);
             PPCODE:
               i_img_info(im,info);
                EXTEND(SP, 4);
@@ -1413,67 +1379,67 @@ i_img_is_monochrome(im)
 void
 i_line(im,x1,y1,x2,y2,val,endp)
     Imager::ImgRaw     im
 void
 i_line(im,x1,y1,x2,y2,val,endp)
     Imager::ImgRaw     im
-              int     x1
-              int     y1
-              int     x2
-              int     y2
+              i_img_dim     x1
+              i_img_dim     y1
+              i_img_dim     x2
+              i_img_dim     y2
      Imager::Color     val
               int     endp
 
 void
 i_line_aa(im,x1,y1,x2,y2,val,endp)
     Imager::ImgRaw     im
      Imager::Color     val
               int     endp
 
 void
 i_line_aa(im,x1,y1,x2,y2,val,endp)
     Imager::ImgRaw     im
-              int     x1
-              int     y1
-              int     x2
-              int     y2
+              i_img_dim     x1
+              i_img_dim     y1
+              i_img_dim     x2
+              i_img_dim     y2
      Imager::Color     val
               int     endp
 
 void
 i_box(im,x1,y1,x2,y2,val)
     Imager::ImgRaw     im
      Imager::Color     val
               int     endp
 
 void
 i_box(im,x1,y1,x2,y2,val)
     Imager::ImgRaw     im
-              int     x1
-              int     y1
-              int     x2
-              int     y2
+              i_img_dim     x1
+              i_img_dim     y1
+              i_img_dim     x2
+              i_img_dim     y2
      Imager::Color     val
 
 void
 i_box_filled(im,x1,y1,x2,y2,val)
     Imager::ImgRaw     im
      Imager::Color     val
 
 void
 i_box_filled(im,x1,y1,x2,y2,val)
     Imager::ImgRaw     im
-              int     x1
-              int     y1
-              int     x2
-              int     y2
+              i_img_dim     x1
+              i_img_dim     y1
+              i_img_dim     x2
+              i_img_dim     y2
           Imager::Color    val
 
 int
 i_box_filledf(im,x1,y1,x2,y2,val)
     Imager::ImgRaw     im
           Imager::Color    val
 
 int
 i_box_filledf(im,x1,y1,x2,y2,val)
     Imager::ImgRaw     im
-              int     x1
-              int     y1
-              int     x2
-              int     y2
+              i_img_dim     x1
+              i_img_dim     y1
+              i_img_dim     x2
+              i_img_dim     y2
           Imager::Color::Float    val
 
 void
 i_box_cfill(im,x1,y1,x2,y2,fill)
     Imager::ImgRaw     im
           Imager::Color::Float    val
 
 void
 i_box_cfill(im,x1,y1,x2,y2,fill)
     Imager::ImgRaw     im
-              int     x1
-              int     y1
-              int     x2
-              int     y2
+              i_img_dim     x1
+              i_img_dim     y1
+              i_img_dim     x2
+              i_img_dim     y2
           Imager::FillHandle    fill
 
 void
 i_arc(im,x,y,rad,d1,d2,val)
     Imager::ImgRaw     im
           Imager::FillHandle    fill
 
 void
 i_arc(im,x,y,rad,d1,d2,val)
     Imager::ImgRaw     im
-              int     x
-              int     y
-             float     rad
-             float     d1
-             float     d2
+              i_img_dim     x
+              i_img_dim     y
+             double     rad
+             double     d1
+             double     d2
           Imager::Color    val
 
 void
           Imager::Color    val
 
 void
@@ -1489,11 +1455,11 @@ i_arc_aa(im,x,y,rad,d1,d2,val)
 void
 i_arc_cfill(im,x,y,rad,d1,d2,fill)
     Imager::ImgRaw     im
 void
 i_arc_cfill(im,x,y,rad,d1,d2,fill)
     Imager::ImgRaw     im
-              int     x
-              int     y
-             float     rad
-             float     d1
-             float     d2
+              i_img_dim     x
+              i_img_dim     y
+             double     rad
+             double     d1
+             double     d2
           Imager::FillHandle    fill
 
 void
           Imager::FillHandle    fill
 
 void
@@ -1510,9 +1476,9 @@ i_arc_aa_cfill(im,x,y,rad,d1,d2,fill)
 void
 i_circle_aa(im,x,y,rad,val)
     Imager::ImgRaw     im
 void
 i_circle_aa(im,x,y,rad,val)
     Imager::ImgRaw     im
-            float     x
-            float     y
-             float     rad
+            double     x
+            double     y
+             double     rad
           Imager::Color    val
 
 int
           Imager::Color    val
 
 int
@@ -1537,8 +1503,8 @@ i_arc_out(im,x,y,rad,d1,d2,val)
             i_img_dim     x
             i_img_dim     y
              i_img_dim     rad
             i_img_dim     x
             i_img_dim     y
              i_img_dim     rad
-            float d1
-            float d2
+            double d1
+            double d2
           Imager::Color    val
 
 int
           Imager::Color    val
 
 int
@@ -1547,8 +1513,8 @@ i_arc_out_aa(im,x,y,rad,d1,d2,val)
             i_img_dim     x
             i_img_dim     y
              i_img_dim     rad
             i_img_dim     x
             i_img_dim     y
              i_img_dim     rad
-            float d1
-            float d2
+            double d1
+            double d2
           Imager::Color    val
 
 
           Imager::Color    val
 
 
@@ -1663,30 +1629,30 @@ i_poly_aa_cfill(im,xc,yc,fill)
 undef_int
 i_flood_fill(im,seedx,seedy,dcol)
     Imager::ImgRaw     im
 undef_int
 i_flood_fill(im,seedx,seedy,dcol)
     Imager::ImgRaw     im
-              int     seedx
-              int     seedy
+              i_img_dim     seedx
+              i_img_dim     seedy
      Imager::Color     dcol
 
 undef_int
 i_flood_cfill(im,seedx,seedy,fill)
     Imager::ImgRaw     im
      Imager::Color     dcol
 
 undef_int
 i_flood_cfill(im,seedx,seedy,fill)
     Imager::ImgRaw     im
-              int     seedx
-              int     seedy
+              i_img_dim     seedx
+              i_img_dim     seedy
      Imager::FillHandle     fill
 
 undef_int
 i_flood_fill_border(im,seedx,seedy,dcol, border)
     Imager::ImgRaw     im
      Imager::FillHandle     fill
 
 undef_int
 i_flood_fill_border(im,seedx,seedy,dcol, border)
     Imager::ImgRaw     im
-              int     seedx
-              int     seedy
+              i_img_dim     seedx
+              i_img_dim     seedy
      Imager::Color     dcol
      Imager::Color     border
 
 undef_int
 i_flood_cfill_border(im,seedx,seedy,fill, border)
     Imager::ImgRaw     im
      Imager::Color     dcol
      Imager::Color     border
 
 undef_int
 i_flood_cfill_border(im,seedx,seedy,fill, border)
     Imager::ImgRaw     im
-              int     seedx
-              int     seedy
+              i_img_dim     seedx
+              i_img_dim     seedy
      Imager::FillHandle     fill
      Imager::Color     border
 
      Imager::FillHandle     fill
      Imager::Color     border
 
@@ -1695,24 +1661,24 @@ void
 i_copyto(im,src,x1,y1,x2,y2,tx,ty)
     Imager::ImgRaw     im
     Imager::ImgRaw     src
 i_copyto(im,src,x1,y1,x2,y2,tx,ty)
     Imager::ImgRaw     im
     Imager::ImgRaw     src
-              int     x1
-              int     y1
-              int     x2
-              int     y2
-              int     tx
-              int     ty
+              i_img_dim     x1
+              i_img_dim     y1
+              i_img_dim     x2
+              i_img_dim     y2
+              i_img_dim     tx
+              i_img_dim     ty
 
 
 void
 i_copyto_trans(im,src,x1,y1,x2,y2,tx,ty,trans)
     Imager::ImgRaw     im
     Imager::ImgRaw     src
 
 
 void
 i_copyto_trans(im,src,x1,y1,x2,y2,tx,ty,trans)
     Imager::ImgRaw     im
     Imager::ImgRaw     src
-              int     x1
-              int     y1
-              int     x2
-              int     y2
-              int     tx
-              int     ty
+              i_img_dim     x1
+              i_img_dim     y1
+              i_img_dim     x2
+              i_img_dim     y2
+              i_img_dim     tx
+              i_img_dim     ty
      Imager::Color     trans
 
 Imager::ImgRaw
      Imager::Color     trans
 
 Imager::ImgRaw
@@ -1724,23 +1690,23 @@ undef_int
 i_rubthru(im,src,tx,ty,src_minx,src_miny,src_maxx,src_maxy)
     Imager::ImgRaw     im
     Imager::ImgRaw     src
 i_rubthru(im,src,tx,ty,src_minx,src_miny,src_maxx,src_maxy)
     Imager::ImgRaw     im
     Imager::ImgRaw     src
-              int     tx
-              int     ty
-              int     src_minx
-              int     src_miny
-              int     src_maxx
-              int     src_maxy
+              i_img_dim     tx
+              i_img_dim     ty
+              i_img_dim     src_minx
+              i_img_dim     src_miny
+              i_img_dim     src_maxx
+              i_img_dim     src_maxy
 
 undef_int
 i_compose(out, src, out_left, out_top, src_left, src_top, width, height, combine = ic_normal, opacity = 0.0)
     Imager::ImgRaw out
     Imager::ImgRaw src
 
 undef_int
 i_compose(out, src, out_left, out_top, src_left, src_top, width, height, combine = ic_normal, opacity = 0.0)
     Imager::ImgRaw out
     Imager::ImgRaw src
-       int out_left
-       int out_top
-       int src_left
-       int src_top
-       int width
-       int height
+       i_img_dim out_left
+       i_img_dim out_top
+       i_img_dim src_left
+       i_img_dim src_top
+       i_img_dim width
+       i_img_dim height
        int combine
        double opacity
 
        int combine
        double opacity
 
@@ -1749,14 +1715,14 @@ i_compose_mask(out, src, mask, out_left, out_top, src_left, src_top, mask_left,
     Imager::ImgRaw out
     Imager::ImgRaw src
     Imager::ImgRaw mask
     Imager::ImgRaw out
     Imager::ImgRaw src
     Imager::ImgRaw mask
-       int out_left
-       int out_top
-       int src_left
-       int src_top
-       int mask_left
-       int mask_top
-       int width
-       int height
+       i_img_dim out_left
+       i_img_dim out_top
+       i_img_dim src_left
+       i_img_dim src_top
+       i_img_dim mask_left
+       i_img_dim mask_top
+       i_img_dim width
+       i_img_dim height
        int combine
        double opacity
 
        int combine
        double opacity
 
@@ -1841,8 +1807,8 @@ i_rotate_exact(im, amount, ...)
 Imager::ImgRaw
 i_matrix_transform(im, xsize, ysize, matrix, ...)
     Imager::ImgRaw      im
 Imager::ImgRaw
 i_matrix_transform(im, xsize, ysize, matrix, ...)
     Imager::ImgRaw      im
-               int      xsize
-               int      ysize
+               i_img_dim      xsize
+               i_img_dim      ysize
       PREINIT:
         double matrix[9];
         AV *av;
       PREINIT:
         double matrix[9];
         AV *av;
@@ -1889,7 +1855,7 @@ i_gaussian(im,stdev)
 void
 i_unsharp_mask(im,stdev,scale)
     Imager::ImgRaw     im
 void
 i_unsharp_mask(im,stdev,scale)
     Imager::ImgRaw     im
-            float     stdev
+            double    stdev
              double    scale
 
 int
              double    scale
 
 int
@@ -2030,9 +1996,6 @@ _is_color_object(sv)
     OUTPUT:
         RETVAL
 
     OUTPUT:
         RETVAL
 
-#ifdef HAVE_LIBT1
-#endif 
-
 #ifdef HAVE_LIBTT
 
 
 #ifdef HAVE_LIBTT
 
 
@@ -2052,6 +2015,7 @@ TT_DESTROY(handle)
 int
 TT_CLONE_SKIP(...)
     CODE:
 int
 TT_CLONE_SKIP(...)
     CODE:
+        (void)items; /* avoid unused warning */
         RETVAL = 1;
     OUTPUT:
         RETVAL
         RETVAL = 1;
     OUTPUT:
         RETVAL
@@ -2064,10 +2028,10 @@ undef_int
 i_tt_text(handle,im,xb,yb,cl,points,str_sv,len_ignored,smooth,utf8,align=1)
   Imager::Font::TT     handle
     Imager::ImgRaw     im
 i_tt_text(handle,im,xb,yb,cl,points,str_sv,len_ignored,smooth,utf8,align=1)
   Imager::Font::TT     handle
     Imager::ImgRaw     im
-              int     xb
-              int     yb
+              i_img_dim     xb
+              i_img_dim     yb
      Imager::Color     cl
      Imager::Color     cl
-             float     points
+             double     points
              SV *     str_sv
               int     smooth
                int     utf8
              SV *     str_sv
               int     smooth
                int     utf8
@@ -2091,10 +2055,10 @@ undef_int
 i_tt_cp(handle,im,xb,yb,channel,points,str_sv,len_ignored,smooth,utf8,align=1)
   Imager::Font::TT     handle
     Imager::ImgRaw     im
 i_tt_cp(handle,im,xb,yb,channel,points,str_sv,len_ignored,smooth,utf8,align=1)
   Imager::Font::TT     handle
     Imager::ImgRaw     im
-              int     xb
-              int     yb
+              i_img_dim     xb
+              i_img_dim     yb
               int     channel
               int     channel
-             float     points
+             double     points
              SV *     str_sv
               int     smooth
                int     utf8
              SV *     str_sv
               int     smooth
                int     utf8
@@ -2117,11 +2081,12 @@ i_tt_cp(handle,im,xb,yb,channel,points,str_sv,len_ignored,smooth,utf8,align=1)
 void
 i_tt_bbox(handle,point,str_sv,len_ignored, utf8)
   Imager::Font::TT     handle
 void
 i_tt_bbox(handle,point,str_sv,len_ignored, utf8)
   Imager::Font::TT     handle
-            float     point
+            double     point
               SV*    str_sv
                int     utf8
             PREINIT:
               SV*    str_sv
                int     utf8
             PREINIT:
-              int     cords[BOUNDING_BOX_COUNT],rc;
+              i_img_dim cords[BOUNDING_BOX_COUNT];
+              int rc;
                char *  str;
                STRLEN len;
                int i;
                char *  str;
                STRLEN len;
                int i;
@@ -2147,8 +2112,8 @@ i_tt_has_chars(handle, text_sv, utf8)
         char const *text;
         STRLEN len;
         char *work;
         char const *text;
         STRLEN len;
         char *work;
-        int count;
-        int i;
+        size_t count;
+        size_t i;
       PPCODE:
 #ifdef SvUTF8
         if (SvUTF8(text_sv))
       PPCODE:
 #ifdef SvUTF8
         if (SvUTF8(text_sv))
@@ -2178,12 +2143,12 @@ i_tt_face_name(handle)
         Imager::Font::TT handle
       PREINIT:
         char name[255];
         Imager::Font::TT handle
       PREINIT:
         char name[255];
-        int len;
+        size_t len;
       PPCODE:
         len = i_tt_face_name(handle, name, sizeof(name));
         if (len) {
           EXTEND(SP, 1);
       PPCODE:
         len = i_tt_face_name(handle, name, sizeof(name));
         if (len) {
           EXTEND(SP, 1);
-          PUSHs(sv_2mortal(newSVpv(name, strlen(name))));
+          PUSHs(sv_2mortal(newSVpv(name, len-1)));
         }
 
 void
         }
 
 void
@@ -2195,7 +2160,7 @@ i_tt_glyph_name(handle, text_sv, utf8 = 0)
         char const *text;
         STRLEN work_len;
         size_t len;
         char const *text;
         STRLEN work_len;
         size_t len;
-        int outsize;
+        size_t outsize;
         char name[255];
       PPCODE:
 #ifdef SvUTF8
         char name[255];
       PPCODE:
 #ifdef SvUTF8
@@ -2271,8 +2236,8 @@ i_writeppm_wiol(im, ig)
 Imager::ImgRaw
 i_readraw_wiol(ig,x,y,datachannels,storechannels,intrl)
         Imager::IO     ig
 Imager::ImgRaw
 i_readraw_wiol(ig,x,y,datachannels,storechannels,intrl)
         Imager::IO     ig
-              int     x
-              int     y
+              i_img_dim     x
+              i_img_dim     y
               int     datachannels
               int     storechannels
               int     intrl
               int     datachannels
               int     storechannels
               int     intrl
@@ -2320,20 +2285,20 @@ i_readtga_wiol(ig, length)
 Imager::ImgRaw
 i_scaleaxis(im,Value,Axis)
     Imager::ImgRaw     im
 Imager::ImgRaw
 i_scaleaxis(im,Value,Axis)
     Imager::ImgRaw     im
-             float     Value
+             double     Value
               int     Axis
 
 Imager::ImgRaw
 i_scale_nn(im,scx,scy)
     Imager::ImgRaw     im
               int     Axis
 
 Imager::ImgRaw
 i_scale_nn(im,scx,scy)
     Imager::ImgRaw     im
-             float     scx
-             float     scy
+             double    scx
+             double    scy
 
 Imager::ImgRaw
 i_scale_mixing(im, width, height)
     Imager::ImgRaw     im
 
 Imager::ImgRaw
 i_scale_mixing(im, width, height)
     Imager::ImgRaw     im
-              int     width
-              int     height
+              i_img_dim     width
+              i_img_dim     height
 
 Imager::ImgRaw
 i_haar(im)
 
 Imager::ImgRaw
 i_haar(im)
@@ -2367,8 +2332,8 @@ i_transform(im,opx,opy,parm)
     Imager::ImgRaw     im
              PREINIT:
              double* parm;
     Imager::ImgRaw     im
              PREINIT:
              double* parm;
-             int*    opx;
-             int*    opy;
+             int *opx;
+             int *opy;
              int     opxl;
              int     opyl;
              int     parmlen;
              int     opxl;
              int     opyl;
              int     parmlen;
@@ -2421,8 +2386,8 @@ i_transform2(sv_width,sv_height,channels,sv_ops,av_n_regs,av_c_regs,av_in_imgs)
        AV *av_in_imgs
        int channels
             PREINIT:
        AV *av_in_imgs
        int channels
             PREINIT:
-             int width;
-             int height;
+             i_img_dim width;
+             i_img_dim height;
             struct rm_op *ops;
             STRLEN ops_len;
             int ops_count;
             struct rm_op *ops;
             STRLEN ops_len;
             int ops_count;
@@ -2526,9 +2491,9 @@ i_bumpmap(im,bump,channel,light_x,light_y,strength)
     Imager::ImgRaw     im
     Imager::ImgRaw     bump
                int     channel
     Imager::ImgRaw     im
     Imager::ImgRaw     bump
                int     channel
-               int     light_x
-               int     light_y
-               int     strength
+         i_img_dim     light_x
+         i_img_dim     light_y
+         i_img_dim     strength
 
 
 void
 
 
 void
@@ -2536,11 +2501,11 @@ i_bumpmap_complex(im,bump,channel,tx,ty,Lx,Ly,Lz,cd,cs,n,Ia,Il,Is)
     Imager::ImgRaw     im
     Imager::ImgRaw     bump
                int     channel
     Imager::ImgRaw     im
     Imager::ImgRaw     bump
                int     channel
-               int     tx
-               int     ty
-             float     Lx
-             float     Ly
-             float     Lz
+               i_img_dim     tx
+               i_img_dim     ty
+             double     Lx
+             double     Ly
+             double     Lz
              float     cd
              float     cs
              float     n
              float     cd
              float     cs
              float     n
@@ -2558,14 +2523,14 @@ i_postlevels(im,levels)
 void
 i_mosaic(im,size)
     Imager::ImgRaw     im
 void
 i_mosaic(im,size)
     Imager::ImgRaw     im
-               int     size
+         i_img_dim     size
 
 void
 i_watermark(im,wmark,tx,ty,pixdiff)
     Imager::ImgRaw     im
     Imager::ImgRaw     wmark
 
 void
 i_watermark(im,wmark,tx,ty,pixdiff)
     Imager::ImgRaw     im
     Imager::ImgRaw     wmark
-               int     tx
-               int     ty
+               i_img_dim     tx
+               i_img_dim     ty
                int     pixdiff
 
 
                int     pixdiff
 
 
@@ -2597,8 +2562,8 @@ i_gradgen(im, ...)
     Imager::ImgRaw     im
       PREINIT:
        int num;
     Imager::ImgRaw     im
       PREINIT:
        int num;
-       int *xo;
-       int *yo;
+       i_img_dim *xo;
+       i_img_dim *yo;
         i_color *ival;
        int dmeasure;
        int i;
         i_color *ival;
        int dmeasure;
        int i;
@@ -2624,12 +2589,12 @@ i_gradgen(im, ...)
        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");
        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(int) * num );
-       yo = mymalloc( sizeof(int) * num );
+       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++) {
        ival = mymalloc( sizeof(i_color) * num );
        for(i = 0; i<num; i++) {
-         xo[i]   = (int)SvIV(* av_fetch(axx, i, 0));
-         yo[i]   = (int)SvIV(* av_fetch(ayy, i, 0));
+         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);
           sv = *av_fetch(ac, i, 0);
          if ( !sv_derived_from(sv, "Imager::Color") ) {
            free(axx); free(ayy); free(ac);
@@ -2745,8 +2710,8 @@ i_nearest_color(im, ...)
     Imager::ImgRaw     im
       PREINIT:
        int num;
     Imager::ImgRaw     im
       PREINIT:
        int num;
-       int *xo;
-       int *yo;
+       i_img_dim *xo;
+       i_img_dim *yo;
         i_color *ival;
        int dmeasure;
        int i;
         i_color *ival;
        int dmeasure;
        int i;
@@ -2772,12 +2737,12 @@ i_nearest_color(im, ...)
        num = num <= av_len(ac) ? num : av_len(ac);
        num++; 
        if (num < 2) croak("Usage: i_nearest_color array refs must have more than 1 entry each");
        num = num <= av_len(ac) ? num : av_len(ac);
        num++; 
        if (num < 2) croak("Usage: i_nearest_color array refs must have more than 1 entry each");
-       xo = mymalloc( sizeof(int) * num );
-       yo = mymalloc( sizeof(int) * num );
+       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++) {
        ival = mymalloc( sizeof(i_color) * num );
        for(i = 0; i<num; i++) {
-         xo[i]   = (int)SvIV(* av_fetch(axx, i, 0));
-         yo[i]   = (int)SvIV(* av_fetch(ayy, i, 0));
+         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);
           sv = *av_fetch(ac, i, 0);
          if ( !sv_derived_from(sv, "Imager::Color") ) {
            free(axx); free(ayy); free(ac);
@@ -2849,8 +2814,8 @@ DSO_call(handle,func_index,hv)
 SV *
 i_get_pixel(im, x, y)
        Imager::ImgRaw im
 SV *
 i_get_pixel(im, x, y)
        Imager::ImgRaw im
-       int x
-       int y;
+       i_img_dim x
+       i_img_dim y;
       PREINIT:
         i_color *color;
       CODE:
       PREINIT:
         i_color *color;
       CODE:
@@ -2870,14 +2835,14 @@ i_get_pixel(im, x, y)
 int
 i_ppix(im, x, y, cl)
         Imager::ImgRaw im
 int
 i_ppix(im, x, y, cl)
         Imager::ImgRaw im
-        int x
-        int y
+        i_img_dim x
+        i_img_dim y
         Imager::Color cl
 
 Imager::ImgRaw
 i_img_pal_new(x, y, channels, maxpal)
         Imager::Color cl
 
 Imager::ImgRaw
 i_img_pal_new(x, y, channels, maxpal)
-       int     x
-        int    y
+       i_img_dim x
+        i_img_dim y
         int     channels
        int     maxpal
 
         int     channels
        int     maxpal
 
@@ -2910,9 +2875,9 @@ i_img_to_rgb(src)
 void
 i_gpal(im, l, r, y)
         Imager::ImgRaw  im
 void
 i_gpal(im, l, r, y)
         Imager::ImgRaw  im
-        int     l
-        int     r
-        int     y
+        i_img_dim     l
+        i_img_dim     r
+        i_img_dim     y
       PREINIT:
         i_palidx *work;
         int count, i;
       PREINIT:
         i_palidx *work;
         int count, i;
@@ -2942,20 +2907,19 @@ i_gpal(im, l, r, y)
 int
 i_ppal(im, l, y, ...)
         Imager::ImgRaw  im
 int
 i_ppal(im, l, y, ...)
         Imager::ImgRaw  im
-        int     l
-        int     y
+        i_img_dim     l
+        i_img_dim     y
       PREINIT:
         i_palidx *work;
       PREINIT:
         i_palidx *work;
-        int i;
+        i_img_dim i;
       CODE:
         if (items > 3) {
       CODE:
         if (items > 3) {
-          work = mymalloc(sizeof(i_palidx) * (items-3));
+          work = malloc_temp(aTHX_ sizeof(i_palidx) * (items-3));
           for (i=0; i < items-3; ++i) {
             work[i] = SvIV(ST(i+3));
           }
           validate_i_ppal(im, work, items - 3);
           RETVAL = i_ppal(im, l, l+items-3, y, work);
           for (i=0; i < items-3; ++i) {
             work[i] = SvIV(ST(i+3));
           }
           validate_i_ppal(im, work, items - 3);
           RETVAL = i_ppal(im, l, l+items-3, y, work);
-          myfree(work);
         }
         else {
           RETVAL = 0;
         }
         else {
           RETVAL = 0;
@@ -2966,8 +2930,8 @@ i_ppal(im, l, y, ...)
 int
 i_ppal_p(im, l, y, data)
         Imager::ImgRaw  im
 int
 i_ppal_p(im, l, y, data)
         Imager::ImgRaw  im
-        int     l
-        int     y
+        i_img_dim     l
+        i_img_dim     y
         SV *data
       PREINIT:
         i_palidx const *work;
         SV *data
       PREINIT:
         i_palidx const *work;
@@ -3116,14 +3080,14 @@ i_img_virtual(im)
 void
 i_gsamp(im, l, r, y, ...)
         Imager::ImgRaw im
 void
 i_gsamp(im, l, r, y, ...)
         Imager::ImgRaw im
-        int l
-        int r
-        int y
+        i_img_dim l
+        i_img_dim r
+        i_img_dim y
       PREINIT:
         int *chans;
         int chan_count;
         i_sample_t *data;
       PREINIT:
         int *chans;
         int chan_count;
         i_sample_t *data;
-        int count, i;
+        i_img_dim count, i;
       PPCODE:
         if (items < 5)
           croak("No channel numbers supplied to g_samp()");
       PPCODE:
         if (items < 5)
           croak("No channel numbers supplied to g_samp()");
@@ -3156,17 +3120,17 @@ i_gsamp(im, l, r, y, ...)
 undef_neg_int
 i_gsamp_bits(im, l, r, y, bits, target, offset, ...)
         Imager::ImgRaw im
 undef_neg_int
 i_gsamp_bits(im, l, r, y, bits, target, offset, ...)
         Imager::ImgRaw im
-        int l
-        int r
-        int y
+        i_img_dim l
+        i_img_dim r
+        i_img_dim y
        int bits
        AV *target
        int bits
        AV *target
-       int offset
+       STRLEN offset
       PREINIT:
         int *chans;
         int chan_count;
         unsigned *data;
       PREINIT:
         int *chans;
         int chan_count;
         unsigned *data;
-        int count, i;
+        i_img_dim count, i;
       CODE:
        i_clear_error();
         if (items < 8)
       CODE:
        i_clear_error();
         if (items < 8)
@@ -3194,8 +3158,8 @@ i_gsamp_bits(im, l, r, y, bits, target, offset, ...)
 undef_neg_int
 i_psamp_bits(im, l, y, bits, channels_sv, data_av, data_offset = 0, pixel_count = -1)
         Imager::ImgRaw im
 undef_neg_int
 i_psamp_bits(im, l, y, bits, channels_sv, data_av, data_offset = 0, pixel_count = -1)
         Imager::ImgRaw im
-        int l
-        int y
+        i_img_dim l
+        i_img_dim y
        int bits
        SV *channels_sv
        AV *data_av
        int bits
        SV *channels_sv
        AV *data_av
@@ -3204,10 +3168,10 @@ i_psamp_bits(im, l, y, bits, channels_sv, data_av, data_offset = 0, pixel_count
       PREINIT:
        int chan_count;
        int *channels;
       PREINIT:
        int chan_count;
        int *channels;
-       int data_count;
-       int data_used;
+       STRLEN data_count;
+       size_t data_used;
        unsigned *data;
        unsigned *data;
-       int i;
+       ptrdiff_t i;
       CODE:
        i_clear_error();
        if (SvOK(channels_sv)) {
       CODE:
        i_clear_error();
        if (SvOK(channels_sv)) {
@@ -3259,10 +3223,10 @@ i_psamp_bits(im, l, y, bits, channels_sv, data_av, data_offset = 0, pixel_count
 Imager::ImgRaw
 i_img_masked_new(targ, mask, x, y, w, h)
         Imager::ImgRaw targ
 Imager::ImgRaw
 i_img_masked_new(targ, mask, x, y, w, h)
         Imager::ImgRaw targ
-        int x
-        int y
-        int w
-        int h
+        i_img_dim x
+        i_img_dim y
+        i_img_dim w
+        i_img_dim h
       PREINIT:
         i_img *mask;
       CODE:
       PREINIT:
         i_img *mask;
       CODE:
@@ -3282,13 +3246,13 @@ i_img_masked_new(targ, mask, x, y, w, h)
 int
 i_plin(im, l, y, ...)
         Imager::ImgRaw  im
 int
 i_plin(im, l, y, ...)
         Imager::ImgRaw  im
-        int     l
-        int     y
+        i_img_dim     l
+        i_img_dim     y
       PREINIT:
         i_color *work;
       PREINIT:
         i_color *work;
-        int i;
+        STRLEN i;
         STRLEN len;
         STRLEN len;
-        int count;
+        size_t count;
       CODE:
         if (items > 3) {
           if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
       CODE:
         if (items > 3) {
           if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
@@ -3326,21 +3290,21 @@ i_plin(im, l, y, ...)
 int
 i_ppixf(im, x, y, cl)
         Imager::ImgRaw im
 int
 i_ppixf(im, x, y, cl)
         Imager::ImgRaw im
-        int x
-        int y
+        i_img_dim x
+        i_img_dim y
         Imager::Color::Float cl
 
 void
 i_gsampf(im, l, r, y, ...)
         Imager::ImgRaw im
         Imager::Color::Float cl
 
 void
 i_gsampf(im, l, r, y, ...)
         Imager::ImgRaw im
-        int l
-        int r
-        int y
+        i_img_dim l
+        i_img_dim r
+        i_img_dim y
       PREINIT:
         int *chans;
         int chan_count;
         i_fsample_t *data;
       PREINIT:
         int *chans;
         int chan_count;
         i_fsample_t *data;
-        int count, i;
+        i_img_dim count, i;
       PPCODE:
         if (items < 5)
           croak("No channel numbers supplied to g_sampf()");
       PPCODE:
         if (items < 5)
           croak("No channel numbers supplied to g_sampf()");
@@ -3373,13 +3337,13 @@ i_gsampf(im, l, r, y, ...)
 int
 i_plinf(im, l, y, ...)
         Imager::ImgRaw  im
 int
 i_plinf(im, l, y, ...)
         Imager::ImgRaw  im
-        int     l
-        int     y
+        i_img_dim     l
+        i_img_dim     y
       PREINIT:
         i_fcolor *work;
       PREINIT:
         i_fcolor *work;
-        int i;
+        i_img_dim i;
         STRLEN len;
         STRLEN len;
-        int count;
+        size_t count;
       CODE:
         if (items > 3) {
           if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
       CODE:
         if (items > 3) {
           if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
@@ -3418,8 +3382,8 @@ i_plinf(im, l, y, ...)
 SV *
 i_gpixf(im, x, y)
        Imager::ImgRaw im
 SV *
 i_gpixf(im, x, y)
        Imager::ImgRaw im
-       int x
-       int y;
+       i_img_dim x
+       i_img_dim y;
       PREINIT:
         i_fcolor *color;
       CODE:
       PREINIT:
         i_fcolor *color;
       CODE:
@@ -3438,12 +3402,12 @@ i_gpixf(im, x, y)
 void
 i_glin(im, l, r, y)
         Imager::ImgRaw im
 void
 i_glin(im, l, r, y)
         Imager::ImgRaw im
-        int l
-        int r
-        int y
+        i_img_dim l
+        i_img_dim r
+        i_img_dim y
       PREINIT:
         i_color *vals;
       PREINIT:
         i_color *vals;
-        int count, i;
+        i_img_dim count, i;
       PPCODE:
         if (l < r) {
           vals = mymalloc((r-l) * sizeof(i_color));
       PPCODE:
         if (l < r) {
           vals = mymalloc((r-l) * sizeof(i_color));
@@ -3470,12 +3434,12 @@ i_glin(im, l, r, y)
 void
 i_glinf(im, l, r, y)
         Imager::ImgRaw im
 void
 i_glinf(im, l, r, y)
         Imager::ImgRaw im
-        int l
-        int r
-        int y
+        i_img_dim l
+        i_img_dim r
+        i_img_dim y
       PREINIT:
         i_fcolor *vals;
       PREINIT:
         i_fcolor *vals;
-        int count, i;
+        i_img_dim count, i;
         i_fcolor zero;
       PPCODE:
        for (i = 0; i < MAXCHANNELS; ++i)
         i_fcolor zero;
       PPCODE:
        for (i = 0; i < MAXCHANNELS; ++i)
@@ -3505,8 +3469,8 @@ i_glinf(im, l, r, y)
 
 Imager::ImgRaw
 i_img_16_new(x, y, ch)
 
 Imager::ImgRaw
 i_img_16_new(x, y, ch)
-        int x
-        int y
+        i_img_dim x
+        i_img_dim y
         int ch
 
 Imager::ImgRaw
         int ch
 
 Imager::ImgRaw
@@ -3515,10 +3479,14 @@ i_img_to_rgb16(im)
 
 Imager::ImgRaw
 i_img_double_new(x, y, ch)
 
 Imager::ImgRaw
 i_img_double_new(x, y, ch)
-        int x
-        int y
+        i_img_dim x
+        i_img_dim y
         int ch
 
         int ch
 
+Imager::ImgRaw
+i_img_to_drgb(im)
+       Imager::ImgRaw im
+
 undef_int
 i_tags_addn(im, name, code, idata)
         Imager::ImgRaw im
 undef_int
 i_tags_addn(im, name, code, idata)
         Imager::ImgRaw im
@@ -3690,6 +3658,7 @@ IFILL_DESTROY(fill)
 int
 IFILL_CLONE_SKIP(...)
     CODE:
 int
 IFILL_CLONE_SKIP(...)
     CODE:
+        (void)items; /* avoid unused warning for XS variable */
         RETVAL = 1;
     OUTPUT:
         RETVAL
         RETVAL = 1;
     OUTPUT:
         RETVAL
@@ -3712,8 +3681,8 @@ i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy)
         Imager::Color bg
         int combine
         int hatch
         Imager::Color bg
         int combine
         int hatch
-        int dx
-        int dy
+        i_img_dim dx
+        i_img_dim dy
       PREINIT:
         unsigned char *cust_hatch;
         STRLEN len;
       PREINIT:
         unsigned char *cust_hatch;
         STRLEN len;
@@ -3733,8 +3702,8 @@ i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy)
         Imager::Color::Float bg
         int combine
         int hatch
         Imager::Color::Float bg
         int combine
         int hatch
-        int dx
-        int dy
+        i_img_dim dx
+        i_img_dim dy
       PREINIT:
         unsigned char *cust_hatch;
         STRLEN len;
       PREINIT:
         unsigned char *cust_hatch;
         STRLEN len;
@@ -3751,8 +3720,8 @@ i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy)
 Imager::FillHandle
 i_new_fill_image(src, matrix, xoff, yoff, combine)
         Imager::ImgRaw src
 Imager::FillHandle
 i_new_fill_image(src, matrix, xoff, yoff, combine)
         Imager::ImgRaw src
-        int xoff
-        int yoff
+        i_img_dim xoff
+        i_img_dim yoff
         int combine
       PREINIT:
         double matrix[9];
         int combine
       PREINIT:
         double matrix[9];
@@ -3795,9 +3764,9 @@ i_int_hlines_testing()
 
 Imager::Internal::Hlines
 i_int_hlines_new(start_y, count_y, start_x, count_x)
 
 Imager::Internal::Hlines
 i_int_hlines_new(start_y, count_y, start_x, count_x)
-       int start_y
+       i_img_dim start_y
        int count_y
        int count_y
-       int start_x
+       i_img_dim start_x
        int count_x
 
 Imager::Internal::Hlines
        int count_x
 
 Imager::Internal::Hlines
@@ -3807,9 +3776,9 @@ i_int_hlines_new_img(im)
 void
 i_int_hlines_add(hlines, y, minx, width)
        Imager::Internal::Hlines hlines
 void
 i_int_hlines_add(hlines, y, minx, width)
        Imager::Internal::Hlines hlines
-       int y
-       int minx
-       int width
+       i_img_dim y
+       i_img_dim minx
+       i_img_dim width
 
 void
 i_int_hlines_DESTROY(hlines)
 
 void
 i_int_hlines_DESTROY(hlines)
@@ -3821,7 +3790,6 @@ i_int_hlines_dump(hlines)
 
 int
 i_int_hlines_CLONE_SKIP(cls)
 
 int
 i_int_hlines_CLONE_SKIP(cls)
-       SV *cls
 
 #endif
 
 
 #endif