[PATCH 1/1] Add cairo_shear and family.

James Cloos cloos at jhcloos.com
Sat Jan 10 11:26:09 PST 2009


Shearing multiplies the matrix by [ sqrt(1+sx*sy) sx sy sqrt(1+sx*sy) 0 0 ].

For a shear in the X direction, use sy=0, for a shear in the
Y direction use sx=0.

The sx*sy component of the matrix preserves area.

With the addition of the shear operation, any matrix can be built
using the provided operations (translate, rotate, scale, shear), while
currently one has to resort to a full-matrix transform for some matrices.

Signed-off-by: James Cloos <cloos at jhcloos.com>
---
 doc/public/cairo-sections.txt         |    3 ++
 doc/public/tmpl/cairo-matrix.sgml     |   20 +++++++++++
 doc/public/tmpl/cairo-transforms.sgml |   10 +++++
 src/cairo-gstate.c                    |   23 ++++++++++++
 src/cairo-matrix.c                    |   60 +++++++++++++++++++++++++++++++++
 src/cairo.c                           |   33 ++++++++++++++++++
 src/cairo.h                           |    5 ++-
 src/cairoint.h                        |    5 +++
 8 files changed, 158 insertions(+), 1 deletions(-)

diff --git a/doc/public/cairo-sections.txt b/doc/public/cairo-sections.txt
index bb64cd6..a1c8841 100644
--- a/doc/public/cairo-sections.txt
+++ b/doc/public/cairo-sections.txt
@@ -262,9 +262,11 @@ cairo_matrix_init
 cairo_matrix_init_identity
 cairo_matrix_init_translate
 cairo_matrix_init_scale
+cairo_matrix_init_shear
 cairo_matrix_init_rotate
 cairo_matrix_translate
 cairo_matrix_scale
+cairo_matrix_shear
 cairo_matrix_rotate
 cairo_matrix_invert
 cairo_matrix_multiply
@@ -356,6 +358,7 @@ cairo_destroy_func_t
 <TITLE>transformations</TITLE>
 cairo_translate
 cairo_scale
+cairo_shear
 cairo_rotate
 cairo_transform
 cairo_set_matrix
diff --git a/doc/public/tmpl/cairo-matrix.sgml b/doc/public/tmpl/cairo-matrix.sgml
index 720cdac..7b61e35 100644
--- a/doc/public/tmpl/cairo-matrix.sgml
+++ b/doc/public/tmpl/cairo-matrix.sgml
@@ -87,6 +87,16 @@ Generic matrix operations
 @sy: 
 
 
+<!-- ##### FUNCTION cairo_matrix_init_shear ##### -->
+<para>
+
+</para>
+
+ at matrix: 
+ at sx: 
+ at sy: 
+
+
 <!-- ##### FUNCTION cairo_matrix_init_rotate ##### -->
 <para>
 
@@ -116,6 +126,16 @@ Generic matrix operations
 @sy: 
 
 
+<!-- ##### FUNCTION cairo_matrix_shear ##### -->
+<para>
+
+</para>
+
+ at matrix: 
+ at sx: 
+ at sy: 
+
+
 <!-- ##### FUNCTION cairo_matrix_rotate ##### -->
 <para>
 
diff --git a/doc/public/tmpl/cairo-transforms.sgml b/doc/public/tmpl/cairo-transforms.sgml
index 60c8ad9..798bd71 100644
--- a/doc/public/tmpl/cairo-transforms.sgml
+++ b/doc/public/tmpl/cairo-transforms.sgml
@@ -43,6 +43,16 @@ space</firstterm>.
 @sy: 
 
 
+<!-- ##### FUNCTION cairo_shear ##### -->
+<para>
+
+</para>
+
+ at cr: 
+ at sx: 
+ at sy: 
+
+
 <!-- ##### FUNCTION cairo_rotate ##### -->
 <para>
 
diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c
index c79e799..5b58ce9 100644
--- a/src/cairo-gstate.c
+++ b/src/cairo-gstate.c
@@ -635,6 +635,29 @@ _cairo_gstate_scale (cairo_gstate_t *gstate, double sx, double sy)
 }
 
 cairo_status_t
