#include "imperl.h"
+#define ARRAY_COUNT(array) (sizeof(array)/sizeof(*array))
+
/*
Context object management
const i_fsample_t *samples;
} i_fsample_list;
+typedef struct {
+ size_t count;
+ const i_polygon_t *polygons;
+} i_polygon_list;
+
/*
Allocate memory that will be discarded when mortals are discarded.
static i_color
S_sv_to_i_color(pTHX_ SV *sv, const char *pname) {
if (!sv_derived_from(sv, "Imager::Color")) {
- croak("%s: not a color object");
+ croak("%s: not a color object", pname);
}
return *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
}
UTIL_table_t i_UTIL_table={getstr,getint,getdouble,getvoid,getobj};
-void my_SvREFCNT_dec(void *p) {
- dTHX;
- SvREFCNT_dec((SV*)p);
+static void
+free_buffer(void *p) {
+ myfree(p);
}
if (SvOK(cbd->closecb)) {
dSP;
I32 count;
- SV *sv;
ENTER;
SAVETMPS;
SPAGAIN;
- sv = POPs;
- success = SvTRUE(sv);
+ if (count) {
+ SV *sv = POPs;
+ success = SvTRUE(sv);
+ }
+ else
+ success = 0;
PUTBACK;
FREETMPS;
myfree(cbd);
}
-static i_io_glue_t *
-do_io_new_buffer(pTHX_ SV *data_sv) {
- const char *data;
- STRLEN length;
+static bool
+im_SvREFSCALAR(SV *sv) {
+ svtype type = SvTYPE(sv);
+
+ switch (type) {
+ case SVt_PV:
+ case SVt_PVIV:
+ case SVt_PVNV:
+ case SVt_PVMG:
+ case SVt_IV:
+ case SVt_NV:
+ case SVt_PVLV:
+#if PERL_VERSION > 10
+ case SVt_REGEXP:
+#endif
+ return 1;
- data = SvPVbyte(data_sv, length);
- SvREFCNT_inc(data_sv);
- return io_new_buffer(data, length, my_SvREFCNT_dec, data_sv);
+ default:
+ return 0;
+ }
}
static const char *
}
}
+static i_io_glue_t *
+do_io_new_buffer(pTHX_ SV *data_sv) {
+ const char *data;
+ char *data_copy;
+ STRLEN length;
+ SV *sv;
+
+ SvGETMAGIC(data_sv);
+ if (SvROK(data_sv)) {
+ if (im_SvREFSCALAR(SvRV(data_sv))) {
+ sv = SvRV(data_sv);
+ }
+ else {
+ i_push_errorf(0, "data is not a scalar or a reference to scalar");
+ return NULL;
+ }
+ }
+ else {
+ sv = data_sv;
+ }
+
+ /* previously this would keep the SV around, but this is unsafe in
+ many ways, so always copy the bytes */
+ data = SvPVbyte(sv, length);
+ data_copy = mymalloc(length);
+ memcpy(data_copy, data, length);
+ return io_new_buffer(data_copy, length, free_buffer, data_copy);
+}
+
static i_io_glue_t *
do_io_new_cb(pTHX_ SV *writecb, SV *readcb, SV *seekcb, SV *closecb) {
struct cbdata *cbd;
char *name;
int value;
};
-static int lookup_name(struct value_name *names, int count, char *name, int def_value)
+static int lookup_name(const struct value_name *names, int count, char *name, int def_value)
{
int i;
for (i = 0; i < count; ++i)
}
}
+static struct value_name
+poly_fill_mode_names[] =
+{
+ { "evenodd", i_pfm_evenodd },
+ { "nonzero", i_pfm_nonzero }
+};
+
+static i_poly_fill_mode_t
+S_get_poly_fill_mode(pTHX_ SV *sv) {
+ if (looks_like_number(sv)) {
+ IV work = SvIV(sv);
+ if (work < (IV)i_pfm_evenodd || work > (IV)i_pfm_nonzero)
+ work = (IV)i_pfm_evenodd;
+ return (i_poly_fill_mode_t)work;
+ }
+ else {
+ return (i_poly_fill_mode_t)lookup_name
+ (poly_fill_mode_names, ARRAY_COUNT(poly_fill_mode_names),
+ SvPV_nolen(sv), i_pfm_evenodd);
+ }
+}
+
+static void
+S_get_polygon_list(pTHX_ i_polygon_list *polys, SV *sv) {
+ AV *av;
+ int i;
+ i_polygon_t *s;
+
+ SvGETMAGIC(sv);
+ if (!SvOK(sv) || !SvROK(sv) || SvTYPE(SvRV(sv)) != SVt_PVAV)
+ croak("polys must be an arrayref");
+
+ av = (AV*)SvRV(sv);
+ polys->count = av_len(av) + 1;
+ if (polys->count < 1)
+ croak("polypolygon: no polygons provided");
+ s = malloc_temp(aTHX_ sizeof(i_polygon_t) * polys->count);
+ for (i = 0; i < polys->count; ++i) {
+ SV **poly_sv = av_fetch(av, i, 0);
+ AV *poly_av;
+ SV **x_sv, **y_sv;
+ AV *x_av, *y_av;
+ double *x_data, *y_data;
+ ssize_t j;
+ ssize_t point_count;
+
+ if (!poly_sv)
+ croak("poly_polygon: nothing found for polygon %d", i);
+ /* needs to be another av */
+ SvGETMAGIC(*poly_sv);
+ if (!SvOK(*poly_sv) || !SvROK(*poly_sv) || SvTYPE(SvRV(*poly_sv)) != SVt_PVAV)
+ croak("poly_polygon: polygon %d isn't an arrayref", i);
+ poly_av = (AV*)SvRV(*poly_sv);
+ /* with two elements */
+ if (av_len(poly_av) != 1)
+ croak("poly_polygon: polygon %d should contain two arrays", i);
+ x_sv = av_fetch(poly_av, 0, 0);
+ y_sv = av_fetch(poly_av, 1, 0);
+ if (!x_sv)
+ croak("poly_polygon: polygon %d has no x elements", i);
+ if (!y_sv)
+ croak("poly_polygon: polygon %d has no y elements", i);
+ SvGETMAGIC(*x_sv);
+ SvGETMAGIC(*y_sv);
+ if (!SvOK(*x_sv) || !SvROK(*x_sv) || SvTYPE(SvRV(*x_sv)) != SVt_PVAV)
+ croak("poly_polygon: polygon %d x elements isn't an array", i);
+ if (!SvOK(*y_sv) || !SvROK(*y_sv) || SvTYPE(SvRV(*y_sv)) != SVt_PVAV)
+ croak("poly_polygon: polygon %d y elements isn't an array", i);
+ x_av = (AV*)SvRV(*x_sv);
+ y_av = (AV*)SvRV(*y_sv);
+ if (av_len(x_av) != av_len(y_av))
+ croak("poly_polygon: polygon %d x and y arrays different lengths", i+1);
+ point_count = av_len(x_av)+1;
+ x_data = malloc_temp(aTHX_ sizeof(double) * point_count * 2);
+ y_data = x_data + point_count;
+
+ for (j = 0; j < point_count; ++j) {
+ SV **x_item_sv = av_fetch(x_av, j, 0);
+ SV **y_item_sv = av_fetch(y_av, j, 0);
+ x_data[j] = x_item_sv ? SvNV(*x_item_sv) : 0;
+ y_data[j] = y_item_sv ? SvNV(*y_item_sv) : 0;
+ }
+ s[i].x = x_data;
+ s[i].y = y_data;
+ s[i].count = point_count;
+ }
+ polys->polygons = s;
+}
+
/* loads the segments of a fountain fill into an array */
static i_fountain_seg *
load_fount_segs(pTHX_ AV *asegs, int *count) {
io_new_buffer(data_sv)
SV *data_sv
CODE:
+ i_clear_error();
RETVAL = do_io_new_buffer(aTHX_ data_sv);
+ if (!RETVAL)
+ XSRETURN(0);
OUTPUT:
RETVAL
SV *readcb;
SV *seekcb;
SV *closecb;
- int maxwrite;
CODE:
RETVAL = do_io_new_cb(aTHX_ writecb, readcb, seekcb, closecb);
OUTPUT:
io_new_buffer(class, data_sv)
SV *data_sv
CODE:
+ i_clear_error();
RETVAL = do_io_new_buffer(aTHX_ data_sv);
+ if (!RETVAL)
+ XSRETURN(0);
OUTPUT:
RETVAL
if (size <= 0)
croak("size negative in call to i_io_raw_read()");
/* prevent an undefined value warning if they supplied an
- undef buffer.
+ undef buffer.
Orginally conditional on !SvOK(), but this will prevent the
- downgrade from croaking */
- sv_setpvn(buffer_sv, "", 0);
+ downgrade from croaking */
+ sv_setpvn(buffer_sv, "", 0);
#ifdef SvUTF8
- if (SvUTF8(buffer_sv))
+ if (SvUTF8(buffer_sv))
sv_utf8_downgrade(buffer_sv, FALSE);
#endif
buffer = SvGROW(buffer_sv, size+1);
if (size <= 0)
croak("size negative in call to i_io_read()");
/* prevent an undefined value warning if they supplied an
- undef buffer.
+ undef buffer.
Orginally conditional on !SvOK(), but this will prevent the
- downgrade from croaking */
- sv_setpvn(buffer_sv, "", 0);
+ downgrade from croaking */
+ sv_setpvn(buffer_sv, "", 0);
#ifdef SvUTF8
- if (SvUTF8(buffer_sv))
+ if (SvUTF8(buffer_sv))
sv_utf8_downgrade(buffer_sv, FALSE);
#endif
buffer = SvGROW(buffer_sv, size+1);
i_img_get_height(im)
Imager::ImgRaw im
+int
+i_img_color_model(im)
+ Imager::ImgRaw im
+
+int
+i_img_color_channels(im)
+ Imager::ImgRaw im
+
+int
+i_img_alpha_channel(im)
+ Imager::ImgRaw im
+ CODE:
+ if (!i_img_alpha_channel(im, &RETVAL))
+ XSRETURN(0);
+ OUTPUT:
+ RETVAL
void
i_img_is_monochrome(im)
double rad
Imager::Color val
+void
+i_circle_aa_fill(im,x,y,rad,fill)
+ Imager::ImgRaw im
+ double x
+ double y
+ double rad
+ Imager::FillHandle fill
+
int
i_circle_out(im,x,y,rad,val)
Imager::ImgRaw im
void
-i_bezier_multi(im,xc,yc,val)
+i_bezier_multi(im,x,y,val)
Imager::ImgRaw im
- Imager::Color val
- PREINIT:
- double *x,*y;
- int len;
- AV *av1;
- AV *av2;
- SV *sv1;
- SV *sv2;
- int i;
- PPCODE:
- ICL_info(val);
- if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_bezier_multi must be a reference to an array\n");
- if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_bezier_multi must be a reference to an array\n");
- if (!SvROK(ST(2))) croak("Imager: Parameter 2 to i_bezier_multi must be a reference to an array\n");
- if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 2 to i_bezier_multi must be a reference to an array\n");
- av1=(AV*)SvRV(ST(1));
- av2=(AV*)SvRV(ST(2));
- if (av_len(av1) != av_len(av2)) croak("Imager: x and y arrays to i_bezier_multi must be equal length\n");
- len=av_len(av1)+1;
- x=mymalloc( len*sizeof(double) );
- y=mymalloc( len*sizeof(double) );
- for(i=0;i<len;i++) {
- sv1=(*(av_fetch(av1,i,0)));
- sv2=(*(av_fetch(av2,i,0)));
- x[i]=(double)SvNV(sv1);
- y[i]=(double)SvNV(sv2);
- }
- i_bezier_multi(im,len,x,y,val);
- myfree(x);
- myfree(y);
-
+ double *x
+ double *y
+ Imager::Color val
+ PREINIT:
+ STRLEN size_x;
+ STRLEN size_y;
+ PPCODE:
+ if (size_x != size_y)
+ croak("Imager: x and y arrays to i_bezier_multi must be equal length\n");
+ i_bezier_multi(im,size_x,x,y,val);
int
-i_poly_aa(im,x,y,val)
+i_poly_aa_m(im,x,y,mode,val)
Imager::ImgRaw im
double *x
double *y
+ i_poly_fill_mode_t mode
Imager::Color val
PREINIT:
STRLEN size_x;
CODE:
if (size_x != size_y)
croak("Imager: x and y arrays to i_poly_aa must be equal length\n");
- RETVAL = i_poly_aa(im, size_x, x, y, val);
+ RETVAL = i_poly_aa_m(im, size_x, x, y, mode, val);
OUTPUT:
RETVAL
int
-i_poly_aa_cfill(im, x, y, fill)
+i_poly_aa_cfill_m(im, x, y, mode, fill)
Imager::ImgRaw im
double *x
double *y
+ i_poly_fill_mode_t mode
Imager::FillHandle fill
PREINIT:
STRLEN size_x;
CODE:
if (size_x != size_y)
croak("Imager: x and y arrays to i_poly_aa_cfill must be equal length\n");
- RETVAL = i_poly_aa_cfill(im, size_x, x, y, fill);
+ RETVAL = i_poly_aa_cfill_m(im, size_x, x, y, mode, fill);
OUTPUT:
RETVAL
+int
+i_poly_poly_aa(im, polys, mode, color)
+ Imager::ImgRaw im
+ i_polygon_list polys
+ i_poly_fill_mode_t mode
+ Imager::Color color
+ CODE:
+ RETVAL = i_poly_poly_aa(im, polys.count, polys.polygons, mode, color);
+ OUTPUT:
+ RETVAL
+
+int
+i_poly_poly_aa_cfill(im, polys, mode, fill)
+ Imager::ImgRaw im
+ i_polygon_list polys
+ i_poly_fill_mode_t mode
+ Imager::FillHandle fill
+ CODE:
+ RETVAL = i_poly_poly_aa_cfill(im, polys.count, polys.polygons, mode, fill);
+ OUTPUT:
+ RETVAL
+
undef_int
i_flood_fill(im,seedx,seedy,dcol)
Imager::ImgRaw im
AV *pmaps_av
PREINIT:
unsigned int mask = 0;
- AV *avmain;
AV *avsub;
SV **temp;
int len;
float usat
float skew
+void
+i_autolevels_mono(im,lsat,usat)
+ Imager::ImgRaw im
+ float lsat
+ float usat
+
void
i_radnoise(im,xo,yo,rscale,ascale)
Imager::ImgRaw im
i_img_dim y;
CODE:
RETVAL = (i_color *)mymalloc(sizeof(i_color));
+ memset(RETVAL, 0, sizeof(*RETVAL));
if (i_gpix(im, x, y, RETVAL) != 0) {
myfree(RETVAL);
XSRETURN_UNDEF;
OUTPUT:
RETVAL
-SV *
+Imager::Color::Float
i_gpixf(im, x, y)
Imager::ImgRaw im
i_img_dim x
i_img_dim y;
- PREINIT:
- i_fcolor *color;
CODE:
- color = (i_fcolor *)mymalloc(sizeof(i_fcolor));
- if (i_gpixf(im, x, y, color) == 0) {
- RETVAL = NEWSV(0,0);
- sv_setref_pv(RETVAL, "Imager::Color::Float", (void *)color);
- }
- else {
- myfree(color);
- RETVAL = &PL_sv_undef;
+ RETVAL = (i_fcolor *)mymalloc(sizeof(i_fcolor));
+ memset(RETVAL, 0, sizeof(*RETVAL));
+ if (i_gpixf(im, x, y, RETVAL) != 0) {
+ myfree(RETVAL);
+ XSRETURN_UNDEF;
}
OUTPUT:
RETVAL
Imager::ImgRaw im
undef_int
-i_tags_addn(im, name, code, idata)
+i_tags_addn(im, name_sv, code, idata)
Imager::ImgRaw im
+ SV *name_sv
int code
int idata
PREINIT:
char *name;
STRLEN len;
CODE:
- if (SvOK(ST(1)))
- name = SvPV(ST(1), len);
+ SvGETMAGIC(name_sv);
+ if (SvOK(name_sv))
+ name = SvPV_nomg(name_sv, len);
else
name = NULL;
RETVAL = i_tags_addn(&im->tags, name, code, idata);
RETVAL
undef_int
-i_tags_add(im, name, code, data, idata)
+i_tags_add(im, name_sv, code, data_sv, idata)
Imager::ImgRaw im
+ SV *name_sv
int code
+ SV *data_sv
int idata
PREINIT:
char *name;
char *data;
STRLEN len;
CODE:
- if (SvOK(ST(1)))
- name = SvPV(ST(1), len);
+ SvGETMAGIC(name_sv);
+ if (SvOK(name_sv))
+ name = SvPV_nomg(name_sv, len);
else
name = NULL;
- if (SvOK(ST(3)))
- data = SvPV(ST(3), len);
+ SvGETMAGIC(data_sv);
+ if (SvOK(data_sv))
+ data = SvPV(data_sv, len);
else {
data = NULL;
len = 0;
OUTPUT:
RETVAL
-SV *
+SysRet
i_tags_find(im, name, start)
Imager::ImgRaw im
char *name
int entry;
CODE:
if (i_tags_find(&im->tags, name, start, &entry)) {
- if (entry == 0)
- RETVAL = newSVpv("0 but true", 0);
- else
- RETVAL = newSViv(entry);
+ RETVAL = entry;
} else {
- RETVAL = &PL_sv_undef;
+ XSRETURN_UNDEF;
}
OUTPUT:
RETVAL
-SV *
+SysRet
i_tags_findn(im, code, start)
Imager::ImgRaw im
int code
int entry;
CODE:
if (i_tags_findn(&im->tags, code, start, &entry)) {
- if (entry == 0)
- RETVAL = newSVpv("0 but true", 0);
- else
- RETVAL = newSViv(entry);
+ RETVAL = entry;
}
else {
- RETVAL = &PL_sv_undef;
+ XSRETURN_UNDEF;
}
OUTPUT:
RETVAL
int combine
Imager::FillHandle
-i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy)
+i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch_sv, dx, dy)
Imager::Color fg
Imager::Color bg
int combine
int hatch
+ SV *cust_hatch_sv
i_img_dim dx
i_img_dim dy
PREINIT:
unsigned char *cust_hatch;
STRLEN len;
CODE:
- if (SvOK(ST(4))) {
- cust_hatch = (unsigned char *)SvPV(ST(4), len);
+ SvGETMAGIC(cust_hatch_sv);
+ if (SvOK(cust_hatch_sv)) {
+ cust_hatch = (unsigned char *)SvPV_nomg(cust_hatch_sv, len);
}
else
cust_hatch = NULL;
RETVAL
Imager::FillHandle
-i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy)
+i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch_sv, dx, dy)
Imager::Color::Float fg
Imager::Color::Float bg
int combine
int hatch
+ SV *cust_hatch_sv
i_img_dim dx
i_img_dim dy
PREINIT:
unsigned char *cust_hatch;
STRLEN len;
CODE:
- if (SvOK(ST(4))) {
- cust_hatch = (unsigned char *)SvPV(ST(4), len);
+ SvGETMAGIC(cust_hatch_sv);
+ if (SvOK(cust_hatch_sv)) {
+ cust_hatch = (unsigned char *)SvPV(cust_hatch_sv, len);
}
else
cust_hatch = NULL;
RETVAL
Imager::FillHandle
-i_new_fill_image(src, matrix, xoff, yoff, combine)
+i_new_fill_image(src, matrix_sv, xoff, yoff, combine)
Imager::ImgRaw src
+ SV *matrix_sv
i_img_dim xoff
i_img_dim yoff
int combine
SV *sv1;
int i;
CODE:
- if (!SvOK(ST(1))) {
+ SvGETMAGIC(matrix_sv);
+ if (!SvOK(matrix_sv)) {
matrixp = NULL;
}
else {
- if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV)
- croak("i_new_fill_image: parameter must be an arrayref");
- av=(AV*)SvRV(ST(1));
+ if (!SvROK(matrix_sv) || SvTYPE(SvRV(matrix_sv)) != SVt_PVAV)
+ croak("i_new_fill_image: matrix parameter must be an arrayref or undef");
+ av=(AV*)SvRV(matrix_sv);
len=av_len(av)+1;
if (len > 9)
len = 9;