[librsvg] Use cairo_matrix_t



commit f93a2acceaa00191ef0b4f138d9c0496f054c262
Author: Christian Persch <chpe gnome org>
Date:   Fri Sep 16 01:16:27 2011 +0200

    Use cairo_matrix_t
    
    I've checked this quite carefully, but it still might contain
    stupid typo bugs ;-)

 Makefile.am         |    1 -
 rsvg-affine.c       |  193 ---------------------------------------------------
 rsvg-base.c         |   32 +++++----
 rsvg-cairo-clip.c   |   39 +++++-----
 rsvg-cairo-draw.c   |  125 ++++++++++++++++-----------------
 rsvg-cairo-render.c |   31 +++------
 rsvg-filter.c       |  157 +++++++++++++++++++++---------------------
 rsvg-filter.h       |    2 +-
 rsvg-marker.c       |   46 ++++++------
 rsvg-paint-server.c |   30 +++-----
 rsvg-paint-server.h |    6 +-
 rsvg-private.h      |   23 +------
 rsvg-structure.c    |   63 ++++++++---------
 rsvg-styles.c       |   86 ++++++++++++++---------
 rsvg-styles.h       |    6 +-
 15 files changed, 310 insertions(+), 530 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index 245c165..482cab9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -32,7 +32,6 @@ enum_sources = \
 	librsvg-enum-types.c
 
 librsvg_ RSVG_API_MAJOR_VERSION@_la_SOURCES = \
-	rsvg-affine.c		\
 	librsvg-features.c 	\
 	rsvg-bpath-util.c 	\
 	rsvg-bpath-util.h 	\
diff --git a/rsvg-base.c b/rsvg-base.c
index 454f20a..1e1f88a 100644
--- a/rsvg-base.c
+++ b/rsvg-base.c
@@ -2099,18 +2099,16 @@ rsvg_render_free (RsvgRender * render)
 }
 
 void
-rsvg_bbox_init (RsvgBbox * self, double *affine)
+rsvg_bbox_init (RsvgBbox * self, cairo_matrix_t *affine)
 {
-    int i;
     self->virgin = 1;
-    for (i = 0; i < 6; i++)
-        self->affine[i] = affine[i];
+    self->affine = *affine;
 }
 
 void
 rsvg_bbox_insert (RsvgBbox * dst, RsvgBbox * src)
 {
-    double affine[6];
+    cairo_matrix_t affine;
     double xmin, ymin;
     double xmax, ymax;
     int i;
@@ -2125,15 +2123,18 @@ rsvg_bbox_insert (RsvgBbox * dst, RsvgBbox * src)
         xmin = ymin = xmax = ymax = 0;
     }
 
