bug 875329 - don't ignore transforms when rendering SVG-in-OT glyphs. r=heycam

This commit is contained in:
Jonathan Kew 2013-09-11 08:27:45 +01:00
parent 9d1d4e73b0
commit b877a162e9
43 changed files with 245 additions and 143 deletions

View File

@ -44,10 +44,20 @@ public:
NS_DECL_QUERYFRAME_TARGET(nsISVGChildFrame)
// Paint this frame - aDirtyRect is the area being redrawn, in frame
// offset pixel coordinates
// Paint this frame.
// aDirtyRect is the area being redrawn, in frame offset pixel coordinates.
// aTransformRoot (if non-null) is the frame at which we stop looking up
// transforms, when painting content that is part of an SVG glyph. (See
// bug 875329.)
// For normal SVG graphics using display-list rendering, any transforms on
// the element or its parents will have already been set up in the context
// before PaintSVG is called. When painting SVG glyphs, this is not the case,
// so the element's full transform needs to be applied; but we don't want to
// apply transforms from outside the actual glyph element, so we need to know
// how far up the ancestor chain to go.
NS_IMETHOD PaintSVG(nsRenderingContext* aContext,
const nsIntRect *aDirtyRect)=0;
const nsIntRect *aDirtyRect,
nsIFrame* aTransformRoot = nullptr) = 0;
// Check if this frame or children contain the given point,
// specified in app units relative to the origin of the outer

View File

@ -59,7 +59,8 @@ public:
virtual void NotifySVGChanged(uint32_t aFlags);
// nsSVGContainerFrame methods:
virtual gfxMatrix GetCanvasTM(uint32_t aFor);
virtual gfxMatrix GetCanvasTM(uint32_t aFor,
nsIFrame* aTransformRoot = nullptr) MOZ_OVERRIDE;
// nsSVGTextContainerFrame methods:
virtual void GetXY(mozilla::SVGUserUnitList *aX, mozilla::SVGUserUnitList *aY);
@ -143,9 +144,9 @@ nsSVGAFrame::NotifySVGChanged(uint32_t aFlags)
// nsSVGContainerFrame methods:
gfxMatrix
nsSVGAFrame::GetCanvasTM(uint32_t aFor)
nsSVGAFrame::GetCanvasTM(uint32_t aFor, nsIFrame* aTransformRoot)
{
if (!(GetStateBits() & NS_FRAME_IS_NONDISPLAY)) {
if (!(GetStateBits() & NS_FRAME_IS_NONDISPLAY) && !aTransformRoot) {
if ((aFor == FOR_PAINTING && NS_SVGDisplayListPaintingEnabled()) ||
(aFor == FOR_HIT_TESTING && NS_SVGDisplayListHitTestingEnabled())) {
return nsSVGIntegrationUtils::GetCSSPxToDevPxMatrix(this);
@ -157,7 +158,9 @@ nsSVGAFrame::GetCanvasTM(uint32_t aFor)
nsSVGContainerFrame *parent = static_cast<nsSVGContainerFrame*>(mParent);
dom::SVGAElement *content = static_cast<dom::SVGAElement*>(mContent);
gfxMatrix tm = content->PrependLocalTransformsTo(parent->GetCanvasTM(aFor));
gfxMatrix tm = content->PrependLocalTransformsTo(
this == aTransformRoot ? gfxMatrix() :
parent->GetCanvasTM(aFor, aTransformRoot));
mCanvasTM = new gfxMatrix(tm);
}

View File

@ -315,7 +315,7 @@ nsSVGClipPathFrame::GetType() const
}
gfxMatrix
nsSVGClipPathFrame::GetCanvasTM(uint32_t aFor)
nsSVGClipPathFrame::GetCanvasTM(uint32_t aFor, nsIFrame* aTransformRoot)
{
SVGClipPathElement *content = static_cast<SVGClipPathElement*>(mContent);

View File

@ -101,7 +101,8 @@ public:
bool mInUse;
// nsSVGContainerFrame methods:
virtual gfxMatrix GetCanvasTM(uint32_t aFor) MOZ_OVERRIDE;
virtual gfxMatrix GetCanvasTM(uint32_t aFor,
nsIFrame* aTransformRoot = nullptr) MOZ_OVERRIDE;
};
#endif

View File

@ -254,7 +254,8 @@ nsSVGDisplayContainerFrame::IsSVGTransformed(gfxMatrix *aOwnTransform,
NS_IMETHODIMP
nsSVGDisplayContainerFrame::PaintSVG(nsRenderingContext* aContext,
const nsIntRect *aDirtyRect)
const nsIntRect *aDirtyRect,
nsIFrame* aTransformRoot)
{
NS_ASSERTION(!NS_SVGDisplayListPaintingEnabled() ||
(mState & NS_FRAME_IS_NONDISPLAY) ||
@ -268,7 +269,7 @@ nsSVGDisplayContainerFrame::PaintSVG(nsRenderingContext* aContext,
for (nsIFrame* kid = mFrames.FirstChild(); kid;
kid = kid->GetNextSibling()) {
nsSVGUtils::PaintFrameWithEffects(aContext, aDirtyRect, kid);
nsSVGUtils::PaintFrameWithEffects(aContext, aDirtyRect, kid, aTransformRoot);
}
return NS_OK;

View File

@ -57,7 +57,8 @@ public:
NS_DECL_FRAMEARENA_HELPERS
// Returns the transform to our gfxContext (to device pixels, not CSS px)
virtual gfxMatrix GetCanvasTM(uint32_t aFor) {
virtual gfxMatrix GetCanvasTM(uint32_t aFor,
nsIFrame* aTransformRoot = nullptr) {
return gfxMatrix();
}
@ -146,7 +147,8 @@ public:
// nsISVGChildFrame interface:
NS_IMETHOD PaintSVG(nsRenderingContext* aContext,
const nsIntRect *aDirtyRect) MOZ_OVERRIDE;
const nsIntRect *aDirtyRect,
nsIFrame* aTransformRoot = nullptr) MOZ_OVERRIDE;
NS_IMETHOD_(nsIFrame*) GetFrameForPoint(const nsPoint &aPoint) MOZ_OVERRIDE;
NS_IMETHOD_(nsRect) GetCoveredRegion() MOZ_OVERRIDE;
virtual void ReflowSVG() MOZ_OVERRIDE;

View File

@ -124,7 +124,8 @@ public:
const nsRect *aPostFilterDirtyRect,
const nsRect *aPreFilterDirtyRect,
const nsRect *aOverridePreFilterVisualOverflowRect,
const gfxRect *aOverrideBBox = nullptr);
const gfxRect *aOverrideBBox = nullptr,
nsIFrame* aTransformRoot = nullptr);
~nsAutoFilterInstance() {}
// If this returns null, then draw nothing. Either the filter draws
@ -141,7 +142,8 @@ nsAutoFilterInstance::nsAutoFilterInstance(nsIFrame *aTarget,
const nsRect *aPostFilterDirtyRect,
const nsRect *aPreFilterDirtyRect,
const nsRect *aPreFilterVisualOverflowRectOverride,
const gfxRect *aOverrideBBox)
const gfxRect *aOverrideBBox,
nsIFrame* aTransformRoot)
{
const SVGFilterElement *filter = aFilterFrame->GetFilterContent();
@ -279,7 +281,8 @@ nsAutoFilterInstance::nsAutoFilterInstance(nsIFrame *aTarget,
nsIntSize(filterRes.width, filterRes.height),
filterToDeviceSpace, filterToFrameSpaceInCSSPx,
preFilterVisualOverflowRect, postFilterDirtyRect,
preFilterDirtyRect, primitiveUnits);
preFilterDirtyRect, primitiveUnits,
aTransformRoot);
}
uint16_t
@ -439,10 +442,12 @@ nsresult
nsSVGFilterFrame::PaintFilteredFrame(nsRenderingContext *aContext,
nsIFrame *aFilteredFrame,
nsSVGFilterPaintCallback *aPaintCallback,
const nsRect *aDirtyArea)
const nsRect *aDirtyArea,
nsIFrame* aTransformRoot)
{
nsAutoFilterInstance instance(aFilteredFrame, this, aPaintCallback,
aDirtyArea, nullptr, nullptr);
aDirtyArea, nullptr, nullptr, nullptr,
aTransformRoot);
if (!instance.get()) {
return NS_OK;
}

