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