fix various GCC warnings, mostly initialized but otherwise unused variables
[imager.git] / Imager.xs
1 #define PERL_NO_GET_CONTEXT
2 #ifdef __cplusplus
3 extern "C" {
4 #endif
5 #include "EXTERN.h"
6 #include "perl.h"
7 #include "XSUB.h"
8 #define NEED_newRV_noinc
9 #define NEED_sv_2pv_nolen
10 #define NEED_sv_2pvbyte
11 #include "ppport.h"
12 #ifdef __cplusplus
13 }
14 #endif
15
16 #define i_int_hlines_testing() 1
17
18 #include "imager.h"
19 #include "feat.h"
20 #include "dynaload.h"
21 #include "regmach.h"
22 #include "imextdef.h"
23 #include "imextpltypes.h"
24 #include "imperlio.h"
25 #include <float.h>
26
27 #if i_int_hlines_testing()
28 #include "imageri.h"
29 #endif
30
31 #include "imperl.h"
32
33 /*
34
35 Context object management
36
37 */
38
39 typedef im_context_t Imager__Context;
40
41 #define im_context_DESTROY(ctx) im_context_refdec((ctx), "DESTROY")
42
43 #ifdef PERL_IMPLICIT_CONTEXT
44
45 #define MY_CXT_KEY "Imager::_context" XS_VERSION
46
47 typedef struct {
48   im_context_t ctx;
49 } my_cxt_t;
50
51 START_MY_CXT
52
53 im_context_t fallback_context;
54
55 static void
56 start_context(pTHX) {
57   dMY_CXT;
58   MY_CXT.ctx = im_context_new();
59   sv_setref_pv(get_sv("Imager::_context", GV_ADD), "Imager::Context", MY_CXT.ctx);
60
61   /* Ideally we'd free this reference, but the error message memory
62      was never released on exit, so the associated memory here is reasonable
63      to keep.
64      With logging enabled we always need at least one context, since
65      objects may be released fairly late and attempt to get the log file.
66   */
67   im_context_refinc(MY_CXT.ctx, "start_context");
68   fallback_context = MY_CXT.ctx;
69 }
70
71 static im_context_t
72 perl_get_context(void) {
73   dTHX;
74   dMY_CXT;
75   
76   return MY_CXT.ctx ? MY_CXT.ctx : fallback_context;
77 }
78
79 #else
80
81 static im_context_t perl_context;
82
83 static void
84 start_context(pTHX) {
85   perl_context = im_context_new();
86   im_context_refinc(perl_context, "start_context");
87 }
88
89 static im_context_t
90 perl_get_context(void) {
91   return perl_context;
92 }
93
94 #endif
95
96 /* used to represent channel lists parameters */
97 typedef struct i_channel_list_tag {
98   int *channels;
99   int count;
100 } i_channel_list;
101
102 typedef struct {
103   size_t count;
104   const i_sample_t *samples;
105 } i_sample_list;
106
107 typedef struct {
108   size_t count;
109   const i_fsample_t *samples;
110 } i_fsample_list;
111
112 /*
113
114 Allocate memory that will be discarded when mortals are discarded.
115
116 */
117
118 static void *
119 malloc_temp(pTHX_ size_t size) {
120   SV *sv = sv_2mortal(newSV(size));
121
122   return SvPVX(sv);
123 }
124
125 static void *
126 calloc_temp(pTHX_ size_t size) {
127   void *result = malloc_temp(aTHX_ size);
128   memset(result, 0, size);
129
130   return result;
131 }
132
133 /* for use with the T_AVARRAY typemap */
134 #define doublePtr(size) ((double *)calloc_temp(aTHX_ sizeof(double) * (size)))
135 #define SvDouble(sv, pname) (SvNV(sv))
136
137 #define intPtr(size) ((int *)calloc_temp(aTHX_ sizeof(int) * (size)))
138 #define SvInt(sv, pname) (SvIV(sv))
139
140 #define i_img_dimPtr(size) ((i_img_dim *)calloc_temp(aTHX_ sizeof(i_img_dim) * (size)))
141 #define SvI_img_dim(sv, pname) (SvIV(sv))
142
143 #define i_colorPtr(size) ((i_color *)calloc_temp(aTHX_ sizeof(i_color *) * (size)))
144
145 #define SvI_color(sv, pname) S_sv_to_i_color(aTHX_ sv, pname)
146
147 static i_color
148 S_sv_to_i_color(pTHX_ SV *sv, const char *pname) {
149   if (!sv_derived_from(sv, "Imager::Color")) {
150     croak("%s: not a color object");
151   }
152   return *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
153 }
154
155 /* These functions are all shared - then comes platform dependant code */
156 static int getstr(void *hv_t,char *key,char **store) {
157   dTHX;
158   SV** svpp;
159   HV* hv=(HV*)hv_t;
160
161   mm_log((1,"getstr(hv_t %p, key %s, store %p)\n",hv_t,key,store));
162
163   if ( !hv_exists(hv,key,strlen(key)) ) return 0;
164
165   svpp=hv_fetch(hv, key, strlen(key), 0);
166   *store=SvPV(*svpp, PL_na );
167
168   return 1;
169 }
170
171 static int getint(void *hv_t,char *key,int *store) {
172   dTHX;
173   SV** svpp;
174   HV* hv=(HV*)hv_t;  
175
176   mm_log((1,"getint(hv_t %p, key %s, store %p)\n",hv_t,key,store));
177
178   if ( !hv_exists(hv,key,strlen(key)) ) return 0;
179
180   svpp=hv_fetch(hv, key, strlen(key), 0);
181   *store=(int)SvIV(*svpp);
182   return 1;
183 }
184
185 static int getdouble(void *hv_t,char* key,double *store) {
186   dTHX;
187   SV** svpp;
188   HV* hv=(HV*)hv_t;
189
190   mm_log((1,"getdouble(hv_t %p, key %s, store %p)\n",hv_t,key,store));
191
192   if ( !hv_exists(hv,key,strlen(key)) ) return 0;
193   svpp=hv_fetch(hv, key, strlen(key), 0);
194   *store=(double)SvNV(*svpp);
195   return 1;
196 }
197
198 static int getvoid(void *hv_t,char* key,void **store) {
199   dTHX;
200   SV** svpp;
201   HV* hv=(HV*)hv_t;
202
203   mm_log((1,"getvoid(hv_t %p, key %s, store %p)\n",hv_t,key,store));
204
205   if ( !hv_exists(hv,key,strlen(key)) ) return 0;
206
207   svpp=hv_fetch(hv, key, strlen(key), 0);
208   *store = INT2PTR(void*, SvIV(*svpp));
209
210   return 1;
211 }
212
213 static int getobj(void *hv_t,char *key,char *type,void **store) {
214   dTHX;
215   SV** svpp;
216   HV* hv=(HV*)hv_t;
217
218   mm_log((1,"getobj(hv_t %p, key %s,type %s, store %p)\n",hv_t,key,type,store));
219
220   if ( !hv_exists(hv,key,strlen(key)) ) return 0;
221
222   svpp=hv_fetch(hv, key, strlen(key), 0);
223
224   if (sv_derived_from(*svpp,type)) {
225     IV tmp = SvIV((SV*)SvRV(*svpp));
226     *store = INT2PTR(void*, tmp);
227   } else {
228     mm_log((1,"getobj: key exists in hash but is not of correct type"));
229     return 0;
230   }
231
232   return 1;
233 }
234
235 UTIL_table_t i_UTIL_table={getstr,getint,getdouble,getvoid,getobj};
236
237 void my_SvREFCNT_dec(void *p) {
238   dTHX;
239   SvREFCNT_dec((SV*)p);
240 }
241
242
243 static void
244 i_log_entry(char *string, int level) {
245   mm_log((level, "%s", string));
246 }
247
248 static SV *
249 make_i_color_sv(pTHX_ const i_color *c) {
250   SV *sv;
251   i_color *col = mymalloc(sizeof(i_color));
252   *col = *c;
253   sv = sv_newmortal();
254   sv_setref_pv(sv, "Imager::Color", (void *)col);
255
256   return sv;
257 }
258
259 #define CBDATA_BUFSIZE 8192
260
261 struct cbdata {
262   /* the SVs we use to call back to Perl */
263   SV *writecb;
264   SV *readcb;
265   SV *seekcb;
266   SV *closecb;
267 };
268
269 static ssize_t
270 call_reader(struct cbdata *cbd, void *buf, size_t size, 
271             size_t maxread) {
272   dTHX;
273   int count;
274   int result;
275   SV *data;
276   dSP;
277
278   if (!SvOK(cbd->readcb)) {
279     mm_log((1, "read callback called but no readcb supplied\n"));
280     i_push_error(0, "read callback called but no readcb supplied");
281     return -1;
282   }
283
284   ENTER;
285   SAVETMPS;
286   EXTEND(SP, 2);
287   PUSHMARK(SP);
288   PUSHs(sv_2mortal(newSViv(size)));
289   PUSHs(sv_2mortal(newSViv(maxread)));
290   PUTBACK;
291
292   count = perl_call_sv(cbd->readcb, G_SCALAR);
293
294   SPAGAIN;
295
296   if (count != 1)
297     croak("Result of perl_call_sv(..., G_SCALAR) != 1");
298
299   data = POPs;
300
301   if (SvOK(data)) {
302     STRLEN len;
303     char *ptr = SvPVbyte(data, len);
304     if (len > maxread)
305       croak("Too much data returned in reader callback (wanted %d, got %d, expected %d)",
306       (int)size, (int)len, (int)maxread);
307     
308     memcpy(buf, ptr, len);
309     result = len;
310   }
311   else {
312     result = -1;
313   }
314
315   PUTBACK;
316   FREETMPS;
317   LEAVE;
318
319   return result;
320 }
321
322 static off_t
323 io_seeker(void *p, off_t offset, int whence) {
324   dTHX;
325   struct cbdata *cbd = p;
326   int count;
327   off_t result;
328   dSP;
329
330   if (!SvOK(cbd->seekcb)) {
331     mm_log((1, "seek callback called but no seekcb supplied\n"));
332     i_push_error(0, "seek callback called but no seekcb supplied");
333     return -1;
334   }
335
336   ENTER;
337   SAVETMPS;
338   EXTEND(SP, 2);
339   PUSHMARK(SP);
340   PUSHs(sv_2mortal(newSViv(offset)));
341   PUSHs(sv_2mortal(newSViv(whence)));
342   PUTBACK;
343
344   count = perl_call_sv(cbd->seekcb, G_SCALAR);
345
346   SPAGAIN;
347
348   if (count != 1)
349     croak("Result of perl_call_sv(..., G_SCALAR) != 1");
350
351   result = POPi;
352
353   PUTBACK;
354   FREETMPS;
355   LEAVE;
356
357   return result;
358 }
359
360 static ssize_t
361 io_writer(void *p, void const *data, size_t size) {
362   dTHX;
363   struct cbdata *cbd = p;
364   I32 count;
365   SV *sv;
366   dSP;
367   bool success;
368
369   if (!SvOK(cbd->writecb)) {
370     mm_log((1, "write callback called but no writecb supplied\n"));
371     i_push_error(0, "write callback called but no writecb supplied");
372     return -1;
373   }
374
375   ENTER;
376   SAVETMPS;
377   EXTEND(SP, 1);
378   PUSHMARK(SP);
379   PUSHs(sv_2mortal(newSVpv((char *)data, size)));
380   PUTBACK;
381
382   count = perl_call_sv(cbd->writecb, G_SCALAR);
383
384   SPAGAIN;
385   if (count != 1)
386     croak("Result of perl_call_sv(..., G_SCALAR) != 1");
387
388   sv = POPs;
389   success = SvTRUE(sv);
390
391
392   PUTBACK;
393   FREETMPS;
394   LEAVE;
395
396   return success ? size : -1;
397 }
398
399 static ssize_t 
400 io_reader(void *p, void *data, size_t size) {
401   struct cbdata *cbd = p;
402
403   return call_reader(cbd, data, size, size);
404 }
405
406 static int io_closer(void *p) {
407   dTHX;
408   struct cbdata *cbd = p;
409   int success = 1;
410
411   if (SvOK(cbd->closecb)) {
412     dSP;
413     I32 count;
414
415     ENTER;
416     SAVETMPS;
417     PUSHMARK(SP);
418     PUTBACK;
419
420     count = perl_call_sv(cbd->closecb, G_SCALAR);
421
422     SPAGAIN;
423     
424     if (count) {
425       SV *sv = POPs;
426       success = SvTRUE(sv);
427     }
428     else
429       success = 0;
430
431     PUTBACK;
432     FREETMPS;
433     LEAVE;
434   }
435
436   return success ? 0 : -1;
437 }
438
439 static void io_destroyer(void *p) {
440   dTHX;
441   struct cbdata *cbd = p;
442
443   SvREFCNT_dec(cbd->writecb);
444   SvREFCNT_dec(cbd->readcb);
445   SvREFCNT_dec(cbd->seekcb);
446   SvREFCNT_dec(cbd->closecb);
447   myfree(cbd);
448 }
449
450 static i_io_glue_t *
451 do_io_new_buffer(pTHX_ SV *data_sv) {
452   const char *data;
453   STRLEN length;
454
455   data = SvPVbyte(data_sv, length);
456   SvREFCNT_inc(data_sv);
457   return io_new_buffer(data, length, my_SvREFCNT_dec, data_sv);
458 }
459
460 static const char *
461 describe_sv(SV *sv) {
462   if (SvOK(sv)) {
463     if (SvROK(sv)) {
464       svtype type = SvTYPE(SvRV(sv));
465       switch (type) {
466       case SVt_PVCV: return "CV";
467       case SVt_PVGV: return "GV";
468       case SVt_PVLV: return "LV";
469       default: return "some reference";
470       }
471     }
472     else {
473       return "non-reference scalar";
474     }
475   }
476   else {
477     return "undef";
478   }
479 }
480
481 static i_io_glue_t *
482 do_io_new_cb(pTHX_ SV *writecb, SV *readcb, SV *seekcb, SV *closecb) {
483   struct cbdata *cbd;
484
485   cbd = mymalloc(sizeof(struct cbdata));
486   cbd->writecb = newSVsv(writecb);
487   cbd->readcb = newSVsv(readcb);
488   cbd->seekcb = newSVsv(seekcb);
489   cbd->closecb = newSVsv(closecb);
490
491   mm_log((1, "do_io_new_cb(writecb %p (%s), readcb %p (%s), seekcb %p (%s), closecb %p (%s))\n", writecb, describe_sv(writecb), readcb, describe_sv(readcb), seekcb, describe_sv(seekcb), closecb, describe_sv(closecb)));
492
493   return io_new_cb(cbd, io_reader, io_writer, io_seeker, io_closer, 
494                    io_destroyer);
495 }
496
497 struct value_name {
498   char *name;
499   int value;
500 };
501 static int lookup_name(struct value_name *names, int count, char *name, int def_value)
502 {
503   int i;
504   for (i = 0; i < count; ++i)
505     if (strEQ(names[i].name, name))
506       return names[i].value;
507
508   return def_value;
509 }
510 static struct value_name transp_names[] =
511 {
512   { "none", tr_none },
513   { "threshold", tr_threshold },
514   { "errdiff", tr_errdiff },
515   { "ordered", tr_ordered, },
516 };
517
518 static struct value_name make_color_names[] =
519 {
520   { "none", mc_none, },
521   { "webmap", mc_web_map, },
522   { "addi", mc_addi, },
523   { "mediancut", mc_median_cut, },
524   { "mono", mc_mono, },
525   { "monochrome", mc_mono, },
526   { "gray", mc_gray, },
527   { "gray4", mc_gray4, },
528   { "gray16", mc_gray16, },
529 };
530
531 static struct value_name translate_names[] =
532 {
533   { "giflib", pt_giflib, },
534   { "closest", pt_closest, },
535   { "perturb", pt_perturb, },
536   { "errdiff", pt_errdiff, },
537 };
538
539 static struct value_name errdiff_names[] =
540 {
541   { "floyd", ed_floyd, },
542   { "jarvis", ed_jarvis, },
543   { "stucki", ed_stucki, },
544   { "custom", ed_custom, },
545 };
546
547 static struct value_name orddith_names[] =
548 {
549   { "random", od_random, },
550   { "dot8", od_dot8, },
551   { "dot4", od_dot4, },
552   { "hline", od_hline, },
553   { "vline", od_vline, },
554   { "/line", od_slashline, },
555   { "slashline", od_slashline, },
556   { "\\line", od_backline, },
557   { "backline", od_backline, },
558   { "tiny", od_tiny, },
559   { "custom", od_custom, },
560 };
561
562 /* look through the hash for quantization options */
563 static void
564 ip_handle_quant_opts(pTHX_ i_quantize *quant, HV *hv)
565 {
566   /*** POSSIBLY BROKEN: do I need to unref the SV from hv_fetch ***/
567   SV **sv;
568   int i;
569   STRLEN len;
570   char *str;
571
572   quant->mc_colors = mymalloc(quant->mc_size * sizeof(i_color));
573
574   sv = hv_fetch(hv, "transp", 6, 0);
575   if (sv && *sv && (str = SvPV(*sv, len))) {
576     quant->transp = 
577       lookup_name(transp_names, sizeof(transp_names)/sizeof(*transp_names), 
578                   str, tr_none);
579     if (quant->transp != tr_none) {
580       quant->tr_threshold = 127;
581       sv = hv_fetch(hv, "tr_threshold", 12, 0);
582       if (sv && *sv)
583         quant->tr_threshold = SvIV(*sv);
584     }
585     if (quant->transp == tr_errdiff) {
586       sv = hv_fetch(hv, "tr_errdiff", 10, 0);
587       if (sv && *sv && (str = SvPV(*sv, len)))
588         quant->tr_errdiff = lookup_name(errdiff_names, sizeof(errdiff_names)/sizeof(*errdiff_names), str, ed_floyd);
589     }
590     if (quant->transp == tr_ordered) {
591       quant->tr_orddith = od_tiny;
592       sv = hv_fetch(hv, "tr_orddith", 10, 0);
593       if (sv && *sv && (str = SvPV(*sv, len)))
594         quant->tr_orddith = lookup_name(orddith_names, sizeof(orddith_names)/sizeof(*orddith_names), str, od_random);
595
596       if (quant->tr_orddith == od_custom) {
597         sv = hv_fetch(hv, "tr_map", 6, 0);
598         if (sv && *sv && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
599           AV *av = (AV*)SvRV(*sv);
600           len = av_len(av) + 1;
601           if (len > sizeof(quant->tr_custom))
602             len = sizeof(quant->tr_custom);
603           for (i = 0; i < len; ++i) {
604             SV **sv2 = av_fetch(av, i, 0);
605             if (sv2 && *sv2) {
606               quant->tr_custom[i] = SvIV(*sv2);
607             }
608           }
609           while (i < sizeof(quant->tr_custom))
610             quant->tr_custom[i++] = 0;
611         }
612       }
613     }
614   }
615   quant->make_colors = mc_median_cut;
616   sv = hv_fetch(hv, "make_colors", 11, 0);
617   if (sv && *sv && (str = SvPV(*sv, len))) {
618     quant->make_colors = 
619       lookup_name(make_color_names, sizeof(make_color_names)/sizeof(*make_color_names), str, mc_median_cut);
620   }
621   sv = hv_fetch(hv, "colors", 6, 0);
622   if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
623     /* needs to be an array of Imager::Color
624        note that the caller allocates the mc_color array and sets mc_size
625        to it's size */
626     AV *av = (AV *)SvRV(*sv);
627     quant->mc_count = av_len(av)+1;
628     if (quant->mc_count > quant->mc_size)
629       quant->mc_count = quant->mc_size;
630     for (i = 0; i < quant->mc_count; ++i) {
631       SV **sv1 = av_fetch(av, i, 0);
632       if (sv1 && *sv1 && SvROK(*sv1) && sv_derived_from(*sv1, "Imager::Color")) {
633         i_color *col = INT2PTR(i_color *, SvIV((SV*)SvRV(*sv1)));
634         quant->mc_colors[i] = *col;
635       }
636     }
637   }
638   sv = hv_fetch(hv, "max_colors", 10, 0);
639   if (sv && *sv) {
640     i = SvIV(*sv);
641     if (i <= quant->mc_size && i >= quant->mc_count)
642       quant->mc_size = i;
643   }
644
645   quant->translate = pt_closest;
646   sv = hv_fetch(hv, "translate", 9, 0);
647   if (sv && *sv && (str = SvPV(*sv, len))) {
648     quant->translate = lookup_name(translate_names, sizeof(translate_names)/sizeof(*translate_names), str, pt_closest);
649   }
650   sv = hv_fetch(hv, "errdiff", 7, 0);
651   if (sv && *sv && (str = SvPV(*sv, len))) {
652     quant->errdiff = lookup_name(errdiff_names, sizeof(errdiff_names)/sizeof(*errdiff_names), str, ed_floyd);
653   }
654   if (quant->translate == pt_errdiff && quant->errdiff == ed_custom) {
655     /* get the error diffusion map */
656     sv = hv_fetch(hv, "errdiff_width", 13, 0);
657     if (sv && *sv)
658       quant->ed_width = SvIV(*sv);
659     sv = hv_fetch(hv, "errdiff_height", 14, 0);
660     if (sv && *sv)
661       quant->ed_height = SvIV(*sv);
662     sv = hv_fetch(hv, "errdiff_orig", 12, 0);
663     if (sv && *sv)
664       quant->ed_orig = SvIV(*sv);
665     if (quant->ed_width > 0 && quant->ed_height > 0) {
666       int sum = 0;
667       quant->ed_map = mymalloc(sizeof(int)*quant->ed_width*quant->ed_height);
668       sv = hv_fetch(hv, "errdiff_map", 11, 0);
669       if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
670         AV *av = (AV*)SvRV(*sv);
671         len = av_len(av) + 1;
672         if (len > quant->ed_width * quant->ed_height)
673           len = quant->ed_width * quant->ed_height;
674         for (i = 0; i < len; ++i) {
675           SV **sv2 = av_fetch(av, i, 0);
676           if (sv2 && *sv2) {
677             quant->ed_map[i] = SvIV(*sv2);
678             sum += quant->ed_map[i];
679           }
680         }
681       }
682       if (!sum) {
683         /* broken map */
684         myfree(quant->ed_map);
685         quant->ed_map = 0;
686         quant->errdiff = ed_floyd;
687       }
688     }
689   }
690   sv = hv_fetch(hv, "perturb", 7, 0);
691   if (sv && *sv)
692     quant->perturb = SvIV(*sv);
693 }
694
695 static void
696 ip_cleanup_quant_opts(pTHX_ i_quantize *quant) {
697   myfree(quant->mc_colors);
698   if (quant->ed_map)
699     myfree(quant->ed_map);
700 }
701
702 /* copies the color map from the hv into the colors member of the HV */
703 static void
704 ip_copy_colors_back(pTHX_ HV *hv, i_quantize *quant) {
705   SV **sv;
706   AV *av;
707   int i;
708   SV *work;
709
710   sv = hv_fetch(hv, "colors", 6, 0);
711   if (!sv || !*sv || !SvROK(*sv) || SvTYPE(SvRV(*sv)) != SVt_PVAV) {
712     /* nothing to do */
713     return;
714   }
715
716   av = (AV *)SvRV(*sv);
717   av_clear(av);
718   av_extend(av, quant->mc_count+1);
719   for (i = 0; i < quant->mc_count; ++i) {
720     i_color *in = quant->mc_colors+i;
721     Imager__Color c = ICL_new_internal(in->rgb.r, in->rgb.g, in->rgb.b, 255);
722     work = sv_newmortal();
723     sv_setref_pv(work, "Imager::Color", (void *)c);
724     SvREFCNT_inc(work);
725     av_push(av, work);
726   }
727 }
728
729 /* loads the segments of a fountain fill into an array */
730 static i_fountain_seg *
731 load_fount_segs(pTHX_ AV *asegs, int *count) {
732   /* Each element of segs must contain:
733      [ start, middle, end, c0, c1, segtype, colortrans ]
734      start, middle, end are doubles from 0 to 1
735      c0, c1 are Imager::Color::Float or Imager::Color objects
736      segtype, colortrans are ints
737   */
738   int i, j;
739   AV *aseg;
740   i_fountain_seg *segs;
741   double work[3];
742   int worki[2];
743
744   *count = av_len(asegs)+1;
745   if (*count < 1) 
746     croak("i_fountain must have at least one segment");
747   segs = mymalloc(sizeof(i_fountain_seg) * *count);
748   for(i = 0; i < *count; i++) {
749     SV **sv1 = av_fetch(asegs, i, 0);
750     if (!sv1 || !*sv1 || !SvROK(*sv1) 
751         || SvTYPE(SvRV(*sv1)) != SVt_PVAV) {
752       myfree(segs);
753       croak("i_fountain: segs must be an arrayref of arrayrefs");
754     }
755     aseg = (AV *)SvRV(*sv1);
756     if (av_len(aseg) != 7-1) {
757       myfree(segs);
758       croak("i_fountain: a segment must have 7 members");
759     }
760     for (j = 0; j < 3; ++j) {
761       SV **sv2 = av_fetch(aseg, j, 0);
762       if (!sv2 || !*sv2) {
763         myfree(segs);
764         croak("i_fountain: XS error");
765       }
766       work[j] = SvNV(*sv2);
767     }
768     segs[i].start  = work[0];
769     segs[i].middle = work[1];
770     segs[i].end    = work[2];
771     for (j = 0; j < 2; ++j) {
772       SV **sv3 = av_fetch(aseg, 3+j, 0);
773       if (!sv3 || !*sv3 || !SvROK(*sv3) ||
774           (!sv_derived_from(*sv3, "Imager::Color")
775            && !sv_derived_from(*sv3, "Imager::Color::Float"))) {
776         myfree(segs);
777         croak("i_fountain: segs must contain colors in elements 3 and 4");
778       }
779       if (sv_derived_from(*sv3, "Imager::Color::Float")) {
780         segs[i].c[j] = *INT2PTR(i_fcolor *, SvIV((SV *)SvRV(*sv3)));
781       }
782       else {
783         i_color c = *INT2PTR(i_color *, SvIV((SV *)SvRV(*sv3)));
784         int ch;
785         for (ch = 0; ch < MAXCHANNELS; ++ch) {
786           segs[i].c[j].channel[ch] = c.channel[ch] / 255.0;
787         }
788       }
789     }
790     for (j = 0; j < 2; ++j) {
791       SV **sv2 = av_fetch(aseg, j+5, 0);
792       if (!sv2 || !*sv2) {
793         myfree(segs);
794         croak("i_fountain: XS error");
795       }
796       worki[j] = SvIV(*sv2);
797     }
798     segs[i].type = worki[0];
799     segs[i].color = worki[1];
800   }
801
802   return segs;
803 }
804
805 /* validates the indexes supplied to i_ppal
806
807 i_ppal() doesn't do that for speed, but I'm not comfortable doing that
808 for calls from perl.
809
810 */
811 static void
812 validate_i_ppal(i_img *im, i_palidx const *indexes, int count) {
813   int color_count = i_colorcount(im);
814   int i;
815
816   if (color_count == -1)
817     croak("i_plin() called on direct color image");
818   
819   for (i = 0; i < count; ++i) {
820     if (indexes[i] >= color_count) {
821       croak("i_plin() called with out of range color index %d (max %d)",
822         indexes[i], color_count-1);
823     }
824   }
825 }
826
827 /* I don't think ICLF_* names belong at the C interface
828    this makes the XS code think we have them, to let us avoid 
829    putting function bodies in the XS code
830 */
831 #define ICLF_new_internal(r, g, b, a) i_fcolor_new((r), (g), (b), (a))
832 #define ICLF_DESTROY(cl) i_fcolor_destroy(cl)
833
834 #ifdef IMAGER_LOG
835 #define i_log_enabled() 1
836 #else
837 #define i_log_enabled() 0
838 #endif
839
840 #if i_int_hlines_testing()
841
842 typedef i_int_hlines *Imager__Internal__Hlines;
843
844 static i_int_hlines *
845 i_int_hlines_new(i_img_dim start_y, i_img_dim count_y, i_img_dim start_x, i_img_dim count_x) {
846   i_int_hlines *result = mymalloc(sizeof(i_int_hlines));
847   i_int_init_hlines(result, start_y, count_y, start_x, count_x);
848
849   return result;
850 }
851
852 static i_int_hlines *
853 i_int_hlines_new_img(i_img *im) {
854   i_int_hlines *result = mymalloc(sizeof(i_int_hlines));
855   i_int_init_hlines_img(result, im);
856
857   return result;
858 }
859
860 static void
861 i_int_hlines_DESTROY(i_int_hlines *hlines) {
862   i_int_hlines_destroy(hlines);
863   myfree(hlines);
864 }
865
866 #define i_int_hlines_CLONE_SKIP(cls) 1
867
868 static int seg_compare(const void *vleft, const void *vright) {
869   const i_int_hline_seg *left = vleft;
870   const i_int_hline_seg *right = vright;
871
872   return left->minx - right->minx;
873 }
874
875 static SV *
876 i_int_hlines_dump(i_int_hlines *hlines) {
877   dTHX;
878   SV *dump = newSVpvf("start_y: %" i_DF " limit_y: %" i_DF " start_x: %" i_DF " limit_x: %" i_DF"\n",
879         i_DFc(hlines->start_y), i_DFc(hlines->limit_y), i_DFc(hlines->start_x), i_DFc(hlines->limit_x));
880   i_img_dim y;
881   
882   for (y = hlines->start_y; y < hlines->limit_y; ++y) {
883     i_int_hline_entry *entry = hlines->entries[y-hlines->start_y];
884     if (entry) {
885       int i;
886       /* sort the segments, if any */
887       if (entry->count)
888         qsort(entry->segs, entry->count, sizeof(i_int_hline_seg), seg_compare);
889
890       sv_catpvf(dump, " %" i_DF " (%" i_DF "):", i_DFc(y), i_DFc(entry->count));
891       for (i = 0; i < entry->count; ++i) {
892         sv_catpvf(dump, " [%" i_DF ", %" i_DF ")", i_DFc(entry->segs[i].minx), 
893                   i_DFc(entry->segs[i].x_limit));
894       }
895       sv_catpv(dump, "\n");
896     }
897   }
898
899   return dump;
900 }
901
902 #endif
903
904 static off_t
905 i_sv_off_t(pTHX_ SV *sv) {
906 #if LSEEKSIZE > IVSIZE
907   return (off_t)SvNV(sv);
908 #else
909   return (off_t)SvIV(sv);
910 #endif
911 }
912
913 static SV *
914 i_new_sv_off_t(pTHX_ off_t off) {
915 #if LSEEKSIZE > IVSIZE
916   return newSVnv(off);
917 #else
918   return newSViv(off);
919 #endif
920 }
921
922 static im_pl_ext_funcs im_perl_funcs =
923 {
924   IMAGER_PL_API_VERSION,
925   IMAGER_PL_API_LEVEL,
926   ip_handle_quant_opts,
927   ip_cleanup_quant_opts,
928   ip_copy_colors_back
929 };
930
931 #define PERL_PL_SET_GLOBAL_CALLBACKS \
932   sv_setiv(get_sv(PERL_PL_FUNCTION_TABLE_NAME, 1), PTR2IV(&im_perl_funcs));
933
934 #define IIM_new i_img_8_new
935 #define IIM_DESTROY i_img_destroy
936 typedef int SysRet;
937
938 #ifdef IMEXIF_ENABLE
939 #define i_exif_enabled() 1
940 #else
941 #define i_exif_enabled() 0
942 #endif
943
944 /* trying to use more C style names, map them here */
945 #define i_io_DESTROY(ig) io_glue_destroy(ig)
946
947 #define i_img_get_width(im) ((im)->xsize)
948 #define i_img_get_height(im) ((im)->ysize)
949
950 #define i_img_epsilonf() (DBL_EPSILON * 4)
951
952 /* avoid some xsubpp strangeness */
953 #define NEWLINE '\n'
954
955 MODULE = Imager         PACKAGE = Imager::Color PREFIX = ICL_
956
957 Imager::Color
958 ICL_new_internal(r,g,b,a)
959                unsigned char     r
960                unsigned char     g
961                unsigned char     b
962                unsigned char     a
963
964 void
965 ICL_DESTROY(cl)
966                Imager::Color    cl
967
968
969 void
970 ICL_set_internal(cl,r,g,b,a)
971                Imager::Color    cl
972                unsigned char     r
973                unsigned char     g
974                unsigned char     b
975                unsigned char     a
976            PPCODE:
977                ICL_set_internal(cl, r, g, b, a);
978                EXTEND(SP, 1);
979                PUSHs(ST(0));
980
981 void
982 ICL_info(cl)
983                Imager::Color    cl
984
985
986 void
987 ICL_rgba(cl)
988               Imager::Color     cl
989             PPCODE:
990                 EXTEND(SP, 4);
991                 PUSHs(sv_2mortal(newSViv(cl->rgba.r)));
992                 PUSHs(sv_2mortal(newSViv(cl->rgba.g)));
993                 PUSHs(sv_2mortal(newSViv(cl->rgba.b)));
994                 PUSHs(sv_2mortal(newSViv(cl->rgba.a)));
995
996 Imager::Color
997 i_hsv_to_rgb(c)
998         Imager::Color c
999       CODE:
1000         RETVAL = mymalloc(sizeof(i_color));
1001         *RETVAL = *c;
1002         i_hsv_to_rgb(RETVAL);
1003       OUTPUT:
1004         RETVAL
1005         
1006 Imager::Color
1007 i_rgb_to_hsv(c)
1008         Imager::Color c
1009       CODE:
1010         RETVAL = mymalloc(sizeof(i_color));
1011         *RETVAL = *c;
1012         i_rgb_to_hsv(RETVAL);
1013       OUTPUT:
1014         RETVAL
1015         
1016
1017
1018 MODULE = Imager        PACKAGE = Imager::Color::Float  PREFIX=ICLF_
1019
1020 Imager::Color::Float
1021 ICLF_new_internal(r, g, b, a)
1022         double r
1023         double g
1024         double b
1025         double a
1026
1027 void
1028 ICLF_DESTROY(cl)
1029         Imager::Color::Float    cl
1030
1031 void
1032 ICLF_rgba(cl)
1033         Imager::Color::Float    cl
1034       PREINIT:
1035         int ch;
1036       PPCODE:
1037         EXTEND(SP, MAXCHANNELS);
1038         for (ch = 0; ch < MAXCHANNELS; ++ch) {
1039         /* printf("%d: %g\n", ch, cl->channel[ch]); */
1040           PUSHs(sv_2mortal(newSVnv(cl->channel[ch])));
1041         }
1042
1043 void
1044 ICLF_set_internal(cl,r,g,b,a)
1045         Imager::Color::Float    cl
1046         double     r
1047         double     g
1048         double     b
1049         double     a
1050       PPCODE:
1051         cl->rgba.r = r;
1052         cl->rgba.g = g;
1053         cl->rgba.b = b;
1054         cl->rgba.a = a;                
1055         EXTEND(SP, 1);
1056         PUSHs(ST(0));
1057
1058 Imager::Color::Float
1059 i_hsv_to_rgb(c)
1060         Imager::Color::Float c
1061       CODE:
1062         RETVAL = mymalloc(sizeof(i_fcolor));
1063         *RETVAL = *c;
1064         i_hsv_to_rgbf(RETVAL);
1065       OUTPUT:
1066         RETVAL
1067         
1068 Imager::Color::Float
1069 i_rgb_to_hsv(c)
1070         Imager::Color::Float c
1071       CODE:
1072         RETVAL = mymalloc(sizeof(i_fcolor));
1073         *RETVAL = *c;
1074         i_rgb_to_hsvf(RETVAL);
1075       OUTPUT:
1076         RETVAL
1077
1078 MODULE = Imager         PACKAGE = Imager::ImgRaw        PREFIX = IIM_
1079
1080 Imager::ImgRaw
1081 IIM_new(x,y,ch)
1082                i_img_dim     x
1083                i_img_dim     y
1084                int     ch
1085
1086 void
1087 IIM_DESTROY(im)
1088                Imager::ImgRaw    im
1089
1090
1091
1092 MODULE = Imager         PACKAGE = Imager
1093
1094 PROTOTYPES: ENABLE
1095
1096
1097 Imager::IO
1098 io_new_fd(fd)
1099                          int     fd
1100
1101 Imager::IO
1102 io_new_bufchain()
1103
1104
1105 Imager::IO
1106 io_new_buffer(data_sv)
1107           SV   *data_sv
1108         CODE:
1109           RETVAL = do_io_new_buffer(aTHX_ data_sv);
1110         OUTPUT:
1111           RETVAL
1112
1113 Imager::IO
1114 io_new_cb(writecb, readcb, seekcb, closecb, maxwrite = CBDATA_BUFSIZE)
1115         SV *writecb;
1116         SV *readcb;
1117         SV *seekcb;
1118         SV *closecb;
1119       CODE:
1120         RETVAL = do_io_new_cb(aTHX_ writecb, readcb, seekcb, closecb);
1121       OUTPUT:
1122         RETVAL
1123
1124 SV *
1125 io_slurp(ig)
1126         Imager::IO     ig
1127              PREINIT:
1128               unsigned char*    data;
1129               size_t    tlength;
1130              CODE:
1131               data    = NULL;
1132               tlength = io_slurp(ig, &data);
1133               RETVAL = newSVpv((char *)data,tlength);
1134               myfree(data);
1135              OUTPUT:
1136               RETVAL
1137
1138
1139 undef_int
1140 i_set_image_file_limits(width, height, bytes)
1141         i_img_dim width
1142         i_img_dim height
1143         size_t bytes
1144
1145 void
1146 i_get_image_file_limits()
1147       PREINIT:
1148         i_img_dim width, height;
1149         size_t bytes;
1150       PPCODE:
1151         if (i_get_image_file_limits(&width, &height, &bytes)) {
1152           EXTEND(SP, 3);
1153           PUSHs(sv_2mortal(newSViv(width)));
1154           PUSHs(sv_2mortal(newSViv(height)));
1155           PUSHs(sv_2mortal(newSVuv(bytes)));
1156         }
1157
1158 bool
1159 i_int_check_image_file_limits(width, height, channels, sample_size)
1160         i_img_dim width
1161         i_img_dim height
1162         int channels
1163         size_t sample_size
1164   PROTOTYPE: DISABLE
1165
1166 MODULE = Imager         PACKAGE = Imager::IO    PREFIX = io_
1167
1168 Imager::IO
1169 io_new_fd(class, fd)
1170         int fd
1171     CODE:
1172         RETVAL = io_new_fd(fd);
1173     OUTPUT:
1174         RETVAL
1175
1176 Imager::IO
1177 io_new_buffer(class, data_sv)
1178         SV *data_sv
1179     CODE:
1180         RETVAL = do_io_new_buffer(aTHX_ data_sv);
1181     OUTPUT:
1182         RETVAL
1183
1184 Imager::IO
1185 io_new_cb(class, writecb, readcb, seekcb, closecb)
1186         SV *writecb;
1187         SV *readcb;
1188         SV *seekcb;
1189         SV *closecb;
1190     CODE:
1191         RETVAL = do_io_new_cb(aTHX_ writecb, readcb, seekcb, closecb);
1192     OUTPUT:
1193         RETVAL
1194
1195 Imager::IO
1196 io_new_bufchain(class)
1197     CODE:
1198         RETVAL = io_new_bufchain();
1199     OUTPUT:
1200         RETVAL
1201
1202 Imager::IO
1203 io__new_perlio(class, io)
1204         PerlIO *io
1205   CODE:
1206         RETVAL = im_io_new_perlio(aTHX_ io);
1207   OUTPUT:
1208         RETVAL
1209
1210 SV *
1211 io_slurp(class, ig)
1212         Imager::IO     ig
1213     PREINIT:
1214         unsigned char*    data;
1215         size_t    tlength;
1216     CODE:
1217         data    = NULL;
1218         tlength = io_slurp(ig, &data);
1219         RETVAL = newSVpv((char *)data,tlength);
1220         myfree(data);
1221     OUTPUT:
1222         RETVAL
1223
1224 MODULE = Imager         PACKAGE = Imager::IO    PREFIX = i_io_
1225
1226 IV
1227 i_io_raw_write(ig, data_sv)
1228         Imager::IO ig
1229         SV *data_sv
1230       PREINIT:
1231         void *data;
1232         STRLEN size;
1233       CODE:
1234         data = SvPVbyte(data_sv, size);
1235         RETVAL = i_io_raw_write(ig, data, size);
1236       OUTPUT:
1237         RETVAL
1238
1239 void
1240 i_io_raw_read(ig, buffer_sv, size)
1241         Imager::IO ig
1242         SV *buffer_sv
1243         IV size
1244       PREINIT:
1245         void *buffer;
1246         ssize_t result;
1247       PPCODE:
1248         if (size <= 0)
1249           croak("size negative in call to i_io_raw_read()");
1250         /* prevent an undefined value warning if they supplied an 
1251            undef buffer.
1252            Orginally conditional on !SvOK(), but this will prevent the
1253            downgrade from croaking */
1254         sv_setpvn(buffer_sv, "", 0);
1255 #ifdef SvUTF8
1256         if (SvUTF8(buffer_sv))
1257           sv_utf8_downgrade(buffer_sv, FALSE);
1258 #endif
1259         buffer = SvGROW(buffer_sv, size+1);
1260         result = i_io_raw_read(ig, buffer, size);
1261         if (result >= 0) {
1262           SvCUR_set(buffer_sv, result);
1263           *SvEND(buffer_sv) = '\0';
1264           SvPOK_only(buffer_sv);
1265           EXTEND(SP, 1);
1266           PUSHs(sv_2mortal(newSViv(result)));
1267         }
1268         ST(1) = buffer_sv;
1269         SvSETMAGIC(ST(1));
1270
1271 void
1272 i_io_raw_read2(ig, size)
1273         Imager::IO ig
1274         IV size
1275       PREINIT:
1276         SV *buffer_sv;
1277         void *buffer;
1278         ssize_t result;
1279       PPCODE:
1280         if (size <= 0)
1281           croak("size negative in call to i_io_read2()");
1282         buffer_sv = newSV(size);
1283         buffer = SvGROW(buffer_sv, size+1);
1284         result = i_io_raw_read(ig, buffer, size);
1285         if (result >= 0) {
1286           SvCUR_set(buffer_sv, result);
1287           *SvEND(buffer_sv) = '\0';
1288           SvPOK_only(buffer_sv);
1289           EXTEND(SP, 1);
1290           PUSHs(sv_2mortal(buffer_sv));
1291         }
1292         else {
1293           /* discard it */
1294           SvREFCNT_dec(buffer_sv);
1295         }
1296
1297 off_t
1298 i_io_raw_seek(ig, position, whence)
1299         Imager::IO ig
1300         off_t position
1301         int whence
1302
1303 int
1304 i_io_raw_close(ig)
1305         Imager::IO ig
1306
1307 void
1308 i_io_DESTROY(ig)
1309         Imager::IO     ig
1310
1311 int
1312 i_io_CLONE_SKIP(...)
1313     CODE:
1314         (void)items; /* avoid unused warning for XS variable */
1315         RETVAL = 1;
1316     OUTPUT:
1317         RETVAL
1318
1319 int
1320 i_io_getc(ig)
1321         Imager::IO ig
1322
1323 int
1324 i_io_putc(ig, c)
1325         Imager::IO ig
1326         int c
1327
1328 int
1329 i_io_close(ig)
1330         Imager::IO ig
1331
1332 int
1333 i_io_flush(ig)
1334         Imager::IO ig
1335
1336 int
1337 i_io_peekc(ig)
1338         Imager::IO ig
1339
1340 int
1341 i_io_seek(ig, off, whence)
1342         Imager::IO ig
1343         off_t off
1344         int whence
1345
1346 void
1347 i_io_peekn(ig, size)
1348         Imager::IO ig
1349         STRLEN size
1350       PREINIT:
1351         SV *buffer_sv;
1352         void *buffer;
1353         ssize_t result;
1354       PPCODE:
1355         buffer_sv = newSV(size+1);
1356         buffer = SvGROW(buffer_sv, size+1);
1357         result = i_io_peekn(ig, buffer, size);
1358         if (result >= 0) {
1359           SvCUR_set(buffer_sv, result);
1360           *SvEND(buffer_sv) = '\0';
1361           SvPOK_only(buffer_sv);
1362           EXTEND(SP, 1);
1363           PUSHs(sv_2mortal(buffer_sv));
1364         }
1365         else {
1366           /* discard it */
1367           SvREFCNT_dec(buffer_sv);
1368         }
1369
1370 void
1371 i_io_read(ig, buffer_sv, size)
1372         Imager::IO ig
1373         SV *buffer_sv
1374         IV size
1375       PREINIT:
1376         void *buffer;
1377         ssize_t result;
1378       PPCODE:
1379         if (size <= 0)
1380           croak("size negative in call to i_io_read()");
1381         /* prevent an undefined value warning if they supplied an 
1382            undef buffer.
1383            Orginally conditional on !SvOK(), but this will prevent the
1384            downgrade from croaking */
1385         sv_setpvn(buffer_sv, "", 0);
1386 #ifdef SvUTF8
1387         if (SvUTF8(buffer_sv))
1388           sv_utf8_downgrade(buffer_sv, FALSE);
1389 #endif
1390         buffer = SvGROW(buffer_sv, size+1);
1391         result = i_io_read(ig, buffer, size);
1392         if (result >= 0) {
1393           SvCUR_set(buffer_sv, result);
1394           *SvEND(buffer_sv) = '\0';
1395           SvPOK_only(buffer_sv);
1396           EXTEND(SP, 1);
1397           PUSHs(sv_2mortal(newSViv(result)));
1398         }
1399         ST(1) = buffer_sv;
1400         SvSETMAGIC(ST(1));
1401
1402 void
1403 i_io_read2(ig, size)
1404         Imager::IO ig
1405         STRLEN size
1406       PREINIT:
1407         SV *buffer_sv;
1408         void *buffer;
1409         ssize_t result;
1410       PPCODE:
1411         if (size == 0)
1412           croak("size zero in call to read2()");
1413         buffer_sv = newSV(size);
1414         buffer = SvGROW(buffer_sv, size+1);
1415         result = i_io_read(ig, buffer, size);
1416         if (result > 0) {
1417           SvCUR_set(buffer_sv, result);
1418           *SvEND(buffer_sv) = '\0';
1419           SvPOK_only(buffer_sv);
1420           EXTEND(SP, 1);
1421           PUSHs(sv_2mortal(buffer_sv));
1422         }
1423         else {
1424           /* discard it */
1425           SvREFCNT_dec(buffer_sv);
1426         }
1427
1428 void
1429 i_io_gets(ig, size = 8192, eol = NEWLINE)
1430         Imager::IO ig
1431         STRLEN size
1432         int eol
1433       PREINIT:
1434         SV *buffer_sv;
1435         void *buffer;
1436         ssize_t result;
1437       PPCODE:
1438         if (size < 2)
1439           croak("size too small in call to gets()");
1440         buffer_sv = sv_2mortal(newSV(size+1));
1441         buffer = SvPVX(buffer_sv);
1442         result = i_io_gets(ig, buffer, size+1, eol);
1443         if (result > 0) {
1444           SvCUR_set(buffer_sv, result);
1445           *SvEND(buffer_sv) = '\0';
1446           SvPOK_only(buffer_sv);
1447           EXTEND(SP, 1);
1448           PUSHs(buffer_sv);
1449         }
1450
1451 IV
1452 i_io_write(ig, data_sv)
1453         Imager::IO ig
1454         SV *data_sv
1455       PREINIT:
1456         void *data;
1457         STRLEN size;
1458       CODE:
1459         data = SvPVbyte(data_sv, size);
1460         RETVAL = i_io_write(ig, data, size);
1461       OUTPUT:
1462         RETVAL
1463
1464 void
1465 i_io_dump(ig, flags = I_IO_DUMP_DEFAULT)
1466         Imager::IO ig
1467         int flags
1468
1469 bool
1470 i_io_set_buffered(ig, flag = 1)
1471         Imager::IO ig
1472         int flag
1473
1474 bool
1475 i_io_is_buffered(ig)
1476         Imager::IO ig
1477
1478 bool
1479 i_io_eof(ig)
1480         Imager::IO ig
1481
1482 bool
1483 i_io_error(ig)
1484         Imager::IO ig
1485
1486 MODULE = Imager         PACKAGE = Imager
1487
1488 PROTOTYPES: ENABLE
1489
1490 void
1491 i_list_formats()
1492              PREINIT:
1493               char*    item;
1494                int     i;
1495              PPCODE:
1496                i=0;
1497                while( (item=i_format_list[i++]) != NULL ) {
1498                       EXTEND(SP, 1);
1499                       PUSHs(sv_2mortal(newSVpv(item,0)));
1500                }
1501
1502 Imager::ImgRaw
1503 i_sametype(im, x, y)
1504     Imager::ImgRaw im
1505                i_img_dim x
1506                i_img_dim y
1507
1508 Imager::ImgRaw
1509 i_sametype_chans(im, x, y, channels)
1510     Imager::ImgRaw im
1511                i_img_dim x
1512                i_img_dim y
1513                int channels
1514
1515 int
1516 i_init_log(name_sv,level)
1517               SV*    name_sv
1518                int     level
1519         PREINIT:
1520           const char *name = SvOK(name_sv) ? SvPV_nolen(name_sv) : NULL;
1521         CODE:
1522           RETVAL = i_init_log(name, level);
1523         OUTPUT:
1524           RETVAL
1525
1526 void
1527 i_log_entry(string,level)
1528               char*    string
1529                int     level
1530
1531 int
1532 i_log_enabled()
1533
1534 void
1535 i_img_info(im)
1536     Imager::ImgRaw     im
1537              PREINIT:
1538                i_img_dim     info[4];
1539              PPCODE:
1540                i_img_info(im,info);
1541                EXTEND(SP, 4);
1542                PUSHs(sv_2mortal(newSViv(info[0])));
1543                PUSHs(sv_2mortal(newSViv(info[1])));
1544                PUSHs(sv_2mortal(newSViv(info[2])));
1545                PUSHs(sv_2mortal(newSViv(info[3])));
1546
1547
1548
1549
1550 void
1551 i_img_setmask(im,ch_mask)
1552     Imager::ImgRaw     im
1553                int     ch_mask
1554
1555 int
1556 i_img_getmask(im)
1557     Imager::ImgRaw     im
1558
1559 int
1560 i_img_getchannels(im)
1561     Imager::ImgRaw     im
1562
1563 void
1564 i_img_getdata(im)
1565     Imager::ImgRaw     im
1566              PPCODE:
1567                EXTEND(SP, 1);
1568                PUSHs(im->idata ? 
1569                      sv_2mortal(newSVpv((char *)im->idata, im->bytes)) 
1570                      : &PL_sv_undef);
1571
1572 IV
1573 i_img_get_width(im)
1574     Imager::ImgRaw      im
1575
1576 IV
1577 i_img_get_height(im)
1578     Imager::ImgRaw      im
1579
1580
1581 void
1582 i_img_is_monochrome(im)
1583         Imager::ImgRaw im
1584       PREINIT:
1585         int zero_is_white;
1586         int result;
1587       PPCODE:
1588         result = i_img_is_monochrome(im, &zero_is_white);
1589         if (result) {
1590           if (GIMME_V == G_ARRAY) {
1591             EXTEND(SP, 2);
1592             PUSHs(&PL_sv_yes);
1593             PUSHs(sv_2mortal(newSViv(zero_is_white)));
1594           }
1595           else {
1596             EXTEND(SP, 1);
1597             PUSHs(&PL_sv_yes);
1598           }
1599         }
1600
1601 void
1602 i_line(im,x1,y1,x2,y2,val,endp)
1603     Imager::ImgRaw     im
1604                i_img_dim     x1
1605                i_img_dim     y1
1606                i_img_dim     x2
1607                i_img_dim     y2
1608      Imager::Color     val
1609                int     endp
1610
1611 void
1612 i_line_aa(im,x1,y1,x2,y2,val,endp)
1613     Imager::ImgRaw     im
1614                i_img_dim     x1
1615                i_img_dim     y1
1616                i_img_dim     x2
1617                i_img_dim     y2
1618      Imager::Color     val
1619                int     endp
1620
1621 void
1622 i_box(im,x1,y1,x2,y2,val)
1623     Imager::ImgRaw     im
1624                i_img_dim     x1
1625                i_img_dim     y1
1626                i_img_dim     x2
1627                i_img_dim     y2
1628      Imager::Color     val
1629
1630 void
1631 i_box_filled(im,x1,y1,x2,y2,val)
1632     Imager::ImgRaw     im
1633                i_img_dim     x1
1634                i_img_dim     y1
1635                i_img_dim     x2
1636                i_img_dim     y2
1637            Imager::Color    val
1638
1639 int
1640 i_box_filledf(im,x1,y1,x2,y2,val)
1641     Imager::ImgRaw     im
1642                i_img_dim     x1
1643                i_img_dim     y1
1644                i_img_dim     x2
1645                i_img_dim     y2
1646            Imager::Color::Float    val
1647
1648 void
1649 i_box_cfill(im,x1,y1,x2,y2,fill)
1650     Imager::ImgRaw     im
1651                i_img_dim     x1
1652                i_img_dim     y1
1653                i_img_dim     x2
1654                i_img_dim     y2
1655            Imager::FillHandle    fill
1656
1657 void
1658 i_arc(im,x,y,rad,d1,d2,val)
1659     Imager::ImgRaw     im
1660                i_img_dim     x
1661                i_img_dim     y
1662              double     rad
1663              double     d1
1664              double     d2
1665            Imager::Color    val
1666
1667 void
1668 i_arc_aa(im,x,y,rad,d1,d2,val)
1669     Imager::ImgRaw     im
1670             double     x
1671             double     y
1672             double     rad
1673             double     d1
1674             double     d2
1675            Imager::Color    val
1676
1677 void
1678 i_arc_cfill(im,x,y,rad,d1,d2,fill)
1679     Imager::ImgRaw     im
1680                i_img_dim     x
1681                i_img_dim     y
1682              double     rad
1683              double     d1
1684              double     d2
1685            Imager::FillHandle    fill
1686
1687 void
1688 i_arc_aa_cfill(im,x,y,rad,d1,d2,fill)
1689     Imager::ImgRaw     im
1690             double     x
1691             double     y
1692             double     rad
1693             double     d1
1694             double     d2
1695            Imager::FillHandle   fill
1696
1697
1698 void
1699 i_circle_aa(im,x,y,rad,val)
1700     Imager::ImgRaw     im
1701              double     x
1702              double     y
1703              double     rad
1704            Imager::Color    val
1705
1706 int
1707 i_circle_out(im,x,y,rad,val)
1708     Imager::ImgRaw     im
1709              i_img_dim     x
1710              i_img_dim     y
1711              i_img_dim     rad
1712            Imager::Color    val
1713
1714 int
1715 i_circle_out_aa(im,x,y,rad,val)
1716     Imager::ImgRaw     im
1717              i_img_dim     x
1718              i_img_dim     y
1719              i_img_dim     rad
1720            Imager::Color    val
1721
1722 int
1723 i_arc_out(im,x,y,rad,d1,d2,val)
1724     Imager::ImgRaw     im
1725              i_img_dim     x
1726              i_img_dim     y
1727              i_img_dim     rad
1728              double d1
1729              double d2
1730            Imager::Color    val
1731
1732 int
1733 i_arc_out_aa(im,x,y,rad,d1,d2,val)
1734     Imager::ImgRaw     im
1735              i_img_dim     x
1736              i_img_dim     y
1737              i_img_dim     rad
1738              double d1
1739              double d2
1740            Imager::Color    val
1741
1742
1743 void
1744 i_bezier_multi(im,x,y,val)
1745     Imager::ImgRaw     im
1746     double *x
1747     double *y
1748     Imager::Color  val
1749   PREINIT:
1750     STRLEN size_x;
1751     STRLEN size_y;
1752   PPCODE:
1753     if (size_x != size_y)
1754       croak("Imager: x and y arrays to i_bezier_multi must be equal length\n");
1755     i_bezier_multi(im,size_x,x,y,val);
1756
1757 int
1758 i_poly_aa(im,x,y,val)
1759     Imager::ImgRaw     im
1760     double *x
1761     double *y
1762     Imager::Color  val
1763   PREINIT:
1764     STRLEN   size_x;
1765     STRLEN   size_y;
1766   CODE:
1767     if (size_x != size_y)
1768       croak("Imager: x and y arrays to i_poly_aa must be equal length\n");
1769     RETVAL = i_poly_aa(im, size_x, x, y, val);
1770   OUTPUT:
1771     RETVAL
1772
1773 int
1774 i_poly_aa_cfill(im, x, y, fill)
1775     Imager::ImgRaw     im
1776     double *x
1777     double *y
1778     Imager::FillHandle     fill
1779   PREINIT:
1780     STRLEN size_x;
1781     STRLEN size_y;
1782   CODE:
1783     if (size_x != size_y)
1784       croak("Imager: x and y arrays to i_poly_aa_cfill must be equal length\n");
1785     RETVAL = i_poly_aa_cfill(im, size_x, x, y, fill);
1786   OUTPUT:
1787     RETVAL
1788
1789 undef_int
1790 i_flood_fill(im,seedx,seedy,dcol)
1791     Imager::ImgRaw     im
1792                i_img_dim     seedx
1793                i_img_dim     seedy
1794      Imager::Color     dcol
1795
1796 undef_int
1797 i_flood_cfill(im,seedx,seedy,fill)
1798     Imager::ImgRaw     im
1799                i_img_dim     seedx
1800                i_img_dim     seedy
1801      Imager::FillHandle     fill
1802
1803 undef_int
1804 i_flood_fill_border(im,seedx,seedy,dcol, border)
1805     Imager::ImgRaw     im
1806                i_img_dim     seedx
1807                i_img_dim     seedy
1808      Imager::Color     dcol
1809      Imager::Color     border
1810
1811 undef_int
1812 i_flood_cfill_border(im,seedx,seedy,fill, border)
1813     Imager::ImgRaw     im
1814                i_img_dim     seedx
1815                i_img_dim     seedy
1816      Imager::FillHandle     fill
1817      Imager::Color     border
1818
1819
1820 void
1821 i_copyto(im,src,x1,y1,x2,y2,tx,ty)
1822     Imager::ImgRaw     im
1823     Imager::ImgRaw     src
1824                i_img_dim     x1
1825                i_img_dim     y1
1826                i_img_dim     x2
1827                i_img_dim     y2
1828                i_img_dim     tx
1829                i_img_dim     ty
1830
1831
1832 void
1833 i_copyto_trans(im,src,x1,y1,x2,y2,tx,ty,trans)
1834     Imager::ImgRaw     im
1835     Imager::ImgRaw     src
1836                i_img_dim     x1
1837                i_img_dim     y1
1838                i_img_dim     x2
1839                i_img_dim     y2
1840                i_img_dim     tx
1841                i_img_dim     ty
1842      Imager::Color     trans
1843
1844 Imager::ImgRaw
1845 i_copy(src)
1846     Imager::ImgRaw     src
1847
1848
1849 undef_int
1850 i_rubthru(im,src,tx,ty,src_minx,src_miny,src_maxx,src_maxy)
1851     Imager::ImgRaw     im
1852     Imager::ImgRaw     src
1853                i_img_dim     tx
1854                i_img_dim     ty
1855                i_img_dim     src_minx
1856                i_img_dim     src_miny
1857                i_img_dim     src_maxx
1858                i_img_dim     src_maxy
1859
1860 undef_int
1861 i_compose(out, src, out_left, out_top, src_left, src_top, width, height, combine = ic_normal, opacity = 0.0)
1862     Imager::ImgRaw out
1863     Imager::ImgRaw src
1864         i_img_dim out_left
1865         i_img_dim out_top
1866         i_img_dim src_left
1867         i_img_dim src_top
1868         i_img_dim width
1869         i_img_dim height
1870         int combine
1871         double opacity
1872
1873 undef_int
1874 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)
1875     Imager::ImgRaw out
1876     Imager::ImgRaw src
1877     Imager::ImgRaw mask
1878         i_img_dim out_left
1879         i_img_dim out_top
1880         i_img_dim src_left
1881         i_img_dim src_top
1882         i_img_dim mask_left
1883         i_img_dim mask_top
1884         i_img_dim width
1885         i_img_dim height
1886         int combine
1887         double opacity
1888
1889 Imager::ImgRaw
1890 i_combine(src_av, channels_av = NULL)
1891         AV *src_av
1892         AV *channels_av
1893   PREINIT:
1894         i_img **imgs = NULL;
1895         STRLEN in_count;
1896         int *channels = NULL;
1897         int i;
1898         SV **psv;
1899         IV tmp;
1900   CODE:
1901         in_count = av_len(src_av) + 1;
1902         if (in_count > 0) {
1903           imgs = mymalloc(sizeof(i_img*) * in_count);
1904           channels = mymalloc(sizeof(int) * in_count);
1905           for (i = 0; i < in_count; ++i) {
1906             psv = av_fetch(src_av, i, 0);
1907             if (!psv || !*psv || !sv_derived_from(*psv, "Imager::ImgRaw")) {
1908               myfree(imgs);
1909               myfree(channels);
1910               croak("imgs must contain only images");
1911             }
1912             tmp = SvIV((SV*)SvRV(*psv));
1913             imgs[i] = INT2PTR(i_img*, tmp);
1914             if (channels_av &&
1915                 (psv = av_fetch(channels_av, i, 0)) != NULL &&
1916                 *psv) {
1917               channels[i] = SvIV(*psv);
1918             }
1919             else {
1920               channels[i] = 0;
1921             }
1922           }
1923         }
1924         RETVAL = i_combine(imgs, channels, in_count);
1925         myfree(imgs);
1926         myfree(channels);
1927   OUTPUT:
1928         RETVAL
1929
1930 undef_int
1931 i_flipxy(im, direction)
1932     Imager::ImgRaw     im
1933                int     direction
1934
1935 Imager::ImgRaw
1936 i_rotate90(im, degrees)
1937     Imager::ImgRaw      im
1938                int      degrees
1939
1940 Imager::ImgRaw
1941 i_rotate_exact(im, amount, ...)
1942     Imager::ImgRaw      im
1943             double      amount
1944       PREINIT:
1945         i_color *backp = NULL;
1946         i_fcolor *fbackp = NULL;
1947         int i;
1948         SV * sv1;
1949       CODE:
1950         /* extract the bg colors if any */
1951         /* yes, this is kind of strange */
1952         for (i = 2; i < items; ++i) {
1953           sv1 = ST(i);
1954           if (sv_derived_from(sv1, "Imager::Color")) {
1955             IV tmp = SvIV((SV*)SvRV(sv1));
1956             backp = INT2PTR(i_color *, tmp);
1957           }
1958           else if (sv_derived_from(sv1, "Imager::Color::Float")) {
1959             IV tmp = SvIV((SV*)SvRV(sv1));
1960             fbackp = INT2PTR(i_fcolor *, tmp);
1961           }
1962         }
1963         RETVAL = i_rotate_exact_bg(im, amount, backp, fbackp);
1964       OUTPUT:
1965         RETVAL
1966
1967 Imager::ImgRaw
1968 i_matrix_transform(im, xsize, ysize, matrix_av, ...)
1969     Imager::ImgRaw      im
1970     i_img_dim      xsize
1971     i_img_dim      ysize
1972     AV *matrix_av
1973   PREINIT:
1974     double matrix[9];
1975     STRLEN len;
1976     SV *sv1;
1977     int i;
1978     i_color *backp = NULL;
1979     i_fcolor *fbackp = NULL;
1980   CODE:
1981     len=av_len(matrix_av)+1;
1982     if (len > 9)
1983       len = 9;
1984     for (i = 0; i < len; ++i) {
1985       sv1=(*(av_fetch(matrix_av,i,0)));
1986       matrix[i] = SvNV(sv1);
1987     }
1988     for (; i < 9; ++i)
1989       matrix[i] = 0;
1990     /* extract the bg colors if any */
1991     /* yes, this is kind of strange */
1992     for (i = 4; i < items; ++i) {
1993       sv1 = ST(i);
1994       if (sv_derived_from(sv1, "Imager::Color")) {
1995         IV tmp = SvIV((SV*)SvRV(sv1));
1996         backp = INT2PTR(i_color *, tmp);
1997       }
1998       else if (sv_derived_from(sv1, "Imager::Color::Float")) {
1999         IV tmp = SvIV((SV*)SvRV(sv1));
2000         fbackp = INT2PTR(i_fcolor *, tmp);
2001       }
2002     }
2003     RETVAL = i_matrix_transform_bg(im, xsize, ysize, matrix, backp, fbackp);
2004   OUTPUT:
2005     RETVAL
2006
2007 undef_int
2008 i_gaussian(im,stdev)
2009     Imager::ImgRaw     im
2010             double     stdev
2011
2012 void
2013 i_unsharp_mask(im,stdev,scale)
2014     Imager::ImgRaw     im
2015              double    stdev
2016              double    scale
2017
2018 int
2019 i_conv(im,coef)
2020         Imager::ImgRaw     im
2021         AV *coef
2022      PREINIT:
2023         double*    c_coef;
2024         int     len;
2025         SV* sv1;
2026         int i;
2027     CODE:
2028         len = av_len(coef) + 1;
2029         c_coef=mymalloc( len * sizeof(double) );
2030         for(i = 0; i  < len; i++) {
2031           sv1 = (*(av_fetch(coef, i, 0)));
2032           c_coef[i] = (double)SvNV(sv1);
2033         }
2034         RETVAL = i_conv(im, c_coef, len);
2035         myfree(c_coef);
2036     OUTPUT:
2037         RETVAL
2038
2039 Imager::ImgRaw
2040 i_convert(src, avmain)
2041     Imager::ImgRaw     src
2042     AV *avmain
2043         PREINIT:
2044           double *coeff;
2045           int outchan;
2046           int inchan;
2047           SV **temp;
2048           AV *avsub;
2049           int len;
2050           int i, j;
2051         CODE:
2052           outchan = av_len(avmain)+1;
2053           /* find the biggest */
2054           inchan = 0;
2055           for (j=0; j < outchan; ++j) {
2056             temp = av_fetch(avmain, j, 0);
2057             if (temp && SvROK(*temp) && SvTYPE(SvRV(*temp)) == SVt_PVAV) {
2058               avsub = (AV*)SvRV(*temp);
2059               len = av_len(avsub)+1;
2060               if (len > inchan)
2061                 inchan = len;
2062             }
2063             else {
2064               i_push_errorf(0, "invalid matrix: element %d is not an array ref", j);
2065               XSRETURN(0);
2066             }
2067           }
2068           coeff = mymalloc(sizeof(double) * outchan * inchan);
2069           for (j = 0; j < outchan; ++j) {
2070             avsub = (AV*)SvRV(*av_fetch(avmain, j, 0));
2071             len = av_len(avsub)+1;
2072             for (i = 0; i < len; ++i) {
2073               temp = av_fetch(avsub, i, 0);
2074               if (temp)
2075                 coeff[i+j*inchan] = SvNV(*temp);
2076               else
2077                 coeff[i+j*inchan] = 0;
2078             }
2079             while (i < inchan)
2080               coeff[i++ + j*inchan] = 0;
2081           }
2082           RETVAL = i_convert(src, coeff, outchan, inchan);
2083           myfree(coeff);
2084         OUTPUT:
2085           RETVAL
2086
2087
2088 undef_int
2089 i_map(im, pmaps_av)
2090     Imager::ImgRaw     im
2091     AV *pmaps_av
2092   PREINIT:
2093     unsigned int mask = 0;
2094     AV *avsub;
2095     SV **temp;
2096     int len;
2097     int i, j;
2098     unsigned char (*maps)[256];
2099   CODE:
2100     len = av_len(pmaps_av)+1;
2101     if (im->channels < len)
2102       len = im->channels;
2103     maps = mymalloc( len * sizeof(unsigned char [256]) );
2104     for (j=0; j<len ; j++) {
2105       temp = av_fetch(pmaps_av, j, 0);
2106       if (temp && SvROK(*temp) && (SvTYPE(SvRV(*temp)) == SVt_PVAV) ) {
2107         avsub = (AV*)SvRV(*temp);
2108         if(av_len(avsub) != 255)
2109           continue;
2110         mask |= 1<<j;
2111         for (i=0; i<256 ; i++) {
2112           int val;
2113           temp = av_fetch(avsub, i, 0);
2114           val = temp ? SvIV(*temp) : 0;
2115           if (val<0) val = 0;
2116           if (val>255) val = 255;
2117           maps[j][i] = val;
2118         }
2119       }
2120     }
2121     i_map(im, maps, mask);
2122     myfree(maps);
2123     RETVAL = 1;
2124   OUTPUT:
2125     RETVAL
2126
2127 float
2128 i_img_diff(im1,im2)
2129     Imager::ImgRaw     im1
2130     Imager::ImgRaw     im2
2131
2132 double
2133 i_img_diffd(im1,im2)
2134     Imager::ImgRaw     im1
2135     Imager::ImgRaw     im2
2136
2137 int
2138 i_img_samef(im1, im2, epsilon = i_img_epsilonf(), what=NULL)
2139     Imager::ImgRaw    im1
2140     Imager::ImgRaw    im2
2141     double epsilon
2142     const char *what
2143
2144 double
2145 i_img_epsilonf()
2146
2147 bool
2148 _is_color_object(sv)
2149         SV* sv
2150     CODE:
2151         SvGETMAGIC(sv);
2152         RETVAL = SvOK(sv) && SvROK(sv) &&
2153            (sv_derived_from(sv, "Imager::Color")
2154           || sv_derived_from(sv, "Imager::Color::Float"));
2155     OUTPUT:
2156         RETVAL
2157
2158 #ifdef HAVE_LIBTT
2159
2160
2161 Imager::Font::TT
2162 i_tt_new(fontname)
2163               char*     fontname
2164
2165
2166 MODULE = Imager         PACKAGE = Imager::Font::TT      PREFIX=TT_
2167
2168 #define TT_DESTROY(handle) i_tt_destroy(handle)
2169
2170 void
2171 TT_DESTROY(handle)
2172      Imager::Font::TT   handle
2173
2174 int
2175 TT_CLONE_SKIP(...)
2176     CODE:
2177         (void)items; /* avoid unused warning */
2178         RETVAL = 1;
2179     OUTPUT:
2180         RETVAL
2181
2182
2183 MODULE = Imager         PACKAGE = Imager
2184
2185
2186 undef_int
2187 i_tt_text(handle,im,xb,yb,cl,points,str_sv,smooth,utf8,align=1)
2188   Imager::Font::TT     handle
2189     Imager::ImgRaw     im
2190                i_img_dim     xb
2191                i_img_dim     yb
2192      Imager::Color     cl
2193              double     points
2194               SV *     str_sv
2195                int     smooth
2196                int     utf8
2197                int     align
2198              PREINIT:
2199                char *str;
2200                STRLEN len;
2201              CODE:
2202                str = SvPV(str_sv, len);
2203 #ifdef SvUTF8
2204                if (SvUTF8(str_sv))
2205                  utf8 = 1;
2206 #endif
2207                RETVAL = i_tt_text(handle, im, xb, yb, cl, points, str, 
2208                                   len, smooth, utf8, align);
2209              OUTPUT:
2210                RETVAL                
2211
2212
2213 undef_int
2214 i_tt_cp(handle,im,xb,yb,channel,points,str_sv,smooth,utf8,align=1)
2215   Imager::Font::TT     handle
2216     Imager::ImgRaw     im
2217                i_img_dim     xb
2218                i_img_dim     yb
2219                int     channel
2220              double     points
2221               SV *     str_sv
2222                int     smooth
2223                int     utf8
2224                int     align
2225              PREINIT:
2226                char *str;
2227                STRLEN len;
2228              CODE:
2229                str = SvPV(str_sv, len);
2230 #ifdef SvUTF8
2231                if (SvUTF8(str_sv))
2232                  utf8 = 1;
2233 #endif
2234                RETVAL = i_tt_cp(handle, im, xb, yb, channel, points, str, len,
2235                                 smooth, utf8, align);
2236              OUTPUT:
2237                 RETVAL
2238
2239
2240 void
2241 i_tt_bbox(handle,point,str_sv,utf8)
2242   Imager::Font::TT     handle
2243              double     point
2244                SV*    str_sv
2245                int     utf8
2246              PREINIT:
2247                i_img_dim cords[BOUNDING_BOX_COUNT];
2248                int rc;
2249                char *  str;
2250                STRLEN len;
2251                int i;
2252              PPCODE:
2253                str = SvPV(str_sv, len);
2254 #ifdef SvUTF8
2255                if (SvUTF8(ST(2)))
2256                  utf8 = 1;
2257 #endif
2258                if ((rc=i_tt_bbox(handle,point,str,len,cords, utf8))) {
2259                  EXTEND(SP, rc);
2260                  for (i = 0; i < rc; ++i) {
2261                    PUSHs(sv_2mortal(newSViv(cords[i])));
2262                  }
2263                }
2264
2265 void
2266 i_tt_has_chars(handle, text_sv, utf8)
2267         Imager::Font::TT handle
2268         SV  *text_sv
2269         int utf8
2270       PREINIT:
2271         char const *text;
2272         STRLEN len;
2273         char *work;
2274         size_t count;
2275         size_t i;
2276       PPCODE:
2277         i_clear_error();
2278         text = SvPV(text_sv, len);
2279 #ifdef SvUTF8
2280         if (SvUTF8(text_sv))
2281           utf8 = 1;
2282 #endif
2283         work = mymalloc(len);
2284         count = i_tt_has_chars(handle, text, len, utf8, work);
2285         if (GIMME_V == G_ARRAY) {
2286           EXTEND(SP, count);
2287           for (i = 0; i < count; ++i) {
2288             PUSHs(boolSV(work[i]));
2289           }
2290         }
2291         else {
2292           EXTEND(SP, 1);
2293           PUSHs(sv_2mortal(newSVpv(work, count)));
2294         }
2295         myfree(work);
2296
2297 void
2298 i_tt_dump_names(handle)
2299         Imager::Font::TT handle
2300
2301 void
2302 i_tt_face_name(handle)
2303         Imager::Font::TT handle
2304       PREINIT:
2305         char name[255];
2306         size_t len;
2307       PPCODE:
2308         len = i_tt_face_name(handle, name, sizeof(name));
2309         if (len) {
2310           EXTEND(SP, 1);
2311           PUSHs(sv_2mortal(newSVpv(name, len-1)));
2312         }
2313
2314 void
2315 i_tt_glyph_name(handle, text_sv, utf8 = 0)
2316         Imager::Font::TT handle
2317         SV *text_sv
2318         int utf8
2319       PREINIT:
2320         char const *text;
2321         STRLEN work_len;
2322         size_t len;
2323         size_t outsize;
2324         char name[255];
2325         SSize_t count = 0;
2326       PPCODE:
2327         i_clear_error();
2328         text = SvPV(text_sv, work_len);
2329 #ifdef SvUTF8
2330         if (SvUTF8(text_sv))
2331           utf8 = 1;
2332 #endif
2333         len = work_len;
2334         while (len) {
2335           unsigned long ch;
2336           if (utf8) {
2337             ch = i_utf8_advance(&text, &len);
2338             if (ch == ~0UL) {
2339               i_push_error(0, "invalid UTF8 character");
2340               XSRETURN_EMPTY;
2341             }
2342           }
2343           else {
2344             ch = *text++;
2345             --len;
2346           }
2347           EXTEND(SP, count+1);
2348           if ((outsize = i_tt_glyph_name(handle, ch, name, sizeof(name))) != 0) {
2349             ST(count) = sv_2mortal(newSVpv(name, 0));
2350           }
2351           else {
2352             ST(count) = &PL_sv_undef;
2353           }
2354           ++count;
2355         }
2356         XSRETURN(count);
2357
2358 #endif 
2359
2360 const char *
2361 i_test_format_probe(ig, length)
2362         Imager::IO     ig
2363                int     length
2364
2365 Imager::ImgRaw
2366 i_readpnm_wiol(ig, allow_incomplete)
2367         Imager::IO     ig
2368                int     allow_incomplete
2369
2370
2371 void
2372 i_readpnm_multi_wiol(ig, allow_incomplete)
2373         Imager::IO ig
2374                int     allow_incomplete
2375       PREINIT:
2376         i_img **imgs;
2377         int count=0;
2378         int i;
2379       PPCODE:
2380         imgs = i_readpnm_multi_wiol(ig, &count, allow_incomplete);
2381         if (imgs) {
2382           EXTEND(SP, count);
2383           for (i = 0; i < count; ++i) {
2384             SV *sv = sv_newmortal();
2385             sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2386             PUSHs(sv);
2387           }
2388           myfree(imgs);
2389         }
2390
2391 undef_int
2392 i_writeppm_wiol(im, ig)
2393     Imager::ImgRaw     im
2394         Imager::IO     ig
2395
2396
2397
2398
2399
2400 Imager::ImgRaw
2401 i_readraw_wiol(ig,x,y,datachannels,storechannels,intrl)
2402         Imager::IO     ig
2403                i_img_dim     x
2404                i_img_dim     y
2405                int     datachannels
2406                int     storechannels
2407                int     intrl
2408
2409 undef_int
2410 i_writeraw_wiol(im,ig)
2411     Imager::ImgRaw     im
2412         Imager::IO     ig
2413
2414 undef_int
2415 i_writebmp_wiol(im,ig)
2416     Imager::ImgRaw     im
2417         Imager::IO     ig
2418
2419 Imager::ImgRaw
2420 i_readbmp_wiol(ig, allow_incomplete=0)
2421         Imager::IO     ig
2422         int            allow_incomplete
2423
2424
2425 undef_int
2426 i_writetga_wiol(im,ig, wierdpack, compress, idstring)
2427     Imager::ImgRaw     im
2428         Imager::IO     ig
2429                int     wierdpack
2430                int     compress
2431               char*    idstring
2432             PREINIT:
2433                 int idlen;
2434                CODE:
2435                 idlen  = SvCUR(ST(4));
2436                 RETVAL = i_writetga_wiol(im, ig, wierdpack, compress, idstring, idlen);
2437                 OUTPUT:
2438                 RETVAL
2439
2440
2441 Imager::ImgRaw
2442 i_readtga_wiol(ig, length)
2443         Imager::IO     ig
2444                int     length
2445
2446
2447
2448
2449 Imager::ImgRaw
2450 i_scaleaxis(im,Value,Axis)
2451     Imager::ImgRaw     im
2452              double     Value
2453                int     Axis
2454
2455 Imager::ImgRaw
2456 i_scale_nn(im,scx,scy)
2457     Imager::ImgRaw     im
2458              double    scx
2459              double    scy
2460
2461 Imager::ImgRaw
2462 i_scale_mixing(im, width, height)
2463     Imager::ImgRaw     im
2464                i_img_dim     width
2465                i_img_dim     height
2466
2467 Imager::ImgRaw
2468 i_haar(im)
2469     Imager::ImgRaw     im
2470
2471 int
2472 i_count_colors(im,maxc)
2473     Imager::ImgRaw     im
2474                int     maxc
2475
2476 void
2477 i_get_anonymous_color_histo(im, maxc = 0x40000000)
2478    Imager::ImgRaw  im
2479    int maxc
2480     PREINIT:
2481         int i;
2482         unsigned int * col_usage = NULL;
2483         int col_cnt;
2484     PPCODE:
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])));
2489         }
2490         myfree(col_usage);
2491         XSRETURN(col_cnt);
2492
2493
2494 void
2495 i_transform(im, opx, opy, parm)
2496     Imager::ImgRaw     im
2497     int *opx
2498     int *opy
2499     double *parm
2500              PREINIT:
2501              STRLEN size_opx, size_opy, size_parm;
2502              i_img *result;
2503              PPCODE:
2504              result=i_transform(im,opx,size_opx,opy,size_opy,parm,size_parm);
2505              if (result) {
2506                SV *result_sv = sv_newmortal();
2507                EXTEND(SP, 1);
2508                sv_setref_pv(result_sv, "Imager::ImgRaw", (void*)result);
2509                PUSHs(result_sv);
2510              }
2511
2512 void
2513 i_transform2(sv_width,sv_height,channels,sv_ops,av_n_regs,av_c_regs,av_in_imgs)
2514         SV *sv_width
2515         SV *sv_height
2516         SV *sv_ops
2517         AV *av_n_regs
2518         AV *av_c_regs
2519         AV *av_in_imgs
2520         int channels
2521              PREINIT:
2522              i_img_dim width;
2523              i_img_dim height;
2524              struct rm_op *ops;
2525              STRLEN ops_len;
2526              int ops_count;
2527              double *n_regs;
2528              int n_regs_count;
2529              i_color *c_regs;
2530              int c_regs_count;
2531              int in_imgs_count;
2532              i_img **in_imgs;
2533              SV *sv1;
2534              IV tmp;
2535              int i;
2536              i_img *result;
2537              PPCODE:
2538
2539              in_imgs_count = av_len(av_in_imgs)+1;
2540              for (i = 0; i < in_imgs_count; ++i) {
2541                sv1 = *av_fetch(av_in_imgs, i, 0);
2542                if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
2543                  croak("sv_in_img must contain only images");
2544                }
2545              }
2546              if (in_imgs_count > 0) {
2547                in_imgs = mymalloc(in_imgs_count*sizeof(i_img*));
2548                for (i = 0; i < in_imgs_count; ++i) {              
2549                  sv1 = *av_fetch(av_in_imgs,i,0);
2550                  if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
2551                    croak("Parameter 5 must contain only images");
2552                  }
2553                  tmp = SvIV((SV*)SvRV(sv1));
2554                  in_imgs[i] = INT2PTR(i_img*, tmp);
2555                }
2556              }
2557              else {
2558                /* no input images */
2559                in_imgs = NULL;
2560              }
2561              /* default the output size from the first input if possible */
2562              if (SvOK(sv_width))
2563                width = SvIV(sv_width);
2564              else if (in_imgs_count)
2565                width = in_imgs[0]->xsize;
2566              else
2567                croak("No output image width supplied");
2568
2569              if (SvOK(sv_height))
2570                height = SvIV(sv_height);
2571              else if (in_imgs_count)
2572                height = in_imgs[0]->ysize;
2573              else
2574                croak("No output image height supplied");
2575
2576              ops = (struct rm_op *)SvPV(sv_ops, ops_len);
2577              if (ops_len % sizeof(struct rm_op))
2578                  croak("Imager: Parameter 3 must be a bitmap of regops\n");
2579              ops_count = ops_len / sizeof(struct rm_op);
2580
2581              n_regs_count = av_len(av_n_regs)+1;
2582              n_regs = mymalloc(n_regs_count * sizeof(double));
2583              for (i = 0; i < n_regs_count; ++i) {
2584                sv1 = *av_fetch(av_n_regs,i,0);
2585                if (SvOK(sv1))
2586                  n_regs[i] = SvNV(sv1);
2587              }
2588              c_regs_count = av_len(av_c_regs)+1;
2589              c_regs = mymalloc(c_regs_count * sizeof(i_color));
2590              /* I don't bother initializing the colou?r registers */
2591
2592              result=i_transform2(width, height, channels, ops, ops_count, 
2593                                  n_regs, n_regs_count, 
2594                                  c_regs, c_regs_count, in_imgs, in_imgs_count);
2595              if (in_imgs)
2596                  myfree(in_imgs);
2597              myfree(n_regs);
2598              myfree(c_regs);
2599              if (result) {
2600                SV *result_sv = sv_newmortal();
2601                EXTEND(SP, 1);
2602                sv_setref_pv(result_sv, "Imager::ImgRaw", (void*)result);
2603                PUSHs(result_sv);
2604              }
2605
2606
2607 void
2608 i_contrast(im,intensity)
2609     Imager::ImgRaw     im
2610              float     intensity
2611
2612 void
2613 i_hardinvert(im)
2614     Imager::ImgRaw     im
2615
2616 void
2617 i_hardinvertall(im)
2618     Imager::ImgRaw     im
2619
2620 void
2621 i_noise(im,amount,type)
2622     Imager::ImgRaw     im
2623              float     amount
2624      unsigned char     type
2625
2626 void
2627 i_bumpmap(im,bump,channel,light_x,light_y,strength)
2628     Imager::ImgRaw     im
2629     Imager::ImgRaw     bump
2630                int     channel
2631          i_img_dim     light_x
2632          i_img_dim     light_y
2633          i_img_dim     strength
2634
2635
2636 void
2637 i_bumpmap_complex(im,bump,channel,tx,ty,Lx,Ly,Lz,cd,cs,n,Ia,Il,Is)
2638     Imager::ImgRaw     im
2639     Imager::ImgRaw     bump
2640                int     channel
2641                i_img_dim     tx
2642                i_img_dim     ty
2643              double     Lx
2644              double     Ly
2645              double     Lz
2646              float     cd
2647              float     cs
2648              float     n
2649      Imager::Color     Ia
2650      Imager::Color     Il
2651      Imager::Color     Is
2652
2653
2654
2655 void
2656 i_postlevels(im,levels)
2657     Imager::ImgRaw     im
2658              int       levels
2659
2660 void
2661 i_mosaic(im,size)
2662     Imager::ImgRaw     im
2663          i_img_dim     size
2664
2665 void
2666 i_watermark(im,wmark,tx,ty,pixdiff)
2667     Imager::ImgRaw     im
2668     Imager::ImgRaw     wmark
2669                i_img_dim     tx
2670                i_img_dim     ty
2671                int     pixdiff
2672
2673
2674 void
2675 i_autolevels(im,lsat,usat,skew)
2676     Imager::ImgRaw     im
2677              float     lsat
2678              float     usat
2679              float     skew
2680
2681 void
2682 i_radnoise(im,xo,yo,rscale,ascale)
2683     Imager::ImgRaw     im
2684              float     xo
2685              float     yo
2686              float     rscale
2687              float     ascale
2688
2689 void
2690 i_turbnoise(im, xo, yo, scale)
2691     Imager::ImgRaw     im
2692              float     xo
2693              float     yo
2694              float     scale
2695
2696
2697 void
2698 i_gradgen(im, xo, yo, ac, dmeasure)
2699     Imager::ImgRaw     im
2700     i_img_dim *xo
2701     i_img_dim *yo
2702     i_color *ac
2703     int dmeasure
2704       PREINIT:
2705         STRLEN size_xo;
2706         STRLEN size_yo;
2707         STRLEN size_ac;
2708       CODE:
2709         if (size_xo != size_yo || size_xo != size_ac)
2710           croak("i_gradgen: x, y and color arrays must be the same size");
2711         if (size_xo < 2)
2712           croak("Usage: i_gradgen array refs must have more than 1 entry each");
2713         i_gradgen(im, size_xo, xo, yo, ac, dmeasure);
2714
2715 Imager::ImgRaw
2716 i_diff_image(im, im2, mindist=0)
2717     Imager::ImgRaw     im
2718     Imager::ImgRaw     im2
2719             double     mindist
2720
2721 undef_int
2722 i_fountain(im, xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
2723     Imager::ImgRaw     im
2724             double     xa
2725             double     ya
2726             double     xb
2727             double     yb
2728                int     type
2729                int     repeat
2730                int     combine
2731                int     super_sample
2732             double     ssample_param
2733       PREINIT:
2734         AV *asegs;
2735         int count;
2736         i_fountain_seg *segs;
2737       CODE:
2738         if (!SvROK(ST(10)) || ! SvTYPE(SvRV(ST(10))))
2739             croak("i_fountain: argument 11 must be an array ref");
2740         
2741         asegs = (AV *)SvRV(ST(10));
2742         segs = load_fount_segs(aTHX_ asegs, &count);
2743         RETVAL = i_fountain(im, xa, ya, xb, yb, type, repeat, combine, 
2744                             super_sample, ssample_param, count, segs);
2745         myfree(segs);
2746       OUTPUT:
2747         RETVAL
2748
2749 Imager::FillHandle
2750 i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
2751             double     xa
2752             double     ya
2753             double     xb
2754             double     yb
2755                int     type
2756                int     repeat
2757                int     combine
2758                int     super_sample
2759             double     ssample_param
2760       PREINIT:
2761         AV *asegs;
2762         int count;
2763         i_fountain_seg *segs;
2764       CODE:
2765         if (!SvROK(ST(9)) || ! SvTYPE(SvRV(ST(9))))
2766             croak("i_fountain: argument 11 must be an array ref");
2767         
2768         asegs = (AV *)SvRV(ST(9));
2769         segs = load_fount_segs(aTHX_ asegs, &count);
2770         RETVAL = i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine, 
2771                                   super_sample, ssample_param, count, segs);
2772         myfree(segs);        
2773       OUTPUT:
2774         RETVAL
2775
2776 Imager::FillHandle
2777 i_new_fill_opacity(other_fill, alpha_mult)
2778     Imager::FillHandle other_fill
2779     double alpha_mult
2780
2781 void
2782 i_errors()
2783       PREINIT:
2784         i_errmsg *errors;
2785         int i;
2786         AV *av;
2787         SV *sv;
2788       PPCODE:
2789         errors = i_errors();
2790         i = 0;
2791         while (errors[i].msg) {
2792           av = newAV();
2793           sv = newSVpv(errors[i].msg, strlen(errors[i].msg));
2794           if (!av_store(av, 0, sv)) {
2795             SvREFCNT_dec(sv);
2796           }
2797           sv = newSViv(errors[i].code);
2798           if (!av_store(av, 1, sv)) {
2799             SvREFCNT_dec(sv);
2800           }
2801           PUSHs(sv_2mortal(newRV_noinc((SV*)av)));
2802           ++i;
2803         }
2804
2805 void
2806 i_clear_error()
2807
2808 void
2809 i_push_error(code, msg)
2810         int code
2811         const char *msg
2812
2813 undef_int
2814 i_nearest_color(im, ...)
2815     Imager::ImgRaw     im
2816       PREINIT:
2817         int num;
2818         i_img_dim *xo;
2819         i_img_dim *yo;
2820         i_color *ival;
2821         int dmeasure;
2822         int i;
2823         SV *sv;
2824         AV *axx;
2825         AV *ayy;
2826         AV *ac;
2827       CODE:
2828         if (items != 5)
2829             croak("Usage: i_nearest_color(im, xo, yo, ival, dmeasure)");
2830         if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2831             croak("i_nearest_color: Second argument must be an array ref");
2832         if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
2833             croak("i_nearest_color: Third argument must be an array ref");
2834         if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
2835             croak("i_nearest_color: Fourth argument must be an array ref");
2836         axx = (AV *)SvRV(ST(1));
2837         ayy = (AV *)SvRV(ST(2));
2838         ac  = (AV *)SvRV(ST(3));
2839         dmeasure = (int)SvIV(ST(4));
2840         
2841         num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
2842         num = num <= av_len(ac) ? num : av_len(ac);
2843         num++; 
2844         if (num < 2) croak("Usage: i_nearest_color array refs must have more than 1 entry each");
2845         xo = mymalloc( sizeof(i_img_dim) * num );
2846         yo = mymalloc( sizeof(i_img_dim) * num );
2847         ival = mymalloc( sizeof(i_color) * num );
2848         for(i = 0; i<num; i++) {
2849           xo[i]   = (i_img_dim)SvIV(* av_fetch(axx, i, 0));
2850           yo[i]   = (i_img_dim)SvIV(* av_fetch(ayy, i, 0));
2851           sv = *av_fetch(ac, i, 0);
2852           if ( !sv_derived_from(sv, "Imager::Color") ) {
2853             free(axx); free(ayy); free(ac);
2854             croak("i_nearest_color: Element of fourth argument is not derived from Imager::Color");
2855           }
2856           ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
2857         }
2858         RETVAL = i_nearest_color(im, num, xo, yo, ival, dmeasure);
2859       OUTPUT:
2860         RETVAL
2861
2862 void
2863 malloc_state()
2864
2865 void
2866 DSO_open(filename)
2867              char*       filename
2868              PREINIT:
2869                void *rc;
2870                char *evstr;
2871              PPCODE:
2872                rc=DSO_open(filename,&evstr);
2873                if (rc!=NULL) {
2874                  if (evstr!=NULL) {
2875                    EXTEND(SP,2); 
2876                    PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
2877                    PUSHs(sv_2mortal(newSVpvn(evstr, strlen(evstr))));
2878                  } else {
2879                    EXTEND(SP,1);
2880                    PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
2881                  }
2882                }
2883
2884
2885 undef_int
2886 DSO_close(dso_handle)
2887              void*       dso_handle
2888
2889 void
2890 DSO_funclist(dso_handle_v)
2891              void*       dso_handle_v
2892              PREINIT:
2893                int i;
2894                DSO_handle *dso_handle;
2895                func_ptr *functions;
2896              PPCODE:
2897                dso_handle=(DSO_handle*)dso_handle_v;
2898                functions = DSO_funclist(dso_handle);
2899                i=0;
2900                while( functions[i].name != NULL) {
2901                  EXTEND(SP,1);
2902                  PUSHs(sv_2mortal(newSVpv(functions[i].name,0)));
2903                  EXTEND(SP,1);
2904                  PUSHs(sv_2mortal(newSVpv(functions[i++].pcode,0)));
2905                }
2906
2907 void
2908 DSO_call(handle,func_index,hv)
2909                void*  handle
2910                int    func_index
2911                HV *hv
2912              PPCODE:
2913                DSO_call( (DSO_handle *)handle,func_index,hv);
2914
2915 Imager::Color
2916 i_get_pixel(im, x, y)
2917         Imager::ImgRaw im
2918         i_img_dim x
2919         i_img_dim y;
2920       CODE:
2921         RETVAL = (i_color *)mymalloc(sizeof(i_color));
2922         if (i_gpix(im, x, y, RETVAL) != 0) {
2923           myfree(RETVAL);
2924           XSRETURN_UNDEF;
2925         }
2926       OUTPUT:
2927         RETVAL
2928         
2929
2930 int
2931 i_ppix(im, x, y, cl)
2932         Imager::ImgRaw im
2933         i_img_dim x
2934         i_img_dim y
2935         Imager::Color cl
2936
2937 Imager::ImgRaw
2938 i_img_pal_new(x, y, channels, maxpal)
2939         i_img_dim x
2940         i_img_dim y
2941         int     channels
2942         int     maxpal
2943
2944 Imager::ImgRaw
2945 i_img_to_pal(src, quant)
2946         Imager::ImgRaw src
2947       PREINIT:
2948         HV *hv;
2949         i_quantize quant;
2950       CODE:
2951         if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2952           croak("i_img_to_pal: second argument must be a hash ref");
2953         hv = (HV *)SvRV(ST(1));
2954         memset(&quant, 0, sizeof(quant));
2955         quant.version = 1;
2956         quant.mc_size = 256;
2957         ip_handle_quant_opts(aTHX_ &quant, hv);
2958         RETVAL = i_img_to_pal(src, &quant);
2959         if (RETVAL) {
2960           ip_copy_colors_back(aTHX_ hv, &quant);
2961         }
2962         ip_cleanup_quant_opts(aTHX_ &quant);
2963       OUTPUT:
2964         RETVAL
2965
2966 Imager::ImgRaw
2967 i_img_to_rgb(src)
2968         Imager::ImgRaw src
2969
2970 void
2971 i_img_make_palette(HV *quant_hv, ...)
2972       PREINIT:
2973         size_t count = items - 1;
2974         i_quantize quant;
2975         i_img **imgs = NULL;
2976         ssize_t i;
2977       PPCODE:
2978         if (count <= 0)
2979           croak("Please supply at least one image (%d)", (int)count);
2980         imgs = mymalloc(sizeof(i_img *) * count);
2981         for (i = 0; i < count; ++i) {
2982           SV *img_sv = ST(i + 1);
2983           if (SvROK(img_sv) && sv_derived_from(img_sv, "Imager::ImgRaw")) {
2984             imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(img_sv)));
2985           }
2986           else {
2987             myfree(imgs);
2988             croak("Image %d is not an image object", (int)i+1);
2989           }
2990         }
2991         memset(&quant, 0, sizeof(quant));
2992         quant.version = 1;
2993         quant.mc_size = 256;
2994         ip_handle_quant_opts(aTHX_ &quant, quant_hv);
2995         i_quant_makemap(&quant, imgs, count);
2996         EXTEND(SP, quant.mc_count);
2997         for (i = 0; i < quant.mc_count; ++i) {
2998           SV *sv_c = make_i_color_sv(aTHX_ quant.mc_colors + i);
2999           PUSHs(sv_c);
3000         }
3001         ip_cleanup_quant_opts(aTHX_ &quant);
3002         
3003
3004 void
3005 i_gpal(im, l, r, y)
3006         Imager::ImgRaw  im
3007         i_img_dim     l
3008         i_img_dim     r
3009         i_img_dim     y
3010       PREINIT:
3011         i_palidx *work;
3012         int count, i;
3013       PPCODE:
3014         if (l < r) {
3015           work = mymalloc((r-l) * sizeof(i_palidx));
3016           count = i_gpal(im, l, r, y, work);
3017           if (GIMME_V == G_ARRAY) {
3018             EXTEND(SP, count);
3019             for (i = 0; i < count; ++i) {
3020               PUSHs(sv_2mortal(newSViv(work[i])));
3021             }
3022           }
3023           else {
3024             EXTEND(SP, 1);
3025             PUSHs(sv_2mortal(newSVpv((char *)work, count * sizeof(i_palidx))));
3026           }
3027           myfree(work);
3028         }
3029         else {
3030           if (GIMME_V != G_ARRAY) {
3031             EXTEND(SP, 1);
3032             PUSHs(&PL_sv_undef);
3033           }
3034         }
3035
3036 int
3037 i_ppal(im, l, y, ...)
3038         Imager::ImgRaw  im
3039         i_img_dim     l
3040         i_img_dim     y
3041       PREINIT:
3042         i_palidx *work;
3043         i_img_dim i;
3044       CODE:
3045         if (items > 3) {
3046           work = malloc_temp(aTHX_ sizeof(i_palidx) * (items-3));
3047           for (i=0; i < items-3; ++i) {
3048             work[i] = SvIV(ST(i+3));
3049           }
3050           validate_i_ppal(im, work, items - 3);
3051           RETVAL = i_ppal(im, l, l+items-3, y, work);
3052         }
3053         else {
3054           RETVAL = 0;
3055         }
3056       OUTPUT:
3057         RETVAL
3058
3059 int
3060 i_ppal_p(im, l, y, data)
3061         Imager::ImgRaw  im
3062         i_img_dim     l
3063         i_img_dim     y
3064         SV *data
3065       PREINIT:
3066         i_palidx const *work;
3067         STRLEN len;
3068       CODE:
3069         work = (i_palidx const *)SvPV(data, len);
3070         len /= sizeof(i_palidx);
3071         if (len > 0) {
3072           validate_i_ppal(im, work, len);
3073           RETVAL = i_ppal(im, l, l+len, y, work);
3074         }
3075         else {
3076           RETVAL = 0;
3077         }
3078       OUTPUT:
3079         RETVAL
3080
3081 SysRet
3082 i_addcolors(im, ...)
3083         Imager::ImgRaw  im
3084       PREINIT:
3085         i_color *colors;
3086         int i;
3087       CODE:
3088         if (items < 2)
3089           croak("i_addcolors: no colors to add");
3090         colors = mymalloc((items-1) * sizeof(i_color));
3091         for (i=0; i < items-1; ++i) {
3092           if (sv_isobject(ST(i+1)) 
3093               && sv_derived_from(ST(i+1), "Imager::Color")) {
3094             IV tmp = SvIV((SV *)SvRV(ST(i+1)));
3095             colors[i] = *INT2PTR(i_color *, tmp);
3096           }
3097           else {
3098             myfree(colors);
3099             croak("i_addcolor: pixels must be Imager::Color objects");
3100           }
3101         }
3102         RETVAL = i_addcolors(im, colors, items-1);
3103       OUTPUT:
3104         RETVAL
3105
3106 undef_int 
3107 i_setcolors(im, index, ...)
3108         Imager::ImgRaw  im
3109         int index
3110       PREINIT:
3111         i_color *colors;
3112         int i;
3113       CODE:
3114         if (items < 3)
3115           croak("i_setcolors: no colors to add");
3116         colors = mymalloc((items-2) * sizeof(i_color));
3117         for (i=0; i < items-2; ++i) {
3118           if (sv_isobject(ST(i+2)) 
3119               && sv_derived_from(ST(i+2), "Imager::Color")) {
3120             IV tmp = SvIV((SV *)SvRV(ST(i+2)));
3121             colors[i] = *INT2PTR(i_color *, tmp);
3122           }
3123           else {
3124             myfree(colors);
3125             croak("i_setcolors: pixels must be Imager::Color objects");
3126           }
3127         }
3128         RETVAL = i_setcolors(im, index, colors, items-2);
3129         myfree(colors);
3130       OUTPUT:
3131         RETVAL
3132
3133 void
3134 i_getcolors(im, index, count=1)
3135         Imager::ImgRaw im
3136         int index
3137         int count
3138       PREINIT:
3139         i_color *colors;
3140         int i;
3141       PPCODE:
3142         if (count < 1)
3143           croak("i_getcolors: count must be positive");
3144         colors = malloc_temp(aTHX_ sizeof(i_color) * count);
3145         if (i_getcolors(im, index, colors, count)) {
3146           EXTEND(SP, count);
3147           for (i = 0; i < count; ++i) {
3148             SV *sv = make_i_color_sv(aTHX_ colors+i);
3149             PUSHs(sv);
3150           }
3151         }
3152
3153 undef_neg_int
3154 i_colorcount(im)
3155         Imager::ImgRaw im
3156
3157 undef_neg_int
3158 i_maxcolors(im)
3159         Imager::ImgRaw im
3160
3161 i_palidx
3162 i_findcolor(im, color)
3163         Imager::ImgRaw im
3164         Imager::Color color
3165       CODE:
3166         if (!i_findcolor(im, color, &RETVAL)) {
3167           XSRETURN_UNDEF;
3168         }
3169       OUTPUT:
3170         RETVAL
3171
3172 int
3173 i_img_bits(im)
3174         Imager::ImgRaw  im
3175
3176 int
3177 i_img_type(im)
3178         Imager::ImgRaw  im
3179
3180 int
3181 i_img_virtual(im)
3182         Imager::ImgRaw  im
3183
3184 void
3185 i_gsamp(im, l, r, y, channels)
3186         Imager::ImgRaw im
3187         i_img_dim l
3188         i_img_dim r
3189         i_img_dim y
3190         i_channel_list channels
3191       PREINIT:
3192         i_sample_t *data;
3193         i_img_dim count, i;
3194       PPCODE:
3195         if (l < r) {
3196           data = mymalloc(sizeof(i_sample_t) * (r-l) * channels.count);
3197           count = i_gsamp(im, l, r, y, data, channels.channels, channels.count);
3198           if (GIMME_V == G_ARRAY) {
3199             EXTEND(SP, count);
3200             for (i = 0; i < count; ++i)
3201               PUSHs(sv_2mortal(newSViv(data[i])));
3202           }
3203           else {
3204             EXTEND(SP, 1);
3205             PUSHs(sv_2mortal(newSVpv((char *)data, count * sizeof(i_sample_t))));
3206           }
3207           myfree(data);
3208         }
3209         else {
3210           if (GIMME_V != G_ARRAY) {
3211             XSRETURN_UNDEF;
3212           }
3213         }
3214
3215 undef_neg_int
3216 i_gsamp_bits(im, l, r, y, bits, target, offset, channels)
3217         Imager::ImgRaw im
3218         i_img_dim l
3219         i_img_dim r
3220         i_img_dim y
3221         int bits
3222         AV *target
3223         STRLEN offset
3224         i_channel_list channels
3225       PREINIT:
3226         unsigned *data;
3227         i_img_dim count, i;
3228       CODE:
3229         i_clear_error();
3230         if (items < 8)
3231           croak("No channel numbers supplied to g_samp()");
3232         if (l < r) {
3233           data = mymalloc(sizeof(unsigned) * (r-l) * channels.count);
3234           count = i_gsamp_bits(im, l, r, y, data, channels.channels, channels.count, bits);
3235           for (i = 0; i < count; ++i) {
3236             av_store(target, i+offset, newSVuv(data[i]));
3237           }
3238           myfree(data);
3239           RETVAL = count;
3240         }
3241         else {
3242           RETVAL = 0;
3243         }
3244       OUTPUT:
3245         RETVAL
3246
3247 undef_neg_int
3248 i_psamp_bits(im, l, y, bits, channels, data_av, data_offset = 0, pixel_count = -1)
3249         Imager::ImgRaw im
3250         i_img_dim l
3251         i_img_dim y
3252         int bits
3253         i_channel_list channels
3254         AV *data_av
3255         i_img_dim data_offset
3256         i_img_dim pixel_count
3257       PREINIT:
3258         STRLEN data_count;
3259         size_t data_used;
3260         unsigned *data;
3261         ptrdiff_t i;
3262       CODE:
3263         i_clear_error();
3264
3265         data_count = av_len(data_av) + 1;
3266         if (data_offset < 0) {
3267           croak("data_offset must be non-negative");
3268         }
3269         if (data_offset > data_count) {
3270           croak("data_offset greater than number of samples supplied");
3271         }
3272         if (pixel_count == -1 || 
3273             data_offset + pixel_count * channels.count > data_count) {
3274           pixel_count = (data_count - data_offset) / channels.count;
3275         }
3276
3277         data_used = pixel_count * channels.count;
3278         data = mymalloc(sizeof(unsigned) * data_count);
3279         for (i = 0; i < data_used; ++i)
3280           data[i] = SvUV(*av_fetch(data_av, data_offset + i, 0));
3281
3282         RETVAL = i_psamp_bits(im, l, l + pixel_count, y, data, channels.channels, 
3283                               channels.count, bits);
3284
3285         if (data)
3286           myfree(data);
3287       OUTPUT:
3288         RETVAL
3289
3290 undef_neg_int
3291 i_psamp(im, x, y, channels, data, offset = 0, width = -1)
3292         Imager::ImgRaw im
3293         i_img_dim x
3294         i_img_dim y
3295         i_channel_list channels
3296         i_sample_list data
3297         i_img_dim offset
3298         i_img_dim width
3299     PREINIT:
3300         i_img_dim r;
3301     CODE:
3302         i_clear_error();
3303         if (offset < 0) {
3304           i_push_error(0, "offset must be non-negative");
3305           XSRETURN_UNDEF;
3306         }
3307         if (offset > 0) {
3308           if (offset > data.count) {
3309             i_push_error(0, "offset greater than number of samples supplied");
3310             XSRETURN_UNDEF;
3311           }
3312           data.samples += offset;
3313           data.count -= offset;
3314         }
3315         if (width == -1 ||
3316             width * channels.count > data.count) {
3317           width = data.count / channels.count;
3318         }
3319         r = x + width;
3320         RETVAL = i_psamp(im, x, r, y, data.samples, channels.channels, channels.count);
3321     OUTPUT:
3322         RETVAL
3323
3324 undef_neg_int
3325 i_psampf(im, x, y, channels, data, offset = 0, width = -1)
3326         Imager::ImgRaw im
3327         i_img_dim x
3328         i_img_dim y
3329         i_channel_list channels
3330         i_fsample_list data
3331         i_img_dim offset
3332         i_img_dim width
3333     PREINIT:
3334         i_img_dim r;
3335     CODE:
3336         i_clear_error();
3337         if (offset < 0) {
3338           i_push_error(0, "offset must be non-negative");
3339           XSRETURN_UNDEF;
3340         }
3341         if (offset > 0) {
3342           if (offset > data.count) {
3343             i_push_error(0, "offset greater than number of samples supplied");
3344             XSRETURN_UNDEF;
3345           }
3346           data.samples += offset;
3347           data.count -= offset;
3348         }
3349         if (width == -1 ||
3350             width * channels.count > data.count) {
3351           width = data.count / channels.count;
3352         }
3353         r = x + width;
3354         RETVAL = i_psampf(im, x, r, y, data.samples, channels.channels, channels.count);
3355     OUTPUT:
3356         RETVAL
3357
3358 Imager::ImgRaw
3359 i_img_masked_new(targ, mask, x, y, w, h)
3360         Imager::ImgRaw targ
3361         i_img_dim x
3362         i_img_dim y
3363         i_img_dim w
3364         i_img_dim h
3365       PREINIT:
3366         i_img *mask;
3367       CODE:
3368         if (SvOK(ST(1))) {
3369           if (!sv_isobject(ST(1)) 
3370               || !sv_derived_from(ST(1), "Imager::ImgRaw")) {
3371             croak("i_img_masked_new: parameter 2 must undef or an image");
3372           }
3373           mask = INT2PTR(i_img *, SvIV((SV *)SvRV(ST(1))));
3374         }
3375         else
3376           mask = NULL;
3377         RETVAL = i_img_masked_new(targ, mask, x, y, w, h);
3378       OUTPUT:
3379         RETVAL
3380
3381 int
3382 i_plin(im, l, y, ...)
3383         Imager::ImgRaw  im
3384         i_img_dim     l
3385         i_img_dim     y
3386       PREINIT:
3387         i_color *work;
3388         STRLEN i;
3389         STRLEN len;
3390         size_t count;
3391       CODE:
3392         if (items > 3) {
3393           if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3394             /* supplied as a byte string */
3395             work = (i_color *)SvPV(ST(3), len);
3396             count = len / sizeof(i_color);
3397             if (count * sizeof(i_color) != len) {
3398               croak("i_plin: length of scalar argument must be multiple of sizeof i_color");
3399             }
3400             RETVAL = i_plin(im, l, l+count, y, work);
3401           }
3402           else {
3403             work = mymalloc(sizeof(i_color) * (items-3));
3404             for (i=0; i < items-3; ++i) {
3405               if (sv_isobject(ST(i+3)) 
3406                   && sv_derived_from(ST(i+3), "Imager::Color")) {
3407                 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3408                 work[i] = *INT2PTR(i_color *, tmp);
3409               }
3410               else {
3411                 myfree(work);
3412                 croak("i_plin: pixels must be Imager::Color objects");
3413               }
3414             }
3415             RETVAL = i_plin(im, l, l+items-3, y, work);
3416             myfree(work);
3417           }
3418         }
3419         else {
3420           RETVAL = 0;
3421         }
3422       OUTPUT:
3423         RETVAL
3424
3425 int
3426 i_ppixf(im, x, y, cl)
3427         Imager::ImgRaw im
3428         i_img_dim x
3429         i_img_dim y
3430         Imager::Color::Float cl
3431
3432 void
3433 i_gsampf(im, l, r, y, channels)
3434         Imager::ImgRaw im
3435         i_img_dim l
3436         i_img_dim r
3437         i_img_dim y
3438         i_channel_list channels
3439       PREINIT:
3440         i_fsample_t *data;
3441         i_img_dim count, i;
3442       PPCODE:
3443         if (l < r) {
3444           data = mymalloc(sizeof(i_fsample_t) * (r-l) * channels.count);
3445           count = i_gsampf(im, l, r, y, data, channels.channels, channels.count);
3446           if (GIMME_V == G_ARRAY) {
3447             EXTEND(SP, count);
3448             for (i = 0; i < count; ++i)
3449               PUSHs(sv_2mortal(newSVnv(data[i])));
3450           }
3451           else {
3452             EXTEND(SP, 1);
3453             PUSHs(sv_2mortal(newSVpv((void *)data, count * sizeof(i_fsample_t))));
3454           }
3455           myfree(data);
3456         }
3457         else {
3458           if (GIMME_V != G_ARRAY) {
3459             XSRETURN_UNDEF;
3460           }
3461         }
3462
3463 int
3464 i_plinf(im, l, y, ...)
3465         Imager::ImgRaw  im
3466         i_img_dim     l
3467         i_img_dim     y
3468       PREINIT:
3469         i_fcolor *work;
3470         i_img_dim i;
3471         STRLEN len;
3472         size_t count;
3473       CODE:
3474         if (items > 3) {
3475           if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3476             /* supplied as a byte string */
3477             work = (i_fcolor *)SvPV(ST(3), len);
3478             count = len / sizeof(i_fcolor);
3479             if (count * sizeof(i_fcolor) != len) {
3480               croak("i_plin: length of scalar argument must be multiple of sizeof i_fcolor");
3481             }
3482             RETVAL = i_plinf(im, l, l+count, y, work);
3483           }
3484           else {
3485             work = mymalloc(sizeof(i_fcolor) * (items-3));
3486             for (i=0; i < items-3; ++i) {
3487               if (sv_isobject(ST(i+3)) 
3488                   && sv_derived_from(ST(i+3), "Imager::Color::Float")) {
3489                 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3490                 work[i] = *INT2PTR(i_fcolor *, tmp);
3491               }
3492               else {
3493                 myfree(work);
3494                 croak("i_plinf: pixels must be Imager::Color::Float objects");
3495               }
3496             }
3497             /**(char *)0 = 1;*/
3498             RETVAL = i_plinf(im, l, l+items-3, y, work);
3499             myfree(work);
3500           }
3501         }
3502         else {
3503           RETVAL = 0;
3504         }
3505       OUTPUT:
3506         RETVAL
3507
3508 Imager::Color::Float
3509 i_gpixf(im, x, y)
3510         Imager::ImgRaw im
3511         i_img_dim x
3512         i_img_dim y;
3513       CODE:
3514         RETVAL = (i_fcolor *)mymalloc(sizeof(i_fcolor));
3515         if (i_gpixf(im, x, y, RETVAL) != 0) {
3516           myfree(RETVAL);
3517           XSRETURN_UNDEF;
3518         }
3519       OUTPUT:
3520         RETVAL
3521
3522 void
3523 i_glin(im, l, r, y)
3524         Imager::ImgRaw im
3525         i_img_dim l
3526         i_img_dim r
3527         i_img_dim y
3528       PREINIT:
3529         i_color *vals;
3530         i_img_dim count, i;
3531       PPCODE:
3532         if (l < r) {
3533           vals = mymalloc((r-l) * sizeof(i_color));
3534           memset(vals, 0, (r-l) * sizeof(i_color));
3535           count = i_glin(im, l, r, y, vals);
3536           if (GIMME_V == G_ARRAY) {
3537             EXTEND(SP, count);
3538             for (i = 0; i < count; ++i) {
3539               SV *sv = make_i_color_sv(aTHX_ vals+i);
3540               PUSHs(sv);
3541             }
3542           }
3543           else if (count) {
3544             EXTEND(SP, 1);
3545             PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_color))));
3546           }
3547           myfree(vals);
3548         }
3549
3550 void
3551 i_glinf(im, l, r, y)
3552         Imager::ImgRaw im
3553         i_img_dim l
3554         i_img_dim r
3555         i_img_dim y
3556       PREINIT:
3557         i_fcolor *vals;
3558         i_img_dim count, i;
3559         i_fcolor zero;
3560       PPCODE:
3561         for (i = 0; i < MAXCHANNELS; ++i)
3562           zero.channel[i] = 0;
3563         if (l < r) {
3564           vals = mymalloc((r-l) * sizeof(i_fcolor));
3565           for (i = 0; i < r-l; ++i)
3566             vals[i] = zero;
3567           count = i_glinf(im, l, r, y, vals);
3568           if (GIMME_V == G_ARRAY) {
3569             EXTEND(SP, count);
3570             for (i = 0; i < count; ++i) {
3571               SV *sv;
3572               i_fcolor *col = mymalloc(sizeof(i_fcolor));
3573               *col = vals[i];
3574               sv = sv_newmortal();
3575               sv_setref_pv(sv, "Imager::Color::Float", (void *)col);
3576               PUSHs(sv);
3577             }
3578           }
3579           else if (count) {
3580             EXTEND(SP, 1);
3581             PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_fcolor))));
3582           }
3583           myfree(vals);
3584         }
3585
3586 Imager::ImgRaw
3587 i_img_8_new(x, y, ch)
3588         i_img_dim x
3589         i_img_dim y
3590         int ch
3591
3592 Imager::ImgRaw
3593 i_img_16_new(x, y, ch)
3594         i_img_dim x
3595         i_img_dim y
3596         int ch
3597
3598 Imager::ImgRaw
3599 i_img_to_rgb16(im)
3600        Imager::ImgRaw im
3601
3602 Imager::ImgRaw
3603 i_img_double_new(x, y, ch)
3604         i_img_dim x
3605         i_img_dim y
3606         int ch
3607
3608 Imager::ImgRaw
3609 i_img_to_drgb(im)
3610        Imager::ImgRaw im
3611
3612 undef_int
3613 i_tags_addn(im, name_sv, code, idata)
3614         Imager::ImgRaw im
3615         SV *name_sv
3616         int     code
3617         int     idata
3618       PREINIT:
3619         char *name;
3620         STRLEN len;
3621       CODE:
3622         SvGETMAGIC(name_sv);
3623         if (SvOK(name_sv))
3624           name = SvPV_nomg(name_sv, len);
3625         else
3626           name = NULL;
3627         RETVAL = i_tags_addn(&im->tags, name, code, idata);
3628       OUTPUT:
3629         RETVAL
3630
3631 undef_int
3632 i_tags_add(im, name_sv, code, data_sv, idata)
3633         Imager::ImgRaw  im
3634         SV *name_sv
3635         int code
3636         SV *data_sv
3637         int idata
3638       PREINIT:
3639         char *name;
3640         char *data;
3641         STRLEN len;
3642       CODE:
3643         SvGETMAGIC(name_sv);
3644         if (SvOK(name_sv))
3645           name = SvPV_nomg(name_sv, len);
3646         else
3647           name = NULL;
3648         SvGETMAGIC(data_sv);
3649         if (SvOK(data_sv))
3650           data = SvPV(data_sv, len);
3651         else {
3652           data = NULL;
3653           len = 0;
3654         }
3655         RETVAL = i_tags_add(&im->tags, name, code, data, len, idata);
3656       OUTPUT:
3657         RETVAL
3658
3659 SysRet
3660 i_tags_find(im, name, start)
3661         Imager::ImgRaw  im
3662         char *name
3663         int start
3664       PREINIT:
3665         int entry;
3666       CODE:
3667         if (i_tags_find(&im->tags, name, start, &entry)) {
3668           RETVAL = entry;
3669         } else {
3670           XSRETURN_UNDEF;
3671         }
3672       OUTPUT:
3673         RETVAL
3674
3675 SysRet
3676 i_tags_findn(im, code, start)
3677         Imager::ImgRaw  im
3678         int             code
3679         int             start
3680       PREINIT:
3681         int entry;
3682       CODE:
3683         if (i_tags_findn(&im->tags, code, start, &entry)) {
3684           RETVAL = entry;
3685         }
3686         else {
3687           XSRETURN_UNDEF;
3688         }
3689       OUTPUT:
3690         RETVAL
3691
3692 int
3693 i_tags_delete(im, entry)
3694         Imager::ImgRaw  im
3695         int             entry
3696       CODE:
3697         RETVAL = i_tags_delete(&im->tags, entry);
3698       OUTPUT:
3699         RETVAL
3700
3701 int
3702 i_tags_delbyname(im, name)
3703         Imager::ImgRaw  im
3704         char *          name
3705       CODE:
3706         RETVAL = i_tags_delbyname(&im->tags, name);
3707       OUTPUT:
3708         RETVAL
3709
3710 int
3711 i_tags_delbycode(im, code)
3712         Imager::ImgRaw  im
3713         int             code
3714       CODE:
3715         RETVAL = i_tags_delbycode(&im->tags, code);
3716       OUTPUT:
3717         RETVAL
3718
3719 void
3720 i_tags_get(im, index)
3721         Imager::ImgRaw  im
3722         int             index
3723       PPCODE:
3724         if (index >= 0 && index < im->tags.count) {
3725           i_img_tag *entry = im->tags.tags + index;
3726           EXTEND(SP, 5);
3727         
3728           if (entry->name) {
3729             PUSHs(sv_2mortal(newSVpv(entry->name, 0)));
3730           }
3731           else {
3732             PUSHs(sv_2mortal(newSViv(entry->code)));
3733           }
3734           if (entry->data) {
3735             PUSHs(sv_2mortal(newSVpvn(entry->data, entry->size)));
3736           }
3737           else {
3738             PUSHs(sv_2mortal(newSViv(entry->idata)));
3739           }
3740         }
3741
3742 void
3743 i_tags_get_string(im, what_sv)
3744         Imager::ImgRaw  im
3745         SV *what_sv
3746       PREINIT:
3747         char const *name = NULL;
3748         int code;
3749         char buffer[200];
3750       PPCODE:
3751         if (SvIOK(what_sv)) {
3752           code = SvIV(what_sv);
3753           name = NULL;
3754         }
3755         else {
3756           name = SvPV_nolen(what_sv);
3757           code = 0;
3758         }
3759         if (i_tags_get_string(&im->tags, name, code, buffer, sizeof(buffer))) {
3760           EXTEND(SP, 1);
3761           PUSHs(sv_2mortal(newSVpv(buffer, 0)));
3762         }
3763
3764 int
3765 i_tags_count(im)
3766         Imager::ImgRaw  im
3767       CODE:
3768         RETVAL = im->tags.count;
3769       OUTPUT:
3770         RETVAL
3771
3772
3773
3774 MODULE = Imager         PACKAGE = Imager::FillHandle PREFIX=IFILL_
3775
3776 void
3777 IFILL_DESTROY(fill)
3778         Imager::FillHandle fill
3779
3780 int
3781 IFILL_CLONE_SKIP(...)
3782     CODE:
3783         (void)items; /* avoid unused warning for XS variable */
3784         RETVAL = 1;
3785     OUTPUT:
3786         RETVAL
3787
3788 MODULE = Imager         PACKAGE = Imager
3789
3790 Imager::FillHandle
3791 i_new_fill_solid(cl, combine)
3792         Imager::Color cl
3793         int combine
3794
3795 Imager::FillHandle
3796 i_new_fill_solidf(cl, combine)
3797         Imager::Color::Float cl
3798         int combine
3799
3800 Imager::FillHandle
3801 i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch_sv, dx, dy)
3802         Imager::Color fg
3803         Imager::Color bg
3804         int combine
3805         int hatch
3806         SV *cust_hatch_sv
3807         i_img_dim dx
3808         i_img_dim dy
3809       PREINIT:
3810         unsigned char *cust_hatch;
3811         STRLEN len;
3812       CODE:
3813         SvGETMAGIC(cust_hatch_sv);
3814         if (SvOK(cust_hatch_sv)) {
3815           cust_hatch = (unsigned char *)SvPV_nomg(cust_hatch_sv, len);
3816         }
3817         else
3818           cust_hatch = NULL;
3819         RETVAL = i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy);
3820       OUTPUT:
3821         RETVAL
3822
3823 Imager::FillHandle
3824 i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch_sv, dx, dy)
3825         Imager::Color::Float fg
3826         Imager::Color::Float bg
3827         int combine
3828         int hatch
3829         SV *cust_hatch_sv
3830         i_img_dim dx
3831         i_img_dim dy
3832       PREINIT:
3833         unsigned char *cust_hatch;
3834         STRLEN len;
3835       CODE:
3836         SvGETMAGIC(cust_hatch_sv);
3837         if (SvOK(cust_hatch_sv)) {
3838           cust_hatch = (unsigned char *)SvPV(cust_hatch_sv, len);
3839         }
3840         else
3841           cust_hatch = NULL;
3842         RETVAL = i_new_fill_hatchf(fg, bg, combine, hatch, cust_hatch, dx, dy);
3843       OUTPUT:
3844         RETVAL
3845
3846 Imager::FillHandle
3847 i_new_fill_image(src, matrix_sv, xoff, yoff, combine)
3848         Imager::ImgRaw src
3849         SV *matrix_sv
3850         i_img_dim xoff
3851         i_img_dim yoff
3852         int combine
3853       PREINIT:
3854         double matrix[9];
3855         double *matrixp;
3856         AV *av;
3857         IV len;
3858         SV *sv1;
3859         int i;
3860       CODE:
3861         SvGETMAGIC(matrix_sv);
3862         if (!SvOK(matrix_sv)) {
3863           matrixp = NULL;
3864         }
3865         else {
3866           if (!SvROK(matrix_sv) || SvTYPE(SvRV(matrix_sv)) != SVt_PVAV)
3867             croak("i_new_fill_image: matrix parameter must be an arrayref or undef");
3868           av=(AV*)SvRV(matrix_sv);
3869           len=av_len(av)+1;
3870           if (len > 9)
3871             len = 9;
3872           for (i = 0; i < len; ++i) {
3873             sv1=(*(av_fetch(av,i,0)));
3874             matrix[i] = SvNV(sv1);
3875           }
3876           for (; i < 9; ++i)
3877             matrix[i] = 0;
3878           matrixp = matrix;
3879         }
3880         RETVAL = i_new_fill_image(src, matrixp, xoff, yoff, combine);
3881       OUTPUT:
3882         RETVAL
3883
3884 MODULE = Imager  PACKAGE = Imager::Internal::Hlines  PREFIX=i_int_hlines_
3885
3886 # this class is only exposed for testing
3887
3888 int
3889 i_int_hlines_testing()
3890
3891 #if i_int_hlines_testing()
3892
3893 Imager::Internal::Hlines
3894 i_int_hlines_new(start_y, count_y, start_x, count_x)
3895         i_img_dim start_y
3896         int count_y
3897         i_img_dim start_x
3898         int count_x
3899
3900 Imager::Internal::Hlines
3901 i_int_hlines_new_img(im)
3902         Imager::ImgRaw im
3903
3904 void
3905 i_int_hlines_add(hlines, y, minx, width)
3906         Imager::Internal::Hlines hlines
3907         i_img_dim y
3908         i_img_dim minx
3909         i_img_dim width
3910
3911 void
3912 i_int_hlines_DESTROY(hlines)
3913         Imager::Internal::Hlines hlines
3914
3915 SV *
3916 i_int_hlines_dump(hlines)
3917         Imager::Internal::Hlines hlines
3918
3919 int
3920 i_int_hlines_CLONE_SKIP(cls)
3921
3922 #endif
3923
3924 MODULE = Imager  PACKAGE = Imager::Context PREFIX=im_context_
3925
3926 void
3927 im_context_DESTROY(ctx)
3928    Imager::Context ctx
3929
3930 #ifdef PERL_IMPLICIT_CONTEXT
3931
3932 void
3933 im_context_CLONE(...)
3934     CODE:
3935       MY_CXT_CLONE;
3936       (void)items;
3937       /* the following sv_setref_pv() will free this inc */
3938       im_context_refinc(MY_CXT.ctx, "CLONE");
3939       MY_CXT.ctx = im_context_clone(MY_CXT.ctx, "CLONE");
3940       sv_setref_pv(get_sv("Imager::_context", GV_ADD), "Imager::Context", MY_CXT.ctx);
3941
3942 #endif
3943
3944 BOOT:
3945         PERL_SET_GLOBAL_CALLBACKS;
3946         PERL_PL_SET_GLOBAL_CALLBACKS;
3947 #ifdef PERL_IMPLICIT_CONTEXT
3948         {
3949           MY_CXT_INIT;
3950           (void)MY_CXT;
3951         }
3952 #endif
3953         start_context(aTHX);
3954         im_get_context = perl_get_context;
3955 #ifdef HAVE_LIBTT
3956         i_tt_start();
3957 #endif