]> git.imager.perl.org - imager.git/blobdiff - Imager.xs
link zlib in using the default installed library name on Win32 instead of as libz.
[imager.git] / Imager.xs
index ce82ff3a72eb171d34a5bd370e8cebceda0d3927..d2ea2cf768691b3c806ac7c9f4d82e681ba4526e 100644 (file)
--- a/Imager.xs
+++ b/Imager.xs
@@ -4,6 +4,8 @@ extern "C" {
 #include "EXTERN.h"
 #include "perl.h"
 #include "XSUB.h"
+#define NEED_newRV_noinc
+#define NEED_sv_2pv_nolen
 #include "ppport.h"
 #ifdef __cplusplus
 }
@@ -323,9 +325,14 @@ static ssize_t call_reader(struct cbdata *cbd, void *buf, size_t size,
 static ssize_t write_flush(struct cbdata *cbd) {
   ssize_t result;
 
-  result = call_writer(cbd, cbd->buffer, cbd->used);
-  cbd->used = 0;
-  return 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) {
@@ -380,7 +387,6 @@ static ssize_t io_writer(void *p, void const *data, size_t size) {
     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 */
-        *(char *)0 = 0;
       if (io_seeker(p, cbd->where - cbd->used, SEEK_CUR) < 0) {
         return -1;
       }
@@ -390,8 +396,9 @@ static ssize_t io_writer(void *p, void const *data, size_t size) {
   }
   cbd->writing = 1;
   if (cbd->used && cbd->used + size > cbd->maxlength) {
-    if (write_flush(cbd) <= 0) {
-      return 0;
+    int write_res = write_flush(cbd);
+    if (write_res <= 0) {
+      return write_res;
     }
     cbd->used = 0;
   }
@@ -404,11 +411,13 @@ static ssize_t io_writer(void *p, void const *data, size_t size) {
   return call_writer(cbd, data, size);
 }
 
-static ssize_t io_reader(void *p, void *data, size_t size) {
+static ssize_t 
+io_reader(void *p, void *data, size_t size) {
   struct cbdata *cbd = p;
   ssize_t total;
   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;
@@ -428,7 +437,7 @@ static ssize_t io_reader(void *p, void *data, size_t size) {
   size  -= cbd->used - cbd->where;
   out   += cbd->used - cbd->where;
   if (size < sizeof(cbd->buffer)) {
-    int did_read;
+    int did_read = 0;
     int copy_size;
     while (size
           && (did_read = call_reader(cbd, cbd->buffer, size, 
@@ -443,6 +452,8 @@ static ssize_t io_reader(void *p, void *data, size_t size) {
       total += copy_size;
       size  -= copy_size;
     }
+    if (did_read < 0)
+      return -1;
   }
   else {
     /* just read the rest - too big for our buffer*/
@@ -452,6 +463,8 @@ static ssize_t io_reader(void *p, void *data, size_t size) {
       total += did_read;
       out   += did_read;
     }
+    if (did_read < 0)
+      return -1;
   }
 
   return total;
@@ -801,6 +814,29 @@ load_fount_segs(AV *asegs, int *count) {
   return segs;
 }
 
+/* validates the indexes supplied to i_ppal
+
+i_ppal() doesn't do that for speed, but I'm not comfortable doing that
+for calls from perl.
+
+*/
+static void
+validate_i_ppal(i_img *im, i_palidx const *indexes, int count) {
+  int color_count = i_colorcount(im);
+  int i;
+
+  if (color_count == -1)
+    croak("i_plin() called on direct color image");
+  
+  for (i = 0; i < count; ++i) {
+    if (indexes[i] >= color_count) {
+      croak("i_plin() called with out of range color index %d (max %d)",
+        indexes[i], color_count-1);
+    }
+  }
+}
+
+
 /* I don't think ICLF_* names belong at the C interface
    this makes the XS code think we have them, to let us avoid 
    putting function bodies in the XS code
@@ -1118,6 +1154,7 @@ i_io_write(ig, data_sv)
 #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        
@@ -1126,7 +1163,7 @@ i_io_write(ig, data_sv)
       OUTPUT:
        RETVAL
 
-SV *
+void
 i_io_read(ig, buffer_sv, size)
        Imager::IO ig
        SV *buffer_sv
@@ -1134,8 +1171,8 @@ i_io_read(ig, buffer_sv, size)
       PREINIT:
         void *buffer;
        int result;
-      CODE:
-        if (size < 0)
+      PPCODE:
+        if (size <= 0)
          croak("size negative in call to i_io_read()");
         /* prevent an undefined value warning if they supplied an 
           undef buffer.
@@ -1148,18 +1185,41 @@ i_io_read(ig, buffer_sv, size)
 #endif
        buffer = SvGROW(buffer_sv, size+1);
         result = i_io_read(ig, buffer, size);
-        if (result < 0) {
-         RETVAL = &PL_sv_undef;
+        if (result >= 0) {
+         SvCUR_set(buffer_sv, result);
+         *SvEND(buffer_sv) = '\0';
+         SvPOK_only(buffer_sv);
+         EXTEND(SP, 1);
+         PUSHs(sv_2mortal(newSViv(result)));
        }
-       else {
+       ST(1) = buffer_sv;
+       SvSETMAGIC(ST(1));
+
+void
+i_io_read2(ig, size)
+       Imager::IO ig
+       int size
+      PREINIT:
+       SV *buffer_sv;
+        void *buffer;
+       int result;
+      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);
+        if (result >= 0) {
          SvCUR_set(buffer_sv, result);
          *SvEND(buffer_sv) = '\0';
          SvPOK_only(buffer_sv);
-         RETVAL = newSViv(result); /* XS will mortal this */
+         EXTEND(SP, 1);
+         PUSHs(sv_2mortal(buffer_sv));
        }
-      OUTPUT:
-       RETVAL
-       buffer_sv
+       else {
+          /* discard it */
+         SvREFCNT_dec(buffer_sv);
+        }
 
 int
 i_io_seek(ig, position, whence)
@@ -1167,7 +1227,7 @@ i_io_seek(ig, position, whence)
        long position
        int whence
 
-void
+int
 i_io_close(ig)
        Imager::IO ig
 
@@ -1498,6 +1558,22 @@ i_flood_cfill(im,seedx,seedy,fill)
               int     seedy
      Imager::FillHandle     fill
 
+undef_int
+i_flood_fill_border(im,seedx,seedy,dcol, border)
+    Imager::ImgRaw     im
+              int     seedx
+              int     seedy
+     Imager::Color     dcol
+     Imager::Color     border
+
+undef_int
+i_flood_cfill_border(im,seedx,seedy,fill, border)
+    Imager::ImgRaw     im
+              int     seedx
+              int     seedy
+     Imager::FillHandle     fill
+     Imager::Color     border
+
 
 void
 i_copyto(im,src,x1,y1,x2,y2,tx,ty)
@@ -2897,6 +2973,12 @@ i_scale_nn(im,scx,scy)
              float     scx
              float     scy
 
+Imager::ImgRaw
+i_scale_mixing(im, width, height)
+    Imager::ImgRaw     im
+              int     width
+              int     height
+
 Imager::ImgRaw
 i_haar(im)
     Imager::ImgRaw     im
@@ -3489,6 +3571,7 @@ i_ppal(im, l, y, ...)
           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);
         }
@@ -3498,6 +3581,28 @@ i_ppal(im, l, y, ...)
       OUTPUT:
         RETVAL
 
+int
+i_ppal_p(im, l, y, data)
+        Imager::ImgRaw  im
+        int     l
+        int     y
+        SV *data
+      PREINIT:
+        i_palidx const *work;
+        STRLEN len;
+      CODE:
+        work = (i_palidx const *)SvPV(data, len);
+        len /= sizeof(i_palidx);
+        if (len > 0) {
+          validate_i_ppal(im, work, len);
+          RETVAL = i_ppal(im, l, l+len, y, work);
+        }
+        else {
+          RETVAL = 0;
+        }
+      OUTPUT:
+        RETVAL
+
 SV *
 i_addcolors(im, ...)
         Imager::ImgRaw  im
@@ -4083,51 +4188,77 @@ i_tags_count(im)
 #ifdef HAVE_WIN32
 
 void
-i_wf_bbox(face, size, text)
+i_wf_bbox(face, size, text_sv, utf8=0)
        char *face
        int size
-       char *text
+       SV *text_sv
+       int utf8
       PREINIT:
        int cords[BOUNDING_BOX_COUNT];
         int rc, i;
+       char const *text;
+         STRLEN text_len;
       PPCODE:
-        if (rc = i_wf_bbox(face, size, text, strlen(text), cords)) {
+        text = SvPV(text_sv, text_len);
+#ifdef SvUTF8
+        if (SvUTF8(text_sv))
+          utf8 = 1;
+#endif
+        if (rc = i_wf_bbox(face, size, text, text_len, cords, utf8)) {
           EXTEND(SP, rc);  
           for (i = 0; i < rc; ++i) 
             PUSHs(sv_2mortal(newSViv(cords[i])));
         }
 
 undef_int
-i_wf_text(face, im, tx, ty, cl, size, text, align, aa)
+i_wf_text(face, im, tx, ty, cl, size, text_sv, align, aa, utf8 = 0)
        char *face
        Imager::ImgRaw im
        int tx
        int ty
        Imager::Color cl
        int size
-       char *text
+       SV *text_sv
        int align
        int aa
+       int utf8
+      PREINIT:
+       char const *text;
+       STRLEN text_len;
       CODE:
-       RETVAL = i_wf_text(face, im, tx, ty, cl, size, text, strlen(text), 
-                          align, aa);
+        text = SvPV(text_sv, text_len);
+#ifdef SvUTF8
+        if (SvUTF8(text_sv))
+          utf8 = 1;
+#endif
+       RETVAL = i_wf_text(face, im, tx, ty, cl, size, text, text_len, 
+                          align, aa, utf8);
       OUTPUT:
        RETVAL
 
 undef_int
-i_wf_cp(face, im, tx, ty, channel, size, text, align, aa)
+i_wf_cp(face, im, tx, ty, channel, size, text_sv, align, aa, utf8 = 0)
        char *face
        Imager::ImgRaw im
        int tx
        int ty
        int channel
        int size
-       char *text
+       SV *text_sv
        int align
        int aa
+       int utf8
+      PREINIT:
+       char const *text;
+       STRLEN text_len;
       CODE:
-       RETVAL = i_wf_cp(face, im, tx, ty, channel, size, text, strlen(text), 
-                        align, aa);
+        text = SvPV(text_sv, text_len);
+#ifdef SvUTF8
+        if (SvUTF8(text_sv))
+          utf8 = 1;
+#endif
+       RETVAL = i_wf_cp(face, im, tx, ty, channel, size, text, text_len, 
+                        align, aa, utf8);
       OUTPUT:
        RETVAL
 
@@ -4281,7 +4412,7 @@ i_ft2_text(font, im, tx, ty, cl, cheight, cwidth, text, align, aa, vlayout, utf8
         RETVAL
 
 undef_int
-i_ft2_cp(font, im, tx, ty, channel, cheight, cwidth, text, align, aa, vlayout, utf8)
+i_ft2_cp(font, im, tx, ty, channel, cheight, cwidth, text_sv, align, aa, vlayout, utf8)
         Imager::Font::FT2 font
         Imager::ImgRaw im
         int tx
@@ -4289,18 +4420,22 @@ i_ft2_cp(font, im, tx, ty, channel, cheight, cwidth, text, align, aa, vlayout, u
         int channel
         double cheight
         double cwidth
-        char *text
+        SV *text_sv
         int align
         int aa
         int vlayout
         int utf8
+      PREINIT:
+       char const *text;
+       STRLEN len;
       CODE:
 #ifdef SvUTF8
         if (SvUTF8(ST(7)))
           utf8 = 1;
 #endif
+       text = SvPV(text_sv, len);
         RETVAL = i_ft2_cp(font, im, tx, ty, channel, cheight, cwidth, text,
-                          strlen(text), align, aa, vlayout, 1);
+                          len, align, aa, vlayout, 1);
       OUTPUT:
         RETVAL