955cbc2f860c197f761d73a23062fc8e8a5c7e6d
[imager.git] / Imager.xs
1 #ifdef __cplusplus
2 extern "C" {
3 #endif
4 #include "EXTERN.h"
5 #include "perl.h"
6 #include "XSUB.h"
7 #include "ppport.h"
8 #ifdef __cplusplus
9
10 #endif
11
12 #include "image.h"
13 #include "feat.h"
14 #include "dynaload.h"
15 #include "regmach.h"
16
17 typedef io_glue* Imager__IO;
18 typedef i_color* Imager__Color;
19 typedef i_fcolor* Imager__Color__Float;
20 typedef i_img*   Imager__ImgRaw;
21
22
23 #ifdef HAVE_LIBTT
24 typedef TT_Fonthandle* Imager__TTHandle;
25 #endif
26
27 #ifdef HAVE_FT2
28 typedef FT2_Fonthandle* Imager__Font__FT2;
29 #endif
30
31 typedef struct i_reader_data_tag
32 {
33   /* presumably a CODE ref or name of a sub */
34   SV *sv;
35 } i_reader_data;
36
37 /* used by functions that want callbacks */
38 static int read_callback(char *userdata, char *buffer, int need, int want) {
39   i_reader_data *rd = (i_reader_data *)userdata;
40   int count;
41   int result;
42   SV *data;
43   dSP; dTARG = sv_newmortal();
44   /* thanks to Simon Cozens for help with the dTARG above */
45
46   ENTER;
47   SAVETMPS;
48   EXTEND(SP, 2);
49   PUSHMARK(SP);
50   PUSHi(want);
51   PUSHi(need);
52   PUTBACK;
53
54   count = perl_call_sv(rd->sv, G_SCALAR);
55
56   SPAGAIN;
57
58   if (count != 1)
59     croak("Result of perl_call_sv(..., G_SCALAR) != 1");
60
61   data = POPs;
62
63   if (SvOK(data)) {
64     STRLEN len;
65     char *ptr = SvPV(data, len);
66     if (len > want)
67       croak("Too much data returned in reader callback");
68     
69     memcpy(buffer, ptr, len);
70     result = len;
71   }
72   else {
73     result = -1;
74   }
75
76   PUTBACK;
77   FREETMPS;
78   LEAVE;
79
80   return result;
81 }
82
83 typedef struct
84 {
85   SV *sv; /* a coderef or sub name */
86 } i_writer_data;
87
88 /* used by functions that want callbacks */
89 static int write_callback(char *userdata, char const *data, int size) {
90   i_writer_data *wd = (i_writer_data *)userdata;
91   int count;
92   int success;
93   SV *sv;
94   dSP; 
95
96   ENTER;
97   SAVETMPS;
98   EXTEND(SP, 1);
99   PUSHMARK(SP);
100   XPUSHs(sv_2mortal(newSVpv((char *)data, size)));
101   PUTBACK;
102
103   count = perl_call_sv(wd->sv, G_SCALAR);
104
105   SPAGAIN;
106
107   if (count != 1)
108     croak("Result of perl_call_sv(..., G_SCALAR) != 1");
109
110   sv = POPs;
111   success = SvTRUE(sv);
112
113
114   PUTBACK;
115   FREETMPS;
116   LEAVE;
117
118   return success;
119 }
120
121 struct value_name {
122   char *name;
123   int value;
124 };
125 static int lookup_name(struct value_name *names, int count, char *name, int def_value)
126 {
127   int i;
128   for (i = 0; i < count; ++i)
129     if (strEQ(names[i].name, name))
130       return names[i].value;
131
132   return def_value;
133 }
134 static struct value_name transp_names[] =
135 {
136   { "none", tr_none },
137   { "threshold", tr_threshold },
138   { "errdiff", tr_errdiff },
139   { "ordered", tr_ordered, },
140 };
141
142 static struct value_name make_color_names[] =
143 {
144   { "none", mc_none, },
145   { "webmap", mc_web_map, },
146   { "addi", mc_addi, },
147 };
148
149 static struct value_name translate_names[] =
150 {
151 #ifdef HAVE_LIBGIF
152   { "giflib", pt_giflib, },
153 #endif
154   { "closest", pt_closest, },
155   { "perturb", pt_perturb, },
156   { "errdiff", pt_errdiff, },
157 };
158
159 static struct value_name errdiff_names[] =
160 {
161   { "floyd", ed_floyd, },
162   { "jarvis", ed_jarvis, },
163   { "stucki", ed_stucki, },
164   { "custom", ed_custom, },
165 };
166
167 static struct value_name orddith_names[] =
168 {
169   { "random", od_random, },
170   { "dot8", od_dot8, },
171   { "dot4", od_dot4, },
172   { "hline", od_hline, },
173   { "vline", od_vline, },
174   { "/line", od_slashline, },
175   { "slashline", od_slashline, },
176   { "\\line", od_backline, },
177   { "backline", od_backline, },
178   { "tiny", od_tiny, },
179   { "custom", od_custom, },
180 };
181
182 /* look through the hash for quantization options */
183 static void handle_quant_opts(i_quantize *quant, HV *hv)
184 {
185   /*** POSSIBLY BROKEN: do I need to unref the SV from hv_fetch ***/
186   SV **sv;
187   int i;
188   STRLEN len;
189   char *str;
190
191   sv = hv_fetch(hv, "transp", 6, 0);
192   if (sv && *sv && (str = SvPV(*sv, len))) {
193     quant->transp = 
194       lookup_name(transp_names, sizeof(transp_names)/sizeof(*transp_names), 
195                   str, tr_none);
196     if (quant->transp != tr_none) {
197       quant->tr_threshold = 127;
198       sv = hv_fetch(hv, "tr_threshold", 12, 0);
199       if (sv && *sv)
200         quant->tr_threshold = SvIV(*sv);
201     }
202     if (quant->transp == tr_errdiff) {
203       sv = hv_fetch(hv, "tr_errdiff", 10, 0);
204       if (sv && *sv && (str = SvPV(*sv, len)))
205         quant->tr_errdiff = lookup_name(errdiff_names, sizeof(errdiff_names)/sizeof(*errdiff_names), str, ed_floyd);
206     }
207     if (quant->transp == tr_ordered) {
208       quant->tr_orddith = od_tiny;
209       sv = hv_fetch(hv, "tr_orddith", 10, 0);
210       if (sv && *sv && (str = SvPV(*sv, len)))
211         quant->tr_orddith = lookup_name(orddith_names, sizeof(orddith_names)/sizeof(*orddith_names), str, od_random);
212
213       if (quant->tr_orddith == od_custom) {
214         sv = hv_fetch(hv, "tr_map", 6, 0);
215         if (sv && *sv && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
216           AV *av = (AV*)SvRV(*sv);
217           len = av_len(av) + 1;
218           if (len > sizeof(quant->tr_custom))
219             len = sizeof(quant->tr_custom);
220           for (i = 0; i < len; ++i) {
221             SV **sv2 = av_fetch(av, i, 0);
222             if (sv2 && *sv2) {
223               quant->tr_custom[i] = SvIV(*sv2);
224             }
225           }
226           while (i < sizeof(quant->tr_custom))
227             quant->tr_custom[i++] = 0;
228         }
229       }
230     }
231   }
232   quant->make_colors = mc_addi;
233   sv = hv_fetch(hv, "make_colors", 11, 0);
234   if (sv && *sv && (str = SvPV(*sv, len))) {
235     quant->make_colors = 
236       lookup_name(make_color_names, sizeof(make_color_names)/sizeof(*make_color_names), str, mc_addi);
237   }
238   sv = hv_fetch(hv, "colors", 6, 0);
239   if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
240     /* needs to be an array of Imager::Color
241        note that the caller allocates the mc_color array and sets mc_size
242        to it's size */
243     AV *av = (AV *)SvRV(*sv);
244     quant->mc_count = av_len(av)+1;
245     if (quant->mc_count > quant->mc_size)
246       quant->mc_count = quant->mc_size;
247     for (i = 0; i < quant->mc_count; ++i) {
248       SV **sv1 = av_fetch(av, i, 0);
249       if (sv1 && *sv1 && SvROK(*sv1) && sv_derived_from(*sv1, "Imager::Color")) {
250         i_color *col = (i_color *)SvIV((SV*)SvRV(*sv1));
251         quant->mc_colors[i] = *col;
252       }
253     }
254   }
255   sv = hv_fetch(hv, "max_colors", 10, 0);
256   if (sv && *sv) {
257     i = SvIV(*sv);
258     if (i <= quant->mc_size && i >= quant->mc_count)
259       quant->mc_size = i;
260   }
261
262   quant->translate = pt_closest;
263   sv = hv_fetch(hv, "translate", 9, 0);
264   if (sv && *sv && (str = SvPV(*sv, len))) {
265     quant->translate = lookup_name(translate_names, sizeof(translate_names)/sizeof(*translate_names), str, pt_closest);
266   }
267   sv = hv_fetch(hv, "errdiff", 7, 0);
268   if (sv && *sv && (str = SvPV(*sv, len))) {
269     quant->errdiff = lookup_name(errdiff_names, sizeof(errdiff_names)/sizeof(*errdiff_names), str, ed_floyd);
270   }
271   if (quant->translate == pt_errdiff && quant->errdiff == ed_custom) {
272     /* get the error diffusion map */
273     sv = hv_fetch(hv, "errdiff_width", 13, 0);
274     if (sv && *sv)
275       quant->ed_width = SvIV(*sv);
276     sv = hv_fetch(hv, "errdiff_height", 14, 0);
277     if (sv && *sv)
278       quant->ed_height = SvIV(*sv);
279     sv = hv_fetch(hv, "errdiff_orig", 12, 0);
280     if (sv && *sv)
281       quant->ed_orig = SvIV(*sv);
282     if (quant->ed_width > 0 && quant->ed_height > 0) {
283       int sum = 0;
284       quant->ed_map = mymalloc(sizeof(int)*quant->ed_width*quant->ed_height);
285       sv = hv_fetch(hv, "errdiff_map", 11, 0);
286       if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
287         AV *av = (AV*)SvRV(*sv);
288         len = av_len(av) + 1;
289         if (len > quant->ed_width * quant->ed_height)
290           len = quant->ed_width * quant->ed_height;
291         for (i = 0; i < len; ++i) {
292           SV **sv2 = av_fetch(av, i, 0);
293           if (sv2 && *sv2) {
294             quant->ed_map[i] = SvIV(*sv2);
295             sum += quant->ed_map[i];
296           }
297         }
298       }
299       if (!sum) {
300         /* broken map */
301         myfree(quant->ed_map);
302         quant->ed_map = 0;
303         quant->errdiff = ed_floyd;
304       }
305     }
306   }
307   sv = hv_fetch(hv, "perturb", 7, 0);
308   if (sv && *sv)
309     quant->perturb = SvIV(*sv);
310 }
311
312 /* look through the hash for options to add to opts */
313 static void handle_gif_opts(i_gif_opts *opts, HV *hv)
314 {
315   SV **sv;
316   int i;
317   /**((char *)0) = '\0';*/
318   sv = hv_fetch(hv, "gif_each_palette", 16, 0);
319   if (sv && *sv)
320     opts->each_palette = SvIV(*sv);
321   sv = hv_fetch(hv, "interlace", 9, 0);
322   if (sv && *sv)
323     opts->interlace = SvIV(*sv);
324   sv = hv_fetch(hv, "gif_delays", 10, 0);
325   if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
326     AV *av = (AV*)SvRV(*sv);
327     opts->delay_count = av_len(av)+1;
328     opts->delays = mymalloc(sizeof(int) * opts->delay_count);
329     for (i = 0; i < opts->delay_count; ++i) {
330       SV *sv1 = *av_fetch(av, i, 0);
331       opts->delays[i] = SvIV(sv1);
332     }
333   }
334   sv = hv_fetch(hv, "gif_user_input", 14, 0);
335   if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
336     AV *av = (AV*)SvRV(*sv);
337     opts->user_input_count = av_len(av)+1;
338     opts->user_input_flags = mymalloc(opts->user_input_count);
339     for (i = 0; i < opts->user_input_count; ++i) {
340       SV *sv1 = *av_fetch(av, i, 0);
341       opts->user_input_flags[i] = SvIV(sv1) != 0;
342     }
343   }
344   sv = hv_fetch(hv, "gif_disposal", 12, 0);
345   if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
346     AV *av = (AV*)SvRV(*sv);
347     opts->disposal_count = av_len(av)+1;
348     opts->disposal = mymalloc(opts->disposal_count);
349     for (i = 0; i < opts->disposal_count; ++i) {
350       SV *sv1 = *av_fetch(av, i, 0);
351       opts->disposal[i] = SvIV(sv1);
352     }
353   }
354   sv = hv_fetch(hv, "gif_tran_color", 14, 0);
355   if (sv && *sv && SvROK(*sv) && sv_derived_from(*sv, "Imager::Color")) {
356     i_color *col = (i_color *)SvIV((SV *)SvRV(*sv));
357     opts->tran_color = *col;
358   }
359   sv = hv_fetch(hv, "gif_positions", 13, 0);
360   if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
361     AV *av = (AV *)SvRV(*sv);
362     opts->position_count = av_len(av) + 1;
363     opts->positions = mymalloc(sizeof(i_gif_pos) * opts->position_count);
364     for (i = 0; i < opts->position_count; ++i) {
365       SV **sv2 = av_fetch(av, i, 0);
366       opts->positions[i].x = opts->positions[i].y = 0;
367       if (sv && *sv && SvROK(*sv) && SvTYPE(SvRV(*sv)) == SVt_PVAV) {
368         AV *av2 = (AV*)SvRV(*sv2);
369         SV **sv3;
370         sv3 = av_fetch(av2, 0, 0);
371         if (sv3 && *sv3)
372           opts->positions[i].x = SvIV(*sv3);
373         sv3 = av_fetch(av2, 1, 0);
374         if (sv3 && *sv3)
375           opts->positions[i].y = SvIV(*sv3);
376       }
377     }
378   }
379   /* Netscape2.0 loop count extension */
380   sv = hv_fetch(hv, "gif_loop_count", 14, 0);
381   if (sv && *sv)
382     opts->loop_count = SvIV(*sv);
383 }
384
385 /* copies the color map from the hv into the colors member of the HV */
386 static void copy_colors_back(HV *hv, i_quantize *quant) {
387   SV **sv;
388   AV *av;
389   int i;
390   SV *work;
391
392   sv = hv_fetch(hv, "colors", 6, 0);
393   if (!sv || !*sv || !SvROK(*sv) || SvTYPE(SvRV(*sv)) != SVt_PVAV) {
394     SV *ref;
395     av = newAV();
396     ref = newRV_inc((SV*) av);
397     sv = hv_store(hv, "colors", 6, ref, 0);
398   }
399   else {
400     av = (AV *)SvRV(*sv);
401   }
402   av_extend(av, quant->mc_count+1);
403   for (i = 0; i < quant->mc_count; ++i) {
404     i_color *in = quant->mc_colors+i;
405     Imager__Color c = ICL_new_internal(in->rgb.r, in->rgb.g, in->rgb.b, 255);
406     work = sv_newmortal();
407     sv_setref_pv(work, "Imager::Color", (void *)c);
408     SvREFCNT_inc(work);
409     if (!av_store(av, i, work)) {
410       SvREFCNT_dec(work);
411     }
412   }
413 }
414
415 /* loads the segments of a fountain fill into an array */
416 i_fountain_seg *load_fount_segs(AV *asegs, int *count) {
417   /* Each element of segs must contain:
418      [ start, middle, end, c0, c1, segtype, colortrans ]
419      start, middle, end are doubles from 0 to 1
420      c0, c1 are Imager::Color::Float or Imager::Color objects
421      segtype, colortrans are ints
422   */
423   int i, j;
424   AV *aseg;
425   SV *sv;
426   i_fountain_seg *segs;
427   double work[3];
428   int worki[2];
429
430   *count = av_len(asegs)+1;
431   if (*count < 1) 
432     croak("i_fountain must have at least one segment");
433   segs = mymalloc(sizeof(i_fountain_seg) * *count);
434   for(i = 0; i < *count; i++) {
435     SV **sv1 = av_fetch(asegs, i, 0);
436     if (!sv1 || !*sv1 || !SvROK(*sv1) 
437         || SvTYPE(SvRV(*sv1)) != SVt_PVAV) {
438       myfree(segs);
439       croak("i_fountain: segs must be an arrayref of arrayrefs");
440     }
441     aseg = (AV *)SvRV(*sv1);
442     if (av_len(aseg) != 7-1) {
443       myfree(segs);
444       croak("i_fountain: a segment must have 7 members");
445     }
446     for (j = 0; j < 3; ++j) {
447       SV **sv2 = av_fetch(aseg, j, 0);
448       if (!sv2 || !*sv2) {
449         myfree(segs);
450         croak("i_fountain: XS error");
451       }
452       work[j] = SvNV(*sv2);
453     }
454     segs[i].start  = work[0];
455     segs[i].middle = work[1];
456     segs[i].end    = work[2];
457     for (j = 0; j < 2; ++j) {
458       SV **sv3 = av_fetch(aseg, 3+j, 0);
459       if (!sv3 || !*sv3 || !SvROK(*sv3) ||
460           (!sv_derived_from(*sv3, "Imager::Color")
461            && !sv_derived_from(*sv3, "Imager::Color::Float"))) {
462         myfree(segs);
463         croak("i_fountain: segs must contain colors in elements 3 and 4");
464       }
465       if (sv_derived_from(*sv3, "Imager::Color::Float")) {
466         segs[i].c[j] = *(i_fcolor *)SvIV((SV *)SvRV(*sv3));
467       }
468       else {
469         i_color c = *(i_color *)SvIV((SV *)SvRV(*sv3));
470         int ch;
471         for (ch = 0; ch < MAXCHANNELS; ++ch) {
472           segs[i].c[j].channel[ch] = c.channel[ch] / 255.0;
473         }
474       }
475     }
476     for (j = 0; j < 2; ++j) {
477       SV **sv2 = av_fetch(aseg, j+5, 0);
478       if (!sv2 || !*sv2) {
479         myfree(segs);
480         croak("i_fountain: XS error");
481       }
482       worki[j] = SvIV(*sv2);
483     }
484     segs[i].type = worki[0];
485     segs[i].color = worki[1];
486   }
487
488   return segs;
489 }
490
491 /* I don't think ICLF_* names belong at the C interface
492    this makes the XS code think we have them, to let us avoid 
493    putting function bodies in the XS code
494 */
495 #define ICLF_new_internal(r, g, b, a) i_fcolor_new((r), (g), (b), (a))
496 #define ICLF_DESTROY(cl) i_fcolor_destroy(cl)
497
498 /* for the fill objects
499    Since a fill object may later have dependent images, (or fills!)
500    we need perl wrappers - oh well
501 */
502 #define IFILL_DESTROY(fill) i_fill_destroy(fill);
503 typedef i_fill_t* Imager__FillHandle;
504
505 MODULE = Imager         PACKAGE = Imager::Color PREFIX = ICL_
506
507 Imager::Color
508 ICL_new_internal(r,g,b,a)
509                unsigned char     r
510                unsigned char     g
511                unsigned char     b
512                unsigned char     a
513
514 void
515 ICL_DESTROY(cl)
516                Imager::Color    cl
517
518
519 void
520 ICL_set_internal(cl,r,g,b,a)
521                Imager::Color    cl
522                unsigned char     r
523                unsigned char     g
524                unsigned char     b
525                unsigned char     a
526            PPCODE:
527                ICL_set_internal(cl, r, g, b, a);
528                EXTEND(SP, 1);
529                PUSHs(ST(0));
530
531 void
532 ICL_info(cl)
533                Imager::Color    cl
534
535
536 void
537 ICL_rgba(cl)
538               Imager::Color     cl
539             PPCODE:
540                 EXTEND(SP, 4);
541                 PUSHs(sv_2mortal(newSVnv(cl->rgba.r)));
542                 PUSHs(sv_2mortal(newSVnv(cl->rgba.g)));
543                 PUSHs(sv_2mortal(newSVnv(cl->rgba.b)));
544                 PUSHs(sv_2mortal(newSVnv(cl->rgba.a)));
545
546
547
548
549 MODULE = Imager        PACKAGE = Imager::Color::Float  PREFIX=ICLF_
550
551 Imager::Color::Float
552 ICLF_new_internal(r, g, b, a)
553         double r
554         double g
555         double b
556         double a
557
558 void
559 ICLF_DESTROY(cl)
560         Imager::Color::Float    cl
561
562 void
563 ICLF_rgba(cl)
564         Imager::Color::Float    cl
565       PREINIT:
566         int ch;
567       PPCODE:
568         EXTEND(SP, MAXCHANNELS);
569         for (ch = 0; ch < MAXCHANNELS; ++ch) {
570         /* printf("%d: %g\n", ch, cl->channel[ch]); */
571           PUSHs(sv_2mortal(newSVnv(cl->channel[ch])));
572         }
573
574 void
575 ICLF_set_internal(cl,r,g,b,a)
576         Imager::Color::Float    cl
577         double     r
578         double     g
579         double     b
580         double     a
581       PPCODE:
582         cl->rgba.r = r;
583         cl->rgba.g = g;
584         cl->rgba.b = b;
585         cl->rgba.a = a;                
586         EXTEND(SP, 1);
587         PUSHs(ST(0));
588
589 MODULE = Imager         PACKAGE = Imager::ImgRaw        PREFIX = IIM_
590
591 Imager::ImgRaw
592 IIM_new(x,y,ch)
593                int     x
594                int     y
595                int     ch
596
597 void
598 IIM_DESTROY(im)
599                Imager::ImgRaw    im
600
601
602
603 MODULE = Imager         PACKAGE = Imager
604
605 PROTOTYPES: ENABLE
606
607
608 Imager::IO
609 io_new_fd(fd)
610                          int     fd
611
612 Imager::IO
613 io_new_bufchain()
614
615
616 void
617 io_slurp(ig)
618         Imager::IO     ig
619              PREINIT:
620               unsigned char*    data;
621              size_t    tlength;
622                 SV*    r;
623              PPCODE:
624               data    = NULL;
625               tlength = io_slurp(ig, &data);
626               r = sv_newmortal();
627               EXTEND(SP,1);
628               PUSHs(sv_2mortal(newSVpv(data,tlength)));
629               myfree(data);
630
631
632
633 void
634 i_list_formats()
635              PREINIT:
636               char*    item;
637                int     i;
638              PPCODE:
639                i=0;
640                while( (item=i_format_list[i++]) != NULL ) {
641                       EXTEND(SP, 1);
642                       PUSHs(sv_2mortal(newSVpv(item,0)));
643                }
644
645 undef_int
646 i_has_format(frmt)
647               char*    frmt
648
649 Imager::ImgRaw
650 i_img_new()
651
652 Imager::ImgRaw
653 i_img_empty(im,x,y)
654     Imager::ImgRaw     im
655                int     x
656                int     y
657
658 Imager::ImgRaw
659 i_img_empty_ch(im,x,y,ch)
660     Imager::ImgRaw     im
661                int     x
662                int     y
663                int     ch
664
665 void
666 init_log(name,level)
667               char*    name
668                int     level
669
670 void
671 i_img_exorcise(im)
672     Imager::ImgRaw     im
673
674 void
675 i_img_destroy(im)
676     Imager::ImgRaw     im
677
678 void
679 i_img_info(im)
680     Imager::ImgRaw     im
681              PREINIT:
682                int     info[4];
683              PPCODE:
684                i_img_info(im,info);
685                EXTEND(SP, 4);
686                PUSHs(sv_2mortal(newSViv(info[0])));
687                PUSHs(sv_2mortal(newSViv(info[1])));
688                PUSHs(sv_2mortal(newSViv(info[2])));
689                PUSHs(sv_2mortal(newSViv(info[3])));
690
691
692
693
694 void
695 i_img_setmask(im,ch_mask)
696     Imager::ImgRaw     im
697                int     ch_mask
698
699 int
700 i_img_getmask(im)
701     Imager::ImgRaw     im
702
703 int
704 i_img_getchannels(im)
705     Imager::ImgRaw     im
706
707 void
708 i_img_getdata(im)
709     Imager::ImgRaw     im
710              PPCODE:
711                EXTEND(SP, 1);
712                PUSHs(im->idata ? sv_2mortal(newSVpv(im->idata, im->bytes)) 
713                      : &PL_sv_undef);
714
715
716 void
717 i_draw(im,x1,y1,x2,y2,val)
718     Imager::ImgRaw     im
719                int     x1
720                int     y1
721                int     x2
722                int     y2
723      Imager::Color     val
724
725 void
726 i_line_aa(im,x1,y1,x2,y2,val)
727     Imager::ImgRaw     im
728                int     x1
729                int     y1
730                int     x2
731                int     y2
732      Imager::Color     val
733
734 void
735 i_box(im,x1,y1,x2,y2,val)
736     Imager::ImgRaw     im
737                int     x1
738                int     y1
739                int     x2
740                int     y2
741      Imager::Color     val
742
743 void
744 i_box_filled(im,x1,y1,x2,y2,val)
745     Imager::ImgRaw     im
746                int     x1
747                int     y1
748                int     x2
749                int     y2
750            Imager::Color    val
751
752 void
753 i_box_cfill(im,x1,y1,x2,y2,fill)
754     Imager::ImgRaw     im
755                int     x1
756                int     y1
757                int     x2
758                int     y2
759            Imager::FillHandle    fill
760
761 void
762 i_arc(im,x,y,rad,d1,d2,val)
763     Imager::ImgRaw     im
764                int     x
765                int     y
766              float     rad
767              float     d1
768              float     d2
769            Imager::Color    val
770
771 void
772 i_arc_cfill(im,x,y,rad,d1,d2,fill)
773     Imager::ImgRaw     im
774                int     x
775                int     y
776              float     rad
777              float     d1
778              float     d2
779            Imager::FillHandle    fill
780
781
782
783 void
784 i_circle_aa(im,x,y,rad,val)
785     Imager::ImgRaw     im
786              float     x
787              float     y
788              float     rad
789            Imager::Color    val
790
791
792
793 void
794 i_bezier_multi(im,xc,yc,val)
795     Imager::ImgRaw     im
796              Imager::Color  val
797              PREINIT:
798              double   *x,*y;
799              int       len;
800              AV       *av1;
801              AV       *av2;
802              SV       *sv1;
803              SV       *sv2;
804              int i;
805              PPCODE:
806              ICL_info(val);
807              if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_bezier_multi must be a reference to an array\n");
808              if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_bezier_multi must be a reference to an array\n");
809              if (!SvROK(ST(2))) croak("Imager: Parameter 2 to i_bezier_multi must be a reference to an array\n");
810              if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 2 to i_bezier_multi must be a reference to an array\n");
811              av1=(AV*)SvRV(ST(1));
812              av2=(AV*)SvRV(ST(2));
813              if (av_len(av1) != av_len(av2)) croak("Imager: x and y arrays to i_bezier_multi must be equal length\n");
814              len=av_len(av1)+1;
815              x=mymalloc( len*sizeof(double) );
816              y=mymalloc( len*sizeof(double) );
817              for(i=0;i<len;i++) {
818                sv1=(*(av_fetch(av1,i,0)));
819                sv2=(*(av_fetch(av2,i,0)));
820                x[i]=(double)SvNV(sv1);
821                y[i]=(double)SvNV(sv2);
822              }
823              i_bezier_multi(im,len,x,y,val);
824              myfree(x);
825              myfree(y);
826
827
828 void
829 i_poly_aa(im,xc,yc,val)
830     Imager::ImgRaw     im
831              Imager::Color  val
832              PREINIT:
833              double   *x,*y;
834              int       len;
835              AV       *av1;
836              AV       *av2;
837              SV       *sv1;
838              SV       *sv2;
839              int i;
840              PPCODE:
841              ICL_info(val);
842              if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
843              if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
844              if (!SvROK(ST(2))) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
845              if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
846              av1=(AV*)SvRV(ST(1));
847              av2=(AV*)SvRV(ST(2));
848              if (av_len(av1) != av_len(av2)) croak("Imager: x and y arrays to i_poly_aa must be equal length\n");
849              len=av_len(av1)+1;
850              x=mymalloc( len*sizeof(double) );
851              y=mymalloc( len*sizeof(double) );
852              for(i=0;i<len;i++) {
853                sv1=(*(av_fetch(av1,i,0)));
854                sv2=(*(av_fetch(av2,i,0)));
855                x[i]=(double)SvNV(sv1);
856                y[i]=(double)SvNV(sv2);
857              }
858              i_poly_aa(im,len,x,y,val);
859              myfree(x);
860              myfree(y);
861
862
863
864 void
865 i_flood_fill(im,seedx,seedy,dcol)
866     Imager::ImgRaw     im
867                int     seedx
868                int     seedy
869      Imager::Color     dcol
870
871 void
872 i_flood_cfill(im,seedx,seedy,fill)
873     Imager::ImgRaw     im
874                int     seedx
875                int     seedy
876      Imager::FillHandle     fill
877
878
879 void
880 i_copyto(im,src,x1,y1,x2,y2,tx,ty)
881     Imager::ImgRaw     im
882     Imager::ImgRaw     src
883                int     x1
884                int     y1
885                int     x2
886                int     y2
887                int     tx
888                int     ty
889
890
891 void
892 i_copyto_trans(im,src,x1,y1,x2,y2,tx,ty,trans)
893     Imager::ImgRaw     im
894     Imager::ImgRaw     src
895                int     x1
896                int     y1
897                int     x2
898                int     y2
899                int     tx
900                int     ty
901      Imager::Color     trans
902
903 void
904 i_copy(im,src)
905     Imager::ImgRaw     im
906     Imager::ImgRaw     src
907
908
909 undef_int
910 i_rubthru(im,src,tx,ty)
911     Imager::ImgRaw     im
912     Imager::ImgRaw     src
913                int     tx
914                int     ty
915
916 undef_int
917 i_flipxy(im, direction)
918     Imager::ImgRaw     im
919                int     direction
920
921 Imager::ImgRaw
922 i_rotate90(im, degrees)
923     Imager::ImgRaw      im
924                int      degrees
925
926 Imager::ImgRaw
927 i_rotate_exact(im, amount)
928     Imager::ImgRaw      im
929             double      amount
930
931 Imager::ImgRaw
932 i_matrix_transform(im, xsize, ysize, matrix)
933     Imager::ImgRaw      im
934                int      xsize
935                int      ysize
936       PREINIT:
937         double matrix[9];
938         AV *av;
939         IV len;
940         SV *sv1;
941         int i;
942       CODE:
943         if (!SvROK(ST(3)) || SvTYPE(SvRV(ST(3))) != SVt_PVAV)
944           croak("i_matrix_transform: parameter 4 must be an array ref\n");
945         av=(AV*)SvRV(ST(3));
946         len=av_len(av)+1;
947         if (len > 9)
948           len = 9;
949         for (i = 0; i < len; ++i) {
950           sv1=(*(av_fetch(av,i,0)));
951           matrix[i] = SvNV(sv1);
952         }
953         for (; i < 9; ++i)
954           matrix[i] = 0;
955         RETVAL = i_matrix_transform(im, xsize, ysize, matrix);        
956       OUTPUT:
957         RETVAL
958
959 void
960 i_gaussian(im,stdev)
961     Imager::ImgRaw     im
962              float     stdev
963
964 void
965 i_conv(im,pcoef)
966     Imager::ImgRaw     im
967              PREINIT:
968              float*    coeff;
969              int     len;
970              AV* av;
971              SV* sv1;
972              int i;
973              PPCODE:
974              if (!SvROK(ST(1))) croak("Imager: Parameter 1 must be a reference to an array\n");
975              if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 must be a reference to an array\n");
976              av=(AV*)SvRV(ST(1));
977              len=av_len(av)+1;
978              coeff=mymalloc( len*sizeof(float) );
979              for(i=0;i<len;i++) {
980                sv1=(*(av_fetch(av,i,0)));
981                coeff[i]=(float)SvNV(sv1);
982              }
983              i_conv(im,coeff,len);
984              myfree(coeff);
985
986 undef_int
987 i_convert(im, src, coeff)
988     Imager::ImgRaw     im
989     Imager::ImgRaw     src
990         PREINIT:
991           float *coeff;
992           int outchan;
993           int inchan;
994           AV *avmain;
995           SV **temp;
996           SV *svsub;
997           AV *avsub;
998           int len;
999           int i, j;
1000         CODE:
1001           if (!SvROK(ST(2)) || SvTYPE(SvRV(ST(2))) != SVt_PVAV)
1002             croak("i_convert: parameter 3 must be an arrayref\n");
1003           avmain = (AV*)SvRV(ST(2));
1004           outchan = av_len(avmain)+1;
1005           /* find the biggest */
1006           inchan = 0;
1007           for (j=0; j < outchan; ++j) {
1008             temp = av_fetch(avmain, j, 0);
1009             if (temp && SvROK(*temp) && SvTYPE(SvRV(*temp)) == SVt_PVAV) {
1010               avsub = (AV*)SvRV(*temp);
1011               len = av_len(avsub)+1;
1012               if (len > inchan)
1013                 inchan = len;
1014             }
1015           }
1016           coeff = mymalloc(sizeof(float) * outchan * inchan);
1017           for (j = 0; j < outchan; ++j) {
1018             avsub = (AV*)SvRV(*av_fetch(avmain, j, 0));
1019             len = av_len(avsub)+1;
1020             for (i = 0; i < len; ++i) {
1021               temp = av_fetch(avsub, i, 0);
1022               if (temp)
1023                 coeff[i+j*inchan] = SvNV(*temp);
1024               else
1025                 coeff[i+j*inchan] = 0;
1026             }
1027             while (i < inchan)
1028               coeff[i++ + j*inchan] = 0;
1029           }
1030           RETVAL = i_convert(im, src, coeff, outchan, inchan);
1031           myfree(coeff);
1032         OUTPUT:
1033           RETVAL
1034
1035
1036 void
1037 i_map(im, pmaps)
1038     Imager::ImgRaw     im
1039         PREINIT:
1040           unsigned int mask = 0;
1041           AV *avmain;
1042           AV *avsub;
1043           SV **temp;
1044           int len;
1045           int i, j;
1046           unsigned char (*maps)[256];
1047         CODE:
1048           if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV)
1049             croak("i_map: parameter 2 must be an arrayref\n");
1050           avmain = (AV*)SvRV(ST(1));
1051           len = av_len(avmain)+1;
1052           if (im->channels < len) len = im->channels;
1053
1054           maps = mymalloc( len * sizeof(unsigned char [256]) );
1055
1056           for (j=0; j<len ; j++) {
1057             temp = av_fetch(avmain, j, 0);
1058             if (temp && SvROK(*temp) && (SvTYPE(SvRV(*temp)) == SVt_PVAV) ) {
1059               avsub = (AV*)SvRV(*temp);
1060               if(av_len(avsub) != 255) continue;
1061               mask |= 1<<j;
1062               for (i=0; i<256 ; i++) {
1063                 int val;
1064                 temp = av_fetch(avsub, i, 0);
1065                 val = temp ? SvIV(*temp) : 0;
1066                 if (val<0) val = 0;
1067                 if (val>255) val = 255;
1068                 maps[j][i] = val;
1069               }
1070             }
1071           }
1072           i_map(im, maps, mask);
1073           myfree(maps);
1074
1075
1076
1077 float
1078 i_img_diff(im1,im2)
1079     Imager::ImgRaw     im1
1080     Imager::ImgRaw     im2
1081
1082
1083
1084 undef_int         
1085 i_init_fonts()
1086
1087 #ifdef HAVE_LIBT1
1088
1089 void
1090 i_t1_set_aa(st)
1091                int     st
1092
1093 int
1094 i_t1_new(pfb,afm=NULL)
1095               char*    pfb
1096               char*    afm
1097
1098 int
1099 i_t1_destroy(font_id)
1100                int     font_id
1101
1102
1103 undef_int
1104 i_t1_cp(im,xb,yb,channel,fontnum,points,str,len,align)
1105     Imager::ImgRaw     im
1106                int     xb
1107                int     yb
1108                int     channel
1109                int     fontnum
1110              float     points
1111               char*    str
1112                int     len
1113                int     align
1114
1115 void
1116 i_t1_bbox(fontnum,point,str,len)
1117                int     fontnum
1118              float     point
1119               char*    str
1120                int     len
1121              PREINIT:
1122                int     cords[6];
1123              PPCODE:
1124                i_t1_bbox(fontnum,point,str,len,cords);
1125                EXTEND(SP, 4);
1126                PUSHs(sv_2mortal(newSViv(cords[0])));
1127                PUSHs(sv_2mortal(newSViv(cords[1])));
1128                PUSHs(sv_2mortal(newSViv(cords[2])));
1129                PUSHs(sv_2mortal(newSViv(cords[3])));
1130                PUSHs(sv_2mortal(newSViv(cords[4])));
1131                PUSHs(sv_2mortal(newSViv(cords[5])));
1132
1133
1134
1135 undef_int
1136 i_t1_text(im,xb,yb,cl,fontnum,points,str,len,align)
1137     Imager::ImgRaw     im
1138                int     xb
1139                int     yb
1140      Imager::Color    cl
1141                int     fontnum
1142              float     points
1143               char*    str
1144                int     len
1145                int     align
1146
1147 #endif 
1148
1149 #ifdef HAVE_LIBTT
1150
1151
1152 Imager::TTHandle
1153 i_tt_new(fontname)
1154               char*     fontname
1155
1156 void
1157 i_tt_destroy(handle)
1158      Imager::TTHandle    handle
1159
1160
1161
1162 undef_int
1163 i_tt_text(handle,im,xb,yb,cl,points,str,len,smooth)
1164   Imager::TTHandle     handle
1165     Imager::ImgRaw     im
1166                int     xb
1167                int     yb
1168      Imager::Color     cl
1169              float     points
1170               char*    str
1171                int     len
1172                int     smooth
1173
1174
1175 undef_int
1176 i_tt_cp(handle,im,xb,yb,channel,points,str,len,smooth)
1177   Imager::TTHandle     handle
1178     Imager::ImgRaw     im
1179                int     xb
1180                int     yb
1181                int     channel
1182              float     points
1183               char*    str
1184                int     len
1185                int     smooth
1186
1187
1188
1189 undef_int
1190 i_tt_bbox(handle,point,str,len)
1191   Imager::TTHandle     handle
1192              float     point
1193               char*    str
1194                int     len
1195              PREINIT:
1196                int     cords[6],rc;
1197              PPCODE:
1198                if ((rc=i_tt_bbox(handle,point,str,len,cords))) {
1199                  EXTEND(SP, 4);
1200                  PUSHs(sv_2mortal(newSViv(cords[0])));
1201                  PUSHs(sv_2mortal(newSViv(cords[1])));
1202                  PUSHs(sv_2mortal(newSViv(cords[2])));
1203                  PUSHs(sv_2mortal(newSViv(cords[3])));
1204                  PUSHs(sv_2mortal(newSViv(cords[4])));
1205                  PUSHs(sv_2mortal(newSViv(cords[5])));
1206                }
1207
1208
1209 #endif 
1210
1211
1212
1213
1214 #ifdef HAVE_LIBJPEG
1215 undef_int
1216 i_writejpeg_wiol(im, ig, qfactor)
1217     Imager::ImgRaw     im
1218         Imager::IO     ig
1219                int     qfactor
1220
1221
1222 void
1223 i_readjpeg_wiol(ig)
1224         Imager::IO     ig
1225              PREINIT:
1226               char*    iptc_itext;
1227                int     tlength;
1228              i_img*    rimg;
1229                 SV*    r;
1230              PPCODE:
1231               iptc_itext = NULL;
1232               rimg = i_readjpeg_wiol(ig,-1,&iptc_itext,&tlength);
1233               if (iptc_itext == NULL) {
1234                     r = sv_newmortal();
1235                     EXTEND(SP,1);
1236                     sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
1237                     PUSHs(r);
1238               } else {
1239                     r = sv_newmortal();
1240                     EXTEND(SP,2);
1241                     sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
1242                     PUSHs(r);
1243                     PUSHs(sv_2mortal(newSVpv(iptc_itext,tlength)));
1244                     myfree(iptc_itext);
1245               }
1246
1247
1248 #endif
1249
1250
1251
1252
1253 #ifdef HAVE_LIBTIFF
1254
1255 Imager::ImgRaw
1256 i_readtiff_wiol(ig, length)
1257         Imager::IO     ig
1258                int     length
1259
1260
1261 undef_int
1262 i_writetiff_wiol(im, ig)
1263     Imager::ImgRaw     im
1264         Imager::IO     ig
1265
1266 undef_int
1267 i_writetiff_wiol_faxable(im, ig, fine)
1268     Imager::ImgRaw     im
1269         Imager::IO     ig
1270                int     fine
1271
1272
1273 #endif /* HAVE_LIBTIFF */
1274
1275
1276
1277
1278
1279 #ifdef HAVE_LIBPNG
1280
1281 Imager::ImgRaw
1282 i_readpng_wiol(ig, length)
1283         Imager::IO     ig
1284                int     length
1285
1286
1287 undef_int
1288 i_writepng_wiol(im, ig)
1289     Imager::ImgRaw     im
1290         Imager::IO     ig
1291
1292
1293 #endif
1294
1295
1296 #ifdef HAVE_LIBGIF
1297
1298 void
1299 i_giflib_version()
1300         PPCODE:
1301           PUSHs(sv_2mortal(newSVnv(IM_GIFMAJOR+IM_GIFMINOR*0.1)));
1302
1303 undef_int
1304 i_writegif(im,fd,colors,pixdev,fixed)
1305     Imager::ImgRaw     im
1306                int     fd
1307                int     colors
1308                int     pixdev
1309              PREINIT:
1310              int     fixedlen;
1311              Imager__Color  fixed;
1312              Imager__Color  tmp;
1313              AV* av;
1314              SV* sv1;
1315              IV  Itmp;
1316              int i;
1317              CODE:
1318              if (!SvROK(ST(4))) croak("Imager: Parameter 4 must be a reference to an array\n");
1319              if (SvTYPE(SvRV(ST(4))) != SVt_PVAV) croak("Imager: Parameter 4 must be a reference to an array\n");
1320              av=(AV*)SvRV(ST(4));
1321              fixedlen=av_len(av)+1;
1322              fixed=mymalloc( fixedlen*sizeof(i_color) );
1323              for(i=0;i<fixedlen;i++) {
1324                sv1=(*(av_fetch(av,i,0)));
1325                if (sv_derived_from(sv1, "Imager::Color")) {
1326                  Itmp = SvIV((SV*)SvRV(sv1));
1327                  tmp = (i_color*) Itmp;
1328                } else croak("Imager: one of the elements of array ref is not of Imager::Color type\n");
1329                fixed[i]=*tmp;
1330              }
1331              RETVAL=i_writegif(im,fd,colors,pixdev,fixedlen,fixed);
1332              myfree(fixed);
1333              ST(0) = sv_newmortal();
1334              if (RETVAL == 0) ST(0)=&PL_sv_undef;
1335              else sv_setiv(ST(0), (IV)RETVAL);
1336
1337
1338
1339
1340 undef_int
1341 i_writegifmc(im,fd,colors)
1342     Imager::ImgRaw    im
1343                int     fd
1344                int     colors
1345
1346
1347 undef_int
1348 i_writegif_gen(fd, ...)
1349                int     fd
1350       PROTOTYPE: $$@
1351       PREINIT:
1352         i_quantize quant;
1353         i_gif_opts opts;
1354         i_img **imgs = NULL;
1355         int img_count;
1356         int i;
1357         HV *hv;
1358       CODE:
1359         if (items < 3)
1360             croak("Usage: i_writegif_gen(fd,hashref, images...)");
1361         if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
1362             croak("i_writegif_gen: Second argument must be a hash ref");
1363         hv = (HV *)SvRV(ST(1));
1364         memset(&quant, 0, sizeof(quant));
1365         quant.mc_size = 256;
1366         quant.mc_colors = mymalloc(quant.mc_size * sizeof(i_color));
1367         memset(&opts, 0, sizeof(opts));
1368         handle_quant_opts(&quant, hv);
1369         handle_gif_opts(&opts, hv);
1370         img_count = items - 2;
1371         RETVAL = 1;
1372         if (img_count < 1) {
1373           RETVAL = 0;
1374           i_clear_error();
1375           i_push_error(0, "You need to specify images to save");
1376         }
1377         else {
1378           imgs = mymalloc(sizeof(i_img *) * img_count);
1379           for (i = 0; i < img_count; ++i) {
1380             SV *sv = ST(2+i);
1381             imgs[i] = NULL;
1382             if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
1383               imgs[i] = (i_img *)SvIV((SV*)SvRV(sv));
1384             }
1385             else {
1386               i_clear_error();
1387               i_push_error(0, "Only images can be saved");
1388               RETVAL = 0;
1389               break;
1390             }
1391           }
1392           if (RETVAL) {
1393             RETVAL = i_writegif_gen(&quant, fd, imgs, img_count, &opts);
1394           }
1395           myfree(imgs);
1396           if (RETVAL) {
1397             copy_colors_back(hv, &quant);
1398           }
1399         }
1400              ST(0) = sv_newmortal();
1401              if (RETVAL == 0) ST(0)=&PL_sv_undef;
1402              else sv_setiv(ST(0), (IV)RETVAL);
1403
1404 undef_int
1405 i_writegif_callback(cb, maxbuffer,...)
1406         int maxbuffer;
1407       PREINIT:
1408         i_quantize quant;
1409         i_gif_opts opts;
1410         i_img **imgs = NULL;
1411         int img_count;
1412         int i;
1413         HV *hv;
1414         i_writer_data wd;
1415       CODE:
1416         if (items < 4)
1417             croak("Usage: i_writegif_callback(\\&callback,maxbuffer,hashref, images...)");
1418         if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
1419             croak("i_writegif_callback: Second argument must be a hash ref");
1420         hv = (HV *)SvRV(ST(2));
1421         memset(&quant, 0, sizeof(quant));
1422         quant.mc_size = 256;
1423         quant.mc_colors = mymalloc(quant.mc_size * sizeof(i_color));
1424         memset(&opts, 0, sizeof(opts));
1425         handle_quant_opts(&quant, hv);
1426         handle_gif_opts(&opts, hv);
1427         img_count = items - 3;
1428         RETVAL = 1;
1429         if (img_count < 1) {
1430           RETVAL = 0;
1431         }
1432         else {
1433           imgs = mymalloc(sizeof(i_img *) * img_count);
1434           for (i = 0; i < img_count; ++i) {
1435             SV *sv = ST(3+i);
1436             imgs[i] = NULL;
1437             if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
1438               imgs[i] = (i_img *)SvIV((SV*)SvRV(sv));
1439             }
1440             else {
1441               RETVAL = 0;
1442               break;
1443             }
1444           }
1445           if (RETVAL) {
1446             wd.sv = ST(0);
1447             RETVAL = i_writegif_callback(&quant, write_callback, (char *)&wd, maxbuffer, imgs, img_count, &opts);
1448           }
1449           myfree(imgs);
1450           if (RETVAL) {
1451             copy_colors_back(hv, &quant);
1452           }
1453         }
1454              ST(0) = sv_newmortal();
1455              if (RETVAL == 0) ST(0)=&PL_sv_undef;
1456              else sv_setiv(ST(0), (IV)RETVAL);
1457
1458 void
1459 i_readgif(fd)
1460                int     fd
1461               PREINIT:
1462                 int*    colour_table;
1463                 int     colours, q, w;
1464               i_img*    rimg;
1465                  SV*    temp[3];
1466                  AV*    ct; 
1467                  SV*    r;
1468                PPCODE:
1469                colour_table = NULL;
1470                colours = 0;
1471
1472         if(GIMME_V == G_ARRAY) {
1473             rimg = i_readgif(fd,&colour_table,&colours);
1474         } else {
1475             /* don't waste time with colours if they aren't wanted */
1476             rimg = i_readgif(fd,NULL,NULL);
1477         }
1478         
1479         if (colour_table == NULL) {
1480             EXTEND(SP,1);
1481             r=sv_newmortal();
1482             sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
1483             PUSHs(r);
1484         } else {
1485             /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
1486             /* I don't know if I have the reference counts right or not :( */
1487             /* Neither do I :-) */
1488             /* No Idea here either */
1489
1490             ct=newAV();
1491             av_extend(ct, colours);
1492             for(q=0; q<colours; q++) {
1493                 for(w=0; w<3; w++)
1494                     temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
1495                 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
1496             }
1497             myfree(colour_table);
1498
1499             EXTEND(SP,2);
1500             r = sv_newmortal();
1501             sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
1502             PUSHs(r);
1503             PUSHs(newRV_noinc((SV*)ct));
1504         }
1505
1506
1507
1508
1509
1510 void
1511 i_readgif_scalar(...)
1512           PROTOTYPE: $
1513             PREINIT:
1514                char*    data;
1515        unsigned int     length;
1516                 int*    colour_table;
1517                 int     colours, q, w;
1518               i_img*    rimg;
1519                  SV*    temp[3];
1520                  AV*    ct; 
1521                  SV*    r;
1522                PPCODE:
1523         data = (char *)SvPV(ST(0), length);
1524         colour_table=NULL;
1525         colours=0;
1526
1527         if(GIMME_V == G_ARRAY) {  
1528             rimg=i_readgif_scalar(data,length,&colour_table,&colours);
1529         } else {
1530             /* don't waste time with colours if they aren't wanted */
1531             rimg=i_readgif_scalar(data,length,NULL,NULL);
1532         }
1533
1534         if (colour_table == NULL) {
1535             EXTEND(SP,1);
1536             r=sv_newmortal();
1537             sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
1538             PUSHs(r);
1539         } else {
1540             /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
1541             /* I don't know if I have the reference counts right or not :( */
1542             /* Neither do I :-) */
1543             ct=newAV();
1544             av_extend(ct, colours);
1545             for(q=0; q<colours; q++) {
1546                 for(w=0; w<3; w++)
1547                     temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
1548                 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
1549             }
1550             myfree(colour_table);
1551             
1552             EXTEND(SP,2);
1553             r=sv_newmortal();
1554             sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
1555             PUSHs(r);
1556             PUSHs(newRV_noinc((SV*)ct));
1557         }
1558
1559 void
1560 i_readgif_callback(...)
1561           PROTOTYPE: &
1562             PREINIT:
1563                char*    data;
1564                 int     length;
1565                 int*    colour_table;
1566                 int     colours, q, w;
1567               i_img*    rimg;
1568                  SV*    temp[3];
1569                  AV*    ct; 
1570                  SV*    r;
1571        i_reader_data    rd;
1572                PPCODE:
1573         rd.sv = ST(0);
1574         colour_table=NULL;
1575         colours=0;
1576
1577         if(GIMME_V == G_ARRAY) {  
1578             rimg=i_readgif_callback(read_callback, (char *)&rd,&colour_table,&colours);
1579         } else {
1580             /* don't waste time with colours if they aren't wanted */
1581             rimg=i_readgif_callback(read_callback, (char *)&rd,NULL,NULL);
1582         }
1583
1584         if (colour_table == NULL) {
1585             EXTEND(SP,1);
1586             r=sv_newmortal();
1587             sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
1588             PUSHs(r);
1589         } else {
1590             /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
1591             /* I don't know if I have the reference counts right or not :( */
1592             /* Neither do I :-) */
1593             /* Neither do I - maybe I'll move this somewhere */
1594             ct=newAV();
1595             av_extend(ct, colours);
1596             for(q=0; q<colours; q++) {
1597                 for(w=0; w<3; w++)
1598                     temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
1599                 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
1600             }
1601             myfree(colour_table);
1602             
1603             EXTEND(SP,2);
1604             r=sv_newmortal();
1605             sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
1606             PUSHs(r);
1607             PUSHs(newRV_noinc((SV*)ct));
1608         }
1609
1610 void
1611 i_readgif_multi(fd)
1612         int     fd
1613       PREINIT:
1614         i_img **imgs;
1615         int count;
1616         int i;
1617       PPCODE:
1618         imgs = i_readgif_multi(fd, &count);
1619         if (imgs) {
1620           EXTEND(SP, count);
1621           for (i = 0; i < count; ++i) {
1622             SV *sv = sv_newmortal();
1623             sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
1624             PUSHs(sv);
1625           }
1626           myfree(imgs);
1627         }
1628
1629 void
1630 i_readgif_multi_scalar(data)
1631       PREINIT:
1632         i_img **imgs;
1633         int count;
1634         char *data;
1635         unsigned int length;
1636         int i;
1637       PPCODE:
1638         data = (char *)SvPV(ST(0), length);
1639         imgs = i_readgif_multi_scalar(data, length, &count);
1640         if (imgs) {
1641           EXTEND(SP, count);
1642           for (i = 0; i < count; ++i) {
1643             SV *sv = sv_newmortal();
1644             sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
1645             PUSHs(sv);
1646           }
1647           myfree(imgs);
1648         }
1649
1650 void
1651 i_readgif_multi_callback(cb)
1652       PREINIT:
1653         i_reader_data rd;
1654         i_img **imgs;
1655         int count;
1656         int i;
1657       PPCODE:
1658         rd.sv = ST(0);
1659         imgs = i_readgif_multi_callback(read_callback, (char *)&rd, &count);
1660         if (imgs) {
1661           EXTEND(SP, count);
1662           for (i = 0; i < count; ++i) {
1663             SV *sv = sv_newmortal();
1664             sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
1665             PUSHs(sv);
1666           }
1667           myfree(imgs);
1668         }
1669
1670 #endif
1671
1672
1673
1674 Imager::ImgRaw
1675 i_readpnm_wiol(ig, length)
1676         Imager::IO     ig
1677                int     length
1678
1679
1680 undef_int
1681 i_writeppm_wiol(im, ig)
1682     Imager::ImgRaw     im
1683         Imager::IO     ig
1684
1685
1686 Imager::ImgRaw
1687 i_readraw_wiol(ig,x,y,datachannels,storechannels,intrl)
1688         Imager::IO     ig
1689                int     x
1690                int     y
1691                int     datachannels
1692                int     storechannels
1693                int     intrl
1694
1695 undef_int
1696 i_writeraw_wiol(im,ig)
1697     Imager::ImgRaw     im
1698         Imager::IO     ig
1699
1700 undef_int
1701 i_writebmp_wiol(im,ig)
1702     Imager::ImgRaw     im
1703         Imager::IO     ig
1704
1705 Imager::ImgRaw
1706 i_readbmp_wiol(ig)
1707         Imager::IO     ig
1708
1709 Imager::ImgRaw
1710 i_scaleaxis(im,Value,Axis)
1711     Imager::ImgRaw     im
1712              float     Value
1713                int     Axis
1714
1715 Imager::ImgRaw
1716 i_scale_nn(im,scx,scy)
1717     Imager::ImgRaw     im
1718              float     scx
1719              float     scy
1720
1721 Imager::ImgRaw
1722 i_haar(im)
1723     Imager::ImgRaw     im
1724
1725 int
1726 i_count_colors(im,maxc)
1727     Imager::ImgRaw     im
1728                int     maxc
1729
1730
1731 Imager::ImgRaw
1732 i_transform(im,opx,opy,parm)
1733     Imager::ImgRaw     im
1734              PREINIT:
1735              double* parm;
1736              int*    opx;
1737              int*    opy;
1738              int     opxl;
1739              int     opyl;
1740              int     parmlen;
1741              AV* av;
1742              SV* sv1;
1743              int i;
1744              CODE:
1745              if (!SvROK(ST(1))) croak("Imager: Parameter 1 must be a reference to an array\n");
1746              if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to an array\n");
1747              if (!SvROK(ST(3))) croak("Imager: Parameter 3 must be a reference to an array\n");
1748              if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 must be a reference to an array\n");
1749              if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 2 must be a reference to an array\n");
1750              if (SvTYPE(SvRV(ST(3))) != SVt_PVAV) croak("Imager: Parameter 3 must be a reference to an array\n");
1751              av=(AV*)SvRV(ST(1));
1752              opxl=av_len(av)+1;
1753              opx=mymalloc( opxl*sizeof(int) );
1754              for(i=0;i<opxl;i++) {
1755                sv1=(*(av_fetch(av,i,0)));
1756                opx[i]=(int)SvIV(sv1);
1757              }
1758              av=(AV*)SvRV(ST(2));
1759              opyl=av_len(av)+1;
1760              opy=mymalloc( opyl*sizeof(int) );
1761              for(i=0;i<opyl;i++) {
1762                sv1=(*(av_fetch(av,i,0)));
1763                opy[i]=(int)SvIV(sv1);
1764              }
1765              av=(AV*)SvRV(ST(3));
1766              parmlen=av_len(av)+1;
1767              parm=mymalloc( parmlen*sizeof(double) );
1768              for(i=0;i<parmlen;i++) { /* FIXME: Bug? */
1769                sv1=(*(av_fetch(av,i,0)));
1770                parm[i]=(double)SvNV(sv1);
1771              }
1772              RETVAL=i_transform(im,opx,opxl,opy,opyl,parm,parmlen);
1773              myfree(parm);
1774              myfree(opy);
1775              myfree(opx);
1776              ST(0) = sv_newmortal();
1777              if (RETVAL == 0) ST(0)=&PL_sv_undef;
1778              else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
1779
1780 Imager::ImgRaw
1781 i_transform2(width,height,ops,n_regs,c_regs,in_imgs)
1782              PREINIT:
1783              int width;
1784              int height;
1785              double* parm;
1786              struct rm_op *ops;
1787              unsigned int ops_len;
1788              int ops_count;
1789              double *n_regs;
1790              int n_regs_count;
1791              i_color *c_regs;
1792              int c_regs_count;
1793              int in_imgs_count;
1794              i_img **in_imgs;
1795              AV* av;
1796              SV* sv1;
1797              IV tmp;
1798              int i;
1799              CODE:
1800              if (!SvROK(ST(3))) croak("Imager: Parameter 4 must be a reference to an array\n");
1801              if (!SvROK(ST(4))) croak("Imager: Parameter 5 must be a reference to an array\n");
1802              if (!SvROK(ST(5))) croak("Imager: Parameter 6 must be a reference to an array of images\n");
1803              if (SvTYPE(SvRV(ST(3))) != SVt_PVAV) croak("Imager: Parameter 4 must be a reference to an array\n");
1804              if (SvTYPE(SvRV(ST(4))) != SVt_PVAV) croak("Imager: Parameter 5 must be a reference to an array\n");
1805
1806         /*if (SvTYPE(SvRV(ST(5))) != SVt_PVAV) croak("Imager: Parameter 6 must be a reference to an array\n");*/
1807
1808              if (SvTYPE(SvRV(ST(5))) == SVt_PVAV) {
1809                av = (AV*)SvRV(ST(5));
1810                in_imgs_count = av_len(av)+1;
1811                for (i = 0; i < in_imgs_count; ++i) {
1812                  sv1 = *av_fetch(av, i, 0);
1813                  if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
1814                    croak("Parameter 5 must contain only images");
1815                  }
1816                }
1817              }
1818              else {
1819                in_imgs_count = 0;
1820              }
1821              if (SvTYPE(SvRV(ST(5))) == SVt_PVAV) {
1822                av = (AV*)SvRV(ST(5));
1823                in_imgs = mymalloc(in_imgs_count*sizeof(i_img*));
1824                for (i = 0; i < in_imgs_count; ++i) {              
1825                  sv1 = *av_fetch(av,i,0);
1826                  if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
1827                    croak("Parameter 5 must contain only images");
1828                  }
1829                  tmp = SvIV((SV*)SvRV(sv1));
1830                  in_imgs[i] = (i_img*)tmp;
1831                }
1832              }
1833              else {
1834                /* no input images */
1835                in_imgs = NULL;
1836              }
1837              /* default the output size from the first input if possible */
1838              if (SvOK(ST(0)))
1839                width = SvIV(ST(0));
1840              else if (in_imgs_count)
1841                width = in_imgs[0]->xsize;
1842              else
1843                croak("No output image width supplied");
1844
1845              if (SvOK(ST(1)))
1846                height = SvIV(ST(1));
1847              else if (in_imgs_count)
1848                height = in_imgs[0]->ysize;
1849              else
1850                croak("No output image height supplied");
1851
1852              ops = (struct rm_op *)SvPV(ST(2), ops_len);
1853              if (ops_len % sizeof(struct rm_op))
1854                  croak("Imager: Parameter 3 must be a bitmap of regops\n");
1855              ops_count = ops_len / sizeof(struct rm_op);
1856              av = (AV*)SvRV(ST(3));
1857              n_regs_count = av_len(av)+1;
1858              n_regs = mymalloc(n_regs_count * sizeof(double));
1859              for (i = 0; i < n_regs_count; ++i) {
1860                sv1 = *av_fetch(av,i,0);
1861                if (SvOK(sv1))
1862                  n_regs[i] = SvNV(sv1);
1863              }
1864              av = (AV*)SvRV(ST(4));
1865              c_regs_count = av_len(av)+1;
1866              c_regs = mymalloc(c_regs_count * sizeof(i_color));
1867              /* I don't bother initializing the colou?r registers */
1868
1869              RETVAL=i_transform2(width, height, 3, ops, ops_count, 
1870                                  n_regs, n_regs_count, 
1871                                  c_regs, c_regs_count, in_imgs, in_imgs_count);
1872              if (in_imgs)
1873                  myfree(in_imgs);
1874              myfree(n_regs);
1875              myfree(c_regs);
1876              ST(0) = sv_newmortal();
1877              if (RETVAL == 0) ST(0)=&PL_sv_undef;
1878              else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
1879
1880
1881 void
1882 i_contrast(im,intensity)
1883     Imager::ImgRaw     im
1884              float     intensity
1885
1886 void
1887 i_hardinvert(im)
1888     Imager::ImgRaw     im
1889
1890 void
1891 i_noise(im,amount,type)
1892     Imager::ImgRaw     im
1893              float     amount
1894      unsigned char     type
1895
1896 void
1897 i_bumpmap(im,bump,channel,light_x,light_y,strength)
1898     Imager::ImgRaw     im
1899     Imager::ImgRaw     bump
1900                int     channel
1901                int     light_x
1902                int     light_y
1903                int     strength
1904
1905 void
1906 i_postlevels(im,levels)
1907     Imager::ImgRaw     im
1908              int       levels
1909
1910 void
1911 i_mosaic(im,size)
1912     Imager::ImgRaw     im
1913                int     size
1914
1915 void
1916 i_watermark(im,wmark,tx,ty,pixdiff)
1917     Imager::ImgRaw     im
1918     Imager::ImgRaw     wmark
1919                int     tx
1920                int     ty
1921                int     pixdiff
1922
1923
1924 void
1925 i_autolevels(im,lsat,usat,skew)
1926     Imager::ImgRaw     im
1927              float     lsat
1928              float     usat
1929              float     skew
1930
1931 void
1932 i_radnoise(im,xo,yo,rscale,ascale)
1933     Imager::ImgRaw     im
1934              float     xo
1935              float     yo
1936              float     rscale
1937              float     ascale
1938
1939 void
1940 i_turbnoise(im, xo, yo, scale)
1941     Imager::ImgRaw     im
1942              float     xo
1943              float     yo
1944              float     scale
1945
1946
1947 void
1948 i_gradgen(im, ...)
1949     Imager::ImgRaw     im
1950       PREINIT:
1951         int num;
1952         int *xo;
1953         int *yo;
1954         i_color *ival;
1955         int dmeasure;
1956         int i;
1957         SV *sv;
1958         AV *axx;
1959         AV *ayy;
1960         AV *ac;
1961       CODE:
1962         if (items != 5)
1963             croak("Usage: i_gradgen(im, xo, yo, ival, dmeasure)");
1964         if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
1965             croak("i_gradgen: Second argument must be an array ref");
1966         if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
1967             croak("i_gradgen: Third argument must be an array ref");
1968         if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
1969             croak("i_gradgen: Fourth argument must be an array ref");
1970         axx = (AV *)SvRV(ST(1));
1971         ayy = (AV *)SvRV(ST(2));
1972         ac  = (AV *)SvRV(ST(3));
1973         dmeasure = (int)SvIV(ST(4));
1974         
1975         num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
1976         num = num <= av_len(ac) ? num : av_len(ac);
1977         num++; 
1978         if (num < 2) croak("Usage: i_gradgen array refs must have more than 1 entry each");
1979         xo = mymalloc( sizeof(int) * num );
1980         yo = mymalloc( sizeof(int) * num );
1981         ival = mymalloc( sizeof(i_color) * num );
1982         for(i = 0; i<num; i++) {
1983           xo[i]   = (int)SvIV(* av_fetch(axx, i, 0));
1984           yo[i]   = (int)SvIV(* av_fetch(ayy, i, 0));
1985           sv = *av_fetch(ac, i, 0);
1986           if ( !sv_derived_from(sv, "Imager::Color") ) {
1987             free(axx); free(ayy); free(ac);
1988             croak("i_gradgen: Element of fourth argument is not derived from Imager::Color");
1989           }
1990           ival[i] = *(i_color *)SvIV((SV *)SvRV(sv));
1991         }
1992         i_gradgen(im, num, xo, yo, ival, dmeasure);
1993
1994 void
1995 i_fountain(im, xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
1996     Imager::ImgRaw     im
1997             double     xa
1998             double     ya
1999             double     xb
2000             double     yb
2001                int     type
2002                int     repeat
2003                int     combine
2004                int     super_sample
2005             double     ssample_param
2006       PREINIT:
2007         AV *asegs;
2008         int count;
2009         i_fountain_seg *segs;
2010       CODE:
2011         if (!SvROK(ST(10)) || ! SvTYPE(SvRV(ST(10))))
2012             croak("i_fountain: argument 11 must be an array ref");
2013         
2014         asegs = (AV *)SvRV(ST(10));
2015         segs = load_fount_segs(asegs, &count);
2016         i_fountain(im, xa, ya, xb, yb, type, repeat, combine, super_sample, 
2017                    ssample_param, count, segs);
2018         myfree(segs);
2019
2020 Imager::FillHandle
2021 i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
2022             double     xa
2023             double     ya
2024             double     xb
2025             double     yb
2026                int     type
2027                int     repeat
2028                int     combine
2029                int     super_sample
2030             double     ssample_param
2031       PREINIT:
2032         AV *asegs;
2033         int count;
2034         i_fountain_seg *segs;
2035       CODE:
2036         if (!SvROK(ST(9)) || ! SvTYPE(SvRV(ST(9))))
2037             croak("i_fountain: argument 11 must be an array ref");
2038         
2039         asegs = (AV *)SvRV(ST(9));
2040         segs = load_fount_segs(asegs, &count);
2041         RETVAL = i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine, 
2042                                   super_sample, ssample_param, count, segs);
2043         myfree(segs);        
2044       OUTPUT:
2045         RETVAL
2046
2047 void
2048 i_errors()
2049       PREINIT:
2050         i_errmsg *errors;
2051         int i;
2052         AV *av;
2053         SV *ref;
2054         SV *sv;
2055       PPCODE:
2056         errors = i_errors();
2057         i = 0;
2058         while (errors[i].msg) {
2059           av = newAV();
2060           sv = newSVpv(errors[i].msg, strlen(errors[i].msg));
2061           if (!av_store(av, 0, sv)) {
2062             SvREFCNT_dec(sv);
2063           }
2064           sv = newSViv(errors[i].code);
2065           if (!av_store(av, 1, sv)) {
2066             SvREFCNT_dec(sv);
2067           }
2068           PUSHs(sv_2mortal(newRV_noinc((SV*)av)));
2069           ++i;
2070         }
2071
2072 void
2073 i_nearest_color(im, ...)
2074     Imager::ImgRaw     im
2075       PREINIT:
2076         int num;
2077         int *xo;
2078         int *yo;
2079         i_color *ival;
2080         int dmeasure;
2081         int i;
2082         SV *sv;
2083         AV *axx;
2084         AV *ayy;
2085         AV *ac;
2086       CODE:
2087         if (items != 5)
2088             croak("Usage: i_nearest_color(im, xo, yo, ival, dmeasure)");
2089         if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2090             croak("i_nearest_color: Second argument must be an array ref");
2091         if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
2092             croak("i_nearest_color: Third argument must be an array ref");
2093         if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
2094             croak("i_nearest_color: Fourth argument must be an array ref");
2095         axx = (AV *)SvRV(ST(1));
2096         ayy = (AV *)SvRV(ST(2));
2097         ac  = (AV *)SvRV(ST(3));
2098         dmeasure = (int)SvIV(ST(4));
2099         
2100         num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
2101         num = num <= av_len(ac) ? num : av_len(ac);
2102         num++; 
2103         if (num < 2) croak("Usage: i_nearest_color array refs must have more than 1 entry each");
2104         xo = mymalloc( sizeof(int) * num );
2105         yo = mymalloc( sizeof(int) * num );
2106         ival = mymalloc( sizeof(i_color) * num );
2107         for(i = 0; i<num; i++) {
2108           xo[i]   = (int)SvIV(* av_fetch(axx, i, 0));
2109           yo[i]   = (int)SvIV(* av_fetch(ayy, i, 0));
2110           sv = *av_fetch(ac, i, 0);
2111           if ( !sv_derived_from(sv, "Imager::Color") ) {
2112             free(axx); free(ayy); free(ac);
2113             croak("i_nearest_color: Element of fourth argument is not derived from Imager::Color");
2114           }
2115           ival[i] = *(i_color *)SvIV((SV *)SvRV(sv));
2116         }
2117         i_nearest_color(im, num, xo, yo, ival, dmeasure);
2118
2119
2120
2121
2122 void
2123 malloc_state()
2124
2125 void
2126 hashinfo(hv)
2127              PREINIT:
2128                HV* hv;
2129                int stuff;
2130              PPCODE:
2131                if (!SvROK(ST(0))) croak("Imager: Parameter 0 must be a reference to a hash\n");        
2132                hv=(HV*)SvRV(ST(0));
2133                if (SvTYPE(hv)!=SVt_PVHV) croak("Imager: Parameter 0 must be a reference to a hash\n");
2134                if (getint(hv,"stuff",&stuff)) printf("ok: %d\n",stuff); else printf("key doesn't exist\n");
2135                if (getint(hv,"stuff2",&stuff)) printf("ok: %d\n",stuff); else printf("key doesn't exist\n");
2136                
2137 void
2138 DSO_open(filename)
2139              char*       filename
2140              PREINIT:
2141                void *rc;
2142                char *evstr;
2143              PPCODE:
2144                rc=DSO_open(filename,&evstr);
2145                if (rc!=NULL) {
2146                  if (evstr!=NULL) {
2147                    EXTEND(SP,2); 
2148                    PUSHs(sv_2mortal(newSViv((IV)rc)));
2149                    PUSHs(sv_2mortal(newSVpvn(evstr, strlen(evstr))));
2150                  } else {
2151                    EXTEND(SP,1);
2152                    PUSHs(sv_2mortal(newSViv((IV)rc)));
2153                  }
2154                }
2155
2156
2157 undef_int
2158 DSO_close(dso_handle)
2159              void*       dso_handle
2160
2161 void
2162 DSO_funclist(dso_handle_v)
2163              void*       dso_handle_v
2164              PREINIT:
2165                int i;
2166                DSO_handle *dso_handle;
2167              PPCODE:
2168                dso_handle=(DSO_handle*)dso_handle_v;
2169                i=0;
2170                while( dso_handle->function_list[i].name != NULL) {
2171                  EXTEND(SP,1);
2172                  PUSHs(sv_2mortal(newSVpv(dso_handle->function_list[i].name,0)));
2173                  EXTEND(SP,1);
2174                  PUSHs(sv_2mortal(newSVpv(dso_handle->function_list[i++].pcode,0)));
2175                }
2176
2177
2178 void
2179 DSO_call(handle,func_index,hv)
2180                void*  handle
2181                int    func_index
2182              PREINIT:
2183                HV* hv;
2184              PPCODE:
2185                if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to a hash\n");        
2186                hv=(HV*)SvRV(ST(2));
2187                if (SvTYPE(hv)!=SVt_PVHV) croak("Imager: Parameter 2 must be a reference to a hash\n");
2188                DSO_call( (DSO_handle *)handle,func_index,hv);
2189
2190
2191
2192 # this is mostly for testing...
2193 SV *
2194 i_get_pixel(im, x, y)
2195         Imager::ImgRaw im
2196         int x
2197         int y;
2198       PREINIT:
2199         i_color *color;
2200       CODE:
2201         color = (i_color *)mymalloc(sizeof(i_color));
2202         if (i_gpix(im, x, y, color) == 0) {
2203           ST(0) = sv_newmortal();
2204           sv_setref_pv(ST(0), "Imager::Color", (void *)color);
2205         }
2206         else {
2207           myfree(color);
2208           ST(0) = &PL_sv_undef;
2209         }
2210         
2211
2212 int
2213 i_ppix(im, x, y, cl)
2214         Imager::ImgRaw im
2215         int x
2216         int y
2217         Imager::Color cl
2218
2219 Imager::ImgRaw
2220 i_img_pal_new(x, y, channels, maxpal)
2221         int     x
2222         int     y
2223         int     channels
2224         int     maxpal
2225
2226 Imager::ImgRaw
2227 i_img_to_pal(src, quant)
2228         Imager::ImgRaw src
2229       PREINIT:
2230         HV *hv;
2231         i_quantize quant;
2232       CODE:
2233         if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2234           croak("i_img_to_pal: second argument must be a hash ref");
2235         hv = (HV *)SvRV(ST(1));
2236         memset(&quant, 0, sizeof(quant));
2237         quant.mc_size = 256;
2238         quant.mc_colors = mymalloc(quant.mc_size * sizeof(i_color));
2239         handle_quant_opts(&quant, hv);
2240         RETVAL = i_img_to_pal(src, &quant);
2241         if (RETVAL) {
2242           copy_colors_back(hv, &quant);
2243         }
2244         myfree(quant.mc_colors);
2245       OUTPUT:
2246         RETVAL
2247
2248 Imager::ImgRaw
2249 i_img_to_rgb(src)
2250         Imager::ImgRaw src
2251
2252 void
2253 i_gpal(im, l, r, y)
2254         Imager::ImgRaw  im
2255         int     l
2256         int     r
2257         int     y
2258       PREINIT:
2259         i_palidx *work;
2260         int count, i;
2261       PPCODE:
2262         if (l < r) {
2263           work = mymalloc((r-l) * sizeof(i_palidx));
2264           count = i_gpal(im, l, r, y, work);
2265           if (GIMME_V == G_ARRAY) {
2266             EXTEND(SP, count);
2267             for (i = 0; i < count; ++i) {
2268               PUSHs(sv_2mortal(newSViv(work[i])));
2269             }
2270           }
2271           else {
2272             EXTEND(SP, 1);
2273             PUSHs(sv_2mortal(newSVpv(work, count * sizeof(i_palidx))));
2274           }
2275           myfree(work);
2276         }
2277         else {
2278           if (GIMME_V != G_ARRAY) {
2279             EXTEND(SP, 1);
2280             PUSHs(&PL_sv_undef);
2281           }
2282         }
2283
2284 int
2285 i_ppal(im, l, y, ...)
2286         Imager::ImgRaw  im
2287         int     l
2288         int     y
2289       PREINIT:
2290         i_palidx *work;
2291         int count, i;
2292       CODE:
2293         if (items > 3) {
2294           work = mymalloc(sizeof(i_palidx) * (items-3));
2295           for (i=0; i < items-3; ++i) {
2296             work[i] = SvIV(ST(i+3));
2297           }
2298           RETVAL = i_ppal(im, l, l+items-3, y, work);
2299           myfree(work);
2300         }
2301         else {
2302           RETVAL = 0;
2303         }
2304       OUTPUT:
2305         RETVAL
2306
2307 SV *
2308 i_addcolors(im, ...)
2309         Imager::ImgRaw  im
2310       PREINIT:
2311         int index;
2312         i_color *colors;
2313         int i;
2314       CODE:
2315         if (items < 2)
2316           croak("i_addcolors: no colors to add");
2317         colors = mymalloc((items-1) * sizeof(i_color));
2318         for (i=0; i < items-1; ++i) {
2319           if (sv_isobject(ST(i+1)) 
2320               && sv_derived_from(ST(i+1), "Imager::Color")) {
2321             IV tmp = SvIV((SV *)SvRV(ST(i+1)));
2322             colors[i] = *(i_color *)tmp;
2323           }
2324           else {
2325             myfree(colors);
2326             croak("i_plin: pixels must be Imager::Color objects");
2327           }
2328         }
2329         index = i_addcolors(im, colors, items-1);
2330         myfree(colors);
2331         if (index == 0) {
2332           ST(0) = sv_2mortal(newSVpv("0 but true", 0));
2333         }
2334         else if (index == -1) {
2335           ST(0) = &PL_sv_undef;
2336         }
2337         else {
2338           ST(0) = sv_2mortal(newSViv(index));
2339         }
2340
2341 int 
2342 i_setcolors(im, index, ...)
2343         Imager::ImgRaw  im
2344         int index
2345       PREINIT:
2346         i_color *colors;
2347         int i;
2348       CODE:
2349         if (items < 3)
2350           croak("i_setcolors: no colors to add");
2351         colors = mymalloc((items-2) * sizeof(i_color));
2352         for (i=0; i < items-2; ++i) {
2353           if (sv_isobject(ST(i+2)) 
2354               && sv_derived_from(ST(i+2), "Imager::Color")) {
2355             IV tmp = SvIV((SV *)SvRV(ST(i+2)));
2356             colors[i] = *(i_color *)tmp;
2357           }
2358           else {
2359             myfree(colors);
2360             croak("i_setcolors: pixels must be Imager::Color objects");
2361           }
2362         }
2363         RETVAL = i_setcolors(im, index, colors, items-2);
2364         myfree(colors);
2365
2366 void
2367 i_getcolors(im, index, ...)
2368         Imager::ImgRaw im
2369         int index
2370       PREINIT:
2371         i_color *colors;
2372         int count = 1;
2373         int i;
2374       PPCODE:
2375         if (items > 3)
2376           croak("i_getcolors: too many arguments");
2377         if (items == 3)
2378           count = SvIV(ST(2));
2379         if (count < 1)
2380           croak("i_getcolors: count must be positive");
2381         colors = mymalloc(sizeof(i_color) * count);
2382         if (i_getcolors(im, index, colors, count)) {
2383           for (i = 0; i < count; ++i) {
2384             i_color *pv;
2385             SV *sv = sv_newmortal();
2386             pv = mymalloc(sizeof(i_color));
2387             *pv = colors[i];
2388             sv_setref_pv(sv, "Imager::Color", (void *)pv);
2389             PUSHs(sv);
2390           }
2391         }
2392         myfree(colors);
2393
2394
2395 SV *
2396 i_colorcount(im)
2397         Imager::ImgRaw im
2398       PREINIT:
2399         int count;
2400       CODE:
2401         count = i_colorcount(im);
2402         if (count >= 0) {
2403           ST(0) = sv_2mortal(newSViv(count));
2404         }
2405         else {
2406           ST(0) = &PL_sv_undef;
2407         }
2408
2409 SV *
2410 i_maxcolors(im)
2411         Imager::ImgRaw im
2412       PREINIT:
2413         int count;
2414       CODE:
2415         count = i_maxcolors(im);
2416         if (count >= 0) {
2417           ST(0) = sv_2mortal(newSViv(count));
2418         }
2419         else {
2420           ST(0) = &PL_sv_undef;
2421         }
2422
2423 SV *
2424 i_findcolor(im, color)
2425         Imager::ImgRaw im
2426         Imager::Color color
2427       PREINIT:
2428         i_palidx index;
2429       CODE:
2430         if (i_findcolor(im, color, &index)) {
2431           ST(0) = sv_2mortal(newSViv(index));
2432         }
2433         else {
2434           ST(0) = &PL_sv_undef;
2435         }
2436
2437 int
2438 i_img_bits(im)
2439         Imager::ImgRaw  im
2440
2441 int
2442 i_img_type(im)
2443         Imager::ImgRaw  im
2444
2445 int
2446 i_img_virtual(im)
2447         Imager::ImgRaw  im
2448
2449 void
2450 i_gsamp(im, l, r, y, ...)
2451         Imager::ImgRaw im
2452         int l
2453         int r
2454         int y
2455       PREINIT:
2456         int *chans;
2457         int chan_count;
2458         i_sample_t *data;
2459         int count, i;
2460       PPCODE:
2461         if (items < 5)
2462           croak("No channel numbers supplied to g_samp()");
2463         if (l < r) {
2464           chan_count = items - 4;
2465           chans = mymalloc(sizeof(int) * chan_count);
2466           for (i = 0; i < chan_count; ++i)
2467             chans[i] = SvIV(ST(i+4));
2468           data = mymalloc(sizeof(i_sample_t) * (r-l) * chan_count);
2469           count = i_gsamp(im, l, r, y, data, chans, chan_count);
2470           if (GIMME_V == G_ARRAY) {
2471             EXTEND(SP, count);
2472             for (i = 0; i < count; ++i)
2473               PUSHs(sv_2mortal(newSViv(data[i])));
2474           }
2475           else {
2476             EXTEND(SP, 1);
2477             PUSHs(sv_2mortal(newSVpv(data, count * sizeof(i_sample_t))));
2478           }
2479         }
2480         else {
2481           if (GIMME_V != G_ARRAY) {
2482             EXTEND(SP, 1);
2483             PUSHs(&PL_sv_undef);
2484           }
2485         }
2486
2487 Imager::ImgRaw
2488 i_img_masked_new(targ, mask, x, y, w, h)
2489         Imager::ImgRaw targ
2490         int x
2491         int y
2492         int w
2493         int h
2494       PREINIT:
2495         i_img *mask;
2496       CODE:
2497         if (SvOK(ST(1))) {
2498           if (!sv_isobject(ST(1)) 
2499               || !sv_derived_from(ST(1), "Imager::ImgRaw")) {
2500             croak("i_img_masked_new: parameter 2 must undef or an image");
2501           }
2502           mask = (i_img *)SvIV((SV *)SvRV(ST(1)));
2503         }
2504         else
2505           mask = NULL;
2506         RETVAL = i_img_masked_new(targ, mask, x, y, w, h);
2507       OUTPUT:
2508         RETVAL
2509
2510 int
2511 i_plin(im, l, y, ...)
2512         Imager::ImgRaw  im
2513         int     l
2514         int     y
2515       PREINIT:
2516         i_color *work;
2517         int count, i;
2518       CODE:
2519         if (items > 3) {
2520           work = mymalloc(sizeof(i_color) * (items-3));
2521           for (i=0; i < items-3; ++i) {
2522             if (sv_isobject(ST(i+3)) 
2523                 && sv_derived_from(ST(i+3), "Imager::Color")) {
2524               IV tmp = SvIV((SV *)SvRV(ST(i+3)));
2525               work[i] = *(i_color *)tmp;
2526             }
2527             else {
2528               myfree(work);
2529               croak("i_plin: pixels must be Imager::Color objects");
2530             }
2531           }
2532           /**(char *)0 = 1;*/
2533           RETVAL = i_plin(im, l, l+items-3, y, work);
2534           myfree(work);
2535         }
2536         else {
2537           RETVAL = 0;
2538         }
2539       OUTPUT:
2540         RETVAL
2541
2542 int
2543 i_ppixf(im, x, y, cl)
2544         Imager::ImgRaw im
2545         int x
2546         int y
2547         Imager::Color::Float cl
2548
2549 void
2550 i_gsampf(im, l, r, y, ...)
2551         Imager::ImgRaw im
2552         int l
2553         int r
2554         int y
2555       PREINIT:
2556         int *chans;
2557         int chan_count;
2558         i_fsample_t *data;
2559         int count, i;
2560       PPCODE:
2561         if (items < 5)
2562           croak("No channel numbers supplied to g_sampf()");
2563         if (l < r) {
2564           chan_count = items - 4;
2565           chans = mymalloc(sizeof(int) * chan_count);
2566           for (i = 0; i < chan_count; ++i)
2567             chans[i] = SvIV(ST(i+4));
2568           data = mymalloc(sizeof(i_fsample_t) * (r-l) * chan_count);
2569           count = i_gsampf(im, l, r, y, data, chans, chan_count);
2570           if (GIMME_V == G_ARRAY) {
2571             EXTEND(SP, count);
2572             for (i = 0; i < count; ++i)
2573               PUSHs(sv_2mortal(newSVnv(data[i])));
2574           }
2575           else {
2576             EXTEND(SP, 1);
2577             PUSHs(sv_2mortal(newSVpv((void *)data, count * sizeof(i_fsample_t))));
2578           }
2579         }
2580         else {
2581           if (GIMME_V != G_ARRAY) {
2582             EXTEND(SP, 1);
2583             PUSHs(&PL_sv_undef);
2584           }
2585         }
2586
2587 int
2588 i_plinf(im, l, y, ...)
2589         Imager::ImgRaw  im
2590         int     l
2591         int     y
2592       PREINIT:
2593         i_fcolor *work;
2594         int count, i;
2595       CODE:
2596         if (items > 3) {
2597           work = mymalloc(sizeof(i_fcolor) * (items-3));
2598           for (i=0; i < items-3; ++i) {
2599             if (sv_isobject(ST(i+3)) 
2600                 && sv_derived_from(ST(i+3), "Imager::Color::Float")) {
2601               IV tmp = SvIV((SV *)SvRV(ST(i+3)));
2602               work[i] = *(i_fcolor *)tmp;
2603             }
2604             else {
2605               myfree(work);
2606               croak("i_plin: pixels must be Imager::Color::Float objects");
2607             }
2608           }
2609           /**(char *)0 = 1;*/
2610           RETVAL = i_plinf(im, l, l+items-3, y, work);
2611           myfree(work);
2612         }
2613         else {
2614           RETVAL = 0;
2615         }
2616       OUTPUT:
2617         RETVAL
2618
2619 SV *
2620 i_gpixf(im, x, y)
2621         Imager::ImgRaw im
2622         int x
2623         int y;
2624       PREINIT:
2625         i_fcolor *color;
2626       CODE:
2627         color = (i_fcolor *)mymalloc(sizeof(i_fcolor));
2628         if (i_gpixf(im, x, y, color) == 0) {
2629           ST(0) = sv_newmortal();
2630           sv_setref_pv(ST(0), "Imager::Color::Float", (void *)color);
2631         }
2632         else {
2633           myfree(color);
2634           ST(0) = &PL_sv_undef;
2635         }
2636         
2637 void
2638 i_glin(im, l, r, y)
2639         Imager::ImgRaw im
2640         int l
2641         int r
2642         int y
2643       PREINIT:
2644         i_color *vals;
2645         int count, i;
2646       PPCODE:
2647         if (l < r) {
2648           vals = mymalloc((r-l) * sizeof(i_color));
2649           count = i_glin(im, l, r, y, vals);
2650           EXTEND(SP, count);
2651           for (i = 0; i < count; ++i) {
2652             SV *sv;
2653             i_color *col = mymalloc(sizeof(i_color));
2654             sv = sv_newmortal();
2655             sv_setref_pv(sv, "Imager::Color", (void *)col);
2656             PUSHs(sv);
2657           }
2658           myfree(vals);
2659         }
2660
2661 void
2662 i_glinf(im, l, r, y)
2663         Imager::ImgRaw im
2664         int l
2665         int r
2666         int y
2667       PREINIT:
2668         i_fcolor *vals;
2669         int count, i;
2670       PPCODE:
2671         if (l < r) {
2672           vals = mymalloc((r-l) * sizeof(i_fcolor));
2673           count = i_glinf(im, l, r, y, vals);
2674           EXTEND(SP, count);
2675           for (i = 0; i < count; ++i) {
2676             SV *sv;
2677             i_fcolor *col = mymalloc(sizeof(i_fcolor));
2678             *col = vals[i];
2679             sv = sv_newmortal();
2680             sv_setref_pv(sv, "Imager::Color::Float", (void *)col);
2681             PUSHs(sv);
2682           }
2683           myfree(vals);
2684         }
2685
2686 Imager::ImgRaw
2687 i_img_16_new(x, y, ch)
2688         int x
2689         int y
2690         int ch
2691
2692 undef_int
2693 i_tags_addn(im, name, code, idata)
2694         Imager::ImgRaw im
2695         int     code
2696         int     idata
2697       PREINIT:
2698         char *name;
2699         STRLEN len;
2700       CODE:
2701         if (SvOK(ST(1)))
2702           name = SvPV(ST(1), len);
2703         else
2704           name = NULL;
2705         RETVAL = i_tags_addn(&im->tags, name, code, idata);
2706       OUTPUT:
2707         RETVAL
2708
2709 undef_int
2710 i_tags_add(im, name, code, data, idata)
2711         Imager::ImgRaw  im
2712         int code
2713         int idata
2714       PREINIT:
2715         char *name;
2716         char *data;
2717         STRLEN len;
2718       CODE:
2719         if (SvOK(ST(1)))
2720           name = SvPV(ST(1), len);
2721         else
2722           name = NULL;
2723         if (SvOK(ST(3)))
2724           data = SvPV(ST(3), len);
2725         else {
2726           data = NULL;
2727           len = 0;
2728         }
2729         RETVAL = i_tags_add(&im->tags, name, code, data, len, idata);
2730       OUTPUT:
2731         RETVAL
2732
2733 SV *
2734 i_tags_find(im, name, start)
2735         Imager::ImgRaw  im
2736         char *name
2737         int start
2738       PREINIT:
2739         int entry;
2740       CODE:
2741         if (i_tags_find(&im->tags, name, start, &entry)) {
2742           if (entry == 0)
2743             ST(0) = sv_2mortal(newSVpv("0 but true", 0));
2744           else
2745             ST(0) = sv_2mortal(newSViv(entry));
2746         } else {
2747           ST(0) = &PL_sv_undef;
2748         }
2749
2750 SV *
2751 i_tags_findn(im, code, start)
2752         Imager::ImgRaw  im
2753         int             code
2754         int             start
2755       PREINIT:
2756         int entry;
2757       CODE:
2758         if (i_tags_findn(&im->tags, code, start, &entry)) {
2759           if (entry == 0)
2760             ST(0) = sv_2mortal(newSVpv("0 but true", 0));
2761           else
2762             ST(0) = sv_2mortal(newSViv(entry));
2763         }
2764         else
2765           ST(0) = &PL_sv_undef;
2766
2767 int
2768 i_tags_delete(im, entry)
2769         Imager::ImgRaw  im
2770         int             entry
2771       CODE:
2772         RETVAL = i_tags_delete(&im->tags, entry);
2773       OUTPUT:
2774         RETVAL
2775
2776 int
2777 i_tags_delbyname(im, name)
2778         Imager::ImgRaw  im
2779         char *          name
2780       CODE:
2781         RETVAL = i_tags_delbyname(&im->tags, name);
2782       OUTPUT:
2783         RETVAL
2784
2785 int
2786 i_tags_delbycode(im, code)
2787         Imager::ImgRaw  im
2788         int             code
2789       CODE:
2790         RETVAL = i_tags_delbycode(&im->tags, code);
2791       OUTPUT:
2792         RETVAL
2793
2794 void
2795 i_tags_get(im, index)
2796         Imager::ImgRaw  im
2797         int             index
2798       PPCODE:
2799         if (index >= 0 && index < im->tags.count) {
2800           i_img_tag *entry = im->tags.tags + index;
2801           EXTEND(SP, 5);
2802         
2803           if (entry->name) {
2804             PUSHs(sv_2mortal(newSVpv(entry->name, 0)));
2805           }
2806           else {
2807             PUSHs(sv_2mortal(newSViv(entry->code)));
2808           }
2809           if (entry->data) {
2810             PUSHs(sv_2mortal(newSVpvn(entry->data, entry->size)));
2811           }
2812           else {
2813             PUSHs(sv_2mortal(newSViv(entry->idata)));
2814           }
2815         }
2816
2817 int
2818 i_tags_count(im)
2819         Imager::ImgRaw  im
2820       CODE:
2821         RETVAL = im->tags.count;
2822       OUTPUT:
2823         RETVAL
2824
2825 #ifdef HAVE_WIN32
2826
2827 void
2828 i_wf_bbox(face, size, text)
2829         char *face
2830         int size
2831         char *text
2832       PREINIT:
2833         int cords[6];
2834       PPCODE:
2835         if (i_wf_bbox(face, size, text, strlen(text), cords)) {
2836           EXTEND(SP, 6);  
2837           PUSHs(sv_2mortal(newSViv(cords[0])));
2838           PUSHs(sv_2mortal(newSViv(cords[1])));
2839           PUSHs(sv_2mortal(newSViv(cords[2])));
2840           PUSHs(sv_2mortal(newSViv(cords[3])));
2841           PUSHs(sv_2mortal(newSViv(cords[4])));
2842           PUSHs(sv_2mortal(newSViv(cords[5])));
2843         }
2844
2845 undef_int
2846 i_wf_text(face, im, tx, ty, cl, size, text, align, aa)
2847         char *face
2848         Imager::ImgRaw im
2849         int tx
2850         int ty
2851         Imager::Color cl
2852         int size
2853         char *text
2854         int align
2855         int aa
2856       CODE:
2857         RETVAL = i_wf_text(face, im, tx, ty, cl, size, text, strlen(text), 
2858                            align, aa);
2859       OUTPUT:
2860         RETVAL
2861
2862 undef_int
2863 i_wf_cp(face, im, tx, ty, channel, size, text, align, aa)
2864         char *face
2865         Imager::ImgRaw im
2866         int tx
2867         int ty
2868         int channel
2869         int size
2870         char *text
2871         int align
2872         int aa
2873       CODE:
2874         RETVAL = i_wf_cp(face, im, tx, ty, channel, size, text, strlen(text), 
2875                          align, aa);
2876       OUTPUT:
2877         RETVAL
2878
2879
2880 #endif
2881
2882 #ifdef HAVE_FT2
2883
2884 MODULE = Imager         PACKAGE = Imager::Font::FT2     PREFIX=FT2_
2885
2886 #define FT2_DESTROY(font) i_ft2_destroy(font)
2887
2888 void
2889 FT2_DESTROY(font)
2890         Imager::Font::FT2 font
2891
2892 MODULE = Imager         PACKAGE = Imager::Font::FreeType2 
2893
2894 Imager::Font::FT2
2895 i_ft2_new(name, index)
2896         char *name
2897         int index
2898
2899 undef_int
2900 i_ft2_setdpi(font, xdpi, ydpi)
2901         Imager::Font::FT2 font
2902         int xdpi
2903         int ydpi
2904
2905 void
2906 i_ft2_getdpi(font)
2907         Imager::Font::FT2 font
2908       PREINIT:
2909         int xdpi, ydpi;
2910       CODE:
2911         if (i_ft2_getdpi(font, &xdpi, &ydpi)) {
2912           EXTEND(SP, 2);
2913           PUSHs(sv_2mortal(newSViv(xdpi)));
2914           PUSHs(sv_2mortal(newSViv(ydpi)));
2915         }
2916
2917 undef_int
2918 i_ft2_sethinting(font, hinting)
2919         Imager::Font::FT2 font
2920         int hinting
2921
2922 undef_int
2923 i_ft2_settransform(font, matrix)
2924         Imager::Font::FT2 font
2925       PREINIT:
2926         double matrix[6];
2927         int len;
2928         AV *av;
2929         SV *sv1;
2930         int i;
2931       CODE:
2932         if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV)
2933           croak("i_ft2_settransform: parameter 2 must be an array ref\n");
2934         av=(AV*)SvRV(ST(1));
2935         len=av_len(av)+1;
2936         if (len > 6)
2937           len = 6;
2938         for (i = 0; i < len; ++i) {
2939           sv1=(*(av_fetch(av,i,0)));
2940           matrix[i] = SvNV(sv1);
2941         }
2942         for (; i < 6; ++i)
2943           matrix[i] = 0;
2944         RETVAL = i_ft2_settransform(font, matrix);
2945       OUTPUT:
2946         RETVAL
2947
2948 void
2949 i_ft2_bbox(font, cheight, cwidth, text)
2950         Imager::Font::FT2 font
2951         double cheight
2952         double cwidth
2953         char *text
2954       PREINIT:
2955         int bbox[6];
2956         int i;
2957       PPCODE:
2958         if (i_ft2_bbox(font, cheight, cwidth, text, strlen(text), bbox)) {
2959           EXTEND(SP, 6);
2960           for (i = 0; i < 6; ++i)
2961             PUSHs(sv_2mortal(newSViv(bbox[i])));
2962         }
2963
2964 void
2965 i_ft2_bbox_r(font, cheight, cwidth, text, vlayout, utf8)
2966         Imager::Font::FT2 font
2967         double cheight
2968         double cwidth
2969         char *text
2970         int vlayout
2971         int utf8
2972       PREINIT:
2973         int bbox[8];
2974         int i;
2975       PPCODE:
2976 #ifdef SvUTF8
2977         if (SvUTF8(ST(3)))
2978           utf8 = 1;
2979 #endif
2980         if (i_ft2_bbox_r(font, cheight, cwidth, text, strlen(text), vlayout,
2981                          utf8, bbox)) {
2982           EXTEND(SP, 8);
2983           for (i = 0; i < 8; ++i)
2984             PUSHs(sv_2mortal(newSViv(bbox[i])));
2985         }
2986
2987 undef_int
2988 i_ft2_text(font, im, tx, ty, cl, cheight, cwidth, text, align, aa, vlayout, utf8)
2989         Imager::Font::FT2 font
2990         Imager::ImgRaw im
2991         int tx
2992         int ty
2993         Imager::Color cl
2994         double cheight
2995         double cwidth
2996         int align
2997         int aa
2998         int vlayout
2999         int utf8
3000       PREINIT:
3001         char *text;
3002         STRLEN len;
3003       CODE:
3004 #ifdef SvUTF8
3005         if (SvUTF8(ST(7))) {
3006           utf8 = 1;
3007         }
3008 #endif
3009         text = SvPV(ST(7), len);
3010         RETVAL = i_ft2_text(font, im, tx, ty, cl, cheight, cwidth, text,
3011                             len, align, aa, vlayout, utf8);
3012       OUTPUT:
3013         RETVAL
3014
3015 undef_int
3016 i_ft2_cp(font, im, tx, ty, channel, cheight, cwidth, text, align, aa, vlayout, utf8)
3017         Imager::Font::FT2 font
3018         Imager::ImgRaw im
3019         int tx
3020         int ty
3021         int channel
3022         double cheight
3023         double cwidth
3024         char *text
3025         int align
3026         int aa
3027         int vlayout
3028         int utf8
3029       CODE:
3030 #ifdef SvUTF8
3031         if (SvUTF8(ST(7)))
3032           utf8 = 1;
3033 #endif
3034         RETVAL = i_ft2_cp(font, im, tx, ty, channel, cheight, cwidth, text,
3035                           strlen(text), align, aa, vlayout, 1);
3036       OUTPUT:
3037         RETVAL
3038
3039 void
3040 ft2_transform_box(font, x0, x1, x2, x3)
3041         Imager::Font::FT2 font
3042         int x0
3043         int x1
3044         int x2
3045         int x3
3046       PREINIT:
3047         int box[4];
3048       PPCODE:
3049         box[0] = x0; box[1] = x1; box[2] = x2; box[3] = x3;
3050         ft2_transform_box(font, box);
3051           EXTEND(SP, 4);
3052           PUSHs(sv_2mortal(newSViv(box[0])));
3053           PUSHs(sv_2mortal(newSViv(box[1])));
3054           PUSHs(sv_2mortal(newSViv(box[2])));
3055           PUSHs(sv_2mortal(newSViv(box[3])));
3056         
3057 #endif
3058
3059 MODULE = Imager         PACKAGE = Imager::FillHandle PREFIX=IFILL_
3060
3061 void
3062 IFILL_DESTROY(fill)
3063         Imager::FillHandle fill
3064
3065 MODULE = Imager         PACKAGE = Imager
3066
3067 Imager::FillHandle
3068 i_new_fill_solid(cl, combine)
3069         Imager::Color cl
3070         int combine
3071
3072 Imager::FillHandle
3073 i_new_fill_solidf(cl, combine)
3074         Imager::Color::Float cl
3075         int combine
3076
3077 Imager::FillHandle
3078 i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy)
3079         Imager::Color fg
3080         Imager::Color bg
3081         int combine
3082         int hatch
3083         int dx
3084         int dy
3085       PREINIT:
3086         unsigned char *cust_hatch;
3087         STRLEN len;
3088       CODE:
3089         if (SvOK(ST(4))) {
3090           cust_hatch = SvPV(ST(4), len);
3091         }
3092         else
3093           cust_hatch = NULL;
3094         RETVAL = i_new_fill_hatch(fg, bg, combine, hatch, cust_hatch, dx, dy);
3095       OUTPUT:
3096         RETVAL
3097