[cairo] Contribution to line join and end caps

Martin Horák horakm at centrum.cz
Fri Aug 1 13:55:19 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_cap_t 
(CAIRO_LINE_JOIN_TRIANGLE, CAIRO_LINE_JOIN_NONE) and one option to cairo_line_join_t 
(CAIRO_LINE_CAP_TRIANGLE)
The patch for cairo.h and cairo-path-stroke.c files is attached - I hope it will be useful.

Regards,
Martin Horak

-------------- next part --------------
--- 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
-------------- next part --------------
--- 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 + dx;
+	y1 = _cairo_fixed_to_double( f->ccw.y + f->cw.y ) / 2 + 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