setcolors() and addcolors() can now accept non-object colors like most
[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
3efb0915
TC
1501undef_int
1502i_flood_fill_border(im,seedx,seedy,dcol, border)
1503 Imager::ImgRaw im
1504 int seedx
1505 int seedy
1506 Imager::Color dcol
1507 Imager::Color border
1508
1509undef_int
1510i_flood_cfill_border(im,seedx,seedy,fill, border)
1511 Imager::ImgRaw im
1512 int seedx
1513 int seedy
1514 Imager::FillHandle fill
1515 Imager::Color border
1516
02d1d628
AMH
1517
1518void
1519i_copyto(im,src,x1,y1,x2,y2,tx,ty)
1520 Imager::ImgRaw im
1521 Imager::ImgRaw src
1522 int x1
1523 int y1
1524 int x2
1525 int y2
1526 int tx
1527 int ty
1528
1529
1530void
1531i_copyto_trans(im,src,x1,y1,x2,y2,tx,ty,trans)
1532 Imager::ImgRaw im
1533 Imager::ImgRaw src
1534 int x1
1535 int y1
1536 int x2
1537 int y2
1538 int tx
1539 int ty
1540 Imager::Color trans
1541
92bda632
TC
1542Imager::ImgRaw
1543i_copy(src)
02d1d628
AMH
1544 Imager::ImgRaw src
1545
1546
faa9b3e7 1547undef_int
71dc4a83 1548i_rubthru(im,src,tx,ty,src_minx,src_miny,src_maxx,src_maxy)
02d1d628
AMH
1549 Imager::ImgRaw im
1550 Imager::ImgRaw src
1551 int tx
1552 int ty
71dc4a83
AMH
1553 int src_minx
1554 int src_miny
1555 int src_maxx
1556 int src_maxy
1557
02d1d628 1558
142c26ff
AMH
1559undef_int
1560i_flipxy(im, direction)
1561 Imager::ImgRaw im
1562 int direction
1563
faa9b3e7
TC
1564Imager::ImgRaw
1565i_rotate90(im, degrees)
1566 Imager::ImgRaw im
1567 int degrees
1568
1569Imager::ImgRaw
0d3b936e 1570i_rotate_exact(im, amount, ...)
faa9b3e7
TC
1571 Imager::ImgRaw im
1572 double amount
0d3b936e
TC
1573 PREINIT:
1574 i_color *backp = NULL;
1575 i_fcolor *fbackp = NULL;
1576 int i;
1577 SV * sv1;
1578 CODE:
1579 /* extract the bg colors if any */
1580 /* yes, this is kind of strange */
1581 for (i = 2; i < items; ++i) {
1582 sv1 = ST(i);
1583 if (sv_derived_from(sv1, "Imager::Color")) {
1584 IV tmp = SvIV((SV*)SvRV(sv1));
1585 backp = INT2PTR(i_color *, tmp);
1586 }
1587 else if (sv_derived_from(sv1, "Imager::Color::Float")) {
1588 IV tmp = SvIV((SV*)SvRV(sv1));
1589 fbackp = INT2PTR(i_fcolor *, tmp);
1590 }
1591 }
1592 RETVAL = i_rotate_exact_bg(im, amount, backp, fbackp);
1593 OUTPUT:
1594 RETVAL
faa9b3e7
TC
1595
1596Imager::ImgRaw
0d3b936e 1597i_matrix_transform(im, xsize, ysize, matrix, ...)
faa9b3e7
TC
1598 Imager::ImgRaw im
1599 int xsize
1600 int ysize
1601 PREINIT:
1602 double matrix[9];
1603 AV *av;
1604 IV len;
1605 SV *sv1;
1606 int i;
0d3b936e
TC
1607 i_color *backp = NULL;
1608 i_fcolor *fbackp = NULL;
faa9b3e7
TC
1609 CODE:
1610 if (!SvROK(ST(3)) || SvTYPE(SvRV(ST(3))) != SVt_PVAV)
1611 croak("i_matrix_transform: parameter 4 must be an array ref\n");
1612 av=(AV*)SvRV(ST(3));
1613 len=av_len(av)+1;
1614 if (len > 9)
1615 len = 9;
1616 for (i = 0; i < len; ++i) {
1617 sv1=(*(av_fetch(av,i,0)));
1618 matrix[i] = SvNV(sv1);
1619 }
1620 for (; i < 9; ++i)
1621 matrix[i] = 0;
0d3b936e
TC
1622 /* extract the bg colors if any */
1623 /* yes, this is kind of strange */
1624 for (i = 4; i < items; ++i) {
1625 sv1 = ST(i);
1626 if (sv_derived_from(sv1, "Imager::Color")) {
1627 IV tmp = SvIV((SV*)SvRV(sv1));
1628 backp = INT2PTR(i_color *, tmp);
1629 }
1630 else if (sv_derived_from(sv1, "Imager::Color::Float")) {
1631 IV tmp = SvIV((SV*)SvRV(sv1));
1632 fbackp = INT2PTR(i_fcolor *, tmp);
1633 }
1634 }
1635 RETVAL = i_matrix_transform_bg(im, xsize, ysize, matrix, backp, fbackp);
faa9b3e7
TC
1636 OUTPUT:
1637 RETVAL
02d1d628
AMH
1638
1639void
1640i_gaussian(im,stdev)
1641 Imager::ImgRaw im
1642 float stdev
1643
b6381851
TC
1644void
1645i_unsharp_mask(im,stdev,scale)
1646 Imager::ImgRaw im
1647 float stdev
1648 double scale
1649
02d1d628
AMH
1650void
1651i_conv(im,pcoef)
1652 Imager::ImgRaw im
1653 PREINIT:
1654 float* coeff;
1655 int len;
1656 AV* av;
1657 SV* sv1;
1658 int i;
1659 PPCODE:
1660 if (!SvROK(ST(1))) croak("Imager: Parameter 1 must be a reference to an array\n");
1661 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 must be a reference to an array\n");
1662 av=(AV*)SvRV(ST(1));
1663 len=av_len(av)+1;
1664 coeff=mymalloc( len*sizeof(float) );
1665 for(i=0;i<len;i++) {
1666 sv1=(*(av_fetch(av,i,0)));
1667 coeff[i]=(float)SvNV(sv1);
1668 }
1669 i_conv(im,coeff,len);
1670 myfree(coeff);
1671
f5991c03
TC
1672undef_int
1673i_convert(im, src, coeff)
1674 Imager::ImgRaw im
1675 Imager::ImgRaw src
1676 PREINIT:
1677 float *coeff;
1678 int outchan;
1679 int inchan;
1680 AV *avmain;
1681 SV **temp;
f5991c03
TC
1682 AV *avsub;
1683 int len;
1684 int i, j;
1685 CODE:
f5991c03
TC
1686 if (!SvROK(ST(2)) || SvTYPE(SvRV(ST(2))) != SVt_PVAV)
1687 croak("i_convert: parameter 3 must be an arrayref\n");
1688 avmain = (AV*)SvRV(ST(2));
1689 outchan = av_len(avmain)+1;
1690 /* find the biggest */
1691 inchan = 0;
1692 for (j=0; j < outchan; ++j) {
1693 temp = av_fetch(avmain, j, 0);
1694 if (temp && SvROK(*temp) && SvTYPE(SvRV(*temp)) == SVt_PVAV) {
1695 avsub = (AV*)SvRV(*temp);
1696 len = av_len(avsub)+1;
1697 if (len > inchan)
1698 inchan = len;
1699 }
1700 }
1701 coeff = mymalloc(sizeof(float) * outchan * inchan);
1702 for (j = 0; j < outchan; ++j) {
1703 avsub = (AV*)SvRV(*av_fetch(avmain, j, 0));
1704 len = av_len(avsub)+1;
1705 for (i = 0; i < len; ++i) {
1706 temp = av_fetch(avsub, i, 0);
1707 if (temp)
1708 coeff[i+j*inchan] = SvNV(*temp);
1709 else
1710 coeff[i+j*inchan] = 0;
1711 }
1712 while (i < inchan)
1713 coeff[i++ + j*inchan] = 0;
1714 }
1715 RETVAL = i_convert(im, src, coeff, outchan, inchan);
1716 myfree(coeff);
f5991c03
TC
1717 OUTPUT:
1718 RETVAL
40eba1ea
AMH
1719
1720
1721void
1722i_map(im, pmaps)
1723 Imager::ImgRaw im
1724 PREINIT:
1725 unsigned int mask = 0;
1726 AV *avmain;
1727 AV *avsub;
1728 SV **temp;
1729 int len;
1730 int i, j;
1731 unsigned char (*maps)[256];
1732 CODE:
1733 if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV)
1734 croak("i_map: parameter 2 must be an arrayref\n");
1735 avmain = (AV*)SvRV(ST(1));
1736 len = av_len(avmain)+1;
1737 if (im->channels < len) len = im->channels;
1738
1739 maps = mymalloc( len * sizeof(unsigned char [256]) );
1740
1741 for (j=0; j<len ; j++) {
1742 temp = av_fetch(avmain, j, 0);
1743 if (temp && SvROK(*temp) && (SvTYPE(SvRV(*temp)) == SVt_PVAV) ) {
1744 avsub = (AV*)SvRV(*temp);
1745 if(av_len(avsub) != 255) continue;
1746 mask |= 1<<j;
1747 for (i=0; i<256 ; i++) {
9495ee93 1748 int val;
40eba1ea 1749 temp = av_fetch(avsub, i, 0);
9495ee93
AMH
1750 val = temp ? SvIV(*temp) : 0;
1751 if (val<0) val = 0;
1752 if (val>255) val = 255;
1753 maps[j][i] = val;
40eba1ea
AMH
1754 }
1755 }
1756 }
1757 i_map(im, maps, mask);
1758 myfree(maps);
1759
1760
1761
02d1d628
AMH
1762float
1763i_img_diff(im1,im2)
1764 Imager::ImgRaw im1
1765 Imager::ImgRaw im2
1766
1767
1768
1769undef_int
4cb58f1b
TC
1770i_init_fonts(t1log=0)
1771 int t1log
02d1d628
AMH
1772
1773#ifdef HAVE_LIBT1
1774
1775void
1776i_t1_set_aa(st)
1777 int st
1778
1779int
6b012d62 1780i_t1_new(pfb,afm)
02d1d628
AMH
1781 char* pfb
1782 char* afm
1783
1784int
1785i_t1_destroy(font_id)
1786 int font_id
1787
1788
1789undef_int
1bd75e4c 1790i_t1_cp(im,xb,yb,channel,fontnum,points,str_sv,len_ignored,align,utf8=0,flags="")
02d1d628
AMH
1791 Imager::ImgRaw im
1792 int xb
1793 int yb
1794 int channel
1795 int fontnum
1796 float points
1bd75e4c 1797 SV* str_sv
02d1d628 1798 int align
1bd75e4c
TC
1799 int utf8
1800 char* flags
1801 PREINIT:
1802 char *str;
1803 STRLEN len;
1804 CODE:
1805#ifdef SvUTF8
1806 if (SvUTF8(str_sv))
1807 utf8 = 1;
1808#endif
1809 str = SvPV(str_sv, len);
1810 RETVAL = i_t1_cp(im, xb,yb,channel,fontnum,points,str,len,align,
1811 utf8,flags);
1812 OUTPUT:
1813 RETVAL
1814
02d1d628
AMH
1815
1816void
1bd75e4c 1817i_t1_bbox(fontnum,point,str_sv,len_ignored,utf8=0,flags="")
02d1d628
AMH
1818 int fontnum
1819 float point
1bd75e4c
TC
1820 SV* str_sv
1821 int utf8
1822 char* flags
02d1d628 1823 PREINIT:
1bd75e4c
TC
1824 char *str;
1825 STRLEN len;
3799c4d1 1826 int cords[BOUNDING_BOX_COUNT];
1bd75e4c 1827 int i;
3799c4d1 1828 int rc;
02d1d628 1829 PPCODE:
1bd75e4c
TC
1830#ifdef SvUTF8
1831 if (SvUTF8(str_sv))
1832 utf8 = 1;
1833#endif
1834 str = SvPV(str_sv, len);
3799c4d1
TC
1835 rc = i_t1_bbox(fontnum,point,str,len,cords,utf8,flags);
1836 if (rc > 0) {
1837 EXTEND(SP, rc);
1838 for (i = 0; i < rc; ++i)
1839 PUSHs(sv_2mortal(newSViv(cords[i])));
1840 }
02d1d628
AMH
1841
1842
1843
1844undef_int
1bd75e4c 1845i_t1_text(im,xb,yb,cl,fontnum,points,str_sv,len_ignored,align,utf8=0,flags="")
02d1d628
AMH
1846 Imager::ImgRaw im
1847 int xb
1848 int yb
1849 Imager::Color cl
1850 int fontnum
1851 float points
1bd75e4c 1852 SV* str_sv
02d1d628 1853 int align
1bd75e4c
TC
1854 int utf8
1855 char* flags
1856 PREINIT:
1857 char *str;
1858 STRLEN len;
1859 CODE:
1860#ifdef SvUTF8
1861 if (SvUTF8(str_sv))
1862 utf8 = 1;
1863#endif
1864 str = SvPV(str_sv, len);
1865 RETVAL = i_t1_text(im, xb,yb,cl,fontnum,points,str,len,align,
1866 utf8,flags);
1867 OUTPUT:
1868 RETVAL
02d1d628 1869
3799c4d1
TC
1870void
1871i_t1_has_chars(handle, text_sv, utf8 = 0)
1872 int handle
1873 SV *text_sv
1874 int utf8
1875 PREINIT:
1876 char const *text;
1877 STRLEN len;
1878 char *work;
1879 int count;
1880 int i;
1881 PPCODE:
1882#ifdef SvUTF8
1883 if (SvUTF8(text_sv))
1884 utf8 = 1;
1885#endif
1886 text = SvPV(text_sv, len);
1887 work = mymalloc(len);
1888 count = i_t1_has_chars(handle, text, len, utf8, work);
1889 if (GIMME_V == G_ARRAY) {
1890 EXTEND(SP, count);
1891 for (i = 0; i < count; ++i) {
1892 PUSHs(sv_2mortal(newSViv(work[i])));
1893 }
1894 }
1895 else {
1896 EXTEND(SP, 1);
1897 PUSHs(sv_2mortal(newSVpv(work, count)));
1898 }
1899 myfree(work);
1900
1901void
1902i_t1_face_name(handle)
1903 int handle
1904 PREINIT:
1905 char name[255];
1906 int len;
1907 PPCODE:
1908 len = i_t1_face_name(handle, name, sizeof(name));
1909 if (len) {
1910 EXTEND(SP, 1);
1911 PUSHs(sv_2mortal(newSVpv(name, strlen(name))));
1912 }
1913
19fa4baf
AMH
1914void
1915i_t1_glyph_name(handle, text_sv, utf8 = 0)
3799c4d1
TC
1916 int handle
1917 SV *text_sv
1918 int utf8
1919 PREINIT:
1920 char const *text;
1921 STRLEN work_len;
1922 int len;
3799c4d1
TC
1923 char name[255];
1924 PPCODE:
1925#ifdef SvUTF8
1926 if (SvUTF8(text_sv))
1927 utf8 = 1;
1928#endif
1929 text = SvPV(text_sv, work_len);
1930 len = work_len;
1931 while (len) {
17892255 1932 unsigned long ch;
3799c4d1
TC
1933 if (utf8) {
1934 ch = i_utf8_advance(&text, &len);
1935 if (ch == ~0UL) {
1936 i_push_error(0, "invalid UTF8 character");
1937 break;
1938 }
1939 }
1940 else {
1941 ch = *text++;
1942 --len;
1943 }
1944 EXTEND(SP, 1);
f364e883 1945 if (i_t1_glyph_name(handle, ch, name, sizeof(name))) {
3799c4d1
TC
1946 PUSHs(sv_2mortal(newSVpv(name, 0)));
1947 }
1948 else {
1949 PUSHs(&PL_sv_undef);
1950 }
1951 }
1952
02d1d628
AMH
1953#endif
1954
1955#ifdef HAVE_LIBTT
1956
1957
4b19f77a 1958Imager::Font::TT
02d1d628
AMH
1959i_tt_new(fontname)
1960 char* fontname
1961
4b19f77a
AMH
1962
1963MODULE = Imager PACKAGE = Imager::Font::TT PREFIX=TT_
1964
1965#define TT_DESTROY(handle) i_tt_destroy(handle)
1966
02d1d628 1967void
4b19f77a
AMH
1968TT_DESTROY(handle)
1969 Imager::Font::TT handle
1970
02d1d628 1971
4b19f77a 1972MODULE = Imager PACKAGE = Imager
02d1d628
AMH
1973
1974
1975undef_int
9ab6338b 1976i_tt_text(handle,im,xb,yb,cl,points,str_sv,len_ignored,smooth,utf8,align=1)
4b19f77a 1977 Imager::Font::TT handle
02d1d628
AMH
1978 Imager::ImgRaw im
1979 int xb
1980 int yb
1981 Imager::Color cl
1982 float points
4f68b48f 1983 SV * str_sv
02d1d628 1984 int smooth
4f68b48f 1985 int utf8
9ab6338b 1986 int align
4f68b48f
TC
1987 PREINIT:
1988 char *str;
1989 STRLEN len;
1990 CODE:
1991#ifdef SvUTF8
1992 if (SvUTF8(str_sv))
1993 utf8 = 1;
1994#endif
1995 str = SvPV(str_sv, len);
1996 RETVAL = i_tt_text(handle, im, xb, yb, cl, points, str,
9ab6338b 1997 len, smooth, utf8, align);
4f68b48f
TC
1998 OUTPUT:
1999 RETVAL
02d1d628
AMH
2000
2001
2002undef_int
9ab6338b 2003i_tt_cp(handle,im,xb,yb,channel,points,str_sv,len_ignored,smooth,utf8,align=1)
4b19f77a 2004 Imager::Font::TT handle
02d1d628
AMH
2005 Imager::ImgRaw im
2006 int xb
2007 int yb
2008 int channel
2009 float points
4f68b48f 2010 SV * str_sv
02d1d628 2011 int smooth
4f68b48f 2012 int utf8
9ab6338b 2013 int align
4f68b48f
TC
2014 PREINIT:
2015 char *str;
2016 STRLEN len;
2017 CODE:
2018#ifdef SvUTF8
2019 if (SvUTF8(str_sv))
2020 utf8 = 1;
2021#endif
2022 str = SvPV(str_sv, len);
2023 RETVAL = i_tt_cp(handle, im, xb, yb, channel, points, str, len,
9ab6338b 2024 smooth, utf8, align);
4f68b48f
TC
2025 OUTPUT:
2026 RETVAL
02d1d628
AMH
2027
2028
a659442a 2029void
4f68b48f 2030i_tt_bbox(handle,point,str_sv,len_ignored, utf8)
4b19f77a 2031 Imager::Font::TT handle
02d1d628 2032 float point
4f68b48f 2033 SV* str_sv
4f68b48f 2034 int utf8
02d1d628 2035 PREINIT:
3799c4d1 2036 int cords[BOUNDING_BOX_COUNT],rc;
4f68b48f
TC
2037 char * str;
2038 STRLEN len;
3799c4d1 2039 int i;
02d1d628 2040 PPCODE:
4f68b48f
TC
2041#ifdef SvUTF8
2042 if (SvUTF8(ST(2)))
2043 utf8 = 1;
2044#endif
2045 str = SvPV(str_sv, len);
2046 if ((rc=i_tt_bbox(handle,point,str,len,cords, utf8))) {
3799c4d1
TC
2047 EXTEND(SP, rc);
2048 for (i = 0; i < rc; ++i) {
2049 PUSHs(sv_2mortal(newSViv(cords[i])));
2050 }
02d1d628
AMH
2051 }
2052
eeaa33fd
TC
2053void
2054i_tt_has_chars(handle, text_sv, utf8)
2055 Imager::Font::TT handle
2056 SV *text_sv
2057 int utf8
2058 PREINIT:
2059 char const *text;
2060 STRLEN len;
2061 char *work;
2062 int count;
2063 int i;
2064 PPCODE:
2065#ifdef SvUTF8
2066 if (SvUTF8(text_sv))
2067 utf8 = 1;
2068#endif
2069 text = SvPV(text_sv, len);
2070 work = mymalloc(len);
2071 count = i_tt_has_chars(handle, text, len, utf8, work);
2072 if (GIMME_V == G_ARRAY) {
2073 EXTEND(SP, count);
2074 for (i = 0; i < count; ++i) {
2075 PUSHs(sv_2mortal(newSViv(work[i])));
2076 }
2077 }
2078 else {
2079 EXTEND(SP, 1);
2080 PUSHs(sv_2mortal(newSVpv(work, count)));
2081 }
2082 myfree(work);
02d1d628 2083
3799c4d1
TC
2084void
2085i_tt_dump_names(handle)
2086 Imager::Font::TT handle
02d1d628 2087
3799c4d1
TC
2088void
2089i_tt_face_name(handle)
2090 Imager::Font::TT handle
2091 PREINIT:
2092 char name[255];
2093 int len;
2094 PPCODE:
2095 len = i_tt_face_name(handle, name, sizeof(name));
2096 if (len) {
2097 EXTEND(SP, 1);
2098 PUSHs(sv_2mortal(newSVpv(name, strlen(name))));
2099 }
02d1d628 2100
19fa4baf
AMH
2101void
2102i_tt_glyph_name(handle, text_sv, utf8 = 0)
3799c4d1
TC
2103 Imager::Font::TT handle
2104 SV *text_sv
2105 int utf8
2106 PREINIT:
2107 char const *text;
2108 STRLEN work_len;
2109 int len;
2110 int outsize;
2111 char name[255];
2112 PPCODE:
2113#ifdef SvUTF8
2114 if (SvUTF8(text_sv))
2115 utf8 = 1;
2116#endif
2117 text = SvPV(text_sv, work_len);
2118 len = work_len;
2119 while (len) {
17892255 2120 unsigned long ch;
3799c4d1
TC
2121 if (utf8) {
2122 ch = i_utf8_advance(&text, &len);
2123 if (ch == ~0UL) {
2124 i_push_error(0, "invalid UTF8 character");
2125 break;
2126 }
2127 }
2128 else {
2129 ch = *text++;
2130 --len;
2131 }
2132 EXTEND(SP, 1);
af070d99 2133 if ((outsize = i_tt_glyph_name(handle, ch, name, sizeof(name))) != 0) {
3799c4d1
TC
2134 PUSHs(sv_2mortal(newSVpv(name, 0)));
2135 }
2136 else {
2137 PUSHs(&PL_sv_undef);
2138 }
2139 }
2140
2141#endif
02d1d628
AMH
2142
2143
2144#ifdef HAVE_LIBJPEG
2145undef_int
dd55acc8 2146i_writejpeg_wiol(im, ig, qfactor)
02d1d628 2147 Imager::ImgRaw im
dd55acc8 2148 Imager::IO ig
02d1d628
AMH
2149 int qfactor
2150
02d1d628
AMH
2151
2152void
2153i_readjpeg_wiol(ig)
2154 Imager::IO ig
2155 PREINIT:
2156 char* iptc_itext;
2157 int tlength;
2158 i_img* rimg;
2159 SV* r;
2160 PPCODE:
2161 iptc_itext = NULL;
2162 rimg = i_readjpeg_wiol(ig,-1,&iptc_itext,&tlength);
2163 if (iptc_itext == NULL) {
2164 r = sv_newmortal();
2165 EXTEND(SP,1);
2166 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2167 PUSHs(r);
2168 } else {
2169 r = sv_newmortal();
2170 EXTEND(SP,2);
2171 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2172 PUSHs(r);
2173 PUSHs(sv_2mortal(newSVpv(iptc_itext,tlength)));
2174 myfree(iptc_itext);
2175 }
2176
f7450478
TC
2177int
2178i_exif_enabled()
02d1d628
AMH
2179
2180#endif
2181
2182
53a6bbd4 2183const char *
e10bf46e
AMH
2184i_test_format_probe(ig, length)
2185 Imager::IO ig
2186 int length
2187
02d1d628
AMH
2188
2189
2190#ifdef HAVE_LIBTIFF
2191
2192Imager::ImgRaw
8f8bd9aa 2193i_readtiff_wiol(ig, length, page=0)
02d1d628
AMH
2194 Imager::IO ig
2195 int length
8f8bd9aa 2196 int page
02d1d628 2197
10461f9a
TC
2198void
2199i_readtiff_multi_wiol(ig, length)
2200 Imager::IO ig
2201 int length
2202 PREINIT:
2203 i_img **imgs;
2204 int count;
2205 int i;
2206 PPCODE:
2207 imgs = i_readtiff_multi_wiol(ig, length, &count);
2208 if (imgs) {
2209 EXTEND(SP, count);
2210 for (i = 0; i < count; ++i) {
2211 SV *sv = sv_newmortal();
2212 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2213 PUSHs(sv);
2214 }
2215 myfree(imgs);
2216 }
2217
02d1d628
AMH
2218
2219undef_int
2220i_writetiff_wiol(im, ig)
2221 Imager::ImgRaw im
2222 Imager::IO ig
2223
10461f9a
TC
2224undef_int
2225i_writetiff_multi_wiol(ig, ...)
2226 Imager::IO ig
2227 PREINIT:
2228 int i;
2229 int img_count;
2230 i_img **imgs;
2231 CODE:
2232 if (items < 2)
2233 croak("Usage: i_writetiff_multi_wiol(ig, images...)");
2234 img_count = items - 1;
2235 RETVAL = 1;
2236 if (img_count < 1) {
2237 RETVAL = 0;
2238 i_clear_error();
2239 i_push_error(0, "You need to specify images to save");
2240 }
2241 else {
2242 imgs = mymalloc(sizeof(i_img *) * img_count);
2243 for (i = 0; i < img_count; ++i) {
2244 SV *sv = ST(1+i);
2245 imgs[i] = NULL;
2246 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
4c4c2ffd 2247 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(sv)));
10461f9a
TC
2248 }
2249 else {
2250 i_clear_error();
2251 i_push_error(0, "Only images can be saved");
2252 myfree(imgs);
2253 RETVAL = 0;
2254 break;
2255 }
2256 }
2257 if (RETVAL) {
2258 RETVAL = i_writetiff_multi_wiol(ig, imgs, img_count);
2259 }
2260 myfree(imgs);
2261 }
2262 OUTPUT:
2263 RETVAL
2264
d2dfdcc9 2265undef_int
4c2d6970 2266i_writetiff_wiol_faxable(im, ig, fine)
d2dfdcc9
TC
2267 Imager::ImgRaw im
2268 Imager::IO ig
4c2d6970 2269 int fine
d2dfdcc9 2270
10461f9a
TC
2271undef_int
2272i_writetiff_multi_wiol_faxable(ig, fine, ...)
2273 Imager::IO ig
2274 int fine
2275 PREINIT:
2276 int i;
2277 int img_count;
2278 i_img **imgs;
2279 CODE:
2280 if (items < 3)
2281 croak("Usage: i_writetiff_multi_wiol_faxable(ig, fine, images...)");
2282 img_count = items - 2;
2283 RETVAL = 1;
2284 if (img_count < 1) {
2285 RETVAL = 0;
2286 i_clear_error();
2287 i_push_error(0, "You need to specify images to save");
2288 }
2289 else {
2290 imgs = mymalloc(sizeof(i_img *) * img_count);
2291 for (i = 0; i < img_count; ++i) {
2292 SV *sv = ST(2+i);
2293 imgs[i] = NULL;
2294 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
4c4c2ffd 2295 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(sv)));
10461f9a
TC
2296 }
2297 else {
2298 i_clear_error();
2299 i_push_error(0, "Only images can be saved");
2300 myfree(imgs);
2301 RETVAL = 0;
2302 break;
2303 }
2304 }
2305 if (RETVAL) {
2306 RETVAL = i_writetiff_multi_wiol_faxable(ig, imgs, img_count, fine);
2307 }
2308 myfree(imgs);
2309 }
2310 OUTPUT:
2311 RETVAL
02d1d628
AMH
2312
2313
10461f9a 2314#endif /* HAVE_LIBTIFF */
02d1d628
AMH
2315
2316
2317#ifdef HAVE_LIBPNG
2318
2319Imager::ImgRaw
790923a4
AMH
2320i_readpng_wiol(ig, length)
2321 Imager::IO ig
2322 int length
02d1d628
AMH
2323
2324
2325undef_int
790923a4 2326i_writepng_wiol(im, ig)
02d1d628 2327 Imager::ImgRaw im
790923a4 2328 Imager::IO ig
02d1d628
AMH
2329
2330
2331#endif
2332
2333
2334#ifdef HAVE_LIBGIF
2335
03bd24d4
TC
2336void
2337i_giflib_version()
2338 PPCODE:
2339 PUSHs(sv_2mortal(newSVnv(IM_GIFMAJOR+IM_GIFMINOR*0.1)));
2340
02d1d628
AMH
2341undef_int
2342i_writegif(im,fd,colors,pixdev,fixed)
2343 Imager::ImgRaw im
2344 int fd
2345 int colors
2346 int pixdev
2347 PREINIT:
2348 int fixedlen;
2349 Imager__Color fixed;
2350 Imager__Color tmp;
2351 AV* av;
2352 SV* sv1;
2353 IV Itmp;
2354 int i;
2355 CODE:
2356 if (!SvROK(ST(4))) croak("Imager: Parameter 4 must be a reference to an array\n");
2357 if (SvTYPE(SvRV(ST(4))) != SVt_PVAV) croak("Imager: Parameter 4 must be a reference to an array\n");
2358 av=(AV*)SvRV(ST(4));
2359 fixedlen=av_len(av)+1;
2360 fixed=mymalloc( fixedlen*sizeof(i_color) );
2361 for(i=0;i<fixedlen;i++) {
2362 sv1=(*(av_fetch(av,i,0)));
2363 if (sv_derived_from(sv1, "Imager::Color")) {
2364 Itmp = SvIV((SV*)SvRV(sv1));
d5fbe3ee 2365 tmp = INT2PTR(i_color*, Itmp);
02d1d628
AMH
2366 } else croak("Imager: one of the elements of array ref is not of Imager::Color type\n");
2367 fixed[i]=*tmp;
2368 }
2369 RETVAL=i_writegif(im,fd,colors,pixdev,fixedlen,fixed);
2370 myfree(fixed);
2371 ST(0) = sv_newmortal();
2372 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2373 else sv_setiv(ST(0), (IV)RETVAL);
2374
2375
2376
2377
2378undef_int
2379i_writegifmc(im,fd,colors)
067d6bdc 2380 Imager::ImgRaw im
02d1d628
AMH
2381 int fd
2382 int colors
2383
02d1d628
AMH
2384
2385undef_int
2386i_writegif_gen(fd, ...)
2387 int fd
2388 PROTOTYPE: $$@
2389 PREINIT:
2390 i_quantize quant;
02d1d628
AMH
2391 i_img **imgs = NULL;
2392 int img_count;
2393 int i;
2394 HV *hv;
2395 CODE:
2396 if (items < 3)
2397 croak("Usage: i_writegif_gen(fd,hashref, images...)");
2398 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2399 croak("i_writegif_gen: Second argument must be a hash ref");
2400 hv = (HV *)SvRV(ST(1));
2401 memset(&quant, 0, sizeof(quant));
2402 quant.mc_size = 256;
02d1d628 2403 handle_quant_opts(&quant, hv);
02d1d628
AMH
2404 img_count = items - 2;
2405 RETVAL = 1;
2406 if (img_count < 1) {
2407 RETVAL = 0;
95b44a76
TC
2408 i_clear_error();
2409 i_push_error(0, "You need to specify images to save");
02d1d628
AMH
2410 }
2411 else {
2412 imgs = mymalloc(sizeof(i_img *) * img_count);
2413 for (i = 0; i < img_count; ++i) {
2414 SV *sv = ST(2+i);
2415 imgs[i] = NULL;
2416 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
4c4c2ffd 2417 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(sv)));
02d1d628
AMH
2418 }
2419 else {
95b44a76
TC
2420 i_clear_error();
2421 i_push_error(0, "Only images can be saved");
02d1d628
AMH
2422 RETVAL = 0;
2423 break;
2424 }
2425 }
2426 if (RETVAL) {
97c4effc 2427 RETVAL = i_writegif_gen(&quant, fd, imgs, img_count);
02d1d628
AMH
2428 }
2429 myfree(imgs);
2430 if (RETVAL) {
2431 copy_colors_back(hv, &quant);
2432 }
2433 }
a73aeb5f
AMH
2434 ST(0) = sv_newmortal();
2435 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2436 else sv_setiv(ST(0), (IV)RETVAL);
46a04ceb 2437 cleanup_quant_opts(&quant);
a73aeb5f 2438
02d1d628
AMH
2439
2440undef_int
2441i_writegif_callback(cb, maxbuffer,...)
2442 int maxbuffer;
2443 PREINIT:
2444 i_quantize quant;
02d1d628
AMH
2445 i_img **imgs = NULL;
2446 int img_count;
2447 int i;
2448 HV *hv;
2449 i_writer_data wd;
2450 CODE:
2451 if (items < 4)
2452 croak("Usage: i_writegif_callback(\\&callback,maxbuffer,hashref, images...)");
2453 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
2454 croak("i_writegif_callback: Second argument must be a hash ref");
2455 hv = (HV *)SvRV(ST(2));
2456 memset(&quant, 0, sizeof(quant));
2457 quant.mc_size = 256;
02d1d628 2458 handle_quant_opts(&quant, hv);
02d1d628
AMH
2459 img_count = items - 3;
2460 RETVAL = 1;
2461 if (img_count < 1) {
2462 RETVAL = 0;
2463 }
2464 else {
2465 imgs = mymalloc(sizeof(i_img *) * img_count);
2466 for (i = 0; i < img_count; ++i) {
2467 SV *sv = ST(3+i);
2468 imgs[i] = NULL;
2469 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
4c4c2ffd 2470 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(sv)));
02d1d628
AMH
2471 }
2472 else {
2473 RETVAL = 0;
2474 break;
2475 }
2476 }
2477 if (RETVAL) {
2478 wd.sv = ST(0);
97c4effc 2479 RETVAL = i_writegif_callback(&quant, write_callback, (char *)&wd, maxbuffer, imgs, img_count);
02d1d628
AMH
2480 }
2481 myfree(imgs);
2482 if (RETVAL) {
2483 copy_colors_back(hv, &quant);
2484 }
2485 }
46a04ceb
TC
2486 ST(0) = sv_newmortal();
2487 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2488 else sv_setiv(ST(0), (IV)RETVAL);
46a04ceb 2489 cleanup_quant_opts(&quant);
02d1d628 2490
10461f9a
TC
2491undef_int
2492i_writegif_wiol(ig, opts,...)
2493 Imager::IO ig
2494 PREINIT:
2495 i_quantize quant;
10461f9a
TC
2496 i_img **imgs = NULL;
2497 int img_count;
2498 int i;
2499 HV *hv;
2500 CODE:
2501 if (items < 3)
2502 croak("Usage: i_writegif_wiol(IO,hashref, images...)");
2503 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2504 croak("i_writegif_callback: Second argument must be a hash ref");
2505 hv = (HV *)SvRV(ST(1));
2506 memset(&quant, 0, sizeof(quant));
2507 quant.mc_size = 256;
10461f9a 2508 handle_quant_opts(&quant, hv);
10461f9a
TC
2509 img_count = items - 2;
2510 RETVAL = 1;
2511 if (img_count < 1) {
2512 RETVAL = 0;
2513 }
2514 else {
2515 imgs = mymalloc(sizeof(i_img *) * img_count);
2516 for (i = 0; i < img_count; ++i) {
2517 SV *sv = ST(2+i);
2518 imgs[i] = NULL;
2519 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
4c4c2ffd 2520 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(sv)));
10461f9a
TC
2521 }
2522 else {
2523 RETVAL = 0;
2524 break;
2525 }
2526 }
2527 if (RETVAL) {
97c4effc 2528 RETVAL = i_writegif_wiol(ig, &quant, imgs, img_count);
10461f9a
TC
2529 }
2530 myfree(imgs);
2531 if (RETVAL) {
2532 copy_colors_back(hv, &quant);
2533 }
2534 }
2535 ST(0) = sv_newmortal();
2536 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2537 else sv_setiv(ST(0), (IV)RETVAL);
10461f9a
TC
2538 cleanup_quant_opts(&quant);
2539
02d1d628
AMH
2540void
2541i_readgif(fd)
2542 int fd
2543 PREINIT:
2544 int* colour_table;
2545 int colours, q, w;
2546 i_img* rimg;
2547 SV* temp[3];
2548 AV* ct;
2549 SV* r;
2550 PPCODE:
2551 colour_table = NULL;
2552 colours = 0;
2553
895dbd34 2554 if(GIMME_V == G_ARRAY) {
02d1d628
AMH
2555 rimg = i_readgif(fd,&colour_table,&colours);
2556 } else {
2557 /* don't waste time with colours if they aren't wanted */
2558 rimg = i_readgif(fd,NULL,NULL);
2559 }
895dbd34 2560
02d1d628
AMH
2561 if (colour_table == NULL) {
2562 EXTEND(SP,1);
2563 r=sv_newmortal();
2564 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2565 PUSHs(r);
2566 } else {
2567 /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
2568 /* I don't know if I have the reference counts right or not :( */
2569 /* Neither do I :-) */
2570 /* No Idea here either */
2571
2572 ct=newAV();
2573 av_extend(ct, colours);
2574 for(q=0; q<colours; q++) {
2575 for(w=0; w<3; w++)
2576 temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
2577 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
2578 }
2579 myfree(colour_table);
895dbd34 2580
02d1d628 2581 EXTEND(SP,2);
895dbd34 2582 r = sv_newmortal();
02d1d628
AMH
2583 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2584 PUSHs(r);
2585 PUSHs(newRV_noinc((SV*)ct));
2586 }
2587
10461f9a
TC
2588void
2589i_readgif_wiol(ig)
2590 Imager::IO ig
2591 PREINIT:
2592 int* colour_table;
2593 int colours, q, w;
2594 i_img* rimg;
2595 SV* temp[3];
2596 AV* ct;
2597 SV* r;
2598 PPCODE:
2599 colour_table = NULL;
2600 colours = 0;
02d1d628 2601
10461f9a
TC
2602 if(GIMME_V == G_ARRAY) {
2603 rimg = i_readgif_wiol(ig,&colour_table,&colours);
2604 } else {
2605 /* don't waste time with colours if they aren't wanted */
2606 rimg = i_readgif_wiol(ig,NULL,NULL);
2607 }
2608
2609 if (colour_table == NULL) {
2610 EXTEND(SP,1);
2611 r=sv_newmortal();
2612 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2613 PUSHs(r);
2614 } else {
2615 /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
2616 /* I don't know if I have the reference counts right or not :( */
2617 /* Neither do I :-) */
2618 /* No Idea here either */
02d1d628 2619
10461f9a
TC
2620 ct=newAV();
2621 av_extend(ct, colours);
2622 for(q=0; q<colours; q++) {
2623 for(w=0; w<3; w++)
2624 temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
2625 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
2626 }
2627 myfree(colour_table);
02d1d628 2628
10461f9a
TC
2629 EXTEND(SP,2);
2630 r = sv_newmortal();
2631 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2632 PUSHs(r);
2633 PUSHs(newRV_noinc((SV*)ct));
2634 }
02d1d628 2635
f1adece7
TC
2636Imager::ImgRaw
2637i_readgif_single_wiol(ig, page=0)
2638 Imager::IO ig
2639 int page
2640
02d1d628
AMH
2641void
2642i_readgif_scalar(...)
2643 PROTOTYPE: $
2644 PREINIT:
2645 char* data;
21e952df 2646 STRLEN length;
02d1d628
AMH
2647 int* colour_table;
2648 int colours, q, w;
2649 i_img* rimg;
2650 SV* temp[3];
2651 AV* ct;
2652 SV* r;
2653 PPCODE:
2654 data = (char *)SvPV(ST(0), length);
2655 colour_table=NULL;
2656 colours=0;
2657
2658 if(GIMME_V == G_ARRAY) {
2659 rimg=i_readgif_scalar(data,length,&colour_table,&colours);
2660 } else {
2661 /* don't waste time with colours if they aren't wanted */
2662 rimg=i_readgif_scalar(data,length,NULL,NULL);
2663 }
2664
2665 if (colour_table == NULL) {
2666 EXTEND(SP,1);
2667 r=sv_newmortal();
2668 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2669 PUSHs(r);
2670 } else {
2671 /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
2672 /* I don't know if I have the reference counts right or not :( */
2673 /* Neither do I :-) */
2674 ct=newAV();
2675 av_extend(ct, colours);
2676 for(q=0; q<colours; q++) {
2677 for(w=0; w<3; w++)
2678 temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
2679 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
2680 }
2681 myfree(colour_table);
2682
2683 EXTEND(SP,2);
2684 r=sv_newmortal();
2685 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2686 PUSHs(r);
2687 PUSHs(newRV_noinc((SV*)ct));
2688 }
2689
2690void
2691i_readgif_callback(...)
2692 PROTOTYPE: &
2693 PREINIT:
02d1d628
AMH
2694 int* colour_table;
2695 int colours, q, w;
2696 i_img* rimg;
2697 SV* temp[3];
2698 AV* ct;
2699 SV* r;
2700 i_reader_data rd;
2701 PPCODE:
2702 rd.sv = ST(0);
2703 colour_table=NULL;
2704 colours=0;
2705
2706 if(GIMME_V == G_ARRAY) {
2707 rimg=i_readgif_callback(read_callback, (char *)&rd,&colour_table,&colours);
2708 } else {
2709 /* don't waste time with colours if they aren't wanted */
2710 rimg=i_readgif_callback(read_callback, (char *)&rd,NULL,NULL);
2711 }
2712
2713 if (colour_table == NULL) {
2714 EXTEND(SP,1);
2715 r=sv_newmortal();
2716 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2717 PUSHs(r);
2718 } else {
2719 /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
2720 /* I don't know if I have the reference counts right or not :( */
2721 /* Neither do I :-) */
2722 /* Neither do I - maybe I'll move this somewhere */
2723 ct=newAV();
2724 av_extend(ct, colours);
2725 for(q=0; q<colours; q++) {
2726 for(w=0; w<3; w++)
2727 temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
2728 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
2729 }
2730 myfree(colour_table);
2731
2732 EXTEND(SP,2);
2733 r=sv_newmortal();
2734 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2735 PUSHs(r);
2736 PUSHs(newRV_noinc((SV*)ct));
2737 }
2738
faa9b3e7
TC
2739void
2740i_readgif_multi(fd)
2741 int fd
2742 PREINIT:
2743 i_img **imgs;
2744 int count;
2745 int i;
2746 PPCODE:
2747 imgs = i_readgif_multi(fd, &count);
2748 if (imgs) {
2749 EXTEND(SP, count);
2750 for (i = 0; i < count; ++i) {
2751 SV *sv = sv_newmortal();
2752 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2753 PUSHs(sv);
2754 }
2755 myfree(imgs);
2756 }
02d1d628 2757
faa9b3e7
TC
2758void
2759i_readgif_multi_scalar(data)
2760 PREINIT:
2761 i_img **imgs;
2762 int count;
2763 char *data;
21e952df 2764 STRLEN length;
faa9b3e7
TC
2765 int i;
2766 PPCODE:
2767 data = (char *)SvPV(ST(0), length);
2768 imgs = i_readgif_multi_scalar(data, length, &count);
2769 if (imgs) {
2770 EXTEND(SP, count);
2771 for (i = 0; i < count; ++i) {
2772 SV *sv = sv_newmortal();
2773 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2774 PUSHs(sv);
2775 }
2776 myfree(imgs);
2777 }
02d1d628 2778
faa9b3e7
TC
2779void
2780i_readgif_multi_callback(cb)
2781 PREINIT:
2782 i_reader_data rd;
2783 i_img **imgs;
2784 int count;
2785 int i;
2786 PPCODE:
2787 rd.sv = ST(0);
2788 imgs = i_readgif_multi_callback(read_callback, (char *)&rd, &count);
2789 if (imgs) {
2790 EXTEND(SP, count);
2791 for (i = 0; i < count; ++i) {
2792 SV *sv = sv_newmortal();
2793 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2794 PUSHs(sv);
2795 }
2796 myfree(imgs);
2797 }
02d1d628 2798
10461f9a
TC
2799void
2800i_readgif_multi_wiol(ig)
2801 Imager::IO ig
2802 PREINIT:
2803 i_img **imgs;
2804 int count;
2805 int i;
2806 PPCODE:
2807 imgs = i_readgif_multi_wiol(ig, &count);
2808 if (imgs) {
2809 EXTEND(SP, count);
2810 for (i = 0; i < count; ++i) {
2811 SV *sv = sv_newmortal();
2812 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2813 PUSHs(sv);
2814 }
2815 myfree(imgs);
2816 }
2817
2818
02d1d628
AMH
2819#endif
2820
2821
2822
2823Imager::ImgRaw
2824i_readpnm_wiol(ig, length)
2825 Imager::IO ig
2826 int length
2827
2828
067d6bdc
AMH
2829undef_int
2830i_writeppm_wiol(im, ig)
2831 Imager::ImgRaw im
2832 Imager::IO ig
2833
2834
02d1d628 2835Imager::ImgRaw
895dbd34
AMH
2836i_readraw_wiol(ig,x,y,datachannels,storechannels,intrl)
2837 Imager::IO ig
02d1d628
AMH
2838 int x
2839 int y
2840 int datachannels
2841 int storechannels
2842 int intrl
2843
2844undef_int
895dbd34 2845i_writeraw_wiol(im,ig)
02d1d628 2846 Imager::ImgRaw im
895dbd34
AMH
2847 Imager::IO ig
2848
261f91c5
TC
2849undef_int
2850i_writebmp_wiol(im,ig)
2851 Imager::ImgRaw im
2852 Imager::IO ig
02d1d628 2853
705fd961
TC
2854Imager::ImgRaw
2855i_readbmp_wiol(ig)
2856 Imager::IO ig
2857
1ec86afa
AMH
2858
2859undef_int
febba01f 2860i_writetga_wiol(im,ig, wierdpack, compress, idstring)
1ec86afa
AMH
2861 Imager::ImgRaw im
2862 Imager::IO ig
febba01f
AMH
2863 int wierdpack
2864 int compress
2865 char* idstring
2866 PREINIT:
febba01f
AMH
2867 int idlen;
2868 CODE:
2869 idlen = SvCUR(ST(4));
2870 RETVAL = i_writetga_wiol(im, ig, wierdpack, compress, idstring, idlen);
2871 OUTPUT:
2872 RETVAL
2873
1ec86afa
AMH
2874
2875Imager::ImgRaw
2876i_readtga_wiol(ig, length)
2877 Imager::IO ig
2878 int length
2879
2880
737a830c
AMH
2881undef_int
2882i_writergb_wiol(im,ig, wierdpack, compress, idstring)
2883 Imager::ImgRaw im
2884 Imager::IO ig
2885 int wierdpack
2886 int compress
2887 char* idstring
2888 PREINIT:
737a830c
AMH
2889 int idlen;
2890 CODE:
2891 idlen = SvCUR(ST(4));
2892 RETVAL = i_writergb_wiol(im, ig, wierdpack, compress, idstring, idlen);
2893 OUTPUT:
2894 RETVAL
2895
2896
2897Imager::ImgRaw
2898i_readrgb_wiol(ig, length)
2899 Imager::IO ig
2900 int length
2901
2902
2903
02d1d628
AMH
2904Imager::ImgRaw
2905i_scaleaxis(im,Value,Axis)
2906 Imager::ImgRaw im
2907 float Value
2908 int Axis
2909
2910Imager::ImgRaw
2911i_scale_nn(im,scx,scy)
2912 Imager::ImgRaw im
2913 float scx
2914 float scy
2915
2916Imager::ImgRaw
2917i_haar(im)
2918 Imager::ImgRaw im
2919
2920int
2921i_count_colors(im,maxc)
2922 Imager::ImgRaw im
2923 int maxc
2924
2925
2926Imager::ImgRaw
2927i_transform(im,opx,opy,parm)
2928 Imager::ImgRaw im
2929 PREINIT:
2930 double* parm;
2931 int* opx;
2932 int* opy;
2933 int opxl;
2934 int opyl;
2935 int parmlen;
2936 AV* av;
2937 SV* sv1;
2938 int i;
2939 CODE:
2940 if (!SvROK(ST(1))) croak("Imager: Parameter 1 must be a reference to an array\n");
2941 if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to an array\n");
2942 if (!SvROK(ST(3))) croak("Imager: Parameter 3 must be a reference to an array\n");
2943 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 must be a reference to an array\n");
2944 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 2 must be a reference to an array\n");
2945 if (SvTYPE(SvRV(ST(3))) != SVt_PVAV) croak("Imager: Parameter 3 must be a reference to an array\n");
2946 av=(AV*)SvRV(ST(1));
2947 opxl=av_len(av)+1;
2948 opx=mymalloc( opxl*sizeof(int) );
2949 for(i=0;i<opxl;i++) {
2950 sv1=(*(av_fetch(av,i,0)));
2951 opx[i]=(int)SvIV(sv1);
2952 }
2953 av=(AV*)SvRV(ST(2));
2954 opyl=av_len(av)+1;
2955 opy=mymalloc( opyl*sizeof(int) );
2956 for(i=0;i<opyl;i++) {
2957 sv1=(*(av_fetch(av,i,0)));
2958 opy[i]=(int)SvIV(sv1);
2959 }
2960 av=(AV*)SvRV(ST(3));
2961 parmlen=av_len(av)+1;
2962 parm=mymalloc( parmlen*sizeof(double) );
2963 for(i=0;i<parmlen;i++) { /* FIXME: Bug? */
2964 sv1=(*(av_fetch(av,i,0)));
2965 parm[i]=(double)SvNV(sv1);
2966 }
2967 RETVAL=i_transform(im,opx,opxl,opy,opyl,parm,parmlen);
2968 myfree(parm);
2969 myfree(opy);
2970 myfree(opx);
2971 ST(0) = sv_newmortal();
2972 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2973 else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
2974
2975Imager::ImgRaw
e5744e01
TC
2976i_transform2(sv_width,sv_height,channels,sv_ops,av_n_regs,av_c_regs,av_in_imgs)
2977 SV *sv_width
2978 SV *sv_height
2979 SV *sv_ops
2980 AV *av_n_regs
2981 AV *av_c_regs
2982 AV *av_in_imgs
2983 int channels
02d1d628
AMH
2984 PREINIT:
2985 int width;
2986 int height;
02d1d628 2987 struct rm_op *ops;
953209f8 2988 STRLEN ops_len;
02d1d628
AMH
2989 int ops_count;
2990 double *n_regs;
2991 int n_regs_count;
2992 i_color *c_regs;
2993 int c_regs_count;
2994 int in_imgs_count;
2995 i_img **in_imgs;
ea9e6c3f 2996 SV *sv1;
02d1d628
AMH
2997 IV tmp;
2998 int i;
2999 CODE:
e5744e01
TC
3000
3001 in_imgs_count = av_len(av_in_imgs)+1;
3002 for (i = 0; i < in_imgs_count; ++i) {
3003 sv1 = *av_fetch(av_in_imgs, i, 0);
3004 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
3005 croak("sv_in_img must contain only images");
02d1d628
AMH
3006 }
3007 }
b8c2033e 3008 if (in_imgs_count > 0) {
02d1d628
AMH
3009 in_imgs = mymalloc(in_imgs_count*sizeof(i_img*));
3010 for (i = 0; i < in_imgs_count; ++i) {
e5744e01 3011 sv1 = *av_fetch(av_in_imgs,i,0);
02d1d628
AMH
3012 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
3013 croak("Parameter 5 must contain only images");
3014 }
3015 tmp = SvIV((SV*)SvRV(sv1));
e375fbd8 3016 in_imgs[i] = INT2PTR(i_img*, tmp);
02d1d628
AMH
3017 }
3018 }
3019 else {
3020 /* no input images */
3021 in_imgs = NULL;
3022 }
3023 /* default the output size from the first input if possible */
e5744e01
TC
3024 if (SvOK(sv_width))
3025 width = SvIV(sv_width);
02d1d628
AMH
3026 else if (in_imgs_count)
3027 width = in_imgs[0]->xsize;
3028 else
3029 croak("No output image width supplied");
3030
e5744e01
TC
3031 if (SvOK(sv_height))
3032 height = SvIV(sv_height);
02d1d628
AMH
3033 else if (in_imgs_count)
3034 height = in_imgs[0]->ysize;
3035 else
3036 croak("No output image height supplied");
3037
e5744e01 3038 ops = (struct rm_op *)SvPV(sv_ops, ops_len);
02d1d628
AMH
3039 if (ops_len % sizeof(struct rm_op))
3040 croak("Imager: Parameter 3 must be a bitmap of regops\n");
3041 ops_count = ops_len / sizeof(struct rm_op);
e5744e01
TC
3042
3043 n_regs_count = av_len(av_n_regs)+1;
02d1d628
AMH
3044 n_regs = mymalloc(n_regs_count * sizeof(double));
3045 for (i = 0; i < n_regs_count; ++i) {
e5744e01 3046 sv1 = *av_fetch(av_n_regs,i,0);
02d1d628
AMH
3047 if (SvOK(sv1))
3048 n_regs[i] = SvNV(sv1);
3049 }
e5744e01 3050 c_regs_count = av_len(av_c_regs)+1;
02d1d628
AMH
3051 c_regs = mymalloc(c_regs_count * sizeof(i_color));
3052 /* I don't bother initializing the colou?r registers */
3053
e5744e01 3054 RETVAL=i_transform2(width, height, channels, ops, ops_count,
02d1d628
AMH
3055 n_regs, n_regs_count,
3056 c_regs, c_regs_count, in_imgs, in_imgs_count);
3057 if (in_imgs)
3058 myfree(in_imgs);
3059 myfree(n_regs);
3060 myfree(c_regs);
3061 ST(0) = sv_newmortal();
3062 if (RETVAL == 0) ST(0)=&PL_sv_undef;
3063 else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
3064
3065
3066void
3067i_contrast(im,intensity)
3068 Imager::ImgRaw im
3069 float intensity
3070
3071void
3072i_hardinvert(im)
3073 Imager::ImgRaw im
3074
3075void
3076i_noise(im,amount,type)
3077 Imager::ImgRaw im
3078 float amount
3079 unsigned char type
3080
3081void
3082i_bumpmap(im,bump,channel,light_x,light_y,strength)
3083 Imager::ImgRaw im
3084 Imager::ImgRaw bump
3085 int channel
3086 int light_x
3087 int light_y
3088 int strength
3089
b2778574
AMH
3090
3091void
3092i_bumpmap_complex(im,bump,channel,tx,ty,Lx,Ly,Lz,cd,cs,n,Ia,Il,Is)
3093 Imager::ImgRaw im
3094 Imager::ImgRaw bump
3095 int channel
3096 int tx
3097 int ty
3098 float Lx
3099 float Ly
3100 float Lz
3101 float cd
3102 float cs
3103 float n
3104 Imager::Color Ia
3105 Imager::Color Il
3106 Imager::Color Is
3107
3108
3109
02d1d628
AMH
3110void
3111i_postlevels(im,levels)
3112 Imager::ImgRaw im
3113 int levels
3114
3115void
3116i_mosaic(im,size)
3117 Imager::ImgRaw im
3118 int size
3119
3120void
3121i_watermark(im,wmark,tx,ty,pixdiff)
3122 Imager::ImgRaw im
3123 Imager::ImgRaw wmark
3124 int tx
3125 int ty
3126 int pixdiff
3127
3128
3129void
3130i_autolevels(im,lsat,usat,skew)
3131 Imager::ImgRaw im
3132 float lsat
3133 float usat
3134 float skew
3135
3136void
3137i_radnoise(im,xo,yo,rscale,ascale)
3138 Imager::ImgRaw im
3139 float xo
3140 float yo
3141 float rscale
3142 float ascale
3143
3144void
3145i_turbnoise(im, xo, yo, scale)
3146 Imager::ImgRaw im
3147 float xo
3148 float yo
3149 float scale
3150
3151
3152void
3153i_gradgen(im, ...)
3154 Imager::ImgRaw im
3155 PREINIT:
3156 int num;
3157 int *xo;
3158 int *yo;
3159 i_color *ival;
3160 int dmeasure;
3161 int i;
3162 SV *sv;
3163 AV *axx;
3164 AV *ayy;
3165 AV *ac;
3166 CODE:
3167 if (items != 5)
3168 croak("Usage: i_gradgen(im, xo, yo, ival, dmeasure)");
3169 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
3170 croak("i_gradgen: Second argument must be an array ref");
3171 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
3172 croak("i_gradgen: Third argument must be an array ref");
3173 if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
3174 croak("i_gradgen: Fourth argument must be an array ref");
3175 axx = (AV *)SvRV(ST(1));
3176 ayy = (AV *)SvRV(ST(2));
3177 ac = (AV *)SvRV(ST(3));
3178 dmeasure = (int)SvIV(ST(4));
3179
3180 num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
3181 num = num <= av_len(ac) ? num : av_len(ac);
3182 num++;
3183 if (num < 2) croak("Usage: i_gradgen array refs must have more than 1 entry each");
3184 xo = mymalloc( sizeof(int) * num );
3185 yo = mymalloc( sizeof(int) * num );
3186 ival = mymalloc( sizeof(i_color) * num );
3187 for(i = 0; i<num; i++) {
3188 xo[i] = (int)SvIV(* av_fetch(axx, i, 0));
3189 yo[i] = (int)SvIV(* av_fetch(ayy, i, 0));
3190 sv = *av_fetch(ac, i, 0);
3191 if ( !sv_derived_from(sv, "Imager::Color") ) {
3192 free(axx); free(ayy); free(ac);
3193 croak("i_gradgen: Element of fourth argument is not derived from Imager::Color");
3194 }
4c4c2ffd 3195 ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
02d1d628
AMH
3196 }
3197 i_gradgen(im, num, xo, yo, ival, dmeasure);
a73aeb5f
AMH
3198 myfree(xo);
3199 myfree(yo);
3200 myfree(ival);
3201
dff75dee
TC
3202Imager::ImgRaw
3203i_diff_image(im, im2, mindist=0)
3204 Imager::ImgRaw im
3205 Imager::ImgRaw im2
3206 int mindist
02d1d628 3207
e310e5f9 3208undef_int
6607600c
TC
3209i_fountain(im, xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
3210 Imager::ImgRaw im
3211 double xa
3212 double ya
3213 double xb
3214 double yb
3215 int type
3216 int repeat
3217 int combine
3218 int super_sample
3219 double ssample_param
3220 PREINIT:
6607600c 3221 AV *asegs;
6607600c
TC
3222 int count;
3223 i_fountain_seg *segs;
6607600c 3224 CODE:
6607600c
TC
3225 if (!SvROK(ST(10)) || ! SvTYPE(SvRV(ST(10))))
3226 croak("i_fountain: argument 11 must be an array ref");
3227
3228 asegs = (AV *)SvRV(ST(10));
f1ac5027 3229 segs = load_fount_segs(asegs, &count);
e310e5f9
TC
3230 RETVAL = i_fountain(im, xa, ya, xb, yb, type, repeat, combine,
3231 super_sample, ssample_param, count, segs);
6607600c 3232 myfree(segs);
e310e5f9
TC
3233 OUTPUT:
3234 RETVAL
02d1d628 3235
f1ac5027
TC
3236Imager::FillHandle
3237i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
3238 double xa
3239 double ya
3240 double xb
3241 double yb
3242 int type
3243 int repeat
3244 int combine
3245 int super_sample
3246 double ssample_param
3247 PREINIT:
3248 AV *asegs;
3249 int count;
3250 i_fountain_seg *segs;
3251 CODE:
3252 if (!SvROK(ST(9)) || ! SvTYPE(SvRV(ST(9))))
3253 croak("i_fountain: argument 11 must be an array ref");
3254
3255 asegs = (AV *)SvRV(ST(9));
3256 segs = load_fount_segs(asegs, &count);
3257 RETVAL = i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine,
3258 super_sample, ssample_param, count, segs);
3259 myfree(segs);
3260 OUTPUT:
3261 RETVAL
3262
4f4f776a
TC
3263void
3264i_errors()
3265 PREINIT:
3266 i_errmsg *errors;
3267 int i;
4f4f776a 3268 AV *av;
4f4f776a
TC
3269 SV *sv;
3270 PPCODE:
3271 errors = i_errors();
3272 i = 0;
3273 while (errors[i].msg) {
3274 av = newAV();
3275 sv = newSVpv(errors[i].msg, strlen(errors[i].msg));
3276 if (!av_store(av, 0, sv)) {
3277 SvREFCNT_dec(sv);
3278 }
3279 sv = newSViv(errors[i].code);
3280 if (!av_store(av, 1, sv)) {
3281 SvREFCNT_dec(sv);
3282 }
3283 PUSHs(sv_2mortal(newRV_noinc((SV*)av)));
3284 ++i;
3285 }
02d1d628 3286
2b405c9e
TC
3287void
3288i_clear_error()
3289
3290void
3291i_push_error(code, msg)
3292 int code
3293 const char *msg
3294
e310e5f9 3295undef_int
02d1d628
AMH
3296i_nearest_color(im, ...)
3297 Imager::ImgRaw im
3298 PREINIT:
3299 int num;
3300 int *xo;
3301 int *yo;
3302 i_color *ival;
3303 int dmeasure;
3304 int i;
3305 SV *sv;
3306 AV *axx;
3307 AV *ayy;
3308 AV *ac;
3309 CODE:
3310 if (items != 5)
3311 croak("Usage: i_nearest_color(im, xo, yo, ival, dmeasure)");
3312 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
3313 croak("i_nearest_color: Second argument must be an array ref");
3314 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
3315 croak("i_nearest_color: Third argument must be an array ref");
3316 if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
3317 croak("i_nearest_color: Fourth argument must be an array ref");
3318 axx = (AV *)SvRV(ST(1));
3319 ayy = (AV *)SvRV(ST(2));
3320 ac = (AV *)SvRV(ST(3));
3321 dmeasure = (int)SvIV(ST(4));
3322
3323 num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
3324 num = num <= av_len(ac) ? num : av_len(ac);
3325 num++;
3326 if (num < 2) croak("Usage: i_nearest_color array refs must have more than 1 entry each");
3327 xo = mymalloc( sizeof(int) * num );
3328 yo = mymalloc( sizeof(int) * num );
3329 ival = mymalloc( sizeof(i_color) * num );
3330 for(i = 0; i<num; i++) {
3331 xo[i] = (int)SvIV(* av_fetch(axx, i, 0));
3332 yo[i] = (int)SvIV(* av_fetch(ayy, i, 0));
3333 sv = *av_fetch(ac, i, 0);
3334 if ( !sv_derived_from(sv, "Imager::Color") ) {
3335 free(axx); free(ayy); free(ac);
3336 croak("i_nearest_color: Element of fourth argument is not derived from Imager::Color");
3337 }
4c4c2ffd 3338 ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
02d1d628 3339 }
e310e5f9
TC
3340 RETVAL = i_nearest_color(im, num, xo, yo, ival, dmeasure);
3341 OUTPUT:
3342 RETVAL
02d1d628
AMH
3343
3344void
3345malloc_state()
3346
02d1d628
AMH
3347void
3348DSO_open(filename)
3349 char* filename
3350 PREINIT:
3351 void *rc;
3352 char *evstr;
3353 PPCODE:
3354 rc=DSO_open(filename,&evstr);
3355 if (rc!=NULL) {
3356 if (evstr!=NULL) {
3357 EXTEND(SP,2);
e375fbd8 3358 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
02d1d628
AMH
3359 PUSHs(sv_2mortal(newSVpvn(evstr, strlen(evstr))));
3360 } else {
3361 EXTEND(SP,1);
e375fbd8 3362 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
02d1d628
AMH
3363 }
3364 }
3365
3366
3367undef_int
3368DSO_close(dso_handle)
3369 void* dso_handle
3370
3371void
3372DSO_funclist(dso_handle_v)
3373 void* dso_handle_v
3374 PREINIT:
3375 int i;
3376 DSO_handle *dso_handle;
3377 PPCODE:
3378 dso_handle=(DSO_handle*)dso_handle_v;
3379 i=0;
3380 while( dso_handle->function_list[i].name != NULL) {
3381 EXTEND(SP,1);
3382 PUSHs(sv_2mortal(newSVpv(dso_handle->function_list[i].name,0)));
3383 EXTEND(SP,1);
3384 PUSHs(sv_2mortal(newSVpv(dso_handle->function_list[i++].pcode,0)));
3385 }
3386
3387
3388void
3389DSO_call(handle,func_index,hv)
3390 void* handle
3391 int func_index
3392 PREINIT:
3393 HV* hv;
3394 PPCODE:
3395 if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to a hash\n");
3396 hv=(HV*)SvRV(ST(2));
3397 if (SvTYPE(hv)!=SVt_PVHV) croak("Imager: Parameter 2 must be a reference to a hash\n");
3398 DSO_call( (DSO_handle *)handle,func_index,hv);
3399
3400
3401
faa9b3e7 3402SV *
f5991c03
TC
3403i_get_pixel(im, x, y)
3404 Imager::ImgRaw im
3405 int x
3406 int y;
faa9b3e7
TC
3407 PREINIT:
3408 i_color *color;
3409 CODE:
3410 color = (i_color *)mymalloc(sizeof(i_color));
3411 if (i_gpix(im, x, y, color) == 0) {
a659442a
TC
3412 RETVAL = NEWSV(0, 0);
3413 sv_setref_pv(RETVAL, "Imager::Color", (void *)color);
faa9b3e7
TC
3414 }
3415 else {
3416 myfree(color);
a659442a 3417 RETVAL = &PL_sv_undef;
faa9b3e7 3418 }
a659442a
TC
3419 OUTPUT:
3420 RETVAL
faa9b3e7
TC
3421
3422
3423int
3424i_ppix(im, x, y, cl)
3425 Imager::ImgRaw im
3426 int x
3427 int y
3428 Imager::Color cl
3429
3430Imager::ImgRaw
3431i_img_pal_new(x, y, channels, maxpal)
3432 int x
3433 int y
3434 int channels
3435 int maxpal
3436
3437Imager::ImgRaw
3438i_img_to_pal(src, quant)
3439 Imager::ImgRaw src
3440 PREINIT:
3441 HV *hv;
3442 i_quantize quant;
3443 CODE:
3444 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
3445 croak("i_img_to_pal: second argument must be a hash ref");
3446 hv = (HV *)SvRV(ST(1));
3447 memset(&quant, 0, sizeof(quant));
3448 quant.mc_size = 256;
faa9b3e7
TC
3449 handle_quant_opts(&quant, hv);
3450 RETVAL = i_img_to_pal(src, &quant);
3451 if (RETVAL) {
3452 copy_colors_back(hv, &quant);
3453 }
46a04ceb 3454 cleanup_quant_opts(&quant);
faa9b3e7
TC
3455 OUTPUT:
3456 RETVAL
3457
3458Imager::ImgRaw
3459i_img_to_rgb(src)
3460 Imager::ImgRaw src
3461
3462void
3463i_gpal(im, l, r, y)
3464 Imager::ImgRaw im
3465 int l
3466 int r
3467 int y
3468 PREINIT:
3469 i_palidx *work;
3470 int count, i;
3471 PPCODE:
3472 if (l < r) {
3473 work = mymalloc((r-l) * sizeof(i_palidx));
3474 count = i_gpal(im, l, r, y, work);
3475 if (GIMME_V == G_ARRAY) {
3476 EXTEND(SP, count);
3477 for (i = 0; i < count; ++i) {
3478 PUSHs(sv_2mortal(newSViv(work[i])));
3479 }
3480 }
3481 else {
3482 EXTEND(SP, 1);
26fd367b 3483 PUSHs(sv_2mortal(newSVpv((char *)work, count * sizeof(i_palidx))));
faa9b3e7
TC
3484 }
3485 myfree(work);
3486 }
3487 else {
3488 if (GIMME_V != G_ARRAY) {
3489 EXTEND(SP, 1);
3490 PUSHs(&PL_sv_undef);
3491 }
3492 }
3493
3494int
3495i_ppal(im, l, y, ...)
3496 Imager::ImgRaw im
3497 int l
3498 int y
3499 PREINIT:
3500 i_palidx *work;
ea9e6c3f 3501 int i;
faa9b3e7
TC
3502 CODE:
3503 if (items > 3) {
3504 work = mymalloc(sizeof(i_palidx) * (items-3));
3505 for (i=0; i < items-3; ++i) {
3506 work[i] = SvIV(ST(i+3));
3507 }
3508 RETVAL = i_ppal(im, l, l+items-3, y, work);
3509 myfree(work);
3510 }
3511 else {
3512 RETVAL = 0;
3513 }
3514 OUTPUT:
3515 RETVAL
3516
3517SV *
3518i_addcolors(im, ...)
3519 Imager::ImgRaw im
3520 PREINIT:
3521 int index;
3522 i_color *colors;
3523 int i;
3524 CODE:
3525 if (items < 2)
3526 croak("i_addcolors: no colors to add");
3527 colors = mymalloc((items-1) * sizeof(i_color));
3528 for (i=0; i < items-1; ++i) {
3529 if (sv_isobject(ST(i+1))
3530 && sv_derived_from(ST(i+1), "Imager::Color")) {
3531 IV tmp = SvIV((SV *)SvRV(ST(i+1)));
4c4c2ffd 3532 colors[i] = *INT2PTR(i_color *, tmp);
faa9b3e7
TC
3533 }
3534 else {
3535 myfree(colors);
ca4d914e 3536 croak("i_addcolor: pixels must be Imager::Color objects");
faa9b3e7
TC
3537 }
3538 }
3539 index = i_addcolors(im, colors, items-1);
3540 myfree(colors);
3541 if (index == 0) {
a659442a 3542 RETVAL = newSVpv("0 but true", 0);
faa9b3e7
TC
3543 }
3544 else if (index == -1) {
a659442a 3545 RETVAL = &PL_sv_undef;
faa9b3e7
TC
3546 }
3547 else {
a659442a 3548 RETVAL = newSViv(index);
faa9b3e7 3549 }
a659442a
TC
3550 OUTPUT:
3551 RETVAL
faa9b3e7 3552
1501d9b3 3553undef_int
faa9b3e7
TC
3554i_setcolors(im, index, ...)
3555 Imager::ImgRaw im
3556 int index
3557 PREINIT:
3558 i_color *colors;
3559 int i;
3560 CODE:
3561 if (items < 3)
3562 croak("i_setcolors: no colors to add");
3563 colors = mymalloc((items-2) * sizeof(i_color));
3564 for (i=0; i < items-2; ++i) {
3565 if (sv_isobject(ST(i+2))
3566 && sv_derived_from(ST(i+2), "Imager::Color")) {
3567 IV tmp = SvIV((SV *)SvRV(ST(i+2)));
4c4c2ffd 3568 colors[i] = *INT2PTR(i_color *, tmp);
faa9b3e7
TC
3569 }
3570 else {
3571 myfree(colors);
3572 croak("i_setcolors: pixels must be Imager::Color objects");
3573 }
3574 }
3575 RETVAL = i_setcolors(im, index, colors, items-2);
3576 myfree(colors);
1501d9b3
TC
3577 OUTPUT:
3578 RETVAL
faa9b3e7
TC
3579
3580void
3581i_getcolors(im, index, ...)
3582 Imager::ImgRaw im
3583 int index
3584 PREINIT:
3585 i_color *colors;
3586 int count = 1;
3587 int i;
3588 PPCODE:
3589 if (items > 3)
3590 croak("i_getcolors: too many arguments");
3591 if (items == 3)
3592 count = SvIV(ST(2));
3593 if (count < 1)
3594 croak("i_getcolors: count must be positive");
3595 colors = mymalloc(sizeof(i_color) * count);
3596 if (i_getcolors(im, index, colors, count)) {
3597 for (i = 0; i < count; ++i) {
3598 i_color *pv;
3599 SV *sv = sv_newmortal();
3600 pv = mymalloc(sizeof(i_color));
3601 *pv = colors[i];
3602 sv_setref_pv(sv, "Imager::Color", (void *)pv);
3603 PUSHs(sv);
3604 }
3605 }
3606 myfree(colors);
3607
3608
a659442a 3609undef_neg_int
faa9b3e7
TC
3610i_colorcount(im)
3611 Imager::ImgRaw im
faa9b3e7 3612
a659442a 3613undef_neg_int
faa9b3e7
TC
3614i_maxcolors(im)
3615 Imager::ImgRaw im
faa9b3e7
TC
3616
3617SV *
3618i_findcolor(im, color)
3619 Imager::ImgRaw im
3620 Imager::Color color
3621 PREINIT:
3622 i_palidx index;
3623 CODE:
3624 if (i_findcolor(im, color, &index)) {
a659442a 3625 RETVAL = newSViv(index);
faa9b3e7
TC
3626 }
3627 else {
a659442a 3628 RETVAL = &PL_sv_undef;
faa9b3e7 3629 }
a659442a
TC
3630 OUTPUT:
3631 RETVAL
faa9b3e7
TC
3632
3633int
3634i_img_bits(im)
3635 Imager::ImgRaw im
3636
3637int
3638i_img_type(im)
3639 Imager::ImgRaw im
3640
3641int
3642i_img_virtual(im)
3643 Imager::ImgRaw im
3644
3645void
3646i_gsamp(im, l, r, y, ...)
3647 Imager::ImgRaw im
3648 int l
3649 int r
3650 int y
3651 PREINIT:
3652 int *chans;
3653 int chan_count;
3654 i_sample_t *data;
3655 int count, i;
3656 PPCODE:
3657 if (items < 5)
3658 croak("No channel numbers supplied to g_samp()");
3659 if (l < r) {
3660 chan_count = items - 4;
3661 chans = mymalloc(sizeof(int) * chan_count);
3662 for (i = 0; i < chan_count; ++i)
3663 chans[i] = SvIV(ST(i+4));
4dfa5522 3664 data = mymalloc(sizeof(i_sample_t) * (r-l) * chan_count); /* XXX: memleak? */
faa9b3e7 3665 count = i_gsamp(im, l, r, y, data, chans, chan_count);
4dfa5522 3666 myfree(chans);
faa9b3e7
TC
3667 if (GIMME_V == G_ARRAY) {
3668 EXTEND(SP, count);
3669 for (i = 0; i < count; ++i)
3670 PUSHs(sv_2mortal(newSViv(data[i])));
3671 }
3672 else {
3673 EXTEND(SP, 1);
26fd367b 3674 PUSHs(sv_2mortal(newSVpv((char *)data, count * sizeof(i_sample_t))));
faa9b3e7 3675 }
a73aeb5f 3676 myfree(data);
faa9b3e7
TC
3677 }
3678 else {
3679 if (GIMME_V != G_ARRAY) {
3680 EXTEND(SP, 1);
3681 PUSHs(&PL_sv_undef);
3682 }
3683 }
3684
a73aeb5f 3685
faa9b3e7
TC
3686Imager::ImgRaw
3687i_img_masked_new(targ, mask, x, y, w, h)
3688 Imager::ImgRaw targ
3689 int x
3690 int y
3691 int w
3692 int h
3693 PREINIT:
3694 i_img *mask;
3695 CODE:
3696 if (SvOK(ST(1))) {
3697 if (!sv_isobject(ST(1))
3698 || !sv_derived_from(ST(1), "Imager::ImgRaw")) {
3699 croak("i_img_masked_new: parameter 2 must undef or an image");
3700 }
4c4c2ffd 3701 mask = INT2PTR(i_img *, SvIV((SV *)SvRV(ST(1))));
faa9b3e7
TC
3702 }
3703 else
3704 mask = NULL;
3705 RETVAL = i_img_masked_new(targ, mask, x, y, w, h);
3706 OUTPUT:
3707 RETVAL
3708
3709int
3710i_plin(im, l, y, ...)
3711 Imager::ImgRaw im
3712 int l
3713 int y
3714 PREINIT:
3715 i_color *work;
ea9e6c3f 3716 int i;
ca4d914e
TC
3717 STRLEN len;
3718 int count;
faa9b3e7
TC
3719 CODE:
3720 if (items > 3) {
ca4d914e
TC
3721 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3722 /* supplied as a byte string */
3723 work = (i_color *)SvPV(ST(3), len);
3724 count = len / sizeof(i_color);
3725 if (count * sizeof(i_color) != len) {
3726 croak("i_plin: length of scalar argument must be multiple of sizeof i_color");
faa9b3e7 3727 }
ca4d914e
TC
3728 RETVAL = i_plin(im, l, l+count, y, work);
3729 }
3730 else {
3731 work = mymalloc(sizeof(i_color) * (items-3));
3732 for (i=0; i < items-3; ++i) {
3733 if (sv_isobject(ST(i+3))
3734 && sv_derived_from(ST(i+3), "Imager::Color")) {
3735 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3736 work[i] = *INT2PTR(i_color *, tmp);
3737 }
3738 else {
3739 myfree(work);
3740 croak("i_plin: pixels must be Imager::Color objects");
3741 }
faa9b3e7 3742 }
ca4d914e
TC
3743 RETVAL = i_plin(im, l, l+items-3, y, work);
3744 myfree(work);
faa9b3e7 3745 }
faa9b3e7
TC
3746 }
3747 else {
3748 RETVAL = 0;
3749 }
3750 OUTPUT:
3751 RETVAL
3752
3753int
3754i_ppixf(im, x, y, cl)
3755 Imager::ImgRaw im
3756 int x
3757 int y
3758 Imager::Color::Float cl
3759
3760void
3761i_gsampf(im, l, r, y, ...)
3762 Imager::ImgRaw im
3763 int l
3764 int r
3765 int y
3766 PREINIT:
3767 int *chans;
3768 int chan_count;
3769 i_fsample_t *data;
3770 int count, i;
3771 PPCODE:
3772 if (items < 5)
3773 croak("No channel numbers supplied to g_sampf()");
3774 if (l < r) {
3775 chan_count = items - 4;
3776 chans = mymalloc(sizeof(int) * chan_count);
3777 for (i = 0; i < chan_count; ++i)
3778 chans[i] = SvIV(ST(i+4));
3779 data = mymalloc(sizeof(i_fsample_t) * (r-l) * chan_count);
3780 count = i_gsampf(im, l, r, y, data, chans, chan_count);
3631271b 3781 myfree(chans);
faa9b3e7
TC
3782 if (GIMME_V == G_ARRAY) {
3783 EXTEND(SP, count);
3784 for (i = 0; i < count; ++i)
3785 PUSHs(sv_2mortal(newSVnv(data[i])));
3786 }
3787 else {
3788 EXTEND(SP, 1);
3789 PUSHs(sv_2mortal(newSVpv((void *)data, count * sizeof(i_fsample_t))));
3790 }
3631271b 3791 myfree(data);
faa9b3e7
TC
3792 }
3793 else {
3794 if (GIMME_V != G_ARRAY) {
3795 EXTEND(SP, 1);
3796 PUSHs(&PL_sv_undef);
3797 }
3798 }
3799
3800int
3801i_plinf(im, l, y, ...)
3802 Imager::ImgRaw im
3803 int l
3804 int y
3805 PREINIT:
3806 i_fcolor *work;
ea9e6c3f 3807 int i;
ca4d914e
TC
3808 STRLEN len;
3809 int count;
faa9b3e7
TC
3810 CODE:
3811 if (items > 3) {
ca4d914e
TC
3812 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3813 /* supplied as a byte string */
3814 work = (i_fcolor *)SvPV(ST(3), len);
3815 count = len / sizeof(i_fcolor);
3816 if (count * sizeof(i_fcolor) != len) {
3817 croak("i_plin: length of scalar argument must be multiple of sizeof i_fcolor");
faa9b3e7 3818 }
ca4d914e
TC
3819 RETVAL = i_plinf(im, l, l+count, y, work);
3820 }
3821 else {
3822 work = mymalloc(sizeof(i_fcolor) * (items-3));
3823 for (i=0; i < items-3; ++i) {
3824 if (sv_isobject(ST(i+3))
3825 && sv_derived_from(ST(i+3), "Imager::Color::Float")) {
3826 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3827 work[i] = *INT2PTR(i_fcolor *, tmp);
3828 }
3829 else {
3830 myfree(work);
3831 croak("i_plinf: pixels must be Imager::Color::Float objects");
3832 }
faa9b3e7 3833 }
ca4d914e
TC
3834 /**(char *)0 = 1;*/
3835 RETVAL = i_plinf(im, l, l+items-3, y, work);
3836 myfree(work);
faa9b3e7 3837 }
faa9b3e7
TC
3838 }
3839 else {
3840 RETVAL = 0;
3841 }
3842 OUTPUT:
3843 RETVAL
3844
3845SV *
3846i_gpixf(im, x, y)
3847 Imager::ImgRaw im
3848 int x
3849 int y;
3850 PREINIT:
3851 i_fcolor *color;
3852 CODE:
3853 color = (i_fcolor *)mymalloc(sizeof(i_fcolor));
3854 if (i_gpixf(im, x, y, color) == 0) {
a659442a
TC
3855 RETVAL = NEWSV(0,0);
3856 sv_setref_pv(RETVAL, "Imager::Color::Float", (void *)color);
faa9b3e7
TC
3857 }
3858 else {
3859 myfree(color);
a659442a 3860 RETVAL = &PL_sv_undef;
faa9b3e7 3861 }
a659442a
TC
3862 OUTPUT:
3863 RETVAL
3864
faa9b3e7
TC
3865void
3866i_glin(im, l, r, y)
3867 Imager::ImgRaw im
3868 int l
3869 int r
3870 int y
3871 PREINIT:
3872 i_color *vals;
3873 int count, i;
3874 PPCODE:
3875 if (l < r) {
3876 vals = mymalloc((r-l) * sizeof(i_color));
3877 count = i_glin(im, l, r, y, vals);
ca4d914e
TC
3878 if (GIMME_V == G_ARRAY) {
3879 EXTEND(SP, count);
3880 for (i = 0; i < count; ++i) {
3881 SV *sv;
3882 i_color *col = mymalloc(sizeof(i_color));
3883 *col = vals[i];
3884 sv = sv_newmortal();
3885 sv_setref_pv(sv, "Imager::Color", (void *)col);
3886 PUSHs(sv);
3887 }
3888 }
3889 else if (count) {
3890 EXTEND(SP, 1);
3891 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_color))));
faa9b3e7
TC
3892 }
3893 myfree(vals);
3894 }
3895
3896void
3897i_glinf(im, l, r, y)
3898 Imager::ImgRaw im
3899 int l
3900 int r
3901 int y
3902 PREINIT:
3903 i_fcolor *vals;
3904 int count, i;
3905 PPCODE:
3906 if (l < r) {
3907 vals = mymalloc((r-l) * sizeof(i_fcolor));
3908 count = i_glinf(im, l, r, y, vals);
ca4d914e
TC
3909 if (GIMME_V == G_ARRAY) {
3910 EXTEND(SP, count);
3911 for (i = 0; i < count; ++i) {
3912 SV *sv;
3913 i_fcolor *col = mymalloc(sizeof(i_fcolor));
3914 *col = vals[i];
3915 sv = sv_newmortal();
3916 sv_setref_pv(sv, "Imager::Color::Float", (void *)col);
3917 PUSHs(sv);
3918 }
3919 }
3920 else if (count) {
3921 EXTEND(SP, 1);
3922 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_fcolor))));
faa9b3e7
TC
3923 }
3924 myfree(vals);
3925 }
3926
3927Imager::ImgRaw
3928i_img_16_new(x, y, ch)
3929 int x
3930 int y
3931 int ch
3932
365ea842
TC
3933Imager::ImgRaw
3934i_img_double_new(x, y, ch)
3935 int x
3936 int y
3937 int ch
3938
faa9b3e7
TC
3939undef_int
3940i_tags_addn(im, name, code, idata)
3941 Imager::ImgRaw im
3942 int code
3943 int idata
3944 PREINIT:
3945 char *name;
3946 STRLEN len;
3947 CODE:
3948 if (SvOK(ST(1)))
3949 name = SvPV(ST(1), len);
3950 else
3951 name = NULL;
3952 RETVAL = i_tags_addn(&im->tags, name, code, idata);
3953 OUTPUT:
3954 RETVAL
3955
3956undef_int
3957i_tags_add(im, name, code, data, idata)
3958 Imager::ImgRaw im
3959 int code
3960 int idata
3961 PREINIT:
3962 char *name;
3963 char *data;
3964 STRLEN len;
3965 CODE:
3966 if (SvOK(ST(1)))
3967 name = SvPV(ST(1), len);
3968 else
3969 name = NULL;
3970 if (SvOK(ST(3)))
3971 data = SvPV(ST(3), len);
3972 else {
3973 data = NULL;
3974 len = 0;
3975 }
3976 RETVAL = i_tags_add(&im->tags, name, code, data, len, idata);
3977 OUTPUT:
3978 RETVAL
3979
3980SV *
3981i_tags_find(im, name, start)
3982 Imager::ImgRaw im
3983 char *name
3984 int start
3985 PREINIT:
3986 int entry;
3987 CODE:
3988 if (i_tags_find(&im->tags, name, start, &entry)) {
3989 if (entry == 0)
a659442a 3990 RETVAL = newSVpv("0 but true", 0);
faa9b3e7 3991 else
a659442a 3992 RETVAL = newSViv(entry);
faa9b3e7 3993 } else {
a659442a 3994 RETVAL = &PL_sv_undef;
faa9b3e7 3995 }
a659442a
TC
3996 OUTPUT:
3997 RETVAL
faa9b3e7
TC
3998
3999SV *
4000i_tags_findn(im, code, start)
4001 Imager::ImgRaw im
4002 int code
4003 int start
4004 PREINIT:
4005 int entry;
4006 CODE:
4007 if (i_tags_findn(&im->tags, code, start, &entry)) {
4008 if (entry == 0)
a659442a 4009 RETVAL = newSVpv("0 but true", 0);
faa9b3e7 4010 else
a659442a 4011 RETVAL = newSViv(entry);
faa9b3e7 4012 }
a659442a
TC
4013 else {
4014 RETVAL = &PL_sv_undef;
4015 }
4016 OUTPUT:
4017 RETVAL
faa9b3e7
TC
4018
4019int
4020i_tags_delete(im, entry)
4021 Imager::ImgRaw im
4022 int entry
4023 CODE:
4024 RETVAL = i_tags_delete(&im->tags, entry);
4025 OUTPUT:
4026 RETVAL
4027
4028int
4029i_tags_delbyname(im, name)
4030 Imager::ImgRaw im
4031 char * name
4032 CODE:
4033 RETVAL = i_tags_delbyname(&im->tags, name);
4034 OUTPUT:
4035 RETVAL
4036
4037int
4038i_tags_delbycode(im, code)
4039 Imager::ImgRaw im
4040 int code
4041 CODE:
4042 RETVAL = i_tags_delbycode(&im->tags, code);
4043 OUTPUT:
4044 RETVAL
4045
4046void
4047i_tags_get(im, index)
4048 Imager::ImgRaw im
4049 int index
4050 PPCODE:
4051 if (index >= 0 && index < im->tags.count) {
4052 i_img_tag *entry = im->tags.tags + index;
4053 EXTEND(SP, 5);
4054
4055 if (entry->name) {
4056 PUSHs(sv_2mortal(newSVpv(entry->name, 0)));
4057 }
4058 else {
4059 PUSHs(sv_2mortal(newSViv(entry->code)));
4060 }
4061 if (entry->data) {
4062 PUSHs(sv_2mortal(newSVpvn(entry->data, entry->size)));
4063 }
4064 else {
4065 PUSHs(sv_2mortal(newSViv(entry->idata)));
4066 }
4067 }
4068
241defe8
TC
4069void
4070i_tags_get_string(im, what_sv)
4071 Imager::ImgRaw im
4072 SV *what_sv
4073 PREINIT:
4074 char const *name = NULL;
4075 int code;
4076 char buffer[200];
241defe8
TC
4077 PPCODE:
4078 if (SvIOK(what_sv)) {
4079 code = SvIV(what_sv);
4080 name = NULL;
4081 }
4082 else {
4083 name = SvPV_nolen(what_sv);
4084 code = 0;
4085 }
4086 if (i_tags_get_string(&im->tags, name, code, buffer, sizeof(buffer))) {
4087 EXTEND(SP, 1);
4088 PUSHs(sv_2mortal(newSVpv(buffer, 0)));
4089 }
4090
faa9b3e7
TC
4091int
4092i_tags_count(im)
4093 Imager::ImgRaw im
4094 CODE:
4095 RETVAL = im->tags.count;
4096 OUTPUT:
4097 RETVAL
4098
4099#ifdef HAVE_WIN32
4100
4101void
4102i_wf_bbox(face, size, text)
4103 char *face
4104 int size
4105 char *text
4106 PREINIT:
3799c4d1 4107 int cords[BOUNDING_BOX_COUNT];
0ab90434 4108 int rc, i;
faa9b3e7 4109 PPCODE:
3799c4d1
TC
4110 if (rc = i_wf_bbox(face, size, text, strlen(text), cords)) {
4111 EXTEND(SP, rc);
4112 for (i = 0; i < rc; ++i)
4113 PUSHs(sv_2mortal(newSViv(cords[i])));
faa9b3e7
TC
4114 }
4115
4116undef_int
4117i_wf_text(face, im, tx, ty, cl, size, text, align, aa)
4118 char *face
4119 Imager::ImgRaw im
4120 int tx
4121 int ty
4122 Imager::Color cl
4123 int size
4124 char *text
4125 int align
4126 int aa
4127 CODE:
4128 RETVAL = i_wf_text(face, im, tx, ty, cl, size, text, strlen(text),
4129 align, aa);
4130 OUTPUT:
4131 RETVAL
4132
4133undef_int
4134i_wf_cp(face, im, tx, ty, channel, size, text, align, aa)
4135 char *face
4136 Imager::ImgRaw im
4137 int tx
4138 int ty
4139 int channel
4140 int size
4141 char *text
4142 int align
4143 int aa
f5991c03 4144 CODE:
faa9b3e7
TC
4145 RETVAL = i_wf_cp(face, im, tx, ty, channel, size, text, strlen(text),
4146 align, aa);
f5991c03
TC
4147 OUTPUT:
4148 RETVAL
02d1d628 4149
8457948a
TC
4150undef_int
4151i_wf_addfont(font)
4152 char *font
faa9b3e7
TC
4153
4154#endif
4155
4156#ifdef HAVE_FT2
4157
4158MODULE = Imager PACKAGE = Imager::Font::FT2 PREFIX=FT2_
4159
4160#define FT2_DESTROY(font) i_ft2_destroy(font)
4161
4162void
4163FT2_DESTROY(font)
4164 Imager::Font::FT2 font
4165
4166MODULE = Imager PACKAGE = Imager::Font::FreeType2
4167
4168Imager::Font::FT2
4169i_ft2_new(name, index)
4170 char *name
4171 int index
4172
4173undef_int
4174i_ft2_setdpi(font, xdpi, ydpi)
4175 Imager::Font::FT2 font
4176 int xdpi
4177 int ydpi
4178
4179void
4180i_ft2_getdpi(font)
4181 Imager::Font::FT2 font
4182 PREINIT:
4183 int xdpi, ydpi;
4184 CODE:
4185 if (i_ft2_getdpi(font, &xdpi, &ydpi)) {
4186 EXTEND(SP, 2);
4187 PUSHs(sv_2mortal(newSViv(xdpi)));
4188 PUSHs(sv_2mortal(newSViv(ydpi)));
4189 }
4190
4191undef_int
4192i_ft2_sethinting(font, hinting)
4193 Imager::Font::FT2 font
4194 int hinting
4195
4196undef_int
4197i_ft2_settransform(font, matrix)
4198 Imager::Font::FT2 font
4199 PREINIT:
4200 double matrix[6];
4201 int len;
4202 AV *av;
4203 SV *sv1;
4204 int i;
4205 CODE:
4206 if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV)
4207 croak("i_ft2_settransform: parameter 2 must be an array ref\n");
4208 av=(AV*)SvRV(ST(1));
4209 len=av_len(av)+1;
4210 if (len > 6)
4211 len = 6;
4212 for (i = 0; i < len; ++i) {
4213 sv1=(*(av_fetch(av,i,0)));
4214 matrix[i] = SvNV(sv1);
4215 }
4216 for (; i < 6; ++i)
4217 matrix[i] = 0;
4218 RETVAL = i_ft2_settransform(font, matrix);
4219 OUTPUT:
4220 RETVAL
4221
4222void
3799c4d1 4223i_ft2_bbox(font, cheight, cwidth, text_sv, utf8)
faa9b3e7
TC
4224 Imager::Font::FT2 font
4225 double cheight
4226 double cwidth
3799c4d1 4227 SV *text_sv
5cb9270b 4228 int utf8
faa9b3e7 4229 PREINIT:
3799c4d1 4230 int bbox[BOUNDING_BOX_COUNT];
faa9b3e7 4231 int i;
3799c4d1
TC
4232 char *text;
4233 STRLEN text_len;
4234 int rc;
faa9b3e7 4235 PPCODE:
3799c4d1 4236 text = SvPV(text_sv, text_len);
5cb9270b 4237#ifdef SvUTF8
3799c4d1 4238 if (SvUTF8(text_sv))
5cb9270b
TC
4239 utf8 = 1;
4240#endif
3799c4d1
TC
4241 rc = i_ft2_bbox(font, cheight, cwidth, text, text_len, bbox, utf8);
4242 if (rc) {
4243 EXTEND(SP, rc);
4244 for (i = 0; i < rc; ++i)
faa9b3e7
TC