+_cairo_gstate_shear (cairo_gstate_t *gstate, double sx, double sy)
+{
+    cairo_matrix_t tmp;
+
+    if (! ISFINITE (sx) || ! ISFINITE (sy))
+	return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
+
+    _cairo_gstate_unset_scaled_font (gstate);
+
+    cairo_matrix_init_shear (&tmp, sx, sy);
+    cairo_matrix_multiply (&gstate->ctm, &tmp, &gstate->ctm);
+
+    /* paranoid check against gradual numerical instability */
+    if (! _cairo_matrix_is_invertible (&gstate->ctm))
+	return _cairo_error (CAIRO_STATUS_INVALID_MATRIX);
+
+    cairo_matrix_init_shear (&tmp, 1/sx, 1/sy);
+    cairo_matrix_multiply (&gstate->ctm_inverse, &gstate->ctm_inverse, &tmp);
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+cairo_status_t
 _cairo_gstate_rotate (cairo_gstate_t *gstate, double angle)
 {
     cairo_matrix_t tmp;
diff --git a/src/cairo-matrix.c b/src/cairo-matrix.c
index 6dfe537..2b75674 100644
--- a/src/cairo-matrix.c
+++ b/src/cairo-matrix.c
@@ -219,6 +219,66 @@ cairo_matrix_scale (cairo_matrix_t *matrix, double sx, double sy)
 slim_hidden_def(cairo_matrix_scale);
 
 /**
+ * cairo_matrix_init_shear:
+ * @matrix: a #cairo_matrix_t
+ * @sx: shear factor in the X direction
+ * @sy: shear factor in the Y direction
+ *
+ * Initializes @matrix to a transformation that shears by @sx and @sy
+ * in the X and Y dimensions, respectively.
+ *
+ * For a shear in the X direction, use sy=0, for a shear in the
+ * Y direction use sx=0.
+ *
+ * Shearing multiplies the current transformation by the matrix
+ * [sqrt(1+sx*sy) sx sy sqrt(1+sx*sy) 0 0].
+ *
+ * Since: 1.10
+ **/
+void
+cairo_matrix_init_shear (cairo_matrix_t *matrix,
+			 double sx, double sy)
+{
+    double rt1sxsy 1.0;
+    if (sx != 0.0 && sy != 0.0)
+	rt1sxsy = sqrt(sx * sy + 1.0);
+    cairo_matrix_init (matrix,
+		       rt1sxsy,  sx,
+		       sy, rt1sxsy,
+		       0, 0);
+}
+slim_hidden_def(cairo_matrix_init_scale);
+
+/**
+ * cairo_matrix_shear:
+ * @matrix: a #cairo_matrix_t
+ * @sx: shear factor in the X direction
+ * @sy: shear factor in the Y direction
+ *
+ * Applies shearing by @sx, @sy to the transformation in @matrix. The
+ * effect of the new transformation is to first shear the coordinates
+ * by @sx and @sy, then apply the original transformation to the coordinates.
+ *
+ * For a shear in the X direction, use sy=0, for a shear in the
+ * Y direction use sx=0.
+ *
+ * Shearing multiplies the current transformation by the matrix
+ * [sqrt(1+sx*sy) sx sy sqrt(1+sx*sy) 0 0].
+ *
+ * Since 1.10
+ **/
+void
+cairo_matrix_shear (cairo_matrix_t *matrix, double sx, double sy)
+{
+    cairo_matrix_t tmp;
+
+    cairo_matrix_init_shear (&tmp, sx, sy);
+
+    cairo_matrix_multiply (matrix, &tmp, matrix);
+}
+slim_hidden_def(cairo_matrix_scale);
+
+/**
  * cairo_matrix_init_rotate:
  * @matrix: a #cairo_matrix_t
  * @radians: angle of rotation, in radians. The direction of rotation
diff --git a/src/cairo.c b/src/cairo.c
index 4cdf685..3154e6c 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -1218,6 +1218,39 @@ cairo_scale (cairo_t *cr, double sx, double sy)
 slim_hidden_def (cairo_scale);
 
 /**
+ * cairo_shear:
+ * @cr: a cairo context
+ * @sx: shear factor for the X dimension
+ * @sy: shear factor for the Y dimension
+ *
+ * Modifies the current transformation matrix (CTM) by shearing the X
+ * and Y user-space axes by @sx and @sy respectively. The shearing of
+ * the axes takes place after any existing transformation of user
+ * space.
+ *
+ * For a shear in the X direction, use sy=0, for a shear in the
+ * Y direction use sx=0.
+ *
+ * Shearing multiplies the current transformation by the matrix
+ * [sqrt(1+sx*sy) sx sy sqrt(1+sx*sy) 0 0].
+ *
+ * Since: 1.10
+ **/
+void
+cairo_shear (cairo_t *cr, double sx, double sy)
+{
+    cairo_status_t status;
+
+    if (cr->status)
+	return;
+
+    status = _cairo_gstate_shear (cr->gstate, sx, sy);
+    if (unlikely (status))
+	_cairo_set_error (cr, status);
+}
+slim_hidden_def (cairo_scale);
+
+/**
  * cairo_rotate:
  * @cr: a cairo context
  * @angle: angle (in radians) by which the user-space axes will be
diff --git a/src/cairo.h b/src/cairo.h
index 8f57ae0..be86d5f 100644
--- a/src/cairo.h
+++ b/src/cairo.h
@@ -590,6 +590,9 @@ cairo_public void
 cairo_scale (cairo_t *cr, double sx, double sy);
 
 cairo_public void
+cairo_shear (cairo_t *cr, double sx, double sy);
+
+cairo_public void
 cairo_rotate (cairo_t *cr, double angle);
 
 cairo_public void
@@ -815,7 +818,7 @@ typedef struct _cairo_scaled_font cairo_scaled_font_t;
  *
  * A #cairo_font_face_t specifies all aspects of a font other
  * than the size or font matrix (a font matrix is used to distort
- * a font by sheering it or scaling it unequally in the two
+ * a font by shearing it or scaling it unequally in the two
  * directions) . A font face can be set on a #cairo_t by using
  * cairo_set_font_face(); the size and font matrix are set with
  * cairo_set_font_size() and cairo_set_font_matrix().
diff --git a/src/cairoint.h b/src/cairoint.h
index a67dff5..38a39fc 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -1120,6 +1120,9 @@ cairo_private cairo_status_t
 _cairo_gstate_scale (cairo_gstate_t *gstate, double sx, double sy);
 
 cairo_private cairo_status_t
+_cairo_gstate_shear (cairo_gstate_t *gstate, double sx, double sy);
+
+cairo_private cairo_status_t
 _cairo_gstate_rotate (cairo_gstate_t *gstate, double angle);
 
 cairo_private cairo_status_t
@@ -2579,10 +2582,12 @@ slim_hidden_proto (cairo_matrix_init);
 slim_hidden_proto (cairo_matrix_init_identity);
 slim_hidden_proto (cairo_matrix_init_rotate);
 slim_hidden_proto (cairo_matrix_init_scale);
+slim_hidden_proto (cairo_matrix_init_shear);
 slim_hidden_proto (cairo_matrix_init_translate);
 slim_hidden_proto (cairo_matrix_invert);
 slim_hidden_proto (cairo_matrix_multiply);
 slim_hidden_proto (cairo_matrix_scale);
+slim_hidden_proto (cairo_matrix_shear);
 slim_hidden_proto (cairo_matrix_transform_distance);
 slim_hidden_proto (cairo_matrix_transform_point);
 slim_hidden_proto (cairo_matrix_translate);
-- 
1.6.0.3.613.g9f8f13.dirty


--=-=-=

-- 
James Cloos <cloos at jhcloos.com>         OpenPGP: 1024D/ED7DAEA6

--=-=-=--


More information about the cairo mailing list