handle failure to clone the log filehandle when cloning the Imager context
[imager.git] / FT2 / FT2.xs
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 #include "imext.h"
9 #include "imperl.h"
10 #include "imft2.h"
11
12 DEFINE_IMAGER_CALLBACKS;
13
14 MODULE = Imager::Font::FT2  PACKAGE = Imager::Font::FT2x     PREFIX=FT2_
15
16 #define FT2_DESTROY(font) i_ft2_destroy(font)
17
18 void
19 FT2_DESTROY(font)
20         Imager::Font::FT2x font
21
22 int
23 FT2_CLONE_SKIP(...)
24     CODE:
25         (void)items;
26         RETVAL = 1;
27     OUTPUT:
28         RETVAL
29
30 MODULE = Imager::Font::FT2  PACKAGE = Imager::Font::FT2
31
32 Imager::Font::FT2x
33 i_ft2_new(name, index)
34         char *name
35         int index
36
37 const char *
38 i_ft2_version(runtime)
39         int runtime
40     PREINIT:
41         char buf[100];
42     CODE:
43         if (!i_ft2_version(runtime, buf, sizeof(buf))) {
44           XSRETURN_EMPTY;
45         }
46         RETVAL = buf;
47     OUTPUT:
48         RETVAL
49
50 undef_int
51 i_ft2_setdpi(font, xdpi, ydpi)
52         Imager::Font::FT2x font
53         int xdpi
54         int ydpi
55
56 void
57 i_ft2_getdpi(font)
58         Imager::Font::FT2x font
59       PREINIT:
60         int xdpi, ydpi;
61       CODE:
62         if (i_ft2_getdpi(font, &xdpi, &ydpi)) {
63           EXTEND(SP, 2);
64           PUSHs(sv_2mortal(newSViv(xdpi)));
65           PUSHs(sv_2mortal(newSViv(ydpi)));
66         }
67
68 undef_int
69 i_ft2_sethinting(font, hinting)
70         Imager::Font::FT2x font
71         int hinting
72
73 undef_int
74 i_ft2_settransform(font, matrix)
75         Imager::Font::FT2x font
76       PREINIT:
77         double matrix[6];
78         int len;
79         AV *av;
80         SV *sv1;
81         int i;
82       CODE:
83         if (!SvROK(ST(1)) || SvTYPE(SvRV(ST(1))) != SVt_PVAV)
84           croak("i_ft2_settransform: parameter 2 must be an array ref\n");
85         av=(AV*)SvRV(ST(1));
86         len=av_len(av)+1;
87         if (len > 6)
88           len = 6;
89         for (i = 0; i < len; ++i) {
90           sv1=(*(av_fetch(av,i,0)));
91           matrix[i] = SvNV(sv1);
92         }
93         for (; i < 6; ++i)
94           matrix[i] = 0;
95         RETVAL = i_ft2_settransform(font, matrix);
96       OUTPUT:
97         RETVAL
98
99 void
100 i_ft2_bbox(font, cheight, cwidth, text_sv, utf8)
101         Imager::Font::FT2x font
102         double cheight
103         double cwidth
104         SV *text_sv
105         int utf8
106       PREINIT:
107         i_img_dim bbox[BOUNDING_BOX_COUNT];
108         int i;
109         char *text;
110         STRLEN text_len;
111         int rc;
112       PPCODE:
113         text = SvPV(text_sv, text_len);
114 #ifdef SvUTF8
115         if (SvUTF8(text_sv))
116           utf8 = 1;
117 #endif
118         rc = i_ft2_bbox(font, cheight, cwidth, text, text_len, bbox, utf8);
119         if (rc) {
120           EXTEND(SP, rc);
121           for (i = 0; i < rc; ++i)
122             PUSHs(sv_2mortal(newSViv(bbox[i])));
123         }
124
125 void
126 i_ft2_bbox_r(font, cheight, cwidth, text_sv, vlayout, utf8)
127         Imager::Font::FT2x font
128         double cheight
129         double cwidth
130         SV *text_sv
131         int vlayout
132         int utf8
133       PREINIT:
134         i_img_dim bbox[8];
135         int i;
136         const char *text;
137         STRLEN len;
138       PPCODE:
139         text = SvPV(text_sv, len);
140 #ifdef SvUTF8
141         if (SvUTF8(text_sv))
142           utf8 = 1;
143 #endif
144         if (i_ft2_bbox_r(font, cheight, cwidth, text, len, vlayout,
145                          utf8, bbox)) {
146           EXTEND(SP, 8);
147           for (i = 0; i < 8; ++i)
148             PUSHs(sv_2mortal(newSViv(bbox[i])));
149         }
150
151 undef_int
152 i_ft2_text(font, im, tx, ty, cl, cheight, cwidth, text_sv, align, aa, vlayout, utf8)
153         Imager::Font::FT2x font
154         Imager::ImgRaw im
155         i_img_dim tx
156         i_img_dim ty
157         Imager::Color cl
158         double cheight
159         double cwidth
160         SV *text_sv
161         int align
162         int aa
163         int vlayout
164         int utf8
165       PREINIT:
166         const char *text;
167         STRLEN len;
168       CODE:
169         text = SvPV(text_sv, len);
170 #ifdef SvUTF8
171         if (SvUTF8(text_sv)) {
172           utf8 = 1;
173         }
174 #endif
175         RETVAL = i_ft2_text(font, im, tx, ty, cl, cheight, cwidth, text,
176                             len, align, aa, vlayout, utf8);
177       OUTPUT:
178         RETVAL
179
180 undef_int
181 i_ft2_cp(font, im, tx, ty, channel, cheight, cwidth, text_sv, align, aa, vlayout, utf8)
182         Imager::Font::FT2x font
183         Imager::ImgRaw im
184         i_img_dim tx
185         i_img_dim ty
186         int channel
187         double cheight
188         double cwidth
189         SV *text_sv
190         int align
191         int aa
192         int vlayout
193         int utf8
194       PREINIT:
195         char const *text;
196         STRLEN len;
197       CODE:
198         text = SvPV(text_sv, len);
199 #ifdef SvUTF8
200         if (SvUTF8(text_sv))
201           utf8 = 1;
202 #endif
203         RETVAL = i_ft2_cp(font, im, tx, ty, channel, cheight, cwidth, text,
204                           len, align, aa, vlayout, utf8);
205       OUTPUT:
206         RETVAL
207
208 void
209 ft2_transform_box(font, x0, x1, x2, x3)
210         Imager::Font::FT2x font
211         i_img_dim x0
212         i_img_dim x1
213         i_img_dim x2
214         i_img_dim x3
215       PREINIT:
216         i_img_dim box[4];
217       PPCODE:
218         box[0] = x0; box[1] = x1; box[2] = x2; box[3] = x3;
219         ft2_transform_box(font, box);
220           EXTEND(SP, 4);
221           PUSHs(sv_2mortal(newSViv(box[0])));
222           PUSHs(sv_2mortal(newSViv(box[1])));
223           PUSHs(sv_2mortal(newSViv(box[2])));
224           PUSHs(sv_2mortal(newSViv(box[3])));
225
226 void
227 i_ft2_has_chars(handle, text_sv, utf8)
228         Imager::Font::FT2x handle
229         SV  *text_sv
230         int utf8
231       PREINIT:
232         char *text;
233         STRLEN len;
234         char *work;
235         size_t count;
236         size_t i;
237       PPCODE:
238         text = SvPV(text_sv, len);
239 #ifdef SvUTF8
240         if (SvUTF8(text_sv))
241           utf8 = 1;
242 #endif
243         work = mymalloc(len);
244         count = i_ft2_has_chars(handle, text, len, utf8, work);
245         if (GIMME_V == G_ARRAY) {
246           if (count) {
247             EXTEND(SP, count);
248             for (i = 0; i < count; ++i) {
249               PUSHs(boolSV(work[i]));
250             }
251           }
252         }
253         else {
254           EXTEND(SP, 1);
255           PUSHs(sv_2mortal(newSVpv(work, count)));
256         }
257         myfree(work);
258
259 void
260 i_ft2_face_name(handle)
261         Imager::Font::FT2x handle
262       PREINIT:
263         char name[255];
264         size_t len;
265       PPCODE:
266         len = i_ft2_face_name(handle, name, sizeof(name));
267         if (len) {
268           EXTEND(SP, 1);
269           PUSHs(sv_2mortal(newSVpv(name, 0)));
270         }
271
272 undef_int
273 i_ft2_can_face_name()
274
275 void
276 i_ft2_glyph_name(handle, text_sv, utf8 = 0, reliable_only = 1)
277         Imager::Font::FT2x handle
278         SV *text_sv
279         int utf8
280         int reliable_only
281       PREINIT:
282         char const *text;
283         STRLEN work_len;
284         size_t len;
285         char name[255];
286         SSize_t count = 0;
287       PPCODE:
288         i_clear_error();
289         text = SvPV(text_sv, work_len);
290         len = work_len;
291 #ifdef SvUTF8
292         if (SvUTF8(text_sv))
293           utf8 = 1;
294 #endif
295         while (len) {
296           unsigned long ch;
297           if (utf8) {
298             ch = i_utf8_advance(&text, &len);
299             if (ch == ~0UL) {
300               i_push_error(0, "invalid UTF8 character");
301               XSRETURN_EMPTY;
302             }
303           }
304           else {
305             ch = *text++;
306             --len;
307           }
308           EXTEND(SP, 1);
309           if (i_ft2_glyph_name(handle, ch, name, sizeof(name), 
310                                          reliable_only)) {
311             PUSHs(sv_2mortal(newSVpv(name, 0)));
312           }
313           else {
314             PUSHs(&PL_sv_undef);
315           }
316         }
317
318 int
319 i_ft2_can_do_glyph_names()
320
321 int
322 i_ft2_face_has_glyph_names(handle)
323         Imager::Font::FT2x handle
324
325 int
326 i_ft2_is_multiple_master(handle)
327         Imager::Font::FT2x handle
328
329 void
330 i_ft2_get_multiple_masters(handle)
331         Imager::Font::FT2x handle
332       PREINIT:
333         i_font_mm mm;
334         int i;
335       PPCODE:
336         if (i_ft2_get_multiple_masters(handle, &mm)) {
337           EXTEND(SP, 2+mm.num_axis);
338           PUSHs(sv_2mortal(newSViv(mm.num_axis)));
339           PUSHs(sv_2mortal(newSViv(mm.num_designs)));
340           for (i = 0; i < mm.num_axis; ++i) {
341             AV *av = newAV();
342             SV *sv;
343             av_extend(av, 3);
344             sv = newSVpv(mm.axis[i].name, strlen(mm.axis[i].name));
345             SvREFCNT_inc(sv);
346             av_store(av, 0, sv);
347             sv = newSViv(mm.axis[i].minimum);
348             SvREFCNT_inc(sv);
349             av_store(av, 1, sv);
350             sv = newSViv(mm.axis[i].maximum);
351             SvREFCNT_inc(sv);
352             av_store(av, 2, sv);
353             PUSHs(newRV_noinc((SV *)av));
354           }
355         }
356
357 undef_int
358 i_ft2_set_mm_coords(handle, ...)
359         Imager::Font::FT2x handle
360       PROTOTYPE: DISABLE
361       PREINIT:
362         long *coords;
363         int ix_coords, i;
364       CODE:
365         /* T_ARRAY handling by xsubpp seems to be busted in 5.6.1, so
366            transfer the array manually */
367         ix_coords = items-1;
368         coords = mymalloc(sizeof(long) * ix_coords);
369         for (i = 0; i < ix_coords; ++i) {
370           coords[i] = (long)SvIV(ST(1+i));
371         }
372         RETVAL = i_ft2_set_mm_coords(handle, ix_coords, coords);
373         myfree(coords);
374       OUTPUT:
375         RETVAL
376
377
378 BOOT:
379         PERL_INITIALIZE_IMAGER_CALLBACKS;
380         i_ft2_start();