From 1c35e721a39317a92d13db0e2d94284efc253673 Mon Sep 17 00:00:00 2001 From: "tor%cs.brown.edu" Date: Sun, 2 Oct 2005 19:35:22 +0000 Subject: [PATCH] Bug 310473 - avoid passing noninvertable matrices to cairo. r=jwatt --- .../renderer/src/cairo/nsSVGCairoCanvas.cpp | 3 + .../src/cairo/nsSVGCairoGlyphGeometry.cpp | 55 ++++++++++++++----- .../renderer/src/cairo/nsSVGCairoGradient.cpp | 8 ++- .../src/cairo/nsSVGCairoPathGeometry.cpp | 23 ++++++-- .../renderer/src/cairo/nsSVGCairoPattern.cpp | 12 ++-- 5 files changed, 75 insertions(+), 26 deletions(-) diff --git a/layout/svg/renderer/src/cairo/nsSVGCairoCanvas.cpp b/layout/svg/renderer/src/cairo/nsSVGCairoCanvas.cpp index 9e5c93e94e3..69a70ea297a 100644 --- a/layout/svg/renderer/src/cairo/nsSVGCairoCanvas.cpp +++ b/layout/svg/renderer/src/cairo/nsSVGCairoCanvas.cpp @@ -630,6 +630,9 @@ nsSVGCairoCanvas::SetClipRect(nsIDOMSVGMatrix *aCTM, float aX, float aY, cairo_matrix_t oldMatrix; cairo_get_matrix(mCR, &oldMatrix); cairo_matrix_t matrix = {m[0], m[1], m[2], m[3], m[4], m[5]}; + cairo_matrix_t inverse = matrix; + if (cairo_matrix_invert(&inverse)) + return NS_ERROR_FAILURE; cairo_transform(mCR, &matrix); cairo_new_path(mCR); diff --git a/layout/svg/renderer/src/cairo/nsSVGCairoGlyphGeometry.cpp b/layout/svg/renderer/src/cairo/nsSVGCairoGlyphGeometry.cpp index f7e4cd96532..ebaa93f30db 100644 --- a/layout/svg/renderer/src/cairo/nsSVGCairoGlyphGeometry.cpp +++ b/layout/svg/renderer/src/cairo/nsSVGCairoGlyphGeometry.cpp @@ -83,7 +83,7 @@ protected: ~nsSVGCairoGlyphGeometry(); nsresult Init(nsISVGGlyphGeometrySource* src); - void GetGlobalTransform(cairo_t *ctx, nsISVGCairoCanvas* aCanvas); + nsresult GetGlobalTransform(cairo_t *ctx, nsISVGCairoCanvas* aCanvas); public: // nsISupports interface: @@ -219,7 +219,12 @@ nsSVGCairoGlyphGeometry::Render(nsISVGRendererCanvas *canvas) cairo_get_matrix(ctx, &matrix); } - GetGlobalTransform(ctx, cairoCanvas); + if (NS_FAILED(GetGlobalTransform(ctx, cairoCanvas))) { + if (renderMode == nsISVGRendererCanvas::SVG_RENDER_MODE_NORMAL) + cairo_restore(ctx); + delete [] cp; + return NS_ERROR_FAILURE; + } metrics->SelectFont(ctx); @@ -297,9 +302,11 @@ nsSVGCairoGlyphGeometry::Render(nsISVGRendererCanvas *canvas) mSource->GetFillGradient(getter_AddRefs(aGrad)); cairo_pattern_t *gradient = CairoGradient(ctx, aGrad, mSource); - cairo_set_source(ctx, gradient); - LOOP_CHARS(cairo_show_text) - cairo_pattern_destroy(gradient); + if (gradient) { + cairo_set_source(ctx, gradient); + LOOP_CHARS(cairo_show_text) + cairo_pattern_destroy(gradient); + } } else if (fillServerType == nsISVGGeometrySource::PAINT_TYPE_PATTERN) { nsCOMPtr aPat; mSource->GetFillPattern(getter_AddRefs(aPat)); @@ -390,9 +397,11 @@ nsSVGCairoGlyphGeometry::Render(nsISVGRendererCanvas *canvas) mSource->GetStrokeGradient(getter_AddRefs(aGrad)); cairo_pattern_t *gradient = CairoGradient(ctx, aGrad, mSource); - cairo_set_source(ctx, gradient); - cairo_stroke(ctx); - cairo_pattern_destroy(gradient); + if (gradient) { + cairo_set_source(ctx, gradient); + cairo_stroke(ctx); + cairo_pattern_destroy(gradient); + } } else if (strokeServerType == nsISVGGeometrySource::PAINT_TYPE_PATTERN) { nsCOMPtr aPat; mSource->GetStrokePattern(getter_AddRefs(aPat)); @@ -486,7 +495,10 @@ nsSVGCairoGlyphGeometry::GetCoveredRegion(nsISVGRendererRegion **_retval) return NS_ERROR_FAILURE; } - GetGlobalTransform(ctx, nsnull); + if (NS_FAILED(GetGlobalTransform(ctx, nsnull))) { + cairo_destroy(ctx); + return NS_ERROR_FAILURE; + } metrics->SelectFont(ctx); @@ -626,7 +638,10 @@ nsSVGCairoGlyphGeometry::ContainsPoint(float x, float y, PRBool *_retval) } cairo_t *ctx = cairo_create(gSVGCairoDummySurface); - GetGlobalTransform(ctx, nsnull); + if (NS_FAILED(GetGlobalTransform(ctx, nsnull))) { + cairo_destroy(ctx); + return NS_ERROR_FAILURE; + } metrics->SelectFont(ctx); @@ -684,7 +699,7 @@ nsSVGCairoGlyphGeometry::ContainsPoint(float x, float y, PRBool *_retval) } -void +nsresult nsSVGCairoGlyphGeometry::GetGlobalTransform(cairo_t *ctx, nsISVGCairoCanvas* aCanvas) { nsCOMPtr ctm; @@ -715,7 +730,15 @@ nsSVGCairoGlyphGeometry::GetGlobalTransform(cairo_t *ctx, nsISVGCairoCanvas* aCa if (aCanvas) { aCanvas->AdjustMatrixForInitialTransform(&matrix); } + + cairo_matrix_t inverse = matrix; + if (cairo_matrix_invert(&inverse)) { + cairo_identity_matrix(ctx); + return NS_ERROR_FAILURE; + } + cairo_set_matrix(ctx, &matrix); + return NS_OK; } NS_IMETHODIMP @@ -741,7 +764,11 @@ nsSVGCairoGlyphGeometry::GetBoundingBox(nsIDOMSVGRect * *aBoundingBox) cairo_t *ctx = cairo_create(gSVGCairoDummySurface); - GetGlobalTransform(ctx, nsnull); + if (NS_FAILED(GetGlobalTransform(ctx, nsnull))) { + cairo_destroy(ctx); + delete [] cp; + return NS_ERROR_FAILURE; + } /* get the metrics */ nsCOMPtr metrics; @@ -750,8 +777,10 @@ nsSVGCairoGlyphGeometry::GetBoundingBox(nsIDOMSVGRect * *aBoundingBox) mSource->GetMetrics(getter_AddRefs(xpmetrics)); metrics = do_QueryInterface(xpmetrics); NS_ASSERTION(metrics, "wrong metrics object!"); - if (!metrics) + if (!metrics) { + delete [] cp; return NS_ERROR_FAILURE; + } } metrics->SelectFont(ctx); diff --git a/layout/svg/renderer/src/cairo/nsSVGCairoGradient.cpp b/layout/svg/renderer/src/cairo/nsSVGCairoGradient.cpp index 5b456488436..dd1def158de 100644 --- a/layout/svg/renderer/src/cairo/nsSVGCairoGradient.cpp +++ b/layout/svg/renderer/src/cairo/nsSVGCairoGradient.cpp @@ -134,7 +134,7 @@ CairoGradient(cairo_t *ctx, nsISVGGradient *aGrad, { NS_ASSERTION(aGrad, "Called CairoGradient without a gradient!"); if (!aGrad) - return NULL; + return nsnull; // Get the transform list (if there is one) nsCOMPtr svgMatrix; @@ -142,6 +142,9 @@ CairoGradient(cairo_t *ctx, nsISVGGradient *aGrad, NS_ASSERTION(svgMatrix, "CairoGradient: GetGradientTransform returns null"); cairo_matrix_t patternMatrix = SVGToMatrix(svgMatrix); + if (cairo_matrix_invert(&patternMatrix)) { + return nsnull; + } cairo_pattern_t *gradient; @@ -153,7 +156,7 @@ CairoGradient(cairo_t *ctx, nsISVGGradient *aGrad, else if (type == nsISVGGradient::SVG_RADIAL_GRADIENT) gradient = CairoRadialGradient(ctx, aGrad); else - return NULL; // Shouldn't happen + return nsnull; // Shouldn't happen PRUint16 aSpread; aGrad->GetSpreadMethod(&aSpread); @@ -164,7 +167,6 @@ CairoGradient(cairo_t *ctx, nsISVGGradient *aGrad, else if (aSpread == nsIDOMSVGGradientElement::SVG_SPREADMETHOD_REPEAT) cairo_pattern_set_extend(gradient, CAIRO_EXTEND_REPEAT); - cairo_matrix_invert(&patternMatrix); cairo_pattern_set_matrix(gradient, &patternMatrix); CairoSetStops(gradient, aGrad); diff --git a/layout/svg/renderer/src/cairo/nsSVGCairoPathGeometry.cpp b/layout/svg/renderer/src/cairo/nsSVGCairoPathGeometry.cpp index 34a21f6d649..032ce88306c 100644 --- a/layout/svg/renderer/src/cairo/nsSVGCairoPathGeometry.cpp +++ b/layout/svg/renderer/src/cairo/nsSVGCairoPathGeometry.cpp @@ -182,6 +182,13 @@ nsSVGCairoPathGeometry::GeneratePath(cairo_t *ctx, nsISVGCairoCanvas* aCanvas) if (aCanvas) { aCanvas->AdjustMatrixForInitialTransform(&matrix); } + + cairo_matrix_t inverse = matrix; + if (cairo_matrix_invert(&inverse)) { + cairo_identity_matrix(ctx); + cairo_new_path(ctx); + return; + } cairo_set_matrix(ctx, &matrix); nsCOMPtr builder; @@ -350,9 +357,11 @@ nsSVGCairoPathGeometry::Render(nsISVGRendererCanvas *canvas) mSource->GetFillGradient(getter_AddRefs(aGrad)); cairo_pattern_t *gradient = CairoGradient(ctx, aGrad, mSource); - cairo_set_source(ctx, gradient); - cairo_fill_preserve(ctx); - cairo_pattern_destroy(gradient); + if (gradient) { + cairo_set_source(ctx, gradient); + cairo_fill_preserve(ctx); + cairo_pattern_destroy(gradient); + } } else if (fillServerType == nsISVGGeometrySource::PAINT_TYPE_PATTERN) { nsCOMPtr aPat; mSource->GetFillPattern(getter_AddRefs(aPat)); @@ -392,9 +401,11 @@ nsSVGCairoPathGeometry::Render(nsISVGRendererCanvas *canvas) mSource->GetStrokeGradient(getter_AddRefs(aGrad)); cairo_pattern_t *gradient = CairoGradient(ctx, aGrad, mSource); - cairo_set_source(ctx, gradient); - cairo_stroke(ctx); - cairo_pattern_destroy(gradient); + if (gradient) { + cairo_set_source(ctx, gradient); + cairo_stroke(ctx); + cairo_pattern_destroy(gradient); + } } else if (strokeServerType == nsISVGGeometrySource::PAINT_TYPE_PATTERN) { nsCOMPtr aPat; mSource->GetStrokePattern(getter_AddRefs(aPat)); diff --git a/layout/svg/renderer/src/cairo/nsSVGCairoPattern.cpp b/layout/svg/renderer/src/cairo/nsSVGCairoPattern.cpp index 39c190d4d61..6c2413e2b7e 100644 --- a/layout/svg/renderer/src/cairo/nsSVGCairoPattern.cpp +++ b/layout/svg/renderer/src/cairo/nsSVGCairoPattern.cpp @@ -113,11 +113,15 @@ CairoPattern(nsISVGRendererCanvas *canvas, nsISVGPattern *aPat, // Translate the pattern frame cairo_matrix_t pmatrix = SVGToMatrix(pMatrix); - cairo_matrix_invert(&pmatrix); + if (cairo_matrix_invert(&pmatrix)) + return nsnull; - cairo_pattern_t *surface_pattern = cairo_pattern_create_for_surface(pattern_surface); - cairo_pattern_set_matrix (surface_pattern, &pmatrix); - cairo_pattern_set_extend (surface_pattern, CAIRO_EXTEND_REPEAT); + cairo_pattern_t *surface_pattern = + cairo_pattern_create_for_surface(pattern_surface); + if (surface_pattern) { + cairo_pattern_set_matrix (surface_pattern, &pmatrix); + cairo_pattern_set_extend (surface_pattern, CAIRO_EXTEND_REPEAT); + } return surface_pattern; }