Branch data Line data Source code
1 : : /* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
2 : : // SPDX-License-Identifier: MIT OR LGPL-2.0-or-later
3 : : // SPDX-FileCopyrightText: 2010 litl, LLC.
4 : :
5 : : #include <config.h>
6 : :
7 : : #include <stddef.h> // for size_t
8 : :
9 : : #include <memory>
10 : :
11 : : #include <cairo.h>
12 : : #include <girepository.h>
13 : : #include <glib.h>
14 : :
15 : : #include <js/Array.h> // for JS::NewArrayObject
16 : : #include <js/CallArgs.h>
17 : : #include <js/Conversions.h>
18 : : #include <js/PropertyAndElement.h>
19 : : #include <js/PropertyDescriptor.h> // for JSPROP_READONLY
20 : : #include <js/PropertySpec.h>
21 : : #include <js/RootingAPI.h>
22 : : #include <js/TypeDecls.h>
23 : : #include <js/Utility.h> // for UniqueChars
24 : : #include <js/Value.h>
25 : : #include <jsapi.h> // for JS_NewPlainObject
26 : :
27 : : #include "gi/arg-inl.h"
28 : : #include "gi/arg.h"
29 : : #include "gi/foreign.h"
30 : : #include "gjs/auto.h"
31 : : #include "gjs/enum-utils.h"
32 : : #include "gjs/jsapi-util-args.h"
33 : : #include "gjs/jsapi-util.h"
34 : : #include "gjs/macros.h"
35 : : #include "modules/cairo-private.h"
36 : :
37 : : #define _GJS_CAIRO_CONTEXT_GET_PRIV_CR_CHECKED(cx, argc, vp, argv, obj) \
38 : : GJS_GET_THIS(cx, argc, vp, argv, obj); \
39 : : cairo_t* cr; \
40 : : if (!CairoContext::for_js_typecheck(cx, obj, &cr, &argv)) \
41 : : return false; \
42 : : if (!cr) \
43 : : return true;
44 : :
45 : : #define _GJS_CAIRO_CONTEXT_DEFINE_FUNC_BEGIN(mname) \
46 : : GJS_JSAPI_RETURN_CONVENTION \
47 : : static bool mname##_func(JSContext* context, unsigned argc, \
48 : : JS::Value* vp) { \
49 : : _GJS_CAIRO_CONTEXT_GET_PRIV_CR_CHECKED(context, argc, vp, argv, obj)
50 : :
51 : : #define _GJS_CAIRO_CONTEXT_DEFINE_FUNC_END \
52 : : return gjs_cairo_check_status(context, cairo_status(cr), "context"); \
53 : : }
54 : :
55 : : #define _GJS_CAIRO_CONTEXT_CHECK_NO_ARGS(m) \
56 : : if (argc > 0) { \
57 : : gjs_throw(context, "Context." #m "() takes no arguments"); \
58 : : return false; \
59 : : }
60 : :
61 : : #define _GJS_CAIRO_CONTEXT_DEFINE_FUNC0(method, cfunc) \
62 : : _GJS_CAIRO_CONTEXT_DEFINE_FUNC_BEGIN(method) \
63 : : cfunc(cr); \
64 : : argv.rval().setUndefined(); \
65 : : _GJS_CAIRO_CONTEXT_DEFINE_FUNC_END
66 : :
67 : : #define _GJS_CAIRO_CONTEXT_DEFINE_FUNC0I(method, cfunc) \
68 : : _GJS_CAIRO_CONTEXT_DEFINE_FUNC_BEGIN(method) \
69 : : int ret; \
70 : : _GJS_CAIRO_CONTEXT_CHECK_NO_ARGS(method) \
71 : : ret = (int)cfunc(cr); \
72 : : argv.rval().setInt32(ret); \
73 : : _GJS_CAIRO_CONTEXT_DEFINE_FUNC_END
74 : :
75 : : #define _GJS_CAIRO_CONTEXT_DEFINE_FUNC0B(method, cfunc) \
76 : : _GJS_CAIRO_CONTEXT_DEFINE_FUNC_BEGIN(method) \
77 : : cairo_bool_t ret; \
78 : : _GJS_CAIRO_CONTEXT_CHECK_NO_ARGS(method) \
79 : : ret = cfunc(cr); \
80 : : argv.rval().setBoolean(ret); \
81 : : _GJS_CAIRO_CONTEXT_DEFINE_FUNC_END
82 : :
83 : : #define _GJS_CAIRO_CONTEXT_DEFINE_FUNC2FFAFF(method, cfunc, n1, n2) \
84 : : _GJS_CAIRO_CONTEXT_DEFINE_FUNC_BEGIN(method) \
85 : : double arg1, arg2; \
86 : : if (!gjs_parse_call_args(context, #method, argv, "ff", #n1, &arg1, #n2, \
87 : : &arg2)) \
88 : : return false; \
89 : : cfunc(cr, &arg1, &arg2); \
90 : : if (cairo_status(cr) == CAIRO_STATUS_SUCCESS) { \
91 : : JS::RootedObject array(context, JS::NewArrayObject(context, 2)); \
92 : : if (!array) \
93 : : return false; \
94 : : JS::RootedValue r{context, \
95 : : JS::NumberValue(JS::CanonicalizeNaN(arg1))}; \
96 : : if (!JS_SetElement(context, array, 0, r)) \
97 : : return false; \
98 : : r.setNumber(JS::CanonicalizeNaN(arg2)); \
99 : : if (!JS_SetElement(context, array, 1, r)) \
100 : : return false; \
101 : : argv.rval().setObject(*array); \
102 : : } \
103 : : _GJS_CAIRO_CONTEXT_DEFINE_FUNC_END
104 : :
105 : : #define _GJS_CAIRO_CONTEXT_DEFINE_FUNC0AFF(method, cfunc) \
106 : : _GJS_CAIRO_CONTEXT_DEFINE_FUNC_BEGIN(method) \
107 : : double arg1, arg2; \
108 : : _GJS_CAIRO_CONTEXT_CHECK_NO_ARGS(method) \
109 : : cfunc(cr, &arg1, &arg2); \
110 : : if (cairo_status(cr) == CAIRO_STATUS_SUCCESS) { \
111 : : JS::RootedObject array(context, JS::NewArrayObject(context, 2)); \
112 : : if (!array) \
113 : : return false; \
114 : : JS::RootedValue r{context, \
115 : : JS::NumberValue(JS::CanonicalizeNaN(arg1))}; \
116 : : if (!JS_SetElement(context, array, 0, r)) \
117 : : return false; \
118 : : r.setNumber(JS::CanonicalizeNaN(arg2)); \
119 : : if (!JS_SetElement(context, array, 1, r)) \
120 : : return false; \
121 : : argv.rval().setObject(*array); \
122 : : } \
123 : : _GJS_CAIRO_CONTEXT_DEFINE_FUNC_END
124 : :
125 : : #define _GJS_CAIRO_CONTEXT_DEFINE_FUNC0AFFFF(method, cfunc) \
126 : : _GJS_CAIRO_CONTEXT_DEFINE_FUNC_BEGIN(method) \
127 : : double arg1, arg2, arg3, arg4; \
128 : : _GJS_CAIRO_CONTEXT_CHECK_NO_ARGS(method) \
129 : : cfunc(cr, &arg1, &arg2, &arg3, &arg4); \
130 : : { \
131 : : JS::RootedObject array(context, JS::NewArrayObject(context, 4)); \
132 : : if (!array) \
133 : : return false; \
134 : : JS::RootedValue r{context, \
135 : : JS::NumberValue(JS::CanonicalizeNaN(arg1))}; \
136 : : if (!JS_SetElement(context, array, 0, r)) \
137 : : return false; \
138 : : r.setNumber(JS::CanonicalizeNaN(arg2)); \
139 : : if (!JS_SetElement(context, array, 1, r)) \
140 : : return false; \
141 : : r.setNumber(JS::CanonicalizeNaN(arg3)); \
142 : : if (!JS_SetElement(context, array, 2, r)) \
143 : : return false; \
144 : : r.setNumber(JS::CanonicalizeNaN(arg4)); \
145 : : if (!JS_SetElement(context, array, 3, r)) \
146 : : return false; \
147 : : argv.rval().setObject(*array); \
148 : : } \
149 : : _GJS_CAIRO_CONTEXT_DEFINE_FUNC_END
150 : :
151 : : #define _GJS_CAIRO_CONTEXT_DEFINE_FUNC0F(method, cfunc) \
152 : : _GJS_CAIRO_CONTEXT_DEFINE_FUNC_BEGIN(method) \
153 : : double ret; \
154 : : _GJS_CAIRO_CONTEXT_CHECK_NO_ARGS(method) \
155 : : ret = cfunc(cr); \
156 : : argv.rval().setNumber(JS::CanonicalizeNaN(ret)); \
157 : : _GJS_CAIRO_CONTEXT_DEFINE_FUNC_END
158 : :
159 : : #define _GJS_CAIRO_CONTEXT_DEFINE_FUNC1(method, cfunc, fmt, t1, n1) \
160 : : _GJS_CAIRO_CONTEXT_DEFINE_FUNC_BEGIN(method) \
161 : : t1 arg1; \
162 : : if (!gjs_parse_call_args(context, #method, argv, fmt, \
163 : : #n1, &arg1)) \
164 : : return false; \
165 : : cfunc(cr, arg1); \
166 : : argv.rval().setUndefined(); \
167 : : _GJS_CAIRO_CONTEXT_DEFINE_FUNC_END
168 : :
169 : : #define _GJS_CAIRO_CONTEXT_DEFINE_FUNC2(method, cfunc, fmt, t1, n1, t2, n2) \
170 : : _GJS_CAIRO_CONTEXT_DEFINE_FUNC_BEGIN(method) \
171 : : t1 arg1; \
172 : : t2 arg2; \
173 : : if (!gjs_parse_call_args(context, #method, argv, fmt, \
174 : : #n1, &arg1, #n2, &arg2)) \
175 : : return false; \
176 : : cfunc(cr, arg1, arg2); \
177 : : argv.rval().setUndefined(); \
178 : : _GJS_CAIRO_CONTEXT_DEFINE_FUNC_END
179 : :
180 : : #define _GJS_CAIRO_CONTEXT_DEFINE_FUNC2B(method, cfunc, fmt, t1, n1, t2, n2) \
181 : : _GJS_CAIRO_CONTEXT_DEFINE_FUNC_BEGIN(method) \
182 : : t1 arg1; \
183 : : t2 arg2; \
184 : : cairo_bool_t ret; \
185 : : if (!gjs_parse_call_args(context, #method, argv, fmt, \
186 : : #n1, &arg1, #n2, &arg2)) \
187 : : return false; \
188 : : ret = cfunc(cr, arg1, arg2); \
189 : : argv.rval().setBoolean(ret); \
190 : : _GJS_CAIRO_CONTEXT_DEFINE_FUNC_END
191 : :
192 : : #define _GJS_CAIRO_CONTEXT_DEFINE_FUNC3(method, cfunc, fmt, t1, n1, t2, n2, t3, n3) \
193 : : _GJS_CAIRO_CONTEXT_DEFINE_FUNC_BEGIN(method) \
194 : : t1 arg1; \
195 : : t2 arg2; \
196 : : t3 arg3; \
197 : : if (!gjs_parse_call_args(context, #method, argv, fmt, \
198 : : #n1, &arg1, #n2, &arg2, #n3, &arg3)) \
199 : : return false; \
200 : : cfunc(cr, arg1, arg2, arg3); \
201 : : argv.rval().setUndefined(); \
202 : : _GJS_CAIRO_CONTEXT_DEFINE_FUNC_END
203 : :
204 : : #define _GJS_CAIRO_CONTEXT_DEFINE_FUNC4(method, cfunc, fmt, t1, n1, t2, n2, t3, n3, t4, n4) \
205 : : _GJS_CAIRO_CONTEXT_DEFINE_FUNC_BEGIN(method) \
206 : : t1 arg1; \
207 : : t2 arg2; \
208 : : t3 arg3; \
209 : : t4 arg4; \
210 : : if (!gjs_parse_call_args(context, #method, argv, fmt, \
211 : : #n1, &arg1, #n2, &arg2, \
212 : : #n3, &arg3, #n4, &arg4)) \
213 : : return false; \
214 : : cfunc(cr, arg1, arg2, arg3, arg4); \
215 : : _GJS_CAIRO_CONTEXT_DEFINE_FUNC_END
216 : :
217 : : #define _GJS_CAIRO_CONTEXT_DEFINE_FUNC5(method, cfunc, fmt, t1, n1, t2, n2, t3, n3, t4, n4, t5, n5) \
218 : : _GJS_CAIRO_CONTEXT_DEFINE_FUNC_BEGIN(method) \
219 : : t1 arg1; \
220 : : t2 arg2; \
221 : : t3 arg3; \
222 : : t4 arg4; \
223 : : t5 arg5; \
224 : : if (!gjs_parse_call_args(context, #method, argv, fmt, \
225 : : #n1, &arg1, #n2, &arg2, #n3, &arg3, \
226 : : #n4, &arg4, #n5, &arg5)) \
227 : : return false; \
228 : : cfunc(cr, arg1, arg2, arg3, arg4, arg5); \
229 : : argv.rval().setUndefined(); \
230 : : _GJS_CAIRO_CONTEXT_DEFINE_FUNC_END
231 : :
232 : : #define _GJS_CAIRO_CONTEXT_DEFINE_FUNC6(method, cfunc, fmt, t1, n1, t2, n2, t3, n3, t4, n4, t5, n5, t6, n6) \
233 : : _GJS_CAIRO_CONTEXT_DEFINE_FUNC_BEGIN(method) \
234 : : t1 arg1; \
235 : : t2 arg2; \
236 : : t3 arg3; \
237 : : t4 arg4; \
238 : : t5 arg5; \
239 : : t6 arg6; \
240 : : if (!gjs_parse_call_args(context, #method, argv, fmt, \
241 : : #n1, &arg1, #n2, &arg2, #n3, &arg3, \
242 : : #n4, &arg4, #n5, &arg5, #n6, &arg6)) \
243 : : return false; \
244 : : cfunc(cr, arg1, arg2, arg3, arg4, arg5, arg6); \
245 : : argv.rval().setUndefined(); \
246 : : _GJS_CAIRO_CONTEXT_DEFINE_FUNC_END
247 : :
248 : : GJS_JSAPI_RETURN_CONVENTION
249 : 49 : cairo_t* CairoContext::constructor_impl(JSContext* context,
250 : : const JS::CallArgs& argv) {
251 : : cairo_t *cr;
252 : :
253 : 49 : JS::RootedObject surface_wrapper(context);
254 [ - + ]: 49 : if (!gjs_parse_call_args(context, "Context", argv, "o",
255 : : "surface", &surface_wrapper))
256 : 0 : return nullptr;
257 : :
258 : 49 : cairo_surface_t* surface = CairoSurface::for_js(context, surface_wrapper);
259 [ + + ]: 49 : if (!surface)
260 : 2 : return nullptr;
261 : :
262 : 47 : cr = cairo_create(surface);
263 : :
264 [ - + ]: 47 : if (!gjs_cairo_check_status(context, cairo_status(cr), "context"))
265 : 0 : return nullptr;
266 : :
267 : 47 : return cr;
268 : 49 : }
269 : :
270 : 53 : void CairoContext::finalize_impl(JS::GCContext*, cairo_t* cr) {
271 [ + + ]: 53 : if (!cr)
272 : 2 : return;
273 : 51 : cairo_destroy(cr);
274 : : }
275 : :
276 : : /* Properties */
277 : : // clang-format off
278 : : const JSPropertySpec CairoContext::proto_props[] = {
279 : : JS_STRING_SYM_PS(toStringTag, "Context", JSPROP_READONLY),
280 : : JS_PS_END};
281 : : // clang-format on
282 : :
283 : : /* Methods */
284 : :
285 [ # # # # : 0 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC5(arc, cairo_arc, "fffff",
# # # # ]
286 : : double, xc, double, yc, double, radius,
287 : : double, angle1, double, angle2)
288 [ # # # # : 0 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC5(arcNegative, cairo_arc_negative, "fffff",
# # # # ]
289 : : double, xc, double, yc, double, radius,
290 : : double, angle1, double, angle2)
291 [ # # # # : 0 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC6(curveTo, cairo_curve_to, "ffffff",
# # # # ]
292 : : double, x1, double, y1, double, x2, double, y2,
293 : : double, x3, double, y3)
294 [ - + - + : 1 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC0(clip, cairo_clip)
- + ]
295 [ - + - + : 1 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC0(clipPreserve, cairo_clip_preserve)
- + ]
296 [ - + - + : 1 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC0AFFFF(clipExtents, cairo_clip_extents)
- + - + -
+ - + - +
- + - + +
- + - ]
297 [ - + - + : 1 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC0(closePath, cairo_close_path)
- + ]
298 [ - + - + : 1 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC0(copyPage, cairo_copy_page)
- + ]
299 [ - + - + : 2 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC2FFAFF(deviceToUser, cairo_device_to_user, "x", "y")
- + - + +
- - + - +
- + + - +
- ]
300 [ - + - + : 2 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC2FFAFF(deviceToUserDistance, cairo_device_to_user_distance, "x", "y")
- + - + +
- - + - +
- + + - +
- ]
301 [ - + - + : 2 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC0(fill, cairo_fill)
- + ]
302 [ - + - + : 1 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC0(fillPreserve, cairo_fill_preserve)
- + ]
303 [ - + - + : 1 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC0AFFFF(fillExtents, cairo_fill_extents)
- + - + -
+ - + - +
- + - + +
- + - ]
304 [ - + - + : 1 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC0I(getAntialias, cairo_get_antialias)
- + - + ]
305 [ # # # # : 0 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC0AFF(getCurrentPoint, cairo_get_current_point)
# # # # #
# # # # #
# # # # #
# ]
306 [ - + - + : 1 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC0I(getDashCount, cairo_get_dash_count)
- + - + ]
307 [ - + - + : 1 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC0I(getFillRule, cairo_get_fill_rule)
- + - + ]
308 [ - + - + : 1 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC0I(getLineCap, cairo_get_line_cap)
- + - + ]
309 [ - + - + : 1 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC0I(getLineJoin, cairo_get_line_join)
- + - + ]
310 [ - + - + : 1 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC0F(getLineWidth, cairo_get_line_width)
- + - + ]
311 [ - + - + : 1 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC0F(getMiterLimit, cairo_get_miter_limit)
- + - + ]
312 [ - + - + : 1 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC0I(getOperator, cairo_get_operator)
- + - + ]
313 [ - + - + : 1 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC0F(getTolerance, cairo_get_tolerance)
- + - + ]
314 [ # # # # : 0 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC0B(hasCurrentPoint, cairo_has_current_point)
# # # # ]
315 [ - + - + : 1 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC0(identityMatrix, cairo_identity_matrix)
- + ]
316 [ - + - + : 1 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC2B(inFill, cairo_in_fill, "ff", double, x, double, y)
- + - + ]
317 [ - + - + : 1 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC2B(inStroke, cairo_in_stroke, "ff", double, x, double, y)
- + - + ]
318 [ - + - + : 3 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC2(lineTo, cairo_line_to, "ff", double, x, double, y)
- + - + ]
319 [ - + - + : 1 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC2(moveTo, cairo_move_to, "ff", double, x, double, y)
- + - + ]
320 [ # # # # : 0 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC0(newPath, cairo_new_path)
# # ]
321 [ # # # # : 0 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC0(newSubPath, cairo_new_sub_path)
# # ]
322 [ - + - + : 1 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC0(paint, cairo_paint)
- + ]
323 [ - + - + : 1 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC1(paintWithAlpha, cairo_paint_with_alpha, "f", double, alpha)
- + - + ]
324 [ # # # # : 0 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC0AFFFF(pathExtents, cairo_path_extents)
# # # # #
# # # # #
# # # # #
# # # ]
325 [ - + - + : 1 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC0(pushGroup, cairo_push_group)
- + ]
326 [ - + - + : 1 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC1(pushGroupWithContent, cairo_push_group_with_content, "i",
- + - + ]
327 : : cairo_content_t, content)
328 [ - + - + : 1 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC0(popGroupToSource, cairo_pop_group_to_source)
- + ]
329 [ # # # # : 0 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC4(rectangle, cairo_rectangle, "ffff",
# # # # ]
330 : : double, x, double, y, double, width, double, height)
331 [ # # # # : 0 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC6(relCurveTo, cairo_rel_curve_to, "ffffff",
# # # # ]
332 : : double, dx1, double, dy1, double, dx2, double, dy2,
333 : : double, dx3, double, dy3)
334 [ # # # # : 0 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC2(relLineTo, cairo_rel_line_to, "ff", double, dx, double, dy)
# # # # ]
335 [ # # # # : 0 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC2(relMoveTo, cairo_rel_move_to, "ff", double, dx, double, dy)
# # # # ]
336 [ # # # # : 0 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC0(resetClip, cairo_reset_clip)
# # ]
337 [ - + - + : 1 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC0(restore, cairo_restore)
- + ]
338 [ - + - + : 1 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC1(rotate, cairo_rotate, "f", double, angle)
- + - + ]
339 [ - + - + : 1 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC0(save, cairo_save)
- + ]
340 [ - + - + : 1 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC2(scale, cairo_scale, "ff", double, sx, double, sy)
- + - + ]
341 [ - + - + : 1 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC1(setAntialias, cairo_set_antialias, "i", cairo_antialias_t, antialias)
- + - + ]
342 [ - + - + : 1 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC1(setFillRule, cairo_set_fill_rule, "i", cairo_fill_rule_t, fill_rule)
- + - + ]
343 [ # # # # : 0 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC1(setFontSize, cairo_set_font_size, "f", double, size)
# # # # ]
344 [ - + - + : 1 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC1(setLineCap, cairo_set_line_cap, "i", cairo_line_cap_t, line_cap)
- + - + ]
345 [ - + - + : 1 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC1(setLineJoin, cairo_set_line_join, "i", cairo_line_join_t, line_join)
- + - + ]
346 [ - + - + : 1 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC1(setLineWidth, cairo_set_line_width, "f", double, width)
- + - + ]
347 [ - + - + : 1 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC1(setMiterLimit, cairo_set_miter_limit, "f", double, limit)
- + - + ]
348 [ - + - + : 1 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC1(setOperator, cairo_set_operator, "i", cairo_operator_t, op)
- + - + ]
349 [ - + - + : 1 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC1(setTolerance, cairo_set_tolerance, "f", double, tolerance)
- + - + ]
350 [ - + - + : 1 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC3(setSourceRGB, cairo_set_source_rgb, "fff",
- + - + ]
351 : : double, red, double, green, double, blue)
352 [ - + - + : 1 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC4(setSourceRGBA, cairo_set_source_rgba, "ffff",
- + - + ]
353 : : double, red, double, green, double, blue, double, alpha)
354 [ - + - + : 1 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC0(showPage, cairo_show_page)
- + ]
355 [ - + - + : 3 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC0(stroke, cairo_stroke)
- + ]
356 [ - + - + : 1 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC0(strokePreserve, cairo_stroke_preserve)
- + ]
357 [ - + - + : 1 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC0AFFFF(strokeExtents, cairo_stroke_extents)
- + - + -
+ - + - +
- + - + +
- + - ]
358 [ - + - + : 1 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC2(translate, cairo_translate, "ff", double, tx, double, ty)
- + - + ]
359 [ - + - + : 2 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC2FFAFF(userToDevice, cairo_user_to_device, "x", "y")
- + - + +
- - + - +
- + + - +
- ]
360 [ - + - + : 2 : _GJS_CAIRO_CONTEXT_DEFINE_FUNC2FFAFF(userToDeviceDistance, cairo_user_to_device_distance, "x", "y")
- + - + +
- - + - +
- + + - +
- ]
361 : :
362 : 0 : bool CairoContext::dispose(JSContext* context, unsigned argc, JS::Value* vp) {
363 [ # # # # : 0 : _GJS_CAIRO_CONTEXT_GET_PRIV_CR_CHECKED(context, argc, vp, rec, obj);
# # ]
364 : :
365 : 0 : cairo_destroy(cr);
366 : 0 : CairoContext::unset_private(obj);
367 : :
368 : 0 : rec.rval().setUndefined();
369 : 0 : return true;
370 : 0 : }
371 : :
372 : : GJS_JSAPI_RETURN_CONVENTION
373 : : static bool
374 : 3 : appendPath_func(JSContext *context,
375 : : unsigned argc,
376 : : JS::Value *vp)
377 : : {
378 [ - + - + : 3 : _GJS_CAIRO_CONTEXT_GET_PRIV_CR_CHECKED(context, argc, vp, argv, obj);
- + ]
379 : :
380 : 3 : JS::RootedObject path_wrapper(context);
381 : :
382 [ - + ]: 3 : if (!gjs_parse_call_args(context, "path", argv, "o",
383 : : "path", &path_wrapper))
384 : 0 : return false;
385 : :
386 : : cairo_path_t* path;
387 [ + + ]: 3 : if (!CairoPath::for_js_typecheck(context, path_wrapper, &path, &argv))
388 : 2 : return false;
389 : :
390 : 1 : cairo_append_path(cr, path);
391 : 1 : argv.rval().setUndefined();
392 : 1 : return true;
393 : 3 : }
394 : :
395 : : GJS_JSAPI_RETURN_CONVENTION
396 : : static bool
397 : 1 : copyPath_func(JSContext *context,
398 : : unsigned argc,
399 : : JS::Value *vp)
400 : : {
401 [ - + - + : 1 : _GJS_CAIRO_CONTEXT_GET_PRIV_CR_CHECKED(context, argc, vp, argv, obj);
- + ]
402 : :
403 : : cairo_path_t *path;
404 : :
405 [ - + ]: 1 : if (!gjs_parse_call_args(context, "", argv, ""))
406 : 0 : return false;
407 : :
408 : 1 : path = cairo_copy_path(cr);
409 : 1 : JSObject* retval = CairoPath::take_c_ptr(context, path);
410 [ - + ]: 1 : if (!retval)
411 : 0 : return false;
412 : :
413 : 1 : argv.rval().setObject(*retval);
414 : 1 : return true;
415 : 1 : }
416 : :
417 : : GJS_JSAPI_RETURN_CONVENTION
418 : : static bool
419 : 0 : copyPathFlat_func(JSContext *context,
420 : : unsigned argc,
421 : : JS::Value *vp)
422 : : {
423 [ # # # # : 0 : _GJS_CAIRO_CONTEXT_GET_PRIV_CR_CHECKED(context, argc, vp, argv, obj);
# # ]
424 : :
425 : : cairo_path_t *path;
426 : :
427 [ # # ]: 0 : if (!gjs_parse_call_args(context, "", argv, ""))
428 : 0 : return false;
429 : :
430 : 0 : path = cairo_copy_path_flat(cr);
431 : 0 : JSObject* retval = CairoPath::take_c_ptr(context, path);
432 [ # # ]: 0 : if (!retval)
433 : 0 : return false;
434 : :
435 : 0 : argv.rval().setObject(*retval);
436 : 0 : return true;
437 : 0 : }
438 : :
439 : : GJS_JSAPI_RETURN_CONVENTION
440 : : static bool
441 : 1 : mask_func(JSContext *context,
442 : : unsigned argc,
443 : : JS::Value *vp)
444 : : {
445 [ - + - + : 1 : _GJS_CAIRO_CONTEXT_GET_PRIV_CR_CHECKED(context, argc, vp, argv, obj);
- + ]
446 : :
447 : 1 : JS::RootedObject pattern_wrapper(context);
448 : :
449 [ - + ]: 1 : if (!gjs_parse_call_args(context, "mask", argv, "o",
450 : : "pattern", &pattern_wrapper))
451 : 0 : return false;
452 : :
453 : 1 : cairo_pattern_t* pattern = CairoPattern::for_js(context, pattern_wrapper);
454 [ - + ]: 1 : if (!pattern)
455 : 0 : return false;
456 : :
457 : 1 : cairo_mask(cr, pattern);
458 : :
459 [ - + ]: 1 : if (!gjs_cairo_check_status(context, cairo_status(cr), "context"))
460 : 0 : return false;
461 : :
462 : 1 : argv.rval().setUndefined();
463 : 1 : return true;
464 : 1 : }
465 : :
466 : : GJS_JSAPI_RETURN_CONVENTION
467 : : static bool
468 : 1 : maskSurface_func(JSContext *context,
469 : : unsigned argc,
470 : : JS::Value *vp)
471 : : {
472 [ - + - + : 1 : _GJS_CAIRO_CONTEXT_GET_PRIV_CR_CHECKED(context, argc, vp, argv, obj);
- + ]
473 : :
474 : 1 : JS::RootedObject surface_wrapper(context);
475 : : double x, y;
476 : :
477 [ - + ]: 1 : if (!gjs_parse_call_args(context, "maskSurface", argv, "off",
478 : : "surface", &surface_wrapper,
479 : : "x", &x,
480 : : "y", &y))
481 : 0 : return false;
482 : :
483 : 1 : cairo_surface_t* surface = CairoSurface::for_js(context, surface_wrapper);
484 [ - + ]: 1 : if (!surface)
485 : 0 : return false;
486 : :
487 : 1 : cairo_mask_surface(cr, surface, x, y);
488 : :
489 [ - + ]: 1 : if (!gjs_cairo_check_status(context, cairo_status(cr), "context"))
490 : 0 : return false;
491 : :
492 : 1 : argv.rval().setUndefined();
493 : 1 : return true;
494 : 1 : }
495 : :
496 : : GJS_JSAPI_RETURN_CONVENTION
497 : : static bool
498 : 2 : setDash_func(JSContext *context,
499 : : unsigned argc,
500 : : JS::Value *vp)
501 : : {
502 [ - + - + : 2 : _GJS_CAIRO_CONTEXT_GET_PRIV_CR_CHECKED(context, argc, vp, argv, obj);
- + ]
503 : :
504 : : guint i;
505 : 2 : JS::RootedObject dashes(context);
506 : : double offset;
507 : : guint len;
508 : : bool is_array;
509 : :
510 [ - + ]: 2 : if (!gjs_parse_call_args(context, "setDash", argv, "of",
511 : : "dashes", &dashes,
512 : : "offset", &offset))
513 : 0 : return false;
514 : :
515 [ - + ]: 2 : if (!JS::IsArrayObject(context, dashes, &is_array))
516 : 0 : return false;
517 [ - + ]: 2 : if (!is_array) {
518 : 0 : gjs_throw(context, "dashes must be an array");
519 : 0 : return false;
520 : : }
521 : :
522 [ - + ]: 2 : if (!JS::GetArrayLength(context, dashes, &len)) {
523 : 0 : gjs_throw(context, "Can't get length of dashes");
524 : 0 : return false;
525 : : }
526 : :
527 : 2 : std::unique_ptr<double[]> dashes_c = std::make_unique<double[]>(len);
528 : 2 : size_t dashes_c_size = 0;
529 : 2 : JS::RootedValue elem(context);
530 [ + + ]: 4 : for (i = 0; i < len; ++i) {
531 : : double b;
532 : :
533 : 2 : elem.setUndefined();
534 [ - + ]: 2 : if (!JS_GetElement(context, dashes, i, &elem)) {
535 : 0 : return false;
536 : : }
537 [ - + ]: 2 : if (elem.isUndefined())
538 : 0 : continue;
539 : :
540 [ - + ]: 2 : if (!JS::ToNumber(context, elem, &b))
541 : 0 : return false;
542 [ - + ]: 2 : if (b <= 0) {
543 : 0 : gjs_throw(context, "Dash value must be positive");
544 : 0 : return false;
545 : : }
546 : :
547 : 2 : dashes_c[dashes_c_size++] = b;
548 : : }
549 : :
550 : 2 : cairo_set_dash(cr, dashes_c.get(), dashes_c_size, offset);
551 : 2 : argv.rval().setUndefined();
552 : 2 : return true;
553 : 2 : }
554 : :
555 : : GJS_JSAPI_RETURN_CONVENTION
556 : : static bool
557 : 8 : setSource_func(JSContext *context,
558 : : unsigned argc,
559 : : JS::Value *vp)
560 : : {
561 [ - + - + : 8 : _GJS_CAIRO_CONTEXT_GET_PRIV_CR_CHECKED(context, argc, vp, argv, obj);
- + ]
562 : :
563 : 8 : JS::RootedObject pattern_wrapper(context);
564 : :
565 [ - + ]: 8 : if (!gjs_parse_call_args(context, "setSource", argv, "o",
566 : : "pattern", &pattern_wrapper))
567 : 0 : return false;
568 : :
569 : 8 : cairo_pattern_t* pattern = CairoPattern::for_js(context, pattern_wrapper);
570 [ + + ]: 8 : if (!pattern)
571 : 2 : return false;
572 : :
573 : 6 : cairo_set_source(cr, pattern);
574 : :
575 [ - + ]: 6 : if (!gjs_cairo_check_status(context, cairo_status(cr), "context"))
576 : 0 : return false;
577 : :
578 : 6 : argv.rval().setUndefined();
579 : :
580 : 6 : return true;
581 : 8 : }
582 : :
583 : : GJS_JSAPI_RETURN_CONVENTION
584 : : static bool
585 : 1 : setSourceSurface_func(JSContext *context,
586 : : unsigned argc,
587 : : JS::Value *vp)
588 : : {
589 [ - + - + : 1 : _GJS_CAIRO_CONTEXT_GET_PRIV_CR_CHECKED(context, argc, vp, argv, obj);
- + ]
590 : :
591 : 1 : JS::RootedObject surface_wrapper(context);
592 : : double x, y;
593 : :
594 [ - + ]: 1 : if (!gjs_parse_call_args(context, "setSourceSurface", argv, "off",
595 : : "surface", &surface_wrapper,
596 : : "x", &x,
597 : : "y", &y))
598 : 0 : return false;
599 : :
600 : 1 : cairo_surface_t* surface = CairoSurface::for_js(context, surface_wrapper);
601 [ - + ]: 1 : if (!surface)
602 : 0 : return false;
603 : :
604 : 1 : cairo_set_source_surface(cr, surface, x, y);
605 : :
606 [ - + ]: 1 : if (!gjs_cairo_check_status(context, cairo_status(cr), "context"))
607 : 0 : return false;
608 : :
609 : 1 : argv.rval().setUndefined();
610 : :
611 : 1 : return true;
612 : 1 : }
613 : :
614 : : GJS_JSAPI_RETURN_CONVENTION
615 : : static bool
616 : 1 : showText_func(JSContext *context,
617 : : unsigned argc,
618 : : JS::Value *vp)
619 : : {
620 [ - + - + : 1 : _GJS_CAIRO_CONTEXT_GET_PRIV_CR_CHECKED(context, argc, vp, argv, obj);
- + ]
621 : :
622 : 1 : JS::UniqueChars utf8;
623 : :
624 [ - + ]: 1 : if (!gjs_parse_call_args(context, "showText", argv, "s",
625 : : "utf8", &utf8))
626 : 0 : return false;
627 : :
628 : 1 : cairo_show_text(cr, utf8.get());
629 : :
630 [ - + ]: 1 : if (!gjs_cairo_check_status(context, cairo_status(cr), "context"))
631 : 0 : return false;
632 : :
633 : 1 : argv.rval().setUndefined();
634 : :
635 : 1 : return true;
636 : 1 : }
637 : :
638 : : GJS_JSAPI_RETURN_CONVENTION
639 : : static bool
640 : 0 : selectFontFace_func(JSContext *context,
641 : : unsigned argc,
642 : : JS::Value *vp)
643 : : {
644 [ # # # # : 0 : _GJS_CAIRO_CONTEXT_GET_PRIV_CR_CHECKED(context, argc, vp, argv, obj);
# # ]
645 : :
646 : 0 : JS::UniqueChars family;
647 : : cairo_font_slant_t slant;
648 : : cairo_font_weight_t weight;
649 : :
650 [ # # ]: 0 : if (!gjs_parse_call_args(context, "selectFontFace", argv, "sii",
651 : : "family", &family,
652 : : "slang", &slant,
653 : : "weight", &weight))
654 : 0 : return false;
655 : :
656 : 0 : cairo_select_font_face(cr, family.get(), slant, weight);
657 : :
658 [ # # ]: 0 : if (!gjs_cairo_check_status(context, cairo_status(cr), "context"))
659 : 0 : return false;
660 : 0 : argv.rval().setUndefined();
661 : :
662 : 0 : return true;
663 : 0 : }
664 : :
665 : : GJS_JSAPI_RETURN_CONVENTION
666 : : static bool
667 : 1 : popGroup_func(JSContext *context,
668 : : unsigned argc,
669 : : JS::Value *vp)
670 : : {
671 [ - + - + : 1 : _GJS_CAIRO_CONTEXT_GET_PRIV_CR_CHECKED(context, argc, vp, rec, obj);
- + ]
672 : :
673 : : cairo_pattern_t *pattern;
674 : : JSObject *pattern_wrapper;
675 : :
676 [ - + ]: 1 : if (argc > 0) {
677 : 0 : gjs_throw(context, "Context.popGroup() takes no arguments");
678 : 0 : return false;
679 : : }
680 : :
681 : 1 : pattern = cairo_pop_group(cr);
682 [ - + ]: 1 : if (!gjs_cairo_check_status(context, cairo_status(cr), "context"))
683 : 0 : return false;
684 : :
685 : 1 : pattern_wrapper = gjs_cairo_pattern_from_pattern(context, pattern);
686 : 1 : cairo_pattern_destroy(pattern);
687 [ - + ]: 1 : if (!pattern_wrapper) {
688 : 0 : gjs_throw(context, "failed to create pattern");
689 : 0 : return false;
690 : : }
691 : :
692 : 1 : rec.rval().setObject(*pattern_wrapper);
693 : :
694 : 1 : return true;
695 : 1 : }
696 : : GJS_JSAPI_RETURN_CONVENTION
697 : : static bool
698 : 6 : getSource_func(JSContext *context,
699 : : unsigned argc,
700 : : JS::Value *vp)
701 : : {
702 [ - + - + : 6 : _GJS_CAIRO_CONTEXT_GET_PRIV_CR_CHECKED(context, argc, vp, rec, obj);
- + ]
703 : :
704 : : cairo_pattern_t *pattern;
705 : : JSObject *pattern_wrapper;
706 : :
707 [ - + ]: 6 : if (argc > 0) {
708 : 0 : gjs_throw(context, "Context.getSource() takes no arguments");
709 : 0 : return false;
710 : : }
711 : :
712 : 6 : pattern = cairo_get_source(cr);
713 [ - + ]: 6 : if (!gjs_cairo_check_status(context, cairo_status(cr), "context"))
714 : 0 : return false;
715 : :
716 : : /* pattern belongs to the context, so keep the reference */
717 : 6 : pattern_wrapper = gjs_cairo_pattern_from_pattern(context, pattern);
718 [ - + ]: 6 : if (!pattern_wrapper) {
719 : 0 : gjs_throw(context, "failed to create pattern");
720 : 0 : return false;
721 : : }
722 : :
723 : 6 : rec.rval().setObject(*pattern_wrapper);
724 : :
725 : 6 : return true;
726 : 6 : }
727 : :
728 : : GJS_JSAPI_RETURN_CONVENTION
729 : : static bool
730 : 4 : getTarget_func(JSContext *context,
731 : : unsigned argc,
732 : : JS::Value *vp)
733 : : {
734 [ - + - + : 4 : _GJS_CAIRO_CONTEXT_GET_PRIV_CR_CHECKED(context, argc, vp, rec, obj);
- + ]
735 : :
736 : : cairo_surface_t *surface;
737 : :
738 [ - + ]: 4 : if (argc > 0) {
739 : 0 : gjs_throw(context, "Context.getTarget() takes no arguments");
740 : 0 : return false;
741 : : }
742 : :
743 : 4 : surface = cairo_get_target(cr);
744 [ - + ]: 4 : if (!gjs_cairo_check_status(context, cairo_status(cr), "context"))
745 : 0 : return false;
746 : :
747 : : /* surface belongs to the context, so keep the reference */
748 : 4 : JSObject* surface_wrapper = CairoSurface::from_c_ptr(context, surface);
749 [ - + ]: 4 : if (!surface_wrapper) {
750 : : /* exception already set */
751 : 0 : return false;
752 : : }
753 : :
754 : 4 : rec.rval().setObject(*surface_wrapper);
755 : :
756 : 4 : return true;
757 : 4 : }
758 : :
759 : : GJS_JSAPI_RETURN_CONVENTION
760 : : static bool
761 : 0 : getGroupTarget_func(JSContext *context,
762 : : unsigned argc,
763 : : JS::Value *vp)
764 : : {
765 [ # # # # : 0 : _GJS_CAIRO_CONTEXT_GET_PRIV_CR_CHECKED(context, argc, vp, rec, obj);
# # ]
766 : :
767 : : cairo_surface_t *surface;
768 : :
769 [ # # ]: 0 : if (argc > 0) {
770 : 0 : gjs_throw(context, "Context.getGroupTarget() takes no arguments");
771 : 0 : return false;
772 : : }
773 : :
774 : 0 : surface = cairo_get_group_target(cr);
775 [ # # ]: 0 : if (!gjs_cairo_check_status(context, cairo_status(cr), "context"))
776 : 0 : return false;
777 : :
778 : : /* surface belongs to the context, so keep the reference */
779 : 0 : JSObject* surface_wrapper = CairoSurface::from_c_ptr(context, surface);
780 [ # # ]: 0 : if (!surface_wrapper) {
781 : : /* exception already set */
782 : 0 : return false;
783 : : }
784 : :
785 : 0 : rec.rval().setObject(*surface_wrapper);
786 : :
787 : 0 : return true;
788 : 0 : }
789 : :
790 : : GJS_JSAPI_RETURN_CONVENTION
791 : 2 : static bool textExtents_func(JSContext* cx, unsigned argc, JS::Value* vp) {
792 [ - + - + : 2 : _GJS_CAIRO_CONTEXT_GET_PRIV_CR_CHECKED(cx, argc, vp, args, this_obj);
- + ]
793 : :
794 : 2 : JS::UniqueChars utf8;
795 [ - + ]: 2 : if (!gjs_parse_call_args(cx, "textExtents", args, "s", "utf8", &utf8))
796 : 0 : return false;
797 : :
798 : : cairo_text_extents_t extents;
799 : 2 : cairo_text_extents(cr, utf8.get(), &extents);
800 [ - + ]: 2 : if (!gjs_cairo_check_status(cx, cairo_status(cr), "context"))
801 : 0 : return false;
802 : :
803 : 2 : JS::RootedObject extents_obj(cx, JS_NewPlainObject(cx));
804 [ - + ]: 2 : if (!extents_obj)
805 : 0 : return false;
806 : :
807 : : JSPropertySpec properties[] = {
808 : 2 : JS_DOUBLE_PS("xBearing", extents.x_bearing, JSPROP_ENUMERATE),
809 : 2 : JS_DOUBLE_PS("yBearing", extents.y_bearing, JSPROP_ENUMERATE),
810 : 2 : JS_DOUBLE_PS("width", extents.width, JSPROP_ENUMERATE),
811 : 2 : JS_DOUBLE_PS("height", extents.height, JSPROP_ENUMERATE),
812 : 2 : JS_DOUBLE_PS("xAdvance", extents.x_advance, JSPROP_ENUMERATE),
813 : 2 : JS_DOUBLE_PS("yAdvance", extents.y_advance, JSPROP_ENUMERATE),
814 : 2 : JS_PS_END};
815 : :
816 [ - + ]: 2 : if (!JS_DefineProperties(cx, extents_obj, properties))
817 : 0 : return false;
818 : :
819 : 2 : args.rval().setObject(*extents_obj);
820 : 2 : return true;
821 : 2 : }
822 : :
823 : : // clang-format off
824 : : const JSFunctionSpec CairoContext::proto_funcs[] = {
825 : : JS_FN("$dispose", &CairoContext::dispose, 0, 0),
826 : : JS_FN("appendPath", appendPath_func, 0, 0),
827 : : JS_FN("arc", arc_func, 0, 0),
828 : : JS_FN("arcNegative", arcNegative_func, 0, 0),
829 : : JS_FN("clip", clip_func, 0, 0),
830 : : JS_FN("clipExtents", clipExtents_func, 0, 0),
831 : : JS_FN("clipPreserve", clipPreserve_func, 0, 0),
832 : : JS_FN("closePath", closePath_func, 0, 0),
833 : : JS_FN("copyPage", copyPage_func, 0, 0),
834 : : JS_FN("copyPath", copyPath_func, 0, 0),
835 : : JS_FN("copyPathFlat", copyPathFlat_func, 0, 0),
836 : : JS_FN("curveTo", curveTo_func, 0, 0),
837 : : JS_FN("deviceToUser", deviceToUser_func, 0, 0),
838 : : JS_FN("deviceToUserDistance", deviceToUserDistance_func, 0, 0),
839 : : JS_FN("fill", fill_func, 0, 0),
840 : : JS_FN("fillPreserve", fillPreserve_func, 0, 0),
841 : : JS_FN("fillExtents", fillExtents_func, 0, 0),
842 : : // fontExtents
843 : : JS_FN("getAntialias", getAntialias_func, 0, 0),
844 : : JS_FN("getCurrentPoint", getCurrentPoint_func, 0, 0),
845 : : // getDash
846 : : JS_FN("getDashCount", getDashCount_func, 0, 0),
847 : : JS_FN("getFillRule", getFillRule_func, 0, 0),
848 : : // getFontFace
849 : : // getFontMatrix
850 : : // getFontOptions
851 : : JS_FN("getGroupTarget", getGroupTarget_func, 0, 0),
852 : : JS_FN("getLineCap", getLineCap_func, 0, 0),
853 : : JS_FN("getLineJoin", getLineJoin_func, 0, 0),
854 : : JS_FN("getLineWidth", getLineWidth_func, 0, 0),
855 : : // getMatrix
856 : : JS_FN("getMiterLimit", getMiterLimit_func, 0, 0),
857 : : JS_FN("getOperator", getOperator_func, 0, 0),
858 : : // getScaledFont
859 : : JS_FN("getSource", getSource_func, 0, 0),
860 : : JS_FN("getTarget", getTarget_func, 0, 0),
861 : : JS_FN("getTolerance", getTolerance_func, 0, 0),
862 : : // glyphPath
863 : : // glyphExtents
864 : : JS_FN("hasCurrentPoint", hasCurrentPoint_func, 0, 0),
865 : : JS_FN("identityMatrix", identityMatrix_func, 0, 0),
866 : : JS_FN("inFill", inFill_func, 0, 0),
867 : : JS_FN("inStroke", inStroke_func, 0, 0),
868 : : JS_FN("lineTo", lineTo_func, 0, 0),
869 : : JS_FN("mask", mask_func, 0, 0),
870 : : JS_FN("maskSurface", maskSurface_func, 0, 0),
871 : : JS_FN("moveTo", moveTo_func, 0, 0),
872 : : JS_FN("newPath", newPath_func, 0, 0),
873 : : JS_FN("newSubPath", newSubPath_func, 0, 0),
874 : : JS_FN("paint", paint_func, 0, 0),
875 : : JS_FN("paintWithAlpha", paintWithAlpha_func, 0, 0),
876 : : JS_FN("pathExtents", pathExtents_func, 0, 0),
877 : : JS_FN("popGroup", popGroup_func, 0, 0),
878 : : JS_FN("popGroupToSource", popGroupToSource_func, 0, 0),
879 : : JS_FN("pushGroup", pushGroup_func, 0, 0),
880 : : JS_FN("pushGroupWithContent", pushGroupWithContent_func, 0, 0),
881 : : JS_FN("rectangle", rectangle_func, 0, 0),
882 : : JS_FN("relCurveTo", relCurveTo_func, 0, 0),
883 : : JS_FN("relLineTo", relLineTo_func, 0, 0),
884 : : JS_FN("relMoveTo", relMoveTo_func, 0, 0),
885 : : JS_FN("resetClip", resetClip_func, 0, 0),
886 : : JS_FN("restore", restore_func, 0, 0),
887 : : JS_FN("rotate", rotate_func, 0, 0),
888 : : JS_FN("save", save_func, 0, 0),
889 : : JS_FN("scale", scale_func, 0, 0),
890 : : JS_FN("selectFontFace", selectFontFace_func, 0, 0),
891 : : JS_FN("setAntialias", setAntialias_func, 0, 0),
892 : : JS_FN("setDash", setDash_func, 0, 0),
893 : : // setFontFace
894 : : // setFontMatrix
895 : : // setFontOptions
896 : : JS_FN("setFontSize", setFontSize_func, 0, 0),
897 : : JS_FN("setFillRule", setFillRule_func, 0, 0),
898 : : JS_FN("setLineCap", setLineCap_func, 0, 0),
899 : : JS_FN("setLineJoin", setLineJoin_func, 0, 0),
900 : : JS_FN("setLineWidth", setLineWidth_func, 0, 0),
901 : : // setMatrix
902 : : JS_FN("setMiterLimit", setMiterLimit_func, 0, 0),
903 : : JS_FN("setOperator", setOperator_func, 0, 0),
904 : : // setScaledFont
905 : : JS_FN("setSource", setSource_func, 0, 0),
906 : : JS_FN("setSourceRGB", setSourceRGB_func, 0, 0),
907 : : JS_FN("setSourceRGBA", setSourceRGBA_func, 0, 0),
908 : : JS_FN("setSourceSurface", setSourceSurface_func, 0, 0),
909 : : JS_FN("setTolerance", setTolerance_func, 0, 0),
910 : : // showGlyphs
911 : : JS_FN("showPage", showPage_func, 0, 0),
912 : : JS_FN("showText", showText_func, 0, 0),
913 : : // showTextGlyphs
914 : : JS_FN("stroke", stroke_func, 0, 0),
915 : : JS_FN("strokeExtents", strokeExtents_func, 0, 0),
916 : : JS_FN("strokePreserve", strokePreserve_func, 0, 0),
917 : : // textPath
918 : : JS_FN("textExtents", textExtents_func, 1, 0),
919 : : // transform
920 : : JS_FN("translate", translate_func, 0, 0),
921 : : JS_FN("userToDevice", userToDevice_func, 0, 0),
922 : : JS_FN("userToDeviceDistance", userToDeviceDistance_func, 0, 0),
923 : : JS_FS_END};
924 : : // clang-format on
925 : :
926 : 3 : [[nodiscard]] static bool context_to_gi_argument(
927 : : JSContext* context, JS::Value value, const char* arg_name,
928 : : GjsArgumentType argument_type, GITransfer transfer, GjsArgumentFlags flags,
929 : : GIArgument* arg) {
930 [ - + ]: 3 : if (value.isNull()) {
931 [ # # ]: 0 : if (!(flags & GjsArgumentFlags::MAY_BE_NULL)) {
932 : : Gjs::AutoChar display_name{
933 : 0 : gjs_argument_display_name(arg_name, argument_type)};
934 : 0 : gjs_throw(context, "%s may not be null", display_name.get());
935 : 0 : return false;
936 : 0 : }
937 : :
938 : 0 : gjs_arg_unset(arg);
939 : 0 : return true;
940 : : }
941 : :
942 : 3 : JS::RootedObject obj(context, &value.toObject());
943 : 3 : cairo_t* cr = CairoContext::for_js(context, obj);
944 [ - + ]: 3 : if (!cr)
945 : 0 : return false;
946 [ + + ]: 3 : if (transfer == GI_TRANSFER_EVERYTHING)
947 : 1 : cairo_reference(cr);
948 : :
949 : 3 : gjs_arg_set(arg, cr);
950 : 3 : return true;
951 : 3 : }
952 : :
953 : : GJS_JSAPI_RETURN_CONVENTION
954 : 4 : static bool context_from_gi_argument(JSContext* context,
955 : : JS::MutableHandleValue value_p,
956 : : GIArgument* arg) {
957 : 4 : JSObject* obj = CairoContext::from_c_ptr(
958 : 4 : context, static_cast<cairo_t*>(arg->v_pointer));
959 [ - + ]: 4 : if (!obj) {
960 : 0 : gjs_throw(context, "Could not create Cairo context");
961 : 0 : return false;
962 : : }
963 : :
964 : 4 : value_p.setObject(*obj);
965 : 4 : return true;
966 : : }
967 : :
968 : 3 : static bool context_release_argument(JSContext*, GITransfer transfer,
969 : : GIArgument* arg) {
970 [ + + ]: 3 : if (transfer != GI_TRANSFER_NOTHING)
971 : 2 : cairo_destroy(gjs_arg_get<cairo_t*>(arg));
972 : 3 : return true;
973 : : }
974 : :
975 : 2 : void gjs_cairo_context_init(void) {
976 : : static GjsForeignInfo foreign_info = {context_to_gi_argument,
977 : : context_from_gi_argument,
978 : : context_release_argument};
979 : :
980 : 2 : gjs_struct_foreign_register("cairo", "Context", &foreign_info);
981 : 2 : }
|