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 <cairo.h>
8 : : #include <girepository/girepository.h> // for GIArgument, GITransfer, ...
9 : : #include <glib.h>
10 : :
11 : : #include <js/CallArgs.h>
12 : : #include <js/Class.h>
13 : : #include <js/Object.h> // for GetClass
14 : : #include <js/PropertyDescriptor.h> // for JSPROP_READONLY
15 : : #include <js/PropertySpec.h>
16 : : #include <js/RootingAPI.h>
17 : : #include <js/TypeDecls.h>
18 : : #include <js/Value.h>
19 : :
20 : : #include "gi/arg-inl.h"
21 : : #include "gi/arg.h"
22 : : #include "gi/foreign.h"
23 : : #include "gjs/auto.h"
24 : : #include "gjs/enum-utils.h"
25 : : #include "gjs/jsapi-class.h"
26 : : #include "gjs/jsapi-util.h"
27 : : #include "gjs/macros.h"
28 : : #include "modules/cairo-private.h"
29 : :
30 : : // Properties
31 : :
32 : : // clang-format off
33 : : const JSPropertySpec CairoPattern::proto_props[] = {
34 : : JS_STRING_SYM_PS(toStringTag, "Pattern", JSPROP_READONLY),
35 : : JS_PS_END};
36 : : // clang-format on
37 : :
38 : : // Methods
39 : :
40 : : GJS_JSAPI_RETURN_CONVENTION
41 : 0 : bool CairoPattern::getType_func(JSContext* cx, unsigned argc, JS::Value* vp) {
42 [ # # ]: 0 : GJS_GET_THIS(cx, argc, vp, rec, obj);
43 : :
44 [ # # ]: 0 : if (argc > 1) {
45 : 0 : gjs_throw(cx, "Pattern.getType() takes no arguments");
46 : 0 : return false;
47 : : }
48 : :
49 : 0 : cairo_pattern_t* pattern = CairoPattern::for_js(cx, obj);
50 [ # # ]: 0 : if (!pattern)
51 : 0 : return false;
52 : :
53 : 0 : cairo_pattern_type_t type = cairo_pattern_get_type(pattern);
54 : :
55 [ # # ]: 0 : if (!gjs_cairo_check_status(cx, cairo_pattern_status(pattern), "pattern"))
56 : 0 : return false;
57 : :
58 : 0 : rec.rval().setInt32(type);
59 : 0 : return true;
60 : 0 : }
61 : :
62 : : const JSFunctionSpec CairoPattern::proto_funcs[] = {
63 : : // getMatrix
64 : : JS_FN("getType", getType_func, 0, 0),
65 : : // setMatrix
66 : : JS_FS_END};
67 : :
68 : : // Public API
69 : :
70 : : /**
71 : : * CairoPattern::finalize_impl:
72 : : * @pattern: pointer to free
73 : : *
74 : : * Destroys the resources associated with a pattern wrapper.
75 : : *
76 : : * This is mainly used for subclasses.
77 : : */
78 : 19 : void CairoPattern::finalize_impl(JS::GCContext*, cairo_pattern_t* pattern) {
79 [ - + ]: 19 : if (!pattern)
80 : 0 : return;
81 : 19 : cairo_pattern_destroy(pattern);
82 : : }
83 : :
84 : : /**
85 : : * gjs_cairo_pattern_from_pattern:
86 : : * @cx: the context
87 : : * @pattern: cairo_pattern to attach to the object
88 : : *
89 : : * Constructs a pattern wrapper given cairo pattern. A reference to @pattern
90 : : * will be taken.
91 : : */
92 : 7 : JSObject* gjs_cairo_pattern_from_pattern(JSContext* cx,
93 : : cairo_pattern_t* pattern) {
94 : 7 : g_return_val_if_fail(cx, nullptr);
95 : 7 : g_return_val_if_fail(pattern, nullptr);
96 : :
97 [ + + + + : 7 : switch (cairo_pattern_get_type(pattern)) {
- ]
98 : 3 : case CAIRO_PATTERN_TYPE_SOLID:
99 : 3 : return CairoSolidPattern::from_c_ptr(cx, pattern);
100 : 2 : case CAIRO_PATTERN_TYPE_SURFACE:
101 : 2 : return CairoSurfacePattern::from_c_ptr(cx, pattern);
102 : 1 : case CAIRO_PATTERN_TYPE_LINEAR:
103 : 1 : return CairoLinearGradient::from_c_ptr(cx, pattern);
104 : 1 : case CAIRO_PATTERN_TYPE_RADIAL:
105 : 1 : return CairoRadialGradient::from_c_ptr(cx, pattern);
106 : 0 : case CAIRO_PATTERN_TYPE_MESH:
107 : : case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
108 : : default:
109 : 0 : gjs_throw(cx,
110 : : "failed to create pattern, unsupported pattern type %d",
111 : 0 : cairo_pattern_get_type(pattern));
112 : 0 : return nullptr;
113 : : }
114 : : }
115 : :
116 : : /**
117 : : * CairoPattern::for_js:
118 : : * @cx: the context
119 : : * @pattern_wrapper: pattern wrapper
120 : : *
121 : : * Returns: the pattern attached to the wrapper.
122 : : */
123 : 11 : cairo_pattern_t* CairoPattern::for_js(JSContext* cx,
124 : : JS::HandleObject pattern_wrapper) {
125 : 11 : g_return_val_if_fail(cx, nullptr);
126 : 11 : g_return_val_if_fail(pattern_wrapper, nullptr);
127 : :
128 : 11 : JS::RootedObject proto(cx, CairoPattern::prototype(cx));
129 : :
130 : 11 : bool is_pattern_subclass = false;
131 [ - + ]: 11 : if (!gjs_object_in_prototype_chain(cx, proto, pattern_wrapper,
132 : : &is_pattern_subclass))
133 : 0 : return nullptr;
134 [ + + ]: 11 : if (!is_pattern_subclass) {
135 : 2 : gjs_throw(cx, "Expected Cairo.Pattern but got %s",
136 : 2 : JS::GetClass(pattern_wrapper)->name);
137 : 2 : return nullptr;
138 : : }
139 : :
140 : 9 : return JS::GetMaybePtrFromReservedSlot<cairo_pattern_t>(
141 : 18 : pattern_wrapper, CairoPattern::POINTER);
142 : 11 : }
143 : :
144 : : GJS_JSAPI_RETURN_CONVENTION
145 : 2 : static bool pattern_to_gi_argument(JSContext* cx, JS::Value value,
146 : : const char* arg_name,
147 : : GjsArgumentType argument_type,
148 : : GITransfer transfer, GjsArgumentFlags flags,
149 : : GIArgument* arg) {
150 [ - + ]: 2 : if (value.isNull()) {
151 [ # # ]: 0 : if (!(flags & GjsArgumentFlags::MAY_BE_NULL)) {
152 : : Gjs::AutoChar display_name{
153 : 0 : gjs_argument_display_name(arg_name, argument_type)};
154 : 0 : gjs_throw(cx, "%s may not be null", display_name.get());
155 : 0 : return false;
156 : 0 : }
157 : :
158 : 0 : gjs_arg_unset(arg);
159 : 0 : return true;
160 : : }
161 : :
162 [ - + ]: 2 : if (!value.isObject()) {
163 : : Gjs::AutoChar display_name{
164 : 0 : gjs_argument_display_name(arg_name, argument_type)};
165 : 0 : gjs_throw(cx, "%s is not a Cairo.Pattern", display_name.get());
166 : 0 : return false;
167 : 0 : }
168 : :
169 : 2 : JS::RootedObject pattern_wrapper{cx, &value.toObject()};
170 : 2 : cairo_pattern_t* s = CairoPattern::for_js(cx, pattern_wrapper);
171 [ - + ]: 2 : if (!s)
172 : 0 : return false;
173 [ + + ]: 2 : if (transfer == GI_TRANSFER_EVERYTHING)
174 : 1 : cairo_pattern_reference(s);
175 : :
176 : 2 : gjs_arg_set(arg, s);
177 : 2 : return true;
178 : 2 : }
179 : :
180 : : GJS_JSAPI_RETURN_CONVENTION
181 : 2 : static bool pattern_from_gi_argument(JSContext* cx,
182 : : JS::MutableHandleValue value_p,
183 : : GIArgument* arg) {
184 : : JSObject* obj =
185 : 2 : CairoPattern::from_c_ptr(cx, gjs_arg_get<cairo_pattern_t*>(arg));
186 [ - + ]: 2 : if (!obj)
187 : 0 : return false;
188 : :
189 : 2 : value_p.setObject(*obj);
190 : 2 : return true;
191 : : }
192 : :
193 : 2 : static bool pattern_release_argument(JSContext*, GITransfer transfer,
194 : : GIArgument* arg) {
195 [ + + ]: 2 : if (transfer != GI_TRANSFER_NOTHING)
196 : 1 : cairo_pattern_destroy(gjs_arg_get<cairo_pattern_t*>(arg));
197 : 2 : return true;
198 : : }
199 : :
200 : 2 : void gjs_cairo_pattern_init() {
201 : : static GjsForeignInfo foreign_info = {pattern_to_gi_argument,
202 : : pattern_from_gi_argument,
203 : : pattern_release_argument};
204 : 2 : gjs_struct_foreign_register("cairo", "Pattern", &foreign_info);
205 : 2 : }
|