[cairo] Contribution to line join and end caps
Martin Horak
horakm at centrum.cz
Fri Aug 1 14:30:40 PDT 2008
Hello,
I am working on a project which uses the cairo library for primary graphics rendering.
Because I quickly needed a special (not currently available in the version 1.6.4) join and end
caps for lines, I implemented them myself. I added new two options to type cairo_line_join_t
(CAIRO_LINE_JOIN_TRIANGLE, CAIRO_LINE_JOIN_NONE) and one option to type cairo_line_cap_t
(CAIRO_LINE_CAP_TRIANGLE)
The patches for cairo.h and cairo-path-stroke.c files are attached. I hope they will be useful.
Regards,
Martin Horak
--- cairo.h 2008-04-08 00:30:32.000000000 +0200
+++ new\cairo.h 2008-08-01 10:19:34.343750000 +0200
@@ -495,6 +495,7 @@
* @CAIRO_LINE_CAP_BUTT: start(stop) the line exactly at the start(end) point
* @CAIRO_LINE_CAP_ROUND: use a round ending, the center of the circle is the end point
* @CAIRO_LINE_CAP_SQUARE: use squared ending, the center of the square is the end point
+ * @CAIRO_LINE_CAP_TRIANGLE: use triangle ending, the triangle vertex is half of line width from the end point
*
* Specifies how to render the endpoints of the path when stroking.
*
@@ -503,7 +504,8 @@
typedef enum _cairo_line_cap {
CAIRO_LINE_CAP_BUTT,
CAIRO_LINE_CAP_ROUND,
- CAIRO_LINE_CAP_SQUARE
+ CAIRO_LINE_CAP_SQUARE,
+ CAIRO_LINE_CAP_TRIANGLE
} cairo_line_cap_t;
cairo_public void
@@ -517,6 +519,9 @@
* joint point
* @CAIRO_LINE_JOIN_BEVEL: use a cut-off join, the join is cut off at half
* the line width from the joint point
+ * @CAIRO_LINE_JOIN_TRIANGLE: use a triangle join, the triangle vertex is at half
+ * of line width from the join point
+ * @CAIRO_LINE_JOIN_NONE: no line join
*
* Specifies how to render the junction of two lines when stroking.
*
@@ -525,7 +530,9 @@
typedef enum _cairo_line_join {
CAIRO_LINE_JOIN_MITER,
CAIRO_LINE_JOIN_ROUND,
- CAIRO_LINE_JOIN_BEVEL
+ CAIRO_LINE_JOIN_BEVEL,
+ CAIRO_LINE_JOIN_TRIANGLE,
+ CAIRO_LINE_JOIN_NONE
} cairo_line_join_t;
cairo_public void
--- cairo-path-stroke.c 2008-04-05 00:45:22.000000000 +0200
+++ new\cairo-path-stroke.c 2008-08-01 14:40:48.421875000 +0200
@@ -278,6 +278,10 @@
}
switch (stroker->style->line_join) {
+ case CAIRO_LINE_JOIN_NONE:
+ {
+ return CAIRO_STATUS_SUCCESS;
+ }
case CAIRO_LINE_JOIN_ROUND: {
int i;
int start, step, stop;
@@ -477,7 +481,59 @@
return _cairo_traps_tessellate_triangle (stroker->traps, tri);
}
- }
+ case CAIRO_LINE_JOIN_TRIANGLE: {
+ double x1, y1, x2, y2, x3, y3;
+ double d, douter;
+ double centerx, centery;
+
+ x1 = _cairo_fixed_to_double (inpt->x);
+ y1 = _cairo_fixed_to_double (inpt->y);
+ x2 = _cairo_fixed_to_double (outpt->x);
+ y2 = _cairo_fixed_to_double (outpt->y);
+ x3 = _cairo_fixed_to_double (in->point.x);
+ y3 = _cairo_fixed_to_double (in->point.y);
+
+ /* center point between inpt and outpt points */
+ centerx = ( x1 + x2 ) / 2.0;
+ centery = ( y1 + y2 ) / 2.0;
+
+ /* distance between inpt and in points */
+ douter = sqrt( ( x1 - x3 ) * ( x1 - x3 ) + ( y1 - y3 ) * ( y1 - y3 ) );
+
+ /* distance between center and in points */
+ d = sqrt( ( centerx - x3 ) * ( centerx - x3 ) + ( centery - y3 ) * ( centery - y3 ) );
+
+ if ( d )
+ {
+ double dx, dy;
+ cairo_point_t quad[4];
+ cairo_point_t outer;
+
+ /* extrapolate distance between in and center to outer point in cartesian space */
+ dx = ( x3 - centerx ) * douter / d;
+ dy = ( y3 - centery ) * douter / d;
+
+ outer.x = _cairo_fixed_from_double ( x3 - dx );
+ outer.y = _cairo_fixed_from_double ( y3 - dy );
+
+ quad[0] = in->point;
+ quad[1] = *inpt;
+ quad[2] = outer;
+ quad[3] = *outpt;
+
+ return _cairo_traps_tessellate_convex_quad (stroker->traps, quad);
+ }
+ else
+ {
+ /* bevel */
+ cairo_point_t tri[3];
+ tri[0] = in->point;
+ tri[1] = *inpt;
+ tri[2] = *outpt;
+ return _cairo_traps_tessellate_triangle (stroker->traps, tri);
+ }
+ }
+ }
}
static cairo_status_t
@@ -516,6 +572,29 @@
return _cairo_traps_tessellate_triangle (stroker->traps, tri);
}
+ case CAIRO_LINE_CAP_TRIANGLE: {
+ double dx, dy, x1, y1;
+ cairo_point_t outer;
+ cairo_point_t tri[3];
+
+ dx = f->usr_vector.x;
+ dy = f->usr_vector.y;
+ dx *= stroker->style->line_width / 2.0;
+ dy *= stroker->style->line_width / 2.0;
+ cairo_matrix_transform_distance (stroker->ctm, &dx, &dy);
+
+ x1 = _cairo_fixed_to_double( f->ccw.x + f->cw.x ) / 2.0 + dx;
+ y1 = _cairo_fixed_to_double( f->ccw.y + f->cw.y ) / 2.0 + dy;
+
+ outer.x = _cairo_fixed_from_double( x1 );
+ outer.y = _cairo_fixed_from_double( y1 );
+
+ tri[0] = outer;
+ tri[1] = f->cw;
+ tri[2] = f->ccw;
+
+ return _cairo_traps_tessellate_triangle (stroker->traps, tri);
+ }
case CAIRO_LINE_CAP_SQUARE: {
double dx, dy;
cairo_slope_t fvector;
More information about the cairo
mailing list