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