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