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