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