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