optimize filled box drawing
[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
AMH
1971
1972#ifdef HAVE_LIBT1
1973
1974void
1975i_t1_set_aa(st)
1976 int st
1977
1978int
6b012d62 1979i_t1_new(pfb,afm)
02d1d628
AMH
1980 char* pfb
1981 char* afm
1982
1983int
1984i_t1_destroy(font_id)
1985 int font_id
1986
1987
1988undef_int
1bd75e4c 1989i_t1_cp(im,xb,yb,channel,fontnum,points,str_sv,len_ignored,align,utf8=0,flags="")
02d1d628
AMH
1990 Imager::ImgRaw im
1991 int xb
1992 int yb
1993 int channel
1994 int fontnum
1995 float points
1bd75e4c 1996 SV* str_sv
02d1d628 1997 int align
1bd75e4c
TC
1998 int utf8
1999 char* flags
2000 PREINIT:
2001 char *str;
2002 STRLEN len;
2003 CODE:
2004#ifdef SvUTF8
2005 if (SvUTF8(str_sv))
2006 utf8 = 1;
2007#endif
2008 str = SvPV(str_sv, len);
2009 RETVAL = i_t1_cp(im, xb,yb,channel,fontnum,points,str,len,align,
2010 utf8,flags);
2011 OUTPUT:
2012 RETVAL
2013
02d1d628
AMH
2014
2015void
1bd75e4c 2016i_t1_bbox(fontnum,point,str_sv,len_ignored,utf8=0,flags="")
02d1d628
AMH
2017 int fontnum
2018 float point
1bd75e4c
TC
2019 SV* str_sv
2020 int utf8
2021 char* flags
02d1d628 2022 PREINIT:
1bd75e4c
TC
2023 char *str;
2024 STRLEN len;
3799c4d1 2025 int cords[BOUNDING_BOX_COUNT];
1bd75e4c 2026 int i;
3799c4d1 2027 int rc;
02d1d628 2028 PPCODE:
1bd75e4c
TC
2029#ifdef SvUTF8
2030 if (SvUTF8(str_sv))
2031 utf8 = 1;
2032#endif
2033 str = SvPV(str_sv, len);
3799c4d1
TC
2034 rc = i_t1_bbox(fontnum,point,str,len,cords,utf8,flags);
2035 if (rc > 0) {
2036 EXTEND(SP, rc);
2037 for (i = 0; i < rc; ++i)
2038 PUSHs(sv_2mortal(newSViv(cords[i])));
2039 }
02d1d628
AMH
2040
2041
2042
2043undef_int
1bd75e4c 2044i_t1_text(im,xb,yb,cl,fontnum,points,str_sv,len_ignored,align,utf8=0,flags="")
02d1d628
AMH
2045 Imager::ImgRaw im
2046 int xb
2047 int yb
2048 Imager::Color cl
2049 int fontnum
2050 float points
1bd75e4c 2051 SV* str_sv
02d1d628 2052 int align
1bd75e4c
TC
2053 int utf8
2054 char* flags
2055 PREINIT:
2056 char *str;
2057 STRLEN len;
2058 CODE:
2059#ifdef SvUTF8
2060 if (SvUTF8(str_sv))
2061 utf8 = 1;
2062#endif
2063 str = SvPV(str_sv, len);
2064 RETVAL = i_t1_text(im, xb,yb,cl,fontnum,points,str,len,align,
2065 utf8,flags);
2066 OUTPUT:
2067 RETVAL
02d1d628 2068
3799c4d1
TC
2069void
2070i_t1_has_chars(handle, text_sv, utf8 = 0)
2071 int handle
2072 SV *text_sv
2073 int utf8
2074 PREINIT:
2075 char const *text;
2076 STRLEN len;
2077 char *work;
2078 int count;
2079 int i;
2080 PPCODE:
2081#ifdef SvUTF8
2082 if (SvUTF8(text_sv))
2083 utf8 = 1;
2084#endif
2085 text = SvPV(text_sv, len);
2086 work = mymalloc(len);
2087 count = i_t1_has_chars(handle, text, len, utf8, work);
2088 if (GIMME_V == G_ARRAY) {
2089 EXTEND(SP, count);
2090 for (i = 0; i < count; ++i) {
2091 PUSHs(sv_2mortal(newSViv(work[i])));
2092 }
2093 }
2094 else {
2095 EXTEND(SP, 1);
2096 PUSHs(sv_2mortal(newSVpv(work, count)));
2097 }
2098 myfree(work);
2099
2100void
2101i_t1_face_name(handle)
2102 int handle
2103 PREINIT:
2104 char name[255];
2105 int len;
2106 PPCODE:
2107 len = i_t1_face_name(handle, name, sizeof(name));
2108 if (len) {
2109 EXTEND(SP, 1);
2110 PUSHs(sv_2mortal(newSVpv(name, strlen(name))));
2111 }
2112
19fa4baf
AMH
2113void
2114i_t1_glyph_name(handle, text_sv, utf8 = 0)
3799c4d1
TC
2115 int handle
2116 SV *text_sv
2117 int utf8
2118 PREINIT:
2119 char const *text;
2120 STRLEN work_len;
2121 int len;
3799c4d1
TC
2122 char name[255];
2123 PPCODE:
2124#ifdef SvUTF8
2125 if (SvUTF8(text_sv))
2126 utf8 = 1;
2127#endif
2128 text = SvPV(text_sv, work_len);
2129 len = work_len;
2130 while (len) {
17892255 2131 unsigned long ch;
3799c4d1
TC
2132 if (utf8) {
2133 ch = i_utf8_advance(&text, &len);
2134 if (ch == ~0UL) {
2135 i_push_error(0, "invalid UTF8 character");
2136 break;
2137 }
2138 }
2139 else {
2140 ch = *text++;
2141 --len;
2142 }
2143 EXTEND(SP, 1);
f364e883 2144 if (i_t1_glyph_name(handle, ch, name, sizeof(name))) {
3799c4d1
TC
2145 PUSHs(sv_2mortal(newSVpv(name, 0)));
2146 }
2147 else {
2148 PUSHs(&PL_sv_undef);
2149 }
2150 }
2151
02d1d628
AMH
2152#endif
2153
2154#ifdef HAVE_LIBTT
2155
2156
4b19f77a 2157Imager::Font::TT
02d1d628
AMH
2158i_tt_new(fontname)
2159 char* fontname
2160
4b19f77a
AMH
2161
2162MODULE = Imager PACKAGE = Imager::Font::TT PREFIX=TT_
2163
2164#define TT_DESTROY(handle) i_tt_destroy(handle)
2165
02d1d628 2166void
4b19f77a
AMH
2167TT_DESTROY(handle)
2168 Imager::Font::TT handle
2169
ffddd407
TC
2170int
2171TT_CLONE_SKIP(...)
2172 CODE:
2173 RETVAL = 1;
2174 OUTPUT:
2175 RETVAL
2176
02d1d628 2177
4b19f77a 2178MODULE = Imager PACKAGE = Imager
02d1d628
AMH
2179
2180
2181undef_int
9ab6338b 2182i_tt_text(handle,im,xb,yb,cl,points,str_sv,len_ignored,smooth,utf8,align=1)
4b19f77a 2183 Imager::Font::TT handle
02d1d628
AMH
2184 Imager::ImgRaw im
2185 int xb
2186 int yb
2187 Imager::Color cl
2188 float points
4f68b48f 2189 SV * str_sv
02d1d628 2190 int smooth
4f68b48f 2191 int utf8
9ab6338b 2192 int align
4f68b48f
TC
2193 PREINIT:
2194 char *str;
2195 STRLEN len;
2196 CODE:
2197#ifdef SvUTF8
2198 if (SvUTF8(str_sv))
2199 utf8 = 1;
2200#endif
2201 str = SvPV(str_sv, len);
2202 RETVAL = i_tt_text(handle, im, xb, yb, cl, points, str,
9ab6338b 2203 len, smooth, utf8, align);
4f68b48f
TC
2204 OUTPUT:
2205 RETVAL
02d1d628
AMH
2206
2207
2208undef_int
9ab6338b 2209i_tt_cp(handle,im,xb,yb,channel,points,str_sv,len_ignored,smooth,utf8,align=1)
4b19f77a 2210 Imager::Font::TT handle
02d1d628
AMH
2211 Imager::ImgRaw im
2212 int xb
2213 int yb
2214 int channel
2215 float points
4f68b48f 2216 SV * str_sv
02d1d628 2217 int smooth
4f68b48f 2218 int utf8
9ab6338b 2219 int align
4f68b48f
TC
2220 PREINIT:
2221 char *str;
2222 STRLEN len;
2223 CODE:
2224#ifdef SvUTF8
2225 if (SvUTF8(str_sv))
2226 utf8 = 1;
2227#endif
2228 str = SvPV(str_sv, len);
2229 RETVAL = i_tt_cp(handle, im, xb, yb, channel, points, str, len,
9ab6338b 2230 smooth, utf8, align);
4f68b48f
TC
2231 OUTPUT:
2232 RETVAL
02d1d628
AMH
2233
2234
a659442a 2235void
4f68b48f 2236i_tt_bbox(handle,point,str_sv,len_ignored, utf8)
4b19f77a 2237 Imager::Font::TT handle
02d1d628 2238 float point
4f68b48f 2239 SV* str_sv
4f68b48f 2240 int utf8
02d1d628 2241 PREINIT:
3799c4d1 2242 int cords[BOUNDING_BOX_COUNT],rc;
4f68b48f
TC
2243 char * str;
2244 STRLEN len;
3799c4d1 2245 int i;
02d1d628 2246 PPCODE:
4f68b48f
TC
2247#ifdef SvUTF8
2248 if (SvUTF8(ST(2)))
2249 utf8 = 1;
2250#endif
2251 str = SvPV(str_sv, len);
2252 if ((rc=i_tt_bbox(handle,point,str,len,cords, utf8))) {
3799c4d1
TC
2253 EXTEND(SP, rc);
2254 for (i = 0; i < rc; ++i) {
2255 PUSHs(sv_2mortal(newSViv(cords[i])));
2256 }
02d1d628
AMH
2257 }
2258
eeaa33fd
TC
2259void
2260i_tt_has_chars(handle, text_sv, utf8)
2261 Imager::Font::TT handle
2262 SV *text_sv
2263 int utf8
2264 PREINIT:
2265 char const *text;
2266 STRLEN len;
2267 char *work;
2268 int count;
2269 int i;
2270 PPCODE:
2271#ifdef SvUTF8
2272 if (SvUTF8(text_sv))
2273 utf8 = 1;
2274#endif
2275 text = SvPV(text_sv, len);
2276 work = mymalloc(len);
2277 count = i_tt_has_chars(handle, text, len, utf8, work);
2278 if (GIMME_V == G_ARRAY) {
2279 EXTEND(SP, count);
2280 for (i = 0; i < count; ++i) {
2281 PUSHs(sv_2mortal(newSViv(work[i])));
2282 }
2283 }
2284 else {
2285 EXTEND(SP, 1);
2286 PUSHs(sv_2mortal(newSVpv(work, count)));
2287 }
2288 myfree(work);
02d1d628 2289
3799c4d1
TC
2290void
2291i_tt_dump_names(handle)
2292 Imager::Font::TT handle
02d1d628 2293
3799c4d1
TC
2294void
2295i_tt_face_name(handle)
2296 Imager::Font::TT handle
2297 PREINIT:
2298 char name[255];
2299 int len;
2300 PPCODE:
2301 len = i_tt_face_name(handle, name, sizeof(name));
2302 if (len) {
2303 EXTEND(SP, 1);
2304 PUSHs(sv_2mortal(newSVpv(name, strlen(name))));
2305 }
02d1d628 2306
19fa4baf
AMH
2307void
2308i_tt_glyph_name(handle, text_sv, utf8 = 0)
3799c4d1
TC
2309 Imager::Font::TT handle
2310 SV *text_sv
2311 int utf8
2312 PREINIT:
2313 char const *text;
2314 STRLEN work_len;
2315 int len;
2316 int outsize;
2317 char name[255];
2318 PPCODE:
2319#ifdef SvUTF8
2320 if (SvUTF8(text_sv))
2321 utf8 = 1;
2322#endif
2323 text = SvPV(text_sv, work_len);
2324 len = work_len;
2325 while (len) {
17892255 2326 unsigned long ch;
3799c4d1
TC
2327 if (utf8) {
2328 ch = i_utf8_advance(&text, &len);
2329 if (ch == ~0UL) {
2330 i_push_error(0, "invalid UTF8 character");
2331 break;
2332 }
2333 }
2334 else {
2335 ch = *text++;
2336 --len;
2337 }
2338 EXTEND(SP, 1);
af070d99 2339 if ((outsize = i_tt_glyph_name(handle, ch, name, sizeof(name))) != 0) {
3799c4d1
TC
2340 PUSHs(sv_2mortal(newSVpv(name, 0)));
2341 }
2342 else {
2343 PUSHs(&PL_sv_undef);
2344 }
2345 }
2346
2347#endif
02d1d628 2348
53a6bbd4 2349const char *
e10bf46e
AMH
2350i_test_format_probe(ig, length)
2351 Imager::IO ig
2352 int length
2353
02d1d628 2354Imager::ImgRaw
d87dc9a4 2355i_readpnm_wiol(ig, allow_incomplete)
02d1d628 2356 Imager::IO ig
d87dc9a4 2357 int allow_incomplete
02d1d628
AMH
2358
2359
2086be61
TC
2360void
2361i_readpnm_multi_wiol(ig, allow_incomplete)
2362 Imager::IO ig
2363 int allow_incomplete
2364 PREINIT:
2365 i_img **imgs;
2366 int count=0;
2367 int i;
2368 PPCODE:
2369 imgs = i_readpnm_multi_wiol(ig, &count, allow_incomplete);
2370 if (imgs) {
2371 EXTEND(SP, count);
2372 for (i = 0; i < count; ++i) {
2373 SV *sv = sv_newmortal();
2374 sv_setref_pv(sv, "Imager::ImgRaw", (void *)imgs[i]);
2375 PUSHs(sv);
2376 }
2377 myfree(imgs);
2378 }
2379
067d6bdc
AMH
2380undef_int
2381i_writeppm_wiol(im, ig)
2382 Imager::ImgRaw im
2383 Imager::IO ig
2384
2385
2086be61
TC
2386
2387
2388
02d1d628 2389Imager::ImgRaw
895dbd34
AMH
2390i_readraw_wiol(ig,x,y,datachannels,storechannels,intrl)
2391 Imager::IO ig
02d1d628
AMH
2392 int x
2393 int y
2394 int datachannels
2395 int storechannels
2396 int intrl
2397
2398undef_int
895dbd34 2399i_writeraw_wiol(im,ig)
02d1d628 2400 Imager::ImgRaw im
895dbd34
AMH
2401 Imager::IO ig
2402
261f91c5
TC
2403undef_int
2404i_writebmp_wiol(im,ig)
2405 Imager::ImgRaw im
2406 Imager::IO ig
02d1d628 2407
705fd961 2408Imager::ImgRaw
d87dc9a4 2409i_readbmp_wiol(ig, allow_incomplete=0)
705fd961 2410 Imager::IO ig
d87dc9a4 2411 int allow_incomplete
705fd961 2412
1ec86afa
AMH
2413
2414undef_int
febba01f 2415i_writetga_wiol(im,ig, wierdpack, compress, idstring)
1ec86afa
AMH
2416 Imager::ImgRaw im
2417 Imager::IO ig
febba01f
AMH
2418 int wierdpack
2419 int compress
2420 char* idstring
2421 PREINIT:
febba01f
AMH
2422 int idlen;
2423 CODE:
2424 idlen = SvCUR(ST(4));
2425 RETVAL = i_writetga_wiol(im, ig, wierdpack, compress, idstring, idlen);
2426 OUTPUT:
2427 RETVAL
2428
1ec86afa
AMH
2429
2430Imager::ImgRaw
2431i_readtga_wiol(ig, length)
2432 Imager::IO ig
2433 int length
2434
2435
737a830c
AMH
2436
2437
02d1d628
AMH
2438Imager::ImgRaw
2439i_scaleaxis(im,Value,Axis)
2440 Imager::ImgRaw im
2441 float Value
2442 int Axis
2443
2444Imager::ImgRaw
2445i_scale_nn(im,scx,scy)
2446 Imager::ImgRaw im
2447 float scx
2448 float scy
2449
658f724e
TC
2450Imager::ImgRaw
2451i_scale_mixing(im, width, height)
2452 Imager::ImgRaw im
2453 int width
2454 int height
2455
02d1d628
AMH
2456Imager::ImgRaw
2457i_haar(im)
2458 Imager::ImgRaw im
2459
2460int
2461i_count_colors(im,maxc)
2462 Imager::ImgRaw im
2463 int maxc
2464
fe622da1 2465void
a60905e4
TC
2466i_get_anonymous_color_histo(im, maxc = 0x40000000)
2467 Imager::ImgRaw im
2468 int maxc
4c99febf 2469 PREINIT:
fe622da1 2470 int i;
a60905e4 2471 unsigned int * col_usage = NULL;
4c99febf
TC
2472 int col_cnt;
2473 PPCODE:
2474 col_cnt = i_get_anonymous_color_histo(im, &col_usage, maxc);
fe622da1 2475 EXTEND(SP, col_cnt);
a60905e4
TC
2476 for (i = 0; i < col_cnt; i++) {
2477 PUSHs(sv_2mortal(newSViv( col_usage[i])));
fe622da1 2478 }
fe622da1
TC
2479 myfree(col_usage);
2480 XSRETURN(col_cnt);
2481
02d1d628
AMH
2482
2483Imager::ImgRaw
2484i_transform(im,opx,opy,parm)
2485 Imager::ImgRaw im
2486 PREINIT:
2487 double* parm;
2488 int* opx;
2489 int* opy;
2490 int opxl;
2491 int opyl;
2492 int parmlen;
2493 AV* av;
2494 SV* sv1;
2495 int i;
2496 CODE:
2497 if (!SvROK(ST(1))) croak("Imager: Parameter 1 must be a reference to an array\n");
2498 if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to an array\n");
2499 if (!SvROK(ST(3))) croak("Imager: Parameter 3 must be a reference to an array\n");
2500 if (SvTYPE(SvRV(ST(1))) != SVt_PVAV) croak("Imager: Parameter 1 must be a reference to an array\n");
2501 if (SvTYPE(SvRV(ST(2))) != SVt_PVAV) croak("Imager: Parameter 2 must be a reference to an array\n");
2502 if (SvTYPE(SvRV(ST(3))) != SVt_PVAV) croak("Imager: Parameter 3 must be a reference to an array\n");
2503 av=(AV*)SvRV(ST(1));
2504 opxl=av_len(av)+1;
2505 opx=mymalloc( opxl*sizeof(int) );
2506 for(i=0;i<opxl;i++) {
2507 sv1=(*(av_fetch(av,i,0)));
2508 opx[i]=(int)SvIV(sv1);
2509 }
2510 av=(AV*)SvRV(ST(2));
2511 opyl=av_len(av)+1;
2512 opy=mymalloc( opyl*sizeof(int) );
2513 for(i=0;i<opyl;i++) {
2514 sv1=(*(av_fetch(av,i,0)));
2515 opy[i]=(int)SvIV(sv1);
2516 }
2517 av=(AV*)SvRV(ST(3));
2518 parmlen=av_len(av)+1;
2519 parm=mymalloc( parmlen*sizeof(double) );
2520 for(i=0;i<parmlen;i++) { /* FIXME: Bug? */
2521 sv1=(*(av_fetch(av,i,0)));
2522 parm[i]=(double)SvNV(sv1);
2523 }
2524 RETVAL=i_transform(im,opx,opxl,opy,opyl,parm,parmlen);
2525 myfree(parm);
2526 myfree(opy);
2527 myfree(opx);
2528 ST(0) = sv_newmortal();
2529 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2530 else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
2531
2532Imager::ImgRaw
e5744e01
TC
2533i_transform2(sv_width,sv_height,channels,sv_ops,av_n_regs,av_c_regs,av_in_imgs)
2534 SV *sv_width
2535 SV *sv_height
2536 SV *sv_ops
2537 AV *av_n_regs
2538 AV *av_c_regs
2539 AV *av_in_imgs
2540 int channels
02d1d628
AMH
2541 PREINIT:
2542 int width;
2543 int height;
02d1d628 2544 struct rm_op *ops;
953209f8 2545 STRLEN ops_len;
02d1d628
AMH
2546 int ops_count;
2547 double *n_regs;
2548 int n_regs_count;
2549 i_color *c_regs;
2550 int c_regs_count;
2551 int in_imgs_count;
2552 i_img **in_imgs;
ea9e6c3f 2553 SV *sv1;
02d1d628
AMH
2554 IV tmp;
2555 int i;
2556 CODE:
e5744e01
TC
2557
2558 in_imgs_count = av_len(av_in_imgs)+1;
2559 for (i = 0; i < in_imgs_count; ++i) {
2560 sv1 = *av_fetch(av_in_imgs, i, 0);
2561 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
2562 croak("sv_in_img must contain only images");
02d1d628
AMH
2563 }
2564 }
b8c2033e 2565 if (in_imgs_count > 0) {
02d1d628
AMH
2566 in_imgs = mymalloc(in_imgs_count*sizeof(i_img*));
2567 for (i = 0; i < in_imgs_count; ++i) {
e5744e01 2568 sv1 = *av_fetch(av_in_imgs,i,0);
02d1d628
AMH
2569 if (!sv_derived_from(sv1, "Imager::ImgRaw")) {
2570 croak("Parameter 5 must contain only images");
2571 }
2572 tmp = SvIV((SV*)SvRV(sv1));
e375fbd8 2573 in_imgs[i] = INT2PTR(i_img*, tmp);
02d1d628
AMH
2574 }
2575 }
2576 else {
2577 /* no input images */
2578 in_imgs = NULL;
2579 }
2580 /* default the output size from the first input if possible */
e5744e01
TC
2581 if (SvOK(sv_width))
2582 width = SvIV(sv_width);
02d1d628
AMH
2583 else if (in_imgs_count)
2584 width = in_imgs[0]->xsize;
2585 else
2586 croak("No output image width supplied");
2587
e5744e01
TC
2588 if (SvOK(sv_height))
2589 height = SvIV(sv_height);
02d1d628
AMH
2590 else if (in_imgs_count)
2591 height = in_imgs[0]->ysize;
2592 else
2593 croak("No output image height supplied");
2594
e5744e01 2595 ops = (struct rm_op *)SvPV(sv_ops, ops_len);
02d1d628
AMH
2596 if (ops_len % sizeof(struct rm_op))
2597 croak("Imager: Parameter 3 must be a bitmap of regops\n");
2598 ops_count = ops_len / sizeof(struct rm_op);
e5744e01
TC
2599
2600 n_regs_count = av_len(av_n_regs)+1;
02d1d628
AMH
2601 n_regs = mymalloc(n_regs_count * sizeof(double));
2602 for (i = 0; i < n_regs_count; ++i) {
e5744e01 2603 sv1 = *av_fetch(av_n_regs,i,0);
02d1d628
AMH
2604 if (SvOK(sv1))
2605 n_regs[i] = SvNV(sv1);
2606 }
e5744e01 2607 c_regs_count = av_len(av_c_regs)+1;
02d1d628
AMH
2608 c_regs = mymalloc(c_regs_count * sizeof(i_color));
2609 /* I don't bother initializing the colou?r registers */
2610
e5744e01 2611 RETVAL=i_transform2(width, height, channels, ops, ops_count,
02d1d628
AMH
2612 n_regs, n_regs_count,
2613 c_regs, c_regs_count, in_imgs, in_imgs_count);
2614 if (in_imgs)
2615 myfree(in_imgs);
2616 myfree(n_regs);
2617 myfree(c_regs);
2618 ST(0) = sv_newmortal();
2619 if (RETVAL == 0) ST(0)=&PL_sv_undef;
2620 else sv_setref_pv(ST(0), "Imager::ImgRaw", (void*)RETVAL);
2621
2622
2623void
2624i_contrast(im,intensity)
2625 Imager::ImgRaw im
2626 float intensity
2627
2628void
2629i_hardinvert(im)
2630 Imager::ImgRaw im
2631
5558f899
TC
2632void
2633i_hardinvertall(im)
2634 Imager::ImgRaw im
2635
02d1d628
AMH
2636void
2637i_noise(im,amount,type)
2638 Imager::ImgRaw im
2639 float amount
2640 unsigned char type
2641
2642void
2643i_bumpmap(im,bump,channel,light_x,light_y,strength)
2644 Imager::ImgRaw im
2645 Imager::ImgRaw bump
2646 int channel
2647 int light_x
2648 int light_y
2649 int strength
2650
b2778574
AMH
2651
2652void
2653i_bumpmap_complex(im,bump,channel,tx,ty,Lx,Ly,Lz,cd,cs,n,Ia,Il,Is)
2654 Imager::ImgRaw im
2655 Imager::ImgRaw bump
2656 int channel
2657 int tx
2658 int ty
2659 float Lx
2660 float Ly
2661 float Lz
2662 float cd
2663 float cs
2664 float n
2665 Imager::Color Ia
2666 Imager::Color Il
2667 Imager::Color Is
2668
2669
2670
02d1d628
AMH
2671void
2672i_postlevels(im,levels)
2673 Imager::ImgRaw im
2674 int levels
2675
2676void
2677i_mosaic(im,size)
2678 Imager::ImgRaw im
2679 int size
2680
2681void
2682i_watermark(im,wmark,tx,ty,pixdiff)
2683 Imager::ImgRaw im
2684 Imager::ImgRaw wmark
2685 int tx
2686 int ty
2687 int pixdiff
2688
2689
2690void
2691i_autolevels(im,lsat,usat,skew)
2692 Imager::ImgRaw im
2693 float lsat
2694 float usat
2695 float skew
2696
2697void
2698i_radnoise(im,xo,yo,rscale,ascale)
2699 Imager::ImgRaw im
2700 float xo
2701 float yo
2702 float rscale
2703 float ascale
2704
2705void
2706i_turbnoise(im, xo, yo, scale)
2707 Imager::ImgRaw im
2708 float xo
2709 float yo
2710 float scale
2711
2712
2713void
2714i_gradgen(im, ...)
2715 Imager::ImgRaw im
2716 PREINIT:
2717 int num;
2718 int *xo;
2719 int *yo;
2720 i_color *ival;
2721 int dmeasure;
2722 int i;
2723 SV *sv;
2724 AV *axx;
2725 AV *ayy;
2726 AV *ac;
2727 CODE:
2728 if (items != 5)
2729 croak("Usage: i_gradgen(im, xo, yo, ival, dmeasure)");
2730 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2731 croak("i_gradgen: Second argument must be an array ref");
2732 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
2733 croak("i_gradgen: Third argument must be an array ref");
2734 if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
2735 croak("i_gradgen: Fourth argument must be an array ref");
2736 axx = (AV *)SvRV(ST(1));
2737 ayy = (AV *)SvRV(ST(2));
2738 ac = (AV *)SvRV(ST(3));
2739 dmeasure = (int)SvIV(ST(4));
2740
2741 num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
2742 num = num <= av_len(ac) ? num : av_len(ac);
2743 num++;
2744 if (num < 2) croak("Usage: i_gradgen array refs must have more than 1 entry each");
2745 xo = mymalloc( sizeof(int) * num );
2746 yo = mymalloc( sizeof(int) * num );
2747 ival = mymalloc( sizeof(i_color) * num );
2748 for(i = 0; i<num; i++) {
2749 xo[i] = (int)SvIV(* av_fetch(axx, i, 0));
2750 yo[i] = (int)SvIV(* av_fetch(ayy, i, 0));
2751 sv = *av_fetch(ac, i, 0);
2752 if ( !sv_derived_from(sv, "Imager::Color") ) {
2753 free(axx); free(ayy); free(ac);
2754 croak("i_gradgen: Element of fourth argument is not derived from Imager::Color");
2755 }
4c4c2ffd 2756 ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
02d1d628
AMH
2757 }
2758 i_gradgen(im, num, xo, yo, ival, dmeasure);
a73aeb5f
AMH
2759 myfree(xo);
2760 myfree(yo);
2761 myfree(ival);
2762
dff75dee
TC
2763Imager::ImgRaw
2764i_diff_image(im, im2, mindist=0)
2765 Imager::ImgRaw im
2766 Imager::ImgRaw im2
01b84320 2767 double mindist
02d1d628 2768
e310e5f9 2769undef_int
6607600c
TC
2770i_fountain(im, xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
2771 Imager::ImgRaw im
2772 double xa
2773 double ya
2774 double xb
2775 double yb
2776 int type
2777 int repeat
2778 int combine
2779 int super_sample
2780 double ssample_param
2781 PREINIT:
6607600c 2782 AV *asegs;
6607600c
TC
2783 int count;
2784 i_fountain_seg *segs;
6607600c 2785 CODE:
6607600c
TC
2786 if (!SvROK(ST(10)) || ! SvTYPE(SvRV(ST(10))))
2787 croak("i_fountain: argument 11 must be an array ref");
2788
2789 asegs = (AV *)SvRV(ST(10));
b13a3ddb 2790 segs = load_fount_segs(aTHX_ asegs, &count);
e310e5f9
TC
2791 RETVAL = i_fountain(im, xa, ya, xb, yb, type, repeat, combine,
2792 super_sample, ssample_param, count, segs);
6607600c 2793 myfree(segs);
e310e5f9
TC
2794 OUTPUT:
2795 RETVAL
02d1d628 2796
f1ac5027
TC
2797Imager::FillHandle
2798i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine, super_sample, ssample_param, segs)
2799 double xa
2800 double ya
2801 double xb
2802 double yb
2803 int type
2804 int repeat
2805 int combine
2806 int super_sample
2807 double ssample_param
2808 PREINIT:
2809 AV *asegs;
2810 int count;
2811 i_fountain_seg *segs;
2812 CODE:
2813 if (!SvROK(ST(9)) || ! SvTYPE(SvRV(ST(9))))
2814 croak("i_fountain: argument 11 must be an array ref");
2815
2816 asegs = (AV *)SvRV(ST(9));
b13a3ddb 2817 segs = load_fount_segs(aTHX_ asegs, &count);
f1ac5027
TC
2818 RETVAL = i_new_fill_fount(xa, ya, xb, yb, type, repeat, combine,
2819 super_sample, ssample_param, count, segs);
2820 myfree(segs);
2821 OUTPUT:
2822 RETVAL
2823
52f2b10a
TC
2824Imager::FillHandle
2825i_new_fill_opacity(other_fill, alpha_mult)
2826 Imager::FillHandle other_fill
2827 double alpha_mult
2828
4f4f776a
TC
2829void
2830i_errors()
2831 PREINIT:
2832 i_errmsg *errors;
2833 int i;
4f4f776a 2834 AV *av;
4f4f776a
TC
2835 SV *sv;
2836 PPCODE:
2837 errors = i_errors();
2838 i = 0;
2839 while (errors[i].msg) {
2840 av = newAV();
2841 sv = newSVpv(errors[i].msg, strlen(errors[i].msg));
2842 if (!av_store(av, 0, sv)) {
2843 SvREFCNT_dec(sv);
2844 }
2845 sv = newSViv(errors[i].code);
2846 if (!av_store(av, 1, sv)) {
2847 SvREFCNT_dec(sv);
2848 }
2849 PUSHs(sv_2mortal(newRV_noinc((SV*)av)));
2850 ++i;
2851 }
02d1d628 2852
2b405c9e
TC
2853void
2854i_clear_error()
2855
2856void
2857i_push_error(code, msg)
2858 int code
2859 const char *msg
2860
e310e5f9 2861undef_int
02d1d628
AMH
2862i_nearest_color(im, ...)
2863 Imager::ImgRaw im
2864 PREINIT:
2865 int num;
2866 int *xo;
2867 int *yo;
2868 i_color *ival;
2869 int dmeasure;
2870 int i;
2871 SV *sv;
2872 AV *axx;
2873 AV *ayy;
2874 AV *ac;
2875 CODE:
2876 if (items != 5)
2877 croak("Usage: i_nearest_color(im, xo, yo, ival, dmeasure)");
2878 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
2879 croak("i_nearest_color: Second argument must be an array ref");
2880 if (!SvROK(ST(2)) || ! SvTYPE(SvRV(ST(2))))
2881 croak("i_nearest_color: Third argument must be an array ref");
2882 if (!SvROK(ST(3)) || ! SvTYPE(SvRV(ST(3))))
2883 croak("i_nearest_color: Fourth argument must be an array ref");
2884 axx = (AV *)SvRV(ST(1));
2885 ayy = (AV *)SvRV(ST(2));
2886 ac = (AV *)SvRV(ST(3));
2887 dmeasure = (int)SvIV(ST(4));
2888
2889 num = av_len(axx) < av_len(ayy) ? av_len(axx) : av_len(ayy);
2890 num = num <= av_len(ac) ? num : av_len(ac);
2891 num++;
2892 if (num < 2) croak("Usage: i_nearest_color array refs must have more than 1 entry each");
2893 xo = mymalloc( sizeof(int) * num );
2894 yo = mymalloc( sizeof(int) * num );
2895 ival = mymalloc( sizeof(i_color) * num );
2896 for(i = 0; i<num; i++) {
2897 xo[i] = (int)SvIV(* av_fetch(axx, i, 0));
2898 yo[i] = (int)SvIV(* av_fetch(ayy, i, 0));
2899 sv = *av_fetch(ac, i, 0);
2900 if ( !sv_derived_from(sv, "Imager::Color") ) {
2901 free(axx); free(ayy); free(ac);
2902 croak("i_nearest_color: Element of fourth argument is not derived from Imager::Color");
2903 }
4c4c2ffd 2904 ival[i] = *INT2PTR(i_color *, SvIV((SV *)SvRV(sv)));
02d1d628 2905 }
e310e5f9
TC
2906 RETVAL = i_nearest_color(im, num, xo, yo, ival, dmeasure);
2907 OUTPUT:
2908 RETVAL
02d1d628
AMH
2909
2910void
2911malloc_state()
2912
02d1d628
AMH
2913void
2914DSO_open(filename)
2915 char* filename
2916 PREINIT:
2917 void *rc;
2918 char *evstr;
2919 PPCODE:
2920 rc=DSO_open(filename,&evstr);
2921 if (rc!=NULL) {
2922 if (evstr!=NULL) {
2923 EXTEND(SP,2);
e375fbd8 2924 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
02d1d628
AMH
2925 PUSHs(sv_2mortal(newSVpvn(evstr, strlen(evstr))));
2926 } else {
2927 EXTEND(SP,1);
e375fbd8 2928 PUSHs(sv_2mortal(newSViv(PTR2IV(rc))));
02d1d628
AMH
2929 }
2930 }
2931
2932
2933undef_int
2934DSO_close(dso_handle)
2935 void* dso_handle
2936
2937void
2938DSO_funclist(dso_handle_v)
2939 void* dso_handle_v
2940 PREINIT:
2941 int i;
2942 DSO_handle *dso_handle;
d8e0c3ba 2943 func_ptr *functions;
02d1d628
AMH
2944 PPCODE:
2945 dso_handle=(DSO_handle*)dso_handle_v;
d8e0c3ba 2946 functions = DSO_funclist(dso_handle);
02d1d628 2947 i=0;
d8e0c3ba 2948 while( functions[i].name != NULL) {
02d1d628 2949 EXTEND(SP,1);
d8e0c3ba 2950 PUSHs(sv_2mortal(newSVpv(functions[i].name,0)));
02d1d628 2951 EXTEND(SP,1);
d8e0c3ba 2952 PUSHs(sv_2mortal(newSVpv(functions[i++].pcode,0)));
02d1d628
AMH
2953 }
2954
02d1d628
AMH
2955void
2956DSO_call(handle,func_index,hv)
2957 void* handle
2958 int func_index
2959 PREINIT:
2960 HV* hv;
2961 PPCODE:
2962 if (!SvROK(ST(2))) croak("Imager: Parameter 2 must be a reference to a hash\n");
2963 hv=(HV*)SvRV(ST(2));
2964 if (SvTYPE(hv)!=SVt_PVHV) croak("Imager: Parameter 2 must be a reference to a hash\n");
2965 DSO_call( (DSO_handle *)handle,func_index,hv);
2966
faa9b3e7 2967SV *
f5991c03
TC
2968i_get_pixel(im, x, y)
2969 Imager::ImgRaw im
2970 int x
2971 int y;
faa9b3e7
TC
2972 PREINIT:
2973 i_color *color;
2974 CODE:
2975 color = (i_color *)mymalloc(sizeof(i_color));
2976 if (i_gpix(im, x, y, color) == 0) {
a659442a
TC
2977 RETVAL = NEWSV(0, 0);
2978 sv_setref_pv(RETVAL, "Imager::Color", (void *)color);
faa9b3e7
TC
2979 }
2980 else {
2981 myfree(color);
a659442a 2982 RETVAL = &PL_sv_undef;
faa9b3e7 2983 }
a659442a
TC
2984 OUTPUT:
2985 RETVAL
faa9b3e7
TC
2986
2987
2988int
2989i_ppix(im, x, y, cl)
2990 Imager::ImgRaw im
2991 int x
2992 int y
2993 Imager::Color cl
2994
2995Imager::ImgRaw
2996i_img_pal_new(x, y, channels, maxpal)
2997 int x
2998 int y
2999 int channels
3000 int maxpal
3001
3002Imager::ImgRaw
3003i_img_to_pal(src, quant)
3004 Imager::ImgRaw src
3005 PREINIT:
3006 HV *hv;
3007 i_quantize quant;
3008 CODE:
3009 if (!SvROK(ST(1)) || ! SvTYPE(SvRV(ST(1))))
3010 croak("i_img_to_pal: second argument must be a hash ref");
3011 hv = (HV *)SvRV(ST(1));
3012 memset(&quant, 0, sizeof(quant));
ec6d8908 3013 quant.version = 1;
faa9b3e7 3014 quant.mc_size = 256;
ec6d8908 3015 ip_handle_quant_opts(aTHX_ &quant, hv);
faa9b3e7
TC
3016 RETVAL = i_img_to_pal(src, &quant);
3017 if (RETVAL) {
ec6d8908 3018 ip_copy_colors_back(aTHX_ hv, &quant);
faa9b3e7 3019 }
ec6d8908 3020 ip_cleanup_quant_opts(aTHX_ &quant);
faa9b3e7
TC
3021 OUTPUT:
3022 RETVAL
3023
3024Imager::ImgRaw
3025i_img_to_rgb(src)
3026 Imager::ImgRaw src
3027
3028void
3029i_gpal(im, l, r, y)
3030 Imager::ImgRaw im
3031 int l
3032 int r
3033 int y
3034 PREINIT:
3035 i_palidx *work;
3036 int count, i;
3037 PPCODE:
3038 if (l < r) {
3039 work = mymalloc((r-l) * sizeof(i_palidx));
3040 count = i_gpal(im, l, r, y, work);
3041 if (GIMME_V == G_ARRAY) {
3042 EXTEND(SP, count);
3043 for (i = 0; i < count; ++i) {
3044 PUSHs(sv_2mortal(newSViv(work[i])));
3045 }
3046 }
3047 else {
3048 EXTEND(SP, 1);
26fd367b 3049 PUSHs(sv_2mortal(newSVpv((char *)work, count * sizeof(i_palidx))));
faa9b3e7
TC
3050 }
3051 myfree(work);
3052 }
3053 else {
3054 if (GIMME_V != G_ARRAY) {
3055 EXTEND(SP, 1);
3056 PUSHs(&PL_sv_undef);
3057 }
3058 }
3059
3060int
3061i_ppal(im, l, y, ...)
3062 Imager::ImgRaw im
3063 int l
3064 int y
3065 PREINIT:
3066 i_palidx *work;
ea9e6c3f 3067 int i;
faa9b3e7
TC
3068 CODE:
3069 if (items > 3) {
3070 work = mymalloc(sizeof(i_palidx) * (items-3));
3071 for (i=0; i < items-3; ++i) {
3072 work[i] = SvIV(ST(i+3));
3073 }
4cda4e76 3074 validate_i_ppal(im, work, items - 3);
faa9b3e7
TC
3075 RETVAL = i_ppal(im, l, l+items-3, y, work);
3076 myfree(work);
3077 }
3078 else {
3079 RETVAL = 0;
3080 }
3081 OUTPUT:
3082 RETVAL
3083
4cda4e76
TC
3084int
3085i_ppal_p(im, l, y, data)
3086 Imager::ImgRaw im
3087 int l
3088 int y
3089 SV *data
3090 PREINIT:
3091 i_palidx const *work;
4cda4e76 3092 STRLEN len;
4cda4e76
TC
3093 CODE:
3094 work = (i_palidx const *)SvPV(data, len);
3095 len /= sizeof(i_palidx);
3096 if (len > 0) {
3097 validate_i_ppal(im, work, len);
3098 RETVAL = i_ppal(im, l, l+len, y, work);
3099 }
3100 else {
3101 RETVAL = 0;
3102 }
3103 OUTPUT:
3104 RETVAL
3105
faa9b3e7
TC
3106SV *
3107i_addcolors(im, ...)
3108 Imager::ImgRaw im
3109 PREINIT:
3110 int index;
3111 i_color *colors;
3112 int i;
3113 CODE:
3114 if (items < 2)
3115 croak("i_addcolors: no colors to add");
3116 colors = mymalloc((items-1) * sizeof(i_color));
3117 for (i=0; i < items-1; ++i) {
3118 if (sv_isobject(ST(i+1))
3119 && sv_derived_from(ST(i+1), "Imager::Color")) {
3120 IV tmp = SvIV((SV *)SvRV(ST(i+1)));
4c4c2ffd 3121 colors[i] = *INT2PTR(i_color *, tmp);
faa9b3e7
TC
3122 }
3123 else {
3124 myfree(colors);
ca4d914e 3125 croak("i_addcolor: pixels must be Imager::Color objects");
faa9b3e7
TC
3126 }
3127 }
3128 index = i_addcolors(im, colors, items-1);
3129 myfree(colors);
3130 if (index == 0) {
a659442a 3131 RETVAL = newSVpv("0 but true", 0);
faa9b3e7
TC
3132 }
3133 else if (index == -1) {
a659442a 3134 RETVAL = &PL_sv_undef;
faa9b3e7
TC
3135 }
3136 else {
a659442a 3137 RETVAL = newSViv(index);
faa9b3e7 3138 }
a659442a
TC
3139 OUTPUT:
3140 RETVAL
faa9b3e7 3141
1501d9b3 3142undef_int
faa9b3e7
TC
3143i_setcolors(im, index, ...)
3144 Imager::ImgRaw im
3145 int index
3146 PREINIT:
3147 i_color *colors;
3148 int i;
3149 CODE:
3150 if (items < 3)
3151 croak("i_setcolors: no colors to add");
3152 colors = mymalloc((items-2) * sizeof(i_color));
3153 for (i=0; i < items-2; ++i) {
3154 if (sv_isobject(ST(i+2))
3155 && sv_derived_from(ST(i+2), "Imager::Color")) {
3156 IV tmp = SvIV((SV *)SvRV(ST(i+2)));
4c4c2ffd 3157 colors[i] = *INT2PTR(i_color *, tmp);
faa9b3e7
TC
3158 }
3159 else {
3160 myfree(colors);
3161 croak("i_setcolors: pixels must be Imager::Color objects");
3162 }
3163 }
3164 RETVAL = i_setcolors(im, index, colors, items-2);
3165 myfree(colors);
1501d9b3
TC
3166 OUTPUT:
3167 RETVAL
faa9b3e7
TC
3168
3169void
3170i_getcolors(im, index, ...)
3171 Imager::ImgRaw im
3172 int index
3173 PREINIT:
3174 i_color *colors;
3175 int count = 1;
3176 int i;
3177 PPCODE:
3178 if (items > 3)
3179 croak("i_getcolors: too many arguments");
3180 if (items == 3)
3181 count = SvIV(ST(2));
3182 if (count < 1)
3183 croak("i_getcolors: count must be positive");
3184 colors = mymalloc(sizeof(i_color) * count);
3185 if (i_getcolors(im, index, colors, count)) {
3186 for (i = 0; i < count; ++i) {
3187 i_color *pv;
3188 SV *sv = sv_newmortal();
3189 pv = mymalloc(sizeof(i_color));
3190 *pv = colors[i];
3191 sv_setref_pv(sv, "Imager::Color", (void *)pv);
3192 PUSHs(sv);
3193 }
3194 }
3195 myfree(colors);
3196
3197
a659442a 3198undef_neg_int
faa9b3e7
TC
3199i_colorcount(im)
3200 Imager::ImgRaw im
faa9b3e7 3201
a659442a 3202undef_neg_int
faa9b3e7
TC
3203i_maxcolors(im)
3204 Imager::ImgRaw im
faa9b3e7
TC
3205
3206SV *
3207i_findcolor(im, color)
3208 Imager::ImgRaw im
3209 Imager::Color color
3210 PREINIT:
3211 i_palidx index;
3212 CODE:
3213 if (i_findcolor(im, color, &index)) {
a659442a 3214 RETVAL = newSViv(index);
faa9b3e7
TC
3215 }
3216 else {
a659442a 3217 RETVAL = &PL_sv_undef;
faa9b3e7 3218 }
a659442a
TC
3219 OUTPUT:
3220 RETVAL
faa9b3e7
TC
3221
3222int
3223i_img_bits(im)
3224 Imager::ImgRaw im
3225
3226int
3227i_img_type(im)
3228 Imager::ImgRaw im
3229
3230int
3231i_img_virtual(im)
3232 Imager::ImgRaw im
3233
3234void
3235i_gsamp(im, l, r, y, ...)
3236 Imager::ImgRaw im
3237 int l
3238 int r
3239 int y
3240 PREINIT:
3241 int *chans;
3242 int chan_count;
3243 i_sample_t *data;
3244 int count, i;
3245 PPCODE:
3246 if (items < 5)
3247 croak("No channel numbers supplied to g_samp()");
3248 if (l < r) {
3249 chan_count = items - 4;
3250 chans = mymalloc(sizeof(int) * chan_count);
3251 for (i = 0; i < chan_count; ++i)
3252 chans[i] = SvIV(ST(i+4));
4dfa5522 3253 data = mymalloc(sizeof(i_sample_t) * (r-l) * chan_count); /* XXX: memleak? */
faa9b3e7 3254 count = i_gsamp(im, l, r, y, data, chans, chan_count);
4dfa5522 3255 myfree(chans);
faa9b3e7
TC
3256 if (GIMME_V == G_ARRAY) {
3257 EXTEND(SP, count);
3258 for (i = 0; i < count; ++i)
3259 PUSHs(sv_2mortal(newSViv(data[i])));
3260 }
3261 else {
3262 EXTEND(SP, 1);
26fd367b 3263 PUSHs(sv_2mortal(newSVpv((char *)data, count * sizeof(i_sample_t))));
faa9b3e7 3264 }
a73aeb5f 3265 myfree(data);
faa9b3e7
TC
3266 }
3267 else {
3268 if (GIMME_V != G_ARRAY) {
3269 EXTEND(SP, 1);
3270 PUSHs(&PL_sv_undef);
3271 }
3272 }
3273
bd8052a6
TC
3274undef_neg_int
3275i_gsamp_bits(im, l, r, y, bits, target, offset, ...)
3276 Imager::ImgRaw im
3277 int l
3278 int r
3279 int y
3280 int bits
3281 AV *target
3282 int offset
3283 PREINIT:
3284 int *chans;
3285 int chan_count;
3286 unsigned *data;
3287 int count, i;
3288 CODE:
3289 i_clear_error();
3290 if (items < 8)
3291 croak("No channel numbers supplied to g_samp()");
3292 if (l < r) {
3293 chan_count = items - 7;
3294 chans = mymalloc(sizeof(int) * chan_count);
3295 for (i = 0; i < chan_count; ++i)
3296 chans[i] = SvIV(ST(i+7));
3297 data = mymalloc(sizeof(unsigned) * (r-l) * chan_count);
3298 count = i_gsamp_bits(im, l, r, y, data, chans, chan_count, bits);
3299 myfree(chans);
3300 for (i = 0; i < count; ++i) {
3301 av_store(target, i+offset, newSVuv(data[i]));
3302 }
3303 myfree(data);
3304 RETVAL = count;
3305 }
3306 else {
3307 RETVAL = 0;
3308 }
3309 OUTPUT:
3310 RETVAL
3311
3312undef_neg_int
3313i_psamp_bits(im, l, y, bits, channels_sv, data_av, data_offset = 0, pixel_count = -1)
3314 Imager::ImgRaw im
3315 int l
3316 int y
3317 int bits
3318 SV *channels_sv
3319 AV *data_av
3320 int data_offset
3321 int pixel_count
3322 PREINIT:
3323 int chan_count;
3324 int *channels;
3325 int data_count;
3326 int data_used;
3327 unsigned *data;
3328 int i;
3329 CODE:
3330 i_clear_error();
3331 if (SvOK(channels_sv)) {
3332 AV *channels_av;
3333 if (!SvROK(channels_sv) || SvTYPE(SvRV(channels_sv)) != SVt_PVAV) {
3334 croak("channels is not an array ref");
3335 }
3336 channels_av = (AV *)SvRV(channels_sv);
3337 chan_count = av_len(channels_av) + 1;
3338 if (chan_count < 1) {
3339 croak("i_psamp_bits: no channels provided");
3340 }
3341 channels = mymalloc(sizeof(int) * chan_count);
3342 for (i = 0; i < chan_count; ++i)
3343 channels[i] = SvIV(*av_fetch(channels_av, i, 0));
3344 }
3345 else {
3346 chan_count = im->channels;
3347 channels = NULL;
3348 }
3349
3350 data_count = av_len(data_av) + 1;
3351 if (data_offset < 0) {
3352 croak("data_offset must by non-negative");
3353 }
3354 if (data_offset > data_count) {
3355 croak("data_offset greater than number of samples supplied");
3356 }
3357 if (pixel_count == -1 ||
3358 data_offset + pixel_count * chan_count > data_count) {
3359 pixel_count = (data_count - data_offset) / chan_count;
3360 }
3361
3362 data_used = pixel_count * chan_count;
3363 data = mymalloc(sizeof(unsigned) * data_count);
3364 for (i = 0; i < data_used; ++i)
3365 data[i] = SvUV(*av_fetch(data_av, data_offset + i, 0));
3366
3367 RETVAL = i_psamp_bits(im, l, l + pixel_count, y, data, channels,
3368 chan_count, bits);
3369
3370 if (data)
3371 myfree(data);
3372 if (channels)
3373 myfree(channels);
3374 OUTPUT:
3375 RETVAL
a73aeb5f 3376
faa9b3e7
TC
3377Imager::ImgRaw
3378i_img_masked_new(targ, mask, x, y, w, h)
3379 Imager::ImgRaw targ
3380 int x
3381 int y
3382 int w
3383 int h
3384 PREINIT:
3385 i_img *mask;
3386 CODE:
3387 if (SvOK(ST(1))) {
3388 if (!sv_isobject(ST(1))
3389 || !sv_derived_from(ST(1), "Imager::ImgRaw")) {
3390 croak("i_img_masked_new: parameter 2 must undef or an image");
3391 }
4c4c2ffd 3392 mask = INT2PTR(i_img *, SvIV((SV *)SvRV(ST(1))));
faa9b3e7
TC
3393 }
3394 else
3395 mask = NULL;
3396 RETVAL = i_img_masked_new(targ, mask, x, y, w, h);
3397 OUTPUT:
3398 RETVAL
3399
3400int
3401i_plin(im, l, y, ...)
3402 Imager::ImgRaw im
3403 int l
3404 int y
3405 PREINIT:
3406 i_color *work;
ea9e6c3f 3407 int i;
ca4d914e
TC
3408 STRLEN len;
3409 int count;
faa9b3e7
TC
3410 CODE:
3411 if (items > 3) {
ca4d914e
TC
3412 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3413 /* supplied as a byte string */
3414 work = (i_color *)SvPV(ST(3), len);
3415 count = len / sizeof(i_color);
3416 if (count * sizeof(i_color) != len) {
3417 croak("i_plin: length of scalar argument must be multiple of sizeof i_color");
faa9b3e7 3418 }
ca4d914e
TC
3419 RETVAL = i_plin(im, l, l+count, y, work);
3420 }
3421 else {
3422 work = mymalloc(sizeof(i_color) * (items-3));
3423 for (i=0; i < items-3; ++i) {
3424 if (sv_isobject(ST(i+3))
3425 && sv_derived_from(ST(i+3), "Imager::Color")) {
3426 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3427 work[i] = *INT2PTR(i_color *, tmp);
3428 }
3429 else {
3430 myfree(work);
3431 croak("i_plin: pixels must be Imager::Color objects");
3432 }
faa9b3e7 3433 }
ca4d914e
TC
3434 RETVAL = i_plin(im, l, l+items-3, y, work);
3435 myfree(work);
faa9b3e7 3436 }
faa9b3e7
TC
3437 }
3438 else {
3439 RETVAL = 0;
3440 }
3441 OUTPUT:
3442 RETVAL
3443
3444int
3445i_ppixf(im, x, y, cl)
3446 Imager::ImgRaw im
3447 int x
3448 int y
3449 Imager::Color::Float cl
3450
3451void
3452i_gsampf(im, l, r, y, ...)
3453 Imager::ImgRaw im
3454 int l
3455 int r
3456 int y
3457 PREINIT:
3458 int *chans;
3459 int chan_count;
3460 i_fsample_t *data;
3461 int count, i;
3462 PPCODE:
3463 if (items < 5)
3464 croak("No channel numbers supplied to g_sampf()");
3465 if (l < r) {
3466 chan_count = items - 4;
3467 chans = mymalloc(sizeof(int) * chan_count);
3468 for (i = 0; i < chan_count; ++i)
3469 chans[i] = SvIV(ST(i+4));
3470 data = mymalloc(sizeof(i_fsample_t) * (r-l) * chan_count);
3471 count = i_gsampf(im, l, r, y, data, chans, chan_count);
3631271b 3472 myfree(chans);
faa9b3e7
TC
3473 if (GIMME_V == G_ARRAY) {
3474 EXTEND(SP, count);
3475 for (i = 0; i < count; ++i)
3476 PUSHs(sv_2mortal(newSVnv(data[i])));
3477 }
3478 else {
3479 EXTEND(SP, 1);
3480 PUSHs(sv_2mortal(newSVpv((void *)data, count * sizeof(i_fsample_t))));
3481 }
3631271b 3482 myfree(data);
faa9b3e7
TC
3483 }
3484 else {
3485 if (GIMME_V != G_ARRAY) {
3486 EXTEND(SP, 1);
3487 PUSHs(&PL_sv_undef);
3488 }
3489 }
3490
3491int
3492i_plinf(im, l, y, ...)
3493 Imager::ImgRaw im
3494 int l
3495 int y
3496 PREINIT:
3497 i_fcolor *work;
ea9e6c3f 3498 int i;
ca4d914e
TC
3499 STRLEN len;
3500 int count;
faa9b3e7
TC
3501 CODE:
3502 if (items > 3) {
ca4d914e
TC
3503 if (items == 4 && SvOK(ST(3)) && !SvROK(ST(3))) {
3504 /* supplied as a byte string */
3505 work = (i_fcolor *)SvPV(ST(3), len);
3506 count = len / sizeof(i_fcolor);
3507 if (count * sizeof(i_fcolor) != len) {
3508 croak("i_plin: length of scalar argument must be multiple of sizeof i_fcolor");
faa9b3e7 3509 }
ca4d914e
TC
3510 RETVAL = i_plinf(im, l, l+count, y, work);
3511 }
3512 else {
3513 work = mymalloc(sizeof(i_fcolor) * (items-3));
3514 for (i=0; i < items-3; ++i) {
3515 if (sv_isobject(ST(i+3))
3516 && sv_derived_from(ST(i+3), "Imager::Color::Float")) {
3517 IV tmp = SvIV((SV *)SvRV(ST(i+3)));
3518 work[i] = *INT2PTR(i_fcolor *, tmp);
3519 }
3520 else {
3521 myfree(work);
3522 croak("i_plinf: pixels must be Imager::Color::Float objects");
3523 }
faa9b3e7 3524 }
ca4d914e
TC
3525 /**(char *)0 = 1;*/
3526 RETVAL = i_plinf(im, l, l+items-3, y, work);
3527 myfree(work);
faa9b3e7 3528 }
faa9b3e7
TC
3529 }
3530 else {
3531 RETVAL = 0;
3532 }
3533 OUTPUT:
3534 RETVAL
3535
3536SV *
3537i_gpixf(im, x, y)
3538 Imager::ImgRaw im
3539 int x
3540 int y;
3541 PREINIT:
3542 i_fcolor *color;
3543 CODE:
3544 color = (i_fcolor *)mymalloc(sizeof(i_fcolor));
3545 if (i_gpixf(im, x, y, color) == 0) {
a659442a
TC
3546 RETVAL = NEWSV(0,0);
3547 sv_setref_pv(RETVAL, "Imager::Color::Float", (void *)color);
faa9b3e7
TC
3548 }
3549 else {
3550 myfree(color);
a659442a 3551 RETVAL = &PL_sv_undef;
faa9b3e7 3552 }
a659442a
TC
3553 OUTPUT:
3554 RETVAL
3555
faa9b3e7
TC
3556void
3557i_glin(im, l, r, y)
3558 Imager::ImgRaw im
3559 int l
3560 int r
3561 int y
3562 PREINIT:
3563 i_color *vals;
3564 int count, i;
3565 PPCODE:
3566 if (l < r) {
3567 vals = mymalloc((r-l) * sizeof(i_color));
b3aa972f 3568 memset(vals, 0, (r-l) * sizeof(i_color));
faa9b3e7 3569 count = i_glin(im, l, r, y, vals);
ca4d914e
TC
3570 if (GIMME_V == G_ARRAY) {
3571 EXTEND(SP, count);
3572 for (i = 0; i < count; ++i) {
3573 SV *sv;
3574 i_color *col = mymalloc(sizeof(i_color));
3575 *col = vals[i];
3576 sv = sv_newmortal();
3577 sv_setref_pv(sv, "Imager::Color", (void *)col);
3578 PUSHs(sv);
3579 }
3580 }
3581 else if (count) {
3582 EXTEND(SP, 1);
3583 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_color))));
faa9b3e7
TC
3584 }
3585 myfree(vals);
3586 }
3587
3588void
3589i_glinf(im, l, r, y)
3590 Imager::ImgRaw im
3591 int l
3592 int r
3593 int y
3594 PREINIT:
3595 i_fcolor *vals;
3596 int count, i;
919e0000 3597 i_fcolor zero;
faa9b3e7 3598 PPCODE:
919e0000
TC
3599 for (i = 0; i < MAXCHANNELS; ++i)
3600 zero.channel[i] = 0;
faa9b3e7
TC
3601 if (l < r) {
3602 vals = mymalloc((r-l) * sizeof(i_fcolor));
b3aa972f
TC
3603 for (i = 0; i < r-l; ++i)
3604 vals[i] = zero;
faa9b3e7 3605 count = i_glinf(im, l, r, y, vals);
ca4d914e
TC
3606 if (GIMME_V == G_ARRAY) {
3607 EXTEND(SP, count);
3608 for (i = 0; i < count; ++i) {
3609 SV *sv;
3610 i_fcolor *col = mymalloc(sizeof(i_fcolor));
3611 *col = vals[i];
3612 sv = sv_newmortal();
3613 sv_setref_pv(sv, "Imager::Color::Float", (void *)col);
3614 PUSHs(sv);
3615 }
3616 }
3617 else if (count) {
3618 EXTEND(SP, 1);
3619 PUSHs(sv_2mortal(newSVpv((void *)vals, count * sizeof(i_fcolor))));
faa9b3e7
TC
3620 }
3621 myfree(vals);
3622 }
3623
3624Imager::ImgRaw
3625i_img_16_new(x, y, ch)
3626 int x
3627 int y
3628 int ch
3629
167660cd
TC
3630Imager::ImgRaw
3631i_img_to_rgb16(im)
3632 Imager::ImgRaw im
3633
365ea842
TC
3634Imager::ImgRaw
3635i_img_double_new(x, y, ch)
3636 int x
3637 int y
3638 int ch
3639
faa9b3e7
TC
3640undef_int
3641i_tags_addn(im, name, code, idata)
3642 Imager::ImgRaw im
3643 int code
3644 int idata
3645 PREINIT:
3646 char *name;
3647 STRLEN len;
3648 CODE:
3649 if (SvOK(ST(1)))
3650 name = SvPV(ST(1), len);
3651 else
3652 name = NULL;
3653 RETVAL = i_tags_addn(&im->tags, name, code, idata);
3654 OUTPUT:
3655 RETVAL
3656
3657undef_int
3658i_tags_add(im, name, code, data, idata)
3659 Imager::ImgRaw im
3660 int code
3661 int idata
3662 PREINIT:
3663 char *name;
3664 char *data;
3665 STRLEN len;
3666 CODE:
3667 if (SvOK(ST(1)))
3668 name = SvPV(ST(1), len);
3669 else
3670 name = NULL;
3671 if (SvOK(ST(3)))
3672 data = SvPV(ST(3), len);
3673 else {
3674 data = NULL;
3675 len = 0;
3676 }
3677 RETVAL = i_tags_add(&im->tags, name, code, data, len, idata);
3678 OUTPUT:
3679 RETVAL
3680
3681SV *
3682i_tags_find(im, name, start)
3683 Imager::ImgRaw im
3684 char *name
3685 int start
3686 PREINIT:
3687 int entry;
3688 CODE:
3689 if (i_tags_find(&im->tags, name, start, &entry)) {
3690 if (entry == 0)
a659442a 3691 RETVAL = newSVpv("0 but true", 0);
faa9b3e7 3692 else
a659442a 3693 RETVAL = newSViv(entry);
faa9b3e7 3694 } else {
a659442a 3695 RETVAL = &PL_sv_undef;
faa9b3e7 3696 }
a659442a
TC
3697 OUTPUT:
3698 RETVAL
faa9b3e7
TC
3699
3700SV *
3701i_tags_findn(im, code, start)
3702 Imager::ImgRaw im
3703 int code
3704 int start
3705 PREINIT:
3706 int entry;
3707 CODE:
3708 if (i_tags_findn(&im->tags, code, start, &entry)) {
3709 if (entry == 0)
a659442a 3710 RETVAL = newSVpv("0 but true", 0);
faa9b3e7 3711 else
a659442a 3712 RETVAL = newSViv(entry);
faa9b3e7 3713 }
a659442a
TC
3714 else {
3715 RETVAL = &PL_sv_undef;
3716 }
3717 OUTPUT:
3718 RETVAL
faa9b3e7
TC
3719
3720int
3721i_tags_delete(im, entry)
3722 Imager::ImgRaw im
3723 int entry
3724 CODE:
3725 RETVAL = i_tags_delete(&im->tags, entry);
3726 OUTPUT:
3727 RETVAL
3728
3729int
3730i_tags_delbyname(im, name)
3731 Imager::ImgRaw im
3732 char * name
3733 CODE:
3734 RETVAL = i_tags_delbyname(&im->tags, name);
3735 OUTPUT:
3736 RETVAL
3737
3738int
3739i_tags_delbycode(im, code)
3740 Imager::ImgRaw im
3741 int code
3742 CODE:
3743 RETVAL = i_tags_delbycode(&im->tags, code);
3744 OUTPUT:
3745 RETVAL
3746
3747void
3748i_tags_get(im, index)
3749 Imager::ImgRaw im
3750 int index
3751 PPCODE:
3752 if (index >= 0 && index < im->tags.count) {
3753 i_img_tag *entry = im->tags.tags + index;
3754 EXTEND(SP, 5);
3755
3756 if (entry->name) {
3757 PUSHs(sv_2mortal(newSVpv(entry->name, 0)));
3758 }
3759 else {
3760 PUSHs(sv_2mortal(newSViv(entry->code)));
3761 }
3762 if (entry->data) {
3763 PUSHs(sv_2mortal(newSVpvn(entry->data, entry->size)));
3764 }
3765 else {
3766 PUSHs(sv_2mortal(newSViv(entry->idata)));
3767 }
3768 }
3769
241defe8
TC
3770void
3771i_tags_get_string(im, what_sv)
3772 Imager::ImgRaw im
3773 SV *what_sv
3774 PREINIT:
3775 char const *name = NULL;
3776 int code;
3777 char buffer[200];
241defe8
TC
3778 PPCODE:
3779 if (SvIOK(what_sv)) {
3780 code = SvIV(what_sv);
3781 name = NULL;
3782 }
3783 else {
3784 name = SvPV_nolen(what_sv);
3785 code = 0;
3786 }
3787 if (i_tags_get_string(&im->tags, name, code, buffer, sizeof(buffer))) {
3788 EXTEND(SP, 1);
3789 PUSHs(sv_2mortal(newSVpv(buffer, 0)));
3790 }
3791
faa9b3e7
TC
3792int
3793i_tags_count(im)
3794 Imager::ImgRaw im
3795 CODE:
3796 RETVAL = im->tags.count;
3797 OUTPUT:
3798 RETVAL
3799
3800#ifdef HAVE_WIN32
3801
3802void
bd4f550c 3803i_wf_bbox(face, size, text_sv, utf8=0)
faa9b3e7
TC
3804 char *face
3805 int size
bd4f550c
TC
3806 SV *text_sv
3807 int utf8
faa9b3e7 3808 PREINIT:
3799c4d1 3809 int cords[BOUNDING_BOX_COUNT];
0ab90434 3810 int rc, i;
bd4f550c
TC
3811 char const *text;
3812 STRLEN text_len;
faa9b3e7 3813 PPCODE:
bd4f550c
TC
3814 text = SvPV(text_sv, text_len);
3815#ifdef SvUTF8
3816 if (SvUTF8(text_sv))
3817 utf8 = 1;
3818#endif
3819 if (rc = i_wf_bbox(face, size, text, text_len, cords, utf8)) {
3799c4d1
TC
3820 EXTEND(SP, rc);
3821 for (i = 0; i < rc; ++i)
3822 PUSHs(sv_2mortal(newSViv(cords[i])));
faa9b3e7
TC
3823 }
3824
3825undef_int
bd4f550c 3826i_wf_text(face, im, tx, ty, cl, size, text_sv, align, aa, utf8 = 0)
faa9b3e7
TC
3827 char *face
3828 Imager::ImgRaw im
3829 int tx
3830 int ty
3831 Imager::Color cl
3832 int size
bd4f550c 3833 SV *text_sv
faa9b3e7
TC
3834 int align
3835 int aa
bd4f550c
TC
3836 int utf8
3837 PREINIT:
3838 char const *text;
3839 STRLEN text_len;
faa9b3e7 3840 CODE:
bd4f550c
TC
3841 text = SvPV(text_sv, text_len);
3842#ifdef SvUTF8
3843 if (SvUTF8(text_sv))
3844 utf8 = 1;
3845#endif
3846 RETVAL = i_wf_text(face, im, tx, ty, cl, size, text, text_len,
3847 align, aa, utf8);
faa9b3e7
TC
3848 OUTPUT:
3849 RETVAL
3850
3851undef_int
bd4f550c 3852i_wf_cp(face, im, tx, ty, channel, size, text_sv, align, aa, utf8 = 0)
faa9b3e7
TC
3853 char *face
3854 Imager::ImgRaw im
3855 int tx
3856 int ty
3857 int channel
3858 int size
bd4f550c 3859 SV *text_sv
faa9b3e7
TC
3860 int align
3861 int aa
bd4f550c
TC
3862 int utf8
3863 PREINIT:
3864 char const *text;
3865 STRLEN text_len;
f5991c03 3866 CODE:
bd4f550c
TC
3867 text = SvPV(text_sv, text_len);
3868#ifdef SvUTF8
3869 if (SvUTF8(text_sv))
3870 utf8 = 1;
3871#endif
a37159c4 3872 RETVAL = i_wf_cp(face, im, tx, ty, channel, size, text, text_len,
bd4f550c 3873 align, aa, utf8);
f5991c03
TC
3874 OUTPUT:
3875 RETVAL
02d1d628 3876
8457948a
TC
3877undef_int
3878i_wf_addfont(font)
3879 char *font
faa9b3e7 3880
8ceea84c
TC
3881undef_int
3882i_wf_delfont(font)
3883 char *font
3884
faa9b3e7
TC
3885#endif
3886
3887#ifdef HAVE_FT2
3888
3889MODULE = Imager PACKAGE = Imager::Font::FT2 PREFIX=FT2_
3890
3891#define FT2_DESTROY(font) i_ft2_destroy(font)
3892
3893void
3894FT2_DESTROY(font)
3895 Imager::Font::FT2 font
3896
ffddd407
TC
3897int
3898FT2_CLONE_SKIP(...)
3899 CODE:
3900 RETVAL = 1;
3901 OUTPUT:
3902 RETVAL
3903
faa9b3e7
TC
3904MODULE = Imager PACKAGE = Imager::Font::FreeType2
3905
3906Imager::Font::FT2
3907i_ft2_new(name, index)
3908 char *name
3909 int index
3910
3911undef_int
3912i_ft2_setdpi(font, xdpi, ydpi)
3913 Imager::Font::FT2 font
3914 int xdpi
3915 int ydpi
3916
3917void
3918i_ft2_getdpi(font)
3919 Imager::Font::FT2 font
3920 PREINIT:
3921 int xdpi, ydpi;
3922 CODE:
3923 if (i_ft2_getdpi(font, &xdpi, &ydpi)) {
3924 EXTEND(SP, 2);
3925 PUSHs(sv_2mortal(newSViv(xdpi)));
3926 PUSHs(sv_2mortal(newSViv(ydpi)));
3927 }
3928
3929undef_int
3930i_ft2_sethinting(font, hinting)
3931 Imager::Font::FT2 font
3932 int hinting
3933
3934undef_int
3935i_ft2_settransform(font, matrix)
3936 Imager::Font::FT2 font
3937 PREINIT:
3938 double matrix[6];
3939 int len;
3940 AV *av;
3941 SV *sv1;
3942 int i;
3943 CODE:
3944 if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV)
3945 croak("i_ft2_settransform: parameter 2 must be an array ref\n");
3946 av=(AV*)SvRV(ST(1));
3947 len=av_len(av)+1;
3948 if (len > 6)
3949 len = 6;
3950 for (i = 0; i < len; ++i) {
3951 sv1=(*(av_fetch(av,i,0)));
3952 matrix[i] = SvNV(sv1);
3953 }
3954 for (; i < 6; ++i)
3955 matrix[i] = 0;
3956 RETVAL = i_ft2_settransform(font, matrix);
3957 OUTPUT:
3958 RETVAL
3959
3960void
3799c4d1 3961i_ft2_bbox(font, cheight, cwidth, text_sv, utf8)
faa9b3e7
TC
3962 Imager::Font::FT2 font
3963 double cheight
3964 double cwidth
3799c4d1 3965 SV *text_sv
5cb9270b 3966 int utf8
faa9b3e7 3967 PREINIT:
3799c4d1 3968 int bbox[BOUNDING_BOX_COUNT];
faa9b3e7 3969 int i;
3799c4d1
TC
3970 char *text;
3971 STRLEN text_len;
3972 int rc;
faa9b3e7 3973 PPCODE:
3799c4d1 3974 text = SvPV(text_sv, text_len);
5cb9270b 3975#ifdef SvUTF8
3799c4d1 3976 if (SvUTF8(text_sv))
5cb9270b
TC
3977 utf8 = 1;
3978#endif
3799c4d1
TC
3979 rc = i_ft2_bbox(font, cheight, cwidth, text, text_len, bbox, utf8);
3980 if (rc) {
3981 EXTEND(SP, rc);
3982 for (i = 0; i < rc; ++i)
faa9b3e7
TC
3983 PUSHs(sv_2mortal(newSViv(bbox[i])));
3984 }
3985
3986void
3987i_ft2_bbox_r(font, cheight, cwidth, text, vlayout, utf8)
3988 Imager::Font::FT2 font
3989 double cheight
3990 double cwidth
3991 char *text
3992 int vlayout
3993 int utf8
3994 PREINIT:
3995 int bbox[8];
3996 int i;
3997 PPCODE:
3998#ifdef SvUTF8
3999 if (SvUTF8(ST(3)))
4000 utf8 = 1;
4001#endif
4002 if (i_ft2_bbox_r(font, cheight, cwidth, text, strlen(text), vlayout,
4003 utf8, bbox)) {
4004 EXTEND(SP, 8);
4005 for (i = 0; i < 8; ++i)
4006 PUSHs(sv_2mortal(newSViv(bbox[i])));
4007 }
4008
4009undef_int
4010i_ft2_text(font, im, tx, ty, cl, cheight, cwidth, text, align, aa, vlayout, utf8)
4011 Imager::Font::FT2 font
4012 Imager::ImgRaw im
4013 int tx
4014 int ty
4015 Imager::Color cl
4016 double cheight
4017 double cwidth
4018 int align
4019 int aa
4020 int vlayout
4021 int utf8
4022 PREINIT:
4023 char *text;
4024 STRLEN len;
4025 CODE:
4026#ifdef SvUTF8
4027 if (SvUTF8(ST(7))) {
4028 utf8 = 1;
4029 }
4030#endif
4031 text = SvPV(ST(7), len);
4032 RETVAL = i_ft2_text(font, im, tx, ty, cl, cheight, cwidth, text,
4033 len, align, aa, vlayout, utf8);
4034 OUTPUT:
4035 RETVAL
4036
4037undef_int
9a6ab99c 4038i_ft2_cp(font, im, tx, ty, channel, cheight, cwidth, text_sv, align, aa, vlayout, utf8)
faa9b3e7
TC
4039 Imager::Font::FT2 font
4040 Imager::ImgRaw im
4041 int tx
4042 int ty
4043 int channel
4044 double cheight
4045 double cwidth
9a6ab99c 4046 SV *text_sv
faa9b3e7
TC
4047 int align
4048 int aa
4049 int vlayout
4050 int utf8
9a6ab99c
TC
4051 PREINIT:
4052 char const *text;
4053 STRLEN len;
faa9b3e7
TC
4054 CODE:
4055#ifdef SvUTF8
4056 if (SvUTF8(ST(7)))
4057 utf8 = 1;
4058#endif
9a6ab99c 4059 text = SvPV(text_sv, len);
faa9b3e7 4060 RETVAL = i_ft2_cp(font, im, tx, ty, channel, cheight, cwidth, text,
9a6ab99c 4061 len, align, aa, vlayout, 1);
faa9b3e7
TC
4062 OUTPUT:
4063 RETVAL
4064
4065void
4066ft2_transform_box(font, x0, x1, x2, x3)
4067 Imager::Font::FT2 font
4068 int x0
4069 int x1
4070 int x2
4071 int x3
4072 PREINIT:
4073 int box[4];
4074 PPCODE:
4075 box[0] = x0; box[1] = x1; box[2] = x2; box[3] = x3;
4076 ft2_transform_box(font, box);
4077 EXTEND(SP, 4);
4078 PUSHs(sv_2mortal(newSViv(box[0])));
4079 PUSHs(sv_2mortal(newSViv(box[1])));
4080 PUSHs(sv_2mortal(newSViv(box[2])));
4081 PUSHs(sv_2mortal(newSViv(box[3])));
3dec2c92
TC
4082
4083void
eeaa33fd 4084i_ft2_has_chars(handle, text_sv, utf8)
3dec2c92 4085 Imager::Font::FT2 handle
eeaa33fd 4086 SV *text_sv
3dec2c92
TC
4087 int utf8
4088 PREINIT:
4089 char *text;
4090 STRLEN len;
4091 char *work;
4092 int count;
4093 int i;
4094 PPCODE:
4095#ifdef SvUTF8
eeaa33fd 4096 if (SvUTF8(text_sv))
3dec2c92
TC
4097 utf8 = 1;
4098#endif
eeaa33fd 4099 text = SvPV(text_sv, len);
3dec2c92
TC
4100 work = mymalloc(len);
4101 count = i_ft2_has_chars(handle, text, len, utf8, work);
4102 if (GIMME_V == G_ARRAY) {
4103 EXTEND(SP, count);
4104 for (i = 0; i < count; ++i) {
4105 PUSHs(sv_2mortal(newSViv(work[i])));
4106 }
4107 }
4108 else {
4109 EXTEND(SP, 1);
4110 PUSHs(sv_2mortal(newSVpv(work, count)));
4111 }
4112 myfree(work);
4113
3799c4d1
TC
4114void
4115i_ft2_face_name(handle)
4116 Imager::Font::FT2 handle
4117 PREINIT:
4118 char name[255];
4119 int len;
4120 PPCODE:
4121 len = i_ft2_face_name(handle, name, sizeof(name));
4122 if (len) {
4123 EXTEND(SP, 1);
4124 PUSHs(sv_2mortal(newSVpv(name, 0)));
4125 }
4126
042cdaea
TC
4127undef_int
4128i_ft2_can_face_name()
4129
19fa4baf 4130void
a4168bea 4131i_ft2_glyph_name(handle, text_sv, utf8 = 0, reliable_only = 1)
3799c4d1
TC
4132 Imager::Font::FT2 handle
4133 SV *text_sv
4134 int utf8
a4168bea 4135 int reliable_only
3799c4d1
TC
4136 PREINIT:
4137 char const *text;
4138 STRLEN work_len;
4139 int len;
3799c4d1
TC
4140 char name[255];
4141 PPCODE:
4142#ifdef SvUTF8
4143 if (SvUTF8(text_sv))
4144 utf8 = 1;
4145#endif
4146 text = SvPV(text_sv, work_len);
4147 len = work_len;
4148 while (len) {
a4168bea 4149 unsigned long ch;
3799c4d1
TC
4150 if (utf8) {
4151 ch = i_utf8_advance(&text, &len);
4152 if (ch == ~0UL) {
4153 i_push_error(0, "invalid UTF8 character");
4154 break;
4155 }
4156 }
4157 else {
4158 ch = *text++;
4159 --len;
4160 }
4161 EXTEND(SP, 1);
f364e883
TC
4162 if (i_ft2_glyph_name(handle, ch, name, sizeof(name),
4163 reliable_only)) {
3799c4d1
TC
4164 PUSHs(sv_2mortal(newSVpv(name, 0)));
4165 }
4166 else {
4167 PUSHs(&PL_sv_undef);
4168 }
4169 }
4170
4171int
4172i_ft2_can_do_glyph_names()
4173
4174int
4175i_ft2_face_has_glyph_names(handle)
4176 Imager::Font::FT2 handle
4177
3e882362
TC
4178int
4179i_ft2_is_multiple_master(handle)
4180 Imager::Font::FT2 handle
4181
4182void
4183i_ft2_get_multiple_masters(handle)
4184 Imager::Font::FT2 handle
4185 PREINIT:
4186 i_font_mm mm;
4187 int i;
4188 PPCODE:
4189 if (i_ft2_get_multiple_masters(handle, &mm)) {
4190 EXTEND(SP, 2+mm.num_axis);
4191 PUSHs(sv_2mortal(newSViv(mm.num_axis)));
4192 PUSHs(sv_2mortal(newSViv(mm.num_designs)));