#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
+#define NEED_newRV_noinc
+#define NEED_sv_2pv_nolen
#include "ppport.h"
#ifdef __cplusplus
}
#include "regmach.h"
#include "imextdef.h"
-typedef io_glue* Imager__IO;
-
#if i_int_hlines_testing()
#include "imageri.h"
#endif
static void
-log_entry(char *string, int level) {
+i_log_entry(char *string, int level) {
mm_log((level, string));
}
FREETMPS;
LEAVE;
- return success ? size : 0;
+ return success ? size : -1;
}
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) {
static ssize_t io_writer(void *p, void const *data, size_t size) {
struct cbdata *cbd = p;
- /*printf("io_writer(%p, %p, %u)\n", p, data, size);*/
+ /* 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 */
- *(char *)0 = 0;
if (io_seeker(p, cbd->where - cbd->used, SEEK_CUR) < 0) {
return -1;
}
}
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;
}
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;
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,
total += copy_size;
size -= copy_size;
}
+ if (did_read < 0)
+ return -1;
}
else {
/* just read the rest - too big for our buffer*/
total += did_read;
out += did_read;
}
+ if (did_read < 0)
+ return -1;
}
return total;
}
-static void io_closer(void *p) {
+static int io_closer(void *p) {
struct cbdata *cbd = p;
if (cbd->writing && cbd->used > 0) {
- write_flush(cbd);
+ if (write_flush(cbd) < 0)
+ return -1;
cbd->writing = 0;
}
FREETMPS;
LEAVE;
}
+
+ return 0;
}
static void io_destroyer(void *p) {
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
#define i_exif_enabled() 0
#endif
+/* trying to use more C style names, map them here */
+#define i_io_DESTROY(ig) io_glue_destroy(ig)
+
MODULE = Imager PACKAGE = Imager::Color PREFIX = ICL_
Imager::Color
PUSHs(sv_2mortal(newSViv(bytes)));
}
-MODULE = Imager PACKAGE = Imager::IO PREFIX = io_glue_
+MODULE = Imager PACKAGE = Imager::IO PREFIX = i_io_
+
+int
+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_read(ig, buffer_sv, size)
+ Imager::IO ig
+ SV *buffer_sv
+ int size
+ PREINIT:
+ void *buffer;
+ int 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
+ 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);
+ EXTEND(SP, 1);
+ PUSHs(sv_2mortal(buffer_sv));
+ }
+ else {
+ /* discard it */
+ SvREFCNT_dec(buffer_sv);
+ }
+
+int
+i_io_seek(ig, position, whence)
+ Imager::IO ig
+ long position
+ int whence
+
+int
+i_io_close(ig)
+ Imager::IO ig
void
-io_glue_DESTROY(ig)
+i_io_DESTROY(ig)
Imager::IO ig
-
MODULE = Imager PACKAGE = Imager
PROTOTYPES: ENABLE
-
-
void
i_list_formats()
PREINIT:
int channels
void
-m_init_log(name,level)
+i_init_log(name,level)
char* name
int level
void
-log_entry(string,level)
+i_log_entry(string,level)
char* string
int level
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)
char const *text;
STRLEN work_len;
int len;
- int outsize;
char name[255];
PPCODE:
#ifdef SvUTF8
--len;
}
EXTEND(SP, 1);
- if ((outsize = i_t1_glyph_name(handle, ch, name, sizeof(name))) != 0) {
+ if (i_t1_glyph_name(handle, ch, name, sizeof(name))) {
PUSHs(sv_2mortal(newSVpv(name, 0)));
}
else {
#endif
-char *
+const char *
i_test_format_probe(ig, length)
Imager::IO ig
int length
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
Imager::ImgRaw im2
int mindist
-void
+undef_int
i_fountain(im, xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
Imager::ImgRaw im
double xa
asegs = (AV *)SvRV(ST(10));
segs = load_fount_segs(asegs, &count);
- i_fountain(im, xa, ya, xb, yb, type, repeat, combine, super_sample,
- ssample_param, count, segs);
+ RETVAL = i_fountain(im, xa, ya, xb, yb, type, repeat, combine,
+ super_sample, ssample_param, count, segs);
myfree(segs);
+ OUTPUT:
+ RETVAL
Imager::FillHandle
i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
}
void
+i_clear_error()
+
+void
+i_push_error(code, msg)
+ int code
+ const char *msg
+
+undef_int
i_nearest_color(im, ...)
Imager::ImgRaw im
PREINIT:
}
ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
}
- i_nearest_color(im, num, xo, yo, ival, dmeasure);
-
-
-
+ RETVAL = i_nearest_color(im, num, xo, yo, ival, dmeasure);
+ OUTPUT:
+ RETVAL
void
malloc_state()
-void
-hashinfo(hv)
- PREINIT:
- HV* hv;
- int stuff;
- PPCODE:
- if (!SvROK(ST(0))) croak("Imager: Parameter 0 must be a reference to a hash\n");
- hv=(HV*)SvRV(ST(0));
- if (SvTYPE(hv)!=SVt_PVHV) croak("Imager: Parameter 0 must be a reference to a hash\n");
- if (getint(hv,"stuff",&stuff)) printf("ok: %d\n",stuff); else printf("key doesn't exist\n");
- if (getint(hv,"stuff2",&stuff)) printf("ok: %d\n",stuff); else printf("key doesn't exist\n");
-
void
DSO_open(filename)
char* filename
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);
}
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
chans[i] = SvIV(ST(i+4));
data = mymalloc(sizeof(i_fsample_t) * (r-l) * chan_count);
count = i_gsampf(im, l, r, y, data, chans, chan_count);
+ myfree(chans);
if (GIMME_V == G_ARRAY) {
EXTEND(SP, count);
for (i = 0; i < count; ++i)
EXTEND(SP, 1);
PUSHs(sv_2mortal(newSVpv((void *)data, count * sizeof(i_fsample_t))));
}
+ myfree(data);
}
else {
if (GIMME_V != G_ARRAY) {
#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
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
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
char const *text;
STRLEN work_len;
int len;
- int outsize;
char name[255];
PPCODE:
#ifdef SvUTF8
--len;
}
EXTEND(SP, 1);
- if ((outsize = i_ft2_glyph_name(handle, ch, name, sizeof(name),
- reliable_only)) != 0) {
+ if (i_ft2_glyph_name(handle, ch, name, sizeof(name),
+ reliable_only)) {
PUSHs(sv_2mortal(newSVpv(name, 0)));
}
else {