Tab expansion in all the source files
[adg.git] / cpml / cpml-path.c
blobf351626c6a88af53df8295358a18c9af95398278
1 /* CPML - Cairo Path Manipulation Library
2 * Copyright (C) 2008, 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 Library 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 * Library 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., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 #include "cpml-path.h"
23 #include <string.h>
25 static cairo_bool_t strip_leadings (CpmlPath *path);
26 static cairo_bool_t path_to_segment (CpmlPath *segment,
27 const CpmlPath *path);
28 static cairo_bool_t path_to_primitive (CpmlPath *primitive,
29 const CpmlPath *path);
31 /**
32 * cpml_path_from_cairo:
33 * @path: an allocated #CpmlPath structure
34 * @src: the source cairo_path_t
35 * @cr: a cairo context
37 * Builds a CpmlPath from a cairo_path_t structure. This operations involves
38 * stripping the leading MOVE_TO data and setting @path->org
40 * @cr is used to get the current point (if needed): it can be %NULL,
41 * in which case (0,0) will be used.
43 * @path and @src can be the same object (a #CpmlPath structure).
45 * Return value: 1 on success, 0 on errors
47 cairo_bool_t
48 cpml_path_from_cairo(CpmlPath *path, const cairo_path_t *src, cairo_t *cr)
50 CpmlPair org = { 0., 0. };
52 if (cr && cairo_has_current_point(cr))
53 cairo_get_current_point(cr, &org.x, &org.y);
55 return cpml_path_from_cairo_explicit(path, src, &org);
58 /**
59 * cpml_path_from_cairo_explicit:
60 * @path: an allocated #CpmlPath structure
61 * @src: the source cairo_path_t
62 * @org: a specific origin
64 * Similar to cpml_path_from_cairo() but using an explicit origin.
66 * @path and @src can be the same object (a #CpmlPath structure).
68 * @org can be %NULL, in which case the original path->org pair
69 * is left untouched.
71 * Return value: 1 on success, 0 on errors
73 cairo_bool_t
74 cpml_path_from_cairo_explicit(CpmlPath *path, const cairo_path_t *src,
75 const CpmlPair *org)
77 if (src->status != CAIRO_STATUS_SUCCESS)
78 return 0;
80 if (path != (CpmlPath *) src)
81 memcpy(path, src, sizeof(cairo_path_t));
83 if (strip_leadings(path)) {
84 /* org taken from leadings MOVE_TO */
85 } else if (path->cairo_path.status != CAIRO_STATUS_SUCCESS) {
86 /* Error: probably an empty path provided */
87 return 0;
88 } else if (org) {
89 /* Use the provided org */
90 cpml_pair_copy(&path->org, org);
93 return 1;
96 /**
97 * cpml_path_copy:
98 * @path: an allocated #CpmlPath
99 * @src: the source path to copy
101 * Strips the leading CAIRO_PATH_MOVE_TO primitives, updating the CpmlPath
102 * structure accordling. Also the path org is update.
104 * Return value: @path or %NULL on errors
106 CpmlPath *cpml_path_copy(CpmlPath *path, const CpmlPath *src)
108 if (path == NULL || src == NULL)
109 return NULL;
111 return memcpy(path, src, sizeof(CpmlPath));
115 * cpml_segment_from_path:
116 * @segment: an allocated #CpmlPath struct
117 * @path: the source path
118 * @index: the segment to retrieve (starting from 1);
119 * %CPML_FIRST or %CPML_LAST can be used
121 * Gets a specific segment from a path.
123 * Return value: 1 if a valid segment was found, 0 on errors
125 cairo_bool_t
126 cpml_segment_from_path(CpmlPath *segment, const CpmlPath *path, int index)
128 CpmlPath residue, result;
129 int i;
131 if (!cpml_path_copy(&residue, path))
132 return 0;
134 i = 0;
136 do {
137 if (!path_to_segment(&result, &residue))
138 return index == CPML_LAST && i > 0;
140 residue.cairo_path.data += result.cairo_path.num_data;
141 residue.cairo_path.num_data -= result.cairo_path.num_data;
142 ++i;
144 if (index == CPML_LAST) {
145 cpml_path_copy(segment, &result);
146 continue;
148 } while (i < index);
150 cpml_path_copy(segment, &result);
151 return 1;
155 * cpml_primitive_from_path:
156 * @primitive: an allocated #CpmlPath struct
157 * @path: the source path
158 * @index: the primitive to retrieve (starting from 1);
159 * %CPML_FIRST or %CPML_LAST can be used
161 * Gets a specific primitive from a path.
163 * Return value: 1 if a valid primitive was found, 0 on errors
165 cairo_bool_t
166 cpml_primitive_from_path(CpmlPath *primitive, const CpmlPath *path, int index)
168 CpmlPath residue, result;
169 int i;
171 if (!cpml_path_copy(&residue, path))
172 return 0;
174 i = 0;
176 do {
177 if (!path_to_primitive(&result, &residue))
178 return index == CPML_LAST && i > 0;
180 residue.cairo_path.data += result.cairo_path.num_data;
181 residue.cairo_path.num_data -= result.cairo_path.num_data;
182 ++i;
184 if (index == CPML_LAST) {
185 cpml_path_copy(primitive, &result);
186 continue;
188 } while (i < index);
190 cpml_path_copy(primitive, &result);
191 return 1;
195 * cpml_primitive_get_pair:
196 * @primitive: the source primitive
197 * @pair: the allocated CpmlPair destination
198 * @index: index of the pair to retrieve, starting from 1
200 * Shortcut to get a pair from a primitive.
202 * Return value: 1 on success, 0 on errors
204 cairo_bool_t
205 cpml_primitive_get_pair(const CpmlPath *primitive, CpmlPair *pair, int index)
207 cairo_path_data_t *data = primitive->cairo_path.data;
209 if (index == 0 || index > data[0].header.length)
210 return 0;
212 pair->x = data[index].point.x;
213 pair->y = data[index].point.y;
214 return 1;
218 * cpml_primitive_set_pair:
219 * @primitive: an allocated CpmlPath primitive
220 * @pair: the source pair
221 * @index: index of the pair to change, starting from 1
223 * Shortcut to set a pair on a primitive.
225 * Return value: 1 on success, 0 on errors
227 cairo_bool_t
228 cpml_primitive_set_pair(CpmlPath *primitive, const CpmlPair *pair, int index)
230 cairo_path_data_t *data = primitive->cairo_path.data;
232 if (index == 0 || index > data[0].header.length)
233 return 0;
235 data[index].point.x = pair->x;
236 data[index].point.y = pair->y;
237 return 1;
241 * cpml_primitive_get_point:
242 * @primitive: the source primitive
243 * @point: the allocated CpmlPair destination
244 * @pos: the position factor, being 0 the starting and 1 the ending point
246 * Gets a point lying on @primitive at a specific percentual position.
248 * Return value: 1 on success, 0 on errors
250 cairo_bool_t
251 cpml_primitive_get_point(const CpmlPath *primitive, CpmlPair *point, double pos)
253 int type = primitive->cairo_path.data[0].header.type;
255 if (type != CAIRO_PATH_CLOSE_PATH && type != CAIRO_PATH_LINE_TO &&
256 type != CAIRO_PATH_CURVE_TO)
257 return 0;
259 /* Common cases */
260 if (type == CAIRO_PATH_CLOSE_PATH || pos == 0.) {
261 return cpml_pair_copy(point, &primitive->org);
262 } else if (pos == 1.0) {
263 int n = type == CAIRO_PATH_LINE_TO ? 1 : 3;
264 return cpml_primitive_get_pair(primitive, point, n);
267 /* TODO */
268 return 0;
272 * cpml_primitive_reverse:
273 * @primitive: an allocated #CpmlPath struct
275 * Reverses a primitive.
277 * Return value: 1 on success, 0 on errors
279 cairo_bool_t cpml_primitive_reverse(CpmlPath *primitive)
281 CpmlPair tmp;
283 switch (primitive->cairo_path.data[0].header.type) {
284 case CAIRO_PATH_LINE_TO:
285 cpml_pair_copy(&tmp, &primitive->org);
286 cpml_primitive_get_pair(primitive, &primitive->org, 1);
287 cpml_primitive_set_pair(primitive, &tmp, 1);
288 break;
289 case CAIRO_PATH_CURVE_TO:
290 cpml_pair_copy(&tmp, &primitive->org);
291 cpml_primitive_get_pair(primitive, &primitive->org, 3);
292 cpml_primitive_set_pair(primitive, &tmp, 3);
294 cpml_primitive_get_pair(primitive, &tmp, 2);
295 primitive->cairo_path.data[2].point.x =
296 primitive->cairo_path.data[3].point.x;
297 primitive->cairo_path.data[2].point.y =
298 primitive->cairo_path.data[3].point.y;
299 cpml_primitive_set_pair(primitive, &tmp, 3);
300 break;
301 default:
302 return 0;
305 return 1;
309 * strip_leadings:
310 * @path: a #CpmlPath
312 * Strips the leading CAIRO_PATH_MOVE_TO primitives, updating the CpmlPath
313 * structure accordling. Also the path org is update.
315 * Return value: 1 on success, 0 on no leading MOVE_TOs or on errors
316 * (check for path->cairo_path.status == CAIRO_STATUS_SUCCESS)
318 static cairo_bool_t strip_leadings(CpmlPath *path)
320 if (path->cairo_path.data[0].header.type != CAIRO_PATH_MOVE_TO)
321 return 0;
323 do {
324 ++path->cairo_path.data;
325 path->org.x = path->cairo_path.data->point.x;
326 path->org.y = path->cairo_path.data->point.y;
327 ++path->cairo_path.data;
328 path->cairo_path.num_data -= 2;
329 if (path->cairo_path.num_data <= 0) {
330 path->cairo_path.status = CAIRO_STATUS_INVALID_PATH_DATA;
331 return 0;
333 } while (path->cairo_path.data->header.type == CAIRO_PATH_MOVE_TO);
335 return 1;
339 * path_to_segment:
340 * @segment: an allocated #CpmlPath struct
341 * @path: the source path
343 * Converts a path to a segment. @segment and @path can be the same struct.
345 * Return value: 1 if a valid segment is found, 0 on errors
347 static cairo_bool_t
348 path_to_segment(CpmlPath *segment, const CpmlPath *path)
350 cairo_path_data_t *path_data;
351 int i;
353 if (segment != path)
354 cpml_path_copy(segment, path);
356 if (!strip_leadings(segment) &&
357 segment->cairo_path.status != CAIRO_STATUS_SUCCESS)
358 return 0;
360 path_data = segment->cairo_path.data;
361 i = 0;
363 do {
364 if (path_data->header.type == CAIRO_PATH_MOVE_TO) {
365 --i;
366 break;
367 } else if (path_data->header.type == CAIRO_PATH_CLOSE_PATH) {
368 break;
370 i += path_data->header.length;
371 path_data += path_data->header.length;
372 } while (i < segment->cairo_path.num_data);
374 segment->cairo_path.num_data = i;
375 return 1;
379 * path_to_primitive:
380 * @primitive: an allocated #CpmlPath struct
381 * @path: the source path
383 * Converts a path to a primitive. @primitive and @path can be the same struct.
385 * Return value: 1 if a valid primitive is found, 0 on errors
387 static cairo_bool_t
388 path_to_primitive(CpmlPath *primitive, const CpmlPath *path)
390 cairo_path_data_t *path_data;
392 if (primitive != path)
393 cpml_path_copy(primitive, path);
395 if (!strip_leadings(primitive) &&
396 primitive->cairo_path.status != CAIRO_STATUS_SUCCESS)
397 return 0;
399 primitive->cairo_path.num_data = 1;
400 return 1;