- fixes to verbose mode in Makefile.PL, also added a -v switch so you
[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
8f8bd9aa 2038i_readtiff_wiol(ig, length, page=0)
02d1d628
AMH
2039 Imager::IO ig
2040 int length
8f8bd9aa 2041 int page
02d1d628 2042
10461f9a
TC
2043void
2044i_readtiff_multi_wiol(ig, length)
2045 Imager::IO ig
2046 int length
2047 PREINIT:
2048 i_img **imgs;
2049 int count;
2050 int i;
2051 PPCODE:
2052 imgs = i_readtiff_multi_wiol(ig, length, &count);
2053 if (imgs) {
2054 EXTEND(SP, count);
2055 for (i = 0; i < count; ++i) {
2056 SV *sv = sv_newmortal();
2057 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2058 PUSHs(sv);
2059 }
2060 myfree(imgs);
2061 }
2062
02d1d628
AMH
2063
2064undef_int
2065i_writetiff_wiol(im, ig)
2066 Imager::ImgRaw im
2067 Imager::IO ig
2068
10461f9a
TC
2069undef_int
2070i_writetiff_multi_wiol(ig, ...)
2071 Imager::IO ig
2072 PREINIT:
2073 int i;
2074 int img_count;
2075 i_img **imgs;
2076 CODE:
2077 if (items < 2)
2078 croak("Usage: i_writetiff_multi_wiol(ig, images...)");
2079 img_count = items - 1;
2080 RETVAL = 1;
2081 if (img_count < 1) {
2082 RETVAL = 0;
2083 i_clear_error();
2084 i_push_error(0, "You need to specify images to save");
2085 }
2086 else {
2087 imgs = mymalloc(sizeof(i_img *) * img_count);
2088 for (i = 0; i < img_count; ++i) {
2089 SV *sv = ST(1+i);
2090 imgs[i] = NULL;
2091 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
4c4c2ffd 2092 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(sv)));
10461f9a
TC
2093 }
2094 else {
2095 i_clear_error();
2096 i_push_error(0, "Only images can be saved");
2097 myfree(imgs);
2098 RETVAL = 0;
2099 break;
2100 }
2101 }
2102 if (RETVAL) {
2103 RETVAL = i_writetiff_multi_wiol(ig, imgs, img_count);
2104 }
2105 myfree(imgs);
2106 }
2107 OUTPUT:
2108 RETVAL
2109
d2dfdcc9 2110undef_int
4c2d6970 2111i_writetiff_wiol_faxable(im, ig, fine)
d2dfdcc9
TC
2112 Imager::ImgRaw im
2113 Imager::IO ig
4c2d6970 2114 int fine
d2dfdcc9 2115
10461f9a
TC
2116undef_int
2117i_writetiff_multi_wiol_faxable(ig, fine, ...)
2118 Imager::IO ig
2119 int fine
2120 PREINIT:
2121 int i;
2122 int img_count;
2123 i_img **imgs;
2124 CODE:
2125 if (items < 3)
2126 croak("Usage: i_writetiff_multi_wiol_faxable(ig, fine, images...)");
2127 img_count = items - 2;
2128 RETVAL = 1;
2129 if (img_count < 1) {
2130 RETVAL = 0;
2131 i_clear_error();
2132 i_push_error(0, "You need to specify images to save");
2133 }
2134 else {
2135 imgs = mymalloc(sizeof(i_img *) * img_count);
2136 for (i = 0; i < img_count; ++i) {
2137 SV *sv = ST(2+i);
2138 imgs[i] = NULL;
2139 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
4c4c2ffd 2140 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(sv)));
10461f9a
TC
2141 }
2142 else {
2143 i_clear_error();
2144 i_push_error(0, "Only images can be saved");
2145 myfree(imgs);
2146 RETVAL = 0;
2147 break;
2148 }
2149 }
2150 if (RETVAL) {
2151 RETVAL = i_writetiff_multi_wiol_faxable(ig, imgs, img_count, fine);
2152 }
2153 myfree(imgs);
2154 }
2155 OUTPUT:
2156 RETVAL
02d1d628
AMH
2157
2158
10461f9a 2159#endif /* HAVE_LIBTIFF */
02d1d628
AMH
2160
2161
2162#ifdef HAVE_LIBPNG
2163
2164Imager::ImgRaw
790923a4
AMH
2165i_readpng_wiol(ig, length)
2166 Imager::IO ig
2167 int length
02d1d628
AMH
2168
2169
2170undef_int
790923a4 2171i_writepng_wiol(im, ig)
02d1d628 2172 Imager::ImgRaw im
790923a4 2173 Imager::IO ig
02d1d628
AMH
2174
2175
2176#endif
2177
2178
2179#ifdef HAVE_LIBGIF
2180
03bd24d4
TC
2181void
2182i_giflib_version()
2183 PPCODE:
2184 PUSHs(sv_2mortal(newSVnv(IM_GIFMAJOR+IM_GIFMINOR*0.1)));
2185
02d1d628
AMH
2186undef_int
2187i_writegif(im,fd,colors,pixdev,fixed)
2188 Imager::ImgRaw im
2189 int fd
2190 int colors
2191 int pixdev
2192 PREINIT:
2193 int fixedlen;
2194 Imager__Color fixed;
2195 Imager__Color tmp;
2196 AV* av;
2197 SV* sv1;
2198 IV Itmp;
2199 int i;
2200 CODE:
2201 if (!SvROK(ST(4))) croak("Imager: Parameter 4 must be a reference to an array\n");
2202 if (SvTYPE(SvRV(ST(4))) != SVt_PVAV) croak("Imager: Parameter 4 must be a reference to an array\n");
2203 av=(AV*)SvRV(ST(4));
2204 fixedlen=av_len(av)+1;
2205 fixed=mymalloc( fixedlen*sizeof(i_color) );
2206 for(i=0;i<fixedlen;i++) {
2207 sv1=(*(av_fetch(av,i,0)));
2208 if (sv_derived_from(sv1, "Imager::Color")) {
2209 Itmp = SvIV((SV*)SvRV(sv1));
d5fbe3ee 2210 tmp = INT2PTR(i_color*, Itmp);
02d1d628
AMH
2211 } else croak("Imager: one of the elements of array ref is not of Imager::Color type\n");
2212 fixed[i]=*tmp;
2213 }
2214 RETVAL=i_writegif(im,fd,colors,pixdev,fixedlen,fixed);
2215 myfree(fixed);
2216 ST(0) = sv_newmortal();
2217 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2218 else sv_setiv(ST(0), (IV)RETVAL);
2219
2220
2221
2222
2223undef_int
2224i_writegifmc(im,fd,colors)
067d6bdc 2225 Imager::ImgRaw im
02d1d628
AMH
2226 int fd
2227 int colors
2228
02d1d628
AMH
2229
2230undef_int
2231i_writegif_gen(fd, ...)
2232 int fd
2233 PROTOTYPE: $$@
2234 PREINIT:
2235 i_quantize quant;
02d1d628
AMH
2236 i_img **imgs = NULL;
2237 int img_count;
2238 int i;
2239 HV *hv;
2240 CODE:
2241 if (items < 3)
2242 croak("Usage: i_writegif_gen(fd,hashref, images...)");
2243 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2244 croak("i_writegif_gen: Second argument must be a hash ref");
2245 hv = (HV *)SvRV(ST(1));
2246 memset(&quant, 0, sizeof(quant));
2247 quant.mc_size = 256;
02d1d628 2248 handle_quant_opts(&quant, hv);
02d1d628
AMH
2249 img_count = items - 2;
2250 RETVAL = 1;
2251 if (img_count < 1) {
2252 RETVAL = 0;
95b44a76
TC
2253 i_clear_error();
2254 i_push_error(0, "You need to specify images to save");
02d1d628
AMH
2255 }
2256 else {
2257 imgs = mymalloc(sizeof(i_img *) * img_count);
2258 for (i = 0; i < img_count; ++i) {
2259 SV *sv = ST(2+i);
2260 imgs[i] = NULL;
2261 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
4c4c2ffd 2262 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(sv)));
02d1d628
AMH
2263 }
2264 else {
95b44a76
TC
2265 i_clear_error();
2266 i_push_error(0, "Only images can be saved");
02d1d628
AMH
2267 RETVAL = 0;
2268 break;
2269 }
2270 }
2271 if (RETVAL) {
97c4effc 2272 RETVAL = i_writegif_gen(&quant, fd, imgs, img_count);
02d1d628
AMH
2273 }
2274 myfree(imgs);
2275 if (RETVAL) {
2276 copy_colors_back(hv, &quant);
2277 }
2278 }
a73aeb5f
AMH
2279 ST(0) = sv_newmortal();
2280 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2281 else sv_setiv(ST(0), (IV)RETVAL);
46a04ceb 2282 cleanup_quant_opts(&quant);
a73aeb5f 2283
02d1d628
AMH
2284
2285undef_int
2286i_writegif_callback(cb, maxbuffer,...)
2287 int maxbuffer;
2288 PREINIT:
2289 i_quantize quant;
02d1d628
AMH
2290 i_img **imgs = NULL;
2291 int img_count;
2292 int i;
2293 HV *hv;
2294 i_writer_data wd;
2295 CODE:
2296 if (items < 4)
2297 croak("Usage: i_writegif_callback(\\&callback,maxbuffer,hashref, images...)");
2298 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
2299 croak("i_writegif_callback: Second argument must be a hash ref");
2300 hv = (HV *)SvRV(ST(2));
2301 memset(&quant, 0, sizeof(quant));
2302 quant.mc_size = 256;
02d1d628 2303 handle_quant_opts(&quant, hv);
02d1d628
AMH
2304 img_count = items - 3;
2305 RETVAL = 1;
2306 if (img_count < 1) {
2307 RETVAL = 0;
2308 }
2309 else {
2310 imgs = mymalloc(sizeof(i_img *) * img_count);
2311 for (i = 0; i < img_count; ++i) {
2312 SV *sv = ST(3+i);
2313 imgs[i] = NULL;
2314 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
4c4c2ffd 2315 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(sv)));
02d1d628
AMH
2316 }
2317 else {
2318 RETVAL = 0;
2319 break;
2320 }
2321 }
2322 if (RETVAL) {
2323 wd.sv = ST(0);
97c4effc 2324 RETVAL = i_writegif_callback(&quant, write_callback, (char *)&wd, maxbuffer, imgs, img_count);
02d1d628
AMH
2325 }
2326 myfree(imgs);
2327 if (RETVAL) {
2328 copy_colors_back(hv, &quant);
2329 }
2330 }
46a04ceb
TC
2331 ST(0) = sv_newmortal();
2332 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2333 else sv_setiv(ST(0), (IV)RETVAL);
46a04ceb 2334 cleanup_quant_opts(&quant);
02d1d628 2335
10461f9a
TC
2336undef_int
2337i_writegif_wiol(ig, opts,...)
2338 Imager::IO ig
2339 PREINIT:
2340 i_quantize quant;
10461f9a
TC
2341 i_img **imgs = NULL;
2342 int img_count;
2343 int i;
2344 HV *hv;
2345 CODE:
2346 if (items < 3)
2347 croak("Usage: i_writegif_wiol(IO,hashref, images...)");
2348 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2349 croak("i_writegif_callback: Second argument must be a hash ref");
2350 hv = (HV *)SvRV(ST(1));
2351 memset(&quant, 0, sizeof(quant));
2352 quant.mc_size = 256;
10461f9a 2353 handle_quant_opts(&quant, hv);
10461f9a
TC
2354 img_count = items - 2;
2355 RETVAL = 1;
2356 if (img_count < 1) {
2357 RETVAL = 0;
2358 }
2359 else {
2360 imgs = mymalloc(sizeof(i_img *) * img_count);
2361 for (i = 0; i < img_count; ++i) {
2362 SV *sv = ST(2+i);
2363 imgs[i] = NULL;
2364 if (SvROK(sv) && sv_derived_from(sv, "Imager::ImgRaw")) {
4c4c2ffd 2365 imgs[i] = INT2PTR(i_img *, SvIV((SV*)SvRV(sv)));
10461f9a
TC
2366 }
2367 else {
2368 RETVAL = 0;
2369 break;
2370 }
2371 }
2372 if (RETVAL) {
97c4effc 2373 RETVAL = i_writegif_wiol(ig, &quant, imgs, img_count);
10461f9a
TC
2374 }
2375 myfree(imgs);
2376 if (RETVAL) {
2377 copy_colors_back(hv, &quant);
2378 }
2379 }
2380 ST(0) = sv_newmortal();
2381 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2382 else sv_setiv(ST(0), (IV)RETVAL);
10461f9a
TC
2383 cleanup_quant_opts(&quant);
2384
02d1d628
AMH
2385void
2386i_readgif(fd)
2387 int fd
2388 PREINIT:
2389 int* colour_table;
2390 int colours, q, w;
2391 i_img* rimg;
2392 SV* temp[3];
2393 AV* ct;
2394 SV* r;
2395 PPCODE:
2396 colour_table = NULL;
2397 colours = 0;
2398
895dbd34 2399 if(GIMME_V == G_ARRAY) {
02d1d628
AMH
2400 rimg = i_readgif(fd,&colour_table,&colours);
2401 } else {
2402 /* don't waste time with colours if they aren't wanted */
2403 rimg = i_readgif(fd,NULL,NULL);
2404 }
895dbd34 2405
02d1d628
AMH
2406 if (colour_table == NULL) {
2407 EXTEND(SP,1);
2408 r=sv_newmortal();
2409 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2410 PUSHs(r);
2411 } else {
2412 /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
2413 /* I don't know if I have the reference counts right or not :( */
2414 /* Neither do I :-) */
2415 /* No Idea here either */
2416
2417 ct=newAV();
2418 av_extend(ct, colours);
2419 for(q=0; q<colours; q++) {
2420 for(w=0; w<3; w++)
2421 temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
2422 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
2423 }
2424 myfree(colour_table);
895dbd34 2425
02d1d628 2426 EXTEND(SP,2);
895dbd34 2427 r = sv_newmortal();
02d1d628
AMH
2428 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2429 PUSHs(r);
2430 PUSHs(newRV_noinc((SV*)ct));
2431 }
2432
10461f9a
TC
2433void
2434i_readgif_wiol(ig)
2435 Imager::IO ig
2436 PREINIT:
2437 int* colour_table;
2438 int colours, q, w;
2439 i_img* rimg;
2440 SV* temp[3];
2441 AV* ct;
2442 SV* r;
2443 PPCODE:
2444 colour_table = NULL;
2445 colours = 0;
02d1d628 2446
10461f9a
TC
2447 if(GIMME_V == G_ARRAY) {
2448 rimg = i_readgif_wiol(ig,&colour_table,&colours);
2449 } else {
2450 /* don't waste time with colours if they aren't wanted */
2451 rimg = i_readgif_wiol(ig,NULL,NULL);
2452 }
2453
2454 if (colour_table == NULL) {
2455 EXTEND(SP,1);
2456 r=sv_newmortal();
2457 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2458 PUSHs(r);
2459 } else {
2460 /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
2461 /* I don't know if I have the reference counts right or not :( */
2462 /* Neither do I :-) */
2463 /* No Idea here either */
02d1d628 2464
10461f9a
TC
2465 ct=newAV();
2466 av_extend(ct, colours);
2467 for(q=0; q<colours; q++) {
2468 for(w=0; w<3; w++)
2469 temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
2470 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
2471 }
2472 myfree(colour_table);
02d1d628 2473
10461f9a
TC
2474 EXTEND(SP,2);
2475 r = sv_newmortal();
2476 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2477 PUSHs(r);
2478 PUSHs(newRV_noinc((SV*)ct));
2479 }
02d1d628 2480
f1adece7
TC
2481Imager::ImgRaw
2482i_readgif_single_wiol(ig, page=0)
2483 Imager::IO ig
2484 int page
2485
02d1d628
AMH
2486void
2487i_readgif_scalar(...)
2488 PROTOTYPE: $
2489 PREINIT:
2490 char* data;
21e952df 2491 STRLEN length;
02d1d628
AMH
2492 int* colour_table;
2493 int colours, q, w;
2494 i_img* rimg;
2495 SV* temp[3];
2496 AV* ct;
2497 SV* r;
2498 PPCODE:
2499 data = (char *)SvPV(ST(0), length);
2500 colour_table=NULL;
2501 colours=0;
2502
2503 if(GIMME_V == G_ARRAY) {
2504 rimg=i_readgif_scalar(data,length,&colour_table,&colours);
2505 } else {
2506 /* don't waste time with colours if they aren't wanted */
2507 rimg=i_readgif_scalar(data,length,NULL,NULL);
2508 }
2509
2510 if (colour_table == NULL) {
2511 EXTEND(SP,1);
2512 r=sv_newmortal();
2513 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2514 PUSHs(r);
2515 } else {
2516 /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
2517 /* I don't know if I have the reference counts right or not :( */
2518 /* Neither do I :-) */
2519 ct=newAV();
2520 av_extend(ct, colours);
2521 for(q=0; q<colours; q++) {
2522 for(w=0; w<3; w++)
2523 temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
2524 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
2525 }
2526 myfree(colour_table);
2527
2528 EXTEND(SP,2);
2529 r=sv_newmortal();
2530 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2531 PUSHs(r);
2532 PUSHs(newRV_noinc((SV*)ct));
2533 }
2534
2535void
2536i_readgif_callback(...)
2537 PROTOTYPE: &
2538 PREINIT:
02d1d628
AMH
2539 int* colour_table;
2540 int colours, q, w;
2541 i_img* rimg;
2542 SV* temp[3];
2543 AV* ct;
2544 SV* r;
2545 i_reader_data rd;
2546 PPCODE:
2547 rd.sv = ST(0);
2548 colour_table=NULL;
2549 colours=0;
2550
2551 if(GIMME_V == G_ARRAY) {
2552 rimg=i_readgif_callback(read_callback, (char *)&rd,&colour_table,&colours);
2553 } else {
2554 /* don't waste time with colours if they aren't wanted */
2555 rimg=i_readgif_callback(read_callback, (char *)&rd,NULL,NULL);
2556 }
2557
2558 if (colour_table == NULL) {
2559 EXTEND(SP,1);
2560 r=sv_newmortal();
2561 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2562 PUSHs(r);
2563 } else {
2564 /* the following creates an [[r,g,b], [r, g, b], [r, g, b]...] */
2565 /* I don't know if I have the reference counts right or not :( */
2566 /* Neither do I :-) */
2567 /* Neither do I - maybe I'll move this somewhere */
2568 ct=newAV();
2569 av_extend(ct, colours);
2570 for(q=0; q<colours; q++) {
2571 for(w=0; w<3; w++)
2572 temp[w]=sv_2mortal(newSViv(colour_table[q*3 + w]));
2573 av_store(ct, q, (SV*)newRV_noinc((SV*)av_make(3, temp)));
2574 }
2575 myfree(colour_table);
2576
2577 EXTEND(SP,2);
2578 r=sv_newmortal();
2579 sv_setref_pv(r, "Imager::ImgRaw", (void*)rimg);
2580 PUSHs(r);
2581 PUSHs(newRV_noinc((SV*)ct));
2582 }
2583
faa9b3e7
TC
2584void
2585i_readgif_multi(fd)
2586 int fd
2587 PREINIT:
2588 i_img **imgs;
2589 int count;
2590 int i;
2591 PPCODE:
2592 imgs = i_readgif_multi(fd, &count);
2593 if (imgs) {
2594 EXTEND(SP, count);
2595 for (i = 0; i < count; ++i) {
2596 SV *sv = sv_newmortal();
2597 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2598 PUSHs(sv);
2599 }
2600 myfree(imgs);
2601 }
02d1d628 2602
faa9b3e7
TC
2603void
2604i_readgif_multi_scalar(data)
2605 PREINIT:
2606 i_img **imgs;
2607 int count;
2608 char *data;
21e952df 2609 STRLEN length;
faa9b3e7
TC
2610 int i;
2611 PPCODE:
2612 data = (char *)SvPV(ST(0), length);
2613 imgs = i_readgif_multi_scalar(data, length, &count);
2614 if (imgs) {
2615 EXTEND(SP, count);
2616 for (i = 0; i < count; ++i) {
2617 SV *sv = sv_newmortal();
2618 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2619 PUSHs(sv);
2620 }
2621 myfree(imgs);
2622 }
02d1d628 2623
faa9b3e7
TC
2624void
2625i_readgif_multi_callback(cb)
2626 PREINIT:
2627 i_reader_data rd;
2628 i_img **imgs;
2629 int count;
2630 int i;
2631 PPCODE:
2632 rd.sv = ST(0);
2633 imgs = i_readgif_multi_callback(read_callback, (char *)&rd, &count);
2634 if (imgs) {
2635 EXTEND(SP, count);
2636 for (i = 0; i < count; ++i) {
2637 SV *sv = sv_newmortal();
2638 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2639 PUSHs(sv);
2640 }
2641 myfree(imgs);
2642 }
02d1d628 2643
10461f9a
TC
2644void
2645i_readgif_multi_wiol(ig)
2646 Imager::IO ig
2647 PREINIT:
2648 i_img **imgs;
2649 int count;
2650 int i;
2651 PPCODE:
2652 imgs = i_readgif_multi_wiol(ig, &count);
2653 if (imgs) {
2654 EXTEND(SP, count);
2655 for (i = 0; i < count; ++i) {
2656 SV *sv = sv_newmortal();
2657 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2658 PUSHs(sv);
2659 }
2660 myfree(imgs);
2661 }
2662
2663
02d1d628
AMH
2664#endif
2665
2666
2667
2668Imager::ImgRaw
2669i_readpnm_wiol(ig, length)
2670 Imager::IO ig
2671 int length
2672
2673
067d6bdc
AMH
2674undef_int
2675i_writeppm_wiol(im, ig)
2676 Imager::ImgRaw im
2677 Imager::IO ig
2678
2679
02d1d628 2680Imager::ImgRaw
895dbd34
AMH
2681i_readraw_wiol(ig,x,y,datachannels,storechannels,intrl)
2682 Imager::IO ig
02d1d628
AMH
2683 int x
2684 int y
2685 int datachannels
2686 int storechannels
2687 int intrl
2688
2689undef_int
895dbd34 2690i_writeraw_wiol(im,ig)
02d1d628 2691 Imager::ImgRaw im
895dbd34
AMH
2692 Imager::IO ig
2693
261f91c5
TC
2694undef_int
2695i_writebmp_wiol(im,ig)
2696 Imager::ImgRaw im
2697 Imager::IO ig
02d1d628 2698
705fd961
TC
2699Imager::ImgRaw
2700i_readbmp_wiol(ig)
2701 Imager::IO ig
2702
1ec86afa
AMH
2703
2704undef_int
febba01f 2705i_writetga_wiol(im,ig, wierdpack, compress, idstring)
1ec86afa
AMH
2706 Imager::ImgRaw im
2707 Imager::IO ig
febba01f
AMH
2708 int wierdpack
2709 int compress
2710 char* idstring
2711 PREINIT:
febba01f
AMH
2712 int idlen;
2713 CODE:
2714 idlen = SvCUR(ST(4));
2715 RETVAL = i_writetga_wiol(im, ig, wierdpack, compress, idstring, idlen);
2716 OUTPUT:
2717 RETVAL
2718
1ec86afa
AMH
2719
2720Imager::ImgRaw
2721i_readtga_wiol(ig, length)
2722 Imager::IO ig
2723 int length
2724
2725
737a830c
AMH
2726undef_int
2727i_writergb_wiol(im,ig, wierdpack, compress, idstring)
2728 Imager::ImgRaw im
2729 Imager::IO ig
2730 int wierdpack
2731 int compress
2732 char* idstring
2733 PREINIT:
737a830c
AMH
2734 int idlen;
2735 CODE:
2736 idlen = SvCUR(ST(4));
2737 RETVAL = i_writergb_wiol(im, ig, wierdpack, compress, idstring, idlen);
2738 OUTPUT:
2739 RETVAL
2740
2741
2742Imager::ImgRaw
2743i_readrgb_wiol(ig, length)
2744 Imager::IO ig
2745 int length
2746
2747
2748
02d1d628
AMH
2749Imager::ImgRaw
2750i_scaleaxis(im,Value,Axis)
2751 Imager::ImgRaw im
2752 float Value
2753 int Axis
2754
2755Imager::ImgRaw
2756i_scale_nn(im,scx,scy)
2757 Imager::ImgRaw im
2758 float scx
2759 float scy
2760
2761Imager::ImgRaw
2762i_haar(im)
2763 Imager::ImgRaw im
2764
2765int
2766i_count_colors(im,maxc)
2767 Imager::ImgRaw im
2768 int maxc
2769
2770
2771Imager::ImgRaw
2772i_transform(im,opx,opy,parm)
2773 Imager::ImgRaw im
2774 PREINIT:
2775 double* parm;
2776 int* opx;
2777 int* opy;
2778 int opxl;
2779 int opyl;
2780 int parmlen;
2781 AV* av;
2782 SV* sv1;
2783 int i;
2784 CODE:
2785 if (!SvROK(ST(1))) croak("Imager: Parameter 1 must be a reference to an array\n");
2786 if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to an array\n");
2787 if (!SvROK(ST(3))) croak("Imager: Parameter 3 must be a reference to an array\n");
2788 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 must be a reference to an array\n");
2789 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 2 must be a reference to an array\n");
2790 if (SvTYPE(SvRV(ST(3))) != SVt_PVAV) croak("Imager: Parameter 3 must be a reference to an array\n");
2791 av=(AV*)SvRV(ST(1));
2792 opxl=av_len(av)+1;
2793 opx=mymalloc( opxl*sizeof(int) );
2794 for(i=0;i<opxl;i++) {
2795 sv1=(*(av_fetch(av,i,0)));
2796 opx[i]=(int)SvIV(sv1);
2797 }
2798 av=(AV*)SvRV(ST(2));
2799 opyl=av_len(av)+1;
2800 opy=mymalloc( opyl*sizeof(int) );
2801 for(i=0;i<opyl;i++) {
2802 sv1=(*(av_fetch(av,i,0)));
2803 opy[i]=(int)SvIV(sv1);
2804 }
2805 av=(AV*)SvRV(ST(3));
2806 parmlen=av_len(av)+1;
2807 parm=mymalloc( parmlen*sizeof(double) );
2808 for(i=0;i<parmlen;i++) { /* FIXME: Bug? */
2809 sv1=(*(av_fetch(av,i,0)));
2810 parm[i]=(double)SvNV(sv1);
2811 }
2812 RETVAL=i_transform(im,opx,opxl,opy,opyl,parm,parmlen);
2813 myfree(parm);
2814 myfree(opy);
2815 myfree(opx);
2816 ST(0) = sv_newmortal();
2817 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2818 else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
2819
2820Imager::ImgRaw
e5744e01
TC
2821i_transform2(sv_width,sv_height,channels,sv_ops,av_n_regs,av_c_regs,av_in_imgs)
2822 SV *sv_width
2823 SV *sv_height
2824 SV *sv_ops
2825 AV *av_n_regs
2826 AV *av_c_regs
2827 AV *av_in_imgs
2828 int channels
02d1d628
AMH
2829 PREINIT:
2830 int width;
2831 int height;
02d1d628 2832 struct rm_op *ops;
953209f8 2833 STRLEN ops_len;
02d1d628
AMH
2834 int ops_count;
2835 double *n_regs;
2836 int n_regs_count;
2837 i_color *c_regs;
2838 int c_regs_count;
2839 int in_imgs_count;
2840 i_img **in_imgs;
ea9e6c3f 2841 SV *sv1;
02d1d628
AMH
2842 IV tmp;
2843 int i;
2844 CODE:
e5744e01
TC
2845
2846 in_imgs_count = av_len(av_in_imgs)+1;
2847 for (i = 0; i < in_imgs_count; ++i) {
2848 sv1 = *av_fetch(av_in_imgs, i, 0);
2849 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
2850 croak("sv_in_img must contain only images");
02d1d628
AMH
2851 }
2852 }
b8c2033e 2853 if (in_imgs_count > 0) {
02d1d628
AMH
2854 in_imgs = mymalloc(in_imgs_count*sizeof(i_img*));
2855 for (i = 0; i < in_imgs_count; ++i) {
e5744e01 2856 sv1 = *av_fetch(av_in_imgs,i,0);
02d1d628
AMH
2857 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
2858 croak("Parameter 5 must contain only images");
2859 }
2860 tmp = SvIV((SV*)SvRV(sv1));
e375fbd8 2861 in_imgs[i] = INT2PTR(i_img*, tmp);
02d1d628
AMH
2862 }
2863 }
2864 else {
2865 /* no input images */
2866 in_imgs = NULL;
2867 }
2868 /* default the output size from the first input if possible */
e5744e01
TC
2869 if (SvOK(sv_width))
2870 width = SvIV(sv_width);
02d1d628
AMH
2871 else if (in_imgs_count)
2872 width = in_imgs[0]->xsize;
2873 else
2874 croak("No output image width supplied");
2875
e5744e01
TC
2876 if (SvOK(sv_height))
2877 height = SvIV(sv_height);
02d1d628
AMH
2878 else if (in_imgs_count)
2879 height = in_imgs[0]->ysize;
2880 else
2881 croak("No output image height supplied");
2882
e5744e01 2883 ops = (struct rm_op *)SvPV(sv_ops, ops_len);
02d1d628
AMH
2884 if (ops_len % sizeof(struct rm_op))
2885 croak("Imager: Parameter 3 must be a bitmap of regops\n");
2886 ops_count = ops_len / sizeof(struct rm_op);
e5744e01
TC
2887
2888 n_regs_count = av_len(av_n_regs)+1;
02d1d628
AMH
2889 n_regs = mymalloc(n_regs_count * sizeof(double));
2890 for (i = 0; i < n_regs_count; ++i) {
e5744e01 2891 sv1 = *av_fetch(av_n_regs,i,0);
02d1d628
AMH
2892 if (SvOK(sv1))
2893 n_regs[i] = SvNV(sv1);
2894 }
e5744e01 2895 c_regs_count = av_len(av_c_regs)+1;
02d1d628
AMH
2896 c_regs = mymalloc(c_regs_count * sizeof(i_color));
2897 /* I don't bother initializing the colou?r registers */
2898
e5744e01 2899 RETVAL=i_transform2(width, height, channels, ops, ops_count,
02d1d628
AMH
2900 n_regs, n_regs_count,
2901 c_regs, c_regs_count, in_imgs, in_imgs_count);
2902 if (in_imgs)
2903 myfree(in_imgs);
2904 myfree(n_regs);
2905 myfree(c_regs);
2906 ST(0) = sv_newmortal();
2907 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2908 else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
2909
2910
2911void
2912i_contrast(im,intensity)
2913 Imager::ImgRaw im
2914 float intensity
2915
2916void
2917i_hardinvert(im)
2918 Imager::ImgRaw im
2919
2920void
2921i_noise(im,amount,type)
2922 Imager::ImgRaw im
2923 float amount
2924 unsigned char type
2925
2926void
2927i_bumpmap(im,bump,channel,light_x,light_y,strength)
2928 Imager::ImgRaw im
2929 Imager::ImgRaw bump
2930 int channel
2931 int light_x
2932 int light_y
2933 int strength
2934
b2778574
AMH
2935
2936void
2937i_bumpmap_complex(im,bump,channel,tx,ty,Lx,Ly,Lz,cd,cs,n,Ia,Il,Is)
2938 Imager::ImgRaw im
2939 Imager::ImgRaw bump
2940 int channel
2941 int tx
2942 int ty
2943 float Lx
2944 float Ly
2945 float Lz
2946 float cd
2947 float cs
2948 float n
2949 Imager::Color Ia
2950 Imager::Color Il
2951 Imager::Color Is
2952
2953
2954
02d1d628
AMH
2955void
2956i_postlevels(im,levels)
2957 Imager::ImgRaw im
2958 int levels
2959
2960void
2961i_mosaic(im,size)
2962 Imager::ImgRaw im
2963 int size
2964
2965void
2966i_watermark(im,wmark,tx,ty,pixdiff)
2967 Imager::ImgRaw im
2968 Imager::ImgRaw wmark
2969 int tx
2970 int ty
2971 int pixdiff
2972
2973
2974void
2975i_autolevels(im,lsat,usat,skew)
2976 Imager::ImgRaw im
2977 float lsat
2978 float usat
2979 float skew
2980
2981void
2982i_radnoise(im,xo,yo,rscale,ascale)
2983 Imager::ImgRaw im
2984 float xo
2985 float yo
2986 float rscale
2987 float ascale
2988
2989void
2990i_turbnoise(im, xo, yo, scale)
2991 Imager::ImgRaw im
2992 float xo
2993 float yo
2994 float scale
2995
2996
2997void
2998i_gradgen(im, ...)
2999 Imager::ImgRaw im
3000 PREINIT:
3001 int num;
3002 int *xo;
3003 int *yo;
3004 i_color *ival;
3005 int dmeasure;
3006 int i;
3007 SV *sv;
3008 AV *axx;
3009 AV *ayy;
3010 AV *ac;
3011 CODE:
3012 if (items != 5)
3013 croak("Usage: i_gradgen(im, xo, yo, ival, dmeasure)");
3014 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
3015 croak("i_gradgen: Second argument must be an array ref");
3016 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
3017 croak("i_gradgen: Third argument must be an array ref");
3018 if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
3019 croak("i_gradgen: Fourth argument must be an array ref");
3020 axx = (AV *)SvRV(ST(1));
3021 ayy = (AV *)SvRV(ST(2));
3022 ac = (AV *)SvRV(ST(3));
3023 dmeasure = (int)SvIV(ST(4));
3024
3025 num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
3026 num = num <= av_len(ac) ? num : av_len(ac);
3027 num++;
3028 if (num < 2) croak("Usage: i_gradgen array refs must have more than 1 entry each");
3029 xo = mymalloc( sizeof(int) * num );
3030 yo = mymalloc( sizeof(int) * num );
3031 ival = mymalloc( sizeof(i_color) * num );
3032 for(i = 0; i<num; i++) {
3033 xo[i] = (int)SvIV(* av_fetch(axx, i, 0));
3034 yo[i] = (int)SvIV(* av_fetch(ayy, i, 0));
3035 sv = *av_fetch(ac, i, 0);
3036 if ( !sv_derived_from(sv, "Imager::Color") ) {
3037 free(axx); free(ayy); free(ac);
3038 croak("i_gradgen: Element of fourth argument is not derived from Imager::Color");
3039 }
4c4c2ffd 3040 ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
02d1d628
AMH
3041 }
3042 i_gradgen(im, num, xo, yo, ival, dmeasure);
a73aeb5f
AMH
3043 myfree(xo);
3044 myfree(yo);
3045 myfree(ival);
3046
dff75dee
TC
3047Imager::ImgRaw
3048i_diff_image(im, im2, mindist=0)
3049 Imager::ImgRaw im
3050 Imager::ImgRaw im2
3051 int mindist
02d1d628 3052
6607600c
TC
3053void
3054i_fountain(im, xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
3055 Imager::ImgRaw im
3056 double xa
3057 double ya
3058 double xb
3059 double yb
3060 int type
3061 int repeat
3062 int combine
3063 int super_sample
3064 double ssample_param
3065 PREINIT:
6607600c 3066 AV *asegs;
6607600c
TC
3067 int count;
3068 i_fountain_seg *segs;
6607600c 3069 CODE:
6607600c
TC
3070 if (!SvROK(ST(10)) || ! SvTYPE(SvRV(ST(10))))
3071 croak("i_fountain: argument 11 must be an array ref");
3072
3073 asegs = (AV *)SvRV(ST(10));
f1ac5027 3074 segs = load_fount_segs(asegs, &count);
6607600c
TC
3075 i_fountain(im, xa, ya, xb, yb, type, repeat, combine, super_sample,
3076 ssample_param, count, segs);
3077 myfree(segs);
02d1d628 3078
f1ac5027
TC
3079Imager::FillHandle
3080i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
3081 double xa
3082 double ya
3083 double xb
3084 double yb
3085 int type
3086 int repeat
3087 int combine
3088 int super_sample
3089 double ssample_param
3090 PREINIT:
3091 AV *asegs;
3092 int count;
3093 i_fountain_seg *segs;
3094 CODE:
3095 if (!SvROK(ST(9)) || ! SvTYPE(SvRV(ST(9))))
3096 croak("i_fountain: argument 11 must be an array ref");
3097
3098 asegs = (AV *)SvRV(ST(9));
3099 segs = load_fount_segs(asegs, &count);
3100 RETVAL = i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine,
3101 super_sample, ssample_param, count, segs);
3102 myfree(segs);
3103 OUTPUT:
3104 RETVAL
3105
4f4f776a
TC
3106void
3107i_errors()
3108 PREINIT:
3109 i_errmsg *errors;
3110 int i;
4f4f776a 3111 AV *av;
4f4f776a
TC
3112 SV *sv;
3113 PPCODE:
3114 errors = i_errors();
3115 i = 0;
3116 while (errors[i].msg) {
3117 av = newAV();
3118 sv = newSVpv(errors[i].msg, strlen(errors[i].msg));
3119 if (!av_store(av, 0, sv)) {
3120 SvREFCNT_dec(sv);
3121 }
3122 sv = newSViv(errors[i].code);
3123 if (!av_store(av, 1, sv)) {
3124 SvREFCNT_dec(sv);
3125 }
3126 PUSHs(sv_2mortal(newRV_noinc((SV*)av)));
3127 ++i;
3128 }
02d1d628
AMH
3129
3130void
3131i_nearest_color(im, ...)
3132 Imager::ImgRaw im
3133 PREINIT:
3134 int num;
3135 int *xo;
3136 int *yo;
3137 i_color *ival;
3138 int dmeasure;
3139 int i;
3140 SV *sv;
3141 AV *axx;
3142 AV *ayy;
3143 AV *ac;
3144 CODE:
3145 if (items != 5)
3146 croak("Usage: i_nearest_color(im, xo, yo, ival, dmeasure)");
3147 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
3148 croak("i_nearest_color: Second argument must be an array ref");
3149 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
3150 croak("i_nearest_color: Third argument must be an array ref");
3151 if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
3152 croak("i_nearest_color: Fourth argument must be an array ref");
3153 axx = (AV *)SvRV(ST(1));
3154 ayy = (AV *)SvRV(ST(2));
3155 ac = (AV *)SvRV(ST(3));
3156 dmeasure = (int)SvIV(ST(4));
3157
3158 num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
3159 num = num <= av_len(ac) ? num : av_len(ac);
3160 num++;
3161 if (num < 2) croak("Usage: i_nearest_color array refs must have more than 1 entry each");
3162 xo = mymalloc( sizeof(int) * num );
3163 yo = mymalloc( sizeof(int) * num );
3164 ival = mymalloc( sizeof(i_color) * num );
3165 for(i = 0; i<num; i++) {
3166 xo[i] = (int)SvIV(* av_fetch(axx, i, 0));
3167 yo[i] = (int)SvIV(* av_fetch(ayy, i, 0));
3168 sv = *av_fetch(ac, i, 0);
3169 if ( !sv_derived_from(sv, "Imager::Color") ) {
3170 free(axx); free(ayy); free(ac);
3171 croak("i_nearest_color: Element of fourth argument is not derived from Imager::Color");
3172 }
4c4c2ffd 3173 ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
02d1d628
AMH
3174 }
3175 i_nearest_color(im, num, xo, yo, ival, dmeasure);
3176
3177
3178
3179
3180void
3181malloc_state()
3182
3183void
3184hashinfo(hv)
3185 PREINIT:
3186 HV* hv;
3187 int stuff;
3188 PPCODE:
3189 if (!SvROK(ST(0))) croak("Imager: Parameter 0 must be a reference to a hash\n");
3190 hv=(HV*)SvRV(ST(0));
3191 if (SvTYPE(hv)!=SVt_PVHV) croak("Imager: Parameter 0 must be a reference to a hash\n");
3192 if (getint(hv,"stuff",&stuff)) printf("ok: %d\n",stuff); else printf("key doesn't exist\n");
3193 if (getint(hv,"stuff2",&stuff)) printf("ok: %d\n",stuff); else printf("key doesn't exist\n");
3194
3195void
3196DSO_open(filename)
3197 char* filename
3198 PREINIT:
3199 void *rc;
3200 char *evstr;
3201 PPCODE:
3202 rc=DSO_open(filename,&evstr);
3203 if (rc!=NULL) {
3204 if (evstr!=NULL) {
3205 EXTEND(SP,2);
e375fbd8 3206 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
02d1d628
AMH
3207 PUSHs(sv_2mortal(newSVpvn(evstr, strlen(evstr))));
3208 } else {
3209 EXTEND(SP,1);
e375fbd8 3210 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
02d1d628
AMH
3211 }
3212 }
3213
3214
3215undef_int
3216DSO_close(dso_handle)
3217 void* dso_handle
3218
3219void
3220DSO_funclist(dso_handle_v)
3221 void* dso_handle_v
3222 PREINIT:
3223 int i;
3224 DSO_handle *dso_handle;
3225 PPCODE:
3226 dso_handle=(DSO_handle*)dso_handle_v;
3227 i=0;
3228 while( dso_handle->function_list[i].name != NULL) {
3229 EXTEND(SP,1);
3230 PUSHs(sv_2mortal(newSVpv(dso_handle->function_list[i].name,0)));
3231 EXTEND(SP,1);
3232 PUSHs(sv_2mortal(newSVpv(dso_handle->function_list[i++].pcode,0)));
3233 }
3234
3235
3236void
3237DSO_call(handle,func_index,hv)
3238 void* handle
3239 int func_index
3240 PREINIT:
3241 HV* hv;
3242 PPCODE:
3243 if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to a hash\n");
3244 hv=(HV*)SvRV(ST(2));
3245 if (SvTYPE(hv)!=SVt_PVHV) croak("Imager: Parameter 2 must be a reference to a hash\n");
3246 DSO_call( (DSO_handle *)handle,func_index,hv);
3247
3248
3249
faa9b3e7 3250SV *
f5991c03
TC
3251i_get_pixel(im, x, y)
3252 Imager::ImgRaw im
3253 int x
3254 int y;
faa9b3e7
TC
3255 PREINIT:
3256 i_color *color;
3257 CODE:
3258 color = (i_color *)mymalloc(sizeof(i_color));
3259 if (i_gpix(im, x, y, color) == 0) {
a659442a
TC
3260 RETVAL = NEWSV(0, 0);
3261 sv_setref_pv(RETVAL, "Imager::Color", (void *)color);
faa9b3e7
TC
3262 }
3263 else {
3264 myfree(color);
a659442a 3265 RETVAL = &PL_sv_undef;
faa9b3e7 3266 }
a659442a
TC
3267 OUTPUT:
3268 RETVAL
faa9b3e7
TC
3269
3270
3271int
3272i_ppix(im, x, y, cl)
3273 Imager::ImgRaw im
3274 int x
3275 int y
3276 Imager::Color cl
3277
3278Imager::ImgRaw
3279i_img_pal_new(x, y, channels, maxpal)
3280 int x
3281 int y
3282 int channels
3283 int maxpal
3284
3285Imager::ImgRaw
3286i_img_to_pal(src, quant)
3287 Imager::ImgRaw src
3288 PREINIT:
3289 HV *hv;
3290 i_quantize quant;
3291 CODE:
3292 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
3293 croak("i_img_to_pal: second argument must be a hash ref");
3294 hv = (HV *)SvRV(ST(1));
3295 memset(&quant, 0, sizeof(quant));
3296 quant.mc_size = 256;
faa9b3e7
TC
3297 handle_quant_opts(&quant, hv);
3298 RETVAL = i_img_to_pal(src, &quant);
3299 if (RETVAL) {
3300 copy_colors_back(hv, &quant);
3301 }
46a04ceb 3302 cleanup_quant_opts(&quant);
faa9b3e7
TC
3303 OUTPUT:
3304 RETVAL
3305
3306Imager::ImgRaw
3307i_img_to_rgb(src)
3308 Imager::ImgRaw src
3309
3310void
3311i_gpal(im, l, r, y)
3312 Imager::ImgRaw im
3313 int l
3314 int r
3315 int y
3316 PREINIT:
3317 i_palidx *work;
3318 int count, i;
3319 PPCODE:
3320 if (l < r) {
3321 work = mymalloc((r-l) * sizeof(i_palidx));
3322 count = i_gpal(im, l, r, y, work);
3323 if (GIMME_V == G_ARRAY) {
3324 EXTEND(SP, count);
3325 for (i = 0; i < count; ++i) {
3326 PUSHs(sv_2mortal(newSViv(work[i])));
3327 }
3328 }
3329 else {
3330 EXTEND(SP, 1);
26fd367b 3331 PUSHs(sv_2mortal(newSVpv((char *)work, count * sizeof(i_palidx))));
faa9b3e7
TC
3332 }
3333 myfree(work);
3334 }
3335 else {
3336 if (GIMME_V != G_ARRAY) {
3337 EXTEND(SP, 1);
3338 PUSHs(&PL_sv_undef);
3339 }
3340 }
3341
3342int
3343i_ppal(im, l, y, ...)
3344 Imager::ImgRaw im
3345 int l
3346 int y
3347 PREINIT:
3348 i_palidx *work;
ea9e6c3f 3349 int i;
faa9b3e7
TC
3350 CODE:
3351 if (items > 3) {
3352 work = mymalloc(sizeof(i_palidx) * (items-3));
3353 for (i=0; i < items-3; ++i) {
3354 work[i] = SvIV(ST(i+3));
3355 }
3356 RETVAL = i_ppal(im, l, l+items-3, y, work);
3357 myfree(work);
3358 }
3359 else {
3360 RETVAL = 0;
3361 }
3362 OUTPUT:
3363 RETVAL
3364
3365SV *
3366i_addcolors(im, ...)
3367 Imager::ImgRaw im
3368 PREINIT:
3369 int index;
3370 i_color *colors;
3371 int i;
3372 CODE:
3373 if (items < 2)
3374 croak("i_addcolors: no colors to add");
3375 colors = mymalloc((items-1) * sizeof(i_color));
3376 for (i=0; i < items-1; ++i) {
3377 if (sv_isobject(ST(i+1))
3378 && sv_derived_from(ST(i+1), "Imager::Color")) {
3379 IV tmp = SvIV((SV *)SvRV(ST(i+1)));
4c4c2ffd 3380 colors[i] = *INT2PTR(i_color *, tmp);
faa9b3e7
TC
3381 }
3382 else {
3383 myfree(colors);
ca4d914e 3384 croak("i_addcolor: pixels must be Imager::Color objects");
faa9b3e7
TC
3385 }
3386 }
3387 index = i_addcolors(im, colors, items-1);
3388 myfree(colors);
3389 if (index == 0) {
a659442a 3390 RETVAL = newSVpv("0 but true", 0);
faa9b3e7
TC
3391 }
3392 else if (index == -1) {
a659442a 3393 RETVAL = &PL_sv_undef;
faa9b3e7
TC
3394 }
3395 else {
a659442a 3396 RETVAL = newSViv(index);
faa9b3e7 3397 }
a659442a
TC
3398 OUTPUT:
3399 RETVAL
faa9b3e7 3400
1501d9b3 3401undef_int
faa9b3e7
TC
3402i_setcolors(im, index, ...)
3403 Imager::ImgRaw im
3404 int index
3405 PREINIT:
3406 i_color *colors;
3407 int i;
3408 CODE:
3409 if (items < 3)
3410 croak("i_setcolors: no colors to add");
3411 colors = mymalloc((items-2) * sizeof(i_color));
3412 for (i=0; i < items-2; ++i) {
3413 if (sv_isobject(ST(i+2))
3414 && sv_derived_from(ST(i+2), "Imager::Color")) {
3415 IV tmp = SvIV((SV *)SvRV(ST(i+2)));
4c4c2ffd 3416 colors[i] = *INT2PTR(i_color *, tmp);
faa9b3e7
TC
3417 }
3418 else {
3419 myfree(colors);
3420 croak("i_setcolors: pixels must be Imager::Color objects");
3421 }
3422 }
3423 RETVAL = i_setcolors(im, index, colors, items-2);
3424 myfree(colors);
1501d9b3
TC
3425 OUTPUT:
3426 RETVAL
faa9b3e7
TC
3427
3428void
3429i_getcolors(im, index, ...)
3430 Imager::ImgRaw im
3431 int index
3432 PREINIT:
3433 i_color *colors;
3434 int count = 1;
3435 int i;
3436 PPCODE:
3437 if (items > 3)
3438 croak("i_getcolors: too many arguments");
3439 if (items == 3)
3440 count = SvIV(ST(2));
3441 if (count < 1)
3442 croak("i_getcolors: count must be positive");
3443 colors = mymalloc(sizeof(i_color) * count);
3444 if (i_getcolors(im, index, colors, count)) {
3445 for (i = 0; i < count; ++i) {
3446 i_color *pv;
3447 SV *sv = sv_newmortal();
3448 pv = mymalloc(sizeof(i_color));
3449 *pv = colors[i];
3450 sv_setref_pv(sv, "Imager::Color", (void *)pv);
3451 PUSHs(sv);
3452 }
3453 }
3454 myfree(colors);
3455
3456
a659442a 3457undef_neg_int
faa9b3e7
TC
3458i_colorcount(im)
3459 Imager::ImgRaw im
faa9b3e7 3460
a659442a 3461undef_neg_int
faa9b3e7
TC
3462i_maxcolors(im)
3463 Imager::ImgRaw im
faa9b3e7
TC
3464
3465SV *
3466i_findcolor(im, color)
3467 Imager::ImgRaw im
3468 Imager::Color color
3469 PREINIT:
3470 i_palidx index;
3471 CODE:
3472 if (i_findcolor(im, color, &index)) {
a659442a 3473 RETVAL = newSViv(index);
faa9b3e7
TC
3474 }
3475 else {
a659442a 3476 RETVAL = &PL_sv_undef;
faa9b3e7 3477 }
a659442a
TC
3478 OUTPUT:
3479 RETVAL
faa9b3e7
TC
3480
3481int
3482i_img_bits(im)
3483 Imager::ImgRaw im
3484
3485int
3486i_img_type(im)
3487 Imager::ImgRaw im
3488
3489int
3490i_img_virtual(im)
3491 Imager::ImgRaw im
3492
3493void
3494i_gsamp(im, l, r, y, ...)
3495 Imager::ImgRaw im
3496 int l
3497 int r
3498 int y
3499 PREINIT:
3500 int *chans;
3501 int chan_count;
3502 i_sample_t *data;
3503 int count, i;
3504 PPCODE:
3505 if (items < 5)
3506 croak("No channel numbers supplied to g_samp()");
3507 if (l < r) {
3508 chan_count = items - 4;
3509 chans = mymalloc(sizeof(int) * chan_count);
3510 for (i = 0; i < chan_count; ++i)
3511 chans[i] = SvIV(ST(i+4));
4dfa5522 3512 data = mymalloc(sizeof(i_sample_t) * (r-l) * chan_count); /* XXX: memleak? */
faa9b3e7 3513 count = i_gsamp(im, l, r, y, data, chans, chan_count);
4dfa5522 3514 myfree(chans);
faa9b3e7
TC
3515 if (GIMME_V == G_ARRAY) {
3516 EXTEND(SP, count);
3517 for (i = 0; i < count; ++i)
3518 PUSHs(sv_2mortal(newSViv(data[i])));
3519 }
3520 else {
3521 EXTEND(SP, 1);
26fd367b 3522 PUSHs(sv_2mortal(newSVpv((char *)data, count * sizeof(i_sample_t))));
faa9b3e7 3523 }
a73aeb5f 3524 myfree(data);
faa9b3e7
TC
3525 }
3526 else {
3527 if (GIMME_V != G_ARRAY) {
3528 EXTEND(SP, 1);
3529 PUSHs(&PL_sv_undef);
3530 }
3531 }
3532
a73aeb5f 3533
faa9b3e7
TC
3534Imager::ImgRaw
3535i_img_masked_new(targ, mask, x, y, w, h)
3536 Imager::ImgRaw targ
3537 int x
3538 int y
3539 int w
3540 int h
3541 PREINIT:
3542 i_img *mask;
3543 CODE:
3544 if (SvOK(ST(1))) {
3545 if (!sv_isobject(ST(1))
3546 || !sv_derived_from(ST(1), "Imager::ImgRaw")) {
3547 croak("i_img_masked_new: parameter 2 must undef or an image");
3548 }
4c4c2ffd 3549 mask = INT2PTR(i_img *, SvIV((SV *)SvRV(ST(1))));
faa9b3e7
TC
3550 }
3551 else
3552 mask = NULL;
3553 RETVAL = i_img_masked_new(targ, mask, x, y, w, h);
3554 OUTPUT:
3555 RETVAL
3556
3557int
3558i_plin(im, l, y, ...)
3559 Imager::ImgRaw im
3560 int l
3561 int y
3562 PREINIT:
3563 i_color *work;
ea9e6c3f 3564 int i;
ca4d914e
TC
3565 STRLEN len;
3566 int count;
faa9b3e7
TC
3567 CODE:
3568 if (items > 3) {
ca4d914e
TC
3569 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3570 /* supplied as a byte string */
3571 work = (i_color *)SvPV(ST(3), len);
3572 count = len / sizeof(i_color);
3573 if (count * sizeof(i_color) != len) {
3574 croak("i_plin: length of scalar argument must be multiple of sizeof i_color");
faa9b3e7 3575 }
ca4d914e
TC
3576 RETVAL = i_plin(im, l, l+count, y, work);
3577 }
3578 else {
3579 work = mymalloc(sizeof(i_color) * (items-3));
3580 for (i=0; i < items-3; ++i) {
3581 if (sv_isobject(ST(i+3))
3582 && sv_derived_from(ST(i+3), "Imager::Color")) {
3583 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3584 work[i] = *INT2PTR(i_color *, tmp);
3585 }
3586 else {
3587 myfree(work);
3588 croak("i_plin: pixels must be Imager::Color objects");
3589 }
faa9b3e7 3590 }
ca4d914e
TC
3591 RETVAL = i_plin(im, l, l+items-3, y, work);
3592 myfree(work);
faa9b3e7 3593 }
faa9b3e7
TC
3594 }
3595 else {
3596 RETVAL = 0;
3597 }
3598 OUTPUT:
3599 RETVAL
3600
3601int
3602i_ppixf(im, x, y, cl)
3603 Imager::ImgRaw im
3604 int x
3605 int y
3606 Imager::Color::Float cl
3607
3608void
3609i_gsampf(im, l, r, y, ...)
3610 Imager::ImgRaw im
3611 int l
3612 int r
3613 int y
3614 PREINIT:
3615 int *chans;
3616 int chan_count;
3617 i_fsample_t *data;
3618 int count, i;
3619 PPCODE:
3620 if (items < 5)
3621 croak("No channel numbers supplied to g_sampf()");
3622 if (l < r) {
3623 chan_count = items - 4;
3624 chans = mymalloc(sizeof(int) * chan_count);
3625 for (i = 0; i < chan_count; ++i)
3626 chans[i] = SvIV(ST(i+4));
3627 data = mymalloc(sizeof(i_fsample_t) * (r-l) * chan_count);
3628 count = i_gsampf(im, l, r, y, data, chans, chan_count);
3629 if (GIMME_V == G_ARRAY) {
3630 EXTEND(SP, count);
3631 for (i = 0; i < count; ++i)
3632 PUSHs(sv_2mortal(newSVnv(data[i])));
3633 }
3634 else {
3635 EXTEND(SP, 1);
3636 PUSHs(sv_2mortal(newSVpv((void *)data, count * sizeof(i_fsample_t))));
3637 }
3638 }
3639 else {
3640 if (GIMME_V != G_ARRAY) {
3641 EXTEND(SP, 1);
3642 PUSHs(&PL_sv_undef);
3643 }
3644 }
3645
3646int
3647i_plinf(im, l, y, ...)
3648 Imager::ImgRaw im
3649 int l
3650 int y
3651 PREINIT:
3652 i_fcolor *work;
ea9e6c3f 3653 int i;
ca4d914e
TC
3654 STRLEN len;
3655 int count;
faa9b3e7
TC
3656 CODE:
3657 if (items > 3) {
ca4d914e
TC
3658 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3659 /* supplied as a byte string */
3660 work = (i_fcolor *)SvPV(ST(3), len);
3661 count = len / sizeof(i_fcolor);
3662 if (count * sizeof(i_fcolor) != len) {
3663 croak("i_plin: length of scalar argument must be multiple of sizeof i_fcolor");
faa9b3e7 3664 }
ca4d914e
TC
3665 RETVAL = i_plinf(im, l, l+count, y, work);
3666 }
3667 else {
3668 work = mymalloc(sizeof(i_fcolor) * (items-3));
3669 for (i=0; i < items-3; ++i) {
3670 if (sv_isobject(ST(i+3))
3671 && sv_derived_from(ST(i+3), "Imager::Color::Float")) {
3672 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3673 work[i] = *INT2PTR(i_fcolor *, tmp);
3674 }
3675 else {
3676 myfree(work);
3677 croak("i_plinf: pixels must be Imager::Color::Float objects");
3678 }
faa9b3e7 3679 }
ca4d914e
TC
3680 /**(char *)0 = 1;*/
3681 RETVAL = i_plinf(im, l, l+items-3, y, work);
3682 myfree(work);
faa9b3e7 3683 }
faa9b3e7
TC
3684 }
3685 else {
3686 RETVAL = 0;
3687 }
3688 OUTPUT:
3689 RETVAL
3690
3691SV *
3692i_gpixf(im, x, y)
3693 Imager::ImgRaw im
3694 int x
3695 int y;
3696 PREINIT:
3697 i_fcolor *color;
3698 CODE:
3699 color = (i_fcolor *)mymalloc(sizeof(i_fcolor));
3700 if (i_gpixf(im, x, y, color) == 0) {
a659442a
TC
3701 RETVAL = NEWSV(0,0);
3702 sv_setref_pv(RETVAL, "Imager::Color::Float", (void *)color);
faa9b3e7
TC
3703 }
3704 else {
3705 myfree(color);
a659442a 3706 RETVAL = &PL_sv_undef;
faa9b3e7 3707 }
a659442a
TC
3708 OUTPUT:
3709 RETVAL
3710
faa9b3e7
TC
3711void
3712i_glin(im, l, r, y)
3713 Imager::ImgRaw im
3714 int l
3715 int r
3716 int y
3717 PREINIT:
3718 i_color *vals;
3719 int count, i;
3720 PPCODE:
3721 if (l < r) {
3722 vals = mymalloc((r-l) * sizeof(i_color));
3723 count = i_glin(im, l, r, y, vals);
ca4d914e
TC
3724 if (GIMME_V == G_ARRAY) {
3725 EXTEND(SP, count);
3726 for (i = 0; i < count; ++i) {
3727 SV *sv;
3728 i_color *col = mymalloc(sizeof(i_color));
3729 *col = vals[i];
3730 sv = sv_newmortal();
3731 sv_setref_pv(sv, "Imager::Color", (void *)col);
3732 PUSHs(sv);
3733 }
3734 }
3735 else if (count) {
3736 EXTEND(SP, 1);
3737 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_color))));
faa9b3e7
TC
3738 }
3739 myfree(vals);
3740 }
3741
3742void
3743i_glinf(im, l, r, y)
3744 Imager::ImgRaw im
3745 int l
3746 int r
3747 int y
3748 PREINIT:
3749 i_fcolor *vals;
3750 int count, i;
3751 PPCODE:
3752 if (l < r) {
3753 vals = mymalloc((r-l) * sizeof(i_fcolor));
3754 count = i_glinf(im, l, r, y, vals);
ca4d914e
TC
3755 if (GIMME_V == G_ARRAY) {
3756 EXTEND(SP, count);
3757 for (i = 0; i < count; ++i) {
3758 SV *sv;
3759 i_fcolor *col = mymalloc(sizeof(i_fcolor));
3760 *col = vals[i];
3761 sv = sv_newmortal();
3762 sv_setref_pv(sv, "Imager::Color::Float", (void *)col);
3763 PUSHs(sv);
3764 }
3765 }
3766 else if (count) {
3767 EXTEND(SP, 1);
3768 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_fcolor))));
faa9b3e7
TC
3769 }
3770 myfree(vals);
3771 }
3772
3773Imager::ImgRaw
3774i_img_16_new(x, y, ch)
3775 int x
3776 int y
3777 int ch
3778
365ea842
TC
3779Imager::ImgRaw
3780i_img_double_new(x, y, ch)
3781 int x
3782 int y
3783 int ch
3784
faa9b3e7
TC
3785undef_int
3786i_tags_addn(im, name, code, idata)
3787 Imager::ImgRaw im
3788 int code
3789 int idata
3790 PREINIT:
3791 char *name;
3792 STRLEN len;
3793 CODE:
3794 if (SvOK(ST(1)))
3795 name = SvPV(ST(1), len);
3796 else
3797 name = NULL;
3798 RETVAL = i_tags_addn(&im->tags, name, code, idata);
3799 OUTPUT:
3800 RETVAL
3801
3802undef_int
3803i_tags_add(im, name, code, data, idata)
3804 Imager::ImgRaw im
3805 int code
3806 int idata
3807 PREINIT:
3808 char *name;
3809 char *data;
3810 STRLEN len;
3811 CODE:
3812 if (SvOK(ST(1)))
3813 name = SvPV(ST(1), len);
3814 else
3815 name = NULL;
3816 if (SvOK(ST(3)))
3817 data = SvPV(ST(3), len);
3818 else {
3819 data = NULL;
3820 len = 0;
3821 }
3822 RETVAL = i_tags_add(&im->tags, name, code, data, len, idata);
3823 OUTPUT:
3824 RETVAL
3825
3826SV *
3827i_tags_find(im, name, start)
3828 Imager::ImgRaw im
3829 char *name
3830 int start
3831 PREINIT:
3832 int entry;
3833 CODE:
3834 if (i_tags_find(&im->tags, name, start, &entry)) {
3835 if (entry == 0)
a659442a 3836 RETVAL = newSVpv("0 but true", 0);
faa9b3e7 3837 else
a659442a 3838 RETVAL = newSViv(entry);
faa9b3e7 3839 } else {
a659442a 3840 RETVAL = &PL_sv_undef;
faa9b3e7 3841 }
a659442a
TC
3842 OUTPUT:
3843 RETVAL
faa9b3e7
TC
3844
3845SV *
3846i_tags_findn(im, code, start)
3847 Imager::ImgRaw im
3848 int code
3849 int start
3850 PREINIT:
3851 int entry;
3852 CODE:
3853 if (i_tags_findn(&im->tags, code, start, &entry)) {
3854 if (entry == 0)
a659442a 3855 RETVAL = newSVpv("0 but true", 0);
faa9b3e7 3856 else
a659442a 3857 RETVAL = newSViv(entry);
faa9b3e7 3858 }
a659442a
TC
3859 else {
3860 RETVAL = &PL_sv_undef;
3861 }
3862 OUTPUT:
3863 RETVAL
faa9b3e7
TC
3864
3865int
3866i_tags_delete(im, entry)
3867 Imager::ImgRaw im
3868 int entry
3869 CODE:
3870 RETVAL = i_tags_delete(&im->tags, entry);
3871 OUTPUT:
3872 RETVAL
3873
3874int
3875i_tags_delbyname(im, name)
3876 Imager::ImgRaw im
3877 char * name
3878 CODE:
3879 RETVAL = i_tags_delbyname(&im->tags, name);
3880 OUTPUT:
3881 RETVAL
3882
3883int
3884i_tags_delbycode(im, code)
3885 Imager::ImgRaw im
3886 int code
3887 CODE:
3888 RETVAL = i_tags_delbycode(&im->tags, code);
3889 OUTPUT:
3890 RETVAL
3891
3892void
3893i_tags_get(im, index)
3894 Imager::ImgRaw im
3895 int index
3896 PPCODE:
3897 if (index >= 0 && index < im->tags.count) {
3898 i_img_tag *entry = im->tags.tags + index;
3899 EXTEND(SP, 5);
3900
3901 if (entry->name) {
3902 PUSHs(sv_2mortal(newSVpv(entry->name, 0)));
3903 }
3904 else {
3905 PUSHs(sv_2mortal(newSViv(entry->code)));
3906 }
3907 if (entry->data) {
3908 PUSHs(sv_2mortal(newSVpvn(entry->data, entry->size)));
3909 }
3910 else {
3911 PUSHs(sv_2mortal(newSViv(entry->idata)));
3912 }
3913 }
3914
241defe8
TC
3915void
3916i_tags_get_string(im, what_sv)
3917 Imager::ImgRaw im
3918 SV *what_sv
3919 PREINIT:
3920 char const *name = NULL;
3921 int code;
3922 char buffer[200];
241defe8
TC
3923 PPCODE:
3924 if (SvIOK(what_sv)) {
3925 code = SvIV(what_sv);
3926 name = NULL;
3927 }
3928 else {
3929 name = SvPV_nolen(what_sv);
3930 code = 0;
3931 }
3932 if (i_tags_get_string(&im->tags, name, code, buffer, sizeof(buffer))) {
3933 EXTEND(SP, 1);
3934 PUSHs(sv_2mortal(newSVpv(buffer, 0)));
3935 }
3936
faa9b3e7
TC
3937int
3938i_tags_count(im)
3939 Imager::ImgRaw im
3940 CODE:
3941 RETVAL = im->tags.count;
3942 OUTPUT:
3943 RETVAL
3944
3945#ifdef HAVE_WIN32
3946
3947void
3948i_wf_bbox(face, size, text)
3949 char *face
3950 int size
3951 char *text
3952 PREINIT:
3799c4d1 3953 int cords[BOUNDING_BOX_COUNT];
0ab90434 3954 int rc, i;
faa9b3e7 3955 PPCODE:
3799c4d1
TC
3956 if (rc = i_wf_bbox(face, size, text, strlen(text), cords)) {
3957 EXTEND(SP, rc);
3958 for (i = 0; i < rc; ++i)
3959 PUSHs(sv_2mortal(newSViv(cords[i])));
faa9b3e7
TC
3960 }
3961
3962undef_int
3963i_wf_text(face, im, tx, ty, cl, size, text, align, aa)
3964 char *face
3965 Imager::ImgRaw im
3966 int tx
3967 int ty
3968 Imager::Color cl
3969 int size
3970 char *text
3971 int align
3972 int aa
3973 CODE:
3974 RETVAL = i_wf_text(face, im, tx, ty, cl, size, text, strlen(text),
3975 align, aa);
3976 OUTPUT:
3977 RETVAL
3978
3979undef_int
3980i_wf_cp(face, im, tx, ty, channel, size, text, align, aa)
3981 char *face
3982 Imager::ImgRaw im
3983 int tx
3984 int ty
3985 int channel
3986 int size
3987 char *text
3988 int align
3989 int aa
f5991c03 3990 CODE:
faa9b3e7
TC
3991 RETVAL = i_wf_cp(face, im, tx, ty, channel, size, text, strlen(text),
3992 align, aa);
f5991c03
TC
3993 OUTPUT:
3994 RETVAL
02d1d628 3995
8457948a
TC
3996undef_int
3997i_wf_addfont(font)
3998 char *font
faa9b3e7
TC
3999
4000#endif
4001
4002#ifdef HAVE_FT2
4003
4004MODULE = Imager PACKAGE = Imager::Font::FT2 PREFIX=FT2_
4005
4006#define FT2_DESTROY(font) i_ft2_destroy(font)
4007
4008void
4009FT2_DESTROY(font)
4010 Imager::Font::FT2 font
4011
4012MODULE = Imager PACKAGE = Imager::Font::FreeType2
4013
4014Imager::Font::FT2
4015i_ft2_new(name, index)
4016 char *name
4017 int index
4018
4019undef_int
4020i_ft2_setdpi(font, xdpi, ydpi)
4021 Imager::Font::FT2 font
4022 int xdpi
4023 int ydpi
4024
4025void
4026i_ft2_getdpi(font)
4027 Imager::Font::FT2 font
4028 PREINIT:
4029 int xdpi, ydpi;
4030 CODE:
4031 if (i_ft2_getdpi(font, &xdpi, &ydpi)) {
4032 EXTEND(SP, 2);
4033 PUSHs(sv_2mortal(newSViv(xdpi)));
4034 PUSHs(sv_2mortal(newSViv(ydpi)));
4035 }
4036
4037undef_int
4038i_ft2_sethinting(font, hinting)
4039 Imager::Font::FT2 font
4040 int hinting
4041
4042undef_int
4043i_ft2_settransform(font, matrix)
4044 Imager::Font::FT2 font
4045 PREINIT:
4046 double matrix[6];
4047 int len;
4048 AV *av;
4049 SV *sv1;
4050 int i;
4051 CODE:
4052 if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV)
4053 croak("i_ft2_settransform: parameter 2 must be an array ref\n");
4054 av=(AV*)SvRV(ST(1));
4055 len=av_len(av)+1;
4056 if (len > 6)
4057 len = 6;
4058 for (i = 0; i < len; ++i) {
4059 sv1=(*(av_fetch(av,i,0)));
4060 matrix[i] = SvNV(sv1);
4061 }
4062 for (; i < 6; ++i)
4063 matrix[i] = 0;
4064 RETVAL = i_ft2_settransform(font, matrix);
4065 OUTPUT:
4066 RETVAL
4067
4068void
3799c4d1 4069i_ft2_bbox(font, cheight, cwidth, text_sv, utf8)
faa9b3e7
TC
4070 Imager::Font::FT2 font
4071 double cheight
4072 double cwidth
3799c4d1 4073 SV *text_sv
5cb9270b 4074 int utf8
faa9b3e7 4075 PREINIT:
3799c4d1 4076 int bbox[BOUNDING_BOX_COUNT];
faa9b3e7 4077 int i;
3799c4d1
TC
4078 char *text;
4079 STRLEN text_len;
4080 int rc;
faa9b3e7 4081 PPCODE:
3799c4d1 4082 text = SvPV(text_sv, text_len);
5cb9270b 4083#ifdef SvUTF8
3799c4d1 4084 if (SvUTF8(text_sv))
5cb9270b
TC
4085 utf8 = 1;
4086#endif
3799c4d1
TC
4087 rc = i_ft2_bbox(font, cheight, cwidth, text, text_len, bbox, utf8);
4088 if (rc) {
4089 EXTEND(SP, rc);
4090 for (i = 0; i < rc; ++i)
faa9b3e7
TC
4091 PUSHs(sv_2mortal(newSViv(bbox[i])));
4092 }
4093
4094void
4095i_ft2_bbox_r(font, cheight, cwidth, text, vlayout, utf8)
4096 Imager::Font::FT2 font
4097 double cheight
4098 double cwidth
4099 char *text
4100 int vlayout
4101 int utf8
4102 PREINIT:
4103 int bbox[8];
4104 int i;
4105 PPCODE:
4106#ifdef SvUTF8
4107 if (SvUTF8(ST(3)))
4108 utf8 = 1;
4109#endif
4110 if (i_ft2_bbox_r(font, cheight, cwidth, text, strlen(text), vlayout,
4111 utf8, bbox)) {
4112 EXTEND(SP, 8);
4113 for (i = 0; i < 8; ++i)
4114 PUSHs(sv_2mortal(newSViv(bbox[i])));
4115 }
4116
4117undef_int
4118i_ft2_text(font, im, tx, ty, cl, cheight, cwidth, text, align, aa, vlayout, utf8)
4119 Imager::Font::FT2 font
4120 Imager::ImgRaw im
4121 int tx
4122 int ty
4123 Imager::Color cl
4124 double cheight
4125 double cwidth
4126 int align
4127 int aa
4128 int vlayout
4129 int utf8
4130 PREINIT:
4131 char *text;
4132 STRLEN len;
4133 CODE:
4134#ifdef SvUTF8
4135 if (SvUTF8(ST(7))) {
4136 utf8 = 1;
4137 }
4138#endif
4139 text = SvPV(ST(7), len);
4140 RETVAL = i_ft2_text(font, im, tx, ty, cl, cheight, cwidth, text,
4141 len, align, aa, vlayout, utf8);
4142 OUTPUT:
4143 RETVAL
4144
4145undef_int
4146i_ft2_cp(font, im, tx, ty, channel, cheight, cwidth, text, align, aa, vlayout, utf8)
4147 Imager::Font::FT2 font
4148 Imager::ImgRaw im
4149 int tx
4150 int ty
4151 int channel
4152 double cheight
4153 double cwidth
4154 char *text
4155 int align
4156 int aa
4157 int vlayout
4158 int utf8
4159 CODE:
4160#ifdef SvUTF8
4161 if (SvUTF8(ST(7)))
4162 utf8 = 1;
4163#endif
4164 RETVAL = i_ft2_cp(font, im, tx, ty, channel, cheight, cwidth, text,
4165 strlen(text), align, aa, vlayout, 1);
4166 OUTPUT:
4167 RETVAL
4168
4169void
4170ft2_transform_box(font, x0, x1, x2, x3)
4171 Imager::Font::FT2 font
4172 int x0
4173 int x1
4174 int x2
4175 int x3
4176 PREINIT:
4177 int box[4];
4178 PPCODE:
4179 box[0] = x0; box[1] = x1; box[2] = x2; box[3] = x3;
4180 ft2_transform_box(font, box);
4181 EXTEND(SP, 4);
4182 PUSHs(sv_2mortal(newSViv(box[0])));
4183 PUSHs(sv_2mortal(newSViv(box[1])));
4184 PUSHs(sv_2mortal(newSViv(box[2])));
4185 PUSHs(sv_2mortal(newSViv(box[3])));
3dec2c92
TC
4186
4187void
eeaa33fd 4188i_ft2_has_chars(handle, text_sv, utf8)
3dec2c92 4189 Imager::Font::FT2 handle
eeaa33fd 4190 SV *text_sv
3dec2c92
TC
4191 int utf8
4192 PREINIT:
4193 char *text;
4194 STRLEN len;
4195 char *work;
4196 int count;
4197 int i;
4198 PPCODE:
4199#ifdef SvUTF8
eeaa33fd 4200 if (SvUTF8(text_sv))
3dec2c92
TC
4201 utf8 = 1;
4202#endif
eeaa33fd 4203 text = SvPV(text_sv, len);
3dec2c92
TC
4204 work = mymalloc(len);
4205 count = i_ft2_has_chars(handle, text, len, utf8, work);
4206 if (GIMME_V == G_ARRAY) {
4207 EXTEND(SP, count);
4208 for (i = 0; i < count; ++i) {
4209 PUSHs(sv_2mortal(newSViv(work[i])));
4210 }
4211 }
4212 else {
4213 EXTEND(SP, 1);
4214 PUSHs(sv_2mortal(newSVpv(work, count)));
4215 }
4216 myfree(work);
4217
3799c4d1
TC
4218void
4219i_ft2_face_name(handle)
4220 Imager::Font::FT2 handle
4221 PREINIT:
4222 char name[255];
4223 int len;
4224 PPCODE:
4225 len = i_ft2_face_name(handle, name, sizeof(name));
4226 if (len) {
4227 EXTEND(SP, 1);
4228 PUSHs(sv_2mortal(newSVpv(name, 0)));
4229 }
4230
042cdaea
TC
4231undef_int
4232i_ft2_can_face_name()
4233
19fa4baf 4234void
a4168bea 4235i_ft2_glyph_name(handle, text_sv, utf8 = 0, reliable_only = 1)
3799c4d1
TC
4236 Imager::Font::FT2 handle
4237 SV *text_sv
4238 int utf8
a4168bea 4239 int reliable_only
3799c4d1
TC
4240 PREINIT:
4241 char const *text;
4242 STRLEN work_len;
4243 int len;
4244 int outsize;
4245 char name[255];
4246 PPCODE:
4247#ifdef SvUTF8
4248 if (SvUTF8(text_sv))
4249 utf8 = 1;
4250#endif
4251 text = SvPV(text_sv, work_len);
4252 len = work_len;
4253 while (len) {
a4168bea 4254 unsigned long ch;
3799c4d1
TC
4255 if (utf8) {
4256 ch = i_utf8_advance(&text, &len);
4257 if (ch == ~0UL) {
4258 i_push_error(0, "invalid UTF8 character");
4259 break;
4260 }
4261 }
4262 else {
4263 ch = *text++;
4264 --len;
4265 }
4266 EXTEND(SP, 1);