Bug 767734 - Give GetCanvasTM knowledge of what the request is for so it can do the right thing when SVG display lists are enabled. r=longsonr.

This commit is contained in:
Jonathan Watt 2012-06-30 12:20:46 +01:00
Родитель 3b0c752628
Коммит 9a0c75c977
34 изменённых файлов: 250 добавлений и 112 удалений

Просмотреть файл

@ -64,6 +64,18 @@ public:
// be called by nsSVGOuterSVGFrame during its reflow. // be called by nsSVGOuterSVGFrame during its reflow.
virtual void UpdateBounds()=0; 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: // Flags to pass to NotifySVGChange:
// //
// DO_NOT_NOTIFY_RENDERING_OBSERVERS - this should only be used when // DO_NOT_NOTIFY_RENDERING_OBSERVERS - this should only be used when

Просмотреть файл

@ -6,6 +6,7 @@
// Keep in (case-insensitive) order: // Keep in (case-insensitive) order:
#include "gfxMatrix.h" #include "gfxMatrix.h"
#include "nsSVGAElement.h" #include "nsSVGAElement.h"
#include "nsSVGIntegrationUtils.h"
#include "nsSVGTSpanFrame.h" #include "nsSVGTSpanFrame.h"
#include "nsSVGUtils.h" #include "nsSVGUtils.h"
#include "SVGLengthList.h" #include "SVGLengthList.h"
@ -58,7 +59,7 @@ public:
virtual void NotifySVGChanged(PRUint32 aFlags); virtual void NotifySVGChanged(PRUint32 aFlags);
// nsSVGContainerFrame methods: // nsSVGContainerFrame methods:
virtual gfxMatrix GetCanvasTM(); virtual gfxMatrix GetCanvasTM(PRUint32 aFor);
// nsSVGTextContainerFrame methods: // nsSVGTextContainerFrame methods:
virtual void GetXY(mozilla::SVGUserUnitList *aX, mozilla::SVGUserUnitList *aY); virtual void GetXY(mozilla::SVGUserUnitList *aX, mozilla::SVGUserUnitList *aY);
@ -144,15 +145,21 @@ nsSVGAFrame::NotifySVGChanged(PRUint32 aFlags)
// nsSVGContainerFrame methods: // nsSVGContainerFrame methods:
gfxMatrix 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) { if (!mCanvasTM) {
NS_ASSERTION(mParent, "null parent"); NS_ASSERTION(mParent, "null parent");
nsSVGContainerFrame *parent = static_cast<nsSVGContainerFrame*>(mParent); nsSVGContainerFrame *parent = static_cast<nsSVGContainerFrame*>(mParent);
nsSVGAElement *content = static_cast<nsSVGAElement*>(mContent); nsSVGAElement *content = static_cast<nsSVGAElement*>(mContent);
gfxMatrix tm = content->PrependLocalTransformsTo(parent->GetCanvasTM()); gfxMatrix tm = content->PrependLocalTransformsTo(parent->GetCanvasTM(aFor));
mCanvasTM = new gfxMatrix(tm); mCanvasTM = new gfxMatrix(tm);
} }

Просмотреть файл

@ -317,7 +317,7 @@ nsSVGClipPathFrame::GetType() const
} }
gfxMatrix gfxMatrix
nsSVGClipPathFrame::GetCanvasTM() nsSVGClipPathFrame::GetCanvasTM(PRUint32 aFor)
{ {
nsSVGClipPathElement *content = static_cast<nsSVGClipPathElement*>(mContent); nsSVGClipPathElement *content = static_cast<nsSVGClipPathElement*>(mContent);

Просмотреть файл

@ -95,7 +95,7 @@ public:
bool mInUse; bool mInUse;
// nsSVGContainerFrame methods: // nsSVGContainerFrame methods:
virtual gfxMatrix GetCanvasTM(); virtual gfxMatrix GetCanvasTM(PRUint32 aFor);
}; };
#endif #endif

Просмотреть файл

@ -50,7 +50,9 @@ public:
NS_DECL_FRAMEARENA_HELPERS NS_DECL_FRAMEARENA_HELPERS
// Returns the transform to our gfxContext (to device pixels, not CSS px) // 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 * Returns true if the frame's content has a transform that applies only to

Просмотреть файл

