File Coverage

xs/render.xs
Criterion Covered Total %
statement 9 86 10.4
branch 16 86 18.6
condition n/a
subroutine n/a
pod n/a
total 25 172 14.5


line stmt bran cond sub pod time code
1             MODULE = PDF::Make::Render PACKAGE = PDF::Make::Render PREFIX = pdfmake_render_
2              
3             PROTOTYPES: DISABLE
4              
5             #
6             # Constructor / Destructor
7             #
8              
9             PDF::Make::Render
10             pdfmake_render_new(class, width, height)
11             char *class
12             int width
13             int height
14             CODE:
15             PERL_UNUSED_VAR(class);
16 0           RETVAL = pdfmake_render_create(width, height);
17 0 0         if (!RETVAL) {
18 0           croak("Failed to create render context");
19             }
20             OUTPUT:
21             RETVAL
22              
23             void
24             pdfmake_render_DESTROY(ctx)
25             PDF::Make::Render ctx
26             CODE:
27 0           pdfmake_render_destroy(ctx);
28              
29             #
30             # Context Properties
31             #
32              
33             int
34             pdfmake_render_width(ctx)
35             PDF::Make::Render ctx
36             CODE:
37 0 0         RETVAL = ctx->width;
38             OUTPUT:
39             RETVAL
40              
41             int
42             pdfmake_render_height(ctx)
43             PDF::Make::Render ctx
44             CODE:
45 0 0         RETVAL = ctx->height;
46             OUTPUT:
47             RETVAL
48              
49             #
50             # Clear
51             #
52              
53             void
54             pdfmake_render_clear(ctx, r=1.0, g=1.0, b=1.0, a=1.0)
55             PDF::Make::Render ctx
56             double r
57             double g
58             double b
59             double a
60             CODE:
61 0           pdfmake_color_t color = {r, g, b, a};
62 0           pdfmake_render_clear(ctx, color);
63              
64             #
65             # Graphics State
66             #
67              
68             void
69             pdfmake_render_save(ctx)
70             PDF::Make::Render ctx
71             CODE:
72 0           pdfmake_render_err_t err = pdfmake_render_save(ctx);
73 0 0         if (err != PDFMAKE_RENDER_OK) {
74 0           croak("Failed to save graphics state: %d", err);
75             }
76              
77             void
78             pdfmake_render_restore(ctx)
79             PDF::Make::Render ctx
80             CODE:
81 0           pdfmake_render_err_t err = pdfmake_render_restore(ctx);
82 0 0         if (err != PDFMAKE_RENDER_OK) {
83 0           croak("Failed to restore graphics state: %d", err);
84             }
85              
86             #
87             # Colors
88             #
89              
90             void
91             pdfmake_render_set_fill_color(ctx, r, g, b, a=1.0)
92             PDF::Make::Render ctx
93             double r
94             double g
95             double b
96             double a
97             CODE:
98 0           pdfmake_render_set_fill_color(ctx, r, g, b, a);
99              
100             void
101             pdfmake_render_set_stroke_color(ctx, r, g, b, a=1.0)
102             PDF::Make::Render ctx
103             double r
104             double g
105             double b
106             double a
107             CODE:
108 0           pdfmake_render_set_stroke_color(ctx, r, g, b, a);
109              
110             #
111             # Stroke Style
112             #
113              
114             void
115             pdfmake_render_set_line_width(ctx, width)
116             PDF::Make::Render ctx
117             double width
118             CODE:
119 0           pdfmake_render_set_line_width(ctx, width);
120              
121             void
122             pdfmake_render_set_line_cap(ctx, cap)
123             PDF::Make::Render ctx
124             int cap
125             CODE:
126 0           pdfmake_render_set_line_cap(ctx, (pdfmake_line_cap_t)cap);
127              
128             void
129             pdfmake_render_set_line_join(ctx, join)
130             PDF::Make::Render ctx
131             int join
132             CODE:
133 0           pdfmake_render_set_line_join(ctx, (pdfmake_line_join_t)join);
134              
135             void
136             pdfmake_render_set_miter_limit(ctx, limit)
137             PDF::Make::Render ctx
138             double limit
139             CODE:
140 0           pdfmake_render_set_miter_limit(ctx, limit);
141              
142             void
143             pdfmake_render_set_dash(ctx, ...)
144             PDF::Make::Render ctx
145             PREINIT:
146 0           double *array = NULL;
147 0           size_t count = 0;
148 0           double phase = 0;
149             CODE:
150 0 0         if (items > 1) {
151             AV *dash_av;
152 0 0         if (SvROK(ST(1)) && SvTYPE(SvRV(ST(1))) == SVt_PVAV) {
    0          
153 0           dash_av = (AV*)SvRV(ST(1));
154 0           count = av_len(dash_av) + 1;
155 0 0         if (count > 0) {
156 0           array = malloc(count * sizeof(double));
157 0 0         for (size_t i = 0; i < count; i++) {
158 0           SV **elem = av_fetch(dash_av, i, 0);
159 0 0         array[i] = elem ? SvNV(*elem) : 0;
160             }
161             }
162             }
163 0 0         if (items > 2) {
164 0           phase = SvNV(ST(2));
165             }
166             }
167 0           pdfmake_render_set_dash(ctx, array, count, phase);
168 0 0         if (array) free(array);
169              
170             #
171             # Fill Rule
172             #
173              
174             void
175             pdfmake_render_set_fill_rule(ctx, rule)
176             PDF::Make::Render ctx
177             int rule
178             CODE:
179 0           pdfmake_render_set_fill_rule(ctx, (pdfmake_fill_rule_t)rule);
180              
181             #
182             # Transformations
183             #
184              
185             void
186             pdfmake_render_translate(ctx, tx, ty)
187             PDF::Make::Render ctx
188             double tx
189             double ty
190             CODE:
191 0           pdfmake_render_translate(ctx, tx, ty);
192              
193             void
194             pdfmake_render_scale(ctx, sx, sy)
195             PDF::Make::Render ctx
196             double sx
197             double sy
198             CODE:
199 0           pdfmake_render_scale(ctx, sx, sy);
200              
201             void
202             pdfmake_render_rotate(ctx, angle)
203             PDF::Make::Render ctx
204             double angle
205             CODE:
206 0           pdfmake_render_rotate(ctx, angle);
207              
208             void
209             pdfmake_render_set_matrix(ctx, a, b, c, d, e, f)
210             PDF::Make::Render ctx
211             double a
212             double b
213             double c
214             double d
215             double e
216             double f
217             CODE:
218 0           pdfmake_matrix_t m = {a, b, c, d, e, f};
219 0           pdfmake_render_set_matrix(ctx, &m);
220              
221             #
222             # Path Construction
223             #
224              
225             void
226             pdfmake_render_move_to(ctx, x, y)
227             PDF::Make::Render ctx
228             double x
229             double y
230             CODE:
231 0           pdfmake_render_move_to(ctx, x, y);
232              
233             void
234             pdfmake_render_line_to(ctx, x, y)
235             PDF::Make::Render ctx
236             double x
237             double y
238             CODE:
239 0           pdfmake_render_line_to(ctx, x, y);
240              
241             void
242             pdfmake_render_curve_to(ctx, x1, y1, x2, y2, x3, y3)
243             PDF::Make::Render ctx
244             double x1
245             double y1
246             double x2
247             double y2
248             double x3
249             double y3
250             CODE:
251 0           pdfmake_render_curve_to(ctx, x1, y1, x2, y2, x3, y3);
252              
253             void
254             pdfmake_render_close_path(ctx)
255             PDF::Make::Render ctx
256             CODE:
257 0           pdfmake_render_close_path(ctx);
258              
259             void
260             pdfmake_render_rect(ctx, x, y, w, h)
261             PDF::Make::Render ctx
262             double x
263             double y
264             double w
265             double h
266             CODE:
267 0           pdfmake_render_rect(ctx, x, y, w, h);
268              
269             void
270             pdfmake_render_new_path(ctx)
271             PDF::Make::Render ctx
272             CODE:
273 0           pdfmake_render_new_path(ctx);
274              
275             #
276             # Path Painting
277             #
278              
279             void
280             pdfmake_render_fill(ctx)
281             PDF::Make::Render ctx
282             CODE:
283 0           pdfmake_render_err_t err = pdfmake_render_fill(ctx);
284 0 0         if (err != PDFMAKE_RENDER_OK && err != PDFMAKE_RENDER_ERR_EMPTY_PATH) {
    0          
285 0           croak("Fill failed: %d", err);
286             }
287              
288             void
289             pdfmake_render_stroke(ctx)
290             PDF::Make::Render ctx
291             CODE:
292 0           pdfmake_render_err_t err = pdfmake_render_stroke(ctx);
293 0 0         if (err != PDFMAKE_RENDER_OK && err != PDFMAKE_RENDER_ERR_EMPTY_PATH) {
    0          
294 0           croak("Stroke failed: %d", err);
295             }
296              
297             void
298             pdfmake_render_fill_stroke(ctx)
299             PDF::Make::Render ctx
300             CODE:
301 0           pdfmake_render_fill_preserve(ctx);
302 0           pdfmake_render_stroke(ctx);
303              
304             #
305             # Clipping
306             #
307              
308             void
309             pdfmake_render_clip(ctx)
310             PDF::Make::Render ctx
311             CODE:
312 0           pdfmake_render_err_t err = pdfmake_render_clip(ctx);
313 0 0         if (err != PDFMAKE_RENDER_OK && err != PDFMAKE_RENDER_ERR_EMPTY_PATH) {
    0          
314 0           croak("Clip failed: %d", err);
315             }
316              
317             void
318             pdfmake_render_reset_clip(ctx)
319             PDF::Make::Render ctx
320             CODE:
321 0           pdfmake_render_reset_clip(ctx);
322              
323             #
324             # Pixel Access
325             #
326              
327             SV *
328             pdfmake_render_get_pixel(ctx, x, y)
329             PDF::Make::Render ctx
330             int x
331             int y
332             CODE:
333 0           uint32_t packed = pdfmake_render_get_pixel(ctx, x, y);
334 0           HV *hv = newHV();
335 0           hv_store(hv, "r", 1, newSViv((packed >> 16) & 0xFF), 0);
336 0           hv_store(hv, "g", 1, newSViv((packed >> 8) & 0xFF), 0);
337 0           hv_store(hv, "b", 1, newSViv(packed & 0xFF), 0);
338 0           hv_store(hv, "a", 1, newSViv((packed >> 24) & 0xFF), 0);
339 0           RETVAL = newRV_noinc((SV*)hv);
340             OUTPUT:
341             RETVAL
342              
343             SV *
344             pdfmake_render_get_pixels(ctx)
345             PDF::Make::Render ctx
346             CODE:
347 0           size_t size = ctx->width * ctx->height * 4;
348 0           RETVAL = newSVpvn((char*)ctx->pixels, size);
349             OUTPUT:
350             RETVAL
351              
352             #
353             # Constants
354             #
355              
356             int
357             CAP_BUTT()
358             CODE:
359 0 0         RETVAL = PDFMAKE_CAP_BUTT;
360             OUTPUT:
361             RETVAL
362              
363             int
364             CAP_ROUND()
365             CODE:
366 0 0         RETVAL = PDFMAKE_CAP_ROUND;
367             OUTPUT:
368             RETVAL
369              
370             int
371             CAP_SQUARE()
372             CODE:
373 0 0         RETVAL = PDFMAKE_CAP_SQUARE;
374             OUTPUT:
375             RETVAL
376              
377             int
378             JOIN_MITER()
379             CODE:
380 0 0         RETVAL = PDFMAKE_JOIN_MITER;
381             OUTPUT:
382             RETVAL
383              
384             int
385             JOIN_ROUND()
386             CODE:
387 0 0         RETVAL = PDFMAKE_JOIN_ROUND;
388             OUTPUT:
389             RETVAL
390              
391             int
392             JOIN_BEVEL()
393             CODE:
394 0 0         RETVAL = PDFMAKE_JOIN_BEVEL;
395             OUTPUT:
396             RETVAL
397              
398             int
399             FILL_NONZERO()
400             CODE:
401 0 0         RETVAL = PDFMAKE_FILL_NONZERO;
402             OUTPUT:
403             RETVAL
404              
405             int
406             FILL_EVENODD()
407             CODE:
408 0 0         RETVAL = PDFMAKE_FILL_EVENODD;
409             OUTPUT:
410             RETVAL
411              
412             BOOT:
413             {
414 90           HV *stash = gv_stashpv("PDF::Make::Render", GV_ADD);
415 90 50         PDFMAKE_REGISTER_CONST(stash, "CAP_BUTT", PDFMAKE_CAP_BUTT);
    50          
416 90 50         PDFMAKE_REGISTER_CONST(stash, "CAP_ROUND", PDFMAKE_CAP_ROUND);
    50          
417 90 50         PDFMAKE_REGISTER_CONST(stash, "CAP_SQUARE", PDFMAKE_CAP_SQUARE);
    50          
418 90 50         PDFMAKE_REGISTER_CONST(stash, "JOIN_MITER", PDFMAKE_JOIN_MITER);
    50          
419 90 50         PDFMAKE_REGISTER_CONST(stash, "JOIN_ROUND", PDFMAKE_JOIN_ROUND);
    50          
420 90 50         PDFMAKE_REGISTER_CONST(stash, "JOIN_BEVEL", PDFMAKE_JOIN_BEVEL);
    50          
421 90 50         PDFMAKE_REGISTER_CONST(stash, "FILL_NONZERO", PDFMAKE_FILL_NONZERO);
    50          
422 90 50         PDFMAKE_REGISTER_CONST(stash, "FILL_EVENODD", PDFMAKE_FILL_EVENODD);
    50          
423              
424             /* TODO: Render dispatch table — pending header conflict fix
425             * The pdfmake_render.h has enum/struct redefinitions when
426             * compiled as part of Make.xs. Enable once headers are fixed.
427             */
428             #if 0
429             enum {
430             ROP_SAVE, ROP_RESTORE,
431             ROP_SET_LINE_WIDTH, ROP_SET_LINE_CAP, ROP_SET_LINE_JOIN,
432             ROP_SET_MITER_LIMIT, ROP_SET_FILL_RULE,
433             ROP_TRANSLATE, ROP_SCALE, ROP_ROTATE,
434             ROP_MOVE_TO, ROP_LINE_TO, ROP_CLOSE_PATH,
435             ROP_RECT, ROP_NEW_PATH,
436             ROP_SET_MATRIX, ROP_CURVE_TO,
437             ROP_COUNT
438             };
439             static pdfmake_chain_entry_t render_dispatch[ROP_COUNT] = {
440             [ROP_SAVE] = { (void*)pdfmake_render_save, 0, {}, .ret_mode=2 },
441             [ROP_RESTORE] = { (void*)pdfmake_render_restore, 0, {}, .ret_mode=2 },
442             [ROP_SET_LINE_WIDTH] = { (void*)pdfmake_render_set_line_width, 1, {PDFMAKE_ARG_DOUBLE}, .ret_mode=2 },
443             [ROP_SET_LINE_CAP] = { (void*)pdfmake_render_set_line_cap, 1, {PDFMAKE_ARG_INT}, .ret_mode=2 },
444             [ROP_SET_LINE_JOIN] = { (void*)pdfmake_render_set_line_join, 1, {PDFMAKE_ARG_INT}, .ret_mode=2 },
445             [ROP_SET_MITER_LIMIT]= { (void*)pdfmake_render_set_miter_limit,1, {PDFMAKE_ARG_DOUBLE}, .ret_mode=2 },
446             [ROP_SET_FILL_RULE] = { (void*)pdfmake_render_set_fill_rule, 1, {PDFMAKE_ARG_INT}, .ret_mode=2 },
447             [ROP_TRANSLATE] = { (void*)pdfmake_render_translate, 2, {PDFMAKE_ARG_DOUBLE, PDFMAKE_ARG_DOUBLE}, .ret_mode=2 },
448             [ROP_SCALE] = { (void*)pdfmake_render_scale, 2, {PDFMAKE_ARG_DOUBLE, PDFMAKE_ARG_DOUBLE}, .ret_mode=2 },
449             [ROP_ROTATE] = { (void*)pdfmake_render_rotate, 1, {PDFMAKE_ARG_DOUBLE}, .ret_mode=2 },
450             [ROP_MOVE_TO] = { (void*)pdfmake_render_move_to, 2, {PDFMAKE_ARG_DOUBLE, PDFMAKE_ARG_DOUBLE}, .ret_mode=2 },
451             [ROP_LINE_TO] = { (void*)pdfmake_render_line_to, 2, {PDFMAKE_ARG_DOUBLE, PDFMAKE_ARG_DOUBLE}, .ret_mode=2 },
452             [ROP_CLOSE_PATH] = { (void*)pdfmake_render_close_path, 0, {}, .ret_mode=2 },
453             [ROP_RECT] = { (void*)pdfmake_render_rect, 4, {PDFMAKE_ARG_DOUBLE, PDFMAKE_ARG_DOUBLE, PDFMAKE_ARG_DOUBLE, PDFMAKE_ARG_DOUBLE}, .ret_mode=2 },
454             [ROP_NEW_PATH] = { (void*)pdfmake_render_new_path, 0, {}, .ret_mode=2 },
455             [ROP_SET_MATRIX] = { (void*)pdfmake_render_set_matrix, 6, {PDFMAKE_ARG_DOUBLE, PDFMAKE_ARG_DOUBLE, PDFMAKE_ARG_DOUBLE, PDFMAKE_ARG_DOUBLE, PDFMAKE_ARG_DOUBLE, PDFMAKE_ARG_DOUBLE}, .ret_mode=2 },
456             [ROP_CURVE_TO] = { (void*)pdfmake_render_curve_to, 6, {PDFMAKE_ARG_DOUBLE, PDFMAKE_ARG_DOUBLE, PDFMAKE_ARG_DOUBLE, PDFMAKE_ARG_DOUBLE, PDFMAKE_ARG_DOUBLE, PDFMAKE_ARG_DOUBLE}, .ret_mode=2 },
457             };
458             int render_table_id = pdfmake_chain_table_count++;
459             pdfmake_chain_tables[render_table_id] = render_dispatch;
460              
461             /* Method names after PREFIX strip: pdfmake_render_save -> save */
462             struct { const char *name; int idx; } render_methods[] = {
463             {"save", ROP_SAVE},
464             {"restore", ROP_RESTORE},
465             {"set_line_width", ROP_SET_LINE_WIDTH},
466             {"set_line_cap", ROP_SET_LINE_CAP},
467             {"set_line_join", ROP_SET_LINE_JOIN},
468             {"set_miter_limit", ROP_SET_MITER_LIMIT},
469             {"set_fill_rule", ROP_SET_FILL_RULE},
470             {"translate", ROP_TRANSLATE},
471             {"scale", ROP_SCALE},
472             {"rotate", ROP_ROTATE},
473             {"move_to", ROP_MOVE_TO},
474             {"line_to", ROP_LINE_TO},
475             {"close_path", ROP_CLOSE_PATH},
476             {"rect", ROP_RECT},
477             {"new_path", ROP_NEW_PATH},
478             {"set_matrix", ROP_SET_MATRIX},
479             {"curve_to", ROP_CURVE_TO},
480             {NULL, 0}
481             };
482             int ri;
483             for (ri = 0; render_methods[ri].name; ri++) {
484             PDFMAKE_REGISTER_CHAIN(stash, render_methods[ri].name,
485             render_table_id, render_methods[ri].idx);
486             }
487             #endif
488             }