From a18aab0709d2c0666fda4349a263509827082c32 Mon Sep 17 00:00:00 2001 From: Nicola Fontana Date: Thu, 12 Mar 2009 15:48:16 +0100 Subject: [PATCH] [CPML] Reworked to include actions in their own constructs Thinking about the function names, came out the separation between operation and construct brings to API explosion. The CPML API should be as clear as possible, so now the actions are merged in their own constructs: the old cpml_intersection() is now implemented as cpml_primitive_intersection() in cpml-primitive.c. This also will allow to add some obvious API, such as cpml_segment_intersection(), and some less obvious one, such as cpml_segment_intersection_with_primitive(). --- cpml/Makefile.am | 6 +- cpml/cpml-action-intersection.c | 177 ----------------------------------- cpml/cpml-action-join.c | 75 --------------- cpml/cpml-action.c | 27 ------ cpml/cpml-close.c | 5 +- cpml/{cpml-action.h => cpml-close.h} | 21 +++-- cpml/cpml-curve.c | 64 ++++++++++++- cpml/cpml-curve.h | 37 +++++--- cpml/cpml-line.c | 48 +++++++++- cpml/cpml-line.h | 21 +++-- cpml/cpml-primitive.c | 107 +++++++++++++++++++++ cpml/cpml-primitive.h | 54 ++++++----- cpml/cpml-segment.c | 2 +- cpml/cpml.h | 1 - demo/cpml-demo.c | 2 +- docs/cpml/cpml-docs.xml | 20 ++-- docs/cpml/cpml-sections.txt | 12 +-- 17 files changed, 311 insertions(+), 368 deletions(-) delete mode 100644 cpml/cpml-action-intersection.c delete mode 100644 cpml/cpml-action-join.c delete mode 100644 cpml/cpml-action.c rename cpml/{cpml-action.h => cpml-close.h} (59%) diff --git a/cpml/Makefile.am b/cpml/Makefile.am index 45c53e7a..7fe2d911 100644 --- a/cpml/Makefile.am +++ b/cpml/Makefile.am @@ -7,7 +7,6 @@ AM_LDFLAGS= @CAIRO_LIBS@ # file groups cpml_h_sources= cpml.h \ - cpml-action.h \ cpml-close.h \ cpml-curve.h \ cpml-line.h \ @@ -18,10 +17,7 @@ cpml_h_sources= cpml.h \ cpml_built_h_sources= cpml_private_h_sources= cpml-alloca.h cpml_built_private_h_sources= -cpml_c_sources= cpml-action.c \ - cpml-action-intersection.c \ - cpml-action-join.c \ - cpml-close.c \ +cpml_c_sources= cpml-close.c \ cpml-curve.c \ cpml-line.c \ cpml-pair.c \ diff --git a/cpml/cpml-action-intersection.c b/cpml/cpml-action-intersection.c deleted file mode 100644 index e48b47f5..00000000 --- a/cpml/cpml-action-intersection.c +++ /dev/null @@ -1,177 +0,0 @@ -/* CPML - Cairo Path Manipulation Library - * Copyright (C) 2008, 2009 Nicola Fontana - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "cpml-action.h" - -static int line_line (const CpmlPrimitive *line1, - const CpmlPrimitive *line2, - CpmlPair *dest); -static int line_curve (const CpmlPrimitive *line, - const CpmlPrimitive *curve, - CpmlPair *dest); -static int curve_curve (const CpmlPrimitive *curve1, - const CpmlPrimitive *curve2, - CpmlPair *dest); - -/** - * cpml_intersection: - * @primitive1: the first #CpmlPrimitive - * @primitive2: the second #CpmlPrimitive - * @dest: the destination #CpmlPair (or a vector of #CpmlPair) - * - * Finds the intersection points between the given primitives and - * returns the result in @dest. If curves are involved, @dest MUST - * be an array of at least 4 #CpmlPair, because this can lead to - * 4 intersection points. - * - * - * TODO - * - * The line_curve() intersection algorithm is not yet implemented. - * The curve_curve() intersection algorithm is not yet implemented. - * - * - * - * Return value: the number of intersection points found - **/ -int -cpml_intersection(const CpmlPrimitive *primitive1, - const CpmlPrimitive *primitive2, CpmlPair *dest) -{ - cairo_path_data_type_t type1, type2; - - type1 = primitive1->data->header.type; - type2 = primitive1->data->header.type; - - /* Close path primitives are treated as line-to */ - if (type1 == CAIRO_PATH_CLOSE_PATH) - type1 = CAIRO_PATH_LINE_TO; - if (type2 == CAIRO_PATH_CLOSE_PATH) - type2 = CAIRO_PATH_LINE_TO; - - /* Dispatcher: probably there's a smarter way to do this */ - if (type1 == CAIRO_PATH_LINE_TO && type2 == CAIRO_PATH_LINE_TO) - return line_line(primitive1, primitive2, dest); - else if (type1 == CAIRO_PATH_CURVE_TO && type2 == CAIRO_PATH_CURVE_TO) - return curve_curve(primitive1, primitive2, dest); - else if (type1 == CAIRO_PATH_LINE_TO && type2 == CAIRO_PATH_CURVE_TO) - return line_curve(primitive1, primitive2, dest); - else if (type1 == CAIRO_PATH_CURVE_TO && type2 == CAIRO_PATH_LINE_TO) - return line_curve(primitive2, primitive1, dest); - - /* Primitive combination not found */ - return 0; -} - -/** - * cpml_intersection_line_line: - * @line1: the first line - * @to: the second line - * @dest: the destination #CpmlPair - * - * Given two lines (@line1 and @line2), gets their intersection point - * and store the result in @dest. - * - * Return value: 1 on success, 0 on no intersections - **/ -static int -line_line(const CpmlPrimitive *line1, const CpmlPrimitive *line2, - CpmlPair *dest) -{ - const cairo_path_data_t *p1a, *p2a, *p1b, *p2b; - CpmlVector va, vb; - double factor; - - p1a = cpml_primitive_get_point(line1, 0); - p2a = cpml_primitive_get_point(line1, 1); - p1b = cpml_primitive_get_point(line2, 0); - p2b = cpml_primitive_get_point(line2, 1); - - va.x = p2a->point.x - p1a->point.x; - va.y = p2a->point.y - p1a->point.y; - vb.x = p2b->point.x - p1b->point.x; - vb.y = p2b->point.y - p1b->point.y; - - factor = va.x * vb.y - va.y * vb.x; - - /* Check if the lines are parallel */ - if (factor == 0) - return 0; - - factor = ((p1a->point.y - p1b->point.y) * vb.x - - (p1a->point.x - p1b->point.x) * vb.y) / factor; - - dest->x = p1a->point.x + va.x * factor; - dest->y = p1a->point.y + va.y * factor; - - return 1; -} - -/** - * line_curve: - * @line: a line - * @curve: a curve - * @dest: a vector of at least 4 #CpmlPair - * - * Given a @line and a Bézier cubic @curve, gets their intersection points - * and store the result in @dest. Because a line and a cubic curve can - * have 4 intersections, @dest MUST be at least an array of 4 #CpmlPair. - * - * - * TODO - * - * To be implemented... - * - * - * - * Return value: the number of intersections (max 4) - **/ -static int -line_curve(const CpmlPrimitive *line, const CpmlPrimitive *curve, - CpmlPair *dest) -{ - return 0; -} - -/** - * curve_curve: - * @curve1: the first curve - * @curve2: the second curve - * @dest: a vector of at least 4 #CpmlPair - * - * Given two Bézier cubic curves (@curve1 and @curve2), gets their - * intersection points and store the result in @dest. Because two - * curves can have 4 intersections, @dest MUST be at least an array - * of 4 #CpmlPair. - * - * - * TODO - * - * To be implemented... - * - * - * - * Return value: the number of intersections (max 4) - **/ -static int -curve_curve(const CpmlPrimitive *curve1, const CpmlPrimitive *curve2, - CpmlPair *dest) -{ - return 0; -} diff --git a/cpml/cpml-action-join.c b/cpml/cpml-action-join.c deleted file mode 100644 index 2237c996..00000000 --- a/cpml/cpml-action-join.c +++ /dev/null @@ -1,75 +0,0 @@ -/* CPML - Cairo Path Manipulation Library - * Copyright (C) 2008, 2009 Nicola Fontana - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "cpml-action.h" - -/** - * cpml_join: - * @primitive1: the first #CpmlPrimitive - * @primitive2: the second #CpmlPrimitive - * - * Joins two primitive modifying the end point of @primitive1 and the - * start point of @primitive2 so that the resulting points will overlap. - * - * This is done by extending the end vector of @primitive1 and the - * start vector of @primitive2 and interpolating the intersection. - * - * - * TODO - * - * This approach is quite naive when curves are involved. - * - * - * - * Return value: 1 on success, 0 if the end vector of @primitive1 - * and the start vector of @primitive2 are parallel - **/ -cairo_bool_t -cpml_join(CpmlPrimitive *primitive1, CpmlPrimitive *primitive2) -{ - cairo_path_data_t *end1, *start2; - CpmlPrimitive line1, line2; - cairo_path_data_t data1[2], data2[2]; - CpmlPair joint; - - end1 = cpml_primitive_get_point(primitive1, -1); - start2 = cpml_primitive_get_point(primitive2, 0); - - /* Check if the primitives are yet connected */ - if (end1->point.x == start2->point.x && end1->point.y == start2->point.y) - return 1; - - line1.org = cpml_primitive_get_point(primitive1, -2); - line1.data = data1; - data1[0].header.type = CAIRO_PATH_LINE_TO; - data1[1] = *end1; - - line2.org = start2; - line2.data = data2; - data2[0].header.type = CAIRO_PATH_LINE_TO; - data2[1] = *cpml_primitive_get_point(primitive2, 1); - - if (!cpml_intersection(&line1, &line2, &joint)) - return 0; - - cpml_pair_to_cairo(&joint, end1); - cpml_pair_to_cairo(&joint, start2); - - return 1; -} diff --git a/cpml/cpml-action.c b/cpml/cpml-action.c deleted file mode 100644 index 043eadae..00000000 --- a/cpml/cpml-action.c +++ /dev/null @@ -1,27 +0,0 @@ -/* CPML - Cairo Path Manipulation Library - * Copyright (C) 2008, 2009 Nicola Fontana - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -/** - * SECTION:action - * @title: Action - * @short_description: Operation that can be executed on two primitives - * - * This section includes operations between two primitives, such as - * joining, finding their intersection points and so on. - **/ diff --git a/cpml/cpml-close.c b/cpml/cpml-close.c index eeb9857b..81cb8b50 100644 --- a/cpml/cpml-close.c +++ b/cpml/cpml-close.c @@ -66,7 +66,7 @@ cpml_close_type_get_npoints(void) * coordinates are interpolated. **/ void -cpml_close_pair_at(CpmlPrimitive *close, CpmlPair *pair, double pos) +cpml_close_pair_at(const CpmlPrimitive *close, CpmlPair *pair, double pos) { cairo_path_data_t *p1, *p2; @@ -88,7 +88,8 @@ cpml_close_pair_at(CpmlPrimitive *close, CpmlPair *pair, double pos) * @pos is not used. **/ void -cpml_close_vector_at(CpmlPrimitive *close, CpmlVector *vector, double pos) +cpml_close_vector_at(const CpmlPrimitive *close, + CpmlVector *vector, double pos) { cairo_path_data_t *p1, *p2; diff --git a/cpml/cpml-action.h b/cpml/cpml-close.h similarity index 59% rename from cpml/cpml-action.h rename to cpml/cpml-close.h index d1ae9bf1..31cf3f67 100644 --- a/cpml/cpml-action.h +++ b/cpml/cpml-close.h @@ -17,21 +17,26 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __CPML_ACTION_H__ -#define __CPML_ACTION_H__ +#ifndef __CPML_CLOSE_H__ +#define __CPML_CLOSE_H__ #include +#include CAIRO_BEGIN_DECLS -cairo_bool_t cpml_join (CpmlPrimitive *primitive1, - CpmlPrimitive *primitive2); -int cpml_intersection (const CpmlPrimitive *primitive1, - const CpmlPrimitive *primitive2, - CpmlPair *dest); +int cpml_close_type_get_npoints (void) CPML_GNUC_CONST; +void cpml_close_pair_at (const CpmlPrimitive *close, + CpmlPair *pair, + double pos); +void cpml_close_vector_at (const CpmlPrimitive *close, + CpmlVector *vector, + double pos); +void cpml_close_offset (CpmlPrimitive *close, + double offset); CAIRO_END_DECLS -#endif /* __CPML_ACTION_H__ */ +#endif /* __CPML_CLOSE_H__ */ diff --git a/cpml/cpml-curve.c b/cpml/cpml-curve.c index b8f31ee4..c1c8df55 100644 --- a/cpml/cpml-curve.c +++ b/cpml/cpml-curve.c @@ -59,7 +59,7 @@ cpml_curve_type_get_npoints(void) * cubic curves is not allowed. **/ void -cpml_curve_pair_at_time(CpmlPrimitive *curve, CpmlPair *pair, double t) +cpml_curve_pair_at_time(const CpmlPrimitive *curve, CpmlPair *pair, double t) { cairo_path_data_t *p1, *p2, *p3, *p4; double t_2, t_3, t1, t1_2, t1_3; @@ -105,7 +105,7 @@ cpml_curve_pair_at_time(CpmlPrimitive *curve, CpmlPair *pair, double t) * **/ void -cpml_curve_pair_at(CpmlPrimitive *curve, CpmlPair *pair, double pos) +cpml_curve_pair_at(const CpmlPrimitive *curve, CpmlPair *pair, double pos) { } @@ -124,7 +124,8 @@ cpml_curve_pair_at(CpmlPrimitive *curve, CpmlPair *pair, double pos) * allowed. **/ void -cpml_curve_vector_at_time(CpmlPrimitive *curve, CpmlVector *vector, double t) +cpml_curve_vector_at_time(const CpmlPrimitive *curve, + CpmlVector *vector, double t) { cairo_path_data_t *p1, *p2, *p3, *p4; CpmlPair p21, p32, p43; @@ -174,11 +175,66 @@ cpml_curve_vector_at_time(CpmlPrimitive *curve, CpmlVector *vector, double t) * **/ void -cpml_curve_vector_at(CpmlPrimitive *curve, CpmlVector *vector, double pos) +cpml_curve_vector_at(const CpmlPrimitive *curve, + CpmlVector *vector, double pos) { } /** + * cpml_curve_intersection: + * @curve: the first curve + * @curve2: the second curve + * @dest: a vector of at least 4 #CpmlPair + * + * Given two Bézier cubic curves (@curve and @curve2), gets their + * intersection points and store the result in @dest. Because two + * curves can have 4 intersections, @dest MUST be at least an array + * of 4 #CpmlPair. + * + * + * TODO + * + * To be implemented... + * + * + * + * Return value: the number of intersections (max 4) + **/ +int +cpml_curve_intersection(const CpmlPrimitive *curve, + const CpmlPrimitive *curve2, CpmlPair *dest) +{ + return 0; +} + +/** + * cpml_curve_intersection_with_line: + * @curve: a curve + * @line: a line + * @dest: a vector of at least 4 #CpmlPair + * + * Given a Bézier cubic @curve and a @line, gets their intersection + * points and store the result in @dest. Because a line and a cubic + * curve can have up to 4 intersections, @dest MUST be at least an + * array of 4 #CpmlPair. + * + * + * TODO + * + * To be implemented... + * + * + * + * Return value: the number of intersections (max 4) + **/ +int +cpml_curve_intersection_with_line(const CpmlPrimitive *curve, + const CpmlPrimitive *line, CpmlPair *dest) +{ + return 0; +} + +/** * cpml_curve_offset: * @curve: the #CpmlPrimitive curve data * @offset: distance for the computed parallel curve diff --git a/cpml/cpml-curve.h b/cpml/cpml-curve.h index f81ebd18..584a1120 100644 --- a/cpml/cpml-curve.h +++ b/cpml/cpml-curve.h @@ -26,21 +26,28 @@ CAIRO_BEGIN_DECLS -int cpml_curve_type_get_npoints (void) CPML_GNUC_CONST; -void cpml_curve_pair_at_time (CpmlPrimitive *curve, - CpmlPair *pair, - double time); -void cpml_curve_pair_at (CpmlPrimitive *curve, - CpmlPair *pair, - double pos); -void cpml_curve_vector_at_time (CpmlPrimitive *curve, - CpmlVector *vector, - double t); -void cpml_curve_vector_at (CpmlPrimitive *curve, - CpmlVector *vector, - double pos); -void cpml_curve_offset (CpmlPrimitive *curve, - double offset); +int cpml_curve_type_get_npoints (void) CPML_GNUC_CONST; +void cpml_curve_pair_at_time (const CpmlPrimitive *curve, + CpmlPair *pair, + double time); +void cpml_curve_pair_at (const CpmlPrimitive *curve, + CpmlPair *pair, + double pos); +void cpml_curve_vector_at_time (const CpmlPrimitive *curve, + CpmlVector *vector, + double t); +void cpml_curve_vector_at (const CpmlPrimitive *curve, + CpmlVector *vector, + double pos); +int cpml_curve_intersection (const CpmlPrimitive *curve, + const CpmlPrimitive *curve2, + CpmlPair *dest); +int cpml_curve_intersection_with_line + (const CpmlPrimitive *curve, + const CpmlPrimitive *line, + CpmlPair *dest); +void cpml_curve_offset (CpmlPrimitive *curve, + double offset); CAIRO_END_DECLS diff --git a/cpml/cpml-line.c b/cpml/cpml-line.c index 0e3e3ec9..c2bdaded 100644 --- a/cpml/cpml-line.c +++ b/cpml/cpml-line.c @@ -58,7 +58,7 @@ cpml_line_type_get_npoints(void) * coordinates are interpolated. **/ void -cpml_line_pair_at(CpmlPrimitive *line, CpmlPair *pair, double pos) +cpml_line_pair_at(const CpmlPrimitive *line, CpmlPair *pair, double pos) { cairo_path_data_t *p1, *p2; @@ -83,7 +83,7 @@ cpml_line_pair_at(CpmlPrimitive *line, CpmlPair *pair, double pos) * @vector = endpoint(@line) - startpoint(@line). **/ void -cpml_line_vector_at(CpmlPrimitive *line, CpmlVector *vector, double pos) +cpml_line_vector_at(const CpmlPrimitive *line, CpmlVector *vector, double pos) { cairo_path_data_t *p1, *p2; @@ -95,6 +95,50 @@ cpml_line_vector_at(CpmlPrimitive *line, CpmlVector *vector, double pos) } /** + * cpml_line_intersection: + * @line: the first line + * @line2: the second line + * @dest: the destination #CpmlPair + * + * Given two lines (@line and @line2), gets their intersection point + * and store the result in @dest. + * + * Return value: 1 on success, 0 on no intersections + **/ +int +cpml_line_intersection(const CpmlPrimitive *line, + const CpmlPrimitive *line2, CpmlPair *dest) +{ + const cairo_path_data_t *p1a, *p2a, *p1b, *p2b; + CpmlVector va, vb; + double factor; + + p1a = cpml_primitive_get_point(line, 0); + p2a = cpml_primitive_get_point(line, 1); + p1b = cpml_primitive_get_point(line2, 0); + p2b = cpml_primitive_get_point(line2, 1); + + va.x = p2a->point.x - p1a->point.x; + va.y = p2a->point.y - p1a->point.y; + vb.x = p2b->point.x - p1b->point.x; + vb.y = p2b->point.y - p1b->point.y; + + factor = va.x * vb.y - va.y * vb.x; + + /* Check if the lines are parallel */ + if (factor == 0) + return 0; + + factor = ((p1a->point.y - p1b->point.y) * vb.x - + (p1a->point.x - p1b->point.x) * vb.y) / factor; + + dest->x = p1a->point.x + va.x * factor; + dest->y = p1a->point.y + va.y * factor; + + return 1; +} + +/** * cpml_line_offset: * @line: the #CpmlPrimitive line data * @offset: distance for the computed parallel line diff --git a/cpml/cpml-line.h b/cpml/cpml-line.h index e22f80dc..6f984f48 100644 --- a/cpml/cpml-line.h +++ b/cpml/cpml-line.h @@ -26,15 +26,18 @@ CAIRO_BEGIN_DECLS -int cpml_line_type_get_npoints (void) CPML_GNUC_CONST; -void cpml_line_pair_at (CpmlPrimitive *line, - CpmlPair *pair, - double pos); -void cpml_line_vector_at (CpmlPrimitive *line, - CpmlVector *vector, - double pos); -void cpml_line_offset (CpmlPrimitive *line, - double offset); +int cpml_line_type_get_npoints (void) CPML_GNUC_CONST; +void cpml_line_pair_at (const CpmlPrimitive *line, + CpmlPair *pair, + double pos); +void cpml_line_vector_at (const CpmlPrimitive *line, + CpmlVector *vector, + double pos); +int cpml_line_intersection (const CpmlPrimitive *line, + const CpmlPrimitive *line2, + CpmlPair *dest); +void cpml_line_offset (CpmlPrimitive *line, + double offset); CAIRO_END_DECLS diff --git a/cpml/cpml-primitive.c b/cpml/cpml-primitive.c index ef539046..8e9d2e3b 100644 --- a/cpml/cpml-primitive.c +++ b/cpml/cpml-primitive.c @@ -393,6 +393,113 @@ cpml_primitive_vector_at(const CpmlPrimitive *primitive, } /** + * cpml_primitive_join: + * @primitive: the first #CpmlPrimitive + * @primitive2: the second #CpmlPrimitive + * + * Joins two primitive modifying the end point of @primitive and the + * start point of @primitive2 so that the resulting points will overlap. + * + * + * TODO + * + * Actually, the join is done by extending the end vector + * of @primitive and the start vector of @primitive2 and + * interpolating the intersection: this means no primitive + * dependent code is needed. Anyway, it is likely to change + * in the future because this approach is quite naive when + * curves are involved. + * + * + * + * Return value: 1 on success, 0 if the end vector of @primitive + * and the start vector of @primitive2 are parallel + **/ +cairo_bool_t +cpml_primitive_join(CpmlPrimitive *primitive, CpmlPrimitive *primitive2) +{ + cairo_path_data_t *end1, *start2; + CpmlPrimitive line1, line2; + cairo_path_data_t data1[2], data2[2]; + CpmlPair joint; + + end1 = cpml_primitive_get_point(primitive, -1); + start2 = cpml_primitive_get_point(primitive2, 0); + + /* Check if the primitives are yet connected */ + if (end1->point.x == start2->point.x && end1->point.y == start2->point.y) + return 1; + + line1.org = cpml_primitive_get_point(primitive, -2); + line1.data = data1; + data1[0].header.type = CAIRO_PATH_LINE_TO; + data1[1] = *end1; + + line2.org = start2; + line2.data = data2; + data2[0].header.type = CAIRO_PATH_LINE_TO; + data2[1] = *cpml_primitive_get_point(primitive2, 1); + + if (!cpml_line_intersection(&line1, &line2, &joint)) + return 0; + + cpml_pair_to_cairo(&joint, end1); + cpml_pair_to_cairo(&joint, start2); + + return 1; +} + +/** + * cpml_primitive_intersection: + * @primitive: the first #CpmlPrimitive + * @primitive2: the second #CpmlPrimitive + * @dest: the destination #CpmlPair (or a vector of #CpmlPair) + * + * Finds the intersection points between the given primitives and + * returns the result in @dest. If curves are involved, @dest MUST + * be an array of at least 4 #CpmlPair, because this can lead to + * 4 intersection points. + * + * + * This function is primitive dependent: every new primitive must + * expose API to get intersections with the any other primitive type + * (excluding %CAIRO_PATH_CLOSE_PATH, as it is converted to a line + * primitive). + * + * + * Return value: the number of intersection points found + **/ +int +cpml_primitive_intersection(const CpmlPrimitive *primitive, + const CpmlPrimitive *primitive2, + CpmlPair *dest) +{ + cairo_path_data_type_t type1, type2; + + type1 = primitive->data->header.type; + type2 = primitive->data->header.type; + + /* Close path primitives are treated as line-to */ + if (type1 == CAIRO_PATH_CLOSE_PATH) + type1 = CAIRO_PATH_LINE_TO; + if (type2 == CAIRO_PATH_CLOSE_PATH) + type2 = CAIRO_PATH_LINE_TO; + + /* Dispatcher: probably there's a smarter way to do this */ + if (type1 == CAIRO_PATH_LINE_TO && type2 == CAIRO_PATH_LINE_TO) + return cpml_line_intersection(primitive, primitive2, dest); + else if (type1 == CAIRO_PATH_CURVE_TO && type2 == CAIRO_PATH_CURVE_TO) + return cpml_curve_intersection(primitive, primitive2, dest); + else if (type1 == CAIRO_PATH_LINE_TO && type2 == CAIRO_PATH_CURVE_TO) + return cpml_curve_intersection_with_line(primitive2, primitive, dest); + else if (type1 == CAIRO_PATH_CURVE_TO && type2 == CAIRO_PATH_LINE_TO) + return cpml_curve_intersection_with_line(primitive, primitive2, dest); + + /* Primitive combination not found */ + return 0; +} + +/** * cpml_primitive_offset: * @primitive: a #CpmlPrimitive * @offset: distance for the computed offset primitive diff --git a/cpml/cpml-primitive.h b/cpml/cpml-primitive.h index f716768a..a4d37ac8 100644 --- a/cpml/cpml-primitive.h +++ b/cpml/cpml-primitive.h @@ -35,33 +35,41 @@ struct _CpmlPrimitive { }; -CpmlPrimitive * cpml_primitive_copy (CpmlPrimitive *primitive, - const CpmlPrimitive *src); -CpmlPrimitive * cpml_primitive_from_segment(CpmlPrimitive *primitive, - CpmlSegment *segment); -void cpml_primitive_reset (CpmlPrimitive *primitive); -cairo_bool_t cpml_primitive_next (CpmlPrimitive *primitive); +CpmlPrimitive * + cpml_primitive_copy (CpmlPrimitive *primitive, + const CpmlPrimitive *src); +CpmlPrimitive * + cpml_primitive_from_segment (CpmlPrimitive *primitive, + CpmlSegment *segment); +void cpml_primitive_reset (CpmlPrimitive *primitive); +cairo_bool_t + cpml_primitive_next (CpmlPrimitive *primitive); -int cpml_primitive_get_npoints (const CpmlPrimitive *primitive); +int cpml_primitive_get_npoints (const CpmlPrimitive *primitive); cairo_path_data_t * - cpml_primitive_get_point (const CpmlPrimitive *primitive, - int npoint); -void cpml_primitive_to_cairo (const CpmlPrimitive *primitive, - cairo_t *cr); -void cpml_primitive_dump (const CpmlPrimitive *primitive, - cairo_bool_t org_also); + cpml_primitive_get_point (const CpmlPrimitive *primitive, + int npoint); +void cpml_primitive_to_cairo (const CpmlPrimitive *primitive, + cairo_t *cr); +void cpml_primitive_dump (const CpmlPrimitive *primitive, + cairo_bool_t org_also); /* To be implemented by the primitives */ -int cpml_primitive_type_get_npoints - (cairo_path_data_type_t type); -void cpml_primitive_pair_at (const CpmlPrimitive *primitive, - CpmlPair *pair, - double pos); -void cpml_primitive_vector_at (const CpmlPrimitive *primitive, - CpmlVector *vector, - double pos); -void cpml_primitive_offset (CpmlPrimitive *primitive, - double offset); +int cpml_primitive_type_get_npoints (cairo_path_data_type_t type); +void cpml_primitive_pair_at (const CpmlPrimitive *primitive, + CpmlPair *pair, + double pos); +void cpml_primitive_vector_at (const CpmlPrimitive *primitive, + CpmlVector *vector, + double pos); +cairo_bool_t + cpml_primitive_join (CpmlPrimitive *primitive, + CpmlPrimitive *primitive2); +int cpml_primitive_intersection (const CpmlPrimitive *primitive, + const CpmlPrimitive *primitive2, + CpmlPair *dest); +void cpml_primitive_offset (CpmlPrimitive *primitive, + double offset); CAIRO_END_DECLS diff --git a/cpml/cpml-segment.c b/cpml/cpml-segment.c index 8bbbd11a..fcb00556 100644 --- a/cpml/cpml-segment.c +++ b/cpml/cpml-segment.c @@ -308,7 +308,7 @@ cpml_segment_offset(CpmlSegment *segment, double offset) cpml_primitive_offset(&primitive, offset); if (!first_cycle) { - cpml_join(&last_primitive, &primitive); + cpml_primitive_join(&last_primitive, &primitive); primitive.org = cpml_primitive_get_point(&last_primitive, -1); } diff --git a/cpml/cpml.h b/cpml/cpml.h index cf24d0b6..947b078b 100644 --- a/cpml/cpml.h +++ b/cpml/cpml.h @@ -20,7 +20,6 @@ #ifndef __CPML_H__ #define __CPML_H__ -#include #include #include #include diff --git a/demo/cpml-demo.c b/demo/cpml-demo.c index 5a891721..fd889ca3 100644 --- a/demo/cpml-demo.c +++ b/demo/cpml-demo.c @@ -309,7 +309,7 @@ intersections(GtkWidget *widget, GdkEventExpose *event, gpointer data) cpml_primitive_from_segment(&primitive1, &segment1); cpml_primitive_from_segment(&primitive2, &segment2); - cpml_intersection(&primitive1, &primitive2, &intersection); + cpml_primitive_intersection(&primitive1, &primitive2, &intersection); cairo_arc(cr, intersection.x, intersection.y, 2.5, 0, 2 * M_PI); cairo_fill(cr); diff --git a/docs/cpml/cpml-docs.xml b/docs/cpml/cpml-docs.xml index 12229285..4c3fc2e8 100644 --- a/docs/cpml/cpml-docs.xml +++ b/docs/cpml/cpml-docs.xml @@ -10,23 +10,21 @@ - CPML core reference + Core reference - - CPML objects + + CPML constructs - - - - - - - Objects manipulation - + + Primitive types + + + + diff --git a/docs/cpml/cpml-sections.txt b/docs/cpml/cpml-sections.txt index ddcb39ea..88b11aa6 100644 --- a/docs/cpml/cpml-sections.txt +++ b/docs/cpml/cpml-sections.txt @@ -69,6 +69,8 @@ cpml_primitive_dump cpml_primitive_type_get_npoints cpml_primitive_pair_at cpml_primitive_vector_at +cpml_primitive_join +cpml_primitive_intersection cpml_primitive_offset @@ -78,6 +80,7 @@ cpml_primitive_offset cpml_line_type_get_npoints cpml_line_pair_at cpml_line_vector_at +cpml_line_intersection cpml_line_offset @@ -89,6 +92,8 @@ cpml_curve_pair_at_time cpml_curve_pair_at cpml_curve_vector_at_time cpml_curve_vector_at +cpml_curve_intersection +cpml_curve_intersection_with_line cpml_curve_offset @@ -100,10 +105,3 @@ cpml_close_pair_at cpml_close_vector_at cpml_close_offset - -
-action -cpml/cpml.h -cpml_join -cpml_intersection -
-- 2.11.4.GIT