X-Git-Url: http://git.imager.perl.org/imager.git/blobdiff_plain/71dc4a8349379692cae40b2f7e1152544a2ff2ef..b47464c19c81e26fb5c8086d66f05c012a6c36cc:/Imager.xs diff --git a/Imager.xs b/Imager.xs index 5e79c193..4a82c12f 100644 --- a/Imager.xs +++ b/Imager.xs @@ -1,45 +1,35 @@ +#define PERL_NO_GET_CONTEXT #ifdef __cplusplus extern "C" { #endif #include "EXTERN.h" #include "perl.h" #include "XSUB.h" +#define NEED_newRV_noinc +#define NEED_sv_2pv_nolen #include "ppport.h" #ifdef __cplusplus - +} #endif -#include "image.h" +#define i_int_hlines_testing() 1 + +#include "imager.h" #include "feat.h" #include "dynaload.h" #include "regmach.h" +#include "imextdef.h" +#include "imextpltypes.h" -typedef io_glue* Imager__IO; -typedef i_color* Imager__Color; -typedef i_fcolor* Imager__Color__Float; -typedef i_img* Imager__ImgRaw; - -/* later perls define this macro to prevent warning when converting -from IV to pointer types */ - -#ifndef INT2PTR -#define INT2PTR(type,value) (type)(value) -#endif - -#ifndef PTR2IV -#define PTR2IV(p) INT2PTR(IV,p) -#endif - -#ifdef HAVE_LIBTT -typedef TT_Fonthandle* Imager__Font__TT; +#if i_int_hlines_testing() +#include "imageri.h" #endif -#ifdef HAVE_FT2 -typedef FT2_Fonthandle* Imager__Font__FT2; -#endif +#include "imperl.h" /* 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; @@ -54,6 +44,7 @@ static int getstr(void *hv_t,char *key,char **store) { } static int getint(void *hv_t,char *key,int *store) { + dTHX; SV** svpp; HV* hv=(HV*)hv_t; @@ -67,6 +58,7 @@ static int getint(void *hv_t,char *key,int *store) { } static int getdouble(void *hv_t,char* key,double *store) { + dTHX; SV** svpp; HV* hv=(HV*)hv_t; @@ -79,6 +71,7 @@ static int getdouble(void *hv_t,char* key,double *store) { } static int getvoid(void *hv_t,char* key,void **store) { + dTHX; SV** svpp; HV* hv=(HV*)hv_t; @@ -93,6 +86,7 @@ static int getvoid(void *hv_t,char* key,void **store) { } static int getobj(void *hv_t,char *key,char *type,void **store) { + dTHX; SV** svpp; HV* hv=(HV*)hv_t; @@ -116,12 +110,13 @@ 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 -log_entry(char *string, int level) { +i_log_entry(char *string, int level) { mm_log((level, string)); } @@ -134,6 +129,7 @@ typedef struct i_reader_data_tag /* 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; @@ -185,6 +181,7 @@ typedef struct /* 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; @@ -256,6 +253,7 @@ 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; @@ -285,11 +283,12 @@ static ssize_t call_writer(struct cbdata *cbd, void const *buf, size_t size) { FREETMPS; LEAVE; - return success ? size : 0; + return success ? size : -1; } static ssize_t call_reader(struct cbdata *cbd, void *buf, size_t size, size_t maxread) { + dTHX; int count; int result; SV *data; @@ -336,14 +335,21 @@ static ssize_t call_reader(struct cbdata *cbd, void *buf, size_t size, } static ssize_t write_flush(struct cbdata *cbd) { + dTHX; 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) { + dTHX; struct cbdata *cbd = p; int count; off_t result; @@ -388,14 +394,14 @@ 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) { + dTHX; 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; } @@ -405,8 +411,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; } @@ -419,12 +426,14 @@ 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) { + dTHX; struct cbdata *cbd = p; ssize_t total; char *out = data; /* so we can do pointer arithmetic */ - int i; + /* printf("io_reader(%p, %p, %d)\n", p, data, size); */ if (cbd->writing) { if (write_flush(cbd) <= 0) return 0; @@ -444,7 +453,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, @@ -459,6 +468,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*/ @@ -468,16 +479,20 @@ 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; } -static void io_closer(void *p) { +static int io_closer(void *p) { + dTHX; struct cbdata *cbd = p; if (cbd->writing && cbd->used > 0) { - write_flush(cbd); + if (write_flush(cbd) < 0) + return -1; cbd->writing = 0; } @@ -496,15 +511,19 @@ static void io_closer(void *p) { FREETMPS; LEAVE; } + + return 0; } static void io_destroyer(void *p) { + dTHX; struct cbdata *cbd = p; SvREFCNT_dec(cbd->writecb); SvREFCNT_dec(cbd->readcb); SvREFCNT_dec(cbd->seekcb); SvREFCNT_dec(cbd->closecb); + myfree(cbd); } struct value_name { @@ -534,13 +553,13 @@ static struct value_name make_color_names[] = { "webmap", mc_web_map, }, { "addi", mc_addi, }, { "mediancut", mc_median_cut, }, + { "mono", mc_mono, }, + { "monochrome", mc_mono, }, }; static struct value_name translate_names[] = { -#ifdef HAVE_LIBGIF { "giflib", pt_giflib, }, -#endif { "closest", pt_closest, }, { "perturb", pt_perturb, }, { "errdiff", pt_errdiff, }, @@ -569,32 +588,9 @@ static struct value_name orddith_names[] = { "custom", od_custom, }, }; -static int -hv_fetch_bool(HV *hv, char *name, int def) { - SV **sv; - - sv = hv_fetch(hv, name, strlen(name), 0); - if (sv && *sv) { - return SvTRUE(*sv); - } - else - return def; -} - -static int -hv_fetch_int(HV *hv, char *name, int def) { - SV **sv; - - sv = hv_fetch(hv, name, strlen(name), 0); - if (sv && *sv) { - return SvIV(*sv); - } - else - return def; -} - /* look through the hash for quantization options */ -static void handle_quant_opts(i_quantize *quant, HV *hv) +static void +ip_handle_quant_opts(pTHX_ i_quantize *quant, HV *hv) { /*** POSSIBLY BROKEN: do I need to unref the SV from hv_fetch ***/ SV **sv; @@ -725,98 +721,16 @@ static void handle_quant_opts(i_quantize *quant, HV *hv) quant->perturb = SvIV(*sv); } -static void cleanup_quant_opts(i_quantize *quant) { +static void +ip_cleanup_quant_opts(pTHX_ i_quantize *quant) { myfree(quant->mc_colors); if (quant->ed_map) myfree(quant->ed_map); } -#if 0 -/* look through the hash for options to add to opts */ -static void handle_gif_opts(i_gif_opts *opts, HV *hv) -{ - SV **sv; - int i; - /**((char *)0) = '\0';*/ - opts->each_palette = hv_fetch_bool(hv, "gif_each_palette", 0); - opts->interlace = hv_fetch_bool(hv, "interlace", 0); - - sv = hv_fetch(hv, "gif_delays", 10, 0); - if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) { - AV *av = (AV*)SvRV(*sv); - opts->delay_count = av_len(av)+1; - opts->delays = mymalloc(sizeof(int) * opts->delay_count); - for (i = 0; i < opts->delay_count; ++i) { - SV *sv1 = *av_fetch(av, i, 0); - opts->delays[i] = SvIV(sv1); - } - } - sv = hv_fetch(hv, "gif_user_input", 14, 0); - if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) { - AV *av = (AV*)SvRV(*sv); - opts->user_input_count = av_len(av)+1; - opts->user_input_flags = mymalloc(opts->user_input_count); - for (i = 0; i < opts->user_input_count; ++i) { - SV *sv1 = *av_fetch(av, i, 0); - opts->user_input_flags[i] = SvIV(sv1) != 0; - } - } - sv = hv_fetch(hv, "gif_disposal", 12, 0); - if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) { - AV *av = (AV*)SvRV(*sv); - opts->disposal_count = av_len(av)+1; - opts->disposal = mymalloc(opts->disposal_count); - for (i = 0; i < opts->disposal_count; ++i) { - SV *sv1 = *av_fetch(av, i, 0); - opts->disposal[i] = SvIV(sv1); - } - } - sv = hv_fetch(hv, "gif_tran_color", 14, 0); - if (sv && *sv && SvROK(*sv) && sv_derived_from(*sv, "Imager::Color")) { - i_color *col = INT2PTR(i_color *, SvIV((SV *)SvRV(*sv))); - opts->tran_color = *col; - } - sv = hv_fetch(hv, "gif_positions", 13, 0); - if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) { - AV *av = (AV *)SvRV(*sv); - opts->position_count = av_len(av) + 1; - opts->positions = mymalloc(sizeof(i_gif_pos) * opts->position_count); - for (i = 0; i < opts->position_count; ++i) { - SV **sv2 = av_fetch(av, i, 0); - opts->positions[i].x = opts->positions[i].y = 0; - if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) { - AV *av2 = (AV*)SvRV(*sv2); - SV **sv3; - sv3 = av_fetch(av2, 0, 0); - if (sv3 && *sv3) - opts->positions[i].x = SvIV(*sv3); - sv3 = av_fetch(av2, 1, 0); - if (sv3 && *sv3) - opts->positions[i].y = SvIV(*sv3); - } - } - } - /* Netscape2.0 loop count extension */ - opts->loop_count = hv_fetch_int(hv, "gif_loop_count", 0); - - opts->eliminate_unused = hv_fetch_bool(hv, "gif_eliminate_unused", 1); -} - -static void cleanup_gif_opts(i_gif_opts *opts) { - if (opts->delays) - myfree(opts->delays); - if (opts->user_input_flags) - myfree(opts->user_input_flags); - if (opts->disposal) - myfree(opts->disposal); - if (opts->positions) - myfree(opts->positions); -} - -#endif - /* copies the color map from the hv into the colors member of the HV */ -static void copy_colors_back(HV *hv, i_quantize *quant) { +static void +ip_copy_colors_back(pTHX_ HV *hv, i_quantize *quant) { SV **sv; AV *av; int i; @@ -824,14 +738,12 @@ static void copy_colors_back(HV *hv, i_quantize *quant) { sv = hv_fetch(hv, "colors", 6, 0); if (!sv || !*sv || !SvROK(*sv) || SvTYPE(SvRV(*sv)) != SVt_PVAV) { - SV *ref; - av = newAV(); - ref = newRV_inc((SV*) av); - sv = hv_store(hv, "colors", 6, ref, 0); - } - else { - av = (AV *)SvRV(*sv); + /* nothing to do */ + return; } + + av = (AV *)SvRV(*sv); + av_clear(av); av_extend(av, quant->mc_count+1); for (i = 0; i < quant->mc_count; ++i) { i_color *in = quant->mc_colors+i; @@ -839,15 +751,13 @@ static void copy_colors_back(HV *hv, i_quantize *quant) { work = sv_newmortal(); sv_setref_pv(work, "Imager::Color", (void *)c); SvREFCNT_inc(work); - if (!av_store(av, i, work)) { - SvREFCNT_dec(work); - } + av_push(av, work); } } /* loads the segments of a fountain fill into an array */ static i_fountain_seg * -load_fount_segs(AV *asegs, int *count) { +load_fount_segs(pTHX_ AV *asegs, int *count) { /* Each element of segs must contain: [ start, middle, end, c0, c1, segtype, colortrans ] start, middle, end are doubles from 0 to 1 @@ -856,7 +766,6 @@ load_fount_segs(AV *asegs, int *count) { */ int i, j; AV *aseg; - SV *sv; i_fountain_seg *segs; double work[3]; int worki[2]; @@ -922,6 +831,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 @@ -929,17 +861,99 @@ load_fount_segs(AV *asegs, 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) -/* for the fill objects - Since a fill object may later have dependent images, (or fills!) - we need perl wrappers - oh well -*/ -#define IFILL_DESTROY(fill) i_fill_destroy(fill); -typedef i_fill_t* Imager__FillHandle; /* the m_init_log() function was called init_log(), renamed to reduce potential naming conflicts */ #define init_log m_init_log +#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 *result = mymalloc(sizeof(i_int_hlines)); + i_int_init_hlines(result, start_y, count_y, start_x, count_x); + + return result; +} + +static i_int_hlines * +i_int_hlines_new_img(i_img *im) { + i_int_hlines *result = mymalloc(sizeof(i_int_hlines)); + i_int_init_hlines_img(result, im); + + return result; +} + +static void +i_int_hlines_DESTROY(i_int_hlines *hlines) { + i_int_hlines_destroy(hlines); + myfree(hlines); +} + +#define i_int_hlines_CLONE_SKIP(cls) 1 + +static int seg_compare(const void *vleft, const void *vright) { + const i_int_hline_seg *left = vleft; + const i_int_hline_seg *right = vright; + + return left->minx - right->minx; +} + +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; + + for (y = hlines->start_y; y < hlines->limit_y; ++y) { + i_int_hline_entry *entry = hlines->entries[y-hlines->start_y]; + if (entry) { + int i; + /* sort the segments, if any */ + if (entry->count) + qsort(entry->segs, entry->count, sizeof(i_int_hline_seg), seg_compare); + + sv_catpvf(dump, " %d (%d):", y, entry->count); + for (i = 0; i < entry->count; ++i) { + sv_catpvf(dump, " [%d, %d)", entry->segs[i].minx, + entry->segs[i].x_limit); + } + sv_catpv(dump, "\n"); + } + } + + return dump; +} + +#endif + +static im_pl_ext_funcs im_perl_funcs = +{ + IMAGER_PL_API_VERSION, + IMAGER_PL_API_LEVEL, + ip_handle_quant_opts, + ip_cleanup_quant_opts, + ip_copy_colors_back +}; + +#define PERL_PL_SET_GLOBAL_CALLBACKS \ + sv_setiv(get_sv(PERL_PL_FUNCTION_TABLE_NAME, 1), PTR2IV(&im_perl_funcs)); + +#ifdef IMEXIF_ENABLE +#define i_exif_enabled() 1 +#else +#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) + +#define i_img_get_width(im) ((im)->xsize) +#define i_img_get_height(im) ((im)->ysize) + MODULE = Imager PACKAGE = Imager::Color PREFIX = ICL_ Imager::Color @@ -1062,7 +1076,6 @@ i_rgb_to_hsv(c) i_rgb_to_hsvf(RETVAL); OUTPUT: RETVAL - MODULE = Imager PACKAGE = Imager::ImgRaw PREFIX = IIM_ @@ -1096,7 +1109,6 @@ io_new_buffer(data) char *data PREINIT: size_t length; - SV* sv; CODE: SvPV(ST(0), length); SvREFCNT_inc(ST(0)); @@ -1146,19 +1158,129 @@ io_slurp(ig) myfree(data); -MODULE = Imager PACKAGE = Imager::IO PREFIX = io_glue_ +undef_int +i_set_image_file_limits(width, height, bytes) + int width + int height + int bytes + +void +i_get_image_file_limits() + PREINIT: + int width, height, 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))); + } + +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 +int +i_io_CLONE_SKIP(...) + CODE: + RETVAL = 1; + OUTPUT: + RETVAL MODULE = Imager PACKAGE = Imager PROTOTYPES: ENABLE - - void i_list_formats() PREINIT: @@ -1191,13 +1313,30 @@ i_img_empty_ch(im,x,y,ch) int y int ch +Imager::ImgRaw +i_sametype(im, x, y) + Imager::ImgRaw im + int x + int y + +Imager::ImgRaw +i_sametype_chans(im, x, y, channels) + Imager::ImgRaw im + int x + int y + int channels + void -m_init_log(name,level) - char* name +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); void -log_entry(string,level) +i_log_entry(string,level) char* string int level @@ -1248,6 +1387,34 @@ i_img_getdata(im) sv_2mortal(newSVpv((char *)im->idata, im->bytes)) : &PL_sv_undef); +IV +i_img_get_width(im) + Imager::ImgRaw im + +IV +i_img_get_height(im) + Imager::ImgRaw im + + +void +i_img_is_monochrome(im) + Imager::ImgRaw im + PREINIT: + int zero_is_white; + int result; + PPCODE: + result = i_img_is_monochrome(im, &zero_is_white); + if (result) { + if (GIMME_V == G_ARRAY) { + EXTEND(SP, 2); + PUSHs(&PL_sv_yes); + PUSHs(sv_2mortal(newSViv(zero_is_white))); + } + else { + EXTEND(SP, 1); + PUSHs(&PL_sv_yes); + } + } void i_line(im,x1,y1,x2,y2,val,endp) @@ -1306,6 +1473,16 @@ i_arc(im,x,y,rad,d1,d2,val) float d2 Imager::Color val +void +i_arc_aa(im,x,y,rad,d1,d2,val) + Imager::ImgRaw im + double x + double y + double rad + double d1 + double d2 + Imager::Color val + void i_arc_cfill(im,x,y,rad,d1,d2,fill) Imager::ImgRaw im @@ -1316,6 +1493,15 @@ i_arc_cfill(im,x,y,rad,d1,d2,fill) float d2 Imager::FillHandle fill +void +i_arc_aa_cfill(im,x,y,rad,d1,d2,fill) + Imager::ImgRaw im + double x + double y + double rad + double d1 + double d2 + Imager::FillHandle fill void @@ -1326,6 +1512,41 @@ i_circle_aa(im,x,y,rad,val) float rad Imager::Color val +int +i_circle_out(im,x,y,rad,val) + Imager::ImgRaw im + i_img_dim x + i_img_dim y + i_img_dim rad + Imager::Color val + +int +i_circle_out_aa(im,x,y,rad,val) + Imager::ImgRaw im + i_img_dim x + i_img_dim y + i_img_dim rad + Imager::Color val + +int +i_arc_out(im,x,y,rad,d1,d2,val) + Imager::ImgRaw im + i_img_dim x + i_img_dim y + i_img_dim rad + float d1 + float d2 + Imager::Color val + +int +i_arc_out_aa(im,x,y,rad,d1,d2,val) + Imager::ImgRaw im + i_img_dim x + i_img_dim y + i_img_dim rad + float d1 + float d2 + Imager::Color val void @@ -1363,7 +1584,7 @@ i_bezier_multi(im,xc,yc,val) myfree(y); -void +int i_poly_aa(im,xc,yc,val) Imager::ImgRaw im Imager::Color val @@ -1375,7 +1596,7 @@ i_poly_aa(im,xc,yc,val) SV *sv1; SV *sv2; int i; - PPCODE: + CODE: ICL_info(val); if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n"); if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n"); @@ -1393,11 +1614,13 @@ i_poly_aa(im,xc,yc,val) x[i]=(double)SvNV(sv1); y[i]=(double)SvNV(sv2); } - i_poly_aa(im,len,x,y,val); + RETVAL = i_poly_aa(im,len,x,y,val); myfree(x); myfree(y); + OUTPUT: + RETVAL -void +int i_poly_aa_cfill(im,xc,yc,fill) Imager::ImgRaw im Imager::FillHandle fill @@ -1409,7 +1632,7 @@ i_poly_aa_cfill(im,xc,yc,fill) SV *sv1; SV *sv2; int i; - PPCODE: + CODE: if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n"); if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n"); if (!SvROK(ST(2))) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n"); @@ -1426,9 +1649,11 @@ i_poly_aa_cfill(im,xc,yc,fill) x[i]=(double)SvNV(sv1); y[i]=(double)SvNV(sv2); } - i_poly_aa_cfill(im,len,x,y,fill); + RETVAL = i_poly_aa_cfill(im,len,x,y,fill); myfree(x); myfree(y); + OUTPUT: + RETVAL @@ -1446,6 +1671,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) @@ -1471,9 +1712,8 @@ i_copyto_trans(im,src,x1,y1,x2,y2,tx,ty,trans) int ty Imager::Color trans -void -i_copy(im,src) - Imager::ImgRaw im +Imager::ImgRaw +i_copy(src) Imager::ImgRaw src @@ -1488,6 +1728,75 @@ i_rubthru(im,src,tx,ty,src_minx,src_miny,src_maxx,src_maxy) int src_maxx int src_maxy +undef_int +i_compose(out, src, out_left, out_top, src_left, src_top, width, height, combine = ic_normal, opacity = 0.0) + Imager::ImgRaw out + Imager::ImgRaw src + int out_left + int out_top + int src_left + int src_top + int width + int height + int combine + double opacity + +undef_int +i_compose_mask(out, src, mask, out_left, out_top, src_left, src_top, mask_left, mask_top, width, height, combine = ic_normal, opacity = 0.0) + Imager::ImgRaw out + Imager::ImgRaw src + Imager::ImgRaw mask + int out_left + int out_top + int src_left + int src_top + int mask_left + int mask_top + int width + int height + int combine + double opacity + +Imager::ImgRaw +i_combine(src_av, channels_av = NULL) + AV *src_av + AV *channels_av + PREINIT: + i_img **imgs = NULL; + STRLEN in_count; + int *channels = NULL; + int i; + SV **psv; + IV tmp; + CODE: + in_count = av_len(src_av) + 1; + if (in_count > 0) { + imgs = mymalloc(sizeof(i_img*) * in_count); + channels = mymalloc(sizeof(int) * in_count); + for (i = 0; i < in_count; ++i) { + psv = av_fetch(src_av, i, 0); + if (!psv || !*psv || !sv_derived_from(*psv, "Imager::ImgRaw")) { + myfree(imgs); + myfree(channels); + croak("imgs must contain only images"); + } + tmp = SvIV((SV*)SvRV(*psv)); + imgs[i] = INT2PTR(i_img*, tmp); + if (channels_av && + (psv = av_fetch(channels_av, i, 0)) != NULL && + *psv) { + channels[i] = SvIV(*psv); + } + else { + channels[i] = 0; + } + } + } + RETVAL = i_combine(imgs, channels, in_count); + myfree(imgs); + myfree(channels); + OUTPUT: + RETVAL undef_int i_flipxy(im, direction) @@ -1500,12 +1809,34 @@ i_rotate90(im, degrees) int degrees Imager::ImgRaw -i_rotate_exact(im, amount) +i_rotate_exact(im, amount, ...) Imager::ImgRaw im double amount + PREINIT: + i_color *backp = NULL; + i_fcolor *fbackp = NULL; + int i; + SV * sv1; + CODE: + /* extract the bg colors if any */ + /* yes, this is kind of strange */ + for (i = 2; 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_rotate_exact_bg(im, amount, backp, fbackp); + OUTPUT: + RETVAL Imager::ImgRaw -i_matrix_transform(im, xsize, ysize, matrix) +i_matrix_transform(im, xsize, ysize, matrix, ...) Imager::ImgRaw im int xsize int ysize @@ -1515,6 +1846,8 @@ i_matrix_transform(im, xsize, ysize, matrix) IV len; SV *sv1; int i; + i_color *backp = NULL; + i_fcolor *fbackp = NULL; CODE: if (!SvROK(ST(3)) || SvTYPE(SvRV(ST(3))) != SVt_PVAV) croak("i_matrix_transform: parameter 4 must be an array ref\n"); @@ -1528,14 +1861,27 @@ i_matrix_transform(im, xsize, ysize, matrix) } for (; i < 9; ++i) matrix[i] = 0; - RETVAL = i_matrix_transform(im, xsize, ysize, matrix); + /* 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 -void +undef_int i_gaussian(im,stdev) Imager::ImgRaw im - float stdev + double stdev void i_unsharp_mask(im,stdev,scale) @@ -1543,46 +1889,40 @@ i_unsharp_mask(im,stdev,scale) float stdev double scale -void -i_conv(im,pcoef) - Imager::ImgRaw im - PREINIT: - float* coeff; - int len; - AV* av; - SV* sv1; - int i; - PPCODE: - if (!SvROK(ST(1))) croak("Imager: Parameter 1 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"); - av=(AV*)SvRV(ST(1)); - len=av_len(av)+1; - coeff=mymalloc( len*sizeof(float) ); - for(i=0;i 0) { + in_imgs = mymalloc(in_imgs_count*sizeof(i_img*)); + for (i = 0; i < in_imgs_count; ++i) { + sv1 = *av_fetch(av_in_imgs,i,0); + if (!sv_derived_from(sv1, "Imager::ImgRaw")) { + croak("Parameter 5 must contain only images"); + } + tmp = SvIV((SV*)SvRV(sv1)); + in_imgs[i] = INT2PTR(i_img*, tmp); + } + } + else { + /* no input images */ + in_imgs = NULL; + } + /* default the output size from the first input if possible */ + if (SvOK(sv_width)) + width = SvIV(sv_width); + else if (in_imgs_count) + width = in_imgs[0]->xsize; + else + croak("No output image width supplied"); + if (SvOK(sv_height)) + height = SvIV(sv_height); + else if (in_imgs_count) + height = in_imgs[0]->ysize; + else + croak("No output image height supplied"); + ops = (struct rm_op *)SvPV(sv_ops, ops_len); + if (ops_len % sizeof(struct rm_op)) + croak("Imager: Parameter 3 must be a bitmap of regops\n"); + ops_count = ops_len / sizeof(struct rm_op); + n_regs_count = av_len(av_n_regs)+1; + n_regs = mymalloc(n_regs_count * sizeof(double)); + for (i = 0; i < n_regs_count; ++i) { + sv1 = *av_fetch(av_n_regs,i,0); + if (SvOK(sv1)) + n_regs[i] = SvNV(sv1); + } + c_regs_count = av_len(av_c_regs)+1; + c_regs = mymalloc(c_regs_count * sizeof(i_color)); + /* I don't bother initializing the colou?r registers */ -undef_int -i_writegifmc(im,fd,colors) - Imager::ImgRaw im - int fd - int colors - - -undef_int -i_writegif_gen(fd, ...) - int fd - PROTOTYPE: $$@ - PREINIT: - i_quantize quant; - i_img **imgs = NULL; - int img_count; - int i; - HV *hv; - CODE: - if (items < 3) - croak("Usage: i_writegif_gen(fd,hashref, images...)"); - if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1)))) - croak("i_writegif_gen: Second argument must be a hash ref"); - hv = (HV *)SvRV(ST(1)); - memset(&quant, 0, sizeof(quant)); - quant.mc_size = 256; - handle_quant_opts(&quant, hv); - img_count = items - 2; - RETVAL = 1; - if (img_count < 1) { - RETVAL = 0; - i_clear_error(); - i_push_error(0, "You need to specify images to save"); - } - else { - imgs = mymalloc(sizeof(i_img *) * img_count); - for (i = 0; i < img_count; ++i) { - SV *sv = ST(2+i); - imgs[i] = NULL; - if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) { - imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(sv))); - } - else { - i_clear_error(); - i_push_error(0, "Only images can be saved"); - RETVAL = 0; - break; - } - } - if (RETVAL) { - RETVAL = i_writegif_gen(&quant, fd, imgs, img_count); - } - myfree(imgs); - if (RETVAL) { - copy_colors_back(hv, &quant); - } - } - ST(0) = sv_newmortal(); - if (RETVAL == 0) ST(0)=&PL_sv_undef; - else sv_setiv(ST(0), (IV)RETVAL); - cleanup_quant_opts(&quant); - - -undef_int -i_writegif_callback(cb, maxbuffer,...) - int maxbuffer; - PREINIT: - i_quantize quant; - i_img **imgs = NULL; - int img_count; - int i; - HV *hv; - i_writer_data wd; - CODE: - if (items < 4) - croak("Usage: i_writegif_callback(\\&callback,maxbuffer,hashref, images...)"); - if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2)))) - croak("i_writegif_callback: Second argument must be a hash ref"); - hv = (HV *)SvRV(ST(2)); - memset(&quant, 0, sizeof(quant)); - quant.mc_size = 256; - handle_quant_opts(&quant, hv); - img_count = items - 3; - RETVAL = 1; - if (img_count < 1) { - RETVAL = 0; - } - else { - imgs = mymalloc(sizeof(i_img *) * img_count); - for (i = 0; i < img_count; ++i) { - SV *sv = ST(3+i); - imgs[i] = NULL; - if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) { - imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(sv))); - } - else { - RETVAL = 0; - break; - } - } - if (RETVAL) { - wd.sv = ST(0); - RETVAL = i_writegif_callback(&quant, write_callback, (char *)&wd, maxbuffer, imgs, img_count); - } - myfree(imgs); - if (RETVAL) { - copy_colors_back(hv, &quant); - } - } - ST(0) = sv_newmortal(); - if (RETVAL == 0) ST(0)=&PL_sv_undef; - else sv_setiv(ST(0), (IV)RETVAL); - cleanup_quant_opts(&quant); - -undef_int -i_writegif_wiol(ig, opts,...) - Imager::IO ig - PREINIT: - i_quantize quant; - i_img **imgs = NULL; - int img_count; - int i; - HV *hv; - CODE: - if (items < 3) - croak("Usage: i_writegif_wiol(IO,hashref, images...)"); - if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1)))) - croak("i_writegif_callback: Second argument must be a hash ref"); - hv = (HV *)SvRV(ST(1)); - memset(&quant, 0, sizeof(quant)); - quant.mc_size = 256; - handle_quant_opts(&quant, hv); - img_count = items - 2; - RETVAL = 1; - if (img_count < 1) { - RETVAL = 0; - } - else { - imgs = mymalloc(sizeof(i_img *) * img_count); - for (i = 0; i < img_count; ++i) { - SV *sv = ST(2+i); - imgs[i] = NULL; - if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) { - imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(sv))); - } - else { - RETVAL = 0; - break; - } - } - if (RETVAL) { - RETVAL = i_writegif_wiol(ig, &quant, imgs, img_count); - } - myfree(imgs); - if (RETVAL) { - copy_colors_back(hv, &quant); - } - } - ST(0) = sv_newmortal(); - if (RETVAL == 0) ST(0)=&PL_sv_undef; - else sv_setiv(ST(0), (IV)RETVAL); - cleanup_quant_opts(&quant); - -void -i_readgif(fd) - int fd - PREINIT: - int* colour_table; - int colours, q, w; - i_img* rimg; - SV* temp[3]; - AV* ct; - SV* r; - PPCODE: - colour_table = NULL; - colours = 0; - - if(GIMME_V == G_ARRAY) { - rimg = i_readgif(fd,&colour_table,&colours); - } else { - /* don't waste time with colours if they aren't wanted */ - rimg = i_readgif(fd,NULL,NULL); - } - - if (colour_table == NULL) { - EXTEND(SP,1); - r=sv_newmortal(); - sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg); - PUSHs(r); - } else { - /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */ - /* I don't know if I have the reference counts right or not :( */ - /* Neither do I :-) */ - /* No Idea here either */ - - ct=newAV(); - av_extend(ct, colours); - for(q=0; q 0) { - av = (AV*)SvRV(ST(5)); - in_imgs = mymalloc(in_imgs_count*sizeof(i_img*)); - for (i = 0; i < in_imgs_count; ++i) { - sv1 = *av_fetch(av,i,0); - if (!sv_derived_from(sv1, "Imager::ImgRaw")) { - croak("Parameter 5 must contain only images"); - } - tmp = SvIV((SV*)SvRV(sv1)); - in_imgs[i] = INT2PTR(i_img*, tmp); - } - } - else { - /* no input images */ - in_imgs = NULL; - } - /* default the output size from the first input if possible */ - if (SvOK(ST(0))) - width = SvIV(ST(0)); - else if (in_imgs_count) - width = in_imgs[0]->xsize; - else - croak("No output image width supplied"); - - if (SvOK(ST(1))) - height = SvIV(ST(1)); - else if (in_imgs_count) - height = in_imgs[0]->ysize; - else - croak("No output image height supplied"); - - ops = (struct rm_op *)SvPV(ST(2), ops_len); - if (ops_len % sizeof(struct rm_op)) - croak("Imager: Parameter 3 must be a bitmap of regops\n"); - ops_count = ops_len / sizeof(struct rm_op); - av = (AV*)SvRV(ST(3)); - n_regs_count = av_len(av)+1; - n_regs = mymalloc(n_regs_count * sizeof(double)); - for (i = 0; i < n_regs_count; ++i) { - sv1 = *av_fetch(av,i,0); - if (SvOK(sv1)) - n_regs[i] = SvNV(sv1); - } - av = (AV*)SvRV(ST(4)); - c_regs_count = av_len(av)+1; - c_regs = mymalloc(c_regs_count * sizeof(i_color)); - /* I don't bother initializing the colou?r registers */ - - RETVAL=i_transform2(width, height, 3, ops, ops_count, - n_regs, n_regs_count, - c_regs, c_regs_count, in_imgs, in_imgs_count); - if (in_imgs) - myfree(in_imgs); - myfree(n_regs); - myfree(c_regs); - ST(0) = sv_newmortal(); - if (RETVAL == 0) ST(0)=&PL_sv_undef; - else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL); + RETVAL=i_transform2(width, height, channels, ops, ops_count, + n_regs, n_regs_count, + c_regs, c_regs_count, in_imgs, in_imgs_count); + if (in_imgs) + myfree(in_imgs); + myfree(n_regs); + myfree(c_regs); + ST(0) = sv_newmortal(); + if (RETVAL == 0) ST(0)=&PL_sv_undef; + else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL); void @@ -2979,6 +2681,10 @@ void i_hardinvert(im) Imager::ImgRaw im +void +i_hardinvertall(im) + Imager::ImgRaw im + void i_noise(im,amount,type) Imager::ImgRaw im @@ -3110,9 +2816,9 @@ Imager::ImgRaw i_diff_image(im, im2, mindist=0) Imager::ImgRaw im Imager::ImgRaw im2 - int mindist + double mindist -void +undef_int i_fountain(im, xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs) Imager::ImgRaw im double xa @@ -3133,10 +2839,12 @@ i_fountain(im, xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_para croak("i_fountain: argument 11 must be an array ref"); 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); + segs = load_fount_segs(aTHX_ asegs, &count); + 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) @@ -3158,20 +2866,24 @@ i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_pa croak("i_fountain: argument 11 must be an array ref"); asegs = (AV *)SvRV(ST(9)); - segs = load_fount_segs(asegs, &count); + segs = load_fount_segs(aTHX_ asegs, &count); RETVAL = i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, count, segs); myfree(segs); OUTPUT: RETVAL +Imager::FillHandle +i_new_fill_opacity(other_fill, alpha_mult) + Imager::FillHandle other_fill + double alpha_mult + void i_errors() PREINIT: i_errmsg *errors; int i; AV *av; - SV *ref; SV *sv; PPCODE: errors = i_errors(); @@ -3191,6 +2903,14 @@ i_errors() } 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: @@ -3235,26 +2955,13 @@ i_nearest_color(im, ...) } 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 @@ -3285,17 +2992,18 @@ DSO_funclist(dso_handle_v) PREINIT: int i; DSO_handle *dso_handle; + func_ptr *functions; PPCODE: dso_handle=(DSO_handle*)dso_handle_v; + functions = DSO_funclist(dso_handle); i=0; - while( dso_handle->function_list[i].name != NULL) { + while( functions[i].name != NULL) { EXTEND(SP,1); - PUSHs(sv_2mortal(newSVpv(dso_handle->function_list[i].name,0))); + PUSHs(sv_2mortal(newSVpv(functions[i].name,0))); EXTEND(SP,1); - PUSHs(sv_2mortal(newSVpv(dso_handle->function_list[i++].pcode,0))); + PUSHs(sv_2mortal(newSVpv(functions[i++].pcode,0))); } - void DSO_call(handle,func_index,hv) void* handle @@ -3308,9 +3016,6 @@ DSO_call(handle,func_index,hv) if (SvTYPE(hv)!=SVt_PVHV) croak("Imager: Parameter 2 must be a reference to a hash\n"); DSO_call( (DSO_handle *)handle,func_index,hv); - - -# this is mostly for testing... SV * i_get_pixel(im, x, y) Imager::ImgRaw im @@ -3321,13 +3026,15 @@ i_get_pixel(im, x, y) CODE: color = (i_color *)mymalloc(sizeof(i_color)); if (i_gpix(im, x, y, color) == 0) { - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Imager::Color", (void *)color); + RETVAL = NEWSV(0, 0); + sv_setref_pv(RETVAL, "Imager::Color", (void *)color); } else { myfree(color); - ST(0) = &PL_sv_undef; + RETVAL = &PL_sv_undef; } + OUTPUT: + RETVAL int @@ -3355,13 +3062,14 @@ i_img_to_pal(src, quant) croak("i_img_to_pal: second argument must be a hash ref"); hv = (HV *)SvRV(ST(1)); memset(&quant, 0, sizeof(quant)); + quant.version = 1; quant.mc_size = 256; - handle_quant_opts(&quant, hv); + ip_handle_quant_opts(aTHX_ &quant, hv); RETVAL = i_img_to_pal(src, &quant); if (RETVAL) { - copy_colors_back(hv, &quant); + ip_copy_colors_back(aTHX_ hv, &quant); } - cleanup_quant_opts(&quant); + ip_cleanup_quant_opts(aTHX_ &quant); OUTPUT: RETVAL @@ -3408,13 +3116,14 @@ i_ppal(im, l, y, ...) int y PREINIT: i_palidx *work; - int count, i; + int i; CODE: if (items > 3) { work = mymalloc(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); } @@ -3424,6 +3133,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 @@ -3443,22 +3174,24 @@ i_addcolors(im, ...) } else { myfree(colors); - croak("i_plin: pixels must be Imager::Color objects"); + croak("i_addcolor: pixels must be Imager::Color objects"); } } index = i_addcolors(im, colors, items-1); myfree(colors); if (index == 0) { - ST(0) = sv_2mortal(newSVpv("0 but true", 0)); + RETVAL = newSVpv("0 but true", 0); } else if (index == -1) { - ST(0) = &PL_sv_undef; + RETVAL = &PL_sv_undef; } else { - ST(0) = sv_2mortal(newSViv(index)); + RETVAL = newSViv(index); } + OUTPUT: + RETVAL -int +undef_int i_setcolors(im, index, ...) Imager::ImgRaw im int index @@ -3482,6 +3215,8 @@ i_setcolors(im, index, ...) } RETVAL = i_setcolors(im, index, colors, items-2); myfree(colors); + OUTPUT: + RETVAL void i_getcolors(im, index, ...) @@ -3512,33 +3247,13 @@ i_getcolors(im, index, ...) myfree(colors); -SV * +undef_neg_int i_colorcount(im) Imager::ImgRaw im - PREINIT: - int count; - CODE: - count = i_colorcount(im); - if (count >= 0) { - ST(0) = sv_2mortal(newSViv(count)); - } - else { - ST(0) = &PL_sv_undef; - } -SV * +undef_neg_int i_maxcolors(im) Imager::ImgRaw im - PREINIT: - int count; - CODE: - count = i_maxcolors(im); - if (count >= 0) { - ST(0) = sv_2mortal(newSViv(count)); - } - else { - ST(0) = &PL_sv_undef; - } SV * i_findcolor(im, color) @@ -3548,11 +3263,13 @@ i_findcolor(im, color) i_palidx index; CODE: if (i_findcolor(im, color, &index)) { - ST(0) = sv_2mortal(newSViv(index)); + RETVAL = newSViv(index); } else { - ST(0) = &PL_sv_undef; + RETVAL = &PL_sv_undef; } + OUTPUT: + RETVAL int i_img_bits(im) @@ -3606,6 +3323,108 @@ i_gsamp(im, l, r, y, ...) } } +undef_neg_int +i_gsamp_bits(im, l, r, y, bits, target, offset, ...) + Imager::ImgRaw im + int l + int r + int y + int bits + AV *target + int offset + PREINIT: + int *chans; + int chan_count; + unsigned *data; + int 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); + for (i = 0; i < count; ++i) { + av_store(target, i+offset, newSVuv(data[i])); + } + myfree(data); + RETVAL = count; + } + else { + RETVAL = 0; + } + OUTPUT: + RETVAL + +undef_neg_int +i_psamp_bits(im, l, y, bits, channels_sv, data_av, data_offset = 0, pixel_count = -1) + Imager::ImgRaw im + int l + int y + int bits + SV *channels_sv + AV *data_av + int data_offset + int pixel_count + PREINIT: + int chan_count; + int *channels; + int data_count; + int data_used; + unsigned *data; + int 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"); + } + 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_used = pixel_count * chan_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); + + if (data) + myfree(data); + if (channels) + myfree(channels); + OUTPUT: + RETVAL Imager::ImgRaw i_img_masked_new(targ, mask, x, y, w, h) @@ -3637,24 +3456,36 @@ i_plin(im, l, y, ...) int y PREINIT: i_color *work; - int count, i; + int i; + STRLEN len; + int count; CODE: if (items > 3) { - work = mymalloc(sizeof(i_color) * (items-3)); - for (i=0; i < items-3; ++i) { - if (sv_isobject(ST(i+3)) - && sv_derived_from(ST(i+3), "Imager::Color")) { - IV tmp = SvIV((SV *)SvRV(ST(i+3))); - work[i] = *INT2PTR(i_color *, tmp); + if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) { + /* supplied as a byte string */ + work = (i_color *)SvPV(ST(3), len); + count = len / sizeof(i_color); + if (count * sizeof(i_color) != len) { + croak("i_plin: length of scalar argument must be multiple of sizeof i_color"); } - else { - myfree(work); - croak("i_plin: pixels must be Imager::Color objects"); + RETVAL = i_plin(im, l, l+count, y, work); + } + else { + work = mymalloc(sizeof(i_color) * (items-3)); + for (i=0; i < items-3; ++i) { + if (sv_isobject(ST(i+3)) + && sv_derived_from(ST(i+3), "Imager::Color")) { + IV tmp = SvIV((SV *)SvRV(ST(i+3))); + work[i] = *INT2PTR(i_color *, tmp); + } + else { + myfree(work); + croak("i_plin: pixels must be Imager::Color objects"); + } } + RETVAL = i_plin(im, l, l+items-3, y, work); + myfree(work); } - /**(char *)0 = 1;*/ - RETVAL = i_plin(im, l, l+items-3, y, work); - myfree(work); } else { RETVAL = 0; @@ -3690,6 +3521,7 @@ i_gsampf(im, l, r, y, ...) 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) @@ -3699,6 +3531,7 @@ i_gsampf(im, l, r, y, ...) EXTEND(SP, 1); PUSHs(sv_2mortal(newSVpv((void *)data, count * sizeof(i_fsample_t)))); } + myfree(data); } else { if (GIMME_V != G_ARRAY) { @@ -3714,24 +3547,37 @@ i_plinf(im, l, y, ...) int y PREINIT: i_fcolor *work; - int count, i; + int i; + STRLEN len; + int count; CODE: if (items > 3) { - work = mymalloc(sizeof(i_fcolor) * (items-3)); - for (i=0; i < items-3; ++i) { - if (sv_isobject(ST(i+3)) - && sv_derived_from(ST(i+3), "Imager::Color::Float")) { - IV tmp = SvIV((SV *)SvRV(ST(i+3))); - work[i] = *INT2PTR(i_fcolor *, tmp); + if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) { + /* supplied as a byte string */ + work = (i_fcolor *)SvPV(ST(3), len); + count = len / sizeof(i_fcolor); + if (count * sizeof(i_fcolor) != len) { + croak("i_plin: length of scalar argument must be multiple of sizeof i_fcolor"); } - else { - myfree(work); - croak("i_plin: pixels must be Imager::Color::Float objects"); + RETVAL = i_plinf(im, l, l+count, y, work); + } + else { + work = mymalloc(sizeof(i_fcolor) * (items-3)); + for (i=0; i < items-3; ++i) { + if (sv_isobject(ST(i+3)) + && sv_derived_from(ST(i+3), "Imager::Color::Float")) { + IV tmp = SvIV((SV *)SvRV(ST(i+3))); + work[i] = *INT2PTR(i_fcolor *, tmp); + } + else { + myfree(work); + croak("i_plinf: pixels must be Imager::Color::Float objects"); + } } + /**(char *)0 = 1;*/ + RETVAL = i_plinf(im, l, l+items-3, y, work); + myfree(work); } - /**(char *)0 = 1;*/ - RETVAL = i_plinf(im, l, l+items-3, y, work); - myfree(work); } else { RETVAL = 0; @@ -3749,14 +3595,16 @@ i_gpixf(im, x, y) CODE: color = (i_fcolor *)mymalloc(sizeof(i_fcolor)); if (i_gpixf(im, x, y, color) == 0) { - ST(0) = sv_newmortal(); - sv_setref_pv(ST(0), "Imager::Color::Float", (void *)color); + RETVAL = NEWSV(0,0); + sv_setref_pv(RETVAL, "Imager::Color::Float", (void *)color); } else { myfree(color); - ST(0) = &PL_sv_undef; + RETVAL = &PL_sv_undef; } - + OUTPUT: + RETVAL + void i_glin(im, l, r, y) Imager::ImgRaw im @@ -3769,14 +3617,22 @@ i_glin(im, l, r, y) PPCODE: if (l < r) { vals = mymalloc((r-l) * sizeof(i_color)); + memset(vals, 0, (r-l) * sizeof(i_color)); count = i_glin(im, l, r, y, vals); - EXTEND(SP, count); - for (i = 0; i < count; ++i) { - SV *sv; - i_color *col = mymalloc(sizeof(i_color)); - sv = sv_newmortal(); - sv_setref_pv(sv, "Imager::Color", (void *)col); - PUSHs(sv); + 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); + PUSHs(sv); + } + } + else if (count) { + EXTEND(SP, 1); + PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_color)))); } myfree(vals); } @@ -3790,18 +3646,29 @@ i_glinf(im, l, r, y) PREINIT: i_fcolor *vals; int count, i; + i_fcolor zero; PPCODE: + for (i = 0; i < MAXCHANNELS; ++i) + zero.channel[i] = 0; if (l < r) { vals = mymalloc((r-l) * sizeof(i_fcolor)); + for (i = 0; i < r-l; ++i) + vals[i] = zero; count = i_glinf(im, l, r, y, vals); - EXTEND(SP, count); - for (i = 0; i < count; ++i) { - SV *sv; - i_fcolor *col = mymalloc(sizeof(i_fcolor)); - *col = vals[i]; - sv = sv_newmortal(); - sv_setref_pv(sv, "Imager::Color::Float", (void *)col); - PUSHs(sv); + if (GIMME_V == G_ARRAY) { + EXTEND(SP, count); + for (i = 0; i < count; ++i) { + SV *sv; + i_fcolor *col = mymalloc(sizeof(i_fcolor)); + *col = vals[i]; + sv = sv_newmortal(); + sv_setref_pv(sv, "Imager::Color::Float", (void *)col); + PUSHs(sv); + } + } + else if (count) { + EXTEND(SP, 1); + PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_fcolor)))); } myfree(vals); } @@ -3812,6 +3679,10 @@ i_img_16_new(x, y, ch) int y int ch +Imager::ImgRaw +i_img_to_rgb16(im) + Imager::ImgRaw im + Imager::ImgRaw i_img_double_new(x, y, ch) int x @@ -3869,12 +3740,14 @@ i_tags_find(im, name, start) CODE: if (i_tags_find(&im->tags, name, start, &entry)) { if (entry == 0) - ST(0) = sv_2mortal(newSVpv("0 but true", 0)); + RETVAL = newSVpv("0 but true", 0); else - ST(0) = sv_2mortal(newSViv(entry)); + RETVAL = newSViv(entry); } else { - ST(0) = &PL_sv_undef; + RETVAL = &PL_sv_undef; } + OUTPUT: + RETVAL SV * i_tags_findn(im, code, start) @@ -3886,12 +3759,15 @@ i_tags_findn(im, code, start) CODE: if (i_tags_findn(&im->tags, code, start, &entry)) { if (entry == 0) - ST(0) = sv_2mortal(newSVpv("0 but true", 0)); + RETVAL = newSVpv("0 but true", 0); else - ST(0) = sv_2mortal(newSViv(entry)); + RETVAL = newSViv(entry); } - else - ST(0) = &PL_sv_undef; + else { + RETVAL = &PL_sv_undef; + } + OUTPUT: + RETVAL int i_tags_delete(im, entry) @@ -3943,345 +3819,37 @@ i_tags_get(im, index) } } -int -i_tags_count(im) - Imager::ImgRaw im - CODE: - RETVAL = im->tags.count; - OUTPUT: - RETVAL - -#ifdef HAVE_WIN32 - -void -i_wf_bbox(face, size, text) - char *face - int size - char *text - int rc, i; - PREINIT: - int cords[BOUNDING_BOX_COUNT]; - PPCODE: - if (rc = i_wf_bbox(face, size, text, strlen(text), cords)) { - 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) - char *face - Imager::ImgRaw im - int tx - int ty - Imager::Color cl - int size - char *text - int align - int aa - CODE: - RETVAL = i_wf_text(face, im, tx, ty, cl, size, text, strlen(text), - align, aa); - OUTPUT: - RETVAL - -undef_int -i_wf_cp(face, im, tx, ty, channel, size, text, align, aa) - char *face - Imager::ImgRaw im - int tx - int ty - int channel - int size - char *text - int align - int aa - CODE: - RETVAL = i_wf_cp(face, im, tx, ty, channel, size, text, strlen(text), - align, aa); - OUTPUT: - RETVAL - - -#endif - -#ifdef HAVE_FT2 - -MODULE = Imager PACKAGE = Imager::Font::FT2 PREFIX=FT2_ - -#define FT2_DESTROY(font) i_ft2_destroy(font) - -void -FT2_DESTROY(font) - Imager::Font::FT2 font - -MODULE = Imager PACKAGE = Imager::Font::FreeType2 - -Imager::Font::FT2 -i_ft2_new(name, index) - char *name - int index - -undef_int -i_ft2_setdpi(font, xdpi, ydpi) - Imager::Font::FT2 font - int xdpi - int ydpi - -void -i_ft2_getdpi(font) - Imager::Font::FT2 font - PREINIT: - int xdpi, ydpi; - CODE: - if (i_ft2_getdpi(font, &xdpi, &ydpi)) { - EXTEND(SP, 2); - PUSHs(sv_2mortal(newSViv(xdpi))); - PUSHs(sv_2mortal(newSViv(ydpi))); - } - -undef_int -i_ft2_sethinting(font, hinting) - Imager::Font::FT2 font - int hinting - -undef_int -i_ft2_settransform(font, matrix) - Imager::Font::FT2 font - PREINIT: - double matrix[6]; - int len; - AV *av; - SV *sv1; - int i; - CODE: - if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV) - croak("i_ft2_settransform: parameter 2 must be an array ref\n"); - av=(AV*)SvRV(ST(1)); - len=av_len(av)+1; - if (len > 6) - len = 6; - for (i = 0; i < len; ++i) { - sv1=(*(av_fetch(av,i,0))); - matrix[i] = SvNV(sv1); - } - for (; i < 6; ++i) - matrix[i] = 0; - RETVAL = i_ft2_settransform(font, matrix); - OUTPUT: - RETVAL - -void -i_ft2_bbox(font, cheight, cwidth, text_sv, utf8) - Imager::Font::FT2 font - double cheight - double cwidth - SV *text_sv - int utf8 - PREINIT: - int bbox[BOUNDING_BOX_COUNT]; - int i; - char *text; - STRLEN text_len; - int rc; - PPCODE: - text = SvPV(text_sv, text_len); -#ifdef SvUTF8 - if (SvUTF8(text_sv)) - utf8 = 1; -#endif - rc = i_ft2_bbox(font, cheight, cwidth, text, text_len, bbox, utf8); - if (rc) { - EXTEND(SP, rc); - for (i = 0; i < rc; ++i) - PUSHs(sv_2mortal(newSViv(bbox[i]))); - } - -void -i_ft2_bbox_r(font, cheight, cwidth, text, vlayout, utf8) - Imager::Font::FT2 font - double cheight - double cwidth - char *text - int vlayout - int utf8 - PREINIT: - int bbox[8]; - int i; - PPCODE: -#ifdef SvUTF8 - if (SvUTF8(ST(3))) - utf8 = 1; -#endif - if (i_ft2_bbox_r(font, cheight, cwidth, text, strlen(text), vlayout, - utf8, bbox)) { - EXTEND(SP, 8); - for (i = 0; i < 8; ++i) - PUSHs(sv_2mortal(newSViv(bbox[i]))); - } - -undef_int -i_ft2_text(font, im, tx, ty, cl, cheight, cwidth, text, align, aa, vlayout, utf8) - Imager::Font::FT2 font - Imager::ImgRaw im - int tx - int ty - Imager::Color cl - double cheight - double cwidth - int align - int aa - int vlayout - int utf8 - PREINIT: - char *text; - STRLEN len; - CODE: -#ifdef SvUTF8 - if (SvUTF8(ST(7))) { - utf8 = 1; - } -#endif - text = SvPV(ST(7), len); - RETVAL = i_ft2_text(font, im, tx, ty, cl, cheight, cwidth, text, - len, align, aa, vlayout, utf8); - OUTPUT: - RETVAL - -undef_int -i_ft2_cp(font, im, tx, ty, channel, cheight, cwidth, text, align, aa, vlayout, utf8) - Imager::Font::FT2 font - Imager::ImgRaw im - int tx - int ty - int channel - double cheight - double cwidth - char *text - int align - int aa - int vlayout - int utf8 - CODE: -#ifdef SvUTF8 - if (SvUTF8(ST(7))) - utf8 = 1; -#endif - RETVAL = i_ft2_cp(font, im, tx, ty, channel, cheight, cwidth, text, - strlen(text), align, aa, vlayout, 1); - OUTPUT: - RETVAL - -void -ft2_transform_box(font, x0, x1, x2, x3) - Imager::Font::FT2 font - int x0 - int x1 - int x2 - int x3 - PREINIT: - int box[4]; - PPCODE: - box[0] = x0; box[1] = x1; box[2] = x2; box[3] = x3; - ft2_transform_box(font, box); - EXTEND(SP, 4); - PUSHs(sv_2mortal(newSViv(box[0]))); - PUSHs(sv_2mortal(newSViv(box[1]))); - PUSHs(sv_2mortal(newSViv(box[2]))); - PUSHs(sv_2mortal(newSViv(box[3]))); - void -i_ft2_has_chars(handle, text_sv, utf8) - Imager::Font::FT2 handle - SV *text_sv - int utf8 +i_tags_get_string(im, what_sv) + Imager::ImgRaw im + SV *what_sv PREINIT: - char *text; - STRLEN len; - char *work; - int count; - int i; + char const *name = NULL; + int code; + char buffer[200]; PPCODE: -#ifdef SvUTF8 - if (SvUTF8(text_sv)) - utf8 = 1; -#endif - text = SvPV(text_sv, len); - work = mymalloc(len); - count = i_ft2_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]))); - } + if (SvIOK(what_sv)) { + code = SvIV(what_sv); + name = NULL; } else { - EXTEND(SP, 1); - PUSHs(sv_2mortal(newSVpv(work, count))); - } - myfree(work); - -void -i_ft2_face_name(handle) - Imager::Font::FT2 handle - PREINIT: - char name[255]; - int len; - PPCODE: - len = i_ft2_face_name(handle, name, sizeof(name)); - if (len) { - EXTEND(SP, 1); - PUSHs(sv_2mortal(newSVpv(name, 0))); + name = SvPV_nolen(what_sv); + code = 0; } - -void -i_ft2_glyph_name(handle, text_sv, utf8 = 0) - Imager::Font::FT2 handle - SV *text_sv - int utf8 - PREINIT: - char const *text; - STRLEN work_len; - int len; - int outsize; - char name[255]; - PPCODE: -#ifdef SvUTF8 - if (SvUTF8(text_sv)) - utf8 = 1; -#endif - text = SvPV(text_sv, work_len); - len = work_len; - while (len) { - unsigned char ch; - if (utf8) { - ch = i_utf8_advance(&text, &len); - if (ch == ~0UL) { - i_push_error(0, "invalid UTF8 character"); - break; - } - } - else { - ch = *text++; - --len; - } + if (i_tags_get_string(&im->tags, name, code, buffer, sizeof(buffer))) { EXTEND(SP, 1); - if (outsize = i_ft2_glyph_name(handle, ch, name, sizeof(name))) { - PUSHs(sv_2mortal(newSVpv(name, 0))); - } - else { - PUSHs(&PL_sv_undef); - } + PUSHs(sv_2mortal(newSVpv(buffer, 0))); } int -i_ft2_can_do_glyph_names() +i_tags_count(im) + Imager::ImgRaw im + CODE: + RETVAL = im->tags.count; + OUTPUT: + RETVAL -int -i_ft2_face_has_glyph_names(handle) - Imager::Font::FT2 handle -#endif MODULE = Imager PACKAGE = Imager::FillHandle PREFIX=IFILL_ @@ -4289,6 +3857,13 @@ void IFILL_DESTROY(fill) Imager::FillHandle fill +int +IFILL_CLONE_SKIP(...) + CODE: + RETVAL = 1; + OUTPUT: + RETVAL + MODULE = Imager PACKAGE = Imager Imager::FillHandle @@ -4378,3 +3953,48 @@ i_new_fill_image(src, matrix, xoff, yoff, combine) RETVAL = i_new_fill_image(src, matrixp, xoff, yoff, combine); OUTPUT: RETVAL + +MODULE = Imager PACKAGE = Imager::Internal::Hlines PREFIX=i_int_hlines_ + +# this class is only exposed for testing + +int +i_int_hlines_testing() + +#if i_int_hlines_testing() + +Imager::Internal::Hlines +i_int_hlines_new(start_y, count_y, start_x, count_x) + int start_y + int count_y + int start_x + int count_x + +Imager::Internal::Hlines +i_int_hlines_new_img(im) + Imager::ImgRaw im + +void +i_int_hlines_add(hlines, y, minx, width) + Imager::Internal::Hlines hlines + int y + int minx + int width + +void +i_int_hlines_DESTROY(hlines) + Imager::Internal::Hlines hlines + +SV * +i_int_hlines_dump(hlines) + Imager::Internal::Hlines hlines + +int +i_int_hlines_CLONE_SKIP(cls) + SV *cls + +#endif + +BOOT: + PERL_SET_GLOBAL_CALLBACKS; + PERL_PL_SET_GLOBAL_CALLBACKS; \ No newline at end of file