View File

@ -66,7 +66,8 @@ public:
nsresult PaintFilteredFrame(nsRenderingContext *aContext,
nsIFrame *aFilteredFrame,
nsSVGFilterPaintCallback *aPaintCallback,
const nsRect* aDirtyArea);
const nsRect* aDirtyArea,
nsIFrame* aTransformRoot);
/**
* Returns the post-filter area that could be dirtied when the given

View File

@ -349,7 +349,8 @@ nsSVGFilterInstance::BuildSourcePaint(PrimitiveInfo *aPrimitive)
gfx->Save();
gfxMatrix matrix =
nsSVGUtils::GetCanvasTM(mTargetFrame, nsISVGChildFrame::FOR_PAINTING);
nsSVGUtils::GetCanvasTM(mTargetFrame, nsISVGChildFrame::FOR_PAINTING,
mTransformRoot);
if (!matrix.IsSingular()) {
gfx->Multiply(matrix);
gfx->Rectangle(r);
@ -439,7 +440,7 @@ nsSVGFilterInstance::BuildSourceImages()
// subtle bugs, and in practice it probably makes no real difference.)
gfxMatrix deviceToFilterSpace = GetFilterSpaceToDeviceSpaceTransform().Invert();
tmpCtx.ThebesContext()->Multiply(deviceToFilterSpace);
mPaintCallback->Paint(&tmpCtx, mTargetFrame, &dirty);
mPaintCallback->Paint(&tmpCtx, mTargetFrame, &dirty, mTransformRoot);
gfxContext copyContext(sourceColorAlpha);
copyContext.SetSource(offscreen);

View File

@ -87,7 +87,8 @@ public:
const nsIntRect& aTargetBounds,
const nsIntRect& aPostFilterDirtyRect,
const nsIntRect& aPreFilterDirtyRect,
uint16_t aPrimitiveUnits) :
uint16_t aPrimitiveUnits,
nsIFrame* aTransformRoot) :
mTargetFrame(aTargetFrame),
mPaintCallback(aPaintCallback),
mFilterElement(aFilterElement),
@ -100,7 +101,8 @@ public:
mTargetBounds(aTargetBounds),
mPostFilterDirtyRect(aPostFilterDirtyRect),
mPreFilterDirtyRect(aPreFilterDirtyRect),
mPrimitiveUnits(aPrimitiveUnits) {
mPrimitiveUnits(aPrimitiveUnits),
mTransformRoot(aTransformRoot) {
}
/**
@ -435,6 +437,7 @@ private:
PrimitiveInfo mFillPaint;
PrimitiveInfo mStrokePaint;
nsTArray<PrimitiveInfo> mPrimitives;
nsIFrame* mTransformRoot;
};
#endif

View File

@ -22,9 +22,12 @@ public:
* The context will be configured to use the "user space" coordinate
* system.
* @param aDirtyRect the dirty rect *in user space pixels*
* @param aTransformRoot the outermost frame whose transform should be taken
* into account when painting an SVG glyph
*/
virtual void Paint(nsRenderingContext *aContext, nsIFrame *aTarget,
const nsIntRect *aDirtyRect) = 0;
const nsIntRect *aDirtyRect,
nsIFrame* aTransformRoot) = 0;
};
#endif

View File

