look at the correct %Config library and include paths
[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
3b000586
TC
954#define i_img_get_width(im) ((im)->xsize)
955#define i_img_get_height(im) ((im)->ysize)
956
02d1d628
AMH
957MODULE = Imager PACKAGE = Imager::Color PREFIX = ICL_
958
959Imager::Color
960ICL_new_internal(r,g,b,a)
961 unsigned char r
962 unsigned char g
963 unsigned char b
964 unsigned char a
965
966void
967ICL_DESTROY(cl)
968 Imager::Color cl
969
970
29106a11 971void
02d1d628
AMH
972ICL_set_internal(cl,r,g,b,a)
973 Imager::Color cl
974 unsigned char r
975 unsigned char g
976 unsigned char b
977 unsigned char a
29106a11 978 PPCODE:
46062ab6 979 ICL_set_internal(cl, r, g, b, a);
29106a11
TC
980 EXTEND(SP, 1);
981 PUSHs(ST(0));
02d1d628
AMH
982
983void
984ICL_info(cl)
985 Imager::Color cl
986
987
988void
989ICL_rgba(cl)
990 Imager::Color cl
991 PPCODE:
992 EXTEND(SP, 4);
993 PUSHs(sv_2mortal(newSVnv(cl->rgba.r)));
994 PUSHs(sv_2mortal(newSVnv(cl->rgba.g)));
995 PUSHs(sv_2mortal(newSVnv(cl->rgba.b)));
996 PUSHs(sv_2mortal(newSVnv(cl->rgba.a)));
997
efdc2568
TC
998Imager::Color
999i_hsv_to_rgb(c)
1000 Imager::Color c
1001 CODE:
1002 RETVAL = mymalloc(sizeof(i_color));
1003 *RETVAL = *c;
1004 i_hsv_to_rgb(RETVAL);
1005 OUTPUT:
1006 RETVAL
1007
1008Imager::Color
1009i_rgb_to_hsv(c)
1010 Imager::Color c
1011 CODE:
1012 RETVAL = mymalloc(sizeof(i_color));
1013 *RETVAL = *c;
1014 i_rgb_to_hsv(RETVAL);
1015 OUTPUT:
1016 RETVAL
1017
02d1d628
AMH
1018
1019
faa9b3e7 1020MODULE = Imager PACKAGE = Imager::Color::Float PREFIX=ICLF_
02d1d628 1021
faa9b3e7
TC
1022Imager::Color::Float
1023ICLF_new_internal(r, g, b, a)
1024 double r
1025 double g
1026 double b
1027 double a
1028
1029void
1030ICLF_DESTROY(cl)
1031 Imager::Color::Float cl
02d1d628 1032
faa9b3e7
TC
1033void
1034ICLF_rgba(cl)
1035 Imager::Color::Float cl
1036 PREINIT:
1037 int ch;
1038 PPCODE:
1039 EXTEND(SP, MAXCHANNELS);
1040 for (ch = 0; ch < MAXCHANNELS; ++ch) {
1041 /* printf("%d: %g\n", ch, cl->channel[ch]); */
1042 PUSHs(sv_2mortal(newSVnv(cl->channel[ch])));
1043 }
1044
1045void
1046ICLF_set_internal(cl,r,g,b,a)
1047 Imager::Color::Float cl
1048 double r
1049 double g
1050 double b
1051 double a
1052 PPCODE:
1053 cl->rgba.r = r;
1054 cl->rgba.g = g;
1055 cl->rgba.b = b;
1056 cl->rgba.a = a;
1057 EXTEND(SP, 1);
1058 PUSHs(ST(0));
02d1d628 1059
efdc2568
TC
1060Imager::Color::Float
1061i_hsv_to_rgb(c)
1062 Imager::Color::Float c
1063 CODE:
1064 RETVAL = mymalloc(sizeof(i_fcolor));
1065 *RETVAL = *c;
1066 i_hsv_to_rgbf(RETVAL);
1067 OUTPUT:
1068 RETVAL
1069
1070Imager::Color::Float
1071i_rgb_to_hsv(c)
1072 Imager::Color::Float c
1073 CODE:
1074 RETVAL = mymalloc(sizeof(i_fcolor));
1075 *RETVAL = *c;
1076 i_rgb_to_hsvf(RETVAL);
1077 OUTPUT:
1078 RETVAL
efdc2568 1079
02d1d628
AMH
1080MODULE = Imager PACKAGE = Imager::ImgRaw PREFIX = IIM_
1081
1082Imager::ImgRaw
1083IIM_new(x,y,ch)
1084 int x
1085 int y
1086 int ch
1087
1088void
1089IIM_DESTROY(im)
1090 Imager::ImgRaw im
1091
1092
1093
1094MODULE = Imager PACKAGE = Imager
1095
1096PROTOTYPES: ENABLE
1097
1098
1099Imager::IO
1100io_new_fd(fd)
1101 int fd
1102
1103Imager::IO
1104io_new_bufchain()
1105
1106
4dfa5522
AMH
1107Imager::IO
1108io_new_buffer(data)
1109 char *data
1110 PREINIT:
1111 size_t length;
4dfa5522
AMH
1112 CODE:
1113 SvPV(ST(0), length);
1114 SvREFCNT_inc(ST(0));
1115 RETVAL = io_new_buffer(data, length, my_SvREFCNT_dec, ST(0));
1116 OUTPUT:
1117 RETVAL
10461f9a
TC
1118
1119Imager::IO
1120io_new_cb(writecb, readcb, seekcb, closecb, maxwrite = CBDATA_BUFSIZE)
1121 SV *writecb;
1122 SV *readcb;
1123 SV *seekcb;
1124 SV *closecb;
1125 int maxwrite;
1126 PREINIT:
1127 struct cbdata *cbd;
1128 CODE:
1129 cbd = mymalloc(sizeof(struct cbdata));
1130 SvREFCNT_inc(writecb);
1131 cbd->writecb = writecb;
1132 SvREFCNT_inc(readcb);
1133 cbd->readcb = readcb;
1134 SvREFCNT_inc(seekcb);
1135 cbd->seekcb = seekcb;
1136 SvREFCNT_inc(closecb);
1137 cbd->closecb = closecb;
1138 cbd->reading = cbd->writing = cbd->where = cbd->used = 0;
1139 if (maxwrite > CBDATA_BUFSIZE)
1140 maxwrite = CBDATA_BUFSIZE;
1141 cbd->maxlength = maxwrite;
1142 RETVAL = io_new_cb(cbd, io_reader, io_writer, io_seeker, io_closer,
1143 io_destroyer);
1144 OUTPUT:
1145 RETVAL
4dfa5522 1146
02d1d628
AMH
1147void
1148io_slurp(ig)
1149 Imager::IO ig
1150 PREINIT:
1151 unsigned char* data;
4dfa5522 1152 size_t tlength;
02d1d628
AMH
1153 PPCODE:
1154 data = NULL;
1155 tlength = io_slurp(ig, &data);
02d1d628 1156 EXTEND(SP,1);
26fd367b 1157 PUSHs(sv_2mortal(newSVpv((char *)data,tlength)));
02d1d628
AMH
1158 myfree(data);
1159
1160
77157728
TC
1161undef_int
1162i_set_image_file_limits(width, height, bytes)
1163 int width
1164 int height
1165 int bytes
1166
1167void
1168i_get_image_file_limits()
1169 PREINIT:
1170 int width, height, bytes;
1171 PPCODE:
1172 if (i_get_image_file_limits(&width, &height, &bytes)) {
1173 EXTEND(SP, 3);
1174 PUSHs(sv_2mortal(newSViv(width)));
1175 PUSHs(sv_2mortal(newSViv(height)));
1176 PUSHs(sv_2mortal(newSViv(bytes)));
1177 }
1178
eda1622c
TC
1179MODULE = Imager PACKAGE = Imager::IO PREFIX = i_io_
1180
1181int
1182i_io_write(ig, data_sv)
1183 Imager::IO ig
1184 SV *data_sv
1185 PREINIT:
1186 void *data;
1187 STRLEN size;
1188 CODE:
1189#ifdef SvUTF8
1190 if (SvUTF8(data_sv)) {
1191 data_sv = sv_2mortal(newSVsv(data_sv));
1f6c1c10 1192 /* yes, we want this to croak() if the SV can't be downgraded */
eda1622c
TC
1193 sv_utf8_downgrade(data_sv, FALSE);
1194 }
1195#endif
1196 data = SvPV(data_sv, size);
1197 RETVAL = i_io_write(ig, data, size);
1198 OUTPUT:
1199 RETVAL
1200
1f6c1c10 1201void
eda1622c
TC
1202i_io_read(ig, buffer_sv, size)
1203 Imager::IO ig
1204 SV *buffer_sv
1205 int size
1206 PREINIT:
1207 void *buffer;
1208 int result;
1f6c1c10
TC
1209 PPCODE:
1210 if (size <= 0)
eda1622c
TC
1211 croak("size negative in call to i_io_read()");
1212 /* prevent an undefined value warning if they supplied an
1213 undef buffer.
1214 Orginally conditional on !SvOK(), but this will prevent the
1215 downgrade from croaking */
1216 sv_setpvn(buffer_sv, "", 0);
1217#ifdef SvUTF8
1218 if (SvUTF8(buffer_sv))
1219 sv_utf8_downgrade(buffer_sv, FALSE);
1220#endif
1221 buffer = SvGROW(buffer_sv, size+1);
1222 result = i_io_read(ig, buffer, size);
1f6c1c10
TC
1223 if (result >= 0) {
1224 SvCUR_set(buffer_sv, result);
1225 *SvEND(buffer_sv) = '\0';
1226 SvPOK_only(buffer_sv);
1227 EXTEND(SP, 1);
1228 PUSHs(sv_2mortal(newSViv(result)));
eda1622c 1229 }
1f6c1c10
TC
1230 ST(1) = buffer_sv;
1231 SvSETMAGIC(ST(1));
1232
1233void
1234i_io_read2(ig, size)
1235 Imager::IO ig
1236 int size
1237 PREINIT:
1238 SV *buffer_sv;
1239 void *buffer;
1240 int result;
1241 PPCODE:
1242 if (size <= 0)
1243 croak("size negative in call to i_io_read2()");
1244 buffer_sv = newSV(size);
1245 buffer = SvGROW(buffer_sv, size+1);
1246 result = i_io_read(ig, buffer, size);
1247 if (result >= 0) {
eda1622c
TC
1248 SvCUR_set(buffer_sv, result);
1249 *SvEND(buffer_sv) = '\0';
1250 SvPOK_only(buffer_sv);
1f6c1c10
TC
1251 EXTEND(SP, 1);
1252 PUSHs(sv_2mortal(buffer_sv));
eda1622c 1253 }
1f6c1c10
TC
1254 else {
1255 /* discard it */
1256 SvREFCNT_dec(buffer_sv);
1257 }
eda1622c
TC
1258
1259int
1260i_io_seek(ig, position, whence)
1261 Imager::IO ig
1262 long position
1263 int whence
c3cc977e 1264
1f6c1c10 1265int
eda1622c
TC
1266i_io_close(ig)
1267 Imager::IO ig
1268
1269void
1270i_io_DESTROY(ig)
c3cc977e
AMH
1271 Imager::IO ig
1272
ffddd407
TC
1273int
1274i_io_CLONE_SKIP(...)
1275 CODE:
1276 RETVAL = 1;
1277 OUTPUT:
1278 RETVAL
1279
c3cc977e
AMH
1280MODULE = Imager PACKAGE = Imager
1281
1282PROTOTYPES: ENABLE
1283
02d1d628
AMH
1284void
1285i_list_formats()
1286 PREINIT:
1287 char* item;
1288 int i;
1289 PPCODE:
1290 i=0;
1291 while( (item=i_format_list[i++]) != NULL ) {
1292 EXTEND(SP, 1);
1293 PUSHs(sv_2mortal(newSVpv(item,0)));
1294 }
1295
1296undef_int
1297i_has_format(frmt)
1298 char* frmt
1299
1300Imager::ImgRaw
1301i_img_new()
1302
1303Imager::ImgRaw
1304i_img_empty(im,x,y)
1305 Imager::ImgRaw im
1306 int x
1307 int y
1308
1309Imager::ImgRaw
1310i_img_empty_ch(im,x,y,ch)
1311 Imager::ImgRaw im
1312 int x
1313 int y
1314 int ch
1315
ec76939c
TC
1316Imager::ImgRaw
1317i_sametype(im, x, y)
1318 Imager::ImgRaw im
1319 int x
1320 int y
1321
1322Imager::ImgRaw
1323i_sametype_chans(im, x, y, channels)
1324 Imager::ImgRaw im
1325 int x
1326 int y
1327 int channels
1328
02d1d628 1329void
bd8052a6
TC
1330i_init_log(name_sv,level)
1331 SV* name_sv
02d1d628 1332 int level
bd8052a6
TC
1333 PREINIT:
1334 const char *name = SvOK(name_sv) ? SvPV_nolen(name_sv) : NULL;
1335 CODE:
1336 i_init_log(name, level);
02d1d628 1337
7f882a01 1338void
bf1573f9 1339i_log_entry(string,level)
7f882a01
AMH
1340 char* string
1341 int level
1342
1343
02d1d628
AMH
1344void
1345i_img_exorcise(im)
1346 Imager::ImgRaw im
1347
1348void
1349i_img_destroy(im)
1350 Imager::ImgRaw im
1351
1352void
1353i_img_info(im)
1354 Imager::ImgRaw im
1355 PREINIT:
1356 int info[4];
1357 PPCODE:
1358 i_img_info(im,info);
1359 EXTEND(SP, 4);
1360 PUSHs(sv_2mortal(newSViv(info[0])));
1361 PUSHs(sv_2mortal(newSViv(info[1])));
1362 PUSHs(sv_2mortal(newSViv(info[2])));
1363 PUSHs(sv_2mortal(newSViv(info[3])));
1364
1365
1366
1367
1368void
1369i_img_setmask(im,ch_mask)
1370 Imager::ImgRaw im
1371 int ch_mask
1372
1373int
1374i_img_getmask(im)
1375 Imager::ImgRaw im
1376
1377int
1378i_img_getchannels(im)
1379 Imager::ImgRaw im
1380
1381void
1382i_img_getdata(im)
1383 Imager::ImgRaw im
1384 PPCODE:
1385 EXTEND(SP, 1);
26fd367b
TC
1386 PUSHs(im->idata ?
1387 sv_2mortal(newSVpv((char *)im->idata, im->bytes))
faa9b3e7 1388 : &PL_sv_undef);
02d1d628 1389
3b000586
TC
1390IV
1391i_img_get_width(im)
1392 Imager::ImgRaw im
1393
1394IV
1395i_img_get_height(im)
1396 Imager::ImgRaw im
1397
1398
bd8052a6
TC
1399void
1400i_img_is_monochrome(im)
1401 Imager::ImgRaw im
1402 PREINIT:
1403 int zero_is_white;
1404 int result;
1405 PPCODE:
1406 result = i_img_is_monochrome(im, &zero_is_white);
1407 if (result) {
1408 if (GIMME_V == G_ARRAY) {
1409 EXTEND(SP, 2);
1410 PUSHs(&PL_sv_yes);
1411 PUSHs(sv_2mortal(newSViv(zero_is_white)));
1412 }
1413 else {
1414 EXTEND(SP, 1);
1415 PUSHs(&PL_sv_yes);
1416 }
1417 }
02d1d628
AMH
1418
1419void
aa833c97 1420i_line(im,x1,y1,x2,y2,val,endp)
02d1d628
AMH
1421 Imager::ImgRaw im
1422 int x1
1423 int y1
1424 int x2
1425 int y2
1426 Imager::Color val
aa833c97 1427 int endp
02d1d628
AMH
1428
1429void
b437ce0a 1430i_line_aa(im,x1,y1,x2,y2,val,endp)
02d1d628
AMH
1431 Imager::ImgRaw im
1432 int x1
1433 int y1
1434 int x2
1435 int y2
1436 Imager::Color val
b437ce0a 1437 int endp
02d1d628
AMH
1438
1439void
1440i_box(im,x1,y1,x2,y2,val)
1441 Imager::ImgRaw im
1442 int x1
1443 int y1
1444 int x2
1445 int y2
1446 Imager::Color val
1447
1448void
1449i_box_filled(im,x1,y1,x2,y2,val)
1450 Imager::ImgRaw im
1451 int x1
1452 int y1
1453 int x2
1454 int y2
1455 Imager::Color val
1456
f1ac5027
TC
1457void
1458i_box_cfill(im,x1,y1,x2,y2,fill)
1459 Imager::ImgRaw im
1460 int x1
1461 int y1
1462 int x2
1463 int y2
1464 Imager::FillHandle fill
1465
02d1d628
AMH
1466void
1467i_arc(im,x,y,rad,d1,d2,val)
1468 Imager::ImgRaw im
1469 int x
1470 int y
1471 float rad
1472 float d1
1473 float d2
1474 Imager::Color val
1475
a8652edf
TC
1476void
1477i_arc_aa(im,x,y,rad,d1,d2,val)
1478 Imager::ImgRaw im
1479 double x
1480 double y
1481 double rad
1482 double d1
1483 double d2
1484 Imager::Color val
1485
f1ac5027
TC
1486void
1487i_arc_cfill(im,x,y,rad,d1,d2,fill)
1488 Imager::ImgRaw im
1489 int x
1490 int y
1491 float rad
1492 float d1
1493 float d2
1494 Imager::FillHandle fill
1495
a8652edf
TC
1496void
1497i_arc_aa_cfill(im,x,y,rad,d1,d2,fill)
1498 Imager::ImgRaw im
1499 double x
1500 double y
1501 double rad
1502 double d1
1503 double d2
1504 Imager::FillHandle fill
02d1d628
AMH
1505
1506
6af18d2b
AMH
1507void
1508i_circle_aa(im,x,y,rad,val)
1509 Imager::ImgRaw im
1510 float x
1511 float y
1512 float rad
1513 Imager::Color val
1514
40068b33
TC
1515int
1516i_circle_out(im,x,y,rad,val)
1517 Imager::ImgRaw im
1518 i_img_dim x
1519 i_img_dim y
1520 i_img_dim rad
1521 Imager::Color val
1522
1523int
1524i_circle_out_aa(im,x,y,rad,val)
1525 Imager::ImgRaw im
1526 i_img_dim x
1527 i_img_dim y
1528 i_img_dim rad
1529 Imager::Color val
1530
1531int
1532i_arc_out(im,x,y,rad,d1,d2,val)
1533 Imager::ImgRaw im
1534 i_img_dim x
1535 i_img_dim y
1536 i_img_dim rad
1537 float d1
1538 float d2
1539 Imager::Color val
1540
1541int
1542i_arc_out_aa(im,x,y,rad,d1,d2,val)
1543 Imager::ImgRaw im
1544 i_img_dim x
1545 i_img_dim y
1546 i_img_dim rad
1547 float d1
1548 float d2
1549 Imager::Color val
6af18d2b
AMH
1550
1551
02d1d628
AMH
1552void
1553i_bezier_multi(im,xc,yc,val)
1554 Imager::ImgRaw im
1555 Imager::Color val
1556 PREINIT:
1557 double *x,*y;
1558 int len;
1559 AV *av1;
1560 AV *av2;
1561 SV *sv1;
1562 SV *sv2;
1563 int i;
1564 PPCODE:
1565 ICL_info(val);
1566 if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_bezier_multi must be a reference to an array\n");
1567 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_bezier_multi must be a reference to an array\n");
1568 if (!SvROK(ST(2))) croak("Imager: Parameter 2 to i_bezier_multi must be a reference to an array\n");
1569 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 2 to i_bezier_multi must be a reference to an array\n");
1570 av1=(AV*)SvRV(ST(1));
1571 av2=(AV*)SvRV(ST(2));
1572 if (av_len(av1) != av_len(av2)) croak("Imager: x and y arrays to i_bezier_multi must be equal length\n");
1573 len=av_len(av1)+1;
1574 x=mymalloc( len*sizeof(double) );
1575 y=mymalloc( len*sizeof(double) );
1576 for(i=0;i<len;i++) {
1577 sv1=(*(av_fetch(av1,i,0)));
1578 sv2=(*(av_fetch(av2,i,0)));
1579 x[i]=(double)SvNV(sv1);
1580 y[i]=(double)SvNV(sv2);
1581 }
1582 i_bezier_multi(im,len,x,y,val);
1583 myfree(x);
1584 myfree(y);
1585
1586
1c5252ed 1587int
02d1d628
AMH
1588i_poly_aa(im,xc,yc,val)
1589 Imager::ImgRaw im
1590 Imager::Color val
1591 PREINIT:
1592 double *x,*y;
1593 int len;
1594 AV *av1;
1595 AV *av2;
1596 SV *sv1;
1597 SV *sv2;
1598 int i;
1c5252ed 1599 CODE:
02d1d628
AMH
1600 ICL_info(val);
1601 if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
1602 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
1603 if (!SvROK(ST(2))) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
1604 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa must be a reference to an array\n");
1605 av1=(AV*)SvRV(ST(1));
1606 av2=(AV*)SvRV(ST(2));
1607 if (av_len(av1) != av_len(av2)) croak("Imager: x and y arrays to i_poly_aa must be equal length\n");
1608 len=av_len(av1)+1;
1609 x=mymalloc( len*sizeof(double) );
1610 y=mymalloc( len*sizeof(double) );
1611 for(i=0;i<len;i++) {
1612 sv1=(*(av_fetch(av1,i,0)));
1613 sv2=(*(av_fetch(av2,i,0)));
1614 x[i]=(double)SvNV(sv1);
1615 y[i]=(double)SvNV(sv2);
1616 }
1c5252ed 1617 RETVAL = i_poly_aa(im,len,x,y,val);
02d1d628
AMH
1618 myfree(x);
1619 myfree(y);
1c5252ed
TC
1620 OUTPUT:
1621 RETVAL
02d1d628 1622
1c5252ed 1623int
43c5dacb
TC
1624i_poly_aa_cfill(im,xc,yc,fill)
1625 Imager::ImgRaw im
1626 Imager::FillHandle fill
1627 PREINIT:
1628 double *x,*y;
1629 int len;
1630 AV *av1;
1631 AV *av2;
1632 SV *sv1;
1633 SV *sv2;
1634 int i;
1c5252ed 1635 CODE:
43c5dacb
TC
1636 if (!SvROK(ST(1))) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
1637 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
1638 if (!SvROK(ST(2))) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
1639 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 1 to i_poly_aa_cfill must be a reference to an array\n");
1640 av1=(AV*)SvRV(ST(1));
1641 av2=(AV*)SvRV(ST(2));
1642 if (av_len(av1) != av_len(av2)) croak("Imager: x and y arrays to i_poly_aa_cfill must be equal length\n");
1643 len=av_len(av1)+1;
1644 x=mymalloc( len*sizeof(double) );
1645 y=mymalloc( len*sizeof(double) );
1646 for(i=0;i<len;i++) {
1647 sv1=(*(av_fetch(av1,i,0)));
1648 sv2=(*(av_fetch(av2,i,0)));
1649 x[i]=(double)SvNV(sv1);
1650 y[i]=(double)SvNV(sv2);
1651 }
1c5252ed 1652 RETVAL = i_poly_aa_cfill(im,len,x,y,fill);
43c5dacb
TC
1653 myfree(x);
1654 myfree(y);
1c5252ed
TC
1655 OUTPUT:
1656 RETVAL
43c5dacb 1657
02d1d628
AMH
1658
1659
a321d497 1660undef_int
02d1d628
AMH
1661i_flood_fill(im,seedx,seedy,dcol)
1662 Imager::ImgRaw im
1663 int seedx
1664 int seedy
1665 Imager::Color dcol
1666
a321d497 1667undef_int
cc6483e0
TC
1668i_flood_cfill(im,seedx,seedy,fill)
1669 Imager::ImgRaw im
1670 int seedx
1671 int seedy
1672 Imager::FillHandle fill
1673
3efb0915
TC
1674undef_int
1675i_flood_fill_border(im,seedx,seedy,dcol, border)
1676 Imager::ImgRaw im
1677 int seedx
1678 int seedy
1679 Imager::Color dcol
1680 Imager::Color border
1681
1682undef_int
1683i_flood_cfill_border(im,seedx,seedy,fill, border)
1684 Imager::ImgRaw im
1685 int seedx
1686 int seedy
1687 Imager::FillHandle fill
1688 Imager::Color border
1689
02d1d628
AMH
1690
1691void
1692i_copyto(im,src,x1,y1,x2,y2,tx,ty)
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
1702
1703void
1704i_copyto_trans(im,src,x1,y1,x2,y2,tx,ty,trans)
1705 Imager::ImgRaw im
1706 Imager::ImgRaw src
1707 int x1
1708 int y1
1709 int x2
1710 int y2
1711 int tx
1712 int ty
1713 Imager::Color trans
1714
92bda632
TC
1715Imager::ImgRaw
1716i_copy(src)
02d1d628
AMH
1717 Imager::ImgRaw src
1718
1719
faa9b3e7 1720undef_int
71dc4a83 1721i_rubthru(im,src,tx,ty,src_minx,src_miny,src_maxx,src_maxy)
02d1d628
AMH
1722 Imager::ImgRaw im
1723 Imager::ImgRaw src
1724 int tx
1725 int ty
71dc4a83
AMH
1726 int src_minx
1727 int src_miny
1728 int src_maxx
1729 int src_maxy
1730
9b1ec2b8
TC
1731undef_int
1732i_compose(out, src, out_left, out_top, src_left, src_top, width, height, combine = ic_normal, opacity = 0.0)
1733 Imager::ImgRaw out
1734 Imager::ImgRaw src
1735 int out_left
1736 int out_top
1737 int src_left
1738 int src_top
1739 int width
1740 int height
1741 int combine
1742 double opacity
1743
1744undef_int
1745i_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)
1746 Imager::ImgRaw out
1747 Imager::ImgRaw src
1748 Imager::ImgRaw mask
1749 int out_left
1750 int out_top
1751 int src_left
1752 int src_top
1753 int mask_left
1754 int mask_top
1755 int width
1756 int height
1757 int combine
1758 double opacity
02d1d628 1759
142c26ff
AMH
1760undef_int
1761i_flipxy(im, direction)
1762 Imager::ImgRaw im
1763 int direction
1764
faa9b3e7
TC
1765Imager::ImgRaw
1766i_rotate90(im, degrees)
1767 Imager::ImgRaw im
1768 int degrees
1769
1770Imager::ImgRaw
0d3b936e 1771i_rotate_exact(im, amount, ...)
faa9b3e7
TC
1772 Imager::ImgRaw im
1773 double amount
0d3b936e
TC
1774 PREINIT:
1775 i_color *backp = NULL;
1776 i_fcolor *fbackp = NULL;
1777 int i;
1778 SV * sv1;
1779 CODE:
1780 /* extract the bg colors if any */
1781 /* yes, this is kind of strange */
1782 for (i = 2; i < items; ++i) {
1783 sv1 = ST(i);
1784 if (sv_derived_from(sv1, "Imager::Color")) {
1785 IV tmp = SvIV((SV*)SvRV(sv1));
1786 backp = INT2PTR(i_color *, tmp);
1787 }
1788 else if (sv_derived_from(sv1, "Imager::Color::Float")) {
1789 IV tmp = SvIV((SV*)SvRV(sv1));
1790 fbackp = INT2PTR(i_fcolor *, tmp);
1791 }
1792 }
1793 RETVAL = i_rotate_exact_bg(im, amount, backp, fbackp);
1794 OUTPUT:
1795 RETVAL
faa9b3e7
TC
1796
1797Imager::ImgRaw
0d3b936e 1798i_matrix_transform(im, xsize, ysize, matrix, ...)
faa9b3e7
TC
1799 Imager::ImgRaw im
1800 int xsize
1801 int ysize
1802 PREINIT:
1803 double matrix[9];
1804 AV *av;
1805 IV len;
1806 SV *sv1;
1807 int i;
0d3b936e
TC
1808 i_color *backp = NULL;
1809 i_fcolor *fbackp = NULL;
faa9b3e7
TC
1810 CODE:
1811 if (!SvROK(ST(3)) || SvTYPE(SvRV(ST(3))) != SVt_PVAV)
1812 croak("i_matrix_transform: parameter 4 must be an array ref\n");
1813 av=(AV*)SvRV(ST(3));
1814 len=av_len(av)+1;
1815 if (len > 9)
1816 len = 9;
1817 for (i = 0; i < len; ++i) {
1818 sv1=(*(av_fetch(av,i,0)));
1819 matrix[i] = SvNV(sv1);
1820 }
1821 for (; i < 9; ++i)
1822 matrix[i] = 0;
0d3b936e
TC
1823 /* extract the bg colors if any */
1824 /* yes, this is kind of strange */
1825 for (i = 4; i < items; ++i) {
1826 sv1 = ST(i);
1827 if (sv_derived_from(sv1, "Imager::Color")) {
1828 IV tmp = SvIV((SV*)SvRV(sv1));
1829 backp = INT2PTR(i_color *, tmp);
1830 }
1831 else if (sv_derived_from(sv1, "Imager::Color::Float")) {
1832 IV tmp = SvIV((SV*)SvRV(sv1));
1833 fbackp = INT2PTR(i_fcolor *, tmp);
1834 }
1835 }
1836 RETVAL = i_matrix_transform_bg(im, xsize, ysize, matrix, backp, fbackp);
faa9b3e7
TC
1837 OUTPUT:
1838 RETVAL
02d1d628 1839
167660cd 1840undef_int
02d1d628
AMH
1841i_gaussian(im,stdev)
1842 Imager::ImgRaw im
167660cd 1843 double stdev
02d1d628 1844
b6381851
TC
1845void
1846i_unsharp_mask(im,stdev,scale)
1847 Imager::ImgRaw im
1848 float stdev
1849 double scale
1850
6a3cbaef
TC
1851int
1852i_conv(im,coef)
1853 Imager::ImgRaw im
1854 AV *coef
1855 PREINIT:
1856 double* c_coef;
1857 int len;
1858 SV* sv1;
1859 int i;
1860 CODE:
1861 len = av_len(coef) + 1;
1862 c_coef=mymalloc( len * sizeof(double) );
1863 for(i = 0; i < len; i++) {
1864 sv1 = (*(av_fetch(coef, i, 0)));
1865 c_coef[i] = (double)SvNV(sv1);
1866 }
1867 RETVAL = i_conv(im, c_coef, len);
1868 myfree(c_coef);
1869 OUTPUT:
1870 RETVAL
02d1d628 1871
d5477d3d
TC
1872Imager::ImgRaw
1873i_convert(src, avmain)
f5991c03 1874 Imager::ImgRaw src
d5477d3d 1875 AV *avmain
f5991c03
TC
1876 PREINIT:
1877 float *coeff;
1878 int outchan;
1879 int inchan;
f5991c03 1880 SV **temp;
f5991c03
TC
1881 AV *avsub;
1882 int len;
1883 int i, j;
1884 CODE:
f5991c03
TC
1885 outchan = av_len(avmain)+1;
1886 /* find the biggest */
1887 inchan = 0;
1888 for (j=0; j < outchan; ++j) {
1889 temp = av_fetch(avmain, j, 0);
1890 if (temp && SvROK(*temp) && SvTYPE(SvRV(*temp)) == SVt_PVAV) {
1891 avsub = (AV*)SvRV(*temp);
1892 len = av_len(avsub)+1;
1893 if (len > inchan)
1894 inchan = len;
1895 }
1896 }
1897 coeff = mymalloc(sizeof(float) * outchan * inchan);
1898 for (j = 0; j < outchan; ++j) {
1899 avsub = (AV*)SvRV(*av_fetch(avmain, j, 0));
1900 len = av_len(avsub)+1;
1901 for (i = 0; i < len; ++i) {
1902 temp = av_fetch(avsub, i, 0);
1903 if (temp)
1904 coeff[i+j*inchan] = SvNV(*temp);
1905 else
1906 coeff[i+j*inchan] = 0;
1907 }
1908 while (i < inchan)
1909 coeff[i++ + j*inchan] = 0;
1910 }
d5477d3d 1911 RETVAL = i_convert(src, coeff, outchan, inchan);
f5991c03 1912 myfree(coeff);
f5991c03
TC
1913 OUTPUT:
1914 RETVAL
40eba1ea
AMH
1915
1916
1917void
1918i_map(im, pmaps)
1919 Imager::ImgRaw im
1920 PREINIT:
1921 unsigned int mask = 0;
1922 AV *avmain;
1923 AV *avsub;
1924 SV **temp;
1925 int len;
1926 int i, j;
1927 unsigned char (*maps)[256];
1928 CODE:
1929 if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV)
1930 croak("i_map: parameter 2 must be an arrayref\n");
1931 avmain = (AV*)SvRV(ST(1));
1932 len = av_len(avmain)+1;
1933 if (im->channels < len) len = im->channels;
1934
1935 maps = mymalloc( len * sizeof(unsigned char [256]) );
1936
1937 for (j=0; j<len ; j++) {
1938 temp = av_fetch(avmain, j, 0);
1939 if (temp && SvROK(*temp) && (SvTYPE(SvRV(*temp)) == SVt_PVAV) ) {
1940 avsub = (AV*)SvRV(*temp);
1941 if(av_len(avsub) != 255) continue;
1942 mask |= 1<<j;
1943 for (i=0; i<256 ; i++) {
9495ee93 1944 int val;
40eba1ea 1945 temp = av_fetch(avsub, i, 0);
9495ee93
AMH
1946 val = temp ? SvIV(*temp) : 0;
1947 if (val<0) val = 0;
1948 if (val>255) val = 255;
1949 maps[j][i] = val;
40eba1ea
AMH
1950 }
1951 }
1952 }
1953 i_map(im, maps, mask);
1954 myfree(maps);
1955
1956
1957
02d1d628
AMH
1958float
1959i_img_diff(im1,im2)
1960 Imager::ImgRaw im1
1961 Imager::ImgRaw im2
1962
e41cfe8f
TC
1963double
1964i_img_diffd(im1,im2)
1965 Imager::ImgRaw im1
1966 Imager::ImgRaw im2
02d1d628
AMH
1967
1968undef_int
4cb58f1b
TC
1969i_init_fonts(t1log=0)
1970 int t1log
02d1d628 1971
813d4d0a
TC
1972bool
1973_is_color_object(sv)
1974 SV* sv
1975 CODE:
1976 SvGETMAGIC(sv);
1977 RETVAL = SvOK(sv) && SvROK(sv) &&
1978 (sv_derived_from(sv, "Imager::Color")
1979 || sv_derived_from(sv, "Imager::Color::Float"));
1980 OUTPUT:
1981 RETVAL
1982
02d1d628
AMH
1983#ifdef HAVE_LIBT1
1984
1985void
1986i_t1_set_aa(st)
1987 int st
1988
1989int
6b012d62 1990i_t1_new(pfb,afm)
02d1d628
AMH
1991 char* pfb
1992 char* afm
1993
1994int
1995i_t1_destroy(font_id)
1996 int font_id
1997
1998
1999undef_int
1bd75e4c 2000i_t1_cp(im,xb,yb,channel,fontnum,points,str_sv,len_ignored,align,utf8=0,flags="")
02d1d628
AMH
2001 Imager::ImgRaw im
2002 int xb
2003 int yb
2004 int channel
2005 int fontnum
2006 float points
1bd75e4c 2007 SV* str_sv
02d1d628 2008 int align
1bd75e4c
TC
2009 int utf8
2010 char* flags
2011 PREINIT:
2012 char *str;
2013 STRLEN len;
2014 CODE:
2015#ifdef SvUTF8
2016 if (SvUTF8(str_sv))
2017 utf8 = 1;
2018#endif
2019 str = SvPV(str_sv, len);
2020 RETVAL = i_t1_cp(im, xb,yb,channel,fontnum,points,str,len,align,
2021 utf8,flags);
2022 OUTPUT:
2023 RETVAL
2024
02d1d628
AMH
2025
2026void
1bd75e4c 2027i_t1_bbox(fontnum,point,str_sv,len_ignored,utf8=0,flags="")
02d1d628
AMH
2028 int fontnum
2029 float point
1bd75e4c
TC
2030 SV* str_sv
2031 int utf8
2032 char* flags
02d1d628 2033 PREINIT:
1bd75e4c
TC
2034 char *str;
2035 STRLEN len;
3799c4d1 2036 int cords[BOUNDING_BOX_COUNT];
1bd75e4c 2037 int i;
3799c4d1 2038 int rc;
02d1d628 2039 PPCODE:
1bd75e4c
TC
2040#ifdef SvUTF8
2041 if (SvUTF8(str_sv))
2042 utf8 = 1;
2043#endif
2044 str = SvPV(str_sv, len);
3799c4d1
TC
2045 rc = i_t1_bbox(fontnum,point,str,len,cords,utf8,flags);
2046 if (rc > 0) {
2047 EXTEND(SP, rc);
2048 for (i = 0; i < rc; ++i)
2049 PUSHs(sv_2mortal(newSViv(cords[i])));
2050 }
02d1d628
AMH
2051
2052
2053
2054undef_int
1bd75e4c 2055i_t1_text(im,xb,yb,cl,fontnum,points,str_sv,len_ignored,align,utf8=0,flags="")
02d1d628
AMH
2056 Imager::ImgRaw im
2057 int xb
2058 int yb
2059 Imager::Color cl
2060 int fontnum
2061 float points
1bd75e4c 2062 SV* str_sv
02d1d628 2063 int align
1bd75e4c
TC
2064 int utf8
2065 char* flags
2066 PREINIT:
2067 char *str;
2068 STRLEN len;
2069 CODE:
2070#ifdef SvUTF8
2071 if (SvUTF8(str_sv))
2072 utf8 = 1;
2073#endif
2074 str = SvPV(str_sv, len);
2075 RETVAL = i_t1_text(im, xb,yb,cl,fontnum,points,str,len,align,
2076 utf8,flags);
2077 OUTPUT:
2078 RETVAL
02d1d628 2079
3799c4d1
TC
2080void
2081i_t1_has_chars(handle, text_sv, utf8 = 0)
2082 int handle
2083 SV *text_sv
2084 int utf8
2085 PREINIT:
2086 char const *text;
2087 STRLEN len;
2088 char *work;
2089 int count;
2090 int i;
2091 PPCODE:
2092#ifdef SvUTF8
2093 if (SvUTF8(text_sv))
2094 utf8 = 1;
2095#endif
2096 text = SvPV(text_sv, len);
2097 work = mymalloc(len);
2098 count = i_t1_has_chars(handle, text, len, utf8, work);
2099 if (GIMME_V == G_ARRAY) {
2100 EXTEND(SP, count);
2101 for (i = 0; i < count; ++i) {
2102 PUSHs(sv_2mortal(newSViv(work[i])));
2103 }
2104 }
2105 else {
2106 EXTEND(SP, 1);
2107 PUSHs(sv_2mortal(newSVpv(work, count)));
2108 }
2109 myfree(work);
2110
2111void
2112i_t1_face_name(handle)
2113 int handle
2114 PREINIT:
2115 char name[255];
2116 int len;
2117 PPCODE:
2118 len = i_t1_face_name(handle, name, sizeof(name));
2119 if (len) {
2120 EXTEND(SP, 1);
2121 PUSHs(sv_2mortal(newSVpv(name, strlen(name))));
2122 }
2123
19fa4baf
AMH
2124void
2125i_t1_glyph_name(handle, text_sv, utf8 = 0)
3799c4d1
TC
2126 int handle
2127 SV *text_sv
2128 int utf8
2129 PREINIT:
2130 char const *text;
2131 STRLEN work_len;
2132 int len;
3799c4d1
TC
2133 char name[255];
2134 PPCODE:
2135#ifdef SvUTF8
2136 if (SvUTF8(text_sv))
2137 utf8 = 1;
2138#endif
2139 text = SvPV(text_sv, work_len);
2140 len = work_len;
2141 while (len) {
17892255 2142 unsigned long ch;
3799c4d1
TC
2143 if (utf8) {
2144 ch = i_utf8_advance(&text, &len);
2145 if (ch == ~0UL) {
2146 i_push_error(0, "invalid UTF8 character");
2147 break;
2148 }
2149 }
2150 else {
2151 ch = *text++;
2152 --len;
2153 }
2154 EXTEND(SP, 1);
f364e883 2155 if (i_t1_glyph_name(handle, ch, name, sizeof(name))) {
3799c4d1
TC
2156 PUSHs(sv_2mortal(newSVpv(name, 0)));
2157 }
2158 else {
2159 PUSHs(&PL_sv_undef);
2160 }
2161 }
2162
02d1d628
AMH
2163#endif
2164
2165#ifdef HAVE_LIBTT
2166
2167
4b19f77a 2168Imager::Font::TT
02d1d628
AMH
2169i_tt_new(fontname)
2170 char* fontname
2171
4b19f77a
AMH
2172
2173MODULE = Imager PACKAGE = Imager::Font::TT PREFIX=TT_
2174
2175#define TT_DESTROY(handle) i_tt_destroy(handle)
2176
02d1d628 2177void
4b19f77a
AMH
2178TT_DESTROY(handle)
2179 Imager::Font::TT handle
2180
ffddd407
TC
2181int
2182TT_CLONE_SKIP(...)
2183 CODE:
2184 RETVAL = 1;
2185 OUTPUT:
2186 RETVAL
2187
02d1d628 2188
4b19f77a 2189MODULE = Imager PACKAGE = Imager
02d1d628
AMH
2190
2191
2192undef_int
9ab6338b 2193i_tt_text(handle,im,xb,yb,cl,points,str_sv,len_ignored,smooth,utf8,align=1)
4b19f77a 2194 Imager::Font::TT handle
02d1d628
AMH
2195 Imager::ImgRaw im
2196 int xb
2197 int yb
2198 Imager::Color cl
2199 float points
4f68b48f 2200 SV * str_sv
02d1d628 2201 int smooth
4f68b48f 2202 int utf8
9ab6338b 2203 int align
4f68b48f
TC
2204 PREINIT:
2205 char *str;
2206 STRLEN len;
2207 CODE:
2208#ifdef SvUTF8
2209 if (SvUTF8(str_sv))
2210 utf8 = 1;
2211#endif
2212 str = SvPV(str_sv, len);
2213 RETVAL = i_tt_text(handle, im, xb, yb, cl, points, str,
9ab6338b 2214 len, smooth, utf8, align);
4f68b48f
TC
2215 OUTPUT:
2216 RETVAL
02d1d628
AMH
2217
2218
2219undef_int
9ab6338b 2220i_tt_cp(handle,im,xb,yb,channel,points,str_sv,len_ignored,smooth,utf8,align=1)
4b19f77a 2221 Imager::Font::TT handle
02d1d628
AMH
2222 Imager::ImgRaw im
2223 int xb
2224 int yb
2225 int channel
2226 float points
4f68b48f 2227 SV * str_sv
02d1d628 2228 int smooth
4f68b48f 2229 int utf8
9ab6338b 2230 int align
4f68b48f
TC
2231 PREINIT:
2232 char *str;
2233 STRLEN len;
2234 CODE:
2235#ifdef SvUTF8
2236 if (SvUTF8(str_sv))
2237 utf8 = 1;
2238#endif
2239 str = SvPV(str_sv, len);
2240 RETVAL = i_tt_cp(handle, im, xb, yb, channel, points, str, len,
9ab6338b 2241 smooth, utf8, align);
4f68b48f
TC
2242 OUTPUT:
2243 RETVAL
02d1d628
AMH
2244
2245
a659442a 2246void
4f68b48f 2247i_tt_bbox(handle,point,str_sv,len_ignored, utf8)
4b19f77a 2248 Imager::Font::TT handle
02d1d628 2249 float point
4f68b48f 2250 SV* str_sv
4f68b48f 2251 int utf8
02d1d628 2252 PREINIT:
3799c4d1 2253 int cords[BOUNDING_BOX_COUNT],rc;
4f68b48f
TC
2254 char * str;
2255 STRLEN len;
3799c4d1 2256 int i;
02d1d628 2257 PPCODE:
4f68b48f
TC
2258#ifdef SvUTF8
2259 if (SvUTF8(ST(2)))
2260 utf8 = 1;
2261#endif
2262 str = SvPV(str_sv, len);
2263 if ((rc=i_tt_bbox(handle,point,str,len,cords, utf8))) {
3799c4d1
TC
2264 EXTEND(SP, rc);
2265 for (i = 0; i < rc; ++i) {
2266 PUSHs(sv_2mortal(newSViv(cords[i])));
2267 }
02d1d628
AMH
2268 }
2269
eeaa33fd
TC
2270void
2271i_tt_has_chars(handle, text_sv, utf8)
2272 Imager::Font::TT handle
2273 SV *text_sv
2274 int utf8
2275 PREINIT:
2276 char const *text;
2277 STRLEN len;
2278 char *work;
2279 int count;
2280 int i;
2281 PPCODE:
2282#ifdef SvUTF8
2283 if (SvUTF8(text_sv))
2284 utf8 = 1;
2285#endif
2286 text = SvPV(text_sv, len);
2287 work = mymalloc(len);
2288 count = i_tt_has_chars(handle, text, len, utf8, work);
2289 if (GIMME_V == G_ARRAY) {
2290 EXTEND(SP, count);
2291 for (i = 0; i < count; ++i) {
2292 PUSHs(sv_2mortal(newSViv(work[i])));
2293 }
2294 }
2295 else {
2296 EXTEND(SP, 1);
2297 PUSHs(sv_2mortal(newSVpv(work, count)));
2298 }
2299 myfree(work);
02d1d628 2300
3799c4d1
TC
2301void
2302i_tt_dump_names(handle)
2303 Imager::Font::TT handle
02d1d628 2304
3799c4d1
TC
2305void
2306i_tt_face_name(handle)
2307 Imager::Font::TT handle
2308 PREINIT:
2309 char name[255];
2310 int len;
2311 PPCODE:
2312 len = i_tt_face_name(handle, name, sizeof(name));
2313 if (len) {
2314 EXTEND(SP, 1);
2315 PUSHs(sv_2mortal(newSVpv(name, strlen(name))));
2316 }
02d1d628 2317
19fa4baf
AMH
2318void
2319i_tt_glyph_name(handle, text_sv, utf8 = 0)
3799c4d1
TC
2320 Imager::Font::TT handle
2321 SV *text_sv
2322 int utf8
2323 PREINIT:
2324 char const *text;
2325 STRLEN work_len;
2326 int len;
2327 int outsize;
2328 char name[255];
2329 PPCODE:
2330#ifdef SvUTF8
2331 if (SvUTF8(text_sv))
2332 utf8 = 1;
2333#endif
2334 text = SvPV(text_sv, work_len);
2335 len = work_len;
2336 while (len) {
17892255 2337 unsigned long ch;
3799c4d1
TC
2338 if (utf8) {
2339 ch = i_utf8_advance(&text, &len);
2340 if (ch == ~0UL) {
2341 i_push_error(0, "invalid UTF8 character");
2342 break;
2343 }
2344 }
2345 else {
2346 ch = *text++;
2347 --len;
2348 }
2349 EXTEND(SP, 1);
af070d99 2350 if ((outsize = i_tt_glyph_name(handle, ch, name, sizeof(name))) != 0) {
3799c4d1
TC
2351 PUSHs(sv_2mortal(newSVpv(name, 0)));
2352 }
2353 else {
2354 PUSHs(&PL_sv_undef);
2355 }
2356 }
2357
2358#endif
02d1d628 2359
53a6bbd4 2360const char *
e10bf46e
AMH
2361i_test_format_probe(ig, length)
2362 Imager::IO ig
2363 int length
2364
02d1d628 2365Imager::ImgRaw
d87dc9a4 2366i_readpnm_wiol(ig, allow_incomplete)
02d1d628 2367 Imager::IO ig
d87dc9a4 2368 int allow_incomplete
02d1d628
AMH
2369
2370
2086be61
TC
2371void
2372i_readpnm_multi_wiol(ig, allow_incomplete)
2373 Imager::IO ig
2374 int allow_incomplete
2375 PREINIT:
2376 i_img **imgs;
2377 int count=0;
2378 int i;
2379 PPCODE:
2380 imgs = i_readpnm_multi_wiol(ig, &count, allow_incomplete);
2381 if (imgs) {
2382 EXTEND(SP, count);
2383 for (i = 0; i < count; ++i) {
2384 SV *sv = sv_newmortal();
2385 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2386 PUSHs(sv);
2387 }
2388 myfree(imgs);
2389 }
2390
067d6bdc
AMH
2391undef_int
2392i_writeppm_wiol(im, ig)
2393 Imager::ImgRaw im
2394 Imager::IO ig
2395
2396
2086be61
TC
2397
2398
2399
02d1d628 2400Imager::ImgRaw
895dbd34
AMH
2401i_readraw_wiol(ig,x,y,datachannels,storechannels,intrl)
2402 Imager::IO ig
02d1d628
AMH
2403 int x
2404 int y
2405 int datachannels
2406 int storechannels
2407 int intrl
2408
2409undef_int
895dbd34 2410i_writeraw_wiol(im,ig)
02d1d628 2411 Imager::ImgRaw im
895dbd34
AMH
2412 Imager::IO ig
2413
261f91c5
TC
2414undef_int
2415i_writebmp_wiol(im,ig)
2416 Imager::ImgRaw im
2417 Imager::IO ig
02d1d628 2418
705fd961 2419Imager::ImgRaw
d87dc9a4 2420i_readbmp_wiol(ig, allow_incomplete=0)
705fd961 2421 Imager::IO ig
d87dc9a4 2422 int allow_incomplete
705fd961 2423
1ec86afa
AMH
2424
2425undef_int
febba01f 2426i_writetga_wiol(im,ig, wierdpack, compress, idstring)
1ec86afa
AMH
2427 Imager::ImgRaw im
2428 Imager::IO ig
febba01f
AMH
2429 int wierdpack
2430 int compress
2431 char* idstring
2432 PREINIT:
febba01f
AMH
2433 int idlen;
2434 CODE:
2435 idlen = SvCUR(ST(4));
2436 RETVAL = i_writetga_wiol(im, ig, wierdpack, compress, idstring, idlen);
2437 OUTPUT:
2438 RETVAL
2439
1ec86afa
AMH
2440
2441Imager::ImgRaw
2442i_readtga_wiol(ig, length)
2443 Imager::IO ig
2444 int length
2445
2446
737a830c
AMH
2447
2448
02d1d628
AMH
2449Imager::ImgRaw
2450i_scaleaxis(im,Value,Axis)
2451 Imager::ImgRaw im
2452 float Value
2453 int Axis
2454
2455Imager::ImgRaw
2456i_scale_nn(im,scx,scy)
2457 Imager::ImgRaw im
2458 float scx
2459 float scy
2460
658f724e
TC
2461Imager::ImgRaw
2462i_scale_mixing(im, width, height)
2463 Imager::ImgRaw im
2464 int width
2465 int height
2466
02d1d628
AMH
2467Imager::ImgRaw
2468i_haar(im)
2469 Imager::ImgRaw im
2470
2471int
2472i_count_colors(im,maxc)
2473 Imager::ImgRaw im
2474 int maxc
2475
fe622da1 2476void
a60905e4
TC
2477i_get_anonymous_color_histo(im, maxc = 0x40000000)
2478 Imager::ImgRaw im
2479 int maxc
4c99febf 2480 PREINIT:
fe622da1 2481 int i;
a60905e4 2482 unsigned int * col_usage = NULL;
4c99febf
TC
2483 int col_cnt;
2484 PPCODE:
2485 col_cnt = i_get_anonymous_color_histo(im, &col_usage, maxc);
fe622da1 2486 EXTEND(SP, col_cnt);
a60905e4
TC
2487 for (i = 0; i < col_cnt; i++) {
2488 PUSHs(sv_2mortal(newSViv( col_usage[i])));
fe622da1 2489 }
fe622da1
TC
2490 myfree(col_usage);
2491 XSRETURN(col_cnt);
2492
02d1d628
AMH
2493
2494Imager::ImgRaw
2495i_transform(im,opx,opy,parm)
2496 Imager::ImgRaw im
2497 PREINIT:
2498 double* parm;
2499 int* opx;
2500 int* opy;
2501 int opxl;
2502 int opyl;
2503 int parmlen;
2504 AV* av;
2505 SV* sv1;
2506 int i;
2507 CODE:
2508 if (!SvROK(ST(1))) croak("Imager: Parameter 1 must be a reference to an array\n");
2509 if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to an array\n");
2510 if (!SvROK(ST(3))) croak("Imager: Parameter 3 must be a reference to an array\n");
2511 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 must be a reference to an array\n");
2512 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 2 must be a reference to an array\n");
2513 if (SvTYPE(SvRV(ST(3))) != SVt_PVAV) croak("Imager: Parameter 3 must be a reference to an array\n");
2514 av=(AV*)SvRV(ST(1));
2515 opxl=av_len(av)+1;
2516 opx=mymalloc( opxl*sizeof(int) );
2517 for(i=0;i<opxl;i++) {
2518 sv1=(*(av_fetch(av,i,0)));
2519 opx[i]=(int)SvIV(sv1);
2520 }
2521 av=(AV*)SvRV(ST(2));
2522 opyl=av_len(av)+1;
2523 opy=mymalloc( opyl*sizeof(int) );
2524 for(i=0;i<opyl;i++) {
2525 sv1=(*(av_fetch(av,i,0)));
2526 opy[i]=(int)SvIV(sv1);
2527 }
2528 av=(AV*)SvRV(ST(3));
2529 parmlen=av_len(av)+1;
2530 parm=mymalloc( parmlen*sizeof(double) );
2531 for(i=0;i<parmlen;i++) { /* FIXME: Bug? */
2532 sv1=(*(av_fetch(av,i,0)));
2533 parm[i]=(double)SvNV(sv1);
2534 }
2535 RETVAL=i_transform(im,opx,opxl,opy,opyl,parm,parmlen);
2536 myfree(parm);
2537 myfree(opy);
2538 myfree(opx);
2539 ST(0) = sv_newmortal();
2540 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2541 else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
2542
2543Imager::ImgRaw
e5744e01
TC
2544i_transform2(sv_width,sv_height,channels,sv_ops,av_n_regs,av_c_regs,av_in_imgs)
2545 SV *sv_width
2546 SV *sv_height
2547 SV *sv_ops
2548 AV *av_n_regs
2549 AV *av_c_regs
2550 AV *av_in_imgs
2551 int channels
02d1d628
AMH
2552 PREINIT:
2553 int width;
2554 int height;
02d1d628 2555 struct rm_op *ops;
953209f8 2556 STRLEN ops_len;
02d1d628
AMH
2557 int ops_count;
2558 double *n_regs;
2559 int n_regs_count;
2560 i_color *c_regs;
2561 int c_regs_count;
2562 int in_imgs_count;
2563 i_img **in_imgs;
ea9e6c3f 2564 SV *sv1;
02d1d628
AMH
2565 IV tmp;
2566 int i;
2567 CODE:
e5744e01
TC
2568
2569 in_imgs_count = av_len(av_in_imgs)+1;
2570 for (i = 0; i < in_imgs_count; ++i) {
2571 sv1 = *av_fetch(av_in_imgs, i, 0);
2572 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
2573 croak("sv_in_img must contain only images");
02d1d628
AMH
2574 }
2575 }
b8c2033e 2576 if (in_imgs_count > 0) {
02d1d628
AMH
2577 in_imgs = mymalloc(in_imgs_count*sizeof(i_img*));
2578 for (i = 0; i < in_imgs_count; ++i) {
e5744e01 2579 sv1 = *av_fetch(av_in_imgs,i,0);
02d1d628
AMH
2580 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
2581 croak("Parameter 5 must contain only images");
2582 }
2583 tmp = SvIV((SV*)SvRV(sv1));
e375fbd8 2584 in_imgs[i] = INT2PTR(i_img*, tmp);
02d1d628
AMH
2585 }
2586 }
2587 else {
2588 /* no input images */
2589 in_imgs = NULL;
2590 }
2591 /* default the output size from the first input if possible */
e5744e01
TC
2592 if (SvOK(sv_width))
2593 width = SvIV(sv_width);
02d1d628
AMH
2594 else if (in_imgs_count)
2595 width = in_imgs[0]->xsize;
2596 else
2597 croak("No output image width supplied");
2598
e5744e01
TC
2599 if (SvOK(sv_height))
2600 height = SvIV(sv_height);
02d1d628
AMH
2601 else if (in_imgs_count)
2602 height = in_imgs[0]->ysize;
2603 else
2604 croak("No output image height supplied");
2605
e5744e01 2606 ops = (struct rm_op *)SvPV(sv_ops, ops_len);
02d1d628
AMH
2607 if (ops_len % sizeof(struct rm_op))
2608 croak("Imager: Parameter 3 must be a bitmap of regops\n");
2609 ops_count = ops_len / sizeof(struct rm_op);
e5744e01
TC
2610
2611 n_regs_count = av_len(av_n_regs)+1;
02d1d628
AMH
2612 n_regs = mymalloc(n_regs_count * sizeof(double));
2613 for (i = 0; i < n_regs_count; ++i) {
e5744e01 2614 sv1 = *av_fetch(av_n_regs,i,0);
02d1d628
AMH
2615 if (SvOK(sv1))
2616 n_regs[i] = SvNV(sv1);
2617 }
e5744e01 2618 c_regs_count = av_len(av_c_regs)+1;
02d1d628
AMH
2619 c_regs = mymalloc(c_regs_count * sizeof(i_color));
2620 /* I don't bother initializing the colou?r registers */
2621
e5744e01 2622 RETVAL=i_transform2(width, height, channels, ops, ops_count,
02d1d628
AMH
2623 n_regs, n_regs_count,
2624 c_regs, c_regs_count, in_imgs, in_imgs_count);
2625 if (in_imgs)
2626 myfree(in_imgs);
2627 myfree(n_regs);
2628 myfree(c_regs);
2629 ST(0) = sv_newmortal();
2630 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2631 else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
2632
2633
2634void
2635i_contrast(im,intensity)
2636 Imager::ImgRaw im
2637 float intensity
2638
2639void
2640i_hardinvert(im)
2641 Imager::ImgRaw im
2642
5558f899
TC
2643void
2644i_hardinvertall(im)
2645 Imager::ImgRaw im
2646
02d1d628
AMH
2647void
2648i_noise(im,amount,type)
2649 Imager::ImgRaw im
2650 float amount
2651 unsigned char type
2652
2653void
2654i_bumpmap(im,bump,channel,light_x,light_y,strength)
2655 Imager::ImgRaw im
2656 Imager::ImgRaw bump
2657 int channel
2658 int light_x
2659 int light_y
2660 int strength
2661
b2778574
AMH
2662
2663void
2664i_bumpmap_complex(im,bump,channel,tx,ty,Lx,Ly,Lz,cd,cs,n,Ia,Il,Is)
2665 Imager::ImgRaw im
2666 Imager::ImgRaw bump
2667 int channel
2668 int tx
2669 int ty
2670 float Lx
2671 float Ly
2672 float Lz
2673 float cd
2674 float cs
2675 float n
2676 Imager::Color Ia
2677 Imager::Color Il
2678 Imager::Color Is
2679
2680
2681
02d1d628
AMH
2682void
2683i_postlevels(im,levels)
2684 Imager::ImgRaw im
2685 int levels
2686
2687void
2688i_mosaic(im,size)
2689 Imager::ImgRaw im
2690 int size
2691
2692void
2693i_watermark(im,wmark,tx,ty,pixdiff)
2694 Imager::ImgRaw im
2695 Imager::ImgRaw wmark
2696 int tx
2697 int ty
2698 int pixdiff
2699
2700
2701void
2702i_autolevels(im,lsat,usat,skew)
2703 Imager::ImgRaw im
2704 float lsat
2705 float usat
2706 float skew
2707
2708void
2709i_radnoise(im,xo,yo,rscale,ascale)
2710 Imager::ImgRaw im
2711 float xo
2712 float yo
2713 float rscale
2714 float ascale
2715
2716void
2717i_turbnoise(im, xo, yo, scale)
2718 Imager::ImgRaw im
2719 float xo
2720 float yo
2721 float scale
2722
2723
2724void
2725i_gradgen(im, ...)
2726 Imager::ImgRaw im
2727 PREINIT:
2728 int num;
2729 int *xo;
2730 int *yo;
2731 i_color *ival;
2732 int dmeasure;
2733 int i;
2734 SV *sv;
2735 AV *axx;
2736 AV *ayy;
2737 AV *ac;
2738 CODE:
2739 if (items != 5)
2740 croak("Usage: i_gradgen(im, xo, yo, ival, dmeasure)");
2741 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2742 croak("i_gradgen: Second argument must be an array ref");
2743 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
2744 croak("i_gradgen: Third argument must be an array ref");
2745 if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
2746 croak("i_gradgen: Fourth argument must be an array ref");
2747 axx = (AV *)SvRV(ST(1));
2748 ayy = (AV *)SvRV(ST(2));
2749 ac = (AV *)SvRV(ST(3));
2750 dmeasure = (int)SvIV(ST(4));
2751
2752 num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
2753 num = num <= av_len(ac) ? num : av_len(ac);
2754 num++;
2755 if (num < 2) croak("Usage: i_gradgen array refs must have more than 1 entry each");
2756 xo = mymalloc( sizeof(int) * num );
2757 yo = mymalloc( sizeof(int) * num );
2758 ival = mymalloc( sizeof(i_color) * num );
2759 for(i = 0; i<num; i++) {
2760 xo[i] = (int)SvIV(* av_fetch(axx, i, 0));
2761 yo[i] = (int)SvIV(* av_fetch(ayy, i, 0));
2762 sv = *av_fetch(ac, i, 0);
2763 if ( !sv_derived_from(sv, "Imager::Color") ) {
2764 free(axx); free(ayy); free(ac);
2765 croak("i_gradgen: Element of fourth argument is not derived from Imager::Color");
2766 }
4c4c2ffd 2767 ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
02d1d628
AMH
2768 }
2769 i_gradgen(im, num, xo, yo, ival, dmeasure);
a73aeb5f
AMH
2770 myfree(xo);
2771 myfree(yo);
2772 myfree(ival);
2773
dff75dee
TC
2774Imager::ImgRaw
2775i_diff_image(im, im2, mindist=0)
2776 Imager::ImgRaw im
2777 Imager::ImgRaw im2
01b84320 2778 double mindist
02d1d628 2779
e310e5f9 2780undef_int
6607600c
TC
2781i_fountain(im, xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
2782 Imager::ImgRaw im
2783 double xa
2784 double ya
2785 double xb
2786 double yb
2787 int type
2788 int repeat
2789 int combine
2790 int super_sample
2791 double ssample_param
2792 PREINIT:
6607600c 2793 AV *asegs;
6607600c
TC
2794 int count;
2795 i_fountain_seg *segs;
6607600c 2796 CODE:
6607600c
TC
2797 if (!SvROK(ST(10)) || ! SvTYPE(SvRV(ST(10))))
2798 croak("i_fountain: argument 11 must be an array ref");
2799
2800 asegs = (AV *)SvRV(ST(10));
b13a3ddb 2801 segs = load_fount_segs(aTHX_ asegs, &count);
e310e5f9
TC
2802 RETVAL = i_fountain(im, xa, ya, xb, yb, type, repeat, combine,
2803 super_sample, ssample_param, count, segs);
6607600c 2804 myfree(segs);
e310e5f9
TC
2805 OUTPUT:
2806 RETVAL
02d1d628 2807
f1ac5027
TC
2808Imager::FillHandle
2809i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
2810 double xa
2811 double ya
2812 double xb
2813 double yb
2814 int type
2815 int repeat
2816 int combine
2817 int super_sample
2818 double ssample_param
2819 PREINIT:
2820 AV *asegs;
2821 int count;
2822 i_fountain_seg *segs;
2823 CODE:
2824 if (!SvROK(ST(9)) || ! SvTYPE(SvRV(ST(9))))
2825 croak("i_fountain: argument 11 must be an array ref");
2826
2827 asegs = (AV *)SvRV(ST(9));
b13a3ddb 2828 segs = load_fount_segs(aTHX_ asegs, &count);
f1ac5027
TC
2829 RETVAL = i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine,
2830 super_sample, ssample_param, count, segs);
2831 myfree(segs);
2832 OUTPUT:
2833 RETVAL
2834
52f2b10a
TC
2835Imager::FillHandle
2836i_new_fill_opacity(other_fill, alpha_mult)
2837 Imager::FillHandle other_fill
2838 double alpha_mult
2839
4f4f776a
TC
2840void
2841i_errors()
2842 PREINIT:
2843 i_errmsg *errors;
2844 int i;
4f4f776a 2845 AV *av;
4f4f776a
TC
2846 SV *sv;
2847 PPCODE:
2848 errors = i_errors();
2849 i = 0;
2850 while (errors[i].msg) {
2851 av = newAV();
2852 sv = newSVpv(errors[i].msg, strlen(errors[i].msg));
2853 if (!av_store(av, 0, sv)) {
2854 SvREFCNT_dec(sv);
2855 }
2856 sv = newSViv(errors[i].code);
2857 if (!av_store(av, 1, sv)) {
2858 SvREFCNT_dec(sv);
2859 }
2860 PUSHs(sv_2mortal(newRV_noinc((SV*)av)));
2861 ++i;
2862 }
02d1d628 2863
2b405c9e
TC
2864void
2865i_clear_error()
2866
2867void
2868i_push_error(code, msg)
2869 int code
2870 const char *msg
2871
e310e5f9 2872undef_int
02d1d628
AMH
2873i_nearest_color(im, ...)
2874 Imager::ImgRaw im
2875 PREINIT:
2876 int num;
2877 int *xo;
2878 int *yo;
2879 i_color *ival;
2880 int dmeasure;
2881 int i;
2882 SV *sv;
2883 AV *axx;
2884 AV *ayy;
2885 AV *ac;
2886 CODE:
2887 if (items != 5)
2888 croak("Usage: i_nearest_color(im, xo, yo, ival, dmeasure)");
2889 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2890 croak("i_nearest_color: Second argument must be an array ref");
2891 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
2892 croak("i_nearest_color: Third argument must be an array ref");
2893 if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
2894 croak("i_nearest_color: Fourth argument must be an array ref");
2895 axx = (AV *)SvRV(ST(1));
2896 ayy = (AV *)SvRV(ST(2));
2897 ac = (AV *)SvRV(ST(3));
2898 dmeasure = (int)SvIV(ST(4));
2899
2900 num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
2901 num = num <= av_len(ac) ? num : av_len(ac);
2902 num++;
2903 if (num < 2) croak("Usage: i_nearest_color array refs must have more than 1 entry each");
2904 xo = mymalloc( sizeof(int) * num );
2905 yo = mymalloc( sizeof(int) * num );
2906 ival = mymalloc( sizeof(i_color) * num );
2907 for(i = 0; i<num; i++) {
2908 xo[i] = (int)SvIV(* av_fetch(axx, i, 0));
2909 yo[i] = (int)SvIV(* av_fetch(ayy, i, 0));
2910 sv = *av_fetch(ac, i, 0);
2911 if ( !sv_derived_from(sv, "Imager::Color") ) {
2912 free(axx); free(ayy); free(ac);
2913 croak("i_nearest_color: Element of fourth argument is not derived from Imager::Color");
2914 }
4c4c2ffd 2915 ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
02d1d628 2916 }
e310e5f9
TC
2917 RETVAL = i_nearest_color(im, num, xo, yo, ival, dmeasure);
2918 OUTPUT:
2919 RETVAL
02d1d628
AMH
2920
2921void
2922malloc_state()
2923
02d1d628
AMH
2924void
2925DSO_open(filename)
2926 char* filename
2927 PREINIT:
2928 void *rc;
2929 char *evstr;
2930 PPCODE:
2931 rc=DSO_open(filename,&evstr);
2932 if (rc!=NULL) {
2933 if (evstr!=NULL) {
2934 EXTEND(SP,2);
e375fbd8 2935 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
02d1d628
AMH
2936 PUSHs(sv_2mortal(newSVpvn(evstr, strlen(evstr))));
2937 } else {
2938 EXTEND(SP,1);
e375fbd8 2939 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
02d1d628
AMH
2940 }
2941 }
2942
2943
2944undef_int
2945DSO_close(dso_handle)
2946 void* dso_handle
2947
2948void
2949DSO_funclist(dso_handle_v)
2950 void* dso_handle_v
2951 PREINIT:
2952 int i;
2953 DSO_handle *dso_handle;
d8e0c3ba 2954 func_ptr *functions;
02d1d628
AMH
2955 PPCODE:
2956 dso_handle=(DSO_handle*)dso_handle_v;
d8e0c3ba 2957 functions = DSO_funclist(dso_handle);
02d1d628 2958 i=0;
d8e0c3ba 2959 while( functions[i].name != NULL) {
02d1d628 2960 EXTEND(SP,1);
d8e0c3ba 2961 PUSHs(sv_2mortal(newSVpv(functions[i].name,0)));
02d1d628 2962 EXTEND(SP,1);
d8e0c3ba 2963 PUSHs(sv_2mortal(newSVpv(functions[i++].pcode,0)));
02d1d628
AMH
2964 }
2965
02d1d628
AMH
2966void
2967DSO_call(handle,func_index,hv)
2968 void* handle
2969 int func_index
2970 PREINIT:
2971 HV* hv;
2972 PPCODE:
2973 if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to a hash\n");
2974 hv=(HV*)SvRV(ST(2));
2975 if (SvTYPE(hv)!=SVt_PVHV) croak("Imager: Parameter 2 must be a reference to a hash\n");
2976 DSO_call( (DSO_handle *)handle,func_index,hv);
2977
faa9b3e7 2978SV *
f5991c03
TC
2979i_get_pixel(im, x, y)
2980 Imager::ImgRaw im
2981 int x
2982 int y;
faa9b3e7
TC
2983 PREINIT:
2984 i_color *color;
2985 CODE:
2986 color = (i_color *)mymalloc(sizeof(i_color));
2987 if (i_gpix(im, x, y, color) == 0) {
a659442a
TC
2988 RETVAL = NEWSV(0, 0);
2989 sv_setref_pv(RETVAL, "Imager::Color", (void *)color);
faa9b3e7
TC
2990 }
2991 else {
2992 myfree(color);
a659442a 2993 RETVAL = &PL_sv_undef;
faa9b3e7 2994 }
a659442a
TC
2995 OUTPUT:
2996 RETVAL
faa9b3e7
TC
2997
2998
2999int
3000i_ppix(im, x, y, cl)
3001 Imager::ImgRaw im
3002 int x
3003 int y
3004 Imager::Color cl
3005
3006Imager::ImgRaw
3007i_img_pal_new(x, y, channels, maxpal)
3008 int x
3009 int y
3010 int channels
3011 int maxpal
3012
3013Imager::ImgRaw
3014i_img_to_pal(src, quant)
3015 Imager::ImgRaw src
3016 PREINIT:
3017 HV *hv;
3018 i_quantize quant;
3019 CODE:
3020 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
3021 croak("i_img_to_pal: second argument must be a hash ref");
3022 hv = (HV *)SvRV(ST(1));
3023 memset(&quant, 0, sizeof(quant));
ec6d8908 3024 quant.version = 1;
faa9b3e7 3025 quant.mc_size = 256;
ec6d8908 3026 ip_handle_quant_opts(aTHX_ &quant, hv);
faa9b3e7
TC
3027 RETVAL = i_img_to_pal(src, &quant);
3028 if (RETVAL) {
ec6d8908 3029 ip_copy_colors_back(aTHX_ hv, &quant);
faa9b3e7 3030 }
ec6d8908 3031 ip_cleanup_quant_opts(aTHX_ &quant);
faa9b3e7
TC
3032 OUTPUT:
3033 RETVAL
3034
3035Imager::ImgRaw
3036i_img_to_rgb(src)
3037 Imager::ImgRaw src
3038
3039void
3040i_gpal(im, l, r, y)
3041 Imager::ImgRaw im
3042 int l
3043 int r
3044 int y
3045 PREINIT:
3046 i_palidx *work;
3047 int count, i;
3048 PPCODE:
3049 if (l < r) {
3050 work = mymalloc((r-l) * sizeof(i_palidx));
3051 count = i_gpal(im, l, r, y, work);
3052 if (GIMME_V == G_ARRAY) {
3053 EXTEND(SP, count);
3054 for (i = 0; i < count; ++i) {
3055 PUSHs(sv_2mortal(newSViv(work[i])));
3056 }
3057 }
3058 else {
3059 EXTEND(SP, 1);
26fd367b 3060 PUSHs(sv_2mortal(newSVpv((char *)work, count * sizeof(i_palidx))));
faa9b3e7
TC
3061 }
3062 myfree(work);
3063 }
3064 else {
3065 if (GIMME_V != G_ARRAY) {
3066 EXTEND(SP, 1);
3067 PUSHs(&PL_sv_undef);
3068 }
3069 }
3070
3071int
3072i_ppal(im, l, y, ...)
3073 Imager::ImgRaw im
3074 int l
3075 int y
3076 PREINIT:
3077 i_palidx *work;
ea9e6c3f 3078 int i;
faa9b3e7
TC
3079 CODE:
3080 if (items > 3) {
3081 work = mymalloc(sizeof(i_palidx) * (items-3));
3082 for (i=0; i < items-3; ++i) {
3083 work[i] = SvIV(ST(i+3));
3084 }
4cda4e76 3085 validate_i_ppal(im, work, items - 3);
faa9b3e7
TC
3086 RETVAL = i_ppal(im, l, l+items-3, y, work);
3087 myfree(work);
3088 }
3089 else {
3090 RETVAL = 0;
3091 }
3092 OUTPUT:
3093 RETVAL
3094
4cda4e76
TC
3095int
3096i_ppal_p(im, l, y, data)
3097 Imager::ImgRaw im
3098 int l
3099 int y
3100 SV *data
3101 PREINIT:
3102 i_palidx const *work;
4cda4e76 3103 STRLEN len;
4cda4e76
TC
3104 CODE:
3105 work = (i_palidx const *)SvPV(data, len);
3106 len /= sizeof(i_palidx);
3107 if (len > 0) {
3108 validate_i_ppal(im, work, len);
3109 RETVAL = i_ppal(im, l, l+len, y, work);
3110 }
3111 else {
3112 RETVAL = 0;
3113 }
3114 OUTPUT:
3115 RETVAL
3116
faa9b3e7
TC
3117SV *
3118i_addcolors(im, ...)
3119 Imager::ImgRaw im
3120 PREINIT:
3121 int index;
3122 i_color *colors;
3123 int i;
3124 CODE:
3125 if (items < 2)
3126 croak("i_addcolors: no colors to add");
3127 colors = mymalloc((items-1) * sizeof(i_color));
3128 for (i=0; i < items-1; ++i) {
3129 if (sv_isobject(ST(i+1))
3130 && sv_derived_from(ST(i+1), "Imager::Color")) {
3131 IV tmp = SvIV((SV *)SvRV(ST(i+1)));
4c4c2ffd 3132 colors[i] = *INT2PTR(i_color *, tmp);
faa9b3e7
TC
3133 }
3134 else {
3135 myfree(colors);
ca4d914e 3136 croak("i_addcolor: pixels must be Imager::Color objects");
faa9b3e7
TC
3137 }
3138 }
3139 index = i_addcolors(im, colors, items-1);
3140 myfree(colors);
3141 if (index == 0) {
a659442a 3142 RETVAL = newSVpv("0 but true", 0);
faa9b3e7
TC
3143 }
3144 else if (index == -1) {
a659442a 3145 RETVAL = &PL_sv_undef;
faa9b3e7
TC
3146 }
3147 else {
a659442a 3148 RETVAL = newSViv(index);
faa9b3e7 3149 }
a659442a
TC
3150 OUTPUT:
3151 RETVAL
faa9b3e7 3152
1501d9b3 3153undef_int
faa9b3e7
TC
3154i_setcolors(im, index, ...)
3155 Imager::ImgRaw im
3156 int index
3157 PREINIT:
3158 i_color *colors;
3159 int i;
3160 CODE:
3161 if (items < 3)
3162 croak("i_setcolors: no colors to add");
3163 colors = mymalloc((items-2) * sizeof(i_color));
3164 for (i=0; i < items-2; ++i) {
3165 if (sv_isobject(ST(i+2))
3166 && sv_derived_from(ST(i+2), "Imager::Color")) {
3167 IV tmp = SvIV((SV *)SvRV(ST(i+2)));
4c4c2ffd 3168 colors[i] = *INT2PTR(i_color *, tmp);
faa9b3e7
TC
3169 }
3170 else {
3171 myfree(colors);
3172 croak("i_setcolors: pixels must be Imager::Color objects");
3173 }
3174 }
3175 RETVAL = i_setcolors(im, index, colors, items-2);
3176 myfree(colors);
1501d9b3
TC
3177 OUTPUT:
3178 RETVAL
faa9b3e7
TC
3179
3180void
3181i_getcolors(im, index, ...)
3182 Imager::ImgRaw im
3183 int index
3184 PREINIT:
3185 i_color *colors;
3186 int count = 1;
3187 int i;
3188 PPCODE:
3189 if (items > 3)
3190 croak("i_getcolors: too many arguments");
3191 if (items == 3)
3192 count = SvIV(ST(2));
3193 if (count < 1)
3194 croak("i_getcolors: count must be positive");
3195 colors = mymalloc(sizeof(i_color) * count);
3196 if (i_getcolors(im, index, colors, count)) {
3197 for (i = 0; i < count; ++i) {
3198 i_color *pv;
3199 SV *sv = sv_newmortal();
3200 pv = mymalloc(sizeof(i_color));
3201 *pv = colors[i];
3202 sv_setref_pv(sv, "Imager::Color", (void *)pv);
3203 PUSHs(sv);
3204 }
3205 }
3206 myfree(colors);
3207
3208
a659442a 3209undef_neg_int
faa9b3e7
TC
3210i_colorcount(im)
3211 Imager::ImgRaw im
faa9b3e7 3212
a659442a 3213undef_neg_int
faa9b3e7
TC
3214i_maxcolors(im)
3215 Imager::ImgRaw im
faa9b3e7
TC
3216
3217SV *
3218i_findcolor(im, color)
3219 Imager::ImgRaw im
3220 Imager::Color color
3221 PREINIT:
3222 i_palidx index;
3223 CODE:
3224 if (i_findcolor(im, color, &index)) {
a659442a 3225 RETVAL = newSViv(index);
faa9b3e7
TC
3226 }
3227 else {
a659442a 3228 RETVAL = &PL_sv_undef;
faa9b3e7 3229 }
a659442a
TC
3230 OUTPUT:
3231 RETVAL
faa9b3e7
TC
3232
3233int
3234i_img_bits(im)
3235 Imager::ImgRaw im
3236
3237int
3238i_img_type(im)
3239 Imager::ImgRaw im
3240
3241int
3242i_img_virtual(im)
3243 Imager::ImgRaw im
3244
3245void
3246i_gsamp(im, l, r, y, ...)
3247 Imager::ImgRaw im
3248 int l
3249 int r
3250 int y
3251 PREINIT:
3252 int *chans;
3253 int chan_count;
3254 i_sample_t *data;
3255 int count, i;
3256 PPCODE:
3257 if (items < 5)
3258 croak("No channel numbers supplied to g_samp()");
3259 if (l < r) {
3260 chan_count = items - 4;
3261 chans = mymalloc(sizeof(int) * chan_count);
3262 for (i = 0; i < chan_count; ++i)
3263 chans[i] = SvIV(ST(i+4));
4dfa5522 3264 data = mymalloc(sizeof(i_sample_t) * (r-l) * chan_count); /* XXX: memleak? */
faa9b3e7 3265 count = i_gsamp(im, l, r, y, data, chans, chan_count);
4dfa5522 3266 myfree(chans);
faa9b3e7
TC
3267 if (GIMME_V == G_ARRAY) {
3268 EXTEND(SP, count);
3269 for (i = 0; i < count; ++i)
3270 PUSHs(sv_2mortal(newSViv(data[i])));
3271 }
3272 else {
3273 EXTEND(SP, 1);
26fd367b 3274 PUSHs(sv_2mortal(newSVpv((char *)data, count * sizeof(i_sample_t))));
faa9b3e7 3275 }
a73aeb5f 3276 myfree(data);
faa9b3e7
TC
3277 }
3278 else {
3279 if (GIMME_V != G_ARRAY) {
3280 EXTEND(SP, 1);
3281 PUSHs(&PL_sv_undef);
3282 }
3283 }
3284
bd8052a6
TC
3285undef_neg_int
3286i_gsamp_bits(im, l, r, y, bits, target, offset, ...)
3287 Imager::ImgRaw im
3288 int l
3289 int r
3290 int y
3291 int bits
3292 AV *target
3293 int offset
3294 PREINIT:
3295 int *chans;
3296 int chan_count;
3297 unsigned *data;
3298 int count, i;
3299 CODE:
3300 i_clear_error();
3301 if (items < 8)
3302 croak("No channel numbers supplied to g_samp()");
3303 if (l < r) {
3304 chan_count = items - 7;
3305 chans = mymalloc(sizeof(int) * chan_count);
3306 for (i = 0; i < chan_count; ++i)
3307 chans[i] = SvIV(ST(i+7));
3308 data = mymalloc(sizeof(unsigned) * (r-l) * chan_count);
3309 count = i_gsamp_bits(im, l, r, y, data, chans, chan_count, bits);
3310 myfree(chans);
3311 for (i = 0; i < count; ++i) {
3312 av_store(target, i+offset, newSVuv(data[i]));
3313 }
3314 myfree(data);
3315 RETVAL = count;
3316 }
3317 else {
3318 RETVAL = 0;
3319 }
3320 OUTPUT:
3321 RETVAL
3322
3323undef_neg_int
3324i_psamp_bits(im, l, y, bits, channels_sv, data_av, data_offset = 0, pixel_count = -1)
3325 Imager::ImgRaw im
3326 int l
3327 int y
3328 int bits
3329 SV *channels_sv
3330 AV *data_av
3331 int data_offset
3332 int pixel_count
3333 PREINIT:
3334 int chan_count;
3335 int *channels;
3336 int data_count;
3337 int data_used;
3338 unsigned *data;
3339 int i;
3340 CODE:
3341 i_clear_error();
3342 if (SvOK(channels_sv)) {
3343 AV *channels_av;
3344 if (!SvROK(channels_sv) || SvTYPE(SvRV(channels_sv)) != SVt_PVAV) {
3345 croak("channels is not an array ref");
3346 }
3347 channels_av = (AV *)SvRV(channels_sv);
3348 chan_count = av_len(channels_av) + 1;
3349 if (chan_count < 1) {
3350 croak("i_psamp_bits: no channels provided");
3351 }
3352 channels = mymalloc(sizeof(int) * chan_count);
3353 for (i = 0; i < chan_count; ++i)
3354 channels[i] = SvIV(*av_fetch(channels_av, i, 0));
3355 }
3356 else {
3357 chan_count = im->channels;
3358 channels = NULL;
3359 }
3360
3361 data_count = av_len(data_av) + 1;
3362 if (data_offset < 0) {
3363 croak("data_offset must by non-negative");
3364 }
3365 if (data_offset > data_count) {
3366 croak("data_offset greater than number of samples supplied");
3367 }
3368 if (pixel_count == -1 ||
3369 data_offset + pixel_count * chan_count > data_count) {
3370 pixel_count = (data_count - data_offset) / chan_count;
3371 }
3372
3373 data_used = pixel_count * chan_count;
3374 data = mymalloc(sizeof(unsigned) * data_count);
3375 for (i = 0; i < data_used; ++i)
3376 data[i] = SvUV(*av_fetch(data_av, data_offset + i, 0));
3377
3378 RETVAL = i_psamp_bits(im, l, l + pixel_count, y, data, channels,
3379 chan_count, bits);
3380
3381 if (data)
3382 myfree(data);
3383 if (channels)
3384 myfree(channels);
3385 OUTPUT:
3386 RETVAL
a73aeb5f 3387
faa9b3e7
TC
3388Imager::ImgRaw
3389i_img_masked_new(targ, mask, x, y, w, h)
3390 Imager::ImgRaw targ
3391 int x
3392 int y
3393 int w
3394 int h
3395 PREINIT:
3396 i_img *mask;
3397 CODE:
3398 if (SvOK(ST(1))) {
3399 if (!sv_isobject(ST(1))
3400 || !sv_derived_from(ST(1), "Imager::ImgRaw")) {
3401 croak("i_img_masked_new: parameter 2 must undef or an image");
3402 }
4c4c2ffd 3403 mask = INT2PTR(i_img *, SvIV((SV *)SvRV(ST(1))));
faa9b3e7
TC
3404 }
3405 else
3406 mask = NULL;
3407 RETVAL = i_img_masked_new(targ, mask, x, y, w, h);
3408 OUTPUT:
3409 RETVAL
3410
3411int
3412i_plin(im, l, y, ...)
3413 Imager::ImgRaw im
3414 int l
3415 int y
3416 PREINIT:
3417 i_color *work;
ea9e6c3f 3418 int i;
ca4d914e
TC
3419 STRLEN len;
3420 int count;
faa9b3e7
TC
3421 CODE:
3422 if (items > 3) {
ca4d914e
TC
3423 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3424 /* supplied as a byte string */
3425 work = (i_color *)SvPV(ST(3), len);
3426 count = len / sizeof(i_color);
3427 if (count * sizeof(i_color) != len) {
3428 croak("i_plin: length of scalar argument must be multiple of sizeof i_color");
faa9b3e7 3429 }
ca4d914e
TC
3430 RETVAL = i_plin(im, l, l+count, y, work);
3431 }
3432 else {
3433 work = mymalloc(sizeof(i_color) * (items-3));
3434 for (i=0; i < items-3; ++i) {
3435 if (sv_isobject(ST(i+3))
3436 && sv_derived_from(ST(i+3), "Imager::Color")) {
3437 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3438 work[i] = *INT2PTR(i_color *, tmp);
3439 }
3440 else {
3441 myfree(work);
3442 croak("i_plin: pixels must be Imager::Color objects");
3443 }
faa9b3e7 3444 }
ca4d914e
TC
3445 RETVAL = i_plin(im, l, l+items-3, y, work);
3446 myfree(work);
faa9b3e7 3447 }
faa9b3e7
TC
3448 }
3449 else {
3450 RETVAL = 0;
3451 }
3452 OUTPUT:
3453 RETVAL
3454
3455int
3456i_ppixf(im, x, y, cl)
3457 Imager::ImgRaw im
3458 int x
3459 int y
3460 Imager::Color::Float cl
3461
3462void
3463i_gsampf(im, l, r, y, ...)
3464 Imager::ImgRaw im
3465 int l
3466 int r
3467 int y
3468 PREINIT:
3469 int *chans;
3470 int chan_count;
3471 i_fsample_t *data;
3472 int count, i;
3473 PPCODE:
3474 if (items < 5)
3475 croak("No channel numbers supplied to g_sampf()");
3476 if (l < r) {
3477 chan_count = items - 4;
3478 chans = mymalloc(sizeof(int) * chan_count);
3479 for (i = 0; i < chan_count; ++i)
3480 chans[i] = SvIV(ST(i+4));
3481 data = mymalloc(sizeof(i_fsample_t) * (r-l) * chan_count);
3482 count = i_gsampf(im, l, r, y, data, chans, chan_count);
3631271b 3483 myfree(chans);
faa9b3e7
TC
3484 if (GIMME_V == G_ARRAY) {
3485 EXTEND(SP, count);
3486 for (i = 0; i < count; ++i)
3487 PUSHs(sv_2mortal(newSVnv(data[i])));
3488 }
3489 else {
3490 EXTEND(SP, 1);
3491 PUSHs(sv_2mortal(newSVpv((void *)data, count * sizeof(i_fsample_t))));
3492 }
3631271b 3493 myfree(data);
faa9b3e7
TC
3494 }
3495 else {
3496 if (GIMME_V != G_ARRAY) {
3497 EXTEND(SP, 1);
3498 PUSHs(&PL_sv_undef);
3499 }
3500 }
3501
3502int
3503i_plinf(im, l, y, ...)
3504 Imager::ImgRaw im
3505 int l
3506 int y
3507 PREINIT:
3508 i_fcolor *work;
ea9e6c3f 3509 int i;
ca4d914e
TC
3510 STRLEN len;
3511 int count;
faa9b3e7
TC
3512 CODE:
3513 if (items > 3) {
ca4d914e
TC
3514 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3515 /* supplied as a byte string */
3516 work = (i_fcolor *)SvPV(ST(3), len);
3517 count = len / sizeof(i_fcolor);
3518 if (count * sizeof(i_fcolor) != len) {
3519 croak("i_plin: length of scalar argument must be multiple of sizeof i_fcolor");
faa9b3e7 3520 }
ca4d914e
TC
3521 RETVAL = i_plinf(im, l, l+count, y, work);
3522 }
3523 else {
3524 work = mymalloc(sizeof(i_fcolor) * (items-3));
3525 for (i=0; i < items-3; ++i) {
3526 if (sv_isobject(ST(i+3))
3527 && sv_derived_from(ST(i+3), "Imager::Color::Float")) {
3528 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3529 work[i] = *INT2PTR(i_fcolor *, tmp);
3530 }
3531 else {
3532 myfree(work);
3533 croak("i_plinf: pixels must be Imager::Color::Float objects");
3534 }
faa9b3e7 3535 }
ca4d914e
TC
3536 /**(char *)0 = 1;*/
3537 RETVAL = i_plinf(im, l, l+items-3, y, work);
3538 myfree(work);
faa9b3e7 3539 }
faa9b3e7
TC
3540 }
3541 else {
3542 RETVAL = 0;
3543 }
3544 OUTPUT:
3545 RETVAL
3546
3547SV *
3548i_gpixf(im, x, y)
3549 Imager::ImgRaw im
3550 int x
3551 int y;
3552 PREINIT:
3553 i_fcolor *color;
3554 CODE:
3555 color = (i_fcolor *)mymalloc(sizeof(i_fcolor));
3556 if (i_gpixf(im, x, y, color) == 0) {
a659442a
TC
3557 RETVAL = NEWSV(0,0);
3558 sv_setref_pv(RETVAL, "Imager::Color::Float", (void *)color);
faa9b3e7
TC
3559 }
3560 else {
3561 myfree(color);
a659442a 3562 RETVAL = &PL_sv_undef;
faa9b3e7 3563 }
a659442a
TC
3564 OUTPUT:
3565 RETVAL
3566
faa9b3e7
TC
3567void
3568i_glin(im, l, r, y)
3569 Imager::ImgRaw im
3570 int l
3571 int r
3572 int y
3573 PREINIT:
3574 i_color *vals;
3575 int count, i;
3576 PPCODE:
3577 if (l < r) {
3578 vals = mymalloc((r-l) * sizeof(i_color));
b3aa972f 3579 memset(vals, 0, (r-l) * sizeof(i_color));
faa9b3e7 3580 count = i_glin(im, l, r, y, vals);
ca4d914e
TC
3581 if (GIMME_V == G_ARRAY) {
3582 EXTEND(SP, count);
3583 for (i = 0; i < count; ++i) {
3584 SV *sv;
3585 i_color *col = mymalloc(sizeof(i_color));
3586 *col = vals[i];
3587 sv = sv_newmortal();
3588 sv_setref_pv(sv, "Imager::Color", (void *)col);
3589 PUSHs(sv);
3590 }
3591 }
3592 else if (count) {
3593 EXTEND(SP, 1);
3594 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_color))));
faa9b3e7
TC
3595 }
3596 myfree(vals);
3597 }
3598
3599void
3600i_glinf(im, l, r, y)
3601 Imager::ImgRaw im
3602 int l
3603 int r
3604 int y
3605 PREINIT:
3606 i_fcolor *vals;
3607 int count, i;
919e0000 3608 i_fcolor zero;
faa9b3e7 3609 PPCODE:
919e0000
TC
3610 for (i = 0; i < MAXCHANNELS; ++i)
3611 zero.channel[i] = 0;
faa9b3e7
TC
3612 if (l < r) {
3613 vals = mymalloc((r-l) * sizeof(i_fcolor));
b3aa972f
TC
3614 for (i = 0; i < r-l; ++i)
3615 vals[i] = zero;
faa9b3e7 3616 count = i_glinf(im, l, r, y, vals);
ca4d914e
TC
3617 if (GIMME_V == G_ARRAY) {
3618 EXTEND(SP, count);
3619 for (i = 0; i < count; ++i) {
3620 SV *sv;
3621 i_fcolor *col = mymalloc(sizeof(i_fcolor));
3622 *col = vals[i];
3623 sv = sv_newmortal();
3624 sv_setref_pv(sv, "Imager::Color::Float", (void *)col);
3625 PUSHs(sv);
3626 }
3627 }
3628 else if (count) {
3629 EXTEND(SP, 1);
3630 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_fcolor))));
faa9b3e7
TC
3631 }
3632 myfree(vals);
3633 }
3634
3635Imager::ImgRaw
3636i_img_16_new(x, y, ch)
3637 int x
3638 int y
3639 int ch
3640
167660cd
TC
3641Imager::ImgRaw
3642i_img_to_rgb16(im)
3643 Imager::ImgRaw im
3644
365ea842
TC
3645Imager::ImgRaw
3646i_img_double_new(x, y, ch)
3647 int x
3648 int y
3649 int ch
3650
faa9b3e7
TC
3651undef_int
3652i_tags_addn(im, name, code, idata)
3653 Imager::ImgRaw im
3654 int code
3655 int idata
3656 PREINIT:
3657 char *name;
3658 STRLEN len;
3659 CODE:
3660 if (SvOK(ST(1)))
3661 name = SvPV(ST(1), len);
3662 else
3663 name = NULL;
3664 RETVAL = i_tags_addn(&im->tags, name, code, idata);
3665 OUTPUT:
3666 RETVAL
3667
3668undef_int
3669i_tags_add(im, name, code, data, idata)
3670 Imager::ImgRaw im
3671 int code
3672 int idata
3673 PREINIT:
3674 char *name;
3675 char *data;
3676 STRLEN len;
3677 CODE:
3678 if (SvOK(ST(1)))
3679 name = SvPV(ST(1), len);
3680 else
3681 name = NULL;
3682 if (SvOK(ST(3)))
3683 data = SvPV(ST(3), len);
3684 else {
3685 data = NULL;
3686 len = 0;
3687 }
3688 RETVAL = i_tags_add(&im->tags, name, code, data, len, idata);
3689 OUTPUT:
3690 RETVAL
3691
3692SV *
3693i_tags_find(im, name, start)
3694 Imager::ImgRaw im
3695 char *name
3696 int start
3697 PREINIT:
3698 int entry;
3699 CODE:
3700 if (i_tags_find(&im->tags, name, start, &entry)) {
3701 if (entry == 0)
a659442a 3702 RETVAL = newSVpv("0 but true", 0);
faa9b3e7 3703 else
a659442a 3704 RETVAL = newSViv(entry);
faa9b3e7 3705 } else {
a659442a 3706 RETVAL = &PL_sv_undef;
faa9b3e7 3707 }
a659442a
TC
3708 OUTPUT:
3709 RETVAL
faa9b3e7
TC
3710
3711SV *
3712i_tags_findn(im, code, start)
3713 Imager::ImgRaw im
3714 int code
3715 int start
3716 PREINIT:
3717 int entry;
3718 CODE:
3719 if (i_tags_findn(&im->tags, code, start, &entry)) {
3720 if (entry == 0)
a659442a 3721 RETVAL = newSVpv("0 but true", 0);
faa9b3e7 3722 else
a659442a 3723 RETVAL = newSViv(entry);
faa9b3e7 3724 }
a659442a
TC
3725 else {
3726 RETVAL = &PL_sv_undef;
3727 }
3728 OUTPUT:
3729 RETVAL
faa9b3e7
TC
3730
3731int
3732i_tags_delete(im, entry)
3733 Imager::ImgRaw im
3734 int entry
3735 CODE:
3736 RETVAL = i_tags_delete(&im->tags, entry);
3737 OUTPUT:
3738 RETVAL
3739
3740int
3741i_tags_delbyname(im, name)
3742 Imager::ImgRaw im
3743 char * name
3744 CODE:
3745 RETVAL = i_tags_delbyname(&im->tags, name);
3746 OUTPUT:
3747 RETVAL
3748
3749int
3750i_tags_delbycode(im, code)
3751 Imager::ImgRaw im
3752 int code
3753 CODE:
3754 RETVAL = i_tags_delbycode(&im->tags, code);
3755 OUTPUT:
3756 RETVAL
3757
3758void
3759i_tags_get(im, index)
3760 Imager::ImgRaw im
3761 int index
3762 PPCODE:
3763 if (index >= 0 && index < im->tags.count) {
3764 i_img_tag *entry = im->tags.tags + index;
3765 EXTEND(SP, 5);
3766
3767 if (entry->name) {
3768 PUSHs(sv_2mortal(newSVpv(entry->name, 0)));
3769 }
3770 else {
3771 PUSHs(sv_2mortal(newSViv(entry->code)));
3772 }
3773 if (entry->data) {
3774 PUSHs(sv_2mortal(newSVpvn(entry->data, entry->size)));
3775 }
3776 else {
3777 PUSHs(sv_2mortal(newSViv(entry->idata)));
3778 }
3779 }
3780
241defe8
TC
3781void
3782i_tags_get_string(im, what_sv)
3783 Imager::ImgRaw im
3784 SV *what_sv
3785 PREINIT:
3786 char const *name = NULL;
3787 int code;
3788 char buffer[200];
241defe8
TC
3789 PPCODE:
3790 if (SvIOK(what_sv)) {
3791 code = SvIV(what_sv);
3792 name = NULL;
3793 }
3794 else {
3795 name = SvPV_nolen(what_sv);
3796 code = 0;
3797 }
3798 if (i_tags_get_string(&im->tags, name, code, buffer, sizeof(buffer))) {
3799 EXTEND(SP, 1);
3800 PUSHs(sv_2mortal(newSVpv(buffer, 0)));
3801 }
3802
faa9b3e7
TC
3803int
3804i_tags_count(im)
3805 Imager::ImgRaw im
3806 CODE:
3807 RETVAL = im->tags.count;
3808 OUTPUT:
3809 RETVAL
3810
3811#ifdef HAVE_WIN32
3812
3813void
bd4f550c 3814i_wf_bbox(face, size, text_sv, utf8=0)
faa9b3e7
TC
3815 char *face
3816 int size
bd4f550c
TC
3817 SV *text_sv
3818 int utf8
faa9b3e7 3819 PREINIT:
3799c4d1 3820 int cords[BOUNDING_BOX_COUNT];
0ab90434 3821 int rc, i;
bd4f550c
TC
3822 char const *text;
3823 STRLEN text_len;
faa9b3e7 3824 PPCODE:
bd4f550c
TC
3825 text = SvPV(text_sv, text_len);
3826#ifdef SvUTF8
3827 if (SvUTF8(text_sv))
3828 utf8 = 1;
3829#endif
3830 if (rc = i_wf_bbox(face, size, text, text_len, cords, utf8)) {
3799c4d1
TC
3831 EXTEND(SP, rc);
3832 for (i = 0; i < rc; ++i)
3833 PUSHs(sv_2mortal(newSViv(cords[i])));
faa9b3e7
TC
3834 }
3835
3836undef_int
bd4f550c 3837i_wf_text(face, im, tx, ty, cl, size, text_sv, align, aa, utf8 = 0)
faa9b3e7
TC
3838 char *face
3839 Imager::ImgRaw im
3840 int tx
3841 int ty
3842 Imager::Color cl
3843 int size
bd4f550c 3844 SV *text_sv
faa9b3e7
TC
3845 int align
3846 int aa
bd4f550c
TC
3847 int utf8
3848 PREINIT:
3849 char const *text;
3850 STRLEN text_len;
faa9b3e7 3851 CODE:
bd4f550c
TC
3852 text = SvPV(text_sv, text_len);
3853#ifdef SvUTF8
3854 if (SvUTF8(text_sv))
3855 utf8 = 1;
3856#endif
3857 RETVAL = i_wf_text(face, im, tx, ty, cl, size, text, text_len,
3858 align, aa, utf8);
faa9b3e7
TC
3859 OUTPUT:
3860 RETVAL
3861
3862undef_int
bd4f550c 3863i_wf_cp(face, im, tx, ty, channel, size, text_sv, align, aa, utf8 = 0)
faa9b3e7
TC
3864 char *face
3865 Imager::ImgRaw im
3866 int tx
3867 int ty
3868 int channel
3869 int size
bd4f550c 3870 SV *text_sv
faa9b3e7
TC
3871 int align
3872 int aa
bd4f550c
TC
3873 int utf8
3874 PREINIT:
3875 char const *text;
3876 STRLEN text_len;
f5991c03 3877 CODE:
bd4f550c
TC
3878 text = SvPV(text_sv, text_len);
3879#ifdef SvUTF8
3880 if (SvUTF8(text_sv))
3881 utf8 = 1;
3882#endif
a37159c4 3883 RETVAL = i_wf_cp(face, im, tx, ty, channel, size, text, text_len,
bd4f550c 3884 align, aa, utf8);
f5991c03
TC
3885 OUTPUT:
3886 RETVAL
02d1d628 3887
8457948a
TC
3888undef_int
3889i_wf_addfont(font)
3890 char *font
faa9b3e7 3891
8ceea84c
TC
3892undef_int
3893i_wf_delfont(font)
3894 char *font
3895
faa9b3e7
TC
3896#endif
3897
3898#ifdef HAVE_FT2
3899
3900MODULE = Imager PACKAGE = Imager::Font::FT2 PREFIX=FT2_
3901
3902#define FT2_DESTROY(font) i_ft2_destroy(font)
3903
3904void
3905FT2_DESTROY(font)
3906 Imager::Font::FT2 font
3907
ffddd407
TC
3908int
3909FT2_CLONE_SKIP(...)
3910 CODE:
3911 RETVAL = 1;
3912 OUTPUT:
3913 RETVAL
3914
faa9b3e7
TC
3915MODULE = Imager PACKAGE = Imager::Font::FreeType2
3916
3917Imager::Font::FT2
3918i_ft2_new(name, index)
3919 char *name
3920 int index
3921
3922undef_int
3923i_ft2_setdpi(font, xdpi, ydpi)
3924 Imager::Font::FT2 font
3925 int xdpi
3926 int ydpi
3927
3928void
3929i_ft2_getdpi(font)
3930 Imager::Font::FT2 font
3931 PREINIT:
3932 int xdpi, ydpi;
3933 CODE:
3934 if (i_ft2_getdpi(font, &xdpi, &ydpi)) {
3935 EXTEND(SP, 2);
3936 PUSHs(sv_2mortal(newSViv(xdpi)));
3937 PUSHs(sv_2mortal(newSViv(ydpi)));
3938 }
3939
3940undef_int
3941i_ft2_sethinting(font, hinting)
3942 Imager::Font::FT2 font
3943 int hinting
3944
3945undef_int
3946i_ft2_settransform(font, matrix)
3947 Imager::Font::FT2 font
3948 PREINIT:
3949 double matrix[6];
3950 int len;
3951 AV *av;
3952 SV *sv1;
3953 int i;
3954 CODE:
3955 if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV)
3956 croak("i_ft2_settransform: parameter 2 must be an array ref\n");
3957 av=(AV*)SvRV(ST(1));
3958 len=av_len(av)+1;
3959 if (len > 6)
3960 len = 6;
3961 for (i = 0; i < len; ++i) {
3962 sv1=(*(av_fetch(av,i,0)));
3963 matrix[i] = SvNV(sv1);
3964 }
3965 for (; i < 6; ++i)
3966 matrix[i] = 0;
3967 RETVAL = i_ft2_settransform(font, matrix);
3968 OUTPUT:
3969 RETVAL
3970
3971void
3799c4d1 3972i_ft2_bbox(font, cheight, cwidth, text_sv, utf8)
faa9b3e7
TC
3973 Imager::Font::FT2 font
3974 double cheight
3975 double cwidth
3799c4d1 3976 SV *text_sv
5cb9270b 3977 int utf8
faa9b3e7 3978 PREINIT:
3799c4d1 3979 int bbox[BOUNDING_BOX_COUNT];
faa9b3e7 3980 int i;
3799c4d1
TC
3981 char *text;
3982 STRLEN text_len;
3983 int rc;
faa9b3e7 3984 PPCODE:
3799c4d1 3985 text = SvPV(text_sv, text_len);
5cb9270b 3986#ifdef SvUTF8
3799c4d1 3987 if (SvUTF8(text_sv))
5cb9270b
TC
3988 utf8 = 1;
3989#endif
3799c4d1
TC
3990 rc = i_ft2_bbox(font, cheight, cwidth, text, text_len, bbox, utf8);
3991 if (rc) {
3992 EXTEND(SP, rc);
3993 for (i = 0; i < rc; ++i)
faa9b3e7
TC
3994 PUSHs(sv_2mortal(newSViv(bbox[i])));
3995 }
3996
3997void
3998i_ft2_bbox_r(font, cheight, cwidth, text, vlayout, utf8)
3999 Imager::Font::FT2 font
4000 double cheight
4001 double cwidth
4002 char *text
4003 int vlayout
4004 int utf8
4005 PREINIT:
4006 int bbox[8];
4007 int i;
4008 PPCODE:
4009#ifdef SvUTF8
4010 if (SvUTF8(ST(3)))
4011 utf8 = 1;
4012#endif
4013 if (i_ft2_bbox_r(font, cheight, cwidth, text, strlen(text), vlayout,
4014 utf8, bbox)) {
4015 EXTEND(SP, 8);
4016 for (i = 0; i < 8; ++i)
4017 PUSHs(sv_2mortal(newSViv(bbox[i])));
4018 }
4019
4020undef_int
4021i_ft2_text(font, im, tx, ty, cl, cheight, cwidth, text, align, aa, vlayout, utf8)
4022 Imager::Font::FT2 font
4023 Imager::ImgRaw im
4024 int tx
4025 int ty
4026 Imager::Color cl
4027 double cheight
4028 double cwidth
4029 int align
4030 int aa
4031 int vlayout
4032 int utf8
4033 PREINIT:
4034 char *text;
4035 STRLEN len;
4036 CODE:
4037#ifdef SvUTF8
4038 if (SvUTF8(ST(7))) {
4039 utf8 = 1;
4040 }
4041#endif
4042 text = SvPV(ST(7), len);
4043 RETVAL = i_ft2_text(font, im, tx, ty, cl, cheight, cwidth, text,
4044 len, align, aa, vlayout, utf8);
4045 OUTPUT:
4046 RETVAL
4047
4048undef_int
9a6ab99c 4049i_ft2_cp(font, im, tx, ty, channel, cheight, cwidth, text_sv, align, aa, vlayout, utf8)
faa9b3e7
TC
4050 Imager::Font::FT2 font
4051 Imager::ImgRaw im
4052 int tx
4053 int ty
4054 int channel
4055 double cheight
4056 double cwidth
9a6ab99c 4057 SV *text_sv
faa9b3e7
TC
4058 int align
4059 int aa
4060 int vlayout
4061 int utf8
9a6ab99c
TC
4062 PREINIT:
4063 char const *text;
4064 STRLEN len;
faa9b3e7
TC
4065 CODE:
4066#ifdef SvUTF8
4067 if (SvUTF8(ST(7)))
4068 utf8 = 1;
4069#endif
9a6ab99c 4070 text = SvPV(text_sv, len);
faa9b3e7 4071 RETVAL = i_ft2_cp(font, im, tx, ty, channel, cheight, cwidth, text,
9a6ab99c 4072 len, align, aa, vlayout, 1);
faa9b3e7
TC
4073 OUTPUT:
4074 RETVAL
4075
4076void
4077ft2_transform_box(font, x0, x1, x2, x3)
4078 Imager::Font::FT2 font
4079 int x0
4080 int x1
4081 int x2
4082 int x3
4083 PREINIT:
4084 int box[4];
4085 PPCODE:
4086 box[0] = x0; box[1] = x1; box[2] = x2; box[3] = x3;
4087 ft2_transform_box(font, box);
4088 EXTEND(SP, 4);
4089 PUSHs(sv_2mortal(newSViv(box[0])));
4090 PUSHs(sv_2mortal(newSViv(box[1])));
4091 PUSHs(sv_2mortal(newSViv(box[2])));
4092 PUSHs(sv_2mortal(newSViv(box[3])));
3dec2c92
TC
4093
4094void
eeaa33fd 4095i_ft2_has_chars(handle, text_sv, utf8)
3dec2c92 4096 Imager::Font::FT2 handle
eeaa33fd 4097 SV *text_sv
3dec2c92
TC
4098 int utf8
4099 PREINIT:
4100 char *text;
4101 STRLEN len;
4102 char *work;
4103 int count;
4104 int i;
4105 PPCODE:
4106#ifdef SvUTF8
eeaa33fd 4107 if (SvUTF8(text_sv))
3dec2c92
TC
4108 utf8 = 1;
4109#endif
eeaa33fd 4110 text = SvPV(text_sv, len);
3dec2c92
TC
4111 work = mymalloc(len);
4112 count = i_ft2_has_chars(handle, text, len, utf8, work);
4113 if (GIMME_V == G_ARRAY) {
4114 EXTEND(SP, count);
4115 for (i = 0; i < count; ++i) {
4116 PUSHs(sv_2mortal(newSViv(work[i])));
4117 }
4118 }
4119 else {
4120 EXTEND(SP, 1);
4121 PUSHs(sv_2mortal(newSVpv(work, count)));
4122 }
4123 myfree(work);
4124
3799c4d1
TC
4125void
4126i_ft2_face_name(handle)
4127 Imager::Font::FT2 handle
4128 PREINIT:
4129 char name[255];
4130 int len;
4131 PPCODE:
4132 len = i_ft2_face_name(handle, name, sizeof(name));
4133 if (len) {
4134 EXTEND(SP, 1);
4135 PUSHs(sv_2mortal(newSVpv(name, 0)));
4136 }
4137
042cdaea
TC
4138undef_int
4139i_ft2_can_face_name()
4140
19fa4baf 4141void
a4168bea 4142i_ft2_glyph_name(handle, text_sv, utf8 = 0, reliable_only = 1)
3799c4d1
TC
4143 Imager::Font::FT2 handle
4144 SV *text_sv
4145 int utf8
a4168bea 4146 int reliable_only
3799c4d1
TC
4147 PREINIT:
4148 char const *text;
4149 STRLEN work_len;
4150 int len;
3799c4d1
TC
4151 char name[255];
4152 PPCODE:
4153#ifdef SvUTF8
4154 if (SvUTF8(text_sv))
4155 utf8 = 1;
4156#endif
4157 text = SvPV(text_sv, work_len);
4158 len = work_len;
4159 while (len) {
a4168bea 4160 unsigned long ch;
3799c4d1
TC
4161 if (utf8) {
4162 ch = i_utf8_advance(&text, &len);
4163 if (ch == ~0UL) {
4164 i_push_error(0, "invalid UTF8 character");
4165 break;
4166 }
4167 }
4168 else {
4169 ch = *text++;
4170 --len;
4171 }
4172 EXTEND(SP, 1);
f364e883
TC
4173 if (i_ft2_glyph_name(handle, ch, name, sizeof(name),
4174 reliable_only)) {
3799c4d1
TC
4175 PUSHs(sv_2mortal(newSVpv(name, 0)));
4176 }
4177 else {
4178 PUSHs(&PL_sv_undef);
4179 }
4180 }
4181
4182int
4183i_ft2_can_do_glyph_names()
4184
4185int
4186i_ft2_face_has_glyph_names(handle)
4187 Imager::Font::FT2 handle
4188
3e882362
TC
4189int
4190i_ft2_is_multiple_master(handle)
4191 Imager::Font::FT2 handle<