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