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