@ -207,7 +207,8 @@ nsAutoFilterInstance::nsAutoFilterInstance(nsIFrame *aTarget,
} else { } else {
// Match filterRes as closely as possible to the pixel density of the nearest // Match filterRes as closely as possible to the pixel density of the nearest
// outer 'svg' device space: // outer 'svg' device space:
gfxMatrix canvasTM = nsSVGUtils::GetCanvasTM(aTarget); gfxMatrix canvasTM =
nsSVGUtils::GetCanvasTM(aTarget, nsISVGChildFrame::FOR_OUTERSVG_TM);
if (canvasTM.IsSingular()) { if (canvasTM.IsSingular()) {
// nothing to draw // nothing to draw
return; return;
@ -233,8 +234,8 @@ nsAutoFilterInstance::nsAutoFilterInstance(nsIFrame *aTarget,
// Only used (so only set) when we paint: // Only used (so only set) when we paint:
gfxMatrix filterToDeviceSpace; gfxMatrix filterToDeviceSpace;
if (aPaint) { if (aPaint) {
filterToDeviceSpace = filterToDeviceSpace = filterToUserSpace *
filterToUserSpace * nsSVGUtils::GetCanvasTM(aTarget); nsSVGUtils::GetCanvasTM(aTarget, nsISVGChildFrame::FOR_PAINTING);
} }
// Convert the passed in rects from frame to filter space: // Convert the passed in rects from frame to filter space:

Просмотреть файл

@ -18,6 +18,7 @@
#include "nsSVGContainerFrame.h" #include "nsSVGContainerFrame.h"
#include "nsSVGEffects.h" #include "nsSVGEffects.h"
#include "nsSVGForeignObjectElement.h" #include "nsSVGForeignObjectElement.h"
#include "nsSVGIntegrationUtils.h"
#include "nsSVGOuterSVGFrame.h" #include "nsSVGOuterSVGFrame.h"
#include "nsSVGUtils.h" #include "nsSVGUtils.h"
#include "mozilla/AutoRestore.h" #include "mozilla/AutoRestore.h"
@ -192,10 +193,9 @@ nsSVGForeignObjectFrame::PaintSVG(nsRenderingContext *aContext,
if (!kid) if (!kid)
return NS_OK; return NS_OK;
gfxMatrix matrixForChildren = GetCanvasTMForChildren(); gfxMatrix canvasTM = GetCanvasTM(FOR_PAINTING);
gfxMatrix matrix = GetCanvasTM();
if (matrixForChildren.IsSingular()) { if (canvasTM.IsSingular()) {
NS_WARNING("Can't render foreignObject element!"); NS_WARNING("Can't render foreignObject element!");
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
@ -205,7 +205,7 @@ nsSVGForeignObjectFrame::PaintSVG(nsRenderingContext *aContext,
/* Check if we need to draw anything. */ /* Check if we need to draw anything. */
if (aDirtyRect) { if (aDirtyRect) {
// Transform the dirty rect into app units in our userspace. // Transform the dirty rect into app units in our userspace.
gfxMatrix invmatrix = matrix; gfxMatrix invmatrix = canvasTM;
invmatrix.Invert(); invmatrix.Invert();
NS_ASSERTION(!invmatrix.IsSingular(), NS_ASSERTION(!invmatrix.IsSingular(),
"inverse of non-singular matrix should be non-singular"); "inverse of non-singular matrix should be non-singular");
@ -237,10 +237,18 @@ nsSVGForeignObjectFrame::PaintSVG(nsRenderingContext *aContext,
gfxRect clipRect = gfxRect clipRect =
nsSVGUtils::GetClipRectForFrame(this, 0.0f, 0.0f, width, height); 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; PRUint32 flags = nsLayoutUtils::PAINT_IN_TRANSFORM;
if (SVGAutoRenderState::IsPaintingToWindow(aContext)) { if (SVGAutoRenderState::IsPaintingToWindow(aContext)) {
@ -268,7 +276,7 @@ nsSVGForeignObjectFrame::GetFrameForPoint(const nsPoint &aPoint)
static_cast<nsSVGElement*>(mContent)-> static_cast<nsSVGElement*>(mContent)->
GetAnimatedLengthValues(&x, &y, &width, &height, nsnull); GetAnimatedLengthValues(&x, &y, &width, &height, nsnull);
gfxMatrix tm = GetCanvasTM().Invert(); gfxMatrix tm = GetCanvasTM(FOR_HIT_TESTING).Invert();
if (tm.IsSingular()) if (tm.IsSingular())
return nsnull; return nsnull;
@ -328,7 +336,8 @@ nsSVGForeignObjectFrame::UpdateBounds()
gfxRect(x, y, w, h), gfxRect(x, y, w, h),
PresContext()->AppUnitsPerCSSPixel()); PresContext()->AppUnitsPerCSSPixel());
// GetCanvasTM includes the x,y translation // 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 // Fully mark our kid dirty so that it gets resized if necessary
// (NS_FRAME_HAS_DIRTY_CHILDREN isn't enough in that case): // (NS_FRAME_HAS_DIRTY_CHILDREN isn't enough in that case):
@ -463,8 +472,14 @@ nsSVGForeignObjectFrame::GetBBoxContribution(const gfxMatrix &aToBBoxUserspace,
//---------------------------------------------------------------------- //----------------------------------------------------------------------
gfxMatrix 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) { if (!mCanvasTM) {
NS_ASSERTION(mParent, "null parent"); NS_ASSERTION(mParent, "null parent");
@ -472,7 +487,7 @@ nsSVGForeignObjectFrame::GetCanvasTM()
nsSVGForeignObjectElement *content = nsSVGForeignObjectElement *content =
static_cast<nsSVGForeignObjectElement*>(mContent); static_cast<nsSVGForeignObjectElement*>(mContent);
gfxMatrix tm = content->PrependLocalTransformsTo(parent->GetCanvasTM()); gfxMatrix tm = content->PrependLocalTransformsTo(parent->GetCanvasTM(aFor));
mCanvasTM = new gfxMatrix(tm); mCanvasTM = new gfxMatrix(tm);
} }
@ -482,15 +497,6 @@ nsSVGForeignObjectFrame::GetCanvasTM()
//---------------------------------------------------------------------- //----------------------------------------------------------------------
// Implementation helpers // Implementation helpers
gfxMatrix
nsSVGForeignObjectFrame::GetCanvasTMForChildren()
{
float cssPxPerDevPx = PresContext()->
AppUnitsToFloatCSSPixels(PresContext()->AppUnitsPerDevPixel());
return GetCanvasTM().Scale(cssPxPerDevPx, cssPxPerDevPx);
}
void nsSVGForeignObjectFrame::RequestReflow(nsIPresShell::IntrinsicDirty aType) void nsSVGForeignObjectFrame::RequestReflow(nsIPresShell::IntrinsicDirty aType)
{ {
if (GetStateBits() & NS_FRAME_FIRST_REFLOW) if (GetStateBits() & NS_FRAME_FIRST_REFLOW)
@ -560,7 +566,7 @@ nsSVGForeignObjectFrame::GetInvalidRegion()
if (kid->HasInvalidFrameInSubtree()) { if (kid->HasInvalidFrameInSubtree()) {
gfxRect r(mRect.x, mRect.y, mRect.width, mRect.height); gfxRect r(mRect.x, mRect.y, mRect.width, mRect.height);
r.Scale(1.0 / nsPresContext::AppUnitsPerCSSPixel()); 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); rect = nsSVGUtils::GetPostFilterVisualOverflowRect(this, rect);
return rect; return rect;
} }

Просмотреть файл

@ -80,7 +80,7 @@ public:
PRUint32 aFlags); PRUint32 aFlags);
NS_IMETHOD_(bool) IsDisplayContainer() { return true; } NS_IMETHOD_(bool) IsDisplayContainer() { return true; }
gfxMatrix GetCanvasTM(); gfxMatrix GetCanvasTM(PRUint32 aFor);
nsRect GetInvalidRegion(); nsRect GetInvalidRegion();
@ -89,10 +89,6 @@ protected:
void DoReflow(); void DoReflow();
void RequestReflow(nsIPresShell::IntrinsicDirty aType); 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 // 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; } bool IsDisabled() const { return mRect.width <= 0 || mRect.height <= 0; }

Просмотреть файл

@ -11,6 +11,7 @@
#include "nsIDOMSVGTransformable.h" #include "nsIDOMSVGTransformable.h"
#include "nsIFrame.h" #include "nsIFrame.h"
#include "nsSVGGraphicElement.h" #include "nsSVGGraphicElement.h"
#include "nsSVGIntegrationUtils.h"
#include "nsSVGUtils.h" #include "nsSVGUtils.h"
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@ -66,15 +67,21 @@ nsSVGGFrame::NotifySVGChanged(PRUint32 aFlags)
} }
gfxMatrix 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) { if (!mCanvasTM) {
NS_ASSERTION(mParent, "null parent"); NS_ASSERTION(mParent, "null parent");
nsSVGContainerFrame *parent = static_cast<nsSVGContainerFrame*>(mParent); nsSVGContainerFrame *parent = static_cast<nsSVGContainerFrame*>(mParent);
nsSVGGraphicElement *content = static_cast<nsSVGGraphicElement*>(mContent); nsSVGGraphicElement *content = static_cast<nsSVGGraphicElement*>(mContent);
gfxMatrix tm = content->PrependLocalTransformsTo(parent->GetCanvasTM()); gfxMatrix tm = content->PrependLocalTransformsTo(parent->GetCanvasTM(aFor));
mCanvasTM = new gfxMatrix(tm); mCanvasTM = new gfxMatrix(tm);
} }

Просмотреть файл

@ -51,7 +51,7 @@ public:
virtual void NotifySVGChanged(PRUint32 aFlags); virtual void NotifySVGChanged(PRUint32 aFlags);
// nsSVGContainerFrame methods: // nsSVGContainerFrame methods:
virtual gfxMatrix GetCanvasTM(); virtual gfxMatrix GetCanvasTM(PRUint32 aFor);
nsAutoPtr<gfxMatrix> mCanvasTM; nsAutoPtr<gfxMatrix> mCanvasTM;
}; };

Просмотреть файл

@ -5,6 +5,7 @@
// Main header first: // Main header first:
#include "nsSVGGenericContainerFrame.h" #include "nsSVGGenericContainerFrame.h"
#include "nsSVGIntegrationUtils.h"
//---------------------------------------------------------------------- //----------------------------------------------------------------------
// nsSVGGenericContainerFrame Implementation // nsSVGGenericContainerFrame Implementation
@ -45,9 +46,16 @@ nsSVGGenericContainerFrame::GetType() const
// nsSVGContainerFrame methods: // nsSVGContainerFrame methods:
gfxMatrix 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"); NS_ASSERTION(mParent, "null parent");
return static_cast<nsSVGContainerFrame*>(mParent)->GetCanvasTM(); return static_cast<nsSVGContainerFrame*>(mParent)->GetCanvasTM(aFor);
} }

Просмотреть файл

@ -48,7 +48,7 @@ public:
#endif #endif
// nsSVGContainerFrame methods: // nsSVGContainerFrame methods:
virtual gfxMatrix GetCanvasTM(); virtual gfxMatrix GetCanvasTM(PRUint32 aFor);
}; };
#endif // __NS_SVGGENERICCONTAINERFRAME_H__ #endif // __NS_SVGGENERICCONTAINERFRAME_H__

Просмотреть файл

@ -56,7 +56,7 @@ public:
} }
// nsSVGGeometryFrame methods: // nsSVGGeometryFrame methods:
virtual gfxMatrix GetCanvasTM() = 0; virtual gfxMatrix GetCanvasTM(PRUint32 aFor) = 0;
PRUint16 GetClipRule(); PRUint16 GetClipRule();
float GetStrokeWidth(); float GetStrokeWidth();

