File Coverage

Imager.xs
Criterion Covered Total %
statement 1105 1360 81.2
branch 721 1344 53.6
condition n/a
subroutine n/a
pod n/a
total 1826 2704 67.5


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