doc: update copyright line for 2021
[adg.git] / src / cpml / cpml-gobject.c
blob25a7e31dd4bf10209c624d7ba31db8e0582cb5ab
1 /* CPML - Cairo Path Manipulation Library
2 * Copyright (C) 2007-2021 Nicola Fontana <ntd at entidi.it>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
21 /**
22 * SECTION:cpml-gobject
23 * @Section_Id:GObject
24 * @title: GObject wrappers
25 * @short_description: Collection of boxed wrappers for CPML structs
27 * These wrappers are supposed to make bindings development easier.
28 * This file defines the wrappers and the functions needed for
29 * implementing the CPML primitives as #GBoxed type.
31 * Since: 1.0
32 **/
34 /**
35 * cpml_memdup:
36 * @src: the memory to copy.
37 * @size: the number of bytes to copy.
39 * A backward compatibility wrapper that calls g_memdup2() (if present)
40 * or g_memdup(). Needed because the latter has been deprecated because
41 * of a unfixable vulnerability (the size was guint instead of gsize).
43 * Since: 1.0
44 **/
47 #include "cpml-internal.h"
49 #include <glib-object.h>
50 #include <string.h>
52 #include "cpml-extents.h"
53 #include "cpml-segment.h"
54 #include "cpml-primitive.h"
55 #include "cpml-curve.h"
57 #include "cpml-gobject.h"
60 GType
61 cpml_pair_get_type(void)
63 static GType pair_type = 0;
65 if (G_UNLIKELY(pair_type == 0))
66 pair_type = g_boxed_type_register_static("CpmlPair",
67 (GBoxedCopyFunc) cpml_pair_dup,
68 g_free);
70 return pair_type;
73 /**
74 * cpml_pair_dup:
75 * @pair: a #CpmlPair structure
77 * Duplicates @pair.
79 * Returns: (transfer full): the duplicate of @pair: must be freed with g_free() when no longer needed.
81 * Since: 1.0
82 **/
83 CpmlPair *
84 cpml_pair_dup(const CpmlPair *pair)
86 return cpml_memdup(pair, sizeof(CpmlPair));
90 GType
91 cpml_primitive_get_type(void)
93 static GType primitive_type = 0;
95 if (G_UNLIKELY(primitive_type == 0))
96 primitive_type = g_boxed_type_register_static("CpmlPrimitive",
97 (GBoxedCopyFunc) cpml_primitive_dup,
98 g_free);
100 return primitive_type;
104 * cpml_primitive_dup:
105 * @primitive: a #CpmlPrimitive structure
107 * Duplicates @primitive. This function makes a shallow duplication of
108 * @primitives, that is the internal pointers of the resulting primitive
109 * struct refer to the same memory as the original @primitive. Check
110 * out cpml_primitive_deep_dup() if it is required also the content
111 * duplication.
113 * Returns: (transfer full): a shallow duplicate of @primitive: must be
114 * freed with g_free() when no longer needed.
116 * Since: 1.0
118 CpmlPrimitive *
119 cpml_primitive_dup(const CpmlPrimitive *primitive)
121 return cpml_memdup(primitive, sizeof(CpmlPrimitive));
125 * cpml_primitive_deep_dup:
126 * @primitive: a #CpmlPrimitive structure
128 * Duplicates @primitive. This function makes a deep duplication of
129 * @primitive, that is it duplicates also the definition data (both
130 * <structfield>org</structfield> and <structfield>data</structfield>).
132 * Furthermore, the new <structfield>segment</structfield> field will
133 * point to a fake duplicated segment with only its first primitive
134 * set (the first primitive of a segment should be a #CPML_MOVE).
135 * This is needed in order to let a #CPML_CLOSE work as expected.
137 * All the data is allocated in the same chunk of memory so freeing
138 * the returned pointer releases all the occupied memory.
140 * Returns: (transfer full): a deep duplicate of @primitive: must be
141 * freed with g_free() when no longer needed
143 * Since: 1.0
145 CpmlPrimitive *
146 cpml_primitive_deep_dup(const CpmlPrimitive *primitive)
148 const CpmlPrimitive *src;
149 CpmlPrimitive *dst;
150 gsize primitive_size, org_size, data_size, segment_size;
151 gchar *ptr;
153 g_return_val_if_fail(primitive != NULL, NULL);
155 src = primitive;
156 primitive_size = sizeof(CpmlPrimitive);
158 if (src->org != NULL)
159 org_size = sizeof(cairo_path_data_t);
160 else
161 org_size = 0;
163 if (src->data != NULL)
164 data_size = sizeof(cairo_path_data_t) * src->data->header.length;
165 else
166 data_size = 0;
168 if (src->segment != NULL && src->segment->data != NULL)
169 segment_size = sizeof(CpmlSegment) +
170 sizeof(cairo_path_data_t) * src->segment->data[0].header.length;
171 else
172 segment_size = 0;
174 dst = g_malloc(primitive_size + org_size + data_size + segment_size);
175 ptr = (gchar *) dst + primitive_size;
177 if (org_size > 0) {
178 dst->org = memcpy(ptr, src->org, org_size);
179 ptr += org_size;
180 } else {
181 dst->org = NULL;
184 if (data_size > 0) {
185 dst->data = memcpy(ptr, src->data, data_size);
186 ptr += data_size;
187 } else {
188 dst->data = NULL;
191 if (segment_size > 0) {
192 dst->segment = memcpy(ptr, src->segment, sizeof(CpmlSegment));
193 ptr += sizeof(CpmlSegment);
194 dst->segment->data = memcpy(ptr, src->segment->data,
195 sizeof(cairo_path_data_t) *
196 src->segment->data[0].header.length);
197 } else {
198 dst->segment = NULL;
201 return dst;
205 GType
206 cpml_segment_get_type(void)
208 static GType segment_type = 0;
210 if (G_UNLIKELY(segment_type == 0))
211 segment_type = g_boxed_type_register_static("CpmlSegment",
212 (GBoxedCopyFunc) cpml_segment_dup,
213 g_free);
215 return segment_type;
219 * cpml_segment_dup:
220 * @segment: a #CpmlSegment structure
222 * Duplicates @segment. This function makes a shallow duplication,
223 * that is the internal pointers of the resulting segment struct
224 * refer to the same memory as the original @segment. Check out
225 * cpml_segment_deep_dup() if it is required also the content
226 * duplication.
228 * Returns: (transfer full): a shallow duplicate of @segment: must be freed with g_free() when no longer needed.
230 * Since: 1.0
232 CpmlSegment *
233 cpml_segment_dup(const CpmlSegment *segment)
235 return cpml_memdup(segment, sizeof(CpmlSegment));
239 * cpml_segment_deep_dup:
240 * @segment: a #CpmlSegment structure
242 * Duplicates @segment. This function makes a deep duplication,
243 * that is it duplicates also the underlying data that defines
244 * the segment. The <structfield>path</structfield> field
245 * is set to <constant>NULL</constant> as
246 * <structfield>data</structfield> is no more referring to the
247 * original cairo path.
249 * All the data is allocated in the same chunk of memory so freeing
250 * the returned pointer releases all the occupied memory.
252 * Returns: (transfer full): a deep duplicate of @segment: must be freed with g_free() when no longer needed.
254 * Since: 1.0
256 CpmlSegment *
257 cpml_segment_deep_dup(const CpmlSegment *segment)
259 CpmlSegment *dest;
260 int num_data;
261 gsize segment_size, data_size;
262 cairo_path_data_t *p_data;
264 g_return_val_if_fail(segment != NULL, NULL);
266 num_data = segment->num_data;
267 segment_size = sizeof(CpmlSegment);
268 data_size = segment->data ? sizeof(cairo_path_data_t) * num_data : 0;
269 dest = (CpmlSegment *) g_malloc(segment_size + data_size);
270 p_data = (cairo_path_data_t *) ((gchar *) dest + segment_size);
272 dest->path = NULL;
274 if (data_size > 0) {
275 dest->data = memcpy(p_data, segment->data, data_size);
276 dest->num_data = num_data;
277 } else {
278 dest->data = NULL;
279 dest->num_data = 0;
282 return dest;
285 GType
286 cpml_curve_offset_algorithm_get_type(void)
288 static GType etype = 0;
289 if (G_UNLIKELY(etype == 0)) {
290 static const GEnumValue values[] = {
291 { CPML_CURVE_OFFSET_ALGORITHM_NONE, "CPML_CURVE_OFFSET_ALGORITHM_NONE", "none" },
292 { CPML_CURVE_OFFSET_ALGORITHM_DEFAULT, "CPML_CURVE_OFFSET_ALGORITHM_DEFAULT", "default" },
293 { CPML_CURVE_OFFSET_ALGORITHM_HANDCRAFT, "CPML_CURVE_OFFSET_ALGORITHM_HANDCRAFT", "handcraft" },
294 { CPML_CURVE_OFFSET_ALGORITHM_BAIOCA, "CPML_CURVE_OFFSET_ALGORITHM_BAIOCA", "baioca" },
295 { 0, NULL, NULL }
298 etype = g_enum_register_static("CpmlCurveOffsetAlgorithm", values);
301 return etype;
304 GType
305 cpml_primitive_type_get_type(void)
307 static GType etype = 0;
308 if (G_UNLIKELY(etype == 0)) {
309 static const GEnumValue values[] = {
310 { CPML_MOVE, "CPML_MOVE", "move" },
311 { CPML_LINE, "CPML_LINE", "line" },
312 { CPML_ARC, "CPML_ARC", "arc" },
313 { CPML_CURVE, "CPML_CURVE", "curve" },
314 { CPML_CLOSE, "CPML_CLOSE", "close" },
315 { 0, NULL, NULL }
318 etype = g_enum_register_static("CpmlPrimitiveType", values);
321 return etype;