[cairo] Contribution to line join and end caps

horakm at centrum.cz horakm at centrum.cz
Fri Aug 1 14:43:27 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