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