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