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