X-Git-Url: http://git.imager.perl.org/imager.git/blobdiff_plain/a556912d911731f0da70f94d373374a238471f77..6a160bce857f1d340fa20c1d4a67d242b5e098f1:/Imager.xs diff --git a/Imager.xs b/Imager.xs index b0c674ea..2b757fed 100644 --- a/Imager.xs +++ b/Imager.xs @@ -7,6 +7,7 @@ extern "C" { #include "XSUB.h" #define NEED_newRV_noinc #define NEED_sv_2pv_nolen +#define NEED_sv_2pvbyte #include "ppport.h" #ifdef __cplusplus } @@ -20,6 +21,8 @@ extern "C" { #include "regmach.h" #include "imextdef.h" #include "imextpltypes.h" +#include "imperlio.h" +#include #if i_int_hlines_testing() #include "imageri.h" @@ -27,13 +30,139 @@ extern "C" { #include "imperl.h" +#ifndef SV_COW_DROP_PV +#define SV_COW_DROP_PV +#endif + +/* + +Context object management + +*/ + +typedef im_context_t Imager__Context; + +#define im_context_DESTROY(ctx) im_context_refdec((ctx), "DESTROY") + +#ifdef PERL_IMPLICIT_CONTEXT + +#define MY_CXT_KEY "Imager::_context" XS_VERSION + +typedef struct { + im_context_t ctx; +} my_cxt_t; + +START_MY_CXT + +im_context_t fallback_context; + +static void +start_context(pTHX) { + dMY_CXT; + MY_CXT.ctx = im_context_new(); + sv_setref_pv(get_sv("Imager::_context", GV_ADD), "Imager::Context", MY_CXT.ctx); + + /* Ideally we'd free this reference, but the error message memory + was never released on exit, so the associated memory here is reasonable + to keep. + With logging enabled we always need at least one context, since + objects may be released fairly late and attempt to get the log file. + */ + im_context_refinc(MY_CXT.ctx, "start_context"); + fallback_context = MY_CXT.ctx; +} + +static im_context_t +perl_get_context(void) { + dTHX; + dMY_CXT; + + return MY_CXT.ctx ? MY_CXT.ctx : fallback_context; +} + +#else + +static im_context_t perl_context; + +static void +start_context(pTHX) { + perl_context = im_context_new(); + im_context_refinc(perl_context, "start_context"); +} + +static im_context_t +perl_get_context(void) { + return perl_context; +} + +#endif + +/* used to represent channel lists parameters */ +typedef struct i_channel_list_tag { + int *channels; + int count; +} i_channel_list; + +typedef struct { + size_t count; + const i_sample_t *samples; +} i_sample_list; + +typedef struct { + size_t count; + const i_fsample_t *samples; +} i_fsample_list; + +/* + +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); +} + +static void * +calloc_temp(pTHX_ size_t size) { + void *result = malloc_temp(aTHX_ size); + memset(result, 0, size); + + return result; +} + +/* for use with the T_AVARRAY typemap */ +#define doublePtr(size) ((double *)calloc_temp(aTHX_ sizeof(double) * (size))) +#define SvDouble(sv, pname) (SvNV(sv)) + +#define intPtr(size) ((int *)calloc_temp(aTHX_ sizeof(int) * (size))) +#define SvInt(sv, pname) (SvIV(sv)) + +#define i_img_dimPtr(size) ((i_img_dim *)calloc_temp(aTHX_ sizeof(i_img_dim) * (size))) +#define SvI_img_dim(sv, pname) (SvIV(sv)) + +#define i_colorPtr(size) ((i_color *)calloc_temp(aTHX_ sizeof(i_color *) * (size))) + +#define SvI_color(sv, pname) S_sv_to_i_color(aTHX_ sv, pname) + +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", pname); + } + return *INT2PTR(i_color *, SvIV((SV *)SvRV(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; - 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; @@ -48,7 +177,7 @@ static int getint(void *hv_t,char *key,int *store) { 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; @@ -62,11 +191,11 @@ static int getdouble(void *hv_t,char* key,double *store) { 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); - *store=(float)SvNV(*svpp); + *store=(double)SvNV(*svpp); return 1; } @@ -75,7 +204,7 @@ static int getvoid(void *hv_t,char* key,void **store) { 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; @@ -90,7 +219,7 @@ static int getobj(void *hv_t,char *key,char *type,void **store) { 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; @@ -109,108 +238,26 @@ static int getobj(void *hv_t,char *key,char *type,void **store) { 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); } static void i_log_entry(char *string, int level) { - mm_log((level, string)); -} - - -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; + mm_log((level, "%s", string)); } -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; +static SV * +make_i_color_sv(pTHX_ const i_color *c) { 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); - + i_color *col = mymalloc(sizeof(i_color)); + *col = *c; + sv = sv_newmortal(); + sv_setref_pv(sv, "Imager::Color", (void *)col); - PUTBACK; - FREETMPS; - LEAVE; - - return success; + return sv; } #define CBDATA_BUFSIZE 8192 @@ -221,81 +268,22 @@ struct cbdata { 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; SV *data; dSP; - if (!SvOK(cbd->readcb)) + if (!SvOK(cbd->readcb)) { + mm_log((1, "read callback called but no readcb supplied\n")); + i_push_error(0, "read callback called but no readcb supplied"); return -1; + } ENTER; SAVETMPS; @@ -316,9 +304,10 @@ static ssize_t call_reader(struct cbdata *cbd, void *buf, size_t size, if (SvOK(data)) { STRLEN len; - char *ptr = SvPV(data, len); + char *ptr = SvPVbyte(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; @@ -334,41 +323,20 @@ static ssize_t call_reader(struct cbdata *cbd, void *buf, size_t size, 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; off_t result; dSP; - if (!SvOK(cbd->seekcb)) + if (!SvOK(cbd->seekcb)) { + mm_log((1, "seek callback called but no seekcb supplied\n")); + i_push_error(0, "seek callback called but no seekcb supplied"); 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); @@ -393,126 +361,83 @@ static off_t io_seeker(void *p, off_t offset, int whence) { 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; + 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; + if (!SvOK(cbd->writecb)) { + mm_log((1, "write callback called but no writecb supplied\n")); + i_push_error(0, "write callback called but no writecb supplied"); + return -1; } - /* it doesn't fit - just pass it up */ - return call_writer(cbd, data, size); + + 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; - 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; - 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; - } - return total; + return call_reader(cbd, data, size, size); } 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; + I32 count; ENTER; SAVETMPS; PUSHMARK(SP); PUTBACK; - perl_call_sv(cbd->closecb, G_VOID); + count = perl_call_sv(cbd->closecb, G_SCALAR); SPAGAIN; + + if (count) { + SV *sv = POPs; + success = SvTRUE(sv); + } + else + success = 0; + PUTBACK; FREETMPS; LEAVE; } - return 0; + return success ? 0 : -1; } static void io_destroyer(void *p) { @@ -526,6 +451,80 @@ static void io_destroyer(void *p) { myfree(cbd); } +static bool +im_SvREFSCALAR(SV *sv) { + svtype type = SvTYPE(sv); + return type == SVt_PV || type == SVt_PVIV || type == SVt_PVNV + || type == SVt_PVMG || type == SVt_IV || type == SVt_NV + || type == SVt_PVLV || type == SVt_REGEXP; +} + +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(data_sv)) { + sv = SvRV(data_sv); + } + else { + i_push_error(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 const char * +describe_sv(SV *sv) { + if (SvOK(sv)) { + if (SvROK(sv)) { + svtype type = SvTYPE(SvRV(sv)); + switch (type) { + case SVt_PVCV: return "CV"; + case SVt_PVGV: return "GV"; + case SVt_PVLV: return "LV"; + default: return "some reference"; + } + } + else { + return "non-reference scalar"; + } + } + else { + return "undef"; + } +} + +static i_io_glue_t * +do_io_new_cb(pTHX_ SV *writecb, SV *readcb, SV *seekcb, SV *closecb) { + struct cbdata *cbd; + + cbd = mymalloc(sizeof(struct cbdata)); + cbd->writecb = newSVsv(writecb); + cbd->readcb = newSVsv(readcb); + cbd->seekcb = newSVsv(seekcb); + cbd->closecb = newSVsv(closecb); + + mm_log((1, "do_io_new_cb(writecb %p (%s), readcb %p (%s), seekcb %p (%s), closecb %p (%s))\n", writecb, describe_sv(writecb), readcb, describe_sv(readcb), seekcb, describe_sv(seekcb), closecb, describe_sv(closecb))); + + return io_new_cb(cbd, io_reader, io_writer, io_seeker, io_closer, + io_destroyer); +} + struct value_name { char *name; int value; @@ -555,6 +554,9 @@ static struct value_name make_color_names[] = { "mediancut", mc_median_cut, }, { "mono", mc_mono, }, { "monochrome", mc_mono, }, + { "gray", mc_gray, }, + { "gray4", mc_gray4, }, + { "gray16", mc_gray16, }, }; static struct value_name translate_names[] = @@ -645,7 +647,7 @@ ip_handle_quant_opts(pTHX_ i_quantize *quant, HV *hv) sv = hv_fetch(hv, "make_colors", 11, 0); if (sv && *sv && (str = SvPV(*sv, len))) { quant->make_colors = - lookup_name(make_color_names, sizeof(make_color_names)/sizeof(*make_color_names), str, mc_addi); + lookup_name(make_color_names, sizeof(make_color_names)/sizeof(*make_color_names), str, mc_median_cut); } sv = hv_fetch(hv, "colors", 6, 0); if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) { @@ -853,7 +855,6 @@ validate_i_ppal(i_img *im, i_palidx const *indexes, int count) { } } - /* 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 @@ -861,17 +862,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) - -/* the m_init_log() function was called init_log(), renamed to reduce - potential naming conflicts */ -#define init_log m_init_log +#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 * -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); @@ -904,9 +906,9 @@ static int seg_compare(const void *vleft, const void *vright) { 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]; @@ -916,10 +918,10 @@ i_int_hlines_dump(i_int_hlines *hlines) { 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) { - 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"); } @@ -930,6 +932,24 @@ i_int_hlines_dump(i_int_hlines *hlines) { #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, @@ -942,6 +962,10 @@ static im_pl_ext_funcs im_perl_funcs = #define PERL_PL_SET_GLOBAL_CALLBACKS \ sv_setiv(get_sv(PERL_PL_FUNCTION_TABLE_NAME, 1), PTR2IV(&im_perl_funcs)); +#define IIM_new i_img_8_new +#define IIM_DESTROY i_img_destroy +typedef int SysRet; + #ifdef IMEXIF_ENABLE #define i_exif_enabled() 1 #else @@ -954,6 +978,11 @@ static im_pl_ext_funcs im_perl_funcs = #define i_img_get_width(im) ((im)->xsize) #define i_img_get_height(im) ((im)->ysize) +#define i_img_epsilonf() (DBL_EPSILON * 4) + +/* avoid some xsubpp strangeness */ +#define NEWLINE '\n' + MODULE = Imager PACKAGE = Imager::Color PREFIX = ICL_ Imager::Color @@ -990,10 +1019,10 @@ ICL_rgba(cl) Imager::Color cl PPCODE: EXTEND(SP, 4); - PUSHs(sv_2mortal(newSVnv(cl->rgba.r))); - PUSHs(sv_2mortal(newSVnv(cl->rgba.g))); - PUSHs(sv_2mortal(newSVnv(cl->rgba.b))); - PUSHs(sv_2mortal(newSVnv(cl->rgba.a))); + PUSHs(sv_2mortal(newSViv(cl->rgba.r))); + PUSHs(sv_2mortal(newSViv(cl->rgba.g))); + PUSHs(sv_2mortal(newSViv(cl->rgba.b))); + PUSHs(sv_2mortal(newSViv(cl->rgba.a))); Imager::Color i_hsv_to_rgb(c) @@ -1081,8 +1110,8 @@ MODULE = Imager PACKAGE = Imager::ImgRaw PREFIX = IIM_ Imager::ImgRaw IIM_new(x,y,ch) - int x - int y + i_img_dim x + i_img_dim y int ch void @@ -1105,14 +1134,13 @@ io_new_bufchain() Imager::IO -io_new_buffer(data) - char *data - PREINIT: - size_t length; +io_new_buffer(data_sv) + SV *data_sv CODE: - SvPV(ST(0), length); - SvREFCNT_inc(ST(0)); - RETVAL = io_new_buffer(data, length, my_SvREFCNT_dec, ST(0)); + i_clear_error(); + RETVAL = do_io_new_buffer(aTHX_ data_sv); + if (!RETVAL) + XSRETURN(0); OUTPUT: RETVAL @@ -1122,104 +1150,145 @@ io_new_cb(writecb, readcb, seekcb, closecb, maxwrite = CBDATA_BUFSIZE) SV *readcb; SV *seekcb; SV *closecb; - int maxwrite; - PREINIT: - struct cbdata *cbd; CODE: - cbd = mymalloc(sizeof(struct cbdata)); - SvREFCNT_inc(writecb); - cbd->writecb = writecb; - SvREFCNT_inc(readcb); - cbd->readcb = readcb; - SvREFCNT_inc(seekcb); - 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); + RETVAL = do_io_new_cb(aTHX_ writecb, readcb, seekcb, closecb); OUTPUT: RETVAL -void +SV * io_slurp(ig) Imager::IO ig PREINIT: unsigned char* data; size_t tlength; - PPCODE: + CODE: data = NULL; tlength = io_slurp(ig, &data); - EXTEND(SP,1); - PUSHs(sv_2mortal(newSVpv((char *)data,tlength))); + RETVAL = newSVpv((char *)data,tlength); myfree(data); + OUTPUT: + RETVAL 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: - 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))); - PUSHs(sv_2mortal(newSViv(bytes))); + PUSHs(sv_2mortal(newSVuv(bytes))); } +bool +i_int_check_image_file_limits(width, height, channels, sample_size) + i_img_dim width + i_img_dim height + int channels + size_t sample_size + PROTOTYPE: DISABLE + +MODULE = Imager PACKAGE = Imager::IO PREFIX = io_ + +Imager::IO +io_new_fd(class, fd) + int fd + CODE: + RETVAL = io_new_fd(fd); + OUTPUT: + RETVAL + +Imager::IO +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 + +Imager::IO +io_new_cb(class, writecb, readcb, seekcb, closecb) + SV *writecb; + SV *readcb; + SV *seekcb; + SV *closecb; + CODE: + RETVAL = do_io_new_cb(aTHX_ writecb, readcb, seekcb, closecb); + OUTPUT: + RETVAL + +Imager::IO +io_new_bufchain(class) + CODE: + RETVAL = io_new_bufchain(); + OUTPUT: + RETVAL + +Imager::IO +io__new_perlio(class, io) + PerlIO *io + CODE: + RETVAL = im_io_new_perlio(aTHX_ io); + OUTPUT: + RETVAL + +SV * +io_slurp(class, ig) + Imager::IO ig + PREINIT: + unsigned char* data; + size_t tlength; + CODE: + data = NULL; + tlength = io_slurp(ig, &data); + RETVAL = newSVpv((char *)data,tlength); + myfree(data); + OUTPUT: + RETVAL + MODULE = Imager PACKAGE = Imager::IO PREFIX = i_io_ -int -i_io_write(ig, data_sv) +IV +i_io_raw_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); + data = SvPVbyte(data_sv, size); + RETVAL = i_io_raw_write(ig, data, size); OUTPUT: RETVAL void -i_io_read(ig, buffer_sv, size) +i_io_raw_read(ig, buffer_sv, size) Imager::IO ig SV *buffer_sv - int size + IV size PREINIT: void *buffer; - int result; + 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 + croak("size negative in call to i_io_raw_read()"); + if (SvTHINKFIRST(buffer_sv)) + sv_force_normal_flags(buffer_sv, SV_COW_DROP_PV); + SvUPGRADE(buffer_sv, SVt_PV); 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'; @@ -1231,19 +1300,19 @@ i_io_read(ig, buffer_sv, size) SvSETMAGIC(ST(1)); void -i_io_read2(ig, size) +i_io_raw_read2(ig, size) Imager::IO ig - int size + IV size 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); - 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'; @@ -1256,14 +1325,14 @@ i_io_read2(ig, size) SvREFCNT_dec(buffer_sv); } -int -i_io_seek(ig, position, whence) +off_t +i_io_raw_seek(ig, position, whence) Imager::IO ig - long position + off_t position int whence int -i_io_close(ig) +i_io_raw_close(ig) Imager::IO ig void @@ -1273,10 +1342,172 @@ i_io_DESTROY(ig) int i_io_CLONE_SKIP(...) CODE: + (void)items; /* avoid unused warning for XS variable */ 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; + ssize_t result; + PPCODE: + buffer_sv = newSV(size+1); + 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()"); + if (SvTHINKFIRST(buffer_sv)) + sv_force_normal_flags(buffer_sv, SV_COW_DROP_PV); + SvUPGRADE(buffer_sv, SVt_PV); + 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; + ssize_t result; + PPCODE: + if (size == 0) + croak("size zero in call to 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); + } + +void +i_io_gets(ig, size = 8192, eol = NEWLINE) + Imager::IO ig + STRLEN size + int eol + PREINIT: + SV *buffer_sv; + void *buffer; + ssize_t result; + PPCODE: + if (size < 2) + croak("size too small in call to gets()"); + buffer_sv = sv_2mortal(newSV(size+1)); + buffer = SvPVX(buffer_sv); + result = i_io_gets(ig, buffer, size+1, eol); + if (result > 0) { + SvCUR_set(buffer_sv, result); + *SvEND(buffer_sv) = '\0'; + SvPOK_only(buffer_sv); + EXTEND(SP, 1); + PUSHs(buffer_sv); + } + +IV +i_io_write(ig, data_sv) + Imager::IO ig + SV *data_sv + PREINIT: + void *data; + STRLEN size; + CODE: + data = SvPVbyte(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 + +bool +i_io_set_buffered(ig, flag = 1) + Imager::IO ig + int flag + +bool +i_io_is_buffered(ig) + Imager::IO ig + +bool +i_io_eof(ig) + Imager::IO ig + +bool +i_io_error(ig) + Imager::IO ig + MODULE = Imager PACKAGE = Imager PROTOTYPES: ENABLE @@ -1293,67 +1524,43 @@ i_list_formats() PUSHs(sv_2mortal(newSVpv(item,0))); } -undef_int -i_has_format(frmt) - char* frmt - -Imager::ImgRaw -i_img_new() - -Imager::ImgRaw -i_img_empty(im,x,y) - Imager::ImgRaw im - int x - int y - -Imager::ImgRaw -i_img_empty_ch(im,x,y,ch) - Imager::ImgRaw im - int x - int y - 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 - int x - int y + i_img_dim x + i_img_dim y 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, level); + RETVAL = i_init_log(name, level); + OUTPUT: + RETVAL void i_log_entry(string,level) char* string int level - -void -i_img_exorcise(im) - Imager::ImgRaw im - -void -i_img_destroy(im) - Imager::ImgRaw im +int +i_log_enabled() void 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); @@ -1419,58 +1626,67 @@ i_img_is_monochrome(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 - 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 - 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 - 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 + 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 - 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 - 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 @@ -1486,11 +1702,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 - 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 @@ -1507,9 +1723,9 @@ i_arc_aa_cfill(im,x,y,rad,d1,d2,fill) 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 @@ -1534,8 +1750,8 @@ i_arc_out(im,x,y,rad,d1,d2,val) i_img_dim x i_img_dim y i_img_dim rad - float d1 - float d2 + double d1 + double d2 Imager::Color val int @@ -1544,146 +1760,84 @@ i_arc_out_aa(im,x,y,rad,d1,d2,val) i_img_dim x i_img_dim y i_img_dim rad - float d1 - float d2 + double d1 + double d2 Imager::Color val 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 9) - len = 9; - for (i = 0; i < len; ++i) { - sv1=(*(av_fetch(av,i,0))); - matrix[i] = SvNV(sv1); - } - for (; i < 9; ++i) - matrix[i] = 0; - /* extract the bg colors if any */ - /* yes, this is kind of strange */ - for (i = 4; i < items; ++i) { - sv1 = ST(i); - if (sv_derived_from(sv1, "Imager::Color")) { - IV tmp = SvIV((SV*)SvRV(sv1)); - backp = INT2PTR(i_color *, tmp); - } - else if (sv_derived_from(sv1, "Imager::Color::Float")) { - IV tmp = SvIV((SV*)SvRV(sv1)); - fbackp = INT2PTR(i_fcolor *, tmp); - } - } - RETVAL = i_matrix_transform_bg(im, xsize, ysize, matrix, backp, fbackp); - OUTPUT: - RETVAL + i_img_dim xsize + i_img_dim ysize + AV *matrix_av + PREINIT: + double matrix[9]; + STRLEN len; + SV *sv1; + int i; + i_color *backp = NULL; + i_fcolor *fbackp = NULL; + CODE: + len=av_len(matrix_av)+1; + if (len > 9) + len = 9; + for (i = 0; i < len; ++i) { + sv1=(*(av_fetch(matrix_av,i,0))); + matrix[i] = SvNV(sv1); + } + for (; i < 9; ++i) + matrix[i] = 0; + /* extract the bg colors if any */ + /* yes, this is kind of strange */ + for (i = 4; i < items; ++i) { + sv1 = ST(i); + if (sv_derived_from(sv1, "Imager::Color")) { + IV tmp = SvIV((SV*)SvRV(sv1)); + backp = INT2PTR(i_color *, tmp); + } + else if (sv_derived_from(sv1, "Imager::Color::Float")) { + IV tmp = SvIV((SV*)SvRV(sv1)); + fbackp = INT2PTR(i_fcolor *, tmp); + } + } + RETVAL = i_matrix_transform_bg(im, xsize, ysize, matrix, backp, fbackp); + OUTPUT: + RETVAL undef_int i_gaussian(im,stdev) @@ -1886,7 +2037,7 @@ i_gaussian(im,stdev) void i_unsharp_mask(im,stdev,scale) Imager::ImgRaw im - float stdev + double stdev double scale int @@ -1934,6 +2085,10 @@ i_convert(src, avmain) if (len > inchan) inchan = len; } + else { + i_push_errorf(0, "invalid matrix: element %d is not an array ref", j); + XSRETURN(0); + } } coeff = mymalloc(sizeof(double) * outchan * inchan); for (j = 0; j < outchan; ++j) { @@ -1955,46 +2110,44 @@ i_convert(src, avmain) RETVAL -void -i_map(im, pmaps) +undef_int +i_map(im, pmaps_av) Imager::ImgRaw im - PREINIT: - unsigned int mask = 0; - AV *avmain; - AV *avsub; - SV **temp; - int len; - int i, j; - unsigned char (*maps)[256]; - CODE: - if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV) - croak("i_map: parameter 2 must be an arrayref\n"); - avmain = (AV*)SvRV(ST(1)); - len = av_len(avmain)+1; - if (im->channels < len) len = im->channels; - - maps = mymalloc( len * sizeof(unsigned char [256]) ); - - for (j=0; j255) val = 255; - maps[j][i] = val; - } - } - } - i_map(im, maps, mask); - myfree(maps); - - + AV *pmaps_av + PREINIT: + unsigned int mask = 0; + AV *avsub; + SV **temp; + int len; + int i, j; + unsigned char (*maps)[256]; + CODE: + len = av_len(pmaps_av)+1; + if (im->channels < len) + len = im->channels; + maps = mymalloc( len * sizeof(unsigned char [256]) ); + for (j=0; j255) val = 255; + maps[j][i] = val; + } + } + } + i_map(im, maps, mask); + myfree(maps); + RETVAL = 1; + OUTPUT: + RETVAL float i_img_diff(im1,im2) @@ -2006,6 +2159,16 @@ i_img_diffd(im1,im2) Imager::ImgRaw im1 Imager::ImgRaw im2 +int +i_img_samef(im1, im2, epsilon = i_img_epsilonf(), what=NULL) + Imager::ImgRaw im1 + Imager::ImgRaw im2 + double epsilon + const char *what + +double +i_img_epsilonf() + bool _is_color_object(sv) SV* sv @@ -2017,9 +2180,6 @@ _is_color_object(sv) OUTPUT: RETVAL -#ifdef HAVE_LIBT1 -#endif - #ifdef HAVE_LIBTT @@ -2039,6 +2199,7 @@ TT_DESTROY(handle) int TT_CLONE_SKIP(...) CODE: + (void)items; /* avoid unused warning */ RETVAL = 1; OUTPUT: RETVAL @@ -2048,13 +2209,13 @@ MODULE = Imager PACKAGE = Imager undef_int -i_tt_text(handle,im,xb,yb,cl,points,str_sv,len_ignored,smooth,utf8,align=1) +i_tt_text(handle,im,xb,yb,cl,points,str_sv,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 - float points + double points SV * str_sv int smooth int utf8 @@ -2063,11 +2224,11 @@ i_tt_text(handle,im,xb,yb,cl,points,str_sv,len_ignored,smooth,utf8,align=1) char *str; STRLEN len; CODE: + str = SvPV(str_sv, len); #ifdef SvUTF8 if (SvUTF8(str_sv)) utf8 = 1; #endif - str = SvPV(str_sv, len); RETVAL = i_tt_text(handle, im, xb, yb, cl, points, str, len, smooth, utf8, align); OUTPUT: @@ -2075,13 +2236,13 @@ i_tt_text(handle,im,xb,yb,cl,points,str_sv,len_ignored,smooth,utf8,align=1) undef_int -i_tt_cp(handle,im,xb,yb,channel,points,str_sv,len_ignored,smooth,utf8,align=1) +i_tt_cp(handle,im,xb,yb,channel,points,str_sv,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 - float points + double points SV * str_sv int smooth int utf8 @@ -2090,11 +2251,11 @@ i_tt_cp(handle,im,xb,yb,channel,points,str_sv,len_ignored,smooth,utf8,align=1) char *str; STRLEN len; CODE: + str = SvPV(str_sv, len); #ifdef SvUTF8 if (SvUTF8(str_sv)) utf8 = 1; #endif - str = SvPV(str_sv, len); RETVAL = i_tt_cp(handle, im, xb, yb, channel, points, str, len, smooth, utf8, align); OUTPUT: @@ -2102,22 +2263,23 @@ 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) +i_tt_bbox(handle,point,str_sv,utf8) Imager::Font::TT handle - float point + double point 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; PPCODE: + str = SvPV(str_sv, len); #ifdef SvUTF8 if (SvUTF8(ST(2))) utf8 = 1; #endif - str = SvPV(str_sv, len); if ((rc=i_tt_bbox(handle,point,str,len,cords, utf8))) { EXTEND(SP, rc); for (i = 0; i < rc; ++i) { @@ -2134,20 +2296,21 @@ i_tt_has_chars(handle, text_sv, utf8) char const *text; STRLEN len; char *work; - int count; - int i; + size_t count; + size_t i; PPCODE: + i_clear_error(); + text = SvPV(text_sv, len); #ifdef SvUTF8 if (SvUTF8(text_sv)) utf8 = 1; #endif - text = SvPV(text_sv, len); work = mymalloc(len); count = i_tt_has_chars(handle, text, len, utf8, work); if (GIMME_V == G_ARRAY) { EXTEND(SP, count); for (i = 0; i < count; ++i) { - PUSHs(sv_2mortal(newSViv(work[i]))); + PUSHs(boolSV(work[i])); } } else { @@ -2165,12 +2328,12 @@ i_tt_face_name(handle) 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); - PUSHs(sv_2mortal(newSVpv(name, strlen(name)))); + PUSHs(sv_2mortal(newSVpv(name, len-1))); } void @@ -2182,14 +2345,16 @@ i_tt_glyph_name(handle, text_sv, utf8 = 0) char const *text; STRLEN work_len; size_t len; - int outsize; + size_t outsize; char name[255]; + SSize_t count = 0; PPCODE: + i_clear_error(); + text = SvPV(text_sv, work_len); #ifdef SvUTF8 if (SvUTF8(text_sv)) utf8 = 1; #endif - text = SvPV(text_sv, work_len); len = work_len; while (len) { unsigned long ch; @@ -2197,21 +2362,23 @@ i_tt_glyph_name(handle, text_sv, utf8 = 0) ch = i_utf8_advance(&text, &len); if (ch == ~0UL) { i_push_error(0, "invalid UTF8 character"); - break; + XSRETURN_EMPTY; } } else { ch = *text++; --len; } - EXTEND(SP, 1); + EXTEND(SP, count+1); if ((outsize = i_tt_glyph_name(handle, ch, name, sizeof(name))) != 0) { - PUSHs(sv_2mortal(newSVpv(name, 0))); + ST(count) = sv_2mortal(newSVpv(name, 0)); } else { - PUSHs(&PL_sv_undef); - } + ST(count) = &PL_sv_undef; + } + ++count; } + XSRETURN(count); #endif @@ -2258,8 +2425,8 @@ i_writeppm_wiol(im, 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 @@ -2307,20 +2474,20 @@ i_readtga_wiol(ig, length) 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 - float scx - float scy + double scx + double scy 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) @@ -2349,56 +2516,25 @@ i_get_anonymous_color_histo(im, maxc = 0x40000000) XSRETURN(col_cnt); -Imager::ImgRaw -i_transform(im,opx,opy,parm) +void +i_transform(im, opx, opy, parm) Imager::ImgRaw im + int *opx + int *opy + double *parm PREINIT: - double* parm; - int* opx; - int* opy; - int opxl; - int opyl; - int parmlen; - AV* av; - SV* sv1; - int i; - CODE: - if (!SvROK(ST(1))) croak("Imager: Parameter 1 must be a reference to an array\n"); - if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to an array\n"); - if (!SvROK(ST(3))) croak("Imager: Parameter 3 must be a reference to an array\n"); - if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 must be a reference to an array\n"); - if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 2 must be a reference to an array\n"); - if (SvTYPE(SvRV(ST(3))) != SVt_PVAV) croak("Imager: Parameter 3 must be a reference to an array\n"); - av=(AV*)SvRV(ST(1)); - opxl=av_len(av)+1; - opx=mymalloc( opxl*sizeof(int) ); - for(i=0;i 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); - myfree(work); } else { RETVAL = 0; @@ -2953,8 +3084,8 @@ i_ppal(im, l, y, ...) 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; @@ -2972,11 +3103,10 @@ i_ppal_p(im, l, y, data) OUTPUT: RETVAL -SV * +SysRet i_addcolors(im, ...) Imager::ImgRaw im PREINIT: - int index; i_color *colors; int i; CODE: @@ -2994,17 +3124,7 @@ i_addcolors(im, ...) croak("i_addcolor: pixels must be Imager::Color objects"); } } - index = i_addcolors(im, colors, items-1); - myfree(colors); - if (index == 0) { - RETVAL = newSVpv("0 but true", 0); - } - else if (index == -1) { - RETVAL = &PL_sv_undef; - } - else { - RETVAL = newSViv(index); - } + RETVAL = i_addcolors(im, colors, items-1); OUTPUT: RETVAL @@ -3036,33 +3156,24 @@ i_setcolors(im, index, ...) RETVAL void -i_getcolors(im, index, ...) +i_getcolors(im, index, count=1) Imager::ImgRaw im int index + int count PREINIT: i_color *colors; - int count = 1; int i; PPCODE: - if (items > 3) - croak("i_getcolors: too many arguments"); - if (items == 3) - count = SvIV(ST(2)); if (count < 1) croak("i_getcolors: count must be positive"); - colors = mymalloc(sizeof(i_color) * count); + colors = malloc_temp(aTHX_ sizeof(i_color) * count); if (i_getcolors(im, index, colors, count)) { + EXTEND(SP, count); for (i = 0; i < count; ++i) { - i_color *pv; - SV *sv = sv_newmortal(); - pv = mymalloc(sizeof(i_color)); - *pv = colors[i]; - sv_setref_pv(sv, "Imager::Color", (void *)pv); + SV *sv = make_i_color_sv(aTHX_ colors+i); PUSHs(sv); } } - myfree(colors); - undef_neg_int i_colorcount(im) @@ -3072,18 +3183,13 @@ undef_neg_int i_maxcolors(im) Imager::ImgRaw im -SV * +i_palidx i_findcolor(im, color) Imager::ImgRaw im Imager::Color color - PREINIT: - i_palidx index; CODE: - if (i_findcolor(im, color, &index)) { - RETVAL = newSViv(index); - } - else { - RETVAL = &PL_sv_undef; + if (!i_findcolor(im, color, &RETVAL)) { + XSRETURN_UNDEF; } OUTPUT: RETVAL @@ -3101,27 +3207,19 @@ i_img_virtual(im) Imager::ImgRaw im void -i_gsamp(im, l, r, y, ...) +i_gsamp(im, l, r, y, channels) Imager::ImgRaw im - int l - int r - int y + i_img_dim l + i_img_dim r + i_img_dim y + i_channel_list channels 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()"); if (l < r) { - chan_count = items - 4; - chans = mymalloc(sizeof(int) * chan_count); - for (i = 0; i < chan_count; ++i) - chans[i] = SvIV(ST(i+4)); - data = mymalloc(sizeof(i_sample_t) * (r-l) * chan_count); /* XXX: memleak? */ - count = i_gsamp(im, l, r, y, data, chans, chan_count); - myfree(chans); + data = mymalloc(sizeof(i_sample_t) * (r-l) * channels.count); + count = i_gsamp(im, l, r, y, data, channels.channels, channels.count); if (GIMME_V == G_ARRAY) { EXTEND(SP, count); for (i = 0; i < count; ++i) @@ -3135,37 +3233,30 @@ i_gsamp(im, l, r, y, ...) } else { if (GIMME_V != G_ARRAY) { - EXTEND(SP, 1); - PUSHs(&PL_sv_undef); + XSRETURN_UNDEF; } } undef_neg_int -i_gsamp_bits(im, l, r, y, bits, target, offset, ...) +i_gsamp_bits(im, l, r, y, bits, target, offset, channels) 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 offset + STRLEN offset + i_channel_list channels PREINIT: - int *chans; - int chan_count; unsigned *data; - int count, i; + i_img_dim count, i; CODE: i_clear_error(); if (items < 8) croak("No channel numbers supplied to g_samp()"); if (l < r) { - chan_count = items - 7; - chans = mymalloc(sizeof(int) * chan_count); - for (i = 0; i < chan_count; ++i) - chans[i] = SvIV(ST(i+7)); - data = mymalloc(sizeof(unsigned) * (r-l) * chan_count); - count = i_gsamp_bits(im, l, r, y, data, chans, chan_count, bits); - myfree(chans); + data = mymalloc(sizeof(unsigned) * (r-l) * channels.count); + count = i_gsamp_bits(im, l, r, y, data, channels.channels, channels.count, bits); for (i = 0; i < count; ++i) { av_store(target, i+offset, newSVuv(data[i])); } @@ -3179,77 +3270,123 @@ i_gsamp_bits(im, l, r, y, bits, target, offset, ...) RETVAL undef_neg_int -i_psamp_bits(im, l, y, bits, channels_sv, data_av, data_offset = 0, pixel_count = -1) +i_psamp_bits(im, l, y, bits, channels, 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 + i_channel_list channels AV *data_av - int data_offset - int pixel_count + i_img_dim data_offset + i_img_dim pixel_count PREINIT: - int chan_count; - int *channels; - int data_count; - int data_used; + STRLEN data_count; + size_t data_used; unsigned *data; - int i; + ptrdiff_t i; CODE: i_clear_error(); - if (SvOK(channels_sv)) { - AV *channels_av; - if (!SvROK(channels_sv) || SvTYPE(SvRV(channels_sv)) != SVt_PVAV) { - croak("channels is not an array ref"); - } - channels_av = (AV *)SvRV(channels_sv); - chan_count = av_len(channels_av) + 1; - if (chan_count < 1) { - croak("i_psamp_bits: no channels provided"); - } - channels = mymalloc(sizeof(int) * chan_count); - for (i = 0; i < chan_count; ++i) - channels[i] = SvIV(*av_fetch(channels_av, i, 0)); - } - else { - chan_count = im->channels; - channels = NULL; - } data_count = av_len(data_av) + 1; if (data_offset < 0) { - croak("data_offset must by non-negative"); + croak("data_offset must be non-negative"); } if (data_offset > data_count) { croak("data_offset greater than number of samples supplied"); } if (pixel_count == -1 || - data_offset + pixel_count * chan_count > data_count) { - pixel_count = (data_count - data_offset) / chan_count; + data_offset + pixel_count * channels.count > data_count) { + pixel_count = (data_count - data_offset) / channels.count; } - data_used = pixel_count * chan_count; + data_used = pixel_count * channels.count; data = mymalloc(sizeof(unsigned) * data_count); for (i = 0; i < data_used; ++i) data[i] = SvUV(*av_fetch(data_av, data_offset + i, 0)); - RETVAL = i_psamp_bits(im, l, l + pixel_count, y, data, channels, - chan_count, bits); + RETVAL = i_psamp_bits(im, l, l + pixel_count, y, data, channels.channels, + channels.count, bits); if (data) myfree(data); - if (channels) - myfree(channels); OUTPUT: RETVAL +undef_neg_int +i_psamp(im, x, y, channels, data, offset = 0, width = -1) + Imager::ImgRaw im + i_img_dim x + i_img_dim y + i_channel_list channels + i_sample_list data + i_img_dim offset + i_img_dim width + PREINIT: + i_img_dim r; + CODE: + i_clear_error(); + if (offset < 0) { + i_push_error(0, "offset must be non-negative"); + XSRETURN_UNDEF; + } + if (offset > 0) { + if (offset > data.count) { + i_push_error(0, "offset greater than number of samples supplied"); + XSRETURN_UNDEF; + } + data.samples += offset; + data.count -= offset; + } + if (width == -1 || + width * channels.count > data.count) { + width = data.count / channels.count; + } + r = x + width; + RETVAL = i_psamp(im, x, r, y, data.samples, channels.channels, channels.count); + OUTPUT: + RETVAL + +undef_neg_int +i_psampf(im, x, y, channels, data, offset = 0, width = -1) + Imager::ImgRaw im + i_img_dim x + i_img_dim y + i_channel_list channels + i_fsample_list data + i_img_dim offset + i_img_dim width + PREINIT: + i_img_dim r; + CODE: + i_clear_error(); + if (offset < 0) { + i_push_error(0, "offset must be non-negative"); + XSRETURN_UNDEF; + } + if (offset > 0) { + if (offset > data.count) { + i_push_error(0, "offset greater than number of samples supplied"); + XSRETURN_UNDEF; + } + data.samples += offset; + data.count -= offset; + } + if (width == -1 || + width * channels.count > data.count) { + width = data.count / channels.count; + } + r = x + width; + RETVAL = i_psampf(im, x, r, y, data.samples, channels.channels, channels.count); + OUTPUT: + RETVAL + 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: @@ -3269,13 +3406,13 @@ i_img_masked_new(targ, mask, x, y, w, h) 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; - int i; + STRLEN i; STRLEN len; - int count; + size_t count; CODE: if (items > 3) { if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) { @@ -3313,32 +3450,24 @@ i_plin(im, l, y, ...) 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, ...) +i_gsampf(im, l, r, y, channels) Imager::ImgRaw im - int l - int r - int y + i_img_dim l + i_img_dim r + i_img_dim y + i_channel_list channels 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()"); if (l < r) { - chan_count = items - 4; - chans = mymalloc(sizeof(int) * chan_count); - for (i = 0; i < chan_count; ++i) - 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); + data = mymalloc(sizeof(i_fsample_t) * (r-l) * channels.count); + count = i_gsampf(im, l, r, y, data, channels.channels, channels.count); if (GIMME_V == G_ARRAY) { EXTEND(SP, count); for (i = 0; i < count; ++i) @@ -3352,21 +3481,20 @@ i_gsampf(im, l, r, y, ...) } else { if (GIMME_V != G_ARRAY) { - EXTEND(SP, 1); - PUSHs(&PL_sv_undef); + XSRETURN_UNDEF; } } 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; - int i; + i_img_dim i; STRLEN len; - int count; + size_t count; CODE: if (items > 3) { if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) { @@ -3402,22 +3530,16 @@ i_plinf(im, l, y, ...) OUTPUT: RETVAL -SV * +Imager::Color::Float i_gpixf(im, x, y) Imager::ImgRaw im - int x - int y; - PREINIT: - i_fcolor *color; + i_img_dim x + i_img_dim y; 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)); + if (i_gpixf(im, x, y, RETVAL) != 0) { + myfree(RETVAL); + XSRETURN_UNDEF; } OUTPUT: RETVAL @@ -3425,12 +3547,12 @@ i_gpixf(im, x, y) 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; - int count, i; + i_img_dim count, i; PPCODE: if (l < r) { vals = mymalloc((r-l) * sizeof(i_color)); @@ -3439,11 +3561,7 @@ i_glin(im, l, r, y) if (GIMME_V == G_ARRAY) { EXTEND(SP, count); for (i = 0; i < count; ++i) { - SV *sv; - i_color *col = mymalloc(sizeof(i_color)); - *col = vals[i]; - sv = sv_newmortal(); - sv_setref_pv(sv, "Imager::Color", (void *)col); + SV *sv = make_i_color_sv(aTHX_ vals+i); PUSHs(sv); } } @@ -3457,12 +3575,12 @@ i_glin(im, l, r, y) 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; - int count, i; + i_img_dim count, i; i_fcolor zero; PPCODE: for (i = 0; i < MAXCHANNELS; ++i) @@ -3490,10 +3608,16 @@ i_glinf(im, l, r, y) myfree(vals); } +Imager::ImgRaw +i_img_8_new(x, y, ch) + i_img_dim x + i_img_dim y + int 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 @@ -3502,21 +3626,27 @@ i_img_to_rgb16(im) Imager::ImgRaw i_img_double_new(x, y, ch) - int x - int y + i_img_dim x + i_img_dim y int ch +Imager::ImgRaw +i_img_to_drgb(im) + 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); @@ -3524,21 +3654,25 @@ i_tags_addn(im, 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; @@ -3547,7 +3681,7 @@ i_tags_add(im, name, code, data, idata) OUTPUT: RETVAL -SV * +SysRet i_tags_find(im, name, start) Imager::ImgRaw im char *name @@ -3556,17 +3690,14 @@ i_tags_find(im, name, start) 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 @@ -3575,13 +3706,10 @@ i_tags_findn(im, code, start) 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 @@ -3677,6 +3805,7 @@ IFILL_DESTROY(fill) int IFILL_CLONE_SKIP(...) CODE: + (void)items; /* avoid unused warning for XS variable */ RETVAL = 1; OUTPUT: RETVAL @@ -3694,19 +3823,21 @@ i_new_fill_solidf(cl, combine) 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 - int dx - int dy + 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; @@ -3715,19 +3846,21 @@ i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy) 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 - int dx - int dy + 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; @@ -3736,10 +3869,11 @@ i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy) 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 - int xoff - int yoff + SV *matrix_sv + i_img_dim xoff + i_img_dim yoff int combine PREINIT: double matrix[9]; @@ -3749,13 +3883,14 @@ i_new_fill_image(src, matrix, xoff, yoff, 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; @@ -3782,9 +3917,9 @@ i_int_hlines_testing() 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 start_x + i_img_dim start_x int count_x Imager::Internal::Hlines @@ -3794,9 +3929,9 @@ i_int_hlines_new_img(im) 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) @@ -3808,10 +3943,40 @@ i_int_hlines_dump(hlines) int i_int_hlines_CLONE_SKIP(cls) - SV *cls + +#endif + +MODULE = Imager PACKAGE = Imager::Context PREFIX=im_context_ + +void +im_context_DESTROY(ctx) + Imager::Context ctx + +#ifdef PERL_IMPLICIT_CONTEXT + +void +im_context_CLONE(...) + CODE: + MY_CXT_CLONE; + (void)items; + /* the following sv_setref_pv() will free this inc */ + im_context_refinc(MY_CXT.ctx, "CLONE"); + MY_CXT.ctx = im_context_clone(MY_CXT.ctx, "CLONE"); + sv_setref_pv(get_sv("Imager::_context", GV_ADD), "Imager::Context", MY_CXT.ctx); #endif BOOT: PERL_SET_GLOBAL_CALLBACKS; - PERL_PL_SET_GLOBAL_CALLBACKS; \ No newline at end of file + PERL_PL_SET_GLOBAL_CALLBACKS; +#ifdef PERL_IMPLICIT_CONTEXT + { + MY_CXT_INIT; + (void)MY_CXT; + } +#endif + start_context(aTHX); + im_get_context = perl_get_context; +#ifdef HAVE_LIBTT + i_tt_start(); +#endif