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