1 /* CPML - Cairo Path Manipulation Library
2 * Copyright (C) 2007-2015 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
,
33 static void put_vector_at (const CpmlPrimitive
*line
,
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
,
42 static void offset (CpmlPrimitive
*line
,
45 intersection (const CpmlPair
*p1_4
,
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
= {
67 p_class
= &class_data
;
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
= {
90 p_class
= &class_data
;
98 get_length(const CpmlPrimitive
*line
)
102 cpml_primitive_put_point(line
, 0, &p1
);
103 cpml_primitive_put_point(line
, -1, &p2
);
105 return cpml_pair_distance(&p1
, &p2
);
109 put_extents(const CpmlPrimitive
*line
, CpmlExtents
*extents
)
113 extents
->is_defined
= 0;
115 cpml_primitive_put_point(line
, 0, &p1
);
116 cpml_primitive_put_point(line
, -1, &p2
);
118 cpml_extents_pair_add(extents
, &p1
);
119 cpml_extents_pair_add(extents
, &p2
);
123 put_pair_at(const CpmlPrimitive
*line
, double pos
, CpmlPair
*pair
)
127 cpml_primitive_put_point(line
, 0, &p1
);
128 cpml_primitive_put_point(line
, -1, &p2
);
130 pair
->x
= p1
.x
+ (p2
.x
- p1
.x
) * pos
;
131 pair
->y
= p1
.y
+ (p2
.y
- p1
.y
) * pos
;
135 put_vector_at(const CpmlPrimitive
*line
, double pos
, CpmlVector
*vector
)
139 cpml_primitive_put_point(line
, 0, &p1
);
140 cpml_primitive_put_point(line
, -1, &p2
);
142 vector
->x
= p2
.x
- p1
.x
;
143 vector
->y
= p2
.y
- p1
.y
;
147 get_closest_pos(const CpmlPrimitive
*line
, const CpmlPair
*pair
)
153 cpml_primitive_put_point(line
, 0, &p1_4
[0]);
154 cpml_primitive_put_point(line
, -1, &p1_4
[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 */
167 intersection(p1_4
, NULL
, &pos
);
169 /* Clamp the result to 0..1 */
179 put_intersections(const CpmlPrimitive
*line
, const CpmlPrimitive
*primitive
,
180 size_t n_dest
, CpmlPair
*dest
)
187 cpml_primitive_put_point(line
, 0, &p1_4
[0]);
188 cpml_primitive_put_point(line
, -1, &p1_4
[1]);
189 cpml_primitive_put_point(primitive
, 0, &p1_4
[2]);
190 cpml_primitive_put_point(primitive
, -1, &p1_4
[3]);
192 return intersection(p1_4
, dest
, NULL
) ? 1 : 0;
196 offset(CpmlPrimitive
*line
, double offset
)
201 cpml_primitive_put_point(line
, 0, &p1
);
202 cpml_primitive_put_point(line
, -1, &p2
);
204 put_vector_at(line
, 0, &normal
);
205 cpml_vector_normal(&normal
);
206 cpml_vector_set_length(&normal
, offset
);
213 cpml_primitive_set_point(line
, 0, &p1
);
214 cpml_primitive_set_point(line
, -1, &p2
);
218 intersection(const CpmlPair
*p1_4
, CpmlPair
*dest
, double *get_factor
)
223 v
[0].x
= p1_4
[1].x
- p1_4
[0].x
;
224 v
[0].y
= p1_4
[1].y
- p1_4
[0].y
;
225 v
[1].x
= p1_4
[3].x
- p1_4
[2].x
;
226 v
[1].y
= p1_4
[3].y
- p1_4
[2].y
;
227 factor
= v
[0].x
* v
[1].y
- v
[0].y
* v
[1].x
;
229 /* Check for equal slopes (the lines are parallel) */
233 factor
= ((p1_4
[0].y
- p1_4
[2].y
) * v
[1].x
-
234 (p1_4
[0].x
- p1_4
[2].x
) * v
[1].y
) / factor
;
237 dest
->x
= p1_4
[0].x
+ v
[0].x
* factor
;
238 dest
->y
= p1_4
[0].y
+ v
[0].y
* factor
;
241 if (get_factor
!= NULL
)
242 *get_factor
= factor
;