-    _rsvg_affine_invert (affine, dst->affine);
-    _rsvg_affine_multiply (affine, src->affine, affine);
+    affine = dst->affine;
+    if (cairo_matrix_invert (&affine) != CAIRO_STATUS_SUCCESS)
+      return; //FIXMEchpe correct??
+
+    cairo_matrix_multiply (&affine, &src->affine, &affine);
 
     for (i = 0; i < 4; i++) {
         double rx, ry, x, y;
         rx = src->rect.x + src->rect.width * (double) (i % 2);
         ry = src->rect.y + src->rect.height * (double) (i / 2);
-        x = affine[0] * rx + affine[2] * ry + affine[4];
-        y = affine[1] * rx + affine[3] * ry + affine[5];
+        x = affine.xx * rx + affine.xy * ry + affine.x0;
+        y = affine.yx * rx + affine.yy * ry + affine.y0;
         if (dst->virgin) {
             xmin = xmax = x;
             ymin = ymax = y;
@@ -2158,7 +2159,7 @@ rsvg_bbox_insert (RsvgBbox * dst, RsvgBbox * src)
 void
 rsvg_bbox_clip (RsvgBbox * dst, RsvgBbox * src)
 {
-    double affine[6];
+    cairo_matrix_t affine;
 	double xmin, ymin;
 	double xmax, ymax;
     int i;
@@ -2173,15 +2174,18 @@ rsvg_bbox_clip (RsvgBbox * dst, RsvgBbox * src)
         xmin = ymin = xmax = ymax = 0;
     }
 
-    _rsvg_affine_invert (affine, dst->affine);
-    _rsvg_affine_multiply (affine, src->affine, affine);
+    affine = dst->affine;
+    if (cairo_matrix_invert (&affine) != CAIRO_STATUS_SUCCESS)
+      return;
+
+    cairo_matrix_multiply (&affine, &src->affine, &affine);
 
     for (i = 0; i < 4; i++) {
         double rx, ry, x, y;
         rx = src->rect.x + src->rect.width * (double) (i % 2);
         ry = src->rect.y + src->rect.height * (double) (i / 2);
-        x = affine[0] * rx + affine[2] * ry + affine[4];
-        y = affine[1] * rx + affine[3] * ry + affine[5];
+        x = affine.xx * rx + affine.xy * ry + affine.x0;
+        y = affine.yx * rx + affine.yy * ry + affine.y0;
         if (dst->virgin) {
             xmin = xmax = x;
             ymin = ymax = y;
diff --git a/rsvg-cairo-clip.c b/rsvg-cairo-clip.c
index ca87628..341ccf5 100644
--- a/rsvg-cairo-clip.c
+++ b/rsvg-cairo-clip.c
@@ -47,17 +47,17 @@ struct RsvgCairoClipRender {
 #define RSVG_CAIRO_CLIP_RENDER(render) (_RSVG_RENDER_CIC ((render), RSVG_RENDER_TYPE_CAIRO_CLIP, RsvgCairoClipRender))
 
 static void
-rsvg_cairo_clip_apply_affine (RsvgCairoClipRender *render, const double affine[6])
+rsvg_cairo_clip_apply_affine (RsvgCairoClipRender *render, cairo_matrix_t *affine)
 {
     RsvgCairoRender *cairo_render = &render->super;
     cairo_matrix_t matrix;
     gboolean nest = cairo_render->cr != cairo_render->initial_cr;
 
     cairo_matrix_init (&matrix,
-                       affine[0], affine[1],
-                       affine[2], affine[3],
-                       affine[4] + (nest ? 0 : render->parent->offset_x),
-                       affine[5] + (nest ? 0 : render->parent->offset_y));
+                       affine->xx, affine->yx,
+                       affine->xy, affine->yy,
+                       affine->x0 + (nest ? 0 : render->parent->offset_x),
+                       affine->y0 + (nest ? 0 : render->parent->offset_y));
     cairo_set_matrix (cairo_render->cr, &matrix);
 }
 
@@ -73,7 +73,7 @@ rsvg_cairo_clip_render_path (RsvgDrawingCtx * ctx, const RsvgBpathDef * bpath_de
 
     cr = cairo_render->cr;
 
-    rsvg_cairo_clip_apply_affine (render, state->affine);
+    rsvg_cairo_clip_apply_affine (render, &state->affine);
 
     cairo_set_fill_rule (cr, rsvg_current_state (ctx)->clip_rule);
 
@@ -158,22 +158,22 @@ void
 rsvg_cairo_clip (RsvgDrawingCtx * ctx, RsvgClipPath * clip, RsvgBbox * bbox)
 {
     RsvgCairoRender *save = RSVG_CAIRO_RENDER (ctx->render);
-    double affinesave[6];
-    int i;
+    cairo_matrix_t affinesave;
+
     ctx->render = rsvg_cairo_clip_render_new (save->cr, save);
 
     /* Horribly dirty hack to have the bbox premultiplied to everything */
     if (clip->units == objectBoundingBox) {
-        double bbtransform[6];
-        bbtransform[0] = bbox->rect.width;
-        bbtransform[1] = 0.;
-        bbtransform[2] = 0.;
-        bbtransform[3] = bbox->rect.height;
-        bbtransform[4] = bbox->rect.x;
-        bbtransform[5] = bbox->rect.y;
-        for (i = 0; i < 6; i++)
-            affinesave[i] = clip->super.state->affine[i];
-        _rsvg_affine_multiply (clip->super.state->affine, bbtransform, clip->super.state->affine);
+        cairo_matrix_t bbtransform;
+        cairo_matrix_init (&bbtransform,
+                           bbox->rect.width,
+                           0,
+                           0,
+                           bbox->rect.height,
+                           bbox->rect.x,
+                           bbox->rect.y);
+        affinesave = clip->super.state->affine;
+        cairo_matrix_multiply (&clip->super.state->affine, &bbtransform, &clip->super.state->affine);
     }
 
     rsvg_state_push (ctx);
@@ -181,8 +181,7 @@ rsvg_cairo_clip (RsvgDrawingCtx * ctx, RsvgClipPath * clip, RsvgBbox * bbox)
     rsvg_state_pop (ctx);
 
     if (clip->units == objectBoundingBox)
-        for (i = 0; i < 6; i++)
-            clip->super.state->affine[i] = affinesave[i];
+        clip->super.state->affine = affinesave;
 
     g_free (ctx->render);
     cairo_clip (save->cr);
diff --git a/rsvg-cairo-draw.c b/rsvg-cairo-draw.c
index 561010c..faa3294 100644
--- a/rsvg-cairo-draw.c
+++ b/rsvg-cairo-draw.c
@@ -100,9 +100,7 @@ _set_source_rsvg_linear_gradient (RsvgDrawingCtx * ctx,
     if (linear->obj_bbox)
         _rsvg_pop_view_box (ctx);
 
-    cairo_matrix_init (&matrix,
-                       linear->affine[0], linear->affine[1],
-                       linear->affine[2], linear->affine[3], linear->affine[4], linear->affine[5]);
+    matrix = linear->affine;
     if (linear->obj_bbox) {
         cairo_matrix_t bboxmatrix;
         cairo_matrix_init (&bboxmatrix, bbox.rect.width, 0, 0, bbox.rect.height,
@@ -147,9 +145,7 @@ _set_source_rsvg_radial_gradient (RsvgDrawingCtx * ctx,
     if (radial->obj_bbox)
         _rsvg_pop_view_box (ctx);
 
-    cairo_matrix_init (&matrix,
-                       radial->affine[0], radial->affine[1],
-                       radial->affine[2], radial->affine[3], radial->affine[4], radial->affine[5]);
+    matrix = radial->affine;
     if (radial->obj_bbox) {
         cairo_matrix_t bboxmatrix;
         cairo_matrix_init (&bboxmatrix, bbox.rect.width, 0, 0, bbox.rect.height,
@@ -199,16 +195,14 @@ _set_source_rsvg_pattern (RsvgDrawingCtx * ctx,
     cairo_pattern_t *pattern;
     cairo_surface_t *surface;
     cairo_matrix_t matrix;
-    int i;
-    double affine[6], caffine[6], bbwscale, bbhscale, scwscale, schscale;
-    double taffine[6], patternw, patternh, patternx, patterny;
+    cairo_matrix_t affine, caffine, taffine;
+    double bbwscale, bbhscale, scwscale, schscale;
+    double patternw, patternh, patternx, patterny;
     int pw, ph;
 
     rsvg_pattern = &local_pattern;
     rsvg_pattern_fix_fallback (rsvg_pattern);
     cr_render = render->cr;
-    _rsvg_affine_identity (affine);
-    _rsvg_affine_identity (caffine);
 
     if (rsvg_pattern->obj_bbox)
         _rsvg_push_view_box (ctx, 1., 1.);
@@ -233,10 +227,10 @@ _set_source_rsvg_pattern (RsvgDrawingCtx * ctx,
         bbhscale = 1.0;
     }
 
-    _rsvg_affine_multiply (taffine, rsvg_pattern->affine, rsvg_current_state (ctx)->affine);
+    cairo_matrix_multiply (&taffine, &rsvg_pattern->affine, &rsvg_current_state (ctx)->affine);
 
-    scwscale = sqrt (taffine[0] * taffine[0] + taffine[2] * taffine[2]);
-    schscale = sqrt (taffine[1] * taffine[1] + taffine[3] * taffine[3]);
+    scwscale = sqrt (taffine.xx * taffine.xx + taffine.xy * taffine.xy);
+    schscale = sqrt (taffine.yx * taffine.yx + taffine.yy * taffine.yy);
 
     pw = patternw * bbwscale * scwscale;
     ph = patternh * bbhscale * schscale;
@@ -251,15 +245,15 @@ _set_source_rsvg_pattern (RsvgDrawingCtx * ctx,
     /* Create the pattern coordinate system */
     if (rsvg_pattern->obj_bbox) {
         /* subtract the pattern origin */
-        affine[4] = bbox.rect.x + patternx * bbox.rect.width;
-        affine[5] = bbox.rect.y + patterny * bbox.rect.height;
+        cairo_matrix_init_translate (&affine,
+                                     bbox.rect.x + patternx * bbox.rect.width,
+                                     bbox.rect.y + patterny * bbox.rect.height);
     } else {
         /* subtract the pattern origin */
-        affine[4] = patternx;
-        affine[5] = patterny;
+        cairo_matrix_init_translate (&affine, patternx, patterny);
     }
     /* Apply the pattern transform */
-    _rsvg_affine_multiply (affine, affine, rsvg_pattern->affine);
+    cairo_matrix_multiply (&affine, &affine, &rsvg_pattern->affine);
 
     /* Create the pattern contents coordinate system */
     if (rsvg_pattern->vbox.active) {
@@ -276,24 +270,27 @@ _set_source_rsvg_pattern (RsvgDrawingCtx * ctx,
         x -= rsvg_pattern->vbox.rect.x * w / rsvg_pattern->vbox.rect.width;
         y -= rsvg_pattern->vbox.rect.y * h / rsvg_pattern->vbox.rect.height;
 
-        caffine[0] = w / rsvg_pattern->vbox.rect.width;
-        caffine[3] = h / rsvg_pattern->vbox.rect.height;
-        caffine[4] = x;
-        caffine[5] = y;
+        cairo_matrix_init (&caffine,
+                           w / rsvg_pattern->vbox.rect.width,
+                           0,
+                           0,
+                           h / rsvg_pattern->vbox.rect.height,
+                           x,
+                           y);
         _rsvg_push_view_box (ctx, rsvg_pattern->vbox.rect.width, rsvg_pattern->vbox.rect.height);
     } else if (rsvg_pattern->obj_cbbox) {
         /* If coords are in terms of the bounding box, use them */
-        caffine[0] = bbox.rect.width;
-        caffine[3] = bbox.rect.height;
+        cairo_matrix_init_scale (&caffine, bbox.rect.width, bbox.rect.height);
         _rsvg_push_view_box (ctx, 1., 1.);
     }
 
     if (scwscale != 1.0 || schscale != 1.0) {
-        double scalematrix[6];
-        _rsvg_affine_scale (scalematrix, scwscale, schscale);
-        _rsvg_affine_multiply (caffine, caffine, scalematrix);
-        _rsvg_affine_scale (scalematrix, 1. / scwscale, 1. / schscale);
-        _rsvg_affine_multiply (affine, scalematrix, affine);
+        cairo_matrix_t scalematrix;
+
+        cairo_matrix_init_scale (&scalematrix, scwscale, schscale);
+        cairo_matrix_multiply (&caffine, &caffine, &scalematrix);
+        cairo_matrix_init_scale (&scalematrix, 1. / scwscale, 1. / schscale);
+        cairo_matrix_multiply (&affine, &scalematrix, &affine);
     }
 
     /* Draw to another surface */
@@ -301,9 +298,8 @@ _set_source_rsvg_pattern (RsvgDrawingCtx * ctx,
 
     /* Set up transformations to be determined by the contents units */
     rsvg_state_push (ctx);
-    for (i = 0; i < 6; i++)
-        rsvg_current_state (ctx)->personal_affine[i] =
-            rsvg_current_state (ctx)->affine[i] = caffine[i];
+    rsvg_current_state (ctx)->personal_affine =
+            rsvg_current_state (ctx)->affine = caffine;
 
     /* Draw everything */
     _rsvg_node_draw_children ((RsvgNode *) rsvg_pattern, ctx, 2);
@@ -316,10 +312,10 @@ _set_source_rsvg_pattern (RsvgDrawingCtx * ctx,
     pattern = cairo_pattern_create_for_surface (surface);
     cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
 
-    cairo_matrix_init (&matrix, affine[0], affine[1], affine[2], affine[3], affine[4], affine[5]);
+    matrix = affine;
+    if (cairo_matrix_invert (&matrix) != CAIRO_STATUS_SUCCESS)
+      goto out;
 
-
-    cairo_matrix_invert (&matrix);
     cairo_pattern_set_matrix (pattern, &matrix);
     cairo_pattern_set_filter (pattern, CAIRO_FILTER_BEST);
 
@@ -328,6 +324,8 @@ _set_source_rsvg_pattern (RsvgDrawingCtx * ctx,
     cairo_pattern_destroy (pattern);
     cairo_destroy (cr_pattern);
     cairo_surface_destroy (surface);
+
+  out:
     if (rsvg_pattern->obj_cbbox || rsvg_pattern->vbox.active)
         _rsvg_pop_view_box (ctx);
 }
@@ -356,17 +354,17 @@ _set_source_rsvg_paint_server (RsvgDrawingCtx * ctx,
 }
 
 static void
-_set_rsvg_affine (RsvgCairoRender * render, const double affine[6])
+_set_rsvg_affine (RsvgCairoRender * render, cairo_matrix_t *affine)
 {
     cairo_t * cr = render->cr;
     cairo_matrix_t matrix;
     gboolean nest = cr != render->initial_cr;
 
     cairo_matrix_init (&matrix,
-                       affine[0], affine[1],
-                       affine[2], affine[3],
-                       affine[4] + (nest ? 0 : render->offset_x),
-                       affine[5] + (nest ? 0 : render->offset_y));
+                       affine->xx, affine->yx,
+                       affine->xy, affine->yy,
+                       affine->x0 + (nest ? 0 : render->offset_x),
+                       affine->y0 + (nest ? 0 : render->offset_y));
     cairo_set_matrix (cr, &matrix);
 }
 
@@ -394,11 +392,11 @@ rsvg_cairo_render_pango_layout (RsvgDrawingCtx * ctx, PangoLayout * layout, doub
 
     cairo_set_antialias (render->cr, state->text_rendering_type);
 
-    _set_rsvg_affine (render, state->affine);
+    _set_rsvg_affine (render, &state->affine);
 
     pango_layout_get_extents (layout, &ink, NULL);
 
-    rsvg_bbox_init (&bbox, state->affine);
+    rsvg_bbox_init (&bbox, &state->affine);
     bbox.rect.x = x + ink.x / (double)PANGO_SCALE;
     bbox.rect.y = y + ink.y / (double)PANGO_SCALE;
     bbox.rect.width = ink.width / (double)PANGO_SCALE;
@@ -464,7 +462,7 @@ rsvg_cairo_render_path (RsvgDrawingCtx * ctx, const RsvgBpathDef * bpath_def)
 
     cairo_set_antialias (cr, state->shape_rendering_type);
 
-    _set_rsvg_affine (render, state->affine);
+    _set_rsvg_affine (render, &state->affine);
 
     cairo_set_line_width (cr, _rsvg_css_normalize_length (&state->stroke_width, ctx, 'h'));
     cairo_set_miter_limit (cr, state->miter_limit);
@@ -492,7 +490,7 @@ rsvg_cairo_render_path (RsvgDrawingCtx * ctx, const RsvgBpathDef * bpath_def)
         }
     }
 
-    rsvg_bbox_init (&bbox, state->affine);
+    rsvg_bbox_init (&bbox, &state->affine);
 
     backup_tolerance = cairo_get_tolerance (cr);
     cairo_set_tolerance (cr, 1.0);
@@ -502,7 +500,7 @@ rsvg_cairo_render_path (RsvgDrawingCtx * ctx, const RsvgBpathDef * bpath_def)
 
     if (state->fill != NULL) {
         RsvgBbox fb;
-        rsvg_bbox_init (&fb, state->affine);
+        rsvg_bbox_init (&fb, &state->affine);
         cairo_fill_extents (cr, &fb.rect.x, &fb.rect.y, &fb.rect.width, &fb.rect.height);
         fb.rect.width -= fb.rect.x;
         fb.rect.height -= fb.rect.y;
@@ -511,7 +509,7 @@ rsvg_cairo_render_path (RsvgDrawingCtx * ctx, const RsvgBpathDef * bpath_def)
     }
     if (state->stroke != NULL) {
         RsvgBbox sb;
-        rsvg_bbox_init (&sb, state->affine);
+        rsvg_bbox_init (&sb, &state->affine);
         cairo_stroke_extents (cr, &sb.rect.x, &sb.rect.y, &sb.rect.width, &sb.rect.height);
         sb.rect.width -= sb.rect.x;
         sb.rect.height -= sb.rect.y;
@@ -589,14 +587,14 @@ rsvg_cairo_render_image (RsvgDrawingCtx * ctx, const GdkPixbuf * pixbuf,
     if (!cairo_pixels)
         return;
 
-    rsvg_bbox_init (&bbox, state->affine);
+    rsvg_bbox_init (&bbox, &state->affine);
     bbox.rect.x = pixbuf_x;
     bbox.rect.y = pixbuf_y;
     bbox.rect.width = w;
     bbox.rect.height = h;
     bbox.virgin = 0;
 
-    _set_rsvg_affine (render, state->affine);
+    _set_rsvg_affine (render, &state->affine);
     cairo_scale (render->cr, w / dwidth, h / dheight);
     pixbuf_x *= dwidth / w;
     pixbuf_y *= dheight / h;
@@ -696,7 +694,7 @@ rsvg_cairo_generate_mask (cairo_t * cr, RsvgMask * self, RsvgDrawingCtx * ctx, R
     guint8 *pixels;
     guint32 width = render->width, height = render->height;
     guint32 rowstride = width * 4, row, i;
-    double affinesave[6];
+    cairo_matrix_t affinesave;
     double sx, sy, sw, sh;
     gboolean nest = cr != render->initial_cr;
 
@@ -734,16 +732,16 @@ rsvg_cairo_generate_mask (cairo_t * cr, RsvgMask * self, RsvgDrawingCtx * ctx, R
 
     /* Horribly dirty hack to have the bbox premultiplied to everything */
     if (self->contentunits == objectBoundingBox) {
-        double bbtransform[6];
-        bbtransform[0] = bbox->rect.width;
-        bbtransform[1] = 0.;
-        bbtransform[2] = 0.;
-        bbtransform[3] = bbox->rect.height;
-        bbtransform[4] = bbox->rect.x;
-        bbtransform[5] = bbox->rect.y;
-        for (i = 0; i < 6; i++)
-            affinesave[i] = self->super.state->affine[i];
-        _rsvg_affine_multiply (self->super.state->affine, bbtransform, self->super.state->affine);
+        cairo_matrix_t bbtransform;
+        cairo_matrix_init (&bbtransform,
+                           bbox->rect.width,
+                           0,
+                           0,
+                           bbox->rect.height,
+                           bbox->rect.x,
+                           bbox->rect.y);
+        affinesave = self->super.state->affine;
+        cairo_matrix_multiply (&self->super.state->affine, &bbtransform, &self->super.state->affine);
         _rsvg_push_view_box (ctx, 1, 1);
     }
 
@@ -753,8 +751,7 @@ rsvg_cairo_generate_mask (cairo_t * cr, RsvgMask * self, RsvgDrawingCtx * ctx, R
 
     if (self->contentunits == objectBoundingBox) {
         _rsvg_pop_view_box (ctx);
-        for (i = 0; i < 6; i++)
-            self->super.state->affine[i] = affinesave[i];
+        self->super.state->affine = affinesave;
     }
 
     render->cr = save_cr;
@@ -852,7 +849,7 @@ rsvg_cairo_push_render_stack (RsvgDrawingCtx * ctx)
     bbox = g_new (RsvgBbox, 1);
     *bbox = render->bbox;
     render->bb_stack = g_list_prepend (render->bb_stack, bbox);
-    rsvg_bbox_init (&render->bbox, state->affine);
+    rsvg_bbox_init (&render->bbox, &state->affine);
 }
 
 void
@@ -953,7 +950,7 @@ rsvg_cairo_add_clipping_rect (RsvgDrawingCtx * ctx, double x, double y, double w
     RsvgCairoRender *render = RSVG_CAIRO_RENDER (ctx->render);
     cairo_t *cr = render->cr;
 
-    _set_rsvg_affine (render, rsvg_current_state (ctx)->affine);
+    _set_rsvg_affine (render, &rsvg_current_state (ctx)->affine);
 
     cairo_rectangle (cr, x, y, w, h);
     cairo_clip (cr);
diff --git a/rsvg-cairo-render.c b/rsvg-cairo-render.c
index f4eac23..8edf768 100644
--- a/rsvg-cairo-render.c
+++ b/rsvg-cairo-render.c
@@ -116,8 +116,8 @@ rsvg_cairo_new_drawing_ctx (cairo_t * cr, RsvgHandle * handle)
     RsvgDrawingCtx *draw;
     RsvgCairoRender *render;
     RsvgState *state;
-    cairo_matrix_t cairo_transform;
-    double affine[6], bbx0, bby0, bbx1, bby1;
+    cairo_matrix_t affine;
+    double bbx0, bby0, bbx1, bby1;
 
     rsvg_handle_get_dimensions (handle, &data);
     if (data.width == 0 || data.height == 0)
@@ -125,12 +125,12 @@ rsvg_cairo_new_drawing_ctx (cairo_t * cr, RsvgHandle * handle)
 
     draw = g_new (RsvgDrawingCtx, 1);
 
-    cairo_get_matrix (cr, &cairo_transform);
+    cairo_get_matrix (cr, &affine);
 
     /* find bounding box of image as transformed by the current cairo context
      * The size of this bounding box determines the size of the intermediate
      * surfaces allocated during drawing. */
-    rsvg_cairo_transformed_image_bounding_box (&cairo_transform,
+    rsvg_cairo_transformed_image_bounding_box (&affine,
                                                data.width, data.height,
                                                &bbx0, &bby0, &bbx1, &bby1);
 
@@ -159,30 +159,19 @@ rsvg_cairo_new_drawing_ctx (cairo_t * cr, RsvgHandle * handle)
     state = rsvg_current_state (draw);
 
     /* apply cairo transformation to our affine transform */
-    affine[0] = cairo_transform.xx;
-    affine[1] = cairo_transform.yx;
-    affine[2] = cairo_transform.xy;
-    affine[3] = cairo_transform.yy;
-    affine[4] = cairo_transform.x0;
-    affine[5] = cairo_transform.y0;
-    _rsvg_affine_multiply (state->affine, affine, state->affine);
+    cairo_matrix_multiply (&state->affine, &affine, &state->affine);
 
     /* scale according to size set by size_func callback */
-    affine[0] = data.width / data.em;
-    affine[1] = 0;
-    affine[2] = 0;
-    affine[3] = data.height / data.ex;
-    affine[4] = 0;
-    affine[5] = 0;
-    _rsvg_affine_multiply (state->affine, affine, state->affine);
+    cairo_matrix_init_scale (&affine, data.width / data.em, data.height / data.ex);
+    cairo_matrix_multiply (&state->affine, &affine, &state->affine);
 
     /* adjust transform so that the corner of the bounding box above is
      * at (0,0) - we compensate for this in _set_rsvg_affine() in
      * rsvg-cairo-render.c and a few other places */
-    state->affine[4] -= render->offset_x;
-    state->affine[5] -= render->offset_y;
+    state->affine.x0 -= render->offset_x;
+    state->affine.y0 -= render->offset_y;
 
-    rsvg_bbox_init (&((RsvgCairoRender *) draw->render)->bbox, state->affine);
+    rsvg_bbox_init (&((RsvgCairoRender *) draw->render)->bbox, &state->affine);
 
     return draw;
 }
diff --git a/rsvg-filter.c b/rsvg-filter.c
index a918f9f..e63a440 100644
--- a/rsvg-filter.c
+++ b/rsvg-filter.c
@@ -59,8 +59,8 @@ struct _RsvgFilterContext {
     GdkPixbuf *source;
     GdkPixbuf *bg;
     RsvgFilterPrimitiveOutput lastresult;
-    double affine[6];
-    double paffine[6];
+    cairo_matrix_t affine;
+    cairo_matrix_t paffine;
     int channelmap[4];
     RsvgDrawingCtx *ctx;
 };
@@ -89,11 +89,11 @@ static RsvgIRect
 rsvg_filter_primitive_get_bounds (RsvgFilterPrimitive * self, RsvgFilterContext * ctx)
 {
     RsvgBbox box, otherbox;
-    double affine[6];
+    cairo_matrix_t affine;
 
-    _rsvg_affine_identity (affine);
-    rsvg_bbox_init (&box, affine);
-    rsvg_bbox_init (&otherbox, ctx->affine);
+    cairo_matrix_init_identity (&affine);
+    rsvg_bbox_init (&box, &affine);
+    rsvg_bbox_init (&otherbox, &ctx->affine);
     otherbox.virgin = 0;
     if (ctx->filter->filterunits == objectBoundingBox)
         _rsvg_push_view_box (ctx->ctx, 1., 1.);
@@ -110,7 +110,7 @@ rsvg_filter_primitive_get_bounds (RsvgFilterPrimitive * self, RsvgFilterContext
         if (self->x.factor != 'n' || self->y.factor != 'n' ||
             self->width.factor != 'n' || self->height.factor != 'n') {
 
-            rsvg_bbox_init (&otherbox, ctx->paffine);
+            rsvg_bbox_init (&otherbox, &ctx->paffine);
             otherbox.virgin = 0;
             if (ctx->filter->primitiveunits == objectBoundingBox)
                 _rsvg_push_view_box (ctx->ctx, 1., 1.);
@@ -135,7 +135,7 @@ rsvg_filter_primitive_get_bounds (RsvgFilterPrimitive * self, RsvgFilterContext
             rsvg_bbox_clip (&box, &otherbox);
         }
 
-    rsvg_bbox_init (&otherbox, affine);
+    rsvg_bbox_init (&otherbox, &affine);
     otherbox.virgin = 0;
     otherbox.rect.x = 0;
     otherbox.rect.y = 0;
@@ -214,7 +214,6 @@ static void
 rsvg_filter_fix_coordinate_system (RsvgFilterContext * ctx, RsvgState * state, RsvgBbox bbox)
 {
     int x, y, height, width;
-    int i;
 
     x = bbox.rect.x;
     y = bbox.rect.y;
@@ -224,17 +223,17 @@ rsvg_filter_fix_coordinate_system (RsvgFilterContext * ctx, RsvgState * state, R
     ctx->width = gdk_pixbuf_get_width (ctx->source);
     ctx->height = gdk_pixbuf_get_height (ctx->source);
 
-    for (i = 0; i < 6; i++)
-        ctx->affine[i] = state->affine[i];
+    ctx->affine = state->affine;
     if (ctx->filter->filterunits == objectBoundingBox) {
-        double affine[6] = { width, 0, 0, height, x, y };
-        _rsvg_affine_multiply (ctx->affine, affine, ctx->affine);
+        cairo_matrix_t affine;
+        cairo_matrix_init (&affine, width, 0, 0, height, x, y);
+        cairo_matrix_multiply (&ctx->affine, &affine, &ctx->affine);
     }
-    for (i = 0; i < 6; i++)
-        ctx->paffine[i] = state->affine[i];
+    ctx->paffine = state->affine;
     if (ctx->filter->primitiveunits == objectBoundingBox) {
-        double affine[6] = { width, 0, 0, height, x, y };
-        _rsvg_affine_multiply (ctx->paffine, affine, ctx->paffine);
+        cairo_matrix_t affine;
+        cairo_matrix_init (&affine, width, 0, 0, height, x, y);
+        cairo_matrix_multiply (&ctx->paffine, &affine, &ctx->paffine);
     }
 }
 
@@ -339,11 +338,9 @@ rsvg_alpha_blt (GdkPixbuf * src, gint srcx, gint srcy, gint srcwidth,
 
 void
 rsvg_art_affine_image (const GdkPixbuf * img, GdkPixbuf * intermediate,
-                       double *affine, double w, double h)
+                       cairo_matrix_t *affine, double w, double h)
 {
-    gdouble tmp_affine[6];
-    gdouble inv_affine[6];
-    gdouble raw_inv_affine[6];
+    cairo_matrix_t inv_affine, raw_inv_affine;
     gint intstride;
     gint basestride;
     gint basex, basey;
@@ -371,28 +368,26 @@ rsvg_art_affine_image (const GdkPixbuf * img, GdkPixbuf * intermediate,
     intpix = gdk_pixbuf_get_pixels (intermediate);
     basebpp = has_alpha ? 4 : 3;
 
-    _rsvg_affine_invert (raw_inv_affine, affine);
-
-    /*scale to w and h */
-    tmp_affine[0] = (double) w;
-    tmp_affine[3] = (double) h;
-    tmp_affine[1] = tmp_affine[2] = tmp_affine[4] = tmp_affine[5] = 0;
-    _rsvg_affine_multiply (tmp_affine, tmp_affine, affine);
-
-    _rsvg_affine_invert (inv_affine, tmp_affine);
+    raw_inv_affine = *affine;
+    if (cairo_matrix_invert (&raw_inv_affine) != CAIRO_STATUS_SUCCESS)
+      return;
 
+    cairo_matrix_init_scale (&inv_affine, w, h);
+    cairo_matrix_multiply (&inv_affine, &inv_affine, affine);
+    if (cairo_matrix_invert (&inv_affine) != CAIRO_STATUS_SUCCESS)
+      return;
 
     /*apply the transformation */
     for (i = 0; i < iwidth; i++)
         for (j = 0; j < iheight; j++) {
-            fbasex = (inv_affine[0] * (double) i + inv_affine[2] * (double) j +
-                      inv_affine[4]) * (double) width;
-            fbasey = (inv_affine[1] * (double) i + inv_affine[3] * (double) j +
-                      inv_affine[5]) * (double) height;
+            fbasex = (inv_affine.xx * (double) i + inv_affine.xy * (double) j +
+                      inv_affine.x0) * (double) width;
+            fbasey = (inv_affine.yx * (double) i + inv_affine.yy * (double) j +
+                      inv_affine.y0) * (double) height;
             basex = floor (fbasex);
             basey = floor (fbasey);
-            rawx = raw_inv_affine[0] * i + raw_inv_affine[2] * j + raw_inv_affine[4];
-            rawy = raw_inv_affine[1] * i + raw_inv_affine[3] * j + raw_inv_affine[5];
+            rawx = raw_inv_affine.xx * i + raw_inv_affine.xy * j + raw_inv_affine.x0;
+            rawy = raw_inv_affine.yx * i + raw_inv_affine.yy * j + raw_inv_affine.y0;
             if (rawx < 0 || rawy < 0 || rawx >= w ||
                 rawy >= h || basex < 0 || basey < 0 || basex >= width || basey >= height) {
                 for (k = 0; k < 4; k++)
@@ -1041,12 +1036,12 @@ rsvg_filter_primitive_convolve_matrix_render (RsvgFilterPrimitive * self, RsvgFi
     height = gdk_pixbuf_get_height (in);
     width = gdk_pixbuf_get_width (in);
 
-    targetx = upself->targetx * ctx->paffine[0];
-    targety = upself->targety * ctx->paffine[3];
+    targetx = upself->targetx * ctx->paffine.xx;
+    targety = upself->targety * ctx->paffine.yy;
 
     if (upself->dx != 0 || upself->dy != 0) {
-        dx = upself->dx * ctx->paffine[0];
-        dy = upself->dy * ctx->paffine[3];
+        dx = upself->dx * ctx->paffine.xx;
+        dy = upself->dy * ctx->paffine.yy;
     } else
         dx = dy = 1;
 
@@ -1413,8 +1408,8 @@ rsvg_filter_primitive_gaussian_blur_render (RsvgFilterPrimitive * self, RsvgFilt
                                        gdk_pixbuf_get_width (in), gdk_pixbuf_get_height (in));
 
     /* scale the SD values */
-    sdx = upself->sdx * ctx->paffine[0];
-    sdy = upself->sdy * ctx->paffine[3];
+    sdx = upself->sdx * ctx->paffine.xx;
+    sdy = upself->sdy * ctx->paffine.yy;
 
     fast_blur (in, output, sdx, sdy, boundarys, op);
 
@@ -1532,8 +1527,8 @@ rsvg_filter_primitive_offset_render (RsvgFilterPrimitive * self, RsvgFilterConte
     dx = _rsvg_css_normalize_length (&upself->dx, ctx->ctx, 'w');
     dy = _rsvg_css_normalize_length (&upself->dy, ctx->ctx, 'v');
 
-    ox = ctx->paffine[0] * dx + ctx->paffine[2] * dy;
-    oy = ctx->paffine[1] * dx + ctx->paffine[3] * dy;
+    ox = ctx->paffine.xx * dx + ctx->paffine.xy * dy;
+    oy = ctx->paffine.yx * dx + ctx->paffine.yy * dy;
 
     for (y = boundarys.y0; y < boundarys.y1; y++)
         for (x = boundarys.x0; x < boundarys.x1; x++) {
@@ -2328,8 +2323,8 @@ rsvg_filter_primitive_erode_render (RsvgFilterPrimitive * self, RsvgFilterContex
     rowstride = gdk_pixbuf_get_rowstride (in);
 
     /* scale the radius values */
-    kx = upself->rx * ctx->paffine[0];
-    ky = upself->ry * ctx->paffine[3];
+    kx = upself->rx * ctx->paffine.xx;
+    ky = upself->ry * ctx->paffine.yy;
 
     output = _rsvg_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, width, height);
 
@@ -2848,13 +2843,13 @@ rsvg_filter_primitive_displacement_map_render (RsvgFilterPrimitive * self, RsvgF
     for (y = boundarys.y0; y < boundarys.y1; y++)
         for (x = boundarys.x0; x < boundarys.x1; x++) {
             if (xch != 4)
-                ox = x + upself->scale * ctx->paffine[0] *
+                ox = x + upself->scale * ctx->paffine.xx *
                     ((double) in2_pixels[y * rowstride + x * 4 + xch] / 255.0 - 0.5);
             else
                 ox = x;
 
             if (ych != 4)
-                oy = y + upself->scale * ctx->paffine[3] *
+                oy = y + upself->scale * ctx->paffine.yy *
                     ((double) in2_pixels[y * rowstride + x * 4 + ych] / 255.0 - 0.5);
             else
                 oy = y;
@@ -3185,9 +3180,13 @@ rsvg_filter_primitive_turbulence_render (RsvgFilterPrimitive * self, RsvgFilterC
     RsvgIRect boundarys;
     guchar *output_pixels;
     GdkPixbuf *output;
-    gdouble affine[6];
+    cairo_matrix_t affine;
     GdkPixbuf *in;
 
+    affine = ctx->paffine;
+    if (cairo_matrix_invert (&affine) != CAIRO_STATUS_SUCCESS)
+      return;
+
     in = rsvg_filter_get_in (self->in, ctx);
     height = gdk_pixbuf_get_height (in);
     width = gdk_pixbuf_get_width (in);
@@ -3202,15 +3201,13 @@ rsvg_filter_primitive_turbulence_render (RsvgFilterPrimitive * self, RsvgFilterC
     output = _rsvg_pixbuf_new_cleared (GDK_COLORSPACE_RGB, 1, 8, width, height);
     output_pixels = gdk_pixbuf_get_pixels (output);
 
-    _rsvg_affine_invert (affine, ctx->paffine);
-
     for (y = 0; y < tileHeight; y++) {
         for (x = 0; x < tileWidth; x++) {
             gint i;
             double point[2];
             guchar *pixel;
-            point[0] = affine[0] * (x + boundarys.x0) + affine[2] * (y + boundarys.y0) + affine[4];
-            point[1] = affine[1] * (x + boundarys.x0) + affine[3] * (y + boundarys.y0) + affine[5];
+            point[0] = affine.xx * (x + boundarys.x0) + affine.xy * (y + boundarys.y0) + affine.x0;
+            point[1] = affine.yx * (x + boundarys.x0) + affine.yy * (y + boundarys.y0) + affine.y0;
 
             pixel = output_pixels + 4 * (x + boundarys.x0) + (y + boundarys.y0) * rowstride;
 
@@ -3330,7 +3327,6 @@ rsvg_filter_primitive_image_render_in (RsvgFilterPrimitive * self, RsvgFilterCon
 {
     RsvgDrawingCtx *ctx;
     RsvgFilterPrimitiveImage *upself;
-    int i;
     RsvgNode *drawable;
 
     ctx = context->ctx;
@@ -3344,8 +3340,7 @@ rsvg_filter_primitive_image_render_in (RsvgFilterPrimitive * self, RsvgFilterCon
     if (!drawable)
         return NULL;
 
-    for (i = 0; i < 6; i++)
-        rsvg_current_state (ctx)->affine[i] = context->paffine[i];
+    rsvg_current_state (ctx)->affine = context->paffine;
 
     return rsvg_get_image_of_node (ctx, drawable, context->width, context->height);
 }
@@ -3381,9 +3376,9 @@ rsvg_filter_primitive_image_render_ext (RsvgFilterPrimitive * self, RsvgFilterCo
 
 
     rsvg_art_affine_image (img, intermediate,
-                           ctx->paffine,
-                           (boundarys.x1 - boundarys.x0) / ctx->paffine[0],
-                           (boundarys.y1 - boundarys.y0) / ctx->paffine[3]);
+                           &ctx->paffine,
+                           (boundarys.x1 - boundarys.x0) / ctx->paffine.xx,
+                           (boundarys.y1 - boundarys.y0) / ctx->paffine.yy);
 
     if (!intermediate) {
         g_object_unref (img);
@@ -3798,7 +3793,7 @@ struct _RsvgNodeLightSource {
 
 static vector3
 get_light_direction (RsvgNodeLightSource * source, gdouble x1, gdouble y1, gdouble z,
-                     gdouble * affine, RsvgDrawingCtx * ctx)
+                     cairo_matrix_t *affine, RsvgDrawingCtx * ctx)
 {
     vector3 output;
 
@@ -3811,8 +3806,8 @@ get_light_direction (RsvgNodeLightSource * source, gdouble x1, gdouble y1, gdoub
     default:
         {
             double x, y;
-            x = affine[0] * x1 + affine[2] * y1 + affine[4];
-            y = affine[1] * x1 + affine[3] * y1 + affine[5];
+            x = affine->xx * x1 + affine->xy * y1 + affine->x0;
+            y = affine->yx * x1 + affine->yy * y1 + affine->y0;
             output.x = _rsvg_css_normalize_length (&source->x, ctx, 'h') - x;
             output.y = _rsvg_css_normalize_length (&source->y, ctx, 'v') - y;
             output.z = _rsvg_css_normalize_length (&source->z, ctx, 'o') - z;
@@ -3825,7 +3820,7 @@ get_light_direction (RsvgNodeLightSource * source, gdouble x1, gdouble y1, gdoub
 
 static vector3
 get_light_colour (RsvgNodeLightSource * source, vector3 colour,
-                  gdouble x1, gdouble y1, gdouble z, gdouble * affine, RsvgDrawingCtx * ctx)
+                  gdouble x1, gdouble y1, gdouble z, cairo_matrix_t *affine, RsvgDrawingCtx * ctx)
 {
     double base, angle, x, y;
     vector3 s;
@@ -3843,8 +3838,8 @@ get_light_colour (RsvgNodeLightSource * source, vector3 colour,
     spy = _rsvg_css_normalize_length (&source->pointsAtY, ctx, 'v');
     spz = _rsvg_css_normalize_length (&source->pointsAtZ, ctx, 'o');
 
-    x = affine[0] * x1 + affine[2] * y1 + affine[4];
-    y = affine[1] * x1 + affine[3] * y1 + affine[5];
+    x = affine->xx * x1 + affine->xy * y1 + affine->x0;
+    y = affine->yx * x1 + affine->yy * y1 + affine->y0;
 
     L.x = sx - x;
     L.y = sy - y;
@@ -3950,7 +3945,7 @@ rsvg_filter_primitive_diffuse_lighting_render (RsvgFilterPrimitive * self, RsvgF
     gdouble factor, surfaceScale;
     vector3 lightcolour, L, N;
     vector3 colour;
-    gdouble iaffine[6];
+    cairo_matrix_t iaffine;
     RsvgNodeLightSource *source = NULL;
     RsvgIRect boundarys;
 
@@ -3974,6 +3969,10 @@ rsvg_filter_primitive_diffuse_lighting_render (RsvgFilterPrimitive * self, RsvgF
     if (source == NULL)
         return;
 
+    iaffine = ctx->paffine;
+    if (cairo_matrix_invert (&iaffine) != CAIRO_STATUS_SUCCESS)
+      return;
+
     upself = (RsvgFilterPrimitiveDiffuseLighting *) self;
     boundarys = rsvg_filter_primitive_get_bounds (self, ctx);
 
@@ -4001,22 +4000,20 @@ rsvg_filter_primitive_diffuse_lighting_render (RsvgFilterPrimitive * self, RsvgF
         rawdx = 1;
         rawdy = 1;
     } else {
-        dx = upself->dx * ctx->paffine[0];
-        dy = upself->dy * ctx->paffine[3];
+        dx = upself->dx * ctx->paffine.xx;
+        dy = upself->dy * ctx->paffine.yy;
         rawdx = upself->dx;
         rawdy = upself->dy;
     }
 
-    _rsvg_affine_invert (iaffine, ctx->paffine);
-
     for (y = boundarys.y0; y < boundarys.y1; y++)
         for (x = boundarys.x0; x < boundarys.x1; x++) {
             z = surfaceScale * (double) in_pixels[y * rowstride + x * 4 + ctx->channelmap[3]];
-            L = get_light_direction (source, x, y, z, iaffine, ctx->ctx);
+            L = get_light_direction (source, x, y, z, &iaffine, ctx->ctx);
             N = get_surface_normal (in_pixels, boundarys, x, y,
                                     dx, dy, rawdx, rawdy, upself->surfaceScale,
                                     rowstride, ctx->channelmap[3]);
-            lightcolour = get_light_colour (source, colour, x, y, z, iaffine, ctx->ctx);
+            lightcolour = get_light_colour (source, colour, x, y, z, &iaffine, ctx->ctx);
             factor = dotproduct (N, L);
 
             output_pixels[y * rowstride + x * 4 + ctx->channelmap[0]] =
@@ -4124,7 +4121,7 @@ rsvg_filter_primitive_specular_lighting_render (RsvgFilterPrimitive * self, Rsvg
     gdouble factor, max, base;
     vector3 lightcolour, colour;
     vector3 L;
-    gdouble iaffine[6];
+    cairo_matrix_t iaffine;
     RsvgIRect boundarys;
     RsvgNodeLightSource *source = NULL;
 
@@ -4148,6 +4145,10 @@ rsvg_filter_primitive_specular_lighting_render (RsvgFilterPrimitive * self, Rsvg
     if (source == NULL)
         return;
 
+    iaffine = ctx->paffine;
+    if (cairo_matrix_invert (&iaffine) != CAIRO_STATUS_SUCCESS)
+      return;
+
     upself = (RsvgFilterPrimitiveSpecularLighting *) self;
     boundarys = rsvg_filter_primitive_get_bounds (self, ctx);
 
@@ -4169,19 +4170,17 @@ rsvg_filter_primitive_specular_lighting_render (RsvgFilterPrimitive * self, Rsvg
 
     surfaceScale = upself->surfaceScale / 255.0;
 
-    _rsvg_affine_invert (iaffine, ctx->paffine);
-
     for (y = boundarys.y0; y < boundarys.y1; y++)
         for (x = boundarys.x0; x < boundarys.x1; x++) {
             z = in_pixels[y * rowstride + x * 4 + 3] * surfaceScale;
-            L = get_light_direction (source, x, y, z, iaffine, ctx->ctx);
+            L = get_light_direction (source, x, y, z, &iaffine, ctx->ctx);
             L.z += 1;
             L = normalise (L);
 
-            lightcolour = get_light_colour (source, colour, x, y, z, iaffine, ctx->ctx);
+            lightcolour = get_light_colour (source, colour, x, y, z, &iaffine, ctx->ctx);
             base = dotproduct (get_surface_normal (in_pixels, boundarys, x, y,
-                                                   1, 1, 1.0 / ctx->paffine[0],
-                                                   1.0 / ctx->paffine[3], upself->surfaceScale,
+                                                   1, 1, 1.0 / ctx->paffine.xx,
+                                                   1.0 / ctx->paffine.yy, upself->surfaceScale,
                                                    rowstride, ctx->channelmap[3]), L);
 
             factor = upself->specularConstant * pow (base, upself->specularExponent) * 255;
diff --git a/rsvg-filter.h b/rsvg-filter.h
index 0aeda22..b7dbbfe 100644
--- a/rsvg-filter.h
+++ b/rsvg-filter.h
@@ -72,7 +72,7 @@ void         rsvg_alpha_blt         (GdkPixbuf * src, gint srcx, gint srcy,
                                      gint srcwidth, gint srcheight,
                                      GdkPixbuf * dst, gint dstx, gint dsty);
 void         rsvg_art_affine_image	(const GdkPixbuf * img, GdkPixbuf * intermediate,
-                                     double *affine, double w, double h);
+                                     cairo_matrix_t *affine, double w, double h);
 
 G_END_DECLS
 
diff --git a/rsvg-marker.c b/rsvg-marker.c
index 3d903a8..d9d3bfe 100644
--- a/rsvg-marker.c
+++ b/rsvg-marker.c
@@ -100,25 +100,25 @@ void
 rsvg_marker_render (RsvgMarker * self, gdouble x, gdouble y, gdouble orient, gdouble linewidth,
 		    RsvgDrawingCtx * ctx)
 {
-    gdouble affine[6];
-    gdouble taffine[6];
+    cairo_matrix_t affine, taffine;
     unsigned int i;
     gdouble rotation;
     RsvgState *state = rsvg_current_state (ctx);
 
-    _rsvg_affine_translate (taffine, x, y);
-    _rsvg_affine_multiply (affine, taffine, state->affine);
+    cairo_matrix_init_translate (&taffine, x, y);
+    cairo_matrix_multiply (&affine, &taffine, &state->affine);
 
     if (self->orientAuto)
-        rotation = orient * 180. / M_PI;
+        rotation = orient;
     else
-        rotation = self->orient;
-    _rsvg_affine_rotate (taffine, rotation);
-    _rsvg_affine_multiply (affine, taffine, affine);
+        rotation = self->orient * M_PI / 180.;
+
+    cairo_matrix_init_rotate (&taffine, rotation);
+    cairo_matrix_multiply (&affine, &taffine, &affine);
 
     if (self->bbox) {
-        _rsvg_affine_scale (taffine, linewidth, linewidth);
-        _rsvg_affine_multiply (affine, taffine, affine);
+        cairo_matrix_init_scale (&taffine, linewidth, linewidth);
+        cairo_matrix_multiply (&affine, &taffine, &affine);
     }
 
     if (self->vbox.active) {
@@ -137,20 +137,21 @@ rsvg_marker_render (RsvgMarker * self, gdouble x, gdouble y, gdouble orient, gdo
         x = -self->vbox.rect.x * w / self->vbox.rect.width;
         y = -self->vbox.rect.y * h / self->vbox.rect.height;
 
-        taffine[0] = w / self->vbox.rect.width;
-        taffine[1] = 0.;
-        taffine[2] = 0.;
-        taffine[3] = h / self->vbox.rect.height;
-        taffine[4] = x;
-        taffine[5] = y;
-        _rsvg_affine_multiply (affine, taffine, affine);
+        cairo_matrix_init (&taffine,
+                           w / self->vbox.rect.width,
+                           0,
+                           0,
+                           h / self->vbox.rect.height,
+                           x,
+                           y);
+        cairo_matrix_multiply (&affine, &taffine, &affine);
         _rsvg_push_view_box (ctx, self->vbox.rect.width, self->vbox.rect.height);
     }
-    _rsvg_affine_translate (taffine,
-                            -_rsvg_css_normalize_length (&self->refX, ctx, 'h'),
-                            -_rsvg_css_normalize_length (&self->refY, ctx, 'v'));
-    _rsvg_affine_multiply (affine, taffine, affine);
 
+    cairo_matrix_init_translate (&taffine,
+                                 -_rsvg_css_normalize_length (&self->refX, ctx, 'h'),
+                                 -_rsvg_css_normalize_length (&self->refY, ctx, 'v'));
+    cairo_matrix_multiply (&affine, &taffine, &affine);
 
     rsvg_state_push (ctx);
     state = rsvg_current_state (ctx);
@@ -159,8 +160,7 @@ rsvg_marker_render (RsvgMarker * self, gdouble x, gdouble y, gdouble orient, gdo
 
     rsvg_state_reconstruct (state, &self->super);
 
-    for (i = 0; i < 6; i++)
-        state->affine[i] = affine[i];
+    state->affine = affine;
 
     rsvg_push_discrete_layer (ctx);
 
diff --git a/rsvg-paint-server.c b/rsvg-paint-server.c
index 13a213c..a330d3c 100644
--- a/rsvg-paint-server.c
+++ b/rsvg-paint-server.c
@@ -271,7 +271,7 @@ rsvg_linear_gradient_set_atts (RsvgNode * self, RsvgHandle * ctx, RsvgPropertyBa
                 rsvg_defs_add_resolver (ctx->priv->defs, &grad->fallback, value);
 	}
         if ((value = rsvg_property_bag_lookup (atts, "gradientTransform"))) {
-            rsvg_parse_transform (grad->affine, value);
+            rsvg_parse_transform (&grad->affine, value);
             grad->hastransform = TRUE;
         }
         if ((value = rsvg_property_bag_lookup (atts, "color")))
@@ -294,7 +294,7 @@ rsvg_new_linear_gradient (void)
     RsvgLinearGradient *grad = NULL;
     grad = g_new (RsvgLinearGradient, 1);
     _rsvg_node_init (&grad->super, RSVG_NODE_TYPE_LINEAR_GRADIENT);
-    _rsvg_affine_identity (grad->affine);
+    cairo_matrix_init_identity (&grad->affine);
     grad->has_current_color = FALSE;
     grad->x1 = grad->y1 = grad->y2 = _rsvg_css_parse_length ("0");
     grad->x2 = _rsvg_css_parse_length ("1");
@@ -345,7 +345,7 @@ rsvg_radial_gradient_set_atts (RsvgNode * self, RsvgHandle * ctx, RsvgPropertyBa
                 rsvg_defs_add_resolver (ctx->priv->defs, &grad->fallback, value);
         }
         if ((value = rsvg_property_bag_lookup (atts, "gradientTransform"))) {
-            rsvg_parse_transform (grad->affine, value);
+            rsvg_parse_transform (&grad->affine, value);
             grad->hastransform = TRUE;
         }
         if ((value = rsvg_property_bag_lookup (atts, "color"))) {
@@ -377,7 +377,7 @@ rsvg_new_radial_gradient (void)
 
     RsvgRadialGradient *grad = g_new (RsvgRadialGradient, 1);
     _rsvg_node_init (&grad->super, RSVG_NODE_TYPE_RADIAL_GRADIENT);
-    _rsvg_affine_identity (grad->affine);
+    cairo_matrix_init_identity (&grad->affine);
     grad->has_current_color = FALSE;
     grad->obj_bbox = TRUE;
     grad->spread = CAIRO_EXTEND_PAD;
@@ -429,7 +429,7 @@ rsvg_pattern_set_atts (RsvgNode * self, RsvgHandle * ctx, RsvgPropertyBag * atts
             }
         }
         if ((value = rsvg_property_bag_lookup (atts, "patternTransform"))) {
-            rsvg_parse_transform (pattern->affine, value);
+            rsvg_parse_transform (&pattern->affine, value);
             pattern->hastransform = TRUE;
         }
         if ((value = rsvg_property_bag_lookup (atts, "patternUnits"))) {
@@ -459,13 +459,13 @@ rsvg_new_pattern (void)
 {
     RsvgPattern *pattern = g_new (RsvgPattern, 1);
     _rsvg_node_init (&pattern->super, RSVG_NODE_TYPE_PATTERN);
+    cairo_matrix_init_identity (&pattern->affine);
     pattern->obj_bbox = TRUE;
     pattern->obj_cbbox = FALSE;
     pattern->x = pattern->y = pattern->width = pattern->height = _rsvg_css_parse_length ("0");
     pattern->fallback = NULL;
     pattern->preserve_aspect_ratio = RSVG_ASPECT_RATIO_XMID_YMID;
     pattern->vbox.active = FALSE;
-    _rsvg_affine_identity (pattern->affine);
     pattern->super.set_atts = rsvg_pattern_set_atts;
     pattern->hasx = pattern->hasy = pattern->haswidth = pattern->hasheight = pattern->hasbbox =
         pattern->hascbox = pattern->hasvbox = pattern->hasaspect = pattern->hastransform = FALSE;
@@ -488,7 +488,6 @@ void
 rsvg_linear_gradient_fix_fallback (RsvgLinearGradient * grad)
 {
     RsvgNode *ufallback;
-    int i;
     ufallback = grad->fallback;
     while (ufallback != NULL) {
         if (RSVG_NODE_TYPE (ufallback) == RSVG_NODE_TYPE_LINEAR_GRADIENT) {
@@ -511,8 +510,7 @@ rsvg_linear_gradient_fix_fallback (RsvgLinearGradient * grad)
             }
             if (!grad->hastransform && fallback->hastransform) {
                 grad->hastransform = TRUE;
-                for (i = 0; i < 6; i++)
-                    grad->affine[i] = fallback->affine[i];
+                grad->affine = fallback->affine;
             }
             if (!grad->hasspread && fallback->hasspread) {
                 grad->hasspread = TRUE;
@@ -530,8 +528,7 @@ rsvg_linear_gradient_fix_fallback (RsvgLinearGradient * grad)
             RsvgRadialGradient *fallback = (RsvgRadialGradient *) ufallback;
             if (!grad->hastransform && fallback->hastransform) {
                 grad->hastransform = TRUE;
-                for (i = 0; i < 6; i++)
-                    grad->affine[i] = fallback->affine[i];
+                grad->affine = fallback->affine;
             }
             if (!grad->hasspread && fallback->hasspread) {
                 grad->hasspread = TRUE;
@@ -553,7 +550,6 @@ void
 rsvg_radial_gradient_fix_fallback (RsvgRadialGradient * grad)
 {
     RsvgNode *ufallback;
-    int i;
     ufallback = grad->fallback;
     while (ufallback != NULL) {
         if (RSVG_NODE_TYPE (ufallback) == RSVG_NODE_TYPE_RADIAL_GRADIENT) {
@@ -580,8 +576,7 @@ rsvg_radial_gradient_fix_fallback (RsvgRadialGradient * grad)
             }
             if (!grad->hastransform && fallback->hastransform) {
                 grad->hastransform = TRUE;
-                for (i = 0; i < 6; i++)
-                    grad->affine[i] = fallback->affine[i];
+                grad->affine = fallback->affine;
             }
             if (!grad->hasspread && fallback->hasspread) {
                 grad->hasspread = TRUE;
@@ -599,8 +594,7 @@ rsvg_radial_gradient_fix_fallback (RsvgRadialGradient * grad)
             RsvgLinearGradient *fallback = (RsvgLinearGradient *) ufallback;
             if (!grad->hastransform && fallback->hastransform) {
                 grad->hastransform = TRUE;
-                for (i = 0; i < 6; i++)
-                    grad->affine[i] = fallback->affine[i];
+                grad->affine = fallback->affine;
             }
             if (!grad->hasspread && fallback->hasspread) {
                 grad->hasspread = TRUE;
@@ -623,7 +617,6 @@ void
 rsvg_pattern_fix_fallback (RsvgPattern * pattern)
 {
     RsvgPattern *fallback;
-    int i;
     for (fallback = pattern->fallback; fallback != NULL; fallback = fallback->fallback) {
         if (!pattern->hasx && fallback->hasx) {
             pattern->hasx = TRUE;
@@ -643,8 +636,7 @@ rsvg_pattern_fix_fallback (RsvgPattern * pattern)
         }
         if (!pattern->hastransform && fallback->hastransform) {
             pattern->hastransform = TRUE;
-            for (i = 0; i < 6; i++)
-                pattern->affine[i] = fallback->affine[i];
+            pattern->affine = fallback->affine;
         }
         if (!pattern->hasvbox && fallback->hasvbox) {
             pattern->vbox = fallback->vbox;
diff --git a/rsvg-paint-server.h b/rsvg-paint-server.h
index 01a99ea..26e84b5 100644
--- a/rsvg-paint-server.h
+++ b/rsvg-paint-server.h
@@ -53,7 +53,7 @@ struct _RsvgGradientStop {
 struct _RsvgLinearGradient {
     RsvgNode super;
     gboolean obj_bbox;
-    double affine[6];           /* user space to actual at time of gradient def */
+    cairo_matrix_t affine; /* user space to actual at time of gradient def */
     cairo_extend_t spread;
     RsvgLength x1, y1, x2, y2;
     guint32 current_color;
@@ -71,7 +71,7 @@ struct _RsvgLinearGradient {
 struct _RsvgRadialGradient {
     RsvgNode super;
     gboolean obj_bbox;
-    double affine[6];           /* user space to actual at time of gradient def */
+    cairo_matrix_t affine; /* user space to actual at time of gradient def */
     cairo_extend_t spread;
     RsvgLength cx, cy, r, fx, fy;
     guint32 current_color;
@@ -91,7 +91,7 @@ struct _RsvgPattern {
     RsvgNode super;
     gboolean obj_cbbox;
     gboolean obj_bbox;
-    double affine[6];           /* user space to actual at time of gradient def */
+    cairo_matrix_t affine; /* user space to actual at time of gradient def */
     RsvgLength x, y, width, height;
     RsvgViewBox vbox;
     unsigned int preserve_aspect_ratio;
diff --git a/rsvg-private.h b/rsvg-private.h
index 4b2b7a9..eb6becf 100644
--- a/rsvg-private.h
+++ b/rsvg-private.h
@@ -251,8 +251,8 @@ struct _RsvgIRect {
 
 typedef struct {
     cairo_rectangle_t rect;
+    cairo_matrix_t affine;
     gboolean virgin;
-    double affine[6];
 } RsvgBbox;
 
 typedef enum {
@@ -384,30 +384,11 @@ void rsvg_add_clipping_rect     (RsvgDrawingCtx * ctx, double x, double y, doubl
 GdkPixbuf *rsvg_get_image_of_node (RsvgDrawingCtx * ctx, RsvgNode * drawable, double w, double h);
 
 
-void _rsvg_affine_invert (double dst_affine[6], const double src_affine[6]);
-
-void _rsvg_affine_multiply (double dst[6], const double src1[6], const double src2[6]);
-
-/* set up the identity matrix */
-void _rsvg_affine_identity (double dst[6]);
-
-/* set up a scaling matrix */
-void _rsvg_affine_scale (double dst[6], double sx, double sy);
-
-/* set up a rotation matrix; theta is given in degrees */
-void _rsvg_affine_rotate (double dst[6], double theta);
-
-/* set up a shearing matrix; theta is given in degrees */
-void _rsvg_affine_shear (double dst[6], double theta);
-
-/* set up a translation matrix */
-void _rsvg_affine_translate (double dst[6], double tx, double ty);
-
 void rsvg_node_set_atts (RsvgNode * node, RsvgHandle * ctx, RsvgPropertyBag * atts);
 
 void rsvg_drawing_ctx_free (RsvgDrawingCtx * handle);
 
-void rsvg_bbox_init     (RsvgBbox * self, double *affine);
+void rsvg_bbox_init     (RsvgBbox * self, cairo_matrix_t *matrix);
 void rsvg_bbox_insert   (RsvgBbox * dst, RsvgBbox * src);
 void rsvg_bbox_clip     (RsvgBbox * dst, RsvgBbox * src);
 
diff --git a/rsvg-structure.c b/rsvg-structure.c
index 3c218b6..29451da 100644
--- a/rsvg-structure.c
+++ b/rsvg-structure.c
@@ -199,7 +199,7 @@ rsvg_node_use_draw (RsvgNode * self, RsvgDrawingCtx * ctx, int dominate)
     RsvgNodeUse *use = (RsvgNodeUse *) self;
     RsvgNode *child;
     RsvgState *state;
-    double affine[6];
+    cairo_matrix_t affine;
     double x, y, w, h;
     x = _rsvg_css_normalize_length (&use->x, ctx, 'h');
     y = _rsvg_css_normalize_length (&use->y, ctx, 'v');
@@ -218,8 +218,8 @@ rsvg_node_use_draw (RsvgNode * self, RsvgDrawingCtx * ctx, int dominate)
 
     state = rsvg_current_state (ctx);
     if (RSVG_NODE_TYPE (child) != RSVG_NODE_TYPE_SYMBOL) {
-        _rsvg_affine_translate (affine, x, y);
-        _rsvg_affine_multiply (state->affine, affine, state->affine);
+        cairo_matrix_init_translate (&affine, x, y);
+        cairo_matrix_multiply (&state->affine, &affine, &state->affine);
 
         rsvg_push_discrete_layer (ctx);
         rsvg_state_push (ctx);
@@ -235,12 +235,14 @@ rsvg_node_use_draw (RsvgNode * self, RsvgDrawingCtx * ctx, int dominate)
                  symbol->vbox.rect.width, symbol->vbox.rect.height,
                  &w, &h, &x, &y);
 
-            _rsvg_affine_translate (affine, x, y);
-            _rsvg_affine_multiply (state->affine, affine, state->affine);
-            _rsvg_affine_scale (affine, w / symbol->vbox.rect.width, h / symbol->vbox.rect.height);
-            _rsvg_affine_multiply (state->affine, affine, state->affine);
-            _rsvg_affine_translate (affine, -symbol->vbox.rect.x, -symbol->vbox.rect.y);
-            _rsvg_affine_multiply (state->affine, affine, state->affine);
+            cairo_matrix_init_translate (&affine, x, y);
+            cairo_matrix_multiply (&state->affine, &affine, &state->affine);
+
+            cairo_matrix_init_scale (&affine, w / symbol->vbox.rect.width, h / symbol->vbox.rect.height);
+            cairo_matrix_multiply (&state->affine, &affine, &state->affine);
+
+            cairo_matrix_init_translate (&affine, -symbol->vbox.rect.x, -symbol->vbox.rect.y);
+            cairo_matrix_multiply (&state->affine, &affine, &state->affine);
 
             _rsvg_push_view_box (ctx, symbol->vbox.rect.width, symbol->vbox.rect.height);
             rsvg_push_discrete_layer (ctx);
@@ -248,8 +250,8 @@ rsvg_node_use_draw (RsvgNode * self, RsvgDrawingCtx * ctx, int dominate)
                 rsvg_add_clipping_rect (ctx, symbol->vbox.rect.x, symbol->vbox.rect.y,
                                         symbol->vbox.rect.width, symbol->vbox.rect.height);
         } else {
-            _rsvg_affine_translate (affine, x, y);
-            _rsvg_affine_multiply (state->affine, affine, state->affine);
+            cairo_matrix_init_translate (&affine, x, y);
+            cairo_matrix_multiply (&state->affine, &affine, &state->affine);
             rsvg_push_discrete_layer (ctx);
         }
 
@@ -268,7 +270,7 @@ rsvg_node_svg_draw (RsvgNode * self, RsvgDrawingCtx * ctx, int dominate)
 {
     RsvgNodeSvg *sself;
     RsvgState *state;
-    gdouble affine[6], affine_old[6], affine_new[6];
+    cairo_matrix_t affine, affine_old, affine_new;
     guint i;
     double nx, ny, nw, nh;
     sself = (RsvgNodeSvg *) self;
@@ -282,45 +284,38 @@ rsvg_node_svg_draw (RsvgNode * self, RsvgDrawingCtx * ctx, int dominate)
 
     state = rsvg_current_state (ctx);
 
-    for (i = 0; i < 6; i++)
-        affine_old[i] = state->affine[i];
+    affine_old = state->affine;
 
     if (sself->vbox.active) {
         double x = nx, y = ny, w = nw, h = nh;
         rsvg_preserve_aspect_ratio (sself->preserve_aspect_ratio,
                                     sself->vbox.rect.width, sself->vbox.rect.height,
                                     &w, &h, &x, &y);
-        affine[0] = w / sself->vbox.rect.width;
-        affine[1] = 0;
-        affine[2] = 0;
-        affine[3] = h / sself->vbox.rect.height;
-        affine[4] = x - sself->vbox.rect.x * w / sself->vbox.rect.width;
-        affine[5] = y - sself->vbox.rect.y * h / sself->vbox.rect.height;
-        _rsvg_affine_multiply (state->affine, affine, state->affine);
+        cairo_matrix_init (&affine,
+                           w / sself->vbox.rect.width,
+                           0,
+                           0,
+                           h / sself->vbox.rect.height,
+                           x - sself->vbox.rect.x * w / sself->vbox.rect.width,
+                           y - sself->vbox.rect.y * h / sself->vbox.rect.height);
+        cairo_matrix_multiply (&state->affine, &affine, &state->affine);
         _rsvg_push_view_box (ctx, sself->vbox.rect.width, sself->vbox.rect.height);
     } else {
-        affine[0] = 1;
-        affine[1] = 0;
-        affine[2] = 0;
-        affine[3] = 1;
-        affine[4] = nx;
-        affine[5] = ny;
-        _rsvg_affine_multiply (state->affine, affine, state->affine);
+        cairo_matrix_init_translate (&affine, nx, ny);
+        cairo_matrix_multiply (&state->affine, &affine, &state->affine);
         _rsvg_push_view_box (ctx, nw, nh);
     }
-    for (i = 0; i < 6; i++)
-        affine_new[i] = state->affine[i];
+
+    affine_new = state->affine;
 
     rsvg_push_discrete_layer (ctx);
 
     /* Bounding box addition must be AFTER the discrete layer push, 
        which must be AFTER the transformation happens. */
     if (!state->overflow && self->parent) {
-        for (i = 0; i < 6; i++)
-            state->affine[i] = affine_old[i];
+        state->affine = affine_old;
         rsvg_add_clipping_rect (ctx, nx, ny, nw, nh);
-        for (i = 0; i < 6; i++)
-            state->affine[i] = affine_new[i];
+        state->affine = affine_new;
     }
 
     for (i = 0; i < self->children->len; i++) {
diff --git a/rsvg-styles.c b/rsvg-styles.c
index 3092754..b49255b 100644
--- a/rsvg-styles.c
+++ b/rsvg-styles.c
@@ -23,6 +23,8 @@
 
    Author: Raph Levien <raph artofcode com>
 */
+#include "config.h"
+
 #include <string.h>
 #include <math.h>
 
@@ -56,6 +58,21 @@ typedef struct _StyleValueData {
     gboolean important;
 } StyleValueData;
 
+/*
+ * _rsvg_cairo_matrix_init_shear: Set up a shearing matrix.
+ * @dst: Where to store the resulting affine transform.
+ * @theta: Shear angle in degrees.
+ *
+ * Sets up a shearing matrix. In the standard libart coordinate system
+ * and a small value for theta, || becomes \\. Horizontal lines remain
+ * unchanged.
+ **/
+static void
+_rsvg_cairo_matrix_init_shear (cairo_matrix_t *dst, double theta)
+{
+  cairo_matrix_init (dst, 1., 0., tan (theta * M_PI / 180.0), 1., 0., 0);
+}
+
 static StyleValueData *
 style_value_data_new (const gchar *value, gboolean important)
 {
@@ -95,8 +112,8 @@ rsvg_state_init (RsvgState * state)
     memset (state, 0, sizeof (RsvgState));
 
     state->parent = NULL;
-    _rsvg_affine_identity (state->affine);
-    _rsvg_affine_identity (state->personal_affine);
+    cairo_matrix_init_identity (&state->affine);
+    cairo_matrix_init_identity (&state->personal_affine);
     state->mask = NULL;
     state->opacity = 0xff;
     state->adobe_blend = 0;
@@ -1241,16 +1258,16 @@ rsvg_parse_cssbuffer (RsvgHandle * ctx, const char *buff, size_t buflen)
    working draft dated 1999-07-06, section 8.5. Return TRUE on
    success. */
 gboolean
-rsvg_parse_transform (double dst[6], const char *src)
+rsvg_parse_transform (cairo_matrix_t *dst, const char *src)
 {
     int idx;
     char keyword[32];
     double args[6];
     int n_args;
     guint key_len;
-    double tmp_affine[6];
+    cairo_matrix_t affine;
 
-    _rsvg_affine_identity (dst);
+    cairo_matrix_init_identity (dst);
 
     idx = 0;
     while (src[idx]) {
@@ -1314,49 +1331,52 @@ rsvg_parse_transform (double dst[6], const char *src)
         if (!strcmp (keyword, "matrix")) {
             if (n_args != 6)
                 return FALSE;
-            _rsvg_affine_multiply (dst, args, dst);
+
+            cairo_matrix_init (&affine, args[0], args[1], args[2], args[3], args[4], args[5]);
+            cairo_matrix_multiply (dst, &affine, dst);
         } else if (!strcmp (keyword, "translate")) {
             if (n_args == 1)
                 args[1] = 0;
             else if (n_args != 2)
                 return FALSE;
-            _rsvg_affine_translate (tmp_affine, args[0], args[1]);
-            _rsvg_affine_multiply (dst, tmp_affine, dst);
+            cairo_matrix_init_translate (&affine, args[0], args[1]);
+            cairo_matrix_multiply (dst, &affine, dst);
         } else if (!strcmp (keyword, "scale")) {
             if (n_args == 1)
                 args[1] = args[0];
             else if (n_args != 2)
                 return FALSE;
-            _rsvg_affine_scale (tmp_affine, args[0], args[1]);
-            _rsvg_affine_multiply (dst, tmp_affine, dst);
+            cairo_matrix_init_scale (&affine, args[0], args[1]);
+            cairo_matrix_multiply (dst, &affine, dst);
         } else if (!strcmp (keyword, "rotate")) {
             if (n_args == 1) {
-                _rsvg_affine_rotate (tmp_affine, args[0]);
-                _rsvg_affine_multiply (dst, tmp_affine, dst);
+
+                cairo_matrix_init_rotate (&affine, args[0] * M_PI / 180.);
+                cairo_matrix_multiply (dst, &affine, dst);
             } else if (n_args == 3) {
-                _rsvg_affine_translate (tmp_affine, args[1], args[2]);
-                _rsvg_affine_multiply (dst, tmp_affine, dst);
+                cairo_matrix_init_translate (&affine, args[1], args[2]);
+                cairo_matrix_multiply (dst, &affine, dst);
 
-                _rsvg_affine_rotate (tmp_affine, args[0]);
-                _rsvg_affine_multiply (dst, tmp_affine, dst);
+                cairo_matrix_init_rotate (&affine, args[0] * M_PI / 180.);
+                cairo_matrix_multiply (dst, &affine, dst);
 
-                _rsvg_affine_translate (tmp_affine, -args[1], -args[2]);
-                _rsvg_affine_multiply (dst, tmp_affine, dst);
+                cairo_matrix_init_translate (&affine, -args[1], -args[2]);
+                cairo_matrix_multiply (dst, &affine, dst);
             } else
                 return FALSE;
         } else if (!strcmp (keyword, "skewX")) {
             if (n_args != 1)
                 return FALSE;
-            _rsvg_affine_shear (tmp_affine, args[0]);
-            _rsvg_affine_multiply (dst, tmp_affine, dst);
+            _rsvg_cairo_matrix_init_shear (&affine, args[0]);
+            cairo_matrix_multiply (dst, &affine, dst);
         } else if (!strcmp (keyword, "skewY")) {
             if (n_args != 1)
                 return FALSE;
-            _rsvg_affine_shear (tmp_affine, args[0]);
+            _rsvg_cairo_matrix_init_shear (&affine, args[0]);
             /* transpose the affine, given that we know [1] is zero */
-            tmp_affine[1] = tmp_affine[2];
-            tmp_affine[2] = 0;
-            _rsvg_affine_multiply (dst, tmp_affine, dst);
+            affine.yx = affine.xy;
+            affine.xy = 0.;
+            cairo_matrix_multiply (dst, &affine, dst);
         } else
             return FALSE;       /* unknown keyword */
     }
@@ -1374,11 +1394,11 @@ rsvg_parse_transform (double dst[6], const char *src)
 static void
 rsvg_parse_transform_attr (RsvgHandle * ctx, RsvgState * state, const char *str)
 {
-    double affine[6];
+    cairo_matrix_t affine;
 
-    if (rsvg_parse_transform (affine, str)) {
-        _rsvg_affine_multiply (state->personal_affine, affine, state->personal_affine);
-        _rsvg_affine_multiply (state->affine, affine, state->affine);
+    if (rsvg_parse_transform (&affine, str)) {
+        cairo_matrix_multiply (&state->personal_affine, &affine, &state->personal_affine);
+        cairo_matrix_multiply (&state->affine, &affine, &state->affine);
     }
 }
 
@@ -1601,10 +1621,8 @@ rsvg_state_push (RsvgDrawingCtx * ctx)
     rsvg_state_init (data);
 
     if (baseon) {
-        int i;
         rsvg_state_reinherit (data, baseon);
-        for (i = 0; i < 6; i++)
-            data->affine[i] = baseon->affine[i];
+        data->affine = baseon->affine;
         data->parent = baseon;
     }
 
@@ -1655,9 +1673,9 @@ rsvg_state_reinherit_top (RsvgDrawingCtx * ctx, RsvgState * state, int dominate)
                 rsvg_state_dominate (current, parent);
             else
                 rsvg_state_reinherit (current, parent);
-            _rsvg_affine_multiply (current->affine,
-                                   current->affine,
-                                   parent->affine);
+            cairo_matrix_multiply (&current->affine,
+                                   &current->affine,
+                                   &parent->affine);
         }
     }
 }
diff --git a/rsvg-styles.h b/rsvg-styles.h
index 2c5ab6d..248d8d7 100644
--- a/rsvg-styles.h
+++ b/rsvg-styles.h
@@ -76,8 +76,8 @@ struct _RsvgVpathDash {
 
 struct _RsvgState {
     RsvgState *parent;
-    double affine[6];
-    double personal_affine[6];
+    cairo_matrix_t affine;
+    cairo_matrix_t personal_affine;
 
     RsvgFilter *filter;
     void *mask;
@@ -206,7 +206,7 @@ void rsvg_parse_style_attrs (RsvgHandle * ctx, RsvgState * state, const char *ta
 gdouble rsvg_viewport_percentage (gdouble width, gdouble height);
 gdouble rsvg_dpi_percentage      (RsvgHandle * ctx);
 
-gboolean rsvg_parse_transform   (double dst[6], const char *src);
+gboolean rsvg_parse_transform   (cairo_matrix_t *matrix, const char *src);
 
 RsvgState *rsvg_state_parent    (RsvgState * state);
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]