Просмотреть файл

@ -17,6 +17,7 @@
#include "nsIDOMSVGRect.h" #include "nsIDOMSVGRect.h"
#include "nsRenderingContext.h" #include "nsRenderingContext.h"
#include "nsSVGEffects.h" #include "nsSVGEffects.h"
#include "nsSVGIntegrationUtils.h"
#include "nsSVGPaintServerFrame.h" #include "nsSVGPaintServerFrame.h"
#include "nsSVGRect.h" #include "nsSVGRect.h"
#include "nsSVGTextPathFrame.h" #include "nsSVGTextPathFrame.h"
@ -309,6 +310,8 @@ nsSVGGlyphFrame::PaintSVG(nsRenderingContext *aContext,
return NS_OK; return NS_OK;
} }
AutoCanvasTMForMarker autoCanvasTMFor(this, FOR_PAINTING);
gfxContext *gfx = aContext->ThebesContext(); gfxContext *gfx = aContext->ThebesContext();
PRUint16 renderMode = SVGAutoRenderState::GetRenderMode(aContext); PRUint16 renderMode = SVGAutoRenderState::GetRenderMode(aContext);
@ -326,7 +329,7 @@ nsSVGGlyphFrame::PaintSVG(nsRenderingContext *aContext,
renderMode == SVGAutoRenderState::CLIP_MASK, renderMode == SVGAutoRenderState::CLIP_MASK,
"Unknown render mode"); "Unknown render mode");
gfxContextMatrixAutoSaveRestore matrixAutoSaveRestore(gfx); gfxContextMatrixAutoSaveRestore matrixAutoSaveRestore(gfx);
SetupGlobalTransform(gfx); SetupGlobalTransform(gfx, FOR_PAINTING);
CharacterIterator iter(this, true); CharacterIterator iter(this, true);
iter.SetInitialMatrix(gfx); iter.SetInitialMatrix(gfx);
@ -349,7 +352,7 @@ nsSVGGlyphFrame::PaintSVG(nsRenderingContext *aContext,
// We are adding patterns or gradients to the context. Save // We are adding patterns or gradients to the context. Save
// it so we don't leak them into the next object we draw // it so we don't leak them into the next object we draw
gfx->Save(); gfx->Save();
SetupGlobalTransform(gfx); SetupGlobalTransform(gfx, FOR_PAINTING);
CharacterIterator iter(this, true); CharacterIterator iter(this, true);
iter.SetInitialMatrix(gfx); iter.SetInitialMatrix(gfx);
@ -374,8 +377,10 @@ nsSVGGlyphFrame::GetFrameForPoint(const nsPoint &aPoint)
return nsnull; return nsnull;
} }
AutoCanvasTMForMarker autoCanvasTMFor(this, FOR_HIT_TESTING);
nsRefPtr<gfxContext> tmpCtx = MakeTmpCtx(); nsRefPtr<gfxContext> tmpCtx = MakeTmpCtx();
SetupGlobalTransform(tmpCtx); SetupGlobalTransform(tmpCtx, FOR_HIT_TESTING);
CharacterIterator iter(this, true); CharacterIterator iter(this, true);
iter.SetInitialMatrix(tmpCtx); iter.SetInitialMatrix(tmpCtx);
@ -483,7 +488,7 @@ nsSVGGlyphFrame::UpdateBounds()
// See bug 614732 comment 32. // See bug 614732 comment 32.
mCoveredRegion = nsSVGUtils::TransformFrameRectToOuterSVG( mCoveredRegion = nsSVGUtils::TransformFrameRectToOuterSVG(
mRect, GetCanvasTM(), PresContext()); mRect, GetCanvasTM(FOR_OUTERSVG_TM), PresContext());
nsRect overflow = nsRect(nsPoint(0,0), mRect.Size()); nsRect overflow = nsRect(nsPoint(0,0), mRect.Size());
nsOverflowAreas overflowAreas(overflow, overflow); nsOverflowAreas overflowAreas(overflow, overflow);
@ -582,7 +587,7 @@ nsSVGGlyphFrame::GetBBoxContribution(const gfxMatrix &aToBBoxUserspace,
} }
nsRefPtr<gfxContext> tmpCtx = MakeTmpCtx(); nsRefPtr<gfxContext> tmpCtx = MakeTmpCtx();
SetupGlobalTransform(tmpCtx); SetupGlobalTransform(tmpCtx, FOR_OUTERSVG_TM);
CharacterIterator iter(this, true); CharacterIterator iter(this, true);
iter.SetInitialMatrix(tmpCtx); iter.SetInitialMatrix(tmpCtx);
AddBoundingBoxesToPath(&iter, tmpCtx); AddBoundingBoxesToPath(&iter, tmpCtx);
@ -617,13 +622,19 @@ nsSVGGlyphFrame::GetBBoxContribution(const gfxMatrix &aToBBoxUserspace,
// nsSVGGeometryFrame methods: // nsSVGGeometryFrame methods:
gfxMatrix gfxMatrix
nsSVGGlyphFrame::GetCanvasTM() nsSVGGlyphFrame::GetCanvasTM(PRUint32 aFor)
{ {
if (mOverrideCanvasTM) { if (mOverrideCanvasTM) {
return *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"); NS_ASSERTION(mParent, "null parent");
return static_cast<nsSVGContainerFrame*>(mParent)->GetCanvasTM(); return static_cast<nsSVGContainerFrame*>(mParent)->GetCanvasTM(aFor);
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@ -1478,9 +1489,9 @@ nsSVGGlyphFrame::NotifyGlyphMetricsChange()
} }
void void
nsSVGGlyphFrame::SetupGlobalTransform(gfxContext *aContext) nsSVGGlyphFrame::SetupGlobalTransform(gfxContext *aContext, PRUint32 aFor)
{ {
gfxMatrix matrix = GetCanvasTM(); gfxMatrix matrix = GetCanvasTM(aFor);
if (!matrix.IsSingular()) { if (!matrix.IsSingular()) {
aContext->Multiply(matrix); aContext->Multiply(matrix);
} }
@ -1559,7 +1570,7 @@ nsSVGGlyphFrame::EnsureTextRun(float *aDrawScale, float *aMetricsScale,
gfxMatrix m; gfxMatrix m;
if (aForceGlobalTransform || if (aForceGlobalTransform ||
!(GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD)) { !(GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD)) {
m = GetCanvasTM(); m = GetCanvasTM(mGetCanvasTMForFlag);
if (m.IsSingular()) if (m.IsSingular())
return false; return false;
} }

Просмотреть файл

@ -31,6 +31,9 @@ class nsSVGGlyphFrame : public nsSVGGlyphFrameBase,
public nsISVGGlyphFragmentNode, public nsISVGGlyphFragmentNode,
public nsISVGChildFrame public nsISVGChildFrame
{ {
class AutoCanvasTMForMarker;
friend class AutoCanvasTMForMarker;
friend class CharacterIterator;
friend nsIFrame* friend nsIFrame*
NS_NewSVGGlyphFrame(nsIPresShell* aPresShell, nsStyleContext* aContext); NS_NewSVGGlyphFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
protected: protected:
@ -38,6 +41,7 @@ protected:
: nsSVGGlyphFrameBase(aContext), : nsSVGGlyphFrameBase(aContext),
mTextRun(nsnull), mTextRun(nsnull),
mStartIndex(0), mStartIndex(0),
mGetCanvasTMForFlag(nsISVGChildFrame::FOR_OUTERSVG_TM),
mCompressWhitespace(true), mCompressWhitespace(true),
mTrimLeadingWhitespace(false), mTrimLeadingWhitespace(false),
mTrimTrailingWhitespace(false) mTrimTrailingWhitespace(false)
@ -154,7 +158,7 @@ public:
NS_IMETHOD_(bool) IsDisplayContainer() { return false; } NS_IMETHOD_(bool) IsDisplayContainer() { return false; }
// nsSVGGeometryFrame methods // nsSVGGeometryFrame methods
gfxMatrix GetCanvasTM(); gfxMatrix GetCanvasTM(PRUint32 aFor);
// nsISVGGlyphFragmentNode interface: // nsISVGGlyphFragmentNode interface:
// These do not use the global transform if NS_STATE_NONDISPLAY_CHILD // These do not use the global transform if NS_STATE_NONDISPLAY_CHILD
@ -171,8 +175,30 @@ public:
} }
} }
protected: private:
friend class CharacterIterator;
/**
* 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 // Use a power of 2 here. It's not so important to match
// nsDeviceContext::AppUnitsPerDevPixel, but since we do a lot of // nsDeviceContext::AppUnitsPerDevPixel, but since we do a lot of
@ -208,7 +234,7 @@ protected:
gfxPattern *aStrokePattern = nsnull); gfxPattern *aStrokePattern = nsnull);
void NotifyGlyphMetricsChange(); void NotifyGlyphMetricsChange();
void SetupGlobalTransform(gfxContext *aContext); void SetupGlobalTransform(gfxContext *aContext, PRUint32 aFor);
nsresult GetHighlight(PRUint32 *charnum, PRUint32 *nchars, nsresult GetHighlight(PRUint32 *charnum, PRUint32 *nchars,
nscolor *foreground, nscolor *background); nscolor *foreground, nscolor *background);
float GetSubStringAdvance(PRUint32 charnum, PRUint32 fragmentChars, float GetSubStringAdvance(PRUint32 charnum, PRUint32 fragmentChars,
@ -227,6 +253,7 @@ protected:
gfxPoint mPosition; gfxPoint mPosition;
// The start index into the position and rotation data // The start index into the position and rotation data
PRUint32 mStartIndex; PRUint32 mStartIndex;
PRUint32 mGetCanvasTMForFlag;
bool mCompressWhitespace; bool mCompressWhitespace;
bool mTrimLeadingWhitespace; bool mTrimLeadingWhitespace;
bool mTrimTrailingWhitespace; bool mTrimTrailingWhitespace;

Просмотреть файл

@ -92,8 +92,9 @@ public:
private: private:
gfxMatrix GetRasterImageTransform(PRInt32 aNativeWidth, gfxMatrix GetRasterImageTransform(PRInt32 aNativeWidth,
PRInt32 aNativeHeight); PRInt32 aNativeHeight,
gfxMatrix GetVectorImageTransform(); PRUint32 aFor);
gfxMatrix GetVectorImageTransform(PRUint32 aFor);
bool TransformContextForPainting(gfxContext* aGfxContext); bool TransformContextForPainting(gfxContext* aGfxContext);
nsCOMPtr<imgIDecoderObserver> mListener; nsCOMPtr<imgIDecoderObserver> mListener;
@ -221,7 +222,9 @@ nsSVGImageFrame::AttributeChanged(PRInt32 aNameSpaceID,
} }
gfxMatrix gfxMatrix
nsSVGImageFrame::GetRasterImageTransform(PRInt32 aNativeWidth, PRInt32 aNativeHeight) nsSVGImageFrame::GetRasterImageTransform(PRInt32 aNativeWidth,
PRInt32 aNativeHeight,
PRUint32 aFor)
{ {
float x, y, width, height; float x, y, width, height;
nsSVGImageElement *element = static_cast<nsSVGImageElement*>(mContent); nsSVGImageElement *element = static_cast<nsSVGImageElement*>(mContent);
@ -233,11 +236,11 @@ nsSVGImageFrame::GetRasterImageTransform(PRInt32 aNativeWidth, PRInt32 aNativeHe
0, 0, aNativeWidth, aNativeHeight, 0, 0, aNativeWidth, aNativeHeight,
element->mPreserveAspectRatio); element->mPreserveAspectRatio);
return viewBoxTM * gfxMatrix().Translate(gfxPoint(x, y)) * GetCanvasTM(); return viewBoxTM * gfxMatrix().Translate(gfxPoint(x, y)) * GetCanvasTM(aFor);
} }
gfxMatrix gfxMatrix
nsSVGImageFrame::GetVectorImageTransform() nsSVGImageFrame::GetVectorImageTransform(PRUint32 aFor)
{ {
float x, y, width, height; float x, y, width, height;
nsSVGImageElement *element = static_cast<nsSVGImageElement*>(mContent); nsSVGImageElement *element = static_cast<nsSVGImageElement*>(mContent);
@ -247,7 +250,7 @@ nsSVGImageFrame::GetVectorImageTransform()
// "native size" that the SVG image has, and it will handle viewBox and // "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. // 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 bool
@ -255,7 +258,7 @@ nsSVGImageFrame::TransformContextForPainting(gfxContext* aGfxContext)
{ {
gfxMatrix imageTransform; gfxMatrix imageTransform;
if (mImageContainer->GetType() == imgIContainer::TYPE_VECTOR) { if (mImageContainer->GetType() == imgIContainer::TYPE_VECTOR) {
imageTransform = GetVectorImageTransform(); imageTransform = GetVectorImageTransform(FOR_PAINTING);
} else { } else {
PRInt32 nativeWidth, nativeHeight; PRInt32 nativeWidth, nativeHeight;
if (NS_FAILED(mImageContainer->GetWidth(&nativeWidth)) || if (NS_FAILED(mImageContainer->GetWidth(&nativeWidth)) ||
@ -263,7 +266,8 @@ nsSVGImageFrame::TransformContextForPainting(gfxContext* aGfxContext)
nativeWidth == 0 || nativeHeight == 0) { nativeWidth == 0 || nativeHeight == 0) {
return false; return false;
} }
imageTransform = GetRasterImageTransform(nativeWidth, nativeHeight); imageTransform =
GetRasterImageTransform(nativeWidth, nativeHeight, FOR_PAINTING);
} }
if (imageTransform.IsSingular()) { if (imageTransform.IsSingular()) {
@ -315,7 +319,7 @@ nsSVGImageFrame::PaintSVG(nsRenderingContext *aContext,
if (GetStyleDisplay()->IsScrollableOverflow()) { if (GetStyleDisplay()->IsScrollableOverflow()) {
gfxRect clipRect = nsSVGUtils::GetClipRectForFrame(this, x, y, gfxRect clipRect = nsSVGUtils::GetClipRectForFrame(this, x, y,
width, height); width, height);
nsSVGUtils::SetClipRect(ctx, GetCanvasTM(), clipRect); nsSVGUtils::SetClipRect(ctx, GetCanvasTM(FOR_PAINTING), clipRect);
} }
if (!TransformContextForPainting(ctx)) { if (!TransformContextForPainting(ctx)) {
@ -340,7 +344,8 @@ nsSVGImageFrame::PaintSVG(nsRenderingContext *aContext,
dirtyRect = aDirtyRect->ToAppUnits(appUnitsPerDevPx); dirtyRect = aDirtyRect->ToAppUnits(appUnitsPerDevPx);
// Adjust dirtyRect to match our local coordinate system. // Adjust dirtyRect to match our local coordinate system.
nsRect rootRect = nsRect rootRect =
nsSVGUtils::TransformFrameRectToOuterSVG(mRect, GetCanvasTM(), PresContext()); nsSVGUtils::TransformFrameRectToOuterSVG(mRect,
GetCanvasTM(FOR_PAINTING), PresContext());
dirtyRect.MoveBy(-rootRect.TopLeft()); dirtyRect.MoveBy(-rootRect.TopLeft());
} }
@ -425,7 +430,8 @@ nsSVGImageFrame::GetFrameForPoint(const nsPoint &aPoint)
} }
if (!nsSVGUtils::HitTestRect( if (!nsSVGUtils::HitTestRect(
GetRasterImageTransform(nativeWidth, nativeHeight), GetRasterImageTransform(nativeWidth, nativeHeight,
FOR_HIT_TESTING),
0, 0, nativeWidth, nativeHeight, 0, 0, nativeWidth, nativeHeight,
PresContext()->AppUnitsToDevPixels(aPoint.x), PresContext()->AppUnitsToDevPixels(aPoint.x),
PresContext()->AppUnitsToDevPixels(aPoint.y))) { PresContext()->AppUnitsToDevPixels(aPoint.y))) {
@ -481,7 +487,7 @@ nsSVGImageFrame::UpdateBounds()
// See bug 614732 comment 32. // See bug 614732 comment 32.
mCoveredRegion = nsSVGUtils::TransformFrameRectToOuterSVG( mCoveredRegion = nsSVGUtils::TransformFrameRectToOuterSVG(
mRect, GetCanvasTM(), PresContext()); mRect, GetCanvasTM(FOR_OUTERSVG_TM), PresContext());
if (mState & NS_FRAME_FIRST_REFLOW) { if (mState & NS_FRAME_FIRST_REFLOW) {
// Make sure we have our filter property (if any) before calling // Make sure we have our filter property (if any) before calling

Просмотреть файл

@ -12,6 +12,7 @@
#include "nsISVGChildFrame.h" #include "nsISVGChildFrame.h"
#include "nsRenderingContext.h" #include "nsRenderingContext.h"
#include "nsSVGContainerFrame.h" #include "nsSVGContainerFrame.h"
#include "nsSVGIntegrationUtils.h"
#include "nsSVGSVGElement.h" #include "nsSVGSVGElement.h"
nsIFrame* nsIFrame*
@ -68,7 +69,7 @@ nsSVGInnerSVGFrame::PaintSVG(nsRenderingContext *aContext,
} }
nsSVGContainerFrame *parent = static_cast<nsSVGContainerFrame*>(mParent); nsSVGContainerFrame *parent = static_cast<nsSVGContainerFrame*>(mParent);
gfxMatrix clipTransform = parent->GetCanvasTM(); gfxMatrix clipTransform = parent->GetCanvasTM(FOR_PAINTING);
gfxContext *gfx = aContext->ThebesContext(); gfxContext *gfx = aContext->ThebesContext();
autoSR.SetContext(gfx); autoSR.SetContext(gfx);
@ -217,7 +218,7 @@ nsSVGInnerSVGFrame::GetFrameForPoint(const nsPoint &aPoint)
float clipX, clipY, clipWidth, clipHeight; float clipX, clipY, clipWidth, clipHeight;
content->GetAnimatedLengthValues(&clipX, &clipY, &clipWidth, &clipHeight, nsnull); content->GetAnimatedLengthValues(&clipX, &clipY, &clipWidth, &clipHeight, nsnull);
if (!nsSVGUtils::HitTestRect(parent->GetCanvasTM(), if (!nsSVGUtils::HitTestRect(parent->GetCanvasTM(FOR_HIT_TESTING),
clipX, clipY, clipWidth, clipHeight, clipX, clipY, clipWidth, clipHeight,
PresContext()->AppUnitsToDevPixels(aPoint.x), PresContext()->AppUnitsToDevPixels(aPoint.x),
PresContext()->AppUnitsToDevPixels(aPoint.y))) { PresContext()->AppUnitsToDevPixels(aPoint.y))) {
@ -246,15 +247,21 @@ nsSVGInnerSVGFrame::NotifyViewportOrTransformChanged(PRUint32 aFlags)
// nsSVGContainerFrame methods: // nsSVGContainerFrame methods:
gfxMatrix 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) { if (!mCanvasTM) {
NS_ASSERTION(mParent, "null parent"); NS_ASSERTION(mParent, "null parent");
nsSVGContainerFrame *parent = static_cast<nsSVGContainerFrame*>(mParent); nsSVGContainerFrame *parent = static_cast<nsSVGContainerFrame*>(mParent);
nsSVGSVGElement *content = static_cast<nsSVGSVGElement*>(mContent); nsSVGSVGElement *content = static_cast<nsSVGSVGElement*>(mContent);
gfxMatrix tm = content->PrependLocalTransformsTo(parent->GetCanvasTM()); gfxMatrix tm = content->PrependLocalTransformsTo(parent->GetCanvasTM(aFor));
mCanvasTM = new gfxMatrix(tm); mCanvasTM = new gfxMatrix(tm);
} }

Просмотреть файл

@ -56,7 +56,7 @@ public:
NS_IMETHOD_(nsIFrame*) GetFrameForPoint(const nsPoint &aPoint); NS_IMETHOD_(nsIFrame*) GetFrameForPoint(const nsPoint &aPoint);
// nsSVGContainerFrame methods: // nsSVGContainerFrame methods:
virtual gfxMatrix GetCanvasTM(); virtual gfxMatrix GetCanvasTM(PRUint32 aFor);
virtual bool HasChildrenOnlyTransform(gfxMatrix *aTransform) const; virtual bool HasChildrenOnlyTransform(gfxMatrix *aTransform) const;

Просмотреть файл

@ -69,7 +69,7 @@ nsSVGMarkerFrame::GetType() const
// nsSVGContainerFrame methods: // nsSVGContainerFrame methods:
gfxMatrix gfxMatrix
nsSVGMarkerFrame::GetCanvasTM() nsSVGMarkerFrame::GetCanvasTM(PRUint32 aFor)
{ {
NS_ASSERTION(mMarkedFrame, "null nsSVGPathGeometry frame"); NS_ASSERTION(mMarkedFrame, "null nsSVGPathGeometry frame");
@ -81,7 +81,7 @@ nsSVGMarkerFrame::GetCanvasTM()
nsSVGMarkerElement *content = static_cast<nsSVGMarkerElement*>(mContent); nsSVGMarkerElement *content = static_cast<nsSVGMarkerElement*>(mContent);
mInUse2 = true; mInUse2 = true;
gfxMatrix markedTM = mMarkedFrame->GetCanvasTM(); gfxMatrix markedTM = mMarkedFrame->GetCanvasTM(aFor);
mInUse2 = false; mInUse2 = false;
gfxMatrix markerTM = content->GetMarkerTransform(mStrokeWidth, mX, mY, mAutoAngle); gfxMatrix markerTM = content->GetMarkerTransform(mStrokeWidth, mX, mY, mAutoAngle);
@ -125,7 +125,8 @@ nsSVGMarkerFrame::PaintMark(nsRenderingContext *aContext,
gfxRect clipRect = gfxRect clipRect =
nsSVGUtils::GetClipRectForFrame(this, viewBox.x, viewBox.y, nsSVGUtils::GetClipRectForFrame(this, viewBox.x, viewBox.y,
viewBox.width, viewBox.height); viewBox.width, viewBox.height);
nsSVGUtils::SetClipRect(gfx, GetCanvasTM(), clipRect); nsSVGUtils::SetClipRect(gfx, GetCanvasTM(nsISVGChildFrame::FOR_PAINTING),
clipRect);
} }
for (nsIFrame* kid = mFrames.FirstChild(); kid; for (nsIFrame* kid = mFrames.FirstChild(); kid;

Просмотреть файл

@ -86,7 +86,7 @@ private:
float mStrokeWidth, mX, mY, mAutoAngle; float mStrokeWidth, mX, mY, mAutoAngle;
// nsSVGContainerFrame methods: // nsSVGContainerFrame methods:
virtual gfxMatrix GetCanvasTM(); virtual gfxMatrix GetCanvasTM(PRUint32 aFor);
// A helper class to allow us to paint markers safely. The helper // A helper class to allow us to paint markers safely. The helper
// automatically sets and clears the mInUse flag on the marker frame (to // automatically sets and clears the mInUse flag on the marker frame (to

Просмотреть файл

@ -188,7 +188,7 @@ nsSVGMaskFrame::GetType() const
} }
gfxMatrix gfxMatrix
nsSVGMaskFrame::GetCanvasTM() nsSVGMaskFrame::GetCanvasTM(PRUint32 aFor)
{ {
NS_ASSERTION(mMaskParentMatrix, "null parent matrix"); NS_ASSERTION(mMaskParentMatrix, "null parent matrix");

Просмотреть файл

@ -89,7 +89,7 @@ private:
bool mInUse; bool mInUse;
// nsSVGContainerFrame methods: // nsSVGContainerFrame methods:
virtual gfxMatrix GetCanvasTM(); virtual gfxMatrix GetCanvasTM(PRUint32 aFor);
}; };
#endif #endif

Просмотреть файл

@ -18,6 +18,7 @@
#include "nsRenderingContext.h" #include "nsRenderingContext.h"
#include "nsStubMutationObserver.h" #include "nsStubMutationObserver.h"
#include "nsSVGForeignObjectFrame.h" #include "nsSVGForeignObjectFrame.h"
#include "nsSVGIntegrationUtils.h"
#include "nsSVGSVGElement.h" #include "nsSVGSVGElement.h"
#include "nsSVGTextFrame.h" #include "nsSVGTextFrame.h"
#include "nsSubDocumentFrame.h" #include "nsSubDocumentFrame.h"
@ -790,8 +791,14 @@ nsSVGOuterSVGFrame::NotifyViewportOrTransformChanged(PRUint32 aFlags)
// nsSVGContainerFrame methods: // nsSVGContainerFrame methods:
gfxMatrix 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) { if (!mCanvasTM) {
nsSVGSVGElement *content = static_cast<nsSVGSVGElement*>(mContent); nsSVGSVGElement *content = static_cast<nsSVGSVGElement*>(mContent);

Просмотреть файл

@ -100,7 +100,7 @@ public:
virtual void NotifyViewportOrTransformChanged(PRUint32 aFlags); virtual void NotifyViewportOrTransformChanged(PRUint32 aFlags);
// nsSVGContainerFrame methods: // nsSVGContainerFrame methods:
virtual gfxMatrix GetCanvasTM(); virtual gfxMatrix GetCanvasTM(PRUint32 aFor);
/* Methods to allow descendant nsSVGForeignObjectFrame frames to register and /* Methods to allow descendant nsSVGForeignObjectFrame frames to register and
* unregister themselves with their nearest nsSVGOuterSVGFrame ancestor. This * unregister themselves with their nearest nsSVGOuterSVGFrame ancestor. This

Просмотреть файл

@ -13,6 +13,7 @@
#include "nsRenderingContext.h" #include "nsRenderingContext.h"
#include "nsSVGEffects.h" #include "nsSVGEffects.h"
#include "nsSVGGraphicElement.h" #include "nsSVGGraphicElement.h"
#include "nsSVGIntegrationUtils.h"
#include "nsSVGMarkerFrame.h" #include "nsSVGMarkerFrame.h"
#include "nsSVGPathGeometryElement.h" #include "nsSVGPathGeometryElement.h"
#include "nsSVGUtils.h" #include "nsSVGUtils.h"
@ -151,6 +152,7 @@ nsSVGPathGeometryFrame::PaintSVG(nsRenderingContext *aContext,
NS_IMETHODIMP_(nsIFrame*) NS_IMETHODIMP_(nsIFrame*)
nsSVGPathGeometryFrame::GetFrameForPoint(const nsPoint &aPoint) nsSVGPathGeometryFrame::GetFrameForPoint(const nsPoint &aPoint)
{ {
gfxMatrix canvasTM = GetCanvasTM(FOR_HIT_TESTING);
PRUint16 fillRule, hitTestFlags; PRUint16 fillRule, hitTestFlags;
if (GetStateBits() & NS_STATE_SVG_CLIPPATH_CHILD) { if (GetStateBits() & NS_STATE_SVG_CLIPPATH_CHILD) {
hitTestFlags = SVG_HIT_TEST_FILL; hitTestFlags = SVG_HIT_TEST_FILL;
@ -159,7 +161,6 @@ nsSVGPathGeometryFrame::GetFrameForPoint(const nsPoint &aPoint)
hitTestFlags = GetHitTestFlags(); hitTestFlags = GetHitTestFlags();
// XXX once bug 614732 is fixed, aPoint won't need any conversion in order // XXX once bug 614732 is fixed, aPoint won't need any conversion in order
// to compare it with mRect. // to compare it with mRect.
gfxMatrix canvasTM = GetCanvasTM();
if (canvasTM.IsSingular()) { if (canvasTM.IsSingular()) {
return nsnull; return nsnull;
} }
@ -176,7 +177,7 @@ nsSVGPathGeometryFrame::GetFrameForPoint(const nsPoint &aPoint)
nsRefPtr<gfxContext> tmpCtx = nsRefPtr<gfxContext> tmpCtx =
new gfxContext(gfxPlatform::GetPlatform()->ScreenReferenceSurface()); new gfxContext(gfxPlatform::GetPlatform()->ScreenReferenceSurface());
GeneratePath(tmpCtx, GetCanvasTM()); GeneratePath(tmpCtx, canvasTM);
gfxPoint userSpacePoint = gfxPoint userSpacePoint =
tmpCtx->DeviceToUser(gfxPoint(PresContext()->AppUnitsToGfxUnits(aPoint.x), tmpCtx->DeviceToUser(gfxPoint(PresContext()->AppUnitsToGfxUnits(aPoint.x),
PresContext()->AppUnitsToGfxUnits(aPoint.y))); PresContext()->AppUnitsToGfxUnits(aPoint.y)));
@ -229,7 +230,7 @@ nsSVGPathGeometryFrame::UpdateBounds()
// See bug 614732 comment 32. // See bug 614732 comment 32.
mCoveredRegion = nsSVGUtils::TransformFrameRectToOuterSVG( mCoveredRegion = nsSVGUtils::TransformFrameRectToOuterSVG(
mRect, GetCanvasTM(), PresContext()); mRect, GetCanvasTM(FOR_OUTERSVG_TM), PresContext());
if (mState & NS_FRAME_FIRST_REFLOW) { if (mState & NS_FRAME_FIRST_REFLOW) {
// Make sure we have our filter property (if any) before calling // Make sure we have our filter property (if any) before calling
@ -382,14 +383,21 @@ nsSVGPathGeometryFrame::GetBBoxContribution(const gfxMatrix &aToBBoxUserspace,
// nsSVGGeometryFrame methods: // nsSVGGeometryFrame methods:
gfxMatrix 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"); NS_ASSERTION(mParent, "null parent");
nsSVGContainerFrame *parent = static_cast<nsSVGContainerFrame*>(mParent); nsSVGContainerFrame *parent = static_cast<nsSVGContainerFrame*>(mParent);
nsSVGGraphicElement *content = static_cast<nsSVGGraphicElement*>(mContent); nsSVGGraphicElement *content = static_cast<nsSVGGraphicElement*>(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 */ /* save/restore the state so we don't screw up the xform */
gfx->Save(); gfx->Save();
GeneratePath(gfx, GetCanvasTM()); GeneratePath(gfx, GetCanvasTM(FOR_PAINTING));
if (renderMode != SVGAutoRenderState::NORMAL) { if (renderMode != SVGAutoRenderState::NORMAL) {
NS_ABORT_IF_FALSE(renderMode == SVGAutoRenderState::CLIP || NS_ABORT_IF_FALSE(renderMode == SVGAutoRenderState::CLIP ||

Просмотреть файл

@ -70,7 +70,7 @@ public:
#endif #endif
// nsSVGGeometryFrame methods // nsSVGGeometryFrame methods
gfxMatrix GetCanvasTM(); gfxMatrix GetCanvasTM(PRUint32 aFor);
protected: protected:
// nsISVGChildFrame interface: // nsISVGChildFrame interface:

Просмотреть файл

@ -125,7 +125,7 @@ nsSVGPatternFrame::GetType() const
// matrix, which depends on our units parameters // matrix, which depends on our units parameters
// and X, Y, Width, and Height // and X, Y, Width, and Height
gfxMatrix gfxMatrix
nsSVGPatternFrame::GetCanvasTM() nsSVGPatternFrame::GetCanvasTM(PRUint32 aFor)
{ {
if (mCTM) { if (mCTM) {
return *mCTM; return *mCTM;
@ -134,7 +134,7 @@ nsSVGPatternFrame::GetCanvasTM()
// Do we know our rendering parent? // Do we know our rendering parent?
if (mSource) { if (mSource) {
// Yes, use it! // Yes, use it!
return mSource->GetCanvasTM(); return mSource->GetCanvasTM(aFor);
} }
// We get here when geometry in the <pattern> container is updated // We get here when geometry in the <pattern> container is updated
@ -637,7 +637,7 @@ nsSVGPatternFrame::GetTargetGeometry(gfxMatrix *aCTM,
} }
// Get the transformation matrix from our calling geometry // 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 // OK, now fix up the bounding box to reflect user coordinates
// We handle device unit scaling in pattern matrix // We handle device unit scaling in pattern matrix

Просмотреть файл

@ -48,7 +48,7 @@ public:
typedef mozilla::SVGAnimatedPreserveAspectRatio SVGAnimatedPreserveAspectRatio; typedef mozilla::SVGAnimatedPreserveAspectRatio SVGAnimatedPreserveAspectRatio;
// nsSVGContainerFrame methods: // nsSVGContainerFrame methods:
virtual gfxMatrix GetCanvasTM(); virtual gfxMatrix GetCanvasTM(PRUint32 aFor);
// nsIFrame interface: // nsIFrame interface:
virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext); virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext);

Просмотреть файл

@ -9,6 +9,7 @@
// Keep others in (case-insensitive) order: // Keep others in (case-insensitive) order:
#include "nsIDOMSVGTSpanElement.h" #include "nsIDOMSVGTSpanElement.h"
#include "nsIDOMSVGAltGlyphElement.h" #include "nsIDOMSVGAltGlyphElement.h"
#include "nsSVGIntegrationUtils.h"
#include "nsSVGUtils.h" #include "nsSVGUtils.h"
//---------------------------------------------------------------------- //----------------------------------------------------------------------
@ -90,10 +91,16 @@ nsSVGTSpanFrame::AttributeChanged(PRInt32 aNameSpaceID,
// nsSVGContainerFrame methods: // nsSVGContainerFrame methods:
gfxMatrix 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"); NS_ASSERTION(mParent, "null parent");
return static_cast<nsSVGContainerFrame*>(mParent)->GetCanvasTM(); return static_cast<nsSVGContainerFrame*>(mParent)->GetCanvasTM(aFor);
} }
//---------------------------------------------------------------------- //----------------------------------------------------------------------

Просмотреть файл

@ -61,7 +61,7 @@ public:
} }
#endif #endif
// nsSVGContainerFrame methods: // nsSVGContainerFrame methods:
virtual gfxMatrix GetCanvasTM(); virtual gfxMatrix GetCanvasTM(PRUint32 aFor);
// nsISVGGlyphFragmentNode interface: // nsISVGGlyphFragmentNode interface:
virtual PRUint32 GetNumberOfChars(); virtual PRUint32 GetNumberOfChars();

Просмотреть файл

@ -13,6 +13,7 @@
#include "nsISVGGlyphFragmentNode.h" #include "nsISVGGlyphFragmentNode.h"
#include "nsSVGGlyphFrame.h" #include "nsSVGGlyphFrame.h"
#include "nsSVGGraphicElement.h" #include "nsSVGGraphicElement.h"
#include "nsSVGIntegrationUtils.h"
#include "nsSVGPathElement.h" #include "nsSVGPathElement.h"
#include "nsSVGTextPathFrame.h" #include "nsSVGTextPathFrame.h"
#include "nsSVGUtils.h" #include "nsSVGUtils.h"
@ -256,15 +257,23 @@ nsSVGTextFrame::GetBBoxContribution(const gfxMatrix &aToBBoxUserspace,
// nsSVGContainerFrame methods: // nsSVGContainerFrame methods:
gfxMatrix 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) { if (!mCanvasTM) {
NS_ASSERTION(mParent, "null parent"); NS_ASSERTION(mParent, "null parent");
nsSVGContainerFrame *parent = static_cast<nsSVGContainerFrame*>(mParent); nsSVGContainerFrame *parent = static_cast<nsSVGContainerFrame*>(mParent);
nsSVGGraphicElement *content = static_cast<nsSVGGraphicElement*>(mContent); nsSVGGraphicElement *content = static_cast<nsSVGGraphicElement*>(mContent);
gfxMatrix tm = content->PrependLocalTransformsTo(parent->GetCanvasTM()); gfxMatrix tm =
content->PrependLocalTransformsTo(parent->GetCanvasTM(aFor));
mCanvasTM = new gfxMatrix(tm); mCanvasTM = new gfxMatrix(tm);
} }

Просмотреть файл

@ -63,7 +63,7 @@ public:
PRUint32 aFlags); PRUint32 aFlags);
// nsSVGContainerFrame methods: // nsSVGContainerFrame methods:
virtual gfxMatrix GetCanvasTM(); virtual gfxMatrix GetCanvasTM(PRUint32 aFor);
// nsSVGTextContainerFrame methods: // nsSVGTextContainerFrame methods:
virtual PRUint32 GetNumberOfChars(); virtual PRUint32 GetNumberOfChars();

Просмотреть файл

@ -1013,7 +1013,7 @@ nsSVGUtils::GetViewBoxTransform(const nsSVGElement* aElement,
} }
gfxMatrix gfxMatrix
nsSVGUtils::GetCanvasTM(nsIFrame *aFrame) nsSVGUtils::GetCanvasTM(nsIFrame *aFrame, PRUint32 aFor)
{ {
// XXX yuck, we really need a common interface for GetCanvasTM // XXX yuck, we really need a common interface for GetCanvasTM
@ -1021,30 +1021,43 @@ nsSVGUtils::GetCanvasTM(nsIFrame *aFrame)
return nsSVGIntegrationUtils::GetCSSPxToDevPxMatrix(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(); nsIAtom* type = aFrame->GetType();
if (type == nsGkAtoms::svgForeignObjectFrame) { if (type == nsGkAtoms::svgForeignObjectFrame) {
return static_cast<nsSVGForeignObjectFrame*>(aFrame)->GetCanvasTM(); return static_cast<nsSVGForeignObjectFrame*>(aFrame)->GetCanvasTM(aFor);
} }
nsSVGContainerFrame *containerFrame = do_QueryFrame(aFrame); nsSVGContainerFrame *containerFrame = do_QueryFrame(aFrame);
if (containerFrame) { if (containerFrame) {
return containerFrame->GetCanvasTM(); return containerFrame->GetCanvasTM(aFor);
} }
return static_cast<nsSVGGeometryFrame*>(aFrame)->GetCanvasTM(); return static_cast<nsSVGGeometryFrame*>(aFrame)->GetCanvasTM(aFor);
} }
gfxMatrix 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); nsISVGChildFrame* svgFrame = do_QueryFrame(aFrame);
NS_ASSERTION(svgFrame, "bad frame"); NS_ASSERTION(svgFrame, "bad frame");
gfxMatrix tm; gfxMatrix tm;
if (svgFrame) { if (svgFrame) {
nsSVGElement *content = static_cast<nsSVGElement*>(aFrame->GetContent()); nsSVGElement *content = static_cast<nsSVGElement*>(aFrame->GetContent());
tm = content->PrependLocalTransformsTo(GetCanvasTM(aFrame->GetParent()), tm = content->PrependLocalTransformsTo(
nsSVGElement::eUserSpaceToParent); GetCanvasTM(aFrame->GetParent(), aFor),
nsSVGElement::eUserSpaceToParent);
} }
return tm; return tm;
} }
@ -1085,7 +1098,8 @@ public:
// aDirtyRect is in user-space pixels, we need to convert to // aDirtyRect is in user-space pixels, we need to convert to
// outer-SVG-frame-relative device pixels. // outer-SVG-frame-relative device pixels.
if (aDirtyRect) { if (aDirtyRect) {
gfxMatrix userToDeviceSpace = nsSVGUtils::GetCanvasTM(aTarget); gfxMatrix userToDeviceSpace =
nsSVGUtils::GetCanvasTM(aTarget, nsISVGChildFrame::FOR_PAINTING);
if (userToDeviceSpace.IsSingular()) { if (userToDeviceSpace.IsSingular()) {
return; return;
} }
@ -1142,7 +1156,7 @@ nsSVGUtils::PaintFrameWithEffects(nsRenderingContext *aContext,
overflowRect = overflowRect + aFrame->GetPosition(); overflowRect = overflowRect + aFrame->GetPosition();
} }
PRUint32 appUnitsPerDevPx = aFrame->PresContext()->AppUnitsPerDevPixel(); PRUint32 appUnitsPerDevPx = aFrame->PresContext()->AppUnitsPerDevPixel();
gfxMatrix tm = GetCanvasTM(aFrame); gfxMatrix tm = GetCanvasTM(aFrame, nsISVGChildFrame::FOR_PAINTING);
if (aFrame->IsFrameOfType(nsIFrame::eSVG | nsIFrame::eSVGContainer)) { if (aFrame->IsFrameOfType(nsIFrame::eSVG | nsIFrame::eSVGContainer)) {
gfxMatrix childrenOnlyTM; gfxMatrix childrenOnlyTM;
if (static_cast<nsSVGContainerFrame*>(aFrame)-> if (static_cast<nsSVGContainerFrame*>(aFrame)->
@ -1193,7 +1207,7 @@ nsSVGUtils::PaintFrameWithEffects(nsRenderingContext *aContext,
gfxMatrix matrix; gfxMatrix matrix;
if (clipPathFrame || maskFrame) if (clipPathFrame || maskFrame)
matrix = GetCanvasTM(aFrame); matrix = GetCanvasTM(aFrame, nsISVGChildFrame::FOR_PAINTING);
/* Check if we need to do additional operations on this child's /* Check if we need to do additional operations on this child's
* rendering, which necessitates rendering into another surface. */ * 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 // aFrame has a valid visual overflow rect, so clip to it before calling
// PushGroup() to minimize the size of the surfaces we'll composite: // PushGroup() to minimize the size of the surfaces we'll composite:
gfxContextMatrixAutoSaveRestore matrixAutoSaveRestore(gfx); gfxContextMatrixAutoSaveRestore matrixAutoSaveRestore(gfx);
gfx->Multiply(GetCanvasTM(aFrame)); gfx->Multiply(GetCanvasTM(aFrame, nsISVGChildFrame::FOR_PAINTING));
nsRect overflowRect = aFrame->GetVisualOverflowRectRelativeToSelf(); nsRect overflowRect = aFrame->GetVisualOverflowRectRelativeToSelf();
if (aFrame->IsFrameOfType(nsIFrame::eSVGGeometry)) { if (aFrame->IsFrameOfType(nsIFrame::eSVGGeometry)) {
// Unlike containers, leaf frames do not include GetPosition() in // Unlike containers, leaf frames do not include GetPosition() in
@ -1231,7 +1245,8 @@ nsSVGUtils::PaintFrameWithEffects(nsRenderingContext *aContext,
if (aDirtyRect) { if (aDirtyRect) {
// aDirtyRect is in outer-<svg> device pixels, but the filter code needs // aDirtyRect is in outer-<svg> device pixels, but the filter code needs
// it in frame space. // it in frame space.
gfxMatrix userToDeviceSpace = GetUserToCanvasTM(aFrame); gfxMatrix userToDeviceSpace =
GetUserToCanvasTM(aFrame, nsISVGChildFrame::FOR_OUTERSVG_TM);
if (userToDeviceSpace.IsSingular()) { if (userToDeviceSpace.IsSingular()) {
return; return;
} }
@ -1310,7 +1325,8 @@ nsSVGUtils::HitTestClip(nsIFrame *aFrame, const nsPoint &aPoint)
return false; return false;
} }
return clipPathFrame->ClipHitTest(aFrame, GetCanvasTM(aFrame), aPoint); return clipPathFrame->ClipHitTest(aFrame, GetCanvasTM(aFrame,
nsISVGChildFrame::FOR_HIT_TESTING), aPoint);
} }
nsIFrame * nsIFrame *

Просмотреть файл

@ -470,7 +470,7 @@ public:
* child SVG frame, container SVG frame, or a regular frame. * child SVG frame, container SVG frame, or a regular frame.
* For regular frames, we just return an identity matrix. * 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 * 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 * space. Specifically, it does not include any other transforms introduced
* by the frame such as x/y offsets and viewBox attributes. * 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 * Notify the descendants of aFrame of a change to one of their ancestors