[AdgTableStyle] Removed useless includes
[adg.git] / src / cpml / cpml-line.c
blob9add4d0e2b24596b6f2a0e5c67f9900dbd0750c0
1 /* CPML - Cairo Path Manipulation Library
2 * Copyright (C) 2008,2009,2010,2011 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.
20 #include "cpml-internal.h"
21 #include "cpml-extents.h"
22 #include "cpml-segment.h"
23 #include "cpml-primitive.h"
24 #include "cpml-primitive-private.h"
27 static double get_length (const CpmlPrimitive *line);
28 static void put_extents (const CpmlPrimitive *line,
29 CpmlExtents *extents);
30 static void put_pair_at (const CpmlPrimitive *line,
31 double pos,
32 CpmlPair *pair);
33 static void put_vector_at (const CpmlPrimitive *line,
34 double pos,
35 CpmlVector *vector);
36 static double get_closest_pos (const CpmlPrimitive *line,
37 const CpmlPair *pair);
38 static size_t put_intersections (const CpmlPrimitive *line,
39 const CpmlPrimitive *primitive,
40 size_t n_dest,
41 CpmlPair *dest);
42 static void offset (CpmlPrimitive *line,
43 double offset);
44 static cairo_bool_t
45 intersection (const CpmlPair *p1_4,
46 CpmlPair *dest,
47 double *get_factor);
50 const _CpmlPrimitiveClass *
51 _cpml_line_get_class(void)
53 static _CpmlPrimitiveClass *p_class = NULL;
55 if (p_class == NULL) {
56 static _CpmlPrimitiveClass class_data = {
57 "line to", 2,
58 get_length,
59 put_extents,
60 put_pair_at,
61 put_vector_at,
62 get_closest_pos,
63 put_intersections,
64 offset,
65 NULL
67 p_class = &class_data;
70 return p_class;
73 const _CpmlPrimitiveClass *
74 _cpml_close_get_class(void)
76 static _CpmlPrimitiveClass *p_class = NULL;
78 if (p_class == NULL) {
79 static _CpmlPrimitiveClass class_data = {
80 "close", 2,
81 get_length,
82 put_extents,
83 put_pair_at,
84 put_vector_at,
85 get_closest_pos,
86 put_intersections,
87 offset,
88 NULL
90 p_class = &class_data;
93 return p_class;
97 static double
98 get_length(const CpmlPrimitive *line)
100 CpmlPair p1, p2;
102 cpml_pair_from_cairo(&p1, cpml_primitive_get_point(line, 0));
103 cpml_pair_from_cairo(&p2, cpml_primitive_get_point(line, -1));
105 return cpml_pair_distance(&p1, &p2);
108 static void
109 put_extents(const CpmlPrimitive *line, CpmlExtents *extents)
111 CpmlPair p1, p2;
113 extents->is_defined = 0;
115 cpml_pair_from_cairo(&p1, cpml_primitive_get_point(line, 0));
116 cpml_pair_from_cairo(&p2, cpml_primitive_get_point(line, -1));
118 cpml_extents_pair_add(extents, &p1);
119 cpml_extents_pair_add(extents, &p2);
122 static void
123 put_pair_at(const CpmlPrimitive *line, double pos, CpmlPair *pair)
125 cairo_path_data_t *p1, *p2;
127 p1 = cpml_primitive_get_point(line, 0);
128 p2 = cpml_primitive_get_point(line, -1);
130 pair->x = p1->point.x + (p2->point.x - p1->point.x) * pos;
131 pair->y = p1->point.y + (p2->point.y - p1->point.y) * pos;
134 static void
135 put_vector_at(const CpmlPrimitive *line, double pos, CpmlVector *vector)
137 cairo_path_data_t *p1, *p2;
139 p1 = cpml_primitive_get_point(line, 0);
140 p2 = cpml_primitive_get_point(line, -1);
142 vector->x = p2->point.x - p1->point.x;
143 vector->y = p2->point.y - p1->point.y;
146 static double
147 get_closest_pos(const CpmlPrimitive *line, const CpmlPair *pair)
149 CpmlPair p1_4[4];
150 CpmlVector normal;
151 double pos;
153 cpml_pair_from_cairo(&p1_4[0], cpml_primitive_get_point(line, 0));
154 cpml_pair_from_cairo(&p1_4[1], cpml_primitive_get_point(line, -1));
156 normal.x = p1_4[1].x - p1_4[2].x;
157 normal.y = p1_4[1].y - p1_4[2].y;
158 cpml_vector_normal(&normal);
160 cpml_pair_copy(&p1_4[2], pair);
162 p1_4[3].x = pair->x + normal.x;
163 p1_4[3].y = pair->y + normal.y;
165 /* Ensure to return 0 if intersection() fails */
166 pos = 0;
167 intersection(p1_4, NULL, &pos);
169 /* Clamp the result to 0..1 */
170 if (pos < 0)
171 pos = 0;
172 else if (pos > 1.)
173 pos = 1.;
175 return pos;
178 static size_t
179 put_intersections(const CpmlPrimitive *line, const CpmlPrimitive *primitive,
180 size_t n_dest, CpmlPair *dest)
182 CpmlPair p1_4[4];
184 if (n_dest == 0)
185 return 0;
187 cpml_pair_from_cairo(&p1_4[0], cpml_primitive_get_point(line, 0));
188 cpml_pair_from_cairo(&p1_4[1], cpml_primitive_get_point(line, -1));
189 cpml_pair_from_cairo(&p1_4[2], cpml_primitive_get_point(primitive, 0));
190 cpml_pair_from_cairo(&p1_4[3], cpml_primitive_get_point(primitive, -1));
192 return intersection(p1_4, dest, NULL) ? 1 : 0;
195 static void
196 offset(CpmlPrimitive *line, double offset)
198 cairo_path_data_t *p1, *p2;
199 CpmlVector normal;
201 p1 = cpml_primitive_get_point(line, 0);
202 p2 = cpml_primitive_get_point(line, -1);
204 put_vector_at(line, 0, &normal);
205 cpml_vector_normal(&normal);
206 cpml_vector_set_length(&normal, offset);
208 p1->point.x += normal.x;
209 p1->point.y += normal.y;
210 p2->point.x += normal.x;
211 p2->point.y += normal.y;
214 static cairo_bool_t
215 intersection(const CpmlPair *p1_4, CpmlPair *dest, double *get_factor)
217 CpmlVector v[2];
218 double factor;
220 v[0].x = p1_4[1].x - p1_4[0].x;
221 v[0].y = p1_4[1].y - p1_4[0].y;
222 v[1].x = p1_4[3].x - p1_4[2].x;
223 v[1].y = p1_4[3].y - p1_4[2].y;
224 factor = v[0].x * v[1].y - v[0].y * v[1].x;
226 /* Check for equal slopes (the lines are parallel) */
227 if (factor == 0)
228 return 0;
230 factor = ((p1_4[0].y - p1_4[2].y) * v[1].x -
231 (p1_4[0].x - p1_4[2].x) * v[1].y) / factor;
233 if (dest != NULL) {
234 dest->x = p1_4[0].x + v[0].x * factor;
235 dest->y = p1_4[0].y + v[0].y * factor;
238 if (get_factor != NULL)
239 *get_factor = factor;
241 return 1;