@ -194,7 +194,8 @@ nsSVGForeignObjectFrame::IsSVGTransformed(gfxMatrix *aOwnTransform,
NS_IMETHODIMP
nsSVGForeignObjectFrame::PaintSVG(nsRenderingContext *aContext,
const nsIntRect *aDirtyRect)
const nsIntRect *aDirtyRect,
nsIFrame* aTransformRoot)
{
NS_ASSERTION(!NS_SVGDisplayListPaintingEnabled() ||
(mState & NS_FRAME_IS_NONDISPLAY),
@ -208,7 +209,7 @@ nsSVGForeignObjectFrame::PaintSVG(nsRenderingContext *aContext,
if (!kid)
return NS_OK;
gfxMatrix canvasTM = GetCanvasTM(FOR_PAINTING);
gfxMatrix canvasTM = GetCanvasTM(FOR_PAINTING, aTransformRoot);
if (canvasTM.IsSingular()) {
NS_WARNING("Can't render foreignObject element!");
@ -486,9 +487,9 @@ nsSVGForeignObjectFrame::GetBBoxContribution(const gfxMatrix &aToBBoxUserspace,
//----------------------------------------------------------------------
gfxMatrix
nsSVGForeignObjectFrame::GetCanvasTM(uint32_t aFor)
nsSVGForeignObjectFrame::GetCanvasTM(uint32_t aFor, nsIFrame* aTransformRoot)
{
if (!(GetStateBits() & NS_FRAME_IS_NONDISPLAY)) {
if (!(GetStateBits() & NS_FRAME_IS_NONDISPLAY) && !aTransformRoot) {
if ((aFor == FOR_PAINTING && NS_SVGDisplayListPaintingEnabled()) ||
(aFor == FOR_HIT_TESTING && NS_SVGDisplayListHitTestingEnabled())) {
return nsSVGIntegrationUtils::GetCSSPxToDevPxMatrix(this);
@ -501,7 +502,9 @@ nsSVGForeignObjectFrame::GetCanvasTM(uint32_t aFor)
SVGForeignObjectElement *content =
static_cast<SVGForeignObjectElement*>(mContent);
gfxMatrix tm = content->PrependLocalTransformsTo(parent->GetCanvasTM(aFor));
gfxMatrix tm = content->PrependLocalTransformsTo(
this == aTransformRoot ? gfxMatrix() :
parent->GetCanvasTM(aFor, aTransformRoot));
mCanvasTM = new gfxMatrix(tm);
}

View File

@ -77,7 +77,8 @@ public:
// nsISVGChildFrame interface:
NS_IMETHOD PaintSVG(nsRenderingContext *aContext,
const nsIntRect *aDirtyRect) MOZ_OVERRIDE;
const nsIntRect *aDirtyRect,
nsIFrame* aTransformRoot = nullptr) MOZ_OVERRIDE;
NS_IMETHOD_(nsIFrame*) GetFrameForPoint(const nsPoint &aPoint) MOZ_OVERRIDE;
NS_IMETHOD_(nsRect) GetCoveredRegion() MOZ_OVERRIDE;
virtual void ReflowSVG() MOZ_OVERRIDE;
@ -86,7 +87,7 @@ public:
uint32_t aFlags) MOZ_OVERRIDE;
NS_IMETHOD_(bool) IsDisplayContainer() MOZ_OVERRIDE { return true; }
gfxMatrix GetCanvasTM(uint32_t aFor);
gfxMatrix GetCanvasTM(uint32_t aFor, nsIFrame* aTransformRoot = nullptr);
nsRect GetInvalidRegion();

View File

@ -65,9 +65,9 @@ nsSVGGFrame::NotifySVGChanged(uint32_t aFlags)
}
gfxMatrix
nsSVGGFrame::GetCanvasTM(uint32_t aFor)
nsSVGGFrame::GetCanvasTM(uint32_t aFor, nsIFrame* aTransformRoot)
{
if (!(GetStateBits() & NS_FRAME_IS_NONDISPLAY)) {
if (!(GetStateBits() & NS_FRAME_IS_NONDISPLAY) && !aTransformRoot) {
if ((aFor == FOR_PAINTING && NS_SVGDisplayListPaintingEnabled()) ||
(aFor == FOR_HIT_TESTING && NS_SVGDisplayListHitTestingEnabled())) {
return nsSVGIntegrationUtils::GetCSSPxToDevPxMatrix(this);
@ -78,8 +78,9 @@ nsSVGGFrame::GetCanvasTM(uint32_t aFor)
nsSVGContainerFrame *parent = static_cast<nsSVGContainerFrame*>(mParent);
SVGGraphicsElement *content = static_cast<SVGGraphicsElement*>(mContent);
gfxMatrix tm = content->PrependLocalTransformsTo(parent->GetCanvasTM(aFor));
gfxMatrix tm = content->PrependLocalTransformsTo(
this == aTransformRoot ? gfxMatrix() :
parent->GetCanvasTM(aFor, aTransformRoot));
mCanvasTM = new gfxMatrix(tm);
}

View File

@ -52,7 +52,8 @@ public:
virtual void NotifySVGChanged(uint32_t aFlags) MOZ_OVERRIDE;
// nsSVGContainerFrame methods:
virtual gfxMatrix GetCanvasTM(uint32_t aFor) MOZ_OVERRIDE;
virtual gfxMatrix GetCanvasTM(uint32_t aFor,
nsIFrame* aTransformRoot = nullptr) MOZ_OVERRIDE;
nsAutoPtr<gfxMatrix> mCanvasTM;
};

View File

@ -46,9 +46,10 @@ nsSVGGenericContainerFrame::GetType() const
// nsSVGContainerFrame methods:
gfxMatrix
nsSVGGenericContainerFrame::GetCanvasTM(uint32_t aFor)
nsSVGGenericContainerFrame::GetCanvasTM(uint32_t aFor,
nsIFrame* aTransformRoot)
{
if (!(GetStateBits() & NS_FRAME_IS_NONDISPLAY)) {
if (!(GetStateBits() & NS_FRAME_IS_NONDISPLAY) && !aTransformRoot) {
if ((aFor == FOR_PAINTING && NS_SVGDisplayListPaintingEnabled()) ||
(aFor == FOR_HIT_TESTING && NS_SVGDisplayListHitTestingEnabled())) {
return nsSVGIntegrationUtils::GetCSSPxToDevPxMatrix(this);
@ -57,5 +58,6 @@ nsSVGGenericContainerFrame::GetCanvasTM(uint32_t aFor)
NS_ASSERTION(mParent, "null parent");
return static_cast<nsSVGContainerFrame*>(mParent)->GetCanvasTM(aFor);
return static_cast<nsSVGContainerFrame*>(mParent)->
GetCanvasTM(aFor, aTransformRoot);
}

View File

@ -49,7 +49,8 @@ public:
#endif
// nsSVGContainerFrame methods:
virtual gfxMatrix GetCanvasTM(uint32_t aFor) MOZ_OVERRIDE;
virtual gfxMatrix GetCanvasTM(uint32_t aFor,
nsIFrame* aTransformRoot = nullptr) MOZ_OVERRIDE;
};
#endif // __NS_SVGGENERICCONTAINERFRAME_H__

View File

@ -52,7 +52,8 @@ public:
}
// nsSVGGeometryFrame methods:
virtual gfxMatrix GetCanvasTM(uint32_t aFor) = 0;
virtual gfxMatrix GetCanvasTM(uint32_t aFor,
nsIFrame* aTransformRoot = nullptr) = 0;
uint16_t GetClipRule();
protected:

View File

@ -358,7 +358,8 @@ nsSVGGlyphFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
NS_IMETHODIMP
nsSVGGlyphFrame::PaintSVG(nsRenderingContext *aContext,
const nsIntRect *aDirtyRect)
const nsIntRect *aDirtyRect,
nsIFrame* aTransformRoot)
{
if (!StyleVisibility()->IsVisible())
return NS_OK;
@ -387,7 +388,7 @@ nsSVGGlyphFrame::PaintSVG(nsRenderingContext *aContext,
renderMode == SVGAutoRenderState::CLIP_MASK,
"Unknown render mode");
gfxContextMatrixAutoSaveRestore matrixAutoSaveRestore(gfx);
SetupGlobalTransform(gfx, FOR_PAINTING);
SetupGlobalTransform(gfx, FOR_PAINTING, aTransformRoot);
CharacterIterator iter(this, true);
if (!iter.SetInitialMatrix(gfx)) {
@ -407,7 +408,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, FOR_PAINTING);
SetupGlobalTransform(gfx, FOR_PAINTING, aTransformRoot);
CharacterIterator iter(this, true);
if (!iter.SetInitialMatrix(gfx)) {
@ -672,19 +673,20 @@ nsSVGGlyphFrame::GetBBoxContribution(const gfxMatrix &aToBBoxUserspace,
// nsSVGGeometryFrame methods:
gfxMatrix
nsSVGGlyphFrame::GetCanvasTM(uint32_t aFor)
nsSVGGlyphFrame::GetCanvasTM(uint32_t aFor, nsIFrame* aTransformRoot)
{
if (mOverrideCanvasTM) {
return *mOverrideCanvasTM;
}
if (!(GetStateBits() & NS_FRAME_IS_NONDISPLAY)) {
if (!(GetStateBits() & NS_FRAME_IS_NONDISPLAY) && !aTransformRoot) {
if ((aFor == FOR_PAINTING && NS_SVGDisplayListPaintingEnabled()) ||
(aFor == FOR_HIT_TESTING && NS_SVGDisplayListHitTestingEnabled())) {
return nsSVGIntegrationUtils::GetCSSPxToDevPxMatrix(this);
}
}
NS_ASSERTION(mParent, "null parent");
return static_cast<nsSVGContainerFrame*>(mParent)->GetCanvasTM(aFor);
return static_cast<nsSVGContainerFrame*>(mParent)->
GetCanvasTM(aFor, aTransformRoot);
}
//----------------------------------------------------------------------
@ -1601,9 +1603,10 @@ nsSVGGlyphFrame::NotifyGlyphMetricsChange()
}
void
nsSVGGlyphFrame::SetupGlobalTransform(gfxContext *aContext, uint32_t aFor)
nsSVGGlyphFrame::SetupGlobalTransform(gfxContext *aContext, uint32_t aFor,
nsIFrame* aTransformRoot)
{
gfxMatrix matrix = GetCanvasTM(aFor);
gfxMatrix matrix = GetCanvasTM(aFor, aTransformRoot);
if (!matrix.IsSingular()) {
aContext->Multiply(matrix);
}

View File

@ -227,7 +227,8 @@ public:
// nsISVGChildFrame interface:
// These four always use the global transform, even if NS_STATE_NONDISPLAY_CHILD
NS_IMETHOD PaintSVG(nsRenderingContext *aContext,
const nsIntRect *aDirtyRect) MOZ_OVERRIDE;
const nsIntRect *aDirtyRect,
nsIFrame* aTransformRoot = nullptr) MOZ_OVERRIDE;
NS_IMETHOD_(nsIFrame*) GetFrameForPoint(const nsPoint &aPoint) MOZ_OVERRIDE;
virtual SVGBBox GetBBoxContribution(const gfxMatrix &aToBBoxUserspace,
uint32_t aFlags) MOZ_OVERRIDE;
@ -238,7 +239,8 @@ public:
NS_IMETHOD_(bool) IsDisplayContainer() MOZ_OVERRIDE { return false; }
// nsSVGGeometryFrame methods
gfxMatrix GetCanvasTM(uint32_t aFor) MOZ_OVERRIDE;
gfxMatrix GetCanvasTM(uint32_t aFor,
nsIFrame* aTransformRoot = nullptr) MOZ_OVERRIDE;
// nsISVGGlyphFragmentNode interface:
// These do not use the global transform if NS_STATE_NONDISPLAY_CHILD
@ -313,7 +315,8 @@ private:
gfxTextObjectPaint *aObjectPaint = nullptr);
void NotifyGlyphMetricsChange();
void SetupGlobalTransform(gfxContext *aContext, uint32_t aFor);
void SetupGlobalTransform(gfxContext *aContext, uint32_t aFor,
nsIFrame* aTransformRoot = nullptr);
float GetSubStringAdvance(uint32_t charnum, uint32_t fragmentChars,
float aMetricsScale);
gfxFloat GetBaselineOffset(float aMetricsScale);

View File

@ -55,7 +55,8 @@ public:
NS_DECL_FRAMEARENA_HELPERS
// nsISVGChildFrame interface:
NS_IMETHOD PaintSVG(nsRenderingContext *aContext, const nsIntRect *aDirtyRect);
NS_IMETHOD PaintSVG(nsRenderingContext *aContext, const nsIntRect *aDirtyRect,
nsIFrame* aTransformRoot) MOZ_OVERRIDE;
NS_IMETHOD_(nsIFrame*) GetFrameForPoint(const nsPoint &aPoint);
virtual void ReflowSVG();
@ -88,9 +89,12 @@ public:
private:
gfxMatrix GetRasterImageTransform(int32_t aNativeWidth,
int32_t aNativeHeight,
uint32_t aFor);
gfxMatrix GetVectorImageTransform(uint32_t aFor);
bool TransformContextForPainting(gfxContext* aGfxContext);
uint32_t aFor,
nsIFrame* aTransformRoot = nullptr);
gfxMatrix GetVectorImageTransform(uint32_t aFor,
nsIFrame* aTransformRoot = nullptr);
bool TransformContextForPainting(gfxContext* aGfxContext,
nsIFrame* aTransformRoot);
nsCOMPtr<imgINotificationObserver> mListener;
@ -205,7 +209,8 @@ nsSVGImageFrame::AttributeChanged(int32_t aNameSpaceID,
gfxMatrix
nsSVGImageFrame::GetRasterImageTransform(int32_t aNativeWidth,
int32_t aNativeHeight,
uint32_t aFor)
uint32_t aFor,
nsIFrame* aTransformRoot)
{
float x, y, width, height;
SVGImageElement *element = static_cast<SVGImageElement*>(mContent);
@ -216,11 +221,14 @@ nsSVGImageFrame::GetRasterImageTransform(int32_t aNativeWidth,
0, 0, aNativeWidth, aNativeHeight,
element->mPreserveAspectRatio);
return viewBoxTM * gfxMatrix().Translate(gfxPoint(x, y)) * GetCanvasTM(aFor);
return viewBoxTM *
gfxMatrix().Translate(gfxPoint(x, y)) *
GetCanvasTM(aFor, aTransformRoot);
}
gfxMatrix
nsSVGImageFrame::GetVectorImageTransform(uint32_t aFor)
nsSVGImageFrame::GetVectorImageTransform(uint32_t aFor,
nsIFrame* aTransformRoot)
{
float x, y, width, height;
SVGImageElement *element = static_cast<SVGImageElement*>(mContent);
@ -230,15 +238,17 @@ nsSVGImageFrame::GetVectorImageTransform(uint32_t aFor)
// "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(aFor);
return gfxMatrix().Translate(gfxPoint(x, y)) *
GetCanvasTM(aFor, aTransformRoot);
}
bool
nsSVGImageFrame::TransformContextForPainting(gfxContext* aGfxContext)
nsSVGImageFrame::TransformContextForPainting(gfxContext* aGfxContext,
nsIFrame* aTransformRoot)
{
gfxMatrix imageTransform;
if (mImageContainer->GetType() == imgIContainer::TYPE_VECTOR) {
imageTransform = GetVectorImageTransform(FOR_PAINTING);
imageTransform = GetVectorImageTransform(FOR_PAINTING, aTransformRoot);
} else {
int32_t nativeWidth, nativeHeight;
if (NS_FAILED(mImageContainer->GetWidth(&nativeWidth)) ||
@ -247,7 +257,8 @@ nsSVGImageFrame::TransformContextForPainting(gfxContext* aGfxContext)
return false;
}
imageTransform =
GetRasterImageTransform(nativeWidth, nativeHeight, FOR_PAINTING);
GetRasterImageTransform(nativeWidth, nativeHeight, FOR_PAINTING,
aTransformRoot);
// NOTE: We need to cancel out the effects of Full-Page-Zoom, or else
// it'll get applied an extra time by DrawSingleUnscaledImage.
@ -269,7 +280,8 @@ nsSVGImageFrame::TransformContextForPainting(gfxContext* aGfxContext)
// nsISVGChildFrame methods:
NS_IMETHODIMP
nsSVGImageFrame::PaintSVG(nsRenderingContext *aContext,
const nsIntRect *aDirtyRect)
const nsIntRect *aDirtyRect,
nsIFrame* aTransformRoot)
{
nsresult rv = NS_OK;
@ -300,10 +312,11 @@ nsSVGImageFrame::PaintSVG(nsRenderingContext *aContext,
if (StyleDisplay()->IsScrollableOverflow()) {
gfxRect clipRect = nsSVGUtils::GetClipRectForFrame(this, x, y,
width, height);
nsSVGUtils::SetClipRect(ctx, GetCanvasTM(FOR_PAINTING), clipRect);
nsSVGUtils::SetClipRect(ctx, GetCanvasTM(FOR_PAINTING, aTransformRoot),
clipRect);
}
if (!TransformContextForPainting(ctx)) {
if (!TransformContextForPainting(ctx, aTransformRoot)) {
return NS_ERROR_FAILURE;
}

View File

@ -59,7 +59,8 @@ nsSVGInnerSVGFrame::GetType() const
NS_IMETHODIMP
nsSVGInnerSVGFrame::PaintSVG(nsRenderingContext *aContext,
const nsIntRect *aDirtyRect)
const nsIntRect *aDirtyRect,
nsIFrame* aTransformRoot)
{
NS_ASSERTION(!NS_SVGDisplayListPaintingEnabled() ||
(mState & NS_FRAME_IS_NONDISPLAY),
@ -78,7 +79,7 @@ nsSVGInnerSVGFrame::PaintSVG(nsRenderingContext *aContext,
}
nsSVGContainerFrame *parent = static_cast<nsSVGContainerFrame*>(mParent);
gfxMatrix clipTransform = parent->GetCanvasTM(FOR_PAINTING);
gfxMatrix clipTransform = parent->GetCanvasTM(FOR_PAINTING, aTransformRoot);
gfxContext *gfx = aContext->ThebesContext();
autoSR.SetContext(gfx);
@ -268,9 +269,9 @@ nsSVGInnerSVGFrame::NotifyViewportOrTransformChanged(uint32_t aFlags)
// nsSVGContainerFrame methods:
gfxMatrix
nsSVGInnerSVGFrame::GetCanvasTM(uint32_t aFor)
nsSVGInnerSVGFrame::GetCanvasTM(uint32_t aFor, nsIFrame* aTransformRoot)
{
if (!(GetStateBits() & NS_FRAME_IS_NONDISPLAY)) {
if (!(GetStateBits() & NS_FRAME_IS_NONDISPLAY) && !aTransformRoot) {
if ((aFor == FOR_PAINTING && NS_SVGDisplayListPaintingEnabled()) ||
(aFor == FOR_HIT_TESTING && NS_SVGDisplayListHitTestingEnabled())) {
return nsSVGIntegrationUtils::GetCSSPxToDevPxMatrix(this);
@ -282,7 +283,9 @@ nsSVGInnerSVGFrame::GetCanvasTM(uint32_t aFor)
nsSVGContainerFrame *parent = static_cast<nsSVGContainerFrame*>(mParent);
SVGSVGElement *content = static_cast<SVGSVGElement*>(mContent);
gfxMatrix tm = content->PrependLocalTransformsTo(parent->GetCanvasTM(aFor));
gfxMatrix tm = content->PrependLocalTransformsTo(
this == aTransformRoot ? gfxMatrix() :
parent->GetCanvasTM(aFor, aTransformRoot));
mCanvasTM = new gfxMatrix(tm);
}

View File

@ -51,13 +51,16 @@ public:
int32_t aModType) MOZ_OVERRIDE;
// nsISVGChildFrame interface:
NS_IMETHOD PaintSVG(nsRenderingContext *aContext, const nsIntRect *aDirtyRect) MOZ_OVERRIDE;
NS_IMETHOD PaintSVG(nsRenderingContext *aContext,
const nsIntRect *aDirtyRect,
nsIFrame* aTransformRoot = nullptr) MOZ_OVERRIDE;
virtual void ReflowSVG() MOZ_OVERRIDE;
virtual void NotifySVGChanged(uint32_t aFlags) MOZ_OVERRIDE;
NS_IMETHOD_(nsIFrame*) GetFrameForPoint(const nsPoint &aPoint) MOZ_OVERRIDE;
// nsSVGContainerFrame methods:
virtual gfxMatrix GetCanvasTM(uint32_t aFor) MOZ_OVERRIDE;
virtual gfxMatrix GetCanvasTM(uint32_t aFor,
nsIFrame* aTransformRoot = nullptr) MOZ_OVERRIDE;
virtual bool HasChildrenOnlyTransform(gfxMatrix *aTransform) const MOZ_OVERRIDE;

View File

@ -382,7 +382,7 @@ public:
mOffset(aOffset) {}
virtual void Paint(nsRenderingContext *aContext, nsIFrame *aTarget,
const nsIntRect* aDirtyRect)
const nsIntRect* aDirtyRect, nsIFrame* aTransformRoot)
{
BasicLayerManager* basic = static_cast<BasicLayerManager*>(mLayerManager);
basic->SetTarget(aContext->ThebesContext());
@ -515,7 +515,7 @@ nsSVGIntegrationUtils::PaintFramesWithEffects(nsRenderingContext* aCtx,
RegularFramePaintCallback callback(aBuilder, aLayerManager,
offsetWithoutSVGGeomFramePos);
nsRect dirtyRect = aDirtyRect - offset;
filterFrame->PaintFilteredFrame(aCtx, aFrame, &callback, &dirtyRect);
filterFrame->PaintFilteredFrame(aCtx, aFrame, &callback, &dirtyRect, nullptr);
} else {
gfx->SetMatrix(matrixAutoSaveRestore.Matrix());
aLayerManager->EndTransaction(FrameLayerBuilder::DrawThebesLayer, aBuilder);

View File

@ -70,7 +70,7 @@ nsSVGMarkerFrame::GetType() const
// nsSVGContainerFrame methods:
gfxMatrix
nsSVGMarkerFrame::GetCanvasTM(uint32_t aFor)
nsSVGMarkerFrame::GetCanvasTM(uint32_t aFor, nsIFrame* aTransformRoot)
{
NS_ASSERTION(mMarkedFrame, "null nsSVGPathGeometry frame");
@ -82,7 +82,7 @@ nsSVGMarkerFrame::GetCanvasTM(uint32_t aFor)
SVGMarkerElement *content = static_cast<SVGMarkerElement*>(mContent);
mInUse2 = true;
gfxMatrix markedTM = mMarkedFrame->GetCanvasTM(aFor);
gfxMatrix markedTM = mMarkedFrame->GetCanvasTM(aFor, aTransformRoot);
mInUse2 = false;
gfxMatrix markerTM = content->GetMarkerTransform(mStrokeWidth, mX, mY,

View File

@ -97,7 +97,8 @@ private:
bool mIsStart; // whether the callback is for a marker-start marker
// nsSVGContainerFrame methods:
virtual gfxMatrix GetCanvasTM(uint32_t aFor) MOZ_OVERRIDE;
virtual gfxMatrix GetCanvasTM(uint32_t aFor,
nsIFrame* aTransformRoot = nullptr) MOZ_OVERRIDE;
// A helper class to allow us to paint markers safely. The helper
// automatically sets and clears the mInUse flag on the marker frame (to

View File

@ -170,7 +170,7 @@ nsSVGMaskFrame::GetType() const
}
gfxMatrix
nsSVGMaskFrame::GetCanvasTM(uint32_t aFor)
nsSVGMaskFrame::GetCanvasTM(uint32_t aFor, nsIFrame* aTransformRoot)
{
NS_ASSERTION(mMaskParentMatrix, "null parent matrix");

View File

@ -92,7 +92,8 @@ private:
bool mInUse;
// nsSVGContainerFrame methods:
virtual gfxMatrix GetCanvasTM(uint32_t aFor) MOZ_OVERRIDE;
virtual gfxMatrix GetCanvasTM(uint32_t aFor,
nsIFrame* aTransformRoot = nullptr) MOZ_OVERRIDE;
};
#endif

View File

@ -865,7 +865,8 @@ nsSVGOuterSVGFrame::NotifyViewportOrTransformChanged(uint32_t aFlags)
NS_IMETHODIMP
nsSVGOuterSVGFrame::PaintSVG(nsRenderingContext* aContext,
const nsIntRect *aDirtyRect)
const nsIntRect *aDirtyRect,
nsIFrame* aTransformRoot)
{
NS_ASSERTION(GetFirstPrincipalChild()->GetType() ==
nsGkAtoms::svgOuterSVGAnonChildFrame &&
@ -873,7 +874,7 @@ nsSVGOuterSVGFrame::PaintSVG(nsRenderingContext* aContext,
"We should have a single, anonymous, child");
nsSVGOuterSVGAnonChildFrame *anonKid =
static_cast<nsSVGOuterSVGAnonChildFrame*>(GetFirstPrincipalChild());
return anonKid->PaintSVG(aContext, aDirtyRect);
return anonKid->PaintSVG(aContext, aDirtyRect, aTransformRoot);
}
SVGBBox
@ -895,15 +896,16 @@ nsSVGOuterSVGFrame::GetBBoxContribution(const gfxMatrix &aToBBoxUserspace,
// nsSVGContainerFrame methods:
gfxMatrix
nsSVGOuterSVGFrame::GetCanvasTM(uint32_t aFor)
nsSVGOuterSVGFrame::GetCanvasTM(uint32_t aFor, nsIFrame* aTransformRoot)
{
if (!(GetStateBits() & NS_FRAME_IS_NONDISPLAY)) {
if (!(GetStateBits() & NS_FRAME_IS_NONDISPLAY) && !aTransformRoot) {
if ((aFor == FOR_PAINTING && NS_SVGDisplayListPaintingEnabled()) ||
(aFor == FOR_HIT_TESTING && NS_SVGDisplayListHitTestingEnabled())) {
return nsSVGIntegrationUtils::GetCSSPxToDevPxMatrix(this);
}
}
if (!mCanvasTM) {
NS_ASSERTION(!aTransformRoot, "transform root will be ignored here");
SVGSVGElement *content = static_cast<SVGSVGElement*>(mContent);
float devPxPerCSSPx =

View File

@ -111,13 +111,15 @@ public:
// nsISVGChildFrame methods:
NS_IMETHOD PaintSVG(nsRenderingContext* aContext,
const nsIntRect *aDirtyRect) MOZ_OVERRIDE;
const nsIntRect *aDirtyRect,
nsIFrame* aTransformRoot = nullptr) MOZ_OVERRIDE;
virtual SVGBBox GetBBoxContribution(const gfxMatrix &aToBBoxUserspace,
uint32_t aFlags) MOZ_OVERRIDE;
// nsSVGContainerFrame methods:
virtual gfxMatrix GetCanvasTM(uint32_t aFor) MOZ_OVERRIDE;
virtual gfxMatrix GetCanvasTM(uint32_t aFor,
nsIFrame* aTransformRoot = nullptr) MOZ_OVERRIDE;
/* Methods to allow descendant nsSVGForeignObjectFrame frames to register and
* unregister themselves with their nearest nsSVGOuterSVGFrame ancestor. This
@ -261,11 +263,12 @@ public:
virtual nsIAtom* GetType() const MOZ_OVERRIDE;
// nsSVGContainerFrame methods:
virtual gfxMatrix GetCanvasTM(uint32_t aFor) MOZ_OVERRIDE {
virtual gfxMatrix GetCanvasTM(uint32_t aFor,
nsIFrame* aTransformRoot) MOZ_OVERRIDE {
// GetCanvasTM returns the transform from an SVG frame to the frame's
// nsSVGOuterSVGFrame's content box, so we do not include any x/y offset
// set on us for any CSS border or padding on our nsSVGOuterSVGFrame.
return static_cast<nsSVGOuterSVGFrame*>(mParent)->GetCanvasTM(aFor);
return static_cast<nsSVGOuterSVGFrame*>(mParent)->GetCanvasTM(aFor, aTransformRoot);
}
virtual bool HasChildrenOnlyTransform(gfxMatrix *aTransform) const MOZ_OVERRIDE;

View File

@ -188,14 +188,15 @@ nsSVGPathGeometryFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
NS_IMETHODIMP
nsSVGPathGeometryFrame::PaintSVG(nsRenderingContext *aContext,
const nsIntRect *aDirtyRect)
const nsIntRect *aDirtyRect,
nsIFrame* aTransformRoot)
{
if (!StyleVisibility()->IsVisible())
return NS_OK;
uint32_t paintOrder = StyleSVG()->mPaintOrder;
if (paintOrder == NS_STYLE_PAINT_ORDER_NORMAL) {
Render(aContext, eRenderFill | eRenderStroke);
Render(aContext, eRenderFill | eRenderStroke, aTransformRoot);
PaintMarkers(aContext);
} else {
while (paintOrder) {
@ -203,10 +204,10 @@ nsSVGPathGeometryFrame::PaintSVG(nsRenderingContext *aContext,
paintOrder & ((1 << NS_STYLE_PAINT_ORDER_BITWIDTH) - 1);
switch (component) {
case NS_STYLE_PAINT_ORDER_FILL:
Render(aContext, eRenderFill);
Render(aContext, eRenderFill, aTransformRoot);
break;
case NS_STYLE_PAINT_ORDER_STROKE:
Render(aContext, eRenderStroke);
Render(aContext, eRenderStroke, aTransformRoot);
break;
case NS_STYLE_PAINT_ORDER_MARKERS:
PaintMarkers(aContext);
@ -497,9 +498,9 @@ nsSVGPathGeometryFrame::GetBBoxContribution(const gfxMatrix &aToBBoxUserspace,
// nsSVGGeometryFrame methods:
gfxMatrix
nsSVGPathGeometryFrame::GetCanvasTM(uint32_t aFor)
nsSVGPathGeometryFrame::GetCanvasTM(uint32_t aFor, nsIFrame* aTransformRoot)
{
if (!(GetStateBits() & NS_FRAME_IS_NONDISPLAY)) {
if (!(GetStateBits() & NS_FRAME_IS_NONDISPLAY) && !aTransformRoot) {
if ((aFor == FOR_PAINTING && NS_SVGDisplayListPaintingEnabled()) ||
(aFor == FOR_HIT_TESTING && NS_SVGDisplayListHitTestingEnabled())) {
return nsSVGIntegrationUtils::GetCSSPxToDevPxMatrix(this);
@ -511,7 +512,9 @@ nsSVGPathGeometryFrame::GetCanvasTM(uint32_t aFor)
nsSVGContainerFrame *parent = static_cast<nsSVGContainerFrame*>(mParent);
dom::SVGGraphicsElement *content = static_cast<dom::SVGGraphicsElement*>(mContent);
return content->PrependLocalTransformsTo(parent->GetCanvasTM(aFor));
return content->PrependLocalTransformsTo(
this == aTransformRoot ? gfxMatrix() :
parent->GetCanvasTM(aFor, aTransformRoot));
}
//----------------------------------------------------------------------
@ -565,7 +568,8 @@ nsSVGPathGeometryFrame::MarkerProperties::GetMarkerEndFrame()
void
nsSVGPathGeometryFrame::Render(nsRenderingContext *aContext,
uint32_t aRenderComponents)
uint32_t aRenderComponents,
nsIFrame* aTransformRoot)
{
gfxContext *gfx = aContext->ThebesContext();
@ -584,7 +588,7 @@ nsSVGPathGeometryFrame::Render(nsRenderingContext *aContext,
/* save/restore the state so we don't screw up the xform */
gfx->Save();
GeneratePath(gfx, GetCanvasTM(FOR_PAINTING));
GeneratePath(gfx, GetCanvasTM(FOR_PAINTING, aTransformRoot));
if (renderMode != SVGAutoRenderState::NORMAL) {
NS_ABORT_IF_FALSE(renderMode == SVGAutoRenderState::CLIP ||

View File

@ -81,12 +81,14 @@ public:
const nsDisplayListSet& aLists) MOZ_OVERRIDE;
// nsSVGGeometryFrame methods
gfxMatrix GetCanvasTM(uint32_t aFor) MOZ_OVERRIDE;
gfxMatrix GetCanvasTM(uint32_t aFor,
nsIFrame* aTransformRoot = nullptr) MOZ_OVERRIDE;
protected:
// nsISVGChildFrame interface:
NS_IMETHOD PaintSVG(nsRenderingContext *aContext,
const nsIntRect *aDirtyRect) MOZ_OVERRIDE;
const nsIntRect *aDirtyRect,
nsIFrame* aTransformRoot = nullptr) MOZ_OVERRIDE;
NS_IMETHOD_(nsIFrame*) GetFrameForPoint(const nsPoint &aPoint) MOZ_OVERRIDE;
NS_IMETHOD_(nsRect) GetCoveredRegion() MOZ_OVERRIDE;
virtual void ReflowSVG() MOZ_OVERRIDE;
@ -100,7 +102,8 @@ protected:
private:
enum { eRenderFill = 1, eRenderStroke = 2 };
void Render(nsRenderingContext *aContext, uint32_t aRenderComponents);
void Render(nsRenderingContext *aContext, uint32_t aRenderComponents,
nsIFrame* aTransformRoot);
void PaintMarkers(nsRenderingContext *aContext);
struct MarkerProperties {

View File

@ -119,7 +119,7 @@ nsSVGPatternFrame::GetType() const
// matrix, which depends on our units parameters
// and X, Y, Width, and Height
gfxMatrix
nsSVGPatternFrame::GetCanvasTM(uint32_t aFor)
nsSVGPatternFrame::GetCanvasTM(uint32_t aFor, nsIFrame* aTransformRoot)
{
if (mCTM) {
return *mCTM;
@ -128,7 +128,7 @@ nsSVGPatternFrame::GetCanvasTM(uint32_t aFor)
// Do we know our rendering parent?
if (mSource) {
// Yes, use it!
return mSource->GetCanvasTM(aFor);
return mSource->GetCanvasTM(aFor, aTransformRoot);
}
// We get here when geometry in the <pattern> container is updated

View File

@ -50,7 +50,8 @@ public:
typedef mozilla::SVGAnimatedPreserveAspectRatio SVGAnimatedPreserveAspectRatio;
// nsSVGContainerFrame methods:
virtual gfxMatrix GetCanvasTM(uint32_t aFor) MOZ_OVERRIDE;
virtual gfxMatrix GetCanvasTM(uint32_t aFor,
nsIFrame* aTransformRoot = nullptr) MOZ_OVERRIDE;
// nsIFrame interface:
NS_IMETHOD AttributeChanged(int32_t aNameSpaceID,

View File

@ -51,7 +51,9 @@ public:
const nsDisplayListSet& aLists) MOZ_OVERRIDE;
// nsISVGChildFrame interface:
NS_IMETHOD PaintSVG(nsRenderingContext* aContext, const nsIntRect *aDirtyRect);
NS_IMETHOD PaintSVG(nsRenderingContext* aContext,
const nsIntRect *aDirtyRect,
nsIFrame* aTransformRoot) MOZ_OVERRIDE;
NS_IMETHODIMP_(nsIFrame*) GetFrameForPoint(const nsPoint &aPoint);
NS_IMETHODIMP_(nsRect) GetCoveredRegion();
virtual void ReflowSVG();
@ -105,7 +107,8 @@ nsSVGSwitchFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
NS_IMETHODIMP
nsSVGSwitchFrame::PaintSVG(nsRenderingContext* aContext,
const nsIntRect *aDirtyRect)
const nsIntRect *aDirtyRect,
nsIFrame* aTransformRoot)
{
NS_ASSERTION(!NS_SVGDisplayListPaintingEnabled() ||
(mState & NS_FRAME_IS_NONDISPLAY),
@ -117,7 +120,7 @@ nsSVGSwitchFrame::PaintSVG(nsRenderingContext* aContext,
nsIFrame *kid = GetActiveChildFrame();
if (kid) {
nsSVGUtils::PaintFrameWithEffects(aContext, aDirtyRect, kid);
nsSVGUtils::PaintFrameWithEffects(aContext, aDirtyRect, kid, aTransformRoot);
}
return NS_OK;
}

View File

@ -91,16 +91,17 @@ nsSVGTSpanFrame::AttributeChanged(int32_t aNameSpaceID,
// nsSVGContainerFrame methods:
gfxMatrix
nsSVGTSpanFrame::GetCanvasTM(uint32_t aFor)
nsSVGTSpanFrame::GetCanvasTM(uint32_t aFor, nsIFrame* aTransformRoot)
{
if (!(GetStateBits() & NS_FRAME_IS_NONDISPLAY)) {
if (!(GetStateBits() & NS_FRAME_IS_NONDISPLAY) && !aTransformRoot) {
if ((aFor == FOR_PAINTING && NS_SVGDisplayListPaintingEnabled()) ||
(aFor == FOR_HIT_TESTING && NS_SVGDisplayListHitTestingEnabled())) {
return nsSVGIntegrationUtils::GetCSSPxToDevPxMatrix(this);
}
}
NS_ASSERTION(mParent, "null parent");
return static_cast<nsSVGContainerFrame*>(mParent)->GetCanvasTM(aFor);
return static_cast<nsSVGContainerFrame*>(mParent)->
GetCanvasTM(aFor, aTransformRoot);
}
//----------------------------------------------------------------------

View File

@ -65,7 +65,8 @@ public:
}
#endif
// nsSVGContainerFrame methods:
virtual gfxMatrix GetCanvasTM(uint32_t aFor) MOZ_OVERRIDE;
virtual gfxMatrix GetCanvasTM(uint32_t aFor,
nsIFrame* aTransformRoot = nullptr) MOZ_OVERRIDE;
// nsISVGGlyphFragmentNode interface:
virtual uint32_t GetNumberOfChars() MOZ_OVERRIDE;

View File

@ -203,7 +203,8 @@ nsSVGTextFrame::NotifySVGChanged(uint32_t aFlags)
NS_IMETHODIMP
nsSVGTextFrame::PaintSVG(nsRenderingContext* aContext,
const nsIntRect *aDirtyRect)
const nsIntRect *aDirtyRect,
nsIFrame* aTransformRoot)
{
NS_ASSERTION(!NS_SVGDisplayListPaintingEnabled() ||
(mState & NS_FRAME_IS_NONDISPLAY),
@ -212,7 +213,7 @@ nsSVGTextFrame::PaintSVG(nsRenderingContext* aContext,
UpdateGlyphPositioning(true);
return nsSVGTextFrameBase::PaintSVG(aContext, aDirtyRect);
return nsSVGTextFrameBase::PaintSVG(aContext, aDirtyRect, aTransformRoot);
}
NS_IMETHODIMP_(nsIFrame*)
@ -268,23 +269,23 @@ nsSVGTextFrame::GetBBoxContribution(const gfxMatrix &aToBBoxUserspace,
// nsSVGContainerFrame methods:
gfxMatrix
nsSVGTextFrame::GetCanvasTM(uint32_t aFor)
nsSVGTextFrame::GetCanvasTM(uint32_t aFor, nsIFrame* aTransformRoot)
{
if (!(GetStateBits() & NS_FRAME_IS_NONDISPLAY)) {
if (!(GetStateBits() & NS_FRAME_IS_NONDISPLAY) && !aTransformRoot) {
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<nsSVGContainerFrame*>(mParent);
dom::SVGGraphicsElement *content = static_cast<dom::SVGGraphicsElement*>(mContent);
gfxMatrix tm =
content->PrependLocalTransformsTo(parent->GetCanvasTM(aFor));
gfxMatrix tm = content->PrependLocalTransformsTo(
this == aTransformRoot ? gfxMatrix() :
parent->GetCanvasTM(aFor, aTransformRoot));
mCanvasTM = new gfxMatrix(tm);
}

View File

@ -68,14 +68,16 @@ public:
// Override these four to ensure that UpdateGlyphPositioning is called
// to bring glyph positions up to date
NS_IMETHOD PaintSVG(nsRenderingContext* aContext,
const nsIntRect *aDirtyRect) MOZ_OVERRIDE;
const nsIntRect *aDirtyRect,
nsIFrame* aTransformRoot = nullptr) MOZ_OVERRIDE;
NS_IMETHOD_(nsIFrame*) GetFrameForPoint(const nsPoint & aPoint) MOZ_OVERRIDE;
virtual void ReflowSVG() MOZ_OVERRIDE;
virtual SVGBBox GetBBoxContribution(const gfxMatrix &aToBBoxUserspace,
uint32_t aFlags) MOZ_OVERRIDE;
// nsSVGContainerFrame methods:
virtual gfxMatrix GetCanvasTM(uint32_t aFor) MOZ_OVERRIDE;
virtual gfxMatrix GetCanvasTM(uint32_t aFor,
nsIFrame* aTransformRoot = nullptr) MOZ_OVERRIDE;
// nsSVGTextContainerFrame methods:
virtual uint32_t GetNumberOfChars() MOZ_OVERRIDE;

View File

@ -3437,7 +3437,8 @@ ShouldPaintCaret(const TextRenderedRun& aThisRun, nsCaret* aCaret)
NS_IMETHODIMP
nsSVGTextFrame2::PaintSVG(nsRenderingContext* aContext,
const nsIntRect *aDirtyRect)
const nsIntRect *aDirtyRect,
nsIFrame* aTransformRoot)
{
nsIFrame* kid = GetFirstPrincipalChild();
if (!kid)
@ -3467,7 +3468,7 @@ nsSVGTextFrame2::PaintSVG(nsRenderingContext* aContext,
return NS_OK;
}
gfxMatrix canvasTM = GetCanvasTM(FOR_PAINTING);
gfxMatrix canvasTM = GetCanvasTM(FOR_PAINTING, aTransformRoot);
if (canvasTM.IsSingular()) {
NS_WARNING("Can't render text element!");
return NS_ERROR_FAILURE;
@ -3731,9 +3732,10 @@ nsSVGTextFrame2::GetBBoxContribution(const gfxMatrix &aToBBoxUserspace,
// nsSVGContainerFrame methods
gfxMatrix
nsSVGTextFrame2::GetCanvasTM(uint32_t aFor)
nsSVGTextFrame2::GetCanvasTM(uint32_t aFor, nsIFrame* aTransformRoot)
{
if (!(GetStateBits() & NS_FRAME_IS_NONDISPLAY)) {
if (!(GetStateBits() & NS_FRAME_IS_NONDISPLAY) &&
!aTransformRoot) {
if ((aFor == FOR_PAINTING && NS_SVGDisplayListPaintingEnabled()) ||
(aFor == FOR_HIT_TESTING && NS_SVGDisplayListHitTestingEnabled())) {
return nsSVGIntegrationUtils::GetCSSPxToDevPxMatrix(this);
@ -3749,7 +3751,9 @@ nsSVGTextFrame2::GetCanvasTM(uint32_t aFor)
nsSVGContainerFrame *parent = static_cast<nsSVGContainerFrame*>(mParent);
dom::SVGTextContentElement *content = static_cast<dom::SVGTextContentElement*>(mContent);
gfxMatrix tm = content->PrependLocalTransformsTo(parent->GetCanvasTM(aFor));
gfxMatrix tm = content->PrependLocalTransformsTo(
this == aTransformRoot ? gfxMatrix() :
parent->GetCanvasTM(aFor, aTransformRoot));
mCanvasTM = new gfxMatrix(tm);
}

View File

@ -245,7 +245,8 @@ public:
// nsISVGChildFrame interface:
virtual void NotifySVGChanged(uint32_t aFlags) MOZ_OVERRIDE;
NS_IMETHOD PaintSVG(nsRenderingContext* aContext,
const nsIntRect* aDirtyRect) MOZ_OVERRIDE;
const nsIntRect* aDirtyRect,
nsIFrame* aTransformRoot = nullptr) MOZ_OVERRIDE;
NS_IMETHOD_(nsIFrame*) GetFrameForPoint(const nsPoint& aPoint) MOZ_OVERRIDE;
virtual void ReflowSVG() MOZ_OVERRIDE;
NS_IMETHOD_(nsRect) GetCoveredRegion() MOZ_OVERRIDE;
@ -253,7 +254,8 @@ public:
uint32_t aFlags) MOZ_OVERRIDE;
// nsSVGContainerFrame methods:
virtual gfxMatrix GetCanvasTM(uint32_t aFor) MOZ_OVERRIDE;
virtual gfxMatrix GetCanvasTM(uint32_t aFor,
nsIFrame* aTransformRoot = nullptr) MOZ_OVERRIDE;
// SVG DOM text methods:
uint32_t GetNumberOfChars(nsIContent* aContent);

View File

@ -630,7 +630,8 @@ nsSVGUtils::GetOuterSVGFrameAndCoveredRegion(nsIFrame* aFrame, nsRect* aRect)
}
gfxMatrix
nsSVGUtils::GetCanvasTM(nsIFrame *aFrame, uint32_t aFor)
nsSVGUtils::GetCanvasTM(nsIFrame *aFrame, uint32_t aFor,
nsIFrame* aTransformRoot)
{
// XXX yuck, we really need a common interface for GetCanvasTM
@ -638,7 +639,8 @@ nsSVGUtils::GetCanvasTM(nsIFrame *aFrame, uint32_t aFor)
return nsSVGIntegrationUtils::GetCSSPxToDevPxMatrix(aFrame);
}
if (!(aFrame->GetStateBits() & NS_FRAME_IS_NONDISPLAY)) {
if (!(aFrame->GetStateBits() & NS_FRAME_IS_NONDISPLAY) &&
!aTransformRoot) {
if ((aFor == nsISVGChildFrame::FOR_PAINTING &&
NS_SVGDisplayListPaintingEnabled()) ||
(aFor == nsISVGChildFrame::FOR_HIT_TESTING &&
@ -649,7 +651,8 @@ nsSVGUtils::GetCanvasTM(nsIFrame *aFrame, uint32_t aFor)
nsIAtom* type = aFrame->GetType();
if (type == nsGkAtoms::svgForeignObjectFrame) {
return static_cast<nsSVGForeignObjectFrame*>(aFrame)->GetCanvasTM(aFor);
return static_cast<nsSVGForeignObjectFrame*>(aFrame)->
GetCanvasTM(aFor, aTransformRoot);
}
if (type == nsGkAtoms::svgOuterSVGFrame) {
return nsSVGIntegrationUtils::GetCSSPxToDevPxMatrix(aFrame);
@ -657,10 +660,11 @@ nsSVGUtils::GetCanvasTM(nsIFrame *aFrame, uint32_t aFor)
nsSVGContainerFrame *containerFrame = do_QueryFrame(aFrame);
if (containerFrame) {
return containerFrame->GetCanvasTM(aFor);
return containerFrame->GetCanvasTM(aFor, aTransformRoot);
}
return static_cast<nsSVGGeometryFrame*>(aFrame)->GetCanvasTM(aFor);
return static_cast<nsSVGGeometryFrame*>(aFrame)->
GetCanvasTM(aFor, aTransformRoot);
}
gfxMatrix
@ -710,7 +714,7 @@ class SVGPaintCallback : public nsSVGFilterPaintCallback
{
public:
virtual void Paint(nsRenderingContext *aContext, nsIFrame *aTarget,
const nsIntRect* aDirtyRect)
const nsIntRect* aDirtyRect, nsIFrame* aTransformRoot)
{
nsISVGChildFrame *svgChildFrame = do_QueryFrame(aTarget);
NS_ASSERTION(svgChildFrame, "Expected SVG frame here");
@ -722,7 +726,7 @@ public:
// outer-SVG-frame-relative device pixels.
if (aDirtyRect) {
gfxMatrix userToDeviceSpace =
nsSVGUtils::GetCanvasTM(aTarget, nsISVGChildFrame::FOR_PAINTING);
nsSVGUtils::GetCanvasTM(aTarget, nsISVGChildFrame::FOR_PAINTING, aTransformRoot);
if (userToDeviceSpace.IsSingular()) {
return;
}
@ -734,14 +738,15 @@ public:
}
}
svgChildFrame->PaintSVG(aContext, dirtyRect);
svgChildFrame->PaintSVG(aContext, dirtyRect, aTransformRoot);
}
};
void
nsSVGUtils::PaintFrameWithEffects(nsRenderingContext *aContext,
const nsIntRect *aDirtyRect,
nsIFrame *aFrame)
nsIFrame *aFrame,
nsIFrame *aTransformRoot)
{
NS_ASSERTION(!NS_SVGDisplayListPaintingEnabled() ||
(aFrame->GetStateBits() & NS_FRAME_IS_NONDISPLAY) ||
@ -786,7 +791,7 @@ nsSVGUtils::PaintFrameWithEffects(nsRenderingContext *aContext,
overflowRect = overflowRect + aFrame->GetPosition();
}
int32_t appUnitsPerDevPx = aFrame->PresContext()->AppUnitsPerDevPixel();
gfxMatrix tm = GetCanvasTM(aFrame, nsISVGChildFrame::FOR_PAINTING);
gfxMatrix tm = GetCanvasTM(aFrame, nsISVGChildFrame::FOR_PAINTING, aTransformRoot);
if (aFrame->IsFrameOfType(nsIFrame::eSVG | nsIFrame::eSVGContainer)) {
gfxMatrix childrenOnlyTM;
if (static_cast<nsSVGContainerFrame*>(aFrame)->
@ -837,7 +842,7 @@ nsSVGUtils::PaintFrameWithEffects(nsRenderingContext *aContext,
gfxMatrix matrix;
if (clipPathFrame || maskFrame)
matrix = GetCanvasTM(aFrame, nsISVGChildFrame::FOR_PAINTING);
matrix = GetCanvasTM(aFrame, nsISVGChildFrame::FOR_PAINTING, aTransformRoot);
/* Check if we need to do additional operations on this child's
* rendering, which necessitates rendering into another surface. */
@ -848,7 +853,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, nsISVGChildFrame::FOR_PAINTING));
gfx->Multiply(GetCanvasTM(aFrame, nsISVGChildFrame::FOR_PAINTING, aTransformRoot));
nsRect overflowRect = aFrame->GetVisualOverflowRectRelativeToSelf();
if (aFrame->IsFrameOfType(nsIFrame::eSVGGeometry) ||
aFrame->IsSVGText()) {
@ -893,9 +898,9 @@ nsSVGUtils::PaintFrameWithEffects(nsRenderingContext *aContext,
dirtyRect = &tmpDirtyRect;
}
SVGPaintCallback paintCallback;
filterFrame->PaintFilteredFrame(aContext, aFrame, &paintCallback, dirtyRect);
filterFrame->PaintFilteredFrame(aContext, aFrame, &paintCallback, dirtyRect, aTransformRoot);
} else {
svgChildFrame->PaintSVG(aContext, aDirtyRect);
svgChildFrame->PaintSVG(aContext, aDirtyRect, aTransformRoot);
}
if (clipPathFrame && isTrivialClip) {
@ -1837,7 +1842,8 @@ nsSVGUtils::PaintSVGGlyph(Element* aElement, gfxContext* aContext,
nsRenderingContext context;
context.Init(frame->PresContext()->DeviceContext(), aContext);
context.AddUserData(&gfxTextObjectPaint::sUserDataKey, aObjectPaint, nullptr);
nsresult rv = svgFrame->PaintSVG(&context, nullptr);
svgFrame->NotifySVGChanged(nsISVGChildFrame::TRANSFORM_CHANGED);
nsresult rv = svgFrame->PaintSVG(&context, nullptr, frame);
return NS_SUCCEEDED(rv);
}

View File

@ -391,7 +391,8 @@ public:
static void
PaintFrameWithEffects(nsRenderingContext *aContext,
const nsIntRect *aDirtyRect,
nsIFrame *aFrame);
nsIFrame *aFrame,
nsIFrame* aTransformRoot = nullptr);
/* Hit testing - check if point hits the clipPath of indicated
* frame. Returns true if no clipPath set. */
@ -408,7 +409,8 @@ 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, uint32_t aFor);
static gfxMatrix GetCanvasTM(nsIFrame* aFrame, uint32_t aFor,
nsIFrame* aTransformRoot = nullptr);
/**
* Returns the transform from aFrame's user space to canvas space. Only call