From 79b907273a800815001980d40edb38dddf443daa Mon Sep 17 00:00:00 2001 From: Bas Schouten Date: Wed, 28 Jul 2010 18:53:17 +0200 Subject: [PATCH] Bug 581083: Use Direct2D geometry to inverse transform which will preserve the required precision. r=jrmuizel a=blocking-betaN --- gfx/cairo/cairo/src/cairo-d2d-surface.cpp | 54 ++++++++++++----------- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/gfx/cairo/cairo/src/cairo-d2d-surface.cpp b/gfx/cairo/cairo/src/cairo-d2d-surface.cpp index 47b662e8b960..7ff860ba8515 100644 --- a/gfx/cairo/cairo/src/cairo-d2d-surface.cpp +++ b/gfx/cairo/cairo/src/cairo-d2d-surface.cpp @@ -668,6 +668,27 @@ _cairo_d2d_matrix_from_matrix(const cairo_matrix_t *matrix) (FLOAT)matrix->y0); } +/** + * Returns the inverse matrix for a D2D1 matrix. We cannot use the Invert function + * on the Matrix3x2F function class since it's statically linked and we'd have to + * lookup the symbol in the library. Doing this ourselves is easier. + * + * \param mat matrix + * \return inverse of matrix mat + */ +static D2D1::Matrix3x2F +_cairo_d2d_invert_matrix(const D2D1::Matrix3x2F &mat) +{ + float inv_det = (1 / mat.Determinant()); + + return D2D1::Matrix3x2F(mat._22 * inv_det, + -mat._12 * inv_det, + -mat._21 * inv_det, + mat._11 * inv_det, + (mat._21 * mat._32 - mat._22 * mat._31) * inv_det, + -(mat._11 * mat._32 - mat._12 * mat._31) * inv_det); +} + /** * Create a D2D stroke style interface for a cairo stroke style object. Must be * released when the calling function is finished with it. @@ -2027,41 +2048,24 @@ _cairo_d2d_stroke(void *surface, return CAIRO_INT_STATUS_UNSUPPORTED; } D2D1::Matrix3x2F mat = _cairo_d2d_matrix_from_matrix(ctm); - - _cairo_path_fixed_transform(path, ctm_inverse); + RefPtr d2dpath = _cairo_d2d_create_path_geometry_for_path(path, + CAIRO_FILL_RULE_WINDING, + D2D1_FIGURE_BEGIN_FILLED); + D2D1::Matrix3x2F inverse_mat = _cairo_d2d_invert_matrix(mat); + + RefPtr trans_geom; + D2DSurfFactory::Instance()->CreateTransformedGeometry(d2dpath, &inverse_mat, &trans_geom); d2dsurf->rt->SetTransform(mat); - cairo_box_t box; - RefPtr brush = _cairo_d2d_create_brush_for_pattern(d2dsurf, source); if (!brush) { return CAIRO_INT_STATUS_UNSUPPORTED; } - if (_cairo_path_fixed_is_box(path, &box)) { - float x1 = _cairo_fixed_to_float(box.p1.x); - float y1 = _cairo_fixed_to_float(box.p1.y); - float x2 = _cairo_fixed_to_float(box.p2.x); - float y2 = _cairo_fixed_to_float(box.p2.y); + d2dsurf->rt->DrawGeometry(trans_geom, brush, (FLOAT)style->line_width, strokeStyle); - d2dsurf->rt->DrawRectangle(D2D1::RectF(x1, - y1, - x2, - y2), - brush, - (FLOAT)style->line_width, - strokeStyle); - - } else { - RefPtr d2dpath = _cairo_d2d_create_path_geometry_for_path(path, - CAIRO_FILL_RULE_WINDING, - D2D1_FIGURE_BEGIN_HOLLOW); - d2dsurf->rt->DrawGeometry(d2dpath, brush, (FLOAT)style->line_width, strokeStyle); - } - - _cairo_path_fixed_transform(path, ctm); d2dsurf->rt->SetTransform(D2D1::Matrix3x2F::Identity()); return CAIRO_INT_STATUS_SUCCESS; }