File Coverage

xs/font.xs
Criterion Covered Total %
statement 72 137 52.5
branch 55 162 33.9
condition n/a
subroutine n/a
pod n/a
total 127 299 42.4


line stmt bran cond sub pod time code
1             MODULE = PDF::Make PACKAGE = PDF::Make::Font
2             PROTOTYPES: ENABLE
3              
4             # ============================================================================
5             # Constructors
6             # ============================================================================
7              
8             SV *
9             standard14(class, base_font, ...)
10             char *class
11             const char *base_font
12             PREINIT:
13 93           pdfmake_arena_t *arena = NULL;
14             pdfmake_font_t *font;
15 93           SV *arena_sv = NULL;
16             CODE:
17             PERL_UNUSED_VAR(class);
18            
19             /* Optional arena parameter */
20 93 100         if (items > 2 && SvOK(ST(2))) {
    100          
21 18 50         if (sv_isobject(ST(2)) && sv_derived_from(ST(2), "PDF::Make::Arena")) {
    50          
22 18           pdfmake_arena_xs_t *arena_xs = INT2PTR(pdfmake_arena_xs_t *, SvIV(SvRV(ST(2))));
23 18           arena = arena_xs->arena;
24 18           arena_sv = ST(2);
25             }
26             }
27            
28             /* Create arena if not provided */
29 93 100         if (!arena) {
30 75           arena = pdfmake_arena_new();
31 75 50         if (!arena)
32 0           croak("PDF::Make::Font: failed to allocate arena");
33             }
34            
35 93           font = pdfmake_font_standard14(arena, base_font);
36 93 100         if (!font)
37 1           croak("PDF::Make::Font: unknown standard font '%s'", base_font);
38            
39 92           RETVAL = sv_newmortal();
40 92           sv_setref_pv(RETVAL, "PDF::Make::Font", (void *)font);
41 92           SvREFCNT_inc(RETVAL);
42             OUTPUT:
43             RETVAL
44              
45             SV *
46             from_file(class, path, ...)
47             char *class
48             const char *path
49             PREINIT:
50             FILE *fp;
51             long file_len;
52             uint8_t *buf;
53             size_t nread;
54 0           pdfmake_arena_t *arena = NULL;
55             pdfmake_font_t *font;
56 0           SV *arena_sv = NULL;
57             CODE:
58             PERL_UNUSED_VAR(class);
59            
60             /* Optional arena parameter */
61 0 0         if (items > 2 && SvOK(ST(2))) {
    0          
62 0 0         if (sv_isobject(ST(2)) && sv_derived_from(ST(2), "PDF::Make::Arena")) {
    0          
63 0           pdfmake_arena_xs_t *arena_xs = INT2PTR(pdfmake_arena_xs_t *, SvIV(SvRV(ST(2))));
64 0           arena = arena_xs->arena;
65 0           arena_sv = ST(2);
66             }
67             }
68            
69             /* Create arena if not provided */
70 0 0         if (!arena) {
71 0           arena = pdfmake_arena_new();
72 0 0         if (!arena)
73 0           croak("PDF::Make::Font: failed to allocate arena");
74             }
75            
76 0           fp = fopen(path, "rb");
77 0 0         if (!fp)
78 0           croak("PDF::Make::Font: cannot open '%s'", path);
79            
80 0 0         if (fseek(fp, 0, SEEK_END) != 0) { fclose(fp); croak("PDF::Make::Font: seek failed"); }
81 0           file_len = ftell(fp);
82 0 0         if (file_len < 0) { fclose(fp); croak("PDF::Make::Font: tell failed"); }
83 0           rewind(fp);
84            
85 0           buf = malloc((size_t)file_len);
86 0 0         if (!buf) { fclose(fp); croak("PDF::Make::Font: malloc failed"); }
87            
88 0           nread = fread(buf, 1, (size_t)file_len, fp);
89 0           fclose(fp);
90 0 0         if ((long)nread != file_len) { free(buf); croak("PDF::Make::Font: short read"); }
91            
92 0           font = pdfmake_font_from_ttf(arena, buf, (size_t)file_len);
93 0           free(buf);
94 0 0         if (!font)
95 0           croak("PDF::Make::Font: failed to parse TTF '%s'", path);
96            
97 0           RETVAL = sv_newmortal();
98 0           sv_setref_pv(RETVAL, "PDF::Make::Font", (void *)font);
99 0           SvREFCNT_inc(RETVAL);
100             OUTPUT:
101             RETVAL
102              
103             SV *
104             from_bytes(class, bytes_sv, ...)
105             char *class
106             SV *bytes_sv
107             PREINIT:
108             STRLEN len;
109             const uint8_t *buf;
110 0           pdfmake_arena_t *arena = NULL;
111             pdfmake_font_t *font;
112 0           SV *arena_sv = NULL;
113             CODE:
114             PERL_UNUSED_VAR(class);
115            
116             /* Optional arena parameter */
117 0 0         if (items > 2 && SvOK(ST(2))) {
    0          
118 0 0         if (sv_isobject(ST(2)) && sv_derived_from(ST(2), "PDF::Make::Arena")) {
    0          
119 0           pdfmake_arena_xs_t *arena_xs = INT2PTR(pdfmake_arena_xs_t *, SvIV(SvRV(ST(2))));
120 0           arena = arena_xs->arena;
121 0           arena_sv = ST(2);
122             }
123             }
124            
125             /* Create arena if not provided */
126 0 0         if (!arena) {
127 0           arena = pdfmake_arena_new();
128 0 0         if (!arena)
129 0           croak("PDF::Make::Font: failed to allocate arena");
130             }
131            
132 0           buf = (const uint8_t *)SvPV(bytes_sv, len);
133 0           font = pdfmake_font_from_ttf(arena, buf, len);
134 0 0         if (!font)
135 0           croak("PDF::Make::Font: failed to parse TTF bytes");
136            
137 0           RETVAL = sv_newmortal();
138 0           sv_setref_pv(RETVAL, "PDF::Make::Font", (void *)font);
139 0           SvREFCNT_inc(RETVAL);
140             OUTPUT:
141             RETVAL
142              
143             # ============================================================================
144             # Accessors
145             # ============================================================================
146              
147             const char *
148             base_font(self)
149             pdfmake_font_t *self
150             CODE:
151 30           RETVAL = self->base_font;
152             OUTPUT:
153             RETVAL
154              
155             IV
156             type(self)
157             pdfmake_font_t *self
158             CODE:
159 30 100         RETVAL = (IV)self->type;
160             OUTPUT:
161             RETVAL
162              
163             IV
164             std14_id(self)
165             pdfmake_font_t *self
166             CODE:
167 1 50         if (self->type != PDFMAKE_FONT_TYPE1)
168 0           croak("PDF::Make::Font::std14_id: not a Standard 14 font");
169 1 50         RETVAL = (IV)self->std14_id;
170             OUTPUT:
171             RETVAL
172              
173             # ============================================================================
174             # Metrics
175             # ============================================================================
176              
177             NV
178             advance(self, codepoint, font_size)
179             pdfmake_font_t *self
180             UV codepoint
181             NV font_size
182             CODE:
183 19           RETVAL = pdfmake_font_advance(self, (uint32_t)codepoint, font_size);
184             OUTPUT:
185             RETVAL
186              
187             NV
188             string_width(self, utf8_sv, font_size)
189             pdfmake_font_t *self
190             SV *utf8_sv
191             NV font_size
192             PREINIT:
193             STRLEN len;
194             const char *utf8;
195             CODE:
196 15506           utf8 = SvPV(utf8_sv, len);
197 15506           RETVAL = pdfmake_font_string_width(self, utf8, len, font_size);
198             OUTPUT:
199             RETVAL
200              
201             SV *
202             metrics(self)
203             pdfmake_font_t *self
204             PREINIT:
205             const pdfmake_font_metrics_t *m;
206             HV *hv;
207             AV *bbox;
208             CODE:
209 8           m = pdfmake_font_metrics(self);
210 8           hv = newHV();
211 8           hv_store(hv, "ascent", 6, newSViv(m->ascent), 0);
212 8           hv_store(hv, "descent", 7, newSViv(m->descent), 0);
213 8           hv_store(hv, "cap_height", 10, newSViv(m->cap_height), 0);
214 8           hv_store(hv, "x_height", 8, newSViv(m->x_height), 0);
215 8           hv_store(hv, "stem_v", 6, newSViv(m->stem_v), 0);
216 8           hv_store(hv, "stem_h", 6, newSViv(m->stem_h), 0);
217 8           hv_store(hv, "italic_angle", 12, newSViv(m->italic_angle), 0);
218 8           hv_store(hv, "flags", 5, newSVuv(m->flags), 0);
219              
220 8           bbox = newAV();
221 8           av_push(bbox, newSViv(m->bbox[0]));
222 8           av_push(bbox, newSViv(m->bbox[1]));
223 8           av_push(bbox, newSViv(m->bbox[2]));
224 8           av_push(bbox, newSViv(m->bbox[3]));
225 8           hv_store(hv, "bbox", 4, newRV_noinc((SV *)bbox), 0);
226              
227 8           RETVAL = newRV_noinc((SV *)hv);
228             OUTPUT:
229             RETVAL
230              
231             # ============================================================================
232             # Encoding
233             # ============================================================================
234              
235             SV *
236             encode_utf8(self, utf8_sv)
237             pdfmake_font_t *self
238             SV *utf8_sv
239             PREINIT:
240             STRLEN len;
241             const char *utf8;
242             pdfmake_buf_t buf;
243             pdfmake_err_t err;
244             CODE:
245 1           utf8 = SvPV(utf8_sv, len);
246 1           pdfmake_buf_init(&buf);
247 1           err = pdfmake_font_encode_utf8(self, utf8, len, &buf);
248 1 50         if (err != PDFMAKE_OK) {
249 0           pdfmake_buf_free(&buf);
250 0           croak("PDF::Make::Font::encode_utf8: encoding failed");
251             }
252 1           RETVAL = newSVpvn((const char *)buf.data, buf.len);
253 1           pdfmake_buf_free(&buf);
254             OUTPUT:
255             RETVAL
256              
257             # ============================================================================
258             # PDF output
259             # ============================================================================
260              
261             UV
262             write_to_doc(self, doc)
263             pdfmake_font_t *self
264             pdfmake_doc_t *doc
265             PREINIT:
266             pdfmake_ref_t ref;
267             CODE:
268 0           ref = pdfmake_font_write(self, doc);
269 0 0         if (ref.num == 0 && ref.gen == 0)
    0          
