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