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