diff --git a/layout/svg/base/src/nsISVGChildFrame.h b/layout/svg/base/src/nsISVGChildFrame.h index 2841f9637daa..ad5b28476745 100644 --- a/layout/svg/base/src/nsISVGChildFrame.h +++ b/layout/svg/base/src/nsISVGChildFrame.h @@ -64,6 +64,18 @@ public: // be called by nsSVGOuterSVGFrame during its reflow. virtual void UpdateBounds()=0; + /** + * Flags used to specify to GetCanvasTM what it's being called for so that it + * knows how far up the tree the "canvas" is. When display lists are being + * used for painting or hit-testing of SVG, the "canvas" is simply user + * space. + */ + enum RequestingCanvasTMFor { + FOR_PAINTING = 1, + FOR_HIT_TESTING, + FOR_OUTERSVG_TM + }; + // Flags to pass to NotifySVGChange: // // DO_NOT_NOTIFY_RENDERING_OBSERVERS - this should only be used when diff --git a/layout/svg/base/src/nsSVGAFrame.cpp b/layout/svg/base/src/nsSVGAFrame.cpp index 256ca0393dc5..915548a027a0 100644 --- a/layout/svg/base/src/nsSVGAFrame.cpp +++ b/layout/svg/base/src/nsSVGAFrame.cpp @@ -6,6 +6,7 @@ // Keep in (case-insensitive) order: #include "gfxMatrix.h" #include "nsSVGAElement.h" +#include "nsSVGIntegrationUtils.h" #include "nsSVGTSpanFrame.h" #include "nsSVGUtils.h" #include "SVGLengthList.h" @@ -58,7 +59,7 @@ public: virtual void NotifySVGChanged(PRUint32 aFlags); // nsSVGContainerFrame methods: - virtual gfxMatrix GetCanvasTM(); + virtual gfxMatrix GetCanvasTM(PRUint32 aFor); // nsSVGTextContainerFrame methods: virtual void GetXY(mozilla::SVGUserUnitList *aX, mozilla::SVGUserUnitList *aY); @@ -144,15 +145,21 @@ nsSVGAFrame::NotifySVGChanged(PRUint32 aFlags) // nsSVGContainerFrame methods: gfxMatrix -nsSVGAFrame::GetCanvasTM() +nsSVGAFrame::GetCanvasTM(PRUint32 aFor) { + if (!(GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD)) { + if ((aFor == FOR_PAINTING && NS_SVGDisplayListPaintingEnabled()) || + (aFor == FOR_HIT_TESTING && NS_SVGDisplayListHitTestingEnabled())) { + return nsSVGIntegrationUtils::GetCSSPxToDevPxMatrix(this); + } + } if (!mCanvasTM) { NS_ASSERTION(mParent, "null parent"); nsSVGContainerFrame *parent = static_cast(mParent); nsSVGAElement *content = static_cast(mContent); - gfxMatrix tm = content->PrependLocalTransformsTo(parent->GetCanvasTM()); + gfxMatrix tm = content->PrependLocalTransformsTo(parent->GetCanvasTM(aFor)); mCanvasTM = new gfxMatrix(tm); } diff --git a/layout/svg/base/src/nsSVGClipPathFrame.cpp b/layout/svg/base/src/nsSVGClipPathFrame.cpp index 991468877e28..4c857fec9088 100644 --- a/layout/svg/base/src/nsSVGClipPathFrame.cpp +++ b/layout/svg/base/src/nsSVGClipPathFrame.cpp @@ -317,7 +317,7 @@ nsSVGClipPathFrame::GetType() const } gfxMatrix -nsSVGClipPathFrame::GetCanvasTM() +nsSVGClipPathFrame::GetCanvasTM(PRUint32 aFor) { nsSVGClipPathElement *content = static_cast(mContent); diff --git a/layout/svg/base/src/nsSVGClipPathFrame.h b/layout/svg/base/src/nsSVGClipPathFrame.h index f7097fcd5bad..116a5f2f24ef 100644 --- a/layout/svg/base/src/nsSVGClipPathFrame.h +++ b/layout/svg/base/src/nsSVGClipPathFrame.h @@ -95,7 +95,7 @@ public: bool mInUse; // nsSVGContainerFrame methods: - virtual gfxMatrix GetCanvasTM(); + virtual gfxMatrix GetCanvasTM(PRUint32 aFor); }; #endif diff --git a/layout/svg/base/src/nsSVGContainerFrame.h b/layout/svg/base/src/nsSVGContainerFrame.h index 2ca7e165f803..b2fdc6cf77c5 100644 --- a/layout/svg/base/src/nsSVGContainerFrame.h +++ b/layout/svg/base/src/nsSVGContainerFrame.h @@ -50,7 +50,9 @@ public: NS_DECL_FRAMEARENA_HELPERS // Returns the transform to our gfxContext (to device pixels, not CSS px) - virtual gfxMatrix GetCanvasTM() { return gfxMatrix(); } + virtual gfxMatrix GetCanvasTM(PRUint32 aFor) { + return gfxMatrix(); + } /** * Returns true if the frame's content has a transform that applies only to diff --git a/layout/svg/base/src/nsSVGFilterFrame.cpp b/layout/svg/base/src/nsSVGFilterFrame.cpp index 3063553141b4..d49e27be88b1 100644 --- a/layout/svg/base/src/nsSVGFilterFrame.cpp +++ b/layout/svg/base/src/nsSVGFilterFrame.cpp @@ -207,7 +207,8 @@ nsAutoFilterInstance::nsAutoFilterInstance(nsIFrame *aTarget, } else { // Match filterRes as closely as possible to the pixel density of the nearest // outer 'svg' device space: - gfxMatrix canvasTM = nsSVGUtils::GetCanvasTM(aTarget); + gfxMatrix canvasTM = + nsSVGUtils::GetCanvasTM(aTarget, nsISVGChildFrame::FOR_OUTERSVG_TM); if (canvasTM.IsSingular()) { // nothing to draw return; @@ -233,8 +234,8 @@ nsAutoFilterInstance::nsAutoFilterInstance(nsIFrame *aTarget, // Only used (so only set) when we paint: gfxMatrix filterToDeviceSpace; if (aPaint) { - filterToDeviceSpace = - filterToUserSpace * nsSVGUtils::GetCanvasTM(aTarget); + filterToDeviceSpace = filterToUserSpace * + nsSVGUtils::GetCanvasTM(aTarget, nsISVGChildFrame::FOR_PAINTING); } // Convert the passed in rects from frame to filter space: diff --git a/layout/svg/base/src/nsSVGForeignObjectFrame.cpp b/layout/svg/base/src/nsSVGForeignObjectFrame.cpp index 60365845f4e0..c225385b27b2 100644 --- a/layout/svg/base/src/nsSVGForeignObjectFrame.cpp +++ b/layout/svg/base/src/nsSVGForeignObjectFrame.cpp @@ -18,6 +18,7 @@ #include "nsSVGContainerFrame.h" #include "nsSVGEffects.h" #include "nsSVGForeignObjectElement.h" +#include "nsSVGIntegrationUtils.h" #include "nsSVGOuterSVGFrame.h" #include "nsSVGUtils.h" #include "mozilla/AutoRestore.h" @@ -192,10 +193,9 @@ nsSVGForeignObjectFrame::PaintSVG(nsRenderingContext *aContext, if (!kid) return NS_OK; - gfxMatrix matrixForChildren = GetCanvasTMForChildren(); - gfxMatrix matrix = GetCanvasTM(); + gfxMatrix canvasTM = GetCanvasTM(FOR_PAINTING); - if (matrixForChildren.IsSingular()) { + if (canvasTM.IsSingular()) { NS_WARNING("Can't render foreignObject element!"); return NS_ERROR_FAILURE; } @@ -205,7 +205,7 @@ nsSVGForeignObjectFrame::PaintSVG(nsRenderingContext *aContext, /* Check if we need to draw anything. */ if (aDirtyRect) { // Transform the dirty rect into app units in our userspace. - gfxMatrix invmatrix = matrix; + gfxMatrix invmatrix = canvasTM; invmatrix.Invert(); NS_ASSERTION(!invmatrix.IsSingular(), "inverse of non-singular matrix should be non-singular"); @@ -237,10 +237,18 @@ nsSVGForeignObjectFrame::PaintSVG(nsRenderingContext *aContext, gfxRect clipRect = nsSVGUtils::GetClipRectForFrame(this, 0.0f, 0.0f, width, height); - nsSVGUtils::SetClipRect(gfx, matrix, clipRect); + nsSVGUtils::SetClipRect(gfx, canvasTM, clipRect); } - gfx->Multiply(matrixForChildren); + // SVG paints in CSS px, but normally frames paint in dev pixels. Here we + // multiply a CSS-px-to-dev-pixel factor onto canvasTM so our children paint + // correctly. + float cssPxPerDevPx = PresContext()-> + AppUnitsToFloatCSSPixels(PresContext()->AppUnitsPerDevPixel()); + gfxMatrix canvasTMForChildren = canvasTM; + canvasTMForChildren.Scale(cssPxPerDevPx, cssPxPerDevPx); + + gfx->Multiply(canvasTMForChildren); PRUint32 flags = nsLayoutUtils::PAINT_IN_TRANSFORM; if (SVGAutoRenderState::IsPaintingToWindow(aContext)) { @@ -268,7 +276,7 @@ nsSVGForeignObjectFrame::GetFrameForPoint(const nsPoint &aPoint) static_cast(mContent)-> GetAnimatedLengthValues(&x, &y, &width, &height, nsnull); - gfxMatrix tm = GetCanvasTM().Invert(); + gfxMatrix tm = GetCanvasTM(FOR_HIT_TESTING).Invert(); if (tm.IsSingular()) return nsnull; @@ -328,7 +336,8 @@ nsSVGForeignObjectFrame::UpdateBounds() gfxRect(x, y, w, h), PresContext()->AppUnitsPerCSSPixel()); // GetCanvasTM includes the x,y translation - mCoveredRegion = ToCanvasBounds(gfxRect(0.0, 0.0, w, h), GetCanvasTM(), PresContext()); + mCoveredRegion = ToCanvasBounds(gfxRect(0.0, 0.0, w, h), + GetCanvasTM(FOR_OUTERSVG_TM), PresContext()); // Fully mark our kid dirty so that it gets resized if necessary // (NS_FRAME_HAS_DIRTY_CHILDREN isn't enough in that case): @@ -463,8 +472,14 @@ nsSVGForeignObjectFrame::GetBBoxContribution(const gfxMatrix &aToBBoxUserspace, //---------------------------------------------------------------------- gfxMatrix -nsSVGForeignObjectFrame::GetCanvasTM() +nsSVGForeignObjectFrame::GetCanvasTM(PRUint32 aFor) { + if (!(GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD)) { + if ((aFor == FOR_PAINTING && NS_SVGDisplayListPaintingEnabled()) || + (aFor == FOR_HIT_TESTING && NS_SVGDisplayListHitTestingEnabled())) { + return nsSVGIntegrationUtils::GetCSSPxToDevPxMatrix(this); + } + } if (!mCanvasTM) { NS_ASSERTION(mParent, "null parent"); @@ -472,7 +487,7 @@ nsSVGForeignObjectFrame::GetCanvasTM() nsSVGForeignObjectElement *content = static_cast(mContent); - gfxMatrix tm = content->PrependLocalTransformsTo(parent->GetCanvasTM()); + gfxMatrix tm = content->PrependLocalTransformsTo(parent->GetCanvasTM(aFor)); mCanvasTM = new gfxMatrix(tm); } @@ -482,15 +497,6 @@ nsSVGForeignObjectFrame::GetCanvasTM() //---------------------------------------------------------------------- // Implementation helpers -gfxMatrix -nsSVGForeignObjectFrame::GetCanvasTMForChildren() -{ - float cssPxPerDevPx = PresContext()-> - AppUnitsToFloatCSSPixels(PresContext()->AppUnitsPerDevPixel()); - - return GetCanvasTM().Scale(cssPxPerDevPx, cssPxPerDevPx); -} - void nsSVGForeignObjectFrame::RequestReflow(nsIPresShell::IntrinsicDirty aType) { if (GetStateBits() & NS_FRAME_FIRST_REFLOW) @@ -560,7 +566,7 @@ nsSVGForeignObjectFrame::GetInvalidRegion() if (kid->HasInvalidFrameInSubtree()) { gfxRect r(mRect.x, mRect.y, mRect.width, mRect.height); r.Scale(1.0 / nsPresContext::AppUnitsPerCSSPixel()); - nsRect rect = ToCanvasBounds(r, GetCanvasTM(), PresContext()); + nsRect rect = ToCanvasBounds(r, GetCanvasTM(FOR_OUTERSVG_TM), PresContext()); rect = nsSVGUtils::GetPostFilterVisualOverflowRect(this, rect); return rect; } diff --git a/layout/svg/base/src/nsSVGForeignObjectFrame.h b/layout/svg/base/src/nsSVGForeignObjectFrame.h index b786eef7a901..9cc327f97dcb 100644 --- a/layout/svg/base/src/nsSVGForeignObjectFrame.h +++ b/layout/svg/base/src/nsSVGForeignObjectFrame.h @@ -80,7 +80,7 @@ public: PRUint32 aFlags); NS_IMETHOD_(bool) IsDisplayContainer() { return true; } - gfxMatrix GetCanvasTM(); + gfxMatrix GetCanvasTM(PRUint32 aFor); nsRect GetInvalidRegion(); @@ -89,10 +89,6 @@ protected: void DoReflow(); void RequestReflow(nsIPresShell::IntrinsicDirty aType); - // Returns GetCanvasTM followed by a scale from CSS px to Dev px. Used for - // painting, because children expect to paint to device space, not userspace. - gfxMatrix GetCanvasTMForChildren(); - // If width or height is less than or equal to zero we must disable rendering bool IsDisabled() const { return mRect.width <= 0 || mRect.height <= 0; } diff --git a/layout/svg/base/src/nsSVGGFrame.cpp b/layout/svg/base/src/nsSVGGFrame.cpp index 38a3ff398f91..d99be16b9fe2 100644 --- a/layout/svg/base/src/nsSVGGFrame.cpp +++ b/layout/svg/base/src/nsSVGGFrame.cpp @@ -11,6 +11,7 @@ #include "nsIDOMSVGTransformable.h" #include "nsIFrame.h" #include "nsSVGGraphicElement.h" +#include "nsSVGIntegrationUtils.h" #include "nsSVGUtils.h" //---------------------------------------------------------------------- @@ -66,15 +67,21 @@ nsSVGGFrame::NotifySVGChanged(PRUint32 aFlags) } gfxMatrix -nsSVGGFrame::GetCanvasTM() +nsSVGGFrame::GetCanvasTM(PRUint32 aFor) { + if (!(GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD)) { + if ((aFor == FOR_PAINTING && NS_SVGDisplayListPaintingEnabled()) || + (aFor == FOR_HIT_TESTING && NS_SVGDisplayListHitTestingEnabled())) { + return nsSVGIntegrationUtils::GetCSSPxToDevPxMatrix(this); + } + } if (!mCanvasTM) { NS_ASSERTION(mParent, "null parent"); nsSVGContainerFrame *parent = static_cast(mParent); nsSVGGraphicElement *content = static_cast(mContent); - gfxMatrix tm = content->PrependLocalTransformsTo(parent->GetCanvasTM()); + gfxMatrix tm = content->PrependLocalTransformsTo(parent->GetCanvasTM(aFor)); mCanvasTM = new gfxMatrix(tm); } diff --git a/layout/svg/base/src/nsSVGGFrame.h b/layout/svg/base/src/nsSVGGFrame.h index abbcba3dd73f..a631f966407c 100644 --- a/layout/svg/base/src/nsSVGGFrame.h +++ b/layout/svg/base/src/nsSVGGFrame.h @@ -51,7 +51,7 @@ public: virtual void NotifySVGChanged(PRUint32 aFlags); // nsSVGContainerFrame methods: - virtual gfxMatrix GetCanvasTM(); + virtual gfxMatrix GetCanvasTM(PRUint32 aFor); nsAutoPtr mCanvasTM; }; diff --git a/layout/svg/base/src/nsSVGGenericContainerFrame.cpp b/layout/svg/base/src/nsSVGGenericContainerFrame.cpp index f294dacf60df..79e96195eca2 100644 --- a/layout/svg/base/src/nsSVGGenericContainerFrame.cpp +++ b/layout/svg/base/src/nsSVGGenericContainerFrame.cpp @@ -5,6 +5,7 @@ // Main header first: #include "nsSVGGenericContainerFrame.h" +#include "nsSVGIntegrationUtils.h" //---------------------------------------------------------------------- // nsSVGGenericContainerFrame Implementation @@ -45,9 +46,16 @@ nsSVGGenericContainerFrame::GetType() const // nsSVGContainerFrame methods: gfxMatrix -nsSVGGenericContainerFrame::GetCanvasTM() +nsSVGGenericContainerFrame::GetCanvasTM(PRUint32 aFor) { + if (!(GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD)) { + if ((aFor == FOR_PAINTING && NS_SVGDisplayListPaintingEnabled()) || + (aFor == FOR_HIT_TESTING && NS_SVGDisplayListHitTestingEnabled())) { + return nsSVGIntegrationUtils::GetCSSPxToDevPxMatrix(this); + } + } + NS_ASSERTION(mParent, "null parent"); - return static_cast(mParent)->GetCanvasTM(); + return static_cast(mParent)->GetCanvasTM(aFor); } diff --git a/layout/svg/base/src/nsSVGGenericContainerFrame.h b/layout/svg/base/src/nsSVGGenericContainerFrame.h index e964c7462cd8..9c0d85153ce1 100644 --- a/layout/svg/base/src/nsSVGGenericContainerFrame.h +++ b/layout/svg/base/src/nsSVGGenericContainerFrame.h @@ -48,7 +48,7 @@ public: #endif // nsSVGContainerFrame methods: - virtual gfxMatrix GetCanvasTM(); + virtual gfxMatrix GetCanvasTM(PRUint32 aFor); }; #endif // __NS_SVGGENERICCONTAINERFRAME_H__ diff --git a/layout/svg/base/src/nsSVGGeometryFrame.h b/layout/svg/base/src/nsSVGGeometryFrame.h index 50375cff9630..b08427679768 100644 --- a/layout/svg/base/src/nsSVGGeometryFrame.h +++ b/layout/svg/base/src/nsSVGGeometryFrame.h @@ -56,7 +56,7 @@ public: } // nsSVGGeometryFrame methods: - virtual gfxMatrix GetCanvasTM() = 0; + virtual gfxMatrix GetCanvasTM(PRUint32 aFor) = 0; PRUint16 GetClipRule(); float GetStrokeWidth(); diff --git a/layout/svg/base/src/nsSVGGlyphFrame.cpp b/layout/svg/base/src/nsSVGGlyphFrame.cpp index 0b2199aebc38..f767028942a7 100644 --- a/layout/svg/base/src/nsSVGGlyphFrame.cpp +++ b/layout/svg/base/src/nsSVGGlyphFrame.cpp @@ -17,6 +17,7 @@ #include "nsIDOMSVGRect.h" #include "nsRenderingContext.h" #include "nsSVGEffects.h" +#include "nsSVGIntegrationUtils.h" #include "nsSVGPaintServerFrame.h" #include "nsSVGRect.h" #include "nsSVGTextPathFrame.h" @@ -309,6 +310,8 @@ nsSVGGlyphFrame::PaintSVG(nsRenderingContext *aContext, return NS_OK; } + AutoCanvasTMForMarker autoCanvasTMFor(this, FOR_PAINTING); + gfxContext *gfx = aContext->ThebesContext(); PRUint16 renderMode = SVGAutoRenderState::GetRenderMode(aContext); @@ -326,7 +329,7 @@ nsSVGGlyphFrame::PaintSVG(nsRenderingContext *aContext, renderMode == SVGAutoRenderState::CLIP_MASK, "Unknown render mode"); gfxContextMatrixAutoSaveRestore matrixAutoSaveRestore(gfx); - SetupGlobalTransform(gfx); + SetupGlobalTransform(gfx, FOR_PAINTING); CharacterIterator iter(this, true); iter.SetInitialMatrix(gfx); @@ -349,7 +352,7 @@ nsSVGGlyphFrame::PaintSVG(nsRenderingContext *aContext, // We are adding patterns or gradients to the context. Save // it so we don't leak them into the next object we draw gfx->Save(); - SetupGlobalTransform(gfx); + SetupGlobalTransform(gfx, FOR_PAINTING); CharacterIterator iter(this, true); iter.SetInitialMatrix(gfx); @@ -374,8 +377,10 @@ nsSVGGlyphFrame::GetFrameForPoint(const nsPoint &aPoint) return nsnull; } + AutoCanvasTMForMarker autoCanvasTMFor(this, FOR_HIT_TESTING); + nsRefPtr tmpCtx = MakeTmpCtx(); - SetupGlobalTransform(tmpCtx); + SetupGlobalTransform(tmpCtx, FOR_HIT_TESTING); CharacterIterator iter(this, true); iter.SetInitialMatrix(tmpCtx); @@ -483,7 +488,7 @@ nsSVGGlyphFrame::UpdateBounds() // See bug 614732 comment 32. mCoveredRegion = nsSVGUtils::TransformFrameRectToOuterSVG( - mRect, GetCanvasTM(), PresContext()); + mRect, GetCanvasTM(FOR_OUTERSVG_TM), PresContext()); nsRect overflow = nsRect(nsPoint(0,0), mRect.Size()); nsOverflowAreas overflowAreas(overflow, overflow); @@ -582,7 +587,7 @@ nsSVGGlyphFrame::GetBBoxContribution(const gfxMatrix &aToBBoxUserspace, } nsRefPtr tmpCtx = MakeTmpCtx(); - SetupGlobalTransform(tmpCtx); + SetupGlobalTransform(tmpCtx, FOR_OUTERSVG_TM); CharacterIterator iter(this, true); iter.SetInitialMatrix(tmpCtx); AddBoundingBoxesToPath(&iter, tmpCtx); @@ -617,13 +622,19 @@ nsSVGGlyphFrame::GetBBoxContribution(const gfxMatrix &aToBBoxUserspace, // nsSVGGeometryFrame methods: gfxMatrix -nsSVGGlyphFrame::GetCanvasTM() +nsSVGGlyphFrame::GetCanvasTM(PRUint32 aFor) { if (mOverrideCanvasTM) { return *mOverrideCanvasTM; } + if (!(GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD)) { + if ((aFor == FOR_PAINTING && NS_SVGDisplayListPaintingEnabled()) || + (aFor == FOR_HIT_TESTING && NS_SVGDisplayListHitTestingEnabled())) { + return nsSVGIntegrationUtils::GetCSSPxToDevPxMatrix(this); + } + } NS_ASSERTION(mParent, "null parent"); - return static_cast(mParent)->GetCanvasTM(); + return static_cast(mParent)->GetCanvasTM(aFor); } //---------------------------------------------------------------------- @@ -1478,9 +1489,9 @@ nsSVGGlyphFrame::NotifyGlyphMetricsChange() } void -nsSVGGlyphFrame::SetupGlobalTransform(gfxContext *aContext) +nsSVGGlyphFrame::SetupGlobalTransform(gfxContext *aContext, PRUint32 aFor) { - gfxMatrix matrix = GetCanvasTM(); + gfxMatrix matrix = GetCanvasTM(aFor); if (!matrix.IsSingular()) { aContext->Multiply(matrix); } @@ -1559,7 +1570,7 @@ nsSVGGlyphFrame::EnsureTextRun(float *aDrawScale, float *aMetricsScale, gfxMatrix m; if (aForceGlobalTransform || !(GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD)) { - m = GetCanvasTM(); + m = GetCanvasTM(mGetCanvasTMForFlag); if (m.IsSingular()) return false; } diff --git a/layout/svg/base/src/nsSVGGlyphFrame.h b/layout/svg/base/src/nsSVGGlyphFrame.h index 0871a07e6aad..3776166898a1 100644 --- a/layout/svg/base/src/nsSVGGlyphFrame.h +++ b/layout/svg/base/src/nsSVGGlyphFrame.h @@ -31,6 +31,9 @@ class nsSVGGlyphFrame : public nsSVGGlyphFrameBase, public nsISVGGlyphFragmentNode, public nsISVGChildFrame { + class AutoCanvasTMForMarker; + friend class AutoCanvasTMForMarker; + friend class CharacterIterator; friend nsIFrame* NS_NewSVGGlyphFrame(nsIPresShell* aPresShell, nsStyleContext* aContext); protected: @@ -38,6 +41,7 @@ protected: : nsSVGGlyphFrameBase(aContext), mTextRun(nsnull), mStartIndex(0), + mGetCanvasTMForFlag(nsISVGChildFrame::FOR_OUTERSVG_TM), mCompressWhitespace(true), mTrimLeadingWhitespace(false), mTrimTrailingWhitespace(false) @@ -154,7 +158,7 @@ public: NS_IMETHOD_(bool) IsDisplayContainer() { return false; } // nsSVGGeometryFrame methods - gfxMatrix GetCanvasTM(); + gfxMatrix GetCanvasTM(PRUint32 aFor); // nsISVGGlyphFragmentNode interface: // These do not use the global transform if NS_STATE_NONDISPLAY_CHILD @@ -171,8 +175,30 @@ public: } } -protected: - friend class CharacterIterator; +private: + + /** + * This class exists purely because it would be too messy to pass the "for" + * flag for GetCanvasTM through the call chains to the GetCanvasTM() call in + * EnsureTextRun. + */ + class AutoCanvasTMForMarker { + public: + AutoCanvasTMForMarker(nsSVGGlyphFrame *aFrame, PRUint32 aFor) + : mFrame(aFrame) + { + mOldFor = mFrame->mGetCanvasTMForFlag; + mFrame->mGetCanvasTMForFlag = aFor; + } + ~AutoCanvasTMForMarker() + { + // Default + mFrame->mGetCanvasTMForFlag = mOldFor; + } + private: + nsSVGGlyphFrame *mFrame; + PRUint32 mOldFor; + }; // Use a power of 2 here. It's not so important to match // nsDeviceContext::AppUnitsPerDevPixel, but since we do a lot of @@ -208,7 +234,7 @@ protected: gfxPattern *aStrokePattern = nsnull); void NotifyGlyphMetricsChange(); - void SetupGlobalTransform(gfxContext *aContext); + void SetupGlobalTransform(gfxContext *aContext, PRUint32 aFor); nsresult GetHighlight(PRUint32 *charnum, PRUint32 *nchars, nscolor *foreground, nscolor *background); float GetSubStringAdvance(PRUint32 charnum, PRUint32 fragmentChars, @@ -227,6 +253,7 @@ protected: gfxPoint mPosition; // The start index into the position and rotation data PRUint32 mStartIndex; + PRUint32 mGetCanvasTMForFlag; bool mCompressWhitespace; bool mTrimLeadingWhitespace; bool mTrimTrailingWhitespace; diff --git a/layout/svg/base/src/nsSVGImageFrame.cpp b/layout/svg/base/src/nsSVGImageFrame.cpp index ddaca976a380..2b54eca01ca9 100644 --- a/layout/svg/base/src/nsSVGImageFrame.cpp +++ b/layout/svg/base/src/nsSVGImageFrame.cpp @@ -92,8 +92,9 @@ public: private: gfxMatrix GetRasterImageTransform(PRInt32 aNativeWidth, - PRInt32 aNativeHeight); - gfxMatrix GetVectorImageTransform(); + PRInt32 aNativeHeight, + PRUint32 aFor); + gfxMatrix GetVectorImageTransform(PRUint32 aFor); bool TransformContextForPainting(gfxContext* aGfxContext); nsCOMPtr mListener; @@ -221,7 +222,9 @@ nsSVGImageFrame::AttributeChanged(PRInt32 aNameSpaceID, } gfxMatrix -nsSVGImageFrame::GetRasterImageTransform(PRInt32 aNativeWidth, PRInt32 aNativeHeight) +nsSVGImageFrame::GetRasterImageTransform(PRInt32 aNativeWidth, + PRInt32 aNativeHeight, + PRUint32 aFor) { float x, y, width, height; nsSVGImageElement *element = static_cast(mContent); @@ -233,11 +236,11 @@ nsSVGImageFrame::GetRasterImageTransform(PRInt32 aNativeWidth, PRInt32 aNativeHe 0, 0, aNativeWidth, aNativeHeight, element->mPreserveAspectRatio); - return viewBoxTM * gfxMatrix().Translate(gfxPoint(x, y)) * GetCanvasTM(); + return viewBoxTM * gfxMatrix().Translate(gfxPoint(x, y)) * GetCanvasTM(aFor); } gfxMatrix -nsSVGImageFrame::GetVectorImageTransform() +nsSVGImageFrame::GetVectorImageTransform(PRUint32 aFor) { float x, y, width, height; nsSVGImageElement *element = static_cast(mContent); @@ -247,7 +250,7 @@ nsSVGImageFrame::GetVectorImageTransform() // "native size" that the SVG image has, and it will handle viewBox and // preserveAspectRatio on its own once we give it a region to draw into. - return gfxMatrix().Translate(gfxPoint(x, y)) * GetCanvasTM(); + return gfxMatrix().Translate(gfxPoint(x, y)) * GetCanvasTM(aFor); } bool @@ -255,7 +258,7 @@ nsSVGImageFrame::TransformContextForPainting(gfxContext* aGfxContext) { gfxMatrix imageTransform; if (mImageContainer->GetType() == imgIContainer::TYPE_VECTOR) { - imageTransform = GetVectorImageTransform(); + imageTransform = GetVectorImageTransform(FOR_PAINTING); } else { PRInt32 nativeWidth, nativeHeight; if (NS_FAILED(mImageContainer->GetWidth(&nativeWidth)) || @@ -263,7 +266,8 @@ nsSVGImageFrame::TransformContextForPainting(gfxContext* aGfxContext) nativeWidth == 0 || nativeHeight == 0) { return false; } - imageTransform = GetRasterImageTransform(nativeWidth, nativeHeight); + imageTransform = + GetRasterImageTransform(nativeWidth, nativeHeight, FOR_PAINTING); } if (imageTransform.IsSingular()) { @@ -315,7 +319,7 @@ nsSVGImageFrame::PaintSVG(nsRenderingContext *aContext, if (GetStyleDisplay()->IsScrollableOverflow()) { gfxRect clipRect = nsSVGUtils::GetClipRectForFrame(this, x, y, width, height); - nsSVGUtils::SetClipRect(ctx, GetCanvasTM(), clipRect); + nsSVGUtils::SetClipRect(ctx, GetCanvasTM(FOR_PAINTING), clipRect); } if (!TransformContextForPainting(ctx)) { @@ -340,7 +344,8 @@ nsSVGImageFrame::PaintSVG(nsRenderingContext *aContext, dirtyRect = aDirtyRect->ToAppUnits(appUnitsPerDevPx); // Adjust dirtyRect to match our local coordinate system. nsRect rootRect = - nsSVGUtils::TransformFrameRectToOuterSVG(mRect, GetCanvasTM(), PresContext()); + nsSVGUtils::TransformFrameRectToOuterSVG(mRect, + GetCanvasTM(FOR_PAINTING), PresContext()); dirtyRect.MoveBy(-rootRect.TopLeft()); } @@ -425,7 +430,8 @@ nsSVGImageFrame::GetFrameForPoint(const nsPoint &aPoint) } if (!nsSVGUtils::HitTestRect( - GetRasterImageTransform(nativeWidth, nativeHeight), + GetRasterImageTransform(nativeWidth, nativeHeight, + FOR_HIT_TESTING), 0, 0, nativeWidth, nativeHeight, PresContext()->AppUnitsToDevPixels(aPoint.x), PresContext()->AppUnitsToDevPixels(aPoint.y))) { @@ -481,7 +487,7 @@ nsSVGImageFrame::UpdateBounds() // See bug 614732 comment 32. mCoveredRegion = nsSVGUtils::TransformFrameRectToOuterSVG( - mRect, GetCanvasTM(), PresContext()); + mRect, GetCanvasTM(FOR_OUTERSVG_TM), PresContext()); if (mState & NS_FRAME_FIRST_REFLOW) { // Make sure we have our filter property (if any) before calling diff --git a/layout/svg/base/src/nsSVGInnerSVGFrame.cpp b/layout/svg/base/src/nsSVGInnerSVGFrame.cpp index a40103e21b37..7756f1c36639 100644 --- a/layout/svg/base/src/nsSVGInnerSVGFrame.cpp +++ b/layout/svg/base/src/nsSVGInnerSVGFrame.cpp @@ -12,6 +12,7 @@ #include "nsISVGChildFrame.h" #include "nsRenderingContext.h" #include "nsSVGContainerFrame.h" +#include "nsSVGIntegrationUtils.h" #include "nsSVGSVGElement.h" nsIFrame* @@ -68,7 +69,7 @@ nsSVGInnerSVGFrame::PaintSVG(nsRenderingContext *aContext, } nsSVGContainerFrame *parent = static_cast(mParent); - gfxMatrix clipTransform = parent->GetCanvasTM(); + gfxMatrix clipTransform = parent->GetCanvasTM(FOR_PAINTING); gfxContext *gfx = aContext->ThebesContext(); autoSR.SetContext(gfx); @@ -217,7 +218,7 @@ nsSVGInnerSVGFrame::GetFrameForPoint(const nsPoint &aPoint) float clipX, clipY, clipWidth, clipHeight; content->GetAnimatedLengthValues(&clipX, &clipY, &clipWidth, &clipHeight, nsnull); - if (!nsSVGUtils::HitTestRect(parent->GetCanvasTM(), + if (!nsSVGUtils::HitTestRect(parent->GetCanvasTM(FOR_HIT_TESTING), clipX, clipY, clipWidth, clipHeight, PresContext()->AppUnitsToDevPixels(aPoint.x), PresContext()->AppUnitsToDevPixels(aPoint.y))) { @@ -246,15 +247,21 @@ nsSVGInnerSVGFrame::NotifyViewportOrTransformChanged(PRUint32 aFlags) // nsSVGContainerFrame methods: gfxMatrix -nsSVGInnerSVGFrame::GetCanvasTM() +nsSVGInnerSVGFrame::GetCanvasTM(PRUint32 aFor) { + if (!(GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD)) { + if ((aFor == FOR_PAINTING && NS_SVGDisplayListPaintingEnabled()) || + (aFor == FOR_HIT_TESTING && NS_SVGDisplayListHitTestingEnabled())) { + return nsSVGIntegrationUtils::GetCSSPxToDevPxMatrix(this); + } + } if (!mCanvasTM) { NS_ASSERTION(mParent, "null parent"); nsSVGContainerFrame *parent = static_cast(mParent); nsSVGSVGElement *content = static_cast(mContent); - gfxMatrix tm = content->PrependLocalTransformsTo(parent->GetCanvasTM()); + gfxMatrix tm = content->PrependLocalTransformsTo(parent->GetCanvasTM(aFor)); mCanvasTM = new gfxMatrix(tm); } diff --git a/layout/svg/base/src/nsSVGInnerSVGFrame.h b/layout/svg/base/src/nsSVGInnerSVGFrame.h index 6b96d09314c8..fa8da7cd0b81 100644 --- a/layout/svg/base/src/nsSVGInnerSVGFrame.h +++ b/layout/svg/base/src/nsSVGInnerSVGFrame.h @@ -56,7 +56,7 @@ public: NS_IMETHOD_(nsIFrame*) GetFrameForPoint(const nsPoint &aPoint); // nsSVGContainerFrame methods: - virtual gfxMatrix GetCanvasTM(); + virtual gfxMatrix GetCanvasTM(PRUint32 aFor); virtual bool HasChildrenOnlyTransform(gfxMatrix *aTransform) const; diff --git a/layout/svg/base/src/nsSVGMarkerFrame.cpp b/layout/svg/base/src/nsSVGMarkerFrame.cpp index dee33b52495e..8575b4a7941a 100644 --- a/layout/svg/base/src/nsSVGMarkerFrame.cpp +++ b/layout/svg/base/src/nsSVGMarkerFrame.cpp @@ -69,7 +69,7 @@ nsSVGMarkerFrame::GetType() const // nsSVGContainerFrame methods: gfxMatrix -nsSVGMarkerFrame::GetCanvasTM() +nsSVGMarkerFrame::GetCanvasTM(PRUint32 aFor) { NS_ASSERTION(mMarkedFrame, "null nsSVGPathGeometry frame"); @@ -81,7 +81,7 @@ nsSVGMarkerFrame::GetCanvasTM() nsSVGMarkerElement *content = static_cast(mContent); mInUse2 = true; - gfxMatrix markedTM = mMarkedFrame->GetCanvasTM(); + gfxMatrix markedTM = mMarkedFrame->GetCanvasTM(aFor); mInUse2 = false; gfxMatrix markerTM = content->GetMarkerTransform(mStrokeWidth, mX, mY, mAutoAngle); @@ -125,7 +125,8 @@ nsSVGMarkerFrame::PaintMark(nsRenderingContext *aContext, gfxRect clipRect = nsSVGUtils::GetClipRectForFrame(this, viewBox.x, viewBox.y, viewBox.width, viewBox.height); - nsSVGUtils::SetClipRect(gfx, GetCanvasTM(), clipRect); + nsSVGUtils::SetClipRect(gfx, GetCanvasTM(nsISVGChildFrame::FOR_PAINTING), + clipRect); } for (nsIFrame* kid = mFrames.FirstChild(); kid; diff --git a/layout/svg/base/src/nsSVGMarkerFrame.h b/layout/svg/base/src/nsSVGMarkerFrame.h index 34dbd230ecaf..593f95e82452 100644 --- a/layout/svg/base/src/nsSVGMarkerFrame.h +++ b/layout/svg/base/src/nsSVGMarkerFrame.h @@ -86,7 +86,7 @@ private: float mStrokeWidth, mX, mY, mAutoAngle; // nsSVGContainerFrame methods: - virtual gfxMatrix GetCanvasTM(); + virtual gfxMatrix GetCanvasTM(PRUint32 aFor); // A helper class to allow us to paint markers safely. The helper // automatically sets and clears the mInUse flag on the marker frame (to diff --git a/layout/svg/base/src/nsSVGMaskFrame.cpp b/layout/svg/base/src/nsSVGMaskFrame.cpp index d9016408264e..f8c6efd3f949 100644 --- a/layout/svg/base/src/nsSVGMaskFrame.cpp +++ b/layout/svg/base/src/nsSVGMaskFrame.cpp @@ -188,7 +188,7 @@ nsSVGMaskFrame::GetType() const } gfxMatrix -nsSVGMaskFrame::GetCanvasTM() +nsSVGMaskFrame::GetCanvasTM(PRUint32 aFor) { NS_ASSERTION(mMaskParentMatrix, "null parent matrix"); diff --git a/layout/svg/base/src/nsSVGMaskFrame.h b/layout/svg/base/src/nsSVGMaskFrame.h index a52d9d4401c3..9150e62d5493 100644 --- a/layout/svg/base/src/nsSVGMaskFrame.h +++ b/layout/svg/base/src/nsSVGMaskFrame.h @@ -89,7 +89,7 @@ private: bool mInUse; // nsSVGContainerFrame methods: - virtual gfxMatrix GetCanvasTM(); + virtual gfxMatrix GetCanvasTM(PRUint32 aFor); }; #endif diff --git a/layout/svg/base/src/nsSVGOuterSVGFrame.cpp b/layout/svg/base/src/nsSVGOuterSVGFrame.cpp index f88d0d39429f..73c76211c286 100644 --- a/layout/svg/base/src/nsSVGOuterSVGFrame.cpp +++ b/layout/svg/base/src/nsSVGOuterSVGFrame.cpp @@ -18,6 +18,7 @@ #include "nsRenderingContext.h" #include "nsStubMutationObserver.h" #include "nsSVGForeignObjectFrame.h" +#include "nsSVGIntegrationUtils.h" #include "nsSVGSVGElement.h" #include "nsSVGTextFrame.h" #include "nsSubDocumentFrame.h" @@ -790,8 +791,14 @@ nsSVGOuterSVGFrame::NotifyViewportOrTransformChanged(PRUint32 aFlags) // nsSVGContainerFrame methods: gfxMatrix -nsSVGOuterSVGFrame::GetCanvasTM() +nsSVGOuterSVGFrame::GetCanvasTM(PRUint32 aFor) { + if (!(GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD)) { + if ((aFor == FOR_PAINTING && NS_SVGDisplayListPaintingEnabled()) || + (aFor == FOR_HIT_TESTING && NS_SVGDisplayListHitTestingEnabled())) { + return nsSVGIntegrationUtils::GetCSSPxToDevPxMatrix(this); + } + } if (!mCanvasTM) { nsSVGSVGElement *content = static_cast(mContent); diff --git a/layout/svg/base/src/nsSVGOuterSVGFrame.h b/layout/svg/base/src/nsSVGOuterSVGFrame.h index 3b70bbdb014c..d53c89b693ae 100644 --- a/layout/svg/base/src/nsSVGOuterSVGFrame.h +++ b/layout/svg/base/src/nsSVGOuterSVGFrame.h @@ -100,7 +100,7 @@ public: virtual void NotifyViewportOrTransformChanged(PRUint32 aFlags); // nsSVGContainerFrame methods: - virtual gfxMatrix GetCanvasTM(); + virtual gfxMatrix GetCanvasTM(PRUint32 aFor); /* Methods to allow descendant nsSVGForeignObjectFrame frames to register and * unregister themselves with their nearest nsSVGOuterSVGFrame ancestor. This diff --git a/layout/svg/base/src/nsSVGPathGeometryFrame.cpp b/layout/svg/base/src/nsSVGPathGeometryFrame.cpp index e7c1089e42cc..a95095456a8e 100644 --- a/layout/svg/base/src/nsSVGPathGeometryFrame.cpp +++ b/layout/svg/base/src/nsSVGPathGeometryFrame.cpp @@ -13,6 +13,7 @@ #include "nsRenderingContext.h" #include "nsSVGEffects.h" #include "nsSVGGraphicElement.h" +#include "nsSVGIntegrationUtils.h" #include "nsSVGMarkerFrame.h" #include "nsSVGPathGeometryElement.h" #include "nsSVGUtils.h" @@ -151,6 +152,7 @@ nsSVGPathGeometryFrame::PaintSVG(nsRenderingContext *aContext, NS_IMETHODIMP_(nsIFrame*) nsSVGPathGeometryFrame::GetFrameForPoint(const nsPoint &aPoint) { + gfxMatrix canvasTM = GetCanvasTM(FOR_HIT_TESTING); PRUint16 fillRule, hitTestFlags; if (GetStateBits() & NS_STATE_SVG_CLIPPATH_CHILD) { hitTestFlags = SVG_HIT_TEST_FILL; @@ -159,7 +161,6 @@ nsSVGPathGeometryFrame::GetFrameForPoint(const nsPoint &aPoint) hitTestFlags = GetHitTestFlags(); // XXX once bug 614732 is fixed, aPoint won't need any conversion in order // to compare it with mRect. - gfxMatrix canvasTM = GetCanvasTM(); if (canvasTM.IsSingular()) { return nsnull; } @@ -176,7 +177,7 @@ nsSVGPathGeometryFrame::GetFrameForPoint(const nsPoint &aPoint) nsRefPtr tmpCtx = new gfxContext(gfxPlatform::GetPlatform()->ScreenReferenceSurface()); - GeneratePath(tmpCtx, GetCanvasTM()); + GeneratePath(tmpCtx, canvasTM); gfxPoint userSpacePoint = tmpCtx->DeviceToUser(gfxPoint(PresContext()->AppUnitsToGfxUnits(aPoint.x), PresContext()->AppUnitsToGfxUnits(aPoint.y))); @@ -229,7 +230,7 @@ nsSVGPathGeometryFrame::UpdateBounds() // See bug 614732 comment 32. mCoveredRegion = nsSVGUtils::TransformFrameRectToOuterSVG( - mRect, GetCanvasTM(), PresContext()); + mRect, GetCanvasTM(FOR_OUTERSVG_TM), PresContext()); if (mState & NS_FRAME_FIRST_REFLOW) { // Make sure we have our filter property (if any) before calling @@ -382,14 +383,21 @@ nsSVGPathGeometryFrame::GetBBoxContribution(const gfxMatrix &aToBBoxUserspace, // nsSVGGeometryFrame methods: gfxMatrix -nsSVGPathGeometryFrame::GetCanvasTM() +nsSVGPathGeometryFrame::GetCanvasTM(PRUint32 aFor) { + if (!(GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD)) { + if ((aFor == FOR_PAINTING && NS_SVGDisplayListPaintingEnabled()) || + (aFor == FOR_HIT_TESTING && NS_SVGDisplayListHitTestingEnabled())) { + return nsSVGIntegrationUtils::GetCSSPxToDevPxMatrix(this); + } + } + NS_ASSERTION(mParent, "null parent"); nsSVGContainerFrame *parent = static_cast(mParent); nsSVGGraphicElement *content = static_cast(mContent); - return content->PrependLocalTransformsTo(parent->GetCanvasTM()); + return content->PrependLocalTransformsTo(parent->GetCanvasTM(aFor)); } //---------------------------------------------------------------------- @@ -461,7 +469,7 @@ nsSVGPathGeometryFrame::Render(nsRenderingContext *aContext) /* save/restore the state so we don't screw up the xform */ gfx->Save(); - GeneratePath(gfx, GetCanvasTM()); + GeneratePath(gfx, GetCanvasTM(FOR_PAINTING)); if (renderMode != SVGAutoRenderState::NORMAL) { NS_ABORT_IF_FALSE(renderMode == SVGAutoRenderState::CLIP || diff --git a/layout/svg/base/src/nsSVGPathGeometryFrame.h b/layout/svg/base/src/nsSVGPathGeometryFrame.h index 6ada66bfd5d1..ed8dcdb6e584 100644 --- a/layout/svg/base/src/nsSVGPathGeometryFrame.h +++ b/layout/svg/base/src/nsSVGPathGeometryFrame.h @@ -70,7 +70,7 @@ public: #endif // nsSVGGeometryFrame methods - gfxMatrix GetCanvasTM(); + gfxMatrix GetCanvasTM(PRUint32 aFor); protected: // nsISVGChildFrame interface: diff --git a/layout/svg/base/src/nsSVGPatternFrame.cpp b/layout/svg/base/src/nsSVGPatternFrame.cpp index 27aba9a12043..4cae392b42c2 100644 --- a/layout/svg/base/src/nsSVGPatternFrame.cpp +++ b/layout/svg/base/src/nsSVGPatternFrame.cpp @@ -125,7 +125,7 @@ nsSVGPatternFrame::GetType() const // matrix, which depends on our units parameters // and X, Y, Width, and Height gfxMatrix -nsSVGPatternFrame::GetCanvasTM() +nsSVGPatternFrame::GetCanvasTM(PRUint32 aFor) { if (mCTM) { return *mCTM; @@ -134,7 +134,7 @@ nsSVGPatternFrame::GetCanvasTM() // Do we know our rendering parent? if (mSource) { // Yes, use it! - return mSource->GetCanvasTM(); + return mSource->GetCanvasTM(aFor); } // We get here when geometry in the container is updated @@ -637,7 +637,7 @@ nsSVGPatternFrame::GetTargetGeometry(gfxMatrix *aCTM, } // Get the transformation matrix from our calling geometry - *aCTM = nsSVGUtils::GetCanvasTM(aTarget); + *aCTM = nsSVGUtils::GetCanvasTM(aTarget, nsISVGChildFrame::FOR_PAINTING); // OK, now fix up the bounding box to reflect user coordinates // We handle device unit scaling in pattern matrix diff --git a/layout/svg/base/src/nsSVGPatternFrame.h b/layout/svg/base/src/nsSVGPatternFrame.h index fe0b740b2a63..8e6462955c73 100644 --- a/layout/svg/base/src/nsSVGPatternFrame.h +++ b/layout/svg/base/src/nsSVGPatternFrame.h @@ -48,7 +48,7 @@ public: typedef mozilla::SVGAnimatedPreserveAspectRatio SVGAnimatedPreserveAspectRatio; // nsSVGContainerFrame methods: - virtual gfxMatrix GetCanvasTM(); + virtual gfxMatrix GetCanvasTM(PRUint32 aFor); // nsIFrame interface: virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext); diff --git a/layout/svg/base/src/nsSVGTSpanFrame.cpp b/layout/svg/base/src/nsSVGTSpanFrame.cpp index 4a8ca46842ea..2c6213194346 100644 --- a/layout/svg/base/src/nsSVGTSpanFrame.cpp +++ b/layout/svg/base/src/nsSVGTSpanFrame.cpp @@ -9,6 +9,7 @@ // Keep others in (case-insensitive) order: #include "nsIDOMSVGTSpanElement.h" #include "nsIDOMSVGAltGlyphElement.h" +#include "nsSVGIntegrationUtils.h" #include "nsSVGUtils.h" //---------------------------------------------------------------------- @@ -90,10 +91,16 @@ nsSVGTSpanFrame::AttributeChanged(PRInt32 aNameSpaceID, // nsSVGContainerFrame methods: gfxMatrix -nsSVGTSpanFrame::GetCanvasTM() +nsSVGTSpanFrame::GetCanvasTM(PRUint32 aFor) { + if (!(GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD)) { + if ((aFor == FOR_PAINTING && NS_SVGDisplayListPaintingEnabled()) || + (aFor == FOR_HIT_TESTING && NS_SVGDisplayListHitTestingEnabled())) { + return nsSVGIntegrationUtils::GetCSSPxToDevPxMatrix(this); + } + } NS_ASSERTION(mParent, "null parent"); - return static_cast(mParent)->GetCanvasTM(); + return static_cast(mParent)->GetCanvasTM(aFor); } //---------------------------------------------------------------------- diff --git a/layout/svg/base/src/nsSVGTSpanFrame.h b/layout/svg/base/src/nsSVGTSpanFrame.h index 9bf2cbc4c665..3ee866a2635a 100644 --- a/layout/svg/base/src/nsSVGTSpanFrame.h +++ b/layout/svg/base/src/nsSVGTSpanFrame.h @@ -61,7 +61,7 @@ public: } #endif // nsSVGContainerFrame methods: - virtual gfxMatrix GetCanvasTM(); + virtual gfxMatrix GetCanvasTM(PRUint32 aFor); // nsISVGGlyphFragmentNode interface: virtual PRUint32 GetNumberOfChars(); diff --git a/layout/svg/base/src/nsSVGTextFrame.cpp b/layout/svg/base/src/nsSVGTextFrame.cpp index d596879272ce..832cee2a2be7 100644 --- a/layout/svg/base/src/nsSVGTextFrame.cpp +++ b/layout/svg/base/src/nsSVGTextFrame.cpp @@ -13,6 +13,7 @@ #include "nsISVGGlyphFragmentNode.h" #include "nsSVGGlyphFrame.h" #include "nsSVGGraphicElement.h" +#include "nsSVGIntegrationUtils.h" #include "nsSVGPathElement.h" #include "nsSVGTextPathFrame.h" #include "nsSVGUtils.h" @@ -256,15 +257,23 @@ nsSVGTextFrame::GetBBoxContribution(const gfxMatrix &aToBBoxUserspace, // nsSVGContainerFrame methods: gfxMatrix -nsSVGTextFrame::GetCanvasTM() +nsSVGTextFrame::GetCanvasTM(PRUint32 aFor) { + if (!(GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD)) { + if ((aFor == FOR_PAINTING && NS_SVGDisplayListPaintingEnabled()) || + (aFor == FOR_HIT_TESTING && NS_SVGDisplayListHitTestingEnabled())) { + return nsSVGIntegrationUtils::GetCSSPxToDevPxMatrix(this); + } + } + if (!mCanvasTM) { NS_ASSERTION(mParent, "null parent"); nsSVGContainerFrame *parent = static_cast(mParent); nsSVGGraphicElement *content = static_cast(mContent); - gfxMatrix tm = content->PrependLocalTransformsTo(parent->GetCanvasTM()); + gfxMatrix tm = + content->PrependLocalTransformsTo(parent->GetCanvasTM(aFor)); mCanvasTM = new gfxMatrix(tm); } diff --git a/layout/svg/base/src/nsSVGTextFrame.h b/layout/svg/base/src/nsSVGTextFrame.h index 13a627e47a9a..60b910df616f 100644 --- a/layout/svg/base/src/nsSVGTextFrame.h +++ b/layout/svg/base/src/nsSVGTextFrame.h @@ -63,7 +63,7 @@ public: PRUint32 aFlags); // nsSVGContainerFrame methods: - virtual gfxMatrix GetCanvasTM(); + virtual gfxMatrix GetCanvasTM(PRUint32 aFor); // nsSVGTextContainerFrame methods: virtual PRUint32 GetNumberOfChars(); diff --git a/layout/svg/base/src/nsSVGUtils.cpp b/layout/svg/base/src/nsSVGUtils.cpp index b30afb4c51bd..eb962d300514 100644 --- a/layout/svg/base/src/nsSVGUtils.cpp +++ b/layout/svg/base/src/nsSVGUtils.cpp @@ -1013,7 +1013,7 @@ nsSVGUtils::GetViewBoxTransform(const nsSVGElement* aElement, } gfxMatrix -nsSVGUtils::GetCanvasTM(nsIFrame *aFrame) +nsSVGUtils::GetCanvasTM(nsIFrame *aFrame, PRUint32 aFor) { // XXX yuck, we really need a common interface for GetCanvasTM @@ -1021,30 +1021,43 @@ nsSVGUtils::GetCanvasTM(nsIFrame *aFrame) return nsSVGIntegrationUtils::GetCSSPxToDevPxMatrix(aFrame); } + if (!(aFrame->GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD)) { + if ((aFor == nsISVGChildFrame::FOR_PAINTING && + NS_SVGDisplayListPaintingEnabled()) || + (aFor == nsISVGChildFrame::FOR_HIT_TESTING && + NS_SVGDisplayListHitTestingEnabled())) { + return nsSVGIntegrationUtils::GetCSSPxToDevPxMatrix(aFrame); + } + } + nsIAtom* type = aFrame->GetType(); if (type == nsGkAtoms::svgForeignObjectFrame) { - return static_cast(aFrame)->GetCanvasTM(); + return static_cast(aFrame)->GetCanvasTM(aFor); } nsSVGContainerFrame *containerFrame = do_QueryFrame(aFrame); if (containerFrame) { - return containerFrame->GetCanvasTM(); + return containerFrame->GetCanvasTM(aFor); } - return static_cast(aFrame)->GetCanvasTM(); + return static_cast(aFrame)->GetCanvasTM(aFor); } gfxMatrix -nsSVGUtils::GetUserToCanvasTM(nsIFrame *aFrame) +nsSVGUtils::GetUserToCanvasTM(nsIFrame *aFrame, PRUint32 aFor) { + NS_ASSERTION(aFor == nsISVGChildFrame::FOR_OUTERSVG_TM, + "Unexpected aFor?"); + nsISVGChildFrame* svgFrame = do_QueryFrame(aFrame); NS_ASSERTION(svgFrame, "bad frame"); gfxMatrix tm; if (svgFrame) { nsSVGElement *content = static_cast(aFrame->GetContent()); - tm = content->PrependLocalTransformsTo(GetCanvasTM(aFrame->GetParent()), - nsSVGElement::eUserSpaceToParent); + tm = content->PrependLocalTransformsTo( + GetCanvasTM(aFrame->GetParent(), aFor), + nsSVGElement::eUserSpaceToParent); } return tm; } @@ -1085,7 +1098,8 @@ public: // aDirtyRect is in user-space pixels, we need to convert to // outer-SVG-frame-relative device pixels. if (aDirtyRect) { - gfxMatrix userToDeviceSpace = nsSVGUtils::GetCanvasTM(aTarget); + gfxMatrix userToDeviceSpace = + nsSVGUtils::GetCanvasTM(aTarget, nsISVGChildFrame::FOR_PAINTING); if (userToDeviceSpace.IsSingular()) { return; } @@ -1142,7 +1156,7 @@ nsSVGUtils::PaintFrameWithEffects(nsRenderingContext *aContext, overflowRect = overflowRect + aFrame->GetPosition(); } PRUint32 appUnitsPerDevPx = aFrame->PresContext()->AppUnitsPerDevPixel(); - gfxMatrix tm = GetCanvasTM(aFrame); + gfxMatrix tm = GetCanvasTM(aFrame, nsISVGChildFrame::FOR_PAINTING); if (aFrame->IsFrameOfType(nsIFrame::eSVG | nsIFrame::eSVGContainer)) { gfxMatrix childrenOnlyTM; if (static_cast(aFrame)-> @@ -1193,7 +1207,7 @@ nsSVGUtils::PaintFrameWithEffects(nsRenderingContext *aContext, gfxMatrix matrix; if (clipPathFrame || maskFrame) - matrix = GetCanvasTM(aFrame); + matrix = GetCanvasTM(aFrame, nsISVGChildFrame::FOR_PAINTING); /* Check if we need to do additional operations on this child's * rendering, which necessitates rendering into another surface. */ @@ -1204,7 +1218,7 @@ nsSVGUtils::PaintFrameWithEffects(nsRenderingContext *aContext, // aFrame has a valid visual overflow rect, so clip to it before calling // PushGroup() to minimize the size of the surfaces we'll composite: gfxContextMatrixAutoSaveRestore matrixAutoSaveRestore(gfx); - gfx->Multiply(GetCanvasTM(aFrame)); + gfx->Multiply(GetCanvasTM(aFrame, nsISVGChildFrame::FOR_PAINTING)); nsRect overflowRect = aFrame->GetVisualOverflowRectRelativeToSelf(); if (aFrame->IsFrameOfType(nsIFrame::eSVGGeometry)) { // Unlike containers, leaf frames do not include GetPosition() in @@ -1231,7 +1245,8 @@ nsSVGUtils::PaintFrameWithEffects(nsRenderingContext *aContext, if (aDirtyRect) { // aDirtyRect is in outer- device pixels, but the filter code needs // it in frame space. - gfxMatrix userToDeviceSpace = GetUserToCanvasTM(aFrame); + gfxMatrix userToDeviceSpace = + GetUserToCanvasTM(aFrame, nsISVGChildFrame::FOR_OUTERSVG_TM); if (userToDeviceSpace.IsSingular()) { return; } @@ -1310,7 +1325,8 @@ nsSVGUtils::HitTestClip(nsIFrame *aFrame, const nsPoint &aPoint) return false; } - return clipPathFrame->ClipHitTest(aFrame, GetCanvasTM(aFrame), aPoint); + return clipPathFrame->ClipHitTest(aFrame, GetCanvasTM(aFrame, + nsISVGChildFrame::FOR_HIT_TESTING), aPoint); } nsIFrame * diff --git a/layout/svg/base/src/nsSVGUtils.h b/layout/svg/base/src/nsSVGUtils.h index afc986b41b5d..73d94f95c376 100644 --- a/layout/svg/base/src/nsSVGUtils.h +++ b/layout/svg/base/src/nsSVGUtils.h @@ -470,7 +470,7 @@ public: * child SVG frame, container SVG frame, or a regular frame. * For regular frames, we just return an identity matrix. */ - static gfxMatrix GetCanvasTM(nsIFrame* aFrame); + static gfxMatrix GetCanvasTM(nsIFrame* aFrame, PRUint32 aFor); /** * Returns the transform from aFrame's user space to canvas space. Only call @@ -481,7 +481,7 @@ public: * space. Specifically, it does not include any other transforms introduced * by the frame such as x/y offsets and viewBox attributes. */ - static gfxMatrix GetUserToCanvasTM(nsIFrame* aFrame); + static gfxMatrix GetUserToCanvasTM(nsIFrame* aFrame, PRUint32 aFor); /** * Notify the descendants of aFrame of a change to one of their ancestors