From 1caf0da9773aa3439eeb66b28b0381925c82d5a4 Mon Sep 17 00:00:00 2001 From: Robert Longson Date: Sun, 29 Mar 2009 14:58:09 +0100 Subject: [PATCH] Bug 484677 - Mouse coordinates in zoomed foreignObject are calculated incorrectly. r+sr=roc --- .../svg/base/src/nsSVGForeignObjectFrame.cpp | 87 ++++++++++--------- layout/svg/base/src/nsSVGForeignObjectFrame.h | 2 +- 2 files changed, 48 insertions(+), 41 deletions(-) diff --git a/layout/svg/base/src/nsSVGForeignObjectFrame.cpp b/layout/svg/base/src/nsSVGForeignObjectFrame.cpp index ce12c14c75f5..18bca3b3de35 100644 --- a/layout/svg/base/src/nsSVGForeignObjectFrame.cpp +++ b/layout/svg/base/src/nsSVGForeignObjectFrame.cpp @@ -233,22 +233,7 @@ nsSVGForeignObjectFrame::PaintSVG(nsSVGRenderState *aContext, if (!kid) return NS_OK; - // GetCanvasTM includes a device pixel to CSS pixel scaling. Since non-SVG - // content takes care of this itself, we need to remove this pre-scaling from - // the matrix returned by GetTMIncludingOffset before painting our children. - float cssPxPerDevPx = - PresContext()->AppUnitsToFloatCSSPixels( - PresContext()->AppUnitsPerDevPixel()); - nsCOMPtr cssPxToDevPxMatrix; - NS_NewSVGMatrix(getter_AddRefs(cssPxToDevPxMatrix), - cssPxPerDevPx, 0.0f, - 0.0f, cssPxPerDevPx); - - nsCOMPtr localTM = GetTMIncludingOffset(); - - // POST-multiply px conversion! - nsCOMPtr tm; - localTM->Multiply(cssPxToDevPxMatrix, getter_AddRefs(tm)); + nsCOMPtr tm = GetUnZoomedTMIncludingOffset(); gfxMatrix matrix = nsSVGUtils::ConvertSVGMatrixToThebes(tm); @@ -280,8 +265,8 @@ nsSVGForeignObjectFrame::PaintSVG(nsSVGRenderState *aContext, static_cast(mContent)-> GetAnimatedLengthValues(&x, &y, &width, &height, nsnull); - // tm already includes the x,y offset - nsSVGUtils::SetClipRect(gfx, localTM, 0.0f, 0.0f, width, height); + nsCOMPtr ctm = GetCanvasTM(); + nsSVGUtils::SetClipRect(gfx, ctm, x, y, width, height); } gfx->Multiply(matrix); @@ -301,7 +286,8 @@ nsSVGForeignObjectFrame::TransformPointFromOuterPx(const nsPoint &aIn, if (GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD) return NS_ERROR_FAILURE; - nsCOMPtr tm = GetTMIncludingOffset(); + nsCOMPtr tm = GetUnZoomedTMIncludingOffset(); + nsCOMPtr inverse; nsresult rv = tm->Inverse(getter_AddRefs(inverse)); if (NS_FAILED(rv)) @@ -325,8 +311,9 @@ nsSVGForeignObjectFrame::GetTransformMatrix(nsIFrame **aOutAncestor) NS_ASSERTION(*aOutAncestor, "How did we end up without an outer frame?"); /* Return the matrix back to the root, factoring in the x and y offsets. */ - nsCOMPtr matrix = GetTMIncludingOffset(); - return nsSVGUtils::ConvertSVGMatrixToThebes(matrix); + nsCOMPtr tm = GetUnZoomedTMIncludingOffset(); + + return nsSVGUtils::ConvertSVGMatrixToThebes(tm); } NS_IMETHODIMP_(nsIFrame*) @@ -512,22 +499,6 @@ nsSVGForeignObjectFrame::GetBBox(nsIDOMSVGRect **_retval) //---------------------------------------------------------------------- -already_AddRefed -nsSVGForeignObjectFrame::GetTMIncludingOffset() -{ - nsCOMPtr ctm = GetCanvasTM(); - if (!ctm) - return nsnull; - - nsSVGForeignObjectElement *fO = - static_cast(mContent); - float x, y; - fO->GetAnimatedLengthValues(&x, &y, nsnull); - nsIDOMSVGMatrix* matrix; - ctm->Translate(x, y, &matrix); - return matrix; -} - already_AddRefed nsSVGForeignObjectFrame::GetCanvasTM() { @@ -564,6 +535,34 @@ nsSVGForeignObjectFrame::GetCanvasTM() //---------------------------------------------------------------------- // Implementation helpers +already_AddRefed +nsSVGForeignObjectFrame::GetUnZoomedTMIncludingOffset() +{ + nsCOMPtr ctm = GetCanvasTM(); + if (!ctm) + return nsnull; + + nsSVGForeignObjectElement *fO = + static_cast(mContent); + float x, y; + fO->GetAnimatedLengthValues(&x, &y, nsnull); + nsCOMPtr localTM; + ctm->Translate(x, y, getter_AddRefs(localTM)); + + float cssPxPerDevPx = + PresContext()->AppUnitsToFloatCSSPixels( + PresContext()->AppUnitsPerDevPixel()); + nsCOMPtr cssPxToDevPxMatrix; + NS_NewSVGMatrix(getter_AddRefs(cssPxToDevPxMatrix), + cssPxPerDevPx, 0.0f, + 0.0f, cssPxPerDevPx); + + // POST-multiply px conversion! + nsIDOMSVGMatrix* matrix; + localTM->Multiply(cssPxToDevPxMatrix, &matrix); + return matrix; +} + void nsSVGForeignObjectFrame::RequestReflow(nsIPresShell::IntrinsicDirty aType) { if (GetStateBits() & NS_FRAME_FIRST_REFLOW) @@ -684,10 +683,18 @@ nsSVGForeignObjectFrame::InvalidateDirtyRect(nsSVGOuterSVGFrame* aOuter, return; nsPresContext* presContext = PresContext(); - nsCOMPtr tm = GetTMIncludingOffset(); + nsCOMPtr ctm = GetCanvasTM(); + + nsSVGForeignObjectElement *fO = + static_cast(mContent); + float x, y; + fO->GetAnimatedLengthValues(&x, &y, nsnull); + nsCOMPtr localTM; + ctm->Translate(x, y, getter_AddRefs(localTM)); + nsIntRect r = nsRect::ToOutsidePixels(aRect, presContext->AppUnitsPerDevPixel()); - float x = r.x, y = r.y, w = r.width, h = r.height; - nsRect rect = GetTransformedRegion(x, y, w, h, tm, presContext); + nsRect rect = GetTransformedRegion(r.x, r.y, r.width, r.height, + localTM, presContext); // XXX invalidate the entire covered region // See bug 418063 diff --git a/layout/svg/base/src/nsSVGForeignObjectFrame.h b/layout/svg/base/src/nsSVGForeignObjectFrame.h index d0668a6baeab..5344c3c05923 100644 --- a/layout/svg/base/src/nsSVGForeignObjectFrame.h +++ b/layout/svg/base/src/nsSVGForeignObjectFrame.h @@ -148,7 +148,7 @@ protected: void DoReflow(); void RequestReflow(nsIPresShell::IntrinsicDirty aType); void UpdateGraphic(); - already_AddRefed GetTMIncludingOffset(); + already_AddRefed GetUnZoomedTMIncludingOffset(); nsresult TransformPointFromOuterPx(const nsPoint &aIn, nsPoint* aOut); void InvalidateDirtyRect(nsSVGOuterSVGFrame* aOuter, const nsRect& aRect, PRUint32 aFlags);