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