[PATCH 1/1] Add cairo_sheer and family.

James Cloos cloos at jhcloos.com
Sat Jan 10 11:28:57 PST 2009


Sheering multiplies the matrix by [1 sx sy 1 0 0].

With the addition of the sheer operation, any matrix can be built
using the provided operations (translate, rotate, scale, sheer), 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                    |   41 +++++++++++++++++++++++++++++++++
 src/cairo.c                           |   25 ++++++++++++++++++++
 src/cairo.h                           |    3 ++
 src/cairoint.h                        |    5 ++++
 8 files changed, 130 insertions(+), 0 deletions(-)

diff --git a/doc/public/cairo-sections.txt b/doc/public/cairo-sections.txt
index bb64cd6..5b6889b 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_sheer
 cairo_matrix_init_rotate
 cairo_matrix_translate
 cairo_matrix_scale
+cairo_matrix_sheer
 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_sheer
 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..c22c5ce 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_sheer ##### -->
+<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_sheer ##### -->
+<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..cc3cd36 100644
--- a/doc/public/tmpl/cairo-transforms.sgml
+++ b/doc/public/tmpl/cairo-transforms.sgml
@@ -43,6 +43,16 @@ space</firstterm>.
 @sy: 
 
 
+<!-- ##### FUNCTION cairo_sheer ##### -->
+<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..c8d516c 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_sheer (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_sheer (&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_sheer (&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..3320696 100644
--- a/src/cairo-matrix.c
+++ b/src/cairo-matrix.c
@@ -219,6 +219,47 @@ cairo_matrix_scale (cairo_matrix_t *matrix, double sx, double sy)
 slim_hidden_def(cairo_matrix_scale);
 
 /**
+ * cairo_matrix_init_sheer:
+ * @matrix: a #cairo_matrix_t
+ * @sx: sheer factor in the X direction
+ * @sy: sheer factor in the Y direction
+ *
+ * Initializes @matrix to a transformation that sheers by @sx and @sy
+ * in the X and Y dimensions, respectively.
+ **/
+void
+cairo_matrix_init_sheer (cairo_matrix_t *matrix,
+			 double sx, double sy)
+{
+    cairo_matrix_init (matrix,
+		       1,  sx,
+		       sy, 1,
+		       0, 0);
+}
+slim_hidden_def(cairo_matrix_init_scale);
+
+/**
+ * cairo_matrix_sheer:
+ * @matrix: a #cairo_matrix_t
+ * @sx: sheer factor in the X direction
+ * @sy: sheer factor in the Y direction
+ *
+ * Applies sheering by @sx, @sy to the transformation in @matrix. The
+ * effect of the new transformation is to first sheer the coordinates
+ * by @sx and @sy, then apply the original transformation to the coordinates.
+ **/
+void
+cairo_matrix_sheer (cairo_matrix_t *matrix, double sx, double sy)
+{
+    cairo_matrix_t tmp;
+
+    cairo_matrix_init_sheer (&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..c81442d 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -1218,6 +1218,31 @@ cairo_scale (cairo_t *cr, double sx, double sy)
 slim_hidden_def (cairo_scale);
 
 /**
+ * cairo_sheer:
+ * @cr: a cairo context
+ * @sx: sheer factor for the X dimension
+ * @sy: sheer factor for the Y dimension
+ *
+ * Modifies the current transformation matrix (CTM) by sheering the X
+ * and Y user-space axes by @sx and @sy respectively. The sheering of
+ * the axes takes place after any existing transformation of user
+ * space.
+ **/
+void
+cairo_sheer (cairo_t *cr, double sx, double sy)
+{
+    cairo_status_t status;
+
+    if (cr->status)
+	return;
+
+    status = _cairo_gstate_sheer (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..c1f0614 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_sheer (cairo_t *cr, double sx, double sy);
+
+cairo_public void
 cairo_rotate (cairo_t *cr, double angle);
 
 cairo_public void
diff --git a/src/cairoint.h b/src/cairoint.h
index a67dff5..b4565f5 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_sheer (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_sheer);
 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_sheer);
 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