1 #define PERL_NO_GET_CONTEXT
8 #define NEED_newRV_noinc
9 #define NEED_sv_2pv_nolen
15 #define i_int_hlines_testing() 1
22 #include "imextpltypes.h"
24 #if i_int_hlines_testing()
30 /* These functions are all shared - then comes platform dependant code */
31 static int getstr(void *hv_t,char *key,char **store) {
36 mm_log((1,"getstr(hv_t 0x%X, key %s, store 0x%X)\n",hv_t,key,store));
38 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
40 svpp=hv_fetch(hv, key, strlen(key), 0);
41 *store=SvPV(*svpp, PL_na );
46 static int getint(void *hv_t,char *key,int *store) {
51 mm_log((1,"getint(hv_t 0x%X, key %s, store 0x%X)\n",hv_t,key,store));
53 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
55 svpp=hv_fetch(hv, key, strlen(key), 0);
56 *store=(int)SvIV(*svpp);
60 static int getdouble(void *hv_t,char* key,double *store) {
65 mm_log((1,"getdouble(hv_t 0x%X, key %s, store 0x%X)\n",hv_t,key,store));
67 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
68 svpp=hv_fetch(hv, key, strlen(key), 0);
69 *store=(float)SvNV(*svpp);
73 static int getvoid(void *hv_t,char* key,void **store) {
78 mm_log((1,"getvoid(hv_t 0x%X, key %s, store 0x%X)\n",hv_t,key,store));
80 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
82 svpp=hv_fetch(hv, key, strlen(key), 0);
83 *store = INT2PTR(void*, SvIV(*svpp));
88 static int getobj(void *hv_t,char *key,char *type,void **store) {
93 mm_log((1,"getobj(hv_t 0x%X, key %s,type %s, store 0x%X)\n",hv_t,key,type,store));
95 if ( !hv_exists(hv,key,strlen(key)) ) return 0;
97 svpp=hv_fetch(hv, key, strlen(key), 0);
99 if (sv_derived_from(*svpp,type)) {
100 IV tmp = SvIV((SV*)SvRV(*svpp));
101 *store = INT2PTR(void*, tmp);
103 mm_log((1,"getobj: key exists in hash but is not of correct type"));
110 UTIL_table_t i_UTIL_table={getstr,getint,getdouble,getvoid,getobj};
112 void my_SvREFCNT_dec(void *p) {
114 SvREFCNT_dec((SV*)p);
119 i_log_entry(char *string, int level) {
120 mm_log((level, string));
124 typedef struct i_reader_data_tag
126 /* presumably a CODE ref or name of a sub */
130 /* used by functions that want callbacks */
131 static int read_callback(char *userdata, char *buffer, int need, int want) {
133 i_reader_data *rd = (i_reader_data *)userdata;
137 dSP; dTARG = sv_newmortal();
138 /* thanks to Simon Cozens for help with the dTARG above */
148 count = perl_call_sv(rd->sv, G_SCALAR);
153 croak("Result of perl_call_sv(..., G_SCALAR) != 1");
159 char *ptr = SvPV(data, len);
161 croak("Too much data returned in reader callback");
163 memcpy(buffer, ptr, len);
179 SV *sv; /* a coderef or sub name */
182 /* used by functions that want callbacks */
183 static int write_callback(char *userdata, char const *data, int size) {
185 i_writer_data *wd = (i_writer_data *)userdata;
195 XPUSHs(sv_2mortal(newSVpv((char *)data, size)));
198 count = perl_call_sv(wd->sv, G_SCALAR);
203 croak("Result of perl_call_sv(..., G_SCALAR) != 1");
206 success = SvTRUE(sv);
216 #define CBDATA_BUFSIZE 8192
219 /* the SVs we use to call back to Perl */
225 /* we need to remember whether the buffer contains write data or
231 /* how far we've read into the buffer (not used for writing) */
234 /* the amount of space used/data available in the buffer */
237 /* the maximum amount to fill the buffer before flushing
238 If any write is larger than this then the buffer is flushed and
239 the full write is performed. The write is _not_ split into
244 char buffer[CBDATA_BUFSIZE];
249 call_writer(cbd, buf, size)
251 Low-level function to call the perl writer callback.
255 static ssize_t call_writer(struct cbdata *cbd, void const *buf, size_t size) {
262 if (!SvOK(cbd->writecb))
269 PUSHs(sv_2mortal(newSVpv((char *)buf, size)));
272 count = perl_call_sv(cbd->writecb, G_SCALAR);
276 croak("Result of perl_call_sv(..., G_SCALAR) != 1");
279 success = SvTRUE(sv);
286 return success ? size : -1;
289 static ssize_t call_reader(struct cbdata *cbd, void *buf, size_t size,
297 if (!SvOK(cbd->readcb))
304 PUSHs(sv_2mortal(newSViv(size)));
305 PUSHs(sv_2mortal(newSViv(maxread)));
308 count = perl_call_sv(cbd->readcb, G_SCALAR);
313 croak("Result of perl_call_sv(..., G_SCALAR) != 1");
319 char *ptr = SvPV(data, len);
321 croak("Too much data returned in reader callback");
323 memcpy(buf, ptr, len);
337 static ssize_t write_flush(struct cbdata *cbd) {
342 result = call_writer(cbd, cbd->buffer, cbd->used);
347 return 1; /* success of some sort */
351 static off_t io_seeker(void *p, off_t offset, int whence) {
353 struct cbdata *cbd = p;
358 if (!SvOK(cbd->seekcb))
362 if (cbd->used && write_flush(cbd) <= 0)
366 if (whence == SEEK_CUR && cbd->reading && cbd->where != cbd->used) {
367 offset -= cbd->where - cbd->used;
370 cbd->where = cbd->used = 0;
376 PUSHs(sv_2mortal(newSViv(offset)));
377 PUSHs(sv_2mortal(newSViv(whence)));
380 count = perl_call_sv(cbd->seekcb, G_SCALAR);
385 croak("Result of perl_call_sv(..., G_SCALAR) != 1");
396 static ssize_t io_writer(void *p, void const *data, size_t size) {
398 struct cbdata *cbd = p;
400 /* printf("io_writer(%p, %p, %u)\n", p, data, size); */
402 if (cbd->reading && cbd->where < cbd->used) {
403 /* we read past the place where the caller expected us to be
404 so adjust our position a bit */
405 if (io_seeker(p, cbd->where - cbd->used, SEEK_CUR) < 0) {
410 cbd->where = cbd->used = 0;
413 if (cbd->used && cbd->used + size > cbd->maxlength) {
414 int write_res = write_flush(cbd);
415 if (write_res <= 0) {
420 if (cbd->used+size <= cbd->maxlength) {
421 memcpy(cbd->buffer + cbd->used, data, size);
425 /* it doesn't fit - just pass it up */
426 return call_writer(cbd, data, size);
430 io_reader(void *p, void *data, size_t size) {
432 struct cbdata *cbd = p;
434 char *out = data; /* so we can do pointer arithmetic */
436 /* printf("io_reader(%p, %p, %d)\n", p, data, size); */
438 if (write_flush(cbd) <= 0)
444 if (size <= cbd->used - cbd->where) {
446 memcpy(data, cbd->buffer+cbd->where, size);
451 memcpy(out, cbd->buffer + cbd->where, cbd->used - cbd->where);
452 total += cbd->used - cbd->where;
453 size -= cbd->used - cbd->where;
454 out += cbd->used - cbd->where;
455 if (size < sizeof(cbd->buffer)) {
459 && (did_read = call_reader(cbd, cbd->buffer, size,
460 sizeof(cbd->buffer))) > 0) {
462 cbd->used = did_read;
464 copy_size = i_min(size, cbd->used);
465 memcpy(out, cbd->buffer, copy_size);
466 cbd->where += copy_size;
475 /* just read the rest - too big for our buffer*/
477 while ((did_read = call_reader(cbd, out, size, size)) > 0) {
489 static int io_closer(void *p) {
491 struct cbdata *cbd = p;
493 if (cbd->writing && cbd->used > 0) {
494 if (write_flush(cbd) < 0)
499 if (SvOK(cbd->closecb)) {
507 perl_call_sv(cbd->closecb, G_VOID);
518 static void io_destroyer(void *p) {
520 struct cbdata *cbd = p;
522 SvREFCNT_dec(cbd->writecb);
523 SvREFCNT_dec(cbd->readcb);
524 SvREFCNT_dec(cbd->seekcb);
525 SvREFCNT_dec(cbd->closecb);
533 static int lookup_name(struct value_name *names, int count, char *name, int def_value)
536 for (i = 0; i < count; ++i)
537 if (strEQ(names[i].name, name))
538 return names[i].value;
542 static struct value_name transp_names[] =
545 { "threshold", tr_threshold },
546 { "errdiff", tr_errdiff },
547 { "ordered", tr_ordered, },
550 static struct value_name make_color_names[] =
552 { "none", mc_none, },
553 { "webmap", mc_web_map, },
554 { "addi", mc_addi, },
555 { "mediancut", mc_median_cut, },
556 { "mono", mc_mono, },
557 { "monochrome", mc_mono, },
560 static struct value_name translate_names[] =
562 { "giflib", pt_giflib, },
563 { "closest", pt_closest, },
564 { "perturb", pt_perturb, },
565 { "errdiff", pt_errdiff, },
568 static struct value_name errdiff_names[] =
570 { "floyd", ed_floyd, },
571 { "jarvis", ed_jarvis, },
572 { "stucki", ed_stucki, },
573 { "custom", ed_custom, },
576 static struct value_name orddith_names[] =
578 { "random", od_random, },
579 { "dot8", od_dot8, },
580 { "dot4", od_dot4, },
581 { "hline", od_hline, },
582 { "vline", od_vline, },
583 { "/line", od_slashline, },
584 { "slashline", od_slashline, },
585 { "\\line", od_backline, },
586 { "backline", od_backline, },
587 { "tiny", od_tiny, },
588 { "custom", od_custom, },
591 /* look through the hash for quantization options */
593 ip_handle_quant_opts(pTHX_ i_quantize *quant, HV *hv)
595 /*** POSSIBLY BROKEN: do I need to unref the SV from hv_fetch ***/
601 quant->mc_colors = mymalloc(quant->mc_size * sizeof(i_color));
603 sv = hv_fetch(hv, "transp", 6, 0);
604 if (sv && *sv && (str = SvPV(*sv, len))) {
606 lookup_name(transp_names, sizeof(transp_names)/sizeof(*transp_names),
608 if (quant->transp != tr_none) {
609 quant->tr_threshold = 127;
610 sv = hv_fetch(hv, "tr_threshold", 12, 0);
612 quant->tr_threshold = SvIV(*sv);
614 if (quant->transp == tr_errdiff) {
615 sv = hv_fetch(hv, "tr_errdiff", 10, 0);
616 if (sv && *sv && (str = SvPV(*sv, len)))
617 quant->tr_errdiff = lookup_name(errdiff_names, sizeof(errdiff_names)/sizeof(*errdiff_names), str, ed_floyd);
619 if (quant->transp == tr_ordered) {
620 quant->tr_orddith = od_tiny;
621 sv = hv_fetch(hv, "tr_orddith", 10, 0);
622 if (sv && *sv && (str = SvPV(*sv, len)))
623 quant->tr_orddith = lookup_name(orddith_names, sizeof(orddith_names)/sizeof(*orddith_names), str, od_random);
625 if (quant->tr_orddith == od_custom) {
626 sv = hv_fetch(hv, "tr_map", 6, 0);
627 if (sv && *sv && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
628 AV *av = (AV*)SvRV(*sv);
629 len = av_len(av) + 1;
630 if (len > sizeof(quant->tr_custom))
631 len = sizeof(quant->tr_custom);
632 for (i = 0; i < len; ++i) {
633 SV **sv2 = av_fetch(av, i, 0);
635 quant->tr_custom[i] = SvIV(*sv2);
638 while (i < sizeof(quant->tr_custom))
639 quant->tr_custom[i++] = 0;
644 quant->make_colors = mc_addi;
645 sv = hv_fetch(hv, "make_colors", 11, 0);
646 if (sv && *sv && (str = SvPV(*sv, len))) {
648 lookup_name(make_color_names, sizeof(make_color_names)/sizeof(*make_color_names), str, mc_addi);
650 sv = hv_fetch(hv, "colors", 6, 0);
651 if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
652 /* needs to be an array of Imager::Color
653 note that the caller allocates the mc_color array and sets mc_size
655 AV *av = (AV *)SvRV(*sv);
656 quant->mc_count = av_len(av)+1;
657 if (quant->mc_count > quant->mc_size)
658 quant->mc_count = quant->mc_size;
659 for (i = 0; i < quant->mc_count; ++i) {
660 SV **sv1 = av_fetch(av, i, 0);
661 if (sv1 && *sv1 && SvROK(*sv1) && sv_derived_from(*sv1, "Imager::Color")) {
662 i_color *col = INT2PTR(i_color *, SvIV((SV*)SvRV(*sv1)));
663 quant->mc_colors[i] = *col;
667 sv = hv_fetch(hv, "max_colors", 10, 0);
670 if (i <= quant->mc_size && i >= quant->mc_count)
674 quant->translate = pt_closest;
675 sv = hv_fetch(hv, "translate", 9, 0);
676 if (sv && *sv && (str = SvPV(*sv, len))) {
677 quant->translate = lookup_name(translate_names, sizeof(translate_names)/sizeof(*translate_names), str, pt_closest);
679 sv = hv_fetch(hv, "errdiff", 7, 0);
680 if (sv && *sv && (str = SvPV(*sv, len))) {
681 quant->errdiff = lookup_name(errdiff_names, sizeof(errdiff_names)/sizeof(*errdiff_names), str, ed_floyd);
683 if (quant->translate == pt_errdiff && quant->errdiff == ed_custom) {
684 /* get the error diffusion map */
685 sv = hv_fetch(hv, "errdiff_width", 13, 0);
687 quant->ed_width = SvIV(*sv);
688 sv = hv_fetch(hv, "errdiff_height", 14, 0);
690 quant->ed_height = SvIV(*sv);
691 sv = hv_fetch(hv, "errdiff_orig", 12, 0);
693 quant->ed_orig = SvIV(*sv);
694 if (quant->ed_width > 0 && quant->ed_height > 0) {
696 quant->ed_map = mymalloc(sizeof(int)*quant->ed_width*quant->ed_height);
697 sv = hv_fetch(hv, "errdiff_map", 11, 0);
698 if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
699 AV *av = (AV*)SvRV(*sv);
700 len = av_len(av) + 1;
701 if (len > quant->ed_width * quant->ed_height)
702 len = quant->ed_width * quant->ed_height;
703 for (i = 0; i < len; ++i) {
704 SV **sv2 = av_fetch(av, i, 0);
706 quant->ed_map[i] = SvIV(*sv2);
707 sum += quant->ed_map[i];
713 myfree(quant->ed_map);
715 quant->errdiff = ed_floyd;
719 sv = hv_fetch(hv, "perturb", 7, 0);
721 quant->perturb = SvIV(*sv);
725 ip_cleanup_quant_opts(pTHX_ i_quantize *quant) {
726 myfree(quant->mc_colors);
728 myfree(quant->ed_map);
731 /* copies the color map from the hv into the colors member of the HV */
733 ip_copy_colors_back(pTHX_ HV *hv, i_quantize *quant) {
739 sv = hv_fetch(hv, "colors", 6, 0);
740 if (!sv || !*sv || !SvROK(*sv) || SvTYPE(SvRV(*sv)) != SVt_PVAV) {
745 av = (AV *)SvRV(*sv);
747 av_extend(av, quant->mc_count+1);
748 for (i = 0; i < quant->mc_count; ++i) {
749 i_color *in = quant->mc_colors+i;
750 Imager__Color c = ICL_new_internal(in->rgb.r, in->rgb.g, in->rgb.b, 255);
751 work = sv_newmortal();
752 sv_setref_pv(work, "Imager::Color", (void *)c);
758 /* loads the segments of a fountain fill into an array */
759 static i_fountain_seg *
760 load_fount_segs(pTHX_ AV *asegs, int *count) {
761 /* Each element of segs must contain:
762 [ start, middle, end, c0, c1, segtype, colortrans ]
763 start, middle, end are doubles from 0 to 1
764 c0, c1 are Imager::Color::Float or Imager::Color objects
765 segtype, colortrans are ints
769 i_fountain_seg *segs;
773 *count = av_len(asegs)+1;
775 croak("i_fountain must have at least one segment");
776 segs = mymalloc(sizeof(i_fountain_seg) * *count);
777 for(i = 0; i < *count; i++) {
778 SV **sv1 = av_fetch(asegs, i, 0);
779 if (!sv1 || !*sv1 || !SvROK(*sv1)
780 || SvTYPE(SvRV(*sv1)) != SVt_PVAV) {
782 croak("i_fountain: segs must be an arrayref of arrayrefs");
784 aseg = (AV *)SvRV(*sv1);
785 if (av_len(aseg) != 7-1) {
787 croak("i_fountain: a segment must have 7 members");
789 for (j = 0; j < 3; ++j) {
790 SV **sv2 = av_fetch(aseg, j, 0);
793 croak("i_fountain: XS error");
795 work[j] = SvNV(*sv2);
797 segs[i].start = work[0];
798 segs[i].middle = work[1];
799 segs[i].end = work[2];
800 for (j = 0; j < 2; ++j) {
801 SV **sv3 = av_fetch(aseg, 3+j, 0);
802 if (!sv3 || !*sv3 || !SvROK(*sv3) ||
803 (!sv_derived_from(*sv3, "Imager::Color")
804 && !sv_derived_from(*sv3, "Imager::Color::Float"))) {
806 croak("i_fountain: segs must contain colors in elements 3 and 4");
808 if (sv_derived_from(*sv3, "Imager::Color::Float")) {
809 segs[i].c[j] = *INT2PTR(i_fcolor *, SvIV((SV *)SvRV(*sv3)));
812 i_color c = *INT2PTR(i_color *, SvIV((SV *)SvRV(*sv3)));
814 for (ch = 0; ch < MAXCHANNELS; ++ch) {
815 segs[i].c[j].channel[ch] = c.channel[ch] / 255.0;
819 for (j = 0; j < 2; ++j) {
820 SV **sv2 = av_fetch(aseg, j+5, 0);
823 croak("i_fountain: XS error");
825 worki[j] = SvIV(*sv2);
827 segs[i].type = worki[0];
828 segs[i].color = worki[1];
834 /* validates the indexes supplied to i_ppal
836 i_ppal() doesn't do that for speed, but I'm not comfortable doing that
841 validate_i_ppal(i_img *im, i_palidx const *indexes, int count) {
842 int color_count = i_colorcount(im);
845 if (color_count == -1)
846 croak("i_plin() called on direct color image");
848 for (i = 0; i < count; ++i) {
849 if (indexes[i] >= color_count) {
850 croak("i_plin() called with out of range color index %d (max %d)",
851 indexes[i], color_count-1);
857 /* I don't think ICLF_* names belong at the C interface
858 this makes the XS code think we have them, to let us avoid
859 putting function bodies in the XS code
861 #define ICLF_new_internal(r, g, b, a) i_fcolor_new((r), (g), (b), (a))
862 #define ICLF_DESTROY(cl) i_fcolor_destroy(cl)
865 /* the m_init_log() function was called init_log(), renamed to reduce
866 potential naming conflicts */
867 #define init_log m_init_log
869 #if i_int_hlines_testing()
871 typedef i_int_hlines *Imager__Internal__Hlines;
873 static i_int_hlines *
874 i_int_hlines_new(int start_y, int count_y, int start_x, int count_x) {
875 i_int_hlines *result = mymalloc(sizeof(i_int_hlines));
876 i_int_init_hlines(result, start_y, count_y, start_x, count_x);
881 static i_int_hlines *
882 i_int_hlines_new_img(i_img *im) {
883 i_int_hlines *result = mymalloc(sizeof(i_int_hlines));
884 i_int_init_hlines_img(result, im);
890 i_int_hlines_DESTROY(i_int_hlines *hlines) {
891 i_int_hlines_destroy(hlines);
895 #define i_int_hlines_CLONE_SKIP(cls) 1
897 static int seg_compare(const void *vleft, const void *vright) {
898 const i_int_hline_seg *left = vleft;
899 const i_int_hline_seg *right = vright;
901 return left->minx - right->minx;
905 i_int_hlines_dump(i_int_hlines *hlines) {
907 SV *dump = newSVpvf("start_y: %d limit_y: %d start_x: %d limit_x: %d\n",
908 hlines->start_y, hlines->limit_y, hlines->start_x, hlines->limit_x);
911 for (y = hlines->start_y; y < hlines->limit_y; ++y) {
912 i_int_hline_entry *entry = hlines->entries[y-hlines->start_y];
915 /* sort the segments, if any */
917 qsort(entry->segs, entry->count, sizeof(i_int_hline_seg), seg_compare);
919 sv_catpvf(dump, " %d (%d):", y, entry->count);
920 for (i = 0; i < entry->count; ++i) {
921 sv_catpvf(dump, " [%d, %d)", entry->segs[i].minx,
922 entry->segs[i].x_limit);
924 sv_catpv(dump, "\n");
933 static im_pl_ext_funcs im_perl_funcs =
935 IMAGER_PL_API_VERSION,
937 ip_handle_quant_opts,
938 ip_cleanup_quant_opts,
942 #define PERL_PL_SET_GLOBAL_CALLBACKS \
943 sv_setiv(get_sv(PERL_PL_FUNCTION_TABLE_NAME, 1), PTR2IV(&im_perl_funcs));
946 #define i_exif_enabled() 1
948 #define i_exif_enabled() 0
951 /* trying to use more C style names, map them here */
952 #define i_io_DESTROY(ig) io_glue_destroy(ig)
954 #define i_img_get_width(im) ((im)->xsize)
955 #define i_img_get_height(im) ((im)->ysize)
957 MODULE = Imager PACKAGE = Imager::Color PREFIX = ICL_
960 ICL_new_internal(r,g,b,a)
972 ICL_set_internal(cl,r,g,b,a)
979 ICL_set_internal(cl, r, g, b, a);
993 PUSHs(sv_2mortal(newSVnv(cl->rgba.r)));
994 PUSHs(sv_2mortal(newSVnv(cl->rgba.g)));
995 PUSHs(sv_2mortal(newSVnv(cl->rgba.b)));
996 PUSHs(sv_2mortal(newSVnv(cl->rgba.a)));
1002 RETVAL = mymalloc(sizeof(i_color));
1004 i_hsv_to_rgb(RETVAL);
1012 RETVAL = mymalloc(sizeof(i_color));
1014 i_rgb_to_hsv(RETVAL);
1020 MODULE = Imager PACKAGE = Imager::Color::Float PREFIX=ICLF_
1022 Imager::Color::Float
1023 ICLF_new_internal(r, g, b, a)
1031 Imager::Color::Float cl
1035 Imager::Color::Float cl
1039 EXTEND(SP, MAXCHANNELS);
1040 for (ch = 0; ch < MAXCHANNELS; ++ch) {
1041 /* printf("%d: %g\n", ch, cl->channel[ch]); */
1042 PUSHs(sv_2mortal(newSVnv(cl->channel[ch])));
1046 ICLF_set_internal(cl,r,g,b,a)
1047 Imager::Color::Float cl
1060 Imager::Color::Float
1062 Imager::Color::Float c
1064 RETVAL = mymalloc(sizeof(i_fcolor));
1066 i_hsv_to_rgbf(RETVAL);
1070 Imager::Color::Float
1072 Imager::Color::Float c
1074 RETVAL = mymalloc(sizeof(i_fcolor));
1076 i_rgb_to_hsvf(RETVAL);
1080 MODULE = Imager PACKAGE = Imager::ImgRaw PREFIX = IIM_
1094 MODULE = Imager PACKAGE = Imager
1113 SvPV(ST(0), length);
1114 SvREFCNT_inc(ST(0));
1115 RETVAL = io_new_buffer(data, length, my_SvREFCNT_dec, ST(0));
1120 io_new_cb(writecb, readcb, seekcb, closecb, maxwrite = CBDATA_BUFSIZE)
1129 cbd = mymalloc(sizeof(struct cbdata));
1130 SvREFCNT_inc(writecb);
1131 cbd->writecb = writecb;
1132 SvREFCNT_inc(readcb);
1133 cbd->readcb = readcb;
1134 SvREFCNT_inc(seekcb);
1135 cbd->seekcb = seekcb;
1136 SvREFCNT_inc(closecb);
1137 cbd->closecb = closecb;
1138 cbd->reading = cbd->writing = cbd->where = cbd->used = 0;
1139 if (maxwrite > CBDATA_BUFSIZE)
1140 maxwrite = CBDATA_BUFSIZE;
1141 cbd->maxlength = maxwrite;
1142 RETVAL = io_new_cb(cbd, io_reader, io_writer, io_seeker, io_closer,
1151 unsigned char* data;
1155 tlength = io_slurp(ig, &data);
1157 PUSHs(sv_2mortal(newSVpv((char *)data,tlength)));
1162 i_set_image_file_limits(width, height, bytes)
1168 i_get_image_file_limits()
1170 int width, height, bytes;
1172 if (i_get_image_file_limits(&width, &height, &bytes)) {
1174 PUSHs(sv_2mortal(newSViv(width)));
1175 PUSHs(sv_2mortal(newSViv(height)));
1176 PUSHs(sv_2mortal(newSViv(bytes)));
1179 MODULE = Imager PACKAGE = Imager::IO PREFIX = i_io_
1182 i_io_write(ig, data_sv)
1190 if (SvUTF8(data_sv)) {
1191 data_sv = sv_2mortal(newSVsv(data_sv));
1192 /* yes, we want this to croak() if the SV can't be downgraded */
1193 sv_utf8_downgrade(data_sv, FALSE);
1196 data = SvPV(data_sv, size);
1197 RETVAL = i_io_write(ig, data, size);
1202 i_io_read(ig, buffer_sv, size)
1211 croak("size negative in call to i_io_read()");
1212 /* prevent an undefined value warning if they supplied an
1214 Orginally conditional on !SvOK(), but this will prevent the
1215 downgrade from croaking */
1216 sv_setpvn(buffer_sv, "", 0);
1218 if (SvUTF8(buffer_sv))
1219 sv_utf8_downgrade(buffer_sv, FALSE);
1221 buffer = SvGROW(buffer_sv, size+1);
1222 result = i_io_read(ig, buffer, size);
1224 SvCUR_set(buffer_sv, result);
1225 *SvEND(buffer_sv) = '\0';
1226 SvPOK_only(buffer_sv);
1228 PUSHs(sv_2mortal(newSViv(result)));
1234 i_io_read2(ig, size)
1243 croak("size negative in call to i_io_read2()");
1244 buffer_sv = newSV(size);
1245 buffer = SvGROW(buffer_sv, size+1);
1246 result = i_io_read(ig, buffer, size);
1248 SvCUR_set(buffer_sv, result);
1249 *SvEND(buffer_sv) = '\0';
1250 SvPOK_only(buffer_sv);
1252 PUSHs(sv_2mortal(buffer_sv));
1256 SvREFCNT_dec(buffer_sv);
1260 i_io_seek(ig, position, whence)
1274 i_io_CLONE_SKIP(...)
1280 MODULE = Imager PACKAGE = Imager
1291 while( (item=i_format_list[i++]) != NULL ) {
1293 PUSHs(sv_2mortal(newSVpv(item,0)));
1310 i_img_empty_ch(im,x,y,ch)
1317 i_sametype(im, x, y)
1323 i_sametype_chans(im, x, y, channels)
1330 i_init_log(name_sv,level)
1334 const char *name = SvOK(name_sv) ? SvPV_nolen(name_sv) : NULL;
1336 i_init_log(name, level);
1339 i_log_entry(string,level)
1358 i_img_info(im,info);
1360 PUSHs(sv_2mortal(newSViv(info[0])));
1361 PUSHs(sv_2mortal(newSViv(info[1])));
1362 PUSHs(sv_2mortal(newSViv(info[2])));
1363 PUSHs(sv_2mortal(newSViv(info[3])));
1369 i_img_setmask(im,ch_mask)
1378 i_img_getchannels(im)
1387 sv_2mortal(newSVpv((char *)im->idata, im->bytes))
1395 i_img_get_height(im)
1400 i_img_is_monochrome(im)
1406 result = i_img_is_monochrome(im, &zero_is_white);
1408 if (GIMME_V == G_ARRAY) {
1411 PUSHs(sv_2mortal(newSViv(zero_is_white)));
1420 i_line(im,x1,y1,x2,y2,val,endp)
1430 i_line_aa(im,x1,y1,x2,y2,val,endp)
1440 i_box(im,x1,y1,x2,y2,val)
1449 i_box_filled(im,x1,y1,x2,y2,val)
1458 i_box_cfill(im,x1,y1,x2,y2,fill)
1464 Imager::FillHandle fill
1467 i_arc(im,x,y,rad,d1,d2,val)
1477 i_arc_aa(im,x,y,rad,d1,d2,val)
1487 i_arc_cfill(im,x,y,rad,d1,d2,fill)
1494 Imager::FillHandle fill
1497 i_arc_aa_cfill(im,x,y,rad,d1,d2,fill)
1504 Imager::FillHandle fill
1508 i_circle_aa(im,x,y,rad,val)
1516 i_circle_out(im,x,y,rad,val)
1524 i_circle_out_aa(im,x,y,rad,val)
1532 i_arc_out(im,x,y,rad,d1,d2,val)
1542 i_arc_out_aa(im,x,y,rad,d1,d2,val)
1553 i_bezier_multi(im,xc,yc,val)
1566 if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_bezier_multi must be a reference to an array\n");
1567 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_bezier_multi must be a reference to an array\n");
1568 if (!SvROK(ST(2))) croak("Imager: Parameter 2 to i_bezier_multi must be a reference to an array\n");
1569 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 2 to i_bezier_multi must be a reference to an array\n");
1570 av1=(AV*)SvRV(ST(1));
1571 av2=(AV*)SvRV(ST(2));
1572 if (av_len(av1) != av_len(av2)) croak("Imager: x and y arrays to i_bezier_multi must be equal length\n");
1574 x=mymalloc( len*sizeof(double) );
1575 y=mymalloc( len*sizeof(double) );
1576 for(i=0;i<len;i++) {
1577 sv1=(*(av_fetch(av1,i,0)));
1578 sv2=(*(av_fetch(av2,i,0)));
1579 x[i]=(double)SvNV(sv1);
1580 y[i]=(double)SvNV(sv2);
1582 i_bezier_multi(im,len,x,y,val);
1588 i_poly_aa(im,xc,yc,val)
1601 if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
1602 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
1603 if (!SvROK(ST(2))) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
1604 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
1605 av1=(AV*)SvRV(ST(1));
1606 av2=(AV*)SvRV(ST(2));
1607 if (av_len(av1) != av_len(av2)) croak("Imager: x and y arrays to i_poly_aa must be equal length\n");
1609 x=mymalloc( len*sizeof(double) );
1610 y=mymalloc( len*sizeof(double) );
1611 for(i=0;i<len;i++) {
1612 sv1=(*(av_fetch(av1,i,0)));
1613 sv2=(*(av_fetch(av2,i,0)));
1614 x[i]=(double)SvNV(sv1);
1615 y[i]=(double)SvNV(sv2);
1617 RETVAL = i_poly_aa(im,len,x,y,val);
1624 i_poly_aa_cfill(im,xc,yc,fill)
1626 Imager::FillHandle fill
1636 if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
1637 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
1638 if (!SvROK(ST(2))) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
1639 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
1640 av1=(AV*)SvRV(ST(1));
1641 av2=(AV*)SvRV(ST(2));
1642 if (av_len(av1) != av_len(av2)) croak("Imager: x and y arrays to i_poly_aa_cfill must be equal length\n");
1644 x=mymalloc( len*sizeof(double) );
1645 y=mymalloc( len*sizeof(double) );
1646 for(i=0;i<len;i++) {
1647 sv1=(*(av_fetch(av1,i,0)));
1648 sv2=(*(av_fetch(av2,i,0)));
1649 x[i]=(double)SvNV(sv1);
1650 y[i]=(double)SvNV(sv2);
1652 RETVAL = i_poly_aa_cfill(im,len,x,y,fill);
1661 i_flood_fill(im,seedx,seedy,dcol)
1668 i_flood_cfill(im,seedx,seedy,fill)
1672 Imager::FillHandle fill
1675 i_flood_fill_border(im,seedx,seedy,dcol, border)
1680 Imager::Color border
1683 i_flood_cfill_border(im,seedx,seedy,fill, border)
1687 Imager::FillHandle fill
1688 Imager::Color border
1692 i_copyto(im,src,x1,y1,x2,y2,tx,ty)
1704 i_copyto_trans(im,src,x1,y1,x2,y2,tx,ty,trans)
1721 i_rubthru(im,src,tx,ty,src_minx,src_miny,src_maxx,src_maxy)
1732 i_compose(out, src, out_left, out_top, src_left, src_top, width, height, combine = ic_normal, opacity = 0.0)
1745 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)
1761 i_flipxy(im, direction)
1766 i_rotate90(im, degrees)
1771 i_rotate_exact(im, amount, ...)
1775 i_color *backp = NULL;
1776 i_fcolor *fbackp = NULL;
1780 /* extract the bg colors if any */
1781 /* yes, this is kind of strange */
1782 for (i = 2; i < items; ++i) {
1784 if (sv_derived_from(sv1, "Imager::Color")) {
1785 IV tmp = SvIV((SV*)SvRV(sv1));
1786 backp = INT2PTR(i_color *, tmp);
1788 else if (sv_derived_from(sv1, "Imager::Color::Float")) {
1789 IV tmp = SvIV((SV*)SvRV(sv1));
1790 fbackp = INT2PTR(i_fcolor *, tmp);
1793 RETVAL = i_rotate_exact_bg(im, amount, backp, fbackp);
1798 i_matrix_transform(im, xsize, ysize, matrix, ...)
1808 i_color *backp = NULL;
1809 i_fcolor *fbackp = NULL;
1811 if (!SvROK(ST(3)) || SvTYPE(SvRV(ST(3))) != SVt_PVAV)
1812 croak("i_matrix_transform: parameter 4 must be an array ref\n");
1813 av=(AV*)SvRV(ST(3));
1817 for (i = 0; i < len; ++i) {
1818 sv1=(*(av_fetch(av,i,0)));
1819 matrix[i] = SvNV(sv1);
1823 /* extract the bg colors if any */
1824 /* yes, this is kind of strange */
1825 for (i = 4; i < items; ++i) {
1827 if (sv_derived_from(sv1, "Imager::Color")) {
1828 IV tmp = SvIV((SV*)SvRV(sv1));
1829 backp = INT2PTR(i_color *, tmp);
1831 else if (sv_derived_from(sv1, "Imager::Color::Float")) {
1832 IV tmp = SvIV((SV*)SvRV(sv1));
1833 fbackp = INT2PTR(i_fcolor *, tmp);
1836 RETVAL = i_matrix_transform_bg(im, xsize, ysize, matrix, backp, fbackp);
1841 i_gaussian(im,stdev)
1846 i_unsharp_mask(im,stdev,scale)
1861 len = av_len(coef) + 1;
1862 c_coef=mymalloc( len * sizeof(double) );
1863 for(i = 0; i < len; i++) {
1864 sv1 = (*(av_fetch(coef, i, 0)));
1865 c_coef[i] = (double)SvNV(sv1);
1867 RETVAL = i_conv(im, c_coef, len);
1873 i_convert(src, avmain)
1885 outchan = av_len(avmain)+1;
1886 /* find the biggest */
1888 for (j=0; j < outchan; ++j) {
1889 temp = av_fetch(avmain, j, 0);
1890 if (temp && SvROK(*temp) && SvTYPE(SvRV(*temp)) == SVt_PVAV) {
1891 avsub = (AV*)SvRV(*temp);
1892 len = av_len(avsub)+1;
1897 coeff = mymalloc(sizeof(float) * outchan * inchan);
1898 for (j = 0; j < outchan; ++j) {
1899 avsub = (AV*)SvRV(*av_fetch(avmain, j, 0));
1900 len = av_len(avsub)+1;
1901 for (i = 0; i < len; ++i) {
1902 temp = av_fetch(avsub, i, 0);
1904 coeff[i+j*inchan] = SvNV(*temp);
1906 coeff[i+j*inchan] = 0;
1909 coeff[i++ + j*inchan] = 0;
1911 RETVAL = i_convert(src, coeff, outchan, inchan);
1921 unsigned int mask = 0;
1927 unsigned char (*maps)[256];
1929 if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV)
1930 croak("i_map: parameter 2 must be an arrayref\n");
1931 avmain = (AV*)SvRV(ST(1));
1932 len = av_len(avmain)+1;
1933 if (im->channels < len) len = im->channels;
1935 maps = mymalloc( len * sizeof(unsigned char [256]) );
1937 for (j=0; j<len ; j++) {
1938 temp = av_fetch(avmain, j, 0);
1939 if (temp && SvROK(*temp) && (SvTYPE(SvRV(*temp)) == SVt_PVAV) ) {
1940 avsub = (AV*)SvRV(*temp);
1941 if(av_len(avsub) != 255) continue;
1943 for (i=0; i<256 ; i++) {
1945 temp = av_fetch(avsub, i, 0);
1946 val = temp ? SvIV(*temp) : 0;
1948 if (val>255) val = 255;
1953 i_map(im, maps, mask);
1964 i_img_diffd(im1,im2)
1969 i_init_fonts(t1log=0)
1973 _is_color_object(sv)
1977 RETVAL = SvOK(sv) && SvROK(sv) &&
1978 (sv_derived_from(sv, "Imager::Color")
1979 || sv_derived_from(sv, "Imager::Color::Float"));
1995 i_t1_destroy(font_id)
2000 i_t1_cp(im,xb,yb,channel,fontnum,points,str_sv,len_ignored,align,utf8=0,flags="")
2019 str = SvPV(str_sv, len);
2020 RETVAL = i_t1_cp(im, xb,yb,channel,fontnum,points,str,len,align,
2027 i_t1_bbox(fontnum,point,str_sv,len_ignored,utf8=0,flags="")
2036 int cords[BOUNDING_BOX_COUNT];
2044 str = SvPV(str_sv, len);
2045 rc = i_t1_bbox(fontnum,point,str,len,cords,utf8,flags);
2048 for (i = 0; i < rc; ++i)
2049 PUSHs(sv_2mortal(newSViv(cords[i])));
2055 i_t1_text(im,xb,yb,cl,fontnum,points,str_sv,len_ignored,align,utf8=0,flags="")
2074 str = SvPV(str_sv, len);
2075 RETVAL = i_t1_text(im, xb,yb,cl,fontnum,points,str,len,align,
2081 i_t1_has_chars(handle, text_sv, utf8 = 0)
2093 if (SvUTF8(text_sv))
2096 text = SvPV(text_sv, len);
2097 work = mymalloc(len);
2098 count = i_t1_has_chars(handle, text, len, utf8, work);
2099 if (GIMME_V == G_ARRAY) {
2101 for (i = 0; i < count; ++i) {
2102 PUSHs(sv_2mortal(newSViv(work[i])));
2107 PUSHs(sv_2mortal(newSVpv(work, count)));
2112 i_t1_face_name(handle)
2118 len = i_t1_face_name(handle, name, sizeof(name));
2121 PUSHs(sv_2mortal(newSVpv(name, strlen(name))));
2125 i_t1_glyph_name(handle, text_sv, utf8 = 0)
2136 if (SvUTF8(text_sv))
2139 text = SvPV(text_sv, work_len);
2144 ch = i_utf8_advance(&text, &len);
2146 i_push_error(0, "invalid UTF8 character");
2155 if (i_t1_glyph_name(handle, ch, name, sizeof(name))) {
2156 PUSHs(sv_2mortal(newSVpv(name, 0)));
2159 PUSHs(&PL_sv_undef);
2173 MODULE = Imager PACKAGE = Imager::Font::TT PREFIX=TT_
2175 #define TT_DESTROY(handle) i_tt_destroy(handle)
2179 Imager::Font::TT handle
2189 MODULE = Imager PACKAGE = Imager
2193 i_tt_text(handle,im,xb,yb,cl,points,str_sv,len_ignored,smooth,utf8,align=1)
2194 Imager::Font::TT handle
2212 str = SvPV(str_sv, len);
2213 RETVAL = i_tt_text(handle, im, xb, yb, cl, points, str,
2214 len, smooth, utf8, align);
2220 i_tt_cp(handle,im,xb,yb,channel,points,str_sv,len_ignored,smooth,utf8,align=1)
2221 Imager::Font::TT handle
2239 str = SvPV(str_sv, len);
2240 RETVAL = i_tt_cp(handle, im, xb, yb, channel, points, str, len,
2241 smooth, utf8, align);
2247 i_tt_bbox(handle,point,str_sv,len_ignored, utf8)
2248 Imager::Font::TT handle
2253 int cords[BOUNDING_BOX_COUNT],rc;
2262 str = SvPV(str_sv, len);
2263 if ((rc=i_tt_bbox(handle,point,str,len,cords, utf8))) {
2265 for (i = 0; i < rc; ++i) {
2266 PUSHs(sv_2mortal(newSViv(cords[i])));
2271 i_tt_has_chars(handle, text_sv, utf8)
2272 Imager::Font::TT handle
2283 if (SvUTF8(text_sv))
2286 text = SvPV(text_sv, len);
2287 work = mymalloc(len);
2288 count = i_tt_has_chars(handle, text, len, utf8, work);
2289 if (GIMME_V == G_ARRAY) {
2291 for (i = 0; i < count; ++i) {
2292 PUSHs(sv_2mortal(newSViv(work[i])));
2297 PUSHs(sv_2mortal(newSVpv(work, count)));
2302 i_tt_dump_names(handle)
2303 Imager::Font::TT handle
2306 i_tt_face_name(handle)
2307 Imager::Font::TT handle
2312 len = i_tt_face_name(handle, name, sizeof(name));
2315 PUSHs(sv_2mortal(newSVpv(name, strlen(name))));
2319 i_tt_glyph_name(handle, text_sv, utf8 = 0)
2320 Imager::Font::TT handle
2331 if (SvUTF8(text_sv))
2334 text = SvPV(text_sv, work_len);
2339 ch = i_utf8_advance(&text, &len);
2341 i_push_error(0, "invalid UTF8 character");
2350 if ((outsize = i_tt_glyph_name(handle, ch, name, sizeof(name))) != 0) {
2351 PUSHs(sv_2mortal(newSVpv(name, 0)));
2354 PUSHs(&PL_sv_undef);
2361 i_test_format_probe(ig, length)
2366 i_readpnm_wiol(ig, allow_incomplete)
2368 int allow_incomplete
2372 i_readpnm_multi_wiol(ig, allow_incomplete)
2374 int allow_incomplete
2380 imgs = i_readpnm_multi_wiol(ig, &count, allow_incomplete);
2383 for (i = 0; i < count; ++i) {
2384 SV *sv = sv_newmortal();
2385 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2392 i_writeppm_wiol(im, ig)
2401 i_readraw_wiol(ig,x,y,datachannels,storechannels,intrl)
2410 i_writeraw_wiol(im,ig)
2415 i_writebmp_wiol(im,ig)
2420 i_readbmp_wiol(ig, allow_incomplete=0)
2422 int allow_incomplete
2426 i_writetga_wiol(im,ig, wierdpack, compress, idstring)
2435 idlen = SvCUR(ST(4));
2436 RETVAL = i_writetga_wiol(im, ig, wierdpack, compress, idstring, idlen);
2442 i_readtga_wiol(ig, length)
2450 i_scaleaxis(im,Value,Axis)
2456 i_scale_nn(im,scx,scy)
2462 i_scale_mixing(im, width, height)
2472 i_count_colors(im,maxc)
2477 i_get_anonymous_color_histo(im, maxc = 0x40000000)
2482 unsigned int * col_usage = NULL;
2485 col_cnt = i_get_anonymous_color_histo(im, &col_usage, maxc);
2486 EXTEND(SP, col_cnt);
2487 for (i = 0; i < col_cnt; i++) {
2488 PUSHs(sv_2mortal(newSViv( col_usage[i])));
2495 i_transform(im,opx,opy,parm)
2508 if (!SvROK(ST(1))) croak("Imager: Parameter 1 must be a reference to an array\n");
2509 if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to an array\n");
2510 if (!SvROK(ST(3))) croak("Imager: Parameter 3 must be a reference to an array\n");
2511 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 must be a reference to an array\n");
2512 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 2 must be a reference to an array\n");
2513 if (SvTYPE(SvRV(ST(3))) != SVt_PVAV) croak("Imager: Parameter 3 must be a reference to an array\n");
2514 av=(AV*)SvRV(ST(1));
2516 opx=mymalloc( opxl*sizeof(int) );
2517 for(i=0;i<opxl;i++) {
2518 sv1=(*(av_fetch(av,i,0)));
2519 opx[i]=(int)SvIV(sv1);
2521 av=(AV*)SvRV(ST(2));
2523 opy=mymalloc( opyl*sizeof(int) );
2524 for(i=0;i<opyl;i++) {
2525 sv1=(*(av_fetch(av,i,0)));
2526 opy[i]=(int)SvIV(sv1);
2528 av=(AV*)SvRV(ST(3));
2529 parmlen=av_len(av)+1;
2530 parm=mymalloc( parmlen*sizeof(double) );
2531 for(i=0;i<parmlen;i++) { /* FIXME: Bug? */
2532 sv1=(*(av_fetch(av,i,0)));
2533 parm[i]=(double)SvNV(sv1);
2535 RETVAL=i_transform(im,opx,opxl,opy,opyl,parm,parmlen);
2539 ST(0) = sv_newmortal();
2540 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2541 else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
2544 i_transform2(sv_width,sv_height,channels,sv_ops,av_n_regs,av_c_regs,av_in_imgs)
2569 in_imgs_count = av_len(av_in_imgs)+1;
2570 for (i = 0; i < in_imgs_count; ++i) {
2571 sv1 = *av_fetch(av_in_imgs, i, 0);
2572 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
2573 croak("sv_in_img must contain only images");
2576 if (in_imgs_count > 0) {
2577 in_imgs = mymalloc(in_imgs_count*sizeof(i_img*));
2578 for (i = 0; i < in_imgs_count; ++i) {
2579 sv1 = *av_fetch(av_in_imgs,i,0);
2580 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
2581 croak("Parameter 5 must contain only images");
2583 tmp = SvIV((SV*)SvRV(sv1));
2584 in_imgs[i] = INT2PTR(i_img*, tmp);
2588 /* no input images */
2591 /* default the output size from the first input if possible */
2593 width = SvIV(sv_width);
2594 else if (in_imgs_count)
2595 width = in_imgs[0]->xsize;
2597 croak("No output image width supplied");
2599 if (SvOK(sv_height))
2600 height = SvIV(sv_height);
2601 else if (in_imgs_count)
2602 height = in_imgs[0]->ysize;
2604 croak("No output image height supplied");
2606 ops = (struct rm_op *)SvPV(sv_ops, ops_len);
2607 if (ops_len % sizeof(struct rm_op))
2608 croak("Imager: Parameter 3 must be a bitmap of regops\n");
2609 ops_count = ops_len / sizeof(struct rm_op);
2611 n_regs_count = av_len(av_n_regs)+1;
2612 n_regs = mymalloc(n_regs_count * sizeof(double));
2613 for (i = 0; i < n_regs_count; ++i) {
2614 sv1 = *av_fetch(av_n_regs,i,0);
2616 n_regs[i] = SvNV(sv1);
2618 c_regs_count = av_len(av_c_regs)+1;
2619 c_regs = mymalloc(c_regs_count * sizeof(i_color));
2620 /* I don't bother initializing the colou?r registers */
2622 RETVAL=i_transform2(width, height, channels, ops, ops_count,
2623 n_regs, n_regs_count,
2624 c_regs, c_regs_count, in_imgs, in_imgs_count);
2629 ST(0) = sv_newmortal();
2630 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2631 else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
2635 i_contrast(im,intensity)
2648 i_noise(im,amount,type)
2654 i_bumpmap(im,bump,channel,light_x,light_y,strength)
2664 i_bumpmap_complex(im,bump,channel,tx,ty,Lx,Ly,Lz,cd,cs,n,Ia,Il,Is)
2683 i_postlevels(im,levels)
2693 i_watermark(im,wmark,tx,ty,pixdiff)
2695 Imager::ImgRaw wmark
2702 i_autolevels(im,lsat,usat,skew)
2709 i_radnoise(im,xo,yo,rscale,ascale)
2717 i_turbnoise(im, xo, yo, scale)
2740 croak("Usage: i_gradgen(im, xo, yo, ival, dmeasure)");
2741 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2742 croak("i_gradgen: Second argument must be an array ref");
2743 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
2744 croak("i_gradgen: Third argument must be an array ref");
2745 if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
2746 croak("i_gradgen: Fourth argument must be an array ref");
2747 axx = (AV *)SvRV(ST(1));
2748 ayy = (AV *)SvRV(ST(2));
2749 ac = (AV *)SvRV(ST(3));
2750 dmeasure = (int)SvIV(ST(4));
2752 num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
2753 num = num <= av_len(ac) ? num : av_len(ac);
2755 if (num < 2) croak("Usage: i_gradgen array refs must have more than 1 entry each");
2756 xo = mymalloc( sizeof(int) * num );
2757 yo = mymalloc( sizeof(int) * num );
2758 ival = mymalloc( sizeof(i_color) * num );
2759 for(i = 0; i<num; i++) {
2760 xo[i] = (int)SvIV(* av_fetch(axx, i, 0));
2761 yo[i] = (int)SvIV(* av_fetch(ayy, i, 0));
2762 sv = *av_fetch(ac, i, 0);
2763 if ( !sv_derived_from(sv, "Imager::Color") ) {
2764 free(axx); free(ayy); free(ac);
2765 croak("i_gradgen: Element of fourth argument is not derived from Imager::Color");
2767 ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
2769 i_gradgen(im, num, xo, yo, ival, dmeasure);
2775 i_diff_image(im, im2, mindist=0)
2781 i_fountain(im, xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
2791 double ssample_param
2795 i_fountain_seg *segs;
2797 if (!SvROK(ST(10)) || ! SvTYPE(SvRV(ST(10))))
2798 croak("i_fountain: argument 11 must be an array ref");
2800 asegs = (AV *)SvRV(ST(10));
2801 segs = load_fount_segs(aTHX_ asegs, &count);
2802 RETVAL = i_fountain(im, xa, ya, xb, yb, type, repeat, combine,
2803 super_sample, ssample_param, count, segs);
2809 i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
2818 double ssample_param
2822 i_fountain_seg *segs;
2824 if (!SvROK(ST(9)) || ! SvTYPE(SvRV(ST(9))))
2825 croak("i_fountain: argument 11 must be an array ref");
2827 asegs = (AV *)SvRV(ST(9));
2828 segs = load_fount_segs(aTHX_ asegs, &count);
2829 RETVAL = i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine,
2830 super_sample, ssample_param, count, segs);
2836 i_new_fill_opacity(other_fill, alpha_mult)
2837 Imager::FillHandle other_fill
2848 errors = i_errors();
2850 while (errors[i].msg) {
2852 sv = newSVpv(errors[i].msg, strlen(errors[i].msg));
2853 if (!av_store(av, 0, sv)) {
2856 sv = newSViv(errors[i].code);
2857 if (!av_store(av, 1, sv)) {
2860 PUSHs(sv_2mortal(newRV_noinc((SV*)av)));
2868 i_push_error(code, msg)
2873 i_nearest_color(im, ...)
2888 croak("Usage: i_nearest_color(im, xo, yo, ival, dmeasure)");
2889 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2890 croak("i_nearest_color: Second argument must be an array ref");
2891 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
2892 croak("i_nearest_color: Third argument must be an array ref");
2893 if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
2894 croak("i_nearest_color: Fourth argument must be an array ref");
2895 axx = (AV *)SvRV(ST(1));
2896 ayy = (AV *)SvRV(ST(2));
2897 ac = (AV *)SvRV(ST(3));
2898 dmeasure = (int)SvIV(ST(4));
2900 num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
2901 num = num <= av_len(ac) ? num : av_len(ac);
2903 if (num < 2) croak("Usage: i_nearest_color array refs must have more than 1 entry each");
2904 xo = mymalloc( sizeof(int) * num );
2905 yo = mymalloc( sizeof(int) * num );
2906 ival = mymalloc( sizeof(i_color) * num );
2907 for(i = 0; i<num; i++) {
2908 xo[i] = (int)SvIV(* av_fetch(axx, i, 0));
2909 yo[i] = (int)SvIV(* av_fetch(ayy, i, 0));
2910 sv = *av_fetch(ac, i, 0);
2911 if ( !sv_derived_from(sv, "Imager::Color") ) {
2912 free(axx); free(ayy); free(ac);
2913 croak("i_nearest_color: Element of fourth argument is not derived from Imager::Color");
2915 ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
2917 RETVAL = i_nearest_color(im, num, xo, yo, ival, dmeasure);
2931 rc=DSO_open(filename,&evstr);
2935 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
2936 PUSHs(sv_2mortal(newSVpvn(evstr, strlen(evstr))));
2939 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
2945 DSO_close(dso_handle)
2949 DSO_funclist(dso_handle_v)
2953 DSO_handle *dso_handle;
2954 func_ptr *functions;
2956 dso_handle=(DSO_handle*)dso_handle_v;
2957 functions = DSO_funclist(dso_handle);
2959 while( functions[i].name != NULL) {
2961 PUSHs(sv_2mortal(newSVpv(functions[i].name,0)));
2963 PUSHs(sv_2mortal(newSVpv(functions[i++].pcode,0)));
2967 DSO_call(handle,func_index,hv)
2973 if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to a hash\n");
2974 hv=(HV*)SvRV(ST(2));
2975 if (SvTYPE(hv)!=SVt_PVHV) croak("Imager: Parameter 2 must be a reference to a hash\n");
2976 DSO_call( (DSO_handle *)handle,func_index,hv);
2979 i_get_pixel(im, x, y)
2986 color = (i_color *)mymalloc(sizeof(i_color));
2987 if (i_gpix(im, x, y, color) == 0) {
2988 RETVAL = NEWSV(0, 0);
2989 sv_setref_pv(RETVAL, "Imager::Color", (void *)color);
2993 RETVAL = &PL_sv_undef;
3000 i_ppix(im, x, y, cl)
3007 i_img_pal_new(x, y, channels, maxpal)
3014 i_img_to_pal(src, quant)
3020 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
3021 croak("i_img_to_pal: second argument must be a hash ref");
3022 hv = (HV *)SvRV(ST(1));
3023 memset(&quant, 0, sizeof(quant));
3025 quant.mc_size = 256;
3026 ip_handle_quant_opts(aTHX_ &quant, hv);
3027 RETVAL = i_img_to_pal(src, &quant);
3029 ip_copy_colors_back(aTHX_ hv, &quant);
3031 ip_cleanup_quant_opts(aTHX_ &quant);
3050 work = mymalloc((r-l) * sizeof(i_palidx));
3051 count = i_gpal(im, l, r, y, work);
3052 if (GIMME_V == G_ARRAY) {
3054 for (i = 0; i < count; ++i) {
3055 PUSHs(sv_2mortal(newSViv(work[i])));
3060 PUSHs(sv_2mortal(newSVpv((char *)work, count * sizeof(i_palidx))));
3065 if (GIMME_V != G_ARRAY) {
3067 PUSHs(&PL_sv_undef);
3072 i_ppal(im, l, y, ...)
3081 work = mymalloc(sizeof(i_palidx) * (items-3));
3082 for (i=0; i < items-3; ++i) {
3083 work[i] = SvIV(ST(i+3));
3085 validate_i_ppal(im, work, items - 3);
3086 RETVAL = i_ppal(im, l, l+items-3, y, work);
3096 i_ppal_p(im, l, y, data)
3102 i_palidx const *work;
3105 work = (i_palidx const *)SvPV(data, len);
3106 len /= sizeof(i_palidx);
3108 validate_i_ppal(im, work, len);
3109 RETVAL = i_ppal(im, l, l+len, y, work);
3118 i_addcolors(im, ...)
3126 croak("i_addcolors: no colors to add");
3127 colors = mymalloc((items-1) * sizeof(i_color));
3128 for (i=0; i < items-1; ++i) {
3129 if (sv_isobject(ST(i+1))
3130 && sv_derived_from(ST(i+1), "Imager::Color")) {
3131 IV tmp = SvIV((SV *)SvRV(ST(i+1)));
3132 colors[i] = *INT2PTR(i_color *, tmp);
3136 croak("i_addcolor: pixels must be Imager::Color objects");
3139 index = i_addcolors(im, colors, items-1);
3142 RETVAL = newSVpv("0 but true", 0);
3144 else if (index == -1) {
3145 RETVAL = &PL_sv_undef;
3148 RETVAL = newSViv(index);
3154 i_setcolors(im, index, ...)
3162 croak("i_setcolors: no colors to add");
3163 colors = mymalloc((items-2) * sizeof(i_color));
3164 for (i=0; i < items-2; ++i) {
3165 if (sv_isobject(ST(i+2))
3166 && sv_derived_from(ST(i+2), "Imager::Color")) {
3167 IV tmp = SvIV((SV *)SvRV(ST(i+2)));
3168 colors[i] = *INT2PTR(i_color *, tmp);
3172 croak("i_setcolors: pixels must be Imager::Color objects");
3175 RETVAL = i_setcolors(im, index, colors, items-2);
3181 i_getcolors(im, index, ...)
3190 croak("i_getcolors: too many arguments");
3192 count = SvIV(ST(2));
3194 croak("i_getcolors: count must be positive");
3195 colors = mymalloc(sizeof(i_color) * count);
3196 if (i_getcolors(im, index, colors, count)) {
3197 for (i = 0; i < count; ++i) {
3199 SV *sv = sv_newmortal();
3200 pv = mymalloc(sizeof(i_color));
3202 sv_setref_pv(sv, "Imager::Color", (void *)pv);
3218 i_findcolor(im, color)
3224 if (i_findcolor(im, color, &index)) {
3225 RETVAL = newSViv(index);
3228 RETVAL = &PL_sv_undef;
3246 i_gsamp(im, l, r, y, ...)
3258 croak("No channel numbers supplied to g_samp()");
3260 chan_count = items - 4;
3261 chans = mymalloc(sizeof(int) * chan_count);
3262 for (i = 0; i < chan_count; ++i)
3263 chans[i] = SvIV(ST(i+4));
3264 data = mymalloc(sizeof(i_sample_t) * (r-l) * chan_count); /* XXX: memleak? */
3265 count = i_gsamp(im, l, r, y, data, chans, chan_count);
3267 if (GIMME_V == G_ARRAY) {
3269 for (i = 0; i < count; ++i)
3270 PUSHs(sv_2mortal(newSViv(data[i])));
3274 PUSHs(sv_2mortal(newSVpv((char *)data, count * sizeof(i_sample_t))));
3279 if (GIMME_V != G_ARRAY) {
3281 PUSHs(&PL_sv_undef);
3286 i_gsamp_bits(im, l, r, y, bits, target, offset, ...)
3302 croak("No channel numbers supplied to g_samp()");
3304 chan_count = items - 7;
3305 chans = mymalloc(sizeof(int) * chan_count);
3306 for (i = 0; i < chan_count; ++i)
3307 chans[i] = SvIV(ST(i+7));
3308 data = mymalloc(sizeof(unsigned) * (r-l) * chan_count);
3309 count = i_gsamp_bits(im, l, r, y, data, chans, chan_count, bits);
3311 for (i = 0; i < count; ++i) {
3312 av_store(target, i+offset, newSVuv(data[i]));
3324 i_psamp_bits(im, l, y, bits, channels_sv, data_av, data_offset = 0, pixel_count = -1)
3342 if (SvOK(channels_sv)) {
3344 if (!SvROK(channels_sv) || SvTYPE(SvRV(channels_sv)) != SVt_PVAV) {
3345 croak("channels is not an array ref");
3347 channels_av = (AV *)SvRV(channels_sv);
3348 chan_count = av_len(channels_av) + 1;
3349 if (chan_count < 1) {
3350 croak("i_psamp_bits: no channels provided");
3352 channels = mymalloc(sizeof(int) * chan_count);
3353 for (i = 0; i < chan_count; ++i)
3354 channels[i] = SvIV(*av_fetch(channels_av, i, 0));
3357 chan_count = im->channels;
3361 data_count = av_len(data_av) + 1;
3362 if (data_offset < 0) {
3363 croak("data_offset must by non-negative");
3365 if (data_offset > data_count) {
3366 croak("data_offset greater than number of samples supplied");
3368 if (pixel_count == -1 ||
3369 data_offset + pixel_count * chan_count > data_count) {
3370 pixel_count = (data_count - data_offset) / chan_count;
3373 data_used = pixel_count * chan_count;
3374 data = mymalloc(sizeof(unsigned) * data_count);
3375 for (i = 0; i < data_used; ++i)
3376 data[i] = SvUV(*av_fetch(data_av, data_offset + i, 0));
3378 RETVAL = i_psamp_bits(im, l, l + pixel_count, y, data, channels,
3389 i_img_masked_new(targ, mask, x, y, w, h)
3399 if (!sv_isobject(ST(1))
3400 || !sv_derived_from(ST(1), "Imager::ImgRaw")) {
3401 croak("i_img_masked_new: parameter 2 must undef or an image");
3403 mask = INT2PTR(i_img *, SvIV((SV *)SvRV(ST(1))));
3407 RETVAL = i_img_masked_new(targ, mask, x, y, w, h);
3412 i_plin(im, l, y, ...)
3423 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3424 /* supplied as a byte string */
3425 work = (i_color *)SvPV(ST(3), len);
3426 count = len / sizeof(i_color);
3427 if (count * sizeof(i_color) != len) {
3428 croak("i_plin: length of scalar argument must be multiple of sizeof i_color");
3430 RETVAL = i_plin(im, l, l+count, y, work);
3433 work = mymalloc(sizeof(i_color) * (items-3));
3434 for (i=0; i < items-3; ++i) {
3435 if (sv_isobject(ST(i+3))
3436 && sv_derived_from(ST(i+3), "Imager::Color")) {
3437 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3438 work[i] = *INT2PTR(i_color *, tmp);
3442 croak("i_plin: pixels must be Imager::Color objects");
3445 RETVAL = i_plin(im, l, l+items-3, y, work);
3456 i_ppixf(im, x, y, cl)
3460 Imager::Color::Float cl
3463 i_gsampf(im, l, r, y, ...)
3475 croak("No channel numbers supplied to g_sampf()");
3477 chan_count = items - 4;
3478 chans = mymalloc(sizeof(int) * chan_count);
3479 for (i = 0; i < chan_count; ++i)
3480 chans[i] = SvIV(ST(i+4));
3481 data = mymalloc(sizeof(i_fsample_t) * (r-l) * chan_count);
3482 count = i_gsampf(im, l, r, y, data, chans, chan_count);
3484 if (GIMME_V == G_ARRAY) {
3486 for (i = 0; i < count; ++i)
3487 PUSHs(sv_2mortal(newSVnv(data[i])));
3491 PUSHs(sv_2mortal(newSVpv((void *)data, count * sizeof(i_fsample_t))));
3496 if (GIMME_V != G_ARRAY) {
3498 PUSHs(&PL_sv_undef);
3503 i_plinf(im, l, y, ...)
3514 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3515 /* supplied as a byte string */
3516 work = (i_fcolor *)SvPV(ST(3), len);
3517 count = len / sizeof(i_fcolor);
3518 if (count * sizeof(i_fcolor) != len) {
3519 croak("i_plin: length of scalar argument must be multiple of sizeof i_fcolor");
3521 RETVAL = i_plinf(im, l, l+count, y, work);
3524 work = mymalloc(sizeof(i_fcolor) * (items-3));
3525 for (i=0; i < items-3; ++i) {
3526 if (sv_isobject(ST(i+3))
3527 && sv_derived_from(ST(i+3), "Imager::Color::Float")) {
3528 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3529 work[i] = *INT2PTR(i_fcolor *, tmp);
3533 croak("i_plinf: pixels must be Imager::Color::Float objects");
3537 RETVAL = i_plinf(im, l, l+items-3, y, work);
3555 color = (i_fcolor *)mymalloc(sizeof(i_fcolor));
3556 if (i_gpixf(im, x, y, color) == 0) {
3557 RETVAL = NEWSV(0,0);
3558 sv_setref_pv(RETVAL, "Imager::Color::Float", (void *)color);
3562 RETVAL = &PL_sv_undef;
3578 vals = mymalloc((r-l) * sizeof(i_color));
3579 memset(vals, 0, (r-l) * sizeof(i_color));
3580 count = i_glin(im, l, r, y, vals);
3581 if (GIMME_V == G_ARRAY) {
3583 for (i = 0; i < count; ++i) {
3585 i_color *col = mymalloc(sizeof(i_color));
3587 sv = sv_newmortal();
3588 sv_setref_pv(sv, "Imager::Color", (void *)col);
3594 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_color))));
3600 i_glinf(im, l, r, y)
3610 for (i = 0; i < MAXCHANNELS; ++i)
3611 zero.channel[i] = 0;
3613 vals = mymalloc((r-l) * sizeof(i_fcolor));
3614 for (i = 0; i < r-l; ++i)
3616 count = i_glinf(im, l, r, y, vals);
3617 if (GIMME_V == G_ARRAY) {
3619 for (i = 0; i < count; ++i) {
3621 i_fcolor *col = mymalloc(sizeof(i_fcolor));
3623 sv = sv_newmortal();
3624 sv_setref_pv(sv, "Imager::Color::Float", (void *)col);
3630 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_fcolor))));
3636 i_img_16_new(x, y, ch)
3646 i_img_double_new(x, y, ch)
3652 i_tags_addn(im, name, code, idata)
3661 name = SvPV(ST(1), len);
3664 RETVAL = i_tags_addn(&im->tags, name, code, idata);
3669 i_tags_add(im, name, code, data, idata)
3679 name = SvPV(ST(1), len);
3683 data = SvPV(ST(3), len);
3688 RETVAL = i_tags_add(&im->tags, name, code, data, len, idata);
3693 i_tags_find(im, name, start)
3700 if (i_tags_find(&im->tags, name, start, &entry)) {
3702 RETVAL = newSVpv("0 but true", 0);
3704 RETVAL = newSViv(entry);
3706 RETVAL = &PL_sv_undef;
3712 i_tags_findn(im, code, start)
3719 if (i_tags_findn(&im->tags, code, start, &entry)) {
3721 RETVAL = newSVpv("0 but true", 0);
3723 RETVAL = newSViv(entry);
3726 RETVAL = &PL_sv_undef;
3732 i_tags_delete(im, entry)
3736 RETVAL = i_tags_delete(&im->tags, entry);
3741 i_tags_delbyname(im, name)
3745 RETVAL = i_tags_delbyname(&im->tags, name);
3750 i_tags_delbycode(im, code)
3754 RETVAL = i_tags_delbycode(&im->tags, code);
3759 i_tags_get(im, index)
3763 if (index >= 0 && index < im->tags.count) {
3764 i_img_tag *entry = im->tags.tags + index;
3768 PUSHs(sv_2mortal(newSVpv(entry->name, 0)));
3771 PUSHs(sv_2mortal(newSViv(entry->code)));
3774 PUSHs(sv_2mortal(newSVpvn(entry->data, entry->size)));
3777 PUSHs(sv_2mortal(newSViv(entry->idata)));
3782 i_tags_get_string(im, what_sv)
3786 char const *name = NULL;
3790 if (SvIOK(what_sv)) {
3791 code = SvIV(what_sv);
3795 name = SvPV_nolen(what_sv);
3798 if (i_tags_get_string(&im->tags, name, code, buffer, sizeof(buffer))) {
3800 PUSHs(sv_2mortal(newSVpv(buffer, 0)));
3807 RETVAL = im->tags.count;
3814 i_wf_bbox(face, size, text_sv, utf8=0)
3820 int cords[BOUNDING_BOX_COUNT];
3825 text = SvPV(text_sv, text_len);
3827 if (SvUTF8(text_sv))
3830 if (rc = i_wf_bbox(face, size, text, text_len, cords, utf8)) {
3832 for (i = 0; i < rc; ++i)
3833 PUSHs(sv_2mortal(newSViv(cords[i])));
3837 i_wf_text(face, im, tx, ty, cl, size, text_sv, align, aa, utf8 = 0)
3852 text = SvPV(text_sv, text_len);
3854 if (SvUTF8(text_sv))
3857 RETVAL = i_wf_text(face, im, tx, ty, cl, size, text, text_len,
3863 i_wf_cp(face, im, tx, ty, channel, size, text_sv, align, aa, utf8 = 0)
3878 text = SvPV(text_sv, text_len);
3880 if (SvUTF8(text_sv))
3883 RETVAL = i_wf_cp(face, im, tx, ty, channel, size, text, text_len,
3900 MODULE = Imager PACKAGE = Imager::Font::FT2 PREFIX=FT2_
3902 #define FT2_DESTROY(font) i_ft2_destroy(font)
3906 Imager::Font::FT2 font
3915 MODULE = Imager PACKAGE = Imager::Font::FreeType2
3918 i_ft2_new(name, index)
3923 i_ft2_setdpi(font, xdpi, ydpi)
3924 Imager::Font::FT2 font
3930 Imager::Font::FT2 font
3934 if (i_ft2_getdpi(font, &xdpi, &ydpi)) {
3936 PUSHs(sv_2mortal(newSViv(xdpi)));
3937 PUSHs(sv_2mortal(newSViv(ydpi)));
3941 i_ft2_sethinting(font, hinting)
3942 Imager::Font::FT2 font
3946 i_ft2_settransform(font, matrix)
3947 Imager::Font::FT2 font
3955 if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV)
3956 croak("i_ft2_settransform: parameter 2 must be an array ref\n");
3957 av=(AV*)SvRV(ST(1));
3961 for (i = 0; i < len; ++i) {
3962 sv1=(*(av_fetch(av,i,0)));
3963 matrix[i] = SvNV(sv1);
3967 RETVAL = i_ft2_settransform(font, matrix);
3972 i_ft2_bbox(font, cheight, cwidth, text_sv, utf8)
3973 Imager::Font::FT2 font
3979 int bbox[BOUNDING_BOX_COUNT];
3985 text = SvPV(text_sv, text_len);
3987 if (SvUTF8(text_sv))
3990 rc = i_ft2_bbox(font, cheight, cwidth, text, text_len, bbox, utf8);
3993 for (i = 0; i < rc; ++i)
3994 PUSHs(sv_2mortal(newSViv(bbox[i])));
3998 i_ft2_bbox_r(font, cheight, cwidth, text, vlayout, utf8)
3999 Imager::Font::FT2 font
4013 if (i_ft2_bbox_r(font, cheight, cwidth, text, strlen(text), vlayout,
4016 for (i = 0; i < 8; ++i)
4017 PUSHs(sv_2mortal(newSViv(bbox[i])));
4021 i_ft2_text(font, im, tx, ty, cl, cheight, cwidth, text, align, aa, vlayout, utf8)
4022 Imager::Font::FT2 font
4038 if (SvUTF8(ST(7))) {
4042 text = SvPV(ST(7), len);
4043 RETVAL = i_ft2_text(font, im, tx, ty, cl, cheight, cwidth, text,
4044 len, align, aa, vlayout, utf8);
4049 i_ft2_cp(font, im, tx, ty, channel, cheight, cwidth, text_sv, align, aa, vlayout, utf8)
4050 Imager::Font::FT2 font
4070 text = SvPV(text_sv, len);
4071 RETVAL = i_ft2_cp(font, im, tx, ty, channel, cheight, cwidth, text,
4072 len, align, aa, vlayout, 1);
4077 ft2_transform_box(font, x0, x1, x2, x3)
4078 Imager::Font::FT2 font
4086 box[0] = x0; box[1] = x1; box[2] = x2; box[3] = x3;
4087 ft2_transform_box(font, box);
4089 PUSHs(sv_2mortal(newSViv(box[0])));
4090 PUSHs(sv_2mortal(newSViv(box[1])));
4091 PUSHs(sv_2mortal(newSViv(box[2])));
4092 PUSHs(sv_2mortal(newSViv(box[3])));
4095 i_ft2_has_chars(handle, text_sv, utf8)
4096 Imager::Font::FT2 handle
4107 if (SvUTF8(text_sv))
4110 text = SvPV(text_sv, len);
4111 work = mymalloc(len);
4112 count = i_ft2_has_chars(handle, text, len, utf8, work);
4113 if (GIMME_V == G_ARRAY) {
4115 for (i = 0; i < count; ++i) {
4116 PUSHs(sv_2mortal(newSViv(work[i])));
4121 PUSHs(sv_2mortal(newSVpv(work, count)));
4126 i_ft2_face_name(handle)
4127 Imager::Font::FT2 handle
4132 len = i_ft2_face_name(handle, name, sizeof(name));
4135 PUSHs(sv_2mortal(newSVpv(name, 0)));
4139 i_ft2_can_face_name()
4142 i_ft2_glyph_name(handle, text_sv, utf8 = 0, reliable_only = 1)
4143 Imager::Font::FT2 handle
4154 if (SvUTF8(text_sv))
4157 text = SvPV(text_sv, work_len);
4162 ch = i_utf8_advance(&text, &len);
4164 i_push_error(0, "invalid UTF8 character");
4173 if (i_ft2_glyph_name(handle, ch, name, sizeof(name),
4175 PUSHs(sv_2mortal(newSVpv(name, 0)));
4178 PUSHs(&PL_sv_undef);
4183 i_ft2_can_do_glyph_names()
4186 i_ft2_face_has_glyph_names(handle)
4187 Imager::Font::FT2 handle
4190 i_ft2_is_multiple_master(handle)
4191 Imager::Font::FT2 handle
4194 i_ft2_get_multiple_masters(handle)
4195 Imager::Font::FT2 handle
4200 if (i_ft2_get_multiple_masters(handle, &mm)) {
4201 EXTEND(SP, 2+mm.num_axis);
4202 PUSHs(sv_2mortal(newSViv(mm.num_axis)));
4203 PUSHs(sv_2mortal(newSViv(mm.num_designs)));
4204 for (i = 0; i < mm.num_axis; ++i) {
4208 sv = newSVpv(mm.axis[i].name, strlen(mm.axis[i].name));
4210 av_store(av, 0, sv);
4211 sv = newSViv(mm.axis[i].minimum);
4213 av_store(av, 1, sv);
4214 sv = newSViv(mm.axis[i].maximum);
4216 av_store(av, 2, sv);
4217 PUSHs(newRV_noinc((SV *)av));
4222 i_ft2_set_mm_coords(handle, ...)
4223 Imager::Font::FT2 handle
4229 /* T_ARRAY handling by xsubpp seems to be busted in 5.6.1, so
4230 transfer the array manually */
4231 ix_coords = items-1;
4232 coords = mymalloc(sizeof(long) * ix_coords);
4233 for (i = 0; i < ix_coords; ++i) {
4234 coords[i] = (long)SvIV(ST(1+i));
4236 RETVAL = i_ft2_set_mm_coords(handle, ix_coords, coords);
4243 MODULE = Imager PACKAGE = Imager::FillHandle PREFIX=IFILL_
4247 Imager::FillHandle fill
4250 IFILL_CLONE_SKIP(...)
4256 MODULE = Imager PACKAGE = Imager
4259 i_new_fill_solid(cl, combine)
4264 i_new_fill_solidf(cl, combine)
4265 Imager::Color::Float cl
4269 i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy)
4277 unsigned char *cust_hatch;
4281 cust_hatch = (unsigned char *)SvPV(ST(4), len);
4285 RETVAL = i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy);
4290 i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy)
4291 Imager::Color::Float fg
4292 Imager::Color::Float bg
4298 unsigned char *cust_hatch;
4302 cust_hatch = (unsigned char *)SvPV(ST(4), len);
4306 RETVAL = i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy);
4311 i_new_fill_image(src, matrix, xoff, yoff, combine)
4328 if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV)
4329 croak("i_new_fill_image: parameter must be an arrayref");
4330 av=(AV*)SvRV(ST(1));
4334 for (i = 0; i < len; ++i) {
4335 sv1=(*(av_fetch(av,i,0)));
4336 matrix[i] = SvNV(sv1);
4342 RETVAL = i_new_fill_image(src, matrixp, xoff, yoff, combine);
4346 MODULE = Imager PACKAGE = Imager::Internal::Hlines PREFIX=i_int_hlines_
4348 # this class is only exposed for testing
4351 i_int_hlines_testing()
4353 #if i_int_hlines_testing()
4355 Imager::Internal::Hlines
4356 i_int_hlines_new(start_y, count_y, start_x, count_x)
4362 Imager::Internal::Hlines
4363 i_int_hlines_new_img(im)
4367 i_int_hlines_add(hlines, y, minx, width)
4368 Imager::Internal::Hlines hlines
4374 i_int_hlines_DESTROY(hlines)
4375 Imager::Internal::Hlines hlines
4378 i_int_hlines_dump(hlines)
4379 Imager::Internal::Hlines hlines
4382 i_int_hlines_CLONE_SKIP(cls)
4388 PERL_SET_GLOBAL_CALLBACKS;
4389 PERL_PL_SET_GLOBAL_CALLBACKS;