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