270 0           croak("PDF::Make::Font: failed to write font to document");
271 0 0         RETVAL = ref.num;
272             OUTPUT:
273             RETVAL
274              
275             # ============================================================================
276             # Cleanup
277             # ============================================================================
278              
279             void
280             DESTROY(self)
281             pdfmake_font_t *self
282             CODE:
283 92           pdfmake_font_free(self);
284              
285              
286             MODULE = PDF::Make PACKAGE = PDF::Make::Font::Std14
287             PROTOTYPES: ENABLE
288              
289             # ============================================================================
290             # Standard 14 font constants and utilities
291             # ============================================================================
292              
293             IV
294             HELVETICA()
295             CODE:
296 4 50         RETVAL = PDFMAKE_STD14_HELVETICA;
297             OUTPUT:
298             RETVAL
299              
300             IV
301             HELVETICA_BOLD()
302             CODE:
303 0 0         RETVAL = PDFMAKE_STD14_HELVETICA_BOLD;
304             OUTPUT:
305             RETVAL
306              
307             IV
308             HELVETICA_OBLIQUE()
309             CODE:
310 0 0         RETVAL = PDFMAKE_STD14_HELVETICA_OBLIQUE;
311             OUTPUT:
312             RETVAL
313              
314             IV
315             HELVETICA_BOLDOBLIQUE()
316             CODE:
317 0 0         RETVAL = PDFMAKE_STD14_HELVETICA_BOLDOBLIQUE;
318             OUTPUT:
319             RETVAL
320              
321             IV
322             TIMES_ROMAN()
323             CODE:
324 1 50         RETVAL = PDFMAKE_STD14_TIMES_ROMAN;
325             OUTPUT:
326             RETVAL
327              
328             IV
329             TIMES_BOLD()
330             CODE:
331 0 0         RETVAL = PDFMAKE_STD14_TIMES_BOLD;
332             OUTPUT:
333             RETVAL
334              
335             IV
336             TIMES_ITALIC()
337             CODE:
338 0 0         RETVAL = PDFMAKE_STD14_TIMES_ITALIC;
339             OUTPUT:
340             RETVAL
341              
342             IV
343             TIMES_BOLDITALIC()
344             CODE:
345 0 0         RETVAL = PDFMAKE_STD14_TIMES_BOLDITALIC;
346             OUTPUT:
347             RETVAL
348              
349             IV
350             COURIER()
351             CODE:
352 1 50         RETVAL = PDFMAKE_STD14_COURIER;
353             OUTPUT:
354             RETVAL
355              
356             IV
357             COURIER_BOLD()
358             CODE:
359 0 0         RETVAL = PDFMAKE_STD14_COURIER_BOLD;
360             OUTPUT:
361             RETVAL
362              
363             IV
364             COURIER_OBLIQUE()
365             CODE:
366 0 0         RETVAL = PDFMAKE_STD14_COURIER_OBLIQUE;
367             OUTPUT:
368             RETVAL
369              
370             IV
371             COURIER_BOLDOBLIQUE()
372             CODE:
373 0 0         RETVAL = PDFMAKE_STD14_COURIER_BOLDOBLIQUE;
374             OUTPUT:
375             RETVAL
376              
377             IV
378             SYMBOL()
379             CODE:
380 1 50         RETVAL = PDFMAKE_STD14_SYMBOL;
381             OUTPUT:
382             RETVAL
383              
384             IV
385             ZAPFDINGBATS()
386             CODE:
387 1 50         RETVAL = PDFMAKE_STD14_ZAPFDINGBATS;
388             OUTPUT:
389             RETVAL
390              
391             IV
392             lookup(class, name)
393             char *class
394             const char *name
395             CODE:
396             PERL_UNUSED_VAR(class);
397 4 50         RETVAL = pdfmake_std14_lookup(name);
398             OUTPUT:
399             RETVAL
400              
401             IV
402             width(class, font_id, codepoint)
403             char *class
404             IV font_id
405             UV codepoint
406             CODE:
407             PERL_UNUSED_VAR(class);
408 2 50         RETVAL = pdfmake_std14_width((pdfmake_std14_id_t)font_id, (uint32_t)codepoint);
409             OUTPUT:
410             RETVAL
411              
412             BOOT:
413             {
414 90           HV *stash = gv_stashpv("PDF::Make::Font", GV_ADD);
415 90 50         PDFMAKE_REGISTER_GETTER(stash, "base_font", pdfmake_font_t, base_font, PDFMAKE_FIELD_STRING);
    50          
416 90 50         PDFMAKE_REGISTER_GETTER(stash, "type", pdfmake_font_t, type, PDFMAKE_FIELD_INT);
    50          
417              
418             /* Standard 14 font constants (defined in Font::Std14, exported by Page) */
419 90           HV *std14 = gv_stashpv("PDF::Make::Font::Std14", GV_ADD);
420 90 50         PDFMAKE_REGISTER_CONST(std14, "HELVETICA", PDFMAKE_STD14_HELVETICA);
    50          
421 90 50         PDFMAKE_REGISTER_CONST(std14, "HELVETICA_BOLD", PDFMAKE_STD14_HELVETICA_BOLD);
    50          
422 90 50         PDFMAKE_REGISTER_CONST(std14, "HELVETICA_OBLIQUE", PDFMAKE_STD14_HELVETICA_OBLIQUE);
    50          
423 90 50         PDFMAKE_REGISTER_CONST(std14, "HELVETICA_BOLDOBLIQUE", PDFMAKE_STD14_HELVETICA_BOLDOBLIQUE);
    50          
424 90 50         PDFMAKE_REGISTER_CONST(std14, "TIMES_ROMAN", PDFMAKE_STD14_TIMES_ROMAN);
    50          
425 90 50         PDFMAKE_REGISTER_CONST(std14, "TIMES_BOLD", PDFMAKE_STD14_TIMES_BOLD);
    50          
426 90 50         PDFMAKE_REGISTER_CONST(std14, "TIMES_ITALIC", PDFMAKE_STD14_TIMES_ITALIC);
    50          
427 90 50         PDFMAKE_REGISTER_CONST(std14, "TIMES_BOLDITALIC", PDFMAKE_STD14_TIMES_BOLDITALIC);
    50          
428 90 50         PDFMAKE_REGISTER_CONST(std14, "COURIER", PDFMAKE_STD14_COURIER);
    50          
429 90 50         PDFMAKE_REGISTER_CONST(std14, "COURIER_BOLD", PDFMAKE_STD14_COURIER_BOLD);
    50          
430 90 50         PDFMAKE_REGISTER_CONST(std14, "COURIER_OBLIQUE", PDFMAKE_STD14_COURIER_OBLIQUE);
    50          
431 90 50         PDFMAKE_REGISTER_CONST(std14, "COURIER_BOLDOBLIQUE", PDFMAKE_STD14_COURIER_BOLDOBLIQUE);
    50          
432 90 50         PDFMAKE_REGISTER_CONST(std14, "SYMBOL", PDFMAKE_STD14_SYMBOL);
    50          
433 90 50         PDFMAKE_REGISTER_CONST(std14, "ZAPFDINGBATS", PDFMAKE_STD14_ZAPFDINGBATS);
    50          
434             }